]>
Commit | Line | Data |
---|---|---|
d5a8d3e8 | 1 | #include "config.h" |
2 | ||
139f06bc | 3 | #include <slang.h> |
6fb96a3f | 4 | #include <stdio.h> |
5 | #include <stdlib.h> | |
6 | #include <string.h> | |
ae1235d0 | 7 | #include <sys/signal.h> |
6fb96a3f | 8 | #include <sys/time.h> |
9 | #include <sys/types.h> | |
91be88a7 | 10 | #include <termios.h> |
6fb96a3f | 11 | #include <unistd.h> |
349586bb | 12 | #include <wchar.h> |
6fb96a3f | 13 | |
d5a8d3e8 | 14 | #ifdef HAVE_ALLOCA_H |
15 | #include <alloca.h> | |
16 | #endif | |
17 | ||
6fb96a3f | 18 | #include "newt.h" |
19 | #include "newt_pr.h" | |
20 | ||
6fb96a3f | 21 | struct Window { |
22 | int height, width, top, left; | |
6a1d8e87 | 23 | SLsmg_Char_Type * buffer; |
aa47774f | 24 | char * title; |
6fb96a3f | 25 | }; |
26 | ||
27 | struct keymap { | |
28 | char * str; | |
29 | int code; | |
30 | char * tc; | |
31 | }; | |
32 | ||
a1f11019 | 33 | static struct Window windowStack[20]; |
34 | static struct Window * currentWindow = NULL; | |
6fb96a3f | 35 | |
a1f11019 | 36 | static char * helplineStack[20]; |
37 | static char ** currentHelpline = NULL; | |
38 | ||
39 | static int cursorRow, cursorCol; | |
5e171db1 | 40 | static int cursorOn = 1; |
9b146a9f | 41 | static int noFlowCtrl = 0; |
7ff5fd71 | 42 | static int trashScreen = 0; |
0593cb33 | 43 | extern int needResize; |
81361f3e | 44 | |
6605d1bf | 45 | static const char * const defaultHelpLine = |
7d4604a9 | 46 | " <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next screen" |
47 | ; | |
48 | ||
57c466b0 | 49 | const struct newtColors newtDefaultColorPalette = { |
6f481af2 | 50 | "white", "blue", /* root fg, bg */ |
51 | "black", "lightgray", /* border fg, bg */ | |
52 | "black", "lightgray", /* window fg, bg */ | |
53 | "white", "black", /* shadow fg, bg */ | |
54 | "red", "lightgray", /* title fg, bg */ | |
55 | "lightgray", "red", /* button fg, bg */ | |
56 | "red", "lightgray", /* active button fg, bg */ | |
f838d158 | 57 | "lightgray", "blue", /* checkbox fg, bg */ |
58 | "lightgray", "red", /* active checkbox fg, bg */ | |
59 | "lightgray", "blue", /* entry box fg, bg */ | |
6f481af2 | 60 | "blue", "lightgray", /* label fg, bg */ |
61 | "black", "lightgray", /* listbox fg, bg */ | |
f838d158 | 62 | "lightgray", "blue", /* active listbox fg, bg */ |
6f481af2 | 63 | "black", "lightgray", /* textbox fg, bg */ |
f838d158 | 64 | "lightgray", "red", /* active textbox fg, bg */ |
6f481af2 | 65 | "white", "blue", /* help line */ |
f838d158 | 66 | "lightgray", "blue", /* root text */ |
6f481af2 | 67 | "blue", /* scale full */ |
68 | "red", /* scale empty */ | |
69 | "blue", "lightgray", /* disabled entry fg, bg */ | |
feef2cb5 | 70 | "black", "lightgray", /* compact button fg, bg */ |
f838d158 | 71 | "lightgray", "red", /* active & sel listbox */ |
6f481af2 | 72 | "black", "brown" /* selected listbox */ |
6fb96a3f | 73 | }; |
74 | ||
57c466b0 | 75 | static const struct keymap keymap[] = { |
feef2cb5 | 76 | { "\033OA", NEWT_KEY_UP, "ku" }, |
77 | { "\020", NEWT_KEY_UP, NULL }, /* emacs ^P */ | |
6f481af2 | 78 | { "\033OB", NEWT_KEY_DOWN, "kd" }, |
feef2cb5 | 79 | { "\016", NEWT_KEY_DOWN, NULL }, /* emacs ^N */ |
6f481af2 | 80 | { "\033OC", NEWT_KEY_RIGHT, "kr" }, |
feef2cb5 | 81 | { "\006", NEWT_KEY_RIGHT, NULL }, /* emacs ^F */ |
6f481af2 | 82 | { "\033OD", NEWT_KEY_LEFT, "kl" }, |
feef2cb5 | 83 | { "\002", NEWT_KEY_LEFT, NULL }, /* emacs ^B */ |
84 | { "\033OH", NEWT_KEY_HOME, "kh" }, | |
85 | { "\033[1~", NEWT_KEY_HOME, NULL }, | |
86 | { "\001", NEWT_KEY_HOME, NULL }, /* emacs ^A */ | |
6f481af2 | 87 | { "\033Ow", NEWT_KEY_END, "kH" }, |
feef2cb5 | 88 | { "\033[4~", NEWT_KEY_END, "@7" }, |
89 | { "\005", NEWT_KEY_END, NULL }, /* emacs ^E */ | |
6f481af2 | 90 | |
feef2cb5 | 91 | { "\033[3~", NEWT_KEY_DELETE, "kD" }, |
92 | { "\004", NEWT_KEY_DELETE, NULL }, /* emacs ^D */ | |
93 | { "\033[2~", NEWT_KEY_INSERT, "kI" }, | |
6f481af2 | 94 | |
feef2cb5 | 95 | { "\033\t", NEWT_KEY_UNTAB, "kB" }, |
3003455e | 96 | { "\033[Z", NEWT_KEY_UNTAB, NULL }, |
6f481af2 | 97 | |
feef2cb5 | 98 | { "\033[5~", NEWT_KEY_PGUP, "kP" }, |
99 | { "\033[6~", NEWT_KEY_PGDN, "kN" }, | |
100 | { "\033V", NEWT_KEY_PGUP, NULL }, | |
101 | { "\033v", NEWT_KEY_PGUP, NULL }, | |
102 | { "\026", NEWT_KEY_PGDN, NULL }, | |
6f481af2 | 103 | |
104 | { "\033[[A", NEWT_KEY_F1, NULL }, | |
105 | { "\033[[B", NEWT_KEY_F2, NULL }, | |
106 | { "\033[[C", NEWT_KEY_F3, NULL }, | |
107 | { "\033[[D", NEWT_KEY_F4, NULL }, | |
108 | { "\033[[E", NEWT_KEY_F5, NULL }, | |
109 | ||
110 | { "\033OP", NEWT_KEY_F1, NULL }, | |
111 | { "\033OQ", NEWT_KEY_F2, NULL }, | |
112 | { "\033OR", NEWT_KEY_F3, NULL }, | |
113 | { "\033OS", NEWT_KEY_F4, NULL }, | |
114 | ||
feef2cb5 | 115 | { "\033[11~", NEWT_KEY_F1, "k1" }, |
116 | { "\033[12~", NEWT_KEY_F2, "k2" }, | |
117 | { "\033[13~", NEWT_KEY_F3, "k3" }, | |
118 | { "\033[14~", NEWT_KEY_F4, "k4" }, | |
119 | { "\033[15~", NEWT_KEY_F5, "k5" }, | |
120 | { "\033[17~", NEWT_KEY_F6, "k6" }, | |
121 | { "\033[18~", NEWT_KEY_F7, "k7" }, | |
122 | { "\033[19~", NEWT_KEY_F8, "k8" }, | |
123 | { "\033[20~", NEWT_KEY_F9, "k9" }, | |
124 | { "\033[21~", NEWT_KEY_F10, "k;" }, | |
125 | { "\033[23~", NEWT_KEY_F11, "F1" }, | |
126 | { "\033[24~", NEWT_KEY_F12, "F2" }, | |
127 | { "\033", NEWT_KEY_ESCAPE, "@2" }, | |
128 | { "\033", NEWT_KEY_ESCAPE, "@9" }, | |
129 | ||
130 | { "\177", NEWT_KEY_BKSPC, NULL }, | |
131 | { "\010", NEWT_KEY_BKSPC, NULL }, | |
132 | ||
6f481af2 | 133 | { 0 }, /* LEAVE this one */ |
6fb96a3f | 134 | }; |
feef2cb5 | 135 | static void initKeymap(); |
136c3059 | 136 | static void freeKeymap(); |
88d3e0a3 | 137 | |
16e8af2f | 138 | static const char ident[] = // ident friendly |
139 | "$Version: Newt windowing library v" VERSION " $" | |
140 | "$Copyright: (C) 1996-2003 Red Hat, Inc. Written by Erik Troan $" | |
141 | "$License: Lesser GNU Public License. $"; | |
6fb96a3f | 142 | |
b7c1b763 | 143 | static newtSuspendCallback suspendCallback = NULL; |
06cf519e | 144 | static void * suspendCallbackData = NULL; |
b7c1b763 | 145 | |
06cf519e | 146 | void newtSetSuspendCallback(newtSuspendCallback cb, void * data) { |
b7c1b763 | 147 | suspendCallback = cb; |
06cf519e | 148 | suspendCallbackData = data; |
b7c1b763 | 149 | } |
150 | ||
ae1235d0 | 151 | static void handleSigwinch(int signum) { |
152 | needResize = 1; | |
153 | } | |
154 | ||
155 | static int getkeyInterruptHook(void) { | |
156 | return -1; | |
157 | } | |
158 | ||
feef2cb5 | 159 | int _newt_wstrlen(const char *str, int len) { |
6f481af2 | 160 | mbstate_t ps; |
161 | wchar_t tmp; | |
162 | int nchars = 0; | |
163 | ||
164 | if (!str) return 0; | |
165 | if (!len) return 0; | |
166 | if (len < 0) len = strlen(str); | |
167 | memset(&ps,0,sizeof(mbstate_t)); | |
168 | while (len > 0) { | |
169 | int x,y; | |
170 | ||
171 | x = mbrtowc(&tmp,str,len,&ps); | |
172 | if (x >0) { | |
173 | str += x; | |
174 | len -= x; | |
175 | y = wcwidth(tmp); | |
176 | if (y>0) | |
177 | nchars+=y; | |
178 | } else break; | |
179 | } | |
180 | return nchars; | |
349586bb | 181 | } |
182 | ||
feef2cb5 | 183 | /** Trim a string to fit |
184 | * @param title - string. NULL will be inserted if necessary | |
185 | * @param chrs - available space. (character cells) | |
186 | */ | |
187 | void trim_string(char *title, int chrs) | |
188 | { | |
189 | char *p = title; | |
b9b1302c | 190 | int ln; |
feef2cb5 | 191 | int x = 0,y = 0; |
192 | wchar_t tmp; | |
193 | mbstate_t ps; | |
194 | ||
195 | memset(&ps, 0, sizeof(ps)); | |
b9b1302c | 196 | ln = strlen(title); |
feef2cb5 | 197 | |
198 | while (*p) { | |
199 | x = mbrtowc(&tmp, p, ln, &ps); | |
200 | if (x < 0) { // error | |
201 | *p = '\0'; | |
202 | return; | |
203 | } | |
204 | y = wcwidth(tmp); | |
b9b1302c | 205 | if (y > chrs) { |
feef2cb5 | 206 | *p = '\0'; |
207 | return; | |
208 | } else { | |
209 | p += x; | |
b9b1302c | 210 | ln -= x; |
211 | chrs -= y; | |
feef2cb5 | 212 | } |
213 | } | |
214 | } | |
215 | ||
16e8af2f | 216 | static int getkey() { |
217 | int c; | |
218 | ||
219 | while ((c = SLang_getkey()) == '\xC') { /* if Ctrl-L redraw whole screen */ | |
5baf7e4b | 220 | SLsmg_touch_lines(0, SLtt_Screen_Rows); |
16e8af2f | 221 | SLsmg_refresh(); |
222 | } | |
223 | return c; | |
224 | ||
225 | } | |
226 | ||
34e56d12 ML |
227 | static void updateColorset(char *fg, char *bg, char **fg_p, char **bg_p) |
228 | { | |
229 | if (*fg && fg_p) | |
230 | *fg_p = fg; | |
231 | if (*bg && bg_p) | |
232 | *bg_p = bg; | |
233 | } | |
234 | ||
235 | /* parse color specifications (e.g. root=,black:border=red,blue) | |
236 | * and update the palette | |
237 | */ | |
238 | static void parseColors(char *s, struct newtColors *palette) | |
239 | { | |
240 | char *name, *str, *fg, *bg; | |
34e56d12 ML |
241 | |
242 | for (str = s; (s = strtok(str, ";:\n\r\t ")); str = NULL) { | |
243 | name = s; | |
244 | if (!(s = strchr(s, '=')) || !*s) | |
245 | continue; | |
246 | *s = '\0'; | |
247 | fg = ++s; | |
248 | if (!(s = strchr(s, ',')) || !*s) | |
249 | continue; | |
250 | *s = '\0'; | |
251 | bg = ++s; | |
252 | ||
253 | if (!strcmp(name, "root")) | |
254 | updateColorset(fg, bg, &palette->rootFg, &palette->rootBg); | |
255 | else if (!strcmp(name, "border")) | |
256 | updateColorset(fg, bg, &palette->borderFg, &palette->borderBg); | |
257 | else if (!strcmp(name, "window")) | |
258 | updateColorset(fg, bg, &palette->windowFg, &palette->windowBg); | |
259 | else if (!strcmp(name, "shadow")) | |
260 | updateColorset(fg, bg, &palette->shadowFg, &palette->shadowBg); | |
261 | else if (!strcmp(name, "title")) | |
262 | updateColorset(fg, bg, &palette->titleFg, &palette->titleBg); | |
263 | else if (!strcmp(name, "button")) | |
264 | updateColorset(fg, bg, &palette->buttonFg, &palette->buttonBg); | |
265 | else if (!strcmp(name, "actbutton")) | |
266 | updateColorset(fg, bg, &palette->actButtonFg, &palette->actButtonBg); | |
267 | else if (!strcmp(name, "checkbox")) | |
268 | updateColorset(fg, bg, &palette->checkboxFg, &palette->checkboxBg); | |
269 | else if (!strcmp(name, "actcheckbox")) | |
270 | updateColorset(fg, bg, &palette->actCheckboxFg, &palette->actCheckboxBg); | |
271 | else if (!strcmp(name, "entry")) | |
272 | updateColorset(fg, bg, &palette->entryFg, &palette->entryBg); | |
273 | else if (!strcmp(name, "label")) | |
274 | updateColorset(fg, bg, &palette->labelFg, &palette->labelBg); | |
275 | else if (!strcmp(name, "listbox")) | |
276 | updateColorset(fg, bg, &palette->listboxFg, &palette->listboxBg); | |
277 | else if (!strcmp(name, "actlistbox")) | |
278 | updateColorset(fg, bg, &palette->actListboxFg, &palette->actListboxBg); | |
279 | else if (!strcmp(name, "textbox")) | |
280 | updateColorset(fg, bg, &palette->textboxFg, &palette->textboxBg); | |
281 | else if (!strcmp(name, "acttextbox")) | |
282 | updateColorset(fg, bg, &palette->actTextboxFg, &palette->actTextboxBg); | |
283 | else if (!strcmp(name, "helpline")) | |
284 | updateColorset(fg, bg, &palette->helpLineFg, &palette->helpLineBg); | |
285 | else if (!strcmp(name, "roottext")) | |
286 | updateColorset(fg, bg, &palette->rootTextFg, &palette->rootTextBg); | |
287 | else if (!strcmp(name, "emptyscale")) | |
288 | updateColorset(fg, bg, NULL, &palette->emptyScale); | |
289 | else if (!strcmp(name, "fullscale")) | |
290 | updateColorset(fg, bg, NULL, &palette->fullScale); | |
291 | else if (!strcmp(name, "disentry")) | |
292 | updateColorset(fg, bg, &palette->disabledEntryFg, &palette->disabledEntryBg); | |
293 | else if (!strcmp(name, "compactbutton")) | |
294 | updateColorset(fg, bg, &palette->compactButtonFg, &palette->compactButtonBg); | |
295 | else if (!strcmp(name, "actsellistbox")) | |
296 | updateColorset(fg, bg, &palette->actSelListboxFg, &palette->actSelListboxBg); | |
297 | else if (!strcmp(name, "sellistbox")) | |
298 | updateColorset(fg, bg, &palette->selListboxFg, &palette->selListboxBg); | |
299 | } | |
300 | } | |
301 | ||
302 | static void initColors(void) | |
303 | { | |
304 | char *colors, *colors_file, buf[16384]; | |
305 | FILE *f; | |
306 | struct newtColors palette; | |
307 | ||
308 | palette = newtDefaultColorPalette; | |
309 | ||
310 | colors_file = getenv("NEWT_COLORS_FILE"); | |
311 | #ifdef NEWT_COLORS_FILE | |
312 | if (colors_file == NULL) | |
313 | colors_file = NEWT_COLORS_FILE; | |
314 | #endif | |
315 | ||
316 | if ((colors = getenv("NEWT_COLORS"))) { | |
317 | strncpy(buf, colors, sizeof (buf)); | |
318 | buf[sizeof (buf) - 1] = '\0'; | |
319 | parseColors(buf, &palette); | |
320 | } else if (colors_file && *colors_file && (f = fopen(colors_file, "r"))) { | |
321 | size_t r; | |
322 | if ((r = fread(buf, 1, sizeof (buf) - 1, f)) > 0) { | |
323 | buf[r] = '\0'; | |
324 | parseColors(buf, &palette); | |
325 | } | |
326 | fclose(f); | |
327 | } | |
328 | ||
329 | newtSetColors(palette); | |
330 | } | |
331 | ||
327436b3 | 332 | void newtFlushInput(void) { |
333 | while (SLang_input_pending(0)) { | |
6f481af2 | 334 | getkey(); |
327436b3 | 335 | } |
336 | } | |
337 | ||
3eec7ce4 | 338 | /** |
339 | * @brief Refresh the screen | |
340 | */ | |
6fb96a3f | 341 | void newtRefresh(void) { |
342 | SLsmg_refresh(); | |
343 | } | |
344 | ||
3cf3e1b9 | 345 | void newtSuspend(void) { |
5e171db1 | 346 | SLtt_set_cursor_visibility (1); |
3cf3e1b9 | 347 | SLsmg_suspend_smg(); |
348 | SLang_reset_tty(); | |
5e171db1 | 349 | SLtt_set_cursor_visibility (cursorOn); |
3cf3e1b9 | 350 | } |
351 | ||
3eec7ce4 | 352 | /** |
353 | * @brief Return after suspension. | |
354 | * @return 0 on success. | |
355 | */ | |
b3ddfdd7 | 356 | int newtResume(void) { |
3cf3e1b9 | 357 | SLsmg_resume_smg (); |
358 | SLsmg_refresh(); | |
9b146a9f | 359 | return SLang_init_tty(0, noFlowCtrl, 0); |
3cf3e1b9 | 360 | } |
361 | ||
6fb96a3f | 362 | void newtCls(void) { |
81361f3e | 363 | SLsmg_set_color(NEWT_COLORSET_ROOT); |
6fb96a3f | 364 | SLsmg_gotorc(0, 0); |
365 | SLsmg_erase_eos(); | |
366 | ||
367 | newtRefresh(); | |
368 | } | |
369 | ||
3eec7ce4 | 370 | /** |
371 | * @brief Resize the screen | |
372 | * @param redraw - boolean - should we redraw the screen? | |
373 | */ | |
ae1235d0 | 374 | void newtResizeScreen(int redraw) { |
0593cb33 | 375 | /* we can't redraw from scratch, just redisplay SLang screen */ |
ae1235d0 | 376 | SLtt_get_screen_size(); |
0593cb33 | 377 | /* SLsmg_reinit_smg(); */ |
16e8af2f | 378 | if (redraw) { |
5baf7e4b | 379 | SLsmg_touch_lines(0, SLtt_Screen_Rows); |
16e8af2f | 380 | newtRefresh(); |
381 | } | |
ae1235d0 | 382 | } |
383 | ||
3eec7ce4 | 384 | /** |
385 | * @brief Initialize the newt library | |
386 | * @return int - 0 for success, else < 0 | |
387 | */ | |
6fb96a3f | 388 | int newtInit(void) { |
16e8af2f | 389 | char * MonoValue, * MonoEnv = "NEWT_MONO"; |
9b146a9f | 390 | char * NoFlowCtrlValue, * NoFlowCtrlEnv = "NEWT_NOFLOWCTRL"; |
16e8af2f | 391 | const char *lang; |
b3ddfdd7 | 392 | int ret; |
16e8af2f | 393 | |
394 | if ((lang = getenv("LC_ALL")) == NULL) | |
395 | if ((lang = getenv("LC_CTYPE")) == NULL) | |
396 | if ((lang = getenv("LANG")) == NULL) | |
397 | lang = ""; | |
3aab8830 | 398 | /* slang doesn't support multibyte encodings except UTF-8, |
399 | avoid character corruption by redrawing the screen */ | |
16e8af2f | 400 | if (strstr (lang, ".euc") != NULL) |
6f481af2 | 401 | trashScreen = 1; |
91be88a7 | 402 | |
16e8af2f | 403 | (void) strlen(ident); |
88d3e0a3 | 404 | |
33b96ba3 | 405 | SLutf8_enable(-1); |
6fb96a3f | 406 | SLtt_get_terminfo(); |
ae1235d0 | 407 | SLtt_get_screen_size(); |
91be88a7 | 408 | |
7d4604a9 | 409 | MonoValue = getenv(MonoEnv); |
85ee6604 | 410 | if ( MonoValue != NULL ) |
6f481af2 | 411 | SLtt_Use_Ansi_Colors = 0; |
6fb96a3f | 412 | |
9b146a9f RG |
413 | NoFlowCtrlValue = getenv(NoFlowCtrlEnv); |
414 | if ( NoFlowCtrlValue != NULL ) | |
415 | noFlowCtrl = 1; | |
416 | ||
b3ddfdd7 | 417 | if ((ret = SLsmg_init_smg()) < 0) |
6f481af2 | 418 | return ret; |
9b146a9f | 419 | if ((ret = SLang_init_tty(0, noFlowCtrl, 0)) < 0) |
6f481af2 | 420 | return ret; |
45f6c4fd | 421 | |
34e56d12 | 422 | initColors(); |
23efd09b | 423 | newtCursorOff(); |
feef2cb5 | 424 | initKeymap(); |
6fb96a3f | 425 | |
ae1235d0 | 426 | SLsignal_intr(SIGWINCH, handleSigwinch); |
427 | SLang_getkey_intr_hook = getkeyInterruptHook; | |
428 | ||
6fb96a3f | 429 | return 0; |
430 | } | |
431 | ||
3eec7ce4 | 432 | /** |
433 | * @brief Closedown the newt library, tidying screen. | |
434 | * @returns int , 0. (no errors reported) | |
435 | */ | |
6fb96a3f | 436 | int newtFinished(void) { |
a753da93 | 437 | if (currentWindow) { |
438 | for (; currentWindow >= windowStack; currentWindow--) { | |
439 | free(currentWindow->buffer); | |
440 | free(currentWindow->title); | |
441 | } | |
442 | currentWindow = NULL; | |
443 | } | |
444 | ||
445 | if (currentHelpline) { | |
446 | for (; currentHelpline >= helplineStack; currentHelpline--) | |
447 | free(*currentHelpline); | |
448 | currentHelpline = NULL; | |
449 | } | |
450 | ||
136c3059 ML |
451 | freeKeymap(); |
452 | ||
6fb96a3f | 453 | SLsmg_gotorc(SLtt_Screen_Rows - 1, 0); |
23efd09b | 454 | newtCursorOn(); |
6fb96a3f | 455 | SLsmg_refresh(); |
456 | SLsmg_reset_smg(); | |
457 | SLang_reset_tty(); | |
458 | ||
459 | return 0; | |
460 | } | |
461 | ||
3eec7ce4 | 462 | /** |
463 | * @brief Set the colors used. | |
464 | * @param colors - newtColor struct used. | |
465 | */ | |
6fb96a3f | 466 | void newtSetColors(struct newtColors colors) { |
16e8af2f | 467 | if (!SLtt_Use_Ansi_Colors) { |
468 | int i; | |
469 | ||
470 | for (i = 2; i < 25; i++) | |
471 | SLtt_set_mono(i, NULL, 0); | |
472 | ||
473 | SLtt_set_mono(NEWT_COLORSET_SELLISTBOX, NULL, SLTT_BOLD_MASK); | |
474 | ||
475 | SLtt_set_mono(NEWT_COLORSET_ACTBUTTON, NULL, SLTT_REV_MASK); | |
476 | SLtt_set_mono(NEWT_COLORSET_ACTCHECKBOX, NULL, SLTT_REV_MASK); | |
477 | SLtt_set_mono(NEWT_COLORSET_ACTLISTBOX, NULL, SLTT_REV_MASK); | |
478 | SLtt_set_mono(NEWT_COLORSET_ACTTEXTBOX, NULL, SLTT_REV_MASK); | |
479 | ||
480 | SLtt_set_mono(NEWT_COLORSET_ACTSELLISTBOX, NULL, SLTT_REV_MASK | SLTT_BOLD_MASK); | |
481 | ||
482 | SLtt_set_mono(NEWT_COLORSET_DISENTRY, NULL, 0); // FIXME | |
483 | SLtt_set_mono(NEWT_COLORSET_FULLSCALE, NULL, SLTT_ULINE_MASK | SLTT_REV_MASK); | |
484 | SLtt_set_mono(NEWT_COLORSET_EMPTYSCALE, NULL, SLTT_ULINE_MASK); | |
485 | return; | |
486 | } | |
81361f3e | 487 | SLtt_set_color(NEWT_COLORSET_ROOT, "", colors.rootFg, colors.rootBg); |
488 | SLtt_set_color(NEWT_COLORSET_BORDER, "", colors.borderFg, colors.borderBg); | |
489 | SLtt_set_color(NEWT_COLORSET_WINDOW, "", colors.windowFg, colors.windowBg); | |
490 | SLtt_set_color(NEWT_COLORSET_SHADOW, "", colors.shadowFg, colors.shadowBg); | |
491 | SLtt_set_color(NEWT_COLORSET_TITLE, "", colors.titleFg, colors.titleBg); | |
492 | SLtt_set_color(NEWT_COLORSET_BUTTON, "", colors.buttonFg, colors.buttonBg); | |
45f6c4fd | 493 | SLtt_set_color(NEWT_COLORSET_ACTBUTTON, "", colors.actButtonFg, |
6f481af2 | 494 | colors.actButtonBg); |
45f6c4fd | 495 | SLtt_set_color(NEWT_COLORSET_CHECKBOX, "", colors.checkboxFg, |
6f481af2 | 496 | colors.checkboxBg); |
45f6c4fd | 497 | SLtt_set_color(NEWT_COLORSET_ACTCHECKBOX, "", colors.actCheckboxFg, |
6f481af2 | 498 | colors.actCheckboxBg); |
81361f3e | 499 | SLtt_set_color(NEWT_COLORSET_ENTRY, "", colors.entryFg, colors.entryBg); |
500 | SLtt_set_color(NEWT_COLORSET_LABEL, "", colors.labelFg, colors.labelBg); | |
45f6c4fd | 501 | SLtt_set_color(NEWT_COLORSET_LISTBOX, "", colors.listboxFg, |
6f481af2 | 502 | colors.listboxBg); |
45f6c4fd | 503 | SLtt_set_color(NEWT_COLORSET_ACTLISTBOX, "", colors.actListboxFg, |
6f481af2 | 504 | colors.actListboxBg); |
45f6c4fd | 505 | SLtt_set_color(NEWT_COLORSET_TEXTBOX, "", colors.textboxFg, |
6f481af2 | 506 | colors.textboxBg); |
45f6c4fd | 507 | SLtt_set_color(NEWT_COLORSET_ACTTEXTBOX, "", colors.actTextboxFg, |
6f481af2 | 508 | colors.actTextboxBg); |
45f6c4fd | 509 | SLtt_set_color(NEWT_COLORSET_HELPLINE, "", colors.helpLineFg, |
6f481af2 | 510 | colors.helpLineBg); |
45f6c4fd | 511 | SLtt_set_color(NEWT_COLORSET_ROOTTEXT, "", colors.rootTextFg, |
6f481af2 | 512 | colors.rootTextBg); |
3cf3e1b9 | 513 | |
5505c898 | 514 | SLtt_set_color(NEWT_COLORSET_EMPTYSCALE, "", "white", |
6f481af2 | 515 | colors.emptyScale); |
5505c898 | 516 | SLtt_set_color(NEWT_COLORSET_FULLSCALE, "", "white", |
6f481af2 | 517 | colors.fullScale); |
a1f11019 | 518 | SLtt_set_color(NEWT_COLORSET_DISENTRY, "", colors.disabledEntryFg, |
6f481af2 | 519 | colors.disabledEntryBg); |
39dd7d98 | 520 | |
521 | SLtt_set_color(NEWT_COLORSET_COMPACTBUTTON, "", colors.compactButtonFg, | |
6f481af2 | 522 | colors.compactButtonBg); |
45f6c4fd | 523 | |
46263d9e | 524 | SLtt_set_color(NEWT_COLORSET_ACTSELLISTBOX, "", colors.actSelListboxFg, |
6f481af2 | 525 | colors.actSelListboxBg); |
46263d9e | 526 | SLtt_set_color(NEWT_COLORSET_SELLISTBOX, "", colors.selListboxFg, |
6f481af2 | 527 | colors.selListboxBg); |
6fb96a3f | 528 | } |
529 | ||
70728aab | 530 | void newtSetColor(int colorset, char *fg, char *bg) { |
7b6003b0 ML |
531 | if (colorset < NEWT_COLORSET_ROOT || |
532 | (colorset > NEWT_COLORSET_SELLISTBOX && colorset < NEWT_COLORSET_CUSTOM(0)) || | |
70728aab | 533 | !SLtt_Use_Ansi_Colors) |
534 | return; | |
535 | ||
536 | SLtt_set_color(colorset, "", fg, bg); | |
537 | } | |
538 | ||
feef2cb5 | 539 | /* Keymap handling - rewritten by Henning Makholm <henning@makholm.net>, |
540 | * November 2003. | |
541 | */ | |
542 | ||
543 | struct kmap_trie_entry { | |
136c3059 | 544 | char alloced; /* alloced/not first element in array */ |
feef2cb5 | 545 | char c ; /* character got from terminal */ |
546 | int code; /* newt key, or 0 if c does not make a complete sequence */ | |
547 | struct kmap_trie_entry *contseq; /* sub-trie for character following c */ | |
548 | struct kmap_trie_entry *next; /* try this if char received != c */ | |
549 | }; | |
136c3059 ML |
550 | |
551 | static struct kmap_trie_entry *kmap_trie_root = NULL; | |
feef2cb5 | 552 | static int keyreader_buf_len = 10 ; |
553 | static unsigned char default_keyreader_buf[10]; | |
554 | static unsigned char *keyreader_buf = default_keyreader_buf; | |
555 | ||
556 | #if 0 /* for testing of the keymap manipulation code */ | |
557 | static void dumpkeys_recursive(struct kmap_trie_entry *curr, int i, FILE *f) { | |
558 | int j, ps ; | |
559 | char seen[256]={0}; | |
560 | if( curr && i >= keyreader_buf_len ) { | |
561 | fprintf(f,"ARGH! Too long sequence!\n") ; | |
562 | return ; | |
563 | } | |
564 | for(;curr;curr=curr->next) { | |
565 | keyreader_buf[i] = curr->c ; | |
566 | ps = seen[(unsigned char)curr->c]++ ; | |
567 | if( ps || curr->code || (!curr->code && !curr->contseq) ) { | |
568 | for(j=0;j<=i;j++) { | |
569 | if( keyreader_buf[j] > 32 && keyreader_buf[j]<127 && | |
570 | keyreader_buf[j] != '^' && keyreader_buf[j] != '\\' ) | |
571 | fprintf(f,"%c",keyreader_buf[j]); | |
572 | else if( keyreader_buf[j] > 0 && keyreader_buf[j]<=32 ) | |
573 | fprintf(f,"^%c",keyreader_buf[j] + 0x40); | |
574 | else | |
575 | fprintf(f,"\\%03o", | |
576 | (unsigned)(unsigned char)keyreader_buf[j]); | |
577 | } | |
578 | if( curr->code ) | |
579 | fprintf(f,": 0x%X\n",curr->code); | |
580 | else | |
581 | fprintf(f,": (just keymap)\n"); | |
582 | } | |
583 | dumpkeys_recursive(curr->contseq,i+1,f); | |
584 | } | |
585 | } | |
586 | static void dump_keymap(void) { | |
587 | FILE *f = fopen("newt.keydump","wt"); | |
588 | if (f) { | |
136c3059 | 589 | dumpkeys_recursive(kmap_trie_root, 0, f); |
feef2cb5 | 590 | fclose(f); |
591 | } | |
592 | } | |
593 | #endif | |
594 | ||
595 | /* newtBindKey may overwrite a binding that is there already */ | |
596 | static void newtBindKey(char *keyseq, int meaning) { | |
136c3059 | 597 | struct kmap_trie_entry *root = kmap_trie_root ; |
feef2cb5 | 598 | struct kmap_trie_entry **curptr = &root ; |
599 | ||
600 | /* Try to make sure the common matching buffer is long enough. */ | |
601 | if( strlen(keyseq) > keyreader_buf_len ) { | |
602 | int i = strlen(keyseq)+10; | |
603 | unsigned char *newbuf = malloc(i); | |
604 | if (newbuf) { | |
605 | if (keyreader_buf != default_keyreader_buf) | |
606 | free(keyreader_buf); | |
607 | keyreader_buf = newbuf; | |
608 | keyreader_buf_len = i; | |
609 | } | |
610 | } | |
611 | ||
612 | if (*keyseq == 0) return; /* binding the empty sequence is meaningless */ | |
613 | ||
614 | while(1) { | |
615 | while ((*curptr) && (*curptr)->c != *keyseq) | |
616 | curptr = &(*curptr)->next; | |
617 | if ((*curptr)==0) { | |
618 | struct kmap_trie_entry* fresh | |
619 | = calloc(strlen(keyseq),sizeof(struct kmap_trie_entry)); | |
620 | if (fresh == 0) return; /* despair! */ | |
136c3059 | 621 | fresh->alloced = 1; |
feef2cb5 | 622 | *curptr = fresh; |
623 | while (keyseq[1]) { | |
624 | fresh->contseq = fresh+1; | |
625 | (fresh++)->c = *(keyseq++); | |
626 | } | |
627 | fresh->c = *keyseq; | |
628 | fresh->code = meaning; | |
629 | return; | |
630 | } | |
631 | if (keyseq[1]==0) { | |
632 | (*curptr)->code = meaning; | |
633 | return; | |
634 | } else { | |
635 | curptr = &(*curptr)->contseq; | |
636 | keyseq++; | |
637 | } | |
638 | } | |
639 | } | |
640 | ||
641 | /* This function recursively inserts all entries in the "to" trie into | |
642 | corresponding positions in the "from" trie, except positions that | |
643 | are already defined in the "from" trie. */ | |
644 | static void kmap_trie_fallback(struct kmap_trie_entry *to, | |
645 | struct kmap_trie_entry **from) { | |
646 | if (*from == NULL) | |
647 | *from = to ; | |
648 | if (*from == to) | |
649 | return ; | |
650 | for (;to!=NULL;to=to->next) { | |
651 | struct kmap_trie_entry **fromcopy = from ; | |
652 | while ((*fromcopy) && (*fromcopy)->c != to->c) | |
653 | fromcopy = &(*fromcopy)->next ; | |
654 | if (*fromcopy) { | |
655 | if ((*fromcopy)->code == 0) | |
656 | (*fromcopy)->code = to->code; | |
657 | kmap_trie_fallback(to->contseq, &(*fromcopy)->contseq); | |
658 | } else { | |
659 | *fromcopy = malloc(sizeof(struct kmap_trie_entry)); | |
660 | if (*fromcopy) { | |
661 | **fromcopy = *to ; | |
136c3059 | 662 | (*fromcopy)->alloced = 1; |
feef2cb5 | 663 | (*fromcopy)->next = 0 ; |
664 | } | |
665 | } | |
666 | } | |
667 | } | |
668 | ||
6fb96a3f | 669 | int newtGetKey(void) { |
b8b8a86f | 670 | int key, lastcode, errors = 0; |
feef2cb5 | 671 | unsigned char *chptr = keyreader_buf, *lastmatch; |
136c3059 | 672 | struct kmap_trie_entry *curr = kmap_trie_root; |
6fb96a3f | 673 | |
b7c1b763 | 674 | do { |
6f481af2 | 675 | key = getkey(); |
676 | if (key == SLANG_GETKEY_ERROR) { | |
6f481af2 | 677 | if (needResize) { |
16e8af2f | 678 | needResize = 0; |
6f481af2 | 679 | return NEWT_KEY_RESIZE; |
16e8af2f | 680 | } |
ae1235d0 | 681 | |
b8b8a86f ML |
682 | /* Ignore other signals, but assume that stdin disappeared (the |
683 | * parent terminal was proably closed) if the error persists. | |
684 | */ | |
685 | if (errors++ > 10) | |
686 | return NEWT_KEY_ERROR; | |
687 | ||
6f481af2 | 688 | continue; |
689 | } | |
ae1235d0 | 690 | |
6f481af2 | 691 | if (key == NEWT_KEY_SUSPEND && suspendCallback) |
692 | suspendCallback(suspendCallbackData); | |
b8b8a86f | 693 | } while (key == NEWT_KEY_SUSPEND || key == SLANG_GETKEY_ERROR); |
6fb96a3f | 694 | |
feef2cb5 | 695 | /* Read more characters, matching against the trie as we go */ |
696 | lastcode = *chptr = key; | |
697 | lastmatch = chptr ; | |
698 | while(1) { | |
699 | while (curr->c != key) { | |
700 | curr = curr->next ; | |
701 | if (curr==NULL) goto break2levels; | |
702 | } | |
703 | if (curr->code) { | |
704 | lastcode = curr->code; | |
705 | lastmatch = chptr; | |
706 | } | |
707 | curr = curr->contseq; | |
708 | if (curr==NULL) break; | |
709 | ||
710 | if (SLang_input_pending(5) <= 0) | |
711 | break; | |
712 | ||
713 | if (chptr==keyreader_buf+keyreader_buf_len-1) break; | |
714 | *++chptr = key = getkey(); | |
6fb96a3f | 715 | } |
feef2cb5 | 716 | break2levels: |
717 | ||
718 | /* The last time the trie matched was at position lastmatch. Back | |
719 | * up if we have read too many characters. */ | |
720 | while (chptr > lastmatch) | |
721 | SLang_ungetkey(*chptr--); | |
722 | ||
723 | return lastcode; | |
6fb96a3f | 724 | } |
725 | ||
3eec7ce4 | 726 | /** |
727 | * @brief Wait for a keystroke | |
728 | */ | |
6fb96a3f | 729 | void newtWaitForKey(void) { |
730 | newtRefresh(); | |
731 | ||
16e8af2f | 732 | getkey(); |
6fb96a3f | 733 | newtClearKeyBuffer(); |
734 | } | |
735 | ||
3eec7ce4 | 736 | /** |
737 | * @brief Clear the keybuffer | |
738 | */ | |
6fb96a3f | 739 | void newtClearKeyBuffer(void) { |
740 | while (SLang_input_pending(1)) { | |
6f481af2 | 741 | getkey(); |
6fb96a3f | 742 | } |
743 | } | |
744 | ||
3eec7ce4 | 745 | /** |
746 | * Open a new window. | |
edad3d82 | 747 | * @param left. int Size; _not_ including border |
748 | * @param top: int size, _not_ including border | |
3eec7ce4 | 749 | * @param width unsigned int |
750 | * @param height unsigned int | |
751 | * @param title - title string | |
a753da93 | 752 | * @return zero on success |
3eec7ce4 | 753 | */ |
edad3d82 | 754 | int newtOpenWindow(int left, int top, |
feef2cb5 | 755 | unsigned int width, unsigned int height, |
6f481af2 | 756 | const char * title) { |
46263d9e | 757 | int j, row, col; |
d4663248 | 758 | int n; |
44de2c93 | 759 | int i; |
6fb96a3f | 760 | |
327436b3 | 761 | newtFlushInput(); |
762 | ||
a753da93 | 763 | if (currentWindow && currentWindow - windowStack + 1 |
764 | >= sizeof (windowStack) / sizeof (struct Window)) | |
765 | return 1; | |
766 | ||
6fb96a3f | 767 | if (!currentWindow) { |
6f481af2 | 768 | currentWindow = windowStack; |
6fb96a3f | 769 | } else { |
6f481af2 | 770 | currentWindow++; |
6fb96a3f | 771 | } |
772 | ||
773 | currentWindow->left = left; | |
774 | currentWindow->top = top; | |
775 | currentWindow->width = width; | |
776 | currentWindow->height = height; | |
649a0152 | 777 | currentWindow->title = title ? strdup(title) : NULL; |
6fb96a3f | 778 | |
b9b1302c | 779 | currentWindow->buffer = malloc(sizeof(SLsmg_Char_Type) * (width + 5) * (height + 3)); |
6fb96a3f | 780 | |
781 | row = top - 1; | |
b9b1302c | 782 | col = left - 2; |
22cc0d5e | 783 | /* clip to the current screen bounds - msw */ |
784 | if (row < 0) | |
6f481af2 | 785 | row = 0; |
22cc0d5e | 786 | if (col < 0) |
6f481af2 | 787 | col = 0; |
22cc0d5e | 788 | if (left + width > SLtt_Screen_Cols) |
6f481af2 | 789 | width = SLtt_Screen_Cols - left; |
22cc0d5e | 790 | if (top + height > SLtt_Screen_Rows) |
6f481af2 | 791 | height = SLtt_Screen_Rows - top; |
d4663248 | 792 | n = 0; |
6fb96a3f | 793 | for (j = 0; j < height + 3; j++, row++) { |
6f481af2 | 794 | SLsmg_gotorc(row, col); |
795 | SLsmg_read_raw(currentWindow->buffer + n, | |
b9b1302c | 796 | currentWindow->width + 5); |
797 | n += currentWindow->width + 5; | |
6fb96a3f | 798 | } |
799 | ||
7ff5fd71 | 800 | newtTrashScreen(); |
801 | ||
81361f3e | 802 | SLsmg_set_color(NEWT_COLORSET_BORDER); |
feef2cb5 | 803 | SLsmg_set_char_set(1); |
6fb96a3f | 804 | SLsmg_draw_box(top - 1, left - 1, height + 2, width + 2); |
feef2cb5 | 805 | SLsmg_set_char_set(0); |
6fb96a3f | 806 | |
aa47774f | 807 | if (currentWindow->title) { |
feef2cb5 | 808 | trim_string (currentWindow->title, width-4); |
6f481af2 | 809 | i = wstrlen(currentWindow->title,-1) + 4; |
810 | i = ((width - i) / 2) + left; | |
811 | SLsmg_gotorc(top - 1, i); | |
812 | SLsmg_set_char_set(1); | |
813 | SLsmg_write_char(SLSMG_RTEE_CHAR); | |
814 | SLsmg_set_char_set(0); | |
815 | SLsmg_write_char(' '); | |
816 | SLsmg_set_color(NEWT_COLORSET_TITLE); | |
10de8f4a | 817 | SLsmg_write_string((char *)currentWindow->title); |
6f481af2 | 818 | SLsmg_set_color(NEWT_COLORSET_BORDER); |
819 | SLsmg_write_char(' '); | |
820 | SLsmg_set_char_set(1); | |
821 | SLsmg_write_char(SLSMG_LTEE_CHAR); | |
822 | SLsmg_set_char_set(0); | |
6fb96a3f | 823 | } |
824 | ||
81361f3e | 825 | SLsmg_set_color(NEWT_COLORSET_WINDOW); |
6fb96a3f | 826 | SLsmg_fill_region(top, left, height, width, ' '); |
827 | ||
81361f3e | 828 | SLsmg_set_color(NEWT_COLORSET_SHADOW); |
6fb96a3f | 829 | SLsmg_fill_region(top + height + 1, left, 1, width + 2, ' '); |
830 | SLsmg_fill_region(top, left + width + 1, height + 1, 1, ' '); | |
831 | ||
832 | for (i = top; i < (top + height + 1); i++) { | |
6f481af2 | 833 | SLsmg_gotorc(i, left + width + 1); |
834 | SLsmg_write_string(" "); | |
6fb96a3f | 835 | } |
44de2c93 | 836 | |
837 | return 0; | |
6fb96a3f | 838 | } |
839 | ||
3eec7ce4 | 840 | /** |
841 | * @brief Draw a centered window. | |
842 | * @param width - width in char cells | |
843 | * @param height - no. of char cells. | |
844 | * @param title - fixed title | |
a753da93 | 845 | * @returns zero on success |
3eec7ce4 | 846 | */ |
feef2cb5 | 847 | int newtCenteredWindow(unsigned int width,unsigned int height, |
848 | const char * title) { | |
edad3d82 | 849 | int top, left; |
f16e164f | 850 | |
edad3d82 | 851 | top = (int)(SLtt_Screen_Rows - height) / 2; |
f16e164f | 852 | |
45f6c4fd | 853 | /* I don't know why, but this seems to look better */ |
f16e164f | 854 | if ((SLtt_Screen_Rows % 2) && (top % 2)) top--; |
855 | ||
edad3d82 | 856 | left = (int)(SLtt_Screen_Cols - width) / 2; |
f16e164f | 857 | |
a753da93 | 858 | return newtOpenWindow(left, top, width, height, title); |
f16e164f | 859 | } |
860 | ||
3eec7ce4 | 861 | /** |
862 | * @brief Remove the top window | |
863 | */ | |
6fb96a3f | 864 | void newtPopWindow(void) { |
e5df813b | 865 | newtPopWindowNoRefresh(); |
866 | newtRefresh(); | |
867 | } | |
868 | ||
869 | void newtPopWindowNoRefresh(void) { | |
6fb96a3f | 870 | int j, row, col; |
45f6c4fd | 871 | int n = 0; |
6fb96a3f | 872 | |
a753da93 | 873 | if (currentWindow == NULL) |
874 | return; | |
875 | ||
6fb96a3f | 876 | row = col = 0; |
877 | ||
878 | row = currentWindow->top - 1; | |
b9b1302c | 879 | col = currentWindow->left - 2; |
22cc0d5e | 880 | if (row < 0) |
6f481af2 | 881 | row = 0; |
22cc0d5e | 882 | if (col < 0) |
6f481af2 | 883 | col = 0; |
6fb96a3f | 884 | for (j = 0; j < currentWindow->height + 3; j++, row++) { |
6f481af2 | 885 | SLsmg_gotorc(row, col); |
886 | SLsmg_write_raw(currentWindow->buffer + n, | |
b9b1302c | 887 | currentWindow->width + 5); |
888 | n += currentWindow->width + 5; | |
6fb96a3f | 889 | } |
890 | ||
891 | free(currentWindow->buffer); | |
aa47774f | 892 | free(currentWindow->title); |
6fb96a3f | 893 | |
45f6c4fd | 894 | if (currentWindow == windowStack) |
6f481af2 | 895 | currentWindow = NULL; |
6fb96a3f | 896 | else |
6f481af2 | 897 | currentWindow--; |
6fb96a3f | 898 | |
899 | SLsmg_set_char_set(0); | |
900 | ||
7ff5fd71 | 901 | newtTrashScreen(); |
6fb96a3f | 902 | } |
903 | ||
45f6c4fd | 904 | void newtGetWindowPos(int * x, int * y) { |
905 | if (currentWindow) { | |
6f481af2 | 906 | *x = currentWindow->left; |
907 | *y = currentWindow->top; | |
45f6c4fd | 908 | } else |
6f481af2 | 909 | *x = *y = 0; |
45f6c4fd | 910 | } |
911 | ||
a1f11019 | 912 | void newtGetrc(int * row, int * col) { |
28de1915 | 913 | *row = cursorRow; |
914 | *col = cursorCol; | |
915 | ||
916 | if (currentWindow) { | |
917 | *row -= currentWindow->top; | |
918 | *col -= currentWindow->left; | |
919 | } | |
a1f11019 | 920 | } |
921 | ||
922 | void newtGotorc(int newRow, int newCol) { | |
923 | if (currentWindow) { | |
6f481af2 | 924 | newRow += currentWindow->top; |
925 | newCol += currentWindow->left; | |
a1f11019 | 926 | } |
927 | ||
928 | cursorRow = newRow; | |
929 | cursorCol = newCol; | |
930 | SLsmg_gotorc(cursorRow, cursorCol); | |
6fb96a3f | 931 | } |
932 | ||
933 | void newtDrawBox(int left, int top, int width, int height, int shadow) { | |
934 | if (currentWindow) { | |
6f481af2 | 935 | top += currentWindow->top; |
936 | left += currentWindow->left; | |
6fb96a3f | 937 | } |
938 | ||
939 | SLsmg_draw_box(top, left, height, width); | |
940 | ||
941 | if (shadow) { | |
6f481af2 | 942 | SLsmg_set_color(NEWT_COLORSET_SHADOW); |
943 | SLsmg_fill_region(top + height, left + 1, 1, width - 1, ' '); | |
944 | SLsmg_fill_region(top + 1, left + width, height, 1, ' '); | |
6fb96a3f | 945 | } |
946 | } | |
947 | ||
948 | void newtClearBox(int left, int top, int width, int height) { | |
949 | if (currentWindow) { | |
6f481af2 | 950 | top += currentWindow->top; |
951 | left += currentWindow->left; | |
6fb96a3f | 952 | } |
953 | ||
954 | SLsmg_fill_region(top, left, height, width, ' '); | |
955 | } | |
956 | ||
6fb96a3f | 957 | static void initKeymap(void) { |
feef2cb5 | 958 | const struct keymap * curr; |
136c3059 ML |
959 | struct kmap_trie_entry *kmap_trie_escBrack, *kmap_trie_escO; |
960 | ||
961 | /* Here are some entries that will help in handling esc O foo and | |
962 | esc [ foo as variants of each other. */ | |
963 | kmap_trie_root = calloc(3, sizeof (struct kmap_trie_entry)); | |
964 | kmap_trie_escBrack = kmap_trie_root + 1; | |
965 | kmap_trie_escO = kmap_trie_root + 2; | |
966 | ||
967 | kmap_trie_root->alloced = 1; | |
968 | kmap_trie_root->c = '\033'; | |
969 | kmap_trie_root->contseq = kmap_trie_escBrack; | |
970 | ||
971 | kmap_trie_escBrack->c = '['; | |
972 | kmap_trie_escBrack->next = kmap_trie_escO; | |
973 | ||
974 | kmap_trie_escO->c = 'O'; | |
6fb96a3f | 975 | |
feef2cb5 | 976 | /* First bind built-in default bindings. They may be shadowed by |
977 | the termcap entries that get bound later. */ | |
6fb96a3f | 978 | for (curr = keymap; curr->code; curr++) { |
feef2cb5 | 979 | if (curr->str) |
980 | newtBindKey(curr->str,curr->code); | |
6fb96a3f | 981 | } |
982 | ||
feef2cb5 | 983 | /* Then bind strings from termcap entries */ |
984 | for (curr = keymap; curr->code; curr++) { | |
985 | if (curr->tc) { | |
986 | char *pc = SLtt_tgetstr(curr->tc); | |
987 | if (pc) { | |
988 | newtBindKey(pc,curr->code); | |
989 | } | |
990 | } | |
991 | } | |
6fb96a3f | 992 | |
feef2cb5 | 993 | /* Finally, invent lowest-priority keybindings that correspond to |
994 | searching for esc-O-foo if esc-[-foo was not found and vice | |
995 | versa. That is needed because of strong confusion among | |
996 | different emulators of VTxxx terminals; some terminfo/termcap | |
997 | descriptions are apparently written by people who were not | |
998 | aware of the differences between "applicataion" and "terminal" | |
999 | keypad modes. Or perhaps they were, but tried to make their | |
1000 | description work with a program that puts the keyboard in the | |
1001 | wrong emulation mode. In short, one needs this: */ | |
136c3059 ML |
1002 | kmap_trie_fallback(kmap_trie_escO->contseq, &kmap_trie_escBrack->contseq); |
1003 | kmap_trie_fallback(kmap_trie_escBrack->contseq, &kmap_trie_escO->contseq); | |
1004 | } | |
1005 | ||
1006 | static void free_keys(struct kmap_trie_entry *kmap, struct kmap_trie_entry *parent, int prepare) { | |
1007 | if (kmap == NULL) | |
1008 | return; | |
1009 | ||
1010 | free_keys(kmap->contseq, kmap, prepare); | |
1011 | free_keys(kmap->next, kmap, prepare); | |
1012 | ||
1013 | if (!kmap->alloced && kmap - parent == 1) | |
1014 | return; | |
1015 | ||
1016 | /* find first element in array */ | |
1017 | while (!kmap->alloced) | |
1018 | kmap--; | |
1019 | ||
1020 | kmap->alloced += prepare ? 1 : -1; | |
1021 | if (!prepare && kmap->alloced == 1) | |
1022 | free(kmap); | |
1023 | } | |
1024 | ||
1025 | static void freeKeymap() { | |
1026 | free_keys(kmap_trie_root, NULL, 1); | |
1027 | free_keys(kmap_trie_root, NULL, 0); | |
1028 | kmap_trie_root = NULL; | |
6fb96a3f | 1029 | } |
6fb96a3f | 1030 | |
3eec7ce4 | 1031 | /** |
1032 | * @brief Delay for a specified number of usecs | |
1033 | * @param int - number of usecs to wait for. | |
1034 | */ | |
feef2cb5 | 1035 | void newtDelay(unsigned int usecs) { |
236ed30e | 1036 | usleep(usecs); |
6fb96a3f | 1037 | } |
8735cc88 | 1038 | |
45c366b1 | 1039 | struct eventResult newtDefaultEventHandler(newtComponent c, |
6f481af2 | 1040 | struct event ev) { |
8735cc88 | 1041 | struct eventResult er; |
1042 | ||
1043 | er.result = ER_IGNORED; | |
1044 | return er; | |
1045 | } | |
81361f3e | 1046 | |
7d4604a9 | 1047 | void newtRedrawHelpLine(void) { |
81361f3e | 1048 | char * buf; |
1049 | ||
1050 | SLsmg_set_color(NEWT_COLORSET_HELPLINE); | |
45f6c4fd | 1051 | |
22cc0d5e | 1052 | if (currentHelpline) { |
6f481af2 | 1053 | /* buffer size needs to be wide enough to hold all the multibyte |
1054 | currentHelpline + all the single byte ' ' to fill the line */ | |
1055 | int wlen = wstrlen(*currentHelpline, -1); | |
1056 | int len; | |
1057 | ||
1058 | if (wlen > SLtt_Screen_Cols) | |
1059 | wlen = SLtt_Screen_Cols; | |
1060 | len = strlen(*currentHelpline) + (SLtt_Screen_Cols - wlen); | |
1061 | buf = alloca(len + 1); | |
1062 | memset(buf, ' ', len); | |
1063 | memcpy(buf, *currentHelpline, strlen(*currentHelpline)); | |
1064 | buf[len] = '\0'; | |
ce11acc8 | 1065 | } else { |
6f481af2 | 1066 | buf = alloca(SLtt_Screen_Cols + 1); |
1067 | memset(buf, ' ', SLtt_Screen_Cols); | |
1068 | buf[SLtt_Screen_Cols] = '\0'; | |
22cc0d5e | 1069 | } |
81361f3e | 1070 | SLsmg_gotorc(SLtt_Screen_Rows - 1, 0); |
10de8f4a | 1071 | SLsmg_write_string(buf); |
b6c968d2 | 1072 | SLsmg_gotorc(cursorRow, cursorCol); |
81361f3e | 1073 | } |
1074 | ||
d4109c37 | 1075 | void newtPushHelpLine(const char * text) { |
a753da93 | 1076 | if (currentHelpline && currentHelpline - helplineStack + 1 |
1077 | >= sizeof (helplineStack) / sizeof (char *)) | |
1078 | return; | |
1079 | ||
7d4604a9 | 1080 | if (!text) |
6f481af2 | 1081 | text = defaultHelpLine; |
45f6c4fd | 1082 | |
81361f3e | 1083 | if (currentHelpline) |
6f481af2 | 1084 | (*(++currentHelpline)) = strdup(text); |
81361f3e | 1085 | else { |
6f481af2 | 1086 | currentHelpline = helplineStack; |
1087 | *currentHelpline = strdup(text); | |
81361f3e | 1088 | } |
1089 | ||
7d4604a9 | 1090 | newtRedrawHelpLine(); |
81361f3e | 1091 | } |
1092 | ||
1093 | void newtPopHelpLine(void) { | |
1094 | if (!currentHelpline) return; | |
1095 | ||
1096 | free(*currentHelpline); | |
1097 | if (currentHelpline == helplineStack) | |
6f481af2 | 1098 | currentHelpline = NULL; |
81361f3e | 1099 | else |
6f481af2 | 1100 | currentHelpline--; |
81361f3e | 1101 | |
7d4604a9 | 1102 | newtRedrawHelpLine(); |
81361f3e | 1103 | } |
1104 | ||
39280c3a | 1105 | void newtDrawRootText(int col, int row, const char * text) { |
81361f3e | 1106 | SLsmg_set_color(NEWT_COLORSET_ROOTTEXT); |
7d4604a9 | 1107 | |
1108 | if (col < 0) { | |
6f481af2 | 1109 | col = SLtt_Screen_Cols + col; |
7d4604a9 | 1110 | } |
1111 | ||
1112 | if (row < 0) { | |
6f481af2 | 1113 | row = SLtt_Screen_Rows + row; |
7d4604a9 | 1114 | } |
45f6c4fd | 1115 | |
81361f3e | 1116 | SLsmg_gotorc(row, col); |
10de8f4a | 1117 | SLsmg_write_string((char *)text); |
81361f3e | 1118 | } |
a1f11019 | 1119 | |
1120 | int newtSetFlags(int oldFlags, int newFlags, enum newtFlagsSense sense) { | |
1121 | switch (sense) { | |
1122 | case NEWT_FLAGS_SET: | |
6f481af2 | 1123 | return oldFlags | newFlags; |
a1f11019 | 1124 | |
1125 | case NEWT_FLAGS_RESET: | |
6f481af2 | 1126 | return oldFlags & (~newFlags); |
a1f11019 | 1127 | |
69bf2308 | 1128 | case NEWT_FLAGS_TOGGLE: |
6f481af2 | 1129 | return oldFlags ^ newFlags; |
69bf2308 | 1130 | |
a1f11019 | 1131 | default: |
6f481af2 | 1132 | return oldFlags; |
a1f11019 | 1133 | } |
1134 | } | |
69bf2308 | 1135 | |
1136 | void newtBell(void) | |
1137 | { | |
721584c3 | 1138 | SLtt_beep(); |
1139 | } | |
1140 | ||
1141 | void newtGetScreenSize(int * cols, int * rows) { | |
1142 | if (rows) *rows = SLtt_Screen_Rows; | |
1143 | if (cols) *cols = SLtt_Screen_Cols; | |
69bf2308 | 1144 | } |
8f52cd47 | 1145 | |
1146 | void newtDefaultPlaceHandler(newtComponent c, int newLeft, int newTop) { | |
1147 | c->left = newLeft; | |
1148 | c->top = newTop; | |
1149 | } | |
1150 | ||
1151 | void newtDefaultMappedHandler(newtComponent c, int isMapped) { | |
1152 | c->isMapped = isMapped; | |
1153 | } | |
23efd09b | 1154 | |
1155 | void newtCursorOff(void) { | |
5e171db1 | 1156 | cursorOn = 0; |
1157 | SLtt_set_cursor_visibility (cursorOn); | |
23efd09b | 1158 | } |
1159 | ||
1160 | void newtCursorOn(void) { | |
5e171db1 | 1161 | cursorOn = 1; |
1162 | SLtt_set_cursor_visibility (cursorOn); | |
23efd09b | 1163 | } |
7ff5fd71 | 1164 | |
1165 | void newtTrashScreen(void) { | |
1166 | if (trashScreen) | |
5baf7e4b | 1167 | SLsmg_touch_lines(0, SLtt_Screen_Rows); |
7ff5fd71 | 1168 | } |
1169 | ||
c397bfc8 DW |
1170 | void newtComponentGetPosition(newtComponent co, int * left, int * top) { |
1171 | if (left) *left = co->left; | |
1172 | if (top) *top = co->top; | |
1173 | } | |
1174 | ||
1175 | void newtComponentGetSize(newtComponent co, int * width, int * height) { | |
1176 | if (width) *width = co->width; | |
1177 | if (height) *height = co->height; | |
1178 | } |