home *** CD-ROM | disk | FTP | other *** search
- /* refresh.c -- Working out what to redraw in a window
- Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
-
- This file is part of Jade.
-
- Jade is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- Jade is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Jade; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include "jade.h"
- #include "jade_protos.h"
-
- _PR void refresh_init(void);
- _PR void refreshwindow(VW *);
- _PR void flaginsertion(TX *, POS *, POS *);
- _PR void flagdeletion(TX *, POS *, POS *);
- _PR void flagmodification(TX *, POS *, POS *);
- _PR void refreshworld(void);
- _PR void refreshworldcurs(void);
-
- _PR VALUE cmd_cursor(VALUE status);
- DEFUN("cursor", cmd_cursor, subr_cursor, (VALUE status), V_Subr1, DOC_cursor) /*
- ::doc:cursor::
- (cursor STATUS)
- Turns cursor on or off, normally cursor is always off when an event is being
- evaluated.
- ::end:: */
- {
- cursor(CurrVW, NILP(status) ? CURS_OFF : CURS_ON);
- return(sym_t);
- }
-
- _PR VALUE cmd_refresh_all(void);
- DEFUN("refresh-all", cmd_refresh_all, subr_refresh_all, (void), V_Subr0, DOC_refresh_all) /*
- ::doc:refresh_all::
- (refresh-all)
- Redraw anything that has been changed since the last refresh.
- ::end:: */
- {
- refreshworld();
- return(sym_t);
- }
-
- void
- refresh_init(void)
- {
- ADD_SUBR(subr_cursor);
- ADD_SUBR(subr_refresh_all);
- }
-
- /*
- * If no changes have been made to the buffer, call this to do any vertical
- * scrolling. Returns 0 if nothing happened, 1 if it scrolled a bit, 2
- * if it redrew the whole window.
- */
- static int
- vertscroll(VW *vw)
- {
- long y = vw->vw_StartLine - vw->vw_LastDisplayOrigin.pos_Line;
- if(y < 0)
- {
- if(-y > vw->vw_MaxScroll)
- {
- redrawall(vw);
- return(2);
- }
- else
- {
- scrollvw(vw, y);
- redrawlines(vw, vw->vw_StartLine,
- vw->vw_LastDisplayOrigin.pos_Line);
- return(1);
- }
- }
- else if(y > 0)
- {
- if(y > vw->vw_MaxScroll)
- {
- redrawall(vw);
- return(2);
- }
- else
- {
- scrollvw(vw, y);
- redrawlines(vw, vw->vw_StartLine + vw->vw_MaxY - y,
- vw->vw_StartLine + vw->vw_MaxY);
- return(1);
- }
- }
- return(0);
- }
-
- /*
- * Refreshes one window.
- */
- void
- refreshwindow(VW *vw)
- {
- TX *tx = vw->vw_Tx;
- if(vw && vw->vw_Window && (!vw->vw_DeferRefresh))
- {
- if(!vw->vw_Sleeping)
- {
- if(vw->vw_Flags & VWFF_REFRESH_STATUS)
- {
- setvwtitle(vw);
- vw->vw_Flags &= ~VWFF_REFRESH_STATUS;
- }
- resyncxy(vw);
- if((vw->vw_LastRefTx != vw->vw_Tx)
- || (vw->vw_Flags & VWFF_FORCE_REFRESH)
- || (tx->tx_Flags & TXFF_REFRESH_ALL))
- {
- redrawall(vw);
- vw->vw_Flags &= ~(VWFF_FORCE_REFRESH | VWFF_REFRESH_BLOCK);
- tx->tx_Flags &= ~TXFF_REFRESH_ALL;
- }
- else if(tx->tx_Changes == tx->tx_LastChanges)
- {
- vertscroll(vw);
- if(vw->vw_Flags & VWFF_REFRESH_BLOCK)
- {
- redrawlinesclr(vw, vw->vw_BlockS.pos_Line,
- vw->vw_BlockE.pos_Line);
- vw->vw_Flags &= ~VWFF_REFRESH_BLOCK;
- }
- }
- else
- {
- long endline = vw->vw_StartLine + vw->vw_MaxY;
- int vscrl;
- /* check if modified region hits window */
- if((vw->vw_StartLine > tx->tx_ModEnd.pos_Line)
- || (endline <= tx->tx_ModStart.pos_Line))
- {
- /* nope. just do any easy scrolling. */
- vertscroll(vw);
- if(vw->vw_Flags & VWFF_REFRESH_BLOCK)
- {
- redrawlinesclr(vw, vw->vw_BlockS.pos_Line,
- vw->vw_BlockE.pos_Line);
- vw->vw_Flags &= ~VWFF_REFRESH_BLOCK;
- }
- }
- else if((vscrl = vertscroll(vw)) != 2)
- {
- /* is modified region just one line? */
- if(tx->tx_ModStart.pos_Line == tx->tx_ModEnd.pos_Line)
- {
- if(vw->vw_Flags & VWFF_REFRESH_BLOCK)
- {
- redrawlinesclr(vw, vw->vw_BlockS.pos_Line,
- vw->vw_BlockE.pos_Line);
- if((tx->tx_ModStart.pos_Line < vw->vw_BlockS.pos_Line)
- || (tx->tx_ModStart.pos_Line > vw->vw_BlockE.pos_Line))
- redrawlinefrom(vw, tx->tx_ModStart.pos_Col,
- tx->tx_ModStart.pos_Line);
- vw->vw_Flags &= ~VWFF_REFRESH_BLOCK;
- }
- else
- redrawlinefrom(vw, tx->tx_ModStart.pos_Col,
- tx->tx_ModStart.pos_Line);
- }
- else if(tx->tx_ModDelta == 0)
- {
- /* not able to do any pasting */
- redrawregion(vw, &tx->tx_ModStart, &tx->tx_ModEnd);
- if(vw->vw_Flags & VWFF_REFRESH_BLOCK)
- {
- if(!(POS_LESS_P(&vw->vw_BlockE, &tx->tx_ModEnd)
- && POS_GREATER_P(&vw->vw_BlockS, &tx->tx_ModStart)))
- redrawlinesclr(vw, vw->vw_BlockS.pos_Line,
- vw->vw_BlockE.pos_Line);
- vw->vw_Flags &= ~VWFF_REFRESH_BLOCK;
- }
- }
- else if(tx->tx_ModDelta > 0)
- {
- /* lines have been added: move down the lines they
- displaced. */
- if(vscrl == 0)
- cutpastelines(vw, tx->tx_ModStart.pos_Line + 1,
- tx->tx_ModStart.pos_Line + tx->tx_ModDelta + 1);
- redrawregion(vw, &tx->tx_ModStart, &tx->tx_ModEnd);
- if(vw->vw_Flags & VWFF_REFRESH_BLOCK)
- {
- if(!(POS_LESS_P(&vw->vw_BlockE, &tx->tx_ModEnd)
- && POS_GREATER_P(&vw->vw_BlockS, &tx->tx_ModStart)))
- redrawlinesclr(vw, vw->vw_BlockS.pos_Line,
- vw->vw_BlockE.pos_Line);
- vw->vw_Flags &= ~VWFF_REFRESH_BLOCK;
- }
- }
- else if(tx->tx_ModDelta < 0)
- {
- /* lines deleted. */
- if(vscrl == 0)
- {
- if(tx->tx_ModStart.pos_Col == 0)
- cutpastelines(vw, tx->tx_ModEnd.pos_Line,
- tx->tx_ModEnd.pos_Line + tx->tx_ModDelta);
- else
- cutpastelines(vw, tx->tx_ModEnd.pos_Line + 1,
- tx->tx_ModEnd.pos_Line + tx->tx_ModDelta + 1);
- }
- redrawregion(vw, &tx->tx_ModStart, &tx->tx_ModEnd);
- if(vw->vw_Flags & VWFF_REFRESH_BLOCK)
- {
- if(!(POS_LESS_P(&vw->vw_BlockE, &tx->tx_ModEnd)
- && POS_GREATER_P(&vw->vw_BlockS, &tx->tx_ModStart)))
- redrawlinesclr(vw, vw->vw_BlockS.pos_Line,
- vw->vw_BlockE.pos_Line);
- vw->vw_Flags &= ~VWFF_REFRESH_BLOCK;
- }
- }
- }
- }
- vw->vw_LastRefTx = tx;
- }
- else
- vw->vw_Flags |= VWFF_FORCE_REFRESH;
- }
- else if(vw)
- {
- if(!(--vw->vw_DeferRefresh))
- vw->vw_Flags |= VWFF_FORCE_REFRESH;
- }
- }
-
- /*
- * Notes that buffer TX has had text added between START and END.
- */
- void
- flaginsertion(TX *tx, POS *start, POS *end)
- {
- if(tx->tx_LastChanges == tx->tx_Changes)
- {
- /* first insertion */
- tx->tx_ModStart = *start;
- tx->tx_ModEnd = *end;
- tx->tx_ModDelta = end->pos_Line - start->pos_Line;
- }
- else
- {
- if(POS_LESS_P(start, &tx->tx_ModStart))
- tx->tx_ModStart = *start;
- if(POS_GREATER_P(end, &tx->tx_ModEnd))
- tx->tx_ModEnd = *end;
- tx->tx_ModDelta += end->pos_Line - start->pos_Line;
- }
- tx->tx_Changes++;
- }
-
- /*
- * Same for deleted areas.
- */
- void
- flagdeletion(TX *tx, POS *start, POS *end)
- {
- if(tx->tx_LastChanges == tx->tx_Changes)
- {
- /* first */
- tx->tx_ModStart = *start;
- tx->tx_ModEnd = *end;
- tx->tx_ModDelta = -(end->pos_Line - start->pos_Line);
- }
- else
- {
- if(POS_LESS_P(start, &tx->tx_ModStart))
- tx->tx_ModStart = *start;
- if(POS_GREATER_P(end, &tx->tx_ModEnd))
- tx->tx_ModEnd = *end;
- tx->tx_ModDelta -= end->pos_Line - start->pos_Line;
- }
- tx->tx_Changes++;
- }
-
- /*
- * Means that there is still the same layout of text between START and END,
- * but some of the character values may have been modified.
- */
- void
- flagmodification(TX *tx, POS *start, POS *end)
- {
- if(tx->tx_LastChanges == tx->tx_Changes)
- {
- /* first */
- tx->tx_ModStart = *start;
- tx->tx_ModEnd = *end;
- tx->tx_ModDelta = 0;
- }
- else
- {
- if(POS_LESS_P(start, &tx->tx_ModStart))
- tx->tx_ModStart = *start;
- if(POS_GREATER_P(end, &tx->tx_ModEnd))
- tx->tx_ModEnd = *end;
- }
- tx->tx_Changes++;
- }
-
- /*
- * Refeshes everything that should be.
- */
- void
- refreshworld(void)
- {
- VW *vw;
- TX *tx;
- for(vw = ViewChain; vw; vw = vw->vw_Next)
- {
- if(vw->vw_Window)
- refreshwindow(vw);
- }
- tx = BufferChain;
- while(tx)
- {
- tx->tx_LastChanges = tx->tx_Changes;
- tx = tx->tx_Next;
- }
- }
-
- /*
- * Same as the above but assumes that the cursor is currently drawn.
- */
- void
- refreshworldcurs(void)
- {
- VW *vw;
- TX *tx;
- for(vw = ViewChain; vw; vw = vw->vw_Next)
- {
- if(vw->vw_Window
- && ((vw->vw_Tx != vw->vw_LastRefTx)
- || (vw->vw_Tx->tx_Changes != vw->vw_Tx->tx_LastChanges)
- || (vw->vw_Flags & (VWFF_FORCE_REFRESH | VWFF_REFRESH_BLOCK
- | VWFF_REFRESH_STATUS))))
- {
- if(vw == CurrVW)
- cursor(vw, CURS_OFF);
- refreshwindow(vw);
- if(vw == CurrVW)
- cursor(vw, CURS_ON);
- }
- }
- tx = BufferChain;
- while(tx)
- {
- tx->tx_LastChanges = tx->tx_Changes;
- tx = tx->tx_Next;
- }
- }
-