#include "wx/dde.h"
#include "wx/intl.h"
+#include "wx/buffer.h"
+#include "wx/strconv.h"
#include "wx/msw/private.h"
IMPLEMENT_DYNAMIC_CLASS(wxDDEServer, wxServerBase)
IMPLEMENT_DYNAMIC_CLASS(wxDDEClient, wxClientBase)
-IMPLEMENT_CLASS(wxDDEConnection, wxConnectionBase)
+IMPLEMENT_DYNAMIC_CLASS(wxDDEConnection, wxConnectionBase)
IMPLEMENT_DYNAMIC_CLASS(wxDDEModule, wxModule)
// ============================================================================
UINT rc = DdeInitialize(&DDEIdInst, callback, APPCLASS_STANDARD, 0L);
if ( rc != DMLERR_NO_ERROR )
{
- DDELogError(_T("Failed to initialize DDE"), rc);
+ DDELogError(wxT("Failed to initialize DDE"), rc);
}
else
{
// deleting them later won't work as DDE won't be initialized any more
wxASSERT_MSG( wxDDEServerObjects.empty() &&
wxDDEClientObjects.empty(),
- _T("all DDE objects should be deleted by now") );
+ wxT("all DDE objects should be deleted by now") );
wxAtomTable.clear();
{
wxDDEConnection *connection = node->GetData();
wxDDEConnectionList::compatibility_iterator next = node->GetNext();
- connection->SetConnected(false);
connection->OnDisconnect(); // May delete the node implicitly
node = next;
}
if ( !hszServer )
{
- return (wxConnectionBase*) NULL;
+ return NULL;
}
if ( !hszTopic )
{
DDEFreeString(hszServer);
- return (wxConnectionBase*) NULL;
+ return NULL;
}
}
}
- return (wxConnectionBase*) NULL;
+ return NULL;
}
wxConnectionBase *wxDDEClient::OnMakeConnection()
bool ok = DdeDisconnect(GetHConv()) != 0;
if ( !ok )
{
- DDELogError(_T("Failed to disconnect from DDE server gracefully"));
+ DDELogError(wxT("Failed to disconnect from DDE server gracefully"));
}
SetConnected( false ); // so we don't try and disconnect again
return ok;
}
-bool wxDDEConnection::DoExecute(const void *data, size_t size, wxIPCFormat WXUNUSED(format))
+bool
+wxDDEConnection::DoExecute(const void *data, size_t size, wxIPCFormat format)
{
- DWORD result;
+ wxCHECK_MSG( format == wxIPC_TEXT ||
+ format == wxIPC_UTF8TEXT ||
+ format == wxIPC_UNICODETEXT,
+ false,
+ wxT("wxDDEServer::Execute() supports only text data") );
+
+ wxMemoryBuffer buffer;
+ LPBYTE realData = NULL;
+ size_t realSize = 0;
+ wxMBConv *conv = NULL;
+
+ // Windows only supports either ANSI or UTF-16 format depending on the
+ // build, so we need to convert the data if it doesn't use it already
+#if wxUSE_UNICODE
+ if ( format == wxIPC_TEXT )
+ {
+ conv = &wxConvLibc;
+ }
+ else if ( format == wxIPC_UTF8TEXT )
+ {
+ conv = &wxConvUTF8;
+ }
+ else // no conversion necessary for wxIPC_UNICODETEXT
+ {
+ realData = (LPBYTE)data;
+ realSize = size;
+ }
- bool ok = DdeClientTransaction((LPBYTE)data,
- size,
- GetHConv(),
- NULL,
-// If the transaction specified by the wType parameter does not pass data or is XTYP_EXECUTE,
-// wFmt should be zero.
- 0,
- XTYP_EXECUTE,
- DDE_TIMEOUT,
- &result) != 0;
+ if ( conv )
+ {
+ const char * const text = (const char *)data;
+ const size_t len = size;
+
+ realSize = conv->ToWChar(NULL, 0, text, len);
+ if ( realSize == wxCONV_FAILED )
+ return false;
+
+ realData = (LPBYTE)buffer.GetWriteBuf(realSize*sizeof(wchar_t));
+ if ( !realData )
+ return false;
+
+ realSize = conv->ToWChar((wchar_t *)realData, realSize, text, len);
+ if ( realSize == wxCONV_FAILED )
+ return false;
+
+ // We need to pass the size of the buffer to DdeClientTransaction() and
+ // not the length of the string.
+ realSize *= sizeof(wchar_t);
+ }
+#else // !wxUSE_UNICODE
+ if ( format == wxIPC_UNICODETEXT )
+ {
+ conv = &wxConvLibc;
+ }
+ else if ( format == wxIPC_UTF8TEXT )
+ {
+ // we could implement this in theory but it's not obvious how to pass
+ // the format information and, basically, why bother -- just use
+ // Unicode build
+ wxFAIL_MSG( wxT("UTF-8 text not supported in ANSI build") );
+
+ return false;
+ }
+ else // don't convert wxIPC_TEXT
+ {
+ realData = (LPBYTE)data;
+ realSize = size;
+ }
+
+ if ( conv )
+ {
+ const wchar_t * const wtext = (const wchar_t *)data;
+ const size_t len = size/sizeof(wchar_t);
+
+ realSize = conv->FromWChar(NULL, 0, wtext, len);
+ if ( realSize == wxCONV_FAILED )
+ return false;
+
+ realData = (LPBYTE)buffer.GetWriteBuf(realSize);
+ if ( !realData )
+ return false;
+
+ realSize = conv->FromWChar((char*)realData, realSize, wtext, len);
+ if ( realSize == wxCONV_FAILED )
+ return false;
+ }
+#endif // wxUSE_UNICODE/!wxUSE_UNICODE
+
+ DWORD result;
+ bool ok = DdeClientTransaction(realData,
+ realSize,
+ GetHConv(),
+ NULL,
+ // MSDN: if the transaction specified by
+ // the wType parameter does not pass data
+ // or is XTYP_EXECUTE, wFmt should be zero.
+ 0,
+ XTYP_EXECUTE,
+ DDE_TIMEOUT,
+ &result) != 0;
if ( !ok )
{
- DDELogError(_T("DDE execute request failed"));
+ DDELogError(wxT("DDE execute request failed"));
}
return ok;
&result);
if ( !returned_data )
{
- DDELogError(_T("DDE data request failed"));
+ DDELogError(wxT("DDE data request failed"));
return NULL;
}
void *data = GetBufferAtLeast(len);
wxASSERT_MSG(data != NULL,
- _T("Buffer too small in wxDDEConnection::Request") );
+ wxT("Buffer too small in wxDDEConnection::Request") );
(void) DdeGetData(returned_data, (LPBYTE)data, len, 0);
(void) DdeFreeDataHandle(returned_data);
void *data = connection->GetBufferAtLeast(len);
wxASSERT_MSG(data != NULL,
- _T("Buffer too small in _DDECallback (XTYP_EXECUTE)") );
+ wxT("Buffer too small in _DDECallback (XTYP_EXECUTE)") );
DdeGetData(hData, (LPBYTE)data, len, 0);
DdeFreeDataHandle(hData);
-// XTYP_EXECUTE cannot be used for arbitrary data, but only for text
+ // XTYP_EXECUTE can be used for text only and the text is
+ // always in ANSI format for ANSI build and Unicode format
+ // in Unicode build
+ #if wxUSE_UNICODE
+ wFmt = wxIPC_UNICODETEXT;
+ #else
+ wFmt = wxIPC_TEXT;
+ #endif
+
if ( connection->OnExecute(connection->m_topicName,
data,
(int)len,
- wxIPC_TEXT ) )
+ (wxIPCFormat)wFmt) )
{
return (DDERETURN)(DWORD)DDE_FACK;
}
void *data = connection->GetBufferAtLeast(len);
wxASSERT_MSG(data != NULL,
- _T("Buffer too small in _DDECallback (XTYP_POKE)") );
+ wxT("Buffer too small in _DDECallback (XTYP_POKE)") );
DdeGetData(hData, (LPBYTE)data, len, 0);
void *data = connection->GetBufferAtLeast(len);
wxASSERT_MSG(data != NULL,
- _T("Buffer too small in _DDECallback (XTYP_ADVDATA)") );
+ wxT("Buffer too small in _DDECallback (XTYP_ADVDATA)") );
DdeGetData(hData, (LPBYTE)data, len, 0);
*/
static HSZ DDEAtomFromString(const wxString& s)
{
- wxASSERT_MSG( DDEIdInst, _T("DDE not initialized") );
+ wxASSERT_MSG( DDEIdInst, wxT("DDE not initialized") );
- HSZ hsz = DdeCreateStringHandle(DDEIdInst, (wxChar*)s.wx_str(), DDE_CP);
+ HSZ hsz = DdeCreateStringHandle(DDEIdInst, wxMSW_CONV_LPTSTR(s), DDE_CP);
if ( !hsz )
{
DDELogError(_("Failed to create DDE string"));
error = DdeGetLastError(DDEIdInst);
}
- wxLogError(s + _T(": ") + DDEGetErrorMsg(error));
+ wxLogError(s + wxT(": ") + DDEGetErrorMsg(error));
}
static wxString DDEGetErrorMsg(UINT error)