#include "ex.h"
#include "ex_re.h"
#include "ex_tty.h"
#include "ex_vis.h"
void setsize();
void winch();
void vintr();
void ovend(ttymode);
wchar_t atube[TUBESIZE];
jmp_buf venv;
int windowchg;
int sigok;
void windowinit()
{
windowchg = 0;
setsize();
if(value(vi_WINDOW) >= lines || options[vi_WINDOW].odefault == value(vi_WINDOW))
value(vi_WINDOW) = lines -1;
options[vi_WINDOW].odefault = lines - 1;
if(options[vi_SCROLL].odefault == value(vi_SCROLL))
value(vi_SCROLL) = value(vi_WINDOW)/2;
options[vi_SCROLL].odefault = (lines - 1)/2;
vsetsiz(value(vi_WINDOW));
setwind();
vok(atube, 1);
}
void redraw()
{
vsave();
windowinit();
vclear();
vdirty(0, lines);
if(state != VISUAL) {
vclean();
vmoveto(dot, cursor, 0);
} else {
vredraw(WTOP);
vrepaint(cursor);
vfixcurs();
}
}
void
#ifdef __STDC__
winch(int sig)
#else
winch(sig)
int sig;
#endif
{
struct winsize jwin;
int l;
if(ioctl(0, TIOCGWINSZ, &jwin) != -1) {
#ifdef XPG4
oldlines = jwin.ws_row;
oldcolumns = jwin.ws_col;
#endif
if (sigok) {
if (columns != jwin.ws_col || lines != jwin.ws_row)
redraw();
}
}
else
windowchg++;
(void)signal(SIGWINCH, winch);
}
void
setsize()
{
struct winsize jwin;
int l;
if(ioctl(0, TIOCGWINSZ, &jwin) != -1) {
if (jwin.ws_col > 0)
columns = jwin.ws_col;
if (jwin.ws_row > 0)
lines = jwin.ws_row;
}
#ifdef XPG4
if (envlines != -1) {
lines = envlines;
}
if (envcolumns != -1) {
columns = envcolumns;
}
if (envlines != -1 || envcolumns != -1) {
jwin.ws_row = lines;
jwin.ws_col = columns;
if (ioctl(0, TIOCSWINSZ, &jwin) == -1) {
jwin.ws_row = oldlines;
jwin.ws_col = oldcolumns;
ioctl(0, TIOCSWINSZ, &jwin);
}
}
#endif
if (lines <= 1)
lines = 24;
l = lines;
if (columns <= 4)
columns = 1000;
value(vi_WINDOW) = options[vi_WINDOW].odefault = l - 1;
}
void
oop(void)
{
unsigned char *ic;
ttymode f;
int resize;
windowchg = 0;
(void)signal(SIGWINCH, winch);
ovbeg();
if (peekchar() == '/') {
(void)vi_compile(getchar(), 1);
savere(&scanre);
if (execute(0, dot) == 0)
error(value(vi_TERSE) ? gettext("Fail") :
gettext("Pattern not found on addressed line"));
ic = (unsigned char *)loc1;
if (ic > linebuf && *ic == 0)
ic--;
} else {
getDOT();
ic = vskipwh(linebuf);
}
donewline();
if (over_strike && !erase_overstrike)
bastate = HARDOPEN;
else if (cursor_address || cursor_up)
bastate = CRTOPEN;
else
bastate = ONEOPEN;
setwind();
if (state != CRTOPEN)
WCOLS = TUBECOLS;
if (!inglobal)
savevis();
vok(atube, 0);
if (state != CRTOPEN)
columns = WCOLS;
Outchar = vputchar;
f = ostart();
if (state == CRTOPEN) {
if (outcol == UKCOL)
outcol = 0;
vmoveitup(1, 1);
} else
outline = destline = WBOT;
vshow(dot, NOLINE);
vnline(ic);
vmain();
if (state != CRTOPEN)
vclean();
Command = (unsigned char *)"open";
ovend(f);
(void)signal(SIGWINCH, SIG_DFL);
}
void
ovbeg(void)
{
if (inopen)
error(gettext("Recursive open/visual not allowed"));
Vlines = lineDOL();
fixzero();
setdot();
pastwh();
dot = addr2;
}
void
ovend(ttymode f)
{
splitw++;
vgoto(WECHO, 0);
vclreol();
vgoto(WECHO, 0);
holdcm = 0;
splitw = 0;
ostop(f);
setoutt();
undvis();
columns = OCOLUMNS;
inopen = 0;
flusho();
netchHAD(Vlines);
}
void
vop(void)
{
int c;
ttymode f;
extern unsigned char termtype[];
if (!cursor_address && !cursor_up) {
if (initev) {
toopen:
if (generic_type)
merror(gettext("I don't know what kind of terminal you are on - all I have is '%s'."), termtype);
putNFL();
merror(gettext("[Using open mode]"));
putNFL();
oop();
return;
}
error(gettext("Visual needs addressable cursor or upline capability"));
}
if (over_strike && !erase_overstrike) {
if (initev)
goto toopen;
error(gettext("Can't use visual on a terminal which overstrikes"));
}
if (!clear_screen) {
if (initev)
goto toopen;
error(gettext("Visual requires clear screen capability"));
}
if (!scroll_forward) {
if (initev)
goto toopen;
error(gettext("Visual requires scrolling"));
}
windowchg = 0;
(void)signal(SIGWINCH, winch);
ovbeg();
bastate = VISUAL;
c = 0;
if (any(peekchar(), "+-^."))
c = getchar();
pastwh();
vsetsiz(isdigit(peekchar()) ? getnum() : value(vi_WINDOW));
setwind();
donewline();
vok(atube, 0);
if (!inglobal)
savevis();
Outchar = vputchar;
vmoving = 0;
f = ostart();
if (initev == 0) {
vcontext(dot, c);
vnline((unsigned char *)NOSTR);
}
vmain();
Command = (unsigned char *)"visual";
ovend(f);
(void)signal(SIGWINCH, SIG_DFL);
}
void
fixzero(void)
{
if (dol == zero) {
bool ochng = chng;
vdoappend((unsigned char *)"");
if (!ochng)
sync();
addr1 = addr2 = one;
} else if (addr2 == zero)
addr2 = one;
}
void
savevis(void)
{
if (inglobal)
return;
truedol = unddol;
saveall();
unddol = dol;
undkind = UNDNONE;
}
void
undvis(void)
{
if (ruptible)
signal(SIGINT, onintr);
squish();
pkill[0] = pkill[1] = 0;
unddol = truedol;
unddel = zero;
undap1 = one;
undap2 = dol + 1;
undkind = UNDALL;
if (undadot <= zero || undadot > dol)
undadot = zero+1;
}
void
setwind(void)
{
WCOLS = columns;
switch (bastate) {
case ONEOPEN:
if (auto_right_margin)
WCOLS--;
case HARDOPEN:
basWTOP = WTOP = WBOT = WECHO = 0;
ZERO = 0;
holdcm++;
break;
case CRTOPEN:
basWTOP = lines - 2;
case VISUAL:
ZERO = lines - TUBESIZE / WCOLS;
if (ZERO < 0)
ZERO = 0;
if (ZERO > basWTOP)
error(gettext("Screen too large for internal buffer"));
WTOP = basWTOP; WBOT = lines - 2; WECHO = lines - 1;
break;
}
state = bastate;
basWLINES = WLINES = WBOT - WTOP + 1;
}
static unsigned char vlinebuf[LBSIZE];
void
vok(wchar_t *atube, int undo)
{
int i;
static int beenhere;
if (WCOLS == 1000)
serror((unsigned char *)
gettext("Don't know enough about your terminal to use %s"),
Command);
if (WCOLS > TUBECOLS)
error(gettext("Terminal too wide"));
if (WLINES >= TUBELINES || WCOLS * (WECHO - ZERO + 1) > TUBESIZE)
error(gettext("Screen too large"));
vtube0 = atube;
if(beenhere)
vclrbyte(atube, WCOLS * (WECHO - ZERO + 1));
for (i = 0; i < ZERO; i++)
vtube[i] = (wchar_t *) 0;
for (; i <= WECHO; i++)
vtube[i] = atube, atube += WCOLS;
if(beenhere++) {
for (; i < TUBELINES; i++)
vtube[i] = (wchar_t *) 0;
}
vutmp = vlinebuf;
if(!undo) {
vundkind = VNONE;
vUNDdot = 0;
}
OCOLUMNS = columns;
inopen = 1;
#ifdef CBREAK
signal(SIGINT, vintr);
#endif
vmoving = 0;
splitw = 0;
doomed = 0;
holdupd = 0;
if(!undo)
Peekkey = 0;
vcnt = vcline = 0;
if (vSCROLL == 0)
vSCROLL = value(vi_SCROLL);
}
#ifdef CBREAK
void
#ifdef __STDC__
vintr(int sig)
#else
vintr(sig)
int sig;
#endif
{
signal(SIGINT, vintr);
if (vcatch)
onintr(0);
ungetkey(ATTN);
draino();
}
#endif
void
vsetsiz(int size)
{
int b;
if (bastate != VISUAL)
return;
b = lines - 1 - size;
if (b >= lines - 1)
b = lines - 2;
if (b < 0)
b = 0;
basWTOP = b;
basWLINES = WBOT - b + 1;
}