[with_jansson=no])
])
+# Find ncursesw
+AC_ARG_WITH([ncursesw],
+ [AS_HELP_STRING([--without-ncursesw], [Build without the ncursesw interface])],
+ [], [with_ncursesw=yes])
+AS_IF([test "x$with_ncursesw" = "xyes"],
+
+ # Prefer ncursesw, if available
+ [AC_SEARCH_LIBS(
+ [wprintw], [ncursesw],
+ [AC_DEFINE([HAVE_CURSESW], [1], [Define if a ncursesw library available])],
+ [with_ncursesw=no])
+])
+AM_CONDITIONAL([WITH_CURSESW], [test "x$with_ncursesw" = xyes])
+
# Find ncurses
AC_ARG_WITH([ncurses],
[AS_HELP_STRING([--without-ncurses], [Build without the ncurses interface])],
# Prefer ncurses over curses, if both are available.
# (On Solaris 11.3, ncurses builds and links for us, but curses does not.)
[AC_SEARCH_LIBS(
- [initscr], [ncurses curses],
+ [initscr], [ncursesw ncurses curses],
[AC_DEFINE([HAVE_CURSES], [1], [Define if a curses library available])],
[with_ncurses=no])
])
USES_IPV6=yes
])
+AC_ARG_ENABLE([braille],
+ [AS_HELP_STRING([--disable-braille], [Do not enable barille character graphs])],
+ [WANTS_BRAILLE=$enableval], [WANTS_BRAILLE=yes])
+
+AS_IF([test "x$WANTS_BRAILLE" = "xyes"], [
+ AC_DEFINE([ENABLE_BRAILLE], [1], [Define to enable IPv6])
+ USES_BRAILLE=yes
+])
+
AC_CHECK_FUNC([socket], [],
[AC_CHECK_LIB([socket], [socket], [], [AC_MSG_ERROR([No socket library found])])])
AM_CONDITIONAL([BUILD_BASH_COMPLETION], [test "x$enable_bash_completion" = xyes])
echo "build options:"
echo "--------------"
-echo "libasan :$with_libasan"
-echo "ipv6 :$USES_IPV6"
-echo "ipinfo :$with_ipinfo"
-echo "ncurses :$with_ncurses"
-echo "gtk :$with_gtk"
-echo "jansson :$with_jansson"
-echo "cap :$have_cap"
-echo "libs :$LIBS"
-echo "cflags :$CFLAGS"
+echo "libasan :$with_libasan"
+echo "ipv6 :$USES_IPV6"
+echo "braille :$USES_BRAILLE"
+echo "ipinfo :$with_ipinfo"
+echo "ncursesw :$with_ncursesw"
+echo "ncurses :$with_ncurses"
+echo "gtk :$with_gtk"
+echo "jansson :$with_jansson"
+echo "cap :$have_cap"
+echo "libs :$LIBS"
+echo "cflags :$CFLAGS"
echo "--------------"
# Prepare config.h, Makefile, and output them.
AC_CONFIG_HEADERS([config.h])
#include "mtr.h"
+#include <locale.h>
+#include <assert.h>
#include <strings.h>
#include <unistd.h>
block_map[NUM_FACTORS - 1] = '>';
}
-static void mtr_print_scaled(
+static int ms_to_factor(
int ms)
{
int i;
for (i = 0; i < NUM_FACTORS; i++) {
- if (ms <= scale[i]) {
- attrset(block_col[i + 1]);
- printw("%c", block_map[i]);
- attrset(A_NORMAL);
- return;
- }
+ if (ms <= scale[i])
+ return i;
+ }
+
+ return NUM_FACTORS;
+}
+
+static void mtr_print_scaled(
+ int ms)
+{
+ int f = ms_to_factor(ms);
+
+ if ((unsigned)f < NUM_FACTORS) {
+ attrset(block_col[f + 1]);
+ printw("%c", block_map[f]);
+ attrset(A_NORMAL);
+ return;
}
printw(">");
}
+#ifdef WITH_BRAILLE_DISPLAY
+static int current_host_range_low_ms = 1000000;
+static int current_host_range_high_ms = -1;
+
+static void compute_current_host_range(const int *ms_data, size_t length)
+{
+ current_host_range_low_ms = 1000000;
+ current_host_range_high_ms = -1;
+
+ for (int i=0; i<length; ++i) {
+ int ms = ms_data[i];
+ if (ms < 0)
+ continue;
+ if (current_host_range_low_ms > ms)
+ current_host_range_low_ms = ms;
+ if (current_host_range_high_ms < ms)
+ current_host_range_high_ms = ms;
+ }
+}
+
+static const int scale_ms_to_braille_factor(int ms)
+{
+ if (ms <= 0)
+ return 0;
+
+ int ms_range = current_host_range_high_ms - current_host_range_low_ms;
+ if (ms_range < 1)
+ return 0;
+
+ return (ms - current_host_range_low_ms) * 4 / ms_range;
+}
+
+static const wchar_t *braille_char_lookup(
+ int ms,
+ const wchar_t *braille_set[5])
+{
+ if (ms < 0)
+ return L""; // this is an error in decoding
+
+ int i = scale_ms_to_braille_factor(ms);
+ if ((unsigned)i >= 4)
+ return L"🮐"; // this is the max
+
+ return braille_set[i];
+}
+
+// handle if left is not provided, but right is
+static const wchar_t *braille_char_left(
+ int left_ms)
+{
+ static const wchar_t *braille_left_lookup[5] = {
+ L"⡀", L"⡄", L"⡆", L"⡇",
+ };
+
+ return braille_char_lookup(left_ms, braille_left_lookup);
+}
+
+
+// handle if right is not provided, but left is
+static const wchar_t *braille_char_right(
+ int right_ms)
+{
+ static const wchar_t *braille_right_lookup[5] = {
+ L"⢀", L"⢠", L"⢰", L"⢸",
+ };
+
+ return braille_char_lookup(right_ms, braille_right_lookup);
+}
+
+// handle both left and right being provided
+static const wchar_t *braille_char_double(
+ int left_ms,
+ int right_ms)
+{
+ static const wchar_t *braille_double_lookup[5][5] = {
+ { L"⣀", L"⣠", L"⣰", L"⣸", },
+ { L"⣄", L"⣤", L"⣴", L"⣼", },
+ { L"⣆", L"⣦", L"⣶", L"⣾", },
+ { L"⣇", L"⣧", L"⣷", L"⣿", }
+ };
+
+ int left_i = scale_ms_to_braille_factor(left_ms);
+ if ((unsigned)left_i >= 4)
+ return L"🮐"; // this is the max
+
+ return braille_char_lookup(right_ms, braille_double_lookup[left_i]);
+}
+
+static void mtr_print_braille(
+ int left_ms,
+ int right_ms)
+{
+ int ms_max = left_ms > right_ms ? left_ms : right_ms;
+ int f = ms_to_factor(ms_max);
+ f = ((unsigned)f < NUM_FACTORS) ? f : NUM_FACTORS - 1;
+
+ const wchar_t *wstr;
+ if (left_ms > 0 && right_ms > 0)
+ wstr = braille_char_double(left_ms, right_ms);
+ else if (left_ms > 0)
+ wstr = braille_char_left(left_ms);
+ else if (right_ms > 0)
+ wstr = braille_char_right(right_ms);
+ else
+ wstr = L"▁";
+
+ attrset(block_col[f + 1]);
+ printw("%ls", wstr);
+ attrset(A_NORMAL);
+}
+
+static void mtr_fill_graph_braille(
+ struct mtr_ctl *ctl,
+ int at,
+ int cols)
+{
+ const int *saved;
+ int i;
+
+ saved = net_saved_pings(at);
+
+ compute_current_host_range(saved, SAVED_PINGS);
+
+ // we can pack twice as many entries into a braille line
+
+ cols = cols * 2;
+ cols = cols <= SAVED_PINGS ? cols : SAVED_PINGS;
+
+ for (i = SAVED_PINGS - cols; i < SAVED_PINGS; i+=2) {
+ int a = saved[i];
+ int b = (i+1 < SAVED_PINGS) ? saved[i+1] : 0;
+
+ if (a == -2 && b == -2) {
+ printw(" ");
+ } else if (a == -1 || b == -1) {
+ attrset(block_col[0]);
+ printw("%c", '?');
+ attrset(A_NORMAL);
+ } else {
+ mtr_print_braille(a, b);
+ }
+ }
+
+}
+#endif
static void mtr_fill_graph(
struct mtr_ctl *ctl,
move(y, startstat);
printw(" ");
- mtr_fill_graph(ctl, at, cols);
+#ifdef WITH_BRAILLE_DISPLAY
+ if (ctl->display_mode == DisplayModeBraille) {
+ mtr_fill_graph_braille(ctl, at, cols);
+ } else
+#endif
+ {
+ mtr_fill_graph(ctl, at, cols);
+ }
printw("\n");
}
}
int bg_col = 0;
int i;
+#ifdef WITH_BRAILLE_DISPLAY
+ // initialize all locale variables, before ncurses starts
+ setlocale(LC_ALL, "");
+#endif
+
initscr();
raw();
noecho();