diff options
Diffstat (limited to 'unix/tclXtNotify.c')
| -rw-r--r-- | unix/tclXtNotify.c | 385 | 
1 files changed, 192 insertions, 193 deletions
| diff --git a/unix/tclXtNotify.c b/unix/tclXtNotify.c index 31157ff..a5d92d6 100644 --- a/unix/tclXtNotify.c +++ b/unix/tclXtNotify.c @@ -1,31 +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. - * - * RCS: @(#) $Id: tclXtNotify.c,v 1.4 1999/07/02 06:05:34 welch Exp $ + * 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. */ @@ -36,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;  /* @@ -75,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);  /*   *---------------------------------------------------------------------- @@ -107,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();      }      /* @@ -126,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;  } @@ -186,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);  } @@ -220,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. @@ -237,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;  } @@ -267,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; @@ -282,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;      } @@ -295,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; @@ -331,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; @@ -363,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; @@ -382,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) { @@ -393,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) { @@ -404,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) { @@ -421,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. @@ -434,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; @@ -447,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; ; @@ -479,7 +470,7 @@ DeleteFileHandler(fd)      if (filePtr->mask & TCL_EXCEPTION) {  	XtRemoveInput(filePtr->except);      } -    ckfree((char *) filePtr); +    ckfree(filePtr);  }  /* @@ -494,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; @@ -529,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); @@ -552,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. @@ -570,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; @@ -585,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; @@ -598,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;      } @@ -623,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. @@ -640,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; @@ -651,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: + */ | 
