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

📄 tkbind.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 5 页
字号:
    Tcl_DString ds;    hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object);    if (hPtr == NULL) {	return;    }    Tcl_DStringInit(&ds);    for (psPtr = (PatSeq *) Tcl_GetHashValue(hPtr); psPtr != NULL;	    psPtr = psPtr->nextObjPtr) {	/* 	 * For each binding, output information about each of the	 * patterns in its sequence.	 */	 	Tcl_DStringSetLength(&ds, 0);	GetPatternString(psPtr, &ds);	Tcl_AppendElement(interp, Tcl_DStringValue(&ds));    }    Tcl_DStringFree(&ds);}/* *-------------------------------------------------------------- * * Tk_DeleteAllBindings -- * *	Remove all bindings associated with a given object in a *	given binding table. * * Results: *	All bindings associated with object are removed from *	bindingTable. * * Side effects: *	None. * *-------------------------------------------------------------- */voidTk_DeleteAllBindings(bindingTable, object)    Tk_BindingTable bindingTable;	/* Table in which to delete					 * bindings. */    ClientData object;			/* Token for object. */{    BindingTable *bindPtr = (BindingTable *) bindingTable;    PatSeq *psPtr, *prevPtr;    PatSeq *nextPtr;    Tcl_HashEntry *hPtr;    hPtr = Tcl_FindHashEntry(&bindPtr->objectTable, (char *) object);    if (hPtr == NULL) {	return;    }    for (psPtr = (PatSeq *) Tcl_GetHashValue(hPtr); psPtr != NULL;	    psPtr = nextPtr) {	nextPtr  = psPtr->nextObjPtr;	/*	 * Be sure to remove each binding from its hash chain in the	 * pattern table.  If this is the last pattern in the chain,	 * then delete the hash entry too.	 */	prevPtr = (PatSeq *) Tcl_GetHashValue(psPtr->hPtr);	if (prevPtr == psPtr) {	    if (psPtr->nextSeqPtr == NULL) {		Tcl_DeleteHashEntry(psPtr->hPtr);	    } else {		Tcl_SetHashValue(psPtr->hPtr, psPtr->nextSeqPtr);	    }	} else {	    for ( ; ; prevPtr = prevPtr->nextSeqPtr) {		if (prevPtr == NULL) {		    panic("Tk_DeleteAllBindings couldn't find on hash chain");		}		if (prevPtr->nextSeqPtr == psPtr) {		    prevPtr->nextSeqPtr = psPtr->nextSeqPtr;		    break;		}	    }	}	psPtr->flags |= MARKED_DELETED;	if (psPtr->refCount == 0) {	    if (psPtr->freeProc != NULL) {		(*psPtr->freeProc)(psPtr->clientData);	    }	    ckfree((char *) psPtr);	}    }    Tcl_DeleteHashEntry(hPtr);}/* *--------------------------------------------------------------------------- * * Tk_BindEvent -- * *	This procedure is invoked to process an X event.  The *	event is added to those recorded for the binding table. *	Then each of the objects at *objectPtr is checked in *	order to see if it has a binding that matches the recent *	events.  If so, the most specific binding is invoked for *	each object. * * Results: *	None. * * Side effects: *	Depends on the command associated with the matching binding. * *	All Tcl bindings scripts for each object are accumulated before *	the first binding is evaluated.  If the action of a Tcl binding *	is to change or delete a binding, or delete the window associated *	with the binding, all the original Tcl binding scripts will still *	fire.  Contrast this with C binding procedures.  If a pending C *	binding (one that hasn't fired yet, but is queued to be fired for *	this window) is deleted, it will not be called, and if it is *	changed, then the new binding procedure will be called.  If the *	window itself is deleted, no further C binding procedures will be *	called for this window.  When both Tcl binding scripts and C binding *	procedures are interleaved, the above rules still apply.  * *--------------------------------------------------------------------------- */voidTk_BindEvent(bindingTable, eventPtr, tkwin, numObjects, objectPtr)    Tk_BindingTable bindingTable;	/* Table in which to look for					 * bindings. */    XEvent *eventPtr;			/* What actually happened. */    Tk_Window tkwin;			/* Window on display where event					 * occurred (needed in order to					 * locate display information). */    int numObjects;			/* Number of objects at *objectPtr. */    ClientData *objectPtr;		/* Array of one or more objects					 * to check for a matching binding. */{    BindingTable *bindPtr;    TkDisplay *dispPtr;    BindInfo *bindInfoPtr;    TkDisplay *oldDispPtr;    ScreenInfo *screenPtr;    XEvent *ringPtr;    PatSeq *vMatchDetailList, *vMatchNoDetailList;    int flags, oldScreen, i, deferModal;    unsigned int matchCount, matchSpace;    Tcl_Interp *interp;    Tcl_DString scripts, savedResult;    Detail detail;    char *p, *end;    PendingBinding *pendingPtr;    PendingBinding staticPending;    TkWindow *winPtr = (TkWindow *)tkwin;    PatternTableKey key;    /*     * Ignore events on windows that don't have names: these are windows     * like wrapper windows that shouldn't be visible to the     * application.     */    if (winPtr->pathName == NULL) {	return;    }    /*     * Ignore the event completely if it is an Enter, Leave, FocusIn,     * or FocusOut event with detail NotifyInferior.  The reason for     * ignoring these events is that we don't want transitions between     * a window and its children to visible to bindings on the parent:     * this would cause problems for mega-widgets, since the internal     * structure of a mega-widget isn't supposed to be visible to     * people watching the parent.     */    if ((eventPtr->type == EnterNotify)  || (eventPtr->type == LeaveNotify)) {	if (eventPtr->xcrossing.detail == NotifyInferior) {	    return;	}    }    if ((eventPtr->type == FocusIn)  || (eventPtr->type == FocusOut)) {	if (eventPtr->xfocus.detail == NotifyInferior) {	    return;	}    }    bindPtr = (BindingTable *) bindingTable;    dispPtr = ((TkWindow *) tkwin)->dispPtr;    bindInfoPtr = (BindInfo *) winPtr->mainPtr->bindInfo;    /*     * Add the new event to the ring of saved events for the     * binding table.  Two tricky points:     *     * 1. Combine consecutive MotionNotify events.  Do this by putting     *    the new event *on top* of the previous event.     * 2. If a modifier key is held down, it auto-repeats to generate     *    continuous KeyPress and KeyRelease events.  These can flush     *    the event ring so that valuable information is lost (such     *    as repeated button clicks).  To handle this, check for the     *    special case of a modifier KeyPress arriving when the previous     *    two events are a KeyRelease and KeyPress of the same key.     *    If this happens, mark the most recent event (the KeyRelease)     *    invalid and put the new event on top of the event before that     *    (the KeyPress).     */    if ((eventPtr->type == MotionNotify)	    && (bindPtr->eventRing[bindPtr->curEvent].type == MotionNotify)) {	/*	 * Don't advance the ring pointer.	 */    } else if (eventPtr->type == KeyPress) {	int i;	for (i = 0; ; i++) {	    if (i >= dispPtr->numModKeyCodes) {		goto advanceRingPointer;	    }	    if (dispPtr->modKeyCodes[i] == eventPtr->xkey.keycode) {		break;	    }	}	ringPtr = &bindPtr->eventRing[bindPtr->curEvent];	if ((ringPtr->type != KeyRelease)		|| (ringPtr->xkey.keycode != eventPtr->xkey.keycode)) {	    goto advanceRingPointer;	}	if (bindPtr->curEvent <= 0) {	    i = EVENT_BUFFER_SIZE - 1;	} else {	    i = bindPtr->curEvent - 1;	}	ringPtr = &bindPtr->eventRing[i];	if ((ringPtr->type != KeyPress)		|| (ringPtr->xkey.keycode != eventPtr->xkey.keycode)) {	    goto advanceRingPointer;	}	bindPtr->eventRing[bindPtr->curEvent].type = -1;	bindPtr->curEvent = i;    } else {	advanceRingPointer:	bindPtr->curEvent++;	if (bindPtr->curEvent >= EVENT_BUFFER_SIZE) {	    bindPtr->curEvent = 0;	}    }    ringPtr = &bindPtr->eventRing[bindPtr->curEvent];    memcpy((VOID *) ringPtr, (VOID *) eventPtr, sizeof(XEvent));    detail.clientData = 0;    flags = flagArray[ringPtr->type];    if (flags & KEY) {	detail.keySym = GetKeySym(dispPtr, ringPtr);	if (detail.keySym == NoSymbol) {	    detail.keySym = 0;	}    } else if (flags & BUTTON) {	detail.button = ringPtr->xbutton.button;    } else if (flags & VIRTUAL) {	detail.name = ((XVirtualEvent *) ringPtr)->name;    }    bindPtr->detailRing[bindPtr->curEvent] = detail;    /*     * Find out if there are any virtual events that correspond to this     * physical event (or sequence of physical events).     */    vMatchDetailList = NULL;    vMatchNoDetailList = NULL;    memset(&key, 0, sizeof(key));    if (ringPtr->type != VirtualEvent) {	Tcl_HashTable *veptPtr;	Tcl_HashEntry *hPtr;	veptPtr = &bindInfoPtr->virtualEventTable.patternTable;        key.object  = NULL;	key.type    = ringPtr->type;	key.detail  = detail;	hPtr = Tcl_FindHashEntry(veptPtr, (char *) &key);	if (hPtr != NULL) {	    vMatchDetailList = (PatSeq *) Tcl_GetHashValue(hPtr);	}	if (key.detail.clientData != 0) {	    key.detail.clientData = 0;	    hPtr = Tcl_FindHashEntry(veptPtr, (char *) &key);	    if (hPtr != NULL) {	        vMatchNoDetailList = (PatSeq *) Tcl_GetHashValue(hPtr);	    }	}    }    /*     * Loop over all the binding tags, finding the binding script or     * callback for each one.  Append all of the binding scripts, with     * %-sequences expanded, to "scripts", with null characters separating     * the scripts for each object.  Append all the callbacks to the array     * of pending callbacks.       */	           pendingPtr = &staticPending;    matchCount = 0;    matchSpace = sizeof(staticPending.matchArray) / sizeof(PatSeq *);    Tcl_DStringInit(&scripts);    for ( ; numObjects > 0; numObjects--, objectPtr++) {	PatSeq *matchPtr, *sourcePtr;	Tcl_HashEntry *hPtr;	matchPtr = NULL;	sourcePtr = NULL;	/*	 * Match the new event against those recorded in the pattern table,	 * saving the longest matching pattern.  For events with details	 * (button and key events), look for a binding for the specific	 * key or button.  First see if the event matches a physical event	 * that the object is interested in, then look for a virtual event.	 */	key.object = *objectPtr;	key.type = ringPtr->type;	key.detail = detail;	hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &key);	if (hPtr != NULL) {	    matchPtr = MatchPatterns(dispPtr, bindPtr, 		    (PatSeq *) Tcl_GetHashValue(hPtr), matchPtr, NULL,		    &sourcePtr);	}	if (vMatchDetailList != NULL) {	    matchPtr = MatchPatterns(dispPtr, bindPtr, vMatchDetailList,		    matchPtr, objectPtr, &sourcePtr);	}	/*	 * If no match was found, look for a binding for all keys or buttons	 * (detail of 0).  Again, first match on a virtual event.	 */	if ((detail.clientData != 0) && (matchPtr == NULL)) {	    key.detail.clientData = 0;	    hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &key);	    if (hPtr != NULL) {		matchPtr = MatchPatterns(dispPtr, bindPtr,			(PatSeq *) Tcl_GetHashValue(hPtr), matchPtr, NULL,			&sourcePtr);	    }	    if (vMatchNoDetailList != NULL) {	        matchPtr = MatchPatterns(dispPtr, bindPtr, vMatchNoDetailList,			matchPtr, objectPtr, &sourcePtr);	    }	}    	if (matchPtr != NULL) {	    if (sourcePtr->eventProc == NULL) {		panic("Tk_BindEvent: missing command");	    }	    if (sourcePtr->eventProc == EvalTclBinding) {		ExpandPercents(winPtr, (char *) sourcePtr->clientData,			eventPtr, detail.keySym, &scripts);	    } else {		if (matchCount >= matchSpace) {		    PendingBinding *new;		    unsigned int oldSize, newSize;		    		    oldSize = sizeof(staticPending)			- sizeof(staticPending.matchArray)			+ matchSpace * sizeof(PatSeq*);		    matchSpace *= 2;		    newSize = sizeof(staticPending)			- sizeof(staticPending.matchArray)			+ matchSpace * sizeof(PatSeq*);		    new = (PendingBinding *) ckalloc(newSize);		    memcpy((VOID *) new, (VOID *) pendingPtr, oldSize);		    if (pendingPtr != &staticPending) {			ckfree((char *) pendingPtr);		    }		    pendingPtr = new;		}		sourcePtr->refCount++;		pendingPtr->matchArray[matchCount] = sourcePtr;		matchCount++;	    }	    /*	     * A "" is added to the scripts string to separate the	     * various scripts that should be invoked.	     */	    Tcl_DStringAppend(&scripts, "", 1);	}    }    if (Tcl_DStringLength(&scripts) == 0) {	return;    }    /*     * Now go back through and evaluate the binding for each object,     * in order, dealing with "break" and "continue" exceptions     * appropriately.     *     * There are two tricks here:     * 1. Bindings can be invoked from in the middle of Tcl commands,     *    where interp->result is significant (for example, a widget     *    might be deleted because of an error in creating it, so the     *    result contains an error message that is eventually going to     *    be returned by the creating command).  To preserve the result,

⌨️ 快捷键说明

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