home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / EXTRAS / UUCODE / UUPC / TEST / UPC12ES1.ZIP / LIB / ssleep.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-11  |  17.6 KB  |  515 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    s s l e e p . c                                                 */
  3. /*                                                                    */
  4. /*    Smart sleep routines for UUPC/extended                          */
  5. /*                                                                    */
  6. /*    Written by Dave Watt, modified by Drew Derbyshire               */
  7. /*                                                                    */
  8. /*    Generates DOS specific code with Windows support by default,    */
  9. /*    generates call to OS/2 family API if FAMILYAPI is defined       */
  10. /*    generates calls to Windows/NT if WIN32 is defined               */
  11. /*--------------------------------------------------------------------*/
  12.  
  13. /*--------------------------------------------------------------------*/
  14. /*                          RCS Information                           */
  15. /*--------------------------------------------------------------------*/
  16.  
  17. /*
  18.  *    $Id: ssleep.c 1.13 1993/10/12 01:20:43 ahd Exp $
  19.  *
  20.  *    Revision history:
  21.  *    $Log: ssleep.c $
  22.  *     Revision 1.13  1993/10/12  01:20:43  ahd
  23.  *     Normalize comments to PL/I style
  24.  *
  25.  *     Revision 1.12  1993/10/12  00:41:51  ahd
  26.  *     Normalize comments
  27.  *
  28.  *     Revision 1.11  1993/10/09  15:47:51  rhg
  29.  *     ANSIify the source
  30.  *
  31.  *     Revision 1.10  1993/09/27  02:42:11  ahd
  32.  *     Use signed number for delay computations under DOS
  33.  *
  34.  *     Revision 1.9  1993/09/24  03:43:27  ahd
  35.  *     Use OS/2 error messages
  36.  *
  37.  *     Revision 1.8  1993/09/20  04:39:51  ahd
  38.  *     OS/2 2.x support
  39.  *
  40.  *     Revision 1.7  1993/08/02  03:24:59  ahd
  41.  *     Further changes in support of Robert Denny's Windows 3.x support
  42.  *
  43.  *     Revision 1.6  1993/07/31  16:22:16  ahd
  44.  *     Changes in support of Robert Denny's Windows 3.x support
  45.  *
  46.  *     Revision 1.5  1993/07/22  23:19:50  ahd
  47.  *     First pass for Robert Denny's Windows 3.x support changes
  48.  *
  49.  *     Revision 1.4  1993/04/11  00:32:29  ahd
  50.  *     Global edits for year, TEXT, etc.
  51.  *
  52.  * Revision 1.3  1992/12/12  16:12:13  ahd
  53.  * Correct test for DesqView
  54.  *
  55.  * Revision 1.2  1992/12/07  02:43:20  ahd
  56.  * Add DesqView support from David M. Watt
  57.  *
  58.  * Revision 1.1  1992/11/16  05:00:26  ahd
  59.  * Initial revision
  60.  *
  61.  */
  62.  
  63. /*--------------------------------------------------------------------*/
  64. /*                        System include files                        */
  65. /*--------------------------------------------------------------------*/
  66.  
  67. #include <limits.h>
  68. #include <stdio.h>
  69. #include <stdlib.h>
  70. #include <signal.h>
  71. #include <time.h>
  72.  
  73. /*--------------------------------------------------------------------*/
  74. /*               MS-DOS and OS/2 specific include files               */
  75. /*--------------------------------------------------------------------*/
  76.  
  77. #if defined(FAMILYAPI) || defined(__OS2__)
  78.  
  79. #define INCL_NOPM
  80. #define INCL_BASE
  81. #include <os2.h>
  82.  
  83. #else
  84.  
  85. #include <dos.h>
  86. #include <sys/timeb.h>
  87.  
  88. #endif
  89.  
  90. #if defined(WIN32) || defined(_Windows)
  91. #include <windows.h>
  92. #endif
  93.  
  94. /*--------------------------------------------------------------------*/
  95. /*                    UUPC/extended include files                     */
  96. /*--------------------------------------------------------------------*/
  97.  
  98. #include "lib.h"
  99. #include "ssleep.h"
  100. #include "safeio.h"
  101. #include "catcher.h"
  102.  
  103. #if defined(_Windows)
  104. #include "winutil.h"
  105. #endif
  106.  
  107.  
  108. #if defined(FAMILYAPI) || defined(__OS2__)
  109. #include "pos2err.h"
  110. #endif
  111.  
  112. /*--------------------------------------------------------------------*/
  113. /*                          Global variables                          */
  114. /*--------------------------------------------------------------------*/
  115.  
  116. #if defined(FAMILYAPI) || defined(__OS2__)
  117. currentfile();
  118. #endif
  119.  
  120.  
  121. /*--------------------------------------------------------------------*/
  122. /*                     MS-DOS specific functions                      */
  123. /*--------------------------------------------------------------------*/
  124.  
  125. #if !defined(FAMILYAPI) && !defined(__OS2__)
  126.  
  127. currentfile();
  128.  
  129. #define MULTIPLEX 0x2F
  130. #define DESQVIEW 0x15
  131.  
  132. #ifdef _Windows
  133.  
  134. static void WindowsDelay( const int milliseconds );
  135.  
  136. /*--------------------------------------------------------------------*/
  137. /*    W i n d o w s D e l a y                                         */
  138. /*                                                                    */
  139. /*    Delay processing under Windows                                  */
  140. /*                                                                    */
  141. /*    NOTE: Minimum resolution is 54.925 ms.                          */
  142. /*--------------------------------------------------------------------*/
  143.  
  144. static void WindowsDelay( const int milliseconds )
  145. {
  146.    MSG msg;
  147.    WORD TimerId = 1;
  148.    BOOL bTimerDone = FALSE;
  149.  
  150. /*--------------------------------------------------------------------*/
  151. /*          A 0-delay call means give up control to Windows           */
  152. /*--------------------------------------------------------------------*/
  153.  
  154.    if (milliseconds == 0)
  155.    {
  156.       while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  157.       {
  158.          TranslateMessage(&msg);
  159.          DispatchMessage(&msg);
  160.       }
  161.       return;
  162.    }
  163.  
  164.    SetTimer( hOurWindow,
  165.             TimerId,
  166.             (milliseconds > 55) ? (WORD)milliseconds : (WORD)55 ,
  167.             NULL );
  168.  
  169.    if ( TimerId == 0 )
  170.    {
  171.       printmsg(0, "WindowsDelay: Unable to set Windows Timer");
  172.       panic();
  173.       return;
  174.    } /* if */
  175.  
  176. /*--------------------------------------------------------------------*/
  177. /*       LOCAL MESSAGE LOOP - Service Windows while waiting for       */
  178. /*       the timer message.                                           */
  179. /*--------------------------------------------------------------------*/
  180.  
  181.    while(!bTimerDone && GetMessage(&msg, NULL, NULL, NULL))
  182.    {
  183.       TranslateMessage(&msg);
  184.       DispatchMessage(&msg);
  185.       if (msg.message == WM_TIMER)
  186.          bTimerDone = TRUE;
  187.    }
  188.  
  189.    if (KillTimer( hOurWindow, TimerId ) == 0)
  190.       printmsg(0, "WindowsDelay: Unable to kill Windows Timer %d",
  191.                   (int) TimerId );
  192.  
  193. } /* WindowsDelay */
  194.  
  195. #else
  196.  
  197. #ifndef WIN32
  198.  
  199. /*--------------------------------------------------------------------*/
  200. /*                      Local function declares                       */
  201. /*--------------------------------------------------------------------*/
  202.  
  203. static void WinGiveUpTimeSlice(void);
  204. static int RunningUnderWindows(void);
  205. static int RunningUnderDesqview(void);
  206. static void DVGiveUpTimeSlice(void);
  207.  
  208. /*--------------------------------------------------------------------*/
  209. /*              Use this first to see if the rest are OK              */
  210. /*                                                                    */
  211. /*                  MOV AX,1600h   ; Check for win386/win3.0          */
  212. /*                                   present                          */
  213. /*                  INT 2Fh                                           */
  214. /* Return AL = 0 -> No Windows, AL = 80 -> No WIn386 mode             */
  215. /*        AL = 1 or AL = FFh -> Win386 2.xx running                   */
  216. /*   else AL = Major version (3), AH = Minor version                  */
  217. /*--------------------------------------------------------------------*/
  218. /* --------------- Release time slice                                 */
  219. /*                  MOV AX,1680h   ; **** Release time slice          */
  220. /*                  INT 2Fh        ; Let someone else run             */
  221. /* Return code is AL = 80H -> service not installed, AL = 0 -> all    */
  222. /*                                                              OK    */
  223. /*--------------------------------------------------------------------*/
  224. /* --------------- Enter critical section (disable task switch)       */
  225. /*                  MOV AX,1681H   ; Don't tread on me!               */
  226. /*                  INT 2Fh                                           */
  227. /*--------------------------------------------------------------------*/
  228. /* --------------- End critical section (Permit task switching)       */
  229. /*                  MOV AX,1682h                                      */
  230. /*                  INT 2Fh                                           */
  231. /*--------------------------------------------------------------------*/
  232.  
  233. /*--------------------------------------------------------------------*/
  234. /*    R u n n i n g U n d e r W i n d o w s                           */
  235. /*                                                                    */
  236. /*    Determines if we are running under MS-Windows 386 or            */
  237. /*    MS-Windows 3.  We save the result, to avoid excessively         */
  238. /*    disabling interrupts when in a spin loop.                       */
  239. /*--------------------------------------------------------------------*/
  240.  
  241. static int RunningUnderWindows(void)
  242. {
  243.  
  244.    static int result = 2;
  245.    union REGS inregs, outregs;
  246.    static const int irq = MULTIPLEX;
  247.  
  248.    if (result != 2)           /* First call?                          */
  249.       return result;          /* No --> Return saved result           */
  250.  
  251.    inregs.x.ax = 0x1600;
  252.    int86(irq, &inregs, &outregs);
  253.    if ( (outregs.h.al & 0x7f) == 0)
  254.       result = 0;
  255.    else
  256.       result = 1;
  257.  
  258.    return result;
  259.  
  260. } /* RunningUnderWindows */
  261.  
  262. /*--------------------------------------------------------------------*/
  263. /*    W i n G i v e U p T i m e S l i c e                             */
  264. /*                                                                    */
  265. /*    Surrender our time slice when executing under Windows/386       */
  266. /*    or Windows release 3.                                           */
  267. /*--------------------------------------------------------------------*/
  268.  
  269. static void WinGiveUpTimeSlice(void)
  270. {
  271.    union REGS inregs, outregs;
  272.    static const int irq = MULTIPLEX;
  273.  
  274.    inregs.x.ax = 0x1680;
  275.    int86(irq, &inregs, &outregs);
  276.    if (outregs.h.al != 0) {
  277.       printmsg(0,"Problem giving up timeslice:  %u\n", outregs.h.al);
  278.       panic();
  279.    }
  280. } /* WinGiveUpTimeSlice */
  281.  
  282. /*--------------------------------------------------------------------*/
  283. /*    R u n n i n g U n d e r D e s q v i e w                         */
  284. /*                                                                    */
  285. /*    Returns TRUE if running under that OTHER DOS multi-tasker.      */
  286. /*--------------------------------------------------------------------*/
  287.  
  288. static int RunningUnderDesqview(void)
  289. {
  290.    static int result = 2;
  291.    union REGS inregs, outregs;
  292.  
  293.    if (result != 2)           /* First call?                          */
  294.       return result;          /* No --> Return saved result           */
  295.  
  296.    inregs.x.ax = 0x2B01;      /* Dos Set Date function */
  297.    inregs.x.cx = 0x4445;      /* CX DX = 'DESQ' */
  298.    inregs.x.dx = 0x5351;
  299.  
  300.    intdos(&inregs, &outregs);
  301.    if (outregs.h.al == 0xff) {
  302.       result = 0;
  303.    } else {
  304.       printmsg(4, "RunningUnderDesqview:  Running under DesqView (AX=0x%x)",
  305.                (int) outregs.x.ax);
  306.       result = 1;
  307.    }
  308.  
  309.    return result;
  310.  
  311. } /* RunningUnderDesqview */
  312.  
  313. /*--------------------------------------------------------------------*/
  314. /*    D V G i v e U p T i m e S l i c e                               */
  315. /*                                                                    */
  316. /*    Surrender the CPU under DesqView                                */
  317. /*--------------------------------------------------------------------*/
  318.  
  319. static void DVGiveUpTimeSlice(void)
  320. {
  321. #ifdef __TURBOC__
  322.    asm {
  323. #else
  324.    _asm \
  325.       {
  326. #endif
  327.       push ax
  328.       mov ax, 101AH
  329.                               /* Switch over to Desqview's stack  */
  330.       int     15H
  331.       mov ax, 1000H
  332.                               /* Give up the timeslice            */
  333.       int     15H
  334.       mov ax, 1025H
  335.                               /* Switch stack back to application */
  336.       int     15H
  337.       pop ax
  338.       }
  339.  
  340. } /* DVGiveUpTimeSlice */
  341.  
  342. #endif /* _Windows */
  343. #endif /* WIN32 */
  344. #endif
  345.  
  346.  
  347. /*--------------------------------------------------------------------*/
  348. /*    ssleep() - wait n seconds                                       */
  349. /*                                                                    */
  350. /*    Simply delay until n seconds have passed.                       */
  351. /*--------------------------------------------------------------------*/
  352.  
  353. void ssleep(time_t interval)
  354. {
  355.    time_t quit = time((time_t *)NULL) + interval;
  356.    long left = (long) interval;
  357.  
  358. /*--------------------------------------------------------------------*/
  359. /*            Break the spin into chunks ddelay can handle            */
  360. /*--------------------------------------------------------------------*/
  361.  
  362.    while ( left > SHRT_MAX / 1000 )
  363.    {
  364.       ddelay( 5000 );         /* Five seconds per pass                */
  365.       if ((left = (long) quit - (long) time( NULL )) <= 0)
  366.          return;
  367.    } /* while */
  368.  
  369. /*--------------------------------------------------------------------*/
  370. /*                 Final delay for the time remaining                 */
  371. /*--------------------------------------------------------------------*/
  372.  
  373.    ddelay( (KEWSHORT) ((short) left * 1000) );
  374.  
  375. } /*ssleep*/
  376.  
  377. /*--------------------------------------------------------------------*/
  378. /*    d d e l a y                                                     */
  379. /*                                                                    */
  380. /*    Delay for an interval of milliseconds                           */
  381. /*--------------------------------------------------------------------*/
  382.  
  383. void   ddelay   (KEWSHORT interval )
  384. {
  385.  
  386. #if defined(FAMILYAPI) || defined(__OS2__)
  387.  
  388.    USHORT result;
  389.  
  390. #elif !defined(_Windows)
  391.  
  392.    struct timeb start;
  393.  
  394. #endif
  395.  
  396. #ifndef _Windows
  397.  
  398. /*--------------------------------------------------------------------*/
  399. /*           Check for user aborts via the ESC (escape) key           */
  400. /*--------------------------------------------------------------------*/
  401.  
  402.    if (bflag[F_ESCAPE])       /* Special Ctrl-C processing avail?     */
  403.    {
  404.       boolean beep = TRUE;
  405.  
  406.       while (safepeek())      /* Yes --> While character in buffer    */
  407.       {
  408.          if (safein() == '\033') /* Look for ESC                      */
  409.             raise( SIGINT );     /* Yes --> eject via std exit        */
  410.          else if ( beep )
  411.          {
  412.              putchar('\a');      /* No --> Complain to user           */
  413.              beep = FALSE;       /* But be nice about it ...
  414.                                     only once per pass through here   */
  415.          } /* else if ( beep ) */
  416.       } /* while */
  417.  
  418.    } /* if (bflag[F_ESCAPE]) */
  419.  
  420. #endif /* _Windows */
  421.  
  422. /*--------------------------------------------------------------------*/
  423. /*                          Now do the wait                           */
  424. /*--------------------------------------------------------------------*/
  425.  
  426. /*--------------------------------------------------------------------*/
  427. /*                          Windows/NT wait                           */
  428. /*--------------------------------------------------------------------*/
  429.  
  430. #ifdef WIN32
  431.    Sleep(interval);
  432.  
  433. /*--------------------------------------------------------------------*/
  434. /*                           Windows wait                             */
  435. /*--------------------------------------------------------------------*/
  436.  
  437. #elif defined(_Windows)
  438.    WindowsDelay(interval);
  439.  
  440. /*--------------------------------------------------------------------*/
  441. /*                             OS/2 wait                              */
  442. /*--------------------------------------------------------------------*/
  443.  
  444. #elif defined(FAMILYAPI) || defined(__OS2__)
  445.  
  446.    result = DosSleep(interval);
  447.    if (result)
  448.       printOS2error( "DosSleep", result );
  449. #else
  450.  
  451. /*--------------------------------------------------------------------*/
  452. /*                            MS-DOS wait                             */
  453. /*--------------------------------------------------------------------*/
  454.  
  455. #ifdef __TURBOC__
  456.    enable();
  457. #else
  458.    _enable();
  459. #endif
  460.  
  461. /*--------------------------------------------------------------------*/
  462. /*       Handle the special case of 0 delay, which is simply a        */
  463. /*                  request to give up our timeslice                  */
  464. /*--------------------------------------------------------------------*/
  465.  
  466.    if (interval == 0)     /* Make it compatible with DosSleep    */
  467.    {
  468.  
  469.       if (RunningUnderWindows())
  470.          WinGiveUpTimeSlice( );
  471.       else if (RunningUnderDesqview())
  472.          DVGiveUpTimeSlice();
  473.  
  474.       return;
  475.    } /* if */
  476.  
  477.    ftime(&start);             /* Get a starting time                  */
  478.  
  479.    for( ; ; )
  480.    {
  481.       struct timeb now;
  482.       long elapsed;
  483.  
  484.       ftime(&now);           /* See how much time has elapsed */
  485.       elapsed = ((long) (now.time - start.time) - 1) * 1000L
  486.                 + (now.millitm + 1000 - start.millitm);
  487.  
  488.       if (elapsed > (long) interval)
  489.          return;
  490.  
  491.       if (RunningUnderWindows())
  492.          WinGiveUpTimeSlice();
  493.       else if (RunningUnderDesqview())
  494.          DVGiveUpTimeSlice();
  495.       else {
  496.  
  497. #ifdef __TURBOC__
  498.  
  499.          delay( (short) ((long) interval - elapsed) );
  500.  
  501. #else
  502.  
  503.          int volatile count;  /* Don't let compiler optimize this     */
  504.          for ( count = 0; count < 2400; count ++);
  505.                               /* We spin so that interrupts are
  506.                                  enabled for most of the loop         */
  507. #endif
  508.  
  509.       } /* else */
  510.    } /* while */
  511.  
  512. #endif /* FAMILYAPI */
  513.  
  514. } /* ddelay */
  515.