⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tkoption.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  * tkOption.c -- * *	This module contains procedures to manage the option *	database, which allows various strings to be associated *	with windows either by name or by class or both. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1996 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tkOption.c 1.57 96/10/17 15:16:45 */#include "tkPort.h"#include "tkInt.h"/* * The option database is stored as one tree for each main window. * Each name or class field in an option is associated with a node or * leaf of the tree.  For example, the options "x.y.z" and "x.y*a" * each correspond to three nodes in the tree;  they share the nodes * "x" and "x.y", but have different leaf nodes.  One of the following * structures exists for each node or leaf in the option tree.  It is * actually stored as part of the parent node, and describes a particular * child of the parent. */typedef struct Element {    Tk_Uid nameUid;			/* Name or class from one element of					 * an option spec. */    union {	struct ElArray *arrayPtr;	/* If this is an intermediate node,					 * a pointer to a structure describing					 * the remaining elements of all					 * options whose prefixes are the					 * same up through this element. */	Tk_Uid valueUid;		/* For leaf nodes, this is the string					 * value of the option. */    } child;    int priority;			/* Used to select among matching					 * options.  Includes both the					 * priority level and a serial #.					 * Greater value means higher					 * priority.  Irrelevant except in					 * leaf nodes. */    int flags;				/* OR-ed combination of bits.  See					 * below for values. */} Element;/* * Flags in Element structures: * * CLASS -		Non-zero means this element refers to a class, *			Zero means this element refers to a name. * NODE -		Zero means this is a leaf element (the child *			field is a value, not a pointer to another node). *			One means this is a node element. * WILDCARD -		Non-zero means this there was a star in the *			original specification just before this element. *			Zero means there was a dot. */#define TYPE_MASK		0x7#define CLASS			0x1#define NODE			0x2#define WILDCARD		0x4#define EXACT_LEAF_NAME		0x0#define EXACT_LEAF_CLASS	0x1#define EXACT_NODE_NAME		0x2#define EXACT_NODE_CLASS	0x3#define WILDCARD_LEAF_NAME	0x4#define WILDCARD_LEAF_CLASS	0x5#define WILDCARD_NODE_NAME	0x6#define WILDCARD_NODE_CLASS	0x7/* * The following structure is used to manage a dynamic array of * Elements.  These structures are used for two purposes:  to store * the contents of a node in the option tree, and for the option * stacks described below. */typedef struct ElArray {    int arraySize;		/* Number of elements actually				 * allocated in the "els" array. */    int numUsed;		/* Number of elements currently in				 * use out of els. */    Element *nextToUse;		/* Pointer to &els[numUsed]. */    Element els[1];		/* Array of structures describing				 * children of this node.  The				 * array will actually contain enough				 * elements for all of the children				 * (and even a few extras, perhaps).				 * This must be the last field in				 * the structure. */} ElArray;#define EL_ARRAY_SIZE(numEls) ((unsigned) (sizeof(ElArray) \	+ ((numEls)-1)*sizeof(Element)))#define INITIAL_SIZE 5/* * In addition to the option tree, which is a relatively static structure, * there are eight additional structures called "stacks", which are used * to speed up queries into the option database.  The stack structures * are designed for the situation where an individual widget makes repeated * requests for its particular options.  The requests differ only in * their last name/class, so during the first request we extract all * the options pertaining to the particular widget and save them in a * stack-like cache;  subsequent requests for the same widget can search * the cache relatively quickly.  In fact, the cache is a hierarchical * one, storing a list of relevant options for this widget and all of * its ancestors up to the application root;  hence the name "stack". * * Each of the eight stacks consists of an array of Elements, ordered in * terms of levels in the window hierarchy.  All the elements relevant * for the top-level widget appear first in the array, followed by all * those from the next-level widget on the path to the current widget, * etc. down to those for the current widget. * * Cached information is divided into eight stacks according to the * CLASS, NODE, and WILDCARD flags.  Leaf and non-leaf information is * kept separate to speed up individual probes (non-leaf information is * only relevant when building the stacks, but isn't relevant when * making probes;  similarly, only non-leaf information is relevant * when the stacks are being extended to the next widget down in the * widget hierarchy).  Wildcard elements are handled separately from * "exact" elements because once they appear at a particular level in * the stack they remain active for all deeper levels;  exact elements * are only relevant at a particular level.  For example, when searching * for options relevant in a particular window, the entire wildcard * stacks get checked, but only the portions of the exact stacks that * pertain to the window's parent.  Lastly, name and class stacks are * kept separate because different search keys are used when searching * them;  keeping them separate speeds up the searches. */#define NUM_STACKS 8static ElArray *stacks[NUM_STACKS];static TkWindow *cachedWindow = NULL;	/* Lowest-level window currently					 * loaded in stacks at present. 					 * NULL means stacks have never					 * been used, or have been					 * invalidated because of a change					 * to the database. *//* * One of the following structures is used to keep track of each * level in the stacks. */typedef struct StackLevel {    TkWindow *winPtr;		/* Window corresponding to this stack				 * level. */    int bases[NUM_STACKS];	/* For each stack, index of first				 * element on stack corresponding to				 * this level (used to restore "numUsed"				 * fields when popping out of a level. */} StackLevel;/* * Information about all of the stack levels that are currently * active.  This array grows dynamically to become as large as needed. */static StackLevel *levels = NULL;				/* Array describing current stack. */static int numLevels = 0;	/* Total space allocated. */static int curLevel = -1;	/* Highest level currently in use.  Note:				 * curLevel is never 0!  (I don't remember				 * why anymore...) *//* * The variable below is a serial number for all options entered into * the database so far.  It increments on each addition to the option * database.  It is used in computing option priorities, so that the * most recent entry wins when choosing between options at the same * priority level. */static int serial = 0;/* * Special "no match" Element to use as default for searches. */static Element defaultMatch;/* * Forward declarations for procedures defined in this file: */static int		AddFromString _ANSI_ARGS_((Tcl_Interp *interp,			    Tk_Window tkwin, char *string, int priority));static void		ClearOptionTree _ANSI_ARGS_((ElArray *arrayPtr));static ElArray *	ExtendArray _ANSI_ARGS_((ElArray *arrayPtr,			    Element *elPtr));static void		ExtendStacks _ANSI_ARGS_((ElArray *arrayPtr,			    int leaf));static int		GetDefaultOptions _ANSI_ARGS_((Tcl_Interp *interp,			    TkWindow *winPtr));	static ElArray *	NewArray _ANSI_ARGS_((int numEls));	static void		OptionInit _ANSI_ARGS_((TkMainInfo *mainPtr));static int		ParsePriority _ANSI_ARGS_((Tcl_Interp *interp,			    char *string));static int		ReadOptionFile _ANSI_ARGS_((Tcl_Interp *interp,			    Tk_Window tkwin, char *fileName, int priority));static void		SetupStacks _ANSI_ARGS_((TkWindow *winPtr, int leaf));/* *-------------------------------------------------------------- * * Tk_AddOption -- * *	Add a new option to the option database. * * Results: *	None. * * Side effects: *	Information is added to the option database. * *-------------------------------------------------------------- */voidTk_AddOption(tkwin, name, value, priority)    Tk_Window tkwin;		/* Window token;  option will be associated				 * with main window for this window. */    char *name;			/* Multi-element name of option. */    char *value;		/* String value for option. */    int priority;		/* Overall priority level to use for				 * this option, such as TK_USER_DEFAULT_PRIO				 * or TK_INTERACTIVE_PRIO.  Must be between				 * 0 and TK_MAX_PRIO. */{    TkWindow *winPtr = ((TkWindow *) tkwin)->mainPtr->winPtr;    register ElArray **arrayPtrPtr;    register Element *elPtr;    Element newEl;    register char *p;    char *field;    int count, firstField, length;#define TMP_SIZE 100    char tmp[TMP_SIZE+1];    if (winPtr->mainPtr->optionRootPtr == NULL) {	OptionInit(winPtr->mainPtr);    }    cachedWindow = NULL;	/* Invalidate the cache. */    /*     * Compute the priority for the new element, including both the     * overall level and the serial number (to disambiguate with the     * level).     */    if (priority < 0) {	priority = 0;    } else if (priority > TK_MAX_PRIO) {	priority = TK_MAX_PRIO;    }    newEl.priority = (priority << 24) + serial;    serial++;    /*     * Parse the option one field at a time.     */    arrayPtrPtr = &(((TkWindow *) tkwin)->mainPtr->optionRootPtr);    p = name;    for (firstField = 1; ; firstField = 0) {	/*	 * Scan the next field from the name and convert it to a Tk_Uid.	 * Must copy the field before calling Tk_Uid, so that a terminating	 * NULL may be added without modifying the source string.	 */	if (*p == '*') {	    newEl.flags = WILDCARD;	    p++;	} else {	    newEl.flags = 0;	}	field = p;	while ((*p != 0) && (*p != '.') && (*p != '*')) {	    p++;	}	length = p - field;	if (length > TMP_SIZE) {	    length = TMP_SIZE;	}	strncpy(tmp, field, (size_t) length);	tmp[length] = 0;	newEl.nameUid = Tk_GetUid(tmp);	if (isupper(UCHAR(*field))) {	    newEl.flags |= CLASS;	}	if (*p != 0) {	    /*	     * New element will be a node.  If this option can't possibly	     * apply to this main window, then just skip it.  Otherwise,	     * add it to the parent, if it isn't already there, and descend	     * into it.	     */	    newEl.flags |= NODE;	    if (firstField && !(newEl.flags & WILDCARD)		    && (newEl.nameUid != winPtr->nameUid)		    && (newEl.nameUid != winPtr->classUid)) {		return;	    }	    for (elPtr = (*arrayPtrPtr)->els, count = (*arrayPtrPtr)->numUsed;		    ; elPtr++, count--) {		if (count == 0) {		    newEl.child.arrayPtr = NewArray(5);		    *arrayPtrPtr = ExtendArray(*arrayPtrPtr, &newEl);		    arrayPtrPtr = &((*arrayPtrPtr)->nextToUse[-1].child.arrayPtr);		    break;		}		if ((elPtr->nameUid == newEl.nameUid)			&& (elPtr->flags == newEl.flags)) {		    arrayPtrPtr = &(elPtr->child.arrayPtr);		    break;		}	    }	    if (*p == '.') {		p++;	    }	} else {	    /*	     * New element is a leaf.  Add it to the parent, if it isn't	     * already there.  If it exists already, keep whichever value	     * has highest priority.	     */	    newEl.child.valueUid = Tk_GetUid(value);	    for (elPtr = (*arrayPtrPtr)->els, count = (*arrayPtrPtr)->numUsed;		    ; elPtr++, count--) {		if (count == 0) {		    *arrayPtrPtr = ExtendArray(*arrayPtrPtr, &newEl);		    return;		}		if ((elPtr->nameUid == newEl.nameUid)			&& (elPtr->flags == newEl.flags)) {		    if (elPtr->priority < newEl.priority) {			elPtr->priority = newEl.priority;			elPtr->child.valueUid = newEl.child.valueUid;		    }		    return;		}	    }	}    }}/* *-------------------------------------------------------------- * * Tk_GetOption -- * *	Retrieve an option from the option database. * * Results: *	The return value is the value specified in the option *	database for the given name and class on the given *	window.  If there is nothing specified in the database *	for that option, then NULL is returned. * * Side effects: *	The internal caches used to speed up option mapping *	may be modified, if this tkwin is different from the *	last tkwin used for option retrieval. * *-------------------------------------------------------------- */Tk_UidTk_GetOption(tkwin, name, className)    Tk_Window tkwin;		/* Token for window that option is				 * associated with. */    char *name;			/* Name of option. */    char *className;		/* Class of option.  NULL means there				 * is no class for this option:  just				 * check for name. */{    Tk_Uid nameId, classId;    register Element *elPtr, *bestPtr;    register int count;    /*     * Note:  no need to call OptionInit here:  it will be done by     * the SetupStacks call below (squeeze out those nanoseconds).     */    if (tkwin != (Tk_Window) cachedWindow) {	SetupStacks((TkWindow *) tkwin, 1);    }    nameId = Tk_GetUid(name);    bestPtr = &defaultMatch;    for (elPtr = stacks[EXACT_LEAF_NAME]->els,	    count = stacks[EXACT_LEAF_NAME]->numUsed; count > 0;	    elPtr++, count--) {	if ((elPtr->nameUid == nameId)		&& (elPtr->priority > bestPtr->priority)) {	    bestPtr = elPtr;	}    }    for (elPtr = stacks[WILDCARD_LEAF_NAME]->els,	    count = stacks[WILDCARD_LEAF_NAME]->numUsed; count > 0;	    elPtr++, count--) {	if ((elPtr->nameUid == nameId)		&& (elPtr->priority > bestPtr->priority)) {	    bestPtr = elPtr;	}    }    if (className != NULL) {	classId = Tk_GetUid(className);	for (elPtr = stacks[EXACT_LEAF_CLASS]->els,		count = stacks[EXACT_LEAF_CLASS]->numUsed; count > 0;		elPtr++, count--) {	    if ((elPtr->nameUid == classId)		    && (elPtr->priority > bestPtr->priority)) {		bestPtr = elPtr;	    }	}	for (elPtr = stacks[WILDCARD_LEAF_CLASS]->els,		count = stacks[WILDCARD_LEAF_CLASS]->numUsed; count > 0;		elPtr++, count--) {	    if ((elPtr->nameUid == classId)		    && (elPtr->priority > bestPtr->priority)) {		bestPtr = elPtr;	    }	}    }    return bestPtr->child.valueUid;}/* *-------------------------------------------------------------- * * Tk_OptionCmd -- * *	This procedure is invoked to process the "option" Tcl command. *	See the user documentation for details on what it does. * * Results: *	A standard Tcl result. * * Side effects: *	See the user documentation. * *-------------------------------------------------------------- */int

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -