Mercurial > hg > index.fcgi > lj > lj046-2players
diff src/old_pc_options.c @ 0:c84446dfb3f5
initial add
author | paulo@localhost |
---|---|
date | Fri, 13 Mar 2009 00:39:12 -0700 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/old_pc_options.c Fri Mar 13 00:39:12 2009 -0700 1.3 @@ -0,0 +1,436 @@ 1.4 +/* PC option screen for LOCKJAW, an implementation of the Soviet Mind Game 1.5 + 1.6 +Copyright (C) 2006 Damian Yerrick <tepples+lj@spamcop.net> 1.7 + 1.8 +This work is free software; you can redistribute it and/or modify 1.9 +it under the terms of the GNU General Public License as published by 1.10 +the Free Software Foundation; either version 2 of the License, or 1.11 +(at your option) any later version. 1.12 + 1.13 +This program is distributed in the hope that it will be useful, 1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.16 +GNU General Public License for more details. 1.17 + 1.18 +You should have received a copy of the GNU General Public License 1.19 +along with this program; if not, write to the Free Software 1.20 +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1.21 + 1.22 +Original game concept and design by Alexey Pajitnov. 1.23 +The Software is not sponsored or endorsed by Alexey Pajitnov, Elorg, 1.24 +or The Tetris Company LLC. 1.25 + 1.26 +*/ 1.27 + 1.28 +#include "ljpc.h" 1.29 +#include <ctype.h> 1.30 +#include "ljpath.h" 1.31 +#include <string.h> 1.32 +#include "options.h" 1.33 +#include "ljlocale.h" 1.34 + 1.35 +#define OPTIONS_OFFSET 0 1.36 +#define optionsMenu (commonOptionsMenu + OPTIONS_OFFSET) 1.37 + 1.38 + 1.39 + 1.40 +#if 0 1.41 +static int getOptionValueByName(int row, const char *value) { 1.42 + for (int x = 0; x < optionsMenu[row].nValues; ++x) { 1.43 + if (!ustrcmp(value, optionsMenu[row].valueNames[x])) { 1.44 + return x + optionsMenu[row].minValue; 1.45 + } 1.46 + } 1.47 + return -1; 1.48 +} 1.49 + 1.50 +static void setOptionValueByNumber(struct LJPrefs *prefs, 1.51 + int row, const char *value) { 1.52 + if (value[0] >= '0' && value[0] <= '9') { 1.53 + int num = atoi(value); 1.54 + if (num >= optionsMenu[row].minValue 1.55 + && num < optionsMenu[row].minValue + optionsMenu[row].nValues) { 1.56 + prefs->number[row] = num; 1.57 + } 1.58 + } 1.59 +} 1.60 + 1.61 +static void setOptionValueByName(struct LJPrefs *prefs, 1.62 + int row, const char *value) { 1.63 + int num = getOptionValueByName(row, value); 1.64 + 1.65 + if (num >= 0) { 1.66 + prefs->number[row] = num; 1.67 + } 1.68 +} 1.69 + 1.70 +static void setOptionValueByBoolean(struct LJPrefs *prefs, 1.71 + int row, const char *value) { 1.72 + int num = atoi(value); 1.73 + 1.74 + if (num >= 0) { 1.75 + prefs->number[row] = num ? 1 : 0; 1.76 + } 1.77 +} 1.78 +#endif 1.79 + 1.80 +/* parse_ini_line ******************* 1.81 +*/ 1.82 +int parse_ini_line(const char *in, char *key, char *var, char *val) 1.83 +{ 1.84 + int c; 1.85 + char *kstart = key; 1.86 + 1.87 + /* Skip whitespace before key */ 1.88 + while(*in && isspace(*in)) 1.89 + in++; 1.90 + 1.91 + /* Parse key */ 1.92 + if(*in == '[') /* if we have a new key, load it */ 1.93 + { 1.94 + in++; 1.95 + 1.96 + /* Skip whitespace before actual key */ 1.97 + while(*in && isspace(*in)) 1.98 + in++; 1.99 + 1.100 + for(c = *in++; 1.101 + c != 0 && c != ']' && c != '\n' && c != '\r'; 1.102 + c = *in++) 1.103 + { 1.104 + if(!isspace(c)) 1.105 + *key++ = c; 1.106 + } 1.107 + *key = 0; 1.108 + /* Strip whitespace after key */ 1.109 + do { 1.110 + *key-- = 0; 1.111 + } while(key >= kstart && isspace(*key)); 1.112 + } 1.113 + 1.114 + /* Skip whitespace before variable */ 1.115 + while(*in && isspace(*in)) 1.116 + in++; 1.117 + if(*in == 0) /* if there is no variable, don't do anything */ 1.118 + return 0; 1.119 + 1.120 + for(c = *in++; 1.121 + c != 0 && c != '=' && c != '\n' && c != '\r'; 1.122 + c = *in++) 1.123 + { 1.124 + if(!isspace(c)) 1.125 + { 1.126 + *var++ = c; 1.127 + } 1.128 + } 1.129 + *var = 0; 1.130 + 1.131 + /* Skip whitespace before value */ 1.132 + while(*in && isspace(*in)) 1.133 + in++; 1.134 + 1.135 + /* Get value */ 1.136 + kstart = val; 1.137 + for(c = *in++; 1.138 + c != 0 && c != '\n' && c != '\r'; 1.139 + c = *in++) 1.140 + { 1.141 + *val++ = c; 1.142 + } 1.143 + /* Strip whitespace after value */ 1.144 + do { 1.145 + *val-- = 0; 1.146 + } while(val >= kstart && isspace(*val)); 1.147 + 1.148 + return 0; 1.149 +} 1.150 + 1.151 +static const char ljIniName[] = "lj.ini"; 1.152 + 1.153 +/** 1.154 + * Finds a FourCC in a list. 1.155 + * @param needle the fourCC to search for 1.156 + * @param haystack a list of fourCCs 1.157 + * @param haystackLen the length of this list 1.158 + * @return the index within haystack where needle was found 1.159 + * or -1 if not found 1.160 + */ 1.161 +int findFourCC(const char *needle, 1.162 + const FourCC *haystack, size_t haystackLen) { 1.163 + for (size_t i = 0; i < haystackLen; ++i) { 1.164 + if (!strncmp(haystack[i].c, needle, 4)) { 1.165 + return i; 1.166 + } 1.167 + } 1.168 + return -1; 1.169 +} 1.170 + 1.171 +void loadOption(struct LJPrefs *prefs, 1.172 + const char *name, const char *value) { 1.173 + for (int i = 0; i < PC_OPTIONS_MENU_LEN; ++i) { 1.174 + if (!strncmp(optionsMenu[i].name.c, name, 4)) { 1.175 + if (isdigit(value[0])) { 1.176 + unsigned long int n = strtoul(value, NULL, 10); 1.177 + if (n >= optionsMenu[i].minValue 1.178 + && n < optionsMenu[i].minValue + optionsMenu[i].nValues) { 1.179 + prefs->number[i] = n; 1.180 + } else { 1.181 + allegro_message("ignoring out of range %s=%lu\n", 1.182 + name, n); 1.183 + } 1.184 + } else if (optionsMenu[i].valueNames) { 1.185 + int nValueNames = (optionsMenu[i].style == OPTSTYLE_FRAMES 1.186 + ? 2 1.187 + : optionsMenu[i].nValues); 1.188 + int foundValue = findFourCC(value, optionsMenu[i].valueNames, nValueNames); 1.189 + if (optionsMenu[i].style == OPTSTYLE_FRAMES 1.190 + && foundValue > 0) { 1.191 + foundValue = optionsMenu[i].nValues - 1; 1.192 + } 1.193 + prefs->number[i] = foundValue + optionsMenu[i].minValue; 1.194 + } 1.195 + return; 1.196 + } 1.197 + } 1.198 +} 1.199 + 1.200 +int loadOptions(struct LJPrefs *prefs) { 1.201 + FILE *fp = ljfopen(ljIniName, "rt"); 1.202 + char key[1024], var[1024], val[1024], input_buf[1024]; 1.203 + 1.204 + if (!fp) return 0; 1.205 + 1.206 + key[0] = 0; 1.207 + var[0] = 0; 1.208 + val[0] = 0; 1.209 + 1.210 + while(fgets (input_buf, sizeof(input_buf), fp)) { 1.211 + parse_ini_line(input_buf, key, var, val); 1.212 + 1.213 + if(!ustrcmp ("Skin", var)) { 1.214 + ustrzcpy(skinName, sizeof(skinName) - 1, val); 1.215 + } else { 1.216 + loadOption(prefs, var, val); 1.217 + } 1.218 + } 1.219 + fclose(fp); 1.220 + 1.221 + if (prefs->number[OPTIONS_SIDEWAYS_DELAY] < prefs->number[OPTIONS_SIDEWAYS_SPEED]) { 1.222 + prefs->number[OPTIONS_SIDEWAYS_DELAY] = prefs->number[OPTIONS_SIDEWAYS_SPEED]; 1.223 + } 1.224 + 1.225 + return 0; 1.226 +} 1.227 + 1.228 +void saveOption(int i, int n, FILE *out) { 1.229 + char name[8], value[8]; 1.230 + int nameIdx = -1; 1.231 + 1.232 + strncpy(name, optionsMenu[i].name.c, 4); 1.233 + name[4] = 0; 1.234 + 1.235 + if (optionsMenu[i].valueNames) { 1.236 + if (optionsMenu[i].style == OPTSTYLE_FRAMES) { 1.237 + if (n == optionsMenu[i].minValue) { 1.238 + nameIdx = 0; 1.239 + } else if (n == optionsMenu[i].minValue + optionsMenu[i].nValues - 1) { 1.240 + nameIdx = 1; 1.241 + } 1.242 + } else { 1.243 + nameIdx = n - optionsMenu[i].minValue; 1.244 + } 1.245 + if (nameIdx >= 0 1.246 + && optionsMenu[i].valueNames[nameIdx].i == 0) { 1.247 + nameIdx = -1; 1.248 + } 1.249 + } 1.250 + 1.251 + if (nameIdx >= 0) { 1.252 + strncpy(value, optionsMenu[i].valueNames[nameIdx].c, 4); 1.253 + value[4] = 0; 1.254 + fprintf(out, "%s=%s\n", 1.255 + name, value); 1.256 + } else { 1.257 + fprintf(out, "%s=%d\n", 1.258 + name, n); 1.259 + } 1.260 +} 1.261 + 1.262 +void saveOptions(const struct LJPrefs *prefs) { 1.263 + FILE *out = ljfopen(ljIniName, "wt"); 1.264 + 1.265 + if (out) { 1.266 + for (int i = 0; i < PC_OPTIONS_MENU_LEN; ++i) { 1.267 + saveOption(i, prefs->number[i], out); 1.268 + } 1.269 + fprintf(out, "Skin=%s\n", 1.270 + skinName); 1.271 + fclose(out); 1.272 + } 1.273 +} 1.274 + 1.275 +void unpackOptions(LJView *v, const struct LJPrefs *prefs) { 1.276 + unpackCommonOptions(v, prefs->number); 1.277 + 1.278 + v->plat->nextAbove = prefs->number[OPTIONS_NEXT_ABOVE]; 1.279 + v->showTrails = prefs->number[OPTIONS_TRAILS]; 1.280 + autoPause = prefs->number[OPTIONS_AUTO_PAUSE]; 1.281 +} 1.282 + 1.283 +/******************************************************************** 1.284 + 1.285 +Allegro based option drawing code 1.286 + 1.287 +********************************************************************/ 1.288 + 1.289 +#define OPTIONS_TOP 100 1.290 +#define OPTIONS_ROW_HT 40 1.291 +#define OPTIONS_ROW_LEFT 80 1.292 +#define OPTIONS_ROW_MID 400 1.293 +#define OPTIONS_ROW_RIGHT 760 1.294 +#define OPTIONS_MENU_VIS 7 1.295 +#define OPTIONS_FONT aver32 1.296 + 1.297 + 1.298 +/** 1.299 + * @param y number of option to draw 1.300 + * @param hilite bitfield: 1=focused, 0=not 1.301 + */ 1.302 +void optionsDrawRow(const unsigned char *prefs, 1.303 + int dstY, int line, int value, int hilite) { 1.304 + unsigned int ht = text_height(OPTIONS_FONT); 1.305 + int buttonY = OPTIONS_TOP + OPTIONS_ROW_HT * dstY; 1.306 + int rowBg = bgColor; 1.307 + const char *nameText; 1.308 + char altNameText[8]; 1.309 + char valueText[OPTIONS_VALUE_LEN]; 1.310 + const char *valueOverride = isDisabledOption(prefs, line); 1.311 + int textcolor = fgColor; 1.312 + const char *valueDesc = NULL; 1.313 + 1.314 + { 1.315 + nameText = ljGetFourCCName(optionsMenu[line].name); 1.316 + if (!nameText) { 1.317 + strncpy(altNameText, optionsMenu[line].name.c, 4); 1.318 + altNameText[4] = 0; 1.319 + nameText = altNameText; 1.320 + } 1.321 + } 1.322 + 1.323 + if (valueOverride) { 1.324 + hilite |= 2; 1.325 + textcolor = makecol(128, 128, 128); 1.326 + } 1.327 + 1.328 + if (hilite == 3) { 1.329 + rowBg = makecol(204, 204, 204); 1.330 + } else if (hilite == 1) { 1.331 + rowBg = hiliteColor; 1.332 + } 1.333 + 1.334 + // If the value of this option is within range, format it as a string. 1.335 + if (value >= optionsMenu[line].minValue 1.336 + && value < optionsMenu[line].minValue + optionsMenu[line].nValues) { 1.337 + if (valueOverride) { 1.338 + ustrzcpy(valueText, sizeof(valueText), "overridden"); 1.339 + valueDesc = valueOverride; 1.340 + } else { 1.341 + valueDesc = getOptionsValueStr(valueText, line + OPTIONS_OFFSET, value); 1.342 + } 1.343 + } else { 1.344 + valueText[0] = '\0'; 1.345 + } 1.346 + 1.347 + // draw current option 1.348 + acquire_screen(); 1.349 + rectfill(screen, 1.350 + OPTIONS_ROW_LEFT, buttonY, 1.351 + OPTIONS_ROW_RIGHT - 1, buttonY + OPTIONS_ROW_HT - 1, 1.352 + rowBg); 1.353 + textout_ex(screen, OPTIONS_FONT, nameText, 1.354 + OPTIONS_ROW_LEFT + 8, buttonY + (OPTIONS_ROW_HT - ht) / 2, 1.355 + textcolor, rowBg); 1.356 + textout_ex(screen, OPTIONS_FONT, 1.357 + valueText, 1.358 + OPTIONS_ROW_MID, buttonY + (OPTIONS_ROW_HT - ht) / 2, 1.359 + textcolor, rowBg); 1.360 + 1.361 + // For an enabled selected item, draw the frame 1.362 + if (hilite == 1) { 1.363 + rect(screen, 1.364 + OPTIONS_ROW_LEFT, buttonY, 1.365 + OPTIONS_ROW_RIGHT - 1, buttonY + OPTIONS_ROW_HT - 1, 1.366 + fgColor); 1.367 + } 1.368 + 1.369 + // For a selected item, draw the help text 1.370 + if (hilite & 1) { 1.371 + buttonY = OPTIONS_TOP + OPTIONS_ROW_HT * OPTIONS_MENU_VIS; 1.372 + rectfill(screen, 1.373 + OPTIONS_ROW_LEFT, buttonY, 1.374 + OPTIONS_ROW_RIGHT - 1, buttonY + OPTIONS_ROW_HT * 5 / 2 - 1, 1.375 + bgColor); 1.376 + 1.377 + const char *descText = ljGetFourCCDesc(optionsMenu[line].name); 1.378 + if (descText) { 1.379 + textout_ex(screen, OPTIONS_FONT, descText, 1.380 + OPTIONS_ROW_LEFT, 1.381 + buttonY + OPTIONS_ROW_HT - ht / 2, 1.382 + textcolor, bgColor); 1.383 + } 1.384 + if (valueDesc) { 1.385 + textout_ex(screen, OPTIONS_FONT, valueDesc, 1.386 + OPTIONS_ROW_LEFT, 1.387 + buttonY + 2 * OPTIONS_ROW_HT - ht / 2, 1.388 + textcolor, bgColor); 1.389 + } 1.390 + } 1.391 + 1.392 + release_screen(); 1.393 +} 1.394 + 1.395 +void optionsClearRow(int dstY, int hilite) { 1.396 + int buttonY = OPTIONS_TOP + OPTIONS_ROW_HT * dstY; 1.397 + rectfill(screen, 1.398 + OPTIONS_ROW_LEFT, buttonY, 1.399 + OPTIONS_ROW_RIGHT - 1, buttonY + OPTIONS_ROW_HT * 5 / 2 - 1, 1.400 + bgColor); 1.401 +} 1.402 + 1.403 +void optionsDrawPage(int page, const unsigned char *prefs) { 1.404 + int nPages = 0; 1.405 + for (; optionsPages[nPages].name; ++nPages) { } 1.406 + 1.407 + vsync(); 1.408 + acquire_screen(); 1.409 + rectfill(screen, 320, 32, SCREEN_W - 1, 63, bgColor); 1.410 + textprintf_right_ex(screen, aver32, 1.411 + SCREEN_W - 16, 32, fgColor, -1, 1.412 + "(%d/%d) %s", 1.413 + page + 1, nPages, optionsPages[page].name); 1.414 + 1.415 + for (int i = optionsPages[page].start; 1.416 + i < optionsPages[page + 1].start; ++i) { 1.417 + optionsDrawRow(prefs, i - optionsPages[page].start, 1.418 + i, prefs[i], 0); 1.419 + } 1.420 + for (int i = optionsPages[page + 1].start; 1.421 + i < optionsPages[page].start + OPTIONS_MENU_VIS; ++i) { 1.422 + optionsClearRow(i - optionsPages[page].start, 0); 1.423 + } 1.424 + release_screen(); 1.425 +} 1.426 + 1.427 +void optionsWinInit(void) { 1.428 + acquire_screen(); 1.429 + clear_to_color(screen, bgColor); 1.430 + textout_ex(screen, aver32, "LOCKJAW > Options", 16, 32, fgColor, -1); 1.431 + textout_ex(screen, aver32, "Rotate: change page; Up/Down: select", 16, 522, fgColor, -1); 1.432 + textout_ex(screen, aver32, "Left/Right change; Enter: exit", 16, 552, fgColor, -1); 1.433 + release_screen(); 1.434 + 1.435 +} 1.436 + 1.437 +void optionsIdle(void) { 1.438 + rest(10); 1.439 +}