2
3
4
5
6
7
8
9
10
11
12
13
16
17
34int box_new(
int,
int,
int,
int,
char *, bool);
35int box2_new(
int,
int,
int,
int,
char *, bool);
45void abend(
int,
char *);
70int mb_to_cc(cchar_t *,
char *, attr_t,
int,
int *,
int);
74int xwgetch(WINDOW *, Chyron *,
int);
75cchar_t
mkccc(
int, attr_t,
char *);
83
84
86 {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}};
88
89
90
92 "black",
"red",
"green",
"yellow",
"blue",
"magenta",
"cyan",
93 "white",
"orange",
"bg",
"abg",
"bblack",
"bred",
"bgreen",
94 "byellow",
"bblue",
"bcyan",
"bmagenta",
"bwhite",
"borange",
""};
172
173
174
175
179
180
181
182
183
184
185
186
187
188
189
190
191
197 strerror_r(errno, tmp_str,
MAXLEN - 1);
200 fprintf(stderr,
"%s\n", tmp_str);
206 strerror_r(errno, tmp_str,
MAXLEN - 1);
209 fprintf(stderr,
"%s\n", tmp_str);
216 strerror_r(errno, tmp_str,
MAXLEN - 1);
219 fprintf(stderr,
"%s\n", tmp_str);
226 abend(-1
, "Terminal color support required");
229 if (!can_change_color()) {
231 fprintf(stderr,
"Terminal cannot change colors\n");
232 fprintf(stderr,
"Check TERM environment variable\n");
233 fprintf(stderr,
"Check terminfo for missing \"ccc\"\n");
264 keypad(stdscr, true);
265 idlok(stdscr, false);
266 idcok(stdscr, false);
267 wbkgrndset(stdscr, &
CCC_NT);
269 immedok(stdscr, true);
275
276
277
279
280
281
282
283
287 extended_pair_content(i, &pfg, &pbg);
288 if (pfg == fg && pbg == bg)
291 if (i >= COLOR_PAIRS) {
297 return (EXIT_FAILURE);
299 if (i < COLOR_PAIRS) {
300 rc = init_extended_pair(i, fg, bg);
309
310
311
312
313
314
319 rgb
->r = (rgb
->r * 1000) / 255;
320 rgb
->g = (rgb
->g * 1000) / 255;
321 rgb
->b = (rgb
->b * 1000) / 255;
322 for (i = 0; i <
clr_cnt; i++) {
323 extended_color_content(i, &r, &g, &b);
324 if (rgb
->r == r && rgb
->g == g && rgb
->b == b) {
329 init_extended_color(i, rgb
->r, rgb
->g, rgb
->b);
336
337
338
339
340
341
342
343
350 return ((rgb
->r - 8) / 10) + 231;
352 int r_index = (rgb
->r < 45) ? 0 : (rgb
->r - 60) / 40 + 1;
353 int g_index = (rgb
->g < 45) ? 0 : (rgb
->g - 60) / 40 + 1;
354 int b_index = (rgb
->b < 45) ? 0 : (rgb
->b - 60) / 40 + 1;
355 return 16 + (36 * r_index) + (6 * g_index) + b_index;
359
360
361
362
363
364
365
368
369
375 rgb
.r = rgb
.g = rgb
.b = 0;
380 }
else if (idx >= 16 && idx <= 231) {
382 rgb
.r = (idx / 36) % 6 * 51;
383 rgb
.g = (idx / 6) % 6 * 51;
384 rgb
.b = (idx % 6) * 51;
385 }
else if (idx >= 232 && idx <= 255) {
386 int gray = (idx - 232) * 11;
387 rgb
.r = rgb
.g = rgb
.b = gray;
393
394
395
396
397
398
399
400
418
419
420
421
422
423
424
425
426
427
428
499
500
501
502
503
504
505
506
507
517 rgb
.r = (rgb
.r * 1000) / 255;
518 rgb
.g = (rgb
.g * 1000) / 255;
519 rgb
.b = (rgb
.b * 1000) / 255;
520 init_extended_color(idx, rgb
.r, rgb
.g, rgb
.b);
523
524
525
528 sscanf(s,
"#%02x%02x%02x", &rgb
.r, &rgb
.g, &rgb
.b);
532
533
534
535
536
537
538
539
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582int mb_to_cc(cchar_t *cmplx_buf,
char *str, attr_t attr,
int cpx,
int *pos,
587 wchar_t wstr[2] = {L'\0', L'\0'};
589 memset(&mbstate, 0,
sizeof(mbstate));
591 if (*pos >= maxlen - 1)
593 while (str[i] !=
'\0') {
595 len = mbrtowc(wstr, s, MB_CUR_MAX, &mbstate);
602 if (*pos >= maxlen - 1)
604 if (setcchar(&cc, wstr, attr, cpx,
nullptr) != ERR) {
605 if (len > 0 && (*pos + len) <
MAXLEN - 1)
606 cmplx_buf[(*pos)++] = cc;
612 setcchar(&cc, wstr, attr, cpx,
nullptr);
613 cmplx_buf[*pos] = cc;
617
618
619
620
621
622
623
624
625cchar_t
mkccc(
int cp, attr_t attr,
char *s) {
627 wchar_t wstr[2] = {L'\0', L'\0'};
629 memset(&mbstate, 0,
sizeof(mbstate));
630 mbrtowc(wstr, s, MB_CUR_MAX, &mbstate);
631 setcchar(&cc, wstr, attr, cp,
nullptr);
635
636
637
638
639
640
641
642
643
644
645
646
647
650 wchar_t wstr[2] = {L'\0', L'\0'};
652 memset(&mbstate, 0,
sizeof(mbstate));
653 size_t len = strlen(s);
654 cmplx_buf = calloc(len + 1,
sizeof(cchar_t));
657 mbrtowc(wstr, s, MB_CUR_MAX, &mbstate);
658 setcchar(&cc, wstr, attr, cp,
nullptr);
660 s += mbrlen(s, MB_CUR_MAX, &mbstate);
664 setcchar(&cc, wstr, attr, cp,
nullptr);
669
670
671
672
673
674
675
676
677
682 wadd_wchstr(win, cmplx_buf);
683 wmove(win, line, col);
688
689
690
691
692
693
694
695
696
697int box2_new(
int wlines,
int wcols,
int wbegy,
int wbegx,
char *wtitle,
705 wlines =
min(wlines, LINES - 2);
706 wcols =
min(wcols, COLS - 2);
713 immedok(win_box[win_ptr], true);
721 int s = strlen(wtitle);
736
737
738
739
740
741
742
743
744
745int box_new(
int wlines,
int wcols,
int wbegy,
int wbegx,
char *wtitle,
753 wlines =
min(wlines, LINES - 2);
754 wcols =
min(wcols, COLS - 2);
761 immedok(win_box[win_ptr], true);
769 int s = strlen(wtitle);
781
782
783
784
785
786
787
788int win_new(
int wlines,
int wcols,
int wbegy,
int wbegx) {
797 immedok(win_win[win_ptr], true);
807
808
809
810
811
812
813
814int win2_new(
int wlines,
int wcols,
int wbegy,
int wbegx) {
823 immedok(win_win2[win_ptr], true);
832
833
834
835
836
837
838
839
840
847 if (title !=
nullptr && *title !=
'\0') {
856 int s = strlen(title);
871 immedok(win_win[win_ptr], true);
875
876
877
878
879
880
886
887
888
889
890
891
892
911 for (i = 0; i <
win_ptr; i++) {
926
927
928
929
930
931
932
935 for (i = 0; i <=
win_ptr; i++) {
949
950
951
952
953
954
955
956
964 mvwaddnwstr(box, 0, 0, &
bw_tl, 1);
965 for (x = 1; x < maxx; x++)
966 waddnwstr(box, &
bw_ho, 1);
967 waddnwstr(box, &
bw_tr, 1);
970 for (y = 1; y < maxy; y++) {
971 mvwaddnwstr(box, y, 0, &
bw_ve, 1);
972 mvwaddnwstr(box, y, maxx, &
bw_ve, 1);
974 mvwaddnwstr(box, maxy, 0, &
bw_bl, 1);
975 for (x = 1; x < maxx; x++)
976 waddnwstr(box, &
bw_ho, 1);
977 waddnwstr(box, &
bw_br, 1);
980
981
982
983
984
985
986
987
988
996 mvwaddnwstr(box, 0, 0, &
bw_tl, 1);
997 for (x = 1; x < maxx; x++)
998 waddnwstr(box, &
bw_ho, 1);
999 waddnwstr(box, &
bw_tr, 1);
1000 maxy = getmaxy(box);
1002 for (y = 1; y < maxy - 4; y++) {
1003 mvwaddnwstr(box, y, 0, &
bw_ve, 1);
1004 mvwaddnwstr(box, y, maxx, &
bw_ve, 1);
1007 mvwaddnwstr(box, y, 0, &
bw_lt, 1);
1009 mvwaddnwstr(box, y, 1, &
bw_rt, 1);
1010 mvwaddnwstr(box, y, 24, &
bw_lt, 1);
1011 for (x = 25; x < maxx; x++)
1012 waddnwstr(box, &
bw_ho, 1);
1013 waddnwstr(box, &
bw_rt, 1);
1016 mvwaddnwstr(box, y, 0, &
bw_ve, 1);
1017 mvwaddnwstr(box, y, maxx, &
bw_ve, 1);
1019 mvwaddnwstr(box, y, 0, &
bw_ve, 1);
1020 mvwaddnwstr(box, y, maxx, &
bw_ve, 1);
1023 mvwaddnwstr(box, y, 0, &
bw_bl, 1);
1024 for (x = 1; x < maxx; x++)
1025 waddnwstr(box, &
bw_ho, 1);
1026 waddnwstr(box, &
bw_br, 1);
1030
1031
1034
1035
1036
1037
1038
1039
1040
1043 int line, pos, em_l, em0_l, em1_l, em2_l, em3_l;
1047 fprintf(stderr,
"\n\n%s\n%s\n%s\n%s\n\n", em0, em1, em2, em3);
1061 em_l =
max(em0_l, em1_l);
1062 em_l =
max(em_l, em2_l);
1063 em_l =
max(em_l, em3_l);
1064 em_l =
max(em_l, chyron
->l);
1065 em_l =
min(em_l, COLS - 4);
1067 pos = ((COLS - em_l) - 4) / 2;
1068 line = (LINES - 6) / 2;
1072 em_l + 2
, line
, pos
, title
);
1077 mvwaddstr(error_win, 0, 1, em0);
1078 mvwaddstr(error_win, 1, 1, em1);
1079 mvwaddstr(error_win, 2, 1, em2);
1080 mvwaddstr(error_win, 3, 1, em3);
1095
1096
1097
1098
1099
1100
1101
1104 int line, pos, em_l, em0_l, em1_l, em2_l, em3_l;
1108 fprintf(stderr,
"\n\n%s\n", em0);
1109 fprintf(stderr,
"%s\n", em1);
1110 fprintf(stderr,
"%s\n", em2);
1111 fprintf(stderr,
"%s\n\n", em3);
1125 em_l =
max(em0_l, em1_l);
1126 em_l =
max(em_l, em2_l);
1127 em_l =
max(em_l, em3_l);
1128 em_l =
max(em_l, chyron
->l);
1129 em_l =
min(em_l, COLS - 4);
1131 pos = ((COLS - em_l) - 4) / 2;
1132 line = (LINES - 6) / 2;
1136 em_l + 2
, line
, pos
, title
);
1141 mvwaddstr(error_win, 0, 1, em0);
1142 mvwaddstr(error_win, 1, 1, em1);
1143 mvwaddstr(error_win, 2, 1, em2);
1144 mvwaddstr(error_win, 3, 1, em3);
1158
1159
1160
1161
1164 int emsg_max_len = 80;
1169 bool f_xwgetch = true;
1170 if (emsg_str[0] ==
'␛' && emsg_str[1] ==
'w') {
1176 fprintf(stderr,
"\n%s\n", emsg);
1184 len =
max(strlen(title), strlen(emsg));
1185 len =
max(len, chyron
->l);
1187 pos = (COLS - len - 4) / 2;
1188 line = (LINES - 4) / 2;
1192 4
, line
, line
, pos
, title
);
1197 mvwaddstr(error_win, 0, 1, emsg);
1205 cmd_key = KEY_F(10);
1211
1212
1213
1221
1222
1223
1224
1225
1227 char wm1[] =
"Seconds remaining:";
1233 fprintf(stderr,
"\n%s\n", title);
1234 fprintf(stderr,
"%s\n", wm1);
1237 len =
max(strlen(title), strlen(wm1));
1238 len =
max(len, chyron
->l);
1240 col = (COLS - len - 4) / 2;
1241 line = (LINES - 4) / 2;
1244 line
, line
, col
, title
);
1248 mvwaddstr(wait_win, 0, 1, wm1);
1250 wmove(wait_win, 1, chyron
->l);
1254
1255
1256
1257
1264
1265
1266
1267
1268
1269
1270
1274 mvwaddstr(wait_win, 0, 21, time_str);
1276 wmove(wait_win, 1, chyron
->l);
1281
1282
1283
1284
1285
1289 WINDOW *action_disposition_win;
1292 fprintf(stderr,
"\n%s\n", title);
1293 fprintf(stderr,
"%s\n", action_str);
1299 len =
max(strlen(title), strlen(action_str));
1300 col = (COLS - len - 4) / 2;
1301 line = (LINES - 4) / 2;
1304 line
, line
, col
, title
);
1308 mvwaddstr(action_disposition_win, 0, 1, action_str);
1310 wmove(action_disposition_win, 1, chyron
->l);
1317
1318
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1337 Chyron *chyron = (Chyron *)calloc(1,
sizeof(Chyron));
1343 chyron
->key[i] = (ChyronKey *)calloc(1,
sizeof(ChyronKey));
1347
1348
1349
1350
1351
1359 free(chyron
->key[i]);
1367
1368
1369
1370
1371
1379
1380
1381
1382
1383
1384
1385
1386
1387
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1420
1421
1422
1423
1424
1427
1428
1429
1430
1431
1432
1433
1434
1435
1458 chyron
->l = end_pos;
1463 chyron
->l = end_pos;
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1477 wmove(win, line, 0);
1479 wmove(win, line, 0);
1481 wmove(win, line, col);
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1508
1509
1510
1511
1512
1513
1514
1523 if (*s ==
'\0' || *s ==
'\n')
1529 mvwaddstr(w, y, x, tmp_str);
1532
1533
1534
1535
1551
1552
1553
1554
1558 for (i = 0, col = 0; i < 16; i++, col++) {
1560 fprintf(stderr,
" ");
1564 fprintf(stderr,
"\n");
1566 fprintf(stderr,
" ");
1569 fprintf(stderr,
"\n");
1572
1573
1574
1575
1577 fprintf(stderr,
"ERROR: %s code: %d\n", s, ec);
1578 fprintf(stderr,
"Press a key to continue");
1580 fprintf(stderr,
"\n");
1584
1585
1586
1587
1592 fprintf(stderr,
"\n\nABEND: %s (code: %d)\n", s, ec);
1596
1597
1598
1599
1600
1601
1602
1605 Chyron *wait_chyron;
1607 int remaining = timeout;
1609 waitpid(pid, &status, WNOHANG);
1610 if (WIFEXITED(status) || WIFSIGNALED(status))
1617 while (remaining > 0 &&
cmd_key != KEY_F(9)) {
1622 waitpid(pid, &status, WNOHANG);
1623 if (WIFEXITED(status) || WIFSIGNALED(status)) {
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1654 mousemask(BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED | BUTTON4_PRESSED |
1661 struct termios raw_tioctl;
1667 halfdelay(
min(255,
max(0, n * 10)));
1668 tcflush(2, TCIFLUSH);
1675 if (c ==
'q' || c ==
'Q' || c == KEY_F(9))
1678 if (n > 0 && c == ERR) {
1684 if (c == KEY_MOUSE) {
1685 if (getmouse(&event) != OK) {
1689 if (event.bstate & BUTTON4_PRESSED) {
1692 }
else if (event.bstate & BUTTON5_PRESSED) {
1696 if (event.bstate & BUTTON1_CLICKED ||
1697 event.bstate & BUTTON1_DOUBLE_CLICKED) {
1698 if (wenclose(win, event.y, event.x)) {
1699 wmouse_trafo(win, &event.y, &event.x, false);
1702 if (chyron && event.y == getmaxy(win) - 1) {
1717
1718
1719
1720
1721
1722
1723int dxwgetch(WINDOW *win, WINDOW *win2, Chyron *chyron,
int n) {
1726 mousemask(BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED | BUTTON4_PRESSED |
1733 struct termios raw_tioctl;
1739 halfdelay(
min(255,
max(0, n * 10)));
1740 tcflush(2, TCIFLUSH);
1747 if (c ==
'q' || c ==
'Q' || c == KEY_F(9))
1750 if (n > 0 && c == ERR) {
1756 if (c == KEY_MOUSE) {
1757 if (getmouse(&event) != OK) {
1761 if (event.bstate & BUTTON4_PRESSED) {
1764 }
else if (event.bstate & BUTTON5_PRESSED) {
1768 if (event.bstate & BUTTON1_CLICKED ||
1769 event.bstate & BUTTON1_DOUBLE_CLICKED) {
1774 if (wenclose(win, event.y, event.x)) {
1775 if (wmouse_trafo(win, &event.y, &event.x, false))
1778 wenclose(win2, event.y, event.x) &&
1779 wmouse_trafo(win2, &event.y, &event.x, false))
1787 if (chyron && event.y == getmaxy(
mouse_win) - 1)
volatile sig_atomic_t sig_received
bool handle_signal(sig_atomic_t)
struct termios shell_tioctl curses_tioctl
#define CHYRON_KEY_MAXLEN
#define min(x, y)
min macro evaluates two expressions, returning least result
#define max(a, b)
max macro evaluates two expressions, returning greatest result.
WINDOW * win_win2[MAXWIN]
int dxwgetch(WINDOW *win, WINDOW *win2, Chyron *chyron, int n)
char const colors_text[][10]
Color names for .minitrc overrides.
bool open_curses(SIO *)
Initialize NCurses and color settings.
int xwgetch(WINDOW *, Chyron *, int)
Wrapper for wgetch that handles signals, mouse events, checks for clicks on the chyron line,...
int box_new(int, int, int, int, char *, bool)
Create a new window with optional box and title.
int box2_new(int, int, int, int, char *, bool)
Create a new window with optional box and title.
void restore_wins()
Restore all windows after a screen resize.
void win_init_attrs()
Initialize window attributes.
WINDOW * win_del()
Delete the current window and its associated box window.
void mvwaddstr_fill(WINDOW *, int, int, char *, int)
For lines shorter than their display area, fill the rest with spaces.
int win2_new(int wlines, int wcols, int wbegy, int wbegx)
Create a new window with specified dimensions and position.
void cbox(WINDOW *)
Draw a box around the specified window.
int win_new(int, int, int, int)
Create a new window with specified dimensions and position.
void cbox2(WINDOW *)
Draw a box with a separator line around the specified window.
void win_resize(int, int, char *)
Resize the current window and its box, and update the title.
void destroy_curses()
Gracefully shut down NCurses and restore terminal settings.
void win_redraw(WINDOW *)
Redraw the specified window.
void display_cmplx_str(WINDOW *win, cchar_t *cmplx_buf, int line, int col)
Display a complex character string on a window.
RGB xterm256_idx_to_rgb(int)
Convert XTerm 256 color index to RGB color.
int clr_name_to_idx(char *)
Get color index from color name.
void list_colors()
list colors to stderr
int rgb_to_curses_clr(RGB *)
Get color index for RGB color.
size_t mk_cmplx_str(cchar_t *cmplx_buf, char *s, attr_t attr, int cp)
Convert a multibyte string to an array of cchar_t complex characters.
void init_hex_clr(int, char *)
Initialize extended ncurses color from HTML style hex string.
bool init_clr_palette(SIO *)
Initialize color palette based on SIO settings.
RGB hex_clr_str_to_rgb(char *)
Convert six-digit HTML style hex color code to RGB struct.
void apply_gamma(RGB *)
Apply gamma correction to RGB color.
int rgb_to_xterm256_idx(RGB *)
Convert RGB color to XTerm 256 color index.
cchar_t mkccc(int, attr_t, char *)
Create a cchar_t with the specified color pair index.
int get_clr_pair(int fg, int bg)
Get color pair index for foreground and background colors.
bool wait_destroy(Chyron *)
Destroy the waiting message window and chyron.
bool waitpid_with_timeout(pid_t pid, int timeout)
Wait for a process to finish with a timeout and optional user cancellation.
bool action_disposition(char *title, char *action_str)
Display a simple action disposition message window or print to stderr.
int nf_error(int, char *)
Display error message and wait for key press.
int wait_continue(WINDOW *, Chyron *, int)
Update the waiting message with remaining time and check for user input.
int answer_yn(char *em0, char *em1, char *em2, char *em3)
Accept a single letter answer.
WINDOW * wait_mk_win(Chyron *, char *)
Display a popup waiting message.
int Perror(char *)
Display a simple error message window or print to stderr.
int display_error(char *em0, char *em1, char *em2, char *em3)
Display an error message window or print to stderr.
void abend(int, char *)
Abnormal program termination.
Chyron * wait_mk_chyron()
Create a Chyron struct for the waiting message.
bool is_set_chyron_key(Chyron *, int)
Check if function key label is set.
void set_chyron_key(Chyron *, int, char *, int)
Set chyron key with default color pair (cp_nt_rev).
void display_chyron(WINDOW *win, Chyron *chyron, int line, int col)
Display chyron on window.
Chyron * destroy_chyron(Chyron *chyron)
Destroy Chyron structure.
int get_chyron_key(Chyron *, int)
Get keycode from chyron.
void set_chyron_key_cp(Chyron *, int, char *, int, int)
Set chyron key with color pair (cp).
void compile_chyron(Chyron *)
construct the chyron string from the chyron structure
void unset_chyron_key(Chyron *, int)
Unset chyron key.
int mb_to_cc(cchar_t *, char *, attr_t, int, int *, int)
Convert multibyte string to complex character array.
Chyron * new_chyron()
Create and initialize Chyron structure.
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
bool str_to_lower(char *)
Converts a string to lowercase.
size_t strnz(char *, size_t)
terminates string at New Line, Carriage Return, or max_len
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
char di_getch()
get single character from terminal in raw mode
bool restore_curses_tioctl()
restore_curses_tioctl() - restore curses terminal settings
bool mk_raw_tioctl(struct termios *)
mk_raw_tioctl() - set terminal to raw mode
bool restore_shell_tioctl()
restore_shell_tioctl() - restore shell terminal settings
void sig_dfl_mode()
Set signal handlers to default behavior.
char text[CHYRON_KEY_MAXLEN]
cchar_t cmplx_buf[MAXLEN]
ChyronKey * key[CHYRON_KEYS]
char nt_hl_rev_bg[COLOR_LEN]
char nt_rev_bg[COLOR_LEN]
char nt_rev_fg[COLOR_LEN]
char ln_bg_clr_x[COLOR_LEN]
char nt_hl_rev_fg[COLOR_LEN]