1998-01-16 07:19:09 -05:00
|
|
|
/*
|
2004-10-11 00:51:21 -04:00
|
|
|
* tcltklib.c
|
|
|
|
* Aug. 27, 1997 Y. Shigehiro
|
|
|
|
* Oct. 24, 1997 Y. Matsumoto
|
1998-01-16 07:19:09 -05:00
|
|
|
*/
|
|
|
|
|
2006-12-01 02:43:05 -05:00
|
|
|
#define TCLTKLIB_RELEASE_DATE "2006-12-01"
|
2004-12-22 23:17:03 -05:00
|
|
|
|
2007-06-09 23:06:15 -04:00
|
|
|
#include "ruby/ruby.h"
|
|
|
|
#include "ruby/signal.h"
|
2004-10-11 00:51:21 -04:00
|
|
|
#undef EXTERN /* avoid conflict with tcl.h of tcl8.2 or before */
|
1998-01-16 07:19:09 -05:00
|
|
|
#include <stdio.h>
|
2003-08-29 04:34:14 -04:00
|
|
|
#ifdef HAVE_STDARG_PROTOTYPES
|
|
|
|
#include <stdarg.h>
|
|
|
|
#define va_init_list(a,b) va_start(a,b)
|
|
|
|
#else
|
|
|
|
#include <varargs.h>
|
|
|
|
#define va_init_list(a,b) va_start(a)
|
|
|
|
#endif
|
1998-01-16 07:19:09 -05:00
|
|
|
#include <string.h>
|
|
|
|
#include <tcl.h>
|
|
|
|
#include <tk.h>
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
#include "stubs.h"
|
|
|
|
|
2005-03-30 03:44:19 -05:00
|
|
|
#ifndef TCL_ALPHA_RELEASE
|
|
|
|
#define TCL_ALPHA_RELEASE 0
|
|
|
|
#define TCL_BETA_RELEASE 1
|
|
|
|
#define TCL_FINAL_RELEASE 2
|
|
|
|
#endif
|
|
|
|
|
2003-10-29 06:03:54 -05:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
# ifndef CONST84
|
|
|
|
# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION <= 4 /* Tcl8.0.x -- 8.4b1 */
|
|
|
|
# define CONST84
|
|
|
|
# else /* unknown (maybe TCL_VERSION >= 8.5) */
|
|
|
|
# ifdef CONST
|
|
|
|
# define CONST84 CONST
|
|
|
|
# else
|
|
|
|
# define CONST84
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
# endif
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2004-01-25 22:49:21 -05:00
|
|
|
# ifdef CONST
|
|
|
|
# define CONST84 CONST
|
|
|
|
# else
|
2004-05-01 12:09:54 -04:00
|
|
|
# define CONST
|
2004-01-25 22:49:21 -05:00
|
|
|
# define CONST84
|
|
|
|
# endif
|
2003-10-29 06:03:54 -05:00
|
|
|
#endif
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* copied from eval.c */
|
|
|
|
#define TAG_RETURN 0x1
|
|
|
|
#define TAG_BREAK 0x2
|
|
|
|
#define TAG_NEXT 0x3
|
|
|
|
#define TAG_RETRY 0x4
|
|
|
|
#define TAG_REDO 0x5
|
|
|
|
#define TAG_RAISE 0x6
|
2004-09-11 13:45:53 -04:00
|
|
|
#define TAG_THROW 0x7
|
2004-05-01 12:09:54 -04:00
|
|
|
#define TAG_FATAL 0x8
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* for ruby_debug */
|
|
|
|
#define DUMP1(ARG1) if (ruby_debug) { fprintf(stderr, "tcltklib: %s\n", ARG1); fflush(stderr); }
|
1999-08-13 01:37:52 -04:00
|
|
|
#define DUMP2(ARG1, ARG2) if (ruby_debug) { fprintf(stderr, "tcltklib: ");\
|
2004-05-01 12:09:54 -04:00
|
|
|
fprintf(stderr, ARG1, ARG2); fprintf(stderr, "\n"); fflush(stderr); }
|
2005-08-08 12:18:29 -04:00
|
|
|
#define DUMP3(ARG1, ARG2, ARG3) if (ruby_debug) { fprintf(stderr, "tcltklib: ");\
|
|
|
|
fprintf(stderr, ARG1, ARG2, ARG3); fprintf(stderr, "\n"); fflush(stderr); }
|
1998-01-16 07:19:09 -05:00
|
|
|
/*
|
|
|
|
#define DUMP1(ARG1)
|
|
|
|
#define DUMP2(ARG1, ARG2)
|
2005-08-08 12:18:29 -04:00
|
|
|
#define DUMP3(ARG1, ARG2, ARG3)
|
1998-01-16 07:19:09 -05:00
|
|
|
*/
|
|
|
|
|
2004-12-22 23:17:03 -05:00
|
|
|
/* release date */
|
|
|
|
const char tcltklib_release_date[] = TCLTKLIB_RELEASE_DATE;
|
|
|
|
|
2004-12-27 06:04:21 -05:00
|
|
|
/* finalize_proc_name */
|
2004-05-01 12:09:54 -04:00
|
|
|
static char *finalize_hook_name = "INTERP_FINALIZE_HOOK";
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
static void ip_finalize _((Tcl_Interp*));
|
2004-12-27 06:04:21 -05:00
|
|
|
|
2006-07-10 05:52:30 -04:00
|
|
|
static int at_exit = 0;
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
/* for callback break & continue */
|
2004-05-01 12:09:54 -04:00
|
|
|
static VALUE eTkCallbackReturn;
|
1999-08-13 01:37:52 -04:00
|
|
|
static VALUE eTkCallbackBreak;
|
|
|
|
static VALUE eTkCallbackContinue;
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
static VALUE eLocalJumpError;
|
|
|
|
|
2005-08-09 02:16:29 -04:00
|
|
|
static VALUE eTkLocalJumpError;
|
|
|
|
static VALUE eTkCallbackRetry;
|
|
|
|
static VALUE eTkCallbackRedo;
|
|
|
|
static VALUE eTkCallbackThrow;
|
|
|
|
|
2005-11-18 03:39:29 -05:00
|
|
|
static VALUE tcltkip_class;
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
static ID ID_at_enc;
|
|
|
|
static ID ID_at_interp;
|
|
|
|
|
|
|
|
static ID ID_stop_p;
|
2005-03-02 02:06:52 -05:00
|
|
|
static ID ID_alive_p;
|
2004-05-01 12:09:54 -04:00
|
|
|
static ID ID_kill;
|
|
|
|
static ID ID_join;
|
2005-03-02 02:06:52 -05:00
|
|
|
static ID ID_value;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
static ID ID_call;
|
|
|
|
static ID ID_backtrace;
|
|
|
|
static ID ID_message;
|
|
|
|
|
|
|
|
static ID ID_at_reason;
|
|
|
|
static ID ID_return;
|
|
|
|
static ID ID_break;
|
|
|
|
static ID ID_next;
|
|
|
|
|
|
|
|
static ID ID_to_s;
|
|
|
|
static ID ID_inspect;
|
|
|
|
|
1999-08-13 01:37:52 -04:00
|
|
|
static VALUE ip_invoke_real _((int, VALUE*, VALUE));
|
2003-10-14 11:25:45 -04:00
|
|
|
static VALUE ip_invoke _((int, VALUE*, VALUE));
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
static VALUE tk_funcall _((VALUE(), int, VALUE*, VALUE));
|
|
|
|
|
2005-04-12 02:37:10 -04:00
|
|
|
/* safe Tcl_Eval and Tcl_GlobalEval */
|
|
|
|
static int
|
2006-06-21 04:32:22 -04:00
|
|
|
tcl_eval(Tcl_Interp *interp, const char *cmd)
|
2005-04-12 02:37:10 -04:00
|
|
|
{
|
|
|
|
char *buf = strdup(cmd);
|
2006-07-03 06:08:11 -04:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
Tcl_AllowExceptions(interp);
|
|
|
|
ret = Tcl_Eval(interp, buf);
|
2005-04-12 02:37:10 -04:00
|
|
|
free(buf);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef Tcl_Eval
|
|
|
|
#define Tcl_Eval tcl_eval
|
|
|
|
|
|
|
|
static int
|
2006-06-21 04:32:22 -04:00
|
|
|
tcl_global_eval(Tcl_Interp *interp, const char *cmd)
|
2005-04-12 02:37:10 -04:00
|
|
|
{
|
|
|
|
char *buf = strdup(cmd);
|
2006-07-03 06:08:11 -04:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
Tcl_AllowExceptions(interp);
|
|
|
|
ret = Tcl_GlobalEval(interp, buf);
|
2005-04-12 02:37:10 -04:00
|
|
|
free(buf);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef Tcl_GlobalEval
|
|
|
|
#define Tcl_GlobalEval tcl_global_eval
|
|
|
|
|
2005-08-04 05:41:57 -04:00
|
|
|
/* Tcl_{Incr|Decr}RefCount for tcl7.x or earlier */
|
|
|
|
#if TCL_MAJOR_VERSION < 8
|
|
|
|
#define Tcl_IncrRefCount(obj) (1)
|
|
|
|
#define Tcl_DecrRefCount(obj) (1)
|
|
|
|
#endif
|
|
|
|
|
2005-08-01 05:47:54 -04:00
|
|
|
/* Tcl_GetStringResult for tcl7.x or earlier */
|
|
|
|
#if TCL_MAJOR_VERSION < 8
|
|
|
|
#define Tcl_GetStringResult(interp) ((interp)->result)
|
|
|
|
#endif
|
2005-04-12 02:37:10 -04:00
|
|
|
|
2005-08-01 21:25:01 -04:00
|
|
|
/* Tcl_[GS]etVar2Ex for tcl8.0 */
|
|
|
|
#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
|
|
|
|
static Tcl_Obj *
|
|
|
|
Tcl_GetVar2Ex(interp, name1, name2, flags)
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
CONST char *name1;
|
|
|
|
CONST char *name2;
|
|
|
|
int flags;
|
|
|
|
{
|
|
|
|
Tcl_Obj *nameObj1, *nameObj2 = NULL, *retObj;
|
|
|
|
|
2005-09-27 21:48:53 -04:00
|
|
|
nameObj1 = Tcl_NewStringObj((char*)name1, -1);
|
2005-08-01 21:25:01 -04:00
|
|
|
Tcl_IncrRefCount(nameObj1);
|
|
|
|
|
|
|
|
if (name2) {
|
2005-09-27 21:48:53 -04:00
|
|
|
nameObj2 = Tcl_NewStringObj((char*)name2, -1);
|
2005-08-01 21:25:01 -04:00
|
|
|
Tcl_IncrRefCount(nameObj2);
|
|
|
|
}
|
|
|
|
|
|
|
|
retObj = Tcl_ObjGetVar2(interp, nameObj1, nameObj2, flags);
|
|
|
|
|
|
|
|
if (name2) {
|
|
|
|
Tcl_DecrRefCount(nameObj2);
|
|
|
|
}
|
|
|
|
|
|
|
|
Tcl_DecrRefCount(nameObj1);
|
|
|
|
|
|
|
|
return retObj;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Tcl_Obj *
|
|
|
|
Tcl_SetVar2Ex(interp, name1, name2, newValObj, flags)
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
CONST char *name1;
|
|
|
|
CONST char *name2;
|
|
|
|
Tcl_Obj *newValObj;
|
|
|
|
int flags;
|
2005-09-27 21:48:53 -04:00
|
|
|
{
|
2005-08-01 21:25:01 -04:00
|
|
|
Tcl_Obj *nameObj1, *nameObj2 = NULL, *retObj;
|
|
|
|
|
2005-09-27 21:48:53 -04:00
|
|
|
nameObj1 = Tcl_NewStringObj((char*)name1, -1);
|
2005-08-01 21:25:01 -04:00
|
|
|
Tcl_IncrRefCount(nameObj1);
|
|
|
|
|
|
|
|
if (name2) {
|
2005-09-27 21:48:53 -04:00
|
|
|
nameObj2 = Tcl_NewStringObj((char*)name2, -1);
|
2005-08-01 21:25:01 -04:00
|
|
|
Tcl_IncrRefCount(nameObj2);
|
|
|
|
}
|
|
|
|
|
|
|
|
retObj = Tcl_ObjSetVar2(interp, nameObj1, nameObj2, newValObj, flags);
|
|
|
|
|
|
|
|
if (name2) {
|
|
|
|
Tcl_DecrRefCount(nameObj2);
|
|
|
|
}
|
|
|
|
|
|
|
|
Tcl_DecrRefCount(nameObj1);
|
|
|
|
|
|
|
|
return retObj;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1998-01-16 07:19:09 -05:00
|
|
|
/* from tkAppInit.c */
|
|
|
|
|
2004-08-29 01:12:00 -04:00
|
|
|
#if TCL_MAJOR_VERSION < 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 4)
|
|
|
|
# if !defined __MINGW32__ && !defined __BORLANDC__
|
1998-01-16 07:19:09 -05:00
|
|
|
/*
|
|
|
|
* The following variable is a special hack that is needed in order for
|
|
|
|
* Sun shared libraries to be used for Tcl.
|
|
|
|
*/
|
|
|
|
|
|
|
|
extern int matherr();
|
|
|
|
int *tclDummyMathPtr = (int *) matherr;
|
2004-08-29 01:12:00 -04:00
|
|
|
# endif
|
2000-05-13 12:13:31 -04:00
|
|
|
#endif
|
1998-01-16 07:19:09 -05:00
|
|
|
|
|
|
|
/*---- module TclTkLib ----*/
|
|
|
|
|
1999-08-13 01:37:52 -04:00
|
|
|
struct invoke_queue {
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
Tcl_Event ev;
|
1999-08-13 01:37:52 -04:00
|
|
|
int argc;
|
2004-05-01 12:09:54 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
Tcl_Obj **argv;
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
char **argv;
|
|
|
|
#endif
|
|
|
|
VALUE interp;
|
|
|
|
int *done;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
int safe_level;
|
2004-05-01 12:09:54 -04:00
|
|
|
VALUE result;
|
1999-08-13 01:37:52 -04:00
|
|
|
VALUE thread;
|
|
|
|
};
|
2003-11-07 16:39:36 -05:00
|
|
|
|
|
|
|
struct eval_queue {
|
|
|
|
Tcl_Event ev;
|
2004-05-01 12:09:54 -04:00
|
|
|
char *str;
|
|
|
|
int len;
|
|
|
|
VALUE interp;
|
|
|
|
int *done;
|
2003-11-07 16:39:36 -05:00
|
|
|
int safe_level;
|
2004-05-01 12:09:54 -04:00
|
|
|
VALUE result;
|
2003-11-07 16:39:36 -05:00
|
|
|
VALUE thread;
|
|
|
|
};
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
struct call_queue {
|
|
|
|
Tcl_Event ev;
|
|
|
|
VALUE (*func)();
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE interp;
|
|
|
|
int *done;
|
|
|
|
int safe_level;
|
|
|
|
VALUE result;
|
|
|
|
VALUE thread;
|
|
|
|
};
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
void
|
|
|
|
invoke_queue_mark(struct invoke_queue *q)
|
|
|
|
{
|
|
|
|
rb_gc_mark(q->interp);
|
|
|
|
rb_gc_mark(q->result);
|
|
|
|
rb_gc_mark(q->thread);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
eval_queue_mark(struct eval_queue *q)
|
|
|
|
{
|
|
|
|
rb_gc_mark(q->interp);
|
|
|
|
rb_gc_mark(q->result);
|
|
|
|
rb_gc_mark(q->thread);
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
void
|
|
|
|
call_queue_mark(struct call_queue *q)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i = 0; i < q->argc; i++) {
|
|
|
|
rb_gc_mark(q->argv[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
rb_gc_mark(q->interp);
|
|
|
|
rb_gc_mark(q->result);
|
|
|
|
rb_gc_mark(q->thread);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
static VALUE eventloop_thread;
|
2005-03-02 02:06:52 -05:00
|
|
|
static VALUE eventloop_stack;
|
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
static VALUE watchdog_thread;
|
2005-03-02 02:06:52 -05:00
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
Tcl_Interp *current_interp;
|
2005-03-02 02:06:52 -05:00
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 'event_loop_max' is a maximum events which the eventloop processes in one
|
|
|
|
* term of thread scheduling. 'no_event_tick' is the count-up value when
|
|
|
|
* there are no event for processing.
|
|
|
|
* 'timer_tick' is a limit of one term of thread scheduling.
|
|
|
|
* If 'timer_tick' == 0, then not use the timer for thread scheduling.
|
|
|
|
*/
|
2003-06-09 14:09:11 -04:00
|
|
|
#define DEFAULT_EVENT_LOOP_MAX 800/*counts*/
|
|
|
|
#define DEFAULT_NO_EVENT_TICK 10/*counts*/
|
|
|
|
#define DEFAULT_NO_EVENT_WAIT 20/*milliseconds ( 1 -- 999 ) */
|
|
|
|
#define WATCHDOG_INTERVAL 10/*milliseconds ( 1 -- 999 ) */
|
2003-07-28 21:24:32 -04:00
|
|
|
#define DEFAULT_TIMER_TICK 0/*milliseconds ( 0 -- 999 ) */
|
2003-10-14 11:25:45 -04:00
|
|
|
#define NO_THREAD_INTERRUPT_TIME 100/*milliseconds ( 1 -- 999 ) */
|
2003-06-09 14:09:11 -04:00
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
static int event_loop_max = DEFAULT_EVENT_LOOP_MAX;
|
|
|
|
static int no_event_tick = DEFAULT_NO_EVENT_TICK;
|
2003-06-09 14:09:11 -04:00
|
|
|
static int no_event_wait = DEFAULT_NO_EVENT_WAIT;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
static int timer_tick = DEFAULT_TIMER_TICK;
|
2003-06-09 11:50:24 -04:00
|
|
|
static int req_timer_tick = DEFAULT_TIMER_TICK;
|
|
|
|
static int run_timer_flag = 0;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
2003-07-28 21:24:32 -04:00
|
|
|
static int event_loop_wait_event = 0;
|
2003-07-29 11:39:59 -04:00
|
|
|
static int event_loop_abort_on_exc = 1;
|
2003-07-27 15:35:06 -04:00
|
|
|
static int loop_counter = 0;
|
2003-06-09 14:09:11 -04:00
|
|
|
|
2003-10-14 11:25:45 -04:00
|
|
|
static int check_rootwidget_flag = 0;
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
/* call ruby interpreter */
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-05-01 12:09:54 -04:00
|
|
|
static int ip_ruby_eval _((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST*));
|
|
|
|
static int ip_ruby_cmd _((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST*));
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
static int ip_ruby_eval _((ClientData, Tcl_Interp *, int, char **));
|
|
|
|
static int ip_ruby_cmd _((ClientData, Tcl_Interp *, int, char **));
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
#endif
|
1999-08-13 01:37:52 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
struct cmd_body_arg {
|
|
|
|
VALUE receiver;
|
|
|
|
ID method;
|
|
|
|
VALUE args;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*----------------------------*/
|
|
|
|
/* use Tcl internal functions */
|
|
|
|
/*----------------------------*/
|
|
|
|
#ifndef TCL_NAMESPACE_DEBUG
|
|
|
|
#define TCL_NAMESPACE_DEBUG 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if TCL_NAMESPACE_DEBUG
|
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
EXTERN struct TclIntStubs *tclIntStubsPtr;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*-- Tcl_GetCurrentNamespace --*/
|
2005-01-30 23:14:50 -05:00
|
|
|
#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION < 5
|
|
|
|
/* Tcl7.x doesn't have namespace support. */
|
|
|
|
/* Tcl8.5+ has definition of Tcl_GetCurrentNamespace() in tclDecls.h */
|
|
|
|
# ifndef Tcl_GetCurrentNamespace
|
2005-01-25 00:09:22 -05:00
|
|
|
EXTERN Tcl_Namespace * Tcl_GetCurrentNamespace _((Tcl_Interp *));
|
2005-01-30 23:14:50 -05:00
|
|
|
# endif
|
|
|
|
# if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS)
|
|
|
|
# ifndef Tcl_GetCurrentNamespace
|
|
|
|
# ifndef FunctionNum_of_GetCurrentNamespace
|
2005-03-02 02:06:52 -05:00
|
|
|
#define FunctionNum_of_GetCurrentNamespace 124
|
2005-01-30 23:14:50 -05:00
|
|
|
# endif
|
2005-03-02 02:06:52 -05:00
|
|
|
struct DummyTclIntStubs_for_GetCurrentNamespace {
|
|
|
|
int magic;
|
|
|
|
struct TclIntStubHooks *hooks;
|
|
|
|
void (*func[FunctionNum_of_GetCurrentNamespace])();
|
|
|
|
Tcl_Namespace * (*tcl_GetCurrentNamespace) _((Tcl_Interp *));
|
2005-01-30 23:14:50 -05:00
|
|
|
};
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2005-01-30 23:14:50 -05:00
|
|
|
#define Tcl_GetCurrentNamespace \
|
2005-03-02 02:06:52 -05:00
|
|
|
(((struct DummyTclIntStubs_for_GetCurrentNamespace *)tclIntStubsPtr)->tcl_GetCurrentNamespace)
|
2005-01-30 23:14:50 -05:00
|
|
|
# endif
|
|
|
|
# endif
|
2005-01-25 00:09:22 -05:00
|
|
|
#endif
|
|
|
|
|
2005-01-30 23:14:50 -05:00
|
|
|
/* namespace check */
|
|
|
|
/* ip_null_namespace(Tcl_Interp *interp) */
|
|
|
|
#if TCL_MAJOR_VERSION < 8
|
|
|
|
#define ip_null_namespace(interp) (0)
|
|
|
|
#else /* support namespace */
|
|
|
|
#define ip_null_namespace(interp) \
|
|
|
|
(Tcl_GetCurrentNamespace(interp) == (Tcl_Namespace *)NULL)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* rbtk_invalid_namespace(tcltkip *ptr) */
|
|
|
|
#if TCL_MAJOR_VERSION < 8
|
|
|
|
#define rbtk_invalid_namespace(ptr) (0)
|
|
|
|
#else /* support namespace */
|
|
|
|
#define rbtk_invalid_namespace(ptr) \
|
|
|
|
((ptr)->default_ns == (Tcl_Namespace*)NULL || Tcl_GetCurrentNamespace((ptr)->ip) != (ptr)->default_ns)
|
|
|
|
#endif
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/*-- Tcl_PopCallFrame & Tcl_PushCallFrame --*/
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
# ifndef CallFrame
|
|
|
|
typedef struct CallFrame {
|
|
|
|
Tcl_Namespace *nsPtr;
|
|
|
|
int dummy1;
|
|
|
|
int dummy2;
|
|
|
|
char *dummy3;
|
|
|
|
struct CallFrame *callerPtr;
|
|
|
|
struct CallFrame *callerVarPtr;
|
|
|
|
int level;
|
|
|
|
char *dummy7;
|
|
|
|
char *dummy8;
|
|
|
|
int dummy9;
|
|
|
|
char* dummy10;
|
|
|
|
} CallFrame;
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# if !defined(TclGetFrame) && !defined(TclGetFrame_TCL_DECLARED)
|
|
|
|
EXTERN int TclGetFrame _((Tcl_Interp *, CONST char *, CallFrame **));
|
|
|
|
# endif
|
|
|
|
# if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS)
|
|
|
|
# ifndef TclGetFrame
|
|
|
|
# ifndef FunctionNum_of_GetFrame
|
|
|
|
#define FunctionNum_of_GetFrame 32
|
|
|
|
# endif
|
|
|
|
struct DummyTclIntStubs_for_GetFrame {
|
|
|
|
int magic;
|
|
|
|
struct TclIntStubHooks *hooks;
|
|
|
|
void (*func[FunctionNum_of_GetFrame])();
|
|
|
|
int (*tclGetFrame) _((Tcl_Interp *, CONST char *, CallFrame **));
|
|
|
|
};
|
|
|
|
#define TclGetFrame \
|
|
|
|
(((struct DummyTclIntStubs_for_GetFrame *)tclIntStubsPtr)->tclGetFrame)
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# if !defined(Tcl_PopCallFrame) && !defined(Tcl_PopCallFrame_TCL_DECLARED)
|
|
|
|
EXTERN void Tcl_PopCallFrame _((Tcl_Interp *));
|
|
|
|
EXTERN int Tcl_PushCallFrame _((Tcl_Interp *, Tcl_CallFrame *, Tcl_Namespace *, int));
|
|
|
|
# endif
|
|
|
|
# if defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS)
|
|
|
|
# ifndef Tcl_PopCallFrame
|
|
|
|
# ifndef FunctionNum_of_PopCallFrame
|
|
|
|
#define FunctionNum_of_PopCallFrame 128
|
|
|
|
# endif
|
|
|
|
struct DummyTclIntStubs_for_PopCallFrame {
|
|
|
|
int magic;
|
|
|
|
struct TclIntStubHooks *hooks;
|
|
|
|
void (*func[FunctionNum_of_PopCallFrame])();
|
|
|
|
void (*tcl_PopCallFrame) _((Tcl_Interp *));
|
|
|
|
int (*tcl_PushCallFrame) _((Tcl_Interp *, Tcl_CallFrame *, Tcl_Namespace *, int));
|
|
|
|
};
|
|
|
|
|
|
|
|
#define Tcl_PopCallFrame \
|
|
|
|
(((struct DummyTclIntStubs_for_PopCallFrame *)tclIntStubsPtr)->tcl_PopCallFrame)
|
|
|
|
#define Tcl_PushCallFrame \
|
|
|
|
(((struct DummyTclIntStubs_for_PopCallFrame *)tclIntStubsPtr)->tcl_PushCallFrame)
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
|
|
|
|
#else /* Tcl7.x */
|
|
|
|
# ifndef CallFrame
|
|
|
|
typedef struct CallFrame {
|
|
|
|
Tcl_HashTable varTable;
|
|
|
|
int level;
|
|
|
|
int argc;
|
|
|
|
char **argv;
|
|
|
|
struct CallFrame *callerPtr;
|
|
|
|
struct CallFrame *callerVarPtr;
|
|
|
|
} CallFrame;
|
|
|
|
# endif
|
|
|
|
# ifndef Tcl_CallFrame
|
|
|
|
#define Tcl_CallFrame CallFrame
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# if !defined(TclGetFrame) && !defined(TclGetFrame_TCL_DECLARED)
|
|
|
|
EXTERN int TclGetFrame _((Tcl_Interp *, CONST char *, CallFrame **));
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# if !defined(Tcl_PopCallFrame) && !defined(Tcl_PopCallFrame_TCL_DECLARED)
|
|
|
|
typedef struct DummyInterp {
|
|
|
|
char *dummy1;
|
|
|
|
char *dummy2;
|
|
|
|
int dummy3;
|
|
|
|
Tcl_HashTable dummy4;
|
|
|
|
Tcl_HashTable dummy5;
|
|
|
|
Tcl_HashTable dummy6;
|
|
|
|
int numLevels;
|
|
|
|
int maxNestingDepth;
|
|
|
|
CallFrame *framePtr;
|
|
|
|
CallFrame *varFramePtr;
|
|
|
|
} DummyInterp;
|
|
|
|
|
|
|
|
static void
|
|
|
|
Tcl_PopCallFrame(interp)
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
{
|
|
|
|
DummyInterp *iPtr = (DummyInterp*)interp;
|
|
|
|
CallFrame *frame = iPtr->varFramePtr;
|
|
|
|
|
|
|
|
/* **** DUMMY **** */
|
|
|
|
iPtr->framePtr = frame.callerPtr;
|
|
|
|
iPtr->varFramePtr = frame.callerVarPtr;
|
|
|
|
|
|
|
|
return TCL_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* dummy */
|
|
|
|
#define Tcl_Namespace char
|
|
|
|
|
|
|
|
static int
|
|
|
|
Tcl_PushCallFrame(interp, framePtr, nsPtr, isProcCallFrame)
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
Tcl_CallFrame *framePtr;
|
|
|
|
Tcl_Namespace *nsPtr;
|
|
|
|
int isProcCallFrame;
|
|
|
|
{
|
|
|
|
DummyInterp *iPtr = (DummyInterp*)interp;
|
|
|
|
CallFrame *frame = (CallFrame *)framePtr;
|
|
|
|
|
|
|
|
/* **** DUMMY **** */
|
|
|
|
Tcl_InitHashTable(&frame.varTable, TCL_STRING_KEYS);
|
|
|
|
if (iPtr->varFramePtr != NULL) {
|
|
|
|
frame.level = iPtr->varFramePtr->level + 1;
|
|
|
|
} else {
|
|
|
|
frame.level = 1;
|
|
|
|
}
|
|
|
|
frame.callerPtr = iPtr->framePtr;
|
|
|
|
frame.callerVarPtr = iPtr->varFramePtr;
|
|
|
|
iPtr->framePtr = &frame;
|
|
|
|
iPtr->varFramePtr = &frame;
|
|
|
|
|
|
|
|
return TCL_OK;
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* TCL_NAMESPACE_DEBUG */
|
|
|
|
|
|
|
|
|
|
|
|
/*---- class TclTkIp ----*/
|
|
|
|
struct tcltkip {
|
|
|
|
Tcl_Interp *ip; /* the interpreter */
|
|
|
|
#if TCL_NAMESPACE_DEBUG
|
|
|
|
Tcl_Namespace *default_ns; /* default namespace */
|
|
|
|
#endif
|
|
|
|
int has_orig_exit; /* has original 'exit' command ? */
|
|
|
|
Tcl_CmdInfo orig_exit_info; /* command info of original 'exit' command */
|
|
|
|
int ref_count; /* reference count of rbtk_preserve_ip call */
|
|
|
|
int allow_ruby_exit; /* allow exiting ruby by 'exit' function */
|
|
|
|
int return_value; /* return value */
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct tcltkip *
|
|
|
|
get_ip(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr;
|
|
|
|
|
|
|
|
Data_Get_Struct(self, struct tcltkip, ptr);
|
|
|
|
if (ptr == 0) {
|
|
|
|
/* rb_raise(rb_eTypeError, "uninitialized TclTkIp"); */
|
|
|
|
return((struct tcltkip *)NULL);
|
|
|
|
}
|
|
|
|
if (ptr->ip == (Tcl_Interp*)NULL) {
|
|
|
|
/* rb_raise(rb_eRuntimeError, "deleted IP"); */
|
2005-07-21 18:05:04 -04:00
|
|
|
return((struct tcltkip *)NULL);
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2005-08-01 00:57:28 -04:00
|
|
|
static int
|
|
|
|
deleted_ip(ptr)
|
|
|
|
struct tcltkip *ptr;
|
|
|
|
{
|
|
|
|
if (!ptr || !ptr->ip || Tcl_InterpDeleted(ptr->ip)
|
|
|
|
#if TCL_NAMESPACE_DEBUG
|
|
|
|
|| rbtk_invalid_namespace(ptr)
|
|
|
|
#endif
|
|
|
|
) {
|
|
|
|
DUMP1("ip is deleted");
|
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
return Qfalse;
|
|
|
|
}
|
2005-01-30 23:14:50 -05:00
|
|
|
|
2004-09-12 12:05:59 -04:00
|
|
|
/* increment/decrement reference count of tcltkip */
|
|
|
|
static int
|
|
|
|
rbtk_preserve_ip(ptr)
|
|
|
|
struct tcltkip *ptr;
|
|
|
|
{
|
|
|
|
ptr->ref_count++;
|
2005-03-02 02:06:52 -05:00
|
|
|
if (ptr->ip == (Tcl_Interp*)NULL) {
|
|
|
|
/* deleted IP */
|
|
|
|
ptr->ref_count = 0;
|
|
|
|
} else {
|
|
|
|
Tcl_Preserve((ClientData)ptr->ip);
|
|
|
|
}
|
2004-09-12 12:05:59 -04:00
|
|
|
return(ptr->ref_count);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rbtk_release_ip(ptr)
|
|
|
|
struct tcltkip *ptr;
|
|
|
|
{
|
|
|
|
ptr->ref_count--;
|
|
|
|
if (ptr->ref_count < 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
ptr->ref_count = 0;
|
2005-03-02 02:06:52 -05:00
|
|
|
} else if (ptr->ip == (Tcl_Interp*)NULL) {
|
|
|
|
/* deleted IP */
|
|
|
|
ptr->ref_count = 0;
|
2004-09-12 12:05:59 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release((ClientData)ptr->ip);
|
2004-09-12 12:05:59 -04:00
|
|
|
}
|
|
|
|
return(ptr->ref_count);
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
static VALUE
|
|
|
|
#ifdef HAVE_STDARG_PROTOTYPES
|
|
|
|
create_ip_exc(VALUE interp, VALUE exc, const char *fmt, ...)
|
|
|
|
#else
|
|
|
|
create_ip_exc(interp, exc, fmt, va_alist)
|
|
|
|
VALUE interp:
|
|
|
|
VALUE exc;
|
|
|
|
const char *fmt;
|
|
|
|
va_dcl
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
char buf[BUFSIZ];
|
|
|
|
VALUE einfo;
|
|
|
|
struct tcltkip *ptr = get_ip(interp);
|
|
|
|
|
|
|
|
va_init_list(args,fmt);
|
|
|
|
vsnprintf(buf, BUFSIZ, fmt, args);
|
|
|
|
buf[BUFSIZ - 1] = '\0';
|
|
|
|
va_end(args);
|
|
|
|
einfo = rb_exc_new2(exc, buf);
|
|
|
|
rb_ivar_set(einfo, ID_at_interp, interp);
|
|
|
|
if (ptr) {
|
|
|
|
Tcl_ResetResult(ptr->ip);
|
|
|
|
}
|
|
|
|
|
|
|
|
return einfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* stub status */
|
|
|
|
static void
|
|
|
|
tcl_stubs_check()
|
|
|
|
{
|
|
|
|
if (!tcl_stubs_init_p()) {
|
|
|
|
int st = ruby_tcl_stubs_init();
|
|
|
|
switch(st) {
|
|
|
|
case TCLTK_STUBS_OK:
|
|
|
|
break;
|
|
|
|
case NO_TCL_DLL:
|
|
|
|
rb_raise(rb_eLoadError, "tcltklib: fail to open tcl_dll");
|
|
|
|
case NO_FindExecutable:
|
|
|
|
rb_raise(rb_eLoadError, "tcltklib: can't find Tcl_FindExecutable");
|
|
|
|
case NO_CreateInterp:
|
|
|
|
rb_raise(rb_eLoadError, "tcltklib: can't find Tcl_CreateInterp()");
|
|
|
|
case NO_DeleteInterp:
|
|
|
|
rb_raise(rb_eLoadError, "tcltklib: can't find Tcl_DeleteInterp()");
|
|
|
|
case FAIL_CreateInterp:
|
|
|
|
rb_raise(rb_eRuntimeError, "tcltklib: fail to create a new IP to call Tcl_InitStubs()");
|
|
|
|
case FAIL_Tcl_InitStubs:
|
|
|
|
rb_raise(rb_eRuntimeError, "tcltklib: fail to Tcl_InitStubs()");
|
|
|
|
default:
|
|
|
|
rb_raise(rb_eRuntimeError, "tcltklib: unknown error(%d) on ruby_tcl_stubs_init()", st);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
tcltkip_init_tk(interp)
|
|
|
|
VALUE interp;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(interp);
|
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
int st;
|
|
|
|
|
|
|
|
if (Tcl_IsSafe(ptr->ip)) {
|
|
|
|
DUMP1("Tk_SafeInit");
|
|
|
|
st = ruby_tk_stubs_safeinit(ptr->ip);
|
|
|
|
switch(st) {
|
|
|
|
case TCLTK_STUBS_OK:
|
|
|
|
break;
|
|
|
|
case NO_Tk_Init:
|
|
|
|
return rb_exc_new2(rb_eLoadError,
|
|
|
|
"tcltklib: can't find Tk_SafeInit()");
|
|
|
|
case FAIL_Tk_Init:
|
|
|
|
return create_ip_exc(interp, rb_eRuntimeError,
|
|
|
|
"tcltklib: fail to Tk_SafeInit(). %s",
|
|
|
|
Tcl_GetStringResult(ptr->ip));
|
|
|
|
case FAIL_Tk_InitStubs:
|
|
|
|
return create_ip_exc(interp, rb_eRuntimeError,
|
|
|
|
"tcltklib: fail to Tk_InitStubs(). %s",
|
|
|
|
Tcl_GetStringResult(ptr->ip));
|
|
|
|
default:
|
|
|
|
return create_ip_exc(interp, rb_eRuntimeError,
|
|
|
|
"tcltklib: unknown error(%d) on ruby_tk_stubs_safeinit", st);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
DUMP1("Tk_Init");
|
|
|
|
st = ruby_tk_stubs_init(ptr->ip);
|
|
|
|
switch(st) {
|
|
|
|
case TCLTK_STUBS_OK:
|
|
|
|
break;
|
|
|
|
case NO_Tk_Init:
|
|
|
|
return rb_exc_new2(rb_eLoadError,
|
|
|
|
"tcltklib: can't find Tk_Init()");
|
|
|
|
case FAIL_Tk_Init:
|
|
|
|
return create_ip_exc(interp, rb_eRuntimeError,
|
|
|
|
"tcltklib: fail to Tk_Init(). %s",
|
|
|
|
Tcl_GetStringResult(ptr->ip));
|
|
|
|
case FAIL_Tk_InitStubs:
|
|
|
|
return create_ip_exc(interp, rb_eRuntimeError,
|
|
|
|
"tcltklib: fail to Tk_InitStubs(). %s",
|
|
|
|
Tcl_GetStringResult(ptr->ip));
|
|
|
|
default:
|
|
|
|
return create_ip_exc(interp, rb_eRuntimeError,
|
|
|
|
"tcltklib: unknown error(%d) on ruby_tk_stubs_init", st);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
DUMP1("Tk_Init");
|
|
|
|
if (ruby_tk_stubs_init(ptr->ip) != TCLTK_STUBS_OK) {
|
|
|
|
return rb_exc_new2(rb_eRuntimeError, ptr->ip->result);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* treat excetiopn on Tcl side */
|
|
|
|
static VALUE rbtk_pending_exception;
|
2005-07-19 01:12:52 -04:00
|
|
|
static int rbtk_eventloop_depth = 0;
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
pending_exception_check0()
|
|
|
|
{
|
|
|
|
volatile VALUE exc = rbtk_pending_exception;
|
|
|
|
|
|
|
|
if (!NIL_P(exc) && rb_obj_is_kind_of(exc, rb_eException)) {
|
|
|
|
DUMP1("find a pending exception");
|
|
|
|
if (rbtk_eventloop_depth > 0) {
|
|
|
|
return 1; /* pending */
|
|
|
|
} else {
|
|
|
|
rbtk_pending_exception = Qnil;
|
2005-08-09 02:16:29 -04:00
|
|
|
|
|
|
|
if (rb_obj_is_kind_of(exc, eTkCallbackRetry)) {
|
|
|
|
DUMP1("pending_exception_check0: call rb_jump_tag(retry)");
|
|
|
|
rb_jump_tag(TAG_RETRY);
|
|
|
|
} else if (rb_obj_is_kind_of(exc, eTkCallbackRedo)) {
|
|
|
|
DUMP1("pending_exception_check0: call rb_jump_tag(redo)");
|
|
|
|
rb_jump_tag(TAG_REDO);
|
|
|
|
} else if (rb_obj_is_kind_of(exc, eTkCallbackThrow)) {
|
|
|
|
DUMP1("pending_exception_check0: call rb_jump_tag(throw)");
|
|
|
|
rb_jump_tag(TAG_THROW);
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_exc_raise(exc);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
pending_exception_check1(thr_crit_bup, ptr)
|
|
|
|
int thr_crit_bup;
|
|
|
|
struct tcltkip *ptr;
|
|
|
|
{
|
|
|
|
volatile VALUE exc = rbtk_pending_exception;
|
|
|
|
|
|
|
|
if (!NIL_P(exc) && rb_obj_is_kind_of(exc, rb_eException)) {
|
|
|
|
DUMP1("find a pending exception");
|
|
|
|
|
|
|
|
if (rbtk_eventloop_depth > 0) {
|
|
|
|
return 1; /* pending */
|
|
|
|
} else {
|
|
|
|
rbtk_pending_exception = Qnil;
|
|
|
|
|
|
|
|
if (ptr != (struct tcltkip *)NULL) {
|
|
|
|
/* Tcl_Release(ptr->ip); */
|
|
|
|
rbtk_release_ip(ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
2005-08-09 02:16:29 -04:00
|
|
|
if (rb_obj_is_kind_of(exc, eTkCallbackRetry)) {
|
|
|
|
DUMP1("pending_exception_check1: call rb_jump_tag(retry)");
|
|
|
|
rb_jump_tag(TAG_RETRY);
|
|
|
|
} else if (rb_obj_is_kind_of(exc, eTkCallbackRedo)) {
|
|
|
|
DUMP1("pending_exception_check1: call rb_jump_tag(redo)");
|
|
|
|
rb_jump_tag(TAG_REDO);
|
|
|
|
} else if (rb_obj_is_kind_of(exc, eTkCallbackThrow)) {
|
|
|
|
DUMP1("pending_exception_check1: call rb_jump_tag(throw)");
|
|
|
|
rb_jump_tag(TAG_THROW);
|
|
|
|
}
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_exc_raise(exc);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-09-12 12:05:59 -04:00
|
|
|
/* call original 'exit' command */
|
|
|
|
static void
|
|
|
|
call_original_exit(ptr, state)
|
|
|
|
struct tcltkip *ptr;
|
|
|
|
int state;
|
|
|
|
{
|
|
|
|
int thr_crit_bup;
|
|
|
|
Tcl_CmdInfo *info;
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
Tcl_Obj *state_obj;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!(ptr->has_orig_exit)) return;
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
Tcl_ResetResult(ptr->ip);
|
|
|
|
|
|
|
|
info = &(ptr->orig_exit_info);
|
|
|
|
|
|
|
|
/* memory allocation for arguments of this command */
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
state_obj = Tcl_NewIntObj(state);
|
|
|
|
Tcl_IncrRefCount(state_obj);
|
|
|
|
|
|
|
|
if (info->isNativeObjectProc) {
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Obj **argv;
|
|
|
|
argv = (Tcl_Obj **)ALLOC_N(Tcl_Obj *, 3);
|
|
|
|
argv[0] = Tcl_NewStringObj("exit", 4);
|
|
|
|
argv[1] = state_obj;
|
|
|
|
argv[2] = (Tcl_Obj *)NULL;
|
2004-09-12 12:05:59 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
ptr->return_value
|
|
|
|
= (*(info->objProc))(info->objClientData, ptr->ip, 2, argv);
|
2004-09-12 12:05:59 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
free(argv);
|
2004-09-12 12:05:59 -04:00
|
|
|
|
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* string interface */
|
|
|
|
char **argv;
|
|
|
|
argv = (char **)ALLOC_N(char *, 3);
|
|
|
|
argv[0] = "exit";
|
2005-07-28 05:14:59 -04:00
|
|
|
/* argv[1] = Tcl_GetString(state_obj); */
|
|
|
|
argv[1] = Tcl_GetStringFromObj(state_obj, (int*)NULL);
|
2004-10-11 00:51:21 -04:00
|
|
|
argv[2] = (char *)NULL;
|
2004-09-12 12:05:59 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
ptr->return_value = (*(info->proc))(info->clientData, ptr->ip,
|
|
|
|
2, (CONST84 char **)argv);
|
2004-09-12 12:05:59 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
free(argv);
|
2004-09-12 12:05:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Tcl_DecrRefCount(state_obj);
|
|
|
|
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
{
|
2004-10-11 00:51:21 -04:00
|
|
|
/* string interface */
|
|
|
|
char **argv;
|
|
|
|
argv = (char **)ALLOC_N(char *, 3);
|
|
|
|
argv[0] = "exit";
|
2006-08-31 07:56:42 -04:00
|
|
|
argv[1] = RSTRING_PTR(rb_fix2str(INT2NUM(state), 10));
|
2004-10-11 00:51:21 -04:00
|
|
|
argv[2] = (char *)NULL;
|
2004-09-12 12:05:59 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
ptr->return_value = (*(info->proc))(info->clientData, ptr->ip,
|
|
|
|
2, argv);
|
2004-09-12 12:05:59 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
free(argv);
|
2004-09-12 12:05:59 -04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
/* Tk_ThreadTimer */
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
static Tcl_TimerToken timer_token = (Tcl_TimerToken)NULL;
|
1999-01-19 23:59:39 -05:00
|
|
|
|
|
|
|
/* timer callback */
|
2002-04-01 01:21:24 -05:00
|
|
|
static void _timer_for_tcl _((ClientData));
|
1999-08-13 01:37:52 -04:00
|
|
|
static void
|
|
|
|
_timer_for_tcl(clientData)
|
|
|
|
ClientData clientData;
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
int thr_crit_bup;
|
|
|
|
|
2003-07-28 21:24:32 -04:00
|
|
|
/* struct invoke_queue *q, *tmp; */
|
|
|
|
/* VALUE thread; */
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2005-03-10 05:13:30 -05:00
|
|
|
DUMP1("call _timer_for_tcl");
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
Tcl_DeleteTimerHandler(timer_token);
|
2003-06-09 11:50:24 -04:00
|
|
|
|
|
|
|
run_timer_flag = 1;
|
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
if (timer_tick > 0) {
|
2005-07-28 05:14:59 -04:00
|
|
|
timer_token = Tcl_CreateTimerHandler(timer_tick, _timer_for_tcl,
|
|
|
|
(ClientData)0);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
timer_token = (Tcl_TimerToken)NULL;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
/* rb_thread_schedule(); */
|
2003-06-09 11:50:24 -04:00
|
|
|
/* tick_counter += event_loop_max; */
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
set_eventloop_tick(self, tick)
|
|
|
|
VALUE self;
|
|
|
|
VALUE tick;
|
|
|
|
{
|
|
|
|
int ttick = NUM2INT(tick);
|
2004-05-01 12:09:54 -04:00
|
|
|
int thr_crit_bup;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
2003-09-07 03:10:44 -04:00
|
|
|
rb_secure(4);
|
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
if (ttick < 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_raise(rb_eArgError,
|
|
|
|
"timer-tick parameter must be 0 or positive number");
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
/* delete old timer callback */
|
2005-07-28 05:14:59 -04:00
|
|
|
Tcl_DeleteTimerHandler(timer_token);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
2003-06-09 11:50:24 -04:00
|
|
|
timer_tick = req_timer_tick = ttick;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
if (timer_tick > 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* start timer callback */
|
2005-07-28 05:14:59 -04:00
|
|
|
timer_token = Tcl_CreateTimerHandler(timer_tick, _timer_for_tcl,
|
|
|
|
(ClientData)0);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
timer_token = (Tcl_TimerToken)NULL;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
return tick;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
get_eventloop_tick(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
return INT2NUM(timer_tick);
|
|
|
|
}
|
|
|
|
|
2003-08-29 04:34:14 -04:00
|
|
|
static VALUE
|
|
|
|
ip_set_eventloop_tick(self, tick)
|
|
|
|
VALUE self;
|
|
|
|
VALUE tick;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return get_eventloop_tick(self);
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
2003-08-29 04:34:14 -04:00
|
|
|
if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* slave IP */
|
|
|
|
return get_eventloop_tick(self);
|
2003-08-29 04:34:14 -04:00
|
|
|
}
|
|
|
|
return set_eventloop_tick(self, tick);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ip_get_eventloop_tick(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
return get_eventloop_tick(self);
|
|
|
|
}
|
|
|
|
|
2003-06-19 12:14:43 -04:00
|
|
|
static VALUE
|
|
|
|
set_no_event_wait(self, wait)
|
|
|
|
VALUE self;
|
|
|
|
VALUE wait;
|
|
|
|
{
|
|
|
|
int t_wait = NUM2INT(wait);
|
|
|
|
|
2003-09-07 03:10:44 -04:00
|
|
|
rb_secure(4);
|
|
|
|
|
2003-06-19 12:14:43 -04:00
|
|
|
if (t_wait <= 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_raise(rb_eArgError,
|
|
|
|
"no_event_wait parameter must be positive number");
|
2003-06-19 12:14:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
no_event_wait = t_wait;
|
|
|
|
|
|
|
|
return wait;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
get_no_event_wait(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
return INT2NUM(no_event_wait);
|
|
|
|
}
|
|
|
|
|
2003-08-29 04:34:14 -04:00
|
|
|
static VALUE
|
|
|
|
ip_set_no_event_wait(self, wait)
|
|
|
|
VALUE self;
|
|
|
|
VALUE wait;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return get_no_event_wait(self);
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
2003-08-29 04:34:14 -04:00
|
|
|
if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* slave IP */
|
|
|
|
return get_no_event_wait(self);
|
2003-08-29 04:34:14 -04:00
|
|
|
}
|
|
|
|
return set_no_event_wait(self, wait);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ip_get_no_event_wait(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
return get_no_event_wait(self);
|
|
|
|
}
|
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
static VALUE
|
|
|
|
set_eventloop_weight(self, loop_max, no_event)
|
|
|
|
VALUE self;
|
|
|
|
VALUE loop_max;
|
|
|
|
VALUE no_event;
|
|
|
|
{
|
|
|
|
int lpmax = NUM2INT(loop_max);
|
|
|
|
int no_ev = NUM2INT(no_event);
|
|
|
|
|
2003-09-07 03:10:44 -04:00
|
|
|
rb_secure(4);
|
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
if (lpmax <= 0 || no_ev <= 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_raise(rb_eArgError, "weight parameters must be positive numbers");
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
event_loop_max = lpmax;
|
|
|
|
no_event_tick = no_ev;
|
|
|
|
|
|
|
|
return rb_ary_new3(2, loop_max, no_event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
get_eventloop_weight(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
return rb_ary_new3(2, INT2NUM(event_loop_max), INT2NUM(no_event_tick));
|
|
|
|
}
|
|
|
|
|
2003-07-27 15:35:06 -04:00
|
|
|
static VALUE
|
2003-08-29 04:34:14 -04:00
|
|
|
ip_set_eventloop_weight(self, loop_max, no_event)
|
|
|
|
VALUE self;
|
|
|
|
VALUE loop_max;
|
|
|
|
VALUE no_event;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return get_eventloop_weight(self);
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
2003-08-29 04:34:14 -04:00
|
|
|
if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* slave IP */
|
|
|
|
return get_eventloop_weight(self);
|
2003-08-29 04:34:14 -04:00
|
|
|
}
|
|
|
|
return set_eventloop_weight(self, loop_max, no_event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ip_get_eventloop_weight(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
return get_eventloop_weight(self);
|
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
static VALUE
|
|
|
|
set_max_block_time(self, time)
|
|
|
|
VALUE self;
|
|
|
|
VALUE time;
|
|
|
|
{
|
|
|
|
struct Tcl_Time tcl_time;
|
|
|
|
VALUE divmod;
|
|
|
|
|
|
|
|
switch(TYPE(time)) {
|
|
|
|
case T_FIXNUM:
|
|
|
|
case T_BIGNUM:
|
2004-10-11 00:51:21 -04:00
|
|
|
/* time is micro-second value */
|
|
|
|
divmod = rb_funcall(time, rb_intern("divmod"), 1, LONG2NUM(1000000));
|
2006-09-02 10:42:08 -04:00
|
|
|
tcl_time.sec = NUM2LONG(RARRAY_PTR(divmod)[0]);
|
|
|
|
tcl_time.usec = NUM2LONG(RARRAY_PTR(divmod)[1]);
|
2004-10-11 00:51:21 -04:00
|
|
|
break;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
case T_FLOAT:
|
2004-10-11 00:51:21 -04:00
|
|
|
/* time is second value */
|
|
|
|
divmod = rb_funcall(time, rb_intern("divmod"), 1, INT2FIX(1));
|
2006-09-02 10:42:08 -04:00
|
|
|
tcl_time.sec = NUM2LONG(RARRAY_PTR(divmod)[0]);
|
|
|
|
tcl_time.usec = (long)(NUM2DBL(RARRAY_PTR(divmod)[1]) * 1000000);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
default:
|
2006-04-05 12:08:45 -04:00
|
|
|
{
|
|
|
|
VALUE tmp = rb_funcall(time, ID_inspect, 0, 0);
|
|
|
|
rb_raise(rb_eArgError, "invalid value for time: '%s'",
|
|
|
|
StringValuePtr(tmp));
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Tcl_SetMaxBlockTime(&tcl_time);
|
|
|
|
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
static VALUE
|
|
|
|
lib_evloop_thread_p(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
if (NIL_P(eventloop_thread)) {
|
|
|
|
return Qnil; /* no eventloop */
|
|
|
|
} else if (rb_thread_current() == eventloop_thread) {
|
|
|
|
return Qtrue; /* is eventloop */
|
|
|
|
} else {
|
|
|
|
return Qfalse; /* not eventloop */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-08-29 04:34:14 -04:00
|
|
|
static VALUE
|
|
|
|
lib_evloop_abort_on_exc(self)
|
2003-07-27 15:35:06 -04:00
|
|
|
VALUE self;
|
|
|
|
{
|
2003-07-29 11:39:59 -04:00
|
|
|
if (event_loop_abort_on_exc > 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qtrue;
|
2003-07-29 11:39:59 -04:00
|
|
|
} else if (event_loop_abort_on_exc == 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qfalse;
|
2003-07-29 11:39:59 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qnil;
|
2003-07-29 11:39:59 -04:00
|
|
|
}
|
2003-07-27 15:35:06 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2003-08-29 04:34:14 -04:00
|
|
|
ip_evloop_abort_on_exc(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
return lib_evloop_abort_on_exc(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
lib_evloop_abort_on_exc_set(self, val)
|
2003-07-27 15:35:06 -04:00
|
|
|
VALUE self, val;
|
|
|
|
{
|
|
|
|
rb_secure(4);
|
2003-07-29 11:39:59 -04:00
|
|
|
if (RTEST(val)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
event_loop_abort_on_exc = 1;
|
2004-05-01 12:09:54 -04:00
|
|
|
} else if (NIL_P(val)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
event_loop_abort_on_exc = -1;
|
2003-07-29 11:39:59 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
event_loop_abort_on_exc = 0;
|
2003-07-29 11:39:59 -04:00
|
|
|
}
|
2003-08-29 04:34:14 -04:00
|
|
|
return lib_evloop_abort_on_exc(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ip_evloop_abort_on_exc_set(self, val)
|
|
|
|
VALUE self, val;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
|
|
|
|
2003-09-07 03:10:44 -04:00
|
|
|
rb_secure(4);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return lib_evloop_abort_on_exc(self);
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
2003-08-29 04:34:14 -04:00
|
|
|
if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* slave IP */
|
|
|
|
return lib_evloop_abort_on_exc(self);
|
2003-08-29 04:34:14 -04:00
|
|
|
}
|
|
|
|
return lib_evloop_abort_on_exc_set(self, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
lib_num_of_mainwindows(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
2005-07-28 05:14:59 -04:00
|
|
|
if (tk_stubs_init_p()) {
|
|
|
|
return INT2FIX(Tk_GetNumMainWindows());
|
|
|
|
} else {
|
|
|
|
return INT2FIX(0);
|
|
|
|
}
|
2003-07-27 15:35:06 -04:00
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
static VALUE
|
|
|
|
call_DoOneEvent(flag_val)
|
|
|
|
VALUE flag_val;
|
|
|
|
{
|
|
|
|
int flag;
|
|
|
|
|
|
|
|
flag = FIX2INT(flag_val);
|
|
|
|
if (Tcl_DoOneEvent(flag)) {
|
|
|
|
return Qtrue;
|
|
|
|
} else {
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
eventloop_sleep(dummy)
|
|
|
|
VALUE dummy;
|
|
|
|
{
|
|
|
|
struct timeval t;
|
|
|
|
|
|
|
|
t.tv_sec = (time_t)0;
|
|
|
|
t.tv_usec = (time_t)(no_event_wait*1000.0);
|
|
|
|
|
|
|
|
#ifdef HAVE_NATIVETHREAD
|
|
|
|
if (!is_ruby_native_thread()) {
|
|
|
|
rb_bug("cross-thread violation on eventloop_sleep()");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
rb_thread_wait_for(t);
|
|
|
|
|
|
|
|
#ifdef HAVE_NATIVETHREAD
|
|
|
|
if (!is_ruby_native_thread()) {
|
|
|
|
rb_bug("cross-thread violation on eventloop_sleep()");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-14 11:25:45 -04:00
|
|
|
static int
|
2005-12-06 11:05:50 -05:00
|
|
|
lib_eventloop_core(check_root, update_flag, check_var, interp)
|
2003-10-14 11:25:45 -04:00
|
|
|
int check_root;
|
2004-05-01 12:09:54 -04:00
|
|
|
int update_flag;
|
2003-10-14 11:25:45 -04:00
|
|
|
int *check_var;
|
2005-12-06 11:05:50 -05:00
|
|
|
Tcl_Interp *interp;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
{
|
2004-09-14 04:01:55 -04:00
|
|
|
volatile VALUE current = eventloop_thread;
|
2003-10-14 11:25:45 -04:00
|
|
|
int found_event = 1;
|
2004-05-01 12:09:54 -04:00
|
|
|
int event_flag;
|
2003-07-27 15:35:06 -04:00
|
|
|
struct timeval t;
|
2004-05-01 12:09:54 -04:00
|
|
|
int thr_crit_bup;
|
2005-03-02 02:06:52 -05:00
|
|
|
int status;
|
|
|
|
int depth = rbtk_eventloop_depth;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
|
|
|
|
if (update_flag) DUMP1("update loop start!!");
|
2003-06-09 11:50:24 -04:00
|
|
|
|
2003-07-27 15:35:06 -04:00
|
|
|
t.tv_sec = (time_t)0;
|
|
|
|
t.tv_usec = (time_t)(no_event_wait*1000.0);
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
Tcl_DeleteTimerHandler(timer_token);
|
2003-07-27 15:35:06 -04:00
|
|
|
run_timer_flag = 0;
|
|
|
|
if (timer_tick > 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2005-07-28 05:14:59 -04:00
|
|
|
timer_token = Tcl_CreateTimerHandler(timer_tick, _timer_for_tcl,
|
|
|
|
(ClientData)0);
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2003-06-09 11:50:24 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
timer_token = (Tcl_TimerToken)NULL;
|
2003-07-27 15:35:06 -04:00
|
|
|
}
|
2003-06-09 11:50:24 -04:00
|
|
|
|
2003-07-27 15:35:06 -04:00
|
|
|
for(;;) {
|
2004-10-11 00:51:21 -04:00
|
|
|
if (rb_thread_alone()) {
|
|
|
|
DUMP1("no other thread");
|
|
|
|
event_loop_wait_event = 0;
|
|
|
|
|
|
|
|
if (update_flag) {
|
|
|
|
event_flag = update_flag | TCL_DONT_WAIT; /* for safety */
|
|
|
|
} else {
|
|
|
|
event_flag = TCL_ALL_EVENTS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (timer_tick == 0 && update_flag == 0) {
|
|
|
|
timer_tick = NO_THREAD_INTERRUPT_TIME;
|
2005-07-28 05:14:59 -04:00
|
|
|
timer_token = Tcl_CreateTimerHandler(timer_tick,
|
|
|
|
_timer_for_tcl,
|
|
|
|
(ClientData)0);
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (check_var != (int *)NULL) {
|
|
|
|
if (*check_var || !found_event) {
|
|
|
|
return found_event;
|
|
|
|
}
|
2005-12-06 11:05:50 -05:00
|
|
|
if (interp != (Tcl_Interp*)NULL
|
|
|
|
&& Tcl_InterpDeleted(interp)) {
|
|
|
|
/* IP for check_var is deleted */
|
|
|
|
return 0;
|
|
|
|
}
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* found_event = Tcl_DoOneEvent(event_flag); */
|
|
|
|
found_event = RTEST(rb_protect(call_DoOneEvent,
|
|
|
|
INT2FIX(event_flag), &status));
|
|
|
|
if (status) {
|
|
|
|
switch (status) {
|
|
|
|
case TAG_RAISE:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rbtk_pending_exception
|
|
|
|
= rb_exc_new2(rb_eException, "unknown exception");
|
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
rbtk_pending_exception = rb_errinfo();
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
if (!NIL_P(rbtk_pending_exception)) {
|
|
|
|
if (rbtk_eventloop_depth == 0) {
|
|
|
|
VALUE exc = rbtk_pending_exception;
|
2005-07-19 01:12:52 -04:00
|
|
|
rbtk_pending_exception = Qnil;
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_exc_raise(exc);
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TAG_FATAL:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_exc_raise(rb_exc_new2(rb_eFatal, "FATAL"));
|
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
rb_exc_raise(rb_errinfo());
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (depth != rbtk_eventloop_depth) {
|
|
|
|
DUMP2("DoOneEvent(1) abnormal exit!! %d",
|
|
|
|
rbtk_eventloop_depth);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (check_var != (int*)NULL && !NIL_P(rbtk_pending_exception)) {
|
|
|
|
DUMP1("exception on wait");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pending_exception_check0()) {
|
|
|
|
/* pending -> upper level */
|
|
|
|
return 0;
|
|
|
|
}
|
2004-10-11 00:51:21 -04:00
|
|
|
|
|
|
|
if (update_flag != 0) {
|
|
|
|
if (found_event) {
|
|
|
|
DUMP1("next update loop");
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
DUMP1("update complete");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
DUMP1("trap check");
|
|
|
|
if (rb_trap_pending) {
|
|
|
|
run_timer_flag = 0;
|
|
|
|
if (rb_prohibit_interrupt || check_var != (int*)NULL) {
|
|
|
|
/* pending or on wait command */
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
rb_trap_exec();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("check Root Widget");
|
2005-07-28 05:14:59 -04:00
|
|
|
if (check_root && tk_stubs_init_p() && Tk_GetNumMainWindows() == 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
run_timer_flag = 0;
|
2005-03-02 02:06:52 -05:00
|
|
|
if (rb_trap_pending) {
|
|
|
|
if (rb_prohibit_interrupt || check_var != (int*)NULL) {
|
|
|
|
/* pending or on wait command */
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
rb_trap_exec();
|
|
|
|
}
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loop_counter++ > 30000) {
|
|
|
|
/* fprintf(stderr, "loop_counter > 30000\n"); */
|
|
|
|
loop_counter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
int tick_counter;
|
|
|
|
|
|
|
|
DUMP1("there are other threads");
|
|
|
|
event_loop_wait_event = 1;
|
|
|
|
|
|
|
|
found_event = 1;
|
|
|
|
|
|
|
|
if (update_flag) {
|
|
|
|
event_flag = update_flag | TCL_DONT_WAIT; /* for safety */
|
|
|
|
} else {
|
|
|
|
event_flag = TCL_ALL_EVENTS | TCL_DONT_WAIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
timer_tick = req_timer_tick;
|
|
|
|
tick_counter = 0;
|
|
|
|
while(tick_counter < event_loop_max) {
|
|
|
|
if (check_var != (int *)NULL) {
|
|
|
|
if (*check_var || !found_event) {
|
|
|
|
return found_event;
|
|
|
|
}
|
2005-12-06 11:05:50 -05:00
|
|
|
if (interp != (Tcl_Interp*)NULL
|
|
|
|
&& Tcl_InterpDeleted(interp)) {
|
|
|
|
/* IP for check_var is deleted */
|
|
|
|
return 0;
|
|
|
|
}
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (NIL_P(eventloop_thread) || current == eventloop_thread) {
|
|
|
|
int st;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
/* st = Tcl_DoOneEvent(event_flag); */
|
|
|
|
st = RTEST(rb_protect(call_DoOneEvent,
|
|
|
|
INT2FIX(event_flag), &status));
|
|
|
|
if (status) {
|
|
|
|
switch (status) {
|
|
|
|
case TAG_RAISE:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rbtk_pending_exception
|
|
|
|
= rb_exc_new2(rb_eException,
|
|
|
|
"unknown exception");
|
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
rbtk_pending_exception = rb_errinfo();
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
if (!NIL_P(rbtk_pending_exception)) {
|
|
|
|
if (rbtk_eventloop_depth == 0) {
|
|
|
|
VALUE exc = rbtk_pending_exception;
|
2005-07-19 01:12:52 -04:00
|
|
|
rbtk_pending_exception = Qnil;
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_exc_raise(exc);
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TAG_FATAL:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_exc_raise(rb_exc_new2(rb_eFatal, "FATAL"));
|
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
rb_exc_raise(rb_errinfo());
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (depth != rbtk_eventloop_depth) {
|
|
|
|
DUMP2("DoOneEvent(2) abnormal exit!! %d",
|
|
|
|
rbtk_eventloop_depth);
|
2004-10-11 00:51:21 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
DUMP1("trap check");
|
|
|
|
if (rb_trap_pending) {
|
|
|
|
run_timer_flag = 0;
|
|
|
|
if (rb_prohibit_interrupt || check_var != (int*)NULL) {
|
|
|
|
/* pending or on wait command */
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
rb_trap_exec();
|
|
|
|
}
|
|
|
|
}
|
2004-10-11 00:51:21 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (check_var != (int*)NULL
|
|
|
|
&& !NIL_P(rbtk_pending_exception)) {
|
|
|
|
DUMP1("exception on wait");
|
|
|
|
return 0;
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (pending_exception_check0()) {
|
|
|
|
/* pending -> upper level */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (st) {
|
|
|
|
tick_counter++;
|
|
|
|
} else {
|
|
|
|
if (update_flag != 0) {
|
|
|
|
DUMP1("update complete");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
tick_counter += no_event_tick;
|
|
|
|
|
|
|
|
/* rb_thread_wait_for(t); */
|
|
|
|
rb_protect(eventloop_sleep, Qnil, &status);
|
|
|
|
|
|
|
|
if (status) {
|
|
|
|
switch (status) {
|
|
|
|
case TAG_RAISE:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rbtk_pending_exception
|
|
|
|
= rb_exc_new2(rb_eException,
|
|
|
|
"unknown exception");
|
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
rbtk_pending_exception = rb_errinfo();
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
if (!NIL_P(rbtk_pending_exception)) {
|
|
|
|
if (rbtk_eventloop_depth == 0) {
|
|
|
|
VALUE exc = rbtk_pending_exception;
|
2005-07-19 01:12:52 -04:00
|
|
|
rbtk_pending_exception = Qnil;
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_exc_raise(exc);
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TAG_FATAL:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_exc_raise(rb_exc_new2(rb_eFatal,
|
|
|
|
"FATAL"));
|
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
rb_exc_raise(rb_errinfo());
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
DUMP2("sleep eventloop %lx", current);
|
|
|
|
DUMP2("eventloop thread is %lx", eventloop_thread);
|
|
|
|
rb_thread_stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!NIL_P(watchdog_thread) && eventloop_thread != current) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
DUMP1("trap check");
|
|
|
|
if (rb_trap_pending) {
|
|
|
|
run_timer_flag = 0;
|
|
|
|
if (rb_prohibit_interrupt || check_var != (int*)NULL) {
|
|
|
|
/* pending or on wait command */
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
rb_trap_exec();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DUMP1("check Root Widget");
|
2005-07-28 05:14:59 -04:00
|
|
|
if (check_root && tk_stubs_init_p() && Tk_GetNumMainWindows() == 0) {
|
2005-03-02 02:06:52 -05:00
|
|
|
run_timer_flag = 0;
|
|
|
|
if (rb_trap_pending) {
|
|
|
|
if (rb_prohibit_interrupt || check_var != (int*)NULL) {
|
|
|
|
/* pending or on wait command */
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
rb_trap_exec();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
2004-10-11 00:51:21 -04:00
|
|
|
|
|
|
|
if (loop_counter++ > 30000) {
|
|
|
|
/* fprintf(stderr, "loop_counter > 30000\n"); */
|
|
|
|
loop_counter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (run_timer_flag) {
|
|
|
|
/*
|
|
|
|
DUMP1("timer interrupt");
|
|
|
|
run_timer_flag = 0;
|
|
|
|
*/
|
|
|
|
break; /* switch to other thread */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DUMP1("trap check & thread scheduling");
|
2006-12-31 18:12:35 -05:00
|
|
|
if (update_flag == 0) ; // TODO: CHECK_INTS
|
2004-05-01 12:09:54 -04:00
|
|
|
|
1999-08-13 01:37:52 -04:00
|
|
|
}
|
2003-10-14 11:25:45 -04:00
|
|
|
return 1;
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
1998-01-16 07:19:09 -05:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
struct evloop_params {
|
|
|
|
int check_root;
|
|
|
|
int update_flag;
|
|
|
|
int *check_var;
|
2005-12-06 11:05:50 -05:00
|
|
|
Tcl_Interp *interp;
|
|
|
|
int thr_crit_bup;
|
2005-03-02 02:06:52 -05:00
|
|
|
};
|
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
VALUE
|
2005-03-02 02:06:52 -05:00
|
|
|
lib_eventloop_main_core(args)
|
|
|
|
VALUE args;
|
2003-10-14 11:25:45 -04:00
|
|
|
{
|
2005-03-02 02:06:52 -05:00
|
|
|
struct evloop_params *params = (struct evloop_params *)args;
|
|
|
|
|
|
|
|
check_rootwidget_flag = params->check_root;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (lib_eventloop_core(params->check_root,
|
|
|
|
params->update_flag,
|
2005-12-06 11:05:50 -05:00
|
|
|
params->check_var,
|
|
|
|
params->interp)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qtrue;
|
2003-10-14 11:25:45 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qfalse;
|
2003-10-14 11:25:45 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
2005-03-02 02:06:52 -05:00
|
|
|
lib_eventloop_main(args)
|
|
|
|
VALUE args;
|
|
|
|
{
|
2005-11-06 23:47:08 -05:00
|
|
|
return lib_eventloop_main_core(args);
|
|
|
|
|
|
|
|
#if 0
|
2005-03-02 02:06:52 -05:00
|
|
|
volatile VALUE ret;
|
|
|
|
int status = 0;
|
|
|
|
|
2005-11-06 23:47:08 -05:00
|
|
|
ret = rb_protect(lib_eventloop_main_core, args, &status);
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
case TAG_RAISE:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rbtk_pending_exception
|
|
|
|
= rb_exc_new2(rb_eException, "unknown exception");
|
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
rbtk_pending_exception = rb_errinfo();
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
return Qnil;
|
|
|
|
|
|
|
|
case TAG_FATAL:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eFatal, "FATAL");
|
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
rbtk_pending_exception = rb_errinfo();
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2005-11-06 23:47:08 -05:00
|
|
|
#endif
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
lib_eventloop_ensure(args)
|
|
|
|
VALUE args;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
{
|
2005-03-02 02:06:52 -05:00
|
|
|
struct evloop_params *ptr = (struct evloop_params *)args;
|
|
|
|
volatile VALUE current_evloop = rb_thread_current();
|
|
|
|
|
|
|
|
DUMP2("eventloop_ensure: current-thread : %lx", current_evloop);
|
|
|
|
DUMP2("eventloop_ensure: eventloop-thread : %lx", eventloop_thread);
|
|
|
|
if (eventloop_thread != current_evloop) {
|
|
|
|
DUMP2("finish eventloop %lx (NOT current eventloop)", current_evloop);
|
2005-12-06 11:05:50 -05:00
|
|
|
|
|
|
|
rb_thread_critical = ptr->thr_crit_bup;
|
|
|
|
|
2006-04-21 02:22:43 -04:00
|
|
|
free(ptr);
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
2005-11-06 23:47:08 -05:00
|
|
|
while((eventloop_thread = rb_ary_pop(eventloop_stack))) {
|
2005-03-02 02:06:52 -05:00
|
|
|
DUMP2("eventloop-ensure: new eventloop-thread -> %lx",
|
|
|
|
eventloop_thread);
|
|
|
|
|
|
|
|
if (eventloop_thread == current_evloop) {
|
|
|
|
rbtk_eventloop_depth--;
|
|
|
|
DUMP2("eventloop %lx : back from recursive call", current_evloop);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-03-10 05:13:30 -05:00
|
|
|
if (NIL_P(eventloop_thread)) {
|
2005-07-28 05:14:59 -04:00
|
|
|
Tcl_DeleteTimerHandler(timer_token);
|
2005-03-10 05:13:30 -05:00
|
|
|
timer_token = (Tcl_TimerToken)NULL;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
if (RTEST(rb_funcall(eventloop_thread, ID_alive_p, 0, 0))) {
|
|
|
|
DUMP2("eventloop-enshure: wake up parent %lx", eventloop_thread);
|
|
|
|
rb_thread_wakeup(eventloop_thread);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2002-06-04 21:56:47 -04:00
|
|
|
}
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2005-12-06 11:05:50 -05:00
|
|
|
rb_thread_critical = ptr->thr_crit_bup;
|
|
|
|
|
2006-04-21 02:22:43 -04:00
|
|
|
free(ptr);
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
DUMP2("finish current eventloop %lx", current_evloop);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2005-12-06 11:05:50 -05:00
|
|
|
lib_eventloop_launcher(check_root, update_flag, check_var, interp)
|
2005-03-02 02:06:52 -05:00
|
|
|
int check_root;
|
|
|
|
int update_flag;
|
|
|
|
int *check_var;
|
2005-12-06 11:05:50 -05:00
|
|
|
Tcl_Interp *interp;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
{
|
2005-03-02 02:06:52 -05:00
|
|
|
volatile VALUE parent_evloop = eventloop_thread;
|
|
|
|
struct evloop_params *args = ALLOC(struct evloop_params);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
tcl_stubs_check();
|
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
eventloop_thread = rb_thread_current();
|
|
|
|
|
2005-08-08 12:18:29 -04:00
|
|
|
if (parent_evloop == eventloop_thread) {
|
|
|
|
DUMP2("eventloop: recursive call on %lx", parent_evloop);
|
|
|
|
rbtk_eventloop_depth++;
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!NIL_P(parent_evloop) && parent_evloop != eventloop_thread) {
|
|
|
|
DUMP2("wait for stop of parent_evloop %lx", parent_evloop);
|
|
|
|
while(!RTEST(rb_funcall(parent_evloop, ID_stop_p, 0))) {
|
|
|
|
DUMP2("parent_evloop %lx doesn't stop", parent_evloop);
|
|
|
|
rb_thread_run(parent_evloop);
|
|
|
|
}
|
|
|
|
DUMP1("succeed to stop parent");
|
|
|
|
}
|
|
|
|
|
|
|
|
rb_ary_push(eventloop_stack, parent_evloop);
|
|
|
|
|
2005-08-08 12:18:29 -04:00
|
|
|
DUMP3("tcltklib: eventloop-thread : %lx -> %lx\n",
|
2004-10-11 00:51:21 -04:00
|
|
|
parent_evloop, eventloop_thread);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
2005-12-06 11:05:50 -05:00
|
|
|
args->check_root = check_root;
|
|
|
|
args->update_flag = update_flag;
|
|
|
|
args->check_var = check_var;
|
|
|
|
args->interp = interp;
|
|
|
|
args->thr_crit_bup = rb_thread_critical;
|
|
|
|
|
|
|
|
rb_thread_critical = Qfalse;
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2005-11-06 23:47:08 -05:00
|
|
|
#if 0
|
2005-03-02 02:06:52 -05:00
|
|
|
return rb_ensure(lib_eventloop_main, (VALUE)args,
|
|
|
|
lib_eventloop_ensure, (VALUE)args);
|
2005-11-06 23:47:08 -05:00
|
|
|
#endif
|
|
|
|
return rb_ensure(lib_eventloop_main_core, (VALUE)args,
|
|
|
|
lib_eventloop_ensure, (VALUE)args);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
}
|
2002-04-01 01:21:24 -05:00
|
|
|
|
1998-01-16 07:19:09 -05:00
|
|
|
/* execute Tk_MainLoop */
|
|
|
|
static VALUE
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
lib_mainloop(argc, argv, self)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
1999-08-13 01:37:52 -04:00
|
|
|
VALUE self;
|
1998-01-16 07:19:09 -05:00
|
|
|
{
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
VALUE check_rootwidget;
|
|
|
|
|
|
|
|
if (rb_scan_args(argc, argv, "01", &check_rootwidget) == 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
check_rootwidget = Qtrue;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
} else if (RTEST(check_rootwidget)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
check_rootwidget = Qtrue;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
check_rootwidget = Qfalse;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
}
|
|
|
|
|
2005-12-06 11:05:50 -05:00
|
|
|
return lib_eventloop_launcher(RTEST(check_rootwidget), 0,
|
|
|
|
(int*)NULL, (Tcl_Interp*)NULL);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
}
|
|
|
|
|
2003-08-29 04:34:14 -04:00
|
|
|
static VALUE
|
|
|
|
ip_mainloop(argc, argv, self)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qnil;
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
2003-08-29 04:34:14 -04:00
|
|
|
if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* slave IP */
|
|
|
|
return Qnil;
|
2003-08-29 04:34:14 -04:00
|
|
|
}
|
|
|
|
return lib_mainloop(argc, argv, self);
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
static VALUE
|
|
|
|
watchdog_evloop_launcher(check_rootwidget)
|
|
|
|
VALUE check_rootwidget;
|
|
|
|
{
|
2005-12-06 11:05:50 -05:00
|
|
|
return lib_eventloop_launcher(RTEST(check_rootwidget), 0,
|
|
|
|
(int*)NULL, (Tcl_Interp*)NULL);
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#define EVLOOP_WAKEUP_CHANCE 3
|
|
|
|
|
|
|
|
static VALUE
|
2002-06-04 21:56:47 -04:00
|
|
|
lib_watchdog_core(check_rootwidget)
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
VALUE check_rootwidget;
|
2002-06-04 21:56:47 -04:00
|
|
|
{
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
VALUE evloop;
|
2003-07-27 15:35:06 -04:00
|
|
|
int prev_val = -1;
|
2003-07-28 21:24:32 -04:00
|
|
|
int chance = 0;
|
2003-07-28 21:45:33 -04:00
|
|
|
int check = RTEST(check_rootwidget);
|
2003-07-28 21:24:32 -04:00
|
|
|
struct timeval t0, t1;
|
2003-06-09 14:09:11 -04:00
|
|
|
|
2003-07-28 21:24:32 -04:00
|
|
|
t0.tv_sec = (time_t)0;
|
|
|
|
t0.tv_usec = (time_t)((NO_THREAD_INTERRUPT_TIME)*1000.0);
|
|
|
|
t1.tv_sec = (time_t)0;
|
|
|
|
t1.tv_usec = (time_t)((WATCHDOG_INTERVAL)*1000.0);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
|
|
|
/* check other watchdog thread */
|
2005-03-02 02:06:52 -05:00
|
|
|
if (!NIL_P(watchdog_thread)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
if (RTEST(rb_funcall(watchdog_thread, ID_stop_p, 0))) {
|
|
|
|
rb_funcall(watchdog_thread, ID_kill, 0);
|
|
|
|
} else {
|
|
|
|
return Qnil;
|
|
|
|
}
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
}
|
|
|
|
watchdog_thread = rb_thread_current();
|
|
|
|
|
|
|
|
/* watchdog start */
|
|
|
|
do {
|
2005-03-02 02:06:52 -05:00
|
|
|
if (NIL_P(eventloop_thread)
|
|
|
|
|| (loop_counter == prev_val && chance >= EVLOOP_WAKEUP_CHANCE)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* start new eventloop thread */
|
|
|
|
DUMP2("eventloop thread %lx is sleeping or dead",
|
|
|
|
eventloop_thread);
|
2005-03-02 02:06:52 -05:00
|
|
|
evloop = rb_thread_create(watchdog_evloop_launcher,
|
2004-10-11 00:51:21 -04:00
|
|
|
(void*)&check_rootwidget);
|
|
|
|
DUMP2("create new eventloop thread %lx", evloop);
|
|
|
|
loop_counter = -1;
|
|
|
|
chance = 0;
|
|
|
|
rb_thread_run(evloop);
|
|
|
|
} else {
|
2005-03-02 02:06:52 -05:00
|
|
|
prev_val = loop_counter;
|
|
|
|
if (RTEST(rb_funcall(eventloop_thread, ID_stop_p, 0))) {
|
|
|
|
++chance;
|
|
|
|
} else {
|
|
|
|
chance = 0;
|
|
|
|
}
|
2004-10-11 00:51:21 -04:00
|
|
|
if (event_loop_wait_event) {
|
|
|
|
rb_thread_wait_for(t0);
|
|
|
|
} else {
|
|
|
|
rb_thread_wait_for(t1);
|
|
|
|
}
|
|
|
|
/* rb_thread_schedule(); */
|
|
|
|
}
|
2005-07-28 05:14:59 -04:00
|
|
|
} while(!check || !tk_stubs_init_p() || Tk_GetNumMainWindows() != 0);
|
1999-01-19 23:59:39 -05:00
|
|
|
|
1998-01-16 07:19:09 -05:00
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
2002-06-04 21:56:47 -04:00
|
|
|
VALUE
|
|
|
|
lib_watchdog_ensure(arg)
|
|
|
|
VALUE arg;
|
|
|
|
{
|
2005-03-02 02:06:52 -05:00
|
|
|
eventloop_thread = Qnil; /* stop eventloops */
|
2002-06-04 21:56:47 -04:00
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
lib_mainloop_watchdog(argc, argv, self)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
VALUE check_rootwidget;
|
|
|
|
|
|
|
|
if (rb_scan_args(argc, argv, "01", &check_rootwidget) == 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
check_rootwidget = Qtrue;
|
2002-06-04 21:56:47 -04:00
|
|
|
} else if (RTEST(check_rootwidget)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
check_rootwidget = Qtrue;
|
2002-06-04 21:56:47 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
check_rootwidget = Qfalse;
|
2002-06-04 21:56:47 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return rb_ensure(lib_watchdog_core, check_rootwidget,
|
2004-10-11 00:51:21 -04:00
|
|
|
lib_watchdog_ensure, Qnil);
|
2002-06-04 21:56:47 -04:00
|
|
|
}
|
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
static VALUE
|
2003-08-29 04:34:14 -04:00
|
|
|
ip_mainloop_watchdog(argc, argv, self)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qnil;
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
2003-08-29 04:34:14 -04:00
|
|
|
if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* slave IP */
|
|
|
|
return Qnil;
|
2003-08-29 04:34:14 -04:00
|
|
|
}
|
|
|
|
return lib_mainloop_watchdog(argc, argv, self);
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
/* thread-safe(?) interaction between Ruby and Tk */
|
|
|
|
struct thread_call_proc_arg {
|
|
|
|
VALUE proc;
|
|
|
|
int *done;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
_thread_call_proc_arg_mark(struct thread_call_proc_arg *q)
|
|
|
|
{
|
|
|
|
rb_gc_mark(q->proc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
_thread_call_proc_core(arg)
|
|
|
|
VALUE arg;
|
|
|
|
{
|
|
|
|
struct thread_call_proc_arg *q = (struct thread_call_proc_arg*)arg;
|
|
|
|
return rb_funcall(q->proc, ID_call, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
_thread_call_proc_ensure(arg)
|
|
|
|
VALUE arg;
|
|
|
|
{
|
|
|
|
struct thread_call_proc_arg *q = (struct thread_call_proc_arg*)arg;
|
|
|
|
*(q->done) = 1;
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
_thread_call_proc(arg)
|
|
|
|
VALUE arg;
|
|
|
|
{
|
|
|
|
struct thread_call_proc_arg *q = (struct thread_call_proc_arg*)arg;
|
|
|
|
|
|
|
|
return rb_ensure(_thread_call_proc_core, (VALUE)q,
|
|
|
|
_thread_call_proc_ensure, (VALUE)q);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
_thread_call_proc_value(th)
|
|
|
|
VALUE th;
|
|
|
|
{
|
|
|
|
return rb_funcall(th, ID_value, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
lib_thread_callback(argc, argv, self)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
struct thread_call_proc_arg *q;
|
|
|
|
VALUE proc, th, ret;
|
|
|
|
int status, foundEvent;
|
|
|
|
|
|
|
|
if (rb_scan_args(argc, argv, "01", &proc) == 0) {
|
|
|
|
proc = rb_block_proc();
|
|
|
|
}
|
|
|
|
|
|
|
|
q = (struct thread_call_proc_arg *)ALLOC(struct thread_call_proc_arg);
|
|
|
|
q->proc = proc;
|
|
|
|
q->done = (int*)ALLOC(int);
|
|
|
|
*(q->done) = 0;
|
|
|
|
|
|
|
|
/* create call-proc thread */
|
|
|
|
th = rb_thread_create(_thread_call_proc, (void*)q);
|
|
|
|
|
|
|
|
rb_thread_schedule();
|
|
|
|
|
|
|
|
/* start sub-eventloop */
|
2005-12-06 11:05:50 -05:00
|
|
|
foundEvent = RTEST(lib_eventloop_launcher(/* not check root-widget */0, 0,
|
|
|
|
q->done, (Tcl_Interp*)NULL));
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
if (RTEST(rb_funcall(th, ID_alive_p, 0))) {
|
|
|
|
rb_funcall(th, ID_kill, 0);
|
|
|
|
ret = Qnil;
|
|
|
|
} else {
|
|
|
|
ret = rb_protect(_thread_call_proc_value, th, &status);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(q->done);
|
|
|
|
free(q);
|
|
|
|
|
|
|
|
if (NIL_P(rbtk_pending_exception)) {
|
2006-12-31 18:12:35 -05:00
|
|
|
/* return rb_errinfo(); */
|
2005-03-02 02:06:52 -05:00
|
|
|
if (status) {
|
2006-12-31 18:12:35 -05:00
|
|
|
rb_exc_raise(rb_errinfo());
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
VALUE exc = rbtk_pending_exception;
|
|
|
|
rbtk_pending_exception = Qnil;
|
|
|
|
/* return exc; */
|
|
|
|
rb_exc_raise(exc);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* do_one_event */
|
2003-08-29 04:34:14 -04:00
|
|
|
static VALUE
|
|
|
|
lib_do_one_event_core(argc, argv, self, is_ip)
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE self;
|
2003-08-29 04:34:14 -04:00
|
|
|
int is_ip;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
volatile VALUE vflags;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
int flags;
|
2003-11-07 16:39:36 -05:00
|
|
|
int found_event;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
2005-07-12 23:47:05 -04:00
|
|
|
if (!NIL_P(eventloop_thread)) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_raise(rb_eRuntimeError, "eventloop is already running");
|
|
|
|
}
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
tcl_stubs_check();
|
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
if (rb_scan_args(argc, argv, "01", &vflags) == 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
flags = TCL_ALL_EVENTS | TCL_DONT_WAIT;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
Check_Type(vflags, T_FIXNUM);
|
|
|
|
flags = FIX2INT(vflags);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
}
|
2003-09-07 03:10:44 -04:00
|
|
|
|
|
|
|
if (rb_safe_level() >= 4 || (rb_safe_level() >=1 && OBJ_TAINTED(vflags))) {
|
|
|
|
flags |= TCL_DONT_WAIT;
|
|
|
|
}
|
|
|
|
|
2003-08-29 04:34:14 -04:00
|
|
|
if (is_ip) {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* check IP */
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qfalse;
|
|
|
|
}
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
|
|
|
|
/* slave IP */
|
|
|
|
flags |= TCL_DONT_WAIT;
|
|
|
|
}
|
2003-08-29 04:34:14 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* found_event = Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT); */
|
|
|
|
found_event = Tcl_DoOneEvent(flags);
|
2003-11-07 16:39:36 -05:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (pending_exception_check0()) {
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
|
2003-11-07 16:39:36 -05:00
|
|
|
if (found_event) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qtrue;
|
2003-06-19 12:14:43 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qfalse;
|
2003-06-19 12:14:43 -04:00
|
|
|
}
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
}
|
|
|
|
|
2003-08-29 04:34:14 -04:00
|
|
|
static VALUE
|
|
|
|
lib_do_one_event(argc, argv, self)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
2002-08-19 01:56:09 -04:00
|
|
|
VALUE self;
|
|
|
|
{
|
2003-08-29 04:34:14 -04:00
|
|
|
return lib_do_one_event_core(argc, argv, self, 0);
|
|
|
|
}
|
2002-08-19 01:56:09 -04:00
|
|
|
|
2003-08-29 04:34:14 -04:00
|
|
|
static VALUE
|
|
|
|
ip_do_one_event(argc, argv, self)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
return lib_do_one_event_core(argc, argv, self, 0);
|
2002-08-19 01:56:09 -04:00
|
|
|
}
|
|
|
|
|
2003-08-29 04:34:14 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
static void
|
|
|
|
ip_set_exc_message(interp, exc)
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
VALUE exc;
|
|
|
|
{
|
|
|
|
char *buf;
|
|
|
|
Tcl_DString dstr;
|
|
|
|
volatile VALUE msg;
|
|
|
|
int thr_crit_bup;
|
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION > 0)
|
|
|
|
volatile VALUE enc;
|
|
|
|
Tcl_Encoding encoding;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
msg = rb_funcall(exc, ID_message, 0, 0);
|
2006-04-05 12:08:45 -04:00
|
|
|
StringValue(msg);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION > 0)
|
2005-08-01 06:09:28 -04:00
|
|
|
enc = rb_attr_get(exc, ID_at_enc);
|
|
|
|
if (NIL_P(enc)) {
|
|
|
|
enc = rb_attr_get(msg, ID_at_enc);
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
if (NIL_P(enc)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
encoding = (Tcl_Encoding)NULL;
|
2004-05-01 12:09:54 -04:00
|
|
|
} else if (TYPE(enc) == T_STRING) {
|
2006-08-31 07:56:42 -04:00
|
|
|
encoding = Tcl_GetEncoding(interp, RSTRING_PTR(enc));
|
2004-05-01 12:09:54 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
enc = rb_funcall(enc, ID_to_s, 0, 0);
|
2006-08-31 07:56:42 -04:00
|
|
|
encoding = Tcl_GetEncoding(interp, RSTRING_PTR(enc));
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* to avoid a garbled error message dialog */
|
2006-08-31 07:56:42 -04:00
|
|
|
buf = ALLOC_N(char, (RSTRING_LEN(msg))+1);
|
|
|
|
memcpy(buf, RSTRING_PTR(msg), RSTRING_LEN(msg));
|
|
|
|
buf[RSTRING_LEN(msg)] = 0;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
Tcl_DStringInit(&dstr);
|
|
|
|
Tcl_DStringFree(&dstr);
|
2006-08-31 07:56:42 -04:00
|
|
|
Tcl_ExternalToUtfDString(encoding, buf, RSTRING_LEN(msg), &dstr);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
Tcl_AppendResult(interp, Tcl_DStringValue(&dstr), (char*)NULL);
|
|
|
|
DUMP2("error message:%s", Tcl_DStringValue(&dstr));
|
2005-04-22 03:57:26 -04:00
|
|
|
Tcl_DStringFree(&dstr);
|
2004-05-01 12:09:54 -04:00
|
|
|
free(buf);
|
|
|
|
|
|
|
|
#else /* TCL_VERSION <= 8.0 */
|
2006-08-31 07:56:42 -04:00
|
|
|
Tcl_AppendResult(interp, RSTRING_PTR(msg), (char*)NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
TkStringValue(obj)
|
|
|
|
VALUE obj;
|
|
|
|
{
|
|
|
|
switch(TYPE(obj)) {
|
|
|
|
case T_STRING:
|
2004-10-11 00:51:21 -04:00
|
|
|
return obj;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
case T_NIL:
|
2004-10-11 00:51:21 -04:00
|
|
|
return rb_str_new2("");
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
case T_TRUE:
|
2004-10-11 00:51:21 -04:00
|
|
|
return rb_str_new2("1");
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
case T_FALSE:
|
2004-10-11 00:51:21 -04:00
|
|
|
return rb_str_new2("0");
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
case T_ARRAY:
|
2004-10-11 00:51:21 -04:00
|
|
|
return rb_funcall(obj, ID_join, 1, rb_str_new2(" "));
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
default:
|
2004-10-11 00:51:21 -04:00
|
|
|
if (rb_respond_to(obj, ID_to_s)) {
|
|
|
|
return rb_funcall(obj, ID_to_s, 0, 0);
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return rb_funcall(obj, ID_inspect, 0, 0);
|
|
|
|
}
|
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
static int
|
|
|
|
tcl_protect_core(interp, proc, data) /* should not raise exception */
|
|
|
|
Tcl_Interp *interp;
|
2005-08-05 04:12:53 -04:00
|
|
|
VALUE (*proc)();
|
|
|
|
VALUE data;
|
2002-03-08 02:03:09 -05:00
|
|
|
{
|
2005-08-06 12:27:12 -04:00
|
|
|
volatile VALUE ret, exc = Qnil;
|
2004-05-01 12:09:54 -04:00
|
|
|
int status = 0;
|
2005-08-05 04:12:53 -04:00
|
|
|
int thr_crit_bup = rb_thread_critical;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-06-12 11:25:49 -04:00
|
|
|
rb_thread_critical = Qfalse;
|
2005-08-05 04:12:53 -04:00
|
|
|
ret = rb_protect(proc, data, &status);
|
2004-06-12 11:25:49 -04:00
|
|
|
rb_thread_critical = Qtrue;
|
2004-05-01 12:09:54 -04:00
|
|
|
if (status) {
|
2005-08-05 07:22:51 -04:00
|
|
|
char *buf;
|
|
|
|
VALUE old_gc, type, str;
|
2004-10-11 00:51:21 -04:00
|
|
|
|
|
|
|
old_gc = rb_gc_disable();
|
|
|
|
|
|
|
|
switch(status) {
|
|
|
|
case TAG_RETURN:
|
2005-08-05 07:22:51 -04:00
|
|
|
type = eTkCallbackReturn;
|
|
|
|
goto error;
|
2004-10-11 00:51:21 -04:00
|
|
|
case TAG_BREAK:
|
2005-08-05 07:22:51 -04:00
|
|
|
type = eTkCallbackBreak;
|
|
|
|
goto error;
|
2004-10-11 00:51:21 -04:00
|
|
|
case TAG_NEXT:
|
2005-08-05 07:22:51 -04:00
|
|
|
type = eTkCallbackContinue;
|
|
|
|
goto error;
|
|
|
|
error:
|
|
|
|
str = rb_str_new2("LocalJumpError: ");
|
2006-12-31 18:12:35 -05:00
|
|
|
rb_str_append(str, rb_obj_as_string(rb_errinfo()));
|
2005-08-06 12:27:12 -04:00
|
|
|
exc = rb_exc_new3(type, str);
|
2004-10-11 00:51:21 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case TAG_RETRY:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-08-09 02:16:29 -04:00
|
|
|
DUMP1("rb_protect: retry");
|
|
|
|
exc = rb_exc_new2(eTkCallbackRetry, "retry jump error");
|
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
exc = rb_errinfo();
|
2005-08-09 02:16:29 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
case TAG_REDO:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-08-09 02:16:29 -04:00
|
|
|
DUMP1("rb_protect: redo");
|
|
|
|
exc = rb_exc_new2(eTkCallbackRedo, "redo jump error");
|
2004-10-11 00:51:21 -04:00
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
exc = rb_errinfo();
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TAG_RAISE:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-08-06 12:27:12 -04:00
|
|
|
exc = rb_exc_new2(rb_eException, "unknown exception");
|
2004-10-11 00:51:21 -04:00
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
exc = rb_errinfo();
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
case TAG_FATAL:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-08-06 12:27:12 -04:00
|
|
|
exc = rb_exc_new2(rb_eFatal, "FATAL");
|
2005-03-02 02:06:52 -05:00
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
exc = rb_errinfo();
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
case TAG_THROW:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-08-09 02:16:29 -04:00
|
|
|
DUMP1("rb_protect: throw");
|
|
|
|
exc = rb_exc_new2(eTkCallbackThrow, "throw jump error");
|
2004-10-11 00:51:21 -04:00
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
exc = rb_errinfo();
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
buf = ALLOC_N(char, 256);
|
|
|
|
sprintf(buf, "unknown loncaljmp status %d", status);
|
2005-08-06 12:27:12 -04:00
|
|
|
exc = rb_exc_new2(rb_eException, buf);
|
2004-10-11 00:51:21 -04:00
|
|
|
free(buf);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (old_gc == Qfalse) rb_gc_enable();
|
|
|
|
|
|
|
|
ret = Qnil;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
2005-08-05 04:12:53 -04:00
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
Tcl_ResetResult(interp);
|
2005-08-05 05:20:13 -04:00
|
|
|
|
|
|
|
/* status check */
|
2005-08-06 12:27:12 -04:00
|
|
|
if (!NIL_P(exc)) {
|
|
|
|
volatile VALUE eclass = rb_obj_class(exc);
|
2005-08-05 05:20:13 -04:00
|
|
|
volatile VALUE backtrace;
|
|
|
|
|
2005-08-08 12:18:29 -04:00
|
|
|
DUMP1("(failed)");
|
|
|
|
|
2005-08-05 05:20:13 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
DUMP1("set backtrace");
|
2005-08-06 12:27:12 -04:00
|
|
|
if (!NIL_P(backtrace = rb_funcall(exc, ID_backtrace, 0, 0))) {
|
|
|
|
backtrace = rb_ary_join(backtrace, rb_str_new2("\n"));
|
|
|
|
Tcl_AddErrorInfo(interp, StringValuePtr(backtrace));
|
2005-08-05 05:20:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
ip_set_exc_message(interp, exc);
|
|
|
|
|
|
|
|
if (eclass == eTkCallbackReturn)
|
2005-08-05 05:20:13 -04:00
|
|
|
return TCL_RETURN;
|
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
if (eclass == eTkCallbackBreak)
|
2005-08-05 05:20:13 -04:00
|
|
|
return TCL_BREAK;
|
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
if (eclass == eTkCallbackContinue)
|
2005-08-05 05:20:13 -04:00
|
|
|
return TCL_CONTINUE;
|
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
if (eclass == rb_eSystemExit || eclass == rb_eInterrupt) {
|
|
|
|
rbtk_pending_exception = exc;
|
2005-08-05 05:20:13 -04:00
|
|
|
return TCL_RETURN;
|
2005-08-06 12:27:12 -04:00
|
|
|
}
|
2005-08-05 05:20:13 -04:00
|
|
|
|
2005-08-09 02:16:29 -04:00
|
|
|
if (rb_obj_is_kind_of(exc, eTkLocalJumpError)) {
|
|
|
|
rbtk_pending_exception = exc;
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
if (rb_obj_is_kind_of(exc, eLocalJumpError)) {
|
|
|
|
VALUE reason = rb_ivar_get(exc, ID_at_reason);
|
2005-08-05 05:20:13 -04:00
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
if (TYPE(reason) == T_SYMBOL) {
|
|
|
|
if (SYM2ID(reason) == ID_return)
|
|
|
|
return TCL_RETURN;
|
2005-08-05 05:20:13 -04:00
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
if (SYM2ID(reason) == ID_break)
|
|
|
|
return TCL_BREAK;
|
2005-08-05 05:20:13 -04:00
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
if (SYM2ID(reason) == ID_next)
|
|
|
|
return TCL_CONTINUE;
|
2005-08-05 05:20:13 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
return TCL_ERROR;
|
2005-08-05 05:20:13 -04:00
|
|
|
}
|
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
/* result must be string or nil */
|
|
|
|
if (!NIL_P(ret)) {
|
|
|
|
/* copy result to the tcl interpreter */
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2005-08-05 05:20:13 -04:00
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
ret = TkStringValue(ret);
|
|
|
|
DUMP1("Tcl_AppendResult");
|
2006-08-31 07:56:42 -04:00
|
|
|
Tcl_AppendResult(interp, RSTRING_PTR(ret), (char *)NULL);
|
2005-08-05 05:20:13 -04:00
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
}
|
2005-08-05 05:20:13 -04:00
|
|
|
|
2006-08-31 07:56:42 -04:00
|
|
|
DUMP2("(result) %s", NIL_P(ret) ? "nil" : RSTRING_PTR(ret));
|
2005-08-08 12:18:29 -04:00
|
|
|
|
2005-08-05 05:20:13 -04:00
|
|
|
return TCL_OK;
|
|
|
|
}
|
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
static int
|
|
|
|
tcl_protect(interp, proc, data)
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
VALUE (*proc)();
|
|
|
|
VALUE data;
|
2005-08-05 04:12:53 -04:00
|
|
|
{
|
2005-08-06 12:27:12 -04:00
|
|
|
int old_trapflag = rb_trap_immediate;
|
|
|
|
int code;
|
2005-08-05 04:12:53 -04:00
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
#ifdef HAVE_NATIVETHREAD
|
|
|
|
if (!is_ruby_native_thread()) {
|
|
|
|
rb_bug("cross-thread violation on tcl_protect()");
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
rb_trap_immediate = 0;
|
|
|
|
code = tcl_protect_core(interp, proc, data);
|
|
|
|
rb_trap_immediate = old_trapflag;
|
2002-03-08 02:03:09 -05:00
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
return code;
|
2003-08-29 04:34:14 -04:00
|
|
|
}
|
|
|
|
|
1998-01-16 07:19:09 -05:00
|
|
|
static int
|
1999-01-19 23:59:39 -05:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-05-01 12:09:54 -04:00
|
|
|
ip_ruby_eval(clientData, interp, argc, argv)
|
1999-08-13 01:37:52 -04:00
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int argc;
|
|
|
|
Tcl_Obj *CONST argv[];
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
ip_ruby_eval(clientData, interp, argc, argv)
|
1999-08-13 01:37:52 -04:00
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1999-01-19 23:59:39 -05:00
|
|
|
#endif
|
1998-01-16 07:19:09 -05:00
|
|
|
{
|
2005-08-06 12:27:12 -04:00
|
|
|
char *arg;
|
2004-05-01 12:09:54 -04:00
|
|
|
int thr_crit_bup;
|
2005-08-06 12:27:12 -04:00
|
|
|
int code;
|
1998-01-16 07:19:09 -05:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (interp == (Tcl_Interp*)NULL) {
|
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eRuntimeError,
|
|
|
|
"IP is deleted");
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
|
1998-01-16 07:19:09 -05:00
|
|
|
/* ruby command has 1 arg. */
|
|
|
|
if (argc != 2) {
|
2005-03-02 02:06:52 -05:00
|
|
|
#if 0
|
|
|
|
rb_raise(rb_eArgError,
|
|
|
|
"wrong number of arguments (%d for 1)", argc - 1);
|
|
|
|
#else
|
|
|
|
char buf[sizeof(int)*8 + 1];
|
|
|
|
Tcl_ResetResult(interp);
|
|
|
|
sprintf(buf, "%d", argc-1);
|
|
|
|
Tcl_AppendResult(interp, "wrong number of arguments (",
|
|
|
|
buf, " for 1)", (char *)NULL);
|
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eArgError,
|
|
|
|
Tcl_GetStringResult(interp));
|
|
|
|
return TCL_ERROR;
|
|
|
|
#endif
|
1998-01-16 07:19:09 -05:00
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
/* get C string from Tcl object */
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-05-01 12:09:54 -04:00
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
str = Tcl_GetStringFromObj(argv[1], &len);
|
2005-08-06 12:27:12 -04:00
|
|
|
arg = ALLOC_N(char, len + 1);
|
|
|
|
memcpy(arg, str, len);
|
|
|
|
arg[len] = 0;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
|
|
|
}
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2005-08-06 12:27:12 -04:00
|
|
|
arg = argv[1];
|
1999-01-19 23:59:39 -05:00
|
|
|
#endif
|
|
|
|
|
1998-01-16 07:19:09 -05:00
|
|
|
/* evaluate the argument string by ruby */
|
2005-08-06 12:27:12 -04:00
|
|
|
DUMP2("rb_eval_string(%s)", arg);
|
1998-01-16 07:19:09 -05:00
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
code = tcl_protect(interp, rb_eval_string, (VALUE)arg);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-05-01 12:09:54 -04:00
|
|
|
free(arg);
|
2005-08-06 12:27:12 -04:00
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
return code;
|
1998-01-16 07:19:09 -05:00
|
|
|
}
|
|
|
|
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* Tcl command `ruby_cmd' */
|
|
|
|
static VALUE
|
|
|
|
ip_ruby_cmd_core(arg)
|
|
|
|
struct cmd_body_arg *arg;
|
2003-10-14 11:25:45 -04:00
|
|
|
{
|
2004-09-11 13:45:53 -04:00
|
|
|
volatile VALUE ret;
|
2004-06-12 11:25:49 -04:00
|
|
|
int thr_crit_bup;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("call ip_ruby_cmd_core");
|
2004-06-12 11:25:49 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qfalse;
|
2004-05-01 12:09:54 -04:00
|
|
|
ret = rb_apply(arg->receiver, arg->method, arg->args);
|
2004-06-12 11:25:49 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("finish ip_ruby_cmd_core");
|
|
|
|
|
|
|
|
return ret;
|
2003-10-14 11:25:45 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* ruby_cmd receiver method arg ... */
|
* ext/tcltklib/tcltklib.c (VwaitVarProc, ip_rbVwaitObjCmd,
WaitVariableProc, WaitVisibilityProc, WaitWindowProc,
ip_rbTkWaitObjCmd, ip_rbTkWaitCommand, rb_threadVwaitProc,
rb_threadWaitVisibilityProc, rb_threadWaitWindowProc,
ip_rb_threadVwaitObjCmd, ip_rb_threadTkWaitObjCmd): prototype;
avoid VC++ warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4850 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-10-28 01:23:47 -05:00
|
|
|
static int
|
2004-05-01 12:09:54 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
ip_ruby_cmd(clientData, interp, argc, argv)
|
2003-10-14 11:25:45 -04:00
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
2004-05-01 12:09:54 -04:00
|
|
|
int argc;
|
|
|
|
Tcl_Obj *CONST argv[];
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
ip_ruby_cmd(clientData, interp, argc, argv)
|
2003-10-14 11:25:45 -04:00
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
2004-05-01 12:09:54 -04:00
|
|
|
int argc;
|
|
|
|
char *argv[];
|
2003-10-14 11:25:45 -04:00
|
|
|
#endif
|
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
volatile VALUE receiver;
|
|
|
|
volatile ID method;
|
2005-08-08 12:18:29 -04:00
|
|
|
volatile VALUE args;
|
2004-05-01 12:09:54 -04:00
|
|
|
char *str;
|
|
|
|
int i;
|
|
|
|
int len;
|
|
|
|
struct cmd_body_arg *arg;
|
|
|
|
int thr_crit_bup;
|
|
|
|
VALUE old_gc;
|
2005-08-06 12:27:12 -04:00
|
|
|
int code;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (interp == (Tcl_Interp*)NULL) {
|
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eRuntimeError,
|
|
|
|
"IP is deleted");
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (argc < 3) {
|
2005-03-02 02:06:52 -05:00
|
|
|
#if 0
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_raise(rb_eArgError, "too few arguments");
|
2005-03-02 02:06:52 -05:00
|
|
|
#else
|
|
|
|
Tcl_ResetResult(interp);
|
|
|
|
Tcl_AppendResult(interp, "too few arguments", (char *)NULL);
|
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eArgError,
|
|
|
|
Tcl_GetStringResult(interp));
|
|
|
|
return TCL_ERROR;
|
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* allocate */
|
|
|
|
arg = ALLOC(struct cmd_body_arg);
|
|
|
|
|
|
|
|
/* get arguments from Tcl objects */
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
old_gc = rb_gc_disable();
|
|
|
|
|
|
|
|
/* get receiver */
|
2003-10-14 11:25:45 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-05-01 12:09:54 -04:00
|
|
|
str = Tcl_GetStringFromObj(argv[1], &len);
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
str = argv[1];
|
2003-10-14 11:25:45 -04:00
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP2("receiver:%s",str);
|
|
|
|
if (str[0] == ':' || ('A' <= str[0] && str[0] <= 'Z')) {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* class | module | constant */
|
|
|
|
receiver = rb_const_get(rb_cObject, rb_intern(str));
|
2004-05-01 12:09:54 -04:00
|
|
|
} else if (str[0] == '$') {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* global variable */
|
|
|
|
receiver = rb_gv_get(str);
|
2004-05-01 12:09:54 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* global variable omitted '$' */
|
|
|
|
char *buf;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
len = strlen(str);
|
|
|
|
buf = ALLOC_N(char, len + 2);
|
|
|
|
buf[0] = '$';
|
2005-07-05 01:56:31 -04:00
|
|
|
memcpy(buf + 1, str, len);
|
2004-10-11 00:51:21 -04:00
|
|
|
buf[len + 1] = 0;
|
|
|
|
receiver = rb_gv_get(buf);
|
|
|
|
free(buf);
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
if (NIL_P(receiver)) {
|
2005-03-02 02:06:52 -05:00
|
|
|
#if 0
|
|
|
|
rb_raise(rb_eArgError,
|
|
|
|
"unknown class/module/global-variable '%s'", str);
|
|
|
|
#else
|
|
|
|
Tcl_ResetResult(interp);
|
|
|
|
Tcl_AppendResult(interp, "unknown class/module/global-variable '",
|
|
|
|
str, "'", (char *)NULL);
|
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eArgError,
|
|
|
|
Tcl_GetStringResult(interp));
|
|
|
|
return TCL_ERROR;
|
|
|
|
#endif
|
2003-10-14 11:25:45 -04:00
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
/* get metrhod */
|
2003-10-14 11:25:45 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-05-01 12:09:54 -04:00
|
|
|
str = Tcl_GetStringFromObj(argv[2], &len);
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
str = argv[2];
|
2003-10-14 11:25:45 -04:00
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
method = rb_intern(str);
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* get args */
|
2005-08-08 12:18:29 -04:00
|
|
|
args = rb_ary_new2(argc - 2);
|
2004-05-01 12:09:54 -04:00
|
|
|
for(i = 3; i < argc; i++) {
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
str = Tcl_GetStringFromObj(argv[i], &len);
|
|
|
|
DUMP2("arg:%s",str);
|
2006-09-02 10:42:08 -04:00
|
|
|
rb_ary_push(args, rb_tainted_str_new(str, len));
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP2("arg:%s",argv[i]);
|
2006-09-02 10:42:08 -04:00
|
|
|
rb_ary_push(args, rb_tainted_str_new2(argv[i]));
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
|
|
|
}
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (old_gc == Qfalse) rb_gc_enable();
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
arg->receiver = receiver;
|
|
|
|
arg->method = method;
|
|
|
|
arg->args = args;
|
|
|
|
|
|
|
|
/* evaluate the argument string by ruby */
|
2005-08-06 12:27:12 -04:00
|
|
|
code = tcl_protect(interp, ip_ruby_cmd_core, (VALUE)arg);
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
free(arg);
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2005-08-06 12:27:12 -04:00
|
|
|
return code;
|
2003-10-14 11:25:45 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/*****************************/
|
|
|
|
/* relpace of 'exit' command */
|
|
|
|
/*****************************/
|
2004-09-11 13:45:53 -04:00
|
|
|
static int
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
ip_InterpExitObjCmd(clientData, interp, argc, argv)
|
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int argc;
|
|
|
|
Tcl_Obj *CONST argv[];
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
ip_InterpExitCommand(clientData, interp, argc, argv)
|
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
#endif
|
|
|
|
{
|
2005-07-28 05:14:59 -04:00
|
|
|
DUMP1("start ip_InterpExitCommand");
|
2005-03-02 02:06:52 -05:00
|
|
|
if (interp != (Tcl_Interp*)NULL
|
|
|
|
&& !Tcl_InterpDeleted(interp)
|
|
|
|
#if TCL_NAMESPACE_DEBUG
|
|
|
|
&& !ip_null_namespace(interp)
|
|
|
|
#endif
|
|
|
|
) {
|
|
|
|
Tcl_ResetResult(interp);
|
|
|
|
/* Tcl_Preserve(interp); */
|
|
|
|
/* Tcl_Eval(interp, "interp eval {} {destroy .}; interp delete {}"); */
|
|
|
|
ip_finalize(interp);
|
|
|
|
Tcl_DeleteInterp(interp);
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(interp);
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
return TCL_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
ip_RubyExitObjCmd(clientData, interp, argc, argv)
|
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int argc;
|
|
|
|
Tcl_Obj *CONST argv[];
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
ip_RubyExitCommand(clientData, interp, argc, argv)
|
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
int state;
|
|
|
|
char *cmd, *param;
|
2005-08-04 05:41:57 -04:00
|
|
|
#if TCL_MAJOR_VERSION < 8
|
|
|
|
char *endptr;
|
|
|
|
cmd = argv[0];
|
|
|
|
#endif
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
DUMP1("start ip_RubyExitCommand");
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2005-07-28 05:14:59 -04:00
|
|
|
/* cmd = Tcl_GetString(argv[0]); */
|
|
|
|
cmd = Tcl_GetStringFromObj(argv[0], (int*)NULL);
|
2004-09-11 13:45:53 -04:00
|
|
|
#endif
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (argc < 1 || argc > 2) {
|
|
|
|
/* arguemnt error */
|
|
|
|
Tcl_AppendResult(interp,
|
|
|
|
"wrong number of arguments: should be \"",
|
|
|
|
cmd, " ?returnCode?\"", (char *)NULL);
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (interp == (Tcl_Interp*)NULL) return TCL_OK;
|
|
|
|
|
|
|
|
Tcl_ResetResult(interp);
|
|
|
|
|
2005-08-05 07:22:51 -04:00
|
|
|
if (rb_safe_level() >= 4 || Tcl_IsSafe(interp)) {
|
2005-03-02 02:06:52 -05:00
|
|
|
ip_finalize(interp);
|
|
|
|
Tcl_DeleteInterp(interp);
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(interp);
|
|
|
|
return TCL_OK;
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
switch(argc) {
|
|
|
|
case 1:
|
2005-03-02 02:06:52 -05:00
|
|
|
/* rb_exit(0); */ /* not return if succeed */
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_AppendResult(interp,
|
|
|
|
"fail to call \"", cmd, "\"", (char *)NULL);
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eSystemExit,
|
|
|
|
Tcl_GetStringResult(interp));
|
|
|
|
rb_iv_set(rbtk_pending_exception, "status", INT2FIX(0));
|
|
|
|
|
|
|
|
return TCL_RETURN;
|
2004-09-11 13:45:53 -04:00
|
|
|
|
|
|
|
case 2:
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2005-04-23 07:04:00 -04:00
|
|
|
if (Tcl_GetIntFromObj(interp, argv[1], &state) == TCL_ERROR) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2005-07-28 05:14:59 -04:00
|
|
|
/* param = Tcl_GetString(argv[1]); */
|
|
|
|
param = Tcl_GetStringFromObj(argv[1], (int*)NULL);
|
2004-09-11 13:45:53 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2004-10-11 00:51:21 -04:00
|
|
|
state = (int)strtol(argv[1], &endptr, 0);
|
2005-04-23 07:04:00 -04:00
|
|
|
if (*endptr) {
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_AppendResult(interp,
|
|
|
|
"expected integer but got \"",
|
|
|
|
argv[1], "\"", (char *)NULL);
|
2005-04-23 07:04:00 -04:00
|
|
|
return TCL_ERROR;
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
param = argv[1];
|
|
|
|
#endif
|
2005-03-02 02:06:52 -05:00
|
|
|
/* rb_exit(state); */ /* not return if succeed */
|
2004-10-11 00:51:21 -04:00
|
|
|
|
|
|
|
Tcl_AppendResult(interp, "fail to call \"", cmd, " ",
|
|
|
|
param, "\"", (char *)NULL);
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eSystemExit,
|
|
|
|
Tcl_GetStringResult(interp));
|
|
|
|
rb_iv_set(rbtk_pending_exception, "status", INT2FIX(state));
|
|
|
|
|
|
|
|
return TCL_RETURN;
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
default:
|
2004-10-11 00:51:21 -04:00
|
|
|
/* arguemnt error */
|
|
|
|
Tcl_AppendResult(interp,
|
|
|
|
"wrong number of arguments: should be \"",
|
|
|
|
cmd, " ?returnCode?\"", (char *)NULL);
|
|
|
|
return TCL_ERROR;
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/**************************/
|
|
|
|
/* based on tclEvent.c */
|
|
|
|
/**************************/
|
|
|
|
|
|
|
|
/*********************/
|
|
|
|
/* replace of update */
|
|
|
|
/*********************/
|
2003-10-14 11:25:45 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-05-01 12:09:54 -04:00
|
|
|
static int ip_rbUpdateObjCmd _((ClientData, Tcl_Interp *, int,
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Obj *CONST []));
|
* ext/tcltklib/tcltklib.c (VwaitVarProc, ip_rbVwaitObjCmd,
WaitVariableProc, WaitVisibilityProc, WaitWindowProc,
ip_rbTkWaitObjCmd, ip_rbTkWaitCommand, rb_threadVwaitProc,
rb_threadWaitVisibilityProc, rb_threadWaitWindowProc,
ip_rb_threadVwaitObjCmd, ip_rb_threadTkWaitObjCmd): prototype;
avoid VC++ warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4850 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-10-28 01:23:47 -05:00
|
|
|
static int
|
2004-05-01 12:09:54 -04:00
|
|
|
ip_rbUpdateObjCmd(clientData, interp, objc, objv)
|
2003-10-14 11:25:45 -04:00
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int objc;
|
|
|
|
Tcl_Obj *CONST objv[];
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
static int ip_rbUpdateCommand _((ClientData, Tcl_Interp *, int, char *[]));
|
* ext/tcltklib/tcltklib.c (VwaitVarProc, ip_rbVwaitObjCmd,
WaitVariableProc, WaitVisibilityProc, WaitWindowProc,
ip_rbTkWaitObjCmd, ip_rbTkWaitCommand, rb_threadVwaitProc,
rb_threadWaitVisibilityProc, rb_threadWaitWindowProc,
ip_rb_threadVwaitObjCmd, ip_rb_threadTkWaitObjCmd): prototype;
avoid VC++ warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4850 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-10-28 01:23:47 -05:00
|
|
|
static int
|
2004-05-01 12:09:54 -04:00
|
|
|
ip_rbUpdateCommand(clientData, interp, objc, objv)
|
2003-10-14 11:25:45 -04:00
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int objc;
|
|
|
|
char *objv[];
|
|
|
|
#endif
|
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
int optionIndex;
|
2005-08-06 12:27:12 -04:00
|
|
|
int ret;
|
2004-05-01 12:09:54 -04:00
|
|
|
int flags = 0;
|
|
|
|
static CONST char *updateOptions[] = {"idletasks", (char *) NULL};
|
|
|
|
enum updateOptions {REGEXP_IDLETASKS};
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("Ruby's 'update' is called");
|
2005-03-02 02:06:52 -05:00
|
|
|
if (interp == (Tcl_Interp*)NULL) {
|
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eRuntimeError,
|
|
|
|
"IP is deleted");
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
#ifdef HAVE_NATIVETHREAD
|
|
|
|
if (!is_ruby_native_thread()) {
|
|
|
|
rb_bug("cross-thread violation on ip_ruby_eval()");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (objc == 1) {
|
2005-11-02 05:06:29 -05:00
|
|
|
flags = TCL_DONT_WAIT;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
} else if (objc == 2) {
|
2005-08-04 05:41:57 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2005-03-03 04:47:30 -05:00
|
|
|
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)updateOptions,
|
2004-10-11 00:51:21 -04:00
|
|
|
"option", 0, &optionIndex) != TCL_OK) {
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
switch ((enum updateOptions) optionIndex) {
|
|
|
|
case REGEXP_IDLETASKS: {
|
2005-11-02 05:06:29 -05:00
|
|
|
flags = TCL_IDLE_EVENTS;
|
2004-10-11 00:51:21 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
2005-08-01 21:25:01 -04:00
|
|
|
rb_bug("ip_rbUpdateObjCmd: bad option index to UpdateOptions");
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
}
|
2005-08-04 05:41:57 -04:00
|
|
|
#else
|
|
|
|
if (strncmp(objv[1], "idletasks", strlen(objv[1])) != 0) {
|
|
|
|
Tcl_AppendResult(interp, "bad option \"", objv[1],
|
|
|
|
"\": must be idletasks", (char *) NULL);
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2005-11-02 05:06:29 -05:00
|
|
|
flags = TCL_IDLE_EVENTS;
|
2005-08-04 05:41:57 -04:00
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
} else {
|
2003-10-14 11:25:45 -04:00
|
|
|
#ifdef Tcl_WrongNumArgs
|
2004-05-01 12:09:54 -04:00
|
|
|
Tcl_WrongNumArgs(interp, 1, objv, "[ idletasks ]");
|
2003-10-14 11:25:45 -04:00
|
|
|
#else
|
2004-05-01 12:09:54 -04:00
|
|
|
# if TCL_MAJOR_VERSION >= 8
|
2005-11-06 23:47:08 -05:00
|
|
|
int dummy;
|
2004-05-01 12:09:54 -04:00
|
|
|
Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_GetStringFromObj(objv[0], &dummy),
|
|
|
|
" [ idletasks ]\"",
|
|
|
|
(char *) NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
# else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
|
2004-10-11 00:51:21 -04:00
|
|
|
objv[0], " [ idletasks ]\"", (char *) NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
# endif
|
2003-10-14 11:25:45 -04:00
|
|
|
#endif
|
2004-10-11 00:51:21 -04:00
|
|
|
return TCL_ERROR;
|
2003-10-14 11:25:45 -04:00
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
Tcl_Preserve(interp);
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* call eventloop */
|
2005-03-02 02:06:52 -05:00
|
|
|
/* ret = lib_eventloop_core(0, flags, (int *)NULL);*/ /* ignore result */
|
2005-12-06 11:05:50 -05:00
|
|
|
ret = RTEST(lib_eventloop_launcher(0, flags, (int *)NULL, interp)); /* ignore result */
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
/* exception check */
|
|
|
|
if (!NIL_P(rbtk_pending_exception)) {
|
|
|
|
Tcl_Release(interp);
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (rb_obj_is_kind_of(rbtk_pending_exception, rb_eSystemExit)) {
|
|
|
|
*/
|
|
|
|
if (rb_obj_is_kind_of(rbtk_pending_exception, rb_eSystemExit)
|
|
|
|
|| rb_obj_is_kind_of(rbtk_pending_exception, rb_eInterrupt)) {
|
|
|
|
return TCL_RETURN;
|
|
|
|
} else{
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* trap check */
|
|
|
|
if (rb_trap_pending) {
|
|
|
|
Tcl_Release(interp);
|
|
|
|
|
|
|
|
return TCL_RETURN;
|
|
|
|
}
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/*
|
|
|
|
* Must clear the interpreter's result because event handlers could
|
|
|
|
* have executed commands.
|
|
|
|
*/
|
|
|
|
|
|
|
|
DUMP2("last result '%s'", Tcl_GetStringResult(interp));
|
|
|
|
Tcl_ResetResult(interp);
|
2005-03-02 02:06:52 -05:00
|
|
|
Tcl_Release(interp);
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("finish Ruby's 'update'");
|
|
|
|
return TCL_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************/
|
|
|
|
/* update with thread */
|
|
|
|
/**********************/
|
|
|
|
struct th_update_param {
|
|
|
|
VALUE thread;
|
|
|
|
int done;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void rb_threadUpdateProc _((ClientData));
|
|
|
|
static void
|
|
|
|
rb_threadUpdateProc(clientData)
|
|
|
|
ClientData clientData; /* Pointer to integer to set to 1. */
|
|
|
|
{
|
|
|
|
struct th_update_param *param = (struct th_update_param *) clientData;
|
|
|
|
|
|
|
|
DUMP1("threadUpdateProc is called");
|
|
|
|
param->done = 1;
|
2004-09-17 02:05:33 -04:00
|
|
|
rb_thread_wakeup(param->thread);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
static int ip_rb_threadUpdateObjCmd _((ClientData, Tcl_Interp *, int,
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Obj *CONST []));
|
2004-05-01 12:09:54 -04:00
|
|
|
static int
|
|
|
|
ip_rb_threadUpdateObjCmd(clientData, interp, objc, objv)
|
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int objc;
|
|
|
|
Tcl_Obj *CONST objv[];
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
static int ip_rb_threadUpdateCommand _((ClientData, Tcl_Interp *, int,
|
2004-10-11 00:51:21 -04:00
|
|
|
char *[]));
|
2004-05-01 12:09:54 -04:00
|
|
|
static int
|
|
|
|
ip_rb_threadUpdateCommand(clientData, interp, objc, objv)
|
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int objc;
|
|
|
|
char *objv[];
|
2003-10-14 11:25:45 -04:00
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
{
|
|
|
|
int optionIndex;
|
|
|
|
int flags = 0;
|
|
|
|
struct th_update_param *param;
|
|
|
|
static CONST char *updateOptions[] = {"idletasks", (char *) NULL};
|
|
|
|
enum updateOptions {REGEXP_IDLETASKS};
|
|
|
|
volatile VALUE current_thread = rb_thread_current();
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("Ruby's 'thread_update' is called");
|
2005-03-02 02:06:52 -05:00
|
|
|
if (interp == (Tcl_Interp*)NULL) {
|
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eRuntimeError,
|
|
|
|
"IP is deleted");
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
#ifdef HAVE_NATIVETHREAD
|
|
|
|
if (!is_ruby_native_thread()) {
|
|
|
|
rb_bug("cross-thread violation on ip_ruby_eval()");
|
|
|
|
}
|
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-07-12 23:47:05 -04:00
|
|
|
if (rb_thread_alone()
|
|
|
|
|| NIL_P(eventloop_thread) || eventloop_thread == current_thread) {
|
2003-10-14 11:25:45 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("call ip_rbUpdateObjCmd");
|
|
|
|
return ip_rbUpdateObjCmd(clientData, interp, objc, objv);
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("call ip_rbUpdateCommand");
|
|
|
|
return ip_rbUpdateCommand(clientData, interp, objc, objv);
|
2003-10-14 11:25:45 -04:00
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("start Ruby's 'thread_update' body");
|
|
|
|
|
|
|
|
if (objc == 1) {
|
2005-11-02 05:06:29 -05:00
|
|
|
flags = TCL_DONT_WAIT;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
} else if (objc == 2) {
|
2005-08-04 05:41:57 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2005-03-03 04:47:30 -05:00
|
|
|
if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)updateOptions,
|
2004-10-11 00:51:21 -04:00
|
|
|
"option", 0, &optionIndex) != TCL_OK) {
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
switch ((enum updateOptions) optionIndex) {
|
|
|
|
case REGEXP_IDLETASKS: {
|
2005-11-02 05:06:29 -05:00
|
|
|
flags = TCL_IDLE_EVENTS;
|
2004-10-11 00:51:21 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
2005-08-01 21:25:01 -04:00
|
|
|
rb_bug("ip_rb_threadUpdateObjCmd: bad option index to UpdateOptions");
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
}
|
2005-08-04 05:41:57 -04:00
|
|
|
#else
|
|
|
|
if (strncmp(objv[1], "idletasks", strlen(objv[1])) != 0) {
|
|
|
|
Tcl_AppendResult(interp, "bad option \"", objv[1],
|
|
|
|
"\": must be idletasks", (char *) NULL);
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2005-11-02 05:06:29 -05:00
|
|
|
flags = TCL_IDLE_EVENTS;
|
2005-08-04 05:41:57 -04:00
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
} else {
|
|
|
|
#ifdef Tcl_WrongNumArgs
|
|
|
|
Tcl_WrongNumArgs(interp, 1, objv, "[ idletasks ]");
|
|
|
|
#else
|
|
|
|
# if TCL_MAJOR_VERSION >= 8
|
2005-11-06 23:47:08 -05:00
|
|
|
int dummy;
|
2004-05-01 12:09:54 -04:00
|
|
|
Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_GetStringFromObj(objv[0], &dummy),
|
|
|
|
" [ idletasks ]\"",
|
|
|
|
(char *) NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
# else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
|
2004-10-11 00:51:21 -04:00
|
|
|
objv[0], " [ idletasks ]\"", (char *) NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
# endif
|
|
|
|
#endif
|
2004-10-11 00:51:21 -04:00
|
|
|
return TCL_ERROR;
|
2003-10-14 11:25:45 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("pass argument check");
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
param = (struct th_update_param *)Tcl_Alloc(sizeof(struct th_update_param));
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_Preserve(param);
|
2004-05-01 12:09:54 -04:00
|
|
|
param->thread = current_thread;
|
|
|
|
param->done = 0;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("set idle proc");
|
|
|
|
Tcl_DoWhenIdle(rb_threadUpdateProc, (ClientData) param);
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
while(!param->done) {
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("wait for complete idle proc");
|
|
|
|
rb_thread_stop();
|
2003-10-14 11:25:45 -04:00
|
|
|
}
|
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_Release(param);
|
2004-05-01 12:09:54 -04:00
|
|
|
Tcl_Free((char *)param);
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("finish Ruby's 'thread_update'");
|
2003-10-14 11:25:45 -04:00
|
|
|
return TCL_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/***************************/
|
|
|
|
/* replace of vwait/tkwait */
|
|
|
|
/***************************/
|
2005-12-06 11:05:50 -05:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
static int ip_rbVwaitObjCmd _((ClientData, Tcl_Interp *, int,
|
|
|
|
Tcl_Obj *CONST []));
|
|
|
|
static int ip_rb_threadVwaitObjCmd _((ClientData, Tcl_Interp *, int,
|
|
|
|
Tcl_Obj *CONST []));
|
|
|
|
static int ip_rbTkWaitObjCmd _((ClientData, Tcl_Interp *, int,
|
|
|
|
Tcl_Obj *CONST []));
|
|
|
|
static int ip_rb_threadTkWaitObjCmd _((ClientData, Tcl_Interp *, int,
|
|
|
|
Tcl_Obj *CONST []));
|
|
|
|
#else
|
|
|
|
static int ip_rbVwaitCommand _((ClientData, Tcl_Interp *, int, char *[]));
|
|
|
|
static int ip_rb_threadVwaitCommand _((ClientData, Tcl_Interp *, int,
|
|
|
|
char *[]));
|
|
|
|
static int ip_rbTkWaitCommand _((ClientData, Tcl_Interp *, int, char *[]));
|
|
|
|
static int ip_rb_threadTkWaitCommand _((ClientData, Tcl_Interp *, int,
|
|
|
|
char *[]));
|
|
|
|
#endif
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
static char *VwaitVarProc _((ClientData, Tcl_Interp *,
|
2004-10-11 00:51:21 -04:00
|
|
|
CONST84 char *,CONST84 char *, int));
|
2003-10-14 11:25:45 -04:00
|
|
|
static char *
|
2004-05-01 12:09:54 -04:00
|
|
|
VwaitVarProc(clientData, interp, name1, name2, flags)
|
2003-10-14 11:25:45 -04:00
|
|
|
ClientData clientData; /* Pointer to integer to set to 1. */
|
|
|
|
Tcl_Interp *interp; /* Interpreter containing variable. */
|
2003-10-29 06:03:54 -05:00
|
|
|
CONST84 char *name1; /* Name of variable. */
|
|
|
|
CONST84 char *name2; /* Second part of variable name. */
|
2003-10-14 11:25:45 -04:00
|
|
|
int flags; /* Information about what happened. */
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
static char *VwaitVarProc _((ClientData, Tcl_Interp *, char *, char *, int));
|
|
|
|
static char *
|
|
|
|
VwaitVarProc(clientData, interp, name1, name2, flags)
|
2003-10-14 11:25:45 -04:00
|
|
|
ClientData clientData; /* Pointer to integer to set to 1. */
|
2004-05-01 12:09:54 -04:00
|
|
|
Tcl_Interp *interp; /* Interpreter containing variable. */
|
|
|
|
char *name1; /* Name of variable. */
|
|
|
|
char *name2; /* Second part of variable name. */
|
|
|
|
int flags; /* Information about what happened. */
|
|
|
|
#endif
|
2003-10-14 11:25:45 -04:00
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
int *donePtr = (int *) clientData;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
*donePtr = 1;
|
|
|
|
return (char *) NULL;
|
2003-10-14 11:25:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
* ext/tcltklib/tcltklib.c (VwaitVarProc, ip_rbVwaitObjCmd,
WaitVariableProc, WaitVisibilityProc, WaitWindowProc,
ip_rbTkWaitObjCmd, ip_rbTkWaitCommand, rb_threadVwaitProc,
rb_threadWaitVisibilityProc, rb_threadWaitWindowProc,
ip_rb_threadVwaitObjCmd, ip_rb_threadTkWaitObjCmd): prototype;
avoid VC++ warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4850 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-10-28 01:23:47 -05:00
|
|
|
static int
|
2004-05-01 12:09:54 -04:00
|
|
|
ip_rbVwaitObjCmd(clientData, interp, objc, objv)
|
2003-10-14 11:25:45 -04:00
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int objc;
|
|
|
|
Tcl_Obj *CONST objv[];
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
* ext/tcltklib/tcltklib.c (VwaitVarProc, ip_rbVwaitObjCmd,
WaitVariableProc, WaitVisibilityProc, WaitWindowProc,
ip_rbTkWaitObjCmd, ip_rbTkWaitCommand, rb_threadVwaitProc,
rb_threadWaitVisibilityProc, rb_threadWaitWindowProc,
ip_rb_threadVwaitObjCmd, ip_rb_threadTkWaitObjCmd): prototype;
avoid VC++ warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4850 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-10-28 01:23:47 -05:00
|
|
|
static int
|
2004-05-01 12:09:54 -04:00
|
|
|
ip_rbVwaitCommand(clientData, interp, objc, objv)
|
2003-10-14 11:25:45 -04:00
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int objc;
|
|
|
|
char *objv[];
|
|
|
|
#endif
|
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
int ret, done, foundEvent;
|
2003-10-14 11:25:45 -04:00
|
|
|
char *nameString;
|
|
|
|
int dummy;
|
2004-05-01 12:09:54 -04:00
|
|
|
int thr_crit_bup;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("Ruby's 'vwait' is called");
|
2005-03-02 02:06:52 -05:00
|
|
|
if (interp == (Tcl_Interp*)NULL) {
|
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eRuntimeError,
|
|
|
|
"IP is deleted");
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
|
2005-12-06 11:05:50 -05:00
|
|
|
#if 0
|
|
|
|
if (!rb_thread_alone()
|
|
|
|
&& eventloop_thread != Qnil
|
|
|
|
&& eventloop_thread != rb_thread_current()) {
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
DUMP1("call ip_rb_threadVwaitObjCmd");
|
|
|
|
return ip_rb_threadVwaitObjCmd(clientData, interp, objc, objv);
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
DUMP1("call ip_rb_threadVwaitCommand");
|
|
|
|
return ip_rb_threadVwaitCommand(clientData, interp, objc, objv);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_Preserve(interp);
|
2005-03-02 02:06:52 -05:00
|
|
|
#ifdef HAVE_NATIVETHREAD
|
|
|
|
if (!is_ruby_native_thread()) {
|
|
|
|
rb_bug("cross-thread violation on ip_ruby_eval()");
|
|
|
|
}
|
|
|
|
#endif
|
2004-09-17 02:05:33 -04:00
|
|
|
|
2003-10-14 11:25:45 -04:00
|
|
|
if (objc != 2) {
|
|
|
|
#ifdef Tcl_WrongNumArgs
|
|
|
|
Tcl_WrongNumArgs(interp, 1, objv, "name");
|
|
|
|
#else
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2003-10-14 11:25:45 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
/* nameString = Tcl_GetString(objv[0]); */
|
|
|
|
nameString = Tcl_GetStringFromObj(objv[0], &dummy);
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2004-10-11 00:51:21 -04:00
|
|
|
nameString = objv[0];
|
2003-10-14 11:25:45 -04:00
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
|
2004-10-11 00:51:21 -04:00
|
|
|
nameString, " name\"", (char *) NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2003-10-14 11:25:45 -04:00
|
|
|
#endif
|
2004-09-17 02:05:33 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(interp);
|
2003-10-14 11:25:45 -04:00
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
2003-10-14 11:25:45 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_IncrRefCount(objv[1]);
|
2003-10-14 11:25:45 -04:00
|
|
|
/* nameString = Tcl_GetString(objv[1]); */
|
|
|
|
nameString = Tcl_GetStringFromObj(objv[1], &dummy);
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2003-10-14 11:25:45 -04:00
|
|
|
nameString = objv[1];
|
|
|
|
#endif
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/*
|
2003-10-14 11:25:45 -04:00
|
|
|
if (Tcl_TraceVar(interp, nameString,
|
2004-10-11 00:51:21 -04:00
|
|
|
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
|
|
|
VwaitVarProc, (ClientData) &done) != TCL_OK) {
|
2003-10-14 11:25:45 -04:00
|
|
|
return TCL_ERROR;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
*/
|
|
|
|
ret = Tcl_TraceVar(interp, nameString,
|
2004-10-11 00:51:21 -04:00
|
|
|
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
|
|
|
VwaitVarProc, (ClientData) &done);
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
|
|
|
if (ret != TCL_OK) {
|
2004-09-17 02:05:33 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(objv[1]);
|
2004-09-17 02:05:33 -04:00
|
|
|
#endif
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(interp);
|
2004-05-01 12:09:54 -04:00
|
|
|
return TCL_ERROR;
|
2003-10-14 11:25:45 -04:00
|
|
|
}
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
done = 0;
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2005-12-06 11:05:50 -05:00
|
|
|
foundEvent = RTEST(lib_eventloop_launcher(/* not check root-widget */0,
|
|
|
|
0, &done, interp));
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
|
|
|
Tcl_UntraceVar(interp, nameString,
|
2004-10-11 00:51:21 -04:00
|
|
|
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
|
|
|
VwaitVarProc, (ClientData) &done);
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* exception check */
|
|
|
|
if (!NIL_P(rbtk_pending_exception)) {
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
Tcl_DecrRefCount(objv[1]);
|
|
|
|
#endif
|
|
|
|
Tcl_Release(interp);
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (rb_obj_is_kind_of(rbtk_pending_exception, rb_eSystemExit)) {
|
|
|
|
*/
|
|
|
|
if (rb_obj_is_kind_of(rbtk_pending_exception, rb_eSystemExit)
|
|
|
|
|| rb_obj_is_kind_of(rbtk_pending_exception, rb_eInterrupt)) {
|
|
|
|
return TCL_RETURN;
|
|
|
|
} else{
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* trap check */
|
|
|
|
if (rb_trap_pending) {
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
Tcl_DecrRefCount(objv[1]);
|
|
|
|
#endif
|
|
|
|
Tcl_Release(interp);
|
|
|
|
|
|
|
|
return TCL_RETURN;
|
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/*
|
|
|
|
* Clear out the interpreter's result, since it may have been set
|
|
|
|
* by event handlers.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Tcl_ResetResult(interp);
|
|
|
|
if (!foundEvent) {
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
Tcl_AppendResult(interp, "can't wait for variable \"", nameString,
|
2004-10-11 00:51:21 -04:00
|
|
|
"\": would wait forever", (char *) NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(objv[1]);
|
2004-09-17 02:05:33 -04:00
|
|
|
#endif
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(interp);
|
2004-05-01 12:09:54 -04:00
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2004-09-17 02:05:33 -04:00
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
Tcl_DecrRefCount(objv[1]);
|
|
|
|
#endif
|
|
|
|
Tcl_Release(interp);
|
2003-10-14 11:25:45 -04:00
|
|
|
return TCL_OK;
|
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
/**************************/
|
|
|
|
/* based on tkCmd.c */
|
|
|
|
/**************************/
|
2003-10-14 11:25:45 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-05-01 12:09:54 -04:00
|
|
|
static char *WaitVariableProc _((ClientData, Tcl_Interp *,
|
2004-10-11 00:51:21 -04:00
|
|
|
CONST84 char *,CONST84 char *, int));
|
2004-05-01 12:09:54 -04:00
|
|
|
static char *
|
|
|
|
WaitVariableProc(clientData, interp, name1, name2, flags)
|
|
|
|
ClientData clientData; /* Pointer to integer to set to 1. */
|
|
|
|
Tcl_Interp *interp; /* Interpreter containing variable. */
|
|
|
|
CONST84 char *name1; /* Name of variable. */
|
|
|
|
CONST84 char *name2; /* Second part of variable name. */
|
|
|
|
int flags; /* Information about what happened. */
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
static char *WaitVariableProc _((ClientData, Tcl_Interp *,
|
2004-10-11 00:51:21 -04:00
|
|
|
char *, char *, int));
|
2004-05-01 12:09:54 -04:00
|
|
|
static char *
|
|
|
|
WaitVariableProc(clientData, interp, name1, name2, flags)
|
|
|
|
ClientData clientData; /* Pointer to integer to set to 1. */
|
|
|
|
Tcl_Interp *interp; /* Interpreter containing variable. */
|
|
|
|
char *name1; /* Name of variable. */
|
|
|
|
char *name2; /* Second part of variable name. */
|
|
|
|
int flags; /* Information about what happened. */
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
int *donePtr = (int *) clientData;
|
|
|
|
|
|
|
|
*donePtr = 1;
|
|
|
|
return (char *) NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void WaitVisibilityProc _((ClientData, XEvent *));
|
|
|
|
static void
|
|
|
|
WaitVisibilityProc(clientData, eventPtr)
|
|
|
|
ClientData clientData; /* Pointer to integer to set to 1. */
|
|
|
|
XEvent *eventPtr; /* Information about event (not used). */
|
|
|
|
{
|
|
|
|
int *donePtr = (int *) clientData;
|
|
|
|
|
|
|
|
if (eventPtr->type == VisibilityNotify) {
|
|
|
|
*donePtr = 1;
|
|
|
|
}
|
|
|
|
if (eventPtr->type == DestroyNotify) {
|
|
|
|
*donePtr = 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void WaitWindowProc _((ClientData, XEvent *));
|
|
|
|
static void
|
|
|
|
WaitWindowProc(clientData, eventPtr)
|
|
|
|
ClientData clientData; /* Pointer to integer to set to 1. */
|
|
|
|
XEvent *eventPtr; /* Information about event. */
|
|
|
|
{
|
|
|
|
int *donePtr = (int *) clientData;
|
|
|
|
|
|
|
|
if (eventPtr->type == DestroyNotify) {
|
|
|
|
*donePtr = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
* ext/tcltklib/tcltklib.c (VwaitVarProc, ip_rbVwaitObjCmd,
WaitVariableProc, WaitVisibilityProc, WaitWindowProc,
ip_rbTkWaitObjCmd, ip_rbTkWaitCommand, rb_threadVwaitProc,
rb_threadWaitVisibilityProc, rb_threadWaitWindowProc,
ip_rb_threadVwaitObjCmd, ip_rb_threadTkWaitObjCmd): prototype;
avoid VC++ warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4850 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-10-28 01:23:47 -05:00
|
|
|
static int
|
2004-05-01 12:09:54 -04:00
|
|
|
ip_rbTkWaitObjCmd(clientData, interp, objc, objv)
|
2003-10-14 11:25:45 -04:00
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int objc;
|
|
|
|
Tcl_Obj *CONST objv[];
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
* ext/tcltklib/tcltklib.c (VwaitVarProc, ip_rbVwaitObjCmd,
WaitVariableProc, WaitVisibilityProc, WaitWindowProc,
ip_rbTkWaitObjCmd, ip_rbTkWaitCommand, rb_threadVwaitProc,
rb_threadWaitVisibilityProc, rb_threadWaitWindowProc,
ip_rb_threadVwaitObjCmd, ip_rb_threadTkWaitObjCmd): prototype;
avoid VC++ warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@4850 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2003-10-28 01:23:47 -05:00
|
|
|
static int
|
2004-05-01 12:09:54 -04:00
|
|
|
ip_rbTkWaitCommand(clientData, interp, objc, objv)
|
2003-10-14 11:25:45 -04:00
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int objc;
|
|
|
|
char *objv[];
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
Tk_Window tkwin = (Tk_Window) clientData;
|
2004-09-17 02:05:33 -04:00
|
|
|
Tk_Window window;
|
2004-05-01 12:09:54 -04:00
|
|
|
int done, index;
|
2003-10-14 11:25:45 -04:00
|
|
|
static CONST char *optionStrings[] = { "variable", "visibility", "window",
|
2004-10-11 00:51:21 -04:00
|
|
|
(char *) NULL };
|
2003-10-14 11:25:45 -04:00
|
|
|
enum options { TKWAIT_VARIABLE, TKWAIT_VISIBILITY, TKWAIT_WINDOW };
|
|
|
|
char *nameString;
|
2004-05-01 12:09:54 -04:00
|
|
|
int ret, dummy;
|
|
|
|
int thr_crit_bup;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("Ruby's 'tkwait' is called");
|
2005-03-02 02:06:52 -05:00
|
|
|
if (interp == (Tcl_Interp*)NULL) {
|
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eRuntimeError,
|
|
|
|
"IP is deleted");
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-12-06 11:05:50 -05:00
|
|
|
#if 0
|
|
|
|
if (!rb_thread_alone()
|
|
|
|
&& eventloop_thread != Qnil
|
|
|
|
&& eventloop_thread != rb_thread_current()) {
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
DUMP1("call ip_rb_threadTkWaitObjCmd");
|
|
|
|
return ip_rb_threadTkWaitObjCmd(clientData, interp, objc, objv);
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
DUMP1("call ip_rb_threadTkWaitCommand");
|
|
|
|
return ip_rb_threadTkWwaitCommand(clientData, interp, objc, objv);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_Preserve(interp);
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (objc != 3) {
|
|
|
|
#ifdef Tcl_WrongNumArgs
|
|
|
|
Tcl_WrongNumArgs(interp, 1, objv, "variable|visibility|window name");
|
|
|
|
#else
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-05-01 12:09:54 -04:00
|
|
|
Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_GetStringFromObj(objv[0], &dummy),
|
|
|
|
" variable|visibility|window name\"",
|
|
|
|
(char *) NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
|
2004-10-11 00:51:21 -04:00
|
|
|
objv[0], " variable|visibility|window name\"",
|
|
|
|
(char *) NULL);
|
2003-10-14 11:25:45 -04:00
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2003-10-14 11:25:45 -04:00
|
|
|
#endif
|
2004-09-17 02:05:33 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(interp);
|
2003-10-14 11:25:45 -04:00
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-05-01 12:09:54 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
/*
|
2003-10-14 11:25:45 -04:00
|
|
|
if (Tcl_GetIndexFromObj(interp, objv[1],
|
|
|
|
(CONST84 char **)optionStrings,
|
2004-10-11 00:51:21 -04:00
|
|
|
"option", 0, &index) != TCL_OK) {
|
2003-10-14 11:25:45 -04:00
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
*/
|
|
|
|
ret = Tcl_GetIndexFromObj(interp, objv[1],
|
2004-10-11 00:51:21 -04:00
|
|
|
(CONST84 char **)optionStrings,
|
|
|
|
"option", 0, &index);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
|
|
|
if (ret != TCL_OK) {
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(interp);
|
2004-05-01 12:09:54 -04:00
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2003-10-14 11:25:45 -04:00
|
|
|
{
|
2004-10-11 00:51:21 -04:00
|
|
|
int c = objv[1][0];
|
|
|
|
size_t length = strlen(objv[1]);
|
|
|
|
|
|
|
|
if ((c == 'v') && (strncmp(objv[1], "variable", length) == 0)
|
|
|
|
&& (length >= 2)) {
|
|
|
|
index = TKWAIT_VARIABLE;
|
|
|
|
} else if ((c == 'v') && (strncmp(objv[1], "visibility", length) == 0)
|
|
|
|
&& (length >= 2)) {
|
|
|
|
index = TKWAIT_VISIBILITY;
|
|
|
|
} else if ((c == 'w') && (strncmp(objv[1], "window", length) == 0)) {
|
|
|
|
index = TKWAIT_WINDOW;
|
|
|
|
} else {
|
|
|
|
Tcl_AppendResult(interp, "bad option \"", objv[1],
|
|
|
|
"\": must be variable, visibility, or window",
|
|
|
|
(char *) NULL);
|
|
|
|
Tcl_Release(interp);
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2003-10-14 11:25:45 -04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
2003-10-14 11:25:45 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_IncrRefCount(objv[2]);
|
2003-10-14 11:25:45 -04:00
|
|
|
/* nameString = Tcl_GetString(objv[2]); */
|
|
|
|
nameString = Tcl_GetStringFromObj(objv[2], &dummy);
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2003-10-14 11:25:45 -04:00
|
|
|
nameString = objv[2];
|
|
|
|
#endif
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
|
|
|
switch ((enum options) index) {
|
2004-09-17 02:05:33 -04:00
|
|
|
case TKWAIT_VARIABLE:
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
/*
|
|
|
|
if (Tcl_TraceVar(interp, nameString,
|
|
|
|
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
|
|
|
WaitVariableProc, (ClientData) &done) != TCL_OK) {
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
ret = Tcl_TraceVar(interp, nameString,
|
|
|
|
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
|
|
|
WaitVariableProc, (ClientData) &done);
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
|
|
|
if (ret != TCL_OK) {
|
2004-09-17 02:05:33 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(objv[2]);
|
2004-09-17 02:05:33 -04:00
|
|
|
#endif
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(interp);
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
done = 0;
|
2005-03-02 02:06:52 -05:00
|
|
|
/* lib_eventloop_core(check_rootwidget_flag, 0, &done); */
|
2005-12-06 11:05:50 -05:00
|
|
|
lib_eventloop_launcher(check_rootwidget_flag, 0, &done, interp);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_UntraceVar(interp, nameString,
|
|
|
|
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
|
|
|
WaitVariableProc, (ClientData) &done);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(objv[2]);
|
2004-09-17 02:05:33 -04:00
|
|
|
#endif
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* exception check */
|
|
|
|
if (!NIL_P(rbtk_pending_exception)) {
|
|
|
|
Tcl_Release(interp);
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (rb_obj_is_kind_of(rbtk_pending_exception, rb_eSystemExit)) {
|
|
|
|
*/
|
|
|
|
if (rb_obj_is_kind_of(rbtk_pending_exception, rb_eSystemExit)
|
|
|
|
|| rb_obj_is_kind_of(rbtk_pending_exception, rb_eInterrupt)) {
|
|
|
|
return TCL_RETURN;
|
|
|
|
} else{
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* trap check */
|
|
|
|
if (rb_trap_pending) {
|
|
|
|
Tcl_Release(interp);
|
|
|
|
|
|
|
|
return TCL_RETURN;
|
|
|
|
}
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
break;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
case TKWAIT_VISIBILITY:
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
if (!tk_stubs_init_p() || Tk_MainWindow(interp) == (Tk_Window)NULL) {
|
2004-10-11 00:51:21 -04:00
|
|
|
window = NULL;
|
|
|
|
} else {
|
|
|
|
window = Tk_NameToWindow(interp, nameString, tkwin);
|
|
|
|
}
|
2004-09-17 02:05:33 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
if (window == NULL) {
|
2005-07-28 05:14:59 -04:00
|
|
|
Tcl_AppendResult(interp, "tkwait: ",
|
|
|
|
"no main-window (not Tk application?)",
|
|
|
|
(char*)NULL);
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-09-17 02:05:33 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(objv[2]);
|
2004-09-17 02:05:33 -04:00
|
|
|
#endif
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(interp);
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tk_CreateEventHandler(window,
|
|
|
|
VisibilityChangeMask|StructureNotifyMask,
|
|
|
|
WaitVisibilityProc, (ClientData) &done);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
done = 0;
|
2005-03-02 02:06:52 -05:00
|
|
|
/* lib_eventloop_core(check_rootwidget_flag, 0, &done); */
|
2005-12-06 11:05:50 -05:00
|
|
|
lib_eventloop_launcher(check_rootwidget_flag, 0, &done, interp);
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
/* exception check */
|
|
|
|
if (!NIL_P(rbtk_pending_exception)) {
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
Tcl_DecrRefCount(objv[2]);
|
|
|
|
#endif
|
|
|
|
Tcl_Release(interp);
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (rb_obj_is_kind_of(rbtk_pending_exception, rb_eSystemExit)) {
|
|
|
|
*/
|
|
|
|
if (rb_obj_is_kind_of(rbtk_pending_exception, rb_eSystemExit)
|
|
|
|
|| rb_obj_is_kind_of(rbtk_pending_exception, rb_eInterrupt)) {
|
|
|
|
return TCL_RETURN;
|
|
|
|
} else{
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* trap check */
|
|
|
|
if (rb_trap_pending) {
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
Tcl_DecrRefCount(objv[2]);
|
|
|
|
#endif
|
|
|
|
Tcl_Release(interp);
|
|
|
|
|
|
|
|
return TCL_RETURN;
|
|
|
|
}
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
if (done != 1) {
|
|
|
|
/*
|
|
|
|
* Note that we do not delete the event handler because it
|
|
|
|
* was deleted automatically when the window was destroyed.
|
|
|
|
*/
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_ResetResult(interp);
|
|
|
|
Tcl_AppendResult(interp, "window \"", nameString,
|
|
|
|
"\" was deleted before its visibility changed",
|
|
|
|
(char *) NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(objv[2]);
|
2004-09-17 02:05:33 -04:00
|
|
|
#endif
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(interp);
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(objv[2]);
|
2004-09-17 02:05:33 -04:00
|
|
|
#endif
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tk_DeleteEventHandler(window,
|
|
|
|
VisibilityChangeMask|StructureNotifyMask,
|
|
|
|
WaitVisibilityProc, (ClientData) &done);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
break;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
case TKWAIT_WINDOW:
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
if (!tk_stubs_init_p() || Tk_MainWindow(interp) == (Tk_Window)NULL) {
|
2004-10-11 00:51:21 -04:00
|
|
|
window = NULL;
|
|
|
|
} else {
|
|
|
|
window = Tk_NameToWindow(interp, nameString, tkwin);
|
|
|
|
}
|
2004-09-17 02:05:33 -04:00
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(objv[2]);
|
2004-09-17 02:05:33 -04:00
|
|
|
#endif
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
if (window == NULL) {
|
2005-07-28 05:14:59 -04:00
|
|
|
Tcl_AppendResult(interp, "tkwait: ",
|
|
|
|
"no main-window (not Tk application?)",
|
|
|
|
(char*)NULL);
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
Tcl_Release(interp);
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tk_CreateEventHandler(window, StructureNotifyMask,
|
|
|
|
WaitWindowProc, (ClientData) &done);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
done = 0;
|
2005-03-02 02:06:52 -05:00
|
|
|
/* lib_eventloop_core(check_rootwidget_flag, 0, &done); */
|
2005-12-06 11:05:50 -05:00
|
|
|
lib_eventloop_launcher(check_rootwidget_flag, 0, &done, interp);
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
/* exception check */
|
|
|
|
if (!NIL_P(rbtk_pending_exception)) {
|
|
|
|
Tcl_Release(interp);
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (rb_obj_is_kind_of(rbtk_pending_exception, rb_eSystemExit)) {
|
|
|
|
*/
|
|
|
|
if (rb_obj_is_kind_of(rbtk_pending_exception, rb_eSystemExit)
|
|
|
|
|| rb_obj_is_kind_of(rbtk_pending_exception, rb_eInterrupt)) {
|
|
|
|
return TCL_RETURN;
|
|
|
|
} else{
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* trap check */
|
|
|
|
if (rb_trap_pending) {
|
|
|
|
Tcl_Release(interp);
|
|
|
|
|
|
|
|
return TCL_RETURN;
|
|
|
|
}
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
/*
|
|
|
|
* Note: there's no need to delete the event handler. It was
|
|
|
|
* deleted automatically when the window was destroyed.
|
|
|
|
*/
|
|
|
|
break;
|
2003-10-14 11:25:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clear out the interpreter's result, since it may have been set
|
|
|
|
* by event handlers.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Tcl_ResetResult(interp);
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_Release(interp);
|
2003-10-14 11:25:45 -04:00
|
|
|
return TCL_OK;
|
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/****************************/
|
|
|
|
/* vwait/tkwait with thread */
|
|
|
|
/****************************/
|
|
|
|
struct th_vwait_param {
|
|
|
|
VALUE thread;
|
|
|
|
int done;
|
|
|
|
};
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
static char *rb_threadVwaitProc _((ClientData, Tcl_Interp *,
|
2004-10-11 00:51:21 -04:00
|
|
|
CONST84 char *,CONST84 char *, int));
|
2004-05-01 12:09:54 -04:00
|
|
|
static char *
|
|
|
|
rb_threadVwaitProc(clientData, interp, name1, name2, flags)
|
|
|
|
ClientData clientData; /* Pointer to integer to set to 1. */
|
|
|
|
Tcl_Interp *interp; /* Interpreter containing variable. */
|
|
|
|
CONST84 char *name1; /* Name of variable. */
|
|
|
|
CONST84 char *name2; /* Second part of variable name. */
|
|
|
|
int flags; /* Information about what happened. */
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
static char *rb_threadVwaitProc _((ClientData, Tcl_Interp *,
|
2004-10-11 00:51:21 -04:00
|
|
|
char *, char *, int));
|
2004-05-01 12:09:54 -04:00
|
|
|
static char *
|
|
|
|
rb_threadVwaitProc(clientData, interp, name1, name2, flags)
|
|
|
|
ClientData clientData; /* Pointer to integer to set to 1. */
|
|
|
|
Tcl_Interp *interp; /* Interpreter containing variable. */
|
|
|
|
char *name1; /* Name of variable. */
|
|
|
|
char *name2; /* Second part of variable name. */
|
|
|
|
int flags; /* Information about what happened. */
|
|
|
|
#endif
|
2003-10-14 11:25:45 -04:00
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
struct th_vwait_param *param = (struct th_vwait_param *) clientData;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
if (flags & (TCL_INTERP_DESTROYED | TCL_TRACE_DESTROYED)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
param->done = -1;
|
2004-09-17 02:05:33 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
param->done = 1;
|
2004-09-17 02:05:33 -04:00
|
|
|
}
|
|
|
|
rb_thread_wakeup(param->thread);
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
return (char *)NULL;
|
|
|
|
}
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
#define TKWAIT_MODE_VISIBILITY 1
|
|
|
|
#define TKWAIT_MODE_DESTROY 2
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
static void rb_threadWaitVisibilityProc _((ClientData, XEvent *));
|
1998-01-16 07:19:09 -05:00
|
|
|
static void
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_threadWaitVisibilityProc(clientData, eventPtr)
|
|
|
|
ClientData clientData; /* Pointer to integer to set to 1. */
|
|
|
|
XEvent *eventPtr; /* Information about event (not used). */
|
1998-01-16 07:19:09 -05:00
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
struct th_vwait_param *param = (struct th_vwait_param *) clientData;
|
|
|
|
|
|
|
|
if (eventPtr->type == VisibilityNotify) {
|
2004-09-17 02:05:33 -04:00
|
|
|
param->done = TKWAIT_MODE_VISIBILITY;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
if (eventPtr->type == DestroyNotify) {
|
2004-09-17 02:05:33 -04:00
|
|
|
param->done = TKWAIT_MODE_DESTROY;
|
2002-08-19 01:56:09 -04:00
|
|
|
}
|
2004-09-17 02:05:33 -04:00
|
|
|
rb_thread_wakeup(param->thread);
|
1998-01-16 07:19:09 -05:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
static void rb_threadWaitWindowProc _((ClientData, XEvent *));
|
|
|
|
static void
|
|
|
|
rb_threadWaitWindowProc(clientData, eventPtr)
|
|
|
|
ClientData clientData; /* Pointer to integer to set to 1. */
|
|
|
|
XEvent *eventPtr; /* Information about event. */
|
2002-08-19 01:56:09 -04:00
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
struct th_vwait_param *param = (struct th_vwait_param *) clientData;
|
|
|
|
|
|
|
|
if (eventPtr->type == DestroyNotify) {
|
2004-09-17 02:05:33 -04:00
|
|
|
param->done = TKWAIT_MODE_DESTROY;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
2004-09-17 02:05:33 -04:00
|
|
|
rb_thread_wakeup(param->thread);
|
2002-08-19 01:56:09 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
static int
|
|
|
|
ip_rb_threadVwaitObjCmd(clientData, interp, objc, objv)
|
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int objc;
|
|
|
|
Tcl_Obj *CONST objv[];
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
static int
|
|
|
|
ip_rb_threadVwaitCommand(clientData, interp, objc, objv)
|
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int objc;
|
|
|
|
char *objv[];
|
|
|
|
#endif
|
1998-01-16 07:19:09 -05:00
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
struct th_vwait_param *param;
|
|
|
|
char *nameString;
|
|
|
|
int ret, dummy;
|
|
|
|
int thr_crit_bup;
|
|
|
|
volatile VALUE current_thread = rb_thread_current();
|
2003-07-23 12:07:35 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("Ruby's 'thread_vwait' is called");
|
2005-03-02 02:06:52 -05:00
|
|
|
if (interp == (Tcl_Interp*)NULL) {
|
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eRuntimeError,
|
|
|
|
"IP is deleted");
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2003-07-23 12:07:35 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (rb_thread_alone() || eventloop_thread == current_thread) {
|
2003-06-21 04:47:22 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("call ip_rbVwaitObjCmd");
|
|
|
|
return ip_rbVwaitObjCmd(clientData, interp, objc, objv);
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("call ip_rbVwaitCommand");
|
|
|
|
return ip_rbVwaitCommand(clientData, interp, objc, objv);
|
2003-06-21 04:47:22 -04:00
|
|
|
#endif
|
2003-08-29 04:34:14 -04:00
|
|
|
}
|
1998-01-16 07:19:09 -05:00
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_Preserve(interp);
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (objc != 2) {
|
|
|
|
#ifdef Tcl_WrongNumArgs
|
|
|
|
Tcl_WrongNumArgs(interp, 1, objv, "name");
|
1999-01-19 23:59:39 -05:00
|
|
|
#else
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
1998-01-16 07:19:09 -05:00
|
|
|
|
2003-10-14 11:25:45 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
/* nameString = Tcl_GetString(objv[0]); */
|
|
|
|
nameString = Tcl_GetStringFromObj(objv[0], &dummy);
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2004-10-11 00:51:21 -04:00
|
|
|
nameString = objv[0];
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
|
|
|
Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
|
2004-10-11 00:51:21 -04:00
|
|
|
nameString, " name\"", (char *) NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
2004-09-17 02:05:33 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(interp);
|
2004-05-01 12:09:54 -04:00
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2004-09-17 02:05:33 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_IncrRefCount(objv[1]);
|
2004-05-01 12:09:54 -04:00
|
|
|
/* nameString = Tcl_GetString(objv[1]); */
|
|
|
|
nameString = Tcl_GetStringFromObj(objv[1], &dummy);
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
nameString = objv[1];
|
|
|
|
#endif
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
param = (struct th_vwait_param *)Tcl_Alloc(sizeof(struct th_vwait_param));
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_Preserve(param);
|
2004-05-01 12:09:54 -04:00
|
|
|
param->thread = current_thread;
|
|
|
|
param->done = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (Tcl_TraceVar(interp, nameString,
|
2004-10-11 00:51:21 -04:00
|
|
|
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
|
|
|
rb_threadVwaitProc, (ClientData) param) != TCL_OK) {
|
2004-05-01 12:09:54 -04:00
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
ret = Tcl_TraceVar(interp, nameString,
|
2004-10-11 00:51:21 -04:00
|
|
|
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
|
|
|
rb_threadVwaitProc, (ClientData) param);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
|
|
|
if (ret != TCL_OK) {
|
2005-06-16 02:22:19 -04:00
|
|
|
Tcl_Release(param);
|
2005-03-02 02:06:52 -05:00
|
|
|
Tcl_Free((char *)param);
|
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(objv[1]);
|
2004-09-17 02:05:33 -04:00
|
|
|
#endif
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(interp);
|
2004-05-01 12:09:54 -04:00
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if (!param->done) { */
|
|
|
|
while(!param->done) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_stop();
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
if (param->done > 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_UntraceVar(interp, nameString,
|
|
|
|
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
|
|
|
rb_threadVwaitProc, (ClientData) param);
|
2004-09-17 02:05:33 -04:00
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_Release(param);
|
2004-05-01 12:09:54 -04:00
|
|
|
Tcl_Free((char *)param);
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
Tcl_DecrRefCount(objv[1]);
|
|
|
|
#endif
|
|
|
|
Tcl_Release(interp);
|
2004-05-01 12:09:54 -04:00
|
|
|
return TCL_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
static int
|
|
|
|
ip_rb_threadTkWaitObjCmd(clientData, interp, objc, objv)
|
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int objc;
|
|
|
|
Tcl_Obj *CONST objv[];
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
static int
|
|
|
|
ip_rb_threadTkWaitCommand(clientData, interp, objc, objv)
|
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int objc;
|
|
|
|
char *objv[];
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
struct th_vwait_param *param;
|
|
|
|
Tk_Window tkwin = (Tk_Window) clientData;
|
2004-09-17 02:05:33 -04:00
|
|
|
Tk_Window window;
|
2004-05-01 12:09:54 -04:00
|
|
|
int index;
|
|
|
|
static CONST char *optionStrings[] = { "variable", "visibility", "window",
|
2004-10-11 00:51:21 -04:00
|
|
|
(char *) NULL };
|
2004-05-01 12:09:54 -04:00
|
|
|
enum options { TKWAIT_VARIABLE, TKWAIT_VISIBILITY, TKWAIT_WINDOW };
|
|
|
|
char *nameString;
|
|
|
|
int ret, dummy;
|
|
|
|
int thr_crit_bup;
|
|
|
|
volatile VALUE current_thread = rb_thread_current();
|
|
|
|
|
|
|
|
DUMP1("Ruby's 'thread_tkwait' is called");
|
2005-03-02 02:06:52 -05:00
|
|
|
if (interp == (Tcl_Interp*)NULL) {
|
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eRuntimeError,
|
|
|
|
"IP is deleted");
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
if (rb_thread_alone() || eventloop_thread == current_thread) {
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("call ip_rbTkWaitObjCmd");
|
|
|
|
return ip_rbTkWaitObjCmd(clientData, interp, objc, objv);
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("call rb_VwaitCommand");
|
|
|
|
return ip_rbTkWaitCommand(clientData, interp, objc, objv);
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_Preserve(interp);
|
|
|
|
Tcl_Preserve(tkwin);
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (objc != 3) {
|
|
|
|
#ifdef Tcl_WrongNumArgs
|
|
|
|
Tcl_WrongNumArgs(interp, 1, objv, "variable|visibility|window name");
|
|
|
|
#else
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_GetStringFromObj(objv[0], &dummy),
|
|
|
|
" variable|visibility|window name\"",
|
|
|
|
(char *) NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
Tcl_AppendResult(interp, "wrong number of arguments: should be \"",
|
2004-10-11 00:51:21 -04:00
|
|
|
objv[0], " variable|visibility|window name\"",
|
|
|
|
(char *) NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
2004-09-17 02:05:33 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(tkwin);
|
|
|
|
Tcl_Release(interp);
|
2004-05-01 12:09:54 -04:00
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
/*
|
|
|
|
if (Tcl_GetIndexFromObj(interp, objv[1],
|
|
|
|
(CONST84 char **)optionStrings,
|
2004-10-11 00:51:21 -04:00
|
|
|
"option", 0, &index) != TCL_OK) {
|
2004-05-01 12:09:54 -04:00
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
ret = Tcl_GetIndexFromObj(interp, objv[1],
|
2004-10-11 00:51:21 -04:00
|
|
|
(CONST84 char **)optionStrings,
|
|
|
|
"option", 0, &index);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
|
|
|
if (ret != TCL_OK) {
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(tkwin);
|
|
|
|
Tcl_Release(interp);
|
2004-05-01 12:09:54 -04:00
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
{
|
2004-10-11 00:51:21 -04:00
|
|
|
int c = objv[1][0];
|
|
|
|
size_t length = strlen(objv[1]);
|
|
|
|
|
|
|
|
if ((c == 'v') && (strncmp(objv[1], "variable", length) == 0)
|
|
|
|
&& (length >= 2)) {
|
|
|
|
index = TKWAIT_VARIABLE;
|
|
|
|
} else if ((c == 'v') && (strncmp(objv[1], "visibility", length) == 0)
|
|
|
|
&& (length >= 2)) {
|
|
|
|
index = TKWAIT_VISIBILITY;
|
|
|
|
} else if ((c == 'w') && (strncmp(objv[1], "window", length) == 0)) {
|
|
|
|
index = TKWAIT_WINDOW;
|
|
|
|
} else {
|
|
|
|
Tcl_AppendResult(interp, "bad option \"", objv[1],
|
|
|
|
"\": must be variable, visibility, or window",
|
|
|
|
(char *) NULL);
|
|
|
|
Tcl_Release(tkwin);
|
|
|
|
Tcl_Release(interp);
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_IncrRefCount(objv[2]);
|
2004-05-01 12:09:54 -04:00
|
|
|
/* nameString = Tcl_GetString(objv[2]); */
|
|
|
|
nameString = Tcl_GetStringFromObj(objv[2], &dummy);
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
nameString = objv[2];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
param = (struct th_vwait_param *)Tcl_Alloc(sizeof(struct th_vwait_param));
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_Preserve(param);
|
2004-05-01 12:09:54 -04:00
|
|
|
param->thread = current_thread;
|
|
|
|
param->done = 0;
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
|
|
|
switch ((enum options) index) {
|
2004-09-17 02:05:33 -04:00
|
|
|
case TKWAIT_VARIABLE:
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
/*
|
|
|
|
if (Tcl_TraceVar(interp, nameString,
|
|
|
|
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
|
|
|
rb_threadVwaitProc, (ClientData) param) != TCL_OK) {
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
ret = Tcl_TraceVar(interp, nameString,
|
|
|
|
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
|
|
|
rb_threadVwaitProc, (ClientData) param);
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
|
|
|
if (ret != TCL_OK) {
|
|
|
|
Tcl_Release(param);
|
|
|
|
Tcl_Free((char *)param);
|
2004-09-17 02:05:33 -04:00
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(objv[2]);
|
2004-09-17 02:05:33 -04:00
|
|
|
#endif
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(tkwin);
|
|
|
|
Tcl_Release(interp);
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
/* if (!param->done) { */
|
|
|
|
while(!param->done) {
|
|
|
|
rb_thread_stop();
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
if (param->done > 0) {
|
|
|
|
Tcl_UntraceVar(interp, nameString,
|
|
|
|
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
|
|
|
|
rb_threadVwaitProc, (ClientData) param);
|
|
|
|
}
|
2004-09-17 02:05:33 -04:00
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(objv[2]);
|
2004-09-17 02:05:33 -04:00
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
break;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
case TKWAIT_VISIBILITY:
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
if (!tk_stubs_init_p() || Tk_MainWindow(interp) == (Tk_Window)NULL) {
|
2004-10-11 00:51:21 -04:00
|
|
|
window = NULL;
|
|
|
|
} else {
|
|
|
|
window = Tk_NameToWindow(interp, nameString, tkwin);
|
|
|
|
}
|
2004-09-17 02:05:33 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
if (window == NULL) {
|
2005-07-28 05:14:59 -04:00
|
|
|
Tcl_AppendResult(interp, "thread_tkwait: ",
|
|
|
|
"no main-window (not Tk application?)",
|
|
|
|
(char*)NULL);
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-09-17 02:05:33 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(param);
|
|
|
|
Tcl_Free((char *)param);
|
2004-09-17 02:05:33 -04:00
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(objv[2]);
|
|
|
|
#endif
|
|
|
|
Tcl_Release(tkwin);
|
|
|
|
Tcl_Release(interp);
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
Tcl_Preserve(window);
|
|
|
|
|
|
|
|
Tk_CreateEventHandler(window,
|
|
|
|
VisibilityChangeMask|StructureNotifyMask,
|
|
|
|
rb_threadWaitVisibilityProc, (ClientData) param);
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
|
|
|
/* if (!param->done) { */
|
|
|
|
/*
|
|
|
|
while(!param->done) {
|
|
|
|
rb_thread_stop();
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
while(param->done != TKWAIT_MODE_VISIBILITY) {
|
|
|
|
if (param->done == TKWAIT_MODE_DESTROY) break;
|
|
|
|
rb_thread_stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
/* when a window is destroyed, no need to call Tk_DeleteEventHandler */
|
|
|
|
if (param->done != TKWAIT_MODE_DESTROY) {
|
|
|
|
Tk_DeleteEventHandler(window,
|
|
|
|
VisibilityChangeMask|StructureNotifyMask,
|
|
|
|
rb_threadWaitVisibilityProc,
|
|
|
|
(ClientData) param);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (param->done != 1) {
|
|
|
|
Tcl_ResetResult(interp);
|
|
|
|
Tcl_AppendResult(interp, "window \"", nameString,
|
|
|
|
"\" was deleted before its visibility changed",
|
|
|
|
(char *) NULL);
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
|
|
|
Tcl_Release(window);
|
|
|
|
|
|
|
|
Tcl_Release(param);
|
|
|
|
Tcl_Free((char *)param);
|
2004-09-17 02:05:33 -04:00
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(objv[2]);
|
2004-09-17 02:05:33 -04:00
|
|
|
#endif
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(tkwin);
|
|
|
|
Tcl_Release(interp);
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(window);
|
2004-09-17 02:05:33 -04:00
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(objv[2]);
|
2004-09-17 02:05:33 -04:00
|
|
|
#endif
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
break;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
case TKWAIT_WINDOW:
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2004-09-17 02:05:33 -04:00
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
if (!tk_stubs_init_p() || Tk_MainWindow(interp) == (Tk_Window)NULL) {
|
2004-10-11 00:51:21 -04:00
|
|
|
window = NULL;
|
|
|
|
} else {
|
|
|
|
window = Tk_NameToWindow(interp, nameString, tkwin);
|
|
|
|
}
|
2004-09-17 02:05:33 -04:00
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(objv[2]);
|
2004-09-17 02:05:33 -04:00
|
|
|
#endif
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
if (window == NULL) {
|
2005-07-28 05:14:59 -04:00
|
|
|
Tcl_AppendResult(interp, "thread_tkwait: ",
|
|
|
|
"no main-window (not Tk application?)",
|
|
|
|
(char*)NULL);
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-09-17 02:05:33 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(param);
|
|
|
|
Tcl_Free((char *)param);
|
2004-09-17 02:05:33 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(tkwin);
|
|
|
|
Tcl_Release(interp);
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Preserve(window);
|
2004-09-17 02:05:33 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tk_CreateEventHandler(window, StructureNotifyMask,
|
|
|
|
rb_threadWaitWindowProc, (ClientData) param);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
/* if (!param->done) { */
|
|
|
|
/*
|
|
|
|
while(!param->done) {
|
|
|
|
rb_thread_stop();
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
while(param->done != TKWAIT_MODE_DESTROY) {
|
|
|
|
rb_thread_stop();
|
|
|
|
}
|
2004-09-17 02:05:33 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_Release(window);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
/* when a window is destroyed, no need to call Tk_DeleteEventHandler
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tk_DeleteEventHandler(window, StructureNotifyMask,
|
|
|
|
rb_threadWaitWindowProc, (ClientData) param);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
*/
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
break;
|
2004-05-01 12:09:54 -04:00
|
|
|
} /* end of 'switch' statement */
|
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_Release(param);
|
2004-05-01 12:09:54 -04:00
|
|
|
Tcl_Free((char *)param);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clear out the interpreter's result, since it may have been set
|
|
|
|
* by event handlers.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Tcl_ResetResult(interp);
|
2004-09-17 02:05:33 -04:00
|
|
|
|
|
|
|
Tcl_Release(tkwin);
|
|
|
|
Tcl_Release(interp);
|
2004-05-01 12:09:54 -04:00
|
|
|
return TCL_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ip_thread_vwait(self, var)
|
|
|
|
VALUE self;
|
|
|
|
VALUE var;
|
|
|
|
{
|
2005-08-04 23:51:50 -04:00
|
|
|
VALUE argv[2];
|
2004-09-17 02:05:33 -04:00
|
|
|
volatile VALUE cmd_str = rb_str_new2("thread_vwait");
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
argv[0] = cmd_str;
|
2004-05-01 12:09:54 -04:00
|
|
|
argv[1] = var;
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2005-08-04 23:51:50 -04:00
|
|
|
return ip_invoke_real(2, argv, self);
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ip_thread_tkwait(self, mode, target)
|
|
|
|
VALUE self;
|
|
|
|
VALUE mode;
|
|
|
|
VALUE target;
|
|
|
|
{
|
2005-08-04 23:51:50 -04:00
|
|
|
VALUE argv[3];
|
2004-09-17 02:05:33 -04:00
|
|
|
volatile VALUE cmd_str = rb_str_new2("thread_tkwait");
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
argv[0] = cmd_str;
|
2004-05-01 12:09:54 -04:00
|
|
|
argv[1] = mode;
|
|
|
|
argv[2] = target;
|
2004-08-30 23:32:33 -04:00
|
|
|
|
2005-08-04 23:51:50 -04:00
|
|
|
return ip_invoke_real(3, argv, self);
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* delete slave interpreters */
|
2005-08-04 05:41:57 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-09-11 13:45:53 -04:00
|
|
|
static void
|
|
|
|
delete_slaves(ip)
|
|
|
|
Tcl_Interp *ip;
|
|
|
|
{
|
2005-03-02 02:06:52 -05:00
|
|
|
int thr_crit_bup;
|
2004-09-11 13:45:53 -04:00
|
|
|
Tcl_Interp *slave;
|
|
|
|
Tcl_Obj *slave_list, *elem;
|
|
|
|
char *slave_name;
|
|
|
|
int i, len;
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
DUMP1("delete slaves");
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2005-01-25 00:09:22 -05:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (!Tcl_InterpDeleted(ip) && Tcl_Eval(ip, "interp slaves") == TCL_OK) {
|
|
|
|
slave_list = Tcl_GetObjResult(ip);
|
|
|
|
Tcl_IncrRefCount(slave_list);
|
2004-09-29 11:54:32 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (Tcl_ListObjLength((Tcl_Interp*)NULL, slave_list, &len) == TCL_OK) {
|
|
|
|
for(i = 0; i < len; i++) {
|
|
|
|
Tcl_ListObjIndex((Tcl_Interp*)NULL, slave_list, i, &elem);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (elem == (Tcl_Obj*)NULL) continue;
|
|
|
|
|
2006-04-25 05:02:00 -04:00
|
|
|
Tcl_IncrRefCount(elem);
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* get slave */
|
2005-07-28 05:14:59 -04:00
|
|
|
/* slave_name = Tcl_GetString(elem); */
|
|
|
|
slave_name = Tcl_GetStringFromObj(elem, (int*)NULL);
|
2005-03-02 02:06:52 -05:00
|
|
|
DUMP2("delete slave:'%s'", slave_name);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
Tcl_DecrRefCount(elem);
|
|
|
|
|
|
|
|
slave = Tcl_GetSlave(ip, slave_name);
|
|
|
|
if (slave == (Tcl_Interp*)NULL) continue;
|
|
|
|
|
|
|
|
/* call ip_finalize */
|
|
|
|
ip_finalize(slave);
|
|
|
|
|
|
|
|
Tcl_DeleteInterp(slave);
|
2005-04-11 07:14:33 -04:00
|
|
|
/* Tcl_Release(slave); */
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
}
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(slave_list);
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
}
|
2005-08-04 05:41:57 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
static void
|
|
|
|
delete_slaves(ip)
|
|
|
|
Tcl_Interp *ip;
|
|
|
|
{
|
|
|
|
int thr_crit_bup;
|
|
|
|
Tcl_Interp *slave;
|
|
|
|
int argc;
|
|
|
|
char **argv;
|
|
|
|
char *slave_list;
|
|
|
|
char *slave_name;
|
|
|
|
int i, len;
|
|
|
|
|
|
|
|
DUMP1("delete slaves");
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
if (!Tcl_InterpDeleted(ip) && Tcl_Eval(ip, "interp slaves") == TCL_OK) {
|
|
|
|
slave_list = ip->result;
|
|
|
|
if (Tcl_SplitList((Tcl_Interp*)NULL,
|
|
|
|
slave_list, &argc, &argv) == TCL_OK) {
|
|
|
|
for(i = 0; i < argc; i++) {
|
|
|
|
slave_name = argv[i];
|
|
|
|
|
|
|
|
DUMP2("delete slave:'%s'", slave_name);
|
|
|
|
|
|
|
|
slave = Tcl_GetSlave(ip, slave_name);
|
|
|
|
if (slave == (Tcl_Interp*)NULL) continue;
|
|
|
|
|
|
|
|
/* call ip_finalize */
|
|
|
|
ip_finalize(slave);
|
|
|
|
|
|
|
|
Tcl_DeleteInterp(slave);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
}
|
|
|
|
#endif
|
2004-09-11 13:45:53 -04:00
|
|
|
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* finalize operation */
|
2007-08-18 04:44:44 -04:00
|
|
|
static void
|
2006-07-10 05:52:30 -04:00
|
|
|
lib_mark_at_exit(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
at_exit = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
ip_null_proc(clientData, interp, argc, argv)
|
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int argc;
|
|
|
|
Tcl_Obj *CONST argv[];
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
ip_null_proc(clientData, interp, argc, argv)
|
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
Tcl_ResetResult(interp);
|
|
|
|
return TCL_OK;
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
static void
|
|
|
|
ip_finalize(ip)
|
|
|
|
Tcl_Interp *ip;
|
|
|
|
{
|
|
|
|
Tcl_CmdInfo info;
|
|
|
|
int thr_crit_bup;
|
2006-04-05 12:08:45 -04:00
|
|
|
|
|
|
|
VALUE rb_debug_bup, rb_verbose_bup;
|
|
|
|
/* When ruby is exiting, printing debug messages in some callback
|
|
|
|
operations from Tcl-IP sometimes cause SEGV. I don't know the
|
|
|
|
reason. But I got SEGV when calling "rb_io_write(rb_stdout, ...)".
|
|
|
|
So, in some part of this function, debug mode and verbose mode
|
|
|
|
are disabled. If you know the reason, please fix it.
|
|
|
|
-- Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) */
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
DUMP1("start ip_finalize");
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (ip == (Tcl_Interp*)NULL) {
|
2005-07-28 05:14:59 -04:00
|
|
|
DUMP1("ip is NULL");
|
|
|
|
return;
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2006-04-05 12:08:45 -04:00
|
|
|
if (Tcl_InterpDeleted(ip)) {
|
2007-07-22 01:33:54 -04:00
|
|
|
DUMP2("ip(%p) is already deleted", ip);
|
2006-04-05 12:08:45 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
#if TCL_NAMESPACE_DEBUG
|
|
|
|
if (ip_null_namespace(ip)) {
|
2007-07-22 01:33:54 -04:00
|
|
|
DUMP2("ip(%p) has null namespace", ip);
|
2005-07-28 05:14:59 -04:00
|
|
|
return;
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
#endif
|
2005-01-25 00:09:22 -05:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2006-04-05 12:08:45 -04:00
|
|
|
rb_debug_bup = ruby_debug;
|
|
|
|
rb_verbose_bup = ruby_verbose;
|
2005-07-28 05:14:59 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
Tcl_Preserve(ip);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* delete slaves */
|
|
|
|
delete_slaves(ip);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2006-07-10 05:52:30 -04:00
|
|
|
/* shut off some connections from Tcl-proc to Ruby */
|
|
|
|
if (at_exit) {
|
|
|
|
/* NOTE: Only when at exit.
|
|
|
|
Because, ruby removes objects, which depends on the deleted
|
|
|
|
interpreter, on some callback operations.
|
|
|
|
It is important for GC. */
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
Tcl_CreateObjCommand(ip, "ruby", ip_null_proc,
|
|
|
|
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
Tcl_CreateObjCommand(ip, "ruby_eval", ip_null_proc,
|
|
|
|
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
Tcl_CreateObjCommand(ip, "ruby_cmd", ip_null_proc,
|
|
|
|
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
Tcl_CreateCommand(ip, "ruby", ip_null_proc,
|
|
|
|
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
Tcl_CreateCommand(ip, "ruby_eval", ip_null_proc,
|
|
|
|
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
Tcl_CreateCommand(ip, "ruby_cmd", ip_null_proc,
|
|
|
|
(ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* delete root widget */
|
2005-07-28 05:14:59 -04:00
|
|
|
#if 0
|
2005-04-11 13:29:51 -04:00
|
|
|
DUMP1("check `destroy'");
|
2005-04-11 23:39:50 -04:00
|
|
|
if (Tcl_GetCommandInfo(ip, "destroy", &info)) {
|
2005-04-11 13:29:51 -04:00
|
|
|
DUMP1("call `destroy'");
|
2005-04-11 23:39:50 -04:00
|
|
|
Tcl_GlobalEval(ip, "destroy .");
|
2005-04-11 13:29:51 -04:00
|
|
|
}
|
2005-07-28 05:14:59 -04:00
|
|
|
#endif
|
|
|
|
#if 1
|
|
|
|
DUMP1("destroy root widget");
|
|
|
|
if (tk_stubs_init_p() && Tk_MainWindow(ip) != (Tk_Window)NULL) {
|
|
|
|
DUMP1("call Tk_DestroyWindow");
|
2006-04-05 12:08:45 -04:00
|
|
|
ruby_debug = Qfalse;
|
|
|
|
ruby_verbose = Qnil;
|
2005-07-28 05:14:59 -04:00
|
|
|
Tk_DestroyWindow(Tk_MainWindow(ip));
|
2006-04-05 12:08:45 -04:00
|
|
|
ruby_debug = rb_debug_bup;
|
|
|
|
ruby_verbose = rb_verbose_bup;
|
2005-07-28 05:14:59 -04:00
|
|
|
}
|
|
|
|
#endif
|
2005-01-25 00:09:22 -05:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* call finalize-hook-proc */
|
2005-04-11 13:29:51 -04:00
|
|
|
DUMP1("check `finalize-hook-proc'");
|
2006-07-10 05:52:30 -04:00
|
|
|
if ( Tcl_GetCommandInfo(ip, finalize_hook_name, &info)) {
|
2005-03-02 02:06:52 -05:00
|
|
|
DUMP2("call finalize hook proc '%s'", finalize_hook_name);
|
2006-04-05 12:08:45 -04:00
|
|
|
ruby_debug = Qfalse;
|
|
|
|
ruby_verbose = Qnil;
|
2005-03-02 02:06:52 -05:00
|
|
|
Tcl_GlobalEval(ip, finalize_hook_name);
|
2006-04-05 12:08:45 -04:00
|
|
|
ruby_debug = rb_debug_bup;
|
|
|
|
ruby_verbose = rb_verbose_bup;
|
2004-08-30 23:32:33 -04:00
|
|
|
}
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2005-04-11 13:29:51 -04:00
|
|
|
DUMP1("check `foreach' & `after'");
|
2005-04-11 23:39:50 -04:00
|
|
|
if ( Tcl_GetCommandInfo(ip, "foreach", &info)
|
2005-04-11 13:29:51 -04:00
|
|
|
&& Tcl_GetCommandInfo(ip, "after", &info) ) {
|
2005-04-12 02:37:10 -04:00
|
|
|
DUMP1("cancel after callbacks");
|
2006-04-05 12:08:45 -04:00
|
|
|
ruby_debug = Qfalse;
|
|
|
|
ruby_verbose = Qnil;
|
2005-04-12 02:37:10 -04:00
|
|
|
Tcl_GlobalEval(ip, "foreach id [after info] {after cancel $id}");
|
2006-04-05 12:08:45 -04:00
|
|
|
ruby_debug = rb_debug_bup;
|
|
|
|
ruby_verbose = rb_verbose_bup;
|
2005-04-11 13:29:51 -04:00
|
|
|
}
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
Tcl_Release(ip);
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
DUMP1("finish ip_finalize");
|
2006-04-05 12:08:45 -04:00
|
|
|
ruby_debug = rb_debug_bup;
|
|
|
|
ruby_verbose = rb_verbose_bup;
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
/* destroy interpreter */
|
2004-05-01 12:09:54 -04:00
|
|
|
static void
|
|
|
|
ip_free(ptr)
|
|
|
|
struct tcltkip *ptr;
|
|
|
|
{
|
2005-03-02 02:06:52 -05:00
|
|
|
int thr_crit_bup;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-11-06 23:47:08 -05:00
|
|
|
DUMP2("free Tcl Interp %lx", (unsigned long)ptr->ip);
|
2004-05-01 12:09:54 -04:00
|
|
|
if (ptr) {
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if ( ptr->ip != (Tcl_Interp*)NULL
|
|
|
|
&& !Tcl_InterpDeleted(ptr->ip)
|
|
|
|
&& Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL
|
|
|
|
&& !Tcl_InterpDeleted(Tcl_GetMaster(ptr->ip)) ) {
|
2005-11-06 23:47:08 -05:00
|
|
|
DUMP2("parent IP(%lx) is not deleted",
|
|
|
|
(unsigned long)Tcl_GetMaster(ptr->ip));
|
|
|
|
DUMP2("slave IP(%lx) should not be deleted",
|
|
|
|
(unsigned long)ptr->ip);
|
2005-03-02 02:06:52 -05:00
|
|
|
free(ptr);
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
return;
|
|
|
|
}
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (ptr->ip == (Tcl_Interp*)NULL) {
|
|
|
|
DUMP1("ip_free is called for deleted IP");
|
|
|
|
free(ptr);
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
return;
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
ip_finalize(ptr->ip);
|
|
|
|
Tcl_DeleteInterp(ptr->ip);
|
|
|
|
Tcl_Release(ptr->ip);
|
2004-09-12 12:05:59 -04:00
|
|
|
|
2006-04-05 12:08:45 -04:00
|
|
|
ptr->ip = (Tcl_Interp*)NULL;
|
2004-10-11 00:51:21 -04:00
|
|
|
free(ptr);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("complete freeing Tcl Interp");
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* create and initialize interpreter */
|
|
|
|
static VALUE ip_alloc _((VALUE));
|
|
|
|
static VALUE
|
|
|
|
ip_alloc(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
return Data_Wrap_Struct(self, 0, ip_free, 0);
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
static void
|
|
|
|
ip_replace_wait_commands(interp, mainWin)
|
|
|
|
Tcl_Interp *interp;
|
2004-05-01 12:09:54 -04:00
|
|
|
Tk_Window mainWin;
|
2005-03-02 02:06:52 -05:00
|
|
|
{
|
|
|
|
/* replace 'vwait' command */
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
DUMP1("Tcl_CreateObjCommand(\"vwait\")");
|
|
|
|
Tcl_CreateObjCommand(interp, "vwait", ip_rbVwaitObjCmd,
|
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
DUMP1("Tcl_CreateCommand(\"vwait\")");
|
|
|
|
Tcl_CreateCommand(interp, "vwait", ip_rbVwaitCommand,
|
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* replace 'tkwait' command */
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
DUMP1("Tcl_CreateObjCommand(\"tkwait\")");
|
|
|
|
Tcl_CreateObjCommand(interp, "tkwait", ip_rbTkWaitObjCmd,
|
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
DUMP1("Tcl_CreateCommand(\"tkwait\")");
|
|
|
|
Tcl_CreateCommand(interp, "tkwait", ip_rbTkWaitCommand,
|
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
#endif
|
2004-09-08 02:23:41 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* add 'thread_vwait' command */
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
DUMP1("Tcl_CreateObjCommand(\"thread_vwait\")");
|
|
|
|
Tcl_CreateObjCommand(interp, "thread_vwait", ip_rb_threadVwaitObjCmd,
|
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
DUMP1("Tcl_CreateCommand(\"thread_vwait\")");
|
|
|
|
Tcl_CreateCommand(interp, "thread_vwait", ip_rb_threadVwaitCommand,
|
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* add 'thread_tkwait' command */
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
DUMP1("Tcl_CreateObjCommand(\"thread_tkwait\")");
|
|
|
|
Tcl_CreateObjCommand(interp, "thread_tkwait", ip_rb_threadTkWaitObjCmd,
|
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
DUMP1("Tcl_CreateCommand(\"thread_tkwait\")");
|
|
|
|
Tcl_CreateCommand(interp, "thread_tkwait", ip_rb_threadTkWaitCommand,
|
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* replace 'update' command */
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
DUMP1("Tcl_CreateObjCommand(\"update\")");
|
|
|
|
Tcl_CreateObjCommand(interp, "update", ip_rbUpdateObjCmd,
|
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
DUMP1("Tcl_CreateCommand(\"update\")");
|
|
|
|
Tcl_CreateCommand(interp, "update", ip_rbUpdateCommand,
|
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* add 'thread_update' command */
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
DUMP1("Tcl_CreateObjCommand(\"thread_update\")");
|
|
|
|
Tcl_CreateObjCommand(interp, "thread_update", ip_rb_threadUpdateObjCmd,
|
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
DUMP1("Tcl_CreateCommand(\"thread_update\")");
|
|
|
|
Tcl_CreateCommand(interp, "thread_update", ip_rb_threadUpdateCommand,
|
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
static int ip_rbNamespaceObjCmd _((ClientData, Tcl_Interp *, int,
|
|
|
|
Tcl_Obj *CONST []));
|
|
|
|
static int
|
|
|
|
ip_rbNamespaceObjCmd(clientData, interp, objc, objv)
|
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
int objc;
|
|
|
|
Tcl_Obj *CONST objv[];
|
|
|
|
{
|
|
|
|
Tcl_CmdInfo info;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!Tcl_GetCommandInfo(interp, "__orig_namespace_command__", &(info))) {
|
|
|
|
Tcl_ResetResult(interp);
|
|
|
|
Tcl_AppendResult(interp,
|
|
|
|
"invalid command name \"namespace\"", (char*)NULL);
|
|
|
|
return TCL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
rbtk_eventloop_depth++;
|
|
|
|
DUMP2("namespace wrapper enter depth == %d", rbtk_eventloop_depth);
|
|
|
|
|
|
|
|
if (info.isNativeObjectProc) {
|
|
|
|
ret = (*(info.objProc))(info.objClientData, interp, objc, objv);
|
|
|
|
} else {
|
|
|
|
/* string interface */
|
|
|
|
int i;
|
|
|
|
char **argv;
|
|
|
|
|
|
|
|
argv = (char **)Tcl_Alloc(sizeof(char *) * (objc + 1));
|
|
|
|
|
|
|
|
for(i = 0; i < objc; i++) {
|
2005-07-28 05:14:59 -04:00
|
|
|
/* argv[i] = Tcl_GetString(objv[i]); */
|
|
|
|
argv[i] = Tcl_GetStringFromObj(objv[i], (int*)NULL);
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
argv[objc] = (char *)NULL;
|
|
|
|
|
|
|
|
ret = (*(info.proc))(info.clientData, interp,
|
|
|
|
objc, (CONST84 char **)argv);
|
|
|
|
|
|
|
|
Tcl_Free((char*)argv);
|
|
|
|
}
|
|
|
|
|
|
|
|
DUMP2("namespace wrapper exit depth == %d", rbtk_eventloop_depth);
|
|
|
|
rbtk_eventloop_depth--;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static void
|
|
|
|
ip_wrap_namespace_command(interp)
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
{
|
2005-08-04 05:41:57 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2005-03-02 02:06:52 -05:00
|
|
|
Tcl_CmdInfo orig_info;
|
|
|
|
|
|
|
|
if (!Tcl_GetCommandInfo(interp, "namespace", &(orig_info))) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (orig_info.isNativeObjectProc) {
|
|
|
|
Tcl_CreateObjCommand(interp, "__orig_namespace_command__",
|
|
|
|
orig_info.objProc, orig_info.objClientData,
|
|
|
|
orig_info.deleteProc);
|
|
|
|
} else {
|
|
|
|
Tcl_CreateCommand(interp, "__orig_namespace_command__",
|
|
|
|
orig_info.proc, orig_info.clientData,
|
|
|
|
orig_info.deleteProc);
|
|
|
|
}
|
|
|
|
|
|
|
|
Tcl_CreateObjCommand(interp, "namespace", ip_rbNamespaceObjCmd,
|
|
|
|
(ClientData) 0, (Tcl_CmdDeleteProc *)NULL);
|
2005-08-04 05:41:57 -04:00
|
|
|
#endif
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* call when interpreter is deleted */
|
|
|
|
static void
|
|
|
|
ip_CallWhenDeleted(clientData, ip)
|
|
|
|
ClientData clientData;
|
|
|
|
Tcl_Interp *ip;
|
|
|
|
{
|
|
|
|
int thr_crit_bup;
|
2005-11-06 23:47:08 -05:00
|
|
|
/* Tk_Window main_win = (Tk_Window) clientData; */
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
DUMP1("start ip_CallWhenDeleted");
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
ip_finalize(ip);
|
|
|
|
|
|
|
|
DUMP1("finish ip_CallWhenDeleted");
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* initialize interpreter */
|
|
|
|
static VALUE
|
|
|
|
ip_init(argc, argv, self)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr; /* tcltkip data struct */
|
|
|
|
VALUE argv0, opts;
|
|
|
|
int cnt;
|
2005-07-28 05:14:59 -04:00
|
|
|
int st;
|
2005-03-02 02:06:52 -05:00
|
|
|
int with_tk = 1;
|
2005-07-28 05:14:59 -04:00
|
|
|
Tk_Window mainWin = (Tk_Window)NULL;
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
/* security check */
|
2006-12-31 18:12:35 -05:00
|
|
|
if (rb_safe_level() >= 4) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_raise(rb_eSecurityError,
|
|
|
|
"Cannot create a TclTkIp object at level %d",
|
2006-12-31 18:12:35 -05:00
|
|
|
rb_safe_level());
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* create object */
|
|
|
|
Data_Get_Struct(self, struct tcltkip, ptr);
|
|
|
|
ptr = ALLOC(struct tcltkip);
|
|
|
|
DATA_PTR(self) = ptr;
|
|
|
|
ptr->ref_count = 0;
|
|
|
|
ptr->allow_ruby_exit = 1;
|
2004-05-01 12:09:54 -04:00
|
|
|
ptr->return_value = 0;
|
|
|
|
|
|
|
|
/* from Tk_Main() */
|
|
|
|
DUMP1("Tcl_CreateInterp");
|
2005-07-28 05:14:59 -04:00
|
|
|
ptr->ip = ruby_tcl_create_ip_and_stubs_init(&st);
|
2004-09-12 12:05:59 -04:00
|
|
|
if (ptr->ip == NULL) {
|
2005-07-28 05:14:59 -04:00
|
|
|
switch(st) {
|
|
|
|
case TCLTK_STUBS_OK:
|
|
|
|
break;
|
|
|
|
case NO_TCL_DLL:
|
|
|
|
rb_raise(rb_eLoadError, "tcltklib: fail to open tcl_dll");
|
|
|
|
case NO_FindExecutable:
|
|
|
|
rb_raise(rb_eLoadError, "tcltklib: can't find Tcl_FindExecutable");
|
|
|
|
case NO_CreateInterp:
|
|
|
|
rb_raise(rb_eLoadError, "tcltklib: can't find Tcl_CreateInterp()");
|
|
|
|
case NO_DeleteInterp:
|
|
|
|
rb_raise(rb_eLoadError, "tcltklib: can't find Tcl_DeleteInterp()");
|
|
|
|
case FAIL_CreateInterp:
|
|
|
|
rb_raise(rb_eRuntimeError, "tcltklib: fail to create a new IP");
|
|
|
|
case FAIL_Tcl_InitStubs:
|
|
|
|
rb_raise(rb_eRuntimeError, "tcltklib: fail to Tcl_InitStubs()");
|
|
|
|
default:
|
|
|
|
rb_raise(rb_eRuntimeError, "tcltklib: unknown error(%d) on ruby_tcl_create_ip_and_stubs_init", st);
|
|
|
|
}
|
2004-09-12 12:05:59 -04:00
|
|
|
}
|
|
|
|
|
2005-01-30 23:14:50 -05:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2005-03-02 02:06:52 -05:00
|
|
|
#if TCL_NAMESPACE_DEBUG
|
2005-01-30 23:14:50 -05:00
|
|
|
DUMP1("get current namespace");
|
|
|
|
if ((ptr->default_ns = Tcl_GetCurrentNamespace(ptr->ip))
|
|
|
|
== (Tcl_Namespace*)NULL) {
|
|
|
|
rb_raise(rb_eRuntimeError, "a new Tk interpreter has a NULL namespace");
|
|
|
|
}
|
2005-03-02 02:06:52 -05:00
|
|
|
#endif
|
2005-01-30 23:14:50 -05:00
|
|
|
#endif
|
|
|
|
|
2004-09-29 11:54:32 -04:00
|
|
|
rbtk_preserve_ip(ptr);
|
|
|
|
DUMP2("IP ref_count = %d", ptr->ref_count);
|
2004-05-01 12:09:54 -04:00
|
|
|
current_interp = ptr->ip;
|
|
|
|
|
2004-09-12 12:05:59 -04:00
|
|
|
ptr->has_orig_exit
|
2004-10-11 00:51:21 -04:00
|
|
|
= Tcl_GetCommandInfo(ptr->ip, "exit", &(ptr->orig_exit_info));
|
2004-09-12 12:05:59 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* from Tcl_AppInit() */
|
|
|
|
DUMP1("Tcl_Init");
|
|
|
|
if (Tcl_Init(ptr->ip) == TCL_ERROR) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_raise(rb_eRuntimeError, "%s", Tcl_GetStringResult(ptr->ip));
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* set variables */
|
|
|
|
cnt = rb_scan_args(argc, argv, "02", &argv0, &opts);
|
|
|
|
switch(cnt) {
|
|
|
|
case 2:
|
2004-10-11 00:51:21 -04:00
|
|
|
/* options */
|
|
|
|
if (NIL_P(opts) || opts == Qfalse) {
|
|
|
|
/* without Tk */
|
|
|
|
with_tk = 0;
|
|
|
|
} else {
|
|
|
|
/* Tcl_SetVar(ptr->ip, "argv", StringValuePtr(opts), 0); */
|
|
|
|
Tcl_SetVar(ptr->ip, "argv", StringValuePtr(opts), TCL_GLOBAL_ONLY);
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
case 1:
|
2004-10-11 00:51:21 -04:00
|
|
|
/* argv0 */
|
|
|
|
if (!NIL_P(argv0)) {
|
2004-12-08 13:14:15 -05:00
|
|
|
if (strncmp(StringValuePtr(argv0), "-e", 3) == 0
|
|
|
|
|| strncmp(StringValuePtr(argv0), "-", 2) == 0) {
|
|
|
|
Tcl_SetVar(ptr->ip, "argv0", "ruby", TCL_GLOBAL_ONLY);
|
|
|
|
} else {
|
|
|
|
/* Tcl_SetVar(ptr->ip, "argv0", StringValuePtr(argv0), 0); */
|
|
|
|
Tcl_SetVar(ptr->ip, "argv0", StringValuePtr(argv0),
|
|
|
|
TCL_GLOBAL_ONLY);
|
|
|
|
}
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
case 0:
|
2004-10-11 00:51:21 -04:00
|
|
|
/* no args */
|
|
|
|
;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* from Tcl_AppInit() */
|
|
|
|
if (with_tk) {
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("Tk_Init");
|
2005-07-28 05:14:59 -04:00
|
|
|
st = ruby_tk_stubs_init(ptr->ip);
|
|
|
|
switch(st) {
|
|
|
|
case TCLTK_STUBS_OK:
|
|
|
|
break;
|
|
|
|
case NO_Tk_Init:
|
|
|
|
rb_raise(rb_eLoadError, "tcltklib: can't find Tk_Init()");
|
|
|
|
case FAIL_Tk_Init:
|
|
|
|
rb_raise(rb_eRuntimeError, "tcltklib: fail to Tk_Init(). %s",
|
|
|
|
Tcl_GetStringResult(ptr->ip));
|
|
|
|
case FAIL_Tk_InitStubs:
|
|
|
|
rb_raise(rb_eRuntimeError, "tcltklib: fail to Tk_InitStubs(). %s",
|
|
|
|
Tcl_GetStringResult(ptr->ip));
|
|
|
|
default:
|
|
|
|
rb_raise(rb_eRuntimeError, "tcltklib: unknown error(%d) on ruby_tk_stubs_init", st);
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
2005-07-28 05:14:59 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("Tcl_StaticPackage(\"Tk\")");
|
2004-05-01 12:09:54 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init, Tk_SafeInit);
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init,
|
|
|
|
(Tcl_PackageInitProc *) NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
/* get main window */
|
|
|
|
mainWin = Tk_MainWindow(ptr->ip);
|
|
|
|
Tk_Preserve((ClientData)mainWin);
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
/* add ruby command to the interpreter */
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
DUMP1("Tcl_CreateObjCommand(\"ruby\")");
|
|
|
|
Tcl_CreateObjCommand(ptr->ip, "ruby", ip_ruby_eval, (ClientData)NULL,
|
2004-10-11 00:51:21 -04:00
|
|
|
(Tcl_CmdDeleteProc *)NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("Tcl_CreateObjCommand(\"ruby_eval\")");
|
|
|
|
Tcl_CreateObjCommand(ptr->ip, "ruby_eval", ip_ruby_eval, (ClientData)NULL,
|
2004-10-11 00:51:21 -04:00
|
|
|
(Tcl_CmdDeleteProc *)NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("Tcl_CreateObjCommand(\"ruby_cmd\")");
|
|
|
|
Tcl_CreateObjCommand(ptr->ip, "ruby_cmd", ip_ruby_cmd, (ClientData)NULL,
|
2004-10-11 00:51:21 -04:00
|
|
|
(Tcl_CmdDeleteProc *)NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
DUMP1("Tcl_CreateCommand(\"ruby\")");
|
|
|
|
Tcl_CreateCommand(ptr->ip, "ruby", ip_ruby_eval, (ClientData)NULL,
|
2004-10-11 00:51:21 -04:00
|
|
|
(Tcl_CmdDeleteProc *)NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("Tcl_CreateCommand(\"ruby_eval\")");
|
|
|
|
Tcl_CreateCommand(ptr->ip, "ruby_eval", ip_ruby_eval, (ClientData)NULL,
|
2004-10-11 00:51:21 -04:00
|
|
|
(Tcl_CmdDeleteProc *)NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP1("Tcl_CreateCommand(\"ruby_cmd\")");
|
|
|
|
Tcl_CreateCommand(ptr->ip, "ruby_cmd", ip_ruby_cmd, (ClientData)NULL,
|
2004-10-11 00:51:21 -04:00
|
|
|
(Tcl_CmdDeleteProc *)NULL);
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* add 'interp_exit', 'ruby_exit' and replace 'exit' command */
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
DUMP1("Tcl_CreateObjCommand(\"interp_exit\")");
|
|
|
|
Tcl_CreateObjCommand(ptr->ip, "interp_exit", ip_InterpExitObjCmd,
|
2004-10-11 00:51:21 -04:00
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
2004-09-11 13:45:53 -04:00
|
|
|
DUMP1("Tcl_CreateObjCommand(\"ruby_exit\")");
|
|
|
|
Tcl_CreateObjCommand(ptr->ip, "ruby_exit", ip_RubyExitObjCmd,
|
2004-10-11 00:51:21 -04:00
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
2004-09-11 13:45:53 -04:00
|
|
|
DUMP1("Tcl_CreateObjCommand(\"exit\") --> \"ruby_exit\"");
|
|
|
|
Tcl_CreateObjCommand(ptr->ip, "exit", ip_RubyExitObjCmd,
|
2004-10-11 00:51:21 -04:00
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
2004-09-11 13:45:53 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
DUMP1("Tcl_CreateCommand(\"interp_exit\")");
|
|
|
|
Tcl_CreateCommand(ptr->ip, "interp_exit", ip_InterpExitCommand,
|
2004-10-11 00:51:21 -04:00
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
2004-09-11 13:45:53 -04:00
|
|
|
DUMP1("Tcl_CreateCommand(\"ruby_exit\")");
|
|
|
|
Tcl_CreateCommand(ptr->ip, "ruby_exit", ip_RubyExitCommand,
|
2004-10-11 00:51:21 -04:00
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
2004-09-11 13:45:53 -04:00
|
|
|
DUMP1("Tcl_CreateCommand(\"exit\") --> \"ruby_exit\"");
|
|
|
|
Tcl_CreateCommand(ptr->ip, "exit", ip_RubyExitCommand,
|
2004-10-11 00:51:21 -04:00
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
2004-09-11 13:45:53 -04:00
|
|
|
#endif
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* replace vwait and tkwait */
|
|
|
|
ip_replace_wait_commands(ptr->ip, mainWin);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* wrap namespace command */
|
|
|
|
ip_wrap_namespace_command(ptr->ip);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* set finalizer */
|
|
|
|
Tcl_CallWhenDeleted(ptr->ip, ip_CallWhenDeleted, (ClientData)mainWin);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
if (mainWin != (Tk_Window)NULL) {
|
|
|
|
Tk_Release((ClientData)mainWin);
|
|
|
|
}
|
2004-09-09 01:03:21 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2005-03-02 02:06:52 -05:00
|
|
|
ip_create_slave_core(interp, argc, argv)
|
|
|
|
VALUE interp;
|
2004-05-01 12:09:54 -04:00
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
{
|
2005-03-02 02:06:52 -05:00
|
|
|
struct tcltkip *master = get_ip(interp);
|
2004-05-01 12:09:54 -04:00
|
|
|
struct tcltkip *slave = ALLOC(struct tcltkip);
|
|
|
|
VALUE safemode;
|
|
|
|
VALUE name;
|
|
|
|
int safe;
|
|
|
|
int thr_crit_bup;
|
2004-09-11 13:45:53 -04:00
|
|
|
Tk_Window mainWin;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(master)) {
|
2005-03-02 02:06:52 -05:00
|
|
|
return rb_exc_new2(rb_eRuntimeError,
|
|
|
|
"deleted master cannot create a new slave");
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
name = argv[0];
|
2005-03-02 02:06:52 -05:00
|
|
|
safemode = argv[1];
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (Tcl_IsSafe(master->ip) == 1) {
|
2004-10-11 00:51:21 -04:00
|
|
|
safe = 1;
|
2004-05-01 12:09:54 -04:00
|
|
|
} else if (safemode == Qfalse || NIL_P(safemode)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
safe = 0;
|
2005-03-02 02:06:52 -05:00
|
|
|
/* rb_secure(4); */ /* already checked */
|
2004-05-01 12:09:54 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
safe = 1;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
#if 0
|
|
|
|
/* init Tk */
|
|
|
|
if (RTEST(with_tk)) {
|
|
|
|
volatile VALUE exc;
|
|
|
|
if (!tk_stubs_init_p()) {
|
|
|
|
exc = tcltkip_init_tk(interp);
|
|
|
|
if (!NIL_P(exc)) {
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
return exc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* create slave-ip */
|
2004-09-12 12:05:59 -04:00
|
|
|
slave->ref_count = 0;
|
|
|
|
slave->allow_ruby_exit = 0;
|
|
|
|
slave->return_value = 0;
|
|
|
|
|
2006-04-05 12:08:45 -04:00
|
|
|
slave->ip = Tcl_CreateSlave(master->ip, StringValuePtr(name), safe);
|
2004-05-01 12:09:54 -04:00
|
|
|
if (slave->ip == NULL) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2005-03-02 02:06:52 -05:00
|
|
|
return rb_exc_new2(rb_eRuntimeError,
|
|
|
|
"fail to create the new slave interpreter");
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
2005-01-30 23:14:50 -05:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2005-03-02 02:06:52 -05:00
|
|
|
#if TCL_NAMESPACE_DEBUG
|
2005-01-30 23:14:50 -05:00
|
|
|
slave->default_ns = Tcl_GetCurrentNamespace(slave->ip);
|
2005-03-02 02:06:52 -05:00
|
|
|
#endif
|
2005-01-30 23:14:50 -05:00
|
|
|
#endif
|
2004-09-12 12:05:59 -04:00
|
|
|
rbtk_preserve_ip(slave);
|
|
|
|
|
|
|
|
slave->has_orig_exit
|
2004-10-11 00:51:21 -04:00
|
|
|
= Tcl_GetCommandInfo(slave->ip, "exit", &(slave->orig_exit_info));
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* replace 'exit' command --> 'interp_exit' command */
|
2005-07-28 05:14:59 -04:00
|
|
|
mainWin = (tk_stubs_init_p())? Tk_MainWindow(slave->ip): (Tk_Window)NULL;
|
2004-09-11 13:45:53 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
DUMP1("Tcl_CreateObjCommand(\"exit\") --> \"interp_exit\"");
|
|
|
|
Tcl_CreateObjCommand(slave->ip, "exit", ip_InterpExitObjCmd,
|
2004-10-11 00:51:21 -04:00
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
2004-09-11 13:45:53 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
DUMP1("Tcl_CreateCommand(\"exit\") --> \"interp_exit\"");
|
|
|
|
Tcl_CreateCommand(slave->ip, "exit", ip_InterpExitCommand,
|
2004-10-11 00:51:21 -04:00
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
2004-09-11 13:45:53 -04:00
|
|
|
#endif
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* replace vwait and tkwait */
|
|
|
|
ip_replace_wait_commands(slave->ip, mainWin);
|
|
|
|
|
|
|
|
/* wrap namespace command */
|
|
|
|
ip_wrap_namespace_command(slave->ip);
|
|
|
|
|
|
|
|
/* set finalizer */
|
|
|
|
Tcl_CallWhenDeleted(slave->ip, ip_CallWhenDeleted, (ClientData)mainWin);
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
return Data_Wrap_Struct(CLASS_OF(interp), 0, ip_free, slave);
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2005-03-02 02:06:52 -05:00
|
|
|
ip_create_slave(argc, argv, self)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
2004-05-01 12:09:54 -04:00
|
|
|
VALUE self;
|
|
|
|
{
|
2005-03-02 02:06:52 -05:00
|
|
|
struct tcltkip *master = get_ip(self);
|
|
|
|
VALUE safemode;
|
|
|
|
VALUE name;
|
2005-08-04 23:51:50 -04:00
|
|
|
VALUE callargv[2];
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(master)) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_raise(rb_eRuntimeError,
|
|
|
|
"deleted master cannot create a new slave interpreter");
|
|
|
|
}
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
/* argument check */
|
2005-03-02 02:06:52 -05:00
|
|
|
if (rb_scan_args(argc, argv, "11", &name, &safemode) == 1) {
|
|
|
|
safemode = Qfalse;
|
|
|
|
}
|
|
|
|
if (Tcl_IsSafe(master->ip) != 1
|
|
|
|
&& (safemode == Qfalse || NIL_P(safemode))) {
|
|
|
|
rb_secure(4);
|
|
|
|
}
|
|
|
|
|
|
|
|
StringValue(name);
|
|
|
|
callargv[0] = name;
|
|
|
|
callargv[1] = safemode;
|
|
|
|
|
2005-08-04 23:51:50 -04:00
|
|
|
return tk_funcall(ip_create_slave_core, 2, callargv, self);
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
|
2005-11-18 03:39:29 -05:00
|
|
|
|
|
|
|
/* self is slave of master? */
|
|
|
|
static VALUE
|
|
|
|
ip_is_slave_of_p(self, master)
|
|
|
|
VALUE self, master;
|
|
|
|
{
|
|
|
|
if (!rb_obj_is_kind_of(master, tcltkip_class)) {
|
|
|
|
rb_raise(rb_eArgError, "expected TclTkIp object");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Tcl_GetMaster(get_ip(self)->ip) == get_ip(master)->ip) {
|
|
|
|
return Qtrue;
|
|
|
|
} else {
|
|
|
|
return Qfalse;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* create console (if supported) */
|
2005-03-30 03:44:19 -05:00
|
|
|
#if defined(MAC_TCL) || defined(__WIN32__)
|
|
|
|
#if TCL_MAJOR_VERSION < 8 \
|
|
|
|
|| (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0) \
|
|
|
|
|| (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 1 \
|
|
|
|
&& (TCL_RELEASE_LEVEL == TCL_ALPHA_RELEASE \
|
|
|
|
|| (TCL_RELEASE_LEVEL == TCL_BETA_RELEASE \
|
|
|
|
&& TCL_RELEASE_SERIAL < 2) ) )
|
|
|
|
EXTERN void TkConsoleCreate _((void));
|
|
|
|
#endif
|
|
|
|
#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 1 \
|
|
|
|
&& ( (TCL_RELEASE_LEVEL == TCL_FINAL_RELEASE \
|
|
|
|
&& TCL_RELEASE_SERIAL == 0) \
|
|
|
|
|| (TCL_RELEASE_LEVEL == TCL_BETA_RELEASE \
|
|
|
|
&& TCL_RELEASE_SERIAL >= 2) )
|
|
|
|
EXTERN void TkConsoleCreate_ _((void));
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
static VALUE
|
|
|
|
ip_create_console_core(interp, argc, argv)
|
|
|
|
VALUE interp;
|
|
|
|
int argc; /* dummy */
|
|
|
|
VALUE *argv; /* dummy */
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(interp);
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
if (!tk_stubs_init_p()) {
|
|
|
|
tcltkip_init_tk(interp);
|
|
|
|
}
|
|
|
|
|
2005-03-30 03:44:19 -05:00
|
|
|
if (Tcl_GetVar(ptr->ip,"tcl_interactive",TCL_GLOBAL_ONLY) == (char*)NULL) {
|
|
|
|
Tcl_SetVar(ptr->ip, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION > 8 \
|
|
|
|
|| (TCL_MAJOR_VERSION == 8 \
|
|
|
|
&& (TCL_MINOR_VERSION > 1 \
|
|
|
|
|| (TCL_MINOR_VERSION == 1 \
|
|
|
|
&& TCL_RELEASE_LEVEL == TCL_FINAL_RELEASE \
|
|
|
|
&& TCL_RELEASE_SERIAL >= 1) ) )
|
|
|
|
Tk_InitConsoleChannels(ptr->ip);
|
|
|
|
|
|
|
|
if (Tk_CreateConsoleWindow(ptr->ip) != TCL_OK) {
|
|
|
|
rb_raise(rb_eRuntimeError, "fail to create console-window");
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#if defined(MAC_TCL) || defined(__WIN32__)
|
|
|
|
#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 1 \
|
|
|
|
&& ( (TCL_RELEASE_LEVEL == TCL_FINAL_RELEASE && TCL_RELEASE_SERIAL == 0) \
|
|
|
|
|| (TCL_RELEASE_LEVEL == TCL_BETA_RELEASE && TCL_RELEASE_SERIAL >= 2) )
|
|
|
|
TkConsoleCreate_();
|
|
|
|
#else
|
|
|
|
TkConsoleCreate();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (TkConsoleInit(ptr->ip) != TCL_OK) {
|
|
|
|
rb_raise(rb_eRuntimeError, "fail to create console-window");
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
rb_notimplement();
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return interp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ip_create_console(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
|
|
|
|
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2005-03-30 03:44:19 -05:00
|
|
|
rb_raise(rb_eRuntimeError, "interpreter is deleted");
|
|
|
|
}
|
|
|
|
|
|
|
|
return tk_funcall(ip_create_console_core, 0, (VALUE*)NULL, self);
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* make ip "safe" */
|
|
|
|
static VALUE
|
|
|
|
ip_make_safe_core(interp, argc, argv)
|
|
|
|
VALUE interp;
|
|
|
|
int argc; /* dummy */
|
|
|
|
VALUE *argv; /* dummy */
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(interp);
|
2004-09-11 13:45:53 -04:00
|
|
|
Tk_Window mainWin;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2005-03-02 02:06:52 -05:00
|
|
|
return rb_exc_new2(rb_eRuntimeError, "interpreter is deleted");
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (Tcl_MakeSafe(ptr->ip) == TCL_ERROR) {
|
2006-04-18 04:43:10 -04:00
|
|
|
/* return rb_exc_new2(rb_eRuntimeError,
|
|
|
|
Tcl_GetStringResult(ptr->ip)); */
|
|
|
|
return create_ip_exc(interp, rb_eRuntimeError,
|
|
|
|
Tcl_GetStringResult(ptr->ip));
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
ptr->allow_ruby_exit = 0;
|
|
|
|
|
|
|
|
/* replace 'exit' command --> 'interp_exit' command */
|
2005-07-28 05:14:59 -04:00
|
|
|
mainWin = (tk_stubs_init_p())? Tk_MainWindow(ptr->ip): (Tk_Window)NULL;
|
2004-09-11 13:45:53 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
DUMP1("Tcl_CreateObjCommand(\"exit\") --> \"interp_exit\"");
|
|
|
|
Tcl_CreateObjCommand(ptr->ip, "exit", ip_InterpExitObjCmd,
|
2004-10-11 00:51:21 -04:00
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
2004-09-11 13:45:53 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
DUMP1("Tcl_CreateCommand(\"exit\") --> \"interp_exit\"");
|
|
|
|
Tcl_CreateCommand(ptr->ip, "exit", ip_InterpExitCommand,
|
2004-10-11 00:51:21 -04:00
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
2004-09-11 13:45:53 -04:00
|
|
|
#endif
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
return interp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ip_make_safe(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
|
|
|
|
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_raise(rb_eRuntimeError, "interpreter is deleted");
|
|
|
|
}
|
|
|
|
|
|
|
|
return tk_funcall(ip_make_safe_core, 0, (VALUE*)NULL, self);
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* is safe? */
|
|
|
|
static VALUE
|
|
|
|
ip_is_safe_p(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_raise(rb_eRuntimeError, "interpreter is deleted");
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (Tcl_IsSafe(ptr->ip)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qtrue;
|
2004-05-01 12:09:54 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qfalse;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* allow_ruby_exit? */
|
2004-05-01 12:09:54 -04:00
|
|
|
static VALUE
|
2004-09-11 13:45:53 -04:00
|
|
|
ip_allow_ruby_exit_p(self)
|
2004-05-01 12:09:54 -04:00
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_raise(rb_eRuntimeError, "interpreter is deleted");
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
if (ptr->allow_ruby_exit) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qtrue;
|
2004-09-11 13:45:53 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qfalse;
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* allow_ruby_exit = mode */
|
2004-05-01 12:09:54 -04:00
|
|
|
static VALUE
|
2004-09-11 13:45:53 -04:00
|
|
|
ip_allow_ruby_exit_set(self, val)
|
|
|
|
VALUE self, val;
|
2004-05-01 12:09:54 -04:00
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
2004-09-11 13:45:53 -04:00
|
|
|
Tk_Window mainWin;
|
|
|
|
|
|
|
|
rb_secure(4);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_raise(rb_eRuntimeError, "interpreter is deleted");
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Tcl_IsSafe(ptr->ip)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_raise(rb_eSecurityError,
|
|
|
|
"insecure operation on a safe interpreter");
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
mainWin = (tk_stubs_init_p())? Tk_MainWindow(ptr->ip): (Tk_Window)NULL;
|
2004-09-11 13:45:53 -04:00
|
|
|
|
|
|
|
if (RTEST(val)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
ptr->allow_ruby_exit = 1;
|
2004-09-11 13:45:53 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("Tcl_CreateObjCommand(\"exit\") --> \"ruby_exit\"");
|
|
|
|
Tcl_CreateObjCommand(ptr->ip, "exit", ip_RubyExitObjCmd,
|
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
2004-09-11 13:45:53 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("Tcl_CreateCommand(\"exit\") --> \"ruby_exit\"");
|
|
|
|
Tcl_CreateCommand(ptr->ip, "exit", ip_RubyExitCommand,
|
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
2004-09-11 13:45:53 -04:00
|
|
|
#endif
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qtrue;
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
ptr->allow_ruby_exit = 0;
|
2004-09-11 13:45:53 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("Tcl_CreateObjCommand(\"exit\") --> \"interp_exit\"");
|
|
|
|
Tcl_CreateObjCommand(ptr->ip, "exit", ip_InterpExitObjCmd,
|
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
2004-09-11 13:45:53 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("Tcl_CreateCommand(\"exit\") --> \"interp_exit\"");
|
|
|
|
Tcl_CreateCommand(ptr->ip, "exit", ip_InterpExitCommand,
|
|
|
|
(ClientData)mainWin, (Tcl_CmdDeleteProc *)NULL);
|
2004-09-11 13:45:53 -04:00
|
|
|
#endif
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qfalse;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* delete interpreter */
|
2004-05-01 12:09:54 -04:00
|
|
|
static VALUE
|
2004-09-11 13:45:53 -04:00
|
|
|
ip_delete(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
2005-03-02 02:06:52 -05:00
|
|
|
int thr_crit_bup;
|
2004-09-11 13:45:53 -04:00
|
|
|
struct tcltkip *ptr = get_ip(self);
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (ptr == (struct tcltkip *)NULL || ptr->ip == (Tcl_Interp*)NULL) {
|
|
|
|
DUMP1("delete deleted IP");
|
|
|
|
return Qnil;
|
2005-01-30 23:14:50 -05:00
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2005-01-25 00:09:22 -05:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
DUMP1("call ip_finalize");
|
|
|
|
ip_finalize(ptr->ip);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
|
|
|
DUMP1("delete interp");
|
2005-03-02 02:06:52 -05:00
|
|
|
Tcl_DeleteInterp(ptr->ip);
|
|
|
|
Tcl_Release(ptr->ip);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-09-11 13:45:53 -04:00
|
|
|
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* is deleted? */
|
2005-01-25 00:09:22 -05:00
|
|
|
static VALUE
|
2005-01-30 23:14:50 -05:00
|
|
|
ip_has_invalid_namespace_p(self)
|
2005-01-25 00:09:22 -05:00
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (ptr == (struct tcltkip *)NULL || ptr->ip == (Tcl_Interp *)NULL) {
|
|
|
|
/* deleted IP */
|
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if TCL_NAMESPACE_DEBUG
|
2005-01-30 23:14:50 -05:00
|
|
|
if (rbtk_invalid_namespace(ptr)) {
|
2005-01-25 00:09:22 -05:00
|
|
|
return Qtrue;
|
|
|
|
} else {
|
|
|
|
return Qfalse;
|
|
|
|
}
|
2005-03-02 02:06:52 -05:00
|
|
|
#else
|
|
|
|
return Qfalse;
|
|
|
|
#endif
|
2005-01-25 00:09:22 -05:00
|
|
|
}
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
static VALUE
|
|
|
|
ip_is_deleted_p(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
|
|
|
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qtrue;
|
2004-09-11 13:45:53 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qfalse;
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-07-21 18:05:04 -04:00
|
|
|
static VALUE
|
|
|
|
ip_has_mainwindow_p(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
|
|
|
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr) || !tk_stubs_init_p()) {
|
2005-07-21 18:05:04 -04:00
|
|
|
return Qnil;
|
|
|
|
} else if (Tk_MainWindow(ptr->ip) == (Tk_Window)NULL) {
|
|
|
|
return Qfalse;
|
|
|
|
} else {
|
|
|
|
return Qtrue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-04 11:26:05 -04:00
|
|
|
/*** ruby string <=> tcl object ***/
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-05-01 12:09:54 -04:00
|
|
|
static VALUE
|
2005-08-04 11:26:05 -04:00
|
|
|
get_str_from_obj(obj)
|
|
|
|
Tcl_Obj *obj;
|
2004-05-01 12:09:54 -04:00
|
|
|
{
|
2005-08-04 11:26:05 -04:00
|
|
|
int len, binary = 0;
|
|
|
|
const char *s;
|
|
|
|
volatile VALUE str;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-08-04 11:26:05 -04:00
|
|
|
#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
|
|
|
|
s = Tcl_GetStringFromObj(obj, &len);
|
|
|
|
#else /* TCL_VERSION >= 8.1 */
|
|
|
|
if (Tcl_GetCharLength(obj) != Tcl_UniCharLen(Tcl_GetUnicode(obj))) {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* possibly binary string */
|
2005-08-04 11:26:05 -04:00
|
|
|
s = Tcl_GetByteArrayFromObj(obj, &len);
|
|
|
|
binary = 1;
|
2004-05-01 12:09:54 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* possibly text string */
|
2005-08-04 11:26:05 -04:00
|
|
|
s = Tcl_GetStringFromObj(obj, &len);
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
2005-08-04 11:26:05 -04:00
|
|
|
#endif
|
|
|
|
str = s ? rb_str_new(s, len) : rb_str_new2("");
|
|
|
|
if (binary) rb_ivar_set(str, ID_at_enc, rb_str_new2("binary"));
|
|
|
|
return str;
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-08-04 11:26:05 -04:00
|
|
|
static Tcl_Obj *
|
|
|
|
get_obj_from_str(str)
|
|
|
|
VALUE str;
|
|
|
|
{
|
|
|
|
const char *s = StringValuePtr(str);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-08-04 11:26:05 -04:00
|
|
|
#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
|
2006-08-31 07:56:42 -04:00
|
|
|
return Tcl_NewStringObj((char*)s, RSTRING_LEN(str));
|
2005-08-04 11:26:05 -04:00
|
|
|
#else /* TCL_VERSION >= 8.1 */
|
|
|
|
VALUE enc = rb_attr_get(str, ID_at_enc);
|
2005-08-09 02:16:29 -04:00
|
|
|
|
|
|
|
if (!NIL_P(enc)) {
|
|
|
|
StringValue(enc);
|
2006-08-31 07:56:42 -04:00
|
|
|
if (strcmp(RSTRING_PTR(enc), "binary") == 0) {
|
2005-08-09 02:16:29 -04:00
|
|
|
/* binary string */
|
2006-08-31 07:56:42 -04:00
|
|
|
return Tcl_NewByteArrayObj(s, RSTRING_LEN(str));
|
2005-08-09 02:16:29 -04:00
|
|
|
} else {
|
|
|
|
/* text string */
|
2006-08-31 07:56:42 -04:00
|
|
|
return Tcl_NewStringObj(s, RSTRING_LEN(str));
|
2005-08-09 02:16:29 -04:00
|
|
|
}
|
2006-08-31 07:56:42 -04:00
|
|
|
} else if (strlen(s) != RSTRING_LEN(str)) {
|
2005-08-04 11:26:05 -04:00
|
|
|
/* probably binary string */
|
2006-08-31 07:56:42 -04:00
|
|
|
return Tcl_NewByteArrayObj(s, RSTRING_LEN(str));
|
2005-08-04 11:26:05 -04:00
|
|
|
} else {
|
|
|
|
/* probably text string */
|
2006-08-31 07:56:42 -04:00
|
|
|
return Tcl_NewStringObj(s, RSTRING_LEN(str));
|
2005-08-04 11:26:05 -04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* ruby string <=> tcl object */
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-08-04 11:26:05 -04:00
|
|
|
static VALUE
|
|
|
|
ip_get_result_string_obj(interp)
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
{
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
Tcl_Obj *retObj;
|
|
|
|
volatile VALUE strval;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-08-04 11:26:05 -04:00
|
|
|
retObj = Tcl_GetObjResult(interp);
|
|
|
|
Tcl_IncrRefCount(retObj);
|
|
|
|
strval = get_str_from_obj(retObj);
|
|
|
|
OBJ_TAINT(strval);
|
|
|
|
Tcl_DecrRefCount(retObj);
|
|
|
|
return strval;
|
|
|
|
#else
|
|
|
|
return rb_tainted_str_new2(interp->result);
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* call Tcl/Tk functions on the eventloop thread */
|
|
|
|
static VALUE
|
|
|
|
callq_safelevel_handler(arg, callq)
|
|
|
|
VALUE arg;
|
|
|
|
VALUE callq;
|
|
|
|
{
|
|
|
|
struct call_queue *q;
|
|
|
|
|
|
|
|
Data_Get_Struct(callq, struct call_queue, q);
|
|
|
|
DUMP2("(safe-level handler) $SAFE = %d", q->safe_level);
|
|
|
|
rb_set_safe_level(q->safe_level);
|
|
|
|
return((q->func)(q->interp, q->argc, q->argv));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int call_queue_handler _((Tcl_Event *, int));
|
|
|
|
static int
|
|
|
|
call_queue_handler(evPtr, flags)
|
|
|
|
Tcl_Event *evPtr;
|
|
|
|
int flags;
|
|
|
|
{
|
|
|
|
struct call_queue *q = (struct call_queue *)evPtr;
|
|
|
|
volatile VALUE ret;
|
|
|
|
volatile VALUE q_dat;
|
|
|
|
struct tcltkip *ptr;
|
|
|
|
|
|
|
|
DUMP2("do_call_queue_handler : evPtr = %p", evPtr);
|
|
|
|
DUMP2("queue_handler thread : %lx", rb_thread_current());
|
|
|
|
DUMP2("added by thread : %lx", q->thread);
|
|
|
|
|
|
|
|
if (*(q->done)) {
|
|
|
|
DUMP1("processed by another event-loop");
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
DUMP1("process it on current event-loop");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* process it */
|
|
|
|
*(q->done) = 1;
|
|
|
|
|
|
|
|
/* deleted ipterp ? */
|
|
|
|
ptr = get_ip(q->interp);
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2005-03-02 02:06:52 -05:00
|
|
|
/* deleted IP --> ignore */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check safe-level */
|
|
|
|
if (rb_safe_level() != q->safe_level) {
|
|
|
|
/* q_dat = Data_Wrap_Struct(rb_cData,0,0,q); */
|
|
|
|
q_dat = Data_Wrap_Struct(rb_cData,call_queue_mark,0,q);
|
|
|
|
ret = rb_funcall(rb_proc_new(callq_safelevel_handler, q_dat),
|
|
|
|
ID_call, 0);
|
|
|
|
rb_gc_force_recycle(q_dat);
|
|
|
|
} else {
|
|
|
|
DUMP2("call function (for caller thread:%lx)", q->thread);
|
|
|
|
DUMP2("call function (current thread:%lx)", rb_thread_current());
|
|
|
|
ret = (q->func)(q->interp, q->argc, q->argv);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set result */
|
2006-09-02 10:42:08 -04:00
|
|
|
RARRAY_PTR(q->result)[0] = ret;
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
/* complete */
|
|
|
|
*(q->done) = -1;
|
|
|
|
|
|
|
|
/* back to caller */
|
2006-12-01 02:43:05 -05:00
|
|
|
if (RTEST(rb_funcall(q->thread, ID_alive_p, 0, 0))) {
|
|
|
|
DUMP2("back to caller (caller thread:%lx)", q->thread);
|
|
|
|
DUMP2(" (current thread:%lx)", rb_thread_current());
|
|
|
|
rb_thread_run(q->thread);
|
|
|
|
DUMP1("finish back to caller");
|
|
|
|
} else {
|
|
|
|
DUMP2("caller is dead (caller thread:%lx)", q->thread);
|
|
|
|
DUMP2(" (current thread:%lx)", rb_thread_current());
|
|
|
|
}
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
/* end of handler : remove it */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
tk_funcall(func, argc, argv, obj)
|
|
|
|
VALUE (*func)();
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE obj;
|
|
|
|
{
|
|
|
|
struct call_queue *callq;
|
|
|
|
int *alloc_done;
|
|
|
|
int thr_crit_bup;
|
|
|
|
volatile VALUE current = rb_thread_current();
|
|
|
|
volatile VALUE ip_obj = obj;
|
|
|
|
volatile VALUE result;
|
|
|
|
volatile VALUE ret;
|
|
|
|
|
|
|
|
|
2005-08-01 00:57:28 -04:00
|
|
|
if (!NIL_P(ip_obj) && deleted_ip(get_ip(ip_obj))) {
|
2005-03-02 02:06:52 -05:00
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NIL_P(eventloop_thread) || current == eventloop_thread) {
|
2005-07-12 23:47:05 -04:00
|
|
|
if (NIL_P(eventloop_thread)) {
|
2005-03-02 02:06:52 -05:00
|
|
|
DUMP2("tk_funcall from thread:%lx but no eventloop", current);
|
2005-07-12 23:47:05 -04:00
|
|
|
} else {
|
|
|
|
DUMP2("tk_funcall from current eventloop %lx", current);
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
result = (func)(ip_obj, argc, argv);
|
|
|
|
if (rb_obj_is_kind_of(result, rb_eException)) {
|
|
|
|
rb_exc_raise(result);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
DUMP2("tk_funcall from thread %lx (NOT current eventloop)", current);
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
2005-08-04 23:51:50 -04:00
|
|
|
/* allocate memory (argv cross over thread : must be in heap) */
|
|
|
|
if (argv) {
|
|
|
|
VALUE *temp = ALLOC_N(VALUE, argc);
|
|
|
|
MEMCPY(temp, argv, VALUE, argc);
|
|
|
|
argv = temp;
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* allocate memory (keep result) */
|
|
|
|
alloc_done = (int*)ALLOC(int);
|
|
|
|
*alloc_done = 0;
|
|
|
|
|
|
|
|
/* allocate memory (freed by Tcl_ServiceEvent) */
|
|
|
|
callq = (struct call_queue *)Tcl_Alloc(sizeof(struct call_queue));
|
|
|
|
Tcl_Preserve(callq);
|
|
|
|
|
|
|
|
/* allocate result obj */
|
2006-09-05 09:07:06 -04:00
|
|
|
result = rb_ary_new3(1, Qnil);
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
/* construct event data */
|
|
|
|
callq->done = alloc_done;
|
|
|
|
callq->func = func;
|
|
|
|
callq->argc = argc;
|
|
|
|
callq->argv = argv;
|
|
|
|
callq->interp = ip_obj;
|
|
|
|
callq->result = result;
|
|
|
|
callq->thread = current;
|
|
|
|
callq->safe_level = rb_safe_level();
|
|
|
|
callq->ev.proc = call_queue_handler;
|
|
|
|
|
|
|
|
/* add the handler to Tcl event queue */
|
|
|
|
DUMP1("add handler");
|
|
|
|
Tcl_QueueEvent(&(callq->ev), TCL_QUEUE_HEAD);
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
|
|
|
/* wait for the handler to be processed */
|
|
|
|
DUMP2("wait for handler (current thread:%lx)", current);
|
|
|
|
while(*alloc_done >= 0) {
|
|
|
|
rb_thread_stop();
|
|
|
|
}
|
|
|
|
DUMP2("back from handler (current thread:%lx)", current);
|
|
|
|
|
|
|
|
/* get result & free allocated memory */
|
2006-09-02 10:42:08 -04:00
|
|
|
ret = RARRAY_PTR(result)[0];
|
2005-03-02 02:06:52 -05:00
|
|
|
free(alloc_done);
|
2005-08-04 23:51:50 -04:00
|
|
|
if (argv) free(argv);
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
Tcl_Release(callq);
|
|
|
|
|
|
|
|
/* exception? */
|
|
|
|
if (rb_obj_is_kind_of(ret, rb_eException)) {
|
|
|
|
DUMP1("raise exception");
|
|
|
|
rb_exc_raise(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
DUMP1("exit tk_funcall");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* eval string in tcl by Tcl_Eval() */
|
2005-08-04 05:41:57 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2005-03-02 02:06:52 -05:00
|
|
|
struct call_eval_info {
|
|
|
|
struct tcltkip *ptr;
|
|
|
|
Tcl_Obj *cmd;
|
|
|
|
};
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
call_tcl_eval(arg)
|
|
|
|
VALUE arg;
|
|
|
|
{
|
|
|
|
struct call_eval_info *inf = (struct call_eval_info *)arg;
|
|
|
|
|
2006-07-03 06:08:11 -04:00
|
|
|
Tcl_AllowExceptions(inf->ptr->ip);
|
2005-03-02 02:06:52 -05:00
|
|
|
inf->ptr->return_value = Tcl_EvalObj(inf->ptr->ip, inf->cmd);
|
|
|
|
|
|
|
|
return Qnil;
|
|
|
|
}
|
2005-08-04 05:41:57 -04:00
|
|
|
#endif
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
static VALUE
|
|
|
|
ip_eval_real(self, cmd_str, cmd_len)
|
|
|
|
VALUE self;
|
|
|
|
char *cmd_str;
|
|
|
|
int cmd_len;
|
|
|
|
{
|
2004-09-11 13:45:53 -04:00
|
|
|
volatile VALUE ret;
|
2004-05-01 12:09:54 -04:00
|
|
|
struct tcltkip *ptr = get_ip(self);
|
|
|
|
int thr_crit_bup;
|
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
/* call Tcl_EvalObj() */
|
|
|
|
{
|
|
|
|
Tcl_Obj *cmd;
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
cmd = Tcl_NewStringObj(cmd_str, cmd_len);
|
|
|
|
Tcl_IncrRefCount(cmd);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(cmd);
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
ptr->return_value = TCL_OK;
|
|
|
|
return rb_tainted_str_new2("");
|
2004-09-11 13:45:53 -04:00
|
|
|
} else {
|
2005-03-02 02:06:52 -05:00
|
|
|
int status;
|
|
|
|
struct call_eval_info inf;
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
/* Tcl_Preserve(ptr->ip); */
|
|
|
|
rbtk_preserve_ip(ptr);
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
#if 0
|
2004-10-11 00:51:21 -04:00
|
|
|
ptr->return_value = Tcl_EvalObj(ptr->ip, cmd);
|
|
|
|
/* ptr->return_value = Tcl_GlobalEvalObj(ptr->ip, cmd); */
|
2005-03-02 02:06:52 -05:00
|
|
|
#else
|
|
|
|
inf.ptr = ptr;
|
|
|
|
inf.cmd = cmd;
|
|
|
|
ret = rb_protect(call_tcl_eval, (VALUE)&inf, &status);
|
|
|
|
switch(status) {
|
|
|
|
case TAG_RAISE:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eException,
|
|
|
|
"unknown exception");
|
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
rbtk_pending_exception = rb_errinfo();
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TAG_FATAL:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eFatal, "FATAL");
|
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
rbtk_pending_exception = rb_errinfo();
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
Tcl_DecrRefCount(cmd);
|
|
|
|
|
|
|
|
}
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (pending_exception_check1(thr_crit_bup, ptr)) {
|
2005-07-28 05:14:59 -04:00
|
|
|
rbtk_release_ip(ptr);
|
2005-03-02 02:06:52 -05:00
|
|
|
return rbtk_pending_exception;
|
|
|
|
}
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
if (ptr->return_value == TCL_ERROR) {
|
2005-07-28 05:14:59 -04:00
|
|
|
if (event_loop_abort_on_exc > 0 && !Tcl_InterpDeleted(ptr->ip)) {
|
|
|
|
volatile VALUE exc;
|
|
|
|
exc = create_ip_exc(self, rb_eRuntimeError,
|
|
|
|
"%s", Tcl_GetStringResult(ptr->ip));
|
|
|
|
rbtk_release_ip(ptr);
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
return exc;
|
|
|
|
} else {
|
|
|
|
if (event_loop_abort_on_exc < 0) {
|
|
|
|
rb_warning("%s (ignore)", Tcl_GetStringResult(ptr->ip));
|
|
|
|
} else {
|
|
|
|
rb_warn("%s (ignore)", Tcl_GetStringResult(ptr->ip));
|
|
|
|
}
|
|
|
|
Tcl_ResetResult(ptr->ip);
|
|
|
|
rbtk_release_ip(ptr);
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
return rb_tainted_str_new2("");
|
|
|
|
}
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* pass back the result (as string) */
|
|
|
|
ret = ip_get_result_string_obj(ptr->ip);
|
2004-09-12 12:05:59 -04:00
|
|
|
rbtk_release_ip(ptr);
|
2004-09-11 13:45:53 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
return ret;
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
DUMP2("Tcl_Eval(%s)", cmd_str);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
ptr->return_value = TCL_OK;
|
|
|
|
return rb_tainted_str_new2("");
|
2004-09-11 13:45:53 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* Tcl_Preserve(ptr->ip); */
|
|
|
|
rbtk_preserve_ip(ptr);
|
|
|
|
ptr->return_value = Tcl_Eval(ptr->ip, cmd_str);
|
|
|
|
/* ptr->return_value = Tcl_GlobalEval(ptr->ip, cmd_str); */
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (pending_exception_check1(thr_crit_bup, ptr)) {
|
2005-07-28 05:14:59 -04:00
|
|
|
rbtk_release_ip(ptr);
|
2005-03-02 02:06:52 -05:00
|
|
|
return rbtk_pending_exception;
|
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (ptr->return_value == TCL_ERROR) {
|
2004-10-11 00:51:21 -04:00
|
|
|
volatile VALUE exc;
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
exc = create_ip_exc(self, rb_eRuntimeError, "%s", ptr->ip->result);
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rbtk_release_ip(ptr);
|
2005-07-28 05:14:59 -04:00
|
|
|
return exc;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
DUMP2("(TCL_Eval result) %d", ptr->return_value);
|
|
|
|
|
|
|
|
/* pass back the result (as string) */
|
2004-09-11 13:45:53 -04:00
|
|
|
ret = ip_get_result_string_obj(ptr->ip);
|
2004-09-12 12:05:59 -04:00
|
|
|
rbtk_release_ip(ptr);
|
2004-09-11 13:45:53 -04:00
|
|
|
return ret;
|
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
evq_safelevel_handler(arg, evq)
|
|
|
|
VALUE arg;
|
|
|
|
VALUE evq;
|
|
|
|
{
|
|
|
|
struct eval_queue *q;
|
|
|
|
|
|
|
|
Data_Get_Struct(evq, struct eval_queue, q);
|
|
|
|
DUMP2("(safe-level handler) $SAFE = %d", q->safe_level);
|
|
|
|
rb_set_safe_level(q->safe_level);
|
|
|
|
return ip_eval_real(q->interp, q->str, q->len);
|
|
|
|
}
|
|
|
|
|
|
|
|
int eval_queue_handler _((Tcl_Event *, int));
|
|
|
|
int
|
|
|
|
eval_queue_handler(evPtr, flags)
|
|
|
|
Tcl_Event *evPtr;
|
|
|
|
int flags;
|
|
|
|
{
|
|
|
|
struct eval_queue *q = (struct eval_queue *)evPtr;
|
|
|
|
volatile VALUE ret;
|
2004-09-11 13:45:53 -04:00
|
|
|
volatile VALUE q_dat;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
if (*(q->done)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("processed by another event-loop");
|
|
|
|
return 0;
|
2004-05-01 12:09:54 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("process it on current event-loop");
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* process it */
|
|
|
|
*(q->done) = 1;
|
|
|
|
|
|
|
|
/* check safe-level */
|
|
|
|
if (rb_safe_level() != q->safe_level) {
|
|
|
|
#ifdef HAVE_NATIVETHREAD
|
2004-10-11 00:51:21 -04:00
|
|
|
if (!is_ruby_native_thread()) {
|
|
|
|
rb_bug("cross-thread violation on eval_queue_handler()");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
/* q_dat = Data_Wrap_Struct(rb_cData,0,0,q); */
|
|
|
|
q_dat = Data_Wrap_Struct(rb_cData,eval_queue_mark,0,q);
|
|
|
|
ret = rb_funcall(rb_proc_new(evq_safelevel_handler, q_dat),
|
|
|
|
ID_call, 0);
|
|
|
|
rb_gc_force_recycle(q_dat);
|
2004-05-01 12:09:54 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
ret = ip_eval_real(q->interp, q->str, q->len);
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* set result */
|
2006-09-02 10:42:08 -04:00
|
|
|
RARRAY_PTR(q->result)[0] = ret;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
/* complete */
|
|
|
|
*(q->done) = -1;
|
|
|
|
|
|
|
|
/* back to caller */
|
2006-12-01 02:43:05 -05:00
|
|
|
if (RTEST(rb_funcall(q->thread, ID_alive_p, 0, 0))) {
|
|
|
|
DUMP2("back to caller (caller thread:%lx)", q->thread);
|
|
|
|
DUMP2(" (current thread:%lx)", rb_thread_current());
|
|
|
|
rb_thread_run(q->thread);
|
|
|
|
DUMP1("finish back to caller");
|
|
|
|
} else {
|
|
|
|
DUMP2("caller is dead (caller thread:%lx)", q->thread);
|
|
|
|
DUMP2(" (current thread:%lx)", rb_thread_current());
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
/* end of handler : remove it */
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ip_eval(self, str)
|
|
|
|
VALUE self;
|
|
|
|
VALUE str;
|
|
|
|
{
|
|
|
|
struct eval_queue *evq;
|
|
|
|
char *eval_str;
|
|
|
|
int *alloc_done;
|
|
|
|
int thr_crit_bup;
|
2004-09-14 04:01:55 -04:00
|
|
|
volatile VALUE current = rb_thread_current();
|
2004-09-11 13:45:53 -04:00
|
|
|
volatile VALUE ip_obj = self;
|
2004-09-14 04:01:55 -04:00
|
|
|
volatile VALUE result;
|
2004-05-01 12:09:54 -04:00
|
|
|
volatile VALUE ret;
|
|
|
|
Tcl_QueuePosition position;
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
StringValue(str);
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (NIL_P(eventloop_thread) || current == eventloop_thread) {
|
2005-07-12 23:47:05 -04:00
|
|
|
if (NIL_P(eventloop_thread)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP2("eval from thread:%lx but no eventloop", current);
|
2005-07-12 23:47:05 -04:00
|
|
|
} else {
|
|
|
|
DUMP2("eval from current eventloop %lx", current);
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
2006-08-31 07:56:42 -04:00
|
|
|
result = ip_eval_real(self, RSTRING_PTR(str), RSTRING_LEN(str));
|
2004-10-11 00:51:21 -04:00
|
|
|
if (rb_obj_is_kind_of(result, rb_eException)) {
|
|
|
|
rb_exc_raise(result);
|
|
|
|
}
|
|
|
|
return result;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
DUMP2("eval from thread %lx (NOT current eventloop)", current);
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
/* allocate memory (protected from Tcl_ServiceEvent) */
|
|
|
|
alloc_done = (int*)ALLOC(int);
|
|
|
|
*alloc_done = 0;
|
|
|
|
|
2006-08-31 07:56:42 -04:00
|
|
|
eval_str = ALLOC_N(char, RSTRING_LEN(str) + 1);
|
|
|
|
memcpy(eval_str, RSTRING_PTR(str), RSTRING_LEN(str));
|
|
|
|
eval_str[RSTRING_LEN(str)] = 0;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
/* allocate memory (freed by Tcl_ServiceEvent) */
|
|
|
|
evq = (struct eval_queue *)Tcl_Alloc(sizeof(struct eval_queue));
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_Preserve(evq);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-09-14 04:01:55 -04:00
|
|
|
/* allocate result obj */
|
2006-09-05 09:07:06 -04:00
|
|
|
result = rb_ary_new3(1, Qnil);
|
2004-09-14 04:01:55 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* construct event data */
|
|
|
|
evq->done = alloc_done;
|
|
|
|
evq->str = eval_str;
|
2006-08-31 07:56:42 -04:00
|
|
|
evq->len = RSTRING_LEN(str);
|
2004-09-11 13:45:53 -04:00
|
|
|
evq->interp = ip_obj;
|
2004-05-01 12:09:54 -04:00
|
|
|
evq->result = result;
|
|
|
|
evq->thread = current;
|
|
|
|
evq->safe_level = rb_safe_level();
|
|
|
|
evq->ev.proc = eval_queue_handler;
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
position = TCL_QUEUE_TAIL;
|
|
|
|
|
|
|
|
/* add the handler to Tcl event queue */
|
|
|
|
DUMP1("add handler");
|
|
|
|
Tcl_QueueEvent(&(evq->ev), position);
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
|
|
|
/* wait for the handler to be processed */
|
|
|
|
DUMP2("wait for handler (current thread:%lx)", current);
|
|
|
|
while(*alloc_done >= 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_stop();
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
DUMP2("back from handler (current thread:%lx)", current);
|
|
|
|
|
|
|
|
/* get result & free allocated memory */
|
2006-09-02 10:42:08 -04:00
|
|
|
ret = RARRAY_PTR(result)[0];
|
2004-09-17 02:05:33 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
free(alloc_done);
|
|
|
|
free(eval_str);
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_Release(evq);
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (rb_obj_is_kind_of(ret, rb_eException)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_exc_raise(ret);
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* restart Tk */
|
|
|
|
static VALUE
|
2005-03-02 02:06:52 -05:00
|
|
|
lib_restart_core(interp, argc, argv)
|
|
|
|
VALUE interp;
|
|
|
|
int argc; /* dummy */
|
|
|
|
VALUE *argv; /* dummy */
|
2004-05-01 12:09:54 -04:00
|
|
|
{
|
2004-09-11 13:45:53 -04:00
|
|
|
volatile VALUE exc;
|
2005-03-02 02:06:52 -05:00
|
|
|
struct tcltkip *ptr = get_ip(interp);
|
2004-05-01 12:09:54 -04:00
|
|
|
int thr_crit_bup;
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* rb_secure(4); */ /* already checked */
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
/* tcl_stubs_check(); */ /* already checked */
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2005-03-02 02:06:52 -05:00
|
|
|
return rb_exc_new2(rb_eRuntimeError, "interpreter is deleted");
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
2004-09-12 12:05:59 -04:00
|
|
|
/* Tcl_Preserve(ptr->ip); */
|
|
|
|
rbtk_preserve_ip(ptr);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* destroy the root wdiget */
|
|
|
|
ptr->return_value = Tcl_Eval(ptr->ip, "destroy .");
|
|
|
|
/* ignore ERROR */
|
|
|
|
DUMP2("(TCL_Eval result) %d", ptr->return_value);
|
|
|
|
Tcl_ResetResult(ptr->ip);
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-05-01 12:09:54 -04:00
|
|
|
/* delete namespace ( tested on tk8.4.5 ) */
|
|
|
|
ptr->return_value = Tcl_Eval(ptr->ip, "namespace delete ::tk::msgcat");
|
|
|
|
/* ignore ERROR */
|
|
|
|
DUMP2("(TCL_Eval result) %d", ptr->return_value);
|
|
|
|
Tcl_ResetResult(ptr->ip);
|
2005-03-02 02:06:52 -05:00
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
/* delete trace proc ( tested on tk8.4.5 ) */
|
|
|
|
ptr->return_value = Tcl_Eval(ptr->ip, "trace vdelete ::tk_strictMotif w ::tk::EventMotifBindings");
|
|
|
|
/* ignore ERROR */
|
|
|
|
DUMP2("(TCL_Eval result) %d", ptr->return_value);
|
|
|
|
Tcl_ResetResult(ptr->ip);
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
/* execute Tk_Init or Tk_SafeInit */
|
|
|
|
exc = tcltkip_init_tk(interp);
|
|
|
|
if (!NIL_P(exc)) {
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-10-11 00:51:21 -04:00
|
|
|
rbtk_release_ip(ptr);
|
2005-03-02 02:06:52 -05:00
|
|
|
return exc;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
2004-09-12 12:05:59 -04:00
|
|
|
/* Tcl_Release(ptr->ip); */
|
|
|
|
rbtk_release_ip(ptr);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* return Qnil; */
|
|
|
|
return interp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
lib_restart(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
|
|
|
|
|
|
|
rb_secure(4);
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
tcl_stubs_check();
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_raise(rb_eRuntimeError, "interpreter is deleted");
|
|
|
|
}
|
|
|
|
|
|
|
|
return tk_funcall(lib_restart_core, 0, (VALUE*)NULL, self);
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ip_restart(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(self);
|
|
|
|
|
|
|
|
rb_secure(4);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
tcl_stubs_check();
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_raise(rb_eRuntimeError, "interpreter is deleted");
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (Tcl_GetMaster(ptr->ip) != (Tcl_Interp*)NULL) {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* slave IP */
|
|
|
|
return Qnil;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
return lib_restart(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
lib_toUTF8_core(ip_obj, src, encodename)
|
|
|
|
VALUE ip_obj;
|
|
|
|
VALUE src;
|
|
|
|
VALUE encodename;
|
|
|
|
{
|
|
|
|
volatile VALUE str = src;
|
|
|
|
|
|
|
|
#ifdef TCL_UTF_MAX
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
Tcl_Encoding encoding;
|
|
|
|
Tcl_DString dstr;
|
|
|
|
int taint_flag = OBJ_TAINTED(str);
|
|
|
|
struct tcltkip *ptr;
|
|
|
|
char *buf;
|
|
|
|
int thr_crit_bup;
|
2005-03-02 02:06:52 -05:00
|
|
|
#endif
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
tcl_stubs_check();
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (NIL_P(src)) {
|
|
|
|
return rb_str_new2("");
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
#ifdef TCL_UTF_MAX
|
2004-05-01 12:09:54 -04:00
|
|
|
if (NIL_P(ip_obj)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
interp = (Tcl_Interp *)NULL;
|
2004-05-01 12:09:54 -04:00
|
|
|
} else {
|
2005-03-02 02:06:52 -05:00
|
|
|
ptr = get_ip(ip_obj);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
interp = (Tcl_Interp *)NULL;
|
2005-03-02 02:06:52 -05:00
|
|
|
} else {
|
|
|
|
interp = ptr->ip;
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
if (NIL_P(encodename)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
if (TYPE(str) == T_STRING) {
|
|
|
|
volatile VALUE enc;
|
2005-08-01 06:09:28 -04:00
|
|
|
enc = rb_attr_get(str, ID_at_enc);
|
2004-10-11 00:51:21 -04:00
|
|
|
if (NIL_P(enc)) {
|
|
|
|
if (NIL_P(ip_obj)) {
|
|
|
|
encoding = (Tcl_Encoding)NULL;
|
|
|
|
} else {
|
2005-08-01 06:09:28 -04:00
|
|
|
enc = rb_attr_get(ip_obj, ID_at_enc);
|
2004-10-11 00:51:21 -04:00
|
|
|
if (NIL_P(enc)) {
|
|
|
|
encoding = (Tcl_Encoding)NULL;
|
|
|
|
} else {
|
|
|
|
StringValue(enc);
|
2006-08-31 07:56:42 -04:00
|
|
|
encoding = Tcl_GetEncoding(interp, RSTRING_PTR(enc));
|
2004-10-11 00:51:21 -04:00
|
|
|
if (encoding == (Tcl_Encoding)NULL) {
|
2006-08-31 07:56:42 -04:00
|
|
|
rb_warning("Tk-interp has unknown encoding information (@encoding:'%s')", RSTRING_PTR(enc));
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
StringValue(enc);
|
2006-08-31 07:56:42 -04:00
|
|
|
if (strcmp(RSTRING_PTR(enc), "binary") == 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
return str;
|
|
|
|
}
|
2006-08-31 07:56:42 -04:00
|
|
|
encoding = Tcl_GetEncoding(interp, RSTRING_PTR(enc));
|
2004-10-11 00:51:21 -04:00
|
|
|
if (encoding == (Tcl_Encoding)NULL) {
|
2006-08-31 07:56:42 -04:00
|
|
|
rb_warning("string has unknown encoding information (@encoding:'%s')", RSTRING_PTR(enc));
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
encoding = (Tcl_Encoding)NULL;
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
StringValue(encodename);
|
2006-08-31 07:56:42 -04:00
|
|
|
encoding = Tcl_GetEncoding(interp, RSTRING_PTR(encodename));
|
2004-10-11 00:51:21 -04:00
|
|
|
if (encoding == (Tcl_Encoding)NULL) {
|
|
|
|
/*
|
|
|
|
rb_warning("unknown encoding name '%s'",
|
2006-08-31 07:56:42 -04:00
|
|
|
RSTRING_PTR(encodename));
|
2004-10-11 00:51:21 -04:00
|
|
|
*/
|
|
|
|
rb_raise(rb_eArgError, "unknown encoding name '%s'",
|
2006-08-31 07:56:42 -04:00
|
|
|
RSTRING_PTR(encodename));
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
StringValue(str);
|
2006-08-31 07:56:42 -04:00
|
|
|
if (!RSTRING_LEN(str)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
return str;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
2006-08-31 07:56:42 -04:00
|
|
|
buf = ALLOC_N(char,RSTRING_LEN(str)+1);
|
|
|
|
memcpy(buf, RSTRING_PTR(str), RSTRING_LEN(str));
|
|
|
|
buf[RSTRING_LEN(str)] = 0;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
Tcl_DStringInit(&dstr);
|
|
|
|
Tcl_DStringFree(&dstr);
|
|
|
|
/* Tcl_ExternalToUtfDString(encoding,buf,strlen(buf),&dstr); */
|
2006-08-31 07:56:42 -04:00
|
|
|
Tcl_ExternalToUtfDString(encoding, buf, RSTRING_LEN(str), &dstr);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
/* str = rb_tainted_str_new2(Tcl_DStringValue(&dstr)); */
|
2005-07-05 01:56:31 -04:00
|
|
|
/* str = rb_str_new2(Tcl_DStringValue(&dstr)); */
|
|
|
|
str = rb_str_new(Tcl_DStringValue(&dstr), Tcl_DStringLength(&dstr));
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_ivar_set(str, ID_at_enc, rb_tainted_str_new2("utf-8"));
|
|
|
|
if (taint_flag) OBJ_TAINT(str);
|
|
|
|
|
|
|
|
if (encoding != (Tcl_Encoding)NULL) {
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_FreeEncoding(encoding);
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
Tcl_DStringFree(&dstr);
|
|
|
|
|
|
|
|
free(buf);
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
lib_toUTF8(argc, argv, self)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
VALUE str, encodename;
|
|
|
|
|
|
|
|
if (rb_scan_args(argc, argv, "11", &str, &encodename) == 1) {
|
2004-10-11 00:51:21 -04:00
|
|
|
encodename = Qnil;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
return lib_toUTF8_core(Qnil, str, encodename);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ip_toUTF8(argc, argv, self)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
VALUE str, encodename;
|
|
|
|
|
|
|
|
if (rb_scan_args(argc, argv, "11", &str, &encodename) == 1) {
|
2004-10-11 00:51:21 -04:00
|
|
|
encodename = Qnil;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
return lib_toUTF8_core(self, str, encodename);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
lib_fromUTF8_core(ip_obj, src, encodename)
|
|
|
|
VALUE ip_obj;
|
|
|
|
VALUE src;
|
|
|
|
VALUE encodename;
|
|
|
|
{
|
|
|
|
volatile VALUE str = src;
|
|
|
|
|
|
|
|
#ifdef TCL_UTF_MAX
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
Tcl_Encoding encoding;
|
|
|
|
Tcl_DString dstr;
|
|
|
|
int taint_flag = OBJ_TAINTED(str);
|
|
|
|
char *buf;
|
|
|
|
int thr_crit_bup;
|
2005-03-02 02:06:52 -05:00
|
|
|
#endif
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
tcl_stubs_check();
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
if (NIL_P(src)) {
|
|
|
|
return rb_str_new2("");
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
#ifdef TCL_UTF_MAX
|
2004-05-01 12:09:54 -04:00
|
|
|
if (NIL_P(ip_obj)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
interp = (Tcl_Interp *)NULL;
|
2005-03-02 02:06:52 -05:00
|
|
|
} else if (get_ip(ip_obj) == (struct tcltkip *)NULL) {
|
|
|
|
interp = (Tcl_Interp *)NULL;
|
2004-05-01 12:09:54 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
interp = get_ip(ip_obj)->ip;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
if (NIL_P(encodename)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
volatile VALUE enc;
|
|
|
|
|
|
|
|
if (TYPE(str) == T_STRING) {
|
2005-08-01 06:09:28 -04:00
|
|
|
enc = rb_attr_get(str, ID_at_enc);
|
2005-08-09 02:16:29 -04:00
|
|
|
if (!NIL_P(enc)) {
|
|
|
|
StringValue(enc);
|
2006-08-31 07:56:42 -04:00
|
|
|
if (strcmp(RSTRING_PTR(enc), "binary") == 0) {
|
2005-08-09 02:16:29 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
return str;
|
|
|
|
}
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NIL_P(ip_obj)) {
|
|
|
|
encoding = (Tcl_Encoding)NULL;
|
|
|
|
} else {
|
2005-08-01 06:09:28 -04:00
|
|
|
enc = rb_attr_get(ip_obj, ID_at_enc);
|
2004-10-11 00:51:21 -04:00
|
|
|
if (NIL_P(enc)) {
|
|
|
|
encoding = (Tcl_Encoding)NULL;
|
|
|
|
} else {
|
|
|
|
StringValue(enc);
|
2006-08-31 07:56:42 -04:00
|
|
|
encoding = Tcl_GetEncoding(interp, RSTRING_PTR(enc));
|
2004-10-11 00:51:21 -04:00
|
|
|
if (encoding == (Tcl_Encoding)NULL) {
|
2006-08-31 07:56:42 -04:00
|
|
|
rb_warning("Tk-interp has unknown encoding information (@encoding:'%s')", RSTRING_PTR(enc));
|
2004-10-11 00:51:21 -04:00
|
|
|
} else {
|
|
|
|
encodename = rb_obj_dup(enc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
StringValue(encodename);
|
|
|
|
|
2006-08-31 07:56:42 -04:00
|
|
|
if (strcmp(RSTRING_PTR(encodename), "binary") == 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
char *s;
|
|
|
|
int len;
|
|
|
|
|
2006-04-05 12:08:45 -04:00
|
|
|
StringValue(str);
|
2006-08-31 07:56:42 -04:00
|
|
|
s = Tcl_GetByteArrayFromObj(Tcl_NewStringObj(RSTRING_PTR(str),
|
|
|
|
RSTRING_LEN(str)),
|
2004-10-11 00:51:21 -04:00
|
|
|
&len);
|
|
|
|
str = rb_tainted_str_new(s, len);
|
|
|
|
rb_ivar_set(str, ID_at_enc, rb_tainted_str_new2("binary"));
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2006-08-31 07:56:42 -04:00
|
|
|
encoding = Tcl_GetEncoding(interp, RSTRING_PTR(encodename));
|
2004-10-11 00:51:21 -04:00
|
|
|
if (encoding == (Tcl_Encoding)NULL) {
|
|
|
|
/*
|
|
|
|
rb_warning("unknown encoding name '%s'",
|
2006-08-31 07:56:42 -04:00
|
|
|
RSTRING_PTR(encodename));
|
2004-10-11 00:51:21 -04:00
|
|
|
encodename = Qnil;
|
|
|
|
*/
|
|
|
|
rb_raise(rb_eArgError, "unknown encoding name '%s'",
|
2006-08-31 07:56:42 -04:00
|
|
|
RSTRING_PTR(encodename));
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
StringValue(str);
|
|
|
|
|
2006-08-31 07:56:42 -04:00
|
|
|
if (RSTRING_LEN(str) == 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
return rb_tainted_str_new2("");
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
2006-08-31 07:56:42 -04:00
|
|
|
buf = ALLOC_N(char,strlen(RSTRING_PTR(str))+1);
|
|
|
|
memcpy(buf, RSTRING_PTR(str), RSTRING_LEN(str));
|
|
|
|
buf[RSTRING_LEN(str)] = 0;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
Tcl_DStringInit(&dstr);
|
|
|
|
Tcl_DStringFree(&dstr);
|
|
|
|
/* Tcl_UtfToExternalDString(encoding,buf,strlen(buf),&dstr); */
|
2006-08-31 07:56:42 -04:00
|
|
|
Tcl_UtfToExternalDString(encoding,buf,RSTRING_LEN(str),&dstr);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
/* str = rb_tainted_str_new2(Tcl_DStringValue(&dstr)); */
|
2005-07-05 01:56:31 -04:00
|
|
|
/* str = rb_str_new2(Tcl_DStringValue(&dstr)); */
|
|
|
|
str = rb_str_new(Tcl_DStringValue(&dstr), Tcl_DStringLength(&dstr));
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_ivar_set(str, ID_at_enc, encodename);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (taint_flag) OBJ_TAINT(str);
|
|
|
|
|
|
|
|
if (encoding != (Tcl_Encoding)NULL) {
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_FreeEncoding(encoding);
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
Tcl_DStringFree(&dstr);
|
|
|
|
|
|
|
|
free(buf);
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
lib_fromUTF8(argc, argv, self)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
VALUE str, encodename;
|
|
|
|
|
|
|
|
if (rb_scan_args(argc, argv, "11", &str, &encodename) == 1) {
|
2004-10-11 00:51:21 -04:00
|
|
|
encodename = Qnil;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
return lib_fromUTF8_core(Qnil, str, encodename);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ip_fromUTF8(argc, argv, self)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
VALUE str, encodename;
|
|
|
|
|
|
|
|
if (rb_scan_args(argc, argv, "11", &str, &encodename) == 1) {
|
2004-10-11 00:51:21 -04:00
|
|
|
encodename = Qnil;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
return lib_fromUTF8_core(self, str, encodename);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
lib_UTF_backslash_core(self, str, all_bs)
|
|
|
|
VALUE self;
|
|
|
|
VALUE str;
|
|
|
|
int all_bs;
|
|
|
|
{
|
|
|
|
#ifdef TCL_UTF_MAX
|
|
|
|
char *src_buf, *dst_buf, *ptr;
|
|
|
|
int read_len = 0, dst_len = 0;
|
|
|
|
int taint_flag = OBJ_TAINTED(str);
|
|
|
|
int thr_crit_bup;
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
tcl_stubs_check();
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
StringValue(str);
|
2006-08-31 07:56:42 -04:00
|
|
|
if (!RSTRING_LEN(str)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return str;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
2006-08-31 07:56:42 -04:00
|
|
|
src_buf = ALLOC_N(char,RSTRING_LEN(str)+1);
|
|
|
|
memcpy(src_buf, RSTRING_PTR(str), RSTRING_LEN(str));
|
|
|
|
src_buf[RSTRING_LEN(str)] = 0;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2006-08-31 07:56:42 -04:00
|
|
|
dst_buf = ALLOC_N(char,RSTRING_LEN(str)+1);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
ptr = src_buf;
|
2006-08-31 07:56:42 -04:00
|
|
|
while(RSTRING_LEN(str) > ptr - src_buf) {
|
2004-10-11 00:51:21 -04:00
|
|
|
if (*ptr == '\\' && (all_bs || *(ptr + 1) == 'u')) {
|
|
|
|
dst_len += Tcl_UtfBackslash(ptr, &read_len, (dst_buf + dst_len));
|
|
|
|
ptr += read_len;
|
|
|
|
} else {
|
|
|
|
*(dst_buf + (dst_len++)) = *(ptr++);
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
str = rb_str_new(dst_buf, dst_len);
|
|
|
|
if (taint_flag) OBJ_TAINT(str);
|
|
|
|
|
|
|
|
free(src_buf);
|
|
|
|
free(dst_buf);
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
lib_UTF_backslash(self, str)
|
|
|
|
VALUE self;
|
|
|
|
VALUE str;
|
|
|
|
{
|
|
|
|
return lib_UTF_backslash_core(self, str, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
lib_Tcl_backslash(self, str)
|
|
|
|
VALUE self;
|
|
|
|
VALUE str;
|
|
|
|
{
|
|
|
|
return lib_UTF_backslash_core(self, str, 1);
|
|
|
|
}
|
|
|
|
|
2005-07-05 01:56:31 -04:00
|
|
|
static VALUE
|
|
|
|
lib_get_system_encoding(self)
|
|
|
|
VALUE self;
|
|
|
|
{
|
|
|
|
#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION > 0)
|
2005-07-28 05:14:59 -04:00
|
|
|
tcl_stubs_check();
|
2005-07-05 01:56:31 -04:00
|
|
|
return rb_str_new2(Tcl_GetEncodingName((Tcl_Encoding)NULL));
|
|
|
|
#else
|
|
|
|
return Qnil;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
lib_set_system_encoding(self, enc_name)
|
|
|
|
VALUE self;
|
|
|
|
VALUE enc_name;
|
|
|
|
{
|
|
|
|
#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION > 0)
|
2005-07-28 05:14:59 -04:00
|
|
|
tcl_stubs_check();
|
|
|
|
|
|
|
|
if (NIL_P(enc_name)) {
|
2005-07-05 01:56:31 -04:00
|
|
|
Tcl_SetSystemEncoding((Tcl_Interp *)NULL, (CONST char *)NULL);
|
|
|
|
return lib_get_system_encoding(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
enc_name = rb_funcall(enc_name, ID_to_s, 0, 0);
|
|
|
|
if (Tcl_SetSystemEncoding((Tcl_Interp *)NULL,
|
2006-04-05 12:08:45 -04:00
|
|
|
StringValuePtr(enc_name)) != TCL_OK) {
|
2005-07-05 01:56:31 -04:00
|
|
|
rb_raise(rb_eArgError, "unknown encoding name '%s'",
|
2006-08-31 07:56:42 -04:00
|
|
|
RSTRING_PTR(enc_name));
|
2005-07-05 01:56:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return enc_name;
|
|
|
|
#else
|
|
|
|
return Qnil;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
/* invoke Tcl proc */
|
|
|
|
struct invoke_info {
|
|
|
|
struct tcltkip *ptr;
|
|
|
|
Tcl_CmdInfo cmdinfo;
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
int objc;
|
|
|
|
Tcl_Obj **objv;
|
|
|
|
#else
|
|
|
|
int argc;
|
|
|
|
char **argv;
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
invoke_tcl_proc(arg)
|
|
|
|
VALUE arg;
|
|
|
|
{
|
|
|
|
struct invoke_info *inf = (struct invoke_info *)arg;
|
|
|
|
int i, len;
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
int argc = inf->objc;
|
|
|
|
char **argv = (char **)NULL;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* memory allocation for arguments of this command */
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
if (!inf->cmdinfo.isNativeObjectProc) {
|
|
|
|
/* string interface */
|
|
|
|
argv = (char **)ALLOC_N(char *, argc+1);
|
|
|
|
for (i = 0; i < argc; ++i) {
|
|
|
|
argv[i] = Tcl_GetStringFromObj(inf->objv[i], &len);
|
|
|
|
}
|
|
|
|
argv[argc] = (char *)NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Tcl_ResetResult(inf->ptr->ip);
|
|
|
|
|
|
|
|
/* Invoke the C procedure */
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
if (inf->cmdinfo.isNativeObjectProc) {
|
|
|
|
inf->ptr->return_value
|
|
|
|
= (*(inf->cmdinfo.objProc))(inf->cmdinfo.objClientData,
|
|
|
|
inf->ptr->ip, inf->objc, inf->objv);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
inf->ptr->return_value
|
|
|
|
= (*(inf->cmdinfo.proc))(inf->cmdinfo.clientData, inf->ptr->ip,
|
|
|
|
argc, (CONST84 char **)argv);
|
|
|
|
|
|
|
|
free(argv);
|
|
|
|
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
inf->ptr->return_value
|
|
|
|
= (*(inf->cmdinfo.proc))(inf->cmdinfo.clientData, inf->ptr->ip,
|
|
|
|
inf->argc, inf->argv);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
static VALUE
|
|
|
|
ip_invoke_core(interp, objc, objv)
|
|
|
|
VALUE interp;
|
|
|
|
int objc;
|
|
|
|
Tcl_Obj **objv;
|
|
|
|
#else
|
|
|
|
static VALUE
|
|
|
|
ip_invoke_core(interp, argc, argv)
|
|
|
|
VALUE interp;
|
|
|
|
int argc;
|
|
|
|
char **argv;
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr;
|
|
|
|
Tcl_CmdInfo info;
|
|
|
|
char *cmd;
|
|
|
|
int len;
|
|
|
|
int thr_crit_bup;
|
2005-11-06 23:47:08 -05:00
|
|
|
int unknown_flag = 0;
|
|
|
|
|
|
|
|
#if 1 /* wrap tcl-proc call */
|
2005-03-02 02:06:52 -05:00
|
|
|
struct invoke_info inf;
|
|
|
|
int status;
|
|
|
|
VALUE ret;
|
2005-11-06 23:47:08 -05:00
|
|
|
#else
|
2004-05-01 12:09:54 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
int argc = objc;
|
|
|
|
char **argv = (char **)NULL;
|
2005-11-06 23:47:08 -05:00
|
|
|
/* Tcl_Obj *resultPtr; */
|
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* get the command name string */
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
cmd = Tcl_GetStringFromObj(objv[0], &len);
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
cmd = argv[0];
|
|
|
|
#endif
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* get the data struct */
|
|
|
|
ptr = get_ip(interp);
|
|
|
|
|
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return rb_tainted_str_new2("");
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* Tcl_Preserve(ptr->ip); */
|
|
|
|
rbtk_preserve_ip(ptr);
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* map from the command name to a C procedure */
|
|
|
|
DUMP2("call Tcl_GetCommandInfo, %s", cmd);
|
|
|
|
if (!Tcl_GetCommandInfo(ptr->ip, cmd, &info)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("error Tcl_GetCommandInfo");
|
2005-04-26 10:00:20 -04:00
|
|
|
DUMP1("try auto_load (call 'unknown' command)");
|
|
|
|
if (!Tcl_GetCommandInfo(ptr->ip,
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
"::unknown",
|
|
|
|
#else
|
|
|
|
"unknown",
|
|
|
|
#endif
|
|
|
|
&info)) {
|
|
|
|
DUMP1("fail to get 'unknown' command");
|
|
|
|
/* if (event_loop_abort_on_exc || cmd[0] != '.') { */
|
|
|
|
if (event_loop_abort_on_exc > 0) {
|
|
|
|
/* Tcl_Release(ptr->ip); */
|
|
|
|
rbtk_release_ip(ptr);
|
|
|
|
/*rb_ip_raise(obj,rb_eNameError,"invalid command name `%s'",cmd);*/
|
|
|
|
return create_ip_exc(interp, rb_eNameError,
|
|
|
|
"invalid command name `%s'", cmd);
|
2004-10-11 00:51:21 -04:00
|
|
|
} else {
|
2005-04-26 10:00:20 -04:00
|
|
|
if (event_loop_abort_on_exc < 0) {
|
|
|
|
rb_warning("invalid command name `%s' (ignore)", cmd);
|
|
|
|
} else {
|
|
|
|
rb_warn("invalid command name `%s' (ignore)", cmd);
|
|
|
|
}
|
|
|
|
Tcl_ResetResult(ptr->ip);
|
|
|
|
/* Tcl_Release(ptr->ip); */
|
|
|
|
rbtk_release_ip(ptr);
|
|
|
|
return rb_tainted_str_new2("");
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
2005-04-26 10:00:20 -04:00
|
|
|
} else {
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
Tcl_Obj **unknown_objv;
|
|
|
|
#else
|
|
|
|
char **unknown_argv;
|
|
|
|
#endif
|
|
|
|
DUMP1("find 'unknown' command -> set arguemnts");
|
|
|
|
unknown_flag = 1;
|
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
unknown_objv = (Tcl_Obj **)ALLOC_N(Tcl_Obj *, objc+2);
|
|
|
|
unknown_objv[0] = Tcl_NewStringObj("::unknown", 9);
|
|
|
|
Tcl_IncrRefCount(unknown_objv[0]);
|
|
|
|
memcpy(unknown_objv + 1, objv, sizeof(Tcl_Obj *)*objc);
|
|
|
|
unknown_objv[++objc] = (Tcl_Obj*)NULL;
|
|
|
|
objv = unknown_objv;
|
|
|
|
#else
|
|
|
|
unknown_argv = (char **)ALLOC_N(char *, argc+2);
|
|
|
|
unknown_argv[0] = strdup("unknown");
|
|
|
|
memcpy(unknown_argv + 1, argv, sizeof(char *)*argc);
|
|
|
|
unknown_argv[++argc] = (char *)NULL;
|
|
|
|
argv = unknown_argv;
|
|
|
|
#endif
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
DUMP1("end Tcl_GetCommandInfo");
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
#if 1 /* wrap tcl-proc call */
|
|
|
|
/* setup params */
|
|
|
|
inf.ptr = ptr;
|
|
|
|
inf.cmdinfo = info;
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
inf.objc = objc;
|
|
|
|
inf.objv = objv;
|
|
|
|
#else
|
|
|
|
inf.argc = argc;
|
|
|
|
inf.argv = argv;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* invoke tcl-proc */
|
|
|
|
ret = rb_protect(invoke_tcl_proc, (VALUE)&inf, &status);
|
|
|
|
switch(status) {
|
|
|
|
case TAG_RAISE:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eException,
|
|
|
|
"unknown exception");
|
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
rbtk_pending_exception = rb_errinfo();
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TAG_FATAL:
|
2006-12-31 18:12:35 -05:00
|
|
|
if (NIL_P(rb_errinfo())) {
|
2005-03-02 02:06:52 -05:00
|
|
|
rbtk_pending_exception = rb_exc_new2(rb_eFatal, "FATAL");
|
|
|
|
} else {
|
2006-12-31 18:12:35 -05:00
|
|
|
rbtk_pending_exception = rb_errinfo();
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* !wrap tcl-proc call */
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* memory allocation for arguments of this command */
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
if (!info.isNativeObjectProc) {
|
2005-11-06 23:47:08 -05:00
|
|
|
int i;
|
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
/* string interface */
|
|
|
|
argv = (char **)ALLOC_N(char *, argc+1);
|
|
|
|
for (i = 0; i < argc; ++i) {
|
|
|
|
argv[i] = Tcl_GetStringFromObj(objv[i], &len);
|
|
|
|
}
|
|
|
|
argv[argc] = (char *)NULL;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Tcl_ResetResult(ptr->ip);
|
|
|
|
|
|
|
|
/* Invoke the C procedure */
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
if (info.isNativeObjectProc) {
|
2004-10-11 00:51:21 -04:00
|
|
|
ptr->return_value = (*info.objProc)(info.objClientData, ptr->ip,
|
|
|
|
objc, objv);
|
2004-05-01 12:09:54 -04:00
|
|
|
#if 0
|
2004-10-11 00:51:21 -04:00
|
|
|
/* get the string value from the result object */
|
|
|
|
resultPtr = Tcl_GetObjResult(ptr->ip);
|
|
|
|
Tcl_SetResult(ptr->ip, Tcl_GetStringFromObj(resultPtr, &len),
|
|
|
|
TCL_VOLATILE);
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
ptr->return_value = (*info.proc)(info.clientData, ptr->ip,
|
|
|
|
argc, (CONST84 char **)argv);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
free(argv);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2004-10-11 00:51:21 -04:00
|
|
|
ptr->return_value = (*info.proc)(info.clientData, ptr->ip,
|
|
|
|
argc, argv);
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
|
|
|
}
|
2005-03-02 02:06:52 -05:00
|
|
|
#endif /* ! wrap tcl-proc call */
|
|
|
|
|
2005-04-26 10:00:20 -04:00
|
|
|
/* free allocated memory for calling 'unknown' command */
|
|
|
|
if (unknown_flag) {
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
Tcl_DecrRefCount(objv[0]);
|
|
|
|
free(objv);
|
|
|
|
#else
|
|
|
|
free(argv[0]);
|
|
|
|
free(argv);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/* exception on mainloop */
|
|
|
|
if (pending_exception_check1(thr_crit_bup, ptr)) {
|
|
|
|
return rbtk_pending_exception;
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
|
|
|
if (ptr->return_value == TCL_ERROR) {
|
2004-10-11 00:51:21 -04:00
|
|
|
if (event_loop_abort_on_exc > 0 && !Tcl_InterpDeleted(ptr->ip)) {
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
return create_ip_exc(interp, rb_eRuntimeError,
|
|
|
|
"%s", Tcl_GetStringResult(ptr->ip));
|
|
|
|
} else {
|
|
|
|
if (event_loop_abort_on_exc < 0) {
|
|
|
|
rb_warning("%s (ignore)", Tcl_GetStringResult(ptr->ip));
|
|
|
|
} else {
|
|
|
|
rb_warn("%s (ignore)", Tcl_GetStringResult(ptr->ip));
|
|
|
|
}
|
|
|
|
Tcl_ResetResult(ptr->ip);
|
|
|
|
return rb_tainted_str_new2("");
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* pass back the result (as string) */
|
|
|
|
return ip_get_result_string_obj(ptr->ip);
|
|
|
|
}
|
|
|
|
|
2003-10-14 11:25:45 -04:00
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-05-01 12:09:54 -04:00
|
|
|
static Tcl_Obj **
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
static char **
|
2003-10-14 11:25:45 -04:00
|
|
|
#endif
|
2004-05-01 12:09:54 -04:00
|
|
|
alloc_invoke_arguments(argc, argv)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int thr_crit_bup;
|
2003-10-14 11:25:45 -04:00
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2005-08-04 11:26:05 -04:00
|
|
|
Tcl_Obj **av;
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2005-08-04 11:26:05 -04:00
|
|
|
char **av;
|
2003-10-14 11:25:45 -04:00
|
|
|
#endif
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
/* memory allocation */
|
2003-10-14 11:25:45 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2005-08-04 11:26:05 -04:00
|
|
|
av = ALLOC_N(Tcl_Obj *, argc+1);
|
2004-05-01 12:09:54 -04:00
|
|
|
for (i = 0; i < argc; ++i) {
|
2005-08-04 11:26:05 -04:00
|
|
|
av[i] = get_obj_from_str(argv[i]);
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_IncrRefCount(av[i]);
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
2005-08-04 11:26:05 -04:00
|
|
|
av[argc] = NULL;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
/* string interface */
|
2005-08-04 11:26:05 -04:00
|
|
|
av = ALLOC_N(char *, argc+1);
|
2004-05-01 12:09:54 -04:00
|
|
|
for (i = 0; i < argc; ++i) {
|
2005-08-04 11:26:05 -04:00
|
|
|
av[i] = strdup(StringValuePtr(argv[i]));
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
2005-08-04 11:26:05 -04:00
|
|
|
av[argc] = NULL;
|
2003-10-14 11:25:45 -04:00
|
|
|
#endif
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
|
|
|
return av;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
free_invoke_arguments(argc, av)
|
|
|
|
int argc;
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
Tcl_Obj **av;
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
char **av;
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < argc; ++i) {
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(av[i]);
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2004-10-11 00:51:21 -04:00
|
|
|
free(av[i]);
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
free(av);
|
1998-01-16 07:19:09 -05:00
|
|
|
}
|
|
|
|
|
2003-07-25 12:43:03 -04:00
|
|
|
static VALUE
|
2004-05-01 12:09:54 -04:00
|
|
|
ip_invoke_real(argc, argv, interp)
|
|
|
|
int argc;
|
2003-07-25 12:43:03 -04:00
|
|
|
VALUE *argv;
|
2004-05-01 12:09:54 -04:00
|
|
|
VALUE interp;
|
2003-07-25 12:43:03 -04:00
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
VALUE v;
|
2004-10-11 00:51:21 -04:00
|
|
|
struct tcltkip *ptr; /* tcltkip data struct */
|
2003-07-25 12:43:03 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
Tcl_Obj **av = (Tcl_Obj **)NULL;
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
char **av = (char **)NULL;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
DUMP2("invoke_real called by thread:%lx", rb_thread_current());
|
|
|
|
|
|
|
|
/* get the data struct */
|
|
|
|
ptr = get_ip(interp);
|
|
|
|
|
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return rb_tainted_str_new2("");
|
2003-07-25 12:43:03 -04:00
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-07-19 01:12:52 -04:00
|
|
|
/* allocate memory for arguments */
|
|
|
|
av = alloc_invoke_arguments(argc, argv);
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* Invoke the C procedure */
|
|
|
|
Tcl_ResetResult(ptr->ip);
|
|
|
|
v = ip_invoke_core(interp, argc, av);
|
|
|
|
|
|
|
|
/* free allocated memory */
|
|
|
|
free_invoke_arguments(argc, av);
|
|
|
|
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
VALUE
|
|
|
|
ivq_safelevel_handler(arg, ivq)
|
|
|
|
VALUE arg;
|
|
|
|
VALUE ivq;
|
|
|
|
{
|
|
|
|
struct invoke_queue *q;
|
|
|
|
|
|
|
|
Data_Get_Struct(ivq, struct invoke_queue, q);
|
|
|
|
DUMP2("(safe-level handler) $SAFE = %d", q->safe_level);
|
|
|
|
rb_set_safe_level(q->safe_level);
|
|
|
|
return ip_invoke_core(q->interp, q->argc, q->argv);
|
|
|
|
}
|
|
|
|
|
|
|
|
int invoke_queue_handler _((Tcl_Event *, int));
|
|
|
|
int
|
|
|
|
invoke_queue_handler(evPtr, flags)
|
|
|
|
Tcl_Event *evPtr;
|
|
|
|
int flags;
|
|
|
|
{
|
|
|
|
struct invoke_queue *q = (struct invoke_queue *)evPtr;
|
|
|
|
volatile VALUE ret;
|
2004-09-11 13:45:53 -04:00
|
|
|
volatile VALUE q_dat;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
DUMP2("do_invoke_queue_handler : evPtr = %p", evPtr);
|
|
|
|
DUMP2("invoke queue_thread : %lx", rb_thread_current());
|
|
|
|
DUMP2("added by thread : %lx", q->thread);
|
|
|
|
|
|
|
|
if (*(q->done)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("processed by another event-loop");
|
|
|
|
return 0;
|
2003-07-25 12:43:03 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("process it on current event-loop");
|
2003-07-25 12:43:03 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* process it */
|
|
|
|
*(q->done) = 1;
|
|
|
|
|
|
|
|
/* check safe-level */
|
|
|
|
if (rb_safe_level() != q->safe_level) {
|
2004-10-11 00:51:21 -04:00
|
|
|
/* q_dat = Data_Wrap_Struct(rb_cData,0,0,q); */
|
|
|
|
q_dat = Data_Wrap_Struct(rb_cData,invoke_queue_mark,0,q);
|
|
|
|
ret = rb_funcall(rb_proc_new(ivq_safelevel_handler, q_dat),
|
|
|
|
ID_call, 0);
|
|
|
|
rb_gc_force_recycle(q_dat);
|
2004-05-01 12:09:54 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP2("call invoke_real (for caller thread:%lx)", q->thread);
|
|
|
|
DUMP2("call invoke_real (current thread:%lx)", rb_thread_current());
|
|
|
|
ret = ip_invoke_core(q->interp, q->argc, q->argv);
|
2003-07-25 12:43:03 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* set result */
|
2006-09-02 10:42:08 -04:00
|
|
|
RARRAY_PTR(q->result)[0] = ret;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
/* complete */
|
|
|
|
*(q->done) = -1;
|
|
|
|
|
|
|
|
/* back to caller */
|
2006-12-01 02:43:05 -05:00
|
|
|
if (RTEST(rb_funcall(q->thread, ID_alive_p, 0, 0))) {
|
|
|
|
DUMP2("back to caller (caller thread:%lx)", q->thread);
|
|
|
|
DUMP2(" (current thread:%lx)", rb_thread_current());
|
|
|
|
rb_thread_run(q->thread);
|
|
|
|
DUMP1("finish back to caller");
|
|
|
|
} else {
|
|
|
|
DUMP2("caller is dead (caller thread:%lx)", q->thread);
|
|
|
|
DUMP2(" (current thread:%lx)", rb_thread_current());
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
/* end of handler : remove it */
|
|
|
|
return 1;
|
2003-07-25 12:43:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2004-05-01 12:09:54 -04:00
|
|
|
ip_invoke_with_position(argc, argv, obj, position)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE obj;
|
|
|
|
Tcl_QueuePosition position;
|
2003-07-25 12:43:03 -04:00
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
struct invoke_queue *ivq;
|
|
|
|
int *alloc_done;
|
|
|
|
int thr_crit_bup;
|
2004-09-14 04:01:55 -04:00
|
|
|
volatile VALUE current = rb_thread_current();
|
2004-09-11 13:45:53 -04:00
|
|
|
volatile VALUE ip_obj = obj;
|
2004-09-14 04:01:55 -04:00
|
|
|
volatile VALUE result;
|
2004-05-01 12:09:54 -04:00
|
|
|
volatile VALUE ret;
|
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
Tcl_Obj **av = (Tcl_Obj **)NULL;
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
char **av = (char **)NULL;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (argc < 1) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_raise(rb_eArgError, "command name missing");
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
2005-03-02 02:06:52 -05:00
|
|
|
if (NIL_P(eventloop_thread) || current == eventloop_thread) {
|
2005-07-12 23:47:05 -04:00
|
|
|
if (NIL_P(eventloop_thread)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP2("invoke from thread:%lx but no eventloop", current);
|
2005-07-12 23:47:05 -04:00
|
|
|
} else {
|
|
|
|
DUMP2("invoke from current eventloop %lx", current);
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
result = ip_invoke_real(argc, argv, ip_obj);
|
|
|
|
if (rb_obj_is_kind_of(result, rb_eException)) {
|
|
|
|
rb_exc_raise(result);
|
|
|
|
}
|
|
|
|
return result;
|
2003-07-25 12:43:03 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
DUMP2("invoke from thread %lx (NOT current eventloop)", current);
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
/* allocate memory (for arguments) */
|
|
|
|
av = alloc_invoke_arguments(argc, argv);
|
|
|
|
|
|
|
|
/* allocate memory (keep result) */
|
|
|
|
alloc_done = (int*)ALLOC(int);
|
|
|
|
*alloc_done = 0;
|
|
|
|
|
|
|
|
/* allocate memory (freed by Tcl_ServiceEvent) */
|
|
|
|
ivq = (struct invoke_queue *)Tcl_Alloc(sizeof(struct invoke_queue));
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_Preserve(ivq);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-09-14 04:01:55 -04:00
|
|
|
/* allocate result obj */
|
2006-09-05 09:07:06 -04:00
|
|
|
result = rb_ary_new3(1, Qnil);
|
2004-09-14 04:01:55 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* construct event data */
|
|
|
|
ivq->done = alloc_done;
|
|
|
|
ivq->argc = argc;
|
|
|
|
ivq->argv = av;
|
2004-09-11 13:45:53 -04:00
|
|
|
ivq->interp = ip_obj;
|
2004-05-01 12:09:54 -04:00
|
|
|
ivq->result = result;
|
|
|
|
ivq->thread = current;
|
|
|
|
ivq->safe_level = rb_safe_level();
|
|
|
|
ivq->ev.proc = invoke_queue_handler;
|
|
|
|
|
|
|
|
/* add the handler to Tcl event queue */
|
|
|
|
DUMP1("add handler");
|
|
|
|
Tcl_QueueEvent(&(ivq->ev), position);
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
|
|
|
/* wait for the handler to be processed */
|
|
|
|
DUMP2("wait for handler (current thread:%lx)", current);
|
|
|
|
while(*alloc_done >= 0) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_stop();
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
DUMP2("back from handler (current thread:%lx)", current);
|
|
|
|
|
|
|
|
/* get result & free allocated memory */
|
2006-09-02 10:42:08 -04:00
|
|
|
ret = RARRAY_PTR(result)[0];
|
2004-05-01 12:09:54 -04:00
|
|
|
free(alloc_done);
|
|
|
|
|
2004-09-17 02:05:33 -04:00
|
|
|
Tcl_Release(ivq);
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* free allocated memory */
|
|
|
|
free_invoke_arguments(argc, av);
|
|
|
|
|
|
|
|
/* exception? */
|
|
|
|
if (rb_obj_is_kind_of(ret, rb_eException)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
DUMP1("raise exception");
|
|
|
|
rb_exc_raise(ret);
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
DUMP1("exit ip_invoke");
|
|
|
|
return ret;
|
2003-07-25 12:43:03 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
/* get return code from Tcl_Eval() */
|
2003-07-25 12:43:03 -04:00
|
|
|
static VALUE
|
2004-05-01 12:09:54 -04:00
|
|
|
ip_retval(self)
|
2003-07-25 12:43:03 -04:00
|
|
|
VALUE self;
|
|
|
|
{
|
2004-10-11 00:51:21 -04:00
|
|
|
struct tcltkip *ptr; /* tcltkip data struct */
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
/* get the data strcut */
|
|
|
|
ptr = get_ip(self);
|
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return rb_tainted_str_new2("");
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
return (INT2FIX(ptr->return_value));
|
2003-07-25 12:43:03 -04:00
|
|
|
}
|
|
|
|
|
2003-07-27 15:35:06 -04:00
|
|
|
static VALUE
|
2004-05-01 12:09:54 -04:00
|
|
|
ip_invoke(argc, argv, obj)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE obj;
|
|
|
|
{
|
|
|
|
return ip_invoke_with_position(argc, argv, obj, TCL_QUEUE_TAIL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ip_invoke_immediate(argc, argv, obj)
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE obj;
|
|
|
|
{
|
2005-11-06 23:47:08 -05:00
|
|
|
/* POTENTIALY INSECURE : can create infinite loop */
|
|
|
|
rb_secure(4);
|
2004-05-01 12:09:54 -04:00
|
|
|
return ip_invoke_with_position(argc, argv, obj, TCL_QUEUE_HEAD);
|
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* access Tcl variables */
|
2005-03-02 02:06:52 -05:00
|
|
|
static VALUE
|
|
|
|
ip_get_variable2_core(interp, argc, argv)
|
|
|
|
VALUE interp;
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(interp);
|
|
|
|
int thr_crit_bup;
|
|
|
|
volatile VALUE varname, index, flag;
|
2003-07-27 15:35:06 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
varname = argv[0];
|
|
|
|
index = argv[1];
|
|
|
|
flag = argv[2];
|
2003-11-07 16:39:36 -05:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/*
|
2004-05-01 12:09:54 -04:00
|
|
|
StringValue(varname);
|
2005-08-01 21:25:01 -04:00
|
|
|
if (!NIL_P(index)) StringValue(index);
|
2005-03-02 02:06:52 -05:00
|
|
|
*/
|
1998-01-16 07:19:09 -05:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
{
|
2005-08-01 21:25:01 -04:00
|
|
|
Tcl_Obj *ret;
|
2004-10-11 00:51:21 -04:00
|
|
|
volatile VALUE strval;
|
|
|
|
|
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
|
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
return rb_tainted_str_new2("");
|
|
|
|
} else {
|
|
|
|
/* Tcl_Preserve(ptr->ip); */
|
|
|
|
rbtk_preserve_ip(ptr);
|
2006-08-31 07:56:42 -04:00
|
|
|
ret = Tcl_GetVar2Ex(ptr->ip, RSTRING_PTR(varname),
|
|
|
|
NIL_P(index) ? NULL : RSTRING_PTR(index),
|
2005-08-01 21:25:01 -04:00
|
|
|
FIX2INT(flag));
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ret == (Tcl_Obj*)NULL) {
|
|
|
|
volatile VALUE exc;
|
2006-04-18 04:43:10 -04:00
|
|
|
/* exc = rb_exc_new2(rb_eRuntimeError,
|
|
|
|
Tcl_GetStringResult(ptr->ip)); */
|
|
|
|
exc = create_ip_exc(interp, rb_eRuntimeError,
|
|
|
|
Tcl_GetStringResult(ptr->ip));
|
2004-10-11 00:51:21 -04:00
|
|
|
/* Tcl_Release(ptr->ip); */
|
|
|
|
rbtk_release_ip(ptr);
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
2005-03-02 02:06:52 -05:00
|
|
|
return exc;
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
2004-07-14 21:18:57 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_IncrRefCount(ret);
|
2005-08-04 11:26:05 -04:00
|
|
|
strval = get_str_from_obj(ret);
|
|
|
|
OBJ_TAINT(strval);
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(ret);
|
|
|
|
|
|
|
|
/* Tcl_Release(ptr->ip); */
|
|
|
|
rbtk_release_ip(ptr);
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
return(strval);
|
2003-11-07 16:39:36 -05:00
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
{
|
2004-10-11 00:51:21 -04:00
|
|
|
char *ret;
|
2005-08-04 05:41:57 -04:00
|
|
|
volatile VALUE strval;
|
2004-10-11 00:51:21 -04:00
|
|
|
|
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return rb_tainted_str_new2("");
|
|
|
|
} else {
|
|
|
|
/* Tcl_Preserve(ptr->ip); */
|
|
|
|
rbtk_preserve_ip(ptr);
|
2006-08-31 07:56:42 -04:00
|
|
|
ret = Tcl_GetVar2(ptr->ip, RSTRING_PTR(varname),
|
|
|
|
NIL_P(index) ? NULL : RSTRING_PTR(index),
|
2005-08-01 21:25:01 -04:00
|
|
|
FIX2INT(flag));
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ret == (char*)NULL) {
|
|
|
|
volatile VALUE exc;
|
|
|
|
exc = rb_exc_new2(rb_eRuntimeError, Tcl_GetStringResult(ptr->ip));
|
|
|
|
/* Tcl_Release(ptr->ip); */
|
|
|
|
rbtk_release_ip(ptr);
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
2005-03-02 02:06:52 -05:00
|
|
|
return exc;
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
strval = rb_tainted_str_new2(ret);
|
|
|
|
/* Tcl_Release(ptr->ip); */
|
|
|
|
rbtk_release_ip(ptr);
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
return(strval);
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
#endif
|
2003-11-07 16:39:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2005-03-02 02:06:52 -05:00
|
|
|
ip_get_variable2(self, varname, index, flag)
|
2003-11-07 16:39:36 -05:00
|
|
|
VALUE self;
|
2005-03-02 02:06:52 -05:00
|
|
|
VALUE varname;
|
|
|
|
VALUE index;
|
|
|
|
VALUE flag;
|
2003-11-07 16:39:36 -05:00
|
|
|
{
|
2005-08-04 23:51:50 -04:00
|
|
|
VALUE argv[3];
|
2005-03-02 02:06:52 -05:00
|
|
|
VALUE retval;
|
|
|
|
|
|
|
|
StringValue(varname);
|
2005-08-01 21:25:01 -04:00
|
|
|
if (!NIL_P(index)) StringValue(index);
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
argv[0] = varname;
|
2005-08-01 21:25:01 -04:00
|
|
|
argv[1] = index;
|
|
|
|
argv[2] = flag;
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2005-08-01 21:25:01 -04:00
|
|
|
retval = tk_funcall(ip_get_variable2_core, 3, argv, self);
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
if (NIL_P(retval)) {
|
|
|
|
return rb_tainted_str_new2("");
|
|
|
|
} else {
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2005-08-01 21:25:01 -04:00
|
|
|
ip_get_variable(self, varname, flag)
|
2003-11-07 16:39:36 -05:00
|
|
|
VALUE self;
|
2005-03-02 02:06:52 -05:00
|
|
|
VALUE varname;
|
|
|
|
VALUE flag;
|
2003-11-07 16:39:36 -05:00
|
|
|
{
|
2005-08-01 21:25:01 -04:00
|
|
|
return ip_get_variable2(self, varname, Qnil, flag);
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ip_set_variable2_core(interp, argc, argv)
|
|
|
|
VALUE interp;
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(interp);
|
|
|
|
int thr_crit_bup;
|
|
|
|
volatile VALUE varname, index, value, flag;
|
2003-11-07 16:39:36 -05:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
varname = argv[0];
|
|
|
|
index = argv[1];
|
|
|
|
value = argv[2];
|
|
|
|
flag = argv[3];
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/*
|
2004-05-01 12:09:54 -04:00
|
|
|
StringValue(varname);
|
2005-08-01 21:25:01 -04:00
|
|
|
if (!NIL_P(index)) StringValue(index);
|
2004-05-01 12:09:54 -04:00
|
|
|
StringValue(value);
|
2005-03-02 02:06:52 -05:00
|
|
|
*/
|
2003-11-07 16:39:36 -05:00
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-05-01 12:09:54 -04:00
|
|
|
{
|
2005-08-01 21:25:01 -04:00
|
|
|
Tcl_Obj *valobj, *ret;
|
2004-10-11 00:51:21 -04:00
|
|
|
volatile VALUE strval;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-08-04 11:26:05 -04:00
|
|
|
valobj = get_obj_from_str(value);
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_IncrRefCount(valobj);
|
|
|
|
|
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(valobj);
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
return rb_tainted_str_new2("");
|
|
|
|
} else {
|
|
|
|
/* Tcl_Preserve(ptr->ip); */
|
|
|
|
rbtk_preserve_ip(ptr);
|
2006-08-31 07:56:42 -04:00
|
|
|
ret = Tcl_SetVar2Ex(ptr->ip, RSTRING_PTR(varname),
|
|
|
|
NIL_P(index) ? NULL : RSTRING_PTR(index),
|
2005-08-01 21:25:01 -04:00
|
|
|
valobj, FIX2INT(flag));
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Tcl_DecrRefCount(valobj);
|
|
|
|
|
|
|
|
if (ret == (Tcl_Obj*)NULL) {
|
|
|
|
volatile VALUE exc;
|
2006-04-18 04:43:10 -04:00
|
|
|
/* exc = rb_exc_new2(rb_eRuntimeError,
|
|
|
|
Tcl_GetStringResult(ptr->ip)); */
|
|
|
|
exc = create_ip_exc(interp, rb_eRuntimeError,
|
|
|
|
Tcl_GetStringResult(ptr->ip));
|
2004-10-11 00:51:21 -04:00
|
|
|
/* Tcl_Release(ptr->ip); */
|
|
|
|
rbtk_release_ip(ptr);
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
2005-03-02 02:06:52 -05:00
|
|
|
return exc;
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_IncrRefCount(ret);
|
2005-08-04 11:26:05 -04:00
|
|
|
strval = get_str_from_obj(ret);
|
|
|
|
OBJ_TAINT(strval);
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(ret);
|
2005-08-04 11:26:05 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
/* Tcl_Release(ptr->ip); */
|
|
|
|
rbtk_release_ip(ptr);
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
return(strval);
|
2003-11-07 16:39:36 -05:00
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
|
|
|
{
|
2004-10-11 00:51:21 -04:00
|
|
|
CONST char *ret;
|
2005-08-04 05:41:57 -04:00
|
|
|
volatile VALUE strval;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return rb_tainted_str_new2("");
|
|
|
|
} else {
|
|
|
|
/* Tcl_Preserve(ptr->ip); */
|
|
|
|
rbtk_preserve_ip(ptr);
|
2006-08-31 07:56:42 -04:00
|
|
|
ret = Tcl_SetVar2(ptr->ip, RSTRING_PTR(varname),
|
|
|
|
NIL_P(index) ? NULL : RSTRING_PTR(index),
|
|
|
|
RSTRING_PTR(value), FIX2INT(flag));
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
if (ret == (char*)NULL) {
|
2005-03-02 02:06:52 -05:00
|
|
|
return rb_exc_new2(rb_eRuntimeError, ptr->ip->result);
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
strval = rb_tainted_str_new2(ret);
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
/* Tcl_Release(ptr->ip); */
|
|
|
|
rbtk_release_ip(ptr);
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
2004-09-11 13:45:53 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
return(strval);
|
2003-11-07 16:39:36 -05:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2005-03-02 02:06:52 -05:00
|
|
|
ip_set_variable2(self, varname, index, value, flag)
|
2003-11-07 16:39:36 -05:00
|
|
|
VALUE self;
|
2005-03-02 02:06:52 -05:00
|
|
|
VALUE varname;
|
|
|
|
VALUE index;
|
|
|
|
VALUE value;
|
|
|
|
VALUE flag;
|
2003-11-07 16:39:36 -05:00
|
|
|
{
|
2005-08-04 23:51:50 -04:00
|
|
|
VALUE argv[4];
|
2005-03-02 02:06:52 -05:00
|
|
|
VALUE retval;
|
|
|
|
|
|
|
|
StringValue(varname);
|
2005-08-01 21:25:01 -04:00
|
|
|
if (!NIL_P(index)) StringValue(index);
|
|
|
|
StringValue(value);
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
argv[0] = varname;
|
2005-08-01 21:25:01 -04:00
|
|
|
argv[1] = index;
|
|
|
|
argv[2] = value;
|
|
|
|
argv[3] = flag;
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2005-08-01 21:25:01 -04:00
|
|
|
retval = tk_funcall(ip_set_variable2_core, 4, argv, self);
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
if (NIL_P(retval)) {
|
|
|
|
return rb_tainted_str_new2("");
|
|
|
|
} else {
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2005-08-01 21:25:01 -04:00
|
|
|
ip_set_variable(self, varname, value, flag)
|
1999-08-13 01:37:52 -04:00
|
|
|
VALUE self;
|
2005-03-02 02:06:52 -05:00
|
|
|
VALUE varname;
|
2005-08-01 21:25:01 -04:00
|
|
|
VALUE value;
|
2005-03-02 02:06:52 -05:00
|
|
|
VALUE flag;
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
2005-08-01 21:25:01 -04:00
|
|
|
return ip_set_variable2(self, varname, Qnil, value, flag);
|
2005-03-02 02:06:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ip_unset_variable2_core(interp, argc, argv)
|
|
|
|
VALUE interp;
|
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
{
|
|
|
|
struct tcltkip *ptr = get_ip(interp);
|
|
|
|
volatile VALUE varname, index, flag;
|
1999-08-13 01:37:52 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
varname = argv[0];
|
|
|
|
index = argv[1];
|
|
|
|
flag = argv[2];
|
1999-08-13 01:37:52 -04:00
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
/*
|
2004-05-01 12:09:54 -04:00
|
|
|
StringValue(varname);
|
2005-08-01 21:25:01 -04:00
|
|
|
if (!NIL_P(index)) StringValue(index);
|
2005-03-02 02:06:52 -05:00
|
|
|
*/
|
1999-08-13 01:37:52 -04:00
|
|
|
|
2004-09-11 13:45:53 -04:00
|
|
|
/* ip is deleted? */
|
2005-08-01 00:57:28 -04:00
|
|
|
if (deleted_ip(ptr)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
return Qtrue;
|
2004-09-11 13:45:53 -04:00
|
|
|
}
|
|
|
|
|
2006-08-31 07:56:42 -04:00
|
|
|
ptr->return_value = Tcl_UnsetVar2(ptr->ip, RSTRING_PTR(varname),
|
|
|
|
NIL_P(index) ? NULL : RSTRING_PTR(index),
|
2005-08-01 21:25:01 -04:00
|
|
|
FIX2INT(flag));
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (ptr->return_value == TCL_ERROR) {
|
2004-10-11 00:51:21 -04:00
|
|
|
if (FIX2INT(flag) & TCL_LEAVE_ERR_MSG) {
|
2006-04-18 04:43:10 -04:00
|
|
|
/* return rb_exc_new2(rb_eRuntimeError,
|
|
|
|
Tcl_GetStringResult(ptr->ip)); */
|
|
|
|
return create_ip_exc(interp, rb_eRuntimeError,
|
|
|
|
Tcl_GetStringResult(ptr->ip));
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
return Qfalse;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
return Qtrue;
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
static VALUE
|
|
|
|
ip_unset_variable2(self, varname, index, flag)
|
|
|
|
VALUE self;
|
|
|
|
VALUE varname;
|
|
|
|
VALUE index;
|
|
|
|
VALUE flag;
|
|
|
|
{
|
2005-08-04 23:51:50 -04:00
|
|
|
VALUE argv[3];
|
2005-03-02 02:06:52 -05:00
|
|
|
VALUE retval;
|
|
|
|
|
|
|
|
StringValue(varname);
|
2005-08-01 21:25:01 -04:00
|
|
|
if (!NIL_P(index)) StringValue(index);
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
argv[0] = varname;
|
2005-08-01 21:25:01 -04:00
|
|
|
argv[1] = index;
|
|
|
|
argv[2] = flag;
|
2005-03-02 02:06:52 -05:00
|
|
|
|
2005-08-01 21:25:01 -04:00
|
|
|
retval = tk_funcall(ip_unset_variable2_core, 3, argv, self);
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
if (NIL_P(retval)) {
|
|
|
|
return rb_tainted_str_new2("");
|
|
|
|
} else {
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-08-01 21:25:01 -04:00
|
|
|
static VALUE
|
|
|
|
ip_unset_variable(self, varname, flag)
|
|
|
|
VALUE self;
|
|
|
|
VALUE varname;
|
|
|
|
VALUE flag;
|
|
|
|
{
|
|
|
|
return ip_unset_variable2(self, varname, Qnil, flag);
|
|
|
|
}
|
|
|
|
|
1999-01-19 23:59:39 -05:00
|
|
|
static VALUE
|
2004-05-01 12:09:54 -04:00
|
|
|
ip_get_global_var(self, varname)
|
1999-08-13 01:37:52 -04:00
|
|
|
VALUE self;
|
2004-05-01 12:09:54 -04:00
|
|
|
VALUE varname;
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
return ip_get_variable(self, varname,
|
2004-10-11 00:51:21 -04:00
|
|
|
INT2FIX(TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
static VALUE
|
|
|
|
ip_get_global_var2(self, varname, index)
|
|
|
|
VALUE self;
|
|
|
|
VALUE varname;
|
|
|
|
VALUE index;
|
|
|
|
{
|
|
|
|
return ip_get_variable2(self, varname, index,
|
2004-10-11 00:51:21 -04:00
|
|
|
INT2FIX(TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
static VALUE
|
|
|
|
ip_set_global_var(self, varname, value)
|
|
|
|
VALUE self;
|
|
|
|
VALUE varname;
|
|
|
|
VALUE value;
|
|
|
|
{
|
|
|
|
return ip_set_variable(self, varname, value,
|
2004-10-11 00:51:21 -04:00
|
|
|
INT2FIX(TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
static VALUE
|
|
|
|
ip_set_global_var2(self, varname, index, value)
|
|
|
|
VALUE self;
|
|
|
|
VALUE varname;
|
|
|
|
VALUE index;
|
|
|
|
VALUE value;
|
|
|
|
{
|
|
|
|
return ip_set_variable2(self, varname, index, value,
|
2004-10-11 00:51:21 -04:00
|
|
|
INT2FIX(TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
static VALUE
|
|
|
|
ip_unset_global_var(self, varname)
|
|
|
|
VALUE self;
|
|
|
|
VALUE varname;
|
|
|
|
{
|
|
|
|
return ip_unset_variable(self, varname,
|
2004-10-11 00:51:21 -04:00
|
|
|
INT2FIX(TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
|
1999-01-19 23:59:39 -05:00
|
|
|
}
|
|
|
|
|
2003-08-29 04:34:14 -04:00
|
|
|
static VALUE
|
2004-05-01 12:09:54 -04:00
|
|
|
ip_unset_global_var2(self, varname, index)
|
|
|
|
VALUE self;
|
|
|
|
VALUE varname;
|
|
|
|
VALUE index;
|
2003-08-29 04:34:14 -04:00
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
return ip_unset_variable2(self, varname, index,
|
2004-10-11 00:51:21 -04:00
|
|
|
INT2FIX(TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG));
|
2003-08-29 04:34:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* treat Tcl_List */
|
1999-01-19 23:59:39 -05:00
|
|
|
static VALUE
|
2004-05-01 12:09:54 -04:00
|
|
|
lib_split_tklist_core(ip_obj, list_str)
|
|
|
|
VALUE ip_obj;
|
|
|
|
VALUE list_str;
|
1999-01-19 23:59:39 -05:00
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
Tcl_Interp *interp;
|
|
|
|
volatile VALUE ary, elem;
|
|
|
|
int idx;
|
|
|
|
int taint_flag = OBJ_TAINTED(list_str);
|
|
|
|
int result;
|
|
|
|
VALUE old_gc;
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
tcl_stubs_check();
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (NIL_P(ip_obj)) {
|
2004-10-11 00:51:21 -04:00
|
|
|
interp = (Tcl_Interp *)NULL;
|
2005-03-02 02:06:52 -05:00
|
|
|
} else if (get_ip(ip_obj) == (struct tcltkip *)NULL) {
|
|
|
|
interp = (Tcl_Interp *)NULL;
|
2004-05-01 12:09:54 -04:00
|
|
|
} else {
|
2004-10-11 00:51:21 -04:00
|
|
|
interp = get_ip(ip_obj)->ip;
|
2004-05-01 12:09:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
StringValue(list_str);
|
|
|
|
|
|
|
|
{
|
1999-01-19 23:59:39 -05:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2004-10-11 00:51:21 -04:00
|
|
|
/* object style interface */
|
|
|
|
Tcl_Obj *listobj;
|
|
|
|
int objc;
|
|
|
|
Tcl_Obj **objv;
|
|
|
|
int thr_crit_bup;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-08-04 11:26:05 -04:00
|
|
|
listobj = get_obj_from_str(list_str);
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_IncrRefCount(listobj);
|
2003-10-14 11:25:45 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
result = Tcl_ListObjGetElements(interp, listobj, &objc, &objv);
|
2003-07-27 15:35:06 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
if (result == TCL_ERROR) {
|
|
|
|
Tcl_DecrRefCount(listobj);
|
|
|
|
if (interp == (Tcl_Interp*)NULL) {
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 01:47:45 -05:00
|
|
|
rb_raise(rb_eRuntimeError, "can't get elements from list");
|
2004-10-11 00:51:21 -04:00
|
|
|
} else {
|
|
|
|
rb_raise(rb_eRuntimeError, "%s", Tcl_GetStringResult(interp));
|
|
|
|
}
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
for(idx = 0; idx < objc; idx++) {
|
|
|
|
Tcl_IncrRefCount(objv[idx]);
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
ary = rb_ary_new2(objc);
|
|
|
|
if (taint_flag) OBJ_TAINT(ary);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
old_gc = rb_gc_disable();
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
for(idx = 0; idx < objc; idx++) {
|
2005-08-04 11:26:05 -04:00
|
|
|
elem = get_str_from_obj(objv[idx]);
|
2004-10-11 00:51:21 -04:00
|
|
|
if (taint_flag) OBJ_TAINT(elem);
|
2006-09-02 10:42:08 -04:00
|
|
|
rb_ary_push(ary, elem);
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
if (old_gc == Qfalse) rb_gc_enable();
|
1999-08-13 01:37:52 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_thread_critical = thr_crit_bup;
|
1999-08-13 01:37:52 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
for(idx = 0; idx < objc; idx++) {
|
|
|
|
Tcl_DecrRefCount(objv[idx]);
|
|
|
|
}
|
1999-01-19 23:59:39 -05:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
Tcl_DecrRefCount(listobj);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2004-10-11 00:51:21 -04:00
|
|
|
/* string style interface */
|
|
|
|
int argc;
|
|
|
|
char **argv;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2006-08-31 07:56:42 -04:00
|
|
|
if (Tcl_SplitList(interp, RSTRING_PTR(list_str),
|
2004-10-11 00:51:21 -04:00
|
|
|
&argc, &argv) == TCL_ERROR) {
|
|
|
|
if (interp == (Tcl_Interp*)NULL) {
|
* array.c: replace rb_protect_inspect() and rb_inspecting_p() by
rb_exec_recursive() in eval.c.
* eval.c (rb_exec_recursive): new function.
* array.c (rb_ary_join): use rb_exec_recursive().
* array.c (rb_ary_inspect, rb_ary_hash): ditto.
* file.c (rb_file_join): ditto.
* hash.c (rb_hash_inspect, rb_hash_to_s, rb_hash_hash): ditto.
* io.c (rb_io_puts): ditto.
* object.c (rb_obj_inspect): ditto
* struct.c (rb_struct_inspect): ditto.
* lib/set.rb (SortedSet::setup): a hack to shut up warning.
[ruby-talk:132866]
* lib/time.rb (Time::strptime): add new function. inspired by
[ruby-talk:132815].
* lib/parsedate.rb (ParseDate::strptime): ditto.
* regparse.c: move st_*_strend() functions from st.c. fixed some
potential memory leaks.
* exception error messages updated. [ruby-core:04497]
* ext/socket/socket.c (Init_socket): add bunch of Socket
constants. Patch from Sam Roberts <sroberts@uniserve.com>.
[ruby-core:04409]
* array.c (rb_ary_s_create): no need for negative argc check.
[ruby-core:04463]
* array.c (rb_ary_unshift_m): ditto.
* lib/xmlrpc/parser.rb (XMLRPC::FaultException): make it subclass
of StandardError class, not Exception class. [ruby-core:04429]
* parse.y (fcall_gen): lvar(arg) will be evaluated as
lvar.call(arg) when lvar is a defined local variable. [new]
* object.c (rb_class_initialize): call inherited method before
calling initializing block.
* eval.c (rb_thread_start_1): initialize newly pushed frame.
* lib/open3.rb (Open3::popen3): $? should not be EXIT_FAILURE.
fixed: [ruby-core:04444]
* eval.c (is_defined): NODE_IASGN is an assignment.
* ext/readline/readline.c (Readline.readline): use rl_outstream
and rl_instream. [ruby-dev:25699]
* ext/etc/etc.c (Init_etc): sGroup needs HAVE_ST_GR_PASSWD check
[ruby-dev:25675]
* misc/ruby-mode.el: [ruby-core:04415]
* lib/rdoc/generators/html_generator.rb: [ruby-core:04412]
* lib/rdoc/generators/ri_generator.rb: ditto.
* struct.c (make_struct): fixed: [ruby-core:04402]
* ext/curses/curses.c (window_color_set): [ruby-core:04393]
* ext/socket/socket.c (Init_socket): SO_REUSEPORT added.
[ruby-talk:130092]
* object.c: [ruby-doc:818]
* parse.y (open_args): fix too verbose warnings for the space
before argument parentheses. [ruby-dev:25492]
* parse.y (parser_yylex): ditto.
* parse.y (parser_yylex): the first expression in the parentheses
should not be a command. [ruby-dev:25492]
* lib/irb/context.rb (IRB::Context::initialize): [ruby-core:04330]
* object.c (Init_Object): remove Object#type. [ruby-core:04335]
* st.c (st_foreach): report success/failure by return value.
[ruby-Bugs-1396]
* parse.y: forgot to initialize parser struct. [ruby-dev:25492]
* parse.y (parser_yylex): no tLABEL on EXPR_BEG.
[ruby-talk:127711]
* document updates - [ruby-core:04296], [ruby-core:04301],
[ruby-core:04302], [ruby-core:04307]
* dir.c (rb_push_glob): should work for NUL delimited patterns.
* dir.c (rb_glob2): should aware of offset in the pattern.
* string.c (rb_str_new4): should propagate taintedness.
* env.h: rename member names in struct FRAME; last_func -> callee,
orig_func -> this_func, last_class -> this_class.
* struct.c (rb_struct_set): use original method name, not callee
name, to retrieve member slot. [ruby-core:04268]
* time.c (time_strftime): protect from format modification from GC
finalizers.
* object.c (Init_Object): remove rb_obj_id_obsolete()
* eval.c (rb_mod_define_method): incomplete subclass check.
[ruby-dev:25464]
* gc.c (rb_data_object_alloc): klass may be NULL.
[ruby-list:40498]
* bignum.c (rb_big_rand): should return positive random number.
[ruby-dev:25401]
* bignum.c (rb_big_rand): do not use rb_big_modulo to generate
random bignums. [ruby-dev:25396]
* variable.c (rb_autoload): [ruby-dev:25373]
* eval.c (svalue_to_avalue): [ruby-dev:25366]
* string.c (rb_str_justify): [ruby-dev:25367]
* io.c (rb_f_select): [ruby-dev:25312]
* ext/socket/socket.c (sock_s_getservbyport): [ruby-talk:124072]
* struct.c (make_struct): [ruby-dev:25249]
* dir.c (dir_open_dir): new function. [ruby-dev:25242]
* io.c (rb_f_open): add type check for return value from to_open.
* lib/pstore.rb (PStore#transaction): Use the empty content when a
file is not found. [ruby-dev:24561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-03-04 01:47:45 -05:00
|
|
|
rb_raise(rb_eRuntimeError, "can't get elements from list");
|
2004-10-11 00:51:21 -04:00
|
|
|
} else {
|
|
|
|
rb_raise(rb_eRuntimeError, "%s", interp->result);
|
|
|
|
}
|
|
|
|
}
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
ary = rb_ary_new2(argc);
|
|
|
|
if (taint_flag) OBJ_TAINT(ary);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
old_gc = rb_gc_disable();
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
2004-10-11 00:51:21 -04:00
|
|
|
for(idx = 0; idx < argc; idx++) {
|
|
|
|
if (taint_flag) {
|
|
|
|
elem = rb_tainted_str_new2(argv[idx]);
|
|
|
|
} else {
|
|
|
|
elem = rb_str_new2(argv[idx]);
|
|
|
|
}
|
|
|
|
/* rb_ivar_set(elem, ID_at_enc, rb_str_new2("binary")); */
|
2006-09-02 10:42:08 -04:00
|
|
|
rb_ary_push(ary, elem);
|
2004-10-11 00:51:21 -04:00
|
|
|
}
|
|
|
|
if (old_gc == Qfalse) rb_gc_enable();
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
return ary;
|
|
|
|
}
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
static VALUE
|
|
|
|
lib_split_tklist(self, list_str)
|
|
|
|
VALUE self;
|
|
|
|
VALUE list_str;
|
|
|
|
{
|
|
|
|
return lib_split_tklist_core(Qnil, list_str);
|
|
|
|
}
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
static VALUE
|
|
|
|
ip_split_tklist(self, list_str)
|
|
|
|
VALUE self;
|
|
|
|
VALUE list_str;
|
|
|
|
{
|
|
|
|
return lib_split_tklist_core(self, list_str);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
}
|
|
|
|
|
1999-08-13 01:37:52 -04:00
|
|
|
static VALUE
|
2004-05-01 12:09:54 -04:00
|
|
|
lib_merge_tklist(argc, argv, obj)
|
1999-08-13 01:37:52 -04:00
|
|
|
int argc;
|
|
|
|
VALUE *argv;
|
|
|
|
VALUE obj;
|
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
int num, len;
|
|
|
|
int *flagPtr;
|
|
|
|
char *dst, *result;
|
|
|
|
volatile VALUE str;
|
|
|
|
int taint_flag = 0;
|
|
|
|
int thr_crit_bup;
|
|
|
|
VALUE old_gc;
|
|
|
|
|
|
|
|
if (argc == 0) return rb_str_new2("");
|
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
tcl_stubs_check();
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
|
|
|
old_gc = rb_gc_disable();
|
|
|
|
|
|
|
|
/* based on Tcl/Tk's Tcl_Merge() */
|
2004-09-10 07:22:31 -04:00
|
|
|
flagPtr = ALLOC_N(int, argc);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
/* pass 1 */
|
|
|
|
len = 1;
|
|
|
|
for(num = 0; num < argc; num++) {
|
2004-10-11 00:51:21 -04:00
|
|
|
if (OBJ_TAINTED(argv[num])) taint_flag = 1;
|
|
|
|
dst = StringValuePtr(argv[num]);
|
2004-05-01 12:09:54 -04:00
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2006-08-31 07:56:42 -04:00
|
|
|
len += Tcl_ScanCountedElement(dst, RSTRING_LEN(argv[num]),
|
2004-10-11 00:51:21 -04:00
|
|
|
&flagPtr[num]) + 1;
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2004-10-11 00:51:21 -04:00
|
|
|
len += Tcl_ScanElement(dst, &flagPtr[num]) + 1;
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
|
|
|
}
|
1999-08-13 01:37:52 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* pass 2 */
|
|
|
|
result = (char *)Tcl_Alloc(len);
|
|
|
|
dst = result;
|
|
|
|
for(num = 0; num < argc; num++) {
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2006-08-31 07:56:42 -04:00
|
|
|
len = Tcl_ConvertCountedElement(RSTRING_PTR(argv[num]),
|
|
|
|
RSTRING_LEN(argv[num]),
|
2004-10-11 00:51:21 -04:00
|
|
|
dst, flagPtr[num]);
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2006-08-31 07:56:42 -04:00
|
|
|
len = Tcl_ConvertElement(RSTRING_PTR(argv[num]), dst, flagPtr[num]);
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
|
|
|
dst += len;
|
|
|
|
*dst = ' ';
|
|
|
|
dst++;
|
2002-10-03 07:20:31 -04:00
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
if (dst == result) {
|
|
|
|
*dst = 0;
|
|
|
|
} else {
|
|
|
|
dst[-1] = 0;
|
1999-08-13 01:37:52 -04:00
|
|
|
}
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
free(flagPtr);
|
1999-08-13 01:37:52 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* create object */
|
|
|
|
str = rb_str_new(result, dst - result - 1);
|
|
|
|
if (taint_flag) OBJ_TAINT(str);
|
|
|
|
Tcl_Free(result);
|
1999-08-13 01:37:52 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
if (old_gc == Qfalse) rb_gc_enable();
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
return str;
|
1998-01-16 07:19:09 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2004-05-01 12:09:54 -04:00
|
|
|
lib_conv_listelement(self, src)
|
1999-08-13 01:37:52 -04:00
|
|
|
VALUE self;
|
2004-05-01 12:09:54 -04:00
|
|
|
VALUE src;
|
1998-01-16 07:19:09 -05:00
|
|
|
{
|
2004-05-01 12:09:54 -04:00
|
|
|
int len, scan_flag;
|
|
|
|
volatile VALUE dst;
|
|
|
|
int taint_flag = OBJ_TAINTED(src);
|
|
|
|
int thr_crit_bup;
|
1998-01-16 07:19:09 -05:00
|
|
|
|
2005-07-28 05:14:59 -04:00
|
|
|
tcl_stubs_check();
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
thr_crit_bup = rb_thread_critical;
|
|
|
|
rb_thread_critical = Qtrue;
|
1998-01-16 07:19:09 -05:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
StringValue(src);
|
|
|
|
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
2006-08-31 07:56:42 -04:00
|
|
|
len = Tcl_ScanCountedElement(RSTRING_PTR(src), RSTRING_LEN(src),
|
2004-10-11 00:51:21 -04:00
|
|
|
&scan_flag);
|
2004-05-01 12:09:54 -04:00
|
|
|
dst = rb_str_new(0, len + 1);
|
2006-08-31 07:56:42 -04:00
|
|
|
len = Tcl_ConvertCountedElement(RSTRING_PTR(src), RSTRING_LEN(src),
|
|
|
|
RSTRING_PTR(dst), scan_flag);
|
2004-05-01 12:09:54 -04:00
|
|
|
#else /* TCL_MAJOR_VERSION < 8 */
|
2006-08-31 07:56:42 -04:00
|
|
|
len = Tcl_ScanElement(RSTRING_PTR(src), &scan_flag);
|
2004-05-01 12:09:54 -04:00
|
|
|
dst = rb_str_new(0, len + 1);
|
2006-08-31 07:56:42 -04:00
|
|
|
len = Tcl_ConvertElement(RSTRING_PTR(src), RSTRING_PTR(dst), scan_flag);
|
2004-05-01 12:09:54 -04:00
|
|
|
#endif
|
|
|
|
|
2006-08-31 07:56:42 -04:00
|
|
|
rb_str_resize(dst, len);
|
2004-05-01 12:09:54 -04:00
|
|
|
if (taint_flag) OBJ_TAINT(dst);
|
|
|
|
|
|
|
|
rb_thread_critical = thr_crit_bup;
|
|
|
|
|
|
|
|
return dst;
|
1998-01-16 07:19:09 -05:00
|
|
|
}
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2004-12-22 23:17:03 -05:00
|
|
|
static VALUE
|
|
|
|
tcltklib_compile_info()
|
|
|
|
{
|
|
|
|
volatile VALUE ret;
|
|
|
|
int size;
|
|
|
|
char form[]
|
|
|
|
= "tcltklib %s :: Ruby%s (%s) %s pthread :: Tcl%s(%s)/Tk%s(%s) %s";
|
|
|
|
char *info;
|
|
|
|
|
|
|
|
size = strlen(form)
|
|
|
|
+ strlen(TCLTKLIB_RELEASE_DATE)
|
|
|
|
+ strlen(RUBY_VERSION)
|
|
|
|
+ strlen(RUBY_RELEASE_DATE)
|
|
|
|
+ strlen("without")
|
|
|
|
+ strlen(TCL_PATCH_LEVEL)
|
|
|
|
+ strlen("without stub")
|
|
|
|
+ strlen(TK_PATCH_LEVEL)
|
|
|
|
+ strlen("without stub")
|
|
|
|
+ strlen("unknown tcl_threads");
|
|
|
|
|
|
|
|
info = ALLOC_N(char, size);
|
|
|
|
|
|
|
|
sprintf(info, form,
|
|
|
|
TCLTKLIB_RELEASE_DATE,
|
|
|
|
RUBY_VERSION, RUBY_RELEASE_DATE,
|
|
|
|
#ifdef HAVE_NATIVETHREAD
|
|
|
|
"with",
|
|
|
|
#else
|
|
|
|
"without",
|
|
|
|
#endif
|
|
|
|
TCL_PATCH_LEVEL,
|
|
|
|
#ifdef USE_TCL_STUBS
|
|
|
|
"with stub",
|
|
|
|
#else
|
|
|
|
"without stub",
|
|
|
|
#endif
|
|
|
|
TK_PATCH_LEVEL,
|
|
|
|
#ifdef USE_TK_STUBS
|
|
|
|
"with stub",
|
|
|
|
#else
|
|
|
|
"without stub",
|
|
|
|
#endif
|
|
|
|
#ifdef WITH_TCL_ENABLE_THREAD
|
|
|
|
# if WITH_TCL_ENABLE_THREAD
|
|
|
|
"with tcl_threads"
|
|
|
|
# else
|
|
|
|
"without tcl_threads"
|
|
|
|
# endif
|
|
|
|
#else
|
|
|
|
"unknown tcl_threads"
|
|
|
|
#endif
|
|
|
|
);
|
|
|
|
|
|
|
|
ret = rb_obj_freeze(rb_str_new2(info));
|
|
|
|
|
|
|
|
free(info);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2006-07-03 06:08:11 -04:00
|
|
|
/*###############################################*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The following is based on tkMenu.[ch]
|
|
|
|
* of Tcl/Tk (>=8.0) source code.
|
|
|
|
*/
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
|
|
|
|
#define MASTER_MENU 0
|
|
|
|
#define TEAROFF_MENU 1
|
|
|
|
#define MENUBAR 2
|
|
|
|
|
|
|
|
struct dummy_TkMenuEntry {
|
|
|
|
int type;
|
|
|
|
struct dummy_TkMenu *menuPtr;
|
|
|
|
/* , and etc. */
|
|
|
|
};
|
|
|
|
|
|
|
|
struct dummy_TkMenu {
|
|
|
|
Tk_Window tkwin;
|
|
|
|
Display *display;
|
|
|
|
Tcl_Interp *interp;
|
|
|
|
Tcl_Command widgetCmd;
|
|
|
|
struct dummy_TkMenuEntry **entries;
|
|
|
|
int numEntries;
|
|
|
|
int active;
|
|
|
|
int menuType; /* MASTER_MENU, TEAROFF_MENU, or MENUBAR */
|
|
|
|
Tcl_Obj *menuTypePtr;
|
|
|
|
/* , and etc. */
|
|
|
|
};
|
|
|
|
|
|
|
|
struct dummy_TkMenuRef {
|
|
|
|
struct dummy_TkMenu *menuPtr;
|
|
|
|
char *dummy1;
|
|
|
|
char *dummy2;
|
|
|
|
char *dummy3;
|
|
|
|
};
|
|
|
|
|
|
|
|
EXTERN struct dummy_TkMenuRef *TkFindMenuReferences(Tcl_Interp*, char*);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ip_make_menu_embeddable(interp, menu_path)
|
|
|
|
VALUE interp;
|
|
|
|
VALUE menu_path;
|
|
|
|
{
|
|
|
|
#if TCL_MAJOR_VERSION >= 8
|
|
|
|
struct tcltkip *ptr = get_ip(interp);
|
|
|
|
struct dummy_TkMenuRef *menuRefPtr;
|
|
|
|
|
|
|
|
StringValue(menu_path);
|
|
|
|
|
2006-08-31 07:56:42 -04:00
|
|
|
menuRefPtr = TkFindMenuReferences(ptr->ip, RSTRING_PTR(menu_path));
|
2006-07-03 06:08:11 -04:00
|
|
|
if (menuRefPtr == (struct dummy_TkMenuRef *) NULL) {
|
|
|
|
rb_raise(rb_eArgError, "not a menu widget, or invalid widget path");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (menuRefPtr->menuPtr == (struct dummy_TkMenu *) NULL) {
|
|
|
|
rb_raise(rb_eRuntimeError,
|
|
|
|
"invalid menu widget (maybe already destroyed)");
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((menuRefPtr->menuPtr)->menuType != MENUBAR) {
|
|
|
|
rb_raise(rb_eRuntimeError,
|
|
|
|
"target menu widget must be a MENUBAR type");
|
|
|
|
}
|
|
|
|
|
|
|
|
(menuRefPtr->menuPtr)->menuType = TEAROFF_MENU;
|
|
|
|
#if 0 /* cause SEGV */
|
|
|
|
{
|
|
|
|
/* char *s = "tearoff"; */
|
|
|
|
char *s = "normal";
|
|
|
|
/* Tcl_SetStringObj((menuRefPtr->menuPtr)->menuTypePtr, s, strlen(s));*/
|
|
|
|
(menuRefPtr->menuPtr)->menuTypePtr = Tcl_NewStringObj(s, strlen(s));
|
|
|
|
/* (menuRefPtr->menuPtr)->menuType = TEAROFF_MENU; */
|
|
|
|
(menuRefPtr->menuPtr)->menuType = MASTER_MENU;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
TkEventuallyRecomputeMenu(menuRefPtr->menuPtr);
|
|
|
|
TkEventuallyRedrawMenu(menuRefPtr->menuPtr,
|
|
|
|
(struct dummy_TkMenuEntry *)NULL);
|
|
|
|
|
|
|
|
#else /* TCL_MAJOR_VERSION <= 7 */
|
|
|
|
rb_notimplement();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return interp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*###############################################*/
|
2005-08-04 05:41:57 -04:00
|
|
|
|
1998-01-16 07:19:09 -05:00
|
|
|
/*---- initialization ----*/
|
1999-08-13 01:37:52 -04:00
|
|
|
void
|
|
|
|
Init_tcltklib()
|
1998-01-16 07:19:09 -05:00
|
|
|
{
|
2005-07-28 05:14:59 -04:00
|
|
|
int ret;
|
2004-05-01 12:09:54 -04:00
|
|
|
|
1998-01-16 07:19:09 -05:00
|
|
|
VALUE lib = rb_define_module("TclTkLib");
|
1999-01-19 23:59:39 -05:00
|
|
|
VALUE ip = rb_define_class("TclTkIp", rb_cObject);
|
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
VALUE ev_flag = rb_define_module_under(lib, "EventFlag");
|
2004-05-01 12:09:54 -04:00
|
|
|
VALUE var_flag = rb_define_module_under(lib, "VarAccessFlag");
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------- */
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
2005-11-18 03:39:29 -05:00
|
|
|
tcltkip_class = ip;
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_global_variable(&eTkCallbackReturn);
|
|
|
|
rb_global_variable(&eTkCallbackBreak);
|
|
|
|
rb_global_variable(&eTkCallbackContinue);
|
|
|
|
|
|
|
|
rb_global_variable(&eventloop_thread);
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_global_variable(&eventloop_stack);
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_global_variable(&watchdog_thread);
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_global_variable(&rbtk_pending_exception);
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
2004-12-22 23:17:03 -05:00
|
|
|
rb_define_const(lib, "COMPILE_INFO", tcltklib_compile_info());
|
|
|
|
|
|
|
|
rb_define_const(lib, "RELEASE_DATE",
|
|
|
|
rb_obj_freeze(rb_str_new2(tcltklib_release_date)));
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_define_const(lib, "FINALIZE_PROC_NAME",
|
2004-10-11 00:51:21 -04:00
|
|
|
rb_str_new2(finalize_hook_name));
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
2003-06-19 12:14:43 -04:00
|
|
|
rb_define_const(ev_flag, "NONE", INT2FIX(0));
|
2002-06-04 04:03:43 -04:00
|
|
|
rb_define_const(ev_flag, "WINDOW", INT2FIX(TCL_WINDOW_EVENTS));
|
|
|
|
rb_define_const(ev_flag, "FILE", INT2FIX(TCL_FILE_EVENTS));
|
|
|
|
rb_define_const(ev_flag, "TIMER", INT2FIX(TCL_TIMER_EVENTS));
|
|
|
|
rb_define_const(ev_flag, "IDLE", INT2FIX(TCL_IDLE_EVENTS));
|
|
|
|
rb_define_const(ev_flag, "ALL", INT2FIX(TCL_ALL_EVENTS));
|
|
|
|
rb_define_const(ev_flag, "DONT_WAIT", INT2FIX(TCL_DONT_WAIT));
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
|
|
|
rb_define_const(var_flag, "NONE", INT2FIX(0));
|
|
|
|
rb_define_const(var_flag, "GLOBAL_ONLY", INT2FIX(TCL_GLOBAL_ONLY));
|
|
|
|
#ifdef TCL_NAMESPACE_ONLY
|
|
|
|
rb_define_const(var_flag, "NAMESPACE_ONLY", INT2FIX(TCL_NAMESPACE_ONLY));
|
|
|
|
#else /* probably Tcl7.6 */
|
|
|
|
rb_define_const(var_flag, "NAMESPACE_ONLY", INT2FIX(0));
|
|
|
|
#endif
|
|
|
|
rb_define_const(var_flag, "LEAVE_ERR_MSG", INT2FIX(TCL_LEAVE_ERR_MSG));
|
|
|
|
rb_define_const(var_flag, "APPEND_VALUE", INT2FIX(TCL_APPEND_VALUE));
|
|
|
|
rb_define_const(var_flag, "LIST_ELEMENT", INT2FIX(TCL_LIST_ELEMENT));
|
|
|
|
#ifdef TCL_PARSE_PART1
|
|
|
|
rb_define_const(var_flag, "PARSE_VARNAME", INT2FIX(TCL_PARSE_PART1));
|
|
|
|
#else /* probably Tcl7.6 */
|
|
|
|
rb_define_const(var_flag, "PARSE_VARNAME", INT2FIX(0));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
2005-04-22 03:57:26 -04:00
|
|
|
eTkCallbackReturn = rb_define_class("TkCallbackReturn", rb_eStandardError);
|
1999-01-19 23:59:39 -05:00
|
|
|
eTkCallbackBreak = rb_define_class("TkCallbackBreak", rb_eStandardError);
|
2003-06-19 12:14:43 -04:00
|
|
|
eTkCallbackContinue = rb_define_class("TkCallbackContinue",
|
|
|
|
rb_eStandardError);
|
1998-01-16 07:19:09 -05:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
|
|
|
eLocalJumpError = rb_const_get(rb_cObject, rb_intern("LocalJumpError"));
|
|
|
|
|
2005-08-09 02:16:29 -04:00
|
|
|
eTkLocalJumpError = rb_define_class("TkLocalJumpError", eLocalJumpError);
|
|
|
|
|
|
|
|
eTkCallbackRetry = rb_define_class("TkCallbackRetry", eTkLocalJumpError);
|
|
|
|
eTkCallbackRedo = rb_define_class("TkCallbackRedo", eTkLocalJumpError);
|
|
|
|
eTkCallbackThrow = rb_define_class("TkCallbackThrow", eTkLocalJumpError);
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
ID_at_enc = rb_intern("@encoding");
|
|
|
|
ID_at_interp = rb_intern("@interp");
|
|
|
|
|
|
|
|
ID_stop_p = rb_intern("stop?");
|
2005-03-02 02:06:52 -05:00
|
|
|
ID_alive_p = rb_intern("alive?");
|
2004-05-01 12:09:54 -04:00
|
|
|
ID_kill = rb_intern("kill");
|
|
|
|
ID_join = rb_intern("join");
|
2005-03-02 02:06:52 -05:00
|
|
|
ID_value = rb_intern("value");
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
ID_call = rb_intern("call");
|
|
|
|
ID_backtrace = rb_intern("backtrace");
|
|
|
|
ID_message = rb_intern("message");
|
|
|
|
|
|
|
|
ID_at_reason = rb_intern("@reason");
|
|
|
|
ID_return = rb_intern("return");
|
|
|
|
ID_break = rb_intern("break");
|
|
|
|
ID_next = rb_intern("next");
|
|
|
|
|
|
|
|
ID_to_s = rb_intern("to_s");
|
|
|
|
ID_inspect = rb_intern("inspect");
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
rb_define_module_function(lib, "mainloop", lib_mainloop, -1);
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_define_module_function(lib, "mainloop_thread?",
|
|
|
|
lib_evloop_thread_p, 0);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
rb_define_module_function(lib, "mainloop_watchdog",
|
2004-10-11 00:51:21 -04:00
|
|
|
lib_mainloop_watchdog, -1);
|
2005-03-02 02:06:52 -05:00
|
|
|
rb_define_module_function(lib, "do_thread_callback",
|
|
|
|
lib_thread_callback, -1);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
rb_define_module_function(lib, "do_one_event", lib_do_one_event, -1);
|
2003-08-29 04:34:14 -04:00
|
|
|
rb_define_module_function(lib, "mainloop_abort_on_exception",
|
|
|
|
lib_evloop_abort_on_exc, 0);
|
|
|
|
rb_define_module_function(lib, "mainloop_abort_on_exception=",
|
|
|
|
lib_evloop_abort_on_exc_set, 1);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
rb_define_module_function(lib, "set_eventloop_tick",set_eventloop_tick,1);
|
|
|
|
rb_define_module_function(lib, "get_eventloop_tick",get_eventloop_tick,0);
|
2003-06-19 12:14:43 -04:00
|
|
|
rb_define_module_function(lib, "set_no_event_wait", set_no_event_wait, 1);
|
|
|
|
rb_define_module_function(lib, "get_no_event_wait", get_no_event_wait, 0);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
rb_define_module_function(lib, "set_eventloop_weight",
|
2004-10-11 00:51:21 -04:00
|
|
|
set_eventloop_weight, 2);
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_define_module_function(lib, "set_max_block_time", set_max_block_time,1);
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
rb_define_module_function(lib, "get_eventloop_weight",
|
2004-10-11 00:51:21 -04:00
|
|
|
get_eventloop_weight, 0);
|
2003-08-29 04:34:14 -04:00
|
|
|
rb_define_module_function(lib, "num_of_mainwindows",
|
2004-10-11 00:51:21 -04:00
|
|
|
lib_num_of_mainwindows, 0);
|
1998-01-16 07:19:09 -05:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
|
|
|
rb_define_module_function(lib, "_split_tklist", lib_split_tklist, 1);
|
|
|
|
rb_define_module_function(lib, "_merge_tklist", lib_merge_tklist, -1);
|
|
|
|
rb_define_module_function(lib, "_conv_listelement",
|
2004-10-11 00:51:21 -04:00
|
|
|
lib_conv_listelement, 1);
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_define_module_function(lib, "_toUTF8", lib_toUTF8, -1);
|
|
|
|
rb_define_module_function(lib, "_fromUTF8", lib_fromUTF8, -1);
|
|
|
|
rb_define_module_function(lib, "_subst_UTF_backslash",
|
2004-10-11 00:51:21 -04:00
|
|
|
lib_UTF_backslash, 1);
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_define_module_function(lib, "_subst_Tcl_backslash",
|
2004-10-11 00:51:21 -04:00
|
|
|
lib_Tcl_backslash, 1);
|
2004-05-01 12:09:54 -04:00
|
|
|
|
2005-07-05 01:56:31 -04:00
|
|
|
rb_define_module_function(lib, "encoding_system",
|
|
|
|
lib_get_system_encoding, 0);
|
|
|
|
rb_define_module_function(lib, "encoding_system=",
|
|
|
|
lib_set_system_encoding, 1);
|
|
|
|
rb_define_module_function(lib, "encoding",
|
|
|
|
lib_get_system_encoding, 0);
|
|
|
|
rb_define_module_function(lib, "encoding=",
|
|
|
|
lib_set_system_encoding, 1);
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
* ext/curses/curses.c, ext/digest/digest.c, ext/dl/handle.c,
ext/dl/ptr.c, ext/dl/sym.c, ext/gdbm/gdbm.c, ext/iconv/iconv.c,
ext/stringio/stringio.c, ext/strscan/strscan.c,
ext/tcltklib/tcltklib.c, ext/win32ole/win32ole.c:
use rb_define_alloc_func().
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3193 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-12-20 06:23:40 -05:00
|
|
|
rb_define_alloc_func(ip, ip_alloc);
|
2003-07-23 12:07:35 -04:00
|
|
|
rb_define_method(ip, "initialize", ip_init, -1);
|
2003-07-25 12:43:03 -04:00
|
|
|
rb_define_method(ip, "create_slave", ip_create_slave, -1);
|
2005-11-18 03:39:29 -05:00
|
|
|
rb_define_method(ip, "slave_of?", ip_is_slave_of_p, 1);
|
2003-07-25 12:43:03 -04:00
|
|
|
rb_define_method(ip, "make_safe", ip_make_safe, 0);
|
|
|
|
rb_define_method(ip, "safe?", ip_is_safe_p, 0);
|
2004-09-11 13:45:53 -04:00
|
|
|
rb_define_method(ip, "allow_ruby_exit?", ip_allow_ruby_exit_p, 0);
|
|
|
|
rb_define_method(ip, "allow_ruby_exit=", ip_allow_ruby_exit_set, 1);
|
2003-07-27 15:35:06 -04:00
|
|
|
rb_define_method(ip, "delete", ip_delete, 0);
|
|
|
|
rb_define_method(ip, "deleted?", ip_is_deleted_p, 0);
|
2005-07-21 18:05:04 -04:00
|
|
|
rb_define_method(ip, "has_mainwindow?", ip_has_mainwindow_p, 0);
|
2005-01-30 23:14:50 -05:00
|
|
|
rb_define_method(ip, "invalid_namespace?", ip_has_invalid_namespace_p, 0);
|
1998-01-16 07:19:09 -05:00
|
|
|
rb_define_method(ip, "_eval", ip_eval, 1);
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_define_method(ip, "_toUTF8", ip_toUTF8, -1);
|
|
|
|
rb_define_method(ip, "_fromUTF8", ip_fromUTF8, -1);
|
2003-10-14 11:25:45 -04:00
|
|
|
rb_define_method(ip, "_thread_vwait", ip_thread_vwait, 1);
|
|
|
|
rb_define_method(ip, "_thread_tkwait", ip_thread_tkwait, 2);
|
1999-01-19 23:59:39 -05:00
|
|
|
rb_define_method(ip, "_invoke", ip_invoke, -1);
|
2005-11-06 23:47:08 -05:00
|
|
|
rb_define_method(ip, "_immediate_invoke", ip_invoke_immediate, -1);
|
1998-01-16 07:19:09 -05:00
|
|
|
rb_define_method(ip, "_return_value", ip_retval, 0);
|
2003-08-29 04:34:14 -04:00
|
|
|
|
2005-03-30 03:44:19 -05:00
|
|
|
rb_define_method(ip, "_create_console", ip_create_console, 0);
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
|
|
|
rb_define_method(ip, "_get_variable", ip_get_variable, 2);
|
|
|
|
rb_define_method(ip, "_get_variable2", ip_get_variable2, 3);
|
|
|
|
rb_define_method(ip, "_set_variable", ip_set_variable, 3);
|
|
|
|
rb_define_method(ip, "_set_variable2", ip_set_variable2, 4);
|
|
|
|
rb_define_method(ip, "_unset_variable", ip_unset_variable, 2);
|
|
|
|
rb_define_method(ip, "_unset_variable2", ip_unset_variable2, 3);
|
|
|
|
rb_define_method(ip, "_get_global_var", ip_get_global_var, 1);
|
|
|
|
rb_define_method(ip, "_get_global_var2", ip_get_global_var2, 2);
|
|
|
|
rb_define_method(ip, "_set_global_var", ip_set_global_var, 2);
|
|
|
|
rb_define_method(ip, "_set_global_var2", ip_set_global_var2, 3);
|
|
|
|
rb_define_method(ip, "_unset_global_var", ip_unset_global_var, 1);
|
|
|
|
rb_define_method(ip, "_unset_global_var2", ip_unset_global_var2, 2);
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
2006-07-03 06:08:11 -04:00
|
|
|
rb_define_method(ip, "_make_menu_embeddable", ip_make_menu_embeddable, 1);
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_define_method(ip, "_split_tklist", ip_split_tklist, 1);
|
|
|
|
rb_define_method(ip, "_merge_tklist", lib_merge_tklist, -1);
|
|
|
|
rb_define_method(ip, "_conv_listelement", lib_conv_listelement, 1);
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
2003-08-29 04:34:14 -04:00
|
|
|
rb_define_method(ip, "mainloop", ip_mainloop, -1);
|
|
|
|
rb_define_method(ip, "mainloop_watchdog", ip_mainloop_watchdog, -1);
|
|
|
|
rb_define_method(ip, "do_one_event", ip_do_one_event, -1);
|
2003-07-29 11:39:59 -04:00
|
|
|
rb_define_method(ip, "mainloop_abort_on_exception",
|
2004-10-11 00:51:21 -04:00
|
|
|
ip_evloop_abort_on_exc, 0);
|
2003-07-29 11:39:59 -04:00
|
|
|
rb_define_method(ip, "mainloop_abort_on_exception=",
|
2004-10-11 00:51:21 -04:00
|
|
|
ip_evloop_abort_on_exc_set, 1);
|
2003-08-29 04:34:14 -04:00
|
|
|
rb_define_method(ip, "set_eventloop_tick", ip_set_eventloop_tick, 1);
|
|
|
|
rb_define_method(ip, "get_eventloop_tick", ip_get_eventloop_tick, 0);
|
|
|
|
rb_define_method(ip, "set_no_event_wait", ip_set_no_event_wait, 1);
|
|
|
|
rb_define_method(ip, "get_no_event_wait", ip_get_no_event_wait, 0);
|
|
|
|
rb_define_method(ip, "set_eventloop_weight", ip_set_eventloop_weight, 2);
|
|
|
|
rb_define_method(ip, "get_eventloop_weight", ip_get_eventloop_weight, 0);
|
2004-05-01 12:09:54 -04:00
|
|
|
rb_define_method(ip, "set_max_block_time", set_max_block_time, 1);
|
2003-08-29 04:34:14 -04:00
|
|
|
rb_define_method(ip, "restart", ip_restart, 0);
|
1998-01-16 07:19:09 -05:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
2005-03-02 02:06:52 -05:00
|
|
|
eventloop_thread = Qnil;
|
|
|
|
|
|
|
|
#ifndef DEFAULT_EVENTLOOP_DEPTH
|
|
|
|
#define DEFAULT_EVENTLOOP_DEPTH 7
|
|
|
|
#endif
|
|
|
|
eventloop_stack = rb_ary_new2(DEFAULT_EVENTLOOP_DEPTH);
|
2005-03-06 10:03:02 -05:00
|
|
|
OBJ_TAINT(eventloop_stack);
|
2005-03-02 02:06:52 -05:00
|
|
|
|
|
|
|
watchdog_thread = Qnil;
|
|
|
|
|
|
|
|
rbtk_pending_exception = Qnil;
|
* tkfont.rb: Fix bugs on TkFont.init_widget_font for Tk8.x.
* tkafter.rb: Add self to 1st argument of interval- and loop-proc
TkAfter#current_interval returns an interval (sleep) time value
TkAfter#current_args returns an array of arguments
TkAfter#return_value returns a return value of last loop-proc
e.g.
TkAfter.new(
proc{|obj| 500 - obj.current_interval}, 10,
[proc{|obj| p obj.current_args}, 'proc', 1],
proc{|obj| p obj.current_args; ['return', 2]},
[proc{|obj|
p obj.return_value
p ['proc', obj.current_args[0].call(obj.return_value[1],
obj.current_args[1])]},
proc{|*args| args[0] + args[1]}, 1],
proc{p ['proc', 4]} ).start(100)
* tk*.rb: Allow to use Symbols for parameters.
Allow new notation of constructor (also allow old notation).
e.g.
TkFrame.new('classname'=>'User'){|base|
pack
f = TkFrame.new(base, :classname=>'ButtonFrame').pack
TkButton.new(
:parent => f,
:text => 'Quit',
:command => proc{exit}
).pack(
:fill => :x,
:pady => 2
)
}
* tkcanvas.rb: (TkcItem) Add 'coords' parameter to the canvas item
constructor (for new notation of constructor).
e.g.
c = TkCanvas.new.pack
l = TkcLine.new(c, :coords=>[[0,0], [100,100]])
* tcltklib.c: New 'mainloop' and 'mainloop_watchdog'.
The priority of their event-loop can be controlled.
They accept an optional argument.
If it false, they don't exit although the root widget is destroyed.
This function is sometimes useful, if it is used with 'restart'.
'mainloop' can't treat Thread#join/value in a callback routine.
(e.g. TkButton.new(:command=>proc{p Thread.new{button.invoke}.value}) )
'mainloop_watchdog' can treat them, but watchdog thread is always running
(so, a little heavier than 'mainloop').
If the purpose of using Thread#join/value is to do something under some
safe-level, please use Proc object.
(e.g. :command=>proc{$SAFE=1;proc{$SAFE=2;button.invoke}.call;p $SAFE})
* tk.rb: Support functions of new 'mainloop' and 'mainloop_watchdog'.
* tk.rb: (Tk.restart) Add 'app-name' paramater and 'use' parameter.
'app-name' specifies the name and the resource class of the
application. If 'app-name' is specified to 'xxx', the application
class on the resource database is set to 'Xxx' and the application
name is changed by the same rule of Tk.appname method. 'use'
specifies the main window for embedding the root widget instead of
generating a new window.
* tk.rb: Add new parameter 'widgetname' to the widget constructor to
support effective use of Resource Database. For example, the
resource 'Xxx*quit.text: QUIT' can set the text of the button
generated by the following code.
e.g.
Tk.restart('Xxx')
TkButton.new(nil, 'widgetname'=>'quit', 'command'=>proc{exit}).pack
Tk.mainloop
* tk.rb: TkOption::get always returns a tainted string.
Add TkOption::new_proc_class.
It generates a class to import procedures defined on the resource
database. For example, there is a following resource file.
----< resource-test >------------
*CMD.foo: {|*args| p [$SAFE, :foo, args]}
*CMD.XXX.bar: {|*args| p [$SAFE, :bar, args]}
*Button.command: ruby {p self; p $SAFE; TkOption::CMD::XXX.bar(1,2,3)}
---------------------------------
The following code is a sample of use of the resource file.
e.g.
require 'tk'
TkOption.readfile 'resource-test'
p TkOption.new_proc_class(:CMD, [:foo], 1)
p TkOption.new_proc_class(:XXX, [:bar], 2, false, TkOption::CMD)
TkButton.new(:text=>'test').pack
Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2515 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2002-06-04 03:03:33 -04:00
|
|
|
|
2004-05-01 12:09:54 -04:00
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
2005-08-04 05:41:57 -04:00
|
|
|
/* if ruby->nativethread-supprt and tcltklib->doen't,
|
|
|
|
the following will cause link-error. */
|
|
|
|
is_ruby_native_thread();
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
2007-08-18 04:44:44 -04:00
|
|
|
rb_set_end_proc(lib_mark_at_exit, 0);
|
2006-07-10 05:52:30 -04:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
2006-08-31 07:56:42 -04:00
|
|
|
ret = ruby_open_tcl_dll(rb_argv0 ? RSTRING_PTR(rb_argv0) : 0);
|
2005-07-28 05:14:59 -04:00
|
|
|
switch(ret) {
|
|
|
|
case TCLTK_STUBS_OK:
|
|
|
|
break;
|
|
|
|
case NO_TCL_DLL:
|
|
|
|
rb_raise(rb_eLoadError, "tcltklib: fail to open tcl_dll");
|
|
|
|
case NO_FindExecutable:
|
|
|
|
rb_raise(rb_eLoadError, "tcltklib: can't find Tcl_FindExecutable");
|
|
|
|
default:
|
|
|
|
rb_raise(rb_eLoadError, "tcltklib: unknown error(%d) on ruby_open_tcl_dll", ret);
|
|
|
|
}
|
2004-05-01 12:09:54 -04:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------- */
|
1998-01-16 07:19:09 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* eof */
|