fzeet 0.6.4 → 0.6.5

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,1135 @@
1
+ require_relative 'ole'
2
+
3
+ module Fzeet
4
+ module Windows
5
+ ffi_lib 'mshtml'
6
+ ffi_convention :stdcall
7
+
8
+ IHTMLDocument = COM::Interface[IDispatch,
9
+ GUID['626FC520-A41E-11cf-A731-00A0C9082637'],
10
+
11
+ get_Script: [[:pointer], :long]
12
+ ]
13
+
14
+ HTMLDocument = COM::Instance[IHTMLDocument]
15
+
16
+ IHTMLDocument2 = COM::Interface[IHTMLDocument,
17
+ GUID['332c4425-26cb-11d0-b483-00c04fd90119'],
18
+
19
+ get_all: [[:pointer], :long],
20
+ get_body: [[:pointer], :long],
21
+ get_activeElement: [[:pointer], :long],
22
+ get_images: [[:pointer], :long],
23
+ get_applets: [[:pointer], :long],
24
+ get_links: [[:pointer], :long],
25
+ get_forms: [[:pointer], :long],
26
+ get_anchors: [[:pointer], :long],
27
+ put_title: [[:pointer], :long],
28
+ get_title: [[:pointer], :long],
29
+ get_scripts: [[:pointer], :long],
30
+ put_designMode: [[:pointer], :long],
31
+ get_designMode: [[:pointer], :long],
32
+ get_selection: [[:pointer], :long],
33
+ get_readyState: [[:pointer], :long],
34
+ get_frames: [[:pointer], :long],
35
+ get_embeds: [[:pointer], :long],
36
+ get_plugins: [[:pointer], :long],
37
+ put_alinkColor: [[VARIANT], :long],
38
+ get_alinkColor: [[:pointer], :long],
39
+ put_bgColor: [[VARIANT], :long],
40
+ get_bgColor: [[:pointer], :long],
41
+ put_fgColor: [[VARIANT], :long],
42
+ get_fgColor: [[:pointer], :long],
43
+ put_linkColor: [[VARIANT], :long],
44
+ get_linkColor: [[:pointer], :long],
45
+ put_vlinkColor: [[VARIANT], :long],
46
+ get_vlinkColor: [[:pointer], :long],
47
+ get_referrer: [[:pointer], :long],
48
+ get_location: [[:pointer], :long],
49
+ get_lastModified: [[:pointer], :long],
50
+ put_URL: [[:pointer], :long],
51
+ get_URL: [[:pointer], :long],
52
+ put_domain: [[:pointer], :long],
53
+ get_domain: [[:pointer], :long],
54
+ put_cookie: [[:pointer], :long],
55
+ get_cookie: [[:pointer], :long],
56
+ put_expando: [[:short], :long],
57
+ get_expando: [[:pointer], :long],
58
+ put_charset: [[:pointer], :long],
59
+ get_charset: [[:pointer], :long],
60
+ put_defaultCharset: [[:pointer], :long],
61
+ get_defaultCharset: [[:pointer], :long],
62
+ get_mimeType: [[:pointer], :long],
63
+ get_fileSize: [[:pointer], :long],
64
+ get_fileCreatedDate: [[:pointer], :long],
65
+ get_fileModifiedDate: [[:pointer], :long],
66
+ get_fileUpdatedDate: [[:pointer], :long],
67
+ get_security: [[:pointer], :long],
68
+ get_protocol: [[:pointer], :long],
69
+ get_nameProp: [[:pointer], :long],
70
+ write: [[:pointer], :long],
71
+ writeln: [[:pointer], :long],
72
+ open: [[:pointer, VARIANT, VARIANT, VARIANT, :pointer], :long],
73
+ close: [[], :long],
74
+ clear: [[], :long],
75
+ queryCommandSupported: [[:pointer, :pointer], :long],
76
+ queryCommandEnabled: [[:pointer, :pointer], :long],
77
+ queryCommandState: [[:pointer, :pointer], :long],
78
+ queryCommandIndeterm: [[:pointer, :pointer], :long],
79
+ queryCommandText: [[:pointer, :pointer], :long],
80
+ queryCommandValue: [[:pointer, :pointer], :long],
81
+ execCommand: [[:pointer, :short, VARIANT, :pointer], :long],
82
+ execCommandShowHelp: [[:pointer, :pointer], :long],
83
+ createElement: [[:pointer, :pointer], :long],
84
+ put_onhelp: [[VARIANT], :long],
85
+ get_onhelp: [[:pointer], :long],
86
+ put_onclick: [[VARIANT], :long],
87
+ get_onclick: [[:pointer], :long],
88
+ put_ondblclick: [[VARIANT], :long],
89
+ get_ondblclick: [[:pointer], :long],
90
+ put_onkeyup: [[VARIANT], :long],
91
+ get_onkeyup: [[:pointer], :long],
92
+ put_onkeydown: [[VARIANT], :long],
93
+ get_onkeydown: [[:pointer], :long],
94
+ put_onkeypress: [[VARIANT], :long],
95
+ get_onkeypress: [[:pointer], :long],
96
+ put_onmouseup: [[VARIANT], :long],
97
+ get_onmouseup: [[:pointer], :long],
98
+ put_onmousedown: [[VARIANT], :long],
99
+ get_onmousedown: [[:pointer], :long],
100
+ put_onmousemove: [[VARIANT], :long],
101
+ get_onmousemove: [[:pointer], :long],
102
+ put_onmouseout: [[VARIANT], :long],
103
+ get_onmouseout: [[:pointer], :long],
104
+ put_onmouseover: [[VARIANT], :long],
105
+ get_onmouseover: [[:pointer], :long],
106
+ put_onreadystatechange: [[VARIANT], :long],
107
+ get_onreadystatechange: [[:pointer], :long],
108
+ put_onafterupdate: [[VARIANT], :long],
109
+ get_onafterupdate: [[:pointer], :long],
110
+ put_onrowexit: [[VARIANT], :long],
111
+ get_onrowexit: [[:pointer], :long],
112
+ put_onrowenter: [[VARIANT], :long],
113
+ get_onrowenter: [[:pointer], :long],
114
+ put_ondragstart: [[VARIANT], :long],
115
+ get_ondragstart: [[:pointer], :long],
116
+ put_onselectstart: [[VARIANT], :long],
117
+ get_onselectstart: [[:pointer], :long],
118
+ elementFromPoint: [[:long, :long, :pointer], :long],
119
+ get_parentWindow: [[:pointer], :long],
120
+ get_styleSheets: [[:pointer], :long],
121
+ put_onbeforeupdate: [[VARIANT], :long],
122
+ get_onbeforeupdate: [[:pointer], :long],
123
+ put_onerrorupdate: [[VARIANT], :long],
124
+ get_onerrorupdate: [[:pointer], :long],
125
+ toString: [[:pointer], :long],
126
+ createStyleSheet: [[:pointer, :long, :pointer], :long]
127
+ ]
128
+
129
+ HTMLDocument2 = COM::Instance[IHTMLDocument2]
130
+
131
+ class HTMLDocument2
132
+ attr_reader :handlers
133
+
134
+ def on(event, &block)
135
+ _event, _block = if event == :ready
136
+ [:readystatechange, -> *args { next unless readyState == 'complete'; block.(*args) }]
137
+ else
138
+ [event, block]
139
+ end
140
+
141
+ ((@handlers ||= {})[_event] ||= []) << _block
142
+ @dcallbacks ||= []
143
+
144
+ send("put_on#{_event}", VARIANT.new.tap { |v|
145
+ v[:vt] = VT_DISPATCH
146
+
147
+ v[:pdispVal] = @dcallbacks.push(DCallback.new.tap { |dcb|
148
+ dcb.instance_variable_set(:@document, self)
149
+ dcb.instance_variable_set(:@event, _event)
150
+
151
+ def dcb.Invoke(*args)
152
+ @document.handlers[@event].each { |handler|
153
+ (handler.arity == 0) ? handler.call : handler.call(*args)
154
+ }
155
+
156
+ S_OK
157
+ end
158
+ }).last
159
+ })
160
+
161
+ self
162
+ end
163
+
164
+ def parentWindow
165
+ FFI::MemoryPointer.new(:pointer) { |pwindow|
166
+ get_parentWindow(pwindow)
167
+
168
+ return HTMLWindow2.new(pwindow.read_pointer)
169
+ }
170
+ end
171
+
172
+ alias window parentWindow
173
+
174
+ def request?; Windows.CoInternetIsFeatureEnabled(FEATURE_XMLHTTP, GET_FEATURE_FROM_PROCESS) == S_OK end
175
+ def request=(enabled) Windows.DetonateHresult(:CoInternetSetFeatureEnabled, FEATURE_XMLHTTP, SET_FEATURE_ON_PROCESS, (enabled) ? 1 : 0) end
176
+
177
+ def request
178
+ disp = nil
179
+
180
+ window.QueryInstance(HTMLWindow5) { |htmlwindow5|
181
+ disp = Dispatch.new(VARIANT.new.tap { |v| htmlwindow5.get_XMLHttpRequest(v) }[:pdispVal])
182
+
183
+ disp.QueryInstance(HTMLXMLHttpRequestFactory) { |factory|
184
+ FFI::MemoryPointer.new(:pointer) { |prequest|
185
+ factory.create(prequest)
186
+
187
+ return HTMLXMLHttpRequest.new(prequest.read_pointer)
188
+ }
189
+ }
190
+ }
191
+ ensure
192
+ disp.Release if disp
193
+ end
194
+
195
+ def xrequest
196
+ disp = nil
197
+
198
+ window.QueryInstance(HTMLWindow6) { |htmlwindow6|
199
+ disp = Dispatch.new(VARIANT.new.tap { |v| htmlwindow6.get_XDomainRequest(v) }[:pdispVal])
200
+
201
+ disp.QueryInstance(HTMLXDomainRequestFactory) { |factory|
202
+ FFI::MemoryPointer.new(:pointer) { |pxrequest|
203
+ factory.create(pxrequest)
204
+
205
+ return HTMLXDomainRequest.new(pxrequest.read_pointer)
206
+ }
207
+ }
208
+ }
209
+ ensure
210
+ disp.Release if disp
211
+ end
212
+
213
+ def readyState
214
+ FFI::MemoryPointer.new(:pointer) { |pstate|
215
+ get_readyState(pstate)
216
+
217
+ return Windows.WCSTOMBS(pstate.read_pointer)
218
+ }
219
+ end
220
+
221
+ def all
222
+ pdisp = nil
223
+
224
+ FFI::MemoryPointer.new(:pointer) { |pdisp|
225
+ get_all(pdisp)
226
+
227
+ disp = Dispatch.new(pdisp.read_pointer)
228
+
229
+ return disp.QueryInstance(HTMLElementCollection)
230
+ }
231
+ ensure
232
+ pdisp.Release if pdisp
233
+ end
234
+
235
+ alias old_createElement createElement
236
+
237
+ def createElement(tag)
238
+ bstr = nil
239
+
240
+ FFI::MemoryPointer.new(:pointer) { |pelem|
241
+ old_createElement(bstr = Windows.SysAllocString("#{tag}\0".encode('utf-16le')), pelem)
242
+
243
+ return HTMLElement.new(pelem.read_pointer)
244
+ }
245
+ ensure
246
+ Windows.SysFreeString(bstr)
247
+ end
248
+ end
249
+
250
+ IHTMLFramesCollection2 = COM::Interface[IDispatch,
251
+ GUID['332c4426-26cb-11d0-b483-00c04fd90119'],
252
+
253
+ item: [[:pointer, :pointer], :long],
254
+ get_length: [[:pointer], :long]
255
+ ]
256
+
257
+ HTMLFramesCollection2 = COM::Instance[IHTMLFramesCollection2]
258
+
259
+ IHTMLWindow2 = COM::Interface[IHTMLFramesCollection2,
260
+ GUID['332c4427-26cb-11d0-b483-00c04fd90119'],
261
+
262
+ get_frames: [[:pointer], :long],
263
+ put_defaultStatus: [[:pointer], :long],
264
+ get_defaultStatus: [[:pointer], :long],
265
+ put_status: [[:pointer], :long],
266
+ get_status: [[:pointer], :long],
267
+ setTimeout: [[:pointer, :long, :pointer, :pointer], :long],
268
+ clearTimeout: [[:long], :long],
269
+ alert: [[:pointer], :long],
270
+ confirm: [[:pointer, :pointer], :long],
271
+ prompt: [[:pointer, :pointer, :pointer], :long],
272
+ get_Image: [[:pointer], :long],
273
+ get_location: [[:pointer], :long],
274
+ get_history: [[:pointer], :long],
275
+ close: [[], :long],
276
+ put_opener: [[VARIANT], :long],
277
+ get_opener: [[:pointer], :long],
278
+ get_navigator: [[:pointer], :long],
279
+ put_name: [[:pointer], :long],
280
+ get_name: [[:pointer], :long],
281
+ get_parent: [[:pointer], :long],
282
+ open: [[:pointer, :pointer, :pointer, :short, :pointer], :long],
283
+ get_self: [[:pointer], :long],
284
+ get_top: [[:pointer], :long],
285
+ get_window: [[:pointer], :long],
286
+ navigate: [[:pointer], :long],
287
+ put_onfocus: [[VARIANT], :long],
288
+ get_onfocus: [[:pointer], :long],
289
+ put_onblur: [[VARIANT], :long],
290
+ get_onblur: [[:pointer], :long],
291
+ put_onload: [[VARIANT], :long],
292
+ get_onload: [[:pointer], :long],
293
+ put_onbeforeunload: [[VARIANT], :long],
294
+ get_onbeforeunload: [[:pointer], :long],
295
+ put_onunload: [[VARIANT], :long],
296
+ get_onunload: [[:pointer], :long],
297
+ put_onhelp: [[VARIANT], :long],
298
+ get_onhelp: [[:pointer], :long],
299
+ put_onerror: [[VARIANT], :long],
300
+ get_onerror: [[:pointer], :long],
301
+ put_onresize: [[VARIANT], :long],
302
+ get_onresize: [[:pointer], :long],
303
+ put_onscroll: [[VARIANT], :long],
304
+ get_onscroll: [[:pointer], :long],
305
+ get_document: [[:pointer], :long],
306
+ get_event: [[:pointer], :long],
307
+ get__newEnum: [[:pointer], :long],
308
+ showModalDialog: [[:pointer, :pointer, :pointer, :pointer], :long],
309
+ showHelp: [[:pointer, VARIANT, :pointer], :long],
310
+ get_screen: [[:pointer], :long],
311
+ get_Option: [[:pointer], :long],
312
+ focus: [[], :long],
313
+ get_closed: [[:pointer], :long],
314
+ blur: [[], :long],
315
+ scroll: [[:long, :long], :long],
316
+ get_clientInformation: [[:pointer], :long],
317
+ setInterval: [[:pointer, :long, :pointer, :pointer], :long],
318
+ clearInterval: [[:long], :long],
319
+ put_offscreenBuffering: [[VARIANT], :long],
320
+ get_offscreenBuffering: [[:pointer], :long],
321
+ execScript: [[:pointer, :pointer, :pointer], :long],
322
+ toString: [[:pointer], :long],
323
+ scrollBy: [[:long, :long], :long],
324
+ scrollTo: [[:long, :long], :long],
325
+ moveTo: [[:long, :long], :long],
326
+ moveBy: [[:long, :long], :long],
327
+ resizeTo: [[:long, :long], :long],
328
+ resizeBy: [[:long, :long], :long],
329
+ get_external: [[:pointer], :long]
330
+ ]
331
+
332
+ HTMLWindow2 = COM::Instance[IHTMLWindow2]
333
+
334
+ class HTMLWindow2
335
+ attr_reader :handlers
336
+
337
+ def on(event, &block)
338
+ ((@handlers ||= {})[event] ||= []) << block
339
+ @dcallbacks ||= []
340
+
341
+ send("put_on#{event}", VARIANT.new.tap { |v|
342
+ v[:vt] = VT_DISPATCH
343
+
344
+ v[:pdispVal] = @dcallbacks.push(DCallback.new.tap { |dcb|
345
+ dcb.instance_variable_set(:@window, self)
346
+ dcb.instance_variable_set(:@event, event)
347
+
348
+ def dcb.Invoke(*args)
349
+ @window.handlers[@event].each { |handler|
350
+ (handler.arity == 0) ? handler.call : handler.call(*args)
351
+ }
352
+
353
+ S_OK
354
+ end
355
+ }).last
356
+ })
357
+
358
+ self
359
+ end
360
+ end
361
+
362
+ IHTMLWindow5 = COM::Interface[IDispatch,
363
+ GUID['3051040e-98b5-11cf-bb82-00aa00bdce0b'],
364
+
365
+ put_XMLHttpRequest: [[VARIANT], :long],
366
+ get_XMLHttpRequest: [[:pointer], :long]
367
+ ]
368
+
369
+ HTMLWindow5 = COM::Instance[IHTMLWindow5]
370
+
371
+ IHTMLWindow6 = COM::Interface[IDispatch,
372
+ GUID['30510453-98b5-11cf-bb82-00aa00bdce0b'],
373
+
374
+ put_XDomainRequest: [[VARIANT], :long],
375
+ get_XDomainRequest: [[:pointer], :long],
376
+ get_sessionStorage: [[:pointer], :long],
377
+ get_localStorage: [[:pointer], :long],
378
+ put_onhashchange: [[VARIANT], :long],
379
+ get_onhashchange: [[:pointer], :long],
380
+ get_maxConnectionsPerServer: [[:pointer], :long],
381
+ postMessage: [[:pointer, VARIANT], :long],
382
+ toStaticHTML: [[:pointer, :pointer], :long],
383
+ put_onmessage: [[VARIANT], :long],
384
+ get_onmessage: [[:pointer], :long],
385
+ msWriteProfilerMark: [[:pointer], :long]
386
+ ]
387
+
388
+ HTMLWindow6 = COM::Instance[IHTMLWindow6]
389
+
390
+ class HTMLWindow6
391
+ attr_reader :handlers
392
+
393
+ def on(event, &block)
394
+ ((@handlers ||= {})[event] ||= []) << block
395
+ @dcallbacks ||= []
396
+
397
+ send("put_on#{event}", VARIANT.new.tap { |v|
398
+ v[:vt] = VT_DISPATCH
399
+
400
+ v[:pdispVal] = @dcallbacks.push(DCallback.new.tap { |dcb|
401
+ dcb.instance_variable_set(:@window, self)
402
+ dcb.instance_variable_set(:@event, event)
403
+
404
+ def dcb.Invoke(*args)
405
+ @window.handlers[@event].each { |handler|
406
+ (handler.arity == 0) ? handler.call : handler.call(*args)
407
+ }
408
+
409
+ S_OK
410
+ end
411
+ }).last
412
+ })
413
+
414
+ self
415
+ end
416
+ end
417
+
418
+ IHTMLXMLHttpRequestFactory = COM::Interface[IDispatch,
419
+ GUID['3051040c-98b5-11cf-bb82-00aa00bdce0b'],
420
+
421
+ create: [[:pointer], :long]
422
+ ]
423
+
424
+ HTMLXMLHttpRequestFactory = COM::Instance[IHTMLXMLHttpRequestFactory]
425
+
426
+ IHTMLXMLHttpRequest = COM::Interface[IDispatch,
427
+ GUID['3051040a-98b5-11cf-bb82-00aa00bdce0b'],
428
+
429
+ get_readyState: [[:pointer], :long],
430
+ get_responseBody: [[:pointer], :long],
431
+ get_responseText: [[:pointer], :long],
432
+ get_responseXML: [[:pointer], :long],
433
+ get_status: [[:pointer], :long],
434
+ get_statusText: [[:pointer], :long],
435
+ put_onreadystatechange: [[VARIANT], :long],
436
+ get_onreadystatechange: [[:pointer], :long],
437
+ abort: [[], :long],
438
+ open: [[:pointer, :pointer, VARIANT, VARIANT, VARIANT], :long],
439
+ send: [[VARIANT], :long],
440
+ getAllResponseHeaders: [[:pointer], :long],
441
+ getResponseHeader: [[:pointer, :pointer], :long],
442
+ setRequestHeader: [[:pointer, :pointer], :long]
443
+ ]
444
+
445
+ HTMLXMLHttpRequest = COM::Instance[IHTMLXMLHttpRequest]
446
+
447
+ class HTMLXMLHttpRequest
448
+ attr_reader :handlers
449
+
450
+ def on(event, &block)
451
+ ((@handlers ||= {})[event] ||= []) << block
452
+ @dcallbacks ||= []
453
+
454
+ __send__("put_on#{event}", VARIANT.new.tap { |v|
455
+ v[:vt] = VT_DISPATCH
456
+
457
+ v[:pdispVal] = @dcallbacks.push(DCallback.new.tap { |dcb|
458
+ dcb.instance_variable_set(:@request, self)
459
+ dcb.instance_variable_set(:@event, event)
460
+
461
+ def dcb.Invoke(*args)
462
+ @request.handlers[@event].each { |handler|
463
+ (handler.arity == 0) ? handler.call : handler.call(*args)
464
+ }
465
+
466
+ S_OK
467
+ end
468
+ }).last
469
+ })
470
+
471
+ self
472
+ end
473
+
474
+ %w{readyState status}.each { |name|
475
+ define_method(name) {
476
+ FFI::MemoryPointer.new(:pointer) { |plong|
477
+ __send__("get_#{name}", plong)
478
+
479
+ return plong.read_long
480
+ }
481
+ }
482
+ }
483
+
484
+ %w{statusText responseText}.each { |name|
485
+ define_method(name) {
486
+ ppbstr = FFI::MemoryPointer.new(:pointer)
487
+
488
+ begin
489
+ __send__("get_#{name}", ppbstr)
490
+
491
+ return nil if (pbstr = ppbstr.read_pointer).null?
492
+
493
+ begin
494
+ Windows.WCSTOMBS(pbstr)
495
+ ensure
496
+ Windows.SysFreeString(pbstr)
497
+ end
498
+ ensure
499
+ ppbstr.free
500
+ end
501
+ }
502
+ }
503
+
504
+ alias old_open open
505
+
506
+ def open(url, method = 'get')
507
+ old_open(
508
+ bstr = Windows.SysAllocString("#{method}\0".encode('utf-16le')),
509
+ bstr2 = Windows.SysAllocString("#{url}\0".encode('utf-16le')),
510
+ VARIANT.new.tap { |v| v[:vt] = VT_BOOL; v[:boolVal] = -1 },
511
+ VARIANT.new,
512
+ VARIANT.new
513
+ )
514
+
515
+ self
516
+ ensure
517
+ Windows.SysFreeString(bstr)
518
+ Windows.SysFreeString(bstr2)
519
+ end
520
+ end
521
+
522
+ IHTMLXDomainRequestFactory = COM::Interface[IDispatch,
523
+ GUID['30510456-98b5-11cf-bb82-00aa00bdce0b'],
524
+
525
+ create: [[:pointer], :long]
526
+ ]
527
+
528
+ HTMLXDomainRequestFactory = COM::Instance[IHTMLXDomainRequestFactory]
529
+
530
+ IHTMLXDomainRequest = COM::Interface[IDispatch,
531
+ GUID['30510454-98b5-11cf-bb82-00aa00bdce0b'],
532
+
533
+ get_responseText: [[:pointer], :long],
534
+ put_timeout: [[:long], :long],
535
+ get_timeout: [[:pointer], :long],
536
+ get_contentType: [[:pointer], :long],
537
+ put_onprogress: [[VARIANT], :long],
538
+ get_onprogress: [[:pointer], :long],
539
+ put_onerror: [[VARIANT], :long],
540
+ get_onerror: [[:pointer], :long],
541
+ put_ontimeout: [[VARIANT], :long],
542
+ get_ontimeout: [[:pointer], :long],
543
+ put_onload: [[VARIANT], :long],
544
+ get_onload: [[:pointer], :long],
545
+ abort: [[], :long],
546
+ open: [[:pointer, :pointer], :long],
547
+ send: [[VARIANT], :long]
548
+ ]
549
+
550
+ HTMLXDomainRequest = COM::Instance[IHTMLXDomainRequest]
551
+
552
+ class HTMLXDomainRequest
553
+ attr_reader :handlers
554
+
555
+ def on(event, &block)
556
+ ((@handlers ||= {})[event] ||= []) << block
557
+ @dcallbacks ||= []
558
+
559
+ __send__("put_on#{event}", VARIANT.new.tap { |v|
560
+ v[:vt] = VT_DISPATCH
561
+
562
+ v[:pdispVal] = @dcallbacks.push(DCallback.new.tap { |dcb|
563
+ dcb.instance_variable_set(:@xrequest, self)
564
+ dcb.instance_variable_set(:@event, event)
565
+
566
+ def dcb.Invoke(*args)
567
+ @xrequest.handlers[@event].each { |handler|
568
+ (handler.arity == 0) ? handler.call : handler.call(*args)
569
+ }
570
+
571
+ S_OK
572
+ end
573
+ }).last
574
+ })
575
+
576
+ self
577
+ end
578
+
579
+ %w{responseText}.each { |name|
580
+ define_method(name) {
581
+ ppbstr = FFI::MemoryPointer.new(:pointer)
582
+
583
+ begin
584
+ __send__("get_#{name}", ppbstr)
585
+
586
+ return nil if (pbstr = ppbstr.read_pointer).null?
587
+
588
+ begin
589
+ Windows.WCSTOMBS(pbstr)
590
+ ensure
591
+ Windows.SysFreeString(pbstr)
592
+ end
593
+ ensure
594
+ ppbstr.free
595
+ end
596
+ }
597
+ }
598
+
599
+ alias old_open open
600
+
601
+ def open(url, method = 'get')
602
+ old_open(
603
+ bstr = Windows.SysAllocString("#{method}\0".encode('utf-16le')),
604
+ bstr2 = Windows.SysAllocString("#{url}\0".encode('utf-16le'))
605
+ )
606
+
607
+ self
608
+ ensure
609
+ Windows.SysFreeString(bstr)
610
+ Windows.SysFreeString(bstr2)
611
+ end
612
+ end
613
+
614
+ IHTMLElement = COM::Interface[IDispatch,
615
+ GUID['3050f1ff-98b5-11cf-bb82-00aa00bdce0b'],
616
+
617
+ setAttribute: [[:pointer, VARIANT, :long], :long],
618
+ getAttribute: [[:pointer, :long, :pointer], :long],
619
+ removeAttribute: [[:pointer, :long, :pointer], :long],
620
+ put_className: [[:pointer], :long],
621
+ get_className: [[:pointer], :long],
622
+ put_id: [[:pointer], :long],
623
+ get_id: [[:pointer], :long],
624
+ get_tagName: [[:pointer], :long],
625
+ get_parentElement: [[:pointer], :long],
626
+ get_style: [[:pointer], :long],
627
+ put_onhelp: [[VARIANT], :long],
628
+ get_onhelp: [[:pointer], :long],
629
+ put_onclick: [[VARIANT], :long],
630
+ get_onclick: [[:pointer], :long],
631
+ put_ondblclick: [[VARIANT], :long],
632
+ get_ondblclick: [[:pointer], :long],
633
+ put_onkeydown: [[VARIANT], :long],
634
+ get_onkeydown: [[:pointer], :long],
635
+ put_onkeyup: [[VARIANT], :long],
636
+ get_onkeyup: [[:pointer], :long],
637
+ put_onkeypress: [[VARIANT], :long],
638
+ get_onkeypress: [[:pointer], :long],
639
+ put_onmouseout: [[VARIANT], :long],
640
+ get_onmouseout: [[:pointer], :long],
641
+ put_onmouseover: [[VARIANT], :long],
642
+ get_onmouseover: [[:pointer], :long],
643
+ put_onmousemove: [[VARIANT], :long],
644
+ get_onmousemove: [[:pointer], :long],
645
+ put_onmousedown: [[VARIANT], :long],
646
+ get_onmousedown: [[:pointer], :long],
647
+ put_onmouseup: [[VARIANT], :long],
648
+ get_onmouseup: [[:pointer], :long],
649
+ get_document: [[:pointer], :long],
650
+ put_title: [[:pointer], :long],
651
+ get_title: [[:pointer], :long],
652
+ put_language: [[:pointer], :long],
653
+ get_language: [[:pointer], :long],
654
+ put_onselectstart: [[VARIANT], :long],
655
+ get_onselectstart: [[:pointer], :long],
656
+ scrollIntoView: [[VARIANT], :long],
657
+ contains: [[:pointer, :pointer], :long],
658
+ get_sourceIndex: [[:pointer], :long],
659
+ get_recordNumber: [[:pointer], :long],
660
+ put_lang: [[:pointer], :long],
661
+ get_lang: [[:pointer], :long],
662
+ get_offsetLeft: [[:pointer], :long],
663
+ get_offsetTop: [[:pointer], :long],
664
+ get_offsetWidth: [[:pointer], :long],
665
+ get_offsetHeight: [[:pointer], :long],
666
+ get_offsetParent: [[:pointer], :long],
667
+ put_innerHTML: [[:pointer], :long],
668
+ get_innerHTML: [[:pointer], :long],
669
+ put_innerText: [[:pointer], :long],
670
+ get_innerText: [[:pointer], :long],
671
+ put_outerHTML: [[:pointer], :long],
672
+ get_outerHTML: [[:pointer], :long],
673
+ put_outerText: [[:pointer], :long],
674
+ get_outerText: [[:pointer], :long],
675
+ insertAdjacentHTML: [[:pointer, :pointer], :long],
676
+ insertAdjacentText: [[:pointer, :pointer], :long],
677
+ get_parentTextEdit: [[:pointer], :long],
678
+ get_isTextEdit: [[:pointer], :long],
679
+ click: [[], :long],
680
+ get_filters: [[:pointer], :long],
681
+ put_ondragstart: [[VARIANT], :long],
682
+ get_ondragstart: [[:pointer], :long],
683
+ put_onbeforeupdate: [[VARIANT], :long],
684
+ get_onbeforeupdate: [[:pointer], :long],
685
+ put_onafterupdate: [[VARIANT], :long],
686
+ get_onafterupdate: [[:pointer], :long],
687
+ put_onerrorupdate: [[VARIANT], :long],
688
+ get_onerrorupdate: [[:pointer], :long],
689
+ put_onrowexit: [[VARIANT], :long],
690
+ get_onrowexit: [[:pointer], :long],
691
+ put_onrowenter: [[VARIANT], :long],
692
+ get_onrowenter: [[:pointer], :long],
693
+ put_ondatasetchanged: [[VARIANT], :long],
694
+ get_ondatasetchanged: [[:pointer], :long],
695
+ put_ondataavailable: [[VARIANT], :long],
696
+ get_ondataavailable: [[:pointer], :long],
697
+ put_ondatasetcomplete: [[VARIANT], :long],
698
+ get_ondatasetcomplete: [[:pointer], :long],
699
+ put_onfilterchange: [[VARIANT], :long],
700
+ get_onfilterchange: [[:pointer], :long],
701
+ get_children: [[:pointer], :long],
702
+ get_all: [[:pointer], :long]
703
+ ]
704
+
705
+ HTMLElement = COM::Instance[IHTMLElement]
706
+
707
+ class HTMLElement
708
+ attr_reader :handlers
709
+
710
+ def on(event, &block)
711
+ ((@handlers ||= {})[event] ||= []) << block
712
+ @dcallbacks ||= []
713
+
714
+ send("put_on#{event}", VARIANT.new.tap { |v|
715
+ v[:vt] = VT_DISPATCH
716
+
717
+ v[:pdispVal] = @dcallbacks.push(DCallback.new.tap { |dcb|
718
+ dcb.instance_variable_set(:@element, self)
719
+ dcb.instance_variable_set(:@event, event)
720
+
721
+ def dcb.Invoke(*args)
722
+ @element.handlers[@event].each { |handler|
723
+ (handler.arity == 0) ? handler.call : handler.call(*args)
724
+ }
725
+
726
+ S_OK
727
+ end
728
+ }).last
729
+ })
730
+
731
+ self
732
+ end
733
+
734
+ %w{offsetLeft offsetTop offsetWidth offsetHeight}.each { |name|
735
+ define_method(name) {
736
+ FFI::MemoryPointer.new(:pointer) { |plong|
737
+ send("get_#{name}", plong)
738
+
739
+ return plong.read_long
740
+ }
741
+ }
742
+ }
743
+
744
+ %w{className id tagName title language lang innerHTML innerText outerHTML outerText}.each { |name|
745
+ define_method(name) {
746
+ ppbstr = FFI::MemoryPointer.new(:pointer)
747
+
748
+ begin
749
+ send("get_#{name}", ppbstr)
750
+
751
+ return nil if (pbstr = ppbstr.read_pointer).null?
752
+
753
+ begin
754
+ Windows.WCSTOMBS(pbstr)
755
+ ensure
756
+ Windows.SysFreeString(pbstr)
757
+ end
758
+ ensure
759
+ ppbstr.free
760
+ end
761
+ }
762
+
763
+ next if name == 'tagName'
764
+
765
+ define_method("#{name}=") { |v|
766
+ bstr = Windows.SysAllocString("#{v}\0".encode('utf-16le'))
767
+
768
+ begin
769
+ send("put_#{name}", bstr)
770
+ ensure
771
+ Windows.SysFreeString(bstr)
772
+ end
773
+ }
774
+ }
775
+
776
+ def attr(*args)
777
+ case args.length
778
+ when 1
779
+ getAttribute(bstr = Windows.SysAllocString("#{args[0]}\0".encode('utf-16le')), 0, v = VARIANT.new)
780
+
781
+ case v[:vt]
782
+ when VT_BSTR; (v[:bstrVal].null?) ? nil : Windows.WCSTOMBS(v[:bstrVal])
783
+ when VT_I4; v[:lVal]
784
+ when VT_BOOL; v[:boolVal] == -1
785
+ else raise
786
+ end
787
+ when 2
788
+ v = VARIANT.new
789
+
790
+ case args[1]
791
+ when String; v[:vt] = VT_BSTR; v[:bstrVal] = bstrv = Windows.SysAllocString("#{args[0]}\0".encode('utf-16le'))
792
+ when Integer; v[:vt] = VT_I4; v[:lVal] = args[1]
793
+ when TrueClass; v[:vt] = VT_BOOL; v[:boolVal] = -1
794
+ when FalseClass, NilClass; v[:vt] = VT_BOOL; v[:boolVal] = 0
795
+ else raise ArgumentError
796
+ end
797
+
798
+ setAttribute(bstr = Windows.SysAllocString("#{args[0]}\0".encode('utf-16le')), v, 0)
799
+
800
+ self
801
+ else raise ArgumentError
802
+ end
803
+ ensure
804
+ Windows.SysFreeString(bstr) if bstr
805
+ Windows.SysFreeString(bstrv) if bstrv
806
+ end
807
+
808
+ def node; QueryInstance(HTMLDOMNode) end
809
+
810
+ def style
811
+ FFI::MemoryPointer.new(:pointer) { |pstyle|
812
+ get_style(pstyle)
813
+
814
+ return HTMLStyle.new(pstyle.read_pointer)
815
+ }
816
+ end
817
+
818
+ def css(hash) s = style; hash.each { |k, v| s.send("#{k}=", v) }; self end
819
+ end
820
+
821
+ IHTMLDOMNode = COM::Interface[IDispatch,
822
+ GUID['3050f5da-98b5-11cf-bb82-00aa00bdce0b'],
823
+
824
+ get_nodeType: [[:pointer], :long],
825
+ get_parentNode: [[:pointer], :long],
826
+ hasChildNodes: [[:pointer], :long],
827
+ get_childNodes: [[:pointer], :long],
828
+ get_attributes: [[:pointer], :long],
829
+ insertBefore: [[:pointer, VARIANT, :pointer], :long],
830
+ removeChild: [[:pointer, :pointer], :long],
831
+ replaceChild: [[:pointer, :pointer, :pointer], :long],
832
+ cloneNode: [[:short, :pointer], :long],
833
+ removeNode: [[:short, :pointer], :long],
834
+ swapNode: [[:pointer, :pointer], :long],
835
+ replaceNode: [[:pointer, :pointer], :long],
836
+ appendChild: [[:pointer, :pointer], :long],
837
+ get_nodeName: [[:pointer], :long],
838
+ put_nodeValue: [[VARIANT], :long],
839
+ get_nodeValue: [[:pointer], :long],
840
+ get_firstChild: [[:pointer], :long],
841
+ get_lastChild: [[:pointer], :long],
842
+ get_previousSibling: [[:pointer], :long],
843
+ get_nextSibling: [[:pointer], :long]
844
+ ]
845
+
846
+ HTMLDOMNode = COM::Instance[IHTMLDOMNode]
847
+
848
+ class HTMLDOMNode
849
+ alias old_appendChild appendChild
850
+
851
+ def appendChild(node)
852
+ FFI::MemoryPointer.new(:pointer) { |pnode|
853
+ old_appendChild(node, pnode)
854
+
855
+ return HTMLDOMNode.new(pnode)
856
+ }
857
+ end
858
+ end
859
+
860
+ IHTMLElementCollection = COM::Interface[IDispatch,
861
+ GUID['3050f21f-98b5-11cf-bb82-00aa00bdce0b'],
862
+
863
+ toString: [[:pointer], :long],
864
+ put_length: [[:long], :long],
865
+ get_length: [[:pointer], :long],
866
+ get__newEnum: [[:pointer], :long],
867
+ item: [[VARIANT, VARIANT, :pointer], :long],
868
+ tags: [[VARIANT, :pointer], :long]
869
+ ]
870
+
871
+ HTMLElementCollection = COM::Instance[IHTMLElementCollection]
872
+
873
+ class HTMLElementCollection
874
+ def get(selector)
875
+ v = VARIANT.new
876
+
877
+ case selector
878
+ when String
879
+ v[:vt] = VT_BSTR
880
+ v[:bstrVal] = bstr = if selector[0] == '#'
881
+ Windows.SysAllocString("#{selector[1..-1]}\0".encode('utf-16le'))
882
+ else
883
+ _tags = true
884
+ Windows.SysAllocString("#{selector}\0".encode('utf-16le'))
885
+ end
886
+ when Integer
887
+ v[:vt] = VT_I4; v[:intVal] = selector
888
+ else raise ArgumentError
889
+ end
890
+
891
+ pdisp = nil
892
+
893
+ FFI::MemoryPointer.new(:pointer) { |pdisp|
894
+ (_tags) ? tags(v, pdisp) : item(v, VARIANT.new, pdisp)
895
+
896
+ return nil if (pdisp = pdisp.read_pointer).null?
897
+
898
+ disp = Dispatch.new(pdisp)
899
+
900
+ return disp.QueryInstance((_tags) ? HTMLElementCollection : HTMLElement)
901
+ }
902
+ ensure
903
+ Windows.SysFreeString(bstr) if bstr
904
+ pdisp.Release if pdisp && !pdisp.null?
905
+ end
906
+ end
907
+
908
+ IHTMLStyle = COM::Interface[IDispatch,
909
+ GUID['3050f25e-98b5-11cf-bb82-00aa00bdce0b'],
910
+
911
+ put_fontFamily: [[:pointer], :long],
912
+ get_fontFamily: [[:pointer], :long],
913
+ put_fontStyle: [[:pointer], :long],
914
+ get_fontStyle: [[:pointer], :long],
915
+ put_fontVariant: [[:pointer], :long],
916
+ get_fontVariant: [[:pointer], :long],
917
+ put_fontWeight: [[:pointer], :long],
918
+ get_fontWeight: [[:pointer], :long],
919
+ put_fontSize: [[:pointer], :long],
920
+ get_fontSize: [[:pointer], :long],
921
+ put_font: [[:pointer], :long],
922
+ get_font: [[:pointer], :long],
923
+ put_color: [[VARIANT], :long],
924
+ get_color: [[:pointer], :long],
925
+ put_background: [[:pointer], :long],
926
+ get_background: [[:pointer], :long],
927
+ put_backgroundColor: [[VARIANT], :long],
928
+ get_backgroundColor: [[:pointer], :long],
929
+ put_backgroundImage: [[:pointer], :long],
930
+ get_backgroundImage: [[:pointer], :long],
931
+ put_backgroundRepeat: [[:pointer], :long],
932
+ get_backgroundRepeat: [[:pointer], :long],
933
+ put_backgroundAttachment: [[:pointer], :long],
934
+ get_backgroundAttachment: [[:pointer], :long],
935
+ put_backgroundPosition: [[:pointer], :long],
936
+ get_backgroundPosition: [[:pointer], :long],
937
+ put_backgroundPositionX: [[VARIANT], :long],
938
+ get_backgroundPositionX: [[:pointer], :long],
939
+ put_backgroundPositionY: [[VARIANT], :long],
940
+ get_backgroundPositionY: [[:pointer], :long],
941
+ put_wordSpacing: [[VARIANT], :long],
942
+ get_wordSpacing: [[:pointer], :long],
943
+ put_letterSpacing: [[VARIANT], :long],
944
+ get_letterSpacing: [[:pointer], :long],
945
+ put_textDecoration: [[:pointer], :long],
946
+ get_textDecoration: [[:pointer], :long],
947
+ put_textDecorationNone: [[:short], :long],
948
+ get_textDecorationNone: [[:pointer], :long],
949
+ put_textDecorationUnderline: [[:short], :long],
950
+ get_textDecorationUnderline: [[:pointer], :long],
951
+ put_textDecorationOverline: [[:short], :long],
952
+ get_textDecorationOverline: [[:pointer], :long],
953
+ put_textDecorationLineThrough: [[:short], :long],
954
+ get_textDecorationLineThrough: [[:pointer], :long],
955
+ put_textDecorationBlink: [[:short], :long],
956
+ get_textDecorationBlink: [[:pointer], :long],
957
+ put_verticalAlign: [[VARIANT], :long],
958
+ get_verticalAlign: [[:pointer], :long],
959
+ put_textTransform: [[:pointer], :long],
960
+ get_textTransform: [[:pointer], :long],
961
+ put_textAlign: [[:pointer], :long],
962
+ get_textAlign: [[:pointer], :long],
963
+ put_textIndent: [[VARIANT], :long],
964
+ get_textIndent: [[:pointer], :long],
965
+ put_lineHeight: [[VARIANT], :long],
966
+ get_lineHeight: [[:pointer], :long],
967
+ put_marginTop: [[VARIANT], :long],
968
+ get_marginTop: [[:pointer], :long],
969
+ put_marginRight: [[VARIANT], :long],
970
+ get_marginRight: [[:pointer], :long],
971
+ put_marginBottom: [[VARIANT], :long],
972
+ get_marginBottom: [[:pointer], :long],
973
+ put_marginLeft: [[VARIANT], :long],
974
+ get_marginLeft: [[:pointer], :long],
975
+ put_margin: [[:pointer], :long],
976
+ get_margin: [[:pointer], :long],
977
+ put_paddingTop: [[VARIANT], :long],
978
+ get_paddingTop: [[:pointer], :long],
979
+ put_paddingRight: [[VARIANT], :long],
980
+ get_paddingRight: [[:pointer], :long],
981
+ put_paddingBottom: [[VARIANT], :long],
982
+ get_paddingBottom: [[:pointer], :long],
983
+ put_paddingLeft: [[VARIANT], :long],
984
+ get_paddingLeft: [[:pointer], :long],
985
+ put_padding: [[:pointer], :long],
986
+ get_padding: [[:pointer], :long],
987
+ put_border: [[:pointer], :long],
988
+ get_border: [[:pointer], :long],
989
+ put_borderTop: [[:pointer], :long],
990
+ get_borderTop: [[:pointer], :long],
991
+ put_borderRight: [[:pointer], :long],
992
+ get_borderRight: [[:pointer], :long],
993
+ put_borderBottom: [[:pointer], :long],
994
+ get_borderBottom: [[:pointer], :long],
995
+ put_borderLeft: [[:pointer], :long],
996
+ get_borderLeft: [[:pointer], :long],
997
+ put_borderColor: [[:pointer], :long],
998
+ get_borderColor: [[:pointer], :long],
999
+ put_borderTopColor: [[VARIANT], :long],
1000
+ get_borderTopColor: [[:pointer], :long],
1001
+ put_borderRightColor: [[VARIANT], :long],
1002
+ get_borderRightColor: [[:pointer], :long],
1003
+ put_borderBottomColor: [[VARIANT], :long],
1004
+ get_borderBottomColor: [[:pointer], :long],
1005
+ put_borderLeftColor: [[VARIANT], :long],
1006
+ get_borderLeftColor: [[:pointer], :long],
1007
+ put_borderWidth: [[:pointer], :long],
1008
+ get_borderWidth: [[:pointer], :long],
1009
+ put_borderTopWidth: [[VARIANT], :long],
1010
+ get_borderTopWidth: [[:pointer], :long],
1011
+ put_borderRightWidth: [[VARIANT], :long],
1012
+ get_borderRightWidth: [[:pointer], :long],
1013
+ put_borderBottomWidth: [[VARIANT], :long],
1014
+ get_borderBottomWidth: [[:pointer], :long],
1015
+ put_borderLeftWidth: [[VARIANT], :long],
1016
+ get_borderLeftWidth: [[:pointer], :long],
1017
+ put_borderStyle: [[:pointer], :long],
1018
+ get_borderStyle: [[:pointer], :long],
1019
+ put_borderTopStyle: [[:pointer], :long],
1020
+ get_borderTopStyle: [[:pointer], :long],
1021
+ put_borderRightStyle: [[:pointer], :long],
1022
+ get_borderRightStyle: [[:pointer], :long],
1023
+ put_borderBottomStyle: [[:pointer], :long],
1024
+ get_borderBottomStyle: [[:pointer], :long],
1025
+ put_borderLeftStyle: [[:pointer], :long],
1026
+ get_borderLeftStyle: [[:pointer], :long],
1027
+ put_width: [[VARIANT], :long],
1028
+ get_width: [[:pointer], :long],
1029
+ put_height: [[VARIANT], :long],
1030
+ get_height: [[:pointer], :long],
1031
+ put_styleFloat: [[:pointer], :long],
1032
+ get_styleFloat: [[:pointer], :long],
1033
+ put_clear: [[:pointer], :long],
1034
+ get_clear: [[:pointer], :long],
1035
+ put_display: [[:pointer], :long],
1036
+ get_display: [[:pointer], :long],
1037
+ put_visibility: [[:pointer], :long],
1038
+ get_visibility: [[:pointer], :long],
1039
+ put_listStyleType: [[:pointer], :long],
1040
+ get_listStyleType: [[:pointer], :long],
1041
+ put_listStylePosition: [[:pointer], :long],
1042
+ get_listStylePosition: [[:pointer], :long],
1043
+ put_listStyleImage: [[:pointer], :long],
1044
+ get_listStyleImage: [[:pointer], :long],
1045
+ put_listStyle: [[:pointer], :long],
1046
+ get_listStyle: [[:pointer], :long],
1047
+ put_whiteSpace: [[:pointer], :long],
1048
+ get_whiteSpace: [[:pointer], :long],
1049
+ put_top: [[VARIANT], :long],
1050
+ get_top: [[:pointer], :long],
1051
+ put_left: [[VARIANT], :long],
1052
+ get_left: [[:pointer], :long],
1053
+ get_position: [[:pointer], :long],
1054
+ put_zIndex: [[VARIANT], :long],
1055
+ get_zIndex: [[:pointer], :long],
1056
+ put_overflow: [[:pointer], :long],
1057
+ get_overflow: [[:pointer], :long],
1058
+ put_pageBreakBefore: [[:pointer], :long],
1059
+ get_pageBreakBefore: [[:pointer], :long],
1060
+ put_pageBreakAfter: [[:pointer], :long],
1061
+ get_pageBreakAfter: [[:pointer], :long],
1062
+ put_cssText: [[:pointer], :long],
1063
+ get_cssText: [[:pointer], :long],
1064
+ put_pixelTop: [[:long], :long],
1065
+ get_pixelTop: [[:pointer], :long],
1066
+ put_pixelLeft: [[:long], :long],
1067
+ get_pixelLeft: [[:pointer], :long],
1068
+ put_pixelWidth: [[:long], :long],
1069
+ get_pixelWidth: [[:pointer], :long],
1070
+ put_pixelHeight: [[:long], :long],
1071
+ get_pixelHeight: [[:pointer], :long],
1072
+ put_posTop: [[:float], :long],
1073
+ get_posTop: [[:pointer], :long],
1074
+ put_posLeft: [[:float], :long],
1075
+ get_posLeft: [[:pointer], :long],
1076
+ put_posWidth: [[:float], :long],
1077
+ get_posWidth: [[:pointer], :long],
1078
+ put_posHeight: [[:float], :long],
1079
+ get_posHeight: [[:pointer], :long],
1080
+ put_cursor: [[:pointer], :long],
1081
+ get_cursor: [[:pointer], :long],
1082
+ put_clip: [[:pointer], :long],
1083
+ get_clip: [[:pointer], :long],
1084
+ put_filter: [[:pointer], :long],
1085
+ get_filter: [[:pointer], :long],
1086
+ setAttribute: [[:pointer, VARIANT, :long], :long],
1087
+ getAttribute: [[:pointer, :long, :pointer], :long],
1088
+ removeAttribute: [[:pointer, :long, :pointer], :long],
1089
+ toString: [[:pointer], :long]
1090
+ ]
1091
+
1092
+ HTMLStyle = COM::Instance[IHTMLStyle]
1093
+
1094
+ class HTMLStyle
1095
+ %w{
1096
+ fontFamily fontStyle fontVariant fontWeight fontSize font
1097
+ background backgroundImage backgroundRepeat backgroundAttachment backgroundPosition
1098
+ textDecoration textTransform textAlign
1099
+ margin padding
1100
+ border borderTop borderRight borderBottom borderLeft borderColor borderWidth borderStyle borderTopStyle borderRightStyle borderBottomStyle borderLeftStyle
1101
+ styleFloat clear display visibility
1102
+ listStyleType listStylePosition listStyleImage listStyle
1103
+ whiteSpace position overflow pageBreakBefore pageBreakAfter cssText cursor clip filter
1104
+ }.each { |name|
1105
+ define_method(name) {
1106
+ ppbstr = FFI::MemoryPointer.new(:pointer)
1107
+
1108
+ begin
1109
+ send("get_#{name}", ppbstr)
1110
+
1111
+ return nil if (pbstr = ppbstr.read_pointer).null?
1112
+
1113
+ begin
1114
+ Windows.WCSTOMBS(pbstr)
1115
+ ensure
1116
+ Windows.SysFreeString(pbstr)
1117
+ end
1118
+ ensure
1119
+ ppbstr.free
1120
+ end
1121
+ }
1122
+
1123
+ define_method("#{name}=") { |v|
1124
+ bstr = Windows.SysAllocString("#{v}\0".encode('utf-16le'))
1125
+
1126
+ begin
1127
+ send("put_#{name}", bstr)
1128
+ ensure
1129
+ Windows.SysFreeString(bstr)
1130
+ end
1131
+ }
1132
+ }
1133
+ end
1134
+ end
1135
+ end