使用ncurses设置新颜色后,粗体黑字意外变为橙色的问题
ncurses中A_BOLD导致颜色异常的问题分析与解决
预先将编号为8的颜色设置为橙色供后续使用,当前需要输出灰色(黑色+粗体属性)文本,但该特定组合却变为了新设置的橙色。代码如下:
#include <curses.h> int main() { ::initscr(); ::start_color(); ::init_color(8, 1000, 500, 0); //Set the 8th color to be orange ::init_pair(1, COLOR_BLACK, COLOR_BLACK); //Set the 1st pair to be black on black ::mvaddstr(0, 0, "Some dim text."); ::mvchgat(0, 0, -1, 0, 1, 0); //Text should be dark black on dark black (invisible) ::mvaddstr(1, 0, "Some bold text."); ::mvchgat(1, 0, -1, A_BOLD, 1, 0); //Text should be light black on dark black ::getch(); ::endwin(); }预期"Some dim text."不可见,"Some bold text."为浅黑底黑字,但实际仅"Some bold text."显示为亮橙色。
问题根源
在标准8/16色终端模式下,ncurses默认将颜色编号0-7作为普通色,8-15作为对应普通色的高亮(亮)版本:
COLOR_BLACK(编号0)的高亮版本对应颜色编号8COLOR_RED(编号1)的高亮版本对应颜色编号9,以此类推
当给文本添加A_BOLD属性时,ncurses会自动将前景色替换为对应普通色的高亮版本。你刚好把颜色8设置为橙色,所以带A_BOLD的黑字就被替换成了橙色,导致不符合预期。
解决方案
方案一:使用非默认亮色映射的颜色编号(推荐,适合现代终端)
大部分现代终端支持256色模式,颜色编号16及以上不会被用作默认的亮色映射,可以用这些编号设置橙色,避免干扰A_BOLD的默认行为:
#include <curses.h> int main() { ::initscr(); ::start_color(); // 使用编号16设置橙色,不影响默认亮色映射 ::init_color(16, 1000, 500, 0); // 后续使用橙色时,创建对应的颜色对 ::init_pair(2, 16, COLOR_BLACK); ::init_pair(1, COLOR_BLACK, COLOR_BLACK); ::mvaddstr(0, 0, "Some dim text."); ::mvchgat(0, 0, -1, 0, 1, 0); ::mvaddstr(1, 0, "Some bold text."); // A_BOLD会使用默认亮黑(编号8),显示为浅黑 ::mvchgat(1, 0, -1, A_BOLD, 1, 0); // 测试橙色文本 ::mvaddstr(2, 0, "Some orange text."); ::mvchgat(2, 0, -1, 0, 2, 0); ::getch(); ::endwin(); }
方案二:显式管理亮黑颜色(适合必须使用编号8的场景)
如果必须将编号8设为橙色,可以先保存默认亮黑的RGB值,再将其转移到其他编号,创建独立的颜色对来实现“黑+粗体”的效果:
#include <curses.h> int main() { ::initscr(); ::start_color(); // 保存默认颜色8(亮黑)的RGB值 short r, g, b; ::color_content(8, &r, &g, &b); // 设置颜色8为橙色 ::init_color(8, 1000, 500, 0); // 将原来的亮黑转移到编号9 ::init_color(9, r, g, b); // 颜色对1:普通黑底黑字(不可见) ::init_pair(1, COLOR_BLACK, COLOR_BLACK); // 颜色对2:亮黑底黑字(替代A_BOLD效果) ::init_pair(2, 9, COLOR_BLACK); // 颜色对3:橙色底黑字(后续使用) ::init_pair(3, 8, COLOR_BLACK); ::mvaddstr(0, 0, "Some dim text."); ::mvchgat(0, 0, -1, 0, 1, 0); ::mvaddstr(1, 0, "Some bold-like text."); // 使用颜色对2实现浅黑效果,不依赖A_BOLD ::mvchgat(1, 0, -1, 0, 2, 0); ::mvaddstr(2, 0, "Some orange text."); ::mvchgat(2, 0, -1, 0, 3, 0); ::getch(); ::endwin(); }
补充说明
部分终端支持真正的粗体渲染(而非用亮色模拟),可以尝试将TERM环境变量设置为xterm-256color或其他支持粗体的终端类型,但这种方式依赖终端配置,兼容性不如前两种方案。
内容的提问来源于stack exchange,提问作者Weak to Enuma Elish
相关产品推荐
相关产品推荐

