1
//------------------------------------------------------------------------
2
// COOKIE : Unix/FLTK Persistence (INI/RC files)
3
//------------------------------------------------------------------------
5
// GL-Friendly Node Builder (C) 2000-2007 Andrew Apted
7
// Based on 'BSP 2.3' by Colin Reed, Lee Killough and others.
9
// This program is free software; you can redistribute it and/or
10
// modify it under the terms of the GNU General Public License
11
// as published by the Free Software Foundation; either version 2
12
// of the License, or (at your option) any later version.
14
// This program is distributed in the hope that it will be useful,
15
// but WITHOUT ANY WARRANTY; without even the implied warranty of
16
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
// GNU General Public License for more details.
19
//------------------------------------------------------------------------
21
// this includes everything we need
25
#define DEBUG_COOKIE 0
28
static const char *cookie_filename;
30
// current section parser func
31
static boolean_g (* cookie_section_parser)
32
(const char *name, const char *value) = NULL;
35
static void CookieDebug(const char *str, ...)
42
vsprintf(buffer, str, args);
45
fprintf(stderr, "COOKIE: %s", buffer);
51
static boolean_g SetBooleanVar(boolean_g& var, const char *value)
53
if (strchr(value, '0'))
59
if (strchr(value, '1'))
66
CookieDebug("Bad Boolean [%s]\n", value);
70
static boolean_g SetIntegerVar(int& var, const char *value)
72
var = strtol(value, NULL, 10);
77
static boolean_g SetStringVar(const char *& var, const char *value)
79
int len = strlen(value);
82
if (value[0] != '"' || len < 2 || value[len-1] != '"' || len > 1020)
84
CookieDebug("Bad String [%s]\n", value);
88
strncpy(buffer, value+1, len-2);
92
var = GlbspStrDup(buffer);
98
//------------------------------------------------------------------------
101
static boolean_g CookieSetBuildVar(const char *name, const char *value)
103
// file names and factor
104
if (strcasecmp(name, "in_file") == 0)
105
return SetStringVar(guix_info.input_file, value);
107
if (strcasecmp(name, "out_file") == 0)
108
return SetStringVar(guix_info.output_file, value);
110
if (strcasecmp(name, "factor") == 0)
111
return SetIntegerVar(guix_info.factor, value);
115
if (strcasecmp(name, "no_reject") == 0)
116
return SetBooleanVar(guix_info.no_reject, value);
118
if (strcasecmp(name, "mini_warnings") == 0)
119
return SetBooleanVar(guix_info.mini_warnings, value);
121
if (strcasecmp(name, "pack_sides") == 0)
122
return SetBooleanVar(guix_info.pack_sides, value);
124
// API change to main glbsp code: 'choose_fresh' --> 'fast'.
125
if (strcasecmp(name, "choose_fresh") == 0)
127
if (! SetBooleanVar(guix_info.fast, value))
130
guix_info.fast = ! guix_info.fast;
136
if (strcasecmp(name, "block_limit") == 0)
137
return SetIntegerVar(guix_info.block_limit, value);
141
if (strcasecmp(name, "gwa_mode") == 0)
142
return SetBooleanVar(guix_info.gwa_mode, value);
144
if (strcasecmp(name, "no_normal") == 0)
145
return SetBooleanVar(guix_info.no_normal, value);
147
if (strcasecmp(name, "force_normal") == 0)
148
return SetBooleanVar(guix_info.force_normal, value);
151
// Unknown build variable !
152
CookieDebug("Unknown Build VAR [%s]\n", name);
156
static boolean_g CookieSetPrefVar(const char *name, const char *value)
159
if (strcasecmp(name, "overwrite_warn") == 0)
160
return SetBooleanVar(guix_prefs.overwrite_warn, value);
163
if (strcasecmp(name, "same_file_warn") == 0)
164
return SetBooleanVar(guix_prefs.same_file_warn, value);
166
// missing extension warning
167
if (strcasecmp(name, "lack_ext_warn") == 0)
168
return SetBooleanVar(guix_prefs.lack_ext_warn, value);
171
if (strcasecmp(name, "save_log_file") == 0)
172
return SetStringVar(guix_prefs.save_log_file, value);
175
// Unknown preference variable !
176
CookieDebug("Unknown Pref VAR [%s]\n", name);
180
static boolean_g CookieSetWinPosVar(const char *name, const char *value)
182
// main window position and size
183
if (strcasecmp(name, "window_x") == 0)
184
return SetIntegerVar(guix_prefs.win_x, value);
186
if (strcasecmp(name, "window_y") == 0)
187
return SetIntegerVar(guix_prefs.win_y, value);
189
if (strcasecmp(name, "window_w") == 0)
190
return SetIntegerVar(guix_prefs.win_w, value);
192
if (strcasecmp(name, "window_h") == 0)
193
return SetIntegerVar(guix_prefs.win_h, value);
196
// other window positions
197
if (strcasecmp(name, "progress_x") == 0)
198
return SetIntegerVar(guix_prefs.progress_x, value);
200
if (strcasecmp(name, "progress_y") == 0)
201
return SetIntegerVar(guix_prefs.progress_y, value);
203
if (strcasecmp(name, "dialog_x") == 0)
204
return SetIntegerVar(guix_prefs.dialog_x, value);
206
if (strcasecmp(name, "dialog_y") == 0)
207
return SetIntegerVar(guix_prefs.dialog_y, value);
209
if (strcasecmp(name, "other_x") == 0)
210
return SetIntegerVar(guix_prefs.other_x, value);
212
if (strcasecmp(name, "other_y") == 0)
213
return SetIntegerVar(guix_prefs.other_y, value);
216
// manual window positions
217
if (strcasecmp(name, "manual_x") == 0)
218
return SetIntegerVar(guix_prefs.manual_x, value);
220
if (strcasecmp(name, "manual_y") == 0)
221
return SetIntegerVar(guix_prefs.manual_y, value);
223
if (strcasecmp(name, "manual_w") == 0)
224
return SetIntegerVar(guix_prefs.manual_w, value);
226
if (strcasecmp(name, "manual_h") == 0)
227
return SetIntegerVar(guix_prefs.manual_h, value);
229
if (strcasecmp(name, "manual_page") == 0)
230
return SetIntegerVar(guix_prefs.manual_page, value);
233
// Unknown window pos variable !
234
CookieDebug("Unknown WindowPos VAR [%s]\n", name);
239
//------------------------------------------------------------------------
242
// returns TRUE if line parsed OK. Note: modifies the buffer.
243
static boolean_g CookieParseLine(char *buf)
248
while (isspace(*buf))
255
// remove trailing whitespace
258
while (len > 0 && isspace(buf[len-1]))
261
CookieDebug("PRE-PARSE: '%s'\n", buf);
270
if (strncasecmp(buf+1, "BUILD_INFO]", 11) == 0)
272
cookie_section_parser = CookieSetBuildVar;
276
if (strncasecmp(buf+1, "PREFERENCES]", 12) == 0)
278
cookie_section_parser = CookieSetPrefVar;
282
if (strncasecmp(buf+1, "WINDOW_POS]", 11) == 0)
284
cookie_section_parser = CookieSetWinPosVar;
289
cookie_section_parser = NULL;
290
CookieDebug("Unknown Section: %s\n", buf);
297
// Righteo, line starts with an identifier. It should be of the
298
// form "name = value". We'll terminate the identifier, and pass
299
// the name/value strings to a section-dependent handler.
304
for (buf++; isalpha(*buf) || *buf == '_'; buf++)
305
{ /* nothing here */ }
307
while (isspace(*buf))
315
while (isspace(*buf))
321
CookieDebug("Name: [%s] Value: [%s]\n", name, buf);
323
if (cookie_section_parser)
325
return (* cookie_section_parser)(name, buf);
328
// variables were found outside of any section
335
// Increments 'problems' each time something is fixed up.
337
void CookieCheckEm(int& problems)
339
// check main window size
340
if (guix_prefs.win_w < MAIN_WINDOW_MIN_W)
342
guix_prefs.win_w = MAIN_WINDOW_MIN_W;
346
if (guix_prefs.win_h < MAIN_WINDOW_MIN_H)
348
guix_prefs.win_h = MAIN_WINDOW_MIN_H;
352
// check manual/license window size
353
if (guix_prefs.manual_w < MANUAL_WINDOW_MIN_W)
355
guix_prefs.manual_w = MANUAL_WINDOW_MIN_W;
359
if (guix_prefs.manual_h < MANUAL_WINDOW_MIN_H)
361
guix_prefs.manual_h = MANUAL_WINDOW_MIN_H;
365
if (guix_info.factor > 32)
367
guix_info.factor = 32;
375
// Determine the path and filename of the cookie file.
377
void CookieSetPath(const char *argv0)
380
GlbspFree(cookie_filename);
388
if (HelperFilenameValid(argv0))
390
strcpy(buffer, HelperReplaceExt(argv0, "ini"));
393
strcpy(buffer, "glBSPX.ini");
395
#elif defined(MACOSX)
399
strcpy(buffer, getenv("HOME"));
400
strcat(buffer, "/Library/Preferences/");
403
strcat(buffer, "glBSPX.rc");
409
strcpy(buffer, getenv("HOME"));
413
// backwards compatibility (glbspX != glBSPX)
415
strcat(buffer, ".glbspX_rc");
417
if (! HelperFileExists(buffer))
419
char *bsp = strrchr(buffer, 'b');
421
if (bsp) strncpy(bsp, "BSP", 3);
425
cookie_filename = GlbspStrDup(buffer);
427
CookieDebug("CookieFilename: '%s'\n", cookie_filename);
433
// Reads the cookie file.
434
// Returns one of the COOKIE_E_* values.
436
// All the variables that can be read here should be initialised to
437
// default values before calling, in case we fail or the variable is
438
// missing in the cookie file.
440
cookie_status_t CookieReadAll(void)
442
CookieDebug("CookieReadAll BEGUN.\n");
444
// open file for reading
445
FILE *fp = fopen(cookie_filename, "r");
448
return COOKIE_E_NO_FILE;
450
cookie_section_parser = NULL;
452
// simple line-by-line parser
458
while (fgets(buffer, sizeof(buffer) - 2, fp))
460
if (! CookieParseLine(buffer))
464
CookieCheckEm(check_probs);
466
CookieDebug("CookieReadAll DONE. %d ParseProbs %d CheckProbs\n",
467
parse_probs, check_probs);
469
// parsing problems take precedence
471
return COOKIE_E_PARSE_ERRORS;
474
return COOKIE_E_CHECK_ERRORS;
480
//------------------------------------------------------------------------
483
static void CookieWriteHeader(FILE *fp)
485
fprintf(fp, "# GLBSPX %s Persistent Data\n", GLBSP_VER);
486
fprintf(fp, "# Editing this file by hand is not recommended.\n");
492
static void CookieWriteBuildInfo(FILE *fp)
494
// identifying section
495
fprintf(fp, "[BUILD_INFO]\n");
498
fprintf(fp, "in_file = \"%s\"\n", guix_info.input_file ?
499
guix_info.input_file : "");
501
fprintf(fp, "out_file = \"%s\"\n", guix_info.output_file ?
502
guix_info.output_file : "");
505
fprintf(fp, "factor = %d\n", guix_info.factor);
508
fprintf(fp, "no_reject = %d\n", guix_info.no_reject ? 1 : 0);
509
fprintf(fp, "mini_warnings = %d\n", guix_info.mini_warnings ? 1 : 0);
510
fprintf(fp, "pack_sides = %d\n", guix_info.pack_sides ? 1 : 0);
511
fprintf(fp, "choose_fresh = %d\n", guix_info.fast ? 0 : 1); // API change
514
fprintf(fp, "block_limit = %d\n", guix_info.block_limit);
517
fprintf(fp, "gwa_mode = %d\n", guix_info.gwa_mode ? 1 : 0);
518
fprintf(fp, "no_normal = %d\n", guix_info.no_normal ? 1 : 0);
519
fprintf(fp, "force_normal = %d\n", guix_info.force_normal ? 1 : 0);
522
// no_progress: not useful for GUI mode.
523
// keep_sect, no_prune: not used in GUI mode (yet).
524
// load_all: determined automatically.
526
// keep a blank line between sections
531
static void CookieWritePrefs(FILE *fp)
533
// identifying section
534
fprintf(fp, "[PREFERENCES]\n");
536
fprintf(fp, "overwrite_warn = %d\n", guix_prefs.overwrite_warn);
537
fprintf(fp, "same_file_warn = %d\n", guix_prefs.same_file_warn);
538
fprintf(fp, "lack_ext_warn = %d\n", guix_prefs.lack_ext_warn);
540
fprintf(fp, "save_log_file = \"%s\"\n", guix_prefs.save_log_file ?
541
guix_prefs.save_log_file : "");
547
static void CookieWriteWindowPos(FILE *fp)
549
// identifying section
550
fprintf(fp, "[WINDOW_POS]\n");
552
// main window position and size
553
fprintf(fp, "window_x = %d\n", guix_prefs.win_x);
554
fprintf(fp, "window_y = %d\n", guix_prefs.win_y);
555
fprintf(fp, "window_w = %d\n", guix_prefs.win_w);
556
fprintf(fp, "window_h = %d\n", guix_prefs.win_h);
558
// other window positions
559
fprintf(fp, "progress_x = %d\n", guix_prefs.progress_x);
560
fprintf(fp, "progress_y = %d\n", guix_prefs.progress_y);
561
fprintf(fp, "dialog_x = %d\n", guix_prefs.dialog_x);
562
fprintf(fp, "dialog_y = %d\n", guix_prefs.dialog_y);
563
fprintf(fp, "other_x = %d\n", guix_prefs.other_x);
564
fprintf(fp, "other_y = %d\n", guix_prefs.other_y);
566
fprintf(fp, "manual_x = %d\n", guix_prefs.manual_x);
567
fprintf(fp, "manual_y = %d\n", guix_prefs.manual_y);
568
fprintf(fp, "manual_w = %d\n", guix_prefs.manual_w);
569
fprintf(fp, "manual_h = %d\n", guix_prefs.manual_h);
570
fprintf(fp, "manual_page = %d\n", guix_prefs.manual_page);
580
// Writes the cookie file.
581
// Returns one of the COOKIE_E_* values.
583
cookie_status_t CookieWriteAll(void)
585
CookieDebug("CookieWriteAll BEGUN.\n");
587
// create file (overwrite if exists)
588
FILE *fp = fopen(cookie_filename, "w");
591
return COOKIE_E_NO_FILE;
593
CookieWriteHeader(fp);
594
CookieWriteBuildInfo(fp);
595
CookieWritePrefs(fp);
596
CookieWriteWindowPos(fp);
601
CookieDebug("CookieWriteAll DONE.\n");