aboutsummaryrefslogtreecommitdiffstats
path: root/ext/tk/tcltklib.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/tk/tcltklib.c')
-rw-r--r--ext/tk/tcltklib.c500
1 files changed, 345 insertions, 155 deletions
diff --git a/ext/tk/tcltklib.c b/ext/tk/tcltklib.c
index d1e5f9d0d0..8f55491d1b 100644
--- a/ext/tk/tcltklib.c
+++ b/ext/tk/tcltklib.c
@@ -4,7 +4,7 @@
* Oct. 24, 1997 Y. Matsumoto
*/
-#define TCLTKLIB_RELEASE_DATE "2005-07-22"
+#define TCLTKLIB_RELEASE_DATE "2005-07-28"
#include "ruby.h"
#include "rubysig.h"
@@ -22,17 +22,14 @@
#include <tcl.h>
#include <tk.h>
+#include "stubs.h"
+
#ifndef TCL_ALPHA_RELEASE
#define TCL_ALPHA_RELEASE 0
#define TCL_BETA_RELEASE 1
#define TCL_FINAL_RELEASE 2
#endif
-#ifdef __MACOS__
-# include <tkMac.h>
-# include <Quickdraw.h>
-#endif
-
#if TCL_MAJOR_VERSION >= 8
# ifndef CONST84
# if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION <= 4 /* Tcl8.0.x -- 8.4b1 */
@@ -81,6 +78,7 @@ static char *finalize_hook_name = "INTERP_FINALIZE_HOOK";
static void ip_finalize _((Tcl_Interp*));
+
/* for callback break & continue */
static VALUE eTkCallbackReturn;
static VALUE eTkCallbackBreak;
@@ -114,7 +112,6 @@ static VALUE ip_invoke _((int, VALUE*, VALUE));
static VALUE tk_funcall _((VALUE(), int, VALUE*, VALUE));
-
/* safe Tcl_Eval and Tcl_GlobalEval */
static int
tcl_eval(interp, cmd)
@@ -549,6 +546,128 @@ rbtk_release_ip(ptr)
}
+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;
+}
+
+
/* treat excetiopn on Tcl side */
static VALUE rbtk_pending_exception;
static int rbtk_eventloop_depth = 0;
@@ -645,7 +764,8 @@ call_original_exit(ptr, state)
char **argv;
argv = (char **)ALLOC_N(char *, 3);
argv[0] = "exit";
- argv[1] = Tcl_GetString(state_obj);
+ /* argv[1] = Tcl_GetString(state_obj); */
+ argv[1] = Tcl_GetStringFromObj(state_obj, (int*)NULL);
argv[2] = (char *)NULL;
ptr->return_value = (*(info->proc))(info->clientData, ptr->ip,
@@ -694,13 +814,13 @@ _timer_for_tcl(clientData)
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
- Tk_DeleteTimerHandler(timer_token);
+ Tcl_DeleteTimerHandler(timer_token);
run_timer_flag = 1;
if (timer_tick > 0) {
- timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
- (ClientData)0);
+ timer_token = Tcl_CreateTimerHandler(timer_tick, _timer_for_tcl,
+ (ClientData)0);
} else {
timer_token = (Tcl_TimerToken)NULL;
}
@@ -730,13 +850,13 @@ set_eventloop_tick(self, tick)
rb_thread_critical = Qtrue;
/* delete old timer callback */
- Tk_DeleteTimerHandler(timer_token);
+ Tcl_DeleteTimerHandler(timer_token);
timer_tick = req_timer_tick = ttick;
if (timer_tick > 0) {
/* start timer callback */
- timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
- (ClientData)0);
+ timer_token = Tcl_CreateTimerHandler(timer_tick, _timer_for_tcl,
+ (ClientData)0);
} else {
timer_token = (Tcl_TimerToken)NULL;
}
@@ -995,7 +1115,11 @@ static VALUE
lib_num_of_mainwindows(self)
VALUE self;
{
- return INT2FIX(Tk_GetNumMainWindows());
+ if (tk_stubs_init_p()) {
+ return INT2FIX(Tk_GetNumMainWindows());
+ } else {
+ return INT2FIX(0);
+ }
}
@@ -1060,13 +1184,13 @@ lib_eventloop_core(check_root, update_flag, check_var)
t.tv_sec = (time_t)0;
t.tv_usec = (time_t)(no_event_wait*1000.0);
- Tk_DeleteTimerHandler(timer_token);
+ Tcl_DeleteTimerHandler(timer_token);
run_timer_flag = 0;
if (timer_tick > 0) {
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
- timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
- (ClientData)0);
+ timer_token = Tcl_CreateTimerHandler(timer_tick, _timer_for_tcl,
+ (ClientData)0);
rb_thread_critical = thr_crit_bup;
} else {
timer_token = (Tcl_TimerToken)NULL;
@@ -1085,9 +1209,9 @@ lib_eventloop_core(check_root, update_flag, check_var)
if (timer_tick == 0 && update_flag == 0) {
timer_tick = NO_THREAD_INTERRUPT_TIME;
- timer_token = Tk_CreateTimerHandler(timer_tick,
- _timer_for_tcl,
- (ClientData)0);
+ timer_token = Tcl_CreateTimerHandler(timer_tick,
+ _timer_for_tcl,
+ (ClientData)0);
}
if (check_var != (int *)NULL) {
@@ -1166,7 +1290,7 @@ lib_eventloop_core(check_root, update_flag, check_var)
}
DUMP1("check Root Widget");
- if (check_root && Tk_GetNumMainWindows() == 0) {
+ if (check_root && tk_stubs_init_p() && Tk_GetNumMainWindows() == 0) {
run_timer_flag = 0;
if (rb_trap_pending) {
if (rb_prohibit_interrupt || check_var != (int*)NULL) {
@@ -1341,7 +1465,7 @@ lib_eventloop_core(check_root, update_flag, check_var)
}
DUMP1("check Root Widget");
- if (check_root && Tk_GetNumMainWindows() == 0) {
+ if (check_root && tk_stubs_init_p() && Tk_GetNumMainWindows() == 0) {
run_timer_flag = 0;
if (rb_trap_pending) {
if (rb_prohibit_interrupt || check_var != (int*)NULL) {
@@ -1457,7 +1581,7 @@ lib_eventloop_ensure(args)
}
if (NIL_P(eventloop_thread)) {
- Tk_DeleteTimerHandler(timer_token);
+ Tcl_DeleteTimerHandler(timer_token);
timer_token = (Tcl_TimerToken)NULL;
break;
@@ -1487,6 +1611,8 @@ lib_eventloop_launcher(check_root, update_flag, check_var)
int depth = rbtk_eventloop_depth;
struct evloop_params *args = ALLOC(struct evloop_params);
+ tcl_stubs_check();
+
eventloop_thread = rb_thread_current();
if (ruby_debug) {
@@ -1624,7 +1750,7 @@ lib_watchdog_core(check_rootwidget)
}
/* rb_thread_schedule(); */
}
- } while(!check || Tk_GetNumMainWindows() != 0);
+ } while(!check || !tk_stubs_init_p() || Tk_GetNumMainWindows() != 0);
return Qnil;
}
@@ -1795,6 +1921,8 @@ lib_do_one_event_core(argc, argv, self, is_ip)
rb_raise(rb_eRuntimeError, "eventloop is already running");
}
+ tcl_stubs_check();
+
if (rb_scan_args(argc, argv, "01", &vflags) == 0) {
flags = TCL_ALL_EVENTS | TCL_DONT_WAIT;
} else {
@@ -2776,6 +2904,7 @@ ip_InterpExitCommand(clientData, interp, argc, argv)
char *argv[];
#endif
{
+ DUMP1("start ip_InterpExitCommand");
if (interp != (Tcl_Interp*)NULL
&& !Tcl_InterpDeleted(interp)
#if TCL_NAMESPACE_DEBUG
@@ -2810,8 +2939,11 @@ ip_RubyExitCommand(clientData, interp, argc, argv)
int state;
char *cmd, *param;
+ DUMP1("start ip_RubyExitCommand");
+
#if TCL_MAJOR_VERSION >= 8
- cmd = Tcl_GetString(argv[0]);
+ /* cmd = Tcl_GetString(argv[0]); */
+ cmd = Tcl_GetStringFromObj(argv[0], (int*)NULL);
#else /* TCL_MAJOR_VERSION < 8 */
char *endptr;
@@ -2864,7 +2996,8 @@ ip_RubyExitCommand(clientData, interp, argc, argv)
if (Tcl_GetIntFromObj(interp, argv[1], &state) == TCL_ERROR) {
return TCL_ERROR;
}
- param = Tcl_GetString(argv[1]);
+ /* param = Tcl_GetString(argv[1]); */
+ param = Tcl_GetStringFromObj(argv[1], (int*)NULL);
#else /* TCL_MAJOR_VERSION < 8 */
state = (int)strtol(argv[1], &endptr, 0);
if (*endptr) {
@@ -3601,13 +3734,16 @@ ip_rbTkWaitCommand(clientData, interp, objc, objv)
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
- if (Tk_MainWindow(interp) == (Tk_Window)NULL) {
+ if (!tk_stubs_init_p() || Tk_MainWindow(interp) == (Tk_Window)NULL) {
window = NULL;
} else {
window = Tk_NameToWindow(interp, nameString, tkwin);
}
if (window == NULL) {
+ Tcl_AppendResult(interp, "tkwait: ",
+ "no main-window (not Tk application?)",
+ (char*)NULL);
rb_thread_critical = thr_crit_bup;
#if TCL_MAJOR_VERSION >= 8
Tcl_DecrRefCount(objv[2]);
@@ -3695,7 +3831,7 @@ ip_rbTkWaitCommand(clientData, interp, objc, objv)
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
- if (Tk_MainWindow(interp) == (Tk_Window)NULL) {
+ if (!tk_stubs_init_p() || Tk_MainWindow(interp) == (Tk_Window)NULL) {
window = NULL;
} else {
window = Tk_NameToWindow(interp, nameString, tkwin);
@@ -3706,6 +3842,9 @@ ip_rbTkWaitCommand(clientData, interp, objc, objv)
#endif
if (window == NULL) {
+ Tcl_AppendResult(interp, "tkwait: ",
+ "no main-window (not Tk application?)",
+ (char*)NULL);
rb_thread_critical = thr_crit_bup;
Tcl_Release(interp);
return TCL_ERROR;
@@ -4165,13 +4304,17 @@ ip_rb_threadTkWaitCommand(clientData, interp, objc, objv)
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
- if (Tk_MainWindow(interp) == (Tk_Window)NULL) {
+ if (!tk_stubs_init_p() || Tk_MainWindow(interp) == (Tk_Window)NULL) {
window = NULL;
} else {
window = Tk_NameToWindow(interp, nameString, tkwin);
}
if (window == NULL) {
+ Tcl_AppendResult(interp, "thread_tkwait: ",
+ "no main-window (not Tk application?)",
+ (char*)NULL);
+
rb_thread_critical = thr_crit_bup;
Tcl_Release(param);
@@ -4250,7 +4393,7 @@ ip_rb_threadTkWaitCommand(clientData, interp, objc, objv)
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
- if (Tk_MainWindow(interp) == (Tk_Window)NULL) {
+ if (!tk_stubs_init_p() || Tk_MainWindow(interp) == (Tk_Window)NULL) {
window = NULL;
} else {
window = Tk_NameToWindow(interp, nameString, tkwin);
@@ -4261,6 +4404,10 @@ ip_rb_threadTkWaitCommand(clientData, interp, objc, objv)
#endif
if (window == NULL) {
+ Tcl_AppendResult(interp, "thread_tkwait: ",
+ "no main-window (not Tk application?)",
+ (char*)NULL);
+
rb_thread_critical = thr_crit_bup;
Tcl_Release(param);
@@ -4388,7 +4535,8 @@ delete_slaves(ip)
if (elem == (Tcl_Obj*)NULL) continue;
/* get slave */
- slave_name = Tcl_GetString(elem);
+ /* slave_name = Tcl_GetString(elem); */
+ slave_name = Tcl_GetStringFromObj(elem, (int*)NULL);
DUMP2("delete slave:'%s'", slave_name);
Tcl_DecrRefCount(elem);
@@ -4418,53 +4566,78 @@ ip_finalize(ip)
{
Tcl_CmdInfo info;
int thr_crit_bup;
+ int rb_debug_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 is
+ disabled. If you know the reason, please fix it.
+ -- Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp) */
DUMP1("start ip_finalize");
if (ip == (Tcl_Interp*)NULL) {
- DUMP1("ip is NULL");
- return;
+ DUMP1("ip is NULL");
+ return;
}
#if TCL_NAMESPACE_DEBUG
if (ip_null_namespace(ip)) {
- DUMP2("ip(%lx) has null namespace", ip);
- return;
+ DUMP2("ip(%lx) has null namespace", ip);
+ return;
}
#endif
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
+ rb_debug_bup = ruby_debug;
+
Tcl_Preserve(ip);
/* delete slaves */
delete_slaves(ip);
/* delete root widget */
+#if 0
DUMP1("check `destroy'");
if (Tcl_GetCommandInfo(ip, "destroy", &info)) {
DUMP1("call `destroy'");
Tcl_GlobalEval(ip, "destroy .");
}
+#endif
+#if 1
+ DUMP1("destroy root widget");
+ if (tk_stubs_init_p() && Tk_MainWindow(ip) != (Tk_Window)NULL) {
+ DUMP1("call Tk_DestroyWindow");
+ ruby_debug = 0;
+ Tk_DestroyWindow(Tk_MainWindow(ip));
+ ruby_debug = rb_debug_bup;
+ }
+#endif
/* call finalize-hook-proc */
DUMP1("check `finalize-hook-proc'");
if (Tcl_GetCommandInfo(ip, finalize_hook_name, &info)) {
DUMP2("call finalize hook proc '%s'", finalize_hook_name);
+ ruby_debug = 0;
Tcl_GlobalEval(ip, finalize_hook_name);
+ ruby_debug = rb_debug_bup;
}
DUMP1("check `foreach' & `after'");
if ( Tcl_GetCommandInfo(ip, "foreach", &info)
&& Tcl_GetCommandInfo(ip, "after", &info) ) {
DUMP1("cancel after callbacks");
+ ruby_debug = 0;
Tcl_GlobalEval(ip, "foreach id [after info] {after cancel $id}");
+ ruby_debug = rb_debug_bup;
}
Tcl_Release(ip);
DUMP1("finish ip_finalize");
+ ruby_debug = rb_debug_bup;
rb_thread_critical = thr_crit_bup;
}
@@ -4629,7 +4802,8 @@ ip_rbNamespaceObjCmd(clientData, interp, objc, objv)
argv = (char **)Tcl_Alloc(sizeof(char *) * (objc + 1));
for(i = 0; i < objc; i++) {
- argv[i] = Tcl_GetString(objv[i]);
+ /* argv[i] = Tcl_GetString(objv[i]); */
+ argv[i] = Tcl_GetStringFromObj(objv[i], (int*)NULL);
}
argv[objc] = (char *)NULL;
@@ -4706,8 +4880,9 @@ ip_init(argc, argv, self)
struct tcltkip *ptr; /* tcltkip data struct */
VALUE argv0, opts;
int cnt;
+ int st;
int with_tk = 1;
- Tk_Window mainWin;
+ Tk_Window mainWin = (Tk_Window)NULL;
/* security check */
if (ruby_safe_level >= 4) {
@@ -4726,9 +4901,26 @@ ip_init(argc, argv, self)
/* from Tk_Main() */
DUMP1("Tcl_CreateInterp");
- ptr->ip = Tcl_CreateInterp();
+ ptr->ip = ruby_tcl_create_ip_and_stubs_init(&st);
if (ptr->ip == NULL) {
- rb_raise(rb_eRuntimeError, "fail to create a new Tk interpreter");
+ 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);
+ }
}
#if TCL_MAJOR_VERSION >= 8
@@ -4790,13 +4982,32 @@ ip_init(argc, argv, self)
/* from Tcl_AppInit() */
if (with_tk) {
DUMP1("Tk_Init");
- if (Tk_Init(ptr->ip) == TCL_ERROR) {
+ 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:
+#if TCL_MAJOR_VERSION >= 8
+ rb_raise(rb_eRuntimeError, "tcltklib: fail to Tk_Init(). %s",
+ Tcl_GetStringResult(ptr->ip));
+#else /* TCL_MAJOR_VERSION < 8 */
+ rb_raise(rb_eRuntimeError, "tcltklib: fail to Tk_Init(). %s",
+ ptr->ip->result);
+#endif
+ case FAIL_Tk_InitStubs:
#if TCL_MAJOR_VERSION >= 8
- rb_raise(rb_eRuntimeError, "%s", Tcl_GetStringResult(ptr->ip));
+ rb_raise(rb_eRuntimeError, "tcltklib: fail to Tk_InitStubs(). %s",
+ Tcl_GetStringResult(ptr->ip));
#else /* TCL_MAJOR_VERSION < 8 */
- rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
+ rb_raise(rb_eRuntimeError, "tcltklib: fail to Tk_InitStubs(). %s",
+ ptr->ip->result);
#endif
+ default:
+ rb_raise(rb_eRuntimeError, "tcltklib: unknown error(%d) on ruby_tk_stubs_init", st);
}
+
DUMP1("Tcl_StaticPackage(\"Tk\")");
#if TCL_MAJOR_VERSION >= 8
Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init, Tk_SafeInit);
@@ -4804,11 +5015,11 @@ ip_init(argc, argv, self)
Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init,
(Tcl_PackageInitProc *) NULL);
#endif
- }
- /* get main window */
- mainWin = Tk_MainWindow(ptr->ip);
- Tk_Preserve((ClientData)mainWin);
+ /* get main window */
+ mainWin = Tk_MainWindow(ptr->ip);
+ Tk_Preserve((ClientData)mainWin);
+ }
/* add ruby command to the interpreter */
#if TCL_MAJOR_VERSION >= 8
@@ -4865,7 +5076,9 @@ ip_init(argc, argv, self)
/* set finalizer */
Tcl_CallWhenDeleted(ptr->ip, ip_CallWhenDeleted, (ClientData)mainWin);
- Tk_Release((ClientData)mainWin);
+ if (mainWin != (Tk_Window)NULL) {
+ Tk_Release((ClientData)mainWin);
+ }
return self;
}
@@ -4892,7 +5105,7 @@ ip_create_slave_core(interp, argc, argv)
"deleted master cannot create a new slave");
}
- name = argv[0];
+ name = argv[0];
safemode = argv[1];
if (Tcl_IsSafe(master->ip) == 1) {
@@ -4907,6 +5120,20 @@ ip_create_slave_core(interp, argc, argv)
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
+#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
+
/* create slave-ip */
slave->ref_count = 0;
slave->allow_ruby_exit = 0;
@@ -4929,7 +5156,7 @@ ip_create_slave_core(interp, argc, argv)
= Tcl_GetCommandInfo(slave->ip, "exit", &(slave->orig_exit_info));
/* replace 'exit' command --> 'interp_exit' command */
- mainWin = Tk_MainWindow(slave->ip);
+ mainWin = (tk_stubs_init_p())? Tk_MainWindow(slave->ip): (Tk_Window)NULL;
#if TCL_MAJOR_VERSION >= 8
DUMP1("Tcl_CreateObjCommand(\"exit\") --> \"interp_exit\"");
Tcl_CreateObjCommand(slave->ip, "exit", ip_InterpExitObjCmd,
@@ -4974,7 +5201,7 @@ ip_create_slave(argc, argv, self)
"deleted master cannot create a new slave interpreter");
}
- /* safe-mode check */
+ /* argument check */
if (rb_scan_args(argc, argv, "11", &name, &safemode) == 1) {
safemode = Qfalse;
}
@@ -5020,11 +5247,14 @@ ip_create_console_core(interp, argc, argv)
{
struct tcltkip *ptr = get_ip(interp);
+ if (!tk_stubs_init_p()) {
+ tcltkip_init_tk(interp);
+ }
+
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 \
@@ -5101,7 +5331,7 @@ ip_make_safe_core(interp, argc, argv)
ptr->allow_ruby_exit = 0;
/* replace 'exit' command --> 'interp_exit' command */
- mainWin = Tk_MainWindow(ptr->ip);
+ mainWin = (tk_stubs_init_p())? Tk_MainWindow(ptr->ip): (Tk_Window)NULL;
#if TCL_MAJOR_VERSION >= 8
DUMP1("Tcl_CreateObjCommand(\"exit\") --> \"interp_exit\"");
Tcl_CreateObjCommand(ptr->ip, "exit", ip_InterpExitObjCmd,
@@ -5195,7 +5425,7 @@ ip_allow_ruby_exit_set(self, val)
"insecure operation on a safe interpreter");
}
- mainWin = Tk_MainWindow(ptr->ip);
+ mainWin = (tk_stubs_init_p())? Tk_MainWindow(ptr->ip): (Tk_Window)NULL;
if (RTEST(val)) {
ptr->allow_ruby_exit = 1;
@@ -5301,7 +5531,7 @@ ip_has_mainwindow_p(self)
struct tcltkip *ptr = get_ip(self);
if (ptr == (struct tcltkip *)NULL || ptr->ip == (Tcl_Interp *)NULL
- || Tcl_InterpDeleted(ptr->ip)) {
+ || Tcl_InterpDeleted(ptr->ip) || !tk_stubs_init_p()) {
return Qnil;
} else if (Tk_MainWindow(ptr->ip) == (Tk_Window)NULL) {
return Qfalse;
@@ -5310,36 +5540,6 @@ ip_has_mainwindow_p(self)
}
}
-
-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;
-}
-
static VALUE
ip_get_result_string_obj(interp)
Tcl_Interp *interp;
@@ -5657,26 +5857,33 @@ ip_eval_real(self, cmd_str, cmd_len)
}
if (pending_exception_check1(thr_crit_bup, ptr)) {
+ rbtk_release_ip(ptr);
return rbtk_pending_exception;
}
if (ptr->return_value == TCL_ERROR) {
- volatile VALUE exc;
-
- exc = create_ip_exc(self, rb_eRuntimeError,
- "%s", Tcl_GetStringResult(ptr->ip));
-
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
-
- rb_thread_critical = thr_crit_bup;
- rb_exc_raise(exc);
+ 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("");
+ }
}
- DUMP2("(TCL_Eval result) %d", ptr->return_value);
/* pass back the result (as string) */
ret = ip_get_result_string_obj(ptr->ip);
- /* Tcl_Release(ptr->ip); */
rbtk_release_ip(ptr);
rb_thread_critical = thr_crit_bup;
return ret;
@@ -5702,6 +5909,7 @@ ip_eval_real(self, cmd_str, cmd_len)
}
if (pending_exception_check1(thr_crit_bup, ptr)) {
+ rbtk_release_ip(ptr);
return rbtk_pending_exception;
}
@@ -5710,15 +5918,13 @@ ip_eval_real(self, cmd_str, cmd_len)
exc = create_ip_exc(self, rb_eRuntimeError, "%s", ptr->ip->result);
- /* Tcl_Release(ptr->ip); */
rbtk_release_ip(ptr);
- rb_exc_raise(exc);
+ return exc;
}
DUMP2("(TCL_Eval result) %d", ptr->return_value);
/* pass back the result (as string) */
ret = ip_get_result_string_obj(ptr->ip);
- /* Tcl_Release(ptr->ip); */
rbtk_release_ip(ptr);
return ret;
#endif
@@ -5894,9 +6100,12 @@ lib_restart_core(interp, argc, argv)
volatile VALUE exc;
struct tcltkip *ptr = get_ip(interp);
int thr_crit_bup;
+ int st;
/* rb_secure(4); */ /* already checked */
+ /* tcl_stubs_check(); */ /* already checked */
+
/* ip is deleted? */
if (ptr == (struct tcltkip *)NULL || ptr->ip == (Tcl_Interp*)NULL
|| Tcl_InterpDeleted(ptr->ip)
@@ -5934,36 +6143,13 @@ lib_restart_core(interp, argc, argv)
DUMP2("(TCL_Eval result) %d", ptr->return_value);
Tcl_ResetResult(ptr->ip);
- /* execute Tk_Init of Tk_SafeInit */
-#if TCL_MAJOR_VERSION >= 8
- if (Tcl_IsSafe(ptr->ip)) {
- DUMP1("Tk_SafeInit");
- if (Tk_SafeInit(ptr->ip) == TCL_ERROR) {
- exc = rb_exc_new2(rb_eRuntimeError, Tcl_GetStringResult(ptr->ip));
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
- return exc;
- }
- } else {
- DUMP1("Tk_Init");
- if (Tk_Init(ptr->ip) == TCL_ERROR) {
- exc = rb_exc_new2(rb_eRuntimeError, Tcl_GetStringResult(ptr->ip));
- /* Tcl_Release(ptr->ip); */
- rbtk_release_ip(ptr);
- rb_thread_critical = thr_crit_bup;
- return exc;
- }
- }
-#else /* TCL_MAJOR_VERSION < 8 */
- DUMP1("Tk_Init");
- if (Tk_Init(ptr->ip) == TCL_ERROR) {
- exc = rb_exc_new2(rb_eRuntimeError, ptr->ip->result);
- /* Tcl_Release(ptr->ip); */
+ /* execute Tk_Init or Tk_SafeInit */
+ exc = tcltkip_init_tk(interp);
+ if (!NIL_P(exc)) {
+ rb_thread_critical = thr_crit_bup;
rbtk_release_ip(ptr);
return exc;
}
-#endif
/* Tcl_Release(ptr->ip); */
rbtk_release_ip(ptr);
@@ -5984,6 +6170,8 @@ lib_restart(self)
rb_secure(4);
+ tcl_stubs_check();
+
/* ip is deleted? */
if (ptr == (struct tcltkip *)NULL || ptr->ip == (Tcl_Interp*)NULL
|| Tcl_InterpDeleted(ptr->ip)
@@ -6007,6 +6195,8 @@ ip_restart(self)
rb_secure(4);
+ tcl_stubs_check();
+
/* ip is deleted? */
if (ptr == (struct tcltkip *)NULL || ptr->ip == (Tcl_Interp*)NULL
|| Tcl_InterpDeleted(ptr->ip)) {
@@ -6039,6 +6229,8 @@ lib_toUTF8_core(ip_obj, src, encodename)
int thr_crit_bup;
#endif
+ tcl_stubs_check();
+
if (NIL_P(src)) {
return rb_str_new2("");
}
@@ -6192,6 +6384,8 @@ lib_fromUTF8_core(ip_obj, src, encodename)
int thr_crit_bup;
#endif
+ tcl_stubs_check();
+
if (NIL_P(src)) {
return rb_str_new2("");
}
@@ -6347,6 +6541,8 @@ lib_UTF_backslash_core(self, str, all_bs)
int taint_flag = OBJ_TAINTED(str);
int thr_crit_bup;
+ tcl_stubs_check();
+
StringValue(str);
if (!RSTRING(str)->len) {
return str;
@@ -6404,6 +6600,7 @@ lib_get_system_encoding(self)
VALUE self;
{
#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION > 0)
+ tcl_stubs_check();
return rb_str_new2(Tcl_GetEncodingName((Tcl_Encoding)NULL));
#else
return Qnil;
@@ -6416,7 +6613,9 @@ lib_set_system_encoding(self, enc_name)
VALUE enc_name;
{
#if TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION > 0)
- if NIL_P(enc_name) {
+ tcl_stubs_check();
+
+ if (NIL_P(enc_name)) {
Tcl_SetSystemEncoding((Tcl_Interp *)NULL, (CONST char *)NULL);
return lib_get_system_encoding(self);
}
@@ -8053,6 +8252,8 @@ lib_split_tklist_core(ip_obj, list_str)
int result;
VALUE old_gc;
+ tcl_stubs_check();
+
if (NIL_P(ip_obj)) {
interp = (Tcl_Interp *)NULL;
} else if (get_ip(ip_obj) == (struct tcltkip *)NULL) {
@@ -8250,6 +8451,8 @@ lib_merge_tklist(argc, argv, obj)
if (argc == 0) return rb_str_new2("");
+ tcl_stubs_check();
+
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
old_gc = rb_gc_disable();
@@ -8314,6 +8517,8 @@ lib_conv_listelement(self, src)
int taint_flag = OBJ_TAINTED(src);
int thr_crit_bup;
+ tcl_stubs_check();
+
thr_crit_bup = rb_thread_critical;
rb_thread_critical = Qtrue;
@@ -8341,15 +8546,6 @@ lib_conv_listelement(self, src)
}
-#ifdef __MACOS__
-static void
-_macinit()
-{
- tcl_macQdPtr = &qd; /* setup QuickDraw globals */
- Tcl_MacSetEventProc(TkMacConvertEvent); /* setup event handler */
-}
-#endif
-
static VALUE
tcltklib_compile_info()
{
@@ -8410,12 +8606,12 @@ tcltklib_compile_info()
return ret;
}
-
/*---- initialization ----*/
void
Init_tcltklib()
{
int thr_crit_bup;
+ int ret;
VALUE lib = rb_define_module("TclTkLib");
VALUE ip = rb_define_class("TclTkIp", rb_cObject);
@@ -8425,16 +8621,6 @@ Init_tcltklib()
/* --------------------------------------------------------------- */
-#if defined USE_TCL_STUBS && defined USE_TK_STUBS
- extern int ruby_tcltk_stubs();
- int ret = ruby_tcltk_stubs();
-
- if (ret)
- rb_raise(rb_eLoadError, "tcltklib: tcltk_stubs init error(%d)", ret);
-#endif
-
- /* --------------------------------------------------------------- */
-
rb_global_variable(&eTkCallbackReturn);
rb_global_variable(&eTkCallbackBreak);
rb_global_variable(&eTkCallbackContinue);
@@ -8641,13 +8827,17 @@ Init_tcltklib()
/* --------------------------------------------------------------- */
-#ifdef __MACOS__
- _macinit();
-#endif
-
- /* from Tk_Main() */
- DUMP1("Tcl_FindExecutable");
- Tcl_FindExecutable(RSTRING(rb_argv0)->ptr);
+ ret = ruby_open_tcl_dll(RSTRING(rb_argv0)->ptr);
+ 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);
+ }
/* --------------------------------------------------------------- */
}