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

1.1       root        1: /* 
                      2:  * tkWindow.c --
                      3:  *
                      4:  *     This file provides basic window-manipulation procedures,
                      5:  *     which are equivalent to procedures in Xlib (and even
                      6:  *     invoke them) but also maintain the local Tk_Window
                      7:  *     structure.
                      8:  *
                      9:  * Copyright 1989-1992 Regents of the University of California.
                     10:  * Permission to use, copy, modify, and distribute this
                     11:  * software and its documentation for any purpose and without
                     12:  * fee is hereby granted, provided that the above copyright
                     13:  * notice appear in all copies.  The University of California
                     14:  * makes no representations about the suitability of this
                     15:  * software for any purpose.  It is provided "as is" without
                     16:  * express or implied warranty.
                     17:  */
                     18: 
                     19: #ifndef lint
                     20: static char rcsid[] = "$Header: /user6/ouster/wish/RCS/tkWindow.c,v 1.92 92/08/21 11:42:44 ouster Exp $ SPRITE (Berkeley)";
                     21: #endif
                     22: 
                     23: #include "tkconfig.h"
                     24: #include "tkint.h"
                     25: 
                     26: /*
                     27:  * Global absolute file name:
                     28:  */
                     29: char *TK_Library = TK_LIBRARY;
                     30: 
                     31: /*
                     32:  * Count of open displays.
                     33:  */
                     34: int tk_Displays;
                     35: 
                     36: /*
                     37:  * Count of number of main windows currently open in this process.
                     38:  */
                     39: 
                     40: int tk_NumMainWindows;
                     41: 
                     42: /*
                     43:  * Added by dhopkins for OLPC Micropolis gtk.Socket integration. 
                     44:  */
                     45: 
                     46: Window tk_RootWindow = 0;
                     47: 
                     48: /*
                     49:  * List of all displays currently in use.
                     50:  */
                     51: 
                     52: TkDisplay *tkDisplayList = NULL;
                     53: 
                     54: /*
                     55:  * Have statics in this module been initialized?
                     56:  */
                     57: 
                     58: static initialized = 0;
                     59: 
                     60: /*
                     61:  * Context information used to map from X window id's to
                     62:  * TkWindow structures (during event handling, for example):
                     63:  */
                     64: 
                     65: XContext tkWindowContext;
                     66: 
                     67: /*
                     68:  * The variables below hold several uid's that are used in many places
                     69:  * in the toolkit.
                     70:  */
                     71: 
                     72: Tk_Uid tkDisabledUid = NULL;
                     73: Tk_Uid tkActiveUid = NULL;
                     74: Tk_Uid tkNormalUid = NULL;
                     75: 
                     76: /*
                     77:  * Default values for "changes" and "atts" fields of TkWindows.  Note
                     78:  * that Tk always requests all events for all windows, except StructureNotify
                     79:  * events on internal windows:  these events are generated internally.
                     80:  */
                     81: 
                     82: static XWindowChanges defChanges = {
                     83:     0, 0, 1, 1, 0, 0, Above
                     84: };
                     85: #define ALL_EVENTS_MASK \
                     86:     KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask| \
                     87:     EnterWindowMask|LeaveWindowMask|PointerMotionMask|ExposureMask| \
                     88:     VisibilityChangeMask|SubstructureNotifyMask| \
                     89:     FocusChangeMask|PropertyChangeMask|ColormapChangeMask
                     90: static XSetWindowAttributes defAtts= {
                     91:     None,                      /* background_pixmap */
                     92:     0,                         /* background_pixel */
                     93:     CopyFromParent,            /* border_pixmap */
                     94:     0,                         /* border_pixel */
                     95:     ForgetGravity,             /* bit_gravity */
                     96:     NorthWestGravity,          /* win_gravity */
                     97:     NotUseful,                 /* backing_store */
                     98:     ~0,                                /* backing_planes */
                     99:     0,                         /* backing_pixel */
                    100:     False,                     /* save_under */
                    101:     ALL_EVENTS_MASK,           /* event_mask */
                    102:     0,                         /* do_not_propagate_mask */
                    103:     False,                     /* override_redirect */
                    104:     CopyFromParent,            /* colormap */
                    105:     None                       /* cursor */
                    106: };
                    107: 
                    108: /*
                    109:  * The following structure defines all of the commands supported by
                    110:  * Tk, and the C procedures that execute them.
                    111:  */
                    112: 
                    113: typedef struct {
                    114:     char *name;                        /* Name of command. */
                    115:     int (*cmdProc) _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
                    116:            int argc, char **argv));
                    117:                                /* Command procedure. */
                    118: } TkCmd;
                    119: 
                    120: TkCmd commands[] = {
                    121:     /*
                    122:      * Commands that are part of the intrinsics:
                    123:      */
                    124: 
                    125:     {"after",          Tk_AfterCmd},
                    126:     {"bind",           Tk_BindCmd},
                    127:     {"destroy",                Tk_DestroyCmd},
                    128:     {"focus",          Tk_FocusCmd},
                    129:     {"grab",           Tk_GrabCmd},
                    130:     {"option",         Tk_OptionCmd},
                    131:     {"pack",           Tk_PackCmd},
                    132:     {"place",          Tk_PlaceCmd},
                    133:     {"selection",      Tk_SelectionCmd},
                    134:     {"tkwait",         Tk_TkwaitCmd},
                    135:     {"update",         Tk_UpdateCmd},
                    136:     {"winfo",          Tk_WinfoCmd},
                    137:     {"wm",             Tk_WmCmd},
                    138:     {"accept",         Tcp_AcceptCmd},
                    139:     {"shutdown",       Tcp_ShutdownCmd},
                    140:     {"connect",                Tcp_ConnectCmd},
                    141:     {"filehandler",    Tcp_FileHandlerCmd},
                    142: 
                    143:     /*
                    144:      * Widget-creation commands.
                    145:      */
                    146:     {"button",         Tk_ButtonCmd},
                    147:     {"canvas",         Tk_CanvasCmd},
                    148:     {"checkbutton",    Tk_ButtonCmd},
                    149:     {"entry",          Tk_EntryCmd},
                    150:     {"frame",          Tk_FrameCmd},
                    151:     {"label",          Tk_ButtonCmd},
                    152:     {"listbox",                Tk_ListboxCmd},
                    153:     {"menu",           Tk_MenuCmd},
                    154:     {"menubutton",     Tk_MenubuttonCmd},
                    155:     {"message",                Tk_MessageCmd},
                    156:     {"radiobutton",    Tk_ButtonCmd},
                    157:     {"scale",          Tk_ScaleCmd},
                    158:     {"scrollbar",      Tk_ScrollbarCmd},
                    159:     {"text",           Tk_TextCmd},
                    160:     {"toplevel",       Tk_FrameCmd},
                    161:     {(char *) NULL,    (int (*)()) NULL}
                    162: };
                    163: 
                    164: /*
                    165:  * Forward declarations to procedures defined later in this file:
                    166:  */
                    167: 
                    168: static Tk_Window       CreateTopLevelWindow _ANSI_ARGS_((Tcl_Interp *interp,
                    169:                            Tk_Window parent, char *name, char *screenName));
                    170: static void            DoConfigureNotify _ANSI_ARGS_((TkWindow *winPtr));
                    171: static TkDisplay *     GetScreen _ANSI_ARGS_((Tcl_Interp *interp,
                    172:                            char *screenName, int *screenPtr));
                    173: static int             NameWindow _ANSI_ARGS_((Tcl_Interp *interp,
                    174:                            TkWindow *winPtr, TkWindow *parentPtr,
                    175:                            char *name));
                    176: static TkWindow        *       NewWindow _ANSI_ARGS_((TkDisplay *dispPtr,
                    177:                            int screenNum));
                    178: 
                    179: /*
                    180:  *----------------------------------------------------------------------
                    181:  *
                    182:  * CreateTopLevelWindow --
                    183:  *
                    184:  *     Make a new window that will be at top-level (its parent will
                    185:  *     be the root window of a screen).
                    186:  *
                    187:  * Results:
                    188:  *     The return value is a token for the new window, or NULL if
                    189:  *     an error prevented the new window from being created.  If
                    190:  *     NULL is returned, an error message will be left in
                    191:  *     interp->result.
                    192:  *
                    193:  * Side effects:
                    194:  *     A new window structure is allocated locally.  An X
                    195:  *     window is NOT initially created, but will be created
                    196:  *     the first time the window is mapped.
                    197:  *
                    198:  *----------------------------------------------------------------------
                    199:  */
                    200: 
                    201: static Tk_Window
                    202: CreateTopLevelWindow(interp, parent, name, screenName)
                    203:     Tcl_Interp *interp;                /* Interpreter to use for error reporting. */
                    204:     Tk_Window parent;          /* Token for logical parent of new window
                    205:                                 * (used for naming, options, etc.).  May
                    206:                                 * be NULL. */
                    207:     char *name;                        /* Name for new window;  if parent is
                    208:                                 * non-NULL, must be unique among parent's
                    209:                                 * children. */
                    210:     char *screenName;          /* Name of screen on which to create
                    211:                                 * window.  NULL means use DISPLAY environment
                    212:                                 * variable to determine.  Empty string means
                    213:                                 * use parent's screen, or DISPLAY if no
                    214:                                 * parent. */
                    215: {
                    216:     register TkWindow *winPtr;
                    217:     register TkDisplay *dispPtr;
                    218:     int screenId;
                    219: 
                    220:     if (!initialized) {
                    221:        initialized = 1;
                    222:        tkWindowContext = XUniqueContext();
                    223:        tkActiveUid = Tk_GetUid("active");
                    224:        tkDisabledUid = Tk_GetUid("disabled");
                    225:        tkNormalUid = Tk_GetUid("normal");
                    226:     }
                    227: 
                    228:     if ((parent != NULL) && (screenName != NULL) && (screenName[0] == '\0')) {
                    229:        dispPtr = ((TkWindow *) parent)->dispPtr;
                    230:        screenId = Tk_ScreenNumber(parent);
                    231:     } else {
                    232:        dispPtr = GetScreen(interp, screenName, &screenId);
                    233:        if (dispPtr == NULL) {
                    234:            return (Tk_Window) NULL;
                    235:        }
                    236:     }
                    237: 
                    238:     winPtr = NewWindow(dispPtr, screenId);
                    239: 
                    240:     /*
                    241:      * Internal windows don't normally ask for StructureNotify events,
                    242:      * since we can generate them internally.  However, for top-level
                    243:      * windows we need to as for the events because the window could
                    244:      * be manipulated externally.
                    245:      */
                    246: 
                    247:     winPtr->atts.event_mask |= StructureNotifyMask;
                    248: 
                    249:     /*
                    250:      * (Need to set the TK_TOP_LEVEL flag immediately here;  otherwise
                    251:      * Tk_DestroyWindow will core dump if it is called before the flag
                    252:      * has been set.)
                    253:      */
                    254: 
                    255:     winPtr->flags |= TK_TOP_LEVEL;
                    256:     if (parent != NULL) {
                    257:        if (NameWindow(interp, winPtr, (TkWindow *) parent, name) != TCL_OK) {
                    258:            Tk_DestroyWindow((Tk_Window) winPtr);
                    259:            return (Tk_Window) NULL;
                    260:        }
                    261:     }
                    262:     TkWmNewWindow(winPtr);
                    263:     return (Tk_Window) winPtr;
                    264: }
                    265: 
                    266: /*
                    267:  *----------------------------------------------------------------------
                    268:  *
                    269:  * GetScreen --
                    270:  *
                    271:  *     Given a string name for a display-plus-screen, find the
                    272:  *     TkDisplay structure for the display and return the screen
                    273:  *     number too.
                    274:  *
                    275:  * Results:
                    276:  *     The return value is a pointer to information about the display,
                    277:  *     or NULL if the display couldn't be opened.  In this case, an
                    278:  *     error message is left in interp->result.  The location at
                    279:  *     *screenPtr is overwritten with the screen number parsed from
                    280:  *     screenName.
                    281:  *
                    282:  * Side effects:
                    283:  *     A new connection is opened to the display if there is no
                    284:  *     connection already.  A new TkDisplay data structure is also
                    285:  *     setup, if necessary.
                    286:  *
                    287:  *----------------------------------------------------------------------
                    288:  */
                    289: 
                    290: static TkDisplay *
                    291: GetScreen(interp, screenName, screenPtr)
                    292:     Tcl_Interp *interp;                /* Place to leave error message. */
                    293:     char *screenName;          /* Name for screen.  NULL or empty means
                    294:                                 * use DISPLAY envariable. */
                    295:     int *screenPtr;            /* Where to store screen number. */
                    296: {
                    297:     register TkDisplay *dispPtr;
                    298:     char *p;
                    299:     int length, screenId;
                    300: 
                    301:     /*
                    302:      * Separate the screen number from the rest of the display
                    303:      * name.  ScreenName is assumed to have the syntax
                    304:      * <display>.<screen> with the dot and the screen being
                    305:      * optional.
                    306:      */
                    307: 
                    308:     if ((screenName == NULL) || (screenName[0] == '\0')) {
                    309:        screenName = getenv("DISPLAY");
                    310:        if (screenName == NULL) {
                    311:            interp->result =
                    312:                    "no display name and no $DISPLAY environment variable";
                    313:            return (TkDisplay *) NULL;
                    314:        }
                    315:     }
                    316:     length = strlen(screenName);
                    317:     screenId = 0;
                    318:     p = screenName+length-1;
                    319:     while (isdigit(*p) && (p != screenName)) {
                    320:        p--;
                    321:     }
                    322:     if ((*p == '.') && (p[1] != '\0')) {
                    323:        length = p - screenName;
                    324:        screenId = strtoul(p+1, (char **) NULL, 10);
                    325:     }
                    326: 
                    327:     /*
                    328:      * See if we already have a connection to this display.  If not,
                    329:      * then open a new connection.
                    330:      */
                    331: 
                    332:     for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr) {
                    333:        if (dispPtr == NULL) {
                    334:            Display *display = NULL;
                    335: 
                    336:            display = XOpenDisplay(screenName);
                    337: 
                    338:            if (display == NULL) {
                    339:                Tcl_AppendResult(interp, "couldn't connect to display \"",
                    340:                        screenName, "\"", (char *) NULL);
                    341:                return (TkDisplay *) NULL;
                    342:            }
                    343:            if (getenv("XSYNCHRONIZE") != NULL) {
                    344:              XSynchronize(display, 1);
                    345:            }
                    346:            tk_Displays++;
                    347:            dispPtr = (TkDisplay *) ckalloc(sizeof(TkDisplay));
                    348:            dispPtr->display = display;
                    349:            dispPtr->nextPtr = tkDisplayList;
                    350:            dispPtr->name = (char *) ckalloc((unsigned) (length+1));
                    351:            dispPtr->lastEventTime = CurrentTime;
                    352:            strncpy(dispPtr->name, screenName, length);
                    353:            dispPtr->mouseMainPtr = NULL;
                    354:            dispPtr->name[length] = '\0';
                    355:            dispPtr->symsPerCode = 0;
                    356:            dispPtr->errorPtr = NULL;
                    357:            dispPtr->deleteCount = 0;
                    358:            dispPtr->commWindow = NULL;
                    359:            dispPtr->selectionOwner = NULL;
                    360:            dispPtr->selectionSerial = 0;
                    361:            dispPtr->multipleAtom = None;
                    362:            dispPtr->atomInit = 0;
                    363:            dispPtr->cursorFont = None;
                    364:            dispPtr->grabWinPtr = NULL;
                    365:            dispPtr->ungrabWinPtr = NULL;
                    366:            dispPtr->buttonWinPtr = NULL;
                    367:            dispPtr->pointerWinPtr = NULL;
                    368:            dispPtr->serverWinPtr = NULL;
                    369:            dispPtr->grabFlags = 0;
                    370:            dispPtr->focusPtr = NULL;
                    371:            tkDisplayList = dispPtr;
                    372:            Tk_CreateFileHandler(ConnectionNumber(display),
                    373:                    TK_READABLE, (void (*)()) NULL,
                    374:                    (ClientData) display);
                    375:            break;
                    376:        }
                    377:        if ((strncmp(dispPtr->name, screenName, length) == 0)
                    378:                && (dispPtr->name[length] == '\0')) {
                    379:            break;
                    380:        }
                    381:     }
                    382:     if (screenId >= ScreenCount(dispPtr->display)) {
                    383:        sprintf(interp->result, "bad screen number \"%d\"", screenId);
                    384:        return (TkDisplay *) NULL;
                    385:     }
                    386:     *screenPtr = screenId;
                    387:     return dispPtr;
                    388: }
                    389: 
                    390: /*
                    391:  *--------------------------------------------------------------
                    392:  *
                    393:  * NewWindow --
                    394:  *
                    395:  *     This procedure creates and initializes a TkWindow structure.
                    396:  *
                    397:  * Results:
                    398:  *     The return value is a pointer to the new window.
                    399:  *
                    400:  * Side effects:
                    401:  *     A new window structure is allocated and all its fields are
                    402:  *     initialized.
                    403:  *
                    404:  *--------------------------------------------------------------
                    405:  */
                    406: 
                    407: static TkWindow *
                    408: NewWindow(dispPtr, screenNum)
                    409:     TkDisplay *dispPtr;                /* Display associated with new window. */
                    410:     int screenNum;             /* Index of screen for new window. */
                    411: {
                    412:     register TkWindow *winPtr;
                    413: 
                    414:     winPtr = (TkWindow *) ckalloc(sizeof(TkWindow));
                    415:     winPtr->display = dispPtr->display;
                    416:     winPtr->dispPtr = dispPtr;
                    417:     winPtr->screenNum = screenNum;
                    418:     winPtr->window = None;
                    419:     winPtr->childList = NULL;
                    420:     winPtr->parentPtr = NULL;
                    421:     winPtr->nextPtr = NULL;
                    422:     winPtr->mainPtr = NULL;
                    423:     winPtr->pathName = NULL;
                    424:     winPtr->nameUid = NULL;
                    425:     winPtr->classUid = NULL;
                    426:     winPtr->changes = defChanges;
                    427:     winPtr->dirtyChanges = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;
                    428:     winPtr->atts = defAtts;
                    429:     winPtr->dirtyAtts = CWEventMask;
                    430:     winPtr->flags = 0;
                    431:     winPtr->handlerList = NULL;
                    432:     winPtr->focusProc = NULL;
                    433:     winPtr->focusData = NULL;
                    434:     winPtr->optionLevel = -1;
                    435:     winPtr->selHandlerList = NULL;
                    436:     winPtr->selClearProc = NULL;
                    437:     winPtr->selClearData = NULL;
                    438:     winPtr->geomProc = NULL;
                    439:     winPtr->geomData = NULL;
                    440:     winPtr->reqWidth = winPtr->reqHeight = 0;
                    441:     winPtr->internalBorderWidth = 0;
                    442:     winPtr->wmInfoPtr = NULL;
                    443:     return winPtr;
                    444: }
                    445: 
                    446: /*
                    447:  *----------------------------------------------------------------------
                    448:  *
                    449:  * NameWindow --
                    450:  *
                    451:  *     This procedure is invoked to give a window a name and insert
                    452:  *     the window into the hierarchy associated with a particular
                    453:  *     application.
                    454:  *
                    455:  * Results:
                    456:  *     A standard Tcl return value.
                    457:  *
                    458:  * Side effects:
                    459:  *      See above.
                    460:  *
                    461:  *----------------------------------------------------------------------
                    462:  */
                    463: 
                    464: static int
                    465: NameWindow(interp, winPtr, parentPtr, name)
                    466:     Tcl_Interp *interp;                /* Interpreter to use for error reporting. */
                    467:     register TkWindow *winPtr; /* Window that is to be named and inserted. */
                    468:     TkWindow *parentPtr;       /* Pointer to logical parent for winPtr
                    469:                                 * (used for naming, options, etc.). */
                    470:     char *name;                        /* Name for winPtr;   must be unique among
                    471:                                 * parentPtr's children. */
                    472: {
                    473: #define FIXED_SIZE 200
                    474:     char staticSpace[FIXED_SIZE];
                    475:     char *pathName;
                    476:     int new;
                    477:     Tcl_HashEntry *hPtr;
                    478:     int length1, length2;
                    479: 
                    480:     /*
                    481:      * Setup all the stuff except name right away, then do the name stuff
                    482:      * last.  This is so that if the name stuff fails, everything else
                    483:      * will be properly initialized (needed to destroy the window cleanly
                    484:      * after the naming failure).
                    485:      */
                    486:     winPtr->parentPtr = parentPtr;
                    487:     winPtr->nextPtr = parentPtr->childList;
                    488:     parentPtr->childList = winPtr;
                    489:     winPtr->mainPtr = parentPtr->mainPtr;
                    490:     winPtr->nameUid = Tk_GetUid(name);
                    491: 
                    492:     /*
                    493:      * To permit names of arbitrary length, must be prepared to malloc
                    494:      * a buffer to hold the new path name.  To run fast in the common
                    495:      * case where names are short, use a fixed-size buffer on the
                    496:      * stack.
                    497:      */
                    498: 
                    499:     length1 = strlen(parentPtr->pathName);
                    500:     length2 = strlen(name);
                    501:     if ((length1+length2+2) <= FIXED_SIZE) {
                    502:        pathName = staticSpace;
                    503:     } else {
                    504:        pathName = (char *) ckalloc((unsigned) (length1+length2+2));
                    505:     }
                    506:     if (length1 == 1) {
                    507:        pathName[0] = '.';
                    508:        strcpy(pathName+1, name);
                    509:     } else {
                    510:        strcpy(pathName, parentPtr->pathName);
                    511:        pathName[length1] = '.';
                    512:        strcpy(pathName+length1+1, name);
                    513:     }
                    514:     hPtr = Tcl_CreateHashEntry(&parentPtr->mainPtr->nameTable, pathName, &new);
                    515:     if (pathName != staticSpace) {
                    516:        ckfree(pathName);
                    517:     }
                    518:     if (!new) {
                    519:        Tcl_AppendResult(interp, "window name \"", name,
                    520:                "\" already exists in parent", (char *) NULL);
                    521:        return TCL_ERROR;
                    522:     }
                    523:     Tcl_SetHashValue(hPtr, winPtr);
                    524:     winPtr->pathName = Tcl_GetHashKey(&parentPtr->mainPtr->nameTable, hPtr);
                    525:     return TCL_OK;
                    526: }
                    527: 
                    528: /*
                    529:  *----------------------------------------------------------------------
                    530:  *
                    531:  * Tk_CreateMainWindow --
                    532:  *
                    533:  *     Make a new main window.  A main window is a special kind of
                    534:  *     top-level window used as the outermost window in an
                    535:  *     application.
                    536:  *
                    537:  * Results:
                    538:  *     The return value is a token for the new window, or NULL if
                    539:  *     an error prevented the new window from being created.  If
                    540:  *     NULL is returned, an error message will be left in
                    541:  *     interp->result.
                    542:  *
                    543:  * Side effects:
                    544:  *     A new window structure is allocated locally;  "interp" is
                    545:  *     associated with the window and registered for "send" commands
                    546:  *     under "baseName".  BaseName may be extended with an instance
                    547:  *     number in the form "#2" if necessary to make it globally
                    548:  *     unique.  Tk-related commands are bound into interp.  An X
                    549:  *     window is NOT initially created, but will be created the
                    550:  *     first time the window is mapped.
                    551:  *
                    552:  *----------------------------------------------------------------------
                    553:  */
                    554: 
                    555: Tk_Window
                    556: Tk_CreateMainWindow(interp, screenName, baseName)
                    557:     Tcl_Interp *interp;                /* Interpreter to use for error reporting. */
                    558:     char *screenName;          /* Name of screen on which to create
                    559:                                 * window.  Empty or NULL string means
                    560:                                 * use DISPLAY environment variable. */
                    561:     char *baseName;            /* Base name for application;  usually of the
                    562:                                 * form "prog instance". */
                    563: {
                    564:     Tk_Window tkwin;
                    565:     int result, dummy;
                    566:     Tcl_HashEntry *hPtr;
                    567:     register TkMainInfo *mainPtr;
                    568:     register TkWindow *winPtr;
                    569:     register TkCmd *cmdPtr;
                    570: 
                    571:     /*
                    572:      * Create the basic TkWindow structure.
                    573:      */
                    574: 
                    575:     tkwin = CreateTopLevelWindow(interp, (Tk_Window) NULL, baseName,
                    576:            screenName);
                    577:     if (tkwin == NULL) {
                    578:        return NULL;
                    579:     }
                    580: 
                    581:     /*
                    582:      * Create the TkMainInfo structure for this application, and set
                    583:      * up name-related information for the new window.
                    584:      */
                    585: 
                    586:     winPtr = (TkWindow *) tkwin;
                    587:     mainPtr = (TkMainInfo *) ckalloc(sizeof(TkMainInfo));
                    588:     mainPtr->winPtr = winPtr;
                    589:     mainPtr->interp = interp;
                    590:     Tcl_InitHashTable(&mainPtr->nameTable, TCL_STRING_KEYS);
                    591:     mainPtr->bindingTable = Tk_CreateBindingTable(interp);
                    592: /* XXX: FOCUS */
                    593: /*    mainPtr->focusPtr = NULL; */
                    594:     mainPtr->optionRootPtr = NULL;
                    595:     winPtr->mainPtr = mainPtr;
                    596:     hPtr = Tcl_CreateHashEntry(&mainPtr->nameTable, ".", &dummy);
                    597:     Tcl_SetHashValue(hPtr, winPtr);
                    598:     winPtr->pathName = Tcl_GetHashKey(&mainPtr->nameTable, hPtr);
                    599: 
                    600:     /*
                    601:      * Register the interpreter for "send" purposes.  If baseName isn't
                    602:      * already unique, find a unique suffix to add to it to make it
                    603:      * unique.  Change the window's name to contain the suffix.
                    604:      */
                    605: 
                    606:     result = Tk_RegisterInterp(interp, baseName, tkwin);
                    607:     if (result == TCL_OK) {
                    608:        winPtr->nameUid = Tk_GetUid(baseName);
                    609:     } else {
                    610:        char newName[110];
                    611:        int i;
                    612: 
                    613:        for (i = 2; ; i++) {
                    614:            sprintf(newName, "%.100s #%d", baseName, i);
                    615:            Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
                    616:            result = Tk_RegisterInterp(interp, newName, tkwin);
                    617:            if (result == TCL_OK) {
                    618:                break;
                    619:            }
                    620:            if (i >= 100) {
                    621:                Tcl_SetResult(interp,
                    622:                        "couldn't generate unique name to register application",
                    623:                        TCL_STATIC);
                    624:                Tk_DestroyWindow(tkwin);
                    625:            }
                    626:        }
                    627:        winPtr->nameUid = Tk_GetUid(newName);
                    628:     }
                    629: 
                    630:     /*
                    631:      * Bind in Tk's commands.
                    632:      */
                    633: 
                    634:     for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
                    635:        Tcl_CreateCommand(interp, cmdPtr->name, cmdPtr->cmdProc,
                    636:                (ClientData) tkwin, (void (*)()) NULL);
                    637:     }
                    638: 
                    639:     /*
                    640:      * Set variables for the intepreter.
                    641:      */
                    642: 
                    643:     Tcl_SetVar(interp, "tk_library", TK_Library, TCL_GLOBAL_ONLY);
                    644:     Tcl_SetVar(interp, "tk_version", TK_VERSION, TCL_GLOBAL_ONLY);
                    645:     Tcl_SetVar(interp, "tkVersion", TK_VERSION, TCL_GLOBAL_ONLY);
                    646: 
                    647:     tk_NumMainWindows++;
                    648:     return tkwin;
                    649: }
                    650: 
                    651: /*
                    652:  *--------------------------------------------------------------
                    653:  *
                    654:  * Tk_CreateWindow --
                    655:  *
                    656:  *     Create a new internal or top-level window as a child of an
                    657:  *     existing window.
                    658:  *
                    659:  * Results:
                    660:  *     The return value is a token for the new window.  This
                    661:  *     is not the same as X's token for the window.  If an error
                    662:  *     occurred in creating the window (e.g. no such display or
                    663:  *     screen), then an error message is left in interp->result and
                    664:  *     NULL is returned.
                    665:  *
                    666:  * Side effects:
                    667:  *     A new window structure is allocated locally.  An X
                    668:  *     window is not initially created, but will be created
                    669:  *     the first time the window is mapped.
                    670:  *
                    671:  *--------------------------------------------------------------
                    672:  */
                    673: 
                    674: Tk_Window
                    675: Tk_CreateWindow(interp, parent, name, screenName)
                    676:     Tcl_Interp *interp;                /* Interpreter to use for error reporting.
                    677:                                 * Interp->result is assumed to be
                    678:                                 * initialized by the caller. */
                    679:     Tk_Window parent;          /* Token for parent of new window. */
                    680:     char *name;                        /* Name for new window.  Must be unique
                    681:                                 * among parent's children. */
                    682:     char *screenName;          /* If NULL, new window will be internal on
                    683:                                 * same screen as its parent.  If non-NULL,
                    684:                                 * gives name of screen on which to create
                    685:                                 * new window;  window will be a top-level
                    686:                                 * window. */
                    687: {
                    688:     TkWindow *parentPtr = (TkWindow *) parent;
                    689:     TkWindow *winPtr;
                    690: 
                    691:     if (screenName == NULL) {
                    692:        winPtr = NewWindow(parentPtr->dispPtr, parentPtr->screenNum);
                    693:        if (NameWindow(interp, winPtr, parentPtr, name) != TCL_OK) {
                    694:            Tk_DestroyWindow((Tk_Window) winPtr);
                    695:            return NULL;
                    696:        } else {
                    697:            return (Tk_Window) winPtr;
                    698:        }
                    699:     } else {
                    700: /*
                    701:  * This is a fix for dvx XOpenDisplay... display name conformalization
                    702:  * bugs...
                    703:  */
                    704:         char dsp[256];
                    705:         int len;
                    706: 
                    707:         strcpy(dsp, screenName);
                    708:         len = strlen(dsp);
                    709:         if (len && (dsp[len -1] == '.'))
                    710:             dsp[len -1] = '\0';
                    711: 
                    712:        return CreateTopLevelWindow(interp, parent, name, dsp);
                    713:     }
                    714: }
                    715: 
                    716: /*
                    717:  *----------------------------------------------------------------------
                    718:  *
                    719:  * Tk_CreateWindowFromPath --
                    720:  *
                    721:  *     This procedure is similar to Tk_CreateInternalWindow except
                    722:  *     that it uses a path name to create the window, rather than
                    723:  *     a parent and a child name.
                    724:  *
                    725:  * Results:
                    726:  *     The return value is a token for the new window.  This
                    727:  *     is not the same as X's token for the window.  If an error
                    728:  *     occurred in creating the window (e.g. no such display or
                    729:  *     screen), then an error message is left in interp->result and
                    730:  *     NULL is returned.
                    731:  *
                    732:  * Side effects:
                    733:  *     A new window structure is allocated locally.  An X
                    734:  *     window is not initially created, but will be created
                    735:  *     the first time the window is mapped.
                    736:  *
                    737:  *----------------------------------------------------------------------
                    738:  */
                    739: 
                    740: Tk_Window
                    741: Tk_CreateWindowFromPath(interp, tkwin, pathName, screenName)
                    742:     Tcl_Interp *interp;                /* Interpreter to use for error reporting.
                    743:                                 * Interp->result is assumed to be
                    744:                                 * initialized by the caller. */
                    745:     Tk_Window tkwin;           /* Token for any window in application
                    746:                                 * that is to contain new window. */
                    747:     char *pathName;            /* Path name for new window within the
                    748:                                 * application of tkwin.  The parent of
                    749:                                 * this window must already exist, but
                    750:                                 * the window itself must not exist. */
                    751:     char *screenName;          /* If NULL, new window will be on same
                    752:                                 * screen as its parent.  If non-NULL,
                    753:                                 * gives name of screen on which to create
                    754:                                 * new window;  window will be a top-level
                    755:                                 * window. */
                    756: {
                    757: #define FIXED_SPACE 5
                    758:     char fixedSpace[FIXED_SPACE+1];
                    759:     char *p;
                    760:     Tk_Window parent;
                    761:     int numChars;
                    762: 
                    763:     /*
                    764:      * Strip the parent's name out of pathName (it's everything up
                    765:      * to the last dot).  There are two tricky parts: (a) must
                    766:      * copy the parent's name somewhere else to avoid modifying
                    767:      * the pathName string (for large names, space for the copy
                    768:      * will have to be malloc'ed);  (b) must special-case the
                    769:      * situation where the parent is ".".
                    770:      */
                    771: 
                    772:     p = strrchr(pathName, '.');
                    773:     if (p == NULL) {
                    774:        Tcl_AppendResult(interp, "bad window path name \"", pathName,
                    775:                "\"", (char *) NULL);
                    776:        return NULL;
                    777:     }
                    778:     numChars = p-pathName;
                    779:     if (numChars > FIXED_SPACE) {
                    780:        p = (char *) ckalloc((unsigned) (numChars+1));
                    781:     } else {
                    782:        p = fixedSpace;
                    783:     }
                    784:     if (numChars == 0) {
                    785:        *p = '.';
                    786:        p[1] = '\0';
                    787:     } else {
                    788:        strncpy(p, pathName, numChars);
                    789:        p[numChars] = '\0';
                    790:     }
                    791: 
                    792:     /*
                    793:      * Find the parent window.
                    794:      */
                    795: 
                    796:     parent = Tk_NameToWindow(interp, p, tkwin);
                    797:     if (p != fixedSpace) {
                    798:        ckfree(p);
                    799:     }
                    800:     if (parent == NULL) {
                    801:        return NULL;
                    802:     }
                    803: 
                    804:     /*
                    805:      * Create the window.
                    806:      */
                    807: 
                    808:     if (screenName == NULL) {
                    809:        TkWindow *parentPtr = (TkWindow *) parent;
                    810:        TkWindow *winPtr;
                    811: 
                    812:        winPtr = NewWindow(parentPtr->dispPtr, parentPtr->screenNum);
                    813:        if (NameWindow(interp, winPtr, parentPtr, pathName+numChars+1)
                    814:                != TCL_OK) {
                    815:            Tk_DestroyWindow((Tk_Window) winPtr);
                    816:            return NULL;
                    817:        } else {
                    818:            return (Tk_Window) winPtr;
                    819:        }
                    820:     } else {
                    821:        return CreateTopLevelWindow(interp, parent, pathName+numChars+1,
                    822:                screenName);
                    823:     }
                    824: }
                    825: 
                    826: /*
                    827:  *--------------------------------------------------------------
                    828:  *
                    829:  * Tk_DestroyWindow --
                    830:  *
                    831:  *     Destroy an existing window.  After this call, the caller
                    832:  *     should never again use the token.
                    833:  *
                    834:  * Results:
                    835:  *     None.
                    836:  *
                    837:  * Side effects:
                    838:  *     The window is deleted, along with all of its children.
                    839:  *     Relevant callback procedures are invoked.
                    840:  *
                    841:  *--------------------------------------------------------------
                    842:  */
                    843: 
                    844: void
                    845: Tk_DestroyWindow(tkwin)
                    846:     Tk_Window tkwin;           /* Window to destroy. */
                    847: {
                    848:     register TkWindow *winPtr = (TkWindow *) tkwin;
                    849:     XEvent event;
                    850: 
                    851:     /*
                    852:      * Recursively destroy children.  The TK_RECURSIVE_DESTROY
                    853:      * flags means that the child's window needn't be explicitly
                    854:      * destroyed (the destroy of the parent already did it), nor
                    855:      * does it need to be removed from its parent's child list,
                    856:      * since the parent is being destroyed too.
                    857:      */
                    858: 
                    859:     while (winPtr->childList != NULL) {
                    860:        winPtr->childList->flags |= TK_RECURSIVE_DESTROY;
                    861:        Tk_DestroyWindow((Tk_Window) winPtr->childList);
                    862:     }
                    863: 
                    864:     /*
                    865:      * Generate a DestroyNotify event.  In order for the DestroyNotify
                    866:      * event to be processed correctly, need to make sure the window
                    867:      * exists.  This is a bit of a kludge, and may be unnecessarily
                    868:      * expensive, but without it no event handlers will get called for
                    869:      * windows that don't exist yet.
                    870:      */
                    871: 
                    872:     if (winPtr->window == None) {
                    873:        Tk_MakeWindowExist(tkwin);
                    874:     }
                    875:     winPtr->flags |= TK_ALREADY_DEAD;
                    876:     event.type = DestroyNotify;
                    877:     event.xdestroywindow.serial =
                    878:            LastKnownRequestProcessed(winPtr->display);
                    879:     event.xdestroywindow.send_event = False;
                    880:     event.xdestroywindow.display = winPtr->display;
                    881:     event.xdestroywindow.event = winPtr->window;
                    882:     event.xdestroywindow.window = winPtr->window;
                    883:     Tk_HandleEvent(&event);
                    884: 
                    885:     /*
                    886:      * Cleanup the data structures associated with this window.
                    887:      * No need to destroy windows during recursive destroys, since
                    888:      * that will happen automatically when the parent window is
                    889:      * destroyed (not true for top-level windows:  must destroy
                    890:      * them explicitly).
                    891:      */
                    892: 
                    893:     if (winPtr->window != None) {
                    894:        if (!(winPtr->flags & TK_RECURSIVE_DESTROY)
                    895:                || (winPtr->flags & TK_TOP_LEVEL)) {
                    896:            XDestroyWindow(winPtr->display, winPtr->window);
                    897:        }
                    898:        XDeleteContext(winPtr->display, winPtr->window, tkWindowContext);
                    899:        winPtr->window = None;
                    900:     }
                    901:     if (winPtr->parentPtr != NULL) {
                    902:        if (winPtr->parentPtr->childList == winPtr) {
                    903:            winPtr->parentPtr->childList = winPtr->nextPtr;
                    904:        } else {
                    905:            register TkWindow *winPtr2;
                    906:     
                    907:            for (winPtr2 = winPtr->parentPtr->childList; ;
                    908:                    winPtr2 = winPtr2->nextPtr) {
                    909:                if (winPtr2 == NULL) {
                    910:                    panic("Tk_DestroyWindow couldn't find child in parent (deleted twice?)");
                    911:                    break;
                    912:                }
                    913:                if (winPtr2->nextPtr == winPtr) {
                    914:                    winPtr2->nextPtr = winPtr->nextPtr;
                    915:                    break;
                    916:                }
                    917:            }
                    918:        }
                    919:     }
                    920:     TkEventDeadWindow(winPtr);
                    921:     TkOptionDeadWindow(winPtr);
                    922:     TkSelDeadWindow(winPtr);
                    923:     if (winPtr->flags & TK_TOP_LEVEL) {
                    924:        TkWmDeadWindow(winPtr);
                    925:     }
                    926:     TkGrabDeadWindow(winPtr);
                    927:     if (winPtr->mainPtr != NULL) {
                    928:        Tk_DeleteAllBindings(winPtr->mainPtr->bindingTable,
                    929:                (ClientData) winPtr->pathName);
                    930:        if (winPtr->pathName != NULL) {
                    931:            Tcl_DeleteHashEntry(Tcl_FindHashEntry(&winPtr->mainPtr->nameTable,
                    932:                    winPtr->pathName));
                    933:        }
                    934:        if (winPtr->mainPtr->winPtr == winPtr) {
                    935:            register TkCmd *cmdPtr;
                    936: 
                    937:            /*
                    938:             * Deleting a main window.  Delete the TkMainInfo structure too
                    939:             * and replace all of Tk's commands with dummy commands that
                    940:             * return errors.  Also delete the "send" command to unregister
                    941:             * the interpreter.
                    942:             */
                    943: 
                    944:            for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) {
                    945:                Tcl_CreateCommand(winPtr->mainPtr->interp, cmdPtr->name,
                    946:                        TkDeadAppCmd, (ClientData) NULL, (void (*)()) NULL);
                    947:            }
                    948:            Tcl_CreateCommand(winPtr->mainPtr->interp, "send",
                    949:                    TkDeadAppCmd, (ClientData) NULL, (void (*)()) NULL);
                    950:            Tcl_DeleteHashTable(&winPtr->mainPtr->nameTable);
                    951:            Tk_DeleteBindingTable(winPtr->mainPtr->bindingTable);
                    952:            ckfree((char *) winPtr->mainPtr);
                    953:            tk_NumMainWindows--;
                    954:        }
                    955:     }
                    956:     ckfree((char *) winPtr);
                    957: }
                    958: 
                    959: /*
                    960:  *--------------------------------------------------------------
                    961:  *
                    962:  * Tk_MapWindow --
                    963:  *
                    964:  *     Map a window within its parent.  This may require the
                    965:  *     window and/or its parents to actually be created.
                    966:  *
                    967:  * Results:
                    968:  *     None.
                    969:  *
                    970:  * Side effects:
                    971:  *     The given window will be mapped.  Windows may also
                    972:  *     be created.
                    973:  *
                    974:  *--------------------------------------------------------------
                    975:  */
                    976: 
                    977: void
                    978: Tk_MapWindow(tkwin)
                    979:     Tk_Window tkwin;           /* Token for window to map. */
                    980: {
                    981:     register TkWindow *winPtr = (TkWindow *) tkwin;
                    982: 
                    983:     if (winPtr->flags & TK_MAPPED) {
                    984:        return;
                    985:     }
                    986:     if (winPtr->window == None) {
                    987:        Tk_MakeWindowExist(tkwin);
                    988:     }
                    989:     if (winPtr->flags & TK_TOP_LEVEL) {
                    990:        if (!TkWmMapWindow(winPtr)) {
                    991:            return;
                    992:        }
                    993:     } else {
                    994:        /*
                    995:         * Don't set the mapped flag for top-level windows:  TkWmMapWindow
                    996:         * does it if appropriate (e.g. if the window is going to be non-
                    997:         * iconic).
                    998:         */
                    999: 
                   1000:        winPtr->flags |= TK_MAPPED;
                   1001:     }
                   1002:     XMapWindow(winPtr->display, winPtr->window);
                   1003:     if (!(winPtr->flags & TK_TOP_LEVEL)) {
                   1004:        XEvent event;
                   1005: 
                   1006:        event.type = MapNotify;
                   1007:        event.xmap.serial = LastKnownRequestProcessed(winPtr->display);
                   1008:        event.xmap.send_event = False;
                   1009:        event.xmap.display = winPtr->display;
                   1010:        event.xmap.event = winPtr->window;
                   1011:        event.xmap.window = winPtr->window;
                   1012:        event.xmap.override_redirect = winPtr->atts.override_redirect;
                   1013:        Tk_HandleEvent(&event);
                   1014:     }
                   1015: }
                   1016: 
                   1017: /*
                   1018:  *--------------------------------------------------------------
                   1019:  *
                   1020:  * Tk_MakeWindowExist --
                   1021:  *
                   1022:  *     Ensure that a particular window actually exists.  This
                   1023:  *     procedure shouldn't normally need to be invoked from
                   1024:  *     outside the Tk package, but may be needed if someone
                   1025:  *     wants to manipulate a window before mapping it.
                   1026:  *
                   1027:  * Results:
                   1028:  *     None.
                   1029:  *
                   1030:  * Side effects:
                   1031:  *     When the procedure returns, the X window associated with
                   1032:  *     tkwin is guaranteed to exist.  This may require the
                   1033:  *     window's ancestors to be created also.
                   1034:  *
                   1035:  *--------------------------------------------------------------
                   1036:  */
                   1037: 
                   1038: void
                   1039: Tk_MakeWindowExist(tkwin)
                   1040:     Tk_Window tkwin;           /* Token for window. */
                   1041: {
                   1042:     register TkWindow *winPtr = (TkWindow *) tkwin;
                   1043:     Window parent;
                   1044: 
                   1045:     if (winPtr->window != None) {
                   1046:        return;
                   1047:     }
                   1048: 
                   1049:     if (winPtr->flags & TK_TOP_LEVEL) {
                   1050:         /*
                   1051:          * workaround by dhopkins for OLPC Micropolis gtk.Socket integration. 
                   1052:         */
                   1053: 
                   1054:        if (tk_RootWindow) {
                   1055:            parent = 
                   1056:                tk_RootWindow;
                   1057:        } else {
                   1058:            parent = 
                   1059:                XRootWindow(winPtr->display, winPtr->screenNum);
                   1060:        }
                   1061: 
                   1062:     } else {
                   1063:        if (winPtr->parentPtr->window == None) {
                   1064:            Tk_MakeWindowExist((Tk_Window) winPtr->parentPtr);
                   1065:        }
                   1066:        parent = winPtr->parentPtr->window;
                   1067:     }
                   1068: 
                   1069: /* workaround to support non-default colormaps */
                   1070: #if 0
                   1071:     winPtr->window = XCreateWindow(winPtr->display, parent,
                   1072:            winPtr->changes.x, winPtr->changes.y,
                   1073:            winPtr->changes.width, winPtr->changes.height,
                   1074:            winPtr->changes.border_width, CopyFromParent,
                   1075:            InputOutput, CopyFromParent, winPtr->dirtyAtts,
                   1076:            &winPtr->atts);
                   1077: #else
                   1078:     { Screen *scr = ScreenOfDisplay(winPtr->display, winPtr->screenNum);
                   1079: 
                   1080:       winPtr->dirtyAtts |= CWColormap | CWBorderPixmap;
                   1081:       winPtr->atts.colormap = Tk_DefaultColormap(scr);
                   1082:       winPtr->atts.border_pixmap = Tk_DefaultPixmap(scr);
                   1083: 
                   1084:       winPtr->window = XCreateWindow(winPtr->display, parent,
                   1085:          winPtr->changes.x, winPtr->changes.y,
                   1086:          winPtr->changes.width, winPtr->changes.height,
                   1087:          winPtr->changes.border_width,
                   1088:          Tk_DefaultDepth(scr),
                   1089:          InputOutput,
                   1090:          Tk_DefaultVisual(scr),
                   1091:          winPtr->dirtyAtts, &winPtr->atts);
                   1092:     }
                   1093: #endif
                   1094: 
                   1095:     XSaveContext(winPtr->display, winPtr->window, tkWindowContext,
                   1096:            (void *) winPtr);
                   1097:     winPtr->dirtyAtts = 0;
                   1098:     winPtr->dirtyChanges &= ~(CWX|CWY|CWWidth|CWHeight|CWBorderWidth);
                   1099:     if (winPtr->dirtyChanges != 0) {
                   1100:        XConfigureWindow(winPtr->display, winPtr->window,
                   1101:                winPtr->dirtyChanges, &winPtr->changes);
                   1102:        winPtr->dirtyChanges = 0;
                   1103:     }
                   1104: 
                   1105:     /*
                   1106:      * Issue a ConfigureNotify event if there were deferred configuration
                   1107:      * changes.
                   1108:      */
                   1109: 
                   1110:     if (winPtr->flags & TK_NEED_CONFIG_NOTIFY) {
                   1111:        winPtr->flags &= ~TK_NEED_CONFIG_NOTIFY;
                   1112:        DoConfigureNotify(winPtr);
                   1113:     }
                   1114: }
                   1115: 
                   1116: /*
                   1117:  *--------------------------------------------------------------
                   1118:  *
                   1119:  * Tk_UnmapWindow, etc. --
                   1120:  *
                   1121:  *     There are several procedures under here, each of which
                   1122:  *     mirrors an existing X procedure.  In addition to performing
                   1123:  *     the functions of the corresponding procedure, each
                   1124:  *     procedure also updates the local window structure and
                   1125:  *     synthesizes an X event (if the window's structure is being
                   1126:  *     managed internally).
                   1127:  *
                   1128:  * Results:
                   1129:  *     See the manual entries.
                   1130:  *
                   1131:  * Side effects:
                   1132:  *     See the manual entries.
                   1133:  *
                   1134:  *--------------------------------------------------------------
                   1135:  */
                   1136: 
                   1137: void
                   1138: Tk_UnmapWindow(tkwin)
                   1139:     Tk_Window tkwin;           /* Token for window to unmap. */
                   1140: {
                   1141:     register TkWindow *winPtr = (TkWindow *) tkwin;
                   1142: 
                   1143:     if (!(winPtr->flags & TK_MAPPED)) {
                   1144:        return;
                   1145:     }
                   1146:     winPtr->flags &= ~TK_MAPPED;
                   1147:     XUnmapWindow(winPtr->display, winPtr->window);
                   1148:     if (!(winPtr->flags & TK_TOP_LEVEL)) {
                   1149:        XEvent event;
                   1150: 
                   1151:        event.type = UnmapNotify;
                   1152:        event.xunmap.serial = LastKnownRequestProcessed(winPtr->display);
                   1153:        event.xunmap.send_event = False;
                   1154:        event.xunmap.display = winPtr->display;
                   1155:        event.xunmap.event = winPtr->window;
                   1156:        event.xunmap.window = winPtr->window;
                   1157:        event.xunmap.from_configure = False;
                   1158:        Tk_HandleEvent(&event);
                   1159:     }
                   1160: }
                   1161: 
                   1162: void
                   1163: Tk_ConfigureWindow(tkwin, valueMask, valuePtr)
                   1164:     Tk_Window tkwin;           /* Window to re-configure. */
                   1165:     unsigned int valueMask;    /* Mask indicating which parts of
                   1166:                                 * *valuePtr are to be used. */
                   1167:     XWindowChanges *valuePtr;  /* New values. */
                   1168: {
                   1169:     register TkWindow *winPtr = (TkWindow *) tkwin;
                   1170: 
                   1171:     if ((winPtr->window == None) || !(winPtr->flags & TK_TOP_LEVEL)) {
                   1172:        if (valueMask & CWX) {
                   1173:            winPtr->changes.x = valuePtr->x;
                   1174:        }
                   1175:        if (valueMask & CWY) {
                   1176:            winPtr->changes.y = valuePtr->y;
                   1177:        }
                   1178:        if (valueMask & CWWidth) {
                   1179:            winPtr->changes.width = valuePtr->width;
                   1180:        }
                   1181:        if (valueMask & CWHeight) {
                   1182:            winPtr->changes.height = valuePtr->height;
                   1183:        }
                   1184:        if (valueMask & CWBorderWidth) {
                   1185:            winPtr->changes.border_width = valuePtr->border_width;
                   1186:        }
                   1187:        if (valueMask & CWSibling) {
                   1188:            winPtr->changes.sibling = valuePtr->sibling;
                   1189:        }
                   1190:        if (valueMask & CWStackMode) {
                   1191:            winPtr->changes.stack_mode = valuePtr->stack_mode;
                   1192:        }
                   1193:     }
                   1194: 
                   1195:     if (winPtr->window != None) {
                   1196:        XConfigureWindow(winPtr->display, winPtr->window,
                   1197:                valueMask, valuePtr);
                   1198:        if (!(winPtr->flags & TK_TOP_LEVEL)) {
                   1199:            DoConfigureNotify(winPtr);
                   1200:        }
                   1201:     } else {
                   1202:        winPtr->dirtyChanges |= valueMask;
                   1203:        winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
                   1204:     }
                   1205: }
                   1206: 
                   1207: void
                   1208: Tk_MoveWindow(tkwin, x, y)
                   1209:     Tk_Window tkwin;           /* Window to move. */
                   1210:     int x, y;                  /* New location for window (within
                   1211:                                 * parent). */
                   1212: {
                   1213:     register TkWindow *winPtr = (TkWindow *) tkwin;
                   1214: 
                   1215:     if (winPtr->window != None) {
                   1216:        XMoveWindow(winPtr->display, winPtr->window, x, y);
                   1217:        if (!(winPtr->flags & TK_TOP_LEVEL)) {
                   1218:            winPtr->changes.x = x;
                   1219:            winPtr->changes.y = y;
                   1220:            DoConfigureNotify(winPtr);
                   1221:        }
                   1222:     } else {
                   1223:        winPtr->changes.x = x;
                   1224:        winPtr->changes.y = y;
                   1225:        winPtr->dirtyChanges |= CWX|CWY;
                   1226:        winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
                   1227:     }
                   1228: }
                   1229: 
                   1230: void
                   1231: Tk_ResizeWindow(tkwin, width, height)
                   1232:     Tk_Window tkwin;           /* Window to resize. */
                   1233:     unsigned int width, height;        /* New dimensions for window. */
                   1234: {
                   1235:     register TkWindow *winPtr = (TkWindow *) tkwin;
                   1236: 
                   1237:     if (winPtr->window != None) {
                   1238:        XResizeWindow(winPtr->display, winPtr->window, width, height);
                   1239:        if (!(winPtr->flags & TK_TOP_LEVEL)) {
                   1240:            winPtr->changes.width = width;
                   1241:            winPtr->changes.height = height;
                   1242:            DoConfigureNotify(winPtr);
                   1243:        }
                   1244:     } else {
                   1245:        winPtr->changes.width = width;
                   1246:        winPtr->changes.height = height;
                   1247:        winPtr->dirtyChanges |= CWWidth|CWHeight;
                   1248:        winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
                   1249:     }
                   1250: }
                   1251: 
                   1252: void
                   1253: Tk_MoveResizeWindow(tkwin, x, y, width, height)
                   1254:     Tk_Window tkwin;           /* Window to move and resize. */
                   1255:     int x, y;                  /* New location for window (within
                   1256:                                 * parent). */
                   1257:     unsigned int width, height;        /* New dimensions for window. */
                   1258: {
                   1259:     register TkWindow *winPtr = (TkWindow *) tkwin;
                   1260: 
                   1261:     if (winPtr->window != None) {
                   1262:        XMoveResizeWindow(winPtr->display, winPtr->window,
                   1263:                x, y, width, height);
                   1264:        if (!(winPtr->flags & TK_TOP_LEVEL)) {
                   1265:            winPtr->changes.x = x;
                   1266:            winPtr->changes.y = y;
                   1267:            winPtr->changes.width = width;
                   1268:            winPtr->changes.height = height;
                   1269:            DoConfigureNotify(winPtr);
                   1270:        }
                   1271:     } else {
                   1272:        winPtr->changes.x = x;
                   1273:        winPtr->changes.y = y;
                   1274:        winPtr->changes.width = width;
                   1275:        winPtr->changes.height = height;
                   1276:        winPtr->dirtyChanges |= CWX|CWY|CWWidth|CWHeight;
                   1277:        winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
                   1278:     }
                   1279: }
                   1280: 
                   1281: void
                   1282: Tk_SetWindowBorderWidth(tkwin, width)
                   1283:     Tk_Window tkwin;           /* Window to modify. */
                   1284:     int width;                 /* New border width for window. */
                   1285: {
                   1286:     register TkWindow *winPtr = (TkWindow *) tkwin;
                   1287: 
                   1288:     winPtr->changes.border_width = width;
                   1289:     if (winPtr->window != None) {
                   1290:        XSetWindowBorderWidth(winPtr->display, winPtr->window, width);
                   1291:        if (!(winPtr->flags & TK_TOP_LEVEL)) {
                   1292:            DoConfigureNotify(winPtr);
                   1293:        }
                   1294:     } else {
                   1295:        winPtr->dirtyChanges |= CWBorderWidth;
                   1296:        winPtr->flags |= TK_NEED_CONFIG_NOTIFY;
                   1297:     }
                   1298: }
                   1299: 
                   1300: void
                   1301: Tk_ChangeWindowAttributes(tkwin, valueMask, attsPtr)
                   1302:     Tk_Window tkwin;           /* Window to manipulate. */
                   1303:     unsigned long valueMask;   /* OR'ed combination of bits,
                   1304:                                 * indicating which fields of
                   1305:                                 * *attsPtr are to be used. */
                   1306:     register XSetWindowAttributes *attsPtr;
                   1307:                                /* New values for some attributes. */
                   1308: {
                   1309:     register TkWindow *winPtr = (TkWindow *) tkwin;
                   1310: 
                   1311:     if (valueMask & CWBackPixmap) {
                   1312:        winPtr->atts.background_pixmap = attsPtr->background_pixmap;
                   1313:     }
                   1314:     if (valueMask & CWBackPixel) {
                   1315:        winPtr->atts.background_pixel = attsPtr->background_pixel;
                   1316:     }
                   1317:     if (valueMask & CWBorderPixmap) {
                   1318:        winPtr->atts.border_pixmap = attsPtr->border_pixmap;
                   1319:     }
                   1320:     if (valueMask & CWBorderPixel) {
                   1321:        winPtr->atts.border_pixel = attsPtr->border_pixel;
                   1322:     }
                   1323:     if (valueMask & CWBitGravity) {
                   1324:        winPtr->atts.bit_gravity = attsPtr->bit_gravity;
                   1325:     }
                   1326:     if (valueMask & CWWinGravity) {
                   1327:        winPtr->atts.win_gravity = attsPtr->win_gravity;
                   1328:     }
                   1329:     if (valueMask & CWBackingStore) {
                   1330:        winPtr->atts.backing_store = attsPtr->backing_store;
                   1331:     }
                   1332:     if (valueMask & CWBackingPlanes) {
                   1333:        winPtr->atts.backing_planes = attsPtr->backing_planes;
                   1334:     }
                   1335:     if (valueMask & CWBackingPixel) {
                   1336:        winPtr->atts.backing_pixel = attsPtr->backing_pixel;
                   1337:     }
                   1338:     if (valueMask & CWOverrideRedirect) {
                   1339:        winPtr->atts.override_redirect = attsPtr->override_redirect;
                   1340:     }
                   1341:     if (valueMask & CWSaveUnder) {
                   1342:        winPtr->atts.save_under = attsPtr->save_under;
                   1343:     }
                   1344:     if (valueMask & CWEventMask) {
                   1345:        winPtr->atts.event_mask = attsPtr->event_mask;
                   1346:     }
                   1347:     if (valueMask & CWDontPropagate) {
                   1348:        winPtr->atts.do_not_propagate_mask
                   1349:                = attsPtr->do_not_propagate_mask;
                   1350:     }
                   1351:     if (valueMask & CWColormap) {
                   1352:        winPtr->atts.colormap = attsPtr->colormap;
                   1353:     }
                   1354:     if (valueMask & CWCursor) {
                   1355:        winPtr->atts.cursor = attsPtr->cursor;
                   1356:     }
                   1357: 
                   1358:     if (winPtr->window != None) {
                   1359:        XChangeWindowAttributes(winPtr->display, winPtr->window,
                   1360:                valueMask, attsPtr);
                   1361:     } else {
                   1362:        winPtr->dirtyAtts |= valueMask;
                   1363:     }
                   1364: }
                   1365: 
                   1366: void
                   1367: Tk_SetWindowBackground(tkwin, pixel)
                   1368:     Tk_Window tkwin;           /* Window to manipulate. */
                   1369:     unsigned long pixel;       /* Pixel value to use for
                   1370:                                 * window's background. */
                   1371: {
                   1372:     register TkWindow *winPtr = (TkWindow *) tkwin;
                   1373: 
                   1374:     winPtr->atts.background_pixel = pixel;
                   1375: 
                   1376:     if (winPtr->window != None) {
                   1377:        XSetWindowBackground(winPtr->display, winPtr->window, pixel);
                   1378:     } else {
                   1379:        winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBackPixmap)
                   1380:                | CWBackPixel;
                   1381:     }
                   1382: }
                   1383: 
                   1384: void
                   1385: Tk_SetWindowBackgroundPixmap(tkwin, pixmap)
                   1386:     Tk_Window tkwin;           /* Window to manipulate. */
                   1387:     Pixmap pixmap;             /* Pixmap to use for window's
                   1388:                                 * background. */
                   1389: {
                   1390:     register TkWindow *winPtr = (TkWindow *) tkwin;
                   1391: 
                   1392:     winPtr->atts.background_pixmap = pixmap;
                   1393: 
                   1394:     if (winPtr->window != None) {
                   1395:        XSetWindowBackgroundPixmap(winPtr->display,
                   1396:                winPtr->window, pixmap);
                   1397:     } else {
                   1398:        winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBackPixel)
                   1399:                | CWBackPixmap;
                   1400:     }
                   1401: }
                   1402: 
                   1403: void
                   1404: Tk_SetWindowBorder(tkwin, pixel)
                   1405:     Tk_Window tkwin;           /* Window to manipulate. */
                   1406:     unsigned long pixel;       /* Pixel value to use for
                   1407:                                 * window's border. */
                   1408: {
                   1409:     register TkWindow *winPtr = (TkWindow *) tkwin;
                   1410: 
                   1411:     winPtr->atts.border_pixel = pixel;
                   1412: 
                   1413:     if (winPtr->window != None) {
                   1414:        XSetWindowBorder(winPtr->display, winPtr->window, pixel);
                   1415:     } else {
                   1416:        winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBorderPixmap)
                   1417:                | CWBorderPixel;
                   1418:     }
                   1419: }
                   1420: 
                   1421: void
                   1422: Tk_SetWindowBorderPixmap(tkwin, pixmap)
                   1423:     Tk_Window tkwin;           /* Window to manipulate. */
                   1424:     Pixmap pixmap;             /* Pixmap to use for window's
                   1425:                                 * border. */
                   1426: {
                   1427:     register TkWindow *winPtr = (TkWindow *) tkwin;
                   1428: 
                   1429:     winPtr->atts.border_pixmap = pixmap;
                   1430: 
                   1431:     if (winPtr->window != None) {
                   1432:        XSetWindowBorderPixmap(winPtr->display,
                   1433:                winPtr->window, pixmap);
                   1434:     } else {
                   1435:        winPtr->dirtyAtts = (winPtr->dirtyAtts & ~CWBorderPixel)
                   1436:                | CWBorderPixmap;
                   1437:     }
                   1438: }
                   1439: 
                   1440: void
                   1441: Tk_DefineCursor(tkwin, cursor)
                   1442:     Tk_Window tkwin;           /* Window to manipulate. */
                   1443:     Cursor cursor;             /* Cursor to use for window (may be None). */
                   1444: {
                   1445:     register TkWindow *winPtr = (TkWindow *) tkwin;
                   1446: 
                   1447:     winPtr->atts.cursor = cursor;
                   1448: 
                   1449:     if (winPtr->window != None) {
                   1450:        XDefineCursor(winPtr->display, winPtr->window, cursor);
                   1451:     } else {
                   1452:        winPtr->dirtyAtts = winPtr->dirtyAtts | CWCursor;
                   1453:     }
                   1454: }
                   1455: 
                   1456: void
                   1457: Tk_UndefineCursor(tkwin)
                   1458:     Tk_Window tkwin;           /* Window to manipulate. */
                   1459: {
                   1460:     Tk_DefineCursor(tkwin, None);
                   1461: }
                   1462: 
                   1463: /*
                   1464:  *----------------------------------------------------------------------
                   1465:  *
                   1466:  * DoConfigureNotify --
                   1467:  *
                   1468:  *     Generate a ConfigureNotify event describing the current
                   1469:  *     configuration of a window.
                   1470:  *
                   1471:  * Results:
                   1472:  *     None.
                   1473:  *
                   1474:  * Side effects:
                   1475:  *     An event is generated and processed by Tk_HandleEvent.
                   1476:  *
                   1477:  *----------------------------------------------------------------------
                   1478:  */
                   1479: 
                   1480: static void
                   1481: DoConfigureNotify(winPtr)
                   1482:     register TkWindow *winPtr;         /* Window whose configuration
                   1483:                                         * was just changed. */
                   1484: {
                   1485:     XEvent event;
                   1486: 
                   1487:     event.type = ConfigureNotify;
                   1488:     event.xconfigure.serial = LastKnownRequestProcessed(winPtr->display);
                   1489:     event.xconfigure.send_event = False;
                   1490:     event.xconfigure.display = winPtr->display;
                   1491:     event.xconfigure.event = winPtr->window;
                   1492:     event.xconfigure.window = winPtr->window;
                   1493:     event.xconfigure.x = winPtr->changes.x;
                   1494:     event.xconfigure.y = winPtr->changes.y;
                   1495:     event.xconfigure.width = winPtr->changes.width;
                   1496:     event.xconfigure.height = winPtr->changes.height;
                   1497:     event.xconfigure.border_width = winPtr->changes.border_width;
                   1498:     if (winPtr->changes.stack_mode == Above) {
                   1499:        event.xconfigure.above = winPtr->changes.sibling;
                   1500:     } else {
                   1501:        event.xconfigure.above = None;
                   1502:     }
                   1503:     event.xconfigure.override_redirect = winPtr->atts.override_redirect;
                   1504:     Tk_HandleEvent(&event);
                   1505: }
                   1506: 
                   1507: /*
                   1508:  *----------------------------------------------------------------------
                   1509:  *
                   1510:  * Tk_SetClass --
                   1511:  *
                   1512:  *     This procedure is used to give a window a class.
                   1513:  *
                   1514:  * Results:
                   1515:  *     None.
                   1516:  *
                   1517:  * Side effects:
                   1518:  *     A new class is stored for tkwin, replacing any existing
                   1519:  *     class for it.
                   1520:  *
                   1521:  *----------------------------------------------------------------------
                   1522:  */
                   1523: 
                   1524: void
                   1525: Tk_SetClass(tkwin, className)
                   1526:     Tk_Window tkwin;           /* Token for window to assign class. */
                   1527:     char *className;           /* New class for tkwin. */
                   1528: {
                   1529:     register TkWindow *winPtr = (TkWindow *) tkwin;
                   1530: 
                   1531:     winPtr->classUid = Tk_GetUid(className);
                   1532:     if (winPtr->flags & TK_TOP_LEVEL) {
                   1533:        TkWmSetClass(winPtr);
                   1534:     }
                   1535: }
                   1536: 
                   1537: /*
                   1538:  *----------------------------------------------------------------------
                   1539:  *
                   1540:  * Tk_NameToWindow --
                   1541:  *
                   1542:  *     Given a string name for a window, this procedure
                   1543:  *     returns the token for the window, if there exists a
                   1544:  *     window corresponding to the given name.
                   1545:  *
                   1546:  * Results:
                   1547:  *     The return result is either a token for the window corresponding
                   1548:  *     to "name", or else NULL to indicate that there is no such
                   1549:  *     window.  In this case, an error message is left in interp->result.
                   1550:  *
                   1551:  * Side effects:
                   1552:  *     None.
                   1553:  *
                   1554:  *----------------------------------------------------------------------
                   1555:  */
                   1556: 
                   1557: Tk_Window
                   1558: Tk_NameToWindow(interp, pathName, tkwin)
                   1559:     Tcl_Interp *interp;                /* Where to report errors. */
                   1560:     char *pathName;            /* Path name of window. */
                   1561:     Tk_Window tkwin;           /* Token for window:  name is assumed to
                   1562:                                 * belong to the same main window as tkwin. */
                   1563: {
                   1564:     Tcl_HashEntry *hPtr;
                   1565: 
                   1566:     hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->nameTable,
                   1567:            pathName);
                   1568:     if (hPtr == NULL) {
                   1569:        Tcl_AppendResult(interp, "bad window path name \"",
                   1570:                pathName, "\"", (char *) NULL);
                   1571:        return NULL;
                   1572:     }
                   1573:     return (Tk_Window) Tcl_GetHashValue(hPtr);
                   1574: }
                   1575: 
                   1576: /*
                   1577:  *----------------------------------------------------------------------
                   1578:  *
                   1579:  * Tk_DisplayName --
                   1580:  *
                   1581:  *     Return the textual name of a window's display.
                   1582:  *
                   1583:  * Results:
                   1584:  *     The return value is the string name of the display associated
                   1585:  *     with tkwin.
                   1586:  *
                   1587:  * Side effects:
                   1588:  *     None.
                   1589:  *
                   1590:  *----------------------------------------------------------------------
                   1591:  */
                   1592: 
                   1593: char *
                   1594: Tk_DisplayName(tkwin)
                   1595:     Tk_Window tkwin;           /* Window whose display name is desired. */
                   1596: {
                   1597:     return ((TkWindow *) tkwin)->dispPtr->name;
                   1598: }

unix.superglobalmegacorp.com

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