/* nap.c */

#include "header.h"

#ifdef __MSDOS__
# include <dos.h>
#endif

/*
 *	routine to take a nap for n milliseconds
 */
nap(x)
register int x;
{
	if (x<=0) return; /* eliminate chance for infinite loop */
	lflush();
	if (x > 999) 
	  sleep(x/1000); 
#ifndef M_XENIX			/* Xenix does not have times() */
	else 
	  napms(x);
#endif /* M_XENIX */
}

#ifdef SYSV
#ifndef M_XENIX
/*	napms - sleep for time milliseconds - uses times() */
/* this assumes that times returns a relative time in 60ths of a second */
/* this will do horrible things if your times() returns seconds! */
napms(time)
int time;
{
	long matchclock, times();
	struct tms stats;

	if (time<=0) time=1; /* eliminate chance for infinite loop */
	if ((matchclock = times(&stats)) == -1 || matchclock == 0)
	  return;	/* error, or BSD style times() */
	matchclock += (time / 17); /*17 ms/tic is 1000 ms/sec / 60 tics/sec */
	while(matchclock > times(&stats))
		;
}
#endif /* M_XENIX */

#else /* not SYSV */
#  ifdef BSD
#    ifdef SIGVTALRM
       /* This must be BSD 4.2!  */
#      define bit(_a) (1<<((_a)-1))
nullf()
{ }

/*	napms - sleep for time milliseconds - uses setitimer() */
napms(time)
int time;
{
	struct itimerval    timeout;
	int     (*oldhandler) ();
	int     oldsig;

	if (time <= 0) return;

	timerclear(&timeout.it_interval);
	timeout.it_value.tv_sec = time / 1000;
	timeout.it_value.tv_usec = (time % 1000) * 1000;

	oldsig = sigblock(bit(SIGALRM));
	setitimer(ITIMER_REAL, &timeout, (struct itimerval *)0);
	oldhandler = signal(SIGALRM, nullf);
	sigpause(oldsig);
	signal(SIGALRM, oldhandler);
	sigsetmask(oldsig);
}

#    else /* SIGVTALARM */
/*	napms - sleep for time milliseconds - uses ftime() */

napms(time)
int time;
{
	/* assumed to be BSD UNIX */
	struct timeb _gtime;
	time_t matchtime;
	unsigned short matchmilli;
	register struct timeb *tp = & _gtime;

	if (time <= 0) return;
	ftime(tp);
	matchmilli = tp->millitm + time;
	matchtime  = tp->time;
	while (matchmilli >= 1000) {
	  ++matchtime;
	  matchmilli -= 1000;
	}

	while(1) {
	  ftime(tp);
	  if ((tp->time > matchtime) ||
	      ((tp->time == matchtime) && (tp->millitm >= matchmilli)))
	    break;
	}
}
#    endif /* SIGVTALARAM */
#  else
#   ifdef __MSDOS__

napms(zzz)
int zzz;
{
  time_t targ_time, t;
  int targ_hund;
  struct time tm;

  time(&targ_time);
  gettime(&tm);
  targ_hund = tm.ti_hund + zzz/10;

  while (targ_hund >= 100) {
    targ_hund -= 100;
    ++targ_time;
  }

  do {
    time(&t);
  } while (t < targ_time);

  do {
    gettime(&tm);
  } while (tm.ti_hund < targ_hund);
}

#   else

napms(time) 
int time; 
{
}	/* do nothing, forget it */
#   endif /* __MSDOS__ */
#  endif /* BSD */
#endif /* SYSV */
