xref: /csrg-svn/contrib/sc/sc.c (revision 45330)
1*45330Sbostic /*	SC	A Spreadsheet Calculator
2*45330Sbostic  *		Main driver
3*45330Sbostic  *
4*45330Sbostic  *		original by James Gosling, September 1982
5*45330Sbostic  *		modifications by Mark Weiser and Bruce Israel,
6*45330Sbostic  *			University of Maryland
7*45330Sbostic  *
8*45330Sbostic  *              More mods Robert Bond, 12/86
9*45330Sbostic  *		More mods by Alan Silverstein, 3-4/88, see list of changes.
10*45330Sbostic  *		Currently supported by pur-phy!sawmill!buhrt (Jeff Buhrt)
11*45330Sbostic  *		$Revision: 6.8 $
12*45330Sbostic  *
13*45330Sbostic  */
14*45330Sbostic 
15*45330Sbostic 
16*45330Sbostic #include <signal.h>
17*45330Sbostic #include <curses.h>
18*45330Sbostic #include <ctype.h>
19*45330Sbostic 
20*45330Sbostic #ifdef BSD42
21*45330Sbostic #include <strings.h>
22*45330Sbostic #else
23*45330Sbostic #ifndef SYSIII
24*45330Sbostic #include <string.h>
25*45330Sbostic #endif
26*45330Sbostic #endif
27*45330Sbostic 
28*45330Sbostic #include <stdio.h>
29*45330Sbostic #include "sc.h"
30*45330Sbostic 
31*45330Sbostic char *getenv();
32*45330Sbostic 
33*45330Sbostic #ifdef SYSV3
34*45330Sbostic void exit();
35*45330Sbostic #endif
36*45330Sbostic 
37*45330Sbostic #ifndef DFLT_PAGER
38*45330Sbostic #define	DFLT_PAGER "more"	/* more is probably more widespread than less */
39*45330Sbostic #endif /* DFLT_PAGER */
40*45330Sbostic 
41*45330Sbostic #define MAXCMD 160	/* for ! command below */
42*45330Sbostic 
43*45330Sbostic extern	char	*rev;
44*45330Sbostic 
45*45330Sbostic /* Globals defined in sc.h */
46*45330Sbostic 
47*45330Sbostic struct ent ***tbl;
48*45330Sbostic int strow, stcol;
49*45330Sbostic int currow, curcol;
50*45330Sbostic int savedrow, savedcol;
51*45330Sbostic int FullUpdate;
52*45330Sbostic int maxrow, maxcol;
53*45330Sbostic int maxrows, maxcols;
54*45330Sbostic int *fwidth;
55*45330Sbostic int *precision;
56*45330Sbostic char *col_hidden;
57*45330Sbostic char *row_hidden;
58*45330Sbostic char line[FBUFLEN];
59*45330Sbostic int changed;
60*45330Sbostic struct ent *to_fix;
61*45330Sbostic int modflg;
62*45330Sbostic int numeric;
63*45330Sbostic char *mdir;
64*45330Sbostic int showsc, showsr;	/* Starting cell for highlighted range */
65*45330Sbostic char mode_ind = '.';
66*45330Sbostic 
67*45330Sbostic char curfile[PATHLEN];
68*45330Sbostic char    revmsg[80];
69*45330Sbostic 
70*45330Sbostic int  linelim = -1;
71*45330Sbostic 
72*45330Sbostic int  showtop   = 1;	/* Causes current cell value display in top line  */
73*45330Sbostic int  showcell  = 1;	/* Causes current cell to be highlighted	  */
74*45330Sbostic int  showrange = 0;	/* Causes ranges to be highlighted		  */
75*45330Sbostic int  showneed  = 0;	/* Causes cells needing values to be highlighted  */
76*45330Sbostic int  showexpr  = 0;	/* Causes cell exprs to be displayed, highlighted */
77*45330Sbostic 
78*45330Sbostic int  autocalc = 1 ;	/* 1 to calculate after each update */
79*45330Sbostic int  calc_order = BYROWS;
80*45330Sbostic int  tbl_style = 0;	/* headers for T command output */
81*45330Sbostic 
82*45330Sbostic int  lastmx, lastmy;	/* Screen address of the cursor */
83*45330Sbostic int  lastcol;		/* Spreadsheet Column the cursor was in last */
84*45330Sbostic char under_cursor[] = " "; /* Data under the < cursor */
85*45330Sbostic 
86*45330Sbostic #ifdef VMS
87*45330Sbostic int VMS_read_raw = 0;
88*45330Sbostic #endif
89*45330Sbostic 
90*45330Sbostic int seenerr;
91*45330Sbostic 
92*45330Sbostic void
yyerror(err)93*45330Sbostic yyerror(err)
94*45330Sbostic char *err; {
95*45330Sbostic     if (seenerr) return;
96*45330Sbostic     seenerr++;
97*45330Sbostic     (void) move(1,0);
98*45330Sbostic     (void) clrtoeol();
99*45330Sbostic     (void) printw("%s: %.*s<=%s",err,linelim,line,line+linelim);
100*45330Sbostic }
101*45330Sbostic 
102*45330Sbostic struct ent *
lookat(row,col)103*45330Sbostic lookat(row,col)
104*45330Sbostic int	row, col;
105*45330Sbostic {
106*45330Sbostic     register struct ent **pp;
107*45330Sbostic 
108*45330Sbostic     checkbounds(&row, &col);
109*45330Sbostic     pp = ATBL(tbl, row, col);
110*45330Sbostic     if (*pp == (struct ent *)0) {
111*45330Sbostic 	*pp = (struct ent *) xmalloc((unsigned)sizeof(struct ent));
112*45330Sbostic 	if (row>maxrow) maxrow = row;
113*45330Sbostic 	if (col>maxcol) maxcol = col;
114*45330Sbostic 	(*pp)->label = (char *)0;
115*45330Sbostic 	(*pp)->row = row;
116*45330Sbostic 	(*pp)->col = col;
117*45330Sbostic 	(*pp)->flags = 0;
118*45330Sbostic 	(*pp)->expr = (struct enode *)0;
119*45330Sbostic 	(*pp)->v = (double) 0.0;
120*45330Sbostic 	(*pp)->evnext = (struct ent *)0;
121*45330Sbostic     }
122*45330Sbostic     return *pp;
123*45330Sbostic }
124*45330Sbostic 
125*45330Sbostic /*
126*45330Sbostic  * This structure is used to keep ent structs around before they
127*45330Sbostic  * are deleted to allow the sync_refs routine a chance to fix the
128*45330Sbostic  * variable references.
129*45330Sbostic  * We also use it as a last-deleted buffer for the 'p' command.
130*45330Sbostic  */
131*45330Sbostic 
132*45330Sbostic void
free_ent(p)133*45330Sbostic free_ent(p)
134*45330Sbostic register struct ent *p;
135*45330Sbostic {
136*45330Sbostic     p->next = to_fix;
137*45330Sbostic     to_fix = p;
138*45330Sbostic     p->flags |= is_deleted;
139*45330Sbostic }
140*45330Sbostic 
141*45330Sbostic void
flush_saved()142*45330Sbostic flush_saved()
143*45330Sbostic {
144*45330Sbostic     register struct ent *p;
145*45330Sbostic     register struct ent *q;
146*45330Sbostic 
147*45330Sbostic     if (!(p = to_fix))
148*45330Sbostic 	return;
149*45330Sbostic     while (p) {
150*45330Sbostic 	(void) clearent(p);
151*45330Sbostic 	q = p->next;
152*45330Sbostic 	xfree((char *)p);
153*45330Sbostic 	p = q;
154*45330Sbostic     }
155*45330Sbostic     to_fix = 0;
156*45330Sbostic }
157*45330Sbostic 
158*45330Sbostic /*
159*45330Sbostic  * standout last time in update()?
160*45330Sbostic  *	At this point we will let curses do work
161*45330Sbostic  */
162*45330Sbostic int	standlast	= FALSE;
163*45330Sbostic 
164*45330Sbostic void
update(anychanged)165*45330Sbostic update (anychanged)
166*45330Sbostic int	anychanged;	/* did any cell really change in value? */
167*45330Sbostic {
168*45330Sbostic     register    row,
169*45330Sbostic                 col;
170*45330Sbostic     register struct ent **pp;
171*45330Sbostic     int     mxcol;
172*45330Sbostic     int     mxrow;
173*45330Sbostic     int     rows;
174*45330Sbostic     int     cols;
175*45330Sbostic     int     minsr, minsc, maxsr, maxsc;
176*45330Sbostic     register r;
177*45330Sbostic     register i;
178*45330Sbostic 
179*45330Sbostic     while (row_hidden[currow])   /* You can't hide the last row or col */
180*45330Sbostic 	currow++;
181*45330Sbostic     while (col_hidden[curcol])
182*45330Sbostic 	curcol++;
183*45330Sbostic     /* First see if the last display still covers curcol */
184*45330Sbostic     if (stcol <= curcol) {
185*45330Sbostic 	for (i = stcol, cols = 0, col = RESCOL;
186*45330Sbostic 			(col + fwidth[i]) < COLS-1 && i < maxcols; i++) {
187*45330Sbostic 	    cols++;
188*45330Sbostic 	    if (col_hidden[i])
189*45330Sbostic 		continue;
190*45330Sbostic 	    col += fwidth[i];
191*45330Sbostic 	}
192*45330Sbostic     }
193*45330Sbostic     while (stcol + cols - 1 < curcol || curcol < stcol) {
194*45330Sbostic 	FullUpdate++;
195*45330Sbostic 	if (stcol - 1 == curcol) {    /* How about back one? */
196*45330Sbostic 	    stcol--;
197*45330Sbostic 	} else if (stcol + cols == curcol) {   /* Forward one? */
198*45330Sbostic 	    stcol++;
199*45330Sbostic 	} else {
200*45330Sbostic 	    /* Try to put the cursor in the center of the screen */
201*45330Sbostic 	    col = (COLS - RESCOL - fwidth[curcol]) / 2 + RESCOL;
202*45330Sbostic 	    stcol = curcol;
203*45330Sbostic 	    for (i=curcol-1; i >= 0 && col-fwidth[i] > RESCOL; i--) {
204*45330Sbostic 		stcol--;
205*45330Sbostic 		if (col_hidden[i])
206*45330Sbostic 		    continue;
207*45330Sbostic 		col -= fwidth[i];
208*45330Sbostic 	    }
209*45330Sbostic 	}
210*45330Sbostic 	/* Now pick up the counts again */
211*45330Sbostic 	for (i = stcol, cols = 0, col = RESCOL;
212*45330Sbostic 			(col + fwidth[i]) < COLS-1 && i < maxcols; i++) {
213*45330Sbostic 	    cols++;
214*45330Sbostic 	    if (col_hidden[i])
215*45330Sbostic 		continue;
216*45330Sbostic 	    col += fwidth[i];
217*45330Sbostic 	}
218*45330Sbostic     }
219*45330Sbostic     /* Now - same process on the rows */
220*45330Sbostic     if (strow <= currow) {
221*45330Sbostic 	for (i = strow, rows = 0, row=RESROW; row<LINES && i<maxrows; i++) {
222*45330Sbostic 	    rows++;
223*45330Sbostic 	    if (row_hidden[i])
224*45330Sbostic 		continue;
225*45330Sbostic 	    row++;
226*45330Sbostic 	}
227*45330Sbostic     }
228*45330Sbostic     while (strow + rows - 1 < currow || currow < strow) {
229*45330Sbostic 	FullUpdate++;
230*45330Sbostic 	if (strow - 1 == currow) {    /* How about up one? */
231*45330Sbostic 	    strow--;
232*45330Sbostic 	} else if (strow + rows == currow) {   /* Down one? */
233*45330Sbostic 	    strow++;
234*45330Sbostic 	} else {
235*45330Sbostic 	    /* Try to put the cursor in the center of the screen */
236*45330Sbostic 	    row = (LINES - RESROW) / 2 + RESROW;
237*45330Sbostic 	    strow = currow;
238*45330Sbostic 	    for (i=currow-1; i >= 0 && row-1 > RESROW; i--) {
239*45330Sbostic 		strow--;
240*45330Sbostic 		if (row_hidden[i])
241*45330Sbostic 		    continue;
242*45330Sbostic 		row--;
243*45330Sbostic 	    }
244*45330Sbostic 	}
245*45330Sbostic 	/* Now pick up the counts again */
246*45330Sbostic 	for (i = strow, rows = 0, row=RESROW; row<LINES && i<maxrows; i++) {
247*45330Sbostic 	    rows++;
248*45330Sbostic 	    if (row_hidden[i])
249*45330Sbostic 		continue;
250*45330Sbostic 	    row++;
251*45330Sbostic 	}
252*45330Sbostic     }
253*45330Sbostic     mxcol = stcol + cols - 1;
254*45330Sbostic     mxrow = strow + rows - 1;
255*45330Sbostic     if (FullUpdate || standlast) {
256*45330Sbostic 	(void) move(2, 0);
257*45330Sbostic 	(void) clrtobot();
258*45330Sbostic 	(void) standout();
259*45330Sbostic 	for (row=RESROW, i=strow; i <= mxrow; i++) {
260*45330Sbostic 	    if (row_hidden[i])
261*45330Sbostic 		continue;
262*45330Sbostic 	    (void) move(row,0);
263*45330Sbostic 	    if (maxrows < 1000)
264*45330Sbostic 		(void) printw("%-*d", RESCOL-1, i);
265*45330Sbostic 	    else
266*45330Sbostic 		(void) printw("%-*d", RESCOL, i);
267*45330Sbostic 	    row++;
268*45330Sbostic 	}
269*45330Sbostic 	(void) move(2,0);
270*45330Sbostic 	(void) printw("%*s", RESCOL, " ");
271*45330Sbostic 
272*45330Sbostic 	for (col=RESCOL, i = stcol; i <= mxcol; i++) {
273*45330Sbostic 	    register int k;
274*45330Sbostic 	    if (col_hidden[i])
275*45330Sbostic 		continue;
276*45330Sbostic 	    (void) move(2, col);
277*45330Sbostic 	    k = fwidth[i]/2;
278*45330Sbostic 	    if (k == 0)
279*45330Sbostic 		(void) printw("%1s", coltoa(i));
280*45330Sbostic 	    else
281*45330Sbostic 	        (void) printw("%*s%-*s", k, " ", fwidth[i]-k, coltoa(i));
282*45330Sbostic 	    col += fwidth[i];
283*45330Sbostic 	}
284*45330Sbostic 	(void) standend();
285*45330Sbostic     }
286*45330Sbostic 
287*45330Sbostic     /* Get rid of cursor standout on the cell at previous cursor position */
288*45330Sbostic     if (showcell)
289*45330Sbostic     {	(void) move(lastmx, lastmy);
290*45330Sbostic         repaint(lastmx, lastmy, fwidth[lastcol]);
291*45330Sbostic     }
292*45330Sbostic 
293*45330Sbostic     if (showrange) {
294*45330Sbostic 	minsr = showsr < currow ? showsr : currow;
295*45330Sbostic 	minsc = showsc < curcol ? showsc : curcol;
296*45330Sbostic 	maxsr = showsr > currow ? showsr : currow;
297*45330Sbostic 	maxsc = showsc > curcol ? showsc : curcol;
298*45330Sbostic 
299*45330Sbostic 	if (showtop) {
300*45330Sbostic 	    (void) move(1,0);
301*45330Sbostic 	    (void) clrtoeol();
302*45330Sbostic 	    (void) printw("Default range:  %s",
303*45330Sbostic 			    r_name(minsr, minsc, maxsr, maxsc));
304*45330Sbostic 	}
305*45330Sbostic     }
306*45330Sbostic 
307*45330Sbostic     /* Repaint the visible screen */
308*45330Sbostic     if (showrange || anychanged || FullUpdate || standlast)
309*45330Sbostic     {
310*45330Sbostic 	/* may be reset in loop, if not next time we will do a FullUpdate */
311*45330Sbostic       if (standlast)
312*45330Sbostic       {	FullUpdate = TRUE;
313*45330Sbostic 	standlast = FALSE;
314*45330Sbostic       }
315*45330Sbostic       for (row = strow, r = RESROW; row <= mxrow; row++) {
316*45330Sbostic 	register c = RESCOL;
317*45330Sbostic 	int do_stand = 0;
318*45330Sbostic 	int fieldlen;
319*45330Sbostic 	int nextcol;
320*45330Sbostic 
321*45330Sbostic 	if (row_hidden[row])
322*45330Sbostic 	    continue;
323*45330Sbostic 	for (pp = ATBL(tbl, row, col = stcol); col <= mxcol;
324*45330Sbostic 	         pp += nextcol - col,  col = nextcol, c += fieldlen) {
325*45330Sbostic 
326*45330Sbostic 	    nextcol = col+1;
327*45330Sbostic 	    if (col_hidden[col]) {
328*45330Sbostic 		fieldlen = 0;
329*45330Sbostic 		continue;
330*45330Sbostic 	    }
331*45330Sbostic 
332*45330Sbostic 	    fieldlen = fwidth[col];
333*45330Sbostic 
334*45330Sbostic 	    /*
335*45330Sbostic 	     * Set standout if:
336*45330Sbostic 	     *
337*45330Sbostic 	     * - showing ranges, and not showing cells which need to be filled
338*45330Sbostic 	     *	 in, and not showing cell expressions, and in a range, OR
339*45330Sbostic 	     *
340*45330Sbostic 	     * - if showing cells which need to be filled in and this one is
341*45330Sbostic 	     *	 of that type (has a value and doesn't have an expression,
342*45330Sbostic 	     *	 or it is a string expression), OR
343*45330Sbostic 	     *
344*45330Sbostic 	     * - if showing cells which have expressions and this one does.
345*45330Sbostic 	     */
346*45330Sbostic 
347*45330Sbostic 	    if ((showrange && (! showneed) && (! showexpr)
348*45330Sbostic 			   && (row >= minsr) && (row <= maxsr)
349*45330Sbostic 			   && (col >= minsc) && (col <= maxsc))
350*45330Sbostic 		    || (showneed && (*pp) && ((*pp) -> flags & is_valid)
351*45330Sbostic 			&& (((*pp) -> flags & is_strexpr) || !((*pp) -> expr)))
352*45330Sbostic 		    || (showexpr && (*pp) && ((*pp) -> expr)))
353*45330Sbostic 	    {
354*45330Sbostic 		(void) move(r, c);
355*45330Sbostic 		(void) standout();
356*45330Sbostic 		standlast++;
357*45330Sbostic 		if (!*pp)	/* no cell, but standing out */
358*45330Sbostic 		{	(void) printw("%*s", fwidth[col], " ");
359*45330Sbostic 			(void) standend();
360*45330Sbostic 			continue;
361*45330Sbostic 		}
362*45330Sbostic 		else
363*45330Sbostic 			do_stand = 1;
364*45330Sbostic 	    }
365*45330Sbostic 	    else
366*45330Sbostic 		do_stand = 0;
367*45330Sbostic 
368*45330Sbostic 	    if ((*pp) && ((*pp) -> flags & is_changed || FullUpdate) || do_stand) {
369*45330Sbostic 		if (do_stand) {
370*45330Sbostic 		    (*pp) -> flags |= is_changed;
371*45330Sbostic 		} else {
372*45330Sbostic 		    (void) move(r, c);
373*45330Sbostic 		    (*pp) -> flags &= ~is_changed;
374*45330Sbostic 		}
375*45330Sbostic 
376*45330Sbostic 		/*
377*45330Sbostic 		 * Show expression; takes priority over other displays:
378*45330Sbostic 		 */
379*45330Sbostic 
380*45330Sbostic 		if (showexpr && ((*pp) -> expr)) {
381*45330Sbostic 		    linelim = 0;
382*45330Sbostic 		    editexp(row, col);		/* set line to expr */
383*45330Sbostic 		    linelim = -1;
384*45330Sbostic 		    showstring(line, /* leftflush = */ 1, /* hasvalue = */ 0,
385*45330Sbostic 				row, col, & nextcol, mxcol, & fieldlen, r, c);
386*45330Sbostic 		}
387*45330Sbostic 		else {
388*45330Sbostic 
389*45330Sbostic 		    /*
390*45330Sbostic 		     * Show cell's numeric value:
391*45330Sbostic 		     */
392*45330Sbostic 
393*45330Sbostic 		    if ((*pp) -> flags & is_valid) {
394*45330Sbostic 			char field[FBUFLEN];
395*45330Sbostic 			(void)sprintf(field,"%*.*f", fwidth[col], precision[col], (*pp)->v);
396*45330Sbostic 			if(strlen(field) > fwidth[col]) {
397*45330Sbostic 			    for(i = 0; i<fwidth[col]; i++)
398*45330Sbostic 				(void)addch('*');
399*45330Sbostic 			} else {
400*45330Sbostic 			    (void)addstr(field);
401*45330Sbostic 			}
402*45330Sbostic 		    }
403*45330Sbostic 
404*45330Sbostic 		    /*
405*45330Sbostic 		     * Show cell's label string:
406*45330Sbostic 		     */
407*45330Sbostic 
408*45330Sbostic 		    if ((*pp) -> label) {
409*45330Sbostic 			showstring((*pp) -> label,
410*45330Sbostic 				    (*pp) -> flags & is_leftflush,
411*45330Sbostic 				    (*pp) -> flags & is_valid,
412*45330Sbostic 				    row, col, & nextcol, mxcol,
413*45330Sbostic 				    & fieldlen, r, c);
414*45330Sbostic 		    }
415*45330Sbostic 		    else	/* repaint a blank cell: */
416*45330Sbostic 		    if ((do_stand || !FullUpdate) &&
417*45330Sbostic 				((*pp)->flags & is_changed) &&
418*45330Sbostic 				!((*pp)->flags & is_valid) && !(*pp)->label) {
419*45330Sbostic 			(void) printw("%*s", fwidth[col], " ");
420*45330Sbostic 		    }
421*45330Sbostic 		} /* else */
422*45330Sbostic 
423*45330Sbostic 		if (do_stand) {
424*45330Sbostic 		    (void) standend();
425*45330Sbostic 		    do_stand = 0;
426*45330Sbostic 		}
427*45330Sbostic 	    }
428*45330Sbostic 	}
429*45330Sbostic 	r++;
430*45330Sbostic       }
431*45330Sbostic     }
432*45330Sbostic 
433*45330Sbostic     (void) move(lastmy, lastmx+fwidth[lastcol]);
434*45330Sbostic     if((inch() & A_CHARTEXT ) == '<')
435*45330Sbostic         (void) addstr(under_cursor);
436*45330Sbostic 
437*45330Sbostic     lastmy =  RESROW;
438*45330Sbostic     for (row = strow; row < currow; row++)
439*45330Sbostic 	if (!row_hidden[row])
440*45330Sbostic 		lastmy += 1;
441*45330Sbostic     lastmx = RESCOL;
442*45330Sbostic     for (col = stcol; col < curcol; col++)
443*45330Sbostic 	if (!col_hidden[col])
444*45330Sbostic 		lastmx += fwidth[col];
445*45330Sbostic     lastcol = curcol;
446*45330Sbostic     if (showcell && (! showneed) && (! showexpr)) {
447*45330Sbostic 	(void) move(lastmy, lastmx);
448*45330Sbostic         (void) standout();
449*45330Sbostic         repaint(lastmx, lastmy, fwidth[lastcol]);
450*45330Sbostic         (void) standend();
451*45330Sbostic     }
452*45330Sbostic     (void) move(lastmy, lastmx+fwidth[lastcol]);
453*45330Sbostic     *under_cursor = (inch() & A_CHARTEXT );
454*45330Sbostic     (void) addstr("<");
455*45330Sbostic 
456*45330Sbostic     (void) move(0, 0);
457*45330Sbostic     (void) clrtoeol();
458*45330Sbostic     if (linelim >= 0) {
459*45330Sbostic 	(void) addch(mode_ind);
460*45330Sbostic 	(void) addstr("> ");
461*45330Sbostic 	(void) addstr(line);
462*45330Sbostic 	(void) move(0, linelim+3);
463*45330Sbostic     } else {
464*45330Sbostic 	if (showtop) {			/* show top line */
465*45330Sbostic 	    register struct ent *p1;
466*45330Sbostic 	    int printed = 0;		/* printed something? */
467*45330Sbostic 
468*45330Sbostic             (void) printw("%s%d ", coltoa(curcol), currow);
469*45330Sbostic 
470*45330Sbostic 	    if (p1 = *ATBL(tbl, currow, curcol)) {
471*45330Sbostic 		if (p1 -> expr) {
472*45330Sbostic 		    /* has expr of some type */
473*45330Sbostic 		    linelim = 0;
474*45330Sbostic 		    editexp(currow, curcol);	/* set line to expr */
475*45330Sbostic 		    linelim = -1;
476*45330Sbostic 		}
477*45330Sbostic 
478*45330Sbostic 		/*
479*45330Sbostic 		 * Display string part of cell:
480*45330Sbostic 		 */
481*45330Sbostic 
482*45330Sbostic 		if ((p1 -> expr) && (p1 -> flags & is_strexpr)) {
483*45330Sbostic 		    (void) addstr((p1 -> flags & is_leftflush) ? "<{" : ">{");
484*45330Sbostic 		    (void) addstr(line);
485*45330Sbostic 		    (void) addstr("} ");	/* and this '}' is for vi % */
486*45330Sbostic 		    printed = 1;
487*45330Sbostic 
488*45330Sbostic 		} else if (p1 -> label) {
489*45330Sbostic 		    /* has constant label only */
490*45330Sbostic 		    (void) addstr ((p1 -> flags & is_leftflush) ? "<\"" : ">\"");
491*45330Sbostic 		    (void) addstr (p1 -> label);
492*45330Sbostic 		    (void) addstr ("\" ");
493*45330Sbostic 		    printed = 1;
494*45330Sbostic 		}
495*45330Sbostic 
496*45330Sbostic 		/*
497*45330Sbostic 		 * Display value part of cell:
498*45330Sbostic 		 */
499*45330Sbostic 
500*45330Sbostic 		if (p1 -> flags & is_valid) {
501*45330Sbostic 		    /* has value or num expr */
502*45330Sbostic 		    if ((! (p1 -> expr)) || (p1 -> flags & is_strexpr))
503*45330Sbostic 			(void) sprintf (line, "%.15g", p1 -> v);
504*45330Sbostic 
505*45330Sbostic 		    (void) addstr ("[");
506*45330Sbostic 		    (void) addstr (line);
507*45330Sbostic 		    (void) addstr ("]");
508*45330Sbostic 		    printed = 1;
509*45330Sbostic 		}
510*45330Sbostic 	    }
511*45330Sbostic 	    if (! printed)
512*45330Sbostic 		(void) addstr ("[]");
513*45330Sbostic 	}
514*45330Sbostic 	(void) move (lastmy, lastmx + fwidth[lastcol]);
515*45330Sbostic     }
516*45330Sbostic     if (revmsg[0]) {
517*45330Sbostic 	(void) move(0, 0);
518*45330Sbostic 	(void) clrtoeol ();	/* get rid of topline display */
519*45330Sbostic 	(void) printw(revmsg);
520*45330Sbostic 	revmsg[0] = '\0';	/* don't show it again */
521*45330Sbostic 	(void) move (lastmy, lastmx + fwidth[lastcol]);
522*45330Sbostic     }
523*45330Sbostic     FullUpdate = FALSE;
524*45330Sbostic }
525*45330Sbostic 
526*45330Sbostic void
repaint(x,y,len)527*45330Sbostic repaint(x, y, len)
528*45330Sbostic int x, y, len;
529*45330Sbostic {
530*45330Sbostic     int c;
531*45330Sbostic 
532*45330Sbostic     while(len-- > 0) {
533*45330Sbostic 	(void) move(y,x);
534*45330Sbostic 	c = inch() & A_CHARTEXT;
535*45330Sbostic 	(void) addch(c);
536*45330Sbostic 	x++;
537*45330Sbostic     }
538*45330Sbostic }
539*45330Sbostic 
540*45330Sbostic char    *progname;
541*45330Sbostic 
542*45330Sbostic int
main(argc,argv)543*45330Sbostic main (argc, argv)
544*45330Sbostic int argc;
545*45330Sbostic char  **argv;
546*45330Sbostic {
547*45330Sbostic     int     inloop = 1;
548*45330Sbostic     register int   c;
549*45330Sbostic     int     edistate = -1;
550*45330Sbostic     int     arg = 1;
551*45330Sbostic     int     narg;
552*45330Sbostic     int     nedistate;
553*45330Sbostic     int	    running;
554*45330Sbostic     char    *revi;
555*45330Sbostic     int	    anychanged = FALSE;
556*45330Sbostic 
557*45330Sbostic     /*
558*45330Sbostic      * Keep command line options around until the file is read so the
559*45330Sbostic      * command line overrides file options
560*45330Sbostic      */
561*45330Sbostic 
562*45330Sbostic     int Mopt = 0;
563*45330Sbostic     int Nopt = 0;
564*45330Sbostic     int Copt = 0;
565*45330Sbostic     int Ropt = 0;
566*45330Sbostic 
567*45330Sbostic     int tempx, tempy; 	/* Temp versions of curx, cury */
568*45330Sbostic 
569*45330Sbostic     if ((revi = strrchr(argv[0], '/')) != NULL)
570*45330Sbostic 	progname = revi+1;
571*45330Sbostic     else
572*45330Sbostic 	progname = argv[0];
573*45330Sbostic 
574*45330Sbostic     while (argc > 1 && argv[1][0] == '-') {
575*45330Sbostic 	argv++;
576*45330Sbostic 	argc--;
577*45330Sbostic     	switch (argv[0][1]) {
578*45330Sbostic 	    case 'x':
579*45330Sbostic #ifdef VMS
580*45330Sbostic 		    (void) fprintf(stderr, "Crypt not available for VMS\n");
581*45330Sbostic 		    exit(1);
582*45330Sbostic #else
583*45330Sbostic 		    Crypt = 1;
584*45330Sbostic #endif
585*45330Sbostic 		    break;
586*45330Sbostic 	    case 'm':
587*45330Sbostic 		    Mopt = 1;
588*45330Sbostic 		    break;
589*45330Sbostic 	    case 'n':
590*45330Sbostic 		    Nopt = 1;
591*45330Sbostic 		    break;
592*45330Sbostic 	    case 'c':
593*45330Sbostic 		    Copt = 1;
594*45330Sbostic 		    break;
595*45330Sbostic 	    case 'r':
596*45330Sbostic 		    Ropt = 1;
597*45330Sbostic 		    break;
598*45330Sbostic 	    default:
599*45330Sbostic 		    (void) fprintf(stderr,"%s: unrecognized option: \"%c\"\n",
600*45330Sbostic 			progname,argv[0][1]);
601*45330Sbostic 		    exit(1);
602*45330Sbostic 	}
603*45330Sbostic     }
604*45330Sbostic 
605*45330Sbostic     *curfile ='\0';
606*45330Sbostic 
607*45330Sbostic     signals();
608*45330Sbostic     (void) initscr();
609*45330Sbostic 
610*45330Sbostic 	/* setup the spreadsheet arrays, initscr() will get the screen size */
611*45330Sbostic     if (!growtbl(GROWNEW, 0, 0))
612*45330Sbostic     {	endwin();
613*45330Sbostic 	exit(1);
614*45330Sbostic     }
615*45330Sbostic 
616*45330Sbostic     (void) clear();
617*45330Sbostic #ifdef VMS
618*45330Sbostic     VMS_read_raw = 1;
619*45330Sbostic #else
620*45330Sbostic     nonl();
621*45330Sbostic     noecho ();
622*45330Sbostic     cbreak();
623*45330Sbostic #endif
624*45330Sbostic     initkbd();
625*45330Sbostic     scrollok(stdscr, 1);
626*45330Sbostic 
627*45330Sbostic     /*
628*45330Sbostic      * Build revision message for later use:
629*45330Sbostic      */
630*45330Sbostic 
631*45330Sbostic     (void) strcpy (revmsg, progname);
632*45330Sbostic     for (revi = rev; (*revi++) != ':'; );	/* copy after colon */
633*45330Sbostic     (void) strcat (revmsg, revi);
634*45330Sbostic     revmsg [strlen (revmsg) - 2] = 0;		/* erase last character */
635*45330Sbostic     (void) strcat (revmsg, ":  Type '?' for help.");
636*45330Sbostic 
637*45330Sbostic     if (argc > 1) {
638*45330Sbostic 	(void) strcpy(curfile,argv[1]);
639*45330Sbostic 	readfile (argv[1], 0);
640*45330Sbostic     }
641*45330Sbostic 
642*45330Sbostic     if (Mopt)
643*45330Sbostic 	autocalc = 0;
644*45330Sbostic     if (Nopt)
645*45330Sbostic 	numeric = 1;
646*45330Sbostic     if (Copt)
647*45330Sbostic 	calc_order = BYCOLS;
648*45330Sbostic     if (Ropt)
649*45330Sbostic 	calc_order = BYROWS;
650*45330Sbostic 
651*45330Sbostic     modflg = 0;
652*45330Sbostic #ifdef VENIX
653*45330Sbostic     setbuf (stdin, NULL);
654*45330Sbostic #endif
655*45330Sbostic     FullUpdate++;
656*45330Sbostic     while (inloop) { running = 1;
657*45330Sbostic     while (running) {
658*45330Sbostic 	nedistate = -1;
659*45330Sbostic 	narg = 1;
660*45330Sbostic 	if (edistate < 0 && linelim < 0 && autocalc && (changed || FullUpdate))
661*45330Sbostic 	{    EvalAll ();
662*45330Sbostic 	     if (changed)		/* if EvalAll changed or was before */
663*45330Sbostic 		anychanged = TRUE;
664*45330Sbostic 	     changed = 0;
665*45330Sbostic 	}
666*45330Sbostic 	else		/* any cells change? */
667*45330Sbostic 	if (changed)
668*45330Sbostic 	     anychanged = TRUE;
669*45330Sbostic 
670*45330Sbostic 	update(anychanged);
671*45330Sbostic 	anychanged = FALSE;
672*45330Sbostic #ifndef SYSV3
673*45330Sbostic 	(void) refresh(); /* 5.3 does a refresh in getch */
674*45330Sbostic #endif
675*45330Sbostic 	c = nmgetch();
676*45330Sbostic 	getyx(stdscr, tempy, tempx);
677*45330Sbostic 	(void) move (1, 0);
678*45330Sbostic 	(void) clrtoeol ();
679*45330Sbostic 	(void) move(tempy, tempx);
680*45330Sbostic 	(void) fflush (stdout);
681*45330Sbostic 	seenerr = 0;
682*45330Sbostic 	showneed = 0;	/* reset after each update */
683*45330Sbostic 	showexpr = 0;
684*45330Sbostic 
685*45330Sbostic 	/* if ((c < ' ') || ( c == DEL ))   how about international here ? PB */
686*45330Sbostic 	   if ( iscntrl(c) )
687*45330Sbostic 	    switch (c) {
688*45330Sbostic #ifdef SIGTSTP
689*45330Sbostic 		case ctl('z'):
690*45330Sbostic 		    (void) deraw();
691*45330Sbostic 		    (void) kill(0, SIGTSTP); /* Nail process group */
692*45330Sbostic 
693*45330Sbostic 		    /* the pc stops here */
694*45330Sbostic 
695*45330Sbostic 		    (void) goraw();
696*45330Sbostic 		    break;
697*45330Sbostic #endif
698*45330Sbostic 		case ctl('r'):
699*45330Sbostic 		    showneed = 1;
700*45330Sbostic 		case ctl('l'):
701*45330Sbostic 		    FullUpdate++;
702*45330Sbostic 		    (void) clearok(stdscr,1);
703*45330Sbostic 		    break;
704*45330Sbostic 		case ctl('x'):
705*45330Sbostic 		    FullUpdate++;
706*45330Sbostic 		    showexpr = 1;
707*45330Sbostic 		    (void) clearok(stdscr,1);
708*45330Sbostic 		    break;
709*45330Sbostic 		default:
710*45330Sbostic 		    error ("No such command (^%c)", c + 0100);
711*45330Sbostic 		    break;
712*45330Sbostic 		case ctl('b'):
713*45330Sbostic 		    backcol(arg);
714*45330Sbostic 		    break;
715*45330Sbostic 		case ctl('c'):
716*45330Sbostic 		    running = 0;
717*45330Sbostic 		    break;
718*45330Sbostic 
719*45330Sbostic 		case ctl('e'):
720*45330Sbostic 
721*45330Sbostic 		    switch (nmgetch()) {
722*45330Sbostic 		    case ctl('p'): case 'k':	doend (-1, 0);	break;
723*45330Sbostic 		    case ctl('n'): case 'j':	doend ( 1, 0);	break;
724*45330Sbostic 		    case ctl('b'): case 'h':
725*45330Sbostic 		    case ctl('h'):		doend ( 0,-1);	break;
726*45330Sbostic 		    case ctl('f'): case 'l':
727*45330Sbostic 		    case ctl('i'): case ' ':	doend ( 0, 1);	break;
728*45330Sbostic 
729*45330Sbostic 		    case ESC:
730*45330Sbostic 		    case ctl('g'):
731*45330Sbostic 			break;
732*45330Sbostic 
733*45330Sbostic 		    default:
734*45330Sbostic 			error("Invalid ^E command");
735*45330Sbostic 			break;
736*45330Sbostic 		    }
737*45330Sbostic 
738*45330Sbostic 		    break;
739*45330Sbostic 
740*45330Sbostic 		case ctl('f'):
741*45330Sbostic 		    forwcol(arg);
742*45330Sbostic 		    break;
743*45330Sbostic 
744*45330Sbostic 		case ctl('g'):
745*45330Sbostic 		    showrange = 0;
746*45330Sbostic 		    linelim = -1;
747*45330Sbostic 		    (void) move (1, 0);
748*45330Sbostic 		    (void) clrtoeol ();
749*45330Sbostic 		    break;
750*45330Sbostic 
751*45330Sbostic 		case ESC:	/* ctl('[') */
752*45330Sbostic 		    write_line(ESC);
753*45330Sbostic 		    break;
754*45330Sbostic 
755*45330Sbostic 		case ctl('d'):
756*45330Sbostic 		    write_line(ctl('d'));
757*45330Sbostic 		    break;
758*45330Sbostic 
759*45330Sbostic 		case DEL:
760*45330Sbostic 		case ctl('h'):
761*45330Sbostic 		    if (linelim < 0) {	/* not editing line */
762*45330Sbostic 			backcol(arg);	/* treat like ^B    */
763*45330Sbostic 			break;
764*45330Sbostic 		    }
765*45330Sbostic 		    write_line(ctl('h'));
766*45330Sbostic 		    break;
767*45330Sbostic 
768*45330Sbostic 		case ctl('i'): 		/* tab */
769*45330Sbostic 		    if (linelim < 0) {	/* not editing line */
770*45330Sbostic 			forwcol(arg);
771*45330Sbostic 			break;
772*45330Sbostic 		    }
773*45330Sbostic 		    if (!showrange) {
774*45330Sbostic 			startshow();
775*45330Sbostic 		    } else {
776*45330Sbostic 			showdr();
777*45330Sbostic 			linelim = strlen(line);
778*45330Sbostic 			line[linelim++] = ' ';
779*45330Sbostic 			line[linelim] = 0;
780*45330Sbostic 			showrange = 0;
781*45330Sbostic 		    }
782*45330Sbostic 		    linelim = strlen (line);
783*45330Sbostic 		    break;
784*45330Sbostic 
785*45330Sbostic 		case ctl('m'):
786*45330Sbostic 		case ctl('j'):
787*45330Sbostic 		    write_line(ctl('m'));
788*45330Sbostic 		    break;
789*45330Sbostic 
790*45330Sbostic 		case ctl('n'):
791*45330Sbostic 		    forwrow(arg);
792*45330Sbostic 		    break;
793*45330Sbostic 
794*45330Sbostic 		case ctl('p'):
795*45330Sbostic 		    backrow(arg);
796*45330Sbostic 		    break;
797*45330Sbostic 
798*45330Sbostic 		case ctl('q'):
799*45330Sbostic 		    break;	/* ignore flow control */
800*45330Sbostic 
801*45330Sbostic 		case ctl('s'):
802*45330Sbostic 		    break;	/* ignore flow control */
803*45330Sbostic 
804*45330Sbostic 		case ctl('t'):
805*45330Sbostic 		    error(
806*45330Sbostic "Toggle:  a:auto  c:cell  e:ext funcs  n:numeric  t:top  x:encrypt  $:pre-scale");
807*45330Sbostic 		    (void) refresh();
808*45330Sbostic 
809*45330Sbostic 		    switch (nmgetch()) {
810*45330Sbostic 			case 'a': case 'A':
811*45330Sbostic 			case 'm': case 'M':
812*45330Sbostic 			    autocalc ^= 1;
813*45330Sbostic 			    error("Automatic recalculation %sabled.",
814*45330Sbostic 				autocalc ? "en":"dis");
815*45330Sbostic 			    break;
816*45330Sbostic 			case 'n': case 'N':
817*45330Sbostic 			    numeric = (! numeric);
818*45330Sbostic 			    error ("Numeric input %sabled.",
819*45330Sbostic 				    numeric ? "en" : "dis");
820*45330Sbostic 			    break;
821*45330Sbostic 			case 't': case 'T':
822*45330Sbostic 			    showtop = (! showtop);
823*45330Sbostic 			    repaint(lastmx, lastmy, fwidth[lastcol]);
824*45330Sbostic 			    error ("Top line %sabled.", showtop ? "en" : "dis");
825*45330Sbostic 			    break;
826*45330Sbostic 			case 'c': case 'C':
827*45330Sbostic 			    showcell = (! showcell);
828*45330Sbostic 			    repaint(lastmx, lastmy, fwidth[lastcol]);
829*45330Sbostic 			    error ("Cell highlighting %sabled.",
830*45330Sbostic 				    showcell ? "en" : "dis");
831*45330Sbostic 			    break;
832*45330Sbostic 			case 'x': case 'X':
833*45330Sbostic 			    Crypt = (! Crypt);
834*45330Sbostic 			    error ("Encryption %sabled.", Crypt? "en" : "dis");
835*45330Sbostic 			    break;
836*45330Sbostic 			case '$':
837*45330Sbostic 			    if (prescale == 1.0) {
838*45330Sbostic 				error ("Prescale enabled.");
839*45330Sbostic 				prescale = 0.01;
840*45330Sbostic 			    } else {
841*45330Sbostic 				prescale = 1.0;
842*45330Sbostic 				error ("Prescale disabled.");
843*45330Sbostic 			    }
844*45330Sbostic 			    break;
845*45330Sbostic 			case 'e': case 'E':
846*45330Sbostic 			    extfunc = (! extfunc);
847*45330Sbostic 			    error ("External functions %sabled.",
848*45330Sbostic 				    extfunc? "en" : "dis");
849*45330Sbostic 			    break;
850*45330Sbostic 			case ESC:
851*45330Sbostic 			case ctl('g'):
852*45330Sbostic 			    --modflg;	/* negate the modflg++ */
853*45330Sbostic 			    break;
854*45330Sbostic 			default:
855*45330Sbostic 			    error ("Invalid toggle command");
856*45330Sbostic 			    --modflg;	/* negate the modflg++ */
857*45330Sbostic 		    }
858*45330Sbostic 		    FullUpdate++;
859*45330Sbostic 		    modflg++;
860*45330Sbostic 		    break;
861*45330Sbostic 
862*45330Sbostic 		case ctl('u'):
863*45330Sbostic 		    narg = arg * 4;
864*45330Sbostic 		    nedistate = 1;
865*45330Sbostic 		    break;
866*45330Sbostic 
867*45330Sbostic 		case ctl('v'):	/* insert variable name */
868*45330Sbostic 		    if (linelim > 0)
869*45330Sbostic 		        ins_string(v_name(currow, curcol));
870*45330Sbostic 		    break;
871*45330Sbostic 
872*45330Sbostic 		case ctl('w'):	/* insert variable expression */
873*45330Sbostic 		    if (linelim > 0)  {
874*45330Sbostic 			char *temp, *temp1;
875*45330Sbostic 			int templim;
876*45330Sbostic 
877*45330Sbostic 			temp = strcpy(xmalloc((unsigned)(strlen(line)+1)),line);
878*45330Sbostic 			templim = linelim;
879*45330Sbostic 			editexp(currow,curcol);
880*45330Sbostic 			temp1= strcpy(xmalloc((unsigned)(strlen(line)+1)),line);
881*45330Sbostic 			strcpy(line, temp);
882*45330Sbostic 			linelim = templim;
883*45330Sbostic 			ins_string(temp1);
884*45330Sbostic 			xfree(temp);
885*45330Sbostic 			xfree(temp1);
886*45330Sbostic 		    }
887*45330Sbostic 		    break;
888*45330Sbostic 
889*45330Sbostic 		case ctl('a'):	/* insert variable value */
890*45330Sbostic 		    if (linelim > 0) {
891*45330Sbostic 			struct ent *p = *ATBL(tbl, currow, curcol);
892*45330Sbostic 			char temp[100];
893*45330Sbostic 
894*45330Sbostic 			if (p && p -> flags & is_valid) {
895*45330Sbostic 			    (void) sprintf (temp, "%.*f",
896*45330Sbostic 					precision[curcol],p -> v);
897*45330Sbostic 			    ins_string(temp);
898*45330Sbostic 			}
899*45330Sbostic 		    }
900*45330Sbostic 		    break;
901*45330Sbostic 
902*45330Sbostic 	    } /* End of the control char switch stmt */
903*45330Sbostic 	else if (isdigit(c) && ((numeric && edistate >= 0) ||
904*45330Sbostic 			(!numeric && (linelim < 0 || edistate >= 0)))) {
905*45330Sbostic 	    /* we got a leading number */
906*45330Sbostic 	    if (edistate != 0) {
907*45330Sbostic 		/* First char of the count */
908*45330Sbostic 		if (c == '0')      /* just a '0' goes to left col */
909*45330Sbostic 		    curcol = 0;
910*45330Sbostic 		else {
911*45330Sbostic 		    nedistate = 0;
912*45330Sbostic 		    narg = c - '0';
913*45330Sbostic 		}
914*45330Sbostic 	    } else {
915*45330Sbostic 		/* Succeeding count chars */
916*45330Sbostic 		nedistate = 0;
917*45330Sbostic 		narg = arg * 10 + (c - '0');
918*45330Sbostic 	    }
919*45330Sbostic 	} else if (linelim >= 0) {
920*45330Sbostic 	    /* Editing line */
921*45330Sbostic 	    switch(c) {
922*45330Sbostic 	    case ')':
923*45330Sbostic 		if (showrange) {
924*45330Sbostic 		    showdr();
925*45330Sbostic 		    showrange = 0;
926*45330Sbostic 		    linelim = strlen (line);
927*45330Sbostic 		}
928*45330Sbostic 		break;
929*45330Sbostic 	    default:
930*45330Sbostic 		break;
931*45330Sbostic 	    }
932*45330Sbostic 	    write_line(c);
933*45330Sbostic 
934*45330Sbostic 	} else if (!numeric && ( c == '+' || c == '-' ) ) {
935*45330Sbostic 	    /* increment/decrement ops */
936*45330Sbostic 	    register struct ent *p = *ATBL(tbl, currow, curcol);
937*45330Sbostic 	    if (!p)
938*45330Sbostic 		continue;
939*45330Sbostic 	    if (p->expr && !(p->flags & is_strexpr)) {
940*45330Sbostic 		error("Can't increment/decrement a formula\n");
941*45330Sbostic 		continue;
942*45330Sbostic 	    }
943*45330Sbostic 	    FullUpdate++;
944*45330Sbostic 	    modflg++;
945*45330Sbostic 	    if( c == '+' )
946*45330Sbostic 	    	p -> v += (double) arg;
947*45330Sbostic 	    else
948*45330Sbostic 		p -> v -= (double) arg;
949*45330Sbostic 	} else
950*45330Sbostic 	    /* switch on a normal command character */
951*45330Sbostic 	    switch (c) {
952*45330Sbostic 		case ':':
953*45330Sbostic 		    break;	/* Be nice to vi users */
954*45330Sbostic 
955*45330Sbostic 		case '@':
956*45330Sbostic 		    EvalAll ();
957*45330Sbostic 		    changed = 0;
958*45330Sbostic 		    anychanged = TRUE;
959*45330Sbostic 		    break;
960*45330Sbostic 
961*45330Sbostic 		case '0': case '1': case '2': case '3': case '4':
962*45330Sbostic 		case '5': case '6': case '7': case '8': case '9':
963*45330Sbostic 		case '-': case '.': case '+':
964*45330Sbostic 		    (void) sprintf(line,"let %s = %c",
965*45330Sbostic 				v_name(currow, curcol), c);
966*45330Sbostic 		    linelim = strlen (line);
967*45330Sbostic 		    insert_mode();
968*45330Sbostic 		    break;
969*45330Sbostic 
970*45330Sbostic 		case '=':
971*45330Sbostic 		    (void) sprintf(line,"let %s = ",
972*45330Sbostic 					v_name(currow, curcol));
973*45330Sbostic 		    linelim = strlen (line);
974*45330Sbostic 		    insert_mode();
975*45330Sbostic 		    break;
976*45330Sbostic 
977*45330Sbostic 		case '!':
978*45330Sbostic 		    {
979*45330Sbostic 		    /*
980*45330Sbostic 		     *  "! command"  executes command
981*45330Sbostic 		     *  "!"	forks a shell
982*45330Sbostic 		     *  "!!" repeats last command
983*45330Sbostic 		     */
984*45330Sbostic #ifdef VMS
985*45330Sbostic 		    error("Not implemented on VMS");
986*45330Sbostic #else /* VMS */
987*45330Sbostic 		    char *shl;
988*45330Sbostic 		    int pid, temp;
989*45330Sbostic 		    char cmd[MAXCMD];
990*45330Sbostic 		    static char lastcmd[MAXCMD];
991*45330Sbostic 
992*45330Sbostic 		    if (!(shl = getenv("SHELL")))
993*45330Sbostic 			shl = "/bin/sh";
994*45330Sbostic 
995*45330Sbostic 		    deraw();
996*45330Sbostic 		    (void) fputs("! ", stdout);
997*45330Sbostic 		    (void) fflush(stdout);
998*45330Sbostic 		    (void) fgets(cmd, MAXCMD, stdin);
999*45330Sbostic 		    cmd[strlen(cmd) - 1] = '\0';	/* clobber \n */
1000*45330Sbostic 		    if(strcmp(cmd,"!") == 0)		/* repeat? */
1001*45330Sbostic 			    (void) strcpy(cmd, lastcmd);
1002*45330Sbostic 		    else
1003*45330Sbostic 			    (void) strcpy(lastcmd, cmd);
1004*45330Sbostic 
1005*45330Sbostic 		    if (modflg)
1006*45330Sbostic 		    {
1007*45330Sbostic 			(void) puts ("[No write since last change]");
1008*45330Sbostic 			(void) fflush (stdout);
1009*45330Sbostic 		    }
1010*45330Sbostic 
1011*45330Sbostic 		    if (!(pid = fork()))
1012*45330Sbostic 		    {
1013*45330Sbostic 			(void) signal (SIGINT, SIG_DFL);  /* reset */
1014*45330Sbostic 			if(strlen(cmd))
1015*45330Sbostic 				(void)execl(shl,shl,"-c",cmd,(char *)0);
1016*45330Sbostic 			else
1017*45330Sbostic 				(void) execl(shl, shl, (char *)0);
1018*45330Sbostic 			exit(-127);
1019*45330Sbostic 		    }
1020*45330Sbostic 
1021*45330Sbostic 		    while (pid != wait(&temp));
1022*45330Sbostic 
1023*45330Sbostic 		    (void) printf("Press RETURN to continue ");
1024*45330Sbostic 		    (void)nmgetch();
1025*45330Sbostic 		    goraw();
1026*45330Sbostic #endif /* VMS */
1027*45330Sbostic 		    break;
1028*45330Sbostic 		    }
1029*45330Sbostic 
1030*45330Sbostic 		/*
1031*45330Sbostic 		 * Range commands:
1032*45330Sbostic 		 */
1033*45330Sbostic 
1034*45330Sbostic 		case '/':
1035*45330Sbostic 		    error (
1036*45330Sbostic "Range:  x:erase  v:value  c:copy  f:fill  d:define  s:show  u:undefine");
1037*45330Sbostic 		    (void) refresh();
1038*45330Sbostic 
1039*45330Sbostic 		    switch (nmgetch()) {
1040*45330Sbostic 		    case 'c':
1041*45330Sbostic 			(void) sprintf(line,"copy [dest_range src_range] ");
1042*45330Sbostic 			linelim = strlen(line);
1043*45330Sbostic 			startshow();
1044*45330Sbostic 			insert_mode();
1045*45330Sbostic 			break;
1046*45330Sbostic 		    case 'x':
1047*45330Sbostic 			(void) sprintf(line,"erase [range] ");
1048*45330Sbostic 			linelim = strlen(line);
1049*45330Sbostic 			startshow();
1050*45330Sbostic 			insert_mode();
1051*45330Sbostic 			break;
1052*45330Sbostic 		    case 'v':
1053*45330Sbostic 			(void) sprintf(line, "value [range] ");
1054*45330Sbostic 			linelim = strlen(line);
1055*45330Sbostic 			startshow();
1056*45330Sbostic 			insert_mode();
1057*45330Sbostic 			break;
1058*45330Sbostic 		    case 'f':
1059*45330Sbostic 			(void) sprintf(line,"fill [range start inc] ");
1060*45330Sbostic 			linelim = strlen(line);
1061*45330Sbostic 			startshow();
1062*45330Sbostic 			insert_mode();
1063*45330Sbostic 			break;
1064*45330Sbostic 		    case 'd':
1065*45330Sbostic 			(void) sprintf(line,"define [string range] \"");
1066*45330Sbostic 			linelim = strlen(line);
1067*45330Sbostic 			startshow();
1068*45330Sbostic 			insert_mode();
1069*45330Sbostic 			modflg++;
1070*45330Sbostic 			break;
1071*45330Sbostic 		    case 'u':
1072*45330Sbostic 			(void) sprintf(line,"undefine [range] ");
1073*45330Sbostic 			linelim = strlen(line);
1074*45330Sbostic 			insert_mode();
1075*45330Sbostic 			modflg++;
1076*45330Sbostic 			break;
1077*45330Sbostic 		    case 's':
1078*45330Sbostic 			if(are_ranges())
1079*45330Sbostic 			{
1080*45330Sbostic 			FILE *f;
1081*45330Sbostic 			int pid;
1082*45330Sbostic 			char px[MAXCMD] ;
1083*45330Sbostic 			char *pager;
1084*45330Sbostic 
1085*45330Sbostic 			(void) strcpy(px, "| sort | ");
1086*45330Sbostic 			if(!(pager = getenv("PAGER")))
1087*45330Sbostic 				pager = DFLT_PAGER;
1088*45330Sbostic 			(void) strcat(px,pager);
1089*45330Sbostic 			f = openout(px, &pid);
1090*45330Sbostic 			if (!f) {
1091*45330Sbostic 			    error("Can't open pipe to sort");
1092*45330Sbostic 			    break;
1093*45330Sbostic 			}
1094*45330Sbostic 			list_range(f);
1095*45330Sbostic 			closeout(f, pid);
1096*45330Sbostic 			}
1097*45330Sbostic 			else error("No ranges defined");
1098*45330Sbostic 			break;
1099*45330Sbostic 
1100*45330Sbostic 		    case ESC:
1101*45330Sbostic 		    case ctl('g'):
1102*45330Sbostic 			break;
1103*45330Sbostic 		   default:
1104*45330Sbostic 			error("Invalid region command");
1105*45330Sbostic 			break;
1106*45330Sbostic 		   }
1107*45330Sbostic 		   break;
1108*45330Sbostic 
1109*45330Sbostic 		/*
1110*45330Sbostic 		 * Row/column commands:
1111*45330Sbostic 		 */
1112*45330Sbostic 
1113*45330Sbostic 		case 'i':
1114*45330Sbostic 		case 'a':
1115*45330Sbostic 		case 'd':
1116*45330Sbostic 		case 'p':
1117*45330Sbostic 		case 'v':
1118*45330Sbostic 		case 'z':
1119*45330Sbostic 		case 's':
1120*45330Sbostic 		    {
1121*45330Sbostic 			register rcqual;
1122*45330Sbostic 
1123*45330Sbostic 			if (! (rcqual = get_rcqual (c))) {
1124*45330Sbostic 			    error ("Invalid row/column command");
1125*45330Sbostic 			    break;
1126*45330Sbostic 			}
1127*45330Sbostic 
1128*45330Sbostic 			error ("");	/* clear line */
1129*45330Sbostic 
1130*45330Sbostic 			if ( rcqual == ESC || rcqual == ctl('g'))
1131*45330Sbostic 			    break;
1132*45330Sbostic 
1133*45330Sbostic 			switch (c) {
1134*45330Sbostic 
1135*45330Sbostic 			case 'i':
1136*45330Sbostic 			    if (rcqual == 'r')	insertrow(arg);
1137*45330Sbostic 			    else		opencol(curcol, arg);
1138*45330Sbostic 			    break;
1139*45330Sbostic 
1140*45330Sbostic 			case 'a':
1141*45330Sbostic 			    if (rcqual == 'r')	while (arg--) duprow();
1142*45330Sbostic 			    else		while (arg--) dupcol();
1143*45330Sbostic 			    break;
1144*45330Sbostic 
1145*45330Sbostic 			case 'd':
1146*45330Sbostic 			    if (rcqual == 'r')	deleterow(arg);
1147*45330Sbostic 			    else		closecol(curcol, arg);
1148*45330Sbostic 			    break;
1149*45330Sbostic 
1150*45330Sbostic 			case 'p':
1151*45330Sbostic 			    while (arg--)	pullcells(rcqual);
1152*45330Sbostic 			    break;
1153*45330Sbostic 
1154*45330Sbostic 			case 'v':
1155*45330Sbostic 			    if (rcqual == 'r')	rowvalueize(arg);
1156*45330Sbostic 			    else		colvalueize(arg);
1157*45330Sbostic 			    modflg = 1;
1158*45330Sbostic 			    break;
1159*45330Sbostic 
1160*45330Sbostic 			case 'z':
1161*45330Sbostic 			    if (rcqual == 'r')	hiderow(arg);
1162*45330Sbostic 			    else		hidecol(arg);
1163*45330Sbostic 			    break;
1164*45330Sbostic 
1165*45330Sbostic 			case 's':
1166*45330Sbostic 			    /* special case; no repeat count */
1167*45330Sbostic 
1168*45330Sbostic 			    if (rcqual == 'r')	rowshow_op();
1169*45330Sbostic 			    else		colshow_op();
1170*45330Sbostic 			    break;
1171*45330Sbostic 			}
1172*45330Sbostic 			break;
1173*45330Sbostic 		    }
1174*45330Sbostic 
1175*45330Sbostic 		case '$':
1176*45330Sbostic 		    {
1177*45330Sbostic 		    register struct ent *p;
1178*45330Sbostic 
1179*45330Sbostic 		    curcol = maxcols - 1;
1180*45330Sbostic 		    while (!VALID_CELL(p, currow, curcol) && curcol > 0)
1181*45330Sbostic 			curcol--;
1182*45330Sbostic 		    break;
1183*45330Sbostic 		    }
1184*45330Sbostic 		case '#':
1185*45330Sbostic 		    {
1186*45330Sbostic 		    register struct ent *p;
1187*45330Sbostic 
1188*45330Sbostic 		    currow = maxrows - 1;
1189*45330Sbostic 		    while (!VALID_CELL(p, currow, curcol) && currow > 0)
1190*45330Sbostic 			currow--;
1191*45330Sbostic 		    break;
1192*45330Sbostic 		    }
1193*45330Sbostic 		case 'w':
1194*45330Sbostic 		    {
1195*45330Sbostic 		    register struct ent *p;
1196*45330Sbostic 
1197*45330Sbostic 		    while (--arg>=0) {
1198*45330Sbostic 			do {
1199*45330Sbostic 			    if (curcol < maxcols - 1)
1200*45330Sbostic 				curcol++;
1201*45330Sbostic 			    else {
1202*45330Sbostic 				if (currow < maxrows - 1) {
1203*45330Sbostic 				    while(++currow < maxrows - 1 &&
1204*45330Sbostic 					    row_hidden[currow]) /* */;
1205*45330Sbostic 				    curcol = 0;
1206*45330Sbostic 				} else {
1207*45330Sbostic 				    error("At end of table");
1208*45330Sbostic 				    break;
1209*45330Sbostic 				}
1210*45330Sbostic 			    }
1211*45330Sbostic 			} while(col_hidden[curcol] ||
1212*45330Sbostic 				!VALID_CELL(p, currow, curcol));
1213*45330Sbostic 		    }
1214*45330Sbostic 		    break;
1215*45330Sbostic 		    }
1216*45330Sbostic 		case 'b':
1217*45330Sbostic 		    {
1218*45330Sbostic 		    register struct ent *p;
1219*45330Sbostic 
1220*45330Sbostic 		    while (--arg>=0) {
1221*45330Sbostic 			do {
1222*45330Sbostic 			    if (curcol)
1223*45330Sbostic 				curcol--;
1224*45330Sbostic 			    else {
1225*45330Sbostic 				if (currow) {
1226*45330Sbostic 				    while(--currow &&
1227*45330Sbostic 					row_hidden[currow]) /* */;
1228*45330Sbostic 				    curcol = maxcols - 1;
1229*45330Sbostic 				} else {
1230*45330Sbostic 				    error ("At start of table");
1231*45330Sbostic 				    break;
1232*45330Sbostic 				}
1233*45330Sbostic 			    }
1234*45330Sbostic 			} while(col_hidden[curcol] ||
1235*45330Sbostic 				!VALID_CELL(p, currow, curcol));
1236*45330Sbostic 		    }
1237*45330Sbostic 		    break;
1238*45330Sbostic 		    }
1239*45330Sbostic 		case '^':
1240*45330Sbostic 		    currow = 0;
1241*45330Sbostic 		    break;
1242*45330Sbostic 		case '?':
1243*45330Sbostic 		    help();
1244*45330Sbostic 		    break;
1245*45330Sbostic 		case '"':
1246*45330Sbostic 		    (void) sprintf (line, "label %s = \"",
1247*45330Sbostic 					v_name(currow, curcol));
1248*45330Sbostic 		    linelim = strlen (line);
1249*45330Sbostic 		    insert_mode();
1250*45330Sbostic 		    break;
1251*45330Sbostic 		case '<':
1252*45330Sbostic 		    (void) sprintf (line, "leftstring %s = \"",
1253*45330Sbostic 			    v_name(currow, curcol));
1254*45330Sbostic 		    linelim = strlen (line);
1255*45330Sbostic 		    insert_mode();
1256*45330Sbostic 		    break;
1257*45330Sbostic 		case '>':
1258*45330Sbostic 		    (void) sprintf (line, "rightstring %s = \"",
1259*45330Sbostic 			   v_name(currow, curcol));
1260*45330Sbostic 		    linelim = strlen (line);
1261*45330Sbostic 		    insert_mode();
1262*45330Sbostic 		    break;
1263*45330Sbostic 		case 'e':
1264*45330Sbostic 		    editv (currow, curcol);
1265*45330Sbostic 		    edit_mode();
1266*45330Sbostic 		    break;
1267*45330Sbostic 		case 'E':
1268*45330Sbostic 		    edits (currow, curcol);
1269*45330Sbostic 		    edit_mode();
1270*45330Sbostic 		    break;
1271*45330Sbostic 		case 'f':
1272*45330Sbostic 		    if (arg == 1)
1273*45330Sbostic 			(void) sprintf (line, "format [for column] %s ",
1274*45330Sbostic 				coltoa(curcol));
1275*45330Sbostic 		    else {
1276*45330Sbostic 			(void) sprintf(line, "format [for columns] %s:",
1277*45330Sbostic 				coltoa(curcol));
1278*45330Sbostic 			(void) sprintf(line+strlen(line), "%s ",
1279*45330Sbostic 				coltoa(curcol+arg-1));
1280*45330Sbostic 		    }
1281*45330Sbostic 		    error("Current format is %d %d",
1282*45330Sbostic 				fwidth[curcol],precision[curcol]);
1283*45330Sbostic 		    linelim = strlen (line);
1284*45330Sbostic 		    insert_mode();
1285*45330Sbostic 		    break;
1286*45330Sbostic 		case 'g':
1287*45330Sbostic 		    (void) sprintf (line, "goto [v] ");
1288*45330Sbostic 		    linelim = strlen (line);
1289*45330Sbostic 		    insert_mode();
1290*45330Sbostic 		    break;
1291*45330Sbostic 		case 'P':
1292*45330Sbostic 		    (void) sprintf (line, "put [\"dest\" range] \"");
1293*45330Sbostic 		    if (*curfile)
1294*45330Sbostic 			error ("Default path is \"%s\"",curfile);
1295*45330Sbostic 		    linelim = strlen (line);
1296*45330Sbostic 		    insert_mode();
1297*45330Sbostic 		    break;
1298*45330Sbostic 		case 'M':
1299*45330Sbostic 		    (void) sprintf (line, "merge [\"source\"] \"");
1300*45330Sbostic 		    linelim = strlen (line);
1301*45330Sbostic 		    insert_mode();
1302*45330Sbostic 		    break;
1303*45330Sbostic 		case 'R':
1304*45330Sbostic 		    if (mdir)
1305*45330Sbostic 			(void) sprintf (line,"merge [\"macro_file\"] \"%s/", mdir);
1306*45330Sbostic 		    else
1307*45330Sbostic 			(void) sprintf (line,"merge [\"macro_file\"] \"");
1308*45330Sbostic 		    linelim = strlen (line);
1309*45330Sbostic 		    insert_mode();
1310*45330Sbostic 		    break;
1311*45330Sbostic 		case 'D':
1312*45330Sbostic 		    (void) sprintf (line, "mdir [\"macro_directory\"] \"");
1313*45330Sbostic 		    linelim = strlen (line);
1314*45330Sbostic 		    insert_mode();
1315*45330Sbostic 		    break;
1316*45330Sbostic 		case 'G':
1317*45330Sbostic 		    (void) sprintf (line, "get [\"source\"] \"");
1318*45330Sbostic 		    if (*curfile)
1319*45330Sbostic 			error ("Default file is \"%s\"",curfile);
1320*45330Sbostic 		    linelim = strlen (line);
1321*45330Sbostic 		    insert_mode();
1322*45330Sbostic 		    break;
1323*45330Sbostic 		case 'W':
1324*45330Sbostic 		    (void) sprintf (line, "write [\"dest\" range] \"");
1325*45330Sbostic 		    linelim = strlen (line);
1326*45330Sbostic 		    insert_mode();
1327*45330Sbostic 		    break;
1328*45330Sbostic 		case 'S':	/* set options */
1329*45330Sbostic 		    (void) sprintf (line, "set ");
1330*45330Sbostic 		    error("Options: byrows, bycols, iterations=n, tblstyle=(0|tbl|latex|tex)");
1331*45330Sbostic 		    linelim = strlen (line);
1332*45330Sbostic 		    insert_mode();
1333*45330Sbostic 		    break;
1334*45330Sbostic 		case 'T':	/* tbl output */
1335*45330Sbostic 		    (void) sprintf (line, "tbl [\"dest\" range] \"");
1336*45330Sbostic 		    linelim = strlen (line);
1337*45330Sbostic 		    insert_mode();
1338*45330Sbostic 		    break;
1339*45330Sbostic 		case 'x':
1340*45330Sbostic 		    {
1341*45330Sbostic 		    register struct ent **pp;
1342*45330Sbostic 		    register int c1;
1343*45330Sbostic 
1344*45330Sbostic 		    flush_saved();
1345*45330Sbostic 		    if(calc_order == BYROWS) {
1346*45330Sbostic 		    for (c1 = curcol; arg-- && c1 < maxcols; c1++) {
1347*45330Sbostic 			pp = ATBL(tbl, currow, c1);
1348*45330Sbostic 			if (*pp) {
1349*45330Sbostic 			    free_ent(*pp);
1350*45330Sbostic 			    *pp = (struct ent *)0;
1351*45330Sbostic 			}
1352*45330Sbostic 		    }
1353*45330Sbostic 		    }
1354*45330Sbostic 		    else {
1355*45330Sbostic 		    for (c1 = currow; arg-- && c1 < maxrows; c1++) {
1356*45330Sbostic 			pp = ATBL(tbl, c1, curcol);
1357*45330Sbostic 			if (*pp) {
1358*45330Sbostic 			    free_ent(*pp);
1359*45330Sbostic 			    *pp = (struct ent *)0;
1360*45330Sbostic 			}
1361*45330Sbostic 		    }
1362*45330Sbostic 		    }
1363*45330Sbostic 		    sync_refs();
1364*45330Sbostic 		    modflg++;
1365*45330Sbostic 		    FullUpdate++;
1366*45330Sbostic 		    }
1367*45330Sbostic 		    break;
1368*45330Sbostic 		case 'Q':
1369*45330Sbostic 		case 'q':
1370*45330Sbostic 		    running = 0;
1371*45330Sbostic 		    break;
1372*45330Sbostic 		case 'h':
1373*45330Sbostic 		    backcol(arg);
1374*45330Sbostic 		    break;
1375*45330Sbostic 		case 'j':
1376*45330Sbostic 		    forwrow(arg);
1377*45330Sbostic 		    break;
1378*45330Sbostic 		case 'k':
1379*45330Sbostic 		    backrow(arg);
1380*45330Sbostic 		    break;
1381*45330Sbostic 		case ' ':
1382*45330Sbostic 		case 'l':
1383*45330Sbostic 		    forwcol(arg);
1384*45330Sbostic 		    break;
1385*45330Sbostic 		case 'm':
1386*45330Sbostic 		    savedrow = currow;
1387*45330Sbostic 		    savedcol = curcol;
1388*45330Sbostic 		    break;
1389*45330Sbostic 		case 'c': {
1390*45330Sbostic 		    register struct ent *p = *ATBL(tbl, savedrow, savedcol);
1391*45330Sbostic 		    register c1;
1392*45330Sbostic 		    register struct ent *n;
1393*45330Sbostic 		    if (!p)
1394*45330Sbostic 			break;
1395*45330Sbostic 		    FullUpdate++;
1396*45330Sbostic 		    modflg++;
1397*45330Sbostic 		    for (c1 = curcol; arg-- && c1 < maxcols; c1++) {
1398*45330Sbostic 			n = lookat (currow, c1);
1399*45330Sbostic 			(void) clearent(n);
1400*45330Sbostic 			copyent( n, p, currow - savedrow, c1 - savedcol);
1401*45330Sbostic 		    }
1402*45330Sbostic 		    break;
1403*45330Sbostic 		}
1404*45330Sbostic 		default:
1405*45330Sbostic 		    if ((toascii(c)) != c)
1406*45330Sbostic 			error ("Weird character, decimal %d\n",
1407*45330Sbostic 				(int) c);
1408*45330Sbostic 		    else
1409*45330Sbostic 			    error ("No such command (%c)", c);
1410*45330Sbostic 		    break;
1411*45330Sbostic 	    }
1412*45330Sbostic 	edistate = nedistate;
1413*45330Sbostic 	arg = narg;
1414*45330Sbostic     }				/* while (running) */
1415*45330Sbostic     inloop = modcheck(" before exiting");
1416*45330Sbostic     }				/*  while (inloop) */
1417*45330Sbostic     deraw();
1418*45330Sbostic     endwin();
1419*45330Sbostic #ifdef VMS	/* Unit VMS "fixes" exit we should say 1 here */
1420*45330Sbostic     exit(1);
1421*45330Sbostic #else
1422*45330Sbostic     exit(0);
1423*45330Sbostic #endif
1424*45330Sbostic     /*NOTREACHED*/
1425*45330Sbostic }
1426*45330Sbostic 
1427*45330Sbostic void
startshow()1428*45330Sbostic startshow()
1429*45330Sbostic {
1430*45330Sbostic     showrange = 1;
1431*45330Sbostic     showsr = currow;
1432*45330Sbostic     showsc = curcol;
1433*45330Sbostic }
1434*45330Sbostic 
1435*45330Sbostic void
showdr()1436*45330Sbostic showdr()
1437*45330Sbostic {
1438*45330Sbostic     int     minsr, minsc, maxsr, maxsc;
1439*45330Sbostic 
1440*45330Sbostic     minsr = showsr < currow ? showsr : currow;
1441*45330Sbostic     minsc = showsc < curcol ? showsc : curcol;
1442*45330Sbostic     maxsr = showsr > currow ? showsr : currow;
1443*45330Sbostic     maxsc = showsc > curcol ? showsc : curcol;
1444*45330Sbostic     (void) sprintf (line+linelim,"%s", r_name(minsr, minsc, maxsr, maxsc));
1445*45330Sbostic }
1446*45330Sbostic 
1447*45330Sbostic void
setorder(i)1448*45330Sbostic setorder(i)
1449*45330Sbostic int i;
1450*45330Sbostic {
1451*45330Sbostic 	if((i == BYROWS)||(i == BYCOLS))
1452*45330Sbostic 	    calc_order = i;
1453*45330Sbostic 	else
1454*45330Sbostic 	    error("Not yet implemented");
1455*45330Sbostic }
1456*45330Sbostic 
1457*45330Sbostic void
setauto(i)1458*45330Sbostic setauto(i)
1459*45330Sbostic int i;
1460*45330Sbostic {
1461*45330Sbostic 	autocalc = i;
1462*45330Sbostic }
1463*45330Sbostic 
1464*45330Sbostic 
1465*45330Sbostic #ifdef VMS
1466*45330Sbostic 
goraw()1467*45330Sbostic goraw()
1468*45330Sbostic {
1469*45330Sbostic     VMS_read_raw = 1;
1470*45330Sbostic     FullUpdate++;
1471*45330Sbostic }
1472*45330Sbostic 
deraw()1473*45330Sbostic deraw()
1474*45330Sbostic {
1475*45330Sbostic     (void) move (LINES - 1, 0);
1476*45330Sbostic     (void) clrtoeol();
1477*45330Sbostic     (void) refresh();
1478*45330Sbostic     VMS_read_raw = 0;
1479*45330Sbostic }
1480*45330Sbostic 
1481*45330Sbostic #else /* VMS */
1482*45330Sbostic void
goraw()1483*45330Sbostic goraw()
1484*45330Sbostic {
1485*45330Sbostic #if SYSV2 || SYSV3
1486*45330Sbostic     fixterm();
1487*45330Sbostic #else /* SYSV2 || SYSV3 */
1488*45330Sbostic     cbreak();
1489*45330Sbostic     nonl();
1490*45330Sbostic     noecho ();
1491*45330Sbostic #endif /* SYSV2 || SYSV3 */
1492*45330Sbostic     kbd_again();
1493*45330Sbostic     (void) clear();
1494*45330Sbostic     FullUpdate++;
1495*45330Sbostic }
1496*45330Sbostic 
1497*45330Sbostic void
deraw()1498*45330Sbostic deraw()
1499*45330Sbostic {
1500*45330Sbostic     (void) move (LINES - 1, 0);
1501*45330Sbostic     (void) clrtoeol();
1502*45330Sbostic     (void) refresh();
1503*45330Sbostic #if SYSV2 || SYSV3
1504*45330Sbostic     resetterm();
1505*45330Sbostic #else
1506*45330Sbostic     nocbreak();
1507*45330Sbostic     nl();
1508*45330Sbostic     echo();
1509*45330Sbostic #endif
1510*45330Sbostic     resetkbd();
1511*45330Sbostic }
1512*45330Sbostic 
1513*45330Sbostic #endif /* VMS */
1514*45330Sbostic 
1515*45330Sbostic void
signals()1516*45330Sbostic signals()
1517*45330Sbostic {
1518*45330Sbostic #ifdef SIGVOID
1519*45330Sbostic     void quit();
1520*45330Sbostic     void time_out();
1521*45330Sbostic     void dump_me();
1522*45330Sbostic #else
1523*45330Sbostic     int quit();
1524*45330Sbostic     int time_out();
1525*45330Sbostic     int dump_me();
1526*45330Sbostic #endif
1527*45330Sbostic 
1528*45330Sbostic     (void) signal(SIGINT, SIG_IGN);
1529*45330Sbostic     (void) signal(SIGQUIT, dump_me);
1530*45330Sbostic     (void) signal(SIGPIPE, quit);
1531*45330Sbostic     (void) signal(SIGTERM, quit);
1532*45330Sbostic     (void) signal(SIGALRM, time_out);
1533*45330Sbostic     (void) signal(SIGFPE, quit);
1534*45330Sbostic     (void) signal(SIGBUS, quit);
1535*45330Sbostic }
1536*45330Sbostic 
1537*45330Sbostic #ifdef SIGVOID
1538*45330Sbostic void
1539*45330Sbostic #endif
quit()1540*45330Sbostic quit()
1541*45330Sbostic {
1542*45330Sbostic     diesave();
1543*45330Sbostic     deraw();
1544*45330Sbostic     resetkbd();
1545*45330Sbostic     endwin();
1546*45330Sbostic     exit(1);
1547*45330Sbostic }
1548*45330Sbostic 
1549*45330Sbostic #ifdef SIGVOID
1550*45330Sbostic void
1551*45330Sbostic #endif
dump_me()1552*45330Sbostic dump_me()
1553*45330Sbostic {
1554*45330Sbostic     diesave();
1555*45330Sbostic     deraw();
1556*45330Sbostic     abort();
1557*45330Sbostic }
1558*45330Sbostic 
1559*45330Sbostic /* try to save the current spreadsheet if we can */
diesave()1560*45330Sbostic diesave()
1561*45330Sbostic {   char	path[PATHLEN];
1562*45330Sbostic     if (modcheck(" before Spreadsheet dies") == 1)
1563*45330Sbostic     {	sprintf(path, "~/SC.SAVE");
1564*45330Sbostic 	if (writefile(path, 0, 0, maxrow, maxcol) < 0)
1565*45330Sbostic 	    if (writefile("/tmp/SC.SAVE", 0, 0, maxrow, maxcol) < 0)
1566*45330Sbostic 		error("Couldn't save current spreadsheet, Sorry");
1567*45330Sbostic     }
1568*45330Sbostic }
1569*45330Sbostic 
1570*45330Sbostic int
modcheck(endstr)1571*45330Sbostic modcheck(endstr)
1572*45330Sbostic char *endstr;
1573*45330Sbostic {
1574*45330Sbostic     if (modflg && curfile[0]) {
1575*45330Sbostic 	int	yn_ans;
1576*45330Sbostic 	char	lin[100];
1577*45330Sbostic 
1578*45330Sbostic 	(void) sprintf (lin,"File \"%s\" is modified, save%s? ",curfile,endstr);
1579*45330Sbostic 	if ((yn_ans = yn_ask(lin)) < 0)
1580*45330Sbostic 		return(1);
1581*45330Sbostic 	else
1582*45330Sbostic 	if (yn_ans == 1)
1583*45330Sbostic 	{    if (writefile(curfile, 0, 0, maxrow, maxcol) < 0)
1584*45330Sbostic  		return (1);
1585*45330Sbostic 	}
1586*45330Sbostic     } else if (modflg) {
1587*45330Sbostic 	int	yn_ans;
1588*45330Sbostic 
1589*45330Sbostic 	if ((yn_ans = yn_ask("Do you want a chance to save the data? ")) < 0)
1590*45330Sbostic 		return(1);
1591*45330Sbostic 	else
1592*45330Sbostic 		return(yn_ans);
1593*45330Sbostic     }
1594*45330Sbostic     return(0);
1595*45330Sbostic }
1596