1 /* 2 * Copyright 2010-2013, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stefano Ceccherini, stefano.ceccherini@gmail.com 7 * Siarzhuk Zharski, zharik@gmx.li 8 */ 9 10 11 #include "Colors.h" 12 13 #include <ctype.h> 14 #include <stdio.h> 15 #include <strings.h> 16 17 #include <Application.h> 18 #include <Catalog.h> 19 #include <Resources.h> 20 21 22 #undef B_TRANSLATION_CONTEXT 23 #define B_TRANSLATION_CONTEXT "Terminal colors scheme" 24 25 26 // Standard colors 27 const rgb_color kBlack = { 0, 0, 0, 255 }; 28 const rgb_color kGreen = { 0, 255, 0, 255 }; 29 const rgb_color kWhite = { 255, 255, 255, 255 }; 30 const rgb_color kYellow = { 255, 255, 0, 255 }; 31 32 const struct ansi_color_scheme kAnsiColorSchemeDefault = { 33 { 40, 40, 40, 255 }, 34 { 204, 0, 0, 255 }, 35 { 78, 154, 6, 255 }, 36 { 218, 168, 0, 255 }, 37 { 51, 102, 152, 255 }, 38 { 115, 68, 123, 255 }, 39 { 6, 152, 154, 255 }, 40 { 245, 245, 245, 255 } 41 }; 42 43 /* The 'bright' colors palette, relates to the existing 44 PREF_ANSI_<color>_HCOLOR macros used elsewhere */ 45 const struct ansi_color_scheme kAnsiColorHSchemeDefault = { 46 { 128, 128, 128, 255 }, 47 { 255, 0, 0, 255 }, 48 { 0, 255, 0, 255 }, 49 { 255, 255, 0, 255 }, 50 { 0, 0, 255, 255 }, 51 { 255, 0, 255, 255 }, 52 { 0, 255, 255, 255 }, 53 { 255, 255, 255, 255 } 54 }; 55 56 const struct color_scheme kColorSchemeDefault = { 57 B_TRANSLATE("Default"), 58 kBlack, 59 kWhite, 60 kWhite, 61 kBlack, 62 kWhite, 63 kBlack, 64 kAnsiColorSchemeDefault, 65 kAnsiColorHSchemeDefault 66 }; 67 68 const struct color_scheme kColorSchemeBlue = { 69 B_TRANSLATE("Blue"), 70 kYellow, 71 { 0, 0, 139, 255 }, 72 kBlack, 73 kYellow, 74 kBlack, 75 { 0, 139, 139, 255 }, 76 kAnsiColorSchemeDefault, 77 kAnsiColorHSchemeDefault 78 }; 79 80 const struct color_scheme kColorSchemeMidnight = { 81 B_TRANSLATE("Midnight"), 82 kWhite, 83 kBlack, 84 kBlack, 85 kWhite, 86 kBlack, 87 kWhite, 88 kAnsiColorSchemeDefault, 89 kAnsiColorHSchemeDefault 90 }; 91 92 const struct color_scheme kColorSchemeProfessional = { 93 B_TRANSLATE("Professional"), 94 kWhite, 95 { 8, 8, 8, 255 }, 96 { 50, 50, 50, 255 }, 97 kWhite, 98 kWhite, 99 { 50, 50, 50, 255 }, 100 kAnsiColorSchemeDefault, 101 kAnsiColorHSchemeDefault 102 }; 103 104 const struct color_scheme kColorSchemeRetro = { 105 B_TRANSLATE("Retro"), 106 kGreen, 107 kBlack, 108 kBlack, 109 kGreen, 110 kBlack, 111 kGreen, 112 kAnsiColorSchemeDefault, 113 kAnsiColorHSchemeDefault 114 }; 115 116 const struct color_scheme kColorSchemeSlate = { 117 B_TRANSLATE("Slate"), 118 kWhite, 119 { 20, 20, 28, 255 }, 120 { 70, 70, 70, 255 }, 121 { 255, 200, 0, 255 }, 122 kWhite, 123 { 70, 70, 70, 255 }, 124 kAnsiColorSchemeDefault, 125 kAnsiColorHSchemeDefault 126 }; 127 128 const struct color_scheme kColorSchemeSolarizedDark = { 129 B_TRANSLATE("Solarized Dark"), 130 { 131, 148, 150, 255 }, 131 { 0, 43, 54, 255 }, 132 { 0, 46, 57, 255 }, 133 { 120, 137, 139, 255 }, 134 { 238, 232, 213, 255 }, 135 { 88, 110, 117, 255 }, 136 { 137 { 7, 54, 66, 255 }, 138 { 220, 50, 47, 255 }, 139 { 133, 153, 0, 255 }, 140 { 181, 137, 0, 255 }, 141 { 38, 139, 210, 255 }, 142 { 211, 54, 130, 255 }, 143 { 42, 161, 152, 255 }, 144 { 238, 232, 213, 255 } 145 }, 146 { 147 { 0, 43, 54, 255 }, 148 { 203, 75, 22, 255 }, 149 { 88, 110, 117, 255 }, 150 { 101, 123, 131, 255 }, 151 { 131, 148, 150, 255 }, 152 { 108, 113, 196, 255 }, 153 { 147, 161, 161, 255 }, 154 { 253, 246, 227, 255 } 155 } 156 }; 157 158 const struct color_scheme kColorSchemeSolarizedLight = { 159 B_TRANSLATE("Solarized Light"), 160 { 101, 123, 131, 255 }, 161 { 253, 246, 227, 255 }, 162 { 236, 228, 207, 255 }, 163 { 90, 112, 120, 255 }, 164 { 147, 161, 161, 255 }, 165 { 7, 54, 66, 255 }, 166 { 167 { 7, 54, 66, 255 }, 168 { 220, 50, 47, 255 }, 169 { 133, 153, 0, 255 }, 170 { 181, 137, 0, 255 }, 171 { 38, 139, 210, 255 }, 172 { 211, 54, 130, 255 }, 173 { 42, 161, 152, 255 }, 174 { 238, 232, 213, 255 } 175 }, 176 { 177 { 0, 43, 54, 255 }, 178 { 203, 75, 22, 255 }, 179 { 88, 110, 117, 255 }, 180 { 101, 123, 131, 255 }, 181 { 131, 148, 150, 255 }, 182 { 108, 113, 196, 255 }, 183 { 147, 161, 161, 255 }, 184 { 253, 246, 227, 255 } 185 } 186 }; 187 188 const struct color_scheme kColorSchemeRelaxed = { 189 B_TRANSLATE("Relaxed"), 190 { 217, 217, 217, 255 }, 191 { 53, 58, 68, 255 }, 192 { 27, 27, 27, 255 }, 193 { 255, 203, 0, 255 }, 194 { 53, 58, 68, 255 }, 195 { 217, 217, 217, 255 }, 196 { 197 { 21, 21, 21, 255 }, 198 { 188, 86, 83, 255 }, 199 { 144, 157, 99, 255 }, 200 { 235, 193, 122, 255 }, 201 { 106, 135, 153, 255 }, 202 { 176, 102, 152, 255 }, 203 { 201, 223, 255, 255 }, 204 { 217, 217, 217, 255 } 205 }, 206 { 207 { 99, 99, 99, 255 }, 208 { 188, 86, 83, 255 }, 209 { 160, 172, 119, 255 }, 210 { 235, 192, 122, 255 }, 211 { 126, 170, 199, 255 }, 212 { 176, 102, 152, 255 }, 213 { 172, 187, 208, 255 }, 214 { 247, 247, 247, 255 } 215 } 216 }; 217 218 struct color_scheme gCustomColorScheme = { 219 B_TRANSLATE("Custom") 220 }; 221 222 const color_scheme* gPredefinedColorSchemes[] = { 223 &kColorSchemeDefault, 224 &kColorSchemeBlue, 225 &kColorSchemeMidnight, 226 &kColorSchemeProfessional, 227 &kColorSchemeRetro, 228 &kColorSchemeSlate, 229 &kColorSchemeSolarizedDark, 230 &kColorSchemeSolarizedLight, 231 &kColorSchemeRelaxed, 232 &gCustomColorScheme, 233 NULL 234 }; 235 236 237 bool 238 ansi_color_scheme::operator==(const ansi_color_scheme& scheme) 239 { 240 return black == scheme.black 241 && red == scheme.red 242 && green == scheme.green 243 && yellow == scheme.yellow 244 && blue == scheme.blue 245 && magenta == scheme.magenta 246 && cyan == scheme.cyan 247 && white == scheme.white; 248 } 249 250 251 bool 252 color_scheme::operator==(const color_scheme& scheme) 253 { 254 return text_fore_color == scheme.text_fore_color 255 && text_back_color == scheme.text_back_color 256 && cursor_fore_color == scheme.cursor_fore_color 257 && cursor_back_color == scheme.cursor_back_color 258 && select_fore_color == scheme.select_fore_color 259 && select_back_color == scheme.select_back_color 260 && ansi_colors == scheme.ansi_colors 261 && ansi_colors_h == scheme.ansi_colors_h; 262 } 263 264 // #pragma mark XColorsTable implementation 265 266 XColorsTable gXColorsTable; 267 268 269 XColorsTable::XColorsTable() 270 : 271 fTable(NULL), 272 fCount(0) 273 { 274 } 275 276 277 XColorsTable::~XColorsTable() 278 { 279 // fTable as result of LoadResource call and owned 280 // by BApplication so no need to free it explicitly 281 fTable = NULL; 282 fCount = 0; 283 } 284 285 286 status_t 287 XColorsTable::LookUpColor(const char* name, rgb_color* color) 288 { 289 if (name == NULL || color == NULL) 290 return B_BAD_DATA; 291 292 size_t length = strlen(name); 293 294 // first check for 'rgb:xx/xx/xx' or '#xxxxxx'-encoded color names 295 u_int r = 0, g = 0, b = 0; 296 float c = 0, m = 0, y = 0, k = 0; 297 if ((length == 12 && sscanf(name, "rgb:%02x/%02x/%02x", &r, &g, &b) == 3) 298 || (length == 7 && sscanf(name, "#%02x%02x%02x", &r, &g, &b) == 3)) { 299 color->set_to(r, g, b); 300 return B_OK; 301 // then check for 'rgb:xxxx/xxxx/xxxx' or '#xxxxxxxxxxxx'-encoded color names 302 } else if ((length == 18 && sscanf(name, "rgb:%04x/%04x/%04x", &r, &g, &b) == 3) 303 || (length == 13 && sscanf(name, "#%04x%04x%04x", &r, &g, &b) == 3)) { 304 color->set_to(r >> 8, g >> 8, b >> 8); 305 return B_OK; 306 // then check for 'cmyk:c.c/m.m/y.y/k.k' or 'cmy:c.c/m.m/y.y'-encoded color names 307 } else if (sscanf(name, "cmyk:%f/%f/%f/%f", &c, &m, &y, &k) == 4 308 || sscanf(name, "cmy:%f/%f/%f", &c, &m, &y) == 3) { 309 if (c >= 0 && m >= 0 && y >= 0 && k >= 0 310 && c <= 1 && m <= 1 && y <= 1 && k <= 1) { 311 color->set_to((1 - c) * (1 - k) * 255, 312 (1 - m) * (1 - k) * 255, 313 (1 - y) * (1 - k) * 255); 314 return B_OK; 315 } 316 } 317 318 // then search the X11 rgb table 319 if (fTable == NULL) { 320 status_t result = _LoadXColorsTable(); 321 if (result != B_OK) 322 return result; 323 } 324 325 // use binary search to lookup color name hash in table 326 int left = -1; 327 int right = fCount; 328 uint32 hash = _HashName(name); 329 while ((right - left) > 1) { 330 int i = (left + right) / 2; 331 ((fTable[i].hash < hash) ? left : right) = i; 332 } 333 334 if (fTable[right].hash == hash) { 335 *color = fTable[right].color; 336 return B_OK; 337 } 338 339 return B_NAME_NOT_FOUND; 340 } 341 342 343 status_t 344 XColorsTable::_LoadXColorsTable() 345 { 346 BResources* res = BApplication::AppResources(); 347 if (res == NULL) 348 return B_ERROR; 349 350 size_t size = 0; 351 fTable = (_XColorEntry*)res->LoadResource(B_RAW_TYPE, "XColorsTable", &size); 352 if (fTable == NULL || size < sizeof(_XColorEntry)) { 353 fTable = NULL; 354 return B_ENTRY_NOT_FOUND; 355 } 356 357 fCount = size / sizeof(_XColorEntry); 358 return B_OK; 359 } 360 361 362 uint32 363 XColorsTable::_HashName(const char* name) 364 { 365 uint32 hash = 0; 366 uint32 g = 0; 367 368 // Using modified P.J.Weinberger hash algorithm 369 // Spaces are purged out, characters are upper-cased 370 // 'E' replaced with 'A' (to join 'grey' and 'gray' variations) 371 for (const char* p = name; *p; p++) { 372 int ch = toupper(*p); 373 switch (ch) { 374 case ' ': 375 break; 376 case 'E': 377 ch = 'A'; 378 default: 379 hash = (hash << 4) + (ch & 0xFF); 380 g = hash & 0xf0000000; 381 if (g != 0) { 382 hash ^= g >> 24; 383 hash ^= g; 384 } 385 break; 386 } 387 } 388 389 return hash; 390 } 391