sltermin.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  1. /* This file contains enough terminfo reading capabilities sufficient for
  2. * the slang SLtt interface.
  3. */
  4. /* Copyright (c) 1992, 1995 John E. Davis
  5. * All rights reserved.
  6. *
  7. * You may distribute under the terms of either the GNU General Public
  8. * License or the Perl Artistic License.
  9. */
  10. #include "config.h"
  11. #include <stdio.h>
  12. #ifdef HAVE_STDLIB_H
  13. # include <stdlib.h>
  14. #endif
  15. #ifndef USE_SETUPTERM
  16. #include "slang.h"
  17. #include "_slang.h"
  18. /*
  19. * The majority of the comments found in the file were taken from the
  20. * term(4) man page on an SGI.
  21. */
  22. /* Short integers are stored in two 8-bit bytes. The first byte contains
  23. * the least significant 8 bits of the value, and the second byte contains
  24. * the most significant 8 bits. (Thus, the value represented is
  25. * 256*second+first.) The value -1 is represented by 0377,0377, and the
  26. * value -2 is represented by 0376,0377; other negative values are illegal.
  27. * The -1 generally means that a capability is missing from this terminal.
  28. * The -2 means that the capability has been cancelled in the terminfo
  29. * source and also is to be considered missing.
  30. */
  31. static int make_integer (unsigned char *buf)
  32. {
  33. register int lo, hi;
  34. lo = (int) *buf++; hi = (int) *buf;
  35. if (hi == 0377)
  36. {
  37. if (lo == 0377) return -1;
  38. if (lo == 0376) return -2;
  39. }
  40. return lo + 256 * hi;
  41. }
  42. /*
  43. * The compiled file is created from the source file descriptions of the
  44. * terminals (see the -I option of infocmp) by using the terminfo compiler,
  45. * tic, and read by the routine setupterm [see curses(3X).] The file is
  46. * divided into six parts in the following order: the header, terminal
  47. * names, boolean flags, numbers, strings, and string table.
  48. *
  49. * The header section begins the file. This section contains six short
  50. * integers in the format described below. These integers are (1) the magic
  51. * number (octal 0432); (2) the size, in bytes, of the names section; (3)
  52. * the number of bytes in the boolean section; (4) the number of short
  53. * integers in the numbers section; (5) the number of offsets (short
  54. * integers) in the strings section; (6) the size, in bytes, of the string
  55. * table.
  56. */
  57. #define MAGIC 0432
  58. /* In this structure, all char * fields are malloced EXCEPT if the
  59. * structure is SLTERMCAP. In that case, only terminal_names is malloced
  60. * and the other fields are pointers into it.
  61. */
  62. typedef struct
  63. {
  64. #define SLTERMINFO 1
  65. #define SLTERMCAP 2
  66. unsigned int flags;
  67. unsigned int name_section_size;
  68. char *terminal_names;
  69. unsigned int boolean_section_size;
  70. unsigned char *boolean_flags;
  71. unsigned int num_numbers;
  72. unsigned char *numbers;
  73. unsigned int num_string_offsets;
  74. unsigned char *string_offsets;
  75. unsigned int string_table_size;
  76. char *string_table;
  77. } Terminfo_Type;
  78. static char *tcap_getstr (char *, Terminfo_Type *);
  79. static int tcap_getnum (char *, Terminfo_Type *);
  80. static int tcap_getflag (char *, Terminfo_Type *);
  81. static int tcap_getent (char *, Terminfo_Type *);
  82. static FILE *open_terminfo (char *file, Terminfo_Type *h)
  83. {
  84. FILE *fp;
  85. unsigned char buf[12];
  86. fp = fopen (file, "rb");
  87. if (fp == NULL) return NULL;
  88. if ((12 == fread ((char *) buf, 1, 12, fp) && (MAGIC == make_integer (buf))))
  89. {
  90. h->name_section_size = make_integer (buf + 2);
  91. h->boolean_section_size = make_integer (buf + 4);
  92. h->num_numbers = make_integer (buf + 6);
  93. h->num_string_offsets = make_integer (buf + 8);
  94. h->string_table_size = make_integer (buf + 10);
  95. }
  96. else
  97. {
  98. fclose (fp);
  99. fp = NULL;
  100. }
  101. return fp;
  102. }
  103. /*
  104. * The terminal names section comes next. It contains the first line of the
  105. * terminfo description, listing the various names for the terminal,
  106. * separated by the bar ( | ) character (see term(5)). The section is
  107. * terminated with an ASCII NUL character.
  108. */
  109. /* returns pointer to malloced space */
  110. static unsigned char *read_terminfo_section (FILE *fp, unsigned int size)
  111. {
  112. char *s;
  113. if (NULL == (s = (char *) SLMALLOC (size))) return NULL;
  114. if (size != fread (s, 1, size, fp))
  115. {
  116. SLFREE (s);
  117. return NULL;
  118. }
  119. return (unsigned char *) s;
  120. }
  121. static char *read_terminal_names (FILE *fp, Terminfo_Type *t)
  122. {
  123. return t->terminal_names = (char *) read_terminfo_section (fp, t->name_section_size);
  124. }
  125. /*
  126. * The boolean flags have one byte for each flag. This byte is either 0 or
  127. * 1 as the flag is present or absent. The value of 2 means that the flag
  128. * has been cancelled. The capabilities are in the same order as the file
  129. * <term.h>.
  130. */
  131. static unsigned char *read_boolean_flags (FILE *fp, Terminfo_Type *t)
  132. {
  133. /* Between the boolean section and the number section, a null byte is
  134. * inserted, if necessary, to ensure that the number section begins on an
  135. * even byte offset. All short integers are aligned on a short word
  136. * boundary.
  137. */
  138. unsigned int size = (t->name_section_size + t->boolean_section_size) % 2;
  139. size += t->boolean_section_size;
  140. return t->boolean_flags = read_terminfo_section (fp, size);
  141. }
  142. /*
  143. * The numbers section is similar to the boolean flags section. Each
  144. * capability takes up two bytes, and is stored as a short integer. If the
  145. * value represented is -1 or -2, the capability is taken to be missing.
  146. */
  147. static unsigned char *read_numbers (FILE *fp, Terminfo_Type *t)
  148. {
  149. return t->numbers = read_terminfo_section (fp, 2 * t->num_numbers);
  150. }
  151. /* The strings section is also similar. Each capability is stored as a
  152. * short integer, in the format above. A value of -1 or -2 means the
  153. * capability is missing. Otherwise, the value is taken as an offset from
  154. * the beginning of the string table. Special characters in ^X or \c
  155. * notation are stored in their interpreted form, not the printing
  156. * representation. Padding information ($<nn>) and parameter information
  157. * (%x) are stored intact in uninterpreted form.
  158. */
  159. static unsigned char *read_string_offsets (FILE *fp, Terminfo_Type *t)
  160. {
  161. return t->string_offsets = (unsigned char *) read_terminfo_section (fp, 2 * t->num_string_offsets);
  162. }
  163. /* The final section is the string table. It contains all the values of
  164. * string capabilities referenced in the string section. Each string is
  165. * null terminated.
  166. */
  167. static char *read_string_table (FILE *fp, Terminfo_Type *t)
  168. {
  169. return t->string_table = (char *) read_terminfo_section (fp, t->string_table_size);
  170. }
  171. /*
  172. * Compiled terminfo(4) descriptions are placed under the directory
  173. * /usr/share/lib/terminfo. In order to avoid a linear search of a huge
  174. * UNIX system directory, a two-level scheme is used:
  175. * /usr/share/lib/terminfo/c/name where name is the name of the terminal,
  176. * and c is the first character of name. Thus, att4425 can be found in the
  177. * file /usr/share/lib/terminfo/a/att4425. Synonyms for the same terminal
  178. * are implemented by multiple links to the same compiled file.
  179. */
  180. #define MAX_TI_DIRS 7
  181. static char *Terminfo_Dirs [MAX_TI_DIRS] =
  182. {
  183. NULL,
  184. "/usr/lib/terminfo",
  185. "/usr/share/lib/terminfo",
  186. "/usr/local/lib/terminfo",
  187. "/lib/terminfo",
  188. "/usr/local/share/terminfo",
  189. "/usr/share/terminfo"
  190. };
  191. char *SLtt_tigetent (char *term)
  192. {
  193. char *tidir;
  194. int i;
  195. FILE *fp = NULL;
  196. char file[256];
  197. Terminfo_Type *ti;
  198. if (
  199. (term == NULL)
  200. #ifdef SLANG_UNTIC
  201. && (SLang_Untic_Terminfo_File == NULL)
  202. #endif
  203. )
  204. return NULL;
  205. if (NULL == (ti = (Terminfo_Type *) SLMALLOC (sizeof (Terminfo_Type))))
  206. {
  207. return NULL;
  208. }
  209. #ifdef SLANG_UNTIC
  210. if (SLang_Untic_Terminfo_File != NULL)
  211. {
  212. fp = open_terminfo (SLang_Untic_Terminfo_File, ti);
  213. goto fp_open_label;
  214. }
  215. else
  216. #endif
  217. /* If we are on a termcap based system, use termcap */
  218. if (0 == tcap_getent (term, ti)) return (char *) ti;
  219. Terminfo_Dirs[0] = getenv ("TERMINFO");
  220. i = 0;
  221. while (i < MAX_TI_DIRS)
  222. {
  223. tidir = Terminfo_Dirs[i];
  224. if (tidir != NULL)
  225. {
  226. sprintf (file, "%s/%c/%s", tidir, *term, term);
  227. if (NULL != (fp = open_terminfo (file, ti))) break;
  228. }
  229. i++;
  230. }
  231. #ifdef SLANG_UNTIC
  232. fp_open_label:
  233. #endif
  234. if (fp != NULL)
  235. {
  236. if (NULL != read_terminal_names (fp, ti))
  237. {
  238. if (NULL != read_boolean_flags (fp, ti))
  239. {
  240. if (NULL != read_numbers (fp, ti))
  241. {
  242. if (NULL != read_string_offsets (fp, ti))
  243. {
  244. if (NULL != read_string_table (fp, ti))
  245. {
  246. /* success */
  247. fclose (fp);
  248. ti->flags = SLTERMINFO;
  249. return (char *) ti;
  250. }
  251. SLFREE (ti->string_offsets);
  252. }
  253. SLFREE (ti->numbers);
  254. }
  255. SLFREE (ti->boolean_flags);
  256. }
  257. SLFREE (ti->terminal_names);
  258. }
  259. fclose (fp);
  260. }
  261. SLFREE (ti);
  262. return NULL;
  263. }
  264. #ifdef SLANG_UNTIC
  265. # define UNTIC_COMMENT(x) ,x
  266. #else
  267. # define UNTIC_COMMENT(x)
  268. #endif
  269. typedef struct
  270. {
  271. char name[3];
  272. int offset;
  273. #ifdef SLANG_UNTIC
  274. char *comment;
  275. #endif
  276. }
  277. Tgetstr_Map_Type;
  278. /* I need to add: K1-5, %0-5(not important), @8, &8... */
  279. static Tgetstr_Map_Type Tgetstr_Map [] =
  280. {
  281. {"@7", 164 UNTIC_COMMENT("KEY End")},
  282. {"AB", 360 UNTIC_COMMENT("set a color background")},
  283. {"AF", 359 UNTIC_COMMENT("set a color foreground")},
  284. {"AL", 110 UNTIC_COMMENT("parm_insert_line")},
  285. {"DL", 106 UNTIC_COMMENT("parm_delete_line")},
  286. {"RI", 112 UNTIC_COMMENT("parm_right_cursor")},
  287. {"Sf", 302 UNTIC_COMMENT("set foreground (color)")},
  288. {"Sb", 303 UNTIC_COMMENT("set background (color)")},
  289. {"ac", 146 UNTIC_COMMENT("acs_chars")},
  290. {"ae", 38 UNTIC_COMMENT("exit_alt_charset_mode")},
  291. {"as", 25 UNTIC_COMMENT("enter_alt_charset_mode")},
  292. {"ce", 6 UNTIC_COMMENT("clr_eol")},
  293. {"cl", 5 UNTIC_COMMENT("clear_screen")},
  294. {"cm", 10 UNTIC_COMMENT("cursor_address")},
  295. {"cs", 3 UNTIC_COMMENT("change_scroll_region")},
  296. {"dc", 21 UNTIC_COMMENT("delete_character")},
  297. {"ds", 23 UNTIC_COMMENT("disable status line")},
  298. {"eA", 155 UNTIC_COMMENT("enable alt char set")},
  299. {"ei", 42 UNTIC_COMMENT("exit_insert_mode")},
  300. {"fs", 47 UNTIC_COMMENT("return from status line")},
  301. {"im", 31 UNTIC_COMMENT("enter_insert_mode")},
  302. {"k0", 65 UNTIC_COMMENT("key_f0")},
  303. {"k1", 66 UNTIC_COMMENT("key_f1")},
  304. {"k2", 68 UNTIC_COMMENT("key_f2")},
  305. {"k3", 69 UNTIC_COMMENT("key_f3")},
  306. {"k4", 70 UNTIC_COMMENT("key_f4")},
  307. {"k5", 71 UNTIC_COMMENT("key_f5")},
  308. {"k6", 72 UNTIC_COMMENT("key_f6")},
  309. {"k7", 73 UNTIC_COMMENT("key_f7")},
  310. {"k8", 74 UNTIC_COMMENT("key_f8")},
  311. {"k9", 75 UNTIC_COMMENT("key_f9")},
  312. {"kA", 78 UNTIC_COMMENT("key_il")},
  313. {"kC", 57 UNTIC_COMMENT("key_clear")},
  314. {"kD", 59 UNTIC_COMMENT("key_dc")},
  315. {"kE", 63 UNTIC_COMMENT("key_eol,")},
  316. {"kF", 84 UNTIC_COMMENT("key_sf")},
  317. {"kH", 80 UNTIC_COMMENT("key_ll")},
  318. {"kI", 77 UNTIC_COMMENT("key_ic")},
  319. {"kL", 60 UNTIC_COMMENT("key_dl")},
  320. {"kM", 62 UNTIC_COMMENT("key_eic,")},
  321. {"kN", 81 UNTIC_COMMENT("key_npage")},
  322. {"kP", 82 UNTIC_COMMENT("key_ppage")},
  323. {"kR", 85 UNTIC_COMMENT("key_sr")},
  324. {"kS", 64 UNTIC_COMMENT("key_eos,")},
  325. {"kT", 86 UNTIC_COMMENT("key_stab")},
  326. {"ka", 56 UNTIC_COMMENT("key_catab")},
  327. {"k;", 67 UNTIC_COMMENT("key_f10")},
  328. {"kb", 55 UNTIC_COMMENT("key_backspace")},
  329. {"kd", 61 UNTIC_COMMENT("key_down")},
  330. {"ke", 88 UNTIC_COMMENT("End keypad transmit mode")},
  331. {"kh", 76 UNTIC_COMMENT("key_home")},
  332. {"kl", 79 UNTIC_COMMENT("key_left")},
  333. {"kr", 83 UNTIC_COMMENT("key_right")},
  334. {"ks", 89 UNTIC_COMMENT("Start keypad transmit mode")},
  335. {"kt", 58 UNTIC_COMMENT("key_ctab")},
  336. {"ku", 87 UNTIC_COMMENT("key_up")},
  337. {"mb", 26 UNTIC_COMMENT("enter_blink_mode")},
  338. {"md", 27 UNTIC_COMMENT("enter_bold_mode")},
  339. {"me", 39 UNTIC_COMMENT("exit_attribute_mode")},
  340. {"mr", 34 UNTIC_COMMENT("enter_reverse_mode")},
  341. {"op", 297 UNTIC_COMMENT("orig_pair (color)")},
  342. {"pf", 119 UNTIC_COMMENT("turn OFF printer")},
  343. {"po", 120 UNTIC_COMMENT("turn ON printer")},
  344. {"se", 43 UNTIC_COMMENT("exit_standout_mode")},
  345. {"so", 35 UNTIC_COMMENT("enter_standout_mode")},
  346. {"sr", 130 UNTIC_COMMENT("scroll_reverse")},
  347. {"te", 40 UNTIC_COMMENT("end cursor addressing")},
  348. {"ti", 28 UNTIC_COMMENT("begin cursor addressing")},
  349. {"ts", 135 UNTIC_COMMENT("goto to status line")},
  350. {"up", 19 UNTIC_COMMENT("cursor_up")},
  351. {"us", 36 UNTIC_COMMENT("enter_underline_mode")},
  352. {"vb", 45 UNTIC_COMMENT("flash_screen")},
  353. {"ve", 16 UNTIC_COMMENT("make cursor very visible")},
  354. {"vi", 13 UNTIC_COMMENT("make cursor invisible")},
  355. {"vs", 20 UNTIC_COMMENT("make cursor very visible")},
  356. {"", 0 UNTIC_COMMENT(NULL)}
  357. };
  358. static int compute_cap_offset (char *cap, Terminfo_Type *t, Tgetstr_Map_Type *map, unsigned int max_ofs)
  359. {
  360. char cha, chb;
  361. (void) t;
  362. cha = *cap++; chb = *cap;
  363. while (*map->name != 0)
  364. {
  365. if ((cha == *map->name) && (chb == *(map->name + 1)))
  366. {
  367. if (map->offset >= (int) max_ofs) return -1;
  368. return map->offset;
  369. }
  370. map++;
  371. }
  372. return -1;
  373. }
  374. char *SLtt_tigetstr (char *cap, char **pp)
  375. {
  376. int offset;
  377. Terminfo_Type *t;
  378. if ((pp == NULL) || (NULL == (t = (Terminfo_Type *) *pp))) return NULL;
  379. if (t->flags == SLTERMCAP) return tcap_getstr (cap, t);
  380. offset = compute_cap_offset (cap, t, Tgetstr_Map, t->num_string_offsets);
  381. if (offset < 0) return NULL;
  382. offset = make_integer (t->string_offsets + 2 * offset);
  383. if (offset < 0) return NULL;
  384. return t->string_table + offset;
  385. }
  386. static Tgetstr_Map_Type Tgetnum_Map[] =
  387. {
  388. {"co", 0 UNTIC_COMMENT("columns")},
  389. {"li", 2 UNTIC_COMMENT("lines")},
  390. {"Co", 13 UNTIC_COMMENT("max colors")},
  391. {"pa", 14 UNTIC_COMMENT("max pairs")},
  392. {"sg", 4 UNTIC_COMMENT("magic cookie glitch")},
  393. {"ws", 7 UNTIC_COMMENT("num columns in status line")},
  394. {"", -1 UNTIC_COMMENT(NULL)}
  395. };
  396. int SLtt_tigetnum (char *cap, char **pp)
  397. {
  398. int offset;
  399. Terminfo_Type *t;
  400. if ((pp == NULL) || (NULL == (t = (Terminfo_Type *) *pp))) return -1;
  401. if (t->flags == SLTERMCAP) return tcap_getnum (cap, t);
  402. offset = compute_cap_offset (cap, t, Tgetnum_Map, t->num_numbers);
  403. if (offset < 0) return -1;
  404. return make_integer (t->numbers + 2 * offset);
  405. }
  406. static Tgetstr_Map_Type Tgetflag_Map[] =
  407. {
  408. {"am", 1 UNTIC_COMMENT("auto right margin")},
  409. {"hs", 9 UNTIC_COMMENT("has status line")},
  410. {"ms", 14 UNTIC_COMMENT("move standout mode")},
  411. {"xs", 3 UNTIC_COMMENT("ceol standout glitch")},
  412. {"xn", 4 UNTIC_COMMENT("NEWLINE ignored after 80 columns")},
  413. {"es", 16 UNTIC_COMMENT("status line esc ok")},
  414. {"", -1 UNTIC_COMMENT(NULL)}
  415. };
  416. int SLtt_tigetflag (char *cap, char **pp)
  417. {
  418. int offset;
  419. Terminfo_Type *t;
  420. if ((pp == NULL) || (NULL == (t = (Terminfo_Type *) *pp))) return -1;
  421. if (t->flags == SLTERMCAP) return tcap_getflag (cap, t);
  422. offset = compute_cap_offset (cap, t, Tgetflag_Map, t->boolean_section_size);
  423. if (offset < 0) return -1;
  424. return (int) *(t->boolean_flags + offset);
  425. }
  426. /* These are my termcap routines. They only work with the TERMCAP environment
  427. * variable. This variable must contain the termcap entry and NOT the file.
  428. */
  429. static int tcap_getflag (char *cap, Terminfo_Type *t)
  430. {
  431. char a, b;
  432. char *f = (char *) t->boolean_flags;
  433. char *fmax;
  434. if (f == NULL) return 0;
  435. fmax = f + t->boolean_section_size;
  436. a = *cap;
  437. b = *(cap + 1);
  438. while (f < fmax)
  439. {
  440. if ((a == f[0]) && (b == f[1]))
  441. return 1;
  442. f += 2;
  443. }
  444. return 0;
  445. }
  446. static char *tcap_get_cap (unsigned char *cap, unsigned char *caps, unsigned int len)
  447. {
  448. unsigned char c0, c1;
  449. unsigned char *caps_max;
  450. c0 = cap[0];
  451. c1 = cap[1];
  452. if (caps == NULL) return NULL;
  453. caps_max = caps + len;
  454. while (caps < caps_max)
  455. {
  456. if ((c0 == caps[0]) && (c1 == caps[1]))
  457. {
  458. return (char *) caps + 3;
  459. }
  460. caps += (int) caps[2];
  461. }
  462. return NULL;
  463. }
  464. static int tcap_getnum (char *cap, Terminfo_Type *t)
  465. {
  466. cap = tcap_get_cap ((unsigned char *) cap, t->numbers, t->num_numbers);
  467. if (cap == NULL) return -1;
  468. return atoi (cap);
  469. }
  470. static char *tcap_getstr (char *cap, Terminfo_Type *t)
  471. {
  472. return tcap_get_cap ((unsigned char *) cap, (unsigned char *) t->string_table, t->string_table_size);
  473. }
  474. static int tcap_extract_field (unsigned char *t0)
  475. {
  476. register unsigned char ch, *t = t0;
  477. while (((ch = *t) != 0) && (ch != ':')) t++;
  478. if (ch == ':') return (int) (t - t0);
  479. return -1;
  480. }
  481. int SLtt_Try_Termcap = 1;
  482. static int tcap_getent (char *term, Terminfo_Type *ti)
  483. {
  484. unsigned char *termcap, ch;
  485. unsigned char *buf, *b;
  486. unsigned char *t;
  487. int len;
  488. if (SLtt_Try_Termcap == 0) return -1;
  489. #if 1
  490. /* XFREE86 xterm sets the TERMCAP environment variable to an invalid
  491. * value. Specifically, it lacks the tc= string.
  492. */
  493. if (!strncmp (term, "xterm", 5))
  494. return -1;
  495. #endif
  496. termcap = (unsigned char *) getenv ("TERMCAP");
  497. if ((termcap == NULL) || (*termcap == '/')) return -1;
  498. /* We have a termcap so lets use it provided it does not have a reference
  499. * to another terminal via tc=. In that case, user terminfo. The alternative
  500. * would be to parse the termcap file which I do not want to do right now.
  501. * Besides, this is a terminfo based system and if the termcap were parsed
  502. * terminfo would almost never get a chance to run. In addition, the tc=
  503. * thing should not occur if tset is used to set the termcap entry.
  504. */
  505. t = termcap;
  506. while ((len = tcap_extract_field (t)) != -1)
  507. {
  508. if ((len > 3) && (t[0] == 't') && (t[1] == 'c') && (t[2] == '='))
  509. return -1;
  510. t += (len + 1);
  511. }
  512. /* malloc some extra space just in case it is needed. */
  513. len = strlen ((char *) termcap) + 256;
  514. if (NULL == (buf = (unsigned char *) SLMALLOC ((unsigned int) len))) return -1;
  515. b = buf;
  516. /* The beginning of the termcap entry contains the names of the entry.
  517. * It is terminated by a colon.
  518. */
  519. ti->terminal_names = (char *) b;
  520. t = termcap;
  521. len = tcap_extract_field (t);
  522. if (len < 0)
  523. {
  524. SLFREE (buf);
  525. return -1;
  526. }
  527. strncpy ((char *) b, (char *) t, (unsigned int) len);
  528. b[len] = 0;
  529. b += len + 1;
  530. ti->name_section_size = len;
  531. /* Now, we are really at the start of the termcap entries. Point the
  532. * termcap variable here since we want to refer to this a number of times.
  533. */
  534. termcap = t + (len + 1);
  535. /* Process strings first. */
  536. ti->string_table = (char *) b;
  537. t = termcap;
  538. while (-1 != (len = tcap_extract_field (t)))
  539. {
  540. unsigned char *b1;
  541. unsigned char *tmax;
  542. /* We are looking for: XX=something */
  543. if ((len < 4) || (t[2] != '=') || (*t == '.'))
  544. {
  545. t += len + 1;
  546. continue;
  547. }
  548. tmax = t + len;
  549. b1 = b;
  550. while (t < tmax)
  551. {
  552. ch = *t++;
  553. if ((ch == '\\') && (t < tmax))
  554. {
  555. t = (unsigned char *) SLexpand_escaped_char ((char *) t, (char *) &ch);
  556. }
  557. else if ((ch == '^') && (t < tmax))
  558. {
  559. ch = *t++;
  560. if (ch == '?') ch = 127;
  561. else ch = (ch | 0x20) - ('a' - 1);
  562. }
  563. *b++ = ch;
  564. }
  565. /* Null terminate it. */
  566. *b++ = 0;
  567. len = (int) (b - b1);
  568. b1[2] = (unsigned char) len; /* replace the = by the length */
  569. /* skip colon to next field. */
  570. t++;
  571. }
  572. ti->string_table_size = (int) (b - (unsigned char *) ti->string_table);
  573. /* Now process the numbers. */
  574. t = termcap;
  575. ti->numbers = b;
  576. while (-1 != (len = tcap_extract_field (t)))
  577. {
  578. unsigned char *b1;
  579. unsigned char *tmax;
  580. /* We are looking for: XX#NUMBER */
  581. if ((len < 4) || (t[2] != '#') || (*t == '.'))
  582. {
  583. t += len + 1;
  584. continue;
  585. }
  586. tmax = t + len;
  587. b1 = b;
  588. while (t < tmax)
  589. {
  590. *b++ = *t++;
  591. }
  592. /* Null terminate it. */
  593. *b++ = 0;
  594. len = (int) (b - b1);
  595. b1[2] = (unsigned char) len; /* replace the # by the length */
  596. t++;
  597. }
  598. ti->num_numbers = (int) (b - ti->numbers);
  599. /* Now process the flags. */
  600. t = termcap;
  601. ti->boolean_flags = b;
  602. while (-1 != (len = tcap_extract_field (t)))
  603. {
  604. /* We are looking for: XX#NUMBER */
  605. if ((len != 2) || (*t == '.') || (*t <= ' '))
  606. {
  607. t += len + 1;
  608. continue;
  609. }
  610. b[0] = t[0];
  611. b[1] = t[1];
  612. t += 3;
  613. b += 2;
  614. }
  615. ti->boolean_section_size = (int) (b - ti->boolean_flags);
  616. ti->flags = SLTERMCAP;
  617. return 0;
  618. }
  619. #else /* USE_SETUPTERM */
  620. /* Ching Hui fixes so that it will work on AIX and OSF/1 */
  621. #include <curses.h>
  622. #include <term.h>
  623. int SLtt_Try_Termcap = 1;
  624. char *SLtt_tigetent (char *term)
  625. {
  626. int rc;
  627. setupterm(term, 1, &rc);
  628. if (rc != 1)
  629. return NULL;
  630. return (char *)cur_term;
  631. }
  632. #define MATCH_CHAR(c, variable) \
  633. do { \
  634. if (*(cap + 1) == c) \
  635. return variable; \
  636. } while (0)
  637. char *SLtt_tigetstr (char *cap, char **pp)
  638. {
  639. if ((pp == NULL) || ((cur_term = (struct term *) *pp) == NULL))
  640. return NULL;
  641. switch(*cap) {
  642. case '@':
  643. MATCH_CHAR('7', key_end);
  644. break;
  645. case 'A':
  646. MATCH_CHAR('A', parm_insert_line);
  647. break;
  648. case 'D':
  649. MATCH_CHAR('L', parm_delete_line);
  650. break;
  651. case 'R':
  652. MATCH_CHAR('I', parm_right_cursor);
  653. break;
  654. case 'a':
  655. #ifdef acs_chars
  656. MATCH_CHAR('c', acs_chars);
  657. #elif defined (box_chars_1)
  658. MATCH_CHAR('c', box_chars_1); /* AIX hack */
  659. #else
  660. MATCH_CHAR('c', NULL);
  661. #endif
  662. MATCH_CHAR('e', exit_alt_charset_mode);
  663. MATCH_CHAR('s', enter_alt_charset_mode);
  664. break;
  665. case 'c':
  666. MATCH_CHAR('e', clr_eol);
  667. MATCH_CHAR('l', clear_screen);
  668. MATCH_CHAR('m', cursor_address);
  669. MATCH_CHAR('s', change_scroll_region);
  670. break;
  671. case 'd':
  672. MATCH_CHAR('c', delete_character);
  673. break;
  674. case 'e':
  675. MATCH_CHAR('i', exit_insert_mode);
  676. #ifdef ena_acs
  677. MATCH_CHAR('A', ena_acs); /* aix hack */
  678. #else
  679. MATCH_CHAR('A', NULL);
  680. #endif
  681. break;
  682. case 'i':
  683. MATCH_CHAR('m', enter_insert_mode);
  684. break;
  685. case 'k':
  686. MATCH_CHAR('0', key_f0);
  687. MATCH_CHAR('1', key_f1);
  688. MATCH_CHAR('1', key_f1);
  689. MATCH_CHAR('2', key_f2);
  690. MATCH_CHAR('3', key_f3);
  691. MATCH_CHAR('4', key_f4);
  692. MATCH_CHAR('5', key_f5);
  693. MATCH_CHAR('6', key_f6);
  694. MATCH_CHAR('7', key_f7);
  695. MATCH_CHAR('8', key_f8);
  696. MATCH_CHAR('9', key_f9);
  697. MATCH_CHAR('A', key_il);
  698. MATCH_CHAR('C', key_clear);
  699. MATCH_CHAR('D', key_dc);
  700. MATCH_CHAR('E', key_eol);
  701. MATCH_CHAR('F', key_sf);
  702. MATCH_CHAR('H', key_ll);
  703. MATCH_CHAR('I', key_ic);
  704. MATCH_CHAR('L', key_dl);
  705. MATCH_CHAR('M', key_eic);
  706. MATCH_CHAR('N', key_npage);
  707. MATCH_CHAR('P', key_ppage);
  708. MATCH_CHAR('R', key_sr);
  709. MATCH_CHAR('S', key_eos);
  710. MATCH_CHAR('T', key_stab);
  711. MATCH_CHAR('a', key_catab);
  712. MATCH_CHAR(';', key_f10);
  713. MATCH_CHAR('b', key_backspace);
  714. MATCH_CHAR('d', key_down);
  715. MATCH_CHAR('e', keypad_local);
  716. MATCH_CHAR('h', key_home);
  717. MATCH_CHAR('l', key_left);
  718. MATCH_CHAR('r', key_right);
  719. MATCH_CHAR('s', keypad_xmit);
  720. MATCH_CHAR('t', key_ctab);
  721. MATCH_CHAR('u', key_up);
  722. break;
  723. case 'm':
  724. MATCH_CHAR('b', enter_blink_mode);
  725. MATCH_CHAR('d', enter_bold_mode);
  726. MATCH_CHAR('e', exit_attribute_mode);
  727. MATCH_CHAR('r', enter_reverse_mode);
  728. break;
  729. case 's':
  730. MATCH_CHAR('e', exit_standout_mode);
  731. MATCH_CHAR('o', enter_standout_mode);
  732. MATCH_CHAR('r', scroll_reverse);
  733. break;
  734. case 't':
  735. MATCH_CHAR('e', exit_ca_mode);
  736. MATCH_CHAR('i', enter_ca_mode);
  737. break;
  738. case 'u':
  739. MATCH_CHAR('p', cursor_up);
  740. MATCH_CHAR('s', enter_underline_mode);
  741. break;
  742. case 'v':
  743. MATCH_CHAR('b', flash_screen);
  744. MATCH_CHAR('i', cursor_invisible);
  745. MATCH_CHAR('s', cursor_visible);
  746. break;
  747. case 'F':
  748. MATCH_CHAR('1', key_f11);
  749. MATCH_CHAR('2', key_f12);
  750. MATCH_CHAR('3', key_f13);
  751. MATCH_CHAR('4', key_f14);
  752. MATCH_CHAR('5', key_f15);
  753. MATCH_CHAR('6', key_f16);
  754. MATCH_CHAR('7', key_f17);
  755. MATCH_CHAR('8', key_f18);
  756. MATCH_CHAR('9', key_f19);
  757. MATCH_CHAR('A', key_f20);
  758. break;
  759. #ifdef orig_pair
  760. case 'o':
  761. MATCH_CHAR('p', orig_pair);
  762. break;
  763. #endif
  764. }
  765. return NULL;
  766. }
  767. int SLtt_tigetnum (char *cap, char **pp)
  768. {
  769. if ((pp == NULL) || ((cur_term = (struct term *) *pp) == NULL))
  770. return (int) NULL;
  771. switch(*cap) {
  772. case 'c':
  773. MATCH_CHAR('o', columns);
  774. break;
  775. case 'l':
  776. MATCH_CHAR('i', lines);
  777. break;
  778. }
  779. return -1;
  780. }
  781. int SLtt_tigetflag (char *cap, char **pp)
  782. {
  783. if ((pp == NULL) || ((cur_term = (struct term *) *pp) == NULL))
  784. return (int) NULL;
  785. switch(*cap) {
  786. case 'a':
  787. MATCH_CHAR('m', auto_right_margin);
  788. break;
  789. case 'm':
  790. MATCH_CHAR('s', move_standout_mode);
  791. break;
  792. case 'x':
  793. MATCH_CHAR('s', ceol_standout_glitch);
  794. break;
  795. case 's':
  796. MATCH_CHAR('g', magic_cookie_glitch);
  797. break;
  798. }
  799. return -1;
  800. }
  801. #endif /* !USE_SETUPTERM */