Annotation of micropolis/src/tk/library/demos/tkSquare.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * tkSquare.c --
                      3:  *
                      4:  *     This module implements "square" widgets.  A "square" is
                      5:  *     a widget that displays a single square that can be moved
                      6:  *     around and resized.  This file is intended as an example
                      7:  *     of how to build a widget.
                      8:  *
                      9:  * Copyright 1991-1992 Regents of the University of California.
                     10:  * Permission to use, copy, modify, and distribute this
                     11:  * software and its documentation for any purpose and without
                     12:  * fee is hereby granted, provided that the above copyright
                     13:  * notice appear in all copies.  The University of California
                     14:  * makes no representations about the suitability of this
                     15:  * software for any purpose.  It is provided "as is" without
                     16:  * express or implied warranty.
                     17:  */
                     18: 
                     19: #ifndef lint
                     20: static char rcsid[] = "$Header: /user6/ouster/wish/scripts/demos/RCS/tkSquare.c,v 1.2 92/04/29 11:45:17 ouster Exp $ SPRITE (Berkeley)";
                     21: #endif
                     22: 
                     23: #include "tkConfig.h"
                     24: #include "tk.h"
                     25: 
                     26: /*
                     27:  * A data structure of the following type is kept for each square
                     28:  * widget managed by this file:
                     29:  */
                     30: 
                     31: typedef struct {
                     32:     Tk_Window tkwin;           /* Window that embodies the square.  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 widget. */
                     37:     int x, y;                  /* Position of square's upper-left corner
                     38:                                 * within widget. */
                     39:     int size;                  /* Width and height of square. */
                     40:     int flags;                 /* Various flags;  see below for
                     41:                                 * definitions. */
                     42: 
                     43:     /*
                     44:      * Information used when displaying widget:
                     45:      */
                     46: 
                     47:     int borderWidth;           /* Width of 3-D border around whole widget. */
                     48:     Tk_3DBorder bgBorder;      /* Used for drawing background. */
                     49:     Tk_3DBorder fgBorder;      /* For drawing square. */
                     50:     int relief;                        /* Indicates whether window as a whole is
                     51:                                 * raised, sunken, or flat. */
                     52:     int doubleBuffer;          /* Non-zero means double-buffer redisplay
                     53:                                 * with pixmap;  zero means draw straight
                     54:                                 * onto the display. */
                     55: } Square;
                     56: 
                     57: /*
                     58:  * Flag bits for squares:
                     59:  *
                     60:  * REDRAW_PENDING -            1 means redraw has already been scheduled.
                     61:  */
                     62: 
                     63: #define REDRAW_PENDING         1
                     64: 
                     65: /*
                     66:  * Information used for argv parsing.
                     67:  */
                     68: 
                     69: static Tk_ConfigSpec configSpecs[] = {
                     70:     {TK_CONFIG_BORDER, "-background", "background", "Background",
                     71:        "#cdb79e", Tk_Offset(Square, bgBorder), TK_CONFIG_COLOR_ONLY},
                     72:     {TK_CONFIG_BORDER, "-background", "background", "Background",
                     73:        "white", Tk_Offset(Square, bgBorder), TK_CONFIG_MONO_ONLY},
                     74:     {TK_CONFIG_SYNONYM, "-bd", "borderWidth", (char *) NULL,
                     75:        (char *) NULL, 0, 0},
                     76:     {TK_CONFIG_SYNONYM, "-bg", "background", (char *) NULL,
                     77:        (char *) NULL, 0, 0},
                     78:     {TK_CONFIG_INT, "-borderwidth", "borderWidth", "BorderWidth",
                     79:        "2", Tk_Offset(Square, borderWidth), 0},
                     80:     {TK_CONFIG_INT, "-dbl", "doubleBuffer", "DoubleBuffer",
                     81:        "1", Tk_Offset(Square, doubleBuffer), 0},
                     82:     {TK_CONFIG_SYNONYM, "-fg", "foreground", (char *) NULL,
                     83:        (char *) NULL, 0, 0},
                     84:     {TK_CONFIG_BORDER, "-foreground", "foreground", "Foreground",
                     85:        "#b03060", Tk_Offset(Square, fgBorder), TK_CONFIG_COLOR_ONLY},
                     86:     {TK_CONFIG_BORDER, "-foreground", "foreground", "Foreground",
                     87:        "black", Tk_Offset(Square, fgBorder), TK_CONFIG_MONO_ONLY},
                     88:     {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
                     89:        "raised", Tk_Offset(Square, relief), 0},
                     90:     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
                     91:        (char *) NULL, 0, 0}
                     92: };
                     93: 
                     94: /*
                     95:  * Forward declarations for procedures defined later in this file:
                     96:  */
                     97: 
                     98: static int             ConfigureSquare _ANSI_ARGS_((Tcl_Interp *interp,
                     99:                            Square *squarePtr, int argc, char **argv,
                    100:                            int flags));
                    101: static void            DestroySquare _ANSI_ARGS_((ClientData clientData));
                    102: static void            DisplaySquare _ANSI_ARGS_((ClientData clientData));
                    103: static void            KeepInWindow _ANSI_ARGS_((Square *squarePtr));
                    104: static void            SquareEventProc _ANSI_ARGS_((ClientData clientData,
                    105:                            XEvent *eventPtr));
                    106: static int             SquareWidgetCmd _ANSI_ARGS_((ClientData clientData,
                    107:                            Tcl_Interp *, int argc, char **argv));
                    108: 
                    109: /*
                    110:  *--------------------------------------------------------------
                    111:  *
                    112:  * Tk_SquareCmd --
                    113:  *
                    114:  *     This procedure is invoked to process the "square" Tcl
                    115:  *     command.  It creates a new "square" widget.
                    116:  *
                    117:  * Results:
                    118:  *     A standard Tcl result.
                    119:  *
                    120:  * Side effects:
                    121:  *     A new widget is created and configured.
                    122:  *
                    123:  *--------------------------------------------------------------
                    124:  */
                    125: 
                    126: int
                    127: Tk_SquareCmd(clientData, interp, argc, argv)
                    128:     ClientData clientData;     /* Main window associated with
                    129:                                 * interpreter. */
                    130:     Tcl_Interp *interp;                /* Current interpreter. */
                    131:     int argc;                  /* Number of arguments. */
                    132:     char **argv;               /* Argument strings. */
                    133: {
                    134:     Tk_Window main = (Tk_Window) clientData;
                    135:     register Square *squarePtr;
                    136:     Tk_Window tkwin;
                    137: 
                    138:     if (argc < 2) {
                    139:        Tcl_AppendResult(interp, "wrong # args:  should be \"",
                    140:                argv[0], " pathName ?options?\"", (char *) NULL);
                    141:        return TCL_ERROR;
                    142:     }
                    143: 
                    144:     tkwin = Tk_CreateWindowFromPath(interp, main, argv[1], (char *) NULL);
                    145:     if (tkwin == NULL) {
                    146:        return TCL_ERROR;
                    147:     }
                    148: 
                    149:     /*
                    150:      * Initialize fields that won't be initialized by ConfigureSquare,
                    151:      * or which ConfigureSquare expects to have reasonable values
                    152:      * (e.g. resource pointers).
                    153:      */
                    154: 
                    155:     squarePtr = (Square *) ckalloc(sizeof(Square));
                    156:     squarePtr->tkwin = tkwin;
                    157:     squarePtr->interp = interp;
                    158:     squarePtr->x = 0;
                    159:     squarePtr->y = 0;
                    160:     squarePtr->size = 20;
                    161:     squarePtr->bgBorder = NULL;
                    162:     squarePtr->fgBorder = NULL;
                    163:     squarePtr->flags = 0;
                    164: 
                    165:     Tk_SetClass(squarePtr->tkwin, "Square");
                    166:     Tk_CreateEventHandler(squarePtr->tkwin, ExposureMask|StructureNotifyMask,
                    167:            SquareEventProc, (ClientData) squarePtr);
                    168:     Tcl_CreateCommand(interp, Tk_PathName(squarePtr->tkwin), SquareWidgetCmd,
                    169:            (ClientData) squarePtr, (void (*)()) NULL);
                    170:     if (ConfigureSquare(interp, squarePtr, argc-2, argv+2, 0) != TCL_OK) {
                    171:        Tk_DestroyWindow(squarePtr->tkwin);
                    172:        return TCL_ERROR;
                    173:     }
                    174: 
                    175:     interp->result = Tk_PathName(squarePtr->tkwin);
                    176:     return TCL_OK;
                    177: }
                    178: 
                    179: /*
                    180:  *----------------------------------------------------------------------
                    181:  *
                    182:  * ConfigureSquare --
                    183:  *
                    184:  *     This procedure is called to process an argv/argc list in
                    185:  *     conjunction with the Tk option database to configure (or
                    186:  *     reconfigure) a square widget.
                    187:  *
                    188:  * Results:
                    189:  *     The return value is a standard Tcl result.  If TCL_ERROR is
                    190:  *     returned, then interp->result contains an error message.
                    191:  *
                    192:  * Side effects:
                    193:  *     Configuration information, such as colors, border width,
                    194:  *     etc. get set for squarePtr;  old resources get freed,
                    195:  *     if there were any.
                    196:  *
                    197:  *----------------------------------------------------------------------
                    198:  */
                    199: 
                    200: static int
                    201: ConfigureSquare(interp, squarePtr, argc, argv, flags)
                    202:     Tcl_Interp *interp;                        /* Used for error reporting. */
                    203:     register Square *squarePtr;                /* Information about widget. */
                    204:     int argc;                          /* Number of valid entries in argv. */
                    205:     char **argv;                       /* Arguments. */
                    206:     int flags;                         /* Flags to pass to
                    207:                                         * Tk_ConfigureWidget. */
                    208: {
                    209:     if (Tk_ConfigureWidget(interp, squarePtr->tkwin, configSpecs,
                    210:            argc, argv, (char *) squarePtr, flags) != TCL_OK) {
                    211:        return TCL_ERROR;
                    212:     }
                    213: 
                    214:     /*
                    215:      * A few options need special processing, such as setting the
                    216:      * background from a 3-D border.
                    217:      */
                    218: 
                    219:     Tk_SetBackgroundFromBorder(squarePtr->tkwin, squarePtr->bgBorder);
                    220: 
                    221:     /*
                    222:      * Register the desired geometry for the window.  Then arrange for
                    223:      * the window to be redisplayed.
                    224:      */
                    225: 
                    226:     Tk_GeometryRequest(squarePtr->tkwin, 200, 150);
                    227:     Tk_SetInternalBorder(squarePtr->tkwin, squarePtr->borderWidth);
                    228:     if (!(squarePtr->flags & REDRAW_PENDING)) {
                    229:        Tk_DoWhenIdle(DisplaySquare, (ClientData) squarePtr);
                    230:        squarePtr->flags |= REDRAW_PENDING;
                    231:     }
                    232:     return TCL_OK;
                    233: }
                    234: 
                    235: /*
                    236:  *--------------------------------------------------------------
                    237:  *
                    238:  * DisplaySquare --
                    239:  *
                    240:  *     This procedure redraws the contents of a square window.
                    241:  *     It is invoked as a do-when-idle handler, so it only runs
                    242:  *     when there's nothing else for the application to do.
                    243:  *
                    244:  * Results:
                    245:  *     None.
                    246:  *
                    247:  * Side effects:
                    248:  *     Information appears on the screen.
                    249:  *
                    250:  *--------------------------------------------------------------
                    251:  */
                    252: 
                    253: static void
                    254: DisplaySquare(clientData)
                    255:     ClientData clientData;     /* Information about window. */
                    256: {
                    257:     register Square *squarePtr = (Square *) clientData;
                    258:     register Tk_Window tkwin = squarePtr->tkwin;
                    259:     Pixmap pm = None;
                    260:     Drawable d;
                    261: 
                    262:     squarePtr->flags &= ~REDRAW_PENDING;
                    263:     if ((tkwin == NULL) || !Tk_IsMapped(tkwin)) {
                    264:        return;
                    265:     }
                    266: 
                    267:     /*
                    268:      * Create a pixmap for double-buffering, if necessary.
                    269:      */
                    270: 
                    271:     if (squarePtr->doubleBuffer) {
                    272:        pm = XCreatePixmap(Tk_Display(tkwin), Tk_WindowId(tkwin),
                    273:                Tk_Width(tkwin), Tk_Height(tkwin),
                    274:                DefaultDepthOfScreen(Tk_Screen(tkwin)));
                    275:        d = pm;
                    276:     } else {
                    277:        d = Tk_WindowId(tkwin);
                    278:     }
                    279: 
                    280:     /*
                    281:      * Redraw the widget's background and border.
                    282:      */
                    283: 
                    284:     Tk_Fill3DRectangle(Tk_Display(tkwin), d, squarePtr->bgBorder,
                    285:            0, 0, Tk_Width(tkwin), Tk_Height(tkwin),
                    286:            squarePtr->borderWidth, squarePtr->relief);
                    287: 
                    288:     /*
                    289:      * Display the square.
                    290:      */
                    291: 
                    292:     Tk_Fill3DRectangle(Tk_Display(tkwin), d, squarePtr->fgBorder,
                    293:            squarePtr->x, squarePtr->y, squarePtr->size, squarePtr->size,
                    294:            squarePtr->borderWidth, TK_RELIEF_RAISED);
                    295: 
                    296:     /*
                    297:      * If double-buffered, copy to the screen and release the pixmap.
                    298:      */
                    299: 
                    300:     if (squarePtr->doubleBuffer) {
                    301:        XCopyArea(Tk_Display(tkwin), pm, Tk_WindowId(tkwin),
                    302:                DefaultGCOfScreen(Tk_Screen(tkwin)), 0, 0,
                    303:                Tk_Width(tkwin), Tk_Height(tkwin), 0, 0);
                    304:        XFreePixmap(Tk_Display(tkwin), pm);
                    305:     }
                    306: }
                    307: 
                    308: /*
                    309:  *--------------------------------------------------------------
                    310:  *
                    311:  * SquareWidgetCmd --
                    312:  *
                    313:  *     This procedure is invoked to process the Tcl command
                    314:  *     that corresponds to a widget managed by this module.
                    315:  *     See the user documentation for details on what it does.
                    316:  *
                    317:  * Results:
                    318:  *     A standard Tcl result.
                    319:  *
                    320:  * Side effects:
                    321:  *     See the user documentation.
                    322:  *
                    323:  *--------------------------------------------------------------
                    324:  */
                    325: 
                    326: static int
                    327: SquareWidgetCmd(clientData, interp, argc, argv)
                    328:     ClientData clientData;             /* Information about square widget. */
                    329:     Tcl_Interp *interp;                        /* Current interpreter. */
                    330:     int argc;                          /* Number of arguments. */
                    331:     char **argv;                       /* Argument strings. */
                    332: {
                    333:     register Square *squarePtr = (Square *) clientData;
                    334:     int result = TCL_OK;
                    335:     int length;
                    336:     char c;
                    337: 
                    338:     if (argc < 2) {
                    339:        Tcl_AppendResult(interp, "wrong # args: should be \"",
                    340:                argv[0], " option ?arg arg ...?\"", (char *) NULL);
                    341:        return TCL_ERROR;
                    342:     }
                    343:     Tk_Preserve((ClientData) squarePtr);
                    344:     c = argv[1][0];
                    345:     length = strlen(argv[1]);
                    346:     if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)) {
                    347:        if (argc == 2) {
                    348:            result = Tk_ConfigureInfo(interp, squarePtr->tkwin, configSpecs,
                    349:                    (char *) squarePtr, (char *) NULL, 0);
                    350:        } else if (argc == 3) {
                    351:            result = Tk_ConfigureInfo(interp, squarePtr->tkwin, configSpecs,
                    352:                    (char *) squarePtr, argv[2], 0);
                    353:        } else {
                    354:            result = ConfigureSquare(interp, squarePtr, argc-2, argv+2,
                    355:                    TK_CONFIG_ARGV_ONLY);
                    356:        }
                    357:     } else if ((c == 'p') && (strncmp(argv[1], "position", length) == 0)) {
                    358:        if ((argc != 2) && (argc != 4)) {
                    359:            Tcl_AppendResult(interp, "wrong # args: should be \"",
                    360:                    argv[0], " position ?x y?\"", (char *) NULL);
                    361:            goto error;
                    362:        }
                    363:        if (argc == 4) {
                    364:            if ((Tcl_GetInt(interp, argv[2], &squarePtr->x) != TCL_OK)
                    365:                    || (Tcl_GetInt(interp, argv[3], &squarePtr->y) != TCL_OK)) {
                    366:                goto error;
                    367:            }
                    368:            KeepInWindow(squarePtr);
                    369:        }
                    370:        sprintf(interp->result, "%d %d", squarePtr->x, squarePtr->y);
                    371:     } else if ((c == 's') && (strncmp(argv[1], "size", length) == 0)) {
                    372:        if ((argc != 2) && (argc != 3)) {
                    373:            Tcl_AppendResult(interp, "wrong # args: should be \"",
                    374:                    argv[0], " size ?amount?\"", (char *) NULL);
                    375:            goto error;
                    376:        }
                    377:        if (argc == 3) {
                    378:            int i;
                    379: 
                    380:            if (Tcl_GetInt(interp, argv[2], &i) != TCL_OK) {
                    381:                goto error;
                    382:            }
                    383:            if ((i <= 0) || (i > 100)) {
                    384:                Tcl_AppendResult(interp, "bad size \"", argv[2],
                    385:                        "\"", (char *) NULL);
                    386:                goto error;
                    387:            }
                    388:            squarePtr->size = i;
                    389:            KeepInWindow(squarePtr);
                    390:        }
                    391:        sprintf(interp->result, "%d", squarePtr->size);
                    392:     } else {
                    393:        Tcl_AppendResult(interp, "bad option \"", argv[1],
                    394:                "\":  must be configure, position, or size", (char *) NULL);
                    395:        goto error;
                    396:     }
                    397:     if (!(squarePtr->flags & REDRAW_PENDING)) {
                    398:        Tk_DoWhenIdle(DisplaySquare, (ClientData) squarePtr);
                    399:        squarePtr->flags |= REDRAW_PENDING;
                    400:     }
                    401:     Tk_Release((ClientData) squarePtr);
                    402:     return result;
                    403: 
                    404:     error:
                    405:     Tk_Release((ClientData) squarePtr);
                    406:     return TCL_ERROR;
                    407: }
                    408: 
                    409: /*
                    410:  *--------------------------------------------------------------
                    411:  *
                    412:  * SquareEventProc --
                    413:  *
                    414:  *     This procedure is invoked by the Tk dispatcher for various
                    415:  *     events on squares.
                    416:  *
                    417:  * Results:
                    418:  *     None.
                    419:  *
                    420:  * Side effects:
                    421:  *     When the window gets deleted, internal structures get
                    422:  *     cleaned up.  When it gets exposed, it is redisplayed.
                    423:  *
                    424:  *--------------------------------------------------------------
                    425:  */
                    426: 
                    427: static void
                    428: SquareEventProc(clientData, eventPtr)
                    429:     ClientData clientData;     /* Information about window. */
                    430:     XEvent *eventPtr;          /* Information about event. */
                    431: {
                    432:     Square *squarePtr = (Square *) clientData;
                    433: 
                    434:     if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
                    435:        if (!(squarePtr->flags & REDRAW_PENDING)) {
                    436:            Tk_DoWhenIdle(DisplaySquare, (ClientData) squarePtr);
                    437:            squarePtr->flags |= REDRAW_PENDING;
                    438:        }
                    439:     } else if (eventPtr->type == ConfigureNotify) {
                    440:        KeepInWindow(squarePtr);
                    441:        if (!(squarePtr->flags & REDRAW_PENDING)) {
                    442:            Tk_DoWhenIdle(DisplaySquare, (ClientData) squarePtr);
                    443:            squarePtr->flags |= REDRAW_PENDING;
                    444:        }
                    445:     } else if (eventPtr->type == DestroyNotify) {
                    446:        Tcl_DeleteCommand(squarePtr->interp, Tk_PathName(squarePtr->tkwin));
                    447:        squarePtr->tkwin = NULL;
                    448:        if (squarePtr->flags & REDRAW_PENDING) {
                    449:            Tk_CancelIdleCall(DisplaySquare, (ClientData) squarePtr);
                    450:        }
                    451:        Tk_EventuallyFree((ClientData) squarePtr, DestroySquare);
                    452:     }
                    453: }
                    454: 
                    455: /*
                    456:  *----------------------------------------------------------------------
                    457:  *
                    458:  * DestroySquare --
                    459:  *
                    460:  *     This procedure is invoked by Tk_EventuallyFree or Tk_Release
                    461:  *     to clean up the internal structure of a square at a safe time
                    462:  *     (when no-one is using it anymore).
                    463:  *
                    464:  * Results:
                    465:  *     None.
                    466:  *
                    467:  * Side effects:
                    468:  *     Everything associated with the square is freed up.
                    469:  *
                    470:  *----------------------------------------------------------------------
                    471:  */
                    472: 
                    473: static void
                    474: DestroySquare(clientData)
                    475:     ClientData clientData;     /* Info about square widget. */
                    476: {
                    477:     register Square *squarePtr = (Square *) clientData;
                    478: 
                    479:     if (squarePtr->bgBorder != NULL) {
                    480:        Tk_Free3DBorder(squarePtr->bgBorder);
                    481:     }
                    482:     if (squarePtr->fgBorder != NULL) {
                    483:        Tk_Free3DBorder(squarePtr->fgBorder);
                    484:     }
                    485:     ckfree((char *) squarePtr);
                    486: }
                    487: 
                    488: /*
                    489:  *----------------------------------------------------------------------
                    490:  *
                    491:  * KeepInWindow --
                    492:  *
                    493:  *     Adjust the position of the square if necessary to keep it in
                    494:  *     the widget's window.
                    495:  *
                    496:  * Results:
                    497:  *     None.
                    498:  *
                    499:  * Side effects:
                    500:  *     The x and y position of the square are adjusted if necessary
                    501:  *     to keep the square in the window.
                    502:  *
                    503:  *----------------------------------------------------------------------
                    504:  */
                    505: 
                    506: static void
                    507: KeepInWindow(squarePtr)
                    508:     register Square *squarePtr;                /* Pointer to widget record. */
                    509: {
                    510:     int i, bd;
                    511: 
                    512:     if (squarePtr->relief == TK_RELIEF_FLAT) {
                    513:        bd = 0;
                    514:     } else {
                    515:        bd = squarePtr->borderWidth;
                    516:     }
                    517:     i = (Tk_Width(squarePtr->tkwin) - bd) - (squarePtr->x + squarePtr->size);
                    518:     if (i < 0) {
                    519:        squarePtr->x += i;
                    520:     }
                    521:     i = (Tk_Height(squarePtr->tkwin) - bd) - (squarePtr->y + squarePtr->size);
                    522:     if (i < 0) {
                    523:        squarePtr->y += i;
                    524:     }
                    525:     if (squarePtr->x < bd) {
                    526:        squarePtr->x = bd;
                    527:     }
                    528:     if (squarePtr->y < bd) {
                    529:        squarePtr->y = bd;
                    530:     }
                    531: }

unix.superglobalmegacorp.com

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