home · contact · privacy
Server/py: Undummify build_fov_map().
[plomrogue] / src / client / interface_conf.c
index 69ef9eb54675fe2f009359e0de502727103801df..679f6c7a92549e8c6c094826e8c072eb0fd8a9a1 100644 (file)
@@ -1,27 +1,34 @@
-/* src/client/interface_conf.c */
+/* src/client/interface_conf.c
+ *
+ * This file is part of PlomRogue. PlomRogue is licensed under the GPL version 3
+ * or any later version. For details on its copyright, license, and warranties,
+ * see the file NOTICE in the root directory of the PlomRogue source package.
+ */
 
-#define _POSIX_C_SOURCE 200809L /* getopt(), optarg, strdup() */
+#define _POSIX_C_SOURCE 200809L /* getopt(), optarg, strdup(), snprintf() */
 #include "interface_conf.h"
 #include <ncurses.h> /* delwin() */
 #include <stddef.h> /* NULL, size_t */
 #include <stdint.h> /* UINT8_MAX, uint8_t, uint32_t */
 #include <stdlib.h> /* EXIT_SUCCESS, atoi(), exit(), free() */
 #include <stdio.h> /* FILE, sprintf() */
-#include <string.h> /* memset(), strchr(), strcmp(), strdup(), strlen() */
+#include <string.h> /* strchr(), strcmp(), strdup(), strlen() */
 #include <unistd.h> /* optarg, getopt() */
-#include "../common/parse_file.h" /* EDIT_STARTED, parse_file(), set_val(),
-                                   * token_from_line()
-                                   */
-#include "../common/readwrite.h" /* try_fopen(), try_fclose_unlink_rename(),
-                                  * try_fwrite()
+#include "../common/parse_file.h" /* token_from_line(),parsetset_singlechar() */
+#include "../common/readwrite.h" /* atomic_write_start(), atomic_write_finish(),
+                                  * detect_atomic_leftover(), try_fwrite()
                                   */
 #include "../common/rexit.h" /* exit_err(), exit_trouble() */
 #include "../common/try_malloc.h" /* try_malloc() */
 #include "array_append.h" /* array_append() */
 #include "cleanup.h" /* set_cleanup_flag() */
 #include "command_db.h" /* get_command() */
-#include "keybindings.h" /* KeyBinding, KeyBindingDB, get_command_to_keycode() */
-#include "map.h" /* map_center() */
+#include "keybindings.h" /* KeyBinding, KeyBindingDB, get_command_to_keycode()*/
+#include "parse.h" /* EDIT_STARTED, parse_file(), parse_flagval(),
+                    * parse_and_reduce_to_readyflag(), parse_id_uniq()
+                    * parsetest_defcontext(), parse_unknown_arg(),
+                    * parsetest_too_many_values(), parse_init_entry()
+                    */
 #include "wincontrol.h" /* toggle_window() */
 #include "windows.h" /* Win, free_winDB(), make_v_screen_and_init_win_sizes() */
 #include "world.h" /* global world */
@@ -98,25 +105,23 @@ static uint8_t start_kbd(char * token0, char * token1, char * str_kbd,
 /* Helper to tokens_into_entries(), sets specific entry member data. "token0"
  * and the state of flags determine what entry member to edit; "win" and "kbdb"
  * are entries to write "token1" data into (as is the global "tmp_active"). If
- * "token0" is "KEY", a keybinding is defined and "token2" is read / must not be
- * NULL. In that case, the line read is checked against having a 4th token.
+ * "token0" is "str_key", a keybinding is defined and "token2" is read/must not
+ * be NULL. In that case, the line read is checked against having a 4th token.
  */
-static uint8_t set_members(char * token0, char * token1, char * token2,
-                           uint8_t * win_flags, uint8_t * ord_flags,
-                           uint8_t kbd_flags,
+static uint8_t set_members(char * token0, char * token1, uint8_t * win_flags,
+                           uint8_t * ord_flags,uint8_t kbd_flags,char * str_key,
                            struct Win * win, struct KeyBindingDB * kbdb);
 
 /* Add keybinding defined in "token1" as keycode and "token2" as command to
  * "kbdb" if "flags" are set to EDIT_STARTED.
  */
-static void set_keybindings(char * token1, char * token2, uint8_t flags,
+static void set_keybindings(char * token1, uint8_t flags,
                             struct KeyBindingDB * kbdb);
 
 
 
 static void write_keybindings(FILE * file, struct KeyBindingDB * kbdb)
 {
-    char * f_name = "write_keybindings()";
     char * sep = " ";
     char * tok0 = "KEY";
     uint8_t i_kb;
@@ -124,12 +129,12 @@ static void write_keybindings(FILE * file, struct KeyBindingDB * kbdb)
     {
         size_t size = strlen(tok0) + strlen(sep) + 3 + strlen(sep)
                       + strlen(kbdb->kbs[i_kb].command->dsc_short) + 1 + 1;
-        char * line = try_malloc(size, f_name);
+        char * line = try_malloc(size, __func__);
         int test = snprintf(line, size, "%s%s%d%s%s\n",
                              tok0, sep, kbdb->kbs[i_kb].keycode, sep,
                              kbdb->kbs[i_kb].command->dsc_short);
-        exit_trouble(test < 0, f_name, "snprintf()");
-        try_fwrite(line, sizeof(char), strlen(line), file, f_name);
+        exit_trouble(test < 0, __func__, "snprintf");
+        try_fwrite(line, sizeof(char), strlen(line), file, __func__);
         free(line);
     }
 }
@@ -139,8 +144,7 @@ static void write_keybindings(FILE * file, struct KeyBindingDB * kbdb)
 static void write_def(FILE * file, char * prefix, uint8_t quotes, char * val,
                       char type)
 {
-    char * f_name = "write_def()";
-    char * val_str;
+    char * val_str = NULL;
     int test_val_str = 1;
     if      ('s' == type)
     {
@@ -149,26 +153,26 @@ static void write_def(FILE * file, char * prefix, uint8_t quotes, char * val,
     if      ('i' == type)
     {
         size_t size_val_str = 6 + 1;
-        val_str = try_malloc(size_val_str, f_name);
+        val_str = try_malloc(size_val_str, __func__);
         test_val_str = snprintf(val_str, size_val_str, "%d", (int16_t) *val);
     }
     else if ('c' == type)
     {
         size_t size_val_str = 1 + 1;
-        val_str = try_malloc(size_val_str, f_name);
+        val_str = try_malloc(size_val_str, __func__);
         test_val_str = snprintf(val_str, size_val_str, "%c", * val);
     }
-    exit_trouble(test_val_str < 0, f_name, "snprintf()");
+    exit_trouble(test_val_str < 0, __func__, "snprintf");
     char * quote = quotes ? "'": "";
     char * affix = "\n";
     size_t size =   strlen(prefix) + strlen(val_str) + (2 * strlen(quote))
                   + strlen(affix) + 1;
-    char * line = try_malloc(size, f_name);
+    char * line = try_malloc(size, __func__);
     int test = snprintf(line, size, "%s%s%s%s%s",
                         prefix, quote, val_str, quote, affix);
-    exit_trouble(test < 0, f_name, "snprintf()");
+    exit_trouble(test < 0, __func__, "snprintf");
     free(val_str);
-    try_fwrite(line, sizeof(char), strlen(line), file, f_name);
+    try_fwrite(line, sizeof(char), strlen(line), file, __func__);
     free(line);
 }
 
@@ -179,6 +183,7 @@ static void tokens_into_entries(char * token0, char * token1)
     char * str_win = "WINDOW";
     char * str_ord = "WIN_ORDER";
     char * str_kbd = "KEYBINDINGS";
+    char * str_key = "KEY";
     static uint8_t win_flags = READY_WIN;
     static uint8_t ord_flags = READY_ORD;
     static uint8_t kbd_flags = READY_KBD;
@@ -187,29 +192,25 @@ static void tokens_into_entries(char * token0, char * token1)
     if (!token0 || !strcmp(token0, str_win) || !strcmp(token0, str_ord)
                 || !strcmp(token0, str_kbd))
     {
-        err_line(   ((win_flags & READY_WIN) ^ READY_WIN)
-                 || ((ord_flags & READY_ORD) ^ READY_ORD)
-                 || ((kbd_flags & READY_KBD) ^ READY_KBD),
-                 "Last definition block not yet finished yet.");
+        parse_and_reduce_to_readyflag(&win_flags, READY_WIN);
+        parse_and_reduce_to_readyflag(&ord_flags, READY_ORD);
+        parse_and_reduce_to_readyflag(&kbd_flags, READY_KBD);
         write_if_win(&win);
-        ord_flags = READY_ORD;
-        win_flags = READY_WIN;
-        kbd_flags = READY_KBD;
     }
-    if (!token0)
+    if (token0)
     {
-        return;
-    }
-    char * token2 = token_from_line(NULL);
-    err_line(strcmp(token0, "KEY") && NULL != token2, "Too many values.");
-    if (   start_win(token0, token1, str_win, &win_flags, &win)
-        || start_ord(token0, token1, str_ord, &ord_flags)
-        || start_kbd(token0, token1, str_kbd, &kbd_flags, &kbdb)
-        || set_members(token0, token1, token2, &win_flags, &ord_flags,
-                       kbd_flags, win, kbdb));
-    else
-    {
-        err_line(1, "Unknown argument.");
+        if (strcmp(token0, str_key))
+        {
+            parsetest_too_many_values();
+        }
+        if (!(   start_win(token0, token1, str_win, &win_flags, &win)
+              || start_ord(token0, token1, str_ord, &ord_flags)
+              || start_kbd(token0, token1, str_kbd, &kbd_flags, &kbdb)
+              || set_members(token0, token1, &win_flags, &ord_flags, kbd_flags,
+                             str_key, win, kbdb)))
+        {
+           parse_unknown_arg();
+        }
     }
 }
 
@@ -217,16 +218,15 @@ static void tokens_into_entries(char * token0, char * token1)
 
 static void write_if_win(struct Win ** win)
 {
-    char * f_name = "write_if_win()";
     if (*win)
     {
         (*win)->target_height_type = (0 >= (*win)->target_height);
         (*win)->target_width_type = (0 >= (*win)->target_width);;
         size_t old_ids_size = strlen(world.winDB.ids);
         size_t new_size = old_ids_size + 1 + 1;
-        char * new_ids = try_malloc(new_size, f_name);
+        char * new_ids = try_malloc(new_size, __func__);
         int test = snprintf(new_ids,new_size,"%s%c",world.winDB.ids,(*win)->id);
-        exit_trouble(test < 0, f_name, "snprintf()");
+        exit_trouble(test < 0, __func__, "snprintf");
         free(world.winDB.ids);
         world.winDB.ids = new_ids;
         array_append(old_ids_size, sizeof(struct Win), *win,
@@ -245,14 +245,9 @@ static uint8_t start_win(char * token0, char * token1, char * str_win,
     {
         return 0;
     }
-    char * f_name = "start_win()";
-    char * err_uniq = "Declaration of ID already used.";
-    *win_flags = EDIT_STARTED;
-    *win = try_malloc(sizeof(struct Win), f_name);
-    memset(*win, 0, sizeof(struct Win));
-    err_line(1 != strlen(token1), "Value must be single ASCII character.");
-    err_line(   world.winDB.ids
-             && (NULL != strchr(world.winDB.ids, token1[0])), err_uniq);
+    *win = (struct Win *) parse_init_entry(win_flags, sizeof(struct Win));
+    parsetest_singlechar(token1);
+    parse_id_uniq(world.winDB.ids && strchr(world.winDB.ids,token1[0]));
     (*win)->id = token1[0];
     return 1;
 }
@@ -312,40 +307,38 @@ static uint8_t start_kbd(char * token0, char * token1, char * str_kbd,
 
 
 
-static uint8_t set_members(char * token0, char * token1, char * token2,
-                           uint8_t * win_flags, uint8_t * ord_flags,
-                           uint8_t kbd_flags,
+static uint8_t set_members(char * token0, char * token1, uint8_t * win_flags,
+                           uint8_t * ord_flags,uint8_t kbd_flags,char * str_key,
                            struct Win * win, struct KeyBindingDB * kbdb)
 {
-    if (   set_val(token0, token1, "NAME", win_flags,
-                   NAME_SET, 's', (char *) &win->title)
-        || set_val(token0, token1, "WIDTH", win_flags,
-                   WIDTH_SET, 'i', (char *) &win->target_width)
-        || set_val(token0, token1, "HEIGHT", win_flags,
-                   HEIGHT_SET, 'i', (char *) &win->target_height));
-    else if (set_val(token0, token1, "BREAK", win_flags,
-                     BREAK_SET, '8', (char *) &win->linebreak))
+    if (   parse_flagval(token0, token1, "NAME", win_flags,
+                         NAME_SET, 's', (char *) &win->title)
+        || parse_flagval(token0, token1, "WIDTH", win_flags,
+                         WIDTH_SET, 'i', (char *) &win->target_width)
+        || parse_flagval(token0, token1, "HEIGHT", win_flags,
+                         HEIGHT_SET, 'i', (char *) &win->target_height));
+    else if (parse_flagval(token0, token1, "BREAK", win_flags,
+                           BREAK_SET, '8', (char *) &win->linebreak))
     {
         err_line(2 < win->linebreak, "Value must be 0, 1 or 2.");
     }
-    else if (set_val(token0, token1, "WIN_FOCUS", ord_flags,
-                     FOCUS_SET, 'c', &tmp_active))
+    else if (parse_flagval(token0, token1, "WIN_FOCUS", ord_flags,
+                           FOCUS_SET, 'c', &tmp_active))
     {
         char * err_null = "Value not empty as it should be.";
         char * err_outside = "ID not found in WIN_ORDER ID series.";
         err_line(!strlen(tmp_order) && tmp_active, err_null);
         err_line(!strchr(tmp_order, tmp_active), err_outside);
     }
-    else if (!strcmp(token0, "KEY"))
+    else if (!strcmp(token0, str_key))
     {
-        err_line(NULL != token_from_line(NULL), "Too many values.");
-        if (* win_flags & EDIT_STARTED)
+        if (*win_flags & EDIT_STARTED)
         {
-            set_keybindings(token1, token2, * win_flags, &win->kb);
+            set_keybindings(token1, *win_flags, &win->kb);
         }
         else
         {
-            set_keybindings(token1, token2, kbd_flags, kbdb);
+            set_keybindings(token1, kbd_flags, kbdb);
         }
     }
     else
@@ -357,13 +350,14 @@ static uint8_t set_members(char * token0, char * token1, char * token2,
 
 
 
-static void set_keybindings(char * token1, char * token2, uint8_t flags,
+static void set_keybindings(char * token1, uint8_t flags,
                             struct KeyBindingDB * kbdb)
 {
-    char * err_out  = "Outside appropriate definition's context.";
-    char * err_code = "Invalid keycode. Must be >= 0 and < 1000.";
-    err_line(!(flags & EDIT_STARTED), err_out);
+    char * token2 = token_from_line(NULL);
     err_line(!token2, "No binding to key given.");
+    parsetest_too_many_values();
+    char * err_code = "Invalid keycode. Must be >= 0 and < 1000.";
+    parsetest_defcontext(flags);
     char * err_many = "No more than 255 keybindings allowed in one section.";
     err_line(UINT8_MAX == kbdb->n_of_kbs, err_many);
     struct KeyBinding kb;
@@ -377,7 +371,7 @@ static void set_keybindings(char * token1, char * token2, uint8_t flags,
     }
     kb.keycode = atoi(token1);
     char * err_uniq = "Binding to key already defined.";
-    err_line(NULL != get_command_to_keycode(kbdb, kb.keycode), err_uniq);
+    err_line(!(!get_command_to_keycode(kbdb, kb.keycode)), err_uniq);
     kb.command = get_command(token2);
     err_line(!(kb.command), "No such command in command DB.");
     array_append(kbdb->n_of_kbs, sizeof(struct KeyBinding), (void *) &kb,
@@ -407,13 +401,8 @@ extern void obey_argv(int argc, char * argv[])
 
 extern void save_interface_conf()
 {
-    char * f_name = "save_interface_conf()";
-    char * path = world.path_interface;
-    size_t size = strlen(path) + 4 + 1;
-    char * path_tmp = try_malloc(size, f_name);
-    int test = snprintf(path_tmp, size, "%s_tmp", path);
-    exit_trouble(test < 0, f_name, "snprintf()");
-    FILE * file = try_fopen(path_tmp, "w", f_name);
+    char * path_tmp;
+    FILE * file = atomic_write_start(world.path_interface, &path_tmp);
     char * str_keybs = "\nKEYBINDINGS ";
     write_def(file, str_keybs, 1, "global", 's');
     write_keybindings(file, &world.kb_global);
@@ -437,26 +426,25 @@ extern void save_interface_conf()
         write_def(file, "HEIGHT ", 0, (char *) &win->target_height, 'i');
         write_keybindings(file, &win->kb);
     }
-    try_fclose_unlink_rename(file, path_tmp, path, f_name);
-    free(path_tmp);
+    atomic_write_finish(file, world.path_interface, path_tmp);
 }
 
 
 
 extern void load_interface_conf()
 {
-    char * f_name = "load_interface_conf()";
-    world.winDB.ids    = try_malloc(1, f_name);
+    world.winDB.ids    = try_malloc(1, __func__);
     world.winDB.ids[0] = '\0';
     world.winDB.wins = NULL;
-    tmp_order    = try_malloc(1, f_name);
+    tmp_order    = try_malloc(1, __func__);
     tmp_order[0] = '\0';
     tmp_active   = '\0';
+    detect_atomic_leftover(world.path_interface);
     parse_file(world.path_interface, tokens_into_entries);
     char * err = "Not all expected windows defined in config file.";
     exit_err(strlen(world.winDB.legal_ids) != strlen(world.winDB.ids), err);
     make_v_screen_and_init_win_sizes();
-    world.winDB.order = try_malloc(1, f_name);
+    world.winDB.order = try_malloc(1, __func__);
     world.winDB.order[0] = '\0';
     uint8_t i;
     for (i = 0; i < strlen(tmp_order); toggle_window(tmp_order[i]), i++);
@@ -492,7 +480,5 @@ extern void reload_interface_conf()
 {
     unload_interface_conf();
     load_interface_conf();
-    map_center();
     world.winDB.v_screen_offset = 0;
 }
-