📄 tkoption.c
字号:
bufferSize = Tcl_Seek(chan, 0L, SEEK_END); (void) Tcl_Seek(chan, 0L, SEEK_SET); if (bufferSize < 0) { Tcl_AppendResult(interp, "error seeking to end of file \"", fileName, "\":", Tcl_PosixError(interp), (char *) NULL); Tcl_Close(NULL, chan); return TCL_ERROR; } buffer = (char *) ckalloc((unsigned) bufferSize+1); bufferSize = Tcl_Read(chan, buffer, bufferSize); if (bufferSize < 0) { Tcl_AppendResult(interp, "error reading file \"", fileName, "\":", Tcl_PosixError(interp), (char *) NULL); Tcl_Close(NULL, chan); return TCL_ERROR; } Tcl_Close(NULL, chan); buffer[bufferSize] = 0; result = AddFromString(interp, tkwin, buffer, priority); ckfree(buffer); return result;}/* *-------------------------------------------------------------- * * NewArray -- * * Create a new ElArray structure of a given size. * * Results: * The return value is a pointer to a properly initialized * element array with "numEls" space. The array is marked * as having no active elements. * * Side effects: * Memory is allocated. * *-------------------------------------------------------------- */static ElArray *NewArray(numEls) int numEls; /* How many elements of space to allocate. */{ register ElArray *arrayPtr; arrayPtr = (ElArray *) ckalloc(EL_ARRAY_SIZE(numEls)); arrayPtr->arraySize = numEls; arrayPtr->numUsed = 0; arrayPtr->nextToUse = arrayPtr->els; return arrayPtr;}/* *-------------------------------------------------------------- * * ExtendArray -- * * Add a new element to an array, extending the array if * necessary. * * Results: * The return value is a pointer to the new array, which * will be different from arrayPtr if the array got expanded. * * Side effects: * Memory may be allocated or freed. * *-------------------------------------------------------------- */static ElArray *ExtendArray(arrayPtr, elPtr) register ElArray *arrayPtr; /* Array to be extended. */ register Element *elPtr; /* Element to be copied into array. */{ /* * If the current array has filled up, make it bigger. */ if (arrayPtr->numUsed >= arrayPtr->arraySize) { register ElArray *newPtr; newPtr = (ElArray *) ckalloc(EL_ARRAY_SIZE(2*arrayPtr->arraySize)); newPtr->arraySize = 2*arrayPtr->arraySize; newPtr->numUsed = arrayPtr->numUsed; newPtr->nextToUse = &newPtr->els[newPtr->numUsed]; memcpy((VOID *) newPtr->els, (VOID *) arrayPtr->els, (arrayPtr->arraySize*sizeof(Element))); ckfree((char *) arrayPtr); arrayPtr = newPtr; } *arrayPtr->nextToUse = *elPtr; arrayPtr->nextToUse++; arrayPtr->numUsed++; return arrayPtr;}/* *-------------------------------------------------------------- * * SetupStacks -- * * Arrange the stacks so that they cache all the option * information for a particular window. * * Results: * None. * * Side effects: * The stacks are modified to hold information for tkwin * and all its ancestors in the window hierarchy. * *-------------------------------------------------------------- */static voidSetupStacks(winPtr, leaf) TkWindow *winPtr; /* Window for which information is to * be cached. */ int leaf; /* Non-zero means this is the leaf * window being probed. Zero means this * is an ancestor of the desired leaf. */{ int level, i, *iPtr; register StackLevel *levelPtr; register ElArray *arrayPtr; /* * The following array defines the order in which the current * stacks are searched to find matching entries to add to the * stacks. Given the current priority-based scheme, the order * below is no longer relevant; all that matters is that an * element is on the list *somewhere*. The ordering is a relic * of the old days when priorities were determined differently. */ static int searchOrder[] = {WILDCARD_NODE_CLASS, WILDCARD_NODE_NAME, EXACT_NODE_CLASS, EXACT_NODE_NAME, -1}; if (winPtr->mainPtr->optionRootPtr == NULL) { OptionInit(winPtr->mainPtr); } /* * Step 1: make sure that options are cached for this window's * parent. */ if (winPtr->parentPtr != NULL) { level = winPtr->parentPtr->optionLevel; if ((level == -1) || (cachedWindow == NULL)) { SetupStacks(winPtr->parentPtr, 0); level = winPtr->parentPtr->optionLevel; } level++; } else { level = 1; } /* * Step 2: pop extra unneeded information off the stacks and * mark those windows as no longer having cached information. */ if (curLevel >= level) { while (curLevel >= level) { levels[curLevel].winPtr->optionLevel = -1; curLevel--; } levelPtr = &levels[level]; for (i = 0; i < NUM_STACKS; i++) { arrayPtr = stacks[i]; arrayPtr->numUsed = levelPtr->bases[i]; arrayPtr->nextToUse = &arrayPtr->els[arrayPtr->numUsed]; } } curLevel = winPtr->optionLevel = level; /* * Step 3: if the root database information isn't loaded or * isn't valid, initialize level 0 of the stack from the * database root (this only happens if winPtr is a main window). */ if ((curLevel == 1) && ((cachedWindow == NULL) || (cachedWindow->mainPtr != winPtr->mainPtr))) { for (i = 0; i < NUM_STACKS; i++) { arrayPtr = stacks[i]; arrayPtr->numUsed = 0; arrayPtr->nextToUse = arrayPtr->els; } ExtendStacks(winPtr->mainPtr->optionRootPtr, 0); } /* * Step 4: create a new stack level; grow the level array if * we've run out of levels. Clear the stacks for EXACT_LEAF_NAME * and EXACT_LEAF_CLASS (anything that was there is of no use * any more). */ if (curLevel >= numLevels) { StackLevel *newLevels; newLevels = (StackLevel *) ckalloc((unsigned) (numLevels*2*sizeof(StackLevel))); memcpy((VOID *) newLevels, (VOID *) levels, (numLevels*sizeof(StackLevel))); ckfree((char *) levels); numLevels *= 2; levels = newLevels; } levelPtr = &levels[curLevel]; levelPtr->winPtr = winPtr; arrayPtr = stacks[EXACT_LEAF_NAME]; arrayPtr->numUsed = 0; arrayPtr->nextToUse = arrayPtr->els; arrayPtr = stacks[EXACT_LEAF_CLASS]; arrayPtr->numUsed = 0; arrayPtr->nextToUse = arrayPtr->els; levelPtr->bases[EXACT_LEAF_NAME] = stacks[EXACT_LEAF_NAME]->numUsed; levelPtr->bases[EXACT_LEAF_CLASS] = stacks[EXACT_LEAF_CLASS]->numUsed; levelPtr->bases[EXACT_NODE_NAME] = stacks[EXACT_NODE_NAME]->numUsed; levelPtr->bases[EXACT_NODE_CLASS] = stacks[EXACT_NODE_CLASS]->numUsed; levelPtr->bases[WILDCARD_LEAF_NAME] = stacks[WILDCARD_LEAF_NAME]->numUsed; levelPtr->bases[WILDCARD_LEAF_CLASS] = stacks[WILDCARD_LEAF_CLASS]->numUsed; levelPtr->bases[WILDCARD_NODE_NAME] = stacks[WILDCARD_NODE_NAME]->numUsed; levelPtr->bases[WILDCARD_NODE_CLASS] = stacks[WILDCARD_NODE_CLASS]->numUsed; /* * Step 5: scan the current stack level looking for matches to this * window's name or class; where found, add new information to the * stacks. */ for (iPtr = searchOrder; *iPtr != -1; iPtr++) { register Element *elPtr; int count; Tk_Uid id; i = *iPtr; if (i & CLASS) { id = winPtr->classUid; } else { id = winPtr->nameUid; } elPtr = stacks[i]->els; count = levelPtr->bases[i]; /* * For wildcard stacks, check all entries; for non-wildcard * stacks, only check things that matched in the parent. */ if (!(i & WILDCARD)) { elPtr += levelPtr[-1].bases[i]; count -= levelPtr[-1].bases[i]; } for ( ; count > 0; elPtr++, count--) { if (elPtr->nameUid != id) { continue; } ExtendStacks(elPtr->child.arrayPtr, leaf); } } cachedWindow = winPtr;}/* *-------------------------------------------------------------- * * ExtendStacks -- * * Given an element array, copy all the elements from the * array onto the system stacks (except for irrelevant leaf * elements). * * Results: * None. * * Side effects: * The option stacks are extended. * *-------------------------------------------------------------- */static voidExtendStacks(arrayPtr, leaf) ElArray *arrayPtr; /* Array of elements to copy onto stacks. */ int leaf; /* If zero, then don't copy exact leaf * elements. */{ register int count; register Element *elPtr; for (elPtr = arrayPtr->els, count = arrayPtr->numUsed; count > 0; elPtr++, count--) { if (!(elPtr->flags & (NODE|WILDCARD)) && !leaf) { continue; } stacks[elPtr->flags] = ExtendArray(stacks[elPtr->flags], elPtr); }}/* *-------------------------------------------------------------- * * OptionInit -- * * Initialize data structures for option handling. * * Results: * None. * * Side effects: * Option-related data structures get initialized. * *-------------------------------------------------------------- */static voidOptionInit(mainPtr) register TkMainInfo *mainPtr; /* Top-level information about * window that isn't initialized * yet. */{ int i; Tcl_Interp *interp; /* * First, once-only initialization. */ if (numLevels == 0) { numLevels = 5; levels = (StackLevel *) ckalloc((unsigned) (5*sizeof(StackLevel))); for (i = 0; i < NUM_STACKS; i++) { stacks[i] = NewArray(10); levels[0].bases[i] = 0; } defaultMatch.nameUid = NULL; defaultMatch.child.valueUid = NULL; defaultMatch.priority = -1; defaultMatch.flags = 0; } /* * Then, per-main-window initialization. Create and delete dummy * interpreter for message logging. */ mainPtr->optionRootPtr = NewArray(20); interp = Tcl_CreateInterp(); (void) GetDefaultOptions(interp, mainPtr->winPtr); Tcl_DeleteInterp(interp);}/* *-------------------------------------------------------------- * * ClearOptionTree -- * * This procedure is called to erase everything in a * hierarchical option database. * * Results: * None. * * Side effects: * All the options associated with arrayPtr are deleted, * along with all option subtrees. The space pointed to * by arrayPtr is freed. * *-------------------------------------------------------------- */static voidClearOptionTree(arrayPtr) ElArray *arrayPtr; /* Array of options; delete everything * referred to recursively by this. */{ register Element *elPtr; int count; for (count = arrayPtr->numUsed, elPtr = arrayPtr->els; count > 0; count--, elPtr++) { if (elPtr->flags & NODE) { ClearOptionTree(elPtr->child.arrayPtr); } } ckfree((char *) arrayPtr);}/* *-------------------------------------------------------------- * * GetDefaultOptions -- * * This procedure is invoked to load the default set of options * for a window. * * Results: * None. * * Side effects: * Options are added to those for winPtr's main window. If * there exists a RESOURCE_MANAGER proprety for winPtr's * display, that is used. Otherwise, the .Xdefaults file in * the user's home directory is used. * *-------------------------------------------------------------- */static intGetDefaultOptions(interp, winPtr) Tcl_Interp *interp; /* Interpreter to use for error reporting. */ TkWindow *winPtr; /* Fetch option defaults for main window * associated with this. */{ char *regProp; int result, actualFormat; unsigned long numItems, bytesAfter; Atom actualType; /* * Try the RESOURCE_MANAGER property on the root window first. */ regProp = NULL; result = XGetWindowProperty(winPtr->display, RootWindow(winPtr->display, 0), XA_RESOURCE_MANAGER, 0, 100000, False, XA_STRING, &actualType, &actualFormat, &numItems, &bytesAfter, (unsigned char **) ®Prop); if ((result == Success) && (actualType == XA_STRING) && (actualFormat == 8)) { result = AddFromString(interp, (Tk_Window) winPtr, regProp, TK_USER_DEFAULT_PRIO); XFree(regProp); return result; } /* * No luck there. Try a .Xdefaults file in the user's home * directory. */ if (regProp != NULL) { XFree(regProp); } result = ReadOptionFile(interp, (Tk_Window) winPtr, "~/.Xdefaults", TK_USER_DEFAULT_PRIO); return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -