diff options
author | Axel Beckert <abe@deuxchevaux.org> | 2011-09-03 14:05:19 +0200 |
---|---|---|
committer | Axel Beckert <abe@deuxchevaux.org> | 2011-09-03 14:05:19 +0200 |
commit | 0636e9ecb5a32db4d4520f50a20652faa825feaf (patch) | |
tree | b94df9221e8ae0de0dc3afac301d5b63b136a7b4 /ansi.c | |
download | screen-0636e9ecb5a32db4d4520f50a20652faa825feaf.tar.gz |
Imported Upstream version 3.7.2upstream/3.7.2
Diffstat (limited to 'ansi.c')
-rw-r--r-- | ansi.c | 2511 |
1 files changed, 2511 insertions, 0 deletions
@@ -0,0 +1,2511 @@ +/* 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: ansi.c,v 1.22 1994/05/31 12:31:25 mlschroe Exp $ FAU") + +#include <sys/types.h> +#include <signal.h> +#include <fcntl.h> +#ifndef sun /* we want to know about TIOCPKT. */ +# include <sys/ioctl.h> +#endif + +#include "config.h" +#include "screen.h" +#include "extern.h" + +extern struct win *windows; /* linked list of all windows */ +extern struct win *fore; +extern struct display *display, *displays; + +extern int force_vt; +extern int all_norefresh; /* => display */ +extern int ZombieKey_destroy, ZombieKey_resurrect; +extern int real_uid, real_gid; +extern time_t Now; +extern struct NewWindow nwin_default; /* for ResetWindow() */ +extern int nversion; + +int Z0width, Z1width; /* widths for Z0/Z1 switching */ + +static struct win *curr; /* window we are working on */ +static int rows, cols; /* window size of the curr window */ + +int visual_bell = 0; +int use_hardstatus = 1; +char *printcmd = 0; + +char *blank; /* line filled with spaces */ +char *null; /* line filled with '\0' */ + +struct mline mline_old; +struct mline mline_blank; +struct mline mline_null; + +struct mchar mchar_null; +struct mchar mchar_blank = {' ' /* , 0, 0, ... */}; +struct mchar mchar_so = {' ', A_SO /* , 0, 0, ... */}; + +static void WinProcess __P((char **, int *)); +static void WinRedisplayLine __P((int, int, int, int)); +static void WinClearLine __P((int, int, int)); +static int WinRewrite __P((int, int, int, int)); +static void WinSetCursor __P((void)); +static int WinResize __P((int, int)); +static void WinRestore __P((void)); +static int Special __P((int)); +static void DoESC __P((int, int)); +static void DoCSI __P((int, int)); +static void SetChar __P((int)); +static void StartString __P((enum string_t)); +static void SaveChar __P((int)); +static void PrintStart __P((void)); +static void PrintChar __P((int)); +static void PrintFlush __P((void)); +static void DesignateCharset __P((int, int)); +static void MapCharset __P((int)); +static void MapCharsetR __P((int)); +static void SaveCursor __P((void)); +static void RestoreCursor __P((void)); +static void BackSpace __P((void)); +static void Return __P((void)); +static void LineFeed __P((int)); +static void ReverseLineFeed __P((void)); +static void InsertAChar __P((int)); +static void InsertChar __P((int)); +static void DeleteChar __P((int)); +static void DeleteLine __P((int)); +static void InsertLine __P((int)); +static void ScrollUpMap __P((int)); +static void ScrollDownMap __P((int)); +static void Scroll __P((char *, int, int, char *)); +static void ForwardTab __P((void)); +static void BackwardTab __P((void)); +static void ClearScreen __P((void)); +static void ClearFromBOS __P((void)); +static void ClearToEOS __P((void)); +static void ClearFullLine __P((void)); +static void ClearToEOL __P((void)); +static void ClearFromBOL __P((void)); +static void ClearInLine __P((int, int, int)); +static void CursorRight __P((int)); +static void CursorUp __P((int)); +static void CursorDown __P((int)); +static void CursorLeft __P((int)); +static void ASetMode __P((int)); +static void SelectRendition __P((void)); +static void RestorePosRendition __P((void)); +static void FillWithEs __P((void)); +static void UpdateLine __P((struct mline *, int, int, int )); +static void FindAKA __P((void)); +static void Report __P((char *, int, int)); +static void FixLine __P((void)); +static void ScrollRegion __P((int)); +static void CheckLP __P((int)); +#ifdef COPY_PASTE +static void AddLineToHist __P((struct win *, struct mline *)); +#endif + + +/* + * The window layer functions + */ + +struct LayFuncs WinLf = +{ + WinProcess, + 0, + WinRedisplayLine, + WinClearLine, + WinRewrite, + WinSetCursor, + WinResize, + WinRestore +}; + +static void +WinProcess(bufpp, lenp) +char **bufpp; +int *lenp; +{ + int addlf, l2 = 0, f, *ilen, l = *lenp; + char *ibuf, *p, *buf = *bufpp; + + fore = D_fore; + /* if w_wlock is set, only one user may write, else we check acls */ + if (fore->w_ptyfd < 0) + { + while ((*lenp)-- > 0) + { + f = *(*bufpp)++; + if (f == ZombieKey_destroy) + { + debug2("Turning undead: %d(%s)\n", fore->w_number, fore->w_title); + KillWindow(fore); + l2--; + break; + } + if (f == ZombieKey_resurrect) + { + SetCurr(fore); + + debug1("Resurrecting Zombie: %d\n", fore->w_number); + LineFeed(2); + RemakeWindow(fore); + l2++; + break; + } + } + if (!l2) + { + char b1[10], b2[10]; + + b1[AddXChar(b1, ZombieKey_destroy)] = '\0'; + b2[AddXChar(b2, ZombieKey_resurrect)] = '\0'; + Msg(0, "Press %s to destroy or %s to resurrect window", b1, b2); + } + *bufpp += *lenp; + *lenp = 0; + return; + } +#ifdef MULTIUSER + if ((fore->w_wlock == WLOCK_OFF) ? + AclCheckPermWin(D_user, ACL_WRITE, fore) : + (D_user != fore->w_wlockuser)) + { + SetCurr(fore); + Special('\007'); + *bufpp += *lenp; + *lenp = 0; + return; + } +#endif /* MULTIUSER */ +#ifdef PSEUDOS + if (W_UWP(fore)) + { + /* we send the user input to our pseudowin */ + ibuf = fore->w_pwin->p_inbuf; ilen = &fore->w_pwin->p_inlen; + f = sizeof(fore->w_pwin->p_inbuf) - *ilen; + } + else +#endif /* PSEUDOS */ + { + /* we send the user input to the window */ + ibuf = fore->w_inbuf; ilen = &fore->w_inlen; + f = sizeof(fore->w_inbuf) - *ilen; + } + + buf = *bufpp; + + while (l) + { + l2 = l; + addlf = 0; + if (fore->w_autolf) + { + for (p = buf; l2; p++, l2--) + if (*p == '\r') + { + l2--; + addlf = 1; + break; + } + l2 = l - l2; + } + if (l2 + addlf > f) + { + debug1("Yuck! pty buffer full (%d chars missing). lets beep\n", l - f); + SetCurr(fore); + Special('\007'); + l = l2 = f; + addlf = 0; + } + if (l2 > 0) + { + bcopy(buf, ibuf + *ilen, l2); + *ilen += l2; + f -= l2; + buf += l2; + l -= l2; + if (f && addlf) + { + ibuf[(*ilen)++] = '\n'; + f--; + } + } + } + *bufpp += *lenp; + *lenp = 0; +} + +static void +WinRedisplayLine(y, from, to, isblank) +int y, from, to, isblank; +{ + if (y < 0) + return; + fore = D_fore; + DisplayLine(isblank ? &mline_blank : &mline_null, &fore->w_mlines[y], + y, from, to); +} + +static int +WinRewrite(y, x1, x2, doit) +int y, x1, x2, doit; +{ + register int cost, dx; + register char *p, *f, *i; +#ifdef COLOR + register char *c; +#endif + + fore = D_fore; + dx = x2 - x1; + if (doit) + { + i = fore->w_mlines[y].image + x1; + while (dx-- > 0) + PUTCHAR(*i++); + return 0; + } + p = fore->w_mlines[y].attr + x1; + f = fore->w_mlines[y].font + x1; +#ifdef COLOR + c = fore->w_mlines[y].color + x1; +#endif + + cost = dx = x2 - x1; + if (D_insert) + cost += D_EIcost + D_IMcost; + while(dx-- > 0) + { +#ifdef COLOR + if (*p++ != D_rend.attr || *f++ != D_rend.font || *c++ != D_rend.color) + return EXPENSIVE; +#else + if (*p++ != D_rend.attr || *f++ != D_rend.font) + return EXPENSIVE; +#endif + } + return cost; +} + +static void +WinClearLine(y, xs, xe) +int y, xs, xe; +{ + fore = D_fore; + DisplayLine(&fore->w_mlines[y], &mline_blank, y, xs, xe); +} + +static void +WinSetCursor() +{ + fore = D_fore; + GotoPos(fore->w_x, fore->w_y); +} + +static int +WinResize(wi, he) +int wi, he; +{ + fore = D_fore; + if (fore) + ChangeWindowSize(fore, wi, he, fore->w_histheight); + return 0; +} + +static void +WinRestore() +{ + fore = D_fore; + ChangeScrollRegion(fore->w_top, fore->w_bot); + KeypadMode(fore->w_keypad); + CursorkeysMode(fore->w_cursorkeys); + SetFlow(fore->w_flow & FLOW_NOW); + InsertMode(fore->w_insert); + ReverseVideo(fore->w_revvid); + CursorVisibility(fore->w_curinv ? -1 : fore->w_curvvis); + fore->w_active = 1; +} + +/* + * Activate - make fore window active + * norefresh = -1 forces a refresh, disregard all_norefresh then. + */ +void +Activate(norefresh) +int norefresh; +{ + debug1("Activate(%d)\n", norefresh); + if (display == 0) + return; + if (D_status) + { + Msg(0, "%s", ""); /* wait till mintime (keep gcc quiet) */ + RemoveStatus(); + } + fore = D_fore; + if (fore) + { + ASSERT(fore->w_display == display); + fore->w_active = D_layfn == &WinLf; + if (fore->w_monitor != MON_OFF) + fore->w_monitor = MON_ON; + fore->w_bell = BELL_OFF; + if (ResizeDisplay(fore->w_width, fore->w_height)) + { + debug2("Cannot resize from (%d,%d)", D_width, D_height); + debug2(" to (%d,%d) -> resize window\n", fore->w_width, fore->w_height); + DoResize(D_width, D_height); + } + } + Redisplay(norefresh + all_norefresh); +} + +void +ResetWindow(p) +register struct win *p; +{ + register int i; + + p->w_wrap = nwin_default.wrap; + p->w_origin = 0; + p->w_insert = 0; + p->w_revvid = 0; + p->w_curinv = 0; + p->w_curvvis = 0; + p->w_autolf = 0; + p->w_keypad = 0; + p->w_cursorkeys = 0; + p->w_top = 0; + p->w_bot = p->w_height - 1; + p->w_saved = 0; + p->w_x = p->w_y = 0; + p->w_state = LIT; + p->w_StringType = NONE; + bzero(p->w_tabs, p->w_width); + for (i = 8; i < p->w_width; i += 8) + p->w_tabs[i] = 1; + p->w_rend = mchar_null; + ResetCharsets(p); +} + +#ifdef KANJI +static char *kanjicharsets[3] = { + "BBBB02", /* jis */ + "\002IBB01", /* euc */ + "BIBB01" /* sjis */ +}; +#endif + +void +ResetCharsets(p) +register struct win *p; +{ + p->w_gr = nwin_default.gr; + p->w_c1 = nwin_default.c1; + SetCharsets(p, "BBBB02"); + if (nwin_default.charset) + SetCharsets(p, nwin_default.charset); +#ifdef KANJI + if (p->w_kanji) + { + p->w_gr = 1; + if (p->w_kanji == SJIS) + p->w_c1 = 0; + SetCharsets(p, kanjicharsets[p->w_kanji]); + } +#endif +} + +void +SetCharsets(p, s) +struct win *p; +char *s; +{ + int i; + + for (i = 0; i < 4 && *s; i++, s++) + if (*s != '.') + p->w_charsets[i] = ((*s == 'B') ? ASCII : *s); + if (*s && *s++ != '.') + p->w_Charset = s[-1] - '0'; + if (*s && *s != '.') + p->w_CharsetR = *s - '0'; + p->w_ss = 0; + p->w_FontL = p->w_charsets[p->w_Charset]; + p->w_FontR = p->w_charsets[p->w_CharsetR]; +} + +static void +FixLine() +{ + struct mline *ml = &curr->w_mlines[curr->w_y]; + if (curr->w_rend.attr && ml->attr == null) + { + if ((ml->attr = (char *)malloc(curr->w_width + 1)) == 0) + { + ml->attr = null; + curr->w_rend.attr = 0; + Msg(0, "Warning: no space for attr - turned off"); + } + bzero(ml->attr, curr->w_width + 1); + } + if ((curr->w_FontL || curr->w_FontR) && ml->font == null) + { + if ((ml->font = (char *)malloc(curr->w_width + 1)) == 0) + { + ml->font = null; + curr->w_FontL = curr->w_charsets[curr->w_ss ? curr->w_ss : curr->w_Charset] = 0; + curr->w_FontR = curr->w_charsets[curr->w_ss ? curr->w_ss : curr->w_CharsetR] = 0; + curr->w_rend.font = 0; + Msg(0, "Warning: no space for font - turned off"); + } + bzero(ml->font, curr->w_width + 1); + } +#ifdef COLOR + if (curr->w_rend.color && ml->color == null) + { + if ((ml->color = (char *)malloc(curr->w_width + 1)) == 0) + { + ml->color = null; + curr->w_rend.color = 0; + Msg(0, "Warning: no space for color - turned off"); + } + bzero(ml->color, curr->w_width + 1); + } +#endif +} + + +/* + * Here comes the vt100 emulator + */ +void +WriteString(wp, buf, len) +struct win *wp; +register char *buf; +register int len; +{ + register int c, font; + + if (!len) + return; + if (wp->w_logfp != NULL) + if ((int)fwrite(buf, len, 1, wp->w_logfp) < 1) + { + Msg(errno, "Error writing logfile"); + fclose(wp->w_logfp); + wp->w_logfp = NULL; + } + /* + * SetCurr() here may prevent output, as it may set display = 0 + */ + SetCurr(wp); + if (display) + { + if (D_status && !(use_hardstatus && D_HS)) + RemoveStatus(); + } + else + { + if (curr->w_tstamp.seconds) + curr->w_tstamp.lastio = Now; + + if (curr->w_monitor == MON_ON || curr->w_monitor == MON_DONE) + { + debug2("ACTIVITY %d %d\n", curr->w_monitor, curr->w_bell); + curr->w_monitor = MON_FOUND; + } + } + + do + { + c = (unsigned char)*buf++; + curr->w_rend.font = curr->w_FontL; /* Default: GL */ + + /* The next part is only for speedup + * (therefore no mchars are used) */ + if (curr->w_state == LIT && +#ifdef KANJI + curr->w_FontL != KANJI && curr->w_FontL != KANA && !curr->w_mbcs && +#endif + c >= ' ' && + ((c & 0x80) == 0 || ((c >= 0xa0 || !curr->w_c1) && !curr->w_gr)) && + !curr->w_insert && !curr->w_ss && curr->w_x < cols - 1) + { + register int currx; + register char *imp, *atp, *fop, at, fo; +#ifdef COLOR + register char *cop, co; +#endif + register char **xtable = 0; + register char *c0tab = 0; + + if (c == '\177') + continue; + FixLine(); + currx = curr->w_x; + imp = curr->w_mlines[curr->w_y].image + currx; + atp = curr->w_mlines[curr->w_y].attr + currx; + fop = curr->w_mlines[curr->w_y].font + currx; + at = curr->w_rend.attr; + fo = curr->w_rend.font; +#ifdef COLOR + cop = curr->w_mlines[curr->w_y].color + currx; + co = curr->w_rend.color; +#endif + if (display) + { + if (D_x != currx || D_y != curr->w_y) + GotoPos(currx, curr->w_y); + /* This is not SetRendition because the compiler would + * not use registers if at/fo/co would be an mchar */ + if (at != D_rend.attr) + SetAttr(at); +#ifdef COLOR + if (co != D_rend.color) + SetColor(co); +#endif + if (fo != D_rend.font) + SetFont(fo); + if (D_insert) + InsertMode(0); + if (D_xtable) + xtable = D_xtable[(int)(unsigned char)D_rend.font]; + if (D_rend.font == '0') + c0tab = D_c0_tab; + } + while (currx < cols - 1) + { + if (display) + { + if (xtable && xtable[c]) + AddStr(xtable[c]); + else if (c0tab) + AddChar(c0tab[c]); + else + AddChar(c); + } + *imp++ = c; + *atp++ = at; + *fop++ = fo; +#ifdef COLOR + *cop++ = co; +#endif + currx++; +skip: if (--len == 0) + break; + c = (unsigned char)*buf++; + if (c == '\177') + goto skip; + if (c < ' ' || ((c & 0x80) && ((c < 0xa0 && curr->w_c1) || curr->w_gr))) + break; + } + curr->w_x = currx; + if (display) + D_x = currx; + if (len == 0) + break; + } + /* end of speedup code */ + + tryagain: + switch (curr->w_state) + { + case PRIN: + switch (c) + { + case '\033': + curr->w_state = PRINESC; + break; + default: + PrintChar(c); + } + break; + case PRINESC: + switch (c) + { + case '[': + curr->w_state = PRINCSI; + break; + default: + PrintChar('\033'); + PrintChar(c); + curr->w_state = PRIN; + } + break; + case PRINCSI: + switch (c) + { + case '4': + curr->w_state = PRIN4; + break; + default: + PrintChar('\033'); + PrintChar('['); + PrintChar(c); + curr->w_state = PRIN; + } + break; + case PRIN4: + switch (c) + { + case 'i': + curr->w_state = LIT; + PrintFlush(); + if (curr->w_pdisplay && curr->w_pdisplay->d_printfd >= 0) + { + close(curr->w_pdisplay->d_printfd); + curr->w_pdisplay->d_printfd = -1; + } + curr->w_pdisplay = 0; + break; + default: + PrintChar('\033'); + PrintChar('['); + PrintChar('4'); + PrintChar(c); + curr->w_state = PRIN; + } + break; + case ASTR: + if (c == 0) + break; + if (c == '\033') + { + curr->w_state = STRESC; + break; + } + /* special xterm hack: accept SetStatus sequence. Yucc! */ + if (!(curr->w_StringType == OSC && c < ' ' && c != '\005')) + if (!curr->w_c1 || c != ('\\' ^ 0xc0)) + { + SaveChar(c); + break; + } + c = '\\'; + /* FALLTHROUGH */ + case STRESC: + switch (c) + { + case '\\': + curr->w_state = LIT; + *curr->w_stringp = '\0'; + switch (curr->w_StringType) + { + case OSC: /* special xterm compatibility hack */ + if (curr->w_stringp - curr->w_string < 2 || + curr->w_string[0] < '0' || + curr->w_string[0] > '2' || + curr->w_string[1] != ';') + break; + curr->w_stringp -= 2; + if (curr->w_stringp > curr->w_string) + bcopy(curr->w_string + 2, curr->w_string, curr->w_stringp - curr->w_string); + *curr->w_stringp = '\0'; + /* FALLTHROUGH */ + case APC: + if (curr->w_hstatus) + { + if (strcmp(curr->w_hstatus, curr->w_string) == 0) + break; /* not changed */ + free(curr->w_hstatus); + curr->w_hstatus = 0; + } + if (curr->w_string != curr->w_stringp) + curr->w_hstatus = SaveStr(curr->w_string); + if (display) + RefreshStatus(); + break; + case GM: + { + struct display *old = display; + for (display = displays; display; display = display->d_next) + if (display != old) + MakeStatus(curr->w_string); + display = old; + } + /*FALLTHROUGH*/ + case PM: + if (!display) + break; + MakeStatus(curr->w_string); + if (D_status && !(use_hardstatus && D_HS) && len > 1) + { + curr->w_outlen = len - 1; + bcopy(buf, curr->w_outbuf, curr->w_outlen); + return; + } + break; + case DCS: + if (display) + AddStr(curr->w_string); + break; + case AKA: + if (curr->w_title == curr->w_akabuf && !*curr->w_string) + break; + ChangeAKA(curr, curr->w_string, 20); + if (!*curr->w_string) + curr->w_autoaka = curr->w_y + 1; + break; + default: + break; + } + break; + case '\033': + SaveChar('\033'); + break; + default: + curr->w_state = ASTR; + SaveChar('\033'); + SaveChar(c); + break; + } + break; + case ESC: + switch (c) + { + case '[': + curr->w_NumArgs = 0; + curr->w_intermediate = 0; + bzero((char *) curr->w_args, MAXARGS * sizeof(int)); + curr->w_state = CSI; + break; + case ']': + StartString(OSC); + break; + case '_': + StartString(APC); + break; + case 'P': + StartString(DCS); + break; + case '^': + StartString(PM); + break; + case '!': + StartString(GM); + break; + case '"': + case 'k': + StartString(AKA); + break; + default: + if (Special(c)) + { + curr->w_state = LIT; + break; + } + debug1("not special. c = %x\n", c); + if (c >= ' ' && c <= '/') + { + if (curr->w_intermediate) +#ifdef KANJI + if (curr->w_intermediate == '$') + c |= '$' << 8; + else +#endif + c = -1; + curr->w_intermediate = c; + } + else if (c >= '0' && c <= '~') + { + DoESC(c, curr->w_intermediate); + curr->w_state = LIT; + } + else + { + curr->w_state = LIT; + goto tryagain; + } + } + break; + case CSI: + switch (c) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (curr->w_NumArgs < MAXARGS) + { + curr->w_args[curr->w_NumArgs] = + 10 * curr->w_args[curr->w_NumArgs] + (c - '0'); + } + break; + case ';': + case ':': + curr->w_NumArgs++; + break; + default: + if (Special(c)) + break; + if (c >= '@' && c <= '~') + { + curr->w_NumArgs++; + DoCSI(c, curr->w_intermediate); + if (curr->w_state != PRIN) + curr->w_state = LIT; + } + else if ((c >= ' ' && c <= '/') || (c >= '<' && c <= '?')) + curr->w_intermediate = curr->w_intermediate ? -1 : c; + else + { + curr->w_state = LIT; + goto tryagain; + } + } + break; + case LIT: + default: + if (c < ' ') + { + if (c == '\033') + { + curr->w_intermediate = 0; + curr->w_state = ESC; + if (display && D_lp_missing && (D_CIC || D_IC || D_IM)) + UpdateLine(&mline_blank, D_bot, cols - 2, cols - 1); + if (curr->w_autoaka < 0) + curr->w_autoaka = 0; + } + else + Special(c); + break; + } + if (c >= 0x80 && c < 0xa0 && curr->w_c1) + { + switch (c) + { + case 0xc0 ^ 'D': + case 0xc0 ^ 'E': + case 0xc0 ^ 'H': + case 0xc0 ^ 'M': + case 0xc0 ^ 'N': + case 0xc0 ^ 'O': + DoESC(c ^ 0xc0, 0); + break; + case 0xc0 ^ '[': + if (display && D_lp_missing && (D_CIC || D_IC || D_IM)) + UpdateLine(&mline_blank, D_bot, cols - 2, cols - 1); + if (curr->w_autoaka < 0) + curr->w_autoaka = 0; + curr->w_NumArgs = 0; + curr->w_intermediate = 0; + bzero((char *) curr->w_args, MAXARGS * sizeof(int)); + curr->w_state = CSI; + break; + case 0xc0 ^ 'P': + StartString(DCS); + break; + default: + break; + } + break; + } + + font = curr->w_rend.font = (c >= 0x80 ? curr->w_FontR : curr->w_FontL); +#ifdef KANJI + if (font == KANA && curr->w_kanji == SJIS && curr->w_mbcs == 0) + { + /* Lets see if it is the first byte of a kanji */ + debug1("%x may be first of SJIS\n", c); + if ((0x81 <= c && c <= 0x9f) || (0xe0 <= c && c <= 0xef)) + { + debug("YES!\n"); + curr->w_mbcs = c; + break; + } + } + if (font == KANJI || curr->w_mbcs) + { + int t = c; + if (curr->w_mbcs == 0) + { + curr->w_mbcs = c; + break; + } + if (curr->w_x == cols - 1) + { + curr->w_x += curr->w_wrap ? 1 : -1; + debug1("Patched w_x to %d\n", curr->w_x); + } + c = curr->w_mbcs; + if (font != KANJI) + { + debug2("SJIS !! %x %x\n", c, t); + if (0x40 <= t && t <= 0xfc && t != 0x7f) + { + if (c <= 0x9f) c = (c - 0x81) * 2 + 0x21; + else c = (c - 0xc1) * 2 + 0x21; + if (t <= 0x7e) t -= 0x1f; + else if (t <= 0x9e) t -= 0x20; + else t -= 0x7e, c++; + curr->w_rend.font = KANJI; + } + else + { + /* Incomplete shift-jis - skip first byte */ + c = t; + t = 0; + } + debug2("SJIS after %x %x\n", c, t); + } + curr->w_mbcs = t; + } + kanjiloop: +#endif + if (curr->w_gr) + { + c &= 0x7f; + if (c < ' ') /* this is ugly but kanji support */ + goto tryagain; /* prevents nicer programming */ + } + if (c == '\177') + break; + if (display) + SetRendition(&curr->w_rend); + if (curr->w_x < cols - 1) + { + if (curr->w_insert) + InsertAChar(c); + else + { + if (display) + PUTCHAR(c); + SetChar(c); + curr->w_x++; + } + } + else if (curr->w_x == cols - 1) + { + if (display && curr->w_wrap && (D_CLP || !force_vt || D_COP)) + { + RAW_PUTCHAR(c); /* don't care about D_insert */ + SetChar(c); + curr->w_x++; + if (D_AM && !D_CLP) + { + SetChar(0); + LineFeed(0); /* terminal auto-wrapped */ + } + } + else + { + if (display) + { + if (D_CLP || curr->w_y != D_bot) + { + RAW_PUTCHAR(c); + GotoPos(curr->w_x, curr->w_y); + } + else + CheckLP(c); + } + SetChar(c); + if (curr->w_wrap) + curr->w_x++; + } + } + else /* curr->w_x > cols - 1 */ + { + SetChar(0); /* we wrapped */ + if (curr->w_insert) + { + LineFeed(2); /* cr+lf, handle LP */ + InsertAChar(c); + } + else + { + if (display && D_AM && D_x != cols) /* write char again */ + { + SetRenditionMline(&curr->w_mlines[curr->w_y], cols - 1); + RAW_PUTCHAR(curr->w_mlines[curr->w_y].image[cols - 1]); + SetRendition(&curr->w_rend); + if (curr->w_y == D_bot) + D_lp_missing = 0; /* just wrote it */ + } + LineFeed((display == 0 || D_AM) ? 0 : 2); + if (display) + PUTCHAR(c); + SetChar(c); + curr->w_x = 1; + } + } +#ifdef KANJI + if (curr->w_mbcs) + { + c = curr->w_mbcs; + curr->w_mbcs = 0; + goto kanjiloop; /* what a hack! */ + } +#endif + if (curr->w_ss) + { + curr->w_FontL = curr->w_charsets[curr->w_Charset]; + curr->w_FontR = curr->w_charsets[curr->w_CharsetR]; + SetFont(curr->w_FontL); + curr->w_ss = 0; + } + break; + } + } + while (--len); + curr->w_outlen = 0; + if (curr->w_state == PRIN) + PrintFlush(); +} + +static int +Special(c) +register int c; +{ + switch (c) + { + case '\b': + BackSpace(); + return 1; + case '\r': + Return(); + return 1; + case '\n': + if (curr->w_autoaka) + FindAKA(); + LineFeed(1); + return 1; + case '\007': + if (display == 0) + curr->w_bell = BELL_ON; + else + { + if (!visual_bell) + PutStr(D_BL); + else + { + if (!D_VB) + curr->w_bell = BELL_VISUAL; + else + PutStr(D_VB); + } + } + return 1; + case '\t': + ForwardTab(); + return 1; + case '\017': /* SI */ + MapCharset(G0); + return 1; + case '\016': /* SO */ + MapCharset(G1); + return 1; + } + return 0; +} + +static void +DoESC(c, intermediate) +int c, intermediate; +{ + debug2("DoESC: %x - inter = %x\n", c, intermediate); + switch (intermediate) + { + case 0: + switch (c) + { + case 'E': + LineFeed(2); + break; + case 'D': + LineFeed(1); + break; + case 'M': + ReverseLineFeed(); + break; + case 'H': + curr->w_tabs[curr->w_x] = 1; + break; + case 'Z': /* jph: Identify as VT100 */ + Report("\033[?%d;%dc", 1, 2); + break; + case '7': + SaveCursor(); + break; + case '8': + RestoreCursor(); + break; + case 'c': + ClearScreen(); + ResetWindow(curr); + SetRendition(&mchar_null); + InsertMode(0); + KeypadMode(0); + CursorkeysMode(0); + ChangeScrollRegion(0, rows - 1); + break; + case '=': + KeypadMode(curr->w_keypad = 1); +#ifndef TIOCPKT + NewAutoFlow(curr, 0); +#endif /* !TIOCPKT */ + break; + case '>': + KeypadMode(curr->w_keypad = 0); +#ifndef TIOCPKT + NewAutoFlow(curr, 1); +#endif /* !TIOCPKT */ + break; + case 'n': /* LS2 */ + MapCharset(G2); + break; + case 'o': /* LS3 */ + MapCharset(G3); + break; + case '~': + MapCharsetR(G1); /* LS1R */ + break; + case '}': + MapCharsetR(G2); /* LS2R */ + break; + case '|': + MapCharsetR(G3); /* LS3R */ + break; + case 'N': /* SS2 */ + if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G2] + || curr->w_charsets[curr->w_CharsetR] != curr->w_charsets[G2]) + curr->w_FontR = curr->w_FontL = curr->w_charsets[curr->w_ss = G2]; + else + curr->w_ss = 0; + break; + case 'O': /* SS3 */ + if (curr->w_charsets[curr->w_Charset] != curr->w_charsets[G3] + || curr->w_charsets[curr->w_CharsetR] != curr->w_charsets[G3]) + curr->w_FontR = curr->w_FontL = curr->w_charsets[curr->w_ss = G3]; + else + curr->w_ss = 0; + break; + case 'g': /* VBELL, private screen sequence */ + if (display == 0) + curr->w_bell = BELL_ON; + else if (!D_VB) + curr->w_bell = BELL_VISUAL; + else + PutStr(D_VB); + break; + } + break; + case '#': + switch (c) + { + case '8': + FillWithEs(); + break; + } + break; + case '(': + DesignateCharset(c, G0); + break; + case ')': + DesignateCharset(c, G1); + break; + case '*': + DesignateCharset(c, G2); + break; + case '+': + DesignateCharset(c, G3); + break; +#ifdef KANJI +/* + * ESC $ ( Fn: invoke multi-byte charset, Fn, to G0 + * ESC $ Fn: same as above. (old sequence) + * ESC $ ) Fn: invoke multi-byte charset, Fn, to G1 + * ESC $ * Fn: invoke multi-byte charset, Fn, to G2 + * ESC $ + Fn: invoke multi-byte charset, Fn, to G3 + */ + case '$': + case '$'<<8 | '(': + DesignateCharset(c & 037, G0); + break; + case '$'<<8 | ')': + DesignateCharset(c & 037, G1); + break; + case '$'<<8 | '*': + DesignateCharset(c & 037, G2); + break; + case '$'<<8 | '+': + DesignateCharset(c & 037, G3); + break; +#endif + } +} + +static void +DoCSI(c, intermediate) +int c, intermediate; +{ + register int i, a1 = curr->w_args[0], a2 = curr->w_args[1]; + + if (curr->w_NumArgs > MAXARGS) + curr->w_NumArgs = MAXARGS; + switch (intermediate) + { + case 0: + switch (c) + { + case 'H': + case 'f': + if (a1 < 1) + a1 = 1; + if (curr->w_origin) + a1 += curr->w_top; + if (a1 > rows) + a1 = rows; + if (a2 < 1) + a2 = 1; + if (a2 > cols) + a2 = cols; + GotoPos(--a2, --a1); + curr->w_x = a2; + curr->w_y = a1; + if (curr->w_autoaka) + curr->w_autoaka = a1 + 1; + break; + case 'J': + if (a1 < 0 || a1 > 2) + a1 = 0; + switch (a1) + { + case 0: + ClearToEOS(); + break; + case 1: + ClearFromBOS(); + break; + case 2: + ClearScreen(); + GotoPos(curr->w_x, curr->w_y); + break; + } + break; + case 'K': + if (a1 < 0 || a1 > 2) + a1 %= 3; + switch (a1) + { + case 0: + ClearToEOL(); + break; + case 1: + ClearFromBOL(); + break; + case 2: + ClearFullLine(); + break; + } + break; + case 'A': + CursorUp(a1 ? a1 : 1); + break; + case 'B': + CursorDown(a1 ? a1 : 1); + break; + case 'C': + CursorRight(a1 ? a1 : 1); + break; + case 'D': + CursorLeft(a1 ? a1 : 1); + break; + case 'm': + SelectRendition(); + break; + case 'g': + if (a1 == 0) + curr->w_tabs[curr->w_x] = 0; + else if (a1 == 3) + bzero(curr->w_tabs, cols); + break; + case 'r': + if (!a1) + a1 = 1; + if (!a2) + a2 = rows; + if (a1 < 1 || a2 > rows || a1 >= a2) + break; + curr->w_top = a1 - 1; + curr->w_bot = a2 - 1; + ChangeScrollRegion(curr->w_top, curr->w_bot); + if (curr->w_origin) + { + GotoPos(0, curr->w_top); + curr->w_y = curr->w_top; + curr->w_x = 0; + } + else + { + GotoPos(0, 0); + curr->w_y = curr->w_x = 0; + } + break; + case 's': + SaveCursor(); + break; + case 't': + if (a1 != 8) + break; + a1 = curr->w_args[2]; + if (a1 < 1) + a1 = curr->w_width; + if (a2 < 1) + a2 = curr->w_height; + if (display && D_CWS == NULL) + { + a2 = curr->w_height; + if (D_CZ0 == NULL || (a1 != Z0width && a1 != Z1width)) + a1 = curr->w_width; + } + if (a1 == curr->w_width && a2 == curr->w_height) + break; + ChangeWindowSize(curr, a1, a2, curr->w_histheight); + SetCurr(curr); + if (display) + Activate(0); + break; + case 'u': + RestoreCursor(); + break; + case 'I': + if (!a1) + a1 = 1; + while (a1--) + ForwardTab(); + break; + case 'Z': + if (!a1) + a1 = 1; + while (a1--) + BackwardTab(); + break; + case 'L': + InsertLine(a1 ? a1 : 1); + break; + case 'M': + DeleteLine(a1 ? a1 : 1); + break; + case 'P': + DeleteChar(a1 ? a1 : 1); + break; + case '@': + InsertChar(a1 ? a1 : 1); + break; + case 'h': + ASetMode(1); + break; + case 'l': + ASetMode(0); + break; + case 'i': + if (display && a1 == 5) + PrintStart(); + break; + case 'n': + if (a1 == 5) /* Report terminal status */ + Report("\033[0n", 0, 0); + else if (a1 == 6) /* Report cursor position */ + Report("\033[%d;%dR", curr->w_y + 1, curr->w_x + 1); + break; + case 'c': /* Identify as VT100 */ + if (a1 == 0) + Report("\033[?%d;%dc", 1, 2); + break; + case 'x': /* decreqtparm */ + if (a1 == 0 || a1 == 1) + Report("\033[%d;1;1;112;112;1;0x", a1 + 2, 0); + break; + case 'p': /* obscure code from a 97801 term */ + if (a1 == 6 || a1 == 7) + { + curr->w_curinv = 7 - a1; + CursorVisibility(curr->w_curinv ? -1 : curr->w_curvvis); + } + break; + case 'S': /* obscure code from a 97801 term */ + ScrollRegion(a1 ? a1 : 1); + break; + case 'T': /* obscure code from a 97801 term */ + ScrollRegion(a1 ? -a1 : -1); + break; + } + break; + case '?': + for (a2 = 0; a2 < curr->w_NumArgs; a2++) + { + a1 = curr->w_args[a2]; + debug2("\\E[?%d%c\n",a1,c); + if (c != 'h' && c != 'l') + break; + i = (c == 'h'); + switch (a1) + { + case 1: /* CKM: cursor key mode */ + CursorkeysMode(curr->w_cursorkeys = i); +#ifndef TIOCPKT + NewAutoFlow(curr, !i); +#endif /* !TIOCPKT */ + break; + case 2: /* ANM: ansi/vt52 mode */ + if (i) + { +#ifdef KANJI + if (curr->w_kanji) + break; +#endif + curr->w_charsets[0] = curr->w_charsets[1] = + curr->w_charsets[2] = curr->w_charsets[2] = + curr->w_FontL = curr->w_FontR = ASCII; + curr->w_Charset = 0; + curr->w_CharsetR = 2; + curr->w_ss = 0; + } + break; + case 3: /* COLM: column mode */ + i = (i ? Z0width : Z1width); + if (curr->w_width != i && (display == 0 || (D_CZ0 || D_CWS))) + { + ChangeWindowSize(curr, i, curr->w_height, curr->w_histheight); + SetCurr(curr); /* update rows/cols */ + if (display) + Activate(0); + } + break; + /* case 4: SCLM: scrolling mode */ + case 5: /* SCNM: screen mode */ + /* This should be reverse video. + * Because it is used in some termcaps to emulate + * a visual bell we do this hack here. + * (screen uses \Eg as special vbell sequence) + */ + if (i) + ReverseVideo(1); + else + { + if (display && D_CVR) + ReverseVideo(0); + else + if (curr->w_revvid) + { + if (display && D_VB) + PutStr(D_VB); + else + curr->w_bell = BELL_VISUAL; + } + } + curr->w_revvid = i; + break; + case 6: /* OM: origin mode */ + if ((curr->w_origin = i) != 0) + { + curr->w_y = curr->w_top; + curr->w_x = 0; + } + else + curr->w_y = curr->w_x = 0; + if (display) + GotoPos(curr->w_x, curr->w_y); + break; + case 7: /* AWM: auto wrap mode */ + curr->w_wrap = i; + break; + /* case 8: ARM: auto repeat mode */ + /* case 9: INLM: interlace mode */ + /* case 10: EDM: edit mode */ + /* case 11: LTM: line transmit mode */ + /* case 13: SCFDM: space compression / field delimiting */ + /* case 14: TEM: transmit execution mode */ + /* case 16: EKEM: edit key execution mode */ + case 25: /* TCEM: text cursor enable mode */ + curr->w_curinv = !i; + CursorVisibility(curr->w_curinv ? -1 : curr->w_curvvis); + break; + /* case 40: 132 col enable */ + /* case 42: NRCM: 7bit NRC character mode */ + /* case 44: margin bell enable */ + } + } + break; + case '>': + switch (c) + { + case 'c': /* secondary DA */ + if (a1 == 0) + Report("\033[>%d;%d;0c", 83, nversion); /* 83 == 'S' */ + break; + } + break; + } +} + + +/* + * Store char in mline. Be sure, that w_Font is set correctly! + */ + +static void +SetChar(c) +register int c; +{ + register struct win *p = curr; + register struct mline *ml; + + FixLine(); + ml = &p->w_mlines[p->w_y]; + p->w_rend.image = c; + copy_mchar2mline(&p->w_rend, ml, p->w_x); +} + +static void +StartString(type) +enum string_t type; +{ + curr->w_StringType = type; + curr->w_stringp = curr->w_string; + curr->w_state = ASTR; +} + +static void +SaveChar(c) +int c; +{ + if (curr->w_stringp >= curr->w_string + MAXSTR - 1) + curr->w_state = LIT; + else + *(curr->w_stringp)++ = c; +} + +static void +PrintStart() +{ + int pi[2]; + + if (printcmd == 0 && D_PO == 0) + return; + curr->w_pdisplay = display; + curr->w_stringp = curr->w_string; + curr->w_state = PRIN; + if (printcmd == 0 || curr->w_pdisplay->d_printfd >= 0) + return; + if (pipe(pi)) + { + Msg(errno, "printing pipe"); + return; + } + switch (fork()) + { + case -1: + Msg(errno, "printing fork"); + return; + case 0: + close(0); + dup(pi[0]); + closeallfiles(0); + if (setuid(real_uid) || setgid(real_gid)) + _exit(1); +#ifdef SIGPIPE + signal(SIGPIPE, SIG_DFL); +#endif + execl("/bin/sh", "sh", "-c", printcmd, 0); + _exit(1); + default: + break; + } + close(pi[0]); + curr->w_pdisplay->d_printfd = pi[1]; +} + +static void +PrintChar(c) +int c; +{ + if (curr->w_stringp >= curr->w_string + MAXSTR - 1) + PrintFlush(); + *(curr->w_stringp)++ = c; +} + +static void +PrintFlush() +{ + struct display *odisp = display; + + display = curr->w_pdisplay; + if (display && printcmd) + { + char *bp = curr->w_string; + int len = curr->w_stringp - curr->w_string; + int r; + while (len && display->d_printfd >= 0) + { + r = write(display->d_printfd, bp, len); + if (r <= 0) + { + Msg(errno, "printing aborted"); + close(display->d_printfd); + display->d_printfd = -1; + break; + } + bp += r; + len -= r; + } + } + else if (display && curr->w_stringp > curr->w_string) + { + PutStr(D_PO); + AddStrn(curr->w_string, curr->w_stringp - curr->w_string); + PutStr(D_PF); + Flush(); + } + curr->w_stringp = curr->w_string; + display = odisp; +} + + +void +NewAutoFlow(win, on) +struct win *win; +int on; +{ + debug1("NewAutoFlow: %d\n", on); + SetCurr(win); + if (win->w_flow & FLOW_AUTOFLAG) + win->w_flow = FLOW_AUTOFLAG | (FLOW_AUTO|FLOW_NOW) * on; + else + win->w_flow = (win->w_flow & ~FLOW_AUTO) | FLOW_AUTO * on; + if (display) + SetFlow(win->w_flow & FLOW_NOW); +} + +static void +DesignateCharset(c, n) +int c, n; +{ + curr->w_ss = 0; +#ifdef KANJI + if (c == ('@' & 037)) + c = KANJI; +#endif + if (c == 'B' || c == 'J') + c = ASCII; + if (curr->w_charsets[n] != c) + { + curr->w_charsets[n] = c; + if (curr->w_Charset == n) + SetFont(curr->w_FontL = c); + if (curr->w_CharsetR == n) + curr->w_FontR = c; + } +} + +static void +MapCharset(n) +int n; +{ + curr->w_ss = 0; + if (curr->w_Charset != n) + { + curr->w_Charset = n; + SetFont(curr->w_FontL = curr->w_charsets[n]); + } +} + +static void +MapCharsetR(n) +int n; +{ + curr->w_ss = 0; + if (curr->w_CharsetR != n) + { + curr->w_CharsetR = n; + curr->w_FontR = curr->w_charsets[n]; + } + curr->w_gr = 1; +} + +static void +SaveCursor() +{ + curr->w_saved = 1; + curr->w_Saved_x = curr->w_x; + curr->w_Saved_y = curr->w_y; + curr->w_SavedRend= curr->w_rend; + curr->w_SavedCharset = curr->w_Charset; + curr->w_SavedCharsetR = curr->w_CharsetR; + bcopy((char *) curr->w_charsets, (char *) curr->w_SavedCharsets, + 4 * sizeof(int)); +} + +static void +RestoreCursor() +{ + if (curr->w_saved) + { + GotoPos(curr->w_Saved_x, curr->w_Saved_y); + curr->w_x = curr->w_Saved_x; + curr->w_y = curr->w_Saved_y; + curr->w_rend = curr->w_SavedRend; + bcopy((char *) curr->w_SavedCharsets, (char *) curr->w_charsets, + 4 * sizeof(int)); + curr->w_Charset = curr->w_SavedCharset; + curr->w_CharsetR = curr->w_SavedCharsetR; + curr->w_ss = 0; + curr->w_FontL = curr->w_charsets[curr->w_Charset]; + curr->w_FontR = curr->w_charsets[curr->w_CharsetR]; + SetRendition(&curr->w_rend); + } +} + +static void +BackSpace() +{ + if (curr->w_x > 0) + { + curr->w_x--; + } + else if (curr->w_wrap && curr->w_y > 0) + { + curr->w_x = cols - 1; + curr->w_y--; + } + if (display) + GotoPos(curr->w_x, curr->w_y); +} + +static void +Return() +{ + if (curr->w_x > 0) + { + curr->w_x = 0; + if (display) + GotoPos(curr->w_x, curr->w_y); + } +} + +static void +LineFeed(out_mode) +int out_mode; +{ + /* out_mode: 0=cr+lf no-output, 1=lf, 2=cr+lf */ + if (out_mode != 1) + curr->w_x = 0; + if (curr->w_y != curr->w_bot) /* Don't scroll */ + { + if (curr->w_y < rows-1) + curr->w_y++; + if (out_mode && display) + GotoPos(curr->w_x, curr->w_y); + return; + } + ScrollUpMap(1); + if (curr->w_autoaka > 1) + curr->w_autoaka--; + if (out_mode && display) + { + ScrollV(0, curr->w_top, cols - 1, curr->w_bot, 1); + GotoPos(curr->w_x, curr->w_y); + } +} + +static void +ReverseLineFeed() +{ + if (curr->w_y == curr->w_top) + { + ScrollDownMap(1); + if (!display) + return; + ScrollV(0, curr->w_top, cols - 1, curr->w_bot, -1); + GotoPos(curr->w_x, curr->w_y); + } + else if (curr->w_y > 0) + CursorUp(1); +} + +static void +InsertAChar(c) +int c; +{ + register int y = curr->w_y, x = curr->w_x; + + if (x == cols) + x--; + save_mline(&curr->w_mlines[y], cols); + if (cols - x - 1 > 0) + bcopy_mline(&curr->w_mlines[y], x, x + 1, cols - x - 1); + SetChar(c); + curr->w_x = x + 1; + if (!display) + return; + if (D_CIC || D_IC || D_IM) + { + InsertMode(curr->w_insert); + INSERTCHAR(c); + if (y == D_bot) + D_lp_missing = 0; + } + else + UpdateLine(&mline_old, y, x, cols - 1); +} + +static void +InsertChar(n) +int n; +{ + register int y = curr->w_y, x = curr->w_x; + + if (n <= 0) + return; + if (x == cols) + x--; + save_mline(&curr->w_mlines[y], cols); + if (n >= cols - x) + n = cols - x; + else + bcopy_mline(&curr->w_mlines[y], x, x + n, cols - x - n); + + ClearInLine(y, x, x + n - 1); + if (!display) + return; + ScrollH(y, x, curr->w_width - 1, -n, &mline_old); + GotoPos(x, y); +} + +static void +DeleteChar(n) +int n; +{ + register int y = curr->w_y, x = curr->w_x; + + if (x == cols) + x--; + save_mline(&curr->w_mlines[y], cols); + + if (n >= cols - x) + n = cols - x; + else + bcopy_mline(&curr->w_mlines[y], x + n, x, cols - x - n); + ClearInLine(y, cols - n, cols - 1); + if (!display) + return; + ScrollH(y, x, curr->w_width - 1, n, &mline_old); + GotoPos(x, y); +} + +static void +DeleteLine(n) +int n; +{ + register int old = curr->w_top; + + if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot) + return; + if (n > curr->w_bot - curr->w_y + 1) + n = curr->w_bot - curr->w_y + 1; + curr->w_top = curr->w_y; + ScrollUpMap(n); + curr->w_top = old; + if (!display) + return; + ScrollV(0, curr->w_y, cols - 1, curr->w_bot, n); + GotoPos(curr->w_x, curr->w_y); +} + +static void +InsertLine(n) +int n; +{ + register int old = curr->w_top; + + if (curr->w_y < curr->w_top || curr->w_y > curr->w_bot) + return; + if (n > curr->w_bot - curr->w_y + 1) + n = curr->w_bot - curr->w_y + 1; + curr->w_top = curr->w_y; + ScrollDownMap(n); + curr->w_top = old; + if (!display) + return; + ScrollV(0, curr->w_y, cols - 1, curr->w_bot, -n); + GotoPos(curr->w_x, curr->w_y); +} + +static void +ScrollRegion(n) +int n; +{ + if (n > 0) + ScrollUpMap(n); + else + ScrollDownMap(-n); + if (!display) + return; + ScrollV(0, curr->w_top, cols - 1, curr->w_bot, n); + GotoPos(curr->w_x, curr->w_y); +} + +static void +ScrollUpMap(n) +int n; +{ + char tmp[256 * sizeof(struct mline)]; + register int i, cnt1, cnt2; + struct mline *ml; +#ifdef COPY_PASTE + register int ii; +#endif + + i = curr->w_top + n; + cnt1 = n * sizeof(struct mline); + cnt2 = (curr->w_bot - i + 1) * sizeof(struct mline); +#ifdef COPY_PASTE + for(ii = curr->w_top; ii < i; ii++) + AddLineToHist(curr, &curr->w_mlines[ii]); +#endif + ml = curr->w_mlines + i; + for (i = n; i; --i) + { + --ml; + clear_mline(ml, 0, cols + 1); + } + Scroll((char *) ml, cnt1, cnt2, tmp); +} + +static void +ScrollDownMap(n) +int n; +{ + char tmp[256 * sizeof(struct mline)]; + register int i, cnt1, cnt2; + struct mline *ml; + + i = curr->w_top; + cnt1 = (curr->w_bot - i - n + 1) * sizeof(struct mline); + cnt2 = n * sizeof(struct mline); + ml = curr->w_mlines + i; + Scroll((char *) ml, cnt1, cnt2, tmp); + for (i = n; i; --i) + { + clear_mline(ml, 0, cols + 1); + ml++; + } +} + +static void +Scroll(cp, cnt1, cnt2, tmp) +char *cp, *tmp; +int cnt1, cnt2; +{ + if (!cnt1 || !cnt2) + return; + if (cnt1 <= cnt2) + { + bcopy(cp, tmp, cnt1); + bcopy(cp + cnt1, cp, cnt2); + bcopy(tmp, cp + cnt2, cnt1); + } + else + { + bcopy(cp + cnt1, tmp, cnt2); + bcopy(cp, cp + cnt2, cnt1); + bcopy(tmp, cp, cnt2); + } +} + +static void +ForwardTab() +{ + register int x = curr->w_x; + + if (x == cols) + { + LineFeed(2); + x = 0; + } + if (curr->w_tabs[x] && x < cols - 1) + x++; + while (x < cols - 1 && !curr->w_tabs[x]) + x++; + GotoPos(x, curr->w_y); + curr->w_x = x; +} + +static void +BackwardTab() +{ + register int x = curr->w_x; + + if (curr->w_tabs[x] && x > 0) + x--; + while (x > 0 && !curr->w_tabs[x]) + x--; + GotoPos(x, curr->w_y); + curr->w_x = x; +} + +static void +ClearScreen() +{ + register int i; + register struct mline *ml = curr->w_mlines; + + for (i = 0; i < rows; ++i) + { +#ifdef COPY_PASTE + AddLineToHist(curr, ml); +#endif + clear_mline(ml, 0, cols + 1); + ml++; + } + if (display) + ClearDisplay(); +} + +static void +ClearFromBOS() +{ + register int n, y = curr->w_y, x = curr->w_x; + + if (display) + Clear(0, 0, 0, cols - 1, x, y, 1); + for (n = 0; n < y; ++n) + ClearInLine(n, 0, cols - 1); + ClearInLine(y, 0, x); + RestorePosRendition(); +} + +static void +ClearToEOS() +{ + register int n, y = curr->w_y, x = curr->w_x; + + if (x == 0 && y == 0) + { + ClearScreen(); + return; + } + if (display) + Clear(x, y, 0, cols - 1, cols - 1, rows - 1, 1); + ClearInLine(y, x, cols - 1); + for (n = y + 1; n < rows; n++) + ClearInLine(n, 0, cols - 1); + RestorePosRendition(); +} + +static void +ClearFullLine() +{ + register int y = curr->w_y; + + if (display) + Clear(0, y, 0, cols - 1, cols - 1, y, 1); + ClearInLine(y, 0, cols - 1); + RestorePosRendition(); +} + +static void +ClearToEOL() +{ + register int y = curr->w_y, x = curr->w_x; + + if (display) + Clear(x, y, 0, cols - 1, cols - 1, y, 1); + ClearInLine(y, x, cols - 1); + RestorePosRendition(); +} + +static void +ClearFromBOL() +{ + register int y = curr->w_y, x = curr->w_x; + + if (display) + Clear(0, y, 0, cols - 1, x, y, 1); + ClearInLine(y, 0, x); + RestorePosRendition(); +} + +static void +ClearInLine(y, x1, x2) +int y, x1, x2; +{ + register int n; + + if (x1 == cols) + x1--; + if (x2 == cols - 1) + x2++; + if ((n = x2 - x1 + 1) != 0) + clear_mline(&curr->w_mlines[y], x1, n); +} + +static void +CursorRight(n) +register int n; +{ + register int x = curr->w_x; + + if (x == cols) + { + LineFeed(2); + x = 0; + } + if ((curr->w_x += n) >= cols) + curr->w_x = cols - 1; + GotoPos(curr->w_x, curr->w_y); +} + +static void +CursorUp(n) +register int n; +{ + if (curr->w_y < curr->w_top) /* if above scrolling rgn, */ + { + if ((curr->w_y -= n) < 0) /* ignore its limits */ + curr->w_y = 0; + } + else + if ((curr->w_y -= n) < curr->w_top) + curr->w_y = curr->w_top; + GotoPos(curr->w_x, curr->w_y); +} + +static void +CursorDown(n) +register int n; +{ + if (curr->w_y > curr->w_bot) /* if below scrolling rgn, */ + { + if ((curr->w_y += n) > rows - 1) /* ignore its limits */ + curr->w_y = rows - 1; + } + else + if ((curr->w_y += n) > curr->w_bot) + curr->w_y = curr->w_bot; + GotoPos(curr->w_x, curr->w_y); +} + +static void +CursorLeft(n) +register int n; +{ + if ((curr->w_x -= n) < 0) + curr->w_x = 0; + GotoPos(curr->w_x, curr->w_y); +} + +static void +ASetMode(on) +int on; +{ + register int i; + + for (i = 0; i < curr->w_NumArgs; ++i) + { + switch (curr->w_args[i]) + { + case 4: + curr->w_insert = on; + InsertMode(on); + break; + case 20: + curr->w_autolf = on; + break; + case 34: + curr->w_curvvis = !on; + CursorVisibility(curr->w_curinv ? -1 : curr->w_curvvis); + break; + default: + break; + } + } +} + +static char rendlist[] = +{ + (1 << NATTR), A_BD, A_DI, A_SO, A_US, A_BL, 0, A_RV, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, ~(A_BD|A_SO|A_DI), ~A_SO, ~A_US, ~A_BL, 0, ~A_RV +}; + +static void +SelectRendition() +{ + register int j, i = 0, a = curr->w_rend.attr; +#ifdef COLOR + register int c = curr->w_rend.color; +#endif + + do + { + j = curr->w_args[i]; +#ifdef COLOR + if (j >= 30 && j <= 39) + c = (c & 0xf0) | (39 - j); + else if (j >= 40 && j <= 49) + c = (c & 0x0f) | ((49 - j) << 4); + if (j == 0) + c = 0; +#endif + if (j < 0 || j >= (sizeof(rendlist)/sizeof(*rendlist))) + continue; + j = rendlist[j]; + if (j & (1 << NATTR)) + a &= j; + else + a |= j; + } + while (++i < curr->w_NumArgs); + if (curr->w_rend.attr != a) + SetAttr(curr->w_rend.attr = a); +#ifdef COLOR + if (curr->w_rend.color != c) + SetColor(curr->w_rend.color = c); +#endif +} + +static void +FillWithEs() +{ + register int i; + register char *p, *ep; + + curr->w_y = curr->w_x = 0; + for (i = 0; i < rows; ++i) + { + clear_mline(&curr->w_mlines[i], 0, cols + 1); + p = curr->w_mlines[i].image; + ep = p + cols; + while (p < ep) + *p++ = 'E'; + } + if (display) + Redisplay(0); +} + + +static void +UpdateLine(oml, y, from, to) +struct mline *oml; +int from, to, y; +{ + ASSERT(display); + DisplayLine(oml, &curr->w_mlines[y], y, from, to); + RestorePosRendition(); +} + + +static void +CheckLP(n_ch) +int n_ch; +{ + register int x; + register struct mline *ml; + + ASSERT(display); + ml = &curr->w_mlines[D_bot]; + x = cols - 1; + + curr->w_rend.image = n_ch; + + D_lpchar = curr->w_rend; + D_lp_missing = 0; + + if (cmp_mchar_mline(&curr->w_rend, ml, x)) + return; + if (!cmp_mchar(&mchar_blank, &curr->w_rend)) /* is new not blank */ + D_lp_missing = 1; + if (!cmp_mchar_mline(&mchar_blank, ml, x)) /* is old char not blank? */ + { + /* old char not blank, new blank, try to delete */ + if (D_UT) + SetRendition(&mchar_null); + if (D_CE) + PutStr(D_CE); + else if (D_DC) + PutStr(D_DC); + else if (D_CDC) + CPutStr(D_CDC, 1); + else + D_lp_missing = 1; + } +} + +/* + * Ugly autoaka hack support: + * ChangeAKA() sets a new aka + * FindAKA() searches for an autoaka match + */ + +void +ChangeAKA(p, s, l) +struct win *p; +char *s; +int l; +{ + if (l > 20) + l = 20; + strncpy(p->w_akachange, s, l); + p->w_akachange[l] = 0; + p->w_title = p->w_akachange; + if (p->w_akachange != p->w_akabuf) + if (p->w_akachange[0] == 0 || p->w_akachange[-1] == ':') + p->w_title = p->w_akabuf + strlen(p->w_akabuf) + 1; + + /* yucc */ + if (p->w_hstatus) + { + display = p->w_display; + if (display) + RefreshStatus(); + } +} + +static void +FindAKA() +{ + register char *cp, *line; + register struct win *wp = curr; + register int len = strlen(wp->w_akabuf); + int y; + + y = (wp->w_autoaka > 0 && wp->w_autoaka <= wp->w_height) ? wp->w_autoaka - 1 : wp->w_y; + cols = wp->w_width; + try_line: + cp = line = wp->w_mlines[y].image; + if (wp->w_autoaka > 0 && *wp->w_akabuf != '\0') + { + for (;;) + { + if (cp - line >= cols - len) + { + if (++y == wp->w_autoaka && y < rows) + goto try_line; + return; + } + if (strncmp(cp, wp->w_akabuf, len) == 0) + break; + cp++; + } + cp += len; + } + for (len = cols - (cp - line); len && *cp == ' '; len--, cp++) + ; + if (len) + { + if (wp->w_autoaka > 0 && (*cp == '!' || *cp == '%' || *cp == '^')) + wp->w_autoaka = -1; + else + wp->w_autoaka = 0; + line = cp; + while (len && *cp != ' ') + { + if (*cp++ == '/') + line = cp; + len--; + } + ChangeAKA(wp, line, cp - line); + } + else + wp->w_autoaka = 0; +} + +void +SetCurr(wp) +struct win *wp; +{ + curr = wp; + if (curr == 0) + return; + cols = curr->w_width; + rows = curr->w_height; + display = curr->w_active ? curr->w_display : 0; +} + +static void +RestorePosRendition() +{ + if (!display) + return; + GotoPos(curr->w_x, curr->w_y); + SetRendition(&curr->w_rend); +} + +/* Send a terminal report as if it were typed. */ +static void +Report(fmt, n1, n2) +char *fmt; +int n1, n2; +{ + register int len; + char rbuf[40]; + + sprintf(rbuf, fmt, n1, n2); + len = strlen(rbuf); + + if ((unsigned)(curr->w_inlen + len) <= sizeof(curr->w_inbuf)) + { + bcopy(rbuf, curr->w_inbuf + curr->w_inlen, len); + curr->w_inlen += len; + } +} + +#ifdef COPY_PASTE +static void +AddLineToHist(wp, ml) +struct win *wp; +struct mline *ml; +{ + register char *q, *o; + struct mline *hml; + + if (wp->w_histheight == 0) + return; + hml = &wp->w_hlines[wp->w_histidx]; + q = ml->image; ml->image = hml->image; hml->image = q; + + q = ml->attr; o = hml->attr; hml->attr = q; ml->attr = null; + if (o != null) + free(o); + + q = ml->font; o = hml->font; hml->font = q; ml->font = null; + if (o != null) + free(o); + +#ifdef COLOR + q = ml->color; o = hml->color; hml->color = q; ml->color = null; + if (o != null) + free(o); +#endif + + if (++wp->w_histidx >= wp->w_histheight) + wp->w_histidx = 0; +} +#endif + |