/[dtapublic]/projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkframe.c
ViewVC logotype

Contents of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkframe.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 69 - (show annotations) (download)
Sat Nov 5 10:54:17 2016 UTC (6 years, 2 months ago) by dashley
File MIME type: text/plain
File size: 32486 byte(s)
License and property (keyword) changes.
1 /* $Header$ */
2
3 /*
4 * tkFrame.c --
5 *
6 * This module implements "frame" and "toplevel" widgets for
7 * the Tk toolkit. Frames are windows with a background color
8 * and possibly a 3-D effect, but not much else in the way of
9 * attributes.
10 *
11 * Copyright (c) 1990-1994 The Regents of the University of California.
12 * Copyright (c) 1994-1997 Sun Microsystems, Inc.
13 *
14 * See the file "license.terms" for information on usage and redistribution
15 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16 *
17 * RCS: @(#) $Id: tkframe.c,v 1.1.1.1 2001/06/13 05:01:10 dtashley Exp $
18 */
19
20 #include "default.h"
21 #include "tkPort.h"
22 #include "tkInt.h"
23
24 /*
25 * A data structure of the following type is kept for each
26 * frame that currently exists for this process:
27 */
28
29 typedef struct {
30 Tk_Window tkwin; /* Window that embodies the frame. NULL
31 * means that the window has been destroyed
32 * but the data structures haven't yet been
33 * cleaned up. */
34 Display *display; /* Display containing widget. Used, among
35 * other things, so that resources can be
36 * freed even after tkwin has gone away. */
37 Tcl_Interp *interp; /* Interpreter associated with widget. Used
38 * to delete widget command. */
39 Tcl_Command widgetCmd; /* Token for frame's widget command. */
40 char *className; /* Class name for widget (from configuration
41 * option). Malloc-ed. */
42 int mask; /* Either FRAME or TOPLEVEL; used to select
43 * which configuration options are valid for
44 * widget. */
45 char *screenName; /* Screen on which widget is created. Non-null
46 * only for top-levels. Malloc-ed, may be
47 * NULL. */
48 char *visualName; /* Textual description of visual for window,
49 * from -visual option. Malloc-ed, may be
50 * NULL. */
51 char *colormapName; /* Textual description of colormap for window,
52 * from -colormap option. Malloc-ed, may be
53 * NULL. */
54 char *menuName; /* Textual description of menu to use for
55 * menubar. Malloc-ed, may be NULL. */
56 Colormap colormap; /* If not None, identifies a colormap
57 * allocated for this window, which must be
58 * freed when the window is deleted. */
59 Tk_3DBorder border; /* Structure used to draw 3-D border and
60 * background. NULL means no background
61 * or border. */
62 int borderWidth; /* Width of 3-D border (if any). */
63 int relief; /* 3-d effect: TK_RELIEF_RAISED etc. */
64 int highlightWidth; /* Width in pixels of highlight to draw
65 * around widget when it has the focus.
66 * 0 means don't draw a highlight. */
67 XColor *highlightBgColorPtr;
68 /* Color for drawing traversal highlight
69 * area when highlight is off. */
70 XColor *highlightColorPtr; /* Color for drawing traversal highlight. */
71 int width; /* Width to request for window. <= 0 means
72 * don't request any size. */
73 int height; /* Height to request for window. <= 0 means
74 * don't request any size. */
75 Tk_Cursor cursor; /* Current cursor for window, or None. */
76 char *takeFocus; /* Value of -takefocus option; not used in
77 * the C code, but used by keyboard traversal
78 * scripts. Malloc'ed, but may be NULL. */
79 int isContainer; /* 1 means this window is a container, 0 means
80 * that it isn't. */
81 char *useThis; /* If the window is embedded, this points to
82 * the name of the window in which it is
83 * embedded (malloc'ed). For non-embedded
84 * windows this is NULL. */
85 int flags; /* Various flags; see below for
86 * definitions. */
87 } Frame;
88
89 /*
90 * Flag bits for frames:
91 *
92 * REDRAW_PENDING: Non-zero means a DoWhenIdle handler
93 * has already been queued to redraw
94 * this window.
95 * GOT_FOCUS: Non-zero means this widget currently
96 * has the input focus.
97 */
98
99 #define REDRAW_PENDING 1
100 #define GOT_FOCUS 4
101
102 /*
103 * The following flag bits are used so that there can be separate
104 * defaults for some configuration options for frames and toplevels.
105 */
106
107 #define FRAME TK_CONFIG_USER_BIT
108 #define TOPLEVEL (TK_CONFIG_USER_BIT << 1)
109 #define BOTH (FRAME | TOPLEVEL)
110
111 static Tk_ConfigSpec configSpecs[] = {
112 {TK_CONFIG_BORDER, "-background", "background", "Background",
113 DEF_FRAME_BG_COLOR, Tk_Offset(Frame, border),
114 BOTH|TK_CONFIG_COLOR_ONLY|TK_CONFIG_NULL_OK},
115 {TK_CONFIG_BORDER, "-background", "background", "Background",
116 DEF_FRAME_BG_MONO, Tk_Offset(Frame, border),
117 BOTH|TK_CONFIG_MONO_ONLY|TK_CONFIG_NULL_OK},
118 {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
119 (char *) NULL, 0, BOTH},
120 {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
121 (char *) NULL, 0, BOTH},
122 {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
123 DEF_FRAME_BORDER_WIDTH, Tk_Offset(Frame, borderWidth), BOTH},
124 {TK_CONFIG_STRING, "-class", "class", "Class",
125 DEF_FRAME_CLASS, Tk_Offset(Frame, className), FRAME},
126 {TK_CONFIG_STRING, "-class", "class", "Class",
127 DEF_TOPLEVEL_CLASS, Tk_Offset(Frame, className), TOPLEVEL},
128 {TK_CONFIG_STRING, "-colormap", "colormap", "Colormap",
129 DEF_FRAME_COLORMAP, Tk_Offset(Frame, colormapName),
130 BOTH|TK_CONFIG_NULL_OK},
131 {TK_CONFIG_BOOLEAN, "-container", "container", "Container",
132 DEF_FRAME_CONTAINER, Tk_Offset(Frame, isContainer), BOTH},
133 {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
134 DEF_FRAME_CURSOR, Tk_Offset(Frame, cursor), BOTH|TK_CONFIG_NULL_OK},
135 {TK_CONFIG_PIXELS, "-height", "height", "Height",
136 DEF_FRAME_HEIGHT, Tk_Offset(Frame, height), BOTH},
137 {TK_CONFIG_COLOR, "-highlightbackground", "highlightBackground",
138 "HighlightBackground", DEF_FRAME_HIGHLIGHT_BG,
139 Tk_Offset(Frame, highlightBgColorPtr), BOTH},
140 {TK_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
141 DEF_FRAME_HIGHLIGHT, Tk_Offset(Frame, highlightColorPtr), BOTH},
142 {TK_CONFIG_PIXELS, "-highlightthickness", "highlightThickness",
143 "HighlightThickness",
144 DEF_FRAME_HIGHLIGHT_WIDTH, Tk_Offset(Frame, highlightWidth), BOTH},
145 {TK_CONFIG_STRING, "-menu", "menu", "Menu",
146 DEF_TOPLEVEL_MENU, Tk_Offset(Frame, menuName),
147 TOPLEVEL|TK_CONFIG_NULL_OK},
148 {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
149 DEF_FRAME_RELIEF, Tk_Offset(Frame, relief), BOTH},
150 {TK_CONFIG_STRING, "-screen", "screen", "Screen",
151 DEF_TOPLEVEL_SCREEN, Tk_Offset(Frame, screenName),
152 TOPLEVEL|TK_CONFIG_NULL_OK},
153 {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
154 DEF_FRAME_TAKE_FOCUS, Tk_Offset(Frame, takeFocus),
155 BOTH|TK_CONFIG_NULL_OK},
156 {TK_CONFIG_STRING, "-use", "use", "Use",
157 DEF_FRAME_USE, Tk_Offset(Frame, useThis), TOPLEVEL|TK_CONFIG_NULL_OK},
158 {TK_CONFIG_STRING, "-visual", "visual", "Visual",
159 DEF_FRAME_VISUAL, Tk_Offset(Frame, visualName),
160 BOTH|TK_CONFIG_NULL_OK},
161 {TK_CONFIG_PIXELS, "-width", "width", "Width",
162 DEF_FRAME_WIDTH, Tk_Offset(Frame, width), BOTH},
163 {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
164 (char *) NULL, 0, 0}
165 };
166
167 /*
168 * Forward declarations for procedures defined later in this file:
169 */
170
171 static int ConfigureFrame _ANSI_ARGS_((Tcl_Interp *interp,
172 Frame *framePtr, int objc, Tcl_Obj *CONST objv[],
173 int flags));
174 static int CreateFrame _ANSI_ARGS_((ClientData clientData,
175 Tcl_Interp *interp, int objc, Tcl_Obj *CONST argv[],
176 int toplevel, char *appName));
177 static void DestroyFrame _ANSI_ARGS_((char *memPtr));
178 static void DisplayFrame _ANSI_ARGS_((ClientData clientData));
179 static void FrameCmdDeletedProc _ANSI_ARGS_((
180 ClientData clientData));
181 static void FrameEventProc _ANSI_ARGS_((ClientData clientData,
182 XEvent *eventPtr));
183 static int FrameWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
184 Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
185 static void MapFrame _ANSI_ARGS_((ClientData clientData));
186
187 /*
188 *--------------------------------------------------------------
189 *
190 * Tk_FrameObjCmd, Tk_ToplevelObjCmd --
191 *
192 * These procedures are invoked to process the "frame" and
193 * "toplevel" Tcl commands. See the user documentation for
194 * details on what they do.
195 *
196 * Results:
197 * A standard Tcl result.
198 *
199 * Side effects:
200 * See the user documentation. These procedures are just wrappers;
201 * they call ButtonCreate to do all of the real work.
202 *
203 *--------------------------------------------------------------
204 */
205
206 int
207 Tk_FrameObjCmd(clientData, interp, objc, objv)
208 ClientData clientData; /* Main window associated with
209 * interpreter. */
210 Tcl_Interp *interp; /* Current interpreter. */
211 int objc; /* Number of arguments. */
212 Tcl_Obj *CONST objv[]; /* Argument objects. */
213 {
214 return CreateFrame(clientData, interp, objc, objv, 0, (char *) NULL);
215 }
216
217 int
218 Tk_ToplevelObjCmd(clientData, interp, objc, objv)
219 ClientData clientData; /* Main window associated with
220 * interpreter. */
221 Tcl_Interp *interp; /* Current interpreter. */
222 int objc; /* Number of arguments. */
223 Tcl_Obj *CONST objv[]; /* Argument objects. */
224 {
225 return CreateFrame(clientData, interp, objc, objv, 1, (char *) NULL);
226 }
227
228 /*
229 *--------------------------------------------------------------
230 *
231 * TkCreateFrame --
232 *
233 * This procedure is invoked to process the "frame" and "toplevel"
234 * Tcl commands; it is also invoked directly by Tk_Init to create
235 * a new main window. See the user documentation for the "frame"
236 * and "toplevel" commands for details on what it does.
237 *
238 * Results:
239 * A standard Tcl result.
240 *
241 * Side effects:
242 * See the user documentation.
243 *
244 *--------------------------------------------------------------
245 */
246
247 int
248 TkCreateFrame(clientData, interp, argc, argv, toplevel, appName)
249 ClientData clientData; /* Main window associated with interpreter.
250 * If we're called by Tk_Init to create a
251 * new application, then this is NULL. */
252 Tcl_Interp *interp; /* Current interpreter. */
253 int argc; /* Number of arguments. */
254 char **argv; /* Argument strings. */
255 int toplevel; /* Non-zero means create a toplevel window,
256 * zero means create a frame. */
257 char *appName; /* Should only be non-NULL if clientData is
258 * NULL: gives the base name to use for the
259 * new application. */
260 {
261 int result, i;
262 Tcl_Obj **objv = (Tcl_Obj **) ckalloc((argc+1) * sizeof(Tcl_Obj **));
263 for (i=0; i<argc; i++) {
264 objv[i] = Tcl_NewStringObj(argv[i], -1);
265 Tcl_IncrRefCount(objv[i]);
266 }
267 objv[argc] = NULL;
268 result = CreateFrame(clientData, interp, argc, objv, toplevel, appName);
269 for (i=0; i<argc; i++) {
270 Tcl_DecrRefCount(objv[i]);
271 }
272 ckfree((char *) objv);
273 return result;
274 }
275
276 static int
277 CreateFrame(clientData, interp, objc, objv, toplevel, appName)
278 ClientData clientData; /* Main window associated with interpreter.
279 * If we're called by Tk_Init to create a
280 * new application, then this is NULL. */
281 Tcl_Interp *interp; /* Current interpreter. */
282 int objc; /* Number of arguments. */
283 Tcl_Obj *CONST objv[]; /* Argument objects. */
284 int toplevel; /* Non-zero means create a toplevel window,
285 * zero means create a frame. */
286 char *appName; /* Should only be non-NULL if clientData is
287 * NULL: gives the base name to use for the
288 * new application. */
289 {
290 Tk_Window tkwin = (Tk_Window) clientData;
291 Frame *framePtr;
292 Tk_Window new;
293 char *className, *screenName, *visualName, *colormapName, *arg, *useOption;
294 int i, c, depth;
295 size_t length;
296 unsigned int mask;
297 Colormap colormap;
298 Visual *visual;
299
300 if (objc < 2) {
301 Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");
302 return TCL_ERROR;
303 }
304
305 /*
306 * Pre-process the argument list. Scan through it to find any
307 * "-class", "-screen", "-visual", and "-colormap" options. These
308 * arguments need to be processed specially, before the window
309 * is configured using the usual Tk mechanisms.
310 */
311
312 className = colormapName = screenName = visualName = useOption = NULL;
313 colormap = None;
314 for (i = 2; i < objc; i += 2) {
315 arg = Tcl_GetStringFromObj(objv[i], (int *) &length);
316 if (length < 2) {
317 continue;
318 }
319 c = arg[1];
320 if ((c == 'c') && (strncmp(arg, "-class", length) == 0)
321 && (length >= 3)) {
322 className = Tcl_GetString(objv[i+1]);
323 } else if ((c == 'c')
324 && (strncmp(arg, "-colormap", length) == 0)) {
325 colormapName = Tcl_GetString(objv[i+1]);
326 } else if ((c == 's') && toplevel
327 && (strncmp(arg, "-screen", length) == 0)) {
328 screenName = Tcl_GetString(objv[i+1]);
329 } else if ((c == 'u') && toplevel
330 && (strncmp(arg, "-use", length) == 0)) {
331 useOption = Tcl_GetString(objv[i+1]);
332 } else if ((c == 'v')
333 && (strncmp(arg, "-visual", length) == 0)) {
334 visualName = Tcl_GetString(objv[i+1]);
335 }
336 }
337
338 /*
339 * Create the window, and deal with the special options -use,
340 * -classname, -colormap, -screenname, and -visual. These options
341 * must be handle before calling ConfigureFrame below, and they must
342 * also be processed in a particular order, for the following
343 * reasons:
344 * 1. Must set the window's class before calling ConfigureFrame,
345 * so that unspecified options are looked up in the option
346 * database using the correct class.
347 * 2. Must set visual information before calling ConfigureFrame
348 * so that colors are allocated in a proper colormap.
349 * 3. Must call TkpUseWindow before setting non-default visual
350 * information, since TkpUseWindow changes the defaults.
351 */
352
353 if (screenName == NULL) {
354 screenName = (toplevel) ? "" : NULL;
355 }
356 if (tkwin != NULL) {
357 new = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]),
358 screenName);
359 } else {
360 /*
361 * We were called from Tk_Init; create a new application.
362 */
363
364 if (appName == NULL) {
365 panic("TkCreateFrame didn't get application name");
366 }
367 new = TkCreateMainWindow(interp, screenName, appName);
368 }
369 if (new == NULL) {
370 goto error;
371 }
372 if (className == NULL) {
373 className = Tk_GetOption(new, "class", "Class");
374 if (className == NULL) {
375 className = (toplevel) ? "Toplevel" : "Frame";
376 }
377 }
378 Tk_SetClass(new, className);
379 if (useOption == NULL) {
380 useOption = Tk_GetOption(new, "use", "Use");
381 }
382 if (useOption != NULL) {
383 if (TkpUseWindow(interp, new, useOption) != TCL_OK) {
384 goto error;
385 }
386 }
387 if (visualName == NULL) {
388 visualName = Tk_GetOption(new, "visual", "Visual");
389 }
390 if (colormapName == NULL) {
391 colormapName = Tk_GetOption(new, "colormap", "Colormap");
392 }
393 if (visualName != NULL) {
394 visual = Tk_GetVisual(interp, new, visualName, &depth,
395 (colormapName == NULL) ? &colormap : (Colormap *) NULL);
396 if (visual == NULL) {
397 goto error;
398 }
399 Tk_SetWindowVisual(new, visual, depth, colormap);
400 }
401 if (colormapName != NULL) {
402 colormap = Tk_GetColormap(interp, new, colormapName);
403 if (colormap == None) {
404 goto error;
405 }
406 Tk_SetWindowColormap(new, colormap);
407 }
408
409 /*
410 * For top-level windows, provide an initial geometry request of
411 * 200x200, just so the window looks nicer on the screen if it
412 * doesn't request a size for itself.
413 */
414
415 if (toplevel) {
416 Tk_GeometryRequest(new, 200, 200);
417 }
418
419 /*
420 * Create the widget record, process configuration options, and
421 * create event handlers. Then fill in a few additional fields
422 * in the widget record from the special options.
423 */
424
425 framePtr = (Frame *) ckalloc(sizeof(Frame));
426 framePtr->tkwin = new;
427 framePtr->display = Tk_Display(new);
428 framePtr->interp = interp;
429 framePtr->widgetCmd = Tcl_CreateObjCommand(interp,
430 Tk_PathName(new), FrameWidgetObjCmd,
431 (ClientData) framePtr, FrameCmdDeletedProc);
432 framePtr->className = NULL;
433 framePtr->mask = (toplevel) ? TOPLEVEL : FRAME;
434 framePtr->screenName = NULL;
435 framePtr->visualName = NULL;
436 framePtr->colormapName = NULL;
437 framePtr->colormap = colormap;
438 framePtr->border = NULL;
439 framePtr->borderWidth = 0;
440 framePtr->relief = TK_RELIEF_FLAT;
441 framePtr->highlightWidth = 0;
442 framePtr->highlightBgColorPtr = NULL;
443 framePtr->highlightColorPtr = NULL;
444 framePtr->width = 0;
445 framePtr->height = 0;
446 framePtr->cursor = None;
447 framePtr->takeFocus = NULL;
448 framePtr->isContainer = 0;
449 framePtr->useThis = NULL;
450 framePtr->flags = 0;
451 framePtr->menuName = NULL;
452
453 /*
454 * Store backreference to frame widget in window structure.
455 */
456 TkSetClassProcs(new, NULL, (ClientData) framePtr);
457
458 mask = ExposureMask | StructureNotifyMask | FocusChangeMask;
459 if (toplevel) {
460 mask |= ActivateMask;
461 }
462 Tk_CreateEventHandler(new, mask, FrameEventProc, (ClientData) framePtr);
463 if (ConfigureFrame(interp, framePtr, objc-2, objv+2, 0) != TCL_OK) {
464 goto error;
465 }
466 if ((framePtr->isContainer)) {
467 if (framePtr->useThis == NULL) {
468 TkpMakeContainer(framePtr->tkwin);
469 } else {
470 Tcl_AppendResult(interp,"A window cannot have both the -use ",
471 "and the -container option set.");
472 return TCL_ERROR;
473 }
474 }
475 if (toplevel) {
476 Tcl_DoWhenIdle(MapFrame, (ClientData) framePtr);
477 }
478 Tcl_SetResult(interp, Tk_PathName(new), TCL_STATIC);
479 return TCL_OK;
480
481 error:
482 if (new != NULL) {
483 Tk_DestroyWindow(new);
484 }
485 return TCL_ERROR;
486 }
487
488 /*
489 *--------------------------------------------------------------
490 *
491 * FrameWidgetObjCmd --
492 *
493 * This procedure is invoked to process the Tcl command
494 * that corresponds to a frame widget. See the user
495 * documentation for details on what it does.
496 *
497 * Results:
498 * A standard Tcl result.
499 *
500 * Side effects:
501 * See the user documentation.
502 *
503 *--------------------------------------------------------------
504 */
505
506 static int
507 FrameWidgetObjCmd(clientData, interp, objc, objv)
508 ClientData clientData; /* Information about frame widget. */
509 Tcl_Interp *interp; /* Current interpreter. */
510 int objc; /* Number of arguments. */
511 Tcl_Obj *CONST objv[]; /* Argument objects. */
512 {
513 static char *frameOptions[] = {
514 "cget", "configure", (char *) NULL
515 };
516 enum options {
517 FRAME_CGET, FRAME_CONFIGURE
518 };
519 register Frame *framePtr = (Frame *) clientData;
520 int result = TCL_OK, index;
521 size_t length;
522 int c, i;
523
524 if (objc < 2) {
525 Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");
526 return TCL_ERROR;
527 }
528 if (Tcl_GetIndexFromObj(interp, objv[1], frameOptions, "option", 0,
529 &index) != TCL_OK) {
530 return TCL_ERROR;
531 }
532 Tcl_Preserve((ClientData) framePtr);
533 switch ((enum options) index) {
534 case FRAME_CGET: {
535 if (objc != 3) {
536 Tcl_WrongNumArgs(interp, 2, objv, "option");
537 result = TCL_ERROR;
538 goto done;
539 }
540 result = Tk_ConfigureValue(interp, framePtr->tkwin, configSpecs,
541 (char *) framePtr, Tcl_GetString(objv[2]), framePtr->mask);
542 break;
543 }
544 case FRAME_CONFIGURE: {
545 if (objc == 2) {
546 result = Tk_ConfigureInfo(interp, framePtr->tkwin, configSpecs,
547 (char *) framePtr, (char *) NULL, framePtr->mask);
548 } else if (objc == 3) {
549 result = Tk_ConfigureInfo(interp, framePtr->tkwin, configSpecs,
550 (char *) framePtr, Tcl_GetString(objv[2]), framePtr->mask);
551 } else {
552 /*
553 * Don't allow the options -class, -colormap, -container,
554 * -newcmap, -screen, -use, or -visual to be changed.
555 */
556
557 for (i = 2; i < objc; i++) {
558 char *arg = Tcl_GetStringFromObj(objv[i], (int *) &length);
559 if (length < 2) {
560 continue;
561 }
562 c = arg[1];
563 if (((c == 'c') && (strncmp(arg, "-class", length) == 0)
564 && (length >= 2))
565 || ((c == 'c') && (framePtr->mask == TOPLEVEL)
566 && (strncmp(arg, "-colormap", length) == 0)
567 && (length >= 3))
568 || ((c == 'c')
569 && (strncmp(arg, "-container", length) == 0)
570 && (length >= 3))
571 || ((c == 's') && (framePtr->mask == TOPLEVEL)
572 && (strncmp(arg, "-screen", length) == 0))
573 || ((c == 'u') && (framePtr->mask == TOPLEVEL)
574 && (strncmp(arg, "-use", length) == 0))
575 || ((c == 'v') && (framePtr->mask == TOPLEVEL)
576 && (strncmp(arg, "-visual", length) == 0))) {
577 Tcl_AppendResult(interp, "can't modify ", arg,
578 " option after widget is created", (char *) NULL);
579 result = TCL_ERROR;
580 goto done;
581 }
582 }
583 result = ConfigureFrame(interp, framePtr, objc-2, objv+2,
584 TK_CONFIG_ARGV_ONLY);
585 }
586 break;
587 }
588 }
589
590 done:
591 Tcl_Release((ClientData) framePtr);
592 return result;
593 }
594
595 /*
596 *----------------------------------------------------------------------
597 *
598 * DestroyFrame --
599 *
600 * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release
601 * to clean up the internal structure of a frame at a safe time
602 * (when no-one is using it anymore).
603 *
604 * Results:
605 * None.
606 *
607 * Side effects:
608 * Everything associated with the frame is freed up.
609 *
610 *----------------------------------------------------------------------
611 */
612
613 static void
614 DestroyFrame(memPtr)
615 char *memPtr; /* Info about frame widget. */
616 {
617 register Frame *framePtr = (Frame *) memPtr;
618
619 Tk_FreeOptions(configSpecs, (char *) framePtr, framePtr->display,
620 framePtr->mask);
621 if (framePtr->colormap != None) {
622 Tk_FreeColormap(framePtr->display, framePtr->colormap);
623 }
624 ckfree((char *) framePtr);
625 }
626
627 /*
628 *----------------------------------------------------------------------
629 *
630 * ConfigureFrame --
631 *
632 * This procedure is called to process an objv/objc list, plus
633 * the Tk option database, in order to configure (or
634 * reconfigure) a frame widget.
635 *
636 * Results:
637 * The return value is a standard Tcl result. If TCL_ERROR is
638 * returned, then the interp's result contains an error message.
639 *
640 * Side effects:
641 * Configuration information, such as text string, colors, font,
642 * etc. get set for framePtr; old resources get freed, if there
643 * were any.
644 *
645 *----------------------------------------------------------------------
646 */
647
648 static int
649 ConfigureFrame(interp, framePtr, objc, objv, flags)
650 Tcl_Interp *interp; /* Used for error reporting. */
651 register Frame *framePtr; /* Information about widget; may or may
652 * not already have values for some fields. */
653 int objc; /* Number of valid entries in objv. */
654 Tcl_Obj *CONST objv[]; /* Arguments. */
655 int flags; /* Flags to pass to Tk_ConfigureWidget. */
656 {
657 char *oldMenuName;
658
659 /*
660 * Need the old menubar name for the menu code to delete it.
661 */
662
663 if (framePtr->menuName == NULL) {
664 oldMenuName = NULL;
665 } else {
666 oldMenuName = ckalloc(strlen(framePtr->menuName) + 1);
667 strcpy(oldMenuName, framePtr->menuName);
668 }
669
670 if (Tk_ConfigureWidget(interp, framePtr->tkwin, configSpecs,
671 objc, (char **) objv, (char *) framePtr,
672 flags | framePtr->mask | TK_CONFIG_OBJS) != TCL_OK) {
673 return TCL_ERROR;
674 }
675
676 if (((oldMenuName == NULL) && (framePtr->menuName != NULL))
677 || ((oldMenuName != NULL) && (framePtr->menuName == NULL))
678 || ((oldMenuName != NULL) && (framePtr->menuName != NULL)
679 && strcmp(oldMenuName, framePtr->menuName) != 0)) {
680 TkSetWindowMenuBar(interp, framePtr->tkwin, oldMenuName,
681 framePtr->menuName);
682 }
683
684 if (framePtr->border != NULL) {
685 Tk_SetBackgroundFromBorder(framePtr->tkwin, framePtr->border);
686 } else {
687 Tk_SetWindowBackgroundPixmap(framePtr->tkwin, None);
688 }
689
690 if (framePtr->highlightWidth < 0) {
691 framePtr->highlightWidth = 0;
692 }
693 Tk_SetInternalBorder(framePtr->tkwin,
694 framePtr->borderWidth + framePtr->highlightWidth);
695 if ((framePtr->width > 0) || (framePtr->height > 0)) {
696 Tk_GeometryRequest(framePtr->tkwin, framePtr->width,
697 framePtr->height);
698 }
699
700 if (oldMenuName != NULL) {
701 ckfree(oldMenuName);
702 }
703
704 if (Tk_IsMapped(framePtr->tkwin)) {
705 if (!(framePtr->flags & REDRAW_PENDING)) {
706 Tcl_DoWhenIdle(DisplayFrame, (ClientData) framePtr);
707 }
708 framePtr->flags |= REDRAW_PENDING;
709 }
710 return TCL_OK;
711 }
712
713 /*
714 *----------------------------------------------------------------------
715 *
716 * DisplayFrame --
717 *
718 * This procedure is invoked to display a frame widget.
719 *
720 * Results:
721 * None.
722 *
723 * Side effects:
724 * Commands are output to X to display the frame in its
725 * current mode.
726 *
727 *----------------------------------------------------------------------
728 */
729
730 static void
731 DisplayFrame(clientData)
732 ClientData clientData; /* Information about widget. */
733 {
734 register Frame *framePtr = (Frame *) clientData;
735 register Tk_Window tkwin = framePtr->tkwin;
736 void (* drawFunction) _ANSI_ARGS_((Tk_Window, Drawable, Tk_3DBorder,
737 int, int, int, int, int, int)) = Tk_Fill3DRectangle;
738
739 framePtr->flags &= ~REDRAW_PENDING;
740 if ((framePtr->tkwin == NULL) || !Tk_IsMapped(tkwin)
741 || framePtr->isContainer) {
742 return;
743 }
744
745 if (framePtr->border != NULL) {
746 drawFunction(tkwin, Tk_WindowId(tkwin),
747 framePtr->border, framePtr->highlightWidth,
748 framePtr->highlightWidth,
749 Tk_Width(tkwin) - 2*framePtr->highlightWidth,
750 Tk_Height(tkwin) - 2*framePtr->highlightWidth,
751 framePtr->borderWidth, framePtr->relief);
752 }
753 if (framePtr->highlightWidth != 0) {
754 GC fgGC, bgGC;
755
756 bgGC = Tk_GCForColor(framePtr->highlightBgColorPtr,
757 Tk_WindowId(tkwin));
758 if (framePtr->flags & GOT_FOCUS) {
759 fgGC = Tk_GCForColor(framePtr->highlightColorPtr,
760 Tk_WindowId(tkwin));
761 TkpDrawHighlightBorder(tkwin, fgGC, bgGC, framePtr->highlightWidth,
762 Tk_WindowId(tkwin));
763 } else {
764 TkpDrawHighlightBorder(tkwin, bgGC, bgGC, framePtr->highlightWidth,
765 Tk_WindowId(tkwin));
766 }
767 }
768 }
769
770 /*
771 *--------------------------------------------------------------
772 *
773 * FrameEventProc --
774 *
775 * This procedure is invoked by the Tk dispatcher on
776 * structure changes to a frame. For frames with 3D
777 * borders, this procedure is also invoked for exposures.
778 *
779 * Results:
780 * None.
781 *
782 * Side effects:
783 * When the window gets deleted, internal structures get
784 * cleaned up. When it gets exposed, it is redisplayed.
785 *
786 *--------------------------------------------------------------
787 */
788
789 static void
790 FrameEventProc(clientData, eventPtr)
791 ClientData clientData; /* Information about window. */
792 register XEvent *eventPtr; /* Information about event. */
793 {
794 register Frame *framePtr = (Frame *) clientData;
795
796 if (((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0))
797 || (eventPtr->type == ConfigureNotify)) {
798 goto redraw;
799 } else if (eventPtr->type == DestroyNotify) {
800 if (framePtr->menuName != NULL) {
801 TkSetWindowMenuBar(framePtr->interp, framePtr->tkwin,
802 framePtr->menuName, NULL);
803 ckfree(framePtr->menuName);
804 framePtr->menuName = NULL;
805 }
806 if (framePtr->tkwin != NULL) {
807
808 /*
809 * If this window is a container, then this event could be
810 * coming from the embedded application, in which case
811 * Tk_DestroyWindow hasn't been called yet. When Tk_DestroyWindow
812 * is called later, then another destroy event will be generated.
813 * We need to be sure we ignore the second event, since the frame
814 * could be gone by then. To do so, delete the event handler
815 * explicitly (normally it's done implicitly by Tk_DestroyWindow).
816 */
817
818 Tk_DeleteEventHandler(framePtr->tkwin,
819 ExposureMask|StructureNotifyMask|FocusChangeMask,
820 FrameEventProc, (ClientData) framePtr);
821 framePtr->tkwin = NULL;
822 Tcl_DeleteCommandFromToken(framePtr->interp, framePtr->widgetCmd);
823 }
824 if (framePtr->flags & REDRAW_PENDING) {
825 Tcl_CancelIdleCall(DisplayFrame, (ClientData) framePtr);
826 }
827 Tcl_CancelIdleCall(MapFrame, (ClientData) framePtr);
828 Tcl_EventuallyFree((ClientData) framePtr, DestroyFrame);
829 } else if (eventPtr->type == FocusIn) {
830 if (eventPtr->xfocus.detail != NotifyInferior) {
831 framePtr->flags |= GOT_FOCUS;
832 if (framePtr->highlightWidth > 0) {
833 goto redraw;
834 }
835 }
836 } else if (eventPtr->type == FocusOut) {
837 if (eventPtr->xfocus.detail != NotifyInferior) {
838 framePtr->flags &= ~GOT_FOCUS;
839 if (framePtr->highlightWidth > 0) {
840 goto redraw;
841 }
842 }
843 } else if (eventPtr->type == ActivateNotify) {
844 TkpSetMainMenubar(framePtr->interp, framePtr->tkwin,
845 framePtr->menuName);
846 }
847 return;
848
849 redraw:
850 if ((framePtr->tkwin != NULL) && !(framePtr->flags & REDRAW_PENDING)) {
851 Tcl_DoWhenIdle(DisplayFrame, (ClientData) framePtr);
852 framePtr->flags |= REDRAW_PENDING;
853 }
854 }
855
856 /*
857 *----------------------------------------------------------------------
858 *
859 * FrameCmdDeletedProc --
860 *
861 * This procedure is invoked when a widget command is deleted. If
862 * the widget isn't already in the process of being destroyed,
863 * this command destroys it.
864 *
865 * Results:
866 * None.
867 *
868 * Side effects:
869 * The widget is destroyed.
870 *
871 *----------------------------------------------------------------------
872 */
873
874 static void
875 FrameCmdDeletedProc(clientData)
876 ClientData clientData; /* Pointer to widget record for widget. */
877 {
878 Frame *framePtr = (Frame *) clientData;
879 Tk_Window tkwin = framePtr->tkwin;
880
881 if (framePtr->menuName != NULL) {
882 TkSetWindowMenuBar(framePtr->interp, framePtr->tkwin,
883 framePtr->menuName, NULL);
884 ckfree(framePtr->menuName);
885 framePtr->menuName = NULL;
886 }
887
888 /*
889 * This procedure could be invoked either because the window was
890 * destroyed and the command was then deleted (in which case tkwin
891 * is NULL) or because the command was deleted, and then this procedure
892 * destroys the widget.
893 */
894
895 if (tkwin != NULL) {
896 framePtr->tkwin = NULL;
897 Tk_DestroyWindow(tkwin);
898 }
899 }
900
901 /*
902 *----------------------------------------------------------------------
903 *
904 * MapFrame --
905 *
906 * This procedure is invoked as a when-idle handler to map a
907 * newly-created top-level frame.
908 *
909 * Results:
910 * None.
911 *
912 * Side effects:
913 * The frame given by the clientData argument is mapped.
914 *
915 *----------------------------------------------------------------------
916 */
917
918 static void
919 MapFrame(clientData)
920 ClientData clientData; /* Pointer to frame structure. */
921 {
922 Frame *framePtr = (Frame *) clientData;
923
924 /*
925 * Wait for all other background events to be processed before
926 * mapping window. This ensures that the window's correct geometry
927 * will have been determined before it is first mapped, so that the
928 * window manager doesn't get a false idea of its desired geometry.
929 */
930
931 Tcl_Preserve((ClientData) framePtr);
932 while (1) {
933 if (Tcl_DoOneEvent(TCL_IDLE_EVENTS) == 0) {
934 break;
935 }
936
937 /*
938 * After each event, make sure that the window still exists
939 * and quit if the window has been destroyed.
940 */
941
942 if (framePtr->tkwin == NULL) {
943 Tcl_Release((ClientData) framePtr);
944 return;
945 }
946 }
947 Tk_MapWindow(framePtr->tkwin);
948 Tcl_Release((ClientData) framePtr);
949 }
950
951 /*
952 *--------------------------------------------------------------
953 *
954 * TkInstallFrameMenu --
955 *
956 * This function is needed when a Windows HWND is created
957 * and a menubar has been set to the window with a system
958 * menu. It notifies the menu package so that the system
959 * menu can be rebuilt.
960 *
961 * Results:
962 * None.
963 *
964 * Side effects:
965 * The system menu (if any) is created for the menubar
966 * associated with this frame.
967 *
968 *--------------------------------------------------------------
969 */
970
971 void
972 TkInstallFrameMenu(tkwin)
973 Tk_Window tkwin; /* The window that was just created. */
974 {
975 TkWindow *winPtr = (TkWindow *) tkwin;
976
977 if (winPtr->mainPtr != NULL) {
978 Frame *framePtr;
979 framePtr = (Frame*) winPtr->instanceData;
980 if (framePtr == NULL) {
981 panic("TkInstallFrameMenu couldn't get frame pointer");
982 }
983 TkpMenuNotifyToplevelCreate(winPtr->mainPtr->interp,
984 framePtr->menuName);
985 }
986 }
987
988 /* End of tkframe.c */

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25