home *** CD-ROM | disk | FTP | other *** search
/ ftp.update.uu.se / ftp.update.uu.se.2014.03.zip / ftp.update.uu.se / pub / rainbow / msdos / decus / RB139 / mail20r.lzh / IO20.INC next >
Text File  |  1988-10-09  |  23KB  |  672 lines

  1. { IO20.INC -- Global I/O procedures to include in programs generally
  2.   Version 2.0 includes prev_page and next_page, changes where pause text
  3.   is displayed -- WPM -- 2/26/86 }
  4.  
  5. {Modified to suit the DEC Rainbow by David P. Maroun on  9-Oct-1988.}
  6.  
  7. { ------------------------------------------------------------ }
  8.  
  9. const
  10.     prev_fld  = $0b ;  { ^K -- up_arrow on Kaypro II '83 }
  11.     next_fld  = $0a ;  { ^J -- linefeed, down_arrow }
  12.     backspace = $08 ;  { ^H -- Backspace key }
  13.     del_fld   = $19 ;  { ^Y }
  14.     prev_page = $12 ;  { ^R }
  15.     next_page = $03 ;  { ^C }
  16.     escape    = $1b ;
  17.     carr_rtn  = $0d ;
  18.     del       = $7f ;
  19.     filler    = $2e ;  { . }
  20.  
  21. type
  22.     str_type = string[132] ;  {Changed to 132 from 80 on 11-Sep-1988.}
  23.  
  24.     intset = set of $00 .. $ff ;
  25.  
  26. const  { Turbo typed constants -- initialized variables }
  27.     terminating : intset = [carr_rtn, next_fld, prev_fld, next_page,
  28.                             prev_page, escape] ;
  29.     adjusting   : intset = [backspace, del_fld, del] ;
  30.  
  31. var
  32.     fld, scrn   : integer ; {For field & screen cursor control}
  33.  
  34. { ------------------------------------------------------------ }
  35.  
  36. { procedure gotoxy (col,row) ; -- Built-in proc in Turbo to place
  37.   cursor on screen.  Upper left is (1,1) not (0,0)! }
  38.  
  39. { procedure clrscr ; -- Built-in proc in Turbo to clear screen. }
  40.  
  41. { procedure clreol ; -- built-in proc in Turbo to clear to end of line }
  42.  
  43. { ------------------------------------------------------------ }
  44.  
  45. procedure clrline (col,row : integer) ;
  46.     begin
  47.         gotoxy (col,row) ;
  48.         clreol
  49.     end ;
  50.  
  51. { ------------------------------------------------------------ }
  52.  
  53. procedure clreos ;
  54.     begin
  55.         write (ESCAPE,'[J')   {ANSI code to clear to the end of the screen}
  56.     end ;
  57. {Changed on 11-Sep-1988.}
  58. { ------------------------------------------------------------ }
  59.  
  60. procedure beep ;
  61.     begin
  62.         write (chr(7))
  63.     end ;
  64.  
  65. { ------------------------------------------------------------ }
  66.  
  67. procedure do_fld_ctl (key : integer) ;
  68.   { Adjusts global FLD based on value of key, the ordinal value of last key pressed }
  69.   { global
  70.         fld : integer -- for field cursor control }
  71.     begin
  72.         case key of
  73.           carr_rtn, next_fld : fld := fld + 1 ;
  74.           prev_fld           : fld := fld - 1 ;
  75.           next_page          : fld := 999 ;
  76.           prev_page          : fld := -999 ;
  77.           escape             : fld := maxint ;  { NOTE -- different from MT+ }
  78.         end  { case }
  79.     end ;  { proc do_fld_ctl }
  80.  
  81. { ------------------------------------------------------------ }
  82.  
  83. procedure do_scrn_ctl ;
  84.   { Checks value of FLD and adjusts value of SCRN accordingly }
  85.   { Global
  86.         fld, scrn : integer -- For field and screen cursor control }
  87.     begin
  88.         if fld < 1 then
  89.                 scrn := scrn - 1
  90.         else if fld = maxint then
  91.                 scrn := maxint
  92.         else
  93.                 scrn := scrn + 1
  94.     end ;
  95.  
  96. { ------------------------------------------------------------ }
  97.  
  98. procedure write_str (st:str_type ; col,row:integer) ;
  99.     begin
  100.         gotoxy (col,row) ;
  101.         write (st)
  102.     end ;
  103.  
  104. { ------------------------------------------------------------ }
  105.  
  106. procedure write_int (int:integer ; width,col,row:integer) ;
  107.     begin
  108.         gotoxy (col,row) ;
  109.         write (int:width)
  110.     end ;
  111.  
  112. { ------------------------------------------------------------ }
  113.  
  114. procedure write_bool (bool:boolean ; col, row:integer) ;
  115.     begin
  116.         gotoxy (col,row) ;
  117.         if bool then write ('YES') else write ('NO ')
  118.     end ;
  119.  
  120. { ------------------------------------------------------------ }
  121.  
  122. procedure write_real (r:real ; width,frac,col,row:integer) ;
  123.     begin
  124.         gotoxy (col,row) ;
  125.         write (r:width:frac)
  126.     end ;
  127.  
  128. { ------------------------------------------------------------ }
  129.  
  130. { This is for Kaypro CP/M -- comment it out to use IBM }
  131. (*
  132. procedure keyin (var ch:char) ;
  133. { Reads a single character from keyboard without echoing it back.
  134.   Modified to trap WordStar commands, 4/29/85 }
  135.     begin
  136.         read (kbd, ch) ;
  137.         if ch = ^S then
  138.             ch := chr(backspace)
  139.         else if ch = ^E then
  140.             ch := chr(prev_fld)
  141.         else if ch = ^X then
  142.             ch := chr(next_fld)
  143.     end ;
  144. *)
  145. { ------------------------------------------------------------ }
  146.  
  147. { This is for IBM PC-DOS -- comment it out for CP/M }
  148.  
  149. procedure keyin (var ch:char) ;
  150. { Reads a single character from keyboard without echoing it back.
  151.   Maps function key scan codes to single keyboard keys.
  152.   Modified for IBM -- from Turbo 3.0 manual, page 360 -- 5/29/85
  153.   Modified for IO20 -- 2/26/86 }
  154.  
  155.     var
  156.         func : boolean ;     { Whether function key or not }
  157.            c : char ;        { Character read }
  158.          key : integer ;     { ORD of character returned }
  159.  
  160.     begin
  161.         func := false ;
  162.         read (kbd,c) ;                       { Get first char }
  163.         if  (ord(c) = escape)                { If there is }
  164.         and keypressed then                  { a second ... }
  165.           begin
  166.             read (kbd,c) ;                   { Get 2nd char }
  167.             if c='[' then
  168.             read(kbd,c); func := true
  169.           end ;
  170.         key := ord(c) ;
  171.  
  172.         if func then                         { Translate func. keys }
  173.             case key of
  174.               65: key := prev_fld ;   { up-arrow }
  175.               66: key := next_fld ;   { down-arrow }
  176.               68 : key := backspace ;  { left-arrow }
  177.             else     if ord(c)= 53 then begin
  178.                           read(kbd,c);
  179.                           If ord(c)=126 then key:=prev_page  { Prev Screen}
  180.                           end
  181.                      else if ord(c)=54 then begin
  182.                           read(kbd,c);
  183.                           If ord(c)=126 then key:=next_page  { Next Screen}
  184.                           end
  185.                      else if ord(c)=51 then begin
  186.                           read(kbd,c);
  187.                           If ord(c)=126 then key:=del_fld { Remove }
  188.                           end
  189.            else       key := 00 ;
  190.             end  { case }
  191.         else  { not a function key }
  192.             case key of
  193.               $13   : key := backspace ;  { ^S -- Like WordStar }
  194.               $05   : key := prev_fld ;   { ^E }
  195.               $18   : key := next_fld ;   { ^X }
  196.             end ;  { case }
  197.  
  198.         ch := chr(key)                       { finally, return the character }
  199.     end ;
  200.  
  201. { ------------------------------------------------------------ }
  202.  
  203. function purgech (instr : str_type ; inchar : char) : str_type ;
  204.     {Purges all instances of the character from the string}
  205.     var
  206.         n      : integer ;  {Loop counter}
  207.         outstr : str_type ; {Result string}
  208.  
  209.     begin
  210.         outstr := '' ;
  211.         for n := 1 to length (instr) do
  212.                 if not (instr[n] = inchar) then
  213.                         outstr := concat (outstr, instr[n]) ;
  214.         purgech := outstr
  215.     end ;
  216.  
  217. { ------------------------------------------------------------ }
  218.  
  219. function stripch (instr:str_type ; inchar:char) : str_type ;
  220.     {Strips leading instances of the character from the string}
  221.     begin
  222.         while not (length(instr) = 0)
  223.         and (instr[1] = inchar) do
  224.                 delete (instr, 1, 1) ;
  225.         stripch := instr
  226.     end ;
  227.  
  228. { ------------------------------------------------------------ }
  229.  
  230. function chopch (instr:str_type ; inchar:char) : str_type ;
  231.     {Chops trailing instances of the character from the string}
  232.     begin
  233.         while not (length(instr) = 0)
  234.         and (instr[length(instr)] = inchar) do
  235.                 delete (instr, length(instr), 1) ;
  236.         chopch := instr
  237.     end ;
  238.  
  239. { ------------------------------------------------------------ }
  240.  
  241. procedure adjust_str (var st : str_type ; key, maxlen, col, row : integer ) ;
  242.   { deletes a character or the whole entry }
  243.     var
  244.         i : integer ;
  245.     begin
  246.       case key of
  247.         del_fld   : begin
  248.                       st := '' ;
  249.                       gotoxy (col, row) ;
  250.                       for i := 1 to maxlen do
  251.                           write (chr(filler)) ;
  252.                       gotoxy (col, row)
  253.                     end ;
  254.         backspace,
  255.         del       : if length(st) = 0 then
  256.                         beep
  257.                     else
  258.                       begin
  259.                         write (chr(backspace), chr(filler), chr(backspace)) ;
  260.                         delete (st, length(st), 1)
  261.                       end
  262.       end  { case }
  263.     end ; { proc adjust_str }
  264.  
  265. { ------------------------------------------------------------ }
  266.  
  267. procedure read_str (var st:str_type ; maxlen, col, row:integer) ;
  268.  
  269.   { Read String.  This procedure gets input from the keyboard one
  270.     character at a time and edits on the fly, rejecting invalid
  271.     characters.  COL and ROW tell where to begin the data input
  272.     field, and MAXLEN is the maximum length of the string to be
  273.     returned. }
  274.  
  275.     var
  276.         ch          : char ;
  277.         i,key       : integer ;
  278.  
  279.     procedure add_to_str ;
  280.         begin
  281.             if length(st) = maxlen then
  282.                     beep
  283.             else
  284.                 begin
  285.                     st  := concat(st, ch) ;     {concatenate char. onto str.}
  286.                     write (ch)
  287.                 end
  288.         end ; {--- of ADD_TO_STR---}
  289.  
  290.     begin {--- READ_STR ---}
  291.         write_str (st, col, row) ;
  292.         for i := (length(st)+1) to maxlen do
  293.                 write (chr(filler)) ;
  294.         gotoxy ((col + length(st)), row) ;
  295.         repeat
  296.             keyin (ch) ;
  297.             key := ord(ch) ;
  298.             if key in [$20 .. $7e] then
  299.                 add_to_str
  300.             else if key in adjusting then
  301.                 adjust_str (st,key,maxlen,col,row)
  302.             else if key in terminating then
  303.                 do_fld_ctl (key)
  304.             else
  305.               beep ;
  306.         until key in terminating ;
  307.         write ('':maxlen - length(st))
  308. end ; {--- of READ_STR ---}
  309.  
  310. { ------------------------------------------------------------ }
  311.  
  312. procedure read_int (var int:integer ; maxlen, col, row:integer) ;
  313.  
  314.   { Read Integer.  This procedure gets input from the keyboard
  315.     one character at a time and edits on the fly, rejecting
  316.     invalid characters.  COL and ROW tell where to begin the data
  317.     input field, and MAXLEN is the maximum length of the integer
  318.     to be returned. }
  319.  
  320.     var
  321.         ch          : char ;
  322.         i,key       : integer ;
  323.         st          : string[5] ;
  324.         maxst       : string[5] ;
  325.         code        : integer ;
  326.  
  327.     procedure add_to_str ;
  328.         begin
  329.             if length(st) = maxlen then
  330.                     beep
  331.             else
  332.                 begin
  333.                     st  := concat(st, ch) ;     {concatenate char. onto str.}
  334.                     write (ch)
  335.                 end
  336.         end ; {--- of ADD_TO_STR---}
  337.  
  338.     begin {--- READ_INT ---}
  339.         str (maxint:5, maxst) ;                    {Make integer into string}
  340.         str (int:maxlen, st) ;
  341.         st := purgech (st, ' ') ;
  342.         st := stripch (st, '0') ;
  343.         write_str (st, col, row) ;
  344.         for i := (length(st)+1) to maxlen do
  345.                 write (chr(filler)) ;
  346.         gotoxy ((col + length(st)), row) ;
  347.         repeat
  348.             keyin (ch) ;
  349.             key := ord(ch) ;
  350.             if key = $2d then                 { minus sign }
  351.               begin
  352.                 if  length(st) = 0 then
  353.                     add_to_str
  354.                 end
  355.             else if key in [$30 .. $39] then  {digits 0 - 9}
  356.               begin
  357.                 add_to_str ;
  358.                 if (length(st) = 5)
  359.                 and (st > maxst) then
  360.                     adjust_str (st,del,maxlen,col,row)
  361.               end
  362.             else if key in adjusting then
  363.                 adjust_str (st,key,maxlen,col,row)
  364.             else if key in terminating then
  365.                 do_fld_ctl (key)
  366.             else
  367.               beep ;
  368.         until key in terminating ;
  369.  
  370.         if st = '' then
  371.             begin
  372.                 int := 0 ;
  373.                 code := 0
  374.             end
  375.         else
  376.                 val (st, int, code) ;              {Make string into integer}
  377.         gotoxy (col, row) ;
  378.         if code = 0 then  {Conversion worked OK}
  379.                 write (int:maxlen)
  380.         else
  381.             begin
  382.                 write ('** CONVERSION ERROR ', code) ;
  383.                 halt
  384.             end
  385. end ; {--- of READ_INT ---}
  386.  
  387. { ------------------------------------------------------------ }
  388.  
  389. function equal (r1,r2 : real) : boolean ;
  390.   { tests functional equality of two real numbers -- 4/30/85 }
  391.     begin
  392.         equal := abs(r1 - r2) < 1.0e-5
  393.     end ;  { function equal }
  394.  
  395. { ------------------------------------------------------------ }
  396.  
  397. function greater (r1,r2 : real) : boolean ;
  398.   { tests functional inequality of two real numbers -- 5/1/85 }
  399.     begin
  400.         greater := (r1 - r2) > 1.0e-5
  401.     end ;  { function greater }
  402.  
  403. { ------------------------------------------------------------ }
  404.  
  405. procedure read_real (var r:real ; maxlen,frac,col,row:integer) ;
  406.  
  407.   { Read Real.  This procedure gets input from the keyboard
  408.     one character at a time and edits on the fly, rejecting
  409.     invalid characters.  COL and ROW tell where to begin the data
  410.     input field; MAXLEN is the maximum length of the string
  411.     representation of the real number, including sign and decimal
  412.     point; FRAC is the fractional part, the number of digits to
  413.     right of the decimal point.
  414.  
  415.     Note -- In TURBO the maximum number of significant digits in
  416.     decimal (not scientific) representation is 11.  It is the
  417.     programmer's responsibility to limit input and computed output
  418.     to 11 significant digits.  }
  419.  
  420.     var
  421.         ch          : char ;    {Input character}
  422.         i,key       : integer ; {Loop control ; ORD of CH}
  423.         st          : string[13] ; {String representation of real number}
  424.         code        : integer ; {Result of VAL conversion}
  425.         rlen        : integer ; {Current length of ST to right of dec. pt.}
  426.         llen        : integer ; {Current length to left, including dec. pt.}
  427.         maxl        : integer ; {Max allowable to left, including dec. pt.}
  428.  
  429.     procedure compute_length ;
  430.         begin
  431.             if pos ('.', st) = 0 then     { If no dec. pt. ... }
  432.               begin
  433.                 llen := length(st) ;      {the whole string is Left}
  434.                 rlen := 0                 {and none is Right}
  435.               end
  436.             else    {There is a decimal point ...}
  437.               begin
  438.                 llen := pos ('.', st) ;   {Left is all up to dec. pt.}
  439.                 rlen := length(st) - llen {Right is the rest}
  440.               end
  441.         end ; { proc compute_length }
  442.  
  443.     procedure add_to_str ;
  444.         procedure add_it ;
  445.             begin
  446.                 st  := concat(st, ch) ;
  447.                 write (ch)
  448.             end ;
  449.         begin {ADD_TO_STR}
  450.             if ch = '.' then      { Decimal point: if not one already, add it }
  451.               begin
  452.                 if pos('.', st) = 0 then
  453.                     add_it
  454.                 else
  455.                     beep
  456.               end
  457.                                   { else it's not a decimal point }
  458.             else if pos('.',st) = 0 then
  459.             { There's no dec pt in string, so digit goes on left. }
  460.               begin
  461.                 if llen = (maxl - 1) then
  462.                     beep  { Only a dec pt is allowed in pos MAXL }
  463.                 else
  464.                     add_it
  465.               end
  466.             else  { There is a dec pt in string, so digit goes on right }
  467.               begin
  468.                 if rlen = frac then
  469.                     beep
  470.                 else
  471.                     add_it
  472.               end
  473.         end ; {--- of ADD_TO_STR---}
  474.  
  475.     begin {--- READ_REAL ---}
  476.                               {Initialize}
  477.         maxl  := maxlen - frac ;
  478.                               {Set up string representation of real and }
  479.                               {determine length of left & right portions}
  480.         str(r:maxlen:frac,st) ;           {Make real into string}
  481.         st := purgech (st, ' ') ;         {Purge all blanks}
  482.         st := stripch (st, '0') ;         {Strip leading zeroes}
  483.         if not (pos('.', st) = 0) then    {If there is a dec. pt ... }
  484.             begin
  485.                 st := chopch (st, '0') ;  {Chop trailing zeroes}
  486.                 st := chopch (st, '.')    {and trailing dec. pt.}
  487.             end ;
  488.  
  489.                               {Write string on console}
  490.         write_str (st, col, row) ;
  491.         for i := (length(st)+1) to maxlen do
  492.                 write (chr(filler)) ;
  493.         gotoxy ((col + length(st)), row) ;
  494.  
  495.                               {Get input a character at a time & edit it}
  496.         repeat
  497.                 compute_length ;
  498.                 keyin (ch) ;
  499.                 key := ord(ch) ;
  500.                 if ch = '-' then
  501.                   begin
  502.                     if length(st) = 0 then
  503.                         add_to_str
  504.                     else
  505.                         beep
  506.                   end
  507.                 else if (ch = '.')
  508.                      or (ch in ['0' .. '9']) then
  509.                     add_to_str
  510.                 else if key in adjusting then
  511.                     adjust_str (st,key,maxlen,col,row)
  512.                 else if key in terminating then
  513.                     do_fld_ctl (key)
  514.                 else
  515.                     beep
  516.         until key in terminating ;
  517.  
  518.                               {Done getting input, now convert back to real}
  519.         if (st = '')                             {If null string ... }
  520.         or (st = '.')
  521.         or (st = '-')
  522.         or (st = '-.') then
  523.             begin
  524.                 r := 0.0 ;                       {Make real zero}
  525.                 code := 0
  526.             end
  527.         else    {Not a null string}
  528.                 val (st, r, code) ;              {Make string into real}
  529.         gotoxy (col, row) ;
  530.         if code = 0 then  {Conversion worked OK}
  531.                 write (r:maxlen:frac)            {Write the real on screen}
  532.         else
  533.             begin
  534.                 write ('** CONVERSION ERROR ', code) ;
  535.                 halt
  536.             end
  537. end ; {--- of READ_REAL ---}
  538.  
  539. { ------------------------------------------------------------ }
  540.  
  541. procedure read_yn (var bool:boolean; col,row:integer) ;
  542.   { Inputs "Y" OR "N" to boolean at column and row specified,
  543.     prints "YES" or "NO."
  544.  
  545.     Note -- use this when the screen control will not return
  546.     to the question and the boolean IS NOT defined before the
  547.     user answers the question. }
  548.  
  549.     var ch:char ;
  550.     begin
  551.         gotoxy (col,row) ;
  552.         write ('   ') ;
  553.         gotoxy (col,row) ;
  554.         repeat
  555.                 keyin (ch)
  556.         until (ch in ['Y', 'y', 'N', 'n']) ;
  557.         if (ch = 'Y') or (ch = 'y') then
  558.             begin
  559.                 write ('YES') ;
  560.                 bool := true
  561.             end
  562.         else
  563.             begin
  564.                 write ('NO ') ;
  565.                 bool := false
  566.             end
  567.     end ; {--- of READ_YN ---}
  568.  
  569. { ------------------------------------------------------------ }
  570.  
  571. procedure read_bool (var bool:boolean; col,row:integer) ;
  572.   { Displays boolean at column and row specified, inputs "Y"
  573.     or "N" to set new value of boolean, prints "YES" or "NO."
  574.  
  575.     Note -- use this when the screen control may return to the
  576.     question and the boolean IS defined before the user answers
  577.     the question. }
  578.  
  579.     var
  580.         ch         : char ;
  581.         key        : integer ;
  582.  
  583.     begin
  584.         write_bool (bool, col, row) ;
  585.         gotoxy (col, row) ;
  586.         repeat
  587.             keyin (ch) ;
  588.             key := ord(ch) ;
  589.             if key in [$59, $79] then           { 'Y', 'y' }
  590.                 begin
  591.                     bool := true ;
  592.                     key := next_fld ;
  593.                     do_fld_ctl(key)
  594.                 end
  595.             else if key in [$4e, $6e] then      { 'N', 'n' }
  596.                 begin
  597.                     bool := false ;
  598.                     key := next_fld ;
  599.                     do_fld_ctl(key)
  600.                 end
  601.             else if key in terminating then
  602.                 do_fld_ctl(key)
  603.             else
  604.                 beep ;
  605.         until key in terminating ;
  606.         write_bool (bool, col, row)
  607.     end ; {--- of READ_BOOL ---}
  608.  
  609. { ------------------------------------------------------------ }
  610.  
  611. procedure pause ;
  612.     {Prints message on bottom line, waits for user response}
  613.     var
  614.         ch   : char ;
  615.         key : integer ;
  616.     begin
  617.         clrline (1,24) ;
  618.         write_str ('PRESS SPACE BAR TO CONTINUE OR UP-ARROW TO GO BACK',14,24) ;
  619.         repeat
  620.                 keyin (ch) ;
  621.                 key := ord(ch) ;
  622.                 case key of
  623.                   $20      : fld := fld + 1 ;
  624.                   prev_fld : fld := fld - 1 ;
  625.                   prev_page : fld := -999 ;
  626.                   escape   : fld := maxint ;
  627.                 end ;
  628.         until key in [$20, prev_fld, prev_page, escape] ;
  629.         clrline (1,24)
  630.     end ; {--- of PAUSE ---}
  631.  
  632. { ------------------------------------------------------------ }
  633.  
  634. procedure hard_pause ;
  635.   { Like Pause, but only accepts space bar or Escape and only goes forward }
  636.     var
  637.         ch   : char ;
  638.         key : integer ;
  639.     begin
  640.         clrline (1,24) ;
  641.         write_str ('PRESS SPACE BAR TO CONTINUE',26,24) ;
  642.         repeat
  643.                 keyin (ch) ;
  644.                 key := ord(ch) ;
  645.                 case key of
  646.                   $20      : fld := fld + 1 ;
  647.                   escape   : fld := maxint ;
  648.                 end ;
  649.         until key in [$20, escape] ;
  650.         clrline (1,24)
  651.     end ; {--- of hard_pause ---}
  652.  
  653. { ------------------------------------------------------------ }
  654.  
  655. procedure show_msg (msg : str_type) ;
  656.   { Beeps, displays message centered on line 23, pauses }
  657.  
  658.     var
  659.         savefld : integer ;
  660.  
  661.     begin
  662.         savefld := fld ;
  663.         beep ;
  664.         clrline (1,23) ;
  665.         write_str (msg,((80-length(msg)) div 2),23) ;
  666.         hard_pause ;
  667.         clrline (1,23) ;
  668.         fld := savefld ;
  669.     end ; { --- of SHOW_MSG --- }
  670.  
  671. { ----- EOF IO20.INC ----------------------------------------- }
  672.