home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Product / Product.zip / sc621_3.zip / src / screen.c < prev    next >
C/C++ Source or Header  |  1993-11-14  |  15KB  |  639 lines

  1. /*    SC    A Spreadsheet Calculator
  2.  *        Curses based Screen 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.  *        Currently supported by sequent!sawmill!buhrt (Jeff Buhrt)
  11.  *        $Revision: 6.21 $
  12.  *
  13.  */
  14.  
  15.  
  16. #include <curses.h>
  17. #include "sc.h"
  18.  
  19. #ifdef VMS
  20. extern int VMS_read_raw;   /*sigh*/
  21.     VMS_read_raw = 1;
  22. #endif
  23.  
  24. #ifdef BROKENCURSES
  25.         /* nl/nonl bug fix */
  26. #undef nl
  27. #undef nonl
  28. #define nl()     (_tty.sg_flags |= CRMOD,_pfast = _rawmode,stty(_tty_ch, &_tty))
  29. #define nonl()     (_tty.sg_flags &= ~CRMOD, _pfast = TRUE, stty(_tty_ch, &_tty))
  30. #endif
  31.  
  32. void    repaint();
  33.  
  34. char    under_cursor = ' '; /* Data under the < cursor */
  35. char    mode_ind = '.';
  36. extern    char    revmsg[];
  37.  
  38. int    rows, lcols;
  39. int    lastmx, lastmy;    /* Screen address of the cursor */
  40. int    lastcol;    /* Spreadsheet Column the cursor was in last */
  41. extern    int *fwidth;
  42. extern    int showrange;    /* Causes ranges to be highlighted    */
  43. extern    int showneed;    /* Causes cells needing values to be highlighted */
  44. extern    int showexpr;    /* Causes cell exprs to be displayed, highlighted */
  45. #ifdef RIGHT_CBUG
  46. extern    int wasforw;    /* Causes screen to be redisplay if on lastcol */
  47. #endif
  48.  
  49. /*
  50.  * update() does general screen update
  51.  *
  52.  * standout last time in update()?
  53.  *    At this point we will let curses do work
  54.  */
  55. int    standlast    = FALSE;
  56.  
  57. void
  58. update (anychanged)
  59. int    anychanged;    /* did any cell really change in value? */
  60. {
  61.     register    row, col;
  62.     register struct ent **pp;
  63.     int    mxrow, mxcol;
  64.     int    minsr = 0, minsc = 0, maxsr = 0, maxsc = 0;
  65.     register r;
  66.     register i;
  67.     static    int    lastcurcol = -1, lastcurrow = -1;
  68.  
  69.     /*
  70.      * place the cursor on the screen, set col, curcol, stcol, lastcol as
  71.      * needed
  72.      */
  73.     if ((curcol != lastcurcol) || FullUpdate)
  74.     {
  75.     while (col_hidden[curcol])   /* You can't hide the last row or col */
  76.         curcol++;
  77.  
  78.     /* First see if the last display still covers curcol */
  79.     if (stcol <= curcol) { 
  80.         for (i = stcol, lcols = 0, col = RESCOL;
  81.                (col + fwidth[i]) < COLS-1 && i < maxcols; i++) {
  82.             lcols++;
  83.  
  84.             if (col_hidden[i])
  85.                 continue;
  86.             col += fwidth[i];
  87.         }
  88.     }
  89.     while (stcol + lcols - 1 < curcol || curcol < stcol) {
  90.         FullUpdate++;
  91.         if (stcol - 1 == curcol) {    /* How about back one? */
  92.             stcol--;
  93.         } else if (stcol + lcols == curcol) {   /* Forward one? */
  94.             stcol++;
  95.         } else {
  96.             /* Try to put the cursor in the center of the screen */
  97.             col = (COLS - RESCOL - fwidth[curcol]) / 2 + RESCOL; 
  98.             stcol = curcol;
  99.             for (i=curcol-1; i >= 0 && col-fwidth[i] > RESCOL; i--)
  100.             {    stcol--;
  101.                 if (col_hidden[i])
  102.                     continue;
  103.                 col -= fwidth[i];
  104.             }
  105.         }
  106.         /* Now pick up the counts again */
  107.         for (i = stcol, lcols = 0,col = RESCOL;
  108.             (col + fwidth[i]) < COLS-1 && i < maxcols; i++) {
  109.             lcols++;
  110.             if (col_hidden[i])
  111.                 continue;
  112.             col += fwidth[i];
  113.         }
  114.     }
  115.     lastcurcol = curcol;
  116.     }
  117.  
  118.     /* Now - same process on the rows as the columns */
  119.     if ((currow != lastcurrow) || FullUpdate)
  120.     {
  121.     while (row_hidden[currow])   /* You can't hide the last row or col */
  122.         currow++;
  123.     if (strow <= currow) { 
  124.         for (i = strow, rows = 0, row=RESROW; row<LINES && i<maxrows; i++)
  125.         {    rows++;
  126.             if (row_hidden[i])
  127.                 continue;
  128.             row++;
  129.         }
  130.     }
  131.  
  132.     while (strow + rows - 1 < currow || currow < strow) {
  133.         FullUpdate++;
  134.         if (strow - 1 == currow) {    /* How about up one? */
  135.             strow--;
  136.         } else if (strow + rows == currow) {   /* Down one? */
  137.             strow++;
  138.         } else {
  139.             /* Try to put the cursor in the center of the screen */
  140.             row = (LINES - RESROW) / 2 + RESROW; 
  141.             strow = currow;
  142.             for (i=currow-1; i >= 0 && row-1 > RESROW; i--) {
  143.                 strow--;
  144.                 if (row_hidden[i])
  145.                     continue;
  146.                 row--;
  147.             }
  148.         }
  149.         /* Now pick up the counts again */
  150.         for (i = strow, rows = 0, row=RESROW; row<LINES && i<maxrows; i++) {
  151.             rows++;
  152.             if (row_hidden[i])
  153.                 continue;
  154.             row++;
  155.         }
  156.     }
  157.     lastcurrow = currow;
  158.     }
  159.     mxcol = stcol + lcols - 1;
  160.     mxrow = strow + rows - 1;
  161.  
  162.     /* Get rid of cursor standout on the cell at previous cursor position */
  163.     if (!FullUpdate)
  164.     {    if (showcell)
  165.         repaint(lastmx, lastmy, fwidth[lastcol]);
  166.  
  167.     (void) move(lastmy, lastmx+fwidth[lastcol]);
  168.  
  169.     if ((inch() & A_CHARTEXT ) == '<')
  170.         (void) addch(under_cursor);
  171.     }
  172.  
  173.     /* where is the the cursor now? */
  174.     lastmy =  RESROW;
  175.     for (row = strow; row < currow; row++)
  176.     if (!row_hidden[row])
  177.         lastmy++;
  178.  
  179.     lastmx = RESCOL;
  180.     for (col = stcol; col < curcol; col++)
  181.     if (!col_hidden[col])
  182.         lastmx += fwidth[col];
  183.     lastcol = curcol;
  184.  
  185.     if (FullUpdate || standlast) {
  186.     (void) move(2, 0);
  187.     (void) clrtobot();
  188.     (void) standout();
  189.  
  190.     for (row=RESROW, i=strow; i <= mxrow; i++) {
  191.         if (row_hidden[i]) 
  192.         continue;
  193.         (void) move(row,0);
  194.         if (maxrows < 1000)
  195.         (void) printw("%-*d", RESCOL-1, i);
  196.         else
  197.         (void) printw("%-*d", RESCOL, i);
  198.         row++;
  199.     }
  200. #ifdef RIGHT_CBUG
  201.     if(wasforw) {
  202.         clearok(stdscr, TRUE);
  203.         wasforw = 0;
  204.     }
  205. #endif
  206.     (void) move(2,0);
  207.     (void) printw("%*s", RESCOL, " ");
  208.  
  209.     for (col=RESCOL, i = stcol; i <= mxcol; i++) {
  210.         register int k;
  211.         if (col_hidden[i])
  212.         continue;
  213.         (void) move(2, col);
  214.         k = fwidth[i]/2;
  215.         if (k == 0)
  216.         (void) printw("%1s", coltoa(i));
  217.         else
  218.             (void) printw("%*s%-*s", k, " ", fwidth[i]-k, coltoa(i));
  219.         col += fwidth[i];
  220.     }
  221.     (void) standend();
  222.     }
  223.  
  224.     if (showrange) {
  225.     minsr = showsr < currow ? showsr : currow;
  226.     minsc = showsc < curcol ? showsc : curcol;
  227.     maxsr = showsr > currow ? showsr : currow;
  228.     maxsc = showsc > curcol ? showsc : curcol;
  229.  
  230.     if (showtop) {
  231.         (void) move(1,0);
  232.         (void) clrtoeol();
  233.         (void) printw("Default range:  %s",
  234.                 r_name(minsr, minsc, maxsr, maxsc));
  235.     }
  236.     }
  237.  
  238.  
  239.     /* Repaint the visible screen */
  240.     if (showrange || anychanged || FullUpdate || standlast)
  241.     {
  242.     /* may be reset in loop, if not next time we will do a FullUpdate */
  243.       if (standlast)
  244.       {    FullUpdate = TRUE;
  245.     standlast = FALSE;
  246.       }
  247.  
  248.       for (row = strow, r = RESROW; row <= mxrow; row++) {
  249.     register c = RESCOL;
  250.     int do_stand = 0;
  251.     int fieldlen;
  252.     int nextcol;
  253.  
  254.     if (row_hidden[row])
  255.         continue;
  256.     for (pp = ATBL(tbl, row, col = stcol); col <= mxcol;
  257.              pp += nextcol - col,  col = nextcol, c += fieldlen) {
  258.  
  259.         nextcol = col+1;
  260.         if (col_hidden[col]) {
  261.         fieldlen = 0;
  262.         continue;
  263.         }
  264.  
  265.         fieldlen = fwidth[col];
  266.  
  267.         /*
  268.          * Set standout if:
  269.          *
  270.          * - showing ranges, and not showing cells which need to be filled
  271.          *     in, and not showing cell expressions, and in a range, OR
  272.          *
  273.          * - if showing cells which need to be filled in and this one is
  274.          *     of that type (has a value and doesn't have an expression,
  275.          *     or it is a string expression), OR
  276.          *
  277.          * - if showing cells which have expressions and this one does.
  278.          */
  279.         if ((showrange && (! showneed) && (! showexpr)
  280.                && (row >= minsr) && (row <= maxsr)
  281.                && (col >= minsc) && (col <= maxsc))
  282.             || (showneed && (*pp) && ((*pp) -> flags & is_valid) &&
  283.               (((*pp) -> flags & is_strexpr) || !((*pp) -> expr)))
  284.             || (showexpr && (*pp) && ((*pp) -> expr)))
  285.         {
  286.         (void) move(r, c);
  287.         (void) standout();
  288.         standlast++;
  289.         if (!*pp)    /* no cell, but standing out */
  290.         {    (void) printw("%*s", fwidth[col], " ");
  291.             (void) standend();
  292.             continue;
  293.         }
  294.         else
  295.             do_stand = 1;
  296.         }
  297.         else
  298.         do_stand = 0;
  299.  
  300.         if ((*pp) && (((*pp) -> flags & is_changed || FullUpdate) || do_stand)) {
  301.         if (do_stand) {
  302.             (*pp) -> flags |= is_changed; 
  303.         } else {
  304.             (void) move(r, c);
  305.             (*pp) -> flags &= ~is_changed;
  306.         }
  307.  
  308.         /*
  309.          * Show expression; takes priority over other displays:
  310.          */
  311.  
  312.         if ((*pp)->cellerror)
  313.             (void) printw("%*.*s", fwidth[col], fwidth[col],
  314.               (*pp)->cellerror == CELLERROR ? "ERROR" : "INVALID");
  315.         else
  316.         if (showexpr && ((*pp) -> expr)) {
  317.             linelim = 0;
  318.             editexp(row, col);        /* set line to expr */
  319.             linelim = -1;
  320.             showstring(line, /* leftflush = */ 1, /* hasvalue = */ 0,
  321.                 row, col, & nextcol, mxcol, & fieldlen, r, c);
  322.         } else {
  323.             /*
  324.              * Show cell's numeric value:
  325.                      */
  326.  
  327.             if ((*pp) -> flags & is_valid) {
  328.             char field[FBUFLEN];
  329.  
  330.             if ((*pp) -> format) {
  331.                 (void) format((*pp) -> format, (*pp) -> v,
  332.                          field, sizeof(field));
  333.             } else {
  334.                 (void) engformat(realfmt[col], fwidth[col], 
  335.                                              precision[col], (*pp) -> v, 
  336.                                              field, sizeof(field));
  337.             }
  338.             if (strlen(field) > fwidth[col]) {
  339.                 for(i = 0; i<fwidth[col]; i++)
  340.                     (void)addch('*');
  341.             } else {
  342.                 for(i = 0; i < fwidth[col] - strlen(field);i++)
  343.                     (void)addch(' ');
  344.                 (void)addstr(field);
  345.             }
  346.             }
  347.  
  348.             /*
  349.              * Show cell's label string:
  350.              */
  351.  
  352.             if ((*pp) -> label) {
  353.             showstring((*pp) -> label,
  354.                     (*pp) -> flags & (is_leftflush|is_label),
  355.                     (*pp) -> flags & is_valid,
  356.                     row, col, & nextcol, mxcol,
  357.                     & fieldlen, r, c);
  358.             }
  359.             else    /* repaint a blank cell: */
  360.             if ((do_stand || !FullUpdate) &&
  361.                 ((*pp)->flags & is_changed) &&
  362.                 !((*pp)->flags & is_valid) && !(*pp)->label) {
  363.             (void) printw("%*s", fwidth[col], " ");
  364.             }
  365.         } /* else */
  366.  
  367.         if (do_stand) {
  368.             (void) standend();
  369.             do_stand = 0;
  370.         }
  371.         }
  372.     }
  373.     r++;
  374.       }
  375.     }
  376.  
  377.     /* place 'cursor marker' */
  378.     if (showcell && (! showneed) && (! showexpr)) {
  379.     (void) move(lastmy, lastmx);
  380.         (void) standout();
  381.         repaint(lastmx, lastmy, fwidth[lastcol]);
  382.         (void) standend();
  383.     }
  384.     (void) move(lastmy, lastmx+fwidth[lastcol]);
  385.     under_cursor = (inch() & A_CHARTEXT);
  386.     (void) addch('<');
  387.  
  388.     (void) move(0, 0);
  389.     (void) clrtoeol();
  390.     if (linelim >= 0) {
  391.     (void) addch(mode_ind);
  392.     (void) addstr("> ");
  393.     (void) addstr(line);
  394.     (void) move((linelim + 3) / COLS, (linelim+3) % COLS);
  395.     } else {
  396.     if (showtop) {            /* show top line */
  397.         register struct ent *p1;
  398.  
  399.         int printed = 0;        /* printed something? */
  400.  
  401.         /* show the current cell's format */
  402.         (void) printw("%s%d ", coltoa(curcol), currow);
  403.         if ((p1 = *ATBL(tbl, currow, curcol)) && p1->format)
  404.         printw("(%s) ", p1->format);
  405.         else
  406.         printw("(%d %d %d) ", fwidth[curcol], precision[curcol],
  407.                 realfmt[curcol]);
  408.  
  409.         if (p1) {
  410.         if (p1 -> expr) {
  411.             /* has expr of some type */
  412.             linelim = 0;
  413.             editexp(currow, curcol);    /* set line to expr */
  414.             linelim = -1;
  415.         }
  416.  
  417.         /*
  418.          * Display string part of cell:
  419.          */
  420.  
  421.         if ((p1 -> expr) && (p1 -> flags & is_strexpr)) {
  422.              if( (p1-> flags & is_label) )
  423.             (void) addstr("|{");
  424.             else
  425.             (void) addstr((p1 -> flags & is_leftflush) ? "<{" : ">{");
  426.             (void) addstr(line);
  427.             (void) addstr("} ");    /* and this '}' is for vi % */
  428.             printed = 1;
  429.  
  430.         } else if (p1 -> label) {
  431.             /* has constant label only */
  432.             if( (p1-> flags & is_label) )
  433.             (void) addstr("|\"");
  434.             else
  435.             (void) addstr ((p1 -> flags & is_leftflush) ? "<\"" : ">\"");
  436.             (void) addstr (p1 -> label);
  437.             (void) addstr ("\" ");
  438.             printed = 1;
  439.         }
  440.  
  441.         /*
  442.          * Display value part of cell:
  443.          */
  444.  
  445.         if (p1 -> flags & is_valid) {
  446.             /* has value or num expr */
  447.             if ((! (p1 -> expr)) || (p1 -> flags & is_strexpr))
  448. #if defined(__EMX__)
  449.             (void) sprintf (line, "%.13g", p1 -> v);
  450. #else
  451.             (void) sprintf (line, "%.15g", p1 -> v);
  452. #endif
  453.             (void) addch ('[');
  454.             (void) addstr (line);
  455.             (void) addch (']');
  456.             *line = '\0'; /* this is the input buffer ! */
  457.             printed = 1;
  458.         }
  459.         }
  460.         if (! printed)
  461.         (void) addstr ("[]");
  462.         /* Display if cell is locked */
  463.         if (p1 && p1->flags&is_locked)
  464.         (void) addstr(" locked");
  465.     }
  466.     (void) move(lastmy, lastmx+fwidth[lastcol]);
  467.     }
  468.  
  469.     if (revmsg[0]) {
  470.     (void) move(0, 0);
  471.     (void) clrtoeol ();    /* get rid of topline display */
  472.     (void) printw(revmsg);
  473.     *revmsg = '\0';        /* don't show it again */
  474.     (void) move (lastmy, lastmx + fwidth[lastcol]);
  475.     }
  476.  
  477.     FullUpdate = FALSE;
  478. }
  479.  
  480. /* redraw what is under the cursor from curses' idea of the screen */
  481. void
  482. repaint(x, y, len)
  483. int x, y, len;
  484. {
  485.     int c;
  486.  
  487.     while(len-- > 0) {
  488.     (void) move(y, x);
  489.     c = inch() & A_CHARTEXT;
  490.     (void) addch(c);
  491.     x++;
  492.     }
  493. }
  494.  
  495. int seenerr;
  496.  
  497. /* error routine for yacc (gram.y) */
  498. void
  499. yyerror(err)
  500. char *err; {
  501.     if (seenerr) return;
  502.     seenerr++;
  503.     (void) move(1,0);
  504.     (void) clrtoeol();
  505.     (void) printw("%s: %.*s<=%s",err,linelim,line,line+linelim);
  506. }
  507.  
  508. #ifdef XENIX2_3
  509. struct termio tmio;
  510. #endif
  511.  
  512. void
  513. startdisp()
  514. {
  515. #if sun
  516.     int     fd;
  517.     fd = dup(0);
  518. #endif
  519. #ifdef TIOCGSIZE
  520.     {    struct ttysize size;
  521.     if (ioctl(0, TIOCGSIZE, &size) == 0)
  522.     { 
  523.         LINES = size.ts_lines;
  524.         COLS = size.ts_cols;
  525.     }
  526.     }
  527. #endif
  528.  
  529. #ifdef XENIX2_3
  530.     (void) ioctl (fileno (stdin), TCGETA, & tmio);
  531. #endif
  532.     (void) initscr();
  533. #if sun
  534.     close(0);
  535.     dup(fd);
  536.     close(fd);
  537. #endif
  538.     (void) clear();
  539. #ifdef VMS
  540.     VMS_read_raw = 1;
  541. #else
  542.     nonl();
  543.     noecho ();
  544.     cbreak();
  545. #endif
  546.     initkbd();
  547.     scrollok(stdscr, 1);
  548.  
  549. #if defined(SYSV3) && !defined(NOIDLOK)
  550. # ifndef IDLOKBAD
  551.     /*
  552.      * turn hardware insert/delete on, if possible.
  553.      * turn on scrolling for systems with SYSVr3.{1,2} (SYSVr3.0 has this set
  554.      * as the default)
  555.      */
  556.      idlok(stdscr,TRUE);
  557. # else    /*
  558.      * This seems to fix (with an empty spreadsheet):
  559.      *    a) Redrawing the bottom half of the screen when you
  560.      *        move between row 9 <-> 10
  561.      *    b) the highlighted row labels being trash when you
  562.      *        move between row 9 <-> 10
  563.      *    c) On an xterm on Esix Rev. D+ from eating lines
  564.      *     -goto (or move) a few lines (or more) past the bottom
  565.      *     of the screen, goto (or move) to the top line on the
  566.      *     screen, move upward and the current line is deleted, the
  567.      *     others move up even when they should not, check by
  568.      *     noticing the rows become 2, 3, 40, 41, 42... (etc).
  569.      */
  570.      idlok(stdscr,FALSE);
  571. # endif
  572. #endif
  573.  
  574.     FullUpdate++;
  575. }
  576.  
  577. void
  578. stopdisp()
  579. {
  580.     deraw();
  581.     resetkbd();
  582.     endwin();
  583. #ifdef XENIX2_3
  584.     (void) ioctl (fileno (stdin), TCSETAW, & tmio);
  585. #endif
  586. }
  587.  
  588. /* init curses */
  589. #ifdef VMS
  590.  
  591. goraw()
  592. {
  593.     VMS_read_raw = 1;
  594.     FullUpdate++;
  595. }
  596.  
  597. deraw()
  598. {
  599.     (void) move (LINES - 1, 0);
  600.     (void) clrtoeol();
  601.     (void) refresh();
  602.     VMS_read_raw = 0;
  603. }
  604.  
  605. #else /* VMS */
  606. void
  607. goraw()
  608. {
  609. #if SYSV2 || SYSV3
  610.     fixterm();
  611. #else /* SYSV2 || SYSV3 */
  612.     cbreak();
  613.     nonl();
  614.     noecho ();
  615. #endif /* SYSV2 || SYSV3 */
  616.     kbd_again();
  617.     (void) clear();
  618.     FullUpdate++;
  619. }
  620.  
  621. /* clean up curses */
  622. void
  623. deraw()
  624. {
  625.     (void) move (LINES - 1, 0);
  626.     (void) clrtoeol();
  627.     (void) refresh();
  628. #if SYSV2 || SYSV3
  629.     resetterm();
  630. #else
  631.     nocbreak();
  632.     nl();
  633.     echo();
  634. #endif
  635.     resetkbd();
  636. }
  637.  
  638. #endif /* VMS */
  639.