home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1991
- * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
- * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
- * Copyright (c) 1987 Oliver Laumann
- * All rights reserved. Not derived from licensed software.
- *
- * Permission is granted to freely use, copy, modify, and redistribute
- * this software, provided that no attempt is made to gain profit from it,
- * the authors are not construed to be liable for any results of using the
- * software, alterations are clearly marked as such, and this notice is
- * not modified.
- *
- * Noteworthy contributors to screen's design and implementation:
- * Wayne Davison (davison@borland.com)
- * Patrick Wolfe (pat@kai.com, kailand!pat)
- * Bart Schaefer (schaefer@cse.ogi.edu)
- * Nathan Glasser (nathan@brokaw.lcs.mit.edu)
- * Larry W. Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu)
- * Howard Chu (hyc@hanauma.jpl.nasa.gov)
- * Tim MacKenzie (tym@dibbler.cs.monash.edu.au)
- * Markku Jarvinen (mta@{cc,cs,ee}.tut.fi)
- * Marc Boucher (marc@CAM.ORG)
- *
- ****************************************************************
- */
-
- #ifndef lint
- static char rcs_id[] = "$Id: ansi.c,v 1.2 92/02/03 02:27:30 jnweiger Exp $ FAU";
- #endif
-
- #include <stdio.h>
- #include <sys/types.h>
- #ifdef BSDI
- #include <sys/signal.h>
- #endif /* BSDI */
- #include <fcntl.h>
- #include "config.h"
- #include "screen.h"
- #include "ansi.h"
- #include "extern.h"
- #ifndef sun /* we want to know about TIOCGWINSZ. jw. */
- # include <sys/ioctl.h>
- #endif
-
- extern char *getenv(), *tgetstr(), *tgoto();
- #ifndef __STDC__
- extern char *malloc();
- #endif
-
- extern struct win *fore;
- extern int ForeNum;
- extern force_vt, assume_LP;
- extern int BellDisplayed;
- extern int MsgMinWait;
- extern int all_norefresh;
-
- int TermcapROWS, TermcapCOLS; /* defaults that we learned from termcap */
- int default_width, default_height; /* width/height a new window will get */
-
- int maxwidth;
-
- int Z0width, Z1width; /* widths for Z0/Z1 switching */
-
- char display_tty[MAXPATH];
- int screenwidth, screenheight; /* width/height of the screen */
- int screentop, screenbot; /* scrollregion start/end */
- int screenx, screeny; /* cursor position */
- char GlobalAttr; /* current attributes */
- char GlobalCharset; /* current font */
- int insert; /* insert mode */
- int keypad; /* application keypad */
- int flow = 1; /* flow control */
-
- int status; /* status is displayed */
- static int status_lastx, status_lasty;
-
- static int rows, cols; /* window size of the curr window */
-
- int default_flow = -1, wrap = 1, default_monitor = 0;
- int visual_bell = 0, termcapHS, use_hardstatus = 1;
- char *Termcap, *extra_incap, *extra_outcap;
- static int Termcaplen;
- char *blank, *null, *LastMsg;
- char Term[MAXSTR+5]; /* +5: "TERM=" */
- char screenterm[20] = "screen";
- char *Z0, *Z1;
- int ISO2022, HS;
- time_t TimeDisplayed, time();
-
- /*
- * the termcap routines need this to work
- */
- short ospeed;
- char *BC;
- char *UP;
-
- static void AddCap __P((char *));
- static void MakeString __P((char *, char *, int, char *));
- static int Special __P((int));
- static void DoESC __P((int, int ));
- static void DoCSI __P((int, int ));
- static void CPutStr __P((char *, int));
- static void SetChar __P(());
- static void StartString __P((enum string_t));
- static void AddChar __P((int ));
- static void PrintChar __P((int ));
- static void PrintFlush __P((void));
- static void KeypadMode __P((int));
- static void DesignateCharset __P((int, int ));
- static void MapCharset __P((int));
- static void SaveCursor __P((void));
- static void RestoreCursor __P((void));
- static void CountChars __P((int));
- static int CalcCost __P((char *));
- static int Rewrite __P((int, int, int, int));
- 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 ClearLine __P((void));
- static void ClearToEOL __P((void));
- static void ClearFromBOL __P((void));
- static void ClearInLine __P((int, int, int, int ));
- static void CursorRight __P(());
- static void CursorUp __P(());
- static void CursorDown __P(());
- static void CursorLeft __P(());
- static void ASetMode __P((int));
- static void SelectRendition __P((void));
- static void FillWithEs __P((void));
- static void RedisplayLine __P((char *, char *, char *, int, int, int ));
- static void FindAKA __P((void));
- static void SetCurr __P((struct win *));
- static void inpRedisplayLine __P((int, int, int, int));
- static void process_inp_input __P((char **, int *));
- static void AbortInp __P((void));
- static void AKAfin __P((char *, int));
- static void Colonfin __P((char *, int));
- static void RAW_PUTCHAR __P((int));
- static char *e_tgetstr __P((char *, char **));
- static int e_tgetflag __P((char *));
- static int e_tgetnum __P((char *));
-
-
- static char *tbuf, *tentry, *termname;
- static char *tp;
- static char *TI, *TE, *BL, *VB, *CR, *NL, *CL, *IS;
- char *WS; /* used in ResizeScreen() */
- char *CE; /* used in help.c */
- static char *CM, *US, *UE, *SO, *SE, *CD, *DO, *SR, *SF, *AL;
- static char *CS, *DL, *DC, *IC, *IM, *EI, *ND, *KS, *KE;
- static char *MB, *MD, *MH, *MR, *ME, *PO, *PF, *HO;
- static char *TS, *FS, *DS, *VI, *VE, *VS;
- static char *CDC, *CDL, *CAL, *CUP, *CDO, *CLE, *CRI, *CIC;
- static char *attrtab[NATTR];
- static AM, MS, COP;
- int LP;
- /*
- * Do not confuse S0 (es-zero), E0 (e-zero) with SO (es-oh), PO (pe-oh),
- * Z0 (z-zero), DO (de-oh)... :-)
- */
- static char *C0, *S0, *E0;
- static char c0_tab[256];
- /*
- */
- static screencap = 0;
- char *OldImage, *OldAttr, *OldFont;
- static struct win *curr;
- static display = 1;
- static StrCost;
- static UPcost, DOcost, LEcost, NDcost, CRcost, IMcost, EIcost, NLcost;
- static tcLineLen;
- static StatLen;
- static lp_missing = 0;
-
- int in_ovl;
- int ovl_blockfore;
- void (*ovl_process)();
- void (*ovl_RedisplayLine)();
- int (*ovl_Rewrite)();
-
- static char *KeyCaps[] =
- {
- "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7", "k8", "k9",
- "kb", "kd", "kh", "kl", "ko", "kr", "ku",
- "K1", "K2", "K3", "K4", "K5",
- "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", "l8", "l9"
- };
- #define NKEYCAPS ((int)(sizeof(KeyCaps)/sizeof(*KeyCaps)))
- static char *KeyCapsArr[NKEYCAPS];
-
- static char TermcapConst[] = "\\\n\
- \t:DO=\\E[%dB:LE=\\E[%dD:RI=\\E[%dC:UP=\\E[%dA:bs:bt=\\E[Z:\\\n\
- \t:cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:cm=\\E[%i%d;%dH:ct=\\E[3g:\\\n\
- \t:do=^J:nd=\\E[C:pt:rc=\\E8:rs=\\Ec:sc=\\E7:st=\\EH:up=\\EM:\\\n\
- \t:le=^H:bl=^G:cr=^M:it#8:ho=\\E[H:nw=\\EE:ta=^I:is=\\E)0:xv:";
-
- void
- InitTermcap()
- {
- register char *s;
- int i;
-
- screencap = 0;
- if ((s = getenv("SCREENCAP")) != 0)
- {
- if ((Termcap = malloc(strlen(s) + 10)) != 0)
- {
- sprintf(Termcap, "TERMCAP=%s", s);
- screencap = 1;
- }
- }
- else
- Termcap = malloc((unsigned) 1024);
- Termcaplen = 0;
- tbuf = malloc((unsigned) 1024);
- tentry = tp = malloc((unsigned) 1024);
- if (!(Termcap && tbuf && tentry))
- Msg_nomem;
- bzero(tbuf, 1024);
- if ((termname = getenv("TERM")) == 0)
- Msg(0, "No TERM in environment.");
- debug1("InitTermcap: looking for tgetent('%s');\n", termname);
- if (tgetent(tbuf, termname) != 1)
- Msg(0, "Cannot find termcap entry for %s.", termname);
- debug1("got it:\n%s\n",tbuf);
- #ifdef DEBUG
- if (extra_incap)
- debug1("Extra incap: %s\n", extra_incap);
- if (extra_outcap)
- debug1("Extra outcap: %s\n", extra_outcap);
- #endif
-
- TermcapCOLS = TermcapROWS = 0;
- if (s = getenv("COLUMNS"))
- TermcapCOLS = atoi(s);
- if (TermcapCOLS <= 0)
- TermcapCOLS = e_tgetnum("co");
- if (TermcapCOLS <= 0)
- TermcapCOLS = 80;
- if (s = getenv("LINES"))
- TermcapROWS = atoi(s);
- if (TermcapROWS <= 0)
- TermcapROWS = e_tgetnum("li");
- if (TermcapROWS <= 0)
- TermcapROWS = 24;
-
- if (e_tgetflag("hc"))
- Msg(0, "You can't run screen on a hardcopy terminal.");
- if (e_tgetflag("os"))
- Msg(0, "You can't run screen on a terminal that overstrikes.");
- if (e_tgetflag("ns"))
- Msg(0, "Terminal must support scrolling.");
- if (!(CL = e_tgetstr("cl", &tp)))
- Msg(0, "Clear screen capability required.");
- if (!(CM = e_tgetstr("cm", &tp)))
- Msg(0, "Addressable cursor capability required.");
- if (default_flow < 0)
- default_flow = e_tgetflag("NF") ? FLOW_NOW * 0 :
- e_tgetflag("xo") ? FLOW_NOW * 1 :
- FLOW_AUTOFLAG;
- AM = e_tgetflag("am");
- LP = assume_LP || (!extra_incap && !strncmp(termname, "vt", 2))
- || !AM || e_tgetflag("LP") || e_tgetflag("xv");
- COP = e_tgetflag("OP");
- HO = e_tgetstr("ho", &tp);
- TI = e_tgetstr("ti", &tp);
- TE = e_tgetstr("te", &tp);
- if (!(BL = e_tgetstr("bl", &tp)))
- BL = "\007";
- VB = e_tgetstr("vb", &tp);
- if (!(BC = e_tgetstr("bc", &tp)))
- {
- if (e_tgetflag("bs"))
- BC = "\b";
- else
- BC = e_tgetstr("le", &tp);
- }
- if (!(CR = e_tgetstr("cr", &tp)))
- CR = "\r";
- if (!(NL = e_tgetstr("nl", &tp)))
- NL = "\n";
- IS = e_tgetstr("is", &tp);
- MS = 1;
- if (e_tgetnum("sg") <= 0 && e_tgetnum("ug") <= 0)
- {
- MS = e_tgetflag("ms");
- attrtab[ATTR_DI] = MH = e_tgetstr("mh", &tp); /* Dim */
- attrtab[ATTR_US] = US = e_tgetstr("us", &tp); /* Underline */
- attrtab[ATTR_BD] = MD = e_tgetstr("md", &tp); /* Bold */
- attrtab[ATTR_RV] = MR = e_tgetstr("mr", &tp); /* Reverse */
- attrtab[ATTR_SO] = SO = e_tgetstr("so", &tp); /* Standout */
- attrtab[ATTR_BL] = MB = e_tgetstr("mb", &tp); /* Blinking */
- ME = e_tgetstr("me", &tp);
- SE = e_tgetstr("se", &tp);
- UE = e_tgetstr("ue", &tp);
- /*
- * Does ME also reverse the effect of SO and/or US? This is not
- * clearly specified by the termcap manual. Anyway, we should at
- * least look whether ME and SE/UE are equal:
- */
- if (UE && ((SE && strcmp(SE, UE) == 0) || (ME && strcmp(ME, UE) == 0)))
- UE = 0;
- if (SE && (ME && strcmp(ME, SE) == 0))
- SE = 0;
-
- /* Set up missing entries */
- s = 0;
- for (i = NATTR-1; i >= 0; i--)
- if (attrtab[i])
- s = attrtab[i];
- for (i = 0; i < NATTR; i++)
- {
- if (attrtab[i] == 0)
- attrtab[i] = s;
- else
- s = attrtab[i];
- }
- }
- else
- {
- US = UE = SO = SE = MB = MD = MH = MR = ME = 0;
- for (i = 0; i < NATTR; i++)
- attrtab[i] = 0;
- }
- CE = e_tgetstr("ce", &tp);
- CD = e_tgetstr("cd", &tp);
- if (!(DO = e_tgetstr("do", &tp)))
- DO = NL;
- UP = e_tgetstr("up", &tp);
- ND = e_tgetstr("nd", &tp);
- SR = e_tgetstr("sr", &tp);
- if (!(SF = e_tgetstr("sf", &tp)))
- SF = NL;
- AL = e_tgetstr("al", &tp);
- DL = e_tgetstr("dl", &tp);
- CS = e_tgetstr("cs", &tp);
- DC = e_tgetstr("dc", &tp);
- IC = e_tgetstr("ic", &tp);
- CIC = e_tgetstr("IC", &tp);
- CDC = e_tgetstr("DC", &tp);
- CDL = e_tgetstr("DL", &tp);
- CAL = e_tgetstr("AL", &tp);
- CUP = e_tgetstr("UP", &tp);
- CDO = e_tgetstr("DO", &tp);
- CLE = e_tgetstr("LE", &tp);
- CRI = e_tgetstr("RI", &tp);
- IM = e_tgetstr("im", &tp);
- EI = e_tgetstr("ei", &tp);
- if (e_tgetflag("in"))
- IC = IM = 0;
- if (IC && IC[0] == '\0')
- IC = 0;
- if (CIC && CIC[0] == '\0')
- CIC = 0;
- if (IM && IM[0] == '\0')
- IM = 0;
- if (EI && EI[0] == '\0')
- EI = 0;
- if (EI == 0)
- IM = 0;
- if (IC && IM && strcmp(IC, IM) == 0)
- IC = 0;
- KS = e_tgetstr("ks", &tp);
- KE = e_tgetstr("ke", &tp);
- if (KE == 0)
- KS = 0;
- ISO2022 = e_tgetflag("G0");
- if (ISO2022)
- {
- if ((S0 = e_tgetstr("S0", &tp)) == NULL)
- #ifdef TERMINFO
- S0 = "\033(%p1%c";
- #else
- S0 = "\033(%.";
- #endif
- if ((E0 = e_tgetstr("E0", &tp)) == NULL)
- E0 = "\033(B";
- C0 = e_tgetstr("C0", &tp);
- }
- else if ((S0 = e_tgetstr("as", &tp)) != NULL
- && (E0 = e_tgetstr("ae", &tp)) != NULL)
- {
- ISO2022 = 1;
- C0 = e_tgetstr("ac", &tp);
- }
- else
- {
- S0 = E0 = "";
- C0 = "g.h.i'j-k-l-m-n+o~p\"q-r-s_t+u+v+w+x|y<z>";
- }
- for (i = 0; i < 256; i++)
- c0_tab[i] = i;
- if (C0)
- for (i = strlen(C0)&~1; i >= 0; i-=2)
- c0_tab[C0[i]] = C0[i+1];
- debug1("ISO2022 = %d\n", ISO2022);
- /* WS changes the window size */
- WS = e_tgetstr("WS", &tp);
- VI = e_tgetstr("vi", &tp);
- VE = e_tgetstr("ve", &tp);
- VS = e_tgetstr("vs", &tp);
- PO = e_tgetstr("po", &tp);
- if (!(PF = e_tgetstr("pf", &tp)))
- PO = 0;
- debug2("terminal size is %d, %d (says TERMCAP)\n", TermcapCOLS, TermcapROWS);
- /* Termcap fields Z0 & Z1 contain width-changing sequences. */
- if ((Z0 = e_tgetstr("Z0", &tp)) != NULL
- && (Z1 = e_tgetstr("Z1", &tp)) == NULL)
- Z0 = NULL;
-
- Z0width = 132;
- Z1width = 80;
-
- CheckScreenSize(0);
- if ((HS = e_tgetflag("hs")) != 0)
- {
- debug("oy! we have a hardware status line, says termcap\n");
- TS = e_tgetstr("ts", &tp);
- FS = e_tgetstr("fs", &tp);
- DS = e_tgetstr("ds", &tp);
- if ((HS = e_tgetnum("ws")) <= 0)
- HS = screenwidth;
- if (!TS || !FS || !DS)
- HS = 0;
- }
- termcapHS = HS;
- if (!use_hardstatus)
- HS = 0;
-
- UPcost = CalcCost(UP);
- DOcost = CalcCost(DO);
- NLcost = CalcCost(NL);
- LEcost = CalcCost(BC);
- NDcost = CalcCost(ND);
- CRcost = CalcCost(CR);
- IMcost = CalcCost(IM);
- EIcost = CalcCost(EI);
- for (i = 0; i < NKEYCAPS; i++)
- KeyCapsArr[i] = e_tgetstr(KeyCaps[i], &tp);
- MakeTermcap(0);
- }
-
- /*
- * if the adaptflag is on, we keep the size of this display, else
- * we may try to restore our old window sizes.
- */
- void
- InitTerm(adapt)
- int adapt;
- {
- display = 1;
- screentop = screenbot = -1;
- PutStr(IS);
- PutStr(TI);
- if (IM && strcmp(IM, EI))
- PutStr(EI);
- insert = 0;
- if (KS && strcmp(KS, KE))
- PutStr(KE);
- keypad = 0;
- PutStr(E0);
- GlobalCharset = ASCII;
- ResizeScreen((struct win *)0);
- ChangeScrollRegion(0, screenheight-1);
- PutStr(CL);
- screenx = screeny = 0;
- fflush(stdout);
- debug1("we %swant to adapt all our windows to the display\n",
- (adapt) ? "" : "don't ");
- /* In case the size was changed by a init sequence */
- CheckScreenSize((adapt) ? 2 : 0);
- }
-
- void
- FinitTerm()
- {
- display = 1;
- InsertMode(0);
- KeypadMode(0);
- ResizeScreen((struct win *)0);
- ChangeScrollRegion(0, screenheight - 1);
- SaveSetAttr(0, ASCII);
- screenx = screeny = -1;
- GotoPos(0, screenheight - 1);
- PutStr(TE);
- fflush(stdout);
- if (Termcap)
- {
- Free(Termcap);
- debug("FinitTerm: old termcap freed\n");
- }
- if (tbuf)
- {
- Free(tbuf);
- debug("FinitTerm: old tbuf freed\n");
- }
- if (tentry)
- {
- Free(tentry);
- debug("FinitTerm: old tentry freed\n");
- }
- }
-
- static void AddCap(s)
- char *s;
- {
- register int n;
-
- if (tcLineLen + (n = strlen(s)) > 55 && Termcaplen < 1024-4)
- {
- strcpy(Termcap + Termcaplen, "\\\n\t:");
- Termcaplen += 4;
- tcLineLen = 0;
- }
- if (Termcaplen + n < 1024)
- {
- strcpy(Termcap + Termcaplen, s);
- Termcaplen += n;
- tcLineLen += n;
- }
- else
- Msg(0, "TERMCAP overflow - sorry.");
- }
-
- char *MakeTermcap(aflag)
- int aflag;
- {
- char buf[1024];
- register char *p, *cp, ch;
- int i;
-
- if (screencap)
- {
- sprintf(Term, "TERM=screen");
- return Termcap;
- }
- if (screenterm == 0 || *screenterm == '\0')
- {
- debug("MakeTermcap sets screenterm=screen\n");
- strcpy(screenterm, "screen");
- }
- for (;;)
- {
- sprintf(Term, "TERM=");
- p = Term + 5;
- if (!aflag && strlen(screenterm) + strlen(termname) < MAXSTR-1)
- {
- sprintf(p, "%s.%s", screenterm, termname);
- if (tgetent(buf, p) == 1)
- break;
- }
- if (screenwidth >= 132)
- {
- sprintf(p, "%s-w", screenterm);
- if (tgetent(buf, p) == 1)
- break;
- }
- sprintf(p, "%s", screenterm);
- if (tgetent(buf, p) == 1)
- break;
- sprintf(p, "vt100");
- break;
- }
- tcLineLen = 100; /* Force NL */
- sprintf(Termcap,
- "TERMCAP=SC|%s|VT 100/ANSI X3.64 virtual terminal|", p);
- Termcaplen = strlen(Termcap);
- if (extra_outcap && *extra_outcap)
- {
- for (cp = extra_outcap; p = index(cp, ':'); cp = p)
- {
- ch = *++p;
- *p = '\0';
- AddCap(cp);
- *p = ch;
- }
- tcLineLen = 100; /* Force NL */
- }
- if (Termcaplen + strlen(TermcapConst) < 1024)
- {
- strcpy(Termcap + Termcaplen, TermcapConst);
- Termcaplen += strlen(TermcapConst);
- }
- sprintf(buf, "li#%d:co#%d:", screenheight, screenwidth);
- AddCap(buf);
- if ((force_vt && !COP) || LP || !AM)
- AddCap("LP:");
- else
- AddCap("am:");
- if (VB)
- AddCap("vb=\\E[?5h\\E[?5l:");
- if (US)
- {
- AddCap("us=\\E[4m:");
- AddCap("ue=\\E[24m:");
- }
- if (SO)
- {
- AddCap("so=\\E[3m:");
- AddCap("se=\\E[23m:");
- }
- if (MB)
- AddCap("mb=\\E[5m:");
- if (MD)
- AddCap("md=\\E[1m:");
- if (MH)
- AddCap("mh=\\E[2m:");
- if (MR)
- AddCap("mr=\\E[7m:");
- if (MB || MD || MH || MR)
- AddCap("me=\\E[m:ms:");
- if ((CS && SR) || AL || CAL || aflag)
- {
- AddCap("sr=\\EM:");
- AddCap("al=\\E[L:");
- AddCap("AL=\\E[%dL:");
- }
- else if (SR)
- AddCap("sr=\\EM:");
- if (CS || DL || CDL || aflag)
- {
- AddCap("dl=\\E[M:");
- AddCap("DL=\\E[%dM:");
- }
- if (CS)
- AddCap("cs=\\E[%i%d;%dr:");
- if (DC || CDC || aflag)
- {
- AddCap("dc=\\E[P:");
- AddCap("DC=\\E[%dP:");
- }
- if (CIC || IC || IM || aflag)
- {
- AddCap("im=\\E[4h:");
- AddCap("ei=\\E[4l:");
- AddCap("mi:");
- AddCap("ic=\\E[@:");
- AddCap("IC=\\E[%d@:");
- }
- if (KS)
- AddCap("ks=\\E=:");
- if (KE)
- AddCap("ke=\\E>:");
- if (ISO2022)
- AddCap("G0:");
- if (PO)
- {
- AddCap("po=\\E[5i:");
- AddCap("pf=\\E[4i:");
- }
- if (Z0)
- {
- AddCap("Z0=\\E[?3h:");
- AddCap("Z1=\\E[?3l:");
- }
- if (WS)
- AddCap("WS=\\E[8;%d;%dt:");
- for (i = 0; i < NKEYCAPS; i++)
- {
- if (KeyCapsArr[i] == 0)
- continue;
- MakeString(KeyCaps[i], buf, sizeof(buf), KeyCapsArr[i]);
- AddCap(buf);
- }
- return Termcap;
- }
-
- static void MakeString(cap, buf, buflen, s)
- char *cap, *buf;
- int buflen;
- char *s;
- {
- register char *p, *pmax;
- register unsigned int c;
-
- p = buf;
- pmax = p + buflen - (3+4+2);
- *p++ = *cap++;
- *p++ = *cap;
- *p++ = '=';
- while ((c = *s++) && (p < pmax))
- {
- switch (c)
- {
- case '\033':
- *p++ = '\\';
- *p++ = 'E';
- break;
- case ':':
- sprintf(p, "\\072");
- p += 4;
- break;
- case '^':
- case '\\':
- *p++ = '\\';
- *p++ = c;
- break;
- default:
- if (c >= 200)
- {
- sprintf(p, "\\%03o", c & 0377);
- p += 4;
- }
- else if (c < ' ')
- {
- *p++ = '^';
- *p++ = c + '@';
- }
- else
- *p++ = c;
- }
- }
- *p++ = ':';
- *p = '\0';
- }
-
- void
- Activate(norefresh)
- int norefresh;
- {
- debug1("Activate(%d)\n", norefresh);
- if (display)
- RemoveStatus();
- display = fore->active = 1;
- ResizeScreen(fore);
- SetCurr(fore);
- debug3("Fore (%d) has size %dx%d", ForeNum, curr->width, curr->height);
- debug1("(%d)\n", curr->histheight);
- ChangeScrollRegion(curr->top, curr->bot);
- KeypadMode(curr->keypad);
- SetFlow(curr->flow & FLOW_NOW);
- if (curr->monitor != MON_OFF)
- curr->monitor = MON_ON;
- curr->bell = BELL_OFF;
- Redisplay(norefresh || all_norefresh);
- }
-
- void
- ResetScreen(p)
- register struct win *p;
- {
- register int i;
-
- p->wrap = wrap;
- p->origin = 0;
- p->insert = 0;
- p->vbwait = 0;
- p->keypad = 0;
- p->top = 0;
- p->bot = p->height - 1;
- p->saved = 0;
- p->LocalAttr = 0;
- p->x = p->y = 0;
- p->state = LIT;
- p->StringType = NONE;
- p->ss = 0;
- p->LocalCharset = G0;
- bzero(p->tabs, p->width);
- for (i = 8; i < p->width; i += 8)
- p->tabs[i] = 1;
- for (i = G0; i <= G3; i++)
- p->charsets[i] = ASCII;
- }
-
- void
- WriteString(wp, buf, len)
- struct win *wp;
- char *buf;
- int len;
- {
- register int c, intermediate = 0;
-
- if (!len)
- return;
- if (wp->logfp != NULL)
- if ((int)fwrite(buf, len, 1, wp->logfp) < 1)
- {
- extern int errno;
-
- Msg(errno, "Error writing logfile");
- fclose(wp->logfp);
- wp->logfp = NULL;
- }
- /*
- * SetCurr() here may prevent output, as it may set display = 0
- */
- SetCurr(wp);
- if (display)
- {
- if (!HS)
- RemoveStatus();
- }
- else if (curr->monitor == MON_ON)
- curr->monitor = MON_FOUND;
-
- do
- {
- c = (unsigned char)*buf++;
- if (c == '\0' || c == '\177')
- continue;
- NextChar:
- switch (curr->state)
- {
- case PRIN:
- switch (c)
- {
- case '\033':
- curr->state = PRINESC;
- break;
- default:
- PrintChar(c);
- }
- break;
- case PRINESC:
- switch (c)
- {
- case '[':
- curr->state = PRINCSI;
- break;
- default:
- PrintChar('\033');
- PrintChar(c);
- curr->state = PRIN;
- }
- break;
- case PRINCSI:
- switch (c)
- {
- case '4':
- curr->state = PRIN4;
- break;
- default:
- PrintChar('\033');
- PrintChar('[');
- PrintChar(c);
- curr->state = PRIN;
- }
- break;
- case PRIN4:
- switch (c)
- {
- case 'i':
- curr->state = LIT;
- PrintFlush();
- break;
- default:
- PrintChar('\033');
- PrintChar('[');
- PrintChar('4');
- PrintChar(c);
- curr->state = PRIN;
- }
- break;
- case STRESC:
- switch (c)
- {
- case '\\':
- curr->state = LIT;
- *(curr->stringp) = '\0';
- switch (curr->StringType)
- {
- case PM:
- if (!display)
- break;
- MakeStatus(curr->string);
- if (!HS && status && len > 1)
- {
- curr->outlen = len - 1;
- bcopy(buf, curr->outbuf, curr->outlen);
- return;
- }
- break;
- case DCS:
- if (display)
- printf("%s", curr->string);
- break;
- case AKA:
- if (curr->akapos == 0 && !*curr->string)
- break;
- strncpy(curr->cmd + curr->akapos, curr->string, 20);
- if (!*curr->string)
- curr->autoaka = curr->y + 1;
- break;
- default:
- break;
- }
- break;
- default:
- curr->state = ASTR;
- AddChar('\033');
- AddChar(c);
- }
- break;
- case ASTR:
- switch (c)
- {
- case '\0':
- break;
- case '\033':
- curr->state = STRESC;
- break;
- default:
- AddChar(c);
- }
- break;
- case ESC:
- switch (c)
- {
- case '[':
- curr->NumArgs = 0;
- intermediate = 0;
- bzero((char *) curr->args, MAXARGS * sizeof(int));
- curr->state = CSI;
- break;
- case ']':
- StartString(OSC);
- break;
- case '_':
- StartString(APC);
- break;
- case 'P':
- StartString(DCS);
- break;
- case '^':
- StartString(PM);
- break;
- case '"':
- case 'k':
- StartString(AKA);
- break;
- default:
- if (Special(c))
- break;
- if (c >= ' ' && c <= '/')
- intermediate = intermediate ? -1 : c;
- else if (c >= '0' && c <= '~')
- {
- DoESC(c, intermediate);
- curr->state = LIT;
- }
- else
- {
- curr->state = LIT;
- goto NextChar;
- }
- }
- 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->NumArgs < MAXARGS)
- {
- curr->args[curr->NumArgs] =
- 10 * curr->args[curr->NumArgs] + c - '0';
- }
- break;
- case ';':
- case ':':
- curr->NumArgs++;
- break;
- default:
- if (Special(c))
- break;
- if (c >= '@' && c <= '~')
- {
- curr->NumArgs++;
- DoCSI(c, intermediate);
- if (curr->state != PRIN)
- curr->state = LIT;
- }
- else if ((c >= ' ' && c <= '/') || (c >= '<' && c <= '?'))
- intermediate = intermediate ? -1 : c;
- else
- {
- curr->state = LIT;
- goto NextChar;
- }
- }
- break;
- case LIT:
- default:
- if (!Special(c))
- {
- if (c == '\033')
- {
- intermediate = 0;
- curr->state = ESC;
- if (display && lp_missing && (CIC || IC || IM))
- {
- RedisplayLine(blank, null, null, screenbot,
- cols - 2, cols - 1);
- GotoPos(curr->x, curr->y);
- }
- if (curr->autoaka < 0)
- curr->autoaka = 0;
- }
- else if (c < ' ')
- break;
- else
- {
- NewRendition(curr->LocalAttr);
- NewCharset(curr->charsets[(curr->ss) ? curr->ss :
- curr->LocalCharset]);
- if (curr->x < cols - 1)
- {
- if (curr->insert)
- InsertAChar(c);
- else
- {
- if (display)
- PUTCHAR(c);
- SetChar(c);
- }
- curr->x++;
- }
- else if (curr->x == cols - 1)
- {
- if (curr->wrap && (LP || !force_vt || COP))
- {
- if (display)
- RAW_PUTCHAR(c);
- SetChar(c);
- if (AM && !LP)
- {
- curr->x = 0; /* terminal auto-wrapped */
- LineFeed(0);
- }
- else
- curr->x++;
- }
- else
- {
- if (display)
- {
- if (LP || curr->y != screenbot)
- {
- RAW_PUTCHAR(c);
- GotoPos(curr->x, curr->y);
- }
- else
- CheckLP(c);
- }
- SetChar(c);
- if (curr->wrap)
- curr->x++;
- }
- }
- else
- {
- LineFeed(2); /* cr+lf, handle LP */
- if (curr->insert)
- InsertAChar(c);
- else
- {
- if (display)
- PUTCHAR(c);
- SetChar(c);
- }
- curr->x = 1;
- }
- if (curr->ss)
- {
- NewCharset(curr->charsets[curr->LocalCharset]);
- curr->ss = 0;
- }
- }
- }
- }
- } while (--len);
- curr->outlen = 0;
- if (curr->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->autoaka)
- FindAKA();
- LineFeed(1);
- return 1;
- case '\007':
- if (!visual_bell)
- PutStr(BL);
- else
- {
- if (!VB)
- curr->bell = BELL_VISUAL;
- else
- PutStr(VB);
- }
- if (!display)
- curr->bell = BELL_ON;
- 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;
- {
- switch (intermediate)
- {
- case 0:
- switch (c)
- {
- case 'E':
- LineFeed(2);
- break;
- case 'D':
- LineFeed(1);
- break;
- case 'M':
- ReverseLineFeed();
- break;
- case 'H':
- curr->tabs[curr->x] = 1;
- break;
- case 'Z': /* jph: Identify as VT100 */
- Report(curr, "\033[?%d;%dc", 1, 2);
- break;
- case '7':
- SaveCursor();
- break;
- case '8':
- RestoreCursor();
- break;
- case 'c':
- ClearScreen();
- ResetScreen(curr);
- NewRendition(0);
- NewCharset(ASCII);
- InsertMode(0);
- KeypadMode(0);
- ChangeScrollRegion(0, rows-1);
- break;
- case '=':
- KeypadMode(curr->keypad = 1);
- #if !defined(TIOCPKT) || defined(sgi)
- NewAutoFlow(curr, 0);
- #endif /* !TIOCPKT || sgi */
- break;
- case '>':
- KeypadMode(curr->keypad = 0);
- #if !defined(TIOCPKT) || defined(sgi)
- NewAutoFlow(curr, 1);
- #endif /* !TIOCPKT || sgi */
- break;
- case 'n': /* LS2 */
- MapCharset(G2);
- break;
- case 'o': /* LS3 */
- MapCharset(G3);
- break;
- case 'N': /* SS2 */
- if (curr->charsets[curr->LocalCharset] != curr->charsets[G2])
- curr->ss = G2;
- else
- curr->ss = 0;
- break;
- case 'O': /* SS3 */
- if (curr->charsets[curr->LocalCharset] != curr->charsets[G3])
- curr->ss = G3;
- else
- curr->ss = 0;
- 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;
- }
- }
-
- static void DoCSI(c, intermediate)
- int c, intermediate;
- {
- register int i, a1 = curr->args[0], a2 = curr->args[1];
-
- if (curr->NumArgs > MAXARGS)
- curr->NumArgs = MAXARGS;
- switch (intermediate)
- {
- case 0:
- switch (c)
- {
- case 'H':
- case 'f':
- if (a1 < 1)
- a1 = 1;
- if (curr->origin)
- a1 += curr->top;
- if (a1 > rows)
- a1 = rows;
- if (a2 < 1)
- a2 = 1;
- if (a2 > cols)
- a2 = cols;
- GotoPos(--a2, --a1);
- curr->x = a2;
- curr->y = a1;
- if (curr->autoaka)
- curr->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->x, curr->y);
- break;
- }
- break;
- case 'K':
- if (a1 < 0 || a1 > 2)
- a1 %= 3;
- switch (a1)
- {
- case 0:
- ClearToEOL();
- break;
- case 1:
- ClearFromBOL();
- break;
- case 2:
- ClearLine();
- 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->tabs[curr->x] = 0;
- else if (a1 == 3)
- bzero(curr->tabs, cols);
- break;
- case 'r':
- if (!a1)
- a1 = 1;
- if (!a2)
- a2 = rows;
- if (a1 < 1 || a2 > rows || a1 >= a2)
- break;
- curr->top = a1 - 1;
- curr->bot = a2 - 1;
- ChangeScrollRegion(curr->top, curr->bot);
- if (curr->origin)
- {
- GotoPos(0, curr->top);
- curr->y = curr->top;
- curr->x = 0;
- }
- else
- {
- GotoPos(0, 0);
- curr->y = curr->x = 0;
- }
- break;
- case 's':
- SaveCursor();
- break;
- case 't':
- if (a1 != 8)
- break;
- a1 = curr->args[2];
- if (a1 < 1)
- a1 = curr->width;
- if (a2 < 1)
- a2 = curr->height;
- if (WS == NULL)
- {
- a2 = curr->height;
- if (Z0 == NULL || (a1 != Z0width && a1 != Z1width))
- a1 = curr->width;
- }
- if (a1 == curr->width && a2 == curr->height)
- break;
- ChangeWindowSize(curr, a1, a2);
- 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 (PO && a1 == 5)
- {
- curr->stringp = curr->string;
- curr->state = PRIN;
- }
- break;
- case 'n':
- if (a1 == 6) /* Report cursor position */
- Report(curr, "\033[%d;%dR", curr->y + 1, curr->x + 1);
- break;
- case 'c': /* Identify as VT100 */
- Report(curr, "\033[?%d;%dc", 1, 2);
- break;
- }
- break;
- case '?':
- debug2("\\E[?%d%c\n",a1,c);
- if (c != 'h' && c != 'l')
- break;
- i = (c == 'h');
- switch (a1)
- {
- case 3:
- i = (i ? Z0width : Z1width);
- if ((Z0 || WS) && curr->width != i)
- {
- ChangeWindowSize(curr, i, curr->height);
- SetCurr(curr);
- if (display)
- Activate(0);
- }
- break;
- case 5:
- if (i)
- curr->vbwait = 1;
- else
- {
- if (curr->vbwait)
- PutStr(VB);
- curr->vbwait = 0;
- }
- break;
- case 6:
- if ((curr->origin = i) != 0)
- {
- GotoPos(0, curr->top);
- curr->y = curr->top;
- curr->x = 0;
- }
- else
- {
- GotoPos(0, 0);
- curr->y = curr->x = 0;
- }
- break;
- case 7:
- curr->wrap = i;
- break;
- case 35:
- debug1("Cursor %svisible\n", i?"in":"");
- curr->cursor_invisible = i;
- break;
- }
- break;
- }
- }
-
- void
- INSERTCHAR(c)
- int c;
- {
- if (!insert && (IC || CIC))
- {
- if (IC)
- PutStr(IC);
- else
- CPutStr(CIC, 1);
- RAW_PUTCHAR(c);
- return;
- }
- InsertMode(1);
- if (insert)
- RAW_PUTCHAR(c);
- else
- RefreshLine(screeny, screenx, screenwidth-1);
- }
-
- void
- PUTCHAR(c)
- int c;
- {
- if (insert)
- InsertMode(0);
- RAW_PUTCHAR(c);
- }
-
- /*
- * RAW_PUTCHAR() is for all text that will be displayed.
- * NOTE, that charset Nr. 0 has a conversion table, but c1, c2, ... don't.
- */
-
- static void
- RAW_PUTCHAR(c)
- int c;
- {
- if (GlobalCharset == '0')
- putchar(c0_tab[c]);
- else
- putchar(c);
- if (screenx < screenwidth - 1)
- screenx++;
- else
- {
- screenx++;
- if ((AM && !LP) || screenx > screenwidth)
- {
- screenx -= screenwidth;
- if (screeny < screenheight-1 && screeny != screenbot)
- screeny++;
- }
- }
- }
-
- void
- PutChar(c)
- int c;
- {
- /* this PutChar for ESC-sequences only */
- putchar(c);
- }
-
- void
- PutStr(s)
- char *s;
- {
- if (display && s)
- tputs(s, 1, PutChar);
- }
-
- static void CPutStr(s, c)
- char *s;
- int c;
- {
- if (display && s)
- tputs(tgoto(s, 0, c), 1, PutChar);
- }
-
- static void SetChar(c)
- register int c;
- {
- register struct win *p = curr;
-
- p->image[p->y][p->x] = c;
- p->attr[p->y][p->x] = p->LocalAttr;
- p->font[p->y][p->x] = p->charsets[p->ss ? p->ss : p->LocalCharset];
- }
-
- static void StartString(type)
- enum string_t type;
- {
- curr->StringType = type;
- curr->stringp = curr->string;
- curr->state = ASTR;
- }
-
- static void AddChar(c)
- int c;
- {
- if (curr->stringp >= curr->string + MAXSTR - 1)
- curr->state = LIT;
- else
- *(curr->stringp)++ = c;
- }
-
- static void PrintChar(c)
- int c;
- {
- if (curr->stringp >= curr->string + MAXSTR - 1)
- PrintFlush();
- *(curr->stringp)++ = c;
- }
-
- static void PrintFlush()
- {
- if (curr->stringp > curr->string)
- {
- tputs(PO, 1, PutChar);
- (void) fflush(stdout);
- (void) write(1, curr->string, curr->stringp - curr->string);
- tputs(PF, 1, PutChar);
- (void) fflush(stdout);
- curr->stringp = curr->string;
- }
- }
-
- /* Insert mode is a toggle on some terminals, so we need this hack:
- */
- void
- InsertMode(on)
- int on;
- {
- if (display && on != insert && IM)
- {
- insert = on;
- if (insert)
- PutStr(IM);
- else
- PutStr(EI);
- }
- }
-
- /* ...and maybe keypad application mode is a toggle, too:
- */
- static void KeypadMode(on)
- int on;
- {
- if (display && keypad != on && KS)
- {
- keypad = on;
- if (keypad)
- PutStr(KS);
- else
- PutStr(KE);
- }
- }
-
- void
- NewAutoFlow(win, on)
- struct win *win;
- int on;
- {
- debug1("NewAutoFlow: %d\n", on);
- SetCurr(win);
- if (win->flow & FLOW_AUTOFLAG)
- win->flow = FLOW_AUTOFLAG | (FLOW_AUTO|FLOW_NOW) * on;
- else
- win->flow = (win->flow & ~FLOW_AUTO) | FLOW_AUTO * on;
- if (display)
- SetFlow(win->flow & FLOW_NOW);
- }
-
- static void DesignateCharset(c, n)
- int c, n;
- {
- curr->ss = 0;
- if (c == 'B')
- c = ASCII;
- if (curr->charsets[n] != c)
- {
- curr->charsets[n] = c;
- if (curr->LocalCharset == n)
- NewCharset(c);
- }
- }
-
- static void MapCharset(n)
- int n;
- {
- curr->ss = 0;
- if (curr->LocalCharset != n)
- {
- curr->LocalCharset = n;
- NewCharset(curr->charsets[n]);
- }
- }
-
- void
- NewCharset(new)
- int new;
- {
- if (!display || GlobalCharset == new)
- return;
- GlobalCharset = new;
- if (new == ASCII)
- PutStr(E0);
- else
- CPutStr(S0, new);
- }
-
- static void SaveCursor()
- {
- curr->saved = 1;
- curr->Saved_x = curr->x;
- curr->Saved_y = curr->y;
- curr->SavedLocalAttr = curr->LocalAttr;
- curr->SavedLocalCharset = curr->LocalCharset;
- bcopy((char *) curr->charsets, (char *) curr->SavedCharsets,
- 4 * sizeof(int));
- }
-
- static void RestoreCursor()
- {
- if (curr->saved)
- {
- GotoPos(curr->Saved_x, curr->Saved_y);
- curr->x = curr->Saved_x;
- curr->y = curr->Saved_y;
- curr->LocalAttr = curr->SavedLocalAttr;
- NewRendition(curr->LocalAttr);
- bcopy((char *) curr->SavedCharsets, (char *) curr->charsets,
- 4 * sizeof(int));
- curr->LocalCharset = curr->SavedLocalCharset;
- NewCharset(curr->charsets[curr->LocalCharset]);
- }
- }
-
- /*ARGSUSED*/
- static void CountChars(c)
- int c;
- {
- StrCost++;
- }
-
- static int CalcCost(s)
- register char *s;
- {
- if (s)
- {
- StrCost = 0;
- tputs(s, 1, CountChars);
- return StrCost;
- }
- else
- return EXPENSIVE;
- }
-
- void
- GotoPos(x2, y2)
- int x2, y2;
- {
- register int dy, dx, x1, y1;
- register int costx, costy;
- register int m;
- register char *s;
- int CMcost;
- enum move_t xm = M_NONE, ym = M_NONE;
-
- if (!display)
- return;
-
- x1 = screenx;
- y1 = screeny;
-
- if (x1 == screenwidth)
- if (LP && AM)
- x1 = -1; /* don't know how the terminal treats this */
- else
- x1--;
- if (x2 == screenwidth)
- x2--;
- dx = x2 - x1;
- dy = y2 - y1;
- if (dy == 0 && dx == 0)
- {
- return;
- }
- if (!MS && GlobalAttr) /* Safe to move in SO mode ? */
- NewRendition(0);
- if (y1 < 0 /* don't know the y position */
- || (y2 > screenbot && y1 <= screenbot) /* have to cross border */
- || (y2 < screentop && y1 >= screentop)) /* of scrollregion ? */
- {
- DoCM:
- if (HO && !x2 && !y2)
- PutStr(HO);
- else
- PutStr(tgoto(CM, x2, y2));
- screenx = x2;
- screeny = y2;
- return;
- }
- /* Calculate CMcost */
- if (HO && !x2 && !y2)
- s = HO;
- else
- s = tgoto(CM, x2, y2);
- CMcost = CalcCost(s);
-
- /* Calculate the cost to move the cursor to the right x position */
- costx = EXPENSIVE;
- if (x1 >= 0) /* relativ x positioning only if we know where we are */
- {
- if (dx > 0)
- {
- if (CRI && (dx > 1 || !ND))
- {
- costx = CalcCost(tgoto(CRI, 0, dx));
- xm = M_CRI;
- }
- if ((m = NDcost * dx) < costx)
- {
- costx = m;
- xm = M_RI;
- }
- /* Speedup: dx <= Rewrite() */
- if (dx < costx && (m = Rewrite(y1, x1, x2, 0)) < costx)
- {
- costx = m;
- xm = M_RW;
- }
- }
- else if (dx < 0)
- {
- if (CLE && (dx < -1 || !BC))
- {
- costx = CalcCost(tgoto(CLE, 0, -dx));
- xm = M_CLE;
- }
- if ((m = -dx * LEcost) < costx)
- {
- costx = m;
- xm = M_LE;
- }
- }
- else
- costx = 0;
- }
- /* Speedup: Rewrite() >= x2 */
- if (x2 + CRcost < costx && (m = Rewrite(y1, 0, x2, 0) + CRcost) < costx)
- {
- costx = m;
- xm = M_CR;
- }
-
- /* Check if it is already cheaper to do CM */
- if (costx >= CMcost)
- goto DoCM;
-
- /* Calculate the cost to move the cursor to the right y position */
- costy = EXPENSIVE;
- if (dy > 0)
- {
- if (CDO && dy > 1) /* DO & NL are always != 0 */
- {
- costy = CalcCost(tgoto(CDO, 0, dy));
- ym = M_CDO;
- }
- if ((m = dy * ((x2 == 0) ? NLcost : DOcost)) < costy)
- {
- costy = m;
- ym = M_DO;
- }
- }
- else if (dy < 0)
- {
- if (CUP && (dy < -1 || !UP))
- {
- costy = CalcCost(tgoto(CUP, 0, -dy));
- ym = M_CUP;
- }
- if ((m = -dy * UPcost) < costy)
- {
- costy = m;
- ym = M_UP;
- }
- }
- else
- costy = 0;
-
- /* Finally check if it is cheaper to do CM */
- if (costx + costy >= CMcost)
- goto DoCM;
-
- switch (xm)
- {
- case M_LE:
- while (dx++ < 0)
- PutStr(BC);
- break;
- case M_CLE:
- CPutStr(CLE, -dx);
- break;
- case M_RI:
- while (dx-- > 0)
- PutStr(ND);
- break;
- case M_CRI:
- CPutStr(CRI, dx);
- break;
- case M_CR:
- PutStr(CR);
- screenx = 0;
- x1 = 0;
- /* FALLTHROUGH */
- case M_RW:
- if (x1 < x2)
- (void) Rewrite(y1, x1, x2, 1);
- break;
- default:
- break;
- }
- switch (ym)
- {
- case M_UP:
- while (dy++ < 0)
- PutStr(UP);
- break;
- case M_CUP:
- CPutStr(CUP, -dy);
- break;
- case M_DO:
- s = (x2 == 0) ? NL : DO;
- while (dy-- > 0)
- PutStr(s);
- break;
- case M_CDO:
- CPutStr(CDO, dy);
- break;
- default:
- break;
- }
- screenx = x2;
- screeny = y2;
- }
-
- static int
- Rewrite(y, x1, x2, doit)
- int y, x1, x2, doit;
- {
- register int cost, dx;
- register char *p, *f, *i;
-
- if (x1 == x2)
- return(0);
- if (in_ovl)
- {
- if (ovl_Rewrite == 0)
- return EXPENSIVE;
- else
- return ((*ovl_Rewrite)(y, x1, x2, doit));
- }
- dx = x2 - x1;
- if (doit)
- {
- i = curr->image[y] + x1;
- while (dx-- > 0)
- PUTCHAR(*i++);
- return(0);
- }
- p = curr->attr[y] + x1;
- f = curr->font[y] + x1;
-
- cost = dx = x2 - x1;
- if (insert)
- cost += EIcost + IMcost;
- while(dx-- > 0)
- {
- if (*p++ != GlobalAttr || *f++ != GlobalCharset)
- return EXPENSIVE;
- }
- return cost;
- }
-
- static void BackSpace()
- {
- if (curr->x > 0)
- {
- curr->x--;
- }
- else if (curr->wrap && curr->y > 0)
- {
- curr->x = cols - 1;
- curr->y--;
- }
- if (display)
- GotoPos(curr->x, curr->y);
- }
-
- static void Return()
- {
- if (curr->x > 0)
- {
- curr->x = 0;
- if (display)
- GotoPos(curr->x, curr->y);
- }
- }
-
- static void LineFeed(out_mode)
- int out_mode;
- {
- /* out_mode: 0=no-output lf, 1=lf, 2=cr+lf */
- if (out_mode == 2)
- curr->x = 0;
- if (curr->y != curr->bot) /* Don't scroll */
- {
- if (curr->y < rows-1)
- curr->y++;
- if (out_mode && display)
- GotoPos(curr->x, curr->y);
- return;
- }
- ScrollUpMap(1);
- if (curr->autoaka > 1)
- curr->autoaka--;
- if (out_mode && display)
- {
- ScrollRegion(curr->top, curr->bot, 1);
- GotoPos(curr->x, curr->y);
- }
- }
-
- static void ReverseLineFeed()
- {
- if (curr->y == curr->top)
- {
- ScrollDownMap(1);
- if (!display)
- return;
- ScrollRegion(curr->top, curr->bot, -1);
- GotoPos(curr->x, curr->y);
- }
- else if (curr->y > 0)
- CursorUp(1);
- }
-
- static void InsertAChar(c)
- int c;
- {
- register int y = curr->y, x = curr->x;
-
- if (x == cols)
- x--;
- bcopy(curr->image[y], OldImage, cols);
- bcopy(curr->attr[y], OldAttr, cols);
- bcopy(curr->font[y], OldFont, cols);
- bcopy(curr->image[y] + x, curr->image[y] + x + 1, cols - x - 1);
- bcopy(curr->attr[y] + x, curr->attr[y] + x + 1, cols - x - 1);
- bcopy(curr->font[y] + x, curr->font[y] + x + 1, cols - x - 1);
- SetChar(c);
- if (!display)
- return;
- if (CIC || IC || IM)
- {
- InsertMode(curr->insert);
- INSERTCHAR(c);
- if (y == screenbot)
- lp_missing = 0;
- }
- else
- {
- RedisplayLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
- GotoPos(++x, y);
- }
- }
-
- static void InsertChar(n)
- int n;
- {
- register int i, y = curr->y, x = curr->x;
-
- if (n <= 0)
- return;
- /*
- * The termcap manual states that only one of IM and IC is
- * to be defined unless the terminal needs both sequences.
- * We don't like this because we think that there may be cases
- * where it is preferable to send IC instead of IM/EI.
- * The hack is to ignore the IC sequence if we are already
- * in insert mode, so that programs which follow the termcap
- * guidelines still work. (I don't believe that there are
- * terminals which need IC in the insert mode. Why switch to
- * insert mode if you must send IC before every character ?)
- */
- if (curr->insert)
- return;
- if (x == cols)
- --x;
- bcopy(curr->image[y], OldImage, cols);
- bcopy(curr->attr[y], OldAttr, cols);
- bcopy(curr->font[y], OldFont, cols);
- if (n > cols - x)
- n = cols - x;
- bcopy(curr->image[y] + x, curr->image[y] + x + n, cols - x - n);
- bcopy(curr->attr[y] + x, curr->attr[y] + x + n, cols - x - n);
- bcopy(curr->font[y] + x, curr->font[y] + x + n, cols - x - n);
- ClearInLine(0, y, x, x + n - 1);
- if (!display)
- return;
- if (IC || CIC || IM)
- {
- if (y == screenbot)
- lp_missing = 0;
- if (!insert)
- {
- if (n == 1 && IC)
- {
- PutStr(IC);
- return;
- }
- if (CIC)
- {
- CPutStr(CIC, n);
- return;
- }
- }
- InsertMode(1);
- for (i = n; i--; )
- INSERTCHAR(' ');
- GotoPos(x, y);
- }
- else
- {
- RedisplayLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
- GotoPos(x, y);
- }
- }
-
- static void DeleteChar(n)
- int n;
- {
- register int i, y = curr->y, x = curr->x;
-
- if (x == cols)
- --x;
- bcopy(curr->image[y], OldImage, cols);
- bcopy(curr->attr[y], OldAttr, cols);
- bcopy(curr->font[y], OldFont, cols);
- if (n > cols - x)
- n = cols - x;
- bcopy(curr->image[y] + x + n, curr->image[y] + x, cols - x - n);
- bcopy(curr->attr[y] + x + n, curr->attr[y] + x, cols - x - n);
- bcopy(curr->font[y] + x + n, curr->font[y] + x, cols - x - n);
- ClearInLine(0, y, cols - n, cols - 1);
- if (!display)
- return;
- if (CDC && !(n == 1 && DC))
- {
- CPutStr(CDC, n);
- if (lp_missing && y == screenbot)
- {
- FixLP(cols - 1 - n, y);
- GotoPos(x, y);
- }
- }
- else if (DC)
- {
- for (i = n; i; i--)
- PutStr(DC);
- if (lp_missing && y == screenbot)
- {
- FixLP(cols - 1 - n, y);
- GotoPos(x, y);
- }
- }
- else
- {
- RedisplayLine(OldImage, OldAttr, OldFont, y, x, cols - 1);
- GotoPos(x, y);
- }
- }
-
- static void DeleteLine(n)
- int n;
- {
- register int old = curr->top;
-
- if (curr->y < curr->top || curr->y > curr->bot)
- return;
- if (n > curr->bot - curr->y + 1)
- n = curr->bot - curr->y + 1;
- curr->top = curr->y;
- ScrollUpMap(n);
- curr->top = old;
- if (!display)
- return;
- ScrollRegion(curr->y, curr->bot, n);
- GotoPos(curr->x, curr->y);
- }
-
- static void InsertLine(n)
- int n;
- {
- register int old = curr->top;
-
- if (curr->y < curr->top || curr->y > curr->bot)
- return;
- if (n > curr->bot - curr->y + 1)
- n = curr->bot - curr->y + 1;
- curr->top = curr->y;
- ScrollDownMap(n);
- curr->top = old;
- if (!display)
- return;
- ScrollRegion(curr->y, curr->bot, -n);
- GotoPos(curr->x, curr->y);
- }
-
- void
- ScrollRegion(ys, ye, n)
- int ys, ye, n;
- {
- int i;
- int up;
- int oldtop, oldbot;
- int alok, dlok, aldlfaster;
- int missy = 0;
-
- if (n == 0)
- return;
- if (ys == 0 && ye == screenheight-1 &&
- (n >= screenheight || -n >= screenheight))
- {
- PutStr(CL);
- screeny = screenx = 0;
- lp_missing = 0;
- return;
- }
-
- if (lp_missing)
- {
- if (screenbot>ye || screenbot<ys)
- missy = screenbot;
- else
- {
- missy = screenbot - n;
- if (missy>ye || missy<ys)
- lp_missing = 0;
- }
- }
-
- up = 1;
- if (n < 0)
- {
- up = 0;
- n = -n;
- }
- if (n >= ye-ys+1)
- n = ye-ys+1;
-
- oldtop = screentop;
- oldbot = screenbot;
- if (screenbot != ye)
- ChangeScrollRegion(ys, ye);
- alok = (AL || CAL || (ye == screenbot && up));
- dlok = (DL || CDL || (ye == screenbot && !up));
- if (screentop != ys && !(alok && dlok))
- ChangeScrollRegion(ys, ye);
-
- if (lp_missing &&
- (oldbot != screenbot ||
- (oldbot == screenbot && up && screentop == ys && screenbot == ye)))
- {
- /* Can't use FixLP */
- GotoPos(screenwidth-1, oldbot);
- SaveSetAttr(curr->attr[missy][screenwidth-1], curr->font[missy][screenwidth-1]);
- PUTCHAR(curr->image[missy][screenwidth-1]);
- RestoreAttr();
- lp_missing = 0;
- if (oldbot == screenbot) /* have scrolled */
- {
- if (--n == 0)
- {
- ChangeScrollRegion(oldtop, oldbot);
- return;
- }
- }
- }
-
- aldlfaster = (n > 1 && ye == screenbot && ((up && CDL) || (!up && CAL)));
-
- if ((up || SR) && screentop == ys && screenbot == ye && !aldlfaster)
- {
- if (up)
- {
- GotoPos(0, ye);
- while (n-- > 0)
- PutStr(NL); /* was SF, I think NL is faster */
- }
- else
- {
- GotoPos(0, ys);
- while (n-- > 0)
- PutStr(SR);
- }
- }
- else if (alok && dlok)
- {
- if (up || ye != screenbot)
- {
- GotoPos(0, up ? ys : ye+1-n);
- if (CDL && !(n == 1 && DL))
- CPutStr(CDL, n);
- else
- for(i=n; i--; )
- PutStr(DL);
- }
- if (!up || ye != screenbot)
- {
- GotoPos(0, up ? ye+1-n : ys);
- if (CAL && !(n == 1 && AL))
- CPutStr(CAL, n);
- else
- for(i=n; i--; )
- PutStr(AL);
- }
- }
- else
- {
- Redisplay(0);
- return;
- }
- if (lp_missing && missy != screenbot)
- FixLP(screenwidth-1, missy);
- ChangeScrollRegion(oldtop, oldbot);
- if (lp_missing && missy != screenbot)
- FixLP(screenwidth-1, missy);
- }
-
- static void ScrollUpMap(n)
- int n;
- {
- char tmp[256 * sizeof(char *)];
- register int ii, i, cnt1, cnt2;
- register char **ppi, **ppa, **ppf;
-
- i = curr->top + n;
- cnt1 = n * sizeof(char *);
- cnt2 = (curr->bot - i + 1) * sizeof(char *);
- ppi = curr->image + i;
- ppa = curr->attr + i;
- ppf = curr->font + i;
- for(ii = curr->top; ii < i; ii++)
- AddLineToHist(curr, &curr->image[ii], &curr->attr[ii], &curr->font[ii]);
- for (i = n; i; --i)
- {
- bclear(*--ppi, cols);
- bzero(*--ppa, cols);
- bzero(*--ppf, cols);
- }
- Scroll((char *) ppi, cnt1, cnt2, tmp);
- Scroll((char *) ppa, cnt1, cnt2, tmp);
- Scroll((char *) ppf, cnt1, cnt2, tmp);
- }
-
- static void ScrollDownMap(n)
- int n;
- {
- char tmp[256 * sizeof(char *)];
- register int i, cnt1, cnt2;
- register char **ppi, **ppa, **ppf;
-
- i = curr->top;
- cnt1 = (curr->bot - i - n + 1) * sizeof(char *);
- cnt2 = n * sizeof(char *);
- Scroll((char *) (ppi = curr->image + i), cnt1, cnt2, tmp);
- Scroll((char *) (ppa = curr->attr + i), cnt1, cnt2, tmp);
- Scroll((char *) (ppf = curr->font + i), cnt1, cnt2, tmp);
- for (i = n; i; --i)
- {
- bclear(*ppi++, cols);
- bzero(*ppa++, cols);
- bzero(*ppf++, cols);
- }
- }
-
- 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->x;
-
- if (x == cols)
- {
- LineFeed(2);
- x = 0;
- }
- if (curr->tabs[x] && x < cols - 1)
- x++;
- while (x < cols - 1 && !curr->tabs[x])
- x++;
- GotoPos(x, curr->y);
- curr->x = x;
- }
-
- static void BackwardTab()
- {
- register int x = curr->x;
-
- if (curr->tabs[x] && x > 0)
- x--;
- while (x > 0 && !curr->tabs[x])
- x--;
- GotoPos(x, curr->y);
- curr->x = x;
- }
-
- static void ClearScreen()
- {
- register int i;
- register char **ppi = curr->image, **ppa = curr->attr, **ppf = curr->font;
-
- for (i = 0; i < rows; ++i)
- {
- AddLineToHist(curr, ppi, ppa, ppf);
- bclear(*ppi++, cols);
- bzero(*ppa++, cols);
- bzero(*ppf++, cols);
- }
- if (display)
- {
- PutStr(CL);
- screenx = screeny = 0;
- lp_missing = 0;
- }
- }
-
- static void ClearFromBOS()
- {
- register int n, y = curr->y, x = curr->x;
-
- for (n = 0; n < y; ++n)
- ClearInLine(1, n, 0, cols - 1);
- ClearInLine(1, y, 0, x);
- GotoPos(x, y);
- RestoreAttr();
- }
-
- static void ClearToEOS()
- {
- register int n, y = curr->y, x = curr->x;
-
- if (!y && !x)
- {
- ClearScreen();
- return;
- }
- if (display && CD)
- {
- PutStr(CD);
- lp_missing = 0;
- }
- ClearInLine(!CD, y, x, cols - 1);
- for (n = y + 1; n < rows; n++)
- ClearInLine(!CD, n, 0, cols - 1);
- GotoPos(x, y);
- RestoreAttr();
- }
-
- static void ClearLine()
- {
- register int y = curr->y, x = curr->x;
-
- ClearInLine(1, y, 0, cols - 1);
- GotoPos(x, y);
- RestoreAttr();
- }
-
- static void ClearToEOL()
- {
- register int y = curr->y, x = curr->x;
-
- ClearInLine(1, y, x, cols - 1);
- GotoPos(x, y);
- RestoreAttr();
- }
-
- static void ClearFromBOL()
- {
- register int y = curr->y, x = curr->x;
-
- ClearInLine(1, y, 0, x);
- GotoPos(x, y);
- RestoreAttr();
- }
-
- static void ClearInLine(displ, y, x1, x2)
- int displ, y, x1, x2;
- {
- register int n;
-
- if (x1 == cols)
- x1--;
- if (x2 == cols)
- x2--;
- if ((n = x2 - x1 + 1) != 0)
- {
- if (displ && display)
- {
- if (x2 == cols - 1 && CE)
- {
- GotoPos(x1, y);
- PutStr(CE);
- if (y == screenbot)
- lp_missing = 0;
- }
- else
- DisplayLine(curr->image[y], curr->attr[y], curr->font[y],
- blank, null, null, y, x1, x2);
- }
- if (curr)
- {
- bclear(curr->image[y] + x1, n);
- bzero(curr->attr[y] + x1, n);
- bzero(curr->font[y] + x1, n);
- }
- }
- }
-
- static void CursorRight(n)
- register int n;
- {
- register int x = curr->x;
-
- if (x == cols)
- {
- LineFeed(2);
- x = 0;
- }
- if ((curr->x += n) >= cols)
- curr->x = cols - 1;
- GotoPos(curr->x, curr->y);
- }
-
- static void CursorUp(n)
- register int n;
- {
- if (curr->y < curr->top) /* if above scrolling rgn, */
- {
- if ((curr->y -= n) < 0) /* ignore its limits */
- curr->y = 0;
- }
- else
- if ((curr->y -= n) < curr->top)
- curr->y = curr->top;
- GotoPos(curr->x, curr->y);
- }
-
- static void CursorDown(n)
- register int n;
- {
- if (curr->y > curr->bot) /* if below scrolling rgn, */
- {
- if ((curr->y += n) > rows - 1) /* ignore its limits */
- curr->y = rows - 1;
- }
- else
- if ((curr->y += n) > curr->bot)
- curr->y = curr->bot;
- GotoPos(curr->x, curr->y);
- }
-
- static void CursorLeft(n)
- register int n;
- {
- if ((curr->x -= n) < 0)
- curr->x = 0;
- GotoPos(curr->x, curr->y);
- }
-
- static void ASetMode(on)
- int on;
- {
- register int i;
-
- for (i = 0; i < curr->NumArgs; ++i)
- {
- switch (curr->args[i])
- {
- case 4:
- curr->insert = on;
- InsertMode(on);
- break;
- }
- }
- }
-
- static void SelectRendition()
- {
- register int i = 0, a = curr->LocalAttr;
-
- do
- {
- switch (curr->args[i])
- {
- case 0:
- a = 0;
- break;
- case 1:
- a |= A_BD;
- break;
- case 2:
- a |= A_DI;
- break;
- case 3:
- a |= A_SO;
- break;
- case 4:
- a |= A_US;
- break;
- case 5:
- a |= A_BL;
- break;
- case 7:
- a |= A_RV;
- break;
- case 22:
- a &= ~(A_BD | A_SO | A_DI);
- break;
- case 23:
- a &= ~A_SO;
- break;
- case 24:
- a &= ~A_US;
- break;
- case 25:
- a &= ~A_BL;
- break;
- case 27:
- a &= ~A_RV;
- break;
- }
- } while (++i < curr->NumArgs);
- NewRendition(curr->LocalAttr = a);
- }
-
- void
- NewRendition(new)
- register int new;
- {
- register int i, old = GlobalAttr;
-
- if (!display || old == new)
- return;
- GlobalAttr = new;
- for (i = 1; i <= A_MAX; i <<= 1)
- {
- if ((old & i) && !(new & i))
- {
- PutStr(UE);
- PutStr(SE);
- PutStr(ME);
- if (new & A_DI)
- PutStr(attrtab[ATTR_DI]);
- if (new & A_US)
- PutStr(attrtab[ATTR_US]);
- if (new & A_BD)
- PutStr(attrtab[ATTR_BD]);
- if (new & A_RV)
- PutStr(attrtab[ATTR_RV]);
- if (new & A_SO)
- PutStr(attrtab[ATTR_SO]);
- if (new & A_BL)
- PutStr(attrtab[ATTR_BL]);
- return;
- }
- }
- if ((new & A_DI) && !(old & A_DI))
- PutStr(attrtab[ATTR_DI]);
- if ((new & A_US) && !(old & A_US))
- PutStr(attrtab[ATTR_US]);
- if ((new & A_BD) && !(old & A_BD))
- PutStr(attrtab[ATTR_BD]);
- if ((new & A_RV) && !(old & A_RV))
- PutStr(attrtab[ATTR_RV]);
- if ((new & A_SO) && !(old & A_SO))
- PutStr(attrtab[ATTR_SO]);
- if ((new & A_BL) && !(old & A_BL))
- PutStr(attrtab[ATTR_BL]);
- }
-
- void
- SaveSetAttr(newattr, newcharset)
- int newattr, newcharset;
- {
- NewRendition(newattr);
- NewCharset(newcharset);
- }
-
- void
- RestoreAttr()
- {
- NewRendition(curr->LocalAttr);
- NewCharset(curr->charsets[curr->LocalCharset]);
- }
-
- static void FillWithEs()
- {
- register int i;
- register char *p, *ep;
-
- curr->y = curr->x = 0;
- for (i = 0; i < rows; ++i)
- {
- bzero(curr->attr[i], cols);
- bzero(curr->font[i], cols);
- p = curr->image[i];
- ep = p + cols;
- while (p < ep)
- *p++ = 'E';
- }
- if (display)
- Redisplay(0);
- }
-
- /*
- * if cur_only, we only redisplay current line, as a full refresh is
- * too expensive.
- */
- void Redisplay(cur_only)
- int cur_only;
- {
- register int i, stop;
-
- PutStr(CL);
- screenx = screeny = 0;
- lp_missing = 0;
- stop = rows; i = 0;
- if (cur_only)
- {
- i = stop = curr->y;
- stop++;
- }
- for (; i < stop; ++i)
- {
- if (in_ovl)
- (*ovl_RedisplayLine)(i, 0, cols - 1, 1);
- else
- DisplayLine(blank, null, null, curr->image[i], curr->attr[i],
- curr->font[i], i, 0, cols - 1);
- }
- if (!in_ovl)
- {
- GotoPos(curr->x, curr->y);
- NewRendition(curr->LocalAttr);
- NewCharset(curr->charsets[curr->LocalCharset]);
- }
- }
-
- void
- DisplayLine(os, oa, of, s, as, fs, y, from, to)
- int from, to, y;
- register char *os, *oa, *of, *s, *as, *fs;
- {
- register int x;
- int last2flag = 0, delete_lp = 0;
-
- if (!LP && y == screenbot && to == cols - 1)
- if (lp_missing
- || s[to] != os[to] || as[to] != oa[to] || of[to] != fs[to])
- {
- if ((IC || IM) && (from < to || !in_ovl))
- {
- if ((to -= 2) < from - 1)
- from--;
- last2flag = 1;
- lp_missing = 0;
- }
- else
- {
- to--;
- delete_lp = (CE || DC || CDC);
- lp_missing = (s[to] != ' ' || as[to] || fs[to]);
- }
- }
- else
- to--;
- for (x = from; x <= to; ++x)
- {
- if (s[x] == os[x] && as[x] == oa[x] && of[x] == fs[x])
- continue;
- GotoPos(x, y);
- NewRendition(as[x]);
- NewCharset(fs[x]);
- PUTCHAR(s[x]);
- }
- if (last2flag)
- {
- GotoPos(x, y);
- NewRendition(as[x + 1]);
- NewCharset(fs[x + 1]);
- PUTCHAR(s[x + 1]);
- GotoPos(x, y);
- NewRendition(as[x]);
- NewCharset(fs[x]);
- INSERTCHAR(s[x]);
- }
- else if (delete_lp)
- {
- if (DC)
- PutStr(DC);
- else if (CDC)
- CPutStr(CDC, 1);
- else if (CE)
- PutStr(CE);
- }
- }
-
- void
- RefreshLine(y, from, to)
- int y, from, to;
- {
- char *oi = null;
-
- if (CE && to == screenwidth-1)
- {
- GotoPos(from, y);
- PutStr(CE);
- oi = blank;
- }
- if (in_ovl)
- (*ovl_RedisplayLine)(y, from, to, (oi == blank));
- else
- DisplayLine(oi, null, null, curr->image[y], curr->attr[y],
- curr->font[y], y, from, to);
- }
-
- static void RedisplayLine(os, oa, of, y, from, to)
- int from, to, y;
- char *os, *oa, *of;
- {
- DisplayLine(os, oa, of, curr->image[y], curr->attr[y],
- curr->font[y], y, from, to);
- NewRendition(curr->LocalAttr);
- NewCharset(curr->charsets[curr->LocalCharset]);
- }
-
- void
- FixLP(x2, y2)
- register int x2, y2;
- {
- register struct win *p = curr;
-
- GotoPos(x2, y2);
- SaveSetAttr(p->attr[y2][x2], p->font[y2][x2]);
- PUTCHAR(p->image[y2][x2]);
- RestoreAttr();
- lp_missing = 0;
- }
-
- void
- CheckLP(n_ch)
- char n_ch;
- {
- register int y = screenbot, x = cols - 1;
- register char n_at, n_fo, o_ch, o_at, o_fo;
-
- o_ch = curr->image[y][x];
- o_at = curr->attr[y][x];
- o_fo = curr->font[y][x];
-
- n_at = curr->LocalAttr;
- n_fo = curr->charsets[curr->LocalCharset];
-
- lp_missing = 0;
- if (n_ch == o_ch && n_at == o_at && n_fo == o_fo)
- {
- return;
- }
- if (n_ch != ' ' || n_at || n_fo)
- lp_missing = 1;
- if (o_ch != ' ' || o_at || o_fo)
- {
- if (DC)
- PutStr(DC);
- else if (CDC)
- CPutStr(CDC, 1);
- else if (CE)
- PutStr(CE);
- else
- lp_missing = 1;
- }
- }
-
- static void FindAKA()
- {
- register char *cp, *line, ch;
- register struct win *wp = curr;
- register int len = strlen(wp->cmd);
- int y;
-
- y = (wp->autoaka > 0 && wp->autoaka <= wp->height) ? wp->autoaka - 1 : wp->y;
- cols = wp->width;
- try_line:
- cp = line = wp->image[y];
- if (wp->autoaka > 0 && (ch = *wp->cmd) != '\0')
- {
- for (;;)
- {
- if ((cp = index(cp, ch)) != NULL
- && !strncmp(cp, wp->cmd, len))
- break;
- if (!cp || ++cp - line >= cols - len)
- {
- if (++y == wp->autoaka && y < rows)
- goto try_line;
- return;
- }
- }
- cp += len;
- }
- for (len = cols - (cp - line); len && *cp == ' '; len--, cp++)
- ;
- if (len)
- {
- if (wp->autoaka > 0 && (*cp == '!' || *cp == '%' || *cp == '^'))
- wp->autoaka = -1;
- else
- wp->autoaka = 0;
- line = wp->cmd + wp->akapos;
- while (len && *cp != ' ')
- {
- if ((*line++ = *cp++) == '/')
- line = wp->cmd + wp->akapos;
- len--;
- }
- *line = '\0';
- }
- else
- wp->autoaka = 0;
- }
-
-
- /* We dont use HS status line with Input.
- * If we would use it, then we should check e_tgetflag("es") if
- * we are allowed to use esc sequences there.
- * For now, we hope that Goto(,,STATLINE,0) brings us in the bottom
- * line. jw.
- */
-
- static char inpbuf[101];
- static int inplen;
- static int inpmaxlen;
- static char *inpstring;
- static int inpstringlen;
- static void (*inpfinfunc)();
-
- void
- Input(istr, len, finfunc)
- char *istr;
- int len;
- void (*finfunc)();
- {
- int maxlen;
-
- inpstring = istr;
- inpstringlen = strlen(istr);
- if (len > 100)
- len = 100;
- maxlen = screenwidth - inpstringlen;
- if (!LP && STATLINE == screenbot)
- maxlen--;
- if (len > maxlen)
- len = maxlen;
- if (len < 2)
- {
- Msg(0, "Width too small");
- return;
- }
- inpmaxlen = len;
- inpfinfunc = finfunc;
- InitOverlayPage(process_inp_input, inpRedisplayLine, (int (*)())0, 1);
- inplen = 0;
- GotoPos(0, STATLINE);
- if (CE)
- PutStr(CE);
- else
- {
- DisplayLine(curr->image[screeny], curr->attr[screeny],
- curr->font[screeny],
- blank, null, null, screeny, 0, cols - 1);
- }
- inpRedisplayLine(STATLINE, 0, inpstringlen - 1, 0);
- GotoPos(inpstringlen, STATLINE);
- }
-
- static void
- process_inp_input(ppbuf, plen)
- char **ppbuf;
- int *plen;
- {
- int len, x;
- char *pbuf;
- char ch;
-
- if (ppbuf == 0)
- {
- AbortInp();
- return;
- }
- x = inpstringlen+inplen;
- len = *plen;
- pbuf = *ppbuf;
- while (len)
- {
- ch = *pbuf++;
- len--;
- if (ch >= ' ' && ch <= '~' && inplen < inpmaxlen)
- {
- inpbuf[inplen++] = ch;
- GotoPos(x, STATLINE);
- SaveSetAttr(A_SO, ASCII);
- PUTCHAR(ch);
- x++;
- }
- else if ((ch == '\b' || ch == 0177) && inplen > 0)
- {
- inplen--;
- x--;
- GotoPos(x, STATLINE);
- SaveSetAttr(0, ASCII);
- PUTCHAR(' ');
- GotoPos(x, STATLINE);
- }
- else if (ch == '\004' || ch == '\003' || ch == '\000' || ch == '\n' || ch == '\r')
- {
- if (ch != '\n' && ch != '\r')
- inplen = 0;
- inpbuf[inplen] = 0;
- AbortInp(); /* redisplays... */
- (*inpfinfunc)(inpbuf, inplen);
- break;
- }
- }
- *ppbuf = pbuf;
- *plen = len;
- }
-
- static void
- AbortInp()
- {
- in_ovl = 0; /* So we can use RefreshLine() */
- RefreshLine(STATLINE, 0, screenwidth-1);
- ExitOverlayPage();
- }
-
- static void
- inpRedisplayLine(y, xs, xe, isblank)
- int y, xs, xe, isblank;
- {
- int q, r, s, l, v;
-
- if (y != STATLINE)
- return;
- inpbuf[inplen] = 0;
- GotoPos(xs,y);
- q = xs;
- v = xe - xs + 1;
- s = 0;
- r = inpstringlen;
- if (v > 0 && q < r)
- {
- SaveSetAttr(A_SO, ASCII);
- l = v;
- if (l > r-q)
- l = r-q;
- printf("%-*.*s", l, l, inpstring + q - s);
- q += l;
- v -= l;
- }
- s = r;
- r += inplen;
- if (v > 0 && q < r)
- {
- SaveSetAttr(A_SO, ASCII);
- l = v;
- if (l > r-q)
- l = r-q;
- printf("%-*.*s", l, l, inpbuf + q - s);
- q += l;
- v -= l;
- }
- s = r;
- r = screenwidth;
- if (!isblank && v > 0 && q < r)
- {
- SaveSetAttr(0, ASCII);
- l = v;
- if (l > r-q)
- l = r-q;
- printf("%-*.*s", l, l, "");
- q += l;
- }
- SetLastPos(q, y);
- }
-
- static void
- AKAfin(buf, len)
- char *buf;
- int len;
- {
- if (len)
- {
- strcpy(curr->cmd + curr->akapos, buf);
- }
- }
-
- void
- InputAKA()
- {
- void Input(), AKAfin();
-
- Input("Set window's a.k.a. to: ", 20, AKAfin);
- }
-
- static void
- Colonfin(buf, len)
- char *buf;
- int len;
- {
- if (len)
- RcLine(buf);
- }
-
- void
- InputColon()
- {
- void Input(), Colonfin();
-
- Input(":", 100, Colonfin);
- }
-
- void
- MakeBlankLine(p, n)
- register char *p;
- register int n;
- {
- while (n--)
- *p++ = ' ';
- }
-
- void
- MakeStatus(msg)
- char *msg;
- {
- register char *s, *t;
- register int max, ti;
-
- SetCurr(fore);
- display = 1;
- if (!(max = HS))
- {
- max = !LP ? cols - 1 : cols;
- }
- if (status)
- {
- if (!BellDisplayed)
- {
- ti = time((time_t *) 0) - TimeDisplayed;
- if (ti < MsgMinWait)
- sleep(MsgMinWait - ti);
- }
- RemoveStatus();
- }
- for (s = t = msg; *s && t - msg < max; ++s)
- if (*s == BELL)
- PutStr(BL);
- else if (*s >= ' ' && *s <= '~')
- *t++ = *s;
- *t = '\0';
- if (t > msg)
- {
- strncpy(LastMsg, msg, maxwidth);
- status = 1;
- status_lastx = screenx;
- status_lasty = screeny;
- StatLen = t - msg;
- if (!HS)
- {
- GotoPos(0, STATLINE);
- SaveSetAttr(A_SO, ASCII);
- InsertMode(0);
- printf("%s", msg);
- screenx = -1;
- }
- else
- {
- debug("HS:");
- SaveSetAttr(0, ASCII);
- InsertMode(0);
- CPutStr(TS, 0);
- printf("%s", msg);
- PutStr(FS);
- }
- (void) fflush(stdout);
- (void) time(&TimeDisplayed);
- }
- }
-
- void
- RemoveStatus()
- {
- if (!status)
- return;
- status = 0;
- BellDisplayed = 0;
- SetCurr(fore);
- display = 1;
- if (!HS)
- {
- GotoPos(0, STATLINE);
- if (in_ovl)
- (*ovl_RedisplayLine)(STATLINE, 0, StatLen - 1, 0);
- else
- RedisplayLine(null, null, null, STATLINE, 0, StatLen - 1);
- GotoPos(status_lastx, status_lasty);
- }
- else
- {
- SaveSetAttr(0, ASCII);
- PutStr(DS);
- }
- }
-
- void
- ClearDisplay()
- {
- PutStr(CL);
- screeny = screenx = 0;
- fflush(stdout);
- }
-
- static void SetCurr(wp)
- struct win *wp;
- {
- curr = wp;
- cols = curr->width;
- rows = curr->height;
- display = curr->active;
- }
-
- void
- InitOverlayPage(pro, red, rewrite, blockfore)
- void (*pro)();
- void (*red)();
- int (*rewrite)();
- int blockfore;
- {
- RemoveStatus();
- SetOvlCurr();
- ChangeScrollRegion(0, screenheight - 1);
- SetFlow(1);
- ovl_process = pro;
- ovl_RedisplayLine = red;
- ovl_Rewrite = rewrite;
- ovl_blockfore = blockfore;
- curr->active = 0;
- in_ovl = 1;
- }
-
- void
- ExitOverlayPage()
- {
- ChangeScrollRegion(curr->top, curr->bot);
- GotoPos(curr->x, curr->y);
- RestoreAttr();
- SetFlow(curr->flow & FLOW_NOW);
- curr->active = 1;
- in_ovl = 0;
- }
-
- void
- SetOvlCurr()
- {
- SetCurr(fore);
- SaveSetAttr(0, ASCII);
- InsertMode(0);
- display = 1;
- }
-
- void
- SetLastPos(x,y)
- int x,y;
- {
- screenx = x;
- screeny = y;
- }
-
- void
- WSresize(width, height)
- int width, height;
- {
- debug2("(display=%d:WSresize says:'%s'\n", display, tgoto(WS, width, height));
- PutStr(tgoto(WS, width, height));
- }
-
- void
- ChangeScrollRegion(top, bot)
- int top, bot;
- {
- if (display == 0)
- return;
- if (CS == 0)
- {
- screentop = 0;
- screenbot = screenheight - 1;
- return;
- }
- if (top == screentop && bot == screenbot)
- return;
- debug2("ChangeScrollRegion: (%d - %d)\n", top, bot);
- PutStr(tgoto(CS, bot, top));
- screentop = top;
- screenbot = bot;
- screeny = screenx = -1; /* Just in case... */
- }
-
-
- void AddLineToHist(wp, pi, pa, pf)
- struct win *wp;
- char **pi, **pa, **pf;
- {
- register char *q;
-
- if (wp->histheight == 0)
- return;
- q = *pi; *pi = wp->ihist[wp->histidx]; wp->ihist[wp->histidx] = q;
- q = *pa; *pa = wp->ahist[wp->histidx]; wp->ahist[wp->histidx] = q;
- q = *pf; *pf = wp->fhist[wp->histidx]; wp->fhist[wp->histidx] = q;
- if (++wp->histidx >= wp->histheight)
- wp->histidx = 0;
- }
-
-
- /*
- *
- * Termcap routines that use our extra_incap
- *
- */
-
- /* findcap:
- * cap = capability we are looking for
- * tepp = pointer to bufferpointer
- * n = size of buffer (0 = infinity)
- */
-
- char *
- findcap(cap, tepp, n)
- char *cap;
- char **tepp;
- int n;
- {
- char *tep;
- char c, *p, *cp;
- int mode; /* mode: 0=LIT 1=^ 2=\x 3,4,5=\nnn */
- int num = 0, capl;
-
- if (!extra_incap)
- return (0);
- tep = *tepp;
- capl = strlen(cap);
- cp = 0;
- mode = 0;
- for (p = extra_incap; *p; )
- {
- if (strncmp(p, cap, capl) == 0)
- {
- p+=capl;
- c = *p;
- if (c && c != ':' && c != '@')
- p++;
- if (c == 0 || c == '@' || c == '=' || c == ':' || c == '#')
- cp = tep;
- }
- while (c = *p)
- {
- p++;
- if (mode == 0)
- {
- if (c == ':')
- break;
- if (c == '^')
- mode = 1;
- if (c == '\\')
- mode = 2;
- }
- else if (mode == 1)
- {
- c = c & 0x1f;
- mode = 0;
- }
- else if (mode == 2)
- {
- switch(c)
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- mode = 3;
- num = 0;
- break;
- case 'E':
- c = 27;
- break;
- case 'n':
- c = '\n';
- break;
- case 'r':
- c = '\r';
- break;
- case 't':
- c = '\t';
- break;
- case 'b':
- c = '\b';
- break;
- case 'f':
- c = '\f';
- break;
- }
- if (mode == 2)
- mode = 0;
- }
- if (mode > 2)
- {
- num = num * 8 + (c - '0');
- if (mode++ == 5 || (*p < '0' || *p > '9'))
- {
- c = num;
- mode = 0;
- }
- }
- if (mode)
- continue;
-
- if (cp && n != 1)
- {
- *cp++ = c;
- n--;
- }
- }
- if (cp)
- {
- *cp++ = 0;
- *tepp = cp;
- debug2("'%s' found in extra_incap -> %s\n", cap, tep);
- return(tep);
- }
- }
- return(0);
- }
-
- static char *
- e_tgetstr(cap, tepp)
- char *cap;
- char **tepp;
- {
- char *tep;
- if (tep = findcap(cap, tepp, 0))
- return((*tep == '@') ? 0 : tep);
- return (tgetstr(cap, tepp));
- }
-
- static int
- e_tgetflag(cap)
- char *cap;
- {
- char buf[2], *bufp;
- char *tep;
- bufp = buf;
- if (tep = findcap(cap, &bufp, 2))
- return((*tep == '@') ? 0 : 1);
- return (tgetflag(cap));
- }
-
- static int
- e_tgetnum(cap)
- char *cap;
- {
- char buf[20], *bufp;
- char *tep, c;
- int res, base = 10;
-
- bufp = buf;
- if (tep = findcap(cap, &bufp, 20))
- {
- c = *tep;
- if (c == '@')
- return(-1);
- if (c == '0')
- base = 8;
- res = 0;
- while ((c = *tep++) >= '0' && c <= '9')
- res = res * base + (c - '0');
- return(res);
- }
- return (tgetnum(cap));
- }
-