home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1993
- * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
- * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
- * Copyright (c) 1987 Oliver Laumann
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program (see the file COPYING); if not, write to the
- * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ****************************************************************
- */
-
- #include "rcs.h"
- RCS_ID("$Id: termcap.c,v 1.3 1993/07/21 15:43:35 mlschroe Exp $ FAU")
-
- #include <sys/types.h>
- #include "config.h"
- #include "screen.h"
- #include "extern.h"
-
- extern struct display *display;
-
- static void AddCap __P((char *));
- static void MakeString __P((char *, char *, int, char *));
- static char *findcap __P((char *, char **, int));
- static char *e_tgetstr __P((char *, char **));
- static int e_tgetflag __P((char *));
- static int e_tgetnum __P((char *));
-
- extern struct term term[]; /* terminal capabilities */
- extern struct NewWindow nwin_undef, nwin_default, nwin_options;
- extern int force_vt, assume_LP;
- extern int Z0width, Z1width;
-
- char Termcap[TERMCAP_BUFSIZE + 8]; /* new termcap +8:"TERMCAP=" */
- static int Termcaplen;
- static int tcLineLen;
- char Term[MAXSTR+5]; /* +5: "TERM=" */
- char screenterm[20]; /* new $TERM, usually "screen" */
-
- char *extra_incap, *extra_outcap;
-
- static const 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:";
-
- char *
- gettermcapstring(s)
- char *s;
- {
- int i;
-
- if (display == 0 || s == 0)
- return 0;
- for (i = 0; i < T_N; i++)
- {
- if (term[i].type != T_STR)
- continue;
- if (strcmp(term[i].tcname, s) == 0)
- return d_tcs[i].str;
- }
- return 0;
- }
-
- int
- InitTermcap(wi, he)
- int wi;
- int he;
- {
- register char *s;
- int i;
- char tbuf[TERMCAP_BUFSIZE], *tp;
-
- ASSERT(display);
- bzero(tbuf, sizeof(tbuf));
- debug1("InitTermcap: looking for tgetent('%s')\n", d_termname);
- if (tgetent(tbuf, d_termname) != 1)
- {
- Msg(0, "Cannot find termcap entry for %s.", d_termname);
- return -1;
- }
- 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
- tp = d_tentry;
-
- for (i = 0; i < T_N; i++)
- {
- switch(term[i].type)
- {
- case T_FLG:
- d_tcs[i].flg = e_tgetflag(term[i].tcname);
- break;
- case T_NUM:
- d_tcs[i].num = e_tgetnum(term[i].tcname);
- break;
- case T_STR:
- d_tcs[i].str = e_tgetstr(term[i].tcname, &tp);
- /* no empty strings, please */
- if (d_tcs[i].str && *d_tcs[i].str == 0)
- d_tcs[i].str = 0;
- break;
- default:
- Panic(0, "Illegal tc type in entry #%d", i);
- /*NOTREACHED*/
- }
- }
- if (HC)
- {
- Msg(0, "You can't run screen on a hardcopy terminal.");
- return -1;
- }
- if (OS)
- {
- Msg(0, "You can't run screen on a terminal that overstrikes.");
- return -1;
- }
- if (NS)
- {
- Msg(0, "Terminal must support scrolling.");
- return -1;
- }
- if (!CL)
- {
- Msg(0, "Clear screen capability required.");
- return -1;
- }
- if (!CM)
- {
- Msg(0, "Addressable cursor capability required.");
- return -1;
- }
- if ((s = getenv("COLUMNS")) && (i = atoi(s)) > 0)
- CO = i;
- if ((s = getenv("LINES")) && (i = atoi(s)) > 0)
- LI = i;
- if (wi)
- CO = wi;
- if (he)
- LI = he;
- if (CO <= 0)
- CO = 80;
- if (LI <= 0)
- LI = 24;
-
- if (nwin_options.flowflag == nwin_undef.flowflag)
- nwin_default.flowflag = CNF ? FLOW_NOW * 0 :
- XO ? FLOW_NOW * 1 :
- FLOW_AUTOFLAG;
- CLP |= assume_LP || !AM || XV || XN ||
- (!extra_incap && !strncmp(d_termname, "vt", 2));
- if (!(BL = e_tgetstr("bl", &tp)))
- if (!BL)
- BL = "\007";
- if (!BC)
- {
- if (BS)
- BC = "\b";
- else
- BC = LE;
- }
- if (!CR)
- CR = "\r";
- if (!NL)
- NL = "\n";
- if (SG <= 0 && UG <= 0)
- {
- /*
- * 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;
-
- for (i = 0; i < NATTR; i++)
- d_attrtab[i] = d_tcs[T_ATTR + i].str;
- /* Set up missing entries */
- s = 0;
- for (i = NATTR-1; i >= 0; i--)
- if (d_attrtab[i])
- s = d_attrtab[i];
- for (i = 0; i < NATTR; i++)
- {
- if (d_attrtab[i] == 0)
- d_attrtab[i] = s;
- else
- s = d_attrtab[i];
- }
- }
- else
- {
- MS = 1;
- for (i = 0; i < NATTR; i++)
- d_attrtab[i] = d_tcs[T_ATTR + i].str = 0;
- }
- if (!DO)
- DO = NL;
- if (!SF)
- SF = NL;
- if (IN)
- IC = IM = 0;
- if (EI == 0)
- IM = 0;
- /* some strange termcap entries have IC == IM */
- if (IC && IM && strcmp(IC, IM) == 0)
- IC = 0;
- if (KE == 0)
- KS = 0;
- if (CCE == 0)
- CCS = 0;
- if (CG0)
- {
- if (CS0 == 0)
- #ifdef TERMINFO
- CS0 = "\033(%p1%c";
- #else
- CS0 = "\033(%.";
- #endif
- if (CE0 == 0)
- CE0 = "\033(B";
- }
- else if (AS && AE)
- {
- CG0 = 1;
- CS0 = AS;
- CE0 = AE;
- CC0 = AC;
- }
- else
- {
- CS0 = CE0 = "";
- CC0 = "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++)
- d_c0_tab[i] = i;
- if (CC0)
- for (i = strlen(CC0) & ~1; i >= 0; i -= 2)
- d_c0_tab[(unsigned int)CC0[i]] = CC0[i + 1];
- debug1("ISO2022 = %d\n", CG0);
- if (PF == 0)
- PO = 0;
- debug2("terminal size is %d, %d (says TERMCAP)\n", CO, LI);
-
- /* Termcap fields Z0 & Z1 contain width-changing sequences. */
- if (CZ1 == 0)
- CZ0 = 0;
- Z0width = 132;
- Z1width = 80;
-
- CheckScreenSize(0);
-
- if (TS == 0 || FS == 0 || DS == 0)
- HS = 0;
- if (HS)
- {
- debug("oy! we have a hardware status line, says termcap\n");
- if (WS <= 0)
- WS = d_width;
- }
-
- d_UPcost = CalcCost(UP);
- d_DOcost = CalcCost(DO);
- d_NLcost = CalcCost(NL);
- d_LEcost = CalcCost(BC);
- d_NDcost = CalcCost(ND);
- d_CRcost = CalcCost(CR);
- d_IMcost = CalcCost(IM);
- d_EIcost = CalcCost(EI);
-
- #ifdef AUTO_NUKE
- if (CAN)
- {
- debug("termcap has AN, setting autonuke\n");
- d_auto_nuke = 1;
- }
- #endif
- if (COL > 0)
- {
- debug1("termcap has OL (%d), setting limit\n", COL);
- d_obufmax = COL;
- }
-
- d_tcinited = 1;
- MakeTermcap(0);
- return 0;
- }
-
-
- static void
- AddCap(s)
- char *s;
- {
- register int n;
-
- if (tcLineLen + (n = strlen(s)) > 55 && Termcaplen < TERMCAP_BUFSIZE - 4)
- {
- strcpy(Termcap + Termcaplen, "\\\n\t:");
- Termcaplen += 4;
- tcLineLen = 0;
- }
- if (Termcaplen + n < TERMCAP_BUFSIZE)
- {
- strcpy(Termcap + Termcaplen, s);
- Termcaplen += n;
- tcLineLen += n;
- }
- else
- Panic(0, "TERMCAP overflow - sorry.");
- }
-
- char *
- MakeTermcap(aflag)
- int aflag;
- {
- char buf[TERMCAP_BUFSIZE];
- register char *p, *cp, *s, ch, *tname;
- int i, wi, he;
-
- if (display)
- {
- wi = d_width;
- he = d_height;
- tname = d_termname;
- }
- else
- {
- wi = 80;
- he = 24;
- tname = "vt100";
- }
- debug1("MakeTermcap(%d)\n", aflag);
- if ((s = getenv("SCREENCAP")) && strlen(s) < TERMCAP_BUFSIZE)
- {
- sprintf(Termcap, "TERMCAP=%s", s); /* TERMCAP_BUFSIZE + ... ? XXX */
- sprintf(Term, "TERM=screen");
- debug("getenvSCREENCAP o.k.\n");
- return Termcap;
- }
- Termcaplen = 0;
- debug1("MakeTermcap screenterm='%s'\n", screenterm);
- debug1("MakeTermcap termname='%s'\n", tname);
- if (*screenterm == '\0')
- {
- debug("MakeTermcap sets screenterm=screen\n");
- strcpy(screenterm, "screen");
- }
- do
- {
- sprintf(Term, "TERM=");
- p = Term + 5;
- if (!aflag && strlen(screenterm) + strlen(tname) < MAXSTR-1)
- {
- sprintf(p, "%s.%s", screenterm, tname);
- if (tgetent(buf, p) == 1)
- break;
- }
- if (wi >= 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");
- }
- while (0); /* Goto free programming... */
- tcLineLen = 100; /* Force NL */
- sprintf(Termcap,
- "TERMCAP=SC|%s|VT 100/ANSI X3.64 virtual terminal|", Term + 5);
- Termcaplen = strlen(Termcap);
- debug1("MakeTermcap decided '%s'\n", p);
- 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 */
- }
- debug1("MakeTermcap after outcap '%s'\n", (char *)TermcapConst);
- if (Termcaplen + strlen(TermcapConst) < TERMCAP_BUFSIZE)
- {
- strcpy(Termcap + Termcaplen, (char *)TermcapConst);
- Termcaplen += strlen(TermcapConst);
- }
- sprintf(buf, "li#%d:co#%d:", he, wi);
- AddCap(buf);
- AddCap("am:");
- if (aflag || (force_vt && !COP) || CLP || !AM)
- {
- AddCap("xn:");
- AddCap("xv:");
- AddCap("LP:");
- }
- if (aflag || (CS && SR) || AL || CAL)
- {
- AddCap("sr=\\EM:");
- AddCap("al=\\E[L:");
- AddCap("AL=\\E[%dL:");
- }
- else if (SR)
- AddCap("sr=\\EM:");
- if (aflag || CS)
- AddCap("cs=\\E[%i%d;%dr:");
- if (aflag || CS || DL || CDL)
- {
- AddCap("dl=\\E[M:");
- AddCap("DL=\\E[%dM:");
- }
- if (aflag || DC || CDC)
- {
- AddCap("dc=\\E[P:");
- AddCap("DC=\\E[%dP:");
- }
- if (aflag || CIC || IC || IM)
- {
- AddCap("im=\\E[4h:");
- AddCap("ei=\\E[4l:");
- AddCap("mi:");
- AddCap("IC=\\E[%d@:");
- }
- if (display)
- {
- 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 (VB)
- AddCap("vb=\\E[?5h\\E[?5l:");
- if (KS)
- {
- AddCap("ks=\\E=:");
- AddCap("ke=\\E>:");
- }
- if (CCS)
- {
- AddCap("CS=\\E[?1h:");
- AddCap("CE=\\E[?1l:");
- }
- if (CG0)
- {
- AddCap("G0:");
- AddCap("as=\\E(0:");
- AddCap("ae=\\E(B:");
- }
- if (PO)
- {
- AddCap("po=\\E[5i:");
- AddCap("pf=\\E[4i:");
- }
- if (CZ0)
- {
- AddCap("Z0=\\E[?3h:");
- AddCap("Z1=\\E[?3l:");
- }
- if (CWS)
- AddCap("WS=\\E[8;%d;%dt:");
- for (i = T_CAPS; i < T_ECAPS; i++)
- {
- switch(term[i].type)
- {
- case T_STR:
- if (d_tcs[i].str == 0)
- break;
- MakeString(term[i].tcname, buf, sizeof(buf), d_tcs[i].str);
- AddCap(buf);
- break;
- case T_FLG:
- if (d_tcs[i].flg == 0)
- break;
- sprintf(buf, "%s:", term[i].tcname);
- AddCap(buf);
- break;
- default:
- break;
- }
- }
- }
- debug("MakeTermcap: end\n");
- 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';
- }
-
-
- /*
- **
- ** Termcap routines that use our extra_incap
- **
- */
-
-
- /* findcap:
- * cap = capability we are looking for
- * tepp = pointer to bufferpointer
- * n = size of buffer (0 = infinity)
- */
-
- static 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)
- {
- mode = 0;
- c = c & 0x1f;
- }
- else if (mode == 2)
- {
- mode = 0;
- 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)
- {
- 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, *tgetstr();
- 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));
- }
-