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