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 >
Wrap
C/C++ Source or Header
|
1994-04-20
|
9KB
|
363 lines
/* 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)
refres