From fbe7f20a0f098ca03913452b29f50f0dc8568f77 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jakob=20Sch=C3=A4ffeler?= Date: Sat, 9 May 2026 23:27:43 +0200 Subject: [PATCH] gdb/tui: fix unexpected reuse of color pairs TUI translates ANSI styling sequences to curses color pairs. Currently, this process uses COLOR_PAIR, which only returns values from 0 to 255 which results in unexpected reuse of color pairs. Replacing wattron/wattroff with wcolor_set avoids the 256 color pair limit imposed by the COLOR_PAIR macro. However, wcolor_set takes a short for the pair index, limiting pairs to SHRT_MAX. To support the full range of COLOR_PAIRS (up to 65536 with ncurses 6.1+), init_pair is replaced with init_extended_pair, and the pair index is passed to wcolor_set via the opts parameter as an extended color pair, a documented ncurses extension. This also results in last_color_pair no longer being needed, and so it is removed. The extended color pair extension requires ncurses 6.1+, so a configure check has been added. The fallback path uses the older color pair API which limits GDB to SHRT_MAX (32767) color pairs. This patch was tested with make check-gdb TESTS="gdb.tui/*.exp" Additionally, I tested this with the python extension from the bug report. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34134 Approved-By: Andrew Burgess --- gdb/config.in | 3 +++ gdb/configure | 1 + gdb/configure.ac | 1 + gdb/tui/tui-io.c | 23 +++++++++++------------ 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/gdb/config.in b/gdb/config.in index 73d0b1913ce..1ef5dc5c2f4 100644 --- a/gdb/config.in +++ b/gdb/config.in @@ -250,6 +250,9 @@ /* Define to 1 if you have the `iconvlist' function. */ #undef HAVE_ICONVLIST +/* Define to 1 if you have the `init_extended_pair' function. */ +#undef HAVE_INIT_EXTENDED_PAIR + /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H diff --git a/gdb/configure b/gdb/configure index 3733ef76948..303d6ea011c 100755 --- a/gdb/configure +++ b/gdb/configure @@ -30238,6 +30238,7 @@ for ac_func in \ getrlimit \ getuid \ iconvlist \ + init_extended_pair \ libiconvlist \ posix_madvise \ pread \ diff --git a/gdb/configure.ac b/gdb/configure.ac index 5296d76f2cf..e55a733fba7 100644 --- a/gdb/configure.ac +++ b/gdb/configure.ac @@ -1520,6 +1520,7 @@ AC_CHECK_FUNCS([ \ getrlimit \ getuid \ iconvlist \ + init_extended_pair \ libiconvlist \ posix_madvise \ pread \ diff --git a/gdb/tui/tui-io.c b/gdb/tui/tui-io.c index 642b88ead0c..896d00f44c8 100644 --- a/gdb/tui/tui-io.c +++ b/gdb/tui/tui-io.c @@ -265,10 +265,6 @@ get_color (const ui_file_style::color &color, int *result) return true; } -/* The most recently emitted color pair. */ - -static int last_color_pair = -1; - /* The most recently applied style. */ static ui_file_style last_style; @@ -299,7 +295,11 @@ get_color_pair (int fg, int bg) back to the default if we've used too many. */ if (next >= COLOR_PAIRS) return 0; +#ifdef HAVE_INIT_EXTENDED_PAIR + init_extended_pair (next, fg, bg); +#else init_pair (next, fg, bg); +#endif color_pair_map[c] = next; return next; } @@ -320,9 +320,8 @@ tui_apply_style (WINDOW *w, ui_file_style style) #endif wattroff (w, A_UNDERLINE); wattroff (w, A_REVERSE); - if (last_color_pair != -1) - wattroff (w, COLOR_PAIR (last_color_pair)); - wattron (w, COLOR_PAIR (0)); + + wcolor_set (w, 0, nullptr); const ui_file_style::color &fg = style.get_foreground (); const ui_file_style::color &bg = style.get_background (); @@ -342,10 +341,11 @@ tui_apply_style (WINDOW *w, ui_file_style style) bgi = (ncurses_norm_attr >> 4) & 15; #endif int pair = get_color_pair (fgi, bgi); - if (last_color_pair != -1) - wattroff (w, COLOR_PAIR (last_color_pair)); - wattron (w, COLOR_PAIR (pair)); - last_color_pair = pair; +#ifdef HAVE_INIT_EXTENDED_PAIR + wcolor_set (w, 0, &pair); +#else + wcolor_set (w, pair, nullptr); +#endif } } @@ -907,7 +907,6 @@ tui_setup_io (int mode) savetty (); /* Clean up color information. */ - last_color_pair = -1; last_style = ui_file_style (); color_map.clear (); color_pair_map.clear (); -- 2.47.3