home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 4 / FreshFish_May-June1994.bin / bbs / may94 / util / edit / jade.lha / Jade / src / refresh.c < prev    next >
C/C++ Source or Header  |  1994-04-20  |  9KB  |  363 lines

  1. /* refresh.c -- Working out what to redraw in a window
  2.    Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
  3.  
  4. This file is part of Jade.
  5.  
  6. Jade is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. Jade is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with Jade; see the file COPYING.    If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "jade.h"
  21. #include "jade_protos.h"
  22.  
  23. _PR void refresh_init(void);
  24. _PR void refreshwindow(VW *);
  25. _PR void flaginsertion(TX *, POS *, POS *);
  26. _PR void flagdeletion(TX *, POS *, POS *);
  27. _PR void flagmodification(TX *, POS *, POS *);
  28. _PR void refreshworld(void);
  29. _PR void refreshworldcurs(void);
  30.  
  31. _PR VALUE cmd_cursor(VALUE status);
  32. DEFUN("cursor", cmd_cursor, subr_cursor, (VALUE status), V_Subr1, DOC_cursor) /*
  33. ::doc:cursor::
  34. (cursor STATUS)
  35. Turns cursor on or off, normally cursor is always off when an event is being
  36. evaluated.
  37. ::end:: */
  38. {
  39.     cursor(CurrVW, NILP(status) ? CURS_OFF : CURS_ON);
  40.     return(sym_t);
  41. }
  42.  
  43. _PR VALUE cmd_refresh_all(void);
  44. DEFUN("refresh-all", cmd_refresh_all, subr_refresh_all, (void), V_Subr0, DOC_refresh_all) /*
  45. ::doc:refresh_all::
  46. (refresh-all)
  47. Redraw anything that has been changed since the last refresh.
  48. ::end:: */
  49. {
  50.     refreshworld();
  51.     return(sym_t);
  52. }
  53.  
  54. void
  55. refresh_init(void)
  56. {
  57.     ADD_SUBR(subr_cursor);
  58.     ADD_SUBR(subr_refresh_all);
  59. }
  60.  
  61. /*
  62.  * If no changes have been made to the buffer, call this to do any vertical
  63.  * scrolling. Returns 0 if nothing happened, 1 if it scrolled a bit, 2
  64.  * if it redrew the whole window.
  65.  */
  66. static int
  67. vertscroll(VW *vw)
  68. {
  69.     long y = vw->vw_StartLine - vw->vw_LastDisplayOrigin.pos_Line;
  70.     if(y < 0)
  71.     {
  72.     if(-y > vw->vw_MaxScroll)
  73.     {
  74.         redrawall(vw);
  75.         return(2);
  76.     }
  77.     else
  78.     {
  79.         scrollvw(vw, y);
  80.         redrawlines(vw, vw->vw_StartLine,
  81.             vw->vw_LastDisplayOrigin.pos_Line);
  82.         return(1);
  83.     }
  84.     }
  85.     else if(y > 0)
  86.     {
  87.     if(y > vw->vw_MaxScroll)
  88.     {
  89.         redrawall(vw);
  90.         return(2);
  91.     }
  92.     else
  93.     {
  94.         scrollvw(vw, y);
  95.         redrawlines(vw, vw->vw_StartLine + vw->vw_MaxY - y,
  96.             vw->vw_StartLine + vw->vw_MaxY);
  97.         return(1);
  98.     }
  99.     }
  100.     return(0);
  101. }
  102.  
  103. /*
  104.  * Refreshes one window.
  105.  */
  106. void
  107. refreshwindow(VW *vw)
  108. {
  109.     TX *tx = vw->vw_Tx;
  110.     if(vw && vw->vw_Window && (!vw->vw_DeferRefresh))
  111.     {
  112.     if(!vw->vw_Sleeping)
  113.     {
  114.         if(vw->vw_Flags & VWFF_REFRESH_STATUS)
  115.         {
  116.         setvwtitle(vw);
  117.         vw->vw_Flags &= ~VWFF_REFRESH_STATUS;
  118.         }
  119.         resyncxy(vw);
  120.         if((vw->vw_LastRefTx != vw->vw_Tx)
  121.            || (vw->vw_Flags & VWFF_FORCE_REFRESH)
  122.            || (tx->tx_Flags & TXFF_REFRESH_ALL))
  123.         {
  124.         redrawall(vw);
  125.         vw->vw_Flags &= ~(VWFF_FORCE_REFRESH | VWFF_REFRESH_BLOCK);
  126.         tx->tx_Flags &= ~TXFF_REFRESH_ALL;
  127.         }
  128.         else if(tx->tx_Changes == tx->tx_LastChanges)
  129.         {
  130.         vertscroll(vw);
  131.         if(vw->vw_Flags & VWFF_REFRESH_BLOCK)
  132.         {
  133.             redrawlinesclr(vw, vw->vw_BlockS.pos_Line,
  134.                    vw->vw_BlockE.pos_Line);
  135.             vw->vw_Flags &= ~VWFF_REFRESH_BLOCK;
  136.         }
  137.         }
  138.         else
  139.         {
  140.         long endline = vw->vw_StartLine + vw->vw_MaxY;
  141.         int vscrl;
  142.         /* check if modified region hits window */
  143.         if((vw->vw_StartLine > tx->tx_ModEnd.pos_Line)
  144.            || (endline <= tx->tx_ModStart.pos_Line))
  145.         {
  146.             /* nope. just do any easy scrolling. */
  147.             vertscroll(vw);
  148.             if(vw->vw_Flags & VWFF_REFRESH_BLOCK)
  149.             {
  150.             redrawlinesclr(vw, vw->vw_BlockS.pos_Line,
  151.                        vw->vw_BlockE.pos_Line);
  152.             vw->vw_Flags &= ~VWFF_REFRESH_BLOCK;
  153.             }
  154.         }
  155.         else if((vscrl = vertscroll(vw)) != 2)
  156.         {
  157.             /* is modified region just one line? */
  158.             if(tx->tx_ModStart.pos_Line == tx->tx_ModEnd.pos_Line)
  159.             {
  160.             if(vw->vw_Flags & VWFF_REFRESH_BLOCK)
  161.             {
  162.                 redrawlinesclr(vw, vw->vw_BlockS.pos_Line,
  163.                        vw->vw_BlockE.pos_Line);
  164.                 if((tx->tx_ModStart.pos_Line < vw->vw_BlockS.pos_Line)
  165.                    || (tx->tx_ModStart.pos_Line > vw->vw_BlockE.pos_Line))
  166.                 redrawlinefrom(vw, tx->tx_ModStart.pos_Col,
  167.                            tx->tx_ModStart.pos_Line);
  168.                 vw->vw_Flags &= ~VWFF_REFRESH_BLOCK;
  169.             }
  170.             else
  171.                 redrawlinefrom(vw, tx->tx_ModStart.pos_Col,
  172.                            tx->tx_ModStart.pos_Line);
  173.             }
  174.             else if(tx->tx_ModDelta == 0)
  175.             {
  176.             /* not able to do any pasting */
  177.             redrawregion(vw, &tx->tx_ModStart, &tx->tx_ModEnd);
  178.             if(vw->vw_Flags & VWFF_REFRESH_BLOCK)
  179.             {
  180.                 if(!(POS_LESS_P(&vw->vw_BlockE, &tx->tx_ModEnd)
  181.                  && POS_GREATER_P(&vw->vw_BlockS, &tx->tx_ModStart)))
  182.                 redrawlinesclr(vw, vw->vw_BlockS.pos_Line,
  183.                            vw->vw_BlockE.pos_Line);
  184.                 vw->vw_Flags &= ~VWFF_REFRESH_BLOCK;
  185.             }
  186.             }
  187.             else if(tx->tx_ModDelta > 0)
  188.             {
  189.             /* lines have been added: move down the lines they
  190.                displaced. */
  191.             if(vscrl == 0)
  192.                 cutpastelines(vw, tx->tx_ModStart.pos_Line + 1,
  193.                       tx->tx_ModStart.pos_Line + tx->tx_ModDelta + 1);
  194.             redrawregion(vw, &tx->tx_ModStart, &tx->tx_ModEnd);
  195.             if(vw->vw_Flags & VWFF_REFRESH_BLOCK)
  196.             {
  197.                 if(!(POS_LESS_P(&vw->vw_BlockE, &tx->tx_ModEnd)
  198.                  && POS_GREATER_P(&vw->vw_BlockS, &tx->tx_ModStart)))
  199.                 redrawlinesclr(vw, vw->vw_BlockS.pos_Line,
  200.                            vw->vw_BlockE.pos_Line);
  201.                 vw->vw_Flags &= ~VWFF_REFRESH_BLOCK;
  202.             }
  203.             }
  204.             else if(tx->tx_ModDelta < 0)
  205.             {
  206.             /* lines deleted. */
  207.             if(vscrl == 0)
  208.             {
  209.                 if(tx->tx_ModStart.pos_Col == 0)
  210.                 cutpastelines(vw, tx->tx_ModEnd.pos_Line,
  211.                           tx->tx_ModEnd.pos_Line + tx->tx_ModDelta);
  212.                 else
  213.                 cutpastelines(vw, tx->tx_ModEnd.pos_Line + 1,
  214.                           tx->tx_ModEnd.pos_Line + tx->tx_ModDelta + 1);
  215.             }
  216.             redrawregion(vw, &tx->tx_ModStart, &tx->tx_ModEnd);
  217.             if(vw->vw_Flags & VWFF_REFRESH_BLOCK)
  218.             {
  219.                 if(!(POS_LESS_P(&vw->vw_BlockE, &tx->tx_ModEnd)
  220.                  && POS_GREATER_P(&vw->vw_BlockS, &tx->tx_ModStart)))
  221.                 redrawlinesclr(vw, vw->vw_BlockS.pos_Line,
  222.                            vw->vw_BlockE.pos_Line);
  223.                 vw->vw_Flags &= ~VWFF_REFRESH_BLOCK;
  224.             }
  225.             }
  226.         }
  227.         }
  228.         vw->vw_LastRefTx = tx;
  229.     }
  230.     else
  231.         vw->vw_Flags |= VWFF_FORCE_REFRESH;
  232.     }
  233.     else if(vw)
  234.     {
  235.     if(!(--vw->vw_DeferRefresh))
  236.         vw->vw_Flags |= VWFF_FORCE_REFRESH;
  237.     }
  238. }
  239.  
  240. /*
  241.  * Notes that buffer TX has had text added between START and END.
  242.  */
  243. void
  244. flaginsertion(TX *tx, POS *start, POS *end)
  245. {
  246.     if(tx->tx_LastChanges == tx->tx_Changes)
  247.     {
  248.     /* first insertion */
  249.     tx->tx_ModStart = *start;
  250.     tx->tx_ModEnd = *end;
  251.     tx->tx_ModDelta = end->pos_Line - start->pos_Line;
  252.     }
  253.     else
  254.     {
  255.     if(POS_LESS_P(start, &tx->tx_ModStart))
  256.         tx->tx_ModStart = *start;
  257.     if(POS_GREATER_P(end, &tx->tx_ModEnd))
  258.         tx->tx_ModEnd = *end;
  259.     tx->tx_ModDelta += end->pos_Line - start->pos_Line;
  260.     }
  261.     tx->tx_Changes++;
  262. }
  263.  
  264. /*
  265.  * Same for deleted areas.
  266.  */
  267. void
  268. flagdeletion(TX *tx, POS *start, POS *end)
  269. {
  270.     if(tx->tx_LastChanges == tx->tx_Changes)
  271.     {
  272.     /* first */
  273.     tx->tx_ModStart = *start;
  274.     tx->tx_ModEnd = *end;
  275.     tx->tx_ModDelta = -(end->pos_Line - start->pos_Line);
  276.     }
  277.     else
  278.     {
  279.     if(POS_LESS_P(start, &tx->tx_ModStart))
  280.         tx->tx_ModStart = *start;
  281.     if(POS_GREATER_P(end, &tx->tx_ModEnd))
  282.         tx->tx_ModEnd = *end;
  283.     tx->tx_ModDelta -= end->pos_Line - start->pos_Line;
  284.     }
  285.     tx->tx_Changes++;
  286. }
  287.  
  288. /*
  289.  * Means that there is still the same layout of text between START and END,
  290.  * but some of the character values may have been modified.
  291.  */
  292. void
  293. flagmodification(TX *tx, POS *start, POS *end)
  294. {
  295.     if(tx->tx_LastChanges == tx->tx_Changes)
  296.     {
  297.     /* first */
  298.     tx->tx_ModStart = *start;
  299.     tx->tx_ModEnd = *end;
  300.     tx->tx_ModDelta = 0;
  301.     }
  302.     else
  303.     {
  304.     if(POS_LESS_P(start, &tx->tx_ModStart))
  305.         tx->tx_ModStart = *start;
  306.     if(POS_GREATER_P(end, &tx->tx_ModEnd))
  307.         tx->tx_ModEnd = *end;
  308.     }
  309.     tx->tx_Changes++;
  310. }
  311.  
  312. /*
  313.  * Refeshes everything that should be.
  314.  */
  315. void
  316. refreshworld(void)
  317. {
  318.     VW *vw;
  319.     TX *tx;
  320.     for(vw = ViewChain; vw; vw = vw->vw_Next)
  321.     {
  322.     if(vw->vw_Window)
  323.         refres