NCurses 似乎具有有限数量的背景颜色(前景色效果很好)

NCurses appears to have a limited number of background colors (foreground colors work fine)

最终 运行 遇到了一个不寻常的问题:在程序启动时,我循环遍历所有支持的 256 种颜色(此处仅使用默认值)并创建一对包含所有可能排列的颜色——这导致65535 对我期望的每个 fg/bg 可能的组合。我已经通过打印到 stderr 来验证这些对是否符合预期。

只是为了检查一下,我的终端支持 256 种颜色、64k 对和 color/pair 重新分配。

问题出在这里:当尝试通过 attrset 打印任意 fg/bg 颜色时(并验证它实际上是上面打印的所需颜色对),前景色工作正常,但是背景颜色保持不变。如果我将所有值硬编码为单个 bg 颜色,它会按预期进行,同样,使每个排列具有相同的 fg/bg 颜色(即,将不同 fg/bg 对的数量限制为 256)也可以作为符合预期,如果我将配对生成代码限制为仅生成 256 对不同的配对,我会看到预期的背景颜色。

从根本上说,这似乎是对可以创建多少个唯一对的某种限制 (256);如果我使用 bg=0 的所有 64k 颜色对,我可以通过它的所有 256 对来寻址任何给定的颜色,结果 window 与我设置所有 fg/bg 排列的结果相同(即,就好像 ncurses 在内部使用 0 来表示所有 bg 颜色。

有什么想法可以解决这个问题吗?我在 valgrind 中没有看到任何内存问题,据我所知,ncurses 文档暗示我的用法是受支持的。 谢谢!

这是生成对的代码:

for(unsigned int c2 = 0; c2 < 256; c2++) {
        for(unsigned int c1 = 0; c1 < 256; c1++) {
            int pi = (c2)*256 + c1;
            init_extended_pair(pi, c1, c1);
            std::cerr << "init " << pi << " : " << c1 << ", " << c2 << "\n";
        }
    }

计算颜色 ID(我已经验证了这个独立工作 - +16 将它映射到默认的 ncurses 颜色,因为只有 216 种等距颜色)

unsigned int CursesObject::getColor(ColorRGBA col) {
    short r, g, b, er, eg, eb;
    r = int(col.r);
    g = int(col.g);
    b = int(col.b);
    
    er = r * 5 / 255;
    eg = g * 5 / 255;
    eb = b * 5 / 255;
    
    unsigned int colID = eb + eg*6 + er * 36;
    return colID + 16;
}

正在计算给定 fg/bg 的对 ID,完成调试代码以检索颜色值

void CursesObject::setColor(ColorRGBA fg, ColorRGBA bg) {
    if(fg == cfg && bg == cbg) return;
    else if(fg == bg) {
        attron(COLOR_PAIR(0));
        return;
    }
    //attrset(0x0);
    
    cfg = fg;
    cbg = bg;
    
    int pairID = this->getColor(fg) + (this->getColor(bg))*256;//\\ + 16;
    //std::cout << "colorPair: " << pairID << " from cid = " << this->getColor(fg) << ", col = " << fg.toString() <<"\n";
    
    static int uidbgOff = 25;
    short dr, db, dg, bbr,bbb,bbg;
    int cp1, cp2;
    extended_pair_content(pairID, &cp1, &cp2);
    color_content(cp1, &dr, &dg, &db);
    color_content(cp2, &bbr, &bbg, &bbb);
    
    std::stringstream ss;
    ss << pairID << " : " << dr << ", " << dg << ", " << db << " | " << bbr << ", " << bbg << ", " << bbb << " reported, pair " << cp1 << ":" << cp2 <<", should be " << this->getColor(fg) << ":" << this->getColor(bg)<<"\n";
    
    
    
    //sleep(5);
    attrset(COLOR_PAIR(pairID));
    this->write({10,uidbgOff}, ss.str());
    uidbgOff++;
    //this->update();
    
}

有趣的是,根据诊断函数的输出,这段代码 根本 不应该工作,即使只有 fg 颜色。例如,尝试打印红色、橙色和蓝绿色时的输出是这样的(它产生正确的颜色,尽管报告它们为零或完全错误:红色在 RGB 顺序中应该是 1k,0,0 - 而不是 0, 0,1k):

4804 : 0, 0, 1000 | 0, 0, 1000 reported, pair 196:18, should be 196:18

51664 : 0, 0, 0 | 0, 0, 0 reported, pair 0:0, should be 208:201

59168 : 0, 0, 0 | 0, 0, 0 reported, pair 0:0, should be 32:231

该示例混合使用了支持 扩展 颜色对和不支持的调用。 attronattrset 调用将颜色对存储在一个 8 位字段中。如果您使用 attr_onattr_set,它们会将颜色对存储为整数(远大于 8 位)。 extended_pair_content 建立在后者之上,允许使用大于 32767 的颜色对。