1 /******************************************************************************
2 
3     #     ####   #          #    #####           #    #
4     #    #    #  #          #    #    #          #    #
5     #    #    #  #          #    #####           ######
6     #    #    #  #          #    #    #   ###    #    #
7     #    #    #  #          #    #    #   ###    #    #
8     #     ####   ######     #    #####    ###    #    #
9 
10 ******************************************************************************/
11 /* This file is part of MAPMAKER 3.0b, Copyright 1987-1992, Whitehead Institute
12    for Biomedical Research. All rights reserved. See READ.ME for license. */
13 
14 /************* IOLIB.H - terminal and text file I/O functions *************
15 OVERVIEW:
16 
17 Terminal I/O is in general assumed to be "glass-TTY" type line
18 oriented blocking I/O with most relevent pre-processing handled by the
19 operating system or this library. (In other words, line editing
20 [delete keys and and so forth], buffering, echoing characters, and
21 type-ahead are handled.) Input will not be recieved until an entire
22 line has been read, and calls to input functions will hang until a
23 line is ready. Assume that 78 columns of output are possible, that output
24 lines scroll off the screen, and that at least 24 lines can fit on a
25 screen. Print()ed strings may be buffered until a '\n', flush(), or
26 input()/getln() call. These functions should be reasonably well-behaved
27 if the program's input or output has been redirected, piped, etc.
28 
29 The text file I/O routines operate very similarly. Random access or
30 binary files are not in general a good idea as both the code for such
31 files and the files themselves are largely unportable. It is also not
32 recomended that anything but a disk file be opened using the functions
33 here (eg do not do open_file("/dev/tty",READ)).
34 
35 Fancy output modes, including "photo-ing", MORE-processing, scrollback
36 and input/output redirection are provided by this library. These are
37 implemented in such a way that most application code can almost
38 completely ignore them: if the library I/O routines are used
39 exclusively (eg print()), something reasonable will happen whan thay
40 are called. The few routines which are exceptions return a boolean on
41 success or failure which can be tested.
42 
43 Even fancier stuff, like better line editing, split screen, and
44 asychronous scrollback has been or will be hacked into this library,
45 using curses, X-windows, or the Macintosh toolbox. This now works
46 under Unix, and VMS, and should work on PCs and Macs soon.
47 
48 The print string ps may be used to hold one screen line for output
49 using sprintf() and print() [or pr()]. Always print ps IMMEDIATELY
50 after it is set, otherwise it may get side-effected in your own
51 procedure calls!  Ps is large (2K chars) for paranoia's sake, as
52 sprintf() can spew out some very large strings of characterss in error
53 conditions. Assume its really only one (or maybe 2-3) lines. ps_ is similar,
54 but for internal use only by the functions in this library.
55 
56 Ln is a global input string side-effected by getln() and fgetln_().
57 The pointer ln itself may be side-effected, (eg: by the token parsing
58 routines) as it is reset during each call to getln() or fgetln_().
59 However, the string space used to hold the input line is reused, and
60 any pointers into the ln string which you saved may point to trash
61 after one of these calls. Ln is alloced for 2K chars, leaving lots of
62 room for paranoia (again, assume it's much smaller).
63 
64 Note that the print() and fprint() functions do an awful lot of
65 processing on the output string, including trying to wrap lines at
66 word breaks, converting tabs to spaces (every 8 chars), buffering
67 output (perhaps multiple lines!) and more. The do_fwrite() function does
68 not do this. Similarly, the getln() function despace()es,
69 lowercase()es, and filter()s its input, while fgetln_(), input(), and
70 finput() functions do not [yes, it's a somewhat odd inconsistancy, but
71 it's handy].
72 
73 It is recomended that only the I/O functions mentioned in here be
74 used, and that most other I/O functions never be used directly. This
75 is both because these functions have been tailored for portability and
76 robustness (crash-proofing), and because they provide a powerful
77 line-oriented interface which takes as much advantage of the operating
78 system as it can. Certainly never intermix code that uses these with
79 code that uses Unix-ish I/O directly!
80 
81 Iocheck() someday may be a function which should be called
82 occasionally to check for the break key, pending output for MORE, etc
83 on computers which don't support asynchronous terminal I/O. This is
84 best done inside some loop in any computationally ugly piece of code
85 such that it gets called at least once every few seconds. Iocheck()
86 returns TRUE if an entire line of input is waiting to be read with
87 input() or getln(). Do not place iocheck() calls inside
88 computationally critical loops, as iocheck() may take some time itself
89 (though likely doesn't).  NOTE: iocheck() IS NOT YET IMPLEMENTED - it
90 exists but does nothing, and it may never...
91 ***************************************************************************/
92 
93 
94 extern char *ps, *ln;  /* these global strings are malloced by io_init() */
95 void iocheck();   /* no args; CURRENTLY A NOP */
96 
97 
98 /************************ Terminal output routines ***********************/
99 void print();	 /* args: char *string; does lots of processing */
100 #define nl() print("\n")
101 #define pr() print(ps)
102 void flush();	 /* no args. forces everything print()ed to be output */
103 
104 bool temp_print(); /* args: char *str; The string is printed out and flush()ed,
105    although it will be erased upon the next call to print(), input(), getln(),
106    etc. A following call to temp_print() will erase the previous string
107    temp_print()ed, and temp_print(NULL) or temp_print("") explicitly
108    clears the last temp_print()ed string. Strings for temp_print may not
109    wrap, and may not contain tabs or newlines. Return FALSE if this is not
110    possible on the user's terminal type. */
111 
112 /* Nice screen control functions - the boolean functions do their stuff and
113    return TRUE if the operation was possible, or return FALSE otherwise. */
114 
115 bool boing(); /* make a noise, if possible */
116 
117 bool highlight();  /* args: bool val; sets highlighting (reverse video) mode-
118    NOTE: this mode may or may not be effective for only one screen line of
119    output! This needs to be handled as yet... */
120 
121 bool maybe_clear_screen();  /* no args; clears the screen, if it can,
122    although not if the terminal is believed to support scrollback or
123    not if curses is enabled. Returns TRUE if it did, FALSE if not. */
124 
125 bool clear_screen(); /* no args; does it anyway and returns TRUE if possible */
126 
127 bool to_column(); /* args: int num; (leftmost=0), returns FALSE if the cursor
128    is already right of the specified column */
129 int at_column(); /* no args; returns the current column (leftmost=0) */
130 void space();     /* args: int n; prints n spaces, regardless */
131 
132 void do_more();       /* no args: does a "Hit return for more" thing */
133 extern int tty_lines; /* You may look at this, but please do not set it. */
134 
135 
136 
137 /********************* Terminal input routines ****************************/
138 void input();   /* args: char *prompt, *string; int max_input_chars;
139    String must have room for max_input_chars+1 chars, and only
140    max_input_chars-1 chars can usually be read, as a '\n' may be read in
141    at the end and then deleted from the string. */
142 
143 void getln();   /* args: char *prompt; side-effects global string ln */
144 
145 /* NOTE: input() filter()s non-printing characters from the returned
146 string, but otherwise returns it verbatim, while getln() filter()s,
147 lowercase()s, and despace()s it! */
148 
149 bool redirect_input(); /* args: char *filename; bool verbose; */
150 /* Semantics are kind of like photo_to_file(). Begin taking standard
151    input from the specified file instead of where-ever it was comming
152    from.  Return FALSE if we fail (e.g. can't open file), in which case
153    nothing is changed. Note that input redirections may be layered inside
154    one-another, up to some reasonable depth. Use redirect_input(NULL) to
155    bag ALL redirects.  Redirect_input(TTY) should redirect to the
156    terminal (THIS IS NOT IMPLEMENTED YET!). */
157 #define TTY ""
158 
159 /* You may look at, but not set, these variables... */
160 #define redirecting_input (redirs>0)
161 extern bool interactive;        /* TRUE if input is currently a terminal */
162 
163 
164 /********************* Fancy Terminal I/O Modes **************************/
165 extern bool more, more_mode, ignore_eof;
166 /* User code could, but probably shouldn't set these variables.
167    Generally, more=FALSE, except in hold() blocks when more_mode=TRUE
168    Ignore_eof is on whether the standard input is a terminal or not.
169    All are set by tty_init() and get_cmd_line_args() */
170 
171 #define hold(with_more_on) \
172   for (do_hold(TRUE,with_more_on); holding>0; do_hold(FALSE,FALSE))
173 extern int holding;
174 /* This is the preferred interface to more, clearing screen, etc */
175 #define unhold() do_hold(FALSE,FALSE)
176 
177 bool photo_to_file(); /* args: char *name, *mode; Returns TRUE if it succeeds,
178    FALSE if it fails (e.g. unable to open file). If a photo file is already
179    open, it is closed and a new one is opened. This function will not affect
180    the current photo mode if it fails. Use name==NULL to turn photo-ing off. */
181 
182 #define log_open (photo_file[0]!='\0') /* Is photo-ing enabled? This will
183    return TRUE even if photo-ing has been temporarily disabled by
184    temp_logging(). To see if photoing is actually happening, look at
185    the logging variable. */
186 
187 extern char *photo_file; /* valid only if log_open is TRUE */
188 extern bool logging;     /* you may examine this, but don't set it directly */
189 
190 /* Here are some new functions to temporarily change fancy modes. These each
191    require a pointer to an int to hold the previous state. For example, to
192    temporarily inhibit logging to a file, use:
193 
194    	temp_logging(FALSE,&save);
195 	...
196 	prev_logging(save);
197 
198    If logging is already off, these calls will have no effect on the code.
199    DO NOT do anything silly to set these modes while inside of a temp mode
200    change, as the results are unpredictable! For example, do not call
201    photo_to_file() inside calls to temp_logging() and prev_logging();
202    Also, do not set the variable more inside calls to temp_more_mode() and
203    prev_more_mode(). In general, this means make sure that these calls do
204    not span any code which would toggle these things! */
205 
206 bool temp_logging();      /* args logging, *save_state; turn logging on/off:
207    To turn it on, a log-file must already be opened with photo_to_file()!
208    If not (the only failure case), FALSE is returned, otherwise TRUE is.
209    However, even in this case, the routine behaves well (that is, you can
210    ignore its return value if you don't care). */
211 void prev_logging();      /* args state; restore logging */
212 
213 bool temp_more_mode(); /* args new_more_mode,*save_state; turn more on/off */
214 void prev_more_mode(); /* args state; */
215 
216 void review_memory(); /* flips back through previous output in a nice way */
217 
218 
219 /******* Curses and WIMP (Windows, Icons, Mouse, and Pointers) Support *******/
220 
221 /* Use one (and only one) of these functions after custom_lib_init()
222    to enable and control really fancy screen management (see system.h for
223    details). These may invoke customized code for really funky WIMP stuff. */
224 
225 bool screen_init();  /* args: int *argc_ptr; char *argv[]; both may be side-
226    effected. Sets up funky screen I/O if possible - this may clear the
227    screen if it is appropriate to do so, among other things. This returns
228    TRUE if screen management (either curses or wimp) was enabled. */
229 
230 bool split_screen_init();
231 /* args: int *argc_ptr; char *argv[]; int top_lines; void (*update_func)();
232          both argc_ptr and argv may be side-effected.
233 	 update_func() gets args: char **text; int top_lines, top_columns;
234 
235    Like screen_init(), except the window is broken into two parts - a
236    top half which may be used to display status information, and a bottom
237    half which scrolls like an ordinary terminal. The top half will have
238    the specified # of lines, and will either be in reverse video or will
239    be separated from the bottom half somehow. The procedure
240    update_func may be called asynchronously, and should side-effect
241    the matrix of characters (text) to reflect what the top part should
242    display. */
243 
244 bool update_top();  /* Forces the top part of a split_screen to be updated.
245    FALSE is returned if split_screen() has not successfully set things up. */
246 void screen_end();  /* no args: undoes screen_init() or split_screen() */
247 
248 bool string_editor(); /* args: char *prompt, *str; int max_num_chars; */
249 
250 
251 /**************************** Text file routines  ****************************/
252 /* IMPORTANT: It is NOT OK to use the text file I/O routines on terminals or
253    other such devices: these routines are geared for real life text disk
254    files! (The obvious exception is logging and input redirection, for which
255    you should use the rather carefuly crafted routines described above!) */
256 
257 /* Mimics 'writable string' behaviour which wasn't problematic in some old
258    pre '89 code. GCC supported it for a long time via the -fwritable-strings
259    option. However, as of version 3.4, it was declared deprecated, and removed
260    in later versions. A lot of the code depends on this questionable behaviour,
261    so the following macro is used throughout this *BSD port. */
262 #define WRS(s)  (char[]){(s)}
263 
264 
265 bool make_filename(); /* args: char *name; int mode; char *extension;
266    This turns name into a perfectly valid file name, and returns TRUE if this
267    was possible. The name may include a directory specification - otherwise it
268    will be opened in the current working directory. name must be able to hold
269    PATH_LENGTH+1 chars. The argument mode should be one of... */
270 #define DEFAULT_EXTENSION  0  /* if name has no ext, one is added */
271 #define FORCE_EXTENSION	   1  /* even if name has an ext, it's changed */
272 
273 bool make_filename_in_dir();
274 /* args: char *name; int ext_mode; char *ext; int dir_mode; char *dir;
275    Like make_filename, but you can also specify a directory. You may use: */
276 #define FORCE_DIR	   0
277 #define DEFAULT_DIR  	   1
278 #define HOME_DIR           "*h*"
279 #define CODE_DIR           "*c*"
280 #define CURRENT_DIR        NULL
281 
282 FILE *open_file();  /* args: char *name, *mode; on failure sends CANTOPEN */
283 #define WRITE  "w"
284 #define READ   "r"
285 #define APPEND "a"
286 void close_file();  /* args: FILE *fp; */
287 
288 bool end_of_file(); /* args: FILE *fp; returns TRUE if finput() or fgetln_()
289    will be able to grab a new line from the file. */
290 bool end_of_text(); /* args: FILE *fp; Like an end-of-file test, except it also
291   returns TRUE if rest of the file is white. As a side-effect, it will step
292   through the file up to the first non-white char. */
293 
294 void fprint();    /* args: FILE *fp; char *string; processes output */
295 void do_fwrite(); /* args: FILE *fp; char *string; no processing happens */
296 #define fwrite(fp,str) (do_fwrite(fp,str))  /* UNIX already has an fwrite() */
297 
298 #define fpr(fp) fprint(fp,ps)
299 #define fwp(fp) fwrite(fp,ps)
300 #define fnl(fp) fwrite(fp,WRS("\n"))
301 
302 void finput();  /* args: FILE *fp; char *str; int max_input_chars; */
303 void fgetln_();  /* args: FILE *fp; side-effects global char *ln;
304    Finput() and fgetln_() both return a filter()ed line, and on end-of-file, the
305    ENDOFILE message is sent. Str must have room for max_input_chars+1 chars,
306    and only max_input_chars-1 chars can usually be read, as a '\n' may be read
307    in at the end and then deleted from the string. */
308 
309 void fgetdataln(); /* args: FILE *fp; int *count; side-effects global ln;
310    Like fgetln_(), although this skips null (white) and comment lines (those
311    beginning with a '#' in the leftmost position. Also, each time any line is
312    read from the file (data, null, or comment), *count is incremented. */
313 
314 #define frewind(fp) fseek(fp,0L,0)
315 #define fflush(fp)  do_fflush(fp)  /* redeclare the C library function */
316 void do_fflush(); /* never call this directly */
317 
318 bool rename_file();
319 /* args: char *old, new; in syscode.c renames old file with new name */
320 
321 bool fgoto_line(); /* in syscode.c - replacement for fseek() */
322 /* args: FILE *fp; long index; */
323 
324 
325 /***** Local declarations provided for syscode.c: for internal use only! *****/
326 
327 extern char *out_file, *in_file, *photo_file;
328 extern char out_modechar, in_modechar, photo_modechar;
329 extern FILE *in, *out, *photo;
330 
331 #define MAX_FILE_ARGS  3
332 #define LOAD_FILE_ARG  0
333 #define RUN_FILE_ARG   1
334 #define PHOTO_FILE_ARG 2
335 extern char **file_arg;
336 extern int num_file_args, dos_output, prep_it, append_it;
337 
338 extern char *ps_, *ln_;     /* input and output strings for the library only */
339 extern char *linebuf;       /* tty output buffer */
340 extern char *gotln, *lnptr; /* input line for getln(), fgetln_() */
341 
342 extern FILE **in_fp;   /* the "stack" of input files for redirecting input */
343 extern int redirs;
344 #define MAXREDIRECTS 	4
345 #define MAXFILES 	10
346 
347 /* a list associating fp's with names etc */
348 typedef struct { FILE *fp; char modechar; char *name; } FILE_INFO;
349 extern FILE_INFO **files;
350 int lookup_fp();
351 void ioerror();
352 
353 void tty_init();  /* no args: in syscode.c, called by lib_init() */
354 void io_init();   /* no args: in iolib.c, called by lib_init() */
355 void tty_hello(); /* no args */
356 
357 extern int cursor, buf, printed_lines, supress_more, lines_written;
358 extern int term, tty_lines;
359 extern bool screen, scrollback;
360 extern int tty_errors, file_errors, puts_errors;
361 
362 #define MAXLINE  2050
363 #define LINE     79
364 #define LASTTAB  72
365 
366 #define TERM_UNKNOWN      0 /* term types */
367 #define ANSI              1
368 #define HP_TERM           2
369 #define CURSES            8
370 #define SCROLLING_ANSI    3
371 #define NONSCROLLING_ANSI 4
372 #define PC_CONSOLE        5
373 #define MAC_WINDOW        6
374 #define WIMP              7
375 
376 bool boing();
377 bool do_clear_screen();
378 bool do_highlight();
379 bool do_delete_previous_line();
380 bool do_cursor_left(); /* args int spaces; char *str_to_then_print; */
381 #define FAR_LEFT -1
382 bool check_tty_lines();
383 
384 void lib_puts();
385 bool tty_gets();
386 bool file_gets();
387 void ioerror();
388 void flush_and_force_nl();
389 extern bool supress_more, more_break_pending;
390 
391 extern bool curses, split;
392 extern bool tried_curses, tried_split, have_drawn_top;
393 /* These functions exist if HAVE_CURSES is defined. */
394 bool curses_init();
395 bool curses_split();
396 void curses_end();
397 void curses_error();
398 void curses_clr_scrn();
399 void curses_del_prev_ln();
400 void curses_del_this_ln();
401 void curses_del_to_eol();
402 void curses_goto_far_left();
403 void curses_cursor_left();
404 void curses_set_highlight();
405 bool curses_gets();
406 void curses_puts();
407 void curses_scrollup();
408 void curses_flush();
409 void curses_boing();
410 void curses_refresh();
411 void curses_update_top();
412 void curses_draw_top();
413 
414 extern bool wimp, tried_wimp;
415 /* These functions exist if HAVE_WIMP is defined. */
416 void do_text_wimp_init();
417 void do_split_wimp_init();
418 void do_custom_wimp_init(); /* Only MAY exist... */
419 
420 extern bool use_gnu_readline;
421 bool do_gnu_readline();
422 bool do_gnu_edit();
423 bool gnu_copyright();
424 
425 bool edit_line(); /* make real decl above */
426 
427