home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume18 / sc6.1 / part04 < prev    next >
Encoding:
Internet Message Format  |  1989-03-20  |  60.1 KB

  1. Subject:  v18i048:  SC spreadsheet, version 6.1, Part04/04
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Robert Bond <sequent!rgb@uunet.uu.net>
  7. Posting-number: Volume 18, Issue 48
  8. Archive-name: sc6.1/part04
  9.  
  10. # This is a shell archive.  Remove anything before this line
  11. # then unpack it by saving it in a file and typing "sh file"
  12. # (Files unpacked will be owned by you and have default permissions).
  13. # This archive contains the following files:
  14. #    ./xmalloc.c
  15. #    ./cmds.c
  16. #    ./range.c
  17. #    ./help.c
  18. #    ./eres.sed
  19. #    ./sres.sed
  20. #    ./Makefile
  21. #    ./psc.c
  22. #
  23. if `test ! -s ./xmalloc.c`
  24. then
  25. echo "Extracting ./xmalloc.c"
  26. cat > ./xmalloc.c << '\SHAR\EOF\'
  27. /*
  28.  * A safer saner malloc, for careless programmers
  29.  * $Revision: 6.1 $
  30.  */
  31.  
  32. #include <stdio.h>
  33. #include <curses.h>
  34.  
  35. extern char *malloc();
  36.  
  37. #ifdef SYSV3
  38. extern void free();
  39. extern void exit();
  40. #endif
  41.  
  42. char *
  43. xmalloc(n)
  44. unsigned n;
  45. {
  46. register char *ptr;
  47.  
  48. if ((ptr = malloc(n + sizeof(double))) == NULL)
  49.     fatal("xmalloc: no memory");
  50. *((int *) ptr) = 12345;        /* magic number */
  51. return(ptr + sizeof(double));
  52. }
  53.  
  54. xfree(p)
  55. char *p;
  56. {
  57. if (p == NULL)
  58.     fatal("xfree: NULL");
  59. p -= sizeof(double);
  60. if (*((int *) p) != 12345)
  61.     fatal("xfree: storage not malloc'ed");
  62. free(p);
  63. }
  64.  
  65. fatal(str)
  66. char *str;
  67. {
  68.     deraw();
  69.     (void) fprintf(stderr,"%s\n", str);
  70.     exit(1);
  71. }
  72. \SHAR\EOF\
  73. else
  74.   echo "will not over write ./xmalloc.c"
  75. fi
  76. if [ `wc -c ./xmalloc.c | awk '{printf $1}'` -ne 670 ]
  77. then
  78. echo `wc -c ./xmalloc.c | awk '{print "Got " $1 ", Expected " 670}'`
  79. fi
  80. if `test ! -s ./cmds.c`
  81. then
  82. echo "Extracting ./cmds.c"
  83. cat > ./cmds.c << '\SHAR\EOF\'
  84. /*    SC    A Spreadsheet Calculator
  85.  *        Command routines
  86.  *
  87.  *        original by James Gosling, September 1982
  88.  *        modifications by Mark Weiser and Bruce Israel,
  89.  *            University of Maryland
  90.  *
  91.  *              More mods Robert Bond, 12/86
  92.  *
  93.  *        $Revision: 6.1 $
  94.  */
  95.  
  96. #include <curses.h>
  97. #include "sc.h"
  98. #include <signal.h>
  99.  
  100. #ifdef BSD42
  101. #include <strings.h>
  102. #else
  103. #ifndef SYSIII
  104. #include <string.h>
  105. #endif
  106. #endif
  107.  
  108. #ifdef SYSV3
  109. extern void exit();
  110. #else
  111. extern int exit();
  112. #endif
  113.  
  114. #define DEFCOLDELIM ':'
  115.  
  116. duprow()
  117. {
  118.     if (currow >= MAXROWS - 1 || maxrow >= MAXROWS - 1) {
  119.     error ("The table can't be any bigger");
  120.     return;
  121.     }
  122.     modflg++;
  123.     currow++;
  124.     openrow (currow);
  125.     for (curcol = 0; curcol <= maxcol; curcol++) {
  126.     register struct ent *p = tbl[currow - 1][curcol];
  127.     if (p) {
  128.         register struct ent *n;
  129.         n = lookat (currow, curcol);
  130.         copyent ( n, p, 1, 0);
  131.     }
  132.     }
  133.     for (curcol = 0; curcol <= maxcol; curcol++) {
  134.     register struct ent *p = tbl[currow][curcol];
  135.     if (p && (p -> flags & is_valid) && !p -> expr)
  136.         break;
  137.     }
  138.     if (curcol > maxcol)
  139.     curcol = 0;
  140. }
  141.  
  142. dupcol() 
  143. {
  144.     if (curcol >= MAXCOLS - 1 || maxcol >= MAXCOLS - 1) {
  145.     error ("The table can't be any wider");
  146.     return;
  147.     }
  148.     modflg++;
  149.     curcol++;
  150.     opencol (curcol);
  151.     for (currow = 0; currow <= maxrow; currow++) {
  152.     register struct ent *p = tbl[currow][curcol - 1];
  153.     if (p) {
  154.         register struct ent *n;
  155.         n = lookat (currow, curcol);
  156.         copyent ( n, p, 0, 1);
  157.     }
  158.     }
  159.     for (currow = 0; currow <= maxrow; currow++) {
  160.     register struct ent *p = tbl[currow][curcol];
  161.     if (p && (p -> flags & is_valid) && !p -> expr)
  162.         break;
  163.     }
  164.     if (currow > maxrow)
  165.     currow = 0;
  166. }
  167.  
  168. insertrow(arg)
  169. register int arg;
  170. {
  171.     while (--arg>=0) openrow (currow);
  172. }
  173.  
  174. deleterow(arg)
  175. register int arg;
  176. {
  177.     flush_saved();
  178.     erase_area(currow, 0, currow + arg - 1, maxcol);
  179.     currow += arg;
  180.     while (--arg>=0) closerow (--currow);
  181.     sync_refs();
  182. }
  183.  
  184. insertcol(arg)
  185. register int arg;
  186. {
  187.     while (--arg>=0) opencol(curcol);
  188. }
  189.  
  190. deletecol(arg)
  191. register int arg;
  192. {
  193.     flush_saved();
  194.     erase_area(0, curcol, maxrow, curcol + arg - 1);
  195.     curcol += arg;
  196.     while (--arg>=0) closecol (--curcol);
  197.     sync_refs();
  198. }
  199.  
  200. rowvalueize(arg)
  201. register int arg;
  202. {
  203.     valueize_area(currow, 0, currow + arg - 1, maxcol);
  204. }
  205.  
  206. colvalueize(arg)
  207. register int arg;
  208. {
  209.     valueize_area(0, curcol, maxrow, curcol + arg - 1);
  210. }
  211.  
  212. erase_area(sr, sc, er, ec)
  213. int sr, sc, er, ec;
  214. {
  215.     register int r, c;
  216.     register struct ent **p;
  217.  
  218.     if (sr > er) {
  219.     r = sr; sr = er; er= r;    
  220.     }
  221.  
  222.     if (sc > ec) {
  223.     c = sc; sc = ec; ec= c;    
  224.     }
  225.  
  226.     if (sr < 0)
  227.     sr = 0; 
  228.     if (sc < 0)
  229.     sc = 0;
  230.     if (er >= MAXROWS)
  231.     er = MAXROWS-1;
  232.     if (ec >= MAXCOLS)
  233.     ec = MAXCOLS-1;
  234.  
  235.     for (r = sr; r <= er; r++) {
  236.     for (c = sc; c <= ec; c++) {
  237.         p = &tbl[r][c];
  238.         if (*p) {
  239.         free_ent(*p);
  240.         *p = 0;
  241.         }
  242.     }
  243.     }
  244.  
  245. }
  246.  
  247. valueize_area(sr, sc, er, ec)
  248. int sr, sc, er, ec;
  249. {
  250.     register int r, c;
  251.     register struct ent *p;
  252.  
  253.     if (sr > er) {
  254.     r = sr; sr = er; er= r;    
  255.     }
  256.  
  257.     if (sc > ec) {
  258.     c = sc; sc = ec; ec= c;    
  259.     }
  260.  
  261.     if (sr < 0)
  262.     sr = 0; 
  263.     if (sc < 0)
  264.     sc = 0;
  265.     if (er >= MAXROWS)
  266.     er = MAXROWS-1;
  267.     if (ec >= MAXCOLS)
  268.     ec = MAXCOLS-1;
  269.  
  270.     for (r = sr; r <= er; r++) {
  271.     for (c = sc; c <= ec; c++) {
  272.         p = tbl[r][c];
  273.         if (p && p->expr) {
  274.         efree(p->expr);
  275.         p->expr = 0;
  276.         p->flags &= ~is_strexpr;
  277.         }
  278.     }
  279.     }
  280.  
  281. }
  282.  
  283. pullcells(to_insert)
  284. int to_insert;
  285. {
  286.     register struct ent *p, *n;
  287.     register int deltar, deltac;
  288.     int minrow, mincol;
  289.     int mxrow, mxcol;
  290.     int numrows, numcols;
  291.  
  292.     if (! to_fix)
  293.     {
  294.     error ("No data to pull");
  295.     return;
  296.     }
  297.  
  298.     minrow = MAXROWS; 
  299.     mincol = MAXCOLS;
  300.     mxrow = 0;
  301.     mxcol = 0;
  302.  
  303.     for (p = to_fix; p; p = p->next) {
  304.     if (p->row < minrow)
  305.         minrow = p->row;
  306.     if (p->row > mxrow)
  307.         mxrow = p->row;
  308.     if (p->col < mincol)
  309.         mincol = p->col;
  310.     if (p->col > mxcol)
  311.         mxcol = p->col;
  312.     }
  313.  
  314.     numrows = mxrow - minrow + 1;
  315.     numcols = mxcol - mincol + 1;
  316.     deltar = currow - minrow;
  317.     deltac = curcol - mincol;
  318.  
  319.     if (to_insert == 'r') {
  320.     insertrow(numrows);
  321.     deltac = 0;
  322.     } else if (to_insert == 'c') {
  323.     insertcol(numcols);
  324.     deltar = 0;
  325.     }
  326.  
  327.     FullUpdate++;
  328.     modflg++;
  329.  
  330.     for (p = to_fix; p; p = p->next) {
  331.     n = lookat (p->row + deltar, p->col + deltac);
  332.     (void) clearent(n);
  333.     copyent( n, p, deltar, deltac);
  334.     n -> flags = p -> flags & ~is_deleted;
  335.     }
  336. }
  337.  
  338. colshow_op()
  339. {
  340.     register int i,j;
  341.     for (i=0; i<MAXCOLS; i++)
  342.     if (col_hidden[i]) 
  343.         break;
  344.     for(j=i; j<MAXCOLS; j++)
  345.     if (!col_hidden[j])
  346.         break;
  347.     j--;
  348.     if (i>=MAXCOLS)
  349.     error ("No hidden columns to show");
  350.     else {
  351.     (void) sprintf(line,"show %s:", coltoa(i));
  352.     (void) sprintf(line + strlen(line),"%s",coltoa(j));
  353.     linelim = strlen (line);
  354.     }
  355. }
  356.  
  357. rowshow_op()
  358. {
  359.     register int i,j;
  360.     for (i=0; i<MAXROWS; i++)
  361.     if (row_hidden[i]) 
  362.         break;
  363.     for(j=i; j<MAXROWS; j++)
  364.     if (!row_hidden[j]) {
  365.         break;
  366.     }
  367.     j--;
  368.  
  369.     if (i>=MAXROWS)
  370.     error ("No hidden rows to show");
  371.     else {
  372.     (void) sprintf(line,"show %d:%d", i, j);
  373.         linelim = strlen (line);
  374.     }
  375. }
  376.  
  377. /*
  378.  * Given a row/column command letter, emit a small menu, then read a qualifier
  379.  * character for a row/column command and convert it to 'r' (row), 'c'
  380.  * (column), or 0 (unknown).  If ch is 'p', an extra qualifier 'm' is allowed.
  381.  */
  382.  
  383. get_rcqual (ch)
  384.     int ch;
  385. {
  386.     error ("%sow/column:  r: row  c: column%s",
  387.  
  388.         (ch == 'i') ? "Insert r" :
  389.         (ch == 'a') ? "Append r" :
  390.         (ch == 'd') ? "Delete r" :
  391.         (ch == 'p') ? "Pull r" :
  392.         (ch == 'v') ? "Values r" :
  393.         (ch == 'z') ? "Zap r" :
  394.         (ch == 's') ? "Show r" : "R",
  395.  
  396.         (ch == 'p') ? "  m: merge" : "");
  397.  
  398.     (void) refresh();
  399.  
  400.     switch (nmgetch())
  401.     {
  402.     case 'r':
  403.     case 'l':
  404.     case 'h':
  405.     case ctl(f):
  406.     case ctl(b):    return ('r');
  407.  
  408.     case 'c':
  409.     case 'j':
  410.     case 'k':
  411.     case ctl(p):
  412.     case ctl(n):    return ('c');
  413.  
  414.     case 'm':    return ((ch == 'p') ? 'm' : 0);
  415.  
  416.     case ESC:
  417.     case ctl (g):    return (ESC);
  418.  
  419.     default:    return (0);
  420.     }
  421.     /*NOTREACHED*/
  422. }
  423.  
  424. openrow (rs)
  425. int rs;
  426. {
  427.     register    r;
  428.     register struct ent **p;
  429.     register    c;
  430.     register    i;
  431.  
  432.     if (rs > maxrow) maxrow = rs;
  433.     if (maxrow >= MAXROWS - 1 || rs > MAXROWS - 1) {
  434.     error ("The table can't be any longer");
  435.     return;
  436.     }
  437.     for (i = maxrow+1; i > rs; i--) {
  438.     row_hidden[i] = row_hidden[i-1];
  439.     }
  440.     for (r = ++maxrow; r > rs; r--)
  441.     for (c = maxcol + 1, p = &tbl[r][0]; --c >= 0; p++)
  442.         if (p[0] = p[-MAXCOLS])
  443.         p[0] -> row++;
  444.     p = &tbl[rs][0];
  445.     for (c = maxcol + 1; --c >= 0;)
  446.     *p++ = 0;
  447.     FullUpdate++;
  448.     modflg++;
  449. }
  450.  
  451. closerow (r)
  452. register r;
  453. {
  454.     register struct ent **p;
  455.     register c;
  456.     register int i;
  457.  
  458.     if (r > maxrow) return;
  459.  
  460.     p = &tbl[r][0];
  461.     for (c=maxcol+1; --c>=0; ) {
  462.     if (*p)
  463.         free_ent(*p);
  464.     *p++ = 0;
  465.     }
  466.  
  467.     for (i = r; i < MAXROWS - 1; i++) {
  468.     row_hidden[i] = row_hidden[i+1];
  469.     }
  470.  
  471.     while (r<maxrow) {
  472.     for (c = maxcol+1, p = &tbl[r][0]; --c>=0; p++)
  473.         if (p[0] = p[MAXCOLS])
  474.         p[0]->row--;
  475.     r++;
  476.     }
  477.  
  478.     p = &tbl[maxrow][0];
  479.     for (c=maxcol+1; --c>=0; ) *p++ = 0;
  480.     maxrow--;
  481.     FullUpdate++;
  482.     modflg++;
  483. }
  484.  
  485. opencol (cs)
  486. int cs;
  487. {
  488.     register r;
  489.     register struct ent **p;
  490.     register c;
  491.     register lim = maxcol-cs+1;
  492.     int i;
  493.  
  494.     if (cs > maxcol) maxcol = cs;
  495.     if (maxcol >= MAXCOLS - 1 || cs > MAXCOLS - 1) {
  496.     error ("The table can't be any wider");
  497.     return;
  498.     }
  499.     for (i = maxcol+1; i > cs; i--) {
  500.     fwidth[i] = fwidth[i-1];
  501.     precision[i] = precision[i-1];
  502.     col_hidden[i] = col_hidden[i-1];
  503.     }
  504.     /* fwidth[cs] = DEFWIDTH;
  505.     precision[i] =  DEFPREC;  */
  506.  
  507.     for (r=0; r<=maxrow; r++) {
  508.     p = &tbl[r][maxcol+1];
  509.     for (c=lim; --c>=0; p--)
  510.         if (p[0] = p[-1])
  511.         p[0]->col++;
  512.     p[0] = 0;
  513.     }
  514.     maxcol++;
  515.     FullUpdate++;
  516.     modflg++;
  517. }
  518.  
  519. closecol (cs)
  520. int cs;
  521. {
  522.     register r;
  523.     register struct ent **p;
  524.     register struct ent *q;
  525.     register c;
  526.     register lim = maxcol-cs;
  527.     int i;
  528.  
  529.     if (lim < 0) return;
  530.  
  531.     for (r=0; r<=maxrow; r++)
  532.     if (q = tbl[r][cs]) {
  533.         free_ent(q);
  534.     }
  535.  
  536.     for (r=0; r<=maxrow; r++) {
  537.     p = &tbl[r][cs];
  538.     for (c=lim; --c>=0; p++)
  539.         if (p[0] = p[1])
  540.         p[0]->col--;
  541.     p[0] = 0;
  542.     }
  543.  
  544.     for (i = cs; i < MAXCOLS - 1; i++) {
  545.     fwidth[i] = fwidth[i+1];
  546.     precision[i] = precision[i+1];
  547.     col_hidden[i] = col_hidden[i+1];
  548.     }
  549.  
  550.     maxcol--;
  551.     FullUpdate++;
  552.     modflg++;
  553. }
  554.  
  555. doend(rowinc, colinc)
  556. int rowinc, colinc;
  557. {
  558.     register struct ent *p;
  559.     int r, c;
  560.  
  561.     if (VALID_CELL(p, currow, curcol)) {
  562.     r = currow + rowinc;
  563.     c = curcol + colinc;
  564.     if (r >= 0 && r < MAXROWS && 
  565.         c >= 0 && c < MAXCOLS &&
  566.         !VALID_CELL(p, r, c)) {
  567.         currow = r;
  568.         curcol = c;
  569.     }
  570.     }
  571.  
  572.     if (!VALID_CELL(p, currow, curcol)) {
  573.         switch (rowinc) {
  574.         case -1:
  575.         while (!VALID_CELL(p, currow, curcol) && currow > 0)
  576.         currow--;
  577.         break;
  578.         case  1:
  579.         while (!VALID_CELL(p, currow, curcol) && currow < MAXROWS-1)
  580.         currow++;
  581.         break;
  582.         case  0:
  583.             switch (colinc) {
  584.          case -1:
  585.             while (!VALID_CELL(p, currow, curcol) && curcol > 0)
  586.             curcol--;
  587.             break;
  588.          case  1:
  589.             while (!VALID_CELL(p, currow, curcol) && curcol < MAXCOLS-1)
  590.             curcol++;
  591.             break;
  592.         }
  593.             break;
  594.         }
  595.  
  596.     error ("");    /* clear line */
  597.     return;
  598.     }
  599.  
  600.     switch (rowinc) {
  601.     case -1:
  602.     while (VALID_CELL(p, currow, curcol) && currow > 0)
  603.         currow--;
  604.     break;
  605.     case  1:
  606.     while (VALID_CELL(p, currow, curcol) && currow < MAXROWS-1)
  607.         currow++;
  608.     break;
  609.     case  0:
  610.     switch (colinc) {
  611.     case -1:
  612.         while (VALID_CELL(p, currow, curcol) && curcol > 0)
  613.         curcol--;
  614.         break;
  615.     case  1:
  616.         while (VALID_CELL(p, currow, curcol) && curcol < MAXCOLS-1)
  617.         curcol++;
  618.         break;
  619.     }
  620.     break;
  621.     }
  622.     if (!VALID_CELL(p, currow, curcol)) {
  623.         currow -= rowinc;
  624.         curcol -= colinc;
  625.     }
  626. }
  627.  
  628. doformat(c1,c2,w,p)
  629. int c1,c2,w,p;
  630. {
  631.     register int i;
  632.  
  633.     if (w > COLS - RESCOL - 2) {
  634.     error("Format too large - Maximum = %d", COLS - RESCOL - 2);
  635.     w = COLS-RESCOL-2;
  636.     }
  637.  
  638.     if (p > w) {
  639.     error("Precision too large");
  640.     p = w;
  641.     }
  642.  
  643.     for(i = c1; i<=c2; i++)
  644.     fwidth[i] = w, precision[i] = p;
  645.  
  646.     FullUpdate++;
  647.     modflg++;
  648. }
  649.  
  650. print_options(f)
  651. FILE *f;
  652. {
  653.     if(
  654.        autocalc &&
  655.        propagation == 10 &&
  656.        calc_order == BYROWS &&
  657.        !numeric &&
  658.        prescale == 1.0 &&
  659.        !extfunc &&
  660.        showcell &&
  661.        showtop &&
  662.        tbl_style == 0
  663.       )
  664.         return;        /* No reason to do this */
  665.  
  666.     (void) fprintf(f, "set");
  667.     if(!autocalc) 
  668.     (void) fprintf(f," !autocalc");
  669.     if(propagation != 10)
  670.     (void) fprintf(f, " iterations = %d", propagation);
  671.     if(calc_order != BYROWS )
  672.     (void) fprintf(f, " bycols");
  673.     if (numeric)
  674.     (void) fprintf(f, " numeric");
  675.     if (prescale != 1.0)
  676.     (void) fprintf(f, " prescale");
  677.     if (extfunc)
  678.     (void) fprintf(f, " extfun");
  679.     if (!showcell)
  680.     (void) fprintf(f, " !cellcur");
  681.     if (!showtop)
  682.     (void) fprintf(f, " !toprow");
  683.     if (tbl_style)
  684.     (void) fprintf(f, " tblstyle = %s", tbl_style == TBL ? "tbl" :
  685.                     tbl_style == LATEX ? "latex" :
  686.                     tbl_style == TEX ? "tex" : "0" );
  687.     (void) fprintf(f, "\n");
  688. }
  689.  
  690. printfile (fname, r0, c0, rn, cn)
  691. char *fname;
  692. int r0, c0, rn, cn;
  693. {
  694.     FILE *f;
  695.     char pline[1000];
  696.     int plinelim;
  697.     int pid;
  698.     int fieldlen, nextcol;
  699.     register row, col;
  700.     register struct ent **p;
  701.     char ch, lin[100];
  702.  
  703.     if (strcmp(fname, curfile) == 0) {
  704.     (void) move (0, 0);
  705.     (void) clrtoeol ();
  706.     (void) sprintf (lin,
  707.         "Confirm that you want to destroy the data base: (y,n)");
  708.     (void) addstr (lin);
  709.     (void) refresh();
  710.     ch = nmgetch();
  711.     if (ch != 'y' && ch != 'Y') 
  712.         return;
  713.     }
  714.  
  715.     f = openout(fname, &pid);
  716.  
  717.     if (f==0) {
  718.     error ("Can't create file \"%s\"", fname);
  719.     return;
  720.     }
  721.     for (row=r0;row<=rn; row++) {
  722.     register c = 0;
  723.  
  724.     if (row_hidden[row])
  725.         continue;
  726.  
  727.     pline[plinelim=0] = '\0';
  728.     for (p = &tbl[row][col=c0]; col<=cn;
  729.             p += nextcol-col, col = nextcol, c += fieldlen) {
  730.  
  731.         nextcol = col+1;
  732.         if (col_hidden[col]) {
  733.         fieldlen = 0;
  734.         continue;
  735.         }
  736.  
  737.         fieldlen = fwidth[col];
  738.         if (*p) {
  739.         char *s;
  740.  
  741.         while (plinelim<c) pline[plinelim++] = ' ';
  742.         plinelim = c;
  743.         if ((*p)->flags&is_valid) {
  744.             (void)sprintf (pline+plinelim,"%*.*f",fwidth[col],
  745.                                         precision[col], (*p)->v);
  746.             plinelim += strlen (pline+plinelim);
  747.         }
  748.         if (s = (*p)->label) {
  749.             int slen;
  750.             char *start, *last;
  751.             register char *fp;
  752.             struct ent *nc;
  753.  
  754.             /* Figure out if the label slops over to a blank field */
  755.             slen = strlen(s);
  756.             while (slen > fieldlen && nextcol <= cn &&
  757.                 !((nc = lookat(row,nextcol))->flags & is_valid) &&
  758.                 !(nc->label)) {
  759.             
  760.                     if (!col_hidden[nextcol])
  761.                  fieldlen += fwidth[nextcol];
  762.  
  763.             nextcol++;
  764.             }
  765.             if (slen > fieldlen)
  766.             slen = fieldlen;
  767.             
  768.             /* Now justify and print */
  769.             start = (*p)->flags & is_leftflush ? pline + c
  770.                     : pline + c + fieldlen - slen;
  771.             last = pline + c + fieldlen;
  772.             fp = plinelim < c ? pline + plinelim : pline + c;
  773.             while (fp < start)
  774.             *fp++ = ' ';
  775.             while (slen--)
  776.             *fp++ = *s++;
  777.             if (!((*p)->flags & is_valid) || fieldlen != fwidth[col])
  778.             while(fp < last)
  779.                 *fp++ = ' ';
  780.             if (plinelim < fp - pline)
  781.             plinelim = fp - pline;
  782.         }
  783.         }
  784.     }
  785.     pline[plinelim++] = '\n';
  786.     pline[plinelim] = 0;
  787.     (void) fputs (pline, f);
  788.     }
  789.  
  790.     closeout(f, pid);
  791. }
  792.  
  793. tblprintfile (fname, r0, c0, rn, cn)
  794. char *fname;
  795. int r0, c0, rn, cn;
  796. {
  797.     FILE *f;
  798.     int pid;
  799.     register row, col;
  800.     register struct ent **p;
  801.     char coldelim = DEFCOLDELIM;
  802.     char ch, lin[100];
  803.  
  804.     if (strcmp(fname, curfile) == 0) {
  805.     (void) move (0, 0);
  806.     (void) clrtoeol ();
  807.     (void) sprintf (lin,
  808.         "Confirm that you want to destroy the data base: (y,n)");
  809.     (void) addstr (lin);
  810.     (void) refresh();
  811.     ch = nmgetch();
  812.     if (ch != 'y' && ch != 'Y') 
  813.         return;
  814.     }
  815.  
  816.     f = openout(fname, &pid);
  817.  
  818.     if (f==0) {
  819.     error ("Can't create file \"%s\"", fname);
  820.     return;
  821.     }
  822.  
  823.     if ( tbl_style == TBL ) {
  824.     fprintf(f,".\\\" ** %s spreadsheet output \n.TS\n",progname);
  825.     fprintf(f,"tab(%c);\n",coldelim);
  826.     for (col=c0;col<=cn; col++) fprintf(f," n");
  827.     fprintf(f, ".\n");
  828.     }
  829.     else if ( tbl_style == LATEX ) {
  830.     fprintf(f,"%% ** %s spreadsheet output\n\\begin{tabular}{",progname);
  831.     for (col=c0;col<=cn; col++) fprintf(f,"c");
  832.     fprintf(f, "}\n");
  833.     coldelim = '&';
  834.     }
  835.     else if ( tbl_style == TEX ) {
  836.     fprintf(f,"{\t%% ** %s spreadsheet output\n\\settabs %d \\columns\n",
  837.         progname, cn-c0+1);
  838.     coldelim = '&';
  839.     }
  840.  
  841.     for (row=r0; row<=rn; row++) {
  842.     if ( tbl_style == TEX )
  843.         (void) fprintf (f, "\\+");
  844.     
  845.     for (p = &tbl[row][col=c0]; col<=cn; col++, p++) {
  846.         if (*p) {
  847.         char *s;
  848.         if ((*p)->flags&is_valid) {
  849.             (void) fprintf (f,"%.*f",precision[col],
  850.                 (*p)->v);
  851.         }
  852.         if (s = (*p)->label) {
  853.                 (void) fprintf (f,"%s",s);
  854.         }
  855.         }
  856.         if ( col < cn )
  857.         (void) fprintf(f,"%c",coldelim);
  858.     }
  859.     if ( tbl_style == LATEX ) {
  860.         if ( row < rn ) (void) fprintf (f, "\\\\");
  861.         }
  862.     else if ( tbl_style == TEX ) {
  863.         (void) fprintf (f, "\\cr");
  864.         }
  865.     (void) fprintf (f,"\n");
  866.     }
  867.  
  868.     if ( tbl_style == TBL )
  869.     (void) fprintf (f,".TE\n.\\\" ** end of %s spreadsheet output\n", progname);
  870.     else if ( tbl_style == LATEX )
  871.     (void) fprintf (f,"\\end{tabular}\n%% ** end of %s spreadsheet output\n", progname);
  872.     else if ( tbl_style == TEX )
  873.     (void) fprintf (f,"}\n%% ** end of %s spreadsheet output\n", progname);
  874.  
  875.     closeout(f, pid);
  876. }
  877.  
  878. struct enode *
  879. copye (e, Rdelta, Cdelta)
  880. register struct enode *e;
  881. int Rdelta, Cdelta;
  882. {
  883.     register struct enode *ret;
  884.     if (e==0) {
  885.         ret = 0;
  886.     } else if (e->op & REDUCE) {
  887.     int newrow, newcol;
  888.     ret = (struct enode *) xmalloc ((unsigned) sizeof (struct enode));
  889.     ret->op = e->op;
  890.     newrow=e->e.r.left.vf & FIX_ROW ? e->e.r.left.vp->row :
  891.                       e->e.r.left.vp->row+Rdelta;
  892.     newcol=e->e.r.left.vf & FIX_COL ? e->e.r.left.vp->col :
  893.                       e->e.r.left.vp->col+Cdelta;
  894.     ret->e.r.left.vp = lookat (newrow, newcol);
  895.     ret->e.r.left.vf = e->e.r.left.vf;
  896.     newrow=e->e.r.right.vf & FIX_ROW ? e->e.r.right.vp->row :
  897.                        e->e.r.right.vp->row+Rdelta;
  898.     newcol=e->e.r.right.vf & FIX_COL ? e->e.r.right.vp->col :
  899.                        e->e.r.right.vp->col+Cdelta;
  900.     ret->e.r.right.vp = lookat (newrow, newcol);
  901.     ret->e.r.right.vf = e->e.r.right.vf;
  902.     } else {
  903.     ret = (struct enode *) xmalloc ((unsigned) sizeof (struct enode));
  904.     ret->op = e->op;
  905.     switch (ret->op) {
  906.     case 'v':
  907.         {
  908.             int newrow, newcol;
  909.             newrow=e->e.v.vf & FIX_ROW ? e->e.v.vp->row :
  910.                          e->e.v.vp->row+Rdelta;
  911.             newcol=e->e.v.vf & FIX_COL ? e->e.v.vp->col :
  912.                          e->e.v.vp->col+Cdelta;
  913.             ret->e.v.vp = lookat (newrow, newcol);
  914.             ret->e.v.vf = e->e.v.vf;
  915.             break;
  916.         }
  917.     case 'k':
  918.         ret->e.k = e->e.k;
  919.         break;
  920.     case 'f':
  921.         ret->e.o.right = copye (e->e.o.right,0,0);
  922.         ret->e.o.left = 0;
  923.          break;
  924.     case '$':
  925.         ret->e.s = xmalloc((unsigned) strlen(e->e.s)+1);
  926.         (void) strcpy(ret->e.s, e->e.s);
  927.         break;
  928.     default:
  929.         ret->e.o.right = copye (e->e.o.right,Rdelta,Cdelta);
  930.         ret->e.o.left = copye (e->e.o.left,Rdelta,Cdelta);
  931.         break;
  932.     }
  933.     }
  934.     return ret;
  935. }
  936.  
  937. /*
  938.  * sync_refs and syncref are used to remove references to
  939.  * deleted struct ents.  Note that the deleted structure must still
  940.  * be hanging around before the call, but not referenced by an entry
  941.  * in tbl.  Thus the free_ent, fix_ent calls in sc.c
  942.  */
  943.  
  944. sync_refs ()
  945. {
  946.     register i,j;
  947.     register struct ent *p;
  948.     sync_ranges();
  949.     for (i=0; i<=maxrow; i++)
  950.     for (j=0; j<=maxcol; j++)
  951.         if ((p=tbl[i][j]) && p->expr)
  952.         syncref(p->expr);
  953. }
  954.  
  955.  
  956. syncref(e)
  957. register struct enode *e;
  958. {
  959.     if (e==0)
  960.     return;
  961.     else if (e->op & REDUCE) {
  962.      e->e.r.right.vp = lookat(e->e.r.right.vp->row, e->e.r.right.vp->col);
  963.      e->e.r.left.vp = lookat(e->e.r.left.vp->row, e->e.r.left.vp->col);
  964.     } else {
  965.     switch (e->op) {
  966.     case 'v':
  967.         e->e.v.vp = lookat(e->e.v.vp->row, e->e.v.vp->col);
  968.         break;
  969.     case 'k':
  970.         break;
  971.     case '$':
  972.         break;
  973.     default:
  974.         syncref(e->e.o.right);
  975.         syncref(e->e.o.left);
  976.         break;
  977.     }
  978.     }
  979. }
  980.  
  981. hiderow(arg)
  982. int arg;
  983. {
  984.     register int r1;
  985.     register int r2;
  986.  
  987.     r1 = currow;
  988.     r2 = r1 + arg - 1;
  989.     if (r1 < 0 || r1 > r2) {
  990.     error ("Invalid range");
  991.     return;
  992.     }
  993.     if (r2 > MAXROWS-2) {
  994.     error ("You can't hide the last row");
  995.     return;
  996.     }
  997.     FullUpdate++;
  998.     while (r1 <= r2)
  999.     row_hidden[r1++] = 1;
  1000. }
  1001.  
  1002. hidecol(arg)
  1003. int arg;
  1004. {
  1005.     register int c1;
  1006.     register int c2;
  1007.  
  1008.     c1 = curcol;
  1009.     c2 = c1 + arg - 1;
  1010.     if (c1 < 0 || c1 > c2) {
  1011.     error ("Invalid range");
  1012.     return;
  1013.     }
  1014.     if (c2 > MAXCOLS-2) {
  1015.     error ("You can't hide the last column");
  1016.     return;
  1017.     }
  1018.     FullUpdate++;
  1019.     while (c1 <= c2)
  1020.     col_hidden[c1++] = 1;
  1021. }
  1022.  
  1023. showrow(r1, r2)
  1024. int r1, r2;
  1025. {
  1026.     if (r1 < 0 || r1 > r2) {
  1027.     error ("Invalid range");
  1028.     return;
  1029.     }
  1030.     if (r2 > MAXROWS-1) {
  1031.     r2 = MAXROWS-1;
  1032.     }
  1033.     FullUpdate++;
  1034.     while (r1 <= r2)
  1035.     row_hidden[r1++] = 0;
  1036. }
  1037.  
  1038. showcol(c1, c2)
  1039. int c1, c2;
  1040. {
  1041.     if (c1 < 0 || c1 > c2) {
  1042.     error ("Invalid range");
  1043.     return;
  1044.     }
  1045.     if (c2 > MAXCOLS-1) {
  1046.     c2 = MAXCOLS-1;
  1047.     }
  1048.     FullUpdate++;
  1049.     while (c1 <= c2)
  1050.     col_hidden[c1++] = 0;
  1051. }
  1052.  
  1053. /* Open the output file, setting up a pipe if needed */
  1054.  
  1055. FILE *
  1056. openout(fname, rpid)
  1057. char *fname;
  1058. int *rpid;
  1059. {
  1060.     int pipefd[2];
  1061.     int pid;
  1062.     FILE *f;
  1063.  
  1064.     while (*fname && (*fname == ' '))  /* Skip leading blanks */
  1065.     fname++;
  1066.  
  1067.     if (*fname != '|') {        /* Open file if not pipe */
  1068.     *rpid = 0;
  1069.     return(fopen(fname, "w"));
  1070.     }
  1071.  
  1072.     fname++;                /* Skip | */
  1073.     if ( pipe (pipefd) < 0) {
  1074.     error("Can't make pipe to child");
  1075.     *rpid = 0;
  1076.     return(0);
  1077.     }
  1078.  
  1079.     deraw();
  1080. #ifdef VMS
  1081.     fprintf(stderr, "No son tasks available yet under VMS--sorry\n");
  1082. #else /* VMS */
  1083.  
  1084.     if ((pid=fork()) == 0)              /* if child  */
  1085.     {
  1086.     (void) close (0);              /* close stdin */
  1087.     (void) close (pipefd[1]);
  1088.     (void) dup (pipefd[0]);          /* connect to pipe input */
  1089.     (void) signal (SIGINT, SIG_DFL);      /* reset */
  1090.     (void) execl ("/bin/sh", "sh", "-c", fname, 0);
  1091.     exit (-127);
  1092.     }
  1093.     else                  /* else parent */
  1094.     {
  1095.     *rpid = pid;
  1096.     f = fdopen (pipefd[1], "w");
  1097.     if (f == 0)
  1098.     {
  1099.         (void) kill (pid, -9);
  1100.         error ("Can't fdopen output");
  1101.         (void) close (pipefd[1]);
  1102.         *rpid = 0;
  1103.         return(0);
  1104.     }
  1105.     }
  1106. #endif /* VMS */
  1107.     return(f);
  1108. }
  1109.  
  1110. closeout(f, pid)
  1111. FILE *f;
  1112. int pid;
  1113. {
  1114.     int temp;
  1115.  
  1116.     (void) fclose (f);
  1117.     if (pid) {
  1118.          while (pid != wait(&temp)) /**/;
  1119.      (void) printf("Press RETURN to continue ");
  1120.      (void) fflush(stdout);
  1121.      (void) nmgetch();
  1122.      goraw();
  1123.     }
  1124. }
  1125.  
  1126. copyent(n,p,dr,dc)
  1127.         register struct ent *n, *p;
  1128.         int dr, dc;
  1129. {
  1130.     if(!n||!p){error("internal error");return;}
  1131.     n -> v = p -> v;
  1132.     n -> flags = p -> flags;
  1133.     n -> expr = copye (p -> expr, dr, dc);
  1134.     n -> label = 0;
  1135.     if (p -> label) {
  1136.     n -> label = (char *)
  1137.         xmalloc  ((unsigned) (strlen (p -> label) + 1));
  1138.     (void) strcpy (n -> label, p -> label);
  1139.     }
  1140. }
  1141.  
  1142. write_fd (f, r0, c0, rn, cn)
  1143. register FILE *f;
  1144. int r0, c0, rn, cn;
  1145. {
  1146.     register struct ent **p;
  1147.     register r, c;
  1148.  
  1149.     (void) fprintf (f, "# This data file was generated by the Spreadsheet ");
  1150.     (void) fprintf (f, "Calculator.\n");
  1151.     (void) fprintf (f, "# You almost certainly shouldn't edit it.\n\n");
  1152.     print_options(f);
  1153.     for (c=0; c<MAXCOLS; c++)
  1154.     if (fwidth[c] != DEFWIDTH || precision[c] != DEFPREC)
  1155.         (void) fprintf (f, "format %s %d %d\n",coltoa(c),fwidth[c],precision[c]);
  1156.     for (c=c0; c<cn; c++) {
  1157.         if (col_hidden[c]) {
  1158.             (void) fprintf(f, "hide %s\n", coltoa(c));
  1159.         }
  1160.     }
  1161.     for (r=r0; r<=rn; r++) {
  1162.     if (row_hidden[r]) {
  1163.         (void) fprintf(f, "hide %d\n", r);
  1164.     }
  1165.     }
  1166.  
  1167.     write_range(f);
  1168.  
  1169.     if (mdir) 
  1170.         (void) fprintf(f, "mdir \"%s\"\n", mdir);
  1171.     for (r=r0; r<=rn; r++) {
  1172.     p = &tbl[r][c0];
  1173.     for (c=c0; c<=cn; c++, p++)
  1174.         if (*p) {
  1175.         if ((*p)->label) {
  1176.             edits(r,c);
  1177.             (void) fprintf(f, "%s\n",line);
  1178.         }
  1179.         if ((*p)->flags&is_valid) {
  1180.             editv (r, c);
  1181.             (void) fprintf (f, "%s\n",line);
  1182.         }
  1183.         }
  1184.     }
  1185. }
  1186.  
  1187. writefile (fname, r0, c0, rn, cn)
  1188. char *fname;
  1189. int r0, c0, rn, cn;
  1190. {
  1191.     register FILE *f;
  1192.     char save[1024];
  1193.     int pid;
  1194.  
  1195. #ifndef VMS
  1196.     if (Crypt) {
  1197.     return (cwritefile(fname, r0, c0, rn, cn));
  1198.     }
  1199. #endif /* VMS */
  1200.  
  1201.     if (*fname == 0) fname = &curfile[0];
  1202.  
  1203.     (void) strcpy(save,fname);
  1204.  
  1205.     f = openout(fname, &pid);
  1206.     if (f == 0) {
  1207.     error ("Can't create file \"%s\"", fname);
  1208.     return (-1);
  1209.     }
  1210.  
  1211.     write_fd(f, r0, c0, rn, cn);
  1212.     
  1213.     closeout(f, pid);
  1214.  
  1215.     if (!pid) {
  1216.         (void) strcpy(curfile, save);
  1217.         modflg = 0;
  1218.         error("File \"%s\" written.",curfile);
  1219.     }
  1220.  
  1221.     return (0);
  1222. }
  1223.  
  1224. readfile (fname,eraseflg)
  1225. char *fname;
  1226. int eraseflg;
  1227. {
  1228.     register FILE *f;
  1229.     char save[1024];
  1230.  
  1231.     if (*fname == '*' && mdir) { 
  1232.        (void) strcpy(save, mdir);
  1233.        *fname = '/';
  1234.        (void) strcat(save, fname);
  1235.     } else {
  1236.         if (*fname == 0)
  1237.         fname = &curfile[0];
  1238.         (void) strcpy(save,fname);
  1239.     }
  1240.  
  1241. #ifndef VMS
  1242.     if (Crypt)  {
  1243.     creadfile(save, eraseflg);
  1244.     return;
  1245.     }
  1246. #endif /* VMS */
  1247.  
  1248.     if (eraseflg && strcmp(fname,curfile) && modcheck(" first")) return;
  1249.  
  1250.     f = fopen (save, "r");
  1251.     if (f==0) {
  1252.     error ("Can't read file \"%s\"", save);
  1253.     return;
  1254.     }
  1255.  
  1256.     if (eraseflg) erasedb ();
  1257.  
  1258.     loading++;
  1259.     while (fgets(line,sizeof line,f)) {
  1260.     linelim = 0;
  1261.     if (line[0] != '#') (void) yyparse ();
  1262.     }
  1263.     --loading;
  1264.     (void) fclose (f);
  1265.     linelim = -1;
  1266.     modflg++;
  1267.     if (eraseflg) {
  1268.     (void) strcpy(curfile,save);
  1269.     modflg = 0;
  1270.     }
  1271.     EvalAll();
  1272. }
  1273.  
  1274. erasedb ()
  1275. {
  1276.     register r, c;
  1277.     for (c = 0; c<=maxcol; c++) {
  1278.     fwidth[c] = DEFWIDTH;
  1279.     precision[c] = DEFPREC;
  1280.     }
  1281.  
  1282.     for (r = 0; r<=maxrow; r++) {
  1283.     register struct ent **p = &tbl[r][0];
  1284.     for (c=0; c++<=maxcol; p++)
  1285.         if (*p) {
  1286.         if ((*p)->expr) efree ((*p) -> expr);
  1287.         if ((*p)->label) xfree ((char *)((*p) -> label));
  1288.         xfree ((char *)(*p));
  1289.         *p = 0;
  1290.         }
  1291.     }
  1292.     maxrow = 0;
  1293.     maxcol = 0;
  1294.     clean_range();
  1295.     FullUpdate++;
  1296. }
  1297.  
  1298. backcol(arg)
  1299.     int arg;
  1300. {
  1301.     while (--arg>=0) {
  1302.     if (curcol)
  1303.         curcol--;
  1304.     else
  1305.         {error ("At column A"); break;}
  1306.     while(col_hidden[curcol] && curcol)
  1307.         curcol--;
  1308.     }
  1309. }
  1310.  
  1311. forwcol(arg)
  1312.     int arg;
  1313. {
  1314.     while (--arg>=0) {
  1315.     if (curcol < MAXCOLS - 1)
  1316.         curcol++;
  1317.     else
  1318.         {error ("The table can't be any wider"); break;}
  1319.     while(col_hidden[curcol]&&(curcol<MAXCOLS-1))
  1320.         curcol++;
  1321.     }
  1322. }
  1323.  
  1324. forwrow(arg)
  1325.     int arg;
  1326. {
  1327.     while (--arg>=0) {
  1328.     if (currow < MAXROWS - 1)
  1329.         currow++;
  1330.     else
  1331.         {error ("The table can't be any longer"); break;}
  1332.     while (row_hidden[currow]&&(currow<MAXROWS-1))
  1333.         currow++;
  1334.     }
  1335. }
  1336.  
  1337. backrow(arg)
  1338.     int arg;
  1339. {
  1340.     while (--arg>=0) {
  1341.     if (currow)
  1342.         currow--;
  1343.     else
  1344.         {error ("At row zero"); break;}
  1345.     while (row_hidden[currow] && currow)
  1346.         currow--;
  1347.     }
  1348. }
  1349.  
  1350.  
  1351. /*
  1352.  * Show a cell's label string or expression value.  May overwrite value if
  1353.  * there is one already displayed in the cell.  Created from old code in
  1354.  * update(), copied with minimal changes.
  1355.  */
  1356.  
  1357. showstring (string, leftflush, hasvalue, row, col, nextcolp, mxcol, fieldlenp, r, c)
  1358.     char *string;    /* to display */
  1359.     int leftflush;    /* or rightflush */
  1360.     int hasvalue;    /* is there a numeric value? */
  1361.     int row, col;    /* spreadsheet location */
  1362.     int *nextcolp;    /* value returned through it */
  1363.     int mxcol;        /* last column displayed? */
  1364.     int *fieldlenp;    /* value returned through it */
  1365.     int r, c;        /* screen row and column */
  1366. {
  1367.     register int nextcol  = *nextcolp;
  1368.     register int fieldlen = *fieldlenp;
  1369.  
  1370.     char field[1024];
  1371.     int  slen;
  1372.     char *start, *last;
  1373.     register char *fp;
  1374.     struct ent *nc;
  1375.  
  1376.     /* This figures out if the label is allowed to
  1377.        slop over into the next blank field */
  1378.  
  1379.     slen = strlen (string);
  1380.     while ((slen > fieldlen) && (nextcol <= mxcol) &&
  1381.        !((nc = lookat (row, nextcol)) -> flags & is_valid) &&
  1382.        !(nc->label)) {
  1383.  
  1384.     if (! col_hidden [nextcol])
  1385.         fieldlen += fwidth [nextcol];
  1386.  
  1387.     nextcol++;
  1388.     }
  1389.     if (slen > fieldlen)
  1390.     slen = fieldlen;
  1391.  
  1392.     /* Now justify and print */
  1393.     start = leftflush ? field : field + fieldlen - slen;
  1394.     last = field+fieldlen;
  1395.     fp = field;
  1396.     while (fp < start)
  1397.     *fp++ = ' ';
  1398.     while (slen--)
  1399.     *fp++ = *string++;
  1400.     if ((! hasvalue) || fieldlen != fwidth[col]) 
  1401.     while (fp < last)
  1402.         *fp++ = ' ';
  1403.     *fp = 0;
  1404. #ifdef VMS
  1405.     mvaddstr(r, c, field);    /* this is a macro */
  1406. #else
  1407.     (void) mvaddstr(r, c, field);
  1408. #endif
  1409.  
  1410.     *nextcolp  = nextcol;
  1411.     *fieldlenp = fieldlen;
  1412. }
  1413. etype(e)
  1414. register struct enode *e;
  1415. {
  1416.  
  1417.     if (e==0) return 0;
  1418.     switch (e->op) {
  1419.     case '+': case '-': case '*': case '/': case '%': case '^':
  1420.     case '<': case '=': case '>': case '&': case '|': case 'm':
  1421.     case '~': case 'k': case INDEX:
  1422.     case REDUCE | '+': case REDUCE | '*': case REDUCE | 'a':
  1423.     case REDUCE | 's': case REDUCE | MAX: case REDUCE | MIN:
  1424.     case ACOS: case ASIN: case ATAN: case ATAN2: case CEIL:
  1425.     case COS: case EXP: case FABS: case FLOOR: case HYPOT:
  1426.     case LOG: case LOG10: case POW: case SIN: case SQRT:
  1427.     case TAN: case DTR: case RTD: case RND: case FV: case PV:
  1428.     case PMT: case HOUR: case MINUTE: case SECOND: case MONTH:
  1429.     case DAY: case YEAR: case NOW: case STON: case EQS:
  1430.     case LMAX: case LMIN: case NVAL: case LOOKUP:
  1431.         return (NUM);
  1432.  
  1433.     case O_SCONST: case '#': case DATE: case FMT: case STINDEX:
  1434.     case EXT: case SVAL: case SUBSTR:
  1435.         return (STR);
  1436.  
  1437.     case 'f':  case '?':
  1438.         return(etype(e->e.o.left));
  1439.  
  1440.     case O_VAR: {
  1441.     register struct ent *p;
  1442.     p = e->e.v.vp;
  1443.     if (p->expr) 
  1444.         return(p->flags & is_strexpr ? STR : NUM);
  1445.     else if (p->label)
  1446.         return(STR);
  1447.     else
  1448.         return(NUM);
  1449.     }
  1450.  
  1451.     default:
  1452.     return(NUM);
  1453.     }
  1454. }
  1455. \SHAR\EOF\
  1456. else
  1457.   echo "will not over write ./cmds.c"
  1458. fi
  1459. if [ `wc -c ./cmds.c | awk '{printf $1}'` -ne 27705 ]
  1460. then
  1461. echo `wc -c ./cmds.c | awk '{print "Got " $1 ", Expected " 27705}'`
  1462. fi
  1463. if `test ! -s ./range.c`
  1464. then
  1465. echo "Extracting ./range.c"
  1466. cat > ./range.c << '\SHAR\EOF\'
  1467.  
  1468. /*    SC    A Spreadsheet Calculator
  1469.  *        Range Manipulations
  1470.  *
  1471.  *              Robert Bond, 4/87
  1472.  *
  1473.  *        $Revision: 6.1 $
  1474.  */
  1475.  
  1476. #include <stdio.h>
  1477. #include <curses.h>
  1478. #include <ctype.h>
  1479. #include "sc.h"
  1480.  
  1481. #ifdef BSD42
  1482. #include <strings.h>
  1483. #else
  1484. #ifndef SYSIII
  1485. #include <string.h>
  1486. #endif
  1487. #endif
  1488.  
  1489. static struct range *rng_base;
  1490.  
  1491. add_range(name, left, right, is_range)
  1492. char *name;
  1493. struct ent_ptr left, right;
  1494. int is_range;
  1495. {
  1496.     struct range *r;
  1497.     register char *p;
  1498.     int len;
  1499.     int minr,minc,maxr,maxc;
  1500.     int minrf, mincf, maxrf, maxcf;
  1501.  
  1502.     if (left.vp->row < right.vp->row) {
  1503.     minr = left.vp->row; minrf = left.vf & FIX_ROW;
  1504.     maxr = right.vp->row; maxrf = right.vf & FIX_ROW;
  1505.     } else {
  1506.     minr = right.vp->row; minrf = right.vf & FIX_ROW;
  1507.     maxr = left.vp->row; maxrf = right.vf & FIX_ROW;
  1508.     } 
  1509.  
  1510.     if (left.vp->col < right.vp->col) {
  1511.     minc = left.vp->col; mincf = left.vf & FIX_COL;
  1512.     maxc = right.vp->col; maxcf = right.vf & FIX_COL;
  1513.     } else {
  1514.     minc = right.vp->col; mincf = right.vf & FIX_COL;
  1515.     maxc = left.vp->col; maxcf = left.vf & FIX_COL;
  1516.     } 
  1517.  
  1518.     left.vp = lookat(minr, minc);
  1519.     left.vf = minrf | mincf;
  1520.     right.vp = lookat(maxr, maxc);
  1521.     right.vf = maxrf | maxcf;
  1522.  
  1523.     if (find_range(name, strlen(name), (struct ent *)0, (struct ent *)0)) {
  1524.     error("Error: range name already defined");
  1525.     xfree(name);
  1526.     return;
  1527.     }
  1528.  
  1529.     if (strlen(name) <= 2) {
  1530.     error("Invalid range name - too short");
  1531.     xfree(name);
  1532.     return;
  1533.     }
  1534.  
  1535.     for(p=name, len=0; *p; p++, len++)
  1536.     if (!((isalpha(*p) && (len<=2)) ||
  1537.         ((isdigit(*p) || isalpha(*p) || (*p == '_')) && (len>2)))) {
  1538.         error("Invalid range name - illegal combination");
  1539.         xfree(name);
  1540.         return;
  1541.         }
  1542.  
  1543.     r = (struct range *)xmalloc((unsigned)sizeof(struct range));
  1544.     r->r_name = name;
  1545.     r->r_left = left;
  1546.     r->r_right = right;
  1547.     r->r_next = rng_base;
  1548.     r->r_prev = 0;
  1549.     r->r_is_range = is_range;
  1550.     if (rng_base)
  1551.         rng_base->r_prev = r;
  1552.     rng_base = r;
  1553. }
  1554.  
  1555. del_range(left, right)
  1556. struct ent *left, *right;
  1557. {
  1558.     register struct range *r;
  1559.     int minr,minc,maxr,maxc;
  1560.  
  1561.     minr = left->row < right->row ? left->row : right->row;
  1562.     minc = left->col < right->col ? left->col : right->col;
  1563.     maxr = left->row > right->row ? left->row : right->row;
  1564.     maxc = left->col > right->col ? left->col : right->col;
  1565.  
  1566.     left = lookat(minr, minc);
  1567.     right = lookat(maxr, maxc);
  1568.  
  1569.     if (!(r = find_range((char *)0, 0, left, right))) 
  1570.     return;
  1571.  
  1572.     if (r->r_next)
  1573.         r->r_next->r_prev = r->r_prev;
  1574.     if (r->r_prev)
  1575.         r->r_prev->r_next = r->r_next;
  1576.     else
  1577.     rng_base = r->r_next;
  1578.     xfree((char *)(r->r_name));
  1579.     xfree((char *)r);
  1580. }
  1581.  
  1582. clean_range()
  1583. {
  1584.     register struct range *r;
  1585.     register struct range *nextr;
  1586.  
  1587.     r = rng_base;
  1588.     rng_base = 0;
  1589.  
  1590.     while (r) {
  1591.     nextr = r->r_next;
  1592.     xfree((char *)(r->r_name));
  1593.     xfree((char *)r);
  1594.     r = nextr;
  1595.     }
  1596. }
  1597.  
  1598. /* Match on name or lmatch, rmatch */
  1599.  
  1600. struct range *
  1601. find_range(name, len, lmatch, rmatch)
  1602. char *name;
  1603. int len;
  1604. struct ent *lmatch;
  1605. struct ent *rmatch;
  1606. {
  1607.     struct range *r;
  1608.     register char *rp, *np;
  1609.     register int c;
  1610.  
  1611.     if (name) {
  1612.     for (r = rng_base; r; r = r->r_next) {
  1613.         for (np = name, rp = r->r_name, c = len;
  1614.          c && *rp && (*rp == *np);
  1615.          rp++, np++, c--) /* */;
  1616.         if (!c && !*rp)
  1617.         return(r);
  1618.     }
  1619.     return(0);
  1620.     }
  1621.  
  1622.     for (r = rng_base; r; r= r->r_next) {
  1623.     if ((lmatch == r->r_left.vp) && (rmatch == r->r_right.vp)) 
  1624.         return(r);
  1625.     }
  1626.     return(0);
  1627. }
  1628.  
  1629. sync_ranges()
  1630. {
  1631.     register struct range *r;
  1632.  
  1633.     r = rng_base;
  1634.     while(r) {
  1635.     r->r_left.vp = lookat(r->r_left.vp->row, r->r_left.vp->col);
  1636.     r->r_right.vp = lookat(r->r_right.vp->row, r->r_right.vp->col);
  1637.     r = r->r_next;
  1638.     }
  1639. }
  1640.  
  1641. write_range(f)
  1642. FILE *f;
  1643. {
  1644.     register struct range *r;
  1645.  
  1646.     for (r = rng_base; r; r = r->r_next) {
  1647.     (void) fprintf(f, "define \"%s\" %s%s%s%d",
  1648.             r->r_name,
  1649.             r->r_left.vf & FIX_COL ? "$":"",
  1650.             coltoa(r->r_left.vp->col), 
  1651.             r->r_left.vf & FIX_ROW ? "$":"",
  1652.             r->r_left.vp->row);
  1653.     if (r->r_is_range)
  1654.         (void) fprintf(f, ":%s%s%s%d\n",
  1655.                 r->r_right.vf & FIX_COL ? "$":"",
  1656.                 coltoa(r->r_right.vp->col), 
  1657.                 r->r_right.vf & FIX_ROW ? "$":"",
  1658.                 r->r_right.vp->row);
  1659.     else
  1660.         (void) fprintf(f, "\n");
  1661.     }
  1662. }
  1663.  
  1664. list_range(f)
  1665. FILE *f;
  1666. {
  1667.     register struct range *r;
  1668.  
  1669.     (void) fprintf(f, "%-30s %s\n\n","Name","Definition");
  1670.  
  1671.     for (r = rng_base; r; r = r->r_next) {
  1672.     (void) fprintf(f, "%-30s %s%s%s%d",
  1673.                 r->r_name,
  1674.                 r->r_left.vf & FIX_COL ? "$":"",
  1675.                 coltoa(r->r_left.vp->col), 
  1676.                 r->r_left.vf & FIX_ROW ? "$":"",
  1677.                 r->r_left.vp->row);
  1678.     if (r->r_is_range)
  1679.         (void) fprintf(f, ":%s%s%s%d\n",
  1680.                 r->r_right.vf & FIX_COL ? "$":"",
  1681.                 coltoa(r->r_right.vp->col), 
  1682.                 r->r_right.vf & FIX_ROW ? "$":"",
  1683.                 r->r_right.vp->row);
  1684.     else
  1685.         (void) fprintf(f, "\n");
  1686.     }
  1687. }
  1688.  
  1689. char *
  1690. v_name(row, col)
  1691. int row, col;
  1692. {
  1693.     struct ent *v;
  1694.     struct range *r;
  1695.     static char buf[20];
  1696.  
  1697.     v = lookat(row, col);
  1698.     if (r = find_range((char *)0, 0, v, v)) {
  1699.     return(r->r_name);
  1700.     } else {
  1701.         (void) sprintf(buf, "%s%d", coltoa(col), row);
  1702.     return(buf);
  1703.     }
  1704. }
  1705.  
  1706. char *
  1707. r_name(r1, c1, r2, c2)
  1708. int r1, c1, r2, c2;
  1709. {
  1710.     struct ent *v1, *v2;
  1711.     struct range *r;
  1712.     static char buf[100];
  1713.  
  1714.     v1 = lookat(r1, c1);
  1715.     v2 = lookat(r2, c2);
  1716.     if (r = find_range((char *)0, 0, v1, v2)) {
  1717.     return(r->r_name);
  1718.     } else {
  1719.         (void) sprintf(buf, "%s", v_name(r1, c1));
  1720.     (void) sprintf(buf+strlen(buf), ":%s", v_name(r2, c2));
  1721.     return(buf);
  1722.     }
  1723. }
  1724.  
  1725. are_ranges()
  1726. {
  1727. return (rng_base != 0);
  1728. }
  1729. \SHAR\EOF\
  1730. else
  1731.   echo "will not over write ./range.c"
  1732. fi
  1733. if [ `wc -c ./range.c | awk '{printf $1}'` -ne 5535 ]
  1734. then
  1735. echo `wc -c ./range.c | awk '{print "Got " $1 ", Expected " 5535}'`
  1736. fi
  1737. if `test ! -s ./help.c`
  1738. then
  1739. echo "Extracting ./help.c"
  1740. cat > ./help.c << '\SHAR\EOF\'
  1741. /*
  1742.  * Help functions for sc 
  1743.  * R. Bond, 1988
  1744.  * $Revision: 6.2 $
  1745.  */
  1746.  
  1747. #include <curses.h>
  1748. #include "sc.h"
  1749.  
  1750. char *intro[] = {
  1751. " ",
  1752. " Overview:",
  1753. " ",
  1754. " A:   This overview",
  1755. " B:   Options",
  1756. " C:   Cursor movement commands",
  1757. " D:   Cell entry and editing commands",
  1758. " E:   File commands",
  1759. " F:   Row and column commands",
  1760. " G:   Range commands",
  1761. " H:   Miscellaneous commands",
  1762. " I:   Variable names/Expressions",
  1763. " J:   Range functions",
  1764. " K:   Numeric functions",
  1765. " L:   String functions",
  1766. " M:   Financial functions",
  1767. " N:   Time and date functions",
  1768. " ",
  1769. " Q:   Return to main spreadsheet",
  1770. 0
  1771. };
  1772.  
  1773. char *options[] = {
  1774. " ",
  1775. " B: Options",
  1776. " ",
  1777. "     ^To  Toggle options. Toggle one option selected by o:",
  1778. " ",
  1779. "          a    Recalculate automatically or on ``@'' commands.",
  1780. "          c    Current cell highlighting enable/disable.",  
  1781. "          e    External function execution enable/disable.",
  1782. "          n    If enabled, a digit starts a numeric value.",
  1783. "          t    Top line display enable/disable.",
  1784. "          x    Encrypt/decrypt database and listing files.",
  1785. "          $    Dollar prescale.  If enabled, all numeric constants.",
  1786. "               (not expressions) entered are multipled by 0.01.",
  1787. " ",
  1788. "     S    Set options.  Options include:",
  1789. " ",
  1790. "          byrows        Recalculate in row order. (default)",
  1791. "          bycols        Recalculate in column order.",
  1792. "          iterations=n  Set the number of iterations allowed. (10)",
  1793. "          tblstyle=xx   Set ``T'' output style to:",
  1794. "                        0 (none), tex, latex, or tbl.",
  1795. 0
  1796. };
  1797.  
  1798. char *cursor[] = {
  1799. " ",
  1800. " C: Cell cursor movement (always OK):",
  1801. " ",
  1802. "     ^N ^P ^B ^F Down, up, back, forward",
  1803. "     ^Ed         Go to end of range.  Follow ^E by a direction indicator",
  1804. "                 such as ^P or j.",
  1805. "     Arrow keys (if the terminal and termcap support them.)",
  1806. " ",
  1807. " Cell cursor movement if no prompt active:",
  1808. "     j,k,l,h    Down, up, right, left",
  1809. "     SPACE      Forward",
  1810. "     ^H         Back",
  1811. "     TAB        Forward, otherwise starts/ends a range",
  1812. "     ^          Up to row 0 of the current column.",
  1813. "     #          Down to the last valid row of the current column.",
  1814. "     0          Back to column A.  Preface with ^U if numeric mode.",
  1815. "     $          Forward to the last valid column of the current row.",
  1816. "     b          Back then up to the previous valid cell.",
  1817. "     w          Forward then down to the next valid cell.",
  1818. "     g          Go to a cell.  Cell name, range name, quoted string,",
  1819. "                or a number specify which cell.",
  1820. 0
  1821. };
  1822.  
  1823.  
  1824. char *cell[] = {
  1825. " ",
  1826. " D: Cell entry and editing commands:",
  1827. " ",
  1828. "     =    Enter a numeric constant or expression.",
  1829. "     <    Enter a left justified string or string expression.",
  1830. "     \",>  Enter a right justified string or string expression.",
  1831. "     e    Edit the current cell's numeric value.",
  1832. "     E    Edit the current cell's string part.",
  1833. "     x    Clear the current cell.",
  1834. "     c    Copy the last marked cell to the current cell.",
  1835. "     m    Mark a cell to be used as the source for ``c''",
  1836. "     +    Increment numeric part",
  1837. "     -    Decrement numeric part",
  1838. " ",
  1839. "     In numeric mode, a decimal digit, ``+'', ``-'', and ``.'' all start",
  1840. "     a new numeric constant or expression.",
  1841. 0
  1842. };
  1843.  
  1844.  
  1845. char *file[] = {
  1846. " ",
  1847. " E: File commands:",
  1848. " ",
  1849. "     G    Get a new database from a file. ",
  1850. "     M    Merge a new file into the current database.",
  1851. "     P    Put the current database into a file.",
  1852. "     W    Write a listing of the current database into a file in",
  1853. "          a form that matches its appearance on the screen.",
  1854. "     T    Write a listing of the current database to a file, but",
  1855. "          put delimiters between each pair of fields.",
  1856. "          Optionally brackets output with control lines for ``tbl'',",
  1857. "          ``LaTeX'', or ``TeX''.",
  1858. " ",
  1859. "     If encryption mode is set, file I/O will be encrypted/decrypted.",
  1860. "     ``\"| program\"'' for a file name will pipe (unencrypted) output to",
  1861. "     a program for Put, Write and Table.  If a cell name is used",
  1862. "     as the file name, the cell's string part will be used as the",
  1863. "     file name.",
  1864. 0
  1865. };
  1866.  
  1867.  
  1868. char *row[] = {
  1869. " ",
  1870. " F: Row and column commands:",
  1871. " ",
  1872. "     ir, ic      Insert a new, empty row (column)",
  1873. "     ar, ac      Append a new copy of the current row (column)",
  1874. "     dr, dc      Delete the current row (column)",
  1875. "     pr, pc, pm  Pull deleted cells back into the spreadsheet",
  1876. "                 Insert rows, columns or merge the cells.",
  1877. "     vr, vc      Remove expressions from the affected rows (columns),",
  1878. "                 leaving only the values.",
  1879. "     zr, zc      Hide (``zap'') the current row (column)",
  1880. "     sr, sc      Show hidden rows (columns)",
  1881. "     f           Set the output format to be used with the values of",
  1882. "                 each cell in this column.  Enter field width and",
  1883. "                 number of fractional digits.  A preceding count can be",
  1884. "                 used to change more than one column.",
  1885. " ",
  1886. "     Commands which move or copy cells also modify the row and column ",
  1887. "     references in the new cell expressions.  Use ``fixed'' or the",
  1888. "     ``$'' style cell reference to supress the change.",
  1889. 0
  1890. };
  1891.  
  1892.  
  1893. char *range[] = {
  1894. " ",
  1895. " G: Range commands:",
  1896. " ",
  1897. "     /x   Clear a range. ",
  1898. "     /v   Remove the expressions from a range of cells, leaving ",
  1899. "          just the values.",
  1900. "     /c   Copy a source range to a destination range.",
  1901. "     /f   Fill a range with constant values starting with a given",
  1902. "          value and increasing by a given increment.",
  1903. "     /d   Assign a name to a cell or a range of cells.  Give the",
  1904. "          the name, surrounded by quotes, and either a cell name such",
  1905. "          as ``A10'' or a range such as ``a1:b20''.",
  1906. "     /s   Shows the currently defined range names.  Pipe output to",
  1907. "          sort, then to less.",
  1908. "     /u   Use this command to undefine a previously defined range",
  1909. "          name.",
  1910. " ",
  1911. "     Range operations affect a rectangular region on the screen",
  1912. "     defined by the upper left and lower right cells in the region.",
  1913. "     A range is specified by giving the cell names separated by ``:'',",
  1914. "     such as ``a20:k52''.  Another way to refer to a range is to use",
  1915. "     a name previously defined using ``/d''.",
  1916. 0
  1917. };
  1918.  
  1919.  
  1920. char *misc[] = {
  1921. " ",
  1922. " H: Miscellaneous commands:",
  1923. " ",
  1924. "     Q q ^C   Exit from the program.",
  1925. "     ^G ESC   Abort entry of the current command.",
  1926. "     ?        Help",
  1927. "     !        Shell escape.  Enter a command to run.  ``!!'' repeats",
  1928. "              the last command.  Just ``!'' starts an interactive shell.",
  1929. "     ^L       Redraw the screen.",
  1930. "     ^R       Redraw the screen.  Highlight cells with values but no",
  1931. "              expressions.",
  1932. "     ^X       Redraw the screen.  Show formulas, not values.",
  1933. "     @        Recalculate the spreadsheet.",
  1934. "     ^V       Type, in the command line, the name of the current cell.",
  1935. "     ^W       Type, in the command line, the current cell's expression.",
  1936. "     ^A       Type, in the command line, the current cell's numeric value.",
  1937. "     TAB      When the character cursor is on the top line TAB can be used",
  1938. "              to start or stop the display of the default range.",
  1939. 0
  1940. };
  1941.  
  1942. char *var[] = {
  1943. " ",
  1944. " I: Variable names:",
  1945. " ",
  1946. "     K20    Row and column can vary on copies.",
  1947. "     $K$20  Row and column stay fixed on copies.",
  1948. "     $K20   Row can vary; column stays fixed on copies.",
  1949. "     K$20   Row stays fixed; column can vary on copies.",
  1950. "     fixed  holds following expession fixed on copies.",
  1951. "     Cells and ranges can also be assigned a symbolic name via the",
  1952. "     range command ``/d''.",
  1953. " ",
  1954. " Expressions:",
  1955. "     -e      Negation                e<=e  Less than or equal",
  1956. "     e+e     Addition                e=e   Equal",
  1957. "     e-e     Subtraction             e!=e  Not Equal",
  1958. "     e*e     Multiplication          e>=e  Greater than or equal",
  1959. "     e/e     Division                e>e  Greater than",
  1960. "     e%e     Modulo                  e<e  Less than",
  1961. "     e^e     Exponentiation          e&e  Boolean operator AND.",
  1962. "     ~e      Boolean operator NOT    e|e     Boolean operator OR",
  1963. "     e?e1:e2 Conditional: If the e is non zero then then e1, otherwise e2.",
  1964. "     Terms may be constants, variable names, and parenthesized expressions.",
  1965. 0
  1966. };
  1967.  
  1968. char *rangef[] = {
  1969. " ",
  1970. " J: Range functions:",
  1971. " ",
  1972. "     @sum(r)           Sum all valid cells in the range.",
  1973. "     @prod(r)          Multiply together all valid cells in the range.",
  1974. "     @avg(r)           Average all valid cells in range.",
  1975. "     @max(r)           Return the maximum value in the range.",
  1976. "     @min(r)           Return the minimum value in the range.",
  1977. "                       See also the numeric versions of max and min.",
  1978. "     @stddev(r)        Return the sample standard deviation of ",
  1979. "                       the cells in the range.",
  1980. "     @index(e,r)       Return the numeric value of the cell at index e",
  1981. "                       into range r.",
  1982. "     @stindex(e,r)     Return the string value of the cell at index e",
  1983. "                       into range r.",
  1984. "     @lookup(e,r)      Search through the range r for a value that",
  1985. "                       matches e.  The value returned is that from the",
  1986. "                       next row and the same column as the match, if",
  1987. "                       the range was a single row, or the value from",
  1988. "                       the next column and the same row as the match if",
  1989. "                       the range was a single column.",
  1990. 0
  1991. };
  1992.  
  1993. char *numericf[] = {
  1994. " ",
  1995. " K: Numeric functions:",
  1996. " ",
  1997. "     @atan2(e1,e2)     Arc tangent of e1/e2.",
  1998. "     @ceil(e)          Smallest integer not less than e.",
  1999. "     @eqs(se1,se2)     1 if string expr se1 has the same value as se2.",
  2000. "     @exp(e)           Exponential function of e.",
  2001. "     @fabs(e)          Absolute value of e.",
  2002. "     @floor(e)         The largest integer not greater than e.",
  2003. "     @hypot(x,y)       Sqrt(x*x+y*y).",
  2004. "     @max(e1,e2,...)   The maximum of the values of the e's.",
  2005. "     @min(e1,e2,...)   The minimum of the values of the e's",
  2006. "     @nval(se,e)       The numeric value of a named cell.",
  2007. "     pi                A constant quite close to pi.",
  2008. "     @pow(e1,e2)       e1 raised to the power of e2.",
  2009. "     @rnd(e)           Round e to the nearest integer.",
  2010. "     @sqrt(e)          Square root of e.",
  2011. "     @ston(se)         Convert string expr se to a numeric",
  2012. "     @ln(e)   @log(e)           Natural/base 10 logarithm of e.",
  2013. "     @dtr(e)  @rtd(e)           Convert degrees to/from radians.",
  2014. "     @cos(e)  @sin(e)  @tan(e)  Trig functions of radian arguments.",
  2015. "     @asin(e) @acos(e) @atan(e) Inverse trig function.",
  2016. 0
  2017. };
  2018.  
  2019. char *stringf[] = {
  2020. " ",
  2021. " L: String functions:",
  2022. " ",
  2023. "     #                 Concatenate strings.  For example, the",
  2024. "                       string expression ``A0 # \"zy dog\"'' yields",
  2025. "                       ``the lazy dog'' if A0 is ``the la''.",
  2026. "     @substr(se,e1,e2) Extract characters e1 through e2 from the",
  2027. "                       string expression se.  For example,",
  2028. "                       ``@substr(\"Nice jacket\" 4, 7)'' yields ",
  2029. "                       ``e jac''.",
  2030. "     @fmt(se,e)        Convert a number to a string using sprintf(3).",
  2031. "                       For example,  ``@fmt(\"*%6.3f*\",10.5)'' yields",
  2032. "                       ``*10.500*''.  Use formats are e, E, f, g, and G.", 
  2033. "     @sval(se,e)       Return the string value of a cell selected by name.",
  2034. "     @ext(se,e)        Call an external function (program or",
  2035. "                       script).  Convert e to a string and append it",
  2036. "                       to the command line as an argument.  @ext yields",
  2037. "                       a string: the first line printed to standard",
  2038. "                       output by the command.",
  2039. "     String expressions are made up of constant strings (characters",
  2040. "     surrounded by quotes), variables, and string functions.",
  2041. 0
  2042. };
  2043.  
  2044.  
  2045. char *finf[] = {
  2046. " ",
  2047. " M: Financial functions:",
  2048. " ",
  2049. "     @pmt(e1,e2,e3)    @pmt(60000,.01,360) computes the monthly",
  2050. "                       payments for a $60000 mortgage at 12%",
  2051. "                       annual interest (.01 per month) for 30",
  2052. "                       years (360 months).",
  2053. " ",
  2054. "     @fv(e1,e2,e3)     @fv(100,.005,36) computes the future value",
  2055. "                       for of 36 monthly payments of $100 at 6%",
  2056. "                       interest (.005 per month).  It answers the",
  2057. "                       question:  ``How much will I have in 2",
  2058. "                       years if I deposit $100 per month in a",
  2059. "                       savings account paying 6% interest com-",
  2060. "                       pounded monthly?''",
  2061. " ",
  2062. "     @pv(e1,e2,e3)     @pv(1000,.015,36) computes the present",
  2063. "                       value of an a ordinary annuity of 36",
  2064. "                       monthly payments of $1000 at 18% annual",
  2065. "                       interest.  It answers the question: ``How",
  2066. "                       much can I borrow at 18% for 30 years if I",
  2067. "                       pay $1000 per month?''",
  2068. 0
  2069. };
  2070.  
  2071.  
  2072. char *timef[] = {
  2073. " ",
  2074. " N: Time and date functions:",
  2075. " ",
  2076. "     @now              Return the current time encoded as the",
  2077. "                       number of seconds since December 31, 1969,",
  2078. "                       midnight, GMT.",
  2079. " ",
  2080. "     All of the following take an argument expressed in seconds:",
  2081. " ",
  2082. "     @date(e)          Convert the time in seconds to a date",
  2083. "                       string 24 characters long in the following",
  2084. "                       form: ``Sun Sep 16 01:03:52 1973''.  Note",
  2085. "                       that you can extract pieces of this fixed format",
  2086. "                       string with @substr.",
  2087. "     @year(e)          Return the year.  Valid years begin with 1970.",
  2088. "     @month(e)         Return the month: 1 (Jan) to 12 (Dec).",
  2089. "     @day(e)           Return the day of the month: 1 to 31.",
  2090. "     @hour(e)          Return the number of hours since midnight: 0 to 23.",
  2091. "     @minute(e)        Return the number of minutes since the",
  2092. "                       last full hour: 0 to 59.",
  2093. "     @second(e)        Return the number of seconds since the",
  2094. "                       last full minute: 0 to 59.",
  2095. 0
  2096. };
  2097.  
  2098. help()
  2099. {
  2100.     int option;
  2101.     char **ns = intro;
  2102.  
  2103.     while((option = pscreen(ns)) != 'q' && option != 'Q') {
  2104.         switch (option) {
  2105.     case 'a': case 'A': ns = intro; break;
  2106.     case 'b': case 'B': ns = options; break;
  2107.     case 'c': case 'C': ns = cursor; break;
  2108.     case 'd': case 'D': ns = cell; break;
  2109.     case 'e': case 'E': ns = file; break;
  2110.     case 'f': case 'F': ns = row; break;
  2111.     case 'g': case 'G': ns = range; break;
  2112.     case 'h': case 'H': ns = misc; break;
  2113.     case 'i': case 'I': ns = var; break;
  2114.     case 'j': case 'J': ns = rangef; break;
  2115.     case 'k': case 'K': ns = numericf; break;
  2116.     case 'l': case 'L': ns = stringf; break;
  2117.     case 'm': case 'M': ns = finf; break;
  2118.     case 'n': case 'N': ns = timef; break;
  2119.     default: ns = intro; break;
  2120.     }
  2121.     }
  2122.     FullUpdate++;
  2123.     (void) move(1,0);
  2124.     (void) clrtobot();
  2125. }
  2126.  
  2127. pscreen(screen)
  2128. char *screen[];
  2129. {
  2130.     int line;
  2131.     int dbline;
  2132.  
  2133.     (void) move(1,0);
  2134.     (void) clrtobot();
  2135.     dbline = 1;
  2136.     for (line = 0; screen[line]; line++) {
  2137.     (void) move(dbline++, 4);
  2138.     (void) addstr (screen[line]);
  2139.     (void) clrtoeol();
  2140.     }
  2141.     (void) move(0,0);
  2142.     (void) printw("Which Screen? [a-n, q]");
  2143.     (void) clrtoeol();
  2144.     (void) refresh();
  2145.     return(nmgetch());
  2146. }
  2147. \SHAR\EOF\
  2148. else
  2149.   echo "will not over write ./help.c"
  2150. fi
  2151. if [ `wc -c ./help.c | awk '{printf $1}'` -ne 15538 ]
  2152. then
  2153. echo `wc -c ./help.c | awk '{print "Got " $1 ", Expected " 15538}'`
  2154. fi
  2155. if `test ! -s ./eres.sed`
  2156. then
  2157. echo "Extracting ./eres.sed"
  2158. cat > ./eres.sed << '\SHAR\EOF\'
  2159. /%token.*K_/!d
  2160. /%token.*K_\(.*\)/s//    "\1",    K_\1,/
  2161. \SHAR\EOF\
  2162. else
  2163.   echo "will not over write ./eres.sed"
  2164. fi
  2165. if [ `wc -c ./eres.sed | awk '{printf $1}'` -ne 50 ]
  2166. then
  2167. echo `wc -c ./eres.sed | awk '{print "Got " $1 ", Expected " 50}'`
  2168. fi
  2169. if `test ! -s ./sres.sed`
  2170. then
  2171. echo "Extracting ./sres.sed"
  2172. cat > ./sres.sed << '\SHAR\EOF\'
  2173. /%token.*S_/!d
  2174. /%token.*S_\(.*\)/s//    "\1",    S_\1,/
  2175. \SHAR\EOF\
  2176. else
  2177.   echo "will not over write ./sres.sed"
  2178. fi
  2179. if [ `wc -c ./sres.sed | awk '{printf $1}'` -ne 50 ]
  2180. then
  2181. echo `wc -c ./sres.sed | awk '{print "Got " $1 ", Expected " 50}'`
  2182. fi
  2183. if `test ! -s ./Makefile`
  2184. then
  2185. echo "Extracting ./Makefile"
  2186. cat > ./Makefile << '\SHAR\EOF\'
  2187. # Specify the name of the program.
  2188. # All documentation and installation keys on this value.
  2189. name=sc
  2190. NAME=SC
  2191.  
  2192. # This is where the install step puts it.
  2193. EXDIR=/h/rgb/bin/sym
  2194.  
  2195. # This is where the man page goes.
  2196. MANDIR=/usr/man/man1
  2197.  
  2198. # Set SIMPLE for lex.c if you don't want arrow keys or lex.c blows up
  2199. #SIMPLE=-DSIMPLE
  2200.  
  2201. # Set INTERNATIONAL if you need 8 bit characters.  You should
  2202. # not set this if you are running 5.3.0.  I think it is OK in 5.3.1.
  2203. #INTERNATIONAL=-DINTERNATIONAL
  2204.  
  2205. # Set SIGVOID if signal routines are type void.  System 5.3, VMS and ANSI C
  2206. # Compliant systems use this.  Most BSD systems do not.
  2207. #SIGVOID=-DSIGVOID
  2208.  
  2209. # This is the name of a pager like "more" If the line is commented out
  2210. # then "more" will be used. "pg" may be appropriate for SYSV
  2211. PAGER=-DDFLT_PAGER=\"less\"
  2212.  
  2213. # Use this for system V.2
  2214. # CFLAGS= -O -DSYSV2 $(SIGVOID)
  2215. # LDFLAGS=
  2216. # LIB=-lm -lcurses -lPW
  2217.  
  2218. # Use this for system V.3
  2219. CFLAGS= -O -DSYSV3 -DSIGVOID
  2220. LDFLAGS=
  2221. LIB=-lm -lcurses -lPW
  2222.  
  2223. # Use this for BSD 4.2
  2224. #CFLAGS=  -O -DBSD42 $(SIGVOID)
  2225. #LDFLAGS=
  2226. #LIB=-lm -lcurses -ltermcap
  2227.  
  2228. # Use this for BSD 4.3
  2229. #CFLAGS= -O -DBSD43 $(SIGVOID)
  2230. #LDFLAGS=
  2231. #LIB=-lm -lcurses -ltermcap
  2232.  
  2233. # Use this for system III (XENIX)
  2234. #CFLAGS= -O -DSYSIII $(SIGVOID)
  2235. #LDFLAGS= -i
  2236. #LIB=-lm -lcurses -ltermcap
  2237.  
  2238. # Use this for VENIX
  2239. #CFLAGS= -DVENIX -DBSD42 -DV7 $(SIGVOID)
  2240. #LDFLAGS= -z -i 
  2241. #LIB=-lm -lcurses -ltermcap
  2242.  
  2243. # All of the source files
  2244. SRC=sc.h sc.c lex.c gram.y interp.c crypt.c xmalloc.c cmds.c range.c help.c \
  2245.     eres.sed sres.sed Makefile psc.c
  2246.  
  2247. # The objects
  2248. OBJS=sc.o interp.o cmds.o crypt.o xmalloc.o range.o help.o lex.o gram.o
  2249.  
  2250. # The documents in the Archive
  2251. DOCS=README CHANGES sc.doc psc.doc tutorial.sc VMS_NOTES BSD_BUGS
  2252.  
  2253. $(name):     $(OBJS)
  2254.     $(CC) ${CFLAGS} ${LDFLAGS} ${OBJS} ${LIB} -o $(name)
  2255.  
  2256. diff_to_sc:    diff_to_sc.c
  2257.     $(CC) ${CFLAGS} -o dtv diff_to_sc.c
  2258.  
  2259. p$(name):    psc.c
  2260.     $(CC) ${CFLAGS} -o p$(name) psc.c
  2261.     cp p$(name) $(EXDIR)/p$(name)
  2262.  
  2263. lex.o:    sc.h y.tab.h gram.o
  2264.     $(CC) ${CFLAGS} ${SIMPLE} ${INTERNATIONAL} -c lex.c
  2265.  
  2266. sc.o:    sc.h sc.c
  2267.     $(CC) ${CFLAGS} ${INTERNATIONAL} $(PAGER) -c sc.c
  2268.  
  2269. interp.o:    interp.c sc.h
  2270.  
  2271. gram.o:    sc.h y.tab.h
  2272.  
  2273. cmds.o: cmds.c sc.h
  2274.  
  2275. crypt.o: crypt.c sc.h
  2276.  
  2277. range.o: range.c sc.h
  2278.  
  2279. help.o: help.c sc.h
  2280.  
  2281. y.tab.h:    gram.y
  2282.  
  2283. gram.o:    sc.h y.tab.h gram.c
  2284.     $(CC) ${CFLAGS} -c gram.c
  2285.     sed<gram.y >experres.h -f eres.sed;sed < gram.y > statres.h -f sres.sed
  2286.  
  2287. gram.c:    gram.y
  2288.     $(YACC) -d gram.y; mv y.tab.c gram.c
  2289.  
  2290. clean:
  2291.     rm -f *.o *res.h y.tab.h $(name) p$(name) debug core gram.c $(name).1 \
  2292.     $(name).man p$(name).man p$(name).1 y.output
  2293.  
  2294. shar: ${SRC} ${DOCS}
  2295.     shar -c -m 64000 -f shar ${DOCS} ${SRC}
  2296.  
  2297. lint: sc.h sc.c lex.c gram.c interp.c cmds.c crypt.c
  2298.     lint ${CFLAGS} ${SIMPLE} sc.c lex.c gram.c interp.c cmds.c crypt.c \
  2299.     range.c xmalloc.c help.c -lcurses -lm
  2300.  
  2301. inspect: sc.h sc.c lex.c gram.c interp.c cmds.c crypt.c
  2302.     /bruces/ianj/bin/i386/inspect -abv -t 8 sc.c lex.c gram.c interp.c \
  2303.     cmds.c crypt.c range.c xmalloc.c help.c
  2304.  
  2305. print: sc.h gram.y sc.c lex.c interp.c cmds.c crypt.c 
  2306.     prc sc.h gram.y sc.c lex.c interp.c cmds.c crypt.c | lpr
  2307.  
  2308. $(name).1:    sc.doc
  2309.     sed -e s/pname/$(name)/g -e s/PNAME/$(NAME)/g sc.doc >  $(name).1
  2310.  
  2311. $(name).man:    $(name).1
  2312.     nroff -man $(name).1 > $(name).man
  2313.  
  2314. p$(name).1:    psc.doc
  2315.     sed -e s/pname/$(name)/g -e s/PNAME/$(NAME)/g psc.doc >  p$(name).1
  2316.  
  2317. p$(name).man:    p$(name).1
  2318.     nroff -man p$(name).1 > p$(name).man
  2319.  
  2320. install: $(EXDIR)/$(name)
  2321.  
  2322. inst-man: $(MANDIR)/$(name).1
  2323.  
  2324. $(EXDIR)/$(name): $(name)
  2325.     -mv $(EXDIR)/$(name) $(EXDIR)/$(name).old
  2326.     strip $(name)
  2327.     cp $(name) $(EXDIR)
  2328.  
  2329. $(MANDIR)/$(name).1: $(name).1
  2330.     cp $(name).1 $(MANDIR)
  2331.  
  2332. diffs: ${SRC}
  2333.     for i in ${SRC} ${DOCS} ;\
  2334.         do \
  2335.         rcsdiff -c -r5.1 $$i ;\
  2336.         done
  2337. \SHAR\EOF\
  2338. else
  2339.   echo "will not over write ./Makefile"
  2340. fi
  2341. if [ `wc -c ./Makefile | awk '{printf $1}'` -ne 3645 ]
  2342. then
  2343. echo `wc -c ./Makefile | awk '{print "Got " $1 ", Expected " 3645}'`
  2344. fi
  2345. if `test ! -s ./psc.c`
  2346. then
  2347. echo "Extracting ./psc.c"
  2348. cat > ./psc.c << '\SHAR\EOF\'
  2349. /* Sc parse routine
  2350.  *
  2351.  * usage psc options
  2352.  * options:
  2353.  *   -L        Left justify strings.  Default is right justify.
  2354.  *   -r        Assemble data into rows first, not columns.
  2355.  *   -R    n    Increment by n between rows 
  2356.  *   -C n    Increment by n between columns
  2357.  *   -n n    Length of the row (column) should be n.
  2358.  *   -s v    Top left location in the spreadsheet should be v; eg, k5
  2359.  *   -d c       Use c as the delimiter between the fields.
  2360.  *   -k         Keep all delimiters - Default is strip multiple delimiters to 1.
  2361.  *   
  2362.  *  Author: Robert Bond
  2363.  *        $Revision: 6.1 $
  2364.  */
  2365.  
  2366. #include <ctype.h>
  2367. #include <stdio.h>
  2368. #include "sc.h"
  2369.  
  2370. #define END 0
  2371. #define NUM 1
  2372. #define ALPHA 2
  2373. #define SPACE 3
  2374. #define EOL 4
  2375.  
  2376. extern char *optarg;
  2377. extern int   optind;
  2378. char *coltoa();
  2379. char *progname;
  2380.  
  2381. #ifdef SYSV3
  2382. extern void exit();
  2383. #else
  2384. extern int exit();
  2385. #endif
  2386.  
  2387. int colfirst = 0;
  2388. int r0 = 0;
  2389. int c0 = 0;
  2390. int rinc = 1;
  2391. int cinc = 1;
  2392. int leftadj = 0;
  2393. int len = 20000;
  2394. char delim1 = ' ';
  2395. char delim2 = '\t';
  2396. int strip_delim = 1;
  2397. int fwidth[MAXCOLS];
  2398. int precision[MAXCOLS];
  2399.  
  2400. char token[1000];
  2401.  
  2402. main(argc, argv)
  2403. int argc;
  2404. char **argv;
  2405. {
  2406.     int curlen;
  2407.     int curcol, coff;
  2408.     int currow, roff;
  2409.     int first;
  2410.     int c;
  2411.     register effr, effc;
  2412.     int i,j;
  2413.     register char *p;
  2414.  
  2415.     progname = argv[0];
  2416.     while ((c = getopt(argc, argv, "rLks:R:C:n:d:")) != EOF) {
  2417.     switch(c) {
  2418.     case 'r':
  2419.         colfirst = 1;
  2420.         break;
  2421.     case 'L':
  2422.         leftadj = 1;
  2423.         break;
  2424.     case 's':
  2425.         c0 = getcol(optarg);
  2426.         r0 = getrow(optarg);
  2427.         break;
  2428.     case 'R':
  2429.         rinc = atoi(optarg);
  2430.         break;
  2431.     case 'C':
  2432.         cinc = atoi(optarg);
  2433.         break;
  2434.     case 'n':
  2435.         len = atoi(optarg);
  2436.         break;
  2437.     case 'd':
  2438.         delim1 = optarg[0];
  2439.         delim2 = 0;
  2440.         break;
  2441.     case 'k':
  2442.         strip_delim = 0;
  2443.         break;
  2444.     default:
  2445.         (void) fprintf(stderr,"Usage: %s [-rkL] [-s v] [-R i] [-C i] [-n i] [-d c]\n", progname);
  2446.         exit(1);
  2447.         }
  2448.     }
  2449.  
  2450.     if (optind < argc) {
  2451.         (void) fprintf(stderr,"Usage: %s [-rL] [-s v] [-R i] [-C i] [-n i] [-d c]\n", progname);
  2452.         exit(1);
  2453.     }
  2454.  
  2455.     curlen = 0;
  2456.     curcol = c0; coff = 0;
  2457.     currow = r0; roff = 0;
  2458.     first = 1;
  2459.  
  2460.     while(1) {
  2461.  
  2462.     effr = currow+roff;
  2463.     effc = curcol+coff;
  2464.  
  2465.     switch(scan()) {
  2466.     case END:
  2467.         for (i = 0; i<MAXCOLS; i++) {
  2468.         if (precision[i])
  2469.             (void) printf("format %s %d %d\n", coltoa(i), precision[i]+1,
  2470.             fwidth[i]);
  2471.         }
  2472.         exit(0);
  2473.     case NUM:
  2474.         first = 0;
  2475.         (void) printf("let %s%d = %s\n", coltoa(effc), effr, token);
  2476.         if (effc > MAXCOLS-1)
  2477.         (void) fprintf(stderr, "Invalid column used: %s\n", coltoa(effc));
  2478.         else {
  2479.         i = 0;
  2480.         j = 0;
  2481.         p = token;
  2482.         while (*p && *p != '.') {
  2483.             p++; i++;
  2484.         }
  2485.         if (*p) {
  2486.             p++; i++;
  2487.         }
  2488.         while (*p) {
  2489.             p++; i++; j++;
  2490.         }
  2491.         if (precision[effc] < i)
  2492.             precision[effc] = i;
  2493.         if (fwidth[effc] < j)
  2494.             fwidth[effc] = j;
  2495.         }
  2496.         break;
  2497.     case ALPHA:
  2498.         first = 0;
  2499.         if (leftadj)
  2500.         (void) printf("leftstring %s%d = \"%s\"\n", coltoa(effc),effr,token); 
  2501.         else
  2502.         (void) printf("rightstring %s%d = \"%s\"\n",coltoa(effc),effr,token); 
  2503.         if (effc > MAXCOLS-1)
  2504.         (void) fprintf(stderr, "Invalid column used: %s\n", coltoa(effc));
  2505.         else {
  2506.         i = strlen(token);
  2507.         if (i > precision[effc])
  2508.             precision[effc] = i;
  2509.         }
  2510.         break;
  2511.     case SPACE:
  2512.         if (first && strip_delim)
  2513.         break;
  2514.         if (colfirst)
  2515.         roff++;
  2516.         else
  2517.         coff++;
  2518.         break;
  2519.     case EOL:
  2520.         curlen++;
  2521.         roff = 0;
  2522.         coff = 0;
  2523.         first = 1;
  2524.         if (colfirst) {
  2525.         if (curlen >= len) {
  2526.             curcol = c0;
  2527.             currow += rinc;
  2528.             curlen = 0;
  2529.         } else {
  2530.             curcol += cinc;
  2531.         }
  2532.         } else {
  2533.         if (curlen >= len) {
  2534.             currow = r0;
  2535.             curcol += cinc;
  2536.             curlen = 0;
  2537.         } else {
  2538.             currow += rinc;
  2539.         }
  2540.         }
  2541.         break;
  2542.     }
  2543.     }
  2544. }
  2545.  
  2546. scan()
  2547. {
  2548.     register int c;
  2549.     register char *p;
  2550.  
  2551.     p = token;
  2552.     c = getchar();
  2553.  
  2554.     if (c == EOF)
  2555.     return(END);
  2556.  
  2557.     if (c == '\n')
  2558.     return(EOL);
  2559.  
  2560.     if (c == delim1 || c == delim2) {
  2561.         if (strip_delim) {
  2562.         while ((c = getchar()) && (c == delim1 || c == delim2))
  2563.             ;
  2564.         (void)ungetc(c, stdin);
  2565.     } 
  2566.     return(SPACE);
  2567.     }
  2568.  
  2569.     if (c == '\"') {
  2570.     while ((c = getchar()) && c != '\"' && c != '\n' && c != EOF)
  2571.         *p++ = c;
  2572.     if (c != '\"')
  2573.         (void)ungetc(c, stdin);
  2574.     *p = 0;
  2575.     return(ALPHA);
  2576.     }
  2577.  
  2578.     while (c != delim1 && c != delim2 && c!= '\n' && c != EOF) {
  2579.     *p++ = c;
  2580.     c = getchar();
  2581.     }
  2582.     *p = 0;
  2583.     (void)ungetc(c, stdin);
  2584.  
  2585.     p = token;
  2586.     c = *p;
  2587.     if (isdigit(c) || c == '.' || c == '-' || c == '+') {
  2588.     while(isdigit(c) || c == '.' || c == '-' || c == '+' || c == 'e'
  2589.         || c == 'E') {
  2590.         c = *p++;
  2591.     }
  2592.     if (c == 0)
  2593.         return(NUM);
  2594.     else
  2595.         return(ALPHA);
  2596.     }
  2597.  
  2598.     return(ALPHA);
  2599. }
  2600.     
  2601. getcol(p)
  2602. char *p;
  2603. {
  2604.     register  col;
  2605.  
  2606.     if (!p)
  2607.     return(0);
  2608.     while(*p && !isalpha(*p)) 
  2609.     p++; 
  2610.     if (!*p)
  2611.     return(0);
  2612.     col = ((*p & 0137) - 'A');
  2613.     if (isalpha(*++p)) 
  2614.     col = (col + 1)*26 + ((*p & 0137) - 'A');
  2615.     return(col);
  2616. }
  2617.  
  2618. getrow(p)
  2619. char *p;
  2620. {
  2621.     int row;
  2622.  
  2623.     if (!p)
  2624.     return(0);
  2625.     while(*p && !isdigit(*p))
  2626.     p++; 
  2627.     if (!*p)
  2628.     return(0);
  2629.     if (sscanf(p, "%d", &row) != 1)
  2630.     return(0);
  2631.     return(row);
  2632. }
  2633.  
  2634. char *
  2635. coltoa(col)
  2636. int col;
  2637. {
  2638.     static char rname[3];
  2639.     register char *p = rname;
  2640.  
  2641.     if (col < 0 || col > 25*26) 
  2642.     (void) fprintf(stderr,"coltoa: invalid col: %d", col);
  2643.  
  2644.     if (col > 25) {
  2645.     *p++ = col/26 + 'A' - 1;
  2646.     col %= 26;
  2647.     }
  2648.     *p++ = col+'A';
  2649.     *p = 0;
  2650.     return(rname);
  2651. }
  2652.  
  2653. \SHAR\EOF\
  2654. else
  2655.   echo "will not over write ./psc.c"
  2656. fi
  2657. if [ `wc -c ./psc.c | awk '{printf $1}'` -ne 5408 ]
  2658. then
  2659. echo `wc -c ./psc.c | awk '{print "Got " $1 ", Expected " 5408}'`
  2660. fi
  2661. echo "Finished archive 4 of 4"
  2662. # if you want to concatenate archives, remove anything after this line
  2663. exit
  2664.  
  2665.