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 /**************** SYSCODE.C - SYSTEM SPECIFIC CODE ***************************/
15 /* Most of this file is doccumented in system.h - it contains most of the
16 system dependent code for the helpers library. */
17
18 #define INC_LIB
19 #define INC_EQN
20 #define INC_HELP_DEFS
21 #include "system.h"
22
23 #ifdef _GNU_READLINE
24 #include "readline/readline.h"
25 #include "readline/history.h"
26 #endif
27
28 /*********************** C-Library Extensions ********************************/
29
30 /***** Time functions *****/
31 /* Note that time() and ctime() seem to be the only portable time functions.
32 However, time() returns different types with different C compilers! */
33
34 TIME_TYPE old_stamp, new_stamp; /* For local use only! */
35
usertime(do_reset)36 real usertime(do_reset) /* return time in seconds, or -1.0 if fail */
37 bool do_reset;
38 {
39 real rtime;
40 new_stamp= time((TIME_TYPE *)NULL); rtime= (real)(new_stamp - old_stamp);
41 if (do_reset) old_stamp= new_stamp;
42 return(rtime);
43 }
44
time_string()45 char *time_string() /* return ptr to "" if fail */
46 {
47 TIME_TYPE the_time; /* note that asctime() does not always exist */
48 char *str;
49 int end;
50
51 the_time=time((TIME_TYPE *)NULL);
52 str=ctime(&the_time);
53 if (str==NULL) return(ptr_to(""));
54 end=len(str)-1;
55 if (str[end]=='\n') str[end]='\0';
56 return(str);
57 }
58
59
60 /***** subprocess functions *****/
61
62
shell_command(cmd)63 bool shell_command(cmd)
64 char *cmd;
65 {
66 bool success, had_curses;
67 success=FALSE;
68
69 #ifdef NO_SYSTEM_FUNC
70 return(FALSE);
71 #else
72 /* NEED WIMP HOOK */
73 #ifdef HAVE_CURSES
74 had_curses= curses;
75 if (curses) curses_end(); /* DO SOMETHING */
76 #endif
77 #ifndef VMS
78 if (system(cmd)==0) success=TRUE;
79 #endif
80 #ifdef VMS
81 if (system(cmd)!=0) success=TRUE;
82 #endif
83 #ifdef HAVE_CURSES
84 if (success && had_curses) curses_refresh();
85 #endif
86 return(success);
87 #endif
88 }
89
90
subshell()91 bool subshell()
92 {
93 char *shell_name, cmd[120];
94 bool success=FALSE, had_curses;
95
96 #ifdef NO_SYSTEM_FUNC
97 return(FALSE);
98 #else
99 /* NEED WIMP HOOK */
100 #ifdef HAVE_CURSES
101 had_curses= curses;
102 if (curses) curses_end(); /* DO SOMETHING */
103 #endif
104 #ifdef TRY_SHELL_VAR
105 if ((shell_name=getenv("SHELL"))!=NULL && !nullstr(shell_name)) {
106 nstrcpy(cmd,shell_name,100); /* maxstrcat(cmd," -i",110); why? */
107 if (system(cmd)==0) success=TRUE;
108 }
109 #endif
110 #ifdef TRY_COMSPEC_VAR
111 if (!success && (shell_name=getenv("COMSPEC"))!=NULL &&
112 !nullstr(shell_name)) {
113 if (system(shell_name)==0) success=TRUE;
114 }
115 #endif
116 #ifdef TRY_SHELL_CMD
117 if (!success && !nullstr(TRY_SHELL_CMD)) {
118 if (system(TRY_SHELL_CMD)==0) success=TRUE;
119 }
120 #endif
121 #ifdef HAVE_CURSES
122 if (success && had_curses) curses_refresh();
123 #endif
124 return(success);
125 #endif
126 }
127
128
129 /***** get/set directories *****/
130
change_directory(dir)131 bool change_directory(dir)
132 char *dir;
133 {
134 if (dir==NULL) send(CRASH);
135 #ifdef HAVE_CHDIR
136 if (chdir(dir)==0) return(TRUE);
137 #endif
138 return(FALSE);
139 }
140
get_directory(buf)141 bool get_directory(buf)
142 char *buf;
143 {
144 if (buf==NULL) send(CRASH);
145 #ifdef HAVE_GETCWD
146 if (getcwd(buf,PATH_LENGTH-2)!=NULL) return(TRUE);
147 #endif
148 return(FALSE);
149 }
150
get_home_directory(buf)151 bool get_home_directory(buf)
152 char *buf;
153 {
154 char *dir;
155 if (buf==NULL) send(CRASH);
156 #ifdef HAVE_GETENV
157 if ((dir=getenv("HOME"))!=NULL)
158 { nstrcpy(buf,dir,PATH_LENGTH); return(TRUE); }
159 #endif
160 return(FALSE);
161 }
162
get_code_directory(buf)163 bool get_code_directory(buf)
164 char *buf;
165 {
166 char *dir;
167 if (buf==NULL) send(CRASH);
168 #ifdef HAVE_GETENV
169 if ((dir=getenv("MAPM_LIB"))!=NULL)
170 { nstrcpy(buf,dir,PATH_LENGTH); return(TRUE); }
171 #endif
172 #ifdef _CODE_DIR /* compiled in default */
173 if (!nullstr(_CODE_DIR))
174 { nstrcpy(buf,_CODE_DIR,PATH_LENGTH); return(TRUE); }
175 #endif
176 return(FALSE);
177 }
178
rename_file(original_name,new_name)179 bool rename_file(original_name,new_name)
180 char *original_name, *new_name;
181 {
182 #ifdef _SYS_DOS
183 sf(ps,"copy %s %s",original_name,new_name);
184 if (system(ps)==0) return(TRUE);
185 else return(FALSE);
186 #else
187 if (rename(original_name,new_name)==-1) return(FALSE);
188 else return(TRUE);
189 #endif
190 }
191
192
fgoto_line(fp,index)193 bool fgoto_line(fp,index)
194 FILE *fp;
195 long index;
196 {
197 #ifdef REPLACE_FSEEK
198 long fseekvalue= 0L;
199 frewind(fp);
200 run while (fseekvalue < index-1) {
201 fgetln_(help_file);
202 fseekvalue+=len(ln)+1;
203 } except_when(ENDOFILE) return(FALSE);
204 return(TRUE);
205 #endif
206 return(fseek(fp,index,0)!=-1);
207 }
208
209 /***** random number functions *****/
210
mkseed(x)211 long mkseed(x) long x;
212 { if (x==RANDOM) return((long)time(NULL)); else return(x); }
213
214 #ifdef USE_RANDOM
do_seedrand(x)215 void do_seedrand(x) long x; { srandom((int)mkseed(x)); }
randnum()216 real randnum() { return(((real)random())/2147483648.0); }
217 #else
218 #ifdef USE_DRAND48
do_seedrand(x)219 void do_seedrand(x) long x; { srand48(mkseed(x)); }
randnum()220 real randnum() { return(drand48()); }
221 #else /* USE_SRAND */
do_seedrand(x)222 void do_seedrand(x) long x; { srand((int)mkseed(x)); }
randnum()223 real randnum() { return(((real)rand())/((real)(RAND_MAX+1))); }
224 #endif
225 #endif
226
227
228 /***** message and signal handling *****/
229
untrapped_msg()230 void untrapped_msg() /* DO NOT ASSUME THAT MSGNAME IS SET! */
231 {
232 /* if (msg!=IOERROR) flush(); most are disk errors */
233 if (msg<1 || msg>MSGS)
234 { fprintf(stderr, "Untrapped error %d (???)\n",msg); exit(1); }
235 fprintf(stderr,"Untrapped error %d (%s)\n",msg,mname[msg]);
236 (*(mstrmsg[msg]))(ps_); fprintf(stderr,ps_); fprintf(stderr,"\n");
237 }
238
trapped_msg()239 void trapped_msg() /* DO NOT ASSUME THAT MSGNAME IS SET! */
240 {
241 /* if (msg!=IOERROR) flush(); most are disk errors */
242 if (msg<1 || msg>MSGS)
243 { fprintf(stderr,"Error %d (???)\n",msg); exit(1); }
244 fprintf(stderr,"Error %d (%s)\n",msg,mname[msg]);
245 (*(mstrmsg[msg]))(ps_); fprintf(stderr,ps_); fprintf(stderr,"\n");
246 }
247
248 #define SHUTDOWN1 "NOTE: In some extreme cases you may have to shut down and "
249 #define SHUTDOWN2 "restart the\nprogram in order to resume proper operation. "
250 #define SHUTDOWN3 "Hit <return> to continue..."
251
verbose_untrapped_msg()252 void verbose_untrapped_msg() /* DO NOT ASSUME THAT MSGNAME IS SET! */
253 {
254 fprintf(stderr,"*** Drats! An unhandled internal error occured. ***\n");
255 if (msg<1 || msg>MSGS) { fprintf(stderr,"error #%d (???)\n",msg); exit(1); }
256 else fprintf(stderr,"Error message #%d (%s) was sent.\n",msg,mname[msg]);
257 (*(mstrmsg[msg]))(ps_); fprintf(stderr,ps_);
258 if (!nullstr(ps_)) fprintf(stderr,"\n");
259 fprintf(stderr,SHUTDOWN1); fprintf(stderr,SHUTDOWN2);
260 fprintf(stderr,SHUTDOWN3); fgets(ps_,MAXLINE,stdin);
261 fprintf(stderr,"\n");
262 }
263
do_trap()264 void do_trap()
265 {
266 if (msg<1 || msg>MSGS)
267 { fprintf(stderr,"Illegal trap message\n"); exit(1); }
268 fprintf(stderr,"Trapped message %d (%s)\n",msg,mname[msg]);
269 (*(mstrmsg[msg]))(ps_); fprintf(stderr,ps_);
270 }
271
272
273 int signals;
274
sigcounter()275 void sigcounter()
276 { signals++; if (signals>MAX_BAD_SIGNALS) send(CRASH); }
277
278
signal_trap_init()279 void signal_trap_init()
280 {
281 signals=0;
282
283 signal(SIGQUIT, handle_quit); /* ANSI Signals - for Microsoft C */
284 signal(SIGINT, handle_interrupt);
285 signal(SIGFPE, handle_matherror);
286 signal(SIGILL, handle_weird_signal);
287 signal(SIGSEGV, handle_buserror);
288 signal(SIGTERM, handle_quit);
289 }
290
291
292
293 /********************************** I/O *************************************/
294
295 void get_screen_preferences();
296 void tty_hello();
297
298 int old_term, old_lines, old_scrollback, old_more, dos_output;
299 bool tried_curses, tried_wimp, tried_split, have_drawn_top;
300 int tty_errors, file_errors, puts_errors;
301 int curses, split, wimp, use_gnu_readline; /* externed global bools */
302 char **file_arg;
303 int num_file_args, prep_it, append_it;
304
305
do_gnu_readline(prompt,str,num)306 bool do_gnu_readline(prompt,str,num)
307 char *prompt, *str;
308 int num;
309 {
310 #ifndef _GNU_READLINE
311 send(CRASH);
312 return(FALSE);
313 #else
314 char *result=NULL;
315
316 result= readline(prompt);
317 if (result==NULL) return(FALSE); /* EOF */
318
319 nstrcpy(str,result,num-2);
320 add_history(str);
321 free((char*)result);
322 return(TRUE);
323 #endif
324 }
325
326
do_gnu_edit(prompt,str,num,initial)327 bool do_gnu_edit(prompt,str,num,initial)
328 char *prompt, *str;
329 int num;
330 char *initial; /* initial may be = str */
331 {
332 #ifndef _GNU_READLINE
333 send(CRASH);
334 return(FALSE);
335 #else
336 char *result=NULL, *hist_entry=NULL;
337
338 result= gnu_edit_this(prompt,initial);
339 if (result==NULL) return(FALSE); /* EOF */
340
341 nstrcpy(str,result,num-2);
342 add_history(str);
343 free((char*)result);
344 return(TRUE);
345 #endif
346 }
347
348
gnu_copyright(str)349 bool gnu_copyright(str)
350 char *str; /* side-effected, so it must be big enough */
351 {
352 #ifndef _GNU_READLINE
353 return(FALSE);
354 #else
355 if (!use_gnu_readline) return(FALSE);
356 sf(str,"GNU Readline Copyright 1988-1989, Free Software Foundation");
357 return(TRUE);
358 #endif
359 }
360
361
tty_gets(str,num)362 bool tty_gets(str, num)
363 char *str; /* must be num+2 chars long, but use num<<len just in case */
364 int num; /* num chars, not including the '\n' or '\0', will be read */
365 /* May send IOERROR, or (hopefully never) CRASH. Return FALSE on EOF.
366 In general, we probably want num to be huge (eg: MAXLINE),
367 as exceeding it causes an I/O error message to be sent.
368 If fgets() works correctly, then line should be valid on EOF, although
369 FALSE is still returned. The operating system is responsible for
370 any post-processing. */
371 {
372 int n, i;
373
374 in_tty_gets = TRUE; hit_interrupt = FALSE;
375
376 if (num<2) send(CRASH);
377 for (i=0; i<num+2; i++) str[i]='\0'; /* To get ok string if EOF */
378
379 if (fgets(str,num+1,in)==NULL) { /* EOF or error */
380 str[num]='\0'; /* in case fgets() is weird */
381 if (++tty_errors>MAX_IO_FAILURES) send(CRASH);
382 if ((n=ferror(in))!=0) ioerror(strerror(n),in,str); /* error */
383 if (feof(in)) return(FALSE); /* else must be EOF */
384 ioerror("fgets() failed",in,str); /* I dunno? */
385 }
386
387 if(hit_interrupt) { str[0] = '\n'; str[1] = '\0'; }
388 in_tty_gets = FALSE;
389
390 cursor=0; printed_lines=0;
391 if (str[0]=='\0' || str[len(str)-1]!='\n') { /* no \n => truncated */
392 if (++tty_errors>MAX_IO_FAILURES) send(CRASH);
393 else ioerror("input line too long",in,str);
394 }
395 tty_errors= 0;
396 return(TRUE);
397 }
398
399
file_gets(fp,str,num)400 bool file_gets(fp,str,num)
401 FILE *fp; /* must be opened with file_open() */
402 char *str; /* must be num+2 chars long, but use num+3 in case of weirdness */
403 int num; /* num chars, not including the '\n' or '\0', will be read */
404 {
405 int i, c, n;
406
407 for (i=0; (c=fgetc(fp))!='\n'; i++)
408 if (c==EOF) { /* error or EOF */
409 str[i]='\0';
410 if (++file_errors>MAX_IO_FAILURES) send(CRASH);
411 else if (feof(fp)) { if (i==0) return(FALSE); else return(TRUE); }
412 else if ((n=ferror(fp))!=0) { ioerror(strerror(n),fp,str); }
413 else ioerror("fgetc() failed",fp,str);
414 } else if (i==num-1) {
415 str[i]='\0';
416 while ((c=fgetc(fp))!='\n') if (c==EOF) break;
417 if (++file_errors>MAX_IO_FAILURES) send(CRASH);
418 ioerror("input line too long",fp,str);
419 } else { /* all is OK */
420 str[i]=c; continue;
421 }
422 str[i]='\0';
423 file_errors= 0;
424 return(TRUE);
425 }
426
427
lib_puts(fp,str)428 void lib_puts(fp,str)
429 FILE *fp;
430 char *str;
431 {
432 int i, n;
433 char c;
434
435 if (fp==NULL || str==NULL) send(CRASH);
436 #ifdef HAVE_CURSES
437 if (curses && fp==out) { curses_puts(str); } else
438 #endif
439 {
440 for (i=0; (c=str[i])!='\0'; i++) {
441 if (c=='\n' && dos_output && fp!=out && !xputc('\015',fp)) {
442 if (++puts_errors>=MAX_IO_FAILURES) send(CRASH);
443 if ((n=ferror(fp))!=0) ioerror(strerror(n),fp,str);
444 else ioerror("xputc() failed",fp,str);
445 }
446 if (!xputc(c,fp)) {
447 if (++puts_errors>=MAX_IO_FAILURES) send(CRASH);
448 if ((n=ferror(fp))!=0) ioerror(strerror(n),fp,str);
449 else ioerror("xputc() failed",fp,str);
450 }
451 }
452 fflush(out);
453 }
454 puts_errors= 0;
455 }
456
457
iocheck()458 void iocheck() { return; }
459
460
tty_init()461 void tty_init()
462 {
463 char *tty_type, *num_lines, copy[10], bp[1025];
464 int x;
465
466 /* THIS HAS NO WIMP HOOK - IT SHOULD NEVER BE CALLED IF WIMP I/O IS USED! */
467
468 #ifdef TRY_ISATTY
469 if (!isatty(fileno(stdin))) { interactive=FALSE; ignore_eof=FALSE; }
470 if (!isatty(fileno(stdout))) { screen=FALSE; }
471 #endif
472 if (!screen) return; /* term=TERM_UNKNOWN, more_mode=scrollback=FALSE */
473
474 /* If we DO assume that a tty type has scrollback, we should NOT clear
475 its screen, NOR should more_mode be on by default. If it does NOT have
476 scrollback, we MAY clear its screen and might turn on more_mode (more
477 mode will be way ugly w/o cursor motion however). In some sense,
478 scrollback=TRUE is the conservative option.*/
479
480 #ifdef TRY_GETENV_TERM
481 if ((tty_type=getenv("TERM"))!=NULL) {
482 nstrcpy(copy,tty_type,9); crunch(copy);
483 if (nstreq(copy,"hp",2))
484 { term=HP_TERM; scrollback=TRUE; tty_lines=24; }
485 else if (nstreq(copy,"300h",4)) /* hp series 300 console */
486 { term=HP_TERM; scrollback= TRUE; tty_lines=46; }
487 else if (nstreq(copy,"ansi",4) || nstreq(copy,"vt",2) ||
488 nstreq(copy,"dec",3) || nstreq(copy,"mac",3))
489 { term=ANSI; scrollback=TRUE; tty_lines=24; }
490 else if (nstreq(copy,"xterm",5)) /* X-Windows terminal emulator */
491 { term=ANSI; scrollback=TRUE; tty_lines=24; }
492 else if (nstreq(copy,"sun",3)) /* sun console/cmdtool/shelltool */
493 { term=ANSI; scrollback=TRUE; tty_lines=34; }
494 else if (nstreq(copy,"pc",2)) /* pc console */
495 { term=ANSI; scrollback=FALSE; tty_lines=25; }
496 #ifdef _GNU_READLINE
497 /* the cmd-line override '-simple' sets this back to FALSE */
498 if (interactive) use_gnu_readline=TRUE; /* else was set to FALSE */
499 #endif
500 #ifdef TRY_TERMCAP
501 if (!nullstr(tty_type)) {
502 tgetent(bp,tty_type);
503 if ((x=tgetnum("li"))>0) tty_lines=x;
504 }
505 #endif
506 } else /* can't getenv("TERM") */
507 #endif /* TRY_GETENV_TERM */
508
509 if (term==TERM_UNKNOWN) {
510 /* either no TERM environment variable or its value is unknown */
511 use_gnu_readline=FALSE; /* it will fail anyway w/o TERM var */
512 if (DEFAULT_TERM_TYPE==HP_TERM) /* all HP_TERMs scrollback? */
513 { scrollback=TRUE; term=HP_TERM; tty_lines=24; }
514 else if (DEFAULT_TERM_TYPE==SCROLLING_ANSI)
515 { scrollback=TRUE; term=ANSI; tty_lines=24; }
516 else if (DEFAULT_TERM_TYPE==NONSCROLLING_ANSI)
517 { scrollback=FALSE; term=ANSI; tty_lines=24; }
518 else if (DEFAULT_TERM_TYPE==PC_CONSOLE)
519 { scrollback=FALSE; term=ANSI; tty_lines=25; }
520 else if (DEFAULT_TERM_TYPE==MAC_WINDOW)
521 { scrollback=FALSE; term=MAC_WINDOW; tty_lines=24; }
522 else /* default is TERM_UNKNOWN terminal type */
523 { scrollback=TRUE; term=TERM_UNKNOWN; tty_lines=24; }
524 }
525
526 #ifdef TRY_GETENV_LINES
527 if ((num_lines=getenv("LINES"))!=NULL && sscanf(num_lines,"%d",&x)==1)
528 tty_lines=x;
529 #endif
530 check_tty_lines(); /* ioctl will always over-ride */
531 #ifdef DEFAULT_SCROLLBACK
532 scrollback=DEFAULT_SCROLLBACK; /* override the settings above */
533 #endif
534 /* if (term!=TERM_UNKNOWN) screen=TRUE; else screen=FALSE; */
535 }
536
537
check_tty_lines()538 bool check_tty_lines() /* return TRUE and set tty_lines if changed */
539 {
540 /* maybe add some weird PC thing here to get #lines */
541 #ifdef TRY_WINSIZE
542 struct winsize thesize;
543 if (screen && ioctl(fileno(stdout),TIOCGWINSZ,&thesize)==0)
544 tty_lines= thesize.ws_row;
545 #endif
546 }
547
548
549 /* Use lib_puts(out,...) (not print()) for these screen handling routines!
550 flush() will be executed immediately beforehand.... */
551
552 int save_cursor;
553 char Tcmd[100];
554
555 /* These have been tested on a Xterm and vt220 */
556 #define ansi_tty_init() lib_puts(out,"\033[0m\n")
557 #define ansi_clr_scrn() lib_puts(out,"\033[1;1H\033[2J")
558 #define ansi_highlight(on) lib_puts(out,on ? "\033[7m":"\033[0m")
559 #define ansi_del_prev_ln() lib_puts(out,"\033[99D\033[K\033[1A\033[K")
560 #define ansi_boing() lib_puts(out,"\007")
ansi_cursor_left(i,s)561 void ansi_cursor_left(i,s) int i; char *s;
562 { if(i<0) sf(Tcmd,"\033[99D\033[K%s",s); else sf(Tcmd,"\033[%dD\033[K%s",i,s);
563 lib_puts(out,Tcmd); }
564
565 #define hp_tty_init() lib_puts(out,"\n\033&d@\n")
566 #define hp_clr_scrn() lib_puts(out,"\033H\033J")
567 #define hp_highlight(on) lib_puts(out,on ? "\033&dB":"\033&d@")
568 #define hp_del_prev_ln() lib_puts(out,"\033&a0C\033K\033A\033K")
569 #define hp_boing() lib_puts(out,"\007")
hp_cursor_left(i,s)570 void hp_cursor_left(i,s) int i; char *s;
571 { if(i<0) sf(Tcmd,"\033&a0C\033K%s",s); else sf(Tcmd,"\033&a-%dC\033K%s",i,s);
572 lib_puts(out,Tcmd); }
573
574 /* These should be filled in for the Mac's ThinkC "console package" */
575 #define mac_tty_init() printf("\n") /* printf() opens window */
576 #define mac_clr_scrn() {}
577 #define mac_highlight(on) {}
578 #define mac_del_prev_ln() {}
579 #define mac_boing() {}
mac_cursor_left()580 void mac_cursor_left() {}
581
tty_hello()582 void tty_hello()
583 {
584 if (term==HP_TERM) hp_tty_init();
585 else if (term==ANSI) ansi_tty_init();
586 else lib_puts(out,"\n");
587 if (!scrollback) { do_clear_screen(); lib_puts(out,"\n"); }
588
589 #ifdef _GNU_READLINE
590 if (use_gnu_readline) rl_bind_key('\t', rl_insert); /* completion off */
591 #endif
592 }
593
594
do_clear_screen()595 bool do_clear_screen()
596 {
597 /* NEEDS WIMP AND MAC CONSOLE HOOK */
598 if (term==HP_TERM) { hp_clr_scrn(); fflush(out); return(TRUE); }
599 else if (term==ANSI) { ansi_clr_scrn(); fflush(out); return(TRUE); }
600 #ifdef HAVE_CURSES
601 else if (term==CURSES) { curses_clr_scrn(); return(TRUE); }
602 #endif
603 else return(FALSE);
604 }
605
606
do_delete_previous_line()607 bool do_delete_previous_line() /* Needed for the "Hit RETURN for more" thing */
608 {
609 /* NEEDS WIMP AND MAC CONSOLE HOOK */
610 if (term==HP_TERM) { hp_del_prev_ln(); fflush(out); return(TRUE); }
611 else if (term==ANSI) { ansi_del_prev_ln(); fflush(out); return(TRUE); }
612 #ifdef HAVE_CURSES
613 else if (term==CURSES) { curses_del_prev_ln(); return(TRUE); }
614 #endif
615 else return(FALSE);
616 }
617
618
do_highlight(reverse)619 bool do_highlight(reverse)
620 bool reverse;
621 {
622 /* NEEDS WIMP AND MAC CONSOLE HOOK */
623 #ifdef HAVE_CURSES
624 if (term==CURSES) { curses_set_highlight(reverse); return(TRUE); }
625 #endif
626 if (term==HP_TERM) { hp_highlight(reverse); fflush(out); return(TRUE); }
627 else if (term==ANSI) { ansi_highlight(reverse);fflush(out); return(TRUE); }
628 else return(FALSE);
629 }
630
631
do_cursor_left(num_spaces,str_to_print)632 bool do_cursor_left(num_spaces,str_to_print)
633 int num_spaces; /* might be FAR_LEFT */
634 char *str_to_print;
635 {
636 /* NEEDS WIMP AND MAC CONSOLE HOOK */
637 if (term==HP_TERM) { hp_cursor_left(num_spaces,str_to_print); }
638 else if (term==ANSI) { ansi_cursor_left(num_spaces,str_to_print); }
639 #ifdef HAVE_CURSES
640 else if (term==CURSES) { curses_cursor_left(num_spaces,str_to_print); }
641 #endif
642 else return(FALSE);
643 return(TRUE);
644 }
645
646
boing()647 bool boing()
648 {
649 /* NEEDS WIMP AND MAC CONSOLE HOOK */
650 if (term==HP_TERM) { hp_boing(); return(TRUE); }
651 else if (term==ANSI) { ansi_boing(); return(TRUE); }
652 #ifdef HAVE_CURSES
653 else if (term==CURSES) { curses_boing(); return(TRUE); }
654 #endif
655 else return(FALSE);
656 }
657
658
659 /****************************** TOPLEVEL STUFF ******************************/
660
misc_init()661 void misc_init() /* init this file */
662 {
663 int i;
664 matrix(file_arg,MAX_FILE_ARGS,PATH_LENGTH+1,char);
665 for (i=0; i<MAX_FILE_ARGS; i++) file_arg[i][0]='\0';
666 old_stamp=new_stamp=time(NULL); dos_output=FALSE;
667 }
668
669
custom_lib_init()670 void custom_lib_init()
671 {
672 /* These init routines shouldn't really DO much - they really are meant for
673 initializing variables, mallocing structures, and so forth. Serious work
674 (for ex kicking off fancy screen I/O) should happen elsewhere. */
675
676 mem_init(); /* memlib.c */
677 msg_init(); /* msglib.c */
678 io_init(); /* iolib.c - just allocates things etc for the I/O lib */
679 str_init(); /* strlib.c */
680 math_init(); /* mathlib.c */
681 eqn_init(); /* eqn.c */
682 misc_init(); /* syscode.c (this file, dummy) */
683 tty_init(); /* also in this file */
684 }
685
lib_init()686 void lib_init()
687 {
688 custom_lib_init();
689 tty_hello();
690 }
691
lib_inits(argc_ptr,argv)692 void lib_inits(argc_ptr,argv)
693 int *argc_ptr;
694 char *argv[];
695 {
696 custom_lib_init();
697 /* if (!screen_init(argc_ptr,argv)) */
698 get_cmd_line_args(argc_ptr,argv);
699 tty_hello();
700 }
701
702
703 /* This is a little specialized for MAPMAKER right now. Generalize soon... */
704 #define ERROR_BADARG \
705 "%s error: unrecognized option '%s'\ntype '%s -help' for help\n"
706 #define ERROR_ONEFILE "%s error: only one %s argument allowed\n"
707 #define ERROR_BADFILE "%s error: bad %s file name '%s'\n"
708 #define ERROR_NOFILE "%s error: can't open %s file '%s'\n"
709 #define ERROR_EMPTYFILE "%s error: %s file '%s' is empty\n"
710 #define ERROR_NOTSCREEN "%s error: output is not a terminal, can't use %s\n"
711 #define HELP_ARG_MSG "\
712 %s optional arguments: [%csimple] [%cnomore] [%cclear] [%chelp] \n\
713 [%cload file] [%cprep file] [%crun file] [%cphoto file] [%cout file]\n\
714 run %s and type 'help' for help with commands and other information \n"
715
716 #define NOTSCREEN_ \
717 { fprintf(stderr,ERROR_NOTSCREEN,argv[0],argv[i]); abnormal_exit(); }
718
get_cmd_line_args(argc_ptr,argv)719 void get_cmd_line_args(argc_ptr,argv)
720 int *argc_ptr;
721 char *argv[];
722 {
723 int i, n;
724
725 for (i=1; i<*argc_ptr; i++) {
726 if (argv[i][0]!=ARG_CHAR) {
727 fprintf(stderr,ERROR_BADARG,argv[0],argv[i],argv[0]);
728 abnormal_exit();
729
730 } else if (matches(argv[i]+1,"simple")) {
731 if (!screen) NOTSCREEN_
732 term=TERM_UNKNOWN; use_gnu_readline=FALSE;
733 argv[i][0]='\0';
734 } else if (matches(argv[i]+1,"nomore")) {
735 if (!screen) NOTSCREEN_
736 more_mode=FALSE;
737 argv[i][0]='\0';
738 } else if (matches(argv[i]+1,"clear")) {
739 if (!screen) NOTSCREEN_
740 if (term==PC_CONSOLE) scrollback=TRUE; else scrollback=FALSE;
741 argv[i][0]='\0';
742
743 } else if (matches(argv[i]+1,"load")) {
744 check_file_arg(*argc_ptr-i,argv[i+1],file_arg[LOAD_FILE_ARG],
745 WRS("load"),WRS("data"),argv[0],READ);
746 prep_it=FALSE;
747 argv[i++][0]='\0'; argv[i][0]='\0';
748 } else if (matches(argv[i]+1,"prep")) {
749 check_file_arg(*argc_ptr-i,argv[i+1],file_arg[LOAD_FILE_ARG],
750 WRS("prep"),WRS("raw"),argv[0],READ);
751 prep_it=TRUE;
752 argv[i++][0]='\0'; argv[i][0]='\0';
753 } else if (matches(argv[i]+1,"run")) {
754 check_file_arg(*argc_ptr-i,argv[i+1],file_arg[RUN_FILE_ARG],
755 WRS("run"),WRS("in"),argv[0],READ);
756 argv[i++][0]='\0'; argv[i][0]='\0';
757 } else if (matches(argv[i]+1,"photo")) {
758 check_file_arg(*argc_ptr-i,argv[i+1],file_arg[PHOTO_FILE_ARG],
759 WRS("photo"),WRS("out"),argv[0],APPEND);
760 append_it=TRUE;
761 argv[i++][0]='\0'; argv[i][0]='\0';
762 } else if (matches(argv[i]+1,"out")) {
763 check_file_arg(*argc_ptr-i,argv[i+1],file_arg[PHOTO_FILE_ARG],
764 WRS("photo"),WRS("out"),argv[0],WRITE);
765 append_it=FALSE;
766 argv[i++][0]='\0'; argv[i][0]='\0';
767 } else if (matches(argv[i]+1,"help")) {
768 fprintf(stderr,HELP_ARG_MSG,argv[0],ARG_CHAR,ARG_CHAR,ARG_CHAR,
769 ARG_CHAR,ARG_CHAR,ARG_CHAR,ARG_CHAR,ARG_CHAR,ARG_CHAR,
770 argv[0]);
771 normal_exit();
772
773 } else {
774 fprintf(stderr,ERROR_BADARG,argv[0],argv[i],argv[0]);
775 abnormal_exit();
776 }
777 }
778 }
779
780
check_file_arg(num,arg,name,type,def_ext,prog,mode)781 bool check_file_arg(num,arg,name,type,def_ext,prog,mode)
782 int num;
783 char *arg, *name, *type, *def_ext, *prog, *mode;
784 {
785 char file[PATH_LENGTH+1];
786 FILE *fp;
787
788 if (!nullstr(name)) {
789 fprintf(stderr,ERROR_ONEFILE,prog,type);
790 abnormal_exit();
791 }
792 nstrcpy(file,arg,PATH_LENGTH);
793 if (!make_filename(file,DEFAULT_EXTENSION,def_ext)) {
794 fprintf(stderr,ERROR_BADFILE,prog,type,file);
795 abnormal_exit();
796 }
797 run {
798 fp=open_file(file,mode);
799 close_file(fp);
800 strcpy(name,file);
801 } except {
802 when IOERROR:
803 when CANTOPEN:
804 when CANTCLOSE:
805 fprintf(stderr,ERROR_NOFILE,prog,type,file);
806 abnormal_exit();
807 when ENDOFILE:
808 fprintf(stderr,ERROR_EMPTYFILE,prog,type,file);
809 abnormal_exit();
810 default:
811 relay;
812 }
813 }
814
815
update_top()816 bool update_top()
817 { return(FALSE); }
818
819
820
821
822 #ifdef PUNT_FOR_NOW /*******************************************************/
823
screen_init(argc_ptr,argv)824 bool screen_init(argc_ptr,argv) /* side-effect wimp, curses, and split */
825 int *argc_ptr;
826 char *argv[];
827 {
828 bool try_curses, try_wimp;
829 get_screen_preferences(argc_ptr,argv,&try_curses,&try_wimp);
830 #ifdef HAVE_WIMP
831 if (!tried_wimp && try_wimp)
832 if (do_wimp_init(argc_ptr,argv)) term=WIMP; /* wimp=TRUE */
833 tried_wimp= TRUE;
834 #endif
835 tty_init();
836 #ifdef HAVE_CURSES
837 if(!wimp && !tried_curses && try_curses)
838 if (curses_init(&tty_lines)) term=CURSES; /* sets curses=TRUE */
839 tried_curses= TRUE;
840 #endif
841 maybe_clear_screen(); nl(); boing();
842 return(wimp || curses);
843 }
844
845
split_screen_init(argc_ptr,argv,top_lines,top_update_function)846 bool split_screen_init(argc_ptr,argv,top_lines,top_update_function)
847 int *argc_ptr;
848 char *argv[];
849 int top_lines;
850 void (*top_update_function)();
851 {
852 bool try_curses, try_wimp;
853 get_screen_preferences(argc_ptr,argv,&try_curses,&try_wimp);
854 #ifdef HAVE_WIMP
855 if (!tried_wimp && try_wimp)
856 if (do_split_wimp_init(top_lines,top_update_function,argc_ptr,argv))
857 term=WIMP; /* sets wimp=TRUE */
858 tried_wimp= TRUE;
859 #endif
860 tty_init();
861 #ifdef HAVE_CURSES
862 if (!wimp && !tried_curses && try_curses)
863 if (curses_init(&tty_lines)) {
864 if (curses_split(top_lines,CURSES_REVERSE_TOP,top_update_function,
865 &tty_lines)) term=CURSES; /* sets curses=TRUE */
866 else curses_end();
867 }
868 tried_curses= TRUE;
869 #endif
870 maybe_clear_screen(); update_top(); nl(); boing();
871 return(wimp || curses);
872 }
873
874
get_screen_preferences(argc_ptr,argv,try_curses,try_wimp)875 void get_screen_preferences(argc_ptr,argv,try_curses,try_wimp)
876 int *argc_ptr;
877 char *argv[];
878 int *try_curses, *try_wimp;
879 {
880 int i, j;
881
882 *try_curses= *try_wimp= MAYBE;
883 for (i=0; i<*argc_ptr; i++) {
884 if (nmatches(argv[i],"-window",2)) *try_wimp=TRUE;
885 else if (nmatches(argv[i],"+window",2)) *try_wimp=FALSE;
886 else if (nmatches(argv[i],"-nowindow",4)) *try_wimp=FALSE;
887 else if (nmatches(argv[i],"-screen",2)) *try_curses=TRUE;
888 else if (nmatches(argv[i],"+screen",2)) *try_curses=FALSE;
889 else if (nmatches(argv[i],"-noscreen",4)) *try_curses=FALSE;
890 else if (nmatches(argv[i],"-line",2)) *try_curses= *try_wimp= FALSE;
891 else continue;
892 /* matched argument, so delete it from the list */
893 for (j=i+1; j<*argc_ptr; j++) argv[j-1]= argv[j];
894 --*argc_ptr;
895 }
896 if (*try_curses==MAYBE) *try_curses=DEFAULT_TRY_CURSES;
897 if (*try_wimp==MAYBE) *try_wimp=DEFAULT_TRY_WIMP;
898 }
899
900
901 /* Custom windows can work similarly to the canned types (text &
902 split), except that the widow code is very application specific: it
903 may respond to mouse clicks and so forth in special ways and have
904 other special stuff, which will probably have to interect with the
905 application code via global variables. Such interfaces could be
906 implemented using a customized do_wimp_init() routine. To make life
907 easy and so that things work similarly, we require (1) that the window
908 have a scrolling text region, (2) that it uses the menu struct (see
909 shell.c), (3) that it only need to know about state variable changes
910 that already call update_top() (or maybe_ok()), and (4) that it
911 effects state changes only when inhibit_menus is FALSE (see shell.c).
912 Like all init routines, do_custom_wimp_init() should do very little -
913 do_wimp_start() in shell.c should do this. */
914
915
update_top()916 bool update_top()
917 {
918 /* NEEDS WIMP HOOK */
919 #ifdef HAVE_CURSES
920 if (curses && split) {
921 if (!have_drawn_top) curses_draw_top(); else curses_update_top();
922 have_drawn_top=TRUE; return(TRUE);
923 }
924 #endif
925 return(FALSE);
926 }
927
928
screen_end()929 void screen_end() {
930 /* NEEDS WIMP HOOK */
931 /* ALSO NEEDS a "Hit return" hook for quiting under a window system */
932 #ifdef HAVE_CURSES
933 if (curses) curses_end(FALSE);
934 #endif
935 }
936
937
string_editor(prompt,str,num)938 bool string_editor(prompt,str,num)
939 char *prompt, *str;
940 int num; /* max #chars in str */
941 {
942 bool successful;
943
944 /* NEEDS WIMP HOOK */
945 successful = FALSE;
946 #ifdef HAVE_CURSES
947 if(curses)
948 successful = curses_string_editor(str,num);
949 #endif
950 return(successful);
951 }
952
953
954 #ifdef HAVE_CURSES
curses_error(where)955 void curses_error(where)
956 char *where;
957 {
958 curses_end(TRUE);
959 printed_lines=4; more_break_pending=FALSE;
960 term= old_term; tty_lines=old_lines;
961 more= old_more; scrollback= old_scrollback;
962 clear_screen();
963
964 if (where==NULL) where=ptr_to("???");
965 fprintf(stderr,"\nwarning: curses failed in %-50s\n",where);
966 fprintf(stderr,"attempting to continue in line mode...\n\n");
967 flush();
968 }
969 #endif
970
971 #endif /* PUNT_FOR_NOW */
972