C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
ui_notcurses.c
Go to the documentation of this file.
1/** @file ui_notcurses.c
2 @ingroup ui_notcurses
3 @brief NotCurses UI backend — lifecycle, surface management, and capabilities.
4
5 Implements all UiRuntime and UiSurface operations declared in ui_backend.h
6 using the NotCurses library.
7*/
8
9#include <iso646.h>
10#define _XOPEN_SOURCE_EXTENDED 1
11
12#include "cm.h"
13#include "ui_backend.h"
16#include <errno.h>
17#include <inttypes.h>
18#include <locale.h>
19#include <stdint.h>
20#include <stdlib.h>
21#include <string.h>
22#include <unistd.h>
23
24UiRuntime *ui = NULL;
25uint ui_color_cnt = 0;
26uint ui_pair_cnt = 0;
29UiSurface *stdsfc;
30uint LINES, COLS;
31UiRuntime *ui;
32UiConfig *ui_config;
34UiCell bkgd_cell;
35
36int sfc_ptr = -1;
38
39/* -------------------------------------------------------------------------
40 Backend identification and capability query
41 ------------------------------------------------------------------------- */
42/** @brief Get the current UI backend in use.
43 * @return The current UI backend as an enum value of type UiBackend.
44 *
45 * This function returns the current UI backend being used by the application.
46 * In this implementation, it always returns UI_BACKEND_NOTCURSES, indicating
47 * that the NotCurses library is being used as the UI backend.
48 */
49UiBackend ui_get_backend() {
51}
52/** @brief Get the capabilities of the current UI backend.
53 * @param caps Pointer to a UiCaps structure to be filled with the capabilities.
54 *
55 * This function populates the provided UiCaps structure with information about
56 * the capabilities of the current UI backend. It sets various fields in the
57 * structure, such as truecolor support, palette size, mouse support, Unicode
58 * support, and resize capability. If the provided pointer is NULL or if the
59 * UI runtime is not initialized, the function does nothing.
60 */
61void ui_get_caps(UiCaps *caps) {
62 if (!caps)
63 return;
64 memset(caps, 0, sizeof(*caps));
65 if (!ui)
66 return;
67 // I don't know that it isn't truecolor
68 caps->truecolor = true;
69 caps->palette256 = true;
70 caps->mouse = ui->mouse_enabled;
71 caps->unicode = true;
72 caps->resize = true;
73 caps->color_pairs = 0;
74}
75/* -------------------------------------------------------------------------
76 Lifecycle
77 ------------------------------------------------------------------------- */
78/** @brief Initialize the UI runtime with the specified configuration and SIO.
79 * @param cfg Pointer to a UiConfig structure containing configuration options.
80 * @param sio Pointer to a SIO structure for input/output operations.
81 * @return Pointer to the initialized UiRuntime structure, or NULL on failure.
82 *
83 * This function initializes the UI runtime using the NotCurses library. It sets
84 * up the terminal, creates the standard plane, and initializes various UI
85 * components based on the provided configuration. If any step fails, it cleans
86 * up and returns NULL.
87 */
88UiRuntime *ui_init(const UiConfig *cfg, SIO *sio) {
89 setlocale(LC_ALL, "en_US.UTF-8");
90 ui = calloc(1, sizeof(*ui));
91 if (!ui)
92 return NULL;
93 char tty_name[MAXLEN];
94 if (ttyname_r(STDIN_FILENO, tty_name, sizeof(tty_name)) != 0) {
95 free(ui);
96 ui = NULL;
97 return NULL;
98 }
99 ui->tty_fp = fopen(tty_name, "r+");
100 if (ui->tty_fp == NULL) {
101 ui = NULL;
102 free(ui);
103 return NULL;
104 }
106 NotCursesOptions nc_opts = {
107 .flags = NCOPTION_SUPPRESS_BANNERS |
108 NCOPTION_NO_QUIT_SIGHANDLERS,
109 };
110 ui->nc = notcurses_init(&nc_opts, ui->tty_fp);
111 if (ui->nc == NULL) {
112 free(ui);
113 ui = NULL;
114 return NULL;
115 }
116 f_notcurses_open = true;
117 stdplane = notcurses_stdplane(ui->nc);
118 notcurses_render(ui->nc);
119
120 if (ui->nc == NULL) {
121 fclose(ui->tty_fp);
122 ui->tty_fp = NULL;
123 free(ui);
124 ui = NULL;
125 return NULL;
126 }
127 notcurses_mice_enable(ui->nc, NCMICE_BUTTON_EVENT);
128 notcurses_cursor_disable(ui->nc);
129 notcurses_stddim_yx(ui->nc, &ui->lines, &ui->cols);
130 stdsfc = calloc(1, sizeof(*stdsfc));
131 if (!stdsfc)
132 return NULL;
133 for (int i = 0; i < SUB_SFC_MAX; i++) {
134 stdsfc->mplane[i] = NULL;
135 stdsfc->meta[i].lines = 0;
136 stdsfc->meta[i].cols = 0;
137 stdsfc->meta[i].y = 0;
138 stdsfc->meta[i].x = 0;
139 stdsfc->meta[i].hidden = false;
140 }
141 stdsfc->runtime = ui;
142 stdsfc->parent = NULL;
143 stdsfc->meta[BOX].lines = ui->lines;
144 stdsfc->meta[BOX].cols = ui->cols;
145 stdsfc->meta[BOX].y = 0;
146 stdsfc->meta[BOX].x = 0;
147 stdsfc->mplane[BOX] = stdplane;
148 if (!stdsfc->mplane[BOX]) {
149 notcurses_stop(ui->nc);
150 f_notcurses_open = false;
151 return NULL;
152 }
153 sfc_ptr = -1;
154 LINES = ui->lines;
155 COLS = ui->cols;
156 ui_pair = calloc(UI_PAIRS, sizeof(UiPair));
157 if (!ui_pair) {
158 free(ui_pair);
159 notcurses_stop(ui->nc);
160 f_notcurses_open = false;
161 free(ui);
162 return NULL;
163 }
164 ui_pair_cnt = 0;
165 ui_color = calloc(UI_COLORS, sizeof(UiColor));
166 if (!ui_color) {
167 free(ui_pair);
168 notcurses_stop(ui->nc);
169 f_notcurses_open = false;
170 free(ui);
171 return NULL;
172 }
173 ui_color_cnt = 0;
174 if (cfg->border_style)
175 ui->border_style = cfg->border_style;
176 if (!ui->border_style)
177 ui->border_style = UI_BORDER_ROUNDED;
178 if (cfg) {
179 switch (ui->border_style) {
180 case UI_BORDER_SINGLE:
181 memcpy(bw.str, border_single, sizeof(bw.str));
182 break;
183 case UI_BORDER_DOUBLE:
184 memcpy(bw.str, border_double, sizeof(bw.str));
185 break;
186 case UI_BORDER_ROUNDED:
187 memcpy(bw.str, border_rounded, sizeof(bw.str));
188 break;
189 case UI_BORDER_HEAVY:
190 memcpy(bw.str, border_heavy, sizeof(bw.str));
191 break;
192 case UI_BORDER_NONE:
193 memcpy(bw.str, border_none, sizeof(bw.str));
194 break;
195 default:
196 memcpy(bw.str, border_rounded, sizeof(bw.str));
197 break;
198 }
199 }
200 ui->tty_fd = notcurses_inputready_fd(ui->nc);
202 stdsfc = calloc(1, sizeof(*stdsfc));
203 return ui;
204}
205
206/* -------------------------------------------------------------------------
207 Surface Creation and Destruction
208 ------------------------------------------------------------------------- */
209/** @brief Create a new UI surface with the specified parameters.
210 * @param w The index of the surface to create.
211 * @param parent Pointer to the parent UiSurface, or NULL for no parent.
212 * @param p The index of the parent plane to attach to.
213 * @param lines The number of lines (rows) for the new surface.
214 * @param cols The number of columns for the new surface.
215 * @param y The y-coordinate for the new surface's position.
216 * @param x The x-coordinate for the new surface's position.
217 * @return Pointer to the newly created UiSurface, or NULL on failure.
218 *
219 * This function creates a new UI surface and initializes its properties based
220 * on the provided parameters. It allocates memory for the surface, sets up its
221 * metadata, and creates a new ncplane for rendering. If any step fails, it
222 * cleans up and returns NULL.
223 */
224UiSurface *ui_surface_new(ss_t w, UiSurface *parent, uint p, uint lines, uint cols, uint y, uint x) {
225 if (!ui)
226 return NULL;
227 UiSurface *s = calloc(1, sizeof(*s));
228 if (!s) {
229 ui_log(ERROR, "Failed to allocate memory for UiSurface\n");
230 return NULL;
231 }
232 ui_log(INFO, _("Memory allocated for new surface"));
233 s->runtime = ui;
234 s->parent = parent;
235 ncplane_options plane_opts = {
236 .y = y,
237 .x = x,
238 .rows = lines,
239 .cols = cols};
240 s->meta[w].y = y;
241 s->meta[w].x = x;
242 s->meta[w].lines = lines;
243 s->meta[w].cols = cols;
244 s->meta[w].hidden = false;
245 if (parent && parent->mplane[p]) {
246 s->mplane[w] = ncplane_create(parent->mplane[p], &plane_opts);
247 if (!s->mplane[w]) {
248 ui_log(ERROR, _("Failed to create mplane: %d"), w);
249 }
250 } else {
251 stdplane = notcurses_stdplane(ui->nc);
252 s->mplane[w] = ncplane_create(stdplane, &plane_opts);
253 if (!s->mplane[w]) {
254 ui_log(ERROR, _("Failed to create stdplane"));
255 }
256 }
257 ui_log(ERROR, _("mplane[%d] created"), w);
258 if (!s->mplane[w]) {
259 notcurses_stop(ui->nc);
260 f_notcurses_open = false;
261 return NULL;
262 }
263 return s;
264}
265/** @brief Create a new UI surface with a border box and optional title.
266 * @param parent Pointer to the parent UiSurface, or NULL for no parent.
267 * @param p The index of the parent plane to attach to.
268 * @param lines The number of lines (rows) for the new surface.
269 * @param cols The number of columns for the new surface.
270 * @param y The y-coordinate for the new surface's position.
271 * @param x The x-coordinate for the new surface's position.
272 * @param wtitle The title to display on the border box, or NULL for no title.
273 * @return Pointer to the newly created UiSurface, or NULL on failure.
274 *
275 * This function creates a new UI surface with a border box and an optional
276 * title. It allocates memory for the surface, sets up its metadata, and creates
277 * a new ncplane for rendering. If any step fails, it cleans up and returns NULL.
278 */
279UiSurface *ui_surface_box(UiSurface *parent, uint p, uint lines, uint cols, uint y, uint x, const char *wtitle) {
280 if (!ui)
281 return NULL;
282 UiSurface *s = calloc(1, sizeof(*s));
283 if (!s)
284 return NULL;
285 s->runtime = ui;
286 s->parent = parent;
287 ncplane_options plane_opts = {
288 .y = y,
289 .x = x,
290 .rows = lines,
291 .cols = cols,
292 .name = NULL};
293 s->meta[BOX].y = y;
294 s->meta[BOX].x = x;
295 s->meta[BOX].lines = lines + 2;
296 s->meta[BOX].cols = cols + 2;
297 s->meta[BOX].hidden = false;
298 strnz__cpy(s->meta[BOX].name, "BOX", XLEN - 1);
299 if (parent && parent->mplane[p]) {
300 s->mplane[BOX] = ncplane_create(parent->mplane[p], &plane_opts);
301 } else {
302 stdplane = notcurses_stdplane(ui->nc);
303 s->mplane[BOX] = ncplane_create(stdplane, &plane_opts);
304 }
305 if (!s->mplane[BOX]) {
306 free(s);
307 return NULL;
308 }
309 ncplane_set_base(s->mplane[BOX],
310 " ",
311 0,
312 cell_box.channels);
313 ncplane_set_channels(s->mplane[BOX], cell_box.channels);
315 ui_border_title(s, wtitle);
316 return s;
317}
318/** @brief Add padding to an existing UI surface.
319 * @param s Pointer to the UiSurface to which padding will be added.
320 * @param w The index of the new padded surface.
321 * @param p The index of the parent plane to attach to.
322 * @param lines The number of lines (rows) for the padded surface.
323 * @param cols The number of columns for the padded surface.
324 * @param y The y-coordinate for the padded surface's position.
325 * @param x The x-coordinate for the padded surface's position.
326 * @return 0 on success, -1 on failure.
327 *
328 * This function adds padding to an existing UI surface by creating a new
329 * ncplane with the specified dimensions and position. It updates the metadata
330 * for the new padded surface and sets its background and scrolling properties.
331 * If any step fails, it cleans up and returns -1.
332 */
333int ui_surface_addpad(UiSurface *s, ss_t w, uint p, uint lines, uint cols, uint y, uint x) {
334 uint plines, pcols;
335 ncplane_dim_yx(s->mplane[p], &plines, &pcols);
336 pcols = min(pcols, cols);
337 plines = min(plines, lines);
338 ncplane_options plane_opts = {
339 .y = y,
340 .x = x,
341 .rows = plines - y,
342 .cols = pcols - x,
343 .name = NULL};
344 s->meta[w].y = y;
345 s->meta[w].x = x;
346 s->meta[w].lines = plines - y;
347 s->meta[w].cols = pcols - x;
348 s->meta[w].hidden = false;
349 s->mplane[w] = ncplane_create(s->mplane[p], &plane_opts);
350 if (!s->mplane[w]) {
351 ui_log(ERROR, _("failed to create mplane[%d]"), w);
352 notcurses_stop(ui->nc);
353 f_notcurses_open = false;
354 return -1;
355 }
356 ncplane_set_base(s->mplane[w], " ", 0, cell_nt.channels);
357 ncplane_set_channels(s->mplane[w], cell_nt.channels);
360 ui_scrollok(s, w, true);
361 return 0;
362}
363/** @brief Add a new window to an existing UI surface.
364 * @param s Pointer to the UiSurface to which the window will be added.
365 * @param w The index of the new window.
366 * @param p The index of the parent plane to attach to.
367 * @param lines The number of lines (rows) for the new window.
368 * @param cols The number of columns for the new window.
369 * @param y The y-coordinate for the new window's position.
370 * @param x The x-coordinate for the new window's position.
371 * @return 0 on success, -1 on failure.
372 *
373 * This function adds a new window to an existing UI surface by creating a new
374 * ncplane with the specified dimensions and position. It updates the metadata
375 * for the new window and sets its background properties. If any step fails, it
376 * cleans up and returns -1.
377 */
378int ui_surface_addwin(UiSurface *s, ss_t w, uint p, uint lines, uint cols, uint y, uint x) {
379 ncplane_options plane_opts = {
380 .y = y,
381 .x = x,
382 .rows = lines,
383 .cols = cols,
384 .name = NULL};
385 s->meta[w].y = y;
386 s->meta[w].x = x;
387 s->meta[w].lines = lines;
388 s->meta[w].cols = cols;
389 s->meta[w].hidden = false;
390 s->mplane[w] = ncplane_create(s->mplane[p], &plane_opts);
391 if (!s->mplane[w]) {
392 ui_log(ERROR, _("failed to create mplane[%d]"), w);
393 notcurses_stop(ui->nc);
394 f_notcurses_open = false;
395 return -1;
396 }
397 ncplane_set_base(s->mplane[w], " ", 0, cell_nt.channels);
398 ncplane_set_channels(s->mplane[w], cell_nt.channels);
401 return 0;
402}
403/** @brief Destroy a UI surface and free its resources.
404 * @param s Pointer to the UiSurface to be destroyed.
405 *
406 * This function destroys a UI surface by freeing its associated ncplanes and
407 * metadata. It also frees the memory allocated for the UiSurface structure.
408 * If the provided pointer is NULL, the function does nothing.
409 */
410void ui_endwin() {
412}
413/** @brief Shutdown the UI runtime and free all associated resources.
414 *
415 * This function shuts down the UI runtime by destroying all surfaces, freeing
416 * memory, and stopping the NotCurses library. It also closes the terminal file
417 * pointer if it was opened. If the UI runtime is not initialized, the function
418 * does nothing.
419 */
421 if (ui == NULL)
422 return;
423 while (sfc_ptr >= 0) {
424 if (ui_surface[sfc_ptr]) {
425 ui_log(INFO, _("Destroying surface: %d"), sfc_ptr);
427 ui_surface[sfc_ptr] = NULL;
428 }
429 sfc_ptr--;
430 }
431 if (stdsfc->mplane[BOX]) {
432 ui_log(INFO, _("Destroying mplane[%d]"), BOX);
433 ncplane_erase(stdsfc->mplane[BOX]);
434 ncplane_destroy(stdsfc->mplane[BOX]);
435 stdsfc->mplane[BOX] = NULL;
436 }
437 if (ui->tty_fp) {
438 // fclose(ui->tty_fp);
439 // ui->tty_fp = NULL;
440 }
441 if (stdsfc != NULL) {
442 ui_log(INFO, _("Destroying stdsfc"));
443 free(stdsfc);
444 stdsfc = NULL;
445 }
446 ui_log(INFO, _("Calling notcurses_stop"));
447 notcurses_stop(ui->nc);
448 f_notcurses_open = false;
449 if (ui != NULL) {
450 if (ui_pair != NULL) {
451 ui_log(INFO, _("Destroying ui_pair"));
452 free(ui_pair);
453 ui_pair = NULL;
454 }
455 if (ui_color != NULL) {
456 ui_log(INFO, _("Destroying ui_color"));
457 free(ui_color);
458 ui_color = NULL;
459 }
460 if (ui->sio) {
461 ui_log(INFO, _("Destroying ui->sio"));
462 free(ui->sio);
463 ui->sio = nullptr;
464 }
465 if (ui != NULL) {
466 ui_log(INFO, _("Destroying ui"));
467 free(ui);
468 ui = NULL;
469 }
470 }
471}
472/** @brief Destroy a UI surface and free its resources.
473 * @param s Pointer to the UiSurface to be destroyed.
474 *
475 * This function destroys a UI surface by freeing its associated ncplanes and
476 * metadata. It also frees the memory allocated for the UiSurface structure.
477 * If the provided pointer is NULL, the function does nothing.
478 */
479void ui_surface_destroy(UiSurface *s) {
480 if (!s)
481 return;
482 ss_t w = SUB_SFC_MAX;
483 while (1) {
484 if (s->mplane[w] != NULL) {
485 ui_log(INFO, _("Destroying mplane[%d]"), w);
486 ncplane_erase(s->mplane[w]);
487 ncplane_destroy(s->mplane[w]);
488 s->mplane[w] = NULL;
489 }
490 if (w == BOX)
491 break;
492 w--;
493 };
494 if (s != NULL) {
495 ui_log(INFO, _("Destroying surface: s"));
496 free(s);
497 s = NULL;
498 }
499}
500/* -------------------------------------------------------------------------
501 Surface Navigation and Management
502 ------------------------------------------------------------------------- */
503/** @brief Move a UI surface to a new position on the screen.
504 * @param s Pointer to the UiSurface to be moved.
505 * @param w The index of the window within the surface to move.
506 * @param y The new y-coordinate for the surface's position.
507 * @param x The new x-coordinate for the surface's position.
508 * @return 0 on success, -1 on failure.
509 *
510 * This function moves a UI surface to a new position on the screen by updating
511 * its metadata and moving the associated ncplane. If the surface is hidden, it
512 * only updates the metadata without moving the ncplane. If any step fails, it
513 * returns -1.
514 */
515int ui_surface_move(UiSurface *s, ss_t w, uint y, uint x) {
516 if (!s)
517 return -1;
518 s->meta[w].y = y;
519 s->meta[w].x = x;
520 if (!s->meta[w].hidden)
521 return ncplane_move_yx(s->mplane[w], y, x) == 0 ? 0 : -1;
522 return 0;
523}
524/** @brief Resize a UI surface to new dimensions.
525 * @param s Pointer to the UiSurface to be resized.
526 * @param w The index of the window within the surface to resize.
527 * @param lines The new number of lines (rows) for the surface.
528 * @param cols The new number of columns for the surface.
529 * @return 0 on success, -1 on failure.
530 *
531 * This function resizes a UI surface to new dimensions by updating its metadata
532 * and resizing the associated ncplane. If any step fails, it returns -1.
533 */
534int ui_surface_resize(UiSurface *s, ss_t w, uint lines, uint cols) {
535 if (!s)
536 return -1;
537 return ncplane_resize_simple(s->mplane[w], (unsigned int)lines,
538 (unsigned int)cols) == 0
539 ? 0
540 : -1;
541}
542/** @brief Clear the contents of the standard plane.
543 * @return 0 on success, -1 on failure.
544 *
545 * This function clears the contents of the standard plane by erasing its
546 * contents. If the standard plane is not initialized, it returns -1.
547 */
548int ui_clear() {
549 if (!stdplane)
550 return -1;
551 ncplane_erase_region(stdplane, 0, 0, 0, 0);
552 return 0;
553}
554/** @brief Clear the contents of the specified window within a UI surface.
555 * @param s Pointer to the UiSurface containing the window to clear.
556 * @param w The index of the window to clear.
557 * @return 0 on success, -1 on failure.
558 *
559 * This function clears the contents of the specified window within a UI surface
560 * by erasing its contents. If the surface or window is not initialized, it
561 * returns -1.
562 */
563int ui_erase() {
564 if (!stdplane)
565 return -1;
566 ncplane_erase_region(stdplane, 0, 0, 0, 0);
567 return 0;
568}
569/** @brief Clear the contents of the specified window within a UI surface.
570 * @param s Pointer to the UiSurface containing the window to clear.
571 * @param w The index of the window to clear.
572 * @return 0 on success, -1 on failure.
573 *
574 * This function clears the contents of the specified window within a UI surface
575 * by erasing its contents. If the surface or window is not initialized, it
576 * returns -1.
577 */
578int ui_werase(UiSurface *s, ss_t w) {
579 if (!s)
580 return -1;
581 ncplane_erase_region(s->mplane[w], 0, 0, 0, 0);
582 return 0;
583}
584/** @brief Clear the contents of the specified window within a UI surface.
585 * @param s Pointer to the UiSurface containing the window to clear.
586 * @param w The index of the window to clear.
587 * @return 0 on success, -1 on failure.
588 *
589 * This function clears the contents of the specified window within a UI surface
590 * by erasing its contents. If the surface or window is not initialized, it
591 * returns -1.
592 */
593int ui_wclear(UiSurface *s, ss_t w) {
594 if (!s)
595 return -1;
596 ncplane_erase_region(s->mplane[w], 0, 0, 0, 0);
597 return 0;
598}
599/** @brief Move the specified window within a UI surface to the top of the z-order.
600 * @param s Pointer to the UiSurface containing the window to move.
601 * @param w The index of the window to move to the top.
602 * @return 0 on success, -1 on failure.
603 *
604 * This function moves the specified window within a UI surface to the top of
605 * the z-order, making it the foremost window. If the surface or window is not
606 * initialized, it returns -1.
607 */
608int ui_top_surface(UiSurface *s, ss_t w) {
609 if (!s)
610 return -1;
611 ncplane_move_top(s->mplane[w]);
612 return 0;
613}
614/** @brief Show the specified window within a UI surface.
615 * @param s Pointer to the UiSurface containing the window to show.
616 * @param w The index of the window to show.
617 * @return 0 on success, -1 on failure.
618 *
619 * This function shows the specified window within a UI surface by updating its
620 * metadata and moving it to its designated position. If the surface or window
621 * is not initialized, it returns -1.
622 */
623int ui_surface_show(UiSurface *s, ss_t w) {
624 if (!s)
625 return -1;
626 if (s->meta[w].hidden) {
627 s->meta[w].hidden = false;
628 ncplane_move_yx(s->mplane[w], s->meta[w].y, s->meta[w].x);
629 }
630 return 0;
631}
632/** @brief Hide the specified window within a UI surface.
633 * @param s Pointer to the UiSurface containing the window to hide.
634 * @param w The index of the window to hide.
635 * @return 0 on success, -1 on failure.
636 *
637 * This function hides the specified window within a UI surface by updating its
638 * metadata and moving it far off-screen. If the surface or window is not
639 * initialized, it returns -1.
640 */
641int ui_surface_hide(UiSurface *s, ss_t w) {
642 if (!s)
643 return -1;
644 if (!s->meta[w].hidden) {
645 s->meta[w].hidden = true;
646 /* Move far off-screen so the plane does not obscure anything. */
647 ncplane_move_yx(s->mplane[w], -s->meta[w].lines - 1, 0);
648 }
649 return 0;
650}
651// -------------------------------------------------------------------------
652// Screen Navigation
653// -------------------------------------------------------------------------
654/** @brief Move the cursor to the specified position within a window of a UI surface.
655 * @param s Pointer to the UiSurface containing the window.
656 * @param w The index of the window within the surface.
657 * @param y The y-coordinate for the new cursor position.
658 * @param x The x-coordinate for the new cursor position.
659 * @return 0 on success, -1 on failure.
660 *
661 * This function moves the cursor to the specified position within a window of
662 * a UI surface. If the surface or window is not initialized, it returns -1.
663 */
664int ui_wmove(UiSurface *s, ss_t w, uint y, uint x) {
665 if (!s)
666 return -1;
667 if (ncplane_cursor_move_yx(s->mplane[w], y, x) != 0)
668 return -1;
669 return 0;
670}
671/** @brief Move the cursor to the specified position within a window of a UI surface.
672 * @param s Pointer to the UiSurface containing the window.
673 * @param w The index of the window within the surface.
674 * @param y The y-coordinate for the new cursor position.
675 * @param x The x-coordinate for the new cursor position.
676 * @return 0 on success, -1 on failure.
677 *
678 * This function moves the cursor to the specified position within a window of
679 * a UI surface. If the surface or window is not initialized, it returns -1.
680 */
681int ui_cursor_move(UiSurface *s, ss_t w, uint y, uint x) {
682 if (!s)
683 return -1;
684 if (ncplane_cursor_move_yx(s->mplane[w], y, x) != 0)
685 return -1;
686 return 0;
687}
688/** @brief Get the current cursor position within a window of a UI surface.
689 * @param s Pointer to the UiSurface containing the window.
690 * @param w The index of the window within the surface.
691 * @param y Pointer to an unsigned integer to store the y-coordinate of the cursor.
692 * @param x Pointer to an unsigned integer to store the x-coordinate of the cursor.
693 *
694 * This function retrieves the current cursor position within a window of a UI
695 * surface. If the surface or window is not initialized, it does nothing.
696 */
697void ui_cursor_yx(int *y, int *x) {
698 notcurses_cursor_yx(ui->nc, y, x);
699}
700/** @brief Get the absolute cursor position within a window of a UI surface.
701 * @param s Pointer to the UiSurface containing the window.
702 * @param w The index of the window within the surface.
703 * @param y Pointer to an integer to store the absolute y-coordinate of the cursor.
704 * @param x Pointer to an integer to store the absolute x-coordinate of the cursor.
705 *
706 * This function retrieves the absolute cursor position within a window of a UI
707 * surface. If the surface or window is not initialized, it does nothing.
708 */
709void ui_abs_yx(UiSurface *s, ss_t w, int *y, int *x) {
710 if (!s)
711 return;
712 ncplane_abs_yx(s->mplane[w], y, x);
713}
714/** @brief Get the current cursor position within a window of a UI surface.
715 * @param s Pointer to the UiSurface containing the window.
716 * @param w The index of the window within the surface.
717 * @param y Pointer to an unsigned integer to store the y-coordinate of the cursor.
718 * @param x Pointer to an unsigned integer to store the x-coordinate of the cursor.
719 *
720 * This function retrieves the current cursor position within a window of a UI
721 * surface. If the surface or window is not initialized, it does nothing.
722 */
723void ui_getyx(UiSurface *s, ss_t w, uint *y, uint *x) {
724 if (!s)
725 return;
726 ncplane_cursor_yx(s->mplane[w], y, x);
727}
728/** @brief Get the maximum dimensions of a window within a UI surface.
729 * @param s Pointer to the UiSurface containing the window.
730 * @param w The index of the window within the surface.
731 * @param y Pointer to an unsigned integer to store the maximum number of lines (rows).
732 * @param x Pointer to an unsigned integer to store the maximum number of columns.
733 *
734 * This function retrieves the maximum dimensions of a window within a UI
735 * surface. If the surface or window is not initialized, it does nothing.
736 */
737void ui_getmaxyx(UiSurface *s, ss_t w, uint *y, uint *x) {
738 if (!s)
739 return;
740 ncplane_dim_yx(s->mplane[w], y, x);
741}
742/** @brief Get the maximum number of lines (rows) of a window within a UI surface.
743 * @param s Pointer to the UiSurface containing the window.
744 * @param w The index of the window within the surface.
745 * @return The maximum number of lines (rows) of the window, or -1 on failure.
746 *
747 * This function retrieves the maximum number of lines (rows) of a window
748 * within a UI surface. If the surface or window is not initialized, it returns
749 * -1.
750 */
751int ui_getmaxy(UiSurface *s, ss_t w) {
752 if (!s)
753 return -1;
754 uint y, x;
755 ncplane_dim_yx(s->mplane[w], &y, &x);
756 return y;
757}
758/** @brief Get the maximum number of columns of a window within a UI surface.
759 * @param s Pointer to the UiSurface containing the window.
760 * @param w The index of the window within the surface.
761 * @return The maximum number of columns of the window, or -1 on failure.
762 *
763 * This function retrieves the maximum number of columns of a window within a
764 * UI surface. If the surface or window is not initialized, it returns -1.
765 */
766int ui_getmaxx(UiSurface *s, ss_t w) {
767 if (!s)
768 return -1;
769 uint y, x;
770 ncplane_dim_yx(s->mplane[w], &y, &x);
771 return x;
772}
773/** @brief Scroll the contents of the specified window up or down by the specified
774 * number of lines.
775 * @param s The surface containing the window to scroll.
776 * @param w The index of the window to scroll.
777 * @param r The number of lines to scroll. Positive values scroll up, negative
778 * values scroll down.
779 * @return 0 on success, -1 on error.
780 *
781 * If r is positive, the contents of the plane are moved up, leaving blank lines
782 * at the bottom. In the view application, the view scope is moved toward end of
783 * file (eof). - scope_toward_eof()
784 *
785 * @note ui_wscrl(-n) - If r is negative, the contents of the plane are moved down,
786 * leaving blank lines at the top. In the view application, the view scope is
787 * moved toward beginning of file (bof). - scope_toward_bof()
788 */
789int ui_wscrl(UiSurface *s, ss_t w, int r) {
790 uint rows, cols;
791 ncplane_dim_yx(s->mplane[w], &rows, &cols);
792
793 if (r > 0) {
794 // Scroll up (toward EOF): notcurses has this natively
795 ncplane_scrollup(s->mplane[w], r);
796 return 0;
797 }
798
799 // Scroll down (toward BOF): shift content down by |r| rows
800 r = -r;
801 if ((uint)r >= rows) {
802 ncplane_erase(s->mplane[w]);
803 return 0;
804 }
805
806 // Copy rows bottom-up to avoid overwriting source before reading
807 for (int src_row = (int)(rows - r) - 1; src_row >= 0; src_row--) {
808 int dst_row = src_row + r;
809 for (uint col = 0; col < cols; col++) {
810 nccell c = NCCELL_TRIVIAL_INITIALIZER;
811 ncplane_at_yx_cell(s->mplane[w], src_row, col, &c);
812 ncplane_putc_yx(s->mplane[w], dst_row, col, &c);
813 nccell_release(s->mplane[w], &c);
814 }
815 }
816 // Blank the top r rows
817 for (int row = 0; row < r; row++) {
818 for (uint col = 0; col < cols; col++) {
819 ncplane_putchar_yx(s->mplane[w], row, col, ' ');
820 }
821 }
822 return 0;
823}
824
825/* -------------------------------------------------------------------------
826 Configuration Control
827 ------------------------------------------------------------------------- */
828/** @brief Enable or disable scrolling for the specified window within a UI surface.
829 * @param s Pointer to the UiSurface containing the window.
830 * @param w The index of the window within the surface.
831 * @param enable True to enable scrolling, false to disable scrolling.
832 * @return 0 on success, -1 on failure.
833 *
834 * This function enables or disables scrolling for the specified window within
835 * a UI surface. If the surface or window is not initialized, it returns -1.
836 */
837int ui_scrollok(UiSurface *s, ss_t w, bool enable) {
838 if (!s)
839 return -1;
840 ncplane_set_scrolling(s->mplane[w], enable);
841 return 0;
842}
843/** @brief Enable or disable the keypad for the specified window within a UI surface.
844 * @param s Pointer to the UiSurface containing the window.
845 * @param w The index of the window within the surface.
846 * @param enable True to enable the keypad, false to disable the keypad.
847 * @return 0 on success, -1 on failure.
848 *
849 * This function does nothing.
850 */
851int ui_idcok(UiSurface *s, ss_t w, bool enable) {
852 (void)s;
853 (void)w;
854 (void)enable;
855 return 0;
856}
857/** @brief Enable or disable the use of the keypad for the specified window within a UI surface.
858 * @param s Pointer to the UiSurface containing the window.
859 * @param w The index of the window within the surface.
860 * @param enable True to enable the use of the keypad, false to disable it.
861 * @return 0 on success, -1 on failure.
862 *
863 * This function does nothing.
864 */
865int ui_idlok(UiSurface *s, ss_t w, bool enable) {
866 (void)s;
867 (void)w;
868 (void)enable;
869 return 0;
870}
871/** @brief Set the scrolling region for the specified window within a UI surface.
872 * @param s Pointer to the UiSurface containing the window.
873 * @param w The index of the window within the surface.
874 * @param top The top line of the scrolling region.
875 * @param bottom The bottom line of the scrolling region.
876 * @return 0 on success, -1 on failure.
877 *
878 * This function does nothing.
879 */
880int ui_setscrreg(UiSurface *s, ss_t w, uint top, uint bottom) {
881 (void)s;
882 (void)w;
883 (void)top;
884 (void)bottom;
885 return 0;
886}
887/** @brief Enable or disable the keypad for the specified window within a UI surface.
888 * @param s Pointer to the UiSurface containing the window.
889 * @param w The index of the window within the surface.
890 * @param enable True to enable the keypad, false to disable it.
891 * @return 0 on success, -1 on failure.
892 *
893 * This function does nothing.
894 */
895int ui_keypad(UiSurface *s, ss_t w, bool enable) {
896 (void)s;
897 (void)w;
898 (void)enable;
899 return 0;
900}
901/* -------------------------------------------------------------------------
902 Screen management functions
903 ------------------------------------------------------------------------- */
904/** @brief Get the current screen size in lines and columns.
905 * @param lines Pointer to an unsigned integer to store the number of lines (rows).
906 * @param cols Pointer to an unsigned integer to store the number of columns.
907 *
908 * This function retrieves the current screen size in lines and columns.
909 */
910void ui_get_screen_size(uint *lines, uint *cols) {
911 if (!ui)
912 return;
913 unsigned int r = 0, c = 0;
914 notcurses_stddim_yx(ui->nc, &r, &c);
915 ui->lines = (int)r;
916 ui->cols = (int)c;
917 if (lines)
918 *lines = ui->lines;
919 if (cols)
920 *cols = ui->cols;
921}
922/** @brief Update the panels and render the UI.
923 *
924 * This function updates the panels and renders the UI.
925 */
927 if (!ui)
928 return;
929 notcurses_render(ui->nc);
930}
931/** @brief Render the UI.
932 *
933 * This function renders the UI.
934 */
935void ui_render() {
936 if (!ui)
937 return;
938 notcurses_render(ui->nc);
939}
940/** @brief Suspend the UI and leave the alternate screen.
941 *
942 * This function suspends the UI and leaves the alternate screen.
943 * It is typically used when the application needs to temporarily exit
944 * the UI mode, such as when executing a shell command or displaying
945 * a message outside of the UI context.
946 *
947 * @return 0 on success, -1 on failure.
948 */
950 if (!ui)
951 return -1;
952 notcurses_leave_alternate_screen(ui->nc);
953 return 0;
954}
955/** @brief Resume the UI and enter the alternate screen.
956 *
957 * This function resumes the UI and enters the alternate screen.
958 * It is typically used after a suspension of the UI, allowing
959 * the application to return to its previous state and continue
960 * rendering the UI.
961 *
962 * @return 0 on success, -1 on failure.
963 */
965 if (!ui)
966 return -1;
967 notcurses_enter_alternate_screen(ui->nc);
968 notcurses_render(ui->nc);
969 return 0;
970}
972 return;
973}
974// -------------------------------------------------------------------------
975// Cursor Control
976// -------------------------------------------------------------------------
977/** @brief Enable or disable the cursor visibility.
978 * @param visible True to enable the cursor, false to disable it.
979 * @return 0 on success, -1 on failure.
980 *
981 * This function enables or disables the cursor visibility. If the UI is not
982 * initialized, it returns -1. When enabling the cursor, it retrieves the
983 * current cursor position and enables the cursor at that position.
984 */
985int ui_curs_set(int visible) {
986 if (!ui)
987 return -1;
988 if (visible == 0) {
989 ui->cursor_visible = false;
990 notcurses_cursor_disable(ui->nc);
991 } else {
992 ui->cursor_visible = true;
993 int y, x;
994 notcurses_cursor_yx(ui->nc, &y, &x);
995 int rc = notcurses_cursor_enable(ui->nc, y, x);
996 return rc;
997 }
998 return 0;
999}
1000/** @brief Enable or disable the cursor at a specific position on the surface and plane specified.
1001 * @param s Pointer to the UiSurface containing the window.
1002 * @param w The index of the window within the surface.
1003 * @param y The y-coordinate for the cursor position.
1004 * @param x The x-coordinate for the cursor position.
1005 * @param visible True to enable the cursor, false to disable it.
1006 * @return 0 on success, -1 on failure.
1007 *
1008 * This function enables or disables the cursor at a specific position on the
1009 * surface and plane specified. If the UI is not initialized, it returns -1.
1010 */
1011int ui_cursor_enable_yx(UiSurface *s, ss_t w, uint y, uint x, bool visible) {
1012 if (!s)
1013 return -1;
1014 if (!visible) {
1015 ui->cursor_visible = false;
1016 notcurses_cursor_disable(ui->nc);
1017 } else {
1018 int yy, xx;
1019 ncplane_abs_yx(s->mplane[w], &yy, &xx);
1020 y += yy;
1021 x += xx;
1022 ui->cursor_visible = true;
1023 int rc = notcurses_cursor_enable(ui->nc, y, x);
1024 return rc;
1025 }
1026 return 0;
1027}
1028/** @brief Enable or disable the cursor at the current position on the surface and plane specified.
1029 * @param s Pointer to the UiSurface containing the window.
1030 * @param w The index of the window within the surface.
1031 * @param visible True to enable the cursor, false to disable it.
1032 * @return 0 on success, -1 on failure.
1033 *
1034 * This function enables or disables the cursor at the current position on the
1035 * surface and plane specified. If the UI is not initialized, it returns -1.
1036 */
1037int ui_cursor_enable(UiSurface *s, ss_t w, bool visible) {
1038 if (!s)
1039 return -1;
1040 if (!visible) {
1041 ui->cursor_visible = false;
1042 notcurses_cursor_disable(ui->nc);
1043 } else {
1044 uint y, x;
1045 ncplane_cursor_yx(s->mplane[w], &y, &x);
1046 int yy, xx;
1047 ncplane_abs_yx(s->mplane[w], &yy, &xx);
1048 y += yy;
1049 x += xx;
1050 ui->cursor_visible = true;
1051 return notcurses_cursor_enable(ui->nc, y, x) == 0 ? 0 : -1;
1052 }
1053 return 0;
1054}
1055/* -------------------------------------------------------------------------
1056 background
1057 ------------------------------------------------------------------------- */
1058/** @brief Set the background cell for the specified window within a UI surface.
1059 * @param s Pointer to the UiSurface containing the window.
1060 * @param w The index of the window within the surface.
1061 * @param cell Pointer to the UiCell representing the background cell.
1062 * @return 0 on success, -1 on failure.
1063 *
1064 * This function sets the background cell for the specified window within a UI
1065 * surface. It updates the styles and channels of the ncplane associated with
1066 * the window and stores the background cell in the metadata. If the surface is
1067 * not initialized, it returns -1.
1068 */
1069int ui_bkgd(UiSurface *s, ss_t w, const UiCell *cell) {
1070 if (!s)
1071 return -1;
1072 ncplane_set_styles(s->mplane[w], cell->stylemask);
1073 ncplane_set_channels(s->mplane[w], cell->channels);
1074 ncplane_set_base(s->mplane[w], " ",
1075 cell->stylemask, cell->channels);
1076 s->meta[w].bkgd_cell = *cell;
1077 return 0;
1078}
1079/** @brief Set the background cell for the specified window within a UI surface without changing the base character.
1080 * @param s Pointer to the UiSurface containing the window.
1081 * @param w The index of the window within the surface.
1082 * @param cell Pointer to the UiCell representing the background cell.
1083 * @return 0 on success, -1 on failure.
1084 *
1085 * This function sets the background cell for the specified window within a UI
1086 * surface without changing the base character. It updates the styles and
1087 * channels of the ncplane associated with the window and stores the background
1088 * cell in the metadata. If the surface is not initialized, it returns -1.
1089 */
1090int ui_bkgdset(UiSurface *s, ss_t w, const UiCell *cell) {
1091 if (!s)
1092 return -1;
1093 ncplane_set_styles(s->mplane[w], cell->stylemask);
1094 ncplane_set_channels(s->mplane[w], cell->channels);
1095 s->meta[w].bkgd_cell = *cell;
1096 // ncplane_set_base(s->mplane[w], " ",
1097 // cell->stylemask, cell->channels);
1098 return 0;
1099}
1100/** @brief Set the background cell for the specified window within a UI surface without changing the base character.
1101 * @param s Pointer to the UiSurface containing the window.
1102 * @param w The index of the window within the surface.
1103 * @param cell Pointer to the UiCell representing the background cell.
1104 * @return 0 on success, -1 on failure.
1105 *
1106 * This function sets the background cell for the specified window within a UI
1107 * surface without changing the base character. It updates the styles and
1108 * channels of the ncplane associated with the window and stores the background
1109 * cell in the metadata. If the surface is not initialized, it returns -1.
1110 */
1111int ui_bkgrnd(UiSurface *s, ss_t w, const UiCell *cell) {
1112 if (!s)
1113 return -1;
1114 ncplane_set_styles(s->mplane[w], cell->stylemask);
1115 ncplane_set_channels(s->mplane[w], cell->channels);
1116 ncplane_set_base(s->mplane[w], " ",
1117 cell->stylemask, cell->channels);
1118 return 0;
1119}
1120/** @brief Set the background cell for the specified window within a UI surface without changing the base character.
1121 * @param s Pointer to the UiSurface containing the window.
1122 * @param w The index of the window within the surface.
1123 * @param cell Pointer to the UiCell representing the background cell.
1124 * @return 0 on success, -1 on failure.
1125 *
1126 * This function sets the background cell for the specified window within a UI
1127 * surface without changing the base character. It updates the styles and
1128 * channels of the ncplane associated with the window and stores the background
1129 * cell in the metadata. If the surface is not initialized, it returns -1.
1130 */
1131int ui_bkgrndset(UiSurface *s, ss_t w, const UiCell *cell) {
1132 if (!s)
1133 return -1;
1134 ncplane_set_styles(s->mplane[w], cell->stylemask);
1135 ncplane_set_channels(s->mplane[w], cell->channels);
1136 ncplane_set_base(s->mplane[w], " ",
1137 cell->stylemask, cell->channels);
1138 return 0;
1139}
1140/* -------------------------------------------------------------------------
1141 Cell Manipulation
1142 ------------------------------------------------------------------------- */
1143/** @brief Get the properties of a cell at the current cursor position in a window of a UI surface.
1144 * @param sfc Pointer to the UiSurface containing the window.
1145 * @param w The index of the window within the surface.
1146 * @param cell Pointer to a UiCell structure to store the cell properties.
1147 * @param wstr Pointer to a wide character string to store the cell's character(s).
1148 * @param style Pointer to a UiStyle variable to store the cell's style attributes.
1149 * @param pair Pointer to a short variable to store the color pair index of the cell.
1150 * @return 0 on success, -1 on failure.
1151 *
1152 * This function retrieves the properties of a cell at the current cursor position
1153 * in a window of a UI surface. It fills in the provided UiCell structure with
1154 * the cell's properties, including its character(s), style attributes, and
1155 * color pair index. If any of the input pointers are NULL, it returns -1.
1156 */
1158 UiSurface *sfc,
1159 ss_t w,
1160 const UiCell *cell,
1161 wchar_t *wstr,
1162 UiStyle *style,
1163 short *pair) {
1164 (void)sfc;
1165 (void)w;
1166 if (!cell || !wstr || !style || !pair)
1167 return -1;
1168 GCluster gc;
1169 gc.u32 = cell->gcluster;
1170 *wstr = gc.w32;
1171 *style = cell->stylemask;
1172 // Convert the channels to a color pair index
1173 UiChannels channels;
1174 channels.fb = cell->channels;
1175 RGB rgb;
1176 rgb.r = channels.f_r;
1177 rgb.g = channels.f_g;
1178 rgb.b = channels.f_b;
1179 // If the color index does not exist, create a new one
1180 int fg = ui_color_from_rgb(&rgb);
1181 rgb.r = channels.b_r;
1182 rgb.g = channels.b_g;
1183 rgb.b = channels.b_b;
1184 // If the color index does not exist, create a new one
1185 int bg = ui_color_from_rgb(&rgb);
1186 // If the color pair does not exist, create a new one
1187 *pair = ui_add_pair(fg, bg);
1188 return 0;
1189}
1190/** @brief Set the properties of a cell at the current cursor position in a window of a UI surface.
1191 * @param sfc Pointer to the UiSurface containing the window.
1192 * @param w The index of the window within the surface.
1193 * @param cell Pointer to a UiCell structure representing the cell properties to set.
1194 * @param wstr Pointer to a wide character string representing the character(s) to set in the cell.
1195 * @param style The style attributes to set for the cell.
1196 * @param pair The color pair index to set for the cell.
1197 * @return 0 on success, -1 on failure.
1198 *
1199 * This function sets the properties of a cell at the current cursor position
1200 * in a window of a UI surface. It updates the specified UiCell structure with
1201 * the provided character(s), style attributes, and color pair index. If any
1202 * of the input pointers are NULL, it returns -1.
1203 */
1205 UiSurface *sfc,
1206 ss_t w,
1207 UiCell *cell,
1208 const wchar_t *wstr,
1209 const UiStyle style,
1210 short pair) {
1211 if (!cell)
1212 return -1;
1213 uint32_t fg, bg;
1214 nccell_init(cell);
1215 GCluster gc;
1216 unicode_to_utf8_gcluster(*wstr, &gc);
1217 nccell_set_styles(cell, style);
1218 UiChannels *chan = (UiChannels *)&cell->channels;
1219 ui_get_pair(pair, &fg, &bg);
1220 ui_color_content(fg, &chan->f_r, &chan->f_g, &chan->f_b);
1221 chan->f_a = 0x40;
1222 ui_color_content(bg, &chan->b_r, &chan->b_g, &chan->b_b);
1223 chan->b_a = 0x40;
1224 nccell_load_egc32(sfc->mplane[w], cell, gc.u32);
1225 return 0;
1226}
1227/** @brief Create a UiCell from a Unicode codepoint and specified foreground and background colors.
1228 * @param ucp Pointer to a wide character string representing the Unicode codepoint.
1229 * @param fg Pointer to a 32-bit unsigned integer representing the foreground color.
1230 * @param bg Pointer to a 32-bit unsigned integer representing the background color.
1231 * @return A UiCell structure representing the created cell.
1232 *
1233 * This function creates a UiCell from a Unicode codepoint and specified foreground
1234 * and background colors. It initializes the cell, sets its width based on the
1235 * Unicode codepoint, converts the codepoint to UTF-8, and sets the styles and
1236 * channels for the cell. The resulting UiCell can be used for rendering text
1237 * in a UI surface.
1238 */
1239UiCell ui_cell_from_ucp(const wchar_t *ucp, const uint32_t *fg, const uint32_t *bg) {
1240 nccell cell;
1241 nccell_init(&cell);
1242 GCluster *gc = (GCluster *)&cell.gcluster;
1243 wchar_t wstr[2] = {ucp[0], L'\0'};
1244 // wcwidth expects Unicode codepoints, not UTF-8 encoded bytes
1245 cell.width = wcwidth(wstr[0]);
1246 // unicode_to_utf8_gcluster converts Unicode codepoints to UTF-8
1247 unicode_to_utf8_gcluster(wstr[0], gc);
1248 nccell_set_styles(&cell, WA_NORMAL);
1249 UiChannels *chan = (UiChannels *)&cell.channels;
1250 chan->bargb = *bg;
1251 chan->fargb = *fg;
1252 chan->b_a = chan->f_a = 0x40;
1253 return cell;
1254}
1255/* -------------------------------------------------------------------------
1256 Colors, Color Pairs
1257 ------------------------------------------------------------------------- */
1258/** @brief Convert an RGB color to a color index in the UI color palette.
1259 * @param rgb Pointer to an RGB structure representing the color to convert.
1260 * @return The color index corresponding to the RGB color, or -1 if the color cannot be added.
1261 *
1262 * This function converts an RGB color to a color index in the UI color palette.
1263 * It applies gamma correction to the RGB values and checks if the color already
1264 * exists in the palette. If it does, it returns the existing index. If not, it
1265 * adds the new color to the palette and returns its index. If the palette is full,
1266 * it returns -1.
1267 */
1268uint ui_color_from_rgb(RGB *rgb) {
1269 uint i;
1270 RGB tmp;
1272 for (i = 0; i < ui_color_cnt && i < UI_COLORS; i++) {
1273 ui_color_content(i, &tmp.r, &tmp.g, &tmp.b);
1274 if (rgb->r == tmp.r && rgb->g == tmp.g && rgb->b == tmp.b)
1275 return i;
1276 }
1277 if (i < UI_COLORS) {
1278 if (i < 16) {
1279 std_color[i].r = rgb->r;
1280 std_color[i].g = rgb->g;
1281 std_color[i].b = rgb->b;
1282 }
1283 ui_init_color(i, rgb->r, rgb->g, rgb->b);
1284 if (ui_color_cnt + 1 < UI_COLORS)
1285 ui_color_cnt++;
1286 return ui_color_cnt - 1;
1287 }
1288 return -1;
1289}
1290/* ------------------------------------------------------------------------- */
1291/** @brief Add a new color pair to the UI color pair palette.
1292 * @param fg The foreground color index for the new color pair.
1293 * @param bg The background color index for the new color pair.
1294 * @return The index of the newly added color pair, or EXIT_FAILURE if the maximum number of pairs is exceeded.
1295 *
1296 * This function adds a new color pair to the UI color pair palette. It checks
1297 * if the specified foreground and background colors already exist in the palette.
1298 * If they do, it returns the existing index. If not, it adds the new color pair
1299 * and returns its index. If the maximum number of pairs is exceeded, it displays
1300 * an error message and returns EXIT_FAILURE.
1301 */
1302uint ui_add_pair(uint fg, uint bg) {
1303 uint16_t i;
1304 for (i = 1; i < ui_pair_cnt; i++) {
1305 if (ui_pair[i].fg == fg && ui_pair[i].bg == bg)
1306 return i;
1307 }
1308 if (i + 1 >= UI_PAIRS) {
1309 ssnprintf(em0, MAXLEN - 1, _("%s, line: %d"), __FILE__, __LINE__ - 1);
1310 ssnprintf(em1, MAXLEN - 1, _("NotCurses COLOR_PAIRS (%d) exceeded (%d)"),
1311 UI_PAIRS, i);
1312 strerror_r(errno, em2, MAXLEN);
1314 return (EXIT_FAILURE);
1315 }
1316 if (i < UI_PAIRS) {
1317 ui_pair[i].fg = fg;
1318 ui_pair[i].bg = bg;
1319 ui_pair_cnt++;
1320 }
1321 return ui_pair_cnt - 1;
1322}
1323/** @brief Get the foreground and background color indices for a given color pair index.
1324 * @param pair The color pair index.
1325 * @param fg Pointer to store the foreground color index.
1326 * @param bg Pointer to store the background color index.
1327 * @return 0 on success, -1 on error (if the pair index is out of bounds).
1328 */
1329int ui_get_pair(uint16_t pair, uint *fg, uint *bg) {
1330 *fg = ui_pair[pair].fg;
1331 *bg = ui_pair[pair].bg;
1332 return 0;
1333}
1334/** @brief Get the combined foreground and background color channels for a given color pair index.
1335 * @param pair The color pair index.
1336 * @return A 64-bit unsigned integer representing the combined foreground and background color channels.
1337 *
1338 * This function retrieves the combined foreground and background color channels
1339 * for a given color pair index. It uses the ui_get_pair function to obtain the
1340 * foreground and background color indices, then retrieves their RGB values and
1341 * constructs a UiChannels structure. The resulting combined channels are returned
1342 * as a 64-bit unsigned integer.
1343 */
1344uint64_t ui_get_channels_from_pair(uint16_t pair) {
1345 uint fg, bg;
1346 // ui_channels is a struct that holds the foreground and background color
1347 // channels
1348 // use channels.fb to get the combined foreground and background color channels
1349 UiChannels ui_channels = {};
1350 ui_get_pair(pair, &fg, &bg);
1351 ui_color_content(fg, &ui_channels.f_r, &ui_channels.f_g, &ui_channels.f_b);
1352 ui_channels.f_a = 0x40;
1353 ui_channels.f_r = ui_color[fg].r;
1354 ui_channels.f_g = ui_color[fg].g;
1355 ui_channels.f_b = ui_color[fg].b;
1356 bg = ui_pair[pair].bg;
1357 ui_color_content(bg, &ui_channels.b_r, &ui_channels.b_g, &ui_channels.b_b);
1358 ui_channels.b_a = 0x40;
1359 ui_channels.b_r = ui_color[bg].r;
1360 ui_channels.b_g = ui_color[bg].g;
1361 ui_channels.b_b = ui_color[bg].b;
1362 return ui_channels.fb;
1363}
1364/** @brief Initialize a color from a hexadecimal string representation.
1365 * @param s A string representing the color in hexadecimal format (e.g., "#RRGGBB").
1366 * @return The index of the initialized color in the UI color palette, or 0 if the color cannot be added.
1367 *
1368 * This function initializes a color from a hexadecimal string representation.
1369 * It converts the hex string to an RGB structure, applies gamma correction,
1370 * and checks if the color already exists in the UI color palette. If it does,
1371 * it returns the existing index. If not, it adds the new color to the palette
1372 * and returns its index. If the palette is full, it returns 0.
1373 */
1374uint ui_init_color_hex(char *s) {
1375 RGB rgb;
1376 rgb = ui_hex_to_rgb(s);
1377 ui_apply_gamma(&rgb);
1378 uint i;
1379 for (i = 0; i < ui_color_cnt && i < UI_COLORS; i++) {
1380 if (rgb.r == ui_color[i].r && rgb.g == ui_color[i].g && rgb.b == ui_color[i].b)
1381 return i;
1382 }
1383 if (i < UI_COLORS) {
1384 if (i < 16) {
1385 std_color[i].r = rgb.r;
1386 std_color[i].g = rgb.g;
1387 std_color[i].b = rgb.b;
1388 }
1389 ui_color[i].r = rgb.r;
1390 ui_color[i].g = rgb.g;
1391 ui_color[i].b = rgb.b;
1392 if (ui_color_cnt + 1 < UI_COLORS)
1393 ui_color_cnt++;
1394 return ui_color_cnt - 1;
1395 }
1396 return 0;
1397}
1398/** @brief Convert a hexadecimal color string to an RGB structure.
1399 * @param s A string representing the color in hexadecimal format (e.g., "#RRGGBB").
1400 * @return An RGB structure containing the red, green, and blue components of the color.
1401 *
1402 * This function converts a hexadecimal color string to an RGB structure. It
1403 * uses sscanf to parse the hex string and extract the red, green, and blue
1404 * components. The resulting RGB structure is returned.
1405 */
1406RGB ui_hex_to_rgb(char *s) {
1407 RGB rgb;
1408 sscanf(s, "#%02hhX%02hhX%02hhX", &rgb.r, &rgb.g, &rgb.b);
1409 return rgb;
1410}
1411/** @brief Get the RGB components of a color from the UI color palette.
1412 * @param color The index of the color in the UI color palette.
1413 * @param r Pointer to store the red component of the color.
1414 * @param g Pointer to store the green component of the color.
1415 * @param b Pointer to store the blue component of the color.
1416 * @return 0 on success, -1 on error (if the color index is out of bounds).
1417 *
1418 * This function retrieves the RGB components of a color from the UI color
1419 * palette. It checks if the specified color index is valid and then fills
1420 * in the provided pointers with the corresponding RGB values. If the color
1421 * index is out of bounds, it returns -1.
1422 */
1423int ui_color_content(uint16_t color, uint8_t *r, uint8_t *g, uint8_t *b) {
1424 if (color + 1 >= UI_COLORS)
1425 return -1;
1426 *r = ui_color[color].r;
1427 *g = ui_color[color].g;
1428 *b = ui_color[color].b;
1429 return 0;
1430}
1431/** @brief Initialize a color in the UI color palette with specified RGB components.
1432 * @param color The index of the color to initialize in the UI color palette.
1433 * @param r The red component of the color (0-255).
1434 * @param g The green component of the color (0-255).
1435 * @param b The blue component of the color (0-255).
1436 * @return 0 on success, -1 on error (if the color index is out of bounds).
1437 *
1438 * This function initializes a color in the UI color palette with specified
1439 * RGB components. It checks if the specified color index is valid and then
1440 * sets the corresponding RGB values in the ui_color array. If the color index
1441 * is out of bounds, it returns -1.
1442 */
1443int ui_init_color(uint16_t color, uint8_t r, uint8_t g, uint8_t b) {
1444 if (color + 1 >= UI_COLORS)
1445 return -1;
1446 ui_color[color].r = r;
1447 ui_color[color].g = g;
1448 ui_color[color].b = b;
1449 return 0;
1450}
1451/** @brief Get the foreground and background color indices for a given color pair index.
1452 * @param pair The color pair index.
1453 * @param fg Pointer to store the foreground color index.
1454 * @param bg Pointer to store the background color index.
1455 * @return 0 on success, -1 on error (if the pair index is out of bounds).
1456 *
1457 * This function retrieves the foreground and background color indices for a
1458 * given color pair index. It checks if the specified pair index is valid and
1459 * then fills in the provided pointers with the corresponding foreground and
1460 * background color indices. If the pair index is out of bounds, it returns -1.
1461 */
1462int ui_pair_content(uint16_t pair, uint *fg, uint *bg) {
1463 if (pair + 1 >= UI_PAIRS)
1464 return -1;
1465 *fg = ui_pair[pair].fg;
1466 *bg = ui_pair[pair].bg;
1467 return 0;
1468}
1469/** @brief Initialize a color pair in the UI color pair palette with specified foreground and background colors.
1470 * @param pair The index of the color pair to initialize in the UI color pair palette.
1471 * @param fg The foreground color index for the color pair.
1472 * @param bg The background color index for the color pair.
1473 * @return 0 on success, -1 on error (if the pair index is out of bounds).
1474 *
1475 * This function initializes a color pair in the UI color pair palette with
1476 * specified foreground and background colors. It checks if the specified
1477 * pair index is valid and then sets the corresponding foreground and background
1478 * color indices in the ui_pair array. If the pair index is out of bounds,
1479 * it returns -1.
1480 */
1481int ui_init_pair(uint16_t pair, uint fg, uint bg) {
1482 if (pair + 1 >= UI_PAIRS)
1483 return -1;
1484 ui_pair[pair].fg = fg;
1485 ui_pair[pair].bg = bg;
1486 return 0;
1487}
1488/** @brief Change the color at a specified index in the UI color palette.
1489 * @param color_idx The index of the color to change in the UI color palette.
1490 * @param color Pointer to a 32-bit unsigned integer representing the new color value.
1491 * @return 0 on success, -1 on error (if the color index is out of bounds).
1492 *
1493 * This function changes the color at a specified index in the UI color palette.
1494 * It applies gamma correction to the new color value and updates both the
1495 * standard and UI color arrays with the new RGB components. If the color index
1496 * is out of bounds, it returns -1.
1497 */
1498int ui_chg_color(uint16_t color_idx, uint32_t *color) {
1499 RGB rgb;
1500 rgb.color = *color;
1501 if (color_idx + 1 >= UI_COLORS)
1502 return -1;
1503 ui_apply_gamma(&rgb);
1504 if (color_idx < 16) {
1505 std_color[color_idx].r = rgb.r;
1506 std_color[color_idx].g = rgb.g;
1507 std_color[color_idx].b = rgb.b;
1508 }
1509 ui_color[color_idx].r = rgb.r;
1510 ui_color[color_idx].g = rgb.g;
1511 ui_color[color_idx].b = rgb.b;
1512 return 0;
1513}
1514/* -------------------------------------------------------------------------
1515 Non-portable escape-hatch getters (see ui_notcurses_compat.h)
1516 ------------------------------------------------------------------------- */
1517/** @brief Get the pointer to the Notcurses context associated with the UI.
1518 * @return A pointer to the Notcurses context, or NULL if the UI is not initialized.
1519 *
1520 * This function retrieves the pointer to the Notcurses context associated
1521 * with the UI. If the UI is not initialized, it returns NULL.
1522 */
1523struct notcurses *ui_notcurses_get_nc() {
1524 if (!ui)
1525 return NULL;
1526 return ui->nc;
1527}
1528/** @brief Get the pointer to the NcPlane associated with a specific window in a UI surface.
1529 * @param s Pointer to the UiSurface containing the window.
1530 * @param w The index of the window within the surface.
1531 * @return A pointer to the NcPlane associated with the specified window, or NULL if the surface is not initialized.
1532 *
1533 * This function retrieves the pointer to the NcPlane associated with a specific
1534 * window in a UI surface. If the surface is not initialized, it returns NULL.
1535 */
1536NcPlane *ui_notcurses_surface_get_plane(const UiSurface *s, ss_t w) {
1537 (void)w;
1538 if (!s)
1539 return NULL;
1540 return s->mplane[w];
1541}
1542// -------------------------------------------------------------------------
1543// Multibyte conversion
1544// -------------------------------------------------------------------------
1545/** ui__mbstr_to_cellstr
1546 @brief Convert multibyte string to complex character array (Notcurses version)
1547 @ingroup UiChyron
1548 @param cmplx_buf Output buffer for complex characters
1549 @param str Input multibyte string
1550 @param cell_base Base cell for attributes and color pair
1551 @param p Pointer to current position in the output buffer, updated as
1552 characters are added
1553 @param atmost Maximum length of the output buffer
1554 @return Number of bytes processed from the input string
1555 @details This function is a specialized version of ui_mbstr_to_cellstr for use
1556 with NCurses. It converts a multibyte string to an array of complex characters
1557 (cchar_t) that can be used with NCurses functions. It handles multibyte
1558 characters and applies the attributes and color pair from the base cell to each
1559 character. The p parameter is updated to reflect the current position in the
1560 output buffer, and the function ensures that it does not exceed the maximum
1561 length specified by atmost. */
1562uint ui_mbstr_to_cellstr(UiSurface *sfc, ss_t w, UiCell *cmplx_buf, const char *str, const UiCell *cell_base, uint *p, const uint atmost) {
1563 short cp;
1564 uint p1 = 0;
1565 uint *pos = &p1;
1566 if (p)
1567 pos = p;
1568 uint i = 0, len = 0;
1569 const char *s;
1570 attr_t style;
1571 UiCell cc;
1572 wchar_t wstr[5];
1573 ui_get_nccell(sfc, w, cell_base, &wstr[0], &style, &cp);
1574 mbstate_t mbstate;
1575 memset(&mbstate, 0, sizeof(mbstate));
1576 if (pos && *pos >= atmost - 1)
1577 return 0;
1578 while (str[i] != '\0') {
1579 s = &str[i];
1580 len = mbrtowc(wstr, s, MB_CUR_MAX, &mbstate);
1581 if (len <= 0) {
1582 wstr[0] = L'?';
1583 wstr[1] = L'\0';
1584 len = 1;
1585 }
1586 wstr[1] = L'\0';
1587 if (*pos > atmost)
1588 break;
1589 if (ui_set_nccell(sfc, w, &cc, wstr, style, cp) != ERR) {
1590 if (len > 0 && (*pos + len) < atmost)
1591 cmplx_buf[(*pos)++] = cc;
1592 }
1593 i += len;
1594 }
1595 wstr[0] = L'\0';
1596 wstr[1] = L'\0';
1597 ui_set_nccell(sfc, w, &cc, wstr, style, cp);
1598 cmplx_buf[*pos] = cc;
1599 return *pos;
1600}
#define min(x, y)
min macro evaluates two expressions, returning least result
Definition cm.h:104
int ui_border_draw(UiSurface *sfc)
Definition ui_common.c:474
int ui_surface_resize(UiSurface *s, ss_t w, uint lines, uint cols)
Resize a UiSurface to new dimensions.
Definition ui_ncurses.c:536
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.
Definition ui_ncurses.c:395
const wchar_t * border_none
Definition ui_common.c:72
UiRuntime * ui_init(const UiConfig *config, SIO *sio)
Initialize the UI runtime with the given configuration and SIO.
Definition ui_ncurses.c:129
void ui_render()
Render the UI by updating panels and refreshing the display.
Definition ui_ncurses.c:884
void ui_getyx(UiSurface *s, ss_t w, uint *lines, uint *cols)
Get the current cursor position within a window of a UI surface.
Definition ui_ncurses.c:675
UiCell cell_nt
Definition ui_common.c:106
char em1[MAXLEN]
Definition ui_common.c:47
int ui_setscrreg(UiSurface *s, ss_t w, uint top, uint bottom)
Set the scrolling region for a UiSurface.
Definition ui_ncurses.c:820
int ui_wmove(UiSurface *s, ss_t w, uint y, uint x)
Move the cursor to a specified position within a UiSurface.
Definition ui_ncurses.c:653
void ui_getmaxyx(UiSurface *s, ss_t w, uint *lines, uint *cols)
Get the maximum dimensions of a UiSurface.
Definition ui_ncurses.c:690
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.
Definition ui_ncurses.c:855
char em2[MAXLEN]
Definition ui_common.c:48
int ui_wscrl(UiSurface *s, ss_t w, int rows)
Scroll the contents of a UiSurface by a specified number of lines.
Definition ui_ncurses.c:738
int ui_idcok(UiSurface *s, ss_t w, bool enable)
Enable or disable the use of the insert/delete character capabilities for a UiSurface.
Definition ui_ncurses.c:803
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.
Definition ui_ncurses.c:369
BorderWide bw
Definition ui_common.c:27
int ui_cursor_move(UiSurface *s, ss_t w, uint y, uint x)
Move the cursor to a specified position within a UiSurface.
Definition ui_ncurses.c:666
#define UI_SFC_MAX
Definition ui_backend.h:196
#define UI_PAIRS
Definition ui_backend.h:194
int ui_suspend()
Suspend the UI, saving the current program state and ending the window session.
Definition ui_ncurses.c:494
void ui_surface_destroy(UiSurface *s)
Destroy a UiSurface, cleaning up its windows and panels.
Definition ui_ncurses.c:468
@ SUB_SFC_MAX
Definition ui_backend.h:47
int ui_border_title(UiSurface *sfc, const char *title)
Draw a box with a title around the specified window.
Definition ui_common.c:563
void ui_update_panels()
Update the panels in the UI.
Definition ui_ncurses.c:890
int ui_bkgd(UiSurface *s, ss_t w, const UiCell *cell)
Set the background of a specific window within a UiSurface.
Definition ui_ncurses.c:927
#define ERR
Definition ui_backend.h:427
int ui_idlok(UiSurface *s, ss_t w, bool enable)
Enable or disable the use of the insert/delete line capabilities for a UiSurface.
Definition ui_ncurses.c:787
const wchar_t * border_double
Definition ui_common.c:69
int ui_surface_move(UiSurface *s, ss_t w, uint y, uint x)
Move a UiSurface to a new position on the screen.
Definition ui_ncurses.c:521
int ui_getmaxy(UiSurface *s, ss_t w)
Get the maximum number of lines (rows) of a UiSurface.
Definition ui_ncurses.c:701
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.
Definition ui_ncurses.c:288
const wchar_t * border_single
Definition ui_common.c:68
void ui_get_screen_size(uint *lines, uint *cols)
Get the current screen size (number of lines and columns).
Definition ui_ncurses.c:722
int ui_surface_show(UiSurface *s, ss_t w)
Show a UiSurface, making it visible on the screen.
Definition ui_ncurses.c:609
int ui_erase()
Erase the entire screen.
Definition ui_ncurses.c:591
void ui_shutdown()
Shutdown the UI runtime, cleaning up resources and freeing memory.
Definition ui_ncurses.c:418
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.
Definition ui_ncurses.c:229
void ui_initialize_sio(SIO *sio)
Definition ui_common.c:182
UiSurface * stdsfc
Definition ui_ncurses.c:46
int sfc_ptr
Definition ui_ncurses.c:42
int ui_curs_set(int visibility)
Set the visibility of the cursor.
Definition ui_ncurses.c:840
int ui_resume()
Resume the UI, restoring the previous program state and updating the display.
Definition ui_ncurses.c:503
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.
Definition ui_ncurses.c:969
int ui_top_surface(UiSurface *s, ss_t w)
Hide a UiSurface, making it invisible on the screen.
Definition ui_ncurses.c:623
int ui_wclear(UiSurface *s, ss_t w)
Clear the contents of a UiSurface or all surfaces.
Definition ui_ncurses.c:571
char em0[MAXLEN]
Definition ui_common.c:46
void ui_endwin()
End the UI application, cleaning up resources and shutting down the UI runtime.
Definition ui_ncurses.c:412
int ui_cursor_enable(UiSurface *s, ss_t w, bool visible)
Enable or disable the cursor for a UiSurface.
Definition ui_ncurses.c:870
int ui_clear()
Clear the entire screen.
Definition ui_ncurses.c:599
int ui_getmaxx(UiSurface *s, ss_t w)
Get the maximum number of columns of a UiSurface.
Definition ui_ncurses.c:712
const wchar_t * border_heavy
Definition ui_common.c:71
int ui_surface_hide(UiSurface *s, ss_t w)
Hide a UiSurface, making it invisible on the screen.
Definition ui_ncurses.c:635
bool f_notcurses_open
Definition ui_common.c:51
const wchar_t * border_rounded
Definition ui_common.c:70
int ui_bkgrnd(UiSurface *s, ss_t w, const UiCell *cell)
Set the background of a specific window within a UiSurface.
Definition ui_ncurses.c:955
int ui_scrollok(UiSurface *s, ss_t w, bool enable)
Enable or disable scrolling for a UiSurface.
Definition ui_ncurses.c:755
uint16_t UiStyle
Definition ui_backend.h:158
#define UI_COLORS
Definition ui_backend.h:193
void ui_get_caps(UiCaps *caps)
Get the UI backend capabilities.
Definition ui_ncurses.c:62
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.
Definition ui_ncurses.c:941
int ui_werase(UiSurface *s, ss_t w)
Erase the contents of a UiSurface or all surfaces.
Definition ui_ncurses.c:551
@ UI_BACKEND_NOTCURSES
Definition ui_backend.h:453
UiCell cell_box
Definition ui_common.c:110
int ui_keypad(UiSurface *s, ss_t w, bool enable)
Enable or disable the keypad for a UiSurface.
Definition ui_ncurses.c:771
#define WA_NORMAL
#define XLEN
int ui_get_pair(uint16_t pair, uint *fg, uint *bg)
Get the foreground and background color indices for a given color pair index.
void ui_abs_yx(UiSurface *s, ss_t w, int *y, int *x)
Get the absolute cursor position within a window of a UI surface.
UiPair * ui_pair
UiConfig * ui_config
UiCell bkgd_cell
uint ui_init_color_hex(char *s)
Initialize a color from a hexadecimal string representation.
UiColor * ui_color
struct notcurses * ui_notcurses_get_nc()
Get the pointer to the Notcurses context associated with the UI.
NcPlane * stdplane
int ui_get_nccell(UiSurface *sfc, ss_t w, const UiCell *cell, wchar_t *wstr, UiStyle *style, short *pair)
Get the properties of a cell at the current cursor position in a window of a UI surface.
uint64_t ui_get_channels_from_pair(uint16_t pair)
Get the combined foreground and background color channels for a given color pair index.
int ui_set_nccell(UiSurface *sfc, ss_t w, UiCell *cell, const wchar_t *wstr, const UiStyle style, short pair)
Set the properties of a cell at the current cursor position in a window of a UI surface.
void ui_cursor_yx(int *y, int *x)
Get the current cursor position within a window of a UI surface.
NcPlane * ui_notcurses_surface_get_plane(const UiSurface *s, ss_t w)
Get the pointer to the NcPlane associated with a specific window in a UI surface.
STDRGB std_color[]
Definition ui_common.c:159
UiLogLevel ui_min_log_level
Definition ui_common.c:1390
void ui_apply_gamma(RGB *rgb)
Apply gamma correction to RGB color.
Definition ui_common.c:941
int ui_pair_content(uint pair, uint *fg, uint *bg)
Get the foreground and background colors of a specified color pair.
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]
Definition ui_ncurses.c:40
int ui_color_content(uint color, uint *r, uint *g, uint *b)
UiRuntime * ui
Definition ui_ncurses.c:39
RGB ui_hex_to_rgb(char *s)
Convert a hexadecimal color string to an RGB structure.
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.
Definition ui_ncurses.c:101
uint ui_pair_cnt
Definition ui_ncurses.c:44
uint ui_color_cnt
Definition ui_ncurses.c:43
void ui_def_prog_mode()
Definition ui_ncurses.c:826
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.
#define MAXLEN
Definition curskeys.c:15
#define _(String)
Definition amort.c:23
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition whence.c:291
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition futil.c:390
int ui_display_error(char *msg0, char *msg1, char *msg2, char *msg3)
Display an error message window or print to stderr.
Definition ui_common.c:1200
UiBackend ui_get_backend()
Get the UI backend type.
Definition ui_ncurses.c:55
wchar_t w32
Definition ui_backend.h:122
uint32_t u32
Definition ui_backend.h:121
UiBorderStyle border_style
Definition ui_backend.h:445
UiLogLevel log_level
Definition ui_backend.h:447
bool palette256
Definition ui_backend.h:458
bool mouse
Definition ui_backend.h:459
int color_pairs
Definition ui_backend.h:462
bool truecolor
Definition ui_backend.h:457
bool unicode
Definition ui_backend.h:460
bool resize
Definition ui_backend.h:461
wchar_t str[11]
Definition ui_backend.h:563