ruby-changes:6539
From: suke <ko1@a...>
Date: Sun, 13 Jul 2008 21:36:40 +0900 (JST)
Subject: [ruby-changes:6539] Ruby:r18055 (trunk): * ext/win32ole/win32ole.c (EVENTSINK_Invoke): using hash
suke 2008-07-13 21:36:26 +0900 (Sun, 13 Jul 2008) New Revision: 18055 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=18055 Log: * ext/win32ole/win32ole.c (EVENTSINK_Invoke): using hash to set value to the reference argument of event. * test/win32ole/test_win32ole_event.rb: ditto. Modified files: trunk/ChangeLog trunk/ext/win32ole/win32ole.c trunk/test/win32ole/test_win32ole_event.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 18054) +++ ChangeLog (revision 18055) @@ -1,3 +1,10 @@ +Sun Jul 13 21:23:08 2008 Masaki Suketa <masaki.suketa@n...> + + * ext/win32ole/win32ole.c (EVENTSINK_Invoke): using hash + to set value to the reference argument of event. + + * test/win32ole/test_win32ole_event.rb: ditto. + Sun Jul 13 06:57:09 2008 Nobuyoshi Nakada <nobu@r...> * ext/pty/pty.c (raise_from_wait, pty_syswait, get_device_once): Index: ext/win32ole/win32ole.c =================================================================== --- ext/win32ole/win32ole.c (revision 18054) +++ ext/win32ole/win32ole.c (revision 18055) @@ -118,7 +118,7 @@ #define WC2VSTR(x) ole_wc2vstr((x), TRUE) -#define WIN32OLE_VERSION "1.2.3" +#define WIN32OLE_VERSION "1.2.4" typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX) (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*); @@ -499,6 +499,8 @@ static VALUE foleparam_inspect(VALUE self); static long ole_search_event_at(VALUE ary, VALUE ev); static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL *is_default); +static void hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams); +static VALUE hash2result(VALUE hash); static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams); static HRESULT find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo); static HRESULT find_coclass(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **pTypeInfo2, TYPEATTR **pTypeAttr2); @@ -7371,7 +7373,45 @@ return def_event; } +static void +hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams) +{ + BSTR *bstrs; + HRESULT hr; + UINT len, i; + VARIANT *pvar; + VALUE val; + VALUE key; + len = 0; + bstrs = ALLOCA_N(BSTR, pdispparams->cArgs + 1); + hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid, + bstrs, pdispparams->cArgs + 1, + &len); + if (FAILED(hr)) + return; + for (i = 0; i < len - 1; i++) { + key = WC2VSTR(bstrs[i + 1]); + val = rb_hash_aref(hash, INT2FIX(i)); + if (val == Qnil) + val = rb_hash_aref(hash, key); + if (val == Qnil) + val = rb_hash_aref(hash, rb_str_intern(key)); + pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1]; + ole_val2ptr_variant(val, pvar); + } +} + +static VALUE +hash2result(VALUE hash) +{ + VALUE ret = Qnil; + ret = rb_hash_aref(hash, rb_str_new2("return")); + if (ret == Qnil) + ret = rb_hash_aref(hash, rb_str_intern(rb_str_new2("return"))); + return ret; +} + static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams) { @@ -7443,10 +7483,19 @@ argv = rb_ary_new(); rb_ary_push(args, argv); result = rb_apply(handler, rb_intern("call"), args); - ary2ptr_dispparams(argv, pdispparams); + if(TYPE(result) == T_HASH) { + hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams); + result = hash2result(result); + } else { + ary2ptr_dispparams(argv, pdispparams); + } } else { result = rb_apply(handler, rb_intern("call"), args); + if(TYPE(result) == T_HASH) { + hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams); + result = hash2result(result); + } } if (pvarResult) { ole_val2variant(result, pvarResult); @@ -7829,7 +7878,6 @@ IEVENTSINKOBJ *pIEV; DWORD dwCookie; struct oleeventdata *poleev; - VALUE events = Qnil; rb_secure(4); rb_scan_args(argc, argv, "11", &ole, &itf); @@ -7966,9 +8014,28 @@ * * Defines the callback event. * If argument is omitted, this method defines the callback of all events. + * If you want to modify reference argument in callback, return hash in + * callback. If you want to return value to OLE server as result of callback + * use `return' or :return. + * * ie = WIN32OLE.new('InternetExplorer.Application') - * ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents') + * ev = WIN32OLE_EVENT.new(ie) * ev.on_event("NavigateComplete") {|url| puts url} + * ev.on_event() {|ev, *args| puts "#{ev} fired"} + * + * ev.on_event("BeforeNavigate2") {|*args| + * ... + * # set true to BeforeNavigate reference argument `Cancel'. + * # Cancel is 7-th argument of BeforeNavigate, + * # so you can use 6 as key of hash instead of 'Cancel'. + * # The argument is counted from 0. + * # The hash key of 0 means first argument.) + * {:Cancel => true} # or {'Cancel' => true} or {6 => true} + * } + * + * ev.on_event(...) {|*args| + * {:return => 1, :xxx => yyy} + * } */ static VALUE fev_on_event(int argc, VALUE *argv, VALUE self) @@ -7982,7 +8049,13 @@ * * Defines the callback of event. * If you want modify argument in callback, - * you should use this method instead of WIN32OLE_EVENT#on_event. + * you could use this method instead of WIN32OLE_EVENT#on_event. + * + * ie = WIN32OLE.new('InternetExplorer.Application') + * ev = WIN32OLE_EVENT.new(ie) + * ev.on_event_with_outargs('BeforeNavigate2') {|*args| + * args.last[6] = true + * } */ static VALUE fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self) Index: test/win32ole/test_win32ole_event.rb =================================================================== --- test/win32ole/test_win32ole_event.rb (revision 18054) +++ test/win32ole/test_win32ole_event.rb (revision 18055) @@ -164,6 +164,76 @@ assert_equal(bl, @ie.locationURL) end + def test_on_event_hash_return + ev = WIN32OLE_EVENT.new(@ie) + ev.on_event('BeforeNavigate2'){|*args| + {:return => 1, :Cancel => true} + } + bl = @ie.locationURL + @ie.navigate("file:///#{@f}") + while @ie.busy + sleep 0.1 + WIN32OLE_EVENT.message_loop + end + assert_equal(bl, @ie.locationURL) + end + + def test_on_event_hash_return2 + ev = WIN32OLE_EVENT.new(@ie) + ev.on_event('BeforeNavigate2'){|*args| + {:Cancel => true} + } + bl = @ie.locationURL + @ie.navigate("file:///#{@f}") + while @ie.busy + sleep 0.1 + WIN32OLE_EVENT.message_loop + end + assert_equal(bl, @ie.locationURL) + end + + def test_on_event_hash_return3 + ev = WIN32OLE_EVENT.new(@ie) + ev.on_event('BeforeNavigate2'){|*args| + {'Cancel' => true} + } + bl = @ie.locationURL + @ie.navigate("file:///#{@f}") + while @ie.busy + sleep 0.1 + WIN32OLE_EVENT.message_loop + end + assert_equal(bl, @ie.locationURL) + end + + def test_on_event_hash_return4 + ev = WIN32OLE_EVENT.new(@ie) + ev.on_event('BeforeNavigate2'){|*args| + {'return' => 2, 'Cancel' => true} + } + bl = @ie.locationURL + @ie.navigate("file:///#{@f}") + while @ie.busy + sleep 0.1 + WIN32OLE_EVENT.message_loop + end + assert_equal(bl, @ie.locationURL) + end + + def test_on_event_hash_return5 + ev = WIN32OLE_EVENT.new(@ie) + ev.on_event('BeforeNavigate2'){|*args| + {6 => true} + } + bl = @ie.locationURL + @ie.navigate("file:///#{@f}") + while @ie.busy + sleep 0.1 + WIN32OLE_EVENT.message_loop + end + assert_equal(bl, @ie.locationURL) + end + def handler1 @event2 = "handler1" end @@ -180,8 +250,19 @@ @ie.quit WIN32OLE_EVENT.message_loop @ie = nil - File.unlink(@f) + WIN32OLE_EVENT.message_loop + sleep 0.1 + begin + File.unlink(@f) + rescue Error::EACCESS + WIN32OLE_EVENT.message_loop + sleep 0.2 + File.unlink(@f) + end + GC.start + WIN32OLE_EVENT.message_loop + sleep 0.1 end end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/