#include "stdafx.h"
#if defined( __linux__ ) || defined(__APPLE__)
#include
#include
#include
#include
#include
#include
#include
#endif
#include
#include
#include "AddInNative.h"
#include
#define TIME_LEN 65
#define BASE_ERRNO 7
#ifdef WIN32
#include
#pragma setlocale("ru-RU" )
#endif
static const wchar_t* g_PropNames[] = {
L"IsEnabled",
L"StringRW",
L"StringRO",
L"StringWO",
};
static const wchar_t* g_PropNamesRu[] = {
L"",
L"",
L"",
L"",
};
static const wchar_t* g_MethodNames[] = {
L"Enable",
L"Disable",
L"DefaultParam",
L"ShowInStatusLine",
L"LoadPicture",
L"ShowMessageBox",
L"Exchange",
L"Concatenate",
L"Loopback"
};
static const wchar_t* g_MethodNamesRu[] = {
L"",
L"",
L"",
L"",
L"",
L"",
L"",
L"",
L"",
};
static const wchar_t g_kClassNames[] = L"CAddInNative"; //"|OtherClass1|OtherClass2";
static IAddInDefBase* pAsyncEvent = NULL;
uint32_t convToShortWchar(WCHAR_T** Dest, const wchar_t* Source, uint32_t len = 0);
uint32_t convFromShortWchar(wchar_t** Dest, const WCHAR_T* Source, uint32_t len = 0);
uint32_t getLenShortWcharStr(const WCHAR_T* Source);
static AppCapabilities g_capabilities = eAppCapabilitiesInvalid;
static WcharWrapper s_names(g_kClassNames);
//---------------------------------------------------------------------------//
long GetClassObject(const WCHAR_T* wsName, IComponentBase** pInterface)
{
if (!*pInterface)
{
*pInterface = new CAddInNative;
return (long)*pInterface;
}
return 0;
}
//---------------------------------------------------------------------------//
AppCapabilities SetPlatformCapabilities(const AppCapabilities capabilities)
{
g_capabilities = capabilities;
return eAppCapabilitiesLast;
}
//---------------------------------------------------------------------------//
long DestroyObject(IComponentBase** pIntf)
{
if (!*pIntf)
return -1;
delete* pIntf;
*pIntf = 0;
return 0;
}
//---------------------------------------------------------------------------//
const WCHAR_T* GetClassNames()
{
return s_names;
}
// CAddInNative
//---------------------------------------------------------------------------//
CAddInNative::CAddInNative()
{
m_iMemory = 0;
m_iConnect = 0;
}
//---------------------------------------------------------------------------//
CAddInNative::~CAddInNative()
{
}
//---------------------------------------------------------------------------//
bool CAddInNative::Init(void* pConnection)
{
m_iConnect = (IAddInDefBase*)pConnection;
return m_iConnect != NULL;
}
//---------------------------------------------------------------------------//
long CAddInNative::GetInfo()
{
// Component should put supported component technology version
// This component supports 2.0 version
return 2000;
}
//---------------------------------------------------------------------------//
void CAddInNative::Done()
{
}
/////////////////////////////////////////////////////////////////////////////
// ILanguageExtenderBase
//---------------------------------------------------------------------------//
bool CAddInNative::RegisterExtensionAs(WCHAR_T** wsExtensionName)
{
const wchar_t* wsExtension = L"CAddInNative";
int iActualSize = ::wcslen(wsExtension) + 1;
WCHAR_T* dest = 0;
if (m_iMemory)
{
if (m_iMemory->AllocMemory((void**)wsExtensionName, iActualSize * sizeof(WCHAR_T)))
::convToShortWchar(wsExtensionName, wsExtension, iActualSize);
return true;
}
return false;
}
//---------------------------------------------------------------------------//
long CAddInNative::GetNProps()
{
// You may delete next lines and add your own implementation code here
return ePropLast;
}
//---------------------------------------------------------------------------//
long CAddInNative::FindProp(const WCHAR_T* wsPropName)
{
long plPropNum = -1;
wchar_t* propName = 0;
::convFromShortWchar(&propName, wsPropName);
plPropNum = findName(g_PropNames, propName, ePropLast);
if (plPropNum == -1)
plPropNum = findName(g_PropNamesRu, propName, ePropLast);
delete[] propName;
return plPropNum;
}
//---------------------------------------------------------------------------//
const WCHAR_T* CAddInNative::GetPropName(long lPropNum, long lPropAlias)
{
if (lPropNum >= ePropLast)
return NULL;
wchar_t* wsCurrentName = NULL;
WCHAR_T* wsPropName = NULL;
int iActualSize = 0;
switch (lPropAlias)
{
case 0: // First language
wsCurrentName = (wchar_t*)g_PropNames[lPropNum];
break;
case 1: // Second language
wsCurrentName = (wchar_t*)g_PropNamesRu[lPropNum];
break;
default:
return 0;
}
if (m_iMemory && wsCurrentName)
{
iActualSize = wcslen(wsCurrentName) + 1;
if (m_iMemory->AllocMemory((void**)&wsPropName, iActualSize * sizeof(WCHAR_T)))
::convToShortWchar(&wsPropName, wsCurrentName, iActualSize);
}
return wsPropName;
}
//---------------------------------------------------------------------------//
bool CAddInNative::GetPropVal(const long lPropNum, tVariant* pvarPropVal)
{
switch (lPropNum)
{
case ePropIsEnabled:
TV_VT(pvarPropVal) = VTYPE_BOOL;
TV_BOOL(pvarPropVal) = m_Enabled;
break;
case ePropStringRO:
case ePropStringRW: {
TV_VT(pvarPropVal) = VTYPE_PWSTR;
TV_WSTR(pvarPropVal) = NULL;
int iActualSize = 0;
iActualSize = m_String.length() + 1;
if (m_iMemory && m_iMemory->AllocMemory((void**)&pvarPropVal->pwstrVal, iActualSize * sizeof(WCHAR_T))) {
::convToShortWchar(&TV_WSTR(pvarPropVal), m_String.c_str(), iActualSize);
pvarPropVal->strLen = m_String.length();
return true;
}
return false;
}
default:
return false;
}
return true;
}
//---------------------------------------------------------------------------//
bool CAddInNative::SetPropVal(const long lPropNum, tVariant* pvarPropVal)
{
switch (lPropNum)
{
case ePropIsEnabled:
if (TV_VT(pvarPropVal) != VTYPE_BOOL)
return false;
m_Enabled = TV_BOOL(pvarPropVal);
break;
case ePropStringRW:
case ePropStringWO:
if (TV_VT(pvarPropVal) != VTYPE_PWSTR)
return false;
m_String = WcharWrapper(TV_WSTR(pvarPropVal));
break;
default:
return false;
}
return true;
}
//---------------------------------------------------------------------------//
bool CAddInNative::IsPropReadable(const long lPropNum)
{
switch (lPropNum)
{
case ePropIsEnabled:
case ePropStringRW:
case ePropStringRO:
return true;
default:
return false;
}
return false;
}
//---------------------------------------------------------------------------//
bool CAddInNative::IsPropWritable(const long lPropNum)
{
switch (lPropNum)
{
case ePropIsEnabled:
case ePropStringRW:
case ePropStringWO:
return true;
default:
return false;
}
return false;
}
//---------------------------------------------------------------------------//
long CAddInNative::GetNMethods()
{
return eMethLast;
}
//---------------------------------------------------------------------------//
long CAddInNative::FindMethod(const WCHAR_T* wsMethodName)
{
long plMethodNum = -1;
wchar_t* name = 0;
::convFromShortWchar(&name, wsMethodName);
plMethodNum = findName(g_MethodNames, name, eMethLast);
if (plMethodNum == -1)
plMethodNum = findName(g_MethodNamesRu, name, eMethLast);
delete[] name;
return plMethodNum;
}
//---------------------------------------------------------------------------//
const WCHAR_T* CAddInNative::GetMethodName(const long lMethodNum, const long lMethodAlias)
{
if (lMethodNum >= eMethLast)
return NULL;
wchar_t* wsCurrentName = NULL;
WCHAR_T* wsMethodName = NULL;
int iActualSize = 0;
switch (lMethodAlias)
{
case 0: // First language
wsCurrentName = (wchar_t*)g_MethodNames[lMethodNum];
break;
case 1: // Second language
wsCurrentName = (wchar_t*)g_MethodNamesRu[lMethodNum];
break;
default:
return 0;
}
if (m_iMemory && wsCurrentName)
{
iActualSize = wcslen(wsCurrentName) + 1;
if (m_iMemory->AllocMemory((void**)&wsMethodName, iActualSize * sizeof(WCHAR_T)))
::convToShortWchar(&wsMethodName, wsCurrentName, iActualSize);
}
return wsMethodName;
}
//---------------------------------------------------------------------------//
long CAddInNative::GetNParams(const long lMethodNum)
{
switch (lMethodNum)
{
case eMethDefaultParam:
return 1;
case eMethShowInStatusLine:
return 1;
case eMethLoadPicture:
return 1;
case eMethExchange:
return 2;
case eMethConcatenate:
return 2;
case eMethLoopback:
return 1;
default:
return 0;
}
return 0;
}
//---------------------------------------------------------------------------//
bool CAddInNative::GetParamDefValue(const long lMethodNum, const long lParamNum,
tVariant* pvarParamDefValue)
{
TV_VT(pvarParamDefValue) = VTYPE_EMPTY;
switch (lMethodNum)
{
case eMethDefaultParam:
if (lParamNum != 0)
return false;
TV_VT(pvarParamDefValue) = VTYPE_BOOL;
TV_BOOL(pvarParamDefValue) = true;
return true;
case eMethEnable:
case eMethDisable:
case eMethShowInStatusLine:
case eMethShowMsgBox:
// There are no parameter values by default
break;
default:
return false;
}
return false;
}
//---------------------------------------------------------------------------//
bool CAddInNative::HasRetVal(const long lMethodNum)
{
switch (lMethodNum)
{
case eMethDefaultParam:
return true;
case eMethLoadPicture:
case eMethConcatenate:
case eMethLoopback:
return true;
default:
return false;
}
return false;
}
//---------------------------------------------------------------------------//
bool CAddInNative::CallAsProc(const long lMethodNum,
tVariant* paParams, const long lSizeArray)
{
switch (lMethodNum)
{
case eMethEnable:
m_Enabled = true;
break;
case eMethDisable:
m_Enabled = false;
break;
case eMethShowInStatusLine:
if (m_iConnect && lSizeArray)
{
tVariant* var = paParams;
m_iConnect->SetStatusLine(var->pwstrVal);
}
break;
case eMethExchange:
tVariant variant;
memcpy(&variant, paParams, sizeof(tVariant));
memcpy(paParams, paParams + 1, sizeof(tVariant));
memcpy(paParams + 1, &variant, sizeof(tVariant));
break;
case eMethShowMsgBox:
{
if (eAppCapabilities1 GetInterface(eIMsgBox);
if (imsgbox)
{
IPlatformInfo* info = (IPlatformInfo*)cnn->GetInterface(eIPlatformInfo);
assert(info);
const IPlatformInfo::AppInfo* plt = info->GetPlatformInfo();
if (!plt)
break;
tVariant retVal;
tVarInit(&retVal);
if (imsgbox->Confirm(plt->AppVersion, &retVal))
{
bool succeed = TV_BOOL(&retVal);
WCHAR_T* result = 0;
if (succeed)
::convToShortWchar(&result, L"OK");
else
::convToShortWchar(&result, L"Cancel");
imsgbox->Alert(result);
delete[] result;
}
}
}
}
break;
default:
return false;
}
return true;
}
//---------------------------------------------------------------------------//
bool CAddInNative::CallAsFunc(const long lMethodNum,
tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray)
{
bool ret = false;
FILE* file = 0;
char* name = 0;
int size = 0;
char* mbstr = 0;
wchar_t* wsTmp = 0;
char* loc = 0;
switch (lMethodNum)
{
case eMethDefaultParam:
if (lSizeArray != 1 || TV_VT(paParams) != VTYPE_BOOL)
return false;
TV_VT(pvarRetValue) = VTYPE_BOOL;
TV_BOOL(pvarRetValue) = TV_BOOL(paParams);
return true;
// Method acceps one argument of type BinaryData ant returns its copy
case eMethConcatenate:
{
tVariant* str1 = paParams;
tVariant* str2 = paParams + 1;
if (TV_VT(str1) != VTYPE_PWSTR) return false;
if (TV_VT(str2) != VTYPE_PWSTR) return false;
TV_VT(pvarRetValue) = VTYPE_PWSTR;
TV_WSTR(pvarRetValue) = NULL;
int iActualSize = str1->strLen + str2->strLen + 1;
if (m_iMemory && m_iMemory->AllocMemory((void**)&pvarRetValue->pwstrVal, iActualSize * sizeof(WCHAR_T))) {
memset((void*)pvarRetValue->pstrVal, 0, sizeof(WCHAR_T) * iActualSize);
memcpy((void*)pvarRetValue->pstrVal, (void*)str1->pstrVal, str1->strLen * sizeof(WCHAR_T));
memcpy((void*)(pvarRetValue->pstrVal + str1->strLen * sizeof(WCHAR_T)), (void*)str2->pstrVal, str2->strLen * sizeof(WCHAR_T));
pvarRetValue->strLen = paParams->strLen + (paParams + 1)->strLen;
return true;
}
return false;
}
case eMethLoopback:
{
if (lSizeArray != 1 || !paParams)
return false;
if (TV_VT(paParams) != VTYPE_BLOB)
{
addError(ADDIN_E_VERY_IMPORTANT, L"AddInNative", L"Parameter type mismatch.", -1);
return false;
}
if (paParams->strLen > 0)
{
m_iMemory->AllocMemory((void**)&pvarRetValue->pstrVal, paParams->strLen);
memcpy((void*)pvarRetValue->pstrVal, (void*)paParams->pstrVal, paParams->strLen);
}
TV_VT(pvarRetValue) = VTYPE_BLOB;
pvarRetValue->strLen = paParams->strLen;
return true;
}
break;
case eMethLoadPicture:
{
if (!lSizeArray || !paParams)
return false;
switch (TV_VT(paParams))
{
case VTYPE_PSTR:
name = paParams->pstrVal;
break;
case VTYPE_PWSTR:
loc = setlocale(LC_ALL, "");
::convFromShortWchar(&wsTmp, TV_WSTR(paParams));
size = wcstombs(0, wsTmp, 0) + 1;
assert(size);
mbstr = new char[size];
assert(mbstr);
memset(mbstr, 0, size);
size = wcstombs(mbstr, wsTmp, getLenShortWcharStr(TV_WSTR(paParams)));
name = mbstr;
setlocale(LC_ALL, loc);
delete[] wsTmp;
break;
default:
return false;
}
}
file = fopen(name, "rb");
if (file == 0)
{
wchar_t* wsMsgBuf;
uint32_t err = errno;
name = strerror(err);
int sizeloc = mbstowcs(0, name, 0) + 1;
assert(sizeloc);
wsMsgBuf = new wchar_t[sizeloc];
assert(wsMsgBuf);
memset(wsMsgBuf, 0, sizeloc * sizeof(wchar_t));
sizeloc = mbstowcs(wsMsgBuf, name, sizeloc);
addError(ADDIN_E_VERY_IMPORTANT, L"AddInNative", wsMsgBuf, RESULT_FROM_ERRNO(err));
delete[] wsMsgBuf;
return false;
}
fseek(file, 0, SEEK_END);
size = ftell(file);
if (size && m_iMemory->AllocMemory((void**)&pvarRetValue->pstrVal, size))
{
fseek(file, 0, SEEK_SET);
size = fread(pvarRetValue->pstrVal, 1, size, file);
pvarRetValue->strLen = size;
TV_VT(pvarRetValue) = VTYPE_BLOB;
ret = true;
}
fclose(file);
if (mbstr && size != -1)
delete[] mbstr;
break;
}
return ret;
}
//---------------------------------------------------------------------------//
void CAddInNative::SetLocale(const WCHAR_T* loc)
{
#if !defined( __linux__ ) && !defined(__APPLE__)
_wsetlocale(LC_ALL, loc);
#else
//We convert in char* char_locale
//also we establish locale
//setlocale(LC_ALL, char_locale);
#endif
}
/////////////////////////////////////////////////////////////////////////////
// LocaleBase
//---------------------------------------------------------------------------//
bool CAddInNative::setMemManager(void* mem)
{
m_iMemory = (IMemoryManager*)mem;
return m_iMemory != 0;
}
//---------------------------------------------------------------------------//
void CAddInNative::addError(uint32_t wcode, const wchar_t* source,
const wchar_t* descriptor, long code)
{
if (m_iConnect)
{
WCHAR_T* err = 0;
WCHAR_T* descr = 0;
::convToShortWchar(&err, source);
::convToShortWchar(&descr, descriptor);
m_iConnect->AddError(wcode, err, descr, code);
delete[] err;
delete[] descr;
}
}
//---------------------------------------------------------------------------//
long CAddInNative::findName(const wchar_t* names[], const wchar_t* name,
const uint32_t size) const
{
long ret = -1;
for (uint32_t i = 0; i < size; i++)
{
if (!wcscmp(names[i], name))
{
ret = i;
break;
}
}
return ret;
}
//---------------------------------------------------------------------------//
uint32_t convToShortWchar(WCHAR_T** Dest, const wchar_t* Source, uint32_t len)
{
if (!len)
len = ::wcslen(Source) + 1;
if (!*Dest)
*Dest = new WCHAR_T[len];
WCHAR_T* tmpShort = *Dest;
wchar_t* tmpWChar = (wchar_t*)Source;
uint32_t res = 0;
::memset(*Dest, 0, len * sizeof(WCHAR_T));
#ifdef __linux__
size_t succeed = (size_t)-1;
size_t f = len * sizeof(wchar_t), t = len * sizeof(WCHAR_T);
const char* fromCode = sizeof(wchar_t) == 2 ? "UTF-16" : "UTF-32";
iconv_t cd = iconv_open("UTF-16LE", fromCode);
if (cd != (iconv_t)-1)
{
succeed = iconv(cd, (char**)&tmpWChar, &f, (char**)&tmpShort, &t);
iconv_close(cd);
if (succeed != (size_t)-1)
return (uint32_t)succeed;
}
#endif //__linux__
for (; len; --len, ++res, ++tmpWChar, ++tmpShort)
{
*tmpShort = (WCHAR_T)*tmpWChar;
}
return res;
}
//---------------------------------------------------------------------------//
uint32_t convFromShortWchar(wchar_t** Dest, const WCHAR_T* Source, uint32_t len)
{
if (!len)
len = getLenShortWcharStr(Source) + 1;
if (!*Dest)
*Dest = new wchar_t[len];
wchar_t* tmpWChar = *Dest;
WCHAR_T* tmpShort = (WCHAR_T*)Source;
uint32_t res = 0;
::memset(*Dest, 0, len * sizeof(wchar_t));
#ifdef __linux__
size_t succeed = (size_t)-1;
const char* fromCode = sizeof(wchar_t) == 2 ? "UTF-16" : "UTF-32";
size_t f = len * sizeof(WCHAR_T), t = len * sizeof(wchar_t);
iconv_t cd = iconv_open("UTF-32LE", fromCode);
if (cd != (iconv_t)-1)
{
succeed = iconv(cd, (char**)&tmpShort, &f, (char**)&tmpWChar, &t);
iconv_close(cd);
if (succeed != (size_t)-1)
return (uint32_t)succeed;
}
#endif //__linux__
for (; len; --len, ++res, ++tmpWChar, ++tmpShort)
{
*tmpWChar = (wchar_t)*tmpShort;
}
return res;
}
//---------------------------------------------------------------------------//
uint32_t getLenShortWcharStr(const WCHAR_T* Source)
{
uint32_t res = 0;
WCHAR_T* tmpShort = (WCHAR_T*)Source;
while (*tmpShort++)
++res;
return res;
}
//---------------------------------------------------------------------------//
#ifdef LINUX_OR_MACOS
WcharWrapper::WcharWrapper(const WCHAR_T* str) : m_str_WCHAR(NULL),
m_str_wchar(NULL)
{
if (str)
{
int len = getLenShortWcharStr(str);
m_str_WCHAR = new WCHAR_T[len + 1];
memset(m_str_WCHAR, 0, sizeof(WCHAR_T) * (len + 1));
memcpy(m_str_WCHAR, str, sizeof(WCHAR_T) * len);
::convFromShortWchar(&m_str_wchar, m_str_WCHAR);
}
}
#endif
//---------------------------------------------------------------------------//
WcharWrapper::WcharWrapper(const wchar_t* str) :
#ifdef LINUX_OR_MACOS
m_str_WCHAR(NULL),
#endif
m_str_wchar(NULL)
{
if (str)
{
int len = wcslen(str);
m_str_wchar = new wchar_t[len + 1];
memset(m_str_wchar, 0, sizeof(wchar_t) * (len + 1));
memcpy(m_str_wchar, str, sizeof(wchar_t) * len);
#ifdef LINUX_OR_MACOS
::convToShortWchar(&m_str_WCHAR, m_str_wchar);
#endif
}
}
//---------------------------------------------------------------------------//
WcharWrapper::~WcharWrapper()
{
#ifdef LINUX_OR_MACOS
if (m_str_WCHAR)
{
delete[] m_str_WCHAR;
m_str_WCHAR = NULL;
}
#endif
if (m_str_wchar)
{
delete[] m_str_wchar;
m_str_wchar = NULL;
}
}
//---------------------------------------------------------------------------//