diff options
Diffstat (limited to 'unix/tclXtNotify.c')
-rw-r--r-- | unix/tclXtNotify.c | 383 |
1 files changed, 192 insertions, 191 deletions
diff --git a/unix/tclXtNotify.c b/unix/tclXtNotify.c index b78ac8c..a5d92d6 100644 --- a/unix/tclXtNotify.c +++ b/unix/tclXtNotify.c @@ -1,29 +1,33 @@ -/* +/* * tclXtNotify.c -- * - * This file contains the notifier driver implementation for the - * Xt intrinsics. + * 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. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ +#ifndef USE_TCL_STUBS +# define USE_TCL_STUBS +#endif #include <X11/Intrinsic.h> -#include <tclInt.h> +#include "tclInt.h" /* - * This structure is used to keep track of the notifier info for a - * a registered file. + * 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. */ + 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. */ @@ -34,33 +38,32 @@ typedef struct FileHandler { } FileHandler; /* - * The following structure is what is added to the Tcl event queue when - * file handlers are ready to fire. + * 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). */ + 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. + * 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. */ + 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; /* @@ -73,26 +76,23 @@ 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)); +static int FileHandlerEventProc(Tcl_Event *evPtr, int flags); +static void FileProc(XtPointer clientData, int *source, + XtInputId *id); +static void NotifierExitHandler(ClientData clientData); +static void TimerProc(XtPointer clientData, XtIntervalId *id); +static void CreateFileHandler(int fd, int mask, + Tcl_FileProc *proc, ClientData clientData); +static void DeleteFileHandler(int fd); +static void SetTimer(const Tcl_Time * timePtr); +static int WaitForEvent(const Tcl_Time * timePtr); /* * Functions defined in this file for use by users of the Xt Notifier: */ -EXTERN XtAppContext TclSetAppContext _ANSI_ARGS_((XtAppContext ctx)); +MODULE_SCOPE void InitNotifier(void); +MODULE_SCOPE XtAppContext TclSetAppContext(XtAppContext ctx); /* *---------------------------------------------------------------------- @@ -105,18 +105,18 @@ EXTERN XtAppContext TclSetAppContext _ANSI_ARGS_((XtAppContext ctx)); * None. * * Side effects: - * Sets the application context used by the notifier. Panics if - * the context is already set when called. + * Sets the application context used by the notifier. Panics if the + * context is already set when called. * *---------------------------------------------------------------------- */ XtAppContext -TclSetAppContext(appContext) - XtAppContext appContext; +TclSetAppContext( + XtAppContext appContext) { if (!initialized) { - InitNotifier(); + InitNotifier(); } /* @@ -124,46 +124,41 @@ TclSetAppContext(appContext) * 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) { + 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"); + * We already have a context. We do not allow switching contexts + * after initialization, so we panic. + */ - } + Tcl_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 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) { - + 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 { + * 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; - } + * Otherwise we remember the context that our caller gave us and + * use it. + */ + + notifier.appContextCreated = 0; + notifier.appContext = appContext; + } } - + return notifier.appContext; } @@ -184,32 +179,37 @@ TclSetAppContext(appContext) */ void -InitNotifier() +InitNotifier(void) { - Tcl_NotifierProcs notifier; + Tcl_NotifierProcs np; + /* - * 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). + * 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; + return; } - notifier.createFileHandlerProc = CreateFileHandler; - notifier.deleteFileHandlerProc = DeleteFileHandler; - notifier.setTimerProc = SetTimer; - notifier.waitForEventProc = WaitForEvent; - Tcl_SetNotifier(¬ifier); + np.createFileHandlerProc = CreateFileHandler; + np.deleteFileHandlerProc = DeleteFileHandler; + np.setTimerProc = SetTimer; + np.waitForEventProc = WaitForEvent; + np.initNotifierProc = Tcl_InitNotifier; + np.finalizeNotifierProc = Tcl_FinalizeNotifier; + np.alertNotifierProc = Tcl_AlertNotifier; + np.serviceModeHookProc = Tcl_ServiceModeHook; + Tcl_SetNotifier(&np); /* * 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)); + memset(&np, 0, sizeof(np)); Tcl_CreateExitHandler(NotifierExitHandler, NULL); } @@ -218,8 +218,8 @@ InitNotifier() * * NotifierExitHandler -- * - * This function is called to cleanup the notifier state before - * Tcl is unloaded. + * This function is called to cleanup the notifier state before Tcl is + * unloaded. * * Results: * None. @@ -235,15 +235,15 @@ NotifierExitHandler( ClientData clientData) /* Not used. */ { if (notifier.currentTimeout != 0) { - XtRemoveTimeOut(notifier.currentTimeout); + XtRemoveTimeOut(notifier.currentTimeout); } for (; notifier.firstFileHandlerPtr != NULL; ) { - Tcl_DeleteFileHandler(notifier.firstFileHandlerPtr->fd); + Tcl_DeleteFileHandler(notifier.firstFileHandlerPtr->fd); } if (notifier.appContextCreated) { - XtDestroyApplicationContext(notifier.appContext); - notifier.appContextCreated = 0; - notifier.appContext = NULL; + XtDestroyApplicationContext(notifier.appContext); + notifier.appContextCreated = 0; + notifier.appContext = NULL; } initialized = 0; } @@ -265,8 +265,8 @@ NotifierExitHandler( */ static void -SetTimer(timePtr) - Tcl_Time *timePtr; /* Timeout value, may be NULL. */ +SetTimer( + const Tcl_Time *timePtr) /* Timeout value, may be NULL. */ { long timeout; @@ -280,9 +280,8 @@ SetTimer(timePtr) } if (timePtr) { timeout = timePtr->sec * 1000 + timePtr->usec / 1000; - notifier.currentTimeout = - XtAppAddTimeOut(notifier.appContext, (unsigned long) timeout, - TimerProc, NULL); + notifier.currentTimeout = XtAppAddTimeOut(notifier.appContext, + (unsigned long) timeout, TimerProc, NULL); } else { notifier.currentTimeout = 0; } @@ -293,22 +292,21 @@ SetTimer(timePtr) * * TimerProc -- * - * This procedure is the XtTimerCallbackProc used to handle - * timeouts. + * This procedure is the XtTimerCallbackProc used to handle timeouts. * * Results: * None. * * Side effects: - * Processes all queued events. + * Processes all queued events. * *---------------------------------------------------------------------- */ static void -TimerProc(data, id) - caddr_t data; /* Not used. */ - XtIntervalId *id; +TimerProc( + XtPointer clientData, /* Not used. */ + XtIntervalId *id) { if (*id != notifier.currentTimeout) { return; @@ -329,22 +327,22 @@ TimerProc(data, id) * None. * * Side effects: - * Creates a new file handler structure and registers one or more - * input procedures with Xt. + * Creates a new file handler structure and registers one or more input + * procedures with Xt. * *---------------------------------------------------------------------- */ static void -CreateFileHandler(fd, mask, proc, clientData) - int fd; /* Handle of stream to watch. */ - int mask; /* OR'ed combination of TCL_READABLE, - * TCL_WRITABLE, and TCL_EXCEPTION: - * indicates conditions under which - * proc should be called. */ - Tcl_FileProc *proc; /* Procedure to call for each - * selected event. */ - ClientData clientData; /* Arbitrary data to pass to proc. */ +CreateFileHandler( + int fd, /* Handle of stream to watch. */ + int mask, /* OR'ed combination of TCL_READABLE, + * TCL_WRITABLE, and TCL_EXCEPTION: indicates + * conditions under which proc should be + * called. */ + Tcl_FileProc *proc, /* Procedure to call for each selected + * event. */ + ClientData clientData) /* Arbitrary data to pass to proc. */ { FileHandler *filePtr; @@ -361,7 +359,7 @@ CreateFileHandler(fd, mask, proc, clientData) } } if (filePtr == NULL) { - filePtr = (FileHandler*) ckalloc(sizeof(FileHandler)); + filePtr = ckalloc(sizeof(FileHandler)); filePtr->fd = fd; filePtr->read = 0; filePtr->write = 0; @@ -380,9 +378,8 @@ CreateFileHandler(fd, mask, proc, clientData) if (mask & TCL_READABLE) { if (!(filePtr->mask & TCL_READABLE)) { - filePtr->read = - XtAppAddInput(notifier.appContext, fd, XtInputReadMask, - FileProc, filePtr); + filePtr->read = XtAppAddInput(notifier.appContext, fd, + INT2PTR(XtInputReadMask), FileProc, filePtr); } } else { if (filePtr->mask & TCL_READABLE) { @@ -391,9 +388,8 @@ CreateFileHandler(fd, mask, proc, clientData) } if (mask & TCL_WRITABLE) { if (!(filePtr->mask & TCL_WRITABLE)) { - filePtr->write = - XtAppAddInput(notifier.appContext, fd, XtInputWriteMask, - FileProc, filePtr); + filePtr->write = XtAppAddInput(notifier.appContext, fd, + INT2PTR(XtInputWriteMask), FileProc, filePtr); } } else { if (filePtr->mask & TCL_WRITABLE) { @@ -402,9 +398,8 @@ CreateFileHandler(fd, mask, proc, clientData) } if (mask & TCL_EXCEPTION) { if (!(filePtr->mask & TCL_EXCEPTION)) { - filePtr->except = - XtAppAddInput(notifier.appContext, fd, XtInputExceptMask, - FileProc, filePtr); + filePtr->except = XtAppAddInput(notifier.appContext, fd, + INT2PTR(XtInputExceptMask), FileProc, filePtr); } } else { if (filePtr->mask & TCL_EXCEPTION) { @@ -419,8 +414,7 @@ CreateFileHandler(fd, mask, proc, clientData) * * DeleteFileHandler -- * - * Cancel a previously-arranged callback arrangement for - * a file. + * Cancel a previously-arranged callback arrangement for a file. * * Results: * None. @@ -432,9 +426,9 @@ CreateFileHandler(fd, mask, proc, clientData) */ static void -DeleteFileHandler(fd) - int fd; /* Stream id for which to remove - * callback procedure. */ +DeleteFileHandler( + int fd) /* Stream id for which to remove callback + * procedure. */ { FileHandler *filePtr, *prevPtr; @@ -445,8 +439,7 @@ DeleteFileHandler(fd) TclSetAppContext(NULL); /* - * Find the entry for the given file (and return if there - * isn't one). + * Find the entry for the given file (and return if there isn't one). */ for (prevPtr = NULL, filePtr = notifier.firstFileHandlerPtr; ; @@ -477,7 +470,7 @@ DeleteFileHandler(fd) if (filePtr->mask & TCL_EXCEPTION) { XtRemoveInput(filePtr->except); } - ckfree((char *) filePtr); + ckfree(filePtr); } /* @@ -492,17 +485,16 @@ DeleteFileHandler(fd) * None. * * Side effects: - * Makes an entry on the Tcl event queue if the event is - * interesting. + * Makes an entry on the Tcl event queue if the event is interesting. * *---------------------------------------------------------------------- */ static void -FileProc(clientData, fd, id) - caddr_t clientData; - int *fd; - XtInputId *id; +FileProc( + XtPointer clientData, + int *fd, + XtInputId *id) { FileHandler *filePtr = (FileHandler *)clientData; FileHandlerEvent *fileEvPtr; @@ -527,13 +519,13 @@ FileProc(clientData, fd, id) if (!(filePtr->mask & mask) || (filePtr->readyMask & mask)) { return; } - + /* * This is an interesting event, so put it onto the event queue. */ filePtr->readyMask |= mask; - fileEvPtr = (FileHandlerEvent *) ckalloc(sizeof(FileHandlerEvent)); + fileEvPtr = ckalloc(sizeof(FileHandlerEvent)); fileEvPtr->header.proc = FileHandlerEventProc; fileEvPtr->fd = filePtr->fd; Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); @@ -550,16 +542,16 @@ FileProc(clientData, fd, id) * * FileHandlerEventProc -- * - * This procedure is called by Tcl_ServiceEvent when a file event - * reaches the front of the event queue. This procedure is - * responsible for actually handling the event by invoking the - * callback for the file handler. + * This procedure is called by Tcl_ServiceEvent when a file event reaches + * the front of the event queue. This procedure is responsible for + * actually handling the event by invoking the callback for the file + * handler. * * Results: - * Returns 1 if the event was handled, meaning it should be removed - * from the queue. Returns 0 if the event was not handled, meaning - * it should stay on the queue. The only time the event isn't - * handled is if the TCL_FILE_EVENTS flag bit isn't set. + * Returns 1 if the event was handled, meaning it should be removed from + * the queue. Returns 0 if the event was not handled, meaning it should + * stay on the queue. The only time the event isn't handled is if the + * TCL_FILE_EVENTS flag bit isn't set. * * Side effects: * Whatever the file handler's callback procedure does. @@ -568,10 +560,10 @@ FileProc(clientData, fd, id) */ static int -FileHandlerEventProc(evPtr, flags) - Tcl_Event *evPtr; /* Event to service. */ - int flags; /* Flags that indicate what events to - * handle, such as TCL_FILE_EVENTS. */ +FileHandlerEventProc( + Tcl_Event *evPtr, /* Event to service. */ + int flags) /* Flags that indicate what events to handle, + * such as TCL_FILE_EVENTS. */ { FileHandler *filePtr; FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) evPtr; @@ -583,9 +575,9 @@ FileHandlerEventProc(evPtr, flags) /* * Search through the file handlers to find the one whose handle matches - * the event. We do this rather than keeping a pointer to the file - * handler directly in the event, so that the handler can be deleted - * while the event is queued without leaving a dangling pointer. + * the event. We do this rather than keeping a pointer to the file handler + * directly in the event, so that the handler can be deleted while the + * event is queued without leaving a dangling pointer. */ for (filePtr = notifier.firstFileHandlerPtr; filePtr != NULL; @@ -596,20 +588,20 @@ FileHandlerEventProc(evPtr, flags) /* * The code is tricky for two reasons: - * 1. The file handler's desired events could have changed - * since the time when the event was queued, so AND the - * ready mask with the desired mask. - * 2. The file could have been closed and re-opened since - * the time when the event was queued. This is why the - * ready mask is stored in the file handler rather than - * the queued event: it will be zeroed when a new - * file handler is created for the newly opened file. + * 1. The file handler's desired events could have changed since the + * time when the event was queued, so AND the ready mask with the + * desired mask. + * 2. The file could have been closed and re-opened since the time + * when the event was queued. This is why the ready mask is stored + * in the file handler rather than the queued event: it will be + * zeroed when a new file handler is created for the newly opened + * file. */ mask = filePtr->readyMask & filePtr->mask; filePtr->readyMask = 0; if (mask != 0) { - (*filePtr->proc)(filePtr->clientData, mask); + filePtr->proc(filePtr->clientData, mask); } break; } @@ -621,14 +613,14 @@ FileHandlerEventProc(evPtr, flags) * * WaitForEvent -- * - * This function is called by Tcl_DoOneEvent to wait for new - * events on the message queue. If the block time is 0, then - * Tcl_WaitForEvent just polls without blocking. + * This function is called by Tcl_DoOneEvent to wait for new events on + * the message queue. If the block time is 0, then Tcl_WaitForEvent just + * polls without blocking. * * Results: - * Returns 1 if an event was found, else 0. This ensures that - * Tcl_DoOneEvent will return 1, even if the event is handled - * by non-Tcl code. + * Returns 1 if an event was found, else 0. This ensures that + * Tcl_DoOneEvent will return 1, even if the event is handled by non-Tcl + * code. * * Side effects: * Queues file events that are detected by the select. @@ -638,7 +630,7 @@ FileHandlerEventProc(evPtr, flags) static int WaitForEvent( - Tcl_Time *timePtr) /* Maximum block time, or NULL. */ + const Tcl_Time *timePtr) /* Maximum block time, or NULL. */ { int timeout; @@ -649,18 +641,27 @@ WaitForEvent( TclSetAppContext(NULL); if (timePtr) { - timeout = timePtr->sec * 1000 + timePtr->usec / 1000; - if (timeout == 0) { - if (XtAppPending(notifier.appContext)) { - goto process; - } else { - return 0; - } - } else { - Tcl_SetTimer(timePtr); - } + timeout = timePtr->sec * 1000 + timePtr->usec / 1000; + if (timeout == 0) { + if (XtAppPending(notifier.appContext)) { + goto process; + } else { + return 0; + } + } else { + Tcl_SetTimer(timePtr); + } } -process: + + process: XtAppProcessEvent(notifier.appContext, XtIMAll); return 1; } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ |