#include <sys/types.h>
#include "config.h"
#include "screen.h"
#include "extern.h"
#undef DEBUGG
extern struct display *display, *displays;
extern int real_uid, real_gid, eff_uid, eff_gid;
extern struct term term[];
extern struct NewWindow nwin_undef, nwin_default, nwin_options;
extern int force_vt;
extern int Z0width, Z1width;
extern int hardstatusemu;
#ifdef MAPKEYS
extern struct action umtab[];
extern struct action mmtab[];
extern struct action dmtab[];
extern struct kmap_ext *kmap_exts;
extern int kmap_extn;
extern int DefaultEsc;
#endif
static void AddCap __P((char *));
static void MakeString __P((char *, char *, int, char *));
static char *findcap __P((char *, char **, int));
static int copyarg __P((char **, char *));
static int e_tgetent __P((char *, char *));
static char *e_tgetstr __P((char *, char **));
static int e_tgetflag __P((char *));
static int e_tgetnum __P((char *));
#ifdef MAPKEYS
static int findseq_ge __P((char *, int, unsigned char **));
static void setseqoff __P((unsigned char *, int, int));
static int addmapseq __P((char *, int, int));
static int remmapseq __P((char *, int));
#ifdef DEBUGG
static void dumpmap __P((void));
#endif
#endif
char Termcap[TERMCAP_BUFSIZE + 8];
static int Termcaplen;
static int tcLineLen;
char Term[MAXSTR+5];
char screenterm[20];
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;
int t, xue, xse, xme;
ASSERT(display);
bzero(tbuf, sizeof(tbuf));
debug1("InitTermcap: looking for tgetent('%s')\n", D_termname);
if (*D_termname == 0 || e_tgetent(tbuf, D_termname) != 1)
{
#ifdef TERMINFO
Msg(0, "Cannot find terminfo entry for '%s'.", D_termname);
#else
Msg(0, "Cannot find termcap entry for '%s'.", D_termname);
#endif
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
if ((D_tentry = (char *)malloc(TERMCAP_BUFSIZE + (extra_incap ? strlen(extra_incap) + 1 : 0))) == 0)
{
Msg(0, strnomem);
return -1;
}
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);
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);
}
}
if (D_HC)
{
Msg(0, "You can't run screen on a hardcopy terminal.");
return -1;
}
if (D_OS)
{
Msg(0, "You can't run screen on a terminal that overstrikes.");
return -1;
}
if (!D_CL)
{
Msg(0, "Clear screen capability required.");
return -1;
}
if (!D_CM)
{
Msg(0, "Addressable cursor capability required.");
return -1;
}
if ((s = getenv("COLUMNS")) && (i = atoi(s)) > 0)
D_CO = i;
if ((s = getenv("LINES")) && (i = atoi(s)) > 0)
D_LI = i;
if (wi)
D_CO = wi;
if (he)
D_LI = he;
if (D_CO <= 0)
D_CO = 80;
if (D_LI <= 0)
D_LI = 24;
if (D_CTF)
{
if (!D_CAF && D_ME && (InStr(D_ME, "\033[m") || InStr(D_ME, "\033[0m")))
{
#ifdef TERMINFO
D_CAF = "\033[3%p1%dm";
D_CAB = "\033[4%p1%dm";
#else
D_CAF = "\033[3%dm";
D_CAB = "\033[4%dm";
#endif
}
if (D_OP && InStr(D_OP, "\033[39;49m"))
D_CAX = 1;
if (D_OP && (InStr(D_OP, "\033[m") || InStr(D_OP, "\033[0m")))
D_OP = 0;
if ((D_EA && InStr(D_EA, "\033(B")) || (D_AS && InStr(D_AS, "\033(0")))
D_CG0 = 1;
if (InStr(D_termname, "xterm") || InStr(D_termname, "rxvt"))
D_CXT = 1;
if (D_CXT)
D_BE = 1;
}
if (nwin_options.flowflag == nwin_undef.flowflag)
nwin_default.flowflag = D_CNF ? FLOW_NOW * 0 :
D_NX ? FLOW_NOW * 1 :
FLOW_AUTOFLAG;
D_CLP |= (!D_AM || D_XV || D_XN);
if (!D_BL)
D_BL = "\007";
if (!D_BC)
{
if (D_BS)
D_BC = "\b";
else
D_BC = D_LE;
}
if (!D_CR)
D_CR = "\r";
if (!D_NL)
D_NL = "\n";
if (D_UG > 0)
D_US = D_UE = 0;
if (D_SG > 0)
D_SO = D_SE = 0;
if (D_UG > 0 && D_SG > 0)
D_MH = D_MD = D_MR = D_MB = D_ME = 0;
xue = ATYP_U;
xse = ATYP_S;
xme = ATYP_M;
if (D_SO && D_SE == 0)
{
Msg(0, "Warning: 'so' but no 'se' capability.");
if (D_ME)
xse = xme;
else
D_SO = 0;
}
if (D_US && D_UE == 0)
{
Msg(0, "Warning: 'us' but no 'ue' capability.");
if (D_ME)
xue = xme;
else
D_US = 0;
}
if ((D_MH || D_MD || D_MR || D_MB) && D_ME == 0)
{
Msg(0, "Warning: 'm?' but no 'me' capability.");
D_MH = D_MD = D_MR = D_MB = 0;
}
if (D_UE && D_SE && strcmp(D_SE, D_UE) == 0)
xse = xue;
if (D_SE && D_ME && strcmp(D_ME, D_SE) == 0)
xse = xme;
if (D_UE && D_ME && strcmp(D_ME, D_UE) == 0)
xue = xme;
for (i = 0; i < NATTR; i++)
{
D_attrtab[i] = D_tcs[T_ATTR + i].str;
D_attrtyp[i] = i == ATTR_SO ? xse : (i == ATTR_US ? xue : xme);
}
s = 0;
t = 0;
for (i = 0; i < NATTR; i++)
if ((s = D_attrtab[i]))
{
t = D_attrtyp[i];
break;
}
for (i = 0; i < NATTR; i++)
{
if (D_attrtab[i] == 0)
{
D_attrtab[i] = s;
D_attrtyp[i] = t;
}
else
{
s = D_attrtab[i];
t = D_attrtyp[i];
}
}
if (D_CAF || D_CAB || D_CSF || D_CSB)
D_hascolor = 1;
if (D_UT)
D_BE = 1;
if (!D_DO)
D_DO = D_NL;
if (!D_SF)
D_SF = D_NL;
if (D_IN)
D_IC = D_IM = 0;
if (D_EI == 0)
D_IM = 0;
if (D_IC && D_IM && strcmp(D_IC, D_IM) == 0)
D_IC = 0;
if (D_KE == 0)
D_KS = 0;
if (D_CVN == 0)
D_CVR = 0;
if (D_VE == 0)
D_VI = D_VS = 0;
if (D_CCE == 0)
D_CCS = 0;
#ifdef FONT
if (D_CG0)
{
if (D_CS0 == 0)
#ifdef TERMINFO
D_CS0 = "\033(%p1%c";
#else
D_CS0 = "\033(%.";
#endif
if (D_CE0 == 0)
D_CE0 = "\033(B";
D_AC = 0;
D_EA = 0;
}
else if (D_AC || (D_AS && D_AE))
{
D_CS0 = (D_AS && D_AE) ? D_AS : "";
D_CE0 = (D_AS && D_AE) ? D_AE : "";
D_CC0 = D_AC;
}
else
{
D_CS0 = D_CE0 = "";
D_CC0 = 0;
D_AC = "";
}
for (i = 0; i < 256; i++)
D_c0_tab[i] = i;
if (D_AC)
{
s = "l+m+k+j+u+t+v+w+q-x|n+o~s_p\"r#`+a:f'g#~o.v-^+<,>h#I#0#y<z>";
for (i = strlen(s) & ~1; i >= 0; i -= 2)
D_c0_tab[(int)(unsigned char)s[i]] = s[i + 1];
}
if (D_CC0)
for (i = strlen(D_CC0) & ~1; i >= 0; i -= 2)
D_c0_tab[(int)(unsigned char)D_CC0[i]] = D_CC0[i + 1];
debug1("ISO2022 = %d\n", D_CG0);
#endif
if (D_PF == 0)
D_PO = 0;
debug2("terminal size is %d, %d (says TERMCAP)\n", D_CO, D_LI);
#ifdef FONT
if (D_CXC)
if (CreateTransTable(D_CXC))
return -1;
#endif
if (D_CZ1 == 0)
D_CZ0 = 0;
Z0width = 132;
Z1width = 80;
CheckScreenSize(0);
if (D_TS == 0 || D_FS == 0 || D_DS == 0)
D_HS = 0;
if (D_HS)
{
debug("oy! we have a hardware status line, says termcap\n");
if (D_WS < 0)
D_WS = 0;
}
D_has_hstatus = hardstatusemu & ~HSTATUS_ALWAYS;
if (D_HS && !(hardstatusemu & HSTATUS_ALWAYS))
D_has_hstatus = HSTATUS_HS;
#ifdef ENCODINGS
if (D_CKJ)
{
int enc = FindEncoding(D_CKJ);
if (enc != -1)
D_encoding = enc;
}
#endif
if (!D_tcs[T_NAVIGATE].str && D_tcs[T_NAVIGATE + 1].str)
D_tcs[T_NAVIGATE].str = D_tcs[T_NAVIGATE + 1].str;
if (!D_tcs[T_NAVIGATE + 2].str && D_tcs[T_NAVIGATE + 3].str)
D_tcs[T_NAVIGATE + 2].str = D_tcs[T_NAVIGATE + 3].str;
D_UPcost = CalcCost(D_UP);
D_DOcost = CalcCost(D_DO);
D_NLcost = CalcCost(D_NL);
D_LEcost = CalcCost(D_BC);
D_NDcost = CalcCost(D_ND);
D_CRcost = CalcCost(D_CR);
D_IMcost = CalcCost(D_IM);
D_EIcost = CalcCost(D_EI);
#ifdef AUTO_NUKE
if (D_CAN)
{
debug("termcap has AN, setting autonuke\n");
D_auto_nuke = 1;
}
#endif
if (D_COL > 0)
{
debug1("termcap has OL (%d), setting limit\n", D_COL);
D_obufmax = D_COL;
D_obuflenmax = D_obuflen - D_obufmax;
}
if (D_tcs[T_CAPS].str && D_tcs[T_CAPS + 10].str && !strcmp(D_tcs[T_CAPS].str, D_tcs[T_CAPS + 10].str))
D_tcs[T_CAPS].str = 0;
if (D_tcs[T_NAVIGATE_DELETE].str && !strcmp(D_tcs[T_NAVIGATE_DELETE].str, "\0177"))
D_tcs[T_NAVIGATE_DELETE].str = 0;
if (D_tcs[T_CURSOR + 3].str && !strcmp(D_tcs[T_CURSOR + 3].str, "\008"))
D_tcs[T_CURSOR + 3].str = 0;
#ifdef MAPKEYS
D_nseqs = 0;
for (i = 0; i < T_OCAPS - T_CAPS; i++)
remap(i, 1);
for (i = 0; i < kmap_extn; i++)
remap(i + (KMAP_KEYS+KMAP_AKEYS), 1);
D_seqp = D_kmaps + 3;
D_seql = 0;
D_seqh = 0;
#endif
D_tcinited = 1;
MakeTermcap(0);
#ifdef MAPKEYS
CheckEscape();
#endif
return 0;
}
#ifdef MAPKEYS
int
remap(n, map)
int n;
int map;
{
char *s = 0;
int fl = 0, domap = 0;
struct action *a1, *a2, *tab;
int l = 0;
struct kmap_ext *kme = 0;
a1 = 0;
if (n >= KMAP_KEYS+KMAP_AKEYS)
{
kme = kmap_exts + (n - (KMAP_KEYS+KMAP_AKEYS));
s = kme->str;
l = kme->fl & ~KMAP_NOTIMEOUT;
fl = kme->fl & KMAP_NOTIMEOUT;
a1 = &kme->um;
}
tab = umtab;
for (;;)
{
a2 = 0;
if (n < KMAP_KEYS+KMAP_AKEYS)
{
a1 = &tab[n];
if (n >= KMAP_KEYS)
n -= T_OCAPS-T_CURSOR;
s = D_tcs[n + T_CAPS].str;
l = s ? strlen(s) : 0;
if (n >= T_CURSOR-T_CAPS)
a2 = &tab[n + (T_OCAPS-T_CURSOR)];
}
if (s == 0 || l == 0)
return 0;
if (a1 && a1->nr == RC_ILLEGAL)
a1 = 0;
if (a2 && a2->nr == RC_ILLEGAL)
a2 = 0;
if (a1 && a1->nr == RC_STUFF && strcmp(a1->args[0], s) == 0)
a1 = 0;
if (a2 && a2->nr == RC_STUFF && strcmp(a2->args[0], s) == 0)
a2 = 0;
domap |= (a1 || a2);
if (tab == umtab)
{
tab = dmtab;
a1 = kme ? &kme->dm : 0;
}
else if (tab == dmtab)
{
tab = mmtab;
a1 = kme ? &kme->mm : 0;
}
else
break;
}
if (map == 0 && domap)
return 0;
if (map && !domap)
return 0;
debug3("%smapping %s %#x\n", map? "" :"un",s,n);
if (map)
return addmapseq(s, l, n | fl);
else
return remmapseq(s, l);
}
void
CheckEscape()
{
struct display *odisplay;
int i, nr;
if (DefaultEsc >= 0)
return;
odisplay = display;
for (display = displays; display; display = display->d_next)
{
for (i = 0; i < D_nseqs; i += D_kmaps[i + 2] * 2 + 4)
{
nr = (D_kmaps[i] << 8 | D_kmaps[i + 1]) & ~KMAP_NOTIMEOUT;
if (nr < KMAP_KEYS+KMAP_AKEYS)
{
if (umtab[nr].nr == RC_COMMAND)
break;
if (umtab[nr].nr == RC_ILLEGAL && dmtab[nr].nr == RC_COMMAND)
break;
}
else
{
struct kmap_ext *kme = kmap_exts + nr - (KMAP_KEYS+KMAP_AKEYS);
if (kme->um.nr == RC_COMMAND)
break;
if (kme->um.nr == RC_ILLEGAL && kme->dm.nr == RC_COMMAND)
break;
}
}
}
if (display == 0)
{
display = odisplay;
return;
}
SetEscape((struct acluser *)0, Ctrl('a'), 'a');
if (odisplay->d_user->u_Esc == -1)
odisplay->d_user->u_Esc = DefaultEsc;
if (odisplay->d_user->u_MetaEsc == -1)
odisplay->d_user->u_MetaEsc = DefaultMetaEsc;
display = 0;
Msg(0, "Warning: escape char set back to ^A");
display = odisplay;
}
static int
findseq_ge(seq, k, sp)
char *seq;
int k;
unsigned char **sp;
{
unsigned char *p;
int j, l;
p = D_kmaps;
while (p - D_kmaps < D_nseqs)
{
l = p[2];
p += 3;
for (j = 0; ; j++)
{
if (j == k || j == l)
j = l - k;
else if (p[j] != ((unsigned char *)seq)[j])
j = p[j] - ((unsigned char *)seq)[j];
else
continue;
break;
}
if (j >= 0)
{
*sp = p - 3;
return j;
}
p += 2 * l + 1;
}
*sp = p;
return -1;
}
static void
setseqoff(p, i, o)
unsigned char *p;
int i;
int o;
{
unsigned char *q;
int l, k;
k = p[2];
if (o < 256)
{
p[k + 4 + i] = o;
return;
}
for (q = p + k * 2 + 4; ; q += l * 2 + 4)
{
l = q[2];
if ((q + l * 2 - p) / 2 >= 256)
{
p[k + 4 + i] = (q - p - 4) / 2;
return;
}
}
}
static int
addmapseq(seq, k, nr)
char *seq;
int k;
int nr;
{
int i, j, l, mo, m;
unsigned char *p, *q;
if (k >= 254)
return -1;
j = findseq_ge(seq, k, &p);
if (j == 0)
{
p[0] = nr >> 8;
p[1] = nr;
return 0;
}
i = p - D_kmaps;
if (D_nseqs + 2 * k + 4 >= D_aseqs)
{
D_kmaps = (unsigned char *)xrealloc((char *)D_kmaps, D_aseqs + 256);
D_aseqs += 256;
p = D_kmaps + i;
}
D_seqp = D_kmaps + 3;
D_seql = 0;
D_seqh = 0;
evdeq(&D_mapev);
if (j > 0)
bcopy((char *)p, (char *)p + 2 * k + 4, D_nseqs - i);
p[0] = nr >> 8;
p[1] = nr;
p[2] = k;
bcopy(seq, (char *)p + 3, k);
bzero(p + k + 3, k + 1);
D_nseqs += 2 * k + 4;
if (j > 0)
{
q = p + 2 * k + 4;
l = q[2];
for (i = 0; i < k; i++)
{
if (p[3 + i] != q[3 + i])
{
p[k + 4 + i] = k;
break;
}
setseqoff(p, i, q[l + 4 + i] ? q[l + 4 + i] + k + 2: 0);
}
}
for (q = D_kmaps; q < p; q += 2 * l + 4)
{
l = q[2];
for (m = j = 0; j < l; j++)
{
mo = m;
if (!m && q[3 + j] != seq[j])
m = 1;
if (q[l + 4 + j] == 0)
{
if (!mo && m)
setseqoff(q, j, (p - q - 4) / 2);
}
else if (q + q[l + 4 + j] * 2 + 4 > p || (q + q[l + 4 + j] * 2 + 4 == p && !m))
setseqoff(q, j, q[l + 4 + j] + k + 2);
}
}
#ifdef DEBUGG
dumpmap();
#endif
return 0;
}
static int
remmapseq(seq, k)
char *seq;
int k;
{
int j, l;
unsigned char *p, *q;
if (k >= 254 || (j = findseq_ge(seq, k, &p)) != 0)
return -1;
for (q = D_kmaps; q < p; q += 2 * l + 4)
{
l = q[2];
for (j = 0; j < l; j++)
{
if (q + q[l + 4 + j] * 2 + 4 == p)
setseqoff(q, j, p[k + 4 + j] ? q[l + 4 + j] + p[k + 4 + j] - k : 0);
else if (q + q[l + 4 + j] * 2 + 4 > p)
q[l + 4 + j] -= k + 2;
}
}
if (D_kmaps + D_nseqs > p + 2 * k + 4)
bcopy((char *)p + 2 * k + 4, (char *)p, (D_kmaps + D_nseqs) - (p + 2 * k + 4));
D_nseqs -= 2 * k + 4;
D_seqp = D_kmaps + 3;
D_seql = 0;
D_seqh = 0;
evdeq(&D_mapev);
#ifdef DEBUGG
dumpmap();
#endif
return 0;
}
#ifdef DEBUGG
static void
dumpmap()
{
unsigned char *p;
int j, n, l, o, oo;
debug("Mappings:\n");
p = D_kmaps;
if (!p)
return;
while (p < D_kmaps + D_nseqs)
{
l = p[2];
debug1("%d: ", p - D_kmaps + 3);
for (j = 0; j < l; j++)
{
o = oo = p[l + 4 + j];
if (o)
o = 2 * o + 4 + (p + 3 + j - D_kmaps);
if (p[j + 3] > ' ' && p[j + 3] < 0177)
{
debug3("%c[%d:%d] ", p[j + 3], oo, o);
}
else
debug3("\\%03o[%d:%d] ", p[j + 3], oo, o);
}
n = p[0] << 8 | p[1];
debug2(" ==> %d%s\n", n & ~KMAP_NOTIMEOUT, (n & KMAP_NOTIMEOUT) ? " (no timeout)" : "");
p += 2 * l + 4;
}
}
#endif
#endif
static void
AddCap(s)
char *s;
{
register int n;
if (tcLineLen + (n = strlen(s)) > 55 && Termcaplen < TERMCAP_BUFSIZE - 4 - 1)
{
strcpy(Termcap + Termcaplen, "\\\n\t:");
Termcaplen += 4;
tcLineLen = 0;
}
if (Termcaplen + n < TERMCAP_BUFSIZE - 1)
{
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 0
int found;
#endif
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);
strcpy(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' || strlen(screenterm) > MAXSTR - 3)
{
debug("MakeTermcap sets screenterm=screen\n");
strcpy(screenterm, "screen");
}
#if 0
found = 1;
#endif
do
{
strcpy(Term, "TERM=");
p = Term + 5;
if (!aflag && strlen(screenterm) + strlen(tname) < MAXSTR-1)
{
sprintf(p, "%s.%s", screenterm, tname);
if (e_tgetent(buf, p) == 1)
break;
}
#ifdef COLOR
if (nwin_default.bce)
{
sprintf(p, "%s-bce", screenterm);
if (e_tgetent(buf, p) == 1)
break;
}
#endif
#ifdef CHECK_SCREEN_W
if (wi >= 132)
{
sprintf(p, "%s-w", screenterm);
if (e_tgetent(buf, p) == 1)
break;
}
#endif
strcpy(p, screenterm);
if (e_tgetent(buf, p) == 1)
break;
strcpy(p, "vt100");
#if 0
found = 0;
#endif
}
while (0);
#if 0
#ifndef TERMINFO
if (found)
{
char xbuf[TERMCAP_BUFSIZE], *xbp = xbuf;
if (tgetstr("im", &xbp) && tgetstr("ic", &xbp) && displays)
{
Msg(0, "Warning: im and ic set in %s termcap entry", p);
}
}
#endif
#endif
tcLineLen = 100;
if (strlen(Term) > TERMCAP_BUFSIZE - 40)
strcpy(Term, "too_long");
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;
}
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 && !D_COP) || D_CLP || !D_AM)
{
AddCap("xn:");
AddCap("xv:");
AddCap("LP:");
}
if (aflag || (D_CS && D_SR) || D_AL || D_CAL)
{
AddCap("sr=\\EM:");
AddCap("al=\\E[L:");
AddCap("AL=\\E[%dL:");
}
else if (D_SR)
AddCap("sr=\\EM:");
if (aflag || D_CS)
AddCap("cs=\\E[%i%d;%dr:");
if (aflag || D_CS || D_DL || D_CDL)
{
AddCap("dl=\\E[M:");
AddCap("DL=\\E[%dM:");
}
if (aflag || D_DC || D_CDC)
{
AddCap("dc=\\E[P:");
AddCap("DC=\\E[%dP:");
}
if (aflag || D_CIC || D_IC || D_IM)
{
AddCap("im=\\E[4h:");
AddCap("ei=\\E[4l:");
AddCap("mi:");
AddCap("IC=\\E[%d@:");
}
#ifdef MAPKEYS
AddCap("ks=\\E[?1h\\E=:");
AddCap("ke=\\E[?1l\\E>:");
#endif
AddCap("vi=\\E[?25l:");
AddCap("ve=\\E[34h\\E[?25h:");
AddCap("vs=\\E[34l:");
AddCap("ti=\\E[?1049h:");
AddCap("te=\\E[?1049l:");
if (display)
{
if (D_US)
{
AddCap("us=\\E[4m:");
AddCap("ue=\\E[24m:");
}
if (D_SO)
{
AddCap("so=\\E[3m:");
AddCap("se=\\E[23m:");
}
if (D_MB)
AddCap("mb=\\E[5m:");
if (D_MD)
AddCap("md=\\E[1m:");
if (D_MH)
AddCap("mh=\\E[2m:");
if (D_MR)
AddCap("mr=\\E[7m:");
if (D_MB || D_MD || D_MH || D_MR)
AddCap("me=\\E[m:ms:");
if (D_hascolor)
AddCap("Co#8:pa#64:AF=\\E[3%dm:AB=\\E[4%dm:op=\\E[39;49m:AX:");
if (D_VB)
AddCap("vb=\\Eg:");
#ifndef MAPKEYS
if (D_KS)
{
AddCap("ks=\\E=:");
AddCap("ke=\\E>:");
}
if (D_CCS)
{
AddCap("CS=\\E[?1h:");
AddCap("CE=\\E[?1l:");
}
#endif
if (D_CG0)
AddCap("G0:");
if (D_CC0 || (D_CS0 && *D_CS0))
{
AddCap("as=\\E(0:");
AddCap("ae=\\E(B:");
AddCap("ac=\\140\\140aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~..--++,,hhII00:");
}
if (D_PO)
{
AddCap("po=\\E[5i:");
AddCap("pf=\\E[4i:");
}
if (D_CZ0)
{
AddCap("Z0=\\E[?3h:");
AddCap("Z1=\\E[?3l:");
}
if (D_CWS)
AddCap("WS=\\E[8;%d;%dt:");
}
for (i = T_CAPS; i < T_ECAPS; i++)
{
#ifdef MAPKEYS
struct action *act;
if (i < T_OCAPS)
{
if (i >= T_KEYPAD)
continue;
if (i >= T_CURSOR && i < T_OCAPS)
{
act = &umtab[i - (T_CURSOR - T_OCAPS + T_CAPS)];
if (act->nr == RC_ILLEGAL)
act = &dmtab[i - (T_CURSOR - T_OCAPS + T_CAPS)];
}
else
{
act = &umtab[i - T_CAPS];
if (act->nr == RC_ILLEGAL)
act = &dmtab[i - T_CAPS];
}
if (act->nr == RC_ILLEGAL && (i == T_NAVIGATE + 1 || i == T_NAVIGATE + 3))
{
act = &umtab[i - T_CAPS - 1];
if (act->nr == RC_ILLEGAL)
act = &dmtab[i - T_CAPS - 1];
}
if (act->nr != RC_ILLEGAL)
{
if (act->nr == RC_STUFF)
{
MakeString(term[i].tcname, buf, sizeof(buf), act->args[0]);
AddCap(buf);
}
continue;
}
}
#endif
if (display == 0)
continue;
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 ':':
strcpy(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';
}
#undef QUOTES
#define QUOTES(p) \
(*p == '\\' && (p[1] == '\\' || p[1] == ',' || p[1] == '%'))
#ifdef FONT
int
CreateTransTable(s)
char *s;
{
int curchar;
char *templ, *arg;
int templlen;
int templnsub;
char *p, *sx;
char **ctable;
int l, c;
if ((D_xtable = (char ***)malloc(256 * sizeof(char **))) == 0)
{
Msg(0, strnomem);
return -1;
}
bzero((char *)D_xtable, 256 * sizeof(char **));
while (*s)
{
if (QUOTES(s))
s++;
curchar = (unsigned char)*s++;
if (curchar == 'B')
curchar = 0;
templ = s;
templlen = 0;
templnsub = 0;
if (D_xtable[curchar] == 0)
{
if ((D_xtable[curchar] = (char **)malloc(257 * sizeof(char *))) == 0)
{
Msg(0, strnomem);
FreeTransTable();
return -1;
}
bzero((char *)D_xtable[curchar], 257 * sizeof(char *));
}
ctable = D_xtable[curchar];
for(; *s && *s != ','; s++)
{
if (QUOTES(s))
s++;
else if (*s == '%')
{
templnsub++;
continue;
}
templlen++;
}
if (*s++ == 0)
break;
while (*s && *s != ',')
{
c = (unsigned char)*s++;
if (QUOTES((s - 1)))
c = (unsigned char)*s++;
else if (c == '%')
c = 256;
if (ctable[c])
free(ctable[c]);
arg = s;
l = copyarg(&s, (char *)0);
if (c != 256)
l = l * templnsub + templlen;
if ((ctable[c] = (char *)malloc(l + 1)) == 0)
{
Msg(0, strnomem);
FreeTransTable();
return -1;
}
sx = ctable[c];
for (p = ((c == 256) ? "%" : templ); *p && *p != ','; p++)
{
if (QUOTES(p))
p++;
else if (*p == '%')
{
s = arg;
sx += copyarg(&s, sx);
continue;
}
*sx++ = *p;
}
*sx = 0;
ASSERT(ctable[c] + l * templnsub + templlen == sx);
debug3("XC: %c %c->%s\n", curchar, c, ctable[c]);
}
if (*s == ',')
s++;
}
return 0;
}
void
FreeTransTable()
{
char ***p, **q;
int i, j;
if ((p = D_xtable) == 0)
return;
for (i = 0; i < 256; i++, p++)
{
if (*p == 0)
continue;
q = *p;
for (j = 0; j < 257; j++, q++)
if (*q)
free(*q);
free(*p);
}
free(D_xtable);
}
#endif
static int
copyarg(pp, s)
char **pp, *s;
{
int l;
char *p;
for (l = 0, p = *pp; *p && *p != ','; p++)
{
if (QUOTES(p))
p++;
if (s)
*s++ = *p;
l++;
}
if (*p == ',')
p++;
*pp = p;
return l;
}
static int
e_tgetent(bp, name)
char *bp, *name;
{
int r;
#ifdef USE_SETEUID
xseteuid(real_uid);
xsetegid(real_gid);
#endif
r = tgetent(bp, name);
#ifdef USE_SETEUID
xseteuid(eff_uid);
xsetegid(eff_gid);
#endif
return r;
}
static char *
findcap(cap, tepp, n)
char *cap;
char **tepp;
int n;
{
char *tep;
char c, *p, *cp;
int mode;
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;
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) > 0;
}
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);
}