Listing 3 Prompt Function

#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <dos.h>
#include <string.h>
#include "./keys.h"

#ifndef YES
#define YES  1
#endif

#ifndef NO
#define NO   0
#endif

#define M_INSERT    1
#define M_TYPEOVER  2

#define MOVE_CUR(row,col) printf("\x1B[%d;%df",row,col);
#define NORMAL  "\x1B[Om"  /* ANSI Normal  Video */
#define REVERSE "\x1B[7m"  /* ANSI Reverse Video */

/* Prototypes */
extern int match (int, char);
extern void change_cur (int, int);
extern void main (void);

int    key;

int prompt( data, match_ch, min_len, max_len, row, col,
          message, fyi_row, fyi_col)

char  data [];        /* Return Message               */
char  match_ch;       /* Code For Which Characters
                     Are Allowed                  */
int   min_len;        /* Min Length Allowed           */
int   max_len;        /* Max Length Allowed           */
int   row;            /* Window Row                   */
int   col;            /* Window Column                */
char  *message;       /* Prompt Message               */
int   fyi_row;        /* FYI Window Row               */
int   fyi_col;        /* FYI Window Column            */
{
   char  buf [80];
   int   terminate;  /* Key That Caused Termination  */
   int   index,i;    /* General Index Variables      */
   int   mode;       /* Mode: INSERT or TYPEOVER     */
   int   changed;    /* Changed Flag: 1=YES, 0=NO    */
   int   edit;       /* Edit Flag:    1=YES, 0NO     */
   int   frst_key;   /* First Key Flag: 1=YES, 0=NO  */
   char  more;       /* YES/NO Flag . . .
                     Used  To Terminate Input    */

   /* Initializations */
   edit      = NO;
   frst_key  = NO;
   changed   = NO;

   mode = M_TYPEOVER;
   change_cur(0, 13); /* Set Cursor To Block Mode    */

   /* Display The FYI Message At The FYI Row, Colunn */
   if (strlen(message)) {
      MOVE_CUR (fyi_row, fyi_col);
      printf(message);
   }

   printf(REVERSE);    /* Change To Reverse Video   */

   strcpy(buf, data);  /* Make A Copy Of The Default
                      Return Value              */

   for (index = strlen(buf); index < max_len; ++index) {
      buf [index] = ' ';  /* Fill Remainder Of Default
                         Value With Blanks   */
   } 
   buf [index] = '\0';

   /* Display Default Value For Field  */
   MOVE_CUR (row, col);
   printf(buf);

   /* Position Cursor At Beginning Of Field  */
   MOVE_CUR (row, col);

   /* Get Input From User */
   for (index = 0,more = YES; more; )  {
      key = getch();
      if (key == 0)
         key = getch()+256;

      switch(key) (
      case C_F1        : /* F1 Key        */
      case C_F2        : /* F2 Key        */
      case C_F3        : /* F3 Key        */
      case C_F4        : /* F4 Key        */
      case C_F5        : /* F4 Key        */
      case C_F6        : /* F6 Key        */
      case C_F7        : /* F7 Key        */
      case C_F8        : /* F8 Key        */
      case C_F9        : /* F9 Key        */
      case C_F10       : /* F0 Key        */
      case C_F11       : /* F11 Key       */
      case C_F12       : /* F12 Key       */
      case C_ESC       : /* ESCAPE Key    */
          frst_key = NO;
          terminate = key;
          buf[index] = '\0';
          more = NO;
          break;
      case C_INS :  /* INSERT Key       */
          frst_key = NO;
          if (mode == M_INSERT) {
             /* Set The Mode To TYPEOVER and
                Change Cursor To Block Mode  */
             mode = M_TYPEOVER;
             change_cur(0, 13);
          }
          else {
             /* Set The Mode To INSERT And
                Change Cursor To Underline   */
             mode = M_INSERT;
             change_cur(12, 13);
          }
          putchar(bur[index]);
          MOVE_CUR(row, (col + index));
          break;

      case C_BACK : /* BACKSPACE Key  */
      case C_DEL  : /* DELETE Key     */
          frst_key = NO;
          changed = YES;
          if (index >= max_len)
             index = max_len - 1;
          for (i = index; i < max_len; i++) {
             if (buf[i+1] == '\0')
                buf[i] = ' ';
             else
                buf[i] = buf[i+1];
          }

          /* Redisplay The Field */
          MOVE_CUR(row, col);
          printf(buf);

          /* Reposition The Cursor. */
          MOVE_CUR(row, (col + index));
          putchar(buf[index]);
          MOVE_CUR(row, (col + index));

          if (key == C_DEL)
             break;

      case C_LEFT : /* LEFT ARROW    */
          first_key = NO;
          if (index <= 0)
             break;
          if (index >= max_len)
             index = max_len -1;
          index--;
          MOVE_CUR(row, (col + index));
          break;

      case C_RIGHT: /* RIGHT ARROW    */
          frst_key = NO;
          edit = YES;
          if (index >= (max_len - 1))
             break;
          index++;
          MOVE_CUR(row, (col + index));
          break;

      case C_HOME : /* HOME KEY  */
      case C_END : /* END KEY   */
          frst_key = NO;
          if (edit == YES) {
             if (key == C_END)
                index = end_of_fld(buf,(strlen(buf)));
             else
                index = 0;
             MOVE_CUR(row, (col + index));
             break;
          }

      case C_DOWN : /* DOWN ARROW       */
      case C_UP   : /* UP ARROW         */
      case C_PGDN : /* PAGE DOWN        */
      case C_PGUP : /* PAGE UP          */
      case C_CR   : /* CARRIAGE RETURN  */
      case C_TAB  : /* TAB    Key       */

          frst_key = NO;

          /* Reset Mode and Edit Flag */
          edit = NO;
          mode = M_INSERT;

          if (strlen(data) >= (unsigned)min_len &&
              index == 0 && changed == NO) {
             /* If The User Has Not Changed The Value Of
                The Data Field, Return The Appropriate
                NO CHANGE Key For The terminating Key
                That Was Pressed. */

             if (key == C_CR) {
              /* Return No Change For Carriage Return  */
                terminate = CR_NO_CHG;
             }
             if (key == C_UP) {
                /* Return No Change For Up Arrow      */
                terminate = UP_NO_CHG;
             }
             if (key == C_DOWN) {
                /* Return No Change For Down Arrow */
                terminate = DN_NO_CHG;
             }
             if (key == C_TAB) {
                /* Return No Change For Tab Key    */
                terminate = TB_NO_CHG;
             }
             if (key  !=  C_CR    &&
                key      !=  C_UP    &&
                key      !=  C_DOWN  &&
                key      !=  C_TAB) terminate = key;

             strcpy(buf, data);

             more = NO;
             break;
          }

          /* If Minimum Length Requirement Has been Met,
             Quit */
          if (index >= min_len) {
             terminate = key;
             more = NO;
             break;
          }

          /* Else Ignore */
          break;

      default     :
          if (index == max_len)
             /* At End Of Data Field - Do Nothing */
             break;

          /* We Have Dealt With All Of The Keys That We
             Needed Above, So Now We Will Filter Out All
             Keys And Characters Above 122 (z) Here. */

          if (key > 'z')               /* Ignore Key */
             break;

          if (match(index, match_ch) == YES) {
             /* Only Accept The User Entered Character
                If It Successfully Passed The match
                function. */
             edit    = YES;
             changed = YES;

             if (frst_key == YES) {
                /* If This Is The First Valid Key That
                   The User Has Entered, Then Wipe Out
                   The Field. */
                for (i = 0; i < max_len; i++)
                   buf[i] = ' ';
                frst_key = NO;
             }

             if (mode == M_INSERT) {
                /* Insert The User Entered Character
                   Into The Field */
                for (i = (max_len - 1); i > index; i--)
                   buf[i] = buf[i-1];
             }

             /* Overwrite The Buffer With The User
                Entered Character */
             buf[index] = (char)key;

             /* Redisplay The Field */
             MOVE_CUR(row, col);
             printf(buf);

             /* Reposition The Cursor. */
             index++;
             if (index >= max_len)
                index --;
             MOVE_CUR(row, (col + index));
             putchar(buf[index]);
             MOVE_CUR(row, (col + index));
          }
          break;
      }
   }
   /* Redraw The Field In The Window's Normal
      Color Attribute */
   printf(NORMAL);
   MOVE_CUR (row, col);
   printf(buf);

   strcpy(data, buf);
   data[(end_of_fld(data,(strlen(data))) + 1)] = '\0';

   /* Change Cursor Back To Underline */
   change_cur(12, 13);
   return (terminate);
}

static int match(index,match_ch)
int index;
char match_ch;
{
   int matches = YES;

   switch (match_ch) {
   case '$' : /* 0-9 or ,$. */
       if (!isdigit(key) && !strchr(".,$",key))
          matches = NO;
       break;

   case '#' : /* 0 - 9 */
       if (!isdigit(key))
          matches = NO;
       break;

   case 'A' : /* A - Z */
       if (!isalpha(key) && !strchr(" ",key))
          matches = NO;
       break;

   case 'D' : /* Date: 0-9 or - or / or .*/
       if (!isdigit(key) && !strchr(".-*/",key))
          matches = NO;
       break;

   case 'l' : /* a-z, A-Z, 0-9, or ;:.,/?*-$#()'! or leading space */
       if (!isalnum(key) &&
           !strchr(" !@#$%^&*()-_=+[{]}';:.,/?",key))
          matches = NO;
       break;

   case 'Q' : /* YyNn as Reply To Yes/No Question */
       if (!strchr("YyNn",key))
          matches = NO;
       key = toupper(key);
       break;

   case 'S' : /* 0-9 or + or - */
       if (!isdigit(key) && !strchr("+-",key))
          matches = NO;
       break;

   case 'T' : /* Time: 0-9 or . or : */
       if (!isdigit(key) && !strchr(".:",key))
          matches = NO;
       break;

   case 'X' : /* MmFf As Reply To Male/Female */
       if (!strchr("MmFf",key))
          matches = NO;
       key = toupper(key);
       break;

   default :
       matches = NO;
       break;
   }
   return (matches);
}

/* This Function Will Return A 0 Based Index Of The
   First Non-Blank Character At The End Of A String. */
int end_of_fld(string, length)
char *string;
int length;
{
   int  i;

   for (i = length - 1; i >= 0; i--) {
      if (string[i] != ' ' && string[i] != '\0')
         return(i);
   }
   return(0);
}

/* This Function Will Change The Appearance Of The
   Cursor To A Block Or An Underscore */
void change_cur(start, end)
int start;
int end;
{
   union REGS r;

   r.h.ah = 1;
   r.h.ch = start;
   r.h.cl = end;
   int86(0x10, &r, &r);
}

/* End of File */