1 /*
2  * $Id: io-term.c,v 1.51 2001/02/13 23:38:06 danny Exp $
3  *
4  * Copyright 1990, 1992, 1993, 1999, 2000, 2001 Free Software Foundation, Inc.
5  *
6  * This file is part of Oleo, the GNU Spreadsheet.
7  *
8  * Oleo is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2, or (at your option)
11  * any later version.
12  *
13  * Oleo is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Oleo; see the file COPYING.  If not, write to
20  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 static char *rcsid = "$Id: io-term.c,v 1.51 2001/02/13 23:38:06 danny Exp $";
24 
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28 
29 #ifdef	WITH_DMALLOC
30 #include <dmalloc.h>
31 #endif
32 
33 #include <ctype.h>
34 #include <stdio.h>
35 #include <locale.h>
36 #include <stdlib.h>
37 
38 #include "global.h"
39 
40 #include "basic.h"
41 #include "cell.h"
42 #include "cmd.h"
43 #include "format.h"
44 #include "font.h"
45 #include "getopt.h"
46 #include "init.h"
47 #define DEFINE_IO_VARS 1
48 #include "io-abstract.h"
49 #include "io-curses.h"
50 #include "io-edit.h"
51 #include "io-generic.h"
52 #include "io-term.h"
53 #include "io-utils.h"
54 #include "io-x11.h"
55 #include "key.h"
56 #include "line.h"
57 #include "lists.h"
58 #define obstack_chunk_alloc ck_malloc
59 #define obstack_chunk_free free
60 #include "obstack.h"
61 #include "oleofile.h"
62 #include "print.h"
63 #include "ref.h"
64 #include "regions.h"
65 #include "window.h"
66 #include "funcs.h"
67 #include "graph.h"
68 #include "mdi.h"
69 #include "postscript.h"
70 
71 #include "userpref.h"
72 #include "mysql.h"
73 #ifdef	HAVE_MOTIF
74 #include "io-motif.h"
75 #endif
76 
77 #ifdef HAVE_LIBGTK
78 #include "gtk/gtk.h"
79 #endif
80 
81 #include "list.h"
82 #include "sc.h"
83 #include "sylk.h"
84 
85 #ifdef	HAVE_PANIC_SAVE
86 #include "panic.h"
87 #endif
88 
89 #if	ENABLE_NLS
90 extern char *gettext(char *);
91 #endif
92 
93 /*
94  * The ultimate global variable
95  */
96 #if 1
97 struct OleoGlobal *Global = NULL;
98 #else
99 struct OleoGlobal	__tempGlobal,
100 			*Global = &__tempGlobal;
101 #endif
102 
103 /* These are the hooks used to do file-io. */
104 void (*read_file) (FILE *, int) = oleo_read_file;
105 void (*write_file) (FILE *, struct rng *) = oleo_write_file;
106 int (*set_file_opts) (int, char *) = oleo_set_options;
107 void (*show_file_opts) () = oleo_show_options;
108 
109 static char	option_separator = '\t';
110 static char	*option_format = NULL;
111 int		option_filter = 0;
112 
113 static char short_options[] = "VqfxthsFSv";
114 static struct option long_options[] =
115 {
116 	{"version",		0,	NULL,			'V'},
117 	{"quiet",		0,	NULL,			'q'},
118 	{"ignore-init-file",	0,	NULL,			'f'},
119 	{"nw",			0,	NULL,			'x'},
120 	{"no-toolkit",		0,	NULL,			't'},
121 	{"help",		0,	NULL,			'h'},
122 	{"separator",		1,	NULL,			's'},
123 	{"space",		0,	NULL,			'S'},
124 	{"format",		1,	NULL,			'F'},
125 	{"filter",		0,	NULL,			'-'},
126 	{"version",		0,	NULL,			'v'},
127 	{NULL,			0,	NULL,			0}
128 };
129 
130 /* Avoid needless messages to stdout. */
131 int spread_quietly = 0;
132 
133 /* Avoid using Displays no matter what else. (-x --no-x) */
134 int no_gtk = 0;
135 int no_x = 0;
136 int no_curses = 0;
137 int no_motif = 0;
138 
139 /* What kind of display? */
140 int using_x = 0;
141 int using_curses = 0;
142 int using_gtk = 0;
143 int using_motif = 0;
144 
145 
146 /* Cell size paramaters. */
147 unsigned int default_width = 8;
148 unsigned int default_height = 1;
149 
150 /* These values are used by clear_spreadsheet ()
151  * to restore the defaults.
152  */
153 unsigned int saved_default_width = 8;
154 unsigned int saved_default_height = 1;
155 
156 /* Other cell defaults: */
157 int default_jst = JST_LFT;
158 int default_fmt = FMT_GEN;
159 int default_prc = 0x0F;		/* FIX ME */
160 int default_lock = LCK_UNL;
161 
162 /* Pointers to interesting cmd_func structures. */
163 struct cmd_func *end_macro_cmd;
164 struct cmd_func *digit_0_cmd;
165 struct cmd_func *digit_9_cmd;
166 struct cmd_func * break_cmd;
167 struct cmd_func * universal_arg_cmd;
168 
169 /* A bland signal handler. */
170 static RETSIGTYPE
got_sig(int sig)171 got_sig (int sig)
172 {
173 }
174 
175 /*
176  * Simple table of variables to set
177  *	All these variables belong in a UserPreferences structure.
178  */
179 
180 struct UserPreferences UserPreferences;
181 
182 /*
183  * How to use this ?
184  *
185  * Set "name" to the string we'll find in the .oleorc.
186  * Put a pointer to the variable to assign to in "var".
187  *
188  * If a function needs to be called upon encountering this option,
189  *	put its address in "trigger".
190  * If it's an integer, put the value to assign in "value".
191  * If it's a string, set "copynext" to 1. The string in the option will be
192  *	copied to the variable.
193  *
194  * Set "write" to 1 if this needs to be saved in .oleorc.
195  *	Even then, only saved to file if integer has the "value" from the table,
196  *	or if the string is non-empty.
197  * Set cont to 1 if processing in do_set_option is to continue.
198  */
199 static struct pref {
200 	char	*name;
201 	void	*var;
202 	int	value;
203 	void	(*trigger)(char *);
204 	int	copynext;
205 	int	write;
206 	int	cont;
207 } Preferences [] = {
208 	{ "a0",		&UserPreferences.a0,		1,	NULL,	0, 1, 1},
209 	{ "noa0",	&UserPreferences.a0,		0,	NULL,	0, 1, 1},
210 	{ "bgcolor",	&UserPreferences.bgcolor,	0,	NULL,	1, 0, 1},
211 	{ "file",	&UserPreferences.file_type,	0,	NULL,	1, 1, 1},
212 	{ "encoding",	&UserPreferences.encoding,	0,	OleoUserPrefEncoding,	1, 1, 0},
213 	{ NULL,	0 }
214 };
215 
216 /* An parser for the language grokked by option setting commands. */
217 
218 static int
do_set_option(char * ptr)219 do_set_option (char *ptr)
220 {
221   int	set_opt = 1;
222   int	i, l;
223   int *tmp;
224   char	*p;
225 
226   while (*ptr == ' ')
227     ptr++;
228 
229   for (l=0,p=ptr; *p && !isspace(*p); p++) l++;
230 
231   for (i=0; Preferences[i].name; i++)
232 	if (strncmp(ptr, Preferences[i].name, l) == 0) {
233 		if (Preferences[i].trigger != NULL)
234 			(Preferences[i].trigger)(ptr);
235 
236 		if (Preferences[i].copynext) {
237 			ptr += strlen(Preferences[i].name) + 1;
238 			Preferences[i].var = strdup(ptr);
239 		} else if (Preferences[i].var) {
240          tmp = Preferences[i].var;
241 			*tmp = Preferences[i].value;
242       }
243 
244 		if (Preferences[i].cont == 0)
245 			return 1;
246 		break;
247 	}
248 
249   if (!strincmp ("no", ptr, 2))
250     {
251       ptr += 2;
252       set_opt = 0;
253       while (*ptr == ' ')
254 	ptr++;
255     }
256   if (!stricmp ("auto", ptr))
257     {
258       Global->auto_recalc = set_opt;
259       return 0;
260     }
261   if (!stricmp ("bkgrnd", ptr) || !stricmp ("background", ptr))
262     {
263       Global->bkgrnd_recalc = set_opt;
264       return 0;
265     }
266   if (!stricmp ("a0", ptr))
267     {
268       Global->a0 = set_opt;
269       io_repaint ();
270       return 0;
271     }
272   if (!stricmp ("backup", ptr))
273     {
274       __make_backups = set_opt;
275       return 0;
276     }
277   if (!stricmp ("bkup_copy", ptr))
278     {
279       __backup_by_copying = set_opt;
280       return 0;
281     }
282   if (set_opt && !strincmp ("ticks ", ptr, 6))
283     {
284       ptr += 6;
285       cell_timer_seconds = astol (&ptr);
286       return 0;
287     }
288   if (set_opt && !strincmp ("print ", ptr, 6))
289     {
290       ptr += 6;
291       print_width = astol (&ptr);
292       return 0;
293     }
294   if (set_opt && !strincmp ("file ", ptr, 5))
295     {
296       ptr += 5;
297       if (!stricmp ("oleo", ptr))
298 	{
299 	  read_file = oleo_read_file;
300 	  write_file = oleo_write_file;
301 	  set_file_opts = oleo_set_options;
302 	  show_file_opts = oleo_show_options;
303 	}
304       else if (!stricmp ("sylk", ptr))
305 	{
306 	  Global->sylk_a0 = 1;
307 	  read_file = sylk_read_file;
308 	  write_file = sylk_write_file;
309 	  set_file_opts = sylk_set_options;
310 	  show_file_opts = sylk_show_options;
311 	}
312       else if (!stricmp ("sylk-noa0", ptr))
313 	{
314 	  Global->sylk_a0 = 0;
315 	  read_file = sylk_read_file;
316 	  write_file = sylk_write_file;
317 	  set_file_opts = sylk_set_options;
318 	  show_file_opts = sylk_show_options;
319 	}
320       else if (!stricmp ("sc", ptr))
321 	{
322 	  read_file = sc_read_file;
323 	  write_file = sc_write_file;
324 	  set_file_opts = sc_set_options;
325 	  show_file_opts = sc_show_options;
326 	}
327 #ifdef	HAVE_PANIC_SAVE
328       else if (!stricmp ("panic", ptr))
329 	{
330 	  read_file = panic_read_file;
331 	  write_file = panic_write_file;
332 	  set_file_opts = panic_set_options;
333 	  show_file_opts = panic_show_options;
334 	}
335 #endif
336       else if (!stricmp ("list", ptr))
337 	{
338 	  read_file = list_read_file;
339 	  write_file = list_write_file;
340 	  set_file_opts = list_set_options;
341 	  show_file_opts = list_show_options;
342 	  /*if (ptr[4])
343 	    {
344 	    ptr+=4;
345 	    sl_sep=string_to_char(&ptr);
346 	    } */
347 	}
348       else
349 	io_error_msg ("Unknown file format %s", ptr);
350       return 0;
351     }
352   if (set_window_option (set_opt, ptr) == 0)
353     {
354       if ((*set_file_opts) (set_opt, ptr))
355 	io_error_msg ("Unknown option '%s'", ptr);
356       return 0;
357     }
358   return 1;
359 }
360 
361 void
save_preferences(void)362 save_preferences(void)
363 {
364 	char	*home = getenv("HOME");
365 	char	*rc, *rc2;
366 	FILE	*fp;
367 	int	i;
368 
369 	rc = malloc(strlen(home) + strlen(RCFILE) + 4);
370 	rc2 = malloc(strlen(home) + strlen(RCFILE) + 4);
371 
372 	sprintf(rc, "%s/%s", home, RCFILE);
373 	sprintf(rc2, "%s/%s.bak", home, RCFILE);
374 
375 	(void)unlink(rc2);
376 	rename(rc, rc2);
377 
378 	free(rc2);
379 
380 	fp = fopen(rc, "w");
381 	if (fp == NULL) {
382 		io_info_msg("Couldn't save preferences in %s: %s",
383 			rc, strerror(errno));
384 		free(rc);
385 		return;
386 	}
387 
388 	for (i=0; Preferences[i].name; i++)
389 		if (Preferences[i].write) {
390 			if (Preferences[i].copynext) {
391 				if (strlen((char *)Preferences[i].var) != 0)
392 				    fprintf(fp, "set-option %s %s\n",
393 					Preferences[i].name,
394 					(char *) Preferences[i].var);
395 			} else if (Preferences[i].value == *(int *)Preferences[i].var)
396 				fprintf(fp, "set-option %s\n",
397 					Preferences[i].name);
398 		}
399 
400 	fclose(fp);
401 
402 	io_info_msg("Saved preferences to %s", rc);
403 
404 	free(rc);
405 }
406 
407 void
set_options(char * ptr)408 set_options (char * ptr)
409 {
410   if (do_set_option (ptr))
411     io_recenter_cur_win ();
412 }
413 
414 void
show_options(void)415 show_options (void)
416 {
417   int n;
418   int fmts;
419   char *data_buf[9];
420 
421   n = Global->auto_recalc;
422   io_text_start ();
423 
424   io_text_line ("auto-recalculation: %s        Recalculate in background: %s",
425 		n ? " on" : "off", Global->bkgrnd_recalc ? "on" : "off");
426   io_text_line ("make backup files:  %s        Copy files into backups:   %s",
427 	__make_backups ? " on" : "off", __backup_by_copying ? "on" : "off");
428 
429   io_text_line ("Asynchronous updates every %u ???",
430 		cell_timer_seconds);
431 
432   io_text_line ("Print width:      %5u", print_width);
433 
434   io_text_line ("");
435 
436   (*show_file_opts) ();
437 
438   io_text_line ("");
439   show_window_options ();
440   io_text_line ("");
441 
442   fmts = usr_set_fmts ();
443   if (fmts)
444     {
445       io_text_line ("User-defined formats:");
446       io_text_line ("Fmt    +Hdr    -Hdr   +Trlr   -Trlr    Zero   Comma Decimal  Prec         Scale");
447       for (n = 0; n < 16; n++)
448 	{
449 	  if (fmts & (1 << n))
450 	    {
451 	      get_usr_stats (n, data_buf);
452 	      io_text_line ("%3d %7s %7s %7s %7s %7s %7s %7s %5s %13s",
453 			    n + 1,
454 			    data_buf[0],
455 			    data_buf[1],
456 			    data_buf[2],
457 			    data_buf[3],
458 			    data_buf[4],
459 			    data_buf[5],
460 			    data_buf[6],
461 			    data_buf[7],
462 			    data_buf[8]);
463 	    }
464 	}
465     }
466   else
467     io_text_line ("No user-defined formats have been defined");
468 
469   io_text_finish ();
470 }
471 
472 
473 void
read_mp_usr_fmt(char * ptr)474 read_mp_usr_fmt (char *ptr)
475 {
476   int usr_n = -1;
477   int n_chrs = 0;
478   char *p;
479   char *buf[9];
480   int i;
481 
482   for (i = 0; i < 9; i++)
483     buf[i] = "";
484   p = ptr;
485   while (*p == ';')
486     {
487       *p++ = '\0';
488       switch (*p++)
489 	{
490 	case 'N':
491 	  usr_n = astol (&p) - 1;
492 	  break;
493 	case 'H':
494 	  switch (*p++)
495 	    {
496 	    case 'P':
497 	      i = 0;
498 	      break;
499 	    case 'N':
500 	      i = 1;
501 	      break;
502 	    default:
503 	      goto badline;
504 	    }
505 	  goto count_chars;
506 	case 'T':
507 	  switch (*p++)
508 	    {
509 	    case 'P':
510 	      i = 2;
511 	      break;
512 	    case 'N':
513 	      i = 3;
514 	      break;
515 	    default:
516 	      goto badline;
517 	    }
518 	  goto count_chars;
519 
520 	case 'Z':
521 	  i = 4;
522 	  goto count_chars;
523 
524 	case 'C':
525 	  i = 5;
526 	  goto count_chars;
527 
528 	case 'D':
529 	  i = 6;
530 	  goto count_chars;
531 
532 	case 'P':
533 	  i = 7;
534 	  goto count_chars;
535 
536 	case 'S':
537 	  i = 8;
538 	  goto count_chars;
539 
540 	count_chars:
541 	  buf[i] = p;
542 	  n_chrs++;
543 	  while (*p && *p != ';')
544 	    {
545 	      p++;
546 	      n_chrs++;
547 	    }
548 	  break;
549 
550 	default:
551 	badline:
552 	  io_error_msg ("Unknown OLEO line %s", ptr);
553 	  return;
554 	}
555     }
556   if (*p || usr_n < 0 || usr_n > 15)
557     goto badline;
558 
559   set_usr_stats (usr_n, buf);
560 }
561 
562 /* Modify this to write out *all* the options */
563 void
write_mp_options(FILE * fp)564 write_mp_options (FILE *fp)
565 {
566   fprintf (fp, "O;%sauto;%sbackground;%sa0;ticks %d\n",
567 	   Global->auto_recalc ? "" : "no",
568 	   Global->bkgrnd_recalc ? "" : "no",
569 	   Global->a0 ? "" : "no",
570 	   cell_timer_seconds);
571 }
572 
573 void
read_mp_options(char * str)574 read_mp_options (char *str)
575 {
576   char *np;
577 
578   while ((np = (char *)index (str, ';')))
579     {
580       *np = '\0';
581       (void) do_set_option (str);
582       *np++ = ';';
583       str = np;
584     }
585   if ((np = (char *)rindex (str, '\n')))
586     *np = '\0';
587   (void) do_set_option (str);
588 }
589 
590 
591 /* Commands related to variables. */
592 
593 void
set_var(struct rng * val,char * var)594 set_var (struct rng *val, char *var)
595 {
596   char *ret;
597 
598   Global->modified = 1;
599   ret = new_var_value (var, strlen(var), val);
600 
601   if (ret)
602     io_error_msg ("Can't set-var %s: %s\n", var, ret);
603 }
604 
605 void
unset_var(char * var)606 unset_var (char *var)
607 {
608   struct rng tmp_rng;
609   struct var *v;
610 
611   v = find_var(var, strlen(var));
612 
613   if (!v || v->var_flags == VAR_UNDEF)
614     {
615       io_error_msg ("No variable named %s exists.", var);
616     }
617   else
618     {
619       tmp_rng.lr = tmp_rng.hr = NON_ROW;
620       tmp_rng.lc = tmp_rng.hc = NON_COL;
621       v = find_or_make_var(var, strlen(var));
622       v->v_rng = tmp_rng;
623       v->var_flags = VAR_UNDEF;
624     }
625 }
626 
627 void
show_var(char * ptr)628 show_var (char *ptr)
629 {
630   struct var *v;
631   int num;
632 
633   while (*ptr == ' ')
634     ptr++;
635   for (num = 0; ptr[num] && ptr[num] != ' '; num++)
636     ;
637 
638   v = find_var (ptr, num);
639   if (!v || v->var_flags == VAR_UNDEF)
640     {
641       io_error_msg ("There is no '%s'", ptr);
642       return;
643     }
644   if (Global->a0)
645     {
646       if (v->v_rng.lr != v->v_rng.hr || v->v_rng.lc != v->v_rng.hc)
647 	/* FOO */ sprintf (print_buf, "%s $%s$%u:$%s$%u", v->var_name, col_to_str (v->v_rng.lc), v->v_rng.lr, col_to_str (v->v_rng.hc), v->v_rng.hr);
648       else
649 	/* FOO */ sprintf (print_buf, "%s $%s$%u", v->var_name, col_to_str (v->v_rng.lc), v->v_rng.lr);
650     }
651   else
652     sprintf (print_buf, "%s %s", v->var_name, range_name (&(v->v_rng)));
653   io_info_msg (print_buf);
654 }
655 
656 static void
show_a_var(char * name,struct var * v)657 show_a_var (char *name, struct var *v)
658 {
659   if (v->var_flags == VAR_UNDEF)
660     return;
661   if (Global->a0)
662     {
663       if (v->v_rng.lr != v->v_rng.hr || v->v_rng.lc != v->v_rng.hc)
664 	/* FOO */ io_text_line ("%-20s  $%s$%u:$%s$%u", v->var_name, col_to_str (v->v_rng.lc), v->v_rng.lr, col_to_str (v->v_rng.hc), v->v_rng.hr);
665       else
666 	/* FOO */ io_text_line ("%-20s  $%s$%u", v->var_name, col_to_str (v->v_rng.lc), v->v_rng.lr);
667     }
668   else
669     io_text_line ("%-20s  %s", v->var_name, range_name (&(v->v_rng)));
670 }
671 
672 void
show_all_var(void)673 show_all_var (void)
674 {
675   io_text_start ();
676   io_text_line ("%-20s  Current Value", "Variable Name");
677   for_all_vars (show_a_var);
678   io_text_finish ();
679 }
680 
681 static FILE * write_variable_fp = 0;
682 
683 static void
write_a_var(char * name,struct var * v)684 write_a_var (char *name, struct var *v)
685 {
686   CELLREF r, c;
687   if (v->var_flags == VAR_UNDEF)
688     return;
689   r = v->v_rng.lr;
690   c = v->v_rng.lc;
691   if (v->var_flags == VAR_CELL)
692     fprintf (write_variable_fp, "%s=%s\n",
693 	     v->var_name, cell_value_string (r, c, 1));
694 }
695 
696 void
write_variables(FILE * fp)697 write_variables (FILE * fp)
698 {
699   if (write_variable_fp)
700     io_error_msg ("Can't re-enter write_variables.");
701   else
702     {
703       write_variable_fp = fp;
704       for_all_vars (write_a_var);
705       write_variable_fp = 0;
706     }
707 }
708 
709 void
read_variables(FILE * fp)710 read_variables (FILE * fp)
711 {
712   char buf[1024];
713   int lineno = 0;
714   while (fgets (buf, 1024, fp))
715     {
716       char * ptr;
717       for (ptr = buf; *ptr && *ptr != '\n'; ++ptr)
718 	;
719       *ptr = '\0';
720       for (ptr = buf; isspace (*ptr); ptr++)
721 	;
722       if (!*ptr || (*ptr == '#'))
723 	continue;
724       {
725 	char * var_name = ptr;
726 	int var_name_len;
727 	char * value_string;
728 	while (*ptr && *ptr != '=')
729 	  ++ptr;
730 	if (!*ptr)
731 	  {
732 	    io_error_msg ("read-variables: format error near line %d.", lineno);
733 	    return;
734 	  }
735 	var_name_len = ptr - var_name;
736 	++ptr;
737 	value_string = ptr;
738 	{
739 	  struct var * var = find_var (var_name, var_name_len);
740 	  if (var)
741 	    {
742 	      switch (var->var_flags)
743 		{
744 		case VAR_UNDEF:
745 		  break;
746 		case VAR_CELL:
747 		  {
748 		    char * error = new_value (var->v_rng.lr, var->v_rng.lc,
749 					      value_string);
750 		    if (error)
751 		      {
752 			io_error_msg (error);
753 			return;	/* actually, io_error_msg never returns. */
754 		      }
755 		    else
756 		      Global->modified = 1;
757 		    break;
758 		  }
759 		case VAR_RANGE:
760 		  io_error_msg ("read-variables (line %d): ranges not supported.",
761 				lineno);
762 		  return;
763 		}
764 	    }
765 	}
766       }
767       ++lineno;
768     }
769   if (!feof (fp))
770     {
771       io_error_msg ("read-variables: read error near line %d.", lineno);
772       return;
773     }
774 }
775 
776 static void
init_maps(void)777 init_maps (void)
778 {
779   num_maps = 0;
780   the_maps = 0;
781   map_names = 0;
782   map_prompts = 0;
783 
784   the_funcs = ck_malloc (sizeof (struct cmd_func *) * 2);
785   num_funcs = 1;
786   the_funcs[0] = &cmd_funcs[0];
787 
788   find_func (0, &end_macro_cmd, "end-macro");
789   find_func (0, &digit_0_cmd, "digit-0");
790   find_func (0, &digit_9_cmd, "digit-9");
791   find_func (0, &break_cmd, "break");
792   find_func (0, &universal_arg_cmd, "universal-argument");
793 
794   create_keymap ("universal", 0);
795   push_command_frame (0, 0, 0);
796 }
797 
798 int
add_usr_cmds(struct cmd_func * new_cmds)799 add_usr_cmds (struct cmd_func *new_cmds)
800 {
801   num_funcs++;
802   the_funcs = ck_realloc (the_funcs, num_funcs * sizeof (struct cmd_func *));
803   the_funcs[num_funcs - 1] = new_cmds;
804   return num_funcs - 1;
805 }
806 
807 /*
808  * The variable below makes it possible for the program "what" to identify
809  * which version of oleo this executable is.
810  */
811 
812 static char *what_version = "@(#)" PACKAGE " " VERSION ;
813 
814 static void
show_usage(void)815 show_usage (void)
816 {
817 
818   printf(_("This is %s %s\n\n"), PACKAGE, VERSION);
819 
820   printf(_("\
821 Usage: %s [OPTION]... [FILE]...\n\
822 "), PACKAGE);
823   printf(_("\
824 \n\
825   -h, --help               display this help and exit\n\
826   -V, --version            output version information and exit\n\
827   -q, --quiet              do not display startup messages\n\
828   -f, --ignore-init-file   ignore settings defined in init file\n\
829   -t, --no-toolkit         disable X toolkit\n\
830   -x, --nw                 disable graphics and fallback to curses\n\
831   -s x, --separator x	   set separator for 'list' file type to x\n\
832   -S, --space		   set separator for 'list' file type to a space\n\
833   -F x, --format x	   set default file type to x (oleo, list, sc  ...)\n\
834   --filter		   read file from stdin, write to stdout on exit\n\
835 \n\
836 Report bugs to <bug-oleo@gnu.org>.\n\
837 "));
838 }
839 
840 static RETSIGTYPE
continue_oleo(int sig)841 continue_oleo (int sig)
842 {
843   io_repaint ();
844   if (using_curses)
845     cont_curses ();
846 }
847 
InitializeGlobals(void)848 void InitializeGlobals(void)
849 {
850   Global->display_opened = 0;
851   Global->return_from_error = 0;
852 
853   /* Initialize stuff that's now in Global */
854   Global->bkgrnd_recalc = 1;
855   Global->auto_recalc = 1;
856   Global->a0 = 0;
857   Global->topclear = 0;
858   Global->alarm_seconds = 1;
859   Global->alarm_active = 1;
860 
861   /* From window.c */
862   Global->scr_lines = 24;
863   Global->scr_cols = 80;
864   user_input = 1;
865   user_status = 2;
866   Global->input = 0;
867   Global->status = 1;
868   input_rows = 1;
869   status_rows = 1;
870   default_right_border = 0;
871   default_bottom_border = 0;
872   nwin = 0;
873   cwin = 0;
874   wins = 0;
875   win_id = 1;
876 
877   Global->sylk_a0 = 1;
878 
879   Global->user_height_scale = 1.;
880   Global->user_width_scale = 1.;
881   Global->height_scale = 1.;
882   Global->width_scale = 1.;
883 
884   Global->cell_font_point_size = 12;
885   Global->block_on_getch = 1;
886 
887   Global->display_formula_mode = 0;
888   Global->auto_motion_direction = magic_down;
889   Global->sl_sep = '\t';
890 
891   Global->CurrentPrintDriver = &PostScriptPrintDriver;
892   Global->zoom = 1.0;
893 
894   Global->mouse_id = 0;
895 
896   Global->oldLocale = NULL;
897 
898   UserPreferences.run_load_hooks = 1;
899   /* End initialize */
900 
901   __make_backups = 1;
902 }
903 
904 void
oleo_catch_signals(void (* h)(int))905 oleo_catch_signals(void (*h)(int))
906 {
907   /*
908    * These probably don't all need to be ifdef, but
909    * it is harmless.
910    */
911 #ifdef SIGCONT
912   signal (SIGCONT, continue_oleo);
913 #endif
914 #ifdef SIGPIPE
915   signal (SIGPIPE, h);
916 #endif
917 
918   /*
919    * It makes little sense to block all signals when using X
920    */
921   if ((! using_x) && (! using_gtk) && (! using_motif)) {
922 #ifdef SIGINT
923   signal (SIGINT, h);
924 #endif
925 #ifdef SIGQUIT
926   signal (SIGQUIT, h);
927 #endif
928 #ifdef SIGILL
929   signal (SIGILL, h);
930 #endif
931 #ifdef SIGEMT
932   signal (SIGEMT, h);
933 #endif
934 #ifdef SIGBUS
935   signal (SIGBUS, h);
936 #endif
937 #ifdef SIGSEGV
938   signal (SIGSEGV, h);
939 #endif
940 #ifdef	SIGHUP
941   signal(SIGHUP, h);
942 #endif
943 #ifdef	SIGTRAP
944   signal(SIGTRAP, h);
945 #endif
946 #ifdef	SIGABRT
947   signal(SIGABRT, h);
948 #endif
949 #ifdef	SIGFPE
950   signal(SIGFPE, h);
951 #endif
952 #ifdef	SIGSYS
953   signal(SIGSYS, h);
954 #endif
955 #ifdef	SIGALRM
956   signal(SIGALRM, h);
957 #endif
958 #ifdef	SIGTERM
959   signal(SIGTERM, h);
960 #endif
961 #ifdef	SIGXCPU
962   signal(SIGXCPU, h);
963 #endif
964 #ifdef	SIGVTALRM
965   signal(SIGVTALRM, h);
966 #endif
967 #ifdef	SIGPROF
968   signal(SIGPROF, h);
969 #endif
970 #ifdef	SIGUSR1
971   signal(SIGUSR1, h);
972 #endif
973 #ifdef	SIGUSR2
974   signal(SIGUSR2, h);
975 #endif
976   }
977 }
978 
979 int
main(int argc,char ** argv)980 main (int argc, char **argv)
981 {
982   volatile int ignore_init_file = 0;
983   FILE * init_fp[2];
984   char * init_file_names[2];
985   volatile int init_fpc = 0;
986   int command_line_file = 0;	/* was there one? */
987 
988 #if 0
989   sleep(30);
990 #endif
991 #if 1	/* ENABLE_NLS */
992   setlocale(LC_ALL, "");
993   bindtextdomain(PACKAGE, LOCALEDIR);
994   textdomain(PACKAGE);
995 #endif
996 
997   MdiInitialize();	/* Create initial Global structure */
998   PlotInit();
999   AllocateDatabaseGlobal();
1000   InitializeGlobals();
1001 
1002   /* Set up the minimal io handler. */
1003 #if 0
1004   cmd_graphics ();
1005 #endif
1006 
1007   {
1008     int opt;
1009 
1010     while (1) {
1011 	opt = getopt_long (argc, argv, short_options, long_options, (int *)0);
1012 	if (opt == EOF)
1013 		break;
1014 
1015 #if 0
1016 	if (opt)
1017 		fprintf(stderr, PACKAGE " option %c\n", opt);
1018 	else {
1019 		fprintf(stderr, PACKAGE " optind %d option %s strange ...\n",
1020 			optind, argv[optind]);
1021 	}
1022 #endif
1023 
1024 	switch (opt)
1025 	  {
1026 	  case 'v':
1027 	  case 'V':
1028 	    printf(_("%s %s\n"), GNU_PACKAGE, VERSION);
1029             printf(_("Copyright 1992-2000 Free Software Foundation, Inc.\n"));
1030             printf(_("%s comes with ABSOLUTELY NO WARRANTY.\n"), GNU_PACKAGE);
1031             printf(_("You may redistribute copies of %s\n"), PACKAGE);
1032             printf(_("under the terms of the GNU General Public License.\n"));
1033             printf(_("For more information about these matters, "));
1034             printf(_("see the files named COPYING.\n"));
1035 	    exit (0);
1036 	    break;
1037 	  case 'q':
1038 	    spread_quietly = 1;
1039 	    break;
1040 	  case 'f':
1041 	    ignore_init_file = 1;
1042 	    break;
1043 	  case 'x':
1044 	    no_x = 1;
1045 	    break;
1046           case 't':
1047             no_gtk = 1;
1048             no_motif = 1;
1049             break;
1050 	  case 'h':
1051 	    show_usage ();
1052 	    exit (0);
1053 	    break;
1054 	  case 's':
1055 	    option_separator = argv[optind][0];
1056 #if 0
1057 	fprintf(stderr, PACKAGE " set list file separator to %c\n", option_separator);
1058 #endif
1059 	    optind++;
1060 	    list_set_separator(option_separator);
1061 	    break;
1062 	  case 'S':
1063 	    option_separator = ' ';
1064 	    list_set_separator(option_separator);
1065 	    break;
1066 	  case 'F':
1067 #if 0
1068 	fprintf(stderr, "F: optind %d argv[optind] '%s' optopt %d %c\n",
1069 		optind, argv[optind], optopt, optopt);
1070 #endif
1071 	    option_format = argv[optind];
1072 	    file_set_default_format(option_format);
1073 	    optind++;
1074 	    break;
1075 	  case '-':
1076 		option_filter = 1;
1077 		break;
1078 	  }
1079       }
1080   }
1081 
1082   if (argc - optind > 1)
1083     {
1084       if (no_motif)
1085       {
1086         show_usage ();
1087         exit (1);
1088       }
1089     }
1090 
1091   init_infinity ();
1092   init_mem ();
1093   init_eval ();
1094   init_refs ();
1095   init_cells ();
1096   init_fonts ();
1097   init_info ();
1098 
1099   /* Find the init files.
1100    * This is done even if ignore_init_file is true because
1101    * it effects whether the disclaimer will be shown.
1102    */
1103     {
1104       char *ptr, *home;
1105 
1106       home = getenv ("HOME");
1107       if (home)
1108 	{
1109 	  ptr = mk_sprintf ("%s/%s", home, RCFILE);
1110 	  init_fp[init_fpc] = fopen (ptr, "r");
1111 	  init_file_names[init_fpc] = ptr;
1112 	  if (init_fp[init_fpc])
1113 	    ++init_fpc;
1114 	}
1115 
1116       init_fp[init_fpc] = fopen (RCFILE, "r");
1117       if (init_fp[init_fpc])
1118 	++init_fpc;
1119     }
1120 
1121   FD_ZERO (&read_fd_set);
1122   FD_ZERO (&read_pending_fd_set);
1123   FD_ZERO (&exception_fd_set);
1124   FD_ZERO (&exception_pending_fd_set);
1125 
1126 #if defined(HAVE_LIBGTK) && !defined(HAVE_MOTIF)
1127    if ((!no_gtk)&&(!no_x)) {
1128 
1129 	gtk_init(&argc, &argv);
1130 
1131 	gtk_graphics ();
1132 	using_gtk = TRUE;
1133 	no_x = TRUE;
1134 	no_curses = TRUE;
1135    }
1136 #endif
1137 
1138 #ifdef HAVE_MOTIF
1139    if ((!no_motif)&&(!no_x)) {
1140 
1141 	motif_init(&argc, argv);
1142 
1143 	using_gtk = FALSE;
1144 	using_motif = TRUE;
1145 	no_x = TRUE;
1146 	no_curses = TRUE;
1147    }
1148 #endif
1149 
1150 #ifndef X_DISPLAY_MISSING
1151   if (!no_x) {
1152     get_x11_args (&argc, argv);
1153     if (Global->io_x11_display_name) {
1154       x11_graphics ();
1155       using_x = TRUE;
1156       no_curses = TRUE;
1157     }
1158   }
1159 #endif /* X_DISPLAY_MISSING */
1160 
1161   if (!no_curses) {
1162 	  tty_graphics ();
1163 	  using_curses = TRUE;
1164 	  /* Allow the disclaimer to be read. */
1165 	  /* if (!init_fpc && !spread_quietly)
1166 		  sleep (5); */
1167   }
1168 
1169   io_open_display ();
1170 
1171   init_graphing ();
1172   PrintInit();
1173   OleoSetEncoding(OLEO_DEFAULT_ENCODING);
1174 
1175   if (setjmp (Global->error_exception))
1176   {
1177 	fprintf (stderr, _("Error in the builtin init scripts (a bug!).\n"));
1178 	io_close_display(69);
1179 	exit (69);
1180   }
1181   else
1182   {
1183 	  init_maps ();
1184 	  init_named_macro_strings ();
1185 	  run_init_cmds ();
1186   }
1187 
1188   oleo_catch_signals(&got_sig);
1189 
1190   /* Read the init file. */
1191   {
1192     volatile int x;
1193     for (x = 0; x < init_fpc; ++x)
1194       {
1195 	if (setjmp (Global->error_exception))
1196 	  {
1197 	    fprintf (stderr, _("   error occured in init file %s near line %d."),
1198 		     init_file_names [x], Global->sneaky_linec);
1199 	    io_info_msg(_("   error occured in init file %s near line %d."),
1200 		     init_file_names [x], Global->sneaky_linec);
1201 	  }
1202 	else
1203 	  if (!ignore_init_file)
1204 	    read_cmds_cmd (init_fp[x]);
1205 	fclose (init_fp[x]);
1206       }
1207   }
1208 
1209 
1210   if (option_filter) {
1211 	    read_file_and_run_hooks(stdin, 0, "stdin");
1212   } else if (argc - optind == 1) {
1213       FILE * fp;
1214       /* fixme: record file name */
1215 
1216     if ((fp = fopen (argv[optind], "r"))) {
1217 	  if (setjmp (Global->error_exception)) {
1218 	    fprintf (stderr, _(", error occured reading '%s'\n"), argv[optind]);
1219 	    io_info_msg(_(", error occured reading '%s'\n"), argv[optind]);
1220 	  } else
1221 	    read_file_and_run_hooks (fp, 0, argv[optind]);
1222 	  fclose (fp);
1223 	  command_line_file = 1;
1224 	  FileSetCurrentFileName(argv[optind]);
1225     } else {
1226 	fprintf (stderr, _("Can't open %s: %s\n"), argv[optind], err_msg ());
1227 	io_info_msg(_("Can't open %s: %s\n"), argv[optind], err_msg ());
1228     }
1229 
1230     optind++;
1231   }
1232 
1233   /* Force the command frame to be rebuilt now that the keymaps exist. */
1234   {
1235     struct command_frame * last_of_the_old = the_cmd_frame->next;
1236     while (the_cmd_frame != last_of_the_old)
1237       free_cmd_frame (the_cmd_frame);
1238     free_cmd_frame (last_of_the_old);
1239   }
1240 
1241   io_recenter_cur_win ();
1242 
1243   Global->display_opened = 1;
1244 
1245 #if 0
1246   /* FIXME - Find better way of doing this */
1247   /* Display openning Copyright screen */
1248   if (!command_line_file)
1249     run_string_as_macro
1250       ("{pushback-keystroke}{builtin-help _NON_WARRANTY_}");
1251 #endif /* 0 */
1252 
1253 #ifdef	HAVE_MOTIF
1254   if (using_motif) {
1255     motif_build_gui();
1256     setjmp (Global->error_exception);
1257     motif_main_loop();
1258   } else {
1259     /* Compile with Motif but don't run with it. */
1260     while (1)
1261     {
1262       setjmp (Global->error_exception);
1263       command_loop (0, 0);
1264     }
1265   }
1266 #else
1267   while (1)
1268     {
1269       setjmp (Global->error_exception);
1270       command_loop (0, 0);
1271     }
1272 #endif
1273   return (0); /* Never Reached! */
1274 }
1275