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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.25  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25