diff options
Diffstat (limited to 'ansi.c')
-rw-r--r-- | ansi.c | 2046 |
1 files changed, 1045 insertions, 1001 deletions
@@ -25,7 +25,6 @@ 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> @@ -33,27 +32,30 @@ RCS_ID("$Id: ansi.c,v 1.22 1994/05/31 12:31:25 mlschroe Exp $ FAU") #include "config.h" #include "screen.h" +#include "braille.h" #include "extern.h" +#include "logfile.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; +extern int nversion; /* numerical version of screen */ +extern int log_flush, logtstamp_on, logtstamp_after; +extern char *logtstamp_string; +extern char *captionstring; +extern char *hstatusstring; +#ifdef COPY_PASTE +extern int compacthist; +#endif int Z0width, Z1width; /* widths for Z0/Z1 switching */ +/* globals set in WriteString */ 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; +int use_hardstatus = 1; /* display status line in hs */ char *printcmd = 0; char *blank; /* line filled with spaces */ @@ -67,25 +69,48 @@ 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)); +/* keep string_t and string_t_string in sync! */ +static char *string_t_string[] = +{ + "NONE", + "DCS", /* Device control string */ + "OSC", /* Operating system command */ + "APC", /* Application program command */ + /* - used for status change */ + "PM", /* Privacy message */ + "AKA", /* title for current screen */ + "GM", /* Global message to every display */ + "STATUS" /* User hardstatus line */ +}; + +/* keep state_t and state_t_string in sync! */ +static char *state_t_string[] = +{ + "LIT", /* Literal input */ + "ESC", /* Start of escape sequence */ + "ASTR", /* Start of control string */ + "STRESC", /* ESC seen in control string */ + "CSI", /* Reading arguments in "CSI Pn ;...*/ + "PRIN", /* Printer mode */ + "PRINESC", /* ESC seen in printer mode */ + "PRINCSI", /* CSI seen in printer mode */ + "PRIN4" /* CSI 4 seen in printer mode */ +}; + 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 StringStart __P((enum string_t)); +static void StringChar __P((int)); +static int StringEnd __P((void)); static void PrintStart __P((void)); static void PrintChar __P((int)); static void PrintFlush __P((void)); +#ifdef FONT static void DesignateCharset __P((int, int)); static void MapCharset __P((int)); static void MapCharsetR __P((int)); +#endif static void SaveCursor __P((void)); static void RestoreCursor __P((void)); static void BackSpace __P((void)); @@ -97,18 +122,13 @@ 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 ClearLineRegion __P((int, int)); static void CursorRight __P((int)); static void CursorUp __P((int)); static void CursorDown __P((int)); @@ -117,271 +137,28 @@ 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; - } +static void LogString __P((struct win *, char *, int)); +static void WReverseVideo __P((struct win *, int)); +static void MFixLine __P((struct win *, int, struct mchar *)); +static void MScrollH __P((struct win *, int, int, int, int)); +static void MScrollV __P((struct win *, int, int, int)); +static void MClear __P((struct win *, int, int, int, int)); +static void MInsChar __P((struct win *, struct mchar *, int, int)); +static void MPutChar __P((struct win *, struct mchar *, int, int)); +static void MWrapChar __P((struct win *, struct mchar *, int, int, int, int)); +static int WindowChangedCheck __P((char *, int, int *)); - 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; +ResetAnsiState(p) +struct win *p; { - 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); + p->w_state = LIT; + p->w_StringType = NONE; } void @@ -409,16 +186,47 @@ register struct win *p; for (i = 8; i < p->w_width; i += 8) p->w_tabs[i] = 1; p->w_rend = mchar_null; +#ifdef FONT ResetCharsets(p); +#endif } -#ifdef KANJI +/* adds max 22 bytes */ +int +GetAnsiStatus(w, buf) +struct win *w; +char *buf; +{ + char *p = buf; + + if (w->w_state == LIT) + return 0; + + strcpy(p, state_t_string[w->w_state]); + p += strlen(p); + if (w->w_intermediate) + { + *p++ = '-'; + if (w->w_intermediate > 0xff) + p += AddXChar(p, w->w_intermediate >> 8); + p += AddXChar(p, w->w_intermediate & 0xff); + } + if (w->w_state == ASTR || w->w_state == STRESC) + sprintf(p, "-%s", string_t_string[w->w_StringType]); + p += strlen(p); + return p - buf; +} + + +#ifdef FONT + +# ifdef KANJI static char *kanjicharsets[3] = { "BBBB02", /* jis */ "B\002IB01", /* euc */ "BIBB01" /* sjis */ }; -#endif +# endif void ResetCharsets(p) @@ -458,50 +266,22 @@ char *s; 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 + * - writes logfiles, + * - sets timestamp and flags activity in window. + * - record program output in window scrollback + * - translate program output for the display and put it into the obuf. + * + * Output is only supressed, where obuf is beyond maximum and the flag + * nonblock is set. Then we set nonblock from 1 to 2 and output a '~' + * character instead. nonblock should be reset to 1 by a successfull + * write. Where nonblock isn't set, the obufmax is ignored. */ void WriteString(wp, buf, len) @@ -509,42 +289,52 @@ struct win *wp; register char *buf; register int len; { - register int c, font; + register int c; +#ifdef FONT + register int font; +#endif + struct canvas *cv; 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 (wp->w_log) + LogString(wp, buf, len); + + /* set global variables (yuck!) */ + curr = wp; + cols = curr->w_width; + rows = curr->w_height; + + /* The status should be already gone, so this is "Just in Case" */ + for (cv = wp->w_layer.l_cvlist; cv; cv = cv->c_lnext) { - if (D_status && !(use_hardstatus && D_HS)) + display = cv->c_display; + if (D_status == STATUS_ON_WIN) RemoveStatus(); - } - else - { - if (curr->w_tstamp.seconds) - curr->w_tstamp.lastio = Now; - - if (curr->w_monitor == MON_ON || curr->w_monitor == MON_DONE) + if (D_nonblock == 1 && (D_obufp - D_obuf > D_obufmax)) { - debug2("ACTIVITY %d %d\n", curr->w_monitor, curr->w_bell); - curr->w_monitor = MON_FOUND; + /* one last surprising '~' means: lost data */ + AddChar('~'); + /* private flag that prevents more output */ + D_nonblock = 2; } } + if (curr->w_silence) + SetTimeout(&curr->w_silenceev, curr->w_silencewait * 1000); + + if (curr->w_monitor == MON_ON) + { + debug2("ACTIVITY %d %d\n", curr->w_monitor, curr->w_bell); + curr->w_monitor = MON_FOUND; + } + do { c = (unsigned char)*buf++; +#ifdef FONT curr->w_rend.font = curr->w_FontL; /* Default: GL */ +#endif /* The next part is only for speedup * (therefore no mchars are used) */ @@ -553,65 +343,40 @@ register int len; 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) + ((c & 0x80) == 0 || ((c >= 0xa0 || !curr->w_c1) && !curr->w_gr)) && !curr->w_ss && + !curr->w_insert && curr->w_x < cols - 1) { register int currx; - register char *imp, *atp, *fop, at, fo; + register char *imp, *atp, at; +#ifdef FONT + register char *fop, fo; +#endif #ifdef COLOR register char *cop, co; #endif - register char **xtable = 0; - register char *c0tab = 0; if (c == '\177') continue; - FixLine(); + MFixLine(curr, curr->w_y, &curr->w_rend); 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; +#ifdef FONT + fop = curr->w_mlines[curr->w_y].font + currx; fo = curr->w_rend.font; +#endif #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; +#ifdef FONT *fop++ = fo; +#endif #ifdef COLOR *cop++ = co; #endif @@ -624,9 +389,12 @@ skip: if (--len == 0) if (c < ' ' || ((c & 0x80) && ((c < 0xa0 && curr->w_c1) || curr->w_gr))) break; } - curr->w_x = currx; - if (display) - D_x = currx; + currx -= curr->w_x; + if (currx > 0) + { + LPutStr(&curr->w_layer, imp - currx, currx, &curr->w_rend, curr->w_x, curr->w_y); + curr->w_x += currx; + } if (len == 0) break; } @@ -700,10 +468,11 @@ skip: if (--len == 0) break; } /* special xterm hack: accept SetStatus sequence. Yucc! */ + /* allow ^E for title escapes */ if (!(curr->w_StringType == OSC && c < ' ' && c != '\005')) if (!curr->w_c1 || c != ('\\' ^ 0xc0)) { - SaveChar(c); + StringChar(c); break; } c = '\\'; @@ -712,76 +481,31 @@ skip: if (--len == 0) switch (c) { case '\\': - curr->w_state = LIT; - *curr->w_stringp = '\0'; - switch (curr->w_StringType) + if (StringEnd() == 0 || len <= 1) + break; + /* check if somewhere a status is displayed */ + for (cv = curr->w_layer.l_cvlist; cv; cv = cv->c_lnext) { - 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) + display = cv->c_display; + if (D_status == STATUS_ON_WIN) 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; + } + if (cv) + { + if (len > IOSIZE + 1) + len = IOSIZE + 1; + curr->w_outlen = len - 1; + bcopy(buf, curr->w_outbuf, len - 1); + return; /* wait till status is gone */ } break; case '\033': - SaveChar('\033'); + StringChar('\033'); break; default: curr->w_state = ASTR; - SaveChar('\033'); - SaveChar(c); + StringChar('\033'); + StringChar(c); break; } break; @@ -795,23 +519,23 @@ skip: if (--len == 0) curr->w_state = CSI; break; case ']': - StartString(OSC); + StringStart(OSC); break; case '_': - StartString(APC); + StringStart(APC); break; case 'P': - StartString(DCS); + StringStart(DCS); break; case '^': - StartString(PM); + StringStart(PM); break; case '!': - StartString(GM); + StringStart(GM); break; case '"': case 'k': - StartString(AKA); + StringStart(AKA); break; default: if (Special(c)) @@ -823,12 +547,14 @@ skip: if (--len == 0) if (c >= ' ' && c <= '/') { if (curr->w_intermediate) + { #ifdef KANJI - if (curr->w_intermediate == '$') - c |= '$' << 8; - else + if (curr->w_intermediate == '$') + c |= '$' << 8; + else #endif - c = -1; + c = -1; + } curr->w_intermediate = c; } else if (c >= '0' && c <= '~') @@ -879,14 +605,16 @@ skip: if (--len == 0) break; case LIT: default: +#ifdef KANJI + if (c <= ' ' || c == 0x7f || (c >= 0x80 && c < 0xa0 && curr->w_c1)) + curr->w_mbcs = 0; +#endif 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; } @@ -902,13 +630,11 @@ skip: if (--len == 0) case 0xc0 ^ 'E': case 0xc0 ^ 'H': case 0xc0 ^ 'M': - case 0xc0 ^ 'N': - case 0xc0 ^ 'O': + case 0xc0 ^ 'N': /* SS2 */ + case 0xc0 ^ 'O': /* SS3 */ 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; @@ -917,7 +643,7 @@ skip: if (--len == 0) curr->w_state = CSI; break; case 0xc0 ^ 'P': - StartString(DCS); + StringStart(DCS); break; default: break; @@ -925,8 +651,9 @@ skip: if (--len == 0) break; } +#ifdef FONT font = curr->w_rend.font = (c >= 0x80 ? curr->w_FontR : curr->w_FontL); -#ifdef KANJI +# ifdef KANJI if (font == KANA && curr->w_kanji == SJIS && curr->w_mbcs == 0) { /* Lets see if it is the first byte of a kanji */ @@ -938,6 +665,8 @@ skip: if (--len == 0) break; } } + if (font == KANJI && c == ' ') + font = curr->w_rend.font = 0; if (font == KANJI || curr->w_mbcs) { int t = c; @@ -985,108 +714,93 @@ skip: if (--len == 0) curr->w_mbcs = t; } kanjiloop: -#endif +# endif if (curr->w_gr) { c &= 0x7f; if (c < ' ') /* this is ugly but kanji support */ goto tryagain; /* prevents nicer programming */ } +#endif /* FONT */ if (c == '\177') break; - if (display) - SetRendition(&curr->w_rend); + curr->w_rend.image = c; if (curr->w_x < cols - 1) { if (curr->w_insert) InsertAChar(c); else { - if (display) - PUTCHAR(c); - SetChar(c); + MPutChar(curr, &curr->w_rend, curr->w_x, curr->w_y); + LPutChar(&curr->w_layer, &curr->w_rend, curr->w_x, curr->w_y); 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++; - } + MPutChar(curr, &curr->w_rend, curr->w_x, curr->w_y); + LPutChar(&curr->w_layer, &curr->w_rend, curr->w_x, curr->w_y); + if (curr->w_wrap) + curr->w_x++; } - else /* curr->w_x > cols - 1 */ + else { - 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; - } + MWrapChar(curr, &curr->w_rend, curr->w_y, curr->w_top, curr->w_bot, curr->w_insert); + LWrapChar(&curr->w_layer, &curr->w_rend, curr->w_y, curr->w_top, curr->w_bot, curr->w_insert); + if (curr->w_y != curr->w_bot && curr->w_y != curr->w_height - 1) + curr->w_y++; + curr->w_x = 1; } -#ifdef KANJI +#ifdef FONT +# ifdef KANJI if (curr->w_mbcs) { c = curr->w_mbcs; curr->w_mbcs = 0; goto kanjiloop; /* what a hack! */ } -#endif +# 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_rend.font = curr->w_FontL; + LSetRendition(&curr->w_layer, &curr->w_rend); curr->w_ss = 0; } +#endif /* FONT */ break; } } while (--len); - curr->w_outlen = 0; - if (curr->w_state == PRIN) + if (!printcmd && curr->w_state == PRIN) PrintFlush(); } +static void +LogString(p, buf, len) +struct win *p; +char *buf; +int len; +{ + if (!p->w_log) + return; + if (logtstamp_on && p->w_logsilence >= logtstamp_after * 2) + { + char *t = MakeWinMsg(logtstamp_string, p, '%'); + logfwrite(p->w_log, t, strlen(t)); /* long time no write */ + } + p->w_logsilence = 0; + if (logfwrite(p->w_log, buf, len) < 1) + { + WMsg(p, errno, "Error writing logfile"); + logfclose(p->w_log); + p->w_log = 0; + } + if (!log_flush) + logfflush(p->w_log); +} + static int Special(c) register int c; @@ -1105,30 +819,19 @@ register int c; 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); - } - } + WBell(curr, visual_bell); return 1; case '\t': ForwardTab(); return 1; +#ifdef FONT case '\017': /* SI */ MapCharset(G0); return 1; case '\016': /* SO */ MapCharset(G1); return 1; +#endif } return 0; } @@ -1167,24 +870,30 @@ int c, intermediate; case 'c': ClearScreen(); ResetWindow(curr); + LKeypadMode(&curr->w_layer, 0); + LCursorkeysMode(&curr->w_layer, 0); +#ifndef TIOCPKT + NewAutoFlow(curr, 1); +#endif + /* XXX SetRendition(&mchar_null); InsertMode(0); - KeypadMode(0); - CursorkeysMode(0); ChangeScrollRegion(0, rows - 1); + */ break; case '=': - KeypadMode(curr->w_keypad = 1); + LKeypadMode(&curr->w_layer, curr->w_keypad = 1); #ifndef TIOCPKT NewAutoFlow(curr, 0); #endif /* !TIOCPKT */ break; case '>': - KeypadMode(curr->w_keypad = 0); + LKeypadMode(&curr->w_layer, curr->w_keypad = 0); #ifndef TIOCPKT NewAutoFlow(curr, 1); #endif /* !TIOCPKT */ break; +#ifdef FONT case 'n': /* LS2 */ MapCharset(G2); break; @@ -1194,6 +903,7 @@ int c, intermediate; case '~': MapCharsetR(G1); /* LS1R */ break; + /* { */ case '}': MapCharsetR(G2); /* LS2R */ break; @@ -1203,7 +913,7 @@ int c, intermediate; 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]; + curr->w_FontR = curr->w_FontL = curr->w_charsets[curr->w_ss = G2]; else curr->w_ss = 0; break; @@ -1214,13 +924,9 @@ int c, intermediate; else curr->w_ss = 0; break; +#endif /* FONT */ 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); + WBell(curr, 1); break; } break; @@ -1232,6 +938,7 @@ int c, intermediate; break; } break; +#ifdef FONT case '(': DesignateCharset(c, G0); break; @@ -1244,7 +951,7 @@ int c, intermediate; case '+': DesignateCharset(c, G3); break; -#ifdef KANJI +# ifdef KANJI /* * ESC $ ( Fn: invoke multi-byte charset, Fn, to G0 * ESC $ Fn: same as above. (old sequence) @@ -1265,7 +972,8 @@ int c, intermediate; case '$'<<8 | '+': DesignateCharset(c & 037, G3); break; -#endif +# endif +#endif /* FONT */ } } @@ -1294,7 +1002,7 @@ int c, intermediate; a2 = 1; if (a2 > cols) a2 = cols; - GotoPos(--a2, --a1); + LGotoPos(&curr->w_layer, --a2, --a1); curr->w_x = a2; curr->w_y = a1; if (curr->w_autoaka) @@ -1313,7 +1021,7 @@ int c, intermediate; break; case 2: ClearScreen(); - GotoPos(curr->w_x, curr->w_y); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); break; } break; @@ -1323,16 +1031,20 @@ int c, intermediate; switch (a1) { case 0: - ClearToEOL(); + ClearLineRegion(curr->w_x, cols - 1); break; case 1: - ClearFromBOL(); + ClearLineRegion(0, curr->w_x); break; case 2: - ClearFullLine(); + ClearLineRegion(0, cols - 1); break; } break; + case 'X': + a1 = curr->w_x + (a1 ? a1 - 1 : 0); + ClearLineRegion(curr->w_x, a1 < cols ? a1 : cols - 1); + break; case 'A': CursorUp(a1 ? a1 : 1); break; @@ -1345,6 +1057,27 @@ int c, intermediate; case 'D': CursorLeft(a1 ? a1 : 1); break; + case 'E': + curr->w_x = 0; + CursorDown(a1 ? a1 : 1); /* positions cursor */ + break; + case 'F': + curr->w_x = 0; + CursorUp(a1 ? a1 : 1); /* positions cursor */ + break; + case 'G': + case '`': /* HPA */ + curr->w_x = a1 ? a1 - 1 : 0; + if (curr->w_x >= cols) + curr->w_x = cols - 1; + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); + break; + case 'd': /* VPA */ + curr->w_y = a1 ? a1 - 1 : 0; + if (curr->w_y >= rows) + curr->w_y = rows - 1; + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); + break; case 'm': SelectRendition(); break; @@ -1363,18 +1096,15 @@ int c, intermediate; break; curr->w_top = a1 - 1; curr->w_bot = a2 - 1; - ChangeScrollRegion(curr->w_top, curr->w_bot); + /* 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; - } + curr->w_y = curr->w_x = 0; + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); break; case 's': SaveCursor(); @@ -1387,18 +1117,9 @@ int c, intermediate; 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); + WChangeSize(curr, a1, a2); + cols = curr->w_width; + rows = curr->w_height; break; case 'u': RestoreCursor(); @@ -1433,15 +1154,9 @@ int c, intermediate; case 'l': ASetMode(0); break; - case 'i': - { - struct display *odisplay = display; - if (display == 0 && displays && displays->d_next == 0) - display = displays; - if (display && a1 == 5) - PrintStart(); - display = odisplay; - } + case 'i': /* MC Media Control */ + if (a1 == 5) + PrintStart(); break; case 'n': if (a1 == 5) /* Report terminal status */ @@ -1461,13 +1176,14 @@ int c, intermediate; if (a1 == 6 || a1 == 7) { curr->w_curinv = 7 - a1; - CursorVisibility(curr->w_curinv ? -1 : curr->w_curvvis); + LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis); } break; - case 'S': /* obscure code from a 97801 term */ + case 'S': /* code from a 97801 term / DEC vt400 */ ScrollRegion(a1 ? a1 : 1); break; - case 'T': /* obscure code from a 97801 term */ + case 'T': /* code from a 97801 term / DEC vt400 */ + case '^': /* SD as per ISO 6429 */ ScrollRegion(a1 ? -a1 : -1); break; } @@ -1483,7 +1199,7 @@ int c, intermediate; switch (a1) { case 1: /* CKM: cursor key mode */ - CursorkeysMode(curr->w_cursorkeys = i); + LCursorkeysMode(&curr->w_layer, curr->w_cursorkeys = i); #ifndef TIOCPKT NewAutoFlow(curr, !i); #endif /* !TIOCPKT */ @@ -1491,50 +1207,30 @@ int c, intermediate; case 2: /* ANM: ansi/vt52 mode */ if (i) { -#ifdef KANJI +#ifdef FONT +# ifdef KANJI if (curr->w_kanji) break; -#endif +# 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; +#endif } 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); - } + WChangeSize(curr, i, curr->w_height); + cols = curr->w_width; + rows = curr->w_height; 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; - } - } + if (i != curr->w_revvid) + WReverseVideo(curr, i); curr->w_revvid = i; break; case 6: /* OM: origin mode */ @@ -1545,8 +1241,7 @@ int c, intermediate; } else curr->w_y = curr->w_x = 0; - if (display) - GotoPos(curr->w_x, curr->w_y); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); break; case 7: /* AWM: auto wrap mode */ curr->w_wrap = i; @@ -1558,13 +1253,21 @@ int c, intermediate; /* case 13: SCFDM: space compression / field delimiting */ /* case 14: TEM: transmit execution mode */ /* case 16: EKEM: edit key execution mode */ + /* case 18: PFF: Printer term form feed */ + /* case 19: PEX: Printer extend screen / scroll. reg */ case 25: /* TCEM: text cursor enable mode */ curr->w_curinv = !i; - CursorVisibility(curr->w_curinv ? -1 : curr->w_curvvis); + LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis); break; - /* case 40: 132 col enable */ + /* case 34: RLM: Right to left mode */ + /* case 35: HEBM: hebrew keyboard map */ + /* case 36: HEM: hebrew encoding */ + /* case 38: TeK Mode */ + /* case 40: 132 col enable */ /* case 42: NRCM: 7bit NRC character mode */ - /* case 44: margin bell enable */ + /* case 44: margin bell enable */ + /* case 66: NKM: Numeric keypad appl mode */ + /* case 68: KBUM: Keyboard usage mode (data process) */ } } break; @@ -1581,25 +1284,8 @@ int c, intermediate; } -/* - * 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) +StringStart(type) enum string_t type; { curr->w_StringType = type; @@ -1608,7 +1294,7 @@ enum string_t type; } static void -SaveChar(c) +StringChar(c) int c; { if (curr->w_stringp >= curr->w_string + MAXSTR - 1) @@ -1617,44 +1303,99 @@ int c; *(curr->w_stringp)++ = c; } +/* + * Do string processing. Returns -1 if output should be suspended + * until status is gone. + */ +static int +StringEnd() +{ + struct canvas *cv; + + 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); + WindowChanged(curr, 'h'); + break; + case PM: + case GM: + for (display = displays; display; display = display->d_next) + { + for (cv = D_cvlist; cv; cv = cv->c_next) + if (cv->c_layer->l_bottom == &curr->w_layer) + break; + if (cv || curr->w_StringType == GM) + MakeStatus(curr->w_string); + } + return -1; + case DCS: + LAY_DISPLAYS(&curr->w_layer, 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; + } + return 0; +} + static void PrintStart() { - int pi[2]; + curr->w_pdisplay = 0; - if (printcmd == 0 && D_PO == 0) - return; + /* find us a nice display to print on, fore prefered */ + for (display = displays; display; display = display->d_next) + if (curr == D_fore && (printcmd || D_PO)) + break; + if (!display) + { + struct canvas *cv; + for (cv = curr->w_layer.l_cvlist; cv; cv = cv->c_lnext) + { + display = cv->c_display; + if (printcmd || D_PO) + break; + } + if (!cv) + { + display = displays; + if (!display || display->d_next || !(printcmd || D_PO)) + 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]; + if (printcmd && curr->w_pdisplay->d_printfd < 0) + curr->w_pdisplay->d_printfd = printpipe(curr, printcmd); } static void @@ -1669,8 +1410,6 @@ int c; static void PrintFlush() { - struct display *odisp = display; - display = curr->w_pdisplay; if (display && printcmd) { @@ -1682,7 +1421,7 @@ PrintFlush() r = write(display->d_printfd, bp, len); if (r <= 0) { - Msg(errno, "printing aborted"); + WMsg(curr, errno, "printing aborted"); close(display->d_printfd); display->d_printfd = -1; break; @@ -1699,7 +1438,6 @@ PrintFlush() Flush(); } curr->w_stringp = curr->w_string; - display = odisp; } @@ -1709,31 +1447,36 @@ 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); + LSetFlow(&win->w_layer, win->w_flow & FLOW_NOW); } + +#ifdef FONT + static void DesignateCharset(c, n) int c, n; { curr->w_ss = 0; -#ifdef KANJI +# ifdef KANJI if (c == ('@' & 037)) c = KANJI; -#endif +# 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); + { + curr->w_FontL = c; + curr->w_rend.font = curr->w_FontL; + LSetRendition(&curr->w_layer, &curr->w_rend); + } if (curr->w_CharsetR == n) curr->w_FontR = c; } @@ -1747,7 +1490,9 @@ int n; if (curr->w_Charset != n) { curr->w_Charset = n; - SetFont(curr->w_FontL = curr->w_charsets[n]); + curr->w_FontL = curr->w_charsets[n]; + curr->w_rend.font = curr->w_FontL; + LSetRendition(&curr->w_layer, &curr->w_rend); } } @@ -1764,6 +1509,8 @@ int n; curr->w_gr = 1; } +#endif /* FONT */ + static void SaveCursor() { @@ -1771,30 +1518,33 @@ SaveCursor() curr->w_Saved_x = curr->w_x; curr->w_Saved_y = curr->w_y; curr->w_SavedRend= curr->w_rend; +#ifdef FONT curr->w_SavedCharset = curr->w_Charset; curr->w_SavedCharsetR = curr->w_CharsetR; bcopy((char *) curr->w_charsets, (char *) curr->w_SavedCharsets, 4 * sizeof(int)); +#endif } 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); - } + if (!curr->w_saved) + return; + LGotoPos(&curr->w_layer, 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; +#ifdef FONT + 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]; +#endif + LSetRendition(&curr->w_layer, &curr->w_rend); } static void @@ -1809,19 +1559,16 @@ BackSpace() curr->w_x = cols - 1; curr->w_y--; } - if (display) - GotoPos(curr->w_x, curr->w_y); + LGotoPos(&curr->w_layer, 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); - } + if (curr->w_x == 0) + return; + curr->w_x = 0; + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void @@ -1835,17 +1582,17 @@ int out_mode; { if (curr->w_y < rows-1) curr->w_y++; - if (out_mode && display) - GotoPos(curr->w_x, curr->w_y); + if (out_mode) + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); return; } - ScrollUpMap(1); + MScrollV(curr, 1, curr->w_top, curr->w_bot); if (curr->w_autoaka > 1) curr->w_autoaka--; - if (out_mode && display) + if (out_mode) { - ScrollV(0, curr->w_top, cols - 1, curr->w_bot, 1); - GotoPos(curr->w_x, curr->w_y); + LScrollV(&curr->w_layer, 1, curr->w_top, curr->w_bot); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } } @@ -1854,11 +1601,9 @@ 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); + MScrollV(curr, -1, curr->w_top, curr->w_bot); + LScrollV(&curr->w_layer, -1, curr->w_top, curr->w_bot); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } else if (curr->w_y > 0) CursorUp(1); @@ -1870,24 +1615,11 @@ 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_rend.image = c; + MInsChar(curr, &curr->w_rend, x, y); 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); + LInsChar(&curr->w_layer, &curr->w_rend, x, y, &mline_old); } static void @@ -1901,16 +1633,9 @@ int n; 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); + MScrollH(curr, -n, y, x, curr->w_width - 1); + LScrollH(&curr->w_layer, -n, y, x, curr->w_width - 1, &mline_old); + LGotoPos(&curr->w_layer, x, y); } static void @@ -1922,137 +1647,46 @@ int n; 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); + MScrollH(curr, n, y, x, curr->w_width - 1); + LScrollH(&curr->w_layer, n, y, x, curr->w_width - 1, &mline_old); + LGotoPos(&curr->w_layer, 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); + MScrollV(curr, n, curr->w_y, curr->w_bot); + LScrollV(&curr->w_layer, n, curr->w_y, curr->w_bot); + LGotoPos(&curr->w_layer, 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); + MScrollV(curr, -n, curr->w_y, curr->w_bot); + LScrollV(&curr->w_layer, -n, curr->w_y, curr->w_bot); + LGotoPos(&curr->w_layer, 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); + MScrollV(curr, n, curr->w_top, curr->w_bot); + LScrollV(&curr->w_layer, n, curr->w_top, curr->w_bot); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } -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() @@ -2068,8 +1702,8 @@ ForwardTab() x++; while (x < cols - 1 && !curr->w_tabs[x]) x++; - GotoPos(x, curr->w_y); curr->w_x = x; + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void @@ -2081,107 +1715,57 @@ BackwardTab() x--; while (x > 0 && !curr->w_tabs[x]) x--; - GotoPos(x, curr->w_y); curr->w_x = x; + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void ClearScreen() { - register int i; - register struct mline *ml = curr->w_mlines; - - for (i = 0; i < rows; ++i) - { + LClear(&curr->w_layer, 0, 0, curr->w_width - 1, curr->w_height - 1, 1); #ifdef COPY_PASTE - AddLineToHist(curr, ml); + MScrollV(curr, curr->w_height, 0, curr->w_height - 1); +#else + MClear(curr, 0, 0, curr->w_width - 1, curr->w_height - 1); #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; + register int 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); + LClear(&curr->w_layer, 0, 0, x, y, 1); + MClear(curr, 0, 0, x, y); RestorePosRendition(); } static void ClearToEOS() { - register int n, y = curr->w_y, x = curr->w_x; + register int 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); + LClear(&curr->w_layer, x, y, cols - 1, rows - 1, 1); + MClear(curr, x, y, cols - 1, rows - 1); RestorePosRendition(); } static void -ClearFullLine() +ClearLineRegion(from, to) +int from, to; { 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); + LClear(&curr->w_layer, from, y, to, y, 1); + MClear(curr, from, y, to, y); 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; { @@ -2194,7 +1778,7 @@ register int n; } if ((curr->w_x += n) >= cols) curr->w_x = cols - 1; - GotoPos(curr->w_x, curr->w_y); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void @@ -2209,7 +1793,7 @@ register int n; else if ((curr->w_y -= n) < curr->w_top) curr->w_y = curr->w_top; - GotoPos(curr->w_x, curr->w_y); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void @@ -2224,7 +1808,7 @@ register int n; else if ((curr->w_y += n) > curr->w_bot) curr->w_y = curr->w_bot; - GotoPos(curr->w_x, curr->w_y); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void @@ -2233,7 +1817,7 @@ register int n; { if ((curr->w_x -= n) < 0) curr->w_x = 0; - GotoPos(curr->w_x, curr->w_y); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); } static void @@ -2246,16 +1830,18 @@ int on; { switch (curr->w_args[i]) { - case 4: + /* case 2: KAM: Lock keyboard */ + case 4: /* IRM: Insert mode */ curr->w_insert = on; - InsertMode(on); + LAY_DISPLAYS(&curr->w_layer, InsertMode(on)); break; - case 20: + /* case 12: SRM: Echo mode on */ + case 20: /* LNM: Linefeed mode */ curr->w_autolf = on; break; case 34: curr->w_curvvis = !on; - CursorVisibility(curr->w_curinv ? -1 : curr->w_curvvis); + LCursorVisibility(&curr->w_layer, curr->w_curinv ? -1 : curr->w_curvvis); break; default: break; @@ -2298,12 +1884,11 @@ SelectRendition() a |= j; } while (++i < curr->w_NumArgs); - if (curr->w_rend.attr != a) - SetAttr(curr->w_rend.attr = a); + curr->w_rend.attr = a; #ifdef COLOR - if (curr->w_rend.color != c) - SetColor(curr->w_rend.color = c); + curr->w_rend.color = c; #endif + LSetRendition(&curr->w_layer, &curr->w_rend); } static void @@ -2312,6 +1897,7 @@ FillWithEs() register int i; register char *p, *ep; + ClearLayer(&curr->w_layer, 1); curr->w_y = curr->w_x = 0; for (i = 0; i < rows; ++i) { @@ -2321,58 +1907,10 @@ FillWithEs() while (p < ep) *p++ = 'E'; } - if (display) - Redisplay(0); + RedisplayLayer(&curr->w_layer, 1); } -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 @@ -2393,14 +1931,9 @@ int l; 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(); - } + WindowChanged(p, 't'); + WindowChanged((struct win *)0, 'w'); + WindowChanged((struct win *)0, 'W'); } static void @@ -2452,25 +1985,11 @@ FindAKA() 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); + LGotoPos(&curr->w_layer, curr->w_x, curr->w_y); + LSetRendition(&curr->w_layer, &curr->w_rend); } /* Send a terminal report as if it were typed. */ @@ -2492,6 +2011,294 @@ int n1, n2; } } + + +/* + *====================================================================* + *====================================================================* + */ + +/********************************************************************** + * + * Memory subsystem. + * + */ + +static void +MFixLine(p, y, mc) +struct win *p; +int y; +struct mchar *mc; +{ + struct mline *ml = &p->w_mlines[y]; + if (mc->attr && ml->attr == null) + { + if ((ml->attr = (char *)malloc(p->w_width + 1)) == 0) + { + ml->attr = null; + mc->attr = p->w_rend.attr = 0; + WMsg(p, 0, "Warning: no space for attr - turned off"); + } + bzero(ml->attr, p->w_width + 1); + } +#ifdef FONT + if (mc->font && ml->font == null) + { + if ((ml->font = (char *)malloc(p->w_width + 1)) == 0) + { + ml->font = null; + p->w_FontL = p->w_charsets[p->w_ss ? p->w_ss : p->w_Charset] = 0; + p->w_FontR = p->w_charsets[p->w_ss ? p->w_ss : p->w_CharsetR] = 0; + mc->font = p->w_rend.font = 0; + WMsg(p, 0, "Warning: no space for font - turned off"); + } + bzero(ml->font, p->w_width + 1); + } +#endif +#ifdef COLOR + if (mc->color && ml->color == null) + { + if ((ml->color = (char *)malloc(p->w_width + 1)) == 0) + { + ml->color = null; + mc->color = p->w_rend.color = 0; + WMsg(p, 0, "Warning: no space for color - turned off"); + } + bzero(ml->color, p->w_width + 1); + } +#endif +} + +/*****************************************************************/ + +static void +MScrollH(p, n, y, xs, xe) +struct win *p; +int n, y, xs, xe; +{ + struct mline *ml; + + if (n == 0) + return; + ml = &p->w_mlines[y]; + if (n > 0) + { + if (xe - xs + 1 > n) + bcopy_mline(ml, xs + n, xs, xe + 1 - xs - n); + else + n = xe - xs + 1; + clear_mline(ml, xe + 1 - n, n); + } + else + { + n = -n; + if (xe - xs + 1 > n) + bcopy_mline(ml, xs, xs + n, xe + 1 - xs - n); + else + n = xe - xs + 1; + clear_mline(ml, xs, n); + } +} + +static void +MScrollV(p, n, ys, ye) +struct win *p; +int n; +int ys, ye; +{ + int i, cnt1, cnt2; + struct mline *tmp[256]; + struct mline *ml; + + if (n == 0) + return; + if (n > 0) + { + if (n > 256) + { + MScrollV(p, n - 256, ys, ye); + n = 256; + } + if (ye - ys + 1 < n) + n = ye - ys + 1; +#ifdef COPY_PASTE + if (compacthist) + { + ye = MFindUsedLine(p, ye, ys); + if (ye - ys + 1 < n) + n = ye - ys + 1; + if (n <= 0) + return; + } +#endif + /* Clear lines */ + ml = p->w_mlines + ys; + for (i = ys; i < ys + n; i++, ml++) + { +#ifdef COPY_PASTE + if (ys == p->w_top) + AddLineToHist(p, ml); +#endif + if (ml->attr != null) + free(ml->attr); + ml->attr = null; +#ifdef FONT + if (ml->font != null) + free(ml->font); + ml->font = null; +#endif +#ifdef COLOR + if (ml->color != null) + free(ml->color); + ml->color = null; +#endif + bclear(ml->image, p->w_width + 1); + } + /* switch 'em over */ + cnt1 = n * sizeof(struct mline); + cnt2 = (ye - ys + 1 - n) * sizeof(struct mline); + if (cnt1 && cnt2) + Scroll((char *)(p->w_mlines + ys), cnt1, cnt2, (char *)tmp); + } + else + { + if (n < -256) + { + MScrollV(p, n + 256, ys, ye); + n = -256; + } + n = -n; + if (ye - ys + 1 < n) + n = ye - ys + 1; + + ml = p->w_mlines + ye; + /* Clear lines */ + for (i = ye; i > ye - n; i--, ml--) + { + if (ml->attr != null) + free(ml->attr); + ml->attr = null; +#ifdef FONT + if (ml->font != null) + free(ml->font); + ml->font = null; +#endif +#ifdef COLOR + if (ml->color != null) + free(ml->color); + ml->color = null; +#endif + bclear(ml->image, p->w_width + 1); + } + cnt1 = n * sizeof(struct mline); + cnt2 = (ye - ys + 1 - n) * sizeof(struct mline); + if (cnt1 && cnt2) + Scroll((char *)(p->w_mlines + ys), cnt2, cnt1, (char *)tmp); + } +} + +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 +MClear(p, xs, ys, xe, ye) +struct win *p; +int xs, ys, xe, ye; +{ + int n, y; + int xxe; + struct mline *ml; + + /* check for magic margin condition */ + if (xs >= p->w_width) + xs = p->w_width - 1; + if (xe >= p->w_width) + xe = p->w_width - 1; + + ml = p->w_mlines + ys; + for (y = ys; y <= ye; y++, ml++) + { + xxe = (y == ye) ? xe : p->w_width - 1; + n = xxe - xs + 1; + if (n > 0) + clear_mline(ml, xs, n); + xs = 0; + } +} + +static void +MInsChar(p, c, x, y) +struct win *p; +struct mchar *c; +int x, y; +{ + int n; + struct mline *ml; + + ASSERT(x >= 0 && x < p->w_width); + MFixLine(p, y, c); + ml = p->w_mlines + y; + n = p->w_width - x - 1; + if (n > 0) + bcopy_mline(ml, x, x + 1, n); + copy_mchar2mline(c, ml, x); +} + +static void +MPutChar(p, c, x, y) +struct win *p; +struct mchar *c; +int x, y; +{ + struct mline *ml; + + MFixLine(p, y, c); + ml = &p->w_mlines[y]; + copy_mchar2mline(c, ml, x); +} + + +static void +MWrapChar(p, c, y, top, bot, ins) +struct win *p; +struct mchar *c; +int y, top, bot; +int ins; +{ + struct mline *ml; + + MFixLine(p, y, c); + ml = &p->w_mlines[y]; + copy_mchar2mline(&mchar_null, ml, p->w_width); + if (y == bot) + MScrollV(p, 1, top, bot); + else if (y < p->w_height - 1) + y++; + MFixLine(p, y, c); + ml = &p->w_mlines[y]; + if (ins && p->w_width > 1) + bcopy_mline(ml, 0, 1, p->w_width - 1); + copy_mchar2mline(c, ml, 0); +} + #ifdef COPY_PASTE static void AddLineToHist(wp, ml) @@ -2510,9 +2317,11 @@ struct mline *ml; if (o != null) free(o); +#ifdef FONT q = ml->font; o = hml->font; hml->font = q; ml->font = null; if (o != null) free(o); +#endif #ifdef COLOR q = ml->color; o = hml->color; hml->color = q; ml->color = null; @@ -2525,3 +2334,238 @@ struct mline *ml; } #endif +int +MFindUsedLine(p, ye, ys) +struct win *p; +int ys, ye; +{ + int y; + struct mline *ml = p->w_mlines + ye; + + debug2("MFindUsedLine: %d %d\n", ye, ys); + for (y = ye; y >= ys; y--, ml--) + { + if (bcmp((char*)ml->image, blank, p->w_width)) + break; + if (ml->attr != null && bcmp((char*)ml->attr, null, p->w_width)) + break; +#ifdef COLOR + if (ml->color != null && bcmp((char*)ml->color, null, p->w_width)) + break; +#endif + } + debug1("MFindUsedLine returning %d\n", y); + return y; +} + + +/* + *====================================================================* + *====================================================================* + */ + +/* + * Tricky: send only one bell even if the window is displayed + * more than one times. + */ +void +WBell(p, visual) +struct win *p; +int visual; +{ + struct canvas *cv; + for (display = displays; display; display = display->d_next) + { + for (cv = D_cvlist; cv; cv = cv->c_next) + if (cv->c_layer->l_bottom == &p->w_layer) + break; + if (cv && !visual) + PutStr(D_BL); + else if (cv && D_VB) + PutStr(D_VB); + else + p->w_bell = visual ? BELL_VISUAL : BELL_FOUND; + } +} + +/* + * This should be reverse video. + * Only change video if window is fore. + * Because it is used in some termcaps to emulate + * a visual bell we do this hack here. + * (screen uses \Eg as special vbell sequence) + */ +static void +WReverseVideo(p, on) +struct win *p; +int on; +{ + struct canvas *cv; + for (cv = p->w_layer.l_cvlist; cv; cv = cv->c_lnext) + { + display = cv->c_display; + if (cv != D_forecv) + continue; + ReverseVideo(on); + if (!on && p->w_revvid && !D_CVR) + { + if (D_VB) + PutStr(D_VB); + else + p->w_bell = BELL_VISUAL; + } + } +} + +void +WMsg(p, err, str) +struct win *p; +int err; +char *str; +{ + extern struct layer *flayer; + struct layer *oldflayer = flayer; + flayer = &p->w_layer; + LMsg(err, str); + flayer = oldflayer; +} + +void +WChangeSize(p, w, h) +struct win *p; +int w, h; +{ + int wok = 0; + struct canvas *cv; + + if (p->w_layer.l_cvlist == 0) + { + /* window not displayed -> works always */ + ChangeWindowSize(p, w, h, p->w_histheight); + return; + } + for (cv = p->w_layer.l_cvlist; cv; cv = cv->c_lnext) + { + display = cv->c_display; + if (p != D_fore) + continue; /* change only fore */ + if (D_CWS) + break; + if (D_CZ0 && (w == Z0width || w == Z1width)) + wok = 1; + } + if (cv == 0 && wok == 0) /* can't change any display */ + return; + if (!D_CWS) + h = p->w_height; + ChangeWindowSize(p, w, h, p->w_histheight); + for (display = displays; display; display = display->d_next) + { + if (p == D_fore) + { + if (D_cvlist && D_cvlist->c_next == 0) + ResizeDisplay(w, h); + else + ResizeDisplay(w, D_height); + ResizeLayersToCanvases(); /* XXX Hmm ? */ + continue; + } + for (cv = D_cvlist; cv; cv = cv->c_next) + if (cv->c_layer->l_bottom == &p->w_layer) + break; + if (cv) + Redisplay(0); + } +} + +static int +WindowChangedCheck(s, what, hp) +char *s; +int what; +int *hp; +{ + int h = 0; + while(*s) + { + if (*s++ != '%') + continue; + while (*s >= '0' && *s <= '9') + s++; + if (*s == 'h') + h = 1; + if (*s == what || what == 'd') + break; + if (*s) + s++; + } + if (hp) + *hp = h; + return *s ? 1 : 0; +} + +void +WindowChanged(p, what) +struct win *p; +int what; +{ + int inwstr, inhstr; + int inwstrh, inhstrh; + int got, ox, oy; + struct display *olddisplay = display; + struct canvas *cv; + + inwstr = inhstr = 0; + + inwstr = WindowChangedCheck(captionstring, what, &inwstrh); + inhstr = WindowChangedCheck(hstatusstring, what, &inhstrh); + + if (p == 0) + { + for (display = displays; display; display = display->d_next) + { + ox = D_x; + oy = D_y; + for (cv = D_cvlist; cv; cv = cv->c_next) + { + p = Layer2Window(cv->c_layer); + if (inwstr || (inwstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0))) + if (cv->c_ye + 1 < D_height) + RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0); + } + p = D_fore; + if (inhstr || (inhstrh && p && p->w_hstatus && *p->w_hstatus && WindowChangedCheck(p->w_hstatus, what, (int *)0))) + RefreshHStatus(); + if (ox != -1 && ox != -1) + GotoPos(ox, oy); + } + display = olddisplay; + return; + } + + if (p->w_hstatus && *p->w_hstatus && (inwstrh || inhstrh) && WindowChangedCheck(p->w_hstatus, what, (int *)0)) + { + inwstr |= inwstrh; + inhstr |= inhstrh; + } + if (!inwstr && !inhstr) + return; + for (display = displays; display; display = display->d_next) + { + got = 0; + ox = D_x; + oy = D_y; + for (cv = D_cvlist; cv; cv = cv->c_next) + { + if (Layer2Window(cv->c_layer) != p) + continue; + got = 1; + if (inwstr && cv->c_ye + 1 < D_height) + RefreshLine(cv->c_ye + 1, 0, D_width - 1, 0); + } + if (got && inhstr && p == D_fore) + RefreshHStatus(); + if (ox != -1 && ox != -1) + GotoPos(ox, oy); + } + display = olddisplay; +} |