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 "Coding.h" 12 #include "PrefHandler.h" 13 #include "TermConst.h" 14 15 #include <Directory.h> 16 #include <Entry.h> 17 #include <File.h> 18 #include <FindDirectory.h> 19 #include <Font.h> 20 #include <GraphicsDefs.h> 21 #include <Message.h> 22 #include <NodeInfo.h> 23 #include <Path.h> 24 25 #include <stdio.h> 26 #include <unistd.h> 27 #include <stdlib.h> 28 #include <string.h> 29 30 /* 31 * Startup preference settings. 32 */ 33 static const pref_defaults kTermDefaults[] = { 34 { PREF_COLS, "80" }, 35 { PREF_ROWS, "25" }, 36 37 { PREF_HALF_FONT_FAMILY, "Courier10 BT" }, 38 { PREF_HALF_FONT_SIZE, "12" }, 39 { PREF_FULL_FONT_FAMILY, "Haru Tohaba" }, 40 { PREF_FULL_FONT_SIZE, "12" }, 41 42 { PREF_TEXT_FORE_COLOR, " 0, 0, 0" }, 43 { PREF_TEXT_BACK_COLOR, "255, 255, 255" }, 44 { PREF_SELECT_FORE_COLOR, "255, 255, 255" }, 45 { PREF_SELECT_BACK_COLOR, " 0, 0, 0" }, 46 { PREF_CURSOR_FORE_COLOR, "255, 255, 255" }, 47 { PREF_CURSOR_BACK_COLOR, " 0, 0, 0" }, 48 49 { PREF_IM_FORE_COLOR, " 0, 0, 0" }, 50 { PREF_IM_BACK_COLOR, "152, 203, 255" }, 51 { PREF_IM_SELECT_COLOR, "255, 152, 152" }, 52 53 { PREF_SHELL, "/bin/sh -login" }, 54 { PREF_HISTORY_SIZE, "500" }, 55 56 { PREF_TEXT_ENCODING, "UTF-8" }, 57 58 { PREF_MOUSE_IMAGE, "Hand cursor"}, 59 { PREF_DRAGN_COPY, "0"}, 60 61 { PREF_GUI_LANGUAGE, "English"}, 62 { PREF_IM_AWARE, "0"}, 63 { NULL, NULL}, 64 }; 65 66 67 PrefHandler *PrefHandler::sPrefHandler = NULL; 68 69 70 PrefHandler::PrefHandler() 71 : 72 fContainer('Pref') 73 { 74 _LoadFromDefault(kTermDefaults); 75 76 BPath path; 77 GetDefaultPath(path); 78 OpenText(path.Path()); 79 80 _ConfirmFont(PREF_HALF_FONT_FAMILY, be_fixed_font); 81 _ConfirmFont(PREF_FULL_FONT_FAMILY, be_fixed_font); 82 } 83 84 85 PrefHandler::PrefHandler(const PrefHandler* p) 86 { 87 fContainer = p->fContainer; 88 } 89 90 91 PrefHandler::~PrefHandler() 92 { 93 } 94 95 96 /* static */ 97 PrefHandler * 98 PrefHandler::Default() 99 { 100 if (sPrefHandler == NULL) 101 sPrefHandler = new PrefHandler(); 102 return sPrefHandler; 103 } 104 105 106 /* static */ 107 void 108 PrefHandler::DeleteDefault() 109 { 110 delete sPrefHandler; 111 sPrefHandler = NULL; 112 } 113 114 115 /* static */ 116 void 117 PrefHandler::SetDefault(PrefHandler *prefHandler) 118 { 119 DeleteDefault(); 120 sPrefHandler = prefHandler; 121 } 122 123 124 /* static */ 125 status_t 126 PrefHandler::GetDefaultPath(BPath& path) 127 { 128 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path, true) != B_OK) 129 return B_ERROR; 130 131 #ifdef HAIKU_TARGET_PLATFORM_HAIKU 132 path.Append("Terminal_settings"); 133 #else 134 path.Append("HaikuTerminal_settings"); 135 #endif 136 137 return B_OK; 138 } 139 140 141 status_t 142 PrefHandler::Open(const char *path) 143 { 144 return _LoadFromFile(path); 145 } 146 147 148 status_t 149 PrefHandler::OpenText(const char *path) 150 { 151 return _LoadFromTextFile(path); 152 } 153 154 155 status_t 156 PrefHandler::Save(const char *path) 157 { 158 // make sure the target path exists 159 #if 0 160 // TODO: currently not needed as we're reusing the standard directory 161 BPath directoryPath(path); 162 if (directoryPath.GetParent(&directoryPath) == B_OK) 163 create_directory(directoryPath.Path(), 0755); 164 #endif 165 166 BFile file(path, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); 167 return fContainer.Flatten(&file); 168 } 169 170 171 void 172 PrefHandler::SaveAsText(const char *path, const char *mimetype, 173 const char *signature) 174 { 175 // make sure the target path exists 176 #if 0 177 BPath directoryPath(path); 178 if (directoryPath.GetParent(&directoryPath) == B_OK) 179 create_directory(directoryPath.Path(), 0755); 180 #endif 181 182 BFile file(path, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); 183 char buffer[512]; 184 type_code type; 185 const char *key; 186 187 for (int32 i = 0; 188 #ifdef B_BEOS_VERSION_DANO 189 fContainer.GetInfo(B_STRING_TYPE, i, &key, &type) == B_OK; 190 #else 191 fContainer.GetInfo(B_STRING_TYPE, i, (char**)&key, &type) == B_OK; 192 #endif 193 i++) { 194 int len = snprintf(buffer, sizeof(buffer), "\"%s\" , \"%s\"\n", key, getString(key)); 195 file.Write(buffer, len); 196 } 197 198 if (mimetype != NULL){ 199 BNodeInfo info(&file); 200 info.SetType(mimetype); 201 info.SetPreferredApp(signature); 202 } 203 } 204 205 206 int32 207 PrefHandler::getInt32(const char *key) 208 { 209 const char *value = fContainer.FindString(key); 210 if (value == NULL) 211 return 0; 212 213 return atoi(value); 214 } 215 216 217 float 218 PrefHandler::getFloat(const char *key) 219 { 220 const char *value = fContainer.FindString(key); 221 if (value == NULL) 222 return 0; 223 224 return atof(value); 225 } 226 227 228 const char* 229 PrefHandler::getString(const char *key) 230 { 231 const char *buffer; 232 if (fContainer.FindString(key, &buffer) != B_OK) 233 buffer = "Error!"; 234 235 //printf("%x GET %s: %s\n", this, key, buf); 236 return buffer; 237 } 238 239 240 bool 241 PrefHandler::getBool(const char *key) 242 { 243 const char *value = fContainer.FindString(key); 244 if (value == NULL) 245 return false; 246 247 return !strcmp(value, PREF_TRUE); 248 } 249 250 251 /** Returns RGB data from given key. */ 252 253 rgb_color 254 PrefHandler::getRGB(const char *key) 255 { 256 rgb_color col; 257 int r, g, b; 258 259 if (const char *s = fContainer.FindString(key)) { 260 sscanf(s, "%d, %d, %d", &r, &g, &b); 261 } else { 262 fprintf(stderr, "PrefHandler::getRGB(%s) - key not found\n", key); 263 r = g = b = 0; 264 } 265 266 col.red = r; 267 col.green = g; 268 col.blue = b; 269 col.alpha = 255; 270 return col; 271 } 272 273 274 /** Setting Int32 data with key. */ 275 276 void 277 PrefHandler::setInt32(const char *key, int32 data) 278 { 279 char buffer[32]; 280 snprintf(buffer, sizeof(buffer), "%d", (int)data); 281 setString(key, buffer); 282 } 283 284 285 /** Setting Float data with key */ 286 287 void 288 PrefHandler::setFloat(const char *key, float data) 289 { 290 char buffer[32]; 291 snprintf(buffer, sizeof(buffer), "%g", data); 292 setString(key, buffer); 293 } 294 295 296 /** Setting Bool data with key */ 297 298 void 299 PrefHandler::setBool(const char *key, bool data) 300 { 301 if (data) 302 setString(key, PREF_TRUE); 303 else 304 setString(key, PREF_FALSE); 305 } 306 307 308 /** Setting CString data with key */ 309 310 void 311 PrefHandler::setString(const char *key, const char *data) 312 { 313 //printf("%x SET %s: %s\n", this, key, data); 314 fContainer.RemoveName(key); 315 fContainer.AddString(key, data); 316 } 317 318 319 /** Setting RGB data with key */ 320 321 void 322 PrefHandler::setRGB(const char *key, const rgb_color data) 323 { 324 char buffer[32]; 325 snprintf(buffer, sizeof(buffer), "%d, %d, %d", data.red, data.green, data.blue); 326 setString(key, buffer); 327 } 328 329 330 /** Check any peference stored or not. */ 331 332 bool 333 PrefHandler::IsEmpty() const 334 { 335 return fContainer.IsEmpty(); 336 } 337 338 339 void 340 PrefHandler::_ConfirmFont(const char *key, const BFont *fallback) 341 { 342 int32 count = count_font_families(); 343 const char *font = getString(key); 344 if (font == NULL) 345 count = 0; 346 347 font_family family; 348 349 for (int32 i = 0; i < count; i++) { 350 if (get_font_family(i, &family) != B_OK) 351 continue; 352 353 if (!strcmp(family, font)) { 354 // found font family: we can safely use this font 355 return; 356 } 357 } 358 359 // use fall-back font 360 361 fallback->GetFamilyAndStyle(&family, NULL); 362 setString(key, family); 363 } 364 365 366 status_t 367 PrefHandler::_LoadFromFile(const char* path) 368 { 369 // Future: It would be nice if we could simply use a flatened BMessage to 370 // save the settings. (Who cares about compatibility in this case anyway?) 371 372 BFile file(path, B_READ_ONLY); 373 status_t status = file.InitCheck(); 374 if (status != B_OK) 375 return status; 376 377 //fContainer.MakeEmpty(); 378 //fContainer.Unflatten(&file); 379 380 off_t size; 381 if (file.GetSize(&size) != B_OK || size != sizeof(struct termprefs)) 382 return B_ERROR; 383 384 struct termprefs prefs; 385 file.Read(&prefs, size); 386 if (prefs.magic != TP_MAGIC || prefs.version != TP_VERSION) 387 return B_ERROR; 388 389 // Valid settings file! 390 391 setInt32(PREF_COLS, prefs.cols); 392 setInt32(PREF_ROWS, prefs.rows); 393 setInt32(PREF_HALF_FONT_SIZE, prefs.font_size); 394 setInt32(PREF_FULL_FONT_SIZE, prefs.font_size); 395 char *font_family = strtok(prefs.font, "/"); 396 char *font_style = strtok(NULL, ""); 397 setString(PREF_FULL_FONT_FAMILY, font_family); 398 setString(PREF_FULL_FONT_STYLE, font_style); 399 setString(PREF_HALF_FONT_FAMILY, font_family); 400 setString(PREF_HALF_FONT_STYLE, font_style); 401 setRGB(PREF_TEXT_BACK_COLOR, prefs.bg); 402 setRGB(PREF_TEXT_FORE_COLOR, prefs.fg); 403 setRGB(PREF_CURSOR_BACK_COLOR, prefs.curbg); 404 setRGB(PREF_CURSOR_FORE_COLOR, prefs.curfg); 405 setRGB(PREF_SELECT_BACK_COLOR, prefs.selbg); 406 setRGB(PREF_SELECT_FORE_COLOR, prefs.selfg); 407 setString(PREF_TEXT_ENCODING, id2longname(prefs.encoding)); 408 409 return B_OK; 410 } 411 412 413 status_t 414 PrefHandler::_LoadFromDefault(const pref_defaults* defaults) 415 { 416 if (defaults == NULL) 417 return B_ERROR; 418 419 while (defaults->key) { 420 setString(defaults->key, defaults->item); 421 ++defaults; 422 } 423 424 return B_OK; 425 } 426 427 428 /** Text is "key","Content" 429 * Comment : Start with '#' 430 */ 431 432 status_t 433 PrefHandler::_LoadFromTextFile(const char * path) 434 { 435 char buffer[1024]; 436 char key[B_FIELD_NAME_LENGTH], data[512]; 437 int n; 438 FILE *file; 439 440 file = fopen(path, "r"); 441 if (file == NULL) 442 return B_ENTRY_NOT_FOUND; 443 444 while (fgets(buffer, sizeof(buffer), file) != NULL) { 445 if (*buffer == '#') 446 continue; 447 448 n = sscanf(buffer, "%*[\"]%[^\"]%*[\"]%*[^\"]%*[\"]%[^\"]", key, data); 449 if (n == 2) 450 setString(key, data); 451 } 452 453 fclose(file); 454 return B_OK; 455 } 456