📄 tkpack.c
字号:
} } curExpand = cavityWidth/numExpand; if (curExpand < minExpand) { minExpand = curExpand; } return (minExpand < 0) ? 0 : minExpand;}/* *---------------------------------------------------------------------- * * YExpansion -- * * Given a list of packed slaves, the first of which is packed * on the top or bottom and is expandable, compute how much to * expand the child. * * Results: * The return value is the number of additional pixels to give to * the child. * * Side effects: * None. * *---------------------------------------------------------------------- */static intYExpansion(slavePtr, cavityHeight) register Packer *slavePtr; /* First in list of remaining * slaves. */ int cavityHeight; /* Vertical space left for all * remaining slaves. */{ int numExpand, minExpand, curExpand; int childHeight; /* * See comments for XExpansion. */ minExpand = cavityHeight; numExpand = 0; for ( ; slavePtr != NULL; slavePtr = slavePtr->nextPtr) { 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; } } else { cavityHeight -= childHeight; if (slavePtr->flags & EXPAND) { numExpand++; } } } curExpand = cavityHeight/numExpand; if (curExpand < minExpand) { minExpand = curExpand; } return (minExpand < 0) ? 0 : minExpand;}/* *-------------------------------------------------------------- * * GetPacker -- * * This internal procedure is used to locate a Packer * structure for a given window, creating one if one * doesn't exist already. * * Results: * The return value is a pointer to the Packer structure * corresponding to tkwin. * * Side effects: * 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 *GetPacker(tkwin) Tk_Window tkwin; /* Token for window for which * packer structure is desired. */{ register Packer *packPtr; Tcl_HashEntry *hPtr; int new; if (!initialized) { initialized = 1; Tcl_InitHashTable(&packerHashTable, TCL_ONE_WORD_KEYS); } /* * See if there's already packer for this window. If not, * then create a new one. */ hPtr = Tcl_CreateHashEntry(&packerHashTable, (char *) tkwin, &new); if (!new) { return (Packer *) Tcl_GetHashValue(hPtr); } packPtr = (Packer *) ckalloc(sizeof(Packer)); packPtr->tkwin = tkwin; packPtr->masterPtr = NULL; packPtr->nextPtr = NULL; packPtr->slavePtr = NULL; packPtr->side = TOP; packPtr->anchor = TK_ANCHOR_CENTER; packPtr->padX = packPtr->padY = 0; packPtr->iPadX = packPtr->iPadY = 0; packPtr->doubleBw = 2*Tk_Changes(tkwin)->border_width; packPtr->abortPtr = NULL; packPtr->flags = 0; Tcl_SetHashValue(hPtr, packPtr); Tk_CreateEventHandler(tkwin, StructureNotifyMask, PackStructureProc, (ClientData) packPtr); return packPtr;}/* *-------------------------------------------------------------- * * PackAfter -- * * This procedure does most of the real work of adding * one or more windows into the packing order for its parent. * * Results: * A standard Tcl return value. * * Side effects: * The geometry of the specified windows may change, both now and * again in the future. * *-------------------------------------------------------------- */static intPackAfter(interp, prevPtr, masterPtr, argc, argv) Tcl_Interp *interp; /* Interpreter for error reporting. */ Packer *prevPtr; /* Pack windows in argv just after this * window; NULL means pack as first * child of masterPtr. */ Packer *masterPtr; /* Master in which to pack windows. */ int argc; /* Number of elements in argv. */ char **argv; /* Array of lists, each containing 2 * elements: window name and side * against which to pack. */{ register Packer *packPtr; Tk_Window tkwin, ancestor, parent; size_t length; char **options; int index, tmp, optionCount, c; /* * Iterate over all of the window specifiers, each consisting of * two arguments. The first argument contains the window name and * the additional arguments contain options such as "top" or * "padx 20". */ for ( ; argc > 0; argc -= 2, argv += 2, prevPtr = packPtr) { if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: window \"", argv[0], "\" should be followed by options", (char *) NULL); return TCL_ERROR; } /* * Find the packer for the window to be packed, and make sure * that the window in which it will be packed is either its * or a descendant of its parent. */ tkwin = Tk_NameToWindow(interp, argv[0], masterPtr->tkwin); if (tkwin == NULL) { return TCL_ERROR; } parent = Tk_Parent(tkwin); for (ancestor = masterPtr->tkwin; ; ancestor = Tk_Parent(ancestor)) { if (ancestor == parent) { break; } if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_LEVEL) { badWindow: Tcl_AppendResult(interp, "can't pack ", argv[0], " inside ", Tk_PathName(masterPtr->tkwin), (char *) NULL); return TCL_ERROR; } } if (((Tk_FakeWin *) (tkwin))->flags & TK_TOP_LEVEL) { goto badWindow; } if (tkwin == masterPtr->tkwin) { goto badWindow; } packPtr = GetPacker(tkwin); /* * Process options for this window. */ if (Tcl_SplitList(interp, argv[1], &optionCount, &options) != TCL_OK) { return TCL_ERROR; } packPtr->side = TOP; packPtr->anchor = TK_ANCHOR_CENTER; packPtr->padX = packPtr->padY = 0; packPtr->iPadX = packPtr->iPadY = 0; packPtr->flags &= ~(FILLX|FILLY|EXPAND); packPtr->flags |= OLD_STYLE; for (index = 0 ; index < optionCount; index++) { char *curOpt = options[index]; c = curOpt[0]; length = strlen(curOpt); if ((c == 't') && (strncmp(curOpt, "top", length)) == 0) { packPtr->side = TOP; } else if ((c == 'b') && (strncmp(curOpt, "bottom", length)) == 0) { packPtr->side = BOTTOM; } else if ((c == 'l') && (strncmp(curOpt, "left", length)) == 0) { packPtr->side = LEFT; } else if ((c == 'r') && (strncmp(curOpt, "right", length)) == 0) { packPtr->side = RIGHT; } else if ((c == 'e') && (strncmp(curOpt, "expand", length)) == 0) { packPtr->flags |= EXPAND; } else if ((c == 'f') && (strcmp(curOpt, "fill")) == 0) { packPtr->flags |= FILLX|FILLY; } else if ((length == 5) && (strcmp(curOpt, "fillx")) == 0) { packPtr->flags |= FILLX; } else if ((length == 5) && (strcmp(curOpt, "filly")) == 0) { packPtr->flags |= FILLY; } else if ((c == 'p') && (strcmp(curOpt, "padx")) == 0) { if (optionCount < (index+2)) { missingPad: Tcl_AppendResult(interp, "wrong # args: \"", curOpt, "\" option must be followed by screen distance", (char *) NULL); goto error; } if ((Tk_GetPixels(interp, tkwin, options[index+1], &tmp) != TCL_OK) || (tmp < 0)) { badPad: Tcl_AppendResult(interp, "bad pad value \"", options[index+1], "\": must be positive screen distance", (char *) NULL); goto error; } packPtr->padX = tmp; packPtr->iPadX = 0; index++; } else if ((c == 'p') && (strcmp(curOpt, "pady")) == 0) { if (optionCount < (index+2)) { goto missingPad; } if ((Tk_GetPixels(interp, tkwin, options[index+1], &tmp) != TCL_OK) || (tmp < 0)) { goto badPad; } packPtr->padY = tmp; packPtr->iPadY = 0; index++; } else if ((c == 'f') && (length > 1) && (strncmp(curOpt, "frame", length) == 0)) { if (optionCount < (index+2)) { Tcl_AppendResult(interp, "wrong # args: \"frame\" ", "option must be followed by anchor point", (char *) NULL); goto error; } if (Tk_GetAnchor(interp, options[index+1], &packPtr->anchor) != TCL_OK) { goto error; } index++; } else { Tcl_AppendResult(interp, "bad option \"", curOpt, "\": should be top, bottom, left, right, ", "expand, fill, fillx, filly, padx, pady, or frame", (char *) NULL); goto error; } } if (packPtr != prevPtr) { /* * Unpack this window if it's currently packed. */ if (packPtr->masterPtr != NULL) { if ((packPtr->masterPtr != masterPtr) && (packPtr->masterPtr->tkwin != Tk_Parent(packPtr->tkwin))) { Tk_UnmaintainGeometry(packPtr->tkwin, packPtr->masterPtr->tkwin); } Unlink(packPtr); } /* * Add the window in the correct place in its parent's * packing order, then make sure that the window is * managed by us. */ packPtr->masterPtr = masterPtr; if (prevPtr == NULL) { packPtr->nextPtr = masterPtr->slavePtr; masterPtr->slavePtr = packPtr; } else { packPtr->nextPtr = prevPtr->nextPtr; prevPtr->nextPtr = packPtr; } Tk_ManageGeometry(tkwin, &packerType, (ClientData) packPtr); } ckfree((char *) options); } /* * Arrange for the parent to be re-packed at the first * idle moment. */ if (masterPtr->abortPtr != NULL) { *masterPtr->abortPtr = 1; } if (!(masterPtr->flags & REQUESTED_REPACK)) { masterPtr->flags |= REQUESTED_REPACK; Tcl_DoWhenIdle(ArrangePacking, (ClientData) masterPtr); } return TCL_OK; error: ckfree((char *) options); return TCL_ERROR;}/* *---------------------------------------------------------------------- * * Unlink -- * * Remove a packer from its parent's list of slaves. * * Results: * None. * * Side effects: * The parent will be scheduled for repacking. * *---------------------------------------------------------------------- */static voidUnlink(packPtr) register Packer *packPtr; /* Window to unlink. */{ register Packer *masterPtr, *packPtr2; masterPtr = packPtr->masterPtr; if (masterPtr == NULL) { return; } if (masterPtr->slavePtr == packPtr) { masterPtr->slavePtr = packPtr->nextPtr; } else { for (packPtr2 = masterPtr->slavePtr; ; packPtr2 = packPtr2->nextPtr) { if (packPtr2 == NULL) { panic("Unlink couldn't find previous window"); } if (packPtr2->nextPtr == packPtr) { packPtr2->nextPtr = packPtr->nextPtr; break; } } } if (!(masterPtr->flags & REQUESTED_REPACK)) { masterPtr->flags |= REQUESTED_REPACK; Tcl_DoWhenIdle(ArrangePacking, (ClientData) masterPtr); } if (masterPtr->abortPtr != NULL) { *masterPtr->abortPtr = 1; } packPtr->masterPtr = NULL;}/* *---------------------------------------------------------------------- * * DestroyPacker -- * * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release * to clean up the internal structure of a packer at a safe time * (when no-one is using it anymore). * * Results: * None. * * Side effects: * Everything associated with the packer is freed up. * *---------------------------------------------------------------------- */static voidDestroyPacker(memPtr) char *memPtr; /* Info about packed window that * is now dead. */{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -