home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d166
/
stevie.lha
/
Stevie
/
source
/
screen.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-11-22
|
10KB
|
408 lines
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
#include "stevie.h"
/*
* The following variable is set (in cursupdate) to the number of physical
* lines taken by the line the cursor is on. We use this to avoid extra calls
* to plines(). The optimized routines updateline() and redrawline()
* make sure that the size of the cursor line hasn't changed. If so, lines below
* the cursor will move up or down and we need to call the routines
* updateNextscreen() and updateRealscreen() to examine the entire screen.
*/
static int Cline_size; /* size (in rows) of the cursor line */
static int Cline_row; /* starting row of the cursor line */
/*
* updateline() - like updateNextscreen() but only for cursor line
*
* This determines whether or not we need to call updateNextscreen() to examine the
* entire screen for changes. This occurs if the size of the cursor line
* (in rows) hasn't changed.
*/
void
updateline()
{
int row, col;
register char *screenp;
LPTR memp;
register char *nextrow;
char extra[16];
int nextra = 0;
char c;
int n;
bool_t eof;
MustRedrawLine = TRUE;
#ifndef AMIGA
if (MustRedrawScreen) {
msg("STEVIE internal error: updateline called");
sleep(5);
}
#endif
screenp = Nextscreen + (Cline_row * Columns);
memp = *Curschar;
memp.index = 0;
eof = FALSE;
col = 0;
row = Cline_row;
while (!eof) {
/* Get the next character to put on the screen. */
/*
* The 'extra' array contains the extra stuff that is inserted to
* represent special characters (tabs, and other non-printable stuff.
* The order in the 'extra' array is reversed.
*/
if (nextra > 0)
c = extra[--nextra];
else {
c = gchar(&memp);
if (inc(&memp) == -1)
eof = TRUE;
/*
* when getting a character from the file, we may have to turn it
* into something else on the way to putting it into
* 'Nextscreen'.
*/
if (c == TAB && !P(P_LS)) {
strcpy(extra, " ");
/* tab amount depends on current column */
nextra = ((P(P_TS) - 1) - col % P(P_TS));
c = ' ';
} else if (c == NUL && P(P_LS)) {
extra[0] = NUL;
nextra = 1;
c = '$';
} else if (c != NUL && (n = chars[c].ch_size) > 1) {
char *p;
nextra = 0;
p = chars[c].ch_str;
/* copy 'ch-str'ing into 'extra' in reverse */
while (n > 1)
extra[nextra++] = p[--n];
c = p[0];
}
}
if (c == NUL) {
row++;
/* get pointer to start of next row */
nextrow = &Nextscreen[row * Columns];
/* blank out the rest of this row */
while (screenp != nextrow)
*screenp++ = ' ';
col = 0;
break;
}
if (col >= Columns) {
row++;
col = 0;
}
/* store the character in Nextscreen */
*screenp++ = c;
col++;
}
if ((row - Cline_row) == Cline_size)
updateNextscreen();
}
/*
* redrawline
*
* Like updateRealscreen() but only for the cursor line.
*/
void
redrawline()
{
register char *np = Nextscreen + (Cline_row * Columns);
register char *rp = Realscreen + (Cline_row * Columns);
register char *endline;
int row, col;
int gorow = -1, gocol = -1;
if (RedrawingDisabled)
return;
if (!MustRedrawLine && !MustRedrawScreen)
return;
if (MustRedrawScreen) {
msg("STEVIE internal error: redrawline called");
sleep(5);
}
endline = np + (Cline_size * Columns);
row = Cline_row;
col = 0;
outstr(T_CI); /* disable cursor */
for (; np < endline; np++, rp++) {
/* If desired screen (contents of Nextscreen) does not */
/* match what's really there, put it there. */
if (*np != *rp) {
/* if we are positioned at the right place, */
/* we don't have to use windgoto(). */
if (gocol != col || gorow != row) {
/*
* If we're just off by one, don't send an entire esc. seq.
* (this happens a lot!)
*/
if (gorow == row && gocol + 1 == col) {
outchar(*(np - 1));
gocol++;
} else
windgoto(gorow = row, gocol = col);
}
outchar(*rp = *np);
gocol++;
}
if (++col >= Columns) {
col = 0;
row++;
}
}
outstr(T_CV); /* enable cursor again */
MustRedrawScreen = FALSE;
}
void
screenclear()
{
char *rp, *np;
char *end;
outstr(T_ED); /* clear the display */
rp = Realscreen;
end = Realscreen + Rows * Columns;
np = Nextscreen;
/* blank out the stored screens */
while (rp != end)
*rp++ = *np++ = ' ';
}
void
cursupdate()
{
LPTR *p;
char c;
int incr, nlines;
int i;
int didincr;
if (bufempty()) { /* special case - file is empty */
*Topchar = *Filemem;
*Curschar = *Filemem;
} else if (LINEOF(Curschar) < LINEOF(Topchar)) {
nlines = cntllines(Curschar, Topchar);
/*
* if the cursor is above the top of the screen, put it at the top of
* the screen..
*/
*Topchar = *Curschar;
Topchar->index = 0;
/*
* ... and, if we weren't very close to begin with, we scroll so that
* the line is close to the middle.
*/
if (nlines > Rows / 3) {
for (i = 0, p = Topchar; i < Rows / 3; i++, *Topchar = *p)
if ((p = prevline(p)) == NULL)
break;
} else
s_ins(0, nlines - 1);
updateNextscreen();
} else if (LINEOF(Curschar) >= LINEOF(Botchar)) {
nlines = cntllines(Botchar, Curschar);
/*
* If the cursor is off the bottom of the screen, put it at the top
* of the screen.. ... and back up
*/
if (nlines > Rows / 3) {
p = Curschar;
for (i = 0; i < (2 * Rows) / 3; i++)
if ((p = prevline(p)) == NULL)
break;
*Topchar = *p;
} else {
scrollup(nlines);
}
updateNextscreen();
}
Cursrow = Curscol = Cursvcol = 0;
for (p = Topchar; p->linep != Curschar->linep; p = nextline(p))
Cursrow += plines(p);
Cline_row = Cursrow;
Cline_size = plines(p);
for (i = 0; i <= Curschar->index; i++) {
c = Curschar->linep->s[i];
/* A tab gets expanded, depending on the current column */
if (c == TAB && !P(P_LS))
incr = P(P_TS) - (Curscol % P(P_TS));
else
incr = chars[c].ch_size;
Curscol += incr;
Cursvcol += incr;
if (Curscol >= Columns) {
Curscol -= Columns;
Cursrow++;
didincr = TRUE;
} else
didincr = FALSE;
}
if (didincr)
Cursrow--;
if (c == TAB && State == NORMAL && !P(P_LS)) {
Curscol--;
Cursvcol--;
} else {
Curscol -= incr;
Cursvcol -= incr;
}
if (Curscol < 0)
Curscol += Columns;
if (set_want_col) {
Curswant = Cursvcol;
set_want_col = FALSE;
}
}
/*
* The rest of the routines in this file perform screen manipulations. The
* given operation is performed physically on the screen. The corresponding
* change is also made to the internal screen image. In this way, the editor
* anticipates the effect of editing changes on the appearance of the screen.
* That way, when we call screenupdate a complete redraw isn't usually
* necessary. Another advantage is that we can keep adding code to anticipate
* screen changes, and in the meantime, everything still works.
*/
/*
* s_ins(row, nlines) - insert 'nlines' lines at 'row'
*/
void
s_ins(row, nlines)
int row;
int nlines;
{
char *s, *d; /* src & dest for block copy */
char *e; /* end point for copy */
int i;
if ((T_IL[0] == NUL) || RedrawingDisabled || nlines <= 0)
return;
/*
* It "looks" better if we do all the inserts at once
*/
outstr(T_SC); /* save position */
if (T_IL_B[0] == NUL) {
for (i = 0; i < nlines; i++) {
windgoto(row, 0);
outstr(T_IL);
}
} else {
windgoto(row, 0);
outstr(T_IL);
if (nlines >= 10)
outchar((char) (nlines / 10 + '0'));
outchar((char) (nlines % 10 + '0'));
outstr(T_IL_B);
}
windgoto(Rows - 1, 0); /* delete any garbage that may have */
outstr(T_EL); /* been shifted to the bottom line */
outstr(T_RC); /* restore the cursor position */
/*
* Now do a block move to update the internal screen image
*/
d = Realscreen + (Columns * (Rows - 1)) - 1;
s = d - (Columns * nlines);
e = Realscreen + (Columns * row);
while (s >= e)
*d-- = *s--;
/*
* Clear the inserted lines
*/
s = Realscreen + (row * Columns);
e = s + (nlines * Columns);
while (s < e)
*s++ = ' ';
}
/*
* s_del(row, nlines) - delete 'nlines' lines at 'row'
*/
void
s_del(row, nlines)
int row;
int nlines;
{
char *s, *d, *e;
int i;
if ((T_DL[0] == NUL) || RedrawingDisabled || nlines <= 0)
return;
outstr(T_SC); /* save position */
windgoto(Rows - 1, 0); /* delete any garbage that */
outstr(T_EL); /* was on the status line */
/* delete the lines */
if (T_DL_B[0] == NUL) {
for (i = 0; i < nlines; i++) {
windgoto(row, 0);
outstr(T_DL); /* delete a line */
}
} else {
windgoto(row, 0);
outstr(T_DL);
if (nlines >= 10)
outchar((char) (nlines / 10 + '0'));
outchar((char) (nlines % 10 + '0'));
outstr(T_DL_B);
}
outstr(T_RC); /* restore position */
/*
* do a block move to update the internal image
*/
d = Realscreen + (row * Columns);
s = d + (nlines * Columns);
e = Realscreen + ((Rows - 1) * Columns);
while (s < e)
*d++ = *s++;
while (d < e) /* clear the lines at the bottom */
*d++ = ' ';
}