OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [generic/] [tkFrame.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.