home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff256.lzh / Stevie / s_io.c < prev    next >
C/C++ Source or Header  |  1989-10-19  |  10KB  |  487 lines

  1. /*
  2.  * s_io() - routines that do screen I/O or effect what we think is
  3.  *          on the screen.
  4.  *
  5.  * By G. R. (Fred) Walter    watmath!grwalter 
  6.  */
  7.  
  8. #include "stevie.h"
  9.  
  10. /*
  11.  * s_cursor_off() - turn off the cursor (if it is appropriate)
  12.  */
  13.  
  14. void
  15. s_cursor_off()
  16. {
  17. #ifdef AMIGA
  18.     if (!Aux_Device)
  19.     outstr(T_CI);
  20. #else
  21.     outstr(T_CI);
  22. #endif
  23. }
  24.  
  25. /*
  26.  * s_cursor_on() - turn on the cursor (if it is appropriate)
  27.  */
  28.  
  29. void
  30. s_cursor_on()
  31. {
  32. #ifdef AMIGA
  33.     if (!Aux_Device)
  34.     outstr(T_CV);
  35. #else
  36.     outstr(T_CV);
  37. #endif
  38. }
  39.  
  40. /*
  41.  * screen_ins(row, nlines, total_rows) - insert 'nlines' lines at 'row' 
  42.  *
  43.  * NOTE: this routine assumes it is called with valid arguments.
  44.  */
  45.  
  46. static void
  47. screen_ins(row, nlines, total_rows)
  48.     int             row;
  49.     int             nlines;
  50.     int             total_rows;
  51. {
  52.     if (nlines < 1 || (row + nlines) > total_rows)
  53.     return;
  54.  
  55. #ifndef T_IL_B
  56.     {
  57.     int             i;
  58.  
  59.     for (i = 0; i < nlines; i++) {
  60.         windgoto(row, 0);
  61.         outstr(T_IL);
  62.     }
  63.     }
  64. #else
  65.     windgoto(row, 0);
  66.     outstr(T_IL);
  67.     if (nlines >= 10)
  68.     outchar((char) (nlines / 10 + '0'));
  69.     outchar((char) (nlines % 10 + '0'));
  70.     outstr(T_IL_B);
  71. #endif
  72.  
  73.     /* delete any garbage that may have been shifted to the status line */
  74.     windgoto(total_rows - 1, 0);
  75.     outstr(T_EL);
  76. }
  77.  
  78. /*
  79.  * screen_del(row, nlines, total_rows) - delete 'nlines' lines at 'row' 
  80.  *
  81.  * NOTE: this routine assumes it is called with valid arguments.
  82.  */
  83.  
  84. static void
  85. screen_del(row, nlines, total_rows)
  86.     int             row;
  87.     int             nlines;
  88.     int             total_rows;
  89. {
  90.     if (nlines < 1 || (row + nlines) > total_rows)
  91.     return;
  92.  
  93.     /* delete any garbage that may have been on the status line */
  94.     windgoto(total_rows - 1, 0);
  95.     outstr(T_EL);
  96.  
  97. #ifndef T_DL_B
  98.     {
  99.     int             i;
  100.  
  101.     for (i = 0; i < nlines; i++) {
  102.         windgoto(row, 0);
  103.         outstr(T_DL);    /* delete a line */
  104.     }
  105.     }
  106. #else
  107.     windgoto(row, 0);
  108.     outstr(T_DL);
  109.     if (nlines >= 10)
  110.     outchar((char) (nlines / 10 + '0'));
  111.     outchar((char) (nlines % 10 + '0'));
  112.     outstr(T_DL_B);
  113. #endif
  114. }
  115.  
  116. /*
  117.  * screen_refresh()
  118.  *
  119.  * Based on the current value of Topchar, refresh the contents of the screen
  120.  * and update Botchar.
  121.  */
  122.  
  123. static void
  124. screen_refresh(type)
  125.     int             type;
  126. {
  127.     char           *ptr;
  128.     int             total_rows;
  129.     int             row;
  130.     int             col;
  131.     LINE           *memp;
  132.     LPtr            start;
  133.     bool_t          off_top;
  134.     bool_t          done;    /* if TRUE, we hit the end of the file */
  135.     bool_t          didline;    /* if TRUE, we finished the last line */
  136.     int             lno;    /* number of the line we're doing */
  137.     int             idx;
  138.     int             i;
  139.     int             j;
  140.  
  141.     if (NumLineSizes <= 0)
  142.     type = NOT_VALID;
  143.  
  144.     if (!RedrawingDisabled)
  145.     s_cursor_off();
  146.  
  147.     off_top = FALSE;
  148.     idx = 0;
  149.     row = 0;
  150.     total_rows = Rows - 1;
  151.     memp = Topchar->linep;
  152.  
  153.     if ((type == VALID) || (type == VALID_TO_CURSCHAR)) {
  154.     j = -1;
  155.     for (i = 0; i < NumLineSizes; i++) {
  156.         if (LinePointers[i] == memp) {
  157.         j = i;
  158.         break;
  159.         }
  160.         row += LineSizes[i];
  161.     }
  162.     if (j == -1) {
  163.         /* Are we off the top of the screen by one line ? */
  164.         if (memp->next == LinePointers[0]) {
  165.         i = plines(Topchar->linep->s);
  166.         if (i < (total_rows)) {
  167.             off_top = TRUE;
  168.             for (idx = NumLineSizes; idx > 0; idx--) {
  169.             LinePointers[idx] = LinePointers[idx - 1];
  170.             LineSizes[idx] = LineSizes[idx - 1];
  171.             }
  172.             LineSizes[idx] = (char) i;
  173.             if (!RedrawingDisabled)
  174.             screen_ins(0, i, Rows);
  175.         }
  176.         }
  177.         row = 0;
  178.     } else if (j == 0 && type == VALID) {
  179.         if (!RedrawingDisabled)
  180.         s_cursor_on();
  181.         return;
  182.     } else {
  183.         if (!RedrawingDisabled)
  184.         screen_del(0, row, Rows);
  185.         row = 0;
  186.         for (;;) {
  187.         LineSizes[idx] = LineSizes[j];
  188.         LinePointers[idx] = LinePointers[j];
  189.  
  190.         if (type == VALID_TO_CURSCHAR) {
  191.             if (LinePointers[idx] == Curschar->linep) {
  192.             memp = LinePointers[idx];
  193.             break;
  194.             }
  195.         }
  196.         j++;
  197.         if (j >= NumLineSizes) {
  198.             memp = LinePointers[idx];
  199.             if (memp->next != Fileend->linep) {
  200.             row += LineSizes[idx];
  201.             idx++;
  202.             memp = memp->next;
  203.             }
  204.             break;
  205.         }
  206.         row += LineSizes[idx];
  207.         idx++;
  208.         }
  209.     }
  210.     }
  211.     if (P(P_NU)) {
  212.     start.linep = memp;
  213.     lno = cntllines(Filemem, &start);
  214.     }
  215.     didline = TRUE;
  216.     done = FALSE;
  217.  
  218.     for (;;) {
  219.     ptr = format_line(memp->s, &col);
  220.     i = 1 + ((col - 1) / Columns);
  221.     if ((row + i) <= total_rows) {
  222.         LinePointers[idx] = memp;
  223.         LineSizes[idx++] = (char) i;
  224.         if (!RedrawingDisabled) {
  225.         windgoto(row, 0);
  226.  
  227.         if (P(P_NU))
  228.             outstr(mkline(lno++));
  229.         outstr(ptr);
  230.  
  231.         j = col;
  232.         col %= Columns;
  233.         if ((col != 0) || (j == 0)) {
  234. #ifdef T_END_L
  235.             windgoto(row + i - 1, col);
  236.             outstr(T_END_L);
  237. #else
  238.             for (; col < Columns; col++)
  239.             outchar(' ');
  240. #endif
  241.         }
  242.         }
  243.         row += i;
  244.         if (memp->next != Fileend->linep) {
  245.         memp = memp->next;
  246.         } else {
  247.         done = TRUE;
  248.         break;
  249.         }
  250.         if (off_top)
  251.         break;
  252.     } else {
  253.         didline = FALSE;
  254.         break;
  255.     }
  256.     }
  257.  
  258.     /* Do we have to do 'off the top of the screen' processing ? */
  259.     if (off_top && !done) {
  260.     row = 0;
  261.     for (idx = 0; idx <= NumLineSizes && row < total_rows; idx++) {
  262.         row += LineSizes[idx];
  263.     }
  264.  
  265.     idx--;
  266.  
  267.     if (row < total_rows) {
  268.         if (LinePointers[idx]->next == Fileend->linep)
  269.         done = TRUE;
  270.         idx++;
  271.     } else if (row > total_rows) {
  272.         row -= LineSizes[idx];
  273.         didline = FALSE;
  274.         memp = LinePointers[idx];
  275.     } else {
  276.         didline = TRUE;
  277.         memp = LinePointers[idx]->next;
  278.         idx++;
  279.     }
  280.     }
  281.     NumLineSizes = idx;
  282.  
  283.     if (done && didline) {
  284.     ptr = "~\n\r";
  285.     } else {
  286.     ptr = "@\n\r";
  287.     }
  288.  
  289.     if (!RedrawingDisabled) {
  290.     if (row < total_rows) {
  291.         /* Clear the rest of the screen. */
  292. #ifdef T_END_D
  293.         windgoto(row, 0);
  294.         outstr(T_END_D);
  295. #else
  296.         screen_del(row, total_rows - row, Rows);
  297.         windgoto(row, 0);
  298. #endif
  299.     }
  300.     /* put '@'s or '~'s on the remaining rows */
  301.     for (; row < total_rows; row++)
  302.         outstr(ptr);
  303.  
  304.     s_cursor_on();
  305.     }
  306.     if (done)
  307.     *Botchar = *Fileend;    /* we hit the end of the file */
  308.     else
  309.     Botchar->linep = memp;
  310. }
  311.  
  312. /*
  313.  * s_refresh()
  314.  *
  315.  * Based on the current value of Curschar, (if necessary) update Topchar and
  316.  * Botchar and refresh the screen contensts.
  317.  */
  318.  
  319. void
  320. s_refresh(type)
  321.     int             type;
  322. {
  323.     LPtr           *p;
  324.     LPtr           *pp;
  325.     int             i;
  326.     int             nlines;
  327.     int             refreshed;
  328.  
  329.     refreshed = FALSE;
  330.  
  331.     if (bufempty()) {        /* special case - file is empty */
  332.     *Topchar = *Filemem;
  333.     *Curschar = *Filemem;
  334.     screen_refresh(NOT_VALID);
  335.     return;
  336.     }
  337.     if (NumLineSizes < 0) {
  338.     type = NOT_VALID;
  339.     }
  340.     if (type != VALID) {
  341.     screen_refresh(type);
  342.     refreshed = TRUE;
  343.     type = VALID;
  344.     }
  345.     if (LINEOF(Curschar) < LINEOF(Topchar)) {
  346.     nlines = cntllines(Curschar, Topchar);
  347.     /*
  348.      * if the cursor is above the top of the screen, put it at the top of
  349.      * the screen.. 
  350.      */
  351.     *Topchar = *Curschar;
  352.     Topchar->index = 0;
  353.     /*
  354.      * ... and, if we weren't very close to begin with, we scroll so that
  355.      * the line is close to the middle. 
  356.      */
  357.     if (nlines > Rows / 3) {
  358.         p = Topchar;
  359.         for (i = 0; i < Rows / 3; i += plines(p->linep->s)) {
  360.         pp = prevline(p);
  361.         if (pp == NULL)
  362.             break;
  363.         p = pp;
  364.         }
  365.         *Topchar = *p;
  366.     }
  367.     screen_refresh(VALID);
  368.     } else if (LINEOF(Curschar) >= LINEOF(Botchar)) {
  369.     nlines = cntllines(Botchar, Curschar);
  370.     /*
  371.      * If the cursor is off the bottom of the screen, put it at the top
  372.      * of the screen.. ... and back up 
  373.      */
  374.     if (nlines > Rows / 3) {
  375.         p = Curschar;
  376.         for (i = 0; i < (2 * Rows) / 3; i += plines(p->linep->s)) {
  377.         pp = prevline(p);
  378.         if (pp == NULL)
  379.             break;
  380.         p = pp;
  381.         }
  382.         *Topchar = *p;
  383.     } else {
  384.         scrollup(nlines);
  385.     }
  386.     screen_refresh(VALID);
  387.     } else if (refreshed == FALSE) {
  388.     screen_refresh(type);
  389.     }
  390.     /* Check if we are below Botchar (this can occur). */
  391.     if (LINEOF(Curschar) == LINEOF(Botchar)) {
  392.     pp = nextline(Topchar);
  393.     if (pp != NULL) {
  394.         Topchar->linep = pp->linep;
  395.         screen_refresh(VALID);
  396.     }
  397.     } else if (LINEOF(Curschar) >= LINEOF(Botchar)) {
  398.     nlines = cntllines(Botchar, Curschar);
  399.     /*
  400.      * If the cursor is off the bottom of the screen, put it at the top
  401.      * of the screen.. ... and back up 
  402.      */
  403.     if (nlines > Rows / 3) {
  404.         p = Curschar;
  405.         for (i = 0; i < (2 * Rows) / 3; i += plines(p->linep->s)) {
  406.         pp = prevline(p);
  407.         if (pp == NULL)
  408.             break;
  409.         p = pp;
  410.         }
  411.         *Topchar = *p;
  412.     } else {
  413.         scrollup(nlines);
  414.     }
  415.     screen_refresh(VALID);
  416.     }
  417. }
  418.  
  419. /*
  420.  * s_clear() - clear the screen and mark the stored information as invalid.
  421.  */
  422. void
  423. s_clear()
  424. {
  425.     outstr(T_ED);        /* clear the display */
  426.     S_NOT_VALID;
  427. }
  428.  
  429. /*
  430.  * Update_Botchar()
  431.  *
  432.  * Based on the current value of Topchar update Botchar.
  433.  */
  434.  
  435. void
  436. Update_Botchar()
  437. {
  438.     int             row;
  439.     LINE           *memp;
  440.     int             total_rows;
  441.     int             i;
  442.  
  443.     row = 0;
  444.     total_rows = Rows - 1;
  445.     memp = Topchar->linep;
  446.  
  447.     for (;;) {
  448.     i = plines(memp->s);
  449.     if ((row + i) <= total_rows) {
  450.         row += i;
  451.         memp = memp->next;
  452.         if (memp == Fileend->linep)
  453.         break;
  454.     } else {
  455.         break;
  456.     }
  457.     }
  458.     Botchar->linep = memp;
  459.  
  460.     MustUpdateBotchar = FALSE;
  461. }
  462.  
  463. #ifdef DONTINCLUDEANYMORE
  464. /*
  465.  * NotValidFromCurschar()
  466.  *
  467.  * Mark the lines in NumLinePointers and NumLineSizes from Curschar on as
  468.  * not valid.
  469.  */
  470.  
  471. void
  472. NotValidFromCurschar()
  473. {
  474.     register int    idx;
  475.     register unsigned long num;
  476.  
  477.     S_VALID_TO_CURSCHAR;
  478.  
  479.     num = LINEOF(Curschar);
  480.     for (idx = 0; idx < NumLineSizes; idx++) {
  481.     if (LinePointers[idx]->num >= num)
  482.         break;
  483.     }
  484.     NumLineSizes = idx;
  485. }
  486. #endif
  487.