]>
cvs.zerfleddert.de Git - micropolis/blob - src/tk/tkcmds.c
4 * This file contains a collection of Tk-related Tcl commands
5 * that didn't fit in any particular file of the toolkit.
7 * Copyright 1990-1992 Regents of the University of California
8 * Permission to use, copy, modify, and distribute this
9 * software and its documentation for any purpose and without
10 * fee is hereby granted, provided that the above copyright
11 * notice appear in all copies. The University of California
12 * makes no representations about the suitability of this
13 * software for any purpose. It is provided "as is" without
14 * express or implied warranty.
18 static char rcsid
[] = "$Header: /user6/ouster/wish/RCS/tkCmds.c,v 1.32 92/06/03 14:21:14 ouster Exp $ SPRITE (Berkeley)";
25 * The data structure below is used by the "after" command to remember
26 * the command to be executed later.
30 Tcl_Interp
*interp
; /* Interpreter in which to execute command. */
31 char *command
; /* Command to execute. Malloc'ed, so must
32 * be freed when structure is deallocated.
33 * NULL means nothing to execute. */
34 int *donePtr
; /* If non-NULL indicates address of word to
35 * set to 1 when command has finally been
40 * Forward declarations for procedures defined later in this file:
43 static void AfterProc
_ANSI_ARGS_((ClientData clientData
));
44 static char * WaitVariableProc
_ANSI_ARGS_((ClientData clientData
,
45 Tcl_Interp
*interp
, char *name1
, char *name2
,
47 static void WaitWindowProc
_ANSI_ARGS_((ClientData clientData
,
51 *----------------------------------------------------------------------
55 * This procedure is invoked to process the "after" Tcl command.
56 * See the user documentation for details on what it does.
59 * A standard Tcl result.
62 * See the user documentation.
64 *----------------------------------------------------------------------
70 ClientData clientData
, /* Main window associated with
71 * interpreter. Not used.*/
72 Tcl_Interp
*interp
, /* Current interpreter. */
73 int argc
, /* Number of arguments. */
74 char **argv
/* Argument strings. */
82 Tcl_AppendResult(interp
, "wrong # args: should be \"",
83 argv
[0], " milliseconds ?command? ?arg arg ...?\"",
88 if ((Tcl_GetInt(interp
, argv
[1], &ms
) != TCL_OK
) || (ms
<= 0)) {
89 Tcl_AppendResult(interp
, "bad milliseconds value \"",
90 argv
[1], "\"", (char *) NULL
);
93 afterPtr
= (AfterInfo
*) ckalloc((unsigned) (sizeof(AfterInfo
)));
94 afterPtr
->interp
= interp
;
96 afterPtr
->command
= (char *) NULL
;
98 afterPtr
->donePtr
= &done
;
99 } else if (argc
== 3) {
100 afterPtr
->command
= (char *) ckalloc((unsigned) (strlen(argv
[2]) + 1));
101 strcpy(afterPtr
->command
, argv
[2]);
102 afterPtr
->donePtr
= (int *) NULL
;
104 afterPtr
->command
= Tcl_Concat(argc
-2, argv
+2);
105 afterPtr
->donePtr
= (int *) NULL
;
107 Tk_CreateTimerHandler(ms
, AfterProc
, (ClientData
) afterPtr
);
115 * Must reset interpreter result because it could have changed as
116 * part of events processed by Tk_DoOneEvent.
119 Tcl_ResetResult(interp
);
124 *----------------------------------------------------------------------
128 * Timer callback to execute commands registered with the
135 * Executes whatever command was specified. If the command
136 * returns an error, then the command "tkerror" is invoked
137 * to process the error; if tkerror fails then information
138 * about the error is output on stderr.
140 *----------------------------------------------------------------------
145 ClientData clientData
/* Describes command to execute. */
148 AfterInfo
*afterPtr
= (AfterInfo
*) clientData
;
151 if (afterPtr
->command
!= NULL
) {
152 result
= Tcl_GlobalEval(afterPtr
->interp
, afterPtr
->command
);
153 if (result
!= TCL_OK
) {
154 TkBindError(afterPtr
->interp
);
156 ckfree(afterPtr
->command
);
158 if (afterPtr
->donePtr
!= NULL
) {
159 *afterPtr
->donePtr
= 1;
161 ckfree((char *) afterPtr
);
165 *----------------------------------------------------------------------
169 * This procedure is invoked to process the "bind" Tcl command.
170 * See the user documentation for details on what it does.
173 * A standard Tcl result.
176 * See the user documentation.
178 *----------------------------------------------------------------------
183 ClientData clientData
, /* Main window associated with
185 Tcl_Interp
*interp
, /* Current interpreter. */
186 int argc
, /* Number of arguments. */
187 char **argv
/* Argument strings. */
190 Tk_Window tkwin
= (Tk_Window
) clientData
;
194 if ((argc
< 2) || (argc
> 4)) {
195 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
196 " window ?pattern? ?command?\"", (char *) NULL
);
199 if (argv
[1][0] == '.') {
200 winPtr
= (TkWindow
*) Tk_NameToWindow(interp
, argv
[1], tkwin
);
201 if (winPtr
== NULL
) {
204 object
= (ClientData
) winPtr
->pathName
;
206 winPtr
= (TkWindow
*) clientData
;
207 object
= (ClientData
) Tk_GetUid(argv
[1]);
214 if (argv
[3][0] == 0) {
215 return Tk_DeleteBinding(interp
, winPtr
->mainPtr
->bindingTable
,
218 if (argv
[3][0] == '+') {
222 mask
= Tk_CreateBinding(interp
, winPtr
->mainPtr
->bindingTable
,
223 object
, argv
[2], argv
[3], append
);
227 } else if (argc
== 3) {
230 command
= Tk_GetBinding(interp
, winPtr
->mainPtr
->bindingTable
,
232 if (command
== NULL
) {
233 Tcl_ResetResult(interp
);
236 interp
->result
= command
;
238 Tk_GetAllBindings(interp
, winPtr
->mainPtr
->bindingTable
, object
);
244 *----------------------------------------------------------------------
248 * This procedure is invoked by Tk_HandleEvent for each event; it
249 * causes any appropriate bindings for that event to be invoked.
255 * Depends on what bindings have been established with the "bind"
258 *----------------------------------------------------------------------
263 TkWindow
*winPtr
, /* Pointer to info about window. */
264 XEvent
*eventPtr
/* Information about event. */
267 ClientData objects
[3];
268 static Tk_Uid allUid
= NULL
;
270 if ((winPtr
->mainPtr
== NULL
) || (winPtr
->mainPtr
->bindingTable
== NULL
)) {
273 objects
[0] = (ClientData
) winPtr
->pathName
;
274 objects
[1] = (ClientData
) winPtr
->classUid
;
275 if (allUid
== NULL
) {
276 allUid
= Tk_GetUid("all");
278 objects
[2] = (ClientData
) allUid
;
279 Tk_BindEvent(winPtr
->mainPtr
->bindingTable
, eventPtr
,
280 (Tk_Window
) winPtr
, 3, objects
);
284 *----------------------------------------------------------------------
288 * This procedure is invoked to process the "destroy" Tcl command.
289 * See the user documentation for details on what it does.
292 * A standard Tcl result.
295 * See the user documentation.
297 *----------------------------------------------------------------------
302 ClientData clientData
, /* Main window associated with
304 Tcl_Interp
*interp
, /* Current interpreter. */
305 int argc
, /* Number of arguments. */
306 char **argv
/* Argument strings. */
310 Tk_Window tkwin
= (Tk_Window
) clientData
;
313 Tcl_AppendResult(interp
, "wrong # args: should be \"",
314 argv
[0], " pathName\"", (char *) NULL
);
318 window
= Tk_NameToWindow(interp
, argv
[1], tkwin
);
319 if (window
== NULL
) {
322 Tk_DestroyWindow(window
);
327 *----------------------------------------------------------------------
331 * This procedure is invoked to process the "update" Tcl command.
332 * See the user documentation for details on what it does.
335 * A standard Tcl result.
338 * See the user documentation.
340 *----------------------------------------------------------------------
346 ClientData clientData
, /* Main window associated with
348 Tcl_Interp
*interp
, /* Current interpreter. */
349 int argc
, /* Number of arguments. */
350 char **argv
/* Argument strings. */
353 Tk_Window tkwin
= (Tk_Window
) clientData
;
357 flags
= TK_DONT_WAIT
;
358 } else if (argc
== 2) {
359 if (strncmp(argv
[1], "idletasks", strlen(argv
[1])) != 0) {
360 Tcl_AppendResult(interp
, "bad argument \"", argv
[1],
361 "\": must be idletasks", (char *) NULL
);
364 flags
= TK_IDLE_EVENTS
;
366 Tcl_AppendResult(interp
, "wrong # args: should be \"",
367 argv
[0], " ?idletasks?\"", (char *) NULL
);
372 * Handle all pending events, sync the display, and repeat over
373 * and over again until all pending events have been handled.
377 while (Tk_DoOneEvent(flags
) != 0) {
378 /* Empty loop body */
380 XSync(Tk_Display(tkwin
), False
);
381 if (Tk_DoOneEvent(flags
) == 0) {
387 * Must clear the interpreter's result because event handlers could
388 * have executed commands.
391 Tcl_ResetResult(interp
);
396 *----------------------------------------------------------------------
400 * This procedure is invoked to process the "wait" Tcl command.
401 * See the user documentation for details on what it does.
404 * A standard Tcl result.
407 * See the user documentation.
409 *----------------------------------------------------------------------
415 ClientData clientData
, /* Main window associated with
417 Tcl_Interp
*interp
, /* Current interpreter. */
418 int argc
, /* Number of arguments. */
419 char **argv
/* Argument strings. */
422 Tk_Window tkwin
= (Tk_Window
) clientData
;
427 Tcl_AppendResult(interp
, "wrong # args: should be \"",
428 argv
[0], " variable|window name\"", (char *) NULL
);
432 length
= strlen(argv
[1]);
433 if ((c
== 'v') && (strncmp(argv
[1], "variable", length
) == 0)) {
434 Tcl_TraceVar(interp
, argv
[2],
435 TCL_GLOBAL_ONLY
|TCL_TRACE_WRITES
|TCL_TRACE_UNSETS
,
436 WaitVariableProc
, (ClientData
) &done
);
441 Tcl_UntraceVar(interp
, argv
[2],
442 TCL_GLOBAL_ONLY
|TCL_TRACE_WRITES
|TCL_TRACE_UNSETS
,
443 WaitVariableProc
, (ClientData
) &done
);
444 } else if ((c
== 'w') && (strncmp(argv
[1], "window", length
) == 0)) {
447 window
= Tk_NameToWindow(interp
, argv
[2], tkwin
);
448 if (window
== NULL
) {
451 Tk_CreateEventHandler(window
, StructureNotifyMask
,
452 WaitWindowProc
, (ClientData
) &done
);
457 Tk_DeleteEventHandler(window
, StructureNotifyMask
,
458 WaitWindowProc
, (ClientData
) &done
);
460 Tcl_AppendResult(interp
, "bad option \"", argv
[1],
461 "\": must be variable or window", (char *) NULL
);
466 * Clear out the interpreter's result, since it may have been set
470 Tcl_ResetResult(interp
);
477 ClientData clientData
, /* Pointer to integer to set to 1. */
478 Tcl_Interp
*interp
, /* Interpreter containing variable. */
479 char *name1
, /* Name of variable. */
480 char *name2
, /* Second part of variable name. */
481 int flags
/* Information about what happened. */
484 int *donePtr
= (int *) clientData
;
487 return (char *) NULL
;
492 ClientData clientData
, /* Pointer to integer to set to 1. */
493 XEvent
*eventPtr
/* Information about event. */
496 int *donePtr
= (int *) clientData
;
498 if (eventPtr
->type
== DestroyNotify
) {
504 *----------------------------------------------------------------------
508 * This procedure is invoked to process the "winfo" Tcl command.
509 * See the user documentation for details on what it does.
512 * A standard Tcl result.
515 * See the user documentation.
517 *----------------------------------------------------------------------
522 ClientData clientData
, /* Main window associated with
524 Tcl_Interp
*interp
, /* Current interpreter. */
525 int argc
, /* Number of arguments. */
526 char **argv
/* Argument strings. */
529 Tk_Window tkwin
= (Tk_Window
) clientData
;
533 register TkWindow
*winPtr
;
535 #define SETUP(name) \
540 window = Tk_NameToWindow(interp, argv[2], tkwin); \
541 if (window == NULL) { \
546 Tcl_AppendResult(interp
, "wrong # args: should be \"",
547 argv
[0], " option ?arg?\"", (char *) NULL
);
551 length
= strlen(argv
[1]);
552 if ((c
== 'a') && (strcmp(argv
[1], "atom") == 0)) {
554 Tcl_AppendResult(interp
, "wrong # args: should be \"",
555 argv
[0], " atom name\"", (char *) NULL
);
558 sprintf(interp
->result
, "%d", Tk_InternAtom(tkwin
, argv
[2]));
559 } else if ((c
== 'a') && (strncmp(argv
[1], "atomname", length
) == 0)
565 Tcl_AppendResult(interp
, "wrong # args: should be \"",
566 argv
[0], " atomname id\"", (char *) NULL
);
569 if (Tcl_GetInt(interp
, argv
[2], (int *) &atom
) != TCL_OK
) {
572 name
= Tk_GetAtomName(tkwin
, atom
);
573 if (strcmp(name
, "?bad atom?") == 0) {
574 Tcl_AppendResult(interp
, "no atom exists with id \"",
575 argv
[2], "\"", (char *) NULL
);
578 interp
->result
= name
;
579 } else if ((c
== 'c') && (strncmp(argv
[1], "children", length
) == 0)
581 char *separator
, *childName
;
585 for (winPtr
= ((TkWindow
*) window
)->childList
; winPtr
!= NULL
;
586 winPtr
= winPtr
->nextPtr
) {
587 childName
= Tcl_Merge(1, &winPtr
->pathName
);
588 Tcl_AppendResult(interp
, separator
, childName
, (char *) NULL
);
592 } else if ((c
== 'c') && (strncmp(argv
[1], "class", length
) == 0)
595 interp
->result
= Tk_Class(window
);
596 } else if ((c
== 'c') && (strncmp(argv
[1], "containing", length
) == 0)
601 Tcl_AppendResult(interp
, "wrong # args: should be \"",
602 argv
[0], " containing rootX rootY\"", (char *) NULL
);
605 if ((Tk_GetPixels(interp
, tkwin
, argv
[2], &rootX
) != TCL_OK
)
606 || (Tk_GetPixels(interp
, tkwin
, argv
[3], &rootY
) != TCL_OK
)) {
609 window
= Tk_CoordsToWindow(rootX
, rootY
, tkwin
);
610 if (window
!= NULL
) {
611 interp
->result
= Tk_PathName(window
);
613 } else if ((c
== 'f') && (strncmp(argv
[1], "fpixels", length
) == 0)
618 Tcl_AppendResult(interp
, "wrong # args: should be \"",
619 argv
[0], " fpixels window number\"", (char *) NULL
);
622 window
= Tk_NameToWindow(interp
, argv
[2], tkwin
);
623 if (window
== NULL
) {
626 if (Tk_GetScreenMM(interp
, window
, argv
[3], &mm
) != TCL_OK
) {
629 pixels
= mm
* WidthOfScreen(Tk_Screen(window
))
630 / WidthMMOfScreen(Tk_Screen(window
));
631 sprintf(interp
->result
, "%g", pixels
);
632 } else if ((c
== 'g') && (strncmp(argv
[1], "geometry", length
) == 0)) {
634 sprintf(interp
->result
, "%dx%d+%d+%d", Tk_Width(window
),
635 Tk_Height(window
), Tk_X(window
), Tk_Y(window
));
636 } else if ((c
== 'h') && (strncmp(argv
[1], "height", length
) == 0)) {
638 sprintf(interp
->result
, "%d", Tk_Height(window
));
639 } else if ((c
== 'i') && (strcmp(argv
[1], "id") == 0)) {
641 sprintf(interp
->result
, "0x%x", Tk_WindowId(window
));
642 } else if ((c
== 'i') && (strncmp(argv
[1], "interps", length
) == 0)
645 Tcl_AppendResult(interp
, "wrong # args: should be \"",
646 argv
[1], " interps\"", (char *) NULL
);
649 return TkGetInterpNames(interp
, tkwin
);
650 } else if ((c
== 'i') && (strncmp(argv
[1], "ismapped", length
) == 0)
653 interp
->result
= Tk_IsMapped(window
) ? "1" : "0";
654 } else if ((c
== 'n') && (strncmp(argv
[1], "name", length
) == 0)) {
656 interp
->result
= Tk_Name(window
);
657 } else if ((c
== 'p') && (strncmp(argv
[1], "parent", length
) == 0)) {
659 winPtr
= (TkWindow
*) window
;
660 if (winPtr
->parentPtr
!= NULL
) {
661 interp
->result
= winPtr
->parentPtr
->pathName
;
663 } else if ((c
== 'p') && (strncmp(argv
[1], "pathname", length
) == 0)
668 argName
= "pathname";
671 if (Tcl_GetInt(interp
, argv
[2], (int *) &id
) != TCL_OK
) {
674 if ((XFindContext(Tk_Display(tkwin
), id
, tkWindowContext
,
675 (void *) &window
) != 0) || (((TkWindow
*) window
)->mainPtr
676 != ((TkWindow
*) tkwin
)->mainPtr
)) {
677 Tcl_AppendResult(interp
, "window id \"", argv
[2],
678 "\" doesn't exist in this application", (char *) NULL
);
681 interp
->result
= Tk_PathName(window
);
682 } else if ((c
== 'p') && (strncmp(argv
[1], "pixels", length
) == 0)
687 Tcl_AppendResult(interp
, "wrong # args: should be \"",
688 argv
[0], " pixels window number\"", (char *) NULL
);
691 window
= Tk_NameToWindow(interp
, argv
[2], tkwin
);
692 if (window
== NULL
) {
695 if (Tk_GetPixels(interp
, window
, argv
[3], &pixels
) != TCL_OK
) {
698 sprintf(interp
->result
, "%d", pixels
);
699 } else if ((c
== 'r') && (strncmp(argv
[1], "reqheight", length
) == 0)
702 sprintf(interp
->result
, "%d", Tk_ReqHeight(window
));
703 } else if ((c
== 'r') && (strncmp(argv
[1], "reqwidth", length
) == 0)
706 sprintf(interp
->result
, "%d", Tk_ReqWidth(window
));
707 } else if ((c
== 'r') && (strcmp(argv
[1], "rootx") == 0)) {
711 Tk_GetRootCoords(window
, &x
, &y
);
712 sprintf(interp
->result
, "%d", x
);
713 } else if ((c
== 'r') && (strcmp(argv
[1], "rooty") == 0)) {
717 Tk_GetRootCoords(window
, &x
, &y
);
718 sprintf(interp
->result
, "%d", y
);
719 } else if ((c
== 's') && (strcmp(argv
[1], "screen") == 0)) {
723 sprintf(string
, "%d", Tk_ScreenNumber(window
));
724 Tcl_AppendResult(interp
, Tk_DisplayName(window
), ".", string
,
726 } else if ((c
== 's') && (strncmp(argv
[1], "screencells", length
) == 0)
728 SETUP("screencells");
729 sprintf(interp
->result
, "%d", Tk_DefaultVisual(Tk_Screen(window
))->map_entries
);
730 } else if ((c
== 's') && (strncmp(argv
[1], "screendepth", length
) == 0)
732 SETUP("screendepth");
733 sprintf(interp
->result
, "%d", Tk_DefaultDepth(Tk_Screen(window
)));
734 } else if ((c
== 's') && (strncmp(argv
[1], "screenheight", length
) == 0)
736 SETUP("screenheight");
737 sprintf(interp
->result
, "%d", HeightOfScreen(Tk_Screen(window
)));
738 } else if ((c
== 's') && (strncmp(argv
[1], "screenmmheight", length
) == 0)
740 SETUP("screenmmheight");
741 sprintf(interp
->result
, "%d", HeightMMOfScreen(Tk_Screen(window
)));
742 } else if ((c
== 's') && (strncmp(argv
[1], "screenmmwidth", length
) == 0)
744 SETUP("screenmmwidth");
745 sprintf(interp
->result
, "%d", WidthMMOfScreen(Tk_Screen(window
)));
746 } else if ((c
== 's') && (strncmp(argv
[1], "screenvisual", length
) == 0)
748 SETUP("screenvisual");
749 switch (Tk_DefaultVisual(Tk_Screen(window
))->class) {
750 case PseudoColor
: interp
->result
= "pseudocolor"; break;
751 case GrayScale
: interp
->result
= "grayscale"; break;
752 case DirectColor
: interp
->result
= "directcolor"; break;
753 case TrueColor
: interp
->result
= "truecolor"; break;
754 case StaticColor
: interp
->result
= "staticcolor"; break;
755 case StaticGray
: interp
->result
= "staticgray"; break;
756 default: interp
->result
= "unknown"; break;
758 } else if ((c
== 's') && (strncmp(argv
[1], "screenwidth", length
) == 0)
760 SETUP("screenwidth");
761 sprintf(interp
->result
, "%d", WidthOfScreen(Tk_Screen(window
)));
762 } else if ((c
== 's') && (strcmp(argv
[1], "server") == 0)) {
764 Tcl_AppendResult(interp
, Tk_DisplayName(window
), (char *) NULL
);
765 } else if ((c
== 't') && (strncmp(argv
[1], "toplevel", length
) == 0)) {
767 for (winPtr
= (TkWindow
*) window
; !(winPtr
->flags
& TK_TOP_LEVEL
);
768 winPtr
= winPtr
->parentPtr
) {
769 /* Empty loop body. */
771 interp
->result
= winPtr
->pathName
;
772 } else if ((c
== 'w') && (strncmp(argv
[1], "width", length
) == 0)) {
774 sprintf(interp
->result
, "%d", Tk_Width(window
));
775 } else if ((c
== 'x') && (argv
[1][1] == '\0')) {
777 sprintf(interp
->result
, "%d", Tk_X(window
));
778 } else if ((c
== 'y') && (argv
[1][1] == '\0')) {
780 sprintf(interp
->result
, "%d", Tk_Y(window
));
782 Tcl_AppendResult(interp
, "bad option \"", argv
[1],
783 "\": must be atom, atomname, children, class, fpixels, geometry, height, ",
784 "id, interps, ismapped, name, parent, pathname, ",
785 "pixels, reqheight, reqwidth, rootx, rooty, ",
786 "screen, screencells, screendepth, screenheight, ",
787 "screenmmheight, screenmmwidth, screenvisual, ",
788 "screenwidth, toplevel, width, x, or y", (char *) NULL
);
794 Tcl_AppendResult(interp
, "wrong # arguments: must be \"",
795 argv
[0], " ", argName
, " window\"", (char *) NULL
);
800 *----------------------------------------------------------------------
804 * If an application has been deleted then all Tk commands will be
805 * re-bound to this procedure.
808 * A standard Tcl error is reported to let the user know that
809 * the application is dead.
812 * See the user documentation.
814 *----------------------------------------------------------------------
820 ClientData clientData
, /* Dummy. */
821 Tcl_Interp
*interp
, /* Current interpreter. */
822 int argc
, /* Number of arguments. */
823 char **argv
/* Argument strings. */
826 Tcl_AppendResult(interp
, "can't invoke \"", argv
[0],
827 "\" command: application has been destroyed", (char *) NULL
);