Commit | Line | Data |
---|---|---|
281ef544 NK |
1 | #include <newt.h> |
2 | #include <signal.h> | |
3 | #include <stdbool.h> | |
4 | ||
5 | #include "../../util/cache.h" | |
6 | #include "../../util/debug.h" | |
7 | #include "../browser.h" | |
8 | #include "../helpline.h" | |
9 | #include "../ui.h" | |
10 | #include "../util.h" | |
11 | #include "../libslang.h" | |
12 | #include "../keysyms.h" | |
13 | ||
14 | pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER; | |
15 | ||
16 | static volatile int ui__need_resize; | |
17 | ||
ba47a142 NK |
18 | extern struct perf_error_ops perf_tui_eops; |
19 | ||
281ef544 NK |
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 __used) | |
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 newt_suspend(void *d __used) | |
92 | { | |
93 | newtSuspend(); | |
94 | raise(SIGTSTP); | |
95 | newtResume(); | |
96 | } | |
97 | ||
98 | static void ui__signal(int sig) | |
99 | { | |
100 | ui__exit(false); | |
101 | psignal(sig, "perf"); | |
102 | exit(0); | |
103 | } | |
104 | ||
dc41b9b8 | 105 | int ui__init(void) |
281ef544 NK |
106 | { |
107 | int err; | |
108 | ||
109 | newtInit(); | |
110 | err = SLkp_init(); | |
111 | if (err < 0) { | |
112 | pr_err("TUI initialization failed.\n"); | |
113 | goto out; | |
114 | } | |
115 | ||
116 | SLkp_define_keysym((char *)"^(kB)", SL_KEY_UNTAB); | |
117 | ||
118 | newtSetSuspendCallback(newt_suspend, NULL); | |
119 | ui_helpline__init(); | |
120 | ui_browser__init(); | |
121 | ||
122 | signal(SIGSEGV, ui__signal); | |
123 | signal(SIGFPE, ui__signal); | |
124 | signal(SIGINT, ui__signal); | |
125 | signal(SIGQUIT, ui__signal); | |
126 | signal(SIGTERM, ui__signal); | |
ba47a142 NK |
127 | |
128 | perf_error__register(&perf_tui_eops); | |
281ef544 NK |
129 | out: |
130 | return err; | |
131 | } | |
132 | ||
133 | void ui__exit(bool wait_for_ok) | |
134 | { | |
135 | if (wait_for_ok) | |
136 | ui__question_window("Fatal Error", | |
137 | ui_helpline__last_msg, | |
138 | "Press any key...", 0); | |
139 | ||
140 | SLtt_set_cursor_visibility(1); | |
141 | SLsmg_refresh(); | |
142 | SLsmg_reset_smg(); | |
143 | SLang_reset_tty(); | |
ba47a142 NK |
144 | |
145 | perf_error__unregister(&perf_tui_eops); | |
281ef544 | 146 | } |