diff --git a/Makefile b/Makefile index 72ba50d..0059265 100755 --- a/Makefile +++ b/Makefile @@ -2,7 +2,8 @@ DESTDIR ?= PREFIX ?= /usr/local MANPREFIX ?= $(PREFIX)/man CFLAGS += -Wall -Wextra -LDLIBS += `pkg-config --libs ncurses` +CFLAGS += `pkg-config --cflags ncursesw` +LDLIBS += `pkg-config --libs ncursesw` torture: LDLIBS = -lm all: ttyplot diff --git a/ttyplot.c b/ttyplot.c index 4afa4db..d47388d 100644 --- a/ttyplot.c +++ b/ttyplot.c @@ -7,6 +7,11 @@ // Apache License 2.0 // +// This is needed on macOS to get the ncurses widechar API, and pkg-config fails to define it. +#ifdef __APPLE__ +#define _XOPEN_SOURCE_EXTENDED +#endif + #include #include // isspace #include @@ -17,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -39,17 +45,15 @@ #define VERSION_STR STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_PATCH) #endif +#define T_RARR '>' +#define T_UARR '^' #ifdef NOACS #define T_HLINE '-' #define T_VLINE '|' -#define T_RARR '>' -#define T_UARR '^' #define T_LLCR 'L' #else #define T_HLINE ACS_HLINE #define T_VLINE ACS_VLINE -#define T_RARR ACS_RARROW -#define T_UARR ACS_UARROW #define T_LLCR ACS_LLCORNER #endif @@ -57,7 +61,7 @@ sigset_t block_sigset; sigset_t empty_sigset; volatile sig_atomic_t sigint_pending = 0; volatile sig_atomic_t sigwinch_pending = 0; -chtype plotchar, max_errchar, min_errchar; +cchar_t plotchar, max_errchar, min_errchar; struct timeval now; double td; struct tm *lt; @@ -161,19 +165,26 @@ void draw_axes(int h, int ph, int pw, double max, double min, char *unit) { mvaddch(h-3, 2, T_LLCR); } -void draw_line(int x, int ph, int l1, int l2, chtype c1, chtype c2, chtype hce, chtype lce) { +void draw_line(int x, int ph, int l1, int l2, cchar_t *c1, cchar_t *c2, cchar_t *hce, cchar_t *lce) { + static cchar_t space = { + .attr = A_REVERSE, + .chars = {' ', '\0'} + }; + cchar_t c1r = *c1, c2r = *c2; + c1r.attr |= A_REVERSE; + c2r.attr |= A_REVERSE; if(l1 > l2) { - mvvline(ph+1-l1, x, c1, l1-l2 ); - mvvline(ph+1-l2, x, c2|A_REVERSE, l2 ); + mvvline_set(ph+1-l1, x, c1, l1-l2 ); + mvvline_set(ph+1-l2, x, &c2r, l2 ); } else if(l1 < l2) { - mvvline(ph+1-l2, x, (c2==hce || c2==lce) ? c2|A_REVERSE : ' '|A_REVERSE, l2-l1 ); - mvvline(ph+1-l1, x, c1|A_REVERSE, l1 ); + mvvline_set(ph+1-l2, x, (c2==hce || c2==lce) ? &c2r : &space, l2-l1 ); + mvvline_set(ph+1-l1, x, &c2r, l1 ); } else { - mvvline(ph+1-l2, x, c2|A_REVERSE, l2 ); + mvvline_set(ph+1-l2, x, &c2r, l2 ); } } -void plot_values(int ph, int pw, double *v1, double *v2, double max, double min, int n, chtype pc, chtype hce, chtype lce, double hm) { +void plot_values(int ph, int pw, double *v1, double *v2, double max, double min, int n, cchar_t *pc, cchar_t *hce, cchar_t *lce, double hm) { const int first_col=3; int i=(n+1)%pw; int x; @@ -231,7 +242,7 @@ void paint_plot(void) { asctime_r(lt, ls); mvaddstr(height-2, width-strlen(ls), ls); - mvvline(height-2, 5, plotchar|A_NORMAL, 1); + mvvline_set(height-2, 5, &plotchar, 1); if (v > 0) { mvprintw(height-2, 7, "last=%.1f min=%.1f max=%.1f avg=%.1f %s ", values1[n], min1, max1, avg1, unit); if(rate) @@ -243,7 +254,7 @@ void paint_plot(void) { } } - plot_values(plotheight, plotwidth, values1, values2, max, hardmin, n, plotchar, max_errchar, min_errchar, hardmax); + plot_values(plotheight, plotwidth, values1, values2, max, hardmin, n, &plotchar, &max_errchar, &min_errchar, hardmax); draw_axes(height, plotheight, plotwidth, max, hardmin, unit); @@ -287,9 +298,13 @@ int main(int argc, char *argv[]) { int show_ver; int show_usage; - plotchar=T_VLINE; - max_errchar='e'; - min_errchar='v'; + setlocale(LC_ALL, ""); + if (MB_CUR_MAX > 1) // if non-ASCII characters are supprted: + plotchar.chars[0]=0x2502; // U+2502 box drawings light vertical + else + plotchar.chars[0]='|'; // U+007C vertical line + max_errchar.chars[0]='e'; + min_errchar.chars[0]='v'; cached_opterr = opterr; opterr=0; @@ -339,16 +354,16 @@ int main(int argc, char *argv[]) { break; case '2': two=1; - plotchar='|'; + plotchar.chars[0]='|'; break; case 'c': - plotchar=optarg[0]; + mbtowc(&plotchar.chars[0], optarg, MB_CUR_MAX); break; case 'e': - max_errchar=optarg[0]; + mbtowc(&max_errchar.chars[0], optarg, MB_CUR_MAX); break; case 'E': - min_errchar=optarg[0]; + mbtowc(&min_errchar.chars[0], optarg, MB_CUR_MAX); break; case 's': softmax=atof(optarg);