#include "mtr.h"
+#include <limits.h>
#include <locale.h>
#ifdef __CYGWIN__
#include <windows.h>
#include "utils.h"
-enum { NUM_FACTORS = 8 };
+enum { NUM_FACTORS = MTR_SCALE_FACTORS };
static double factors[NUM_FACTORS];
static int scale[NUM_FACTORS];
static char block_map[NUM_FACTORS];
#ifdef WITH_BRAILLE_DISPLAY
static const wchar_t *braille_map[NUM_FACTORS] = {
- L"⣀", L"⣀", L"⣤", L"⣤", L"⣶", L"⣶", L"⣿", L"⣿"
+ L"â£\80", L"â£\80", L"⣤", L"⣤", L"⣦", L"⣦", L"⣶", L"⣶", L"⣿", L"⣿"
};
#endif
enum { black = 1, red, green, yellow, blue, magenta, cyan, white };
static const int block_col[NUM_FACTORS + 1] = {
COLOR_PAIR(red) | A_BOLD,
- A_NORMAL,
- COLOR_PAIR(green),
COLOR_PAIR(green) | A_BOLD,
+ COLOR_PAIR(green) | A_BOLD,
+ COLOR_PAIR(green) | A_BOLD,
+ COLOR_PAIR(yellow) | A_BOLD,
COLOR_PAIR(yellow) | A_BOLD,
COLOR_PAIR(magenta) | A_BOLD,
- COLOR_PAIR(magenta),
+ COLOR_PAIR(red) | A_BOLD,
+ COLOR_PAIR(red) | A_BOLD,
COLOR_PAIR(red),
- COLOR_PAIR(red) | A_BOLD
+ COLOR_PAIR(red)
};
static void pwcenter(
for (i = 0; i < NUM_FACTORS; i++) {
scale[i] = 0;
}
+ if (ctl->fixed_scale) {
+ for (i = 0; i < MTR_SCALE_THRESHOLDS; i++) {
+ scale[i] = ctl->scale[i];
+ }
+ scale[NUM_FACTORS - 1] = INT_MAX;
+ return;
+ }
+
max = net_max(ctl);
for (at = ctl->display_offset; at < max; at++) {
saved = net_saved_pings(at);
}
/* Initialize block_map. The block_split is always smaller than 9 */
- block_split = (NUM_FACTORS - 2) / 2;
+ block_split = NUM_FACTORS / 2;
for (i = 1; i <= block_split; i++) {
block_map[i] = '0' + i;
}
attrset(A_NORMAL);
} else {
if (ctl->display_mode == DisplayModeBlockmap) {
- if (saved[i] > scale[6]) {
+ if (saved[i] > scale[NUM_FACTORS - 2]) {
printw("%c", block_map[NUM_FACTORS - 1]);
} else {
printw(".");
fputs(" -p, --split split output\n", out);
#ifdef HAVE_CURSES
fputs(" -t, --curses use curses terminal interface\n", out);
-#endif
fputs(" --displaymode MODE select initial display mode\n", out);
+ fputs(" --compact start curses interface in compact mode\n", out);
+ fputs(" --scale SCALE set stripchart scale thresholds\n", out);
+#endif
#ifdef HAVE_GTK
fputs(" -g, --gtk use GTK+ xwindow interface\n", out);
#endif
}
+#ifdef HAVE_CURSES
+static void set_fixed_scale(
+ struct mtr_ctl *ctl,
+ const int *thresholds)
+{
+ int i;
+
+ for (i = 0; i < MTR_SCALE_THRESHOLDS; i++) {
+ ctl->scale[i] = thresholds[i] * 1000;
+ }
+ ctl->fixed_scale = 1;
+}
+
+
+static void parse_scale(
+ struct mtr_ctl *ctl,
+ const char *scale_arg)
+{
+ static const int fast_scale[MTR_SCALE_THRESHOLDS] = {
+ 1, 2, 3, 4, 5, 10, 20, 40, 80
+ };
+ static const int average_scale[MTR_SCALE_THRESHOLDS] = {
+ 5, 15, 25, 35, 45, 55, 101, 200, 400
+ };
+ static const int slow_scale[MTR_SCALE_THRESHOLDS] = {
+ 50, 100, 150, 200, 300, 500, 750, 1000, 2000
+ };
+ const char *cursor = scale_arg;
+ int thresholds[MTR_SCALE_THRESHOLDS];
+ int previous = -1;
+ int i;
+
+ if (!strcmp(scale_arg, "fast")) {
+ set_fixed_scale(ctl, fast_scale);
+ return;
+ }
+ if (!strcmp(scale_arg, "average")) {
+ set_fixed_scale(ctl, average_scale);
+ return;
+ }
+ if (!strcmp(scale_arg, "slow")) {
+ set_fixed_scale(ctl, slow_scale);
+ return;
+ }
+
+ for (i = 0; i < MTR_SCALE_THRESHOLDS; i++) {
+ char *end;
+ long threshold;
+
+ errno = 0;
+ threshold = strtol(cursor, &end, 10);
+ if (cursor == end || errno || threshold < 0 ||
+ threshold > INT_MAX / 1000) {
+ error(EXIT_FAILURE, 0, "invalid scale threshold: %s", scale_arg);
+ }
+ if (threshold <= previous) {
+ error(EXIT_FAILURE, 0,
+ "scale thresholds must be strictly increasing: %s",
+ scale_arg);
+ }
+
+ thresholds[i] = threshold;
+ previous = threshold;
+
+ if (i == MTR_SCALE_THRESHOLDS - 1) {
+ if (*end) {
+ error(EXIT_FAILURE, 0,
+ "scale expects %d thresholds: %s",
+ MTR_SCALE_THRESHOLDS, scale_arg);
+ }
+ } else if (*end != ':') {
+ error(EXIT_FAILURE, 0,
+ "scale expects %d colon-separated thresholds: %s",
+ MTR_SCALE_THRESHOLDS, scale_arg);
+ }
+ cursor = end + 1;
+ }
+
+ set_fixed_scale(ctl, thresholds);
+}
+#endif
+
+
static void parse_arg(
struct mtr_ctl *ctl,
names_t ** names,
enum {
OPT_DISPLAYMODE = CHAR_MAX + 1,
OPT_REPORT_ON_EXIT = CHAR_MAX + 2,
- OPT_IPINFO4 = CHAR_MAX + 3,
+ OPT_SCALE = CHAR_MAX + 3,
+ OPT_IPINFO4 = CHAR_MAX + 4,
+ OPT_COMPACT = CHAR_MAX + 5,
#ifdef ENABLE_IPV6
- OPT_IPINFO6 = CHAR_MAX + 4,
- OPT_CACHE = CHAR_MAX + 5,
+ OPT_IPINFO6 = CHAR_MAX + 6,
+ OPT_CACHE = CHAR_MAX + 7,
#else
- OPT_CACHE = CHAR_MAX + 4,
+ OPT_CACHE = CHAR_MAX + 6,
#endif /* ifdef ENABLE_IPV6 */
};
static const struct option long_options[] = {
#ifdef HAVE_JANSSON
{"json", 0, NULL, 'j'},
#endif
+#ifdef HAVE_CURSES
{"displaymode", 1, NULL, OPT_DISPLAYMODE},
+ {"compact", 0, NULL, OPT_COMPACT},
+ {"scale", 1, NULL, OPT_SCALE},
+#endif
{"split", 0, NULL, 'p'}, /* BL */
/* maybe above should change to -d 'x' */
ctl->DisplayMode = DisplayXML;
break;
+#ifdef HAVE_CURSES
case OPT_DISPLAYMODE:
ctl->display_mode =
strtoint_or_err(optarg, "invalid argument");
error(EXIT_FAILURE, 0, "value out of range (%d - %d): %s",
DisplayModeDefault, (DisplayModeMAX - 1), optarg);
break;
+ case OPT_COMPACT:
+ ctl->CompactLayout = 1;
+ break;
+ case OPT_SCALE:
+ parse_scale(ctl, optarg);
+ break;
+#endif
case 'c':
ctl->MaxPing =
strtoint_or_err(optarg, "invalid argument");