1 #include <signal.h> 2 #include <stdbool.h> 3 4 #include "../../util/cache.h" 5 #include "../../util/debug.h" 6 #include "../browser.h" 7 #include "../helpline.h" 8 #include "../ui.h" 9 #include "../util.h" 10 #include "../libslang.h" 11 #include "../keysyms.h" 12 #include "tui.h" 13 14 static volatile int ui__need_resize; 15 16 extern struct perf_error_ops perf_tui_eops; 17 18 extern void hist_browser__init_hpp(void); 19 20 void ui__refresh_dimensions(bool force) 21 { 22 if (force || ui__need_resize) { 23 ui__need_resize = 0; 24 pthread_mutex_lock(&ui__lock); 25 SLtt_get_screen_size(); 26 SLsmg_reinit_smg(); 27 pthread_mutex_unlock(&ui__lock); 28 } 29 } 30 31 static void ui__sigwinch(int sig __maybe_unused) 32 { 33 ui__need_resize = 1; 34 } 35 36 static void ui__setup_sigwinch(void) 37 { 38 static bool done; 39 40 if (done) 41 return; 42 43 done = true; 44 pthread__unblock_sigwinch(); 45 signal(SIGWINCH, ui__sigwinch); 46 } 47 48 int ui__getch(int delay_secs) 49 { 50 struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL; 51 fd_set read_set; 52 int err, key; 53 54 ui__setup_sigwinch(); 55 56 FD_ZERO(&read_set); 57 FD_SET(0, &read_set); 58 59 if (delay_secs) { 60 timeout.tv_sec = delay_secs; 61 timeout.tv_usec = 0; 62 } 63 64 err = select(1, &read_set, NULL, NULL, ptimeout); 65 66 if (err == 0) 67 return K_TIMER; 68 69 if (err == -1) { 70 if (errno == EINTR) 71 return K_RESIZE; 72 return K_ERROR; 73 } 74 75 key = SLang_getkey(); 76 if (key != K_ESC) 77 return key; 78 79 FD_ZERO(&read_set); 80 FD_SET(0, &read_set); 81 timeout.tv_sec = 0; 82 timeout.tv_usec = 20; 83 err = select(1, &read_set, NULL, NULL, &timeout); 84 if (err == 0) 85 return K_ESC; 86 87 SLang_ungetkey(key); 88 return SLkp_getkey(); 89 } 90 91 static void ui__signal(int sig) 92 { 93 ui__exit(false); 94 psignal(sig, "perf"); 95 exit(0); 96 } 97 98 int ui__init(void) 99 { 100 int err; 101 102 SLutf8_enable(-1); 103 SLtt_get_terminfo(); 104 SLtt_get_screen_size(); 105 106 err = SLsmg_init_smg(); 107 if (err < 0) 108 goto out; 109 err = SLang_init_tty(0, 0, 0); 110 if (err < 0) 111 goto out; 112 113 err = SLkp_init(); 114 if (err < 0) { 115 pr_err("TUI initialization failed.\n"); 116 goto out; 117 } 118 119 SLkp_define_keysym((char *)"^(kB)", SL_KEY_UNTAB); 120 121 ui_helpline__init(); 122 ui_browser__init(); 123 tui_progress__init(); 124 125 signal(SIGSEGV, ui__signal); 126 signal(SIGFPE, ui__signal); 127 signal(SIGINT, ui__signal); 128 signal(SIGQUIT, ui__signal); 129 signal(SIGTERM, ui__signal); 130 131 perf_error__register(&perf_tui_eops); 132 133 hist_browser__init_hpp(); 134 out: 135 return err; 136 } 137 138 void ui__exit(bool wait_for_ok) 139 { 140 if (wait_for_ok) 141 ui__question_window("Fatal Error", 142 ui_helpline__last_msg, 143 "Press any key...", 0); 144 145 SLtt_set_cursor_visibility(1); 146 SLsmg_refresh(); 147 SLsmg_reset_smg(); 148 SLang_reset_tty(); 149 150 perf_error__unregister(&perf_tui_eops); 151 } 152