From 29f17227ad41d506327d16125bd288af8e7d38cd Mon Sep 17 00:00:00 2001 From: pspjuth Date: Tue, 11 Apr 2006 21:52:19 +0000 Subject: * generic/tkWindow.c (Tk_NameToWindow): Allow NULL interp to Tk_NameToWindow. This fixes TkGetWindowFromObj which promises to handle NULL but didn't. * generic/tkGrid.c: Fixed handling of out of bounds row or column. * tests/grid.test: [Bug 1432666] --- ChangeLog | 9 ++++ generic/tkGrid.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++------- generic/tkWindow.c | 15 ++++-- tests/grid.test | 72 +++++++++++++++++++++++++++- 4 files changed, 208 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index beaea3e..46e0d77 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2006-04-11 Peter Spjuth + + * generic/tkWindow.c (Tk_NameToWindow): Allow NULL interp to + Tk_NameToWindow. This fixes TkGetWindowFromObj which promises to + handle NULL but didn't. + + * generic/tkGrid.c: Fixed handling of out of bounds row or column. + * tests/grid.test: [Bug 1432666] + 2006-04-11 Don Porter * unix/Makefile.in: Updated `make dist` target to be sure the diff --git a/generic/tkGrid.c b/generic/tkGrid.c index fc68c5b..fa3281b 100644 --- a/generic/tkGrid.c +++ b/generic/tkGrid.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkGrid.c,v 1.43 2006/04/05 20:54:58 hobbs Exp $ + * RCS: @(#) $Id: tkGrid.c,v 1.44 2006/04/11 21:52:20 pspjuth Exp $ */ #include "tkInt.h" @@ -295,6 +295,10 @@ 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); @@ -1039,30 +1043,31 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv) } return TCL_OK; } - + for (j = 0; j < lObjc; j++) { int allSlaves = 0; - if (Tcl_GetIntFromObj(interp, lObjv[j], &slot) == TCL_OK) { + if (Tcl_GetIntFromObj(NULL, lObjv[j], &slot) == TCL_OK) { first = slot; last = slot; slavePtr = NULL; } else if (strcmp(Tcl_GetString(lObjv[j]), "all") == 0) { /* - * Reset any lingering error from e.g GetInt. + * Make sure master is initialised. */ - Tcl_ResetResult(interp); + + InitMasterData(masterPtr); + slavePtr = masterPtr->slavePtr; if (slavePtr == NULL) { continue; } allSlaves = 1; - } else if (TkGetWindowFromObj(interp, tkwin, lObjv[j], &slave) + } else if (TkGetWindowFromObj(NULL, tkwin, lObjv[j], &slave) == TCL_OK) { /* * Is it gridded in this master? */ - Tcl_ResetResult(interp); slavePtr = GetGrid(slave); if (slavePtr->masterPtr != masterPtr) { Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ", @@ -1072,7 +1077,6 @@ GridRowColumnConfigureCommand(tkwin, interp, objc, objv) return TCL_ERROR; } } else { - Tcl_ResetResult(interp); Tcl_AppendResult(interp, Tcl_GetString(objv[0]), " ", Tcl_GetString(objv[1]), ": illegal index \"", Tcl_GetString(lObjv[j]), "\"", NULL); @@ -2436,6 +2440,86 @@ SetGridSize(masterPtr) /* *---------------------------------------------------------------------- * + * SetSlaveColumn -- + * + * Update column data for a slave, checking that MAX_ELEMENT bound + * is not passed. + * + * Results: + * TCL_ERROR if out of bounds, TCL_OK otherwise + * + * Side effects: + * 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 */ +{ + int newColumn, newNumCols, lastCol; + + newColumn = (column >= 0) ? column : slavePtr->column; + newNumCols = (numCols >= 1) ? numCols : slavePtr->numCols; + + lastCol = ((newColumn >= 0) ? newColumn : 0) + newNumCols; + if (lastCol >= MAX_ELEMENT) { + Tcl_SetResult(interp, "Column out of bounds", TCL_STATIC); + return TCL_ERROR; + } + + slavePtr->column = newColumn; + slavePtr->numCols = newNumCols; + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * SetSlaveRow -- + * + * Update row data for a slave, checking that MAX_ELEMENT bound + * is not passed. + * + * Results: + * TCL_ERROR if out of bounds, TCL_OK otherwise + * + * Side effects: + * 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 */ +{ + int newRow, newNumRows, lastRow; + + newRow = (row >= 0) ? row : slavePtr->row; + newNumRows = (numRows >= 1) ? numRows : slavePtr->numRows; + + lastRow = ((newRow >= 0) ? newRow : 0) + newNumRows; + if (lastRow >= MAX_ELEMENT) { + Tcl_SetResult(interp, "Row out of bounds", TCL_STATIC); + return TCL_ERROR; + } + + slavePtr->row = newRow; + slavePtr->numRows = newNumRows; + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * CheckSlotData -- * * This internal procedure is used to manage the storage for row and @@ -2976,7 +3060,9 @@ ConfigureSlaves(interp, tkwin, objc, objv) "\": must be a non-negative integer", NULL); return TCL_ERROR; } - slavePtr->column = tmp; + if (SetSlaveColumn(interp, slavePtr, tmp, -1) != TCL_OK) { + return TCL_ERROR; + } break; case CONF_COLUMNSPAN: if (Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK @@ -2986,7 +3072,9 @@ ConfigureSlaves(interp, tkwin, objc, objv) "\": must be a positive integer", NULL); return TCL_ERROR; } - slavePtr->numCols = tmp; + if (SetSlaveColumn(interp, slavePtr, -1, tmp) != TCL_OK) { + return TCL_ERROR; + } break; case CONF_IN: if (TkGetWindowFromObj(interp, tkwin, objv[i+1], @@ -3055,7 +3143,9 @@ ConfigureSlaves(interp, tkwin, objc, objv) "\": must be a non-negative integer", NULL); return TCL_ERROR; } - slavePtr->row = tmp; + if (SetSlaveRow(interp, slavePtr, tmp, -1) != TCL_OK) { + return TCL_ERROR; + } break; case CONF_ROWSPAN: if ((Tcl_GetIntFromObj(NULL, objv[i+1], &tmp) != TCL_OK) @@ -3065,7 +3155,9 @@ ConfigureSlaves(interp, tkwin, objc, objv) "\": must be a positive integer", NULL); return TCL_ERROR; } - slavePtr->numRows = tmp; + if (SetSlaveRow(interp, slavePtr, -1, tmp) != TCL_OK) { + return TCL_ERROR; + } break; } } @@ -3150,11 +3242,18 @@ ConfigureSlaves(interp, tkwin, objc, objv) */ if (slavePtr->column == -1) { - slavePtr->column = defaultColumn; + if (SetSlaveColumn(interp, slavePtr, defaultColumn, -1) != TCL_OK) { + return TCL_ERROR; + } + } + if (SetSlaveColumn(interp, slavePtr, -1, + slavePtr->numCols + defaultColumnSpan - 1) != TCL_OK) { + return TCL_ERROR; } - slavePtr->numCols += defaultColumnSpan - 1; if (slavePtr->row == -1) { - slavePtr->row = defaultRow; + if (SetSlaveRow(interp, slavePtr, defaultRow, -1) != TCL_OK) { + return TCL_ERROR; + } } defaultColumn += slavePtr->numCols; defaultColumnSpan = 1; @@ -3238,7 +3337,10 @@ ConfigureSlaves(interp, tkwin, objc, objv) if (slavePtr->column == lastColumn && slavePtr->row + slavePtr->numRows - 1 == lastRow) { if (slavePtr->numCols <= width) { - slavePtr->numRows++; + if (SetSlaveRow(interp, slavePtr, + -1, slavePtr->numRows + 1) != TCL_OK) { + return TCL_ERROR; + } match++; j += slavePtr->numCols - 1; lastWindow = Tk_PathName(slavePtr->tkwin); diff --git a/generic/tkWindow.c b/generic/tkWindow.c index d61e1ec..ad42c6f 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWindow.c,v 1.72 2006/04/05 21:00:00 hobbs Exp $ + * RCS: @(#) $Id: tkWindow.c,v 1.73 2006/04/11 21:52:20 pspjuth Exp $ */ #include "tkPort.h" @@ -2259,7 +2259,8 @@ Tk_SetClassProcs(tkwin, procs, instanceData) * Results: * The return result is either a token for the window corresponding to * "name", or else NULL to indicate that there is no such window. In this - * case, an error message is left in the interp's result. + * case, an error message is left in the interp's result, unless interp + * is NULL. * * Side effects: * None. @@ -2282,15 +2283,19 @@ Tk_NameToWindow(interp, pathName, tkwin) * we're on our way out of the application. */ - Tcl_AppendResult(interp, "NULL main window", NULL); + if (interp != NULL) { + Tcl_AppendResult(interp, "NULL main window", NULL); + } return NULL; } hPtr = Tcl_FindHashEntry(&((TkWindow *) tkwin)->mainPtr->nameTable, pathName); if (hPtr == NULL) { - Tcl_AppendResult(interp, "bad window path name \"", - pathName, "\"", NULL); + if (interp != NULL) { + Tcl_AppendResult(interp, "bad window path name \"", + pathName, "\"", NULL); + } return NULL; } return (Tk_Window) Tcl_GetHashValue(hPtr); diff --git a/tests/grid.test b/tests/grid.test index c58d442..0d8129a 100644 --- a/tests/grid.test +++ b/tests/grid.test @@ -5,7 +5,7 @@ # Copyright (c) 1998-1999 by Scriptics Corporation. # All rights reserved. # -# RCS: @(#) $Id: grid.test,v 1.27 2006/04/05 20:54:57 hobbs Exp $ +# RCS: @(#) $Id: grid.test,v 1.28 2006/04/11 21:52:20 pspjuth Exp $ package require tcltest 2.1 eval tcltest::configure $argv @@ -781,6 +781,76 @@ test grid-10.34 {column/row configure - empty 'all' configure} { destroy $t } {} +test grid-10.35 {column/row configure} { + # Test that no lingering message is there + frame .f + set res [grid columnconfigure .f all -weight 1] + append res [grid columnconfigure .f {0 all} -weight 1] + frame .f.f + grid .f.f + append res [grid columnconfigure .f {.f.f} -weight 1] + append res [grid columnconfigure .f {.f.f 1} -weight 1] + append res [grid columnconfigure .f {2 .f.f} -weight 1] + destroy .f + set res +} {} +grid_reset 10.35 + +test grid-10.36 {column/row configure} { + list [catch {grid columnconfigure . all} msg] $msg +} {1 {expected integer but got "all" (when retreiving options only integer indices are allowed)}} +grid_reset 10.36 + +test grid-10.37 {column/row configure} { + list [catch {grid columnconfigure . 100000} msg] $msg +} {0 {-minsize 0 -pad 0 -uniform {} -weight 0}} +grid_reset 10.37 + +test grid-10.38 {column/row configure} -body { + # This is a test for bug 1423666 where a column >= 10000 caused + # a crash in layout. The update is needed to reach the layout stage. + # Test different combinations of row/column overflow + frame .f + set res {} + lappend res [catch {grid .f -row 10 -column 9999} msg] $msg ; update + lappend res [catch {grid .f -row 9999 -column 10} msg] $msg ; update + lappend res [catch {grid .f -columnspan 2 -column 9998} msg] $msg ; update + lappend res [catch {grid .f -rowspan 2 -row 9998} msg] $msg ; update + lappend res [catch {grid .f -column 9998 -columnspan 2} msg] $msg ; update + lappend res [catch {grid .f -row 9998 -rowspan 2} msg] $msg ; update + set res +} -cleanup {destroy .f} -result [lrange { + 1 {Column out of bounds} + 1 {Row out of bounds} + 1 {Column out of bounds} + 1 {Row out of bounds} + 1 {Column out of bounds} + 1 {Row out of bounds} +} 0 end] +grid_reset 10.38 + +test grid-10.39 {column/row configure} -body { + # Additional tests for row/column overflow + frame .f + frame .g + set res {} + grid .f -row 9998 -column 0 + lappend res [catch {grid ^ -in .} msg] $msg ; update + lappend res [catch {grid .g} msg] $msg ; update + grid forget .f .g + lappend res [catch {grid .f - -column 9998} msg] $msg ; update + grid forget .f .g + lappend res [catch {eval grid [string repeat " x " 9999] .f} msg] $msg + update + set res +} -cleanup {destroy .f .g} -result [lrange { + 1 {Row out of bounds} + 1 {Row out of bounds} + 1 {Column out of bounds} + 1 {Column out of bounds} +} 0 end] +grid_reset 10.39 + # auto-placement tests test grid-11.1 {default widget placement} { -- cgit v0.12