home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tkisrc04.zip / tcl / os2 / tclOS2Notify.c < prev    next >
C/C++ Source or Header  |  1998-08-07  |  7KB  |  267 lines

  1. /* 
  2.  * tclOS2Notify.c --
  3.  *
  4.  *    This file contains OS/2-specific procedures for the notifier,
  5.  *    which is the lowest-level part of the Tcl event loop.  This file
  6.  *    works together with ../generic/tclNotify.c.
  7.  *
  8.  * Copyright (c) 1995-1996 Sun Microsystems, Inc.
  9.  * Copyright (c) 1996-1997 Illya Vaes
  10.  *
  11.  * See the file "license.terms" for information on usage and redistribution
  12.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  13.  *
  14.  */
  15.  
  16. #include "tclInt.h"
  17. #include "tclPort.h"
  18.  
  19. /*
  20.  * The following variable is a backdoor for use by Tk.  It is set when
  21.  * Tk needs to process events on the Tcl event queue without reentering
  22.  * the system event loop.  Tk uses it to flush the Tcl event queue.
  23.  */
  24.  
  25. static int ignoreEvents = 0;
  26.  
  27. /*
  28.  *----------------------------------------------------------------------
  29.  *
  30.  * TclOS2FlushEvents --
  31.  *
  32.  *    This function is a special purpose hack to allow Tk to
  33.  *    process queued Window events during a recursive event loop
  34.  *    without looking for new events on the system event queue.
  35.  *
  36.  * Results:
  37.  *    None.
  38.  *
  39.  * Side effects:
  40.  *    Services any pending Tcl events and calls idle handlers.
  41.  *
  42.  *----------------------------------------------------------------------
  43.  */
  44.  
  45. void
  46. TclOS2FlushEvents()
  47. {
  48.     ignoreEvents = 1;
  49.     while (Tcl_DoOneEvent(TCL_DONT_WAIT|TCL_WINDOW_EVENTS|TCL_IDLE_EVENTS)) {
  50.     }
  51.     ignoreEvents = 0;
  52. }
  53.  
  54. /*
  55.  *----------------------------------------------------------------------
  56.  *
  57.  * Tcl_WatchFile --
  58.  *
  59.  *    Arrange for Tcl_DoOneEvent to include this file in the masks
  60.  *    for the next call to select.  This procedure is invoked by
  61.  *    event sources, which are in turn invoked by Tcl_DoOneEvent
  62.  *    before it invokes select.
  63.  *
  64.  * Results:
  65.  *    None.
  66.  *
  67.  * Side effects:
  68.  *    
  69.  *    The notifier will generate a file event when the I/O channel
  70.  *    given by fd next becomes ready in the way indicated by mask.
  71.  *    If fd is already registered then the old mask will be replaced
  72.  *    with the new one.  Once the event is sent, the notifier will
  73.  *    not send any more events about the fd until the next call to
  74.  *    Tcl_NotifyFile. 
  75.  *
  76.  *----------------------------------------------------------------------
  77.  */
  78.  
  79. void
  80. Tcl_WatchFile(file, mask)
  81.     Tcl_File file;        /* Opaque identifier for a stream. */
  82.     int mask;            /* OR'ed combination of TCL_READABLE,
  83.                  * TCL_WRITABLE, and TCL_EXCEPTION:
  84.                  * indicates conditions to wait for
  85.                  * in select. */
  86. {
  87.     int type;
  88.  
  89.     (void) Tcl_GetFileInfo(file, &type);
  90.  
  91.     if (type == TCL_OS2_SOCKET) {
  92.     TclOS2WatchSocket(file, mask);
  93.     } else if (type == TCL_OS2_FILE) {
  94.     Tcl_Time timeout = { 0, 0 };
  95.  
  96.     /*
  97.      * Files are always ready under OS/2, so we just set a
  98.      * 0 timeout.
  99.      */
  100.  
  101.     Tcl_SetMaxBlockTime(&timeout);
  102.     } else if (type == TCL_OS2_PIPE) {
  103.     /*
  104.      * We don't support waiting on pipes yet.
  105.      */
  106.     }
  107. }
  108.  
  109. /*
  110.  *----------------------------------------------------------------------
  111.  *
  112.  * Tcl_FileReady --
  113.  *
  114.  *    Indicates what conditions (readable, writable, etc.) were
  115.  *    present on a file the last time the notifier invoked select.
  116.  *    This procedure is typically invoked by event sources to see
  117.  *    if they should queue events.
  118.  *
  119.  * Results:
  120.  *    The return value is 0 if none of the conditions specified by mask
  121.  *    was true for fd the last time the system checked.  If any of the
  122.  *    conditions were true, then the return value is a mask of those
  123.  *    that were true.
  124.  *
  125.  * Side effects:
  126.  *    None.
  127.  *
  128.  *----------------------------------------------------------------------
  129.  */
  130.  
  131. int
  132. Tcl_FileReady(file, mask)
  133.     Tcl_File file;    /* File handle for a stream. */
  134.     int mask;            /* OR'ed combination of TCL_READABLE,
  135.                  * TCL_WRITABLE, and TCL_EXCEPTION:
  136.                  * indicates conditions caller cares about. */
  137. {
  138.     int type;
  139.  
  140.     (void) Tcl_GetFileInfo(file, &type);
  141.  
  142.     if (type == TCL_OS2_SOCKET) {
  143.     return TclOS2SocketReady(file, mask);
  144.     } else if (type == TCL_OS2_FILE) {
  145.     /*
  146.      * Under OS/2, files are always ready, so we just return the
  147.      * mask that was passed in.
  148.      */
  149.  
  150.     return mask;
  151.     }
  152.     return 0;
  153. }
  154.  
  155. /*
  156.  *----------------------------------------------------------------------
  157.  *
  158.  * Tcl_WaitForEvent --
  159.  *
  160.  *    This procedure does the lowest level wait for events in a
  161.  *    platform-specific manner.  It uses information provided by
  162.  *    previous calls to Tcl_WatchFile, plus the timePtr argument,
  163.  *    to determine what to wait for and how long to wait.
  164.  *
  165.  * Results:
  166.  *    The return value is normally TCL_OK.  However, if there are
  167.  *    no events to wait for (e.g. no files and no timers) so that
  168.  *    the procedure would block forever, then it returns TCL_ERROR.
  169.  *
  170.  * Side effects:
  171.  *    May put the process to sleep for a while, depending on timePtr.
  172.  *    When this procedure returns, an event of interest to the application
  173.  *    has probably, but not necessarily, occurred.
  174.  *
  175.  *----------------------------------------------------------------------
  176.  */
  177.  
  178. int
  179. Tcl_WaitForEvent(timePtr)
  180.     Tcl_Time *timePtr;        /* Specifies the maximum amount of time
  181.                  * that this procedure should block before
  182.                  * returning.  The time is given as an
  183.                  * interval, not an absolute wakeup time.
  184.                  * NULL means block forever. */
  185. {
  186.     QMSG msg;
  187.     int foundEvent = 1;
  188.  
  189.     /*
  190.      * If we are ignoring events from the system, just return immediately.
  191.      */
  192.  
  193.     if (ignoreEvents) {
  194.     return TCL_OK;
  195.     }
  196.  
  197.     /*
  198.      * Set up the asynchronous select handlers for any sockets we
  199.      * are watching.
  200.      */
  201.  
  202.     TclOS2NotifySocket();
  203.  
  204.     /*
  205.      * Look for an event, setting a timer so we don't block forever.
  206.      */
  207.  
  208. #ifndef CLI_VERSION
  209.     if (timePtr != NULL) {
  210.     ULONG ms;
  211.     ms = timePtr->sec * 1000;
  212.     ms += timePtr->usec / 1000;
  213.  
  214.     if (ms > 0) {
  215.         ULONG timerHandle = WinStartTimer(hab, NULLHANDLE, 1, ms);
  216.         WinGetMsg(hab, &msg, NULLHANDLE, 0, 0);
  217.         WinStopTimer(hab, NULLHANDLE, timerHandle);
  218.     } else {
  219.  
  220.         /*
  221.          * If the timeout is too small, we just poll.
  222.          */
  223.  
  224.         foundEvent = WinPeekMsg(hab, &msg, NULLHANDLE, 0, 0, PM_REMOVE);
  225.     }
  226.     } else {
  227.     WinGetMsg(hab, &msg, NULLHANDLE, 0, 0);
  228.     }
  229.  
  230.     /*
  231.      * Dispatch the message, if we found one.  If we are exiting, be
  232.      * sure to inform Tcl so we can clean up properly.
  233.      */
  234.  
  235.     if (foundEvent) {
  236.     if (msg.msg == WM_QUIT) {
  237.         Tcl_Exit(0);
  238.     }
  239.     WinDispatchMsg(hab, &msg);
  240.     }
  241. #endif
  242.     return TCL_OK;
  243. }
  244.  
  245. /*
  246.  *----------------------------------------------------------------------
  247.  *
  248.  * Tcl_Sleep --
  249.  *
  250.  *    Delay execution for the specified number of milliseconds.
  251.  *
  252.  * Results:
  253.  *    None.
  254.  *
  255.  * Side effects:
  256.  *    Time passes.
  257.  *
  258.  *----------------------------------------------------------------------
  259.  */
  260.  
  261. void
  262. Tcl_Sleep(ms)
  263.     int ms;            /* Number of milliseconds to sleep. */
  264. {
  265.     DosSleep(ms);
  266. }
  267.