DEFINITIONS
This source file includes following functions.
- _timer_for_tcl
- set_eventloop_tick
- get_eventloop_tick
- set_eventloop_weight
- get_eventloop_weight
- lib_mainloop_core
- lib_mainloop_ensure
- lib_mainloop_launcher
- lib_mainloop
- lib_watchdog_core
- lib_watchdog_ensure
- lib_mainloop_watchdog
- lib_do_one_event
- get_ip
- ip_eval_rescue
- lib_restart
- ip_ruby
- ip_free
- ip_alloc
- ip_init
- ip_eval
- ip_toUTF8
- ip_fromUTF8
- ip_invoke_real
- ivq_safelevel_handler
- invoke_queue_handler
- ip_invoke
- ip_retval
- _macinit
- Init_tcltklib
1
2
3
4
5
6
7 #include "ruby.h"
8 #include "rubysig.h"
9 #undef EXTERN
10 #include <stdio.h>
11 #include <string.h>
12 #include <tcl.h>
13 #include <tk.h>
14
15 #ifdef __MACOS__
16 # include <tkMac.h>
17 # include <Quickdraw.h>
18 #endif
19
20
21
22 #define DUMP1(ARG1) if (ruby_debug) { fprintf(stderr, "tcltklib: %s\n", ARG1);}
23 #define DUMP2(ARG1, ARG2) if (ruby_debug) { fprintf(stderr, "tcltklib: ");\
24 fprintf(stderr, ARG1, ARG2); fprintf(stderr, "\n"); }
25
26
27
28
29
30
31 static VALUE eTkCallbackBreak;
32 static VALUE eTkCallbackContinue;
33
34 static VALUE ip_invoke_real _((int, VALUE*, VALUE));
35
36
37
38 #if !defined __MINGW32__
39
40
41
42
43
44 extern int matherr();
45 int *tclDummyMathPtr = (int *) matherr;
46 #endif
47
48
49
50 struct invoke_queue {
51 Tcl_Event ev;
52 int argc;
53 VALUE *argv;
54 VALUE obj;
55 int done;
56 int safe_level;
57 VALUE *result;
58 VALUE thread;
59 };
60
61 static VALUE main_thread;
62 static VALUE eventloop_thread;
63 static VALUE watchdog_thread;
64 Tcl_Interp *current_interp;
65
66
67
68
69
70
71
72
73 static int tick_counter;
74 #define DEFAULT_EVENT_LOOP_MAX 800
75 #define DEFAULT_NO_EVENT_TICK 10
76 #define DEFAULT_TIMER_TICK 0
77 static int event_loop_max = DEFAULT_EVENT_LOOP_MAX;
78 static int no_event_tick = DEFAULT_NO_EVENT_TICK;
79 static int timer_tick = DEFAULT_TIMER_TICK;
80
81 #if TCL_MAJOR_VERSION >= 8
82 static int ip_ruby _((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST*));
83 #else
84 static int ip_ruby _((ClientData, Tcl_Interp *, int, char **));
85 #endif
86
87
88 static Tcl_TimerToken timer_token = (Tcl_TimerToken)NULL;
89
90
91 static void _timer_for_tcl _((ClientData));
92 static void
93 _timer_for_tcl(clientData)
94 ClientData clientData;
95 {
96 struct invoke_queue *q, *tmp;
97 VALUE thread;
98
99 Tk_DeleteTimerHandler(timer_token);
100 if (timer_tick > 0) {
101 timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
102 (ClientData)0);
103 } else {
104 timer_token = (Tcl_TimerToken)NULL;
105 }
106
107
108 timer_tick += event_loop_max;
109 }
110
111 static VALUE
112 set_eventloop_tick(self, tick)
113 VALUE self;
114 VALUE tick;
115 {
116 int ttick = NUM2INT(tick);
117
118 if (ttick < 0) {
119 rb_raise(rb_eArgError, "timer-tick parameter must be 0 or plus number");
120 }
121
122
123 Tk_DeleteTimerHandler(timer_token);
124
125 timer_tick = ttick;
126 if (timer_tick > 0) {
127
128 timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
129 (ClientData)0);
130 } else {
131 timer_token = (Tcl_TimerToken)NULL;
132 }
133
134 return tick;
135 }
136
137 static VALUE
138 get_eventloop_tick(self)
139 VALUE self;
140 {
141 return INT2NUM(timer_tick);
142 }
143
144 static VALUE
145 set_eventloop_weight(self, loop_max, no_event)
146 VALUE self;
147 VALUE loop_max;
148 VALUE no_event;
149 {
150 int lpmax = NUM2INT(loop_max);
151 int no_ev = NUM2INT(no_event);
152
153 if (lpmax <= 0 || no_ev <= 0) {
154 rb_raise(rb_eArgError, "weight parameters must be plus number");
155 }
156
157 event_loop_max = lpmax;
158 no_event_tick = no_ev;
159
160 return rb_ary_new3(2, loop_max, no_event);
161 }
162
163 static VALUE
164 get_eventloop_weight(self)
165 VALUE self;
166 {
167 return rb_ary_new3(2, INT2NUM(event_loop_max), INT2NUM(no_event_tick));
168 }
169
170 VALUE
171 lib_mainloop_core(check_root_widget)
172 VALUE check_root_widget;
173 {
174 VALUE current = eventloop_thread;
175 int check = (check_root_widget == Qtrue);
176
177 Tk_DeleteTimerHandler(timer_token);
178 if (timer_tick > 0) {
179 timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
180 (ClientData)0);
181 } else {
182 timer_token = (Tcl_TimerToken)NULL;
183 }
184
185 for(;;) {
186 tick_counter = 0;
187 while(tick_counter < event_loop_max) {
188 if (Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT)) {
189 tick_counter++;
190 } else {
191 tick_counter += no_event_tick;
192 }
193 if (watchdog_thread != 0 && eventloop_thread != current) {
194 return Qnil;
195 }
196 }
197 if (check && Tk_GetNumMainWindows() == 0) {
198 break;
199 }
200 rb_thread_schedule();
201 }
202 return Qnil;
203 }
204
205 VALUE
206 lib_mainloop_ensure(parent_evloop)
207 VALUE parent_evloop;
208 {
209 Tk_DeleteTimerHandler(timer_token);
210 timer_token = (Tcl_TimerToken)NULL;
211 DUMP2("mainloop-ensure: current-thread : %lx\n", rb_thread_current());
212 DUMP2("mainloop-ensure: eventloop-thread : %lx\n", eventloop_thread);
213 if (eventloop_thread == rb_thread_current()) {
214 DUMP2("tcltklib: eventloop-thread -> %lx\n", parent_evloop);
215 eventloop_thread = parent_evloop;
216 }
217 return Qnil;
218 }
219
220 static VALUE
221 lib_mainloop_launcher(check_rootwidget)
222 VALUE check_rootwidget;
223 {
224 VALUE parent_evloop = eventloop_thread;
225
226 eventloop_thread = rb_thread_current();
227
228 if (ruby_debug) {
229 fprintf(stderr, "tcltklib: eventloop-thread : %lx -> %lx\n",
230 parent_evloop, eventloop_thread);
231 }
232
233 return rb_ensure(lib_mainloop_core, check_rootwidget,
234 lib_mainloop_ensure, parent_evloop);
235 }
236
237
238 static VALUE
239 lib_mainloop(argc, argv, self)
240 int argc;
241 VALUE *argv;
242 VALUE self;
243 {
244 VALUE check_rootwidget;
245
246 if (rb_scan_args(argc, argv, "01", &check_rootwidget) == 0) {
247 check_rootwidget = Qtrue;
248 } else if (RTEST(check_rootwidget)) {
249 check_rootwidget = Qtrue;
250 } else {
251 check_rootwidget = Qfalse;
252 }
253
254 return lib_mainloop_launcher(check_rootwidget);
255 }
256
257 VALUE
258 lib_watchdog_core(check_rootwidget)
259 VALUE check_rootwidget;
260 {
261 VALUE current = eventloop_thread;
262 VALUE evloop;
263 int check = (check_rootwidget == Qtrue);
264 ID stop = rb_intern("stop?");
265
266
267 if (watchdog_thread != 0) {
268 if (rb_funcall(watchdog_thread, stop, 0) == Qtrue) {
269 rb_funcall(watchdog_thread, rb_intern("kill"), 0);
270 } else {
271 return Qnil;
272 }
273 }
274 watchdog_thread = rb_thread_current();
275
276
277 do {
278 if (eventloop_thread == 0
279 || rb_funcall(eventloop_thread, stop, 0) == Qtrue) {
280
281 DUMP2("eventloop thread %lx is sleeping or dead", eventloop_thread);
282 evloop = rb_thread_create(lib_mainloop_launcher,
283 (void*)&check_rootwidget);
284 DUMP2("create new eventloop thread %lx", evloop);
285 rb_thread_run(evloop);
286 } else {
287 rb_thread_schedule();
288 }
289 } while(!check || Tk_GetNumMainWindows() != 0);
290
291 return Qnil;
292 }
293
294 VALUE
295 lib_watchdog_ensure(arg)
296 VALUE arg;
297 {
298 eventloop_thread = 0;
299 return Qnil;
300 }
301
302 static VALUE
303 lib_mainloop_watchdog(argc, argv, self)
304 int argc;
305 VALUE *argv;
306 VALUE self;
307 {
308 VALUE check_rootwidget;
309
310 if (rb_scan_args(argc, argv, "01", &check_rootwidget) == 0) {
311 check_rootwidget = Qtrue;
312 } else if (RTEST(check_rootwidget)) {
313 check_rootwidget = Qtrue;
314 } else {
315 check_rootwidget = Qfalse;
316 }
317
318 return rb_ensure(lib_watchdog_core, check_rootwidget,
319 lib_watchdog_ensure, Qnil);
320 }
321
322 static VALUE
323 lib_do_one_event(argc, argv, self)
324 int argc;
325 VALUE *argv;
326 VALUE self;
327 {
328 VALUE obj, vflags;
329 int flags;
330
331 if (rb_scan_args(argc, argv, "01", &vflags) == 0) {
332 flags = 0;
333 } else {
334 Check_Type(vflags, T_FIXNUM);
335 flags = FIX2INT(vflags);
336 }
337 return INT2NUM(Tcl_DoOneEvent(flags));
338 }
339
340
341 struct tcltkip {
342 Tcl_Interp *ip;
343 int return_value;
344 };
345
346 static struct tcltkip *
347 get_ip(self)
348 VALUE self;
349 {
350 struct tcltkip *ptr;
351
352 Data_Get_Struct(self, struct tcltkip, ptr);
353 if (ptr == 0) {
354 rb_raise(rb_eTypeError, "uninitialized TclTkIp");
355 }
356 return ptr;
357 }
358
359
360 static VALUE
361 ip_eval_rescue(failed, einfo)
362 VALUE *failed;
363 VALUE einfo;
364 {
365 *failed = einfo;
366 return Qnil;
367 }
368
369
370 static VALUE
371 lib_restart(self)
372 VALUE self;
373 {
374 struct tcltkip *ptr = get_ip(self);
375
376
377 ptr->return_value = Tcl_Eval(ptr->ip, "destroy .");
378
379 DUMP2("(TCL_Eval result) %d", ptr->return_value);
380
381
382 DUMP1("Tk_Init");
383 if (Tk_Init(ptr->ip) == TCL_ERROR) {
384 rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
385 }
386
387 return Qnil;
388 }
389
390 static int
391 #if TCL_MAJOR_VERSION >= 8
392 ip_ruby(clientData, interp, argc, argv)
393 ClientData clientData;
394 Tcl_Interp *interp;
395 int argc;
396 Tcl_Obj *CONST argv[];
397 #else
398 ip_ruby(clientData, interp, argc, argv)
399 ClientData clientData;
400 Tcl_Interp *interp;
401 int argc;
402 char *argv[];
403 #endif
404 {
405 VALUE res;
406 int old_trapflg;
407 VALUE failed = 0;
408 char *arg;
409 int dummy;
410
411
412 if (argc != 2) {
413 rb_raise(rb_eArgError, "wrong # of arguments (%d for 1)", argc);
414 }
415
416
417 #if TCL_MAJOR_VERSION >= 8
418 arg = Tcl_GetStringFromObj(argv[1], &dummy);
419 #else
420 arg = argv[1];
421 #endif
422
423
424 DUMP2("rb_eval_string(%s)", arg);
425 old_trapflg = rb_trap_immediate;
426 rb_trap_immediate = 0;
427 res = rb_rescue2(rb_eval_string, (VALUE)arg,
428 ip_eval_rescue, (VALUE)&failed,
429 rb_eStandardError, rb_eScriptError, 0);
430 rb_trap_immediate = old_trapflg;
431
432 Tcl_ResetResult(interp);
433 if (failed) {
434 VALUE eclass = CLASS_OF(failed);
435 Tcl_AppendResult(interp, StringValuePtr(failed), (char*)NULL);
436 if (eclass == eTkCallbackBreak) {
437 return TCL_BREAK;
438 } else if (eclass == eTkCallbackContinue) {
439 return TCL_CONTINUE;
440 } else {
441 return TCL_ERROR;
442 }
443 }
444
445
446 if (NIL_P(res)) {
447 DUMP1("(rb_eval_string result) nil");
448 return TCL_OK;
449 }
450
451
452 DUMP2("(rb_eval_string result) %s", StringValuePtr(res));
453 DUMP1("Tcl_AppendResult");
454 Tcl_AppendResult(interp, StringValuePtr(res), (char *)NULL);
455
456 return TCL_OK;
457 }
458
459
460 static void
461 ip_free(ptr)
462 struct tcltkip *ptr;
463 {
464 DUMP1("Tcl_DeleteInterp");
465 if (ptr) {
466 Tcl_DeleteInterp(ptr->ip);
467 free(ptr);
468 }
469 }
470
471
472 static VALUE
473 ip_alloc(self)
474 VALUE self;
475 {
476 return Data_Wrap_Struct(self, 0, ip_free, 0);
477 }
478
479 static VALUE
480 ip_init(self)
481 VALUE self;
482 {
483 struct tcltkip *ptr;
484
485
486 Data_Get_Struct(self, struct tcltkip, ptr);
487 ptr = ALLOC(struct tcltkip);
488 DATA_PTR(self) = ptr;
489 ptr->return_value = 0;
490
491
492 DUMP1("Tcl_CreateInterp");
493 ptr->ip = Tcl_CreateInterp();
494 current_interp = ptr->ip;
495
496
497 DUMP1("Tcl_Init");
498 if (Tcl_Init(ptr->ip) == TCL_ERROR) {
499 rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
500 }
501 DUMP1("Tk_Init");
502 if (Tk_Init(ptr->ip) == TCL_ERROR) {
503 rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
504 }
505 DUMP1("Tcl_StaticPackage(\"Tk\")");
506 Tcl_StaticPackage(ptr->ip, "Tk", Tk_Init,
507 (Tcl_PackageInitProc *) NULL);
508
509
510 #if TCL_MAJOR_VERSION >= 8
511 DUMP1("Tcl_CreateObjCommand(\"ruby\")");
512 Tcl_CreateObjCommand(ptr->ip, "ruby", ip_ruby, (ClientData)NULL,
513 (Tcl_CmdDeleteProc *)NULL);
514 #else
515 DUMP1("Tcl_CreateCommand(\"ruby\")");
516 Tcl_CreateCommand(ptr->ip, "ruby", ip_ruby, (ClientData)NULL,
517 (Tcl_CmdDeleteProc *)NULL);
518 #endif
519
520 return self;
521 }
522
523
524 static VALUE
525 ip_eval(self, str)
526 VALUE self;
527 VALUE str;
528 {
529 char *s;
530 char *buf;
531 struct tcltkip *ptr = get_ip(self);
532
533
534 s = StringValuePtr(str);
535 buf = ALLOCA_N(char, strlen(s)+1);
536 strcpy(buf, s);
537 DUMP2("Tcl_Eval(%s)", buf);
538 ptr->return_value = Tcl_Eval(ptr->ip, buf);
539 if (ptr->return_value == TCL_ERROR) {
540 rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
541 }
542 DUMP2("(TCL_Eval result) %d", ptr->return_value);
543
544
545 return(rb_str_new2(ptr->ip->result));
546 }
547
548
549 static VALUE
550 ip_toUTF8(self, str, encodename)
551 VALUE self;
552 VALUE str;
553 VALUE encodename;
554 {
555 #ifdef TCL_UTF_MAX
556 Tcl_Interp *interp;
557 Tcl_Encoding encoding;
558 Tcl_DString dstr;
559 struct tcltkip *ptr;
560 char *buf;
561
562 ptr = get_ip(self);
563 interp = ptr->ip;
564
565 StringValue(encodename);
566 StringValue(str);
567 encoding = Tcl_GetEncoding(interp, RSTRING(encodename)->ptr);
568 if (!RSTRING(str)->len) return str;
569 buf = ALLOCA_N(char,strlen(RSTRING(str)->ptr)+1);
570 strcpy(buf, RSTRING(str)->ptr);
571
572 Tcl_DStringInit(&dstr);
573 Tcl_DStringFree(&dstr);
574 Tcl_ExternalToUtfDString(encoding,buf,strlen(buf),&dstr);
575 str = rb_str_new2(Tcl_DStringValue(&dstr));
576
577 Tcl_FreeEncoding(encoding);
578 Tcl_DStringFree(&dstr);
579 #endif
580 return str;
581 }
582
583 static VALUE
584 ip_fromUTF8(self, str, encodename)
585 VALUE self;
586 VALUE str;
587 VALUE encodename;
588 {
589 #ifdef TCL_UTF_MAX
590 Tcl_Interp *interp;
591 Tcl_Encoding encoding;
592 Tcl_DString dstr;
593 struct tcltkip *ptr;
594 char *buf;
595
596 ptr = get_ip(self);
597 interp = ptr->ip;
598
599 StringValue(encodename);
600 StringValue(str);
601 encoding = Tcl_GetEncoding(interp,RSTRING(encodename)->ptr);
602 if (!RSTRING(str)->len) return str;
603 buf = ALLOCA_N(char,strlen(RSTRING(str)->ptr)+1);
604 strcpy(buf,RSTRING(str)->ptr);
605
606 Tcl_DStringInit(&dstr);
607 Tcl_DStringFree(&dstr);
608 Tcl_UtfToExternalDString(encoding,buf,strlen(buf),&dstr);
609 str = rb_str_new2(Tcl_DStringValue(&dstr));
610
611 Tcl_FreeEncoding(encoding);
612 Tcl_DStringFree(&dstr);
613
614 #endif
615 return str;
616 }
617
618
619 static VALUE
620 ip_invoke_real(argc, argv, obj)
621 int argc;
622 VALUE *argv;
623 VALUE obj;
624 {
625 VALUE v;
626 struct tcltkip *ptr;
627 int i;
628 Tcl_CmdInfo info;
629 char *cmd, *s;
630 char **av = (char **)NULL;
631 #if TCL_MAJOR_VERSION >= 8
632 Tcl_Obj **ov = (Tcl_Obj **)NULL;
633 Tcl_Obj *resultPtr;
634 #endif
635
636
637 ptr = get_ip(obj);
638
639
640 v = argv[0];
641 cmd = StringValuePtr(v);
642
643
644 if (!Tcl_GetCommandInfo(ptr->ip, cmd, &info)) {
645 rb_raise(rb_eNameError, "invalid command name `%s'", cmd);
646 }
647
648
649 #if TCL_MAJOR_VERSION >= 8
650 if (info.isNativeObjectProc) {
651
652 ov = (Tcl_Obj **)ALLOCA_N(Tcl_Obj *, argc+1);
653 for (i = 0; i < argc; ++i) {
654 v = argv[i];
655 s = StringValuePtr(v);
656 ov[i] = Tcl_NewStringObj(s, RSTRING(v)->len);
657 Tcl_IncrRefCount(ov[i]);
658 }
659 ov[argc] = (Tcl_Obj *)NULL;
660 }
661 else
662 #endif
663 {
664
665 av = (char **)ALLOCA_N(char *, argc+1);
666 for (i = 0; i < argc; ++i) {
667 v = argv[i];
668 s = StringValuePtr(v);
669 av[i] = ALLOCA_N(char, strlen(s)+1);
670 strcpy(av[i], s);
671 }
672 av[argc] = (char *)NULL;
673 }
674
675 Tcl_ResetResult(ptr->ip);
676
677
678 #if TCL_MAJOR_VERSION >= 8
679 if (info.isNativeObjectProc) {
680 int dummy;
681 ptr->return_value = (*info.objProc)(info.objClientData,
682 ptr->ip, argc, ov);
683
684
685 resultPtr = Tcl_GetObjResult(ptr->ip);
686 Tcl_SetResult(ptr->ip, Tcl_GetStringFromObj(resultPtr, &dummy),
687 TCL_VOLATILE);
688
689 for (i=0; i<argc; i++) {
690 Tcl_DecrRefCount(ov[i]);
691 }
692 }
693 else
694 #endif
695 {
696 ptr->return_value = (*info.proc)(info.clientData,
697 ptr->ip, argc, av);
698 }
699
700 if (ptr->return_value == TCL_ERROR) {
701 rb_raise(rb_eRuntimeError, "%s", ptr->ip->result);
702 }
703
704
705 return rb_str_new2(ptr->ip->result);
706 }
707
708 VALUE
709 ivq_safelevel_handler(arg, ivq)
710 VALUE arg;
711 VALUE ivq;
712 {
713 struct invoke_queue *q;
714
715 Data_Get_Struct(ivq, struct invoke_queue, q);
716 DUMP2("(safe-level handler) $SAFE = %d", q->safe_level);
717 rb_set_safe_level(q->safe_level);
718 return ip_invoke_real(q->argc, q->argv, q->obj);
719 }
720
721 int invoke_queue_handler _((Tcl_Event *, int));
722 int
723 invoke_queue_handler(evPtr, flags)
724 Tcl_Event *evPtr;
725 int flags;
726 {
727 struct invoke_queue *tmp, *q = (struct invoke_queue *)evPtr;
728
729 DUMP1("do_invoke_queue_handler");
730 DUMP2("invoke queue_thread : %lx", rb_thread_current());
731 DUMP2("added by thread : %lx", q->thread);
732
733 if (q->done) {
734
735 return 0;
736 }
737
738
739 q->done = 1;
740
741
742 if (rb_safe_level() != q->safe_level) {
743 *(q->result) = rb_funcall(rb_proc_new(ivq_safelevel_handler,
744 Data_Wrap_Struct(rb_cData,0,0,q)),
745 rb_intern("call"), 0);
746 } else {
747 *(q->result) = ip_invoke_real(q->argc, q->argv, q->obj);
748 }
749
750
751 rb_thread_run(q->thread);
752
753
754 return 1;
755 }
756
757 static VALUE
758 ip_invoke(argc, argv, obj)
759 int argc;
760 VALUE *argv;
761 VALUE obj;
762 {
763 struct invoke_queue *tmp;
764 VALUE current = rb_thread_current();
765 VALUE result;
766 VALUE *alloc_argv, *alloc_result;
767 Tcl_QueuePosition position;
768
769 if (eventloop_thread == 0 || current == eventloop_thread) {
770 DUMP2("invoke from current eventloop %lx", current);
771 return ip_invoke_real(argc, argv, obj);
772 }
773
774 DUMP2("invoke from thread %lx (NOT current eventloop)", current);
775
776
777 alloc_argv = ALLOC_N(VALUE,argc);
778 MEMCPY(alloc_argv, argv, VALUE, argc);
779 alloc_result = ALLOC(VALUE);
780
781
782 tmp = (struct invoke_queue *)Tcl_Alloc(sizeof(struct invoke_queue));
783
784
785 tmp->done = 0;
786 tmp->obj = obj;
787 tmp->argc = argc;
788 tmp->argv = alloc_argv;
789 tmp->result = alloc_result;
790 tmp->thread = current;
791 tmp->safe_level = rb_safe_level();
792 tmp->ev.proc = invoke_queue_handler;
793 position = TCL_QUEUE_TAIL;
794
795
796 Tcl_QueueEvent(&tmp->ev, position);
797
798
799 rb_thread_stop();
800
801
802 result = *alloc_result;
803 free(alloc_argv);
804 free(alloc_result);
805
806 return result;
807 }
808
809
810 static VALUE
811 ip_retval(self)
812 VALUE self;
813 {
814 struct tcltkip *ptr;
815
816
817 ptr = get_ip(self);
818
819 return (INT2FIX(ptr->return_value));
820 }
821
822 #ifdef __MACOS__
823 static void
824 _macinit()
825 {
826 tcl_macQdPtr = &qd;
827 Tcl_MacSetEventProc(TkMacConvertEvent);
828 }
829 #endif
830
831
832 void
833 Init_tcltklib()
834 {
835 VALUE lib = rb_define_module("TclTkLib");
836 VALUE ip = rb_define_class("TclTkIp", rb_cObject);
837
838 VALUE ev_flag = rb_define_module_under(lib, "EventFlag");
839
840 #if defined USE_TCL_STUBS && defined USE_TK_STUBS
841 extern int ruby_tcltk_stubs();
842 int ret = ruby_tcltk_stubs();
843 if (ret)
844 rb_raise(rb_eLoadError, "tcltklib: tcltk_stubs init error(%d)", ret);
845 #endif
846
847 rb_define_const(ev_flag, "WINDOW", INT2FIX(TCL_WINDOW_EVENTS));
848 rb_define_const(ev_flag, "FILE", INT2FIX(TCL_FILE_EVENTS));
849 rb_define_const(ev_flag, "TIMER", INT2FIX(TCL_TIMER_EVENTS));
850 rb_define_const(ev_flag, "IDLE", INT2FIX(TCL_IDLE_EVENTS));
851 rb_define_const(ev_flag, "ALL", INT2FIX(TCL_ALL_EVENTS));
852 rb_define_const(ev_flag, "DONT_WAIT", INT2FIX(TCL_DONT_WAIT));
853
854 eTkCallbackBreak = rb_define_class("TkCallbackBreak", rb_eStandardError);
855 eTkCallbackContinue = rb_define_class("TkCallbackContinue",rb_eStandardError);
856
857 rb_define_module_function(lib, "mainloop", lib_mainloop, -1);
858 rb_define_module_function(lib, "mainloop_watchdog",
859 lib_mainloop_watchdog, -1);
860 rb_define_module_function(lib, "do_one_event", lib_do_one_event, -1);
861 rb_define_module_function(lib, "set_eventloop_tick",set_eventloop_tick,1);
862 rb_define_module_function(lib, "get_eventloop_tick",get_eventloop_tick,0);
863 rb_define_module_function(lib, "set_eventloop_weight",
864 set_eventloop_weight, 2);
865 rb_define_module_function(lib, "get_eventloop_weight",
866 get_eventloop_weight, 0);
867
868 rb_define_singleton_method(ip, "allocate", ip_alloc, 0);
869 rb_define_method(ip, "initialize", ip_init, 0);
870 rb_define_method(ip, "_eval", ip_eval, 1);
871 rb_define_method(ip, "_toUTF8",ip_toUTF8,2);
872 rb_define_method(ip, "_fromUTF8",ip_fromUTF8,2);
873 rb_define_method(ip, "_invoke", ip_invoke, -1);
874 rb_define_method(ip, "_return_value", ip_retval, 0);
875 rb_define_method(ip, "mainloop", lib_mainloop, -1);
876 rb_define_method(ip, "mainloop_watchdog", lib_mainloop_watchdog, -1);
877 rb_define_method(ip, "do_one_event", lib_do_one_event, -1);
878 rb_define_method(ip, "set_eventloop_tick", set_eventloop_tick, 1);
879 rb_define_method(ip, "get_eventloop_tick", get_eventloop_tick, 0);
880 rb_define_method(ip, "set_eventloop_weight", set_eventloop_weight, 2);
881 rb_define_method(ip, "get_eventloop_weight", get_eventloop_weight, 0);
882 rb_define_method(ip, "restart", lib_restart, 0);
883
884 main_thread = rb_thread_current();
885 eventloop_thread = 0;
886 watchdog_thread = 0;
887
888 #ifdef __MACOS__
889 _macinit();
890 #endif
891
892
893
894 DUMP1("Tcl_FindExecutable");
895 Tcl_FindExecutable(RSTRING(rb_argv0)->ptr);
896 }
897
898