1 /* Copyright (c) 2008, 2009
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Micah Cowan (micah@cowan.name)
5 * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
7 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9 * Copyright (c) 1987 Oliver Laumann
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3, or (at your option)
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program (see the file COPYING); if not, see
23 * https://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
33 #include <sys/types.h>
44 static void AddCap(char *);
45 static void MakeString(char *, char *, int, char *);
46 static char *findcap(char *, char **, int);
47 static int copyarg(char **, char *);
48 static int e_tgetent(char *, char *);
49 static char *e_tgetstr(char *, char **);
50 static int e_tgetflag(char *);
51 static int e_tgetnum(char *);
52 static int findseq_ge(char *, int, unsigned char **);
53 static void setseqoff(unsigned char *, int, int);
54 static int addmapseq(char *, int, int);
55 static int remmapseq(char *, int);
57 char Termcap
[TERMCAP_BUFSIZE
+ 8]; /* new termcap +8:"TERMCAP=" */
58 static int Termcaplen
;
60 char Term
[MAXSTR
+ 5]; /* +5: "TERM=" */
61 char screenterm
[MAXTERMLEN
+ 1]; /* new $TERM, usually "screen" */
63 char *extra_incap
, *extra_outcap
;
65 static const char TermcapConst
[] = "DO=\\E[%dB:LE=\\E[%dD:RI=\\E[%dC:\
66 UP=\\E[%dA:bs:bt=\\E[Z:cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:cm=\\E[%i%d;%dH:\
67 ct=\\E[3g:do=^J:nd=\\E[C:pt:rc=\\E8:rs=\\Ec:sc=\\E7:st=\\EH:up=\\EM:\
68 le=^H:bl=^G:cr=^M:it#8:ho=\\E[H:nw=\\EE:ta=^I:is=\\E)0:";
70 char *gettermcapstring(char *s
)
74 if (display
== NULL
|| s
== NULL
)
76 for (i
= 0; i
< T_N
; i
++) {
77 if (term
[i
].type
!= T_STR
)
79 if (strcmp(term
[i
].tcname
, s
) == 0)
86 * Compile the terminal capabilities for a display.
87 * Input: tgetent(, D_termname) extra_incap, extra_outcap.
88 * Effect: display initialisation.
90 int InitTermcap(int width
, int height
)
94 char tbuf
[TERMCAP_BUFSIZE
], *tp
;
97 memset(tbuf
, 0, ARRAY_SIZE(tbuf
));
98 if (*D_termname
== 0 || e_tgetent(tbuf
, D_termname
) != 1) {
99 Msg(0, "Cannot find terminfo entry for '%s'.", D_termname
);
103 if ((D_tentry
= malloc(TERMCAP_BUFSIZE
+ (extra_incap
? strlen(extra_incap
) + 1 : 0))) == NULL
) {
104 Msg(0, "%s", strnomem
);
109 * loop through all needed capabilities, record their values in the display
112 for (i
= 0; i
< T_N
; i
++) {
113 switch (term
[i
].type
) {
115 D_tcs
[i
].flg
= e_tgetflag(term
[i
].tcname
);
118 D_tcs
[i
].num
= e_tgetnum(term
[i
].tcname
);
121 D_tcs
[i
].str
= e_tgetstr(term
[i
].tcname
, &tp
);
122 /* no empty strings, please */
123 if (D_tcs
[i
].str
&& *D_tcs
[i
].str
== 0)
127 Panic(0, "Illegal tc type in entry #%d", i
);
132 * Now a good deal of sanity checks on the retrieved capabilities.
135 Msg(0, "You can't run screen on a hardcopy terminal.");
139 Msg(0, "You can't run screen on a terminal that overstrikes.");
143 Msg(0, "Clear screen capability required.");
147 Msg(0, "Addressable cursor capability required.");
150 if ((s
= getenv("COLUMNS")) && (i
= atoi(s
)) > 0)
152 if ((s
= getenv("LINES")) && (i
= atoi(s
)) > 0)
164 /* standard fixes for xterms etc */
165 /* assume color for everything that looks ansi-compatible */
166 if (!D_CAF
&& D_ME
&& (strstr(D_ME
, "\033[m") || strstr(D_ME
, "\033[0m"))) {
167 D_CAF
= "\033[3%p1%dm";
168 D_CAB
= "\033[4%p1%dm";
170 if (D_OP
&& strstr(D_OP
, "\033[39;49m"))
172 if (D_OP
&& (strstr(D_OP
, "\033[m") || strstr(D_OP
, "\033[0m")))
175 if ((D_EA
&& strstr(D_EA
, "\033(B")) || (D_AS
&& strstr(D_AS
, "\033(0")))
177 if (strstr(D_termname
, "xterm") || strstr(D_termname
, "rxvt") || (D_CKM
&&
178 (strstr(D_CKM
, "\033[M") || strstr(D_CKM
, "\033[<")))) {
180 kmapdef
[0] = D_CKM
? SaveStr(D_CKM
) : NULL
;
182 /* "be" seems to be standard for xterms... */
186 if (nwin_options
.flowflag
== nwin_undef
.flowflag
)
187 nwin_default
.flowflag
= D_CNF
? FLOW_OFF
: D_NX
? FLOW_ON
: FLOW_AUTOFLAG
;
188 D_CLP
|= (!D_AM
|| D_XV
|| D_XN
);
203 * Set up attribute handling.
204 * This is rather complicated because termcap has different
212 /* Unfortunately there is no 'mg' capability.
213 * For now we think that mg > 0 if sg and ug > 0.
215 if (D_UG
> 0 && D_SG
> 0)
216 D_MH
= D_MD
= D_MR
= D_MB
= D_ME
= NULL
;
222 if (D_SO
&& D_SE
== NULL
) {
223 Msg(0, "Warning: 'so' but no 'se' capability.");
229 if (D_US
&& D_UE
== NULL
) {
230 Msg(0, "Warning: 'us' but no 'ue' capability.");
236 if ((D_MH
|| D_MD
|| D_MR
|| D_MB
) && D_ME
== NULL
) {
237 Msg(0, "Warning: 'm?' but no 'me' capability.");
238 D_MH
= D_MD
= D_MR
= D_MB
= NULL
;
241 * Does ME also reverse the effect of SO and/or US? This is not
242 * clearly specified by the termcap manual. Anyway, we should at
243 * least look whether ME and SE/UE are equal:
245 if (D_UE
&& D_SE
&& strcmp(D_SE
, D_UE
) == 0)
247 if (D_SE
&& D_ME
&& strcmp(D_ME
, D_SE
) == 0)
249 if (D_UE
&& D_ME
&& strcmp(D_ME
, D_UE
) == 0)
252 for (i
= 0; i
< NATTR
; i
++) {
253 D_attrtab
[i
] = D_tcs
[T_ATTR
+ i
].str
;
254 D_attrtyp
[i
] = i
== ATTR_SO
? xse
: (i
== ATTR_US
? xue
: xme
);
257 /* Set up missing entries (attributes are priority ordered) */
260 for (i
= 0; i
< NATTR
; i
++)
261 if ((s
= D_attrtab
[i
])) {
265 for (i
= 0; i
< NATTR
; i
++) {
266 if (D_attrtab
[i
] == NULL
) {
274 if (D_CAF
|| D_CAB
|| D_CSF
|| D_CSB
)
277 D_BE
= 1; /* screen erased with background color */
287 /* some strange termcap entries have IC == IM */
288 if (D_IC
&& D_IM
&& strcmp(D_IC
, D_IM
) == 0)
301 D_CS0
= "\033(%p1%c";
306 } else if (D_AC
|| (D_AS
&& D_AE
)) { /* some kind of graphics */
307 D_CS0
= (D_AS
&& D_AE
) ? D_AS
: "";
308 D_CE0
= (D_AS
&& D_AE
) ? D_AE
: "";
313 D_AC
= ""; /* enable default string */
316 for (i
= 0; i
< 256; i
++)
319 /* init with default string first */
320 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>";
321 for (i
= (strlen(s
) - 2) & ~1; i
>= 0; i
-= 2)
322 D_c0_tab
[(int)(unsigned char)s
[i
]] = s
[i
+ 1];
325 for (i
= (strlen(D_CC0
) - 2) & ~1; i
>= 0; i
-= 2)
326 D_c0_tab
[(int)(unsigned char)D_CC0
[i
]] = D_CC0
[i
+ 1];
331 if (CreateTransTable(D_CXC
))
334 /* Termcap fields Z0 & Z1 contain width-changing sequences. */
340 if (D_TS
== NULL
|| D_FS
== NULL
|| D_DS
== NULL
)
346 D_has_hstatus
= hardstatusemu
& ~HSTATUS_ALWAYS
;
347 if (D_HS
&& !(hardstatusemu
& HSTATUS_ALWAYS
))
348 D_has_hstatus
= HSTATUS_HS
;
351 int enc
= FindEncoding(D_CKJ
);
355 if (!D_tcs
[T_NAVIGATE
].str
&& D_tcs
[T_NAVIGATE
+ 1].str
)
356 D_tcs
[T_NAVIGATE
].str
= D_tcs
[T_NAVIGATE
+ 1].str
; /* kh = @1 */
357 if (!D_tcs
[T_NAVIGATE
+ 2].str
&& D_tcs
[T_NAVIGATE
+ 3].str
)
358 D_tcs
[T_NAVIGATE
+ 2].str
= D_tcs
[T_NAVIGATE
+ 3].str
; /* kH = @7 */
360 D_UPcost
= CalcCost(D_UP
);
361 D_DOcost
= CalcCost(D_DO
);
362 D_NLcost
= CalcCost(D_NL
);
363 D_LEcost
= CalcCost(D_BC
);
364 D_NDcost
= CalcCost(D_ND
);
365 D_CRcost
= CalcCost(D_CR
);
366 D_IMcost
= CalcCost(D_IM
);
367 D_EIcost
= CalcCost(D_EI
);
374 D_obuflenmax
= D_obuflen
- D_obufmax
;
377 /* Some xterm entries set F0 and F10 to the same string. Nuke F0. */
378 if (D_tcs
[T_CAPS
].str
&& D_tcs
[T_CAPS
+ 10].str
&& !strcmp(D_tcs
[T_CAPS
].str
, D_tcs
[T_CAPS
+ 10].str
))
379 D_tcs
[T_CAPS
].str
= NULL
;
380 /* Some xterm entries set kD to ^?. Nuke it. */
381 if (D_tcs
[T_NAVIGATE_DELETE
].str
&& !strcmp(D_tcs
[T_NAVIGATE_DELETE
].str
, "\0177"))
382 D_tcs
[T_NAVIGATE_DELETE
].str
= NULL
;
383 /* wyse52 entries have kcub1 == kb == ^H. Nuke... */
384 if (D_tcs
[T_CURSOR
+ 3].str
&& !strcmp(D_tcs
[T_CURSOR
+ 3].str
, "\008"))
385 D_tcs
[T_CURSOR
+ 3].str
= NULL
;
388 for (i
= 0; i
< T_OCAPS
- T_CAPS
; i
++)
390 for (i
= 0; i
< kmap_extn
; i
++)
391 remap(i
+ (KMAP_KEYS
+ KMAP_AKEYS
), 1);
392 D_seqp
= D_kmaps
+ 3;
398 /* Make sure libterm uses external term properties for our tputs() calls. */
399 e_tgetent(tbuf
, D_termname
);
404 int remap(int n
, int map
)
407 int fl
= 0, domap
= 0;
408 struct action
*a1
, *a2
, *tab
;
410 struct kmap_ext
*kme
= NULL
;
413 if (n
>= KMAP_KEYS
+ KMAP_AKEYS
) {
414 kme
= kmap_exts
+ (n
- (KMAP_KEYS
+ KMAP_AKEYS
));
416 l
= kme
->fl
& ~KMAP_NOTIMEOUT
;
417 fl
= kme
->fl
& KMAP_NOTIMEOUT
;
423 if (n
< KMAP_KEYS
+ KMAP_AKEYS
) {
426 n
-= T_OCAPS
- T_CURSOR
;
427 s
= D_tcs
[n
+ T_CAPS
].str
;
428 l
= s
? strlen(s
) : 0;
429 if (n
>= T_CURSOR
- T_CAPS
)
430 a2
= &tab
[n
+ (T_OCAPS
- T_CURSOR
)];
432 if (s
== NULL
|| l
== 0)
434 if (a1
&& a1
->nr
== RC_ILLEGAL
)
436 if (a2
&& a2
->nr
== RC_ILLEGAL
)
438 if (a1
&& a1
->nr
== RC_STUFF
&& a1
->args
[0] && strcmp(a1
->args
[0], s
) == 0)
440 if (a2
&& a2
->nr
== RC_STUFF
&& a2
->args
[0] && strcmp(a2
->args
[0], s
) == 0)
445 a1
= kme
? &kme
->dm
: NULL
;
446 } else if (tab
== dmtab
) {
448 a1
= kme
? &kme
->mm
: NULL
;
454 if (map
== 0 && domap
)
459 return addmapseq(s
, l
, n
| fl
);
461 return remmapseq(s
, l
);
464 void CheckEscape(void)
473 for (display
= displays
; display
; display
= display
->d_next
) {
474 for (i
= 0; i
< D_nseqs
; i
+= D_kmaps
[i
+ 2] * 2 + 4) {
475 nr
= (D_kmaps
[i
] << 8 | D_kmaps
[i
+ 1]) & ~KMAP_NOTIMEOUT
;
476 if (nr
< KMAP_KEYS
+ KMAP_AKEYS
) {
477 if (umtab
[nr
].nr
== RC_COMMAND
)
479 if (umtab
[nr
].nr
== RC_ILLEGAL
&& dmtab
[nr
].nr
== RC_COMMAND
)
482 struct kmap_ext
*kme
= kmap_exts
+ nr
- (KMAP_KEYS
+ KMAP_AKEYS
);
483 if (kme
->um
.nr
== RC_COMMAND
)
485 if (kme
->um
.nr
== RC_ILLEGAL
&& kme
->dm
.nr
== RC_COMMAND
)
490 if (display
== NULL
) {
494 SetEscape(NULL
, Ctrl('a'), 'a');
495 if (odisplay
->d_user
->u_Esc
== -1)
496 odisplay
->d_user
->u_Esc
= DefaultEsc
;
497 if (odisplay
->d_user
->u_MetaEsc
== -1)
498 odisplay
->d_user
->u_MetaEsc
= DefaultMetaEsc
;
500 Msg(0, "Warning: escape char set back to ^A");
504 static int findseq_ge(char *seq
, int k
, unsigned char **sp
)
510 while (p
- D_kmaps
< D_nseqs
) {
514 if (j
== k
|| j
== l
)
516 else if (p
[j
] != ((unsigned char *)seq
)[j
])
517 j
= p
[j
] - ((unsigned char *)seq
)[j
];
532 static void setseqoff(unsigned char *p
, int i
, int o
)
542 /* go for the biggest offset */
543 for (q
= p
+ k
* 2 + 4;; q
+= l
* 2 + 4) {
545 if ((q
+ l
* 2 - p
) / 2 >= 256) {
546 p
[k
+ 4 + i
] = (q
- p
- 4) / 2;
552 static int addmapseq(char *seq
, int k
, int nr
)
555 unsigned char *p
, *q
;
559 j
= findseq_ge(seq
, k
, &p
);
566 if (D_nseqs
+ 2 * k
+ 4 >= D_aseqs
) {
567 D_kmaps
= xrealloc((char *)D_kmaps
, D_aseqs
+ 256);
571 D_seqp
= D_kmaps
+ 3;
576 memmove((char *)p
+ 2 * k
+ 4, (char *)p
, D_nseqs
- i
);
580 memmove((char *)p
+ 3, seq
, k
);
581 memset(p
+ k
+ 3, 0, k
+ 1);
582 D_nseqs
+= 2 * k
+ 4;
586 for (i
= 0; i
< k
; i
++) {
587 if (p
[3 + i
] != q
[3 + i
]) {
591 setseqoff(p
, i
, q
[l
+ 4 + i
] ? q
[l
+ 4 + i
] + k
+ 2 : 0);
594 for (q
= D_kmaps
; q
< p
; q
+= 2 * l
+ 4) {
596 for (m
= j
= 0; j
< l
; j
++) {
598 if (!m
&& q
[3 + j
] != seq
[j
])
600 if (q
[l
+ 4 + j
] == 0) {
602 setseqoff(q
, j
, (p
- q
- 4) / 2);
603 } else if (q
+ q
[l
+ 4 + j
] * 2 + 4 > p
|| (q
+ q
[l
+ 4 + j
] * 2 + 4 == p
&& !m
))
604 setseqoff(q
, j
, q
[l
+ 4 + j
] + k
+ 2);
610 static int remmapseq(char *seq
, int k
)
613 unsigned char *p
, *q
;
615 if (k
>= 254 || (j
= findseq_ge(seq
, k
, &p
)) != 0)
617 for (q
= D_kmaps
; q
< p
; q
+= 2 * l
+ 4) {
619 for (j
= 0; j
< l
; j
++) {
620 if (q
+ q
[l
+ 4 + j
] * 2 + 4 == p
)
621 setseqoff(q
, j
, p
[k
+ 4 + j
] ? q
[l
+ 4 + j
] + p
[k
+ 4 + j
] - k
: 0);
622 else if (q
+ q
[l
+ 4 + j
] * 2 + 4 > p
)
623 q
[l
+ 4 + j
] -= k
+ 2;
626 if (D_kmaps
+ D_nseqs
> p
+ 2 * k
+ 4)
627 memmove((char *)p
, (char *)p
+ 2 * k
+ 4, (D_kmaps
+ D_nseqs
) - (p
+ 2 * k
+ 4));
628 D_nseqs
-= 2 * k
+ 4;
629 D_seqp
= D_kmaps
+ 3;
637 * Appends to the static variable Termcap
639 static void AddCap(char *s
)
644 if (Termcaplen
+ n
< TERMCAP_BUFSIZE
- 1) {
645 strcpy(Termcap
+ Termcaplen
, s
);
652 * Reads a displays capabilities and reconstructs a termcap entry in the
653 * global buffer "Termcap". A pointer to this buffer is returned.
655 char *MakeTermcap(bool aflag
)
657 char buf
[TERMCAP_BUFSIZE
];
658 char *p
, *cp
, *s
, ch
, *tname
;
659 int i
, width
, height
;
670 if ((s
= getenv("SCREENCAP")) && strlen(s
) < TERMCAP_BUFSIZE
) {
671 sprintf(Termcap
, "TERMCAP=%s", s
);
672 strcpy(Term
, "TERM=screen");
676 if (*screenterm
== '\0' || strlen(screenterm
) > MAXSTR
- 3) {
677 strncpy(screenterm
, "screen", MAXTERMLEN
);
678 screenterm
[MAXTERMLEN
] = '\0';
681 strcpy(Term
, "TERM=");
683 if (!aflag
&& strlen(screenterm
) + strlen(tname
) < MAXSTR
- 1) {
684 sprintf(p
, "%s.%s", screenterm
, tname
);
685 if (e_tgetent(buf
, p
) == 1)
688 if (nwin_default
.bce
) {
689 sprintf(p
, "%s-bce", screenterm
);
690 if (e_tgetent(buf
, p
) == 1)
693 strcpy(p
, screenterm
);
694 if (e_tgetent(buf
, p
) == 1)
698 while (0); /* Goto free programming... */
700 tcLineLen
= 100; /* Force NL */
701 if (strlen(Term
) > TERMCAP_BUFSIZE
- 40)
702 strcpy(Term
, "too_long");
703 sprintf(Termcap
, "TERMCAP=SC|%s|VT 100/ANSI X3.64 virtual terminal:", Term
+ 5);
704 Termcaplen
= strlen(Termcap
);
705 if (extra_outcap
&& *extra_outcap
) {
706 for (cp
= extra_outcap
; (p
= strchr(cp
, ':')); cp
= p
) {
712 tcLineLen
= 100; /* Force NL */
714 if (Termcaplen
+ strlen(TermcapConst
) < TERMCAP_BUFSIZE
) {
715 strcpy(Termcap
+ Termcaplen
, TermcapConst
);
716 Termcaplen
+= strlen(TermcapConst
);
718 sprintf(buf
, "li#%d:co#%d:", height
, width
);
721 if (aflag
|| (force_vt
&& !D_COP
) || D_CLP
|| !D_AM
) {
726 if (aflag
|| (D_CS
&& D_SR
) || D_AL
|| D_CAL
) {
729 AddCap("AL=\\E[%dL:");
733 AddCap("cs=\\E[%i%d;%dr:");
734 if (aflag
|| D_CS
|| D_DL
|| D_CDL
) {
736 AddCap("DL=\\E[%dM:");
738 if (aflag
|| D_DC
|| D_CDC
) {
740 AddCap("DC=\\E[%dP:");
742 if (aflag
|| D_CIC
|| D_IC
|| D_IM
) {
743 AddCap("im=\\E[4h:");
744 AddCap("ei=\\E[4l:");
746 AddCap("IC=\\E[%d@:");
748 AddCap("ks=\\E[?1h\\E=:");
749 AddCap("ke=\\E[?1l\\E>:");
750 AddCap("vi=\\E[?25l:");
751 AddCap("ve=\\E[34h\\E[?25h:");
752 AddCap("vs=\\E[34l:");
753 AddCap("ti=\\E[?1049h:");
754 AddCap("te=\\E[?1049l:");
757 AddCap("us=\\E[4m:");
758 AddCap("ue=\\E[24m:");
761 AddCap("so=\\E[3m:");
762 AddCap("se=\\E[23m:");
765 AddCap("so=\\E[7m:");
766 AddCap("se=\\E[27m:");
769 AddCap("mb=\\E[5m:");
771 AddCap("md=\\E[1m:");
773 AddCap("mh=\\E[2m:");
775 AddCap("mr=\\E[7m:");
776 if (D_MB
|| D_MD
|| D_MH
|| D_MR
)
777 AddCap("me=\\E[m:ms:");
779 AddCap("Co#8:pa#64:AF=\\E[3%dm:AB=\\E[4%dm:op=\\E[39;49m:AX:");
784 if (D_CC0
|| (D_CS0
&& *D_CS0
)) {
787 /* avoid `` because some shells dump core... */
788 AddCap("ac=\\140\\140aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~..--++,,hhII00:");
791 AddCap("po=\\E[5i:");
792 AddCap("pf=\\E[4i:");
795 AddCap("Z0=\\E[?3h:");
796 AddCap("Z1=\\E[?3l:");
799 AddCap("WS=\\E[8;%d;%dt:");
801 for (i
= T_CAPS
; i
< T_ECAPS
; i
++) {
804 if (i
>= T_KEYPAD
) /* don't put keypad codes in TERMCAP */
805 continue; /* - makes it too big */
806 #if (TERMCAP_BUFSIZE < 1024)
807 if (i
>= T_FEXTRA
&& i
< T_BACKTAB
) /* also skip extra vt220 keys */
809 if (i
> T_BACKTAB
&& i
< T_NAVIGATE
) /* more vt220 keys */
812 if (i
>= T_CURSOR
&& i
< T_OCAPS
) {
813 act
= &umtab
[i
- (T_CURSOR
- T_OCAPS
+ T_CAPS
)];
814 if (act
->nr
== RC_ILLEGAL
)
815 act
= &dmtab
[i
- (T_CURSOR
- T_OCAPS
+ T_CAPS
)];
817 act
= &umtab
[i
- T_CAPS
];
818 if (act
->nr
== RC_ILLEGAL
)
819 act
= &dmtab
[i
- T_CAPS
];
821 if (act
->nr
== RC_ILLEGAL
&& (i
== T_NAVIGATE
+ 1 || i
== T_NAVIGATE
+ 3)) {
822 /* kh -> @1, kH -> @7 */
823 act
= &umtab
[i
- T_CAPS
- 1];
824 if (act
->nr
== RC_ILLEGAL
)
825 act
= &dmtab
[i
- T_CAPS
- 1];
827 if (act
->nr
!= RC_ILLEGAL
) {
828 if (act
->nr
== RC_STUFF
) {
829 MakeString(term
[i
].tcname
, buf
, ARRAY_SIZE(buf
), act
->args
[0]);
837 switch (term
[i
].type
) {
839 if (D_tcs
[i
].str
== NULL
)
841 MakeString(term
[i
].tcname
, buf
, ARRAY_SIZE(buf
), D_tcs
[i
].str
);
845 if (D_tcs
[i
].flg
== 0)
847 sprintf(buf
, "%s:", term
[i
].tcname
);
857 #define TERMCAP_MAX_WIDTH 63
858 void DumpTermcap(int aflag
, FILE *f
)
863 if ((p
= index(MakeTermcap(aflag
), '=')) == NULL
)
866 /* write termcap entry with wrapping */
867 while ((pe
= index(p
, ':')))
870 if ((col
> 8) && ((col
+ n
) > TERMCAP_MAX_WIDTH
))
872 fwrite("\\\n\t:", 1, 4, f
);
880 fwrite(p
, 1, strlen(p
), f
);
884 static void MakeString(char *cap
, char *buf
, int buflen
, char *s
)
890 pmax
= p
+ buflen
- (3 + 4 + 2);
894 while ((c
= *s
++) && (p
< pmax
)) {
911 sprintf(p
, "\\%03o", c
& 0377);
913 } else if (c
< ' ') {
926 (*p == '\\' && (p[1] == '\\' || p[1] == ',' || p[1] == '%'))
928 int CreateTransTable(char *s
)
938 if ((D_xtable
= calloc(256, sizeof(char **))) == NULL
) {
939 Msg(0, "%s", strnomem
);
946 curchar
= (unsigned char)*s
++;
948 curchar
= 0; /* ASCII */
952 if (D_xtable
[curchar
] == NULL
) {
953 if ((D_xtable
[curchar
] = calloc(257, sizeof(char *))) == NULL
) {
954 Msg(0, "%s", strnomem
);
959 ctable
= D_xtable
[curchar
];
960 for (; *s
&& *s
!= ','; s
++) {
963 else if (*s
== '%') {
971 while (*s
&& *s
!= ',') {
972 c
= (unsigned char)*s
++;
974 c
= (unsigned char)*s
++;
980 l
= copyarg(&s
, NULL
);
982 l
= l
* templnsub
+ templlen
;
983 if ((ctable
[c
] = malloc(l
+ 1)) == NULL
) {
984 Msg(0, "%s", strnomem
);
989 for (p
= ((c
== 256) ? "%" : templ
); *p
&& *p
!= ','; p
++) {
992 else if (*p
== '%') {
994 sx
+= copyarg(&s
, sx
);
1007 void FreeTransTable(void)
1012 if ((p
= D_xtable
) == NULL
)
1014 for (i
= 0; i
< 256; i
++, p
++) {
1018 for (j
= 0; j
< 257; j
++, q
++)
1027 static int copyarg(char **pp
, char *s
)
1032 for (l
= 0, p
= *pp
; *p
&& *p
!= ','; p
++) {
1047 ** Termcap routines that use our extra_incap
1051 static int e_tgetent(char *bp
, char *name
)
1057 r
= tgetent(bp
, name
);
1064 * cap = capability we are looking for
1065 * tepp = pointer to bufferpointer
1066 * n = size of buffer (0 = infinity)
1069 static char *findcap(char *cap
, char **tepp
, int n
)
1073 int mode
; /* mode: 0=LIT 1=^ 2=\x 3,4,5=\nnn */
1082 for (p
= extra_incap
; *p
;) {
1083 if (strncmp(p
, cap
, capl
) == 0) {
1086 if (c
&& c
!= ':' && c
!= '@')
1088 if (c
== 0 || c
== '@' || c
== '=' || c
== ':' || c
== '#')
1100 } else if (mode
== 1) {
1103 } else if (mode
== 2) {
1140 num
= num
* 8 + (c
- '0');
1141 if (mode
++ == 5 || (*p
< '0' || *p
> '9')) {
1163 static char *e_tgetstr(char *cap
, char **tepp
)
1166 if ((tep
= findcap(cap
, tepp
, 0)))
1167 return (*tep
== '@') ? NULL
: tep
;
1168 return tgetstr(cap
, tepp
);
1171 static int e_tgetflag(char *cap
)
1176 if ((tep
= findcap(cap
, &bufp
, 2)))
1177 return (*tep
== '@') ? 0 : 1;
1178 return tgetflag(cap
) > 0;
1181 static int e_tgetnum(char *cap
)
1183 char buf
[20], *bufp
;
1188 if ((tep
= findcap(cap
, &bufp
, 20))) {
1195 while ((c
= *tep
++) >= '0' && c
<= '9')
1196 res
= res
* base
+ (c
- '0');
1199 return tgetnum(cap
);