📄 tclxtnotify.c
字号:
/* * tclXtNotify.c -- * * This file contains the notifier driver implementation for the * Xt intrinsics. * * Copyright (c) 1997 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclXtNotify.c,v 1.4 1999/07/02 06:05:34 welch Exp $ */#include <X11/Intrinsic.h>#include <tclInt.h>/* * This structure is used to keep track of the notifier info for a * a registered file. */typedef struct FileHandler { int fd; int mask; /* Mask of desired events: TCL_READABLE, etc. */ int readyMask; /* Events that have been seen since the last time FileHandlerEventProc was called for this file. */ XtInputId read; /* Xt read callback handle. */ XtInputId write; /* Xt write callback handle. */ XtInputId except; /* Xt exception callback handle. */ Tcl_FileProc *proc; /* Procedure to call, in the style of * Tcl_CreateFileHandler. */ ClientData clientData; /* Argument to pass to proc. */ struct FileHandler *nextPtr;/* Next in list of all files we care about. */} FileHandler;/* * The following structure is what is added to the Tcl event queue when * file handlers are ready to fire. */typedef struct FileHandlerEvent { Tcl_Event header; /* Information that is standard for * all events. */ int fd; /* File descriptor that is ready. Used * to find the FileHandler structure for * the file (can't point directly to the * FileHandler structure because it could * go away while the event is queued). */} FileHandlerEvent;/* * The following static structure contains the state information for the * Xt based implementation of the Tcl notifier. */static struct NotifierState { XtAppContext appContext; /* The context used by the Xt * notifier. Can be set with * TclSetAppContext. */ int appContextCreated; /* Was it created by us? */ XtIntervalId currentTimeout; /* Handle of current timer. */ FileHandler *firstFileHandlerPtr; /* Pointer to head of file handler * list. */} notifier;/* * The following static indicates whether this module has been initialized. */static int initialized = 0;/* * Static routines defined in this file. */static int FileHandlerEventProc _ANSI_ARGS_((Tcl_Event *evPtr, int flags));static void FileProc _ANSI_ARGS_((caddr_t clientData, int *source, XtInputId *id));void InitNotifier _ANSI_ARGS_((void));static void NotifierExitHandler _ANSI_ARGS_(( ClientData clientData));static void TimerProc _ANSI_ARGS_((caddr_t clientData, XtIntervalId *id));static void CreateFileHandler _ANSI_ARGS_((int fd, int mask, Tcl_FileProc * proc, ClientData clientData));static void DeleteFileHandler _ANSI_ARGS_((int fd));static void SetTimer _ANSI_ARGS_((Tcl_Time * timePtr));static int WaitForEvent _ANSI_ARGS_((Tcl_Time * timePtr));/* * Functions defined in this file for use by users of the Xt Notifier: */EXTERN XtAppContext TclSetAppContext _ANSI_ARGS_((XtAppContext ctx));/* *---------------------------------------------------------------------- * * TclSetAppContext -- * * Set the notifier application context. * * Results: * None. * * Side effects: * Sets the application context used by the notifier. Panics if * the context is already set when called. * *---------------------------------------------------------------------- */XtAppContextTclSetAppContext(appContext) XtAppContext appContext;{ if (!initialized) { InitNotifier(); } /* * If we already have a context we check whether we were asked to set a * new context. If so, we panic because we try to prevent switching * contexts by mistake. Otherwise, we return the one we have. */ if (notifier.appContext != NULL) { if (appContext != NULL) { /* * We already have a context. We do not allow switching contexts * after initialization, so we panic. */ panic("TclSetAppContext: multiple application contexts"); } } else { /* * If we get here we have not yet gotten a context, so either create * one or use the one supplied by our caller. */ if (appContext == NULL) { /* * We must create a new context and tell our caller what it is, so * she can use it too. */ notifier.appContext = XtCreateApplicationContext(); notifier.appContextCreated = 1; } else { /* * Otherwise we remember the context that our caller gave us * and use it. */ notifier.appContextCreated = 0; notifier.appContext = appContext; } } return notifier.appContext;}/* *---------------------------------------------------------------------- * * InitNotifier -- * * Initializes the notifier state. * * Results: * None. * * Side effects: * Creates a new exit handler. * *---------------------------------------------------------------------- */voidInitNotifier(){ Tcl_NotifierProcs notifier; /* * Only reinitialize if we are not in exit handling. The notifier * can get reinitialized after its own exit handler has run, because * of exit handlers for the I/O and timer sub-systems (order dependency). */ if (TclInExit()) { return; } notifier.createFileHandlerProc = CreateFileHandler; notifier.deleteFileHandlerProc = DeleteFileHandler; notifier.setTimerProc = SetTimer; notifier.waitForEventProc = WaitForEvent; Tcl_SetNotifier(¬ifier); /* * DO NOT create the application context yet; doing so would prevent * external applications from setting it for us to their own ones. */ initialized = 1; memset(¬ifier, 0, sizeof(notifier)); Tcl_CreateExitHandler(NotifierExitHandler, NULL);}/* *---------------------------------------------------------------------- * * NotifierExitHandler -- * * This function is called to cleanup the notifier state before * Tcl is unloaded. * * Results: * None. * * Side effects: * Destroys the notifier window. * *---------------------------------------------------------------------- */static voidNotifierExitHandler( ClientData clientData) /* Not used. */{ if (notifier.currentTimeout != 0) { XtRemoveTimeOut(notifier.currentTimeout); } for (; notifier.firstFileHandlerPtr != NULL; ) { Tcl_DeleteFileHandler(notifier.firstFileHandlerPtr->fd); } if (notifier.appContextCreated) { XtDestroyApplicationContext(notifier.appContext); notifier.appContextCreated = 0; notifier.appContext = NULL; } initialized = 0;}/* *---------------------------------------------------------------------- * * SetTimer -- * * This procedure sets the current notifier timeout value. * * Results: * None. * * Side effects: * Replaces any previous timer. * *---------------------------------------------------------------------- */static voidSetTimer(timePtr) Tcl_Time *timePtr; /* Timeout value, may be NULL. */{ long timeout; if (!initialized) { InitNotifier(); } TclSetAppContext(NULL); if (notifier.currentTimeout != 0) { XtRemoveTimeOut(notifier.currentTimeout); } if (timePtr) { timeout = timePtr->sec * 1000 + timePtr->usec / 1000; notifier.currentTimeout = XtAppAddTimeOut(notifier.appContext, (unsigned long) timeout, TimerProc, NULL); } else { notifier.currentTimeout = 0; }}/* *---------------------------------------------------------------------- * * TimerProc -- * * This procedure is the XtTimerCallbackProc used to handle * timeouts. * * Results: * None. * * Side effects: * Processes all queued events. * *---------------------------------------------------------------------- */static voidTimerProc(data, id) caddr_t data; /* Not used. */ XtIntervalId *id;{ if (*id != notifier.currentTimeout) { return; } notifier.currentTimeout = 0; Tcl_ServiceAll();}/* *---------------------------------------------------------------------- * * CreateFileHandler -- * * This procedure registers a file handler with the Xt notifier. * * Results: * None. * * Side effects: * Creates a new file handler structure and registers one or more * input procedures with Xt.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -