xref: /original-bsd/contrib/sc/cmds.c (revision 3ba7c9e2)
1*3ba7c9e2Sbostic /*	SC	A Spreadsheet Calculator
2*3ba7c9e2Sbostic  *		Command routines
3*3ba7c9e2Sbostic  *
4*3ba7c9e2Sbostic  *		original by James Gosling, September 1982
5*3ba7c9e2Sbostic  *		modifications by Mark Weiser and Bruce Israel,
6*3ba7c9e2Sbostic  *			University of Maryland
7*3ba7c9e2Sbostic  *
8*3ba7c9e2Sbostic  *              More mods Robert Bond, 12/86
9*3ba7c9e2Sbostic  *
10*3ba7c9e2Sbostic  *		$Revision: 6.8 $
11*3ba7c9e2Sbostic  */
12*3ba7c9e2Sbostic 
13*3ba7c9e2Sbostic #include <curses.h>
14*3ba7c9e2Sbostic #if defined(BSD42) || defined(BSD43)
15*3ba7c9e2Sbostic #include <sys/file.h>
16*3ba7c9e2Sbostic #else
17*3ba7c9e2Sbostic #include <fcntl.h>
18*3ba7c9e2Sbostic #endif
19*3ba7c9e2Sbostic #include "sc.h"
20*3ba7c9e2Sbostic #include <signal.h>
21*3ba7c9e2Sbostic #include <errno.h>
22*3ba7c9e2Sbostic 
23*3ba7c9e2Sbostic #ifdef BSD42
24*3ba7c9e2Sbostic #include <strings.h>
25*3ba7c9e2Sbostic #else
26*3ba7c9e2Sbostic #ifndef SYSIII
27*3ba7c9e2Sbostic #include <string.h>
28*3ba7c9e2Sbostic #endif
29*3ba7c9e2Sbostic #endif
30*3ba7c9e2Sbostic 
31*3ba7c9e2Sbostic #ifdef SYSV3
32*3ba7c9e2Sbostic extern void exit();
33*3ba7c9e2Sbostic #else
34*3ba7c9e2Sbostic extern int exit();
35*3ba7c9e2Sbostic #endif
36*3ba7c9e2Sbostic 
37*3ba7c9e2Sbostic extern	int	errno;
38*3ba7c9e2Sbostic 
39*3ba7c9e2Sbostic #define DEFCOLDELIM ':'
40*3ba7c9e2Sbostic 
41*3ba7c9e2Sbostic void
duprow()42*3ba7c9e2Sbostic duprow()
43*3ba7c9e2Sbostic {
44*3ba7c9e2Sbostic     if (currow >= maxrows - 1 || maxrow >= maxrows - 1) {
45*3ba7c9e2Sbostic 	if (!growtbl(GROWROW, 0, 0))
46*3ba7c9e2Sbostic 		return;
47*3ba7c9e2Sbostic     }
48*3ba7c9e2Sbostic     modflg++;
49*3ba7c9e2Sbostic     currow++;
50*3ba7c9e2Sbostic     openrow (currow);
51*3ba7c9e2Sbostic     for (curcol = 0; curcol <= maxcol; curcol++) {
52*3ba7c9e2Sbostic 	register struct ent *p = *ATBL(tbl, currow - 1, curcol);
53*3ba7c9e2Sbostic 	if (p) {
54*3ba7c9e2Sbostic 	    register struct ent *n;
55*3ba7c9e2Sbostic 	    n = lookat (currow, curcol);
56*3ba7c9e2Sbostic 	    (void)copyent ( n, p, 1, 0);
57*3ba7c9e2Sbostic 	}
58*3ba7c9e2Sbostic     }
59*3ba7c9e2Sbostic     for (curcol = 0; curcol <= maxcol; curcol++) {
60*3ba7c9e2Sbostic 	register struct ent *p = *ATBL(tbl, currow, curcol);
61*3ba7c9e2Sbostic 	if (p && (p -> flags & is_valid) && !p -> expr)
62*3ba7c9e2Sbostic 	    break;
63*3ba7c9e2Sbostic     }
64*3ba7c9e2Sbostic     if (curcol > maxcol)
65*3ba7c9e2Sbostic 	curcol = 0;
66*3ba7c9e2Sbostic }
67*3ba7c9e2Sbostic 
68*3ba7c9e2Sbostic void
dupcol()69*3ba7c9e2Sbostic dupcol()
70*3ba7c9e2Sbostic {
71*3ba7c9e2Sbostic     if (curcol >= maxcols - 1 || maxcol >= maxcols - 1) {
72*3ba7c9e2Sbostic 	if (!growtbl(GROWCOL, 0, 0))
73*3ba7c9e2Sbostic 		return;
74*3ba7c9e2Sbostic     }
75*3ba7c9e2Sbostic     modflg++;
76*3ba7c9e2Sbostic     curcol++;
77*3ba7c9e2Sbostic     opencol (curcol, 1);
78*3ba7c9e2Sbostic     for (currow = 0; currow <= maxrow; currow++) {
79*3ba7c9e2Sbostic 	register struct ent *p = *ATBL(tbl, currow, curcol - 1);
80*3ba7c9e2Sbostic 	if (p) {
81*3ba7c9e2Sbostic 	    register struct ent *n;
82*3ba7c9e2Sbostic 	    n = lookat (currow, curcol);
83*3ba7c9e2Sbostic 	    copyent ( n, p, 0, 1);
84*3ba7c9e2Sbostic 	}
85*3ba7c9e2Sbostic     }
86*3ba7c9e2Sbostic     for (currow = 0; currow <= maxrow; currow++) {
87*3ba7c9e2Sbostic 	register struct ent *p = *ATBL(tbl, currow, curcol);
88*3ba7c9e2Sbostic 	if (p && (p -> flags & is_valid) && !p -> expr)
89*3ba7c9e2Sbostic 	    break;
90*3ba7c9e2Sbostic     }
91*3ba7c9e2Sbostic     if (currow > maxrow)
92*3ba7c9e2Sbostic 	currow = 0;
93*3ba7c9e2Sbostic }
94*3ba7c9e2Sbostic 
95*3ba7c9e2Sbostic void
insertrow(arg)96*3ba7c9e2Sbostic insertrow(arg)
97*3ba7c9e2Sbostic register int arg;
98*3ba7c9e2Sbostic {
99*3ba7c9e2Sbostic     while (--arg>=0) openrow (currow);
100*3ba7c9e2Sbostic }
101*3ba7c9e2Sbostic 
102*3ba7c9e2Sbostic void
deleterow(arg)103*3ba7c9e2Sbostic deleterow(arg)
104*3ba7c9e2Sbostic register int arg;
105*3ba7c9e2Sbostic {
106*3ba7c9e2Sbostic     flush_saved();
107*3ba7c9e2Sbostic     erase_area(currow, 0, currow + arg - 1, maxcol);
108*3ba7c9e2Sbostic     currow += arg;
109*3ba7c9e2Sbostic     while (--arg>=0) closerow (--currow);
110*3ba7c9e2Sbostic     sync_refs();
111*3ba7c9e2Sbostic }
112*3ba7c9e2Sbostic 
113*3ba7c9e2Sbostic void
rowvalueize(arg)114*3ba7c9e2Sbostic rowvalueize(arg)
115*3ba7c9e2Sbostic register int arg;
116*3ba7c9e2Sbostic {
117*3ba7c9e2Sbostic     valueize_area(currow, 0, currow + arg - 1, maxcol);
118*3ba7c9e2Sbostic }
119*3ba7c9e2Sbostic 
120*3ba7c9e2Sbostic void
colvalueize(arg)121*3ba7c9e2Sbostic colvalueize(arg)
122*3ba7c9e2Sbostic register int arg;
123*3ba7c9e2Sbostic {
124*3ba7c9e2Sbostic     valueize_area(0, curcol, maxrow, curcol + arg - 1);
125*3ba7c9e2Sbostic }
126*3ba7c9e2Sbostic 
127*3ba7c9e2Sbostic void
erase_area(sr,sc,er,ec)128*3ba7c9e2Sbostic erase_area(sr, sc, er, ec)
129*3ba7c9e2Sbostic int sr, sc, er, ec;
130*3ba7c9e2Sbostic {
131*3ba7c9e2Sbostic     register int r, c;
132*3ba7c9e2Sbostic     register struct ent **pp;
133*3ba7c9e2Sbostic 
134*3ba7c9e2Sbostic     if (sr > er) {
135*3ba7c9e2Sbostic 	r = sr; sr = er; er= r;
136*3ba7c9e2Sbostic     }
137*3ba7c9e2Sbostic 
138*3ba7c9e2Sbostic     if (sc > ec) {
139*3ba7c9e2Sbostic 	c = sc; sc = ec; ec= c;
140*3ba7c9e2Sbostic     }
141*3ba7c9e2Sbostic 
142*3ba7c9e2Sbostic     if (sr < 0)
143*3ba7c9e2Sbostic 	sr = 0;
144*3ba7c9e2Sbostic     if (sc < 0)
145*3ba7c9e2Sbostic 	sc = 0;
146*3ba7c9e2Sbostic     checkbounds(&er, &ec);
147*3ba7c9e2Sbostic 
148*3ba7c9e2Sbostic     for (r = sr; r <= er; r++) {
149*3ba7c9e2Sbostic 	for (c = sc; c <= ec; c++) {
150*3ba7c9e2Sbostic 	    pp = ATBL(tbl, r, c);
151*3ba7c9e2Sbostic 	    if (*pp) {
152*3ba7c9e2Sbostic 		free_ent(*pp);
153*3ba7c9e2Sbostic 		*pp = (struct ent *)0;
154*3ba7c9e2Sbostic 	    }
155*3ba7c9e2Sbostic 	}
156*3ba7c9e2Sbostic     }
157*3ba7c9e2Sbostic }
158*3ba7c9e2Sbostic 
159*3ba7c9e2Sbostic void
valueize_area(sr,sc,er,ec)160*3ba7c9e2Sbostic valueize_area(sr, sc, er, ec)
161*3ba7c9e2Sbostic int sr, sc, er, ec;
162*3ba7c9e2Sbostic {
163*3ba7c9e2Sbostic     register int r, c;
164*3ba7c9e2Sbostic     register struct ent *p;
165*3ba7c9e2Sbostic 
166*3ba7c9e2Sbostic     if (sr > er) {
167*3ba7c9e2Sbostic 	r = sr; sr = er; er= r;
168*3ba7c9e2Sbostic     }
169*3ba7c9e2Sbostic 
170*3ba7c9e2Sbostic     if (sc > ec) {
171*3ba7c9e2Sbostic 	c = sc; sc = ec; ec= c;
172*3ba7c9e2Sbostic     }
173*3ba7c9e2Sbostic 
174*3ba7c9e2Sbostic     if (sr < 0)
175*3ba7c9e2Sbostic 	sr = 0;
176*3ba7c9e2Sbostic     if (sc < 0)
177*3ba7c9e2Sbostic 	sc = 0;
178*3ba7c9e2Sbostic     checkbounds(&er, &ec);
179*3ba7c9e2Sbostic 
180*3ba7c9e2Sbostic     for (r = sr; r <= er; r++) {
181*3ba7c9e2Sbostic 	for (c = sc; c <= ec; c++) {
182*3ba7c9e2Sbostic 	    p = *ATBL(tbl, r, c);
183*3ba7c9e2Sbostic 	    if (p && p->expr) {
184*3ba7c9e2Sbostic 		efree(p, p->expr);
185*3ba7c9e2Sbostic 		p->expr = (struct enode *)0;
186*3ba7c9e2Sbostic 		p->flags &= ~is_strexpr;
187*3ba7c9e2Sbostic 	    }
188*3ba7c9e2Sbostic 	}
189*3ba7c9e2Sbostic     }
190*3ba7c9e2Sbostic 
191*3ba7c9e2Sbostic }
192*3ba7c9e2Sbostic 
193*3ba7c9e2Sbostic void
pullcells(to_insert)194*3ba7c9e2Sbostic pullcells(to_insert)
195*3ba7c9e2Sbostic int to_insert;
196*3ba7c9e2Sbostic {
197*3ba7c9e2Sbostic     register struct ent *p, *n;
198*3ba7c9e2Sbostic     register int deltar, deltac;
199*3ba7c9e2Sbostic     int minrow, mincol;
200*3ba7c9e2Sbostic     int mxrow, mxcol;
201*3ba7c9e2Sbostic     int numrows, numcols;
202*3ba7c9e2Sbostic 
203*3ba7c9e2Sbostic     if (! to_fix)
204*3ba7c9e2Sbostic     {
205*3ba7c9e2Sbostic 	error ("No data to pull");
206*3ba7c9e2Sbostic 	return;
207*3ba7c9e2Sbostic     }
208*3ba7c9e2Sbostic 
209*3ba7c9e2Sbostic     minrow = maxrows;
210*3ba7c9e2Sbostic     mincol = maxcols;
211*3ba7c9e2Sbostic     mxrow = 0;
212*3ba7c9e2Sbostic     mxcol = 0;
213*3ba7c9e2Sbostic 
214*3ba7c9e2Sbostic     for (p = to_fix; p; p = p->next) {
215*3ba7c9e2Sbostic 	if (p->row < minrow)
216*3ba7c9e2Sbostic 	    minrow = p->row;
217*3ba7c9e2Sbostic 	if (p->row > mxrow)
218*3ba7c9e2Sbostic 	    mxrow = p->row;
219*3ba7c9e2Sbostic 	if (p->col < mincol)
220*3ba7c9e2Sbostic 	    mincol = p->col;
221*3ba7c9e2Sbostic 	if (p->col > mxcol)
222*3ba7c9e2Sbostic 	    mxcol = p->col;
223*3ba7c9e2Sbostic     }
224*3ba7c9e2Sbostic 
225*3ba7c9e2Sbostic     numrows = mxrow - minrow + 1;
226*3ba7c9e2Sbostic     numcols = mxcol - mincol + 1;
227*3ba7c9e2Sbostic     deltar = currow - minrow;
228*3ba7c9e2Sbostic     deltac = curcol - mincol;
229*3ba7c9e2Sbostic 
230*3ba7c9e2Sbostic     if (to_insert == 'r') {
231*3ba7c9e2Sbostic 	insertrow(numrows);
232*3ba7c9e2Sbostic 	deltac = 0;
233*3ba7c9e2Sbostic     } else if (to_insert == 'c') {
234*3ba7c9e2Sbostic 	opencol(curcol, numcols);
235*3ba7c9e2Sbostic 	deltar = 0;
236*3ba7c9e2Sbostic     }
237*3ba7c9e2Sbostic 
238*3ba7c9e2Sbostic     FullUpdate++;
239*3ba7c9e2Sbostic     modflg++;
240*3ba7c9e2Sbostic 
241*3ba7c9e2Sbostic     for (p = to_fix; p; p = p->next) {
242*3ba7c9e2Sbostic 	n = lookat (p->row + deltar, p->col + deltac);
243*3ba7c9e2Sbostic 	(void) clearent(n);
244*3ba7c9e2Sbostic 	copyent( n, p, deltar, deltac);
245*3ba7c9e2Sbostic 	n -> flags = p -> flags & ~is_deleted;
246*3ba7c9e2Sbostic     }
247*3ba7c9e2Sbostic }
248*3ba7c9e2Sbostic 
249*3ba7c9e2Sbostic void
colshow_op()250*3ba7c9e2Sbostic colshow_op()
251*3ba7c9e2Sbostic {
252*3ba7c9e2Sbostic     register int i,j;
253*3ba7c9e2Sbostic     for (i=0; i<maxcols; i++)
254*3ba7c9e2Sbostic 	if (col_hidden[i])
255*3ba7c9e2Sbostic 	    break;
256*3ba7c9e2Sbostic     for(j=i; j<maxcols; j++)
257*3ba7c9e2Sbostic 	if (!col_hidden[j])
258*3ba7c9e2Sbostic 	    break;
259*3ba7c9e2Sbostic     j--;
260*3ba7c9e2Sbostic     if (i>=maxcols)
261*3ba7c9e2Sbostic 	error ("No hidden columns to show");
262*3ba7c9e2Sbostic     else {
263*3ba7c9e2Sbostic 	(void) sprintf(line,"show %s:", coltoa(i));
264*3ba7c9e2Sbostic 	(void) sprintf(line + strlen(line),"%s",coltoa(j));
265*3ba7c9e2Sbostic 	linelim = strlen (line);
266*3ba7c9e2Sbostic     }
267*3ba7c9e2Sbostic }
268*3ba7c9e2Sbostic 
269*3ba7c9e2Sbostic void
rowshow_op()270*3ba7c9e2Sbostic rowshow_op()
271*3ba7c9e2Sbostic {
272*3ba7c9e2Sbostic     register int i,j;
273*3ba7c9e2Sbostic     for (i=0; i<maxrows; i++)
274*3ba7c9e2Sbostic 	if (row_hidden[i])
275*3ba7c9e2Sbostic 	    break;
276*3ba7c9e2Sbostic     for(j=i; j<maxrows; j++)
277*3ba7c9e2Sbostic 	if (!row_hidden[j]) {
278*3ba7c9e2Sbostic 	    break;
279*3ba7c9e2Sbostic 	}
280*3ba7c9e2Sbostic     j--;
281*3ba7c9e2Sbostic 
282*3ba7c9e2Sbostic     if (i>=maxrows)
283*3ba7c9e2Sbostic 	error ("No hidden rows to show");
284*3ba7c9e2Sbostic     else {
285*3ba7c9e2Sbostic 	(void) sprintf(line,"show %d:%d", i, j);
286*3ba7c9e2Sbostic         linelim = strlen (line);
287*3ba7c9e2Sbostic     }
288*3ba7c9e2Sbostic }
289*3ba7c9e2Sbostic 
290*3ba7c9e2Sbostic /*
291*3ba7c9e2Sbostic  * Given a row/column command letter, emit a small menu, then read a qualifier
292*3ba7c9e2Sbostic  * character for a row/column command and convert it to 'r' (row), 'c'
293*3ba7c9e2Sbostic  * (column), or 0 (unknown).  If ch is 'p', an extra qualifier 'm' is allowed.
294*3ba7c9e2Sbostic  */
295*3ba7c9e2Sbostic 
296*3ba7c9e2Sbostic int
get_rcqual(ch)297*3ba7c9e2Sbostic get_rcqual (ch)
298*3ba7c9e2Sbostic     int ch;
299*3ba7c9e2Sbostic {
300*3ba7c9e2Sbostic     error ("%sow/column:  r: row  c: column%s",
301*3ba7c9e2Sbostic 
302*3ba7c9e2Sbostic 	    (ch == 'i') ? "Insert r" :
303*3ba7c9e2Sbostic 	    (ch == 'a') ? "Append r" :
304*3ba7c9e2Sbostic 	    (ch == 'd') ? "Delete r" :
305*3ba7c9e2Sbostic 	    (ch == 'p') ? "Pull r" :
306*3ba7c9e2Sbostic 	    (ch == 'v') ? "Values r" :
307*3ba7c9e2Sbostic 	    (ch == 'z') ? "Zap r" :
308*3ba7c9e2Sbostic 	    (ch == 's') ? "Show r" : "R",
309*3ba7c9e2Sbostic 
310*3ba7c9e2Sbostic 	    (ch == 'p') ? "  m: merge" : "");
311*3ba7c9e2Sbostic 
312*3ba7c9e2Sbostic     (void) refresh();
313*3ba7c9e2Sbostic 
314*3ba7c9e2Sbostic     switch (nmgetch())
315*3ba7c9e2Sbostic     {
316*3ba7c9e2Sbostic 	case 'r':
317*3ba7c9e2Sbostic 	case 'l':
318*3ba7c9e2Sbostic 	case 'h':
319*3ba7c9e2Sbostic 	case ctl('f'):
320*3ba7c9e2Sbostic 	case ctl('b'):	return ('r');
321*3ba7c9e2Sbostic 
322*3ba7c9e2Sbostic 	case 'c':
323*3ba7c9e2Sbostic 	case 'j':
324*3ba7c9e2Sbostic 	case 'k':
325*3ba7c9e2Sbostic 	case ctl('p'):
326*3ba7c9e2Sbostic 	case ctl('n'):	return ('c');
327*3ba7c9e2Sbostic 
328*3ba7c9e2Sbostic 	case 'm':	return ((ch == 'p') ? 'm' : 0);
329*3ba7c9e2Sbostic 
330*3ba7c9e2Sbostic 	case ESC:
331*3ba7c9e2Sbostic 	case ctl('g'):	return (ESC);
332*3ba7c9e2Sbostic 
333*3ba7c9e2Sbostic 	default:	return (0);
334*3ba7c9e2Sbostic     }
335*3ba7c9e2Sbostic     /*NOTREACHED*/
336*3ba7c9e2Sbostic }
337*3ba7c9e2Sbostic 
338*3ba7c9e2Sbostic void
openrow(rs)339*3ba7c9e2Sbostic openrow (rs)
340*3ba7c9e2Sbostic int	rs;
341*3ba7c9e2Sbostic {
342*3ba7c9e2Sbostic     register	r, c;
343*3ba7c9e2Sbostic     struct ent	**tmprow, **pp;
344*3ba7c9e2Sbostic 
345*3ba7c9e2Sbostic     if (rs > maxrow) maxrow = rs;
346*3ba7c9e2Sbostic     if (maxrow >= maxrows - 1 || rs > maxrows - 1) {
347*3ba7c9e2Sbostic 	if (!growtbl(GROWROW, rs, 0))
348*3ba7c9e2Sbostic 		return;
349*3ba7c9e2Sbostic     }
350*3ba7c9e2Sbostic 	/*
351*3ba7c9e2Sbostic 	 * save the last active row+1, shift the rows downward, put the last
352*3ba7c9e2Sbostic 	 * row in place of the first
353*3ba7c9e2Sbostic 	 */
354*3ba7c9e2Sbostic     tmprow = tbl[++maxrow];
355*3ba7c9e2Sbostic     for (r = maxrow; r > rs; r--) {
356*3ba7c9e2Sbostic 	row_hidden[r] = row_hidden[r-1];
357*3ba7c9e2Sbostic 	tbl[r] = tbl[r-1];
358*3ba7c9e2Sbostic 	pp = ATBL(tbl, r, 0);
359*3ba7c9e2Sbostic 	for (c = 0; c < maxcols; c++, pp++)
360*3ba7c9e2Sbostic 		if (*pp)
361*3ba7c9e2Sbostic 			(*pp)->row = r;
362*3ba7c9e2Sbostic     }
363*3ba7c9e2Sbostic     tbl[r] = tmprow;	/* the last row was never used.... */
364*3ba7c9e2Sbostic     FullUpdate++;
365*3ba7c9e2Sbostic     modflg++;
366*3ba7c9e2Sbostic }
367*3ba7c9e2Sbostic 
368*3ba7c9e2Sbostic void
closerow(r)369*3ba7c9e2Sbostic closerow (r)
370*3ba7c9e2Sbostic register r;
371*3ba7c9e2Sbostic {
372*3ba7c9e2Sbostic     register struct ent **pp;
373*3ba7c9e2Sbostic     register c;
374*3ba7c9e2Sbostic     struct ent	**tmprow;
375*3ba7c9e2Sbostic 
376*3ba7c9e2Sbostic     if (r > maxrow) return;
377*3ba7c9e2Sbostic 
378*3ba7c9e2Sbostic     /* save the row and empty it out */
379*3ba7c9e2Sbostic     tmprow = tbl[r];
380*3ba7c9e2Sbostic     pp = ATBL(tbl, r, 0);
381*3ba7c9e2Sbostic     for (c=maxcol+1; --c>=0; pp++) {
382*3ba7c9e2Sbostic 	if (*pp)
383*3ba7c9e2Sbostic 	{	free_ent(*pp);
384*3ba7c9e2Sbostic 		*pp = (struct ent *)0;
385*3ba7c9e2Sbostic 	}
386*3ba7c9e2Sbostic     }
387*3ba7c9e2Sbostic 
388*3ba7c9e2Sbostic     /* move the rows, put the deleted row at the end */
389*3ba7c9e2Sbostic     for (; r < maxrows - 1; r++) {
390*3ba7c9e2Sbostic 	row_hidden[r] = row_hidden[r+1];
391*3ba7c9e2Sbostic 	tbl[r] = tbl[r+1];
392*3ba7c9e2Sbostic 	pp = ATBL(tbl, r, 0);
393*3ba7c9e2Sbostic 	for (c = 0; c < maxcols; c++, pp++)
394*3ba7c9e2Sbostic 		if (*pp)
395*3ba7c9e2Sbostic 			(*pp)->row = r;
396*3ba7c9e2Sbostic     }
397*3ba7c9e2Sbostic     tbl[r] = tmprow;
398*3ba7c9e2Sbostic 
399*3ba7c9e2Sbostic     maxrow--;
400*3ba7c9e2Sbostic     FullUpdate++;
401*3ba7c9e2Sbostic     modflg++;
402*3ba7c9e2Sbostic }
403*3ba7c9e2Sbostic 
404*3ba7c9e2Sbostic void
opencol(cs,numcol)405*3ba7c9e2Sbostic opencol (cs, numcol)
406*3ba7c9e2Sbostic int	cs;
407*3ba7c9e2Sbostic int	numcol;
408*3ba7c9e2Sbostic {
409*3ba7c9e2Sbostic     register r;
410*3ba7c9e2Sbostic     register struct ent **pp;
411*3ba7c9e2Sbostic     register c;
412*3ba7c9e2Sbostic     register lim = maxcol-cs+1;
413*3ba7c9e2Sbostic     int i;
414*3ba7c9e2Sbostic 
415*3ba7c9e2Sbostic     if (cs > maxcol)
416*3ba7c9e2Sbostic 	maxcol = cs;
417*3ba7c9e2Sbostic     maxcol += numcol;
418*3ba7c9e2Sbostic 
419*3ba7c9e2Sbostic     if ((maxcol >= maxcols - 1) && !growtbl(GROWCOL, 0, maxcol))
420*3ba7c9e2Sbostic 		return;
421*3ba7c9e2Sbostic 
422*3ba7c9e2Sbostic     for (i = maxcol; i > cs; i--) {
423*3ba7c9e2Sbostic 	fwidth[i] = fwidth[i-numcol];
424*3ba7c9e2Sbostic 	precision[i] = precision[i-numcol];
425*3ba7c9e2Sbostic 	col_hidden[i] = col_hidden[i-numcol];
426*3ba7c9e2Sbostic     }
427*3ba7c9e2Sbostic     for (c = cs; c - cs < numcol; c++)
428*3ba7c9e2Sbostic     {	fwidth[c] = DEFWIDTH;
429*3ba7c9e2Sbostic 	precision[c] =  DEFPREC;
430*3ba7c9e2Sbostic     }
431*3ba7c9e2Sbostic 
432*3ba7c9e2Sbostic     for (r=0; r<=maxrow; r++) {
433*3ba7c9e2Sbostic 	pp = ATBL(tbl, r, maxcol);
434*3ba7c9e2Sbostic 	for (c=lim; --c>=0; pp--)
435*3ba7c9e2Sbostic 	    if (pp[0] = pp[-numcol])
436*3ba7c9e2Sbostic 		pp[0]->col += numcol;
437*3ba7c9e2Sbostic 
438*3ba7c9e2Sbostic 	pp = ATBL(tbl, r, cs);
439*3ba7c9e2Sbostic 	for (c = cs; c - cs < numcol; c++, pp++)
440*3ba7c9e2Sbostic 		*pp = (struct ent *)0;
441*3ba7c9e2Sbostic     }
442*3ba7c9e2Sbostic     FullUpdate++;
443*3ba7c9e2Sbostic     modflg++;
444*3ba7c9e2Sbostic }
445*3ba7c9e2Sbostic 
446*3ba7c9e2Sbostic void
closecol(cs,numcol)447*3ba7c9e2Sbostic closecol (cs, numcol)
448*3ba7c9e2Sbostic int cs;
449*3ba7c9e2Sbostic int	numcol;
450*3ba7c9e2Sbostic {
451*3ba7c9e2Sbostic     register r;
452*3ba7c9e2Sbostic     register struct ent **pp;
453*3ba7c9e2Sbostic     register struct ent *q;
454*3ba7c9e2Sbostic     register c;
455*3ba7c9e2Sbostic     register lim = maxcol-cs;
456*3ba7c9e2Sbostic     int i;
457*3ba7c9e2Sbostic     char buf[50];
458*3ba7c9e2Sbostic 
459*3ba7c9e2Sbostic     if (lim - numcol < -1)
460*3ba7c9e2Sbostic     {	sprintf(buf, "Can't delete %d column%s %d columns left", numcol,
461*3ba7c9e2Sbostic 			(numcol > 1 ? "s," : ","), lim+1);
462*3ba7c9e2Sbostic 	error(buf);
463*3ba7c9e2Sbostic 	return;
464*3ba7c9e2Sbostic     }
465*3ba7c9e2Sbostic     flush_saved();
466*3ba7c9e2Sbostic     erase_area(0, curcol, maxrow, curcol + numcol - 1);
467*3ba7c9e2Sbostic     sync_refs();
468*3ba7c9e2Sbostic 
469*3ba7c9e2Sbostic     /* clear then copy the block left */
470*3ba7c9e2Sbostic     lim = maxcols - numcol - 1;
471*3ba7c9e2Sbostic     for (r=0; r<=maxrow; r++) {
472*3ba7c9e2Sbostic 	for (c = cs; c - cs < numcol; c++)
473*3ba7c9e2Sbostic 		if (q = *ATBL(tbl, r, c))
474*3ba7c9e2Sbostic 			free_ent(q);
475*3ba7c9e2Sbostic 
476*3ba7c9e2Sbostic 	pp = ATBL(tbl, r, cs);
477*3ba7c9e2Sbostic 	for (c=cs; c <= lim; c++, pp++)
478*3ba7c9e2Sbostic 	{   if (c > lim)
479*3ba7c9e2Sbostic 		*pp = (struct ent *)0;
480*3ba7c9e2Sbostic 	    else
481*3ba7c9e2Sbostic 	    if (pp[0] = pp[numcol])
482*3ba7c9e2Sbostic 		pp[0]->col -= numcol;
483*3ba7c9e2Sbostic 	}
484*3ba7c9e2Sbostic 
485*3ba7c9e2Sbostic 	c = numcol;
486*3ba7c9e2Sbostic 	for (; --c >= 0; pp++)
487*3ba7c9e2Sbostic 		*pp = (struct ent *)0;
488*3ba7c9e2Sbostic     }
489*3ba7c9e2Sbostic 
490*3ba7c9e2Sbostic     for (i = cs; i < maxcols - numcol - 1; i++) {
491*3ba7c9e2Sbostic 	fwidth[i] = fwidth[i+numcol];
492*3ba7c9e2Sbostic 	precision[i] = precision[i+numcol];
493*3ba7c9e2Sbostic 	col_hidden[i] = col_hidden[i+numcol];
494*3ba7c9e2Sbostic     }
495*3ba7c9e2Sbostic     for (; i < maxcols - 1; i++) {
496*3ba7c9e2Sbostic 	fwidth[i] = DEFWIDTH;
497*3ba7c9e2Sbostic 	precision[i] = DEFPREC;
498*3ba7c9e2Sbostic 	col_hidden[i] = 0;
499*3ba7c9e2Sbostic     }
500*3ba7c9e2Sbostic 
501*3ba7c9e2Sbostic     maxcol -= numcol;
502*3ba7c9e2Sbostic     FullUpdate++;
503*3ba7c9e2Sbostic     modflg++;
504*3ba7c9e2Sbostic }
505*3ba7c9e2Sbostic 
506*3ba7c9e2Sbostic void
doend(rowinc,colinc)507*3ba7c9e2Sbostic doend(rowinc, colinc)
508*3ba7c9e2Sbostic int rowinc, colinc;
509*3ba7c9e2Sbostic {
510*3ba7c9e2Sbostic     register struct ent *p;
511*3ba7c9e2Sbostic     int r, c;
512*3ba7c9e2Sbostic 
513*3ba7c9e2Sbostic     if (VALID_CELL(p, currow, curcol)) {
514*3ba7c9e2Sbostic 	r = currow + rowinc;
515*3ba7c9e2Sbostic 	c = curcol + colinc;
516*3ba7c9e2Sbostic 	if (r >= 0 && r < maxrows &&
517*3ba7c9e2Sbostic 	    c >= 0 && c < maxcols &&
518*3ba7c9e2Sbostic 	    !VALID_CELL(p, r, c)) {
519*3ba7c9e2Sbostic 		currow = r;
520*3ba7c9e2Sbostic 		curcol = c;
521*3ba7c9e2Sbostic 	}
522*3ba7c9e2Sbostic     }
523*3ba7c9e2Sbostic 
524*3ba7c9e2Sbostic     if (!VALID_CELL(p, currow, curcol)) {
525*3ba7c9e2Sbostic         switch (rowinc) {
526*3ba7c9e2Sbostic         case -1:
527*3ba7c9e2Sbostic 	    while (!VALID_CELL(p, currow, curcol) && currow > 0)
528*3ba7c9e2Sbostic 		currow--;
529*3ba7c9e2Sbostic 	    break;
530*3ba7c9e2Sbostic         case  1:
531*3ba7c9e2Sbostic 	    while (!VALID_CELL(p, currow, curcol) && currow < maxrows-1)
532*3ba7c9e2Sbostic 		currow++;
533*3ba7c9e2Sbostic 	    break;
534*3ba7c9e2Sbostic         case  0:
535*3ba7c9e2Sbostic             switch (colinc) {
536*3ba7c9e2Sbostic  	    case -1:
537*3ba7c9e2Sbostic 	        while (!VALID_CELL(p, currow, curcol) && curcol > 0)
538*3ba7c9e2Sbostic 		    curcol--;
539*3ba7c9e2Sbostic 	        break;
540*3ba7c9e2Sbostic  	    case  1:
541*3ba7c9e2Sbostic 	        while (!VALID_CELL(p, currow, curcol) && curcol < maxcols-1)
542*3ba7c9e2Sbostic 		    curcol++;
543*3ba7c9e2Sbostic 	        break;
544*3ba7c9e2Sbostic 	    }
545*3ba7c9e2Sbostic             break;
546*3ba7c9e2Sbostic         }
547*3ba7c9e2Sbostic 
548*3ba7c9e2Sbostic 	error ("");	/* clear line */
549*3ba7c9e2Sbostic 	return;
550*3ba7c9e2Sbostic     }
551*3ba7c9e2Sbostic 
552*3ba7c9e2Sbostic     switch (rowinc) {
553*3ba7c9e2Sbostic     case -1:
554*3ba7c9e2Sbostic 	while (VALID_CELL(p, currow, curcol) && currow > 0)
555*3ba7c9e2Sbostic 	    currow--;
556*3ba7c9e2Sbostic 	break;
557*3ba7c9e2Sbostic     case  1:
558*3ba7c9e2Sbostic 	while (VALID_CELL(p, currow, curcol) && currow < maxrows-1)
559*3ba7c9e2Sbostic 	    currow++;
560*3ba7c9e2Sbostic 	break;
561*3ba7c9e2Sbostic     case  0:
562*3ba7c9e2Sbostic 	switch (colinc) {
563*3ba7c9e2Sbostic 	case -1:
564*3ba7c9e2Sbostic 	    while (VALID_CELL(p, currow, curcol) && curcol > 0)
565*3ba7c9e2Sbostic 		curcol--;
566*3ba7c9e2Sbostic 	    break;
567*3ba7c9e2Sbostic 	case  1:
568*3ba7c9e2Sbostic 	    while (VALID_CELL(p, currow, curcol) && curcol < maxcols-1)
569*3ba7c9e2Sbostic 		curcol++;
570*3ba7c9e2Sbostic 	    break;
571*3ba7c9e2Sbostic 	}
572*3ba7c9e2Sbostic 	break;
573*3ba7c9e2Sbostic     }
574*3ba7c9e2Sbostic     if (!VALID_CELL(p, currow, curcol)) {
575*3ba7c9e2Sbostic         currow -= rowinc;
576*3ba7c9e2Sbostic         curcol -= colinc;
577*3ba7c9e2Sbostic     }
578*3ba7c9e2Sbostic }
579*3ba7c9e2Sbostic 
580*3ba7c9e2Sbostic void
doformat(c1,c2,w,p)581*3ba7c9e2Sbostic doformat(c1,c2,w,p)
582*3ba7c9e2Sbostic int c1,c2,w,p;
583*3ba7c9e2Sbostic {
584*3ba7c9e2Sbostic     register int i;
585*3ba7c9e2Sbostic 
586*3ba7c9e2Sbostic     if (w > COLS - RESCOL - 2) {
587*3ba7c9e2Sbostic 	error("Format too large - Maximum = %d", COLS - RESCOL - 2);
588*3ba7c9e2Sbostic 	w = COLS-RESCOL-2;
589*3ba7c9e2Sbostic     }
590*3ba7c9e2Sbostic 
591*3ba7c9e2Sbostic     if (p > w) {
592*3ba7c9e2Sbostic 	error("Precision too large");
593*3ba7c9e2Sbostic 	p = w;
594*3ba7c9e2Sbostic     }
595*3ba7c9e2Sbostic 
596*3ba7c9e2Sbostic     for(i = c1; i<=c2; i++)
597*3ba7c9e2Sbostic 	fwidth[i] = w, precision[i] = p;
598*3ba7c9e2Sbostic 
599*3ba7c9e2Sbostic     FullUpdate++;
600*3ba7c9e2Sbostic     modflg++;
601*3ba7c9e2Sbostic }
602*3ba7c9e2Sbostic 
603*3ba7c9e2Sbostic void
print_options(f)604*3ba7c9e2Sbostic print_options(f)
605*3ba7c9e2Sbostic FILE *f;
606*3ba7c9e2Sbostic {
607*3ba7c9e2Sbostic     if(
608*3ba7c9e2Sbostic        autocalc &&
609*3ba7c9e2Sbostic        propagation == 10 &&
610*3ba7c9e2Sbostic        calc_order == BYROWS &&
611*3ba7c9e2Sbostic        !numeric &&
612*3ba7c9e2Sbostic        prescale == 1.0 &&
613*3ba7c9e2Sbostic        !extfunc &&
614*3ba7c9e2Sbostic        showcell &&
615*3ba7c9e2Sbostic        showtop &&
616*3ba7c9e2Sbostic        tbl_style == 0
617*3ba7c9e2Sbostic       )
618*3ba7c9e2Sbostic 		return;		/* No reason to do this */
619*3ba7c9e2Sbostic 
620*3ba7c9e2Sbostic     (void) fprintf(f, "set");
621*3ba7c9e2Sbostic     if(!autocalc)
622*3ba7c9e2Sbostic 	(void) fprintf(f," !autocalc");
623*3ba7c9e2Sbostic     if(propagation != 10)
624*3ba7c9e2Sbostic 	(void) fprintf(f, " iterations = %d", propagation);
625*3ba7c9e2Sbostic     if(calc_order != BYROWS )
626*3ba7c9e2Sbostic 	(void) fprintf(f, " bycols");
627*3ba7c9e2Sbostic     if (numeric)
628*3ba7c9e2Sbostic 	(void) fprintf(f, " numeric");
629*3ba7c9e2Sbostic     if (prescale != 1.0)
630*3ba7c9e2Sbostic 	(void) fprintf(f, " prescale");
631*3ba7c9e2Sbostic     if (extfunc)
632*3ba7c9e2Sbostic 	(void) fprintf(f, " extfun");
633*3ba7c9e2Sbostic     if (!showcell)
634*3ba7c9e2Sbostic 	(void) fprintf(f, " !cellcur");
635*3ba7c9e2Sbostic     if (!showtop)
636*3ba7c9e2Sbostic 	(void) fprintf(f, " !toprow");
637*3ba7c9e2Sbostic     if (tbl_style)
638*3ba7c9e2Sbostic 	(void) fprintf(f, " tblstyle = %s", tbl_style == TBL ? "tbl" :
639*3ba7c9e2Sbostic 					tbl_style == LATEX ? "latex" :
640*3ba7c9e2Sbostic 					tbl_style == TEX ? "tex" : "0" );
641*3ba7c9e2Sbostic     (void) fprintf(f, "\n");
642*3ba7c9e2Sbostic }
643*3ba7c9e2Sbostic 
644*3ba7c9e2Sbostic void
printfile(fname,r0,c0,rn,cn)645*3ba7c9e2Sbostic printfile (fname, r0, c0, rn, cn)
646*3ba7c9e2Sbostic char *fname;
647*3ba7c9e2Sbostic int r0, c0, rn, cn;
648*3ba7c9e2Sbostic {
649*3ba7c9e2Sbostic     FILE *f;
650*3ba7c9e2Sbostic     char pline[FBUFLEN];
651*3ba7c9e2Sbostic     int plinelim;
652*3ba7c9e2Sbostic     int pid;
653*3ba7c9e2Sbostic     int fieldlen, nextcol;
654*3ba7c9e2Sbostic     register row, col;
655*3ba7c9e2Sbostic     register struct ent **pp;
656*3ba7c9e2Sbostic 
657*3ba7c9e2Sbostic     if ((strcmp(fname, curfile) == 0) &&
658*3ba7c9e2Sbostic 	!yn_ask("Confirm that you want to destroy the data base: (y,n)"))
659*3ba7c9e2Sbostic 	return;
660*3ba7c9e2Sbostic 
661*3ba7c9e2Sbostic     if ((f = openout(fname, &pid)) == (FILE *)0)
662*3ba7c9e2Sbostic     {	error ("Can't create file \"%s\"", fname);
663*3ba7c9e2Sbostic 	return;
664*3ba7c9e2Sbostic     }
665*3ba7c9e2Sbostic     for (row=r0;row<=rn; row++) {
666*3ba7c9e2Sbostic 	register c = 0;
667*3ba7c9e2Sbostic 
668*3ba7c9e2Sbostic 	if (row_hidden[row])
669*3ba7c9e2Sbostic 	    continue;
670*3ba7c9e2Sbostic 
671*3ba7c9e2Sbostic 	pline[plinelim=0] = '\0';
672*3ba7c9e2Sbostic 	for (pp = ATBL(tbl, row, col=c0); col<=cn;
673*3ba7c9e2Sbostic 	        pp += nextcol-col, col = nextcol, c += fieldlen) {
674*3ba7c9e2Sbostic 
675*3ba7c9e2Sbostic 	    nextcol = col+1;
676*3ba7c9e2Sbostic 	    if (col_hidden[col]) {
677*3ba7c9e2Sbostic 		fieldlen = 0;
678*3ba7c9e2Sbostic 		continue;
679*3ba7c9e2Sbostic 	    }
680*3ba7c9e2Sbostic 
681*3ba7c9e2Sbostic 	    fieldlen = fwidth[col];
682*3ba7c9e2Sbostic 	    if (*pp) {
683*3ba7c9e2Sbostic 		char *s;
684*3ba7c9e2Sbostic 
685*3ba7c9e2Sbostic 		while (plinelim<c) pline[plinelim++] = ' ';
686*3ba7c9e2Sbostic 		plinelim = c;
687*3ba7c9e2Sbostic 		if ((*pp)->flags&is_valid) {
688*3ba7c9e2Sbostic 		    (void)sprintf (pline+plinelim,"%*.*f",fwidth[col],
689*3ba7c9e2Sbostic 		                                precision[col], (*pp)->v);
690*3ba7c9e2Sbostic 		    plinelim += strlen (pline+plinelim);
691*3ba7c9e2Sbostic 		}
692*3ba7c9e2Sbostic 		if (s = (*pp)->label) {
693*3ba7c9e2Sbostic 		    int slen;
694*3ba7c9e2Sbostic 		    char *start, *last;
695*3ba7c9e2Sbostic 		    register char *fp;
696*3ba7c9e2Sbostic 		    struct ent *nc;
697*3ba7c9e2Sbostic 
698*3ba7c9e2Sbostic 		    /* Figure out if the label slops over to a blank field */
699*3ba7c9e2Sbostic 		    slen = strlen(s);
700*3ba7c9e2Sbostic 		    while (slen > fieldlen && nextcol <= cn &&
701*3ba7c9e2Sbostic 			    !((nc = lookat(row,nextcol))->flags & is_valid) &&
702*3ba7c9e2Sbostic 			    !(nc->label)) {
703*3ba7c9e2Sbostic 
704*3ba7c9e2Sbostic 	                if (!col_hidden[nextcol])
705*3ba7c9e2Sbostic 		 	    fieldlen += fwidth[nextcol];
706*3ba7c9e2Sbostic 
707*3ba7c9e2Sbostic 			nextcol++;
708*3ba7c9e2Sbostic 		    }
709*3ba7c9e2Sbostic 		    if (slen > fieldlen)
710*3ba7c9e2Sbostic 			slen = fieldlen;
711*3ba7c9e2Sbostic 
712*3ba7c9e2Sbostic 		    /* Now justify and print */
713*3ba7c9e2Sbostic 		    start = (*pp)->flags & is_leftflush ? pline + c
714*3ba7c9e2Sbostic 					: pline + c + fieldlen - slen;
715*3ba7c9e2Sbostic 		    last = pline + c + fieldlen;
716*3ba7c9e2Sbostic 		    fp = plinelim < c ? pline + plinelim : pline + c;
717*3ba7c9e2Sbostic 		    while (fp < start)
718*3ba7c9e2Sbostic 			*fp++ = ' ';
719*3ba7c9e2Sbostic 		    while (slen--)
720*3ba7c9e2Sbostic 			*fp++ = *s++;
721*3ba7c9e2Sbostic 		    if (!((*pp)->flags & is_valid) || fieldlen != fwidth[col])
722*3ba7c9e2Sbostic 			while(fp < last)
723*3ba7c9e2Sbostic 			    *fp++ = ' ';
724*3ba7c9e2Sbostic 		    if (plinelim < fp - pline)
725*3ba7c9e2Sbostic 			plinelim = fp - pline;
726*3ba7c9e2Sbostic 		}
727*3ba7c9e2Sbostic 	    }
728*3ba7c9e2Sbostic 	}
729*3ba7c9e2Sbostic 	pline[plinelim++] = '\n';
730*3ba7c9e2Sbostic 	pline[plinelim] = '\0';
731*3ba7c9e2Sbostic 	(void) fputs (pline, f);
732*3ba7c9e2Sbostic     }
733*3ba7c9e2Sbostic 
734*3ba7c9e2Sbostic     closeout(f, pid);
735*3ba7c9e2Sbostic }
736*3ba7c9e2Sbostic 
737*3ba7c9e2Sbostic void
tblprintfile(fname,r0,c0,rn,cn)738*3ba7c9e2Sbostic tblprintfile (fname, r0, c0, rn, cn)
739*3ba7c9e2Sbostic char *fname;
740*3ba7c9e2Sbostic int r0, c0, rn, cn;
741*3ba7c9e2Sbostic {
742*3ba7c9e2Sbostic     FILE *f;
743*3ba7c9e2Sbostic     int pid;
744*3ba7c9e2Sbostic     register row, col;
745*3ba7c9e2Sbostic     register struct ent **pp;
746*3ba7c9e2Sbostic     char coldelim = DEFCOLDELIM;
747*3ba7c9e2Sbostic 
748*3ba7c9e2Sbostic     if ((strcmp(fname, curfile) == 0) &&
749*3ba7c9e2Sbostic 	!yn_ask("Confirm that you want to destroy the data base: (y,n)"))
750*3ba7c9e2Sbostic 	    return;
751*3ba7c9e2Sbostic 
752*3ba7c9e2Sbostic     if ((f = openout(fname, &pid)) == (FILE *)0)
753*3ba7c9e2Sbostic     {	error ("Can't create file \"%s\"", fname);
754*3ba7c9e2Sbostic 	return;
755*3ba7c9e2Sbostic     }
756*3ba7c9e2Sbostic 
757*3ba7c9e2Sbostic     if ( tbl_style == TBL ) {
758*3ba7c9e2Sbostic 	fprintf(f,".\\\" ** %s spreadsheet output \n.TS\n",progname);
759*3ba7c9e2Sbostic 	fprintf(f,"tab(%c);\n",coldelim);
760*3ba7c9e2Sbostic 	for (col=c0;col<=cn; col++) fprintf(f," n");
761*3ba7c9e2Sbostic 	fprintf(f, ".\n");
762*3ba7c9e2Sbostic 	}
763*3ba7c9e2Sbostic     else if ( tbl_style == LATEX ) {
764*3ba7c9e2Sbostic 	fprintf(f,"%% ** %s spreadsheet output\n\\begin{tabular}{",progname);
765*3ba7c9e2Sbostic 	for (col=c0;col<=cn; col++) fprintf(f,"c");
766*3ba7c9e2Sbostic 	fprintf(f, "}\n");
767*3ba7c9e2Sbostic 	coldelim = '&';
768*3ba7c9e2Sbostic 	}
769*3ba7c9e2Sbostic     else if ( tbl_style == TEX ) {
770*3ba7c9e2Sbostic 	fprintf(f,"{\t%% ** %s spreadsheet output\n\\settabs %d \\columns\n",
771*3ba7c9e2Sbostic 		progname, cn-c0+1);
772*3ba7c9e2Sbostic 	coldelim = '&';
773*3ba7c9e2Sbostic 	}
774*3ba7c9e2Sbostic 
775*3ba7c9e2Sbostic     for (row=r0; row<=rn; row++) {
776*3ba7c9e2Sbostic 	if ( tbl_style == TEX )
777*3ba7c9e2Sbostic 	    (void) fprintf (f, "\\+");
778*3ba7c9e2Sbostic 
779*3ba7c9e2Sbostic 	for (pp = ATBL(tbl, row, col=c0); col<=cn; col++, pp++) {
780*3ba7c9e2Sbostic 	    if (*pp) {
781*3ba7c9e2Sbostic 		char *s;
782*3ba7c9e2Sbostic 		if ((*pp)->flags&is_valid) {
783*3ba7c9e2Sbostic 		    (void) fprintf (f,"%.*f",precision[col],
784*3ba7c9e2Sbostic 				(*pp)->v);
785*3ba7c9e2Sbostic 		}
786*3ba7c9e2Sbostic 		if (s = (*pp)->label) {
787*3ba7c9e2Sbostic 	            (void) fprintf (f,"%s",s);
788*3ba7c9e2Sbostic 		}
789*3ba7c9e2Sbostic 	    }
790*3ba7c9e2Sbostic 	    if ( col < cn )
791*3ba7c9e2Sbostic 		(void) fprintf(f,"%c",coldelim);
792*3ba7c9e2Sbostic 	}
793*3ba7c9e2Sbostic 	if ( tbl_style == LATEX ) {
794*3ba7c9e2Sbostic 	    if ( row < rn ) (void) fprintf (f, "\\\\");
795*3ba7c9e2Sbostic 	    }
796*3ba7c9e2Sbostic 	else if ( tbl_style == TEX ) {
797*3ba7c9e2Sbostic 	    (void) fprintf (f, "\\cr");
798*3ba7c9e2Sbostic 	    }
799*3ba7c9e2Sbostic 	(void) fprintf (f,"\n");
800*3ba7c9e2Sbostic     }
801*3ba7c9e2Sbostic 
802*3ba7c9e2Sbostic     if ( tbl_style == TBL )
803*3ba7c9e2Sbostic     (void) fprintf (f,".TE\n.\\\" ** end of %s spreadsheet output\n", progname);
804*3ba7c9e2Sbostic     else if ( tbl_style == LATEX )
805*3ba7c9e2Sbostic     (void) fprintf (f,"\\end{tabular}\n%% ** end of %s spreadsheet output\n", progname);
806*3ba7c9e2Sbostic     else if ( tbl_style == TEX )
807*3ba7c9e2Sbostic     (void) fprintf (f,"}\n%% ** end of %s spreadsheet output\n", progname);
808*3ba7c9e2Sbostic 
809*3ba7c9e2Sbostic     closeout(f, pid);
810*3ba7c9e2Sbostic }
811*3ba7c9e2Sbostic 
812*3ba7c9e2Sbostic struct enode *
copye(e,Rdelta,Cdelta)813*3ba7c9e2Sbostic copye (e, Rdelta, Cdelta)
814*3ba7c9e2Sbostic register struct enode *e;
815*3ba7c9e2Sbostic int Rdelta, Cdelta;
816*3ba7c9e2Sbostic {
817*3ba7c9e2Sbostic     register struct enode *ret;
818*3ba7c9e2Sbostic 
819*3ba7c9e2Sbostic     if (e == (struct enode *)0) {
820*3ba7c9e2Sbostic         ret = (struct enode *)0;
821*3ba7c9e2Sbostic     } else if (e->op & REDUCE) {
822*3ba7c9e2Sbostic 	int newrow, newcol;
823*3ba7c9e2Sbostic 	ret = (struct enode *) xmalloc ((unsigned) sizeof (struct enode));
824*3ba7c9e2Sbostic 	ret->op = e->op;
825*3ba7c9e2Sbostic 	newrow=e->e.r.left.vf & FIX_ROW ? e->e.r.left.vp->row :
826*3ba7c9e2Sbostic 					  e->e.r.left.vp->row+Rdelta;
827*3ba7c9e2Sbostic 	newcol=e->e.r.left.vf & FIX_COL ? e->e.r.left.vp->col :
828*3ba7c9e2Sbostic 					  e->e.r.left.vp->col+Cdelta;
829*3ba7c9e2Sbostic 	ret->e.r.left.vp = lookat (newrow, newcol);
830*3ba7c9e2Sbostic 	ret->e.r.left.vf = e->e.r.left.vf;
831*3ba7c9e2Sbostic 	newrow=e->e.r.right.vf & FIX_ROW ? e->e.r.right.vp->row :
832*3ba7c9e2Sbostic 					   e->e.r.right.vp->row+Rdelta;
833*3ba7c9e2Sbostic 	newcol=e->e.r.right.vf & FIX_COL ? e->e.r.right.vp->col :
834*3ba7c9e2Sbostic 					   e->e.r.right.vp->col+Cdelta;
835*3ba7c9e2Sbostic 	ret->e.r.right.vp = lookat (newrow, newcol);
836*3ba7c9e2Sbostic 	ret->e.r.right.vf = e->e.r.right.vf;
837*3ba7c9e2Sbostic     } else {
838*3ba7c9e2Sbostic 	ret = (struct enode *) xmalloc ((unsigned) sizeof (struct enode));
839*3ba7c9e2Sbostic 	ret->op = e->op;
840*3ba7c9e2Sbostic 	switch (ret->op) {
841*3ba7c9e2Sbostic 	case 'v':
842*3ba7c9e2Sbostic 		{
843*3ba7c9e2Sbostic 		    int newrow, newcol;
844*3ba7c9e2Sbostic 		    newrow=e->e.v.vf & FIX_ROW ? e->e.v.vp->row :
845*3ba7c9e2Sbostic 						 e->e.v.vp->row+Rdelta;
846*3ba7c9e2Sbostic 		    newcol=e->e.v.vf & FIX_COL ? e->e.v.vp->col :
847*3ba7c9e2Sbostic 						 e->e.v.vp->col+Cdelta;
848*3ba7c9e2Sbostic 		    ret->e.v.vp = lookat (newrow, newcol);
849*3ba7c9e2Sbostic 		    ret->e.v.vf = e->e.v.vf;
850*3ba7c9e2Sbostic 		    break;
851*3ba7c9e2Sbostic 		}
852*3ba7c9e2Sbostic 	case 'k':
853*3ba7c9e2Sbostic 		ret->e.k = e->e.k;
854*3ba7c9e2Sbostic 		break;
855*3ba7c9e2Sbostic 	case 'f':
856*3ba7c9e2Sbostic 		ret->e.o.right = copye (e->e.o.right,0,0);
857*3ba7c9e2Sbostic 		ret->e.o.left = (struct enode *)0;
858*3ba7c9e2Sbostic  		break;
859*3ba7c9e2Sbostic 	case '$':
860*3ba7c9e2Sbostic 		ret->e.s = xmalloc((unsigned) strlen(e->e.s)+1);
861*3ba7c9e2Sbostic 		(void) strcpy(ret->e.s, e->e.s);
862*3ba7c9e2Sbostic 		break;
863*3ba7c9e2Sbostic 	default:
864*3ba7c9e2Sbostic 		ret->e.o.right = copye (e->e.o.right,Rdelta,Cdelta);
865*3ba7c9e2Sbostic 		ret->e.o.left = copye (e->e.o.left,Rdelta,Cdelta);
866*3ba7c9e2Sbostic 		break;
867*3ba7c9e2Sbostic 	}
868*3ba7c9e2Sbostic     }
869*3ba7c9e2Sbostic     return ret;
870*3ba7c9e2Sbostic }
871*3ba7c9e2Sbostic 
872*3ba7c9e2Sbostic /*
873*3ba7c9e2Sbostic  * sync_refs and syncref are used to remove references to
874*3ba7c9e2Sbostic  * deleted struct ents.  Note that the deleted structure must still
875*3ba7c9e2Sbostic  * be hanging around before the call, but not referenced by an entry
876*3ba7c9e2Sbostic  * in tbl.  Thus the free_ent, fix_ent calls in sc.c
877*3ba7c9e2Sbostic  */
878*3ba7c9e2Sbostic void
sync_refs()879*3ba7c9e2Sbostic sync_refs ()
880*3ba7c9e2Sbostic {
881*3ba7c9e2Sbostic     register i,j;
882*3ba7c9e2Sbostic     register struct ent *p;
883*3ba7c9e2Sbostic     sync_ranges();
884*3ba7c9e2Sbostic     for (i=0; i<=maxrow; i++)
885*3ba7c9e2Sbostic 	for (j=0; j<=maxcol; j++)
886*3ba7c9e2Sbostic 	    if ((p = *ATBL(tbl, i, j)) && p->expr)
887*3ba7c9e2Sbostic 		syncref(p->expr);
888*3ba7c9e2Sbostic }
889*3ba7c9e2Sbostic 
890*3ba7c9e2Sbostic void
syncref(e)891*3ba7c9e2Sbostic syncref(e)
892*3ba7c9e2Sbostic register struct enode *e;
893*3ba7c9e2Sbostic {
894*3ba7c9e2Sbostic     if (e == (struct enode *)0)
895*3ba7c9e2Sbostic 	return;
896*3ba7c9e2Sbostic     else if (e->op & REDUCE) {
897*3ba7c9e2Sbostic  	e->e.r.right.vp = lookat(e->e.r.right.vp->row, e->e.r.right.vp->col);
898*3ba7c9e2Sbostic  	e->e.r.left.vp = lookat(e->e.r.left.vp->row, e->e.r.left.vp->col);
899*3ba7c9e2Sbostic     } else {
900*3ba7c9e2Sbostic 	switch (e->op) {
901*3ba7c9e2Sbostic 	case 'v':
902*3ba7c9e2Sbostic 		e->e.v.vp = lookat(e->e.v.vp->row, e->e.v.vp->col);
903*3ba7c9e2Sbostic 		break;
904*3ba7c9e2Sbostic 	case 'k':
905*3ba7c9e2Sbostic 		break;
906*3ba7c9e2Sbostic 	case '$':
907*3ba7c9e2Sbostic 		break;
908*3ba7c9e2Sbostic 	default:
909*3ba7c9e2Sbostic 		syncref(e->e.o.right);
910*3ba7c9e2Sbostic 		syncref(e->e.o.left);
911*3ba7c9e2Sbostic 		break;
912*3ba7c9e2Sbostic 	}
913*3ba7c9e2Sbostic     }
914*3ba7c9e2Sbostic }
915*3ba7c9e2Sbostic 
916*3ba7c9e2Sbostic void
hiderow(arg)917*3ba7c9e2Sbostic hiderow(arg)
918*3ba7c9e2Sbostic int arg;
919*3ba7c9e2Sbostic {
920*3ba7c9e2Sbostic     register int r1;
921*3ba7c9e2Sbostic     register int r2;
922*3ba7c9e2Sbostic 
923*3ba7c9e2Sbostic     r1 = currow;
924*3ba7c9e2Sbostic     r2 = r1 + arg - 1;
925*3ba7c9e2Sbostic     if (r1 < 0 || r1 > r2) {
926*3ba7c9e2Sbostic 	error ("Invalid range");
927*3ba7c9e2Sbostic 	return;
928*3ba7c9e2Sbostic     }
929*3ba7c9e2Sbostic     if (r2 >= maxrows-1)
930*3ba7c9e2Sbostic     {	if (!growtbl(GROWROW, arg+1, 0))
931*3ba7c9e2Sbostic 	{	error("You can't hide the last row");
932*3ba7c9e2Sbostic 		return;
933*3ba7c9e2Sbostic 	}
934*3ba7c9e2Sbostic     }
935*3ba7c9e2Sbostic     FullUpdate++;
936*3ba7c9e2Sbostic     modflg++;
937*3ba7c9e2Sbostic     while (r1 <= r2)
938*3ba7c9e2Sbostic 	row_hidden[r1++] = 1;
939*3ba7c9e2Sbostic }
940*3ba7c9e2Sbostic 
941*3ba7c9e2Sbostic void
hidecol(arg)942*3ba7c9e2Sbostic hidecol(arg)
943*3ba7c9e2Sbostic int arg;
944*3ba7c9e2Sbostic {
945*3ba7c9e2Sbostic     register int c1;
946*3ba7c9e2Sbostic     register int c2;
947*3ba7c9e2Sbostic 
948*3ba7c9e2Sbostic     c1 = curcol;
949*3ba7c9e2Sbostic     c2 = c1 + arg - 1;
950*3ba7c9e2Sbostic     if (c1 < 0 || c1 > c2) {
951*3ba7c9e2Sbostic 	error ("Invalid range");
952*3ba7c9e2Sbostic 	return;
953*3ba7c9e2Sbostic     }
954*3ba7c9e2Sbostic     if (c2 >= maxcols-1)
955*3ba7c9e2Sbostic     {	if ((arg >= ABSMAXCOLS-1) || !growtbl(GROWCOL, 0, arg+1))
956*3ba7c9e2Sbostic 	{	error("You can't hide the last col");
957*3ba7c9e2Sbostic 		return;
958*3ba7c9e2Sbostic 	}
959*3ba7c9e2Sbostic     }
960*3ba7c9e2Sbostic     FullUpdate++;
961*3ba7c9e2Sbostic     modflg++;
962*3ba7c9e2Sbostic     while (c1 <= c2)
963*3ba7c9e2Sbostic 	col_hidden[c1++] = 1;
964*3ba7c9e2Sbostic }
965*3ba7c9e2Sbostic 
966*3ba7c9e2Sbostic void
showrow(r1,r2)967*3ba7c9e2Sbostic showrow(r1, r2)
968*3ba7c9e2Sbostic int r1, r2;
969*3ba7c9e2Sbostic {
970*3ba7c9e2Sbostic     if (r1 < 0 || r1 > r2) {
971*3ba7c9e2Sbostic 	error ("Invalid range");
972*3ba7c9e2Sbostic 	return;
973*3ba7c9e2Sbostic     }
974*3ba7c9e2Sbostic     if (r2 > maxrows-1) {
975*3ba7c9e2Sbostic 	r2 = maxrows-1;
976*3ba7c9e2Sbostic     }
977*3ba7c9e2Sbostic     FullUpdate++;
978*3ba7c9e2Sbostic     modflg++;
979*3ba7c9e2Sbostic     while (r1 <= r2)
980*3ba7c9e2Sbostic 	row_hidden[r1++] = 0;
981*3ba7c9e2Sbostic }
982*3ba7c9e2Sbostic 
983*3ba7c9e2Sbostic void
showcol(c1,c2)984*3ba7c9e2Sbostic showcol(c1, c2)
985*3ba7c9e2Sbostic int c1, c2;
986*3ba7c9e2Sbostic {
987*3ba7c9e2Sbostic     if (c1 < 0 || c1 > c2) {
988*3ba7c9e2Sbostic 	error ("Invalid range");
989*3ba7c9e2Sbostic 	return;
990*3ba7c9e2Sbostic     }
991*3ba7c9e2Sbostic     if (c2 > maxcols-1) {
992*3ba7c9e2Sbostic 	c2 = maxcols-1;
993*3ba7c9e2Sbostic     }
994*3ba7c9e2Sbostic     FullUpdate++;
995*3ba7c9e2Sbostic     modflg++;
996*3ba7c9e2Sbostic     while (c1 <= c2)
997*3ba7c9e2Sbostic 	col_hidden[c1++] = 0;
998*3ba7c9e2Sbostic }
999*3ba7c9e2Sbostic 
1000*3ba7c9e2Sbostic /* Open the output file, setting up a pipe if needed */
1001*3ba7c9e2Sbostic 
1002*3ba7c9e2Sbostic FILE *
openout(fname,rpid)1003*3ba7c9e2Sbostic openout(fname, rpid)
1004*3ba7c9e2Sbostic char *fname;
1005*3ba7c9e2Sbostic int *rpid;
1006*3ba7c9e2Sbostic {
1007*3ba7c9e2Sbostic     int pipefd[2];
1008*3ba7c9e2Sbostic     int pid;
1009*3ba7c9e2Sbostic     FILE *f;
1010*3ba7c9e2Sbostic     char *efname;
1011*3ba7c9e2Sbostic 
1012*3ba7c9e2Sbostic     while (*fname && (*fname == ' '))  /* Skip leading blanks */
1013*3ba7c9e2Sbostic 	fname++;
1014*3ba7c9e2Sbostic 
1015*3ba7c9e2Sbostic     if (*fname != '|') {		/* Open file if not pipe */
1016*3ba7c9e2Sbostic 	*rpid = 0;
1017*3ba7c9e2Sbostic 
1018*3ba7c9e2Sbostic 	efname = findhome(fname);
1019*3ba7c9e2Sbostic #ifdef DOBACKUPS
1020*3ba7c9e2Sbostic 	if (!backup_file(efname) &&
1021*3ba7c9e2Sbostic 	    (yn_ask("Could not create backup copy, Save anyhow?: (y,n)") != 1))
1022*3ba7c9e2Sbostic 		return(0);
1023*3ba7c9e2Sbostic #endif
1024*3ba7c9e2Sbostic 	return(fopen(efname, "w"));
1025*3ba7c9e2Sbostic     }
1026*3ba7c9e2Sbostic 
1027*3ba7c9e2Sbostic     fname++;				/* Skip | */
1028*3ba7c9e2Sbostic     if ( pipe (pipefd) < 0) {
1029*3ba7c9e2Sbostic 	error("Can't make pipe to child");
1030*3ba7c9e2Sbostic 	*rpid = 0;
1031*3ba7c9e2Sbostic 	return(0);
1032*3ba7c9e2Sbostic     }
1033*3ba7c9e2Sbostic 
1034*3ba7c9e2Sbostic     deraw();
1035*3ba7c9e2Sbostic #ifdef VMS
1036*3ba7c9e2Sbostic     fprintf(stderr, "No son tasks available yet under VMS--sorry\n");
1037*3ba7c9e2Sbostic #else /* VMS */
1038*3ba7c9e2Sbostic 
1039*3ba7c9e2Sbostic     if ((pid=fork()) == 0)			  /* if child  */
1040*3ba7c9e2Sbostic     {
1041*3ba7c9e2Sbostic 	(void) close (0);			  /* close stdin */
1042*3ba7c9e2Sbostic 	(void) close (pipefd[1]);
1043*3ba7c9e2Sbostic 	(void) dup (pipefd[0]);		  /* connect to pipe input */
1044*3ba7c9e2Sbostic 	(void) signal (SIGINT, SIG_DFL);	  /* reset */
1045*3ba7c9e2Sbostic 	(void) execl ("/bin/sh", "sh", "-c", fname, 0);
1046*3ba7c9e2Sbostic 	exit (-127);
1047*3ba7c9e2Sbostic     }
1048*3ba7c9e2Sbostic     else				  /* else parent */
1049*3ba7c9e2Sbostic     {
1050*3ba7c9e2Sbostic 	*rpid = pid;
1051*3ba7c9e2Sbostic 	if ((f = fdopen (pipefd[1], "w")) == (FILE *)0)
1052*3ba7c9e2Sbostic 	{
1053*3ba7c9e2Sbostic 	    (void) kill (pid, -9);
1054*3ba7c9e2Sbostic 	    error ("Can't fdopen output");
1055*3ba7c9e2Sbostic 	    (void) close (pipefd[1]);
1056*3ba7c9e2Sbostic 	    *rpid = 0;
1057*3ba7c9e2Sbostic 	    return(0);
1058*3ba7c9e2Sbostic 	}
1059*3ba7c9e2Sbostic     }
1060*3ba7c9e2Sbostic #endif /* VMS */
1061*3ba7c9e2Sbostic     return(f);
1062*3ba7c9e2Sbostic }
1063*3ba7c9e2Sbostic 
1064*3ba7c9e2Sbostic void
closeout(f,pid)1065*3ba7c9e2Sbostic closeout(f, pid)
1066*3ba7c9e2Sbostic FILE *f;
1067*3ba7c9e2Sbostic int pid;
1068*3ba7c9e2Sbostic {
1069*3ba7c9e2Sbostic     int temp;
1070*3ba7c9e2Sbostic 
1071*3ba7c9e2Sbostic     (void) fclose (f);
1072*3ba7c9e2Sbostic     if (pid) {
1073*3ba7c9e2Sbostic          while (pid != wait(&temp)) /**/;
1074*3ba7c9e2Sbostic 	 (void) printf("Press RETURN to continue ");
1075*3ba7c9e2Sbostic 	 (void) fflush(stdout);
1076*3ba7c9e2Sbostic 	 (void) nmgetch();
1077*3ba7c9e2Sbostic 	 goraw();
1078*3ba7c9e2Sbostic     }
1079*3ba7c9e2Sbostic }
1080*3ba7c9e2Sbostic 
1081*3ba7c9e2Sbostic void
copyent(n,p,dr,dc)1082*3ba7c9e2Sbostic copyent(n,p,dr,dc)
1083*3ba7c9e2Sbostic 	    register struct ent *n, *p;
1084*3ba7c9e2Sbostic 	    int dr, dc;
1085*3ba7c9e2Sbostic {
1086*3ba7c9e2Sbostic     if(!n||!p){error("internal error");return;}
1087*3ba7c9e2Sbostic     n -> v = p -> v;
1088*3ba7c9e2Sbostic     n -> flags = p -> flags;
1089*3ba7c9e2Sbostic     n -> expr = copye (p -> expr, dr, dc);
1090*3ba7c9e2Sbostic     n -> label = (char *)0;
1091*3ba7c9e2Sbostic     if (p -> label) {
1092*3ba7c9e2Sbostic 	n -> label = (char *)
1093*3ba7c9e2Sbostic 		xmalloc  ((unsigned) (strlen (p -> label) + 1));
1094*3ba7c9e2Sbostic 	(void) strcpy (n -> label, p -> label);
1095*3ba7c9e2Sbostic     }
1096*3ba7c9e2Sbostic }
1097*3ba7c9e2Sbostic 
1098*3ba7c9e2Sbostic void
write_fd(f,r0,c0,rn,cn)1099*3ba7c9e2Sbostic write_fd (f, r0, c0, rn, cn)
1100*3ba7c9e2Sbostic register FILE *f;
1101*3ba7c9e2Sbostic int r0, c0, rn, cn;
1102*3ba7c9e2Sbostic {
1103*3ba7c9e2Sbostic     register struct ent **pp;
1104*3ba7c9e2Sbostic     register r, c;
1105*3ba7c9e2Sbostic 
1106*3ba7c9e2Sbostic     (void) fprintf (f, "# This data file was generated by the Spreadsheet ");
1107*3ba7c9e2Sbostic     (void) fprintf (f, "Calculator.\n");
1108*3ba7c9e2Sbostic     (void) fprintf (f, "# You almost certainly shouldn't edit it.\n\n");
1109*3ba7c9e2Sbostic     print_options(f);
1110*3ba7c9e2Sbostic     for (c=0; c<maxcols; c++)
1111*3ba7c9e2Sbostic 	if (fwidth[c] != DEFWIDTH || precision[c] != DEFPREC)
1112*3ba7c9e2Sbostic 	    (void) fprintf (f, "format %s %d %d\n",coltoa(c),fwidth[c],precision[c]);
1113*3ba7c9e2Sbostic     for (c=c0; c<cn; c++) {
1114*3ba7c9e2Sbostic         if (col_hidden[c]) {
1115*3ba7c9e2Sbostic             (void) fprintf(f, "hide %s\n", coltoa(c));
1116*3ba7c9e2Sbostic         }
1117*3ba7c9e2Sbostic     }
1118*3ba7c9e2Sbostic     for (r=r0; r<=rn; r++) {
1119*3ba7c9e2Sbostic 	if (row_hidden[r]) {
1120*3ba7c9e2Sbostic 	    (void) fprintf(f, "hide %d\n", r);
1121*3ba7c9e2Sbostic 	}
1122*3ba7c9e2Sbostic     }
1123*3ba7c9e2Sbostic 
1124*3ba7c9e2Sbostic     write_range(f);
1125*3ba7c9e2Sbostic 
1126*3ba7c9e2Sbostic     if (mdir)
1127*3ba7c9e2Sbostic 	    (void) fprintf(f, "mdir \"%s\"\n", mdir);
1128*3ba7c9e2Sbostic     for (r=r0; r<=rn; r++) {
1129*3ba7c9e2Sbostic 	pp = ATBL(tbl, r, c0);
1130*3ba7c9e2Sbostic 	for (c=c0; c<=cn; c++, pp++)
1131*3ba7c9e2Sbostic 	    if (*pp) {
1132*3ba7c9e2Sbostic 		if ((*pp)->label) {
1133*3ba7c9e2Sbostic 		    edits(r,c);
1134*3ba7c9e2Sbostic 		    (void) fprintf(f, "%s\n",line);
1135*3ba7c9e2Sbostic 		}
1136*3ba7c9e2Sbostic 		if ((*pp)->flags&is_valid) {
1137*3ba7c9e2Sbostic 		    editv (r, c);
1138*3ba7c9e2Sbostic 		    (void) fprintf (f, "%s\n",line);
1139*3ba7c9e2Sbostic 		}
1140*3ba7c9e2Sbostic 	    }
1141*3ba7c9e2Sbostic     }
1142*3ba7c9e2Sbostic }
1143*3ba7c9e2Sbostic 
1144*3ba7c9e2Sbostic int
writefile(fname,r0,c0,rn,cn)1145*3ba7c9e2Sbostic writefile (fname, r0, c0, rn, cn)
1146*3ba7c9e2Sbostic char *fname;
1147*3ba7c9e2Sbostic int r0, c0, rn, cn;
1148*3ba7c9e2Sbostic {
1149*3ba7c9e2Sbostic     register FILE *f;
1150*3ba7c9e2Sbostic     char save[PATHLEN];
1151*3ba7c9e2Sbostic     int pid;
1152*3ba7c9e2Sbostic 
1153*3ba7c9e2Sbostic #ifndef VMS
1154*3ba7c9e2Sbostic     if (Crypt) {
1155*3ba7c9e2Sbostic 	return (cwritefile(fname, r0, c0, rn, cn));
1156*3ba7c9e2Sbostic     }
1157*3ba7c9e2Sbostic #endif /* VMS */
1158*3ba7c9e2Sbostic 
1159*3ba7c9e2Sbostic     if (*fname == '\0') fname = curfile;
1160*3ba7c9e2Sbostic 
1161*3ba7c9e2Sbostic     (void) strcpy(save,fname);
1162*3ba7c9e2Sbostic 
1163*3ba7c9e2Sbostic     if ((f= openout(fname, &pid)) == (FILE *)0)
1164*3ba7c9e2Sbostic     {	error ("Can't create file \"%s\"", fname);
1165*3ba7c9e2Sbostic 	return (-1);
1166*3ba7c9e2Sbostic     }
1167*3ba7c9e2Sbostic 
1168*3ba7c9e2Sbostic     write_fd(f, r0, c0, rn, cn);
1169*3ba7c9e2Sbostic 
1170*3ba7c9e2Sbostic     closeout(f, pid);
1171*3ba7c9e2Sbostic 
1172*3ba7c9e2Sbostic     if (!pid) {
1173*3ba7c9e2Sbostic         (void) strcpy(curfile, save);
1174*3ba7c9e2Sbostic         modflg = 0;
1175*3ba7c9e2Sbostic         error("File \"%s\" written.",curfile);
1176*3ba7c9e2Sbostic     }
1177*3ba7c9e2Sbostic 
1178*3ba7c9e2Sbostic     return (0);
1179*3ba7c9e2Sbostic }
1180*3ba7c9e2Sbostic 
1181*3ba7c9e2Sbostic void
readfile(fname,eraseflg)1182*3ba7c9e2Sbostic readfile (fname,eraseflg)
1183*3ba7c9e2Sbostic char *fname;
1184*3ba7c9e2Sbostic int eraseflg;
1185*3ba7c9e2Sbostic {
1186*3ba7c9e2Sbostic     register FILE *f;
1187*3ba7c9e2Sbostic     char save[PATHLEN];
1188*3ba7c9e2Sbostic 
1189*3ba7c9e2Sbostic     if (*fname == '*' && mdir) {
1190*3ba7c9e2Sbostic        (void) strcpy(save, mdir);
1191*3ba7c9e2Sbostic        *fname = '/';
1192*3ba7c9e2Sbostic        (void) strcat(save, fname);
1193*3ba7c9e2Sbostic     } else {
1194*3ba7c9e2Sbostic         if (*fname == '\0')
1195*3ba7c9e2Sbostic 	    fname = curfile;
1196*3ba7c9e2Sbostic         (void) strcpy(save,fname);
1197*3ba7c9e2Sbostic     }
1198*3ba7c9e2Sbostic 
1199*3ba7c9e2Sbostic #ifndef VMS
1200*3ba7c9e2Sbostic     if (Crypt)  {
1201*3ba7c9e2Sbostic 	creadfile(save, eraseflg);
1202*3ba7c9e2Sbostic 	return;
1203*3ba7c9e2Sbostic     }
1204*3ba7c9e2Sbostic #endif /* VMS */
1205*3ba7c9e2Sbostic 
1206*3ba7c9e2Sbostic     if (eraseflg && strcmp(fname,curfile) && modcheck(" first")) return;
1207*3ba7c9e2Sbostic 
1208*3ba7c9e2Sbostic     if ((f = fopen(findhome(save), "r")) == (FILE *)0)
1209*3ba7c9e2Sbostic     {	error ("Can't read file \"%s\"", save);
1210*3ba7c9e2Sbostic 	return;
1211*3ba7c9e2Sbostic     }
1212*3ba7c9e2Sbostic 
1213*3ba7c9e2Sbostic     if (eraseflg) erasedb ();
1214*3ba7c9e2Sbostic 
1215*3ba7c9e2Sbostic     loading++;
1216*3ba7c9e2Sbostic     while (fgets(line,sizeof line,f)) {
1217*3ba7c9e2Sbostic 	linelim = 0;
1218*3ba7c9e2Sbostic 	if (line[0] != '#') (void) yyparse ();
1219*3ba7c9e2Sbostic     }
1220*3ba7c9e2Sbostic     --loading;
1221*3ba7c9e2Sbostic     (void) fclose (f);
1222*3ba7c9e2Sbostic     linelim = -1;
1223*3ba7c9e2Sbostic     modflg++;
1224*3ba7c9e2Sbostic     if (eraseflg) {
1225*3ba7c9e2Sbostic 	(void) strcpy(curfile,save);
1226*3ba7c9e2Sbostic 	modflg = 0;
1227*3ba7c9e2Sbostic     }
1228*3ba7c9e2Sbostic     EvalAll();
1229*3ba7c9e2Sbostic }
1230*3ba7c9e2Sbostic 
1231*3ba7c9e2Sbostic void
erasedb()1232*3ba7c9e2Sbostic erasedb ()
1233*3ba7c9e2Sbostic {
1234*3ba7c9e2Sbostic     register r, c;
1235*3ba7c9e2Sbostic     for (c = 0; c<=maxcol; c++) {
1236*3ba7c9e2Sbostic 	fwidth[c] = DEFWIDTH;
1237*3ba7c9e2Sbostic 	precision[c] = DEFPREC;
1238*3ba7c9e2Sbostic     }
1239*3ba7c9e2Sbostic 
1240*3ba7c9e2Sbostic     for (r = 0; r<=maxrow; r++) {
1241*3ba7c9e2Sbostic 	register struct ent **pp = ATBL(tbl, r, 0);
1242*3ba7c9e2Sbostic 	for (c=0; c++<=maxcol; pp++)
1243*3ba7c9e2Sbostic 	    if (*pp) {
1244*3ba7c9e2Sbostic 		if ((*pp)->expr) efree (*pp, (*pp) -> expr);
1245*3ba7c9e2Sbostic 		if ((*pp)->label) xfree ((char *)((*pp) -> label));
1246*3ba7c9e2Sbostic 		xfree ((char *)(*pp));
1247*3ba7c9e2Sbostic 		*pp = (struct ent *)0;
1248*3ba7c9e2Sbostic 	    }
1249*3ba7c9e2Sbostic     }
1250*3ba7c9e2Sbostic     maxrow = 0;
1251*3ba7c9e2Sbostic     maxcol = 0;
1252*3ba7c9e2Sbostic     clean_range();
1253*3ba7c9e2Sbostic     FullUpdate++;
1254*3ba7c9e2Sbostic }
1255*3ba7c9e2Sbostic 
1256*3ba7c9e2Sbostic void
backcol(arg)1257*3ba7c9e2Sbostic backcol(arg)
1258*3ba7c9e2Sbostic 	int arg;
1259*3ba7c9e2Sbostic {
1260*3ba7c9e2Sbostic     while (--arg>=0) {
1261*3ba7c9e2Sbostic 	if (curcol)
1262*3ba7c9e2Sbostic 	    curcol--;
1263*3ba7c9e2Sbostic 	else
1264*3ba7c9e2Sbostic 	    {error ("At column A"); break;}
1265*3ba7c9e2Sbostic 	while(col_hidden[curcol] && curcol)
1266*3ba7c9e2Sbostic 	    curcol--;
1267*3ba7c9e2Sbostic     }
1268*3ba7c9e2Sbostic }
1269*3ba7c9e2Sbostic 
1270*3ba7c9e2Sbostic void
forwcol(arg)1271*3ba7c9e2Sbostic forwcol(arg)
1272*3ba7c9e2Sbostic 	int arg;
1273*3ba7c9e2Sbostic {
1274*3ba7c9e2Sbostic     while (--arg>=0) {
1275*3ba7c9e2Sbostic 	if (curcol < maxcols - 1)
1276*3ba7c9e2Sbostic 	    curcol++;
1277*3ba7c9e2Sbostic 	else
1278*3ba7c9e2Sbostic 	if (!growtbl(GROWCOL, 0, arg))	/* get as much as needed */
1279*3ba7c9e2Sbostic 		break;
1280*3ba7c9e2Sbostic 	while(col_hidden[curcol]&&(curcol<maxcols-1))
1281*3ba7c9e2Sbostic 	    curcol++;
1282*3ba7c9e2Sbostic     }
1283*3ba7c9e2Sbostic }
1284*3ba7c9e2Sbostic 
1285*3ba7c9e2Sbostic void
forwrow(arg)1286*3ba7c9e2Sbostic forwrow(arg)
1287*3ba7c9e2Sbostic 	int arg;
1288*3ba7c9e2Sbostic {
1289*3ba7c9e2Sbostic     while (--arg>=0) {
1290*3ba7c9e2Sbostic 	if (currow < maxrows - 1)
1291*3ba7c9e2Sbostic 	    currow++;
1292*3ba7c9e2Sbostic 	else
1293*3ba7c9e2Sbostic 	if (!growtbl(GROWROW, arg, 0))	/* get as much as needed */
1294*3ba7c9e2Sbostic 		break;
1295*3ba7c9e2Sbostic 	while (row_hidden[currow]&&(currow<maxrows-1))
1296*3ba7c9e2Sbostic 	    currow++;
1297*3ba7c9e2Sbostic     }
1298*3ba7c9e2Sbostic }
1299*3ba7c9e2Sbostic 
1300*3ba7c9e2Sbostic void
backrow(arg)1301*3ba7c9e2Sbostic backrow(arg)
1302*3ba7c9e2Sbostic 	int arg;
1303*3ba7c9e2Sbostic {
1304*3ba7c9e2Sbostic     while (--arg>=0) {
1305*3ba7c9e2Sbostic 	if (currow)
1306*3ba7c9e2Sbostic 	    currow--;
1307*3ba7c9e2Sbostic 	else
1308*3ba7c9e2Sbostic 	    {error ("At row zero"); break;}
1309*3ba7c9e2Sbostic 	while (row_hidden[currow] && currow)
1310*3ba7c9e2Sbostic 	    currow--;
1311*3ba7c9e2Sbostic     }
1312*3ba7c9e2Sbostic }
1313*3ba7c9e2Sbostic 
1314*3ba7c9e2Sbostic 
1315*3ba7c9e2Sbostic /*
1316*3ba7c9e2Sbostic  * Show a cell's label string or expression value.  May overwrite value if
1317*3ba7c9e2Sbostic  * there is one already displayed in the cell.  Created from old code in
1318*3ba7c9e2Sbostic  * update(), copied with minimal changes.
1319*3ba7c9e2Sbostic  */
1320*3ba7c9e2Sbostic 
1321*3ba7c9e2Sbostic void
showstring(string,leftflush,hasvalue,row,col,nextcolp,mxcol,fieldlenp,r,c)1322*3ba7c9e2Sbostic showstring (string, leftflush, hasvalue, row, col, nextcolp, mxcol, fieldlenp, r, c)
1323*3ba7c9e2Sbostic     char *string;	/* to display */
1324*3ba7c9e2Sbostic     int leftflush;	/* or rightflush */
1325*3ba7c9e2Sbostic     int hasvalue;	/* is there a numeric value? */
1326*3ba7c9e2Sbostic     int row, col;	/* spreadsheet location */
1327*3ba7c9e2Sbostic     int *nextcolp;	/* value returned through it */
1328*3ba7c9e2Sbostic     int mxcol;		/* last column displayed? */
1329*3ba7c9e2Sbostic     int *fieldlenp;	/* value returned through it */
1330*3ba7c9e2Sbostic     int r, c;		/* screen row and column */
1331*3ba7c9e2Sbostic {
1332*3ba7c9e2Sbostic     register int nextcol  = *nextcolp;
1333*3ba7c9e2Sbostic     register int fieldlen = *fieldlenp;
1334*3ba7c9e2Sbostic 
1335*3ba7c9e2Sbostic     char field[FBUFLEN];
1336*3ba7c9e2Sbostic     int  slen;
1337*3ba7c9e2Sbostic     char *start, *last;
1338*3ba7c9e2Sbostic     register char *fp;
1339*3ba7c9e2Sbostic     struct ent *nc;
1340*3ba7c9e2Sbostic 
1341*3ba7c9e2Sbostic     /* This figures out if the label is allowed to
1342*3ba7c9e2Sbostic        slop over into the next blank field */
1343*3ba7c9e2Sbostic 
1344*3ba7c9e2Sbostic     slen = strlen (string);
1345*3ba7c9e2Sbostic     while ((slen > fieldlen) && (nextcol <= mxcol) &&
1346*3ba7c9e2Sbostic 	   !((nc = lookat (row, nextcol)) -> flags & is_valid) &&
1347*3ba7c9e2Sbostic 	   !(nc->label)) {
1348*3ba7c9e2Sbostic 
1349*3ba7c9e2Sbostic 	if (! col_hidden [nextcol])
1350*3ba7c9e2Sbostic 	    fieldlen += fwidth [nextcol];
1351*3ba7c9e2Sbostic 
1352*3ba7c9e2Sbostic 	nextcol++;
1353*3ba7c9e2Sbostic     }
1354*3ba7c9e2Sbostic     if (slen > fieldlen)
1355*3ba7c9e2Sbostic 	slen = fieldlen;
1356*3ba7c9e2Sbostic 
1357*3ba7c9e2Sbostic     /* Now justify and print */
1358*3ba7c9e2Sbostic     start = leftflush ? field : field + fieldlen - slen;
1359*3ba7c9e2Sbostic     last = field+fieldlen;
1360*3ba7c9e2Sbostic     fp = field;
1361*3ba7c9e2Sbostic     while (fp < start)
1362*3ba7c9e2Sbostic 	*fp++ = ' ';
1363*3ba7c9e2Sbostic     while (slen--)
1364*3ba7c9e2Sbostic 	*fp++ = *string++;
1365*3ba7c9e2Sbostic     if ((! hasvalue) || fieldlen != fwidth[col])
1366*3ba7c9e2Sbostic 	while (fp < last)
1367*3ba7c9e2Sbostic 	    *fp++ = ' ';
1368*3ba7c9e2Sbostic     *fp = '\0';
1369*3ba7c9e2Sbostic #ifdef VMS
1370*3ba7c9e2Sbostic     mvaddstr(r, c, field);	/* this is a macro */
1371*3ba7c9e2Sbostic #else
1372*3ba7c9e2Sbostic     (void) mvaddstr(r, c, field);
1373*3ba7c9e2Sbostic #endif
1374*3ba7c9e2Sbostic 
1375*3ba7c9e2Sbostic     *nextcolp  = nextcol;
1376*3ba7c9e2Sbostic     *fieldlenp = fieldlen;
1377*3ba7c9e2Sbostic }
1378*3ba7c9e2Sbostic 
1379*3ba7c9e2Sbostic int
etype(e)1380*3ba7c9e2Sbostic etype(e)
1381*3ba7c9e2Sbostic register struct enode *e;
1382*3ba7c9e2Sbostic {
1383*3ba7c9e2Sbostic     if (e == (struct enode *)0)
1384*3ba7c9e2Sbostic 	return NUM;
1385*3ba7c9e2Sbostic     switch (e->op) {
1386*3ba7c9e2Sbostic     case O_SCONST: case '#': case DATE: case FMT: case STINDEX:
1387*3ba7c9e2Sbostic     case EXT: case SVAL: case SUBSTR:
1388*3ba7c9e2Sbostic         return (STR);
1389*3ba7c9e2Sbostic 
1390*3ba7c9e2Sbostic     case '?':
1391*3ba7c9e2Sbostic     case IF:
1392*3ba7c9e2Sbostic         return(etype(e->e.o.right->e.o.left));
1393*3ba7c9e2Sbostic 
1394*3ba7c9e2Sbostic     case 'f':
1395*3ba7c9e2Sbostic         return(etype(e->e.o.right));
1396*3ba7c9e2Sbostic 
1397*3ba7c9e2Sbostic     case O_VAR: {
1398*3ba7c9e2Sbostic 	register struct ent *p;
1399*3ba7c9e2Sbostic 	p = e->e.v.vp;
1400*3ba7c9e2Sbostic 	if (p->expr)
1401*3ba7c9e2Sbostic 	    return(p->flags & is_strexpr ? STR : NUM);
1402*3ba7c9e2Sbostic 	else if (p->label)
1403*3ba7c9e2Sbostic 	    return(STR);
1404*3ba7c9e2Sbostic 	else
1405*3ba7c9e2Sbostic 	    return(NUM);
1406*3ba7c9e2Sbostic 	}
1407*3ba7c9e2Sbostic 
1408*3ba7c9e2Sbostic     default:
1409*3ba7c9e2Sbostic 	return(NUM);
1410*3ba7c9e2Sbostic     }
1411*3ba7c9e2Sbostic }
1412*3ba7c9e2Sbostic 
1413*3ba7c9e2Sbostic /* return 1 if yes given, 0 otherwise */
1414*3ba7c9e2Sbostic int
yn_ask(msg)1415*3ba7c9e2Sbostic yn_ask(msg)
1416*3ba7c9e2Sbostic char	*msg;
1417*3ba7c9e2Sbostic {	char ch;
1418*3ba7c9e2Sbostic 
1419*3ba7c9e2Sbostic 	(void) move (0, 0);
1420*3ba7c9e2Sbostic 	(void) clrtoeol ();
1421*3ba7c9e2Sbostic 	(void) addstr (msg);
1422*3ba7c9e2Sbostic 	(void) refresh();
1423*3ba7c9e2Sbostic 	ch = nmgetch();
1424*3ba7c9e2Sbostic 	if ( ch != 'y' && ch != 'Y' && ch != 'n' && ch != 'N' ) {
1425*3ba7c9e2Sbostic 		if (ch == ctl('g') || ch == ESC)
1426*3ba7c9e2Sbostic 			return(-1);
1427*3ba7c9e2Sbostic 		error("y or n response required");
1428*3ba7c9e2Sbostic 		return (-1);
1429*3ba7c9e2Sbostic 	}
1430*3ba7c9e2Sbostic 	if (ch == 'y' || ch == 'Y')
1431*3ba7c9e2Sbostic 		return(1);
1432*3ba7c9e2Sbostic 	else
1433*3ba7c9e2Sbostic 		return(0);
1434*3ba7c9e2Sbostic }
1435*3ba7c9e2Sbostic 
1436*3ba7c9e2Sbostic #include <pwd.h>
1437*3ba7c9e2Sbostic char	*
findhome(path)1438*3ba7c9e2Sbostic findhome(path)
1439*3ba7c9e2Sbostic char	*path;
1440*3ba7c9e2Sbostic {
1441*3ba7c9e2Sbostic 	static	char	*HomeDir = NULL;
1442*3ba7c9e2Sbostic 	extern	char	*getenv();
1443*3ba7c9e2Sbostic 
1444*3ba7c9e2Sbostic 	if (*path == '~')
1445*3ba7c9e2Sbostic 	{	char	*pathptr;
1446*3ba7c9e2Sbostic 		char	tmppath[PATHLEN];
1447*3ba7c9e2Sbostic 
1448*3ba7c9e2Sbostic 		if (HomeDir == NULL)
1449*3ba7c9e2Sbostic 		{	HomeDir = getenv("HOME");
1450*3ba7c9e2Sbostic 			if (HomeDir == NULL)
1451*3ba7c9e2Sbostic 				HomeDir = "/";
1452*3ba7c9e2Sbostic 		}
1453*3ba7c9e2Sbostic 		pathptr = path + 1;
1454*3ba7c9e2Sbostic 		if ((*pathptr == '/') || (*pathptr == '\0'))
1455*3ba7c9e2Sbostic 		{	strcpy(tmppath, HomeDir);
1456*3ba7c9e2Sbostic 		}
1457*3ba7c9e2Sbostic 		else
1458*3ba7c9e2Sbostic 		{	struct	passwd *pwent;
1459*3ba7c9e2Sbostic 			extern	struct	passwd *getpwnam();
1460*3ba7c9e2Sbostic 			char	*namep;
1461*3ba7c9e2Sbostic 			char	name[50];
1462*3ba7c9e2Sbostic 
1463*3ba7c9e2Sbostic 			namep = name;
1464*3ba7c9e2Sbostic 			while ((*pathptr != '\0') && (*pathptr != '/'))
1465*3ba7c9e2Sbostic 				*(namep++) = *(pathptr++);
1466*3ba7c9e2Sbostic 			*namep = '\0';
1467*3ba7c9e2Sbostic 			if ((pwent = getpwnam(name)) == NULL)
1468*3ba7c9e2Sbostic 			{	sprintf(path, "Can't find user %s", name);
1469*3ba7c9e2Sbostic 				return(NULL);
1470*3ba7c9e2Sbostic 			}
1471*3ba7c9e2Sbostic 			strcpy(tmppath, pwent->pw_dir);
1472*3ba7c9e2Sbostic 		}
1473*3ba7c9e2Sbostic 
1474*3ba7c9e2Sbostic 		strcat(tmppath, pathptr);
1475*3ba7c9e2Sbostic 		strcpy(path, tmppath);
1476*3ba7c9e2Sbostic 	}
1477*3ba7c9e2Sbostic 	return(path);
1478*3ba7c9e2Sbostic }
1479*3ba7c9e2Sbostic 
1480*3ba7c9e2Sbostic #ifdef DOBACKUPS
1481*3ba7c9e2Sbostic #include <sys/types.h>
1482*3ba7c9e2Sbostic #include <sys/stat.h>
1483*3ba7c9e2Sbostic 
1484*3ba7c9e2Sbostic /*
1485*3ba7c9e2Sbostic  * make a backup copy of a file, use the same mode and name in the format
1486*3ba7c9e2Sbostic  * [path/]#file~
1487*3ba7c9e2Sbostic  * return 1 if we were successful, 0 otherwise
1488*3ba7c9e2Sbostic  */
1489*3ba7c9e2Sbostic int
backup_file(path)1490*3ba7c9e2Sbostic backup_file(path)
1491*3ba7c9e2Sbostic char	*path;
1492*3ba7c9e2Sbostic {
1493*3ba7c9e2Sbostic 	struct	stat	statbuf;
1494*3ba7c9e2Sbostic 	char	fname[PATHLEN];
1495*3ba7c9e2Sbostic 	char	tpath[PATHLEN];
1496*3ba7c9e2Sbostic #ifdef sequent
1497*3ba7c9e2Sbostic 	char	*buf;
1498*3ba7c9e2Sbostic #else
1499*3ba7c9e2Sbostic 	char	buf[BUFSIZ];
1500*3ba7c9e2Sbostic #endif
1501*3ba7c9e2Sbostic 	char	*tpp;
1502*3ba7c9e2Sbostic 	int	infd, outfd;
1503*3ba7c9e2Sbostic 	int	count;
1504*3ba7c9e2Sbostic 
1505*3ba7c9e2Sbostic 	/* tpath will be the [path/]file ---> [path/]#file~ */
1506*3ba7c9e2Sbostic 	strcpy(tpath, path);
1507*3ba7c9e2Sbostic 	if ((tpp = strrchr(tpath, '/')) == NULL)
1508*3ba7c9e2Sbostic 		tpp = tpath;
1509*3ba7c9e2Sbostic 	else
1510*3ba7c9e2Sbostic 		tpp++;
1511*3ba7c9e2Sbostic 	strcpy(fname, tpp);
1512*3ba7c9e2Sbostic 	sprintf(tpp, "#%s~", fname);
1513*3ba7c9e2Sbostic 
1514*3ba7c9e2Sbostic 	if (stat(path, &statbuf) == 0)
1515*3ba7c9e2Sbostic 	{
1516*3ba7c9e2Sbostic #ifdef sequent
1517*3ba7c9e2Sbostic 		if ((buf = xmalloc(statbuf.st_blksize)) == (char *)0)
1518*3ba7c9e2Sbostic 			return(0);
1519*3ba7c9e2Sbostic #endif
1520*3ba7c9e2Sbostic 
1521*3ba7c9e2Sbostic 		if ((infd = open(path, O_RDONLY, 0)) < 0)
1522*3ba7c9e2Sbostic 		{
1523*3ba7c9e2Sbostic #ifdef sequent
1524*3ba7c9e2Sbostic 			xfree(buf);
1525*3ba7c9e2Sbostic #endif
1526*3ba7c9e2Sbostic 			return(0);
1527*3ba7c9e2Sbostic 		}
1528*3ba7c9e2Sbostic 		if ((outfd = open(tpath, O_TRUNC|O_WRONLY|O_CREAT,
1529*3ba7c9e2Sbostic 					statbuf.st_mode)) < 0)
1530*3ba7c9e2Sbostic 		{
1531*3ba7c9e2Sbostic #ifdef sequent
1532*3ba7c9e2Sbostic 			xfree(buf);
1533*3ba7c9e2Sbostic #endif
1534*3ba7c9e2Sbostic 			return(0);
1535*3ba7c9e2Sbostic 		}
1536*3ba7c9e2Sbostic #ifdef sequent
1537*3ba7c9e2Sbostic 		while((count = read(infd, buf, statbuf.st_blksize)) > 0)
1538*3ba7c9e2Sbostic #else
1539*3ba7c9e2Sbostic 		while((count = read(infd, buf, sizeof(buf))) > 0)
1540*3ba7c9e2Sbostic #endif
1541*3ba7c9e2Sbostic 		{	if (write(outfd, buf, count) != count)
1542*3ba7c9e2Sbostic 			{	count = -1;
1543*3ba7c9e2Sbostic 				break;
1544*3ba7c9e2Sbostic 			}
1545*3ba7c9e2Sbostic 		}
1546*3ba7c9e2Sbostic 		close(infd);
1547*3ba7c9e2Sbostic 		close(outfd);
1548*3ba7c9e2Sbostic #ifdef sequent
1549*3ba7c9e2Sbostic 		xfree(buf);
1550*3ba7c9e2Sbostic #endif
1551*3ba7c9e2Sbostic 		return((count < 0) ? 0 : 1);
1552*3ba7c9e2Sbostic 	}
1553*3ba7c9e2Sbostic 	else
1554*3ba7c9e2Sbostic 	if (errno == ENOENT)
1555*3ba7c9e2Sbostic 		return(1);
1556*3ba7c9e2Sbostic 	return(0);
1557*3ba7c9e2Sbostic }
1558*3ba7c9e2Sbostic #endif
1559