Annotation of micropolis/src/tk/tkframe.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * tkFrame.c --
                      3:  *
                      4:  *     This module implements "frame" widgets for the Tk
                      5:  *     toolkit.  Frames are windows with a background color
                      6:  *     and possibly a 3-D effect, but no other attributes.
                      7:  *
                      8:  * Copyright 1990 Regents of the University of California.
                      9:  * Permission to use, copy, modify, and distribute this
                     10:  * software and its documentation for any purpose and without
                     11:  * fee is hereby granted, provided that the above copyright
                     12:  * notice appear in all copies.  The University of California
                     13:  * makes no representations about the suitability of this
                     14:  * software for any purpose.  It is provided "as is" without
                     15:  * express or implied warranty.
                     16:  */
                     17: 
                     18: #ifndef lint
                     19: static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkFrame.c,v 1.27 92/08/21 16:17:24 ouster Exp $ SPRITE (Berkeley)";
                     20: #endif
                     21: 
                     22: #include "default.h"
                     23: #include "tkconfig.h"
                     24: #include "tk.h"
                     25: 
                     26: /*
                     27:  * A data structure of the following type is kept for each
                     28:  * frame that currently exists for this process:
                     29:  */
                     30: 
                     31: typedef struct {
                     32:     Tk_Window tkwin;           /* Window that embodies the frame.  NULL
                     33:                                 * means that the window has been destroyed
                     34:                                 * but the data structures haven't yet been
                     35:                                 * cleaned up.*/
                     36:     Tcl_Interp *interp;                /* Interpreter associated with
                     37:                                 * widget.  Used to delete widget
                     38:                                 * command.  */
                     39:     Tk_Uid screenName;         /* If this window isn't a toplevel window
                     40:                                 * then this is NULL;  otherwise it gives
                     41:                                 * the name of the screen on which window
                     42:                                 * is displayed. */
                     43:     Tk_3DBorder border;                /* Structure used to draw 3-D border and
                     44:                                 * background. */
                     45:     int borderWidth;           /* Width of 3-D border (if any). */
                     46:     int relief;                        /* 3-d effect: TK_RELIEF_RAISED etc. */
                     47:     int width;                 /* Width to request for window.  <= 0 means
                     48:                                 * don't request any size. */
                     49:     int height;                        /* Height to request for window.  <= 0 means
                     50:                                 * don't request any size. */
                     51:     char *geometry;            /* Geometry that user requested.  NULL
                     52:                                 * means use width and height instead. 
                     53:                                 * Malloc'ed. */
                     54:     Cursor cursor;             /* Current cursor for window, or None. */
                     55:     int flags;                 /* Various flags;  see below for
                     56:                                 * definitions. */
                     57: } Frame;
                     58: 
                     59: /*
                     60:  * Flag bits for frames:
                     61:  *
                     62:  * REDRAW_PENDING:             Non-zero means a DoWhenIdle handler
                     63:  *                             has already been queued to redraw
                     64:  *                             this window.
                     65:  * CLEAR_NEEDED;               Need to clear the window when redrawing.
                     66:  */
                     67: 
                     68: #define REDRAW_PENDING         1
                     69: #define CLEAR_NEEDED           2
                     70: 
                     71: static Tk_ConfigSpec configSpecs[] = {
                     72:     {TK_CONFIG_BORDER, "-background", "background", "Background",
                     73:        DEF_FRAME_BG_COLOR, Tk_Offset(Frame, border), TK_CONFIG_COLOR_ONLY},
                     74:     {TK_CONFIG_BORDER, "-background", "background", "Background",
                     75:        DEF_FRAME_BG_MONO, Tk_Offset(Frame, border), TK_CONFIG_MONO_ONLY},
                     76:     {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
                     77:        (char *) NULL, 0, 0},
                     78:     {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
                     79:        (char *) NULL, 0, 0},
                     80:     {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
                     81:        DEF_FRAME_BORDER_WIDTH, Tk_Offset(Frame, borderWidth), 0},
                     82:     {TK_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
                     83:        DEF_FRAME_CURSOR, Tk_Offset(Frame, cursor), TK_CONFIG_NULL_OK},
                     84:     {TK_CONFIG_STRING, "-geometry", "geometry", "Geometry",
                     85:        DEF_FRAME_GEOMETRY, Tk_Offset(Frame, geometry), TK_CONFIG_NULL_OK},
                     86:     {TK_CONFIG_PIXELS, "-height", "height", "Height",
                     87:        DEF_FRAME_HEIGHT, Tk_Offset(Frame, height), 0},
                     88:     {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
                     89:        DEF_FRAME_RELIEF, Tk_Offset(Frame, relief), 0},
                     90:     {TK_CONFIG_PIXELS, "-width", "width", "Width",
                     91:        DEF_FRAME_WIDTH, Tk_Offset(Frame, width), 0},
                     92:     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
                     93:        (char *) NULL, 0, 0}
                     94: };
                     95: 
                     96: /*
                     97:  * Forward declarations for procedures defined later in this file:
                     98:  */
                     99: 
                    100: static int     ConfigureFrame _ANSI_ARGS_((Tcl_Interp *interp,
                    101:                    Frame *framePtr, int argc, char **argv, int flags));
                    102: static void    DestroyFrame _ANSI_ARGS_((ClientData clientData));
                    103: static void    DisplayFrame _ANSI_ARGS_((ClientData clientData));
                    104: static void    FrameEventProc _ANSI_ARGS_((ClientData clientData,
                    105:                    XEvent *eventPtr));
                    106: static int     FrameWidgetCmd _ANSI_ARGS_((ClientData clientData,
                    107:                    Tcl_Interp *interp, int argc, char **argv));
                    108: static void    MapFrame _ANSI_ARGS_((ClientData clientData));
                    109: 
                    110: /*
                    111:  *--------------------------------------------------------------
                    112:  *
                    113:  * Tk_FrameCmd --
                    114:  *
                    115:  *     This procedure is invoked to process the "frame" and
                    116:  *     "toplevel" Tcl commands.  See the user documentation for
                    117:  *     details on what it does.
                    118:  *
                    119:  * Results:
                    120:  *     A standard Tcl result.
                    121:  *
                    122:  * Side effects:
                    123:  *     See the user documentation.
                    124:  *
                    125:  *--------------------------------------------------------------
                    126:  */
                    127: 
                    128: int
                    129: Tk_FrameCmd(clientData, interp, argc, argv)
                    130:     ClientData clientData;     /* Main window associated with
                    131:                                 * interpreter. */
                    132:     Tcl_Interp *interp;                /* Current interpreter. */
                    133:     int argc;                  /* Number of arguments. */
                    134:     char **argv;               /* Argument strings. */
                    135: {
                    136:     Tk_Window tkwin = (Tk_Window) clientData;
                    137:     Tk_Window new;
                    138:     register Frame *framePtr;
                    139:     Tk_Uid screenUid;
                    140:     char *className, *screen;
                    141:     int src, dst;
                    142: 
                    143:     if (argc < 2) {
                    144:        Tcl_AppendResult(interp, "wrong # args: should be \"",
                    145:                argv[0], " pathName ?options?\"", (char *) NULL);
                    146:        return TCL_ERROR;
                    147:     }
                    148: 
                    149:     /*
                    150:      * The code below is a special workaround that extracts a few key
                    151:      * options from the argument list now, rather than letting
                    152:      * ConfigureFrame do it.  This is necessary because we have
                    153:      * to know the window's screen (if it's top-level) and its
                    154:      * class before creating the window.
                    155:      */
                    156: 
                    157:     screen = NULL;
                    158:     className = (argv[0][0] == 't') ? "Toplevel" : "Frame";
                    159:     for (src = 2, dst = 2; src < argc;  src += 2) {
                    160:        char c;
                    161: 
                    162:        c = argv[src][1];
                    163:        if ((c == 'c')
                    164:                && (strncmp(argv[src], "-class", strlen(argv[src])) == 0)) {
                    165:            className = argv[src+1];
                    166:        } else if ((argv[0][0] == 't') && (c == 's')
                    167:                && (strncmp(argv[src], "-screen", strlen(argv[src])) == 0)) {
                    168:            screen = argv[src+1];
                    169:        } else {
                    170:            argv[dst] = argv[src];
                    171:            argv[dst+1] = argv[src+1];
                    172:            dst += 2;
                    173:        }
                    174:     }
                    175:     argc -= src-dst;
                    176: 
                    177:     /*
                    178:      * Provide a default screen for top-level windows (same as screen
                    179:      * of parent window).
                    180:      */
                    181: 
                    182:     if ((argv[0][0] == 't') && (screen == NULL)) {
                    183:        screen = "";
                    184:     }
                    185:     if (screen != NULL) {
                    186:        screenUid = Tk_GetUid(screen);
                    187:     } else {
                    188:        screenUid = NULL;
                    189:     }
                    190: 
                    191:     /*
                    192:      * Create the window.
                    193:      */
                    194: 
                    195:     new = Tk_CreateWindowFromPath(interp, tkwin, argv[1], screenUid);
                    196: 
                    197:     if (new == NULL) {
                    198:        return TCL_ERROR;
                    199:     }
                    200: 
                    201:     Tk_SetClass(new, className);
                    202:     framePtr = (Frame *) ckalloc(sizeof(Frame));
                    203:     framePtr->tkwin = new;
                    204:     framePtr->interp = interp;
                    205:     framePtr->screenName = screenUid;
                    206:     framePtr->border = NULL;
                    207:     framePtr->geometry = NULL;
                    208:     framePtr->cursor = None;
                    209:     framePtr->flags = 0;
                    210:     Tk_CreateEventHandler(framePtr->tkwin, ExposureMask|StructureNotifyMask,
                    211:            FrameEventProc, (ClientData) framePtr);
                    212:     Tcl_CreateCommand(interp, Tk_PathName(framePtr->tkwin),
                    213:            FrameWidgetCmd, (ClientData) framePtr, (void (*)()) NULL);
                    214: 
                    215:     if (ConfigureFrame(interp, framePtr, argc-2, argv+2, 0) != TCL_OK) {
                    216:        Tk_DestroyWindow(framePtr->tkwin);
                    217:        return TCL_ERROR;
                    218:     }
                    219:     if (screenUid != NULL) {
                    220:        Tk_DoWhenIdle(MapFrame, (ClientData) framePtr);
                    221:     }
                    222:     interp->result = Tk_PathName(framePtr->tkwin);
                    223:     return TCL_OK;
                    224: }
                    225: 
                    226: /*
                    227:  *--------------------------------------------------------------
                    228:  *
                    229:  * FrameWidgetCmd --
                    230:  *
                    231:  *     This procedure is invoked to process the Tcl command
                    232:  *     that corresponds to a frame widget.  See the user
                    233:  *     documentation for details on what it does.
                    234:  *
                    235:  * Results:
                    236:  *     A standard Tcl result.
                    237:  *
                    238:  * Side effects:
                    239:  *     See the user documentation.
                    240:  *
                    241:  *--------------------------------------------------------------
                    242:  */
                    243: 
                    244: static int
                    245: FrameWidgetCmd(clientData, interp, argc, argv)
                    246:     ClientData clientData;     /* Information about frame widget. */
                    247:     Tcl_Interp *interp;                /* Current interpreter. */
                    248:     int argc;                  /* Number of arguments. */
                    249:     char **argv;               /* Argument strings. */
                    250: {
                    251:     register Frame *framePtr = (Frame *) clientData;
                    252:     int result = TCL_OK;
                    253:     int length;
                    254:     char c;
                    255: 
                    256:     if (argc < 2) {
                    257:        Tcl_AppendResult(interp, "wrong # args: should be \"",
                    258:                argv[0], " option ?arg arg ...?\"", (char *) NULL);
                    259:        return TCL_ERROR;
                    260:     }
                    261:     Tk_Preserve((ClientData) framePtr);
                    262:     c = argv[1][0];
                    263:     length = strlen(argv[1]);
                    264:     if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)) {
                    265:        if (argc == 2) {
                    266:            result = Tk_ConfigureInfo(interp, framePtr->tkwin, configSpecs,
                    267:                    (char *) framePtr, (char *) NULL, 0);
                    268:        } else if (argc == 3) {
                    269:            result = Tk_ConfigureInfo(interp, framePtr->tkwin, configSpecs,
                    270:                    (char *) framePtr, argv[2], 0);
                    271:        } else {
                    272:            result = ConfigureFrame(interp, framePtr, argc-2, argv+2,
                    273:                    TK_CONFIG_ARGV_ONLY);
                    274:        }
                    275:     } else {
                    276:        Tcl_AppendResult(interp, "bad option \"", argv[1],
                    277:                "\":  must be configure", (char *) NULL);
                    278:        result = TCL_ERROR;
                    279:     }
                    280:     Tk_Release((ClientData) framePtr);
                    281:     return result;
                    282: }
                    283: 
                    284: /*
                    285:  *----------------------------------------------------------------------
                    286:  *
                    287:  * DestroyFrame --
                    288:  *
                    289:  *     This procedure is invoked by Tk_EventuallyFree or Tk_Release
                    290:  *     to clean up the internal structure of a frame at a safe time
                    291:  *     (when no-one is using it anymore).
                    292:  *
                    293:  * Results:
                    294:  *     None.
                    295:  *
                    296:  * Side effects:
                    297:  *     Everything associated with the frame is freed up.
                    298:  *
                    299:  *----------------------------------------------------------------------
                    300:  */
                    301: 
                    302: static void
                    303: DestroyFrame(clientData)
                    304:     ClientData clientData;     /* Info about frame widget. */
                    305: {
                    306:     register Frame *framePtr = (Frame *) clientData;
                    307: 
                    308:     if (framePtr->border != NULL) {
                    309:        Tk_Free3DBorder(framePtr->border);
                    310:     }
                    311:     if (framePtr->geometry != NULL) {
                    312:        ckfree(framePtr->geometry);
                    313:     }
                    314:     if (framePtr->cursor != None) {
                    315:        Tk_FreeCursor(framePtr->cursor);
                    316:     }
                    317:     ckfree((char *) framePtr);
                    318: }
                    319: 
                    320: /*
                    321:  *----------------------------------------------------------------------
                    322:  *
                    323:  * ConfigureFrame --
                    324:  *
                    325:  *     This procedure is called to process an argv/argc list, plus
                    326:  *     the Tk option database, in order to configure (or
                    327:  *     reconfigure) a frame widget.
                    328:  *
                    329:  * Results:
                    330:  *     The return value is a standard Tcl result.  If TCL_ERROR is
                    331:  *     returned, then interp->result contains an error message.
                    332:  *
                    333:  * Side effects:
                    334:  *     Configuration information, such as text string, colors, font,
                    335:  *     etc. get set for framePtr;  old resources get freed, if there
                    336:  *     were any.
                    337:  *
                    338:  *----------------------------------------------------------------------
                    339:  */
                    340: 
                    341: static int
                    342: ConfigureFrame(interp, framePtr, argc, argv, flags)
                    343:     Tcl_Interp *interp;                /* Used for error reporting. */
                    344:     register Frame *framePtr;  /* Information about widget;  may or may
                    345:                                 * not already have values for some fields. */
                    346:     int argc;                  /* Number of valid entries in argv. */
                    347:     char **argv;               /* Arguments. */
                    348:     int flags;                 /* Flags to pass to Tk_ConfigureWidget. */
                    349: {
                    350:     if (Tk_ConfigureWidget(interp, framePtr->tkwin, configSpecs,
                    351:            argc, argv, (char *) framePtr, flags) != TCL_OK) {
                    352:        return TCL_ERROR;
                    353:     }
                    354: 
                    355:     Tk_SetBackgroundFromBorder(framePtr->tkwin, framePtr->border);
                    356:     Tk_SetInternalBorder(framePtr->tkwin, framePtr->borderWidth);
                    357:     if (framePtr->geometry != NULL) {
                    358:        int height, width;
                    359:        if (sscanf(framePtr->geometry, "%dx%d", &width, &height) != 2) {
                    360:            Tcl_AppendResult(interp, "bad geometry \"", framePtr->geometry,
                    361:                    "\": expected widthxheight", (char *) NULL);
                    362:            return TCL_ERROR;
                    363:        }
                    364:        Tk_GeometryRequest(framePtr->tkwin, width, height);
                    365:     } else if ((framePtr->width > 0) && (framePtr->height > 0)) {
                    366:        Tk_GeometryRequest(framePtr->tkwin, framePtr->width,
                    367:                framePtr->height);
                    368:     }
                    369: 
                    370:     if (Tk_IsMapped(framePtr->tkwin)
                    371:            && !(framePtr->flags & REDRAW_PENDING)) {
                    372:        Tk_DoWhenIdle(DisplayFrame, (ClientData) framePtr);
                    373:        framePtr->flags |= REDRAW_PENDING|CLEAR_NEEDED;
                    374:     }
                    375:     return TCL_OK;
                    376: }
                    377: 
                    378: /*
                    379:  *----------------------------------------------------------------------
                    380:  *
                    381:  * DisplayFrame --
                    382:  *
                    383:  *     This procedure is invoked to display a frame widget.
                    384:  *
                    385:  * Results:
                    386:  *     None.
                    387:  *
                    388:  * Side effects:
                    389:  *     Commands are output to X to display the frame in its
                    390:  *     current mode.
                    391:  *
                    392:  *----------------------------------------------------------------------
                    393:  */
                    394: 
                    395: static void
                    396: DisplayFrame(clientData)
                    397:     ClientData clientData;     /* Information about widget. */
                    398: {
                    399:     register Frame *framePtr = (Frame *) clientData;
                    400:     register Tk_Window tkwin = framePtr->tkwin;
                    401: 
                    402:     framePtr->flags &= ~REDRAW_PENDING;
                    403:     if ((framePtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) {
                    404:        return;
                    405:     }
                    406: 
                    407:     if (framePtr->flags & CLEAR_NEEDED) {
                    408:        XClearWindow(Tk_Display(tkwin), Tk_WindowId(tkwin));
                    409:        framePtr->flags &= ~CLEAR_NEEDED;
                    410:     }
                    411:     if ((framePtr->border != NULL)
                    412:            && (framePtr->relief != TK_RELIEF_FLAT)) {
                    413:        Tk_Draw3DRectangle(Tk_Display(tkwin), Tk_WindowId(tkwin),
                    414:                framePtr->border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin),
                    415:                framePtr->borderWidth, framePtr->relief);
                    416:     }
                    417: }
                    418: 
                    419: /*
                    420:  *--------------------------------------------------------------
                    421:  *
                    422:  * FrameEventProc --
                    423:  *
                    424:  *     This procedure is invoked by the Tk dispatcher on
                    425:  *     structure changes to a frame.  For frames with 3D
                    426:  *     borders, this procedure is also invoked for exposures.
                    427:  *
                    428:  * Results:
                    429:  *     None.
                    430:  *
                    431:  * Side effects:
                    432:  *     When the window gets deleted, internal structures get
                    433:  *     cleaned up.  When it gets exposed, it is redisplayed.
                    434:  *
                    435:  *--------------------------------------------------------------
                    436:  */
                    437: 
                    438: static void
                    439: FrameEventProc(clientData, eventPtr)
                    440:     ClientData clientData;     /* Information about window. */
                    441:     register XEvent *eventPtr; /* Information about event. */
                    442: {
                    443:     register Frame *framePtr = (Frame *) clientData;
                    444: 
                    445:     if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
                    446:        if ((framePtr->relief != TK_RELIEF_FLAT) && (framePtr->tkwin != NULL)
                    447:                && !(framePtr->flags & REDRAW_PENDING)) {
                    448:            Tk_DoWhenIdle(DisplayFrame, (ClientData) framePtr);
                    449:            framePtr->flags |= REDRAW_PENDING;
                    450:        }
                    451:     } else if (eventPtr->type == DestroyNotify) {
                    452:        Tcl_DeleteCommand(framePtr->interp, Tk_PathName(framePtr->tkwin));
                    453:        framePtr->tkwin = NULL;
                    454:        if (framePtr->flags & REDRAW_PENDING) {
                    455:            Tk_CancelIdleCall(DisplayFrame, (ClientData) framePtr);
                    456:        }
                    457:        Tk_CancelIdleCall(MapFrame, (ClientData) framePtr);
                    458:        Tk_EventuallyFree((ClientData) framePtr, DestroyFrame);
                    459:     }
                    460: }
                    461: 
                    462: /*
                    463:  *----------------------------------------------------------------------
                    464:  *
                    465:  * MapFrame --
                    466:  *
                    467:  *     This procedure is invoked as a when-idle handler to map a
                    468:  *     newly-created top-level frame.
                    469:  *
                    470:  * Results:
                    471:  *     None.
                    472:  *
                    473:  * Side effects:
                    474:  *     The frame given by the clientData argument is mapped.
                    475:  *
                    476:  *----------------------------------------------------------------------
                    477:  */
                    478: 
                    479: static void
                    480: MapFrame(clientData)
                    481:     ClientData clientData;             /* Pointer to frame structure. */
                    482: {
                    483:     Frame *framePtr = (Frame *) clientData;
                    484: 
                    485:     /*
                    486:      * Wait for all other background events to be processed before
                    487:      * mapping window.  This ensures that the window's correct geometry
                    488:      * will have been determined before it is first mapped, so that the
                    489:      * window manager doesn't get a false idea of its desired geometry.
                    490:      */
                    491: 
                    492:     do {
                    493:        if (Tk_DoOneEvent(TK_IDLE_EVENTS) == 0) {
                    494:            break;
                    495:        }
                    496: 
                    497:        /*
                    498:         * After each event, make sure that the window still exists,
                    499:         * and quit if the window has been destroyed.
                    500:         */
                    501: 
                    502:        if (framePtr->tkwin == NULL) {
                    503:            return;
                    504:        }
                    505:     } while (1);
                    506:     Tk_MapWindow(framePtr->tkwin);
                    507: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.