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