1 /*
2 * tkCmds.c --
3 *
4 * This file contains a collection of Tk-related Tcl commands
5 * that didn't fit in any particular file of the toolkit.
6 *
7 * Copyright (c) 1990-1994 The Regents of the University of California.
8 * Copyright (c) 1994-1996 Sun Microsystems, Inc.
9 *
10 * See the file "license.terms" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12 *
13 * SCCS: @(#) tkCmds.c 1.110 96/04/03 15:54:47
14 */
15
16 #include "tkInt.h"
17 #include <errno.h>
18
19 /*
20 * Forward declarations for procedures defined later in this file:
21 */
22
23 static Tk_Window GetDisplayOf _ANSI_ARGS_((Tcl_Interp *interp,
24 Tk_Window tkwin, char **argv));
25 static TkWindow * GetToplevel _ANSI_ARGS_((Tk_Window tkwin));
26 static char * WaitVariableProc _ANSI_ARGS_((ClientData clientData,
27 Tcl_Interp *interp, char *name1, char *name2,
28 int flags));
29 static void WaitVisibilityProc _ANSI_ARGS_((ClientData clientData,
30 XEvent *eventPtr));
31 static void WaitWindowProc _ANSI_ARGS_((ClientData clientData,
32 XEvent *eventPtr));
33
34 /*
35 *----------------------------------------------------------------------
36 *
37 * Tk_BellCmd --
38 *
39 * This procedure is invoked to process the "bell" Tcl command.
40 * See the user documentation for details on what it does.
41 *
42 * Results:
43 * A standard Tcl result.
44 *
45 * Side effects:
46 * See the user documentation.
47 *
48 *----------------------------------------------------------------------
49 */
50
51 int
Tk_BellCmd(clientData,interp,argc,argv)52 Tk_BellCmd(clientData, interp, argc, argv)
53 ClientData clientData; /* Main window associated with interpreter. */
54 Tcl_Interp *interp; /* Current interpreter. */
55 int argc; /* Number of arguments. */
56 char **argv; /* Argument strings. */
57 {
58 Tk_Window tkwin = (Tk_Window) clientData;
59 size_t length;
60
61 if ((argc != 1) && (argc != 3)) {
62 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
63 " ?-displayof window?\"", (char *) NULL);
64 return TCL_ERROR;
65 }
66
67 if (argc == 3) {
68 length = strlen(argv[1]);
69 if ((length < 2) || (strncmp(argv[1], "-displayof", length) != 0)) {
70 Tcl_AppendResult(interp, "bad option \"", argv[1],
71 "\": must be -displayof", (char *) NULL);
72 return TCL_ERROR;
73 }
74 tkwin = Tk_NameToWindow(interp, argv[2], tkwin);
75 if (tkwin == NULL) {
76 return TCL_ERROR;
77 }
78 }
79 XBell(Tk_Display(tkwin), 0);
80 XForceScreenSaver(Tk_Display(tkwin), ScreenSaverReset);
81 XFlush(Tk_Display(tkwin));
82 return TCL_OK;
83 }
84
85 /*
86 *----------------------------------------------------------------------
87 *
88 * Tk_BindCmd --
89 *
90 * This procedure is invoked to process the "bind" Tcl command.
91 * See the user documentation for details on what it does.
92 *
93 * Results:
94 * A standard Tcl result.
95 *
96 * Side effects:
97 * See the user documentation.
98 *
99 *----------------------------------------------------------------------
100 */
101
102 int
Tk_BindCmd(clientData,interp,argc,argv)103 Tk_BindCmd(clientData, interp, argc, argv)
104 ClientData clientData; /* Main window associated with interpreter. */
105 Tcl_Interp *interp; /* Current interpreter. */
106 int argc; /* Number of arguments. */
107 char **argv; /* Argument strings. */
108 {
109 Tk_Window tkwin = (Tk_Window) clientData;
110 TkWindow *winPtr;
111 ClientData object;
112
113 if ((argc < 2) || (argc > 4)) {
114 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
115 " window ?pattern? ?command?\"", (char *) NULL);
116 return TCL_ERROR;
117 }
118 if (argv[1][0] == '.') {
119 winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[1], tkwin);
120 if (winPtr == NULL) {
121 return TCL_ERROR;
122 }
123 object = (ClientData) winPtr->pathName;
124 } else {
125 winPtr = (TkWindow *) clientData;
126 object = (ClientData) Tk_GetUid(argv[1]);
127 }
128
129 if (argc == 4) {
130 int append = 0;
131 unsigned long mask;
132
133 if (argv[3][0] == 0) {
134 return Tk_DeleteBinding(interp, winPtr->mainPtr->bindingTable,
135 object, argv[2]);
136 }
137 if (argv[3][0] == '+') {
138 argv[3]++;
139 append = 1;
140 }
141 mask = Tk_CreateBinding(interp, winPtr->mainPtr->bindingTable,
142 object, argv[2], argv[3], append);
143 if (mask == 0) {
144 return TCL_ERROR;
145 }
146 } else if (argc == 3) {
147 char *command;
148
149 command = Tk_GetBinding(interp, winPtr->mainPtr->bindingTable,
150 object, argv[2]);
151 if (command == NULL) {
152 Tcl_ResetResult(interp);
153 return TCL_OK;
154 }
155 interp->result = command;
156 } else {
157 Tk_GetAllBindings(interp, winPtr->mainPtr->bindingTable, object);
158 }
159 return TCL_OK;
160 }
161
162 /*
163 *----------------------------------------------------------------------
164 *
165 * TkBindEventProc --
166 *
167 * This procedure is invoked by Tk_HandleEvent for each event; it
168 * causes any appropriate bindings for that event to be invoked.
169 *
170 * Results:
171 * None.
172 *
173 * Side effects:
174 * Depends on what bindings have been established with the "bind"
175 * command.
176 *
177 *----------------------------------------------------------------------
178 */
179
180 void
TkBindEventProc(winPtr,eventPtr)181 TkBindEventProc(winPtr, eventPtr)
182 TkWindow *winPtr; /* Pointer to info about window. */
183 XEvent *eventPtr; /* Information about event. */
184 {
185 #define MAX_OBJS 20
186 ClientData objects[MAX_OBJS], *objPtr;
187 static Tk_Uid allUid = NULL;
188 TkWindow *topLevPtr;
189 int i, count;
190 char *p;
191 Tcl_HashEntry *hPtr;
192
193 if ((winPtr->mainPtr == NULL) || (winPtr->mainPtr->bindingTable == NULL)) {
194 return;
195 }
196
197 objPtr = objects;
198 if (winPtr->numTags != 0) {
199 /*
200 * Make a copy of the tags for the window, replacing window names
201 * with pointers to the pathName from the appropriate window.
202 */
203
204 if (winPtr->numTags > MAX_OBJS) {
205 objPtr = (ClientData *) ckalloc((unsigned)
206 (winPtr->numTags * sizeof(ClientData)));
207 }
208 for (i = 0; i < winPtr->numTags; i++) {
209 p = (char *) winPtr->tagPtr[i];
210 if (*p == '.') {
211 hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->nameTable, p);
212 if (hPtr != NULL) {
213 p = ((TkWindow *) Tcl_GetHashValue(hPtr))->pathName;
214 } else {
215 p = NULL;
216 }
217 }
218 objPtr[i] = (ClientData) p;
219 }
220 count = winPtr->numTags;
221 } else {
222 objPtr[0] = (ClientData) winPtr->pathName;
223 objPtr[1] = (ClientData) winPtr->classUid;
224 for (topLevPtr = winPtr;
225 (topLevPtr != NULL) && !(topLevPtr->flags & TK_TOP_LEVEL);
226 topLevPtr = topLevPtr->parentPtr) {
227 /* Empty loop body. */
228 }
229 if ((winPtr != topLevPtr) && (topLevPtr != NULL)) {
230 count = 4;
231 objPtr[2] = (ClientData) topLevPtr->pathName;
232 } else {
233 count = 3;
234 }
235 if (allUid == NULL) {
236 allUid = Tk_GetUid("all");
237 }
238 objPtr[count-1] = (ClientData) allUid;
239 }
240 Tk_BindEvent(winPtr->mainPtr->bindingTable, eventPtr, (Tk_Window) winPtr,
241 count, objPtr);
242 if (objPtr != objects) {
243 ckfree((char *) objPtr);
244 }
245 }
246
247 /*
248 *----------------------------------------------------------------------
249 *
250 * Tk_BindtagsCmd --
251 *
252 * This procedure is invoked to process the "bindtags" Tcl command.
253 * See the user documentation for details on what it does.
254 *
255 * Results:
256 * A standard Tcl result.
257 *
258 * Side effects:
259 * See the user documentation.
260 *
261 *----------------------------------------------------------------------
262 */
263
264 int
Tk_BindtagsCmd(clientData,interp,argc,argv)265 Tk_BindtagsCmd(clientData, interp, argc, argv)
266 ClientData clientData; /* Main window associated with interpreter. */
267 Tcl_Interp *interp; /* Current interpreter. */
268 int argc; /* Number of arguments. */
269 char **argv; /* Argument strings. */
270 {
271 Tk_Window tkwin = (Tk_Window) clientData;
272 TkWindow *winPtr, *winPtr2;
273 int i, tagArgc;
274 char *p, **tagArgv;
275
276 if ((argc < 2) || (argc > 3)) {
277 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
278 " window ?tags?\"", (char *) NULL);
279 return TCL_ERROR;
280 }
281 winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[1], tkwin);
282 if (winPtr == NULL) {
283 return TCL_ERROR;
284 }
285 if (argc == 2) {
286 if (winPtr->numTags == 0) {
287 Tcl_AppendElement(interp, winPtr->pathName);
288 Tcl_AppendElement(interp, winPtr->classUid);
289 for (winPtr2 = winPtr;
290 (winPtr2 != NULL) && !(winPtr2->flags & TK_TOP_LEVEL);
291 winPtr2 = winPtr2->parentPtr) {
292 /* Empty loop body. */
293 }
294 if ((winPtr != winPtr2) && (winPtr2 != NULL)) {
295 Tcl_AppendElement(interp, winPtr2->pathName);
296 }
297 Tcl_AppendElement(interp, "all");
298 } else {
299 for (i = 0; i < winPtr->numTags; i++) {
300 Tcl_AppendElement(interp, (char *) winPtr->tagPtr[i]);
301 }
302 }
303 return TCL_OK;
304 }
305 if (winPtr->tagPtr != NULL) {
306 TkFreeBindingTags(winPtr);
307 }
308 if (argv[2][0] == 0) {
309 return TCL_OK;
310 }
311 if (Tcl_SplitList(interp, argv[2], &tagArgc, &tagArgv) != TCL_OK) {
312 return TCL_ERROR;
313 }
314 winPtr->numTags = tagArgc;
315 winPtr->tagPtr = (ClientData *) ckalloc((unsigned)
316 (tagArgc * sizeof(ClientData)));
317 for (i = 0; i < tagArgc; i++) {
318 p = tagArgv[i];
319 if (p[0] == '.') {
320 char *copy;
321
322 /*
323 * Handle names starting with "." specially: store a malloc'ed
324 * string, rather than a Uid; at event time we'll look up the
325 * name in the window table and use the corresponding window,
326 * if there is one.
327 */
328
329 copy = (char *) ckalloc((unsigned) (strlen(p) + 1));
330 strcpy(copy, p);
331 winPtr->tagPtr[i] = (ClientData) copy;
332 } else {
333 winPtr->tagPtr[i] = (ClientData) Tk_GetUid(p);
334 }
335 }
336 ckfree((char *) tagArgv);
337 return TCL_OK;
338 }
339
340 /*
341 *----------------------------------------------------------------------
342 *
343 * TkFreeBindingTags --
344 *
345 * This procedure is called to free all of the binding tags
346 * associated with a window; typically it is only invoked where
347 * there are window-specific tags.
348 *
349 * Results:
350 * None.
351 *
352 * Side effects:
353 * Any binding tags for winPtr are freed.
354 *
355 *----------------------------------------------------------------------
356 */
357
358 void
TkFreeBindingTags(winPtr)359 TkFreeBindingTags(winPtr)
360 TkWindow *winPtr; /* Window whose tags are to be released. */
361 {
362 int i;
363 char *p;
364
365 for (i = 0; i < winPtr->numTags; i++) {
366 p = (char *) (winPtr->tagPtr[i]);
367 if (*p == '.') {
368 /*
369 * Names starting with "." are malloced rather than Uids, so
370 * they have to be freed.
371 */
372
373 ckfree(p);
374 }
375 }
376 ckfree((char *) winPtr->tagPtr);
377 winPtr->numTags = 0;
378 winPtr->tagPtr = NULL;
379 }
380
381 /*
382 *----------------------------------------------------------------------
383 *
384 * Tk_DestroyCmd --
385 *
386 * This procedure is invoked to process the "destroy" Tcl command.
387 * See the user documentation for details on what it does.
388 *
389 * Results:
390 * A standard Tcl result.
391 *
392 * Side effects:
393 * See the user documentation.
394 *
395 *----------------------------------------------------------------------
396 */
397
398 int
Tk_DestroyCmd(clientData,interp,argc,argv)399 Tk_DestroyCmd(clientData, interp, argc, argv)
400 ClientData clientData; /* Main window associated with
401 * interpreter. */
402 Tcl_Interp *interp; /* Current interpreter. */
403 int argc; /* Number of arguments. */
404 char **argv; /* Argument strings. */
405 {
406 Tk_Window window;
407 Tk_Window tkwin = (Tk_Window) clientData;
408 int i;
409
410 for (i = 1; i < argc; i++) {
411 window = Tk_NameToWindow(interp, argv[i], tkwin);
412 if (window == NULL) {
413 return TCL_ERROR;
414 }
415 Tk_DestroyWindow(window);
416 }
417 return TCL_OK;
418 }
419
420 /*
421 *----------------------------------------------------------------------
422 *
423 * Tk_LowerCmd --
424 *
425 * This procedure is invoked to process the "lower" Tcl command.
426 * See the user documentation for details on what it does.
427 *
428 * Results:
429 * A standard Tcl result.
430 *
431 * Side effects:
432 * See the user documentation.
433 *
434 *----------------------------------------------------------------------
435 */
436
437 /* ARGSUSED */
438 int
Tk_LowerCmd(clientData,interp,argc,argv)439 Tk_LowerCmd(clientData, interp, argc, argv)
440 ClientData clientData; /* Main window associated with
441 * interpreter. */
442 Tcl_Interp *interp; /* Current interpreter. */
443 int argc; /* Number of arguments. */
444 char **argv; /* Argument strings. */
445 {
446 Tk_Window main = (Tk_Window) clientData;
447 Tk_Window tkwin, other;
448
449 if ((argc != 2) && (argc != 3)) {
450 Tcl_AppendResult(interp, "wrong # args: should be \"",
451 argv[0], " window ?belowThis?\"", (char *) NULL);
452 return TCL_ERROR;
453 }
454
455 tkwin = Tk_NameToWindow(interp, argv[1], main);
456 if (tkwin == NULL) {
457 return TCL_ERROR;
458 }
459 if (argc == 2) {
460 other = NULL;
461 } else {
462 other = Tk_NameToWindow(interp, argv[2], main);
463 if (other == NULL) {
464 return TCL_ERROR;
465 }
466 }
467 if (Tk_RestackWindow(tkwin, Below, other) != TCL_OK) {
468 Tcl_AppendResult(interp, "can't lower \"", argv[1], "\" below \"",
469 argv[2], "\"", (char *) NULL);
470 return TCL_ERROR;
471 }
472 return TCL_OK;
473 }
474
475 /*
476 *----------------------------------------------------------------------
477 *
478 * Tk_RaiseCmd --
479 *
480 * This procedure is invoked to process the "raise" Tcl command.
481 * See the user documentation for details on what it does.
482 *
483 * Results:
484 * A standard Tcl result.
485 *
486 * Side effects:
487 * See the user documentation.
488 *
489 *----------------------------------------------------------------------
490 */
491
492 /* ARGSUSED */
493 int
Tk_RaiseCmd(clientData,interp,argc,argv)494 Tk_RaiseCmd(clientData, interp, argc, argv)
495 ClientData clientData; /* Main window associated with
496 * interpreter. */
497 Tcl_Interp *interp; /* Current interpreter. */
498 int argc; /* Number of arguments. */
499 char **argv; /* Argument strings. */
500 {
501 Tk_Window main = (Tk_Window) clientData;
502 Tk_Window tkwin, other;
503
504 if ((argc != 2) && (argc != 3)) {
505 Tcl_AppendResult(interp, "wrong # args: should be \"",
506 argv[0], " window ?aboveThis?\"", (char *) NULL);
507 return TCL_ERROR;
508 }
509
510 tkwin = Tk_NameToWindow(interp, argv[1], main);
511 if (tkwin == NULL) {
512 return TCL_ERROR;
513 }
514 if (argc == 2) {
515 other = NULL;
516 } else {
517 other = Tk_NameToWindow(interp, argv[2], main);
518 if (other == NULL) {
519 return TCL_ERROR;
520 }
521 }
522 if (Tk_RestackWindow(tkwin, Above, other) != TCL_OK) {
523 Tcl_AppendResult(interp, "can't raise \"", argv[1], "\" above \"",
524 argv[2], "\"", (char *) NULL);
525 return TCL_ERROR;
526 }
527 return TCL_OK;
528 }
529
530 /*
531 *----------------------------------------------------------------------
532 *
533 * Tk_TkCmd --
534 *
535 * This procedure is invoked to process the "tk" Tcl command.
536 * See the user documentation for details on what it does.
537 *
538 * Results:
539 * A standard Tcl result.
540 *
541 * Side effects:
542 * See the user documentation.
543 *
544 *----------------------------------------------------------------------
545 */
546
547 /* ARGSUSED */
548 int
Tk_TkCmd(clientData,interp,argc,argv)549 Tk_TkCmd(clientData, interp, argc, argv)
550 ClientData clientData; /* Main window associated with
551 * interpreter. */
552 Tcl_Interp *interp; /* Current interpreter. */
553 int argc; /* Number of arguments. */
554 char **argv; /* Argument strings. */
555 {
556 char c;
557 size_t length;
558 Tk_Window tkwin = (Tk_Window) clientData;
559 TkWindow *winPtr;
560
561 if (argc < 2) {
562 Tcl_AppendResult(interp, "wrong # args: should be \"",
563 argv[0], " option ?arg?\"", (char *) NULL);
564 return TCL_ERROR;
565 }
566 c = argv[1][0];
567 length = strlen(argv[1]);
568 if ((c == 'a') && (strncmp(argv[1], "appname", length) == 0)) {
569 winPtr = ((TkWindow *) tkwin)->mainPtr->winPtr;
570 if (argc > 3) {
571 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
572 " appname ?newName?\"", (char *) NULL);
573 return TCL_ERROR;
574 }
575 if (argc == 3) {
576 winPtr->nameUid = Tk_GetUid(Tk_SetAppName(tkwin, argv[2]));
577 }
578 interp->result = winPtr->nameUid;
579 } else {
580 Tcl_AppendResult(interp, "bad option \"", argv[1],
581 "\": must be appname", (char *) NULL);
582 return TCL_ERROR;
583 }
584 return TCL_OK;
585 }
586
587 /*
588 *----------------------------------------------------------------------
589 *
590 * Tk_TkwaitCmd --
591 *
592 * This procedure is invoked to process the "tkwait" Tcl command.
593 * See the user documentation for details on what it does.
594 *
595 * Results:
596 * A standard Tcl result.
597 *
598 * Side effects:
599 * See the user documentation.
600 *
601 *----------------------------------------------------------------------
602 */
603
604 /* ARGSUSED */
605 int
Tk_TkwaitCmd(clientData,interp,argc,argv)606 Tk_TkwaitCmd(clientData, interp, argc, argv)
607 ClientData clientData; /* Main window associated with
608 * interpreter. */
609 Tcl_Interp *interp; /* Current interpreter. */
610 int argc; /* Number of arguments. */
611 char **argv; /* Argument strings. */
612 {
613 Tk_Window tkwin = (Tk_Window) clientData;
614 int c, done;
615 size_t length;
616
617 if (argc != 3) {
618 Tcl_AppendResult(interp, "wrong # args: should be \"",
619 argv[0], " variable|visibility|window name\"", (char *) NULL);
620 return TCL_ERROR;
621 }
622 c = argv[1][0];
623 length = strlen(argv[1]);
624 if ((c == 'v') && (strncmp(argv[1], "variable", length) == 0)
625 && (length >= 2)) {
626 if (Tcl_TraceVar(interp, argv[2],
627 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
628 WaitVariableProc, (ClientData) &done) != TCL_OK) {
629 return TCL_ERROR;
630 }
631 done = 0;
632 while (!done) {
633 Tcl_DoOneEvent(0);
634 }
635 Tcl_UntraceVar(interp, argv[2],
636 TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
637 WaitVariableProc, (ClientData) &done);
638 } else if ((c == 'v') && (strncmp(argv[1], "visibility", length) == 0)
639 && (length >= 2)) {
640 Tk_Window window;
641
642 window = Tk_NameToWindow(interp, argv[2], tkwin);
643 if (window == NULL) {
644 return TCL_ERROR;
645 }
646 Tk_CreateEventHandler(window, VisibilityChangeMask|StructureNotifyMask,
647 WaitVisibilityProc, (ClientData) &done);
648 done = 0;
649 while (!done) {
650 Tcl_DoOneEvent(0);
651 }
652 if (done != 1) {
653 /*
654 * Note that we do not delete the event handler because it
655 * was deleted automatically when the window was destroyed.
656 */
657
658 Tcl_ResetResult(interp);
659 Tcl_AppendResult(interp, "window \"", argv[2],
660 "\" was deleted before its visibility changed",
661 (char *) NULL);
662 return TCL_ERROR;
663 }
664 Tk_DeleteEventHandler(window, VisibilityChangeMask|StructureNotifyMask,
665 WaitVisibilityProc, (ClientData) &done);
666 } else if ((c == 'w') && (strncmp(argv[1], "window", length) == 0)) {
667 Tk_Window window;
668
669 window = Tk_NameToWindow(interp, argv[2], tkwin);
670 if (window == NULL) {
671 return TCL_ERROR;
672 }
673 Tk_CreateEventHandler(window, StructureNotifyMask,
674 WaitWindowProc, (ClientData) &done);
675 done = 0;
676 while (!done) {
677 Tcl_DoOneEvent(0);
678 }
679 /*
680 * Note: there's no need to delete the event handler. It was
681 * deleted automatically when the window was destroyed.
682 */
683 } else {
684 Tcl_AppendResult(interp, "bad option \"", argv[1],
685 "\": must be variable, visibility, or window", (char *) NULL);
686 return TCL_ERROR;
687 }
688
689 /*
690 * Clear out the interpreter's result, since it may have been set
691 * by event handlers.
692 */
693
694 Tcl_ResetResult(interp);
695 return TCL_OK;
696 }
697
698 /* ARGSUSED */
699 static char *
WaitVariableProc(clientData,interp,name1,name2,flags)700 WaitVariableProc(clientData, interp, name1, name2, flags)
701 ClientData clientData; /* Pointer to integer to set to 1. */
702 Tcl_Interp *interp; /* Interpreter containing variable. */
703 char *name1; /* Name of variable. */
704 char *name2; /* Second part of variable name. */
705 int flags; /* Information about what happened. */
706 {
707 int *donePtr = (int *) clientData;
708
709 *donePtr = 1;
710 return (char *) NULL;
711 }
712
713 /*ARGSUSED*/
714 static void
WaitVisibilityProc(clientData,eventPtr)715 WaitVisibilityProc(clientData, eventPtr)
716 ClientData clientData; /* Pointer to integer to set to 1. */
717 XEvent *eventPtr; /* Information about event (not used). */
718 {
719 int *donePtr = (int *) clientData;
720
721 if (eventPtr->type == VisibilityNotify) {
722 *donePtr = 1;
723 }
724 if (eventPtr->type == DestroyNotify) {
725 *donePtr = 2;
726 }
727 }
728
729 static void
WaitWindowProc(clientData,eventPtr)730 WaitWindowProc(clientData, eventPtr)
731 ClientData clientData; /* Pointer to integer to set to 1. */
732 XEvent *eventPtr; /* Information about event. */
733 {
734 int *donePtr = (int *) clientData;
735
736 if (eventPtr->type == DestroyNotify) {
737 *donePtr = 1;
738 }
739 }
740
741 /*
742 *----------------------------------------------------------------------
743 *
744 * Tk_UpdateCmd --
745 *
746 * This procedure is invoked to process the "update" Tcl command.
747 * See the user documentation for details on what it does.
748 *
749 * Results:
750 * A standard Tcl result.
751 *
752 * Side effects:
753 * See the user documentation.
754 *
755 *----------------------------------------------------------------------
756 */
757
758 /* ARGSUSED */
759 int
Tk_UpdateCmd(clientData,interp,argc,argv)760 Tk_UpdateCmd(clientData, interp, argc, argv)
761 ClientData clientData; /* Main window associated with
762 * interpreter. */
763 Tcl_Interp *interp; /* Current interpreter. */
764 int argc; /* Number of arguments. */
765 char **argv; /* Argument strings. */
766 {
767 Tk_Window tkwin = (Tk_Window) clientData;
768 int flags;
769 Display *display;
770
771 if (argc == 1) {
772 flags = TCL_DONT_WAIT;
773 } else if (argc == 2) {
774 if (strncmp(argv[1], "idletasks", strlen(argv[1])) != 0) {
775 Tcl_AppendResult(interp, "bad option \"", argv[1],
776 "\": must be idletasks", (char *) NULL);
777 return TCL_ERROR;
778 }
779 flags = TCL_IDLE_EVENTS;
780 } else {
781 Tcl_AppendResult(interp, "wrong # args: should be \"",
782 argv[0], " ?idletasks?\"", (char *) NULL);
783 return TCL_ERROR;
784 }
785
786 /*
787 * Handle all pending events, sync the display, and repeat over
788 * and over again until all pending events have been handled.
789 * Special note: it's possible that the entire application could
790 * be destroyed by an event handler that occurs during the update.
791 * Thus, don't use any information from tkwin after calling
792 * Tcl_DoOneEvent.
793 */
794
795 display = Tk_Display(tkwin);
796 while (1) {
797 while (Tcl_DoOneEvent(flags) != 0) {
798 /* Empty loop body */
799 }
800 XSync(display, False);
801 if (Tcl_DoOneEvent(flags) == 0) {
802 break;
803 }
804 }
805
806 /*
807 * Must clear the interpreter's result because event handlers could
808 * have executed commands.
809 */
810
811 Tcl_ResetResult(interp);
812 return TCL_OK;
813 }
814
815 /*
816 *----------------------------------------------------------------------
817 *
818 * Tk_WinfoCmd --
819 *
820 * This procedure is invoked to process the "winfo" Tcl command.
821 * See the user documentation for details on what it does.
822 *
823 * Results:
824 * A standard Tcl result.
825 *
826 * Side effects:
827 * See the user documentation.
828 *
829 *----------------------------------------------------------------------
830 */
831
832 int
Tk_WinfoCmd(clientData,interp,argc,argv)833 Tk_WinfoCmd(clientData, interp, argc, argv)
834 ClientData clientData; /* Main window associated with
835 * interpreter. */
836 Tcl_Interp *interp; /* Current interpreter. */
837 int argc; /* Number of arguments. */
838 char **argv; /* Argument strings. */
839 {
840 Tk_Window tkwin = (Tk_Window) clientData;
841 size_t length;
842 char c, *argName;
843 Tk_Window window;
844 register TkWindow *winPtr;
845
846 #define SETUP(name) \
847 if (argc != 3) {\
848 argName = name; \
849 goto wrongArgs; \
850 } \
851 window = Tk_NameToWindow(interp, argv[2], tkwin); \
852 if (window == NULL) { \
853 return TCL_ERROR; \
854 }
855
856 if (argc < 2) {
857 Tcl_AppendResult(interp, "wrong # args: should be \"",
858 argv[0], " option ?arg?\"", (char *) NULL);
859 return TCL_ERROR;
860 }
861 c = argv[1][0];
862 length = strlen(argv[1]);
863 if ((c == 'a') && (strcmp(argv[1], "atom") == 0)) {
864 char *atomName;
865
866 if (argc == 3) {
867 atomName = argv[2];
868 } else if (argc == 5) {
869 atomName = argv[4];
870 tkwin = GetDisplayOf(interp, tkwin, argv+2);
871 if (tkwin == NULL) {
872 return TCL_ERROR;
873 }
874 } else {
875 Tcl_AppendResult(interp, "wrong # args: should be \"",
876 argv[0], " atom ?-displayof window? name\"",
877 (char *) NULL);
878 return TCL_ERROR;
879 }
880 sprintf(interp->result, "%ld", Tk_InternAtom(tkwin, atomName));
881 } else if ((c == 'a') && (strncmp(argv[1], "atomname", length) == 0)
882 && (length >= 5)) {
883 Atom atom;
884 char *name, *id;
885
886 if (argc == 3) {
887 id = argv[2];
888 } else if (argc == 5) {
889 id = argv[4];
890 tkwin = GetDisplayOf(interp, tkwin, argv+2);
891 if (tkwin == NULL) {
892 return TCL_ERROR;
893 }
894 } else {
895 Tcl_AppendResult(interp, "wrong # args: should be \"",
896 argv[0], " atomname ?-displayof window? id\"",
897 (char *) NULL);
898 return TCL_ERROR;
899 }
900 if (Tcl_GetInt(interp, id, (int *) &atom) != TCL_OK) {
901 return TCL_ERROR;
902 }
903 name = Tk_GetAtomName(tkwin, atom);
904 if (strcmp(name, "?bad atom?") == 0) {
905 Tcl_AppendResult(interp, "no atom exists with id \"",
906 argv[2], "\"", (char *) NULL);
907 return TCL_ERROR;
908 }
909 interp->result = name;
910 } else if ((c == 'c') && (strncmp(argv[1], "cells", length) == 0)
911 && (length >= 2)) {
912 SETUP("cells");
913 sprintf(interp->result, "%d", Tk_Visual(window)->map_entries);
914 } else if ((c == 'c') && (strncmp(argv[1], "children", length) == 0)
915 && (length >= 2)) {
916 SETUP("children");
917 for (winPtr = ((TkWindow *) window)->childList; winPtr != NULL;
918 winPtr = winPtr->nextPtr) {
919 Tcl_AppendElement(interp, winPtr->pathName);
920 }
921 } else if ((c == 'c') && (strncmp(argv[1], "class", length) == 0)
922 && (length >= 2)) {
923 SETUP("class");
924 interp->result = Tk_Class(window);
925 } else if ((c == 'c') && (strncmp(argv[1], "colormapfull", length) == 0)
926 && (length >= 3)) {
927 SETUP("colormapfull");
928 interp->result = (TkCmapStressed(window, Tk_Colormap(window)))
929 ? "1" : "0";
930 } else if ((c == 'c') && (strncmp(argv[1], "containing", length) == 0)
931 && (length >= 3)) {
932 int rootX, rootY, index;
933
934 if (argc == 4) {
935 index = 2;
936 } else if (argc == 6) {
937 index = 4;
938 tkwin = GetDisplayOf(interp, tkwin, argv+2);
939 if (tkwin == NULL) {
940 return TCL_ERROR;
941 }
942 } else {
943 Tcl_AppendResult(interp, "wrong # args: should be \"",
944 argv[0], " containing ?-displayof window? rootX rootY\"",
945 (char *) NULL);
946 return TCL_ERROR;
947 }
948 if ((Tk_GetPixels(interp, tkwin, argv[index], &rootX) != TCL_OK)
949 || (Tk_GetPixels(interp, tkwin, argv[index+1], &rootY)
950 != TCL_OK)) {
951 return TCL_ERROR;
952 }
953 window = Tk_CoordsToWindow(rootX, rootY, tkwin);
954 if (window != NULL) {
955 interp->result = Tk_PathName(window);
956 }
957 } else if ((c == 'd') && (strncmp(argv[1], "depth", length) == 0)) {
958 SETUP("depth");
959 sprintf(interp->result, "%d", Tk_Depth(window));
960 } else if ((c == 'e') && (strncmp(argv[1], "exists", length) == 0)) {
961 if (argc != 3) {
962 argName = "exists";
963 goto wrongArgs;
964 }
965 window = Tk_NameToWindow(interp, argv[2], tkwin);
966 if ((window == NULL)
967 || (((TkWindow *) window)->flags & TK_ALREADY_DEAD)) {
968 interp->result = "0";
969 } else {
970 interp->result = "1";
971 }
972 } else if ((c == 'f') && (strncmp(argv[1], "fpixels", length) == 0)
973 && (length >= 2)) {
974 double mm, pixels;
975
976 if (argc != 4) {
977 Tcl_AppendResult(interp, "wrong # args: should be \"",
978 argv[0], " fpixels window number\"", (char *) NULL);
979 return TCL_ERROR;
980 }
981 window = Tk_NameToWindow(interp, argv[2], tkwin);
982 if (window == NULL) {
983 return TCL_ERROR;
984 }
985 if (Tk_GetScreenMM(interp, window, argv[3], &mm) != TCL_OK) {
986 return TCL_ERROR;
987 }
988 pixels = mm * WidthOfScreen(Tk_Screen(window))
989 / WidthMMOfScreen(Tk_Screen(window));
990 Tcl_PrintDouble(interp, pixels, interp->result);
991 } else if ((c == 'g') && (strncmp(argv[1], "geometry", length) == 0)) {
992 SETUP("geometry");
993 sprintf(interp->result, "%dx%d+%d+%d", Tk_Width(window),
994 Tk_Height(window), Tk_X(window), Tk_Y(window));
995 } else if ((c == 'h') && (strncmp(argv[1], "height", length) == 0)) {
996 SETUP("height");
997 sprintf(interp->result, "%d", Tk_Height(window));
998 } else if ((c == 'i') && (strcmp(argv[1], "id") == 0)) {
999 SETUP("id");
1000 Tk_MakeWindowExist(window);
1001 sprintf(interp->result, "0x%x", (unsigned int) Tk_WindowId(window));
1002 } else if ((c == 'i') && (strncmp(argv[1], "interps", length) == 0)
1003 && (length >= 2)) {
1004 if (argc == 4) {
1005 tkwin = GetDisplayOf(interp, tkwin, argv+2);
1006 if (tkwin == NULL) {
1007 return TCL_ERROR;
1008 }
1009 } else if (argc != 2) {
1010 Tcl_AppendResult(interp, "wrong # args: should be \"",
1011 argv[0], " interps ?-displayof window?\"",
1012 (char *) NULL);
1013 return TCL_ERROR;
1014 }
1015 return TkGetInterpNames(interp, tkwin);
1016 } else if ((c == 'i') && (strncmp(argv[1], "ismapped", length) == 0)
1017 && (length >= 2)) {
1018 SETUP("ismapped");
1019 interp->result = Tk_IsMapped(window) ? "1" : "0";
1020 } else if ((c == 'm') && (strncmp(argv[1], "manager", length) == 0)) {
1021 SETUP("manager");
1022 winPtr = (TkWindow *) window;
1023 if (winPtr->geomMgrPtr != NULL) {
1024 interp->result = winPtr->geomMgrPtr->name;
1025 }
1026 } else if ((c == 'n') && (strncmp(argv[1], "name", length) == 0)) {
1027 SETUP("name");
1028 interp->result = Tk_Name(window);
1029 } else if ((c == 'p') && (strncmp(argv[1], "parent", length) == 0)) {
1030 SETUP("parent");
1031 winPtr = (TkWindow *) window;
1032 if (winPtr->parentPtr != NULL) {
1033 interp->result = winPtr->parentPtr->pathName;
1034 }
1035 } else if ((c == 'p') && (strncmp(argv[1], "pathname", length) == 0)
1036 && (length >= 2)) {
1037 int index, id;
1038
1039 if (argc == 3) {
1040 index = 2;
1041 } else if (argc == 5) {
1042 index = 4;
1043 tkwin = GetDisplayOf(interp, tkwin, argv+2);
1044 if (tkwin == NULL) {
1045 return TCL_ERROR;
1046 }
1047 } else {
1048 Tcl_AppendResult(interp, "wrong # args: should be \"",
1049 argv[0], " pathname ?-displayof window? id\"",
1050 (char *) NULL);
1051 return TCL_ERROR;
1052 }
1053 if (Tcl_GetInt(interp, argv[index], &id) != TCL_OK) {
1054 return TCL_ERROR;
1055 }
1056 window = Tk_IdToWindow(Tk_Display(tkwin), (Window) id);
1057 if ((window == NULL) || (((TkWindow *) window)->mainPtr
1058 != ((TkWindow *) tkwin)->mainPtr)) {
1059 Tcl_AppendResult(interp, "window id \"", argv[index],
1060 "\" doesn't exist in this application", (char *) NULL);
1061 return TCL_ERROR;
1062 }
1063 interp->result = Tk_PathName(window);
1064 } else if ((c == 'p') && (strncmp(argv[1], "pixels", length) == 0)
1065 && (length >= 2)) {
1066 int pixels;
1067
1068 if (argc != 4) {
1069 Tcl_AppendResult(interp, "wrong # args: should be \"",
1070 argv[0], " pixels window number\"", (char *) NULL);
1071 return TCL_ERROR;
1072 }
1073 window = Tk_NameToWindow(interp, argv[2], tkwin);
1074 if (window == NULL) {
1075 return TCL_ERROR;
1076 }
1077 if (Tk_GetPixels(interp, window, argv[3], &pixels) != TCL_OK) {
1078 return TCL_ERROR;
1079 }
1080 sprintf(interp->result, "%d", pixels);
1081 } else if ((c == 'p') && (strcmp(argv[1], "pointerx") == 0)) {
1082 int x, y;
1083
1084 SETUP("pointerx");
1085 winPtr = GetToplevel(window);
1086 if (winPtr == NULL) {
1087 x = -1;
1088 } else {
1089 TkGetPointerCoords((Tk_Window)winPtr, &x, &y);
1090 }
1091 sprintf(interp->result, "%d", x);
1092 } else if ((c == 'p') && (strcmp(argv[1], "pointerxy") == 0)) {
1093 int x, y;
1094
1095 SETUP("pointerxy");
1096 winPtr = GetToplevel(window);
1097 if (winPtr == NULL) {
1098 x = -1;
1099 } else {
1100 TkGetPointerCoords((Tk_Window)winPtr, &x, &y);
1101 }
1102 sprintf(interp->result, "%d %d", x, y);
1103 } else if ((c == 'p') && (strcmp(argv[1], "pointery") == 0)) {
1104 int x, y;
1105
1106 SETUP("pointery");
1107 winPtr = GetToplevel(window);
1108 if (winPtr == NULL) {
1109 y = -1;
1110 } else {
1111 TkGetPointerCoords((Tk_Window)winPtr, &x, &y);
1112 }
1113 sprintf(interp->result, "%d", y);
1114 } else if ((c == 'r') && (strncmp(argv[1], "reqheight", length) == 0)
1115 && (length >= 4)) {
1116 SETUP("reqheight");
1117 sprintf(interp->result, "%d", Tk_ReqHeight(window));
1118 } else if ((c == 'r') && (strncmp(argv[1], "reqwidth", length) == 0)
1119 && (length >= 4)) {
1120 SETUP("reqwidth");
1121 sprintf(interp->result, "%d", Tk_ReqWidth(window));
1122 } else if ((c == 'r') && (strncmp(argv[1], "rgb", length) == 0)
1123 && (length >= 2)) {
1124 XColor *colorPtr;
1125
1126 if (argc != 4) {
1127 Tcl_AppendResult(interp, "wrong # args: should be \"",
1128 argv[0], " rgb window colorName\"", (char *) NULL);
1129 return TCL_ERROR;
1130 }
1131 window = Tk_NameToWindow(interp, argv[2], tkwin);
1132 if (window == NULL) {
1133 return TCL_ERROR;
1134 }
1135 colorPtr = Tk_GetColor(interp, window, argv[3]);
1136 if (colorPtr == NULL) {
1137 return TCL_ERROR;
1138 }
1139 sprintf(interp->result, "%d %d %d", colorPtr->red, colorPtr->green,
1140 colorPtr->blue);
1141 Tk_FreeColor(colorPtr);
1142 } else if ((c == 'r') && (strcmp(argv[1], "rootx") == 0)) {
1143 int x, y;
1144
1145 SETUP("rootx");
1146 Tk_GetRootCoords(window, &x, &y);
1147 sprintf(interp->result, "%d", x);
1148 } else if ((c == 'r') && (strcmp(argv[1], "rooty") == 0)) {
1149 int x, y;
1150
1151 SETUP("rooty");
1152 Tk_GetRootCoords(window, &x, &y);
1153 sprintf(interp->result, "%d", y);
1154 } else if ((c == 's') && (strcmp(argv[1], "screen") == 0)) {
1155 char string[20];
1156
1157 SETUP("screen");
1158 sprintf(string, "%d", Tk_ScreenNumber(window));
1159 Tcl_AppendResult(interp, Tk_DisplayName(window), ".", string,
1160 (char *) NULL);
1161 } else if ((c == 's') && (strncmp(argv[1], "screencells", length) == 0)
1162 && (length >= 7)) {
1163 SETUP("screencells");
1164 sprintf(interp->result, "%d", CellsOfScreen(Tk_Screen(window)));
1165 } else if ((c == 's') && (strncmp(argv[1], "screendepth", length) == 0)
1166 && (length >= 7)) {
1167 SETUP("screendepth");
1168 sprintf(interp->result, "%d", DefaultDepthOfScreen(Tk_Screen(window)));
1169 } else if ((c == 's') && (strncmp(argv[1], "screenheight", length) == 0)
1170 && (length >= 7)) {
1171 SETUP("screenheight");
1172 sprintf(interp->result, "%d", HeightOfScreen(Tk_Screen(window)));
1173 } else if ((c == 's') && (strncmp(argv[1], "screenmmheight", length) == 0)
1174 && (length >= 9)) {
1175 SETUP("screenmmheight");
1176 sprintf(interp->result, "%d", HeightMMOfScreen(Tk_Screen(window)));
1177 } else if ((c == 's') && (strncmp(argv[1], "screenmmwidth", length) == 0)
1178 && (length >= 9)) {
1179 SETUP("screenmmwidth");
1180 sprintf(interp->result, "%d", WidthMMOfScreen(Tk_Screen(window)));
1181 } else if ((c == 's') && (strncmp(argv[1], "screenvisual", length) == 0)
1182 && (length >= 7)) {
1183 SETUP("screenvisual");
1184 switch (DefaultVisualOfScreen(Tk_Screen(window))->class) {
1185 case PseudoColor: interp->result = "pseudocolor"; break;
1186 case GrayScale: interp->result = "grayscale"; break;
1187 case DirectColor: interp->result = "directcolor"; break;
1188 case TrueColor: interp->result = "truecolor"; break;
1189 case StaticColor: interp->result = "staticcolor"; break;
1190 case StaticGray: interp->result = "staticgray"; break;
1191 default: interp->result = "unknown"; break;
1192 }
1193 } else if ((c == 's') && (strncmp(argv[1], "screenwidth", length) == 0)
1194 && (length >= 7)) {
1195 SETUP("screenwidth");
1196 sprintf(interp->result, "%d", WidthOfScreen(Tk_Screen(window)));
1197 } else if ((c == 's') && (strncmp(argv[1], "server", length) == 0)
1198 && (length >= 2)) {
1199 SETUP("server");
1200 TkGetServerInfo(interp, window);
1201 } else if ((c == 't') && (strncmp(argv[1], "toplevel", length) == 0)) {
1202 SETUP("toplevel");
1203 winPtr = GetToplevel(window);
1204 if (winPtr != NULL) {
1205 interp->result = winPtr->pathName;
1206 }
1207 } else if ((c == 'v') && (strncmp(argv[1], "viewable", length) == 0)
1208 && (length >= 3)) {
1209 SETUP("viewable");
1210 for (winPtr = (TkWindow *) window; ; winPtr = winPtr->parentPtr) {
1211 if ((winPtr == NULL) || !(winPtr->flags & TK_MAPPED)) {
1212 interp->result = "0";
1213 break;
1214 }
1215 if (winPtr->flags & TK_TOP_LEVEL) {
1216 interp->result = "1";
1217 break;
1218 }
1219 }
1220 } else if ((c == 'v') && (strcmp(argv[1], "visual") == 0)) {
1221 SETUP("visual");
1222 switch (Tk_Visual(window)->class) {
1223 case PseudoColor: interp->result = "pseudocolor"; break;
1224 case GrayScale: interp->result = "grayscale"; break;
1225 case DirectColor: interp->result = "directcolor"; break;
1226 case TrueColor: interp->result = "truecolor"; break;
1227 case StaticColor: interp->result = "staticcolor"; break;
1228 case StaticGray: interp->result = "staticgray"; break;
1229 default: interp->result = "unknown"; break;
1230 }
1231 } else if ((c == 'v') && (strncmp(argv[1], "visualid", length) == 0)
1232 && (length >= 7)) {
1233 SETUP("visualid");
1234 sprintf(interp->result, "0x%x", (unsigned int)
1235 XVisualIDFromVisual(Tk_Visual(window)));
1236 } else if ((c == 'v') && (strncmp(argv[1], "visualsavailable", length) == 0)
1237 && (length >= 7)) {
1238 XVisualInfo template, *visInfoPtr;
1239 int count, i;
1240 char string[70], visualIdString[16], *fmt;
1241 int includeVisualId;
1242
1243 if (argc == 3) {
1244 includeVisualId = 0;
1245 } else if ((argc == 4)
1246 && (strncmp(argv[3], "includeids", strlen(argv[3])) == 0)) {
1247 includeVisualId = 1;
1248 } else {
1249 Tcl_AppendResult(interp, "wrong # args: should be \"",
1250 argv[0], " visualsavailable window ?includeids?\"",
1251 (char *) NULL);
1252 return TCL_ERROR;
1253 }
1254
1255 window = Tk_NameToWindow(interp, argv[2], tkwin);
1256 if (window == NULL) {
1257 return TCL_ERROR;
1258 }
1259
1260 template.screen = Tk_ScreenNumber(window);
1261 visInfoPtr = XGetVisualInfo(Tk_Display(window), VisualScreenMask,
1262 &template, &count);
1263 if (visInfoPtr == NULL) {
1264 interp->result = "can't find any visuals for screen";
1265 return TCL_ERROR;
1266 }
1267 for (i = 0; i < count; i++) {
1268 switch (visInfoPtr[i].class) {
1269 case PseudoColor: fmt = "pseudocolor %d"; break;
1270 case GrayScale: fmt = "grayscale %d"; break;
1271 case DirectColor: fmt = "directcolor %d"; break;
1272 case TrueColor: fmt = "truecolor %d"; break;
1273 case StaticColor: fmt = "staticcolor %d"; break;
1274 case StaticGray: fmt = "staticgray %d"; break;
1275 default: fmt = "unknown"; break;
1276 }
1277 sprintf(string, fmt, visInfoPtr[i].depth);
1278 if (includeVisualId) {
1279 sprintf(visualIdString, " 0x%x",
1280 (unsigned int) visInfoPtr[i].visualid);
1281 strcat(string, visualIdString);
1282 }
1283 Tcl_AppendElement(interp, string);
1284 }
1285 XFree((char *) visInfoPtr);
1286 } else if ((c == 'v') && (strncmp(argv[1], "vrootheight", length) == 0)
1287 && (length >= 6)) {
1288 int x, y;
1289 int width, height;
1290
1291 SETUP("vrootheight");
1292 Tk_GetVRootGeometry(window, &x, &y, &width, &height);
1293 sprintf(interp->result, "%d", height);
1294 } else if ((c == 'v') && (strncmp(argv[1], "vrootwidth", length) == 0)
1295 && (length >= 6)) {
1296 int x, y;
1297 int width, height;
1298
1299 SETUP("vrootwidth");
1300 Tk_GetVRootGeometry(window, &x, &y, &width, &height);
1301 sprintf(interp->result, "%d", width);
1302 } else if ((c == 'v') && (strcmp(argv[1], "vrootx") == 0)) {
1303 int x, y;
1304 int width, height;
1305
1306 SETUP("vrootx");
1307 Tk_GetVRootGeometry(window, &x, &y, &width, &height);
1308 sprintf(interp->result, "%d", x);
1309 } else if ((c == 'v') && (strcmp(argv[1], "vrooty") == 0)) {
1310 int x, y;
1311 int width, height;
1312
1313 SETUP("vrooty");
1314 Tk_GetVRootGeometry(window, &x, &y, &width, &height);
1315 sprintf(interp->result, "%d", y);
1316 } else if ((c == 'w') && (strncmp(argv[1], "width", length) == 0)) {
1317 SETUP("width");
1318 sprintf(interp->result, "%d", Tk_Width(window));
1319 } else if ((c == 'x') && (argv[1][1] == '\0')) {
1320 SETUP("x");
1321 sprintf(interp->result, "%d", Tk_X(window));
1322 } else if ((c == 'y') && (argv[1][1] == '\0')) {
1323 SETUP("y");
1324 sprintf(interp->result, "%d", Tk_Y(window));
1325 } else {
1326 Tcl_AppendResult(interp, "bad option \"", argv[1],
1327 "\": must be atom, atomname, cells, children, ",
1328 "class, colormapfull, containing, depth, exists, fpixels, ",
1329 "geometry, height, ",
1330 "id, interps, ismapped, manager, name, parent, pathname, ",
1331 "pixels, pointerx, pointerxy, pointery, reqheight, ",
1332 "reqwidth, rgb, ",
1333 "rootx, rooty, ",
1334 "screen, screencells, screendepth, screenheight, ",
1335 "screenmmheight, screenmmwidth, screenvisual, ",
1336 "screenwidth, server, ",
1337 "toplevel, viewable, visual, visualid, visualsavailable, ",
1338 "vrootheight, vrootwidth, vrootx, vrooty, ",
1339 "width, x, or y", (char *) NULL);
1340 return TCL_ERROR;
1341 }
1342 return TCL_OK;
1343
1344 wrongArgs:
1345 Tcl_AppendResult(interp, "wrong # arguments: must be \"",
1346 argv[0], " ", argName, " window\"", (char *) NULL);
1347 return TCL_ERROR;
1348 }
1349
1350 /*
1351 *----------------------------------------------------------------------
1352 *
1353 * GetDisplayOf --
1354 *
1355 * Parses a "-displayof" option for the "winfo" command.
1356 *
1357 * Results:
1358 * The return value is a token for the window specified in
1359 * argv[1]. If argv[0] and argv[1] couldn't be parsed, NULL
1360 * is returned and an error is left in interp->result.
1361 *
1362 * Side effects:
1363 * None.
1364 *
1365 *----------------------------------------------------------------------
1366 */
1367
1368 static Tk_Window
GetDisplayOf(interp,tkwin,argv)1369 GetDisplayOf(interp, tkwin, argv)
1370 Tcl_Interp *interp; /* Interpreter for error reporting. */
1371 Tk_Window tkwin; /* Window to use for looking up window
1372 * given in argv[1]. */
1373 char **argv; /* Array of two strings. First must be
1374 * "-displayof" or an abbreviation, second
1375 * must be window name. */
1376 {
1377 size_t length;
1378
1379 length = strlen(argv[0]);
1380 if ((length < 2) || (strncmp(argv[0], "-displayof", length) != 0)) {
1381 Tcl_AppendResult(interp, "bad argument \"", argv[0],
1382 "\": must be -displayof", (char *) NULL);
1383 return (Tk_Window) NULL;
1384 }
1385 return Tk_NameToWindow(interp, argv[1], tkwin);
1386 }
1387
1388 /*
1389 *----------------------------------------------------------------------
1390 *
1391 * TkDeadAppCmd --
1392 *
1393 * If an application has been deleted then all Tk commands will be
1394 * re-bound to this procedure.
1395 *
1396 * Results:
1397 * A standard Tcl error is reported to let the user know that
1398 * the application is dead.
1399 *
1400 * Side effects:
1401 * See the user documentation.
1402 *
1403 *----------------------------------------------------------------------
1404 */
1405
1406 /* ARGSUSED */
1407 int
TkDeadAppCmd(clientData,interp,argc,argv)1408 TkDeadAppCmd(clientData, interp, argc, argv)
1409 ClientData clientData; /* Dummy. */
1410 Tcl_Interp *interp; /* Current interpreter. */
1411 int argc; /* Number of arguments. */
1412 char **argv; /* Argument strings. */
1413 {
1414 Tcl_AppendResult(interp, "can't invoke \"", argv[0],
1415 "\" command: application has been destroyed", (char *) NULL);
1416 return TCL_ERROR;
1417 }
1418
1419 /*
1420 *----------------------------------------------------------------------
1421 *
1422 * GetToplevel --
1423 *
1424 * Retrieves the toplevel window which is the nearest ancestor of
1425 * of the specified window.
1426 *
1427 * Results:
1428 * Returns the toplevel window or NULL if the window has no
1429 * ancestor which is a toplevel.
1430 *
1431 * Side effects:
1432 * None.
1433 *
1434 *----------------------------------------------------------------------
1435 */
1436
1437 static TkWindow *
GetToplevel(tkwin)1438 GetToplevel(tkwin)
1439 Tk_Window tkwin; /* Window for which the toplevel should be
1440 * deterined. */
1441 {
1442 TkWindow *winPtr = (TkWindow *) tkwin;
1443
1444 while (!(winPtr->flags & TK_TOP_LEVEL)) {
1445 winPtr = winPtr->parentPtr;
1446 if (winPtr == NULL) {
1447 return NULL;
1448 }
1449 }
1450 return winPtr;
1451 }
1452