A clock has been added which utilizes setitimer(). Could be better
[cboard.git] / src / rcfile.c
blobfec5ff949413b7436f7296934c1f91babc63c38d
1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
2 /*
3 Copyright (C) 2002-2006 Ben Kibbey <bjk@luxsci.net>
5 This program 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.
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.
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
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <err.h>
23 #include <ctype.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <errno.h>
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
32 #ifdef HAVE_NCURSES_H
33 #include <ncurses.h>
34 #endif
36 #include "chess.h"
37 #include "conf.h"
38 #include "misc.h"
39 #include "colors.h"
40 #include "rcfile.h"
42 #ifdef WITH_DMALLOC
43 #include <dmalloc.h>
44 #endif
46 static int attributes(const char *filename, int line, char *str)
48 char *tmp;
49 int attrs = 0;
51 while ((tmp = strsep(&str, ",")) != NULL) {
52 if (strcasecmp(tmp, "BOLD") == 0)
53 attrs |= A_BOLD;
54 else if (strcasecmp(tmp, "REVERSE") == 0)
55 attrs |= A_REVERSE;
56 else if (strcasecmp(tmp, "NONE") == 0)
57 attrs |= A_NORMAL;
58 else if (strcasecmp(tmp, "DIM") == 0)
59 attrs |= A_DIM;
60 else if (strcasecmp(tmp, "STANDOUT") == 0)
61 attrs |= A_STANDOUT;
62 else if (strcasecmp(tmp, "UNDERLINE") == 0)
63 attrs |= A_UNDERLINE;
64 else if (strcasecmp(tmp, "BLINK") == 0)
65 attrs |= A_BLINK;
66 else if (strcasecmp(tmp, "INVISIBLE") == 0)
67 attrs |= A_INVIS;
68 else
69 errx(EXIT_FAILURE, "%s(%i): invalid attribute \"%s\"", filename,
70 line, tmp);
73 return attrs;
76 static short color_name(const char *filename, int line, const char *color)
78 if (strcasecmp(color, "BLACK") == 0)
79 return COLOR_BLACK;
80 else if (strcasecmp(color, "WHITE") == 0)
81 return COLOR_WHITE;
82 else if (strcasecmp(color, "GREEN") == 0)
83 return COLOR_GREEN;
84 else if (strcasecmp(color, "YELLOW") == 0)
85 return COLOR_YELLOW;
86 else if (strcasecmp(color, "MAGENTA") == 0)
87 return COLOR_MAGENTA;
88 else if (strcasecmp(color, "BLUE") == 0)
89 return COLOR_BLUE;
90 else if (strcasecmp(color, "RED") == 0)
91 return COLOR_RED;
92 else if (strcasecmp(color, "CYAN") == 0)
93 return COLOR_CYAN;
94 else
95 errx(EXIT_FAILURE, "%s(%i): invalid color \"%s\"", filename, line,
96 color);
98 return -1;
101 static void parse_color(const char *filename, int line, const char *str,
102 struct color_s *c)
104 char fg[16], bg[16], attr[64], nattr[64];
105 struct color_s ctmp = *c;
106 int n;
108 if ((n = sscanf(str, "%[a-zA-Z] %[a-zA-Z] %[a-zA-Z,] %[a-zA-Z,]", fg, bg,
109 attr, nattr)) < 2)
110 errx(EXIT_FAILURE, "%s(%i): parse error", filename, line);
112 ctmp.fg = color_name(filename, line, fg);
113 ctmp.bg = color_name(filename, line, bg);
114 ctmp.attrs = ctmp.nattrs = 0;
116 if (n > 2)
117 ctmp.attrs = attributes(filename, line, attr);
119 if (n > 3)
120 ctmp.nattrs = attributes(filename, line, nattr);
122 *c = ctmp;
125 static int on_or_off(const char *filename, int lines, const char *str)
127 if (strcasecmp(str, "on") == 0 || strcasecmp(str, "1") == 0 ||
128 strcasecmp(str, "yes") == 0 || strcasecmp(str, "true") == 0)
129 return 1;
131 if (strcasecmp(str, "off") == 0 || strcasecmp(str, "0") == 0 ||
132 strcasecmp(str, "no") == 0 || strcasecmp(str, "false") == 0)
133 return 0;
135 errx(EXIT_FAILURE, "%s(%i): invalid value \"%s\"", filename, lines, str);
138 void copydatafile(const char *dst, const char *src)
140 FILE *fp, *ofp;
141 char buf[LINE_MAX], *s;
143 snprintf(buf, sizeof(buf), "%s/%s", DATA_PATH, src);
145 if ((fp = fopen(buf, "r")) == NULL) {
146 if (errno != ENOENT)
147 warn("%s", buf);
148 return;
151 if ((ofp = fopen(dst, "w+")) == NULL) {
152 fclose(fp);
153 warn("%s", dst);
154 return;
157 while ((s = fgets(buf, sizeof(buf), fp)) != NULL)
158 fprintf(ofp, "%s", s);
160 fclose(fp);
161 fclose(ofp);
164 void set_config_defaults()
166 struct stat st;
168 config.pattern = strdup("*.pgn");
169 config.engine_cmd = strdup("gnuchess --xboard");
170 config.jumpcount = 5;
171 config.linegraphics = 1;
172 config.saveprompt = 1;
173 config.deleteprompt = 1;
174 config.validmoves = 1;
176 set_default_colors();
178 if (stat(config.nagfile, &st) == -1) {
179 if (errno == ENOENT)
180 copydatafile(config.nagfile, "nag.data");
181 else
182 warn("%s", config.nagfile);
185 if (stat(config.ccfile, &st) == -1) {
186 if (errno == ENOENT)
187 copydatafile(config.nagfile, "cc.data");
188 else
189 warn("%s", config.ccfile);
193 void parse_rcfile(const char *filename)
195 FILE *fp;
196 char *line, buf[LINE_MAX];
197 int lines = 0;
198 char *altengine = NULL;
199 int k = 0;
200 int init = 0;
202 if ((fp = fopen(filename, "r")) == NULL)
203 err(EXIT_FAILURE, "%s", filename);
205 while ((line = fgets(buf, sizeof(buf), fp)) != NULL) {
206 int n, c;
207 char var[30], val[50];
208 char token[MAX_PGN_LINE_LEN + 1], value[MAX_PGN_LINE_LEN + 1];
209 char *p;
211 lines++;
212 line = trim(line);
214 if (!line[0] || line[0] == '#')
215 continue;
217 if ((n = sscanf(line, "%s %[^\n]", var, val)) != 2)
218 errx(EXIT_FAILURE, "%s(%i): parse error %i", filename, lines,n);
220 strncpy(val, trim(val), sizeof(val));
221 strncpy(var, trim(var), sizeof(var));
223 if (strcmp(var, "jump_count") == 0) {
224 if (!isinteger(val))
225 errx(EXIT_FAILURE, "%s(%i): value is not an integer", filename,
226 lines);
228 config.jumpcount = atoi(val);
230 else if (strcmp(var, "bind") == 0) {
231 config.keys = Realloc(config.keys, (k + 2) *
232 sizeof(struct key_s *));
233 config.keys[k] = Calloc(1, sizeof(struct key_s));
234 p = val;
235 n = 0;
237 while (*p && !isspace(*p))
238 p++, n++;
240 c = *p;
241 *p = 0;
242 p -= n;
244 if (strcasecmp(p, "none") == 0)
245 config.keys[k]->type = KEY_DEFAULT;
246 else if (strcasecmp(p, "repeat") == 0)
247 config.keys[k]->type = KEY_REPEAT;
248 else if (strcasecmp(p, "set") == 0)
249 config.keys[k]->type = KEY_SET;
250 else
251 errx(EXIT_FAILURE, "%s(%i): invalid value \"%s\"", filename,
252 lines, p);
254 p = val + n;
255 *p = c;
257 while (*p && isspace(*p))
258 p++;
260 config.keys[k]->c = *p++;
261 config.keys[k++]->str = strdup(p);
262 config.keys[k] = NULL;
264 else if (strcmp(var, "engine_init") == 0) {
265 config.einit = Realloc(config.einit, (init + 2) * sizeof(char *));
266 config.einit[init++] = strdup(val);
267 config.einit[init] = NULL;
269 else if (strcmp(var, "pattern") == 0) {
270 free(config.pattern);
271 config.pattern = strdup(val);
273 else if (strcmp(var, "mpl") == 0) {
274 if (!isinteger(val))
275 errx(EXIT_FAILURE, "%s(%i): value is not an integer", filename,
276 lines);
277 pgn_config_set(PGN_MPL, (int *)atoi(val));
279 else if (strcmp(var, "stop_on_error") == 0)
280 pgn_config_set(PGN_STOP_ON_ERROR, (int *)on_or_off(filename, lines,
281 val));
282 else if (strcmp(var, "tag") == 0) {
283 if ((n = sscanf(val, "%s %s ", token, value)) < 1 ||
284 n > 2)
285 errx(EXIT_FAILURE, "%s(%i): invalid value \"%s\"", filename,
286 lines, val);
288 if (n == 1)
289 value[0] = 0;
290 else {
291 p = val + strlen(token);
292 strncpy(value, p, sizeof(value));
295 for (n = 0; n < strlen(token); n++) {
296 if (!isalnum(token[n]) && token[n] != '_')
297 errx(EXIT_FAILURE,
298 "%s(%i): token names must match 0-9A-Za-z_.",
299 filename, lines);
302 token[0] = toupper(token[0]);
303 pgn_tag_add(&config.tag, token, value);
305 else if (strcmp(var, "save_directory") == 0)
306 config.savedirectory = strdup(val);
307 else if (strcmp(var, "line_graphics") == 0)
308 config.linegraphics = on_or_off(filename, lines, val);
309 else if (strcmp(var, "save_prompt") == 0)
310 config.saveprompt = on_or_off(filename, lines, val);
311 else if (strcmp(var, "delete_prompt") == 0)
312 config.deleteprompt = on_or_off(filename, lines, val);
313 else if (strcmp(var, "valid_moves") == 0)
314 config.validmoves = on_or_off(filename, lines, val);
315 else if (strcmp(var, "board_details") == 0)
316 config.details = on_or_off(filename, lines, val);
317 else if (strcmp(var, "engine_cmd") == 0)
318 altengine = strdup(val);
319 else if (strcmp(var, "color_board_window") == 0)
320 parse_color(filename, lines, val, &config.color[CONF_BDWINDOW]);
321 else if (strcmp(var, "color_board_selected") == 0)
322 parse_color(filename, lines, val, &config.color[CONF_BSELECTED]);
323 else if (strcmp(var, "color_board_white_moves") == 0)
324 parse_color(filename, lines, val, &config.color[CONF_BMOVESW]);
325 else if (strcmp(var, "color_board_black_moves") == 0)
326 parse_color(filename, lines, val, &config.color[CONF_BMOVESB]);
327 else if (strcmp(var, "color_board_count") == 0)
328 parse_color(filename, lines, val, &config.color[CONF_BCOUNT]);
329 else if (strcmp(var, "color_board_cursor") == 0)
330 parse_color(filename, lines, val, &config.color[CONF_BCURSOR]);
331 else if (strcmp(var, "color_board_black") == 0)
332 parse_color(filename, lines, val, &config.color[CONF_BBLACK]);
333 else if (strcmp(var, "color_board_white") == 0)
334 parse_color(filename, lines, val, &config.color[CONF_BWHITE]);
335 else if (strcmp(var, "color_board_graphics") == 0)
336 parse_color(filename, lines, val, &config.color[CONF_BGRAPHICS]);
337 else if (strcmp(var, "color_board_coords") == 0)
338 parse_color(filename, lines, val, &config.color[CONF_BCOORDS]);
339 else if (strcmp(var, "color_status_window") == 0)
340 parse_color(filename, lines, val, &config.color[CONF_SWINDOW]);
341 else if (strcmp(var, "color_status_title") == 0)
342 parse_color(filename, lines, val, &config.color[CONF_STITLE]);
343 else if (strcmp(var, "color_status_border") == 0)
344 parse_color(filename, lines, val, &config.color[CONF_SBORDER]);
345 else if (strcmp(var, "color_status_notify") == 0)
346 parse_color(filename, lines, val, &config.color[CONF_SNOTIFY]);
347 else if (strcmp(var, "color_status_engine") == 0)
348 parse_color(filename, lines, val, &config.color[CONF_SENGINE]);
349 else if (strcmp(var, "color_tag_window") == 0)
350 parse_color(filename, lines, val, &config.color[CONF_TWINDOW]);
351 else if (strcmp(var, "color_tag_title") == 0)
352 parse_color(filename, lines, val, &config.color[CONF_TTITLE]);
353 else if (strcmp(var, "color_tag_border") == 0)
354 parse_color(filename, lines, val, &config.color[CONF_TBORDER]);
355 else if (strcmp(var, "color_history_window") == 0)
356 parse_color(filename, lines, val, &config.color[CONF_HWINDOW]);
357 else if (strcmp(var, "color_history_title") == 0)
358 parse_color(filename, lines, val, &config.color[CONF_HTITLE]);
359 else if (strcmp(var, "color_history_border") == 0)
360 parse_color(filename, lines, val, &config.color[CONF_HBORDER]);
361 else if (strcmp(var, "color_message_window") == 0)
362 parse_color(filename, lines, val, &config.color[CONF_MWINDOW]);
363 else if (strcmp(var, "color_message_title") == 0)
364 parse_color(filename, lines, val, &config.color[CONF_MTITLE]);
365 else if (strcmp(var, "color_message_border") == 0)
366 parse_color(filename, lines, val, &config.color[CONF_MBORDER]);
367 else if (strcmp(var, "color_message_prompt") == 0)
368 parse_color(filename, lines, val, &config.color[CONF_MPROMPT]);
369 else if (strcmp(var, "color_input_window") == 0)
370 parse_color(filename, lines, val, &config.color[CONF_IWINDOW]);
371 else if (strcmp(var, "color_input_title") == 0)
372 parse_color(filename, lines, val, &config.color[CONF_ITITLE]);
373 else if (strcmp(var, "color_input_border") == 0)
374 parse_color(filename, lines, val, &config.color[CONF_IBORDER]);
375 else if (strcmp(var, "color_input_prompt") == 0)
376 parse_color(filename, lines, val, &config.color[CONF_IPROMPT]);
377 else if (strcmp(var, "color_menu") == 0)
378 parse_color(filename, lines, val, &config.color[CONF_MENU]);
379 else if (strcmp(var, "color_menu_selected") == 0)
380 parse_color(filename, lines, val, &config.color[CONF_MENUS]);
381 else if (strcmp(var, "color_menu_highlight") == 0)
382 parse_color(filename, lines, val, &config.color[CONF_MENUH]);
383 else
384 errx(EXIT_FAILURE, "%s(%i): invalid parameter \"%s\"", filename,
385 lines, var);
388 fclose(fp);
390 if (altengine) {
391 free(config.engine_cmd);
392 config.engine_cmd = NULL;
393 config.engine_cmd = strdup(altengine);