/*******************************************************************************
**      userio.c -- Tattletale Model 8 User I/O Interface Functions
**
**      Copyright (C) 1991-94 ONSET Computer Corp.  --jhg               All rights reserved.
**
**      Saturday, January 26, 1991
*******************************************************************************/

#ifndef PRECOMPHDRS
#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>

#include	<cfxbios.h>		// Persistor BIOS and I/O Definitions
#include	<cfxpico.h>		// Persistor PicoDOS Definitions
//#include        <TT8lib.h>
#include        <userio.h>
#endif

#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 *\
*******************************************************************************/
short QueryDateTime(ptr prompt, short 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, (short) sizeof(buf)))
                        return (FALSE);

                if (! *buf)                     /* just return keyed */
                        strcpy(buf, def);       /* copy default and fall through */

                /* *c is NULL ptr for the "/" and ":" seperators */
                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 month 0 - 11 */
                        if(tm->tm_year >= 2000)
                           tm->tm_year = (tm->tm_year - 2000) + 100;
                        else
                           tm->tm_year = (tm->tm_year - 1900);
                        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
*******************************************************************************/
short QueryYesNo(ptr prompt, short 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 ((short) (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.
**      
*******************************************************************************/
short QueryChar(ptr prompt, short defChar, ptr scanSet, char *reply)
        {
        char    c, buf[2];
        short   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, (short) 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.
*******************************************************************************/
short 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, (short) 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() */


/*******************************************************************************
**      QueryFloat              Query user for a float 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. "%f", "%e" )
**              2. carriage return is not echoed.
*******************************************************************************/
short QueryFloat(ptr prompt, ptr defFmt, ptr scanFmt, float *value)
        {
        char    buf[20];

        while (1)
                {
                printf(prompt);
                if (defFmt)
                        if (*defFmt)
                                {
                                printf(" [");
                                printf(defFmt, *value);
                                printf("]");
                                }
                printf(" ? ");

                if (! InputLine(buf, (short) 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 */
                }

        }       /* QueryFloat() */


/*******************************************************************************
**      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
**      
*******************************************************************************/
short InputLine(ptr linebuf, short linelen)
        {
        short                   i;
        char                    ch;
        char                    *bufptr = linebuf;
        
        while (1)
                {
                fflush(stdout);
//                i = SerTimedGetByte(30000L);    //30sec timeout
                i = SCIRxGetCharWithTimeout(30000L);    //30sec timeout
                if(i == -1){
                  printf("\n\nInput Timeout!\n");
                  return(FALSE);
                  }
                else
                  ch = (char) i;
                switch (ch)
                        {
                        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.
*******************************************************************************/
short kbhit()
        {
        
//        return (SerByteAvail());
        return (SCIRxQueuedCount());
        }       /* kbhit() */


/*******************************************************************************
**      kbflush         Flush any keyboard characters pending and return TRUE if any
**                              were available.
*******************************************************************************/
short kbflush()
        {
        short   avail = kbhit();
        
        while (kbhit())
//                SerGetByte();
		        SCIRxGetChar();
                
        return (avail);
        
        }       /* kbflush() */

