vruby 2004.08.07

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,625 @@
1
+ ###################################
2
+ #
3
+ # vrdde.rb
4
+ # Programmed by nyasu <nyasu@osk.3web.ne.jp>
5
+ # Copyright 1999-2001 Nishikawa,Yasuhiro
6
+ #
7
+ # More information at http://www.threeweb.ad.jp/~nyasu/software/vrproject.html
8
+ # (in Japanese)
9
+ #
10
+ ###################################
11
+
12
+ =begin
13
+ = VisualuRuby(tmp) modules for DDE
14
+ This file provides modules for DDE conversation.
15
+ <<< handlers.rd
16
+ =end
17
+
18
+
19
+ # DDE_ADVISE not tested.
20
+
21
+ VR_DIR="vr/" unless defined?(::VR_DIR)
22
+ require VR_DIR+'vruby'
23
+ require VR_DIR+'sysmod'
24
+
25
+ module DDElParam
26
+ PackDDElParam=Win32API.new("user32","PackDDElParam",["I","I","I"],"L")
27
+ UnpackDDElParam=Win32API.new("user32","UnpackDDElParam",["I","L","P","P"],"I")
28
+ FreeDDElParam=Win32API.new("user32","FreeDDElParam",["I","L"],"I")
29
+ ReuseDDElParam=Win32API.new("user32","ReuseDDElParam","IIIII","L")
30
+
31
+ def packDDElParam(msg,low,high)
32
+ PackDDElParam.call(msg,low,high)
33
+ end
34
+ def unpackDDElParam(msg,lparam)
35
+ a=" "; b=" "
36
+ UnpackDDElParam.call(msg,lparam,a,b)
37
+ [a.unpack("I")[0],b.unpack("I")[0]]
38
+ end
39
+
40
+ def freeDDElParam(msg,lparam)
41
+ FreeDDElParam.call(msg,lparam)
42
+ end
43
+
44
+ def reuseDDElParam(lParam, uMsgIn, uMsgOut, uLow, uHigh) #by yukimi_sake
45
+ ReuseDDElParam.call(lParam, uMsgIn, uMsgOut, uLow, uHigh)
46
+ end
47
+ end
48
+
49
+ module VRDdeConversation
50
+ =begin
51
+ == VRDdeConversation
52
+ Utilities for DDE conversation.
53
+
54
+ === Methods
55
+ --- sendDDEAck(shwnd,aItem,retcode=0,ack=true,busy=false)
56
+ Sends DDE_ACK message to shwnd.
57
+
58
+ == VRDdeConversation::DDEAckFlags
59
+ This is a capsule of return code,ack flag, busy flag for DDE_ACK message
60
+ === Attributes
61
+ --- retcode
62
+ 8bit value.
63
+ --- ack
64
+ DDE request is accepted or not.
65
+ --- busy
66
+ busy or not.
67
+ =end
68
+
69
+ WM_DDE_INITIATE = 0x3e0
70
+ WM_DDE_TERMINATE= 0x3e1
71
+ WM_DDE_ADVISE = 0x3e2
72
+ WM_DDE_UNADVISE = 0x3e3
73
+ WM_DDE_ACK = 0x3e4
74
+ WM_DDE_DATA = 0x3e5
75
+ WM_DDE_REQUEST = 0x3e6
76
+ WM_DDE_POKE = 0x3e7
77
+ WM_DDE_EXECUTE = 0x3e8
78
+
79
+ class DDEAckFlags
80
+ # attr_accessor :ack
81
+ # attr_accessor :busy
82
+ # attr_accessor :retcode
83
+ def ack() @_vr_ack; end
84
+ def busy() @_vr_busy; end
85
+ def retcode() @_vr_retcode; end
86
+
87
+ def initialize(ack=true,busy=false,retcode=0)
88
+ @_vr_ack,@_vr_busy,@_vr_retcode = ack,busy,retcode
89
+ end
90
+ end
91
+
92
+ def sendDDEAck(shwnd,aItem,retcode=0,ack=true,busy=false)
93
+ r = retcode & 0xff
94
+ r |= 0x8000 if ack
95
+ r |= 0x4000 if busy
96
+ lparam = packDDElParam(WM_DDE_ACK,r,aItem)
97
+ SMSG::PostMessage.call shwnd,WM_DDE_ACK, self.hWnd,lparam
98
+ end
99
+ end
100
+
101
+ module VRDdeServer
102
+ =begin
103
+ == VRDdeServer
104
+ This module prepares fundamental functions for DDE server.
105
+
106
+ === Methods
107
+ --- addDDEAppTopic(appname,topic)
108
+ Adds acceptable pair of application name and topic for DDE.
109
+ --- delDDEAppTopic(appname,topic)
110
+ Deletes acceptable pair of application name and topic.
111
+
112
+ === Event handlers
113
+ --- ????_ddeinitiate(shwnd,appname,topic)
114
+ Fired when DDE client whose hwnd is ((|shwnd|)) connects the
115
+ DDE server.
116
+ --- ???_ddeterminate(shwnd)
117
+ Fred when DDE client whose hwnd is ((|shwnd|)) disconnects.
118
+ =end
119
+
120
+ include VRMessageHandler
121
+ include VRDdeConversation
122
+ include DDElParam
123
+
124
+ def ddeserverinit
125
+ acceptEvents([WM_DDE_INITIATE,WM_DDE_TERMINATE])
126
+ addHandler WM_DDE_INITIATE,"_ddeInitiate",MSGTYPE::ARGINTINTINT,nil
127
+ addHandler WM_DDE_TERMINATE,"_ddeTerminate",MSGTYPE::ARGWINT,nil
128
+ @_vr_clients={} #{client's hwnd=>[client's hwnd,appname,topic]
129
+ @_vr_ddeacceptable=[] # [appname,topic]
130
+ end
131
+ def vrinit
132
+ super
133
+ ddeserverinit
134
+ end
135
+
136
+ def self__ddeInitiate(shwnd,aApp,aTopic)
137
+ p=[GAtom::GetName(aApp),GAtom::GetName(aTopic)]
138
+ return unless @_vr_ddeacceptable.index(p)
139
+
140
+ @_vr_clients[shwnd] = [shwnd] + p
141
+ r=nil
142
+ r=selfmsg_dispatching("ddeinitiate",shwnd,p[0],p[1])
143
+ SMSG::SendMessage.call shwnd,WM_DDE_ACK,self.hWnd,MAKELPARAM(aApp,aTopic)
144
+ end
145
+
146
+ def self__ddeTerminate(shwnd)
147
+ selfmsg_dispatching("ddeterminate",shwnd)
148
+ SMSG::PostMessage.call shwnd,WM_DDE_TERMINATE,self.hWnd,0
149
+ @_vr_clients.delete(shwnd)
150
+ end
151
+
152
+ def addDDEAppTopic(appname,topic)
153
+ @_vr_ddeacceptable.push([appname,topic])
154
+ end
155
+ def delDDEAppTopic(appname,topic)
156
+ @_vr_ddeacceptable.delete([appname,topic])
157
+ end
158
+
159
+ def self_ddeinitiate(*args) end
160
+ def self_ddeterminate(*arg) end
161
+ end
162
+
163
+ module VRDdeExecuteServer
164
+ =begin
165
+ == VRDdeExecuteServer
166
+ This module provides a feature of DDE_Execute server.
167
+ ((<VRDdeServer>)) is included.
168
+
169
+ === Event handler
170
+ --- self_ddeexecute(command,shwnd,appname,topic)
171
+ Fired when the client whose name is ((|shwnd|)) sends DDE_EXECUTE
172
+ to the server.The command string is ((|command|)).
173
+ If the return value is a kind of VRDdeConversation::((<DDEAckFlags>)),
174
+ DDE_ACK message that will be sent is according to this return value.
175
+ =end
176
+
177
+ include VRDdeServer
178
+
179
+ EXECUTEMETHOD="ddeexecute"
180
+
181
+ def ddeexecuteserverinit
182
+ addEvent WM_DDE_EXECUTE
183
+ addHandler WM_DDE_EXECUTE,"_ddeexecuteinternal",MSGTYPE::ARGINTINT,nil
184
+ end
185
+ def vrinit
186
+ super
187
+ ddeexecuteserverinit
188
+ end
189
+
190
+ def self__ddeexecuteinternal(shwnd,hcmd)
191
+ cl=@_vr_clients[shwnd]
192
+ raise "unknown dde client (not initiated)" unless cl
193
+ cmd=GMEM::Get(hcmd).unpack("A*")[0]
194
+ ret=nil
195
+ ret=selfmsg_dispatching(EXECUTEMETHOD,cmd,*cl)
196
+ freeDDElParam(WM_DDE_EXECUTE,hcmd) #by yukimi_sake
197
+ if ret.is_a?(DDEAckFlags) then
198
+ sendDDEAck shwnd,hcmd,(ret.retcode || 0),ret.ack,ret.busy
199
+ else
200
+ sendDDEAck shwnd,hcmd
201
+ end
202
+ end
203
+ end
204
+
205
+ module VRDdeRequestServer #by yukimi_sake
206
+ =begin
207
+ == VRDdeRequestServer
208
+ This module provides a feature of DDE_REQUEST server.
209
+ ((<VRDdeServer>)) is included.
210
+
211
+ === Event handler
212
+ --- self_dderequest(item,shwnd,app,topic)
213
+ Fired when the client whose name is ((|shwnd|)) sends DDE_REQUEST
214
+ to the server.The item string is ((|item|)).
215
+ Retuern value(as String) is sended to shwnd which is handle of client,
216
+ using WM_DDE_DATA message.
217
+ If the return value is a kind of VRDdeConversation::((<DDEAckFlags>)),
218
+ DDE_ACK message that will be sent is according to this return value.
219
+ =end
220
+
221
+ include VRDdeServer
222
+
223
+ EXECUTEMETHOD="dderequest"
224
+ GMEM_DDESHARE=0x2000
225
+
226
+ def sendDDEData(shwnd,lp,data)
227
+ raise "Data must be a String" unless data.is_a? String
228
+ dDEDATA=[0xb000,ClipboardFormat::CF_TEXT,data+"\0"].pack("Ssa*")
229
+ hData=GMEM::AllocStr(GMEM_DDESHARE,dDEDATA)
230
+ lParam=reuseDDElParam lp,WM_DDE_REQUEST,WM_DDE_DATA,hData,HIWORD(lp)
231
+ SMSG::PostMessage.call shwnd, WM_DDE_DATA, self.hWnd, lParam
232
+ end
233
+
234
+ def dderequestserverinit
235
+ addEvent WM_DDE_REQUEST
236
+ addHandler WM_DDE_REQUEST,"_dderequestinternal",MSGTYPE::ARGINTINT,nil
237
+ end
238
+
239
+ def vrinit
240
+ super
241
+ dderequestserverinit
242
+ end
243
+
244
+ def self__dderequestinternal(shwnd,lparam)
245
+ cl=@_vr_clients[shwnd]
246
+ raise "unknown dde client (not initiated)" unless cl
247
+ cformat,aitem = unpackDDElParam(WM_DDE_REQUEST,lparam)
248
+ raise "not supported this format" unless cformat == 1
249
+ item = GAtom::GetName(aitem)
250
+ ret=nil
251
+ ret=selfmsg_dispatching(EXECUTEMETHOD,item,*cl)
252
+ if ret.is_a?(DDEAckFlags) then
253
+ freeDDElParam(WM_DDE_REQEST,lparam)
254
+ sendDDEAck shwnd,aitem,(ret.retcode || 0),ret.ack,ret.busy
255
+ else
256
+ sendDDEData shwnd,lparam,ret
257
+ end
258
+ end
259
+ def self_dderequest(item,shwnd,app,topic) end
260
+ end
261
+
262
+ module VRDdePokeServer #by yukimi_sake
263
+ =begin
264
+ == VRDdePokeServer
265
+ This module provides a feature of DDE_POKE server.
266
+ ((<VRDdeServer>)) is included.
267
+
268
+ === Event handler
269
+ --- self_ddepoke(item,data,cfmt,shwnd,app,topic)
270
+ Fired when the client whose name is ((|shwnd|)) sends DDE_POKE
271
+ to the server.The item string is ((|item|)).The data is ((|data|)).
272
+ If you want to treat data other than String, carry out according to
273
+ clipboard format ((|cfmt|)) in the handler.
274
+ If the return value is a kind of VRDdeConversation::((<DDEAckFlags>)),
275
+ DDE_ACK message that will be sent is according to this return value.
276
+ =end
277
+ include VRDdeServer
278
+
279
+ EXECUTEMETHOD="ddepoke"
280
+
281
+ def ddepokeserverinit
282
+ addEvent WM_DDE_POKE
283
+ addHandler WM_DDE_POKE,"_ddepokeinternal",MSGTYPE::ARGINTINT,nil
284
+ end
285
+
286
+ def vrinit
287
+ super
288
+ ddepokeserverinit
289
+ end
290
+
291
+ def self__ddepokeinternal(shwnd,lparam)
292
+ cl=@_vr_clients[shwnd]
293
+ raise "unknown dde client (not initiated)" unless cl
294
+ hdata,aitem = unpackDDElParam(WM_DDE_POKE,lparam)
295
+ item = GAtom::GetName(aitem)
296
+ datastr = GMEM::Get(hdata)
297
+ flag,cfmt,data = datastr.unpack("SsA*")
298
+ if (flag&0x2000) > 0 then # fRelease is asserted
299
+ GMEM::Free(hdata)
300
+ end
301
+ ret=nil
302
+ ret=selfmsg_dispatching(EXECUTEMETHOD,item,data,cfmt,*cl)
303
+ freeDDElParam(WM_DDE_POKE, lparam)
304
+ if ret.is_a?(DDEAckFlags) then
305
+ sendDDEAck shwnd,aitem,(ret.retcode || 0),ret.ack,ret.busy
306
+ else
307
+ sendDDEAck shwnd,aitem
308
+ end
309
+ end
310
+ def self_ddepoke(item,data,cfmt,shwnd,app,topic) end
311
+ end
312
+
313
+ module VRDdeClient
314
+ =begin
315
+ == VRDdeClient
316
+ This module provides features of DDE clients.
317
+
318
+ === Methods
319
+ --- ddeconnected?
320
+ --- ddeready?
321
+ Returns whether it is able to request dde conversation.
322
+ --- ddebusy?
323
+ Returns true when it waits DDE_ACK/DDE_DATA message.
324
+
325
+ --- ddeexecute(appname,topic.command)
326
+ Sends DDE_EXECUTE request to the server specified by the pair of (appname,topic).
327
+ --- ddepoke(appname,topic,item,data,fmt)
328
+ Sends DDE_POKE request to the server specified by the pair of (appname,topic).
329
+ The ((|data|)) in the format of ((|fmt|)) (1 as CF_TEXT and so on) is transferred
330
+ tothe ((|item|)) in the server
331
+ --- dderequest(appname,topic,item,fmt)
332
+ Sends DDE_REQUEST request to the server specified by the pair of (appname,topic).
333
+ The server calls back ((<self_dderequestdata>)) method of client window to
334
+ transfer the data of ((|item|)).
335
+ --- ddeadvise(appname,topic,item,fmt)
336
+ --- ddeunadvise(appname,topic,item,fmt)
337
+ Not tested.
338
+
339
+ === Event handlers
340
+ ???? is the downcase-ed appname of the DDE conversation. It is because the ???? name
341
+ is named by WM_DDE_ACK message's App-name which is created by the server and that
342
+ may be different from the requested appname from client.
343
+
344
+ --- ????_ddeterminate(shwnd)
345
+ Fired when the server disconnects the conversation.
346
+ --- ????_dderefused(retcode,busy)
347
+ Fired when the server refused the connection. The return code is ((|retcode|)) and
348
+ busy flag is ((|busy|)).
349
+ --- ????_ddeexecdone(retcode)
350
+ Fired when the server accepts the DDE_EXECUTE request.
351
+ --- ????_ddepokedone(retcode)
352
+ Fired when the server accepts the DDE_POKE request.
353
+ --- ????_ddedata(data,fmt,flag)
354
+ Fired when the server returns the data by the DDE_REQUEST that client sended.
355
+ If the return value is a kind of VRDdeConversation::((<DDEAckFlags>)),
356
+ DDE_ACK message that will be sent is according to this return value.
357
+ --- ????_ddeadvisedata(data,fmt,flag)
358
+ Not tested.
359
+ =end
360
+
361
+ include VRMessageHandler
362
+ include VRDdeConversation
363
+ include DDElParam
364
+
365
+ private
366
+ STATUSCONNECT= 1
367
+ STATUSEXECUTE= 2
368
+ STATUSPOKE = 4
369
+ STATUSREQUEST= 8
370
+ STATUSADVISE = 16
371
+ STATUSTERMINATE=128
372
+ GMEMSTYLE = 0x2042
373
+
374
+
375
+ def ddeconnect(appname,topic)
376
+ raise "DDE_INITIATE busy!" if @_vr_ddesearching
377
+ raise "Application name must be specified" unless appname
378
+ aApp = GAtom::Add(appname)
379
+ aTopic = if topic then GAtom::Add(topic) else 0 end
380
+
381
+ srv = @_vr_servers.find do |key,item| item[1]==appname end
382
+
383
+ shwnd = if srv then srv[0] else 0xffffffff end
384
+ @_vr_ddesearching=nil
385
+ SMSG::SendMessage.call shwnd,WM_DDE_INITIATE,self.hWnd,MAKELPARAM(aApp,aTopic)
386
+ shwnd = @_vr_ddesearching unless srv
387
+ @_vr_ddesearching=nil
388
+
389
+ GAtom::Delete(aApp)
390
+ GAtom::Delete(aTopic) if topic!=0
391
+ raise "DDE Server (#{appname}:#{topic}) not found" unless shwnd
392
+ shwnd
393
+ end
394
+
395
+ def ddeterminate(shwnd)
396
+ SMSG::PostMessage.call shwnd,WM_DDE_TERMINATE,self.hWnd,0
397
+ @_vr_servers[shwnd][2]|=STATUSTERMINATE
398
+ # @_vr_servers.delete(shwnd)
399
+ end
400
+
401
+ public
402
+ def vrinit
403
+ super
404
+ ddeclientinit
405
+ end
406
+
407
+ def ddeclientinit
408
+ acceptEvents([WM_DDE_ACK,WM_DDE_DATA,WM_DDE_TERMINATE])
409
+ addHandler WM_DDE_ACK, "ddeAck", MSGTYPE::ARGINTINT,nil
410
+ addHandler WM_DDE_DATA,"ddeData",MSGTYPE::ARGINTINT,nil
411
+ addHandler WM_DDE_TERMINATE,"ddeTerminate",MSGTYPE::ARGWINT,nil
412
+ @_vr_servers={} # {server's hwnd => [server's hwnd,appname,status,params]}
413
+ @_vr_ddesearching = false
414
+ end
415
+
416
+ def ddeconnected?(appname)
417
+ srv = @_vr_servers.find do |key,item| item[1].downcase==appname.downcase end
418
+ if srv then srv=srv[1];((srv[2]&STATUSCONNECT)>0) else false end
419
+ end
420
+ def ddebusy?(appname)
421
+ srv = @_vr_servers.find do |key,item| item[1].downcase==appname.downcase end
422
+ if srv then srv=srv[1]; ((srv[2] & ~STATUSCONNECT)>0) else nil end
423
+ end
424
+ def ddeidle?(appname)
425
+ srv = @_vr_servers.find do |key,item| item[1].downcase==appname.downcase end
426
+ if srv then
427
+ srv=srv[1]
428
+ ((srv[2]&STATUSCONNECT)>0) and ((srv[2] & ~STATUSCONNECT)==0)
429
+ else
430
+ true
431
+ end
432
+ end
433
+ def ddeready?(appname)
434
+ srv = @_vr_servers.find do |key,item| item[1].downcase==appname.downcase end
435
+ if srv then
436
+ srv=srv[1]
437
+ ((srv[2]&STATUSCONNECT)>0) and
438
+ ((srv[2] & ~(STATUSCONNECT | STATUSADVISE))==0)
439
+ else
440
+ true
441
+ end
442
+ end
443
+
444
+ def ddeexecute(appname,topic,cmdstr)
445
+ raise "dde(#{appname}:#{topic}) not ready" unless ddeready?(appname)
446
+ shwnd=ddeconnect(appname,topic)
447
+ executemem = GMEM::AllocStr(GMEMSTYLE,cmdstr)
448
+ @_vr_servers[shwnd][2] |= STATUSEXECUTE
449
+ SMSG::PostMessage.call shwnd,WM_DDE_EXECUTE,self.hWnd,executemem
450
+ end
451
+
452
+ def ddepoke(appname,topic,item,data,fmt=ClipboardFormat::CF_TEXT)
453
+ raise "dde(#{appname}:#{topic}) not ready" unless ddeready?(appname)
454
+ shwnd=ddeconnect(appname,topic)
455
+
456
+ aItem = GAtom::Add(item.to_s)
457
+
458
+ pokedata=[0,fmt].pack("Ss")+data.to_s
459
+ pokemem = GMEM::AllocStr(GMEMSTYLE,pokedata)
460
+
461
+ @_vr_servers[shwnd][2] |= STATUSPOKE
462
+ @_vr_servers[shwnd][3] = pokemem
463
+
464
+ lparam = packDDElParam(WM_DDE_POKE,pokemem,aItem)
465
+ SMSG::PostMessage.call shwnd,WM_DDE_POKE,self.hWnd,lparam
466
+ end
467
+
468
+ def dderequest(appname,topic,item,fmt=ClipboardFormat::CF_TEXT)
469
+ raise "dde(#{appname}:#{topic}) not ready" unless ddeready?(appname)
470
+ shwnd=ddeconnect(appname,topic)
471
+
472
+ aItem = GAtom::Add(item.to_s)
473
+
474
+ @_vr_servers[shwnd][2] |= STATUSREQUEST
475
+ SMSG::PostMessage.call shwnd,WM_DDE_REQUEST,self.hWnd,
476
+ MAKELPARAM(fmt.to_i,aItem)
477
+ end
478
+
479
+ def ddeadvise(appname,topic,item,fmt=1,defup=false,ackreq=false)
480
+ raise "dde(#{appname}:#{topic}) not ready" unless ddeready?(appname)
481
+ shwnd=ddeconnect(appname,topic)
482
+
483
+ aItem = GAtom::Add(item.to_s)
484
+
485
+ flag = 0
486
+ if defup then flag |= 0x4000 end
487
+ if ackreq then flag |= 0x8000 end
488
+
489
+ advisedata=[flag,fmt].pack("Ss")
490
+ advisemem = GMEM::AllocStr(GMEMSTYLE,advisedata)
491
+
492
+ @_vr_servers[shwnd][2] |= STATUSADVISE
493
+ lparam = packDDElParam(WM_DDE_POKE,advisemem,aItem)
494
+ SMSG::PostMessage.call shwnd,WM_DDE_ADVISE,self.hWnd,lparam
495
+ end
496
+
497
+ def ddeunadvise(appname,topic,item,fmt=0)
498
+ raise "dde(#{appname}:#{topic}) not ready" unless ddeready?(appname)
499
+ shwnd=ddeconnect(appname,topic)
500
+
501
+ aItem = GAtom::Add(item.to_s)
502
+
503
+ @_vr_servers[n][2] |= STATUSREQUEST
504
+ SMSG::PostMessage.call @_vr_servers[n][0],WM_DDE_UNADVISE,self.hWnd,
505
+ MAKELPARAM(fmt.to_i,aItem)
506
+ end
507
+
508
+
509
+ def self_ddeTerminate(shwnd)
510
+ controlmsg_dispatching(@_vr_servers[shwnd][1],"ddeterminate")
511
+ # fname=@_vr_servers[shwnd][1] + "_ddeterminate"
512
+ # send(fname,shwnd) if respond_to?(fname)
513
+ @_vr_servers.delete(shwnd)
514
+ end
515
+
516
+ def self_ddeAck(shwnd,lparam)
517
+ #p "ACK"
518
+ sv = @_vr_servers[shwnd]
519
+ fname=""
520
+ if(!sv) then
521
+ aApp,aTopic = LOWORD(lparam),HIWORD(lparam)
522
+ appname=GAtom::GetName(aApp).downcase
523
+ tpcname=GAtom::GetName(aTopic)
524
+ appname2=appname.dup
525
+ def appname2.name() self; end # tricky thing for parentrelayer
526
+ @_vr_servers[shwnd]=[shwnd,appname2,STATUSCONNECT,nil]
527
+
528
+ @_vr_ddesearching=shwnd
529
+
530
+ GAtom::Delete(aApp)
531
+ GAtom::Delete(aTopic)
532
+
533
+ elsif (sv[2] & ~STATUSCONNECT)>0 then
534
+ wstatus,param = unpackDDElParam(WM_DDE_ACK,lparam)
535
+ freeDDElParam(WM_DDE_ACK,lparam)
536
+
537
+ retcode = wstatus&0xf
538
+ busy= 0<(wstatus&0x4000)
539
+ ack = 0<(wstatus&0x8000)
540
+ sname = sv[1]
541
+
542
+ unless ack then
543
+ sv[2] &= STATUSCONNECT
544
+ # fname=sname+"_dderefused"
545
+ # send(fname,retcode,busy) if respond_to?(fname)
546
+ controlmsg_dispatching(sname,"dderefused",retcode,busy)
547
+ end
548
+ if (sv[2] & STATUSEXECUTE)>0 then
549
+ GMEM::Free(param) unless ack
550
+ sv[2] &= ~STATUSEXECUTE
551
+ fname="ddeexecdone"
552
+ ddeterminate(shwnd)
553
+ elsif(sv[2] & STATUSPOKE)>0 then
554
+ GAtom::Delete(param)
555
+ GMEM::Free(sv[3])
556
+ sv[3]=nil
557
+ sv[2] &= ~STATUSPOKE
558
+ fname="ddepokedone"
559
+ ddeterminate(shwnd)
560
+ elsif(sv[2] & STATUSREQUEST)>0 then
561
+ GAtom::Delete(param)
562
+ sv[2] &= ~STATUSPOKE
563
+ fname=nil
564
+ ddeterminate(shwnd)
565
+ elsif(sv[2] & STATUSADVISE)>0 then
566
+ GMEM::Free(param) unless ack
567
+ sv[2] &= ~STATUSADVISE
568
+ fname=nil
569
+ else
570
+ ddeterminate(shwnd)
571
+ end
572
+ controlmsg_dispatching(sname,fname,retcode) if ack and fname
573
+ else
574
+ raise "DDE MultiSession Error"
575
+ end
576
+ end
577
+
578
+ def self_ddeData(shwnd,lparam)
579
+ #p "DATA"
580
+ datamem,aItem = unpackDDElParam(WM_DDE_DATA,lparam)
581
+ freeDDElParam(WM_DDE_DATA,lparam)
582
+
583
+ sv = @_vr_servers[shwnd]
584
+ fname=sname=nil
585
+
586
+ datastr = GMEM::Get(datamem)
587
+ flag,fmt,data = datastr.unpack("Ssa*")
588
+
589
+ if (flag&0x2000) > 0 then # fRelease is asserted
590
+ GMEM::Free(datamem)
591
+ end
592
+
593
+ ret = nil
594
+ if(!sv) then
595
+ # Ignored
596
+ else
597
+ sname=sv[1]
598
+ if (sv[2] & STATUSREQUEST)>0 then
599
+ sv[2]&=1
600
+ fname="ddedata"
601
+ ddeterminate(sv[0])
602
+ elsif (sv[2] & STATUSADVISE)>0
603
+ sv[2]&=1
604
+ fname="ddeadvisedata"
605
+ else
606
+ end
607
+
608
+ fn=sname+fname
609
+ if(fn) then
610
+ ret=controlmsg_dispatching(sname,fname,data,fmt,flag)
611
+ end
612
+ end
613
+
614
+ if (flag&0x8000) > 0 then #fAckReq is asserted
615
+ if ret.is_a?(DDEAckFlags) then
616
+ sendDDEAck shwnd,aItem,(ret.retcode || 0),ret.ack,ret.busy
617
+ else
618
+ sendDDEAck shwnd,aItem
619
+ end
620
+ else
621
+ GAtom::Delete(aItem)
622
+ end
623
+
624
+ end
625
+ end