2.9BSD/usr/contrib/jove/jove_screen.c
/*
Jonathan Payne at Lincoln-Sudbury Regional High School 5-25-83
jove_screen.c
Deals with writing output to the screen optimally i.e. it doesn't
write what is already there. It keeps an exact image of the screen
in the Screen array. */
#include "jove.h"
#include "jove_temp.h"
#include "termcap.h"
extern int BufSize;
int CheckTime,
tabstop = 8;
struct scrimage
*nimage, /* What lines should be where after redisplay */
*oimage; /* What line are after redisplay */
struct screenline *Screen, /* The screen */
*Curline; /* Current line */
char *cursor, /* Offset into current line */
*cursend;
int CapCol,
CapLine,
i_line,
i_col;
make_scr()
{
register int i;
register struct screenline *ns;
register char *nsp;
nimage = (struct scrimage *) emalloc(LI * sizeof (struct scrimage));
oimage = (struct scrimage *) emalloc(LI * sizeof (struct scrimage));
ns = Screen = (struct screenline *)
emalloc(LI * sizeof(struct screenline));
nsp = (char *) emalloc(CO * LI);
for (i = 0; i < LI; i++) {
ns->s_line = nsp;
nsp += CO;
ns->s_length = nsp - 1; /* End of line */
ns++;
}
cl_scr();
}
clrline(cp1, cp2)
register char *cp1,
*cp2;
{
while (cp1 <= cp2)
*cp1++ = ' ';
}
cl_eol()
{
if (InputPending || cursor > cursend)
return;
if (cursor < Curline->s_length) {
clrline(cursor, Curline->s_length);
Curline->s_length = cursor;
Placur(i_line, i_col);
putpad(CE, 1);
}
}
cl_scr()
{
register int i;
register struct screenline *sp = Screen;
for (i = 0; i < LI; i++, sp++) {
clrline(sp->s_line, sp->s_length);
sp->s_length = sp->s_line;
oimage[i].Line = 0;
}
putpad(CL, LI);
Placur(0, 0);
UpdMesg++;
}
#define soutputc(c) if (--n > 0) sputc(c); else { sputc('!'); goto outahere;}
/* Output one character (if necessary) at the current position */
#define sputc(c) ((*cursor != c) ? dosputc(c) : (cursor++, i_col++))
dosputc(c)
register char c;
{
if (*cursor != c) {
Placur(i_line, i_col);
outchar(c);
CapCol++;
*cursor++ = c;
i_col++;
} else {
cursor++;
i_col++;
}
}
/* Write `line' at the current position of `cursor'. Stop when we
reach the end of the screen. Aborts if there is a character
waiting. */
swrite(line)
register char *line;
{
register char c;
int col = 0,
aborted = 0;
register int n = cursend - cursor;
while (c = *line++) {
if (CheckTime) {
flusho();
CheckTime = 0;
if (InputPending = charp()) {
aborted = 1;
break;
}
}
if (c == '\t') {
int nchars;
nchars = (tabstop - (col % tabstop));
col += nchars;
while (nchars--)
soutputc(' ')
} else if (c < 040 || c == '\177') {
soutputc('^')
soutputc(c == '\177' ? '?' : c + '@')
col += 2;
} else {
soutputc(c)
col++;
}
}
outahere:
if (cursor > Curline->s_length)
Curline->s_length = cursor;
return !aborted;
}
/* This is for writing a buffer line to the screen. This is to
* minimize the amount of copying from one buffer to another buffer.
* This gets the info directly from ibuff[12].
*/
BufSwrite(linenum)
{
register char c,
*bp;
LINE *lp = nimage[linenum].Line;
register int n = cursend - cursor;
int tl = lp->l_dline,
nl,
col = 0,
StartCol = nimage[linenum].StartCol,
aborted = 0;
#define OkayOut(c) if (col++ >= StartCol) soutputc(c) else
if (lp == curline) {
bp = linebuf;
nl = BUFSIZ;
} else {
bp = getblock(tl, READ);
nl = nleft;
tl &= ~OFFMSK;
}
while (c = *bp++) {
if (CheckTime) {
flusho();
CheckTime = 0;
if (InputPending = charp()) {
aborted = 1;
break;
}
}
if (c == '\t') {
int nchars;
nchars = (tabstop - (col % tabstop));
while (nchars--)
OkayOut(' ');
} else if (c < 040 || c == '\177') {
OkayOut('^');
OkayOut(c == '\177' ? '?' : c + '@');
} else
OkayOut(c);
if (--nl == 0) {
bp = getblock(tl += INCRMT, READ);
nl = nleft;
}
}
outahere:
if (cursor > Curline->s_length)
Curline->s_length = cursor;
return !aborted; /* Didn't abort */
}
putstr(str)
register char *str;
{
register char c;
while (c = *str++)
outchar(c);
}
i_set(nline, ncol)
register int nline,
ncol;
{
Curline = &Screen[nline];
cursor = Curline->s_line + ncol;
cursend = &Curline->s_line[CO - 1];
i_line = nline;
i_col = ncol;
}
extern int diffnum;
/* Insert `num' lines a top, but leave all the lines BELOW `bottom'
* alone (at least they won't look any different when we are done).
* This changes the screen array AND does the physical changes.
*/
v_ins_line(num, top, bottom)
{
register int i;
struct screenline savelines[MAXNLINES];
/* Save the screen pointers. */
for(i = 0; i < num && top + i <= bottom; i++)
savelines[i] = Screen[bottom - i];
/* Num number of bottom lines will be lost.
* Copy everything down num number of times.
*/
for (i = bottom; i > top && i-num >= 0; i--) {
Screen[i] = Screen[i - num];
Screen[i] = Screen[i - num];
}
/* Restore the saved ones, making them blank. */
for (i = 0; i < num; i++) {
Screen[top + i] = savelines[i];
clrline(Screen[top + i].s_line, Screen[top + i].s_length);
}
/* VT100/bitgraph are special cases ... uhg! */
if (BG) { /* But it makes such a big difference built in */
putstr(sprint("\033[%d;%dr\033[%dL\033[r",
top + 1, bottom + 1, num));
CapCol = CapLine = 0;
} else if (VT) {
Placur(top, 0);
putstr(sprint("\0337\033[%d;%dr\0338", top + 1, bottom + 1));
for (i = 0; i < num; i++)
putstr(SR);
putstr("\0337\033[r\0338");
} else {
Placur(bottom - num + 1, 0);
for (i = 0; i < num; i++)
putpad(DL, LI - CapLine);
Placur(top, 0);
for (i = 0; i < num; i++)
putpad(AL, LI - CapLine);
}
}
/* Delete `num' lines starting at `top' leaving the lines below `bottom'
alone. This updates the internal image as well as the physical image. */
v_del_line(num, top, bottom)
{
register int i,
bot;
struct screenline savelines[MAXNLINES];
bot = bottom;
/* Save the lost lines. */
for (i = 0; i < num && top + i <= bottom; i++)
savelines[i] = Screen[top + i];
/* Copy everything up num number of lines. */
for (i = top; num + i <= bottom; i++) {
Screen[i] = Screen[i + num];
Screen[i] = Screen[i + num];
}
/* Restore the lost ones, clearing them. */
for (i = 0; i < num; i++) {
Screen[bottom - i] = savelines[i];
clrline(Screen[bot].s_line, Screen[bot].s_length);
bot--;
}
if (BG) { /* It makes such a big difference when built in!!! */
putstr(sprint("\033[%d;%dr\033[%dM\033[r",
top + 1, bottom + 1, num));
CapCol = CapLine = 0;
} else if (VT) {
Placur(bottom, 0);
putstr(sprint("\0337\033[%d;%dr\0338", top + 1, bottom + 1));
for (i = 0; i < num; i++)
outchar('\n');
putstr("\0337\033[r\0338");
} else {
Placur(top, 0);
for (i = 0; i < num; i++)
putpad(DL, LI - CapLine);
Placur(bottom + 1 - num, 0);
for (i = 0; i < num; i++)
putpad(AL, LI - CapLine);
}
}