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