diff options
author | nagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-07-27 19:35:06 +0000 |
---|---|---|
committer | nagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-07-27 19:35:06 +0000 |
commit | b388591ab76c81eb2c7b4a5d66a840235f1365df (patch) | |
tree | d45ad5c93760b70162054cfc085ba34a86d698be /ext/tcltklib | |
parent | e4ffaf6ea862785cef27ec5bd1083d2622ff0121 (diff) | |
download | ruby-b388591ab76c81eb2c7b4a5d66a840235f1365df.tar.gz |
multi-tk.rb : (new) library to support multiple Tk interpreters (high level)
tcltklib.c : add some methods to support multiple interpreters (low level)
MANUAL.euc : modify descriptions
tcltklib/sample/safeTk.rb : (new) sample : how to use safeTk interpreter
tk/sample/safe-tk.rb : (new) sample : how to use multi-tk.rb
tk.rb, tkafter.rb : bug fix and add feature to supprt multi-tk
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4186 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/tcltklib')
-rw-r--r-- | ext/tcltklib/MANIFEST | 5 | ||||
-rw-r--r-- | ext/tcltklib/MANUAL.euc | 35 | ||||
-rw-r--r-- | ext/tcltklib/demo/safeTk.rb | 22 | ||||
-rw-r--r-- | ext/tcltklib/tcltklib.c | 348 |
4 files changed, 274 insertions, 136 deletions
diff --git a/ext/tcltklib/MANIFEST b/ext/tcltklib/MANIFEST index 4e37fb900f..7337bbeba5 100644 --- a/ext/tcltklib/MANIFEST +++ b/ext/tcltklib/MANIFEST @@ -6,11 +6,12 @@ stubs.c depend extconf.rb lib/tcltk.rb -demo/lines1.rb demo/lines0.tcl +demo/lines1.rb demo/lines2.rb +demo/safeTk.rb +sample/sample0.rb sample/sample1.rb sample/sample2.rb sample/maru.gif sample/batsu.gif -sample/sample0.rb diff --git a/ext/tcltklib/MANUAL.euc b/ext/tcltklib/MANUAL.euc index f44e491e46..9f52c1ea8f 100644 --- a/ext/tcltklib/MANUAL.euc +++ b/ext/tcltklib/MANUAL.euc @@ -244,6 +244,27 @@ require "tcltklib" すると, 以下のモジュール, クラスが利用可能です. : 現在の loop_max と no_event_tick との値を返す. : ( see set_eventloop_wait ) + mainloop_abort_on_no_widget_cmd=(bool) + : Tk インタープリタ上で widget に対応するコマンドが存在しない + : という例外を発生した際に,イベントループをエラー停止させる + : かどうかを指定する.true を指定した場合はエラー停止するが, + : false の場合は例外を無視してイベントループを継続する. + : デフォルトでは false に設定されている. + : これは,コールバック処理の消去を忘れたままに widget を破壊 + : してしまった場合のエラー停止の回避に役立つ.特に複数のイン + : タープリタが同時に動作している場合には,それらを管理するイ + : ベントループは 1 個であるため,いずれかのインタープリタが強 + : 制停止させられた際にコールバックの完全な消去に失敗する場合 + : がしばしば見られる.そのような場合でもエラーを無視してイベ + : ントループが稼働を続けることで,残りのインタープリタが正常 + : に動作し続けることができる. + + mainloop_abort_on_no_widget_cmd + : Tk インタープリタ上で widget に対応するコマンドが存在しない + : という例外を発生した際に,イベントループをエラー停止させる + : かどうかを設定状態を true/false で得る. + + クラス TclTkIp クラスメソッド new(ip_name=nil, options='') @@ -274,6 +295,16 @@ require "tcltklib" すると, 以下のモジュール, クラスが利用可能です. : Tcl/Tk インタープリタを safe インタープリタであるかを調べる. : safe インタープリタであれば true を返す. + delete + : Tcl/Tk インタープリタを delete する. + : delete されたインタープリタは,以後一切の操作ができなくなり, + : コマンドを送っても例外を発生するようになる. + + deleted? + : Tcl/Tk インタープリタがすでに delete されているかを調べる. + : delete 済みでコマンドを受け付けない状態になっているならば + : true を返す. + restart : Tcl/Tk インタープリタの Tk 部分の初期化,再起動を行う. : 一旦 root widget を破壊した後に再度 Tk の機能が必要と @@ -308,6 +339,10 @@ require "tcltklib" すると, 以下のモジュール, クラスが利用可能です. get_eventloop_tick : 引数を含めて TclTkLib.get_eventloop_tick に同じ set_eventloop_weight : 引数を含めて TclTkLib.set_eventloop_weight に同じ get_eventloop_weight : 引数を含めて TclTkLib.set_eventloop_weight に同じ + mainloop_abort_on_no_widget_cmd= + : 引数を含めて TclTkLib.mainloop_abort_on_no_widget_cmd= に同じ + mainloop_abort_on_no_widget_cmd + : 引数を含めて TclTkLib.mainloop_abort_on_no_widget_cmd に同じ クラス TkCallbackBreak < StandardError クラス TkCallbackContinue < StandardError diff --git a/ext/tcltklib/demo/safeTk.rb b/ext/tcltklib/demo/safeTk.rb new file mode 100644 index 0000000000..5d2c60e700 --- /dev/null +++ b/ext/tcltklib/demo/safeTk.rb @@ -0,0 +1,22 @@ +#!/usr/bin/env ruby +require 'tcltklib' + +master = TclTkIp.new +slave_name = 'slave0' +slave = master.create_slave(slave_name, true) +master._eval("::safe::interpInit #{slave_name}") +master._eval("::safe::loadTk #{slave_name}") + +master._invoke('label', '.l1', '-text', 'master') +master._invoke('pack', '.l1', '-padx', '30', '-pady', '50') +master._eval('label .l2 -text {root widget of master-ip}') +master._eval('pack .l2 -padx 30 -pady 50') + +slave._invoke('label', '.l1', '-text', 'slave') +slave._invoke('pack', '.l1', '-padx', '30', '-pady', '50') +slave._eval('label .l2 -text {root widget of slave-ip}') +slave._eval('pack .l2 -padx 30 -pady 20') +slave._eval('label .l3 -text {( container frame widget of master-ip )}') +slave._eval('pack .l3 -padx 30 -pady 20') + +TclTkLib.mainloop diff --git a/ext/tcltklib/tcltklib.c b/ext/tcltklib/tcltklib.c index 9df98742b7..bf258f6d9b 100644 --- a/ext/tcltklib/tcltklib.c +++ b/ext/tcltklib/tcltklib.c @@ -83,6 +83,8 @@ static int timer_tick = DEFAULT_TIMER_TICK; static int req_timer_tick = DEFAULT_TIMER_TICK; static int run_timer_flag = 0; +static int event_loop_abort_no_cmd = 0; +static int loop_counter = 0; #if TCL_MAJOR_VERSION >= 8 static int ip_ruby _((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST*)); @@ -108,10 +110,10 @@ _timer_for_tcl(clientData) run_timer_flag = 1; if (timer_tick > 0) { - timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl, - (ClientData)0); + timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl, + (ClientData)0); } else { - timer_token = (Tcl_TimerToken)NULL; + timer_token = (Tcl_TimerToken)NULL; } /* rb_thread_schedule(); */ @@ -126,8 +128,8 @@ set_eventloop_tick(self, tick) int ttick = NUM2INT(tick); if (ttick < 0) { - rb_raise(rb_eArgError, - "timer-tick parameter must be 0 or positive number"); + rb_raise(rb_eArgError, + "timer-tick parameter must be 0 or positive number"); } /* delete old timer callback */ @@ -135,11 +137,11 @@ set_eventloop_tick(self, tick) timer_tick = req_timer_tick = ttick; if (timer_tick > 0) { - /* start timer callback */ - timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl, - (ClientData)0); + /* start timer callback */ + timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl, + (ClientData)0); } else { - timer_token = (Tcl_TimerToken)NULL; + timer_token = (Tcl_TimerToken)NULL; } return tick; @@ -160,8 +162,8 @@ set_no_event_wait(self, wait) int t_wait = NUM2INT(wait); if (t_wait <= 0) { - rb_raise(rb_eArgError, - "no_event_wait parameter must be positive number"); + rb_raise(rb_eArgError, + "no_event_wait parameter must be positive number"); } no_event_wait = t_wait; @@ -186,7 +188,7 @@ set_eventloop_weight(self, loop_max, no_event) int no_ev = NUM2INT(no_event); if (lpmax <= 0 || no_ev <= 0) { - rb_raise(rb_eArgError, "weight parameters must be positive numbers"); + rb_raise(rb_eArgError, "weight parameters must be positive numbers"); } event_loop_max = lpmax; @@ -202,85 +204,110 @@ get_eventloop_weight(self) return rb_ary_new3(2, INT2NUM(event_loop_max), INT2NUM(no_event_tick)); } +static VALUE +rb_evloop_abort_no_cmd(self) + VALUE self; +{ + return event_loop_abort_no_cmd? Qtrue: Qfalse; +} + +static VALUE +rb_evloop_abort_no_cmd_set(self, val) + VALUE self, val; +{ + rb_secure(4); + event_loop_abort_no_cmd = (val == Qtrue)? 1: 0; + return rb_event_loop_abort_no_cmd(); +} + VALUE lib_mainloop_core(check_root_widget) - VALUE check_root_widget; + VALUE check_root_widget; { - VALUE current = eventloop_thread; - int check = (check_root_widget == Qtrue); - int tick_counter; - struct timeval t; - - t.tv_sec = (time_t)0; - t.tv_usec = (time_t)(no_event_wait*1000.0); - - Tk_DeleteTimerHandler(timer_token); - run_timer_flag = 0; - if (timer_tick > 0) { - timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl, - (ClientData)0); - } else { - timer_token = (Tcl_TimerToken)NULL; - } + VALUE current = eventloop_thread; + int check = (check_root_widget == Qtrue); + int tick_counter; + struct timeval t; - for(;;) { - if (rb_thread_alone()) { - DUMP1("no other thread"); - if (timer_tick == 0) { - timer_tick = NO_THREAD_INTERRUPT_TIME; + t.tv_sec = (time_t)0; + t.tv_usec = (time_t)(no_event_wait*1000.0); + + Tk_DeleteTimerHandler(timer_token); + run_timer_flag = 0; + if (timer_tick > 0) { timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl, (ClientData)0); - } - - Tcl_DoOneEvent(TCL_ALL_EVENTS); - - if (run_timer_flag) { - DUMP1("timer interrupt"); - run_timer_flag = 0; - DUMP1("check Root Widget"); - if (check && Tk_GetNumMainWindows() == 0) { - return Qnil; - } - } - } else { - DUMP1("there are other threads"); - timer_tick = req_timer_tick; - tick_counter = 0; - while(tick_counter < event_loop_max) { - if (Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT)) { - tick_counter++; - } else { - tick_counter += no_event_tick; - - DUMP1("check Root Widget"); - if (check && Tk_GetNumMainWindows() == 0) { - return Qnil; - } - - rb_thread_wait_for(t); - } + timer_token = (Tcl_TimerToken)NULL; + } - if (watchdog_thread != 0 && eventloop_thread != current) { - return Qnil; - } + for(;;) { + if (rb_thread_alone()) { + DUMP1("no other thread"); + if (timer_tick == 0) { + timer_tick = NO_THREAD_INTERRUPT_TIME; + timer_token = Tk_CreateTimerHandler(timer_tick, + _timer_for_tcl, + (ClientData)0); + } + + Tcl_DoOneEvent(TCL_ALL_EVENTS); + + if (loop_counter++ > 30000) { + loop_counter = 0; + } + + if (run_timer_flag) { + DUMP1("timer interrupt"); + run_timer_flag = 0; + DUMP1("check Root Widget"); + if (check && Tk_GetNumMainWindows() == 0) { + return Qnil; + } + } - if (run_timer_flag) { - DUMP1("timer interrupt"); - run_timer_flag = 0; - break; /* switch to other thread */ + } else { + DUMP1("there are other threads"); + timer_tick = req_timer_tick; + tick_counter = 0; + while(tick_counter < event_loop_max) { + if (Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT)) { + tick_counter++; + } else { + tick_counter += no_event_tick; + + DUMP1("check Root Widget"); + if (check && Tk_GetNumMainWindows() == 0) { + return Qnil; + } + + rb_thread_wait_for(t); + } + + if (loop_counter++ > 30000) { + loop_counter = 0; + } + + if (watchdog_thread != 0 && eventloop_thread != current) { + return Qnil; + } + + if (run_timer_flag) { + DUMP1("timer interrupt"); + run_timer_flag = 0; + break; /* switch to other thread */ + } + } + + DUMP1("check Root Widget"); + if (check && Tk_GetNumMainWindows() == 0) { + return Qnil; + } } - } - DUMP1("check Root Widget"); - if (check && Tk_GetNumMainWindows() == 0) { - return Qnil; - } + rb_thread_schedule(); } - - rb_thread_schedule(); - } - return Qnil; + return Qnil; } VALUE @@ -292,8 +319,8 @@ lib_mainloop_ensure(parent_evloop) DUMP2("mainloop-ensure: current-thread : %lx\n", rb_thread_current()); DUMP2("mainloop-ensure: eventloop-thread : %lx\n", eventloop_thread); if (eventloop_thread == rb_thread_current()) { - DUMP2("tcltklib: eventloop-thread -> %lx\n", parent_evloop); - eventloop_thread = parent_evloop; + DUMP2("tcltklib: eventloop-thread -> %lx\n", parent_evloop); + eventloop_thread = parent_evloop; } return Qnil; } @@ -307,8 +334,8 @@ lib_mainloop_launcher(check_rootwidget) eventloop_thread = rb_thread_current(); if (ruby_debug) { - fprintf(stderr, "tcltklib: eventloop-thread : %lx -> %lx\n", - parent_evloop, eventloop_thread); + fprintf(stderr, "tcltklib: eventloop-thread : %lx -> %lx\n", + parent_evloop, eventloop_thread); } return rb_ensure(lib_mainloop_core, check_rootwidget, @@ -325,11 +352,11 @@ lib_mainloop(argc, argv, self) VALUE check_rootwidget; if (rb_scan_args(argc, argv, "01", &check_rootwidget) == 0) { - check_rootwidget = Qtrue; + check_rootwidget = Qtrue; } else if (RTEST(check_rootwidget)) { - check_rootwidget = Qtrue; + check_rootwidget = Qtrue; } else { - check_rootwidget = Qfalse; + check_rootwidget = Qfalse; } return lib_mainloop_launcher(check_rootwidget); @@ -342,36 +369,37 @@ lib_watchdog_core(check_rootwidget) VALUE current = eventloop_thread; VALUE evloop; int check = (check_rootwidget == Qtrue); - ID stop = rb_intern("stop?"); + int prev_val = -1; struct timeval t; + VALUE ret; t.tv_sec = (time_t)0; t.tv_usec = (time_t)((WATCHDOG_INTERVAL)*1000.0); /* check other watchdog thread */ if (watchdog_thread != 0) { - if (rb_funcall(watchdog_thread, stop, 0) == Qtrue) { - rb_funcall(watchdog_thread, rb_intern("kill"), 0); - } else { - return Qnil; - } + if (rb_funcall(watchdog_thread, rb_intern("stop?"), 0) == Qtrue) { + rb_funcall(watchdog_thread, rb_intern("kill"), 0); + } else { + return Qnil; + } } watchdog_thread = rb_thread_current(); /* watchdog start */ do { - if (eventloop_thread == 0 - || rb_funcall(eventloop_thread, stop, 0) == Qtrue) { - /* start new eventloop thread */ - DUMP2("eventloop thread %lx is sleeping or dead", eventloop_thread); - evloop = rb_thread_create(lib_mainloop_launcher, - (void*)&check_rootwidget); - DUMP2("create new eventloop thread %lx", evloop); - rb_thread_run(evloop); - } else { - rb_thread_wait_for(t); - /* rb_thread_schedule(); */ - } + if (eventloop_thread == 0 || loop_counter == prev_val) { + /* start new eventloop thread */ + DUMP2("eventloop thread %lx is sleeping or dead", + eventloop_thread); + evloop = rb_thread_create(lib_mainloop_launcher, + (void*)&check_rootwidget); + DUMP2("create new eventloop thread %lx", evloop); + rb_thread_run(evloop); + } else { + rb_thread_wait_for(t); + /* rb_thread_schedule(); */ + } } while(!check || Tk_GetNumMainWindows() != 0); return Qnil; @@ -394,11 +422,11 @@ lib_mainloop_watchdog(argc, argv, self) VALUE check_rootwidget; if (rb_scan_args(argc, argv, "01", &check_rootwidget) == 0) { - check_rootwidget = Qtrue; + check_rootwidget = Qtrue; } else if (RTEST(check_rootwidget)) { - check_rootwidget = Qtrue; + check_rootwidget = Qtrue; } else { - check_rootwidget = Qfalse; + check_rootwidget = Qfalse; } return rb_ensure(lib_watchdog_core, check_rootwidget, @@ -416,16 +444,16 @@ lib_do_one_event(argc, argv, self) int ret; if (rb_scan_args(argc, argv, "01", &vflags) == 0) { - flags = TCL_ALL_EVENTS; + flags = TCL_ALL_EVENTS; } else { - Check_Type(vflags, T_FIXNUM); - flags = FIX2INT(vflags); + Check_Type(vflags, T_FIXNUM); + flags = FIX2INT(vflags); } ret = Tcl_DoOneEvent(flags); if (ret) { - return Qtrue; + return Qtrue; } else { - return Qfalse; + return Qfalse; } } @@ -473,15 +501,15 @@ lib_restart(self) /* execute Tk_Init of Tk_SafeInit */ #if TCL_MAJOR_VERSION >= 8 if (Tcl_IsSafe(ptr->ip)) { - DUMP1("Tk_SafeInit"); - if (Tk_SafeInit(ptr->ip) == TCL_ERROR) { - rb_raise(rb_eRuntimeError, "%s", ptr->ip->result); - } + DUMP1("Tk_SafeInit"); + if (Tk_SafeInit(ptr->ip) == TCL_ERROR) { + rb_raise(rb_eRuntimeError, "%s", ptr->ip->result); + } } else { - DUMP1("Tk_Init"); - if (Tk_Init(ptr->ip) == TCL_ERROR) { - rb_raise(rb_eRuntimeError, "%s", ptr->ip->result); - } + DUMP1("Tk_Init"); + if (Tk_Init(ptr->ip) == TCL_ERROR) { + rb_raise(rb_eRuntimeError, "%s", ptr->ip->result); + } } #else DUMP1("Tk_Init"); @@ -569,6 +597,7 @@ ip_free(ptr) { DUMP1("Tcl_DeleteInterp"); if (ptr) { + Tcl_Release((ClientData)ptr->ip); Tcl_DeleteInterp(ptr->ip); free(ptr); } @@ -602,6 +631,7 @@ ip_init(argc, argv, self) /* from Tk_Main() */ DUMP1("Tcl_CreateInterp"); ptr->ip = Tcl_CreateInterp(); + Tcl_Preserve((ClientData)ptr->ip); current_interp = ptr->ip; /* from Tcl_AppInit() */ @@ -680,8 +710,10 @@ ip_create_slave(argc, argv, self) /* create slave-ip */ if ((slave->ip = Tcl_CreateSlave(master->ip, StringValuePtr(name), safe)) == NULL) { - rb_raise(rb_eRuntimeError, "fail to create the new slave interpreter"); + rb_ip_raise(self, rb_eRuntimeError, + "fail to create the new slave interpreter"); } + Tcl_Preserve((ClientData)slave->ip); slave->return_value = 0; return Data_Wrap_Struct(CLASS_OF(self), 0, ip_free, slave); @@ -695,7 +727,7 @@ ip_make_safe(self) struct tcltkip *ptr = get_ip(self); if (Tcl_MakeSafe(ptr->ip) == TCL_ERROR) { - rb_raise(rb_eRuntimeError, "%s", ptr->ip->result); + rb_ip_raise(self, rb_eRuntimeError, "%s", ptr->ip->result); } return self; @@ -715,6 +747,32 @@ ip_is_safe_p(self) } } +/* delete interpreter */ +static VALUE +ip_delete(self) + VALUE self; +{ + struct tcltkip *ptr = get_ip(self); + + Tcl_DeleteInterp(ptr->ip); + + return Qnil; +} + +/* is deleted? */ +static VALUE +ip_is_deleted_p(self) + VALUE self; +{ + struct tcltkip *ptr = get_ip(self); + + if (Tcl_InterpDeleted(ptr->ip)) { + return Qtrue; + } else { + return Qfalse; + } +} + /* eval string in tcl by Tcl_Eval() */ static VALUE ip_eval(self, str) @@ -722,7 +780,7 @@ ip_eval(self, str) VALUE str; { char *s; - char *buf; /* Tcl_Eval requires re-writable string region */ + char *buf; /* Tcl_Eval requires re-writable string region */ struct tcltkip *ptr = get_ip(self); /* call Tcl_Eval() */ @@ -741,7 +799,6 @@ ip_eval(self, str) return(rb_tainted_str_new2(ptr->ip->result)); } - static VALUE ip_toUTF8(self, str, encodename) VALUE self; @@ -838,9 +895,21 @@ ip_invoke_real(argc, argv, obj) v = argv[0]; cmd = StringValuePtr(v); + /* ip is deleted? */ + if (Tcl_InterpDeleted(ptr->ip)) { + Tcl_ResetResult(ptr->ip); + return rb_tainted_str_new2(""); + } + /* map from the command name to a C procedure */ if (!Tcl_GetCommandInfo(ptr->ip, cmd, &info)) { - rb_raise(rb_eNameError, "invalid command name `%s'", cmd); + if (event_loop_abort_no_cmd || cmd[0] != '.') + rb_raise(rb_eNameError, "invalid command name `%s'", cmd); + else { + Tcl_ResetResult(ptr->ip); + rb_warning("invalid command name `%s' (ignore)", cmd); + return rb_tainted_str_new2(""); + } } /* memory allocation for arguments of this command */ @@ -859,7 +928,7 @@ ip_invoke_real(argc, argv, obj) else #endif { - /* string interface */ + /* string interface */ av = (char **)ALLOCA_N(char *, argc+1); for (i = 0; i < argc; ++i) { v = argv[i]; @@ -931,8 +1000,8 @@ invoke_queue_handler(evPtr, flags) DUMP2("added by thread : %lx", q->thread); if (q->done) { - /* processed by another event-loop */ - return 0; + /* processed by another event-loop */ + return 0; } /* process it */ @@ -940,11 +1009,12 @@ invoke_queue_handler(evPtr, flags) /* check safe-level */ if (rb_safe_level() != q->safe_level) { - *(q->result) = rb_funcall(rb_proc_new(ivq_safelevel_handler, - Data_Wrap_Struct(rb_cData,0,0,q)), - rb_intern("call"), 0); + *(q->result) + = rb_funcall(rb_proc_new(ivq_safelevel_handler, + Data_Wrap_Struct(rb_cData,0,0,q)), + rb_intern("call"), 0); } else { - *(q->result) = ip_invoke_real(q->argc, q->argv, q->obj); + *(q->result) = ip_invoke_real(q->argc, q->argv, q->obj); } /* back to caller */ @@ -970,8 +1040,8 @@ ip_invoke(argc, argv, obj) rb_raise(rb_eArgError, "command name missing"); } if (eventloop_thread == 0 || current == eventloop_thread) { - DUMP2("invoke from current eventloop %lx", current); - return ip_invoke_real(argc, argv, obj); + DUMP2("invoke from current eventloop %lx", current); + return ip_invoke_real(argc, argv, obj); } DUMP2("invoke from thread %lx (NOT current eventloop)", current); @@ -1071,12 +1141,18 @@ Init_tcltklib() set_eventloop_weight, 2); rb_define_module_function(lib, "get_eventloop_weight", get_eventloop_weight, 0); + rb_define_module_function(lib, "mainloop_abort_on_no_widget_cmd", + rb_evloop_abort_no_cmd, 0); + rb_define_module_function(lib, "mainloop_abort_on_no_widget_cmd=", + rb_evloop_abort_no_cmd_set, 1); rb_define_alloc_func(ip, ip_alloc); rb_define_method(ip, "initialize", ip_init, -1); rb_define_method(ip, "create_slave", ip_create_slave, -1); rb_define_method(ip, "make_safe", ip_make_safe, 0); rb_define_method(ip, "safe?", ip_is_safe_p, 0); + rb_define_method(ip, "delete", ip_delete, 0); + rb_define_method(ip, "deleted?", ip_is_deleted_p, 0); rb_define_method(ip, "_eval", ip_eval, 1); rb_define_method(ip, "_toUTF8",ip_toUTF8,2); rb_define_method(ip, "_fromUTF8",ip_fromUTF8,2); @@ -1085,6 +1161,10 @@ Init_tcltklib() rb_define_method(ip, "mainloop", lib_mainloop, -1); rb_define_method(ip, "mainloop_watchdog", lib_mainloop_watchdog, -1); rb_define_method(ip, "do_one_event", lib_do_one_event, -1); + rb_define_method(ip, "mainloop_abort_on no_widget_cmd", + rb_evloop_abort_no_cmd, 0); + rb_define_method(ip, "mainloop_abort_on_no_widget_cmd=", + rb_evloop_abort_no_cmd_set, 1); rb_define_method(ip, "set_eventloop_tick", set_eventloop_tick, 1); rb_define_method(ip, "get_eventloop_tick", get_eventloop_tick, 0); rb_define_method(ip, "set_no_event_wait", set_no_event_wait, 1); |