summaryrefslogtreecommitdiffstats
path: root/Source/CursesDialog/cmCursesColor.cxx
blob: c0b468b6006031cac434d94be062c99cc6824035 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/* 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);
}