C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
dwin.c
Go to the documentation of this file.
1/** @file dwin.c
2 @brief Window support for C-Menu - EXPERIMENTAL
3 @details This file contains functions for managing NCurses windows and color
4 settings for the Chyron structure for function key labels and mouse click
5 handling. This file is a work in progress and may be subject to change as the
6 C-Menu project evolves. Generally, don't try to use it yet unless you want
7 complete the half-done code modifications.
8 @author Bill Waller
9 Copyright (c) 2025
10 MIT License
11 billxwaller@gmail.com
12 @date 2026-02-09
13 */
14
15/** @defgroup window_support Window Support
16 @brief Manage NCurses windows and color settings
17 */
18
19#include "include/ui_backend.h"
20#include "ui/ui_ncurses_internal.h"
21#include <cm.h>
22#include <errno.h>
23#include <fcntl.h>
24#include <math.h>
25#include <stdlib.h>
26#include <string.h>
27#include <sys/ioctl.h>
28#include <sys/stat.h>
29#include <sys/types.h>
30#include <termios.h>
31#include <unistd.h>
32#include <wchar.h>
33
34#define NC true
35
37 WF_BOX = 0b00000001,
38 WF_WIN = 0b00000010,
39 WF_WIN2 = 0b00000100
40};
41
42SCREEN *screen;
43FILE *tty_fp;
44UiRuntime *ui_runtime;
45UiConfig *ui_config;
46UiSurface *ui_box[MAXWIN];
47UiSurface *ui_win[MAXWIN];
48UiSurface *ui_win2[MAXWIN];
49UiRect ui_rect;
50
51WINDOW *win_win2[MAXWIN]; /**< array of pointers to windows */
52WINDOW *win_win[MAXWIN]; /**< array of pointers to windows */
53WINDOW *win_box[MAXWIN]; /**< array of pointers to box windows */
54
58
59void ui_rect_set(UiRect *, int, int, int, int);
60int win2_new(int wlines, int wcols, int wbegy, int wbegx);
61bool open_curses(SIO *);
62bool init_clr_palette(SIO *);
63void destroy_curses();
64int box_new(int, int, int, int, char *);
65int box_hsplit_new(int, int, int, int, int, char *);
66int border_draw(WINDOW *);
67int border_hsplit(WINDOW *, int);
68int border_hsplit_text(WINDOW *, char *, int);
69
70int win_new(int, int);
71void win_redraw(WINDOW *);
72void win_resize(int, int, char *);
73void win_del();
74void restore_wins();
75void win_init_attrs();
76void mvwaddstr_fill(WINDOW *, int, int, char *, int);
77void abend(int, char *);
78int nf_error(int, char *);
79int Perror(char *);
82WINDOW *win_main;
84void list_colors();
85int clr_name_to_idx(char *);
86void init_hex_clr(int, char *);
87RGB hex_clr_str_to_rgb(char *);
88RGB xterm256_idx_to_rgb(int);
89int rgb_to_curses_clr(RGB *);
90int rgb_to_xterm256_idx(RGB *);
91void apply_gamma(RGB *);
92
93Chyron *new_chyron();
94void set_chyron_key(Chyron *, int, char *, int);
95void set_chyron_key_cp(Chyron *, int, char *, int, int);
96bool is_set_chyron_key(Chyron *, int);
97void unset_chyron_key(Chyron *, int);
98void compile_chyron(Chyron *);
99int get_chyron_key(Chyron *, int);
100Chyron *destroy_chyron(Chyron *chyron);
101Chyron *wait_mk_chyron();
102
103int mb_to_cc(cchar_t *, char *, attr_t, int, int *, int);
104void initialize_local_colors(SIO *);
105
106int wait_continue(WINDOW *, Chyron *, int);
107bool wait_destroy(Chyron *);
108int xwgetch(WINDOW *, Chyron *, int);
109cchar_t mkcc(int, attr_t, const char *);
110void activate_chyron_key(Chyron *chyron, int k);
111void activate_all_chyron_keys(Chyron *chyron);
112void deactivate_chyron_key(Chyron *chyron, int k);
113void deactivate_all_chyron_keys(Chyron *chyron);
114void check_panels(int);
115int bare_box_new(int, int, int, int, char *);
116int win2_box_new(int, int, int, int, char *);
117
118WINDOW *mouse_win;
119WINDOW *wait_mk_win(Chyron *, char *);
120// SIO *sio; /**< Global pointer to SIO struct for terminal and color settings
121
122cchar_t ls, rs, ts, bs, tl, tr, bl, br, lt, rt, sp, ra, la, ua, da, ran, chk;
123
124/** StdColors
125 @details Standard 16 colors for xterm256 color conversions These colors can
126 be overridden in ".minitrc" */
127RGB StdColors[16] = {
128 {0, 0, 0}, {128, 0, 0}, {0, 128, 0}, {128, 128, 0}, {0, 0, 128}, {128, 0, 128}, {0, 128, 128}, {192, 192, 192}, {128, 128, 128}, {255, 0, 0}, {0, 255, 0}, {255, 255, 0}, {0, 0, 255}, {255, 0, 255}, {0, 255, 255}, {255, 255, 255}};
129/** colors_text
130 @brief Color names for .minitrc overrides
131 @details These names are used in .minitrc to specify color overrides The
132 order of these names corresponds to the ColorsEnum values */
133char const colors_text[][10] = {
134 "black", "red", "green", "yellow", "blue", "magenta", "cyan",
135 "white", "orange", "bg", "abg", "bblack", "bred", "bgreen",
136 "byellow", "bblue", "bcyan", "bmagenta", "bwhite", "borange", ""};
137
138const wchar_t bw_ho = BW_HO; /**< horizontal line */
139const wchar_t bw_ve = BW_VE; /**< vertical line */
140const wchar_t bw_tl = BW_RTL; /**< top left corner */
141const wchar_t bw_tr = BW_RTR; /**< top right corner */
142const wchar_t bw_bl = BW_RBL; /**< bottom left corner */
143const wchar_t bw_br = BW_RBR; /**< bottom right corner */
144const wchar_t bw_lt = BW_LT; /**< left tee */
145const wchar_t bw_rt = BW_RT; /**< right tee */
146const wchar_t bw_sp = BW_SP; /**< tee space */
147const wchar_t bw_ra = BW_RA; /**< right arrow */
148const wchar_t bw_la = BW_LA; /**< right arrow */
149const wchar_t bw_ua = BW_UA; /**< right arrow */
150const wchar_t bw_da = BW_DA; /**< right arrow */
151const wchar_t bw_ran = BW_RAN; /**< right angle */
152const wchar_t bw_chk = BW_CHK; /**< right angle */
153
154double GRAY_GAMMA = 1.2; /**< Gamma correction value for gray colors. Set in .minitrc */
155double RED_GAMMA = 1.2; /**< Gamma correction value for red colors. Set in .minitrc */
156double GREEN_GAMMA = 1.2; /**< Gamma correction value for green colors. Set in .minitrc */
157double BLUE_GAMMA = 1.2; /**< Gamma correction value for blue colors. Set in .minitrc */
158
160unsigned int cmd_key;
161bool f_sigwench = false;
167int m_begy = -1;
168int m_begx = -1;
174char fn[MAXLEN];
195int clr_cnt = 0;
198cchar_t CC_BG;
199cchar_t CC_BOX;
200cchar_t CC_IND;
201cchar_t CC_LN;
202cchar_t CC_CMDLN;
203cchar_t CC_TITLE;
204cchar_t CC_NT;
205cchar_t CC_NT_REV;
207cchar_t CC_NT_HL;
208cchar_t CC_NORM;
209cchar_t CC_BRKTL;
210cchar_t CC_BRKTR;
212cchar_t CC_CHK;
213cchar_t CC_RAN;
214cchar_t CC_RED;
215cchar_t CC_GREEN;
216cchar_t CC_YELLOW;
217cchar_t CC_BLUE;
218/** Global file/pipe numbers */
220
221/** @brief Initialize window attributes
222 @ingroup window_support
223 @details This function initializes color pairs for the window
224 cp_nt, and cp_box are global variables
225 */
227 return;
228}
229
230/** open_curses
231 @brief Initialize NCurses and color settings
232 @ingroup window_support
233 @param sio Pointer to SIO struct with terminal and color settings
234 @return true if successful, false if error
235 @details This function initializes NCurses and sets up color pairs based on
236 the settings in the SIO struct. It also applies gamma correction to colors.
237 Use this function to initialize NCurses if you don't want NCurses to receive
238 data from the stdin pipe
239 @code
240 1. saves stdin and stdout file descriptors in SIO
241 2. opens a terminal device for NCurses screen IO
242 3. replaces STDERR_FILENO with terminal file descriptor
243 @endcode */
244bool open_curses(SIO *sio) {
245 char tmp_str[MAXLEN];
246 char emsg0[MAXLEN];
247
248 // Get the name of the terminal device
249 sio->stdin_fd = dup(STDIN_FILENO);
250 sio->stdout_fd = dup(STDOUT_FILENO);
251 sio->stderr_fd = dup(STDERR_FILENO);
252 if (ttyname_r(STDERR_FILENO, sio->tty_name, sizeof(sio->tty_name)) != 0) {
253 strerror_r(errno, tmp_str, MAXLEN - 1);
254 strnz__cpy(emsg0, "ttyname_r failed ", MAXLEN - 1);
255 strnz__cat(emsg0, tmp_str, MAXLEN - 1);
256 fprintf(stderr, "%s\n", tmp_str);
257 exit(0);
258 }
259 // open the terminal device for NCurses input and output
260 tty_fp = fopen(sio->tty_name, "r+");
261 if (tty_fp == nullptr) {
262 strerror_r(errno, tmp_str, MAXLEN - 1);
263 strnz__cpy(emsg0, "fopen(sio->tty_name) failed ", MAXLEN - 1);
264 strnz__cat(emsg0, tmp_str, MAXLEN - 1);
265 fprintf(stderr, "%s\n", tmp_str);
266 exit(0);
267 }
268 // newterm() allows us to specify a tty device for NCurses input and
269 // output.
270 screen = newterm(nullptr, tty_fp, tty_fp);
271 if (screen == nullptr) {
272 strerror_r(errno, tmp_str, MAXLEN - 1);
273 strnz__cpy(emsg0, "newterm failed ", MAXLEN - 1);
274 strnz__cat(emsg0, tmp_str, MAXLEN - 1);
275 fprintf(stderr, "%s\n", tmp_str);
276 exit(0);
277 }
278 set_term(screen);
279 f_curses_open = true;
280 if (!has_colors()) {
282 abend(-1, "Terminal color support required");
283 }
284 start_color();
285 if (!can_change_color()) {
287 fprintf(stderr, "Terminal cannot change colors\n");
288 fprintf(stderr, "Check TERM environment variable\n");
289 fprintf(stderr, "Check terminfo for missing \"ccc\"\n");
290 abend(-1, "fatal error");
291 }
292 panel_main = new_panel(stdscr);
293 noecho();
294 keypad(stdscr, true);
295 idlok(stdscr, false);
296 idcok(stdscr, false);
297 wbkgrnd(stdscr, &CC_NORM);
298 for (win_ptr = 0; win_ptr < MAXWIN; win_ptr++) {
299 panel_box[win_ptr] = nullptr;
300 ui_win[win_ptr] = nullptr;
301 ui_win2[win_ptr] = nullptr;
302 ui_box[win_ptr] = nullptr;
303 win_win[win_ptr] = nullptr;
304 win_win2[win_ptr] = nullptr;
305 win_box[win_ptr] = nullptr;
306 }
307 win_ptr = -1;
308 return sio;
309}
310/** @brief Initialize local color variables and color pairs based on SIO settings
311 @ingroup color_management
312 @param sio Pointer to SIO struct with color settings
313 @details This function initializes local color variables and color pairs
314 based on the settings in the SIO struct. It applies gamma correction to
315 colors and sets up cchar_t variables for use in NCurses functions. The color
316 pair indices are stored in global variables for easy reference throughout the
317 code when applying colors to various parts of the interface using NCurses
318 functions that accept color pair indices.
319 */
321 /** gamma correction values */
322 /** These are read from ~/.minitrc */
323 /** used when initializing colors */
329
330 // Color Pairs
331 // Often used standardized color pairs for the user interface
348
349 // cchar_t For setting backgrounds
350 // with attributes and color pairs
351 CC_FILL_CHAR = mkcc(cp_fill_char, WA_NORMAL, " ");
352 CC_BRKTL = mkcc(cp_brackets, WA_NORMAL, " ");
353 CC_BRKTR = mkcc(cp_brackets, WA_NORMAL, " ");
354 CC_NT = mkcc(cp_nt, WA_NORMAL, " ");
355 CC_NT_REV = mkcc(cp_nt_rev, WA_NORMAL, " ");
356 CC_NT_HL_REV = mkcc(cp_nt_hl_rev, WA_NORMAL, " ");
357 CC_NT_HL = mkcc(cp_nt_hl, WA_NORMAL, " ");
358 CC_BOX = mkcc(cp_box, WA_NORMAL, " ");
359 CC_IND = mkcc(cp_ind, WA_NORMAL, " ");
360 CC_CMDLN = mkcc(cp_cmdln, WA_NORMAL, " ");
361 CC_TITLE = mkcc(cp_title, WA_NORMAL, " ");
362 CC_LN = mkcc(cp_ln, WA_NORMAL, " ");
363 CC_NORM = mkcc(cp_norm, WA_NORMAL, " ");
364 CC_RAN = mkcc(cp_ind, WA_NORMAL, " ");
365 CC_CHK = mkcc(cp_ind, WA_NORMAL, " ");
366 CC_RED = mkcc(cp_red, WA_NORMAL, " ");
367 CC_GREEN = mkcc(cp_green, WA_NORMAL, " ");
368 CC_YELLOW = mkcc(cp_yellow, WA_NORMAL, " ");
369 CC_BLUE = mkcc(cp_blue, WA_NORMAL, " ");
370
371 // cchar_t For borders and indicators
372 // with attributes and color pairs
373 setcchar(&ls, &bw_ve, WA_NORMAL, cp_box, NULL); // Left side
374 setcchar(&rs, &bw_ve, WA_NORMAL, cp_box, NULL); // Right side
375 setcchar(&ts, &bw_ho, WA_NORMAL, cp_box, NULL); // Top side
376 setcchar(&bs, &bw_ho, WA_NORMAL, cp_box, NULL); // Bottom side
377 setcchar(&tl, &bw_tl, WA_NORMAL, cp_box, NULL); // Top-left corner
378 setcchar(&tr, &bw_tr, WA_NORMAL, cp_box, NULL); // Top-right corner
379 setcchar(&bl, &bw_bl, WA_NORMAL, cp_box, NULL); // Bottom-left corner
380 setcchar(&br, &bw_br, WA_NORMAL, cp_box, NULL); // Bottom-right corner
381 setcchar(&lt, &bw_lt, WA_NORMAL, cp_box, NULL); // Left tee
382 setcchar(&rt, &bw_rt, WA_NORMAL, cp_box, NULL); // Right tee
383 setcchar(&sp, &bw_sp, WA_NORMAL, cp_box, NULL); // Space
384 setcchar(&ra, &bw_ra, WA_NORMAL, cp_box, NULL); // Right arrow
385 setcchar(&la, &bw_la, WA_NORMAL, cp_box, NULL); // Left arrow
386 setcchar(&ua, &bw_ua, WA_NORMAL, cp_box, NULL); // Up arrow
387 setcchar(&da, &bw_da, WA_NORMAL, cp_box, NULL); // Down arrow
388 setcchar(&ran, &bw_ran, WA_NORMAL, cp_ind, NULL); // Right angle
389 setcchar(&chk, &bw_chk, WA_NORMAL, cp_ind, NULL); // Right angle
390}
391/** @defgroup color_management Color Management
392 @brief Conversion of Color Data Types and Management of Colors and Color
393 Pairs
394 */
395/** get_clr_pair
396 @brief Get color pair index for foreground and background colors
397 @ingroup color_management
398 @param fg Foreground color index
399 @param bg Background color index
400 @return Color pair index */
401int get_clr_pair(int fg, int bg) {
402 int rc, i, pfg, pbg;
403 for (i = 1; i < clr_pair_cnt; i++) {
404 extended_pair_content(i, &pfg, &pbg);
405 if (pfg == fg && pbg == bg)
406 return i;
407 }
408 if (i >= COLOR_PAIRS) {
409 ssnprintf(em0, MAXLEN - 1, "%s, line: %d", __FILE__, __LINE__ - 1);
410 ssnprintf(em1, MAXLEN - 1, "NCurses COLOR_PAIRS (%d) exceeded (%d)",
411 COLOR_PAIRS, i);
412 strerror_r(errno, em2, MAXLEN);
414 return (EXIT_FAILURE);
415 }
416 if (i < COLOR_PAIRS) {
417 rc = init_extended_pair(i, fg, bg);
418 if (rc == ERR)
419 return ERR;
420 }
421 if (i < COLOR_PAIRS)
422 clr_pair_cnt++;
423 return i;
424}
425/** rgb_to_curses_clr
426 @brief Get color index for RGB color
427 @ingroup color_management
428 @param rgb RGB color
429 @return NCurses color index
430 @details Curses uses 0-1000 for RGB values. If the color does not exist, it
431 is created along with a new color index */
432int rgb_to_curses_clr(RGB *rgb) {
433 int i;
434 int r, g, b;
435 apply_gamma(rgb);
436 rgb->r = (rgb->r * 1000) / 255;
437 rgb->g = (rgb->g * 1000) / 255;
438 rgb->b = (rgb->b * 1000) / 255;
439 for (i = 0; i < clr_cnt; i++) {
440 extended_color_content(i, &r, &g, &b);
441 if (rgb->r == r && rgb->g == g && rgb->b == b) {
442 return i;
443 }
444 }
445 if (i < COLORS) {
446 init_extended_color(i, rgb->r, rgb->g, rgb->b);
447 clr_cnt++;
448 return clr_cnt - 1;
449 }
450 return ERR;
451}
452/** rgb_to_xterm256_idx
453 @brief Convert RGB color to XTerm 256 color index
454 @ingroup color_management
455 @param rgb RGB color
456 @return XTerm 256 color index
457 @details This function converts an RGB color to the nearest XTerm 256 color
458 index. It first checks if the color is a shade of gray, and if so, it uses
459 the gray ramp. Otherwise, it calculates the nearest color in the 6x6x6 color
460 cube. */
461int rgb_to_xterm256_idx(RGB *rgb) {
462 if (rgb->r == rgb->g && rgb->g == rgb->b) {
463 if (rgb->r < 8)
464 return 16;
465 if (rgb->r > 248)
466 return 231;
467 return ((rgb->r - 8) / 10) + 231;
468 } else {
469 int r_index = (rgb->r < 45) ? 0 : (rgb->r - 60) / 40 + 1;
470 int g_index = (rgb->g < 45) ? 0 : (rgb->g - 60) / 40 + 1;
471 int b_index = (rgb->b < 45) ? 0 : (rgb->b - 60) / 40 + 1;
472 return 16 + (36 * r_index) + (6 * g_index) + b_index;
473 }
474}
475/** xterm256_idx_to_rgb
476 @brief Convert XTerm 256 color index to RGB
477 @ingroup color_management
478 @param idx XTerm 256 color index
479 @return RGB color
480 @details This function converts an XTerm 256 color index to an RGB color. It
481 first checks if the index is in the standard 16 colors, then checks if it's
482 in the 6x6x6 color cube, and finally checks if it's in the gray ramp. */
484 /** Convert XTerm 256 color index to RGB
485 @param idx - XTerm 256 color index
486 @return RGB struct */
487 RGB rgb;
488 if (idx > 255)
489 idx = 255;
490 if (idx < 0)
491 idx = 0;
492 rgb.r = rgb.g = rgb.b = 0;
493 if (idx < 16) {
494 rgb.r = StdColors[idx].r;
495 rgb.g = StdColors[idx].g;
496 rgb.b = StdColors[idx].b;
497 } else if (idx >= 16 && idx <= 231) {
498 idx -= 16;
499 rgb.r = (idx / 36) % 6 * 51;
500 rgb.g = (idx / 6) % 6 * 51;
501 rgb.b = (idx % 6) * 51;
502 } else if (idx >= 232 && idx <= 255) {
503 int gray = (idx - 232) * 11;
504 rgb.r = rgb.g = rgb.b = gray;
505 }
506 return rgb;
507}
508
509/** apply_gamma
510 @brief Apply gamma correction to RGB color
511 @ingroup color_management
512 @param rgb Pointer to RGB color
513 @details This function modifies the RGB color in place. It applies gamma
514 correction to the RGB color based on the gamma values set in the SIO struct.
515 If the color is a shade of gray, it applies the gray gamma correction.
516 Otherwise, it applies the individual red, green, and blue gamma corrections.
517 */
518void apply_gamma(RGB *rgb) {
519 if (rgb->r == rgb->g && rgb->r == rgb->b) {
520 if (GRAY_GAMMA > 0.0f && GRAY_GAMMA != 1.0f) {
521 rgb->r = (int)(pow((rgb->r / 255.0f), 1.0f / GRAY_GAMMA) * 255.0f);
522 rgb->g = rgb->r;
523 rgb->b = rgb->r;
524 }
525 return;
526 }
527 if (rgb->r != 0 && RED_GAMMA > 0.0f && RED_GAMMA != 1.0f)
528 rgb->r = (int)(pow((rgb->r / 255.0f), 1.0f / RED_GAMMA) * 255.0f);
529 if (rgb->g != 0 && GREEN_GAMMA > 0.0f && GREEN_GAMMA != 1.0f)
530 rgb->g = (int)(pow((rgb->g / 255.0f), 1.0f / GREEN_GAMMA) * 255.0f);
531 if (rgb->b != 0 && BLUE_GAMMA > 0.0f && BLUE_GAMMA != 1.0f)
532 rgb->b = (int)(pow((rgb->b / 255.0f), 1.0f / BLUE_GAMMA) * 255.0f);
533}
534/** init_clr_palette
535 @brief Initialize color palette based on SIO settings
536 @ingroup color_management
537 @param sio Pointer to SIO struct with color settings
538 @return true if successful, false if error
539 @details This function initializes the xterm256 color cube and applies any
540 color overrides specified in the SIO struct. The color strings in the SIO
541 struct are expected to be six-digit HTML style hex color codes (e.g.,
542 "#RRGGBB"). If a color override is specified for any of the standard colors,
543 it is applied using the init_hex_clr function. After processing all colors,
544 the clr_cnt variable is set to CLR_NCOLORS to indicate that the standard
545 colors have been initialized. */
546bool init_clr_palette(SIO *sio) {
547 if (sio->black[0])
549 if (sio->red[0])
551 if (sio->green[0])
553 if (sio->yellow[0])
555 if (sio->blue[0])
557 if (sio->magenta[0])
559 if (sio->cyan[0])
561 if (sio->white[0])
563 if (sio->bblack[0])
565 if (sio->bred[0])
567 if (sio->bgreen[0])
569 if (sio->byellow[0])
571 if (sio->bblue[0])
573 if (sio->bmagenta[0])
575 if (sio->bcyan[0])
577 if (sio->bwhite[0])
579 if (sio->borange[0])
581 if (sio->fg[0])
583 if (sio->bg[0])
585 if (sio->box_fg[0])
587 if (sio->box_bg[0])
589 if (sio->ind_fg[0])
591 if (sio->ind_bg[0])
593 if (sio->title_fg[0])
595 if (sio->title_bg[0])
597 if (sio->ln_fg[0])
599 if (sio->ln_bg[0])
601 if (sio->nt_fg[0])
603 if (sio->nt_bg[0])
605 if (sio->nt_rev_fg[0])
607 if (sio->nt_rev_bg[0])
609 if (sio->nt_hl_fg[0])
611 if (sio->nt_hl_bg[0])
613 if (sio->nt_hl_rev_fg[0])
615 if (sio->nt_hl_rev_bg[0])
617 if (sio->fill_char_fg[0])
619 if (sio->fill_char_bg[0])
621 if (sio->brackets_fg[0])
623 if (sio->brackets_bg[0])
626 return true;
627}
628/** init_hex_clr
629 @brief Initialize extended ncurses color from HTML style hex string
630 @ingroup color_management
631 @param idx Color index
632 @param s Hex color string
633 @details NCurses uses 0-1000 for RGB values, so the RGB values from the hex
634 string are converted to this range before initializing the color. If the
635 color index is less than 16, the RGB values are also stored in the StdColors
636 array for reference.
637 */
638void init_hex_clr(int idx, char *s) {
639 RGB rgb;
641 apply_gamma(&rgb);
642 if (idx < 16) {
643 StdColors[idx].r = rgb.r;
644 StdColors[idx].g = rgb.g;
645 StdColors[idx].b = rgb.b;
646 }
647 rgb.r = (rgb.r * 1000) / 255;
648 rgb.g = (rgb.g * 1000) / 255;
649 rgb.b = (rgb.b * 1000) / 255;
650 init_extended_color(idx, rgb.r, rgb.g, rgb.b);
651}
652/** hex_clr_str_to_rgb
653 @brief Convert six-digit HTML style hex color code to RGB struct
654 @ingroup color_management
655 @param s six-digit HTML style hex color code */
656RGB hex_clr_str_to_rgb(char *s) {
657 RGB rgb;
658 sscanf(s, "#%02x%02x%02x", &rgb.r, &rgb.g, &rgb.b);
659 return rgb;
660}
661/** destroy_curses
662 @brief Gracefully shut down NCurses and restore terminal settings
663 @ingroup window_support
664 @details This function should be called before exiting the program to ensure
665 that the terminal is left in a usable state. It checks if NCurses was
666 initialized and, if so, it erases the screen, and ends the
667 NCurses session. It also restores the original terminal settings using
668 restore_shell_tioctl and resets signal handlers to their default state with
669 sig_dfl_mode. */
671 if (!f_curses_open)
672 return;
673 for (win_ptr = 0; win_ptr < MAXWIN; win_ptr++) {
674 del_panel(panel_box[win_ptr]);
675 delwin(win_win2[win_ptr]);
676 delwin(win_win[win_ptr]);
677 delwin(win_box[win_ptr]);
678 }
679 win_ptr = -1;
680 endwin();
681 delscreen(screen);
682 fclose(tty_fp);
683 f_curses_open = false;
686 return;
687}
688/** mb_to_cc
689 @brief Convert multibyte string to complex character array
690 @ingroup Chyron
691 @param cmplx_buf Output buffer for complex characters
692 @param str Input multibyte string
693 @param attr Attributes to apply to the complex characters
694 @param cpx Color pair index for the complex characters
695 @param pos Pointer to current position in the output buffer, updated as
696 characters are added
697 @param maxlen Maximum length of the output buffer
698 @return Number of bytes processed from the input string
699 @details This function converts a multibyte string to an array of complex
700 characters (cchar_t) that can be used with NCurses functions. It handles
701 multibyte characters and applies the specified color pair to each character.
702 The pos parameter is updated to reflect the current position in the output
703 buffer, and the function ensures that it does not exceed the maximum length.
704*/
705int mb_to_cc(cchar_t *cmplx_buf, char *str, attr_t attr, int cpx, int *pos,
706 int maxlen) {
707 int i = 0, len = 0;
708 const char *s;
709 cchar_t cc = {0};
710 wchar_t wstr[2] = {L'\0', L'\0'};
711 mbstate_t mbstate;
712 memset(&mbstate, 0, sizeof(mbstate));
713 attr = WA_NORMAL;
714 if (*pos >= maxlen - 1)
715 return 0;
716 while (str[i] != '\0') {
717 s = &str[i];
718 len = mbrtowc(wstr, s, MB_CUR_MAX, &mbstate);
719 if (len <= 0) {
720 wstr[0] = L'?';
721 wstr[1] = L'\0';
722 len = 1;
723 }
724 wstr[1] = L'\0';
725 if (*pos >= maxlen - 1)
726 break;
727 if (setcchar(&cc, wstr, attr, cpx, nullptr) != ERR) {
728 if (len > 0 && (*pos + len) < MAXLEN - 1)
729 cmplx_buf[(*pos)++] = cc;
730 }
731 i += len;
732 }
733 wstr[0] = L'\0';
734 wstr[1] = L'\0';
735 setcchar(&cc, wstr, attr, cpx, nullptr);
736 cmplx_buf[*pos] = cc;
737 return *pos;
738}
739/** mkcc
740 @brief Create a cchar_t with the specified color pair index
741 @ingroup color_management
742 @param cp Color pair index
743 @param attr Attributes to apply to the cchar_t
744 @param s Multibyte string to convert to wide character (only the first
745 character is used)
746 @return cchar_t with the specified color pair index and a space character
747 as the wide character */
748cchar_t mkcc(int cp, attr_t attr, const char *s) {
749 mbstate_t mbstate;
750 memset(&mbstate, 0, sizeof(mbstate));
751 size_t len;
752 size_t n;
753 cchar_t cc = {0};
754 wchar_t wstr[2] = {L'\0', L'\0'};
755 len = strlen(s);
756 if (len > 0) {
757 n = mbrtowc(wstr, s, MB_CUR_MAX, &mbstate);
758 if (n <= 0) {
759 wstr[0] = L'?';
760 wstr[1] = L'\0';
761 } else {
762 wstr[1] = L'\0';
763 }
764 } else {
765 wstr[0] = L' ';
766 wstr[1] = L'\0';
767 }
768 setcchar(&cc, wstr, attr, cp, nullptr);
769 return cc;
770}
771/** str_to_cc
772 @brief Convert a multibyte string to an array of cchar_t complex characters
773 @ingroup color_management
774 @param cmplx_buf Output buffer for complex characters
775 @param s Input multibyte string
776 @param attr Attributes to apply to the complex characters
777 @param cp Color pair index for the complex characters
778 @param maxlen Maximum length of the output buffer
779 @return Number of complex characters added to the output buffer
780 @details This function converts a multibyte string to an array of cchar_t
781 complex characters that can be used with NCurses functions. It handles
782 multibyte characters and applies the specified color pair to each character.
783 The function ensures that it does not exceed the maximum length of the output
784 buffer. */
785size_t
786str_to_cc(cchar_t *cmplx_buf, const char *s, attr_t attr, int cp, size_t maxlen) {
787 int i = 0, j = 0;
788 int len = 0;
789 cchar_t cc = {0};
790 wchar_t wstr[2] = {L'\0', L'\0'};
791 mbstate_t mbstate;
792 memset(&mbstate, 0, sizeof(mbstate));
793 while (s[i] != '\0') {
794 if (s[i] == '\033') {
795 i++;
796 continue;
797 }
798 wstr[1] = L'\0';
799 len = mbrtowc(wstr, &s[i], MB_CUR_MAX, &mbstate);
800 if (len <= 0) {
801 wstr[0] = L'?';
802 wstr[1] = L'\0';
803 len = 1;
804 }
805 if (setcchar(&cc, wstr, attr, cp, nullptr) != ERR) {
806 if (len > 0)
807 if ((j + len) < (int)maxlen + 1)
808 cmplx_buf[j++] = cc;
809 }
810 i += len;
811 }
812 wstr[0] = '\0';
813 wstr[1] = '\0';
814 setcchar(&cc, wstr, WA_NORMAL, cp, nullptr);
815 cmplx_buf[j++] = cc;
816 return j;
817}
818/** mk_cmplx_str
819 @brief Convert a multibyte string to an array of cchar_t complex characters
820 @ingroup color_management
821 @param cmplx_buf Output buffer for complex characters
822 @param s Input multibyte string
823 @param attr Attributes to apply to the complex characters
824 @param cp Color pair index for the complex characters
825 @return Number of bytes processed from the input string
826 */
827size_t
828mk_cmplx_str(cchar_t *cmplx_buf, char *s, attr_t attr, int cp) {
829 cchar_t cc = {0};
830 wchar_t wstr[2] = {L'\0', L'\0'};
831 mbstate_t mbstate;
832 memset(&mbstate, 0, sizeof(mbstate));
833 size_t len = strlen(s);
834
835 while (*s != '\0') {
836 mbrtowc(wstr, s, MB_CUR_MAX, &mbstate);
837 setcchar(&cc, wstr, attr, cp, nullptr);
838 *cmplx_buf++ = cc;
839 s += mbrlen(s, MB_CUR_MAX, &mbstate);
840 }
841 wstr[0] = L'\0';
842 wstr[1] = L'\0';
843 setcchar(&cc, wstr, attr, cp, nullptr);
844 *cmplx_buf++ = cc;
845 return len;
846}
847/** display_cmplx_str
848 @brief Display a complex character string on a window
849 @ingroup color_management
850 @param win NCurses window to display the string on
851 @param cmplx_buf Array of cchar_t complex characters to display
852 @param line Line number to display the string on
853 @param col Column number to start displaying the string from
854 @details This function clears the line where the string will be displayed,
855 then uses wadd_wchstr to add the complex character string (cmplx_buf) to the
856 window. Finally, it moves the cursor to the specified column position. */
857void display_cmplx_str(WINDOW *win, cchar_t *cmplx_buf, int line, int col) {
858 wmove(win, line, 0);
859 wclrtoeol(win);
860 wmove(win, line, 0);
861 wadd_wchstr(win, cmplx_buf);
862 wmove(win, line, col);
863 return;
864}
865/** @brief Converts a Unicode code point to a UTF-8 encoded string.
866 @ingroup utility_functions
867 @param cp - Unicode code point to convert
868 @param buffer - buffer to receive UTF-8 encoded string (must be at least 4 bytes)
869 @returns number of bytes written to buffer, or 0 if cp is invalid
870 @details This function encodes the given Unicode code point into its UTF-8 representation and stores it in the provided buffer. The caller must ensure that the buffer has enough space to hold the resulting UTF-8 string (up to 4 bytes for code points up to U+10FFFF). If the code point is invalid (e.g., greater than U+10FFFF), this function returns 0 and does not modify the buffer. */
871int wccp_to_str(wchar_t cp, uint8_t *buffer) {
872 if (cp <= 0x7F) {
873 // 1-byte sequence: 0xxxxxxx
874 buffer[0] = (uint8_t)cp;
875 return 1;
876 } else if (cp <= 0x7FF) {
877 // 2-byte sequence: 110xxxxx 10xxxxxx
878 buffer[0] = (uint8_t)(0xC0 | ((cp >> 6) & 0x1F));
879 buffer[1] = (uint8_t)(0x80 | (cp & 0x3F));
880 return 2;
881 } else if (cp <= 0xFFFF) {
882 // 3-byte sequence: 1110xxxx 10xxxxxx 10xxxxxx
883 buffer[0] = (uint8_t)(0xE0 | ((cp >> 12) & 0x0F));
884 buffer[1] = (uint8_t)(0x80 | ((cp >> 6) & 0x3F));
885 buffer[2] = (uint8_t)(0x80 | (cp & 0x3F));
886 return 3;
887 } else if (cp <= 0x10FFFF) {
888 // 4-byte sequence: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
889 buffer[0] = (uint8_t)(0xF0 | ((cp >> 18) & 0x07));
890 buffer[1] = (uint8_t)(0x80 | ((cp >> 12) & 0x3F));
891 buffer[2] = (uint8_t)(0x80 | ((cp >> 6) & 0x3F));
892 buffer[3] = (uint8_t)(0x80 | (cp & 0x3F));
893 return 4;
894 }
895 return 0; // Invalid Unicode code point
896}
897/** ui_rect_set
898 @brief Set the properties of a UiRect structure
899 @ingroup utility_functions
900 @param r Pointer to the UiRect structure to set
901 @param y Y-coordinate (row) of the rectangle's top-left corner
902 @param x X-coordinate (column) of the rectangle's top-left corner
903 @param h Height (number of rows) of the rectangle
904 @param w Width (number of columns) of the rectangle
905 @details This function initializes the fields of a UiRect structure
906 with the specified values for position and size. It is used to define
907 rectangular areas in a user interface. */
908void ui_rect_set(UiRect *r, int y, int x, int h, int w) {
909 r->y = y;
910 r->x = x;
911 r->rows = h;
912 r->cols = w;
913}
914/** box_hsplit_new
915 @brief Create a new window with optional box and title, and a second window
916 inside it, split horizontally
917 @ingroup window_support
918 @param wlines Number of lines for the first window
919 @param split_win_lines Number of lines for the second window
920 @param wcols Number of columns for the first window
921 @param wbegy Beginning Y position for the first window
922 @param wbegx Beginning X position for the first window
923 @param wtitle Window title for the first window
924 @return 0 if successful, 1 if error */
925int box_hsplit_new(int wlines, int split_win_lines, int wcols, int wbegy, int wbegx, char *wtitle) {
926 if (win_ptr >= MAXWIN) {
927 Perror("Maximum number of windows (%d) exceeded");
928 exit(EXIT_FAILURE);
929 }
930 wlines = min(wlines, LINES - 2);
931 wcols = min(wcols, COLS - 2);
932 bare_box_new(wlines + split_win_lines + 1, wcols, wbegy, wbegx, wtitle);
933 wbkgrnd(win_box[win_ptr], &CC_BOX);
934 wbkgrndset(win_box[win_ptr], &CC_BOX);
936 update_panels();
937 doupdate();
938 win_new(wlines, wcols);
939 win2_new(2, wcols, wlines + 2, 1);
940 return 0;
941}
942/** win2_box_new
943 @brief Create a new window with optional box and title, and a second window
944 inside it
945 @ingroup window_support
946 @param wlines Number of lines for the first window
947 @param wcols Number of columns for the first window
948 @param wbegy Beginning Y position for the first window
949 @param wbegx Beginning X position for the first window
950 @param wtitle Window title for the first window
951 @return 0 if successful, 1 if error */
952int win2_box_new(int wlines, int wcols, int wbegy, int wbegx, char *wtitle) {
953 bare_box_new(wlines, wcols, wbegy, wbegx, wtitle);
954 win_new(wlines, wcols);
955 win2_new(wlines, wcols, 1, 1);
956 return 0;
957}
958/** box_new
959 @brief Create a new window with optional box and title
960 @ingroup window_support
961 @param wlines Number of lines
962 @param wcols Number of columns
963 @param wbegy Beginning Y position
964 @param wbegx Beginning X position
965 @param wtitle Window title
966 @return 0 if successful, 1 if error */
967int box_new(int wlines, int wcols, int wbegy, int wbegx, char *wtitle) {
968 bare_box_new(wlines, wcols, wbegy, wbegx, wtitle);
969 win_new(wlines, wcols);
970 return 0;
971}
972/** box_new
973 @brief Create a new window with optional box and title
974 @ingroup window_support
975 @param wlines Number of lines
976 @param wcols Number of columns
977 @param wbegy Beginning Y position
978 @param wbegx Beginning X position
979 @param wtitle Window title
980 @return 0 if successful, 1 if error */
981int bare_box_new(int wlines, int wcols, int wbegy, int wbegx, char *wtitle) {
982 int maxy, maxx;
983 if (win_ptr >= MAXWIN) {
984 Perror("Maximum number of windows (%d) exceeded");
985 exit(EXIT_FAILURE);
986 }
987#ifdef NCURSES_UI
988 getmaxyx(stdscr, maxy, maxx);
989#else
991#endif
992 wlines = min(wlines, maxy - 2);
993 wcols = min(wcols, maxx - 2);
994 win_ptr++;
995 // -------------------> win_box <-------------------
996#ifdef UAL_UI
997 ui_rect_set(&ui_rect, wbegy, wbegx, wlines + 2, wcols + 2);
998 ui_box[win_ptr] = ui_surface_new(ui_runtime, NULL, ui_rect);
999 win_box[win_ptr] = ui_box[win_ptr]->win;
1000 panel_box[win_ptr] = ui_box[win_ptr]->pan;
1001
1002 UiStyle *ui_style = ui_style_from_cch(&CC_BOX);
1003 ui_bkgrnd(ui_box[win_ptr], ui_style, " "); // flood fill_char
1004 ui_bkgrnd_set(ui_box[win_ptr], ui_style, " "); // like wattron
1005 wborder_set(win_box[win_ptr], &ls, &rs, &ts, &bs, &tl, &tr, &bl, &br);
1006 border_title(win_box[win_ptr], wtitle);
1007
1008 ui_rect_set(&ui_rect, 1, 1, wlines, wcols);
1009 ui_win[win_ptr] = ui_surface_new(ui_runtime, ui_box[win_ptr], ui_rect);
1010 ui_style = ui_style_from_cch(&CC_NT);
1011 ui_bkgrnd(ui_win[win_ptr], ui_style, " "); // flood fill_char
1012 ui_bkgrnd_set(ui_win[win_ptr], ui_style, " "); // like wattron
1013 win_win[win_ptr] = ui_win[win_ptr]->win;
1014 panel_win[win_ptr] = ui_win[win_ptr]->pan;
1015 mvwaddstr(win_win[win_ptr], 10, 1, "Hello!");
1016
1017#else
1018 win_box[win_ptr] = newwin(wlines + 2, wcols + 2, wbegy, wbegx);
1019 if (win_box[win_ptr] == nullptr) {
1020 Perror("win_box[win_ptr] = newwin() failed");
1021 exit(EXIT_FAILURE);
1022 }
1023 panel_box[win_ptr] = new_panel(win_box[win_ptr]);
1024 wbkgrnd(win_box[win_ptr], &CC_BOX);
1025 wbkgrndset(win_box[win_ptr], &CC_BOX);
1028#endif
1029 return 0;
1030}
1031/** win_new
1032 @brief Create a new window with specified dimensions and position
1033 @ingroup window_support
1034 @param wlines Number of lines
1035 @param wcols Number of columns
1036 @return 0 if successful, 1 if error */
1037int win_new(int wlines, int wcols) {
1038 // -------------------> win_win <-------------------
1039 win_win[win_ptr] = derwin(win_box[win_ptr], wlines, wcols, 1, 1);
1040 if (win_win[win_ptr] == nullptr) {
1041 Perror("win_win[win_ptr] = derwin() failed");
1042 exit(EXIT_FAILURE);
1043 }
1044 panel_win[win_ptr] = new_panel(win_win[win_ptr]);
1045 wbkgrnd(win_win[win_ptr], &CC_NT);
1046 wbkgrndset(win_win[win_ptr], &CC_NT);
1047 keypad(win_win[win_ptr], true);
1048 idlok(win_win[win_ptr], false);
1049 idcok(win_win[win_ptr], false);
1050 wsetscrreg(win_win[win_ptr], 0, wlines - 1);
1051 scrollok(win_win[win_ptr], true);
1052 return 0;
1053}
1054
1055/*
1056------------------------------------------------------------------------- */
1057
1058/** win2_new
1059 @brief Create a new subwindow (win2) with specified dimensions and position
1060 @ingroup window_support
1061 @param wlines Number of lines
1062 @param wcols Number of columns
1063 @param wbegy Beginning Y position relative to the parent window
1064 @param wbegx Beginning X position relative to the parent window
1065 @return 0 if successful, 1 if error */
1066int win2_new(int wlines, int wcols, int wbegy, int wbegx) {
1067
1068 // -------------------> win2_win <-------------------
1069 win_win2[win_ptr] = derwin(win_box[win_ptr], wlines, wcols, wbegy, wbegx);
1070 if (win_win2[win_ptr] == nullptr) {
1071 Perror("win_win2[win_ptr] = derwin() failed");
1072 exit(EXIT_FAILURE);
1073 }
1074 panel_win2[win_ptr] = new_panel(win_win2[win_ptr]);
1075 wbkgrnd(win_win2[win_ptr], &CC_NT);
1076 keypad(win_win2[win_ptr], true);
1077 idlok(win_win2[win_ptr], false);
1078 idcok(win_win2[win_ptr], false);
1079 return 0;
1080}
1081/** check_panels
1082 @brief Check and display the panels for a given window index
1083 @ingroup window_support
1084 @param i Index of the window to check
1085 @details This function checks the panels associated with the
1086 specified window index. It sets the background color for each panel,
1087 displays a label indicating the panel type, and updates the display.
1088 The function pauses after displaying each panel to allow the user to
1089 view the changes. */
1090void check_panels(int i) {
1091 if (i == -1)
1092 return;
1093 char tmp_str[MAXLEN];
1094 wbkgrnd(win_box[i], &CC_RED);
1095 ssnprintf(tmp_str, MAXLEN - 1, "box[%d]", i);
1096 mvwaddstr(win_box[i], 5, 2, tmp_str);
1097 show_panel(panel_box[i]);
1098 update_panels();
1099 doupdate();
1100 getch();
1101
1102 wbkgrnd(win_win[i], &CC_GREEN);
1103 ssnprintf(tmp_str, MAXLEN - 1, "win[%d]", i);
1104 mvwaddstr(win_win[i], 6, 2, tmp_str);
1105 show_panel(panel_win[i]);
1106 update_panels();
1107 doupdate();
1108 getch();
1109
1110 wbkgrnd(win_win2[i], &CC_BLUE);
1111 ssnprintf(tmp_str, MAXLEN - 1, "win2[%d]", i);
1112 mvwaddstr(win_win2[i], 0, 0, tmp_str);
1113 update_panels();
1114 doupdate();
1115 show_panel(panel_win2[i]);
1116 getch();
1117}
1118/** win_resize
1119 @brief Resize the current window and its box, and update the title
1120 @ingroup window_support
1121 @param wlines Number of lines
1122 @param wcols Number of columns
1123 @param title Window title
1124 @details This function resizes the current window and its associated box
1125 window to the specified number of lines and columns. It also updates the
1126 title of the box window if a title is provided. After resizing, it refreshes
1127 the windows to apply the changes. */
1128void win_resize(int wlines, int wcols, char *title) {
1129 int maxx;
1130 update_panels();
1131 doupdate();
1132 wresize(win_box[win_ptr], wlines + 2, wcols + 2);
1133 wbkgrndset(win_box[win_ptr], &CC_BOX);
1134 wborder_set(win_box[win_ptr], &ls, &rs, &ts, &bs, &tl, &tr, &bl, &br);
1135 if (title != nullptr && *title != '\0') {
1136 wmove(win_box[win_ptr], 0, 1);
1137 waddnstr(win_box[win_ptr], (const char *)&bw_rt, 1);
1138 wmove(win_box[win_ptr], 0, 2);
1139 waddnstr(win_box[win_ptr], (const char *)&bw_sp, 1);
1140 mvwaddnwstr(win_box[win_ptr], 0, 1, &bw_rt, 1);
1141 mvwaddnwstr(win_box[win_ptr], 0, 2, &bw_sp, 1);
1142 mvwaddstr(win_box[win_ptr], 0, 3, title);
1143 maxx = getmaxx(win_box[win_ptr]);
1144 int s = strlen(title);
1145 if ((s + 3) < maxx)
1146 mvwaddch(win_box[win_ptr], 0, (s + 3), ' ');
1147 if ((s + 4) < maxx)
1148 mvwaddnwstr(win_box[win_ptr], 0, (s + 4), &bw_lt, 1);
1149 }
1150 update_panels();
1151 wresize(win_win[win_ptr], wlines, wcols);
1152 wbkgrndset(win_win[win_ptr], &CC_NT);
1153 wsetscrreg(win_win[win_ptr], 0, wlines - 1);
1154 keypad(win_win[win_ptr], TRUE);
1155 idlok(win_win[win_ptr], false);
1156 idcok(win_win[win_ptr], false);
1157 scrollok(win_win[win_ptr], true);
1158 update_panels();
1159 doupdate();
1160}
1161/** win_redraw
1162 @brief Redraw the specified window
1163 @ingroup window_support
1164 @param win Pointer to the window to redraw
1165 @details This function erases the contents of the specified window and then
1166 refreshes it to update the display. Use this function when you need to clear
1167 and redraw a window, such as after resizing or when updating its contents. */
1168void win_redraw(WINDOW *win) {
1169 werase(win);
1170 update_panels();
1171}
1172/** win_del
1173 @brief Delete the current window and its associated box window
1174 @ingroup window_support
1175 @details This function deletes the current window and its associated box
1176 window, if they exist. It also refreshes the remaining windows to ensure the
1177 display is updated correctly. After calling this function, the global win_ptr
1178 variable is decremented to point to the previous window in the stack. */
1179void win_del() {
1180 if (win_ptr >= MAXWIN) {
1181 Perror("win_ptr >= MAXWIN");
1182 exit(EXIT_FAILURE);
1183 }
1184 if (win_ptr >= 0) {
1185
1186 if (panel_win[win_ptr] != nullptr) {
1187 del_panel(panel_win[win_ptr]);
1188 panel_win[win_ptr] = nullptr;
1189 }
1190 if (win_win[win_ptr] != nullptr) {
1191 delwin(win_win[win_ptr]);
1192 win_win[win_ptr] = nullptr;
1193 }
1194
1195 if (panel_win2[win_ptr] != nullptr) {
1196 del_panel(panel_win2[win_ptr]);
1197 panel_win2[win_ptr] = nullptr;
1198 }
1199 if (win_win2[win_ptr] != nullptr) {
1200 delwin(win_win2[win_ptr]);
1201 win_win2[win_ptr] = nullptr;
1202 }
1203
1204 if (panel_box[win_ptr] != nullptr) {
1205 del_panel(panel_box[win_ptr]);
1206 panel_box[win_ptr] = nullptr;
1207 }
1208
1209 if (win_box[win_ptr] != nullptr) {
1210 delwin(win_box[win_ptr]);
1211 win_box[win_ptr] = nullptr;
1212 }
1213 win_ptr--;
1214 }
1215}
1216
1217/** restore_wins
1218 @brief Restore all windows after a screen resize
1219 @ingroup window_support
1220 @details This function is used to restore the display of all windows after a
1221 screen resize event. It clears the standard screen and then iterates through
1222 all existing windows, touching them to ensure they are redrawn
1223 correctly on the resized screen. Use this function in response to a SIGWINCH
1224 signal to handle terminal resizing gracefully. */
1226 touchwin(stdscr);
1227 for (int i = 0; i <= win_ptr; i++) {
1228 if (win_box[i] != nullptr)
1229 touchwin(win_box[i]);
1230 if (win_win[i] != nullptr)
1231 touchwin(win_win[i]);
1232 if (win_win2[i] == nullptr)
1233 touchwin(win_win2[i]);
1234 }
1235}
1236int border_draw(WINDOW *box) {
1237 int maxy = getmaxy(box);
1238 int maxx = getmaxx(box);
1239 int y = 0;
1240 int x = 0;
1241 mvwadd_wchnstr(box, y, x++, &tl, 1); // top left
1242 for (x = 1; x < maxx - 1; x++)
1243 mvwadd_wchnstr(box, y, x, &ts, 1); // horizontal line
1244 mvwadd_wchnstr(box, y, maxx - 1, &tr, 1); // top left
1245
1246 for (y = 1; y < maxy - 1; y++) {
1247 mvwadd_wchnstr(box, y, 0, &ls, 1); // vertical line
1248 mvwadd_wchnstr(box, y, maxx - 1, &rs, 1); // vertical line
1249 }
1250
1251 mvwadd_wchnstr(box, y, 0, &bl, 1); // bottom left
1252 for (x = 1; x < maxx - 1; x++)
1253 mvwadd_wchnstr(box, y, x, &bs, 1); // horizontal line
1254 mvwadd_wchnstr(box, y, maxx - 1, &br, 1); // bottom right
1255 return 0;
1256}
1257
1258/** border-hsplit
1259 @brief Draw a box with a separator line around the specified window
1260 @ingroup window_support
1261 @param box Pointer to the window to draw the box around
1262 @param y Line number where the separator line should be drawn
1263 @details This function draws a box around the specified window, similar to
1264 border_draw(), but it also includes a horizontal separator line that divides the box
1265 into two sections. The separator line is drawn at a fixed position (line 00,
1266 page 00) and extends across the width of the box. Use this function when you
1267 want to visually separate two sections within a window, such as for a header
1268 and content area. */
1269int border_hsplit(WINDOW *box, int y) {
1270 int maxx = getmaxx(box);
1271 mvwaddnwstr(box, y, 0, &bw_lt, 1);
1272 for (int x = 1; x < maxx - 1; x++)
1273 waddnwstr(box, &bw_ho, 1);
1274 mvwaddnwstr(box, y, maxx - 1, &bw_rt, 1);
1275 return 0;
1276}
1277/** border_hsplit_text
1278 @brief Draw a box with a separator line and text around the specified window
1279 @ingroup window_support
1280 @param box Pointer to the window to draw the box around
1281 @param text Text to display in the middle of the separator line
1282 @param separator_line Line number where the separator line should be drawn
1283 @details This function draws a box around the specified window, similar to
1284 border_draw(), but it also includes a horizontal separator line that divides the box
1285 into two sections. The separator line is drawn at the specified line number and
1286 extends across the width of the box, with the provided text displayed in the
1287 middle of the line. Use this function when you want to visually separate two
1288 sections within a window and label the separator with descriptive text. */
1289int border_hsplit_text(WINDOW *box, char *text, int separator_line) {
1290 int pos = 0;
1291 int maxx = getmaxx(box);
1292 int l;
1293 int y = separator_line;
1294 int x = 0;
1295 // Clearly, this is a bit hacky, but it works. We want to draw the
1296 // horizontal line with text in the middle, so we start by drawing the left
1297 // edge, then the text, then the right edge, and finally fill in the
1298 // horizontal line on either side of the text. mvwadd_wchnstr(box, y, x++,
1299 // &lt, 1);
1300 mvwadd_wchnstr(box, y, x++, &lt, 1);
1301 mvwadd_wchnstr(box, y, x++, &ts, 1);
1302 mvwadd_wchnstr(box, y, x++, &rt, 1);
1303 mvwadd_wchnstr(box, y, x++, &sp, 1);
1304 strnz(text, maxx - 7);
1305 cchar_t text_cc[MAXLEN] = {0};
1306 l = mb_to_cc(text_cc, text, WA_NORMAL, cp_box, &pos, MAXLEN - 1);
1307 mvwadd_wchnstr(box, y, x, text_cc, l);
1308 x += l;
1309 mvwadd_wchnstr(box, y, x++, &sp, 1);
1310 mvwadd_wchnstr(box, y, x++, &lt, 1);
1311
1312 while (x < maxx - 1)
1313 mvwadd_wchnstr(box, y, x++, &ts, 1);
1314 mvwadd_wchnstr(box, y, x++, &rt, 1);
1315 return 0;
1316}
1317/** border_title
1318 @brief Draw a box with a title around the specified window
1319 @ingroup window_support
1320 @param box Pointer to the window to draw the box around
1321 @param title Title text to display at the top of the box
1322 @details This function draws a box around the specified window, similar to
1323 border_draw(), but it also includes a title at the top of the box. The title
1324 is displayed in the center of the top edge of the box, and the horizontal line
1325 is drawn on either side of the title. Use this function when you want to
1326 visually label a window with a title. */
1327int border_title(WINDOW *box, char *title) {
1328 int pos = 0;
1329 int maxx = getmaxx(box);
1330 int y = 0;
1331 int x = 0;
1332 int l;
1333 mvwadd_wchnstr(box, y, x++, &tl, 1); // top left
1334 mvwadd_wchnstr(box, y, x++, &rt, 1); // right tee
1335 mvwadd_wchnstr(box, y, x++, &sp, 1); // space
1336 cchar_t title_cc[MAXLEN] = {0};
1337 l = mb_to_cc(title_cc, title, WA_NORMAL, cp_title, &pos, MAXLEN - 1);
1338 l = min(l, maxx - 7);
1339 mvwadd_wchnstr(box, y, x, title_cc, l);
1340 x += l;
1341 mvwadd_wchnstr(box, y, x++, &sp, 1); // space
1342 mvwadd_wchnstr(box, y, x++, &lt, 1); // left tee
1343 while (x < maxx - 1)
1344 mvwadd_wchnstr(box, y, x++, &ts, 1); // horizontal line
1345 return 0;
1346}
1347/* int box_title(WINDOW *box, char *title) {
1348 wbkgrndset(box, &CC_BOX);
1349 int y, x, l;
1350 int maxx;
1351 int pos = 0;
1352 y = 0;
1353 x = 1;
1354 maxx = getmaxx(box);
1355 mvwadd_wchnstr(box, y, x++, &ts, 1);
1356 mvwadd_wchnstr(box, y, x++, &rt, 1);
1357 mvwadd_wchnstr(box, y, x++, &sp, 1);
1358 cchar_t title_cc[MAXLEN] = {0};
1359 l = mb_to_cc(title_cc, title, WA_NORMAL, cp_box, &pos, MAXLEN - 1);
1360 mvwadd_wchnstr(box, y, x, title_cc, l);
1361 x += l;
1362 mvwadd_wchnstr(box, y, x++, &sp, 1);
1363 mvwadd_wchnstr(box, y, x++, &lt, 1);
1364 while (x < maxx - 1)
1365 mvwadd_wchnstr(box, y, x++, &ts, 1);
1366 return 0;
1367} */
1368/** @defgroup error_handling Error Handling
1369 @brief Display Error messages
1370 */
1371
1372/** @brief Display a message in a window or print to stderr if curses is not available
1373 @ingroup error_handling
1374 @param msg Message to display
1375 @return Pointer to the created window, or nullptr if curses is not available or screen is too small */
1376WINDOW *
1377message_win(char *msg) {
1378 if (!f_curses_open) {
1379 fprintf(stderr, "\n\n%s\n\n", msg);
1380 return nullptr;
1381 }
1382 if (LINES < 4 || COLS < 42)
1383 return nullptr;
1384 int wlines = 3, wcols = 40;
1385 int wbegy = 0;
1386 int wbegx = COLS - wcols - 2;
1387 WINDOW *win = subwin(stdscr, wlines, wcols, wbegy, wbegx);
1388 if (win == nullptr)
1389 return win;
1390 wbkgrndset(win, &CC_BOX);
1391 wborder_set(win, &ls, &rs, &ts, &bs, &tl, &tr, &bl, &br);
1392 strnz(msg, 40);
1393 mvwaddstr(win, 0, 1, msg);
1394 update_panels();
1395 doupdate();
1396 return win;
1397}
1398/** answer_yn
1399 @brief Accept a single letter answer
1400 @ingroup error_handling
1401 @param msg0 First error message line
1402 @param msg1 Second error message line
1403 @param msg2 Third error message line
1404 @param msg3 Fourth error message line
1405 @return Key code of user command */
1406int answer_yn(char *msg0, char *msg1, char *msg2, char *msg3) {
1407 char title[MAXLEN];
1408 int line, pos, msg_l, msg0_l, msg1_l, msg2_l, msg3_l;
1409 WINDOW *error_win;
1410
1411 if (!f_curses_open) {
1412 fprintf(stderr, "\n\n%s\n%s\n%s\n%s\n\n", msg0, msg1, msg2, msg3);
1413 return 1;
1414 }
1415
1416 Chyron *chyron = new_chyron();
1417 set_chyron_key(chyron, 1, "F1 Help", KEY_F(1));
1418 set_chyron_key(chyron, 2, "N - No", 'n');
1419 set_chyron_key(chyron, 3, "Y - Yes", 'y');
1420 compile_chyron(chyron);
1421
1422 msg0_l = strnz(msg0, COLS - 4);
1423 msg1_l = strnz(msg1, COLS - 4);
1424 msg2_l = strnz(msg2, COLS - 4);
1425 msg3_l = strnz(msg1, COLS - 4);
1426 msg_l = max(msg0_l, msg1_l);
1427 msg_l = max(msg_l, msg2_l);
1428 msg_l = max(msg_l, msg3_l);
1429 msg_l = max(msg_l, chyron->l);
1430 msg_l = min(msg_l, COLS - 4);
1431
1432 pos = ((COLS - msg_l) - 4) / 2;
1433 line = (LINES - 6) / 2;
1434 strnz__cpy(title, "Notification", MAXLEN - 1);
1435 if (box_new(5, msg_l + 2, line, pos, title)) {
1436 ssnprintf(title, MAXLEN - 1, "box_new(%d, %d, %d, %d, %s) failed", 5,
1437 msg_l + 2, line, pos, title);
1438 destroy_chyron(chyron);
1439 abend(-1, title);
1440 }
1441 error_win = win_win[win_ptr];
1442 mvwaddstr(error_win, 0, 1, msg0);
1443 mvwaddstr(error_win, 1, 1, msg1);
1444 mvwaddstr(error_win, 2, 1, msg2);
1445 mvwaddstr(error_win, 3, 1, msg3);
1446 display_chyron(error_win, chyron, 4, chyron->l + 1);
1447
1448 do {
1449 curs_set(1);
1450 cmd_key = xwgetch(error_win, chyron, -1);
1451 curs_set(0);
1452 if (cmd_key == KEY_F(1) || cmd_key == 'N' || cmd_key == 'n' || cmd_key == 'Y' || cmd_key == 'y')
1453 break;
1454 } while (1);
1455 win_del();
1456 destroy_chyron(chyron);
1457 return (cmd_key);
1458}
1459/** display_error
1460 @brief Display an error message window or print to stderr
1461 @ingroup error_handling
1462 @param msg0 First error message line
1463 @param msg1 Second error message line
1464 @param msg2 Third error message line
1465 @param msg3 Fourth error message line
1466 @return Key code of user command */
1467int display_error(char *msg0, char *msg1, char *msg2, char *msg3) {
1468 char title[MAXLEN];
1469 int line, pos, msg_l, msg0_l, msg1_l, msg2_l, msg3_l;
1470 WINDOW *error_win;
1471
1472 if (!f_curses_open) {
1473 fprintf(stderr, "\n\n%s\n", msg0);
1474 fprintf(stderr, "%s\n", msg1);
1475 fprintf(stderr, "%s\n", msg2);
1476 fprintf(stderr, "%s\n\n", msg3);
1477 return 1;
1478 }
1479
1480 Chyron *chyron = new_chyron();
1481 set_chyron_key(chyron, 1, "F1 Help", KEY_F(1));
1482 set_chyron_key(chyron, 9, "F9 Cancel", KEY_F(9));
1483 set_chyron_key(chyron, 10, "F10 Continue", KEY_F(10));
1484 compile_chyron(chyron);
1485
1486 msg0_l = strnz(msg0, COLS - 4);
1487 msg1_l = strnz(msg1, COLS - 4);
1488 msg2_l = strnz(msg2, COLS - 4);
1489 msg3_l = strnz(msg1, COLS - 4);
1490 msg_l = max(msg0_l, msg1_l);
1491 msg_l = max(msg_l, msg2_l);
1492 msg_l = max(msg_l, msg3_l);
1493 msg_l = max(msg_l, chyron->l);
1494 msg_l = min(msg_l, COLS - 4);
1495
1496 pos = ((COLS - msg_l) - 4) / 2;
1497 line = (LINES - 6) / 2;
1498 strnz__cpy(title, "Notification", MAXLEN - 1);
1499 if (box_new(5, msg_l + 2, line, pos, title)) {
1500 ssnprintf(title, MAXLEN - 1, "box_new(%d, %d, %d, %d, %s) failed", 5,
1501 msg_l + 2, line, pos, title);
1502 destroy_chyron(chyron);
1503 abend(-1, title);
1504 }
1505 error_win = win_win[win_ptr];
1506 mvwaddstr(error_win, 0, 1, msg0);
1507 mvwaddstr(error_win, 1, 1, msg1);
1508 mvwaddstr(error_win, 2, 1, msg2);
1509 mvwaddstr(error_win, 3, 1, msg3);
1510 display_chyron(error_win, chyron, 4, chyron->l + 1);
1511 do {
1512 cmd_key = xwgetch(error_win, chyron, -1);
1513 if (cmd_key == KEY_F(9) || cmd_key == KEY_F(10) || cmd_key == 'q' || cmd_key == 'Q')
1514 break;
1515 } while (1);
1516 win_del();
1517 destroy_chyron(chyron);
1518 return (cmd_key);
1519}
1520
1521/** Perror
1522 @brief Display a simple error message window or print to stderr
1523 @ingroup error_handling
1524 @param emsg_str Error message string
1525 @return Key code of user command */
1526int Perror(char *emsg_str) {
1527 char emsg[MAXLEN];
1528 unsigned in_key;
1529 WINDOW *error_win;
1530 int len, line, pos;
1531 char title[MAXLEN];
1532 bool f_xwgetch = true;
1533 if (emsg_str[0] == '␛' && emsg_str[1] == 'w') {
1534 emsg_str += 2;
1535 f_xwgetch = false;
1536 }
1537 strnz__cpy(emsg, emsg_str, 79);
1538 if (!f_curses_open) {
1539 fprintf(stderr, "\n%s\n", emsg);
1540 return 1;
1541 }
1542 Chyron *chyron = new_chyron();
1543 set_chyron_key(chyron, 1, "F1 Help", KEY_F(1));
1544 set_chyron_key(chyron, 9, "F9 Cancel", KEY_F(9));
1545 set_chyron_key(chyron, 10, "F10 Continue", KEY_F(10));
1546 compile_chyron(chyron);
1547 len = strnz(emsg, COLS - 4);
1548 pos = (COLS - len - 4) / 2;
1549 line = (LINES - 4) / 2;
1550 strnz__cpy(title, "Notification", MAXLEN - 1);
1551 if (box_new(2, len + 2, line, pos, title)) {
1552 ssnprintf(title, MAXLEN - 1, "box_new(%d, %d, %d, %d, %s, %b) failed",
1553 4, line, line, pos, title);
1554 destroy_chyron(chyron);
1555 abend(-1, title);
1556 }
1557 error_win = win_win[win_ptr];
1558 mvwaddstr(error_win, 0, 1, emsg);
1559 display_chyron(error_win, chyron, 1, chyron->l + 1);
1560 if (f_xwgetch) {
1561 curs_set(1);
1562 in_key = xwgetch(error_win, chyron, -1);
1563 curs_set(0);
1564 } else {
1565 in_key = KEY_F(10);
1566 }
1567 destroy_chyron(chyron);
1568 win_del();
1569 return (in_key);
1570}
1571/** wait_mk_chyron
1572 @brief Create a Chyron struct for the waiting message
1573 @ingroup error_handling
1574 @return Pointer to the chyron struct */
1575Chyron *
1577 Chyron *chyron = new_chyron();
1578 set_chyron_key(chyron, 9, "F9 Cancel", KEY_F(9));
1579 compile_chyron(chyron);
1580 return chyron;
1581}
1582/** wait_mk_win
1583 @brief Display a popup waiting message
1584 @ingroup error_handling
1585 @param chyron Pointer to Chyron struct for displaying key options
1586 @param title window title
1587 @return WINDOW * struct */
1588WINDOW *
1589wait_mk_win(Chyron *chyron, char *title) {
1590 char wm1[] = "Seconds remaining:";
1591 int len;
1592 int line, col;
1593 WINDOW *wait_win;
1594
1595 if (!f_curses_open) {
1596 fprintf(stderr, "\n%s\n", title);
1597 fprintf(stderr, "%s\n", wm1);
1598 return NULL;
1599 }
1600 len = max(strlen(title), strlen(wm1));
1601 len = max(len, chyron->l);
1602 len = max(len, 40);
1603 col = (COLS - len - 4) / 2;
1604 line = (LINES - 4) / 2;
1605 if (box_new(2, len + 2, line, col, title)) {
1606 ssnprintf(title, MAXLEN - 1, "box_new(%d, %d, %d, %d, %s) failed", 4,
1607 line, line, col, title);
1608 abend(-1, title);
1609 }
1610 wait_win = win_win[win_ptr];
1611 mvwaddstr(wait_win, 0, 1, wm1);
1612 display_chyron(wait_win, chyron, 1, 0);
1613 wmove(wait_win, 1, chyron->l);
1614 return wait_win;
1615}
1616/** wait_destroy
1617 @brief Destroy the waiting message window and chyron
1618 @ingroup error_handling
1619 @param chyron Pointer to Chyron struct for displaying key options
1620 @return true if successful */
1621bool wait_destroy(Chyron *chyron) {
1622 win_del();
1623 destroy_chyron(chyron);
1624 update_panels();
1625 doupdate();
1626 return true;
1627}
1628/** wait_continue
1629 @brief Update the waiting message with remaining time and check for user
1630 input
1631 @ingroup error_handling
1632 @param chyron Pointer to Chyron struct for displaying key options
1633 @param wait_win Pointer to the waiting message window
1634 @param remaining Time remaining for the wait in seconds
1635 @return true if the wait should continue, false if it should be cancelled */
1636int wait_continue(WINDOW *wait_win, Chyron *chyron, int remaining) {
1637 char time_str[10];
1638 ssnprintf(time_str, 9, "%-4d", remaining);
1639 mvwaddstr(wait_win, 0, 21, time_str);
1640 display_chyron(wait_win, chyron, 1, 0);
1641 wmove(wait_win, 1, chyron->l);
1642 cmd_key = xwgetch(wait_win, chyron, 1);
1643 return cmd_key;
1644}
1645/** action_disposition
1646 @brief Display a simple action disposition message window or print to stderr
1647 @ingroup error_handling
1648 @param title Window title
1649 @param action_str Action description string
1650 @return true if successful */
1651bool action_disposition(char *title, char *action_str) {
1652 int len;
1653 int line, col;
1654 WINDOW *action_disposition_win;
1655
1656 if (!f_curses_open) {
1657 fprintf(stderr, "\n%s\n", title);
1658 fprintf(stderr, "%s\n", action_str);
1659 return true;
1660 }
1661 Chyron *chyron = new_chyron();
1662 set_chyron_key(chyron, 10, "F10 Continue", KEY_F(10));
1663 compile_chyron(chyron);
1664 len = max(strlen(title), strlen(action_str));
1665 col = (COLS - len - 4) / 2;
1666 line = (LINES - 4) / 2;
1667 if (box_new(2, len + 2, line, col, title)) {
1668 ssnprintf(em0, MAXLEN - 1, "box_new(%d, %d, %d, %d, %s) failed", 4,
1669 line, line, col, title);
1671 }
1672 action_disposition_win = win_win[win_ptr];
1673 mvwaddstr(action_disposition_win, 0, 1, action_str);
1674 display_chyron(action_disposition_win, chyron, 1, 0);
1675 wmove(action_disposition_win, 1, chyron->l);
1676 cmd_key = xwgetch(action_disposition_win, chyron, 1);
1677 win_del();
1678 destroy_chyron(chyron);
1679 return true;
1680}
1681/** @defgroup Chyron Chyron Management
1682 @brief Create and manage the Chyron
1683 */
1684
1685/** new_chyron
1686 @brief Create and initialize Chyron structure
1687 @ingroup Chyron
1688 @return pointer to new Chyron structure
1689 @details This function allocates memory for a new Chyron structure and
1690 initializes the key pointers. Each key pointer is allocated memory for a
1691 ChyronKey structure. The Chyron structure is used to manage function key
1692 labels and their associated keycodes for mouse click handling in the chyron
1693 area of the interface.
1694 The use of calloc ensures that the allocated memory is initialized to
1695 zero, which means that the text for each key will be initialized to an empty
1696 string and the keycodes will be initialized to zero. This allows the
1697 is_set_chyron_key function to check if a key is set by checking if the first
1698 character of the text is not '\0'. If any memory allocation fails, the
1699 function will call abend to handle the error and return nullptr.
1700 */
1701Chyron *new_chyron() {
1702 Chyron *chyron = (Chyron *)calloc(1, sizeof(Chyron));
1703 if (!chyron) {
1704 abend(-1, "calloc chyron failed");
1705 return nullptr;
1706 }
1707 for (int i = 0; i < CHYRON_KEYS; i++) {
1708 chyron->key[i] = (ChyronKey *)calloc(1, sizeof(ChyronKey));
1709 if (!chyron->key[i]) {
1710 abend(-1, "calloc chyron->key[i] failed");
1711 return nullptr;
1712 }
1713 }
1714 return chyron;
1715}
1716/** destroy_chyron
1717 @brief Destroy Chyron structure
1718 @ingroup Chyron
1719 @param chyron pointer to Chyron structure
1720 @return nullptr
1721 */
1722Chyron *destroy_chyron(Chyron *chyron) {
1723 int i;
1724
1725 if (!chyron)
1726 return nullptr;
1727 for (i = 0; i < CHYRON_KEYS; i++) {
1728 if (chyron->key[i]) {
1729 free(chyron->key[i]);
1730 chyron->key[i] = nullptr;
1731 }
1732 }
1733 free(chyron);
1734 chyron = nullptr;
1735 return chyron;
1736}
1737/** is_set_chyron_key
1738 @brief Check if function key label is set
1739 @ingroup Chyron
1740 @param chyron structure
1741 @param k Function key index (0-19)
1742 @return true if set, false if not set */
1743bool is_set_chyron_key(Chyron *chyron, int k) {
1744 if (chyron->key[k]->text[0] != '\0')
1745 return true;
1746 else
1747 return false;
1748}
1749/** set_chyron_key_cp
1750 @brief Set chyron key with color pair (cp)
1751 @ingroup Chyron
1752 @param chyron structure
1753 @param k chyron key index (0-19)
1754 @param s chyron key label
1755 @param kc chyron key code
1756 @param cp color pair index for the key label
1757 @details This function is like set_chyron_key, except it includes a color
1758 pair numbers */
1759void set_chyron_key_cp(Chyron *chyron, int k, char *s, int kc, int cp) {
1760 if (*s != '\0')
1761 ssnprintf(chyron->key[k]->text, CHYRON_KEY_MAXLEN - 1, "%s", s);
1762 else
1763 chyron->key[k]->text[0] = '\0';
1764 chyron->key[k]->keycode = kc;
1765 chyron->key[k]->active = true;
1766 chyron->key[k]->cp = cp;
1767}
1768/** set_chyron_key
1769 @brief Set chyron key with default color pair (cp_nt_rev)
1770 @ingroup Chyron
1771 @param chyron structure
1772 @param k chyron key index (0-19)
1773 @param s chyron key label
1774 @param kc chyron key code
1775 @details This function sets the label and keycode for a function key in the
1776 chyron structure. It uses the default color pair cp_nt_rev for the key
1777 label. If the input string s is not empty, it copies the string into the
1778 chyron key's text field. If the input string is empty, it sets the first
1779 character of the text field to '\0' to indicate that the key is not set.
1780 The keycode is stored in the chyron key's keycode field, and the color pair
1781 index is set to cp_nt_rev.
1782 */
1783void set_chyron_key(Chyron *chyron, int k, char *s, int kc) {
1784 if (*s != '\0')
1785 ssnprintf(chyron->key[k]->text, CHYRON_KEY_MAXLEN - 1, "%s", s);
1786 else
1787 chyron->key[k]->text[0] = '\0';
1788 chyron->key[k]->keycode = kc;
1789 chyron->key[k]->active = true;
1790 chyron->key[k]->cp = cp_nt_rev;
1791}
1792/** unset_chyron_key
1793 @brief Unset chyron key
1794 @ingroup Chyron
1795 @param chyron structure
1796 @param k chyron_key index
1797*/
1798void unset_chyron_key(Chyron *chyron, int k) {
1799 chyron->key[k]->text[0] = '\0';
1800}
1801/** activate_chyron_key
1802 @brief Activate chyron key
1803 @ingroup Chyron
1804 @param chyron structure
1805 @param k chyron_key index
1806*/
1807void activate_chyron_key(Chyron *chyron, int k) {
1808 chyron->key[k]->active = true;
1809}
1810/** deactivate_chyron_key
1811 @brief Deactivate chyron key
1812 @ingroup Chyron
1813 @param chyron structure
1814 @param k chyron_key index
1815*/
1816void activate_all_chyron_keys(Chyron *chyron) {
1817 for (int k = 0; k < CHYRON_KEYS; k++)
1818 chyron->key[k]->active = true;
1819}
1820/** deactivate_chyron_key
1821 @brief Deactivate chyron key
1822 @ingroup Chyron
1823 @param chyron structure
1824 @param k chyron_key index
1825*/
1826void deactivate_chyron_key(Chyron *chyron, int k) {
1827 chyron->key[k]->active = false;
1828}
1829/** deactivate_all_chyron_keys
1830 @brief Deactivate all chyron keys
1831 @ingroup Chyron
1832 @param chyron structure
1833*/
1834void deactivate_all_chyron_keys(Chyron *chyron) {
1835 for (int k = 0; k < CHYRON_KEYS; k++)
1836 chyron->key[k]->active = false;
1837}
1838/** compile_chyron
1839 @brief construct the chyron string from the chyron structure
1840 @ingroup Chyron
1841 @param chyron
1842 @details The chyron string is constructed by concatenating the labels of the
1843 set keys, separated by " | ". The end_pos values for each key are set to
1844 determine the zones for mouse clicks. When a mouse click occurs, the
1845 get_chyron_key function uses the end_pos values to determine which key was
1846 clicked based on the X position of the click.
1847*/
1848void compile_chyron(Chyron *chyron) {
1849 int end_pos = 0;
1850 int k = 0;
1851 int pos = 0;
1852 int cp = cp_nt_rev;
1853 cchar_t *cx;
1854 char tmp_str[MAXLEN];
1855 while (k < CHYRON_KEYS) {
1856 if (chyron->key[k]->text[0] == '\0' || !chyron->key[k]->active) {
1857 k++;
1858 continue;
1859 }
1860 if (end_pos == 0) {
1861 cx = chyron->cmplx_buf;
1862 mb_to_cc(cx, " ", WA_NORMAL, cp_nt_rev, &pos, MAXLEN - 1);
1863 } else {
1864 mb_to_cc(chyron->cmplx_buf, "|", WA_NORMAL, cp_nt_rev, &pos,
1865 MAXLEN - 1);
1866 }
1867 cx = chyron->cmplx_buf;
1868 if (chyron->key[k]->cp)
1869 cp = chyron->key[k]->cp;
1870 mb_to_cc(cx, chyron->key[k]->text, WA_NORMAL, cp, &pos, MAXLEN - 1);
1871 end_pos = pos;
1872 chyron->l = end_pos;
1873 chyron->key[k]->end_pos = end_pos;
1874 ssnprintf(tmp_str, MAXLEN - 1, "k=%d, text=%s, end_pos=%d", k,
1875 chyron->key[k]->text, chyron->key[k]->end_pos);
1876 k++;
1877 }
1878 mb_to_cc(chyron->cmplx_buf, " ", WA_NORMAL, cp, &pos, MAXLEN - 1);
1879 chyron->l = end_pos;
1880}
1881/** display_chyron
1882 @brief Display chyron on window
1883 @ingroup Chyron
1884 @param win NCurses window to display chyron on
1885 @param chyron Chyron structure containing the compiled chyron string
1886 @param line Line number to display the chyron on
1887 @param col Column number to start displaying the chyron from
1888 @details This function clears the line where the chyron will be displayed,
1889 then uses wadd_wchstr to add the compiled chyron string (cmplx_buf) to the
1890 window. Finally, it moves the cursor to the specified column position.
1891*/
1892void display_chyron(WINDOW *win, Chyron *chyron, int line, int col) {
1893 wmove(win, line, 0);
1894 wclrtoeol(win);
1895 wmove(win, line, 0);
1896 wadd_wchstr(win, chyron->cmplx_buf);
1897 wmove(win, line, col);
1898 update_panels();
1899 doupdate();
1900 return;
1901}
1902/** get_chyron_key
1903 @brief Get keycode from chyron
1904 @ingroup Chyron
1905 @param chyron structure
1906 @param x Mouse X position
1907 @return Keycode
1908 @details This function uses the end_pos values set in compile_chyron
1909 to determine which key was clicked.
1910 The chyron functions provide xwgetch() with a mechanism to translate
1911 mouse click positions into key codes based on the labels set in the chyron
1912 structure. When a mouse click occurs, xwgetch() can call get_chyron_key()
1913 with the X position of the click to determine which function key was clicked,
1914 allowing for dynamic and customizable function key behavior in the chyron
1915 area of the interface.
1916*/
1917int get_chyron_key(Chyron *chyron, int x) {
1918 int i = 0;
1919 int k = -1;
1920 while (i < CHYRON_KEYS - 1) {
1921 if (chyron->key[i]->text[0] != '\0' && chyron->key[i]->active)
1922 if (chyron->key[i]->end_pos >= x) {
1923 k = i;
1924 break;
1925 }
1926 i++;
1927 }
1928 if (k == -1)
1929 return 0;
1930 return chyron->key[k]->keycode;
1931}
1932
1933/** mvwaddstr_fill
1934 @brief For lines shorter than their display area, fill the rest with spaces
1935 @ingroup window_support
1936 @param w Pointer to window
1937 @param y Y coordinate
1938 @param x X coordinate
1939 @param s String to display
1940 @param l Length of display area */
1941void mvwaddstr_fill(WINDOW *w, int y, int x, char *s, int l) {
1942 char *d, *e;
1943 int maxy, maxx;
1944 char tmp_str[MAXLEN];
1945 getmaxyx(w, maxy, maxx);
1946 y = min(y, maxy);
1947 l = min(l, maxx);
1948 l = min(l, MAXLEN - 1);
1949 e = d = tmp_str;
1950 e += l;
1951 while (d < e) {
1952 if (*s == '\0' || *s == '\n')
1953 *d++ = ' ';
1954 else
1955 *d++ = *s++;
1956 }
1957 *d = '\0';
1958 l = strlen(tmp_str);
1959 mvwaddstr(w, y, x, tmp_str);
1960}
1961/** clr_name_to_idx
1962 @brief Get color index from color name
1963 @ingroup color_management
1964 @param s Color name
1965 @return Color index or -1 if not found */
1966int clr_name_to_idx(char *s) {
1967 int i = 0;
1968 int n = 16;
1969
1971 while (i < n) {
1972 if (!strcmp(colors_text[i], s))
1973 break;
1974 i++;
1975 }
1976 if (i >= n)
1977 return (-1);
1978 return (i);
1979}
1980/** list_colors
1981 @brief list colors to stderr
1982 @ingroup color_management
1983 @details only lists the first 16, since that's how many we let the
1984 user redefine */
1986 int i, col;
1987
1988 for (i = 0, col = 0; i < 16; i++, col++) {
1989 if (i < 8) {
1990 fprintf(stderr, " ");
1991 }
1992 if (i == 8) {
1993 col = 0;
1994 fprintf(stderr, "\n");
1995 } else if (col > 0)
1996 fprintf(stderr, " ");
1997 fprintf(stderr, "%s", colors_text[i]);
1998 }
1999 fprintf(stderr, "\n");
2000}
2001/** nf_error
2002 @brief Display error message and wait for key press
2003 @ingroup error_handling
2004 @param ec Error code
2005 @param s Error message */
2006int nf_error(int ec, char *s) {
2007 fprintf(stderr, "ERROR: %s code: %d\n", s, ec);
2008 fprintf(stderr, "Press a key to continue");
2009 di_getch();
2010 fprintf(stderr, "\n");
2011 return ec;
2012}
2013/** abend
2014 @brief Abnormal program termination
2015 @ingroup error_handling
2016 @param ec Exit code
2017 @param s Error message */
2018void abend(int ec, char *s) {
2022 fprintf(stderr, "\n\nABEND: %s (code: %d)\n", s, ec);
2023 exit(EXIT_FAILURE);
2024}
2025/** waitpid_with_timeout
2026 @brief Wait for a process to finish with a timeout and optional user
2027 cancellation
2028 @ingroup error_handling
2029 @param pid Process ID to wait for
2030 @param timeout Time in seconds to wait before timing out
2031 @return true if the process finished, false if it timed out or was cancelled
2032 */
2033bool waitpid_with_timeout(pid_t pid, int timeout) {
2034 int status;
2035 Chyron *wait_chyron;
2036 WINDOW *wait_win;
2037 int remaining = timeout;
2038 bool rc = false;
2039
2040 waitpid(pid, &status, WNOHANG);
2041 if (WIFEXITED(status) || WIFSIGNALED(status)) {
2042 kill(pid, SIGKILL);
2043 waitpid(pid, &status, 0);
2044 return true;
2045 }
2046 usleep(100000); // Sleep for 200ms */
2047 wait_chyron = wait_mk_chyron();
2048 ssnprintf(em0, MAXLEN - 1, "Waiting for process %d to finish...", pid);
2049 wait_win = wait_mk_win(wait_chyron, em0);
2050 cmd_key = 0;
2051 while (remaining > 0 && cmd_key != KEY_F(9)) {
2052 cmd_key = wait_continue(wait_win, wait_chyron, remaining);
2053 if (cmd_key == KEY_F(9))
2054 break;
2055 if (cmd_key == KEY_F(10)) {
2056 remaining = timeout;
2057 continue;
2058 }
2059 remaining--;
2060 waitpid(pid, &status, WNOHANG);
2061 if (WIFEXITED(status) || WIFSIGNALED(status)) {
2062 rc = true;
2063 break;
2064 }
2065 }
2066 kill(pid, SIGKILL);
2067 waitpid(pid, &status, 0);
2068 win_del();
2069 destroy_chyron(wait_chyron);
2070 update_panels();
2071 doupdate();
2072 return rc;
2073}
2074/** xwgetch
2075 @brief Wrapper for wgetch that handles signals, mouse events, checks for
2076 clicks on the chyron line, and accepts a sinigle character answer
2077 @ingroup window_support
2078 @param win Pointer to window
2079 @param chyron Pointer to chyron struct
2080 @param n Number of seconds to wait before timing out
2081 @verbatim
2082
2083 0: Wait indefinitely for user input (raw mode)
2084 accept a single character answer, and don't wait for Enter key
2085 1: Wait for 1 decisecond
2086 n > 1: Wait for n/10 seconds
2087
2088 @endverbatim
2089 @return Key code or ERR if interrupted by signal
2090 @details Get mouse event and check if it's a left click or double click. If
2091 the click is outside the window, ignore it. If it's on the chyron line, get
2092 the corresponding key command. Otherwise, store the click coordinates as
2093 click_y and click_x for later use. */
2094int xwgetch(WINDOW *win, Chyron *chyron, int n) {
2095 int c;
2096 MEVENT event;
2097 mousemask(BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED | BUTTON4_PRESSED | BUTTON5_PRESSED,
2098 nullptr);
2099 click_y = event.y = -1;
2100 click_x = event.x = -1;
2101
2102 if (n == -1) {
2103 struct termios raw_tioctl;
2104 raw_tioctl = curses_tioctl;
2105 mk_raw_tioctl(&raw_tioctl);
2106 } else if (n == 0)
2107 halfdelay(1);
2108 else
2109 halfdelay(min(255, max(0, n * 10)));
2110 tcflush(2, TCIFLUSH);
2111 do {
2112 curs_set(1);
2113 c = wgetch(win);
2114 curs_set(0);
2115 if (sig_received != 0) {
2117 c = display_error(em0, em1, em2, nullptr);
2118 if (c == 'q' || c == 'Q' || c == KEY_F(9))
2119 exit(EXIT_FAILURE);
2120 }
2121 if (n > 0 && c == ERR) {
2122 c = 0;
2123 break;
2124 }
2125 if (c == ERR)
2126 continue;
2127 if (c == KEY_MOUSE) {
2128 if (getmouse(&event) != OK) {
2129 c = 0;
2130 continue;
2131 }
2132 if (event.bstate & BUTTON4_PRESSED) {
2133 return KEY_UP;
2134 } else if (event.bstate & BUTTON5_PRESSED) {
2135 return KEY_DOWN;
2136 }
2137 if (event.bstate & BUTTON1_CLICKED || event.bstate & BUTTON1_DOUBLE_CLICKED) {
2138 if (wenclose(win, event.y, event.x)) {
2139 wmouse_trafo(win, &event.y, &event.x, false);
2140 click_y = event.y;
2141 click_x = event.x;
2142 if (chyron && event.y == getmaxy(win) - 1) {
2143 c = get_chyron_key(chyron, event.x);
2144 break;
2145 } else
2146 break;
2147 }
2148 c = ERR;
2149 continue;
2150 }
2151 }
2152 } while (c == ERR);
2154 return c;
2155}
2156/** dxwgetch
2157 @brief Wrapper for wgetch that handles signals, mouse events, checks for
2158 clicks on the chyron line, and accepts a sinigle character answer
2159 @ingroup window_support
2160 @param win_0 Pointer to window 0
2161 @param win_1 Pointer to window 1
2162 @param win_2 Pointer to window 2
2163 @param win_3 Pointer to window 3
2164 @param win_c Pointer to chyron window
2165 @param chyron Pointer to chyron struct
2166 @param n Number of seconds to wait before timing out
2167 @verbatim
2168
2169 0: Wait indefinitely for user input (raw mode)
2170 accept a single character answer, and don't wait for Enter key
2171 1: Wait for 1 decisecond
2172 n > 1: Wait for n/10 seconds
2173
2174 @endverbatim
2175 @return Key code or ERR if interrupted by signal
2176 @details Get mouse event and check if it's a left click or double click. If
2177 the click is outside the windows, ignore it. If it's on the chyron line, get
2178 the corresponding key command. Otherwise, store the click coordinates as
2179 click_y and click_x for later use. */
2180int dxwgetch(WINDOW *win_0, WINDOW *win_1, WINDOW *win_2, WINDOW *win_3, WINDOW *win_c, Chyron *chyron, int n) {
2181 int c;
2182 MEVENT event;
2183 mousemask(BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED | BUTTON4_PRESSED | BUTTON5_PRESSED,
2184 nullptr);
2185 click_y = event.y = -1;
2186 click_x = event.x = -1;
2187
2188 if (n == -1) {
2189 struct termios raw_tioctl;
2190 raw_tioctl = curses_tioctl;
2191 mk_raw_tioctl(&raw_tioctl);
2192 } else if (n == 0)
2193 halfdelay(1);
2194 else
2195 halfdelay(min(255, max(0, n * 10)));
2196 tcflush(2, TCIFLUSH);
2197 do {
2198 curs_set(1);
2199 c = wgetch(win_0);
2200 curs_set(0);
2201 if (sig_received != 0) {
2203 c = display_error(em0, em1, em2, nullptr);
2204 if (c == 'q' || c == 'Q' || c == KEY_F(9))
2205 exit(EXIT_FAILURE);
2206 }
2207 if (n > 0 && c == ERR) {
2208 c = 0;
2209 break;
2210 }
2211 if (c == ERR)
2212 continue;
2213 if (c == KEY_MOUSE) {
2214 if (getmouse(&event) != OK) {
2215 c = 0;
2216 continue;
2217 }
2218 if (event.bstate & BUTTON4_PRESSED) {
2219 return KEY_UP;
2220 } else if (event.bstate & BUTTON5_PRESSED) {
2221 return KEY_DOWN;
2222 }
2223 if (event.bstate & BUTTON1_CLICKED || event.bstate & BUTTON1_DOUBLE_CLICKED) {
2224 // Check if the click is in win_0, win_1, or win_2, and set
2225 // mouse_win
2226 // accordingly
2227 // don't free mouse_win, since it is borrowed
2228 mouse_win = nullptr;
2229 if (win_1 != nullptr && wenclose(win_1, event.y, event.x) && wmouse_trafo(win_1, &event.y, &event.x, false))
2230 mouse_win = win_1;
2231 else if (win_2 != nullptr && wenclose(win_2, event.y, event.x) && wmouse_trafo(win_2, &event.y, &event.x, false))
2232 mouse_win = win_2;
2233 else if (win_3 != nullptr && wenclose(win_3, event.y, event.x) && wmouse_trafo(win_3, &event.y, &event.x, false))
2234 mouse_win = win_3;
2235 click_y = event.y;
2236 click_x = event.x;
2237 if (mouse_win == nullptr) {
2238 c = 0;
2239 break;
2240 }
2241 if (mouse_win == win_c && chyron && (event.y == getmaxy(mouse_win) - 1))
2242 c = get_chyron_key(chyron, event.x);
2243 break;
2244 }
2245 }
2246 } while (c == ERR);
2248 return c;
2249}
2250/** vgetch
2251 @brief Wrapper for wgetch that handles signals and mouse events, and accepts a single character answer
2252 @ingroup window_support
2253 @param win Pointer to window
2254 @param n Number of seconds to wait before timing out
2255 @return Key code or ERR if interrupted by signal
2256 @details This function is similar to xwgetch, but it does not handle chyron clicks. It sets the terminal to raw mode if n is -1, or halfdelay mode if n is 0 or greater. It waits for user input and returns the key code. If a signal is received, it handles the signal and may display an error message. If the user presses 'q', 'Q', or F9, the program exits.
2257 */
2258int vgetch(WINDOW *win, int n) {
2259 int c;
2260 mousemask(0, nullptr);
2261
2262 curs_set(1);
2263 if (n == -1) {
2264 struct termios raw_tioctl;
2265 raw_tioctl = curses_tioctl;
2266 mk_raw_tioctl(&raw_tioctl);
2267 } else if (n == 0)
2268 halfdelay(1);
2269 else
2270 halfdelay(min(255, max(0, n * 10)));
2271 do {
2272 c = wgetch(win);
2273 if (n > 0 && c == ERR) {
2274 c = 0;
2275 break;
2276 }
2277 } while (c == ERR);
2278 curs_set(0);
2279 // restore_curses_tioctl();
2280 return c;
2281}
cchar_t CC_YELLOW
Definition dwin.c:216
volatile sig_atomic_t sig_received
Definition sig.c:31
const wchar_t bw_chk
Definition dwin.c:152
bool handle_signal(sig_atomic_t)
int cp_box
Definition dwin.c:179
#define BW_RBL
Definition cm.h:588
#define MAXWIN
Definition cm.h:37
const wchar_t bw_rt
Definition dwin.c:145
int cp_brackets
Definition dwin.c:190
const wchar_t bw_ho
Definition dwin.c:138
int cp_nt
Definition dwin.c:183
int cp_nt_hl
Definition dwin.c:185
int cp_ind
Definition dwin.c:180
int clr_pair_cnt
Definition dwin.c:197
WINDOW * win_win[MAXWIN]
Definition dwin.c:52
cchar_t tl
Definition cm.h:501
cchar_t chk
Definition cm.h:631
cchar_t la
Definition cm.h:631
#define BW_DA
Definition cm.h:599
const wchar_t bw_tl
Definition dwin.c:140
const wchar_t bw_ua
Definition dwin.c:149
cchar_t CC_FILL_CHAR
Definition dwin.c:211
char em1[MAXLEN]
Definition dwin.c:176
PANEL * panel_win2[MAXWIN]
Definition dwin.c:55
cchar_t ua
Definition cm.h:631
int cp_title
Definition dwin.c:182
int tty_fd
Definition dwin.c:219
int cp_yellow
Definition dwin.c:193
#define BW_HO
Definition cm.h:580
WINDOW * win_win2[MAXWIN]
Definition dwin.c:51
#define BW_VE
Definition cm.h:581
int clr_cnt
Definition dwin.c:195
bool f_curses_open
Definition sig.c:33
#define BW_LT
Definition cm.h:590
cchar_t CC_BLUE
Definition dwin.c:217
#define BW_RTR
Definition cm.h:587
cchar_t da
Definition cm.h:631
#define CHYRON_KEYS
Definition cm.h:333
struct termios shell_tioctl curses_tioctl
Definition scriou.c:34
cchar_t br
Definition cm.h:501
WINDOW * mouse_win
Definition dwin.c:118
const wchar_t bw_tr
Definition dwin.c:141
cchar_t CC_NT
Definition dwin.c:204
cchar_t rs
Definition cm.h:501
#define BW_RT
Definition cm.h:592
cchar_t lt
Definition cm.h:631
int clr_pair_idx
Definition dwin.c:196
cchar_t CC_GREEN
Definition dwin.c:215
cchar_t ran
Definition cm.h:631
const wchar_t bw_ran
Definition dwin.c:151
int cp_blue
Definition dwin.c:194
cchar_t CC_IND
Definition dwin.c:200
cchar_t CC_BRKTL
Definition cm.h:494
const wchar_t bw_sp
Definition dwin.c:146
int border_draw(WINDOW *)
Definition dwin.c:1236
const wchar_t bw_ra
Definition dwin.c:147
cchar_t CC_BOX
Definition dwin.c:199
#define BW_UA
Definition cm.h:598
const wchar_t bw_da
Definition dwin.c:150
cchar_t sp
Definition cm.h:631
cchar_t CC_TITLE
Definition dwin.c:203
int cp_red
Definition dwin.c:191
#define BW_RAN
Definition cm.h:600
const wchar_t bw_lt
Definition dwin.c:144
SCREEN * screen
Definition dwin.c:42
cchar_t bl
Definition cm.h:501
const wchar_t bw_la
Definition dwin.c:148
int click_x
Definition dwin.c:81
int cp_nt_hl_rev
Definition dwin.c:186
#define CHYRON_KEY_MAXLEN
Definition cm.h:330
int src_line
Definition dwin.c:172
cchar_t CC_RED
Definition dwin.c:214
char * src_name
Definition dwin.c:173
#define BW_SP
Definition cm.h:595
#define BW_RBR
Definition cm.h:589
PANEL * panel_win[MAXWIN]
Definition dwin.c:56
const wchar_t bw_bl
Definition dwin.c:142
int win_ptr
Definition dwin.c:164
@ CLR_CMDLN_BG
Definition cm.h:187
@ CLR_FILL_CHAR_BG
Definition cm.h:183
@ CLR_BOX_BG
Definition cm.h:177
@ CLR_FILL_CHAR_FG
Definition cm.h:182
@ CLR_FG
Definition cm.h:174
@ CLR_RED
Definition cm.h:158
@ CLR_NT_FG
Definition cm.h:188
@ CLR_BRACKETS_FG
Definition cm.h:180
@ CLR_YELLOW
Definition cm.h:160
@ CLR_IND_FG
Definition cm.h:178
@ CLR_BCYAN
Definition cm.h:171
@ CLR_TITLE_FG
Definition cm.h:196
@ CLR_WHITE
Definition cm.h:164
@ CLR_MAGENTA
Definition cm.h:162
@ CLR_BRACKETS_BG
Definition cm.h:181
@ CLR_NT_REV_BG
Definition cm.h:191
@ CLR_BLACK
Definition cm.h:157
@ CLR_BWHITE
Definition cm.h:172
@ CLR_LN_BG
Definition cm.h:185
@ CLR_NT_HL_REV_BG
Definition cm.h:195
@ CLR_BBLACK
Definition cm.h:165
@ CLR_LN_FG
Definition cm.h:184
@ CLR_NT_HL_FG
Definition cm.h:192
@ CLR_BBLUE
Definition cm.h:169
@ CLR_BGREEN
Definition cm.h:167
@ CLR_BYELLOW
Definition cm.h:168
@ CLR_BMAGENTA
Definition cm.h:170
@ CLR_BORANGE
Definition cm.h:173
@ CLR_NT_HL_BG
Definition cm.h:193
@ CLR_NT_HL_REV_FG
Definition cm.h:194
@ CLR_BG
Definition cm.h:175
@ CLR_BOX_FG
Definition cm.h:176
@ CLR_NT_BG
Definition cm.h:189
@ CLR_TITLE_BG
Definition cm.h:197
@ CLR_BRED
Definition cm.h:166
@ CLR_NCOLORS
Definition cm.h:198
@ CLR_BLUE
Definition cm.h:161
@ CLR_IND_BG
Definition cm.h:179
@ CLR_GREEN
Definition cm.h:159
@ CLR_CMDLN_FG
Definition cm.h:186
@ CLR_NT_REV_FG
Definition cm.h:190
@ CLR_CYAN
Definition cm.h:163
#define BW_LA
Definition cm.h:597
int exit_code
Definition dwin.c:159
FILE * tty_fp
Definition dwin.c:43
#define BW_RA
Definition cm.h:596
int cp_green
Definition dwin.c:192
int click_y
Definition dwin.c:80
#define min(x, y)
min macro evaluates two expressions, returning least result
Definition cm.h:89
char em0[MAXLEN]
Definition dwin.c:175
cchar_t CC_NT_HL
Definition dwin.c:207
cchar_t ts
Definition cm.h:501
char em3[MAXLEN]
Definition dwin.c:178
cchar_t CC_CMDLN
Definition dwin.c:202
PANEL * panel_box[MAXWIN]
Definition dwin.c:57
char const colors_text[][10]
Color names for .minitrc overrides.
Definition dwin.c:133
#define BW_CHK
Definition cm.h:603
const wchar_t bw_ve
Definition dwin.c:139
cchar_t CC_NT_REV
Definition dwin.c:205
int cp_nt_rev
Definition dwin.c:184
#define BW_RTL
Definition cm.h:586
cchar_t tr
Definition cm.h:501
cchar_t ra
Definition cm.h:631
cchar_t ls
Definition cm.h:631
int win_attr
Definition dwin.c:162
cchar_t rt
Definition cm.h:631
WINDOW * win_box[MAXWIN]
Definition dwin.c:53
int cp_fill_char
Definition dwin.c:189
char fn[MAXLEN]
Definition dwin.c:174
char em2[MAXLEN]
Definition dwin.c:177
const wchar_t bw_br
Definition dwin.c:143
cchar_t bs
Definition cm.h:501
cchar_t CC_BRKTR
Definition cm.h:495
cchar_t CC_LN
Definition dwin.c:201
cchar_t CC_NT_HL_REV
Definition dwin.c:206
#define max(a, b)
max macro evaluates two expressions, returning greatest result.
Definition cm.h:82
#define TRUE
Definition iloan.c:19
#define MAXLEN
Definition curskeys.c:15
int box_attr
Definition dwin.c:163
unsigned int cmd_key
Definition dwin.c:160
WINDOW * win_main
Definition dwin.c:82
int pipe_in
Definition dwin.c:219
bool f_sigwench
Definition dwin.c:161
int m_cols
Definition dwin.c:166
UiSurface * ui_box[MAXWIN]
Definition dwin.c:46
RGB StdColors[16]
Definition dwin.c:127
int m_begy
Definition dwin.c:167
int m_begx
Definition dwin.c:168
int stdout_fd
Definition dwin.c:171
double BLUE_GAMMA
Definition dwin.c:157
cchar_t CC_NORM
Definition dwin.c:208
int mouse_support
Definition dwin.c:169
int cp_ln
Definition dwin.c:187
int m_lines
Definition dwin.c:165
UiSurface * ui_win2[MAXWIN]
Definition dwin.c:48
UiRuntime * ui_runtime
Definition dwin.c:44
cchar_t CC_BG
Definition dwin.c:198
cchar_t CC_RAN
Definition dwin.c:213
UiRect ui_rect
Definition dwin.c:49
UiSurface * ui_win[MAXWIN]
Definition dwin.c:47
cchar_t CC_CHK
Definition dwin.c:212
int stdin_fd
Definition dwin.c:170
double GRAY_GAMMA
Definition dwin.c:154
double RED_GAMMA
Definition dwin.c:155
int cp_cmdln
Definition dwin.c:181
PANEL * panel_main
Definition dwin.c:83
int pipe_out
Definition dwin.c:219
double GREEN_GAMMA
Definition dwin.c:156
UiConfig * ui_config
Definition dwin.c:45
int cp_norm
Definition dwin.c:188
WinFlags
Definition dwin.c:36
@ WF_WIN2
Definition dwin.c:39
@ WF_BOX
Definition dwin.c:37
@ WF_WIN
Definition dwin.c:38
bool open_curses(SIO *)
Initialize NCurses and color settings.
Definition dwin.c:244
int border_title(WINDOW *, char *)
Draw a box with a title around the specified window.
Definition dwin.c:1327
int dxwgetch(WINDOW *, WINDOW *, WINDOW *, WINDOW *, WINDOW *, Chyron *, int)
Wrapper for wgetch that handles signals, mouse events, checks for clicks on the chyron line,...
Definition dwin.c:2180
int xwgetch(WINDOW *, Chyron *, int)
Wrapper for wgetch that handles signals, mouse events, checks for clicks on the chyron line,...
Definition dwin.c:2094
void restore_wins()
Restore all windows after a screen resize.
Definition dwin.c:1225
void win_del()
Delete the current window and its associated box window.
Definition dwin.c:1179
void check_panels(int)
Check and display the panels for a given window index.
Definition dwin.c:1090
int border_hsplit_text(WINDOW *, char *, int)
Draw a box with a separator line and text around the specified window.
Definition dwin.c:1289
int bare_box_new(int, int, int, int, char *)
Create a new window with optional box and title.
Definition dwin.c:981
int win_new(int, int)
Create a new window with specified dimensions and position.
Definition dwin.c:1037
int border_hsplit(WINDOW *, int)
Draw a box with a separator line around the specified window.
Definition dwin.c:1269
void win_init_attrs()
Initialize window attributes.
Definition dwin.c:226
void mvwaddstr_fill(WINDOW *, int, int, char *, int)
For lines shorter than their display area, fill the rest with spaces.
Definition dwin.c:1941
int box_new(int, int, int, int, char *)
Create a new window with optional box and title.
Definition dwin.c:967
int box_hsplit_new(int, int, int, int, int, char *)
Create a new window with optional box and title, and a second window inside it, split horizontally.
Definition dwin.c:925
int win2_new(int, int, int, int)
Create a new subwindow (win2) with specified dimensions and position.
Definition dwin.c:1066
int vgetch(WINDOW *, int)
Wrapper for wgetch that handles signals and mouse events, and accepts a single character answer.
Definition dwin.c:2258
void win_resize(int, int, char *)
Resize the current window and its box, and update the title.
Definition dwin.c:1128
void destroy_curses()
Gracefully shut down NCurses and restore terminal settings.
Definition dwin.c:670
void win_redraw(WINDOW *)
Redraw the specified window.
Definition dwin.c:1168
int win2_box_new(int, int, int, int, char *)
Create a new window with optional box and title, and a second window inside it.
Definition dwin.c:952
void initialize_local_colors(SIO *)
Initialize local color variables and color pairs based on SIO settings.
Definition dwin.c:320
void display_cmplx_str(WINDOW *, cchar_t *, int, int)
Display a complex character string on a window.
Definition dwin.c:857
RGB xterm256_idx_to_rgb(int)
Convert XTerm 256 color index to RGB.
Definition dwin.c:483
size_t str_to_cc(cchar_t *, const char *, attr_t, int, size_t)
Convert a multibyte string to an array of cchar_t complex characters.
Definition dwin.c:786
int clr_name_to_idx(char *)
Get color index from color name.
Definition dwin.c:1966
void list_colors()
list colors to stderr
Definition dwin.c:1985
int rgb_to_curses_clr(RGB *)
Get color index for RGB color.
Definition dwin.c:432
size_t mk_cmplx_str(cchar_t *, char *, attr_t, int)
Convert a multibyte string to an array of cchar_t complex characters.
Definition dwin.c:828
void init_hex_clr(int, char *)
Initialize extended ncurses color from HTML style hex string.
Definition dwin.c:638
bool init_clr_palette(SIO *)
Initialize color palette based on SIO settings.
Definition dwin.c:546
RGB hex_clr_str_to_rgb(char *)
Convert six-digit HTML style hex color code to RGB struct.
Definition dwin.c:656
void apply_gamma(RGB *)
Apply gamma correction to RGB color.
Definition dwin.c:518
int rgb_to_xterm256_idx(RGB *)
Convert RGB color to XTerm 256 color index.
Definition dwin.c:461
cchar_t mkcc(int, attr_t, const char *)
Create a cchar_t with the specified color pair index.
Definition dwin.c:748
int get_clr_pair(int, int)
Get color pair index for foreground and background colors.
Definition dwin.c:401
WINDOW * message_win(char *)
Display a message in a window or print to stderr if curses is not available.
Definition dwin.c:1377
bool wait_destroy(Chyron *)
Destroy the waiting message window and chyron.
Definition dwin.c:1621
bool waitpid_with_timeout(pid_t, int)
Wait for a process to finish with a timeout and optional user cancellation.
Definition dwin.c:2033
bool action_disposition(char *eitle, char *action_str)
Display a simple action disposition message window or print to stderr.
Definition dwin.c:1651
int nf_error(int, char *)
Display error message and wait for key press.
Definition dwin.c:2006
int answer_yn(char *, char *, char *, char *)
Accept a single letter answer.
Definition dwin.c:1406
int wait_continue(WINDOW *, Chyron *, int)
Update the waiting message with remaining time and check for user input.
Definition dwin.c:1636
WINDOW * wait_mk_win(Chyron *, char *)
Display a popup waiting message.
Definition dwin.c:1589
int Perror(char *)
Display a simple error message window or print to stderr.
Definition dwin.c:1526
void abend(int, char *)
Abnormal program termination.
Definition dwin.c:2018
Chyron * wait_mk_chyron()
Create a Chyron struct for the waiting message.
Definition dwin.c:1576
int display_error(char *, char *, char *, char *)
Display an error message window or print to stderr.
Definition dwin.c:1467
bool is_set_chyron_key(Chyron *, int)
Check if function key label is set.
Definition dwin.c:1743
void set_chyron_key(Chyron *, int, char *, int)
Set chyron key with default color pair (cp_nt_rev).
Definition dwin.c:1783
void display_chyron(WINDOW *, Chyron *, int, int)
Display chyron on window.
Definition dwin.c:1892
Chyron * destroy_chyron(Chyron *chyron)
Destroy Chyron structure.
Definition dwin.c:1722
void activate_chyron_key(Chyron *, int)
Activate chyron key.
Definition dwin.c:1807
int get_chyron_key(Chyron *, int)
Get keycode from chyron.
Definition dwin.c:1917
void set_chyron_key_cp(Chyron *, int, char *, int, int)
Set chyron key with color pair (cp).
Definition dwin.c:1759
void compile_chyron(Chyron *)
construct the chyron string from the chyron structure
Definition dwin.c:1848
void activate_all_chyron_keys(Chyron *)
Deactivate chyron key.
Definition dwin.c:1816
void unset_chyron_key(Chyron *, int)
Unset chyron key.
Definition dwin.c:1798
int mb_to_cc(cchar_t *, char *, attr_t, int, int *, int)
Convert multibyte string to complex character array.
Definition dwin.c:705
void deactivate_all_chyron_keys(Chyron *)
Deactivate all chyron keys.
Definition dwin.c:1834
void deactivate_chyron_key(Chyron *, int)
Deactivate chyron key.
Definition dwin.c:1826
Chyron * new_chyron()
Create and initialize Chyron structure.
Definition dwin.c:1701
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition futil.c:544
bool str_to_lower(char *)
Converts a string to lowercase.
Definition futil.c:508
void ui_rect_set(UiRect *, int, int, int, int)
Set the properties of a UiRect structure.
Definition dwin.c:908
size_t strnz(char *, size_t)
terminates string at New Line, Carriage Return, or max_len
Definition futil.c:615
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition futil.c:420
int wccp_to_str(wchar_t, uint8_t *)
Converts a Unicode code point to a UTF-8 encoded string.
Definition dwin.c:871
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
Definition futil.c:573
char di_getch()
get single character from terminal in raw mode
Definition scriou.c:148
bool restore_curses_tioctl()
restore_curses_tioctl() - restore curses terminal settings
Definition scriou.c:81
bool mk_raw_tioctl(struct termios *)
mk_raw_tioctl() - set terminal to raw mode
Definition scriou.c:126
bool restore_shell_tioctl()
restore_shell_tioctl() - restore shell terminal settings
Definition scriou.c:56
void sig_dfl_mode()
Set signal handlers to default behavior.
Definition sig.c:42
void ui_get_screen_size(UiRuntime *ui, int *rows, int *cols)
Get the current screen size.
Definition ui_ncurses.c:257
char text[CHYRON_KEY_MAXLEN]
Definition cm.h:337
int end_pos
Definition cm.h:340
int cp
Definition cm.h:341
int keycode
Definition cm.h:339
bool active
Definition cm.h:336
int l
Definition cm.h:348
cchar_t cmplx_buf[MAXLEN]
Definition cm.h:347
ChyronKey * key[CHYRON_KEYS]
Definition cm.h:345
int r
Definition cm.h:382
int b
Definition cm.h:382
int g
Definition cm.h:382
char nt_hl_rev_bg[COLOR_LEN]
Definition cm.h:852
double green_gamma
Definition cm.h:807
char nt_rev_bg[COLOR_LEN]
Definition cm.h:846
char ln_fg[COLOR_LEN]
Definition cm.h:839
char black[COLOR_LEN]
Definition cm.h:810
char title_bg[COLOR_LEN]
Definition cm.h:854
double blue_gamma
Definition cm.h:808
char bred[COLOR_LEN]
Definition cm.h:820
char yellow[COLOR_LEN]
Definition cm.h:813
char nt_hl_bg[COLOR_LEN]
Definition cm.h:848
int stdout_fd
Definition cm.h:861
char nt_hl_fg[COLOR_LEN]
Definition cm.h:847
int stderr_fd
Definition cm.h:862
char ind_fg[COLOR_LEN]
Definition cm.h:833
char bcyan[COLOR_LEN]
Definition cm.h:825
char borange[COLOR_LEN]
Definition cm.h:827
double red_gamma
Definition cm.h:806
char red[COLOR_LEN]
Definition cm.h:811
char nt_fg[COLOR_LEN]
Definition cm.h:843
char magenta[COLOR_LEN]
Definition cm.h:815
char ln_bg[COLOR_LEN]
Definition cm.h:840
char bgreen[COLOR_LEN]
Definition cm.h:821
char nt_rev_fg[COLOR_LEN]
Definition cm.h:845
char brackets_fg[COLOR_LEN]
Definition cm.h:835
char fill_char_fg[COLOR_LEN]
Definition cm.h:837
char byellow[COLOR_LEN]
Definition cm.h:822
char bwhite[COLOR_LEN]
Definition cm.h:826
char box_bg[COLOR_LEN]
Definition cm.h:832
char fg[COLOR_LEN]
Definition cm.h:829
char cyan[COLOR_LEN]
Definition cm.h:816
char brackets_bg[COLOR_LEN]
Definition cm.h:836
char box_fg[COLOR_LEN]
Definition cm.h:831
char tty_name[MAXLEN]
Definition cm.h:855
char fill_char_bg[COLOR_LEN]
Definition cm.h:838
char green[COLOR_LEN]
Definition cm.h:812
char white[COLOR_LEN]
Definition cm.h:817
char bg[COLOR_LEN]
Definition cm.h:830
char bblue[COLOR_LEN]
Definition cm.h:823
char title_fg[COLOR_LEN]
Definition cm.h:853
char bmagenta[COLOR_LEN]
Definition cm.h:824
char blue[COLOR_LEN]
Definition cm.h:814
char nt_hl_rev_fg[COLOR_LEN]
Definition cm.h:850
int stdin_fd
Definition cm.h:860
double gray_gamma
Definition cm.h:809
char bblack[COLOR_LEN]
Definition cm.h:819
char ind_bg[COLOR_LEN]
Definition cm.h:834
char nt_bg[COLOR_LEN]
Definition cm.h:844
int cols
Definition ui_backend.h:200
int rows
Definition ui_backend.h:199