]> cvs.zerfleddert.de Git - micropolis/blob - src/tk/tkwindow.c
allow scenario window to be closed
[micropolis] / src / tk / tkwindow.c
1 /*
2 * tkWindow.c --
3 *
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
7 * structure.
8 *
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.
17 */
18
19 #ifndef lint
20 static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkWindow.c,v 1.92 92/08/21 11:42:44 ouster Exp $ SPRITE (Berkeley)";
21 #endif
22
23 #include "tkconfig.h"
24 #include "tkint.h"
25
26 /*
27 * Global absolute file name:
28 */
29 char *TK_Library = TK_LIBRARY;
30
31 /*
32 * Count of open displays.
33 */
34 int tk_Displays;
35
36 /*
37 * Count of number of main windows currently open in this process.
38 */
39
40 int tk_NumMainWindows;
41
42 /*
43 * Added by dhopkins for OLPC Micropolis gtk.Socket integration.
44 */
45
46 Window tk_RootWindow = 0;
47
48 /*
49 * List of all displays currently in use.
50 */
51
52 TkDisplay *tkDisplayList = NULL;
53
54 /*
55 * Have statics in this module been initialized?
56 */
57
58 static initialized = 0;
59
60 /*
61 * Context information used to map from X window id's to
62 * TkWindow structures (during event handling, for example):
63 */
64
65 XContext tkWindowContext;
66
67 /*
68 * The variables below hold several uid's that are used in many places
69 * in the toolkit.
70 */
71
72 Tk_Uid tkDisabledUid = NULL;
73 Tk_Uid tkActiveUid = NULL;
74 Tk_Uid tkNormalUid = NULL;
75
76 /*
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.
80 */
81
82 static XWindowChanges defChanges = {
83 0, 0, 1, 1, 0, 0, Above
84 };
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 */
94 0, /* border_pixel */
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 */
105 None /* cursor */
106 };
107
108 /*
109 * The following structure defines all of the commands supported by
110 * Tk, and the C procedures that execute them.
111 */
112
113 typedef struct {
114 char *name; /* Name of command. */
115 int (*cmdProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
116 int argc, char **argv));
117 /* Command procedure. */
118 } TkCmd;
119
120 TkCmd commands[] = {
121 /*
122 * Commands that are part of the intrinsics:
123 */
124
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},
137 {"wm", Tk_WmCmd},
138 {"accept", Tcp_AcceptCmd},
139 {"shutdown", Tcp_ShutdownCmd},
140 {"connect", Tcp_ConnectCmd},
141 {"filehandler", Tcp_FileHandlerCmd},
142
143 /*
144 * Widget-creation commands.
145 */
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}
162 };
163
164 /*
165 * Forward declarations to procedures defined later in this file:
166 */
167
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,
175 char *name));
176 static TkWindow * NewWindow _ANSI_ARGS_((TkDisplay *dispPtr,
177 int screenNum));
178 \f
179 /*
180 *----------------------------------------------------------------------
181 *
182 * CreateTopLevelWindow --
183 *
184 * Make a new window that will be at top-level (its parent will
185 * be the root window of a screen).
186 *
187 * Results:
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
191 * interp->result.
192 *
193 * Side effects:
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.
197 *
198 *----------------------------------------------------------------------
199 */
200
201 static Tk_Window
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
206 * be NULL. */
207 char *name; /* Name for new window; if parent is
208 * non-NULL, must be unique among parent's
209 * children. */
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
214 * parent. */
215 {
216 register TkWindow *winPtr;
217 register TkDisplay *dispPtr;
218 int screenId;
219
220 if (!initialized) {
221 initialized = 1;
222 tkWindowContext = XUniqueContext();
223 tkActiveUid = Tk_GetUid("active");
224 tkDisabledUid = Tk_GetUid("disabled");
225 tkNormalUid = Tk_GetUid("normal");
226 }
227
228 if ((parent != NULL) && (screenName != NULL) && (screenName[0] == '\0')) {
229 dispPtr = ((TkWindow *) parent)->dispPtr;
230 screenId = Tk_ScreenNumber(parent);
231 } else {
232 dispPtr = GetScreen(interp, screenName, &screenId);
233 if (dispPtr == NULL) {
234 return (Tk_Window) NULL;
235 }
236 }
237
238 winPtr = NewWindow(dispPtr, screenId);
239
240 /*
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.
245 */
246
247 winPtr->atts.event_mask |= StructureNotifyMask;
248
249 /*
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
252 * has been set.)
253 */
254
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;
260 }
261 }
262 TkWmNewWindow(winPtr);
263 return (Tk_Window) winPtr;
264 }
265 \f
266 /*
267 *----------------------------------------------------------------------
268 *
269 * GetScreen --
270 *
271 * Given a string name for a display-plus-screen, find the
272 * TkDisplay structure for the display and return the screen
273 * number too.
274 *
275 * Results:
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
280 * screenName.
281 *
282 * Side effects:
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.
286 *
287 *----------------------------------------------------------------------
288 */
289
290 static TkDisplay *
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. */
296 {
297 register TkDisplay *dispPtr;
298 char *p;
299 int length, screenId;
300
301 /*
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
305 * optional.
306 */
307
308 if ((screenName == NULL) || (screenName[0] == '\0')) {
309 screenName = getenv("DISPLAY");
310 if (screenName == NULL) {
311 interp->result =
312 "no display name and no $DISPLAY environment variable";
313 return (TkDisplay *) NULL;
314 }
315 }
316 length = strlen(screenName);
317 screenId = 0;
318 p = screenName+length-1;
319 while (isdigit(*p) && (p != screenName)) {
320 p--;
321 }
322 if ((*p == '.') && (p[1] != '\0')) {
323 length = p - screenName;
324 screenId = strtoul(p+1, (char **) NULL, 10);
325 }
326
327 /*
328 * See if we already have a connection to this display. If not,
329 * then open a new connection.
330 */
331
332 for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr) {
333 if (dispPtr == NULL) {
334 Display *display = NULL;
335
336 display = XOpenDisplay(screenName);
337
338 if (display == NULL) {
339 Tcl_AppendResult(interp, "couldn't connect to display \"",
340 screenName, "\"", (char *) NULL);
341 return (TkDisplay *) NULL;
342 }
343 if (getenv("XSYNCHRONIZE") != NULL) {
344 XSynchronize(display, 1);
345 }
346 tk_Displays++;
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);
375 break;
376 }
377 if ((strncmp(dispPtr->name, screenName, length) == 0)
378 && (dispPtr->name[length] == '\0')) {
379 break;
380 }
381 }
382 if (screenId >= ScreenCount(dispPtr->display)) {
383 sprintf(interp->result, "bad screen number \"%d\"", screenId);
384 return (TkDisplay *) NULL;
385 }
386 *screenPtr = screenId;
387 return dispPtr;
388 }
389 \f
390 /*
391 *--------------------------------------------------------------
392 *
393 * NewWindow --
394 *
395 * This procedure creates and initializes a TkWindow structure.
396 *
397 * Results:
398 * The return value is a pointer to the new window.
399 *
400 * Side effects:
401 * A new window structure is allocated and all its fields are
402 * initialized.
403 *
404 *--------------------------------------------------------------
405 */
406
407 static TkWindow *
408 NewWindow(dispPtr, screenNum)
409 TkDisplay *dispPtr; /* Display associated with new window. */
410 int screenNum; /* Index of screen for new window. */
411 {
412 register TkWindow *winPtr;
413
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;
430 winPtr->flags = 0;
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;
443 return winPtr;
444 }
445 \f
446 /*
447 *----------------------------------------------------------------------
448 *
449 * NameWindow --
450 *
451 * This procedure is invoked to give a window a name and insert
452 * the window into the hierarchy associated with a particular
453 * application.
454 *
455 * Results:
456 * A standard Tcl return value.
457 *
458 * Side effects:
459 * See above.
460 *
461 *----------------------------------------------------------------------
462 */
463
464 static int
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. */
472 {
473 #define FIXED_SIZE 200
474 char staticSpace[FIXED_SIZE];
475 char *pathName;
476 int new;
477 Tcl_HashEntry *hPtr;
478 int length1, length2;
479
480 /*
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).
485 */
486 winPtr->parentPtr = parentPtr;
487 winPtr->nextPtr = parentPtr->childList;
488 parentPtr->childList = winPtr;
489 winPtr->mainPtr = parentPtr->mainPtr;
490 winPtr->nameUid = Tk_GetUid(name);
491
492 /*
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
496 * stack.
497 */
498
499 length1 = strlen(parentPtr->pathName);
500 length2 = strlen(name);
501 if ((length1+length2+2) <= FIXED_SIZE) {
502 pathName = staticSpace;
503 } else {
504 pathName = (char *) ckalloc((unsigned) (length1+length2+2));
505 }
506 if (length1 == 1) {
507 pathName[0] = '.';
508 strcpy(pathName+1, name);
509 } else {
510 strcpy(pathName, parentPtr->pathName);
511 pathName[length1] = '.';
512 strcpy(pathName+length1+1, name);
513 }
514 hPtr = Tcl_CreateHashEntry(&parentPtr->mainPtr->nameTable, pathName, &new);
515 if (pathName != staticSpace) {
516 ckfree(pathName);
517 }
518 if (!new) {
519 Tcl_AppendResult(interp, "window name \"", name,
520 "\" already exists in parent", (char *) NULL);
521 return TCL_ERROR;
522 }
523 Tcl_SetHashValue(hPtr, winPtr);
524 winPtr->pathName = Tcl_GetHashKey(&parentPtr->mainPtr->nameTable, hPtr);
525 return TCL_OK;
526 }
527 \f
528 /*
529 *----------------------------------------------------------------------
530 *
531 * Tk_CreateMainWindow --
532 *
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
535 * application.
536 *
537 * Results:
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
541 * interp->result.
542 *
543 * Side effects:
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.
551 *
552 *----------------------------------------------------------------------
553 */
554
555 Tk_Window
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". */
563 {
564 Tk_Window tkwin;
565 int result, dummy;
566 Tcl_HashEntry *hPtr;
567 register TkMainInfo *mainPtr;
568 register TkWindow *winPtr;
569 register TkCmd *cmdPtr;
570
571 /*
572 * Create the basic TkWindow structure.
573 */
574
575 tkwin = CreateTopLevelWindow(interp, (Tk_Window) NULL, baseName,
576 screenName);
577 if (tkwin == NULL) {
578 return NULL;
579 }
580
581 /*
582 * Create the TkMainInfo structure for this application, and set
583 * up name-related information for the new window.
584 */
585
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);
592 /* XXX: FOCUS */
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);
599
600 /*
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.
604 */
605
606 result = Tk_RegisterInterp(interp, baseName, tkwin);
607 if (result == TCL_OK) {
608 winPtr->nameUid = Tk_GetUid(baseName);
609 } else {
610 char newName[110];
611 int i;
612
613 for (i = 2; ; i++) {
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) {
618 break;
619 }
620 if (i >= 100) {
621 Tcl_SetResult(interp,
622 "couldn't generate unique name to register application",
623 TCL_STATIC);
624 Tk_DestroyWindow(tkwin);
625 }
626 }
627 winPtr->nameUid = Tk_GetUid(newName);
628 }
629
630 /*
631 * Bind in Tk's commands.
632 */
633
634 for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
635 Tcl_CreateCommand(interp, cmdPtr->name, cmdPtr->cmdProc,
636 (ClientData) tkwin, (void (*)()) NULL);
637 }
638
639 /*
640 * Set variables for the intepreter.
641 */
642
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);
646
647 tk_NumMainWindows++;
648 return tkwin;
649 }
650 \f
651 /*
652 *--------------------------------------------------------------
653 *
654 * Tk_CreateWindow --
655 *
656 * Create a new internal or top-level window as a child of an
657 * existing window.
658 *
659 * Results:
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
664 * NULL is returned.
665 *
666 * Side effects:
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.
670 *
671 *--------------------------------------------------------------
672 */
673
674 Tk_Window
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
686 * window. */
687 {
688 TkWindow *parentPtr = (TkWindow *) parent;
689 TkWindow *winPtr;
690
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);
695 return NULL;
696 } else {
697 return (Tk_Window) winPtr;
698 }
699 } else {
700 /*
701 * This is a fix for dvx XOpenDisplay... display name conformalization
702 * bugs...
703 */
704 char dsp[256];
705 int len;
706
707 strcpy(dsp, screenName);
708 len = strlen(dsp);
709 if (len && (dsp[len -1] == '.'))
710 dsp[len -1] = '\0';
711
712 return CreateTopLevelWindow(interp, parent, name, dsp);
713 }
714 }
715 \f
716 /*
717 *----------------------------------------------------------------------
718 *
719 * Tk_CreateWindowFromPath --
720 *
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.
724 *
725 * Results:
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
730 * NULL is returned.
731 *
732 * Side effects:
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.
736 *
737 *----------------------------------------------------------------------
738 */
739
740 Tk_Window
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
755 * window. */
756 {
757 #define FIXED_SPACE 5
758 char fixedSpace[FIXED_SPACE+1];
759 char *p;
760 Tk_Window parent;
761 int numChars;
762
763 /*
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 ".".
770 */
771
772 p = strrchr(pathName, '.');
773 if (p == NULL) {
774 Tcl_AppendResult(interp, "bad window path name \"", pathName,
775 "\"", (char *) NULL);
776 return NULL;
777 }
778 numChars = p-pathName;
779 if (numChars > FIXED_SPACE) {
780 p = (char *) ckalloc((unsigned) (numChars+1));
781 } else {
782 p = fixedSpace;
783 }
784 if (numChars == 0) {
785 *p = '.';
786 p[1] = '\0';
787 } else {
788 strncpy(p, pathName, numChars);
789 p[numChars] = '\0';
790 }
791
792 /*
793 * Find the parent window.
794 */
795
796 parent = Tk_NameToWindow(interp, p, tkwin);
797 if (p != fixedSpace) {
798 ckfree(p);
799 }
800 if (parent == NULL) {
801 return NULL;
802 }
803
804 /*
805 * Create the window.
806 */
807
808 if (screenName == NULL) {
809 TkWindow *parentPtr = (TkWindow *) parent;
810 TkWindow *winPtr;
811
812 winPtr = NewWindow(parentPtr->dispPtr, parentPtr->screenNum);
813 if (NameWindow(interp, winPtr, parentPtr, pathName+numChars+1)
814 != TCL_OK) {
815 Tk_DestroyWindow((Tk_Window) winPtr);
816 return NULL;
817 } else {
818 return (Tk_Window) winPtr;
819 }
820 } else {
821 return CreateTopLevelWindow(interp, parent, pathName+numChars+1,
822 screenName);
823 }
824 }
825 \f
826 /*
827 *--------------------------------------------------------------
828 *
829 * Tk_DestroyWindow --
830 *
831 * Destroy an existing window. After this call, the caller
832 * should never again use the token.
833 *
834 * Results:
835 * None.
836 *
837 * Side effects:
838 * The window is deleted, along with all of its children.
839 * Relevant callback procedures are invoked.
840 *
841 *--------------------------------------------------------------
842 */
843
844 void
845 Tk_DestroyWindow(tkwin)
846 Tk_Window tkwin; /* Window to destroy. */
847 {
848 register TkWindow *winPtr = (TkWindow *) tkwin;
849 XEvent event;
850
851 /*
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.
857 */
858
859 while (winPtr->childList != NULL) {
860 winPtr->childList->flags |= TK_RECURSIVE_DESTROY;
861 Tk_DestroyWindow((Tk_Window) winPtr->childList);
862 }
863
864 /*
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.
870 */
871
872 if (winPtr->window == None) {
873 Tk_MakeWindowExist(tkwin);
874 }
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);
884
885 /*
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
890 * them explicitly).
891 */
892
893 if (winPtr->window != None) {
894 if (!(winPtr->flags & TK_RECURSIVE_DESTROY)
895 || (winPtr->flags & TK_TOP_LEVEL)) {
896 XDestroyWindow(winPtr->display, winPtr->window);
897 }
898 XDeleteContext(winPtr->display, winPtr->window, tkWindowContext);
899 winPtr->window = None;
900 }
901 if (winPtr->parentPtr != NULL) {
902 if (winPtr->parentPtr->childList == winPtr) {
903 winPtr->parentPtr->childList = winPtr->nextPtr;
904 } else {
905 register TkWindow *winPtr2;
906
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?)");
911 break;
912 }
913 if (winPtr2->nextPtr == winPtr) {
914 winPtr2->nextPtr = winPtr->nextPtr;
915 break;
916 }
917 }
918 }
919 }
920 TkEventDeadWindow(winPtr);
921 TkOptionDeadWindow(winPtr);
922 TkSelDeadWindow(winPtr);
923 if (winPtr->flags & TK_TOP_LEVEL) {
924 TkWmDeadWindow(winPtr);
925 }
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,
932 winPtr->pathName));
933 }
934 if (winPtr->mainPtr->winPtr == winPtr) {
935 register TkCmd *cmdPtr;
936
937 /*
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
941 * the interpreter.
942 */
943
944 for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
945 Tcl_CreateCommand(winPtr->mainPtr->interp, cmdPtr->name,
946 TkDeadAppCmd, (ClientData) NULL, (void (*)()) NULL);
947 }
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);
953 tk_NumMainWindows--;
954 }
955 }
956 ckfree((char *) winPtr);
957 }
958 \f
959 /*
960 *--------------------------------------------------------------
961 *
962 * Tk_MapWindow --
963 *
964 * Map a window within its parent. This may require the
965 * window and/or its parents to actually be created.
966 *
967 * Results:
968 * None.
969 *
970 * Side effects:
971 * The given window will be mapped. Windows may also
972 * be created.
973 *
974 *--------------------------------------------------------------
975 */
976
977 void
978 Tk_MapWindow(tkwin)
979 Tk_Window tkwin; /* Token for window to map. */
980 {
981 register TkWindow *winPtr = (TkWindow *) tkwin;
982
983 if (winPtr->flags & TK_MAPPED) {
984 return;
985 }
986 if (winPtr->window == None) {
987 Tk_MakeWindowExist(tkwin);
988 }
989 if (winPtr->flags & TK_TOP_LEVEL) {
990 if (!TkWmMapWindow(winPtr)) {
991 return;
992 }
993 } else {
994 /*
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-
997 * iconic).
998 */
999
1000 winPtr->flags |= TK_MAPPED;
1001 }
1002 XMapWindow(winPtr->display, winPtr->window);
1003 if (!(winPtr->flags & TK_TOP_LEVEL)) {
1004 XEvent event;
1005
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);
1014 }
1015 }
1016 \f
1017 /*
1018 *--------------------------------------------------------------
1019 *
1020 * Tk_MakeWindowExist --
1021 *
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.
1026 *
1027 * Results:
1028 * None.
1029 *
1030 * Side effects:
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.
1034 *
1035 *--------------------------------------------------------------
1036 */
1037
1038 void
1039 Tk_MakeWindowExist(tkwin)
1040 Tk_Window tkwin; /* Token for window. */
1041 {
1042 register TkWindow *winPtr = (TkWindow *) tkwin;
1043 Window parent;
1044
1045 if (winPtr->window != None) {
1046 return;
1047 }
1048
1049 if (winPtr->flags & TK_TOP_LEVEL) {
1050 /*
1051 * workaround by dhopkins for OLPC Micropolis gtk.Socket integration.
1052 */
1053
1054 if (tk_RootWindow) {
1055 parent =
1056 tk_RootWindow;
1057 } else {
1058 parent =
1059 XRootWindow(winPtr->display, winPtr->screenNum);
1060 }
1061
1062 } else {
1063 if (winPtr->parentPtr->window == None) {
1064 Tk_MakeWindowExist((Tk_Window) winPtr->parentPtr);
1065 }
1066 parent = winPtr->parentPtr->window;
1067 }
1068
1069 /* workaround to support non-default colormaps */
1070 #if 0
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,
1076 &winPtr->atts);
1077 #else
1078 { Screen *scr = ScreenOfDisplay(winPtr->display, winPtr->screenNum);
1079
1080 winPtr->dirtyAtts |= CWColormap | CWBorderPixmap;
1081 winPtr->atts.colormap = Tk_DefaultColormap(scr);
1082 winPtr->atts.border_pixmap = Tk_DefaultPixmap(scr);
1083
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),
1089 InputOutput,
1090 Tk_DefaultVisual(scr),
1091 winPtr->dirtyAtts, &winPtr->atts);
1092 }
1093 #endif
1094
1095 XSaveContext(winPtr->display, winPtr->window, tkWindowContext,
1096 (void *) winPtr);
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;
1103 }
1104
1105 /*
1106 * Issue a ConfigureNotify event if there were deferred configuration
1107 * changes.
1108 */
1109
1110 if (winPtr->flags & TK_NEED_CONFIG_NOTIFY) {
1111 winPtr->flags &= ~TK_NEED_CONFIG_NOTIFY;
1112 DoConfigureNotify(winPtr);
1113 }
1114 }
1115 \f
1116 /*
1117 *--------------------------------------------------------------
1118 *
1119 * Tk_UnmapWindow, etc. --
1120 *
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).
1127 *
1128 * Results:
1129 * See the manual entries.
1130 *
1131 * Side effects:
1132 * See the manual entries.
1133 *
1134 *--------------------------------------------------------------
1135 */
1136
1137 void
1138 Tk_UnmapWindow(tkwin)
1139 Tk_Window tkwin; /* Token for window to unmap. */
1140 {
1141 register TkWindow *winPtr = (TkWindow *) tkwin;
1142
1143 if (!(winPtr->flags & TK_MAPPED)) {
1144 return;
1145 }
1146 winPtr->flags &= ~TK_MAPPED;
1147 XUnmapWindow(winPtr->display, winPtr->window);
1148 if (!(winPtr->flags & TK_TOP_LEVEL)) {
1149 XEvent event;
1150
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);
1159 }
1160 }
1161
1162 void
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. */
1168 {
1169 register TkWindow *winPtr = (TkWindow *) tkwin;
1170
1171 if ((winPtr->window == None) || !(winPtr->flags & TK_TOP_LEVEL)) {
1172 if (valueMask & CWX) {
1173 winPtr->changes.x = valuePtr->x;
1174 }
1175 if (valueMask & CWY) {
1176 winPtr->changes.y = valuePtr->y;
1177 }
1178 if (valueMask & CWWidth) {
1179 winPtr->changes.width = valuePtr->width;
1180 }
1181 if (valueMask & CWHeight) {
1182 winPtr->changes.height = valuePtr->height;
1183 }
1184 if (valueMask & CWBorderWidth) {
1185 winPtr->changes.border_width = valuePtr->border_width;
1186 }
1187 if (valueMask & CWSibling) {
1188 winPtr->changes.sibling = valuePtr->sibling;
1189 }
1190 if (valueMask & CWStackMode) {
1191 winPtr->changes.stack_mode = valuePtr->stack_mode;
1192 }
1193 }
1194
1195 if (winPtr->window != None) {
1196 XConfigureWindow(winPtr->display, winPtr->window,
1197 valueMask, valuePtr);
1198 if (!(winPtr->flags & TK_TOP_LEVEL)) {
1199 DoConfigureNotify(winPtr);
1200 }
1201 } else {
1202 winPtr->dirtyChanges |= valueMask;
1203 winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1204 }
1205 }
1206
1207 void
1208 Tk_MoveWindow(tkwin, x, y)
1209 Tk_Window tkwin; /* Window to move. */
1210 int x, y; /* New location for window (within
1211 * parent). */
1212 {
1213 register TkWindow *winPtr = (TkWindow *) tkwin;
1214
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);
1221 }
1222 } else {
1223 winPtr->changes.x = x;
1224 winPtr->changes.y = y;
1225 winPtr->dirtyChanges |= CWX|CWY;
1226 winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1227 }
1228 }
1229
1230 void
1231 Tk_ResizeWindow(tkwin, width, height)
1232 Tk_Window tkwin; /* Window to resize. */
1233 unsigned int width, height; /* New dimensions for window. */
1234 {
1235 register TkWindow *winPtr = (TkWindow *) tkwin;
1236
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);
1243 }
1244 } else {
1245 winPtr->changes.width = width;
1246 winPtr->changes.height = height;
1247 winPtr->dirtyChanges |= CWWidth|CWHeight;
1248 winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1249 }
1250 }
1251
1252 void
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
1256 * parent). */
1257 unsigned int width, height; /* New dimensions for window. */
1258 {
1259 register TkWindow *winPtr = (TkWindow *) tkwin;
1260
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);
1270 }
1271 } else {
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;
1278 }
1279 }
1280
1281 void
1282 Tk_SetWindowBorderWidth(tkwin, width)
1283 Tk_Window tkwin; /* Window to modify. */
1284 int width; /* New border width for window. */
1285 {
1286 register TkWindow *winPtr = (TkWindow *) tkwin;
1287
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);
1293 }
1294 } else {
1295 winPtr->dirtyChanges |= CWBorderWidth;
1296 winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
1297 }
1298 }
1299
1300 void
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. */
1308 {
1309 register TkWindow *winPtr = (TkWindow *) tkwin;
1310
1311 if (valueMask & CWBackPixmap) {
1312 winPtr->atts.background_pixmap = attsPtr->background_pixmap;
1313 }
1314 if (valueMask & CWBackPixel) {
1315 winPtr->atts.background_pixel = attsPtr->background_pixel;
1316 }
1317 if (valueMask & CWBorderPixmap) {
1318 winPtr->atts.border_pixmap = attsPtr->border_pixmap;
1319 }
1320 if (valueMask & CWBorderPixel) {
1321 winPtr->atts.border_pixel = attsPtr->border_pixel;
1322 }
1323 if (valueMask & CWBitGravity) {
1324 winPtr->atts.bit_gravity = attsPtr->bit_gravity;
1325 }
1326 if (valueMask & CWWinGravity) {
1327 winPtr->atts.win_gravity = attsPtr->win_gravity;
1328 }
1329 if (valueMask & CWBackingStore) {
1330 winPtr->atts.backing_store = attsPtr->backing_store;
1331 }
1332 if (valueMask & CWBackingPlanes) {
1333 winPtr->atts.backing_planes = attsPtr->backing_planes;
1334 }
1335 if (valueMask & CWBackingPixel) {
1336 winPtr->atts.backing_pixel = attsPtr->backing_pixel;
1337 }
1338 if (valueMask & CWOverrideRedirect) {
1339 winPtr->atts.override_redirect = attsPtr->override_redirect;
1340 }
1341 if (valueMask & CWSaveUnder) {
1342 winPtr->atts.save_under = attsPtr->save_under;
1343 }
1344 if (valueMask & CWEventMask) {
1345 winPtr->atts.event_mask = attsPtr->event_mask;
1346 }
1347 if (valueMask & CWDontPropagate) {
1348 winPtr->atts.do_not_propagate_mask
1349 = attsPtr->do_not_propagate_mask;
1350 }
1351 if (valueMask & CWColormap) {
1352 winPtr->atts.colormap = attsPtr->colormap;
1353 }
1354 if (valueMask & CWCursor) {
1355 winPtr->atts.cursor = attsPtr->cursor;
1356 }
1357
1358 if (winPtr->window != None) {
1359 XChangeWindowAttributes(winPtr->display, winPtr->window,
1360 valueMask, attsPtr);
1361 } else {
1362 winPtr->dirtyAtts |= valueMask;
1363 }
1364 }
1365
1366 void
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. */
1371 {
1372 register TkWindow *winPtr = (TkWindow *) tkwin;
1373
1374 winPtr->atts.background_pixel = pixel;
1375
1376 if (winPtr->window != None) {
1377 XSetWindowBackground(winPtr->display, winPtr->window, pixel);
1378 } else {
1379 winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBackPixmap)
1380 | CWBackPixel;
1381 }
1382 }
1383
1384 void
1385 Tk_SetWindowBackgroundPixmap(tkwin, pixmap)
1386 Tk_Window tkwin; /* Window to manipulate. */
1387 Pixmap pixmap; /* Pixmap to use for window's
1388 * background. */
1389 {
1390 register TkWindow *winPtr = (TkWindow *) tkwin;
1391
1392 winPtr->atts.background_pixmap = pixmap;
1393
1394 if (winPtr->window != None) {
1395 XSetWindowBackgroundPixmap(winPtr->display,
1396 winPtr->window, pixmap);
1397 } else {
1398 winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBackPixel)
1399 | CWBackPixmap;
1400 }
1401 }
1402
1403 void
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. */
1408 {
1409 register TkWindow *winPtr = (TkWindow *) tkwin;
1410
1411 winPtr->atts.border_pixel = pixel;
1412
1413 if (winPtr->window != None) {
1414 XSetWindowBorder(winPtr->display, winPtr->window, pixel);
1415 } else {
1416 winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBorderPixmap)
1417 | CWBorderPixel;
1418 }
1419 }
1420
1421 void
1422 Tk_SetWindowBorderPixmap(tkwin, pixmap)
1423 Tk_Window tkwin; /* Window to manipulate. */
1424 Pixmap pixmap; /* Pixmap to use for window's
1425 * border. */
1426 {
1427 register TkWindow *winPtr = (TkWindow *) tkwin;
1428
1429 winPtr->atts.border_pixmap = pixmap;
1430
1431 if (winPtr->window != None) {
1432 XSetWindowBorderPixmap(winPtr->display,
1433 winPtr->window, pixmap);
1434 } else {
1435 winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBorderPixel)
1436 | CWBorderPixmap;
1437 }
1438 }
1439
1440 void
1441 Tk_DefineCursor(tkwin, cursor)
1442 Tk_Window tkwin; /* Window to manipulate. */
1443 Cursor cursor; /* Cursor to use for window (may be None). */
1444 {
1445 register TkWindow *winPtr = (TkWindow *) tkwin;
1446
1447 winPtr->atts.cursor = cursor;
1448
1449 if (winPtr->window != None) {
1450 XDefineCursor(winPtr->display, winPtr->window, cursor);
1451 } else {
1452 winPtr->dirtyAtts = winPtr->dirtyAtts | CWCursor;
1453 }
1454 }
1455
1456 void
1457 Tk_UndefineCursor(tkwin)
1458 Tk_Window tkwin; /* Window to manipulate. */
1459 {
1460 Tk_DefineCursor(tkwin, None);
1461 }
1462 \f
1463 /*
1464 *----------------------------------------------------------------------
1465 *
1466 * DoConfigureNotify --
1467 *
1468 * Generate a ConfigureNotify event describing the current
1469 * configuration of a window.
1470 *
1471 * Results:
1472 * None.
1473 *
1474 * Side effects:
1475 * An event is generated and processed by Tk_HandleEvent.
1476 *
1477 *----------------------------------------------------------------------
1478 */
1479
1480 static void
1481 DoConfigureNotify(winPtr)
1482 register TkWindow *winPtr; /* Window whose configuration
1483 * was just changed. */
1484 {
1485 XEvent event;
1486
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;
1500 } else {
1501 event.xconfigure.above = None;
1502 }
1503 event.xconfigure.override_redirect = winPtr->atts.override_redirect;
1504 Tk_HandleEvent(&event);
1505 }
1506 \f
1507 /*
1508 *----------------------------------------------------------------------
1509 *
1510 * Tk_SetClass --
1511 *
1512 * This procedure is used to give a window a class.
1513 *
1514 * Results:
1515 * None.
1516 *
1517 * Side effects:
1518 * A new class is stored for tkwin, replacing any existing
1519 * class for it.
1520 *
1521 *----------------------------------------------------------------------
1522 */
1523
1524 void
1525 Tk_SetClass(tkwin, className)
1526 Tk_Window tkwin; /* Token for window to assign class. */
1527 char *className; /* New class for tkwin. */
1528 {
1529 register TkWindow *winPtr = (TkWindow *) tkwin;
1530
1531 winPtr->classUid = Tk_GetUid(className);
1532 if (winPtr->flags & TK_TOP_LEVEL) {
1533 TkWmSetClass(winPtr);
1534 }
1535 }
1536 \f
1537 /*
1538 *----------------------------------------------------------------------
1539 *
1540 * Tk_NameToWindow --
1541 *
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.
1545 *
1546 * Results:
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.
1550 *
1551 * Side effects:
1552 * None.
1553 *
1554 *----------------------------------------------------------------------
1555 */
1556
1557 Tk_Window
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. */
1563 {
1564 Tcl_HashEntry *hPtr;
1565
1566 hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->nameTable,
1567 pathName);
1568 if (hPtr == NULL) {
1569 Tcl_AppendResult(interp, "bad window path name \"",
1570 pathName, "\"", (char *) NULL);
1571 return NULL;
1572 }
1573 return (Tk_Window) Tcl_GetHashValue(hPtr);
1574 }
1575 \f
1576 /*
1577 *----------------------------------------------------------------------
1578 *
1579 * Tk_DisplayName --
1580 *
1581 * Return the textual name of a window's display.
1582 *
1583 * Results:
1584 * The return value is the string name of the display associated
1585 * with tkwin.
1586 *
1587 * Side effects:
1588 * None.
1589 *
1590 *----------------------------------------------------------------------
1591 */
1592
1593 char *
1594 Tk_DisplayName(tkwin)
1595 Tk_Window tkwin; /* Window whose display name is desired. */
1596 {
1597 return ((TkWindow *) tkwin)->dispPtr->name;
1598 }
Impressum, Datenschutz