2
3
4
5
6
7
8
9
10
11
13#define _XOPEN_SOURCE_EXTENDED 1
18#ifdef UAL_LEGACY_COMPAT
19#include "ui_ncurses_compat.h"
28
29
30
31
32
33
34
35
36
37
49
50
52
53
54
59
60
61
65 memset(caps, 0,
sizeof(*caps));
78
79
81
82
83
84
85
88 sscanf(fg,
"#%02x%02x%02x", &rgb.r, &rgb.g, &rgb.b);
90 sscanf(bg,
"#%02x%02x%02x", &rgb.r, &rgb.g, &rgb.b);
95
96
97
98
99
100
104 rgb.r = (*fg >> 16) & 0xff;
105 rgb.g = (*fg >> 8) & 0xff;
108 rgb.r = (*bg >> 16) & 0xff;
109 rgb.g = (*bg >> 8) & 0xff;
113 wchar_t wstr[2] = {L'\0', L'\0'};
116 setcchar(&cc, wstr,
WA_NORMAL, cp,
nullptr);
121
122
124
125
126
127
128
129struct UiRuntime *
ui_init(
const UiConfig *cfg, SIO *sio) {
130 setlocale(LC_ALL,
"en_US.UTF-8");
131 ui = calloc(1,
sizeof(*
ui));
135 if (ttyname_r(STDERR_FILENO, tty_name,
sizeof(tty_name)) != 0) {
139 ui->tty_fp = fopen(tty_name,
"r+");
144 ui->tty_fd = fileno(
ui->tty_fp);
147 ui_log(INFO,
_(
"ui_init: using tty: %s"), tty_name);
148 ui->screen = newterm(NULL,
ui->tty_fp,
ui->tty_fp);
155 set_term(
ui->screen);
156 if (!has_colors() || !can_change_color()) {
161 use_default_colors();
164 keypad(stdscr,
TRUE);
165 if (
ui->mouse_enabled)
166 mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);
167 getmaxyx(stdscr,
ui->lines,
ui->cols);
174 stdsfc->meta[BOX].lines = (
int)
ui->lines;
175 stdsfc->meta[BOX].cols = (
int)
ui->cols;
178 stdsfc->mwin[BOX] = stdscr;
182 ui_log(ERROR,
_(
"new_panel failed for stdsfc->mpan[BOX]"));
187 if (!
ui->border_style)
188 ui->border_style = UI_BORDER_ROUNDED;
190 switch (
ui->border_style) {
191 case UI_BORDER_SINGLE:
194 case UI_BORDER_DOUBLE:
197 case UI_BORDER_ROUNDED:
200 case UI_BORDER_HEAVY:
212 ui_log(INFO,
_(
"ui_init: stdsfc->mwin[BOX]: %p, stdsfc->mpan[BOX]: %p"), (
void *)
stdsfc->mwin[BOX], (
void *)
stdsfc->mpan[BOX]);
219
220
221
222
223
224
225
226
227
228
229UiSurface *
ui_surface_new(ss_t w, UiSurface *parent, uint p, uint lines, uint cols, uint y, uint x) {
234 if (lines > maxy || cols > maxx) {
242 UiSurface *s = calloc(1,
sizeof(*s));
251 s->meta[w].lines = lines;
252 s->meta[w].cols = cols;
256 if (parent && parent->mwin[p]) {
257 s->mwin[w] = derwin(parent->mwin[p], lines, cols, y, x);
263 s->mwin[w] = newwin(lines, cols, y, x);
268 s->mpan[w] = new_panel(s->mwin[w]);
278
279
280
281
282
283
284
285
286
287
288UiSurface *
ui_surface_box(UiSurface *parent, uint p, uint lines, uint cols, uint y, uint x,
const char *wtitle) {
293 if (lines > maxy || cols > maxx) {
300 UiSurface *s = calloc(1,
sizeof(*s));
307 s->meta[BOX].lines = lines;
308 s->meta[BOX].cols = cols;
309 if (parent && parent->mwin[p]) {
310 s->mwin[BOX] = derwin(parent->mwin[p], lines, cols, y, x);
316 s->mwin[BOX] = newwin(lines, cols, y, x);
321 s->mpan[BOX] = new_panel(s->mwin[BOX]);
323 delwin(s->mwin[BOX]);
331 immedok(s->mwin[BOX],
true);
336
337
338
344 hide_panel(s->mpan[i]);
345 del_panel(s->mpan[i]);
359
360
361
362
363
364
365
366
367
368
369int ui_surface_addpad(UiSurface *s, ss_t w, uint view_win, uint lines, uint cols, uint begy, uint begx) {
372 s->mwin[w] = newpad(lines, cols);
373 if (s->mwin[w] ==
nullptr)
375 s->mwin[view_win] = subpad(s->mwin[PAD], lines, cols, 0, 0);
376 if (s->mwin[view_win] ==
nullptr)
378 s->mpan[w] = new_panel(s->mwin[view_win]);
379 immedok(s->mwin[w],
true);
385
386
387
388
389
390
391
392
393
394
396 s->mwin[w] = derwin(s->mwin[p], lines, cols, y, x);
401 s->mpan[w] = new_panel(s->mwin[w]);
402 keypad(s->mwin[w],
true);
405 immedok(s->mwin[w],
true);
411
417
421 ui_log(INFO,
_(
"ui_shutdown in progress..."));
427 ui_log(INFO,
_(
"surface destroy: %d"),
sfc_ptr);
430 if (
stdsfc->mpan[0] != NULL) {
431 ui_log(INFO,
_(
"calling del_panel(stdsfc->mpan[BOX])"));
432 hide_panel(
stdsfc->mpan[0]);
433 del_panel(
stdsfc->mpan[0]);
436 ui_log(INFO,
_(
"calling endwin()"));
439 if (
ui->screen != NULL) {
440 ui_log(INFO,
_(
"calling delscreen(ui->screen)"));
441 delscreen(
ui->screen);
444 if (
ui->tty_fp != NULL) {
445 ui_log(INFO,
_(
"closing tty_fp"));
450 ui_log(INFO,
_(
"freeing stdsfc"));
459 ui_log(INFO,
_(
"freeing ui"));
465
466
467
472 if (s->mpan[i] != NULL) {
473 hide_panel(s->mpan[i]);
475 del_panel(s->mpan[i]);
480 if (s->mwin[i] != NULL) {
491
492
493
500
501
502
514
515
516
517
518
519
520
526 return move_panel(s->mpan[w], y, x);
529
530
531
532
533
534
535
539 s->meta[w].lines = lines;
540 s->meta[w].cols = cols;
541 wresize(s->mwin[w], lines + 2, cols + 2);
542 wresize(s->mwin[w + 1], lines, cols);
546
547
548
549
550
566
567
568
569
570
588
589
590
596
597
598
604
605
606
607
608
612 show_panel(s->mpan[w]);
613 s->meta[w].hidden =
false;
618
619
620
621
622
626 top_panel(s->mpan[w]);
630
631
632
633
634
638 hide_panel(s->mpan[w]);
639 s->meta[w].hidden =
true;
646
647
648
649
650
651
652
653int ui_wmove(UiSurface *s, ss_t w, uint y, uint x) {
654 if (!s || !s->mwin[w])
656 return wmove(s->mwin[w], y, x);
659
660
661
662
663
664
665
667 if (!s || !s->mwin[w])
669 return wmove(s->mwin[w], y, x);
675void ui_getyx(UiSurface *s, ss_t w, uint *lines, uint *cols) {
679 getyx(s->mwin[w], _lines, _cols);
680 *lines = (uint)(_lines);
681 *cols = (uint)(_cols);
684
685
686
687
688
689
693 getmaxyx(s->mwin[w], *lines, *cols);
696
697
698
699
700
704 return (
int)(getmaxy(s->mwin[w]));
707
708
709
710
711
715 return (
int)(getmaxx(s->mwin[w]));
718
719
720
721
725 getmaxyx(stdscr,
ui->lines,
ui->cols);
732
733
734
735
736
737
741 wscrl(s->mwin[w], n);
749
750
751
752
753
754
759 scrollok(s->mwin[w],
true);
761 scrollok(s->mwin[w],
false);
765
766
767
768
769
770
775 keypad(s->mwin[w],
true);
777 keypad(s->mwin[w],
false);
781
782
783
784
785
786
791 idlok(s->mwin[w],
true);
793 idlok(s->mwin[w],
false);
797
798
799
800
801
802
807 idcok(s->mwin[w],
true);
809 idcok(s->mwin[w],
false);
813
814
815
816
817
818
819
823 wsetscrreg(s->mwin[w], top, bottom);
833
834
835
836
837
838
839
841 curs_set(visibility);
847
848
849
850
851
852
853
854
858 wmove(s->mwin[w], y, x);
859 ui->cursor_visible = visible;
860 curs_set(visible ? 2 : 0);
864
865
866
867
868
869
875 ui->cursor_visible = visible;
876 curs_set(visible ? 1 : 0);
880
881
883
889
894
900
901
903
904
905
906
907
911 wnoutrefresh(s->mwin[w]);
921
922
923
924
925
926
927int ui_bkgd(UiSurface *s, ss_t w,
const UiCell *cell) {
930 wbkgrnd(s->mwin[w], cell);
935
936
937
938
939
940
944 wbkgrndset(s->mwin[w], cell);
949
950
951
952
953
954
955int ui_bkgrnd(UiSurface *s, ss_t w,
const UiCell *cell) {
958 wbkgrnd(s->mwin[w], cell);
963
964
965
966
967
968
972 wbkgrndset(s->mwin[w], cell);
976
977
979
980
981
982
983
984
985
986
987int ui_getcchar(
const UiCell *cell, wchar_t *wstr, attr_t *attrs,
short *pair,
const void *opts) {
989 getcchar(cell, wstr, attrs, pair,
nullptr);
993
994
995
996
997
998
999
1000
1001int ui_setcchar(UiCell *cell,
const wchar_t *wstr,
const attr_t attrs,
short pair,
const void *opts) {
1003 return setcchar(cell, wstr, attrs, pair, NULL);
1006
1007
1009
1010
1011
1012
1013
1020 if (pfg == fg && pbg == bg)
1028 return (EXIT_FAILURE);
1030 rc = init_extended_pair(i, fg, bg);
1036 return (EXIT_FAILURE);
1042
1043
1044
1045
1046
1047
1051 init_extended_pair(pair, fg, bg);
1056
1057
1058
1059
1061 if (rgb->r == rgb->g && rgb->g == rgb->b && rgb->b == 0)
1064 if (rgb->r > 255 || rgb->g > 255 || rgb->b > 255) {
1066 ui_log(ERROR,
"%s",
em0);
1068 ui_log(ERROR,
"%s",
em0);
1075 rgb->r = (rgb->r * 1000) / 255;
1076 rgb->g = (rgb->g * 1000) / 255;
1077 rgb->b = (rgb->b * 1000) / 255;
1079 extended_color_content(i, &tmp.r, &tmp.g, &tmp.b);
1080 if (rgb->r == tmp.r && rgb->g == tmp.g && rgb->b == tmp.b)
1089 init_extended_color(i, rgb->r, rgb->g, rgb->b);
1097
1098
1099
1100
1105 extended_color_content(color_idx, &rgb.r, &rgb.g, &rgb.b);
1106 rgb.r = (rgb.r * 255) / 1000;
1107 rgb.g = (rgb.g * 255) / 1000;
1108 rgb.b = (rgb.b * 255) / 1000;
1113 sscanf(s,
"#%02x%02x%02x", &rgb.r, &rgb.g, &rgb.b);
1117 int _color = (
int)color;
1119 extended_color_content(_color, &_r, &_g, &_b);
1126
1127
1128
1129
1130
1131
1132
1134 init_extended_color(color, r, g, b);
1138
1139
1140
1141
1142
1143
1145 int _pair = (
int)pair;
1147 extended_pair_content(_pair, &_fg, &_bg);
1153
1154
1155
1156
1157
1158
1160 init_extended_pair(pair, fg, bg);
1164
1165
1166
1167
1168
1173 rgb.r = (*color >> 16) & 0xff;
1174 rgb.g = (*color >> 8) & 0xff;
1175 rgb.b = *color & 0xff;
1177 if (color_idx < 16) {
1182 rgb.r = (rgb.r * 1000) / 255;
1183 rgb.g = (rgb.g * 1000) / 255;
1184 rgb.b = (rgb.b * 1000) / 255;
1185 init_extended_color(color_idx, rgb.r, rgb.g, rgb.b);
1189
1190
1192
1193
1194
1201
1202
1203
1210
1211
1212
1213
1214
1223uint
ui__mbstr_to_cellstr(UiCell *cmplx_buf,
const char *str,
const UiCell *cell_base, uint *p,
const uint atmost) {
1232 uint i = 0, len = 0;
1236 getcchar(cell_base, &wstr[0], &attrs, &cp,
nullptr);
1238 memset(&mbstate, 0,
sizeof(mbstate));
1239 if (pos && *pos >= atmost - 1)
1241 while (str[i] !=
'\0') {
1243 len = mbrtowc(wstr, s, MB_CUR_MAX, &mbstate);
1252 if (setcchar(&cc, wstr, attrs, cp,
nullptr) !=
ERR) {
1253 if (len > 0 && (*pos + len) < atmost)
1254 cmplx_buf[(*pos)++] = cc;
1260 setcchar(&cc, wstr, attrs, cp,
nullptr);
1261 cmplx_buf[*pos] = cc;
int ui_border_draw(UiSurface *sfc)
int ui_surface_resize(UiSurface *s, ss_t w, uint lines, uint cols)
Resize a UiSurface to new dimensions.
int ui_surface_addwin(UiSurface *s, ss_t w, uint p, uint lines, uint cols, uint y, uint x)
Add a new window to the specified UiSurface.
const wchar_t * border_none
UiRuntime * ui_init(const UiConfig *config, SIO *sio)
Initialize the UI runtime with the given configuration and SIO.
void ui_render()
Render the UI by updating panels and refreshing the display.
void ui_getyx(UiSurface *s, ss_t w, uint *lines, uint *cols)
Get the current cursor position within a window of a UI surface.
int ui_setscrreg(UiSurface *s, ss_t w, uint top, uint bottom)
Set the scrolling region for a UiSurface.
int ui_wmove(UiSurface *s, ss_t w, uint y, uint x)
Move the cursor to a specified position within a UiSurface.
void ui_getmaxyx(UiSurface *s, ss_t w, uint *lines, uint *cols)
Get the maximum dimensions of a UiSurface.
int ui_cursor_enable_yx(UiSurface *s, ss_t w, uint y, uint x, bool visible)
Enable or disable the cursor at a specific position within a UiSurface.
int ui_wscrl(UiSurface *s, ss_t w, int rows)
Scroll the contents of a UiSurface by a specified number of lines.
int ui_idcok(UiSurface *s, ss_t w, bool enable)
Enable or disable the use of the insert/delete character capabilities for a UiSurface.
int ui_surface_addpad(UiSurface *s, ss_t w, uint view_win, uint lines, uint cols, uint begy, uint begx)
Add a new pad to the specified UiSurface.
int ui_cursor_move(UiSurface *s, ss_t w, uint y, uint x)
Move the cursor to a specified position within a UiSurface.
int ui_suspend()
Suspend the UI, saving the current program state and ending the window session.
void ui_surface_destroy(UiSurface *s)
Destroy a UiSurface, cleaning up its windows and panels.
int ui_border_title(UiSurface *sfc, const char *title)
Draw a box with a title around the specified window.
void ui_update_panels()
Update the panels in the UI.
int ui_bkgd(UiSurface *s, ss_t w, const UiCell *cell)
Set the background of a specific window within a UiSurface.
int ui_idlok(UiSurface *s, ss_t w, bool enable)
Enable or disable the use of the insert/delete line capabilities for a UiSurface.
const wchar_t * border_double
int ui_surface_move(UiSurface *s, ss_t w, uint y, uint x)
Move a UiSurface to a new position on the screen.
int ui_getmaxy(UiSurface *s, ss_t w)
Get the maximum number of lines (rows) of a UiSurface.
UiSurface * ui_surface_box(UiSurface *parent, uint p, uint lines, uint cols, uint y, uint x, const char *title)
Create a new UI surface with a border box and optional title.
const wchar_t * border_single
void ui_get_screen_size(uint *lines, uint *cols)
Get the current screen size (number of lines and columns).
int ui_surface_show(UiSurface *s, ss_t w)
Show a UiSurface, making it visible on the screen.
int ui_erase()
Erase the entire screen.
void ui_shutdown()
Shutdown the UI runtime, cleaning up resources and freeing memory.
UiSurface * ui_surface_new(ss_t w, UiSurface *parent, uint p, uint lines, uint cols, uint y, uint x)
Create a new UI surface with the specified parameters.
void ui_initialize_sio(SIO *sio)
int ui_curs_set(int visibility)
Set the visibility of the cursor.
int ui_resume()
Resume the UI, restoring the previous program state and updating the display.
int ui_bkgrndset(UiSurface *s, ss_t w, const UiCell *cell)
Set the background for new content to be written to a specific window within a UiSurface.
int ui_top_surface(UiSurface *s, ss_t w)
Hide a UiSurface, making it invisible on the screen.
int ui_wclear(UiSurface *s, ss_t w)
Clear the contents of a UiSurface or all surfaces.
void ui_endwin()
End the UI application, cleaning up resources and shutting down the UI runtime.
int ui_cursor_enable(UiSurface *s, ss_t w, bool visible)
Enable or disable the cursor for a UiSurface.
int ui_clear()
Clear the entire screen.
int ui_getmaxx(UiSurface *s, ss_t w)
Get the maximum number of columns of a UiSurface.
const wchar_t * border_heavy
int ui_surface_hide(UiSurface *s, ss_t w)
Hide a UiSurface, making it invisible on the screen.
const wchar_t * border_rounded
int ui_bkgrnd(UiSurface *s, ss_t w, const UiCell *cell)
Set the background of a specific window within a UiSurface.
int ui_scrollok(UiSurface *s, ss_t w, bool enable)
Enable or disable scrolling for a UiSurface.
int ui_wnoutrefresh(UiSurface *s, ss_t w)
Refresh a specific window within a UiSurface.
void ui_get_caps(UiCaps *caps)
Get the UI backend capabilities.
int ui_bkgdset(UiSurface *s, ss_t w, const UiCell *cell)
Set the background for new content to be written to a specific window within a UiSurface.
int ui_doupdate()
Refresh the display by updating the screen.
int ui_werase(UiSurface *s, ss_t w)
Erase the contents of a UiSurface or all surfaces.
int ui_keypad(UiSurface *s, ss_t w, bool enable)
Enable or disable the keypad for a UiSurface.
UiLogLevel ui_min_log_level
void ui_apply_gamma(RGB *rgb)
Apply gamma correction to RGB color.
int ui_setcchar(UiCell *cell, const wchar_t *wstr, const attr_t attrs, short pair, const void *opts)
Set the character and attributes of a UiCell.
uint ui__mbstr_to_cellstr(UiCell *cmplx_buf, const char *str, const UiCell *cell_base, uint *p, const uint atmost)
int ui_chg_pair(uint pair, uint fg, uint bg)
Change the foreground and background colors of an existing color pair.
int ui_pair_content(uint pair, uint *fg, uint *bg)
Get the foreground and background colors of a specified color pair.
SCREEN * ui_ncurses_get_screen()
Get the current SCREEN pointer used by the UI.
int ui_getcchar(const UiCell *cell, wchar_t *wstr, attr_t *attrs, short *pair, const void *opts)
Get the character and attributes from a UiCell.
int ui_init_color(uint color, uint r, uint g, uint b)
Initialize a color in the curses color table with specified RGB values.
int ui_init_pair(uint pair, uint fg, uint bg)
Initialize a color pair in the curses color table with specified foreground and background colors.
uint ui_add_pair(uint fg, uint bg)
Add a new color pair to the UI, or retrieve the index of an existing pair.
UiSurface * ui_surface[UI_SFC_MAX]
uint32_t ui_get_color(uint16_t color_idx)
Get the RGB color value for a given color index.
int ui_color_content(uint color, uint *r, uint *g, uint *b)
void fast_exit(UiSurface *s)
Exit the UI application quickly, cleaning up resources.
RGB ui_hex_to_rgb(char *s)
Convert a hexadecimal color string to an RGB structure.
int ui_pair_from_hex(const char *fg, const char *bg)
Convert hex color strings to a curses color pair index.
WINDOW * ui_ncurses_surface_get_win(const UiSurface *s, ss_t w)
Get the current FILE pointer for the TTY used by the UI.
UiCell ui_cell_from_ucp(const wchar_t *ucp, const uint32_t *fg, const uint32_t *bg)
Convert a Unicode code point to a curses UiCell with specified foreground and background colors.
PANEL * ui_ncurses_surface_get_panel(const UiSurface *s, ss_t w)
Get the current PANEL pointer for a specific window within a UiSurface.
int ui_color_from_rgb(RGB *rgb)
Convert RGB to curses color index, adding new color if necessary.
int ui_chg_color(uint16_t color_idx, uint32_t *color)
Change the RGB color value for a given color index.
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
bool restore_shell_tioctl()
restore_shell_tioctl() - restore shell terminal settings
void sig_dfl_mode()
Set signal handlers to default behavior.
int ui_display_error(char *msg0, char *msg1, char *msg2, char *msg3)
Display an error message window or print to stderr.
UiBackend ui_get_backend()
Get the UI backend type.
UiBorderStyle border_style