lib/dde/xl_server.rb in dde-0.2.8 vs lib/dde/xl_server.rb in dde-0.2.9

- old
+ new

@@ -5,16 +5,18 @@ # Class encapsulates DDE Server mimicking Excel. It is used to create DDE server with specific service name # (default name 'excel') and store data received by the server via DDE class XlServer < Server attr_reader :format, # data format(s) (registered clipboard formats) that server supports - :table # data table for data storage + :data # data storage/processor + attr_accessor :actions # Actions to be run on table after each successful DDE input (:draw, :debug, :timer) + # Creates new Xl Server instance def initialize(init_flags = nil, &dde_callback ) - @table = DDE::XlTable.new + @data = DDE::XlTable.new # Trying to register or retrieve existing format XlTable try 'Registering format XlTable', DDE::Errors::FormatError do @format = register_clipboard_format("XlTable") end @@ -23,91 +25,66 @@ end # HDDEDATA CALLBACK DdeCallback(UINT uType, UINT uFmt, HCONV hConv, HSZ hsz1, HSZ hsz2, # HDDEDATA hData, DWORD dwData1, DWORD dwData2) def default_callback - lambda do |type, format, conv, hsz1, hsz2, data, data1, data2| + 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 - # format:: Not used. - # conv:: Not used. - # hsz1:: Handle to the topic name. - # hsz2:: Handle to the service name. - # data:: Handle to DDE data. Meaning of this parameter depends on the type of the current transaction. - # data1:: 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. - # data2:: 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). + # format:: Not used. + # conv:: Not used. + # hsz1:: Handle to the topic name. + # hsz2:: Handle to the service name. + # data_handle:: Handle to DDE data. Meaning depends on the type of the current transaction. + # data1:: Pointer to a CONVCONTEXT structure that contains context information for the conversation. + # If the client is not a DDEML application, this parameter is 0. + # data2:: Specifies whether the client is the same application instance as the server. If the parameter + # is 1, the client is the same instance. If it is 0, the client is a different instance. + # *Returns*:: A server callback function should return TRUE(1, but DDE_FACK works just fine too) + # 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 and a conversation is successfully established, the system passes + # the conversation 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 == @service.handle cout "Service #{@service}: connect requested by client\n" - 1 # instead of true # Yes, this server supports requested (name) handle + DDE_FACK # instead of true # Yes, this server supports requested (name) handle else cout "Service #{@service} unable to process connection request for #{hsz2}\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. + # 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. - if @table.get_data(data) # Extract incoming DDE data from client into server's table - # Converting hsz1 into "[topic]item" string and - @table.topic = dde_query_string(@id, hsz1) - # @table.draw # Simply printing it for now, no queues - @table.timer - # // 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); - # + @data.topic = dde_query_string(@id, hsz1) # Convert hsz1 into "[topic]item" string and + if @data.receive(data_handle) # Receive incoming DDE data and process it + + # Perform actions like :draw, :debug, :timer, :formats on received data (default :timer) + @actions.each{|action| @data.send(action.to_sym)} DDE_FACK # Transaction successful else + @data.debug cout "Service #{@service} unable to process data request (XTYP_POKE) for #{hsz2}" 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 end - # Make 'excel' the default name for named service - alias_method :__start_service, :start_service - def start_service( name='excel', init_flags=nil, &dde_callback) - dde_callback ||= default_callback - __start_service( name, init_flags, &dde_callback ) + super name, init_flags, &dde_callback || default_callback end end end \ No newline at end of file