#include "ex.h"
#include "ex_tty.h"
#include "ex_vis.h"
void fixundo(void);
unsigned char *vUA1, *vUA2;
unsigned char *vUD1, *vUD2;
void
vUndo(void)
{
if (vundkind == VNONE || vundkind == VCAPU || vUNDdot != dot) {
(void) beep();
return;
}
CP(vutmp, linebuf);
vUD1 = linebuf; vUD2 = strend(linebuf);
putmk1(dot, vUNDsav);
getDOT();
vUA1 = linebuf; vUA2 = strend(linebuf);
vundkind = VCAPU;
if (state == ONEOPEN || state == HARDOPEN) {
vjumpto(dot, vUNDcurs, 0);
return;
}
vdirty(vcline, 1);
if(MB_CUR_MAX > 1)
rewrite = _ON;
vsyncCL();
if(MB_CUR_MAX > 1)
rewrite = _OFF;
cursor = linebuf;
vfixcurs();
}
void
vundo(show)
bool show;
{
int cnt;
line *addr;
unsigned char *cp;
unsigned char temp[LBSIZE];
bool savenote;
int (*OO)();
short oldhold = hold;
unsigned multic[MULTI_BYTE_MAX];
int length;
wchar_t wchar;
switch (vundkind) {
case VMANYINS:
wcursor = 0;
addr1 = undap1;
addr2 = undap2 - 1;
vsave();
(void) YANKreg('1');
notecnt = 0;
case VMANY:
case VMCHNG:
vsave();
addr = dot - vcline;
notecnt = 1;
if (undkind == UNDPUT && undap1 == undap2) {
(void) beep();
break;
}
if (show)
if (undkind == UNDMOVE)
vdirty(0, lines);
else
vreplace(undap1 - addr, undap2 - undap1,
undkind == UNDPUT ? 0 : unddol - dol);
savenote = notecnt;
undo(1);
if (show && (vundkind != VMCHNG || addr != dot))
killU();
vundkind = VMANY;
cnt = dot - addr;
if (cnt < 0 || cnt > vcnt || state != VISUAL) {
if (show)
vjumpto(dot, (unsigned char *)NOSTR, '.');
break;
}
if (!savenote)
notecnt = 0;
if (show) {
vcline = cnt;
if(MB_CUR_MAX > 1)
rewrite = _ON;
vrepaint(vmcurs);
if(MB_CUR_MAX > 1)
rewrite = _OFF;
}
vmcurs = 0;
break;
case VCHNG:
case VCAPU:
vundkind = VCHNG;
strcpy(temp, vutmp);
strcpy(vutmp, linebuf);
doomed = lcolumn(vUA2) - lcolumn(vUA1);
strcLIN(temp);
cp = vUA1; vUA1 = vUD1; vUD1 = cp;
cp = vUA2; vUA2 = vUD2; vUD2 = cp;
if (!show)
break;
cursor = vUD1;
if (state == HARDOPEN) {
doomed = 0;
vsave();
vopen(dot, WBOT);
vnline(cursor);
break;
}
vcursat(cursor);
OO = Outchar; Outchar = vinschar; hold |= HOLDQIK;
vprepins();
temp[vUA2 - linebuf] = 0;
for (cp = &temp[vUA1 - linebuf]; *cp;) {
length = mbtowc(&wchar, (char *)cp, MULTI_BYTE_MAX);
if(length < 0) {
putoctal = 1;
putchar(*cp++);
putoctal = 0;
} else {
putchar(wchar);
cp += length;
}
}
Outchar = OO; hold = oldhold;
endim();
physdc(cindent(), cindent() + doomed);
doomed = 0;
vdirty(vcline, 1);
if(MB_CUR_MAX > 1)
rewrite = _ON;
vsyncCL();
if(MB_CUR_MAX > 1)
rewrite = _OFF;
if (cursor > linebuf && cursor >= strend(linebuf))
cursor = lastchr(linebuf, cursor);
vfixcurs();
break;
case VNONE:
(void) beep();
break;
}
}
void
vmacchng(fromvis)
bool fromvis;
{
line *savedot, *savedol;
unsigned char *savecursor;
unsigned char savelb[LBSIZE];
int nlines, more;
line *a1, *a2;
unsigned char ch;
int copyw(), copywR();
if (!inopen)
return;
if (!vmacp)
vch_mac = VC_NOTINMAC;
#ifdef UNDOTRACE
if (trace)
fprintf(trace, "vmacchng, vch_mac=%d, linebuf='%s', *dot=%o\n", vch_mac, linebuf, *dot);
#endif
if (vmacp && fromvis)
vsave();
#ifdef UNDOTRACE
if (trace)
fprintf(trace, "after vsave, linebuf='%s', *dot=%o\n", linebuf, *dot);
#endif
switch(vch_mac) {
case VC_NOCHANGE:
vch_mac = VC_ONECHANGE;
break;
case VC_ONECHANGE:
#ifdef UNDOTRACE
vudump("before vmacchng hairy case");
#endif
savedot = dot; savedol = dol; savecursor = cursor;
CP(savelb, linebuf);
nlines = dol - zero;
while ((line *) endcore - truedol < nlines)
if (morelines() < 0)
return;
copyw(truedol+1, zero+1, nlines);
truedol += nlines;
#ifdef UNDOTRACE
visdump("before vundo");
#endif
vundo(0);
#ifdef UNDOTRACE
visdump("after vundo");
vudump("after vundo");
#endif
saveall();
#ifdef UNDOTRACE
vudump("after saveall");
#endif
more = savedol - dol;
if (more)
(*(more>0 ? copywR : copyw))(savedol+1, dol+1, truedol-dol);
unddol += more; truedol += more; undap2 += more;
truedol -= nlines;
copyw(zero+1, truedol+1, nlines);
dot = savedot; dol = savedol ; cursor = savecursor;
CP(linebuf, savelb);
vch_mac = VC_MANYCHANGE;
otchng = tchng;
inopen = -1;
vundkind = VMANY;
#ifdef UNDOTRACE
vudump("after vmacchng");
#endif
break;
case VC_NOTINMAC:
case VC_MANYCHANGE:
break;
}
}
void
vnoapp(void)
{
vUD1 = vUD2 = cursor;
if (lastcmd[0] == 'A' || lastcmd[0] == 'a' || lastcmd[0] == 'i' ||
lastcmd[0] == 'R') {
vmcurs = cursor;
}
}
int
vmove(void)
{
int cnt;
if (wdot) {
if (wdot < one || wdot > dol) {
(void) beep();
return (0);
}
cnt = wdot - dot;
wdot = NOLINE;
if (cnt)
killU();
vupdown(cnt, wcursor);
return (0);
}
if (vUNDdot != dot) {
vUNDsav = *dot;
vUNDcurs = wcursor;
vUNDdot = dot;
}
if (state == HARDOPEN) {
unsigned char *cp;
if (rubble) {
int c;
int oldhold = hold;
sethard();
cp = wcursor;
c = *cp;
*cp = 0;
hold |= HOLDDOL;
(void) vreopen(WTOP, lineDOT(), vcline);
hold = oldhold;
*cp = c;
} else if (wcursor > cursor) {
int length;
char multic[MULTI_BYTE_MAX];
wchar_t wchar;
vfixcurs();
for (cp = cursor; *cp && cp < wcursor;) {
length = mbtowc(&wchar, (char *)cp, MULTI_BYTE_MAX);
if(length == 0)
putchar(' ');
else if(length < 0) {
putoctal = 1;
putchar(*cp++);
putoctal = 0;
} else {
cp += length;
putchar(wchar);
}
}
}
}
vsetcurs(wcursor);
return (0);
}
int
vdelete(unsigned char c)
{
unsigned char *cp;
int i;
if (wdot) {
if (wcursor) {
(void) vchange('d');
return (0);
}
if ((i = xdw()) < 0)
return (0);
if (state != VISUAL) {
vgoto(LINE(0), 0);
(void) vputchar('@');
}
wdot = dot;
vremote(i, delete, 0);
notenam = (unsigned char *)"delete";
DEL[0] = 0;
killU();
vreplace(vcline, i, 0);
if (wdot > dol)
vcline--;
vrepaint(NOSTR);
return (0);
}
if (wcursor < linebuf)
wcursor = linebuf;
if (cursor == wcursor) {
(void) beep();
return (0);
}
i = vdcMID();
cp = cursor;
setDEL();
CP(cp, wcursor);
if (cp > linebuf && (cp[0] == 0 || c == '#'))
cp = lastchr(linebuf, cp);
if (state == HARDOPEN) {
bleep(i, cp);
cursor = cp;
return (0);
}
physdc(lcolumn(cursor), i);
DEPTH(vcline) = 0;
if(MB_CUR_MAX > 1)
rewrite = _ON;
(void) vreopen(LINE(vcline), lineDOT(), vcline);
if(MB_CUR_MAX > 1)
rewrite = _OFF;
vsyncCL();
vsetcurs(cp);
return (0);
}
int
vchange(unsigned char c)
{
unsigned char *cp;
int i, ind, cnt;
line *addr;
if (wdot) {
if ((cnt = xdw()) < 0)
return (0);
getDOT();
if (wcursor && cnt == 1) {
wdot = 0;
if (c == 'd') {
(void) vdelete(c);
return (0);
}
goto smallchange;
}
if (cursor && wcursor) {
*cursor = 0;
strcpy(genbuf, linebuf);
getaline(*wdot);
if (strlen(genbuf) + strlen(wcursor) > LBSIZE - 2) {
getDOT();
(void) beep();
return (0);
}
strcat(genbuf, wcursor);
if (c == 'd' && *vpastwh(genbuf) == 0) {
wcursor = 0;
getDOT();
op = 0;
notpart(lastreg);
notpart('1');
(void) vdelete(c);
return (0);
}
ind = -1;
} else if (c == 'd' && wcursor == 0) {
(void) vdelete(c);
return (0);
} else
if (value(vi_LISP) && value(vi_AUTOINDENT))
ind = lindent(dot);
else
ind = whitecnt(linebuf);
i = vcline >= 0 ? LINE(vcline) : WTOP;
addr = dot;
vremote(cnt, delete, 0);
setpk();
notenam = (unsigned char *)"delete";
if (c != 'd')
notenam = (unsigned char *)"change";
DEL[0] = 0;
if (cnt > 1)
killU();
vreplace(vcline, cnt, 0);
wdot = NOLINE;
noteit(0);
vcline--;
if (addr <= dol)
dot--;
if (ind >= 0) {
fixundo();
*genindent(ind) = 0;
vdoappend(genbuf);
} else {
vmcurs = cursor;
strcLIN(genbuf);
vdoappend(linebuf);
}
if (c != 'd' && state != VISUAL && state != HARDOPEN) {
int oldhold = hold;
hold |= HOLDAT, vclrlin(i, dot), hold = oldhold;
}
vcline++;
if (vcline < 0)
vcline = 0;
vopen(dot, i);
vsyncCL();
noteit(1);
if (c != 'd') {
if (ind >= 0) {
cursor = linebuf;
fixundo();
linebuf[0] = 0;
vfixcurs();
} else {
ind = 0;
fixundo();
vcursat(cursor);
}
vappend('x', 1, ind);
return (0);
}
if (*cursor == 0 && cursor > linebuf)
cursor = lastchr(linebuf, cursor);
vrepaint(cursor);
return (0);
}
smallchange:
if (wcursor < linebuf)
wcursor = linebuf;
if (cursor == wcursor) {
(void) beep();
return (0);
}
i = vdcMID();
cp = cursor;
if (state != HARDOPEN)
vfixcurs();
if (state == HARDOPEN)
bleep(i, cp);
else {
vcursbef(wcursor);
putchar('$');
i = cindent();
}
cursor = cp;
setDEL();
CP(cursor, wcursor);
fixundo();
if (state != HARDOPEN) {
vgotoCL(lcolumn(cp));
doomed = i - cindent();
} else {
doomed = 0;
}
prepapp();
vappend('c', 1, 0);
return (0);
}
void
voOpen(int c, int cnt)
{
int ind = 0, i;
short oldhold = hold;
vsave();
setLAST();
if (value(vi_AUTOINDENT))
ind = whitecnt(linebuf);
if (c == 'O') {
vcline--;
dot--;
if (dot > zero)
getDOT();
}
if (value(vi_AUTOINDENT)) {
if (value(vi_LISP))
ind = lindent(dot + 1);
}
killU();
prepapp();
if (FIXUNDO)
vundkind = VMANY;
if (state != VISUAL)
c = WBOT + 1;
else {
c = vcline < 0 ? WTOP - cnt : LINE(vcline) + DEPTH(vcline);
if (c < ZERO)
c = ZERO;
i = LINE(vcline + 1) - c;
if (i < cnt && c <= WBOT && (!insert_line || !delete_line))
vinslin(c, cnt - i, vcline);
}
*genindent(ind) = 0;
vdoappend(genbuf);
vcline++;
oldhold = hold;
hold |= HOLDROL;
vopen(dot, c);
hold = oldhold;
if (value(vi_SLOWOPEN))
vscrap();
else
vsync1(LINE(vcline));
cursor = linebuf;
fixundo();
linebuf[0] = 0;
vappend('o', cnt, ind);
}
unsigned char vshnam[2] = { 'x', 0 };
int
vshftop(void)
{
line *addr;
int cnt;
if ((cnt = xdw()) < 0)
return (0);
addr = dot;
vremote(cnt, vshift, 0);
vshnam[0] = op;
notenam = vshnam;
dot = addr;
vreplace(vcline, cnt, cnt);
if (state == HARDOPEN)
vcnt = 0;
vrepaint(NOSTR);
return (0);
}
int
vfilter(void)
{
line *addr;
int cnt;
unsigned char *oglobp;
short d;
if ((cnt = xdw()) < 0)
return (0);
if (vglobp)
vglobp = (unsigned char *)uxb;
if (readecho('!'))
return (0);
oglobp = globp; globp = genbuf + 1;
d = peekc; ungetchar(0);
CATCH
fixech();
unix0(0, 0);
ONERR
splitw = 0;
ungetchar(d);
vrepaint(cursor);
globp = oglobp;
return (0);
ENDCATCH
ungetchar(d); globp = oglobp;
addr = dot;
CATCH
vgoto(WECHO, 0); flusho();
vremote(cnt, vi_filter, 2);
ONERR
vdirty(0, lines);
ENDCATCH
if (dot == zero && dol > zero)
dot = one;
splitw = 0;
notenam = (unsigned char *)"";
vreplace(vcline, cnt, undap2 - undap1);
dot = addr;
if (dot > dol) {
dot--;
vcline--;
}
vrepaint(NOSTR);
return (0);
}
int
xdw(void)
{
unsigned char *cp;
int cnt;
if (wdot == NOLINE || wdot < one || wdot > dol) {
(void) beep();
return (-1);
}
vsave();
setLAST();
if (dot > wdot || (dot == wdot && wcursor != 0 && cursor > wcursor)) {
line *addr;
vcline -= dot - wdot;
addr = dot; dot = wdot; wdot = addr;
cp = cursor; cursor = wcursor; wcursor = cp;
}
if (cursor && wcursor == linebuf && wdot > dot) {
wdot--;
getDOT();
if (vpastwh(linebuf) >= cursor)
wcursor = 0;
else {
getaline(*wdot);
wcursor = strend(linebuf);
getDOT();
}
}
cnt = wdot - dot + 1;
if (vreg) {
vremote(cnt, YANKreg, vreg);
}
vreg = 0;
if (any(op, (unsigned char *)"cdCS")) {
vremote(cnt, YANKreg, '1');
}
return (cnt);
}
int
vshift(void)
{
shift(op, 1);
return (0);
}
void
vrep(int cnt)
{
int i, c;
unsigned char *endcurs;
endcurs = cursor;
for(i = 1; i <= cnt; i++) {
if(!*endcurs) {
(void) beep();
return;
}
endcurs = nextchr(endcurs);
}
i = lcolumn(endcurs);
vcursat(cursor);
doomed = i - cindent();
if(value(vi_TERSE))
vshowmode(gettext("r"));
else
vshowmode(gettext("REPLACE 1 CHAR"));
if (!vglobp) {
c = getesc();
if (c == 0) {
vshowmode("");
vfixcurs();
return;
}
ungetkey(c);
}
CP(vutmp, linebuf);
if (FIXUNDO)
vundkind = VCHNG;
wcursor = endcurs;
vUD1 = cursor; vUD2 = wcursor;
CP(cursor, wcursor);
prepapp();
vappend('r', cnt, 0);
*lastcp++ = INS[0];
setLAST();
}
int
vyankit(void)
{
int cnt;
if (wdot) {
if ((cnt = xdw()) < 0)
return (0);
vremote(cnt, yank, 0);
setpk();
notenam = (unsigned char *)"yank";
if (FIXUNDO)
vundkind = VNONE;
DEL[0] = 0;
wdot = NOLINE;
if (notecnt <= vcnt - vcline && notecnt < value(vi_REPORT))
notecnt = 0;
vrepaint(cursor);
return (0);
} else {
setLAST();
}
takeout(DEL);
return (0);
}
void
setpk(void)
{
if (wcursor) {
pkill[0] = cursor;
pkill[1] = wcursor;
}
}
void
fixundo(void)
{
if (lastcmd[0] == 'C' || lastcmd[0] == 'c' || lastcmd[0] == 'o' ||
lastcmd[0] == 'R' || lastcmd[0] == 'S' || lastcmd[0] == 's') {
vmcurs = cursor;
}
}