vruby 2004.08.07

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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