+ if (x >= ctx->history_size)
+ {
+ mvwaddch (ctx->window, /* y = */ 3, /* x = */ x + 2, ' ');
+ continue;
+ }
+
+ index = (history_offset + x) % ctx->history_size;
+ latency = ctx->history_by_time[index];
+
+ if (latency < 0) {
+ continue;
+ }
+
+ if (latency >= 0.0)
+ {
+ double ratio;
+
+ size_t symbols_num = hist_symbols_acs_num;
+ size_t colors_num = 1;
+
+ size_t index_symbols;
+ size_t index_colors;
+ size_t intensity;
+
+ /* latency is in milliseconds, opt_interval is in seconds. */
+ ratio = (latency * 0.001) / opt_interval;
+ if (ratio > 1) {
+ ratio = 1.0;
+ }
+
+ if (has_utf8 ())
+ symbols_num = hist_symbols_utf8_num;
+
+ if (has_colors () == TRUE)
+ colors_num = hist_colors_num;
+
+ intensity = (size_t) (ratio * ((double) (symbols_num * colors_num)));
+ if (intensity >= (symbols_num * colors_num))
+ intensity = (symbols_num * colors_num) - 1;
+
+ index_symbols = intensity % symbols_num;
+ assert (index_symbols < symbols_num);
+
+ index_colors = intensity / symbols_num;
+ assert (index_colors < colors_num);
+
+ if (has_utf8())
+ {
+ color = hist_colors_utf8[index_colors];
+ symbol = hist_symbols_utf8[index_symbols];
+ }
+ else
+ {
+ color = hist_colors_acs[index_colors];
+ symbolc = hist_symbols_acs[index_symbols] | A_ALTCHARSET;
+ }
+ }
+ else /* if (!(latency >= 0.0)) */
+ wattron (ctx->window, A_BOLD);
+
+ if (has_colors () == TRUE)
+ wattron (ctx->window, COLOR_PAIR(color));
+
+ if (has_utf8())
+ mvwprintw (ctx->window, /* y = */ 3, /* x = */ x + 2, symbol);
+ else
+ mvwaddch (ctx->window, /* y = */ 3, /* x = */ x + 2, symbolc);
+
+ if (has_colors () == TRUE)
+ wattroff (ctx->window, COLOR_PAIR(color));
+
+ /* Use negation here to handle NaN correctly. */
+ if (!(latency >= 0.0))
+ wattroff (ctx->window, A_BOLD);
+ } /* for (x) */
+
+ return (0);
+} /* }}} int update_graph_prettyping */
+
+static int update_graph_histogram (ping_context_t *ctx) /* {{{ */
+{
+ uint32_t *counters;
+ uint32_t *accumulated;
+ uint32_t max;
+ size_t i;
+ size_t x_max;
+ size_t x;
+
+ size_t symbols_num = hist_symbols_acs_num;
+
+ clean_history (ctx);
+
+ if (ctx->history_received == 0)
+ return (ENOENT);
+
+ if (has_utf8 ())
+ symbols_num = hist_symbols_utf8_num;
+
+ x_max = (size_t) getmaxx (ctx->window);
+ if (x_max <= 4)
+ return (EINVAL);
+ x_max -= 4;
+
+ counters = calloc (x_max, sizeof (*counters));
+ accumulated = calloc (x_max, sizeof (*accumulated));
+
+ /* Bucketize */
+ max = 0;
+ for (i = 0; i < ctx->history_received; i++)
+ {
+ double latency = ctx->history_by_value[i] / 1000.0;
+ size_t index = (size_t) (((double) x_max) * latency / opt_interval);
+
+ if (index >= x_max)
+ index = x_max - 1;
+
+ counters[index]++;
+ if (max < counters[index])
+ max = counters[index];
+ }
+
+ /* Sum */
+ accumulated[0] = counters[0];
+ for (x = 1; x < x_max; x++)
+ accumulated[x] = counters[x] + accumulated[x - 1];
+
+ /* Calculate ratios */
+ for (x = 0; x < x_max; x++)
+ {
+ double height = ((double) counters[x]) / ((double) max);
+ double ratio_this = ((double) accumulated[x]) / ((double) ctx->history_received);
+ double ratio_prev = 0.0;
+ size_t index;
+ int color = 0;
+
+ index = (size_t) (height * ((double) symbols_num));
+ if (index >= symbols_num)
+ index = symbols_num - 1;
+
+ if (x > 0)
+ ratio_prev = ((double) accumulated[x - 1]) / ((double) ctx->history_received);
+
+ if (has_colors () == TRUE)
+ {
+ if ((ratio_this <= threshold_green)
+ || ((ratio_prev < threshold_green)
+ && (ratio_this > threshold_green)))
+ color = OPING_GREEN;
+ else if ((ratio_this <= threshold_yellow)
+ || ((ratio_prev < threshold_yellow)
+ && (ratio_this > threshold_yellow)))
+ color = OPING_YELLOW;
+ else
+ color = OPING_RED;
+
+ wattron (ctx->window, COLOR_PAIR(color));
+ }
+
+ if (counters[x] == 0)
+ mvwaddch (ctx->window, /* y = */ 3, /* x = */ x + 2, ' ');
+ else if (has_utf8 ())
+ mvwprintw (ctx->window, /* y = */ 3, /* x = */ x + 2,
+ hist_symbols_utf8[index]);
+ else
+ mvwaddch (ctx->window, /* y = */ 3, /* x = */ x + 2,
+ hist_symbols_acs[index] | A_ALTCHARSET);
+
+ if (has_colors () == TRUE)
+ wattroff (ctx->window, COLOR_PAIR(color));
+
+ }
+
+ free (accumulated);