\section{Interprocess communication overview}\label{ipcoverview}
 
-Classes: \helpref{wxDDEServer}{wxddeserver}, \helpref{wxDDEConnection}{wxddeconnection}, 
-\helpref{wxDDEClient}{wxddeclient}, 
-\helpref{wxTCPServer}{wxtcpserver}, \helpref{wxTCPConnection}{wxtcpconnection}, 
-\helpref{wxTCPClient}{wxtcpclient}
+Classes: \helpref{wxServer}{wxddeserver},
+\helpref{wxConnection}{wxddeconnection},
+\helpref{wxClient}{wxddeclient}
+%\helpref{wxTCPServer}{wxtcpserver}, \helpref{wxTCPConnection}{wxtcpconnection},
+%\helpref{wxTCPClient}{wxtcpclient}
 
-wxWindows has a number of different classes to help with interprocess communication
-and network programming. This section only discusses one family of classes - the DDE-like
-protocol - but here's a list of other useful classes:
+wxWindows has a number of different classes to help with
+interprocess communication and network programming. This section
+only discusses one family of classes -- the DDE-like protocol --
+but here's a list of other useful classes:
 
 \begin{itemize}\itemsep=0pt
-\item \helpref{wxSocketEvent}{wxsocketevent}, 
-\helpref{wxSocketBase}{wxsocketbase}, 
-\helpref{wxSocketClient}{wxsocketclient}, 
+\item \helpref{wxSocketEvent}{wxsocketevent},
+\helpref{wxSocketBase}{wxsocketbase},
+\helpref{wxSocketClient}{wxsocketclient},
 \helpref{wxSocketServer}{wxsocketserver}: classes for the low-level TCP/IP API.
-\item \helpref{wxProtocol}{wxprotocol}, \helpref{wxURL}{wxurl}, \helpref{wxFTP}{wxftp}, wxHTTP: classes
+\item \helpref{wxProtocol}{wxprotocol}, \helpref{wxURL}{wxurl}, \helpref{wxFTP}{wxftp}, \helpref{wxHTTP}{wxhttp}: classes
 for programming popular Internet protocols.
 \end{itemize}
 
-Further information on these classes will be available in due course.
+wxWindows' DDE-like protocol is a high-level protocol based on
+Windows DDE. There are two implementations of this DDE-like
+protocol: one using real DDE running on Windows only, and another
+using TCP/IP (sockets) that runs on most platforms. Since the API
+and virtually all of the behaviour is the same apart from the
+names of the classes, you should find it easy to switch between
+the two implementations.
 
-Notice that by including {\tt <wx/ipc.h>} you may define convnient synonyms for
-the IPC classes: {\tt wxServer} for either {\tt wxDDEServer} or 
-{\tt wxTCPServer} depending on whether DDE-based or socket-based implementation
-is used and the same thing for {\tt wxClient} and {\tt wxConnection}. By
-default, DDE implementation is used under Windows. If you want to use IPC
-between the different workstations you should define {\tt wxUSE\_DDE\_FOR\_IPC}
-as $0$ before including this header -- this will force using TCP/IP
-implementation even under Windows.
+Notice that by including {\tt <wx/ipc.h>} you may define
+convenient synonyms for the IPC classes: {\tt wxServer} for either
+{\tt wxDDEServer} or {\tt wxTCPServer} depending on whether
+DDE-based or socket-based implementation is used and the same
+thing for {\tt wxClient} and {\tt wxConnection}.
 
+By default, DDE implementation is used under Windows. DDE works
+only within one computer. If you want to use IPC between
+different workstations you should define {\tt
+wxUSE\_DDE\_FOR\_IPC} as $0$ before including this header -- this
+will force using TCP/IP implementation even under Windows.
 
-wxWindows has a high-level protocol based on Windows DDE.
-There are two implementations of this DDE-like protocol:
-one using real DDE running on Windows only, and another using TCP/IP (sockets) that runs
-on most platforms. Since the API is the same apart from the names of the classes, you
-should find it easy to switch between the two implementations.
+The following description refers to wx... but remember that the
+equivalent wxTCP... and wxDDE... classes can be used in much the
+same way.
 
-The following description refers to 'DDE' but remember that the equivalent wxTCP... classes
-can be used in much the same way.
-
-Three classes are central to the DDE API:
+Three classes are central to the DDE-like API:
 
 \begin{enumerate}\itemsep=0pt
-\item wxDDEClient. This represents the client application, and is used
+\item wxClient. This represents the client application, and is used
 only within a client program.
-\item wxDDEServer. This represents the server application, and is used
+\item wxServer. This represents the server application, and is used
 only within a server program.
-\item wxDDEConnection. This represents the connection from the current
-client or server to the other application (server or client), and can be used
-in both server and client programs. Most DDE
-transactions operate on this object.
+\item wxConnection. This represents the connection from the
+client to the server - both the client and the server use an
+instance of this class, one per connection. Most DDE transactions
+operate on this object.
 \end{enumerate}
 
-Messages between applications are usually identified by three variables:
-connection object, topic name and item name.  A data string is a fourth
-element of some messages. To create a connection (a conversation in
-Windows parlance), the client application sends the message
-MakeConnection to the client object, with a string service name to
-identify the server and a topic name to identify the topic for the
-duration of the connection. Under Unix, the service name may be either an
-integer port identifier in which case an Internet domain socket will be used
-for the communications or a valid file name (which shouldn't exist and will be
-deleted afterwards) in which case a Unix domain socket is created.
+Messages between applications are usually identified by three
+variables: connection object, topic name and item name.  A data
+string is a fourth element of some messages. To create a
+connection (a conversation in Windows parlance), the client
+application uses wxClient::MakeConnection to send a message to the
+server object, with a string service name to identify the server
+and a topic name to identify the topic for the duration of the
+connection. Under Unix, the service name may be either an integer
+port identifier in which case an Internet domain socket will be
+used for the communications or a valid file name (which shouldn't
+exist and will be deleted afterwards) in which case a Unix domain
+socket is created.
 
 {\bf SECURITY NOTE:} Using Internet domain sockets if extremely insecure for
 IPC as there is absolutely no access control for them, use Unix domain sockets
 whenever possible!
 
-The server then responds and either vetoes the connection or allows it.
-If allowed, a connection object is created which persists until the
-connection is closed.  The connection object is then used for subsequent
-messages between client and server.
+The server then responds and either vetoes the connection or
+allows it. If allowed, both the server and client objects create
+wxConnection objects which persist until the connection is
+closed. The connection object is then used for sending and
+receiving subsequent messages between client and server -
+overriding virtual functions in your class derived from
+wxConnection allows you to handle the DDE messages.
 
 To create a working server, the programmer must:
 
 \begin{enumerate}\itemsep=0pt
-\item Derive a class from wxDDEServer.
-\item Override the handler OnAcceptConnection for accepting or rejecting a connection,
-on the basis of the topic argument. This member must create and return a connection
-object if the connection is accepted.
-\item Create an instance of your server object, and call Create to
+\item Derive a class from wxConnection, providing handlers for various messages sent to the server
+side of a wxConnection (e.g. OnExecute, OnRequest, OnPoke). Only
+the handlers actually required by the application need to be
+overridden.
+\item Derive a class from wxServer, overriding OnAcceptConnection
+to accept or reject a connection on the basis of the topic
+argument. This member must create and return an instance of the
+derived connection class if the connection is accepted.
+\item Create an instance of your server object and call Create to
 activate it, giving it a service name.
-\item Derive a class from wxDDEConnection.
-\item Provide handlers for various messages that are sent to the server
-side of a wxDDEConnection.
 \end{enumerate}
 
 To create a working client, the programmer must:
 
 \begin{enumerate}\itemsep=0pt
-\item Derive a class from wxDDEClient.
-\item Override the handler OnMakeConnection to create and return
-an appropriate connection object.
+\item Derive a class from wxConnection, providing handlers for various
+messages sent to the client side of a wxConnection (e.g.
+OnAdvise). Only the handlers actually required by the application
+need to be overridden.
+\item Derive a class from wxClient, overriding OnMakeConnection to
+create and return an instance of the derived connection class.
 \item Create an instance of your client object.
-\item Derive a class from wxDDEConnection.
-\item Provide handlers for various messages that are sent to the client
-side of a wxDDEConnection.
-\item When appropriate, create a new connection by sending a MakeConnection
-message to the client object, with arguments host name (processed in Unix only),
-service name, and topic name for this connection. The client object will call OnMakeConnection
-to create a connection object of the desired type.
-\item Use the wxDDEConnection member functions to send messages to the server.
+\item When appropriate, create a new connection using
+\helpref{wxClient::MakeConnection}{wxddeclientmakeconnection},
+with arguments host name (processed in Unix only, use `localhost'
+for local computer), service name, and topic name for this
+connection. The client object will call
+\helpref{OnMakeConnection}{wxddeclientonmakeconnection} to create
+a connection object of the derived class if the connection is
+successful.
+\item Use the wxConnection member functions to send messages to the server.
 \end{enumerate}
 
 \subsection{Data transfer}
 
-These are the ways that data can be transferred from one application to
-another.
+These are the ways that data can be transferred from one
+application to another. These are methods of wxConnection.
 
 \begin{itemize}\itemsep=0pt
 \item {\bf Execute:} the client calls the server with a data string representing
 
 \subsection{More DDE details}
 
-A wxDDEClient object represents the client part of a client-server DDE
-(Dynamic Data Exchange) conversation (available in both
+A wxClient object initiates the client part of a client-server
+DDE-like (Dynamic Data Exchange) conversation (available in both
 Windows and Unix).
 
 To create a client which can communicate with a suitable server,
-you need to derive a class from wxDDEConnection and another from wxDDEClient.
-The custom wxDDEConnection class will intercept communications in
-a `conversation' with a server, and the custom wxDDEServer is required
-so that a user-overridden \helpref{wxDDEClient::OnMakeConnection}{wxddeclientonmakeconnection} member can return
-a wxDDEConnection of the required class, when a connection is made.
+you need to derive a class from wxConnection and another from
+wxClient. The custom wxConnection class will receive
+communications in a `conversation' with a server.  and the custom
+wxServer is required so that a user-overridden
+\helpref{wxDDEClient::OnMakeConnection}{wxddeclientonmakeconnection}
+member can return a wxDDEConnection of the required class, when a
+connection is made.
 
 For example:
 
 \begin{verbatim}
-class MyConnection: public wxDDEConnection
-{
+class MyConnection: public wxConnection {
  public:
-  MyConnection(void)::wxDDEConnection(ipc_buffer, 3999) {}
+  MyConnection(void)::wxConnection() {}
   ~MyConnection(void) { }
   bool OnAdvise(const wxString& topic, const wxString& item, char *data, int size, wxIPCFormat format)
   { wxMessageBox(topic, data); }
 };
 
-class MyClient: public wxDDEClient
-{
+class MyClient: public wxClient {
  public:
   MyClient(void) {}
   wxConnectionBase *OnMakeConnection(void) { return new MyConnection; }
 
 \end{verbatim}
 
-Here, {\bf MyConnection} will respond to \helpref{OnAdvise}{wxddeconnectiononadvise} messages sent
-by the server.
-
-When the client application starts, it must create an instance of the derived wxDDEClient. In the following, command line
-arguments are used to pass the host name (the name of the machine the server is running
-on) and the server name (identifying the server process). Calling \helpref{wxDDEClient::MakeConnection}{wxddeclientmakeconnection}\rtfsp
-implicitly creates an instance of {\bf MyConnection} if the request for a
-connection is accepted, and the client then requests an {\it Advise} loop
-from the server, where the server calls the client when data has changed.
+Here, {\bf MyConnection} will respond to
+\helpref{OnAdvise}{wxddeconnectiononadvise} messages sent by the
+server by displaying a message box.
+
+When the client application starts, it must create an instance of
+the derived wxClient. In the following, command line arguments
+are used to pass the host name (the name of the machine the
+server is running on) and the server name (identifying the server
+process). Calling
+\helpref{wxDDEClient::MakeConnection}{wxddeclientmakeconnection}\rtfsp
+implicitly creates an instance of {\bf MyConnection} if the
+request for a connection is accepted, and the client then
+requests an {\it Advise} loop from the server (an Advise loop is
+where the server calls the client when data has changed).
 
 \begin{verbatim}
   wxString server = "4242";
 
 static wxList wxDDEClientObjects;
 static wxList wxDDEServerObjects;
 
-char *DDEDefaultIPCBuffer = NULL;
-int DDEDefaultIPCBufferSize = 0;
 static bool DDEInitialized = FALSE;
 
 // ----------------------------------------------------------------------------
         DdeUninitialize(DDEIdInst);
         DDEIdInst = 0;
     }
-
-    delete [] DDEDefaultIPCBuffer;
 }
 
 // ----------------------------------------------------------------------------
     {
         wxDDEConnection *connection = (wxDDEConnection *)node->Data();
         wxNode *next = node->Next();
+        connection->SetConnected(false);
         connection->OnDisconnect(); // May delete the node implicitly
         node = next;
     }
 // ----------------------------------------------------------------------------
 
 wxDDEConnection::wxDDEConnection(char *buffer, int size)
+     : wxConnectionBase(buffer, size)
 {
-    if (buffer == NULL)
-    {
-        if (DDEDefaultIPCBuffer == NULL)
-            DDEDefaultIPCBuffer = new char[DDEDefaultIPCBufferSize];
-        m_bufPtr = DDEDefaultIPCBuffer;
-        m_bufSize = DDEDefaultIPCBufferSize;
-    }
-    else
-    {
-        m_bufPtr = buffer;
-        m_bufSize = size;
-    }
-
     m_client = NULL;
     m_server = NULL;
 
 }
 
 wxDDEConnection::wxDDEConnection()
+     : wxConnectionBase()
 {
     m_hConv = 0;
     m_sendingData = NULL;
     m_server = NULL;
     m_client = NULL;
-    if (DDEDefaultIPCBuffer == NULL)
-        DDEDefaultIPCBuffer = new char[DDEDefaultIPCBufferSize];
-
-    m_bufPtr = DDEDefaultIPCBuffer;
-    m_bufSize = DDEDefaultIPCBufferSize;
 }
 
 wxDDEConnection::~wxDDEConnection()
 {
+    Disconnect();
     if (m_server)
         m_server->GetConnections().DeleteObject(this);
     else
 // Calls that CLIENT can make
 bool wxDDEConnection::Disconnect()
 {
+    if ( !GetConnected() )
+        return true;
+
     DDEDeleteConnection(GetHConv());
 
     bool ok = DdeDisconnect(GetHConv()) != 0;
         DDELogError(_T("Failed to disconnect from DDE server gracefully"));
     }
 
+    SetConnected( false );  // so we don't try and disconnect again
+
     return ok;
 }
 
 char *wxDDEConnection::Request(const wxString& item, int *size, wxIPCFormat format)
 {
     DWORD result;
+
     HSZ atom = DDEGetAtom(item);
 
     HDDEDATA returned_data = DdeClientTransaction(NULL, 0,
         return NULL;
     }
 
-    DWORD len = DdeGetData(returned_data, (LPBYTE)m_bufPtr, m_bufSize, 0);
+    DWORD len = DdeGetData(returned_data, NULL, 0, 0);
+
+    wxChar *data = GetBufferAtLeast( len );
+    wxASSERT_MSG(data != NULL,
+                 _T("Buffer too small in wxDDEConnection::Request") );
+    DdeGetData(returned_data, (LPBYTE)data, len, 0);
 
     DdeFreeDataHandle(returned_data);
 
     if (size)
         *size = (int)len;
 
-    return m_bufPtr;
+    return data;
 }
 
 bool wxDDEConnection::Poke(const wxString& item, wxChar *data, int size, wxIPCFormat format)
 
     HSZ item_atom = DDEGetAtom(item);
     HSZ topic_atom = DDEGetAtom(m_topicName);
-    m_sendingData = data;
+    m_sendingData = data;  // mrf: potential for scope problems here?
     m_dataSize = size;
     m_dataType = format;
 
         case XTYP_DISCONNECT:
             {
                 wxDDEConnection *connection = DDEFindConnection(hConv);
-                if (connection && connection->OnDisconnect())
+                if (connection)
                 {
-                    DDEDeleteConnection(hConv);  // Delete mapping: hConv => connection
-                    return (DDERETURN)(DWORD)TRUE;
+                    connection->SetConnected( false );
+                    if (connection->OnDisconnect())
+                    {
+                        DDEDeleteConnection(hConv);  // Delete mapping: hConv => connection
+                        return (DDERETURN)(DWORD)TRUE;
+                    }
                 }
                 break;
             }
 
                 if (connection)
                 {
-                    DWORD len = DdeGetData(hData,
-                                           (LPBYTE)connection->m_bufPtr,
-                                           connection->m_bufSize,
-                                           0);
+                    DWORD len = DdeGetData(hData, NULL, 0, 0);
+
+                    wxChar *data = connection->GetBufferAtLeast( len );
+                    wxASSERT_MSG(data != NULL,
+                                 _T("Buffer too small in _DDECallback (XTYP_EXECUTE)") );
+
+                    DdeGetData(hData, (LPBYTE)data, len, 0);
+
                     DdeFreeDataHandle(hData);
+
                     if ( connection->OnExecute(connection->m_topicName,
-                                               connection->m_bufPtr,
+                                               data,
                                                (int)len,
                                                (wxIPCFormat) wFmt) )
                     {
                 {
                     wxString item_name = DDEStringFromAtom(hsz2);
 
-                    DWORD len = DdeGetData(hData,
-                                           (LPBYTE)connection->m_bufPtr,
-                                           connection->m_bufSize,
-                                           0);
+                    DWORD len = DdeGetData(hData, NULL, 0, 0);
+
+                    wxChar *data = connection->GetBufferAtLeast( len );
+                    wxASSERT_MSG(data != NULL,
+                                 _T("Buffer too small in _DDECallback (XTYP_EXECUTE)") );
+
+                    DdeGetData(hData, (LPBYTE)data, len, 0);
+
                     DdeFreeDataHandle(hData);
 
                     connection->OnPoke(connection->m_topicName,
                                        item_name,
-                                       (wxChar*)connection->m_bufPtr,
+                                       data,
                                        (int)len,
                                        (wxIPCFormat) wFmt);
 
                 {
                     wxString item_name = DDEStringFromAtom(hsz2);
 
-                    DWORD len = DdeGetData(hData,
-                                           (LPBYTE)connection->m_bufPtr,
-                                           connection->m_bufSize,
-                                           0);
+                    DWORD len = DdeGetData(hData, NULL, 0, 0);
+
+                    wxChar *data = connection->GetBufferAtLeast( len );
+                    wxASSERT_MSG(data != NULL,
+                                 _T("Buffer too small in _DDECallback (XTYP_ADVDATA)") );
+
+                    DdeGetData(hData, (LPBYTE)data, len, 0);
+
                     DdeFreeDataHandle(hData);
                     if ( connection->OnAdvise(connection->m_topicName,
                                               item_name,
-                                              connection->m_bufPtr,
+                                              data,
                                               (int)len,
                                               (wxIPCFormat) wFmt) )
                     {