type
       zeile = string[80];


procedure LF(lines : integer);      { linefeeds }

begin
       while (lines > 0) do begin
           writeln;
           lines := lines - 1;
       end;
end;


procedure BEEP(n : integer);         { BEEPs }

begin
       while (n > 0) do begin
          write(chr(7));
          n := n - 1;
       end;
end;


procedure CUROFF;                   { Cursor off }

begin
       write(chr(27),'.0');
end;


procedure CURON;                    { Cursor on, displayed as _ }

begin
       write(chr(27),'.4');
end;


procedure HALF(str : zeile);       { str is printed in lowvideo }

begin
       lowvideo;
       write(str);
       normvideo;
end;


procedure PUL(str : zeile);        { str is displayed in the status line }

begin
       write(chr(27),'f');
       writeln(str);
       write(chr(27),'g');
end;


procedure LINE(n : integer);

begin
       while (n > 0) do begin
          write('-');
          n := n - 1;
       end;
end;


procedure SNV(n : integer);

begin
       write(chr(27),'~!',chr(n+48));
end;


procedure SPACES(n : integer);

begin
       write('':n);
end;


{ the input fuction getstr is written for TURBO-Pascal and allows
  the user to define a window (maximal one line) in which text can
  be edited WORDSTAR like }

type
       menge  = set of char;


function getstr(VAR bptr : zeile; x,y,len : integer; bereich : menge;
                exact : boolean; endset : menge) : char;

{ - buffer is the string, which is edited
  - x,y are the coordinates, where the window starts
  - len is the maximal length of the window
  - bereich is the amount of characters, which are allowed for input
  - if the exact flag is set the user must enter exactly len characters }

const
       BS       = ^H;     { cursor left/delete }
       DEL      = #127;   { cursor left/delete }
       FIELDL   = ^A;     { cursor to the beginning of the left word }
       FIELDR   = ^F;     { cursor to the beginning of the right word }
       CHARD    = ^G;     { delete character }
       WORDD    = ^T;     { delete word }
       LINED    = ^Y;     { delete line }
       CULEFT   = ^S;     { cursor left }
       CURIGHT  = ^D;     { cursor right }
       CTRL_L   = ^L;     { ctrl - L }
       CTRL_Q   = ^Q;     { ctrl - Q }
       CTRL_V   = ^V;     { ctrl - V }
       CTRL_Y   = ^Y;     { ctrl - Y }

var
       exit      : boolean;
       insert_on : boolean;
       i,j,max   : integer;
       c         : char;
       default   : zeile;


procedure delete_to_eoln;

{ deletes from the cursor position to the end of line }


begin
       gotoxy(x+i-1,y);
       write(^[,'T');
       gotoxy(x+i-1,y);
end;


procedure char_delete(anzahl : integer);

{ deletes the character at the actual cursor position
  and shifts the following characters to the left      }

var
       j : integer;

begin
       if i < max then begin
          bptr[0] := chr(max);
          delete(bptr,i,anzahl);
          max := max - anzahl;
          delete_to_eoln;
          for j := i to max-1 do
             write(bptr[j]);
          gotoxy(x+i-1,y);
       end;
end;


procedure init;

{ initialize start configuration }

begin
       insert_on := true;
       max       := length(default) + 1;
       i         := max;
       bptr      := default;
       gotoxy(x,y);
       write(default);
       delete_to_eoln;
       i         := 1;
       gotoxy(x,y);
end;


begin
       exit    := false;
       default := bptr;
       init;
       while not exit do begin
          read(kbd,c);
          if c in bereich then begin
             if (max <= len) OR ((not insert_on) AND (i <= len)) then begin
                if insert_on then begin
                   bptr[0] := char(max + 1);
                   insert(c,bptr,i);
                   delete_to_eoln;
                   for j := i to max do
                      write(bptr[j]);
                   gotoxy(x+i,y);
                   i   := i + 1;
                   max := max + 1;
                end
                else begin
                   gotoxy(x+i-1,y);
                   write(c);
                   bptr[i] := c;
                   i := i + 1;
                   if max < i then max := i;
                end;
             end
             else
                write(#7);
          end
          else case c of
             CULEFT  : if i > 1 then begin
                          i := i - 1;
                          gotoxy(x+i-1,y);
                       end;
             CURIGHT : if i < max then begin
                          i := i + 1;
                          gotoxy(x+i-1,y);
                       end;
             FIELDL  : begin
                          repeat
                             if i > 1 then i := i - 1 ;
                          until (i=1) or ((bptr[i]<>' ') AND (bptr[i-1]=' '));
                          gotoxy(x+i-1,y);
                       end;
             FIELDR  : begin
                          repeat
                             if i < max then i := i + 1;
                          until (i=max) or ((bptr[i]<>' ') AND (bptr[i-1]=' '));
                          gotoxy(x+i-1,y);
                       end;
             BS,DEL  : if i > 1 then begin
                          i := i - 1;
                          char_delete(1);
                       end;
             CHARD   : char_delete(1);
             WORDD   : begin
                          j := i;
                          repeat
                             if j < max then j := j + 1;
                          until (j=max) or ((bptr[j]<>' ') AND (bptr[j-1]=' '));
                          char_delete(j-i);
                       end;
             LINED   : begin
                          i   := 1;
                          max := 1;
                          delete_to_eoln;
                       end;
             CTRL_Q  : begin
                          read(kbd,c);
                          case c of
                             CTRL_Y  : char_delete(max-i);
                             { deletes from cursor to end of line }

                             CTRL_L  : init;
                             { removes all changes and restarts the input }

                          else
                                       write(#7);
                          end;
                       end;
             CTRL_V  : insert_on := not insert_on;
             else
                       if c in endset then
                          exit := ((exact = false) OR
                                   ((exact = true) AND (len = max-1)))
                       else
                          write(#7);
          end;
       end;
       bptr[0] := chr(max-1);
       getstr    := c;
end;

