C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
ui_ncurses.c
Go to the documentation of this file.
1/** @file ui_ncurses.c
2 @ingroup ui_ncurses
3 @brief NCurses UI backend — lifecycle, surface management, and capabilities.
4
5 Implements all UiRuntime and UiSurface operations declared in ui_backend.h
6 using the NCurses / panelw library.
7
8 When compiled as part of the main C-Menu build (UAL_LEGACY_COMPAT defined),
9 the legacy globals @c screen and @c tty_fp from dwin.c are kept in sync so
10 that code not yet migrated to the UAL API continues to work.
11*/
12
13#define _XOPEN_SOURCE_EXTENDED 1
14
15#include "cm.h"
16
18#ifdef UAL_LEGACY_COMPAT
19#include "ui_ncurses_compat.h"
20#endif
21#include <locale.h>
22#include <stdint.h>
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26
27UiRuntime *ui = NULL;
29
30int win_ptr = -1;
31int sfc_ptr = -1;
32
33uint ui_color_cnt = 0;
34uint ui_pair_cnt = 0;
35
36UiSurface *stdsfc;
37
38/** BOX WIDE UNICODE CODEPOINTS */
39
40wchar_t *border_single = L"─│├┤┬┴┼┌┐└┘";
41wchar_t *border_rounded = L"─│├┤┬┴┼╭╮╰╯";
42wchar_t *border_double = L"═║╠╣╦╩╬╔╗╚╝";
43wchar_t *border_heavy = L"━┃┣┫┳┻╋┏┓┗┛";
44wchar_t *border_none = L" ";
45
46BorderWide bw;
47
48const wchar_t *bw_rtl = L"\x256d"; /**< rounded top left */
49const wchar_t *bw_rtr = L"\x256e"; /**< rounded top right */
50const wchar_t *bw_rbl = L"\x2570"; /**< rounded bottom left */
51const wchar_t *bw_rbr = L"\x256f"; /**< rounded bottom right */
52const wchar_t *bw_sp = L"\x20"; /**< space */
53const wchar_t *bw_ra = L"\x2192"; /**< large right arrow */
54const wchar_t *bw_la = L"\x2190"; /**< large left arrow */
55const wchar_t *bw_ua = L"\x2191"; /**< large up arrow */
56const wchar_t *bw_da = L"\x2193"; /**< large down arrow */
57const wchar_t *bw_ran = L"\x276F"; /**< right_angle */
58const wchar_t *bw_lan = L"\x276E"; /**< left_angle */
59const wchar_t *bw_chk = L"\x2611"; /**< left_angle */
60const wchar_t *bw_h09 = L"\x23BD"; /**< horizontal line 9 */
61
62STDRGB std_color[] = {
63 {0, 0, 0},
64 {128, 0, 0},
65 {0, 128, 0},
66 {128, 128, 0},
67 {0, 0, 128},
68 {128, 0, 128},
69 {0, 128, 128},
70 {192, 192, 192},
71 {128, 128, 128},
72 {255, 0, 0},
73 {0, 255, 0},
74 {255, 255, 0},
75 {0, 0, 255},
76 {255, 0, 255},
77 {0, 255, 255},
78 {255, 255, 255}};
79
80/* -------------------------------------------------------------------------
81 Backend identification and capability query
82 ------------------------------------------------------------------------- */
83
84UiBackend ui_get_backend() {
85 return UI_BACKEND_NCURSES;
86}
87
88void ui_get_caps(UiCaps *caps) {
89 if (!caps)
90 return;
91 memset(caps, 0, sizeof(*caps));
92 if (!ui)
93 return;
94 // Will add code to actually check later. For now, just lie.
95 caps->truecolor = true;
96 caps->palette256 = true;
98 caps->unicode = true;
99 caps->resize = true;
100 caps->color_pairs = 0;
101}
102/* -------------------------------------------------------------------------
103 Colors, Color Pairs
104 ------------------------------------------------------------------------- */
105uint ui_add_pair(uint fg, uint bg) {
106 int rc;
107 uint i;
108 uint pfg, pbg;
109 for (i = 1; i < ui_pair_cnt; i++) {
110 ui_pair_content(i, &pfg, &pbg);
111 if (pfg == fg && pbg == bg)
112 return i;
113 }
114 if (i + 1 >= UI_PAIRS) {
115 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 1);
116 ssnprintf(em1, MAXLEN - 1, "ui_add_pair failed for pair: %d", i);
117 strerror_r(errno, em2, MAXLEN);
119 return (EXIT_FAILURE);
120 }
121 rc = init_extended_pair(i, fg, bg);
122 if (rc == ERR) {
123 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 1);
124 ssnprintf(em1, MAXLEN - 1, "init_extended_pair failed for pair: %d", i);
125 ssnprintf(em2, MAXLEN - 1, "fg: %d, bg: %d, ui_pair_cnt: %d", fg, bg, ui_pair_cnt);
127 return (EXIT_FAILURE);
128 }
129 ui_pair_cnt++;
130 return (int)(ui_pair_cnt - 1);
131}
132int ui_chg_pair(uint pair, uint fg, uint bg) {
133 if (pair + 1 >= UI_PAIRS)
134 return -1;
135 init_extended_pair(pair, fg, bg);
136 return 0;
137}
138int ui_add_color_rgb(RGB *rgb) {
139 uint i;
140 RGB tmp;
141 apply_gamma(rgb);
142 rgb->r = (rgb->r * 1000) / 255;
143 rgb->g = (rgb->g * 1000) / 255;
144 rgb->b = (rgb->b * 1000) / 255;
145 rgb->a = 0;
146 for (i = 0; i < ui_color_cnt && i < UI_COLORS; i++) {
147 extended_color_content(i, &tmp.r, &tmp.g, &tmp.b);
148 if (rgb->r == tmp.r && rgb->g == tmp.g && rgb->b == tmp.b)
149 return i;
150 }
151 if (i < UI_COLORS) {
152 if (i < 16) {
153 std_color[i].r = rgb->r;
154 std_color[i].g = rgb->g;
155 std_color[i].b = rgb->b;
156 }
157 init_extended_color(i, rgb->r, rgb->g, rgb->b);
158 if (ui_color_cnt + 1 < UI_COLORS)
159 ui_color_cnt++;
160 return ui_color_cnt - 1;
161 }
162 return 0;
163}
164uint32_t ui_get_color(uint16_t color_idx) {
165 if (color_idx + 1 >= UI_COLORS)
166 return -1;
167 RGB rgb;
168 extended_color_content(color_idx, &rgb.r, &rgb.g, &rgb.b);
169 rgb.r = (rgb.r * 255) / 1000;
170 rgb.g = (rgb.g * 255) / 1000;
171 rgb.b = (rgb.b * 255) / 1000;
172 return 0;
173}
174RGB ui_hex_to_rgb(char *s) {
175 RGB rgb;
176 sscanf(s, "#%02x%02x%02x", &rgb.r, &rgb.g, &rgb.b);
177 return rgb;
178}
179int ui_color_content(uint color, uint *r, uint *g, uint *b) {
180 int _color = (int)color;
181 int _r, _g, _b;
182 extended_color_content(_color, &_r, &_g, &_b);
183 *r = (uint)_r;
184 *g = (uint)_g;
185 *b = (uint)_b;
186 return 0;
187}
188
189int ui_init_color(uint color, uint r, uint g, uint b) {
190 init_extended_color(color, r, g, b);
191 return 0;
192}
193
194int ui_pair_content(uint pair, uint *fg, uint *bg) {
195 int _pair = (int)pair;
196 int _fg, _bg;
197 extended_pair_content(_pair, &_fg, &_bg);
198 *fg = (uint)_fg;
199 *bg = (uint)_bg;
200 return 0;
201}
202int ui_init_pair(uint pair, uint fg, uint bg) {
203 init_extended_pair(pair, fg, bg);
204 return 0;
205}
206int ui_chg_color(uint16_t color_idx, uint32_t *color) {
207 if (color_idx + 1 >= UI_COLORS)
208 return -1;
209 RGB rgb;
210 rgb.r = (*color >> 16) & 0xff;
211 rgb.g = (*color >> 8) & 0xff;
212 rgb.b = *color & 0xff;
213 apply_gamma(&rgb);
214 rgb.r = (rgb.r * 1000) / 255;
215 rgb.g = (rgb.g * 1000) / 255;
216 rgb.b = (rgb.b * 1000) / 255;
217 if (color_idx < 16) {
218 std_color[color_idx].r = rgb.r;
219 std_color[color_idx].g = rgb.g;
220 std_color[color_idx].b = rgb.b;
221 }
222 init_extended_color(color_idx, rgb.r, rgb.g, rgb.b);
223 return 0;
224}
225
226/* -------------------------------------------------------------------------
227 Styles
228 ------------------------------------------------------------------------- */
229
230int ui_pair_from_hex(const char *fg, const char *bg) {
231 RGB rgb;
232 sscanf(fg, "#%02x%02x%02x", &rgb.r, &rgb.g, &rgb.b);
233 int f_idx = ui_add_color_rgb(&rgb);
234 sscanf(bg, "#%02x%02x%02x", &rgb.r, &rgb.g, &rgb.b);
235 int b_idx = ui_add_color_rgb(&rgb);
236 return ui_add_pair(f_idx, b_idx);
237}
238
239UiCell ui_cell_from_ucp(const wchar_t *ucp, const uint32_t *fg, const uint32_t *bg) {
240 UiCell cc = {0};
241 RGB rgb;
242 rgb.r = (*fg >> 16) & 0xff;
243 rgb.g = (*fg >> 8) & 0xff;
244 rgb.b = *fg & 0xff;
245 int f_idx = ui_add_color_rgb(&rgb);
246 rgb.r = (*bg >> 16) & 0xff;
247 rgb.g = (*bg >> 8) & 0xff;
248 rgb.b = *bg & 0xff;
249 int b_idx = ui_add_color_rgb(&rgb);
250 short cp = ui_add_pair(f_idx, b_idx);
251 wchar_t wstr[2] = {L'\0', L'\0'};
252 wstr[0] = *ucp;
253 wstr[1] = L'\0';
254 setcchar(&cc, wstr, WA_NORMAL, cp, nullptr);
255 return cc;
256}
257
258/* -------------------------------------------------------------------------
259 Lifecycle
260 ------------------------------------------------------------------------- */
261struct UiRuntime *ui_init(const UiConfig *cfg) {
262 setlocale(LC_ALL, "");
263 ui = calloc(1, sizeof(*ui));
264 if (!ui)
265 return NULL;
266 char tty_name[MAXLEN];
267 if (cfg && cfg->tty_path) {
268 strncpy(tty_name, cfg->tty_path, sizeof(tty_name) - 1);
269 tty_name[sizeof(tty_name) - 1] = '\0';
270 } else {
271 if (ttyname_r(STDERR_FILENO, tty_name, sizeof(tty_name)) != 0) {
272 free(ui);
273 return NULL;
274 }
275 }
276 ui->tty_fp = fopen(tty_name, "r+");
277 if (!ui->tty_fp) {
278 free(ui);
279 return NULL;
280 }
281 ui->screen = newterm(NULL, ui->tty_fp, ui->tty_fp);
282 if (!ui->screen) {
283 fclose(ui->tty_fp);
284 free(ui);
285 return NULL;
286 }
287 set_term(ui->screen);
288 f_curses_open = true;
289 if (!has_colors() || !can_change_color()) {
291 return NULL;
292 }
293 start_color();
294 use_default_colors();
295 cbreak();
296 noecho();
297 keypad(stdscr, TRUE);
298 if (cfg) {
303 } else {
304 ui->cursor_visible = false;
305 ui->alt_screen = false;
306 }
308 mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);
309 getmaxyx(stdscr, ui->lines, ui->cols);
310 if (cfg) {
311 if (ui->border_style == 'r' || ui->border_style == 'R') {
312 memcpy(bw.str, border_rounded, sizeof(bw.str));
313 } else if (ui->border_style == 's' || ui->border_style == 'S') {
314 memcpy(bw.str, border_single, sizeof(bw.str));
315 } else if (ui->border_style == 'd' || ui->border_style == 'D') {
316 memcpy(bw.str, border_double, sizeof(bw.str));
317 } else if (ui->border_style == 'h' || ui->border_style == 'H') {
318 memcpy(bw.str, border_heavy, sizeof(bw.str));
319 } else if (ui->border_style == 'n' || ui->border_style == 'N') {
320 memcpy(bw.str, border_none, sizeof(bw.str));
321 }
322 }
323 stdsfc = calloc(1, sizeof(*stdsfc));
324 if (!stdsfc)
325 return NULL;
327 stdsfc->parent = NULL;
330 stdsfc->meta[BOX].y = 0;
331 stdsfc->meta[BOX].x = 0;
332 stdsfc->mwin[BOX] = stdscr;
333 stdsfc->mpan[BOX] = new_panel(stdsfc->mwin[BOX]);
334 if (!stdsfc->mpan[BOX]) {
335 free(stdsfc);
336 Perror("new_panel failed for stdsfc->mpan[BOX]");
337 exit(EXIT_FAILURE);
338 }
339 return ui;
340}
341void ui_endwin() {
343}
345 if (ui == NULL)
346 return;
347 for (int i = sfc_ptr; i >= 0; i--) {
348 if (ui_surface[i] != NULL) {
350 ui_surface[i] = NULL;
351 }
352 }
353 if (stdsfc->mpan[0] != NULL) {
354 hide_panel(stdsfc->mpan[0]);
355 del_panel(stdsfc->mpan[0]);
356 stdsfc->mpan[0] = NULL;
357 }
358 f_curses_open = false;
359 endwin();
360 if (ui->screen != NULL) {
361 delscreen(ui->screen);
362 ui->screen = NULL;
363 }
364 if (ui->tty_fp != NULL) {
365 fclose(ui->tty_fp);
366 ui->tty_fp = NULL;
367 }
368 if (stdsfc != NULL) {
369 free(stdsfc);
370 stdsfc = NULL;
371 }
372 if (ui != NULL) {
373 free(ui);
374 ui = NULL;
375 }
376}
377void ui_surface_destroy(UiSurface *s) {
378 if (!s)
379 return;
380 for (int i = SUB_SFC_MAX; i >= 0; i--) {
381 if (s->mpan[i] != NULL) {
382 hide_panel(s->mpan[i]);
383 del_panel(s->mpan[i]);
384 s->mpan[i] = NULL;
385 }
386 }
387 for (int i = SUB_SFC_MAX; i >= 0; i--) {
388 if (s->mwin[i] != NULL) {
389 delwin(s->mwin[i]);
390 s->mwin[i] = NULL;
391 }
392 }
393 if (s != NULL) {
394 free(s);
395 s = NULL;
396 }
397}
399 def_prog_mode();
400 endwin();
401 return 0;
402}
404 reset_prog_mode();
405 update_panels();
406 doupdate();
407 return 0;
408}
409
410/* -------------------------------------------------------------------------
411 Surface Creation and Destruction
412 ------------------------------------------------------------------------- */
413
414UiSurface *ui_surface_new(uint w, UiSurface *parent, uint p, uint lines, uint cols, uint y, uint x) {
415 if (!ui)
416 return NULL;
417 UiSurface *s = calloc(1, sizeof(*s));
418 if (!s)
419 return NULL;
420 for (int i = 0; i < SUB_SFC_MAX; i++) {
421 s->mwin[i] = NULL;
422 s->mpan[i] = NULL;
423 }
424 s->runtime = ui;
425 s->parent = parent;
426 s->meta[w].lines = lines;
427 s->meta[w].cols = cols;
428 s->meta[w].y = y;
429 s->meta[w].x = x;
430
431 if (parent && parent->mwin[p]) {
432 s->mwin[w] = derwin(parent->mwin[p], lines, cols, y, x);
433 if (!s->mwin[w]) {
434 free(s);
435 return NULL;
436 }
437 } else {
438 s->mwin[w] = newwin(lines, cols, y, x);
439 if (!s->mwin[w]) {
440 free(s);
441 return NULL;
442 }
443 s->mpan[w] = new_panel(s->mwin[w]);
444 if (!s->mpan[w]) {
445 delwin(s->mwin[w]);
446 free(s);
447 return NULL;
448 }
449 }
450 return s;
451}
452
453UiSurface *ui_box_surface_new(UiSurface *parent, uint p, uint lines, uint cols, uint y, uint x, char *wtitle) {
454 UiSurface *s = calloc(1, sizeof(*s));
455 if (!s)
456 return NULL;
457 s->runtime = ui;
458 s->parent = parent;
459 s->meta[BOX].y = y;
460 s->meta[BOX].x = x;
461 s->meta[BOX].lines = lines;
462 s->meta[BOX].cols = cols;
463 if (parent && parent->mwin[p]) {
464 s->mwin[BOX] = derwin(parent->mwin[p], lines + 2, cols + 2, y, x);
465 if (!s->mwin[BOX]) {
466 free(s);
467 return NULL;
468 }
469 } else {
470 s->mwin[BOX] = newwin(lines + 2, cols + 2, y, x);
471 if (!s->mwin[BOX]) {
472 free(s);
473 return NULL;
474 }
475 s->mpan[BOX] = new_panel(s->mwin[BOX]);
476 if (!s->mpan[BOX]) {
477 delwin(s->mwin[BOX]);
478 return NULL;
479 }
480 }
481 ui_scrollok(s, BOX, false);
483 border_title(s, wtitle);
484#ifdef DEBUG_UI
485 immedok(s->mwin[BOX], true);
486#endif
487 return s;
488}
489
490void fast_exit(UiSurface *s) {
491 update_panels();
492 doupdate();
493 for (int i = SUB_SFC_MAX; i >= 0; i--) {
494 if (s->mpan[i]) {
495 hide_panel(s->mpan[i]);
496 del_panel(s->mpan[i]);
497 s->mpan[i] = NULL;
498 }
499 }
500 for (int i = SUB_SFC_MAX; i >= 0; i--) {
501 if (s->mwin[i]) {
502 delwin(s->mwin[i]);
503 s->mwin[i] = NULL;
504 }
505 }
506 endwin();
507 exit(EXIT_SUCCESS);
508}
509int ui_surface_addpad(UiSurface *s, uint w, uint view_win, uint lines, uint cols) {
510 s->mwin[w] = newpad(lines, cols);
511 if (s->mwin[w] == nullptr)
512 return -1;
513 s->mwin[view_win] = subpad(s->mwin[PAD], lines, cols, 0, 0);
514 if (s->mwin[view_win] == nullptr)
515 return -1;
516 s->mpan[w] = new_panel(s->mwin[view_win]);
517 immedok(s->mwin[w], true);
518#ifdef DEBUG_UI
519#endif
520 return 0;
521}
522
523int ui_surface_addwin(UiSurface *s, uint w, uint p, uint lines, uint cols, uint y, uint x) {
524 s->mwin[w] = derwin(s->mwin[p], lines, cols, y, x);
525 if (!s->mwin[w]) {
526 free(s);
527 return -1;
528 }
529 s->mpan[w] = new_panel(s->mwin[w]);
530 keypad(s->mwin[w], true);
533 immedok(s->mwin[w], true);
534#ifdef DEBUG_UI
535#endif
536 return 0;
537}
538// -------------------------------------------------------------------------
539// Surface Management
540// -------------------------------------------------------------------------
541
542int ui_surface_move(UiSurface *s, uint w, uint y, uint x) {
543 if (!s)
544 return -1;
545 s->meta[w].y = y;
546 s->meta[w].x = x;
547 return move_panel(s->mpan[w], y, x);
548}
549
550int ui_surface_resize(UiSurface *s, uint w, uint lines, uint cols) {
551 if (!s)
552 return -1;
553 s->meta[w].lines = lines;
554 s->meta[w].cols = cols;
555 wresize(s->mwin[w], lines + 2, cols + 2);
556 wresize(s->mwin[w + 1], lines, cols);
557 return 0;
558}
559
560int ui_werase(UiSurface *s, uint w) {
561 if (w == ALLWINS) {
562 for (int i = 1; i < SUB_SFC_MAX; i++) {
563 if (s->mwin[i]) {
564 werase(s->mwin[i]);
565 }
566 }
567 } else {
568 if (s->mwin[w]) {
569 werase(s->mwin[w]);
570 }
571 }
572 return 0;
573}
574int ui_wclear(UiSurface *s, uint w) {
575 if (!s)
576 return -1;
577 if (w == ALLWINS) {
578 for (int i = 1; i < SUB_SFC_MAX; i++) {
579 if (s->mwin[i]) {
580 wclear(s->mwin[i]);
581 }
582 }
583 } else {
584 if (s->mwin[w]) {
585 wclear(s->mwin[w]);
586 }
587 }
588 return 0;
589}
590int ui_erase() {
591 erase();
592 return 0;
593}
594int ui_clear() {
595 clear();
596 return 0;
597}
598int ui_surface_show(UiSurface *s, uint w) {
599 if (!s)
600 return -1;
601 show_panel(s->mpan[w]);
602 s->meta[w].hidden = false;
603 return 0;
604 return 0;
605}
606
607int ui_top_panel(UiSurface *s, uint w) {
608 if (!s)
609 return -1;
610 top_panel(s->mpan[w]);
611 return 0;
612}
613
614int ui_surface_hide(UiSurface *s, uint w) {
615 if (!s)
616 return -1;
617 hide_panel(s->mpan[w]);
618 s->meta[w].hidden = true;
619 return 0;
620}
621
622// -------------------------------------------------------------------------
623// Controls and Settings
624// -------------------------------------------------------------------------
625
626int ui_scrollok(UiSurface *s, uint w, bool enable) {
627 if (!s->mwin[w])
628 return -1;
629 if (enable)
630 scrollok(s->mwin[w], true);
631 else
632 scrollok(s->mwin[w], false);
633 return 0;
634}
635int ui_keypad(UiSurface *s, uint w, bool enable) {
636 if (!s->mwin[w])
637 return -1;
638 if (enable)
639 keypad(s->mwin[w], true);
640 else
641 keypad(s->mwin[w], false);
642 return 0;
643}
644int ui_idlok(UiSurface *s, uint w, bool enable) {
645 if (!s->mwin[w])
646 return -1;
647 if (enable)
648 idlok(s->mwin[w], true);
649 else
650 idlok(s->mwin[w], false);
651 return 0;
652}
653int ui_idcok(UiSurface *s, uint w, bool enable) {
654 if (!s->mwin[w])
655 return -1;
656 if (enable)
657 idcok(s->mwin[w], true);
658 else
659 idcok(s->mwin[w], false);
660 return 0;
661}
662int ui_setscrreg(UiSurface *s, uint w, uint top, uint bottom) {
663 if (!s->mwin[w])
664 return -1;
665 wsetscrreg(s->mwin[w], top, bottom);
666 return 0;
667}
668void ui_getyx(UiSurface *s, uint w, uint *lines, uint *cols) {
669 if (!s->mwin[w])
670 return;
671 int _lines, _cols;
672 getyx(s->mwin[w], _lines, _cols);
673 *lines = (uint)(_lines);
674 *cols = (uint)(_cols);
675}
676void ui_getmaxyx(UiSurface *s, uint w, uint *lines, uint *cols) {
677 if (!s->mwin[w])
678 return;
679 getmaxyx(s->mwin[w], *lines, *cols);
680}
681int ui_getmaxy(UiSurface *s, uint w) {
682 if (!s->mwin[w])
683 return -1;
684 return (int)(getmaxy(s->mwin[w]));
685}
686int ui_getmaxx(UiSurface *s, uint w) {
687
688 if (!s->mwin[w])
689 return -1;
690 return (int)(getmaxx(s->mwin[w]));
691}
692void ui_get_screen_size(uint *lines, uint *cols) {
693 if (!ui)
694 return;
695 getmaxyx(stdscr, ui->lines, ui->cols);
696 if (lines)
697 *lines = ui->lines;
698 if (cols)
699 *cols = ui->cols;
700}
701// included for symetry with notcurses, which needs it to compensate
702// for cursor positioning bug
703int ui_cursor_enable_yx(UiSurface *s, uint w, uint y, uint x, bool visible) {
704 (void)s;
705 (void)w;
706 if (!ui)
707 return -1;
708 wmove(s->mwin[w], y, x);
709 ui->cursor_visible = visible;
710 curs_set(visible ? 1 : 0);
711 return 0;
712}
713int ui_cursor_enable(UiSurface *s, uint w, bool visible) {
714 (void)s;
715 (void)w;
716 if (!ui)
717 return -1;
718 ui->cursor_visible = visible;
719 curs_set(visible ? 1 : 0);
720 return 0;
721}
722
723// -------------------------------------------------------------------------
724// Screen Navigation
725// -------------------------------------------------------------------------
726
727int ui_cursor_move(UiSurface *s, uint w, uint y, uint x) {
728 if (!s || !s->mwin[w])
729 return -1;
730 return wmove(s->mwin[w], y, x);
731}
732int ui_wmove(UiSurface *s, uint w, uint y, uint x) {
733 if (!s || !s->mwin[w])
734 return -1;
735 return wmove(s->mwin[w], y, x);
736}
737int ui_curs_set(int visibility) {
738 curs_set(visibility);
739 return 0;
740}
741int ui_wscrl(UiSurface *s, uint w, uint n) {
742 if (!s->mwin[w])
743 return -1;
744 wscrl(s->mwin[w], n);
746 return 0;
747}
748// -------------------------------------------------------------------------
749// Background
750// -------------------------------------------------------------------------
751
752// for the entire window
753int ui_bkgd(UiSurface *s, uint w, const UiCell *cell) {
754 if (!s)
755 return -1;
756 wbkgrnd(s->mwin[w], cell);
757 return 0;
758}
759// for new content to be written to the window
760int ui_bkgdset(UiSurface *s, uint w, const UiCell *cell) {
761 if (!s)
762 return -1;
763 wbkgrndset(s->mwin[w], cell);
764 return 0;
765}
766// for the entire window
767int ui_bkgrnd(UiSurface *s, uint w, const UiCell *cell) {
768 if (!s->mwin[w])
769 return -1;
770 wbkgrnd(s->mwin[w], cell);
771 return 0;
772}
773// for new content to be written to the window
774int ui_bkgrndset(UiSurface *s, uint w, const UiCell *cell) {
775 if (!s->mwin[w])
776 return -1;
777 wbkgrndset(s->mwin[w], cell);
778 return 0;
779}
780/* -------------------------------------------------------------------------
781 Cell Manipulation
782 ------------------------------------------------------------------------- */
783
784int ui_getcchar(const UiCell *uc, wchar_t *wstr, attr_t *attrs, uint16_t *pair, void *opts) {
785 short p;
786 getcchar(uc, wstr, attrs, &p, opts);
787 pair = (uint16_t *)&p;
788 p = (short)(*pair); // Tell compiler to forget about it!
789 return 0;
790}
791
792int ui_setcchar(cchar_t *wch, const wchar_t *wc, const attr_t attrs, short pair, const void *opts) {
793 (void)opts;
794 return setcchar(wch, wc, attrs, pair, NULL);
795}
796/* -------------------------------------------------------------------------
797 Rendering
798 ------------------------------------------------------------------------- */
799
800void ui_render() {
801 update_panels();
802 doupdate();
803}
805 update_panels();
806}
808 doupdate();
809 return 0;
810}
811int ui_wnoutrefresh(UiSurface *s, uint w) {
812 if (!s)
813 return -1;
814 wnoutrefresh(s->mwin[w]);
815 return 0;
816}
817/* -------------------------------------------------------------------------
818 Non-portable escape-hatch getters (see ui_ncurses_compat.h)
819 ------------------------------------------------------------------------- */
820
822 if (!ui)
823 return NULL;
824 return ui->screen;
825}
826
827WINDOW *ui_ncurses_surface_get_win(const UiSurface *s, uint w) {
828 if (!s)
829 return NULL;
830 return s->mwin[w];
831}
832
833PANEL *ui_ncurses_surface_get_panel(const UiSurface *s, uint w) {
834 if (!s)
835 return NULL;
836 return s->mpan[w];
837}
bool f_curses_open
Definition sig.c:33
const wchar_t * bw_sp
Definition ui_ncurses.c:52
void ui_render()
Definition ui_ncurses.c:800
int ui_cursor_move(UiSurface *s, uint w, uint y, uint x)
Definition ui_ncurses.c:727
wchar_t * border_rounded
Definition ui_ncurses.c:41
UiRuntime * ui_init(const UiConfig *config)
Definition ui_ncurses.c:261
void ui_getyx(UiSurface *s, uint w, uint *lines, uint *cols)
Definition ui_ncurses.c:668
int ui_surface_hide(UiSurface *s, uint w)
Definition ui_ncurses.c:614
const wchar_t * bw_ran
Definition ui_ncurses.c:57
int ui_bkgdset(UiSurface *s, uint w, const UiCell *cell)
Definition ui_ncurses.c:760
UiSurface * ui_surface_new(uint w, UiSurface *parent, uint p, uint lines, uint cols, uint y, uint x)
Definition ui_ncurses.c:414
int ui_setscrreg(UiSurface *s, uint w, uint top, uint bottom)
Definition ui_ncurses.c:662
int ui_scrollok(UiSurface *s, uint w, bool enable)
Definition ui_ncurses.c:626
const wchar_t * bw_rbr
Definition ui_ncurses.c:51
int ui_add_color_rgb(RGB *rgb)
Definition ui_ncurses.c:138
const wchar_t * bw_ua
Definition ui_ncurses.c:55
int ui_wclear(UiSurface *s, uint w)
Definition ui_ncurses.c:574
const wchar_t * bw_chk
Definition ui_ncurses.c:59
BorderWide bw
Definition ui_ncurses.c:46
uint16_t attr_t
Definition ui_backend.h:256
int ui_bkgd(UiSurface *s, uint w, const UiCell *cell)
Definition ui_ncurses.c:753
#define UI_SFC_MAX
Definition ui_backend.h:24
const wchar_t * bw_rtl
Definition ui_ncurses.c:48
const wchar_t * bw_rtr
Definition ui_ncurses.c:49
const wchar_t * bw_lan
Definition ui_ncurses.c:58
#define UI_PAIRS
Definition ui_backend.h:40
int ui_suspend()
Definition ui_ncurses.c:398
void ui_surface_destroy(UiSurface *s)
Definition ui_ncurses.c:377
int ui_surface_move(UiSurface *s, uint w, uint y, uint x)
Definition ui_ncurses.c:542
int ui_idlok(UiSurface *s, uint w, bool enable)
Definition ui_ncurses.c:644
const wchar_t * bw_ra
Definition ui_ncurses.c:53
void ui_update_panels()
Definition ui_ncurses.c:804
#define ERR
Definition ui_backend.h:249
STDRGB std_color[]
Definition ui_ncurses.c:62
int ui_wmove(UiSurface *s, uint w, uint y, uint x)
Definition ui_ncurses.c:732
UiSurface * ui_surface[UI_SFC_MAX]
Definition ui_ncurses.c:28
const wchar_t * bw_h09
Definition ui_ncurses.c:60
uint32_t ui_get_color(uint16_t color_idx)
Definition ui_ncurses.c:164
int ui_werase(UiSurface *s, uint w)
Definition ui_ncurses.c:560
void ui_get_screen_size(uint *lines, uint *cols)
Definition ui_ncurses.c:692
void fast_exit(UiSurface *s)
Definition ui_ncurses.c:490
int ui_erase()
Definition ui_ncurses.c:590
UiRuntime * ui
RGB ui_hex_to_rgb(char *s)
Definition ui_ncurses.c:174
void ui_shutdown()
Definition ui_ncurses.c:344
int ui_wscrl(UiSurface *s, uint w, int rows)
int win_ptr
Definition ui_ncurses.c:30
UiSurface * stdsfc
Definition ui_ncurses.c:36
int sfc_ptr
Definition nckeys.c:47
UiCell ui_cell_from_ucp(const wchar_t *ucp, const uint32_t *fg, const uint32_t *bg)
Definition ui_ncurses.c:239
int ui_curs_set(int visibility)
Definition ui_ncurses.c:737
int ui_top_panel(UiSurface *s, uint w)
Definition ui_ncurses.c:607
int ui_resume()
Definition ui_ncurses.c:403
uint ui_pair_cnt
Definition ui_ncurses.c:34
int ui_wnoutrefresh(UiSurface *s, uint w)
Definition ui_ncurses.c:811
struct nccell UiCell
Definition ui_backend.h:250
int ui_surface_resize(UiSurface *s, uint w, uint lines, uint cols)
Definition ui_ncurses.c:550
const wchar_t * bw_la
Definition ui_ncurses.c:54
uint ui_color_cnt
Definition ui_ncurses.c:33
void ui_endwin()
Definition ui_ncurses.c:341
wchar_t * border_heavy
Definition ui_ncurses.c:43
int ui_surface_show(UiSurface *s, uint w)
Definition ui_ncurses.c:598
int ui_clear()
Definition ui_ncurses.c:594
UiSurface * ui_box_surface_new(UiSurface *parent, uint p, uint lines, uint cols, uint y, uint x, char *title)
Definition ui_ncurses.c:453
int ui_keypad(UiSurface *s, uint w, bool enable)
Definition ui_ncurses.c:635
int ui_cursor_enable(UiSurface *s, uint w, bool visible)
Disable (visible = false) or enable (visibile = true) the cursor at its current position on the surfa...
Definition ui_ncurses.c:713
const wchar_t * bw_da
Definition ui_ncurses.c:56
wchar_t * border_double
Definition ui_ncurses.c:42
int ui_idcok(UiSurface *s, uint w, bool enable)
Definition ui_ncurses.c:653
#define UI_COLORS
Definition ui_backend.h:39
void ui_get_caps(UiCaps *caps)
Query the capabilities of the active backend.
Definition ui_ncurses.c:88
int ui_doupdate()
Definition ui_ncurses.c:807
@ UI_BACKEND_NCURSES
Definition ui_backend.h:156
UiBackend ui_get_backend()
Return which backend is powering this runtime.
Definition ui_ncurses.c:84
int ui_surface_addpad(UiSurface *s, uint w, uint view_win, uint lines, uint cols)
Definition ui_ncurses.c:509
void ui_getmaxyx(UiSurface *s, uint w, uint *lines, uint *cols)
Definition ui_ncurses.c:676
const wchar_t * bw_rbl
Definition ui_ncurses.c:50
int ui_cursor_enable_yx(UiSurface *s, uint w, uint y, uint x, bool visible)
Disable (visible = false) or enable (visibile = true) the cursor at a specified position on the surfa...
Definition ui_ncurses.c:703
#define ALLWINS
Definition ui_backend.h:92
int ui_surface_addwin(UiSurface *s, uint w, uint p, uint lines, uint cols, uint y, uint x)
Definition ui_ncurses.c:523
int ui_chg_color(uint16_t color_idx, uint32_t *color)
Definition ui_ncurses.c:206
#define WA_NORMAL
PANEL * ui_ncurses_surface_get_panel(const UiSurface *s, uint w)
Return the raw NCurses PANEL* underlying a surface.
Definition ui_ncurses.c:833
int ui_chg_pair(uint pair, uint fg, uint bg)
Definition ui_ncurses.c:132
int ui_pair_content(uint pair, uint *fg, uint *bg)
Definition ui_ncurses.c:194
SCREEN * ui_ncurses_get_screen()
Definition ui_ncurses.c:821
int ui_getmaxx(UiSurface *s, uint w)
Definition ui_ncurses.c:686
int ui_bkgrndset(UiSurface *s, uint w, const UiCell *cell)
Definition ui_ncurses.c:774
int ui_init_color(uint color, uint r, uint g, uint b)
Definition ui_ncurses.c:189
int ui_init_pair(uint pair, uint fg, uint bg)
Definition ui_ncurses.c:202
uint ui_add_pair(uint fg, uint bg)
Definition ui_ncurses.c:105
int ui_getcchar(const UiCell *uc, wchar_t *wstr, attr_t *attrs, uint16_t *pair, void *opts)
Definition ui_ncurses.c:784
int ui_color_content(uint color, uint *r, uint *g, uint *b)
Definition ui_ncurses.c:179
int ui_pair_from_hex(const char *fg, const char *bg)
Definition ui_ncurses.c:230
int ui_getmaxy(UiSurface *s, uint w)
Definition ui_ncurses.c:681
int ui_bkgrnd(UiSurface *s, uint w, const UiCell *cell)
Definition ui_ncurses.c:767
wchar_t * border_single
Definition ui_ncurses.c:40
int ui_setcchar(cchar_t *wch, const wchar_t *wc, const attr_t attrs, short pair, const void *opts)
Definition ui_ncurses.c:792
wchar_t * border_none
Definition ui_ncurses.c:44
WINDOW * ui_ncurses_surface_get_win(const UiSurface *s, uint w)
Return the raw NCurses WINDOW* underlying a surface.
Definition ui_ncurses.c:827
#define TRUE
Definition iloan.c:19
#define MAXLEN
Definition curskeys.c:15
UiCell cell_nt
Definition dwin.c:94
char em1[MAXLEN]
Definition dwin.c:143
char em2[MAXLEN]
Definition dwin.c:144
int border_draw(UiSurface *sfc)
Definition dwin.c:581
void apply_gamma(RGB *rgb)
Apply gamma correction to RGB color.
Definition dwin.c:307
char em0[MAXLEN]
Definition dwin.c:142
int border_title(UiSurface *sfc, char *title)
Draw a box with a title around the specified window.
Definition dwin.c:676
int Perror(char *emsg_str)
Display a simple error message window or print to stderr.
Definition dwin.c:841
int display_error(char *msg0, char *msg1, char *msg2, char *msg3)
Display an error message window or print to stderr.
Definition dwin.c:778
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition futil.c:413
bool cursor_visible
Definition ui_backend.h:145
const char * tty_path
Definition ui_backend.h:147
bool enable_mouse
Definition ui_backend.h:143
char border_style
Definition ui_backend.h:146
bool enable_alt_screen
Definition ui_backend.h:144
bool palette256
Definition ui_backend.h:170
bool mouse
Definition ui_backend.h:171
int color_pairs
Definition ui_backend.h:174
bool truecolor
Definition ui_backend.h:169
bool unicode
Definition ui_backend.h:172
bool resize
Definition ui_backend.h:173
wchar_t str[11]
Definition ui_backend.h:185
uint8_t g
Definition ui_backend.h:261
uint8_t r
Definition ui_backend.h:260
uint8_t b
Definition ui_backend.h:262
Runtime state for the NotCurses backend.
unsigned int cols
unsigned int lines
struct UiSurface * parent
struct UiRuntime * runtime
struct UiSurfaceMeta meta[SUB_SFC_MAX]