diff options
Diffstat (limited to 'tk/generic/tkGrid.c')
-rw-r--r-- | tk/generic/tkGrid.c | 1786 |
1 files changed, 1111 insertions, 675 deletions
diff --git a/tk/generic/tkGrid.c b/tk/generic/tkGrid.c index def4a434d49..9a94970dcba 100644 --- a/tk/generic/tkGrid.c +++ b/tk/generic/tkGrid.c @@ -42,6 +42,12 @@ #define TYPICAL_SIZE 25 /* (arbitrary guess) */ #define PREALLOC 10 /* extra slots to allocate */ +/* + * Pre-allocate room for uniform groups during layout. + */ + +#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 @@ -75,6 +81,9 @@ typedef struct SlotInfo { 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 @@ -103,6 +112,9 @@ typedef struct GridLayout { * 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 + * 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 @@ -161,10 +173,13 @@ typedef struct Gridder { 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 (half of this space is left 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 iPadX, iPadY; /* Total extra pixels to allocate inside the * window (half this amount will appear on * each side). */ @@ -205,6 +220,16 @@ typedef struct Gridder { #define STICK_SOUTH 4 #define STICK_WEST 8 + +/* + * Structure to gather information about uniform groups during layout. + */ + +typedef struct UniformGroup { + Tk_Uid group; + int minSize; +} UniformGroup; + /* * Flag values for Grid structures: * @@ -233,9 +258,25 @@ 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 argc, char *argv[])); + 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, @@ -243,6 +284,8 @@ static void GridLostSlaveProc _ANSI_ARGS_((ClientData clientData, 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)); @@ -250,6 +293,14 @@ static void StickyToString _ANSI_ARGS_((int flags, char *result)); static int StringToSticky _ANSI_ARGS_((char *string)); static void Unlink _ANSI_ARGS_((Gridder *gridPtr)); +/* + * Prototypes for procedures contained in other files but not exported + * using tkIntDecls.h + */ + +void TkPrintPadAmount _ANSI_ARGS_((Tcl_Interp*, char*, int, int)); +int TkParsePadAmount _ANSI_ARGS_((Tcl_Interp*, Tk_Window, Tcl_Obj*, int*, int*)); + static Tk_GeomMgr gridMgrType = { "grid", /* name */ GridReqProc, /* requestProc */ @@ -274,632 +325,851 @@ static Tk_GeomMgr gridMgrType = { */ int -Tk_GridCmd(clientData, interp, argc, argv) +Tk_GridObjCmd(clientData, interp, objc, objv) ClientData clientData; /* Main window associated with * interpreter. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { Tk_Window tkwin = (Tk_Window) clientData; - Gridder *masterPtr; /* master grid record */ - GridMaster *gridPtr; /* pointer to grid data */ - size_t length; /* streing length of argument */ - char c; /* 1st character of argument */ + static CONST char *optionStrings[] = { + "bbox", "columnconfigure", "configure", "forget", + "info", "location", "propagate", "remove", + "rowconfigure", "size", "slaves", (char *) 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 }; + int index; + - if ((argc >= 2) && ((argv[1][0] == '.') || (argv[1][0] == REL_SKIP) || - (argv[1][0] == REL_VERT))) { - return ConfigureSlaves(interp, tkwin, argc-1, argv+1); + 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); + } } - if (argc < 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " option arg ?arg ...?\"", (char *) NULL); + if (objc < 3) { + Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } - c = argv[1][0]; - length = strlen(argv[1]); - - if ((c == 'b') && (strncmp(argv[1], "bbox", length) == 0)) { - Tk_Window master; - int row, column; /* origin for bounding box */ - int row2, column2; /* end of bounding box */ - 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 */ - char buf[TCL_INTEGER_SPACE * 4]; - - if (argc!=3 && argc != 5 && argc != 7) { - Tcl_AppendResult(interp, "wrong number of arguments: ", - "must be \"",argv[0], - " bbox master ?column row ?column row??\"", - (char *) NULL); - return TCL_ERROR; - } - - master = Tk_NameToWindow(interp, argv[2], tkwin); - if (master == NULL) { - return TCL_ERROR; - } - masterPtr = GetGrid(master); - - if (argc >= 5) { - if (Tcl_GetInt(interp, argv[3], &column) != TCL_OK) { - return TCL_ERROR; - } - if (Tcl_GetInt(interp, argv[4], &row) != TCL_OK) { - return TCL_ERROR; - } - column2 = column; - row2 = row; - } - - if (argc == 7) { - if (Tcl_GetInt(interp, argv[5], &column2) != TCL_OK) { - return TCL_ERROR; - } - if (Tcl_GetInt(interp, argv[6], &row2) != TCL_OK) { - return TCL_ERROR; - } - } - - gridPtr = masterPtr->masterDataPtr; - if (gridPtr == NULL) { - Tcl_SetResult(interp, "0 0 0 0", TCL_STATIC); - return(TCL_OK); - } - SetGridSize(masterPtr); - endX = MAX(gridPtr->columnEnd, gridPtr->columnMax); - endY = MAX(gridPtr->rowEnd, gridPtr->rowMax); - - if ((endX == 0) || (endY == 0)) { - Tcl_SetResult(interp, "0 0 0 0", TCL_STATIC); - return(TCL_OK); - } - if (argc == 3) { - row = column = 0; - row2 = endY; - column2 = endX; - } + if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } - if (column > column2) { - int temp = column; - column = column2, column2 = temp; - } - if (row > row2) { - int temp = row; - row = row2, row2 = temp; - } + switch ((enum options) index) { + case GRID_BBOX: + return GridBboxCommand(tkwin, interp, objc, objv); + case GRID_CONFIGURE: + return ConfigureSlaves(interp, tkwin, objc-2, objv+2); + case GRID_FORGET: + case GRID_REMOVE: + return GridForgetRemoveCommand(tkwin, interp, objc, objv); + case GRID_INFO: + return GridInfoCommand(tkwin, interp, objc, objv); + case GRID_LOCATION: + return GridLocationCommand(tkwin, interp, objc, objv); + case GRID_PROPAGATE: + return GridPropagateCommand(tkwin, interp, objc, objv); + case GRID_SIZE: + return GridSizeCommand(tkwin, interp, objc, objv); + case GRID_SLAVES: + return GridSlavesCommand(tkwin, interp, objc, objv); - if (column > 0 && column < endX) { - x = gridPtr->columnPtr[column-1].offset; - } else if (column > 0) { - x = gridPtr->columnPtr[endX-1].offset; - } + /* + * Sample argument combinations: + * grid columnconfigure <master> <index> -option + * grid columnconfigure <master> <index> -option value -option value + * grid rowconfigure <master> <index> + * grid rowconfigure <master> <index> -option + * grid rowconfigure <master> <index> -option value -option value. + */ - if (row > 0 && row < endY) { - y = gridPtr->rowPtr[row-1].offset; - } else if (row > 0) { - y = gridPtr->rowPtr[endY-1].offset; - } + case GRID_COLUMNCONFIGURE: + case GRID_ROWCONFIGURE: + return GridRowColumnConfigureCommand(tkwin, interp, objc, objv); + } - if (column2 < 0) { - width = 0; - } else if (column2 >= endX) { - width = gridPtr->columnPtr[endX-1].offset - x; - } else { - width = gridPtr->columnPtr[column2].offset - x; - } + /* This should not happen */ + Tcl_SetResult(interp, "Internal error in grid.", TCL_STATIC); + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * GridBboxCommand -- + * + * Implementation of the [grid bbox] subcommand. + * + * Results: + * Standard Tcl result. + * + * Side effects: + * Places bounding box information in the interp's result field. + * + *---------------------------------------------------------------------- + */ - if (row2 < 0) { - height = 0; - } else if (row2 >= endY) { - height = gridPtr->rowPtr[endY-1].offset - y; - } else { - height = gridPtr->rowPtr[row2].offset - y; - } - - sprintf(buf, "%d %d %d %d", x + gridPtr->startX, y + gridPtr->startY, - width, height); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - } else if ((c == 'c') && (strncmp(argv[1], "configure", length) == 0)) { - if (argv[2][0] != '.') { - Tcl_AppendResult(interp, "bad argument \"", argv[2], - "\": must be name of window", (char *) NULL); - return TCL_ERROR; - } - return ConfigureSlaves(interp, tkwin, argc-2, argv+2); - } else if (((c == 'f') && (strncmp(argv[1], "forget", length) == 0)) || - ((c == 'r') && (strncmp(argv[1], "remove", length) == 0))) { - Tk_Window slave; - Gridder *slavePtr; - int i; +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. */ +{ + Tk_Window master; + Gridder *masterPtr; /* master grid record */ + GridMaster *gridPtr; /* pointer to grid data */ + int row, column; /* origin for bounding box */ + int row2, column2; /* end of bounding box */ + 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 */ - for (i = 2; i < argc; i++) { - slave = Tk_NameToWindow(interp, argv[i], tkwin); - if (slave == NULL) { - return TCL_ERROR; - } - 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->numCols = 1; - slavePtr->numRows = 1; - slavePtr->padX = slavePtr->padY = 0; - slavePtr->iPadX = slavePtr->iPadY = 0; - slavePtr->doubleBw = 2*Tk_Changes(tkwin)->border_width; - if (slavePtr->flags & REQUESTED_RELAYOUT) { - Tcl_CancelIdleCall(ArrangeGrid, (ClientData) slavePtr); - } - slavePtr->flags = 0; - slavePtr->sticky = 0; - } - Tk_ManageGeometry(slave, (Tk_GeomMgr *) NULL, - (ClientData) NULL); - if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { - Tk_UnmaintainGeometry(slavePtr->tkwin, - slavePtr->masterPtr->tkwin); - } - Unlink(slavePtr); - Tk_UnmapWindow(slavePtr->tkwin); - } - } - } else if ((c == 'i') && (strncmp(argv[1], "info", length) == 0)) { - register Gridder *slavePtr; - Tk_Window slave; - char buffer[64 + TCL_INTEGER_SPACE * 4]; + 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 (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " info window\"", (char *) NULL); + if (objc >= 5) { + if (Tcl_GetIntFromObj(interp, objv[3], &column) != TCL_OK) { return TCL_ERROR; } - slave = Tk_NameToWindow(interp, argv[2], tkwin); - if (slave == NULL) { + if (Tcl_GetIntFromObj(interp, objv[4], &row) != TCL_OK) { return TCL_ERROR; } - slavePtr = GetGrid(slave); - if (slavePtr->masterPtr == NULL) { - Tcl_ResetResult(interp); - return TCL_OK; - } + column2 = column; + row2 = row; + } - 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); - sprintf(buffer, " -ipadx %d -ipady %d -padx %d -pady %d", - slavePtr->iPadX/2, slavePtr->iPadY/2, slavePtr->padX/2, - slavePtr->padY/2); - Tcl_AppendResult(interp, buffer, (char *) NULL); - StickyToString(slavePtr->sticky,buffer); - Tcl_AppendResult(interp, " -sticky ", buffer, (char *) NULL); - } else if((c == 'l') && (strncmp(argv[1], "location", length) == 0)) { - Tk_Window master; - 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 */ - char buf[TCL_INTEGER_SPACE * 2]; - - if (argc != 5) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " location master x y\"", (char *)NULL); + if (objc == 7) { + if (Tcl_GetIntFromObj(interp, objv[5], &column2) != TCL_OK) { return TCL_ERROR; } - - master = Tk_NameToWindow(interp, argv[2], tkwin); - if (master == NULL) { + if (Tcl_GetIntFromObj(interp, objv[6], &row2) != TCL_OK) { return TCL_ERROR; } + } + + gridPtr = masterPtr->masterDataPtr; + if (gridPtr == NULL) { + Tcl_SetObjResult(interp, NewQuadObj(interp, 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)); + return TCL_OK; + } + if (objc == 3) { + row = column = 0; + row2 = endY; + column2 = endX; + } + + if (column > column2) { + int temp = column; + column = column2, column2 = temp; + } + if (row > row2) { + int temp = row; + row = row2, row2 = temp; + } + + if (column > 0 && column < endX) { + x = gridPtr->columnPtr[column-1].offset; + } 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, + x + gridPtr->startX, y + gridPtr->startY, width, height)); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * GridForgetRemoveCommand -- + * + * Implementation of the [grid forget]/[grid remove] subcommands. + * See the user documentation for details on what these do. + * + * Results: + * Standard Tcl result. + * + * Side effects: + * Removes a window from a grid layout. + * + *---------------------------------------------------------------------- + */ - if (Tk_GetPixels(interp, master, argv[3], &x) != TCL_OK) { - return TCL_ERROR; - } - if (Tk_GetPixels(interp, master, argv[4], &y) != TCL_OK) { +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. */ +{ + 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; } - masterPtr = GetGrid(master); - if (masterPtr->masterDataPtr == NULL) { - Tcl_SetResult(interp, "-1 -1", TCL_STATIC); - return TCL_OK; + 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->numCols = 1; + slavePtr->numRows = 1; + slavePtr->padX = slavePtr->padY = 0; + slavePtr->padLeft = slavePtr->padTop = 0; + slavePtr->iPadX = slavePtr->iPadY = 0; + slavePtr->doubleBw = 2*Tk_Changes(tkwin)->border_width; + if (slavePtr->flags & REQUESTED_RELAYOUT) { + Tcl_CancelIdleCall(ArrangeGrid, (ClientData) slavePtr); + } + slavePtr->flags = 0; + slavePtr->sticky = 0; + } + Tk_ManageGeometry(slave, (Tk_GeomMgr *) NULL, + (ClientData) NULL); + if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { + Tk_UnmaintainGeometry(slavePtr->tkwin, + slavePtr->masterPtr->tkwin); + } + Unlink(slavePtr); + Tk_UnmapWindow(slavePtr->tkwin); } - gridPtr = masterPtr->masterDataPtr; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * GridInfoCommand -- + * + * Implementation of the [grid info] subcommand. See the user + * documentation for details on what it does. + * + * Results: + * Standard Tcl result. + * + * Side effects: + * Puts gridding information in the interpreter's result. + * + *---------------------------------------------------------------------- + */ - /* - * 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. - */ +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. */ +{ + 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; + } + if (TkGetWindowFromObj(interp, tkwin, objv[2], &slave) != TCL_OK) { + return TCL_ERROR; + } + slavePtr = GetGrid(slave); + if (slavePtr->masterPtr == NULL) { + 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); + 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); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * GridLocationCommand -- + * + * Implementation of the [grid location] subcommand. See the user + * documentation for details on what it does. + * + * Results: + * Standard Tcl result. + * + * Side effects: + * Puts location information in the interpreter's result field. + * + *---------------------------------------------------------------------- + */ - while (masterPtr->flags & REQUESTED_RELAYOUT) { - Tcl_CancelIdleCall(ArrangeGrid, (ClientData) masterPtr); - ArrangeGrid ((ClientData) masterPtr); +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. */ +{ + Tk_Window master; + 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 */ + + 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)); + 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. + */ + + while (masterPtr->flags & REQUESTED_RELAYOUT) { + Tcl_CancelIdleCall(ArrangeGrid, (ClientData) masterPtr); + ArrangeGrid ((ClientData) masterPtr); + } + SetGridSize(masterPtr); + endX = MAX(gridPtr->columnEnd, gridPtr->columnMax); + endY = MAX(gridPtr->rowEnd, gridPtr->rowMax); + + slotPtr = masterPtr->masterDataPtr->columnPtr; + if (x < masterPtr->masterDataPtr->startX) { + i = -1; + } else { + x -= masterPtr->masterDataPtr->startX; + for (i = 0; slotPtr[i].offset < x && i < endX; i++) { + /* null body */ } - SetGridSize(masterPtr); - endX = MAX(gridPtr->columnEnd, gridPtr->columnMax); - endY = MAX(gridPtr->rowEnd, gridPtr->rowMax); - - slotPtr = masterPtr->masterDataPtr->columnPtr; - if (x < masterPtr->masterDataPtr->startX) { - i = -1; - } else { - x -= masterPtr->masterDataPtr->startX; - for (i=0;slotPtr[i].offset < x && i < endX; i++) { - /* null body */ - } + } + + slotPtr = masterPtr->masterDataPtr->rowPtr; + if (y < masterPtr->masterDataPtr->startY) { + j = -1; + } else { + y -= masterPtr->masterDataPtr->startY; + for (j = 0; slotPtr[j].offset < y && j < endY; j++) { + /* null body */ } + } + + Tcl_SetObjResult(interp, NewPairObj(interp, i, j)); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * GridPropagateCommand -- + * + * Implementation of the [grid propagate] subcommand. See the user + * documentation for details on what it does. + * + * Results: + * Standard Tcl result. + * + * Side effects: + * May alter geometry propagation for a widget. + * + *---------------------------------------------------------------------- + */ - slotPtr = masterPtr->masterDataPtr->rowPtr; - if (y < masterPtr->masterDataPtr->startY) { - j = -1; +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. */ +{ + Tk_Window master; + Gridder *masterPtr; + int propagate, old; + + if (objc > 4) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?"); + return TCL_ERROR; + } + + if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) { + return TCL_ERROR; + } + masterPtr = GetGrid(master); + if (objc == 3) { + Tcl_SetObjResult(interp, + Tcl_NewBooleanObj(!(masterPtr->flags & DONT_PROPAGATE))); + return TCL_OK; + } + if (Tcl_GetBooleanFromObj(interp, objv[3], &propagate) != TCL_OK) { + return TCL_ERROR; + } + + /* Only request a relayout if the propagation bit changes */ + + old = !(masterPtr->flags & DONT_PROPAGATE); + if (propagate != old) { + if (propagate) { + masterPtr->flags &= ~DONT_PROPAGATE; } else { - y -= masterPtr->masterDataPtr->startY; - for (j=0;slotPtr[j].offset < y && j < endY; j++) { - /* null body */ - } + 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; + } + if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { + masterPtr->flags |= REQUESTED_RELAYOUT; + Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * GridRowColumnConfigureCommand -- + * + * Implementation of the [grid rowconfigure] and [grid columnconfigure] + * subcommands. See the user documentation for details on what these + * do. + * + * Results: + * Standard Tcl result. + * + * Side effects: + * Depends on arguments; see user documentation. + * + *---------------------------------------------------------------------- + */ - sprintf(buf, "%d %d", i, j); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - } else if ((c == 'p') && (strncmp(argv[1], "propagate", length) == 0)) { - Tk_Window master; - int propagate; +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. */ +{ + Tk_Window master; + Gridder *masterPtr; + 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; + char *string; + static CONST char *optionStrings[] = { + "-minsize", "-pad", "-uniform", "-weight", (char *) NULL }; + enum options { ROWCOL_MINSIZE, ROWCOL_PAD, ROWCOL_UNIFORM, ROWCOL_WEIGHT }; + int index; - if (argc > 4) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " propagate window ?boolean?\"", - (char *) NULL); + if (((objc % 2 != 0) && (objc > 6)) || (objc < 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "master index ?-option value...?"); + return TCL_ERROR; + } + + if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) { + return TCL_ERROR; + } + + if (Tcl_ListObjGetElements(interp, objv[3], &lObjc, &lObjv) != TCL_OK) { + return TCL_ERROR; + } + + string = Tcl_GetString(objv[1]); + checkOnly = ((objc == 4) || (objc == 5)); + masterPtr = GetGrid(master); + slotType = (*string == 'c') ? COLUMN : ROW; + if (checkOnly && lObjc > 1) { + Tcl_AppendResult(interp, Tcl_GetString(objv[3]), + " must be a single element.", (char *) NULL); + return TCL_ERROR; + } + for (j = 0; j < lObjc; j++) { + if (Tcl_GetIntFromObj(interp, lObjv[j], &slot) != TCL_OK) { return TCL_ERROR; } - master = Tk_NameToWindow(interp, argv[2], tkwin); - if (master == NULL) { + 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); return TCL_ERROR; + } else if (ok == TCL_OK) { + slotPtr = (slotType == COLUMN) ? + masterPtr->masterDataPtr->columnPtr : + masterPtr->masterDataPtr->rowPtr; } - masterPtr = GetGrid(master); - if (argc == 3) { - Tcl_SetResult(interp, - ((masterPtr->flags & DONT_PROPAGATE) ? "0" : "1"), - TCL_STATIC); + + /* + * Return all of the options for this row or column. If the + * request is out of range, return all 0's. + */ + + if (objc == 4) { + int minsize = 0, pad = 0, weight = 0; + Tk_Uid uniform = NULL; + Tcl_Obj *res = Tcl_NewListObj(0, NULL); + + if (ok == TCL_OK) { + minsize = slotPtr[slot].minSize; + pad = slotPtr[slot].pad; + weight = slotPtr[slot].weight; + uniform = slotPtr[slot].uniform; + } + + Tcl_ListObjAppendElement(interp, res, + Tcl_NewStringObj("-minsize", -1)); + Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(minsize)); + Tcl_ListObjAppendElement(interp, res, + Tcl_NewStringObj("-pad", -1)); + Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(pad)); + Tcl_ListObjAppendElement(interp, res, + Tcl_NewStringObj("-uniform", -1)); + Tcl_ListObjAppendElement(interp, res, + Tcl_NewStringObj(uniform == NULL ? "" : uniform, -1)); + Tcl_ListObjAppendElement(interp, res, + Tcl_NewStringObj("-weight", -1)); + Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(weight)); + Tcl_SetObjResult(interp, res); return TCL_OK; } - if (Tcl_GetBoolean(interp, argv[3], &propagate) != TCL_OK) { - return TCL_ERROR; - } - /* Only request a relayout if the propagation bit changes */ + /* + * 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 ((!propagate) ^ (masterPtr->flags&DONT_PROPAGATE)) { - if (propagate) { - masterPtr->flags &= ~DONT_PROPAGATE; - } else { - masterPtr->flags |= DONT_PROPAGATE; + for (i = 4; i < objc; i += 2) { + if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", 0, + &index) != TCL_OK) { + return TCL_ERROR; } - - /* - * Re-arrange the master to allow new geometry information to - * propagate upwards to the master's master. - */ - - if (masterPtr->abortPtr != NULL) { - *masterPtr->abortPtr = 1; + 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) { + return TCL_ERROR; + } else { + slotPtr[slot].minSize = size; + } } - if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { - masterPtr->flags |= REQUESTED_RELAYOUT; - Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); + 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) { + return TCL_ERROR; + } else if (wt < 0) { + Tcl_AppendResult(interp, "invalid arg \"", + Tcl_GetString(objv[i]), + "\": should be non-negative", (char *) NULL); + return TCL_ERROR; + } else { + slotPtr[slot].weight = wt; + } } - } - } else if ((c == 's') && (strncmp(argv[1], "size", length) == 0) - && (length > 1)) { - Tk_Window master; - - if (argc != 3) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " size window\"", (char *) NULL); - return TCL_ERROR; - } - master = Tk_NameToWindow(interp, argv[2], tkwin); - if (master == NULL) { - return TCL_ERROR; - } - masterPtr = GetGrid(master); - - if (masterPtr->masterDataPtr != NULL) { - char buf[TCL_INTEGER_SPACE * 2]; - - SetGridSize(masterPtr); - gridPtr = masterPtr->masterDataPtr; - sprintf(buf, "%d %d", - MAX(gridPtr->columnEnd, gridPtr->columnMax), - MAX(gridPtr->rowEnd, gridPtr->rowMax)); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - } else { - Tcl_SetResult(interp, "0 0", TCL_STATIC); - } - } else if ((c == 's') && (strncmp(argv[1], "slaves", length) == 0) - && (length > 1)) { - Tk_Window master; - Gridder *slavePtr; - int i, value; - int row = -1, column = -1; - - if ((argc < 3) || ((argc%2) == 0)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " slaves window ?-option value...?\"", - (char *) NULL); - return TCL_ERROR; - } - - for (i=3; i<argc; i+=2) { - length = strlen(argv[i]); - if ((*argv[i] != '-') || (length < 2)) { - Tcl_AppendResult(interp, "invalid args: should be \"", - argv[0], " slaves window ?-option value...?\"", - (char *) NULL); - return TCL_ERROR; + else if (index == ROWCOL_UNIFORM) { + if (objc == 5) { + Tk_Uid value; + value = (ok == TCL_OK) ? slotPtr[slot].uniform : ""; + if (value == NULL) { + value = ""; + } + 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 (Tcl_GetInt(interp, argv[i+1], &value) != TCL_OK) { - return TCL_ERROR; + 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) { + return TCL_ERROR; + } else if (size < 0) { + Tcl_AppendResult(interp, "invalid arg \"", + Tcl_GetString(objv[i]), + "\": should be non-negative", (char *) NULL); + return TCL_ERROR; + } else { + slotPtr[slot].pad = size; + } } - if (value < 0) { - Tcl_AppendResult(interp, argv[i], - " is an invalid value: should NOT be < 0", - (char *) NULL); - return TCL_ERROR; + } + } + + /* + * If we changed a property, re-arrange the table, + * and check for constraint shrinkage. + */ + + if (objc != 5) { + 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].uniform == NULL)) { + last--; } - if (strncmp(argv[i], "-column", length) == 0) { - column = value; - } else if (strncmp(argv[i], "-row", length) == 0) { - row = value; - } else { - Tcl_AppendResult(interp, argv[i], - " is an invalid option: should be \"", - "-row, -column\"", - (char *) NULL); - return TCL_ERROR; + 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].uniform == NULL)) { + last--; } + masterPtr->masterDataPtr->columnMax = last + 1; } - master = Tk_NameToWindow(interp, argv[2], tkwin); - if (master == NULL) { - return TCL_ERROR; + + if (masterPtr->abortPtr != NULL) { + *masterPtr->abortPtr = 1; } - masterPtr = GetGrid(master); - - for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; - slavePtr = slavePtr->nextPtr) { - if (column>=0 && (slavePtr->column > column - || slavePtr->column+slavePtr->numCols-1 < column)) { - continue; - } - if (row>=0 && (slavePtr->row > row || - slavePtr->row+slavePtr->numRows-1 < row)) { - continue; - } - Tcl_AppendElement(interp, Tk_PathName(slavePtr->tkwin)); + if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { + masterPtr->flags |= REQUESTED_RELAYOUT; + Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * GridSizeCommand -- + * + * Implementation of the [grid size] subcommand. See the user + * documentation for details on what it does. + * + * Results: + * Standard Tcl result. + * + * Side effects: + * Puts grid size information in the interpreter's result. + * + *---------------------------------------------------------------------- + */ - /* - * Sample argument combinations: - * grid columnconfigure <master> <index> -option - * grid columnconfigure <master> <index> -option value -option value - * grid rowconfigure <master> <index> - * grid rowconfigure <master> <index> -option - * grid rowconfigure <master> <index> -option value -option value. - */ - - } else if(((c == 'c') && (strncmp(argv[1], "columnconfigure", length) == 0) - && (length >= 3)) || - ((c == 'r') && (strncmp(argv[1], "rowconfigure", length) == 0) - && (length >=2))) { - Tk_Window master; - SlotInfo *slotPtr = NULL; - int slot; /* the column or row number */ - size_t length; /* the # of chars in the "-option" string */ - int slotType; /* COLUMN or ROW */ - int size; /* the configuration value */ - int checkOnly; /* check the size only */ - int argcPtr; /* Number of items in index list */ - char **argvPtr; /* array of indeces */ - char **indexP; /* String value of current index list item. */ - int ok; /* temporary TCL result code */ - int i; - - if (((argc%2 != 0) && (argc>6)) || (argc < 4)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " ", argv[1], " master index ?-option value...?\"", - (char *)NULL); - return TCL_ERROR; - } +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. */ +{ + Tk_Window master; + Gridder *masterPtr; + GridMaster *gridPtr; /* pointer to grid data */ + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + + if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) { + return TCL_ERROR; + } + masterPtr = GetGrid(master); + + if (masterPtr->masterDataPtr != NULL) { + SetGridSize(masterPtr); + gridPtr = masterPtr->masterDataPtr; + Tcl_SetObjResult(interp, NewPairObj(interp, + MAX(gridPtr->columnEnd, gridPtr->columnMax), + MAX(gridPtr->rowEnd, gridPtr->rowMax))); + } else { + Tcl_SetObjResult(interp, NewPairObj(interp, 0, 0)); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * GridSlavesCommand -- + * + * 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. + * + *---------------------------------------------------------------------- + */ - master = Tk_NameToWindow(interp, argv[2], tkwin); - if (master == NULL) { +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. */ +{ + Tk_Window master; + Gridder *masterPtr; /* master grid record */ + Gridder *slavePtr; + int i, value; + int row = -1, column = -1; + static CONST char *optionStrings[] = { + "-column", "-row", (char *) 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) { return TCL_ERROR; } - - if (Tcl_SplitList(interp, argv[3], &argcPtr, &argvPtr) != TCL_OK) { + if (Tcl_GetIntFromObj(interp, objv[i+1], &value) != TCL_OK) { return TCL_ERROR; } - - checkOnly = ((argc == 4) || (argc == 5)); - masterPtr = GetGrid(master); - slotType = (c == 'c') ? COLUMN : ROW; - if (checkOnly && argcPtr > 1) { - Tcl_AppendResult(interp, argv[3], - " must be a single element.", (char *) NULL); - Tcl_Free((char *)argvPtr); + if (value < 0) { + Tcl_AppendResult(interp, Tcl_GetString(objv[i]), + " is an invalid value: should NOT be < 0", + (char *) NULL); return TCL_ERROR; } - for (indexP=argvPtr; *indexP != NULL; indexP++) { - if (Tcl_GetInt(interp, *indexP, &slot) != TCL_OK) { - Tcl_Free((char *)argvPtr); - return TCL_ERROR; - } - ok = CheckSlotData(masterPtr, slot, slotType, checkOnly); - if ((ok!=TCL_OK) && ((argc<4) || (argc>5))) { - Tcl_AppendResult(interp, argv[0], - " ", argv[1], ": \"", *argvPtr,"\" is out of range", - (char *) NULL); - Tcl_Free((char *)argvPtr); - return TCL_ERROR; - } else 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. - */ - - if (argc == 4) { - Tcl_Free((char *)argvPtr); - } - if ((argc == 4) && (ok == TCL_OK)) { - char buf[64 + TCL_INTEGER_SPACE * 3]; - - sprintf(buf, "-minsize %d -pad %d -weight %d", - slotPtr[slot].minSize,slotPtr[slot].pad, - slotPtr[slot].weight); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - return (TCL_OK); - } else if (argc == 4) { - Tcl_SetResult(interp, "-minsize 0 -pad 0 -weight 0", - TCL_STATIC); - return (TCL_OK); - } - - /* - * 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. - */ - - for (i=4; i<argc; i+=2) { - length = strlen(argv[i]); - if ((*argv[i] != '-') || length < 2) { - Tcl_AppendResult(interp, "invalid arg \"", - argv[i], "\" :expecting -minsize, -pad, or -weight.", - (char *) NULL); - Tcl_Free((char *)argvPtr); - return TCL_ERROR; - } - if (strncmp(argv[i], "-minsize", length) == 0) { - if (argc == 5) { - char buf[TCL_INTEGER_SPACE]; - int value; - - value = (ok == TCL_OK) ? slotPtr[slot].minSize : 0; - sprintf(buf, "%d", value); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - } else if (Tk_GetPixels(interp, master, argv[i+1], &size) - != TCL_OK) { - Tcl_Free((char *)argvPtr); - return TCL_ERROR; - } else { - slotPtr[slot].minSize = size; - } - } - else if (strncmp(argv[i], "-weight", length) == 0) { - int wt; - if (argc == 5) { - char buf[TCL_INTEGER_SPACE]; - int value; - - value = (ok == TCL_OK) ? slotPtr[slot].weight : 0; - sprintf(buf, "%d", value); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - } else if (Tcl_GetInt(interp, argv[i+1], &wt) != TCL_OK) { - Tcl_Free((char *)argvPtr); - return TCL_ERROR; - } else if (wt < 0) { - Tcl_AppendResult(interp, "invalid arg \"", argv[i], - "\": should be non-negative", (char *) NULL); - Tcl_Free((char *)argvPtr); - return TCL_ERROR; - } else { - slotPtr[slot].weight = wt; - } - } - else if (strncmp(argv[i], "-pad", length) == 0) { - if (argc == 5) { - char buf[TCL_INTEGER_SPACE]; - int value; - - value = (ok == TCL_OK) ? slotPtr[slot].pad : 0; - sprintf(buf, "%d", value); - Tcl_SetResult(interp, buf, TCL_VOLATILE); - } else if (Tk_GetPixels(interp, master, argv[i+1], &size) - != TCL_OK) { - Tcl_Free((char *)argvPtr); - return TCL_ERROR; - } else if (size < 0) { - Tcl_AppendResult(interp, "invalid arg \"", argv[i], - "\": should be non-negative", (char *) NULL); - Tcl_Free((char *)argvPtr); - return TCL_ERROR; - } else { - slotPtr[slot].pad = size; - } - } else { - Tcl_AppendResult(interp, "invalid arg \"", - argv[i], "\": expecting -minsize, -pad, or -weight.", - (char *) NULL); - Tcl_Free((char *)argvPtr); - return TCL_ERROR; - } - } + if (index == SLAVES_COLUMN) { + column = value; + } else { + row = value; } - Tcl_Free((char *)argvPtr); - - /* - * If we changed a property, re-arrange the table, - * and check for constraint shrinkage. - */ + } - if (argc != 5) { - if (slotType == ROW) { - int last = masterPtr->masterDataPtr->rowMax - 1; - while ((last >= 0) && (slotPtr[last].weight == 0) - && (slotPtr[last].pad == 0) - && (slotPtr[last].minSize == 0)) { - 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)) { - last--; - } - masterPtr->masterDataPtr->columnMax = last + 1; - } + if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) { + return TCL_ERROR; + } + masterPtr = GetGrid(master); - if (masterPtr->abortPtr != NULL) { - *masterPtr->abortPtr = 1; - } - if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { - masterPtr->flags |= REQUESTED_RELAYOUT; - Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); - } + res = Tcl_NewListObj(0, NULL); + for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; + slavePtr = slavePtr->nextPtr) { + if (column>=0 && (slavePtr->column > column + || slavePtr->column+slavePtr->numCols-1 < column)) { + continue; } - } else { - Tcl_AppendResult(interp, "bad option \"", argv[1], - "\": must be bbox, columnconfigure, configure, forget, info, ", - "location, propagate, remove, rowconfigure, size, or slaves.", - (char *) NULL); - return TCL_ERROR; + if (row>=0 && (slavePtr->row > row || + slavePtr->row+slavePtr->numRows-1 < row)) { + continue; + } + Tcl_ListObjAppendElement(interp, res, + Tcl_NewStringObj(Tk_PathName(slavePtr->tkwin), -1)); } + Tcl_SetObjResult(interp, res); return TCL_OK; } @@ -932,7 +1202,7 @@ GridReqProc(clientData, tkwin) register Gridder *gridPtr = (Gridder *) clientData; gridPtr = gridPtr->masterPtr; - if (!(gridPtr->flags & REQUESTED_RELAYOUT)) { + if (gridPtr && !(gridPtr->flags & REQUESTED_RELAYOUT)) { gridPtr->flags |= REQUESTED_RELAYOUT; Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr); } @@ -1166,9 +1436,9 @@ AdjustForSticky(slavePtr, xPtr, yPtr, widthPtr, heightPtr) int diffy=0; /* Cavity hight - slave height. */ int sticky = slavePtr->sticky; - *xPtr += slavePtr->padX/2; + *xPtr += slavePtr->padLeft; *widthPtr -= slavePtr->padX; - *yPtr += slavePtr->padY/2; + *yPtr += slavePtr->padTop; *heightPtr -= slavePtr->padY; if (*widthPtr > (Tk_ReqWidth(slavePtr->tkwin) + slavePtr->iPadX)) { @@ -1264,13 +1534,22 @@ ArrangeGrid(clientData) SetGridSize(masterPtr); width = ResolveConstraints(masterPtr, COLUMN, 0); height = ResolveConstraints(masterPtr, ROW, 0); - width += 2*Tk_InternalBorderWidth(masterPtr->tkwin); - height += 2*Tk_InternalBorderWidth(masterPtr->tkwin); + 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); + } + if (height < Tk_MinReqHeight(masterPtr->tkwin)) { + height = Tk_MinReqHeight(masterPtr->tkwin); + } if (((width != Tk_ReqWidth(masterPtr->tkwin)) - || (height != Tk_ReqHeight(masterPtr->tkwin))) - && !(masterPtr->flags & DONT_PROPAGATE)) { - Tk_GeometryRequest(masterPtr->tkwin, width, height); + || (height != Tk_ReqHeight(masterPtr->tkwin))) + && !(masterPtr->flags & DONT_PROPAGATE)) { + Tk_GeometryRequest(masterPtr->tkwin, width, height); if (width>1 && height>1) { masterPtr->flags |= REQUESTED_RELAYOUT; Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); @@ -1289,15 +1568,17 @@ ArrangeGrid(clientData) */ realWidth = Tk_Width(masterPtr->tkwin) - - 2*Tk_InternalBorderWidth(masterPtr->tkwin); + Tk_InternalBorderLeft(masterPtr->tkwin) - + Tk_InternalBorderRight(masterPtr->tkwin); realHeight = Tk_Height(masterPtr->tkwin) - - 2*Tk_InternalBorderWidth(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_InternalBorderWidth(masterPtr->tkwin); - slotPtr->startY += Tk_InternalBorderWidth(masterPtr->tkwin); + slotPtr->startX += Tk_InternalBorderLeft(masterPtr->tkwin); + slotPtr->startY += Tk_InternalBorderTop(masterPtr->tkwin); /* * Now adjust the actual size of the slave to its cavity by @@ -1414,6 +1695,14 @@ ResolveConstraints(masterPtr, slotType, maxOffset) * 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]; + /* Pre-allocated space for uniform groups. */ + UniformGroup *uniformGroupPtr; + /* Uniform groups data. */ + int uniformGroups; /* Number of currently used uniform groups. */ + int uniformGroupsAlloced; /* Size of allocated space for uniform groups. + */ + int weight, minSize; /* * For typical sized tables, we'll use stack space for the layout data @@ -1463,13 +1752,15 @@ ResolveConstraints(masterPtr, slotType, maxOffset) for (slot=0; slot < constraintCount; slot++) { layoutPtr[slot].minSize = slotPtr[slot].minSize; - layoutPtr[slot].weight = slotPtr[slot].weight; + 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; } @@ -1525,6 +1816,83 @@ ResolveConstraints(masterPtr, slotType, maxOffset) } /* + * Step 2b. + * Consider demands on uniform sizes. + */ + + uniformGroupPtr = uniformPre; + uniformGroupsAlloced = UNIFORM_PREALLOC; + uniformGroups = 0; + + for (slot = 0; slot < gridCount; slot++) { + if (layoutPtr[slot].uniform != NULL) { + for (start = 0; start < uniformGroups; start++) { + if (uniformGroupPtr[start].group == layoutPtr[slot].uniform) { + break; + } + } + if (start >= uniformGroups) { + /* + * Have not seen that group before, set up data for it. + */ + + if (uniformGroups >= uniformGroupsAlloced) { + /* + * We need to allocate more space. + */ + + size_t oldSize = uniformGroupsAlloced + * 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); + } + uniformGroupPtr = new; + uniformGroupsAlloced += UNIFORM_PREALLOC; + } + uniformGroups++; + uniformGroupPtr[start].group = layoutPtr[slot].uniform; + uniformGroupPtr[start].minSize = 0; + } + weight = layoutPtr[slot].weight; + weight = weight > 0 ? weight : 1; + minSize = (layoutPtr[slot].minSize + weight - 1) / weight; + if (minSize > uniformGroupPtr[start].minSize) { + uniformGroupPtr[start].minSize = minSize; + } + } + } + + /* + * Data has been gathered about uniform groups. Now relayout accordingly. + */ + + if (uniformGroups > 0) { + for (slot = 0; slot < gridCount; slot++) { + if (layoutPtr[slot].uniform != NULL) { + for (start = 0; start < uniformGroups; start++) { + if (uniformGroupPtr[start].group == + layoutPtr[slot].uniform) { + weight = layoutPtr[slot].weight; + weight = weight > 0 ? weight : 1; + layoutPtr[slot].minSize = + uniformGroupPtr[start].minSize * weight; + break; + } + } + } + } + } + + if (uniformGroupPtr != uniformPre) { + ckfree((char *) uniformGroupPtr); + } + + /* * Step 3. * Determine the minimum slot offsets going from left to right * that would fit all of the slaves. This determines the minimum @@ -1707,7 +2075,7 @@ ResolveConstraints(masterPtr, slotType, maxOffset) --layoutPtr; if (layoutPtr != layoutData) { - Tcl_Free((char *)layoutPtr); + ckfree((char *)layoutPtr); } return requiredSize; } @@ -1770,6 +2138,7 @@ GetGrid(tkwin) gridPtr->numRows = 1; gridPtr->padX = gridPtr->padY = 0; + gridPtr->padLeft = gridPtr->padTop = 0; gridPtr->iPadX = gridPtr->iPadY = 0; gridPtr->doubleBw = 2*Tk_Changes(tkwin)->border_width; gridPtr->abortPtr = NULL; @@ -1886,7 +2255,7 @@ CheckSlotData(masterPtr, slot, slotType, checkOnly) masterPtr->masterDataPtr->columnPtr; memcpy((VOID *) new, (VOID *) old, oldSize ); memset((VOID *) (new+numSlot), 0, newSize - oldSize ); - Tcl_Free((char *) old); + ckfree((char *) old); if (slotType == ROW) { masterPtr->masterDataPtr->rowPtr = new ; masterPtr->masterDataPtr->rowSpace = newNumSlot ; @@ -2037,14 +2406,14 @@ DestroyGrid(memPtr) if (gridPtr->masterDataPtr != NULL) { if (gridPtr->masterDataPtr->rowPtr != NULL) { - Tcl_Free((char *) gridPtr->masterDataPtr -> rowPtr); + ckfree((char *) gridPtr->masterDataPtr -> rowPtr); } if (gridPtr->masterDataPtr->columnPtr != NULL) { - Tcl_Free((char *) gridPtr->masterDataPtr -> columnPtr); + ckfree((char *) gridPtr->masterDataPtr -> columnPtr); } - Tcl_Free((char *) gridPtr->masterDataPtr); + ckfree((char *) gridPtr->masterDataPtr); } - Tcl_Free((char *) gridPtr); + ckfree((char *) gridPtr); } /* @@ -2145,12 +2514,12 @@ GridStructureProc(clientData, eventPtr) */ static int -ConfigureSlaves(interp, tkwin, argc, argv) +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 argc; /* Number of elements in argv. */ - char *argv[]; /* Argument strings: contains one or more + 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 @@ -2159,38 +2528,57 @@ ConfigureSlaves(interp, tkwin, argc, argv) Gridder *masterPtr; Gridder *slavePtr; Tk_Window other, slave, parent, ancestor; - int i, j, c, tmp; - size_t length; + 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 */ + static CONST char *optionStrings[] = { + "-column", "-columnspan", "-in", "-ipadx", "-ipady", + "-padx", "-pady", "-row", "-rowspan", "-sticky", + (char *) 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; /* * Count the number of windows, or window short-cuts. */ - for(numWindows=i=0;i<argc;i++) { - char firstChar = *argv[i]; + firstChar = 0; + for (numWindows = i = 0; i < objc; i++) { + prevChar = firstChar; + string = Tcl_GetStringFromObj(objv[i], (int *) &length); + firstChar = string[0]; + if (firstChar == '.') { numWindows++; continue; } - length = strlen(argv[i]); + if (length > 1 && i == 0) { + Tcl_AppendResult(interp, "bad argument \"", string, + "\": must be name of window", (char *) NULL); + return TCL_ERROR; + } if (length > 1 && firstChar == '-') { break; } if (length > 1) { Tcl_AppendResult(interp, "unexpected parameter, \"", - argv[i], "\", in configure list. ", + string, "\", in configure list. ", "Should be window name or option", (char *) NULL); return TCL_ERROR; } if ((firstChar == REL_HORIZ) && ((numWindows == 0) || - (*argv[i-1] == REL_SKIP) || (*argv[i-1] == REL_VERT))) { + (prevChar == REL_SKIP) || (prevChar == REL_VERT))) { Tcl_AppendResult(interp, "Must specify window before shortcut '-'.", (char *) NULL); @@ -2203,12 +2591,12 @@ ConfigureSlaves(interp, tkwin, argc, argv) } Tcl_AppendResult(interp, "invalid window shortcut, \"", - argv[i], "\" should be '-', 'x', or '^'", (char *) NULL); + string, "\" should be '-', 'x', or '^'", (char *) NULL); return TCL_ERROR; } numWindows = i; - if ((argc-numWindows)&1) { + if ((objc - numWindows) & 1) { Tcl_AppendResult(interp, "extra option or", " option with no value", (char *) NULL); return TCL_ERROR; @@ -2227,7 +2615,8 @@ ConfigureSlaves(interp, tkwin, argc, argv) masterPtr = NULL; for (j = 0; j < numWindows; j++) { - char firstChar = *argv[j]; + string = Tcl_GetString(objv[j]); + firstChar = string[0]; /* * '^' and 'x' cause us to skip a column. '-' is processed @@ -2242,19 +2631,20 @@ ConfigureSlaves(interp, tkwin, argc, argv) continue; } - for (defaultColumnSpan=1; - j + defaultColumnSpan < numWindows && - (*argv[j+defaultColumnSpan] == REL_HORIZ); + for (defaultColumnSpan = 1; j + defaultColumnSpan < numWindows; defaultColumnSpan++) { - /* null body */ + char *string = Tcl_GetString(objv[j + defaultColumnSpan]); + if (*string != REL_HORIZ) { + break; + } } - slave = Tk_NameToWindow(interp, argv[j], tkwin); - if (slave == NULL) { + if (TkGetWindowFromObj(interp, tkwin, objv[j], &slave) != TCL_OK) { return TCL_ERROR; } - if (Tk_IsTopLevel(slave)) { - Tcl_AppendResult(interp, "can't manage \"", argv[j], + + if (Tk_TopWinHierarchy(slave)) { + Tcl_AppendResult(interp, "can't manage \"", Tcl_GetString(objv[j]), "\": it's a top-level window", (char *) NULL); return TCL_ERROR; } @@ -2275,38 +2665,34 @@ ConfigureSlaves(interp, tkwin, argc, argv) * about keeping track of the old state. */ - for (i = numWindows; i < argc; i+=2) { - length = strlen(argv[i]); - c = argv[i][1]; - - if (length < 2) { - Tcl_AppendResult(interp, "unknown or ambiguous option \"", - argv[i], "\": must be ", - "-column, -columnspan, -in, -ipadx, -ipady, ", - "-padx, -pady, -row, -rowspan, or -sticky", - (char *) NULL); + for (i = numWindows; i < objc; i += 2) { + if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", 0, + &index) != TCL_OK) { return TCL_ERROR; } - if ((c == 'c') && (strncmp(argv[i], "-column", length) == 0)) { - if (Tcl_GetInt(interp, argv[i+1], &tmp) != TCL_OK || tmp<0) { + 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 \"", argv[i+1], + Tcl_AppendResult(interp, "bad column value \"", + Tcl_GetString(objv[i+1]), "\": must be a non-negative integer", (char *)NULL); return TCL_ERROR; } slavePtr->column = tmp; - } else if ((c == 'c') - && (strncmp(argv[i], "-columnspan", length) == 0)) { - if (Tcl_GetInt(interp, argv[i+1], &tmp) != TCL_OK || tmp <= 0) { + } else if (index == CONF_COLUMNSPAN) { + if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK || + tmp <= 0) { Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "bad columnspan value \"", argv[i+1], + Tcl_AppendResult(interp, "bad columnspan value \"", + Tcl_GetString(objv[i+1]), "\": must be a positive integer", (char *)NULL); return TCL_ERROR; } slavePtr->numCols = tmp; - } else if ((c == 'i') && (strncmp(argv[i], "-in", length) == 0)) { - other = Tk_NameToWindow(interp, argv[i+1], tkwin); - if (other == NULL) { + } else if (index == CONF_IN) { + if (TkGetWindowFromObj(interp, tkwin, objv[i+1], &other) != + TCL_OK) { return TCL_ERROR; } if (other == slave) { @@ -2316,84 +2702,70 @@ ConfigureSlaves(interp, tkwin, argc, argv) } masterPtr = GetGrid(other); InitMasterData(masterPtr); - } else if ((c == 'i') - && (strncmp(argv[i], "-ipadx", length) == 0)) { - if ((Tk_GetPixels(interp, slave, argv[i+1], &tmp) != TCL_OK) + } else if (index == CONF_IPADX) { + if ((Tk_GetPixelsFromObj(interp, slave, objv[i+1], &tmp) + != TCL_OK) || (tmp < 0)) { Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "bad ipadx value \"", argv[i+1], + Tcl_AppendResult(interp, "bad ipadx value \"", + Tcl_GetString(objv[i+1]), "\": must be positive screen distance", (char *) NULL); return TCL_ERROR; } slavePtr->iPadX = tmp*2; - } else if ((c == 'i') - && (strncmp(argv[i], "-ipady", length) == 0)) { - if ((Tk_GetPixels(interp, slave, argv[i+1], &tmp) != TCL_OK) - || (tmp< 0)) { + } else if (index == CONF_IPADY) { + if ((Tk_GetPixelsFromObj(interp, slave, objv[i+1], &tmp) + != TCL_OK) + || (tmp < 0)) { Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "bad ipady value \"", argv[i+1], + Tcl_AppendResult(interp, "bad ipady value \"", + Tcl_GetString(objv[i+1]), "\": must be positive screen distance", (char *) NULL); return TCL_ERROR; } slavePtr->iPadY = tmp*2; - } else if ((c == 'p') - && (strncmp(argv[i], "-padx", length) == 0)) { - if ((Tk_GetPixels(interp, slave, argv[i+1], &tmp) != TCL_OK) - || (tmp< 0)) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "bad padx value \"", argv[i+1], - "\": must be positive screen distance", - (char *) NULL); + } else if (index == CONF_PADX) { + if (TkParsePadAmount(interp, tkwin, objv[i+1], + &slavePtr->padLeft, &slavePtr->padX) != TCL_OK) { return TCL_ERROR; } - slavePtr->padX = tmp*2; - } else if ((c == 'p') - && (strncmp(argv[i], "-pady", length) == 0)) { - if ((Tk_GetPixels(interp, slave, argv[i+1], &tmp) != TCL_OK) - || (tmp< 0)) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "bad pady value \"", argv[i+1], - "\": must be positive screen distance", - (char *) NULL); + } else if (index == CONF_PADY) { + if (TkParsePadAmount(interp, tkwin, objv[i+1], + &slavePtr->padTop, &slavePtr->padY) != TCL_OK) { return TCL_ERROR; } - slavePtr->padY = tmp*2; - } else if ((c == 'r') && (strncmp(argv[i], "-row", length) == 0)) { - if (Tcl_GetInt(interp, argv[i+1], &tmp) != TCL_OK || tmp<0) { + } else if (index == CONF_ROW) { + if (Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK + || tmp < 0) { Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "bad grid value \"", argv[i+1], + Tcl_AppendResult(interp, "bad grid value \"", + Tcl_GetString(objv[i+1]), "\": must be a non-negative integer", (char *)NULL); return TCL_ERROR; } slavePtr->row = tmp; - } else if ((c == 'r') - && (strncmp(argv[i], "-rowspan", length) == 0)) { - if ((Tcl_GetInt(interp, argv[i+1], &tmp) != TCL_OK) || tmp<=0) { + } else if (index == CONF_ROWSPAN) { + if ((Tcl_GetIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) + || tmp <= 0) { Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "bad rowspan value \"", argv[i+1], + Tcl_AppendResult(interp, "bad rowspan value \"", + Tcl_GetString(objv[i+1]), "\": must be a positive integer", (char *)NULL); return TCL_ERROR; } slavePtr->numRows = tmp; - } else if ((c == 's') - && strncmp(argv[i], "-sticky", length) == 0) { - int sticky = StringToSticky(argv[i+1]); + } else if (index == CONF_STICKY) { + int sticky = StringToSticky(Tcl_GetString(objv[i+1])); if (sticky == -1) { - Tcl_AppendResult(interp, "bad stickyness value \"", argv[i+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; - } else { - Tcl_AppendResult(interp, "unknown or ambiguous option \"", - argv[i], "\": must be ", - "-column, -columnspan, -in, -ipadx, -ipady, ", - "-padx, -pady, -row, -rowspan, or -sticky", - (char *) NULL); - return TCL_ERROR; } } @@ -2435,8 +2807,8 @@ ConfigureSlaves(interp, tkwin, argc, argv) if (ancestor == parent) { break; } - if (Tk_IsTopLevel(ancestor)) { - Tcl_AppendResult(interp, "can't put ", argv[j], + if (Tk_TopWinHierarchy(ancestor)) { + Tcl_AppendResult(interp, "can't put ", Tcl_GetString(objv[j]), " inside ", Tk_PathName(masterPtr->tkwin), (char *) NULL); Unlink(slavePtr); @@ -2449,7 +2821,7 @@ ConfigureSlaves(interp, tkwin, argc, argv) */ if (masterPtr->masterPtr == slavePtr) { - Tcl_AppendResult(interp, "can't put ", argv[j], + Tcl_AppendResult(interp, "can't put ", Tcl_GetString(objv[j]), " inside ", Tk_PathName(masterPtr->tkwin), ", would cause management loop.", (char *) NULL); @@ -2494,15 +2866,23 @@ ConfigureSlaves(interp, tkwin, argc, argv) /* 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 lastRow, lastColumn; /* implied end of table */ + + string = Tcl_GetString(objv[j]); + firstChar = string[0]; - if (*argv[j] == '.') { - lastWindow = argv[j]; + if (firstChar == '.') { + lastWindow = string; + numSkip = 0; } - if (*argv[j] != REL_VERT) { + if (firstChar == REL_SKIP) { + numSkip++; + } + if (firstChar != REL_VERT) { continue; } @@ -2513,9 +2893,9 @@ ConfigureSlaves(interp, tkwin, argc, argv) } /* Count the number of consecutive ^'s starting from this position */ - for (width=1; width+j < numWindows && *argv[j+width] == REL_VERT; - width++) { - /* Null Body */ + for (width = 1; width + j < numWindows; width++) { + char *string = Tcl_GetString(objv[j+width]); + if (*string != REL_VERT) break; } /* @@ -2537,6 +2917,8 @@ ConfigureSlaves(interp, tkwin, argc, argv) lastColumn = otherPtr->column + otherPtr->numCols; } + lastColumn += numSkip; + for (match=0, slavePtr = masterPtr->slavePtr; slavePtr != NULL; slavePtr = slavePtr->nextPtr) { @@ -2547,6 +2929,7 @@ ConfigureSlaves(interp, tkwin, argc, argv) match++; j += slavePtr->numCols - 1; lastWindow = Tk_PathName(slavePtr->tkwin); + numSkip = 0; break; } } @@ -2556,7 +2939,6 @@ ConfigureSlaves(interp, tkwin, argc, argv) (char *) NULL); return TCL_ERROR; } -/* j += width - 1; */ } if (masterPtr == NULL) { @@ -2646,6 +3028,60 @@ StringToSticky(string) } } return sticky; -} +} + +/* + *---------------------------------------------------------------------- + * + * NewPairObj -- + * + * Creates a new list object and fills it with two integer objects. + * + * Results: + * The newly created list object is returned. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +static Tcl_Obj * +NewPairObj(interp, val1, val2) + Tcl_Interp *interp; /* Current interpreter. */ + int val1, val2; +{ + Tcl_Obj *res = Tcl_NewListObj(0, NULL); + Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(val1)); + Tcl_ListObjAppendElement(interp, res, Tcl_NewIntObj(val2)); + return res; +} + +/* + *---------------------------------------------------------------------- + * + * NewQuadObj -- + * + * Creates a new list object and fills it with four integer objects. + * + * Results: + * The newly created list object is returned. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +static Tcl_Obj * +NewQuadObj(interp, val1, val2, val3, val4) + Tcl_Interp *interp; /* Current interpreter. */ + int val1, val2, val3, 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; +} |