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