{ INTOOLS  -  Procedures and Functions for interactive input in Pascal
  Copyright (c) 1984 by Ronald Florence    

  These procedures and functions were written to avoid the horrors of
  "Data Format Error in file USER" crashes. The procedures will work
  with IBM Pascal or MS-Pascal, and can be incorporately separately as
  needed with {$include} metacommands. 

    RDREAL: reads a real number (positive or negative) in decimal format
    RDINT: reads an integer (positive or negative) within a specified range
    RDCHAR: reads a character in a specified set  (inkey)
    NOMORE: prompts the user with 'More?' and reads a 'y' or 'n' (inkey)
    YESNO: reads a 'y' or 'n' (inkey)

  Use the tools in 'repeat...until' loops. For example:
      repeat
          write ('Enter an integer between 0 and 10: ');
      until rdint(0,10);
  Include 'charset = set of char' as a type declaration when using RDCHAR    }



function rdreal (var  r: real): boolean;
    const    bell = chr (7);
    var   decimal, left, right: real;
          neg: boolean;
begin
    left:= 0;
    decimal:= 1;
    right:= 0;
    neg:= false;
    while not eoln and not (input^ in [chr(33)..chr(255)]) do get (input);
    neg:= input^ = chr(45);
    if neg then get (input);
    rdreal:= input^ in ['0'..'9'];
    while input^ in ['0'..'9'] do begin;
        left:= left * 10 + ord (input^) - ord ('0');
        get (input);
    end;
    if input^ = chr(46) then begin
        get (input);
        while input^ in ['0'..'9'] do begin
            right:= right + decimal * (ord (input^) - ord ('0')) / 10;
            decimal:= decimal / 10;
            get (input);
        end;
    end;
    r:= left + right;
    if neg then r:= - r;
    if input^ in [chr(33)..chr(44), chr(47), chr(58)..chr(255)] then begin
        rdreal:= false;
        write (bell);
    end;
    readln;
end;


function rdint (var  i:integer; low,high:integer): boolean;
    const   bell = chr (7);
    var   neg: boolean;
begin
    i:= 0;
    neg:= false;
    while not eoln and not (input^ in [chr(33)..chr(255)]) do get (input);
    neg:= input^ = chr(45);
    if neg then get (input);
    while input^ in ['0'..'9'] do begin
        i:= i * 10 + ord (input^) - ord ('0');
        get (input);
    end;
    if neg then i:= - i;
    if (input^ in [chr(33)..chr(44), chr(46), chr(47), chr(58)..chr(255)]) or
        (eoln and ((i < low) or (i > high))) then begin
            rdint:= false;
            write (bell);
    end
    else rdint:= (i >= low) and (i <= high);
    readln;
end;


function rdchar (okchars: charset): char;
var   f, g: file of char;
      c: char;
function inkey: char;
    begin
        repeat get (f) until f^ <> chr (0);
        inkey:= f^;
    end;
begin
    assign (f, 'user');
    reset (f);
    assign (g, 'user');
    rewrite (g);
    repeat
        c:= inkey;
        if not (c in okchars) then if c in ['A'..'Z'] then
            c:= chr (ord(c) - ord('A') + ord('a'))
        else if c in ['a'..'z'] then c:= chr (ord(c) - ord('a') + ord('A'));
    until c in okchars;
    write (g, c);
    writeln;
    rdchar:= c;
end;


function nomore: boolean;
var   f, g: file of char;
      c: char;
function inkey: char;
    begin
        repeat get (f) until f^ <> chr (0);
        inkey:= f^;
    end;
begin
    write ('More? ');
    assign (f, 'user');
    reset (f);
    assign (g, 'user');
    rewrite (g);
    repeat c:= inkey until c in ['y','Y','n','N'];
    write (g, c);
    writeln;
    nomore:= c in ['n', 'N']
end;


function yes: boolean;
var   f, g: file of char;
      c: char;
function inkey: char;
    begin
        repeat get (f) until f^ <> chr (0);
        inkey:= f^;
    end;
begin
    assign (f, 'user');
    reset (f);
    assign (g, 'user');
    rewrite (g);
    repeat c:= inkey until c in ['y','Y','n','N'];
    write (g,c);
    writeln;
    yes:= c in ['y', 'Y'];
end;
 rewrite (g);
    repeat c:= inkey until c in ['y','Y','n','N'];
    write (g,c);
    writel