From d6093b3a7d57aa34d3ee2a84112c59328bf1feed Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Tue, 28 Jan 2014 04:25:45 +0100 Subject: [PATCH] Client: Added checks / syntax validation for config files. Also changed commands config file format to simplify doing those checks. --- confclient/commands | 220 ++++++++++++++++++++++++++++++--------- src/client/command_db.c | 96 ++++++----------- src/client/command_db.h | 4 +- src/client/keybindings.c | 39 +++++-- src/client/keybindings.h | 5 +- src/client/main.c | 19 ++-- src/client/misc.c | 45 +++++--- src/client/misc.h | 1 + src/client/windows.c | 78 +++++++++----- src/client/windows.h | 17 ++- src/client/world.h | 3 +- 11 files changed, 342 insertions(+), 185 deletions(-) diff --git a/confclient/commands b/confclient/commands index 28ab122..50c2069 100644 --- a/confclient/commands +++ b/confclient/commands @@ -1,51 +1,169 @@ -wait wait 0 wait / next turn -use use i use selected inventory object -drop drop i drop object from inventory -pick pick_up 0 pick up object from ground -player_u move N player up -player_d move S player down -player_l move W player left -player_r move E player right -quit 0 0 quit -to_g_keywin 0 0 toggle global keys window -to_mapwin 0 0 toggle map window -to_infowin 0 0 toggle info window -to_logwin 0 0 toggle log window -to_wg_keywin 0 0 toggle window geometry keys window -to_wk_keywin 0 0 toggle window keybinding keys window -cyc_win_f 0 0 cycle window selection forwards -winconf 0 0 toggle window configuration view -cyc_win_b 0 0 cycle window selection backwards -scrl_l 0 0 scroll pad left -scrl_r 0 0 scroll pad right -g_keys_d 0 0 global keybindings nav down -g_keys_u 0 0 global keybindings nav up -g_keys_m 0 0 global keybindings modify -shift_f 0 0 shift window forwards -shift_b 0 0 shift window backwards -grow_h 0 0 grow window horizontally -shri_h 0 0 shrink window horizontally -grow_v 0 0 grow window vertically -shri_v 0 0 shrink window vertically -to_height_t 0 0 toggle window height type -to_width_t 0 0 toggle window width type -w_keys_d 0 0 win keys nav down -w_keys_u 0 0 win keys nav up -w_keys_m 0 0 win keys mod -wg_keys_d 0 0 win geometry config keybindings nav down -wg_keys_u 0 0 win geometry config keybindings nav up -wg_keys_m 0 0 win geometry config keybindings modify -wk_keys_d 0 0 win keybindings config keybindings nav down -wk_keys_u 0 0 win keybindings config keybindings nav up -wk_keys_m 0 0 win keybindings config keybindings modify -reload_conf 0 0 reload windows and keybindings configuration -save_conf 0 0 save windows and keybindings -map_u 0 0 map up -map_d 0 0 map down -map_l 0 0 map left -map_r 0 0 map right -map_c 0 0 map center player -to_a_keywin 0 0 toggle view of available keybindings -to_inv 0 0 toggle inventory window -inv_d 0 0 inventory selection down -inv_u 0 0 inventory selection up +wait +wait / next turn +wait +0 +% +player_u +player up +move +N +% +player_d +player down +move +S +% +player_l +player left +move +W +% +player_r +player right +move +E +% +pick +pick up object from ground +pick_up +0 +% +use +use selected inventory object +use +i +% +drop +drop object from inventory +drop +i +% +quit +quit +% +cyc_win_f +cycle window selection forwards +% +cyc_win_b +cycle window selection backwards +% +shift_f +shift window forwards +% +shift_b +shift window backwards +% +scrl_l +scroll pad left +% +scrl_r +scroll pad right +% +g_keys_d +global keybindings nav down +% +g_keys_u +global keybindings nav up +% +g_keys_m +global keybindings modify +% +winconf +toggle window configuration view +% +grow_h +grow window horizontally +% +shri_h +shrink window horizontally +% +grow_v +grow window vertically +% +shri_v +shrink window vertically +% +to_height_t +toggle window height type +% +to_width_t +toggle window width type +% +inv_d +inventory selection down +% +inv_u +inventory selection up +% +w_keys_d +win keys nav down +% +w_keys_u +win keys nav up +% +w_keys_m +win keys mod +% +wg_keys_d +win geometry config keybindings nav down +% +wg_keys_u +win geometry config keybindings nav up +% +wg_keys_m +win geometry config keybindings modify +% +wk_keys_d +win keybindings config keybindings nav down +% +wk_keys_u +win keybindings config keybindings nav up +% +wk_keys_m +win keybindings config keybindings modify +% +reload_conf +reload windows and keybindings configuration +% +save_conf +save windows and keybindings +% +map_u +map up +% +map_d +map down +% +map_l +map left +% +map_r +map right +% +map_c +map center player +% +to_a_keywin +toggle view of available keybindings +% +to_inv +toggle inventory window +% +to_g_keywin +toggle global keys window +% +to_mapwin +toggle map window +% +to_infowin +toggle info window +% +to_logwin +toggle log window +% +to_wg_keywin +toggle window geometry keys window +% +to_wk_keywin +toggle window keybinding keys window +% diff --git a/src/client/command_db.c b/src/client/command_db.c index 19cd406..57ea2f3 100644 --- a/src/client/command_db.c +++ b/src/client/command_db.c @@ -5,50 +5,24 @@ #include /* uint8_t, uint32_t */ #include /* FILE, sprintf() */ #include /* free() */ -#include /* memcpy(), strlen(), strtok(), strcmp() */ -#include "../common/readwrite.h" /* try_fopen(), try_fclose(), try_fgets() - * textfile_sizes() - */ -#include "../common/rexit.h" /* for exit_err() */ +#include /* memset(), strlen(), strcmp() */ +#include "../common/readwrite.h" /* try_fopen(),try_fclose(),textfile_sizes() */ +#include "../common/rexit.h" /* exit_trouble() */ #include "../common/try_malloc.h" /* try_malloc() */ -#include "cleanup.h" /* set_cleanup_flag() */ +#include "err_try_fgets.h" /* reset_err_try_fgets_counter() */ #include "misc.h" /* array_append() */ #include "world.h" /* global world */ +#include "cleanup.h" /* set_cleanup_flag() */ -/* Helpers to init_command_db(). */ -static uint8_t copy_tokenized_string(char * line, char ** ch_ptr, char * delim); -static char * init_command_db_err(char * line_copy, uint8_t line_number); - - -static uint8_t copy_tokenized_string(char * line, char ** ch_ptr, char * delim) -{ - char * f_name = "copy_tokenized_string()"; - char * dsc_ptr = strtok(line, delim); - if (!dsc_ptr) - { - return 1; - } - * ch_ptr = try_malloc(strlen(dsc_ptr) + 1, f_name); - memcpy(* ch_ptr, dsc_ptr, strlen(dsc_ptr) + 1); - return 0; -} - - - -static char * init_command_db_err(char * line_copy, uint8_t line_number) +/* Helper to init_command_db(). */ +static void write_line_to_target(char ** target, char * line) { - char * f_name = "init_command_db_err"; - char * err_start = "Failed reading command config file at "; - char * err_middle = " due to malformed line "; - line_copy[strlen(line_copy) - 1] = '\0'; - char * err = try_malloc(strlen(err_start) + strlen(world.path_commands) + - strlen(err_middle) + 3 + 2 + strlen(line_copy) + 1, - f_name); - sprintf(err, "%s%s%s%d: %s", err_start, world.path_commands, err_middle, - line_number, line_copy); - return err; + char * f_name = "write_line_to_target()"; + *target = try_malloc(strlen(line), f_name); + line[strlen(line) - 1] = '\0'; + sprintf(*target, "%s", line); } @@ -61,16 +35,12 @@ extern struct Command * get_command(char * dsc_short) { if (0 == strcmp(dsc_short, cmd_ptr->dsc_short)) { - break; + return cmd_ptr; } cmd_ptr = &cmd_ptr[1]; i++; } - char * err_start = "get_command_data() failed on request for: "; - char err[strlen(err_start) + strlen(dsc_short) + 1]; - sprintf(err, "%s%s", err_start, dsc_short); - exit_err(i == world.commandDB.n, err); - return cmd_ptr; + return NULL; } @@ -78,34 +48,34 @@ extern struct Command * get_command(char * dsc_short) extern void init_command_db() { char * f_name = "init_command_db()"; + char * context = "Failed reading command DB file. "; FILE * file = try_fopen(world.path_commands, "r", f_name); - uint32_t lines; - uint32_t linemax = textfile_sizes(file, &lines); + uint32_t linemax = textfile_sizes(file, NULL); char line[linemax + 1]; + reset_err_try_fgets_counter(); uint8_t i = 0; - char * delim = " "; - while (try_fgets(line, linemax + 1, file, f_name)) + while (1) { - if ('\n' == line[0] || 0 == line[0]) + int test_for_end = try_fgetc(file, f_name); + if (EOF == test_for_end || '\n' == test_for_end) { break; } - char line_copy[strlen(line) + 1]; - sprintf(line_copy, "%s", line); + exit_trouble(EOF == ungetc(test_for_end, file), f_name, "ungetc()"); struct Command cmd; - char * arg_string; - exit_err(( copy_tokenized_string(line, &cmd.dsc_short, delim) - || copy_tokenized_string(NULL, &cmd.server_msg, delim) - || NULL == (arg_string = strtok(NULL, delim)) - || strlen(arg_string) > 1 - || copy_tokenized_string(NULL, &cmd.dsc_long, "\n")), - init_command_db_err(line_copy, i + 1)); - cmd.arg = arg_string[0]; - if (!strcmp("0", cmd.server_msg)) - { /* A .server_msg == NULL helps control.c's */ - free(cmd.server_msg); /* try_key() and try_server_command() to */ - cmd.server_msg = NULL; /* differentiate server commands from */ - } /* non-server commands. */ + memset(&cmd, 0, sizeof(struct Command)); + err_try_fgets(line, linemax, file, context, "nf"); + write_line_to_target(&cmd.dsc_short, line); + err_try_fgets(line, linemax, file, context, "0nf"); + write_line_to_target(&cmd.dsc_long, line); + err_try_fgets(line, linemax, file, context, "0nf"); + if (strcmp(world.delim, line)) + { + write_line_to_target(&cmd.server_msg, line); + err_try_fgets(line, linemax, file, context, "0nfs"); + cmd.arg = line[0]; + err_try_fgets(line, linemax, file, context, "d"); + } array_append(i, sizeof(struct Command), (void *) &cmd, (void **) &world.commandDB.cmds); i++; diff --git a/src/client/command_db.h b/src/client/command_db.h index 566bf70..e20d16d 100644 --- a/src/client/command_db.h +++ b/src/client/command_db.h @@ -28,7 +28,9 @@ struct CommandDB -/* Return Command struct for command described by its "dsc_short" member. */ +/* Return Command struct for command described by its "dsc_short" member. Return + * NULL if no such command is found. + */ extern struct Command * get_command(char * dsc_short); /* Reads in CommandDB config file line by line until end or first empty line. */ diff --git a/src/client/keybindings.c b/src/client/keybindings.c index 857cd50..eb67f26 100644 --- a/src/client/keybindings.c +++ b/src/client/keybindings.c @@ -3,12 +3,14 @@ #include "keybindings.h" #include /* keycode defines, cbreak(), halfdelay(), getch() */ #include /* NULL */ -#include /* FILE, sprintf(), snprintf() */ #include /* uint8_t, uint16_t, uint32_t */ +#include /* FILE, sprintf() */ #include /* free(), atoi() */ #include /* strlen(), strchr(), strcmp() */ -#include "../common/readwrite.h" /* textfile_sizes(), try_fgets(),try_fwrite()*/ +#include "../common/readwrite.h" /* try_fwrite()*/ #include "../common/try_malloc.h" /* try_malloc() */ +#include "command_db.h" /* get_command() */ +#include "err_try_fgets.h" /* err_try_fgets(), err_line() */ #include "windows.h" /* draw_all_wins() */ #include "world.h" /* global world */ @@ -158,8 +160,7 @@ extern char * get_keyname_to_keycode(uint16_t keycode) -extern void write_keybindings_to_file(FILE * file, struct KeyBindingDB * kbd, - char * delim) +extern void write_keybindings_to_file(FILE * file, struct KeyBindingDB * kbd) { char * f_name = "write_keybindings_to_file()"; uint16_t linemax = 0; @@ -181,7 +182,7 @@ extern void write_keybindings_to_file(FILE * file, struct KeyBindingDB * kbd, try_fwrite(line, sizeof(char), strlen(line), file, f_name); kb_p = kb_p->next; } - try_fwrite(delim, strlen(delim), 1, file, f_name); + try_fwrite(world.delim, strlen(world.delim), 1, file, f_name); } @@ -190,22 +191,38 @@ extern void read_keybindings_from_file(char * line, uint32_t linemax, FILE * file, struct KeyBindingDB * kbd) { char * f_name = "read_keybindings_from_file()"; - char * cmdptr; + char * context = "Failed reading keybindings from interface config file. "; + char * err_space = "Line illegally ends in whitespace."; + char * err_nospace = "No whitespace found in line."; + char * err_int = "Line starts not with a decimal number in digits."; + char * err_toolarge = "Keycode number too large, must be below 1000."; + char * err_cmd = "No such command in command DB."; struct KeyBinding ** loc_last_ptr = &kbd->kbs; * loc_last_ptr = 0; - while (try_fgets(line, linemax + 1, file, f_name)) + while (1) { - if (!strcmp("%\n", line)) + err_try_fgets(line, linemax, file, context, "0nf"); + if (!strcmp(world.delim, line)) { break; } + err_line(' ' == line[strlen(line) - 2], line, context, err_space); + char * ptr_space; + err_line(!(ptr_space = strchr(line, ' ')), line, context, err_nospace); + uint8_t i = 0; + err_line(0 == (ptr_space - line), line, context, err_int); + for (; i < (ptr_space - line); i++) + { + err_line(line[i] < '0' || '9' < line[i], line, context, err_int); + } + err_line(i > 3, line, context, err_toolarge); * loc_last_ptr = try_malloc(sizeof(struct KeyBinding), f_name); struct KeyBinding * kb_p = * loc_last_ptr; + line[strlen(line) - 1] = '\0'; + kb_p->command = get_command(ptr_space + 1); + err_line(!(kb_p->command), line, context, err_cmd); kb_p->next = 0; kb_p->key = atoi(line); - cmdptr = strchr(line, ' ') + 1; - cmdptr[strlen(cmdptr) - 1] = '\0'; - kb_p->command = get_command(cmdptr); loc_last_ptr = & kb_p->next; } } diff --git a/src/client/keybindings.h b/src/client/keybindings.h index d0cc001..ff89a4c 100644 --- a/src/client/keybindings.h +++ b/src/client/keybindings.h @@ -37,9 +37,8 @@ extern struct Command * get_command_to_keycode(struct KeyBinding * kb_p, */ extern char * get_keyname_to_keycode(uint16_t keycode); -/* Read/write from/to "file" "kbd", delimited by "delim". */ -extern void write_keybindings_to_file(FILE * file, struct KeyBindingDB * kbd, - char * delim); +/* Read/write from/to "file" "kbd", delimited by world.delim. */ +extern void write_keybindings_to_file(FILE * file, struct KeyBindingDB * kbd); extern void read_keybindings_from_file(char * line, uint32_t linemax, FILE * file, struct KeyBindingDB * kbd); diff --git a/src/client/main.c b/src/client/main.c index c7ac6f1..6599d62 100644 --- a/src/client/main.c +++ b/src/client/main.c @@ -5,12 +5,13 @@ #include /* NULL */ #include /* exit() */ #include /* memset() */ -#include "../common/rexit.h" /* set_cleanup_func(), exit_trouble() */ +#include /* access() */ +#include "../common/rexit.h" /* set_cleanup_func(), exit_trouble(),exit_err() */ #include "cleanup.h" /* cleanup(), set_cleanup_flag() */ #include "command_db.h" /* init_command_db() */ #include "io.h" /* io_loop(), try_send() */ #include "misc.h" /* load_interface_conf(), winch_called() */ -#include "windows.h" /* struct Win, winch_called() */ +#include "windows.h" /* winch_called() */ #include "world.h" /* struct World */ @@ -23,10 +24,12 @@ int main(int argc, char * argv[]) { char * f_name = "main()"; - /* Declare hard-coded paths here. */ - world.path_server_in = "server/in"; - world.path_commands = "confclient/commands"; - world.path_interface_conf = "confclient/interface_conf"; + /* Declare hard-coded paths and values here. */ + world.path_server_in = "server/in"; + world.path_commands = "confclient/commands"; + world.path_interface = "confclient/interface_conf"; + world.winDB.legal_ids = "012ciklm"; + world.delim = "%\n"; /* Parse command line arguments. */ obey_argv(argc, argv); @@ -34,6 +37,10 @@ int main(int argc, char * argv[]) /* So error exits also go through the client's cleanup() function. */ set_cleanup_func(cleanup); + /* Check existence of config files. */ + exit_err(access(world.path_commands, F_OK), "No commands config file."); + exit_err(access(world.path_interface, F_OK), "No interface config file."); + /* Initialize the whole interface. */ world.winDB.t_screen = initscr(); set_cleanup_flag(CLEANUP_NCURSES); diff --git a/src/client/misc.c b/src/client/misc.c index 4f967df..3bcd784 100644 --- a/src/client/misc.c +++ b/src/client/misc.c @@ -1,28 +1,30 @@ /* src/client/misc.c */ #include "misc.h" -#include /* exit() */ #include /* delwin() */ #include /* NULL */ #include /* uint8_t, uint32_t */ -#include /* sprintf() */ -#include /* strlen() */ +#include /* FILE, sprintf() */ +#include /* free(), exit() */ +#include /* memcpy(), strlen() */ #include /* global optarg, getopt() */ #include "../common/readwrite.h" /* try_fopen(), try_fclose(), textfile_sizes(), * try_fclose_unlink_rename(), */ +#include "../common/rexit.h" /* exit_err() */ +#include "../common/try_malloc.h" /* try_malloc() */ #include "cleanup.h" /* set_cleanup_flag() */ +#include "err_try_fgets.h" /* reset_err_try_fgets_counter() */ #include "keybindings.h" /* free_keybindings(), read_keybindings_from_file(), * write_keybindings_to_file() */ #include "map_window.h" /* map_center() */ -#include "windows.h" /* for free_winDB(), make_v_screen_and_init_win_sizes(), +#include "windows.h" /* free_winDB(), make_v_screen_and_init_win_sizes(), * read_winconf_from_file(), write_winconf_of_id_to_file(), * toggle_window() */ #include "world.h" /* global world */ -#include "../common/try_malloc.h" /* try_malloc() */ extern void obey_argv(int argc, char * argv[]) @@ -32,7 +34,7 @@ extern void obey_argv(int argc, char * argv[]) { if ('i' == opt) { - world.path_interface_conf = optarg; + world.path_interface = optarg; } else { @@ -46,19 +48,18 @@ extern void obey_argv(int argc, char * argv[]) extern void save_interface_conf() { char * f_name = "save_interface_conf()"; - char * path = world.path_interface_conf; + char * path = world.path_interface; char path_tmp[strlen(path) + 4 + 1]; sprintf(path_tmp, "%s_tmp", path); FILE * file = try_fopen(path_tmp, "w", f_name); - char * delim = "%\n"; - write_keybindings_to_file(file, &world.kb_global, delim); - write_keybindings_to_file(file, &world.kb_wingeom, delim); - write_keybindings_to_file(file, &world.kb_winkeys, delim); - write_order_wins_visible_active(file, delim); + write_keybindings_to_file(file, &world.kb_global); + write_keybindings_to_file(file, &world.kb_wingeom); + write_keybindings_to_file(file, &world.kb_winkeys); + write_order_wins_visible_active(file); uint8_t i; for (i = 0; i < strlen(world.winDB.ids); i++) { - write_winconf_of_id_to_file(file, world.winDB.ids[i], delim); + write_winconf_of_id_to_file(file, world.winDB.ids[i]); } try_fclose_unlink_rename(file, path_tmp, path, f_name); } @@ -70,23 +71,35 @@ extern void load_interface_conf() char * f_name = "load_interface_conf()"; /* Read keybindings and WincConf DB from interface config file. */ - FILE * file = try_fopen(world.path_interface_conf, "r", f_name); + reset_err_try_fgets_counter(); + FILE * file = try_fopen(world.path_interface, "r", f_name); uint32_t linemax = textfile_sizes(file, NULL); char line[linemax + 1]; read_keybindings_from_file(line, linemax, file, &world.kb_global); read_keybindings_from_file(line, linemax, file, &world.kb_wingeom); read_keybindings_from_file(line, linemax, file, &world.kb_winkeys); - read_order_wins_visible_active(line, linemax, file); + char active_tmp; + char * order_tmp; + read_order_wins_visible_active(line, linemax, file, &order_tmp, &active_tmp); while (read_winconf_from_file(line, linemax, file)); try_fclose(file, f_name); + /* Check that windows of all legal IDs have been initalized. The validity of + * this test relies on read_winconf_from_file() failing on duplicates. Only + * on success initialize the windows as visible, to enable safe cleaning up. + */ + char * err = "Failed to initialize all expected windows."; + exit_err(strlen(world.winDB.legal_ids) != strlen(world.winDB.ids), err); + world.winDB.active = active_tmp; + world.winDB.order = order_tmp; + /* Build windows as defined by read interface data and toggle them on. */ make_v_screen_and_init_win_sizes(); - uint8_t i; char tmp_active = world.winDB.active; char tmp_order[strlen(world.winDB.order) + 1]; sprintf(tmp_order, "%s", world.winDB.order); world.winDB.order[0] = '\0'; + uint8_t i; for (i = 0; i < strlen(tmp_order); toggle_window(tmp_order[i]), i++); world.winDB.active = tmp_active; diff --git a/src/client/misc.h b/src/client/misc.h index 30f1710..928d8db 100644 --- a/src/client/misc.h +++ b/src/client/misc.h @@ -36,4 +36,5 @@ extern void array_append(uint32_t old_n, size_t region_size, void * new_region, void ** ptr_old_array); + #endif diff --git a/src/client/windows.c b/src/client/windows.c index ee74528..cd3ad8c 100644 --- a/src/client/windows.c +++ b/src/client/windows.c @@ -11,10 +11,8 @@ #include /* uint8_t, uint16_t, uint32_t, UINT16_MAX */ #include /* sprintf() */ #include /* memcpy(), strlen(), strnlen(), strchr(), memset() */ +#include "../common/readwrite.h" /* try_fputc(), try_write(), try_fgetc() */ #include "../common/rexit.h" /* exit_trouble(), exit_err() */ -#include "../common/readwrite.h" /* try_fputc(), try_write(), try_fgets(), - * try_fgetc() - */ #include "../common/try_malloc.h" /* try_malloc() */ #include "../common/yx_uint16.h" /* struct yx_uint16 */ #include "draw_wins.h" /* draw_winconf_geometry(), draw_winconf_keybindings(), @@ -24,6 +22,7 @@ * draw_win_keybindings_winconf_geometry(), * draw_win_keybindings_global() */ +#include "err_try_fgets.h" /* err_try_fgets(), err_line() */ #include "keybindings.h" /* free_keybindings(), write_keybidings_to_file(), * read_keybindings_from_file() */ @@ -595,23 +594,31 @@ extern uint8_t read_winconf_from_file(char * line, uint32_t linemax, FILE * file) { char * f_name = "read_winconf_from_file()"; - int test = try_fgetc(file, f_name); - if (EOF == test || '\n' == test) + char * context = "Failed reading individual window's configuration from " + "interface config file. "; + char * err_id = "Illegal ID(s) selected."; + char * err_2 = "Double-initialized window."; + int test_for_end = try_fgetc(file, f_name); + if (EOF == test_for_end || '\n' == test_for_end) { return 0; } + exit_trouble(EOF == ungetc(test_for_end, file), f_name, "ungetc()"); + err_try_fgets(line, linemax, file, context, "ns"); + err_line(NULL == strchr(world.winDB.legal_ids, line[0]), line, context, + err_id); + exit_err(world.winDB.ids && NULL!=strchr(world.winDB.ids, line[0]), err_2); struct Win win; memset(&win, 0, sizeof(struct Win)); - win.id = (char) test; - try_fgetc(file, f_name); - try_fgets(line, linemax + 1, file, f_name); + win.id = (char) line[0]; + err_try_fgets(line, linemax, file, context, "0n"); win.title = try_malloc(strlen(line), f_name); - memcpy(win.title, line, strlen(line) - 1); /* Eliminate newline char */ - win.title[strlen(line) - 1] = '\0'; /* char at end of string. */ - try_fgets(line, linemax + 1, file, f_name); + memcpy(win.title, line, strlen(line) - 1); /* Eliminate newline char */ + win.title[strlen(line) - 1] = '\0'; /* char at end of string. */ + err_try_fgets(line, linemax, file, context, "0ni"); win.target_height = atoi(line); win.target_height_type = (0 >= win.target_height); - try_fgets(line, linemax + 1, file, f_name); + err_try_fgets(line, linemax, file, context, "0ni"); win.target_width = atoi(line); win.target_width_type = (0 >= win.target_width); read_keybindings_from_file(line, linemax, file, &win.kb); @@ -635,7 +642,7 @@ extern uint8_t read_winconf_from_file(char * line, uint32_t linemax, -extern void write_winconf_of_id_to_file(FILE * file, char c, char * delim) +extern void write_winconf_of_id_to_file(FILE * file, char c) { char * f_name = "write_winconf_of_id_to_file()"; struct Win * wc = get_win_by_id(c); @@ -653,38 +660,53 @@ extern void write_winconf_of_id_to_file(FILE * file, char c, char * delim) try_fwrite(line, sizeof(char), strlen(line), file, f_name); sprintf(line, "%d\n", wc->target_width); try_fwrite(line, sizeof(char), strlen(line), file, f_name); - write_keybindings_to_file(file, &wc->kb, delim); + write_keybindings_to_file(file, &wc->kb); } extern void read_order_wins_visible_active(char * line, uint32_t linemax, - FILE * file) + FILE * file, char ** tmp_order, + char * tmp_active) { char * f_name = "read_order_wins_visible_active()"; - char win_order[linemax + 1]; - try_fgets(win_order, linemax + 1, file, f_name); - win_order[strlen(win_order) - 1] = '\0'; - world.winDB.order = try_malloc(strlen(win_order) + 1, f_name); - sprintf(world.winDB.order, "%s", win_order); - int char_or_eof = try_fgetc(file, f_name); - char * err_eof = "fgetc() unexpectedly hitting EOF"; - exit_trouble(EOF == char_or_eof, f_name, err_eof); - world.winDB.active = (uint8_t) char_or_eof; - exit_trouble(EOF == try_fgetc(file, f_name), f_name, err_eof); - try_fgets(line, linemax + 1, file, f_name); + char * context = "Failed reading order and activation of visible windows " + "from interface config file. "; + char * err_id = "Illegal ID(s) selected."; + err_try_fgets(line, linemax, file, context, "01"); + uint32_t i = 0; + for (; i < strlen(line) - 1; i++) + { + char * test = strchr(world.winDB.legal_ids, line[i]); + err_line(!test, line, context, err_id); + } + line[strlen(line) - 1] = '\0'; + *tmp_order = try_malloc(strlen(line) + 1, f_name); + sprintf(*tmp_order, "%s", line); + if (*tmp_order[0]) + { + err_try_fgets(line, linemax, file, context, "0nfs"); + err_line(NULL == strchr(*tmp_order, line[0]), line, context, err_id); + *tmp_active = line[0]; + } + else + { + err_try_fgets(line, linemax, file, context, "0ne"); + *tmp_active = '\0'; + } + err_try_fgets(line, linemax, file, context, "d"); } -extern void write_order_wins_visible_active(FILE * file, char * delim) +extern void write_order_wins_visible_active(FILE * file) { char * f_name = "write_order_wins_visible_active()"; try_fwrite(world.winDB.order, strlen(world.winDB.order), 1, file, f_name); try_fputc('\n', file, f_name); try_fputc(world.winDB.active, file, f_name); try_fputc('\n', file, f_name); - try_fwrite(delim, strlen(delim), 1, file, f_name); + try_fwrite(world.delim, strlen(world.delim), 1, file, f_name); } diff --git a/src/client/windows.h b/src/client/windows.h index 97da5f1..4ac01d0 100644 --- a/src/client/windows.h +++ b/src/client/windows.h @@ -37,6 +37,7 @@ struct WinDB WINDOW * v_screen; /* virtual screen (ncurses pad) */ struct Win * wins; /* array of windows */ struct yx_uint16 v_screen_size; /* virtual screen size */ + char * legal_ids; /* ids allowed to be used */ char * ids; /* all windows' ids, followed by \0 */ char * order; /* visible windows' id's order, followed by \0 */ uint16_t v_screen_offset; /* how many cells v_screen view moved rightwards*/ @@ -71,19 +72,25 @@ extern uint16_t center_offset(uint16_t position, extern struct Win * get_win_by_id(char id); /* Read/write individual Win (identified by "c") and world.winDB.order / - * world.winDB.active from/to "file". Follow writing with "delim" delimiter. - * Use "line" and "linemax" as expected by try_fgets(). + * world.winDB.active from/to "file" up to the world.delim delimiter. Use "line" + * and "linemax" as expected by try_fgets(). * * Note that read_winconf_from_file() returns 1 on success and 0 if it detects * having found the end of the valid interface configuration file by either * hitting a EOF or a newline (so empty newlines at the end of the file are ok). + * + * Note that read_order_wins_visible_active() only reads the promised values + * into pointers for temporary storage. This is due to the order in which window + * data is initialized: winDB.order and winDB.active should only be set when all + * windows have been initialized, so cleaning up on error is not confused. */ extern uint8_t read_winconf_from_file(char * line, uint32_t linemax, FILE * file); -extern void write_winconf_of_id_to_file(FILE * file, char c, char * delim); +extern void write_winconf_of_id_to_file(FILE * file, char c); extern void read_order_wins_visible_active(char * line, uint32_t linemax, - FILE * file); -extern void write_order_wins_visible_active(FILE * file, char * delim); + FILE * file, char ** tmp_order, + char * tmp_active); +extern void write_order_wins_visible_active(FILE * file); /* Builds virtual sreen from .t_screen's size, fits win's sizes to them.*/ extern void make_v_screen_and_init_win_sizes(); diff --git a/src/client/world.h b/src/client/world.h index a71f772..307f53f 100644 --- a/src/client/world.h +++ b/src/client/world.h @@ -28,9 +28,10 @@ struct World struct yx_uint16 player_pos; /* coordinates of player on map */ char * log; /* log of player's activities */ char * path_server_in; /* path of server's input fifo */ - char * path_interface_conf; /* path of interface configuration file */ + char * path_interface; /* path of interface configuration file */ char * path_commands; /* path of commands config file */ char * player_inventory; /* one-item-per-line string list of owned items */ + char * delim; /* delimiter for multi-line blocks in config files */ uint16_t turn; /* world/game turn */ uint16_t player_score; /* player's score*/ uint8_t halfdelay; /* how long to wait for getch() input in io_loop() */ -- 2.30.2