3]*********************************************************************
3]*                                                                   *
3]*                      Smart Input Routines                         *
3]*                                                                   *
3]*                       Author: Jim Shields                         *
3]*                         December, 1988                            *
3]*                                                                   *
3]*        Send questions, suggestions, flames, and cookies to:       *
3]*                                                                   *
3]*                        PLink: RATKING                             *
3]*                   CompuServe: 72777,3265                          *
3]*                                                                   *
3]*********************************************************************





'*********************************************************************
'*
'*    SetDefaults: Set up default values
'*

SetDefaults:

  AutoAdvance% = FALSE%
  RightJustify = FALSE%
  MandEntry%   = FALSE%
  MandFill%    = FALSE%
  Separator$   = "_"
  OKChars$     = ""
  Default$     = ""
  HighValue$   = ""
  LowValue$    = ""
  DiscValue%   = FALSE%
  FOR I = 1 TO 30: DiscValues$(I) = "": NEXT I

RETURN







'*********************************************************************
'*
'*    GetKeyStroke:  Get a single keystroke
'*



GetKeyStroke:


 ALoop:
   a$ = ""
   WHILE a$ = ""
     a$=INKEY$
   WEND
   IF OKChars$ <> "" THEN
     IF (INSTR(OKChars$,a$) = 0) AND (INSTR(SpecialChars$,a$) = 0) THEN BEEP: GOTO ALoop
   END IF

' Got a valid keystroke; return

 RetKey$ = a$
 KeyValue% = ASC(RetKey$)
 SpecialKey% = (INSTR(SpecialChars$,a$) <> 0)

RETURN




'*********************************************************************
'*
'*    GetYN: Get a yes/no answer
'*

GetYN:

  LOCATE InitialY%, InitialX%
  Res$ = ""

  IF Default$ = "" THEN
    PRINT LEFT$(Separator$,1);
  ELSE
    PRINT LEFT$(Default$,1);
  END IF

  LOCATE InitialY%, InitialX%
  OKChars$ = SpecialChars$+"YyNn"

  GOSUB GetKeyStroke

  IF SpecialKey% AND KeyValue%<>13 THEN RETURN

  IF KeyValue% = 13 AND Default$ = "" THEN BEEP:GOTO GetYN
  IF KeyValue% = 13 THEN Res$ = Default$

  IF Res$ = "" THEN Res$ = RetKey$

  ReturnString$ = Res$
  YResponse% = INSTR("Yy",Res$) <> 0

RETURN






'*********************************************************************
'*
'*    GetString: Get a string
'*


GetString:

 'get a string

 ' Set up:

 R = InitialY%
 IF RightJustify% THEN C = InitialX%+Length% ELSE C = InitialX%
 StrLen = 0

 KeyValue% = 0:
 Res$ = ""
 LOCATE InitialY%,InitialX%
 FOR a=1 TO Length%
   PRINT LEFT$(Separator$,1);
 NEXT a

 IF Default$ <> "" THEN
   IF RightJustify% THEN
     LOCATE R,C-LEN(Default$)
     C = C-LEN(Default$)
     PRINT Default$;
   ELSE
     LOCATE R,C
     PRINT Default$;
     C = C+LEN(Default$)
   END IF
   StrLen = LEN(Default$)
   Res$ = Default$
 END IF


 GLoop:

 WHILE (KeyValue%<> 13) AND (StrLen <= Length%)

 LoopTop:

   LOCATE R,C
   GOSUB GetKeyStroke

   ' Process backspace:


   IF KeyValue% <> 8 THEN CheckRet
   IF StrLen=0 THEN EndGLoop

   IF NOT RightJustify% THEN
     StrLen = StrLen-1
     C = C-1
     Res$ = LEFT$(Res$,StrLen)
     LOCATE R,C
     PRINT LEFT$(Separator$,1);
     GOTO EndGLoop
   ELSE
     LOCATE R,C
     PRINT LEFT$(Separator$,1);
     StrLen = StrLen-1
     C = C+1
     Res$ = LEFT$(Res$,StrLen)
     LOCATE R,InitialX%+(Length%-StrLen)
     PRINT Res$;
     GOTO EndGLoop
   END IF

   ' Process <return>:

   CheckRet:
   IF KeyValue%=13 THEN
      IF MandEntry% AND StrLen = 0 AND Default$ = "" THEN
      DisplayError(MandEntryErr!)
      KeyValue% = 0
      GOTO LoopTop
      END IF

      IF MandFill% AND StrLen <> Length% AND Default$ = "" THEN
      DisplayError(MandFillErr!)
      KeyValue% = 0
      GOTO LoopTop
      END IF

   END IF



   'Process other special keys (just return)

   SpecKey:
   IF SpecialKey% THEN EndGetString

   IF StrLen < Length% THEN
     Res$ = Res$+RetKey$
     IF RightJustify% THEN
       C = C-1
       LOCATE R,C
       PRINT Res$
     ELSE
       PRINT RetKey$;
       C = C+1
     END IF
     StrLen = StrLen+1

   ELSE
      BEEP
   END IF

   IF StrLen = Length% AND AutoAdvance% THEN EndGetString

 EndGLoop:
 WEND

 EndGetString:

 'Check range

 IF HighValue$<>"" OR LowValue$ <> "" THEN
   IF Res$ > HighValue$ THEN
     DisplayError(RangeHiErr!)
     GOTO GetString
   END IF
   IF Res$ < LowValue$ THEN
     DisplayError(RangeLowErr!)
     GOTO GetString
   END IF
 END IF

 'Check for discrete values

 IF DiscValue% THEN
 ValueOK% = FALSE

   FOR I = 1 TO 30
     IF DiscValues$(I) <> "" THEN
       IF LEFT$(DiscValues$(I),Length%) = LEFT$(Res$,Length%) THEN
         ValueOK% = TRUE%
       END IF
     END IF
   NEXT I

   IF NOT ValueOK% THEN
     DisplayError(DiscValErr!)
     GOTO GetString
   END IF

 END IF

 ReturnString$ = Res$
 RETURN




'*********************************************************************
'*
'*    GetNumber: Get a numeric value
'*


GetNumber:

 ' Set up:

 R = InitialY%
 IF RightJustify% THEN C = InitialX%+Length% ELSE C = InitialX%
 StrLen = 0
 OKChars$ = SpecialChars$ + "0123456789-"
 IF DecPos% > 0 THEN OKChars$ = OKChars$ + "."
 GotDecimal = FALSE%
 KeyValue% = 0
 Res$ = ""

 LOCATE InitialY%,InitialX%
 FOR a=1 TO Length%
   PRINT LEFT$(Separator$,1);
 NEXT a

 IF Default$ <> "" THEN
   IF RightJustify% THEN
     LOCATE R,C-LEN(Default$)
     C = C-LEN(Default$)
     PRINT Default$;
   ELSE
     LOCATE R,C
     PRINT Default$;
     C = C+LEN(Default$)
   END IF
   StrLen = LEN(Default$)
   Res$ = Default$
 END IF


 NGLoop:

 WHILE (KeyValue%<> 13) AND (StrLen <= Length%)

 NLoopTop:

   LOCATE R,C
   GOSUB GetKeyStroke

   ' Process backspace:


   IF KeyValue% <> 8 THEN NCheckRet
   IF StrLen=0 THEN NEndGLoop

   IF Right%(Res$,1) = "." THEN GotDecimal% = FALSE%

   IF NOT RightJustify% THEN
     StrLen = StrLen-1
     C = C-1
     Res$ = LEFT$(Res$,StrLen)
     LOCATE R,C
     PRINT LEFT$(Separator$,1);
     GOTO NEndGLoop
   ELSE
     LOCATE R,C
     PRINT LEFT$(Separator$,1);
     StrLen = StrLen-1
     C = C+1
     Res$ = LEFT$(Res$,StrLen)
     LOCATE R,InitialX%+(Length%-StrLen)
     PRINT Res$;
     GOTO NEndGLoop
   END IF

   ' Process <return>:

   NCheckRet:

   IF KeyValue%=13 THEN
      IF MandEntry% AND StrLen = 0 AND Default$ = "" THEN
      DisplayError(MandEntryErr!)
      KeyValue% = 0
      GOTO NLoopTop
      END IF

      IF MandFill% AND StrLen <> Length% AND Default$ = "" THEN
      DisplayError(MandFillErr!)
      KeyValue% = 0
      GOTO NLoopTop
      END IF

   END IF



   'Process other special keys (just return)

   NSpecKey:
   IF SpecialKey% THEN NEndGetString

' Check for more than one Decimal point:

  IF RetKey$ = "." THEN
    IF Length% = 0 THEN BEEP: GOTO NEndGLoop
    IF GotDecimal% THEN BEEP: GOTO NEndGLoop
  END IF

' Finally!  Process a valid keystroke

   IF StrLen < Length% THEN
     Res$ = Res$+RetKey$
     IF RightJustify% THEN
       C = C-1
       LOCATE R,C
       PRINT Res$
     ELSE
       PRINT RetKey$;
       C = C+1
     END IF
     StrLen = StrLen+1

   ELSE
      BEEP
   END IF

   IF StrLen = Length% AND AutoAdvance% THEN NEndGetString

 NEndGLoop:
 WEND

 NEndGetString:

 'Check range

 IF HighValue$<>"" OR LowValue$ <> "" THEN
   IF Res$ > HighValue$ THEN
     DisplayError(RangeHiErr!)
     GOTO GetNumber
   END IF
   IF Res$ < LowValue$ THEN
     DisplayError(RangeLowErr!)
     GOTO GetNumber

   END IF
 END IF

 'Check for discrete values

 IF DiscValue% THEN
 ValueOK% = FALSE

   FOR I = 1 TO 30
     IF DiscValues$(I) <> "" THEN
       IF LEFT$(DiscValues$(I),Length%) = LEFT$(Res$,Length%) THEN 
         ValueOK% = TRUE%
       END IF
     END IF
   NEXT I

   IF NOT ValueOK% THEN
     DisplayError(DiscValErr!)
     GOTO GetNumber
   END IF

 END IF

 ReturnString$ = Res$
 RETURN

'*********************************************************************
'*
'*    SetUp : Initialize required variables
'*



SetUp:

  'truth values for comparisons

  TRUE% = (1=1)
  FALSE% = (1=2)

  'Discrete values array

  DIM DiscValues$(30)

  'Specific Error codes:

    MandEntryErr! = 1!       ' Mandatory entry error
    MandFillErr!  = 2!       ' Mandatory fill error
    RangeLowErr!  = 3!       ' Range error: value too low
    RangeHiErr!   = 4!       ' Range error: value too high
    DiscValErr!   = 5!       ' Discrete value error: invalid value

  'Special character strings

  FOR a = 0 TO 31
    SpecialChars$ = SpecialChars$+CHR$(a)
  NEXT a
  FOR a = 127 TO 255
    SpecialChars$ = SpecialChars$+CHR$(a)
  NEXT a

RETURN

'*********************************************************************
'*
'*    DisplayError:  Display Smart Input Errors
'*



SUB DisplayError(Errno!) STATIC

  IF Errno! = 1 THEN er$ = "Error: Field requires value"
  IF Errno! = 2 THEN er$ = "Error: Field must be filled"
  IF Errno! = 3 THEN er$ = "Error: Value too low"
  IF Errno! = 4 THEN er$ = "Error: Value too high"
  IF Errno! = 5 THEN er$ = "Error: Invalid value entered"

  WINDOW 3, er$,(1,186)-(LEN(er$)*8+10,186),16
  p$ = ""
  WHILE p$ = ""
    p$ = INKEY$
  WEND
  WINDOW CLOSE 3
END SUB
