xref: /netbsd-src/external/bsd/less/dist/lesstest/term.c (revision f8cf1a9151c7af1cb0bd8b09c13c66bca599c027)
1 #include <string.h>
2 #include <fcntl.h>
3 #include <termios.h>
4 #include <termcap.h>
5 #include <sys/ioctl.h>
6 #include "lesstest.h"
7 
8 TermInfo terminfo;
9 
10 static void set_termio_flags(struct termios* s) {
11 	s->c_lflag &= ~(0
12 #ifdef ICANON
13 		| ICANON
14 #endif
15 #ifdef ECHO
16 		| ECHO
17 #endif
18 #ifdef ECHOE
19 		| ECHOE
20 #endif
21 #ifdef ECHOK
22 		| ECHOK
23 #endif
24 #if ECHONL
25 		| ECHONL
26 #endif
27 	);
28 
29 	s->c_oflag |= (0
30 #ifdef OXTABS
31 		| OXTABS
32 #else
33 #ifdef TAB3
34 		| TAB3
35 #else
36 #ifdef XTABS
37 		| XTABS
38 #endif
39 #endif
40 #endif
41 #ifdef OPOST
42 		| OPOST
43 #endif
44 #ifdef ONLCR
45 		| ONLCR
46 #endif
47 	);
48 
49 	s->c_oflag &= ~(0
50 #ifdef ONOEOT
51 		| ONOEOT
52 #endif
53 #ifdef OCRNL
54 		| OCRNL
55 #endif
56 #ifdef ONOCR
57 		| ONOCR
58 #endif
59 #ifdef ONLRET
60 		| ONLRET
61 #endif
62 	);
63 }
64 
65 // Enable or disable raw mode on the given tty.
66 void raw_mode(int tty, int on) {
67 	struct termios s;
68 	static struct termios save_term;
69 	if (!on) {
70 		s = save_term;
71 	} else {
72 		tcgetattr(tty, &s);
73 		save_term = s;
74 		set_termio_flags(&s);
75 		s.c_cc[VMIN] = 1;
76 		s.c_cc[VTIME] = 0;
77 	}
78 	tcsetattr(tty, TCSADRAIN, &s);
79 }
80 
81 // Initialize the enter & exit capabilities for a given terminal mode.
82 static void setup_mode(char* enter_cap, char* exit_cap, char** enter_str, char** exit_str, char** spp) {
83 	*enter_str = tgetstr(enter_cap, spp);
84 	if (*enter_str == NULL) *enter_str = "";
85 	*exit_str = tgetstr(exit_cap, spp);
86 	if (*exit_str == NULL) *exit_str = tgetstr("me", spp);
87 	if (*exit_str == NULL) *exit_str = "";
88 }
89 
90 static char* ltgetstr(char* id, char** area) {
91 	char* str = tgetstr(id, area);
92 	if (str == NULL) str = "";
93 	return str;
94 }
95 
96 // Initialize the terminfo struct with info about the terminal $TERM.
97 int setup_term(void) {
98 	static char termbuf[4096];
99 	static char sbuf[4096];
100 	char* term = getenv("TERM");
101 	if (term == NULL) term = "dumb";
102 	if (tgetent(termbuf, term) <= 0) {
103 		fprintf(stderr, "cannot setup terminal %s\n", term);
104 		return 0;
105 	}
106 	char* sp = sbuf;
107 	setup_mode("so", "se", &terminfo.enter_standout, &terminfo.exit_standout, &sp);
108 	setup_mode("us", "ue", &terminfo.enter_underline, &terminfo.exit_underline, &sp);
109 	setup_mode("md", "me", &terminfo.enter_bold, &terminfo.exit_bold, &sp);
110 	setup_mode("mb", "me", &terminfo.enter_blink, &terminfo.exit_blink, &sp);
111 
112 	char* bs = ltgetstr("kb", &sp);
113 	terminfo.backspace_key = (strlen(bs) == 1) ? *bs : '\b';
114 	terminfo.cursor_move = ltgetstr("cm", &sp);
115 	terminfo.clear_screen = ltgetstr("cl", &sp);
116 	terminfo.init_term = ltgetstr("ti", &sp);
117 	terminfo.deinit_term = ltgetstr("te", &sp);
118 	terminfo.enter_keypad = ltgetstr("ks", &sp);
119 	terminfo.exit_keypad = ltgetstr("ke", &sp);
120 	terminfo.key_right = ltgetstr("kr", &sp);
121 	terminfo.key_left = ltgetstr("kl", &sp);
122 	terminfo.key_up = ltgetstr("ku", &sp);
123 	terminfo.key_down = ltgetstr("kd", &sp);
124 	terminfo.key_home = ltgetstr("kh", &sp);
125 	terminfo.key_end = ltgetstr("@7", &sp);
126 	return 1;
127 }
128