📄 sltermin.c
字号:
/* This file contains enough terminfo reading capabilities sufficient for
* the slang SLtt interface.
*/
/* Copyright (c) 1992, 1995 John E. Davis
* All rights reserved.
*
* You may distribute under the terms of either the GNU General Public
* License or the Perl Artistic License.
*/
#include "config.h"
#include <stdio.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#ifndef USE_SETUPTERM
#include "slang.h"
#include "_slang.h"
/*
* The majority of the comments found in the file were taken from the
* term(4) man page on an SGI.
*/
/* Short integers are stored in two 8-bit bytes. The first byte contains
* the least significant 8 bits of the value, and the second byte contains
* the most significant 8 bits. (Thus, the value represented is
* 256*second+first.) The value -1 is represented by 0377,0377, and the
* value -2 is represented by 0376,0377; other negative values are illegal.
* The -1 generally means that a capability is missing from this terminal.
* The -2 means that the capability has been cancelled in the terminfo
* source and also is to be considered missing.
*/
static int make_integer (unsigned char *buf)
{
register int lo, hi;
lo = (int) *buf++; hi = (int) *buf;
if (hi == 0377)
{
if (lo == 0377) return -1;
if (lo == 0376) return -2;
}
return lo + 256 * hi;
}
/*
* The compiled file is created from the source file descriptions of the
* terminals (see the -I option of infocmp) by using the terminfo compiler,
* tic, and read by the routine setupterm [see curses(3X).] The file is
* divided into six parts in the following order: the header, terminal
* names, boolean flags, numbers, strings, and string table.
*
* The header section begins the file. This section contains six short
* integers in the format described below. These integers are (1) the magic
* number (octal 0432); (2) the size, in bytes, of the names section; (3)
* the number of bytes in the boolean section; (4) the number of short
* integers in the numbers section; (5) the number of offsets (short
* integers) in the strings section; (6) the size, in bytes, of the string
* table.
*/
#define MAGIC 0432
/* In this structure, all char * fields are malloced EXCEPT if the
* structure is SLTERMCAP. In that case, only terminal_names is malloced
* and the other fields are pointers into it.
*/
typedef struct
{
#define SLTERMINFO 1
#define SLTERMCAP 2
unsigned int flags;
unsigned int name_section_size;
char *terminal_names;
unsigned int boolean_section_size;
unsigned char *boolean_flags;
unsigned int num_numbers;
unsigned char *numbers;
unsigned int num_string_offsets;
unsigned char *string_offsets;
unsigned int string_table_size;
char *string_table;
} Terminfo_Type;
static char *tcap_getstr (char *, Terminfo_Type *);
static int tcap_getnum (char *, Terminfo_Type *);
static int tcap_getflag (char *, Terminfo_Type *);
static int tcap_getent (char *, Terminfo_Type *);
static FILE *open_terminfo (char *file, Terminfo_Type *h)
{
FILE *fp;
unsigned char buf[12];
fp = fopen (file, "rb");
if (fp == NULL) return NULL;
if ((12 == fread ((char *) buf, 1, 12, fp) && (MAGIC == make_integer (buf))))
{
h->name_section_size = make_integer (buf + 2);
h->boolean_section_size = make_integer (buf + 4);
h->num_numbers = make_integer (buf + 6);
h->num_string_offsets = make_integer (buf + 8);
h->string_table_size = make_integer (buf + 10);
}
else
{
fclose (fp);
fp = NULL;
}
return fp;
}
/*
* The terminal names section comes next. It contains the first line of the
* terminfo description, listing the various names for the terminal,
* separated by the bar ( | ) character (see term(5)). The section is
* terminated with an ASCII NUL character.
*/
/* returns pointer to malloced space */
static unsigned char *read_terminfo_section (FILE *fp, unsigned int size)
{
char *s;
if (NULL == (s = (char *) SLMALLOC (size))) return NULL;
if (size != fread (s, 1, size, fp))
{
SLFREE (s);
return NULL;
}
return (unsigned char *) s;
}
static char *read_terminal_names (FILE *fp, Terminfo_Type *t)
{
return t->terminal_names = (char *) read_terminfo_section (fp, t->name_section_size);
}
/*
* The boolean flags have one byte for each flag. This byte is either 0 or
* 1 as the flag is present or absent. The value of 2 means that the flag
* has been cancelled. The capabilities are in the same order as the file
* <term.h>.
*/
static unsigned char *read_boolean_flags (FILE *fp, Terminfo_Type *t)
{
/* Between the boolean section and the number section, a null byte is
* inserted, if necessary, to ensure that the number section begins on an
* even byte offset. All short integers are aligned on a short word
* boundary.
*/
unsigned int size = (t->name_section_size + t->boolean_section_size) % 2;
size += t->boolean_section_size;
return t->boolean_flags = read_terminfo_section (fp, size);
}
/*
* The numbers section is similar to the boolean flags section. Each
* capability takes up two bytes, and is stored as a short integer. If the
* value represented is -1 or -2, the capability is taken to be missing.
*/
static unsigned char *read_numbers (FILE *fp, Terminfo_Type *t)
{
return t->numbers = read_terminfo_section (fp, 2 * t->num_numbers);
}
/* The strings section is also similar. Each capability is stored as a
* short integer, in the format above. A value of -1 or -2 means the
* capability is missing. Otherwise, the value is taken as an offset from
* the beginning of the string table. Special characters in ^X or \c
* notation are stored in their interpreted form, not the printing
* representation. Padding information ($<nn>) and parameter information
* (%x) are stored intact in uninterpreted form.
*/
static unsigned char *read_string_offsets (FILE *fp, Terminfo_Type *t)
{
return t->string_offsets = (unsigned char *) read_terminfo_section (fp, 2 * t->num_string_offsets);
}
/* The final section is the string table. It contains all the values of
* string capabilities referenced in the string section. Each string is
* null terminated.
*/
static char *read_string_table (FILE *fp, Terminfo_Type *t)
{
return t->string_table = (char *) read_terminfo_section (fp, t->string_table_size);
}
/*
* Compiled terminfo(4) descriptions are placed under the directory
* /usr/share/lib/terminfo. In order to avoid a linear search of a huge
* UNIX system directory, a two-level scheme is used:
* /usr/share/lib/terminfo/c/name where name is the name of the terminal,
* and c is the first character of name. Thus, att4425 can be found in the
* file /usr/share/lib/terminfo/a/att4425. Synonyms for the same terminal
* are implemented by multiple links to the same compiled file.
*/
#define MAX_TI_DIRS 7
static char *Terminfo_Dirs [MAX_TI_DIRS] =
{
NULL,
"/usr/lib/terminfo",
"/usr/share/lib/terminfo",
"/usr/local/lib/terminfo",
"/lib/terminfo",
"/usr/local/share/terminfo",
"/usr/share/terminfo"
};
char *SLtt_tigetent (char *term)
{
char *tidir;
int i;
FILE *fp = NULL;
char file[256];
Terminfo_Type *ti;
if (
(term == NULL)
#ifdef SLANG_UNTIC
&& (SLang_Untic_Terminfo_File == NULL)
#endif
)
return NULL;
if (NULL == (ti = (Terminfo_Type *) SLMALLOC (sizeof (Terminfo_Type))))
{
return NULL;
}
#ifdef SLANG_UNTIC
if (SLang_Untic_Terminfo_File != NULL)
{
fp = open_terminfo (SLang_Untic_Terminfo_File, ti);
goto fp_open_label;
}
else
#endif
/* If we are on a termcap based system, use termcap */
if (0 == tcap_getent (term, ti)) return (char *) ti;
Terminfo_Dirs[0] = getenv ("TERMINFO");
i = 0;
while (i < MAX_TI_DIRS)
{
tidir = Terminfo_Dirs[i];
if (tidir != NULL)
{
sprintf (file, "%s/%c/%s", tidir, *term, term);
if (NULL != (fp = open_terminfo (file, ti))) break;
}
i++;
}
#ifdef SLANG_UNTIC
fp_open_label:
#endif
if (fp != NULL)
{
if (NULL != read_terminal_names (fp, ti))
{
if (NULL != read_boolean_flags (fp, ti))
{
if (NULL != read_numbers (fp, ti))
{
if (NULL != read_string_offsets (fp, ti))
{
if (NULL != read_string_table (fp, ti))
{
/* success */
fclose (fp);
ti->flags = SLTERMINFO;
return (char *) ti;
}
SLFREE (ti->string_offsets);
}
SLFREE (ti->numbers);
}
SLFREE (ti->boolean_flags);
}
SLFREE (ti->terminal_names);
}
fclose (fp);
}
SLFREE (ti);
return NULL;
}
#ifdef SLANG_UNTIC
# define UNTIC_COMMENT(x) ,x
#else
# define UNTIC_COMMENT(x)
#endif
typedef struct
{
char name[3];
int offset;
#ifdef SLANG_UNTIC
char *comment;
#endif
}
Tgetstr_Map_Type;
/* I need to add: K1-5, %0-5(not important), @8, &8... */
static Tgetstr_Map_Type Tgetstr_Map [] =
{
{"@7", 164 UNTIC_COMMENT("KEY End")},
{"AB", 360 UNTIC_COMMENT("set a color background")},
{"AF", 359 UNTIC_COMMENT("set a color foreground")},
{"AL", 110 UNTIC_COMMENT("parm_insert_line")},
{"DL", 106 UNTIC_COMMENT("parm_delete_line")},
{"RI", 112 UNTIC_COMMENT("parm_right_cursor")},
{"Sf", 302 UNTIC_COMMENT("set foreground (color)")},
{"Sb", 303 UNTIC_COMMENT("set background (color)")},
{"ac", 146 UNTIC_COMMENT("acs_chars")},
{"ae", 38 UNTIC_COMMENT("exit_alt_charset_mode")},
{"as", 25 UNTIC_COMMENT("enter_alt_charset_mode")},
{"ce", 6 UNTIC_COMMENT("clr_eol")},
{"cl", 5 UNTIC_COMMENT("clear_screen")},
{"cm", 10 UNTIC_COMMENT("cursor_address")},
{"cs", 3 UNTIC_COMMENT("change_scroll_region")},
{"dc", 21 UNTIC_COMMENT("delete_character")},
{"ds", 23 UNTIC_COMMENT("disable status line")},
{"eA", 155 UNTIC_COMMENT("enable alt char set")},
{"ei", 42 UNTIC_COMMENT("exit_insert_mode")},
{"fs", 47 UNTIC_COMMENT("return from status line")},
{"im", 31 UNTIC_COMMENT("enter_insert_mode")},
{"k0", 65 UNTIC_COMMENT("key_f0")},
{"k1", 66 UNTIC_COMMENT("key_f1")},
{"k2", 68 UNTIC_COMMENT("key_f2")},
{"k3", 69 UNTIC_COMMENT("key_f3")},
{"k4", 70 UNTIC_COMMENT("key_f4")},
{"k5", 71 UNTIC_COMMENT("key_f5")},
{"k6", 72 UNTIC_COMMENT("key_f6")},
{"k7", 73 UNTIC_COMMENT("key_f7")},
{"k8", 74 UNTIC_COMMENT("key_f8")},
{"k9", 75 UNTIC_COMMENT("key_f9")},
{"kA", 78 UNTIC_COMMENT("key_il")},
{"kC", 57 UNTIC_COMMENT("key_clear")},
{"kD", 59 UNTIC_COMMENT("key_dc")},
{"kE", 63 UNTIC_COMMENT("key_eol,")},
{"kF", 84 UNTIC_COMMENT("key_sf")},
{"kH", 80 UNTIC_COMMENT("key_ll")},
{"kI", 77 UNTIC_COMMENT("key_ic")},
{"kL", 60 UNTIC_COMMENT("key_dl")},
{"kM", 62 UNTIC_COMMENT("key_eic,")},
{"kN", 81 UNTIC_COMMENT("key_npage")},
{"kP", 82 UNTIC_COMMENT("key_ppage")},
{"kR", 85 UNTIC_COMMENT("key_sr")},
{"kS", 64 UNTIC_COMMENT("key_eos,")},
{"kT", 86 UNTIC_COMMENT("key_stab")},
{"ka", 56 UNTIC_COMMENT("key_catab")},
{"k;", 67 UNTIC_COMMENT("key_f10")},
{"kb", 55 UNTIC_COMMENT("key_backspace")},
{"kd", 61 UNTIC_COMMENT("key_down")},
{"ke", 88 UNTIC_COMMENT("End keypad transmit mode")},
{"kh", 76 UNTIC_COMMENT("key_home")},
{"kl", 79 UNTIC_COMMENT("key_left")},
{"kr", 83 UNTIC_COMMENT("key_right")},
{"ks", 89 UNTIC_COMMENT("Start keypad transmit mode")},
{"kt", 58 UNTIC_COMMENT("key_ctab")},
{"ku", 87 UNTIC_COMMENT("key_up")},
{"mb", 26 UNTIC_COMMENT("enter_blink_mode")},
{"md", 27 UNTIC_COMMENT("enter_bold_mode")},
{"me", 39 UNTIC_COMMENT("exit_attribute_mode")},
{"mr", 34 UNTIC_COMMENT("enter_reverse_mode")},
{"op", 297 UNTIC_COMMENT("orig_pair (color)")},
{"pf", 119 UNTIC_COMMENT("turn OFF printer")},
{"po", 120 UNTIC_COMMENT("turn ON printer")},
{"se", 43 UNTIC_COMMENT("exit_standout_mode")},
{"so", 35 UNTIC_COMMENT("enter_standout_mode")},
{"sr", 130 UNTIC_COMMENT("scroll_reverse")},
{"te", 40 UNTIC_COMMENT("end cursor addressing")},
{"ti", 28 UNTIC_COMMENT("begin cursor addressing")},
{"ts", 135 UNTIC_COMMENT("goto to status line")},
{"up", 19 UNTIC_COMMENT("cursor_up")},
{"us", 36 UNTIC_COMMENT("enter_underline_mode")},
{"vb", 45 UNTIC_COMMENT("flash_screen")},
{"ve", 16 UNTIC_COMMENT("make cursor very visible")},
{"vi", 13 UNTIC_COMMENT("make cursor invisible")},
{"vs", 20 UNTIC_COMMENT("make cursor very visible")},
{"", 0 UNTIC_COMMENT(NULL)}
};
static int compute_cap_offset (char *cap, Terminfo_Type *t, Tgetstr_Map_Type *map, unsigned int max_ofs)
{
char cha, chb;
(void) t;
cha = *cap++; chb = *cap;
while (*map->name != 0)
{
if ((cha == *map->name) && (chb == *(map->name + 1)))
{
if (map->offset >= (int) max_ofs) return -1;
return map->offset;
}
map++;
}
return -1;
}
char *SLtt_tigetstr (char *cap, char **pp)
{
int offset;
Terminfo_Type *t;
if ((pp == NULL) || (NULL == (t = (Terminfo_Type *) *pp))) return NULL;
if (t->flags == SLTERMCAP) return tcap_getstr (cap, t);
offset = compute_cap_offset (cap, t, Tgetstr_Map, t->num_string_offsets);
if (offset < 0) return NULL;
offset = make_integer (t->string_offsets + 2 * offset);
if (offset < 0) return NULL;
return t->string_table + offset;
}
static Tgetstr_Map_Type Tgetnum_Map[] =
{
{"co", 0 UNTIC_COMMENT("columns")},
{"li", 2 UNTIC_COMMENT("lines")},
{"Co", 13 UNTIC_COMMENT("max colors")},
{"pa", 14 UNTIC_COMMENT("max pairs")},
{"sg", 4 UNTIC_COMMENT("magic cookie glitch")},
{"ws", 7 UNTIC_COMMENT("num columns in status line")},
{"", -1 UNTIC_COMMENT(NULL)}
};
int SLtt_tigetnum (char *cap, char **pp)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -