A very minimal DDE interface is provided. The interface is very simple and based on the DDEML library. As a server, WXLS allows connections to the topic XLISP-STAT under the service name XLISP-STAT. It accepts two kinds of transactions:
dde-connect takes two arguments, strings naming a service and a topic. The topic string is optional; it defaults to the service string. The return value is a descriptor of the conversation if the connection is established, otherwise it is nil. At the moment conversation descriptors are integer indices into a table, and the number of concurrent conversation is limited to 30. This may change.
dde-disconnect takes a conversation descriptor and attempts to close the conversation. If successful it returns t, otherwise nil. If dde-disconnect is called with no arguments, then all currently active conversations are terminated. In this case the return value is t if any are terminated, nil if not.
dde-client-transaction requires a conversation descriptor as its first argument. The remaining arguments are keyword arguments:
As an example, you could have WXLS communicate with WXLS by DDE (why you would want to I do not know, but it works):
> (dde-connect "xlisp-stat") 0 > (dde-client-transaction 0 :data "(+ 1 2)") T > (dde-client-transaction 0 :type :request :item "value") "3" > (dde-disconnect 0) TYou can also communicate with the program manager:
> (dde-connect "progman") 0 > (dde-client-transaction 0 :type :request :item "Groups") "Accessories\r Gnu Emacs\r Microsoft Visual C++ 5.0\r Metrowerks CodeWarrior\r StartUp\r Adobe Acrobat\r Macromedia Shockwave\r StuffIt\r Watcom C_C++\r Watcom C_C++ Tools Help\r Watcom C_C++ Additional Help\r Borland C++ 5.02\r Corman Lisp 1.21\r Microsoft Reference\r " > (dde-client-transaction 0 :data "[ShowGroup(Gnu Emacs,1)]") T > (dde-disconnect 0) TThe first transaction is an execute transaction that opens the Main group's window. The second is a request that obtains a list of the current groups.
There is one additional client function, dde-services. This function takes two optional arguments, service and a topic arguments, which should be strings or nil. It returns a list of all matching services as a list of lists of a service and a topic name. Some examples:
> (dde-services "progman") (("PROGMAN"f "PROGMAN") ("SHELL" "APPPROPERTIES") ("FOLDERS" "APPPROPERTIES")) > (dde-services) (("XLISP-STAT" "XLISP-STAT") ("XLISP-STAT" "SYSTEM") ("PROGMAN" "PROGMAN") ("SHELL" "APPPROPERTIES") ("FOLDERS" "APPPROPERTIES")) > (dde-services "shell") (("PROGMAN" "PROGMAN") ("SHELL" "APPPROPERTIES") ("FOLDERS" "APPPROPERTIES"))
This DDE interface is experimental and may change. For the moment it seems adequate for providing configuring the integration of WXLS into Windows during setup.
I have recently added a few higher level functions to simplify acting as a DDE client. These functions are patterned after the DDE client interface in VBA. The available functions are dde-execute, dde-request, and dde-poke.
dde-execute takes a conversation descriptor and a command string as arguments. It returns t on success and nil on failure.
dde-request takes a conversation descriptor and an item string as arguments. It also accepts the :binary keyword argument. On success it returns a string or a binary array, depending on the binary argument; on failure it returns nil.
dde-poke takes a conversation descriptor, an item string, and a
value as arguments. The value can be any Lisp object; if it is not a
string it is converted to one using format with the
dde-services takes optional service and topic names and returns a list of all matching service-topic pairs.
As an example, here is how to interact with an Excel document. THIs assumes that Excel is running. This is adapted from an example provided by Russell Lenth.
First, you can ask Excel to load a spread sheet:
> (setf chan (dde-connect "excel" "system")) 0 > (dde-execute chan "[Open(\"fred.xls\")]") T > (dde-disconnect chan) TNext, open a connection to the spread sheet and ask for the contents of the first column:
> (setf chan (dde-connect "excel" "[fred.xls]Sheet1")) 0 > (dde-request chan "c1") "HELLO\r 2\r "Finally, place a new value is row 1, column 3, retrieve row 1, and close the connection:
> (dde-poke 0 "r1c3" 5) T > (dde-request 0 "r1") "HELLO\t3\t5\r " > (dde-disconnect chan) T
The DDE server has been redesigned to allow customization via an object-based interface. This is still very much experimental. Details are given elsewhere.