summaryrefslogtreecommitdiff
path: root/display.c
diff options
context:
space:
mode:
Diffstat (limited to 'display.c')
-rw-r--r--display.c1937
1 files changed, 1937 insertions, 0 deletions
diff --git a/display.c b/display.c
new file mode 100644
index 0000000..e4cdb1c
--- /dev/null
+++ b/display.c
@@ -0,0 +1,1937 @@
+/* Copyright (c) 1993
+ * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
+ * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
+ * Copyright (c) 1987 Oliver Laumann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING); if not, write to the
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ ****************************************************************
+ */
+
+#include "rcs.h"
+RCS_ID("$Id: display.c,v 1.16 1994/05/31 12:31:50 mlschroe Exp $ FAU")
+
+
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "config.h"
+#include "screen.h"
+#include "extern.h"
+
+static void CountChars __P((int));
+static void PutChar __P((int));
+static int BlankResize __P((int, int));
+
+
+extern struct win *windows;
+
+extern int use_hardstatus;
+extern int MsgMinWait;
+extern int Z0width, Z1width;
+extern char *blank, *null;
+extern struct mline mline_blank, mline_null;
+extern struct mchar mchar_null, mchar_blank, mchar_so;
+
+/*
+ * tputs needs this to calculate the padding
+ */
+#ifndef NEED_OSPEED
+extern
+#endif /* NEED_OSPEED */
+short ospeed;
+
+
+struct display *display, *displays;
+
+#ifndef MULTI
+struct display TheDisplay;
+#endif
+
+/*
+ * The default values
+ */
+int defobuflimit = OBUF_MAX;
+#ifdef AUTO_NUKE
+int defautonuke = 0;
+#endif
+
+/*
+ * Default layer management
+ */
+
+void
+DefProcess(bufp, lenp)
+char **bufp;
+int *lenp;
+{
+ *bufp += *lenp;
+ *lenp = 0;
+}
+
+void
+DefRedisplayLine(y, xs, xe, isblank)
+int y, xs, xe, isblank;
+{
+ if (isblank == 0 && y >= 0)
+ DefClearLine(y, xs, xe);
+}
+
+void
+DefClearLine(y, xs, xe)
+int y, xs, xe;
+{
+ DisplayLine(&mline_null, &mline_blank, y, xs, xe);
+}
+
+/*ARGSUSED*/
+int
+DefRewrite(y, xs, xe, doit)
+int y, xs, xe, doit;
+{
+ return EXPENSIVE;
+}
+
+void
+DefSetCursor()
+{
+ GotoPos(0, 0);
+}
+
+/*ARGSUSED*/
+int
+DefResize(wi, he)
+int wi, he;
+{
+ return -1;
+}
+
+void
+DefRestore()
+{
+ InsertMode(0);
+ ChangeScrollRegion(0, D_height - 1);
+ KeypadMode(0);
+ CursorkeysMode(0);
+ CursorVisibility(0);
+ SetRendition(&mchar_null);
+ SetFlow(FLOW_NOW);
+}
+
+/*
+ * Blank layer management
+ */
+
+struct LayFuncs BlankLf =
+{
+ DefProcess,
+ 0,
+ DefRedisplayLine,
+ DefClearLine,
+ DefRewrite,
+ DefSetCursor,
+ BlankResize,
+ DefRestore
+};
+
+struct layer BlankLayer =
+{
+ 0,
+ 0,
+ &BlankLf,
+ 0
+};
+
+/*ARGSUSED*/
+static int
+BlankResize(wi, he)
+int wi, he;
+{
+ return 0;
+}
+
+
+/*
+ * Generate new display
+ */
+
+struct display *
+MakeDisplay(uname, utty, term, fd, pid, Mode)
+char *uname, *utty, *term;
+int fd, pid;
+struct mode *Mode;
+{
+ struct user **u;
+
+ if (!*(u = FindUserPtr(uname)) && UserAdd(uname, (char *)0, u))
+ return 0; /* could not find or add user */
+
+#ifdef MULTI
+ if ((display = (struct display *)malloc(sizeof(*display))) == 0)
+ return 0;
+ bzero((char *) display, sizeof(*display));
+#else
+ if (displays)
+ return 0;
+ display = &TheDisplay;
+#endif
+ display->d_next = displays;
+ displays = display;
+ D_flow = 1;
+ D_nonblock = 0;
+ D_userfd = fd;
+ D_OldMode = *Mode;
+ Resize_obuf(); /* Allocate memory for buffer */
+ D_obufmax = defobuflimit;
+#ifdef AUTO_NUKE
+ D_auto_nuke = defautonuke;
+#endif
+ D_obufp = D_obuf;
+ D_printfd = -1;
+ D_userpid = pid;
+#if defined(POSIX) || defined(TERMIO)
+# ifdef POSIX
+ switch (cfgetospeed(&D_OldMode.tio))
+# else
+ switch (D_OldMode.tio.c_cflag & CBAUD)
+# endif
+ {
+#ifdef B0
+ case B0: D_dospeed = 0; break;
+#endif
+#ifdef B50
+ case B50: D_dospeed = 1; break;
+#endif
+#ifdef B75
+ case B75: D_dospeed = 2; break;
+#endif
+#ifdef B110
+ case B110: D_dospeed = 3; break;
+#endif
+#ifdef B134
+ case B134: D_dospeed = 4; break;
+#endif
+#ifdef B150
+ case B150: D_dospeed = 5; break;
+#endif
+#ifdef B200
+ case B200: D_dospeed = 6; break;
+#endif
+#ifdef B300
+ case B300: D_dospeed = 7; break;
+#endif
+#ifdef B600
+ case B600: D_dospeed = 8; break;
+#endif
+#ifdef B1200
+ case B1200: D_dospeed = 9; break;
+#endif
+#ifdef B1800
+ case B1800: D_dospeed = 10; break;
+#endif
+#ifdef B2400
+ case B2400: D_dospeed = 11; break;
+#endif
+#ifdef B4800
+ case B4800: D_dospeed = 12; break;
+#endif
+#ifdef B9600
+ case B9600: D_dospeed = 13; break;
+#endif
+#ifdef EXTA
+ case EXTA: D_dospeed = 14; break;
+#endif
+#ifdef EXTB
+ case EXTB: D_dospeed = 15; break;
+#endif
+#ifdef B57600
+ case B57600: D_dospeed = 16; break;
+#endif
+#ifdef B115200
+ case B115200: D_dospeed = 17; break;
+#endif
+ default: ;
+ }
+#else /* POSIX || TERMIO */
+ D_dospeed = (short) D_OldMode.m_ttyb.sg_ospeed;
+#endif /* POSIX || TERMIO */
+ debug1("New displays ospeed = %d\n", D_dospeed);
+ strcpy(D_usertty, utty);
+ strcpy(D_termname, term);
+
+ D_user = *u;
+ D_lay = &BlankLayer;
+ D_layfn = BlankLayer.l_layfn;
+ return display;
+}
+
+void
+FreeDisplay()
+{
+ struct win *p;
+#ifdef MULTI
+ struct display *d, **dp;
+#endif
+
+ FreeTransTable();
+ freetty();
+ if (D_tentry)
+ free(D_tentry);
+ D_tentry = 0;
+ D_tcinited = 0;
+#ifdef MULTI
+ for (dp = &displays; (d = *dp) ; dp = &d->d_next)
+ if (d == display)
+ break;
+ ASSERT(d);
+ if (D_status_lastmsg)
+ free(D_status_lastmsg);
+ if (D_obuf)
+ free(D_obuf);
+ *dp = display->d_next;
+ free((char *)display);
+#else /* MULTI */
+ ASSERT(display == displays);
+ ASSERT(display == &TheDisplay);
+ displays = 0;
+#endif /* MULTI */
+ for (p = windows; p; p = p->w_next)
+ {
+ if (p->w_display == display)
+ p->w_display = 0;
+ if (p->w_pdisplay == display)
+ p->w_pdisplay = 0;
+ }
+ display = 0;
+}
+
+/*
+ * if the adaptflag is on, we keep the size of this display, else
+ * we may try to restore our old window sizes.
+ */
+void
+InitTerm(adapt)
+int adapt;
+{
+ ASSERT(display);
+ ASSERT(D_tcinited);
+ D_top = D_bot = -1;
+ PutStr(D_TI);
+ PutStr(D_IS);
+ /* Check for toggle */
+ if (D_IM && strcmp(D_IM, D_EI))
+ PutStr(D_EI);
+ D_insert = 0;
+ /* Check for toggle */
+#ifdef MAPKEYS
+ PutStr(D_KS);
+ PutStr(D_CCS);
+#else
+ if (D_KS && strcmp(D_KS, D_KE))
+ PutStr(D_KE);
+ if (D_CCS && strcmp(D_CCS, D_CCE))
+ PutStr(D_CCE);
+#endif
+ D_keypad = 0;
+ D_cursorkeys = 0;
+ PutStr(D_ME);
+ PutStr(D_EA);
+ PutStr(D_CE0);
+ D_rend = mchar_null;
+ D_atyp = 0;
+ if (adapt == 0)
+ ResizeDisplay(D_defwidth, D_defheight);
+ ChangeScrollRegion(0, D_height - 1);
+ D_x = D_y = 0;
+ Flush();
+ ClearDisplay();
+ debug1("we %swant to adapt all our windows to the display\n",
+ (adapt) ? "" : "don't ");
+ /* In case the size was changed by a init sequence */
+ CheckScreenSize((adapt) ? 2 : 0);
+}
+
+void
+FinitTerm()
+{
+ ASSERT(display);
+ if (D_tcinited)
+ {
+ ResizeDisplay(D_defwidth, D_defheight);
+ DefRestore();
+ SetRendition(&mchar_null);
+#ifdef MAPKEYS
+ PutStr(D_KE);
+ PutStr(D_CCE);
+#endif
+ if (D_hstatus)
+ PutStr(D_DS);
+ D_x = D_y = -1;
+ GotoPos(0, D_height - 1);
+ AddChar('\n');
+ PutStr(D_TE);
+ }
+ Flush();
+}
+
+
+void
+INSERTCHAR(c)
+int c;
+{
+ ASSERT(display);
+ if (!D_insert && D_x < D_width - 1)
+ {
+ if (D_IC || D_CIC)
+ {
+ if (D_IC)
+ PutStr(D_IC);
+ else
+ CPutStr(D_CIC, 1);
+ RAW_PUTCHAR(c);
+ return;
+ }
+ InsertMode(1);
+ if (!D_insert)
+ {
+ RefreshLine(D_y, D_x, D_width-1, 0);
+ return;
+ }
+ }
+ RAW_PUTCHAR(c);
+}
+
+void
+PUTCHAR(c)
+int c;
+{
+ ASSERT(display);
+ if (D_insert && D_x < D_width - 1)
+ InsertMode(0);
+ RAW_PUTCHAR(c);
+}
+
+void
+PUTCHARLP(c)
+int c;
+{
+ if (D_x < D_width - 1)
+ {
+ if (D_insert)
+ InsertMode(0);
+ RAW_PUTCHAR(c);
+ return;
+ }
+ if (D_CLP || D_y != D_bot)
+ {
+ RAW_PUTCHAR(c);
+ return;
+ }
+ D_lp_missing = 1;
+ D_rend.image = c;
+ D_lpchar = D_rend;
+}
+
+/*
+ * RAW_PUTCHAR() is for all text that will be displayed.
+ * NOTE: charset Nr. 0 has a conversion table, but c1, c2, ... don't.
+ */
+
+void
+RAW_PUTCHAR(c)
+int c;
+{
+ ASSERT(display);
+#ifdef KANJI
+ if (D_rend.font == KANJI)
+ {
+ int t = c;
+ if (D_mbcs == 0)
+ {
+ D_mbcs = c;
+ return;
+ }
+ if (D_x == D_width - 1)
+ D_x += D_AM ? 1 : -1;
+ c = D_mbcs;
+ c &= 0x7f;
+ t &= 0x7f;
+ if (D_kanji == EUC)
+ {
+ c |= 0x80;
+ t |= 0x80;
+ }
+ else if (D_kanji == SJIS)
+ {
+ t += (c & 1) ? ((t <= 0x5f) ? 0x1f : 0x20) : 0x7e;
+ c = (c - 0x21) / 2 + ((c < 0x5e) ? 0x81 : 0xc1);
+ }
+ D_mbcs = t;
+ }
+ else if (D_rend.font == KANA)
+ {
+ if (D_kanji == EUC)
+ {
+ AddChar(0x8e); /* SS2 */
+ c |= 0x80;
+ }
+ else if (D_kanji == SJIS)
+ c |= 0x80;
+ }
+ kanjiloop:
+#endif
+ if (D_xtable && D_xtable[(int)(unsigned char)D_rend.font] && D_xtable[(int)(unsigned char)D_rend.font][(int)(unsigned char)c])
+ AddStr(D_xtable[(int)(unsigned char)D_rend.font][(int)(unsigned char)c]);
+ else
+ AddChar(D_rend.font != '0' ? c : D_c0_tab[(int)(unsigned char)c]);
+
+ if (++D_x >= D_width)
+ {
+ if (D_AM == 0)
+ D_x = D_width - 1;
+ else if (!D_CLP || D_x > D_width)
+ {
+ D_x -= D_width;
+ if (D_y < D_height-1 && D_y != D_bot)
+ D_y++;
+ }
+ }
+#ifdef KANJI
+ if (D_mbcs)
+ {
+ c = D_mbcs;
+ D_mbcs = 0;
+ goto kanjiloop;
+ }
+#endif
+}
+
+static void
+PutChar(c)
+int c;
+{
+ /* this PutChar for ESC-sequences only (AddChar is a macro) */
+ AddChar(c);
+}
+
+void
+PutStr(s)
+char *s;
+{
+ if (display && s)
+ {
+ ospeed = D_dospeed;
+ tputs(s, 1, PutChar);
+ }
+}
+
+void
+CPutStr(s, c)
+char *s;
+int c;
+{
+ if (display && s)
+ {
+ ospeed = D_dospeed;
+ tputs(tgoto(s, 0, c), 1, PutChar);
+ }
+}
+
+
+/* Insert mode is a toggle on some terminals, so we need this hack:
+ */
+void
+InsertMode(on)
+int on;
+{
+ if (display && on != D_insert && D_IM)
+ {
+ D_insert = on;
+ if (D_insert)
+ PutStr(D_IM);
+ else
+ PutStr(D_EI);
+ }
+}
+
+/* ...and maybe keypad application mode is a toggle, too:
+ */
+void
+KeypadMode(on)
+int on;
+{
+#ifdef MAPKEYS
+ if (display)
+ D_keypad = on;
+#else
+ if (display && D_keypad != on && D_KS)
+ {
+ D_keypad = on;
+ if (D_keypad)
+ PutStr(D_KS);
+ else
+ PutStr(D_KE);
+ }
+#endif
+}
+
+void
+CursorkeysMode(on)
+int on;
+{
+#ifdef MAPKEYS
+ if (display)
+ D_cursorkeys = on;
+#else
+ if (display && D_cursorkeys != on && D_CCS)
+ {
+ D_cursorkeys = on;
+ if (D_cursorkeys)
+ PutStr(D_CCS);
+ else
+ PutStr(D_CCE);
+ }
+#endif
+}
+
+void
+ReverseVideo(on)
+int on;
+{
+ if (display && D_revvid != on && D_CVR)
+ {
+ D_revvid = on;
+ if (D_revvid)
+ PutStr(D_CVR);
+ else
+ PutStr(D_CVN);
+ }
+}
+
+void
+CursorVisibility(v)
+int v;
+{
+ if (display && D_curvis != v)
+ {
+ if (D_curvis)
+ PutStr(D_VE); /* do this always, just to be safe */
+ D_curvis = 0;
+ if (v == -1 && D_VI)
+ PutStr(D_VI);
+ else if (v == 1 && D_VS)
+ PutStr(D_VS);
+ else
+ return;
+ D_curvis = v;
+ }
+}
+
+static int StrCost;
+
+/* ARGSUSED */
+static void
+CountChars(c)
+int c;
+{
+ StrCost++;
+}
+
+int
+CalcCost(s)
+register char *s;
+{
+ ASSERT(display);
+ if (!s)
+ return EXPENSIVE;
+ StrCost = 0;
+ ospeed = D_dospeed;
+ tputs(s, 1, CountChars);
+ return StrCost;
+}
+
+void
+GotoPos(x2, y2)
+int x2, y2;
+{
+ register int dy, dx, x1, y1;
+ register int costx, costy;
+ register int m;
+ register char *s;
+ int CMcost;
+ enum move_t xm = M_NONE, ym = M_NONE;
+
+ if (!display)
+ return;
+
+ x1 = D_x;
+ y1 = D_y;
+
+ if (x1 == D_width)
+ if (D_CLP && D_AM)
+ x1 = -1; /* don't know how the terminal treats this */
+ else
+ x1--;
+ if (x2 == D_width)
+ x2--;
+ dx = x2 - x1;
+ dy = y2 - y1;
+ if (dy == 0 && dx == 0)
+ return;
+ if (!D_MS) /* Safe to move ? */
+ SetRendition(&mchar_null);
+ if (y1 < 0 /* don't know the y position */
+ || (y2 > D_bot && y1 <= D_bot) /* have to cross border */
+ || (y2 < D_top && y1 >= D_top)) /* of scrollregion ? */
+ {
+ DoCM:
+ if (D_HO && !x2 && !y2)
+ PutStr(D_HO);
+ else
+ PutStr(tgoto(D_CM, x2, y2));
+ D_x = x2;
+ D_y = y2;
+ return;
+ }
+ /* Calculate CMcost */
+ if (D_HO && !x2 && !y2)
+ s = D_HO;
+ else
+ s = tgoto(D_CM, x2, y2);
+ CMcost = CalcCost(s);
+
+ /* Calculate the cost to move the cursor to the right x position */
+ costx = EXPENSIVE;
+ if (x1 >= 0) /* relativ x positioning only if we know where we are */
+ {
+ if (dx > 0)
+ {
+ if (D_CRI && (dx > 1 || !D_ND))
+ {
+ costx = CalcCost(tgoto(D_CRI, 0, dx));
+ xm = M_CRI;
+ }
+ if ((m = D_NDcost * dx) < costx)
+ {
+ costx = m;
+ xm = M_RI;
+ }
+ /* Speedup: dx <= Rewrite() */
+ if (dx < costx && (m = Rewrite(y1, x1, x2, 0)) < costx)
+ {
+ costx = m;
+ xm = M_RW;
+ }
+ }
+ else if (dx < 0)
+ {
+ if (D_CLE && (dx < -1 || !D_BC))
+ {
+ costx = CalcCost(tgoto(D_CLE, 0, -dx));
+ xm = M_CLE;
+ }
+ if ((m = -dx * D_LEcost) < costx)
+ {
+ costx = m;
+ xm = M_LE;
+ }
+ }
+ else
+ costx = 0;
+ }
+ /* Speedup: Rewrite() >= x2 */
+ if (x2 + D_CRcost < costx && (m = (x2 ? Rewrite(y1, 0, x2, 0) : 0) + D_CRcost) < costx)
+ {
+ costx = m;
+ xm = M_CR;
+ }
+
+ /* Check if it is already cheaper to do CM */
+ if (costx >= CMcost)
+ goto DoCM;
+
+ /* Calculate the cost to move the cursor to the right y position */
+ costy = EXPENSIVE;
+ if (dy > 0)
+ {
+ if (D_CDO && dy > 1) /* DO & NL are always != 0 */
+ {
+ costy = CalcCost(tgoto(D_CDO, 0, dy));
+ ym = M_CDO;
+ }
+ if ((m = dy * ((x2 == 0) ? D_NLcost : D_DOcost)) < costy)
+ {
+ costy = m;
+ ym = M_DO;
+ }
+ }
+ else if (dy < 0)
+ {
+ if (D_CUP && (dy < -1 || !D_UP))
+ {
+ costy = CalcCost(tgoto(D_CUP, 0, -dy));
+ ym = M_CUP;
+ }
+ if ((m = -dy * D_UPcost) < costy)
+ {
+ costy = m;
+ ym = M_UP;
+ }
+ }
+ else
+ costy = 0;
+
+ /* Finally check if it is cheaper to do CM */
+ if (costx + costy >= CMcost)
+ goto DoCM;
+
+ switch (xm)
+ {
+ case M_LE:
+ while (dx++ < 0)
+ PutStr(D_BC);
+ break;
+ case M_CLE:
+ CPutStr(D_CLE, -dx);
+ break;
+ case M_RI:
+ while (dx-- > 0)
+ PutStr(D_ND);
+ break;
+ case M_CRI:
+ CPutStr(D_CRI, dx);
+ break;
+ case M_CR:
+ PutStr(D_CR);
+ D_x = 0;
+ x1 = 0;
+ /* FALLTHROUGH */
+ case M_RW:
+ if (x1 < x2)
+ (void) Rewrite(y1, x1, x2, 1);
+ break;
+ default:
+ break;
+ }
+
+ switch (ym)
+ {
+ case M_UP:
+ while (dy++ < 0)
+ PutStr(D_UP);
+ break;
+ case M_CUP:
+ CPutStr(D_CUP, -dy);
+ break;
+ case M_DO:
+ s = (x2 == 0) ? D_NL : D_DO;
+ while (dy-- > 0)
+ PutStr(s);
+ break;
+ case M_CDO:
+ CPutStr(D_CDO, dy);
+ break;
+ default:
+ break;
+ }
+ D_x = x2;
+ D_y = y2;
+}
+
+void
+ClearDisplay()
+{
+ ASSERT(display);
+ Clear(0, 0, 0, D_width - 1, D_width - 1, D_height - 1, 0);
+}
+
+void
+Clear(x1, y1, xs, xe, x2, y2, uselayfn)
+int x1, y1, xs, xe, x2, y2, uselayfn;
+{
+ int y, xxe;
+
+ ASSERT(display);
+ if (x1 == D_width)
+ x1--;
+ if (x2 == D_width)
+ x2--;
+ if (D_UT) /* Safe to erase ? */
+ SetRendition(&mchar_null);
+ if (D_lp_missing && y1 <= D_bot && xe >= D_width - 1)
+ {
+ if (y2 > D_bot || (y2 == D_bot && x2 >= D_width - 1))
+ D_lp_missing = 0;
+ }
+ if (x2 == D_width - 1 && (xs == 0 || y1 == y2) && xe == D_width - 1 && y2 == D_height - 1)
+ {
+#ifdef AUTO_NUKE
+ if (x1 == 0 && y1 == 0 && D_auto_nuke)
+ NukePending();
+#endif
+ if (x1 == 0 && y1 == 0 && D_CL)
+ {
+ PutStr(D_CL);
+ D_y = D_x = 0;
+ return;
+ }
+ /*
+ * Workaround a hp700/22 terminal bug. Do not use CD where CE
+ * is also appropriate.
+ */
+ if (D_CD && (y1 < y2 || !D_CE))
+ {
+ GotoPos(x1, y1);
+ PutStr(D_CD);
+ return;
+ }
+ }
+ if (x1 == 0 && xs == 0 && (xe == D_width - 1 || y1 == y2) && y1 == 0 && D_CCD)
+ {
+ GotoPos(x1, y1);
+ PutStr(D_CCD);
+ return;
+ }
+ xxe = xe;
+ for (y = y1; y <= y2; y++, x1 = xs)
+ {
+ if (y == y2)
+ xxe = x2;
+ if (x1 == 0 && D_CB && (xxe != D_width - 1 || (D_x == xxe && D_y == y)))
+ {
+ GotoPos(xxe, y);
+ PutStr(D_CB);
+ continue;
+ }
+ if (xxe == D_width - 1 && D_CE)
+ {
+ GotoPos(x1, y);
+ PutStr(D_CE);
+ continue;
+ }
+ if (uselayfn)
+ ClearLine(y, x1, xxe);
+ else
+ DisplayLine(&mline_null, &mline_blank, y, x1, xxe);
+ }
+}
+
+
+/*
+ * if cur_only > 0, we only redisplay current line, as a full refresh is
+ * too expensive over a low baud line.
+ */
+void
+Redisplay(cur_only)
+int cur_only;
+{
+ register int i, stop;
+
+ ASSERT(display);
+ DefRestore();
+ ClearDisplay();
+ stop = D_height;
+ i = 0;
+ if (cur_only > 0 && D_fore)
+ {
+ i = stop = D_fore->w_y;
+ stop++;
+ }
+ else
+ RedisplayLine(-1, 0, D_width - 1, 1);
+ for (; i < stop; i++)
+ RedisplayLine(i, 0, D_width - 1, 1);
+ RefreshStatus();
+ Restore();
+ SetCursor();
+}
+
+
+void
+ScrollH(y, xs, xe, n, oml)
+int y, xs, xe, n;
+struct mline *oml;
+{
+ int i;
+
+ if (n == 0)
+ return;
+ if (xe != D_width - 1)
+ {
+ RefreshLine(y, xs, xe, 0);
+ /* UpdateLine(oml, y, xs, xe); */
+ return;
+ }
+ GotoPos(xs, y);
+ if (D_UT)
+ SetRendition(&mchar_null);
+ if (n > 0)
+ {
+ if (D_CDC && !(n == 1 && D_DC))
+ CPutStr(D_CDC, n);
+ else if (D_DC)
+ {
+ for (i = n; i--; )
+ PutStr(D_DC);
+ }
+ else
+ {
+ RefreshLine(y, xs, xe, 0);
+ /* UpdateLine(oml, y, xs, xe); */
+ return;
+ }
+ }
+ else
+ {
+ if (!D_insert)
+ {
+ if (D_CIC && !(n == -1 && D_IC))
+ CPutStr(D_CIC, -n);
+ else if (D_IC)
+ {
+ for (i = -n; i--; )
+ PutStr(D_IC);
+ }
+ else if (D_IM)
+ {
+ InsertMode(1);
+ for (i = -n; i--; )
+ INSERTCHAR(' ');
+ }
+ else
+ {
+ /* UpdateLine(oml, y, xs, xe); */
+ RefreshLine(y, xs, xe, 0);
+ return;
+ }
+ }
+ else
+ {
+ for (i = -n; i--; )
+ INSERTCHAR(' ');
+ }
+ }
+ if (D_lp_missing && y == D_bot)
+ {
+ if (n > 0)
+ FixLP(D_width - 1 - n, y);
+ D_lp_missing = 0;
+ }
+}
+
+void
+ScrollV(xs, ys, xe, ye, n)
+int xs, ys, xe, ye, n;
+{
+ int i;
+ int up;
+ int oldtop, oldbot;
+ int alok, dlok, aldlfaster;
+ int missy = 0;
+
+ ASSERT(display);
+ if (n == 0)
+ return;
+ if (n >= ye - ys + 1 || -n >= ye - ys + 1)
+ {
+ Clear(xs, ys, xs, xe, xe, ye, 0);
+ return;
+ }
+ if (xs != 0 || xe != D_width - 1)
+ {
+ Redisplay(0);
+ return;
+ }
+
+ if (D_lp_missing)
+ {
+ if (D_bot > ye || D_bot < ys)
+ missy = D_bot;
+ else
+ {
+ missy = D_bot - n;
+ if (missy > ye || missy < ys)
+ D_lp_missing = 0;
+ }
+ }
+
+ up = 1;
+ if (n < 0)
+ {
+ up = 0;
+ n = -n;
+ }
+ if (n >= ye - ys + 1)
+ n = ye - ys + 1;
+
+ oldtop = D_top;
+ oldbot = D_bot;
+ if (D_bot != ye)
+ ChangeScrollRegion(ys, ye);
+ alok = (D_AL || D_CAL || (ye == D_bot && up));
+ dlok = (D_DL || D_CDL || (ye == D_bot && !up));
+ if (D_top != ys && !(alok && dlok))
+ ChangeScrollRegion(ys, ye);
+
+ if (D_lp_missing &&
+ (oldbot != D_bot ||
+ (oldbot == D_bot && up && D_top == ys && D_bot == ye)))
+ {
+ FixLP(D_width - 1, oldbot);
+ if (oldbot == D_bot) /* have scrolled */
+ {
+ if (--n == 0)
+ {
+ ChangeScrollRegion(oldtop, oldbot);
+ return;
+ }
+ }
+ }
+
+ aldlfaster = (n > 1 && ye == D_bot && ((up && D_CDL) || (!up && D_CAL)));
+
+ if (D_UT)
+ SetRendition(&mchar_null);
+ if ((up || D_SR) && D_top == ys && D_bot == ye && !aldlfaster)
+ {
+ if (up)
+ {
+ GotoPos(0, ye);
+ while (n-- > 0)
+ PutStr(D_NL); /* was SF, I think NL is faster */
+ }
+ else
+ {
+ GotoPos(0, ys);
+ while (n-- > 0)
+ PutStr(D_SR);
+ }
+ }
+ else if (alok && dlok)
+ {
+ if (up || ye != D_bot)
+ {
+ GotoPos(0, up ? ys : ye+1-n);
+ if (D_CDL && !(n == 1 && D_DL))
+ CPutStr(D_CDL, n);
+ else
+ for(i = n; i--; )
+ PutStr(D_DL);
+ }
+ if (!up || ye != D_bot)
+ {
+ GotoPos(0, up ? ye+1-n : ys);
+ if (D_CAL && !(n == 1 && D_AL))
+ CPutStr(D_CAL, n);
+ else
+ for(i = n; i--; )
+ PutStr(D_AL);
+ }
+ }
+ else
+ {
+ Redisplay(0);
+ return;
+ }
+ if (D_lp_missing && missy != D_bot)
+ FixLP(D_width - 1, missy);
+ ChangeScrollRegion(oldtop, oldbot);
+ if (D_lp_missing && missy != D_bot)
+ FixLP(D_width - 1, missy);
+}
+
+void
+SetAttr(new)
+register int new;
+{
+ register int i, j, old, typ;
+
+ if (!display || (old = D_rend.attr) == new)
+ return;
+#if defined(TERMINFO) && defined(USE_SGR)
+ debug1("USE_SGR defined, sa is %s\n", D_SA ? D_SA : "undefined");
+ if (D_SA)
+ {
+ char *tparm();
+ SetFont(ASCII);
+ tputs(tparm(D_SA, new & A_SO, new & A_US, new & A_RV, new & A_BL,
+ new & A_DI, new & A_BD, 0 , 0 ,
+ 0), 1, PutChar);
+ D_rend.attr = new;
+ D_atyp = 0;
+# ifdef COLOR
+ if (D_CAF || D_CAB)
+ D_rend.color = 0;
+# endif
+ return;
+ }
+#endif
+ typ = D_atyp;
+ if ((new & old) != old)
+ {
+ if ((typ & ATYP_U))
+ PutStr(D_UE);
+ if ((typ & ATYP_S))
+ PutStr(D_SE);
+ if ((typ & ATYP_M))
+ {
+ PutStr(D_ME);
+#ifdef COLOR
+ /* ansi attrib handling: \E[m resets color, too */
+ if (D_CAF || D_CAB)
+ D_rend.color = 0;
+#endif
+ }
+ old = 0;
+ typ = 0;
+ }
+ old ^= new;
+ for (i = 0, j = 1; old && i < NATTR; i++, j <<= 1)
+ {
+ if ((old & j) == 0)
+ continue;
+ old ^= j;
+ if (D_attrtab[i])
+ {
+ PutStr(D_attrtab[i]);
+ typ |= D_attrtyp[i];
+ }
+ }
+ D_rend.attr = new;
+ D_atyp = typ;
+}
+
+void
+SetFont(new)
+int new;
+{
+ if (!display || D_rend.font == new)
+ return;
+ D_rend.font = new;
+#ifdef KANJI
+ if ((new == KANJI || new == KANA) && D_kanji)
+ return; /* all done in RAW_PUTCHAR */
+#endif
+ if (D_xtable && D_xtable[(int)(unsigned char)new] &&
+ D_xtable[(int)(unsigned char)new][256])
+ {
+ PutStr(D_xtable[(int)(unsigned char)new][256]);
+ return;
+ }
+
+ if (!D_CG0 && new != '0')
+ new = ASCII;
+
+ if (new == ASCII)
+ PutStr(D_CE0);
+#ifdef KANJI
+ else if (new < ' ')
+ {
+ AddStr("\033$");
+ AddChar(new + '@');
+ }
+#endif
+ else
+ CPutStr(D_CS0, new);
+}
+
+#ifdef COLOR
+void
+SetColor(new)
+int new;
+{
+ int of, ob, f, b;
+
+ if (!display || D_rend.color == new)
+ return;
+ of = D_rend.color & 0xf;
+ ob = (D_rend.color >> 4) & 0xf;
+ f = new & 0xf;
+ b = (new >> 4) & 0xf;
+
+ if (!D_CAX && ((f == 0 && f != of) || (b == 0 && b != ob)))
+ {
+ int oattr;
+
+ oattr = D_rend.attr;
+ AddStr("\033[m");
+ D_rend.attr = 0;
+ D_rend.color = 0;
+ of = ob = 0;
+ SetAttr(oattr);
+ }
+ if (D_CAF || D_CAB)
+ {
+ if (f != of)
+ CPutStr(D_CAF, 9 - f);
+ if (b != ob)
+ CPutStr(D_CAB, 9 - b);
+ }
+ D_rend.color = new;
+}
+#endif
+
+void
+SetRendition(mc)
+struct mchar *mc;
+{
+ if (!display)
+ return;
+ if (D_rend.attr != mc->attr)
+ SetAttr(mc->attr);
+#ifdef COLOR
+ if (D_rend.color != mc->color)
+ SetColor(mc->color);
+#endif
+ if (D_rend.font != mc->font)
+ SetFont(mc->font);
+}
+
+void
+SetRenditionMline(ml, x)
+struct mline *ml;
+int x;
+{
+ if (!display)
+ return;
+ if (D_rend.attr != ml->attr[x])
+ SetAttr(ml->attr[x]);
+#ifdef COLOR
+ if (D_rend.color != ml->color[x])
+ SetColor(ml->color[x]);
+#endif
+ if (D_rend.font != ml->font[x])
+ SetFont(ml->font[x]);
+}
+
+void
+MakeStatus(msg)
+char *msg;
+{
+ register char *s, *t;
+ register int max, ti;
+
+ if (!display)
+ return;
+
+ if (!D_tcinited)
+ {
+ debug("tc not inited, just writing msg\n");
+ AddStr(msg);
+ AddStr("\r\n");
+ Flush();
+ return;
+ }
+ if (!use_hardstatus || !D_HS)
+ {
+ max = D_width;
+ if (D_CLP == 0)
+ max--;
+ }
+ else
+ max = D_WS;
+ if (D_status)
+ {
+ if (!D_status_bell)
+ {
+ ti = time((time_t *) 0) - D_status_time;
+ if (ti < MsgMinWait)
+ sleep(MsgMinWait - ti);
+ }
+ RemoveStatus();
+ }
+ for (s = t = msg; *s && t - msg < max; ++s)
+ if (*s == BELL)
+ PutStr(D_BL);
+ else if ((unsigned char)*s >= ' ' && *s != 0177)
+ *t++ = *s;
+ *t = '\0';
+ if (t > msg)
+ {
+ if (t - msg >= D_status_buflen)
+ {
+ char *buf;
+ if (D_status_lastmsg)
+ buf = realloc(D_status_lastmsg, t - msg + 1);
+ else
+ buf = malloc(t - msg + 1);
+ if (buf)
+ {
+ D_status_lastmsg = buf;
+ D_status_buflen = t - msg + 1;
+ }
+ }
+ if (t - msg < D_status_buflen)
+ strcpy(D_status_lastmsg, msg);
+ D_status = 1;
+ D_status_len = t - msg;
+ D_status_lastx = D_x;
+ D_status_lasty = D_y;
+ if (!use_hardstatus || !D_HS)
+ {
+ debug1("using STATLINE %d\n", STATLINE);
+ GotoPos(0, STATLINE);
+ SetRendition(&mchar_so);
+ InsertMode(0);
+ AddStr(msg);
+ D_x = -1;
+ }
+ else
+ {
+ debug("using HS\n");
+ SetRendition(&mchar_null);
+ InsertMode(0);
+ if (D_hstatus)
+ PutStr(D_DS);
+ CPutStr(D_TS, 0);
+ AddStr(msg);
+ PutStr(D_FS);
+ D_hstatus = 1;
+ }
+ Flush();
+ (void) time(&D_status_time);
+ }
+}
+
+void
+RemoveStatus()
+{
+ struct win *p;
+
+ if (!display)
+ return;
+ if (!D_status)
+ return;
+
+ /*
+ * UGLY HACK ALERT - this should NOT be in display.c
+ * We need to find the window that caused an activity or bell
+ * message, to reenable this function there.
+ */
+ for (p = windows; p; p = p->w_next)
+ {
+ if (p->w_display != display)
+ continue;
+ if (p->w_monitor == MON_MSG)
+ {
+ debug1("RemoveStatus clearing monitor win %d\n", p->w_number);
+ p->w_monitor = MON_DONE;
+ }
+ if (p->w_bell == BELL_MSG)
+ {
+ debug1("RemoveStatus clearing bell win %d\n", p->w_number);
+ p->w_bell = BELL_DONE;
+ }
+ }
+ D_status = 0;
+ D_status_bell = 0;
+ if (!use_hardstatus || !D_HS)
+ {
+ GotoPos(0, STATLINE);
+ RefreshLine(STATLINE, 0, D_status_len - 1, 0);
+ GotoPos(D_status_lastx, D_status_lasty);
+ }
+ else
+ {
+ /*
+ SetRendition(&mchar_null);
+ if (D_hstatus)
+ PutStr(D_DS);
+ */
+ RefreshStatus();
+ }
+ SetCursor();
+}
+
+/*
+ * Refreshes the harstatus of the _window_. Shouldn't be here...
+ */
+
+void
+RefreshStatus()
+{
+ char *buf;
+
+ if (D_HS)
+ {
+ SetRendition(&mchar_null);
+ if (D_hstatus)
+ PutStr(D_DS);
+ if (D_fore && D_fore->w_hstatus)
+ {
+ buf = MakeWinMsg(D_fore->w_hstatus, D_fore, '\005');
+ CPutStr(D_TS, 0);
+ if (strlen(buf) > D_WS)
+ AddStrn(buf, D_WS);
+ else
+ AddStr(buf);
+ PutStr(D_FS);
+ D_hstatus = 1;
+ }
+ }
+ else if (D_fore && D_fore->w_hstatus)
+ {
+ buf = MakeWinMsg(D_fore->w_hstatus, D_fore, '\005');
+ Msg(0, "%s", buf);
+ }
+}
+
+void
+RefreshLine(y, from, to, isblank)
+int y, from, to, isblank;
+{
+ ASSERT(display);
+ debug2("RefreshLine %d %d", y, from);
+ debug2(" %d %d\n", to, isblank);
+ if (isblank == 0 && D_CE && to == D_width - 1)
+ {
+ GotoPos(from, y);
+ if (D_UT)
+ SetRendition(&mchar_null);
+ PutStr(D_CE);
+ isblank = 1;
+ }
+ RedisplayLine(y, from, to, isblank);
+}
+
+void
+FixLP(x2, y2)
+register int x2, y2;
+{
+ struct mchar oldrend;
+
+ ASSERT(display);
+ oldrend = D_rend;
+ GotoPos(x2, y2);
+ SetRendition(&D_lpchar);
+ PUTCHAR(D_lpchar.image);
+ D_lp_missing = 0;
+ SetRendition(&oldrend);
+}
+
+void
+DisplayLine(oml, ml, y, from, to)
+struct mline *oml, *ml;
+int from, to, y;
+{
+ register int x;
+ int last2flag = 0, delete_lp = 0;
+
+ ASSERT(display);
+ ASSERT(y >= 0 && y < D_height);
+ ASSERT(from >= 0 && from < D_width);
+ ASSERT(to >= 0 && to < D_width);
+ if (!D_CLP && y == D_bot && to == D_width - 1)
+ if (D_lp_missing || !cmp_mline(oml, ml, to))
+ {
+ if ((D_IC || D_IM) && from < to)
+ {
+ to -= 2;
+ last2flag = 1;
+ D_lp_missing = 0;
+ }
+ else
+ {
+ to--;
+ delete_lp = (D_CE || D_DC || D_CDC);
+ D_lp_missing = !cmp_mchar_mline(&mchar_blank, ml, to);
+ copy_mline2mchar(&D_lpchar, ml, to);
+ }
+ }
+ else
+ to--;
+ for (x = from; x <= to; x++)
+ {
+ if (x || D_x != D_width || D_y != y - 1)
+ {
+ if (x < to || x != D_width - 1 || ml->image[x + 1] == ' ')
+ if (cmp_mline(oml, ml, x))
+ continue;
+ GotoPos(x, y);
+ }
+#ifdef KANJI
+ if (badkanji(ml->font, x))
+ {
+ x--;
+ GotoPos(x, y);
+ }
+#endif
+ SetRenditionMline(ml, x);
+ PUTCHAR(ml->image[x]);
+#ifdef KANJI
+ if (ml->font[x] == KANJI)
+ PUTCHAR(ml->image[++x]);
+#endif
+ }
+ if (to == D_width - 1 && y < D_height - 1 && ml->image[to + 1] == ' ')
+ GotoPos(0, y + 1);
+ if (last2flag)
+ {
+ GotoPos(x, y);
+ SetRenditionMline(ml, x + 1);
+ PUTCHAR(ml->image[x + 1]);
+ GotoPos(x, y);
+ SetRenditionMline(ml, x);
+ INSERTCHAR(ml->image[x]);
+ }
+ else if (delete_lp)
+ {
+ if (D_UT)
+ {
+ SetRendition(&mchar_null);
+ }
+ if (D_DC)
+ PutStr(D_DC);
+ else if (D_CDC)
+ CPutStr(D_CDC, 1);
+ else if (D_CE)
+ PutStr(D_CE);
+ }
+}
+
+void
+SetLastPos(x,y)
+int x,y;
+{
+ ASSERT(display);
+ D_x = x;
+ D_y = y;
+}
+
+int
+ResizeDisplay(wi, he)
+int wi, he;
+{
+ ASSERT(display);
+ debug2("ResizeDisplay: to (%d,%d).\n", wi, he);
+ if (D_width == wi && D_height == he)
+ {
+ debug("ResizeDisplay: No change\n");
+ return 0;
+ }
+ if (D_CWS)
+ {
+ debug("ResizeDisplay: using WS\n");
+ PutStr(tgoto(D_CWS, wi, he));
+ ChangeScreenSize(wi, he, 0);
+ return 0;
+ }
+ else if (D_CZ0 && (wi == Z0width || wi == Z1width))
+ {
+ debug("ResizeDisplay: using Z0/Z1\n");
+ PutStr(wi == Z0width ? D_CZ0 : D_CZ1);
+ ChangeScreenSize(wi, D_height, 0);
+ return (he == D_height) ? 0 : -1;
+ }
+ return -1;
+}
+
+void
+ChangeScrollRegion(newtop, newbot)
+int newtop, newbot;
+{
+ if (display == 0)
+ return;
+ if (D_CS == 0)
+ {
+ D_top = 0;
+ D_bot = D_height - 1;
+ return;
+ }
+ if (D_top == newtop && D_bot == newbot)
+ return;
+ debug2("ChangeScrollRegion: (%d - %d)\n", newtop, newbot);
+ PutStr(tgoto(D_CS, newbot, newtop));
+ D_top = newtop;
+ D_bot = newbot;
+ D_y = D_x = -1; /* Just in case... */
+}
+
+
+/*
+ * Layer creation / removal
+ */
+
+int
+InitOverlayPage(datasize, lf, block)
+int datasize;
+struct LayFuncs *lf;
+int block;
+{
+ char *data;
+ struct layer *newlay;
+
+ RemoveStatus();
+ debug3("Entering new layer display %#x D_fore %#x oldlay %#x\n",
+ (unsigned int)display, (unsigned int)D_fore, (unsigned int)D_lay);
+ if ((newlay = (struct layer *)malloc(sizeof(struct layer))) == 0)
+ {
+ Msg(0, "No memory for layer struct");
+ return -1;
+ }
+ data = 0;
+ if (datasize)
+ {
+ if ((data = malloc(datasize)) == 0)
+ {
+ free((char *)newlay);
+ Msg(0, "No memory for layer data");
+ return -1;
+ }
+ bzero(data, datasize);
+ }
+ newlay->l_layfn = lf;
+ newlay->l_block = block | D_lay->l_block;
+ newlay->l_data = data;
+ newlay->l_next = D_lay;
+ if (D_fore)
+ {
+ D_fore->w_lay = newlay; /* XXX: CHECK */
+ D_fore->w_active = 0; /* XXX: CHECK */
+ }
+ D_lay = newlay;
+ D_layfn = newlay->l_layfn;
+ Restore();
+ return 0;
+}
+
+void
+ExitOverlayPage()
+{
+ struct layer *oldlay;
+
+ debug3("Exiting layer display %#x fore %#x D_lay %#x\n",
+ (unsigned int)display, (unsigned int)D_fore, (unsigned int)D_lay);
+ oldlay = D_lay;
+ if (oldlay->l_data)
+ free(oldlay->l_data);
+ D_lay = oldlay->l_next;
+ D_layfn = D_lay->l_layfn;
+ free((char *)oldlay);
+ if (D_fore)
+ D_fore->w_lay = D_lay; /* XXX: Is this necessary ? */
+ Restore();
+ SetCursor();
+}
+
+
+/*
+ * Output buffering routines
+ */
+
+void
+AddStr(str)
+char *str;
+{
+ register char c;
+
+ ASSERT(display);
+ while ((c = *str++))
+ AddChar(c);
+}
+
+void
+AddStrn(str, n)
+char *str;
+int n;
+{
+ register char c;
+
+ ASSERT(display);
+ while ((c = *str++) && n-- > 0)
+ AddChar(c);
+ while (n-- > 0)
+ AddChar(' ');
+}
+
+void
+Flush()
+{
+ register int l;
+ register char *p;
+
+ ASSERT(display);
+ l = D_obufp - D_obuf;
+ debug1("Flush(): %d\n", l);
+ ASSERT(l + D_obuffree == D_obuflen);
+ if (l == 0)
+ return;
+ if (D_userfd < 0)
+ {
+ D_obuffree += l;
+ D_obufp = D_obuf;
+ return;
+ }
+ p = D_obuf;
+ if (fcntl(D_userfd, F_SETFL, 0))
+ debug1("Warning: BLOCK fcntl failed: %d\n", errno);
+ while (l)
+ {
+ register int wr;
+ wr = write(D_userfd, p, l);
+ if (wr <= 0)
+ {
+ if (errno == EINTR)
+ continue;
+ debug1("Writing to display: %d\n", errno);
+ wr = l;
+ }
+ D_obuffree += wr;
+ p += wr;
+ l -= wr;
+ }
+ D_obuffree += l;
+ D_obufp = D_obuf;
+ if (fcntl(D_userfd, F_SETFL, FNBLOCK))
+ debug1("Warning: NBLOCK fcntl failed: %d\n", errno);
+}
+
+void
+freetty()
+{
+ if (D_userfd >= 0)
+ close(D_userfd);
+ debug1("did freetty %d\n", D_userfd);
+ D_userfd = -1;
+ D_obufp = 0;
+ D_obuffree = 0;
+ if (D_obuf)
+ free(D_obuf);
+ D_obuf = 0;
+ D_obuflen = 0;
+}
+
+/*
+ * Asynchronous output routines by
+ * Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
+ */
+
+void
+Resize_obuf()
+{
+ register int ind;
+
+ ASSERT(display);
+ if (D_obuflen && D_obuf)
+ {
+ ind = D_obufp - D_obuf;
+ D_obuflen += GRAIN;
+ D_obuffree += GRAIN;
+ D_obuf = realloc(D_obuf, D_obuflen);
+ }
+ else
+ {
+ ind = 0;
+ D_obuflen = GRAIN;
+ D_obuffree = GRAIN;
+ D_obuf = malloc(D_obuflen);
+ }
+ if (!D_obuf)
+ Panic(0, "Out of memory");
+ D_obufp = D_obuf + ind;
+ debug1("ResizeObuf: resized to %d\n", D_obuflen);
+}
+
+#ifdef AUTO_NUKE
+void
+NukePending()
+{/* Nuke pending output in current display, clear screen */
+ register int len;
+ int oldtop = D_top, oldbot = D_bot;
+ struct mchar oldrend;
+ int oldkeypad = D_keypad, oldcursorkeys = D_cursorkeys;
+ int oldcurvis = D_curvis;
+
+ oldrend = D_rend;
+ len = D_obufp - D_obuf;
+ debug1("NukePending: nuking %d chars\n", len);
+
+ /* Throw away any output that we can... */
+# ifdef POSIX
+ tcflush(D_userfd, TCOFLUSH);
+# else
+# ifdef TCFLSH
+ (void) ioctl(D_userfd, TCFLSH, (char *) 1);
+# endif
+# endif
+
+ D_obufp = D_obuf;
+ D_obuffree += len;
+ D_top = D_bot = -1;
+ PutStr(D_TI);
+ PutStr(D_IS);
+ /* Turn off all attributes. (Tim MacKenzie) */
+ if (D_ME)
+ PutStr(D_ME);
+ else
+ {
+ PutStr(D_SE);
+ PutStr(D_UE);
+ }
+ /* FIXME: reset color! */
+ /* Check for toggle */
+ if (D_IM && strcmp(D_IM, D_EI))
+ PutStr(D_EI);
+ D_insert = 0;
+ /* Check for toggle */
+#ifndef MAPKEYS
+ if (D_KS && strcmp(D_KS, D_KE))
+ PutStr(D_KE);
+ D_keypad = 0;
+ if (D_CCS && strcmp(D_CCS, D_CCE))
+ PutStr(D_CCE);
+ D_cursorkeys = 0;
+#endif
+ PutStr(D_CE0);
+ D_rend = mchar_null;
+ D_atyp = 0;
+ PutStr(D_DS);
+ D_hstatus = 0;
+ PutStr(D_VE);
+ D_curvis = 0;
+ ChangeScrollRegion(oldtop, oldbot);
+ SetRendition(&oldrend);
+ KeypadMode(oldkeypad);
+ CursorkeysMode(oldcursorkeys);
+ CursorVisibility(oldcurvis);
+ if (D_CWS)
+ {
+ debug("ResizeDisplay: using WS\n");
+ PutStr(tgoto(D_CWS, D_width, D_height));
+ }
+ else if (D_CZ0 && (D_width == Z0width || D_width == Z1width))
+ {
+ debug("ResizeDisplay: using Z0/Z1\n");
+ PutStr(D_width == Z0width ? D_CZ0 : D_CZ1);
+ }
+}
+#endif /* AUTO_NUKE */
+
+#ifdef KANJI
+int
+badkanji(f, x)
+char *f;
+int x;
+{
+ int i, j;
+ if (f[x] != KANJI)
+ return 0;
+ for (i = j = 0; i < x; i++)
+ if (*f++ == KANJI)
+ j ^= 1;
+ return j;
+}
+#endif