nsnake
Classic snake game for the terminal
Colors.cpp
1 #include <Interface/Colors.hpp>
2 
3 #include <cstdlib> // strtol()
4 
5 bool Colors::hasColors = false;
6 
7 bool Colors::init()
8 {
9  if (has_colors() != TRUE) /* ncurses BOOL */
10  {
11  Colors::hasColors = false;
12  return false;
13  }
14  Colors::hasColors = true;
15 
16  start_color();
17 
18  // This is a big hack to initialize all 64
19  // possible color pairs in ncurses.
20  //
21  // The thing is, all colors are between
22  // COLOR_BLACK and COLOR_WHITE.
23  // Since I've set a large number of enums covering
24  // all possibilities, I can do it all in a for loop.
25  // Check 'man init_pair' for more details.
26  //
27  // Here's the internal value of colors,
28  // taken straight from <curses.h>:
29  //
30  // #define COLOR_BLACK 0
31  // #define COLOR_RED 1
32  // #define COLOR_GREEN 2
33  // #define COLOR_YELLOW 3
34  // #define COLOR_BLUE 4
35  // #define COLOR_MAGENTA 5
36  // #define COLOR_CYAN 6
37  // #define COLOR_WHITE 7
38  //
39  int i, j, k = 1;
40  for (i = COLOR_BLACK; i <= COLOR_WHITE; i++)
41  {
42  for (j = COLOR_BLACK; j <= COLOR_WHITE; j++)
43  {
44  init_pair(k, i, j);
45  k++;
46  }
47  }
48 
49  // Besides the normal color pairs, we can use
50  // whatever colors the user has currently set to
51  // their terminal.
52  // It looks more "natural".
53  //
54  // So COLOR_PAIR(-1, -1) is the default foreground
55  // and background.
56  //
57  // Let's do it if the current terminal supports it.
58 
59  if (use_default_colors() != ERR)
60  {
61  // default background
62  init_pair(64, COLOR_BLACK, COLOR_DEFAULT);
63  init_pair(65, COLOR_RED, COLOR_DEFAULT);
64  init_pair(66, COLOR_GREEN, COLOR_DEFAULT);
65  init_pair(67, COLOR_YELLOW, COLOR_DEFAULT);
66  init_pair(68, COLOR_BLUE, COLOR_DEFAULT);
67  init_pair(69, COLOR_MAGENTA, COLOR_DEFAULT);
68  init_pair(70, COLOR_CYAN, COLOR_DEFAULT);
69  init_pair(71, COLOR_WHITE, COLOR_DEFAULT);
70  }
71  return true;
72 }
73 
74 Color Colors::rgb(short r, short g, short b)
75 {
76  if (can_change_color() == FALSE)
77  return 0;
78 
79  if (COLORS < 256)
80  return 0;
81 
82  static int color_no = 8;
83  color_no++;
84  if (color_no >= COLORS)
85  color_no = 8;
86 
87  // init_color receives values from 0 to 1000
88  int expand = 1000/255;
89 
90  init_color((color_no - 1), r*expand, g*expand, b*expand);
91  return (color_no - 1);
92 }
93 Color Colors::hex(std::string hex)
94 {
95  if (hex[0] != '#') return 0; // sorry
96  if (hex.size() != 7) return 0; // #RRGGBB format
97 
98  char col[3];
99  col[2] = '\0';
100 
101  col[0] = hex[1];
102  col[1] = hex[2];
103  long r = strtol(col, NULL, 16);
104 
105  col[0] = hex[3];
106  col[1] = hex[4];
107  long g = strtol(col, NULL, 16);
108 
109  col[0] = hex[5];
110  col[1] = hex[6];
111  long b = strtol(col, NULL, 16);
112 
113  return Colors::rgb(r, g, b);
114 }
115 
116 ColorPair Colors::pair(Color foreground, Color background, bool is_bold)
117 {
118  // Basic nCurses colors
119  if ((foreground < 8) && (background < 8))
120  {
121  if (background == COLOR_DEFAULT)
122  {
123  if (is_bold)
124  return COLOR_PAIR(64 + foreground) | A_BOLD;
125  else
126  return COLOR_PAIR(64 + foreground);
127  }
128 
129  if (is_bold)
130  return COLOR_PAIR(foreground*8 + background + 1) | A_BOLD;
131  else
132  return COLOR_PAIR(foreground*8 + background + 1);
133  }
134 
135  if (COLORS < 256)
136  {
137  if (is_bold)
138  return COLOR_PAIR(0) | A_BOLD;
139  else
140  return COLOR_PAIR(0);
141  }
142 
143  // Will create color pair
144  // (above the 64 regular ones plus 12 default = 72)
145  static int color_pair_no = 72;
146  color_pair_no++;
147  if (color_pair_no >= COLOR_PAIRS)
148  color_pair_no = 72;
149 
150  init_pair((color_pair_no - 1), foreground, background);
151 
152  if (is_bold)
153  return COLOR_PAIR(color_pair_no - 1) | A_BOLD;
154  else
155  return COLOR_PAIR(color_pair_no - 1);
156 }
157 Color Colors::fromString(std::string str)
158 {
159  if (str.empty())
160  return 255;
161 
162  if (str == "default") return COLOR_DEFAULT;
163  if (str == "black") return COLOR_BLACK;
164  if (str == "red") return COLOR_RED;
165  if (str == "green") return COLOR_GREEN;
166  if (str == "yellow") return COLOR_YELLOW;
167  if (str == "blue") return COLOR_BLUE;
168  if (str == "magenta") return COLOR_MAGENTA;
169  if (str == "cyan") return COLOR_CYAN;
170  if (str == "white") return COLOR_WHITE;
171 
172  // keep in mind this error code
173  return 255;
174 }
175 
176 ColorPair Colors::pairFromString(std::string foreground, std::string background, bool is_bold)
177 {
178  if (foreground.empty() || background.empty())
179  return 255;
180 
181  short f = Colors::fromString(foreground);
182  short b = Colors::fromString(background);
183 
184  return Colors::pair(f, b, is_bold);
185 }
186 
187 void Colors::activate(WINDOW* window, Color foreground, Color background)
188 {
189  Colors::pairActivate(window, Colors::pair(foreground, background));
190 }
191 
192 void Colors::pairActivate(WINDOW* window, ColorPair color)
193 {
194  wattrset(window, color);
195 }
196