diff --git a/src/interactive/interactive.cpp b/src/interactive/interactive.cpp index aa1dd60..9543a59 100644 --- a/src/interactive/interactive.cpp +++ b/src/interactive/interactive.cpp @@ -6,98 +6,94 @@ #include #include #include +#include +#include #include "interactive.hpp" namespace interactive { -// Helper function to convert ANSI color codes to ncurses attributes -int ansi_to_ncurses_attr(const std::string& ansi_code) { - if (ansi_code == "0") return A_NORMAL; - if (ansi_code == "1") return A_BOLD; - - // Handle colors - if (ansi_code == "1;31") return A_BOLD | COLOR_PAIR(2); // Red - if (ansi_code == "1;32") return A_BOLD | COLOR_PAIR(3); // Green - if (ansi_code == "1;33") return A_BOLD | COLOR_PAIR(4); // Yellow - if (ansi_code == "1;34") return A_BOLD | COLOR_PAIR(5); // Blue - if (ansi_code == "1;35") return A_BOLD | COLOR_PAIR(6); // Magenta - if (ansi_code == "1;36") return A_BOLD | COLOR_PAIR(7); // Cyan - if (ansi_code == "1;37") return A_BOLD | COLOR_PAIR(8); // White - if (ansi_code == "90") return COLOR_PAIR(9); // Dark Grey - if (ansi_code == "38;5;142") return COLOR_PAIR(10); // Dark Yellow - if (ansi_code == "38;5;250") return COLOR_PAIR(11); // Light Grey - - return A_NORMAL; -} - int fullscreen_window::ncurses_streambuf::overflow(int c) { if (c != EOF) { - buffer += static_cast(c); - if (c == '\n') { - // Process ANSI escape sequences - std::string processed; - size_t pos = 0; - while (pos < buffer.length()) { - if (buffer[pos] == '\033' && pos + 1 < buffer.length() && buffer[pos + 1] == '[') { - // Found ANSI escape sequence - size_t end = buffer.find('m', pos); - if (end != std::string::npos) { - std::string ansi_code = buffer.substr(pos + 2, end - pos - 2); - int ncurses_attr = ansi_to_ncurses_attr(ansi_code); - wattron(win, ncurses_attr); - pos = end + 1; - } else { - // Invalid ANSI sequence, just print it - processed += buffer[pos++]; - } - } else { - processed += buffer[pos++]; - } - } + // Check for ANSI escape sequence + if (c == '\033') { + is_escape_sequence = true; + escape_sequence = "\033"; + } else if (is_escape_sequence) { + escape_sequence += static_cast(c); - wprintw(win, "%s", processed.c_str()); + // Check if the escape sequence is complete + if (escape_sequence.size() >= 2 && escape_sequence[1] == '[' && + (c == 'm' || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))) { + + // Handle color codes + if (escape_sequence.back() == 'm') { + // Process color code + if (escape_sequence == "\033[0m") { + wattrset(win, A_NORMAL); // Reset attributes + } else if (escape_sequence == "\033[1;31m") { + wattron(win, COLOR_PAIR(1)); // Red + } else if (escape_sequence == "\033[1;32m") { + wattron(win, COLOR_PAIR(2)); // Green + } else if (escape_sequence == "\033[1;33m") { + wattron(win, COLOR_PAIR(3)); // Yellow + } else if (escape_sequence == "\033[1;34m") { + wattron(win, COLOR_PAIR(4)); // Blue + } else if (escape_sequence == "\033[1;35m") { + wattron(win, COLOR_PAIR(5)); // Magenta + } else if (escape_sequence == "\033[1;36m") { + wattron(win, COLOR_PAIR(6)); // Cyan + } else if (escape_sequence == "\033[1;37m") { + wattron(win, COLOR_PAIR(7)); // White + } else if (escape_sequence == "\033[90m") { + wattron(win, A_DIM | COLOR_PAIR(7)); // Dark grey + } else if (escape_sequence == "\033[38;5;142m") { + wattron(win, COLOR_PAIR(3) | A_DIM); // Dark yellow + } else if (escape_sequence == "\033[38;5;250m") { + wattron(win, COLOR_PAIR(7) | A_DIM); // Light grey + } + } + + is_escape_sequence = false; + escape_sequence.clear(); + } + } else if (c == '\n') { + wprintw(win, "%s", buffer.c_str()); wrefresh(win); buffer.clear(); + } else { + buffer += static_cast(c); } } return c; } fullscreen_window::fullscreen_window(std::string title) { + // Set locale for wide character support + std::setlocale(LC_ALL, ""); + // Initialize ncurses initscr(); - start_color(); - use_default_colors(); - - // Initialize color pairs - init_pair(1, COLOR_BLACK, -1); // Black - init_pair(2, COLOR_RED, -1); // Red - init_pair(3, COLOR_GREEN, -1); // Green - init_pair(4, COLOR_YELLOW, -1); // Yellow - init_pair(5, COLOR_BLUE, -1); // Blue - init_pair(6, COLOR_MAGENTA, -1); // Magenta - init_pair(7, COLOR_CYAN, -1); // Cyan - init_pair(8, COLOR_WHITE, -1); // White - init_pair(9, COLOR_BLACK, -1); // Dark Grey - init_pair(10, COLOR_YELLOW, -1); // Dark Yellow - init_pair(11, COLOR_WHITE, -1); // Light Grey - raw(); // Use raw mode for better control noecho(); keypad(stdscr, TRUE); // Enable keypad curs_set(0); // Hide cursor set_escdelay(25); // Set ESC delay to 25ms + + // Enable color support + start_color(); + use_default_colors(); + + // Initialize color pairs for ANSI colors + init_pair(1, COLOR_RED, -1); // Red + init_pair(2, COLOR_GREEN, -1); // Green + init_pair(3, COLOR_YELLOW, -1); // Yellow + init_pair(4, COLOR_BLUE, -1); // Blue + init_pair(5, COLOR_MAGENTA, -1); // Magenta + init_pair(6, COLOR_CYAN, -1); // Cyan + init_pair(7, COLOR_WHITE, -1); // White + refresh(); - // Initialize color pairs - init_pair(12, COLOR_RED, -1); - init_pair(13, COLOR_GREEN, -1); - init_pair(14, COLOR_YELLOW, -1); - init_pair(15, COLOR_BLUE, -1); - init_pair(16, COLOR_MAGENTA, -1); - init_pair(17, COLOR_CYAN, -1); - init_pair(18, COLOR_WHITE, -1); - // Create display window (takes up all but bottom 4 lines) int max_y, max_x; getmaxyx(stdscr, max_y, max_x); diff --git a/src/interactive/interactive.hpp b/src/interactive/interactive.hpp index a92b9c2..a080c83 100644 --- a/src/interactive/interactive.hpp +++ b/src/interactive/interactive.hpp @@ -23,6 +23,8 @@ class fullscreen_window { private: WINDOW* win; std::string buffer; + bool is_escape_sequence = false; + std::string escape_sequence; protected: virtual int overflow(int c) override;