#!/usr/bin/env ruby lib = File.join(File.dirname(__FILE__), '..', 'lib') $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include? lib require 'dde' # console output redirection (may need to wrap it in synchronization code, etc) def cout *args print *args end cout "Starting script\n" require 'win/gui/message' include Win::GUI::Message include Win::DDE server = DDE::XlServer.new # create server # std::queue q; // Queue contains the tables to output # HDDEDATA CALLBACK DdeCallback(UINT uType, UINT uFmt, HCONV hConv, HSZ hsz1, HSZ hsz2, # HDDEDATA hData, DWORD dwData1, DWORD dwData2) dde_callback = lambda do |type, format, conv, hsz1, hsz2, data_handle, data1, data2| case type when XTYP_CONNECT # Request to connect from client, creating data exchange channel # hsz1:: Handle to the topic name. # hsz2:: Handle to the service name. # dwData1:: Pointer to a CONVCONTEXT structure that contains context information for the conversation. # If the client is not a Dynamic Data Exchange Management Library (DDEML) application, # this parameter is 0. # dwData2:: Specifies whether the client is the same application instance as the server. If the # parameter is 1, the client is the same instance. If the parameter is 0, the client # is a different instance. # *Returns*:: A server callback function should return TRUE(1) to allow the client to establish a # conversation on the specified service name and topic name pair, or the function # should return FALSE to deny the conversation. If the callback function returns TRUE(1) # and a conversation is successfully established, the system passes the conversation # todo: handle to the server by issuing an XTYP_CONNECT_CONFIRM transaction to the server's # callback function (unless the server specified the CBF_SKIP_CONNECT_CONFIRMS flag # in the DdeInitialize function). if hsz2 == server.service.handle 1 # instead of true # Yes, this server supports requested (name) handle else cout "Unable to process connection request for #{hsz2}, service handle is #{server.service}\n" DDE_FNOTPROCESSED # 0 instead of false # No, server does not support requested (name) handle end when XTYP_POKE # Client initiated XTYP_POKE transaction to push unsolicited data to the server # format:: Specifies the format of the data sent from the server. # conv:: Handle to the conversation. # hsz1:: Handle to the topic name. (Excel: [topic]item ?!) # hsz2:: Handle to the item name. # data_handle:: Handle to the data that the client is sending to the server. # *Returns*:: A server callback function should return the DDE_FACK flag if it processes this # transaction, the DDE_FBUSY flag if it is too busy to process this transaction, # or the DDE_FNOTPROCESSED flag if it rejects this transaction. # # # CHAR buf[200]; flag = server.table.get_data(data_handle) # extract client's DDE data into server's xltable if flag # Converting hsz1 into "[topic]item" string and server.table.topic_item = dde_query_string(server.id, hsz1) server.table.draw # Simply printing it for now, no queues # // Placing table into print queue # WaitForSingleObject(hMutex1,INFINITE); # q.push(server.xltable); # ReleaseMutex(hMutex1); # // Allowing the table output thread to start... # ReleaseSemaphore(hSemaphore,1,NULL); # cout "Transaction finished" DDE_FACK # Transaction successful else cout "Unable to receive dataprocess connection request for #{hsz2}, server handle is #{server.handle}\n" DDE_FNOTPROCESSED # 0 Transaction NOT successful - return (HDDEDATA)TRUE; ?!(why TRUE, not FALSE) end when XTYP_DISCONNECT # DDE client disconnects # server.xltable.Delete(); # break; DDE_FNOTPROCESSED # 0 - return((HDDEDATA)NULL);// is it the same as 0 ?! when XTYP_ERROR # DDE Error # WaitForSingleObject(hMutex, INFINITE); # std::cerr<<"DDE error.\n"; # ReleaseMutex(hMutex); # break; DDE_FNOTPROCESSED # 0 - return((HDDEDATA)NULL);// is it the same as 0 ?! else DDE_FNOTPROCESSED # 0 - return((HDDEDATA)NULL);// is it the same as 0 ?! end end # Staring service with default name 'excel' cout "Starting DDE service 'excel'\n" server.start_service &dde_callback msg = Msg.new # pointer to Msg FFI struct # Starting message loop (necessary for DDE processing) cout "Starting message loop\n" while msg = get_message(msg) translate_message(msg); dispatch_message(msg); end