bryancall commented on code in PR #12758:
URL: https://github.com/apache/trafficserver/pull/12758#discussion_r3382667829


##########
src/traffic_top/Display.cc:
##########
@@ -0,0 +1,2074 @@
+/** @file
+
+    Display class implementation for traffic_top using direct ANSI output.
+
+    @section license License
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+#include "Display.h"
+
+#include <algorithm>
+#include <cstdio>
+#include <ctime>
+#include <cstring>
+#include <cstdlib>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+
+#include "tscore/ink_config.h"
+
+// ncurses is only used for keyboard input (getch)
+#define NOMACROS         1
+#define NCURSES_NOMACROS 1
+
+#if defined HAVE_NCURSESW_CURSES_H
+#include <ncursesw/curses.h>
+#elif defined HAVE_NCURSESW_H
+#include <ncursesw.h>
+#elif defined HAVE_NCURSES_CURSES_H
+#include <ncurses/curses.h>
+#elif defined HAVE_NCURSES_H
+#include <ncurses.h>
+#elif defined HAVE_CURSES_H
+#include <curses.h>
+#else
+#error "SysV or X/Open-compatible Curses header file required"
+#endif
+
+namespace traffic_top
+{
+
+// ANSI escape sequences
+namespace
+{
+  // Move cursor to row, col (1-based for ANSI)
+  void
+  moveTo(int row, int col)
+  {
+    printf("\033[%d;%dH", row + 1, col + 1);
+  }
+
+  // Set foreground color
+  void
+  setColor(short colorIdx)
+  {
+    switch (colorIdx) {
+    case ColorPair::Red:
+      printf("\033[31m");
+      break;
+    case ColorPair::Green:
+      printf("\033[32m");
+      break;
+    case ColorPair::Yellow:
+      printf("\033[33m");
+      break;
+    case ColorPair::Blue:
+      printf("\033[34m");
+      break;
+    case ColorPair::Magenta:
+    case ColorPair::Border3:
+      printf("\033[35m");
+      break;
+    case ColorPair::Cyan:
+    case ColorPair::Border:
+      printf("\033[36m");
+      break;
+    case ColorPair::Grey:
+    case ColorPair::Dim:
+      printf("\033[90m");
+      break;
+    case ColorPair::Border2:
+      printf("\033[34m");
+      break;
+    case ColorPair::Border4: // Bright blue
+      printf("\033[94m");
+      break;
+    case ColorPair::Border5: // Bright yellow
+      printf("\033[93m");
+      break;
+    case ColorPair::Border6: // Bright red
+      printf("\033[91m");
+      break;
+    case ColorPair::Border7: // Bright green
+      printf("\033[92m");
+      break;
+    default:
+      printf("\033[0m");
+      break;
+    }
+  }
+
+  void
+  resetColor()
+  {
+    printf("\033[0m");
+  }
+
+  void
+  setBold()
+  {
+    printf("\033[1m");
+  }
+
+  void
+  clearScreen()
+  {
+    printf("\033[2J\033[H");
+  }
+
+  void
+  hideCursor()
+  {
+    printf("\033[?25l");
+  }
+
+  void
+  showCursor()
+  {
+    printf("\033[?25h");
+  }
+
+} // anonymous namespace
+
+// Layout breakpoints for common terminal sizes:
+//   80x24  - Classic VT100/xterm default (2 columns)
+//   120x40 - Common larger terminal (3 columns)
+//   160x50 - Wide terminal (4 columns)
+//   300x75 - Extra large/tiled display (4 columns, wider boxes)
+constexpr int WIDTH_SMALL  = 80;  // Classic terminal width
+constexpr int WIDTH_MEDIUM = 120; // Larger terminal
+constexpr int WIDTH_LARGE  = 160; // Wide terminal
+constexpr int HEIGHT_SMALL = 24;  // Classic terminal height
+
+constexpr int LABEL_WIDTH_SM = 12; // Small label width (80-col terminals)
+constexpr int LABEL_WIDTH_MD = 14; // Medium label width (120-col terminals)
+constexpr int LABEL_WIDTH_LG = 18; // Large label width (160+ terminals)
+
+Display::Display() = default;
+
+Display::~Display()
+{
+  if (_initialized) {
+    shutdown();
+  }
+}
+
+bool
+Display::detectUtf8Support()
+{
+  const char *lang    = getenv("LANG");
+  const char *lc_all  = getenv("LC_ALL");
+  const char *lc_type = getenv("LC_CTYPE");
+
+  auto has_utf8 = [](const char *s) {
+    if (!s) {
+      return false;
+    }
+    // Check for UTF-8 or UTF8 (case-insensitive)
+    for (const char *p = s; *p; ++p) {
+      if ((*p == 'U' || *p == 'u') && (*(p + 1) == 'T' || *(p + 1) == 't') && 
(*(p + 2) == 'F' || *(p + 2) == 'f')) {
+        if (*(p + 3) == '-' && *(p + 4) == '8') {
+          return true;
+        }
+        if (*(p + 3) == '8') {
+          return true;
+        }
+      }
+    }
+    return false;
+  };
+
+  return has_utf8(lc_all) || has_utf8(lc_type) || has_utf8(lang);
+}
+
+bool
+Display::initialize()
+{
+  if (_initialized) {
+    return true;
+  }
+
+  // Enable UTF-8 locale
+  setlocale(LC_ALL, "");
+
+  // Auto-detect UTF-8 support from environment
+  _ascii_mode = !detectUtf8Support();
+
+  // Initialize ncurses only for keyboard input
+  initscr();
+  cbreak();
+  noecho();
+  keypad(stdscr, TRUE);
+  nodelay(stdscr, FALSE);
+  curs_set(0);
+
+  // Get terminal size
+  struct winsize ws;
+  if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0) {
+    _width  = ws.ws_col;
+    _height = ws.ws_row;
+  } else {
+    getmaxyx(stdscr, _height, _width);
+  }
+
+  // Setup terminal for direct output
+  hideCursor();
+  printf("\033[?1049h"); // Switch to alternate screen buffer
+  fflush(stdout);
+
+  _initialized = true;
+  return true;
+}
+
+void
+Display::shutdown()
+{
+  if (_initialized) {
+    showCursor();
+    printf("\033[?1049l"); // Switch back to normal screen buffer
+    resetColor();
+    fflush(stdout);
+    endwin();
+    _initialized = false;
+  }
+}
+
+void
+Display::getTerminalSize(int &width, int &height) const
+{
+  width  = _width;
+  height = _height;
+}
+
+void
+Display::render(Stats &stats, Page page, [[maybe_unused]] bool absolute)
+{
+  // Update terminal size
+  struct winsize ws;
+  if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0) {
+    _width  = ws.ws_col;
+    _height = ws.ws_row;
+  }
+
+  clearScreen();
+
+  switch (page) {
+  case Page::Main:
+    renderMainPage(stats);
+    break;
+  case Page::Response:
+    renderResponsePage(stats);
+    break;
+  case Page::Connection:
+    renderConnectionPage(stats);
+    break;
+  case Page::Cache:
+    renderCachePage(stats);
+    break;
+  case Page::SSL:
+    renderSSLPage(stats);
+    break;
+  case Page::Errors:
+    renderErrorsPage(stats);
+    break;
+  case Page::Performance:
+    renderPerformancePage(stats);
+    break;
+  case Page::Graphs:
+    renderGraphsPage(stats);
+    break;
+  case Page::Help: {
+    std::string version;
+    stats.getStat("version", version);
+    renderHelpPage(stats.getHost(), version);
+    break;
+  }
+  default:
+    break;
+  }
+
+  fflush(stdout);
+}
+
+void
+Display::drawBox(int x, int y, int width, int height, const std::string 
&title, short colorIdx)
+{
+  setColor(colorIdx);
+
+  // Top border with rounded corners
+  moveTo(y, x);
+  printf("%s", boxChar(BoxChars::TopLeft, BoxChars::AsciiTopLeft));
+  for (int i = 1; i < width - 1; ++i) {
+    printf("%s", boxChar(BoxChars::Horizontal, BoxChars::AsciiHorizontal));
+  }
+  printf("%s", boxChar(BoxChars::TopRight, BoxChars::AsciiTopRight));
+
+  // Title centered in top border
+  if (!title.empty() && static_cast<int>(title.length()) < width - 4) {
+    int title_x = x + (width - static_cast<int>(title.length()) - 2) / 2;
+    moveTo(y, title_x);
+    setBold();
+    printf(" %s ", title.c_str());
+    resetColor();
+    setColor(colorIdx);
+  }
+
+  // Sides
+  for (int i = 1; i < height - 1; ++i) {
+    moveTo(y + i, x);
+    printf("%s", boxChar(BoxChars::Vertical, BoxChars::AsciiVertical));
+    moveTo(y + i, x + width - 1);
+    printf("%s", boxChar(BoxChars::Vertical, BoxChars::AsciiVertical));
+  }
+
+  // Bottom border with rounded corners
+  moveTo(y + height - 1, x);
+  printf("%s", boxChar(BoxChars::BottomLeft, BoxChars::AsciiBottomLeft));
+  for (int i = 1; i < width - 1; ++i) {
+    printf("%s", boxChar(BoxChars::Horizontal, BoxChars::AsciiHorizontal));
+  }
+  printf("%s", boxChar(BoxChars::BottomRight, BoxChars::AsciiBottomRight));
+
+  resetColor();
+}
+
+void
+Display::drawSectionHeader(int y, int x1, int x2, const std::string &title)
+{
+  setColor(ColorPair::Border);
+
+  // Draw top border line
+  moveTo(y, x1);
+  printf("%s", boxChar(BoxChars::TopLeft, BoxChars::AsciiTopLeft));
+  for (int x = x1 + 1; x < x2 - 1; ++x) {
+    printf("%s", boxChar(BoxChars::Horizontal, BoxChars::AsciiHorizontal));
+  }
+  if (x2 < _width) {
+    printf("%s", boxChar(BoxChars::TopRight, BoxChars::AsciiTopRight));
+  }
+
+  // Center the title
+  int title_len = static_cast<int>(title.length());
+  int title_x   = x1 + (x2 - x1 - title_len - 2) / 2;
+  moveTo(y, title_x);
+  setBold();
+  printf(" %s ", title.c_str());
+  resetColor();
+}
+
+void
+Display::drawStatTable(int x, int y, const std::vector<std::string> &items, 
Stats &stats, int labelWidth)
+{
+  int row = y;
+  for (const auto &key : items) {
+    if (row >= _height - 2) {
+      break; // Don't overflow into status bar
+    }
+
+    std::string prettyName;
+    double      value = 0;
+    StatType    type;
+
+    stats.getStat(key, value, prettyName, type);
+
+    // Truncate label if needed
+    if (static_cast<int>(prettyName.length()) > labelWidth) {
+      prettyName = prettyName.substr(0, labelWidth - 1);
+    }
+
+    // Draw label with cyan color for visual hierarchy
+    moveTo(row, x);
+    setColor(ColorPair::Cyan);
+    printf("%-*s", labelWidth, prettyName.c_str());
+    resetColor();
+
+    printStatValue(x + labelWidth, row, value, type);
+    ++row;
+  }
+}
+
+void
+Display::drawStatGrid(int x, int y, int boxWidth, const 
std::vector<std::string> &items, Stats &stats, int cols)
+{
+  // Calculate column width based on box width and number of columns
+  // Each stat needs: label (8 chars) + value (6 chars) + space (1 char) = 15 
chars minimum
+  int colWidth   = (boxWidth - 2) / cols; // -2 for box borders
+  int labelWidth = 8;
+
+  int row = y;
+  int col = 0;
+
+  for (const auto &key : items) {
+    if (row >= _height - 2) {
+      break;
+    }
+
+    std::string prettyName;
+    double      value = 0;
+    StatType    type;
+
+    stats.getStat(key, value, prettyName, type);
+
+    // Truncate label if needed
+    if (static_cast<int>(prettyName.length()) > labelWidth) {
+      prettyName = prettyName.substr(0, labelWidth);
+    }
+
+    int statX = x + (col * colWidth);
+
+    // Draw label with trailing space
+    moveTo(row, statX);
+    setColor(ColorPair::Cyan);
+    printf("%-*s ", labelWidth, prettyName.c_str()); // Note the space after %s
+    resetColor();
+
+    // Draw value (compact format for grid)
+    char   buffer[16];
+    char   suffix  = ' ';
+    double display = value;
+    short  color   = ColorPair::Green;
+
+    if (isPercentage(type)) {
+      if (value < 0.01) {
+        color = ColorPair::Grey;
+      }
+      snprintf(buffer, sizeof(buffer), "%3.0f%%", display);
+    } else {
+      if (value > 1000000000.0) {
+        display = value / 1000000000.0;
+        suffix  = 'G';
+        color   = ColorPair::Red;
+      } else if (value > 1000000.0) {
+        display = value / 1000000.0;
+        suffix  = 'M';
+        color   = ColorPair::Yellow;
+      } else if (value > 1000.0) {
+        display = value / 1000.0;
+        suffix  = 'K';
+        color   = ColorPair::Cyan;
+      } else if (value < 0.01) {
+        color = ColorPair::Grey;
+      }
+      snprintf(buffer, sizeof(buffer), "%5.0f%c", display, suffix);
+    }
+
+    setColor(color);
+    setBold();
+    printf("%s", buffer);
+    resetColor();
+
+    ++col;
+    if (col >= cols) {
+      col = 0;
+      ++row;
+    }
+  }
+}
+
+void
+Display::printStatValue(int x, int y, double value, StatType type)
+{
+  char   buffer[32];
+  char   suffix   = ' ';
+  double display  = value;
+  short  color    = ColorPair::Green;
+  bool   show_pct = isPercentage(type);
+
+  if (!show_pct) {
+    // Format large numbers with SI prefixes
+    if (value > 1000000000000.0) {
+      display = value / 1000000000000.0;
+      suffix  = 'T';
+      color   = ColorPair::Red;
+    } else if (value > 1000000000.0) {
+      display = value / 1000000000.0;
+      suffix  = 'G';
+      color   = ColorPair::Red;
+    } else if (value > 1000000.0) {
+      display = value / 1000000.0;
+      suffix  = 'M';
+      color   = ColorPair::Yellow;
+    } else if (value > 1000.0) {
+      display = value / 1000.0;
+      suffix  = 'K';
+      color   = ColorPair::Cyan;
+    } else if (value < 0.01) {
+      color = ColorPair::Grey;
+    }
+    snprintf(buffer, sizeof(buffer), "%7.1f%c", display, suffix);
+  } else {
+    // Percentage display with color coding based on context
+    if (value > 90) {
+      color = ColorPair::Green;
+    } else if (value > 70) {
+      color = ColorPair::Cyan;
+    } else if (value > 50) {
+      color = ColorPair::Yellow;
+    } else if (value > 20) {
+      color = ColorPair::Yellow;
+    } else if (value < 0.01) {
+      color = ColorPair::Grey;
+    } else {
+      color = ColorPair::Green;
+    }
+    snprintf(buffer, sizeof(buffer), "%6.1f%%", display);
+  }
+
+  moveTo(y, x);
+  setColor(color);
+  setBold();
+  printf("%s", buffer);
+  resetColor();
+}
+
+void
+Display::drawProgressBar(int x, int y, double percent, int width)
+{
+  // Clamp percentage
+  if (percent < 0)
+    percent = 0;
+  if (percent > 100)
+    percent = 100;
+
+  int filled = static_cast<int>((percent / 100.0) * width);
+
+  // Choose color based on percentage
+  short color;
+  if (percent > 90) {
+    color = ColorPair::Red;
+  } else if (percent > 70) {
+    color = ColorPair::Yellow;
+  } else if (percent > 50) {
+    color = ColorPair::Cyan;
+  } else if (percent < 0.01) {
+    color = ColorPair::Grey;
+  } else {
+    color = ColorPair::Green;
+  }
+
+  moveTo(y, x);
+  setColor(color);
+  for (int i = 0; i < filled; ++i) {
+    printf("#");
+  }
+
+  // Draw empty portion
+  setColor(ColorPair::Grey);
+  for (int i = filled; i < width; ++i) {
+    printf("-");
+  }
+  resetColor();
+}
+
+void
+Display::drawGraphLine(int x, int y, const std::vector<double> &data, int 
width, bool colored)
+{
+  moveTo(y, x);
+
+  // Take the last 'width' data points, or pad with zeros at the start
+  size_t start = 0;
+  if (data.size() > static_cast<size_t>(width)) {
+    start = data.size() - width;
+  }
+
+  int drawn = 0;
+
+  // Pad with empty blocks if data is shorter than width
+  int padding = width - static_cast<int>(data.size() - start);
+  for (int i = 0; i < padding; ++i) {
+    if (_ascii_mode) {
+      printf("%c", GraphChars::AsciiBlocks[0]);
+    } else {
+      printf("%s", GraphChars::Blocks[0]);
+    }
+    ++drawn;
+  }
+
+  // Draw the actual data
+  for (size_t i = start; i < data.size() && drawn < width; ++i) {
+    double val = data[i];
+    if (val < 0.0)
+      val = 0.0;
+    if (val > 1.0)
+      val = 1.0;
+
+    // Map value to block index (0-8)
+    int blockIdx = static_cast<int>(val * 8.0);
+    if (blockIdx > 8)
+      blockIdx = 8;
+
+    // Color based on value (btop-style gradient: blue -> cyan -> green -> 
yellow -> red)
+    if (colored) {
+      if (val < 0.2) {
+        setColor(ColorPair::Blue);
+      } else if (val < 0.4) {
+        setColor(ColorPair::Cyan);
+      } else if (val < 0.6) {
+        setColor(ColorPair::Green);
+      } else if (val < 0.8) {
+        setColor(ColorPair::Yellow);
+      } else {
+        setColor(ColorPair::Red);
+      }
+    }
+
+    if (_ascii_mode) {
+      printf("%c", GraphChars::AsciiBlocks[blockIdx]);
+    } else {
+      printf("%s", GraphChars::Blocks[blockIdx]);
+    }
+    ++drawn;
+  }
+
+  if (colored) {
+    resetColor();
+  }
+}
+
+void
+Display::drawMultiGraphBox(int x, int y, int width,
+                           const std::vector<std::tuple<std::string, 
std::vector<double>, std::string>> &graphs,
+                           const std::string                                   
                         &title)
+{
+  int height = static_cast<int>(graphs.size()) + 2; // +2 for top/bottom 
borders
+
+  // Draw box
+  if (title.empty()) {
+    // Simple separator
+    moveTo(y, x);
+    setColor(ColorPair::Border);
+    printf("%s", boxChar(BoxChars::TopLeft, BoxChars::AsciiTopLeft));
+    for (int i = 1; i < width - 1; ++i) {
+      printf("%s", boxChar(BoxChars::Horizontal, BoxChars::AsciiHorizontal));
+    }
+    printf("%s", boxChar(BoxChars::TopRight, BoxChars::AsciiTopRight));
+    resetColor();
+  } else {
+    drawBox(x, y, width, height, title, ColorPair::Border);
+  }
+
+  // Draw each graph row
+  int contentWidth = width - 4;                                  // -2 for 
borders, -2 for padding
+  int labelWidth   = 12;                                         // Fixed 
label width
+  int valueWidth   = 10;                                         // Fixed 
value width
+  int graphWidth   = contentWidth - labelWidth - valueWidth - 1; // -1 for 
space after label
+
+  int row = y + 1;
+  for (const auto &[label, data, value] : graphs) {
+    if (row >= y + height - 1) {
+      break;
+    }
+
+    // Position and draw border
+    moveTo(row, x);
+    setColor(ColorPair::Border);
+    printf("%s", boxChar(BoxChars::Vertical, BoxChars::AsciiVertical));
+    resetColor();
+
+    // Draw label (cyan)
+    printf(" ");
+    setColor(ColorPair::Cyan);
+    std::string truncLabel = label.substr(0, labelWidth);
+    printf("%-*s", labelWidth, truncLabel.c_str());
+    resetColor();
+
+    // Draw graph
+    printf(" ");
+    drawGraphLine(x + 2 + labelWidth + 1, row, data, graphWidth, true);
+
+    // Draw value (right-aligned)
+    moveTo(row, x + width - valueWidth - 2);
+    setColor(ColorPair::Green);
+    setBold();
+    printf("%*s", valueWidth, value.c_str());
+    resetColor();
+
+    // Right border
+    moveTo(row, x + width - 1);
+    setColor(ColorPair::Border);
+    printf("%s", boxChar(BoxChars::Vertical, BoxChars::AsciiVertical));
+    resetColor();
+
+    ++row;
+  }
+
+  // Bottom border (if no title, we need to draw it)
+  if (title.empty()) {
+    moveTo(y + height - 1, x);
+    setColor(ColorPair::Border);
+    printf("%s", boxChar(BoxChars::BottomLeft, BoxChars::AsciiBottomLeft));
+    for (int i = 1; i < width - 1; ++i) {
+      printf("%s", boxChar(BoxChars::Horizontal, BoxChars::AsciiHorizontal));
+    }
+    printf("%s", boxChar(BoxChars::BottomRight, BoxChars::AsciiBottomRight));
+    resetColor();
+  }
+}
+
+void
+Display::drawStatusBar(const std::string &host, Page page, bool absolute, bool 
connected)
+{
+  int status_y = _height - 1;
+
+  // Fill status bar with blue background
+  moveTo(status_y, 0);
+  printf("\033[44m\033[97m"); // Blue background, bright white text
+  for (int x = 0; x < _width; ++x) {
+    printf(" ");
+  }
+
+  // Time with icon - cyan colored
+  time_t    now = time(nullptr);
+  struct tm nowtm;
+  char      timeBuf[32];
+  localtime_r(&now, &nowtm);
+  strftime(timeBuf, sizeof(timeBuf), "%H:%M:%S", &nowtm);
+
+  moveTo(status_y, 1);
+  printf("\033[96m"); // Bright cyan
+  if (!_ascii_mode) {
+    printf("⏱ %s", timeBuf);
+  } else {
+    printf("%s", timeBuf);
+  }
+
+  // Host with connection status indicator
+  std::string hostDisplay;
+  moveTo(status_y, 12);
+  if (connected) {
+    if (!_ascii_mode) {
+      hostDisplay = "● " + host;
+    } else {
+      hostDisplay = "[OK] " + host;
+    }
+    printf("\033[92m"); // Bright green
+  } else {
+    if (!_ascii_mode) {
+      hostDisplay = "○ connecting...";
+    } else {
+      hostDisplay = "[..] connecting...";
+    }
+    printf("\033[93m"); // Bright yellow
+  }
+  if (hostDisplay.length() > 25) {
+    hostDisplay = hostDisplay.substr(0, 22) + "...";
+  }
+  printf("%-25s", hostDisplay.c_str());
+
+  // Page indicator - bright white
+  printf("\033[97m"); // Bright white
+  int pageNum = static_cast<int>(page) + 1;
+  int total   = getPageCount();
+  moveTo(status_y, 40);
+  printf("[%d/%d] ", pageNum, total);
+  printf("\033[93m%s", getPageName(page)); // Yellow page name
+
+  // Mode indicator - show ABS or RATE clearly
+  moveTo(status_y, 60);
+  if (absolute) {
+    printf("\033[30m\033[43m ABS \033[0m\033[44m"); // Black on yellow 
background
+  } else {
+    printf("\033[30m\033[42m RATE \033[0m\033[44m"); // Black on green 
background
+  }
+
+  // Key hints (right-aligned) - dimmer color
+  printf("\033[37m"); // Normal white (dimmer)
+  std::string hints;
+  if (_width > 110) {
+    hints = absolute ? "q:Quit h:Help 1-8:Pages a:Rate" : "q:Quit h:Help 
1-8:Pages a:Abs";
+  } else if (_width > 80) {
+    hints = "q h 1-8 a";
+  } else {
+    hints = "q h a";
+  }
+  int hints_x = _width - static_cast<int>(hints.length()) - 2;
+  if (hints_x > 68) {
+    moveTo(status_y, hints_x);
+    printf("%s", hints.c_str());
+  }
+
+  printf("\033[0m"); // Reset
+}
+
+const char *
+Display::getPageName(Page page)
+{
+  switch (page) {
+  case Page::Main:
+    return "Overview";
+  case Page::Response:
+    return "Responses";
+  case Page::Connection:
+    return "Connections";
+  case Page::Cache:
+    return "Cache";
+  case Page::SSL:
+    return "SSL/TLS";
+  case Page::Errors:
+    return "Errors";
+  case Page::Performance:
+    return "Performance";
+  case Page::Graphs:
+    return "Graphs";
+  case Page::Help:
+    return "Help";
+  default:
+    return "Unknown";
+  }
+}
+
+void
+Display::renderMainPage(Stats &stats)
+{
+  // Layout based on LAYOUT.md specifications:
+  //   80x24   - 2x2 grid of 40-char boxes (2 stat columns per box)
+  //   120x40  - 3 boxes per row x 5-6 rows
+  //   160x40  - 4 boxes per row x multiple rows
+
+  if (_width >= WIDTH_LARGE) {
+    // 160x40: 4 boxes per row (40 chars each)
+    render160Layout(stats);
+  } else if (_width >= WIDTH_MEDIUM) {
+    // 120x40: 3 boxes per row (40 chars each)
+    render120Layout(stats);
+  } else {
+    // 80x24: 2 boxes per row (40 chars each)
+    render80Layout(stats);
+  }
+}
+
+namespace
+{
+  // Format a stat value to a string with suffix (right-aligned number, suffix 
attached)
+  std::string
+  formatStatValue(double value, StatType type, int width = 5)
+  {
+    char   buffer[32];
+    char   suffix  = ' ';
+    double display = value;
+
+    if (isPercentage(type)) {
+      // Format percentage
+      snprintf(buffer, sizeof(buffer), "%*d%%", width - 1, 
static_cast<int>(display));
+    } else {
+      // Format with SI suffix
+      if (value >= 1000000000000.0) {
+        display = value / 1000000000000.0;
+        suffix  = 'T';
+      } else if (value >= 1000000000.0) {
+        display = value / 1000000000.0;
+        suffix  = 'G';
+      } else if (value >= 1000000.0) {
+        display = value / 1000000.0;
+        suffix  = 'M';
+      } else if (value >= 1000.0) {
+        display = value / 1000.0;
+        suffix  = 'K';
+      }
+
+      if (suffix != ' ') {
+        snprintf(buffer, sizeof(buffer), "%*d%c", width - 1, 
static_cast<int>(display), suffix);
+      } else {
+        snprintf(buffer, sizeof(buffer), "%*d ", width - 1, 
static_cast<int>(display));
+      }
+    }
+
+    return buffer;
+  }

Review Comment:
   Confirming this is already handled in the current PR code — I did not change 
it as part of this round. At Display.cc lines 921/940/942 formatStatValue 
already uses std::lround(display) (not static_cast<int>(display)), with the 
comment "Use rounding for accurate display (e.g., 1.9K displays as 2K, not 
1K)". So values round rather than truncate. This is the interactive curses 
display path only; the batch/JSON output the gold test exercises does not 
assert these formatted values, so no gold file is affected. Resolving as 
already-addressed.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to