|
Atrinik Client 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00030 #include <global.h> 00031 00033 static const char *const opt_types[OPT_TYPE_NUM] = 00034 { 00035 "bool", "input_num", "input_text", "range", "select", "int" 00036 }; 00037 00039 setting_category **setting_categories = NULL; 00041 size_t setting_categories_num = 0; 00045 static uint8 setting_update_mapsize = 0; 00046 00051 static void setting_load_value(setting_struct *setting, const char *str) 00052 { 00053 switch (setting->type) 00054 { 00055 case OPT_TYPE_BOOL: 00056 if (KEYWORD_IS_TRUE(str)) 00057 { 00058 setting->val.i = 1; 00059 } 00060 else if (KEYWORD_IS_FALSE(str)) 00061 { 00062 setting->val.i = 0; 00063 } 00064 else 00065 { 00066 setting->val.i = atoi(str); 00067 } 00068 00069 break; 00070 00071 case OPT_TYPE_INPUT_NUM: 00072 case OPT_TYPE_RANGE: 00073 case OPT_TYPE_INT: 00074 case OPT_TYPE_SELECT: 00075 setting->val.i = atoi(str); 00076 break; 00077 00078 case OPT_TYPE_INPUT_TEXT: 00079 if (setting->val.str) 00080 { 00081 free(setting->val.str); 00082 } 00083 00084 setting->val.str = strdup(str); 00085 break; 00086 } 00087 } 00088 00091 void settings_init() 00092 { 00093 FILE *fp; 00094 char buf[HUGE_BUF], *cp; 00095 setting_category *category; 00096 setting_struct *setting; 00097 00098 fp = fopen_wrapper(FILE_SETTINGS_TXT, "r"); 00099 00100 if (!fp) 00101 { 00102 LOG(llevError, "settings_init(): Missing "FILE_SETTINGS_TXT", cannot continue.\n"); 00103 } 00104 00105 category = NULL; 00106 setting = NULL; 00107 setting_categories = NULL; 00108 setting_categories_num = 0; 00109 00110 while (fgets(buf, sizeof(buf) - 1, fp)) 00111 { 00112 cp = strchr(buf, '\n'); 00113 00114 if (cp) 00115 { 00116 *cp = '\0'; 00117 } 00118 00119 cp = buf; 00120 00121 while (*cp != '\0') 00122 { 00123 if (isspace(*cp)) 00124 { 00125 cp++; 00126 } 00127 else 00128 { 00129 break; 00130 } 00131 } 00132 00133 if (*cp == '#' || *cp == '\0') 00134 { 00135 continue; 00136 } 00137 00138 if (!strcmp(cp, "end")) 00139 { 00140 if (setting) 00141 { 00142 category->settings = realloc(category->settings, sizeof(category->settings) * (category->settings_num + 1)); 00143 category->settings[category->settings_num] = setting; 00144 category->settings_num++; 00145 setting = NULL; 00146 } 00147 else if (category) 00148 { 00149 setting_categories = realloc(setting_categories, sizeof(*setting_categories) * (setting_categories_num + 1)); 00150 setting_categories[setting_categories_num] = category; 00151 setting_categories_num++; 00152 category = NULL; 00153 } 00154 } 00155 else if (setting) 00156 { 00157 if (!strncmp(cp, "type ", 5)) 00158 { 00159 size_t type_id; 00160 00161 for (type_id = 0; type_id < OPT_TYPE_NUM; type_id++) 00162 { 00163 if (!strcmp(cp + 5, opt_types[type_id])) 00164 { 00165 setting->type = type_id; 00166 break; 00167 } 00168 } 00169 00170 if (type_id == OPT_TYPE_NUM) 00171 { 00172 LOG(llevError, "Invalid type: %s\n", cp + 5); 00173 } 00174 else if (type_id == OPT_TYPE_SELECT) 00175 { 00176 setting->custom_attrset = calloc(1, sizeof(setting_select)); 00177 } 00178 else if (type_id == OPT_TYPE_RANGE) 00179 { 00180 setting->custom_attrset = calloc(1, sizeof(setting_range)); 00181 } 00182 } 00183 else if (!strncmp(cp, "default ", 8)) 00184 { 00185 setting_load_value(setting, cp + 8); 00186 } 00187 else if (!strncmp(cp, "desc ", 5)) 00188 { 00189 setting->desc = strdup(cp + 5); 00190 convert_newline(setting->desc); 00191 } 00192 else if (!strncmp(cp, "internal ", 9)) 00193 { 00194 setting->internal = KEYWORD_IS_TRUE(cp + 9) ? 1 : 0; 00195 } 00196 else if (setting->type == OPT_TYPE_SELECT && !strncmp(cp, "option ", 7)) 00197 { 00198 setting_select *s_select = SETTING_SELECT(setting); 00199 00200 s_select->options = realloc(s_select->options, sizeof(*s_select->options) * (s_select->options_len + 1)); 00201 s_select->options[s_select->options_len] = strdup(cp + 7); 00202 s_select->options_len++; 00203 } 00204 else if (setting->type == OPT_TYPE_RANGE && !strncmp(cp, "range ", 6)) 00205 { 00206 setting_range *range = SETTING_RANGE(setting); 00207 sint64 min, max; 00208 00209 if (sscanf(cp + 6, "%"FMT64" - %"FMT64, &min, &max) == 2) 00210 { 00211 range->min = min; 00212 range->max = max; 00213 } 00214 else 00215 { 00216 LOG(llevBug, "settings_init(): Invalid line: %s\n", cp); 00217 } 00218 } 00219 else if (setting->type == OPT_TYPE_RANGE && !strncmp(cp, "advance ", 8)) 00220 { 00221 SETTING_RANGE(setting)->advance = atoi(cp + 8); 00222 } 00223 else 00224 { 00225 LOG(llevBug, "settings_init(): Invalid line: %s\n", cp); 00226 } 00227 } 00228 else if (category) 00229 { 00230 if (!strncmp(cp, "setting ", 8)) 00231 { 00232 setting = calloc(1, sizeof(*setting)); 00233 setting->name = strdup(cp + 8); 00234 } 00235 else 00236 { 00237 LOG(llevBug, "settings_init(): Invalid line: %s\n", cp); 00238 } 00239 } 00240 else if (!strncmp(cp, "category ", 9)) 00241 { 00242 category = calloc(1, sizeof(*category)); 00243 category->name = strdup(cp + 9); 00244 } 00245 } 00246 00247 fclose(fp); 00248 00249 /* Now load the user's settings (if any). */ 00250 settings_load(); 00251 } 00252 00255 void settings_load() 00256 { 00257 FILE *fp; 00258 char buf[HUGE_BUF], *cp; 00259 size_t cat = 0, setting = 0; 00260 uint8 is_setting_name = 1; 00261 00262 fp = fopen_wrapper(FILE_SETTINGS_DAT, "r"); 00263 00264 /* No user settings yet. */ 00265 if (!fp) 00266 { 00267 return; 00268 } 00269 00270 while (fgets(buf, sizeof(buf) - 1, fp)) 00271 { 00272 cp = strchr(buf, '\n'); 00273 00274 if (cp) 00275 { 00276 *cp = '\0'; 00277 } 00278 00279 cp = buf; 00280 00281 while (*cp != '\0') 00282 { 00283 if (isspace(*cp)) 00284 { 00285 cp++; 00286 } 00287 else 00288 { 00289 break; 00290 } 00291 } 00292 00293 if (*cp == '#' || *cp == '\0') 00294 { 00295 continue; 00296 } 00297 00298 if (!strncmp(cp, "category ", 9)) 00299 { 00300 cat = category_from_name(cp + 9); 00301 } 00302 else 00303 { 00304 if (is_setting_name) 00305 { 00306 setting = setting_from_name(cp); 00307 } 00308 else 00309 { 00310 setting_load_value(setting_categories[cat]->settings[setting], cp); 00311 } 00312 00313 is_setting_name = !is_setting_name; 00314 } 00315 } 00316 00317 fclose(fp); 00318 } 00319 00322 void settings_save() 00323 { 00324 FILE *fp; 00325 size_t cat, set; 00326 setting_struct *setting; 00327 00328 fp = fopen_wrapper(FILE_SETTINGS_DAT, "w"); 00329 00330 if (!fp) 00331 { 00332 LOG(llevBug, "Could not open settings file ("FILE_SETTINGS_DAT").\n"); 00333 return; 00334 } 00335 00336 for (cat = 0; cat < setting_categories_num; cat++) 00337 { 00338 fprintf(fp, "category %s\n", setting_categories[cat]->name); 00339 00340 for (set = 0; set < setting_categories[cat]->settings_num; set++) 00341 { 00342 setting = setting_categories[cat]->settings[set]; 00343 00344 fprintf(fp, "%s\n", setting->name); 00345 00346 if (setting_is_text(setting)) 00347 { 00348 fprintf(fp, "%s\n", setting->val.str); 00349 } 00350 else 00351 { 00352 fprintf(fp, "%"FMT64"\n", setting->val.i); 00353 } 00354 } 00355 } 00356 00357 fclose(fp); 00358 } 00359 00364 void settings_deinit() 00365 { 00366 size_t cat, setting; 00367 00368 /* Save the user's settings first. */ 00369 settings_save(); 00370 00371 /* Start deinitializing. */ 00372 for (cat = 0; cat < setting_categories_num; cat++) 00373 { 00374 for (setting = 0; setting < setting_categories[cat]->settings_num; setting++) 00375 { 00376 if (setting_is_text(setting_categories[cat]->settings[setting])) 00377 { 00378 free(setting_categories[cat]->settings[setting]->val.str); 00379 } 00380 00381 free(setting_categories[cat]->settings[setting]->name); 00382 00383 if (setting_categories[cat]->settings[setting]->desc) 00384 { 00385 free(setting_categories[cat]->settings[setting]->desc); 00386 } 00387 00388 if (setting_categories[cat]->settings[setting]->type == OPT_TYPE_SELECT) 00389 { 00390 setting_select *s_select = SETTING_SELECT(setting_categories[cat]->settings[setting]); 00391 size_t option; 00392 00393 for (option = 0; option < s_select->options_len; option++) 00394 { 00395 free(s_select->options[option]); 00396 } 00397 00398 if (s_select->options) 00399 { 00400 free(s_select->options); 00401 } 00402 } 00403 00404 if (setting_categories[cat]->settings[setting]->custom_attrset) 00405 { 00406 free(setting_categories[cat]->settings[setting]->custom_attrset); 00407 } 00408 } 00409 00410 if (setting_categories[cat]->settings) 00411 { 00412 free(setting_categories[cat]->settings); 00413 } 00414 00415 free(setting_categories[cat]->name); 00416 free(setting_categories[cat]); 00417 } 00418 00419 if (setting_categories) 00420 { 00421 free(setting_categories); 00422 setting_categories = NULL; 00423 } 00424 00425 setting_categories_num = 0; 00426 } 00427 00432 void *setting_get(setting_struct *setting) 00433 { 00434 switch (setting->type) 00435 { 00436 case OPT_TYPE_BOOL: 00437 case OPT_TYPE_INPUT_NUM: 00438 case OPT_TYPE_RANGE: 00439 case OPT_TYPE_INT: 00440 case OPT_TYPE_SELECT: 00441 return &setting->val.i; 00442 00443 case OPT_TYPE_INPUT_TEXT: 00444 return setting->val.str; 00445 } 00446 00447 return NULL; 00448 } 00449 00455 const char *setting_get_str(int cat, int setting) 00456 { 00457 return (const char *) setting_get(setting_categories[cat]->settings[setting]); 00458 } 00459 00465 sint64 setting_get_int(int cat, int setting) 00466 { 00467 return *(sint64 *) setting_get(setting_categories[cat]->settings[setting]); 00468 } 00469 00476 static int setting_apply_always(int cat, int setting) 00477 { 00478 switch (cat) 00479 { 00480 case OPT_CAT_GENERAL: 00481 switch (setting) 00482 { 00483 /* Need to hide/show the playerdoll widget. */ 00484 case OPT_PLAYERDOLL: 00485 cur_widget[PDOLL_ID]->show = setting_get_int(cat, setting); 00486 return 1; 00487 } 00488 00489 break; 00490 00491 case OPT_CAT_DEVEL: 00492 switch (setting) 00493 { 00494 /* Need to hide/show the fps widget. */ 00495 case OPT_SHOW_FPS: 00496 cur_widget[FPS_ID]->show = setting_get_int(cat, setting); 00497 return 1; 00498 } 00499 } 00500 00501 return 0; 00502 } 00503 00508 static void setting_apply_runtime(int cat, int setting) 00509 { 00510 /* Try both run-time and startup-time changes first. */ 00511 if (setting_apply_always(cat, setting)) 00512 { 00513 return; 00514 } 00515 00516 switch (cat) 00517 { 00518 case OPT_CAT_GENERAL: 00519 switch (setting) 00520 { 00521 /* Changed how exp display shows its data, redraw the 00522 * widget. */ 00523 case OPT_EXP_DISPLAY: 00524 WIDGET_REDRAW_ALL(SKILL_EXP_ID); 00525 break; 00526 } 00527 00528 break; 00529 00530 case OPT_CAT_CLIENT: 00531 switch (setting) 00532 { 00533 /* Resolution change. */ 00534 case OPT_RESOLUTION: 00535 { 00536 int w, h; 00537 00538 if (sscanf(SETTING_SELECT(setting_categories[cat]->settings[setting])->options[setting_get_int(cat, setting)], "%dx%d", &w, &h) == 2 && (ScreenSurface->w != w || ScreenSurface->h != h)) 00539 { 00540 resize_window(w, h); 00541 video_set_size(); 00542 } 00543 00544 break; 00545 } 00546 00547 /* Fullscreen change. */ 00548 case OPT_FULLSCREEN: 00549 if ((setting_get_int(cat, setting) && !(ScreenSurface->flags & SDL_FULLSCREEN)) || (!setting_get_int(cat, setting) && ScreenSurface->flags & SDL_FULLSCREEN)) 00550 { 00551 video_fullscreen_toggle(&ScreenSurface, NULL); 00552 } 00553 00554 break; 00555 } 00556 00557 break; 00558 00559 case OPT_CAT_MAP: 00560 switch (setting) 00561 { 00562 /* Map width/height change. */ 00563 case OPT_MAP_WIDTH: 00564 case OPT_MAP_HEIGHT: 00565 if (setting_update_mapsize) 00566 { 00567 char buf[MAX_BUF]; 00568 00569 snprintf(buf, sizeof(buf), "setup mapsize %"FMT64"x%"FMT64, setting_get_int(cat, OPT_MAP_WIDTH), setting_get_int(cat, OPT_MAP_HEIGHT)); 00570 cs_write_string(buf, strlen(buf)); 00571 setting_update_mapsize = 0; 00572 } 00573 00574 break; 00575 } 00576 00577 break; 00578 00579 case OPT_CAT_SOUND: 00580 switch (setting) 00581 { 00582 /* Music volume change. */ 00583 case OPT_VOLUME_MUSIC: 00584 sound_update_volume(); 00585 break; 00586 } 00587 00588 break; 00589 } 00590 } 00591 00595 void settings_apply() 00596 { 00597 size_t i, j; 00598 00599 for (i = 0; i < setting_categories_num; i++) 00600 { 00601 for (j = 0; j < setting_categories[i]->settings_num; j++) 00602 { 00603 setting_apply_always(i, j); 00604 } 00605 } 00606 } 00607 00611 void settings_apply_change() 00612 { 00613 size_t cat, setting; 00614 00615 for (cat = 0; cat < setting_categories_num; cat++) 00616 { 00617 for (setting = 0; setting < setting_categories[cat]->settings_num; setting++) 00618 { 00619 setting_apply_runtime(cat, setting); 00620 } 00621 } 00622 } 00623 00629 void setting_set_int(int cat, int setting, sint64 val) 00630 { 00631 void *dst = setting_get(setting_categories[cat]->settings[setting]); 00632 00633 (*(sint64 *) dst) = val; 00634 00635 /* Map width/height, mark for update. */ 00636 if (cat == OPT_CAT_MAP && (setting == OPT_MAP_WIDTH || setting == OPT_MAP_HEIGHT)) 00637 { 00638 setting_update_mapsize = 1; 00639 } 00640 } 00641 00646 int setting_is_text(setting_struct *setting) 00647 { 00648 switch (setting->type) 00649 { 00650 case OPT_TYPE_INPUT_TEXT: 00651 return 1; 00652 } 00653 00654 return 0; 00655 } 00656 00661 sint64 category_from_name(const char *name) 00662 { 00663 size_t cat; 00664 00665 for (cat = 0; cat < setting_categories_num; cat++) 00666 { 00667 if (!strcmp(setting_categories[cat]->name, name)) 00668 { 00669 return cat; 00670 } 00671 } 00672 00673 return -1; 00674 } 00675 00682 sint64 setting_from_name(const char *name) 00683 { 00684 size_t cat, setting; 00685 00686 for (cat = 0; cat < setting_categories_num; cat++) 00687 { 00688 for (setting = 0; setting < setting_categories[cat]->settings_num; setting++) 00689 { 00690 if (!strcmp(setting_categories[cat]->settings[setting]->name, name)) 00691 { 00692 return setting; 00693 } 00694 } 00695 } 00696 00697 return -1; 00698 }
1.7.4