/*
 * @(#)timer.c
 *
 * Copyright 2005 - 2013  David A. Bagley, bagleyd AT verizon.net
 *
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear in
 * supporting documentation, and that the name of the author not be
 * used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.
 *
 * This program is distributed in the hope that it will be "useful",
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */

/* Methods file for timer */

#include "timer.h"

#ifndef WINVER
#ifndef HAVE_USLEEP
#if !defined( VMS ) || defined( XVMSUTILS ) || ( __VMS_VER >= 70000000 )
#ifdef USE_XVMSUTILS
#include <X11/unix_time.h>
#endif
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#if HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#endif
#endif
#if defined(SYSV) || defined(SVR4)
#ifdef LESS_THAN_AIX3_2
#include <sys/poll.h>
#else /* !LESS_THAN_AIX3_2 */
#include <poll.h>
#endif /* !LESS_THAN_AIX3_2 */
#endif /* defined(SYSV) || defined(SVR4) */

/* not static in case usleep found in system include */
int
usleep(unsigned int usec)
{
#if (defined (SYSV) || defined(SVR4)) && !defined(__hpux)
#if defined(HAVE_NANOSLEEP)
	{
		struct timespec rqt;

		rqt.tv_nsec = 1000 * (usec % (unsigned int) 1000000);
		rqt.tv_sec = usec / (unsigned int) 1000000;
		return nanosleep(&rqt, NULL);
	}
#else
	(void) poll(
#if defined(__cplusplus) || defined(c_plusplus)
		(pollfd *) /* guess */
#else
		(void *)
#endif
		0, (int) 0, usec / 1000);	/* ms resolution */
#endif
#else
#ifdef __VMS
	long timadr[2];

	if (usec != 0) {
		timadr[0] = -usec * 10;
		timadr[1] = -1;

		sys$setimr(4, &timadr, 0, 0, 0);
		sys$waitfr(4);
	}
#else
	struct timeval time_out;

#if 0
	/* (!defined(AIXV3) && !defined(__hpux)) */
	extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);

#endif

	time_out.tv_usec = usec % (unsigned int) 1000000;
	time_out.tv_sec = usec / (unsigned int) 1000000;
	(void) select(0, (void *) 0, (void *) 0, (void *) 0, &time_out);
#endif
#endif
	return 0;
}
#endif

#if (!defined(WINVER) || (WINVER <= 0x030a)) /* if X or WINDOWS 3.1 or less */
void
Sleep(unsigned int cMilliseconds)
{
#if (defined(WINVER) && (WINVER <= 0x030a))
	unsigned long time_out = GetTickCount() + cMilliseconds;

	while (time_out > GetTickCount());
#else
	(void) usleep(cMilliseconds * 1000);
#endif
}
#endif
#endif

void
useTimer(TimeVal * oldTime, int delay)
{
	int sleepTime;
#ifdef WINVER
	long tv = (long) GetTickCount();

	sleepTime = delay - (tv - (*oldTime));
	*oldTime = tv;
	if (sleepTime > 0) {
		Sleep((unsigned int) sleepTime);
	}
#else
	struct timeval tv;

	(void) X_GETTIMEOFDAY(&tv);
	sleepTime = delay * 1000 -
		((tv.tv_sec - (*oldTime).tv_sec) * 1000000 +
		tv.tv_usec - (*oldTime).tv_usec);
	(*oldTime).tv_sec = tv.tv_sec;
	(*oldTime).tv_usec = tv.tv_usec;
	if (sleepTime > 0) {
		(void) usleep((unsigned int) sleepTime);
	}
#endif
}
