1
2(********************************************************************)
3(*                                                                  *)
4(*  echo.s7i      Filter file which generates an echo of the input  *)
5(*  Copyright (C) 1992, 1993, 1994, 2005  Thomas Mertes             *)
6(*                                                                  *)
7(*  This file is part of the Seed7 Runtime Library.                 *)
8(*                                                                  *)
9(*  The Seed7 Runtime Library is free software; you can             *)
10(*  redistribute it and/or modify it under the terms of the GNU     *)
11(*  Lesser General Public License as published by the Free Software *)
12(*  Foundation; either version 2.1 of the License, or (at your      *)
13(*  option) any later version.                                      *)
14(*                                                                  *)
15(*  The Seed7 Runtime Library is distributed in the hope that it    *)
16(*  will be useful, but WITHOUT ANY WARRANTY; without even the      *)
17(*  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR *)
18(*  PURPOSE.  See the GNU Lesser General Public License for more    *)
19(*  details.                                                        *)
20(*                                                                  *)
21(*  You should have received a copy of the GNU Lesser General       *)
22(*  Public License along with this program; if not, write to the    *)
23(*  Free Software Foundation, Inc., 51 Franklin Street,             *)
24(*  Fifth Floor, Boston, MA  02110-1301, USA.                       *)
25(*                                                                  *)
26(********************************************************************)
27
28
29(**
30 *  [[file|File]] implementation type which generates an echo of the input.
31 *)
32const type: echoFile is sub null_file struct
33    var file: inFile is STD_NULL;
34    var file: outFile is STD_NULL;
35    var integer: inPos is 1;
36  end struct;
37
38
39(**
40 *  Open a file that echoes characters read from ''inFile'' to ''outFile''.
41 *  Reading operations are forwarded to ''inFile''. All normal characters
42 *  that are read from ''inFile'' are also written to ''outFile''.
43 *  @return the file opened.
44 *)
45const func file: openEcho (in file: inFile, in file: outFile) is func
46  result
47    var file: newFile is STD_NULL;
48  local
49    var echoFile: new_echoFile is echoFile.value;
50  begin
51    new_echoFile.inFile := inFile;
52    new_echoFile.outFile := outFile;
53    new_echoFile.inPos := 1;
54    newFile := toInterface(new_echoFile);
55  end func;
56
57
58(**
59 *  Read a character from an echoFile.
60 *  The request is forwarded to ''inFile''. The character read from
61 *  ''inFile'' is written (echoed) to ''outFile''. Ctrl-C and ctrl-T
62 *  are handled special, as they can be used to terminate the
63 *  program. The user is asked for confirmation before the program
64 *  is terminated.
65 *  @return the character read, or [[char#EOF|EOF]] at the end of the file.
66 *)
67const func char: getc (inout echoFile: inFile) is func
68  result
69    var char: charRead is ' ';
70  local
71    var integer: number is 0;
72  begin
73    repeat
74      flush(inFile.outFile);
75(*    cursor_on(inFile.outFile); *)
76      charRead := getc(inFile.inFile);
77(*    cursor_off(inFile.outFile); *)
78      if charRead >= ' ' and charRead <= '~' then
79        incr(inFile.inPos);
80        write(inFile.outFile, charRead);
81      elsif charRead = '\n' then
82        inFile.inPos := 1;
83        writeln(inFile.outFile);
84      elsif charRead = '\b' then
85        if inFile.inPos > 1 then
86          decr(inFile.inPos);
87          backSpace(inFile.outFile, " ");
88        end if;
89      elsif charRead = '\C' or charRead = '\T' then
90        write(inFile.outFile, " terminate (y/n)? ");
91        flush(inFile.outFile);
92        if lower(getc(inFile.inFile)) = 'y' then
93          writeln(inFile.outFile, "yes");
94          writeln(inFile.outFile);
95          writeln(inFile.outFile, "*** PROGRAM TERMINATED BY USER");
96          exit(PROGRAM);
97        else
98          backSpace(inFile.outFile, " terminate (y/n)? ");
99        end if;
100      elsif charRead <> EOF then
101        incr(inFile.inPos);
102        write(inFile.outFile, '?');
103      end if;
104    until charRead <> '\C' and charRead <> '\T';
105  end func;
106
107
108(**
109 *  Read a string with a maximum length from an echoFile.
110 *  @return the string read.
111 *)
112const func string: gets (inout echoFile: inFile, in integer: maxLength) is func
113  result
114    var string: striRead is "";
115  local
116    var integer: number is 1;
117    var char: ch is ' ';
118  begin
119    while number <= maxLength and ch <> EOF do
120      ch := getc(inFile);
121      if ch <> EOF then
122        striRead &:= str(ch);
123      end if;
124    end while;
125  end func;
126