#include "sh.h"
RCSID("$Id: ed.refresh.c,v 3.39 2005/02/15 21:09:02 christos Exp $")
#include "ed.h"
Char *litptr;
static int vcursor_h, vcursor_v;
static int rprompt_h, rprompt_v;
static int MakeLiteral __P((Char *, int, Char));
static int Draw __P((Char *, int));
static void Vdraw __P((Char, int));
static void RefreshPromptpart __P((Char *));
static void update_line __P((Char *, Char *, int));
static void str_insert __P((Char *, int, int, Char *, int));
static void str_delete __P((Char *, int, int, int));
static void str_cp __P((Char *, Char *, int));
#ifndef WINNT_NATIVE
static
#else
extern
#endif
void PutPlusOne __P((Char, int));
static void cpy_pad_spaces __P((Char *, Char *, int));
#if defined(DEBUG_UPDATE) || defined(DEBUG_REFRESH) || defined(DEBUG_LITERAL)
static void dprintf __P((char *, ...));
#ifdef DEBUG_UPDATE
static void dprintstr __P((char *, const Char *, const Char *));
static void
dprintstr(str, f, t)
char *str;
const Char *f, *t;
{
dprintf("%s:\"", str);
while (f < t) {
if (*f & ~ASCII)
dprintf("[%x]", *f++);
else
dprintf("%c", *f++ & ASCII);
}
dprintf("\"\r\n");
}
#endif
static void
#ifdef PROTOTYPES
dprintf(char *fmt, ...)
#else
dprintf(va_list)
va_dcl
#endif
{
static int fd = -1;
char *dtty;
if ((dtty = getenv("DEBUGTTY"))) {
int o;
va_list va;
#ifdef PROTOTYPES
va_start(va, fmt);
#else
char *fmt;
va_start(va);
fmt = va_arg(va, char *);
#endif
if (fd == -1)
fd = open(dtty, O_RDWR);
o = SHOUT;
flush();
SHOUT = fd;
xvprintf(fmt, va);
va_end(va);
flush();
SHOUT = o;
}
}
#endif
static int litlen = 0, litalloc = 0;
static int MakeLiteral(str, len, addlit)
Char *str;
int len;
Char addlit;
{
int i, addlitlen = 0;
Char *addlitptr = 0;
if (addlit) {
if ((addlit & LITERAL) != 0) {
addlitptr = litptr + (addlit & ~LITERAL) * LIT_FACTOR;
addlitlen = Strlen(addlitptr);
} else {
addlitptr = &addlit;
addlitlen = 1;
}
for (i = 0; i < litlen; i += LIT_FACTOR)
if (!Strncmp(addlitptr, litptr + i, addlitlen) && !Strncmp(str, litptr + i + addlitlen, len) && litptr[i + addlitlen + len] == 0)
return (i / LIT_FACTOR) | LITERAL;
} else {
addlitlen = 0;
for (i = 0; i < litlen; i += LIT_FACTOR)
if (!Strncmp(str, litptr + i, len) && litptr[i + len] == 0)
return (i / LIT_FACTOR) | LITERAL;
}
if (litlen + addlitlen + len + 1 + (LIT_FACTOR - 1) > litalloc) {
Char *newlitptr;
int add = 256;
while (len + addlitlen + 1 + (LIT_FACTOR - 1) > add)
add *= 2;
if (litptr)
newlitptr = (Char *)xrealloc(litptr, (litalloc + add) * sizeof(Char));
else
newlitptr = (Char *)xmalloc((litalloc + add) * sizeof(Char));
if (!newlitptr)
return '?';
litptr = newlitptr;
litalloc += add;
if (addlitptr && addlitptr != &addlit)
addlitptr = litptr + (addlit & ~LITERAL) * LIT_FACTOR;
}
i = litlen / LIT_FACTOR;
if (i >= LITERAL || i == CHAR_DBWIDTH)
return '?';
if (addlitptr) {
Strncpy(litptr + litlen, addlitptr, addlitlen);
litlen += addlitlen;
}
Strncpy(litptr + litlen, str, len);
litlen += len;
do
litptr[litlen++] = 0;
while (litlen % LIT_FACTOR);
return i | LITERAL;
}
static int
Draw(cp, nocomb)
Char *cp;
int nocomb;
{
int l, w, i, lv, lh;
Char ch, attr;
NLSChar c;
attr = *cp & ~CHAR;
l = NLSFrom(cp, NLSZEROT, &c);
w = NLSClassify(c, nocomb);
switch (w) {
case NLSCLASS_NL:
Vdraw('\0', 0);
vcursor_h = 0;
vcursor_v++;
break;
case NLSCLASS_TAB:
do {
Vdraw(' ', 1);
} while ((vcursor_h & 07) != 0);
break;
case NLSCLASS_CTRL:
Vdraw('^' | attr, 1);
if (c == CTL_ESC('\177')) {
Vdraw('?' | attr, 1);
} else {
#ifdef IS_ASCII
Vdraw(c | 0100 | attr, 1);
#else
Vdraw(_toebcdic[_toascii[c]|0100] | attr, 1);
#endif
}
break;
case NLSCLASS_ILLEGAL:
ch = *cp & CHAR;
Vdraw('\\' | attr, 1);
Vdraw((((ch >> 6) & 7) + '0') | attr, 1);
Vdraw((((ch >> 3) & 7) + '0') | attr, 1);
Vdraw(((ch & 7) + '0') | attr, 1);
break;
case NLSCLASS_ILLEGAL2:
case NLSCLASS_ILLEGAL3:
case NLSCLASS_ILLEGAL4:
Vdraw('\\' | attr, 1);
Vdraw('U' | attr, 1);
Vdraw('+' | attr, 1);
for (i = 8 * NLSCLASS_ILLEGAL_SIZE(w) - 4; i >= 0; i -= 4)
Vdraw("0123456789ABCDEF"[(c >> i) & 15] | attr, 1);
break;
case 0:
lv = vcursor_v;
lh = vcursor_h;
for (;;) {
lh--;
if (lh < 0) {
lv--;
if (lv < 0)
break;
lh = Strlen(Vdisplay[lv]) - 1;
}
if (Vdisplay[lv][lh] != CHAR_DBWIDTH)
break;
}
if (lv < 0) {
int l2 = l;
for (; l2-- > 0; cp++) {
ch = *cp & CHAR;
Vdraw('\\' | attr, 1);
Vdraw((((ch >> 6) & 7) + '0') | attr, 1);
Vdraw((((ch >> 3) & 7) + '0') | attr, 1);
Vdraw(((ch & 7) + '0') | attr, 1);
}
return l;
}
Vdisplay[lv][lh] = MakeLiteral(cp, l, Vdisplay[lv][lh]);
break;
default:
if (l > 1)
Vdraw(MakeLiteral(cp, l, 0), w);
else
Vdraw(*cp, w);
break;
}
return l;
}
static void
Vdraw(c, width)
Char c;
int width;
{
#ifdef DEBUG_REFRESH
# ifdef SHORT_STRINGS
dprintf("Vdrawing %6.6o '%c' %d\r\n", (unsigned)c, (int)(c & ASCII), width);
# else
dprintf("Vdrawing %3.3o '%c' %d\r\n", (unsigned)c, (int)c, width);
# endif
#endif
while (vcursor_h + width > TermH)
Vdraw(' ', 1);
Vdisplay[vcursor_v][vcursor_h] = (Char) c;
if (width)
vcursor_h++;
while (--width > 0)
Vdisplay[vcursor_v][vcursor_h++] = CHAR_DBWIDTH;
if (vcursor_h >= TermH) {
Vdisplay[vcursor_v][TermH] = '\0';
vcursor_h = 0;
vcursor_v++;
#ifdef DEBUG_REFRESH
if (vcursor_v >= TermV) {
dprintf("\r\nVdraw: vcursor_v overflow! Vcursor_v == %d > %d\r\n",
vcursor_v, TermV);
abort();
}
#endif
}
}
static void
RefreshPromptpart(buf)
Char *buf;
{
Char *cp;
NLSChar c;
int l, w;
for (cp = buf; *cp; ) {
if (*cp & LITERAL) {
Char *litstart = cp;
while (*cp & LITERAL)
cp++;
if (*cp) {
l = NLSFrom(cp, NLSZEROT, &c);
w = NLSWidth(c);
Vdraw(MakeLiteral(litstart, cp + l - litstart, 0), w);
cp += l;
}
else {
break;
}
}
else
cp += Draw(cp, cp == buf);
}
}
#ifndef WINNT_NATIVE
static
#endif
int OldvcV = 0;
void
Refresh()
{
int cur_line;
Char *cp;
int cur_h, cur_v = 0, new_vcv;
int rhdiff;
Char oldgetting;
#ifdef DEBUG_REFRESH
dprintf("PromptBuf = :%s:\r\n", short2str(PromptBuf));
dprintf("InputBuf = :%s:\r\n", short2str(InputBuf));
#endif
oldgetting = GettingInput;
GettingInput = 0;
vcursor_h = 0;
vcursor_v = 0;
RefreshPromptpart(RPromptBuf);
rprompt_h = vcursor_h;
rprompt_v = vcursor_v;
vcursor_h = 0;
vcursor_v = 0;
RefreshPromptpart(PromptBuf);
cur_h = -1;
for (cp = InputBuf; (cp < LastChar); ) {
if (cp >= Cursor && cur_h == -1) {
cur_h = vcursor_h;
cur_v = vcursor_v;
Cursor = cp;
}
cp += Draw(cp, cp == InputBuf);
}
if (cur_h == -1) {
cur_h = vcursor_h;
cur_v = vcursor_v;
}
rhdiff = TermH - vcursor_h - rprompt_h;
if (rprompt_h != 0 && rprompt_v == 0 && vcursor_v == 0 && rhdiff > 1) {
while (--rhdiff > 0)
Vdraw(' ', 1);
RefreshPromptpart(RPromptBuf);
}
else {
rprompt_h = 0;
rprompt_v = 0;
}
new_vcv = vcursor_v;
Vdraw('\0', 1);
#if defined (DEBUG_REFRESH)
dprintf("TermH=%d, vcur_h=%d, vcur_v=%d, Vdisplay[0]=\r\n:%80.80s:\r\n",
TermH, vcursor_h, vcursor_v, short2str(Vdisplay[0]));
#endif
#ifdef DEBUG_UPDATE
dprintf("updating %d lines.\r\n", new_vcv);
#endif
for (cur_line = 0; cur_line <= new_vcv; cur_line++) {
update_line(Display[cur_line], Vdisplay[cur_line], cur_line);
#ifdef WINNT_NATIVE
flush();
#endif
cpy_pad_spaces(Display[cur_line], Vdisplay[cur_line], TermH);
}
#ifdef DEBUG_REFRESH
dprintf("\r\nvcursor_v = %d, OldvcV = %d, cur_line = %d\r\n",
vcursor_v, OldvcV, cur_line);
#endif
if (OldvcV > new_vcv) {
for (; cur_line <= OldvcV; cur_line++) {
update_line(Display[cur_line], STRNULL, cur_line);
*Display[cur_line] = '\0';
}
}
OldvcV = new_vcv;
#ifdef DEBUG_REFRESH
dprintf("\r\nCursorH = %d, CursorV = %d, cur_h = %d, cur_v = %d\r\n",
CursorH, CursorV, cur_h, cur_v);
#endif
#ifdef WINNT_NATIVE
flush();
#endif
MoveToLine(cur_v);
MoveToChar(cur_h);
SetAttributes(0);
flush();
GettingInput = oldgetting;
}
#ifdef notdef
GotoBottom()
{
MoveToLine(OldvcV);
}
#endif
void
PastBottom()
{
MoveToLine(OldvcV);
(void) putraw('\r');
(void) putraw('\n');
ClearDisp();
flush();
}
static void
str_insert(d, dat, dlen, s, num)
Char *d;
int dat, dlen;
Char *s;
int num;
{
Char *a, *b;
if (num <= 0)
return;
if (num > dlen - dat)
num = dlen - dat;
#ifdef DEBUG_REFRESH
dprintf("str_insert() starting: %d at %d max %d, d == \"%s\"\n",
num, dat, dlen, short2str(d));
dprintf("s == \"%s\"n", short2str(s));
#endif
if (num > 0) {
b = d + dlen - 1;
a = b - num;
while (a >= &d[dat])
*b-- = *a--;
d[dlen] = '\0';
}
#ifdef DEBUG_REFRESH
dprintf("str_insert() after insert: %d at %d max %d, d == \"%s\"\n",
num, dat, dlen, short2str(d));
dprintf("s == \"%s\"n", short2str(s));
#endif
for (a = d + dat; (a < d + dlen) && (num > 0); num--)
*a++ = *s++;
#ifdef DEBUG_REFRESH
dprintf("str_insert() after copy: %d at %d max %d, d == \"%s\"\n",
num, dat, dlen, d, short2str(s));
dprintf("s == \"%s\"n", short2str(s));
#endif
}
static void
str_delete(d, dat, dlen, num)
Char *d;
int dat, dlen, num;
{
Char *a, *b;
if (num <= 0)
return;
if (dat + num >= dlen) {
d[dat] = '\0';
return;
}
#ifdef DEBUG_REFRESH
dprintf("str_delete() starting: %d at %d max %d, d == \"%s\"\n",
num, dat, dlen, short2str(d));
#endif
if (num > 0) {
b = d + dat;
a = b + num;
while (a < &d[dlen])
*b++ = *a++;
d[dlen] = '\0';
}
#ifdef DEBUG_REFRESH
dprintf("str_delete() after delete: %d at %d max %d, d == \"%s\"\n",
num, dat, dlen, short2str(d));
#endif
}
static void
str_cp(a, b, n)
Char *a, *b;
int n;
{
while (n-- && *b)
*a++ = *b++;
}
#define MIN_END_KEEP 4
static void
update_line(old, new, cur_line)
Char *old, *new;
int cur_line;
{
Char *o, *n, *p, c;
Char *ofd, *ols, *oe, *nfd, *nls, *ne;
Char *osb, *ose, *nsb, *nse;
int fx, sx;
for (o = old, n = new; *o && (*o == *n); o++, n++)
continue;
ofd = o;
nfd = n;
while (*o)
o++;
while (ofd < o) {
if (o[-1] != ' ')
break;
o--;
}
oe = o;
*oe = (Char) 0;
while (*n)
n++;
while (nfd < n) {
if (n[-1] != ' ')
break;
n--;
}
ne = n;
*ne = (Char) 0;
if (*ofd == '\0' && *nfd == '\0') {
#ifdef DEBUG_UPDATE
dprintf("no difference.\r\n");
#endif
return;
}
while ((o > ofd) && (n > nfd) && (*--o == *--n))
continue;
if (*o != *n) {
o++;
n++;
}
while (*o == CHAR_DBWIDTH) {
o++;
n++;
}
ols = o;
nls = n;
osb = ols;
nsb = nls;
ose = ols;
nse = nls;
if (*ofd) {
for (c = *ofd, n = nfd; n < nls; n++) {
if (c == *n) {
for (o = ofd, p = n; p < nls && o < ols && *o == *p; o++, p++)
continue;
if (((nse - nsb) < (p - n)) && (2 * (p - n) > n - nfd)) {
nsb = n;
nse = p;
osb = ofd;
ose = o;
}
}
}
}
if (*nfd) {
for (c = *nfd, o = ofd; o < ols; o++) {
if (c == *o) {
for (n = nfd, p = o; p < ols && n < nls && *p == *n; p++, n++)
continue;
if (((ose - osb) < (p - o)) && (2 * (p - o) > o - ofd)) {
nsb = nfd;
nse = n;
osb = o;
ose = p;
}
}
}
}
#ifdef notdef
if (ols < ose)
ols = ose;
if (nls < nse)
nls = nse;
#endif
if ((oe - ols) < MIN_END_KEEP) {
ols = oe;
nls = ne;
}
fx = (int) ((nsb - nfd) - (osb - ofd));
sx = (int) ((nls - nse) - (ols - ose));
if (!T_CanIns) {
if (fx > 0) {
osb = ols;
ose = ols;
nsb = nls;
nse = nls;
}
if (sx > 0) {
ols = oe;
nls = ne;
}
if ((ols - ofd) < (nls - nfd)) {
ols = oe;
nls = ne;
}
}
if (!T_CanDel) {
if (fx < 0) {
osb = ols;
ose = ols;
nsb = nls;
nse = nls;
}
if (sx < 0) {
ols = oe;
nls = ne;
}
if ((ols - ofd) > (nls - nfd)) {
ols = oe;
nls = ne;
}
}
if ((ose - osb) < MIN_END_KEEP) {
osb = ols;
ose = ols;
nsb = nls;
nse = nls;
}
fx = (int) ((nsb - nfd) - (osb - ofd));
sx = (int) ((nls - nse) - (ols - ose));
#ifdef DEBUG_UPDATE
dprintf("\n");
dprintf("ofd %d, osb %d, ose %d, ols %d, oe %d\n",
ofd - old, osb - old, ose - old, ols - old, oe - old);
dprintf("nfd %d, nsb %d, nse %d, nls %d, ne %d\n",
nfd - new, nsb - new, nse - new, nls - new, ne - new);
dprintf("xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n");
dprintf("xxx-xxx:\"01234567890123456789012345678901234567890\"\r\n");
dprintstr("old- oe", old, oe);
dprintstr("new- ne", new, ne);
dprintstr("old-ofd", old, ofd);
dprintstr("new-nfd", new, nfd);
dprintstr("ofd-osb", ofd, osb);
dprintstr("nfd-nsb", nfd, nsb);
dprintstr("osb-ose", osb, ose);
dprintstr("nsb-nse", nsb, nse);
dprintstr("ose-ols", ose, ols);
dprintstr("nse-nls", nse, nls);
dprintstr("ols- oe", ols, oe);
dprintstr("nls- ne", nls, ne);
#endif
MoveToLine(cur_line);
p = (ols != oe) ? oe : ose;
if ((nsb != nfd) && fx > 0 && ((p - old) + fx < TermH)) {
#ifdef DEBUG_UPDATE
dprintf("first diff insert at %d...\r\n", nfd - new);
#endif
MoveToChar(nfd - new);
if (nsb != ne) {
#ifdef DEBUG_UPDATE
dprintf("with stuff to keep at end\r\n");
#endif
if (fx > 0) {
#ifdef DEBUG_UPDATE
if (!T_CanIns)
dprintf(" ERROR: cannot insert in early first diff\n");
#endif
Insert_write(nfd, fx);
str_insert(old, (int) (ofd - old), TermH, nfd, fx);
}
so_write(nfd + fx, (nsb - nfd) - fx);
str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
}
else {
#ifdef DEBUG_UPDATE
dprintf("without anything to save\r\n");
#endif
so_write(nfd, (nsb - nfd));
str_cp(ofd, nfd, (int) (nsb - nfd));
return;
}
}
else if (fx < 0) {
#ifdef DEBUG_UPDATE
dprintf("first diff delete at %d...\r\n", ofd - old);
#endif
MoveToChar(ofd - old);
if (osb != oe) {
#ifdef DEBUG_UPDATE
dprintf("with stuff to save at end\r\n");
#endif
if (fx < 0) {
#ifdef DEBUG_UPDATE
if (!T_CanDel)
dprintf(" ERROR: cannot delete in first diff\n");
#endif
DeleteChars(-fx);
str_delete(old, (int) (ofd - old), TermH, -fx);
}
so_write(nfd, (nsb - nfd));
str_cp(ofd, nfd, (int) (nsb - nfd));
}
else {
#ifdef DEBUG_UPDATE
dprintf("but with nothing left to save\r\n");
#endif
so_write(nfd, (nsb - nfd));
#ifdef DEBUG_REFRESH
dprintf("cleareol %d\n", (oe - old) - (ne - new));
#endif
#ifndef WINNT_NATIVE
ClearEOL((oe - old) - (ne - new));
#else
ClearEOL(TermH - CursorH);
#endif
return;
}
}
else
fx = 0;
if (sx < 0) {
#ifdef DEBUG_UPDATE
dprintf("second diff delete at %d...\r\n", (ose - old) + fx);
#endif
MoveToChar((ose - old) + fx);
if (ols != oe) {
#ifdef DEBUG_UPDATE
dprintf("with stuff to save at end\r\n");
#endif
if (sx < 0) {
#ifdef DEBUG_UPDATE
if (!T_CanDel)
dprintf(" ERROR: cannot delete in second diff\n");
#endif
DeleteChars(-sx);
}
so_write(nse, (nls - nse));
}
else {
int olen = (int) (oe - old + fx);
if (olen > TermH)
olen = TermH;
#ifdef DEBUG_UPDATE
dprintf("but with nothing left to save\r\n");
#endif
so_write(nse, (nls - nse));
#ifdef DEBUG_REFRESH
dprintf("cleareol %d\n", olen - (ne - new));
#endif
#ifndef WINNT_NATIVE
ClearEOL(olen - (ne - new));
#else
ClearEOL(TermH - CursorH);
#endif
}
}
if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) {
#ifdef DEBUG_UPDATE
dprintf("late first diff insert at %d...\r\n", nfd - new);
#endif
MoveToChar(nfd - new);
if (nsb != ne) {
#ifdef DEBUG_UPDATE
dprintf("with stuff to keep at end\r\n");
#endif
fx = (int) ((nsb - nfd) - (osb - ofd));
if (fx > 0) {
#ifdef DEBUG_UPDATE
if (!T_CanIns)
dprintf(" ERROR: cannot insert in late first diff\n");
#endif
Insert_write(nfd, fx);
str_insert(old, (int) (ofd - old), TermH, nfd, fx);
}
so_write(nfd + fx, (nsb - nfd) - fx);
str_cp(ofd + fx, nfd + fx, (int) ((nsb - nfd) - fx));
}
else {
#ifdef DEBUG_UPDATE
dprintf("without anything to save\r\n");
#endif
so_write(nfd, (nsb - nfd));
str_cp(ofd, nfd, (int) (nsb - nfd));
}
}
if (sx >= 0) {
#ifdef DEBUG_UPDATE
dprintf("second diff insert at %d...\r\n", nse - new);
#endif
MoveToChar(nse - new);
if (ols != oe) {
#ifdef DEBUG_UPDATE
dprintf("with stuff to keep at end\r\n");
#endif
if (sx > 0) {
#ifdef DEBUG_UPDATE
if (!T_CanIns)
dprintf(" ERROR: cannot insert in second diff\n");
#endif
Insert_write(nse, sx);
}
so_write(nse + sx, (nls - nse) - sx);
}
else {
#ifdef DEBUG_UPDATE
dprintf("without anything to save\r\n");
#endif
so_write(nse, (nls - nse));
}
}
#ifdef DEBUG_UPDATE
dprintf("done.\r\n");
#endif
}
static void
cpy_pad_spaces(dst, src, width)
Char *dst, *src;
int width;
{
int i;
for (i = 0; i < width; i++) {
if (*src == (Char) 0)
break;
*dst++ = *src++;
}
while (i < width) {
*dst++ = ' ';
i++;
}
*dst = (Char) 0;
}
void
RefCursor()
{
Char *cp;
NLSChar c;
int l, w, h, th, v;
h = 0;
v = 0;
th = TermH;
for (cp = PromptBuf; *cp; ) {
if (*cp & LITERAL) {
cp++;
continue;
}
l = NLSFrom(cp, NLSZEROT, &c);
w = NLSClassify(c, cp == PromptBuf);
cp += l;
switch(w) {
case NLSCLASS_NL:
h = 0;
v++;
break;
case NLSCLASS_TAB:
while (++h & 07)
;
break;
case NLSCLASS_CTRL:
h += 2;
break;
case NLSCLASS_ILLEGAL:
h += 4;
break;
case NLSCLASS_ILLEGAL2:
case NLSCLASS_ILLEGAL3:
case NLSCLASS_ILLEGAL4:
h += 3 + 2 * NLSCLASS_ILLEGAL_SIZE(w);
break;
default:
h += w;
}
if (h >= th) {
h -= th;
v++;
}
}
for (cp = InputBuf; cp < Cursor;) {
l = NLSFrom(cp, Cursor - cp, &c);
w = NLSClassify(c, cp == InputBuf);
cp += l;
switch(w) {
case NLSCLASS_NL:
h = 0;
v++;
break;
case NLSCLASS_TAB:
while (++h & 07)
;
break;
case NLSCLASS_CTRL:
h += 2;
break;
case NLSCLASS_ILLEGAL:
h += 4;
break;
case NLSCLASS_ILLEGAL2:
case NLSCLASS_ILLEGAL3:
case NLSCLASS_ILLEGAL4:
h += 3 + 2 * NLSCLASS_ILLEGAL_SIZE(w);
break;
default:
h += w;
}
if (h >= th) {
h -= th;
v++;
}
}
MoveToLine(v);
MoveToChar(h);
flush();
}
#ifndef WINTT_NATIVE
static void
PutPlusOne(c, width)
Char c;
int width;
{
while (width > 1 && CursorH + width > TermH)
PutPlusOne(' ', 1);
if ((c & LITERAL) != 0) {
Char *d;
for (d = litptr + (c & ~LITERAL) * LIT_FACTOR; *d; d++)
(void) putwraw(*d);
} else {
(void) putwraw(c);
}
Display[CursorV][CursorH++] = (Char) c;
while (--width > 0)
Display[CursorV][CursorH++] = CHAR_DBWIDTH;
if (CursorH >= TermH) {
CursorH = 0;
CursorV++;
OldvcV++;
if (T_Margin & MARGIN_AUTO) {
if (T_Margin & MARGIN_MAGIC) {
(void) putraw(' ');
(void) putraw('\b');
}
}
else {
(void) putraw('\r');
(void) putraw('\n');
}
}
}
#endif
void
RefPlusOne(int l)
{
Char *cp;
int w;
NLSChar c;
if (Cursor != LastChar) {
Refresh();
return;
}
if (rprompt_h != 0 && (TermH - CursorH - rprompt_h < 3)) {
Refresh();
return;
}
cp = Cursor - l;
NLSFrom(cp, (size_t)l, &c);
w = NLSClassify(c, cp == InputBuf);
switch(w) {
case NLSCLASS_CTRL:
PutPlusOne('^', 1);
if (c == CTL_ESC('\177')) {
PutPlusOne('?', 1);
break;
}
#ifdef IS_ASCII
PutPlusOne((c | 0100), 1);
#else
PutPlusOne(_toebcdic[_toascii[c]|0100], 1);
#endif
break;
case NLSCLASS_ILLEGAL:
PutPlusOne('\\', 1);
PutPlusOne(((c >> 6) & 7) + '0', 1);
PutPlusOne(((c >> 3) & 7) + '0', 1);
PutPlusOne((c & 7) + '0', 1);
break;
case 1:
if (l > 1)
PutPlusOne(MakeLiteral(cp, l, 0), 1);
else
PutPlusOne(*cp, 1);
break;
default:
Refresh();
return;
}
flush();
}
void
ClearDisp()
{
int i;
CursorV = 0;
CursorH = 0;
for (i = 0; i < TermV; i++)
(void) memset(Display[i], 0, TermH * sizeof(Display[0][0]));
OldvcV = 0;
litlen = 0;
}
void
ClearLines()
{
int i;
if (T_CanCEOL) {
for (i = OldvcV; i >= 0; i--) {
MoveToLine(i);
MoveToChar(0);
ClearEOL(TermH);
}
}
else {
MoveToLine(OldvcV);
(void) putraw('\r');
(void) putraw('\n');
}
}