#include <sys/stropts.h>
#include <sys/eucioctl.h>
#ifndef PRESUNEUC
#include <locale.h>
#ifdef putchar
# undef putchar
#endif
#ifdef getchar
# undef getchar
#endif
#endif
#include "ex.h"
#include "ex_re.h"
#include "ex_tty.h"
#include "ex_vis.h"
#ifndef PRESUNEUC
int (*wdwc)(wchar_t);
int (*wdbdg)(wchar_t, wchar_t, int);
wchar_t *(*wddlm)(wchar_t, wchar_t, int);
wchar_t (*mcfllr)(void);
#endif
int
any(int c, unsigned char *s)
{
int x;
while (x = *s++)
if (x == c)
return (1);
return (0);
}
int
backtab(int i)
{
int j;
j = i % value(vi_SHIFTWIDTH);
if (j == 0)
j = value(vi_SHIFTWIDTH);
i -= j;
if (i < 0)
i = 0;
return (i);
}
void
change(void)
{
tchng++;
chng = tchng;
}
int
column(unsigned char *cp)
{
if (cp == 0)
cp = &linebuf[LBSIZE - 2];
return (qcolumn(cp, (unsigned char *)0));
}
int
lcolumn(unsigned char *cp)
{
if (cp == 0)
cp = &linebuf[LBSIZE - 2];
return (nqcolumn(lastchr(linebuf, cp), (unsigned char *)0));
}
void
comment(void)
{
int c;
do {
c = getchar();
} while (c != '\n' && c != EOF);
if (c == EOF)
ungetchar(c);
}
void
Copy(unsigned char *to, unsigned char *from, int size)
{
if (size > 0)
do
*to++ = *from++;
while (--size > 0);
}
void
copyw(line *to, line *from, int size)
{
if (size > 0)
do
*to++ = *from++;
while (--size > 0);
}
void
copywR(line *to, line *from, int size)
{
while (--size >= 0)
to[size] = from[size];
}
int
ctlof(int c)
{
return (c == DELETE ? '?' : c | ('A' - 1));
}
void
dingdong(void)
{
if (flash_screen && value(vi_FLASH))
putpad((unsigned char *)flash_screen);
else if (value(vi_ERRORBELLS))
putpad((unsigned char *)bell);
}
int
fixindent(int indent)
{
int i;
unsigned char *cp;
i = whitecnt(genbuf);
cp = vpastwh(genbuf);
if (*cp == 0 && i == indent && linebuf[0] == 0) {
genbuf[0] = 0;
return (i);
}
CP(genindent(i), cp);
return (i);
}
void
filioerr(unsigned char *cp)
{
int oerrno = errno;
lprintf("\"%s\"", cp);
errno = oerrno;
syserror(1);
}
unsigned char *
genindent(indent)
int indent;
{
unsigned char *cp;
for (cp = genbuf; indent >= value(vi_TABSTOP); indent -= value(vi_TABSTOP))
*cp++ = '\t';
for (; indent > 0; indent--)
*cp++ = ' ';
return (cp);
}
void
getDOT(void)
{
getaline(*dot);
}
line *
getmark(c)
int c;
{
line *addr;
for (addr = one; addr <= dol; addr++)
if (names[c - 'a'] == (*addr &~ 01)) {
return (addr);
}
return (0);
}
void
ignnEOF(void)
{
int c = getchar();
if (c == EOF)
ungetchar(c);
else if (c=='"')
comment();
}
int
iswhite(int c)
{
return (c == ' ' || c == '\t');
}
int
junk(wchar_t c)
{
if (c && !value(vi_BEAUTIFY))
return (0);
if (c >= ' ' && c != DELETE)
return (0);
switch (c) {
case '\t':
case '\n':
case '\f':
return (0);
default:
return (1);
}
}
void
killed(void)
{
killcnt(addr2 - addr1 + 1);
}
void
killcnt(int cnt)
{
extern char *verbalize();
if (inopen) {
notecnt = cnt;
notenam = notesgn = (unsigned char *)"";
return;
}
if (!notable(cnt))
return;
if (value(vi_TERSE) == 0) {
verbalize(cnt, Command, "");
} else {
if (cnt == 1) {
viprintf(gettext("1 line"), cnt);
} else {
viprintf(gettext("%d lines"), cnt);
}
}
putNFL();
}
int
lineno(line *a)
{
return (a - zero);
}
int
lineDOL(void)
{
return (lineno(dol));
}
int
lineDOT(void)
{
return (lineno(dot));
}
void
markDOT(void)
{
markpr(dot);
}
void
markpr(line *which)
{
if ((inglobal == 0 || inopen) && which <= endcore) {
names['z'-'a'+1] = *which & ~01;
if (inopen)
ncols['z'-'a'+1] = cursor;
}
}
int
markreg(int c)
{
if (c == '\'' || c == '`')
return ('z' + 1);
if (c >= 'a' && c <= 'z')
return (c);
return (0);
}
unsigned char *
mesg(str)
unsigned char *str;
{
unsigned char *cp;
str = (unsigned char *)strcpy(genbuf, str);
return (str);
}
void
merror(unsigned char *seekpt, int i)
{
unsigned char *cp = linebuf;
if (seekpt == 0)
return;
merror1(seekpt);
if (*cp == '\n')
putnl(), cp++;
if (inopen > 0 && clr_eol)
vclreol();
if (enter_standout_mode && exit_bold)
putpad((unsigned char *)enter_standout_mode);
#ifdef PRESUNEUC
viprintf(mesg(cp), i);
#else
viprintf((char *)mesg(cp), i);
#endif
if (enter_standout_mode && exit_bold)
putpad((unsigned char *)exit_bold);
}
void
merror1(unsigned char *seekpt)
{
strcpy(linebuf, seekpt);
}
#define MAXDATA (56*1024)
int
morelines(void)
{
unsigned char *end;
if ((int) sbrk(1024 * sizeof (line)) == -1) {
if (endcore >= (line *) MAXDATA)
return -1;
end = (unsigned char *) MAXDATA;
while (brk(end+2) == -1)
end -= 64;
if (end <= (unsigned char *) endcore)
return -1;
endcore = (line *) end;
} else {
endcore += 1024;
}
return (0);
}
void
nonzero(void)
{
if (addr1 == zero) {
notempty();
error(value(vi_TERSE) ? gettext("Nonzero address required") :
gettext("Nonzero address required on this command"));
}
}
int
notable(int i)
{
return (hush == 0 && !inglobal && i > value(vi_REPORT));
}
void
notempty(void)
{
if (dol == zero)
error(value(vi_TERSE) ? gettext("No lines") :
gettext("No lines in the buffer"));
}
void
netchHAD(int cnt)
{
netchange(lineDOL() - cnt);
}
void
netchange(int i)
{
unsigned char *cp;
if (i > 0)
notesgn = cp = (unsigned char *)"more ";
else
notesgn = cp = (unsigned char *)"fewer ", i = -i;
if (inopen) {
notecnt = i;
notenam = (unsigned char *)"";
return;
}
if (!notable(i))
return;
if (*cp == 'm')
#ifdef PRESUNEUC
viprintf(mesg(value(vi_TERSE) ?
#else
viprintf((char *)mesg(value(vi_TERSE) ?
#endif
gettext("%d more lines") :
gettext("%d more lines in file after %s")), i, Command);
else
#ifdef PRESUNEUC
viprintf(mesg(value(vi_TERSE) ?
#else
viprintf((char *)mesg(value(vi_TERSE) ?
#endif
gettext("%d fewer lines") :
gettext("%d fewer lines in file after %s")), i, Command);
putNFL();
}
void
putmark(line *addr)
{
putmk1(addr, putline());
}
void
putmk1(line *addr, int n)
{
line *markp;
int oldglobmk;
oldglobmk = *addr & 1;
*addr &= ~1;
for (markp = (anymarks ? names : &names['z'-'a'+1]);
markp <= &names['z'-'a'+1]; markp++)
if (*markp == *addr)
*markp = n;
*addr = n | oldglobmk;
}
unsigned char *
plural(i)
long i;
{
return (i == 1 ? (unsigned char *)"" : (unsigned char *)"s");
}
int qcount();
short vcntcol;
int
qcolumn(unsigned char *lim, unsigned char *gp)
{
int x, length;
int col;
wchar_t wchar;
int (*OO)();
OO = Outchar;
Outchar = qcount;
vcntcol = 0;
if (lim != NULL) {
if(lim == linebuf - 1 || lim == &linebuf[LBSIZE-2])
length = 1;
else
length = mbtowc(&wchar, (char *)lim, MULTI_BYTE_MAX);
if(length < 0)
length = 1;
x = lim[length];
lim[length] = 0;
}
pline(0);
if (lim != NULL)
lim[length] = x;
if(length > 1 && !gp) {
if ((col = wcwidth(wchar)) < 0)
col = 0;
vcntcol = vcntcol - col + 1;
}
if (gp)
while (*gp) {
length = mbtowc(&wchar, (char *)gp, MULTI_BYTE_MAX);
if(length < 0) {
putoctal = 1;
putchar(*gp++);
putoctal = 0;
} else {
putchar(wchar);
gp += length;
}
}
Outchar = OO;
return (vcntcol);
}
int
nqcolumn(unsigned char *lim, unsigned char *gp)
{
int x, length;
wchar_t wchar;
int (*OO)();
OO = Outchar;
Outchar = qcount;
vcntcol = 0;
if (lim != NULL) {
if(lim == linebuf - 1 || lim == &linebuf[LBSIZE-2])
length = 1;
else
length = mbtowc(&wchar, (char *)lim, MULTI_BYTE_MAX);
if(length < 0)
length = 1;
x = lim[length];
lim[length] = 0;
}
pline(0);
if (lim != NULL)
lim[length] = x;
if (gp)
while (*gp) {
length = mbtowc(&wchar, (char *)gp, MULTI_BYTE_MAX);
if(length < 0) {
putoctal = 1;
putchar(*gp++);
putoctal = 0;
} else {
putchar(wchar);
gp += length;
}
}
Outchar = OO;
return (vcntcol);
}
int
qcount(c)
wchar_t c;
{
int cols;
#ifndef PRESUNEUC
int remcols;
short OWCOLS;
#endif
if (c == '\t') {
vcntcol += value(vi_TABSTOP) - vcntcol % value(vi_TABSTOP);
return (0);
}
#ifdef PRESUNEUC
if ((cols = wcwidth(c)) > 0)
vcntcol += cols;
#else
if ((cols = wcwidth(c)) < 0)
cols = 0;
OWCOLS = WCOLS;
if (WCOLS == 0)
WCOLS = columns;
if ((mc_wrap) == 1 && (remcols = (WCOLS - (vcntcol % WCOLS))) < cols)
vcntcol += remcols;
WCOLS = OWCOLS;
vcntcol += cols;
#endif
return (0);
}
void
reverse(line *a1, line *a2)
{
line t;
for (;;) {
t = *--a2;
if (a2 <= a1)
return;
*a2 = *a1;
*a1++ = t;
}
}
void
save(line *a1, line *a2)
{
int more;
if (!FIXUNDO)
return;
#ifdef UNDOTRACE
if (trace)
vudump("before save");
#endif
undkind = UNDNONE;
undadot = dot;
more = (a2 - a1 + 1) - (unddol - dol);
while (more > (endcore - truedol))
if (morelines() < 0)
error(value(vi_TERSE) ? gettext("Out of memory") :
gettext("Out of memory saving lines for undo - try using ed"));
if (more)
(*(more > 0 ? copywR : copyw))(unddol + more + 1, unddol + 1,
(truedol - unddol));
unddol += more;
truedol += more;
copyw(dol + 1, a1, a2 - a1 + 1);
undkind = UNDALL;
unddel = a1 - 1;
undap1 = a1;
undap2 = a2 + 1;
#ifdef UNDOTRACE
if (trace)
vudump("after save");
#endif
}
void
save12(void)
{
save(addr1, addr2);
}
void
saveall(void)
{
save(one, dol);
}
int
span(void)
{
return (addr2 - addr1 + 1);
}
void
sync(void)
{
chng = 0;
tchng = 0;
xchng = 0;
}
int
skipwh(void)
{
int wh;
wh = 0;
while (iswhite(peekchar())) {
wh++;
ignchar();
}
return (wh);
}
void
smerror(unsigned char *seekpt, unsigned char *cp)
{
errcnt++;
merror1(seekpt);
if (inopen && clr_eol)
vclreol();
if (enter_standout_mode && exit_bold)
putpad((unsigned char *)enter_standout_mode);
lprintf(mesg(linebuf), cp);
if (enter_standout_mode && exit_bold)
putpad((unsigned char *)exit_bold);
}
unsigned char *
strend(cp)
unsigned char *cp;
{
while (*cp)
cp++;
return (cp);
}
void
strcLIN(unsigned char *dp)
{
CP(linebuf, dp);
}
void
syserror(int danger)
{
int e = errno;
char *errstr;
extern char *strerror();
dirtcnt = 0;
putchar(' ');
if (danger)
edited = 0;
if ((errstr = strerror(e)) != NULL)
error(errstr);
else
error(gettext("System error %d"), e);
}
int
tabcol(int col, int ts)
{
int offset, result;
if (col >= columns) {
offset = columns * (col/columns);
col -= offset;
} else
offset = 0;
result = col + ts - (col % ts) + offset;
return (result);
}
unsigned char *
vfindcol(i)
int i;
{
unsigned char *cp, *oldcp;
int (*OO)() = Outchar;
int length;
unsigned char x;
wchar_t wchar;
Outchar = qcount;
(void) qcolumn(linebuf - 1, (unsigned char *)NOSTR);
for (cp = linebuf; *cp && vcntcol < i; ) {
oldcp = cp;
length = mbtowc(&wchar, (char *)cp, MULTI_BYTE_MAX);
if(length < 0) {
putoctal = 1;
putchar(*cp++);
putoctal = 0;
} else {
putchar(wchar);
cp += length;
}
}
if (cp != linebuf)
cp = oldcp;
Outchar = OO;
return (cp);
}
unsigned char *
vskipwh(cp)
unsigned char *cp;
{
while (iswhite(*cp) && cp[1])
cp++;
return (cp);
}
unsigned char *
vpastwh(cp)
unsigned char *cp;
{
while (iswhite(*cp))
cp++;
return (cp);
}
int
whitecnt(unsigned char *cp)
{
int i;
i = 0;
for (;;)
switch (*cp++) {
case '\t':
i += value(vi_TABSTOP) - i % value(vi_TABSTOP);
break;
case ' ':
i++;
break;
default:
return (i);
}
}
void
markit(line *addr)
{
if (addr != dot && addr >= one && addr <= dol)
markDOT();
}
void
onhup(sig)
int sig;
{
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
if (chng == 0) {
cleanup(1);
exit(++errcnt);
}
if (setexit() == 0) {
if (preserve()) {
cleanup(1);
exit(++errcnt);
}
}
if (kflag)
crypt_close(perm);
if (xtflag)
crypt_close(tperm);
exit(++errcnt);
}
void oncore(sig)
int sig;
{
static int timescalled = 0;
char *messagep;
signal(SIGINT, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(sig, SIG_DFL);
messagep = (char *)gettext("\r\nYour file has been preserved\r\n");
if (timescalled++ == 0 && chng && setexit() == 0) {
if (inopen)
vsave();
(void) preserve();
write(1, messagep, strlen(messagep));
}
if (timescalled < 2) {
normal(normf);
cleanup(2);
kill(getpid(), sig);
}
if (kflag)
crypt_close(perm);
if (xtflag)
crypt_close(tperm);
exit(++errcnt);
}
void
onintr(sig)
int sig;
{
#ifndef CBREAK
signal(SIGINT, onintr);
#else
signal(SIGINT, inopen ? vintr : onintr);
#endif
cancelalarm();
draino();
if (!inopen) {
pstop();
setlastchar('\n');
#ifdef CBREAK
}
#else
} else
vraw();
#endif
error(gettext("\nInterrupt") + (inopen!=0));
}
void
setrupt(void)
{
if (ruptible) {
#ifndef CBREAK
signal(SIGINT, onintr);
#else
signal(SIGINT, inopen ? vintr : onintr);
#endif
#ifdef SIGTSTP
if (dosusp)
signal(SIGTSTP, onsusp);
#endif
}
}
int
preserve(void)
{
#ifdef VMUNIX
tflush();
#endif
synctmp();
pid = fork();
if (pid < 0)
return (0);
if (pid == 0) {
close(0);
dup(tfile);
execlp(EXPRESERVE, "expreserve", (char *) 0);
exit(++errcnt);
}
waitfor();
if (rpid == pid && status == 0)
return (1);
return (0);
}
#ifndef V6
void exit(i)
int i;
{
extern void _exit(int) __NORETURN;
#ifdef TRACE
if (trace)
fclose(trace);
#endif
_exit(i);
}
#endif
#ifdef SIGTSTP
extern void redraw();
void
onsusp(sig)
int sig;
{
ttymode f;
int savenormtty;
f = setty(normf);
vnfl();
putpad((unsigned char *)exit_ca_mode);
flush();
resetterm();
savenormtty = normtty;
normtty = 0;
signal(SIGTSTP, SIG_DFL);
kill(0, SIGTSTP);
signal(SIGTSTP, onsusp);
normtty = savenormtty;
vcontin(0);
flush();
setty(f);
if (!inopen)
syserror(0);
else {
if(vcnt < 0) {
vcnt = -vcnt;
if(state == VISUAL)
vclear();
else if(state == CRTOPEN)
vcnt = 0;
}
vdirty(0, lines);
if (sig)
vrepaint(cursor);
}
}
#endif
unsigned char *nextchr(cursor)
unsigned char *cursor;
{
wchar_t wchar;
int length;
length = mbtowc(&wchar, (char *)cursor, MULTI_BYTE_MAX);
if(length <= 0)
return(++cursor);
return(cursor + length);
}
unsigned char *lastchr(linebuf, cursor)
unsigned char *linebuf, *cursor;
{
wchar_t wchar;
int length;
unsigned char *ccursor, *ocursor;
if(cursor == linebuf)
return(linebuf - 1);
ccursor = ocursor = linebuf;
while(ccursor < cursor) {
length = mbtowc(&wchar, (char *)ccursor, MULTI_BYTE_MAX);
ocursor = ccursor;
if(length <= 0)
ccursor++;
else
ccursor += length;
}
return(ocursor);
}
int
ixlatctl(int flag)
{
static struct strioctl sb = {0, 0, 0, 0};
if (!(MULTI_BYTE_MAX > 1))
return (0);
switch (flag) {
case 0:
sb.ic_cmd = EUC_MSAVE;
sb.ic_len = 0;
sb.ic_dp = 0;
if (ioctl(0, I_STR, &sb) < 0)
return (-1);
return (0);
case 1:
sb.ic_cmd = EUC_MREST;
sb.ic_len = 0;
sb.ic_dp = 0;
if (ioctl(0, I_STR, &sb) < 0)
return (-1);
return (0);
case 11:
return (0);
default:
return (-1);
}
}
#ifndef PRESUNEUC
void
localize(void)
{
wchar_t fillerchar;
extern int wdchkind();
extern int wdbindf();
extern wchar_t *wddelim();
extern wchar_t mcfiller();
wdwc = wdchkind;
wdbdg = wdbindf;
wddlm = wddelim;
mcfllr = mcfiller;
mc_wrap = 1;
fillerchar = mcfiller();
mc_filler = isascii(fillerchar) ? (fillerchar & 0x7f) : '~';
}
#endif