4 * This file provides basic window-manipulation procedures,
5 * which are equivalent to procedures in Xlib (and even
6 * invoke them) but also maintain the local Tk_Window
9 * Copyright 1989-1992 Regents of the University of California.
10 * Permission to use, copy, modify, and distribute this
11 * software and its documentation for any purpose and without
12 * fee is hereby granted, provided that the above copyright
13 * notice appear in all copies. The University of California
14 * makes no representations about the suitability of this
15 * software for any purpose. It is provided "as is" without
16 * express or implied warranty.
20 static char rcsid
[] = "$Header: /user6/ouster/wish/RCS/tkWindow.c,v 1.92 92/08/21 11:42:44 ouster Exp $ SPRITE (Berkeley)";
27 * Global absolute file name:
29 char *TK_Library
= TK_LIBRARY
;
32 * Count of open displays.
37 * Count of number of main windows currently open in this process.
40 int tk_NumMainWindows
;
43 * Added by dhopkins for OLPC Micropolis gtk.Socket integration.
46 Window tk_RootWindow
= 0;
49 * List of all displays currently in use.
52 TkDisplay
*tkDisplayList
= NULL
;
55 * Have statics in this module been initialized?
58 static initialized
= 0;
61 * Context information used to map from X window id's to
62 * TkWindow structures (during event handling, for example):
65 XContext tkWindowContext
;
68 * The variables below hold several uid's that are used in many places
72 Tk_Uid tkDisabledUid
= NULL
;
73 Tk_Uid tkActiveUid
= NULL
;
74 Tk_Uid tkNormalUid
= NULL
;
77 * Default values for "changes" and "atts" fields of TkWindows. Note
78 * that Tk always requests all events for all windows, except StructureNotify
79 * events on internal windows: these events are generated internally.
82 static XWindowChanges defChanges
= {
83 0, 0, 1, 1, 0, 0, Above
85 #define ALL_EVENTS_MASK \
86 KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask| \
87 EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask| \
88 VisibilityChangeMask|SubstructureNotifyMask| \
89 FocusChangeMask|PropertyChangeMask|ColormapChangeMask
90 static XSetWindowAttributes defAtts
= {
91 None
, /* background_pixmap */
92 0, /* background_pixel */
93 CopyFromParent
, /* border_pixmap */
95 ForgetGravity
, /* bit_gravity */
96 NorthWestGravity
, /* win_gravity */
97 NotUseful
, /* backing_store */
98 ~0, /* backing_planes */
99 0, /* backing_pixel */
100 False
, /* save_under */
101 ALL_EVENTS_MASK
, /* event_mask */
102 0, /* do_not_propagate_mask */
103 False
, /* override_redirect */
104 CopyFromParent
, /* colormap */
109 * The following structure defines all of the commands supported by
110 * Tk, and the C procedures that execute them.
114 char *name
; /* Name of command. */
115 int (*cmdProc
) _ANSI_ARGS_((ClientData clientData
, Tcl_Interp
*interp
,
116 int argc
, char **argv
));
117 /* Command procedure. */
122 * Commands that are part of the intrinsics:
125 {"after", Tk_AfterCmd
},
126 {"bind", Tk_BindCmd
},
127 {"destroy", Tk_DestroyCmd
},
128 {"focus", Tk_FocusCmd
},
129 {"grab", Tk_GrabCmd
},
130 {"option", Tk_OptionCmd
},
131 {"pack", Tk_PackCmd
},
132 {"place", Tk_PlaceCmd
},
133 {"selection", Tk_SelectionCmd
},
134 {"tkwait", Tk_TkwaitCmd
},
135 {"update", Tk_UpdateCmd
},
136 {"winfo", Tk_WinfoCmd
},
138 {"accept", Tcp_AcceptCmd
},
139 {"shutdown", Tcp_ShutdownCmd
},
140 {"connect", Tcp_ConnectCmd
},
141 {"filehandler", Tcp_FileHandlerCmd
},
144 * Widget-creation commands.
146 {"button", Tk_ButtonCmd
},
147 {"canvas", Tk_CanvasCmd
},
148 {"checkbutton", Tk_ButtonCmd
},
149 {"entry", Tk_EntryCmd
},
150 {"frame", Tk_FrameCmd
},
151 {"label", Tk_ButtonCmd
},
152 {"listbox", Tk_ListboxCmd
},
153 {"menu", Tk_MenuCmd
},
154 {"menubutton", Tk_MenubuttonCmd
},
155 {"message", Tk_MessageCmd
},
156 {"radiobutton", Tk_ButtonCmd
},
157 {"scale", Tk_ScaleCmd
},
158 {"scrollbar", Tk_ScrollbarCmd
},
159 {"text", Tk_TextCmd
},
160 {"toplevel", Tk_FrameCmd
},
161 {(char *) NULL
, (int (*)()) NULL
}
165 * Forward declarations to procedures defined later in this file:
168 static Tk_Window CreateTopLevelWindow
_ANSI_ARGS_((Tcl_Interp
*interp
,
169 Tk_Window parent
, char *name
, char *screenName
));
170 static void DoConfigureNotify
_ANSI_ARGS_((TkWindow
*winPtr
));
171 static TkDisplay
* GetScreen
_ANSI_ARGS_((Tcl_Interp
*interp
,
172 char *screenName
, int *screenPtr
));
173 static int NameWindow
_ANSI_ARGS_((Tcl_Interp
*interp
,
174 TkWindow
*winPtr
, TkWindow
*parentPtr
,
176 static TkWindow
* NewWindow
_ANSI_ARGS_((TkDisplay
*dispPtr
,
180 *----------------------------------------------------------------------
182 * CreateTopLevelWindow --
184 * Make a new window that will be at top-level (its parent will
185 * be the root window of a screen).
188 * The return value is a token for the new window, or NULL if
189 * an error prevented the new window from being created. If
190 * NULL is returned, an error message will be left in
194 * A new window structure is allocated locally. An X
195 * window is NOT initially created, but will be created
196 * the first time the window is mapped.
198 *----------------------------------------------------------------------
202 CreateTopLevelWindow(interp
, parent
, name
, screenName
)
203 Tcl_Interp
*interp
; /* Interpreter to use for error reporting. */
204 Tk_Window parent
; /* Token for logical parent of new window
205 * (used for naming, options, etc.). May
207 char *name
; /* Name for new window; if parent is
208 * non-NULL, must be unique among parent's
210 char *screenName
; /* Name of screen on which to create
211 * window. NULL means use DISPLAY environment
212 * variable to determine. Empty string means
213 * use parent's screen, or DISPLAY if no
216 register TkWindow
*winPtr
;
217 register TkDisplay
*dispPtr
;
222 tkWindowContext
= XUniqueContext();
223 tkActiveUid
= Tk_GetUid("active");
224 tkDisabledUid
= Tk_GetUid("disabled");
225 tkNormalUid
= Tk_GetUid("normal");
228 if ((parent
!= NULL
) && (screenName
!= NULL
) && (screenName
[0] == '\0')) {
229 dispPtr
= ((TkWindow
*) parent
)->dispPtr
;
230 screenId
= Tk_ScreenNumber(parent
);
232 dispPtr
= GetScreen(interp
, screenName
, &screenId
);
233 if (dispPtr
== NULL
) {
234 return (Tk_Window
) NULL
;
238 winPtr
= NewWindow(dispPtr
, screenId
);
241 * Internal windows don't normally ask for StructureNotify events,
242 * since we can generate them internally. However, for top-level
243 * windows we need to as for the events because the window could
244 * be manipulated externally.
247 winPtr
->atts
.event_mask
|= StructureNotifyMask
;
250 * (Need to set the TK_TOP_LEVEL flag immediately here; otherwise
251 * Tk_DestroyWindow will core dump if it is called before the flag
255 winPtr
->flags
|= TK_TOP_LEVEL
;
256 if (parent
!= NULL
) {
257 if (NameWindow(interp
, winPtr
, (TkWindow
*) parent
, name
) != TCL_OK
) {
258 Tk_DestroyWindow((Tk_Window
) winPtr
);
259 return (Tk_Window
) NULL
;
262 TkWmNewWindow(winPtr
);
263 return (Tk_Window
) winPtr
;
267 *----------------------------------------------------------------------
271 * Given a string name for a display-plus-screen, find the
272 * TkDisplay structure for the display and return the screen
276 * The return value is a pointer to information about the display,
277 * or NULL if the display couldn't be opened. In this case, an
278 * error message is left in interp->result. The location at
279 * *screenPtr is overwritten with the screen number parsed from
283 * A new connection is opened to the display if there is no
284 * connection already. A new TkDisplay data structure is also
285 * setup, if necessary.
287 *----------------------------------------------------------------------
291 GetScreen(interp
, screenName
, screenPtr
)
292 Tcl_Interp
*interp
; /* Place to leave error message. */
293 char *screenName
; /* Name for screen. NULL or empty means
294 * use DISPLAY envariable. */
295 int *screenPtr
; /* Where to store screen number. */
297 register TkDisplay
*dispPtr
;
299 int length
, screenId
;
302 * Separate the screen number from the rest of the display
303 * name. ScreenName is assumed to have the syntax
304 * <display>.<screen> with the dot and the screen being
308 if ((screenName
== NULL
) || (screenName
[0] == '\0')) {
309 screenName
= getenv("DISPLAY");
310 if (screenName
== NULL
) {
312 "no display name and no $DISPLAY environment variable";
313 return (TkDisplay
*) NULL
;
316 length
= strlen(screenName
);
318 p
= screenName
+length
-1;
319 while (isdigit(*p
) && (p
!= screenName
)) {
322 if ((*p
== '.') && (p
[1] != '\0')) {
323 length
= p
- screenName
;
324 screenId
= strtoul(p
+1, (char **) NULL
, 10);
328 * See if we already have a connection to this display. If not,
329 * then open a new connection.
332 for (dispPtr
= tkDisplayList
; ; dispPtr
= dispPtr
->nextPtr
) {
333 if (dispPtr
== NULL
) {
334 Display
*display
= NULL
;
336 display
= XOpenDisplay(screenName
);
338 if (display
== NULL
) {
339 Tcl_AppendResult(interp
, "couldn't connect to display \"",
340 screenName
, "\"", (char *) NULL
);
341 return (TkDisplay
*) NULL
;
343 if (getenv("XSYNCHRONIZE") != NULL
) {
344 XSynchronize(display
, 1);
347 dispPtr
= (TkDisplay
*) ckalloc(sizeof(TkDisplay
));
348 dispPtr
->display
= display
;
349 dispPtr
->nextPtr
= tkDisplayList
;
350 dispPtr
->name
= (char *) ckalloc((unsigned) (length
+1));
351 dispPtr
->lastEventTime
= CurrentTime
;
352 strncpy(dispPtr
->name
, screenName
, length
);
353 dispPtr
->mouseMainPtr
= NULL
;
354 dispPtr
->name
[length
] = '\0';
355 dispPtr
->symsPerCode
= 0;
356 dispPtr
->errorPtr
= NULL
;
357 dispPtr
->deleteCount
= 0;
358 dispPtr
->commWindow
= NULL
;
359 dispPtr
->selectionOwner
= NULL
;
360 dispPtr
->selectionSerial
= 0;
361 dispPtr
->multipleAtom
= None
;
362 dispPtr
->atomInit
= 0;
363 dispPtr
->cursorFont
= None
;
364 dispPtr
->grabWinPtr
= NULL
;
365 dispPtr
->ungrabWinPtr
= NULL
;
366 dispPtr
->buttonWinPtr
= NULL
;
367 dispPtr
->pointerWinPtr
= NULL
;
368 dispPtr
->serverWinPtr
= NULL
;
369 dispPtr
->grabFlags
= 0;
370 dispPtr
->focusPtr
= NULL
;
371 tkDisplayList
= dispPtr
;
372 Tk_CreateFileHandler(ConnectionNumber(display
),
373 TK_READABLE
, (void (*)()) NULL
,
374 (ClientData
) display
);
377 if ((strncmp(dispPtr
->name
, screenName
, length
) == 0)
378 && (dispPtr
->name
[length
] == '\0')) {
382 if (screenId
>= ScreenCount(dispPtr
->display
)) {
383 sprintf(interp
->result
, "bad screen number \"%d\"", screenId
);
384 return (TkDisplay
*) NULL
;
386 *screenPtr
= screenId
;
391 *--------------------------------------------------------------
395 * This procedure creates and initializes a TkWindow structure.
398 * The return value is a pointer to the new window.
401 * A new window structure is allocated and all its fields are
404 *--------------------------------------------------------------
408 NewWindow(dispPtr
, screenNum
)
409 TkDisplay
*dispPtr
; /* Display associated with new window. */
410 int screenNum
; /* Index of screen for new window. */
412 register TkWindow
*winPtr
;
414 winPtr
= (TkWindow
*) ckalloc(sizeof(TkWindow
));
415 winPtr
->display
= dispPtr
->display
;
416 winPtr
->dispPtr
= dispPtr
;
417 winPtr
->screenNum
= screenNum
;
418 winPtr
->window
= None
;
419 winPtr
->childList
= NULL
;
420 winPtr
->parentPtr
= NULL
;
421 winPtr
->nextPtr
= NULL
;
422 winPtr
->mainPtr
= NULL
;
423 winPtr
->pathName
= NULL
;
424 winPtr
->nameUid
= NULL
;
425 winPtr
->classUid
= NULL
;
426 winPtr
->changes
= defChanges
;
427 winPtr
->dirtyChanges
= CWX
|CWY
|CWWidth
|CWHeight
|CWBorderWidth
;
428 winPtr
->atts
= defAtts
;
429 winPtr
->dirtyAtts
= CWEventMask
;
431 winPtr
->handlerList
= NULL
;
432 winPtr
->focusProc
= NULL
;
433 winPtr
->focusData
= NULL
;
434 winPtr
->optionLevel
= -1;
435 winPtr
->selHandlerList
= NULL
;
436 winPtr
->selClearProc
= NULL
;
437 winPtr
->selClearData
= NULL
;
438 winPtr
->geomProc
= NULL
;
439 winPtr
->geomData
= NULL
;
440 winPtr
->reqWidth
= winPtr
->reqHeight
= 0;
441 winPtr
->internalBorderWidth
= 0;
442 winPtr
->wmInfoPtr
= NULL
;
447 *----------------------------------------------------------------------
451 * This procedure is invoked to give a window a name and insert
452 * the window into the hierarchy associated with a particular
456 * A standard Tcl return value.
461 *----------------------------------------------------------------------
465 NameWindow(interp
, winPtr
, parentPtr
, name
)
466 Tcl_Interp
*interp
; /* Interpreter to use for error reporting. */
467 register TkWindow
*winPtr
; /* Window that is to be named and inserted. */
468 TkWindow
*parentPtr
; /* Pointer to logical parent for winPtr
469 * (used for naming, options, etc.). */
470 char *name
; /* Name for winPtr; must be unique among
471 * parentPtr's children. */
473 #define FIXED_SIZE 200
474 char staticSpace
[FIXED_SIZE
];
478 int length1
, length2
;
481 * Setup all the stuff except name right away, then do the name stuff
482 * last. This is so that if the name stuff fails, everything else
483 * will be properly initialized (needed to destroy the window cleanly
484 * after the naming failure).
486 winPtr
->parentPtr
= parentPtr
;
487 winPtr
->nextPtr
= parentPtr
->childList
;
488 parentPtr
->childList
= winPtr
;
489 winPtr
->mainPtr
= parentPtr
->mainPtr
;
490 winPtr
->nameUid
= Tk_GetUid(name
);
493 * To permit names of arbitrary length, must be prepared to malloc
494 * a buffer to hold the new path name. To run fast in the common
495 * case where names are short, use a fixed-size buffer on the
499 length1
= strlen(parentPtr
->pathName
);
500 length2
= strlen(name
);
501 if ((length1
+length2
+2) <= FIXED_SIZE
) {
502 pathName
= staticSpace
;
504 pathName
= (char *) ckalloc((unsigned) (length1
+length2
+2));
508 strcpy(pathName
+1, name
);
510 strcpy(pathName
, parentPtr
->pathName
);
511 pathName
[length1
] = '.';
512 strcpy(pathName
+length1
+1, name
);
514 hPtr
= Tcl_CreateHashEntry(&parentPtr
->mainPtr
->nameTable
, pathName
, &new);
515 if (pathName
!= staticSpace
) {
519 Tcl_AppendResult(interp
, "window name \"", name
,
520 "\" already exists in parent", (char *) NULL
);
523 Tcl_SetHashValue(hPtr
, winPtr
);
524 winPtr
->pathName
= Tcl_GetHashKey(&parentPtr
->mainPtr
->nameTable
, hPtr
);
529 *----------------------------------------------------------------------
531 * Tk_CreateMainWindow --
533 * Make a new main window. A main window is a special kind of
534 * top-level window used as the outermost window in an
538 * The return value is a token for the new window, or NULL if
539 * an error prevented the new window from being created. If
540 * NULL is returned, an error message will be left in
544 * A new window structure is allocated locally; "interp" is
545 * associated with the window and registered for "send" commands
546 * under "baseName". BaseName may be extended with an instance
547 * number in the form "#2" if necessary to make it globally
548 * unique. Tk-related commands are bound into interp. An X
549 * window is NOT initially created, but will be created the
550 * first time the window is mapped.
552 *----------------------------------------------------------------------
556 Tk_CreateMainWindow(interp
, screenName
, baseName
)
557 Tcl_Interp
*interp
; /* Interpreter to use for error reporting. */
558 char *screenName
; /* Name of screen on which to create
559 * window. Empty or NULL string means
560 * use DISPLAY environment variable. */
561 char *baseName
; /* Base name for application; usually of the
562 * form "prog instance". */
567 register TkMainInfo
*mainPtr
;
568 register TkWindow
*winPtr
;
569 register TkCmd
*cmdPtr
;
572 * Create the basic TkWindow structure.
575 tkwin
= CreateTopLevelWindow(interp
, (Tk_Window
) NULL
, baseName
,
582 * Create the TkMainInfo structure for this application, and set
583 * up name-related information for the new window.
586 winPtr
= (TkWindow
*) tkwin
;
587 mainPtr
= (TkMainInfo
*) ckalloc(sizeof(TkMainInfo
));
588 mainPtr
->winPtr
= winPtr
;
589 mainPtr
->interp
= interp
;
590 Tcl_InitHashTable(&mainPtr
->nameTable
, TCL_STRING_KEYS
);
591 mainPtr
->bindingTable
= Tk_CreateBindingTable(interp
);
593 /* mainPtr->focusPtr = NULL; */
594 mainPtr
->optionRootPtr
= NULL
;
595 winPtr
->mainPtr
= mainPtr
;
596 hPtr
= Tcl_CreateHashEntry(&mainPtr
->nameTable
, ".", &dummy
);
597 Tcl_SetHashValue(hPtr
, winPtr
);
598 winPtr
->pathName
= Tcl_GetHashKey(&mainPtr
->nameTable
, hPtr
);
601 * Register the interpreter for "send" purposes. If baseName isn't
602 * already unique, find a unique suffix to add to it to make it
603 * unique. Change the window's name to contain the suffix.
606 result
= Tk_RegisterInterp(interp
, baseName
, tkwin
);
607 if (result
== TCL_OK
) {
608 winPtr
->nameUid
= Tk_GetUid(baseName
);
614 sprintf(newName
, "%.100s #%d", baseName
, i
);
615 Tcl_SetResult(interp
, (char *) NULL
, TCL_STATIC
);
616 result
= Tk_RegisterInterp(interp
, newName
, tkwin
);
617 if (result
== TCL_OK
) {
621 Tcl_SetResult(interp
,
622 "couldn't generate unique name to register application",
624 Tk_DestroyWindow(tkwin
);
627 winPtr
->nameUid
= Tk_GetUid(newName
);
631 * Bind in Tk's commands.
634 for (cmdPtr
= commands
; cmdPtr
->name
!= NULL
; cmdPtr
++) {
635 Tcl_CreateCommand(interp
, cmdPtr
->name
, cmdPtr
->cmdProc
,
636 (ClientData
) tkwin
, (void (*)()) NULL
);
640 * Set variables for the intepreter.
643 Tcl_SetVar(interp
, "tk_library", TK_Library
, TCL_GLOBAL_ONLY
);
644 Tcl_SetVar(interp
, "tk_version", TK_VERSION
, TCL_GLOBAL_ONLY
);
645 Tcl_SetVar(interp
, "tkVersion", TK_VERSION
, TCL_GLOBAL_ONLY
);
652 *--------------------------------------------------------------
656 * Create a new internal or top-level window as a child of an
660 * The return value is a token for the new window. This
661 * is not the same as X's token for the window. If an error
662 * occurred in creating the window (e.g. no such display or
663 * screen), then an error message is left in interp->result and
667 * A new window structure is allocated locally. An X
668 * window is not initially created, but will be created
669 * the first time the window is mapped.
671 *--------------------------------------------------------------
675 Tk_CreateWindow(interp
, parent
, name
, screenName
)
676 Tcl_Interp
*interp
; /* Interpreter to use for error reporting.
677 * Interp->result is assumed to be
678 * initialized by the caller. */
679 Tk_Window parent
; /* Token for parent of new window. */
680 char *name
; /* Name for new window. Must be unique
681 * among parent's children. */
682 char *screenName
; /* If NULL, new window will be internal on
683 * same screen as its parent. If non-NULL,
684 * gives name of screen on which to create
685 * new window; window will be a top-level
688 TkWindow
*parentPtr
= (TkWindow
*) parent
;
691 if (screenName
== NULL
) {
692 winPtr
= NewWindow(parentPtr
->dispPtr
, parentPtr
->screenNum
);
693 if (NameWindow(interp
, winPtr
, parentPtr
, name
) != TCL_OK
) {
694 Tk_DestroyWindow((Tk_Window
) winPtr
);
697 return (Tk_Window
) winPtr
;
701 * This is a fix for dvx XOpenDisplay... display name conformalization
707 strcpy(dsp
, screenName
);
709 if (len
&& (dsp
[len
-1] == '.'))
712 return CreateTopLevelWindow(interp
, parent
, name
, dsp
);
717 *----------------------------------------------------------------------
719 * Tk_CreateWindowFromPath --
721 * This procedure is similar to Tk_CreateInternalWindow except
722 * that it uses a path name to create the window, rather than
723 * a parent and a child name.
726 * The return value is a token for the new window. This
727 * is not the same as X's token for the window. If an error
728 * occurred in creating the window (e.g. no such display or
729 * screen), then an error message is left in interp->result and
733 * A new window structure is allocated locally. An X
734 * window is not initially created, but will be created
735 * the first time the window is mapped.
737 *----------------------------------------------------------------------
741 Tk_CreateWindowFromPath(interp
, tkwin
, pathName
, screenName
)
742 Tcl_Interp
*interp
; /* Interpreter to use for error reporting.
743 * Interp->result is assumed to be
744 * initialized by the caller. */
745 Tk_Window tkwin
; /* Token for any window in application
746 * that is to contain new window. */
747 char *pathName
; /* Path name for new window within the
748 * application of tkwin. The parent of
749 * this window must already exist, but
750 * the window itself must not exist. */
751 char *screenName
; /* If NULL, new window will be on same
752 * screen as its parent. If non-NULL,
753 * gives name of screen on which to create
754 * new window; window will be a top-level
757 #define FIXED_SPACE 5
758 char fixedSpace
[FIXED_SPACE
+1];
764 * Strip the parent's name out of pathName (it's everything up
765 * to the last dot). There are two tricky parts: (a) must
766 * copy the parent's name somewhere else to avoid modifying
767 * the pathName string (for large names, space for the copy
768 * will have to be malloc'ed); (b) must special-case the
769 * situation where the parent is ".".
772 p
= strrchr(pathName
, '.');
774 Tcl_AppendResult(interp
, "bad window path name \"", pathName
,
775 "\"", (char *) NULL
);
778 numChars
= p
-pathName
;
779 if (numChars
> FIXED_SPACE
) {
780 p
= (char *) ckalloc((unsigned) (numChars
+1));
788 strncpy(p
, pathName
, numChars
);
793 * Find the parent window.
796 parent
= Tk_NameToWindow(interp
, p
, tkwin
);
797 if (p
!= fixedSpace
) {
800 if (parent
== NULL
) {
808 if (screenName
== NULL
) {
809 TkWindow
*parentPtr
= (TkWindow
*) parent
;
812 winPtr
= NewWindow(parentPtr
->dispPtr
, parentPtr
->screenNum
);
813 if (NameWindow(interp
, winPtr
, parentPtr
, pathName
+numChars
+1)
815 Tk_DestroyWindow((Tk_Window
) winPtr
);
818 return (Tk_Window
) winPtr
;
821 return CreateTopLevelWindow(interp
, parent
, pathName
+numChars
+1,
827 *--------------------------------------------------------------
829 * Tk_DestroyWindow --
831 * Destroy an existing window. After this call, the caller
832 * should never again use the token.
838 * The window is deleted, along with all of its children.
839 * Relevant callback procedures are invoked.
841 *--------------------------------------------------------------
845 Tk_DestroyWindow(tkwin
)
846 Tk_Window tkwin
; /* Window to destroy. */
848 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
852 * Recursively destroy children. The TK_RECURSIVE_DESTROY
853 * flags means that the child's window needn't be explicitly
854 * destroyed (the destroy of the parent already did it), nor
855 * does it need to be removed from its parent's child list,
856 * since the parent is being destroyed too.
859 while (winPtr
->childList
!= NULL
) {
860 winPtr
->childList
->flags
|= TK_RECURSIVE_DESTROY
;
861 Tk_DestroyWindow((Tk_Window
) winPtr
->childList
);
865 * Generate a DestroyNotify event. In order for the DestroyNotify
866 * event to be processed correctly, need to make sure the window
867 * exists. This is a bit of a kludge, and may be unnecessarily
868 * expensive, but without it no event handlers will get called for
869 * windows that don't exist yet.
872 if (winPtr
->window
== None
) {
873 Tk_MakeWindowExist(tkwin
);
875 winPtr
->flags
|= TK_ALREADY_DEAD
;
876 event
.type
= DestroyNotify
;
877 event
.xdestroywindow
.serial
=
878 LastKnownRequestProcessed(winPtr
->display
);
879 event
.xdestroywindow
.send_event
= False
;
880 event
.xdestroywindow
.display
= winPtr
->display
;
881 event
.xdestroywindow
.event
= winPtr
->window
;
882 event
.xdestroywindow
.window
= winPtr
->window
;
883 Tk_HandleEvent(&event
);
886 * Cleanup the data structures associated with this window.
887 * No need to destroy windows during recursive destroys, since
888 * that will happen automatically when the parent window is
889 * destroyed (not true for top-level windows: must destroy
893 if (winPtr
->window
!= None
) {
894 if (!(winPtr
->flags
& TK_RECURSIVE_DESTROY
)
895 || (winPtr
->flags
& TK_TOP_LEVEL
)) {
896 XDestroyWindow(winPtr
->display
, winPtr
->window
);
898 XDeleteContext(winPtr
->display
, winPtr
->window
, tkWindowContext
);
899 winPtr
->window
= None
;
901 if (winPtr
->parentPtr
!= NULL
) {
902 if (winPtr
->parentPtr
->childList
== winPtr
) {
903 winPtr
->parentPtr
->childList
= winPtr
->nextPtr
;
905 register TkWindow
*winPtr2
;
907 for (winPtr2
= winPtr
->parentPtr
->childList
; ;
908 winPtr2
= winPtr2
->nextPtr
) {
909 if (winPtr2
== NULL
) {
910 panic("Tk_DestroyWindow couldn't find child in parent (deleted twice?)");
913 if (winPtr2
->nextPtr
== winPtr
) {
914 winPtr2
->nextPtr
= winPtr
->nextPtr
;
920 TkEventDeadWindow(winPtr
);
921 TkOptionDeadWindow(winPtr
);
922 TkSelDeadWindow(winPtr
);
923 if (winPtr
->flags
& TK_TOP_LEVEL
) {
924 TkWmDeadWindow(winPtr
);
926 TkGrabDeadWindow(winPtr
);
927 if (winPtr
->mainPtr
!= NULL
) {
928 Tk_DeleteAllBindings(winPtr
->mainPtr
->bindingTable
,
929 (ClientData
) winPtr
->pathName
);
930 if (winPtr
->pathName
!= NULL
) {
931 Tcl_DeleteHashEntry(Tcl_FindHashEntry(&winPtr
->mainPtr
->nameTable
,
934 if (winPtr
->mainPtr
->winPtr
== winPtr
) {
935 register TkCmd
*cmdPtr
;
938 * Deleting a main window. Delete the TkMainInfo structure too
939 * and replace all of Tk's commands with dummy commands that
940 * return errors. Also delete the "send" command to unregister
944 for (cmdPtr
= commands
; cmdPtr
->name
!= NULL
; cmdPtr
++) {
945 Tcl_CreateCommand(winPtr
->mainPtr
->interp
, cmdPtr
->name
,
946 TkDeadAppCmd
, (ClientData
) NULL
, (void (*)()) NULL
);
948 Tcl_CreateCommand(winPtr
->mainPtr
->interp
, "send",
949 TkDeadAppCmd
, (ClientData
) NULL
, (void (*)()) NULL
);
950 Tcl_DeleteHashTable(&winPtr
->mainPtr
->nameTable
);
951 Tk_DeleteBindingTable(winPtr
->mainPtr
->bindingTable
);
952 ckfree((char *) winPtr
->mainPtr
);
956 ckfree((char *) winPtr
);
960 *--------------------------------------------------------------
964 * Map a window within its parent. This may require the
965 * window and/or its parents to actually be created.
971 * The given window will be mapped. Windows may also
974 *--------------------------------------------------------------
979 Tk_Window tkwin
; /* Token for window to map. */
981 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
983 if (winPtr
->flags
& TK_MAPPED
) {
986 if (winPtr
->window
== None
) {
987 Tk_MakeWindowExist(tkwin
);
989 if (winPtr
->flags
& TK_TOP_LEVEL
) {
990 if (!TkWmMapWindow(winPtr
)) {
995 * Don't set the mapped flag for top-level windows: TkWmMapWindow
996 * does it if appropriate (e.g. if the window is going to be non-
1000 winPtr
->flags
|= TK_MAPPED
;
1002 XMapWindow(winPtr
->display
, winPtr
->window
);
1003 if (!(winPtr
->flags
& TK_TOP_LEVEL
)) {
1006 event
.type
= MapNotify
;
1007 event
.xmap
.serial
= LastKnownRequestProcessed(winPtr
->display
);
1008 event
.xmap
.send_event
= False
;
1009 event
.xmap
.display
= winPtr
->display
;
1010 event
.xmap
.event
= winPtr
->window
;
1011 event
.xmap
.window
= winPtr
->window
;
1012 event
.xmap
.override_redirect
= winPtr
->atts
.override_redirect
;
1013 Tk_HandleEvent(&event
);
1018 *--------------------------------------------------------------
1020 * Tk_MakeWindowExist --
1022 * Ensure that a particular window actually exists. This
1023 * procedure shouldn't normally need to be invoked from
1024 * outside the Tk package, but may be needed if someone
1025 * wants to manipulate a window before mapping it.
1031 * When the procedure returns, the X window associated with
1032 * tkwin is guaranteed to exist. This may require the
1033 * window's ancestors to be created also.
1035 *--------------------------------------------------------------
1039 Tk_MakeWindowExist(tkwin
)
1040 Tk_Window tkwin
; /* Token for window. */
1042 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1045 if (winPtr
->window
!= None
) {
1049 if (winPtr
->flags
& TK_TOP_LEVEL
) {
1051 * workaround by dhopkins for OLPC Micropolis gtk.Socket integration.
1054 if (tk_RootWindow
) {
1059 XRootWindow(winPtr
->display
, winPtr
->screenNum
);
1063 if (winPtr
->parentPtr
->window
== None
) {
1064 Tk_MakeWindowExist((Tk_Window
) winPtr
->parentPtr
);
1066 parent
= winPtr
->parentPtr
->window
;
1069 /* workaround to support non-default colormaps */
1071 winPtr
->window
= XCreateWindow(winPtr
->display
, parent
,
1072 winPtr
->changes
.x
, winPtr
->changes
.y
,
1073 winPtr
->changes
.width
, winPtr
->changes
.height
,
1074 winPtr
->changes
.border_width
, CopyFromParent
,
1075 InputOutput
, CopyFromParent
, winPtr
->dirtyAtts
,
1078 { Screen
*scr
= ScreenOfDisplay(winPtr
->display
, winPtr
->screenNum
);
1080 winPtr
->dirtyAtts
|= CWColormap
| CWBorderPixmap
;
1081 winPtr
->atts
.colormap
= Tk_DefaultColormap(scr
);
1082 winPtr
->atts
.border_pixmap
= Tk_DefaultPixmap(scr
);
1084 winPtr
->window
= XCreateWindow(winPtr
->display
, parent
,
1085 winPtr
->changes
.x
, winPtr
->changes
.y
,
1086 winPtr
->changes
.width
, winPtr
->changes
.height
,
1087 winPtr
->changes
.border_width
,
1088 Tk_DefaultDepth(scr
),
1090 Tk_DefaultVisual(scr
),
1091 winPtr
->dirtyAtts
, &winPtr
->atts
);
1095 XSaveContext(winPtr
->display
, winPtr
->window
, tkWindowContext
,
1097 winPtr
->dirtyAtts
= 0;
1098 winPtr
->dirtyChanges
&= ~(CWX
|CWY
|CWWidth
|CWHeight
|CWBorderWidth
);
1099 if (winPtr
->dirtyChanges
!= 0) {
1100 XConfigureWindow(winPtr
->display
, winPtr
->window
,
1101 winPtr
->dirtyChanges
, &winPtr
->changes
);
1102 winPtr
->dirtyChanges
= 0;
1106 * Issue a ConfigureNotify event if there were deferred configuration
1110 if (winPtr
->flags
& TK_NEED_CONFIG_NOTIFY
) {
1111 winPtr
->flags
&= ~TK_NEED_CONFIG_NOTIFY
;
1112 DoConfigureNotify(winPtr
);
1117 *--------------------------------------------------------------
1119 * Tk_UnmapWindow, etc. --
1121 * There are several procedures under here, each of which
1122 * mirrors an existing X procedure. In addition to performing
1123 * the functions of the corresponding procedure, each
1124 * procedure also updates the local window structure and
1125 * synthesizes an X event (if the window's structure is being
1126 * managed internally).
1129 * See the manual entries.
1132 * See the manual entries.
1134 *--------------------------------------------------------------
1138 Tk_UnmapWindow(tkwin
)
1139 Tk_Window tkwin
; /* Token for window to unmap. */
1141 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1143 if (!(winPtr
->flags
& TK_MAPPED
)) {
1146 winPtr
->flags
&= ~TK_MAPPED
;
1147 XUnmapWindow(winPtr
->display
, winPtr
->window
);
1148 if (!(winPtr
->flags
& TK_TOP_LEVEL
)) {
1151 event
.type
= UnmapNotify
;
1152 event
.xunmap
.serial
= LastKnownRequestProcessed(winPtr
->display
);
1153 event
.xunmap
.send_event
= False
;
1154 event
.xunmap
.display
= winPtr
->display
;
1155 event
.xunmap
.event
= winPtr
->window
;
1156 event
.xunmap
.window
= winPtr
->window
;
1157 event
.xunmap
.from_configure
= False
;
1158 Tk_HandleEvent(&event
);
1163 Tk_ConfigureWindow(tkwin
, valueMask
, valuePtr
)
1164 Tk_Window tkwin
; /* Window to re-configure. */
1165 unsigned int valueMask
; /* Mask indicating which parts of
1166 * *valuePtr are to be used. */
1167 XWindowChanges
*valuePtr
; /* New values. */
1169 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1171 if ((winPtr
->window
== None
) || !(winPtr
->flags
& TK_TOP_LEVEL
)) {
1172 if (valueMask
& CWX
) {
1173 winPtr
->changes
.x
= valuePtr
->x
;
1175 if (valueMask
& CWY
) {
1176 winPtr
->changes
.y
= valuePtr
->y
;
1178 if (valueMask
& CWWidth
) {
1179 winPtr
->changes
.width
= valuePtr
->width
;
1181 if (valueMask
& CWHeight
) {
1182 winPtr
->changes
.height
= valuePtr
->height
;
1184 if (valueMask
& CWBorderWidth
) {
1185 winPtr
->changes
.border_width
= valuePtr
->border_width
;
1187 if (valueMask
& CWSibling
) {
1188 winPtr
->changes
.sibling
= valuePtr
->sibling
;
1190 if (valueMask
& CWStackMode
) {
1191 winPtr
->changes
.stack_mode
= valuePtr
->stack_mode
;
1195 if (winPtr
->window
!= None
) {
1196 XConfigureWindow(winPtr
->display
, winPtr
->window
,
1197 valueMask
, valuePtr
);
1198 if (!(winPtr
->flags
& TK_TOP_LEVEL
)) {
1199 DoConfigureNotify(winPtr
);
1202 winPtr
->dirtyChanges
|= valueMask
;
1203 winPtr
->flags
|= TK_NEED_CONFIG_NOTIFY
;
1208 Tk_MoveWindow(tkwin
, x
, y
)
1209 Tk_Window tkwin
; /* Window to move. */
1210 int x
, y
; /* New location for window (within
1213 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1215 if (winPtr
->window
!= None
) {
1216 XMoveWindow(winPtr
->display
, winPtr
->window
, x
, y
);
1217 if (!(winPtr
->flags
& TK_TOP_LEVEL
)) {
1218 winPtr
->changes
.x
= x
;
1219 winPtr
->changes
.y
= y
;
1220 DoConfigureNotify(winPtr
);
1223 winPtr
->changes
.x
= x
;
1224 winPtr
->changes
.y
= y
;
1225 winPtr
->dirtyChanges
|= CWX
|CWY
;
1226 winPtr
->flags
|= TK_NEED_CONFIG_NOTIFY
;
1231 Tk_ResizeWindow(tkwin
, width
, height
)
1232 Tk_Window tkwin
; /* Window to resize. */
1233 unsigned int width
, height
; /* New dimensions for window. */
1235 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1237 if (winPtr
->window
!= None
) {
1238 XResizeWindow(winPtr
->display
, winPtr
->window
, width
, height
);
1239 if (!(winPtr
->flags
& TK_TOP_LEVEL
)) {
1240 winPtr
->changes
.width
= width
;
1241 winPtr
->changes
.height
= height
;
1242 DoConfigureNotify(winPtr
);
1245 winPtr
->changes
.width
= width
;
1246 winPtr
->changes
.height
= height
;
1247 winPtr
->dirtyChanges
|= CWWidth
|CWHeight
;
1248 winPtr
->flags
|= TK_NEED_CONFIG_NOTIFY
;
1253 Tk_MoveResizeWindow(tkwin
, x
, y
, width
, height
)
1254 Tk_Window tkwin
; /* Window to move and resize. */
1255 int x
, y
; /* New location for window (within
1257 unsigned int width
, height
; /* New dimensions for window. */
1259 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1261 if (winPtr
->window
!= None
) {
1262 XMoveResizeWindow(winPtr
->display
, winPtr
->window
,
1263 x
, y
, width
, height
);
1264 if (!(winPtr
->flags
& TK_TOP_LEVEL
)) {
1265 winPtr
->changes
.x
= x
;
1266 winPtr
->changes
.y
= y
;
1267 winPtr
->changes
.width
= width
;
1268 winPtr
->changes
.height
= height
;
1269 DoConfigureNotify(winPtr
);
1272 winPtr
->changes
.x
= x
;
1273 winPtr
->changes
.y
= y
;
1274 winPtr
->changes
.width
= width
;
1275 winPtr
->changes
.height
= height
;
1276 winPtr
->dirtyChanges
|= CWX
|CWY
|CWWidth
|CWHeight
;
1277 winPtr
->flags
|= TK_NEED_CONFIG_NOTIFY
;
1282 Tk_SetWindowBorderWidth(tkwin
, width
)
1283 Tk_Window tkwin
; /* Window to modify. */
1284 int width
; /* New border width for window. */
1286 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1288 winPtr
->changes
.border_width
= width
;
1289 if (winPtr
->window
!= None
) {
1290 XSetWindowBorderWidth(winPtr
->display
, winPtr
->window
, width
);
1291 if (!(winPtr
->flags
& TK_TOP_LEVEL
)) {
1292 DoConfigureNotify(winPtr
);
1295 winPtr
->dirtyChanges
|= CWBorderWidth
;
1296 winPtr
->flags
|= TK_NEED_CONFIG_NOTIFY
;
1301 Tk_ChangeWindowAttributes(tkwin
, valueMask
, attsPtr
)
1302 Tk_Window tkwin
; /* Window to manipulate. */
1303 unsigned long valueMask
; /* OR'ed combination of bits,
1304 * indicating which fields of
1305 * *attsPtr are to be used. */
1306 register XSetWindowAttributes
*attsPtr
;
1307 /* New values for some attributes. */
1309 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1311 if (valueMask
& CWBackPixmap
) {
1312 winPtr
->atts
.background_pixmap
= attsPtr
->background_pixmap
;
1314 if (valueMask
& CWBackPixel
) {
1315 winPtr
->atts
.background_pixel
= attsPtr
->background_pixel
;
1317 if (valueMask
& CWBorderPixmap
) {
1318 winPtr
->atts
.border_pixmap
= attsPtr
->border_pixmap
;
1320 if (valueMask
& CWBorderPixel
) {
1321 winPtr
->atts
.border_pixel
= attsPtr
->border_pixel
;
1323 if (valueMask
& CWBitGravity
) {
1324 winPtr
->atts
.bit_gravity
= attsPtr
->bit_gravity
;
1326 if (valueMask
& CWWinGravity
) {
1327 winPtr
->atts
.win_gravity
= attsPtr
->win_gravity
;
1329 if (valueMask
& CWBackingStore
) {
1330 winPtr
->atts
.backing_store
= attsPtr
->backing_store
;
1332 if (valueMask
& CWBackingPlanes
) {
1333 winPtr
->atts
.backing_planes
= attsPtr
->backing_planes
;
1335 if (valueMask
& CWBackingPixel
) {
1336 winPtr
->atts
.backing_pixel
= attsPtr
->backing_pixel
;
1338 if (valueMask
& CWOverrideRedirect
) {
1339 winPtr
->atts
.override_redirect
= attsPtr
->override_redirect
;
1341 if (valueMask
& CWSaveUnder
) {
1342 winPtr
->atts
.save_under
= attsPtr
->save_under
;
1344 if (valueMask
& CWEventMask
) {
1345 winPtr
->atts
.event_mask
= attsPtr
->event_mask
;
1347 if (valueMask
& CWDontPropagate
) {
1348 winPtr
->atts
.do_not_propagate_mask
1349 = attsPtr
->do_not_propagate_mask
;
1351 if (valueMask
& CWColormap
) {
1352 winPtr
->atts
.colormap
= attsPtr
->colormap
;
1354 if (valueMask
& CWCursor
) {
1355 winPtr
->atts
.cursor
= attsPtr
->cursor
;
1358 if (winPtr
->window
!= None
) {
1359 XChangeWindowAttributes(winPtr
->display
, winPtr
->window
,
1360 valueMask
, attsPtr
);
1362 winPtr
->dirtyAtts
|= valueMask
;
1367 Tk_SetWindowBackground(tkwin
, pixel
)
1368 Tk_Window tkwin
; /* Window to manipulate. */
1369 unsigned long pixel
; /* Pixel value to use for
1370 * window's background. */
1372 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1374 winPtr
->atts
.background_pixel
= pixel
;
1376 if (winPtr
->window
!= None
) {
1377 XSetWindowBackground(winPtr
->display
, winPtr
->window
, pixel
);
1379 winPtr
->dirtyAtts
= (winPtr
->dirtyAtts
& ~CWBackPixmap
)
1385 Tk_SetWindowBackgroundPixmap(tkwin
, pixmap
)
1386 Tk_Window tkwin
; /* Window to manipulate. */
1387 Pixmap pixmap
; /* Pixmap to use for window's
1390 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1392 winPtr
->atts
.background_pixmap
= pixmap
;
1394 if (winPtr
->window
!= None
) {
1395 XSetWindowBackgroundPixmap(winPtr
->display
,
1396 winPtr
->window
, pixmap
);
1398 winPtr
->dirtyAtts
= (winPtr
->dirtyAtts
& ~CWBackPixel
)
1404 Tk_SetWindowBorder(tkwin
, pixel
)
1405 Tk_Window tkwin
; /* Window to manipulate. */
1406 unsigned long pixel
; /* Pixel value to use for
1407 * window's border. */
1409 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1411 winPtr
->atts
.border_pixel
= pixel
;
1413 if (winPtr
->window
!= None
) {
1414 XSetWindowBorder(winPtr
->display
, winPtr
->window
, pixel
);
1416 winPtr
->dirtyAtts
= (winPtr
->dirtyAtts
& ~CWBorderPixmap
)
1422 Tk_SetWindowBorderPixmap(tkwin
, pixmap
)
1423 Tk_Window tkwin
; /* Window to manipulate. */
1424 Pixmap pixmap
; /* Pixmap to use for window's
1427 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1429 winPtr
->atts
.border_pixmap
= pixmap
;
1431 if (winPtr
->window
!= None
) {
1432 XSetWindowBorderPixmap(winPtr
->display
,
1433 winPtr
->window
, pixmap
);
1435 winPtr
->dirtyAtts
= (winPtr
->dirtyAtts
& ~CWBorderPixel
)
1441 Tk_DefineCursor(tkwin
, cursor
)
1442 Tk_Window tkwin
; /* Window to manipulate. */
1443 Cursor cursor
; /* Cursor to use for window (may be None). */
1445 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1447 winPtr
->atts
.cursor
= cursor
;
1449 if (winPtr
->window
!= None
) {
1450 XDefineCursor(winPtr
->display
, winPtr
->window
, cursor
);
1452 winPtr
->dirtyAtts
= winPtr
->dirtyAtts
| CWCursor
;
1457 Tk_UndefineCursor(tkwin
)
1458 Tk_Window tkwin
; /* Window to manipulate. */
1460 Tk_DefineCursor(tkwin
, None
);
1464 *----------------------------------------------------------------------
1466 * DoConfigureNotify --
1468 * Generate a ConfigureNotify event describing the current
1469 * configuration of a window.
1475 * An event is generated and processed by Tk_HandleEvent.
1477 *----------------------------------------------------------------------
1481 DoConfigureNotify(winPtr
)
1482 register TkWindow
*winPtr
; /* Window whose configuration
1483 * was just changed. */
1487 event
.type
= ConfigureNotify
;
1488 event
.xconfigure
.serial
= LastKnownRequestProcessed(winPtr
->display
);
1489 event
.xconfigure
.send_event
= False
;
1490 event
.xconfigure
.display
= winPtr
->display
;
1491 event
.xconfigure
.event
= winPtr
->window
;
1492 event
.xconfigure
.window
= winPtr
->window
;
1493 event
.xconfigure
.x
= winPtr
->changes
.x
;
1494 event
.xconfigure
.y
= winPtr
->changes
.y
;
1495 event
.xconfigure
.width
= winPtr
->changes
.width
;
1496 event
.xconfigure
.height
= winPtr
->changes
.height
;
1497 event
.xconfigure
.border_width
= winPtr
->changes
.border_width
;
1498 if (winPtr
->changes
.stack_mode
== Above
) {
1499 event
.xconfigure
.above
= winPtr
->changes
.sibling
;
1501 event
.xconfigure
.above
= None
;
1503 event
.xconfigure
.override_redirect
= winPtr
->atts
.override_redirect
;
1504 Tk_HandleEvent(&event
);
1508 *----------------------------------------------------------------------
1512 * This procedure is used to give a window a class.
1518 * A new class is stored for tkwin, replacing any existing
1521 *----------------------------------------------------------------------
1525 Tk_SetClass(tkwin
, className
)
1526 Tk_Window tkwin
; /* Token for window to assign class. */
1527 char *className
; /* New class for tkwin. */
1529 register TkWindow
*winPtr
= (TkWindow
*) tkwin
;
1531 winPtr
->classUid
= Tk_GetUid(className
);
1532 if (winPtr
->flags
& TK_TOP_LEVEL
) {
1533 TkWmSetClass(winPtr
);
1538 *----------------------------------------------------------------------
1540 * Tk_NameToWindow --
1542 * Given a string name for a window, this procedure
1543 * returns the token for the window, if there exists a
1544 * window corresponding to the given name.
1547 * The return result is either a token for the window corresponding
1548 * to "name", or else NULL to indicate that there is no such
1549 * window. In this case, an error message is left in interp->result.
1554 *----------------------------------------------------------------------
1558 Tk_NameToWindow(interp
, pathName
, tkwin
)
1559 Tcl_Interp
*interp
; /* Where to report errors. */
1560 char *pathName
; /* Path name of window. */
1561 Tk_Window tkwin
; /* Token for window: name is assumed to
1562 * belong to the same main window as tkwin. */
1564 Tcl_HashEntry
*hPtr
;
1566 hPtr
= Tcl_FindHashEntry(&((TkWindow
*) tkwin
)->mainPtr
->nameTable
,
1569 Tcl_AppendResult(interp
, "bad window path name \"",
1570 pathName
, "\"", (char *) NULL
);
1573 return (Tk_Window
) Tcl_GetHashValue(hPtr
);
1577 *----------------------------------------------------------------------
1581 * Return the textual name of a window's display.
1584 * The return value is the string name of the display associated
1590 *----------------------------------------------------------------------
1594 Tk_DisplayName(tkwin
)
1595 Tk_Window tkwin
; /* Window whose display name is desired. */
1597 return ((TkWindow
*) tkwin
)->dispPtr
->name
;