xref: /haiku/src/apps/terminal/Colors.cpp (revision f2df0cfe93a902842f6f4629ff614f5b3f9bf687)
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