home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 100-199 / ff197.lzh / Stevie / screen.c < prev    next >
C/C++ Source or Header  |  1989-03-28  |  12KB  |  509 lines

  1. /*
  2.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  3.  *
  4.  * Code Contributions By : Tim Thompson           twitch!tjt
  5.  *                         Tony Andrews           onecom!wldrdg!tony 
  6.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  7.  */
  8.  
  9. #include "stevie.h"
  10.  
  11. /*
  12.  * The following variable is set (in cursupdate) to the number of physical
  13.  * lines taken by the line the cursor is on. We use this to avoid extra calls
  14.  * to plines(). The optimized routines updateline() and redrawline()
  15.  * make sure that the size of the cursor line hasn't changed. If so, lines below
  16.  * the cursor will move up or down and we need to call the routines
  17.  * updateNextscreen() and updateRealscreen() to examine the entire screen. 
  18.  */
  19. static int      Cline_size;    /* size (in rows) of the cursor line */
  20. static int      Cline_row;    /* starting row of the cursor line */
  21.  
  22. /*
  23.  * updateline() - like updateNextscreen() but only for cursor line 
  24.  *
  25.  * This determines whether or not we need to call updateNextscreen() to examine
  26.  * the entire screen for changes. This occurs if the size of the cursor line
  27.  * (in rows) hasn't changed.
  28.  */
  29. void
  30. updateline()
  31. {
  32.     register int    row;
  33.     register int    col;
  34.     register char  *screenp;
  35.     register char   c;
  36.     LPtr            memp;
  37.     register char  *nextrow;
  38.     char            extra[16];
  39.     char           *p_extra;
  40.     int             n_extra;
  41.     int             n;
  42.     bool_t          eof;
  43.     int             lno;    /* number of the line we're doing */
  44.     int             coff;    /* column offset */
  45.  
  46.     MustRedrawLine = TRUE;
  47.  
  48.     coff = P(P_NU) ? 8 : 0;
  49.  
  50.     /*
  51.      * This should be done more efficiently. 
  52.      */
  53.     if (P(P_NU))
  54.     lno = cntllines(Filemem, Curschar);
  55.  
  56.     screenp = Nextscreen + (Cline_row * Columns);
  57.  
  58.     memp = *Curschar;
  59.     memp.index = 0;
  60.  
  61.     eof = FALSE;
  62.     col = 0;
  63.     row = Cline_row;
  64.  
  65.     p_extra = NULL;
  66.     n_extra = 0;
  67.     if (P(P_NU)) {
  68.     strcpy(extra, mkline(lno));
  69.     p_extra = extra;
  70.     n_extra = 8;
  71.     }
  72.     while (!eof) {
  73.     /* Get the next character to put on the screen. */
  74.  
  75.     /*
  76.      * The 'extra' array contains the extra stuff that is inserted to
  77.      * represent special characters (tabs, and other non-printable stuff.
  78.      * The order in the 'extra' array is reversed. 
  79.      */
  80.  
  81.     if (n_extra > 0) {
  82.         c = *p_extra++;
  83.         n_extra--;
  84.     } else {
  85.         c = gchar(&memp);
  86.         if (inc(&memp) == -1)
  87.         eof = TRUE;
  88.         /*
  89.          * when getting a character from the file, we may have to turn it
  90.          * into something else on the way to putting it into
  91.          * 'Nextscreen'. 
  92.          */
  93.         if (c == TAB && !P(P_LS)) {
  94.         strcpy(extra, "               ");
  95.         p_extra = extra;
  96.         /* tab amount depends on current column */
  97.         n_extra = ((P(P_TS) - 1) - (col - coff) % P(P_TS));
  98.         c = ' ';
  99.         } else if (c == NUL && P(P_LS)) {
  100.         extra[0] = NUL;
  101.         p_extra = extra;
  102.         n_extra = 1;
  103.         c = '$';
  104.         } else if (c != NUL && (n = chars[c].ch_size) > 1) {
  105.         p_extra = chars[c].ch_str;
  106.         c = *p_extra++;
  107.         n_extra = n - 1;
  108.         }
  109.     }
  110.  
  111.     if (c == NUL) {
  112.         row++;
  113.         /* get pointer to start of next row */
  114.         nextrow = Nextscreen + (row * Columns);
  115.         /* blank out the rest of this row */
  116.         while (screenp < nextrow)
  117.         *screenp++ = ' ';
  118.         break;
  119.     }
  120.     if (col >= Columns) {
  121.         row++;
  122.         col = 0;
  123.     }
  124.     /* store the character in Nextscreen */
  125.     *screenp++ = c;
  126.     col++;
  127.     }
  128.     if ((row - Cline_row) != Cline_size) {
  129.     updateNextscreen(VALID_TO_CURSCHAR);
  130.     }
  131. }
  132.  
  133. /*
  134.  * redrawline 
  135.  *
  136.  * Like updateRealscreen() but only for the cursor line. 
  137.  */
  138. void
  139. redrawline()
  140. {
  141.     register char  *np = Nextscreen + (Cline_row * Columns);
  142.     register char  *rp = Realscreen + (Cline_row * Columns);
  143.     register char  *endline;
  144.     register int    row, col;
  145.     int             gorow = -1, gocol = -1;
  146.  
  147.     if (RedrawingDisabled)
  148.     return;
  149.  
  150.     if (!MustRedrawLine && !MustRedrawScreen)
  151.     return;
  152.  
  153.     if (MustRedrawScreen) {
  154.     msg("STEVIE internal error: redrawline called");
  155.     sleep(5);
  156.     }
  157.     endline = np + (Cline_size * Columns);
  158.  
  159.     row = Cline_row;
  160.     col = 0;
  161.  
  162.     outstr(T_CI);        /* disable cursor */
  163.  
  164.     for (; np < endline; np++, rp++) {
  165.     /* If desired screen (contents of Nextscreen) does not */
  166.     /* match what's really there, put it there. */
  167.     if (*np != *rp) {
  168.         /* if we are positioned at the right place, */
  169.         /* we don't have to use windgoto(). */
  170.         if (gocol != col || gorow != row) {
  171.         /*
  172.          * If we're just off by one, don't send an entire esc. seq.
  173.          * (this happens a lot!) 
  174.          */
  175.         if (gorow == row && gocol + 1 == col) {
  176.             outchar(*(np - 1));
  177.             gocol++;
  178.         } else
  179.             windgoto(gorow = row, gocol = col);
  180.         }
  181.         outchar(*rp = *np);
  182.         gocol++;
  183.     }
  184.     if (++col >= Columns) {
  185.         col = 0;
  186.         row++;
  187.     }
  188.     }
  189.     outstr(T_CV);        /* enable cursor again */
  190.  
  191.     MustRedrawScreen = FALSE;
  192. }
  193.  
  194. /*
  195.  * prt_line() - print the given line
  196.  */
  197. void
  198. prt_line(s)
  199.     char           *s;
  200. {
  201.     register int    si = 0;
  202.     register int    c;
  203.     register int    col = 0;
  204.  
  205.     char            extra[16];
  206.     int             n_extra = 0;
  207.     int             n;
  208.  
  209.     for (;;) {
  210.  
  211.     if (n_extra > 0)
  212.         c = extra[--n_extra];
  213.     else {
  214.         c = s[si++];
  215.         if (c == TAB && !P(P_LS)) {
  216.         strcpy(extra, "                ");
  217.         /* tab amount depends on current column */
  218.         n_extra = (P(P_TS) - 1) - col % P(P_TS);
  219.         c = ' ';
  220.         } else if (c == NUL && P(P_LS)) {
  221.         extra[0] = NUL;
  222.         n_extra = 1;
  223.         c = '$';
  224.         } else if (c != NUL && (n = chars[c].ch_size) > 1) {
  225.         char           *p;
  226.  
  227.         n_extra = 0;
  228.         p = chars[c].ch_str;
  229.         /* copy 'ch-str'ing into 'extra' in reverse */
  230.         while (n > 1)
  231.             extra[n_extra++] = p[--n];
  232.         c = p[0];
  233.         }
  234.     }
  235.  
  236.     if (c == NUL)
  237.         break;
  238.  
  239.     outchar(c);
  240.     col++;
  241.     }
  242. }
  243.  
  244. void
  245. screenclear()
  246. {
  247.     register char  *rp;
  248.     register char  *np;
  249.     register char  *end;
  250.     register int    i;
  251.  
  252.     outstr(T_ED);        /* clear the display */
  253.  
  254.     rp = Realscreen;
  255.     end = Realscreen + Rows * Columns;
  256.     np = Nextscreen;
  257.  
  258.     /* blank out the stored screens */
  259.     while (rp != end)
  260.     *rp++ = *np++ = ' ';
  261.  
  262.     /* clear screen info */
  263.     for (i = 0; i < Rows; i++) {
  264.     LinePointers[i] = NULL;
  265.     LineSizes[i] = '\0';
  266.     }
  267.     NumLineSizes = 0;
  268. }
  269.  
  270. void
  271. cursupdate()
  272. {
  273.     LPtr           *p;
  274.     LPtr           *pp;
  275.     char            c;
  276.     int             incr, nlines;
  277.     int             i;
  278.     int             didincr;
  279.  
  280.     if (bufempty()) {        /* special case - file is empty */
  281.     *Topchar = *Filemem;
  282.     *Curschar = *Filemem;
  283.     for (i = 0; i < Rows; i++)
  284.         LineSizes[i] = 0;
  285.     } else if (LINEOF(Curschar) < LINEOF(Topchar)) {
  286.     nlines = cntllines(Curschar, Topchar);
  287.     /*
  288.      * if the cursor is above the top of the screen, put it at the top of
  289.      * the screen.. 
  290.      */
  291.     *Topchar = *Curschar;
  292.     Topchar->index = 0;
  293.     /*
  294.      * ... and, if we weren't very close to begin with, we scroll so that
  295.      * the line is close to the middle. 
  296.      */
  297.     if (nlines > Rows / 3) {
  298.         p = Topchar;
  299.         for (i = 0; i < Rows / 3; i += plines(p)) {
  300.         pp = prevline(p);
  301.         if (pp == NULL)
  302.             break;
  303.         p = pp;
  304.         }
  305.         *Topchar = *p;
  306.     } else
  307.         s_ins(0, nlines - 1, Rows, Columns);
  308.     updateNextscreen(VALID);
  309.     } else if (LINEOF(Curschar) >= LINEOF(Botchar)) {
  310.     nlines = cntllines(Botchar, Curschar);
  311.     /*
  312.      * If the cursor is off the bottom of the screen, put it at the top
  313.      * of the screen.. ... and back up 
  314.      */
  315.     if (nlines > Rows / 3) {
  316.         p = Curschar;
  317.         for (i = 0; i < (2 * Rows) / 3; i += plines(p)) {
  318.         pp = prevline(p);
  319.         if (pp == NULL)
  320.             break;
  321.         p = pp;
  322.         }
  323.         *Topchar = *p;
  324.     } else {
  325.         scrollup(nlines);
  326.     }
  327.     updateNextscreen(VALID);
  328.     }
  329.     Cursrow = Curscol = Cursvcol = i = 0;
  330.     for (p = Topchar; p->linep != Curschar->linep; p = nextline(p))
  331.     Cursrow += LineSizes[i++];
  332.  
  333.     if (P(P_NU))
  334.     Curscol = 8;
  335.  
  336.     Cline_row = Cursrow;
  337.     if (i >= NumLineSizes) {    /* Should only happen with a line that is too
  338.                  * long to fit on the last screen line. */
  339.     Cline_size = 0;
  340.     } else {
  341.     Cline_size = LineSizes[i];
  342.  
  343.     for (i = 0; i <= Curschar->index; i++) {
  344.         c = Curschar->linep->s[i];
  345.         /* A tab gets expanded, depending on the current column */
  346.         if (c == TAB && !P(P_LS))
  347.         incr = P(P_TS) - (Cursvcol % P(P_TS));
  348.         else
  349.         incr = chars[c].ch_size;
  350.         Curscol += incr;
  351.         Cursvcol += incr;
  352.         if (Curscol >= Columns) {
  353.         Curscol -= Columns;
  354.         Cursrow++;
  355.         didincr = TRUE;
  356.         } else
  357.         didincr = FALSE;
  358.     }
  359.     if (didincr)
  360.         Cursrow--;
  361.  
  362.     if (c == TAB && State == NORMAL && !P(P_LS)) {
  363.         Curscol--;
  364.         Cursvcol--;
  365.     } else {
  366.         Curscol -= incr;
  367.         Cursvcol -= incr;
  368.     }
  369.     if (Curscol < 0)
  370.         Curscol += Columns;
  371.     }
  372.  
  373.     if (set_want_col) {
  374.     Curswant = Cursvcol;
  375.     set_want_col = FALSE;
  376.     }
  377. }
  378.  
  379. /*
  380.  * The rest of the routines in this file perform screen manipulations. The
  381.  * given operation is performed physically on the screen. The corresponding
  382.  * change is also made to the internal screen image. In this way, the editor
  383.  * anticipates the effect of editing changes on the appearance of the screen.
  384.  * That way, when we call screenupdate a complete redraw isn't usually
  385.  * necessary. Another advantage is that we can keep adding code to anticipate
  386.  * screen changes, and in the meantime, everything still works. 
  387.  */
  388.  
  389. /*
  390.  * s_ins(row, nlines, total_rows, columns) - insert 'nlines' lines at 'row' 
  391.  */
  392. void
  393. s_ins(row, nlines, total_rows, columns)
  394.     int             row;
  395.     int             nlines;
  396.     int            total_rows;
  397.     int            columns;
  398. {
  399.     register char  *s;    /* src for block copy */
  400.     register char  *d;    /* dest for block copy */
  401.     register char  *e;    /* end point for copy */
  402.     int             i;
  403.  
  404.     if (nlines > (total_rows - 1 - row))
  405.     nlines = total_rows - 1 - row;
  406.  
  407.     if ((T_IL[0] == NUL) || RedrawingDisabled || nlines <= 0)
  408.     return;
  409.  
  410.     /*
  411.      * It "looks" better if we do all the inserts at once 
  412.      */
  413.     outstr(T_SC);        /* save position */
  414.  
  415.     if (T_IL_B[0] == NUL) {
  416.     for (i = 0; i < nlines; i++) {
  417.         windgoto(row, 0);
  418.         outstr(T_IL);
  419.     }
  420.     } else {
  421.     windgoto(row, 0);
  422.     outstr(T_IL);
  423.     if (nlines >= 10)
  424.         outchar((char) (nlines / 10 + '0'));
  425.     outchar((char) (nlines % 10 + '0'));
  426.     outstr(T_IL_B);
  427.     }
  428.  
  429.     windgoto(total_rows - 1, 0);    /* delete any garbage that may have */
  430.     outstr(T_EL);        /* been shifted to the bottom line */
  431.  
  432.     outstr(T_RC);        /* restore the cursor position */
  433.  
  434.     /*
  435.      * Now do a block move to update the internal screen image 
  436.      */
  437.     d = Realscreen + (columns * (total_rows - 1)) - 1;
  438.     s = d - (columns * nlines);
  439.     e = Realscreen + (columns * row);
  440.  
  441.     while (s >= e)
  442.     *d-- = *s--;
  443.  
  444.     /*
  445.      * Clear the inserted lines 
  446.      */
  447.     s = Realscreen + (row * columns);
  448.     e = s + (nlines * columns);
  449.     while (s < e)
  450.     *s++ = ' ';
  451. }
  452.  
  453. /*
  454.  * s_del(row, nlines, total_rows, columns) - delete 'nlines' lines at 'row' 
  455.  */
  456. void
  457. s_del(row, nlines, total_rows, columns)
  458.     int             row;
  459.     int             nlines;
  460.     int            total_rows;
  461.     int            columns;
  462. {
  463.     register char  *s;
  464.     register char  *d;
  465.     register char  *e;
  466.     int             i;
  467.  
  468.     if (nlines > (total_rows - 1 - row))
  469.     nlines = total_rows - 1 - row;
  470.  
  471.     if ((T_DL[0] == NUL) || RedrawingDisabled || nlines <= 0)
  472.     return;
  473.  
  474.     outstr(T_SC);        /* save position */
  475.  
  476.     windgoto(total_rows - 1, 0);    /* delete any garbage that */
  477.     outstr(T_EL);        /* was on the status line */
  478.  
  479.     /* delete the lines */
  480.     if (T_DL_B[0] == NUL) {
  481.     for (i = 0; i < nlines; i++) {
  482.         windgoto(row, 0);
  483.         outstr(T_DL);    /* delete a line */
  484.     }
  485.     } else {
  486.     windgoto(row, 0);
  487.     outstr(T_DL);
  488.     if (nlines >= 10)
  489.         outchar((char) (nlines / 10 + '0'));
  490.     outchar((char) (nlines % 10 + '0'));
  491.     outstr(T_DL_B);
  492.     }
  493.  
  494.     outstr(T_RC);        /* restore position */
  495.  
  496.     /*
  497.      * do a block move to update the internal image 
  498.      */
  499.     d = Realscreen + (row * columns);
  500.     s = d + (nlines * columns);
  501.     e = Realscreen + ((total_rows - 1) * columns);
  502.  
  503.     while (s < e)
  504.     *d++ = *s++;
  505.  
  506.     while (d < e)        /* clear the lines at the bottom */
  507.     *d++ = ' ';
  508. }
  509.