/* SC A Spreadsheet Calculator * Main driver * * James Gosling, September 1982 * */ #include #include "sc.h" int linelim = -1; error (fmt,a,b,c,d,e) { move (1,0); clrtoeol (); printw (fmt,a,b,c,d,e); } int seenerr; yyerror (err) char *err; { if (seenerr) return; seenerr++; move (1,0); clrtoeol (); printw ("%s: %.*s<=%s",err,linelim,line,line+linelim); } struct ent *lookat(row,col){ register struct ent **p = &tbl[row][col]; if (*p==0) { *p = (struct ent *) malloc (sizeof (struct ent)); if (row>maxrow) maxrow = row; if (col>maxcol) maxcol = col; (*p)->label = 0; (*p)->flags = 0; (*p)->row = row; (*p)->col = col; (*p)->expr = 0; } return *p; } update () { register row, col; register struct ent **p; static lastmx, lastmy; int maxcol; int rows = LINES - 2; int cols; if (curcol < stcol) stcol = curcol, FullUpdate++; if (currow < strow) strow = currow, FullUpdate++; while (1) { register i; for (i = stcol, cols = 0, col = 0; col < COLS - 4 && i < MAXCOLS; i++) col += fwidth[i], cols++; if (curcol >= stcol + cols) stcol++, FullUpdate++; else break; } if (currow >= strow + rows) strow = currow - rows + 1, FullUpdate++; if (FullUpdate) { move (2, 0); clrtobot (); } maxcol = stcol + cols - 1; for (row = strow + rows - 1; row >= strow; row--) { register c = 0; for (p = &tbl[row][col = stcol]; col <= maxcol; col++, p++) { if (*p && ((*p) -> flags & is_changed || FullUpdate)) { register r = row - strow + 2; char *s; move (r, c); (*p) -> flags &= ~is_changed; if ((*p) -> flags & is_valid) printw ("%*.*f", fwidth[col], precision[col], (*p) -> v); if (s = (*p) -> label) mvaddstr (r, (*p) -> flags & is_leftflush ? c : c - strlen (s) + fwidth[col], s); } c += fwidth[col]; } } mvaddstr (lastmy, lastmx, " "); lastmy = currow - strow + 2; lastmx = 0; for (col = stcol; col <= curcol;) lastmx += fwidth[col++]; mvaddstr (lastmy, lastmx, "<"); move (0, 0); clrtoeol (); if (linelim >= 0) { addstr (">> "); addstr (line); } else move (lastmy, lastmx); FullUpdate = 0; } #define ctl(c) ('c'&037) main (argc, argv) char **argv; { int running = 1; register char c; int edistate = -1; int arg = 1; int narg; int nedistate = -1; { register i; for (i = 0; i < MAXCOLS; i++) { fwidth[i] = 10; precision[i] = 2; } } initscr (); clear (); raw (); noecho (); error ("Welcome to the Spreadsheet Calculator, type '?' for help."); if (argc > 1) readfile (argv[1]); while (running) { nedistate = -1; narg = 1; if (edistate < 0 && linelim < 0 && (changed || FullUpdate)) EvalAll (), changed = 0; update (); refresh (); move (1, 0); clrtoeol (); fflush (stdout); seenerr = 0; if ((c = getchar ()) < ' ') switch (c) { default: error ("No such command (^%c)", c + 0100); break; case ctl (b): while (--arg>=0) if (curcol) curcol--; break; case ctl (c): running = 0; break; case ctl (f): while (--arg>=0) if (curcol < MAXCOLS - 1) curcol++; break; case ctl (g): linelim = -1; break; case ctl (h): while (--arg>=0) if (linelim > 0) line[--linelim] = 0; break; case ctl (j): if (currow >= MAXCOLS - 1 || maxcol >= MAXCOLS - 1) { error ("The table can't be any bigger"); break; } currow++; openrow (currow); for (curcol = 0; curcol <= maxcol; curcol++) { register struct ent *p = tbl[currow - 1][curcol]; if (p) { register struct ent *n; n = lookat (currow, curcol); n -> v = p -> v; n -> flags = p -> flags; n -> expr = copye (p -> expr, 1, 0); n -> label = 0; if (p -> label) { n -> label = (char *) malloc (strlen (p -> label) + 1); strcpy (n -> label, p -> label); } } } for (curcol = 0; curcol <= maxcol; curcol++) { register struct ent *p = tbl[currow][curcol]; if (p && (p -> flags & is_valid) && !p -> expr) break; } if (curcol > maxcol) curcol = 0; break; case ctl (l): FullUpdate++; break; case ctl (m): if (linelim < 0) line[linelim = 0] = 0; else { linelim = 0; yyparse (); linelim = -1; } break; case ctl (n): while (--arg>=0) if (currow < MAXROWS - 1) currow++; break; case ctl (p): while (--arg>=0) if (currow) currow--; break; case ctl (q): break; /* ignore flow control */ case ctl (s): break; /* ignore flow control */ case ctl (u): narg = arg * 4; nedistate = 1; break; case ctl (v): if (linelim > 0) { sprintf (line + linelim, "r%dc%d", currow, curcol); linelim = strlen (line); } break; } else if ('0' <= c && c <= '9' && (linelim < 0 || edistate >= 0)) { if (edistate != 0) arg = 0; nedistate = 0; narg = arg * 10 + (c - '0'); } else if (linelim >= 0) { line[linelim++] = c; line[linelim] = 0; } else switch (c) { case '.': nedistate = 1; break; case '=': sprintf (line, "let r%dc%d = ", currow, curcol); linelim = strlen (line); break; case '?': help (); break; case '"': sprintf (line, "label r%dc%d = \"", currow, curcol); linelim = strlen (line); break; case '<': sprintf (line, "leftstring r%dc%d = \"", currow, curcol); linelim = strlen (line); break; case '>': sprintf (line, "rightstring r%dc%d = \"", currow, curcol); linelim = strlen (line); break; case 'e': editv (currow, curcol); break; case 'f': sprintf (line, "format [for column] %d [is] ", curcol); linelim = strlen (line); break; case 'p': sprintf (line, "put [database into] \""); linelim = strlen (line); break; case 'g': sprintf (line, "get [database from] \""); linelim = strlen (line); break; case 'w': sprintf (line, "write [listing to] \""); linelim = strlen (line); break; case 'r': while (--arg>=0) openrow (currow); break; case 'd': while (--arg>=0) closerow (currow); break; case 'c': while (--arg>=0) opencol (curcol); break; case 'D': while (--arg>=0) closecol (curcol); break; } edistate = nedistate; arg = narg; } move (LINES - 1, 0); refresh (); noraw (); echo (); endwin (); } writefile (fname) char *fname; { register FILE *f = fopen (fname, "w"); register struct ent **p; register r, c; if (f==0) { error ("Can't create %s", fname); return; } fprintf (f, "# This data file was generated by the Spreadsheet Calculator.\ \n# You almost certainly shouldn't edit it.\n\n"); for (c=0; clabel) fprintf (f, "%sstring r%dc%d = \"%s\"\n", (*p)->flags&is_leftflush ? "left" : "right", r,c,(*p)->label); if ((*p)->flags&is_valid) { editv (r, c); fprintf (f, "%s\n",line); } } } fclose (f); } readfile (fname) char *fname; { register FILE *f = fopen (fname, "r"); if (f==0) { error ("Can't read %s", fname); return; } erasedb (); while (fgets(line,sizeof line,f)) { linelim = 0; if (line[0] != '#') yyparse (); } fclose (f); linelim = -1; } erasedb () { register r, c; for (c = 0; c=0; p++) if (*p) { if ((*p)->expr) efree ((*p) -> expr); if ((*p)->label) free ((*p) -> label); free (*p); *p = 0; } } maxrow = 0; maxcol = 0; FullUpdate++; } openrow (rs) { register r; register struct ent **p; register c; if (maxcol >= MAXCOLS - 1) { error ("The table can't be any bigger"); return; } for (r = ++maxrow; r > rs; r--) for (c = maxcol + 1, p = &tbl[r][0]; --c >= 0; p++) if (p[0] = p[-MAXCOLS]) p[0] -> row++; p = &tbl[rs][0]; for (c = maxcol + 1; --c >= 0;) *p++ = 0; FullUpdate++; } closerow (r) register r; { register struct ent **p; register c; while (r=0; p++) if (p[0] = p[MAXCOLS]) p[0]->row--; r++; } p = &tbl[maxrow][0]; for (c=maxcol+1; --c>=0; ) *p++ = 0; maxrow--; FullUpdate++; } opencol (cs) { register r; register struct ent **p; register c; register lim = maxcol-cs+1; for (r=0; r<=maxrow; r++) { p = &tbl[r][maxcol+1]; for (c=lim; --c>=0; p--) if (p[0] = p[-1]) p[0]->col++; p[0] = 0; } maxcol++; FullUpdate++; } closecol (cs) { register r; register struct ent **p; register c; register lim = maxcol-cs; for (r=0; r<=maxrow; r++) { p = &tbl[r][cs]; for (c=lim; --c>=0; p++) if (p[0] = p[1]) p[0]->col++; p[0] = 0; } maxcol--; FullUpdate++; }