tkFrame.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:60k
- /*
- * tkFrame.c --
- *
- * This module implements "frame", "labelframe" 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.15.2.4 2007/04/29 02:24:02 das Exp $
- */
- #include "default.h"
- #include "tkPort.h"
- #include "tkInt.h"
- /*
- * The following enum is used to define the type of the frame.
- */
- enum FrameType {
- TYPE_FRAME, TYPE_TOPLEVEL, TYPE_LABELFRAME
- };
- /*
- * 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. */
- Tk_OptionTable optionTable; /* Table that defines configuration options
- * available for this widget. */
- char *className; /* Class name for widget (from configuration
- * option). Malloc-ed. */
- enum FrameType type; /* Type of widget, such as TYPE_FRAME. */
- 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. */
- Tcl_Obj *padXPtr; /* Value of -padx option: specifies how many
- * pixels of extra space to leave on left and
- * right of child area. */
- int padX; /* Integer value corresponding to padXPtr. */
- Tcl_Obj *padYPtr; /* Value of -padx option: specifies how many
- * pixels of extra space to leave above and
- * below child area. */
- int padY; /* Integer value corresponding to padYPtr. */
- } Frame;
- /*
- * A data structure of the following type is kept for each labelframe
- * widget managed by this file:
- */
- typedef struct {
- Frame frame; /* A pointer to the generic frame structure.
- * This must be the first element of the
- * Labelframe. */
- /*
- * Labelframe specific configuration settings.
- */
- Tcl_Obj *textPtr; /* Value of -text option: specifies text to
- * display in button. */
- Tk_Font tkfont; /* Value of -font option: specifies font
- * to use for display text. */
- XColor *textColorPtr; /* Value of -fg option: specifies foreground
- * color in normal mode. */
- int labelAnchor; /* Value of -labelanchor option: specifies
- * where to place the label. */
- Tk_Window labelWin; /* Value of -labelwidget option: Window to
- * use as label for the frame. */
- /*
- * Labelframe specific fields for use with configuration settings above.
- */
- GC textGC; /* GC for drawing text in normal mode. */
- Tk_TextLayout textLayout; /* Stored text layout information. */
- XRectangle labelBox; /* The label's actual size and position. */
- int labelReqWidth; /* The label's requested width. */
- int labelReqHeight; /* The label's requested height. */
- int labelTextX, labelTextY; /* Position of the text to be drawn. */
- } Labelframe;
- /*
- * The following macros define how many extra pixels to leave
- * around a label's text.
- */
- #define LABELSPACING 1
- #define LABELMARGIN 4
- /*
- * 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 enum is used to define a type for the -labelanchor option
- * of the Labelframe widget. These values are used as indices into the
- * string table below.
- */
- enum labelanchor {
- LABELANCHOR_E, LABELANCHOR_EN, LABELANCHOR_ES,
- LABELANCHOR_N, LABELANCHOR_NE, LABELANCHOR_NW,
- LABELANCHOR_S, LABELANCHOR_SE, LABELANCHOR_SW,
- LABELANCHOR_W, LABELANCHOR_WN, LABELANCHOR_WS
- };
- static char *labelAnchorStrings[] = {
- "e", "en", "es", "n", "ne", "nw", "s", "se", "sw", "w", "wn", "ws",
- (char *) NULL
- };
- /*
- * Information used for parsing configuration options. There are
- * one common table used by all and one table for each widget class.
- */
- static Tk_OptionSpec commonOptSpec[] = {
- {TK_OPTION_BORDER, "-background", "background", "Background",
- DEF_FRAME_BG_COLOR, -1, Tk_Offset(Frame, border),
- TK_OPTION_NULL_OK, (ClientData) DEF_FRAME_BG_MONO, 0},
- {TK_OPTION_SYNONYM, "-bg", (char *) NULL, (char *) NULL,
- (char *) NULL, 0, -1, 0, (ClientData) "-background", 0},
- {TK_OPTION_STRING, "-colormap", "colormap", "Colormap",
- DEF_FRAME_COLORMAP, -1, Tk_Offset(Frame, colormapName),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_BOOLEAN, "-container", "container", "Container",
- DEF_FRAME_CONTAINER, -1, Tk_Offset(Frame, isContainer),
- 0, 0, 0},
- {TK_OPTION_CURSOR, "-cursor", "cursor", "Cursor",
- DEF_FRAME_CURSOR, -1, Tk_Offset(Frame, cursor),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_PIXELS, "-height", "height", "Height",
- DEF_FRAME_HEIGHT, -1, Tk_Offset(Frame, height),
- 0, 0, 0},
- {TK_OPTION_COLOR, "-highlightbackground", "highlightBackground",
- "HighlightBackground", DEF_FRAME_HIGHLIGHT_BG, -1,
- Tk_Offset(Frame, highlightBgColorPtr), 0, 0, 0},
- {TK_OPTION_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
- DEF_FRAME_HIGHLIGHT, -1, Tk_Offset(Frame, highlightColorPtr),
- 0, 0, 0},
- {TK_OPTION_PIXELS, "-highlightthickness", "highlightThickness",
- "HighlightThickness", DEF_FRAME_HIGHLIGHT_WIDTH, -1,
- Tk_Offset(Frame, highlightWidth), 0, 0, 0},
- {TK_OPTION_PIXELS, "-padx", "padX", "Pad",
- DEF_FRAME_PADX, Tk_Offset(Frame, padXPtr),
- Tk_Offset(Frame, padX), 0, 0, 0},
- {TK_OPTION_PIXELS, "-pady", "padY", "Pad",
- DEF_FRAME_PADY, Tk_Offset(Frame, padYPtr),
- Tk_Offset(Frame, padY), 0, 0, 0},
- {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
- DEF_FRAME_TAKE_FOCUS, -1, Tk_Offset(Frame, takeFocus),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_STRING, "-visual", "visual", "Visual",
- DEF_FRAME_VISUAL, -1, Tk_Offset(Frame, visualName),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_PIXELS, "-width", "width", "Width",
- DEF_FRAME_WIDTH, -1, Tk_Offset(Frame, width),
- 0, 0, 0},
- {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, 0, 0, 0, 0}
- };
- static Tk_OptionSpec frameOptSpec[] = {
- {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
- (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
- {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
- DEF_FRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth),
- 0, 0, 0},
- {TK_OPTION_STRING, "-class", "class", "Class",
- DEF_FRAME_CLASS, -1, Tk_Offset(Frame, className),
- 0, 0, 0},
- {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
- DEF_FRAME_RELIEF, -1, Tk_Offset(Frame, relief),
- 0, 0, 0},
- {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, 0, 0, (ClientData) commonOptSpec, 0}
- };
- static Tk_OptionSpec toplevelOptSpec[] = {
- {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
- (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
- {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
- DEF_FRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth),
- 0, 0, 0},
- {TK_OPTION_STRING, "-class", "class", "Class",
- DEF_TOPLEVEL_CLASS, -1, Tk_Offset(Frame, className),
- 0, 0, 0},
- {TK_OPTION_STRING, "-menu", "menu", "Menu",
- DEF_TOPLEVEL_MENU, -1, Tk_Offset(Frame, menuName),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
- DEF_FRAME_RELIEF, -1, Tk_Offset(Frame, relief),
- 0, 0, 0},
- {TK_OPTION_STRING, "-screen", "screen", "Screen",
- DEF_TOPLEVEL_SCREEN, -1, Tk_Offset(Frame, screenName),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_STRING, "-use", "use", "Use",
- DEF_TOPLEVEL_USE, -1, Tk_Offset(Frame, useThis),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, 0, 0, (ClientData) commonOptSpec, 0}
- };
- static Tk_OptionSpec labelframeOptSpec[] = {
- {TK_OPTION_SYNONYM, "-bd", (char *) NULL, (char *) NULL,
- (char *) NULL, 0, -1, 0, (ClientData) "-borderwidth", 0},
- {TK_OPTION_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
- DEF_LABELFRAME_BORDER_WIDTH, -1, Tk_Offset(Frame, borderWidth),
- 0, 0, 0},
- {TK_OPTION_STRING, "-class", "class", "Class",
- DEF_LABELFRAME_CLASS, -1, Tk_Offset(Frame, className),
- 0, 0, 0},
- {TK_OPTION_SYNONYM, "-fg", "foreground", (char *) NULL,
- (char *) NULL, 0, -1, 0, (ClientData) "-foreground", 0},
- {TK_OPTION_FONT, "-font", "font", "Font",
- DEF_LABELFRAME_FONT, -1, Tk_Offset(Labelframe, tkfont), 0, 0, 0},
- {TK_OPTION_COLOR, "-foreground", "foreground", "Foreground",
- DEF_LABELFRAME_FG, -1, Tk_Offset(Labelframe, textColorPtr), 0, 0, 0},
- {TK_OPTION_STRING_TABLE, "-labelanchor", "labelAnchor", "LabelAnchor",
- DEF_LABELFRAME_LABELANCHOR, -1, Tk_Offset(Labelframe, labelAnchor),
- 0, (ClientData) labelAnchorStrings, 0},
- {TK_OPTION_WINDOW, "-labelwidget", "labelWidget", "LabelWidget",
- (char *) NULL, -1, Tk_Offset(Labelframe, labelWin),
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_RELIEF, "-relief", "relief", "Relief",
- DEF_LABELFRAME_RELIEF, -1, Tk_Offset(Frame, relief),
- 0, 0, 0},
- {TK_OPTION_STRING, "-text", "text", "Text",
- DEF_LABELFRAME_TEXT, Tk_Offset(Labelframe, textPtr), -1,
- TK_OPTION_NULL_OK, 0, 0},
- {TK_OPTION_END, (char *) NULL, (char *) NULL, (char *) NULL,
- (char *) NULL, 0, 0, 0, (ClientData) commonOptSpec, 0}
- };
- /*
- * Class names for widgets, indexed by FrameType.
- */
- static char *classNames[] = {"Frame", "Toplevel", "Labelframe"};
- /*
- * The following table maps from FrameType to the option template for
- * that class of widgets.
- */
- static Tk_OptionSpec *optionSpecs[] = {
- frameOptSpec,
- toplevelOptSpec,
- labelframeOptSpec,
- };
- /*
- * Forward declarations for procedures defined later in this file:
- */
- static void ComputeFrameGeometry _ANSI_ARGS_((Frame *framePtr));
- static int ConfigureFrame _ANSI_ARGS_((Tcl_Interp *interp,
- Frame *framePtr, int objc, Tcl_Obj *CONST objv[]));
- static int CreateFrame _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST argv[],
- enum FrameType type, char *appName));
- static void DestroyFrame _ANSI_ARGS_((char *memPtr));
- static void DestroyFramePartly _ANSI_ARGS_((Frame *framePtr));
- static void DisplayFrame _ANSI_ARGS_((ClientData clientData));
- static void FrameCmdDeletedProc _ANSI_ARGS_((
- ClientData clientData));
- static void FrameEventProc _ANSI_ARGS_((ClientData clientData,
- XEvent *eventPtr));
- static void FrameLostSlaveProc _ANSI_ARGS_((
- ClientData clientData, Tk_Window tkwin));
- static void FrameRequestProc _ANSI_ARGS_((ClientData clientData,
- Tk_Window tkwin));
- static void FrameStructureProc _ANSI_ARGS_((
- ClientData clientData, XEvent *eventPtr));
- static int FrameWidgetObjCmd _ANSI_ARGS_((ClientData clientData,
- Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
- static void FrameWorldChanged _ANSI_ARGS_((
- ClientData instanceData));
- static void MapFrame _ANSI_ARGS_((ClientData clientData));
- /*
- * The structure below defines frame class behavior by means of procedures
- * that can be invoked from generic window code.
- */
- static Tk_ClassProcs frameClass = {
- sizeof(Tk_ClassProcs), /* size */
- FrameWorldChanged /* worldChangedProc */
- };
- /*
- * The structure below defines the official type record for the
- * labelframe's geometry manager:
- */
- static Tk_GeomMgr frameGeomType = {
- "labelframe", /* name */
- FrameRequestProc, /* requestProc */
- FrameLostSlaveProc /* lostSlaveProc */
- };
- /*
- *--------------------------------------------------------------
- *
- * Tk_FrameObjCmd, Tk_ToplevelObjCmd, Tk_LabelframeObjCmd --
- *
- * These procedures are invoked to process the "frame",
- * "toplevel" and "labelframe" 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 CreateFrame to do all of the real work.
- *
- *--------------------------------------------------------------
- */
- int
- Tk_FrameObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Either NULL or pointer to option table. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
- {
- return CreateFrame(clientData, interp, objc, objv, TYPE_FRAME,
- (char *) NULL);
- }
- int
- Tk_ToplevelObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Either NULL or pointer to option table. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
- {
- return CreateFrame(clientData, interp, objc, objv, TYPE_TOPLEVEL,
- (char *) NULL);
- }
- int
- Tk_LabelframeObjCmd(clientData, interp, objc, objv)
- ClientData clientData; /* Either NULL or pointer to option table. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
- {
- return CreateFrame(clientData, interp, objc, objv, TYPE_LABELFRAME,
- (char *) NULL);
- }
- /*
- *--------------------------------------------------------------
- *
- * TkCreateFrame --
- *
- * This procedure is the old command procedure for the "frame"
- * and "toplevel" commands. Now it is used 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; /* Either NULL or pointer to option table. */
- 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 there is no main
- * window associated with the interpreter.
- * 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 ? TYPE_TOPLEVEL : TYPE_FRAME, appName);
- for (i=0; i<argc; i++) {
- Tcl_DecrRefCount(objv[i]);
- }
- ckfree((char *) objv);
- return result;
- }
- static int
- CreateFrame(clientData, interp, objc, objv, type, appName)
- ClientData clientData; /* NULL. */
- Tcl_Interp *interp; /* Current interpreter. */
- int objc; /* Number of arguments. */
- Tcl_Obj *CONST objv[]; /* Argument objects. */
- enum FrameType type; /* What widget type to create. */
- char *appName; /* Should only be non-NULL if there are no
- * Main window associated with the interpreter.
- * Gives the base name to use for the
- * new application. */
- {
- Tk_Window tkwin;
- Frame *framePtr;
- Tk_OptionTable optionTable;
- Tk_Window new;
- CONST char *className, *screenName, *visualName, *colormapName, *arg, *useOption;
- int i, c, depth, length;
- unsigned int mask;
- Colormap colormap;
- Visual *visual;
- if (objc < 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?");
- return TCL_ERROR;
- }
- /*
- * Create the option table for this widget class. If it has already
- * been created, the cached pointer will be returned.
- */
- optionTable = Tk_CreateOptionTable(interp, optionSpecs[type]);
- /*
- * 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], &length);
- if (length < 2) {
- continue;
- }
- c = arg[1];
- if ((c == 'c') && (strncmp(arg, "-class", (unsigned) length) == 0)
- && (length >= 3)) {
- className = Tcl_GetString(objv[i+1]);
- } else if ((c == 'c')
- && (strncmp(arg, "-colormap", (unsigned) length) == 0)) {
- colormapName = Tcl_GetString(objv[i+1]);
- } else if ((c == 's') && (type == TYPE_TOPLEVEL)
- && (strncmp(arg, "-screen", (unsigned) length) == 0)) {
- screenName = Tcl_GetString(objv[i+1]);
- } else if ((c == 'u') && (type == TYPE_TOPLEVEL)
- && (strncmp(arg, "-use", (unsigned) length) == 0)) {
- useOption = Tcl_GetString(objv[i+1]);
- } else if ((c == 'v')
- && (strncmp(arg, "-visual", (unsigned) 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 = (type == TYPE_TOPLEVEL) ? "" : NULL;
- }
- /*
- * Main window associated with interpreter.
- * If we're called by Tk_Init to create a
- * new application, then this is NULL.
- */
- tkwin = Tk_MainWindow(interp);
- if (tkwin != NULL) {
- new = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]),
- screenName);
- } else if (appName == NULL) {
- /*
- * This occurs when someone tried to create a frame/toplevel
- * while we are being destroyed. Let an error be thrown.
- */
- Tcl_AppendResult(interp, "unable to create widget "",
- Tcl_GetString(objv[1]), """, (char *) NULL);
- new = NULL;
- } else {
- /*
- * We were called from Tk_Init; create a new application.
- */
- new = TkCreateMainWindow(interp, screenName, appName);
- }
- if (new == NULL) {
- goto error;
- }
- if (className == NULL) {
- className = Tk_GetOption(new, "class", "Class");
- if (className == NULL) {
- className = classNames[type];
- }
- }
- Tk_SetClass(new, className);
- if (useOption == NULL) {
- useOption = Tk_GetOption(new, "use", "Use");
- }
- if ((useOption != NULL) && (*useOption != 0)) {
- 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 ((colormapName != NULL) && (*colormapName == 0)) {
- colormapName = NULL;
- }
- 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 (type == TYPE_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.
- */
- if (type == TYPE_LABELFRAME) {
- framePtr = (Frame *) ckalloc(sizeof(Labelframe));
- memset((void *) framePtr, 0, (sizeof(Labelframe)));
- } else {
- framePtr = (Frame *) ckalloc(sizeof(Frame));
- memset((void *) framePtr, 0, (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->optionTable = optionTable;
- framePtr->type = type;
- framePtr->colormap = colormap;
- framePtr->relief = TK_RELIEF_FLAT;
- framePtr->cursor = None;
- if (framePtr->type == TYPE_LABELFRAME) {
- Labelframe *labelframePtr = (Labelframe *) framePtr;
- labelframePtr->labelAnchor = LABELANCHOR_NW;
- labelframePtr->textGC = None;
- }
- /*
- * Store backreference to frame widget in window structure.
- */
- Tk_SetClassProcs(new, &frameClass, (ClientData) framePtr);
- mask = ExposureMask | StructureNotifyMask | FocusChangeMask;
- if (type == TYPE_TOPLEVEL) {
- mask |= ActivateMask;
- }
- Tk_CreateEventHandler(new, mask, FrameEventProc, (ClientData) framePtr);
- if ((Tk_InitOptions(interp, (char *) framePtr, optionTable, new)
- != TCL_OK) ||
- (ConfigureFrame(interp, framePtr, objc-2, objv+2) != 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.", (char *) NULL);
- goto error;
- }
- }
- if (type == TYPE_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 CONST char *frameOptions[] = {
- "cget", "configure", (char *) NULL
- };
- enum options {
- FRAME_CGET, FRAME_CONFIGURE
- };
- register Frame *framePtr = (Frame *) clientData;
- int result = TCL_OK, index;
- int c, i, length;
- Tcl_Obj *objPtr;
- 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;
- }
- objPtr = Tk_GetOptionValue(interp, (char *) framePtr,
- framePtr->optionTable, objv[2], framePtr->tkwin);
- if (objPtr == NULL) {
- result = TCL_ERROR;
- goto done;
- } else {
- Tcl_SetObjResult(interp, objPtr);
- }
- break;
- }
- case FRAME_CONFIGURE: {
- if (objc <= 3) {
- objPtr = Tk_GetOptionInfo(interp, (char *) framePtr,
- framePtr->optionTable,
- (objc == 3) ? objv[2] : (Tcl_Obj *) NULL,
- framePtr->tkwin);
- if (objPtr == NULL) {
- result = TCL_ERROR;
- goto done;
- } else {
- Tcl_SetObjResult(interp, objPtr);
- }
- } 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], &length);
- if (length < 2) {
- continue;
- }
- c = arg[1];
- if (((c == 'c')
- && (strncmp(arg, "-class", (unsigned) length) == 0)
- && (length >= 2))
- || ((c == 'c')
- && (strncmp(arg, "-colormap", (unsigned) length) == 0)
- && (length >= 3))
- || ((c == 'c')
- && (strncmp(arg, "-container", (unsigned) length) == 0)
- && (length >= 3))
- || ((c == 's') && (framePtr->type == TYPE_TOPLEVEL)
- && (strncmp(arg, "-screen", (unsigned) length) == 0))
- || ((c == 'u') && (framePtr->type == TYPE_TOPLEVEL)
- && (strncmp(arg, "-use", (unsigned) length) == 0))
- || ((c == 'v')
- && (strncmp(arg, "-visual", (unsigned) 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);
- }
- 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;
- register Labelframe *labelframePtr = (Labelframe *) memPtr;
- if (framePtr->type == TYPE_LABELFRAME) {
- Tk_FreeTextLayout(labelframePtr->textLayout);
- if (labelframePtr->textGC != None) {
- Tk_FreeGC(framePtr->display, labelframePtr->textGC);
- }
- }
- if (framePtr->colormap != None) {
- Tk_FreeColormap(framePtr->display, framePtr->colormap);
- }
- ckfree((char *) framePtr);
- }
- /*
- *----------------------------------------------------------------------
- *
- * DestroyFramePartly --
- *
- * This procedure is invoked to clean up everything that needs
- * tkwin to be defined when deleted. During the destruction
- * process tkwin is always set to NULL and this procedure must
- * be called before that happens.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Some things associated with the frame are freed up.
- *
- *----------------------------------------------------------------------
- */
- static void
- DestroyFramePartly(framePtr)
- Frame *framePtr; /* Info about frame widget. */
- {
- register Labelframe *labelframePtr = (Labelframe *) framePtr;
- if (framePtr->type == TYPE_LABELFRAME && labelframePtr->labelWin != NULL) {
- Tk_DeleteEventHandler(labelframePtr->labelWin, StructureNotifyMask,
- FrameStructureProc, (ClientData) framePtr);
- Tk_ManageGeometry(labelframePtr->labelWin, (Tk_GeomMgr *) NULL,
- (ClientData) NULL);
- if (framePtr->tkwin != Tk_Parent(labelframePtr->labelWin)) {
- Tk_UnmaintainGeometry(labelframePtr->labelWin, framePtr->tkwin);
- }
- Tk_UnmapWindow(labelframePtr->labelWin);
- labelframePtr->labelWin = NULL;
- }
- Tk_FreeConfigOptions((char *) framePtr, framePtr->optionTable,
- framePtr->tkwin);
- }
- /*
- *----------------------------------------------------------------------
- *
- * 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)
- 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. */
- {
- Tk_SavedOptions savedOptions;
- char *oldMenuName;
- Tk_Window oldWindow = NULL;
- Labelframe *labelframePtr = (Labelframe *) framePtr;
- /*
- * 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 (framePtr->type == TYPE_LABELFRAME) {
- oldWindow = labelframePtr->labelWin;
- }
- if (Tk_SetOptions(interp, (char *) framePtr,
- framePtr->optionTable, objc, objv,
- framePtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) {
- if (oldMenuName != NULL) {
- ckfree(oldMenuName);
- }
- return TCL_ERROR;
- } else {
- Tk_FreeSavedOptions(&savedOptions);
- }
- /*
- * A few of the options require additional processing.
- */
- 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 (oldMenuName != NULL) {
- ckfree(oldMenuName);
- }
- if (framePtr->border != NULL) {
- Tk_SetBackgroundFromBorder(framePtr->tkwin, framePtr->border);
- } else {
- Tk_SetWindowBackgroundPixmap(framePtr->tkwin, None);
- }
- if (framePtr->highlightWidth < 0) {
- framePtr->highlightWidth = 0;
- }
- if (framePtr->padX < 0) {
- framePtr->padX = 0;
- }
- if (framePtr->padY < 0) {
- framePtr->padY = 0;
- }
- /*
- * If a -labelwidget is specified, check that it is valid and set
- * up geometry management for it.
- */
- if (framePtr->type == TYPE_LABELFRAME) {
- if (oldWindow != labelframePtr->labelWin) {
- if (oldWindow != NULL) {
- Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,
- FrameStructureProc, (ClientData) framePtr);
- Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL,
- (ClientData) NULL);
- Tk_UnmaintainGeometry(oldWindow, framePtr->tkwin);
- Tk_UnmapWindow(oldWindow);
- }
- if (labelframePtr->labelWin != NULL) {
- Tk_Window ancestor, parent, sibling = NULL;
- /*
- * Make sure that the frame is either the parent of the
- * window used as label or a descendant of that
- * parent. Also, don't allow a top-level window to be
- * managed inside the frame.
- */
- parent = Tk_Parent(labelframePtr->labelWin);
- for (ancestor = framePtr->tkwin; ;
- ancestor = Tk_Parent(ancestor)) {
- if (ancestor == parent) {
- break;
- }
- sibling = ancestor;
- if (Tk_IsTopLevel(ancestor)) {
- badWindow:
- Tcl_AppendResult(interp, "can't use ",
- Tk_PathName(labelframePtr->labelWin),
- " as label in this frame", (char *) NULL);
- labelframePtr->labelWin = NULL;
- return TCL_ERROR;
- }
- }
- if (Tk_IsTopLevel(labelframePtr->labelWin)) {
- goto badWindow;
- }
- if (labelframePtr->labelWin == framePtr->tkwin) {
- goto badWindow;
- }
- Tk_CreateEventHandler(labelframePtr->labelWin,
- StructureNotifyMask, FrameStructureProc,
- (ClientData) framePtr);
- Tk_ManageGeometry(labelframePtr->labelWin, &frameGeomType,
- (ClientData) framePtr);
- /*
- * If the frame is not parent to the label, make
- * sure the label is above its sibling in the stacking
- * order.
- */
- if (sibling != NULL) {
- Tk_RestackWindow(labelframePtr->labelWin, Above, sibling);
- }
- }
- }
- }
- FrameWorldChanged((ClientData) framePtr);
- return TCL_OK;
- }
- /*
- *---------------------------------------------------------------------------
- *
- * FrameWorldChanged --
- *
- * This procedure is called when the world has changed in some
- * way and the widget needs to recompute all its graphics contexts
- * and determine its new geometry.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Frame will be relayed out and redisplayed.
- *
- *---------------------------------------------------------------------------
- */
-
- static void
- FrameWorldChanged(instanceData)
- ClientData instanceData; /* Information about widget. */
- {
- Frame *framePtr = (Frame *) instanceData;
- Labelframe *labelframePtr = (Labelframe *) framePtr;
- Tk_Window tkwin = framePtr->tkwin;
- XGCValues gcValues;
- GC gc;
- int anyTextLabel, anyWindowLabel;
- int bWidthLeft, bWidthRight, bWidthTop, bWidthBottom;
- char *labelText;
- anyTextLabel = (framePtr->type == TYPE_LABELFRAME) &&
- (labelframePtr->textPtr != NULL) &&
- (labelframePtr->labelWin == NULL);
- anyWindowLabel = (framePtr->type == TYPE_LABELFRAME) &&
- (labelframePtr->labelWin != NULL);
- if (framePtr->type == TYPE_LABELFRAME) {
- /*
- * The textGC is needed even in the labelWin case, so it's
- * always created for a labelframe.
- */
- gcValues.font = Tk_FontId(labelframePtr->tkfont);
- gcValues.foreground = labelframePtr->textColorPtr->pixel;
- gcValues.graphics_exposures = False;
- gc = Tk_GetGC(tkwin, GCForeground | GCFont | GCGraphicsExposures,
- &gcValues);
- if (labelframePtr->textGC != None) {
- Tk_FreeGC(framePtr->display, labelframePtr->textGC);
- }
- labelframePtr->textGC = gc;
- /*
- * Calculate label size.
- */
-
- labelframePtr->labelReqWidth = labelframePtr->labelReqHeight = 0;
- if (anyTextLabel) {
- labelText = Tcl_GetString(labelframePtr->textPtr);
- Tk_FreeTextLayout(labelframePtr->textLayout);
- labelframePtr->textLayout = Tk_ComputeTextLayout(labelframePtr->tkfont,
- labelText, -1, 0, TK_JUSTIFY_CENTER, 0,
- &labelframePtr->labelReqWidth, &labelframePtr->labelReqHeight);
- labelframePtr->labelReqWidth += 2 * LABELSPACING;
- labelframePtr->labelReqHeight += 2 * LABELSPACING;
- } else if (anyWindowLabel) {
- labelframePtr->labelReqWidth = Tk_ReqWidth(labelframePtr->labelWin);
- labelframePtr->labelReqHeight = Tk_ReqHeight(labelframePtr->labelWin);
- }
- /*
- * Make sure label size is at least as big as the border.
- * This simplifies later calculations and gives a better
- * appearance with thick borders.
- */
-
- if ((labelframePtr->labelAnchor >= LABELANCHOR_N) &&
- (labelframePtr->labelAnchor <= LABELANCHOR_SW)) {
- if (labelframePtr->labelReqHeight < framePtr->borderWidth) {
- labelframePtr->labelReqHeight = framePtr->borderWidth;
- }
- } else {
- if (labelframePtr->labelReqWidth < framePtr->borderWidth) {
- labelframePtr->labelReqWidth = framePtr->borderWidth;
- }
- }
- }
- /*
- * Calculate individual border widths.
- */
- bWidthBottom = bWidthTop = bWidthRight = bWidthLeft =
- framePtr->borderWidth + framePtr->highlightWidth;
- bWidthLeft += framePtr->padX;
- bWidthRight += framePtr->padX;
- bWidthTop += framePtr->padY;
- bWidthBottom += framePtr->padY;
-
- if (anyTextLabel || anyWindowLabel) {
- switch (labelframePtr->labelAnchor) {
- case LABELANCHOR_E:
- case LABELANCHOR_EN:
- case LABELANCHOR_ES:
- bWidthRight += labelframePtr->labelReqWidth -
- framePtr->borderWidth;
- break;
- case LABELANCHOR_N:
- case LABELANCHOR_NE:
- case LABELANCHOR_NW:
- bWidthTop += labelframePtr->labelReqHeight - framePtr->borderWidth;
- break;
- case LABELANCHOR_S:
- case LABELANCHOR_SE:
- case LABELANCHOR_SW:
- bWidthBottom += labelframePtr->labelReqHeight -
- framePtr->borderWidth;
- break;
- default:
- bWidthLeft += labelframePtr->labelReqWidth - framePtr->borderWidth;
- break;
- }
- }
- Tk_SetInternalBorderEx(tkwin, bWidthLeft, bWidthRight, bWidthTop,
- bWidthBottom);
- ComputeFrameGeometry(framePtr);
- /*
- * A labelframe should request size for its label.
- */
- if (framePtr->type == TYPE_LABELFRAME) {
- int minwidth = labelframePtr->labelReqWidth;
- int minheight = labelframePtr->labelReqHeight;
- int padding = framePtr->highlightWidth;
- if (framePtr->borderWidth > 0) {
- padding += framePtr->borderWidth + LABELMARGIN;
- }
- padding *= 2;
- if ((labelframePtr->labelAnchor >= LABELANCHOR_N) &&
- (labelframePtr->labelAnchor <= LABELANCHOR_SW)) {
- minwidth += padding;
- minheight += framePtr->borderWidth + framePtr->highlightWidth;
- } else {
- minheight += padding;
- minwidth += framePtr->borderWidth + framePtr->highlightWidth;
- }
- Tk_SetMinimumRequestSize(tkwin, minwidth, minheight);
- }
- if ((framePtr->width > 0) || (framePtr->height > 0)) {
- Tk_GeometryRequest(tkwin, framePtr->width, framePtr->height);
- }
- if (Tk_IsMapped(tkwin)) {
- if (!(framePtr->flags & REDRAW_PENDING)) {
- Tcl_DoWhenIdle(DisplayFrame, (ClientData) framePtr);
- }
- framePtr->flags |= REDRAW_PENDING;
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * ComputeFrameGeometry --
- *
- * This procedure is called to compute various geometrical
- * information for a frame, such as where various things get
- * displayed. It's called when the window is reconfigured.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Display-related numbers get changed in *framePtr.
- *
- *----------------------------------------------------------------------
- */
- static void
- ComputeFrameGeometry(framePtr)
- register Frame *framePtr; /* Information about widget. */
- {
- int otherWidth, otherHeight, otherWidthT, otherHeightT, padding;
- int maxWidth, maxHeight;
- Tk_Window tkwin;
- Labelframe *labelframePtr = (Labelframe *) framePtr;
- /*
- * We have nothing to do here unless there is a label.
- */
- if (framePtr->type != TYPE_LABELFRAME) return;
- if ((labelframePtr->textPtr == NULL) &&
- (labelframePtr->labelWin == NULL)) return;
- tkwin = framePtr->tkwin;
- /*
- * Calculate the available size for the label
- */
- labelframePtr->labelBox.width = labelframePtr->labelReqWidth;
- labelframePtr->labelBox.height = labelframePtr->labelReqHeight;
- padding = framePtr->highlightWidth;
- if (framePtr->borderWidth > 0) {
- padding += framePtr->borderWidth + LABELMARGIN;
- }
- padding *= 2;
- maxHeight = Tk_Height(tkwin);
- maxWidth = Tk_Width(tkwin);
- if ((labelframePtr->labelAnchor >= LABELANCHOR_N) &&
- (labelframePtr->labelAnchor <= LABELANCHOR_SW)) {
- maxWidth -= padding;
- if (maxWidth < 1) maxWidth = 1;
- } else {
- maxHeight -= padding;
- if (maxHeight < 1) maxHeight = 1;
- }
- if (labelframePtr->labelBox.width > maxWidth) {
- labelframePtr->labelBox.width = maxWidth;
- }
- if (labelframePtr->labelBox.height > maxHeight) {
- labelframePtr->labelBox.height = maxHeight;
- }
- /*
- * Calculate label and text position.
- * The text's position is based on the requested size (= the text's
- * real size) to get proper alignment if the text does not fit.
- */
- otherWidth = Tk_Width(tkwin) - labelframePtr->labelBox.width;
- otherHeight = Tk_Height(tkwin) - labelframePtr->labelBox.height;
- otherWidthT = Tk_Width(tkwin) - labelframePtr->labelReqWidth;
- otherHeightT = Tk_Height(tkwin) - labelframePtr->labelReqHeight;
- padding = framePtr->highlightWidth;
- switch (labelframePtr->labelAnchor) {
- case LABELANCHOR_E:
- case LABELANCHOR_EN:
- case LABELANCHOR_ES:
- labelframePtr->labelTextX = otherWidthT - padding;
- labelframePtr->labelBox.x = otherWidth - padding;
- break;
- case LABELANCHOR_N:
- case LABELANCHOR_NE:
- case LABELANCHOR_NW:
- labelframePtr->labelTextY = padding;
- labelframePtr->labelBox.y = padding;
- break;
- case LABELANCHOR_S:
- case LABELANCHOR_SE:
- case LABELANCHOR_SW:
- labelframePtr->labelTextY = otherHeightT - padding;
- labelframePtr->labelBox.y = otherHeight - padding;
- break;
- default:
- labelframePtr->labelTextX = padding;
- labelframePtr->labelBox.x = padding;
- break;
- }
- if (framePtr->borderWidth > 0) {
- padding += framePtr->borderWidth + LABELMARGIN;
- }
- switch (labelframePtr->labelAnchor) {
- case LABELANCHOR_NW:
- case LABELANCHOR_SW:
- labelframePtr->labelTextX = padding;
- labelframePtr->labelBox.x = padding;
- break;
- case LABELANCHOR_N:
- case LABELANCHOR_S:
- labelframePtr->labelTextX = otherWidthT / 2;
- labelframePtr->labelBox.x = otherWidth / 2;
- break;
- case LABELANCHOR_NE:
- case LABELANCHOR_SE:
- labelframePtr->labelTextX = otherWidthT - padding;
- labelframePtr->labelBox.x = otherWidth - padding;
- break;
- case LABELANCHOR_EN:
- case LABELANCHOR_WN:
- labelframePtr->labelTextY = padding;
- labelframePtr->labelBox.y = padding;
- break;
- case LABELANCHOR_E:
- case LABELANCHOR_W:
- labelframePtr->labelTextY = otherHeightT / 2;
- labelframePtr->labelBox.y = otherHeight / 2;
- break;
- default:
- labelframePtr->labelTextY = otherHeightT - padding;
- labelframePtr->labelBox.y = otherHeight - padding;
- break;
- }
- }
- /*
- *----------------------------------------------------------------------
- *
- * 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;
- int bdX1, bdY1, bdX2, bdY2, hlWidth;
- Pixmap pixmap;
- TkRegion clipRegion = NULL;
- framePtr->flags &= ~REDRAW_PENDING;
- if ((framePtr->tkwin == NULL) || !Tk_IsMapped(tkwin)
- || framePtr->isContainer) {
- return;
- }
- /*
- * Highlight shall always be drawn if it exists, so do that first.
- */
- hlWidth = framePtr->highlightWidth;
- if (hlWidth != 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, hlWidth,
- Tk_WindowId(tkwin));
- } else {
- TkpDrawHighlightBorder(tkwin, bgGC, bgGC, hlWidth,
- Tk_WindowId(tkwin));
- }
- }
- /*
- * If -background is set to "", no interior is drawn.
- */
- if (framePtr->border == NULL) return;
- if (framePtr->type != TYPE_LABELFRAME) {
- /*
- * Pass to platform specific draw function. In general, it just
- * draws a simple rectangle, but it may "theme" the background.
- */
- noLabel:
- TkpDrawFrame(tkwin, framePtr->border, hlWidth,
- framePtr->borderWidth, framePtr->relief);
- } else {
- Labelframe *labelframePtr = (Labelframe *) framePtr;
- if ((labelframePtr->textPtr == NULL) &&
- (labelframePtr->labelWin == NULL)) {
- goto noLabel;
- }
- #ifndef TK_NO_DOUBLE_BUFFERING
- /*
- * In order to avoid screen flashes, this procedure redraws the
- * frame into off-screen memory, then copies it back on-screen
- * in a single operation. This means there's no point in time
- * where the on-screen image has been cleared.
- */
- pixmap = Tk_GetPixmap(framePtr->display, Tk_WindowId(tkwin),
- Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin));
- #else
- pixmap = Tk_WindowId(tkwin);
- #endif /* TK_NO_DOUBLE_BUFFERING */
- /*
- * Clear the pixmap.
- */
- Tk_Fill3DRectangle(tkwin, pixmap, framePtr->border, 0, 0,
- Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT);
- /*
- * Calculate how the label affects the border's position.
- */
- bdX1 = bdY1 = hlWidth;
- bdX2 = Tk_Width(tkwin) - hlWidth;
- bdY2 = Tk_Height(tkwin) - hlWidth;
- switch (labelframePtr->labelAnchor) {
- case LABELANCHOR_E:
- case LABELANCHOR_EN:
- case LABELANCHOR_ES:
- bdX2 -= (labelframePtr->labelBox.width - framePtr->borderWidth)
- / 2;
- break;
- case LABELANCHOR_N:
- case LABELANCHOR_NE:
- case LABELANCHOR_NW:
- /*
- * Since the glyphs of the text tend to be in the lower part
- * we favor a lower border position by rounding up.
- */
- bdY1 += (labelframePtr->labelBox.height - framePtr->borderWidth +1)
- / 2;
- break;
- case LABELANCHOR_S:
- case LABELANCHOR_SE:
- case LABELANCHOR_SW:
- bdY2 -= (labelframePtr->labelBox.height - framePtr->borderWidth)
- / 2;
- break;
- default:
- bdX1 += (labelframePtr->labelBox.width - framePtr->borderWidth)
- / 2;
- break;
- }
- /*
- * Draw border
- */
- Tk_Draw3DRectangle(tkwin, pixmap, framePtr->border, bdX1, bdY1,
- bdX2 - bdX1, bdY2 - bdY1, framePtr->borderWidth,
- framePtr->relief);
- if (labelframePtr->labelWin == NULL) {
- /*
- * Clear behind the label
- */
- Tk_Fill3DRectangle(tkwin, pixmap,
- framePtr->border, labelframePtr->labelBox.x,
- labelframePtr->labelBox.y, labelframePtr->labelBox.width,
- labelframePtr->labelBox.height, 0, TK_RELIEF_FLAT);
- /*
- * Draw label.
- * If there is not room for the entire label, use clipping to
- * get a nice appearance.
- */
-
- if ((labelframePtr->labelBox.width < labelframePtr->labelReqWidth)
- || (labelframePtr->labelBox.height <
- labelframePtr->labelReqHeight)) {
- clipRegion = TkCreateRegion();
- TkUnionRectWithRegion(&labelframePtr->labelBox, clipRegion,
- clipRegion);
- TkSetRegion(framePtr->display, labelframePtr->textGC,
- clipRegion);
- }
- Tk_DrawTextLayout(framePtr->display, pixmap,
- labelframePtr->textGC, labelframePtr->textLayout,
- labelframePtr->labelTextX + LABELSPACING,
- labelframePtr->labelTextY + LABELSPACING, 0, -1);
- if (clipRegion != NULL) {
- XSetClipMask(framePtr->display, labelframePtr->textGC, None);
- TkDestroyRegion(clipRegion);
- }
- } else {
- /*
- * Reposition and map the window (but in different ways depending
- * on whether the frame is the window's parent).
- */
-
- if (framePtr->tkwin == Tk_Parent(labelframePtr->labelWin)) {
- if ((labelframePtr->labelBox.x != Tk_X(labelframePtr->labelWin))
- || (labelframePtr->labelBox.y !=
- Tk_Y(labelframePtr->labelWin))
- || (labelframePtr->labelBox.width !=
- Tk_Width(labelframePtr->labelWin))
- || (labelframePtr->labelBox.height !=
- Tk_Height(labelframePtr->labelWin))) {
- Tk_MoveResizeWindow(labelframePtr->labelWin,
- labelframePtr->labelBox.x, labelframePtr->labelBox.y,
- labelframePtr->labelBox.width,
- labelframePtr->labelBox.height);
- }
- Tk_MapWindow(labelframePtr->labelWin);
- } else {
- Tk_MaintainGeometry(labelframePtr->labelWin, framePtr->tkwin,
- labelframePtr->labelBox.x, labelframePtr->labelBox.y,
- labelframePtr->labelBox.width,
- labelframePtr->labelBox.height);
- }
- }
- #ifndef TK_NO_DOUBLE_BUFFERING
- /*
- * Everything's been redisplayed; now copy the pixmap onto the screen
- * and free up the pixmap.
- */
- XCopyArea(framePtr->display, pixmap, Tk_WindowId(tkwin),
- labelframePtr->textGC, hlWidth, hlWidth,
- (unsigned) (Tk_Width(tkwin) - 2 * hlWidth),
- (unsigned) (Tk_Height(tkwin) - 2 * hlWidth),
- hlWidth, hlWidth);
- Tk_FreePixmap(framePtr->display, pixmap);
- #endif /* TK_NO_DOUBLE_BUFFERING */
- }
- }
- /*
- *--------------------------------------------------------------
- *
- * 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)) {
- goto redraw;
- } else if (eventPtr->type == ConfigureNotify) {
- ComputeFrameGeometry(framePtr);
- 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).
- */
- /*
- * Since the tkwin pointer will be gone when we reach
- * DestroyFrame, we must free all options now.
- */
- DestroyFramePartly(framePtr);
- 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) {
- /*
- * Some options need tkwin to be freed, so we free them here,
- * before setting tkwin to NULL.
- */
- DestroyFramePartly(framePtr);
- 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);
- }
- }
- /*
- *--------------------------------------------------------------
- *
- * FrameStructureProc --
- *
- * This procedure is invoked whenever StructureNotify events
- * occur for a window that's managed as label for the frame.
- * This procudure's only purpose is to clean up when windows
- * are deleted.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The window is disassociated from the frame when it is
- * deleted.
- *
- *--------------------------------------------------------------
- */
- static void
- FrameStructureProc(clientData, eventPtr)
- ClientData clientData; /* Pointer to record describing frame. */
- XEvent *eventPtr; /* Describes what just happened. */
- {
- Labelframe *labelframePtr = (Labelframe *) clientData;
- if (eventPtr->type == DestroyNotify) {
- /*
- * This should only happen in a labelframe but it doesn't
- * hurt to be careful.
- */
- if (labelframePtr->frame.type == TYPE_LABELFRAME) {
- labelframePtr->labelWin = NULL;
- FrameWorldChanged((ClientData) labelframePtr);
- }
- }
- }
- /*
- *--------------------------------------------------------------
- *
- * FrameRequestProc --
- *
- * This procedure is invoked whenever a window that's associated
- * with a frame changes its requested dimensions.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The size and location on the screen of the window may change.
- * depending on the options specified for the frame.
- *
- *--------------------------------------------------------------
- */
- static void
- FrameRequestProc(clientData, tkwin)
- ClientData clientData; /* Pointer to record for frame. */
- Tk_Window tkwin; /* Window that changed its desired
- * size. */
- {
- Frame *framePtr = (Frame *) clientData;
- FrameWorldChanged((ClientData) framePtr);
- }
- /*
- *--------------------------------------------------------------
- *
- * FrameLostSlaveProc --
- *
- * This procedure is invoked by Tk whenever some other geometry
- * claims control over a slave that used to be managed by us.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Forgets all frame-related information about the slave.
- *
- *--------------------------------------------------------------
- */
- static void
- FrameLostSlaveProc(clientData, tkwin)
- ClientData clientData; /* Frame structure for slave window that
- * was stolen away. */
- Tk_Window tkwin; /* Tk's handle for the slave window. */
- {
- Frame *framePtr = (Frame *) clientData;
- Labelframe *labelframePtr = (Labelframe *) clientData;
- /*
- * This should only happen in a labelframe but it doesn't
- * hurt to be careful.
- */
-
- if (labelframePtr->frame.type == TYPE_LABELFRAME) {
- Tk_DeleteEventHandler(labelframePtr->labelWin, StructureNotifyMask,
- FrameStructureProc, (ClientData) labelframePtr);
- if (framePtr->tkwin != Tk_Parent(labelframePtr->labelWin)) {
- Tk_UnmaintainGeometry(labelframePtr->labelWin, framePtr->tkwin);
- }
- Tk_UnmapWindow(labelframePtr->labelWin);
- labelframePtr->labelWin = NULL;
- }
- FrameWorldChanged((ClientData) framePtr);
- }
- /*
- *--------------------------------------------------------------
- *
- * TkToplevelWindowFromCommandToken --
- *
- * If the given command name to the command for a toplevel window
- * in the given interpreter, return the tkwin for that toplevel
- * window. Note that this lookup can't be done using the
- * standard tkwin internal table because the command might have
- * been renamed.
- *
- * Results:
- * A Tk_Window token, or NULL if the name does not refer to a
- * toplevel window.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
- Tk_Window
- TkToplevelWindowForCommand(interp, cmdName)
- Tcl_Interp *interp;
- CONST char *cmdName;
- {
- Tcl_CmdInfo cmdInfo;
- Frame *framePtr;
- if (Tcl_GetCommandInfo(interp, cmdName, &cmdInfo) == 0) {
- return NULL;
- }
- if (cmdInfo.objProc != FrameWidgetObjCmd) {
- return NULL;
- }
- framePtr = (Frame *) cmdInfo.objClientData;
- if (framePtr->type != TYPE_TOPLEVEL) {
- return NULL;
- }
- return framePtr->tkwin;
- }