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