home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / packer / arc / arctool / field.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-09-29  |  32.1 KB  |  980 lines

  1. {
  2.                        F i l e    I n f o r m a t i o n
  3.  
  4. * DESCRIPTION
  5. Author Frank Wood. Turbo Pascal 4.0 unit for coding input screens. The
  6. main function locates fields, allows complete editing, and returns
  7. terminating keystroke. Eight fields types with crash proof data entry and
  8. error messages. Menu pick function also included.
  9.  
  10. * ASSOCIATED FILES
  11. FIELD.PAS
  12. FLDDEMO.PAS
  13. FLDTEST.PAS
  14. OLDDEMO.PAS
  15. FIELD.TXT
  16.  
  17. }
  18. Unit field;
  19.  
  20. { FIELD.PAS was developed by Frank Wood from KEYIN.INC by Michael
  21.   H. Hughes.  This material is hereby placed in the Public Domain. }
  22.  
  23. Interface
  24.  
  25. Uses Crt,Dos;
  26.  
  27. { Values returned by ReadyKey for IBM PC keys }
  28. Const backspacekey =  8;  { Cursor left and erase }
  29.       tabkey       =  9;  { Move to field on right }
  30.       shiftabkey   = 15;  { Move to field on left }
  31.       enterkey     = 13;  { Accept field }
  32.       esckey       = 27;  { Exit screen or program }
  33.       spacekey     = 32;  { Space bar }
  34.  
  35.       extendedkey  =  0;  { Nul returned to indicate an extended key }
  36.       insertkey    = 82;  { Toggle insert mode }
  37.       deletekey    = 83;  { Delete a character }
  38.       homekey      = 71;  { Cursor to first position in field }
  39.       endkey       = 79;  { Cursor to end of entry or accept screen }
  40.       uparrowkey   = 72;  { Move to field above }
  41.       dnarrowkey   = 80;  { Move to field below }
  42.       larrowkey    = 75;  { Cursor left }
  43.       rarrowkey    = 77;  { Cursor right }
  44.  
  45. { Special IBM PC characters used in menu screen. }
  46.       pickpointer = $1A;
  47.       pickmarker  = $FE;
  48.  
  49. { Constants to be used with the Boolean variable required. }
  50.       optional  = False;
  51.       manditory = True;
  52.  
  53. Type  message     = string[70];
  54.       fldtypes    = (alsymb,ascii,caplet,digits,usnint,sgnint,usndec,sgndec);
  55.       cursortypes = (hidden,underline,block);
  56.  
  57. Var firstpass: Boolean;   { Kills tabkey, shiftabkey, uparrowkey, dnarrowkey. }
  58.     reversevideo: Boolean;{ Selects reverse video or markers for field. }
  59.     zerovoid: Boolean;    { A required numerical data entry may not be zero. }
  60.     hitxtcolor: Byte;     { Highlight text color    }
  61.     lotxtcolor: Byte;     { Normal text color       }
  62.     txtbkgnd: Byte;       { Screen background color }
  63.  
  64. { "cursor" hides the cursor or switches between block and underline types. }
  65. Procedure cursor(cursortype: cursortypes);
  66.  
  67. { "note" displays an operator message on line 25 of the screen. }
  68. Procedure note(msg: message);
  69.  
  70. { "errmsg" displays an error message on line 25 of the screen. }
  71. Procedure errmsg(msg: message);
  72.  
  73. { "getkey" waits for a keystroke input and returns its numeric value. }
  74. Function getkey(var specialkey:Boolean): Byte;
  75.  
  76. { "getspecialkey" waits for a special keystroke and returns its numeric value.
  77.   An error message is generated if the operator presses an ordinary key. }
  78. Function getspecialkey: Byte;
  79.  
  80. { "editfield" is the master field input routine.  This function will display a
  81.   string, or an integer or real number at a specified position on the screen,
  82.   will allow the operator to enter or edit the data, and place the edited
  83.   result back in the string, integer or real variable.  Each character is
  84.   checked as it is entered and an error message is displayed for any
  85.   inappropriate keys.
  86.  
  87.   The parameters required are as follows:
  88.  
  89.   col,row  - The column and row position of the field.
  90.  
  91.   fldsize  - The maximum field length in character positions.
  92.  
  93.   decpla   - The number of digits allowed right of the decimal point.
  94.  
  95.   fldtype  - The type of data to be entered, specified as follows:
  96.  
  97.                alsymb - All printable symbols.
  98.                lascii - Lower (standard) ASCII characters only.
  99.                caplet - Upper case letters and other ASCII characters.
  100.                         Shifting is not required; lower case letters are
  101.                         converted to upper-case.
  102.                digits - Digits only processed as an ASCII string.
  103.                unsint - Digits only (unsigned integer).
  104.                sgnint - Digits and minus sign.
  105.                unsdec - Digits and decimal point.
  106.                sgndec - Digits, sign, and decimal point.
  107.  
  108.   required - True if data must be entered in this field.  A zero is not
  109.              accepted for a required field if zerovoid = True.
  110.  
  111.   buffer   - The string, integer or real variable that holds the initial value
  112.              and will receive the final value of the field.  If blank on entry
  113.              the routine will display markers to indicate the length of the
  114.              field, otherwise the current contents are displayed.
  115.  
  116.   editfield- This function returns the value of the keystroke that terminates
  117.              the operation. }
  118.  
  119. Function editfield(col,row,fldsize,decpla: Byte; fldtype: fldtypes;
  120.                    required: Boolean; Var buffer): Byte;
  121.  
  122. { "getpick" allows a field to be expressed as a picklist.  Given an array of
  123.   strings, it will display them as a picklist beginning at the specified column
  124.   and row position on the screen.  The operator may then move a pointer up
  125.   and down the list by pressing "spacekey" or "backspacekey".  Pressing a
  126.   letter key will cause the routine to search for a string beginning with
  127.   that letter, and position the pointer on that item.
  128.  
  129.   The parameters required are as follows:
  130.  
  131.   col,row  - The column and row position of the upper left corner of the menu
  132.              block.  This will be 2 places to the left of the leftmost
  133.              character of the first menu text line.
  134.  
  135.   maxpick  - The number of items or lines in the menu
  136.  
  137.   choice   - The number of the item where the pointer is to be positioned
  138.              when the routine is first called.  If a value of 1 is used, the
  139.              pointer will initially be on the first line of the pick list.
  140.              When the function is terminated with the enterkey, this variable
  141.              will contain the number of the item chosen.
  142.  
  143.   picklist - An array of strings, each having a maximum length of 30
  144.              characters.  The number of strings in the array must at least
  145.              as great as the value of "number".  This is an untyped parameter,
  146.              and it is up to the programmer to ensure that the array is of the
  147.              correct dimensions.
  148.  
  149.   getpick  - This function returns the value of the key stroke that terminates
  150.              the operation in the same manner as "editfield".}
  151.  
  152. { Generate A Menu Display and return the number of the choice. }
  153. Function getpick(col,row,maxpick: Byte; Var choice: Byte; Var picklist):Byte;
  154.  
  155. Implementation
  156.  
  157.  
  158. Procedure beep;
  159.  
  160. Begin
  161.   write(chr(7))
  162. End;
  163.  
  164.  
  165. Procedure cursor(cursortype: cursortypes);
  166.  
  167. Var reg: Registers;
  168.     startline: Byte;
  169.     monocrt: Boolean;
  170.  
  171. Begin
  172.   { Check to see if the CRT is monochrome. }
  173.   reg.AH:=$0F;
  174.   Intr($10,reg);           { Use interupt 10 to get display type }
  175.   If reg.AL = $07
  176.   Then monocrt:=True
  177.   Else monocrt:=False;
  178.  
  179.   { Set the startline value for the cursor type chosen. }
  180.   If cursortype = block
  181.   Then startline:=$00
  182.   Else If monocrt
  183.   Then startline:=$0C      { For monochrome cursor endline = $0D }
  184.   Else startline:=$06;     { For CGA cursor endline = $07        }
  185.   If cursortype = hidden
  186.   Then reg.CH:=$20         { This blows cursor into oblivion     }
  187.   Else reg.CH:=startline;
  188.   reg.CL:=07;
  189.   reg.AH:=1;
  190.   Intr($10,reg)            { Use interupt 10 to set startline    }
  191. End;
  192.  
  193.  
  194. Procedure blank(col,row,places: Byte);
  195.  
  196. Var start: Byte;
  197.  
  198. Begin
  199.   GotoXY(col,row);
  200.   For start:=1 To places Do Write(' ');
  201.   GotoXY(col,row)
  202. End;
  203.  
  204. Procedure note(msg: message); { Display a note at line 25 }
  205. Begin
  206.   cursor(hidden);
  207.   blank(1,25,78);
  208.   TextColor(hitxtcolor);
  209.   Write('Note');          { displayed with highlight }
  210.   TextColor(hitxtcolor+Blink);
  211.   Write(': ');            { displayed with blink and highlight }
  212.   TextColor(hitxtcolor);
  213.   Write(msg);             { displayed with highlight }
  214.   TextColor(lotxtcolor)
  215. End;
  216.  
  217. Procedure errmsg(msg: message); { Display an error message at line 25 }
  218. Begin
  219.   TextColor(hitxtcolor+Blink);
  220.   TextBackground(txtbkgnd);
  221.   blank(1,25,78);
  222.   Write(chr(7),'ERROR: ');  { sound bell, display with blink and highlight }
  223.   TextColor(hitxtcolor);
  224.   Write(msg);               { displayed with highlight }
  225.   TextColor(lotxtcolor);
  226. End;
  227.  
  228. { Waits for a key and returns its value }
  229. Function getkey(var specialkey:Boolean): Byte;
  230.  
  231. Var ch: Char;
  232.  
  233. Begin
  234.       ch:=ReadKey;
  235.       If ord(ch) = extendedkey Then
  236.         Begin
  237.           specialkey:=True;
  238.           ch:=ReadKey
  239.         End
  240.       Else If (ord(ch) = backspacekey) Or
  241.               (ord(ch) = tabkey) Or
  242.               (ord(ch) = enterkey) Or
  243.               (ord(ch) = esckey)
  244.       Then specialkey:=True
  245.       Else specialkey:=False;
  246.       getkey:=ord(ch)
  247. End;
  248.  
  249. { Waits for a special key and returns its value }
  250. Function getspecialkey: Byte;
  251.  
  252. Var
  253.   ch: Byte;
  254.   specialkey: Boolean;
  255.  
  256. Begin
  257.   Repeat
  258.     GotoXY(78,25);
  259.     TextColor(hitxtcolor);
  260.     Write(chr($FE));
  261.     GotoXY(78,25);
  262.     TextColor(lotxtcolor);
  263.     cursor(underline);
  264.     ch:=getkey(specialkey);
  265.     If Not specialkey
  266.     Then errmsg('Entry Must be a Special Key!');
  267.   Until specialkey;
  268.   getspecialkey:=ch;
  269. End;
  270.  
  271. { Allows editing of old or entry of new data and returns last keystroke }
  272. Function editfield(col,row,fldsize,decpla: Byte; fldtype: fldtypes;
  273.                    required: Boolean; Var buffer): Byte;
  274.  
  275. Type inputkeys = set of Char;
  276.      intdata = Integer;  { Identifier to typecast untyped variable }
  277.      realdata = Real;    { Identifier to typecast untyped variable }
  278.  
  279. Var field: string[80];   { Holding string for key input }
  280.  
  281.     posn: Byte;          { Current cursor position in field }
  282.     count: Byte;         { Number of characters in field }
  283.     ptr,ctr: Byte;       { Temporary pointer,counter }
  284.     code: Integer;       { Error code returned by Val procedure }
  285.     intvalue: Integer;   { Integer value returned by Val procedure }
  286.     realvalue: Real;     { Real value returned by Val procedure }
  287.  
  288.     specialkey: Boolean; { Key has an extended code }
  289.     numdata: Boolean;    { Data is not a string }
  290.     decdata: Boolean;    { Data is a decimal number }
  291.     empty: Boolean;      { Field is currently blank }
  292.     first: Boolean;      { First character is still being processed }
  293.     edit: Boolean;       { Field is in edit mode, editing key was pressed }
  294.     insert: Boolean;     { Field is in insert mode, insert key was pressed }
  295.     error: Boolean;      { Keying error has occured }
  296.     beyond: Boolean;     { Cursor is beyond last character position in field }
  297.     terminate: Boolean;  { Field entry has been terminated }
  298.     abort: Boolean;      { Field entry has been canceled }
  299.  
  300.     regkeys: Inputkeys;  { All printable keys }
  301.     asckeys: Inputkeys;  { Ordinary ASCII keys }
  302.     digkeys: Inputkeys;  { Digit keys only }
  303.  
  304.     ch: Char;            { Current key pressed }
  305.     chval: Byte;         { Ord() of current key pressed }
  306.     datablock: Byte;     { Symbol showing unused position in field }
  307.  
  308. { Changes colors and datablock character as required }
  309. Procedure inscrn(input: Boolean);
  310.  
  311. Begin
  312.   If reversevideo Then           { Reverse video display }
  313.     Begin
  314.       If input Then              { Reverse }
  315.         Begin
  316.           TextColor(txtbkgnd);
  317.           TextBackground(lotxtcolor)
  318.         End
  319.       Else                       { Normal }
  320.         Begin
  321.           TextColor(lotxtcolor);
  322.           TextBackground(txtbkgnd)
  323.         End;
  324.       datablock:=$20             { A blank space for reverse video }
  325.     End
  326.   Else                           { Regular display }
  327.     Begin
  328.       If input Then              { Highlight }
  329.         TextColor(hitxtcolor)
  330.       Else
  331.         TextColor(lotxtcolor);   { Normal }
  332.       TextBackground(txtbkgnd);
  333.       datablock:=$FE             { The regular block synbol }
  334.     End
  335. End;
  336.  
  337. Begin { editfield function }
  338.  
  339.   { Set display }
  340.   inscrn(False);
  341.  
  342.   { Determine data type }
  343.   If fldtype > digits Then numdata:=True Else numdata:=False;
  344.   If fldtype > sgnint Then decdata:=True Else decdata:=False;
  345.  
  346.   { Load data from buffer to "field" and initialize field length }
  347.   If numdata Then
  348.     If decdata Then
  349.       Begin
  350.         If (fldtype = usndec) Then
  351.           Begin
  352.             If (decpla <> 0) And (fldsize < 3) Then fldsize:=3;
  353.             If (decpla <> 0) And (decpla > fldsize-2) Then decpla:=fldsize-2
  354.           End
  355.         Else
  356.           Begin
  357.             If (decpla = 0) And (fldsize < 2) Then fldsize:=2;
  358.             If (decpla <> 0) And (fldsize < 4) Then fldsize:=4;
  359.             If (decpla <> 0) And (decpla > fldsize-3) Then decpla:=fldsize-3
  360.           End;
  361.         str(realdata(buffer):fldsize:decpla,field)
  362.       End
  363.     Else
  364.       Begin
  365.         If (fldtype = sgnint) And (fldsize < 2) Then fldsize:=2;
  366.         str(intdata(buffer):fldsize,field)
  367.       End
  368.   Else
  369.     Begin
  370.       move(buffer,ch,1);
  371.       move(buffer,field,ord(ch)+1)
  372.     End;
  373.   If length(field) > fldsize Then field[0]:=chr(fldsize);
  374.   If length(field) < fldsize Then
  375.     For posn:=length(field)+1 To fldsize Do field[posn]:=chr(datablock);
  376.   count:=length(field);
  377.   If count = 0 Then empty:=True Else empty:=False;
  378.   field[0]:=chr(fldsize);
  379.  
  380.   { Delete leading blanks }
  381.   While numdata And (field[1] = ' ') Do
  382.     If count = 1 Then
  383.       Begin
  384.         field[1]:=chr(datablock);
  385.         count:=0
  386.       End
  387.     Else
  388.       Begin
  389.         move(field[2],field[1],fldsize-1);
  390.         field[fldsize]:=chr(datablock);
  391.         count:=pred(count)
  392.       End;
  393.  
  394.   { Clear message line and display existing value }
  395.   blank(1,25,78);
  396.   cursor(hidden);
  397.   inscrn(True);
  398.   GotoXY(col,row);
  399.   Write(field);
  400.   GotoXY(col,row);
  401.  
  402.   { Initialize conditions }
  403.   regkeys:=[#1..#6,#11..#12,#14..#26,#28..#31,#32..#255];
  404.   asckeys:=[#32..#127];
  405.   digkeys:=[#48..#57];
  406.   posn:=1; insert:=False; edit:=False; first:=True;
  407.   error:=False; terminate:=False; abort:=False;
  408.   editfield:=0;
  409.  
  410.   { Get input from keyboard }
  411.   Repeat  { Until valid data or aborted }
  412.  
  413.     Repeat  { Until field entry terminated }
  414.  
  415.       { Reset cursor position and turn cursor on }
  416.       If error Then
  417.         Begin
  418.           GotoXY(col+posn-1,row);
  419.           inscrn(False)
  420.         End;
  421.       If insert Then cursor(block) Else cursor(underline);
  422.  
  423.       { Get character and turn cursor off }
  424.       chval:=getkey(specialkey);
  425.       cursor(hidden);
  426.       ch:=chr(chval);
  427.  
  428.       { Erase message line and reset cursor and attributes }
  429.       If error Then
  430.         Begin
  431.           blank(1,25,78);
  432.           GotoXY(col+posn-1,row);
  433.           inscrn(True);
  434.           error:=False
  435.         End;
  436.  
  437.       { Check if cursor is beyond end of field }
  438.       If posn <= fldsize Then beyond:=False Else beyond:=True;
  439.  
  440.       { Select proper response to the key pressed }
  441.       If specialkey Then Case chval Of
  442.  
  443.         esckey,
  444.         uparrowkey,
  445.         dnarrowkey,
  446.         tabkey,
  447.         shiftabkey:
  448.              If firstpass and Not (chval = esckey) Then
  449.                beep
  450.              Else
  451.                Begin
  452.                  { Set function return value }
  453.                  Case chval Of
  454.                    esckey:     editfield:=esckey;
  455.                    uparrowkey: editfield:=uparrowkey;
  456.                    dnarrowkey: editfield:=dnarrowkey;
  457.                    tabkey:     editfield:=tabkey;
  458.                    shiftabkey: editfield:=shiftabkey
  459.                  End;
  460.                  insert:=False;
  461.                  abort:=True;
  462.                  terminate:=True
  463.                End;
  464.  
  465.         enterkey:
  466.              Begin
  467.                { Accept data and terminate }
  468.                If empty And required Then
  469.                  Begin   { required field empty }
  470.                    errmsg('You Must Enter Data for This Item!');
  471.                    error:=True
  472.                  End;
  473.                If Not error Then
  474.                  Begin
  475.                    { accept existing data }
  476.                    If first And Not edit And Not numdata Then
  477.                      Begin
  478.                        move(buffer,field,fldsize+1);
  479.                        If length(field) > fldsize Then field[0]:=chr(fldsize)
  480.                      End;
  481.                    editfield:=enterkey;
  482.                    terminate:=True
  483.                  End;
  484.                insert:=false
  485.              End;
  486.  
  487.         rarrowkey:
  488.              Begin
  489.                { cursor right }
  490.                edit:=True;
  491.                If (posn <= count) and (posn < fldsize) Then
  492.                  Begin
  493.                    Inc(posn);
  494.                    GotoXY(col+posn-1,row)
  495.                  End
  496.                Else beep
  497.              End;
  498.  
  499.         larrowkey:
  500.              Begin
  501.                { cursor left }
  502.                edit:=True;
  503.                If posn > 1 Then
  504.                  Begin
  505.                    Dec(posn);
  506.                    GotoXY(col+posn-1,row)
  507.                  End
  508.                Else beep
  509.              End;
  510.  
  511.         homekey:
  512.              Begin
  513.                { cursor to first position in field }
  514.                edit:=True;
  515.                If posn > 1 Then
  516.                  Begin
  517.                    posn:=1;
  518.                    GotoXY(col,row)
  519.                  End
  520.                Else beep
  521.              End;
  522.  
  523.         endkey:
  524.              Begin
  525.                { cursor right }
  526.                edit:=True;
  527.                If posn <= count Then
  528.                  Begin
  529.                    posn:=succ(count);
  530.                    GotoXY(col+posn-1,row)
  531.                  End
  532.                Else beep
  533.              End;
  534.  
  535.         insertkey:
  536.              Begin
  537.                edit:=True;
  538.                insert:=not insert
  539.              End;
  540.  
  541.         backspacekey:
  542.              Begin
  543.                { Destructive backspace }
  544.                If posn > 1 Then
  545.                  Begin
  546.                    posn:=pred(posn);
  547.                    If posn < count+1 Then
  548.                      Begin
  549.                        move(field[posn+1],field[posn],fldsize-posn);
  550.                        count:=pred(count);
  551.                        If count = 0 Then empty:=True Else empty:=False;
  552.                        field[fldsize]:=chr(datablock);
  553.                        GotoXY(col,row);
  554.                        Write(field);
  555.                        GotoXY(col+posn-1,row)
  556.                      End
  557.                  End
  558.                Else beep
  559.              End;
  560.  
  561.         deletekey:
  562.              Begin
  563.                { Delete the character at the cursor position }
  564.                edit:=True;
  565.                If posn < count+1 Then
  566.                  Begin
  567.                    move(field[posn+1],field[posn],fldsize-posn);
  568.                    count:=pred(count);
  569.                    If count = 0 Then empty:=True Else empty:=False;
  570.                    field[fldsize]:=chr(datablock);
  571.                    GotoXY(col,row);
  572.                    Write(field);
  573.                    GotoXY(col+posn-1,row)
  574.                  End
  575.              End
  576.  
  577.         Else beep  { Ignore other specialkeys }
  578.       End  { specialkey case statement }
  579.  
  580.       Else If beyond Then beep
  581.  
  582.       Else If ch in regkeys Then
  583.         Begin
  584.           { Character (Printable) key }
  585.           If first And Not empty And Not edit Then
  586.             Begin
  587.               { Clear the current field if first key press is data }
  588.               fillchar(field[1],fldsize,chr(datablock));
  589.               GotoXY(col,row);
  590.               Write(field);
  591.               GotoXY(col,row);
  592.               count:=0; posn:=1; empty:=True;
  593.             End;
  594.  
  595.           { Validate key }
  596.           Case fldtype Of
  597.             alsymb:;
  598.             ascii,
  599.             caplet:
  600.                  If Not (ch in asckeys) Then
  601.                    Begin
  602.                      errmsg('Entry Must be an Ordinary ASCII Character!');
  603.                      error:=True
  604.                    End
  605.                  Else If fldtype = caplet Then
  606.                    ch:=UpCase(ch);
  607.             digits,
  608.             usnint:
  609.                  If Not (ch in digkeys) Then
  610.                    Begin
  611.                      errmsg('Entry Must be a Digit!');
  612.                      error:=True
  613.                    End;
  614.             sgnint:
  615.                  If Not (ch in digkeys)
  616.                  And Not ((ch = '-') And (posn = 1)) Then
  617.                    Begin
  618.                      errmsg('Entry Must be Digit or Initial Minus Sign!');
  619.                      error:=True
  620.                    End;
  621.             usndec:
  622.                  If Not (ch in digkeys)
  623.                  And Not ((ch = '.') And (pos('.',field) = 0))
  624.                  And Not ((ch = '.') And (pos('.',field) = posn)) Then
  625.                    Begin
  626.                      errmsg('Entry Must be Digit or Decimal Point!');
  627.                      error:=true
  628.                    End;
  629.             sgndec:
  630.                  If Not (ch in digkeys)
  631.                  And Not ((ch = '-') And (posn = 1))
  632.                  And Not ((ch = '.') And (pos('.',field) = 0))
  633.                  And Not ((ch = '.') And (pos('.',field) = posn)) Then
  634.                    Begin
  635.                      errmsg
  636.                      ('Must be Digit, Initial Minus Sign, or Declimal Point!');
  637.                      error:=True
  638.                    End
  639.                  Else
  640.             Else
  641.           End; { fldtype Case statement }
  642.  
  643.           { Display the character and update the pointers }
  644.           If not error And insert And (count = fldsize) Then
  645.             Begin
  646.               errmsg('Field is Full!');
  647.               error:=True
  648.             End
  649.           Else
  650.             If not error And insert and (field[posn] = '-') Then
  651.               Begin
  652.                 errmsg('Insertion Ahead of Minus Sign Not Allowed!');
  653.                 error:=True
  654.               End
  655.           Else
  656.             If not error Then
  657.               Begin
  658.                 { Insert a space at the cursor position }
  659.                 If insert and (posn <= count) Then
  660.                   Begin
  661.                     move(field[posn],field[posn+1],fldsize-posn);
  662.                     Inc(count);
  663.                     field[posn]:=' ';
  664.                     GotoXY(col,row);
  665.                     Write(field);
  666.                     GotoXY(col+posn-1,row)
  667.                   End;
  668.                 Write(ch);
  669.                 field[posn]:=ch;
  670.                 If posn > count Then count:=posn;
  671.                 If posn <= fldsize Then Inc(posn);
  672.                 first:=False; empty:=False
  673.               End
  674.         End    { printable character case }
  675.  
  676.       Else beep;
  677.  
  678.     Until terminate; { End of input }
  679.  
  680.     { Input Complete; Validate and Format or Abort }
  681.     field[0]:=chr(count);
  682.     If Not abort Then
  683.       Begin
  684.         If numdata Then
  685.           Begin
  686.             { Delete extra leading zeros }
  687.             While (count > 1) And (field[1] = '0')
  688.                   And (field[2] <> '.') Do
  689.               Begin
  690.                 move(field[2],field[1],fldsize-1);
  691.                 field[fldsize]:=chr(datablock);
  692.                 Dec(count);
  693.                 field[0]:=chr(count)
  694.               End;
  695.             While (count > 2) And (field[1] = '-')
  696.                   And (field[2] = '0') And (field[3] <> '.') Do
  697.               Begin
  698.                 move(field[3],field[2],fldsize-2);
  699.                 field[fldsize]:=chr(datablock);
  700.                 Dec(count);
  701.                 field[0]:=chr(count)
  702.               End;
  703.             { Place a zero in an empty field or add a zero where needed }
  704.             If count = 0 Then
  705.               Begin
  706.                 Inc(count);
  707.                 field[0]:=chr(count);
  708.                 field[1]:='0'
  709.               End
  710.             Else If field[1] = '.' Then
  711.               Begin
  712.                 Inc(count);
  713.                 field[0]:=chr(count);
  714.                 move(field[1],field[2],count-1);
  715.                 field[1]:='0'
  716.               End
  717.             Else If (field[1] = '-') And ((field[2] = '.') Or (count = 1)) Then
  718.               Begin
  719.                 Inc(count);
  720.                 field[0]:=chr(count);
  721.                 move(field[2],field[3],count-2);
  722.                 field[2]:='0'
  723.               End;
  724.             If field[count] = '.' Then
  725.               If (decpla <> 0) Then
  726.                 Begin
  727.                   Inc(count);
  728.                   field[0]:=chr(count);
  729.                   field[count]:='0'
  730.                 End
  731.               Else
  732.                 Begin
  733.                   field[count]:=chr(datablock);
  734.                   Dec(count);
  735.                   field[0]:=chr(count)
  736.                 End;
  737.             val(field,realvalue,code);
  738.             { check for zero value when entry is required }
  739.             If required And (realvalue = 0) And zerovoid Then
  740.               Begin
  741.                 errmsg('Zero is Not a Valid Entry!');
  742.                 If count > fldsize Then count:=fldsize;
  743.                 error:=True; posn:=1; edit:=True;
  744.                 terminate:=False
  745.               End
  746.             Else If decdata Then
  747.               Begin
  748.                 field[0]:=chr(fldsize);
  749.                 ptr:=pos('.',field);
  750.                 { Check for too many digits }
  751.                 If (decpla > 0) And (((ptr > 0) And (ptr+decpla > fldsize))
  752.                     Or ((ptr = 0) And (count+decpla > fldsize-1))) Then
  753.                   Begin
  754.                     errmsg('Too Many Digits before Decimal Point!');
  755.                     If count > fldsize Then count:=fldsize;
  756.                     error:=True; edit:=True; terminate:=False;
  757.                     posn:=1
  758.                   End
  759.                 Else If ((count-ptr) > decpla) And Not (ptr = 0) Then
  760.                   Begin
  761.                     errmsg('Too Many Digits after Decimal Point!');
  762.                     If count > fldsize Then count:=fldsize;
  763.                     error:=True; edit:=True; terminate:=False;
  764.                     posn:=count+1
  765.                   End
  766.                 Else
  767.                   Begin
  768.                     field[0]:=chr(count);
  769.                     realdata(buffer):=realvalue
  770.                   End
  771.               End
  772.             Else { Integer data }
  773.               Begin
  774.                 val(field,intvalue,code);
  775.                 If (code = 0) And (field[1] <> '-')
  776.                 And Not ((intvalue >= 0) And (intvalue <= 32767)) Then
  777.                   Begin
  778.                     errmsg('Invalid Entry, Maximum Integer is 32767!');
  779.                     error:=True; edit:=True; terminate:=False;
  780.                     posn:=1
  781.                   End
  782.                 Else If (code = 0) And (field[1] = '-')
  783.                 And Not ((intvalue >= -32768) And (intvalue <= 0)) Then
  784.                   Begin
  785.                     errmsg('Invalid Entry, Minimum Integer is -32768!');
  786.                     error:=True; edit:=True; terminate:=False;
  787.                     posn:=1
  788.                   End
  789.                 Else intdata(buffer):=intvalue
  790.               End
  791.           End
  792.         Else { String data }
  793.           Begin
  794.             { Set count for blank field to zero }
  795.             ptr:=1;
  796.             While (field[ptr] = ' ') And (ptr < count) Do Inc(ptr);
  797.             If (field[ptr] = ' ') And (ptr = count) Then
  798.               Begin
  799.                 If required Then
  800.                   Begin
  801.                     errmsg('You Must Enter Data Not Blanks!');
  802.                     error:=True; posn:=1; edit:=True;
  803.                     terminate:=False
  804.                   End
  805.                 Else
  806.                   Begin
  807.                     field[0]:=chr(0);
  808.                     count:=0
  809.                   End
  810.               End
  811.           End;
  812.         { Display the field and load it to the buffer }
  813.         If Not error Then
  814.           Begin
  815.             inscrn(False);
  816.             blank(col,row,fldsize);
  817.             If numdata Then
  818.               If decdata Then
  819.                 Write(realdata(buffer):fldsize:decpla)
  820.               Else { Integer data }
  821.                 Write(intdata(buffer):fldsize)
  822.             Else { String data }
  823.               Begin
  824.                 Write(field);
  825.                 move(field,buffer,length(field)+1)
  826.               End;
  827.             sound(80);  { Make a clicking sound }
  828.             delay(3);   { to confirm successful }
  829.             nosound     { entry of data!        }
  830.           End
  831.         Else { Error }
  832.           If numdata Then
  833.             Begin
  834.               field[0]:=chr(fldsize);
  835.               inscrn(True);
  836.               blank(col,row,fldsize);
  837.               Write(field)
  838.             End
  839.       End
  840.     Else { Abort }
  841.       { Restore original data and exit without change }
  842.       Begin
  843.         inscrn(False);
  844.         blank(col,row,fldsize); { Erase field }
  845.         If numdata Then
  846.           If decdata Then
  847.             Write(realdata(buffer):fldsize:decpla)
  848.           Else { Integer data }
  849.             Write(intdata(buffer):fldsize)
  850.         Else { String data }
  851.           Begin
  852.             move(buffer,ch,1);
  853.             move(buffer,field,ord(ch)+1);
  854.             If length(field) > fldsize Then
  855.               field[0]:=chr(fldsize);
  856.             Write(field)
  857.           End
  858.       End;
  859.  
  860.   Until terminate
  861. End;  { editfield }
  862.  
  863. Function getpick(col,row,maxpick: Byte; Var choice: Byte; Var picklist):Byte;
  864.  
  865.   Const maxnumber=20; { maximum size of list array }
  866.  
  867.   Type listtype=Array[1..maxnumber] Of String[30];
  868.  
  869.   Var list: listtype Absolute picklist;
  870.       picknum, count, chval, initial: Byte;
  871.       pointer, marker: String[3];
  872.       firstletter: String[1];
  873.       ch: Char;
  874.       specialkey: Boolean;
  875.  
  876.   Begin
  877.     pointer:='   ';
  878.     pointer[2]:=chr(pickpointer);
  879.     marker:='   ';
  880.     marker[2]:=chr(pickmarker);
  881.     cursor(hidden);
  882.     TextColor(lotxtcolor);
  883.  
  884.     { Display list }
  885.     For picknum:=1 To maxpick Do
  886.       Begin
  887.         GotoXY(col,picknum+row-1);
  888.         Write(marker,list[picknum])
  889.       End;
  890.     note('SPACE, BACKSPACE or First Letter to Move; ENTER to Select!');
  891.  
  892.     { Pick menu }
  893.     picknum:=choice;
  894.     initial:=choice;
  895.     getpick:=0;
  896.     Repeat
  897.       { Display current pick }
  898.       GotoXY(col,row+picknum-1);
  899.       TextColor(hitxtcolor+Blink);
  900.       Write(pointer);
  901.       TextColor(hitxtcolor);
  902.       Write(list[picknum]);
  903.       { Get Keyboard and clear current pick }
  904.       chval:=getkey(specialkey);
  905.       GotoXY(col,row+picknum-1);
  906.       TextColor(hitxtcolor);
  907.       Write(pointer); { Kill blink on pointer }
  908.       GotoXY(col,row+picknum-1);
  909.       TextColor(lotxtcolor);
  910.       If (chval <> enterkey) Then
  911.         Write(marker,list[picknum]);
  912.       { If abort, reset initial pick }
  913.       If (chval = uparrowkey) Or
  914.          (chval = dnarrowkey) Or
  915.          (chval = tabkey) Or
  916.          (chval = shiftabkey) Or
  917.          (chval = esckey) Then
  918.         Begin
  919.           GotoXY(col,row+initial-1);
  920.           TextColor(hitxtcolor);
  921.           Write(pointer,list[initial])
  922.         End;
  923.  
  924.       { Determine new Pick }
  925.       Case chval Of
  926.         enterkey:
  927.             Begin
  928.               getpick:=enterkey;
  929.               choice:=picknum
  930.             End;
  931.         endkey:
  932.             picknum:=maxpick;
  933.         homekey:
  934.             picknum:=1;
  935.         esckey:
  936.             getpick:=esckey;
  937.         uparrowkey:
  938.             If firstpass Then beep
  939.             Else getpick:=uparrowkey;
  940.         dnarrowkey:
  941.             If firstpass Then beep
  942.             Else getpick:=dnarrowkey;
  943.         tabkey:
  944.             If firstpass Then beep
  945.             Else getpick:=tabkey;
  946.         shiftabkey:
  947.             If firstpass Then beep
  948.             Else getpick:=shiftabkey;
  949.         backspacekey:
  950.             If picknum > 1 Then Dec(picknum)
  951.             Else picknum:=maxpick;
  952.         spacekey:
  953.             If picknum < (maxpick) Then Inc(picknum)
  954.             Else picknum:=1
  955.         Else { default case }
  956.           Begin
  957.             { Check for first character of line }
  958.             count:=picknum;
  959.             ch:=UpCase(chr(chval));
  960.             Repeat
  961.               Inc(count);
  962.               If count > maxpick Then count:=1;
  963.               firstletter:=copy(list[count],1,1);
  964.             Until (count = picknum)
  965.                Or (ch = UpCase(firstletter[1]));
  966.             picknum:=count
  967.           End
  968.       End;   { chval Case statement }
  969.  
  970.     Until (chval = enterkey) Or
  971.           (chval = esckey) Or
  972.           (chval = uparrowkey) Or
  973.           (chval = dnarrowkey) Or
  974.           (chval = tabkey) Or
  975.           (chval = shiftabkey)
  976.   End;
  977.  
  978. End.
  979. 
  980.