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-1997 Sun Microsystems, Inc.
9  * Copyright (c) 2000 Scriptics Corporation.
10  *
11  * See the file "license.terms" for information on usage and redistribution
12  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13  *
14  * RCS: @(#) $Id: tkCmds.c,v 1.31 2002/09/02 19:16:23 hobbs Exp $
15  */
16 
17 #include "tkPort.h"
18 #include "tkInt.h"
19 #include <errno.h>
20 
21 #if defined(WIN32)
22 #include "tkWinInt.h"
23 #else
24 #if defined(MAC_TCL)
25 #include "tkMacInt.h"
26 #elif defined(MAC_OSX_TK)
27 #include "tkMacOSXInt.h"
28 #else
29 #include "tkUnixInt.h"
30 #endif
31 #endif
32 /*
33  * Forward declarations for procedures defined later in this file:
34  */
35 
36 static TkWindow *	GetToplevel _ANSI_ARGS_((Tk_Window tkwin));
37 static char *		WaitVariableProc _ANSI_ARGS_((ClientData clientData,
38 			    Tcl_Interp *interp, Var name1,
39 			    CONST char *name2, int flags));
40 static void		WaitVisibilityProc _ANSI_ARGS_((ClientData clientData,
41 			    XEvent *eventPtr));
42 static void		WaitWindowProc _ANSI_ARGS_((ClientData clientData,
43 			    XEvent *eventPtr));
44 
45 /*
46  *----------------------------------------------------------------------
47  *
48  * Tk_BellObjCmd --
49  *
50  *	This procedure is invoked to process the "bell" Tcl command.
51  *	See the user documentation for details on what it does.
52  *
53  * Results:
54  *	A standard Tcl result.
55  *
56  * Side effects:
57  *	See the user documentation.
58  *
59  *----------------------------------------------------------------------
60  */
61 
62 int
Tk_BellObjCmd(clientData,interp,objc,objv)63 Tk_BellObjCmd(clientData, interp, objc, objv)
64     ClientData clientData;	/* Main window associated with interpreter. */
65     Tcl_Interp *interp;		/* Current interpreter. */
66     int objc;			/* Number of arguments. */
67     Tcl_Obj *CONST objv[];	/* Argument objects. */
68 {
69     static CONST char *bellOptions[] = {"-displayof", "-nice", (char *) NULL};
70     enum options { TK_BELL_DISPLAYOF, TK_BELL_NICE };
71     Tk_Window tkwin = (Tk_Window) clientData;
72     int i, index, nice = 0;
73 
74     if (objc > 4) {
75 	Tcl_WrongNumArgs(interp, 1, objv, "?-displayof window? ?-nice?");
76 	return TCL_ERROR;
77     }
78 
79     for (i = 1; i < objc; i++) {
80 	if (Tcl_GetIndexFromObj(interp, objv[i], bellOptions, "option", 0,
81 		&index) != TCL_OK) {
82 	    return TCL_ERROR;
83 	}
84 	switch ((enum options) index) {
85 	    case TK_BELL_DISPLAYOF:
86 		if (++i >= objc) {
87 		    Tcl_WrongNumArgs(interp, 1, objv,
88 			    "?-displayof window? ?-nice?");
89 		    return TCL_ERROR;
90 		}
91 		tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), tkwin);
92 		if (tkwin == NULL) {
93 		    return TCL_ERROR;
94 		}
95 		break;
96 	    case TK_BELL_NICE:
97 		nice = 1;
98 		break;
99 	}
100     }
101     XBell(Tk_Display(tkwin), 0);
102     if (!nice) {
103 	XForceScreenSaver(Tk_Display(tkwin), ScreenSaverReset);
104     }
105     XFlush(Tk_Display(tkwin));
106     return TCL_OK;
107 }
108 
109 /*
110  *----------------------------------------------------------------------
111  *
112  * Tk_BindObjCmd --
113  *
114  *	This procedure is invoked to process the "bind" Tcl command.
115  *	See the user documentation for details on what it does.
116  *
117  * Results:
118  *	A standard Tcl result.
119  *
120  * Side effects:
121  *	See the user documentation.
122  *
123  *----------------------------------------------------------------------
124  */
125 
126 int
Tk_BindObjCmd(clientData,interp,objc,objv)127 Tk_BindObjCmd(clientData, interp, objc, objv)
128     ClientData clientData;	/* Main window associated with interpreter. */
129     Tcl_Interp *interp;		/* Current interpreter. */
130     int objc;			/* Number of arguments. */
131     Tcl_Obj *CONST objv[];	/* Argument objects. */
132 {
133     Tk_Window tkwin = (Tk_Window) clientData;
134     TkWindow *winPtr;
135     ClientData object;
136     char *string;
137 
138     if ((objc < 2) || (objc > 4)) {
139 	Tcl_WrongNumArgs(interp, 1, objv, "window ?pattern? ?command?");
140 	return TCL_ERROR;
141     }
142     string = Tcl_GetString(objv[1]);
143 
144     /*
145      * Bind tags either a window name or a tag name for the first argument.
146      * If the argument starts with ".", assume it is a window; otherwise, it
147      * is a tag.
148      */
149 
150     if (string[0] == '.') {
151 	winPtr = (TkWindow *) Tk_NameToWindow(interp, string, tkwin);
152 	if (winPtr == NULL) {
153 	    return TCL_ERROR;
154 	}
155 	object = (ClientData) winPtr->pathName;
156     } else {
157 	winPtr = (TkWindow *) clientData;
158 	object = (ClientData) Tk_GetUid(string);
159     }
160 
161     /*
162      * If there are four arguments, the command is modifying a binding.  If
163      * there are three arguments, the command is querying a binding.  If there
164      * are only two arguments, the command is querying all the bindings for
165      * the given tag/window.
166      */
167 
168     if (objc == 4) {
169 	int append = 0;
170 	unsigned long mask;
171 	char *sequence, *script;
172 	sequence	= Tcl_GetString(objv[2]);
173 	script		= Tcl_GetString(objv[3]);
174 
175 	/*
176 	 * If the script is null, just delete the binding.
177 	 */
178 
179 	if (script[0] == 0) {
180 	    return Tk_DeleteBinding(interp, winPtr->mainPtr->bindingTable,
181 		    object, sequence);
182 	}
183 
184 	/*
185 	 * If the script begins with "+", append this script to the existing
186 	 * binding.
187 	 */
188 
189 	if (script[0] == '+') {
190 	    script++;
191 	    append = 1;
192 	}
193 	mask = Tk_CreateBinding(interp, winPtr->mainPtr->bindingTable,
194 		object, sequence, objv[3], append);
195 	if (mask == 0) {
196 	    return TCL_ERROR;
197 	}
198     } else if (objc == 3) {
199 	Tcl_Obj *command;
200 
201 	command = Tk_GetBinding(interp, winPtr->mainPtr->bindingTable,
202 		object, Tcl_GetString(objv[2]));
203 	if (command == NULL) {
204 	    Tcl_ResetResult(interp);
205 	    return TCL_OK;
206 	}
207 	Tcl_SetObjResult(interp,command);
208     } else {
209 	Tk_GetAllBindings(interp, winPtr->mainPtr->bindingTable, object);
210     }
211     return TCL_OK;
212 }
213 
214 /*
215  *----------------------------------------------------------------------
216  *
217  * TkBindEventProc --
218  *
219  *	This procedure is invoked by Tk_HandleEvent for each event;  it
220  *	causes any appropriate bindings for that event to be invoked.
221  *
222  * Results:
223  *	None.
224  *
225  * Side effects:
226  *	Depends on what bindings have been established with the "bind"
227  *	command.
228  *
229  *----------------------------------------------------------------------
230  */
231 
232 void
TkBindEventProc(winPtr,eventPtr)233 TkBindEventProc(winPtr, eventPtr)
234     TkWindow *winPtr;			/* Pointer to info about window. */
235     XEvent *eventPtr;			/* Information about event. */
236 {
237 #define MAX_OBJS 20
238     ClientData objects[MAX_OBJS], *objPtr;
239     TkWindow *topLevPtr;
240     int i, count;
241     char *p;
242     Tcl_HashEntry *hPtr;
243 
244     if ((winPtr->mainPtr == NULL) || (winPtr->mainPtr->bindingTable == NULL)) {
245 	return;
246     }
247 
248     objPtr = objects;
249     if (winPtr->numTags != 0) {
250 	/*
251 	 * Make a copy of the tags for the window, replacing window names
252 	 * with pointers to the pathName from the appropriate window.
253 	 */
254 
255 	if (winPtr->numTags > MAX_OBJS) {
256 	    objPtr = (ClientData *) ckalloc((unsigned)
257 		    (winPtr->numTags * sizeof(ClientData)));
258 	}
259 	for (i = 0; i < winPtr->numTags; i++) {
260 	    p = (char *) winPtr->tagPtr[i];
261 	    if (*p == '.') {
262 		hPtr = Tcl_FindHashEntry(&winPtr->mainPtr->nameTable, p);
263 		if (hPtr != NULL) {
264 		    p = ((TkWindow *) Tcl_GetHashValue(hPtr))->pathName;
265 		} else {
266 		    p = NULL;
267 		}
268 	    }
269 	    objPtr[i] = (ClientData) p;
270 	}
271 	count = winPtr->numTags;
272     } else {
273 	objPtr[0] = (ClientData) winPtr->pathName;
274 	objPtr[1] = (ClientData) winPtr->classUid;
275 	for (topLevPtr = winPtr;
276 		(topLevPtr != NULL) && !(topLevPtr->flags & TK_TOP_HIERARCHY);
277 		topLevPtr = topLevPtr->parentPtr) {
278 	    /* Empty loop body. */
279 	}
280 	if ((winPtr != topLevPtr) && (topLevPtr != NULL)) {
281 	    count = 4;
282 	    objPtr[2] = (ClientData) topLevPtr->pathName;
283 	} else {
284 	    count = 3;
285 	}
286 	objPtr[count-1] = (ClientData) Tk_GetUid("all");
287     }
288     Tk_BindEvent(winPtr->mainPtr->bindingTable, eventPtr, (Tk_Window) winPtr,
289 	    count, objPtr);
290     if (objPtr != objects) {
291 	ckfree((char *) objPtr);
292     }
293 }
294 
295 /*
296  *----------------------------------------------------------------------
297  *
298  * Tk_BindtagsObjCmd --
299  *
300  *	This procedure is invoked to process the "bindtags" Tcl command.
301  *	See the user documentation for details on what it does.
302  *
303  * Results:
304  *	A standard Tcl result.
305  *
306  * Side effects:
307  *	See the user documentation.
308  *
309  *----------------------------------------------------------------------
310  */
311 
312 int
Tk_BindtagsObjCmd(clientData,interp,objc,objv)313 Tk_BindtagsObjCmd(clientData, interp, objc, objv)
314     ClientData clientData;	/* Main window associated with interpreter. */
315     Tcl_Interp *interp;		/* Current interpreter. */
316     int objc;			/* Number of arguments. */
317     Tcl_Obj *CONST objv[];	/* Argument objects. */
318 {
319     Tk_Window tkwin = (Tk_Window) clientData;
320     TkWindow *winPtr, *winPtr2;
321     int i, length;
322     char *p;
323     Tcl_Obj *listPtr, **tags;
324 
325     if ((objc < 2) || (objc > 3)) {
326 	Tcl_WrongNumArgs(interp, 1, objv, "window ?taglist?");
327 	return TCL_ERROR;
328     }
329     winPtr = (TkWindow *) Tk_NameToWindow(interp, Tcl_GetString(objv[1]),
330 	    tkwin);
331     if (winPtr == NULL) {
332 	return TCL_ERROR;
333     }
334     if (objc == 2) {
335 	listPtr = Tcl_NewObj();
336 	Tcl_IncrRefCount(listPtr);
337 	if (winPtr->numTags == 0) {
338 	    Tcl_ListObjAppendElement(interp, listPtr,
339 		    Tcl_NewStringObj(winPtr->pathName, -1));
340 	    Tcl_ListObjAppendElement(interp, listPtr,
341 		    Tcl_NewStringObj(winPtr->classUid, -1));
342 	    winPtr2 = winPtr;
343 	    while ((winPtr2 != NULL) && !(Tk_TopWinHierarchy(winPtr2))) {
344 		winPtr2 = winPtr2->parentPtr;
345 	    }
346 	    if ((winPtr != winPtr2) && (winPtr2 != NULL)) {
347 		Tcl_ListObjAppendElement(interp, listPtr,
348 			Tcl_NewStringObj(winPtr2->pathName, -1));
349 	    }
350 	    Tcl_ListObjAppendElement(interp, listPtr,
351 		    Tcl_NewStringObj("all", -1));
352 	} else {
353 	    for (i = 0; i < winPtr->numTags; i++) {
354 		Tcl_ListObjAppendElement(interp, listPtr,
355 			Tcl_NewStringObj((char *)winPtr->tagPtr[i], -1));
356 	    }
357 	}
358 	Tcl_SetObjResult(interp, listPtr);
359 	Tcl_DecrRefCount(listPtr);
360 	return TCL_OK;
361     }
362     if (winPtr->tagPtr != NULL) {
363 	TkFreeBindingTags(winPtr);
364     }
365     if (Tcl_ListObjGetElements(interp, objv[2], &length, &tags) != TCL_OK) {
366 	return TCL_ERROR;
367     }
368     if (length == 0) {
369 	return TCL_OK;
370     }
371 
372     winPtr->numTags = length;
373     winPtr->tagPtr = (ClientData *) ckalloc((unsigned)
374 	    (length * sizeof(ClientData)));
375     for (i = 0; i < length; i++) {
376 	p = Tcl_GetString(tags[i]);
377 	if (p[0] == '.') {
378 	    char *copy;
379 
380 	    /*
381 	     * Handle names starting with "." specially: store a malloc'ed
382 	     * string, rather than a Uid;  at event time we'll look up the
383 	     * name in the window table and use the corresponding window,
384 	     * if there is one.
385 	     */
386 
387 	    copy = (char *) ckalloc((unsigned) (strlen(p) + 1));
388 	    strcpy(copy, p);
389 	    winPtr->tagPtr[i] = (ClientData) copy;
390 	} else {
391 	    winPtr->tagPtr[i] = (ClientData) Tk_GetUid(p);
392 	}
393     }
394     return TCL_OK;
395 }
396 
397 /*
398  *----------------------------------------------------------------------
399  *
400  * TkFreeBindingTags --
401  *
402  *	This procedure is called to free all of the binding tags
403  *	associated with a window;  typically it is only invoked where
404  *	there are window-specific tags.
405  *
406  * Results:
407  *	None.
408  *
409  * Side effects:
410  *	Any binding tags for winPtr are freed.
411  *
412  *----------------------------------------------------------------------
413  */
414 
415 void
TkFreeBindingTags(winPtr)416 TkFreeBindingTags(winPtr)
417     TkWindow *winPtr;		/* Window whose tags are to be released. */
418 {
419     int i;
420     char *p;
421 
422     for (i = 0; i < winPtr->numTags; i++) {
423 	p = (char *) (winPtr->tagPtr[i]);
424 	if (*p == '.') {
425 	    /*
426 	     * Names starting with "." are malloced rather than Uids, so
427 	     * they have to be freed.
428 	     */
429 
430 	    ckfree(p);
431 	}
432     }
433     ckfree((char *) winPtr->tagPtr);
434     winPtr->numTags = 0;
435     winPtr->tagPtr = NULL;
436 }
437 
438 /*
439  *----------------------------------------------------------------------
440  *
441  * Tk_DestroyObjCmd --
442  *
443  *	This procedure is invoked to process the "destroy" Tcl command.
444  *	See the user documentation for details on what it does.
445  *
446  * Results:
447  *	A standard Tcl result.
448  *
449  * Side effects:
450  *	See the user documentation.
451  *
452  *----------------------------------------------------------------------
453  */
454 
455 int
Tk_DestroyObjCmd(clientData,interp,objc,objv)456 Tk_DestroyObjCmd(clientData, interp, objc, objv)
457     ClientData clientData;		/* Main window associated with
458 				 * interpreter. */
459     Tcl_Interp *interp;		/* Current interpreter. */
460     int objc;			/* Number of arguments. */
461     Tcl_Obj *CONST objv[];	/* Argument objects. */
462 {
463     Tk_Window window;
464     Tk_Window tkwin = (Tk_Window) clientData;
465     int i;
466 
467     for (i = 1; i < objc; i++) {
468 	window = Tk_NameToWindow(interp, Tcl_GetString(objv[i]), tkwin);
469 	if (window == NULL) {
470 	    Tcl_ResetResult(interp);
471 	    continue;
472 	}
473 	Tk_DestroyWindow(window);
474 	if (window == tkwin) {
475 	    /*
476 	     * We just deleted the main window for the application! This
477 	     * makes it impossible to do anything more (tkwin isn't
478 	     * valid anymore).
479 	     */
480 
481 	    break;
482 	 }
483     }
484     return TCL_OK;
485 }
486 
487 /*
488  *----------------------------------------------------------------------
489  *
490  * Tk_LowerObjCmd --
491  *
492  *	This procedure is invoked to process the "lower" Tcl command.
493  *	See the user documentation for details on what it does.
494  *
495  * Results:
496  *	A standard Tcl result.
497  *
498  * Side effects:
499  *	See the user documentation.
500  *
501  *----------------------------------------------------------------------
502  */
503 
504 	/* ARGSUSED */
505 int
Tk_LowerObjCmd(clientData,interp,objc,objv)506 Tk_LowerObjCmd(clientData, interp, objc, objv)
507     ClientData clientData;	/* Main window associated with
508 				 * interpreter. */
509     Tcl_Interp *interp;		/* Current interpreter. */
510     int objc;			/* Number of arguments. */
511     Tcl_Obj *CONST objv[];	/* Argument objects. */
512 {
513     Tk_Window mainwin = (Tk_Window) clientData;
514     Tk_Window tkwin, other;
515 
516     if ((objc != 2) && (objc != 3)) {
517 	Tcl_WrongNumArgs(interp, 1, objv, "window ?belowThis?");
518 	return TCL_ERROR;
519     }
520 
521     tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[1]), mainwin);
522     if (tkwin == NULL) {
523 	return TCL_ERROR;
524     }
525     if (objc == 2) {
526 	other = NULL;
527     } else {
528 	other = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), mainwin);
529 	if (other == NULL) {
530 	    return TCL_ERROR;
531 	}
532     }
533     if (Tk_RestackWindow(tkwin, Below, other) != TCL_OK) {
534 	Tcl_AppendResult(interp, "can't lower \"", Tcl_GetString(objv[1]),
535 		"\" below \"", (other ? Tcl_GetString(objv[2]) : ""),
536 		"\"", (char *) NULL);
537 	return TCL_ERROR;
538     }
539     return TCL_OK;
540 }
541 
542 /*
543  *----------------------------------------------------------------------
544  *
545  * Tk_RaiseObjCmd --
546  *
547  *	This procedure is invoked to process the "raise" Tcl command.
548  *	See the user documentation for details on what it does.
549  *
550  * Results:
551  *	A standard Tcl result.
552  *
553  * Side effects:
554  *	See the user documentation.
555  *
556  *----------------------------------------------------------------------
557  */
558 
559 	/* ARGSUSED */
560 int
Tk_RaiseObjCmd(clientData,interp,objc,objv)561 Tk_RaiseObjCmd(clientData, interp, objc, objv)
562     ClientData clientData;	/* Main window associated with
563 				 * interpreter. */
564     Tcl_Interp *interp;		/* Current interpreter. */
565     int objc;			/* Number of arguments. */
566     Tcl_Obj *CONST objv[];	/* Argument objects. */
567 {
568     Tk_Window mainwin = (Tk_Window) clientData;
569     Tk_Window tkwin, other;
570 
571     if ((objc != 2) && (objc != 3)) {
572 	Tcl_WrongNumArgs(interp, 1, objv, "window ?aboveThis?");
573 	return TCL_ERROR;
574     }
575 
576     tkwin = Tk_NameToWindow(interp, Tcl_GetString(objv[1]), mainwin);
577     if (tkwin == NULL) {
578 	return TCL_ERROR;
579     }
580     if (objc == 2) {
581 	other = NULL;
582     } else {
583 	other = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), mainwin);
584 	if (other == NULL) {
585 	    return TCL_ERROR;
586 	}
587     }
588     if (Tk_RestackWindow(tkwin, Above, other) != TCL_OK) {
589 	Tcl_AppendResult(interp, "can't raise \"", Tcl_GetString(objv[1]),
590 		"\" above \"", (other ? Tcl_GetString(objv[2]) : ""),
591 		"\"", (char *) NULL);
592 	return TCL_ERROR;
593     }
594     return TCL_OK;
595 }
596 
597 /*
598  *----------------------------------------------------------------------
599  *
600  * Tk_TkObjCmd --
601  *
602  *	This procedure is invoked to process the "tk" Tcl command.
603  *	See the user documentation for details on what it does.
604  *
605  * Results:
606  *	A standard Tcl result.
607  *
608  * Side effects:
609  *	See the user documentation.
610  *
611  *----------------------------------------------------------------------
612  */
613 
614 int
Tk_TkObjCmd(clientData,interp,objc,objv)615 Tk_TkObjCmd(clientData, interp, objc, objv)
616     ClientData clientData;	/* Main window associated with interpreter. */
617     Tcl_Interp *interp;		/* Current interpreter. */
618     int objc;			/* Number of arguments. */
619     Tcl_Obj *CONST objv[];	/* Argument objects. */
620 {
621     int index;
622     Tk_Window tkwin;
623     static CONST char *optionStrings[] = {
624 	"appname",	"caret",	"scaling",	"useinputmethods",
625 	"windowingsystem",		NULL
626     };
627     enum options {
628 	TK_APPNAME,	TK_CARET,	TK_SCALING,	TK_USE_IM,
629 	TK_WINDOWINGSYSTEM
630     };
631 
632     tkwin = (Tk_Window) clientData;
633 
634     if (objc < 2) {
635 	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?");
636 	return TCL_ERROR;
637     }
638     if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
639 	    &index) != TCL_OK) {
640 	return TCL_ERROR;
641     }
642 
643     switch ((enum options) index) {
644         case TK_APPNAME: {
645 	    TkWindow *winPtr;
646 	    char *string;
647 
648 	    if (Tcl_IsSafe(interp)) {
649 		Tcl_SetResult(interp,
650 			"appname not accessible in a safe interpreter",
651 			TCL_STATIC);
652 		return TCL_ERROR;
653 	    }
654 
655 	    winPtr = (TkWindow *) tkwin;
656 
657 	    if (objc > 3) {
658 	        Tcl_WrongNumArgs(interp, 2, objv, "?newName?");
659 		return TCL_ERROR;
660 	    }
661 	    if (objc == 3) {
662 		string = Tcl_GetStringFromObj(objv[2], NULL);
663 		winPtr->nameUid = Tk_GetUid(Tk_SetAppName(tkwin, string));
664 	    }
665 	    Tcl_AppendResult(interp, winPtr->nameUid, NULL);
666 	    break;
667 	}
668 	case TK_CARET: {
669 	    Tcl_Obj *objPtr;
670 	    TkCaret *caretPtr;
671 	    Tk_Window window;
672 	    static CONST char *caretStrings[]
673 		= { "-x",	"-y", "-height", NULL };
674 	    enum caretOptions
675 		{ TK_CARET_X, TK_CARET_Y, TK_CARET_HEIGHT };
676 
677 	    if ((objc < 3) || ((objc > 4) && !(objc & 1))) {
678 	        Tcl_WrongNumArgs(interp, 2, objv,
679 			"window ?-x x? ?-y y? ?-height height?");
680 		return TCL_ERROR;
681 	    }
682 	    window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);
683 	    if (window == NULL) {
684 		return TCL_ERROR;
685 	    }
686 	    caretPtr = &(((TkWindow *) window)->dispPtr->caret);
687 	    if (objc == 3) {
688 		/*
689 		 * Return all the current values
690 		 */
691 		objPtr = Tcl_NewObj();
692 		Tcl_ListObjAppendElement(interp, objPtr,
693 			Tcl_NewStringObj("-height", 7));
694 		Tcl_ListObjAppendElement(interp, objPtr,
695 			Tcl_NewIntObj(caretPtr->height));
696 		Tcl_ListObjAppendElement(interp, objPtr,
697 			Tcl_NewStringObj("-x", 2));
698 		Tcl_ListObjAppendElement(interp, objPtr,
699 			Tcl_NewIntObj(caretPtr->x));
700 		Tcl_ListObjAppendElement(interp, objPtr,
701 			Tcl_NewStringObj("-y", 2));
702 		Tcl_ListObjAppendElement(interp, objPtr,
703 			Tcl_NewIntObj(caretPtr->y));
704 		Tcl_SetObjResult(interp, objPtr);
705 	    } else if (objc == 4) {
706 		int value;
707 		/*
708 		 * Return the current value of the selected option
709 		 */
710 		if (Tcl_GetIndexFromObj(interp, objv[3], caretStrings,
711 			"caret option", 0, &index) != TCL_OK) {
712 		    return TCL_ERROR;
713 		}
714 		if (index == TK_CARET_X) {
715 		    value = caretPtr->x;
716 		} else if (index == TK_CARET_Y) {
717 		    value = caretPtr->y;
718 		} else /* if (index == TK_CARET_HEIGHT) -- last case */ {
719 		    value = caretPtr->height;
720 		}
721 		Tcl_SetIntObj(Tcl_GetObjResult(interp), value);
722 	    } else {
723 		int i, value, x = 0, y = 0, height = -1;
724 
725 		for (i = 3; i < objc; i += 2) {
726 		    if ((Tcl_GetIndexFromObj(interp, objv[i], caretStrings,
727 			    "caret option", 0, &index) != TCL_OK) ||
728 			    (Tcl_GetIntFromObj(interp, objv[i+1], &value)
729 				!= TCL_OK)) {
730 			return TCL_ERROR;
731 		    }
732 		    if (index == TK_CARET_X) {
733 			x = value;
734 		    } else if (index == TK_CARET_Y) {
735 			y = value;
736 		    } else /* if (index == TK_CARET_HEIGHT) -- last case */ {
737 			height = value;
738 		    }
739 		}
740 		if (height < 0) {
741 		    height = Tk_Height(window);
742 		}
743 		Tk_SetCaretPos(window, x, y, height);
744 	    }
745 	    break;
746 	}
747 	case TK_SCALING: {
748 	    Screen *screenPtr;
749 	    int skip, width, height;
750 	    double d;
751 
752 	    if (Tcl_IsSafe(interp)) {
753 		Tcl_SetResult(interp,
754 			"scaling not accessible in a safe interpreter",
755 			TCL_STATIC);
756 		return TCL_ERROR;
757 	    }
758 
759 	    screenPtr = Tk_Screen(tkwin);
760 
761 	    skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
762 	    if (skip < 0) {
763 		return TCL_ERROR;
764 	    }
765 	    if (objc - skip == 2) {
766 		d = 25.4 / 72;
767 		d *= WidthOfScreen(screenPtr);
768 		d /= WidthMMOfScreen(screenPtr);
769 		Tcl_SetDoubleObj(Tcl_GetObjResult(interp), d);
770 	    } else if (objc - skip == 3) {
771 		if (Tcl_GetDoubleFromObj(interp, objv[2+skip], &d) != TCL_OK) {
772 		    return TCL_ERROR;
773 		}
774 		d = (25.4 / 72) / d;
775 		width = (int) (d * WidthOfScreen(screenPtr) + 0.5);
776 		if (width <= 0) {
777 		    width = 1;
778 		}
779 		height = (int) (d * HeightOfScreen(screenPtr) + 0.5);
780 		if (height <= 0) {
781 		    height = 1;
782 		}
783 		WidthMMOfScreen(screenPtr) = width;
784 		HeightMMOfScreen(screenPtr) = height;
785 	    } else {
786 		Tcl_WrongNumArgs(interp, 2, objv,
787 			"?-displayof window? ?factor?");
788 		return TCL_ERROR;
789 	    }
790 	    break;
791 	}
792 	case TK_USE_IM: {
793 	    TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
794 	    int skip;
795 
796 	    if (Tcl_IsSafe(interp)) {
797 		Tcl_SetResult(interp,
798 			"useinputmethods not accessible in a safe interpreter",
799 			TCL_STATIC);
800 		return TCL_ERROR;
801 	    }
802 
803 	    skip = TkGetDisplayOf(interp, objc-2, objv+2, &tkwin);
804 	    if (skip < 0) {
805 		return TCL_ERROR;
806 	    } else if (skip) {
807 		dispPtr = ((TkWindow *) tkwin)->dispPtr;
808 	    }
809 	    if ((objc - skip) == 3) {
810 		/*
811 		 * In the case where TK_USE_INPUT_METHODS is not defined,
812 		 * this will be ignored and we will always return 0.
813 		 * That will indicate to the user that input methods
814 		 * are just not available.
815 		 */
816 		int boolVal;
817 		if (Tcl_GetBooleanFromObj(interp, objv[2+skip], &boolVal)
818 			!= TCL_OK) {
819 		    return TCL_ERROR;
820 		}
821 #ifdef TK_USE_INPUT_METHODS
822 		if (boolVal) {
823 		    dispPtr->flags |= TK_DISPLAY_USE_IM;
824 		} else {
825 		    dispPtr->flags &= ~TK_DISPLAY_USE_IM;
826 		}
827 #endif /* TK_USE_INPUT_METHODS */
828 	    } else if ((objc - skip) != 2) {
829 		Tcl_WrongNumArgs(interp, 2, objv,
830 			"?-displayof window? ?boolean?");
831 		return TCL_ERROR;
832 	    }
833 	    Tcl_SetBooleanObj(Tcl_GetObjResult(interp),
834 		    (int) (dispPtr->flags & TK_DISPLAY_USE_IM));
835 	    break;
836 	}
837         case TK_WINDOWINGSYSTEM: {
838 	    CONST char *windowingsystem;
839 
840 	    if (objc != 2) {
841 	        Tcl_WrongNumArgs(interp, 2, objv, NULL);
842 		return TCL_ERROR;
843 	    }
844 #if defined(WIN32)
845 	    windowingsystem = "win32";
846 #elif defined(MAC_TCL)
847 	    windowingsystem = "classic";
848 #elif defined(MAC_OSX_TK)
849 	    windowingsystem = "aqua";
850 #else
851 	    windowingsystem = "x11";
852 #endif
853 	    Tcl_SetStringObj(Tcl_GetObjResult(interp), windowingsystem, -1);
854 	    break;
855 	}
856     }
857     return TCL_OK;
858 }
859 
860 /*
861  *----------------------------------------------------------------------
862  *
863  * Tk_TkwaitObjCmd --
864  *
865  *	This procedure is invoked to process the "tkwait" Tcl command.
866  *	See the user documentation for details on what it does.
867  *
868  * Results:
869  *	A standard Tcl result.
870  *
871  * Side effects:
872  *	See the user documentation.
873  *
874  *----------------------------------------------------------------------
875  */
876 
877 	/* ARGSUSED */
878 int
Tk_TkwaitObjCmd(clientData,interp,objc,objv)879 Tk_TkwaitObjCmd(clientData, interp, objc, objv)
880     ClientData clientData;	/* Main window associated with
881 				 * interpreter. */
882     Tcl_Interp *interp;		/* Current interpreter. */
883     int objc;			/* Number of arguments. */
884     Tcl_Obj *CONST objv[];	/* Argument objects. */
885 {
886     Tk_Window tkwin = (Tk_Window) clientData;
887     int done, index;
888     static CONST char *optionStrings[] = { "variable", "visibility", "window",
889 					 (char *) NULL };
890     enum options { TKWAIT_VARIABLE, TKWAIT_VISIBILITY, TKWAIT_WINDOW };
891 
892     if (objc != 3) {
893 	Tcl_WrongNumArgs(interp, 1, objv, "variable|visibility|window name");
894 	return TCL_ERROR;
895     }
896 
897     if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
898 	    &index) != TCL_OK) {
899 	return TCL_ERROR;
900     }
901 
902     switch ((enum options) index) {
903 	case TKWAIT_VARIABLE: {
904 	    if (Lang_TraceVar(interp, objv[2],
905 		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
906 		    WaitVariableProc, (ClientData) &done) != TCL_OK) {
907 		return TCL_ERROR;
908 	    }
909 	    done = 0;
910 	    while (!done) {
911 		Tcl_DoOneEvent(0);
912 	    }
913 	    Lang_UntraceVar(interp, objv[2],
914 		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
915 		    WaitVariableProc, (ClientData) &done);
916 	    break;
917 	}
918 
919 	case TKWAIT_VISIBILITY: {
920 	    Tk_Window window;
921 
922 	    window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);
923 	    if (window == NULL) {
924 		return TCL_ERROR;
925 	    }
926 	    Tk_CreateEventHandler(window,
927 		    VisibilityChangeMask|StructureNotifyMask,
928 		    WaitVisibilityProc, (ClientData) &done);
929 	    done = 0;
930 	    while (!done) {
931 		Tcl_DoOneEvent(0);
932 	    }
933 	    if (done != 1) {
934 		/*
935 		 * Note that we do not delete the event handler because it
936 		 * was deleted automatically when the window was destroyed.
937 		 */
938 
939 		Tcl_ResetResult(interp);
940 		Tcl_AppendResult(interp, "window \"", Tcl_GetString(objv[2]),
941 			"\" was deleted before its visibility changed",
942 			(char *) NULL);
943 		return TCL_ERROR;
944 	    }
945 	    Tk_DeleteEventHandler(window,
946 		    VisibilityChangeMask|StructureNotifyMask,
947 		    WaitVisibilityProc, (ClientData) &done);
948 	    break;
949 	}
950 
951 	case TKWAIT_WINDOW: {
952 	    Tk_Window window;
953 
954 	    window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin);
955 	    if (window == NULL) {
956 		return TCL_ERROR;
957 	    }
958 	    Tk_CreateEventHandler(window, StructureNotifyMask,
959 		    WaitWindowProc, (ClientData) &done);
960 	    done = 0;
961 	    while (!done) {
962 		Tcl_DoOneEvent(0);
963 	    }
964 	    /*
965 	     * Note:  there's no need to delete the event handler.  It was
966 	     * deleted automatically when the window was destroyed.
967 	     */
968 	    break;
969 	}
970     }
971 
972     /*
973      * Clear out the interpreter's result, since it may have been set
974      * by event handlers.
975      */
976 
977     Tcl_ResetResult(interp);
978     return TCL_OK;
979 }
980 
981 	/* ARGSUSED */
982 static char *
WaitVariableProc(clientData,interp,name1,name2,flags)983 WaitVariableProc(clientData, interp, name1, name2, flags)
984     ClientData clientData;	/* Pointer to integer to set to 1. */
985     Tcl_Interp *interp;		/* Interpreter containing variable. */
986     Var name1;			/* Name of variable. */
987     CONST char *name2;		/* Second part of variable name. */
988     int flags;			/* Information about what happened. */
989 {
990     int *donePtr = (int *) clientData;
991 
992     *donePtr = 1;
993     return (char *) NULL;
994 }
995 
996 	/*ARGSUSED*/
997 static void
WaitVisibilityProc(clientData,eventPtr)998 WaitVisibilityProc(clientData, eventPtr)
999     ClientData clientData;	/* Pointer to integer to set to 1. */
1000     XEvent *eventPtr;		/* Information about event (not used). */
1001 {
1002     int *donePtr = (int *) clientData;
1003 
1004     if (eventPtr->type == VisibilityNotify) {
1005 	*donePtr = 1;
1006     }
1007     if (eventPtr->type == DestroyNotify) {
1008 	*donePtr = 2;
1009     }
1010 }
1011 
1012 static void
WaitWindowProc(clientData,eventPtr)1013 WaitWindowProc(clientData, eventPtr)
1014     ClientData clientData;	/* Pointer to integer to set to 1. */
1015     XEvent *eventPtr;		/* Information about event. */
1016 {
1017     int *donePtr = (int *) clientData;
1018 
1019     if (eventPtr->type == DestroyNotify) {
1020 	*donePtr = 1;
1021     }
1022 }
1023 
1024 /*
1025  *----------------------------------------------------------------------
1026  *
1027  * Tk_UpdateObjCmd --
1028  *
1029  *	This procedure is invoked to process the "update" Tcl command.
1030  *	See the user documentation for details on what it does.
1031  *
1032  * Results:
1033  *	A standard Tcl result.
1034  *
1035  * Side effects:
1036  *	See the user documentation.
1037  *
1038  *----------------------------------------------------------------------
1039  */
1040 
1041 	/* ARGSUSED */
1042 int
Tk_UpdateObjCmd(clientData,interp,objc,objv)1043 Tk_UpdateObjCmd(clientData, interp, objc, objv)
1044     ClientData clientData;	/* Main window associated with
1045 				 * interpreter. */
1046     Tcl_Interp *interp;		/* Current interpreter. */
1047     int objc;			/* Number of arguments. */
1048     Tcl_Obj *CONST objv[];	/* Argument objects. */
1049 {
1050     static CONST char *updateOptions[] = {"idletasks", (char *) NULL};
1051     int flags, index;
1052     TkDisplay *dispPtr;
1053 
1054     if (objc == 1) {
1055 	flags = TCL_DONT_WAIT;
1056     } else if (objc == 2) {
1057 	if (Tcl_GetIndexFromObj(interp, objv[1], updateOptions, "option", 0,
1058 		&index) != TCL_OK) {
1059 	    return TCL_ERROR;
1060 	}
1061 	flags = TCL_IDLE_EVENTS;
1062     } else {
1063         Tcl_WrongNumArgs(interp, 1, objv, "?idletasks?");
1064 	return TCL_ERROR;
1065     }
1066 
1067     /*
1068      * Handle all pending events, sync all displays, and repeat over
1069      * and over again until all pending events have been handled.
1070      * Special note:  it's possible that the entire application could
1071      * be destroyed by an event handler that occurs during the update.
1072      * Thus, don't use any information from tkwin after calling
1073      * Tcl_DoOneEvent.
1074      */
1075 
1076     while (1) {
1077 	while (Tcl_DoOneEvent(flags) != 0) {
1078 	    /* Empty loop body */
1079 	}
1080 	for (dispPtr = TkGetDisplayList(); dispPtr != NULL;
1081 		dispPtr = dispPtr->nextPtr) {
1082 	    XSync(dispPtr->display, False);
1083 	}
1084 	if (Tcl_DoOneEvent(flags) == 0) {
1085 	    break;
1086 	}
1087     }
1088 
1089     /*
1090      * Must clear the interpreter's result because event handlers could
1091      * have executed commands.
1092      */
1093 
1094     Tcl_ResetResult(interp);
1095     return TCL_OK;
1096 }
1097 
1098 /*
1099  *----------------------------------------------------------------------
1100  *
1101  * Tk_WinfoObjCmd --
1102  *
1103  *	This procedure is invoked to process the "winfo" Tcl command.
1104  *	See the user documentation for details on what it does.
1105  *
1106  * Results:
1107  *	A standard Tcl result.
1108  *
1109  * Side effects:
1110  *	See the user documentation.
1111  *
1112  *----------------------------------------------------------------------
1113  */
1114 
1115 int
Tk_WinfoObjCmd(clientData,interp,objc,objv)1116 Tk_WinfoObjCmd(clientData, interp, objc, objv)
1117     ClientData clientData;	/* Main window associated with
1118 				 * interpreter. */
1119     Tcl_Interp *interp;		/* Current interpreter. */
1120     int objc;			/* Number of arguments. */
1121     Tcl_Obj *CONST objv[];	/* Argument objects. */
1122 {
1123     int index, x, y, width, height, useX, useY, class, skip;
1124     char *string;
1125     TkWindow *winPtr;
1126     Tk_Window tkwin;
1127     Tcl_Obj *resultPtr;
1128 
1129     static TkStateMap visualMap[] = {
1130 	{PseudoColor,	"pseudocolor"},
1131 	{GrayScale,	"grayscale"},
1132 	{DirectColor,	"directcolor"},
1133 	{TrueColor,	"truecolor"},
1134 	{StaticColor,	"staticcolor"},
1135 	{StaticGray,	"staticgray"},
1136 	{-1,		NULL}
1137     };
1138     static CONST char *optionStrings[] = {
1139 	"cells",	"children",	"class",	"colormapfull",
1140 	"depth",	"geometry",	"height",	"id",
1141 	"ismapped",	"manager",	"name",		"parent",
1142 	"pointerx",	"pointery",	"pointerxy",	"reqheight",
1143 	"reqwidth",	"rootx",	"rooty",	"screen",
1144 	"screencells",	"screendepth",	"screenheight",	"screenwidth",
1145 	"screenmmheight","screenmmwidth","screenvisual","server",
1146 	"toplevel",	"viewable",	"visual",	"visualid",
1147 	"vrootheight",	"vrootwidth",	"vrootx",	"vrooty",
1148 	"width",	"x",		"y",
1149 
1150 	"atom",		"atomname",	"containing",	"interps",
1151 	"pathname",
1152 
1153 	"exists",	"fpixels",	"pixels",	"rgb",
1154 	"visualsavailable",
1155 
1156 	NULL
1157     };
1158     enum options {
1159 	WIN_CELLS,	WIN_CHILDREN,	WIN_CLASS,	WIN_COLORMAPFULL,
1160 	WIN_DEPTH,	WIN_GEOMETRY,	WIN_HEIGHT,	WIN_ID,
1161 	WIN_ISMAPPED,	WIN_MANAGER,	WIN_NAME,	WIN_PARENT,
1162 	WIN_POINTERX,	WIN_POINTERY,	WIN_POINTERXY,	WIN_REQHEIGHT,
1163 	WIN_REQWIDTH,	WIN_ROOTX,	WIN_ROOTY,	WIN_SCREEN,
1164 	WIN_SCREENCELLS,WIN_SCREENDEPTH,WIN_SCREENHEIGHT,WIN_SCREENWIDTH,
1165 	WIN_SCREENMMHEIGHT,WIN_SCREENMMWIDTH,WIN_SCREENVISUAL,WIN_SERVER,
1166 	WIN_TOPLEVEL,	WIN_VIEWABLE,	WIN_VISUAL,	WIN_VISUALID,
1167 	WIN_VROOTHEIGHT,WIN_VROOTWIDTH,	WIN_VROOTX,	WIN_VROOTY,
1168 	WIN_WIDTH,	WIN_X,		WIN_Y,
1169 
1170 	WIN_ATOM,	WIN_ATOMNAME,	WIN_CONTAINING,	WIN_INTERPS,
1171 	WIN_PATHNAME,
1172 
1173 	WIN_EXISTS,	WIN_FPIXELS,	WIN_PIXELS,	WIN_RGB,
1174 	WIN_VISUALSAVAILABLE
1175     };
1176 
1177     tkwin = (Tk_Window) clientData;
1178 
1179     if (objc < 2) {
1180 	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?");
1181 	return TCL_ERROR;
1182     }
1183     if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
1184 	    &index) != TCL_OK) {
1185 	return TCL_ERROR;
1186     }
1187 
1188     if (index < WIN_ATOM) {
1189 	if (objc != 3) {
1190 	    Tcl_WrongNumArgs(interp, 2, objv, "window");
1191 	    return TCL_ERROR;
1192 	}
1193 	string = Tcl_GetStringFromObj(objv[2], NULL);
1194 	tkwin = Tk_NameToWindow(interp, string, tkwin);
1195 	if (tkwin == NULL) {
1196 	    return TCL_ERROR;
1197 	}
1198     }
1199     winPtr = (TkWindow *) tkwin;
1200     resultPtr = Tcl_GetObjResult(interp);
1201 
1202     switch ((enum options) index) {
1203 	case WIN_CELLS: {
1204 	    Tcl_SetIntObj(resultPtr, Tk_Visual(tkwin)->map_entries);
1205 	    break;
1206 	}
1207 	case WIN_CHILDREN: {
1208 	    Tcl_Obj *strPtr;
1209 
1210 	    winPtr = winPtr->childList;
1211 	    for ( ; winPtr != NULL; winPtr = winPtr->nextPtr) {
1212 		if (!(winPtr->flags & TK_ANONYMOUS_WINDOW)) {
1213 		    strPtr = LangWidgetObj(interp,(Tk_Window) winPtr);
1214 		    Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);
1215 		}
1216 	    }
1217 	    break;
1218 	}
1219 	case WIN_CLASS: {
1220 	    Tcl_SetStringObj(resultPtr, Tk_Class(tkwin), -1);
1221 	    break;
1222 	}
1223 	case WIN_COLORMAPFULL: {
1224 	    Tcl_SetBooleanObj(resultPtr,
1225 		    TkpCmapStressed(tkwin, Tk_Colormap(tkwin)));
1226 	    break;
1227 	}
1228 	case WIN_DEPTH: {
1229 	    Tcl_SetIntObj(resultPtr, Tk_Depth(tkwin));
1230 	    break;
1231 	}
1232 	case WIN_GEOMETRY: {
1233 	    char buf[16 + TCL_INTEGER_SPACE * 4];
1234 
1235 	    sprintf(buf, "%dx%d+%d+%d", Tk_Width(tkwin), Tk_Height(tkwin),
1236 		    Tk_X(tkwin), Tk_Y(tkwin));
1237 	    Tcl_SetStringObj(resultPtr, buf, -1);
1238 	    break;
1239 	}
1240 	case WIN_HEIGHT: {
1241 	    Tcl_SetIntObj(resultPtr, Tk_Height(tkwin));
1242 	    break;
1243 	}
1244 	case WIN_ID: {
1245 	    char buf[TCL_INTEGER_SPACE];
1246 
1247 	    Tk_MakeWindowExist(tkwin);
1248 	    TkpPrintWindowId(buf, Tk_WindowId(tkwin));
1249 	    Tcl_SetStringObj(resultPtr, buf, -1);
1250 	    break;
1251 	}
1252 	case WIN_ISMAPPED: {
1253 	    Tcl_SetBooleanObj(resultPtr, (int) Tk_IsMapped(tkwin));
1254 	    break;
1255 	}
1256 	case WIN_MANAGER: {
1257 	    if (winPtr->geomMgrPtr != NULL) {
1258 		Tcl_SetStringObj(resultPtr, winPtr->geomMgrPtr->name, -1);
1259 	    }
1260 	    break;
1261 	}
1262 	case WIN_NAME: {
1263 	    Tcl_SetStringObj(resultPtr, Tk_Name(tkwin), -1);
1264 	    break;
1265 	}
1266 	case WIN_PARENT: {
1267 	    if (winPtr->parentPtr != NULL) {
1268 		Tcl_SetObjResult(interp, LangWidgetObj(interp, (Tk_Window) winPtr->parentPtr));
1269 	    }
1270 	    break;
1271 	}
1272 	case WIN_POINTERX: {
1273 	    useX = 1;
1274 	    useY = 0;
1275 	    goto pointerxy;
1276 	}
1277 	case WIN_POINTERY: {
1278 	    useX = 0;
1279 	    useY = 1;
1280 	    goto pointerxy;
1281 	}
1282 	case WIN_POINTERXY: {
1283 	    useX = 1;
1284 	    useY = 1;
1285 
1286 	    pointerxy:
1287 	    winPtr = GetToplevel(tkwin);
1288 	    if (winPtr == NULL) {
1289 		x = -1;
1290 		y = -1;
1291 	    } else {
1292 		TkGetPointerCoords((Tk_Window) winPtr, &x, &y);
1293 	    }
1294 	    if (useX & useY) {
1295 		Tcl_IntResults(interp, 2, 0, x, y);
1296 	    } else if (useX) {
1297 		Tcl_SetIntObj(resultPtr, x);
1298 	    } else {
1299 		Tcl_SetIntObj(resultPtr, y);
1300 	    }
1301 	    break;
1302 	}
1303 	case WIN_REQHEIGHT: {
1304 	    Tcl_SetIntObj(resultPtr, Tk_ReqHeight(tkwin));
1305 	    break;
1306 	}
1307 	case WIN_REQWIDTH: {
1308 	    Tcl_SetIntObj(resultPtr, Tk_ReqWidth(tkwin));
1309 	    break;
1310 	}
1311 	case WIN_ROOTX: {
1312 	    Tk_GetRootCoords(tkwin, &x, &y);
1313 	    Tcl_SetIntObj(resultPtr, x);
1314 	    break;
1315 	}
1316 	case WIN_ROOTY: {
1317 	    Tk_GetRootCoords(tkwin, &x, &y);
1318 	    Tcl_SetIntObj(resultPtr, y);
1319 	    break;
1320 	}
1321 	case WIN_SCREEN: {
1322 	    char buf[TCL_INTEGER_SPACE];
1323 
1324 	    sprintf(buf, "%d", Tk_ScreenNumber(tkwin));
1325 	    Tcl_AppendStringsToObj(resultPtr, Tk_DisplayName(tkwin), ".",
1326 		    buf, NULL);
1327 	    break;
1328 	}
1329 	case WIN_SCREENCELLS: {
1330 	    Tcl_SetIntObj(resultPtr, CellsOfScreen(Tk_Screen(tkwin)));
1331 	    break;
1332 	}
1333 	case WIN_SCREENDEPTH: {
1334 	    Tcl_SetIntObj(resultPtr, DefaultDepthOfScreen(Tk_Screen(tkwin)));
1335 	    break;
1336 	}
1337 	case WIN_SCREENHEIGHT: {
1338 	    Tcl_SetIntObj(resultPtr, HeightOfScreen(Tk_Screen(tkwin)));
1339 	    break;
1340 	}
1341 	case WIN_SCREENWIDTH: {
1342 	    Tcl_SetIntObj(resultPtr, WidthOfScreen(Tk_Screen(tkwin)));
1343 	    break;
1344 	}
1345 	case WIN_SCREENMMHEIGHT: {
1346 	    Tcl_SetIntObj(resultPtr, HeightMMOfScreen(Tk_Screen(tkwin)));
1347 	    break;
1348 	}
1349 	case WIN_SCREENMMWIDTH: {
1350 	    Tcl_SetIntObj(resultPtr, WidthMMOfScreen(Tk_Screen(tkwin)));
1351 	    break;
1352 	}
1353 	case WIN_SCREENVISUAL: {
1354 	    class = DefaultVisualOfScreen(Tk_Screen(tkwin))->class;
1355 	    goto visual;
1356 	}
1357 	case WIN_SERVER: {
1358 	    TkGetServerInfo(interp, tkwin);
1359 	    break;
1360 	}
1361 	case WIN_TOPLEVEL: {
1362 	    winPtr = GetToplevel(tkwin);
1363 	    if (winPtr != NULL) {
1364 		Tcl_ResetResult(interp);
1365 		Tcl_SetObjResult(interp, LangWidgetObj(interp, (Tk_Window) winPtr));
1366 	    }
1367 	    break;
1368 	}
1369 	case WIN_VIEWABLE: {
1370 	    int viewable = 0;
1371 	    for ( ; ; winPtr = winPtr->parentPtr) {
1372 		if ((winPtr == NULL) || !(winPtr->flags & TK_MAPPED)) {
1373 		    break;
1374 		}
1375 		if (winPtr->flags & TK_TOP_HIERARCHY) {
1376 		    viewable = 1;
1377 		    break;
1378 		}
1379 	    }
1380 
1381 	    Tcl_SetBooleanObj(resultPtr, viewable);
1382 	    break;
1383 	}
1384 	case WIN_VISUAL: {
1385 	    class = Tk_Visual(tkwin)->class;
1386 
1387 	    visual:
1388 	    string = TkFindStateString(visualMap, class);
1389 	    if (string == NULL) {
1390 		string = "unknown";
1391 	    }
1392 	    Tcl_SetStringObj(resultPtr, string, -1);
1393 	    break;
1394 	}
1395 	case WIN_VISUALID: {
1396 	    char buf[TCL_INTEGER_SPACE];
1397 
1398 	    sprintf(buf, "0x%x",
1399 		    (unsigned int) XVisualIDFromVisual(Tk_Visual(tkwin)));
1400 	    Tcl_SetStringObj(resultPtr, buf, -1);
1401 	    break;
1402 	}
1403 	case WIN_VROOTHEIGHT: {
1404 	    Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
1405 	    Tcl_SetIntObj(resultPtr, height);
1406 	    break;
1407 	}
1408 	case WIN_VROOTWIDTH: {
1409 	    Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
1410 	    Tcl_SetIntObj(resultPtr, width);
1411 	    break;
1412 	}
1413 	case WIN_VROOTX: {
1414 	    Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
1415 	    Tcl_SetIntObj(resultPtr, x);
1416 	    break;
1417 	}
1418 	case WIN_VROOTY: {
1419 	    Tk_GetVRootGeometry(tkwin, &x, &y, &width, &height);
1420 	    Tcl_SetIntObj(resultPtr, y);
1421 	    break;
1422 	}
1423 	case WIN_WIDTH: {
1424 	    Tcl_SetIntObj(resultPtr, Tk_Width(tkwin));
1425 	    break;
1426 	}
1427 	case WIN_X: {
1428 	    Tcl_SetIntObj(resultPtr, Tk_X(tkwin));
1429 	    break;
1430 	}
1431 	case WIN_Y: {
1432 	    Tcl_SetIntObj(resultPtr, Tk_Y(tkwin));
1433 	    break;
1434 	}
1435 
1436 	/*
1437 	 * Uses -displayof.
1438 	 */
1439 
1440 	case WIN_ATOM: {
1441 	    skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
1442 	    if (skip < 0) {
1443 		return TCL_ERROR;
1444 	    }
1445 	    if (objc - skip != 3) {
1446 	        Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? name");
1447 		return TCL_ERROR;
1448 	    }
1449 	    objv += skip;
1450 	    string = Tcl_GetStringFromObj(objv[2], NULL);
1451 	    Tcl_SetLongObj(resultPtr, (long) Tk_InternAtom(tkwin, string));
1452 	    break;
1453 	}
1454 	case WIN_ATOMNAME: {
1455 	    CONST char *name;
1456 	    long id;
1457 
1458 	    skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
1459 	    if (skip < 0) {
1460 		return TCL_ERROR;
1461 	    }
1462 	    if (objc - skip != 3) {
1463 		Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? id");
1464 		return TCL_ERROR;
1465 	    }
1466 	    objv += skip;
1467 	    if (Tcl_GetLongFromObj(interp, objv[2], &id) != TCL_OK) {
1468 		return TCL_ERROR;
1469 	    }
1470 	    name = Tk_GetAtomName(tkwin, (Atom) id);
1471 	    if (strcmp(name, "?bad atom?") == 0) {
1472 		string = Tcl_GetStringFromObj(objv[2], NULL);
1473 		Tcl_AppendStringsToObj(resultPtr,
1474 			"no atom exists with id \"", string, "\"", NULL);
1475 		return TCL_ERROR;
1476 	    }
1477 	    Tcl_SetStringObj(resultPtr, name, -1);
1478 	    break;
1479 	}
1480 	case WIN_CONTAINING: {
1481 	    skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
1482 	    if (skip < 0) {
1483 		return TCL_ERROR;
1484 	    }
1485 	    if (objc - skip != 4) {
1486 		Tcl_WrongNumArgs(interp, 2, objv,
1487 			"?-displayof window? rootX rootY");
1488 		return TCL_ERROR;
1489 	    }
1490 	    objv += skip;
1491 	    string = Tcl_GetStringFromObj(objv[2], NULL);
1492 	    if (Tk_GetPixels(interp, tkwin, string, &x) != TCL_OK) {
1493 		return TCL_ERROR;
1494 	    }
1495 	    string = Tcl_GetStringFromObj(objv[3], NULL);
1496 	    if (Tk_GetPixels(interp, tkwin, string, &y) != TCL_OK) {
1497 		return TCL_ERROR;
1498 	    }
1499 	    tkwin = Tk_CoordsToWindow(x, y, tkwin);
1500 	    if (tkwin != NULL) {
1501 		Tcl_ResetResult(interp);
1502 		Tcl_SetObjResult(interp, LangWidgetObj(interp, tkwin));
1503 	    }
1504 	    break;
1505 	}
1506 	case WIN_INTERPS: {
1507 	    int result;
1508 
1509 	    skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
1510 	    if (skip < 0) {
1511 		return TCL_ERROR;
1512 	    }
1513 	    if (objc - skip != 2) {
1514 		Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window?");
1515 		return TCL_ERROR;
1516 	    }
1517 	    result = TkGetInterpNames(interp, tkwin);
1518 	    return result;
1519 	}
1520 	case WIN_PATHNAME: {
1521 	    Window id;
1522 
1523 	    skip = TkGetDisplayOf(interp, objc - 2, objv + 2, &tkwin);
1524 	    if (skip < 0) {
1525 		return TCL_ERROR;
1526 	    }
1527 	    if (objc - skip != 3) {
1528 		Tcl_WrongNumArgs(interp, 2, objv, "?-displayof window? id");
1529 		return TCL_ERROR;
1530 	    }
1531 	    if (TkpScanWindowId(interp, objv[2+skip], &id) != TCL_OK) {
1532 		return TCL_ERROR;
1533 	    }
1534 	    winPtr = (TkWindow *)Tk_IdToWindow(Tk_Display(tkwin), id);
1535 	    if ((winPtr == NULL) ||
1536 		    (winPtr->mainPtr != ((TkWindow *) tkwin)->mainPtr)) {
1537 	        string = Tcl_GetStringFromObj(objv[2 + skip], NULL);
1538 		Tcl_AppendStringsToObj(resultPtr, "window id \"", string,
1539 			"\" doesn't exist in this application", (char *) NULL);
1540 		return TCL_ERROR;
1541 	    }
1542 
1543 	    /*
1544 	     * If the window is a utility window with no associated path
1545 	     * (such as a wrapper window or send communication window), just
1546 	     * return an empty string.
1547 	     */
1548 
1549 	    tkwin = (Tk_Window) winPtr;
1550 	    if (Tk_PathName(tkwin) != NULL) {
1551 		Tcl_ResetResult(interp);
1552 		Tcl_SetObjResult(interp, LangWidgetObj(interp,tkwin));
1553 	    }
1554 	    break;
1555 	}
1556 
1557 	/*
1558 	 * objv[3] is window.
1559 	 */
1560 
1561 	case WIN_EXISTS: {
1562 	    int alive;
1563 
1564 	    if (objc != 3) {
1565 		Tcl_WrongNumArgs(interp, 2, objv, "window");
1566 		return TCL_ERROR;
1567 	    }
1568 	    string = Tcl_GetStringFromObj(objv[2], NULL);
1569 	    winPtr = (TkWindow *) Tk_NameToWindow(interp, string, tkwin);
1570 	    Tcl_ResetResult(interp);
1571 	    resultPtr = Tcl_GetObjResult(interp);
1572 
1573 	    alive = 1;
1574 	    if ((winPtr == NULL) || (winPtr->flags & TK_ALREADY_DEAD)) {
1575 		alive = 0;
1576 	    }
1577 	    Tcl_SetBooleanObj(resultPtr, alive);
1578 	    break;
1579 	}
1580 	case WIN_FPIXELS: {
1581 	    double mm, pixels;
1582 
1583 	    if (objc != 4) {
1584 		Tcl_WrongNumArgs(interp, 2, objv, "window number");
1585 		return TCL_ERROR;
1586 	    }
1587 	    string = Tcl_GetStringFromObj(objv[2], NULL);
1588 	    tkwin = Tk_NameToWindow(interp, string, tkwin);
1589 	    if (tkwin == NULL) {
1590 		return TCL_ERROR;
1591 	    }
1592 	    string = Tcl_GetStringFromObj(objv[3], NULL);
1593 	    if (Tk_GetScreenMM(interp, tkwin, string, &mm) != TCL_OK) {
1594 		return TCL_ERROR;
1595 	    }
1596 	    pixels = mm * WidthOfScreen(Tk_Screen(tkwin))
1597 		    / WidthMMOfScreen(Tk_Screen(tkwin));
1598 	    Tcl_SetDoubleObj(resultPtr, pixels);
1599 	    break;
1600 	}
1601 	case WIN_PIXELS: {
1602 	    int pixels;
1603 
1604 	    if (objc != 4) {
1605 		Tcl_WrongNumArgs(interp, 2, objv, "window number");
1606 		return TCL_ERROR;
1607 	    }
1608 	    string = Tcl_GetStringFromObj(objv[2], NULL);
1609 	    tkwin = Tk_NameToWindow(interp, string, tkwin);
1610 	    if (tkwin == NULL) {
1611 		return TCL_ERROR;
1612 	    }
1613 	    string = Tcl_GetStringFromObj(objv[3], NULL);
1614 	    if (Tk_GetPixels(interp, tkwin, string, &pixels) != TCL_OK) {
1615 		return TCL_ERROR;
1616 	    }
1617 	    Tcl_SetIntObj(resultPtr, pixels);
1618 	    break;
1619 	}
1620 	case WIN_RGB: {
1621 	    XColor *colorPtr;
1622 
1623 	    if (objc != 4) {
1624 		Tcl_WrongNumArgs(interp, 2, objv, "window colorName");
1625 		return TCL_ERROR;
1626 	    }
1627 	    string = Tcl_GetStringFromObj(objv[2], NULL);
1628 	    tkwin = Tk_NameToWindow(interp, string, tkwin);
1629 	    if (tkwin == NULL) {
1630 		return TCL_ERROR;
1631 	    }
1632 	    string = Tcl_GetStringFromObj(objv[3], NULL);
1633 	    colorPtr = Tk_GetColor(interp, tkwin, string);
1634 	    if (colorPtr == NULL) {
1635 		return TCL_ERROR;
1636 	    }
1637 	    Tcl_IntResults(interp, 3, 0, colorPtr->red, colorPtr->green,
1638 		    colorPtr->blue);
1639 	    Tk_FreeColor(colorPtr);
1640 	    break;
1641 	}
1642 	case WIN_VISUALSAVAILABLE: {
1643 	    XVisualInfo template, *visInfoPtr;
1644 	    int count, i;
1645 	    int includeVisualId;
1646 	    Tcl_Obj *strPtr;
1647 	    char buf[16 + TCL_INTEGER_SPACE];
1648 	    char visualIdString[TCL_INTEGER_SPACE];
1649 
1650 	    if (objc == 3) {
1651 		includeVisualId = 0;
1652 	    } else if ((objc == 4)
1653 		    && (strcmp(Tcl_GetStringFromObj(objv[3], NULL),
1654 			    "includeids") == 0)) {
1655 		includeVisualId = 1;
1656 	    } else {
1657 		Tcl_WrongNumArgs(interp, 2, objv, "window ?includeids?");
1658 		return TCL_ERROR;
1659 	    }
1660 
1661 	    string = Tcl_GetStringFromObj(objv[2], NULL);
1662 	    tkwin = Tk_NameToWindow(interp, string, tkwin);
1663 	    if (tkwin == NULL) {
1664 		return TCL_ERROR;
1665 	    }
1666 
1667 	    template.screen = Tk_ScreenNumber(tkwin);
1668 	    visInfoPtr = XGetVisualInfo(Tk_Display(tkwin), VisualScreenMask,
1669 		    &template, &count);
1670 	    if (visInfoPtr == NULL) {
1671 		Tcl_SetStringObj(resultPtr,
1672 			"can't find any visuals for screen", -1);
1673 		return TCL_ERROR;
1674 	    }
1675 	    for (i = 0; i < count; i++) {
1676 		string = TkFindStateString(visualMap, visInfoPtr[i].class);
1677 		if (string == NULL) {
1678 		    strcpy(buf, "unknown");
1679 		} else {
1680 		    sprintf(buf, "%s %d", string, visInfoPtr[i].depth);
1681 		}
1682 		if (includeVisualId) {
1683 		    sprintf(visualIdString, " 0x%x",
1684 			    (unsigned int) visInfoPtr[i].visualid);
1685 		    strcat(buf, visualIdString);
1686 		}
1687 		strPtr = Tcl_NewStringObj(buf, -1);
1688 		Tcl_ListObjAppendElement(NULL, resultPtr, strPtr);
1689 	    }
1690 	    XFree((char *) visInfoPtr);
1691 	    break;
1692 	}
1693     }
1694     return TCL_OK;
1695 }
1696 
1697 #if 0
1698 /*
1699  *----------------------------------------------------------------------
1700  *
1701  * Tk_WmObjCmd --
1702  *
1703  *	This procedure is invoked to process the "wm" Tcl command.
1704  *	See the user documentation for details on what it does.
1705  *
1706  * Results:
1707  *	A standard Tcl result.
1708  *
1709  * Side effects:
1710  *	See the user documentation.
1711  *
1712  *----------------------------------------------------------------------
1713  */
1714 
1715 	/* ARGSUSED */
1716 int
1717 Tk_WmObjCmd(clientData, interp, objc, objv)
1718     ClientData clientData;	/* Main window associated with
1719 				 * interpreter. */
1720     Tcl_Interp *interp;		/* Current interpreter. */
1721     int objc;			/* Number of arguments. */
1722     Tcl_Obj *CONST objv[];	/* Argument objects. */
1723 {
1724     Tk_Window tkwin;
1725     TkWindow *winPtr;
1726 
1727     static CONST char *optionStrings[] = {
1728 	"aspect",	"client",	"command",	"deiconify",
1729 	"focusmodel",	"frame",	"geometry",	"grid",
1730 	"group",	"iconbitmap",	"iconify",	"iconmask",
1731 	"iconname",	"iconposition",	"iconwindow",	"maxsize",
1732 	"minsize",	"overrideredirect",	"positionfrom",	"protocol",
1733 	"resizable",	"sizefrom",	"state",	"title",
1734 	"tracing",	"transient",	"withdraw",	(char *) NULL
1735     };
1736     enum options {
1737 	TKWM_ASPECT,	TKWM_CLIENT,	TKWM_COMMAND,	TKWM_DEICONIFY,
1738 	TKWM_FOCUSMOD,	TKWM_FRAME,	TKWM_GEOMETRY,	TKWM_GRID,
1739 	TKWM_GROUP,	TKWM_ICONBMP,	TKWM_ICONIFY,	TKWM_ICONMASK,
1740 	TKWM_ICONNAME,	TKWM_ICONPOS,	TKWM_ICONWIN,	TKWM_MAXSIZE,
1741 	TKWM_MINSIZE,	TKWM_OVERRIDE,	TKWM_POSFROM,	TKWM_PROTOCOL,
1742 	TKWM_RESIZABLE,	TKWM_SIZEFROM,	TKWM_STATE,	TKWM_TITLE,
1743 	TKWM_TRACING,	TKWM_TRANSIENT,	TKWM_WITHDRAW
1744     };
1745 
1746     tkwin = (Tk_Window) clientData;
1747 
1748     if (objc < 2) {
1749 	Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg?");
1750 	return TCL_ERROR;
1751     }
1752     if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
1753 	    &index) != TCL_OK) {
1754 	return TCL_ERROR;
1755     }
1756 
1757     if (index == TKWM_TRACING) {
1758 	int wmTracing;
1759 	TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
1760 
1761 	if ((objc != 2) && (objc != 3)) {
1762 	    Tcl_WrongNumArgs(interp, 1, objv, "tracing ?boolean?");
1763 	    return TCL_ERROR;
1764 	}
1765 	if (objc == 2) {
1766 	    Tcl_SetObjResult(interp,
1767 		    Tcl_NewBooleanObj(dispPtr->flags & TK_DISPLAY_WM_TRACING));
1768 	    return TCL_OK;
1769 	}
1770 	if (Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing) != TCL_OK) {
1771 	    return TCL_ERROR;
1772 	}
1773 	if (wmTracing) {
1774 	    dispPtr->flags |= TK_DISPLAY_WM_TRACING;
1775 	} else {
1776 	    dispPtr->flags &= ~TK_DISPLAY_WM_TRACING;
1777 	}
1778 	return TCL_OK;
1779     }
1780 
1781     if (objc < 3) {
1782 	Tcl_WrongNumArgs(interp, 2, objv, "window ?arg?");
1783 	return TCL_ERROR;
1784     }
1785 
1786     winPtr = (TkWindow *) Tk_NameToWindow(interp,
1787 	    Tcl_GetString(objv[2]), tkwin);
1788     if (winPtr == NULL) {
1789 	return TCL_ERROR;
1790     }
1791     if (!(winPtr->flags & TK_TOP_LEVEL)) {
1792 	Tcl_AppendResult(interp, "window \"", winPtr->pathName,
1793 		"\" isn't a top-level window", (char *) NULL);
1794 	return TCL_ERROR;
1795     }
1796 
1797     switch ((enum options) index) {
1798 	case TKWM_ASPECT: {
1799 	    TkpWmAspectCmd(interp, tkwin, winPtr, objc, objv);
1800 	    break;
1801 	}
1802 	case TKWM_CLIENT: {
1803 	    TkpWmClientCmd(interp, tkwin, winPtr, objc, objv);
1804 	    break;
1805 	}
1806 	case TKWM_COMMAND: {
1807 	    TkpWmCommandCmd(interp, tkwin, winPtr, objc, objv);
1808 	    break;
1809 	}
1810 	case TKWM_DEICONIFY: {
1811 	    TkpWmDeiconifyCmd(interp, tkwin, winPtr, objc, objv);
1812 	    break;
1813 	}
1814 	case TKWM_FOCUSMOD: {
1815 	    TkpWmFocusmodCmd(interp, tkwin, winPtr, objc, objv);
1816 	    break;
1817 	}
1818 	case TKWM_FRAME: {
1819 	    TkpWmFrameCmd(interp, tkwin, winPtr, objc, objv);
1820 	    break;
1821 	}
1822 	case TKWM_GEOMETRY: {
1823 	    TkpWmGeometryCmd(interp, tkwin, winPtr, objc, objv);
1824 	    break;
1825 	}
1826 	case TKWM_GRID: {
1827 	    TkpWmGridCmd(interp, tkwin, winPtr, objc, objv);
1828 	    break;
1829 	}
1830 	case TKWM_GROUP: {
1831 	    TkpWmGroupCmd(interp, tkwin, winPtr, objc, objv);
1832 	    break;
1833 	}
1834 	case TKWM_ICONBMP: {
1835 	    TkpWmIconbitmapCmd(interp, tkwin, winPtr, objc, objv);
1836 	    break;
1837 	}
1838 	case TKWM_ICONIFY: {
1839 	    TkpWmIconifyCmd(interp, tkwin, winPtr, objc, objv);
1840 	    break;
1841 	}
1842 	case TKWM_ICONMASK: {
1843 	    TkpWmIconmaskCmd(interp, tkwin, winPtr, objc, objv);
1844 	    break;
1845 	}
1846 	case TKWM_ICONNAME: {
1847 	    /* slight Unix variation */
1848 	    TkpWmIconnameCmd(interp, tkwin, winPtr, objc, objv);
1849 	    break;
1850 	}
1851 	case TKWM_ICONPOS: {
1852 	    /* nearly same - 1 line more on Unix */
1853 	    TkpWmIconpositionCmd(interp, tkwin, winPtr, objc, objv);
1854 	    break;
1855 	}
1856 	case TKWM_ICONWIN: {
1857 	    TkpWmIconwindowCmd(interp, tkwin, winPtr, objc, objv);
1858 	    break;
1859 	}
1860 	case TKWM_MAXSIZE: {
1861 	    /* nearly same, win diffs */
1862 	    TkpWmMaxsizeCmd(interp, tkwin, winPtr, objc, objv);
1863 	    break;
1864 	}
1865 	case TKWM_MINSIZE: {
1866 	    /* nearly same, win diffs */
1867 	    TkpWmMinsizeCmd(interp, tkwin, winPtr, objc, objv);
1868 	    break;
1869 	}
1870 	case TKWM_OVERRIDE: {
1871 	    /* almost same */
1872 	    TkpWmOverrideCmd(interp, tkwin, winPtr, objc, objv);
1873 	    break;
1874 	}
1875 	case TKWM_POSFROM: {
1876 	    /* Equal across platforms */
1877 	    TkpWmPositionfromCmd(interp, tkwin, winPtr, objc, objv);
1878 	    break;
1879 	}
1880 	case TKWM_PROTOCOL: {
1881 	    /* Equal across platforms */
1882 	    TkpWmProtocolCmd(interp, tkwin, winPtr, objc, objv);
1883 	    break;
1884 	}
1885 	case TKWM_RESIZABLE: {
1886 	    /* almost same */
1887 	    TkpWmResizableCmd(interp, tkwin, winPtr, objc, objv);
1888 	    break;
1889 	}
1890 	case TKWM_SIZEFROM: {
1891 	    /* Equal across platforms */
1892 	    TkpWmSizefromCmd(interp, tkwin, winPtr, objc, objv);
1893 	    break;
1894 	}
1895 	case TKWM_STATE: {
1896 	    TkpWmStateCmd(interp, tkwin, winPtr, objc, objv);
1897 	    break;
1898 	}
1899 	case TKWM_TITLE: {
1900 	    TkpWmTitleCmd(interp, tkwin, winPtr, objc, objv);
1901 	    break;
1902 	}
1903 	case TKWM_TRANSIENT: {
1904 	    TkpWmTransientCmd(interp, tkwin, winPtr, objc, objv);
1905 	    break;
1906 	}
1907 	case TKWM_WITHDRAW: {
1908 	    TkpWmWithdrawCmd(interp, tkwin, winPtr, objc, objv);
1909 	    break;
1910 	}
1911     }
1912 
1913     updateGeom:
1914     if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) {
1915 	Tcl_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr);
1916 	wmPtr->flags |= WM_UPDATE_PENDING;
1917     }
1918     return TCL_OK;
1919 }
1920 #endif
1921 
1922 /*
1923  *----------------------------------------------------------------------
1924  *
1925  * TkGetDisplayOf --
1926  *
1927  *	Parses a "-displayof window" option for various commands.  If
1928  *	present, the literal "-displayof" should be in objv[0] and the
1929  *	window name in objv[1].
1930  *
1931  * Results:
1932  *	The return value is 0 if the argument strings did not contain
1933  *	the "-displayof" option.  The return value is 2 if the
1934  *	argument strings contained both the "-displayof" option and
1935  *	a valid window name.  Otherwise, the return value is -1 if
1936  *	the window name was missing or did not specify a valid window.
1937  *
1938  *	If the return value was 2, *tkwinPtr is filled with the
1939  *	token for the window specified on the command line.  If the
1940  *	return value was -1, an error message is left in interp's
1941  *	result object.
1942  *
1943  * Side effects:
1944  *	None.
1945  *
1946  *----------------------------------------------------------------------
1947  */
1948 
1949 int
TkGetDisplayOf(interp,objc,objv,tkwinPtr)1950 TkGetDisplayOf(interp, objc, objv, tkwinPtr)
1951     Tcl_Interp *interp;		/* Interpreter for error reporting. */
1952     int objc;			/* Number of arguments. */
1953     Tcl_Obj *CONST objv[];	/* Argument objects. If it is present,
1954 				 * "-displayof" should be in objv[0] and
1955 				 * objv[1] the name of a window. */
1956     Tk_Window *tkwinPtr;	/* On input, contains main window of
1957 				 * application associated with interp.  On
1958 				 * output, filled with window specified as
1959 				 * option to "-displayof" argument, or
1960 				 * unmodified if "-displayof" argument was not
1961 				 * present. */
1962 {
1963     char *string;
1964     int length;
1965 
1966     if (objc < 1) {
1967 	return 0;
1968     }
1969     string = Tcl_GetStringFromObj(objv[0], &length);
1970     if ((length >= 2) &&
1971 	    (strncmp(string, "-displayof", (unsigned) length) == 0)) {
1972         if (objc < 2) {
1973 	    Tcl_SetStringObj(Tcl_GetObjResult(interp),
1974 		    "value for \"-displayof\" missing", -1);
1975 	    return -1;
1976 	}
1977 	string = Tcl_GetStringFromObj(objv[1], NULL);
1978 	*tkwinPtr = Tk_NameToWindow(interp, string, *tkwinPtr);
1979 	if (*tkwinPtr == NULL) {
1980 	    return -1;
1981 	}
1982 	return 2;
1983     }
1984     return 0;
1985 }
1986 
1987 /*
1988  *----------------------------------------------------------------------
1989  *
1990  * TkDeadAppCmd --
1991  *
1992  *	If an application has been deleted then all Tk commands will be
1993  *	re-bound to this procedure.
1994  *
1995  * Results:
1996  *	A standard Tcl error is reported to let the user know that
1997  *	the application is dead.
1998  *
1999  * Side effects:
2000  *	See the user documentation.
2001  *
2002  *----------------------------------------------------------------------
2003  */
2004 
2005 	/* ARGSUSED */
2006 int
TkDeadAppCmd(clientData,interp,argc,objv)2007 TkDeadAppCmd(clientData, interp, argc, objv)
2008     ClientData clientData;	/* Dummy. */
2009     Tcl_Interp *interp;		/* Current interpreter. */
2010     int argc;			/* Number of arguments. */
2011     Tcl_Obj *CONST *objv;	/* Argument strings. */
2012 {
2013     Tcl_AppendResult(interp, "can't invoke \"", Tcl_GetString(objv[0]),
2014 	    "\" command:  application has been destroyed", (char *) NULL);
2015     return TCL_ERROR;
2016 }
2017 
2018 /*
2019  *----------------------------------------------------------------------
2020  *
2021  * GetToplevel --
2022  *
2023  *	Retrieves the toplevel window which is the nearest ancestor of
2024  *	of the specified window.
2025  *
2026  * Results:
2027  *	Returns the toplevel window or NULL if the window has no
2028  *	ancestor which is a toplevel.
2029  *
2030  * Side effects:
2031  *	None.
2032  *
2033  *----------------------------------------------------------------------
2034  */
2035 
2036 static TkWindow *
GetToplevel(tkwin)2037 GetToplevel(tkwin)
2038     Tk_Window tkwin;		/* Window for which the toplevel should be
2039 				 * deterined. */
2040 {
2041      TkWindow *winPtr = (TkWindow *) tkwin;
2042 
2043      while (!(winPtr->flags & TK_TOP_LEVEL)) {
2044 	 winPtr = winPtr->parentPtr;
2045 	 if (winPtr == NULL) {
2046 	     return NULL;
2047 	 }
2048      }
2049      return winPtr;
2050 }
2051 
2052 
2053 
2054 
2055 
2056