home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / EFFO / pd7.lzh / SRC / sc.c < prev    next >
Text File  |  1990-05-04  |  54KB  |  1,631 lines

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