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

📄 tkbind.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 5 页
字号:
     *    we save it in a dynamic string.     * 2. The binding's action can potentially delete the binding,     *    so bindPtr may not point to anything valid once the action     *    completes.  Thus we have to save bindPtr->interp in a     *    local variable in order to restore the result.     */    interp = bindPtr->interp;    Tcl_DStringInit(&savedResult);    /*     * Save information about the current screen, then invoke a script     * if the screen has changed.     */    Tcl_DStringGetResult(interp, &savedResult);    screenPtr = &bindInfoPtr->screenInfo;    oldDispPtr = screenPtr->curDispPtr;    oldScreen = screenPtr->curScreenIndex;    if ((dispPtr != screenPtr->curDispPtr)	    || (Tk_ScreenNumber(tkwin) != screenPtr->curScreenIndex)) {	screenPtr->curDispPtr = dispPtr;	screenPtr->curScreenIndex = Tk_ScreenNumber(tkwin);	ChangeScreen(interp, dispPtr->name, screenPtr->curScreenIndex);    }    if (matchCount > 0) {	pendingPtr->nextPtr = bindInfoPtr->pendingList;	pendingPtr->tkwin = tkwin;	pendingPtr->deleted = 0;	bindInfoPtr->pendingList = pendingPtr;    }        /*     * Save the current value of the TK_DEFER_MODAL flag so we can     * restore it at the end of the loop.  Clear the flag so we can     * detect any recursive requests for a modal loop.     */    flags = winPtr->flags;    winPtr->flags &= ~TK_DEFER_MODAL;    p = Tcl_DStringValue(&scripts);    end = p + Tcl_DStringLength(&scripts);    i = 0;    while (p < end) {	int code;		screenPtr->bindingDepth++;	Tcl_AllowExceptions(interp);	if (*p == '\0') {	    PatSeq *psPtr;	    	    psPtr = pendingPtr->matchArray[i];	    i++;	    code = TCL_OK;	    if ((pendingPtr->deleted == 0)		    && ((psPtr->flags & MARKED_DELETED) == 0)) {		code = (*psPtr->eventProc)(psPtr->clientData, interp, eventPtr,			tkwin, detail.keySym);	    }	    psPtr->refCount--;	    if ((psPtr->refCount == 0) && (psPtr->flags & MARKED_DELETED)) {		if (psPtr->freeProc != NULL) {		    (*psPtr->freeProc)(psPtr->clientData);		}		ckfree((char *) psPtr);	    }	} else {	    code = Tcl_GlobalEval(interp, p);	    p += strlen(p);	}	p++;	screenPtr->bindingDepth--;	if (code != TCL_OK) {	    if (code == TCL_CONTINUE) {		/*		 * Do nothing:  just go on to the next command.		 */	    } else if (code == TCL_BREAK) {		break;	    } else {		Tcl_AddErrorInfo(interp, "\n    (command bound to event)");		Tcl_BackgroundError(interp);		break;	    }	}    }    if (matchCount > 0 && !pendingPtr->deleted) {	/*	 * Restore the original modal flag value and invoke the modal loop	 * if needed.	 */	deferModal = winPtr->flags & TK_DEFER_MODAL;	winPtr->flags = (winPtr->flags & (unsigned int) ~TK_DEFER_MODAL) 	    | (flags & TK_DEFER_MODAL);	if (deferModal) {	    (*winPtr->classProcsPtr->modalProc)(tkwin, eventPtr);	}    }    if ((screenPtr->bindingDepth != 0) &&            ((oldDispPtr != screenPtr->curDispPtr)                    || (oldScreen != screenPtr->curScreenIndex))) {	/*	 * Some other binding script is currently executing, but its	 * screen is no longer current.  Change the current display	 * back again.	 */	screenPtr->curDispPtr = oldDispPtr;	screenPtr->curScreenIndex = oldScreen;	ChangeScreen(interp, oldDispPtr->name, oldScreen);    }    Tcl_DStringResult(interp, &savedResult);    Tcl_DStringFree(&scripts);    if (matchCount > 0) {	PendingBinding **curPtrPtr;	for (curPtrPtr = &bindInfoPtr->pendingList; ; ) {	    if (*curPtrPtr == pendingPtr) {		*curPtrPtr = pendingPtr->nextPtr;		break;	    }	    curPtrPtr = &(*curPtrPtr)->nextPtr;	}	if (pendingPtr != &staticPending) {	    ckfree((char *) pendingPtr);	}    }}/* *--------------------------------------------------------------------------- * * TkBindDeadWindow -- * *	This procedure is invoked when it is determined that a window is *	dead.  It cleans up bind-related information about the window * * Results: *	None. * * Side effects: *	Any pending C bindings for this window are cancelled. * *--------------------------------------------------------------------------- */ voidTkBindDeadWindow(winPtr)    TkWindow *winPtr;		/* The window that is being deleted. */{    BindInfo *bindInfoPtr;    PendingBinding *curPtr;    bindInfoPtr = (BindInfo *) winPtr->mainPtr->bindInfo;    curPtr = bindInfoPtr->pendingList;    while (curPtr != NULL) {	if (curPtr->tkwin == (Tk_Window) winPtr) {	    curPtr->deleted = 1;	}	curPtr = curPtr->nextPtr;    }}/* *---------------------------------------------------------------------- * * MatchPatterns -- * *      Given a list of pattern sequences and a list of recent events, *      return the pattern sequence that best matches the event list, *	if there is one. * *	This procedure is used in two different ways.  In the simplest *	use, "object" is NULL and psPtr is a list of pattern sequences, *	each of which corresponds to a binding.  In this case, the *	procedure finds the pattern sequences that match the event list *	and returns the most specific of those, if there is more than one. * *	In the second case, psPtr is a list of pattern sequences, each *	of which corresponds to a definition for a virtual binding. *	In order for one of these sequences to "match", it must match *	the events (as above) but in addition there must be a binding *	for its associated virtual event on the current object.  The *	"object" argument indicates which object the binding must be for. * * Results: *      The return value is NULL if bestPtr is NULL and no pattern matches *	the recent events from bindPtr.  Otherwise the return value is *	the most specific pattern sequence among bestPtr and all those *	at psPtr that match the event list and object.  If a pattern *	sequence other than bestPtr is returned, then *bestCommandPtr *	is filled in with a pointer to the command from the best sequence. * * Side effects: *      None. * *---------------------------------------------------------------------- */static PatSeq *MatchPatterns(dispPtr, bindPtr, psPtr, bestPtr, objectPtr, sourcePtrPtr)    TkDisplay *dispPtr;		/* Display from which the event came. */    BindingTable *bindPtr;	/* Information about binding table, such as				 * ring of recent events. */    PatSeq *psPtr;		/* List of pattern sequences. */    PatSeq *bestPtr; 		/* The best match seen so far, from a				 * previous call to this procedure.  NULL				 * means no prior best match. */    ClientData *objectPtr;	/* If NULL, the sequences at psPtr				 * correspond to "normal" bindings.  If				 * non-NULL, the sequences at psPtr correspond				 * to virtual bindings; in order to match each				 * sequence must correspond to a virtual				 * binding for which a binding exists for				 * object in bindPtr. */    PatSeq **sourcePtrPtr;	/* Filled with the pattern sequence that				 * contains the eventProc and clientData				 * associated with the best match.  If this				 * differs from the return value, it is the				 * virtual event that most closely matched the				 * return value (a physical event).  Not				 * modified unless a result other than bestPtr				 * is returned. */{    PatSeq *matchPtr, *bestSourcePtr, *sourcePtr;    bestSourcePtr = *sourcePtrPtr;    /*     * Iterate over all the pattern sequences.     */    for ( ; psPtr != NULL; psPtr = psPtr->nextSeqPtr) {	XEvent *eventPtr;	Pattern *patPtr;	Window window;	Detail *detailPtr;	int patCount, ringCount, flags, state;	int modMask;	/*	 * Iterate over all the patterns in a sequence to be	 * sure that they all match.	 */	eventPtr = &bindPtr->eventRing[bindPtr->curEvent];	detailPtr = &bindPtr->detailRing[bindPtr->curEvent];	window = eventPtr->xany.window;	patPtr = psPtr->pats;	patCount = psPtr->numPats;	ringCount = EVENT_BUFFER_SIZE;	while (patCount > 0) {	    if (ringCount <= 0) {		goto nextSequence;	    }	    if (eventPtr->xany.type != patPtr->eventType) {		/*		 * Most of the event types are considered superfluous		 * in that they are ignored if they occur in the middle		 * of a pattern sequence and have mismatching types.  The		 * only ones that cannot be ignored are ButtonPress and		 * ButtonRelease events (if the next event in the pattern		 * is a KeyPress or KeyRelease) and KeyPress and KeyRelease		 * events (if the next pattern event is a ButtonPress or		 * ButtonRelease).  Here are some tricky cases to consider:		 * 1. Double-Button or Double-Key events.		 * 2. Double-ButtonRelease or Double-KeyRelease events.		 * 3. The arrival of various events like Enter and Leave		 *    and FocusIn and GraphicsExpose between two button		 *    presses or key presses.		 * 4. Modifier keys like Shift and Control shouldn't		 *    generate conflicts with button events.		 */		if ((patPtr->eventType == KeyPress)			|| (patPtr->eventType == KeyRelease)) {		    if ((eventPtr->xany.type == ButtonPress)			    || (eventPtr->xany.type == ButtonRelease)) {			goto nextSequence;		    }		} else if ((patPtr->eventType == ButtonPress)			|| (patPtr->eventType == ButtonRelease)) {		    if ((eventPtr->xany.type == KeyPress)			    || (eventPtr->xany.type == KeyRelease)) {			int i;			/*			 * Ignore key events if they are modifier keys.			 */			for (i = 0; i < dispPtr->numModKeyCodes; i++) {			    if (dispPtr->modKeyCodes[i]				    == eventPtr->xkey.keycode) {				/*				 * This key is a modifier key, so ignore it.				 */				goto nextEvent;			    }			}			goto nextSequence;		    }		}		goto nextEvent;	    }	    if (eventPtr->xany.window != window) {		goto nextSequence;	    }	    /*	     * Note: it's important for the keysym check to go before	     * the modifier check, so we can ignore unwanted modifier	     * keys before choking on the modifier check.	     */	    if ((patPtr->detail.clientData != 0)		    && (patPtr->detail.clientData != detailPtr->clientData)) {		/*		 * The detail appears not to match.  However, if the event		 * is a KeyPress for a modifier key then just ignore the		 * event.  Otherwise event sequences like "aD" never match		 * because the shift key goes down between the "a" and the		 * "D".		 */		if (eventPtr->xany.type == KeyPress) {		    int i;		    for (i = 0; i < dispPtr->numModKeyCodes; i++) {			if (dispPtr->modKeyCodes[i] == eventPtr->xkey.keycode) {			    goto nextEvent;			}		    }		}		goto nextSequence;	    }	    flags = flagArray[eventPtr->type];	    if (flags & (KEY_BUTTON_MOTION_VIRTUAL)) {		state = eventPtr->xkey.state;	    } else if (flags & CROSSING) {		state = eventPtr->xcrossing.state;	    } else {		state = 0;	    }	    if (patPtr->needMods != 0) {		modMask = patPtr->needMods;		if ((modMask & META_MASK) && (dispPtr->metaModMask != 0)) {		    modMask = (modMask & ~META_MASK) | dispPtr->metaModMask;		}		if ((modMask & ALT_MASK) && (dispPtr->altModMask != 0)) {		    modMask = (modMask & ~ALT_MASK) | dispPtr->altModMask;		}		if ((state & modMask) != modMask) {		    goto nextSequence;		}	    }	    if (psPtr->flags & PAT_NEARBY) {		XEvent *firstPtr;		int timeDiff;		firstPtr = &bindPtr->eventRing[bindPtr->curEvent];		timeDiff = (Time) firstPtr->xkey.time - eventPtr->xkey.time;		if ((firstPtr->xkey.x_root			    < (eventPtr->xkey.x_root - NEARBY_PIXELS))			|| (firstPtr->xkey.x_root			    > (eventPtr->xkey.x_root + NEARBY_PIXELS))			|| (firstPtr->xkey.y_root			    < (eventPtr->xkey.y_root - NEARBY_PIXELS))			|| (firstPtr->xkey.y_root			    > (eventPtr->xkey.y_root + NEARBY_PIXELS))			|| (timeDiff > NEARBY_MS)) {		    goto nextSequence;		}	    }	    patPtr++;	    patCount--;	    nextEvent:	    if (eventPtr == bindPtr->eventRing) {		eventPtr = &bindPtr->eventRing[EVENT_BUFFER_SIZE-1];		detailPtr = &bindPtr->detailRing[EVENT_BUFFER_SIZE-1];	    } else {		eventPtr--;		detailPtr--;	    }	    ringCount--;	}	matchPtr = psPtr;	sourcePtr = psPtr;	if (objectPtr != NULL) {	    int iVirt;	    VirtualOwners *voPtr;	    PatternTableKey key;	    /*	     * The sequence matches the physical constraints.	     * Is this object interested in any of the virtual events	     * that correspond to this sequence?  	     */	    voPtr = psPtr->voPtr;	    memset(&key, 0, sizeof(key));	    key.object = *objectPtr;	    key.type = VirtualEvent;	  

⌨️ 快捷键说明

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