CMake/Source/CursesDialog/cmCursesColor.cxx
Matthew Woehlke 671fe28313 ccmake: Improve coloring, allow customization
Change the default color for strings from BLUE (which is nearly
illegible on any terminals using the standard color palette which has
been around since at least CGA, almost 40 years ago) to CYAN. Add
ability to customize the colors via an environment variable (inspired by
LS_COLORS and using similar syntax).

Fixes: #20596
2020-04-24 11:21:13 -04:00

79 lines
1.9 KiB
C++

/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesColor.h"
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <unordered_map>
#include <utility>
#include "cmCursesStandardIncludes.h"
bool cmCursesColor::HasColors()
{
#ifdef HAVE_CURSES_USE_DEFAULT_COLORS
return has_colors();
#else
return false;
#endif
}
void cmCursesColor::InitColors()
{
#ifdef HAVE_CURSES_USE_DEFAULT_COLORS
if (HasColors()) {
start_color();
use_default_colors();
init_pair(BoolOff, GetColor('N', COLOR_RED), -1);
init_pair(BoolOn, GetColor('Y', COLOR_GREEN), -1);
init_pair(String, GetColor('S', COLOR_CYAN), -1);
init_pair(Path, GetColor('P', COLOR_YELLOW), -1);
init_pair(Choice, GetColor('C', COLOR_MAGENTA), -1);
}
#endif
}
short cmCursesColor::GetColor(char id, short fallback)
{
static bool initialized = false;
static std::unordered_map<char, short> env;
if (!initialized) {
if (auto* v = getenv("CCMAKE_COLORS")) {
while (v[0] && v[1] && v[1] == '=') {
auto const n = std::toupper(*v);
char buffer[12];
memset(buffer, 0, sizeof(buffer));
if (auto* const e = strchr(v, ':')) {
if (static_cast<size_t>(e - v) > sizeof(buffer)) {
break;
}
strncpy(buffer, v + 2, static_cast<size_t>(e - v - 2));
v = e + 1;
} else {
auto const l = strlen(v);
if (l > sizeof(buffer)) {
break;
}
strncpy(buffer, v + 2, l - 2);
v += l;
}
auto const c = atoi(buffer);
if (c && c < COLORS) {
env.emplace(n, static_cast<short>(c));
}
}
}
initialized = true;
}
auto const iter = env.find(id);
return (iter == env.end() ? fallback : iter->second);
}