]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dde.cpp
Restored the ability to scroll.
[wxWidgets.git] / src / msw / dde.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: dde.cpp
3// Purpose: DDE classes
4// Author: Julian Smart
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "dde.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include "wx/defs.h"
25#endif
26
47d67540 27#if wxUSE_IPC
2bda0e17
KB
28
29#ifndef WX_PRECOMP
30#include "wx/utils.h"
31#include "wx/app.h"
32#endif
33
e2a6f233 34#include "wx/module.h"
2bda0e17
KB
35#include "wx/dde.h"
36
03ab016d
JS
37#include "wx/msw/private.h"
38#include <windows.h>
39#include <ddeml.h>
40
57c208c5 41#ifndef __TWIN32__
65fd5cb0 42#if !wxUSE_NORLANDER_HEADERS
2bda0e17
KB
43#ifdef __GNUWIN32__
44#include "wx/msw/gnuwin32/extra.h"
45#endif
57c208c5 46#endif
65fd5cb0 47#endif
2bda0e17 48
2bda0e17
KB
49#include <string.h>
50
51#ifdef __WIN32__
52#define _EXPORT /**/
53#else
54#define _EXPORT _export
55#endif
56
57#if !USE_SHARED_LIBRARY
58IMPLEMENT_DYNAMIC_CLASS(wxDDEServer, wxServerBase)
59IMPLEMENT_DYNAMIC_CLASS(wxDDEClient, wxClientBase)
60IMPLEMENT_CLASS(wxDDEConnection, wxConnectionBase)
61#endif
62
63static wxDDEConnection *DDEFindConnection(HCONV hConv);
64static void DDEDeleteConnection(HCONV hConv);
65static wxDDEServer *DDEFindServer(const wxString& s);
66
67extern "C" HDDEDATA EXPENTRY _EXPORT _DDECallback(
68WORD wType,
69WORD wFmt,
70HCONV hConv,
71HSZ hsz1,
72HSZ hsz2,
73HDDEDATA hData,
74DWORD lData1,
75DWORD lData2);
76
77// Add topic name to atom table before using in conversations
78static HSZ DDEAddAtom(const wxString& string);
79static HSZ DDEGetAtom(const wxString& string);
80static void DDEPrintError(void);
81
82static DWORD DDEIdInst = 0L;
83static wxDDEConnection *DDECurrentlyConnecting = NULL;
84
85static wxList wxAtomTable(wxKEY_STRING);
86static wxList wxDDEClientObjects;
87static wxList wxDDEServerObjects;
88
89char *DDEDefaultIPCBuffer = NULL;
90int DDEDefaultIPCBufferSize = 0;
91
92/*
93 * Initialization
94 *
95 */
96
97static bool DDEInitialized = FALSE;
98
99void wxDDEInitialize()
100{
101 if (DDEInitialized)
102 return;
103 DDEInitialized = TRUE;
104
105 // Should insert filter flags
106 DdeInitialize(&DDEIdInst, (PFNCALLBACK)MakeProcInstance(
107 (FARPROC)_DDECallback, wxGetInstance()),
108 APPCLASS_STANDARD,
109 0L);
110}
111
112/*
113 * CleanUp
114 */
115
116void wxDDECleanUp()
117{
118 if (DDEIdInst != 0)
119 {
120 DdeUninitialize(DDEIdInst);
121 DDEIdInst = 0;
122 }
123 if (DDEDefaultIPCBuffer)
124 delete [] DDEDefaultIPCBuffer ;
125}
126
e2a6f233
JS
127// A module to allow DDE initialization/cleanup
128// without calling these functions from app.cpp or from
129// the user's application.
130
131class wxDDEModule: public wxModule
132{
133DECLARE_DYNAMIC_CLASS(wxDDEModule)
134public:
135 wxDDEModule() {}
136 bool OnInit() { wxDDEInitialize(); return TRUE; };
137 void OnExit() { wxDDECleanUp(); };
138};
139
140IMPLEMENT_DYNAMIC_CLASS(wxDDEModule, wxModule)
141
2bda0e17
KB
142// Global find connection
143static wxDDEConnection *DDEFindConnection(HCONV hConv)
144{
145 wxNode *node = wxDDEServerObjects.First();
146 wxDDEConnection *found = NULL;
147 while (node && !found)
148 {
149 wxDDEServer *object = (wxDDEServer *)node->Data();
150 found = object->FindConnection((WXHCONV) hConv);
151 node = node->Next();
152 }
153 if (found)
154 return found;
155
156 node = wxDDEClientObjects.First();
157 while (node && !found)
158 {
159 wxDDEClient *object = (wxDDEClient *)node->Data();
160 found = object->FindConnection((WXHCONV) hConv);
161 node = node->Next();
162 }
163 return found;
164}
165
166// Global delete connection
167static void DDEDeleteConnection(HCONV hConv)
168{
169 wxNode *node = wxDDEServerObjects.First();
170 bool found = FALSE;
171 while (node && !found)
172 {
173 wxDDEServer *object = (wxDDEServer *)node->Data();
174 found = object->DeleteConnection((WXHCONV) hConv);
175 node = node->Next();
176 }
177 if (found)
178 return;
179
180 node = wxDDEServerObjects.First();
181 while (node && !found)
182 {
183 wxDDEClient *object = (wxDDEClient *)node->Data();
184 found = object->DeleteConnection((WXHCONV) hConv);
185 node = node->Next();
186 }
187}
188
189// Find a server from a service name
190static wxDDEServer *DDEFindServer(const wxString& s)
191{
192 wxNode *node = wxDDEServerObjects.First();
193 wxDDEServer *found = NULL;
194 while (node && !found)
195 {
196 wxDDEServer *object = (wxDDEServer *)node->Data();
197
198 if (object->GetServiceName() == s)
199 found = object;
200 else node = node->Next();
201 }
202 return found;
203}
204
205/*
206 * Server
207 *
208 */
209
210wxDDEServer::wxDDEServer(void)
211{
b3324be2 212 m_serviceName = "";
2bda0e17
KB
213 wxDDEServerObjects.Append(this);
214}
215
216bool wxDDEServer::Create(const wxString& server_name)
217{
b3324be2 218 m_serviceName = server_name;
837e5743 219 HSZ serviceName = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST server_name, CP_WINANSI);
2bda0e17 220
57c208c5 221 if (DdeNameService(DDEIdInst, serviceName, (HSZ) NULL, DNS_REGISTER) == 0)
2bda0e17
KB
222 {
223 DDEPrintError();
224 return FALSE;
225 }
226 return TRUE;
227}
228
229wxDDEServer::~wxDDEServer(void)
230{
837e5743 231 if (m_serviceName != _T(""))
2bda0e17 232 {
837e5743 233 HSZ serviceName = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST m_serviceName, CP_WINANSI);
2bda0e17
KB
234 if (DdeNameService(DDEIdInst, serviceName, NULL, DNS_UNREGISTER) == 0)
235 {
236 DDEPrintError();
237 }
238 }
239 wxDDEServerObjects.DeleteObject(this);
240
b3324be2 241 wxNode *node = m_connections.First();
2bda0e17
KB
242 while (node)
243 {
244 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
245 wxNode *next = node->Next();
246 connection->OnDisconnect(); // May delete the node implicitly
247 node = next;
248 }
249
250 // If any left after this, delete them
b3324be2 251 node = m_connections.First();
2bda0e17
KB
252 while (node)
253 {
254 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
255 wxNode *next = node->Next();
256 delete connection;
257 node = next;
258 }
259}
260
261wxConnectionBase *wxDDEServer::OnAcceptConnection(const wxString& /* topic */)
262{
263 return new wxDDEConnection;
264}
265
266wxDDEConnection *wxDDEServer::FindConnection(WXHCONV conv)
267{
b3324be2 268 wxNode *node = m_connections.First();
2bda0e17
KB
269 wxDDEConnection *found = NULL;
270 while (node && !found)
271 {
272 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
b3324be2 273 if (connection->m_hConv == conv)
2bda0e17
KB
274 found = connection;
275 else node = node->Next();
276 }
277 return found;
278}
279
280// Only delete the entry in the map, not the actual connection
281bool wxDDEServer::DeleteConnection(WXHCONV conv)
282{
b3324be2 283 wxNode *node = m_connections.First();
2bda0e17
KB
284 bool found = FALSE;
285 while (node && !found)
286 {
287 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
b3324be2 288 if (connection->m_hConv == conv)
2bda0e17
KB
289 {
290 found = TRUE;
291 delete node;
292 }
293 else node = node->Next();
294 }
295 return found;
296}
297
298
299/*
300 * Client
301 *
302 */
303
304
305wxDDEClient::wxDDEClient(void)
306{
307 wxDDEClientObjects.Append(this);
308}
309
310wxDDEClient::~wxDDEClient(void)
311{
312 wxDDEClientObjects.DeleteObject(this);
b3324be2 313 wxNode *node = m_connections.First();
2bda0e17
KB
314 while (node)
315 {
316 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
317 delete connection; // Deletes the node implicitly (see ~wxDDEConnection)
b3324be2 318 node = m_connections.First();
2bda0e17
KB
319 }
320}
321
322bool wxDDEClient::ValidHost(const wxString& /* host */)
323{
324 return TRUE;
325}
326
327wxConnectionBase *wxDDEClient::MakeConnection(const wxString& /* host */, const wxString& server_name, const wxString& topic)
328{
837e5743
OK
329 HSZ serviceName = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST server_name, CP_WINANSI);
330 HSZ topic_atom = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST topic, CP_WINANSI);
2bda0e17
KB
331
332 HCONV hConv = DdeConnect(DDEIdInst, serviceName, topic_atom, (PCONVCONTEXT)NULL);
57c208c5
JS
333 if (hConv == (HCONV) NULL)
334 return (wxConnectionBase*) NULL;
2bda0e17
KB
335 else
336 {
337 wxDDEConnection *connection = (wxDDEConnection*) OnMakeConnection();
338 if (connection)
339 {
b3324be2
JS
340 connection->m_hConv = (WXHCONV) hConv;
341 connection->m_topicName = topic;
342 connection->m_client = this;
343 m_connections.Append(connection);
2bda0e17
KB
344 return connection;
345 }
57c208c5 346 else return (wxConnectionBase*) NULL;
2bda0e17
KB
347 }
348}
349
350wxConnectionBase *wxDDEClient::OnMakeConnection(void)
351{
352 return new wxDDEConnection;
353}
354
355wxDDEConnection *wxDDEClient::FindConnection(WXHCONV conv)
356{
b3324be2 357 wxNode *node = m_connections.First();
2bda0e17
KB
358 wxDDEConnection *found = NULL;
359 while (node && !found)
360 {
361 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
b3324be2 362 if (connection->m_hConv == conv)
2bda0e17
KB
363 found = connection;
364 else node = node->Next();
365 }
366 return found;
367}
368
369// Only delete the entry in the map, not the actual connection
370bool wxDDEClient::DeleteConnection(WXHCONV conv)
371{
b3324be2 372 wxNode *node = m_connections.First();
2bda0e17
KB
373 bool found = FALSE;
374 while (node && !found)
375 {
376 wxDDEConnection *connection = (wxDDEConnection *)node->Data();
b3324be2 377 if (connection->m_hConv == conv)
2bda0e17
KB
378 {
379 found = TRUE;
380 delete node;
381 }
382 else node = node->Next();
383 }
384 return found;
385}
386
387/*
388 * Connection
389 */
390
391wxDDEConnection::wxDDEConnection(char *buffer, int size)
392{
393 if (buffer == NULL)
394 {
395 if (DDEDefaultIPCBuffer == NULL)
396 DDEDefaultIPCBuffer = new char[DDEDefaultIPCBufferSize];
b3324be2
JS
397 m_bufPtr = DDEDefaultIPCBuffer;
398 m_bufSize = DDEDefaultIPCBufferSize;
2bda0e17
KB
399 }
400 else
401 {
b3324be2
JS
402 m_bufPtr = buffer;
403 m_bufSize = size;
2bda0e17
KB
404 }
405
b3324be2 406 m_topicName = "";
2bda0e17 407
b3324be2
JS
408 m_client = NULL;
409 m_server = NULL;
2bda0e17 410
b3324be2
JS
411 m_hConv = 0;
412 m_sendingData = NULL;
2bda0e17
KB
413}
414
415wxDDEConnection::wxDDEConnection(void)
416{
b3324be2
JS
417 m_hConv = 0;
418 m_sendingData = NULL;
419 m_server = NULL;
420 m_client = NULL;
2bda0e17
KB
421 if (DDEDefaultIPCBuffer == NULL)
422 DDEDefaultIPCBuffer = new char[DDEDefaultIPCBufferSize];
423
b3324be2
JS
424 m_bufPtr = DDEDefaultIPCBuffer;
425 m_bufSize = DDEDefaultIPCBufferSize;
426 m_topicName = "";
2bda0e17
KB
427}
428
429wxDDEConnection::~wxDDEConnection(void)
430{
b3324be2
JS
431 if (m_server)
432 m_server->GetConnections().DeleteObject(this);
2bda0e17 433 else
b3324be2 434 m_client->GetConnections().DeleteObject(this);
2bda0e17
KB
435}
436
437// Calls that CLIENT can make
438bool wxDDEConnection::Disconnect(void)
439{
b3324be2
JS
440 DDEDeleteConnection((HCONV) m_hConv);
441 return (DdeDisconnect((HCONV) m_hConv) != 0);
2bda0e17
KB
442}
443
837e5743 444bool wxDDEConnection::Execute(wxChar *data, int size, wxIPCFormat format)
2bda0e17
KB
445{
446 DWORD result;
447 if (size < 0)
837e5743 448 size = wxStrlen(data);
2bda0e17
KB
449
450 size ++;
451
b3324be2 452 return (DdeClientTransaction((LPBYTE)data, size, (HCONV) m_hConv,
2bda0e17
KB
453 NULL, format, XTYP_EXECUTE, 5000, &result) ? TRUE : FALSE);
454}
455
0d2a2b60 456char *wxDDEConnection::Request(const wxString& item, int *size, wxIPCFormat format)
2bda0e17
KB
457{
458 DWORD result;
459 HSZ atom = DDEGetAtom(item);
460
b3324be2 461 HDDEDATA returned_data = DdeClientTransaction(NULL, 0, (HCONV) m_hConv,
2bda0e17
KB
462 atom, format, XTYP_REQUEST, 5000, &result);
463
b3324be2 464 DWORD len = DdeGetData(returned_data, (LPBYTE)(m_bufPtr), m_bufSize, 0);
2bda0e17
KB
465
466 DdeFreeDataHandle(returned_data);
467
468 if (size) *size = (int)len;
469 if (len > 0)
470 {
b3324be2 471 return m_bufPtr;
2bda0e17
KB
472 }
473 else return NULL;
474}
475
837e5743 476bool wxDDEConnection::Poke(const wxString& item, wxChar *data, int size, wxIPCFormat format)
2bda0e17
KB
477{
478 DWORD result;
479 if (size < 0)
837e5743 480 size = wxStrlen(data);
2bda0e17
KB
481
482 size ++;
483
484 HSZ item_atom = DDEGetAtom(item);
b3324be2 485 return (DdeClientTransaction((LPBYTE)data, size, (HCONV) m_hConv,
2bda0e17
KB
486 item_atom, format, XTYP_POKE, 5000, &result) ? TRUE : FALSE);
487}
488
489bool wxDDEConnection::StartAdvise(const wxString& item)
490{
491 DWORD result;
492 HSZ atom = DDEGetAtom(item);
493
b3324be2 494 return (DdeClientTransaction(NULL, 0, (HCONV) m_hConv,
2bda0e17
KB
495 atom, CF_TEXT, XTYP_ADVSTART, 5000, &result) ? TRUE : FALSE);
496}
497
498bool wxDDEConnection::StopAdvise(const wxString& item)
499{
500 DWORD result;
501 HSZ atom = DDEGetAtom(item);
502
b3324be2 503 return (DdeClientTransaction(NULL, 0, (HCONV) m_hConv,
2bda0e17
KB
504 atom, CF_TEXT, XTYP_ADVSTOP, 5000, &result) ? TRUE : FALSE);
505}
506
507// Calls that SERVER can make
837e5743 508bool wxDDEConnection::Advise(const wxString& item, wxChar *data, int size, wxIPCFormat format)
2bda0e17
KB
509{
510 if (size < 0)
837e5743 511 size = wxStrlen(data);
2bda0e17
KB
512
513 size ++;
514
515 HSZ item_atom = DDEGetAtom(item);
b3324be2
JS
516 HSZ topic_atom = DDEGetAtom(m_topicName);
517 m_sendingData = data;
518 m_dataSize = size;
519 m_dataType = format;
2bda0e17
KB
520 return (DdePostAdvise(DDEIdInst, topic_atom, item_atom) != 0);
521}
522
523bool wxDDEConnection::OnDisconnect(void)
524{
525 delete this;
526 return TRUE;
527}
528
529
530#define DDERETURN HDDEDATA
531
532HDDEDATA EXPENTRY _EXPORT _DDECallback(
533WORD wType,
534WORD wFmt,
535HCONV hConv,
536HSZ hsz1,
537HSZ hsz2,
538HDDEDATA hData,
539DWORD /* lData1 */,
540DWORD /* lData2 */)
541{
542 switch (wType)
543 {
544 case XTYP_CONNECT:
545 {
837e5743
OK
546 wxChar topic_buf[100];
547 wxChar server_buf[100];
548 DdeQueryString(DDEIdInst, hsz1, (LPTSTR)topic_buf, WXSIZEOF(topic_buf),
2bda0e17 549 CP_WINANSI);
837e5743 550 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)server_buf, WXSIZEOF(topic_buf),
2bda0e17
KB
551 CP_WINANSI);
552 wxDDEServer *server = DDEFindServer(server_buf);
553 if (server)
554 {
555 wxDDEConnection *connection =
556 (wxDDEConnection*) server->OnAcceptConnection(wxString(topic_buf));
557 if (connection)
558 {
b3324be2 559 connection->m_server = server;
2bda0e17 560 server->GetConnections().Append(connection);
b3324be2
JS
561 connection->m_hConv = 0;
562 connection->m_topicName = topic_buf;
2bda0e17
KB
563 DDECurrentlyConnecting = connection;
564 return (DDERETURN)TRUE;
565 }
566 }
567 else return (DDERETURN)0;
568 break;
569 }
570
571 case XTYP_CONNECT_CONFIRM:
572 {
573 if (DDECurrentlyConnecting)
574 {
b3324be2 575 DDECurrentlyConnecting->m_hConv = (WXHCONV) hConv;
2bda0e17
KB
576 DDECurrentlyConnecting = NULL;
577 return (DDERETURN)TRUE;
578 }
579 else return 0;
580 break;
581 }
582
583 case XTYP_DISCONNECT:
584 {
585 wxDDEConnection *connection = DDEFindConnection(hConv);
586 if (connection && connection->OnDisconnect())
587 {
588 DDEDeleteConnection(hConv); // Delete mapping: hConv => connection
589 return (DDERETURN)TRUE;
590 }
591 else return (DDERETURN)0;
592 break;
593 }
594
595 case XTYP_EXECUTE:
596 {
597 wxDDEConnection *connection = DDEFindConnection(hConv);
598
599 if (connection)
600 {
b3324be2 601 DWORD len = DdeGetData(hData, (LPBYTE)(connection->m_bufPtr), connection->m_bufSize, 0);
2bda0e17 602 DdeFreeDataHandle(hData);
0d2a2b60 603 if (connection->OnExecute(connection->m_topicName, connection->m_bufPtr, (int)len, (wxIPCFormat) wFmt))
2bda0e17
KB
604 return (DDERETURN)DDE_FACK;
605 else
606 return (DDERETURN)DDE_FNOTPROCESSED;
607 } else return (DDERETURN)DDE_FNOTPROCESSED;
608 break;
609 }
610
611 case XTYP_REQUEST:
612 {
613 wxDDEConnection *connection = DDEFindConnection(hConv);
614
615 if (connection)
616 {
837e5743
OK
617 wxChar item_name[200];
618 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
2bda0e17
KB
619 CP_WINANSI);
620
621 int user_size = -1;
0d2a2b60 622 char *data = connection->OnRequest(connection->m_topicName, wxString(item_name), &user_size, (wxIPCFormat) wFmt);
2bda0e17
KB
623 if (data)
624 {
625 if (user_size < 0) user_size = strlen(data);
626
627 HDDEDATA handle = DdeCreateDataHandle(DDEIdInst,
628 (LPBYTE)data, user_size + 1, 0, hsz2, wFmt, 0);
629 return (DDERETURN)handle;
630 } else return (DDERETURN)0;
631 } else return (DDERETURN)0;
632 break;
633 }
634
635 case XTYP_POKE:
636 {
637 wxDDEConnection *connection = DDEFindConnection(hConv);
638
639 if (connection)
640 {
837e5743
OK
641 wxChar item_name[200];
642 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
2bda0e17 643 CP_WINANSI);
b3324be2 644 DWORD len = DdeGetData(hData, (LPBYTE)(connection->m_bufPtr), connection->m_bufSize, 0);
2bda0e17 645 DdeFreeDataHandle(hData);
0d2a2b60 646 connection->OnPoke(connection->m_topicName, wxString(item_name), connection->m_bufPtr, (int)len, (wxIPCFormat) wFmt);
2bda0e17
KB
647 return (DDERETURN)DDE_FACK;
648 } else return (DDERETURN)DDE_FNOTPROCESSED;
649 break;
650 }
651
652 case XTYP_ADVSTART:
653 {
654 wxDDEConnection *connection = DDEFindConnection(hConv);
655
656 if (connection)
657 {
837e5743
OK
658 wxChar item_name[200];
659 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
2bda0e17
KB
660 CP_WINANSI);
661
b3324be2 662 return (DDERETURN)connection->OnStartAdvise(connection->m_topicName, wxString(item_name));
2bda0e17
KB
663 } else return (DDERETURN)0;
664 break;
665 }
666
667 case XTYP_ADVSTOP:
668 {
669 wxDDEConnection *connection = DDEFindConnection(hConv);
670
671 if (connection)
672 {
837e5743
OK
673 wxChar item_name[200];
674 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
2bda0e17 675 CP_WINANSI);
b3324be2 676 return (DDERETURN)connection->OnStopAdvise(connection->m_topicName, wxString(item_name));
2bda0e17
KB
677 } else return (DDERETURN)0;
678 break;
679 }
680
681 case XTYP_ADVREQ:
682 {
683 wxDDEConnection *connection = DDEFindConnection(hConv);
684
b3324be2 685 if (connection && connection->m_sendingData)
2bda0e17
KB
686 {
687 HDDEDATA data = DdeCreateDataHandle(DDEIdInst,
b3324be2
JS
688 (LPBYTE)connection->m_sendingData,
689 connection->m_dataSize, 0, hsz2, connection->m_dataType, 0);
690 connection->m_sendingData = NULL;
2bda0e17
KB
691 return (DDERETURN)data;
692 } else return (DDERETURN)NULL;
693 break;
694 }
695
696 case XTYP_ADVDATA:
697 {
698 wxDDEConnection *connection = DDEFindConnection(hConv);
699
700 if (connection)
701 {
837e5743
OK
702 wxChar item_name[200];
703 DdeQueryString(DDEIdInst, hsz2, (LPTSTR)item_name, WXSIZEOF(item_name),
2bda0e17
KB
704 CP_WINANSI);
705
b3324be2 706 DWORD len = DdeGetData(hData, (LPBYTE)(connection->m_bufPtr), connection->m_bufSize, 0);
2bda0e17 707 DdeFreeDataHandle(hData);
0d2a2b60 708 if (connection->OnAdvise(connection->m_topicName, wxString(item_name), connection->m_bufPtr, (int)len, (wxIPCFormat) wFmt))
2bda0e17
KB
709 return (DDERETURN)DDE_FACK;
710 else
711 return (DDERETURN)DDE_FNOTPROCESSED;
712 } else return (DDERETURN)DDE_FNOTPROCESSED;
713 break;
714 }
715 }
716 return 0;
717}
718
719// Atom table stuff
720static HSZ DDEAddAtom(const wxString& string)
721{
837e5743 722 HSZ atom = DdeCreateStringHandle(DDEIdInst, WXSTRINGCAST string, CP_WINANSI);
2bda0e17
KB
723 wxAtomTable.Append(string, (wxObject *)atom);
724 return atom;
725}
726
727static HSZ DDEGetAtom(const wxString& string)
728{
729 wxNode *node = wxAtomTable.Find(string);
730 if (node)
731 return (HSZ)node->Data();
732 else
733 {
734 DDEAddAtom(string);
735 return (HSZ)(wxAtomTable.Find(string)->Data());
736 }
737}
738
739void DDEPrintError(void)
740{
837e5743 741 wxChar *err = NULL;
2bda0e17
KB
742 switch (DdeGetLastError(DDEIdInst))
743 {
744 case DMLERR_ADVACKTIMEOUT:
837e5743 745 err = _T("A request for a synchronous advise transaction has timed out.");
2bda0e17
KB
746 break;
747 case DMLERR_BUSY:
837e5743 748 err = _T("The response to the transaction caused the DDE_FBUSY bit to be set.");
2bda0e17
KB
749 break;
750 case DMLERR_DATAACKTIMEOUT:
837e5743 751 err = _T("A request for a synchronous data transaction has timed out.");
2bda0e17
KB
752 break;
753 case DMLERR_DLL_NOT_INITIALIZED:
837e5743 754 err = _T("A DDEML function was called without first calling the DdeInitialize function,\n\ror an invalid instance identifier\n\rwas passed to a DDEML function.");
2bda0e17
KB
755 break;
756 case DMLERR_DLL_USAGE:
837e5743 757 err = _T("An application initialized as APPCLASS_MONITOR has\n\rattempted to perform a DDE transaction,\n\ror an application initialized as APPCMD_CLIENTONLY has \n\rattempted to perform server transactions.");
2bda0e17
KB
758 break;
759 case DMLERR_EXECACKTIMEOUT:
837e5743 760 err = _T("A request for a synchronous execute transaction has timed out.");
2bda0e17
KB
761 break;
762 case DMLERR_INVALIDPARAMETER:
837e5743 763 err = _T("A parameter failed to be validated by the DDEML.");
2bda0e17
KB
764 break;
765 case DMLERR_LOW_MEMORY:
837e5743 766 err = _T("A DDEML application has created a prolonged race condition.");
2bda0e17
KB
767 break;
768 case DMLERR_MEMORY_ERROR:
837e5743 769 err = _T("A memory allocation failed.");
2bda0e17
KB
770 break;
771 case DMLERR_NO_CONV_ESTABLISHED:
837e5743 772 err = _T("A client's attempt to establish a conversation has failed.");
2bda0e17
KB
773 break;
774 case DMLERR_NOTPROCESSED:
837e5743 775 err = _T("A transaction failed.");
2bda0e17
KB
776 break;
777 case DMLERR_POKEACKTIMEOUT:
837e5743 778 err = _T("A request for a synchronous poke transaction has timed out.");
2bda0e17
KB
779 break;
780 case DMLERR_POSTMSG_FAILED:
837e5743 781 err = _T("An internal call to the PostMessage function has failed. ");
2bda0e17
KB
782 break;
783 case DMLERR_REENTRANCY:
837e5743 784 err = _T("Reentrancy problem.");
2bda0e17
KB
785 break;
786 case DMLERR_SERVER_DIED:
837e5743 787 err = _T("A server-side transaction was attempted on a conversation\n\rthat was terminated by the client, or the server\n\rterminated before completing a transaction.");
2bda0e17
KB
788 break;
789 case DMLERR_SYS_ERROR:
837e5743 790 err = _T("An internal error has occurred in the DDEML.");
2bda0e17
KB
791 break;
792 case DMLERR_UNADVACKTIMEOUT:
837e5743 793 err = _T("A request to end an advise transaction has timed out.");
2bda0e17
KB
794 break;
795 case DMLERR_UNFOUND_QUEUE_ID:
837e5743 796 err = _T("An invalid transaction identifier was passed to a DDEML function.\n\rOnce the application has returned from an XTYP_XACT_COMPLETE callback,\n\rthe transaction identifier for that callback is no longer valid.");
2bda0e17
KB
797 break;
798 default:
837e5743 799 err = _T("Unrecognised error type.");
2bda0e17
KB
800 break;
801 }
837e5743 802 MessageBox((HWND) NULL, (LPCTSTR)err, _T("DDE Error"), MB_OK | MB_ICONINFORMATION);
2bda0e17
KB
803}
804
805#endif
47d67540 806 // wxUSE_IPC