home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / UUPC11XS.ZIP / LIB / SSLEEP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-12  |  15.5 KB  |  450 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.  *    $Header: E:\src\uupc\LIB\RCS\SSLEEP.C 1.3 1992/12/12 16:12:13 ahd Exp $
  19.  *
  20.  *    Revision history:
  21.  *    $Log: SSLEEP.C $
  22.  * Revision 1.3  1992/12/12  16:12:13  ahd
  23.  * Correct test for DesqView
  24.  *
  25.  * Revision 1.2  1992/12/07  02:43:20  ahd
  26.  * Add DesqView support from David M. Watt
  27.  *
  28.  * Revision 1.1  1992/11/16  05:00:26  ahd
  29.  * Initial revision
  30.  *
  31.  */
  32.  
  33. /*--------------------------------------------------------------------*/
  34. /*                        System include files                        */
  35. /*--------------------------------------------------------------------*/
  36.  
  37. #include <limits.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <signal.h>
  41. #include <time.h>
  42.  
  43. /*--------------------------------------------------------------------*/
  44. /*               MS-DOS and OS/2 specific include files               */
  45. /*--------------------------------------------------------------------*/
  46.  
  47. #ifdef FAMILYAPI
  48.  
  49. #define INCL_NOPM
  50. #define INCL_BASE
  51. #include <os2.h>
  52.  
  53. #else
  54.  
  55. #include <dos.h>
  56. #include <sys/timeb.h>
  57.  
  58. #endif
  59.  
  60. #ifdef WIN32
  61. #include <windows.h>
  62. #endif
  63.  
  64. /*--------------------------------------------------------------------*/
  65. /*                    UUPC/extended include files                     */
  66. /*--------------------------------------------------------------------*/
  67.  
  68. #include "lib.h"
  69. #include "ssleep.h"
  70. #include "safeio.h"
  71.  
  72. /*--------------------------------------------------------------------*/
  73. /*                          Global variables                          */
  74. /*--------------------------------------------------------------------*/
  75.  
  76. currentfile();
  77.  
  78. /*--------------------------------------------------------------------*/
  79. /*                     MS-DOS specific functions                      */
  80. /*--------------------------------------------------------------------*/
  81.  
  82. #ifndef FAMILYAPI
  83. #define MULTIPLEX 0x2F
  84. #define DESQVIEW 0x15
  85.  
  86. #ifdef _Windows
  87.  
  88. #include <windows.h>
  89.  
  90. void WindowsDelay( int milliseconds );
  91.  
  92. /*--------------------------------------------------------------------*/
  93. /*    W i n d o w s D e l a y                                         */
  94. /*                                                                    */
  95. /*    Delay processing under Windows                                  */
  96. /*--------------------------------------------------------------------*/
  97.  
  98. void WindowsDelay( int milliseconds )
  99. {
  100.    WORD TimerId = SetTimer( NULL, 0,
  101.             milliseconds ? (WORD) milliseconds : (WORD) 1,
  102.             NULL );
  103.  
  104.    if ( TimerId == 0 )
  105.    {
  106.       printmsg(0, "WindowsDelay: Unable to set Windows Timer");
  107.       return;
  108.    } /* if */
  109.  
  110.    WaitMessage();
  111.  
  112.    if ( !KillTimer( NULL, TimerId ) )
  113.       printmsg(0, "WindowsDelay: Unable to kill Windows Timer %d",
  114.                   (int) TimerId );
  115.  
  116. } /* WindowsDelay */
  117.  
  118. #else
  119.  
  120. #ifndef WIN32
  121.  
  122. /*--------------------------------------------------------------------*/
  123. /*                      Local function declares                       */
  124. /*--------------------------------------------------------------------*/
  125.  
  126. static void WinGiveUpTimeSlice(void);
  127. static int RunningUnderWindows(void);
  128. static int RunningUnderDesqview(void);
  129. static void DVGiveUpTimeSlice(void);
  130.  
  131. /*--------------------------------------------------------------------*/
  132. /*              Use this first to see if the rest are OK              */
  133. /*                                                                    */
  134. /*                  MOV AX,1600h   ; Check for win386/win3.0          */
  135. /*                                   present                          */
  136. /*                  INT 2Fh                                           */
  137. /* Return AL = 0 -> No Windows, AL = 80 -> No WIn386 mode             */
  138. /*        AL = 1 or AL = FFh -> Win386 2.xx running                   */
  139. /*   else AL = Major version (3), AH = Minor version                  */
  140. /*--------------------------------------------------------------------*/
  141. /* --------------- Release time slice                                 */
  142. /*                  MOV AX,1680h   ; **** Release time slice          */
  143. /*                  INT 2Fh        ; Let someone else run             */
  144. /* Return code is AL = 80H -> service not installed, AL = 0 -> all    */
  145. /*                                                              OK    */
  146. /*--------------------------------------------------------------------*/
  147. /* --------------- Enter critical section (disable task switch)       */
  148. /*                  MOV AX,1681H   ; Don't tread on me!               */
  149. /*                  INT 2Fh                                           */
  150. /*--------------------------------------------------------------------*/
  151. /* --------------- End critical section (Permit task switching)       */
  152. /*                  MOV AX,1682h                                      */
  153. /*                  INT 2Fh                                           */
  154. /*--------------------------------------------------------------------*/
  155.  
  156. /*--------------------------------------------------------------------*/
  157. /*    R u n n i n g U n d e r W i n d o w s                           */
  158. /*                                                                    */
  159. /*    Determines if we are running under MS-Windows 386 or            */
  160. /*    MS-Windows 3.  We save the result, to avoid excessively         */
  161. /*    disabling interrupts when in a spin loop.                       */
  162. /*--------------------------------------------------------------------*/
  163.  
  164. static int RunningUnderWindows(void)
  165. {
  166.  
  167.    static int result = 2;
  168.    union REGS inregs, outregs;
  169.    int irq;
  170.  
  171.    if (result != 2)           /* First call?                         */
  172.       return result;          /* No --> Return saved result          */
  173.  
  174.    irq = MULTIPLEX;
  175.    inregs.x.ax = 0x1600;
  176.    int86(irq, &inregs, &outregs);
  177.    if ( (outregs.h.al & 0x7f) == 0)
  178.       result = 0;
  179.    else
  180.       result = 1;
  181.  
  182.    return result;
  183.  
  184. } /* RunningUnderWindows */
  185.  
  186. /*--------------------------------------------------------------------*/
  187. /*    W i n G i v e U p T i m e S l i c e                             */
  188. /*                                                                    */
  189. /*    Surrender our time slice when executing under Windows/386       */
  190. /*    or Windows release 3.                                           */
  191. /*--------------------------------------------------------------------*/
  192.  
  193. static void WinGiveUpTimeSlice(void)
  194. {
  195.    union REGS inregs, outregs;
  196.    int irq = MULTIPLEX;
  197.  
  198.    inregs.x.ax = 0x1680;
  199.    int86(irq, &inregs, &outregs);
  200.    if (outregs.h.al != 0) {
  201.       printmsg(0,"Problem giving up timeslice:  %u\n", outregs.h.al);
  202.       panic();
  203.    }
  204. } /* WinGiveUpTimeSlice */
  205.  
  206. /*--------------------------------------------------------------------*/
  207. /*    R u n n i n g U n d e r D e s q v i e w                         */
  208. /*                                                                    */
  209. /*    Returns TRUE if running under that OTHER DOS multi-tasker.      */
  210. /*--------------------------------------------------------------------*/
  211.  
  212. static int RunningUnderDesqview(void)
  213. {
  214.    static int result = 2;
  215.    union REGS inregs, outregs;
  216.  
  217.    if (result != 2)           /* First call?                         */
  218.       return result;          /* No --> Return saved result          */
  219.  
  220.    inregs.x.ax = 0x2B01;      /* Dos Set Date function */
  221.    inregs.x.cx = 0x4445;      /* CX DX = 'DESQ' */
  222.    inregs.x.dx = 0x5351;
  223.  
  224.    intdos(&inregs, &outregs);
  225.    if (outregs.h.al == 0xff) {
  226.       result = 0;
  227.    } else {
  228.       printmsg(4, "RunningUnderDesqview:  Running under DesqView (AX=0x%x)",
  229.                (int) outregs.x.ax);
  230.       result = 1;
  231.    }
  232.  
  233.    return result;
  234.  
  235. } /* RunningUnderDesqview */
  236.  
  237. /*--------------------------------------------------------------------*/
  238. /*    D V G i v e U p T i m e S l i c e                               */
  239. /*                                                                    */
  240. /*    Surrender the CPU under DesqView                                */
  241. /*--------------------------------------------------------------------*/
  242.  
  243. static void DVGiveUpTimeSlice(void)
  244. {
  245. #ifdef __TURBOC__
  246.    asm {
  247. #else
  248.    _asm \
  249.       {
  250. #endif
  251.       push ax
  252.       mov ax, 101AH
  253.                               /* Switch over to Desqview's stack  */
  254.       int     15H
  255.       mov ax, 1000H
  256.                               /* Give up the timeslice            */
  257.       int     15H
  258.       mov ax, 1025H
  259.                               /* Switch stack back to application */
  260.       int     15H
  261.       pop ax
  262.       }
  263.  
  264. } /* DVGiveUpTimeSlice */
  265.  
  266. #endif /* _Windows */
  267. #endif /* WIN32 */
  268. #endif
  269.  
  270.  
  271. /*--------------------------------------------------------------------*/
  272. /*    ssleep() - wait n seconds                                       */
  273. /*                                                                    */
  274. /*    Simply delay until n seconds have passed.                       */
  275. /*--------------------------------------------------------------------*/
  276.  
  277. void ssleep(time_t interval)
  278. {
  279.    time_t start = time((time_t *)NULL);
  280.    time_t left = interval;
  281.  
  282. /*--------------------------------------------------------------------*/
  283. /*            Break the spin into chunks ddelay can handle            */
  284. /*--------------------------------------------------------------------*/
  285.  
  286.    while ( (left*1000L) > (long) INT_MAX )
  287.    {
  288.       ddelay( 5000 );         /* Five seconds per pass               */
  289.       left = max(interval - (time( NULL ) - start),0);
  290.    } /* while */
  291.  
  292. /*--------------------------------------------------------------------*/
  293. /*                 Final delay for the time remaining                 */
  294. /*--------------------------------------------------------------------*/
  295.  
  296.    ddelay( (int) (left * 1000L) );
  297.  
  298. } /*ssleep*/
  299.  
  300. /*--------------------------------------------------------------------*/
  301. /*    d d e l a y                                                     */
  302. /*                                                                    */
  303. /*    Delay for an interval of milliseconds                           */
  304. /*--------------------------------------------------------------------*/
  305.  
  306. void   ddelay   (int milliseconds)
  307. {
  308.  
  309. #ifdef FAMILYAPI
  310.    USHORT result;
  311. #else
  312.    struct timeb t;
  313.    time_t seconds;
  314.    unsigned last;
  315. #endif
  316.  
  317. #ifndef _Windows
  318.  
  319. /*--------------------------------------------------------------------*/
  320. /*           Check for user aborts via the ESC (escape) key           */
  321. /*--------------------------------------------------------------------*/
  322.  
  323.    if (bflag[F_ESCAPE])       /* Special Ctrl-C processing avail?    */
  324.    {
  325.       boolean beep = TRUE;
  326.  
  327.       while (safepeek())      /* Yes --> While character in buffer   */
  328.       {
  329.          if (safein() == '\033') /* Look for ESC                     */
  330.             raise( SIGINT );     /* Yes --> eject via std exit       */
  331.          else if ( beep )
  332.          {
  333.              putchar('\a');      /* No --> Complain to user          */
  334.              beep = FALSE;       /* But be nice about it ...
  335.                                     only once per pass through here  */
  336.          } /* else if ( beep ) */
  337.       } /* while */
  338.  
  339.    } /* if (bflag[F_ESCAPE]) */
  340.  
  341. #endif /* _Windows */
  342.  
  343. /*--------------------------------------------------------------------*/
  344. /*                          Now do the wait                           */
  345. /*--------------------------------------------------------------------*/
  346.  
  347. /*--------------------------------------------------------------------*/
  348. /*                          Windows/NT wait                           */
  349. /*--------------------------------------------------------------------*/
  350.  
  351. #ifdef WIN32
  352.    Sleep(milliseconds);
  353.  
  354. /*--------------------------------------------------------------------*/
  355. /*                             OS/2 wait                              */
  356. /*--------------------------------------------------------------------*/
  357.  
  358. #elif FAMILYAPI
  359.    result = DosSleep(milliseconds);
  360.    if (result != 0)
  361.       panic();
  362. #else
  363.  
  364. /*--------------------------------------------------------------------*/
  365. /*                            MS-DOS wait                             */
  366. /*--------------------------------------------------------------------*/
  367.  
  368. #ifndef _Windows
  369.  
  370. #ifdef __TURBOC__
  371.    enable();
  372. #else
  373.    _enable();
  374. #endif
  375.  
  376. #endif
  377.  
  378. /*--------------------------------------------------------------------*/
  379. /*       Handle the special case of 0 delay, which is simply a        */
  380. /*                  request to give up our timeslice                  */
  381. /*--------------------------------------------------------------------*/
  382.  
  383.    if (milliseconds == 0)     /* Make it compatible with DosSleep    */
  384.    {
  385.  
  386. #ifdef _Windows
  387.       WindowsDelay( milliseconds );
  388. #else
  389.  
  390.       if (RunningUnderWindows())
  391.          WinGiveUpTimeSlice( );
  392.       else if (RunningUnderDesqview())
  393.          DVGiveUpTimeSlice();
  394.  
  395. #endif
  396.       return;
  397.    } /* if */
  398.  
  399.    ftime(&t);                 /* Get a starting time                 */
  400.    last = t.millitm;          /* Save milliseconds portion           */
  401.    seconds = t.time;          /* Save seconds as well                */
  402.  
  403.    while( milliseconds > 0)   /* Begin the spin loop                 */
  404.    {
  405.  
  406. #ifdef _Windows
  407.  
  408.       WindowsDelay( milliseconds );
  409.  
  410. #else
  411.       if (RunningUnderWindows())
  412.          WinGiveUpTimeSlice();
  413.       else if (RunningUnderDesqview())
  414.          DVGiveUpTimeSlice();
  415.       else {
  416.  
  417. #ifdef __TURBOC__
  418.  
  419.          delay( milliseconds );
  420.  
  421. #else
  422.  
  423.          int volatile count;  /* Don't let compiler optimize this    */
  424.          for ( count = 0; count < 2400; count ++);
  425.                               /* We spin so that interrupts are
  426.                                  enabled for most of the loop        */
  427. #endif
  428.  
  429.       } /* else */
  430. #endif /* _Windows */
  431.  
  432.       ftime(&t);              /* Take a new time check               */
  433.  
  434.       if (t.time == seconds)  /* Same second as last pass?           */
  435.          milliseconds -= (t.millitm - last); /* Yes --> mSecond delta*/
  436.       else
  437.          milliseconds -= 1000 * (int) (t.time - seconds)
  438.                               - (last - t.millitm);
  439.                               /* No --> Handle wrap of mSeconds      */
  440.  
  441.       last = t.millitm;       /* Update last tick indicator          */
  442.       seconds = t.time;       /* Update this as well; only needed if
  443.                                  it changed (see above), but it
  444.                                  kills time (which is our job)       */
  445.    } /* while */
  446.  
  447. #endif /* FAMILYAPI */
  448.  
  449. } /* ddelay */
  450.