diff options
Diffstat (limited to 'generic/tkPack.c')
-rw-r--r-- | generic/tkPack.c | 220 |
1 files changed, 140 insertions, 80 deletions
diff --git a/generic/tkPack.c b/generic/tkPack.c index 0733d86..07047a9 100644 --- a/generic/tkPack.c +++ b/generic/tkPack.c @@ -10,20 +10,20 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkPack.c,v 1.27 2007/12/13 15:24:16 dgp Exp $ + * RCS: @(#) $Id: tkPack.c,v 1.35 2009/09/18 22:35:00 pspjuth Exp $ */ #include "tkInt.h" typedef enum {TOP, BOTTOM, LEFT, RIGHT} Side; -static CONST char *sideNames[] = { +static const char *const sideNames[] = { "top", "bottom", "left", "right", NULL }; -/* For each window that the packer cares about (either because - * the window is managed by the packer or because the window - * has slaves that are managed by the packer), there is a - * structure of the following type: +/* + * For each window that the packer cares about (either because the window is + * managed by the packer or because the window has slaves that are managed by + * the packer), there is a structure of the following type: */ typedef struct Packer { @@ -34,9 +34,9 @@ typedef struct Packer { struct Packer *masterPtr; /* Master window within which this window is * packed (NULL means this window isn't * managed by the packer). */ - struct Packer *nextPtr; /* Next window packed within same master. - * List is priority-ordered: first on list - * gets packed first. */ + struct Packer *nextPtr; /* Next window packed within same master. List + * is priority-ordered: first on list gets + * packed first. */ struct Packer *slavePtr; /* First in list of slaves packed inside this * window (NULL means no packed slaves). */ Side side; /* Side of master against which this window is @@ -89,6 +89,8 @@ typedef struct Packer { * size. 0 means if this window is a master then * Tk will set its requested size to fit the * needs of its slaves. + * ALLOCED_MASTER 1 means that Pack has allocated itself as + * geometry master for this window. */ #define REQUESTED_REPACK 1 @@ -97,6 +99,7 @@ typedef struct Packer { #define EXPAND 8 #define OLD_STYLE 16 #define DONT_PROPAGATE 32 +#define ALLOCED_MASTER 64 /* * The following structure is the official type record for the packer: @@ -118,11 +121,11 @@ static const Tk_GeomMgr packerType = { static void ArrangePacking(ClientData clientData); static int ConfigureSlaves(Tcl_Interp *interp, Tk_Window tkwin, - int objc, Tcl_Obj *CONST objv[]); + int objc, Tcl_Obj *const objv[]); static void DestroyPacker(char *memPtr); static Packer * GetPacker(Tk_Window tkwin); static int PackAfter(Tcl_Interp *interp, Packer *prevPtr, - Packer *masterPtr, int objc,Tcl_Obj *CONST objv[]); + Packer *masterPtr, int objc,Tcl_Obj *const objv[]); static void PackStructureProc(ClientData clientData, XEvent *eventPtr); static void Unlink(Packer *packPtr); @@ -130,7 +133,7 @@ static int XExpansion(Packer *slavePtr, int cavityWidth); static int YExpansion(Packer *slavePtr, int cavityHeight); /* - *-------------------------------------------------------------- + *------------------------------------------------------------------------ * * TkPrintPadAmount -- * @@ -144,14 +147,14 @@ static int YExpansion(Packer *slavePtr, int cavityHeight); * Side effects: * None. * - *-------------------------------------------------------------- + *------------------------------------------------------------------------ */ void TkPrintPadAmount( Tcl_Interp *interp, /* The interpreter into which the result is * written. */ - char *switchName, /* One of "padx", "pady", "ipadx" or "ipady" */ + const char *switchName, /* One of "padx", "pady", "ipadx" or "ipady" */ int halfSpace, /* The left or top padding amount */ int allSpace) /* The total amount of padding */ { @@ -166,7 +169,7 @@ TkPrintPadAmount( } /* - *-------------------------------------------------------------- + *------------------------------------------------------------------------ * * Tk_PackCmd -- * @@ -179,7 +182,7 @@ TkPrintPadAmount( * Side effects: * See the user documentation. * - *-------------------------------------------------------------- + *------------------------------------------------------------------------ */ int @@ -187,11 +190,11 @@ Tk_PackObjCmd( ClientData clientData, /* Main window associated with interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ - Tcl_Obj *CONST objv[]) /* Argument objects. */ + Tcl_Obj *const objv[]) /* Argument objects. */ { - Tk_Window tkwin = (Tk_Window) clientData; - char *argv2; - static CONST char *optionStrings[] = { + Tk_Window tkwin = clientData; + const char *argv2; + static const char *const optionStrings[] = { /* after, append, before and unpack are deprecated */ "after", "append", "before", "unpack", "configure", "forget", "info", "propagate", "slaves", NULL }; @@ -201,7 +204,8 @@ Tk_PackObjCmd( int index; if (objc >= 2) { - char *string = Tcl_GetString(objv[1]); + const char *string = Tcl_GetString(objv[1]); + if (string[0] == '.') { return ConfigureSlaves(interp, tkwin, objc-1, objv+1); } @@ -307,8 +311,7 @@ Tk_PackObjCmd( } slavePtr = GetPacker(slave); if ((slavePtr != NULL) && (slavePtr->masterPtr != NULL)) { - Tk_ManageGeometry(slave, NULL, - (ClientData) NULL); + Tk_ManageGeometry(slave, NULL, NULL); if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin); @@ -385,6 +388,16 @@ Tk_PackObjCmd( return TCL_ERROR; } if (propagate) { + /* + * If we have slaves, we need to register as geometry master. + */ + + if (masterPtr->slavePtr != NULL) { + if (TkSetGeometryMaster(interp, master, "pack") != TCL_OK) { + return TCL_ERROR; + } + masterPtr->flags |= ALLOCED_MASTER; + } masterPtr->flags &= ~DONT_PROPAGATE; /* @@ -397,9 +410,13 @@ Tk_PackObjCmd( } if (!(masterPtr->flags & REQUESTED_REPACK)) { masterPtr->flags |= REQUESTED_REPACK; - Tcl_DoWhenIdle(ArrangePacking, (ClientData) masterPtr); + Tcl_DoWhenIdle(ArrangePacking, masterPtr); } } else { + if (masterPtr->flags & ALLOCED_MASTER) { + TkFreeGeometryMaster(master, "pack"); + masterPtr->flags &= ~ALLOCED_MASTER; + } masterPtr->flags |= DONT_PROPAGATE; } break; @@ -407,6 +424,7 @@ Tk_PackObjCmd( case PACK_SLAVES: { Tk_Window master; Packer *masterPtr, *slavePtr; + Tcl_Obj *resultObj; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "window"); @@ -415,11 +433,14 @@ Tk_PackObjCmd( if (TkGetWindowFromObj(interp, tkwin, objv[2], &master) != TCL_OK) { return TCL_ERROR; } + resultObj = Tcl_NewObj(); masterPtr = GetPacker(master); for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; slavePtr = slavePtr->nextPtr) { - Tcl_AppendElement(interp, Tk_PathName(slavePtr->tkwin)); + Tcl_ListObjAppendElement(NULL, resultObj, + TkNewWindowObj(slavePtr->tkwin)); } + Tcl_SetObjResult(interp, resultObj); break; } case PACK_UNPACK: { @@ -435,8 +456,7 @@ Tk_PackObjCmd( } packPtr = GetPacker(tkwin2); if ((packPtr != NULL) && (packPtr->masterPtr != NULL)) { - Tk_ManageGeometry(tkwin2, NULL, - (ClientData) NULL); + Tk_ManageGeometry(tkwin2, NULL, NULL); if (packPtr->masterPtr->tkwin != Tk_Parent(packPtr->tkwin)) { Tk_UnmaintainGeometry(packPtr->tkwin, packPtr->masterPtr->tkwin); @@ -452,7 +472,7 @@ Tk_PackObjCmd( } /* - *-------------------------------------------------------------- + *------------------------------------------------------------------------ * * PackReqProc -- * @@ -466,7 +486,7 @@ Tk_PackObjCmd( * Arranges for tkwin, and all its managed siblings, to be re-packed at * the next idle point. * - *-------------------------------------------------------------- + *------------------------------------------------------------------------ */ /* ARGSUSED */ @@ -477,17 +497,17 @@ PackReqProc( Tk_Window tkwin) /* Other Tk-related information about the * window. */ { - register Packer *packPtr = (Packer *) clientData; + register Packer *packPtr = clientData; packPtr = packPtr->masterPtr; if (!(packPtr->flags & REQUESTED_REPACK)) { packPtr->flags |= REQUESTED_REPACK; - Tcl_DoWhenIdle(ArrangePacking, (ClientData) packPtr); + Tcl_DoWhenIdle(ArrangePacking, packPtr); } } /* - *-------------------------------------------------------------- + *------------------------------------------------------------------------ * * PackLostSlaveProc -- * @@ -500,7 +520,7 @@ PackReqProc( * Side effects: * Forgets all packer-related information about the slave. * - *-------------------------------------------------------------- + *------------------------------------------------------------------------ */ /* ARGSUSED */ @@ -510,7 +530,7 @@ PackLostSlaveProc( * stolen away. */ Tk_Window tkwin) /* Tk's handle for the slave window. */ { - register Packer *slavePtr = (Packer *) clientData; + register Packer *slavePtr = clientData; if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin); @@ -520,7 +540,7 @@ PackLostSlaveProc( } /* - *-------------------------------------------------------------- + *------------------------------------------------------------------------ * * ArrangePacking -- * @@ -535,7 +555,7 @@ PackLostSlaveProc( * Side effects: * The packed slaves of masterPtr may get resized or moved. * - *-------------------------------------------------------------- + *------------------------------------------------------------------------ */ static void @@ -543,7 +563,7 @@ ArrangePacking( ClientData clientData) /* Structure describing master whose slaves * are to be re-layed out. */ { - register Packer *masterPtr = (Packer *) clientData; + register Packer *masterPtr = clientData; register Packer *slavePtr; int cavityX, cavityY, cavityWidth, cavityHeight; /* These variables keep track of the @@ -583,7 +603,7 @@ ArrangePacking( } masterPtr->abortPtr = &abort; abort = 0; - Tcl_Preserve((ClientData) masterPtr); + Tcl_Preserve(masterPtr); /* * Pass #1: scan all the slaves to figure out the total amount of space @@ -652,7 +672,7 @@ ArrangePacking( && !(masterPtr->flags & DONT_PROPAGATE)) { Tk_GeometryRequest(masterPtr->tkwin, maxWidth, maxHeight); masterPtr->flags |= REQUESTED_REPACK; - Tcl_DoWhenIdle(ArrangePacking, (ClientData) masterPtr); + Tcl_DoWhenIdle(ArrangePacking, masterPtr); goto done; } @@ -843,7 +863,7 @@ ArrangePacking( done: masterPtr->abortPtr = NULL; - Tcl_Release((ClientData) masterPtr); + Tcl_Release(masterPtr); } /* @@ -890,9 +910,11 @@ XExpansion( childWidth = Tk_ReqWidth(slavePtr->tkwin) + slavePtr->doubleBw + slavePtr->padX + slavePtr->iPadX; if ((slavePtr->side == TOP) || (slavePtr->side == BOTTOM)) { - curExpand = (cavityWidth - childWidth)/numExpand; - if (curExpand < minExpand) { - minExpand = curExpand; + if (numExpand) { + curExpand = (cavityWidth - childWidth)/numExpand; + if (curExpand < minExpand) { + minExpand = curExpand; + } } } else { cavityWidth -= childWidth; @@ -901,9 +923,11 @@ XExpansion( } } } - curExpand = cavityWidth/numExpand; - if (curExpand < minExpand) { - minExpand = curExpand; + if (numExpand) { + curExpand = cavityWidth/numExpand; + if (curExpand < minExpand) { + minExpand = curExpand; + } } return (minExpand < 0) ? 0 : minExpand; } @@ -945,9 +969,11 @@ YExpansion( childHeight = Tk_ReqHeight(slavePtr->tkwin) + slavePtr->doubleBw + slavePtr->padY + slavePtr->iPadY; if ((slavePtr->side == LEFT) || (slavePtr->side == RIGHT)) { - curExpand = (cavityHeight - childHeight)/numExpand; - if (curExpand < minExpand) { - minExpand = curExpand; + if (numExpand) { + curExpand = (cavityHeight - childHeight)/numExpand; + if (curExpand < minExpand) { + minExpand = curExpand; + } } } else { cavityHeight -= childHeight; @@ -956,15 +982,17 @@ YExpansion( } } } - curExpand = cavityHeight/numExpand; - if (curExpand < minExpand) { - minExpand = curExpand; + if (numExpand) { + curExpand = cavityHeight/numExpand; + if (curExpand < minExpand) { + minExpand = curExpand; + } } return (minExpand < 0) ? 0 : minExpand; } /* - *-------------------------------------------------------------- + *------------------------------------------------------------------------ * * GetPacker -- * @@ -979,7 +1007,7 @@ YExpansion( * A new packer structure may be created. If so, then a callback is set * up to clean things up when the window is deleted. * - *-------------------------------------------------------------- + *------------------------------------------------------------------------ */ static Packer * @@ -1005,9 +1033,9 @@ GetPacker( hPtr = Tcl_CreateHashEntry(&dispPtr->packerHashTable, (char *) tkwin, &isNew); if (!isNew) { - return (Packer *) Tcl_GetHashValue(hPtr); + return Tcl_GetHashValue(hPtr); } - packPtr = (Packer *) ckalloc(sizeof(Packer)); + packPtr = ckalloc(sizeof(Packer)); packPtr->tkwin = tkwin; packPtr->masterPtr = NULL; packPtr->nextPtr = NULL; @@ -1022,12 +1050,12 @@ GetPacker( packPtr->flags = 0; Tcl_SetHashValue(hPtr, packPtr); Tk_CreateEventHandler(tkwin, StructureNotifyMask, - PackStructureProc, (ClientData) packPtr); + PackStructureProc, packPtr); return packPtr; } /* - *-------------------------------------------------------------- + *------------------------------------------------------------------------ * * PackAfter -- * @@ -1041,7 +1069,7 @@ GetPacker( * The geometry of the specified windows may change, both now and again * in the future. * - *-------------------------------------------------------------- + *------------------------------------------------------------------------ */ static int @@ -1052,7 +1080,7 @@ PackAfter( * masterPtr. */ Packer *masterPtr, /* Master in which to pack windows. */ int objc, /* Number of elements in objv. */ - Tcl_Obj *CONST objv[]) /* Array of lists, each containing 2 elements: + Tcl_Obj *const objv[]) /* Array of lists, each containing 2 elements: * window name and side against which to * pack. */ { @@ -1124,7 +1152,7 @@ PackAfter( packPtr->flags |= OLD_STYLE; for (index = 0 ; index < optionCount; index++) { Tcl_Obj *curOptPtr = options[index]; - char *curOpt = Tcl_GetStringFromObj(curOptPtr, &length); + const char *curOpt = Tcl_GetStringFromObj(curOptPtr, &length); c = curOpt[0]; @@ -1227,7 +1255,17 @@ PackAfter( packPtr->nextPtr = prevPtr->nextPtr; prevPtr->nextPtr = packPtr; } - Tk_ManageGeometry(tkwin, &packerType, (ClientData) packPtr); + Tk_ManageGeometry(tkwin, &packerType, packPtr); + + if (!(masterPtr->flags & DONT_PROPAGATE)) { + if (TkSetGeometryMaster(interp, masterPtr->tkwin, "pack") + != TCL_OK) { + Tk_ManageGeometry(tkwin, NULL, NULL); + Unlink(packPtr); + return TCL_ERROR; + } + masterPtr->flags |= ALLOCED_MASTER; + } } } @@ -1240,7 +1278,7 @@ PackAfter( } if (!(masterPtr->flags & REQUESTED_REPACK)) { masterPtr->flags |= REQUESTED_REPACK; - Tcl_DoWhenIdle(ArrangePacking, (ClientData) masterPtr); + Tcl_DoWhenIdle(ArrangePacking, masterPtr); } return TCL_OK; } @@ -1286,13 +1324,24 @@ Unlink( } if (!(masterPtr->flags & REQUESTED_REPACK)) { masterPtr->flags |= REQUESTED_REPACK; - Tcl_DoWhenIdle(ArrangePacking, (ClientData) masterPtr); + Tcl_DoWhenIdle(ArrangePacking, masterPtr); } if (masterPtr->abortPtr != NULL) { *masterPtr->abortPtr = 1; } packPtr->masterPtr = NULL; + + /* + * If we have emptied this master from slaves it means we are no longer + * handling it and should mark it as free. + */ + + if (masterPtr->slavePtr == NULL && masterPtr->flags & ALLOCED_MASTER) { + TkFreeGeometryMaster(masterPtr->tkwin, "pack"); + masterPtr->flags &= ~ALLOCED_MASTER; + } + } /* @@ -1319,7 +1368,8 @@ DestroyPacker( * dead. */ { register Packer *packPtr = (Packer *) memPtr; - ckfree((char *) packPtr); + + ckfree(packPtr); } /* @@ -1346,20 +1396,20 @@ PackStructureProc( * eventPtr. */ XEvent *eventPtr) /* Describes what just happened. */ { - register Packer *packPtr = (Packer *) clientData; + register Packer *packPtr = clientData; if (eventPtr->type == ConfigureNotify) { if ((packPtr->slavePtr != NULL) && !(packPtr->flags & REQUESTED_REPACK)) { packPtr->flags |= REQUESTED_REPACK; - Tcl_DoWhenIdle(ArrangePacking, (ClientData) packPtr); + Tcl_DoWhenIdle(ArrangePacking, packPtr); } if ((packPtr->masterPtr != NULL) && (packPtr->doubleBw != 2*Tk_Changes(packPtr->tkwin)->border_width)) { if (!(packPtr->masterPtr->flags & REQUESTED_REPACK)) { packPtr->doubleBw = 2*Tk_Changes(packPtr->tkwin)->border_width; packPtr->masterPtr->flags |= REQUESTED_REPACK; - Tcl_DoWhenIdle(ArrangePacking, (ClientData) packPtr->masterPtr); + Tcl_DoWhenIdle(ArrangePacking, packPtr->masterPtr); } } } else if (eventPtr->type == DestroyNotify) { @@ -1371,8 +1421,7 @@ PackStructureProc( for (slavePtr = packPtr->slavePtr; slavePtr != NULL; slavePtr = nextPtr) { - Tk_ManageGeometry(slavePtr->tkwin, NULL, - (ClientData) NULL); + Tk_ManageGeometry(slavePtr->tkwin, NULL, NULL); Tk_UnmapWindow(slavePtr->tkwin); slavePtr->masterPtr = NULL; nextPtr = slavePtr->nextPtr; @@ -1386,10 +1435,10 @@ PackStructureProc( } if (packPtr->flags & REQUESTED_REPACK) { - Tcl_CancelIdleCall(ArrangePacking, (ClientData) packPtr); + Tcl_CancelIdleCall(ArrangePacking, packPtr); } packPtr->tkwin = NULL; - Tcl_EventuallyFree((ClientData) packPtr, DestroyPacker); + Tcl_EventuallyFree(packPtr, DestroyPacker); } else if (eventPtr->type == MapNotify) { /* * When a master gets mapped, must redo the geometry computation so @@ -1399,7 +1448,7 @@ PackStructureProc( if ((packPtr->slavePtr != NULL) && !(packPtr->flags & REQUESTED_REPACK)) { packPtr->flags |= REQUESTED_REPACK; - Tcl_DoWhenIdle(ArrangePacking, (ClientData) packPtr); + Tcl_DoWhenIdle(ArrangePacking, packPtr); } } else if (eventPtr->type == UnmapNotify) { register Packer *packPtr2; @@ -1441,7 +1490,7 @@ ConfigureSlaves( 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 + 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. */ @@ -1449,8 +1498,8 @@ ConfigureSlaves( Packer *masterPtr, *slavePtr, *prevPtr, *otherPtr; Tk_Window other, slave, parent, ancestor; int i, j, numWindows, tmp, positionGiven; - char *string; - static CONST char *optionStrings[] = { + const char *string; + static const char *const optionStrings[] = { "-after", "-anchor", "-before", "-expand", "-fill", "-in", "-ipadx", "-ipady", "-padx", "-pady", "-side", NULL }; enum options { @@ -1532,8 +1581,8 @@ ConfigureSlaves( if (prevPtr->masterPtr == NULL) { notPacked: Tcl_AppendResult(interp, "window \"", - Tcl_GetString(objv[i+1]), - "\" isn't packed", NULL); + Tcl_GetString(objv[i+1]), "\" isn't packed", + NULL); return TCL_ERROR; } masterPtr = prevPtr->masterPtr; @@ -1730,6 +1779,7 @@ ConfigureSlaves( } Unlink(slavePtr); } + slavePtr->masterPtr = masterPtr; if (prevPtr == NULL) { slavePtr->nextPtr = masterPtr->slavePtr; @@ -1738,9 +1788,19 @@ ConfigureSlaves( slavePtr->nextPtr = prevPtr->nextPtr; prevPtr->nextPtr = slavePtr; } - Tk_ManageGeometry(slave, &packerType, (ClientData) slavePtr); + Tk_ManageGeometry(slave, &packerType, slavePtr); prevPtr = slavePtr; + if (!(masterPtr->flags & DONT_PROPAGATE)) { + if (TkSetGeometryMaster(interp, masterPtr->tkwin, "pack") + != TCL_OK) { + Tk_ManageGeometry(slave, NULL, NULL); + Unlink(slavePtr); + return TCL_ERROR; + } + masterPtr->flags |= ALLOCED_MASTER; + } + /* * Arrange for the master to be re-packed at the first idle moment. */ @@ -1751,7 +1811,7 @@ ConfigureSlaves( } if (!(masterPtr->flags & REQUESTED_REPACK)) { masterPtr->flags |= REQUESTED_REPACK; - Tcl_DoWhenIdle(ArrangePacking, (ClientData) masterPtr); + Tcl_DoWhenIdle(ArrangePacking, masterPtr); } } return TCL_OK; |