File: term.c

package info (click to toggle)
less 668-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 10,988 kB
  • sloc: ansic: 24,976; perl: 884; sh: 399; makefile: 123; python: 33
file content (128 lines) | stat: -rw-r--r-- 2,850 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <termcap.h>
#include <sys/ioctl.h>
#include "lesstest.h"

TermInfo terminfo;

static void set_termio_flags(struct termios* s) {
	s->c_lflag &= ~(0
#ifdef ICANON
		| ICANON
#endif
#ifdef ECHO
		| ECHO
#endif
#ifdef ECHOE
		| ECHOE
#endif
#ifdef ECHOK
		| ECHOK
#endif
#if ECHONL
		| ECHONL
#endif
	);

	s->c_oflag |= (0
#ifdef OXTABS
		| OXTABS
#else
#ifdef TAB3
		| TAB3
#else
#ifdef XTABS
		| XTABS
#endif
#endif
#endif
#ifdef OPOST
		| OPOST
#endif
#ifdef ONLCR
		| ONLCR
#endif
	);

	s->c_oflag &= ~(0
#ifdef ONOEOT
		| ONOEOT
#endif
#ifdef OCRNL
		| OCRNL
#endif
#ifdef ONOCR
		| ONOCR
#endif
#ifdef ONLRET
		| ONLRET
#endif
	);
}

// Enable or disable raw mode on the given tty.
void raw_mode(int tty, int on) {
	struct termios s;
	static struct termios save_term;
	if (!on) {
		s = save_term;
	} else {
		tcgetattr(tty, &s);
		save_term = s;
		set_termio_flags(&s);
		s.c_cc[VMIN] = 1;
		s.c_cc[VTIME] = 0;
	}
	tcsetattr(tty, TCSADRAIN, &s);
}

// Initialize the enter & exit capabilities for a given terminal mode.
static void setup_mode(char* enter_cap, char* exit_cap, char** enter_str, char** exit_str, char** spp) {
	*enter_str = tgetstr(enter_cap, spp);
	if (*enter_str == NULL) *enter_str = "";
	*exit_str = tgetstr(exit_cap, spp);
	if (*exit_str == NULL) *exit_str = tgetstr("me", spp);
	if (*exit_str == NULL) *exit_str = "";
}

static char* ltgetstr(char* id, char** area) {
	char* str = tgetstr(id, area);
	if (str == NULL) str = "";
	return str;
}

// Initialize the terminfo struct with info about the terminal $TERM.
int setup_term(void) {
	static char termbuf[4096];
	static char sbuf[4096];
	char* term = getenv("TERM");
	if (term == NULL) term = "dumb";
	if (tgetent(termbuf, term) <= 0) {
		fprintf(stderr, "cannot setup terminal %s\n", term);
		return 0;
	}
	char* sp = sbuf;
	setup_mode("so", "se", &terminfo.enter_standout, &terminfo.exit_standout, &sp);
	setup_mode("us", "ue", &terminfo.enter_underline, &terminfo.exit_underline, &sp);
	setup_mode("md", "me", &terminfo.enter_bold, &terminfo.exit_bold, &sp);
	setup_mode("mb", "me", &terminfo.enter_blink, &terminfo.exit_blink, &sp);

	char* bs = ltgetstr("kb", &sp);
	terminfo.backspace_key = (strlen(bs) == 1) ? *bs : '\b';
	terminfo.cursor_move = ltgetstr("cm", &sp);
	terminfo.clear_screen = ltgetstr("cl", &sp);
	terminfo.clear_eos = ltgetstr("cd", &sp);
	terminfo.init_term = ltgetstr("ti", &sp);
	terminfo.deinit_term = ltgetstr("te", &sp);
	terminfo.enter_keypad = ltgetstr("ks", &sp);
	terminfo.exit_keypad = ltgetstr("ke", &sp);
	terminfo.key_right = ltgetstr("kr", &sp);
	terminfo.key_left = ltgetstr("kl", &sp);
	terminfo.key_up = ltgetstr("ku", &sp);
	terminfo.key_down = ltgetstr("kd", &sp);
	terminfo.key_home = ltgetstr("kh", &sp);
	terminfo.key_end = ltgetstr("@7", &sp);
	return 1;
}