(********************************************************************) (* *) (* echo.s7i Filter file which generates an echo of the input *) (* Copyright (C) 1992, 1993, 1994, 2005 Thomas Mertes *) (* *) (* This file is part of the Seed7 Runtime Library. *) (* *) (* The Seed7 Runtime Library is free software; you can *) (* redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) (* Foundation; either version 2.1 of the License, or (at your *) (* option) any later version. *) (* *) (* The Seed7 Runtime Library is distributed in the hope that it *) (* will be useful, but WITHOUT ANY WARRANTY; without even the *) (* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR *) (* PURPOSE. See the GNU Lesser General Public License for more *) (* details. *) (* *) (* You should have received a copy of the GNU Lesser General *) (* Public License along with this program; if not, write to the *) (* Free Software Foundation, Inc., 51 Franklin Street, *) (* Fifth Floor, Boston, MA 02110-1301, USA. *) (* *) (********************************************************************) (** * [[file|File]] implementation type which generates an echo of the input. *) const type: echoFile is sub null_file struct var file: inFile is STD_NULL; var file: outFile is STD_NULL; var integer: inPos is 1; end struct; (** * Open a file that echoes characters read from ''inFile'' to ''outFile''. * Reading operations are forwarded to ''inFile''. All normal characters * that are read from ''inFile'' are also written to ''outFile''. * @return the file opened. *) const func file: openEcho (in file: inFile, in file: outFile) is func result var file: newFile is STD_NULL; local var echoFile: new_echoFile is echoFile.value; begin new_echoFile.inFile := inFile; new_echoFile.outFile := outFile; new_echoFile.inPos := 1; newFile := toInterface(new_echoFile); end func; (** * Read a character from an echoFile. * The request is forwarded to ''inFile''. The character read from * ''inFile'' is written (echoed) to ''outFile''. Ctrl-C and ctrl-T * are handled special, as they can be used to terminate the * program. The user is asked for confirmation before the program * is terminated. * @return the character read, or [[char#EOF|EOF]] at the end of the file. *) const func char: getc (inout echoFile: inFile) is func result var char: charRead is ' '; local var integer: number is 0; begin repeat flush(inFile.outFile); (* cursor_on(inFile.outFile); *) charRead := getc(inFile.inFile); (* cursor_off(inFile.outFile); *) if charRead >= ' ' and charRead <= '~' then incr(inFile.inPos); write(inFile.outFile, charRead); elsif charRead = '\n' then inFile.inPos := 1; writeln(inFile.outFile); elsif charRead = '\b' then if inFile.inPos > 1 then decr(inFile.inPos); backSpace(inFile.outFile, " "); end if; elsif charRead = '\C' or charRead = '\T' then write(inFile.outFile, " terminate (y/n)? "); flush(inFile.outFile); if lower(getc(inFile.inFile)) = 'y' then writeln(inFile.outFile, "yes"); writeln(inFile.outFile); writeln(inFile.outFile, "*** PROGRAM TERMINATED BY USER"); exit(PROGRAM); else backSpace(inFile.outFile, " terminate (y/n)? "); end if; elsif charRead <> EOF then incr(inFile.inPos); write(inFile.outFile, '?'); end if; until charRead <> '\C' and charRead <> '\T'; end func; (** * Read a string with a maximum length from an echoFile. * @return the string read. * @exception RANGE_ERROR The parameter ''maxLength'' is negative. *) const func string: gets (inout echoFile: inFile, in integer: maxLength) is func result var string: striRead is ""; local var integer: number is 1; var char: ch is ' '; begin if maxLength < 0 then raise RANGE_ERROR; else while number <= maxLength and ch <> EOF do ch := getc(inFile); if ch <> EOF then striRead &:= str(ch); end if; incr(number); end while; end if; end func;