xref: /haiku/src/apps/terminal/PrefHandler.cpp (revision 85fb3e7df81f8d5b6e47a9a64a53873ea906ea6e)
1 /*
2  * Copyright 2003-2007, Haiku, Inc. All Rights Reserved.
3  * Copyright (c) 2004 Daniel Furrer <assimil8or@users.sourceforge.net>
4  * Copyright (c) 2003-4 Kian Duffy <myob@users.sourceforge.net>
5  * Copyright (c) 1998,99 Kazuho Okui and Takashi Murai.
6  *
7  * Distributed unter the terms of the MIT License.
8  */
9 
10 
11 #include "PrefHandler.h"
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <unistd.h>
17 
18 #include <Catalog.h>
19 #include <Directory.h>
20 #include <Entry.h>
21 #include <File.h>
22 #include <FindDirectory.h>
23 #include <Font.h>
24 #include <GraphicsDefs.h>
25 #include <Locale.h>
26 #include <Message.h>
27 #include <NodeInfo.h>
28 #include <Path.h>
29 
30 #include "PrefHandler.h"
31 #include "TermConst.h"
32 
33 
34 /*
35  * Startup preference settings.
36  */
37 static const pref_defaults kTermDefaults[] = {
38 	{ PREF_COLS,				"80" },
39 	{ PREF_ROWS,				"25" },
40 
41 	{ PREF_HALF_FONT_FAMILY,	"Courier10 BT" },
42 	{ PREF_HALF_FONT_STYLE,		"Regular" },
43 	{ PREF_HALF_FONT_SIZE,		"12" },
44 
45 	{ PREF_TEXT_FORE_COLOR,		"  0,   0,   0" },
46 	{ PREF_TEXT_BACK_COLOR,		"255, 255, 255" },
47 	{ PREF_SELECT_FORE_COLOR,	"255, 255, 255" },
48 	{ PREF_SELECT_BACK_COLOR,	"  0,   0,   0" },
49 
50 	{ PREF_IM_FORE_COLOR,		"  0,   0,   0" },
51 	{ PREF_IM_BACK_COLOR,		"152, 203, 255" },
52 	{ PREF_IM_SELECT_COLOR,		"255, 152, 152" },
53 
54 	{ PREF_SHELL,				"/bin/sh -login" },
55 	{ PREF_HISTORY_SIZE,		"10000" },
56 
57 	{ PREF_TEXT_ENCODING,		"UTF-8" },
58 
59 	{ PREF_GUI_LANGUAGE,		"English"},
60 	{ PREF_IM_AWARE,			"0"},
61 
62 	{ PREF_TAB_TITLE,			"%1d: %p" },
63 	{ PREF_WINDOW_TITLE,		"Terminal %i: %t" },
64 	{ PREF_WARN_ON_EXIT,		PREF_TRUE },
65 
66 	{ NULL, NULL},
67 };
68 
69 
70 PrefHandler *PrefHandler::sPrefHandler = NULL;
71 
72 
73 PrefHandler::PrefHandler()
74 	:
75 	fContainer('Pref')
76 {
77 	_LoadFromDefault(kTermDefaults);
78 
79 	BPath path;
80 	GetDefaultPath(path);
81 	OpenText(path.Path());
82 
83 	_ConfirmFont(PREF_HALF_FONT_FAMILY, be_fixed_font);
84 }
85 
86 
87 PrefHandler::PrefHandler(const PrefHandler* p)
88 {
89 	fContainer = p->fContainer;
90 }
91 
92 
93 PrefHandler::~PrefHandler()
94 {
95 }
96 
97 
98 /* static */
99 PrefHandler *
100 PrefHandler::Default()
101 {
102 	if (sPrefHandler == NULL)
103 		sPrefHandler = new PrefHandler();
104 	return sPrefHandler;
105 }
106 
107 
108 /* static */
109 void
110 PrefHandler::DeleteDefault()
111 {
112 	delete sPrefHandler;
113 	sPrefHandler = NULL;
114 }
115 
116 
117 /* static */
118 void
119 PrefHandler::SetDefault(PrefHandler *prefHandler)
120 {
121 	DeleteDefault();
122 	sPrefHandler = prefHandler;
123 }
124 
125 
126 /* static */
127 status_t
128 PrefHandler::GetDefaultPath(BPath& path)
129 {
130 	status_t status;
131 	status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true);
132 	if (status != B_OK)
133 		return status;
134 
135 	status = path.Append("Terminal");
136 	if (status != B_OK)
137 		return status;
138 
139 	// Just create the directory. Harmless if already there
140 	status = create_directory(path.Path(), 0755);
141 	if (status != B_OK)
142 		return status;
143 
144 	return path.Append("Default");
145 }
146 
147 
148 status_t
149 PrefHandler::OpenText(const char *path)
150 {
151 	return _LoadFromTextFile(path);
152 }
153 
154 
155 void
156 PrefHandler::SaveDefaultAsText()
157 {
158 	BPath path;
159 	if (GetDefaultPath(path) == B_OK)
160 		SaveAsText(path.Path(), PREFFILE_MIMETYPE);
161 }
162 
163 
164 void
165 PrefHandler::SaveAsText(const char *path, const char *mimetype,
166 	const char *signature)
167 {
168 	// make sure the target path exists
169 #if 0
170 	BPath directoryPath(path);
171 	if (directoryPath.GetParent(&directoryPath) == B_OK)
172 		create_directory(directoryPath.Path(), 0755);
173 #endif
174 
175 	BFile file(path, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
176 	char buffer[512];
177 	type_code type;
178 	const char *key;
179 
180 	for (int32 i = 0;
181 #ifdef B_BEOS_VERSION_DANO
182 			fContainer.GetInfo(B_STRING_TYPE, i, &key, &type) == B_OK;
183 #else
184 			fContainer.GetInfo(B_STRING_TYPE, i, (char**)&key, &type) == B_OK;
185 #endif
186 			i++) {
187 		int len = snprintf(buffer, sizeof(buffer), "\"%s\" , \"%s\"\n", key, getString(key));
188 		file.Write(buffer, len);
189 	}
190 
191 	if (mimetype != NULL){
192 		BNodeInfo info(&file);
193 		info.SetType(mimetype);
194 		info.SetPreferredApp(signature);
195 	}
196 }
197 
198 
199 int32
200 PrefHandler::getInt32(const char *key)
201 {
202 	const char *value = fContainer.FindString(key);
203 	if (value == NULL)
204 		return 0;
205 
206 	return atoi(value);
207 }
208 
209 
210 float
211 PrefHandler::getFloat(const char *key)
212 {
213 	const char *value = fContainer.FindString(key);
214 	if (value == NULL)
215 		return 0;
216 
217 	return atof(value);
218 }
219 
220 #undef B_TRANSLATION_CONTEXT
221 #define B_TRANSLATION_CONTEXT "Terminal getString"
222 
223 const char*
224 PrefHandler::getString(const char *key)
225 {
226 	const char *buffer;
227 	if (fContainer.FindString(key, &buffer) != B_OK)
228 		buffer = B_TRANSLATE("Error!");
229 
230 	//printf("%x GET %s: %s\n", this, key, buf);
231 	return buffer;
232 }
233 
234 
235 bool
236 PrefHandler::getBool(const char *key)
237 {
238 	const char *value = fContainer.FindString(key);
239 	if (value == NULL)
240 		return false;
241 
242 	return !strcmp(value, PREF_TRUE);
243 }
244 
245 
246 #undef B_TRANSLATION_CONTEXT
247 #define B_TRANSLATION_CONTEXT "Terminal getRGB"
248 
249 /** Returns RGB data from given key. */
250 
251 rgb_color
252 PrefHandler::getRGB(const char *key)
253 {
254 	rgb_color col;
255 	int r, g, b;
256 
257 	if (const char *s = fContainer.FindString(key)) {
258 		sscanf(s, "%d, %d, %d", &r, &g, &b);
259 	} else {
260 		fprintf(stderr,
261 			"PrefHandler::getRGB(%s) - key not found\n", key);
262 		r = g = b = 0;
263 	}
264 
265 	col.red = r;
266 	col.green = g;
267 	col.blue = b;
268 	col.alpha = 255;
269 	return col;
270 }
271 
272 
273 /** Setting Int32 data with key. */
274 
275 void
276 PrefHandler::setInt32(const char *key, int32 data)
277 {
278 	char buffer[32];
279 	snprintf(buffer, sizeof(buffer), "%d", (int)data);
280 	setString(key, buffer);
281 }
282 
283 
284 /** Setting Float data with key */
285 
286 void
287 PrefHandler::setFloat(const char *key, float data)
288 {
289 	char buffer[32];
290 	snprintf(buffer, sizeof(buffer), "%g", data);
291 	setString(key, buffer);
292 }
293 
294 
295 /** Setting Bool data with key */
296 
297 void
298 PrefHandler::setBool(const char *key, bool data)
299 {
300 	if (data)
301 		setString(key, PREF_TRUE);
302 	else
303 		setString(key, PREF_FALSE);
304 }
305 
306 
307 /** Setting CString data with key */
308 
309 void
310 PrefHandler::setString(const char *key, const char *data)
311 {
312 	//printf("%x SET %s: %s\n", this, key, data);
313 	fContainer.RemoveName(key);
314 	fContainer.AddString(key, data);
315 }
316 
317 
318 /** Setting RGB data with key */
319 
320 void
321 PrefHandler::setRGB(const char *key, const rgb_color data)
322 {
323 	char buffer[32];
324 	snprintf(buffer, sizeof(buffer), "%d, %d, %d", data.red, data.green, data.blue);
325 	setString(key, buffer);
326 }
327 
328 
329 /** Check any peference stored or not. */
330 
331 bool
332 PrefHandler::IsEmpty() const
333 {
334 	return fContainer.IsEmpty();
335 }
336 
337 
338 void
339 PrefHandler::_ConfirmFont(const char *key, const BFont *fallback)
340 {
341 	int32 count = count_font_families();
342 	const char *font = getString(key);
343 	if (font == NULL)
344 		count = 0;
345 
346 	font_family family;
347 
348 	for (int32 i = 0; i < count; i++) {
349 		if (get_font_family(i, &family) != B_OK)
350 			continue;
351 
352 		if (!strcmp(family, font)) {
353 			// found font family: we can safely use this font
354 			return;
355 		}
356 	}
357 
358 	// use fall-back font
359 
360 	fallback->GetFamilyAndStyle(&family, NULL);
361 	setString(key, family);
362 }
363 
364 
365 status_t
366 PrefHandler::_LoadFromDefault(const pref_defaults* defaults)
367 {
368 	if (defaults == NULL)
369 		return B_ERROR;
370 
371 	while (defaults->key) {
372 		setString(defaults->key, defaults->item);
373 		++defaults;
374 	}
375 
376 	return B_OK;
377 }
378 
379 
380 /**	Text is "key","Content"
381  *	Comment : Start with '#'
382  */
383 
384 status_t
385 PrefHandler::_LoadFromTextFile(const char * path)
386 {
387 	char buffer[1024];
388 	char key[B_FIELD_NAME_LENGTH], data[512];
389 	int n;
390 	FILE *file;
391 
392 	file = fopen(path, "r");
393 	if (file == NULL)
394 		return B_ENTRY_NOT_FOUND;
395 
396 	while (fgets(buffer, sizeof(buffer), file) != NULL) {
397 		if (*buffer == '#')
398 			continue;
399 
400 		n = sscanf(buffer, "%*[\"]%[^\"]%*[\"]%*[^\"]%*[\"]%[^\"]", key, data);
401 		if (n == 2)
402 			setString(key, data);
403 	}
404 
405 	fclose(file);
406 	return B_OK;
407 }
408