comparison src/old_pc_options.c @ 0:c84446dfb3f5

initial add
author paulo@localhost
date Fri, 13 Mar 2009 00:39:12 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:f6cb8b5fdacb
1 /* PC option screen for LOCKJAW, an implementation of the Soviet Mind Game
2
3 Copyright (C) 2006 Damian Yerrick <tepples+lj@spamcop.net>
4
5 This work is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Original game concept and design by Alexey Pajitnov.
20 The Software is not sponsored or endorsed by Alexey Pajitnov, Elorg,
21 or The Tetris Company LLC.
22
23 */
24
25 #include "ljpc.h"
26 #include <ctype.h>
27 #include "ljpath.h"
28 #include <string.h>
29 #include "options.h"
30 #include "ljlocale.h"
31
32 #define OPTIONS_OFFSET 0
33 #define optionsMenu (commonOptionsMenu + OPTIONS_OFFSET)
34
35
36
37 #if 0
38 static int getOptionValueByName(int row, const char *value) {
39 for (int x = 0; x < optionsMenu[row].nValues; ++x) {
40 if (!ustrcmp(value, optionsMenu[row].valueNames[x])) {
41 return x + optionsMenu[row].minValue;
42 }
43 }
44 return -1;
45 }
46
47 static void setOptionValueByNumber(struct LJPrefs *prefs,
48 int row, const char *value) {
49 if (value[0] >= '0' && value[0] <= '9') {
50 int num = atoi(value);
51 if (num >= optionsMenu[row].minValue
52 && num < optionsMenu[row].minValue + optionsMenu[row].nValues) {
53 prefs->number[row] = num;
54 }
55 }
56 }
57
58 static void setOptionValueByName(struct LJPrefs *prefs,
59 int row, const char *value) {
60 int num = getOptionValueByName(row, value);
61
62 if (num >= 0) {
63 prefs->number[row] = num;
64 }
65 }
66
67 static void setOptionValueByBoolean(struct LJPrefs *prefs,
68 int row, const char *value) {
69 int num = atoi(value);
70
71 if (num >= 0) {
72 prefs->number[row] = num ? 1 : 0;
73 }
74 }
75 #endif
76
77 /* parse_ini_line *******************
78 */
79 int parse_ini_line(const char *in, char *key, char *var, char *val)
80 {
81 int c;
82 char *kstart = key;
83
84 /* Skip whitespace before key */
85 while(*in && isspace(*in))
86 in++;
87
88 /* Parse key */
89 if(*in == '[') /* if we have a new key, load it */
90 {
91 in++;
92
93 /* Skip whitespace before actual key */
94 while(*in && isspace(*in))
95 in++;
96
97 for(c = *in++;
98 c != 0 && c != ']' && c != '\n' && c != '\r';
99 c = *in++)
100 {
101 if(!isspace(c))
102 *key++ = c;
103 }
104 *key = 0;
105 /* Strip whitespace after key */
106 do {
107 *key-- = 0;
108 } while(key >= kstart && isspace(*key));
109 }
110
111 /* Skip whitespace before variable */
112 while(*in && isspace(*in))
113 in++;
114 if(*in == 0) /* if there is no variable, don't do anything */
115 return 0;
116
117 for(c = *in++;
118 c != 0 && c != '=' && c != '\n' && c != '\r';
119 c = *in++)
120 {
121 if(!isspace(c))
122 {
123 *var++ = c;
124 }
125 }
126 *var = 0;
127
128 /* Skip whitespace before value */
129 while(*in && isspace(*in))
130 in++;
131
132 /* Get value */
133 kstart = val;
134 for(c = *in++;
135 c != 0 && c != '\n' && c != '\r';
136 c = *in++)
137 {
138 *val++ = c;
139 }
140 /* Strip whitespace after value */
141 do {
142 *val-- = 0;
143 } while(val >= kstart && isspace(*val));
144
145 return 0;
146 }
147
148 static const char ljIniName[] = "lj.ini";
149
150 /**
151 * Finds a FourCC in a list.
152 * @param needle the fourCC to search for
153 * @param haystack a list of fourCCs
154 * @param haystackLen the length of this list
155 * @return the index within haystack where needle was found
156 * or -1 if not found
157 */
158 int findFourCC(const char *needle,
159 const FourCC *haystack, size_t haystackLen) {
160 for (size_t i = 0; i < haystackLen; ++i) {
161 if (!strncmp(haystack[i].c, needle, 4)) {
162 return i;
163 }
164 }
165 return -1;
166 }
167
168 void loadOption(struct LJPrefs *prefs,
169 const char *name, const char *value) {
170 for (int i = 0; i < PC_OPTIONS_MENU_LEN; ++i) {
171 if (!strncmp(optionsMenu[i].name.c, name, 4)) {
172 if (isdigit(value[0])) {
173 unsigned long int n = strtoul(value, NULL, 10);
174 if (n >= optionsMenu[i].minValue
175 && n < optionsMenu[i].minValue + optionsMenu[i].nValues) {
176 prefs->number[i] = n;
177 } else {
178 allegro_message("ignoring out of range %s=%lu\n",
179 name, n);
180 }
181 } else if (optionsMenu[i].valueNames) {
182 int nValueNames = (optionsMenu[i].style == OPTSTYLE_FRAMES
183 ? 2
184 : optionsMenu[i].nValues);
185 int foundValue = findFourCC(value, optionsMenu[i].valueNames, nValueNames);
186 if (optionsMenu[i].style == OPTSTYLE_FRAMES
187 && foundValue > 0) {
188 foundValue = optionsMenu[i].nValues - 1;
189 }
190 prefs->number[i] = foundValue + optionsMenu[i].minValue;
191 }
192 return;
193 }
194 }
195 }
196
197 int loadOptions(struct LJPrefs *prefs) {
198 FILE *fp = ljfopen(ljIniName, "rt");
199 char key[1024], var[1024], val[1024], input_buf[1024];
200
201 if (!fp) return 0;
202
203 key[0] = 0;
204 var[0] = 0;
205 val[0] = 0;
206
207 while(fgets (input_buf, sizeof(input_buf), fp)) {
208 parse_ini_line(input_buf, key, var, val);
209
210 if(!ustrcmp ("Skin", var)) {
211 ustrzcpy(skinName, sizeof(skinName) - 1, val);
212 } else {
213 loadOption(prefs, var, val);
214 }
215 }
216 fclose(fp);
217
218 if (prefs->number[OPTIONS_SIDEWAYS_DELAY] < prefs->number[OPTIONS_SIDEWAYS_SPEED]) {
219 prefs->number[OPTIONS_SIDEWAYS_DELAY] = prefs->number[OPTIONS_SIDEWAYS_SPEED];
220 }
221
222 return 0;
223 }
224
225 void saveOption(int i, int n, FILE *out) {
226 char name[8], value[8];
227 int nameIdx = -1;
228
229 strncpy(name, optionsMenu[i].name.c, 4);
230 name[4] = 0;
231
232 if (optionsMenu[i].valueNames) {
233 if (optionsMenu[i].style == OPTSTYLE_FRAMES) {
234 if (n == optionsMenu[i].minValue) {
235 nameIdx = 0;
236 } else if (n == optionsMenu[i].minValue + optionsMenu[i].nValues - 1) {
237 nameIdx = 1;
238 }
239 } else {
240 nameIdx = n - optionsMenu[i].minValue;
241 }
242 if (nameIdx >= 0
243 && optionsMenu[i].valueNames[nameIdx].i == 0) {
244 nameIdx = -1;
245 }
246 }
247
248 if (nameIdx >= 0) {
249 strncpy(value, optionsMenu[i].valueNames[nameIdx].c, 4);
250 value[4] = 0;
251 fprintf(out, "%s=%s\n",
252 name, value);
253 } else {
254 fprintf(out, "%s=%d\n",
255 name, n);
256 }
257 }
258
259 void saveOptions(const struct LJPrefs *prefs) {
260 FILE *out = ljfopen(ljIniName, "wt");
261
262 if (out) {
263 for (int i = 0; i < PC_OPTIONS_MENU_LEN; ++i) {
264 saveOption(i, prefs->number[i], out);
265 }
266 fprintf(out, "Skin=%s\n",
267 skinName);
268 fclose(out);
269 }
270 }
271
272 void unpackOptions(LJView *v, const struct LJPrefs *prefs) {
273 unpackCommonOptions(v, prefs->number);
274
275 v->plat->nextAbove = prefs->number[OPTIONS_NEXT_ABOVE];
276 v->showTrails = prefs->number[OPTIONS_TRAILS];
277 autoPause = prefs->number[OPTIONS_AUTO_PAUSE];
278 }
279
280 /********************************************************************
281
282 Allegro based option drawing code
283
284 ********************************************************************/
285
286 #define OPTIONS_TOP 100
287 #define OPTIONS_ROW_HT 40
288 #define OPTIONS_ROW_LEFT 80
289 #define OPTIONS_ROW_MID 400
290 #define OPTIONS_ROW_RIGHT 760
291 #define OPTIONS_MENU_VIS 7
292 #define OPTIONS_FONT aver32
293
294
295 /**
296 * @param y number of option to draw
297 * @param hilite bitfield: 1=focused, 0=not
298 */
299 void optionsDrawRow(const unsigned char *prefs,
300 int dstY, int line, int value, int hilite) {
301 unsigned int ht = text_height(OPTIONS_FONT);
302 int buttonY = OPTIONS_TOP + OPTIONS_ROW_HT * dstY;
303 int rowBg = bgColor;
304 const char *nameText;
305 char altNameText[8];
306 char valueText[OPTIONS_VALUE_LEN];
307 const char *valueOverride = isDisabledOption(prefs, line);
308 int textcolor = fgColor;
309 const char *valueDesc = NULL;
310
311 {
312 nameText = ljGetFourCCName(optionsMenu[line].name);
313 if (!nameText) {
314 strncpy(altNameText, optionsMenu[line].name.c, 4);
315 altNameText[4] = 0;
316 nameText = altNameText;
317 }
318 }
319
320 if (valueOverride) {
321 hilite |= 2;
322 textcolor = makecol(128, 128, 128);
323 }
324
325 if (hilite == 3) {
326 rowBg = makecol(204, 204, 204);
327 } else if (hilite == 1) {
328 rowBg = hiliteColor;
329 }
330
331 // If the value of this option is within range, format it as a string.
332 if (value >= optionsMenu[line].minValue
333 && value < optionsMenu[line].minValue + optionsMenu[line].nValues) {
334 if (valueOverride) {
335 ustrzcpy(valueText, sizeof(valueText), "overridden");
336 valueDesc = valueOverride;
337 } else {
338 valueDesc = getOptionsValueStr(valueText, line + OPTIONS_OFFSET, value);
339 }
340 } else {
341 valueText[0] = '\0';
342 }
343
344 // draw current option
345 acquire_screen();
346 rectfill(screen,
347 OPTIONS_ROW_LEFT, buttonY,
348 OPTIONS_ROW_RIGHT - 1, buttonY + OPTIONS_ROW_HT - 1,
349 rowBg);
350 textout_ex(screen, OPTIONS_FONT, nameText,
351 OPTIONS_ROW_LEFT + 8, buttonY + (OPTIONS_ROW_HT - ht) / 2,
352 textcolor, rowBg);
353 textout_ex(screen, OPTIONS_FONT,
354 valueText,
355 OPTIONS_ROW_MID, buttonY + (OPTIONS_ROW_HT - ht) / 2,
356 textcolor, rowBg);
357
358 // For an enabled selected item, draw the frame
359 if (hilite == 1) {
360 rect(screen,
361 OPTIONS_ROW_LEFT, buttonY,
362 OPTIONS_ROW_RIGHT - 1, buttonY + OPTIONS_ROW_HT - 1,
363 fgColor);
364 }
365
366 // For a selected item, draw the help text
367 if (hilite & 1) {
368 buttonY = OPTIONS_TOP + OPTIONS_ROW_HT * OPTIONS_MENU_VIS;
369 rectfill(screen,
370 OPTIONS_ROW_LEFT, buttonY,
371 OPTIONS_ROW_RIGHT - 1, buttonY + OPTIONS_ROW_HT * 5 / 2 - 1,
372 bgColor);
373
374 const char *descText = ljGetFourCCDesc(optionsMenu[line].name);
375 if (descText) {
376 textout_ex(screen, OPTIONS_FONT, descText,
377 OPTIONS_ROW_LEFT,
378 buttonY + OPTIONS_ROW_HT - ht / 2,
379 textcolor, bgColor);
380 }
381 if (valueDesc) {
382 textout_ex(screen, OPTIONS_FONT, valueDesc,
383 OPTIONS_ROW_LEFT,
384 buttonY + 2 * OPTIONS_ROW_HT - ht / 2,
385 textcolor, bgColor);
386 }
387 }
388
389 release_screen();
390 }
391
392 void optionsClearRow(int dstY, int hilite) {
393 int buttonY = OPTIONS_TOP + OPTIONS_ROW_HT * dstY;
394 rectfill(screen,
395 OPTIONS_ROW_LEFT, buttonY,
396 OPTIONS_ROW_RIGHT - 1, buttonY + OPTIONS_ROW_HT * 5 / 2 - 1,
397 bgColor);
398 }
399
400 void optionsDrawPage(int page, const unsigned char *prefs) {
401 int nPages = 0;
402 for (; optionsPages[nPages].name; ++nPages) { }
403
404 vsync();
405 acquire_screen();
406 rectfill(screen, 320, 32, SCREEN_W - 1, 63, bgColor);
407 textprintf_right_ex(screen, aver32,
408 SCREEN_W - 16, 32, fgColor, -1,
409 "(%d/%d) %s",
410 page + 1, nPages, optionsPages[page].name);
411
412 for (int i = optionsPages[page].start;
413 i < optionsPages[page + 1].start; ++i) {
414 optionsDrawRow(prefs, i - optionsPages[page].start,
415 i, prefs[i], 0);
416 }
417 for (int i = optionsPages[page + 1].start;
418 i < optionsPages[page].start + OPTIONS_MENU_VIS; ++i) {
419 optionsClearRow(i - optionsPages[page].start, 0);
420 }
421 release_screen();
422 }
423
424 void optionsWinInit(void) {
425 acquire_screen();
426 clear_to_color(screen, bgColor);
427 textout_ex(screen, aver32, "LOCKJAW > Options", 16, 32, fgColor, -1);
428 textout_ex(screen, aver32, "Rotate: change page; Up/Down: select", 16, 522, fgColor, -1);
429 textout_ex(screen, aver32, "Left/Right change; Enter: exit", 16, 552, fgColor, -1);
430 release_screen();
431
432 }
433
434 void optionsIdle(void) {
435 rest(10);
436 }