]>
git.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 *----------------------------------------------------------------------
69 Tk_AfterCmd(clientData
, interp
, argc
, argv
)
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. */
81 Tcl_AppendResult(interp
, "wrong # args: should be \"",
82 argv
[0], " milliseconds ?command? ?arg arg ...?\"",
87 if ((Tcl_GetInt(interp
, argv
[1], &ms
) != TCL_OK
) || (ms
<= 0)) {
88 Tcl_AppendResult(interp
, "bad milliseconds value \"",
89 argv
[1], "\"", (char *) NULL
);
92 afterPtr
= (AfterInfo
*) ckalloc((unsigned) (sizeof(AfterInfo
)));
93 afterPtr
->interp
= interp
;
95 afterPtr
->command
= (char *) NULL
;
97 afterPtr
->donePtr
= &done
;
98 } else if (argc
== 3) {
99 afterPtr
->command
= (char *) ckalloc((unsigned) (strlen(argv
[2]) + 1));
100 strcpy(afterPtr
->command
, argv
[2]);
101 afterPtr
->donePtr
= (int *) NULL
;
103 afterPtr
->command
= Tcl_Concat(argc
-2, argv
+2);
104 afterPtr
->donePtr
= (int *) NULL
;
106 Tk_CreateTimerHandler(ms
, AfterProc
, (ClientData
) afterPtr
);
114 * Must reset interpreter result because it could have changed as
115 * part of events processed by Tk_DoOneEvent.
118 Tcl_ResetResult(interp
);
123 *----------------------------------------------------------------------
127 * Timer callback to execute commands registered with the
134 * Executes whatever command was specified. If the command
135 * returns an error, then the command "tkerror" is invoked
136 * to process the error; if tkerror fails then information
137 * about the error is output on stderr.
139 *----------------------------------------------------------------------
143 AfterProc(clientData
)
144 ClientData clientData
; /* Describes command to execute. */
146 AfterInfo
*afterPtr
= (AfterInfo
*) clientData
;
149 if (afterPtr
->command
!= NULL
) {
150 result
= Tcl_GlobalEval(afterPtr
->interp
, afterPtr
->command
);
151 if (result
!= TCL_OK
) {
152 TkBindError(afterPtr
->interp
);
154 ckfree(afterPtr
->command
);
156 if (afterPtr
->donePtr
!= NULL
) {
157 *afterPtr
->donePtr
= 1;
159 ckfree((char *) afterPtr
);
163 *----------------------------------------------------------------------
167 * This procedure is invoked to process the "bind" Tcl command.
168 * See the user documentation for details on what it does.
171 * A standard Tcl result.
174 * See the user documentation.
176 *----------------------------------------------------------------------
180 Tk_BindCmd(clientData
, interp
, argc
, argv
)
181 ClientData clientData
; /* Main window associated with
183 Tcl_Interp
*interp
; /* Current interpreter. */
184 int argc
; /* Number of arguments. */
185 char **argv
; /* Argument strings. */
187 Tk_Window tkwin
= (Tk_Window
) clientData
;
191 if ((argc
< 2) || (argc
> 4)) {
192 Tcl_AppendResult(interp
, "wrong # args: should be \"", argv
[0],
193 " window ?pattern? ?command?\"", (char *) NULL
);
196 if (argv
[1][0] == '.') {
197 winPtr
= (TkWindow
*) Tk_NameToWindow(interp
, argv
[1], tkwin
);
198 if (winPtr
== NULL
) {
201 object
= (ClientData
) winPtr
->pathName
;
203 winPtr
= (TkWindow
*) clientData
;
204 object
= (ClientData
) Tk_GetUid(argv
[1]);
211 if (argv
[3][0] == 0) {
212 return Tk_DeleteBinding(interp
, winPtr
->mainPtr
->bindingTable
,
215 if (argv
[3][0] == '+') {
219 mask
= Tk_CreateBinding(interp
, winPtr
->mainPtr
->bindingTable
,
220 object
, argv
[2], argv
[3], append
);
224 } else if (argc
== 3) {
227 command
= Tk_GetBinding(interp
, winPtr
->mainPtr
->bindingTable
,
229 if (command
== NULL
) {
230 Tcl_ResetResult(interp
);
233 interp
->result
= command
;
235 Tk_GetAllBindings(interp
, winPtr
->mainPtr
->bindingTable
, object
);
241 *----------------------------------------------------------------------
245 * This procedure is invoked by Tk_HandleEvent for each event; it
246 * causes any appropriate bindings for that event to be invoked.
252 * Depends on what bindings have been established with the "bind"
255 *----------------------------------------------------------------------
259 TkBindEventProc(winPtr
, eventPtr
)
260 TkWindow
*winPtr
; /* Pointer to info about window. */
261 XEvent
*eventPtr
; /* Information about event. */
263 ClientData objects
[3];
264 static Tk_Uid allUid
= NULL
;
266 if ((winPtr
->mainPtr
== NULL
) || (winPtr
->mainPtr
->bindingTable
== NULL
)) {
269 objects
[0] = (ClientData
) winPtr
->pathName
;
270 objects
[1] = (ClientData
) winPtr
->classUid
;
271 if (allUid
== NULL
) {
272 allUid
= Tk_GetUid("all");
274 objects
[2] = (ClientData
) allUid
;
275 Tk_BindEvent(winPtr
->mainPtr
->bindingTable
, eventPtr
,
276 (Tk_Window
) winPtr
, 3, objects
);
280 *----------------------------------------------------------------------
284 * This procedure is invoked to process the "destroy" Tcl command.
285 * See the user documentation for details on what it does.
288 * A standard Tcl result.
291 * See the user documentation.
293 *----------------------------------------------------------------------
297 Tk_DestroyCmd(clientData
, interp
, argc
, argv
)
298 ClientData clientData
; /* Main window associated with
300 Tcl_Interp
*interp
; /* Current interpreter. */
301 int argc
; /* Number of arguments. */
302 char **argv
; /* Argument strings. */
305 Tk_Window tkwin
= (Tk_Window
) clientData
;
308 Tcl_AppendResult(interp
, "wrong # args: should be \"",
309 argv
[0], " pathName\"", (char *) NULL
);
313 window
= Tk_NameToWindow(interp
, argv
[1], tkwin
);
314 if (window
== NULL
) {
317 Tk_DestroyWindow(window
);
322 *----------------------------------------------------------------------
326 * This procedure is invoked to process the "update" Tcl command.
327 * See the user documentation for details on what it does.
330 * A standard Tcl result.
333 * See the user documentation.
335 *----------------------------------------------------------------------
340 Tk_UpdateCmd(clientData
, interp
, argc
, argv
)
341 ClientData clientData
; /* Main window associated with
343 Tcl_Interp
*interp
; /* Current interpreter. */
344 int argc
; /* Number of arguments. */
345 char **argv
; /* Argument strings. */
347 Tk_Window tkwin
= (Tk_Window
) clientData
;
351 flags
= TK_DONT_WAIT
;
352 } else if (argc
== 2) {
353 if (strncmp(argv
[1], "idletasks", strlen(argv
[1])) != 0) {
354 Tcl_AppendResult(interp
, "bad argument \"", argv
[1],
355 "\": must be idletasks", (char *) NULL
);
358 flags
= TK_IDLE_EVENTS
;
360 Tcl_AppendResult(interp
, "wrong # args: should be \"",
361 argv
[0], " ?idletasks?\"", (char *) NULL
);
366 * Handle all pending events, sync the display, and repeat over
367 * and over again until all pending events have been handled.
371 while (Tk_DoOneEvent(flags
) != 0) {
372 /* Empty loop body */
374 XSync(Tk_Display(tkwin
), False
);
375 if (Tk_DoOneEvent(flags
) == 0) {
381 * Must clear the interpreter's result because event handlers could
382 * have executed commands.
385 Tcl_ResetResult(interp
);
390 *----------------------------------------------------------------------
394 * This procedure is invoked to process the "wait" Tcl command.
395 * See the user documentation for details on what it does.
398 * A standard Tcl result.
401 * See the user documentation.
403 *----------------------------------------------------------------------
408 Tk_TkwaitCmd(clientData
, interp
, argc
, argv
)
409 ClientData clientData
; /* Main window associated with
411 Tcl_Interp
*interp
; /* Current interpreter. */
412 int argc
; /* Number of arguments. */
413 char **argv
; /* Argument strings. */
415 Tk_Window tkwin
= (Tk_Window
) clientData
;
420 Tcl_AppendResult(interp
, "wrong # args: should be \"",
421 argv
[0], " variable|window name\"", (char *) NULL
);
425 length
= strlen(argv
[1]);
426 if ((c
== 'v') && (strncmp(argv
[1], "variable", length
) == 0)) {
427 Tcl_TraceVar(interp
, argv
[2],
428 TCL_GLOBAL_ONLY
|TCL_TRACE_WRITES
|TCL_TRACE_UNSETS
,
429 WaitVariableProc
, (ClientData
) &done
);
434 Tcl_UntraceVar(interp
, argv
[2],
435 TCL_GLOBAL_ONLY
|TCL_TRACE_WRITES
|TCL_TRACE_UNSETS
,
436 WaitVariableProc
, (ClientData
) &done
);
437 } else if ((c
== 'w') && (strncmp(argv
[1], "window", length
) == 0)) {
440 window
= Tk_NameToWindow(interp
, argv
[2], tkwin
);
441 if (window
== NULL
) {
444 Tk_CreateEventHandler(window
, StructureNotifyMask
,
445 WaitWindowProc
, (ClientData
) &done
);
450 Tk_DeleteEventHandler(window
, StructureNotifyMask
,
451 WaitWindowProc
, (ClientData
) &done
);
453 Tcl_AppendResult(interp
, "bad option \"", argv
[1],
454 "\": must be variable or window", (char *) NULL
);
459 * Clear out the interpreter's result, since it may have been set
463 Tcl_ResetResult(interp
);
469 WaitVariableProc(clientData
, interp
, name1
, name2
, flags
)
470 ClientData clientData
; /* Pointer to integer to set to 1. */
471 Tcl_Interp
*interp
; /* Interpreter containing variable. */
472 char *name1
; /* Name of variable. */
473 char *name2
; /* Second part of variable name. */
474 int flags
; /* Information about what happened. */
476 int *donePtr
= (int *) clientData
;
479 return (char *) NULL
;
483 WaitWindowProc(clientData
, eventPtr
)
484 ClientData clientData
; /* Pointer to integer to set to 1. */
485 XEvent
*eventPtr
; /* Information about event. */
487 int *donePtr
= (int *) clientData
;
489 if (eventPtr
->type
== DestroyNotify
) {
495 *----------------------------------------------------------------------
499 * This procedure is invoked to process the "winfo" Tcl command.
500 * See the user documentation for details on what it does.
503 * A standard Tcl result.
506 * See the user documentation.
508 *----------------------------------------------------------------------
512 Tk_WinfoCmd(clientData
, interp
, argc
, argv
)
513 ClientData clientData
; /* Main window associated with
515 Tcl_Interp
*interp
; /* Current interpreter. */
516 int argc
; /* Number of arguments. */
517 char **argv
; /* Argument strings. */
519 Tk_Window tkwin
= (Tk_Window
) clientData
;
523 register TkWindow
*winPtr
;
525 #define SETUP(name) \
530 window = Tk_NameToWindow(interp, argv[2], tkwin); \
531 if (window == NULL) { \
536 Tcl_AppendResult(interp
, "wrong # args: should be \"",
537 argv
[0], " option ?arg?\"", (char *) NULL
);
541 length
= strlen(argv
[1]);
542 if ((c
== 'a') && (strcmp(argv
[1], "atom") == 0)) {
544 Tcl_AppendResult(interp
, "wrong # args: should be \"",
545 argv
[0], " atom name\"", (char *) NULL
);
548 sprintf(interp
->result
, "%d", Tk_InternAtom(tkwin
, argv
[2]));
549 } else if ((c
== 'a') && (strncmp(argv
[1], "atomname", length
) == 0)
555 Tcl_AppendResult(interp
, "wrong # args: should be \"",
556 argv
[0], " atomname id\"", (char *) NULL
);
559 if (Tcl_GetInt(interp
, argv
[2], (int *) &atom
) != TCL_OK
) {
562 name
= Tk_GetAtomName(tkwin
, atom
);
563 if (strcmp(name
, "?bad atom?") == 0) {
564 Tcl_AppendResult(interp
, "no atom exists with id \"",
565 argv
[2], "\"", (char *) NULL
);
568 interp
->result
= name
;
569 } else if ((c
== 'c') && (strncmp(argv
[1], "children", length
) == 0)
571 char *separator
, *childName
;
575 for (winPtr
= ((TkWindow
*) window
)->childList
; winPtr
!= NULL
;
576 winPtr
= winPtr
->nextPtr
) {
577 childName
= Tcl_Merge(1, &winPtr
->pathName
);
578 Tcl_AppendResult(interp
, separator
, childName
, (char *) NULL
);
582 } else if ((c
== 'c') && (strncmp(argv
[1], "class", length
) == 0)
585 interp
->result
= Tk_Class(window
);
586 } else if ((c
== 'c') && (strncmp(argv
[1], "containing", length
) == 0)
591 Tcl_AppendResult(interp
, "wrong # args: should be \"",
592 argv
[0], " containing rootX rootY\"", (char *) NULL
);
595 if ((Tk_GetPixels(interp
, tkwin
, argv
[2], &rootX
) != TCL_OK
)
596 || (Tk_GetPixels(interp
, tkwin
, argv
[3], &rootY
) != TCL_OK
)) {
599 window
= Tk_CoordsToWindow(rootX
, rootY
, tkwin
);
600 if (window
!= NULL
) {
601 interp
->result
= Tk_PathName(window
);
603 } else if ((c
== 'f') && (strncmp(argv
[1], "fpixels", length
) == 0)
608 Tcl_AppendResult(interp
, "wrong # args: should be \"",
609 argv
[0], " fpixels window number\"", (char *) NULL
);
612 window
= Tk_NameToWindow(interp
, argv
[2], tkwin
);
613 if (window
== NULL
) {
616 if (Tk_GetScreenMM(interp
, window
, argv
[3], &mm
) != TCL_OK
) {
619 pixels
= mm
* WidthOfScreen(Tk_Screen(window
))
620 / WidthMMOfScreen(Tk_Screen(window
));
621 sprintf(interp
->result
, "%g", pixels
);
622 } else if ((c
== 'g') && (strncmp(argv
[1], "geometry", length
) == 0)) {
624 sprintf(interp
->result
, "%dx%d+%d+%d", Tk_Width(window
),
625 Tk_Height(window
), Tk_X(window
), Tk_Y(window
));
626 } else if ((c
== 'h') && (strncmp(argv
[1], "height", length
) == 0)) {
628 sprintf(interp
->result
, "%d", Tk_Height(window
));
629 } else if ((c
== 'i') && (strcmp(argv
[1], "id") == 0)) {
631 sprintf(interp
->result
, "0x%x", Tk_WindowId(window
));
632 } else if ((c
== 'i') && (strncmp(argv
[1], "interps", length
) == 0)
635 Tcl_AppendResult(interp
, "wrong # args: should be \"",
636 argv
[1], " interps\"", (char *) NULL
);
639 return TkGetInterpNames(interp
, tkwin
);
640 } else if ((c
== 'i') && (strncmp(argv
[1], "ismapped", length
) == 0)
643 interp
->result
= Tk_IsMapped(window
) ? "1" : "0";
644 } else if ((c
== 'n') && (strncmp(argv
[1], "name", length
) == 0)) {
646 interp
->result
= Tk_Name(window
);
647 } else if ((c
== 'p') && (strncmp(argv
[1], "parent", length
) == 0)) {
649 winPtr
= (TkWindow
*) window
;
650 if (winPtr
->parentPtr
!= NULL
) {
651 interp
->result
= winPtr
->parentPtr
->pathName
;
653 } else if ((c
== 'p') && (strncmp(argv
[1], "pathname", length
) == 0)
658 argName
= "pathname";
661 if (Tcl_GetInt(interp
, argv
[2], (int *) &id
) != TCL_OK
) {
664 if ((XFindContext(Tk_Display(tkwin
), id
, tkWindowContext
,
665 (void *) &window
) != 0) || (((TkWindow
*) window
)->mainPtr
666 != ((TkWindow
*) tkwin
)->mainPtr
)) {
667 Tcl_AppendResult(interp
, "window id \"", argv
[2],
668 "\" doesn't exist in this application", (char *) NULL
);
671 interp
->result
= Tk_PathName(window
);
672 } else if ((c
== 'p') && (strncmp(argv
[1], "pixels", length
) == 0)
677 Tcl_AppendResult(interp
, "wrong # args: should be \"",
678 argv
[0], " pixels window number\"", (char *) NULL
);
681 window
= Tk_NameToWindow(interp
, argv
[2], tkwin
);
682 if (window
== NULL
) {
685 if (Tk_GetPixels(interp
, window
, argv
[3], &pixels
) != TCL_OK
) {
688 sprintf(interp
->result
, "%d", pixels
);
689 } else if ((c
== 'r') && (strncmp(argv
[1], "reqheight", length
) == 0)
692 sprintf(interp
->result
, "%d", Tk_ReqHeight(window
));
693 } else if ((c
== 'r') && (strncmp(argv
[1], "reqwidth", length
) == 0)
696 sprintf(interp
->result
, "%d", Tk_ReqWidth(window
));
697 } else if ((c
== 'r') && (strcmp(argv
[1], "rootx") == 0)) {
701 Tk_GetRootCoords(window
, &x
, &y
);
702 sprintf(interp
->result
, "%d", x
);
703 } else if ((c
== 'r') && (strcmp(argv
[1], "rooty") == 0)) {
707 Tk_GetRootCoords(window
, &x
, &y
);
708 sprintf(interp
->result
, "%d", y
);
709 } else if ((c
== 's') && (strcmp(argv
[1], "screen") == 0)) {
713 sprintf(string
, "%d", Tk_ScreenNumber(window
));
714 Tcl_AppendResult(interp
, Tk_DisplayName(window
), ".", string
,
716 } else if ((c
== 's') && (strncmp(argv
[1], "screencells", length
) == 0)
718 SETUP("screencells");
719 sprintf(interp
->result
, "%d", Tk_DefaultVisual(Tk_Screen(window
))->map_entries
);
720 } else if ((c
== 's') && (strncmp(argv
[1], "screendepth", length
) == 0)
722 SETUP("screendepth");
723 sprintf(interp
->result
, "%d", Tk_DefaultDepth(Tk_Screen(window
)));
724 } else if ((c
== 's') && (strncmp(argv
[1], "screenheight", length
) == 0)
726 SETUP("screenheight");
727 sprintf(interp
->result
, "%d", HeightOfScreen(Tk_Screen(window
)));
728 } else if ((c
== 's') && (strncmp(argv
[1], "screenmmheight", length
) == 0)
730 SETUP("screenmmheight");
731 sprintf(interp
->result
, "%d", HeightMMOfScreen(Tk_Screen(window
)));
732 } else if ((c
== 's') && (strncmp(argv
[1], "screenmmwidth", length
) == 0)
734 SETUP("screenmmwidth");
735 sprintf(interp
->result
, "%d", WidthMMOfScreen(Tk_Screen(window
)));
736 } else if ((c
== 's') && (strncmp(argv
[1], "screenvisual", length
) == 0)
738 SETUP("screenvisual");
739 switch (Tk_DefaultVisual(Tk_Screen(window
))->class) {
740 case PseudoColor
: interp
->result
= "pseudocolor"; break;
741 case GrayScale
: interp
->result
= "grayscale"; break;
742 case DirectColor
: interp
->result
= "directcolor"; break;
743 case TrueColor
: interp
->result
= "truecolor"; break;
744 case StaticColor
: interp
->result
= "staticcolor"; break;
745 case StaticGray
: interp
->result
= "staticgray"; break;
746 default: interp
->result
= "unknown"; break;
748 } else if ((c
== 's') && (strncmp(argv
[1], "screenwidth", length
) == 0)
750 SETUP("screenwidth");
751 sprintf(interp
->result
, "%d", WidthOfScreen(Tk_Screen(window
)));
752 } else if ((c
== 's') && (strcmp(argv
[1], "server") == 0)) {
754 Tcl_AppendResult(interp
, Tk_DisplayName(window
), (char *) NULL
);
755 } else if ((c
== 't') && (strncmp(argv
[1], "toplevel", length
) == 0)) {
757 for (winPtr
= (TkWindow
*) window
; !(winPtr
->flags
& TK_TOP_LEVEL
);
758 winPtr
= winPtr
->parentPtr
) {
759 /* Empty loop body. */
761 interp
->result
= winPtr
->pathName
;
762 } else if ((c
== 'w') && (strncmp(argv
[1], "width", length
) == 0)) {
764 sprintf(interp
->result
, "%d", Tk_Width(window
));
765 } else if ((c
== 'x') && (argv
[1][1] == '\0')) {
767 sprintf(interp
->result
, "%d", Tk_X(window
));
768 } else if ((c
== 'y') && (argv
[1][1] == '\0')) {
770 sprintf(interp
->result
, "%d", Tk_Y(window
));
772 Tcl_AppendResult(interp
, "bad option \"", argv
[1],
773 "\": must be atom, atomname, children, class, fpixels, geometry, height, ",
774 "id, interps, ismapped, name, parent, pathname, ",
775 "pixels, reqheight, reqwidth, rootx, rooty, ",
776 "screen, screencells, screendepth, screenheight, ",
777 "screenmmheight, screenmmwidth, screenvisual, ",
778 "screenwidth, toplevel, width, x, or y", (char *) NULL
);
784 Tcl_AppendResult(interp
, "wrong # arguments: must be \"",
785 argv
[0], " ", argName
, " window\"", (char *) NULL
);
790 *----------------------------------------------------------------------
794 * If an application has been deleted then all Tk commands will be
795 * re-bound to this procedure.
798 * A standard Tcl error is reported to let the user know that
799 * the application is dead.
802 * See the user documentation.
804 *----------------------------------------------------------------------
809 TkDeadAppCmd(clientData
, interp
, argc
, argv
)
810 ClientData clientData
; /* Dummy. */
811 Tcl_Interp
*interp
; /* Current interpreter. */
812 int argc
; /* Number of arguments. */
813 char **argv
; /* Argument strings. */
815 Tcl_AppendResult(interp
, "can't invoke \"", argv
[0],
816 "\" command: application has been destroyed", (char *) NULL
);