1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2002-2013 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
27 #include <sys/types.h>
44 static int attributes(const char *filename
, int line
, char *str
)
49 while ((tmp
= strsep(&str
, ",")) != NULL
) {
50 if (strcasecmp(tmp
, "BOLD") == 0)
52 else if (strcasecmp(tmp
, "REVERSE") == 0)
54 else if (strcasecmp(tmp
, "NONE") == 0)
56 else if (strcasecmp(tmp
, "DIM") == 0)
58 else if (strcasecmp(tmp
, "STANDOUT") == 0)
60 else if (strcasecmp(tmp
, "UNDERLINE") == 0)
62 else if (strcasecmp(tmp
, "BLINK") == 0)
64 else if (strcasecmp(tmp
, "INVISIBLE") == 0)
67 errx(EXIT_FAILURE
, _("%s(%i): invalid attribute \"%s\""), filename
,
74 static short color_name(const char *filename
, int line
, const char *color
)
76 if (strcasecmp(color
, "BLACK") == 0)
78 else if (strcasecmp(color
, "WHITE") == 0)
80 else if (strcasecmp(color
, "GREEN") == 0)
82 else if (strcasecmp(color
, "YELLOW") == 0)
84 else if (strcasecmp(color
, "MAGENTA") == 0)
86 else if (strcasecmp(color
, "BLUE") == 0)
88 else if (strcasecmp(color
, "RED") == 0)
90 else if (strcasecmp(color
, "CYAN") == 0)
92 else if (strcasecmp(color
, "-") == 0)
95 errx(EXIT_FAILURE
, _("%s(%i): invalid color \"%s\""), filename
, line
,
101 static void parse_color(const char *filename
, int line
, const char *str
,
104 char fg
[16], bg
[16], attr
[64], nattr
[64];
107 if ((n
= sscanf(str
, "%[a-zA-Z-] %[a-zA-Z-] %[a-zA-Z,-] %[a-zA-Z,-]", fg
, bg
,
109 errx(EXIT_FAILURE
, _ ("%s(%i): parse error"), filename
, line
);
111 if ((n
= color_name(filename
, line
, fg
)) >= 0)
114 if ((n
= color_name(filename
, line
, bg
)) >= 0)
117 c
->attrs
= c
->nattrs
= 0;
120 c
->attrs
= attributes(filename
, line
, attr
);
123 c
->nattrs
= attributes(filename
, line
, nattr
);
126 static int on_or_off(const char *filename
, int lines
, const char *str
)
128 if (strcasecmp(str
, "on") == 0 || strcasecmp(str
, "1") == 0 ||
129 strcasecmp(str
, "yes") == 0 || strcasecmp(str
, "true") == 0)
132 if (strcasecmp(str
, "off") == 0 || strcasecmp(str
, "0") == 0 ||
133 strcasecmp(str
, "no") == 0 || strcasecmp(str
, "false") == 0)
136 errx(EXIT_FAILURE
, _("%s(%i): invalid value \"%s\""), filename
, lines
, str
);
139 void copydatafile(const char *dst
, const char *src
)
142 char buf
[LINE_MAX
], *s
;
144 snprintf(buf
, sizeof(buf
), "%s/%s", DATA_PATH
, src
);
146 if ((fp
= fopen(buf
, "r")) == NULL
) {
152 if ((ofp
= fopen(dst
, "w+")) == NULL
) {
158 while ((s
= fgets(buf
, sizeof(buf
), fp
)) != NULL
)
159 fprintf(ofp
, "%s", s
);
165 static char *fancy_key_name(wint_t c
)
167 static char buf
[64] = {0};
170 strncpy(buf
, keyname(c
) ? keyname (c
) : key_name (c
), sizeof(buf
)-1);
173 if (*p
== '^' && *(p
+ 1) == '[')
176 if (*p
== '^' && *(p
+ 1) == 'J')
179 if (strncasecmp(p
, "KEY_", 4) == 0) {
180 for (p
= buf
; *p
; p
++)
197 else if (strcmp(p
, "ppage") == 0)
199 else if (strcmp(p
, "npage") == 0)
212 void add_key_binding(struct key_s
***dst
, key_func
*func
, wint_t c
,
213 char *desc
, int repeat
)
216 struct key_s
**k
= *dst
;
219 for (i
= 0; k
[i
]; i
++);
221 k
= Realloc(k
, (i
+ 2) * sizeof(struct key_s
*));
222 k
[i
] = Calloc(1, sizeof(struct key_s
));
226 k
[i
]->key
= str_to_wchar (fancy_key_name(c
));
229 k
[i
]->d
= str_to_wchar(desc
);
236 void set_default_keys()
238 add_key_binding(&history_keys
, do_history_jump_next
, KEY_UP
, _("history jump next"), 1);
239 add_key_binding(&history_keys
, do_history_jump_prev
, KEY_DOWN
, _("history jump previous"), 1);
240 add_key_binding(&history_keys
, do_history_next
, KEY_RIGHT
, _("next move"), 1);
241 add_key_binding(&history_keys
, do_history_prev
, KEY_LEFT
, _("previous move"), 1);
242 add_key_binding(&history_keys
, do_history_half_move_toggle
, ' ', _("toggle half move (ply) stepping"), 0);
243 add_key_binding(&history_keys
, do_history_rotate_board
, 'r', _("rotate board"), 0);
244 add_key_binding(&history_keys
, do_history_jump
, 'j', _("jump to move number"), 1);
245 add_key_binding(&history_keys
, do_history_find_new
, '/', _("new move text expression"), 0);
246 add_key_binding(&history_keys
, do_history_find_next
, ']', _("find next move text expression"), 1);
247 add_key_binding(&history_keys
, do_history_find_prev
, '[', _("find previous move text expression"), 1);
248 add_key_binding(&history_keys
, do_history_annotate
, CTRL_KEY('a'), _("annotate the previous move"), 0);
249 add_key_binding(&history_keys
, do_history_rav_next
, '+', _("next variation of the previous move"), 0);
250 add_key_binding(&history_keys
, do_history_rav_prev
, '-', _("previous variation of the previous move"), 0);
251 add_key_binding(&history_keys
, do_history_menu
, 'M', _("move history tree"), 0);
252 add_key_binding(&history_keys
, do_history_help
, KEY_F(1), _("more help"), 0);
253 add_key_binding(&history_keys
, do_history_help
, CTRL_KEY('g'), NULL
, 0);
254 add_key_binding(&history_keys
, do_history_toggle
, 'h', _("exit history mode"), 0);
256 add_key_binding(&edit_keys
, do_edit_select
, ' ', _("select piece for movement"), 0);
257 add_key_binding(&edit_keys
, do_edit_commit
, '\n', _("commit selected piece"), 0);
258 add_key_binding(&edit_keys
, do_edit_cancel_selected
, KEY_ESCAPE
, _("cancel selected piece"), 0);
259 add_key_binding(&edit_keys
, do_edit_delete
, 'd', _("remove the piece under the cursor"), 0);
260 add_key_binding(&edit_keys
, do_edit_insert
, 'i', _("insert piece"), 0);
261 add_key_binding(&edit_keys
, do_edit_toggle_castle
, 'c', _("toggle castling availability"), 0);
262 add_key_binding(&edit_keys
, do_edit_enpassant
, 'p', _("toggle enpassant square"), 0);
263 add_key_binding(&edit_keys
, do_edit_switch_turn
, 'w', _("toggle turn"), 0);
264 add_key_binding(&edit_keys
, do_edit_help
, KEY_F(1), _("more help"), 0);
265 add_key_binding(&history_keys
, do_edit_help
, CTRL_KEY('g'), NULL
, 0);
266 add_key_binding(&edit_keys
, do_edit_exit
, 'e', _("exit edit mode"), 0);
268 add_key_binding(&play_keys
, do_play_select
, ' ', _("select piece for movement"), 0);
269 add_key_binding(&play_keys
, do_play_commit
, '\n', _("commit selected piece"), 0);
270 add_key_binding(&play_keys
, do_play_cancel_selected
, KEY_ESCAPE
, _("cancel selected piece"), 0);
271 add_key_binding(&play_keys
, do_play_set_clock
, 'C', _("set clock"), 0);
272 // add_key_binding(&play_keys, do_play_switch_turn, 'w', _("switch turn"), 0);
273 add_key_binding(&play_keys
, do_play_undo
, 'u', _("undo previous move"), 1);
274 add_key_binding(&play_keys
, do_play_go
, 'g', _("force the chess engine to make the next move"), 0);
275 add_key_binding(&play_keys
, do_play_send_command
, '|', _("send a command to the chess engine"), 0);
276 add_key_binding(&play_keys
, do_play_toggle_eh_mode
, 'w', _("toggle engine/human play"), 0);
277 add_key_binding(&play_keys
, do_play_toggle_engine
, 'E', _("toggle engine/engine play"), 0);
278 add_key_binding(&play_keys
, do_play_toggle_human
, 'H', _("toggle human/human play"), 0);
279 add_key_binding(&play_keys
, do_play_toggle_pause
, 'p', _("toggle pausing of this game"), 0);
280 add_key_binding(&play_keys
, do_play_history_mode
, 'h', _("enter history mode"), 0);
281 add_key_binding(&play_keys
, do_play_edit_mode
, 'e', _("enter edit mode"), 0);
282 add_key_binding(&play_keys
, do_play_help
, KEY_F(1), _("more help"), 0);
283 add_key_binding(&play_keys
, do_play_help
, CTRL_KEY('g'), NULL
, 0);
285 add_key_binding(&global_keys
, do_global_tag_edit
, CTRL_KEY('t'), _("edit roster tags"), 0);
286 add_key_binding(&global_keys
, do_global_tag_view
, 't', _("view roster tags"), 0);
287 add_key_binding(&global_keys
, do_global_find_new
, '?', _("new find game expression"), 0);
288 add_key_binding(&global_keys
, do_global_find_next
, '}', _("find next game"), 1);
289 add_key_binding(&global_keys
, do_global_find_prev
, '{', _("find previous game"), 1);
290 add_key_binding(&global_keys
, do_global_new_game
, CTRL_KEY('n'), _("new game or round"), 0);
291 add_key_binding(&global_keys
, do_global_new_all
, CTRL_KEY('k'), _("new game from scratch"), 0);
292 add_key_binding(&global_keys
, do_global_copy_game
, CTRL_KEY('i'), _("copy current game"), 0);
293 add_key_binding(&global_keys
, do_global_next_game
, '>', _("next game"), 1);
294 add_key_binding(&global_keys
, do_global_prev_game
, '<', _("previous game"), 1);
295 add_key_binding(&global_keys
, do_global_game_jump
, 'J', _("jump to game"), 1);
296 add_key_binding(&global_keys
, do_global_toggle_delete
, 'X', _("toggle delete flag"), 1);
297 add_key_binding(&global_keys
, do_global_delete_game
, CTRL_KEY('X'), _("delete the current or flagged games"), 0);
298 add_key_binding(&global_keys
, do_global_resume_game
, CTRL_KEY('r'), _("load a PGN file"), 0);
299 add_key_binding(&global_keys
, do_global_save_game
, 's', _("save game"), 0);
300 add_key_binding(&global_keys
, do_global_toggle_board_details
, CTRL_KEY('d'), _("toggle board details"), 0);
301 add_key_binding(&global_keys
, do_global_toggle_strict_castling
, CTRL_KEY('p'), _("toggle strict castling"), 0);
302 add_key_binding(&global_keys
, do_global_toggle_engine_window
, 'W', _("toggle chess engine IO window"), 0);
304 add_key_binding(&global_keys
, do_global_perl
, CTRL_KEY('O'), _("Call PERL subroutine"), 0);
306 add_key_binding(&global_keys
, do_global_about
, KEY_F(10), _("version information"), 0);
307 add_key_binding(&global_keys
, do_global_quit
, 'Q', _("quit"), 0);
310 void set_config_defaults()
314 config
.pattern
= strdup("*.[Pp][Gg][Nn]*");
315 config
.engine_cmd
= strdup("gnuchess --xboard");
316 config
.engine_protocol
= 1;
317 config
.jumpcount
= 5;
318 config
.linegraphics
= 1;
319 config
.saveprompt
= 1;
320 config
.deleteprompt
= 1;
321 config
.validmoves
= 1;
323 config
.showattacks
= 1;
324 config
.coordsyleft
= TRUE
;
325 config
.fmpolyglot
= FALSE
;
326 config
.boardleft
= TRUE
;
327 config
.exitdialogbox
= TRUE
;
328 config
.enginecmdblacktag
= TRUE
;
330 set_default_colors();
332 if (stat(config
.nagfile
, &st
) == -1) {
334 copydatafile(config
.nagfile
, "nag.data");
336 warn("%s", config
.nagfile
);
339 if (stat(config
.ccfile
, &st
) == -1) {
341 copydatafile(config
.ccfile
, "cc.data");
343 warn("%s", config
.ccfile
);
347 static void update_key(struct key_s
**dst
, struct custom_key_s config_key
,
348 wint_t c
, char *desc
)
352 for (i
= 0; dst
[i
]; i
++) {
353 if (dst
[i
]->f
== config_key
.func
) {
359 dst
[i
]->key
= str_to_wchar(fancy_key_name(c
));
362 dst
[i
]->d
= str_to_wchar(desc
);
369 add_key_binding(&dst
, config_key
.func
, c
,
370 (desc
) ? desc
: _("no description"), config_key
.r
);
376 static struct known_key_s
382 { KEY_DOWN
, "down" },
383 { KEY_LEFT
, "left" },
384 { KEY_RIGHT
, "right" },
385 { KEY_HOME
, "home" },
387 { KEY_DC
, "delete" },
388 { KEY_PPAGE
, "pgup" },
389 { KEY_NPAGE
, "pgdn" },
390 { KEY_IC
, "insert" },
392 { KEY_ESCAPE
, "escape" },
397 static wint_t parse_key(const char *filename
, int lines
, wchar_t **key
)
400 wchar_t *orig
= *key
;
403 if (!key
|| !wcslen (*key
))
407 if (orig
[wcslen(orig
) - 1] != '\"')
408 errx(EXIT_FAILURE
, _("%s(%i): unbalanced quotes"), filename
, lines
);
411 orig
[wcslen(orig
) - 1] = 0;
419 for (i
= 0; known_keys
[i
].name
; i
++) {
420 wchar_t *wc
= str_to_wchar (known_keys
[i
].name
);
422 if (!wcsncasecmp (p
, wc
, wcslen (wc
))) {
424 p
+= strlen (known_keys
[i
].name
);
437 else if (*p
== 'F' || *p
== 'f') {
438 char *str
= wchar_to_str (++p
);
440 c
= KEY_F(atoi(str
));
441 p
+= integer_len(atoi(str
));
450 errx(EXIT_FAILURE
, _("%s(%i): parse error \"%ls\""), filename
,
453 else if (*p
== '\\') {
460 orig
+= wcslen(orig
) - wcslen(p
);
465 static void parse_key_binding(const char *filename
, int lines
, char *val
)
467 char mode
[64], func
[64];
468 wchar_t desc
[64] = {0};
478 n
= sscanf(val
, "%s %ls %s %63lc", mode
, key
, func
, desc
);
481 errx(EXIT_FAILURE
, _ ("%s(%i): too few arguments"), filename
, lines
);
483 if (strcasecmp(mode
, "history") == 0)
485 else if (strcasecmp(mode
, "play") == 0)
487 else if (strcasecmp(mode
, "edit") == 0)
490 errx(EXIT_FAILURE
, _ ("%s(%i): invalid game mode \"%s\""), filename
,
494 c
= parse_key(filename
, lines
, &p
);
497 for (i
= 0; global_keys
[i
]; i
++) {
498 if (global_keys
[i
]->c
== c
)
500 _("%s(%i): key \"%ls\" conflicts with a global key"),
501 filename
, lines
, key
);
505 for (f
= -2, i
= 0; config_keys
[i
].name
; i
++) {
506 if (strcmp(config_keys
[i
].name
, func
) == 0 &&
507 config_keys
[i
].mode
== m
) {
514 errx(EXIT_FAILURE
, _("%s(%i): invalid command \"%s\""), filename
,
517 str
= wchar_to_str (desc
);
521 update_key(play_keys
, config_keys
[f
], c
, (n
> 3) ? str
: NULL
);
524 update_key(history_keys
, config_keys
[f
], c
, (n
> 3) ? str
: NULL
);
527 update_key(edit_keys
, config_keys
[f
], c
, (n
> 3) ? str
: NULL
);
530 update_key(global_keys
, config_keys
[f
], c
, (n
> 3) ? str
: NULL
);
537 static void parse_macro(const char *filename
, int lines
, char *val
)
540 wchar_t keys
[2048] = {0}, key
[8];
547 n
= sscanf(val
, "%s %ls %2047lc", mode
, key
, keys
);
550 errx(EXIT_FAILURE
, _("%s(%i): too few arguments"), filename
, lines
);
552 if (strcasecmp(mode
, "history") == 0)
554 else if (strcasecmp(mode
, "play") == 0)
556 else if (strcasecmp(mode
, "edit") == 0)
558 else if (strcasecmp(mode
, "any") == 0)
561 errx(EXIT_FAILURE
, _ ("%s(%i): invalid game mode \"%s\""), filename
,
565 c
= parse_key(filename
, lines
, &p
);
568 for (i
= 0; macros
[i
]; i
++);
570 macros
= Realloc(macros
, (i
+ 2) * sizeof(struct macro_s
));
571 macros
[i
] = Calloc(1, sizeof(struct macro_s
));
576 while ((c
= parse_key(filename
, lines
, &p
)) != 0) {
577 macros
[i
]->keys
= Realloc(macros
[i
]->keys
, (macros
[i
]->total
+ 2) *
579 macros
[i
]->keys
[macros
[i
]->total
++] = c
;
585 void parse_rcfile(const char *filename
)
588 char *line
, buf
[LINE_MAX
];
590 char *altengine
= NULL
;
595 if ((fp
= fopen(filename
, "r")) == NULL
)
596 err(EXIT_FAILURE
, "%s", filename
);
598 while ((line
= fgets(buf
, sizeof(buf
), fp
)) != NULL
) {
600 char var
[30] = {0}, val
[LINE_MAX
- sizeof(var
) - 1] = {0};
601 char token
[MAX_PGN_LINE_LEN
+ 1] = {0};
602 char value
[MAX_PGN_LINE_LEN
+ 1] = {0};
608 if (!line
[0] || line
[0] == '#')
611 if ((n
= sscanf(line
, "%s %[^\n]", var
, val
)) != 2)
612 errx(EXIT_FAILURE
, _("%s(%i): parse error %i"), filename
, lines
,n
);
614 p
= strdup(trim(val
));
615 strncpy(val
, p
, sizeof(val
)-1);
617 p
= strdup(trim(var
));
618 strncpy(var
, p
, sizeof(var
)-1);
621 if (strcmp(var
, "jump_count") == 0) {
623 errx(EXIT_FAILURE
, _("%s(%i): value is not an integer"), filename
,
626 config
.jumpcount
= atoi(val
);
628 else if (strcmp(var
, "engine_init") == 0) {
629 config
.einit
= Realloc(config
.einit
, (init
+ 2) * sizeof(char *));
630 config
.einit
[init
++] = strdup(val
);
631 config
.einit
[init
] = NULL
;
633 else if (strcmp(var
, "pattern") == 0) {
634 free(config
.pattern
);
635 config
.pattern
= strdup(val
);
637 else if (strcmp(var
, "mpl") == 0) {
639 errx(EXIT_FAILURE
, _("%s(%i): value is not an integer"),
641 pgn_config_set(PGN_MPL
, atoi(val
));
643 else if (strcmp(var
, "stop_on_error") == 0)
644 pgn_config_set(PGN_STOP_ON_ERROR
, on_or_off(filename
, lines
, val
));
645 else if (strcmp(var
, "tag") == 0) {
646 if ((n
= sscanf(val
, "%s %s ", token
, value
)) < 1 || n
> 2)
647 errx(EXIT_FAILURE
, _ ("%s(%i): invalid value \"%s\""), filename
,
653 p
= val
+ strlen(token
);
654 strncpy(value
, p
, sizeof(value
)-1);
657 for (n
= 0; n
< strlen(token
); n
++) {
658 if (!isalnum(token
[n
]) && token
[n
] != '_')
660 _ ("%s(%i): token names must match 0-9A-Za-z_."),
664 token
[0] = toupper(token
[0]);
665 pgn_tag_add(&config
.tag
, token
, value
);
667 else if (strcmp(var
, "save_directory") == 0)
668 config
.savedirectory
= strdup(val
);
669 else if (strcmp(var
, "line_graphics") == 0)
670 config
.linegraphics
= on_or_off(filename
, lines
, val
);
671 else if (strcmp(var
, "save_prompt") == 0)
672 config
.saveprompt
= on_or_off(filename
, lines
, val
);
673 else if (strcmp(var
, "delete_prompt") == 0)
674 config
.deleteprompt
= on_or_off(filename
, lines
, val
);
675 else if (strcmp(var
, "valid_moves") == 0)
676 config
.validmoves
= on_or_off(filename
, lines
, val
);
677 else if (strcmp(var
, "board_details") == 0)
678 config
.details
= on_or_off(filename
, lines
, val
);
679 else if (strcmp(var
, "show_attacks") == 0)
680 config
.showattacks
= on_or_off(filename
, lines
, val
);
681 else if (strcmp(var
, "coords_y_left") == 0 )
682 config
.coordsyleft
= on_or_off(filename
, lines
, val
);
683 else if (strcmp(var
, "fm_polyglot") == 0 )
684 config
.fmpolyglot
= on_or_off(filename
, lines
, val
);
685 else if (strcmp(var
, "board_left") == 0 )
686 config
.boardleft
= on_or_off(filename
, lines
, val
);
687 else if (strcmp(var
, "exit_dialog_box") == 0 )
688 config
.exitdialogbox
= on_or_off(filename
, lines
, val
);
689 else if (strcmp(var
, "engine_cmd_blacktag") == 0 )
690 config
.enginecmdblacktag
= on_or_off(filename
, lines
, val
);
691 else if (strcmp(var
, "strict_castling") == 0)
692 pgn_config_set(PGN_STRICT_CASTLING
, on_or_off(filename
, lines
, val
));
693 else if (strcmp(var
, "engine_cmd") == 0)
694 altengine
= strdup(val
);
695 else if (strcmp(var
, "engine_protocol") == 0) {
697 errx(EXIT_FAILURE
, _ ("%s(%i): value is not an integer"),
700 config
.engine_protocol
= atoi(val
);
702 if (config
.engine_protocol
!= 1 && config
.engine_protocol
!= 2)
703 errx(EXIT_FAILURE
, _ ("%s(%i): invalid value"), filename
, lines
);
705 else if (strcmp(var
, "utf8_pieces") == 0)
706 config
.utf8_pieces
= on_or_off (filename
, lines
, val
);
707 else if (strcmp(var
, "color_board_window") == 0)
708 parse_color(filename
, lines
, val
, &config
.color
[CONF_BDWINDOW
]);
709 else if (strcmp(var
, "color_board_selected") == 0)
710 parse_color(filename
, lines
, val
, &config
.color
[CONF_BSELECTED
]);
711 else if (strcmp(var
, "color_board_white_moves") == 0)
712 parse_color(filename
, lines
, val
, &config
.color
[CONF_BMOVESW
]);
713 else if (strcmp(var
, "color_board_black_moves") == 0)
714 parse_color(filename
, lines
, val
, &config
.color
[CONF_BMOVESB
]);
715 else if (strcmp(var
, "color_board_count") == 0)
716 parse_color(filename
, lines
, val
, &config
.color
[CONF_BCOUNT
]);
717 else if (strcmp(var
, "color_board_cursor") == 0)
718 parse_color(filename
, lines
, val
, &config
.color
[CONF_BCURSOR
]);
719 else if (strcmp(var
, "color_board_black") == 0)
720 parse_color(filename
, lines
, val
, &config
.color
[CONF_BBLACK
]);
721 else if (strcmp(var
, "color_board_white") == 0)
722 parse_color(filename
, lines
, val
, &config
.color
[CONF_BWHITE
]);
723 else if (strcmp(var
, "color_board_graphics") == 0)
724 parse_color(filename
, lines
, val
, &config
.color
[CONF_BGRAPHICS
]);
725 else if (strcmp(var
, "color_board_coords") == 0)
726 parse_color(filename
, lines
, val
, &config
.color
[CONF_BCOORDS
]);
727 else if (strcmp(var
, "color_board_castling") == 0)
728 parse_color(filename
, lines
, val
, &config
.color
[CONF_BCASTLING
]);
729 else if (strcmp(var
, "color_board_enpassant") == 0)
730 parse_color(filename
, lines
, val
, &config
.color
[CONF_BENPASSANT
]);
731 else if (strcmp(var
, "color_board_attack") == 0)
732 parse_color(filename
, lines
, val
, &config
.color
[CONF_BATTACK
]);
733 else if (strcmp(var
, "color_status_window") == 0)
734 parse_color(filename
, lines
, val
, &config
.color
[CONF_SWINDOW
]);
735 else if (strcmp(var
, "color_status_title") == 0)
736 parse_color(filename
, lines
, val
, &config
.color
[CONF_STITLE
]);
737 else if (strcmp(var
, "color_status_border") == 0)
738 parse_color(filename
, lines
, val
, &config
.color
[CONF_SBORDER
]);
739 else if (strcmp(var
, "color_status_notify") == 0)
740 parse_color(filename
, lines
, val
, &config
.color
[CONF_SNOTIFY
]);
741 else if (strcmp(var
, "color_status_engine") == 0)
742 parse_color(filename
, lines
, val
, &config
.color
[CONF_SENGINE
]);
743 else if (strcmp(var
, "color_tag_window") == 0)
744 parse_color(filename
, lines
, val
, &config
.color
[CONF_TWINDOW
]);
745 else if (strcmp(var
, "color_tag_title") == 0)
746 parse_color(filename
, lines
, val
, &config
.color
[CONF_TTITLE
]);
747 else if (strcmp(var
, "color_tag_border") == 0)
748 parse_color(filename
, lines
, val
, &config
.color
[CONF_TBORDER
]);
749 else if (strcmp(var
, "color_history_window") == 0)
750 parse_color(filename
, lines
, val
, &config
.color
[CONF_HWINDOW
]);
751 else if (strcmp(var
, "color_history_title") == 0)
752 parse_color(filename
, lines
, val
, &config
.color
[CONF_HTITLE
]);
753 else if (strcmp(var
, "color_history_border") == 0)
754 parse_color(filename
, lines
, val
, &config
.color
[CONF_HBORDER
]);
755 else if (strcmp(var
, "color_message_window") == 0)
756 parse_color(filename
, lines
, val
, &config
.color
[CONF_MWINDOW
]);
757 else if (strcmp(var
, "color_message_title") == 0)
758 parse_color(filename
, lines
, val
, &config
.color
[CONF_MTITLE
]);
759 else if (strcmp(var
, "color_message_border") == 0)
760 parse_color(filename
, lines
, val
, &config
.color
[CONF_MBORDER
]);
761 else if (strcmp(var
, "color_message_prompt") == 0)
762 parse_color(filename
, lines
, val
, &config
.color
[CONF_MPROMPT
]);
763 else if (strcmp(var
, "color_input_window") == 0)
764 parse_color(filename
, lines
, val
, &config
.color
[CONF_IWINDOW
]);
765 else if (strcmp(var
, "color_input_title") == 0)
766 parse_color(filename
, lines
, val
, &config
.color
[CONF_ITITLE
]);
767 else if (strcmp(var
, "color_input_border") == 0)
768 parse_color(filename
, lines
, val
, &config
.color
[CONF_IBORDER
]);
769 else if (strcmp(var
, "color_input_prompt") == 0)
770 parse_color(filename
, lines
, val
, &config
.color
[CONF_IPROMPT
]);
771 else if (strcmp(var
, "color_menu") == 0)
772 parse_color(filename
, lines
, val
, &config
.color
[CONF_MENU
]);
773 else if (strcmp(var
, "color_menu_selected") == 0)
774 parse_color(filename
, lines
, val
, &config
.color
[CONF_MENUS
]);
775 else if (strcmp(var
, "color_menu_highlight") == 0)
776 parse_color(filename
, lines
, val
, &config
.color
[CONF_MENUH
]);
777 else if (strcmp(var
, "color_menu_graphics") == 0)
778 parse_color(filename
, lines
, val
,
779 &config
.color
[CONF_HISTORY_MENU_LG
]);
780 else if (strcmp(var
, "bind") == 0)
781 parse_key_binding(filename
, lines
, val
);
782 else if (strcmp(var
, "macro") == 0)
783 parse_macro(filename
, lines
, val
);
784 else if (strcmp(var
, "cbind") == 0) {
785 config
.keys
= Realloc(config
.keys
, (k
+ 2) *
786 sizeof(struct config_key_s
*));
787 config
.keys
[k
] = Calloc(1, sizeof(struct config_key_s
));
791 while (*p
&& !isspace(*p
))
798 if (strcasecmp(p
, "none") == 0)
799 config
.keys
[k
]->type
= KEY_DEFAULT
;
800 else if (strcasecmp(p
, "repeat") == 0)
801 config
.keys
[k
]->type
= KEY_REPEAT
;
802 else if (strcasecmp(p
, "set") == 0)
803 config
.keys
[k
]->type
= KEY_SET
;
805 errx(EXIT_FAILURE
, _ ("%s(%i): invalid value \"%s\""), filename
,
811 while (*p
&& isspace(*p
))
814 config
.keys
[k
]->c
= *p
++;
819 config
.keys
[k
++]->str
= str_to_wchar (p
);
820 config
.keys
[k
] = NULL
;
823 errx(EXIT_FAILURE
, _ ("%s(%i): invalid parameter \"%s\""), filename
,
830 free(config
.engine_cmd
);
831 config
.engine_cmd
= NULL
;
832 config
.engine_cmd
= altengine
;
835 if (config
.enginecmdblacktag
)
836 pgn_tag_add(&config
.tag
, "Black", config
.engine_cmd
);