diff options
Diffstat (limited to 'generic/tkGrid.c')
-rw-r--r-- | generic/tkGrid.c | 2546 |
1 files changed, 1467 insertions, 1079 deletions
diff --git a/generic/tkGrid.c b/generic/tkGrid.c index 008e321..c6a00d5 100644 --- a/generic/tkGrid.c +++ b/generic/tkGrid.c @@ -5,8 +5,8 @@ * * Copyright (c) 1996-1997 by Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" @@ -19,26 +19,22 @@ # undef MAX #endif #define MAX(x,y) ((x) > (y) ? (x) : (y)) -#ifdef MIN -# undef MIN -#endif -#define MIN(x,y) ((x) > (y) ? (y) : (x)) -#define COLUMN (1) /* working on column offsets */ -#define ROW (2) /* working on row offsets */ +#define COLUMN (1) /* Working on column offsets. */ +#define ROW (2) /* Working on row offsets. */ -#define CHECK_ONLY (1) /* check max slot constraint */ -#define CHECK_SPACE (2) /* alloc more space, don't change max */ +#define CHECK_ONLY (1) /* Check max slot constraint. */ +#define CHECK_SPACE (2) /* Alloc more space, don't change max. */ /* - * Pre-allocate enough row and column slots for "typical" sized tables - * this value should be chosen so by the time the extra malloc's are - * required, the layout calculations overwehlm them. [A "slot" contains - * information for either a row or column, depending upon the context.] + * Pre-allocate enough row and column slots for "typical" sized tables this + * value should be chosen so by the time the extra malloc's are required, the + * layout calculations overwehlm them. [A "slot" contains information for + * either a row or column, depending upon the context.] */ -#define TYPICAL_SIZE 25 /* (arbitrary guess) */ -#define PREALLOC 10 /* extra slots to allocate */ +#define TYPICAL_SIZE 25 /* (Arbitrary guess) */ +#define PREALLOC 10 /* Extra slots to allocate. */ /* * Pre-allocate room for uniform groups during layout. @@ -46,10 +42,10 @@ #define UNIFORM_PREALLOC 10 -/* - * Data structures are allocated dynamically to support arbitrary sized tables. - * However, the space is proportional to the highest numbered slot with - * some non-default property. This limit is used to head off mistakes and +/* + * Data structures are allocated dynamically to support arbitrary sized + * tables. However, the space is proportional to the highest numbered slot + * with some non-default property. This limit is used to head off mistakes and * denial of service attacks by limiting the amount of storage required. */ @@ -64,63 +60,67 @@ #define REL_VERT '^' /* Extend widget from row above. */ /* - * Structure to hold information for grid masters. A slot is either - * a row or column. + * Default value for 'grid anchor'. + */ + +#define GRID_DEFAULT_ANCHOR TK_ANCHOR_NW + +/* + * Structure to hold information for grid masters. A slot is either a row or + * column. */ typedef struct SlotInfo { - int minSize; /* The minimum size of this slot (in pixels). + int minSize; /* The minimum size of this slot (in pixels). * It is set via the rowconfigure or * columnconfigure commands. */ - int weight; /* The resize weight of this slot. (0) means + int weight; /* The resize weight of this slot. (0) means * this slot doesn't resize. Extra space in * the layout is given distributed among slots * inproportion to their weights. */ - int pad; /* Extra padding, in pixels, required for - * this slot. This amount is "added" to the - * largest slave in the slot. */ - Tk_Uid uniform; /* Value of -uniform option. It is used to + int pad; /* Extra padding, in pixels, required for this + * slot. This amount is "added" to the largest + * slave in the slot. */ + Tk_Uid uniform; /* Value of -uniform option. It is used to * group slots that should have the same * size. */ - int offset; /* This is a cached value used for - * introspection. It is the pixel - * offset of the right or bottom edge - * of this slot from the beginning of the - * layout. */ - int temp; /* This is a temporary value used for - * calculating adjusted weights when - * shrinking the layout below its - * nominal size. */ + int offset; /* This is a cached value used for + * introspection. It is the pixel offset of + * the right or bottom edge of this slot from + * the beginning of the layout. */ + int temp; /* This is a temporary value used for + * calculating adjusted weights when shrinking + * the layout below its nominal size. */ } SlotInfo; /* - * Structure to hold information during layout calculations. There - * is one of these for each slot, an array for each of the rows or columns. + * Structure to hold information during layout calculations. There is one of + * these for each slot, an array for each of the rows or columns. */ typedef struct GridLayout { - struct Gridder *binNextPtr; /* The next slave window in this bin. - * Each bin contains a list of all - * slaves whose spans are >1 and whose - * right edges fall in this slot. */ - int minSize; /* Minimum size needed for this slot, - * in pixels. This is the space required - * to hold any slaves contained entirely - * in this slot, adjusted for any slot - * constrants, such as size or padding. */ + struct Gridder *binNextPtr; /* The next slave window in this bin. Each bin + * contains a list of all slaves whose spans + * are >1 and whose right edges fall in this + * slot. */ + int minSize; /* Minimum size needed for this slot, in + * pixels. This is the space required to hold + * any slaves contained entirely in this slot, + * adjusted for any slot constrants, such as + * size or padding. */ int pad; /* Padding needed for this slot */ int weight; /* Slot weight, controls resizing. */ - Tk_Uid uniform; /* Value of -uniform option. It is used to + Tk_Uid uniform; /* Value of -uniform option. It is used to * group slots that should have the same * size. */ - int minOffset; /* The minimum offset, in pixels, from - * the beginning of the layout to the - * right/bottom edge of the slot calculated - * from top/left to bottom/right. */ - int maxOffset; /* The maximum offset, in pixels, from - * the beginning of the layout to the - * right-or-bottom edge of the slot calculated - * from bottom-or-right to top-or-left. */ + int minOffset; /* The minimum offset, in pixels, from the + * beginning of the layout to the bottom/right + * edge of the slot calculated from top/left + * to bottom/right. */ + int maxOffset; /* The maximum offset, in pixels, from the + * beginning of the layout to the bottom/right + * edge of the slot calculated from + * bottom/right to top/left. */ } GridLayout; /* @@ -136,81 +136,84 @@ typedef struct { * column constraints. */ int rowEnd; /* The last row occupied by any slave. */ int rowMax; /* The number of rows with constraints. */ - int rowSpace; /* The number of slots currently allocated - * for row constraints. */ + int rowSpace; /* The number of slots currently allocated for + * row constraints. */ int startX; /* Pixel offset of this layout within its - * parent. */ + * master. */ int startY; /* Pixel offset of this layout within its - * parent. */ + * master. */ + Tk_Anchor anchor; /* Value of anchor option: specifies where a + * grid without weight should be placed. */ } GridMaster; /* - * For each window that the grid cares about (either because - * the window is managed by the grid or because the window - * has slaves that are managed by the grid), there is a - * structure of the following type: + * For each window that the grid cares about (either because the window is + * managed by the grid or because the window has slaves that are managed by + * the grid), there is a structure of the following type: */ typedef struct Gridder { - Tk_Window tkwin; /* Tk token for window. NULL means that - * the window has been deleted, but the - * gridder hasn't had a chance to clean up - * yet because the structure is still in - * use. */ - struct Gridder *masterPtr; /* Master window within which this window - * is managed (NULL means this window - * isn't managed by the gridder). */ - struct Gridder *nextPtr; /* Next window managed within same - * parent. List order doesn't matter. */ - struct Gridder *slavePtr; /* First in list of slaves managed - * inside this window (NULL means - * no grid slaves). */ + Tk_Window tkwin; /* Tk token for window. NULL means that the + * window has been deleted, but the gridder + * hasn't had a chance to clean up yet because + * the structure is still in use. */ + struct Gridder *masterPtr; /* Master window within which this window is + * managed (NULL means this window isn't + * managed by the gridder). */ + struct Gridder *nextPtr; /* Next window managed within same master. + * List order doesn't matter. */ + struct Gridder *slavePtr; /* First in list of slaves managed inside this + * window (NULL means no grid slaves). */ GridMaster *masterDataPtr; /* Additional data for geometry master. */ - int column, row; /* Location in the grid (starting - * from zero). */ + Tcl_Obj *in; /* Store master name when removed. */ + int column, row; /* Location in the grid (starting from + * zero). */ int numCols, numRows; /* Number of columns or rows this slave spans. * Should be at least 1. */ int padX, padY; /* Total additional pixels to leave around the - * window. Some is of this space is on each - * side. This is space *outside* the window: + * window. Some is of this space is on each + * side. This is space *outside* the window: * we'll allocate extra space in frame but * won't enlarge window). */ - int padLeft, padTop; /* The part of padX or padY to use on the - * left or top of the widget, respectively. - * By default, this is half of padX or padY. */ + int padLeft, padTop; /* The part of padX or padY to use on the left + * or top of the widget, respectively. By + * default, this is half of padX or padY. */ int iPadX, iPadY; /* Total extra pixels to allocate inside the * window (half this amount will appear on * each side). */ int sticky; /* which sides of its cavity this window * sticks to. See below for definitions */ - int doubleBw; /* Twice the window's last known border - * width. If this changes, the window - * must be re-arranged within its parent. */ - int *abortPtr; /* If non-NULL, it means that there is a nested - * call to ArrangeGrid already working on - * this window. *abortPtr may be set to 1 to - * abort that nested call. This happens, for - * example, if tkwin or any of its slaves + int doubleBw; /* Twice the window's last known border width. + * If this changes, the window must be + * re-arranged within its master. */ + int *abortPtr; /* If non-NULL, it means that there is a + * nested call to ArrangeGrid already working + * on this window. *abortPtr may be set to 1 + * to abort that nested call. This happens, + * for example, if tkwin or any of its slaves * is deleted. */ - int flags; /* Miscellaneous flags; see below - * for definitions. */ + int flags; /* Miscellaneous flags; see below for + * definitions. */ /* * These fields are used temporarily for layout calculations only. */ struct Gridder *binNextPtr; /* Link to next span>1 slave in this bin. */ - int size; /* Nominal size (width or height) in pixels - * of the slave. This includes the padding. */ + int size; /* Nominal size (width or height) in pixels of + * the slave. This includes the padding. */ } Gridder; -/* Flag values for "sticky"ness The 16 combinations subsume the packer's +/* + * Flag values for "sticky"ness. The 16 combinations subsume the packer's * notion of anchor and fill. * - * STICK_NORTH This window sticks to the top of its cavity. - * STICK_EAST This window sticks to the right edge of its cavity. - * STICK_SOUTH This window sticks to the bottom of its cavity. - * STICK_WEST This window sticks to the left edge of its cavity. + * STICK_NORTH This window sticks to the top of its cavity. + * STICK_EAST This window sticks to the right edge of its + * cavity. + * STICK_SOUTH This window sticks to the bottom of its cavity. + * STICK_WEST This window sticks to the left edge of its + * cavity. */ #define STICK_NORTH 1 @@ -231,14 +234,13 @@ typedef struct UniformGroup { /* * Flag values for Grid structures: * - * REQUESTED_RELAYOUT: 1 means a Tcl_DoWhenIdle request - * has already been made to re-arrange - * all the slaves of this window. - * - * DONT_PROPAGATE: 1 means don't set this window's requested - * size. 0 means if this window is a master - * then Tk will set its requested size to fit - * the needs of its slaves. + * REQUESTED_RELAYOUT 1 means a Tcl_DoWhenIdle request has already + * been made to re-arrange all the slaves of this + * window. + * DONT_PROPAGATE 1 means don't set this window's requested + * size. 0 means if this window is a master then + * Tk will set its requested size to fit the + * needs of its slaves. */ #define REQUESTED_RELAYOUT 1 @@ -248,66 +250,71 @@ typedef struct UniformGroup { * Prototypes for procedures used only in this file: */ -static void AdjustForSticky _ANSI_ARGS_((Gridder *slavePtr, int *xPtr, - int *yPtr, int *widthPtr, int *heightPtr)); -static int AdjustOffsets _ANSI_ARGS_((int width, - int elements, SlotInfo *slotPtr)); -static void ArrangeGrid _ANSI_ARGS_((ClientData clientData)); -static int CheckSlotData _ANSI_ARGS_((Gridder *masterPtr, int slot, - int slotType, int checkOnly)); -static int ConfigureSlaves _ANSI_ARGS_((Tcl_Interp *interp, - Tk_Window tkwin, int objc, Tcl_Obj *CONST objv[])); -static void DestroyGrid _ANSI_ARGS_((char *memPtr)); -static Gridder *GetGrid _ANSI_ARGS_((Tk_Window tkwin)); -static int GridBboxCommand _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int GridForgetRemoveCommand _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int GridInfoCommand _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int GridLocationCommand _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int GridPropagateCommand _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int GridRowColumnConfigureCommand _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int GridSizeCommand _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static int GridSlavesCommand _ANSI_ARGS_((Tk_Window tkwin, - Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); -static void GridStructureProc _ANSI_ARGS_(( - ClientData clientData, XEvent *eventPtr)); -static void GridLostSlaveProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin)); -static void GridReqProc _ANSI_ARGS_((ClientData clientData, - Tk_Window tkwin)); -static void InitMasterData _ANSI_ARGS_((Gridder *masterPtr)); -static Tcl_Obj *NewPairObj _ANSI_ARGS_((Tcl_Interp*, int, int)); -static Tcl_Obj *NewQuadObj _ANSI_ARGS_((Tcl_Interp*, int, int, int, int)); -static int ResolveConstraints _ANSI_ARGS_((Gridder *gridPtr, - int rowOrColumn, int maxOffset)); -static void SetGridSize _ANSI_ARGS_((Gridder *gridPtr)); -static int SetSlaveColumn _ANSI_ARGS_((Tcl_Interp *interp, - Gridder *slavePtr, int column, int numCols)); -static int SetSlaveRow _ANSI_ARGS_((Tcl_Interp *interp, - Gridder *slavePtr, int row, int numRows)); -static void StickyToString _ANSI_ARGS_((int flags, char *result)); -static int StringToSticky _ANSI_ARGS_((char *string)); -static void Unlink _ANSI_ARGS_((Gridder *gridPtr)); - -static Tk_GeomMgr gridMgrType = { +static void AdjustForSticky(Gridder *slavePtr, int *xPtr, + int *yPtr, int *widthPtr, int *heightPtr); +static int AdjustOffsets(int width, int elements, + SlotInfo *slotPtr); +static void ArrangeGrid(ClientData clientData); +static int CheckSlotData(Gridder *masterPtr, int slot, + int slotType, int checkOnly); +static int ConfigureSlaves(Tcl_Interp *interp, Tk_Window tkwin, + int objc, Tcl_Obj *CONST objv[]); +static void DestroyGrid(char *memPtr); +static Gridder * GetGrid(Tk_Window tkwin); +static int GridAnchorCommand(Tk_Window tkwin, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int GridBboxCommand(Tk_Window tkwin, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int GridForgetRemoveCommand(Tk_Window tkwin, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); +static int GridInfoCommand(Tk_Window tkwin, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int GridLocationCommand(Tk_Window tkwin, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); +static int GridPropagateCommand(Tk_Window tkwin, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); +static int GridRowColumnConfigureCommand(Tk_Window tkwin, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]); +static int GridSizeCommand(Tk_Window tkwin, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static int GridSlavesCommand(Tk_Window tkwin, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]); +static void GridStructureProc(ClientData clientData, + XEvent *eventPtr); +static void GridLostSlaveProc(ClientData clientData, + Tk_Window tkwin); +static void GridReqProc(ClientData clientData, Tk_Window tkwin); +static void InitMasterData(Gridder *masterPtr); +static Tcl_Obj * NewPairObj(int, int); +static Tcl_Obj * NewQuadObj(int, int, int, int); +static int ResolveConstraints(Gridder *gridPtr, int rowOrColumn, + int maxOffset); +static void SetGridSize(Gridder *gridPtr); +static int SetSlaveColumn(Tcl_Interp *interp, Gridder *slavePtr, + int column, int numCols); +static int SetSlaveRow(Tcl_Interp *interp, Gridder *slavePtr, + int row, int numRows); +static void StickyToString(int flags, char *result); +static int StringToSticky(char *string); +static void Unlink(Gridder *gridPtr); + +static const Tk_GeomMgr gridMgrType = { "grid", /* name */ GridReqProc, /* requestProc */ GridLostSlaveProc, /* lostSlaveProc */ }; /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * Tk_GridCmd -- * - * This procedure is invoked to process the "grid" Tcl command. - * See the user documentation for details on what it does. + * This procedure is invoked to process the "grid" Tcl command. See the + * user documentation for details on what it does. * * Results: * A standard Tcl result. @@ -315,31 +322,32 @@ static Tk_GeomMgr gridMgrType = { * Side effects: * See the user documentation. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ int -Tk_GridObjCmd(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. */ +Tk_GridObjCmd( + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window tkwin = (Tk_Window) clientData; static CONST char *optionStrings[] = { - "bbox", "columnconfigure", "configure", "forget", - "info", "location", "propagate", "remove", - "rowconfigure", "size", "slaves", (char *) NULL }; + "anchor", "bbox", "columnconfigure", "configure", + "forget", "info", "location", "propagate", "remove", + "rowconfigure", "size", "slaves", NULL + }; enum options { - GRID_BBOX, GRID_COLUMNCONFIGURE, GRID_CONFIGURE, GRID_FORGET, - GRID_INFO, GRID_LOCATION, GRID_PROPAGATE, GRID_REMOVE, - GRID_ROWCONFIGURE, GRID_SIZE, GRID_SLAVES }; + GRID_ANCHOR, GRID_BBOX, GRID_COLUMNCONFIGURE, GRID_CONFIGURE, + GRID_FORGET, GRID_INFO, GRID_LOCATION, GRID_PROPAGATE, GRID_REMOVE, + GRID_ROWCONFIGURE, GRID_SIZE, GRID_SLAVES + }; int index; - - + if (objc >= 2) { char *argv1 = Tcl_GetString(objv[1]); + if ((argv1[0] == '.') || (argv1[0] == REL_SKIP) || (argv1[0] == REL_VERT)) { return ConfigureSlaves(interp, tkwin, objc-1, objv+1); @@ -356,22 +364,24 @@ Tk_GridObjCmd(clientData, interp, objc, objv) } switch ((enum options) index) { - case GRID_BBOX: + case GRID_ANCHOR: + return GridAnchorCommand(tkwin, interp, objc, objv); + case GRID_BBOX: return GridBboxCommand(tkwin, interp, objc, objv); - case GRID_CONFIGURE: + case GRID_CONFIGURE: return ConfigureSlaves(interp, tkwin, objc-2, objv+2); - case GRID_FORGET: - case GRID_REMOVE: + case GRID_FORGET: + case GRID_REMOVE: return GridForgetRemoveCommand(tkwin, interp, objc, objv); - case GRID_INFO: + case GRID_INFO: return GridInfoCommand(tkwin, interp, objc, objv); - case GRID_LOCATION: + case GRID_LOCATION: return GridLocationCommand(tkwin, interp, objc, objv); - case GRID_PROPAGATE: + case GRID_PROPAGATE: return GridPropagateCommand(tkwin, interp, objc, objv); - case GRID_SIZE: + case GRID_SIZE: return GridSizeCommand(tkwin, interp, objc, objv); - case GRID_SLAVES: + case GRID_SLAVES: return GridSlavesCommand(tkwin, interp, objc, objv); /* @@ -383,8 +393,8 @@ Tk_GridObjCmd(clientData, interp, objc, objv) * grid rowconfigure <master> <index> -option value -option value. */ - case GRID_COLUMNCONFIGURE: - case GRID_ROWCONFIGURE: + case GRID_COLUMNCONFIGURE: + case GRID_ROWCONFIGURE: return GridRowColumnConfigureCommand(tkwin, interp, objc, objv); } @@ -396,6 +406,75 @@ Tk_GridObjCmd(clientData, interp, objc, objv) /* *---------------------------------------------------------------------- * + * GridAnchorCommand -- + * + * Implementation of the [grid anchor] subcommand. See the user + * documentation for details on what it does. + * + * Results: + * Standard Tcl result. + * + * Side effects: + * May recompute grid geometry. + * + *---------------------------------------------------------------------- + */ + +static int +GridAnchorCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ +{ + Tk_Window master; + Gridder *masterPtr; + GridMaster *gridPtr; + Tk_Anchor old; + + if (objc > 4) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?anchor?"); + return TCL_ERROR; + } + + if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) { + return TCL_ERROR; + } + masterPtr = GetGrid(master); + + if (objc == 3) { + gridPtr = masterPtr->masterDataPtr; + Tcl_SetResult(interp, (char *) Tk_NameOfAnchor(gridPtr == NULL ? + GRID_DEFAULT_ANCHOR : gridPtr->anchor), TCL_VOLATILE); + return TCL_OK; + } + + InitMasterData(masterPtr); + gridPtr = masterPtr->masterDataPtr; + old = gridPtr->anchor; + if (Tk_GetAnchorFromObj(interp, objv[3], &gridPtr->anchor) != TCL_OK) { + return TCL_ERROR; + } + + /* + * Only request a relayout if the anchor changes. + */ + + if (old != gridPtr->anchor) { + if (masterPtr->abortPtr != NULL) { + *masterPtr->abortPtr = 1; + } + if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { + masterPtr->flags |= REQUESTED_RELAYOUT; + Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * GridBboxCommand -- * * Implementation of the [grid bbox] subcommand. @@ -410,11 +489,11 @@ Tk_GridObjCmd(clientData, interp, objc, objv) */ static int -GridBboxCommand(tkwin, interp, objc, objv) - Tk_Window tkwin; /* Main window of the application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +GridBboxCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window master; Gridder *masterPtr; /* master grid record */ @@ -424,17 +503,17 @@ GridBboxCommand(tkwin, interp, objc, objv) int endX, endY; /* last column/row in the layout */ int x=0, y=0; /* starting pixels for this bounding box */ int width, height; /* size of the bounding box */ - + if (objc!=3 && objc != 5 && objc != 7) { Tcl_WrongNumArgs(interp, 2, objv, "master ?column row ?column row??"); return TCL_ERROR; } - + if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) { return TCL_ERROR; } masterPtr = GetGrid(master); - + if (objc >= 5) { if (Tcl_GetIntFromObj(interp, objv[3], &column) != TCL_OK) { return TCL_ERROR; @@ -445,7 +524,7 @@ GridBboxCommand(tkwin, interp, objc, objv) column2 = column; row2 = row; } - + if (objc == 7) { if (Tcl_GetIntFromObj(interp, objv[5], &column2) != TCL_OK) { return TCL_ERROR; @@ -454,65 +533,70 @@ GridBboxCommand(tkwin, interp, objc, objv) return TCL_ERROR; } } - + gridPtr = masterPtr->masterDataPtr; if (gridPtr == NULL) { - Tcl_SetObjResult(interp, NewQuadObj(interp, 0, 0, 0, 0)); + Tcl_SetObjResult(interp, NewQuadObj(0, 0, 0, 0)); return TCL_OK; } - + SetGridSize(masterPtr); endX = MAX(gridPtr->columnEnd, gridPtr->columnMax); endY = MAX(gridPtr->rowEnd, gridPtr->rowMax); - + if ((endX == 0) || (endY == 0)) { - Tcl_SetObjResult(interp, NewQuadObj(interp, 0, 0, 0, 0)); + Tcl_SetObjResult(interp, NewQuadObj(0, 0, 0, 0)); return TCL_OK; } if (objc == 3) { - row = column = 0; + row = 0; + column = 0; row2 = endY; column2 = endX; } - + if (column > column2) { int temp = column; - column = column2, column2 = temp; + + column = column2; + column2 = temp; } if (row > row2) { int temp = row; - row = row2, row2 = temp; + + row = row2; + row2 = temp; } - + if (column > 0 && column < endX) { x = gridPtr->columnPtr[column-1].offset; - } else if (column > 0) { + } else if (column > 0) { x = gridPtr->columnPtr[endX-1].offset; } - + if (row > 0 && row < endY) { y = gridPtr->rowPtr[row-1].offset; } else if (row > 0) { y = gridPtr->rowPtr[endY-1].offset; } - + if (column2 < 0) { width = 0; } else if (column2 >= endX) { width = gridPtr->columnPtr[endX-1].offset - x; } else { width = gridPtr->columnPtr[column2].offset - x; - } - + } + if (row2 < 0) { height = 0; } else if (row2 >= endY) { height = gridPtr->rowPtr[endY-1].offset - y; } else { height = gridPtr->rowPtr[row2].offset - y; - } - - Tcl_SetObjResult(interp, NewQuadObj(interp, + } + + Tcl_SetObjResult(interp, NewQuadObj( x + gridPtr->startX, y + gridPtr->startY, width, height)); return TCL_OK; } @@ -522,8 +606,8 @@ GridBboxCommand(tkwin, interp, objc, objv) * * GridForgetRemoveCommand -- * - * Implementation of the [grid forget]/[grid remove] subcommands. - * See the user documentation for details on what these do. + * Implementation of the [grid forget]/[grid remove] subcommands. See the + * user documentation for details on what these do. * * Results: * Standard Tcl result. @@ -535,18 +619,18 @@ GridBboxCommand(tkwin, interp, objc, objv) */ static int -GridForgetRemoveCommand(tkwin, interp, objc, objv) - Tk_Window tkwin; /* Main window of the application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +GridForgetRemoveCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window slave; Gridder *slavePtr; int i; char *string = Tcl_GetString(objv[1]); char c = string[0]; - + for (i = 2; i < objc; i++) { if (TkGetWindowFromObj(interp, tkwin, objv[i], &slave) != TCL_OK) { return TCL_ERROR; @@ -554,27 +638,48 @@ GridForgetRemoveCommand(tkwin, interp, objc, objv) slavePtr = GetGrid(slave); if (slavePtr->masterPtr != NULL) { - /* * For "forget", reset all the settings to their defaults */ - + if (c == 'f') { - slavePtr->column = slavePtr->row = -1; + slavePtr->column = -1; + slavePtr->row = -1; slavePtr->numCols = 1; slavePtr->numRows = 1; - slavePtr->padX = slavePtr->padY = 0; - slavePtr->padLeft = slavePtr->padTop = 0; - slavePtr->iPadX = slavePtr->iPadY = 0; + slavePtr->padX = 0; + slavePtr->padY = 0; + slavePtr->padLeft = 0; + slavePtr->padTop = 0; + slavePtr->iPadX = 0; + slavePtr->iPadY = 0; + if (slavePtr->in != NULL) { + Tcl_DecrRefCount(slavePtr->in); + slavePtr->in = NULL; + } slavePtr->doubleBw = 2*Tk_Changes(tkwin)->border_width; if (slavePtr->flags & REQUESTED_RELAYOUT) { Tcl_CancelIdleCall(ArrangeGrid, (ClientData) slavePtr); } slavePtr->flags = 0; slavePtr->sticky = 0; + } else { + /* + * When removing, store name of master to be able to + * restore it later, even if the master is recreated. + */ + + if (slavePtr->in != NULL) { + Tcl_DecrRefCount(slavePtr->in); + slavePtr->in = NULL; + } + if (slavePtr->masterPtr != NULL) { + slavePtr->in = Tcl_NewStringObj( + Tk_PathName(slavePtr->masterPtr->tkwin), -1); + Tcl_IncrRefCount(slavePtr->in); + } } - Tk_ManageGeometry(slave, (Tk_GeomMgr *) NULL, - (ClientData) NULL); + Tk_ManageGeometry(slave, NULL, (ClientData) NULL); if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin); @@ -591,7 +696,7 @@ GridForgetRemoveCommand(tkwin, interp, objc, objv) * * GridInfoCommand -- * - * Implementation of the [grid info] subcommand. See the user + * Implementation of the [grid info] subcommand. See the user * documentation for details on what it does. * * Results: @@ -604,16 +709,16 @@ GridForgetRemoveCommand(tkwin, interp, objc, objv) */ static int -GridInfoCommand(tkwin, interp, objc, objv) - Tk_Window tkwin; /* Main window of the application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +GridInfoCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { register Gridder *slavePtr; Tk_Window slave; char buffer[64 + TCL_INTEGER_SPACE * 4]; - + if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "window"); return TCL_ERROR; @@ -626,19 +731,19 @@ GridInfoCommand(tkwin, interp, objc, objv) Tcl_ResetResult(interp); return TCL_OK; } - + Tcl_AppendElement(interp, "-in"); Tcl_AppendElement(interp, Tk_PathName(slavePtr->masterPtr->tkwin)); sprintf(buffer, " -column %d -row %d -columnspan %d -rowspan %d", slavePtr->column, slavePtr->row, slavePtr->numCols, slavePtr->numRows); - Tcl_AppendResult(interp, buffer, (char *) NULL); + Tcl_AppendResult(interp, buffer, NULL); TkPrintPadAmount(interp, "ipadx", slavePtr->iPadX/2, slavePtr->iPadX); TkPrintPadAmount(interp, "ipady", slavePtr->iPadY/2, slavePtr->iPadY); TkPrintPadAmount(interp, "padx", slavePtr->padLeft, slavePtr->padX); TkPrintPadAmount(interp, "pady", slavePtr->padTop, slavePtr->padY); StickyToString(slavePtr->sticky, buffer); - Tcl_AppendResult(interp, " -sticky ", buffer, (char *) NULL); + Tcl_AppendResult(interp, " -sticky ", buffer, NULL); return TCL_OK; } @@ -647,7 +752,7 @@ GridInfoCommand(tkwin, interp, objc, objv) * * GridLocationCommand -- * - * Implementation of the [grid location] subcommand. See the user + * Implementation of the [grid location] subcommand. See the user * documentation for details on what it does. * * Results: @@ -660,58 +765,58 @@ GridInfoCommand(tkwin, interp, objc, objv) */ static int -GridLocationCommand(tkwin, interp, objc, objv) - Tk_Window tkwin; /* Main window of the application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +GridLocationCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window master; - Gridder *masterPtr; /* master grid record */ - GridMaster *gridPtr; /* pointer to grid data */ + Gridder *masterPtr; /* Master grid record. */ + GridMaster *gridPtr; /* Pointer to grid data. */ register SlotInfo *slotPtr; - int x, y; /* Offset in pixels, from edge of parent. */ - int i, j; /* Corresponding column and row indeces. */ - int endX, endY; /* end of grid */ - + int x, y; /* Offset in pixels, from edge of master. */ + int i, j; /* Corresponding column and row indeces. */ + int endX, endY; /* End of grid. */ + if (objc != 5) { Tcl_WrongNumArgs(interp, 2, objv, "master x y"); return TCL_ERROR; } - + if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) { return TCL_ERROR; } - + if (Tk_GetPixelsFromObj(interp, master, objv[3], &x) != TCL_OK) { return TCL_ERROR; } if (Tk_GetPixelsFromObj(interp, master, objv[4], &y) != TCL_OK) { return TCL_ERROR; } - + masterPtr = GetGrid(master); if (masterPtr->masterDataPtr == NULL) { - Tcl_SetObjResult(interp, NewPairObj(interp, -1, -1)); + Tcl_SetObjResult(interp, NewPairObj(-1, -1)); return TCL_OK; } gridPtr = masterPtr->masterDataPtr; - - /* - * Update any pending requests. This is not always the - * steady state value, as more configure events could be in - * the pipeline, but its as close as its easy to get. + + /* + * Update any pending requests. This is not always the steady state value, + * as more configure events could be in the pipeline, but its as close as + * its easy to get. */ - + while (masterPtr->flags & REQUESTED_RELAYOUT) { Tcl_CancelIdleCall(ArrangeGrid, (ClientData) masterPtr); - ArrangeGrid ((ClientData) masterPtr); + ArrangeGrid((ClientData) masterPtr); } SetGridSize(masterPtr); endX = MAX(gridPtr->columnEnd, gridPtr->columnMax); endY = MAX(gridPtr->rowEnd, gridPtr->rowMax); - - slotPtr = masterPtr->masterDataPtr->columnPtr; + + slotPtr = masterPtr->masterDataPtr->columnPtr; if (x < masterPtr->masterDataPtr->startX) { i = -1; } else { @@ -720,8 +825,8 @@ GridLocationCommand(tkwin, interp, objc, objv) /* null body */ } } - - slotPtr = masterPtr->masterDataPtr->rowPtr; + + slotPtr = masterPtr->masterDataPtr->rowPtr; if (y < masterPtr->masterDataPtr->startY) { j = -1; } else { @@ -730,8 +835,8 @@ GridLocationCommand(tkwin, interp, objc, objv) /* null body */ } } - - Tcl_SetObjResult(interp, NewPairObj(interp, i, j)); + + Tcl_SetObjResult(interp, NewPairObj(i, j)); return TCL_OK; } @@ -740,7 +845,7 @@ GridLocationCommand(tkwin, interp, objc, objv) * * GridPropagateCommand -- * - * Implementation of the [grid propagate] subcommand. See the user + * Implementation of the [grid propagate] subcommand. See the user * documentation for details on what it does. * * Results: @@ -753,16 +858,16 @@ GridLocationCommand(tkwin, interp, objc, objv) */ static int -GridPropagateCommand(tkwin, interp, objc, objv) - Tk_Window tkwin; /* Main window of the application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +GridPropagateCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window master; Gridder *masterPtr; int propagate, old; - + if (objc > 4) { Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?"); return TCL_ERROR; @@ -780,9 +885,11 @@ GridPropagateCommand(tkwin, interp, objc, objv) if (Tcl_GetBooleanFromObj(interp, objv[3], &propagate) != TCL_OK) { return TCL_ERROR; } - - /* Only request a relayout if the propagation bit changes */ - + + /* + * Only request a relayout if the propagation bit changes. + */ + old = !(masterPtr->flags & DONT_PROPAGATE); if (propagate != old) { if (propagate) { @@ -790,12 +897,12 @@ GridPropagateCommand(tkwin, interp, objc, objv) } else { masterPtr->flags |= DONT_PROPAGATE; } - + /* * Re-arrange the master to allow new geometry information to * propagate upwards to the master's master. */ - + if (masterPtr->abortPtr != NULL) { *masterPtr->abortPtr = 1; } @@ -813,8 +920,7 @@ GridPropagateCommand(tkwin, interp, objc, objv) * GridRowColumnConfigureCommand -- * * Implementation of the [grid rowconfigure] and [grid columnconfigure] - * subcommands. See the user documentation for details on what these - * do. + * subcommands. See the user documentation for details on what these do. * * Results: * Standard Tcl result. @@ -826,27 +932,29 @@ GridPropagateCommand(tkwin, interp, objc, objv) */ static int -GridRowColumnConfigureCommand(tkwin, interp, objc, objv) - Tk_Window tkwin; /* Main window of the application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +GridRowColumnConfigureCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - Tk_Window master; - Gridder *masterPtr; + Tk_Window master, slave; + Gridder *masterPtr, *slavePtr; SlotInfo *slotPtr = NULL; int slot; /* the column or row number */ int slotType; /* COLUMN or ROW */ int size; /* the configuration value */ - int checkOnly; /* check the size only */ int lObjc; /* Number of items in index list */ Tcl_Obj **lObjv; /* array of indices */ int ok; /* temporary TCL result code */ - int i, j; + int i, j, first, last; char *string; static CONST char *optionStrings[] = { - "-minsize", "-pad", "-uniform", "-weight", (char *) NULL }; - enum options { ROWCOL_MINSIZE, ROWCOL_PAD, ROWCOL_UNIFORM, ROWCOL_WEIGHT }; + "-minsize", "-pad", "-uniform", "-weight", NULL + }; + enum options { + ROWCOL_MINSIZE, ROWCOL_PAD, ROWCOL_UNIFORM, ROWCOL_WEIGHT + }; int index; Tcl_Obj *listCopy; @@ -871,41 +979,40 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv) if (lObjc == 0) { Tcl_AppendResult(interp, "no ", (slotType == COLUMN) ? "column" : "row", - " indices specified", (char *) NULL); + " indices specified", NULL); Tcl_DecrRefCount(listCopy); return TCL_ERROR; } - checkOnly = ((objc == 4) || (objc == 5)); masterPtr = GetGrid(master); - if (checkOnly && (lObjc > 1)) { - Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ", - Tcl_GetString(objv[1]), - ": must specify a single element on retrieval", (char *) NULL); - Tcl_DecrRefCount(listCopy); - return TCL_ERROR; - } - for (j = 0; j < lObjc; j++) { - if (Tcl_GetIntFromObj(interp, lObjv[j], &slot) != TCL_OK) { + first = 0; /* lint */ + last = 0; /* lint */ + + if ((objc == 4) || (objc == 5)) { + if (lObjc != 1) { + Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ", + Tcl_GetString(objv[1]), + ": must specify a single element on retrieval", NULL); Tcl_DecrRefCount(listCopy); return TCL_ERROR; } - ok = CheckSlotData(masterPtr, slot, slotType, checkOnly); - if ((ok != TCL_OK) && ((objc < 4) || (objc > 5))) { - Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ", - Tcl_GetString(objv[1]), ": \"", Tcl_GetString(lObjv[j]), - "\" is out of range", (char *) NULL); + if (Tcl_GetIntFromObj(interp, lObjv[0], &slot) != TCL_OK) { + Tcl_AppendResult(interp, + " (when retreiving options only integer indices are " + "allowed)", NULL); Tcl_DecrRefCount(listCopy); return TCL_ERROR; - } else if (ok == TCL_OK) { + } + ok = CheckSlotData(masterPtr, slot, slotType, /* checkOnly */ 1); + if (ok == TCL_OK) { slotPtr = (slotType == COLUMN) ? masterPtr->masterDataPtr->columnPtr : masterPtr->masterDataPtr->rowPtr; } /* - * Return all of the options for this row or column. If the - * request is out of range, return all 0's. + * Return all of the options for this row or column. If the request is + * out of range, return all 0's. */ if (objc == 4) { @@ -939,116 +1046,200 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv) } /* - * Loop through each option value pair, setting the values as - * required. If only one option is given, with no value, the - * current value is returned. + * If only one option is given, with no value, the current value is + * returned. */ - for (i = 4; i < objc; i += 2) { - if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", - 0, &index) != TCL_OK) { + if (Tcl_GetIndexFromObj(interp, objv[4], optionStrings, "option", 0, + &index) != TCL_OK) { + Tcl_DecrRefCount(listCopy); + return TCL_ERROR; + } + if (index == ROWCOL_MINSIZE) { + Tcl_SetObjResult(interp, + Tcl_NewIntObj((ok == TCL_OK) ? slotPtr[slot].minSize : 0)); + } else if (index == ROWCOL_WEIGHT) { + Tcl_SetObjResult(interp, + Tcl_NewIntObj((ok == TCL_OK) ? slotPtr[slot].weight : 0)); + } else if (index == ROWCOL_UNIFORM) { + Tk_Uid value = (ok == TCL_OK) ? slotPtr[slot].uniform : ""; + + Tcl_SetObjResult(interp, + Tcl_NewStringObj(value == NULL ? "" : value, -1)); + } else if (index == ROWCOL_PAD) { + Tcl_SetObjResult(interp, + Tcl_NewIntObj((ok == TCL_OK) ? slotPtr[slot].pad : 0)); + } + Tcl_DecrRefCount(listCopy); + return TCL_OK; + } + + for (j = 0; j < lObjc; j++) { + int allSlaves = 0; + + if (Tcl_GetIntFromObj(NULL, lObjv[j], &slot) == TCL_OK) { + first = slot; + last = slot; + slavePtr = NULL; + } else if (strcmp(Tcl_GetString(lObjv[j]), "all") == 0) { + /* + * Make sure master is initialised. + */ + + InitMasterData(masterPtr); + + slavePtr = masterPtr->slavePtr; + if (slavePtr == NULL) { + continue; + } + allSlaves = 1; + } else if (TkGetWindowFromObj(NULL, tkwin, lObjv[j], &slave) + == TCL_OK) { + /* + * Is it gridded in this master? + */ + + slavePtr = GetGrid(slave); + if (slavePtr->masterPtr != masterPtr) { + Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ", + Tcl_GetString(objv[1]), ": the window \"", + Tcl_GetString(lObjv[j]), "\" is not managed by \"", + Tcl_GetString(objv[2]), "\"", NULL); Tcl_DecrRefCount(listCopy); return TCL_ERROR; } - if (index == ROWCOL_MINSIZE) { - if (objc == 5) { - Tcl_SetObjResult(interp, Tcl_NewIntObj( - (ok == TCL_OK) ? slotPtr[slot].minSize : 0)); - } else if (Tk_GetPixelsFromObj(interp, master, objv[i+1], &size) - != TCL_OK) { - Tcl_DecrRefCount(listCopy); - return TCL_ERROR; - } else { - slotPtr[slot].minSize = size; - } - } else if (index == ROWCOL_WEIGHT) { - int wt; - if (objc == 5) { - Tcl_SetObjResult(interp, Tcl_NewIntObj( - (ok == TCL_OK) ? slotPtr[slot].weight : 0)); - } else if (Tcl_GetIntFromObj(interp, objv[i+1], &wt) - != TCL_OK) { - Tcl_DecrRefCount(listCopy); - return TCL_ERROR; - } else if (wt < 0) { - Tcl_AppendResult(interp, "invalid arg \"", - Tcl_GetString(objv[i]), - "\": should be non-negative", (char *) NULL); - Tcl_DecrRefCount(listCopy); + } else { + Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ", + Tcl_GetString(objv[1]), ": illegal index \"", + Tcl_GetString(lObjv[j]), "\"", NULL); + Tcl_DecrRefCount(listCopy); + return TCL_ERROR; + } + + /* + * The outer loop is only to handle "all". + */ + + do { + if (slavePtr != NULL) { + first = (slotType == COLUMN) ? + slavePtr->column : slavePtr->row; + last = first - 1 + ((slotType == COLUMN) ? + slavePtr->numCols : slavePtr->numRows); + } + + for (slot = first; slot <= last; slot++) { + ok = CheckSlotData(masterPtr, slot, slotType, /*checkOnly*/ 0); + if (ok != TCL_OK) { + Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ", + Tcl_GetString(objv[1]), ": \"", + Tcl_GetString(lObjv[j]), + "\" is out of range", NULL); + Tcl_DecrRefCount(listCopy); return TCL_ERROR; - } else { - slotPtr[slot].weight = wt; } - } else if (index == ROWCOL_UNIFORM) { - if (objc == 5) { - Tk_Uid value; - value = (ok == TCL_OK) ? slotPtr[slot].uniform : ""; - if (value == NULL) { - value = ""; + slotPtr = (slotType == COLUMN) ? + masterPtr->masterDataPtr->columnPtr : + masterPtr->masterDataPtr->rowPtr; + + /* + * Loop through each option value pair, setting the values as + * required. + */ + + for (i = 4; i < objc; i += 2) { + if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, + "option", 0, &index) != TCL_OK) { + Tcl_DecrRefCount(listCopy); + return TCL_ERROR; } - Tcl_SetObjResult(interp, Tcl_NewStringObj(value, -1)); - } else { - slotPtr[slot].uniform = Tk_GetUid(Tcl_GetString(objv[i+1])); - if (slotPtr[slot].uniform != NULL && - slotPtr[slot].uniform[0] == 0) { - slotPtr[slot].uniform = NULL; + if (index == ROWCOL_MINSIZE) { + if (Tk_GetPixelsFromObj(interp, master, objv[i+1], + &size) != TCL_OK) { + Tcl_DecrRefCount(listCopy); + return TCL_ERROR; + } else { + slotPtr[slot].minSize = size; + } + } else if (index == ROWCOL_WEIGHT) { + int wt; + + if (Tcl_GetIntFromObj(interp,objv[i+1],&wt)!=TCL_OK) { + Tcl_DecrRefCount(listCopy); + return TCL_ERROR; + } else if (wt < 0) { + Tcl_AppendResult(interp, "invalid arg \"", + Tcl_GetString(objv[i]), + "\": should be non-negative", NULL); + Tcl_DecrRefCount(listCopy); + return TCL_ERROR; + } else { + slotPtr[slot].weight = wt; + } + } else if (index == ROWCOL_UNIFORM) { + slotPtr[slot].uniform = + Tk_GetUid(Tcl_GetString(objv[i+1])); + if (slotPtr[slot].uniform != NULL && + slotPtr[slot].uniform[0] == 0) { + slotPtr[slot].uniform = NULL; + } + } else if (index == ROWCOL_PAD) { + if (Tk_GetPixelsFromObj(interp, master, objv[i+1], + &size) != TCL_OK) { + Tcl_DecrRefCount(listCopy); + return TCL_ERROR; + } else if (size < 0) { + Tcl_AppendResult(interp, "invalid arg \"", + Tcl_GetString(objv[i]), + "\": should be non-negative", NULL); + Tcl_DecrRefCount(listCopy); + return TCL_ERROR; + } else { + slotPtr[slot].pad = size; + } } } - } else if (index == ROWCOL_PAD) { - if (objc == 5) { - Tcl_SetObjResult(interp, Tcl_NewIntObj( - (ok == TCL_OK) ? slotPtr[slot].pad : 0)); - } else if (Tk_GetPixelsFromObj(interp, master, objv[i+1], &size) - != TCL_OK) { - Tcl_DecrRefCount(listCopy); - return TCL_ERROR; - } else if (size < 0) { - Tcl_AppendResult(interp, "invalid arg \"", - Tcl_GetString(objv[i]), - "\": should be non-negative", (char *) NULL); - Tcl_DecrRefCount(listCopy); - return TCL_ERROR; - } else { - slotPtr[slot].pad = size; - } } - } + if (slavePtr != NULL) { + slavePtr = slavePtr->nextPtr; + } + } while ((allSlaves == 1) && (slavePtr != NULL)); } Tcl_DecrRefCount(listCopy); /* - * If we changed a property, re-arrange the table, - * and check for constraint shrinkage. + * We changed a property, re-arrange the table, and check for constraint + * shrinkage. A null slotPtr will occur for 'all' checks. */ - if (objc != 5) { + if (slotPtr != NULL) { if (slotType == ROW) { int last = masterPtr->masterDataPtr->rowMax - 1; + while ((last >= 0) && (slotPtr[last].weight == 0) - && (slotPtr[last].pad == 0) - && (slotPtr[last].minSize == 0) + && (slotPtr[last].pad == 0) && (slotPtr[last].minSize == 0) && (slotPtr[last].uniform == NULL)) { last--; } masterPtr->masterDataPtr->rowMax = last+1; } else { int last = masterPtr->masterDataPtr->columnMax - 1; + while ((last >= 0) && (slotPtr[last].weight == 0) - && (slotPtr[last].pad == 0) - && (slotPtr[last].minSize == 0) + && (slotPtr[last].pad == 0) && (slotPtr[last].minSize == 0) && (slotPtr[last].uniform == NULL)) { last--; } masterPtr->masterDataPtr->columnMax = last + 1; } + } - if (masterPtr->abortPtr != NULL) { - *masterPtr->abortPtr = 1; - } - if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { - masterPtr->flags |= REQUESTED_RELAYOUT; - Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); - } + if (masterPtr->abortPtr != NULL) { + *masterPtr->abortPtr = 1; + } + if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { + masterPtr->flags |= REQUESTED_RELAYOUT; + Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); } return TCL_OK; } @@ -1058,7 +1249,7 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv) * * GridSizeCommand -- * - * Implementation of the [grid size] subcommand. See the user + * Implementation of the [grid size] subcommand. See the user * documentation for details on what it does. * * Results: @@ -1071,16 +1262,16 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv) */ static int -GridSizeCommand(tkwin, interp, objc, objv) - Tk_Window tkwin; /* Main window of the application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +GridSizeCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window master; Gridder *masterPtr; GridMaster *gridPtr; /* pointer to grid data */ - + if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "window"); return TCL_ERROR; @@ -1090,15 +1281,15 @@ GridSizeCommand(tkwin, interp, objc, objv) return TCL_ERROR; } masterPtr = GetGrid(master); - + if (masterPtr->masterDataPtr != NULL) { SetGridSize(masterPtr); gridPtr = masterPtr->masterDataPtr; - Tcl_SetObjResult(interp, NewPairObj(interp, + Tcl_SetObjResult(interp, NewPairObj( MAX(gridPtr->columnEnd, gridPtr->columnMax), MAX(gridPtr->rowEnd, gridPtr->rowMax))); } else { - Tcl_SetObjResult(interp, NewPairObj(interp, 0, 0)); + Tcl_SetObjResult(interp, NewPairObj(0, 0)); } return TCL_OK; } @@ -1108,42 +1299,42 @@ GridSizeCommand(tkwin, interp, objc, objv) * * GridSlavesCommand -- * - * Implementation of the [grid slaves] subcommand. See the user + * Implementation of the [grid slaves] subcommand. See the user * documentation for details on what it does. * * Results: * Standard Tcl result. * * Side effects: - * Places a list of slaves of the specified window in the - * interpreter's result field. + * Places a list of slaves of the specified window in the interpreter's + * result field. * *---------------------------------------------------------------------- */ static int -GridSlavesCommand(tkwin, interp, objc, objv) - Tk_Window tkwin; /* Main window of the application. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ +GridSlavesCommand( + Tk_Window tkwin, /* Main window of the application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { Tk_Window master; Gridder *masterPtr; /* master grid record */ Gridder *slavePtr; - int i, value; + int i, value, index; int row = -1, column = -1; static CONST char *optionStrings[] = { - "-column", "-row", (char *) NULL }; + "-column", "-row", NULL + }; enum options { SLAVES_COLUMN, SLAVES_ROW }; - int index; Tcl_Obj *res; - + if ((objc < 3) || ((objc % 2) == 0)) { Tcl_WrongNumArgs(interp, 2, objv, "window ?-option value...?"); return TCL_ERROR; } - + for (i = 3; i < objc; i += 2) { if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", 0, &index) != TCL_OK) { @@ -1154,8 +1345,7 @@ GridSlavesCommand(tkwin, interp, objc, objv) } if (value < 0) { Tcl_AppendResult(interp, Tcl_GetString(objv[i]), - " is an invalid value: should NOT be < 0", - (char *) NULL); + " is an invalid value: should NOT be < 0", NULL); return TCL_ERROR; } if (index == SLAVES_COLUMN) { @@ -1172,7 +1362,7 @@ GridSlavesCommand(tkwin, interp, objc, objv) res = Tcl_NewListObj(0, NULL); for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; - slavePtr = slavePtr->nextPtr) { + slavePtr = slavePtr->nextPtr) { if (column>=0 && (slavePtr->column > column || slavePtr->column+slavePtr->numCols-1 < column)) { continue; @@ -1189,30 +1379,29 @@ GridSlavesCommand(tkwin, interp, objc, objv) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * GridReqProc -- * - * This procedure is invoked by Tk_GeometryRequest for - * windows managed by the grid. + * This procedure is invoked by Tk_GeometryRequest for windows managed by + * the grid. * * Results: * None. * * Side effects: - * Arranges for tkwin, and all its managed siblings, to - * be re-arranged at the next idle point. + * Arranges for tkwin, and all its managed siblings, to be re-arranged at + * the next idle point. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static void -GridReqProc(clientData, tkwin) - ClientData clientData; /* Grid's information about - * window that got new preferred - * geometry. */ - Tk_Window tkwin; /* Other Tk-related information - * about the window. */ +GridReqProc( + ClientData clientData, /* Grid's information about window that got + * new preferred geometry. */ + Tk_Window tkwin) /* Other Tk-related information about the + * window. */ { register Gridder *gridPtr = (Gridder *) clientData; @@ -1224,12 +1413,12 @@ GridReqProc(clientData, tkwin) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * GridLostSlaveProc -- * - * This procedure is invoked by Tk whenever some other geometry - * claims control over a slave that used to be managed by us. + * This procedure is invoked by Tk whenever some other geometry claims + * control over a slave that used to be managed by us. * * Results: * None. @@ -1237,14 +1426,14 @@ GridReqProc(clientData, tkwin) * Side effects: * Forgets all grid-related information about the slave. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static void -GridLostSlaveProc(clientData, tkwin) - ClientData clientData; /* Grid structure for slave window that - * was stolen away. */ - Tk_Window tkwin; /* Tk's handle for the slave window. */ +GridLostSlaveProc( + ClientData clientData, /* Grid structure for slave window that was + * stolen away. */ + Tk_Window tkwin) /* Tk's handle for the slave window. */ { register Gridder *slavePtr = (Gridder *) clientData; @@ -1256,39 +1445,38 @@ GridLostSlaveProc(clientData, tkwin) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * AdjustOffsets -- * - * This procedure adjusts the size of the layout to fit in the - * space provided. If it needs more space, the extra is added - * according to the weights. If it needs less, the space is removed - * according to the weights, but at no time does the size drop below - * the minsize specified for that slot. + * This procedure adjusts the size of the layout to fit in the space + * provided. If it needs more space, the extra is added according to the + * weights. If it needs less, the space is removed according to the + * weights, but at no time does the size drop below the minsize specified + * for that slot. * * Results: - * The initial offset of the layout, - * if all the weights are zero, else 0. + * The size used by the layout. * * Side effects: * The slot offsets are modified to shrink the layout. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static int -AdjustOffsets(size, slots, slotPtr) - int size; /* The total layout size (in pixels). */ - int slots; /* Number of slots. */ - register SlotInfo *slotPtr; /* Pointer to slot array. */ +AdjustOffsets( + int size, /* The total layout size (in pixels). */ + int slots, /* Number of slots. */ + register SlotInfo *slotPtr) /* Pointer to slot array. */ { register int slot; /* Current slot. */ int diff; /* Extra pixels needed to add to the layout. */ - int totalWeight = 0; /* Sum of the weights for all the slots. */ - int weight = 0; /* Sum of the weights so far. */ + int totalWeight; /* Sum of the weights for all the slots. */ + int weight; /* Sum of the weights so far. */ int minSize; /* Minimum possible layout size. */ - int newDiff; /* The most pixels that can be added on - * the current pass. */ + int newDiff; /* The most pixels that can be added on the + * current pass. */ diff = size - slotPtr[slots-1].offset; @@ -1297,24 +1485,24 @@ AdjustOffsets(size, slots, slotPtr) */ if (diff == 0) { - return(0); + return size; } /* - * If all the weights are zero, center the layout in its parent if - * there is extra space, else clip on the bottom/right. + * If all the weights are zero, there is nothing more to do. */ + totalWeight = 0; for (slot = 0; slot < slots; slot++) { totalWeight += slotPtr[slot].weight; } - if (totalWeight == 0 ) { - return(diff > 0 ? diff/2 : 0); + if (totalWeight == 0) { + return slotPtr[slots-1].offset; } /* - * Add extra space according to the slot weights. This is done + * Add extra space according to the slot weights. This is done * cumulatively to prevent round-off error accumulation. */ @@ -1324,13 +1512,13 @@ AdjustOffsets(size, slots, slotPtr) weight += slotPtr[slot].weight; slotPtr[slot].offset += diff * weight / totalWeight; } - return(0); + return size; } /* - * The layout must shrink below its requested size. Compute the - * minimum possible size by looking at the slot minSizes. - * Store each slot's minimum size in temp. + * The layout must shrink below its requested size. Compute the minimum + * possible size by looking at the slot minSizes. Store each slot's + * minimum size in temp. */ minSize = 0; @@ -1346,34 +1534,35 @@ AdjustOffsets(size, slots, slotPtr) } /* - * If the requested size is less than the minimum required size, - * set the slot sizes to their minimum values, then clip on the - * bottom/right. + * If the requested size is less than the minimum required size, set the + * slot sizes to their minimum values. */ if (size <= minSize) { int offset = 0; + for (slot = 0; slot < slots; slot++) { offset += slotPtr[slot].temp; slotPtr[slot].offset = offset; } - return(0); + return minSize; } /* - * Remove space from slots according to their weights. The weights - * get renormalized anytime a slot shrinks to its minimum size. + * Remove space from slots according to their weights. The weights get + * renormalized anytime a slot shrinks to its minimum size. */ while (diff < 0) { - /* * Find the total weight for the shrinkable slots. */ - for (totalWeight=slot=0; slot < slots; slot++) { + totalWeight = 0; + for (slot = 0; slot < slots; slot++) { int current = (slot == 0) ? slotPtr[slot].offset : slotPtr[slot].offset - slotPtr[slot-1].offset; + if (current > slotPtr[slot].minSize) { totalWeight += slotPtr[slot].weight; slotPtr[slot].temp = slotPtr[slot].weight; @@ -1391,9 +1580,10 @@ AdjustOffsets(size, slots, slotPtr) newDiff = diff; for (slot = 0; slot < slots; slot++) { - int current; /* current size of this slot */ - int maxDiff; /* max diff that would cause - * this slot to equal its minsize */ + int current; /* Current size of this slot. */ + int maxDiff; /* Maximum diff that would cause this slot to + * equal its minsize. */ + if (slotPtr[slot].temp == 0) { continue; } @@ -1410,43 +1600,44 @@ AdjustOffsets(size, slots, slotPtr) * Now distribute the space. */ - for (weight=slot=0; slot < slots; slot++) { + weight = 0; + for (slot = 0; slot < slots; slot++) { weight += slotPtr[slot].temp; slotPtr[slot].offset += newDiff * weight / totalWeight; } diff -= newDiff; } - return(0); + return size; } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * AdjustForSticky -- * - * This procedure adjusts the size of a slave in its cavity based - * on its "sticky" flags. + * This procedure adjusts the size of a slave in its cavity based on its + * "sticky" flags. * * Results: - * The input x, y, width, and height are changed to represent the - * desired coordinates of the slave. + * The input x, y, width, and height are changed to represent the desired + * coordinates of the slave. * * Side effects: * None. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static void -AdjustForSticky(slavePtr, xPtr, yPtr, widthPtr, heightPtr) - Gridder *slavePtr; /* Slave window to arrange in its cavity. */ - int *xPtr; /* Pixel location of the left edge of the cavity. */ - int *yPtr; /* Pixel location of the top edge of the cavity. */ - int *widthPtr; /* Width of the cavity (in pixels). */ - int *heightPtr; /* Height of the cavity (in pixels). */ +AdjustForSticky( + Gridder *slavePtr, /* Slave window to arrange in its cavity. */ + int *xPtr, /* Pixel location of the left edge of the cavity. */ + int *yPtr, /* Pixel location of the top edge of the cavity. */ + int *widthPtr, /* Width of the cavity (in pixels). */ + int *heightPtr) /* Height of the cavity (in pixels). */ { - int diffx=0; /* Cavity width - slave width. */ - int diffy=0; /* Cavity hight - slave height. */ + int diffx = 0; /* Cavity width - slave width. */ + int diffy = 0; /* Cavity hight - slave height. */ int sticky = slavePtr->sticky; *xPtr += slavePtr->padLeft; @@ -1479,14 +1670,13 @@ AdjustForSticky(slavePtr, xPtr, yPtr, widthPtr, heightPtr) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * ArrangeGrid -- * - * This procedure is invoked (using the Tcl_DoWhenIdle - * mechanism) to re-layout a set of windows managed by - * the grid. It is invoked at idle time so that a - * series of grid requests can be merged into a single + * This procedure is invoked (using the Tcl_DoWhenIdle mechanism) to + * re-layout a set of windows managed by the grid. It is invoked at idle + * time so that a series of grid requests can be merged into a single * layout operation. * * Results: @@ -1495,28 +1685,29 @@ AdjustForSticky(slavePtr, xPtr, yPtr, widthPtr, heightPtr) * Side effects: * The slaves of masterPtr may get resized or moved. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static void -ArrangeGrid(clientData) - ClientData clientData; /* Structure describing parent whose slaves +ArrangeGrid( + ClientData clientData) /* Structure describing master whose slaves * are to be re-layed out. */ { register Gridder *masterPtr = (Gridder *) clientData; - register Gridder *slavePtr; + register Gridder *slavePtr; GridMaster *slotPtr = masterPtr->masterDataPtr; int abort; - int width, height; /* requested size of layout, in pixels */ - int realWidth, realHeight; /* actual size layout should take-up */ + int width, height; /* Requested size of layout, in pixels. */ + int realWidth, realHeight; /* Actual size layout should take-up. */ + int usedX, usedY; masterPtr->flags &= ~REQUESTED_RELAYOUT; /* - * If the parent has no slaves anymore, then don't do anything - * at all: just leave the parent's size as-is. Otherwise there is - * no way to "relinquish" control over the parent so another geometry - * manager can take over. + * If the master has no slaves anymore, then don't do anything at all: + * just leave the master's size as-is. Otherwise there is no way to + * "relinquish" control over the master so another geometry manager can + * take over. */ if (masterPtr->slavePtr == NULL) { @@ -1528,9 +1719,9 @@ ArrangeGrid(clientData) } /* - * Abort any nested call to ArrangeGrid for this window, since - * we'll do everything necessary here, and set up so this call - * can be aborted if necessary. + * Abort any nested call to ArrangeGrid for this window, since we'll do + * everything necessary here, and set up so this call can be aborted if + * necessary. */ if (masterPtr->abortPtr != NULL) { @@ -1545,13 +1736,13 @@ ArrangeGrid(clientData) */ SetGridSize(masterPtr); - width = ResolveConstraints(masterPtr, COLUMN, 0); + width = ResolveConstraints(masterPtr, COLUMN, 0); height = ResolveConstraints(masterPtr, ROW, 0); width += Tk_InternalBorderLeft(masterPtr->tkwin) + Tk_InternalBorderRight(masterPtr->tkwin); height += Tk_InternalBorderTop(masterPtr->tkwin) + Tk_InternalBorderBottom(masterPtr->tkwin); - + if (width < Tk_MinReqWidth(masterPtr->tkwin)) { width = Tk_MinReqWidth(masterPtr->tkwin); } @@ -1569,15 +1760,14 @@ ArrangeGrid(clientData) } masterPtr->abortPtr = NULL; Tcl_Release((ClientData) masterPtr); - return; + return; } /* - * If the currently requested layout size doesn't match the parent's - * window size, then adjust the slot offsets according to the - * weights. If all of the weights are zero, center the layout in - * its parent. I haven't decided what to do if the parent is smaller - * than the requested size. + * If the currently requested layout size doesn't match the master's + * window size, then adjust the slot offsets according to the weights. If + * all of the weights are zero, place the layout according to the anchor + * value. */ realWidth = Tk_Width(masterPtr->tkwin) - @@ -1586,23 +1776,22 @@ ArrangeGrid(clientData) realHeight = Tk_Height(masterPtr->tkwin) - Tk_InternalBorderTop(masterPtr->tkwin) - Tk_InternalBorderBottom(masterPtr->tkwin); - slotPtr->startX = AdjustOffsets(realWidth, - MAX(slotPtr->columnEnd,slotPtr->columnMax), slotPtr->columnPtr); - slotPtr->startY = AdjustOffsets(realHeight, - MAX(slotPtr->rowEnd,slotPtr->rowMax), slotPtr->rowPtr); - slotPtr->startX += Tk_InternalBorderLeft(masterPtr->tkwin); - slotPtr->startY += Tk_InternalBorderTop(masterPtr->tkwin); + usedX = AdjustOffsets(realWidth, + MAX(slotPtr->columnEnd, slotPtr->columnMax), slotPtr->columnPtr); + usedY = AdjustOffsets(realHeight, MAX(slotPtr->rowEnd, slotPtr->rowMax), + slotPtr->rowPtr); + TkComputeAnchor(masterPtr->masterDataPtr->anchor, masterPtr->tkwin, + 0, 0, usedX, usedY, &slotPtr->startX, &slotPtr->startY); /* - * Now adjust the actual size of the slave to its cavity by - * computing the cavity size, and adjusting the widget according - * to its stickyness. + * Now adjust the actual size of the slave to its cavity by computing the + * cavity size, and adjusting the widget according to its stickyness. */ for (slavePtr = masterPtr->slavePtr; slavePtr != NULL && !abort; slavePtr = slavePtr->nextPtr) { - int x, y; /* top left coordinate */ - int width, height; /* slot or slave size */ + int x, y; /* Top left coordinate */ + int width, height; /* Slot or slave size */ int col = slavePtr->column; int row = slavePtr->row; @@ -1612,49 +1801,47 @@ ArrangeGrid(clientData) width = slotPtr->columnPtr[slavePtr->numCols+col-1].offset - x; height = slotPtr->rowPtr[slavePtr->numRows+row-1].offset - y; - x += slotPtr->startX; - y += slotPtr->startY; + x += slotPtr->startX; + y += slotPtr->startY; AdjustForSticky(slavePtr, &x, &y, &width, &height); /* - * Now put the window in the proper spot. (This was taken directly - * from tkPack.c.) If the slave is a child of the master, then - * do this here. Otherwise let Tk_MaintainGeometry do the work. - */ - - if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) { - if ((width <= 0) || (height <= 0)) { - Tk_UnmapWindow(slavePtr->tkwin); - } else { - if ((x != Tk_X(slavePtr->tkwin)) - || (y != Tk_Y(slavePtr->tkwin)) - || (width != Tk_Width(slavePtr->tkwin)) - || (height != Tk_Height(slavePtr->tkwin))) { - Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height); - } - if (abort) { - break; - } - - /* - * Don't map the slave if the master isn't mapped: wait - * until the master gets mapped later. - */ - - if (Tk_IsMapped(masterPtr->tkwin)) { - Tk_MapWindow(slavePtr->tkwin); - } - } - } else { - if ((width <= 0) || (height <= 0)) { - Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin); - Tk_UnmapWindow(slavePtr->tkwin); - } else { - Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin, - x, y, width, height); - } - } + * Now put the window in the proper spot. (This was taken directly + * from tkPack.c.) If the slave is a child of the master, then do this + * here. Otherwise let Tk_MaintainGeometry do the work. + */ + + if (masterPtr->tkwin == Tk_Parent(slavePtr->tkwin)) { + if ((width <= 0) || (height <= 0)) { + Tk_UnmapWindow(slavePtr->tkwin); + } else { + if ((x != Tk_X(slavePtr->tkwin)) + || (y != Tk_Y(slavePtr->tkwin)) + || (width != Tk_Width(slavePtr->tkwin)) + || (height != Tk_Height(slavePtr->tkwin))) { + Tk_MoveResizeWindow(slavePtr->tkwin, x, y, width, height); + } + if (abort) { + break; + } + + /* + * Don't map the slave if the master isn't mapped: wait until + * the master gets mapped later. + */ + + if (Tk_IsMapped(masterPtr->tkwin)) { + Tk_MapWindow(slavePtr->tkwin); + } + } + } else if ((width <= 0) || (height <= 0)) { + Tk_UnmaintainGeometry(slavePtr->tkwin, masterPtr->tkwin); + Tk_UnmapWindow(slavePtr->tkwin); + } else { + Tk_MaintainGeometry(slavePtr->tkwin, masterPtr->tkwin, x, y, + width, height); + } } masterPtr->abortPtr = NULL; @@ -1662,13 +1849,13 @@ ArrangeGrid(clientData) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * ResolveConstraints -- * - * Resolve all of the column and row boundaries. Most of - * the calculations are identical for rows and columns, so this procedure - * is called twice, once for rows, and again for columns. + * Resolve all of the column and row boundaries. Most of the calculations + * are identical for rows and columns, so this procedure is called twice, + * once for rows, and again for columns. * * Results: * The offset (in pixels) from the left/top edge of this layout is @@ -1678,34 +1865,34 @@ ArrangeGrid(clientData) * The slot offsets are copied into the SlotInfo structure for the * geometry master. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static int -ResolveConstraints(masterPtr, slotType, maxOffset) - Gridder *masterPtr; /* The geometry master for this grid. */ - int slotType; /* Either ROW or COLUMN. */ - int maxOffset; /* The actual maximum size of this layout - * in pixels, or 0 (not currently used). */ +ResolveConstraints( + Gridder *masterPtr, /* The geometry master for this grid. */ + int slotType, /* Either ROW or COLUMN. */ + int maxOffset) /* The actual maximum size of this layout in + * pixels, or 0 (not currently used). */ { register SlotInfo *slotPtr; /* Pointer to row/col constraints. */ register Gridder *slavePtr; /* List of slave windows in this grid. */ int constraintCount; /* Count of rows or columns that have - * constraints. */ + * constraints. */ int slotCount; /* Last occupied row or column. */ - int gridCount; /* The larger of slotCount and constraintCount. - */ + int gridCount; /* The larger of slotCount and + * constraintCount. */ GridLayout *layoutPtr; /* Temporary layout structure. */ int requiredSize; /* The natural size of the grid (pixels). * This is the minimum size needed to * accomodate all of the slaves at their * requested sizes. */ int offset; /* The pixel offset of the right edge of the - * current slot from the beginning of the - * layout. */ + * current slot from the beginning of the + * layout. */ int slot; /* The current slot. */ int start; /* The first slot of a contiguous set whose - * constraints are not yet fully resolved. */ + * constraints are not yet fully resolved. */ int end; /* The Last slot of a contiguous set whose * constraints are not yet fully resolved. */ UniformGroup uniformPre[UNIFORM_PREALLOC]; @@ -1713,13 +1900,14 @@ ResolveConstraints(masterPtr, slotType, maxOffset) UniformGroup *uniformGroupPtr; /* Uniform groups data. */ int uniformGroups; /* Number of currently used uniform groups. */ - int uniformGroupsAlloced; /* Size of allocated space for uniform groups. - */ + int uniformGroupsAlloced; /* Size of allocated space for uniform + * groups. */ int weight, minSize; + int prevGrow, accWeight, grow; /* - * For typical sized tables, we'll use stack space for the layout data - * to avoid the overhead of a malloc and free for every layout. + * For typical sized tables, we'll use stack space for the layout data to + * avoid the overhead of a malloc and free for every layout. */ GridLayout layoutData[TYPICAL_SIZE + 1]; @@ -1727,30 +1915,32 @@ ResolveConstraints(masterPtr, slotType, maxOffset) if (slotType == COLUMN) { constraintCount = masterPtr->masterDataPtr->columnMax; slotCount = masterPtr->masterDataPtr->columnEnd; - slotPtr = masterPtr->masterDataPtr->columnPtr; + slotPtr = masterPtr->masterDataPtr->columnPtr; } else { constraintCount = masterPtr->masterDataPtr->rowMax; slotCount = masterPtr->masterDataPtr->rowEnd; - slotPtr = masterPtr->masterDataPtr->rowPtr; + slotPtr = masterPtr->masterDataPtr->rowPtr; } /* * Make sure there is enough memory for the layout. */ - gridCount = MAX(constraintCount,slotCount); + gridCount = MAX(constraintCount, slotCount); if (gridCount >= TYPICAL_SIZE) { - layoutPtr = (GridLayout *) ckalloc(sizeof(GridLayout) * (1+gridCount)); + layoutPtr = (GridLayout *) + ckalloc(sizeof(GridLayout) * (1+gridCount)); } else { layoutPtr = layoutData; } /* - * Allocate an extra layout slot to represent the left/top edge of - * the 0th slot to make it easier to calculate slot widths from - * offsets without special case code. - * Initialize the "dummy" slot to the left/top of the table. - * This slot avoids special casing the first slot. + * Allocate an extra layout slot to represent the left/top edge of the 0th + * slot to make it easier to calculate slot widths from offsets without + * special case code. + * + * Initialize the "dummy" slot to the left/top of the table. This slot + * avoids special casing the first slot. */ layoutPtr->minOffset = 0; @@ -1759,74 +1949,77 @@ ResolveConstraints(masterPtr, slotType, maxOffset) /* * Step 1. - * Copy the slot constraints into the layout structure, - * and initialize the rest of the fields. + * Copy the slot constraints into the layout structure, and initialize the + * rest of the fields. */ for (slot=0; slot < constraintCount; slot++) { - layoutPtr[slot].minSize = slotPtr[slot].minSize; - layoutPtr[slot].weight = slotPtr[slot].weight; - layoutPtr[slot].uniform = slotPtr[slot].uniform; - layoutPtr[slot].pad = slotPtr[slot].pad; - layoutPtr[slot].binNextPtr = NULL; + layoutPtr[slot].minSize = slotPtr[slot].minSize; + layoutPtr[slot].weight = slotPtr[slot].weight; + layoutPtr[slot].uniform = slotPtr[slot].uniform; + layoutPtr[slot].pad = slotPtr[slot].pad; + layoutPtr[slot].binNextPtr = NULL; } - for(;slot<gridCount;slot++) { - layoutPtr[slot].minSize = 0; - layoutPtr[slot].weight = 0; - layoutPtr[slot].uniform = NULL; - layoutPtr[slot].pad = 0; - layoutPtr[slot].binNextPtr = NULL; + for (; slot<gridCount; slot++) { + layoutPtr[slot].minSize = 0; + layoutPtr[slot].weight = 0; + layoutPtr[slot].uniform = NULL; + layoutPtr[slot].pad = 0; + layoutPtr[slot].binNextPtr = NULL; } /* * Step 2. - * Slaves with a span of 1 are used to determine the minimum size of - * each slot. Slaves whose span is two or more slots don't - * contribute to the minimum size of each slot directly, but can cause - * slots to grow if their size exceeds the the sizes of the slots they - * span. - * - * Bin all slaves whose spans are > 1 by their right edges. This - * allows the computation on minimum and maximum possible layout - * sizes at each slot boundary, without the need to re-sort the slaves. + * Slaves with a span of 1 are used to determine the minimum size of each + * slot. Slaves whose span is two or more slots don't contribute to the + * minimum size of each slot directly, but can cause slots to grow if + * their size exceeds the the sizes of the slots they span. + * + * Bin all slaves whose spans are > 1 by their right edges. This allows + * the computation on minimum and maximum possible layout sizes at each + * slot boundary, without the need to re-sort the slaves. */ - + switch (slotType) { - case COLUMN: - for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; - slavePtr = slavePtr->nextPtr) { - int rightEdge = slavePtr->column + slavePtr->numCols - 1; - slavePtr->size = Tk_ReqWidth(slavePtr->tkwin) + - slavePtr->padX + slavePtr->iPadX + slavePtr->doubleBw; - if (slavePtr->numCols > 1) { - slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr; - layoutPtr[rightEdge].binNextPtr = slavePtr; - } else { - int size = slavePtr->size + layoutPtr[rightEdge].pad; - if (size > layoutPtr[rightEdge].minSize) { - layoutPtr[rightEdge].minSize = size; - } + case COLUMN: + for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; + slavePtr = slavePtr->nextPtr) { + int rightEdge = slavePtr->column + slavePtr->numCols - 1; + + slavePtr->size = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->padX + + slavePtr->iPadX + slavePtr->doubleBw; + if (slavePtr->numCols > 1) { + slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr; + layoutPtr[rightEdge].binNextPtr = slavePtr; + } else { + int size = slavePtr->size + layoutPtr[rightEdge].pad; + + if (size > layoutPtr[rightEdge].minSize) { + layoutPtr[rightEdge].minSize = size; } } - break; - case ROW: - for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; - slavePtr = slavePtr->nextPtr) { - int rightEdge = slavePtr->row + slavePtr->numRows - 1; - slavePtr->size = Tk_ReqHeight(slavePtr->tkwin) + - slavePtr->padY + slavePtr->iPadY + slavePtr->doubleBw; - if (slavePtr->numRows > 1) { - slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr; - layoutPtr[rightEdge].binNextPtr = slavePtr; - } else { - int size = slavePtr->size + layoutPtr[rightEdge].pad; - if (size > layoutPtr[rightEdge].minSize) { - layoutPtr[rightEdge].minSize = size; - } + } + break; + case ROW: + for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; + slavePtr = slavePtr->nextPtr) { + int rightEdge = slavePtr->row + slavePtr->numRows - 1; + + slavePtr->size = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->padY + + slavePtr->iPadY + slavePtr->doubleBw; + if (slavePtr->numRows > 1) { + slavePtr->binNextPtr = layoutPtr[rightEdge].binNextPtr; + layoutPtr[rightEdge].binNextPtr = slavePtr; + } else { + int size = slavePtr->size + layoutPtr[rightEdge].pad; + + if (size > layoutPtr[rightEdge].minSize) { + layoutPtr[rightEdge].minSize = size; } } - break; } + break; + } /* * Step 2b. @@ -1858,13 +2051,14 @@ ResolveConstraints(masterPtr, slotType, maxOffset) * sizeof(UniformGroup); size_t newSize = (uniformGroupsAlloced + UNIFORM_PREALLOC) * sizeof(UniformGroup); - UniformGroup *new = (UniformGroup *) ckalloc(newSize); - UniformGroup *old = uniformGroupPtr; - memcpy((VOID *) new, (VOID *) old, oldSize); - if (old != uniformPre) { - ckfree((char *) old); + UniformGroup *newUG = (UniformGroup *) ckalloc(newSize); + UniformGroup *oldUG = uniformGroupPtr; + + memcpy(newUG, oldUG, oldSize); + if (oldUG != uniformPre) { + ckfree((char *) oldUG); } - uniformGroupPtr = new; + uniformGroupPtr = newUG; uniformGroupsAlloced += UNIFORM_PREALLOC; } uniformGroups++; @@ -1907,54 +2101,58 @@ ResolveConstraints(masterPtr, slotType, maxOffset) /* * Step 3. - * Determine the minimum slot offsets going from left to right - * that would fit all of the slaves. This determines the minimum + * Determine the minimum slot offsets going from left to right that would + * fit all of the slaves. This determines the minimum */ - for (offset=slot=0; slot < gridCount; slot++) { - layoutPtr[slot].minOffset = layoutPtr[slot].minSize + offset; - for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL; - slavePtr = slavePtr->binNextPtr) { - int span = (slotType == COLUMN) ? slavePtr->numCols : slavePtr->numRows; - int required = slavePtr->size + layoutPtr[slot - span].minOffset; - if (required > layoutPtr[slot].minOffset) { - layoutPtr[slot].minOffset = required; - } - } - offset = layoutPtr[slot].minOffset; + for (offset=0,slot=0; slot < gridCount; slot++) { + layoutPtr[slot].minOffset = layoutPtr[slot].minSize + offset; + for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL; + slavePtr = slavePtr->binNextPtr) { + int span = (slotType == COLUMN) ? + slavePtr->numCols : slavePtr->numRows; + int required = slavePtr->size + layoutPtr[slot - span].minOffset; + + if (required > layoutPtr[slot].minOffset) { + layoutPtr[slot].minOffset = required; + } + } + offset = layoutPtr[slot].minOffset; } /* * At this point, we know the minimum required size of the entire layout. - * It might be prudent to stop here if our "master" will resize itself - * to this size. + * It might be prudent to stop here if our "master" will resize itself to + * this size. */ requiredSize = offset; if (maxOffset > offset) { - offset=maxOffset; + offset=maxOffset; } /* * Step 4. - * Determine the minimum slot offsets going from right to left, - * bounding the pixel range of each slot boundary. - * Pre-fill all of the right offsets with the actual size of the table; - * they will be reduced as required. + * Determine the minimum slot offsets going from right to left, bounding + * the pixel range of each slot boundary. Pre-fill all of the right + * offsets with the actual size of the table; they will be reduced as + * required. */ for (slot=0; slot < gridCount; slot++) { - layoutPtr[slot].maxOffset = offset; + layoutPtr[slot].maxOffset = offset; } for (slot=gridCount-1; slot > 0;) { - for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL; - slavePtr = slavePtr->binNextPtr) { - int span = (slotType == COLUMN) ? slavePtr->numCols : slavePtr->numRows; - int require = offset - slavePtr->size; - int startSlot = slot - span; - if (startSlot >=0 && require < layoutPtr[startSlot].maxOffset) { - layoutPtr[startSlot].maxOffset = require; - } + for (slavePtr = layoutPtr[slot].binNextPtr; slavePtr != NULL; + slavePtr = slavePtr->binNextPtr) { + int span = (slotType == COLUMN) ? + slavePtr->numCols : slavePtr->numRows; + int require = offset - slavePtr->size; + int startSlot = slot - span; + + if (startSlot >=0 && require < layoutPtr[startSlot].maxOffset) { + layoutPtr[startSlot].maxOffset = require; + } } offset -= layoutPtr[slot].minSize; slot--; @@ -1967,58 +2165,56 @@ ResolveConstraints(masterPtr, slotType, maxOffset) /* * Step 5. - * At this point, each slot boundary has a range of values that - * will satisfy the overall layout size. - * Make repeated passes over the layout structure looking for - * spans of slot boundaries where the minOffsets are less than - * the maxOffsets, and adjust the offsets according to the slot - * weights. At each pass, at least one slot boundary will have - * its range of possible values fixed at a single value. + * At this point, each slot boundary has a range of values that will + * satisfy the overall layout size. Make repeated passes over the layout + * structure looking for spans of slot boundaries where the minOffsets are + * less than the maxOffsets, and adjust the offsets according to the slot + * weights. At each pass, at least one slot boundary will have its range + * of possible values fixed at a single value. */ - for (start=0; start < gridCount;) { - int totalWeight = 0; /* Sum of the weights for all of the - * slots in this span. */ - int need = 0; /* The minimum space needed to layout - * this span. */ - int have; /* The actual amount of space that will - * be taken up by this span. */ - int weight; /* Cumulative weights of the columns in - * this span. */ - int noWeights = 0; /* True if the span has no weights. */ - - /* - * Find a span by identifying ranges of slots whose edges are - * already constrained at fixed offsets, but whose internal - * slot boundaries have a range of possible positions. - */ - - if (layoutPtr[start].minOffset == layoutPtr[start].maxOffset) { + for (start = 0; start < gridCount;) { + int totalWeight = 0; /* Sum of the weights for all of the slots in + * this span. */ + int need = 0; /* The minimum space needed to layout this + * span. */ + int have; /* The actual amount of space that will be + * taken up by this span. */ + int weight; /* Cumulative weights of the columns in this + * span. */ + int noWeights = 0; /* True if the span has no weights. */ + + /* + * Find a span by identifying ranges of slots whose edges are already + * constrained at fixed offsets, but whose internal slot boundaries + * have a range of possible positions. + */ + + if (layoutPtr[start].minOffset == layoutPtr[start].maxOffset) { start++; continue; } - for (end=start+1; end<gridCount; end++) { + for (end = start + 1; end < gridCount; end++) { if (layoutPtr[end].minOffset == layoutPtr[end].maxOffset) { break; } } /* - * We found a span. Compute the total weight, minumum space required, - * for this span, and the actual amount of space the span should - * use. + * We found a span. Compute the total weight, minumum space required, + * for this span, and the actual amount of space the span should use. */ - for (slot=start; slot<=end; slot++) { + for (slot = start; slot <= end; slot++) { totalWeight += layoutPtr[slot].weight; need += layoutPtr[slot].minSize; } have = layoutPtr[end].maxOffset - layoutPtr[start-1].minOffset; /* - * If all the weights in the span are zero, then distribute the - * extra space evenly. + * If all the weights in the span are zero, then distribute the extra + * space evenly. */ if (totalWeight == 0) { @@ -2028,100 +2224,180 @@ ResolveConstraints(masterPtr, slotType, maxOffset) /* * It might not be possible to give the span all of the space - * available on this pass without violating the size constraints - * of one or more of the internal slot boundaries. - * Determine the maximum amount of space that when added to the - * entire span, would cause a slot boundary to have its possible - * range reduced to one value, and reduce the amount of extra - * space allocated on this pass accordingly. - * - * The calculation is done cumulatively to avoid accumulating - * roundoff errors. + * available on this pass without violating the size constraints of + * one or more of the internal slot boundaries. Try to determine the + * maximum amount of space that when added to the entire span, would + * cause a slot boundary to have its possible range reduced to one + * value, and reduce the amount of extra space allocated on this pass + * accordingly. + * + * The calculation is done cumulatively to avoid accumulating roundoff + * errors. */ - for (weight=0,slot=start; slot<end; slot++) { - int diff = layoutPtr[slot].maxOffset - layoutPtr[slot].minOffset; - weight += noWeights ? 1 : layoutPtr[slot].weight; - if ((noWeights || layoutPtr[slot].weight>0) && - (diff*totalWeight/weight) < (have-need)) { - have = diff * totalWeight / weight + need; + do { + int prevMinOffset = layoutPtr[start - 1].minOffset; + + prevGrow = 0; + accWeight = 0; + for (slot = start; slot <= end; slot++) { + weight = noWeights ? 1 : layoutPtr[slot].weight; + accWeight += weight; + grow = (have - need) * accWeight / totalWeight - prevGrow; + prevGrow += grow; + + if ((weight > 0) && + ((prevMinOffset + layoutPtr[slot].minSize + grow) + > layoutPtr[slot].maxOffset)) { + int newHave; + + /* + * There is not enough room to grow that much. Calculate + * how much this slot can grow and how much "have" that + * corresponds to. + */ + + grow = layoutPtr[slot].maxOffset - + layoutPtr[slot].minSize - prevMinOffset; + newHave = grow * totalWeight / weight; + if (newHave > totalWeight) { + /* + * By distributing multiples of totalWeight we + * minimize rounding errors since they will only + * happen in the last loop(s). + */ + + newHave = newHave / totalWeight * totalWeight; + } + if (newHave <= 0) { + /* + * We can end up with a "have" of 0 here if the + * previous slots have taken all the space. In that + * case we cannot guess an appropriate "have" so we + * just try some lower "have" that is >= 1, to make + * sure this terminates. + */ + + newHave = (have - need) - 1; + if (newHave > (3 * totalWeight)) { + /* + * Go down 25% for large values. + */ + newHave = newHave * 3 / 4; + } + + if (newHave > totalWeight) { + /* + * Round down to a multiple of totalWeight. + */ + newHave = newHave / totalWeight * totalWeight; + } + + if (newHave <= 0) { + newHave = 1; + } + } + have = newHave + need; + + /* + * Restart loop to check if the new "have" will fit. + */ + + break; + } + prevMinOffset += layoutPtr[slot].minSize + grow; + if (prevMinOffset < layoutPtr[slot].minOffset) { + prevMinOffset = layoutPtr[slot].minOffset; + } } - } + + /* + * Quit the outer loop if the inner loop ran all the way. + */ + } while (slot <= end); /* - * Now distribute the extra space among the slots by - * adjusting the minSizes and minOffsets. + * Now distribute the extra space among the slots by adjusting the + * minSizes and minOffsets. */ - for (weight=0,slot=start; slot<end; slot++) { - weight += noWeights ? 1 : layoutPtr[slot].weight; - layoutPtr[slot].minOffset += - (int)((double) (have-need) * weight/totalWeight + 0.5); - layoutPtr[slot].minSize = layoutPtr[slot].minOffset - - layoutPtr[slot-1].minOffset; + prevGrow = 0; + accWeight = 0; + for (slot = start; slot <= end; slot++) { + accWeight += noWeights ? 1 : layoutPtr[slot].weight; + grow = (have - need) * accWeight / totalWeight - prevGrow; + prevGrow += grow; + layoutPtr[slot].minSize += grow; + if ((layoutPtr[slot-1].minOffset + layoutPtr[slot].minSize) + > layoutPtr[slot].minOffset) { + layoutPtr[slot].minOffset = layoutPtr[slot-1].minOffset + + layoutPtr[slot].minSize; + } } - layoutPtr[slot].minSize = layoutPtr[slot].minOffset - - layoutPtr[slot-1].minOffset; /* - * Having pushed the top/left boundaries of the slots to - * take up extra space, the bottom/right space is recalculated - * to propagate the new space allocation. + * Having pushed the top/left boundaries of the slots to take up extra + * space, the bottom/right space is recalculated to propagate the new + * space allocation. */ - for (slot=end; slot > start; slot--) { - layoutPtr[slot-1].maxOffset = - layoutPtr[slot].maxOffset-layoutPtr[slot].minSize; + for (slot = end; slot > start; slot--) { + /* + * maxOffset may not go up. + */ + + if ((layoutPtr[slot].maxOffset-layoutPtr[slot].minSize) + < layoutPtr[slot-1].maxOffset) { + layoutPtr[slot-1].maxOffset = + layoutPtr[slot].maxOffset-layoutPtr[slot].minSize; + } } } - /* * Step 6. - * All of the space has been apportioned; copy the - * layout information back into the master. + * All of the space has been apportioned; copy the layout information back + * into the master. */ for (slot=0; slot < gridCount; slot++) { - slotPtr[slot].offset = layoutPtr[slot].minOffset; + slotPtr[slot].offset = layoutPtr[slot].minOffset; } --layoutPtr; if (layoutPtr != layoutData) { - ckfree((char *)layoutPtr); + ckfree((char *) layoutPtr); } return requiredSize; } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * GetGrid -- * - * This internal procedure is used to locate a Grid - * structure for a given window, creating one if one - * doesn't exist already. + * This internal procedure is used to locate a Grid structure for a given + * window, creating one if one doesn't exist already. * * Results: - * The return value is a pointer to the Grid structure - * corresponding to tkwin. + * The return value is a pointer to the Grid structure corresponding to + * tkwin. * * Side effects: - * A new grid structure may be created. If so, then - * a callback is set up to clean things up when the - * window is deleted. + * A new grid structure may be created. If so, then a callback is set up + * to clean things up when the window is deleted. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static Gridder * -GetGrid(tkwin) - Tk_Window tkwin; /* Token for window for which - * grid structure is desired. */ +GetGrid( + Tk_Window tkwin) /* Token for window for which grid structure + * is desired. */ { register Gridder *gridPtr; Tcl_HashEntry *hPtr; - int new; + int isNew; TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; if (!dispPtr->gridInit) { @@ -2130,12 +2406,12 @@ GetGrid(tkwin) } /* - * See if there's already grid for this window. If not, - * then create a new one. + * See if there's already grid for this window. If not, then create a new + * one. */ - hPtr = Tcl_CreateHashEntry(&dispPtr->gridHashTable, (char *) tkwin, &new); - if (!new) { + hPtr = Tcl_CreateHashEntry(&dispPtr->gridHashTable, (char*) tkwin, &isNew); + if (!isNew) { return (Gridder *) Tcl_GetHashValue(hPtr); } gridPtr = (Gridder *) ckalloc(sizeof(Gridder)); @@ -2146,18 +2422,23 @@ GetGrid(tkwin) gridPtr->slavePtr = NULL; gridPtr->binNextPtr = NULL; - gridPtr->column = gridPtr->row = -1; + gridPtr->column = -1; + gridPtr->row = -1; gridPtr->numCols = 1; gridPtr->numRows = 1; - gridPtr->padX = gridPtr->padY = 0; - gridPtr->padLeft = gridPtr->padTop = 0; - gridPtr->iPadX = gridPtr->iPadY = 0; + gridPtr->padX = 0; + gridPtr->padY = 0; + gridPtr->padLeft = 0; + gridPtr->padTop = 0; + gridPtr->iPadX = 0; + gridPtr->iPadY = 0; gridPtr->doubleBw = 2*Tk_Changes(tkwin)->border_width; gridPtr->abortPtr = NULL; gridPtr->flags = 0; gridPtr->sticky = 0; gridPtr->size = 0; + gridPtr->in = NULL; gridPtr->masterDataPtr = NULL; Tcl_SetHashValue(hPtr, gridPtr); Tk_CreateEventHandler(tkwin, StructureNotifyMask, @@ -2166,35 +2447,34 @@ GetGrid(tkwin) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * SetGridSize -- * - * This internal procedure sets the size of the grid occupied - * by slaves. + * This internal procedure sets the size of the grid occupied by slaves. * * Results: - * none + * None * * Side effects: - * The width and height arguments are filled in the master data structure. - * Additional space is allocated for the constraints to accomodate - * the offsets. + * The width and height arguments are filled in the master data + * structure. Additional space is allocated for the constraints to + * accomodate the offsets. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static void -SetGridSize(masterPtr) - Gridder *masterPtr; /* The geometry master for this grid. */ +SetGridSize( + Gridder *masterPtr) /* The geometry master for this grid. */ { - register Gridder *slavePtr; /* Current slave window. */ + register Gridder *slavePtr; /* Current slave window. */ int maxX = 0, maxY = 0; for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; - slavePtr = slavePtr->nextPtr) { - maxX = MAX(maxX,slavePtr->numCols + slavePtr->column); - maxY = MAX(maxY,slavePtr->numRows + slavePtr->row); + slavePtr = slavePtr->nextPtr) { + maxX = MAX(maxX, slavePtr->numCols + slavePtr->column); + maxY = MAX(maxY, slavePtr->numRows + slavePtr->row); } masterPtr->masterDataPtr->columnEnd = maxX; masterPtr->masterDataPtr->rowEnd = maxY; @@ -2207,37 +2487,37 @@ SetGridSize(masterPtr) * * SetSlaveColumn -- * - * Update column data for a slave, checking that MAX_ELEMENT bound + * Update column data for a slave, checking that MAX_ELEMENT bound * is not passed. * * Results: - * TCL_ERROR if out of bounds, TCL_OK otherwise + * TCL_ERROR if out of bounds, TCL_OK otherwise * * Side effects: - * Slave fields are updated. + * Slave fields are updated. * *---------------------------------------------------------------------- */ static int SetSlaveColumn( - Tcl_Interp *interp, /* Interp for error message */ - Gridder *slavePtr, /* Slave to be updated */ - int column, /* New column or -1 to be unchanged */ - int numCols) /* New columnspan or -1 to be unchanged */ + Tcl_Interp *interp, /* Interp for error message. */ + Gridder *slavePtr, /* Slave to be updated. */ + int column, /* New column or -1 to be unchanged. */ + int numCols) /* New columnspan or -1 to be unchanged. */ { int newColumn, newNumCols, lastCol; - newColumn = (column >= 0) ? column : slavePtr->column; + newColumn = (column >= 0) ? column : slavePtr->column; newNumCols = (numCols >= 1) ? numCols : slavePtr->numCols; - lastCol = ((newColumn >= 0) ? newColumn : 0) + newNumCols; + lastCol = ((newColumn >= 0) ? newColumn : 0) + newNumCols; if (lastCol >= MAX_ELEMENT) { - Tcl_SetResult(interp, "Column out of bounds", TCL_STATIC); - return TCL_ERROR; + Tcl_SetResult(interp, "Column out of bounds", TCL_STATIC); + return TCL_ERROR; } - slavePtr->column = newColumn; + slavePtr->column = newColumn; slavePtr->numCols = newNumCols; return TCL_OK; } @@ -2247,70 +2527,70 @@ SetSlaveColumn( * * SetSlaveRow -- * - * Update row data for a slave, checking that MAX_ELEMENT bound + * Update row data for a slave, checking that MAX_ELEMENT bound * is not passed. * * Results: - * TCL_ERROR if out of bounds, TCL_OK otherwise + * TCL_ERROR if out of bounds, TCL_OK otherwise * * Side effects: - * Slave fields are updated. + * Slave fields are updated. * *---------------------------------------------------------------------- */ static int SetSlaveRow( - Tcl_Interp *interp, /* Interp for error message */ - Gridder *slavePtr, /* Slave to be updated */ - int row, /* New row or -1 to be unchanged */ - int numRows) /* New rowspan or -1 to be unchanged */ + Tcl_Interp *interp, /* Interp for error message. */ + Gridder *slavePtr, /* Slave to be updated. */ + int row, /* New row or -1 to be unchanged. */ + int numRows) /* New rowspan or -1 to be unchanged. */ { int newRow, newNumRows, lastRow; - newRow = (row >= 0) ? row : slavePtr->row; + newRow = (row >= 0) ? row : slavePtr->row; newNumRows = (numRows >= 1) ? numRows : slavePtr->numRows; - lastRow = ((newRow >= 0) ? newRow : 0) + newNumRows; + lastRow = ((newRow >= 0) ? newRow : 0) + newNumRows; if (lastRow >= MAX_ELEMENT) { - Tcl_SetResult(interp, "Row out of bounds", TCL_STATIC); - return TCL_ERROR; + Tcl_SetResult(interp, "Row out of bounds", TCL_STATIC); + return TCL_ERROR; } - slavePtr->row = newRow; + slavePtr->row = newRow; slavePtr->numRows = newNumRows; return TCL_OK; } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * CheckSlotData -- * - * This internal procedure is used to manage the storage for - * row and column (slot) constraints. + * This internal procedure is used to manage the storage for row and + * column (slot) constraints. * * Results: * TRUE if the index is OK, False otherwise. * * Side effects: - * A new master grid structure may be created. If so, then - * it is initialized. In addition, additional storage for - * a row or column constraints may be allocated, and the constraint - * maximums are adjusted. + * A new master grid structure may be created. If so, then it is + * initialized. In addition, additional storage for a row or column + * constraints may be allocated, and the constraint maximums are + * adjusted. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static int -CheckSlotData(masterPtr, slot, slotType, checkOnly) - Gridder *masterPtr; /* the geometry master for this grid */ - int slot; /* which slot to look at */ - int slotType; /* ROW or COLUMN */ - int checkOnly; /* don't allocate new space if true */ +CheckSlotData( + Gridder *masterPtr, /* The geometry master for this grid. */ + int slot, /* Which slot to look at. */ + int slotType, /* ROW or COLUMN. */ + int checkOnly) /* Don't allocate new space if true. */ { - int numSlot; /* number of slots already allocated (Space) */ - int end; /* last used constraint */ + int numSlot; /* Number of slots already allocated (Space) */ + int end; /* Last used constraint. */ /* * If slot is out of bounds, return immediately. @@ -2326,35 +2606,36 @@ CheckSlotData(masterPtr, slot, slotType, checkOnly) /* * If we need to allocate more space, allocate a little extra to avoid - * repeated re-alloc's for large tables. We need enough space to - * hold all of the offsets as well. + * repeated re-alloc's for large tables. We need enough space to hold all + * of the offsets as well. */ InitMasterData(masterPtr); end = (slotType == ROW) ? masterPtr->masterDataPtr->rowMax : masterPtr->masterDataPtr->columnMax; if (checkOnly == CHECK_ONLY) { - return (end < slot) ? TCL_ERROR : TCL_OK; + return ((end < slot) ? TCL_ERROR : TCL_OK); } else { - numSlot = (slotType == ROW) ? masterPtr->masterDataPtr->rowSpace - : masterPtr->masterDataPtr->columnSpace; + numSlot = (slotType == ROW) ? masterPtr->masterDataPtr->rowSpace + : masterPtr->masterDataPtr->columnSpace; if (slot >= numSlot) { - int newNumSlot = slot + PREALLOC ; - size_t oldSize = numSlot * sizeof(SlotInfo) ; - size_t newSize = newNumSlot * sizeof(SlotInfo) ; - SlotInfo *new = (SlotInfo *) ckalloc(newSize); - SlotInfo *old = (slotType == ROW) ? - masterPtr->masterDataPtr->rowPtr : - masterPtr->masterDataPtr->columnPtr; - memcpy((VOID *) new, (VOID *) old, oldSize ); - memset((VOID *) (new+numSlot), 0, newSize - oldSize ); - ckfree((char *) old); + int newNumSlot = slot + PREALLOC; + size_t oldSize = numSlot * sizeof(SlotInfo); + size_t newSize = newNumSlot * sizeof(SlotInfo); + SlotInfo *newSI = (SlotInfo *) ckalloc(newSize); + SlotInfo *oldSI = (slotType == ROW) + ? masterPtr->masterDataPtr->rowPtr + : masterPtr->masterDataPtr->columnPtr; + + memcpy(newSI, oldSI, oldSize); + memset(newSI+numSlot, 0, newSize - oldSize); + ckfree((char *) oldSI); if (slotType == ROW) { - masterPtr->masterDataPtr->rowPtr = new ; - masterPtr->masterDataPtr->rowSpace = newNumSlot ; + masterPtr->masterDataPtr->rowPtr = newSI; + masterPtr->masterDataPtr->rowSpace = newNumSlot; } else { - masterPtr->masterDataPtr->columnPtr = new; - masterPtr->masterDataPtr->columnSpace = newNumSlot ; + masterPtr->masterDataPtr->columnPtr = newSI; + masterPtr->masterDataPtr->columnSpace = newNumSlot; } } if (slot >= end && checkOnly != CHECK_SPACE) { @@ -2369,33 +2650,31 @@ CheckSlotData(masterPtr, slot, slotType, checkOnly) } /* - *-------------------------------------------------------------- + *---------------------------------------------------------------------- * * InitMasterData -- * - * This internal procedure is used to allocate and initialize - * the data for a geometry master, if the data - * doesn't exist already. + * This internal procedure is used to allocate and initialize the data + * for a geometry master, if the data doesn't exist already. * * Results: * none * * Side effects: - * A new master grid structure may be created. If so, then - * it is initialized. + * A new master grid structure may be created. If so, then it is + * initialized. * - *-------------------------------------------------------------- + *---------------------------------------------------------------------- */ static void -InitMasterData(masterPtr) - Gridder *masterPtr; +InitMasterData( + Gridder *masterPtr) { - size_t size; if (masterPtr->masterDataPtr == NULL) { - GridMaster *gridPtr = masterPtr->masterDataPtr = - (GridMaster *) ckalloc(sizeof(GridMaster)); - size = sizeof(SlotInfo) * TYPICAL_SIZE; + GridMaster *gridPtr = masterPtr->masterDataPtr = (GridMaster *) + ckalloc(sizeof(GridMaster)); + size_t size = sizeof(SlotInfo) * TYPICAL_SIZE; gridPtr->columnEnd = 0; gridPtr->columnMax = 0; @@ -2407,9 +2686,10 @@ InitMasterData(masterPtr) gridPtr->rowSpace = TYPICAL_SIZE; gridPtr->startX = 0; gridPtr->startY = 0; + gridPtr->anchor = GRID_DEFAULT_ANCHOR; - memset((VOID *) gridPtr->columnPtr, 0, size); - memset((VOID *) gridPtr->rowPtr, 0, size); + memset(gridPtr->columnPtr, 0, size); + memset(gridPtr->rowPtr, 0, size); } } @@ -2418,21 +2698,21 @@ InitMasterData(masterPtr) * * Unlink -- * - * Remove a grid from its parent's list of slaves. + * Remove a grid from its master's list of slaves. * * Results: * None. * * Side effects: - * The parent will be scheduled for re-arranging, and the size of the + * The master will be scheduled for re-arranging, and the size of the * grid will be adjusted accordingly * *---------------------------------------------------------------------- */ static void -Unlink(slavePtr) - register Gridder *slavePtr; /* Window to unlink. */ +Unlink( + register Gridder *slavePtr) /* Window to unlink. */ { register Gridder *masterPtr, *slavePtr2; @@ -2444,9 +2724,9 @@ Unlink(slavePtr) if (masterPtr->slavePtr == slavePtr) { masterPtr->slavePtr = slavePtr->nextPtr; } else { - for (slavePtr2 = masterPtr->slavePtr; ; slavePtr2 = slavePtr2->nextPtr) { + for (slavePtr2=masterPtr->slavePtr ; ; slavePtr2=slavePtr2->nextPtr) { if (slavePtr2 == NULL) { - panic("Unlink couldn't find previous window"); + Tcl_Panic("Unlink couldn't find previous window"); } if (slavePtr2->nextPtr == slavePtr) { slavePtr2->nextPtr = slavePtr->nextPtr; @@ -2471,11 +2751,11 @@ Unlink(slavePtr) * * DestroyGrid -- * - * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release - * to clean up the internal structure of a grid at a safe time - * (when no-one is using it anymore). Cleaning up the grid involves - * freeing the main structure for all windows. and the master structure - * for geometry managers. + * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release to + * clean up the internal structure of a grid at a safe time (when no-one + * is using it anymore). Cleaning up the grid involves freeing the main + * structure for all windows and the master structure for geometry + * managers. * * Results: * None. @@ -2487,8 +2767,8 @@ Unlink(slavePtr) */ static void -DestroyGrid(memPtr) - char *memPtr; /* Info about window that is now dead. */ +DestroyGrid( + char *memPtr) /* Info about window that is now dead. */ { register Gridder *gridPtr = (Gridder *) memPtr; @@ -2501,6 +2781,9 @@ DestroyGrid(memPtr) } ckfree((char *) gridPtr->masterDataPtr); } + if (gridPtr->in != NULL) { + Tcl_DecrRefCount(gridPtr->in); + } ckfree((char *) gridPtr); } @@ -2509,37 +2792,37 @@ DestroyGrid(memPtr) * * GridStructureProc -- * - * This procedure is invoked by the Tk event dispatcher in response - * to StructureNotify events. + * This procedure is invoked by the Tk event dispatcher in response to + * StructureNotify events. * * Results: * None. * * Side effects: * If a window was just deleted, clean up all its grid-related - * information. If it was just resized, re-configure its slaves, if - * any. + * information. If it was just resized, re-configure its slaves, if any. * *---------------------------------------------------------------------- */ static void -GridStructureProc(clientData, eventPtr) - ClientData clientData; /* Our information about window - * referred to by eventPtr. */ - XEvent *eventPtr; /* Describes what just happened. */ +GridStructureProc( + ClientData clientData, /* Our information about window referred to by + * eventPtr. */ + XEvent *eventPtr) /* Describes what just happened. */ { register Gridder *gridPtr = (Gridder *) clientData; TkDisplay *dispPtr = ((TkWindow *) gridPtr->tkwin)->dispPtr; if (eventPtr->type == ConfigureNotify) { - if (!(gridPtr->flags & REQUESTED_RELAYOUT)) { + if ((gridPtr->slavePtr != NULL) + && !(gridPtr->flags & REQUESTED_RELAYOUT)) { gridPtr->flags |= REQUESTED_RELAYOUT; Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr); } - if (gridPtr->doubleBw != 2*Tk_Changes(gridPtr->tkwin)->border_width) { - if ((gridPtr->masterPtr != NULL) && - !(gridPtr->masterPtr->flags & REQUESTED_RELAYOUT)) { + if ((gridPtr->masterPtr != NULL) && + (gridPtr->doubleBw != 2*Tk_Changes(gridPtr->tkwin)->border_width)) { + if (!(gridPtr->masterPtr->flags & REQUESTED_RELAYOUT)) { gridPtr->doubleBw = 2*Tk_Changes(gridPtr->tkwin)->border_width; gridPtr->masterPtr->flags |= REQUESTED_RELAYOUT; Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr->masterPtr); @@ -2552,7 +2835,7 @@ GridStructureProc(clientData, eventPtr) Unlink(gridPtr); } for (gridPtr2 = gridPtr->slavePtr; gridPtr2 != NULL; - gridPtr2 = nextPtr) { + gridPtr2 = nextPtr) { Tk_UnmapWindow(gridPtr2->tkwin); gridPtr2->masterPtr = NULL; nextPtr = gridPtr2->nextPtr; @@ -2566,7 +2849,8 @@ GridStructureProc(clientData, eventPtr) gridPtr->tkwin = NULL; Tcl_EventuallyFree((ClientData) gridPtr, DestroyGrid); } else if (eventPtr->type == MapNotify) { - if (!(gridPtr->flags & REQUESTED_RELAYOUT)) { + if ((gridPtr->slavePtr != NULL) + && !(gridPtr->flags & REQUESTED_RELAYOUT)) { gridPtr->flags |= REQUESTED_RELAYOUT; Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr); } @@ -2574,7 +2858,7 @@ GridStructureProc(clientData, eventPtr) register Gridder *gridPtr2; for (gridPtr2 = gridPtr->slavePtr; gridPtr2 != NULL; - gridPtr2 = gridPtr2->nextPtr) { + gridPtr2 = gridPtr2->nextPtr) { Tk_UnmapWindow(gridPtr2->tkwin); } } @@ -2585,15 +2869,14 @@ GridStructureProc(clientData, eventPtr) * * ConfigureSlaves -- * - * This implements the guts of the "grid configure" command. Given - * a list of slaves and configuration options, it arranges for the - * grid to manage the slaves and sets the specified options. - * arguments consist of windows or window shortcuts followed by - * "-option value" pairs. + * This implements the guts of the "grid configure" command. Given a list + * of slaves and configuration options, it arranges for the grid to + * manage the slaves and sets the specified options. Arguments consist + * of windows or window shortcuts followed by "-option value" pairs. * * Results: - * TCL_OK is returned if all went well. Otherwise, TCL_ERROR is - * returned and the interp's result is set to contain an error message. + * TCL_OK is returned if all went well. Otherwise, TCL_ERROR is returned + * and the interp's result is set to contain an error message. * * Side effects: * Slave windows get taken over by the grid. @@ -2602,57 +2885,90 @@ GridStructureProc(clientData, eventPtr) */ static int -ConfigureSlaves(interp, tkwin, objc, objv) - Tcl_Interp *interp; /* Interpreter for error reporting. */ - Tk_Window tkwin; /* Any window in application containing - * slaves. Used to look up slave names. */ - int objc; /* Number of elements in argv. */ - Tcl_Obj *CONST objv[]; /* Argument objects: contains one or more - * window names followed by any number - * of "option value" pairs. Caller must - * make sure that there is at least one - * window name. */ +ConfigureSlaves( + Tcl_Interp *interp, /* Interpreter for error reporting. */ + Tk_Window tkwin, /* Any window in application containing + * slaves. Used to look up slave names. */ + int objc, /* Number of elements in argv. */ + Tcl_Obj *CONST objv[]) /* Argument objects: contains one or more + * window names followed by any number of + * "option value" pairs. Caller must make sure + * that there is at least one window name. */ { - Gridder *masterPtr; + Gridder *masterPtr = NULL; Gridder *slavePtr; Tk_Window other, slave, parent, ancestor; int i, j, tmp; - int length; int numWindows; int width; - int defaultColumn = 0; /* default column number */ - int defaultColumnSpan = 1; /* default number of columns */ - char *lastWindow; /* use this window to base current - * Row/col on */ - int numSkip; /* number of 'x' found */ + int defaultRow = -1; + int defaultColumn = 0; /* Default column number */ + int defaultColumnSpan = 1; /* Default number of columns */ + char *lastWindow; /* Use this window to base current row/col + * on */ + int numSkip; /* Number of 'x' found */ static CONST char *optionStrings[] = { "-column", "-columnspan", "-in", "-ipadx", "-ipady", - "-padx", "-pady", "-row", "-rowspan", "-sticky", - (char *) NULL }; + "-padx", "-pady", "-row", "-rowspan", "-sticky", NULL + }; enum options { CONF_COLUMN, CONF_COLUMNSPAN, CONF_IN, CONF_IPADX, CONF_IPADY, CONF_PADX, CONF_PADY, CONF_ROW, CONF_ROWSPAN, CONF_STICKY }; int index; char *string; - char firstChar, prevChar; + char firstChar; + int positionGiven; /* * Count the number of windows, or window short-cuts. */ firstChar = 0; - for (numWindows = i = 0; i < objc; i++) { - prevChar = firstChar; + for (numWindows=0, i=0; i < objc; i++) { + int length; + char prevChar = firstChar; + string = Tcl_GetStringFromObj(objv[i], &length); firstChar = string[0]; - + if (firstChar == '.') { + /* + * Check that windows are valid, and locate the first slave's + * parent window (default for -in). + */ + + if (TkGetWindowFromObj(interp, tkwin, objv[i], &slave) != TCL_OK) { + return TCL_ERROR; + } + if (masterPtr == NULL) { + /* + * Is there any saved -in from a removed slave? + * If there is, it becomes default for -in. + * If the stored master does not exist, just ignore it. + */ + + struct Gridder *slavePtr = GetGrid(slave); + if (slavePtr->in != NULL) { + if (TkGetWindowFromObj(interp, slave, slavePtr->in, &parent) + == TCL_OK) { + masterPtr = GetGrid(parent); + InitMasterData(masterPtr); + } + } + } + if (masterPtr == NULL) { + parent = Tk_Parent(slave); + if (parent != NULL) { + masterPtr = GetGrid(parent); + InitMasterData(masterPtr); + } + } numWindows++; continue; } if (length > 1 && i == 0) { Tcl_AppendResult(interp, "bad argument \"", string, - "\": must be name of window", (char *) NULL); + "\": must be name of window", NULL); return TCL_ERROR; } if (length > 1 && firstChar == '-') { @@ -2661,15 +2977,14 @@ ConfigureSlaves(interp, tkwin, objc, objv) if (length > 1) { Tcl_AppendResult(interp, "unexpected parameter, \"", string, "\", in configure list. ", - "Should be window name or option", (char *) NULL); + "Should be window name or option", NULL); return TCL_ERROR; } if ((firstChar == REL_HORIZ) && ((numWindows == 0) || (prevChar == REL_SKIP) || (prevChar == REL_VERT))) { Tcl_AppendResult(interp, - "Must specify window before shortcut '-'.", - (char *) NULL); + "Must specify window before shortcut '-'.", NULL); return TCL_ERROR; } @@ -2679,36 +2994,79 @@ ConfigureSlaves(interp, tkwin, objc, objv) } Tcl_AppendResult(interp, "invalid window shortcut, \"", - string, "\" should be '-', 'x', or '^'", (char *) NULL); + string, "\" should be '-', 'x', or '^'", NULL); return TCL_ERROR; } numWindows = i; if ((objc - numWindows) & 1) { - Tcl_AppendResult(interp, "extra option or", - " option with no value", (char *) NULL); + Tcl_AppendResult(interp, "extra option or option with no value", NULL); return TCL_ERROR; } /* - * Iterate over all of the slave windows and short-cuts, parsing - * options for each slave. It's a bit wasteful to re-parse the - * options for each slave, but things get too messy if we try to - * parse the arguments just once at the beginning. For example, - * if a slave already is managed we want to just change a few - * existing values without resetting everything. If there are - * multiple windows, the -in option only gets processed for the - * first window. + * Go through all options looking for -in and -row, which are needed to be + * found first to handle the special case where ^ is used on a row without + * windows names, but with an -in option. Since all options are checked + * here, we do not need to handle the error case again later. + */ + + for (i = numWindows; i < objc; i += 2) { + if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == CONF_IN) { + if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other) != + TCL_OK) { + return TCL_ERROR; + } + masterPtr = GetGrid(other); + InitMasterData(masterPtr); + } else if (index == CONF_ROW) { + if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK + || tmp < 0) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "bad row value \"", + Tcl_GetString(objv[i+1]), "\": must be ", + "a non-negative integer", NULL); + return TCL_ERROR; + } + defaultRow = tmp; + } + } + + /* + * If no -row is given, use the first unoccupied row of the master. + */ + + if (defaultRow < 0) { + if (masterPtr != NULL && masterPtr->masterDataPtr != NULL) { + SetGridSize(masterPtr); + defaultRow = masterPtr->masterDataPtr->rowEnd; + } else { + defaultRow = 0; + } + } + + /* + * Iterate over all of the slave windows and short-cuts, parsing options + * for each slave. It's a bit wasteful to re-parse the options for each + * slave, but things get too messy if we try to parse the arguments just + * once at the beginning. For example, if a slave already is managed we + * want to just change a few existing values without resetting everything. + * If there are multiple windows, the -in option only gets processed for + * the first window. */ - masterPtr = NULL; + positionGiven = 0; for (j = 0; j < numWindows; j++) { string = Tcl_GetString(objv[j]); firstChar = string[0]; /* - * '^' and 'x' cause us to skip a column. '-' is processed - * as part of its preceeding slave. + * '^' and 'x' cause us to skip a column. '-' is processed as part of + * its preceeding slave. */ if ((firstChar == REL_VERT) || (firstChar == REL_SKIP)) { @@ -2722,6 +3080,7 @@ ConfigureSlaves(interp, tkwin, objc, objv) for (defaultColumnSpan = 1; j + defaultColumnSpan < numWindows; defaultColumnSpan++) { char *string = Tcl_GetString(objv[j + defaultColumnSpan]); + if (*string != REL_HORIZ) { break; } @@ -2733,7 +3092,7 @@ ConfigureSlaves(interp, tkwin, objc, objv) if (Tk_TopWinHierarchy(slave)) { Tcl_AppendResult(interp, "can't manage \"", Tcl_GetString(objv[j]), - "\": it's a top-level window", (char *) NULL); + "\": it's a top-level window", NULL); return TCL_ERROR; } slavePtr = GetGrid(slave); @@ -2742,49 +3101,48 @@ ConfigureSlaves(interp, tkwin, objc, objv) * The following statement is taken from tkPack.c: * * "If the slave isn't currently managed, reset all of its - * configuration information to default values (there could - * be old values left from a previous packer)." + * configuration information to default values (there could be old + * values left from a previous packer)." * - * I [D.S.] disagree with this statement. If a slave is disabled (using - * "forget") and then re-enabled, I submit that 90% of the time the - * programmer will want it to retain its old configuration information. - * If the programmer doesn't want this behavior, then the + * I [D.S.] disagree with this statement. If a slave is disabled + * (using "forget") and then re-enabled, I submit that 90% of the time + * the programmer will want it to retain its old configuration + * information. If the programmer doesn't want this behavior, then the * defaults can be reestablished by hand, without having to worry - * about keeping track of the old state. + * about keeping track of the old state. */ for (i = numWindows; i < objc; i += 2) { - if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", 0, - &index) != TCL_OK) { - return TCL_ERROR; - } - if (index == CONF_COLUMN) { - if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK || - tmp < 0) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "bad column value \"", - Tcl_GetString(objv[i+1]), - "\": must be a non-negative integer", (char *)NULL); + Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", 0, + &index); + switch ((enum options) index) { + case CONF_COLUMN: + if (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK + || tmp < 0) { + Tcl_AppendResult(interp, "bad column value \"", + Tcl_GetString(objv[i+1]), "\": must be ", + "a non-negative integer", NULL); return TCL_ERROR; } if (SetSlaveColumn(interp, slavePtr, tmp, -1) != TCL_OK) { return TCL_ERROR; } - } else if (index == CONF_COLUMNSPAN) { - if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK || - tmp <= 0) { - Tcl_ResetResult(interp); + break; + case CONF_COLUMNSPAN: + if (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK + || tmp <= 0) { Tcl_AppendResult(interp, "bad columnspan value \"", - Tcl_GetString(objv[i+1]), - "\": must be a positive integer", (char *)NULL); + Tcl_GetString(objv[i+1]), "\": must be ", + "a positive integer", NULL); return TCL_ERROR; } if (SetSlaveColumn(interp, slavePtr, -1, tmp) != TCL_OK) { return TCL_ERROR; } - } else if (index == CONF_IN) { - if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other) != - TCL_OK) { + break; + case CONF_IN: + if (TkGetWindowFromObj(interp, tkwin, objv[i+1], + &other) != TCL_OK) { return TCL_ERROR; } if (other == slave) { @@ -2792,89 +3150,106 @@ ConfigureSlaves(interp, tkwin, objc, objv) TCL_STATIC); return TCL_ERROR; } + positionGiven = 1; masterPtr = GetGrid(other); InitMasterData(masterPtr); - } else if (index == CONF_IPADX) { - if ((Tk_GetPixelsFromObj(interp, slave, objv[i+1], &tmp) - != TCL_OK) - || (tmp < 0)) { - Tcl_ResetResult(interp); + break; + case CONF_STICKY: { + int sticky = StringToSticky(Tcl_GetString(objv[i+1])); + + if (sticky == -1) { + Tcl_AppendResult(interp, "bad stickyness value \"", + Tcl_GetString(objv[i+1]), "\": must be ", + "a string containing n, e, s, and/or w", NULL); + return TCL_ERROR; + } + slavePtr->sticky = sticky; + break; + } + case CONF_IPADX: + if ((Tk_GetPixelsFromObj(NULL, slave, objv[i+1], + &tmp) != TCL_OK) || (tmp < 0)) { Tcl_AppendResult(interp, "bad ipadx value \"", - Tcl_GetString(objv[i+1]), - "\": must be positive screen distance", - (char *) NULL); + Tcl_GetString(objv[i+1]), "\": must be ", + "positive screen distance", NULL); return TCL_ERROR; } slavePtr->iPadX = tmp*2; - } else if (index == CONF_IPADY) { - if ((Tk_GetPixelsFromObj(interp, slave, objv[i+1], &tmp) - != TCL_OK) - || (tmp < 0)) { - Tcl_ResetResult(interp); + break; + case CONF_IPADY: + if ((Tk_GetPixelsFromObj(NULL, slave, objv[i+1], + &tmp) != TCL_OK) || (tmp < 0)) { Tcl_AppendResult(interp, "bad ipady value \"", - Tcl_GetString(objv[i+1]), - "\": must be positive screen distance", - (char *) NULL); + Tcl_GetString(objv[i+1]), "\": must be ", + "positive screen distance", NULL); return TCL_ERROR; } slavePtr->iPadY = tmp*2; - } else if (index == CONF_PADX) { + break; + case CONF_PADX: if (TkParsePadAmount(interp, tkwin, objv[i+1], &slavePtr->padLeft, &slavePtr->padX) != TCL_OK) { return TCL_ERROR; } - } else if (index == CONF_PADY) { + break; + case CONF_PADY: if (TkParsePadAmount(interp, tkwin, objv[i+1], &slavePtr->padTop, &slavePtr->padY) != TCL_OK) { return TCL_ERROR; } - } else if (index == CONF_ROW) { - if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK + break; + case CONF_ROW: + if (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK || tmp < 0) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "bad grid value \"", + Tcl_AppendResult(interp, "bad row value \"", Tcl_GetString(objv[i+1]), - "\": must be a non-negative integer", (char *)NULL); + "\": must be a non-negative integer", NULL); return TCL_ERROR; } if (SetSlaveRow(interp, slavePtr, tmp, -1) != TCL_OK) { return TCL_ERROR; } - } else if (index == CONF_ROWSPAN) { - if ((Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) + break; + case CONF_ROWSPAN: + if ((Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK) || tmp <= 0) { - Tcl_ResetResult(interp); Tcl_AppendResult(interp, "bad rowspan value \"", Tcl_GetString(objv[i+1]), - "\": must be a positive integer", (char *)NULL); + "\": must be a positive integer", NULL); return TCL_ERROR; } if (SetSlaveRow(interp, slavePtr, -1, tmp) != TCL_OK) { return TCL_ERROR; } - } else if (index == CONF_STICKY) { - int sticky = StringToSticky(Tcl_GetString(objv[i+1])); - if (sticky == -1) { - Tcl_AppendResult(interp, "bad stickyness value \"", - Tcl_GetString(objv[i+1]), - "\": must be a string containing n, e, s, and/or w", - (char *)NULL); - return TCL_ERROR; - } - slavePtr->sticky = sticky; + break; } } /* - * Make sure we have a geometry master. We look at: - * 1) the -in flag - * 2) the geometry master of the first slave (if specified) - * 3) the parent of the first slave. + * If no position was specified via -in and the slave is already + * packed, then leave it in its current location. */ - - if (masterPtr == NULL) { + + if (!positionGiven && (slavePtr->masterPtr != NULL)) { masterPtr = slavePtr->masterPtr; + goto scheduleLayout; } + + /* + * If the same -in window is passed in again, then just leave it in + * its current location. + */ + + if (positionGiven && (masterPtr == slavePtr->masterPtr)) { + goto scheduleLayout; + } + + /* + * Make sure we have a geometry master. We look at: + * 1) the -in flag + * 2) the parent of the first slave. + */ + parent = Tk_Parent(slave); if (masterPtr == NULL) { masterPtr = GetGrid(parent); @@ -2888,15 +3263,16 @@ ConfigureSlaves(interp, tkwin, objc, objv) if (slavePtr->masterPtr == NULL) { Gridder *tempPtr = masterPtr->slavePtr; + slavePtr->masterPtr = masterPtr; masterPtr->slavePtr = slavePtr; slavePtr->nextPtr = tempPtr; } /* - * Make sure that the slave's parent is either the master or - * an ancestor of the master, and that the master and slave - * aren't the same. + * Make sure that the slave's parent is either the master or an + * ancestor of the master, and that the master and slave aren't the + * same. */ for (ancestor = masterPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) { @@ -2905,8 +3281,7 @@ ConfigureSlaves(interp, tkwin, objc, objv) } if (Tk_TopWinHierarchy(ancestor)) { Tcl_AppendResult(interp, "can't put ", Tcl_GetString(objv[j]), - " inside ", Tk_PathName(masterPtr->tkwin), - (char *) NULL); + " inside ", Tk_PathName(masterPtr->tkwin), NULL); Unlink(slavePtr); return TCL_ERROR; } @@ -2919,8 +3294,7 @@ ConfigureSlaves(interp, tkwin, objc, objv) if (masterPtr->masterPtr == slavePtr) { Tcl_AppendResult(interp, "can't put ", Tcl_GetString(objv[j]), " inside ", Tk_PathName(masterPtr->tkwin), - ", would cause management loop.", - (char *) NULL); + ", would cause management loop.", NULL); Unlink(slavePtr); return TCL_ERROR; } @@ -2932,7 +3306,7 @@ ConfigureSlaves(interp, tkwin, objc, objv) */ if (slavePtr->column == -1) { - if (SetSlaveColumn(interp, slavePtr, defaultColumn, -1) != TCL_OK) { + if (SetSlaveColumn(interp, slavePtr, defaultColumn,-1) != TCL_OK){ return TCL_ERROR; } } @@ -2941,23 +3315,18 @@ ConfigureSlaves(interp, tkwin, objc, objv) return TCL_ERROR; } if (slavePtr->row == -1) { - if (masterPtr->masterDataPtr == NULL) { - slavePtr->row = 0; - } else { - if (SetSlaveRow(interp, slavePtr, - masterPtr->masterDataPtr->rowEnd, -1) != TCL_OK) { - return TCL_ERROR; - } + if (SetSlaveRow(interp, slavePtr, defaultRow, -1) != TCL_OK) { + return TCL_ERROR; } } defaultColumn += slavePtr->numCols; defaultColumnSpan = 1; /* - * Arrange for the parent to be re-arranged at the first - * idle moment. + * Arrange for the master to be re-arranged at the first idle moment. */ + scheduleLayout: if (masterPtr->abortPtr != NULL) { *masterPtr->abortPtr = 1; } @@ -2967,14 +3336,16 @@ ConfigureSlaves(interp, tkwin, objc, objv) } } - /* Now look for all the "^"'s. */ + /* + * Now look for all the "^"'s. + */ lastWindow = NULL; numSkip = 0; for (j = 0; j < numWindows; j++) { struct Gridder *otherPtr; - int match; /* found a match for the ^ */ - int lastRow, lastColumn; /* implied end of table */ + int match; /* Found a match for the ^ */ + int lastRow, lastColumn; /* Implied end of table. */ string = Tcl_GetString(objv[j]); firstChar = string[0]; @@ -2991,28 +3362,28 @@ ConfigureSlaves(interp, tkwin, objc, objv) } if (masterPtr == NULL) { - Tcl_AppendResult(interp, "can't use '^', cant find master", - (char *) NULL); + Tcl_AppendResult(interp, "can't use '^', cant find master", NULL); return TCL_ERROR; } - /* Count the number of consecutive ^'s starting from this position */ + /* + * Count the number of consecutive ^'s starting from this position. + */ + for (width = 1; width + j < numWindows; width++) { char *string = Tcl_GetString(objv[j+width]); - if (*string != REL_VERT) break; + + if (*string != REL_VERT) { + break; + } } /* * Find the implied grid location of the ^ */ - if (lastWindow == NULL) { - if (masterPtr->masterDataPtr != NULL) { - SetGridSize(masterPtr); - lastRow = masterPtr->masterDataPtr->rowEnd - 2; - } else { - lastRow = 0; - } + if (lastWindow == NULL) { + lastRow = defaultRow - 1; lastColumn = 0; } else { other = Tk_NameToWindow(interp, lastWindow, tkwin); @@ -3023,13 +3394,13 @@ ConfigureSlaves(interp, tkwin, objc, objv) lastColumn += numSkip; - for (match=0, slavePtr = masterPtr->slavePtr; slavePtr != NULL; - slavePtr = slavePtr->nextPtr) { + match = 0; + for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; + slavePtr = slavePtr->nextPtr) { if (slavePtr->column == lastColumn && slavePtr->row + slavePtr->numRows - 1 == lastRow) { if (slavePtr->numCols <= width) { - if (SetSlaveRow(interp, slavePtr, -1, slavePtr->numRows + 1) != TCL_OK) { return TCL_ERROR; @@ -3044,14 +3415,13 @@ ConfigureSlaves(interp, tkwin, objc, objv) } if (!match) { Tcl_AppendResult(interp, "can't find slave to extend with \"^\".", - (char *) NULL); + NULL); return TCL_ERROR; } } if (masterPtr == NULL) { - Tcl_AppendResult(interp, "can't determine master window", - (char *) NULL); + Tcl_AppendResult(interp, "can't determine master window", NULL); return TCL_ERROR; } SetGridSize(masterPtr); @@ -3063,8 +3433,8 @@ ConfigureSlaves(interp, tkwin, objc, objv) * * StickyToString * - * Converts the internal boolean combination of "sticky" bits onto - * a TCL list element containing zero or mor of n, s, e, or w. + * Converts the internal boolean combination of "sticky" bits onto a Tcl + * list element containing zero or more of n, s, e, or w. * * Results: * A string is placed into the "result" pointer. @@ -3076,9 +3446,9 @@ ConfigureSlaves(interp, tkwin, objc, objv) */ static void -StickyToString(flags, result) - int flags; /* the sticky flags */ - char *result; /* where to put the result */ +StickyToString( + int flags, /* The sticky flags. */ + char *result) /* Where to put the result. */ { int count = 0; if (flags&STICK_NORTH) { @@ -3096,7 +3466,7 @@ StickyToString(flags, result) if (count) { result[count] = '\0'; } else { - sprintf(result,"{}"); + sprintf(result, "{}"); } } @@ -3105,12 +3475,12 @@ StickyToString(flags, result) * * StringToSticky -- * - * Converts an ascii string representing a widgets stickyness - * into the boolean result. + * Converts an ascii string representing a widgets stickyness into the + * boolean result. * * Results: - * The boolean combination of the "sticky" bits is retuned. If an - * error occurs, such as an invalid character, -1 is returned instead. + * The boolean combination of the "sticky" bits is retuned. If an error + * occurs, such as an invalid character, -1 is returned instead. * * Side effects: * none @@ -3119,20 +3489,30 @@ StickyToString(flags, result) */ static int -StringToSticky(string) - char *string; +StringToSticky( + char *string) { int sticky = 0; char c; while ((c = *string++) != '\0') { switch (c) { - case 'n': case 'N': sticky |= STICK_NORTH; break; - case 'e': case 'E': sticky |= STICK_EAST; break; - case 's': case 'S': sticky |= STICK_SOUTH; break; - case 'w': case 'W': sticky |= STICK_WEST; break; - case ' ': case ',': case '\t': case '\r': case '\n': break; - default: return -1; + case 'n': case 'N': + sticky |= STICK_NORTH; + break; + case 'e': case 'E': + sticky |= STICK_EAST; + break; + case 's': case 'S': + sticky |= STICK_SOUTH; + break; + case 'w': case 'W': + sticky |= STICK_WEST; + break; + case ' ': case ',': case '\t': case '\r': case '\n': + break; + default: + return -1; } } return sticky; @@ -3155,14 +3535,14 @@ StringToSticky(string) */ static Tcl_Obj * -NewPairObj(interp, val1, val2) - Tcl_Interp *interp; /* Current interpreter. */ - int val1, val2; +NewPairObj( + int val1, int val2) { - Tcl_Obj *res = Tcl_NewListObj(0, NULL); - Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(val1)); - Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(val2)); - return res; + Tcl_Obj *ary[2]; + + ary[0] = Tcl_NewIntObj(val1); + ary[1] = Tcl_NewIntObj(val2); + return Tcl_NewListObj(2, ary); } /* @@ -3182,14 +3562,22 @@ NewPairObj(interp, val1, val2) */ static Tcl_Obj * -NewQuadObj(interp, val1, val2, val3, val4) - Tcl_Interp *interp; /* Current interpreter. */ - int val1, val2, val3, val4; +NewQuadObj( + int val1, int val2, int val3, int val4) { - Tcl_Obj *res = Tcl_NewListObj(0, NULL); - Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(val1)); - Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(val2)); - Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(val3)); - Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(val4)); - return res; + Tcl_Obj *ary[4]; + + ary[0] = Tcl_NewIntObj(val1); + ary[1] = Tcl_NewIntObj(val2); + ary[2] = Tcl_NewIntObj(val3); + ary[3] = Tcl_NewIntObj(val4); + return Tcl_NewListObj(4, ary); } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ |