📄 tkgrid.c
字号:
static Gridder *GetGrid(tkwin) Tk_Window tkwin; /* Token for window for which * grid structure is desired. */{ register Gridder *gridPtr; Tcl_HashEntry *hPtr; int new; if (!initialized) { initialized = 1; Tcl_InitHashTable(&gridHashTable, TCL_ONE_WORD_KEYS); } /* * See if there's already grid for this window. If not, * then create a new one. */ hPtr = Tcl_CreateHashEntry(&gridHashTable, (char *) tkwin, &new); if (!new) { return (Gridder *) Tcl_GetHashValue(hPtr); } gridPtr = (Gridder *) Tcl_Alloc(sizeof(Gridder)); gridPtr->tkwin = tkwin; gridPtr->masterPtr = NULL; gridPtr->masterDataPtr = NULL; gridPtr->nextPtr = NULL; gridPtr->slavePtr = NULL; gridPtr->binNextPtr = NULL; gridPtr->column = gridPtr->row = -1; gridPtr->numCols = 1; gridPtr->numRows = 1; gridPtr->padX = gridPtr->padY = 0; gridPtr->iPadX = gridPtr->iPadY = 0; gridPtr->doubleBw = 2*Tk_Changes(tkwin)->border_width; gridPtr->abortPtr = NULL; gridPtr->flags = 0; gridPtr->sticky = 0; gridPtr->size = 0; gridPtr->masterDataPtr = NULL; Tcl_SetHashValue(hPtr, gridPtr); Tk_CreateEventHandler(tkwin, StructureNotifyMask, GridStructureProc, (ClientData) gridPtr); return gridPtr;}/* *-------------------------------------------------------------- * * SetGridSize -- * * This internal procedure sets the size of the grid occupied * by slaves. * * Results: * none * * Side effects: * The width and height arguments are filled in the master data structure. * Additional space is allocated for the constraints to accomodate * the offsets. * *-------------------------------------------------------------- */static voidSetGridSize(masterPtr) Gridder *masterPtr; /* The geometry master for this grid. */{ register Gridder *slavePtr; /* Current slave window. */ int maxX = 0, maxY = 0; for (slavePtr = masterPtr->slavePtr; slavePtr != NULL; slavePtr = slavePtr->nextPtr) { maxX = MAX(maxX,slavePtr->numCols + slavePtr->column); maxY = MAX(maxY,slavePtr->numRows + slavePtr->row); } masterPtr->masterDataPtr->columnEnd = maxX; masterPtr->masterDataPtr->rowEnd = maxY; CheckSlotData(masterPtr, maxX, COLUMN, CHECK_SPACE); CheckSlotData(masterPtr, maxY, ROW, CHECK_SPACE);}/* *-------------------------------------------------------------- * * CheckSlotData -- * * This internal procedure is used to manage the storage for * row and column (slot) constraints. * * Results: * TRUE if the index is OK, False otherwise. * * Side effects: * A new master grid structure may be created. If so, then * it is initialized. In addition, additional storage for * a row or column constraints may be allocated, and the constraint * maximums are adjusted. * *-------------------------------------------------------------- */static intCheckSlotData(masterPtr, slot, slotType, checkOnly) Gridder *masterPtr; /* the geometry master for this grid */ int slot; /* which slot to look at */ int slotType; /* ROW or COLUMN */ int checkOnly; /* don't allocate new space if true */{ int numSlot; /* number of slots already allocated (Space) */ int end; /* last used constraint */ /* * If slot is out of bounds, return immediately. */ if (slot < 0 || slot >= MAX_ELEMENT) { return TCL_ERROR; } if ((checkOnly == CHECK_ONLY) && (masterPtr->masterDataPtr == NULL)) { return TCL_ERROR; } /* * If we need to allocate more space, allocate a little extra to avoid * repeated re-alloc's for large tables. We need enough space to * hold all of the offsets as well. */ InitMasterData(masterPtr); end = (slotType == ROW) ? masterPtr->masterDataPtr->rowMax : masterPtr->masterDataPtr->columnMax; if (checkOnly == CHECK_ONLY) { return (end < slot) ? TCL_ERROR : TCL_OK; } else { numSlot = (slotType == ROW) ? masterPtr->masterDataPtr->rowSpace : masterPtr->masterDataPtr->columnSpace; if (slot >= numSlot) { int newNumSlot = slot + PREALLOC ; size_t oldSize = numSlot * sizeof(SlotInfo) ; size_t newSize = newNumSlot * sizeof(SlotInfo) ; SlotInfo *new = (SlotInfo *) Tcl_Alloc(newSize); SlotInfo *old = (slotType == ROW) ? masterPtr->masterDataPtr->rowPtr : masterPtr->masterDataPtr->columnPtr; memcpy((VOID *) new, (VOID *) old, oldSize ); memset((VOID *) (new+numSlot), 0, newSize - oldSize ); Tcl_Free((char *) old); if (slotType == ROW) { masterPtr->masterDataPtr->rowPtr = new ; masterPtr->masterDataPtr->rowSpace = newNumSlot ; } else { masterPtr->masterDataPtr->columnPtr = new; masterPtr->masterDataPtr->columnSpace = newNumSlot ; } } if (slot >= end && checkOnly != CHECK_SPACE) { if (slotType == ROW) { masterPtr->masterDataPtr->rowMax = slot+1; } else { masterPtr->masterDataPtr->columnMax = slot+1; } } return TCL_OK; }}/* *-------------------------------------------------------------- * * InitMasterData -- * * This internal procedure is used to allocate and initialize * the data for a geometry master, if the data * doesn't exist already. * * Results: * none * * Side effects: * A new master grid structure may be created. If so, then * it is initialized. * *-------------------------------------------------------------- */static voidInitMasterData(masterPtr) Gridder *masterPtr;{ size_t size; if (masterPtr->masterDataPtr == NULL) { GridMaster *gridPtr = masterPtr->masterDataPtr = (GridMaster *) Tcl_Alloc(sizeof(GridMaster)); size = sizeof(SlotInfo) * TYPICAL_SIZE; gridPtr->columnEnd = 0; gridPtr->columnMax = 0; gridPtr->columnPtr = (SlotInfo *) Tcl_Alloc(size); gridPtr->columnSpace = 0; gridPtr->columnSpace = TYPICAL_SIZE; gridPtr->rowEnd = 0; gridPtr->rowMax = 0; gridPtr->rowPtr = (SlotInfo *) Tcl_Alloc(size); gridPtr->rowSpace = 0; gridPtr->rowSpace = TYPICAL_SIZE; memset((VOID *) gridPtr->columnPtr, 0, size); memset((VOID *) gridPtr->rowPtr, 0, size); }}/* *---------------------------------------------------------------------- * * Unlink -- * * Remove a grid from its parent's list of slaves. * * Results: * None. * * Side effects: * The parent will be scheduled for re-arranging, and the size of the * grid will be adjusted accordingly * *---------------------------------------------------------------------- */static voidUnlink(slavePtr) register Gridder *slavePtr; /* Window to unlink. */{ register Gridder *masterPtr, *slavePtr2; GridMaster *gridPtr; /* pointer to grid data */ masterPtr = slavePtr->masterPtr; if (masterPtr == NULL) { return; } gridPtr = masterPtr->masterDataPtr; if (masterPtr->slavePtr == slavePtr) { masterPtr->slavePtr = slavePtr->nextPtr; } else { for (slavePtr2 = masterPtr->slavePtr; ; slavePtr2 = slavePtr2->nextPtr) { if (slavePtr2 == NULL) { panic("Unlink couldn't find previous window"); } if (slavePtr2->nextPtr == slavePtr) { slavePtr2->nextPtr = slavePtr->nextPtr; break; } } } if (!(masterPtr->flags & REQUESTED_RELAYOUT)) { masterPtr->flags |= REQUESTED_RELAYOUT; Tcl_DoWhenIdle(ArrangeGrid, (ClientData) masterPtr); } if (masterPtr->abortPtr != NULL) { *masterPtr->abortPtr = 1; } if ((slavePtr->numCols+slavePtr->column == gridPtr->columnMax) || (slavePtr->numRows+slavePtr->row == gridPtr->rowMax)) { } slavePtr->masterPtr = NULL;}/* *---------------------------------------------------------------------- * * DestroyGrid -- * * This procedure is invoked by Tk_EventuallyFree or Tcl_Release * to clean up the internal structure of a grid at a safe time * (when no-one is using it anymore). Cleaning up the grid involves * freeing the main structure for all windows. and the master structure * for geometry managers. * * Results: * None. * * Side effects: * Everything associated with the grid is freed up. * *---------------------------------------------------------------------- */static voidDestroyGrid(memPtr) char *memPtr; /* Info about window that is now dead. */{ register Gridder *gridPtr = (Gridder *) memPtr; if (gridPtr->masterDataPtr != NULL) { if (gridPtr->masterDataPtr->rowPtr != NULL) { Tcl_Free((char *) gridPtr->masterDataPtr -> rowPtr); } if (gridPtr->masterDataPtr->columnPtr != NULL) { Tcl_Free((char *) gridPtr->masterDataPtr -> columnPtr); } Tcl_Free((char *) gridPtr->masterDataPtr); } Tcl_Free((char *) gridPtr);}/* *---------------------------------------------------------------------- * * GridStructureProc -- * * This procedure is invoked by the Tk event dispatcher in response * to StructureNotify events. * * Results: * None. * * Side effects: * If a window was just deleted, clean up all its grid-related * information. If it was just resized, re-configure its slaves, if * any. * *---------------------------------------------------------------------- */static voidGridStructureProc(clientData, eventPtr) ClientData clientData; /* Our information about window * referred to by eventPtr. */ XEvent *eventPtr; /* Describes what just happened. */{ register Gridder *gridPtr = (Gridder *) clientData; if (eventPtr->type == ConfigureNotify) { if (!(gridPtr->flags & REQUESTED_RELAYOUT)) { gridPtr->flags |= REQUESTED_RELAYOUT; Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr); } if (gridPtr->doubleBw != 2*Tk_Changes(gridPtr->tkwin)->border_width) { if ((gridPtr->masterPtr != NULL) && !(gridPtr->masterPtr->flags & REQUESTED_RELAYOUT)) { gridPtr->doubleBw = 2*Tk_Changes(gridPtr->tkwin)->border_width; gridPtr->masterPtr->flags |= REQUESTED_RELAYOUT; Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr->masterPtr); } } } else if (eventPtr->type == DestroyNotify) { register Gridder *gridPtr2, *nextPtr; if (gridPtr->masterPtr != NULL) { Unlink(gridPtr); } for (gridPtr2 = gridPtr->slavePtr; gridPtr2 != NULL; gridPtr2 = nextPtr) { Tk_UnmapWindow(gridPtr2->tkwin); gridPtr2->masterPtr = NULL; nextPtr = gridPtr2->nextPtr; gridPtr2->nextPtr = NULL; } Tcl_DeleteHashEntry(Tcl_FindHashEntry(&gridHashTable, (char *) gridPtr->tkwin)); if (gridPtr->flags & REQUESTED_RELAYOUT) { Tk_CancelIdleCall(ArrangeGrid, (ClientData) gridPtr); } gridPtr->tkwin = NULL; Tk_EventuallyFree((ClientData) gridPtr, DestroyGrid); } else if (eventPtr->type == MapNotify) { if (!(gridPtr->flags & REQUESTED_RELAYOUT)) { gridPtr->flags |= REQUESTED_RELAYOUT; Tcl_DoWhenIdle(ArrangeGrid, (ClientData) gridPtr); } } else if (eventPtr->type == UnmapNotify) { register Gridder *gridPtr2; for (gridPtr2 = gridPtr->slavePtr; gridPtr2 != NULL; gridPtr2 = gridPtr2->nextPtr) { Tk_UnmapWindow(gridPtr2->tkwin); } }}/* *---------------------------------------------------------------------- * * ConfigureSlaves -- * * This implements the guts of the "grid configure" command. Given * a list of slaves and configuration options, it arranges for the * grid to manage the slaves and sets the specified options. * arguments consist of windows or window shortcuts followed by * "-option value" pairs. * * Results: * TCL_OK is returned if all went well. Otherwise, TCL_ERROR is * returned and interp->result is set to contain an error message. * * Side effects: * Slave windows get taken over by the grid. * *---------------------------------------------------------------------- */static intConfigureSlaves(interp, tkwin, argc, argv) 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 * window names followed by any number * of "option value" pairs. Caller must * make sure that there is at least one * window name. */{ Gridder *masterPtr; Gridder *slavePtr; Tk_Win
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -