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 33 const struct color_scheme kColorSchemeDefault = { 34 B_TRANSLATE("Default"), 35 kBlack, 36 kWhite, 37 kWhite, 38 kBlack, 39 kWhite, 40 kBlack 41 }; 42 43 const struct color_scheme kColorSchemeBlue = { 44 B_TRANSLATE("Blue"), 45 kYellow, 46 { 0, 0, 139, 255 }, 47 kBlack, 48 kYellow, 49 kBlack, 50 { 0, 139, 139, 255 }, 51 }; 52 53 const struct color_scheme kColorSchemeMidnight = { 54 B_TRANSLATE("Midnight"), 55 kWhite, 56 kBlack, 57 kBlack, 58 kWhite, 59 kBlack, 60 kWhite 61 }; 62 63 const struct color_scheme kColorSchemeProfessional = { 64 B_TRANSLATE("Professional"), 65 kWhite, 66 { 8, 8, 8, 255 }, 67 { 50, 50, 50, 255 }, 68 kWhite, 69 kWhite, 70 { 50, 50, 50, 255 }, 71 }; 72 73 const struct color_scheme kColorSchemeRetro = { 74 B_TRANSLATE("Retro"), 75 kGreen, 76 kBlack, 77 kBlack, 78 kGreen, 79 kBlack, 80 kGreen 81 }; 82 83 const struct color_scheme kColorSchemeSlate = { 84 B_TRANSLATE("Slate"), 85 kWhite, 86 { 20, 20, 28, 255 }, 87 { 70, 70, 70, 255 }, 88 { 255, 200, 0, 255 }, 89 kWhite, 90 { 70, 70, 70, 255 }, 91 }; 92 93 const struct color_scheme kColorSchemeSolarizedDark = { 94 B_TRANSLATE("Solarized Dark"), 95 { 119, 137, 139, 255 }, 96 { 0, 36, 45, 255 }, 97 { 0, 46, 57, 255 }, 98 { 120, 137, 139, 255 }, 99 { 136, 151, 151, 255 }, 100 { 0, 46, 57, 255 }, 101 }; 102 103 const struct color_scheme kColorSchemeSolarizedLight = { 104 B_TRANSLATE("Solarized Light"), 105 { 90, 112, 120, 255 }, 106 { 253, 244, 223, 255 }, 107 { 236, 228, 207, 255 }, 108 { 90, 112, 120, 255 }, 109 { 78, 99, 106, 255 }, 110 { 236, 228, 207, 255 }, 111 }; 112 113 struct color_scheme gCustomColorScheme = { 114 B_TRANSLATE("Custom") 115 }; 116 117 const color_scheme* gPredefinedColorSchemes[] = { 118 &kColorSchemeDefault, 119 &kColorSchemeBlue, 120 &kColorSchemeMidnight, 121 &kColorSchemeProfessional, 122 &kColorSchemeRetro, 123 &kColorSchemeSlate, 124 &kColorSchemeSolarizedDark, 125 &kColorSchemeSolarizedLight, 126 &gCustomColorScheme, 127 NULL 128 }; 129 130 131 bool 132 color_scheme::operator==(const color_scheme& scheme) 133 { 134 return text_fore_color == scheme.text_fore_color 135 && text_back_color == scheme.text_back_color 136 && cursor_fore_color == scheme.cursor_fore_color 137 && cursor_back_color == scheme.cursor_back_color 138 && select_fore_color == scheme.select_fore_color 139 && select_back_color == scheme.select_back_color; 140 } 141 142 // #pragma mark XColorsTable implementation 143 144 XColorsTable gXColorsTable; 145 146 147 XColorsTable::XColorsTable() 148 : 149 fTable(NULL), 150 fCount(0) 151 { 152 } 153 154 155 XColorsTable::~XColorsTable() 156 { 157 // fTable as result of LoadResource call and owned 158 // by BApplication so no need to free it explicitly 159 fTable = NULL; 160 fCount = 0; 161 } 162 163 164 status_t 165 XColorsTable::LookUpColor(const char* name, rgb_color* color) 166 { 167 if (name == NULL || color == NULL) 168 return B_BAD_DATA; 169 170 // first check for 'rgb:xxx/xxx/xxx'-encoded color names 171 const char magic[5] = "rgb:"; 172 if (strncasecmp(name, magic, sizeof(magic) - 1) == 0) { 173 int r = 0, g = 0, b = 0; 174 if (sscanf(&name[4], "%x/%x/%x", &r, &g, &b) == 3) { 175 color->set_to(0xFF & r, 0xFF & g, 0xFF & b); 176 return B_OK; 177 } 178 // else - let the chance lookup in rgb.txt table. Is it reasonable?? 179 } 180 181 // for non-'rgb:xxx/xxx/xxx'-encoded - search the X11 rgb table 182 if (fTable == NULL) { 183 status_t result = _LoadXColorsTable(); 184 if (result != B_OK) 185 return result; 186 } 187 188 // use binary search to lookup color name hash in table 189 int left = -1; 190 int right = fCount; 191 uint32 hash = _HashName(name); 192 while ((right - left) > 1) { 193 int i = (left + right) / 2; 194 ((fTable[i].hash < hash) ? left : right) = i; 195 } 196 197 if (fTable[right].hash == hash) { 198 memcpy(color, &fTable[right].color, sizeof(rgb_color)); 199 return B_OK; 200 } 201 202 return B_NAME_NOT_FOUND; 203 } 204 205 206 status_t 207 XColorsTable::_LoadXColorsTable() 208 { 209 BResources* res = BApplication::AppResources(); 210 if (res == NULL) 211 return B_ERROR; 212 213 size_t size = 0; 214 fTable = (_XColorEntry*)res->LoadResource(B_RAW_TYPE, "XColorsTable", &size); 215 if (fTable == NULL || size < sizeof(_XColorEntry)) { 216 fTable = NULL; 217 return B_ENTRY_NOT_FOUND; 218 } 219 220 fCount = size / sizeof(_XColorEntry); 221 return B_OK; 222 } 223 224 225 uint32 226 XColorsTable::_HashName(const char* name) 227 { 228 uint32 hash = 0; 229 uint32 g = 0; 230 231 // Using modified P.J.Weinberger hash algorithm 232 // Spaces are purged out, characters are upper-cased 233 // 'E' replaced with 'A' (to join 'grey' and 'gray' variations) 234 for (const char* p = name; *p; p++) { 235 int ch = toupper(*p); 236 switch (ch) { 237 case ' ': 238 break; 239 case 'E': 240 ch = 'A'; 241 default: 242 hash = (hash << 4) + (ch & 0xFF); 243 g = hash & 0xf0000000; 244 if (g != 0) { 245 hash ^= g >> 24; 246 hash ^= g; 247 } 248 break; 249 } 250 } 251 252 return hash; 253 } 254