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