1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2002-2011 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>
34 #elif defined(HAVE_CURSES_H)
53 static int attributes(const char *filename
, int line
, char *str
)
58 while ((tmp
= strsep(&str
, ",")) != NULL
) {
59 if (strcasecmp(tmp
, "BOLD") == 0)
61 else if (strcasecmp(tmp
, "REVERSE") == 0)
63 else if (strcasecmp(tmp
, "NONE") == 0)
65 else if (strcasecmp(tmp
, "DIM") == 0)
67 else if (strcasecmp(tmp
, "STANDOUT") == 0)
69 else if (strcasecmp(tmp
, "UNDERLINE") == 0)
71 else if (strcasecmp(tmp
, "BLINK") == 0)
73 else if (strcasecmp(tmp
, "INVISIBLE") == 0)
76 errx(EXIT_FAILURE
, "%s(%i): invalid attribute \"%s\"", filename
,
83 static short color_name(const char *filename
, int line
, const char *color
)
85 if (strcasecmp(color
, "BLACK") == 0)
87 else if (strcasecmp(color
, "WHITE") == 0)
89 else if (strcasecmp(color
, "GREEN") == 0)
91 else if (strcasecmp(color
, "YELLOW") == 0)
93 else if (strcasecmp(color
, "MAGENTA") == 0)
95 else if (strcasecmp(color
, "BLUE") == 0)
97 else if (strcasecmp(color
, "RED") == 0)
99 else if (strcasecmp(color
, "CYAN") == 0)
101 else if (strcasecmp(color
, "-") == 0)
104 errx(EXIT_FAILURE
, "%s(%i): invalid color \"%s\"", filename
, line
,
110 static void parse_color(const char *filename
, int line
, const char *str
,
113 char fg
[16], bg
[16], attr
[64], nattr
[64];
116 if ((n
= sscanf(str
, "%[a-zA-Z-] %[a-zA-Z-] %[a-zA-Z,-] %[a-zA-Z,-]", fg
, bg
,
118 errx(EXIT_FAILURE
, "%s(%i): parse error", filename
, line
);
120 if ((n
= color_name(filename
, line
, fg
)) >= 0)
123 if ((n
= color_name(filename
, line
, bg
)) >= 0)
126 c
->attrs
= c
->nattrs
= 0;
129 c
->attrs
= attributes(filename
, line
, attr
);
132 c
->nattrs
= attributes(filename
, line
, nattr
);
135 static int on_or_off(const char *filename
, int lines
, const char *str
)
137 if (strcasecmp(str
, "on") == 0 || strcasecmp(str
, "1") == 0 ||
138 strcasecmp(str
, "yes") == 0 || strcasecmp(str
, "true") == 0)
141 if (strcasecmp(str
, "off") == 0 || strcasecmp(str
, "0") == 0 ||
142 strcasecmp(str
, "no") == 0 || strcasecmp(str
, "false") == 0)
145 errx(EXIT_FAILURE
, "%s(%i): invalid value \"%s\"", filename
, lines
, str
);
148 void copydatafile(const char *dst
, const char *src
)
151 char buf
[LINE_MAX
], *s
;
153 snprintf(buf
, sizeof(buf
), "%s/%s", DATA_PATH
, src
);
155 if ((fp
= fopen(buf
, "r")) == NULL
) {
161 if ((ofp
= fopen(dst
, "w+")) == NULL
) {
167 while ((s
= fgets(buf
, sizeof(buf
), fp
)) != NULL
)
168 fprintf(ofp
, "%s", s
);
174 static char *fancy_key_name(int c
)
179 strncpy(buf
, keyname(c
), sizeof(buf
));
182 if (*p
== '^' && *(p
+ 1) == '[')
185 if (*p
== '^' && *(p
+ 1) == 'J')
188 if (strncasecmp(p
, "KEY_", 4) == 0) {
189 for (p
= buf
; *p
; p
++)
206 else if (strcmp(p
, "ppage") == 0)
208 else if (strcmp(p
, "npage") == 0)
221 void add_key_binding(struct key_s
***dst
, key_func
*func
, int c
, char *desc
,
225 struct key_s
**k
= *dst
;
228 for (i
= 0; k
[i
]; i
++);
230 k
= Realloc(k
, (i
+ 2) * sizeof(struct key_s
*));
231 k
[i
] = Calloc(1, sizeof(struct key_s
));
235 k
[i
]->key
= strdup(fancy_key_name(c
));
238 k
[i
]->d
= strdup(desc
);
245 void set_default_keys()
247 add_key_binding(&history_keys
, do_history_jump_next
, KEY_UP
, "history jump next", 1);
248 add_key_binding(&history_keys
, do_history_jump_prev
, KEY_DOWN
, "history jump previous", 1);
249 add_key_binding(&history_keys
, do_history_next
, KEY_RIGHT
, "next move", 1);
250 add_key_binding(&history_keys
, do_history_prev
, KEY_LEFT
, "previous move", 1);
251 add_key_binding(&history_keys
, do_history_half_move_toggle
, ' ', "toggle half move (ply) stepping", 0);
252 add_key_binding(&history_keys
, do_history_jump
, 'j', "jump to move number", 1);
253 add_key_binding(&history_keys
, do_history_find_new
, '/', "new move text expression", 0);
254 add_key_binding(&history_keys
, do_history_find_next
, ']', "find next move text expression", 1);
255 add_key_binding(&history_keys
, do_history_find_prev
, '[', "find previous move text expression", 1);
256 add_key_binding(&history_keys
, do_history_annotate
, CTRL('a'), "annotate the previous move", 0);
257 add_key_binding(&history_keys
, do_history_rav_next
, '+', "next variation of the previous move", 0);
258 add_key_binding(&history_keys
, do_history_rav_prev
, '-', "previous variation of the previous move", 0);
259 add_key_binding(&history_keys
, do_history_menu
, 'M', "move history tree", 0);
260 add_key_binding(&history_keys
, do_history_help
, KEY_F(1), "more help", 0);
261 add_key_binding(&history_keys
, do_history_help
, CTRL('g'), NULL
, 0);
262 add_key_binding(&history_keys
, do_history_toggle
, 'h', "exit history mode", 0);
264 add_key_binding(&edit_keys
, do_edit_select
, ' ', "select piece for movement", 0);
265 add_key_binding(&edit_keys
, do_edit_commit
, '\n', "commit selected piece", 0);
266 add_key_binding(&edit_keys
, do_edit_cancel_selected
, KEY_ESCAPE
, "cancel selected piece", 0);
267 add_key_binding(&edit_keys
, do_edit_delete
, 'd', "remove the piece under the cursor", 0);
268 add_key_binding(&edit_keys
, do_edit_insert
, 'i', "insert piece", 0);
269 add_key_binding(&edit_keys
, do_edit_toggle_castle
, 'c', "toggle castling availability", 0);
270 add_key_binding(&edit_keys
, do_edit_enpassant
, 'p', "toggle enpassant square", 0);
271 add_key_binding(&edit_keys
, do_edit_switch_turn
, 'w', "toggle turn", 0);
272 add_key_binding(&edit_keys
, do_edit_help
, KEY_F(1), "more help", 0);
273 add_key_binding(&history_keys
, do_edit_help
, CTRL('g'), NULL
, 0);
274 add_key_binding(&edit_keys
, do_edit_exit
, 'e', "exit edit mode", 0);
276 add_key_binding(&play_keys
, do_play_select
, ' ', "select piece for movement", 0);
277 add_key_binding(&play_keys
, do_play_commit
, '\n', "commit selected piece", 0);
278 add_key_binding(&play_keys
, do_play_cancel_selected
, KEY_ESCAPE
, "cancel selected piece", 0);
279 add_key_binding(&play_keys
, do_play_set_clock
, 'C', "set clock", 0);
280 add_key_binding(&play_keys
, do_play_switch_turn
, 'w', "switch turn", 0);
281 add_key_binding(&play_keys
, do_play_undo
, 'u', "undo previous move", 1);
282 add_key_binding(&play_keys
, do_play_go
, 'g', "force the chess engine to make the next move", 0);
283 add_key_binding(&play_keys
, do_play_send_command
, '|', "send a command to the chess engine", 0);
284 add_key_binding(&play_keys
, do_play_toggle_engine
, 'E', "toggle engine/engine play", 0);
285 add_key_binding(&play_keys
, do_play_toggle_human
, 'H', "toggle human/human play", 0);
286 add_key_binding(&play_keys
, do_play_toggle_pause
, 'p', "toggle pausing of this game", 0);
287 add_key_binding(&play_keys
, do_play_history_mode
, 'h', "enter history mode", 0);
288 add_key_binding(&play_keys
, do_play_edit_mode
, 'e', "enter edit mode", 0);
289 add_key_binding(&play_keys
, do_play_help
, KEY_F(1), "more help", 0);
290 add_key_binding(&play_keys
, do_play_help
, CTRL('g'), NULL
, 0);
292 add_key_binding(&global_keys
, do_global_tag_edit
, CTRL('t'), "edit roster tags", 0);
293 add_key_binding(&global_keys
, do_global_tag_view
, 't', "view roster tags", 0);
294 add_key_binding(&global_keys
, do_global_find_new
, '?', "new find game expression", 0);
295 add_key_binding(&global_keys
, do_global_find_next
, '}', "find next game", 1);
296 add_key_binding(&global_keys
, do_global_find_prev
, '{', "find previous game", 1);
297 add_key_binding(&global_keys
, do_global_new_game
, CTRL('n'), "new game or round", 0);
298 add_key_binding(&global_keys
, do_global_new_all
, CTRL('k'), "new game from scratch", 0);
299 add_key_binding(&global_keys
, do_global_copy_game
, CTRL('i'), "copy current game", 0);
300 add_key_binding(&global_keys
, do_global_next_game
, '>', "next game", 1);
301 add_key_binding(&global_keys
, do_global_prev_game
, '<', "previous game", 1);
302 add_key_binding(&global_keys
, do_global_game_jump
, 'J', "jump to game", 1);
303 add_key_binding(&global_keys
, do_global_toggle_delete
, 'X', "toggle delete flag", 1);
304 add_key_binding(&global_keys
, do_global_delete_game
, CTRL('X'), "delete the current or flagged games", 0);
305 add_key_binding(&global_keys
, do_global_resume_game
, CTRL('r'), "load a PGN file", 0);
306 add_key_binding(&global_keys
, do_global_save_game
, 's', "save game", 0);
307 add_key_binding(&global_keys
, do_global_toggle_board_details
, CTRL('d'), "toggle board details", 0);
308 add_key_binding(&global_keys
, do_global_toggle_strict_castling
, CTRL('p'), "toggle strict castling", 0);
309 add_key_binding(&global_keys
, do_global_toggle_engine_window
, 'W', "toggle chess engine IO window", 0);
311 add_key_binding(&global_keys
, do_global_perl
, CTRL('O'), "Call PERL subroutine", 0);
313 add_key_binding(&global_keys
, do_global_about
, KEY_F(10), "version information", 0);
314 add_key_binding(&global_keys
, do_global_quit
, 'Q', "quit", 0);
317 void set_config_defaults()
321 config
.pattern
= strdup("*.[Pp][Gg][Nn]*");
322 config
.engine_cmd
= strdup("gnuchess --xboard");
323 config
.engine_protocol
= 1;
324 config
.jumpcount
= 5;
325 config
.linegraphics
= 1;
326 config
.saveprompt
= 1;
327 config
.deleteprompt
= 1;
328 config
.validmoves
= 1;
331 set_default_colors();
333 if (stat(config
.nagfile
, &st
) == -1) {
335 copydatafile(config
.nagfile
, "nag.data");
337 warn("%s", config
.nagfile
);
340 if (stat(config
.ccfile
, &st
) == -1) {
342 copydatafile(config
.ccfile
, "cc.data");
344 warn("%s", config
.ccfile
);
348 static void update_key(struct key_s
**dst
, struct custom_key_s config_key
,
353 for (i
= 0; dst
[i
]; i
++) {
354 if (dst
[i
]->f
== config_key
.func
) {
360 dst
[i
]->key
= strdup(fancy_key_name(c
));
362 if (desc
&& dst
[i
]->d
)
366 dst
[i
]->d
= strdup(desc
);
372 add_key_binding(&dst
, config_key
.func
, c
, (desc
) ? desc
: "no description",
379 static int parse_key(const char *filename
, int lines
, char **key
)
389 if (orig
[strlen(orig
) - 1] != '\"')
390 errx(EXIT_FAILURE
, "%s(%i): unbalanced quotes", filename
, lines
);
393 orig
[strlen(orig
) - 1] = 0;
399 if (strncasecmp(p
, "up", 2) == 0) {
403 else if (strncasecmp(p
, "down", 4) == 0) {
407 else if (strncasecmp(p
, "left", 4) == 0) {
411 else if (strncasecmp(p
, "right", 5) == 0) {
415 else if (strncasecmp(p
, "home", 4) == 0) {
419 else if (strncasecmp(p
, "end", 3) == 0) {
423 else if (strncasecmp(p
, "delete", 6) == 0) {
427 else if (strncasecmp(p
, "pgup", 4) == 0) {
431 else if (strncasecmp(p
, "pgdn", 4) == 0) {
435 else if (strncasecmp(p
, "insert", 5) == 0) {
439 else if (strncasecmp(p
, "space", 5) == 0) {
443 else if (strncasecmp(p
, "escape", 6) == 0) {
447 else if (strncasecmp(p
, "enter", 5) == 0) {
451 else if (*p
== '^') {
455 else if (*p
== 'F' || *p
== 'f') {
456 c
= KEY_F(atoi(++p
));
457 p
+= integer_len(atoi(p
));
464 errx(EXIT_FAILURE
, "%s(%i): parse error \"%s\"", filename
, lines
,
467 else if (*p
== '\\') {
474 orig
+= strlen(orig
) - strlen(p
);
479 static void parse_key_binding(const char *filename
, int lines
, char *val
)
481 char mode
[64], key
[16], func
[64], desc
[64];
489 n
= sscanf(val
, "%s %s %s %s", mode
, key
, func
, desc
);
492 errx(EXIT_FAILURE
, "%s(%i): too few arguments", filename
, lines
);
494 if (strcasecmp(mode
, "history") == 0)
496 else if (strcasecmp(mode
, "play") == 0)
498 else if (strcasecmp(mode
, "edit") == 0)
501 errx(EXIT_FAILURE
, "%s(%i): invalid game mode \"%s\"", filename
, lines
,
505 c
= parse_key(filename
, lines
, &p
);
508 for (i
= 0; global_keys
[i
]; i
++) {
509 if (global_keys
[i
]->c
== c
)
510 errx(EXIT_FAILURE
, "%s(%i): key \"%s\" conflicts with a global "
511 "key", filename
, lines
, key
);
515 for (f
= -2, i
= 0; config_keys
[i
].name
; i
++) {
516 if (strcmp(config_keys
[i
].name
, func
) == 0 &&
517 config_keys
[i
].mode
== m
) {
524 errx(EXIT_FAILURE
, "%s(%i): invalid command \"%s\"", filename
, lines
,
529 update_key(play_keys
, config_keys
[f
], c
, (n
> 3) ? desc
: NULL
);
532 update_key(history_keys
, config_keys
[f
], c
, (n
> 3) ? desc
: NULL
);
535 update_key(edit_keys
, config_keys
[f
], c
, (n
> 3) ? desc
: NULL
);
538 update_key(global_keys
, config_keys
[f
], c
, (n
> 3) ? desc
: NULL
);
543 static void parse_macro(const char *filename
, int lines
, char *val
)
545 char mode
[16], key
[8], keys
[256] = {0};
552 n
= sscanf(val
, "%s %s %255c", mode
, key
, keys
);
555 errx(EXIT_FAILURE
, "%s(%i): too few arguments", filename
, lines
);
557 if (strcasecmp(mode
, "history") == 0)
559 else if (strcasecmp(mode
, "play") == 0)
561 else if (strcasecmp(mode
, "edit") == 0)
563 else if (strcasecmp(mode
, "any") == 0)
566 errx(EXIT_FAILURE
, "%s(%i): invalid game mode \"%s\"", filename
, lines
,
570 c
= parse_key(filename
, lines
, &p
);
573 for (i
= 0; macros
[i
]; i
++);
575 macros
= Realloc(macros
, (i
+ 2) * sizeof(struct macro_s
));
576 macros
[i
] = Calloc(1, sizeof(struct macro_s
));
581 while ((c
= parse_key(filename
, lines
, &p
)) != 0) {
582 macros
[i
]->keys
= Realloc(macros
[i
]->keys
, (macros
[i
]->total
+ 2) *
584 macros
[i
]->keys
[macros
[i
]->total
++] = c
;
590 void parse_rcfile(const char *filename
)
593 char *line
, buf
[LINE_MAX
];
595 char *altengine
= NULL
;
600 if ((fp
= fopen(filename
, "r")) == NULL
)
601 err(EXIT_FAILURE
, "%s", filename
);
603 while ((line
= fgets(buf
, sizeof(buf
), fp
)) != NULL
) {
605 char var
[30], val
[LINE_MAX
- sizeof(var
) - 1];
606 char token
[MAX_PGN_LINE_LEN
+ 1], value
[MAX_PGN_LINE_LEN
+ 1];
612 if (!line
[0] || line
[0] == '#')
615 if ((n
= sscanf(line
, "%s %[^\n]", var
, val
)) != 2)
616 errx(EXIT_FAILURE
, "%s(%i): parse error %i", filename
, lines
,n
);
618 p
= strdup(trim(val
));
619 strncpy(val
, p
, sizeof(val
));
621 p
= strdup(trim(var
));
622 strncpy(var
, p
, sizeof(var
));
625 if (strcmp(var
, "jump_count") == 0) {
627 errx(EXIT_FAILURE
, "%s(%i): value is not an integer", filename
,
630 config
.jumpcount
= atoi(val
);
632 else if (strcmp(var
, "engine_init") == 0) {
633 config
.einit
= Realloc(config
.einit
, (init
+ 2) * sizeof(char *));
634 config
.einit
[init
++] = strdup(val
);
635 config
.einit
[init
] = NULL
;
637 else if (strcmp(var
, "pattern") == 0) {
638 free(config
.pattern
);
639 config
.pattern
= strdup(val
);
641 else if (strcmp(var
, "mpl") == 0) {
643 errx(EXIT_FAILURE
, "%s(%i): value is not an integer", filename
,
645 pgn_config_set(PGN_MPL
, atoi(val
));
647 else if (strcmp(var
, "stop_on_error") == 0)
648 pgn_config_set(PGN_STOP_ON_ERROR
, on_or_off(filename
, lines
, val
));
649 else if (strcmp(var
, "tag") == 0) {
650 if ((n
= sscanf(val
, "%s %s ", token
, value
)) < 1 ||
652 errx(EXIT_FAILURE
, "%s(%i): invalid value \"%s\"", filename
,
658 p
= val
+ strlen(token
);
659 strncpy(value
, p
, sizeof(value
));
662 for (n
= 0; n
< strlen(token
); n
++) {
663 if (!isalnum(token
[n
]) && token
[n
] != '_')
665 "%s(%i): token names must match 0-9A-Za-z_.",
669 token
[0] = toupper(token
[0]);
670 pgn_tag_add(&config
.tag
, token
, value
);
672 else if (strcmp(var
, "save_directory") == 0)
673 config
.savedirectory
= strdup(val
);
674 else if (strcmp(var
, "line_graphics") == 0)
675 config
.linegraphics
= on_or_off(filename
, lines
, val
);
676 else if (strcmp(var
, "save_prompt") == 0)
677 config
.saveprompt
= on_or_off(filename
, lines
, val
);
678 else if (strcmp(var
, "delete_prompt") == 0)
679 config
.deleteprompt
= on_or_off(filename
, lines
, val
);
680 else if (strcmp(var
, "valid_moves") == 0)
681 config
.validmoves
= on_or_off(filename
, lines
, val
);
682 else if (strcmp(var
, "board_details") == 0)
683 config
.details
= on_or_off(filename
, lines
, val
);
684 else if (strcmp(var
, "strict_castling") == 0)
685 pgn_config_set(PGN_STRICT_CASTLING
, on_or_off(filename
, lines
, val
));
686 else if (strcmp(var
, "engine_cmd") == 0)
687 altengine
= strdup(val
);
688 else if (strcmp(var
, "engine_protocol") == 0) {
690 errx(EXIT_FAILURE
, "%s(%i): value is not an integer", filename
,
693 config
.engine_protocol
= atoi(val
);
695 if (config
.engine_protocol
!= 1 && config
.engine_protocol
!= 2)
696 errx(EXIT_FAILURE
, "%s(%i): invalid value", filename
, lines
);
698 else if (strcmp(var
, "color_board_window") == 0)
699 parse_color(filename
, lines
, val
, &config
.color
[CONF_BDWINDOW
]);
700 else if (strcmp(var
, "color_board_selected") == 0)
701 parse_color(filename
, lines
, val
, &config
.color
[CONF_BSELECTED
]);
702 else if (strcmp(var
, "color_board_white_moves") == 0)
703 parse_color(filename
, lines
, val
, &config
.color
[CONF_BMOVESW
]);
704 else if (strcmp(var
, "color_board_black_moves") == 0)
705 parse_color(filename
, lines
, val
, &config
.color
[CONF_BMOVESB
]);
706 else if (strcmp(var
, "color_board_count") == 0)
707 parse_color(filename
, lines
, val
, &config
.color
[CONF_BCOUNT
]);
708 else if (strcmp(var
, "color_board_cursor") == 0)
709 parse_color(filename
, lines
, val
, &config
.color
[CONF_BCURSOR
]);
710 else if (strcmp(var
, "color_board_black") == 0)
711 parse_color(filename
, lines
, val
, &config
.color
[CONF_BBLACK
]);
712 else if (strcmp(var
, "color_board_white") == 0)
713 parse_color(filename
, lines
, val
, &config
.color
[CONF_BWHITE
]);
714 else if (strcmp(var
, "color_board_graphics") == 0)
715 parse_color(filename
, lines
, val
, &config
.color
[CONF_BGRAPHICS
]);
716 else if (strcmp(var
, "color_board_coords") == 0)
717 parse_color(filename
, lines
, val
, &config
.color
[CONF_BCOORDS
]);
718 else if (strcmp(var
, "color_board_castling") == 0)
719 parse_color(filename
, lines
, val
, &config
.color
[CONF_BCASTLING
]);
720 else if (strcmp(var
, "color_board_enpassant") == 0)
721 parse_color(filename
, lines
, val
, &config
.color
[CONF_BENPASSANT
]);
722 else if (strcmp(var
, "color_status_window") == 0)
723 parse_color(filename
, lines
, val
, &config
.color
[CONF_SWINDOW
]);
724 else if (strcmp(var
, "color_status_title") == 0)
725 parse_color(filename
, lines
, val
, &config
.color
[CONF_STITLE
]);
726 else if (strcmp(var
, "color_status_border") == 0)
727 parse_color(filename
, lines
, val
, &config
.color
[CONF_SBORDER
]);
728 else if (strcmp(var
, "color_status_notify") == 0)
729 parse_color(filename
, lines
, val
, &config
.color
[CONF_SNOTIFY
]);
730 else if (strcmp(var
, "color_status_engine") == 0)
731 parse_color(filename
, lines
, val
, &config
.color
[CONF_SENGINE
]);
732 else if (strcmp(var
, "color_tag_window") == 0)
733 parse_color(filename
, lines
, val
, &config
.color
[CONF_TWINDOW
]);
734 else if (strcmp(var
, "color_tag_title") == 0)
735 parse_color(filename
, lines
, val
, &config
.color
[CONF_TTITLE
]);
736 else if (strcmp(var
, "color_tag_border") == 0)
737 parse_color(filename
, lines
, val
, &config
.color
[CONF_TBORDER
]);
738 else if (strcmp(var
, "color_history_window") == 0)
739 parse_color(filename
, lines
, val
, &config
.color
[CONF_HWINDOW
]);
740 else if (strcmp(var
, "color_history_title") == 0)
741 parse_color(filename
, lines
, val
, &config
.color
[CONF_HTITLE
]);
742 else if (strcmp(var
, "color_history_border") == 0)
743 parse_color(filename
, lines
, val
, &config
.color
[CONF_HBORDER
]);
744 else if (strcmp(var
, "color_message_window") == 0)
745 parse_color(filename
, lines
, val
, &config
.color
[CONF_MWINDOW
]);
746 else if (strcmp(var
, "color_message_title") == 0)
747 parse_color(filename
, lines
, val
, &config
.color
[CONF_MTITLE
]);
748 else if (strcmp(var
, "color_message_border") == 0)
749 parse_color(filename
, lines
, val
, &config
.color
[CONF_MBORDER
]);
750 else if (strcmp(var
, "color_message_prompt") == 0)
751 parse_color(filename
, lines
, val
, &config
.color
[CONF_MPROMPT
]);
752 else if (strcmp(var
, "color_input_window") == 0)
753 parse_color(filename
, lines
, val
, &config
.color
[CONF_IWINDOW
]);
754 else if (strcmp(var
, "color_input_title") == 0)
755 parse_color(filename
, lines
, val
, &config
.color
[CONF_ITITLE
]);
756 else if (strcmp(var
, "color_input_border") == 0)
757 parse_color(filename
, lines
, val
, &config
.color
[CONF_IBORDER
]);
758 else if (strcmp(var
, "color_input_prompt") == 0)
759 parse_color(filename
, lines
, val
, &config
.color
[CONF_IPROMPT
]);
760 else if (strcmp(var
, "color_menu") == 0)
761 parse_color(filename
, lines
, val
, &config
.color
[CONF_MENU
]);
762 else if (strcmp(var
, "color_menu_selected") == 0)
763 parse_color(filename
, lines
, val
, &config
.color
[CONF_MENUS
]);
764 else if (strcmp(var
, "color_menu_highlight") == 0)
765 parse_color(filename
, lines
, val
, &config
.color
[CONF_MENUH
]);
766 else if (strcmp(var
, "color_menu_graphics") == 0)
767 parse_color(filename
, lines
, val
,
768 &config
.color
[CONF_HISTORY_MENU_LG
]);
769 else if (strcmp(var
, "bind") == 0)
770 parse_key_binding(filename
, lines
, val
);
771 else if (strcmp(var
, "macro") == 0)
772 parse_macro(filename
, lines
, val
);
773 else if (strcmp(var
, "cbind") == 0) {
774 config
.keys
= Realloc(config
.keys
, (k
+ 2) *
775 sizeof(struct config_key_s
*));
776 config
.keys
[k
] = Calloc(1, sizeof(struct config_key_s
));
780 while (*p
&& !isspace(*p
))
787 if (strcasecmp(p
, "none") == 0)
788 config
.keys
[k
]->type
= KEY_DEFAULT
;
789 else if (strcasecmp(p
, "repeat") == 0)
790 config
.keys
[k
]->type
= KEY_REPEAT
;
791 else if (strcasecmp(p
, "set") == 0)
792 config
.keys
[k
]->type
= KEY_SET
;
794 errx(EXIT_FAILURE
, "%s(%i): invalid value \"%s\"", filename
,
800 while (*p
&& isspace(*p
))
803 config
.keys
[k
]->c
= *p
++;
808 config
.keys
[k
++]->str
= strdup(p
);
809 config
.keys
[k
] = NULL
;
812 errx(EXIT_FAILURE
, "%s(%i): invalid parameter \"%s\"", filename
,
819 free(config
.engine_cmd
);
820 config
.engine_cmd
= NULL
;
821 config
.engine_cmd
= altengine
;