📄 tclnotify.c
字号:
if ((proc != NULL) && (*proc)(evPtr, flags)) { if (notifier.firstEventPtr == evPtr) { notifier.firstEventPtr = evPtr->nextPtr; if (evPtr->nextPtr == NULL) { notifier.lastEventPtr = NULL; } if (notifier.markerEventPtr == evPtr) { notifier.markerEventPtr = NULL; } } else { for (prevPtr = notifier.firstEventPtr; prevPtr->nextPtr != evPtr; prevPtr = prevPtr->nextPtr) { /* Empty loop body. */ } prevPtr->nextPtr = evPtr->nextPtr; if (evPtr->nextPtr == NULL) { notifier.lastEventPtr = prevPtr; } if (notifier.markerEventPtr == evPtr) { notifier.markerEventPtr = prevPtr; } } ckfree((char *) evPtr); return 1; } else { /* * The event wasn't actually handled, so we have to restore * the proc field to allow the event to be attempted again. */ evPtr->proc = proc; } /* * The handler for this event asked to defer it. Just go on to * the next event. */ continue; } return 0;}/* *---------------------------------------------------------------------- * * Tcl_GetServiceMode -- * * This routine returns the current service mode of the notifier. * * Results: * Returns either TCL_SERVICE_ALL or TCL_SERVICE_NONE. * * Side effects: * None. * *---------------------------------------------------------------------- */intTcl_GetServiceMode(){ if (!initialized) { InitNotifier(); } return notifier.serviceMode;}/* *---------------------------------------------------------------------- * * Tcl_SetServiceMode -- * * This routine sets the current service mode of the notifier. * * Results: * Returns the previous service mode. * * Side effects: * None. * *---------------------------------------------------------------------- */intTcl_SetServiceMode(mode) int mode; /* New service mode: TCL_SERVICE_ALL or * TCL_SERVICE_NONE */{ int oldMode; if (!initialized) { InitNotifier(); } oldMode = notifier.serviceMode; notifier.serviceMode = mode; return oldMode;}/* *---------------------------------------------------------------------- * * Tcl_SetMaxBlockTime -- * * This procedure is invoked by event sources to tell the notifier * how long it may block the next time it blocks. The timePtr * argument gives a maximum time; the actual time may be less if * some other event source requested a smaller time. * * Results: * None. * * Side effects: * May reduce the length of the next sleep in the notifier. * *---------------------------------------------------------------------- */voidTcl_SetMaxBlockTime(timePtr) Tcl_Time *timePtr; /* Specifies a maximum elapsed time for * the next blocking operation in the * event notifier. */{ if (!initialized) { InitNotifier(); } if (!notifier.blockTimeSet || (timePtr->sec < notifier.blockTime.sec) || ((timePtr->sec == notifier.blockTime.sec) && (timePtr->usec < notifier.blockTime.usec))) { notifier.blockTime = *timePtr; notifier.blockTimeSet = 1; } /* * If we are called outside an event source traversal, set the * timeout immediately. */ if (!notifier.inTraversal) { if (notifier.blockTimeSet) { Tcl_SetTimer(¬ifier.blockTime); } else { Tcl_SetTimer(NULL); } }}/* *---------------------------------------------------------------------- * * Tcl_DoOneEvent -- * * Process a single event of some sort. If there's no work to * do, wait for an event to occur, then process it. * * Results: * The return value is 1 if the procedure actually found an event * to process. If no processing occurred, then 0 is returned (this * can happen if the TCL_DONT_WAIT flag is set or if there are no * event handlers to wait for in the set specified by flags). * * Side effects: * May delay execution of process while waiting for an event, * unless TCL_DONT_WAIT is set in the flags argument. Event * sources are invoked to check for and queue events. Event * handlers may produce arbitrary side effects. * *---------------------------------------------------------------------- */intTcl_DoOneEvent(flags) int flags; /* Miscellaneous flag values: may be any * combination of TCL_DONT_WAIT, * TCL_WINDOW_EVENTS, TCL_FILE_EVENTS, * TCL_TIMER_EVENTS, TCL_IDLE_EVENTS, or * others defined by event sources. */{ int result = 0, oldMode; EventSource *sourcePtr; Tcl_Time *timePtr; if (!initialized) { InitNotifier(); } /* * The first thing we do is to service any asynchronous event * handlers. */ if (Tcl_AsyncReady()) { (void) Tcl_AsyncInvoke((Tcl_Interp *) NULL, 0); return 1; } /* * No event flags is equivalent to TCL_ALL_EVENTS. */ if ((flags & TCL_ALL_EVENTS) == 0) { flags |= TCL_ALL_EVENTS; } /* * Set the service mode to none so notifier event routines won't * try to service events recursively. */ oldMode = notifier.serviceMode; notifier.serviceMode = TCL_SERVICE_NONE; /* * The core of this procedure is an infinite loop, even though * we only service one event. The reason for this is that we * may be processing events that don't do anything inside of Tcl. */ while (1) { /* * If idle events are the only things to service, skip the * main part of the loop and go directly to handle idle * events (i.e. don't wait even if TCL_DONT_WAIT isn't set). */ if ((flags & TCL_ALL_EVENTS) == TCL_IDLE_EVENTS) { flags = TCL_IDLE_EVENTS|TCL_DONT_WAIT; goto idleEvents; } /* * Ask Tcl to service a queued event, if there are any. */ if (Tcl_ServiceEvent(flags)) { result = 1; break; } /* * If TCL_DONT_WAIT is set, be sure to poll rather than * blocking, otherwise reset the block time to infinity. */ if (flags & TCL_DONT_WAIT) { notifier.blockTime.sec = 0; notifier.blockTime.usec = 0; notifier.blockTimeSet = 1; } else { notifier.blockTimeSet = 0; } /* * Set up all the event sources for new events. This will * cause the block time to be updated if necessary. */ notifier.inTraversal = 1; for (sourcePtr = notifier.firstEventSourcePtr; sourcePtr != NULL; sourcePtr = sourcePtr->nextPtr) { if (sourcePtr->setupProc) { (sourcePtr->setupProc)(sourcePtr->clientData, flags); } } notifier.inTraversal = 0; if ((flags & TCL_DONT_WAIT) || notifier.blockTimeSet) { timePtr = ¬ifier.blockTime; } else { timePtr = NULL; } /* * Wait for a new event or a timeout. If Tcl_WaitForEvent * returns -1, we should abort Tcl_DoOneEvent. */ result = Tcl_WaitForEvent(timePtr); if (result < 0) { result = 0; break; } /* * Check all the event sources for new events. */ for (sourcePtr = notifier.firstEventSourcePtr; sourcePtr != NULL; sourcePtr = sourcePtr->nextPtr) { if (sourcePtr->checkProc) { (sourcePtr->checkProc)(sourcePtr->clientData, flags); } } /* * Check for events queued by the notifier or event sources. */ if (Tcl_ServiceEvent(flags)) { result = 1; break; } /* * We've tried everything at this point, but nobody we know * about had anything to do. Check for idle events. If none, * either quit or go back to the top and try again. */ idleEvents: if (flags & TCL_IDLE_EVENTS) { if (TclServiceIdle()) { result = 1; break; } } if (flags & TCL_DONT_WAIT) { break; } /* * If Tcl_WaitForEvent has returned 1, * indicating that one system event has been dispatched * (and thus that some Tcl code might have been indirectly executed), * we break out of the loop. * We do this to give VwaitCmd for instance a chance to check * if that system event had the side effect of changing the * variable (so the vwait can return and unwind properly). * * NB: We will process idle events if any first, because * otherwise we might never do the idle events if the notifier * always gets system events. */ if (result) { break; } } notifier.serviceMode = oldMode; return result;}/* *---------------------------------------------------------------------- * * Tcl_ServiceAll -- * * This routine checks all of the event sources, processes * events that are on the Tcl event queue, and then calls the * any idle handlers. Platform specific notifier callbacks that * generate events should call this routine before returning to * the system in order to ensure that Tcl gets a chance to * process the new events. * * Results: * Returns 1 if an event or idle handler was invoked, else 0. * * Side effects: * Anything that an event or idle handler may do. * *---------------------------------------------------------------------- */intTcl_ServiceAll(){ int result = 0; EventSource *sourcePtr; if (!initialized) { InitNotifier(); } if (notifier.serviceMode == TCL_SERVICE_NONE) { return result; } /* * We need to turn off event servicing like we to in Tcl_DoOneEvent, * to avoid recursive calls. */ notifier.serviceMode = TCL_SERVICE_NONE; /* * Check async handlers first. */ if (Tcl_AsyncReady()) { (void) Tcl_AsyncInvoke((Tcl_Interp *) NULL, 0); } /* * Make a single pass through all event sources, queued events, * and idle handlers. Note that we wait to update the notifier * timer until the end so we can avoid multiple changes. */ notifier.inTraversal = 1; notifier.blockTimeSet = 0; for (sourcePtr = notifier.firstEventSourcePtr; sourcePtr != NULL; sourcePtr = sourcePtr->nextPtr) { if (sourcePtr->setupProc) { (sourcePtr->setupProc)(sourcePtr->clientData, TCL_ALL_EVENTS); } } for (sourcePtr = notifier.firstEventSourcePtr; sourcePtr != NULL; sourcePtr = sourcePtr->nextPtr) { if (sourcePtr->checkProc) { (sourcePtr->checkProc)(sourcePtr->clientData, TCL_ALL_EVENTS); } } while (Tcl_ServiceEvent(0)) { result = 1; } if (TclServiceIdle()) { result = 1; } if (!notifier.blockTimeSet) { Tcl_SetTimer(NULL); } else { Tcl_SetTimer(¬ifier.blockTime); } notifier.inTraversal = 0; notifier.serviceMode = TCL_SERVICE_ALL; return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -