btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / apps / terminal / PrefHandler.cpp
blob99bf741ede7c87735c7d82f10e00adfe5cd6496b
1 /*
2 * Copyright 2003-2015, 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.
7 * Distributed unter the terms of the MIT License.
9 * Authors:
10 * Kian Duffy, myob@users.sourceforge.net
11 * Daniel Furrer, assimil8or@users.sourceforge.net
12 * Siarzhuk Zharski, zharik@gmx.li
16 #include "PrefHandler.h"
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
23 #include <Catalog.h>
24 #include <Directory.h>
25 #include <Entry.h>
26 #include <File.h>
27 #include <FindDirectory.h>
28 #include <Font.h>
29 #include <GraphicsDefs.h>
30 #include <Locale.h>
31 #include <Message.h>
32 #include <NodeInfo.h>
33 #include <Path.h>
35 #include "Globals.h"
36 #include "TermConst.h"
38 #include <iostream>
41 * Startup preference settings.
43 static const pref_defaults kTermDefaults[] = {
44 { PREF_COLS, "80" },
45 { PREF_ROWS, "25" },
47 // No need for PREF_HALF_FONT_FAMILY/_STYLE defaults here,
48 // these entries will be filled with corresponding params
49 // of the current system fixed font if they are not
50 // available in the settings file
52 { PREF_HALF_FONT_SIZE, "12" },
54 { PREF_TEXT_FORE_COLOR, " 0, 0, 0" },
55 { PREF_TEXT_BACK_COLOR, "255, 255, 255" },
56 { PREF_CURSOR_FORE_COLOR, "255, 255, 255" },
57 { PREF_CURSOR_BACK_COLOR, " 0, 0, 0" },
58 { PREF_SELECT_FORE_COLOR, "255, 255, 255" },
59 { PREF_SELECT_BACK_COLOR, " 0, 0, 0" },
61 { PREF_IM_FORE_COLOR, " 0, 0, 0" },
62 { PREF_IM_BACK_COLOR, "152, 203, 255" },
63 { PREF_IM_SELECT_COLOR, "255, 152, 152" },
65 { PREF_ANSI_BLACK_COLOR, " 40, 40, 40" },
66 { PREF_ANSI_RED_COLOR, "204, 0, 0" },
67 { PREF_ANSI_GREEN_COLOR, " 78, 154, 6" },
68 { PREF_ANSI_YELLOW_COLOR, "218, 168, 0" },
69 { PREF_ANSI_BLUE_COLOR, " 51, 102, 152" },
70 { PREF_ANSI_MAGENTA_COLOR, "115, 68, 123" },
71 { PREF_ANSI_CYAN_COLOR, " 6, 152, 154" },
72 { PREF_ANSI_WHITE_COLOR, "245, 245, 245" },
74 { PREF_ANSI_BLACK_HCOLOR, "128, 128, 128" },
75 { PREF_ANSI_RED_HCOLOR, "255, 0, 0" },
76 { PREF_ANSI_GREEN_HCOLOR, " 0, 255, 0" },
77 { PREF_ANSI_YELLOW_HCOLOR, "255, 255, 0" },
78 { PREF_ANSI_BLUE_HCOLOR, " 0, 0, 255" },
79 { PREF_ANSI_MAGENTA_HCOLOR, "255, 0, 255" },
80 { PREF_ANSI_CYAN_HCOLOR, " 0, 255, 255" },
81 { PREF_ANSI_WHITE_HCOLOR, "255, 255, 255" },
83 { PREF_HISTORY_SIZE, "10000" },
85 { PREF_TEXT_ENCODING, "UTF-8" },
87 { PREF_IM_AWARE, "0"},
89 { PREF_TAB_TITLE, "%1d: %p%e" },
90 { PREF_WINDOW_TITLE, "%T% i: %t" },
91 { PREF_BLINK_CURSOR, PREF_TRUE },
92 { PREF_WARN_ON_EXIT, PREF_TRUE },
93 { PREF_CURSOR_STYLE, PREF_BLOCK_CURSOR },
94 { PREF_EMULATE_BOLD, PREF_FALSE },
96 { NULL, NULL},
100 PrefHandler *PrefHandler::sPrefHandler = NULL;
103 PrefHandler::PrefHandler(bool loadSettings)
105 fContainer('Pref')
107 _LoadFromDefault(kTermDefaults);
109 if (loadSettings) {
110 BPath path;
111 GetDefaultPath(path);
112 OpenText(path.Path());
115 // TODO: If no fixed font is available, be_fixed_font
116 // points to a proportional font.
117 if (IsFontUsable(be_fixed_font))
118 _ConfirmFont(be_fixed_font);
119 else {
120 int32 numFamilies = count_font_families();
121 for (int32 i = 0; i < numFamilies; i++) {
122 font_family family;
123 uint32 flags;
124 if (get_font_family(i, &family, &flags) == B_OK) {
125 font_style style;
126 int32 numStyles = count_font_styles(family);
127 for (int32 j = 0; j < numStyles; j++) {
128 if (get_font_style(family, j, &style) == B_OK) {
129 BFont fallBackFont;
130 fallBackFont.SetFamilyAndStyle(family, style);
131 if (IsFontUsable(fallBackFont)) {
132 _ConfirmFont(&fallBackFont);
133 return;
143 PrefHandler::PrefHandler(const PrefHandler* p)
145 fContainer = p->fContainer;
149 PrefHandler::~PrefHandler()
154 /* static */
155 PrefHandler *
156 PrefHandler::Default()
158 if (sPrefHandler == NULL)
159 sPrefHandler = new PrefHandler();
160 return sPrefHandler;
164 /* static */
165 void
166 PrefHandler::DeleteDefault()
168 delete sPrefHandler;
169 sPrefHandler = NULL;
173 /* static */
174 void
175 PrefHandler::SetDefault(PrefHandler *prefHandler)
177 DeleteDefault();
178 sPrefHandler = prefHandler;
182 /* static */
183 status_t
184 PrefHandler::GetDefaultPath(BPath& path)
186 status_t status;
187 status = find_directory(B_USER_SETTINGS_DIRECTORY, &path, true);
188 if (status != B_OK)
189 return status;
191 status = path.Append("Terminal");
192 if (status != B_OK)
193 return status;
195 // Just create the directory. Harmless if already there
196 status = create_directory(path.Path(), 0755);
197 if (status != B_OK)
198 return status;
200 return path.Append("Default");
204 status_t
205 PrefHandler::OpenText(const char *path)
207 return _LoadFromTextFile(path);
211 void
212 PrefHandler::SaveDefaultAsText()
214 BPath path;
215 if (GetDefaultPath(path) == B_OK)
216 SaveAsText(path.Path(), PREFFILE_MIMETYPE);
220 void
221 PrefHandler::SaveAsText(const char *path, const char *mimetype,
222 const char *signature)
224 // make sure the target path exists
225 #if 0
226 BPath directoryPath(path);
227 if (directoryPath.GetParent(&directoryPath) == B_OK)
228 create_directory(directoryPath.Path(), 0755);
229 #endif
231 BFile file(path, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
232 char buffer[512];
233 type_code type;
234 const char *key;
236 for (int32 i = 0;
237 #ifdef B_BEOS_VERSION_DANO
238 fContainer.GetInfo(B_STRING_TYPE, i, &key, &type) == B_OK;
239 #else
240 fContainer.GetInfo(B_STRING_TYPE, i, (char**)&key, &type) == B_OK;
241 #endif
242 i++) {
243 int len = snprintf(buffer, sizeof(buffer), "\"%s\" , \"%s\"\n",
244 key, getString(key));
245 file.Write(buffer, len);
248 if (mimetype != NULL) {
249 BNodeInfo info(&file);
250 info.SetType(mimetype);
251 info.SetPreferredApp(signature);
256 int32
257 PrefHandler::getInt32(const char *key)
259 const char *value = fContainer.FindString(key);
260 if (value == NULL)
261 return 0;
263 return atoi(value);
267 float
268 PrefHandler::getFloat(const char *key)
270 const char *value = fContainer.FindString(key);
271 if (value == NULL)
272 return 0;
274 return atof(value);
278 #undef B_TRANSLATION_CONTEXT
279 #define B_TRANSLATION_CONTEXT "Terminal getString"
281 const char*
282 PrefHandler::getString(const char *key)
284 const char *buffer;
285 if (fContainer.FindString(key, &buffer) != B_OK)
286 buffer = B_TRANSLATE("Error!");
288 //printf("%x GET %s: %s\n", this, key, buf);
289 return buffer;
293 bool
294 PrefHandler::getBool(const char *key)
296 const char *value = fContainer.FindString(key);
297 if (value == NULL)
298 return false;
300 return strcmp(value, PREF_TRUE) == 0;
305 PrefHandler::getCursor(const char *key)
307 const char *value = fContainer.FindString(key);
308 if (value != NULL && strcmp(value, PREF_BLOCK_CURSOR) != 0) {
309 if (strcmp(value, PREF_UNDERLINE_CURSOR) == 0)
310 return UNDERLINE_CURSOR;
311 if (strcmp(value, PREF_IBEAM_CURSOR) == 0)
312 return IBEAM_CURSOR;
314 return BLOCK_CURSOR;
318 #undef B_TRANSLATION_CONTEXT
319 #define B_TRANSLATION_CONTEXT "Terminal getRGB"
321 /** Returns RGB data from given key. */
323 rgb_color
324 PrefHandler::getRGB(const char *key)
326 rgb_color col;
327 int r, g, b;
329 if (const char *s = fContainer.FindString(key)) {
330 sscanf(s, "%d, %d, %d", &r, &g, &b);
331 } else {
332 fprintf(stderr,
333 "PrefHandler::getRGB(%s) - key not found\n", key);
334 r = g = b = 0;
337 col.red = r;
338 col.green = g;
339 col.blue = b;
340 col.alpha = 255;
341 return col;
345 /** Setting Int32 data with key. */
347 void
348 PrefHandler::setInt32(const char *key, int32 data)
350 char buffer[32];
351 snprintf(buffer, sizeof(buffer), "%d", (int)data);
352 setString(key, buffer);
356 /** Setting Float data with key */
358 void
359 PrefHandler::setFloat(const char *key, float data)
361 char buffer[32];
362 snprintf(buffer, sizeof(buffer), "%g", data);
363 setString(key, buffer);
367 /** Setting Bool data with key */
369 void
370 PrefHandler::setBool(const char *key, bool data)
372 if (data)
373 setString(key, PREF_TRUE);
374 else
375 setString(key, PREF_FALSE);
379 /** Setting CString data with key */
381 void
382 PrefHandler::setString(const char *key, const char *data)
384 //printf("%x SET %s: %s\n", this, key, data);
385 fContainer.RemoveName(key);
386 fContainer.AddString(key, data);
390 /** Setting RGB data with key */
392 void
393 PrefHandler::setRGB(const char *key, const rgb_color data)
395 char buffer[32];
396 snprintf(buffer, sizeof(buffer), "%d, %d, %d", data.red, data.green, data.blue);
397 setString(key, buffer);
401 /** Check any peference stored or not. */
403 bool
404 PrefHandler::IsEmpty() const
406 return fContainer.IsEmpty();
410 void
411 PrefHandler::_ConfirmFont(const BFont *fallbackFont)
413 font_family family;
414 font_style style;
416 const char *prefFamily = getString(PREF_HALF_FONT_FAMILY);
417 int32 familiesCount = (prefFamily != NULL) ? count_font_families() : 0;
419 for (int32 i = 0; i < familiesCount; i++) {
420 if (get_font_family(i, &family) != B_OK
421 || strcmp(family, prefFamily) != 0)
422 continue;
424 const char *prefStyle = getString(PREF_HALF_FONT_STYLE);
425 int32 stylesCount = (prefStyle != NULL) ? count_font_styles(family) : 0;
427 for (int32 j = 0; j < stylesCount; j++) {
428 // check style if we can safely use this font
429 if (get_font_style(family, j, &style) == B_OK
430 && strcmp(style, prefStyle) == 0)
431 return;
435 // use fall-back font
436 fallbackFont->GetFamilyAndStyle(&family, &style);
437 setString(PREF_HALF_FONT_FAMILY, family);
438 setString(PREF_HALF_FONT_STYLE, style);
442 status_t
443 PrefHandler::_LoadFromDefault(const pref_defaults* defaults)
445 if (defaults == NULL)
446 return B_ERROR;
448 while (defaults->key) {
449 setString(defaults->key, defaults->item);
450 ++defaults;
453 return B_OK;
457 /** Text is "key","Content"
458 * Comment : Start with '#'
461 status_t
462 PrefHandler::_LoadFromTextFile(const char * path)
464 char buffer[1024];
465 char key[B_FIELD_NAME_LENGTH], data[512];
466 int n;
467 FILE *file;
469 file = fopen(path, "r");
470 if (file == NULL)
471 return B_ENTRY_NOT_FOUND;
473 while (fgets(buffer, sizeof(buffer), file) != NULL) {
474 if (*buffer == '#')
475 continue;
477 n = sscanf(buffer, "%*[\"]%[^\"]%*[\"]%*[^\"]%*[\"]%[^\"]", key, data);
478 if (n == 2)
479 setString(key, data);
482 fclose(file);
483 return B_OK;