#include "ex.h"
#include "ex_tty.h"
#include "ex_vis.h"
void
vmoveto(addr, curs, context)
line *addr;
unsigned char *curs;
unsigned char context;
{
markit(addr);
vsave();
vjumpto(addr, curs, context);
}
void
vjumpto(line *addr, unsigned char *curs, unsigned char context)
{
noteit(0);
if (context != 0)
vcontext(addr, context);
else
vshow(addr, NOLINE);
noteit(1);
vnline(curs);
}
void
vupdown(int cnt, unsigned char *curs)
{
if (cnt > 0)
vdown(cnt, 0, 0);
else if (cnt < 0)
vup(-cnt, 0, 0);
if (vcnt == 0)
vrepaint(curs);
else
vnline(curs);
}
void
vup(int cnt, int ind, bool scroll)
{
int i, tot;
if (dot == one) {
(void) beep();
return;
}
vsave();
i = lineDOT() - 1;
if (cnt > i) {
ind -= cnt - i;
if (ind < 0)
ind = 0;
cnt = i;
}
if (!scroll && cnt <= vcline) {
vshow(dot - cnt, NOLINE);
return;
}
cnt -= vcline, dot -= vcline, vcline = 0;
if (hold & HOLDWIG)
goto contxt;
if (state == VISUAL && !insert_line && !scroll_reverse &&
cnt <= WTOP - ZERO && vfit(dot - cnt, cnt) <= WTOP - ZERO)
goto okr;
tot = WECHO - WTOP;
if (state != VISUAL || (!insert_line && !scroll_reverse) || (!scroll && (cnt > tot || vfit(dot - cnt, cnt) > tot / 3 + 1))) {
if (ind > basWLINES / 2)
ind = basWLINES / 3;
contxt:
vcontext(dot + ind - cnt, '.');
return;
}
okr:
vrollR(cnt);
if (scroll) {
vcline += ind, dot += ind;
if (vcline >= vcnt)
dot -= vcline - vcnt + 1, vcline = vcnt - 1;
getDOT();
}
}
void
vdown(int cnt, int ind, bool scroll)
{
int i, tot;
if (dot == dol) {
(void) beep();
return;
}
vsave();
i = dol - dot;
if (cnt > i) {
ind -= cnt - i;
if (ind < 0)
ind = 0;
cnt = i;
}
i = vcnt - vcline - 1;
if (!scroll && cnt <= i) {
vshow(dot + cnt, NOLINE);
return;
}
cnt -= i, dot += i, vcline += i;
if (hold & HOLDWIG)
goto dcontxt;
if (!scroll) {
tot = WECHO - WTOP;
if (state != VISUAL || cnt - tot > 0 || vfit(dot, cnt) > tot / 3 + 1) {
dcontxt:
vcontext(dot + cnt, '.');
return;
}
}
if (cnt > 0)
vroll(cnt);
if (state == VISUAL && scroll) {
vcline -= ind, dot -= ind;
if (vcline < 0)
dot -= vcline, vcline = 0;
getDOT();
}
}
void
vcontext(line *addr, unsigned char where)
{
line *top;
getaline(*addr);
if (state != VISUAL)
top = addr;
else switch (where) {
case '^':
addr = vback(addr, basWLINES - vdepth());
getaline(*addr);
case '-':
top = vback(addr, basWLINES - vdepth());
getaline(*addr);
break;
case '.':
top = vback(addr, basWLINES / 2 - vdepth());
getaline(*addr);
break;
default:
top = addr;
break;
}
if (state == ONEOPEN && LINE(0) == WBOT)
vup1();
vcnt = vcline = 0;
vclean();
if (state == CRTOPEN)
vup1();
vshow(addr, top);
}
void
vclean(void)
{
if (state != VISUAL && state != CRTOPEN) {
destcol = 0;
if (!ateopr())
vup1();
vcnt = 0;
}
}
void
vshow(line *addr, line *top)
{
#ifndef CBREAK
bool fried = 0;
#endif
int cnt = addr - dot;
int i = vcline + cnt;
short oldhold = hold;
if (state != HARDOPEN && state != ONEOPEN && i >= 0 && i < vcnt) {
dot = addr;
getDOT();
vcline = i;
return;
}
if (state != VISUAL) {
dot = addr;
vopen(dot, WBOT);
return;
}
if (top == 0) {
vcontext(addr, '.');
return;
}
dot = top;
#ifndef CBREAK
if (vcookit(2))
fried++, vcook();
#endif
oldhold = hold;
hold |= HOLDAT;
vclear();
vreset(0);
vredraw(WTOP);
vcline = addr - top;
dot = addr;
getDOT();
hold = oldhold;
vsync(LASTLINE);
#ifndef CBREAK
if (fried)
flusho(), vraw();
#endif
}
void
vreset(bool inecho)
{
vcnt = vcline = 0;
WTOP = basWTOP;
WLINES = basWLINES;
if (inecho)
splitw = 1, vgoto(WECHO, 0);
}
line *
vback(tp, cnt)
int cnt;
line *tp;
{
int d;
if (cnt > 0)
for (; tp > one; tp--) {
getaline(tp[-1]);
d = vdepth();
if (d > cnt)
break;
cnt -= d;
}
return (tp);
}
int
vfit(line *tp, int cnt)
{
int j;
j = 0;
while (cnt > 0) {
cnt--;
getaline(tp[cnt]);
j += vdepth();
}
if (tp > dot)
j -= WBOT - LASTLINE;
return (j);
}
void
vroll(int cnt)
{
#ifndef CBREAK
bool fried = 0;
#endif
short oldhold = hold;
#ifdef ADEBUG
if (trace)
tfixnl(), fprintf(trace, "vroll(%d)\n", cnt);
#endif
if (state != VISUAL)
hold |= HOLDAT|HOLDROL;
if (WBOT == WECHO) {
vcnt = 0;
if (state == ONEOPEN)
vup1();
}
#ifndef CBREAK
if (vcookit(cnt))
fried++, vcook();
#endif
for (; cnt > 0 && Peekkey != ATTN; cnt--) {
dot++, vcline++;
vopen(dot, LASTLINE);
vscrap();
}
hold = oldhold;
if (state == HARDOPEN)
sethard();
vsyncCL();
#ifndef CBREAK
if (fried)
flusho(), vraw();
#endif
}
void
vrollR(int cnt)
{
bool fried = 0;
short oldhold = hold;
#ifdef ADEBUG
if (trace)
tfixnl(), fprintf(trace, "vrollR(%d), dot=%d\n", cnt, lineDOT());
#endif
#ifndef CBREAK
if (vcookit(cnt))
fried++, vcook();
#endif
if (WBOT == WECHO)
vcnt = 0;
heldech = 0;
hold |= HOLDAT|HOLDECH;
for (; cnt > 0 && Peekkey != ATTN; cnt--) {
dot--;
vopen(dot, WTOP);
vscrap();
}
hold = oldhold;
if (heldech)
vclrech(0);
vsync(LINE(vcnt-1));
#ifndef CBREAK
if (fried)
flusho(), vraw();
#endif
}
int
vcookit(int cnt)
{
return (cnt > 1 && (ospeed < B1200 && !initev || cnt > lines * 2));
}
int
vdepth(void)
{
int d;
d = (column(NOSTR) + WCOLS - 1 + (Putchar == listchar) + insert_null_glitch) / WCOLS;
#ifdef ADEBUG
if (trace)
tfixnl(), fprintf(trace, "vdepth returns %d\n", d == 0 ? 1 : d);
#endif
return (d == 0 ? 1 : d);
}
void
vnline(unsigned char *curs)
{
unsigned char *owcursor;
int j;
if (curs) {
if(curs >= strend(linebuf)) {
if(!*linebuf)
wcursor = linebuf;
else {
wcursor = strend(linebuf);
wcursor = lastchr(linebuf, wcursor);
}
} else {
owcursor = wcursor = curs;
j = wcursor - linebuf;
for(wcursor = linebuf; wcursor - linebuf < j; ) {
owcursor = wcursor;
wcursor = nextchr(wcursor);
}
if(wcursor - linebuf > j)
wcursor = owcursor;
}
} else if (vmoving)
wcursor = vfindcol(vmovcol);
else
wcursor = vskipwh(linebuf);
cursor = linebuf;
(void) vmove();
}