/*******************************************************************************
**	tt7pcio.c -- Tattletale Model-7 User I/O Interface Functions
**
**	Copyright (C) 1991 ONSET Computer Corp.  --jhg		All rights reserved.
**
**      Modified for PC compatability 12-1-93  --rcg
	These functions are located in the TT7 library and must
	be compiled and linked with TurboC to allow the PC simulation to run.
*******************************************************************************/

/* In \tc\include */
#include	<ctype.h>
#include	<setjmp.h>
#include	<signal.h>
#include	<stdarg.h>
#include	<stddef.h>
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<time.h>

/* In \az68\include\tt7 */
#include	<TT7.h>
#include	<serio.h>
#include	<userio.h>


#define	ABORT		0x03
#define	BKSP		0x08
#define	REDISP		0x12
#define	RESTRT		0x15


/*******************************************************************************
**	QueryDateTime		Query user for the Date and Time
**	
**	Return TRUE for all replies except ctrl-C.  Print prompt string (verbatim)
**	followed by the default reply (either the current system calander time if
**	defTime is TRUE or the calander time contained in the tm structure.
**	Returns result in struct tm, but does not set the system clock.
**	
**	NOTES:
**		1.	carriage return is not echoed.
**		2.	ctrl-C always return FALSE
**		3.	input format is compatable with CrossCut's Paste Time & Date (cmd-D)
**	
**	Typical Usage:
**		struct tm 	t;
**		if (! QueryDateTime("\nCurrent Date and Time", TRUE, &t))
**			... error processing for ctrl-C ...
**		SetTimeTM(&t, NULL);	\* set the system time *\
*******************************************************************************/
bool QueryDateTime(ptr prompt, bool defTime, struct tm *tm)
	{
	char		buf[40];
	char		def[40];
	time_t		secs;
	
	while (1)
		{
		printf(prompt);
		if (defTime)
			secs = time(NULL);
		else
			secs = mktime(tm);
			
		strftime(def, sizeof(def), "%m/%d/%y %H:%M:%S", localtime(&secs));
		
		printf(" [%s] ? ", def);

		if (! InputLine(buf, sizeof(buf)))
			return (FALSE);

		if (! *buf)			/* just return keyed */
			strcpy(buf, def);	/* copy default and fall through */

		if (sscanf(buf, "%d%*c%d%*c%d%*c%d%*c%d%*c%d",
			&tm->tm_mon, &tm->tm_mday, &tm->tm_year,
			&tm->tm_hour, &tm->tm_min, &tm->tm_sec));
			{
			tm->tm_mon--;		/* adjust to c's 0 - 11 */
			return (TRUE);
			}
			
		if (*prompt != '\n')
			putchar('\n');	/* reprompt and try again */
		}
	
		return (TRUE);

	}	/* QueryDateTime() */


/*******************************************************************************
**	QueryYesNo		Query user for a yes or no reply.
**	
**	Return TRUE only for a Yes reply (which may be return only default if defYes
**	is TRUE).  Print prompt string (verbatim) followed by (Yes/No) followed by
**	default reply character inside square brackets, followed by a question mark.
**	
**	NOTES:
**		1.	carriage return is not echoed.
**		2.	ctrl-C always return FALSE
*******************************************************************************/
bool QueryYesNo(ptr prompt, bool defYes)
	{
	char	reply;
	char	buf[100];
	
	strncpy(buf, prompt, sizeof(buf) - 10);
	strcat(buf, " (Yes/No)");
	if (! QueryChar(buf, defYes ? 'Y' : 'N', "YN", &reply))
		return (FALSE);
	return (reply == 'Y');
	
	}	/* QueryYesNo() */


/*******************************************************************************
**	QueryChar		Query user for a character reply.
**	
**	Return TRUE for all replies except ctrl-C.  Print prompt string (verbatim)
**	followed by optional default character inside square brackets, followed by
**	a question mark.  Return default character if just return pressed, otherwise
**	scan reply accepting only characters from scanSet.
**	
**	NOTES:
**		1.	carriage return is not echoed.
**		2. 	If the scanSet contains no lower case characters, the input will be
**			converted to upper case.
**		3.	Same as 2 but opposite case sense.
**	
*******************************************************************************/
bool QueryChar(ptr prompt, char defChar, ptr scanSet, char *reply)
	{
	char	c, buf[2];
	bool	forceUpper = FALSE, forceLower = FALSE;
	ptr		pss = scanSet;
	
	if (scanSet)
		{
		forceUpper = forceLower = TRUE;
		while (c = *pss++)
			if (isupper(c))
				forceLower = FALSE;
			else if (islower(c))
				forceUpper = FALSE;
		}

	while (1)
		{
		printf(prompt);
		if (defChar)
			printf(" [%c]", *reply = defChar);
		printf(" ? ");

		if (! InputLine(buf, sizeof(buf)))
			return (FALSE);

		if ((! *buf) && defChar)
			return (TRUE);

		if (forceUpper)
			*reply = toupper(*buf);
		else if (forceLower)
			*reply = tolower(*buf);
		else
			*reply = *buf;

		if (scanSet)
			if (strchr(scanSet, *reply))
				return (TRUE);

		if (*prompt != '\n')
			putchar('\n');	/* reprompt and try again */
		}

	}	/* QueryChar() */



/*******************************************************************************
**	QueryNum		Query user for a numeric value.
**	
**	Return TRUE for all replies except ctrl-C.  Print prompt string (verbatim)
**	followed by optional default value (if defFmt in non-NULL and not a NULL
**	string) inside square brackets, followed by a question mark.  Return default
**	value if just return pressed, otherwise scan reply using scanFmt string.
**	
**	NOTES:
**		1. defFmt and scanFmt are scanf specifiers (e.g. "%ld", "lu", "%lx")
**		2. carriage return is not echoed.
*******************************************************************************/
bool QueryNum(ptr prompt, ptr defFmt, ptr scanFmt, ulong *value)
	{
	char	buf[20];
	
	while (1)
		{
		printf(prompt);
		if (defFmt)
			if (*defFmt)
				{
				printf(" [");
				printf(defFmt, *value);
				printf("]");
				}
		printf(" ? ");

		if (! InputLine(buf, sizeof(buf)))
			return (FALSE);

		if (! *buf)			/* just return keyed */
			return (TRUE);

		if (sscanf(buf, scanFmt, value))
			return (TRUE);

		if (*prompt != '\n')
			putchar('\n');	/* reprompt and try again */
		}

	}	/* QueryNum() */


/*******************************************************************************
**	InputLine		Input line from keyboard with minimal editing features
**	
**	Returns TRUE for all input except ctrl-C and returs NULL terminated string
**	in buffer.  Does not echo or include the terminating return character.
**	
**	Typical Usage:
**		char	myline[40];
**		if (! InputLine(myline, sizeof(myline)))
**			... error processing for ctrl-C ...
**	
**	
**	Edit Commands:
**		ctrl-C 0x03		cancel operation, return FALSE
**		ctrl-H 0x08		backspace and erase
**		ctrl-R 0x12		re-display current line
**		ctrl-U 0x15		clear line and start again
**	
*******************************************************************************/
bool InputLine(ptr linebuf, short linelen)
	{
	short			i;
	char			ch;
	char			*bufptr = linebuf;
	
	while (1)
		{
		switch (ch = getchar())
			{
			case '\r' :
			case '\n' :
				*bufptr = '\0';
				return (TRUE);
				
			case BKSP :
				if (bufptr > linebuf)
					{
					bufptr--;
					putchar(BKSP);
					}
				break;

			case '\0' :
			case ABORT :
				*linebuf = '\0';
				return (FALSE);

			case REDISP :
				putchar('\n');
				for (i = 0; &linebuf[i] < bufptr; i++)
					putchar(linebuf[i]);
				break;

			case RESTRT :
				while (bufptr > linebuf)
					{
					bufptr--;
					putchar(BKSP);
					}
				break;

				*linebuf = '\0';
				return (FALSE);

			default :
				if (bufptr < linebuf + linelen-1)
					{
					*bufptr++ = ch;
					putchar(ch);
					}
				else
					{
					bufptr[-1] = ch;
					putchar(BKSP);
					putchar(ch);
					}
				break;
			}
		}
	
	}	/* InputLine() */


/*******************************************************************************
**	kbhit		Return TRUE if keyboard character available.
*******************************************************************************/


/*******************************************************************************
**	kbflush		Flush any keyboard characters pending and return TRUE if any
**				were available.
*******************************************************************************/
bool kbflush(void)             /* Modified for PC compatability */
	{
	return 0;

	}	/* kbflush() */

