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