]>
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
) {
503 static int LegacyMode
= 0;
506 Tk_WinfoCmdSetLegacy (
507 ClientData clientData
, /* Main window associated with
509 Tcl_Interp
*interp
, /* Current interpreter. */
510 int argc
, /* Number of arguments. */
511 char **argv
/* Argument strings. */
520 *----------------------------------------------------------------------
524 * This procedure is invoked to process the "winfo" Tcl command.
525 * See the user documentation for details on what it does.
528 * A standard Tcl result.
531 * See the user documentation.
533 *----------------------------------------------------------------------
538 ClientData clientData
, /* Main window associated with
540 Tcl_Interp
*interp
, /* Current interpreter. */
541 int argc
, /* Number of arguments. */
542 char **argv
/* Argument strings. */
545 Tk_Window tkwin
= (Tk_Window
) clientData
;
549 register TkWindow
*winPtr
;
551 #define SETUP(name) \
556 window = Tk_NameToWindow(interp, argv[2], tkwin); \
557 if (window == NULL) { \
562 Tcl_AppendResult(interp
, "wrong # args: should be \"",
563 argv
[0], " option ?arg?\"", (char *) NULL
);
567 length
= strlen(argv
[1]);
568 if ((c
== 'a') && (strcmp(argv
[1], "atom") == 0)) {
570 Tcl_AppendResult(interp
, "wrong # args: should be \"",
571 argv
[0], " atom name\"", (char *) NULL
);
574 sprintf(interp
->result
, "%d", Tk_InternAtom(tkwin
, argv
[2]));
575 } else if ((c
== 'a') && (strncmp(argv
[1], "atomname", length
) == 0)
581 Tcl_AppendResult(interp
, "wrong # args: should be \"",
582 argv
[0], " atomname id\"", (char *) NULL
);
585 if (Tcl_GetInt(interp
, argv
[2], (int *) &atom
) != TCL_OK
) {
588 name
= Tk_GetAtomName(tkwin
, atom
);
589 if (strcmp(name
, "?bad atom?") == 0) {
590 Tcl_AppendResult(interp
, "no atom exists with id \"",
591 argv
[2], "\"", (char *) NULL
);
594 interp
->result
= name
;
595 } else if ((c
== 'c') && (strncmp(argv
[1], "children", length
) == 0)
597 char *separator
, *childName
;
601 for (winPtr
= ((TkWindow
*) window
)->childList
; winPtr
!= NULL
;
602 winPtr
= winPtr
->nextPtr
) {
603 childName
= Tcl_Merge(1, &winPtr
->pathName
);
604 Tcl_AppendResult(interp
, separator
, childName
, (char *) NULL
);
608 } else if ((c
== 'c') && (strncmp(argv
[1], "class", length
) == 0)
611 interp
->result
= Tk_Class(window
);
612 } else if ((c
== 'c') && (strncmp(argv
[1], "containing", length
) == 0)
617 Tcl_AppendResult(interp
, "wrong # args: should be \"",
618 argv
[0], " containing rootX rootY\"", (char *) NULL
);
621 if ((Tk_GetPixels(interp
, tkwin
, argv
[2], &rootX
) != TCL_OK
)
622 || (Tk_GetPixels(interp
, tkwin
, argv
[3], &rootY
) != TCL_OK
)) {
625 window
= Tk_CoordsToWindow(rootX
, rootY
, tkwin
);
626 if (window
!= NULL
) {
627 interp
->result
= Tk_PathName(window
);
629 } else if ((c
== 'f') && (strncmp(argv
[1], "fpixels", length
) == 0)
634 Tcl_AppendResult(interp
, "wrong # args: should be \"",
635 argv
[0], " fpixels window number\"", (char *) NULL
);
638 window
= Tk_NameToWindow(interp
, argv
[2], tkwin
);
639 if (window
== NULL
) {
642 if (Tk_GetScreenMM(interp
, window
, argv
[3], &mm
) != TCL_OK
) {
645 pixels
= mm
* WidthOfScreen(Tk_Screen(window
))
646 / WidthMMOfScreen(Tk_Screen(window
));
647 sprintf(interp
->result
, "%g", pixels
);
648 } else if ((c
== 'g') && (strncmp(argv
[1], "geometry", length
) == 0)) {
650 sprintf(interp
->result
, "%dx%d+%d+%d", Tk_Width(window
),
651 Tk_Height(window
), Tk_X(window
), Tk_Y(window
));
652 } else if ((c
== 'h') && (strncmp(argv
[1], "height", length
) == 0)) {
654 sprintf(interp
->result
, "%d", Tk_Height(window
));
655 } else if ((c
== 'i') && (strcmp(argv
[1], "id") == 0)) {
657 sprintf(interp
->result
, "0x%x", Tk_WindowId(window
));
658 } else if ((c
== 'i') && (strncmp(argv
[1], "interps", length
) == 0)
661 Tcl_AppendResult(interp
, "wrong # args: should be \"",
662 argv
[1], " interps\"", (char *) NULL
);
665 return TkGetInterpNames(interp
, tkwin
);
666 } else if ((c
== 'i') && (strncmp(argv
[1], "ismapped", length
) == 0)
669 interp
->result
= Tk_IsMapped(window
) ? "1" : "0";
670 } else if ((c
== 'n') && (strncmp(argv
[1], "name", length
) == 0)) {
672 interp
->result
= Tk_Name(window
);
673 } else if ((c
== 'p') && (strncmp(argv
[1], "parent", length
) == 0)) {
675 winPtr
= (TkWindow
*) window
;
676 if (winPtr
->parentPtr
!= NULL
) {
677 interp
->result
= winPtr
->parentPtr
->pathName
;
679 } else if ((c
== 'p') && (strncmp(argv
[1], "pathname", length
) == 0)
684 argName
= "pathname";
687 if (Tcl_GetInt(interp
, argv
[2], (int *) &id
) != TCL_OK
) {
690 if ((XFindContext(Tk_Display(tkwin
), id
, tkWindowContext
,
691 (void *) &window
) != 0) || (((TkWindow
*) window
)->mainPtr
692 != ((TkWindow
*) tkwin
)->mainPtr
)) {
693 Tcl_AppendResult(interp
, "window id \"", argv
[2],
694 "\" doesn't exist in this application", (char *) NULL
);
697 interp
->result
= Tk_PathName(window
);
698 } else if ((c
== 'p') && (strncmp(argv
[1], "pixels", length
) == 0)
703 Tcl_AppendResult(interp
, "wrong # args: should be \"",
704 argv
[0], " pixels window number\"", (char *) NULL
);
707 window
= Tk_NameToWindow(interp
, argv
[2], tkwin
);
708 if (window
== NULL
) {
711 if (Tk_GetPixels(interp
, window
, argv
[3], &pixels
) != TCL_OK
) {
714 sprintf(interp
->result
, "%d", pixels
);
715 } else if ((c
== 'r') && (strncmp(argv
[1], "reqheight", length
) == 0)
718 sprintf(interp
->result
, "%d", Tk_ReqHeight(window
));
719 } else if ((c
== 'r') && (strncmp(argv
[1], "reqwidth", length
) == 0)
722 sprintf(interp
->result
, "%d", Tk_ReqWidth(window
));
723 } else if ((c
== 'r') && (strcmp(argv
[1], "rootx") == 0)) {
727 Tk_GetRootCoords(window
, &x
, &y
);
728 sprintf(interp
->result
, "%d", x
);
729 } else if ((c
== 'r') && (strcmp(argv
[1], "rooty") == 0)) {
733 Tk_GetRootCoords(window
, &x
, &y
);
734 sprintf(interp
->result
, "%d", y
);
735 } else if ((c
== 's') && (strcmp(argv
[1], "screen") == 0)) {
739 sprintf(string
, "%d", Tk_ScreenNumber(window
));
740 Tcl_AppendResult(interp
, Tk_DisplayName(window
), ".", string
,
742 } else if ((c
== 's') && (strncmp(argv
[1], "screencells", length
) == 0)
744 SETUP("screencells");
745 sprintf(interp
->result
, "%d", Tk_DefaultVisual(Tk_Screen(window
))->map_entries
);
746 } else if ((c
== 's') && (strncmp(argv
[1], "screendepth", length
) == 0)
748 SETUP("screendepth");
749 sprintf(interp
->result
, "%d", Tk_DefaultDepth(Tk_Screen(window
)));
750 } else if ((c
== 's') && (strncmp(argv
[1], "screenheight", length
) == 0)
752 SETUP("screenheight");
753 sprintf(interp
->result
, "%d", HeightOfScreen(Tk_Screen(window
)));
754 } else if ((c
== 's') && (strncmp(argv
[1], "screenmmheight", length
) == 0)
756 SETUP("screenmmheight");
757 sprintf(interp
->result
, "%d", HeightMMOfScreen(Tk_Screen(window
)));
758 } else if ((c
== 's') && (strncmp(argv
[1], "screenmmwidth", length
) == 0)
760 SETUP("screenmmwidth");
761 sprintf(interp
->result
, "%d", WidthMMOfScreen(Tk_Screen(window
)));
762 } else if ((c
== 's') && (strncmp(argv
[1], "screenvisual", length
) == 0)
764 SETUP("screenvisual");
765 switch (Tk_DefaultVisual(Tk_Screen(window
))->class) {
766 case PseudoColor
: interp
->result
= "pseudocolor"; break;
767 case GrayScale
: interp
->result
= "grayscale"; break;
768 case DirectColor
: interp
->result
= "directcolor"; break;
769 case TrueColor
: interp
->result
= LegacyMode
?"pseudocolor":"truecolor"; break;
770 case StaticColor
: interp
->result
= "staticcolor"; break;
771 case StaticGray
: interp
->result
= "staticgray"; break;
772 default: interp
->result
= "unknown"; break;
774 } else if ((c
== 's') && (strncmp(argv
[1], "screenwidth", length
) == 0)
776 SETUP("screenwidth");
777 sprintf(interp
->result
, "%d", WidthOfScreen(Tk_Screen(window
)));
778 } else if ((c
== 's') && (strcmp(argv
[1], "server") == 0)) {
780 Tcl_AppendResult(interp
, Tk_DisplayName(window
), (char *) NULL
);
781 } else if ((c
== 't') && (strncmp(argv
[1], "toplevel", length
) == 0)) {
783 for (winPtr
= (TkWindow
*) window
; !(winPtr
->flags
& TK_TOP_LEVEL
);
784 winPtr
= winPtr
->parentPtr
) {
785 /* Empty loop body. */
787 interp
->result
= winPtr
->pathName
;
788 } else if ((c
== 'w') && (strncmp(argv
[1], "width", length
) == 0)) {
790 sprintf(interp
->result
, "%d", Tk_Width(window
));
791 } else if ((c
== 'x') && (argv
[1][1] == '\0')) {
793 sprintf(interp
->result
, "%d", Tk_X(window
));
794 } else if ((c
== 'y') && (argv
[1][1] == '\0')) {
796 sprintf(interp
->result
, "%d", Tk_Y(window
));
798 Tcl_AppendResult(interp
, "bad option \"", argv
[1],
799 "\": must be atom, atomname, children, class, fpixels, geometry, height, ",
800 "id, interps, ismapped, name, parent, pathname, ",
801 "pixels, reqheight, reqwidth, rootx, rooty, ",
802 "screen, screencells, screendepth, screenheight, ",
803 "screenmmheight, screenmmwidth, screenvisual, ",
804 "screenwidth, toplevel, width, x, or y", (char *) NULL
);
810 Tcl_AppendResult(interp
, "wrong # arguments: must be \"",
811 argv
[0], " ", argName
, " window\"", (char *) NULL
);
816 *----------------------------------------------------------------------
820 * If an application has been deleted then all Tk commands will be
821 * re-bound to this procedure.
824 * A standard Tcl error is reported to let the user know that
825 * the application is dead.
828 * See the user documentation.
830 *----------------------------------------------------------------------
836 ClientData clientData
, /* Dummy. */
837 Tcl_Interp
*interp
, /* Current interpreter. */
838 int argc
, /* Number of arguments. */
839 char **argv
/* Argument strings. */
842 Tcl_AppendResult(interp
, "can't invoke \"", argv
[0],
843 "\" command: application has been destroyed", (char *) NULL
);