From e8e8f91cff96eebc1b440df18d9c3ef4ced1ca60 Mon Sep 17 00:00:00 2001
From: Christian Heller <c.heller@plomlompom.de>
Date: Thu, 23 Jan 2014 06:07:38 +0100
Subject: [PATCH] Read interface config from one file (which can be set as
 command line argument) instead of whole directory tree.

---
 confclient/interface_conf                  |  97 +++++
 confclient/keybindings_global              |  16 -
 confclient/keybindings_wingeom             |   8 -
 confclient/keybindings_winkeys             |   3 -
 confclient/windows/Win_0                   |   7 -
 confclient/windows/Win_1                   |   7 -
 confclient/windows/Win_2                   |   7 -
 confclient/windows/Win_c                   |   8 -
 confclient/windows/Win_i                   |   4 -
 confclient/windows/Win_k                   |   4 -
 confclient/windows/Win_l                   |   4 -
 confclient/windows/Win_m                   |  15 -
 confclient/windows/toggle_order_and_active |   2 -
 src/client/keybindings.c                   |  81 ++--
 src/client/keybindings.h                   |  11 +-
 src/client/main.c                          |   6 +-
 src/client/misc.c                          |  87 ++++-
 src/client/misc.h                          |   3 +
 src/client/wincontrol.c                    | 423 ++++++++-------------
 src/client/wincontrol.h                    |  35 +-
 src/client/world.h                         |   1 +
 21 files changed, 392 insertions(+), 437 deletions(-)
 create mode 100644 confclient/interface_conf
 delete mode 100644 confclient/keybindings_global
 delete mode 100644 confclient/keybindings_wingeom
 delete mode 100644 confclient/keybindings_winkeys
 delete mode 100644 confclient/windows/Win_0
 delete mode 100644 confclient/windows/Win_1
 delete mode 100644 confclient/windows/Win_2
 delete mode 100644 confclient/windows/Win_c
 delete mode 100644 confclient/windows/Win_i
 delete mode 100644 confclient/windows/Win_k
 delete mode 100644 confclient/windows/Win_l
 delete mode 100644 confclient/windows/Win_m
 delete mode 100644 confclient/windows/toggle_order_and_active

diff --git a/confclient/interface_conf b/confclient/interface_conf
new file mode 100644
index 0000000..fdc2609
--- /dev/null
+++ b/confclient/interface_conf
@@ -0,0 +1,97 @@
+81 quit
+265 to_a_keywin
+266 to_mapwin
+267 to_infowin
+268 to_inv
+269 to_logwin
+270 to_g_keywin
+271 to_wg_keywin
+272 to_wk_keywin
+119 winconf
+62 cyc_win_f
+60 cyc_win_b
+262 scrl_l
+360 scrl_r
+114 reload_conf
+67 save_conf
+%
+258 shift_f
+259 shift_b
+42 grow_h
+95 shri_h
+43 grow_v
+45 shri_v
+121 to_height_t
+120 to_width_t
+%
+258 w_keys_d
+259 w_keys_u
+10 w_keys_m
+%
+kmicl
+m
+%
+0
+Global keys
+-13
+29
+258 g_keys_d
+259 g_keys_u
+10 g_keys_m
+%
+1
+Window geometry keys
+8
+29
+258 wg_keys_d
+259 wg_keys_u
+10 wg_keys_m
+%
+2
+Window keybinding keys
+3
+29
+258 wk_keys_d
+259 wk_keys_u
+10 wk_keys_m
+%
+c
+Inventory
+5
+33
+100 drop
+259 inv_u
+258 inv_d
+117 use
+%
+i
+Info
+3
+33
+%
+k
+Available keys
+0
+29
+%
+l
+Log
+-10
+33
+%
+m
+Map
+0
+-64
+112 pick
+58 wait
+107 player_u
+106 player_d
+104 player_l
+108 player_r
+259 map_u
+258 map_d
+260 map_l
+261 map_r
+46 map_c
+%
diff --git a/confclient/keybindings_global b/confclient/keybindings_global
deleted file mode 100644
index 739af7d..0000000
--- a/confclient/keybindings_global
+++ /dev/null
@@ -1,16 +0,0 @@
-81 quit
-265 to_a_keywin
-266 to_mapwin
-267 to_infowin
-268 to_inv
-269 to_logwin
-270 to_g_keywin
-271 to_wg_keywin
-272 to_wk_keywin
-119 winconf
-62 cyc_win_f
-60 cyc_win_b
-262 scrl_l
-360 scrl_r
-114 reload_conf
-67 save_conf
diff --git a/confclient/keybindings_wingeom b/confclient/keybindings_wingeom
deleted file mode 100644
index d322501..0000000
--- a/confclient/keybindings_wingeom
+++ /dev/null
@@ -1,8 +0,0 @@
-258 shift_f
-259 shift_b
-42 grow_h
-95 shri_h
-43 grow_v
-45 shri_v
-121 to_height_t
-120 to_width_t
diff --git a/confclient/keybindings_winkeys b/confclient/keybindings_winkeys
deleted file mode 100644
index 8a15320..0000000
--- a/confclient/keybindings_winkeys
+++ /dev/null
@@ -1,3 +0,0 @@
-258 w_keys_d
-259 w_keys_u
-10 w_keys_m
diff --git a/confclient/windows/Win_0 b/confclient/windows/Win_0
deleted file mode 100644
index e79bdcd..0000000
--- a/confclient/windows/Win_0
+++ /dev/null
@@ -1,7 +0,0 @@
-Global keys
-0
--13
-29
-258 g_keys_d
-259 g_keys_u
-10 g_keys_m
diff --git a/confclient/windows/Win_1 b/confclient/windows/Win_1
deleted file mode 100644
index 645c8c4..0000000
--- a/confclient/windows/Win_1
+++ /dev/null
@@ -1,7 +0,0 @@
-Window geometry keys
-1
-8
-29
-258 wg_keys_d
-259 wg_keys_u
-10 wg_keys_m
diff --git a/confclient/windows/Win_2 b/confclient/windows/Win_2
deleted file mode 100644
index c1d9448..0000000
--- a/confclient/windows/Win_2
+++ /dev/null
@@ -1,7 +0,0 @@
-Window keybinding keys
-2
-3
-29
-258 wk_keys_d
-259 wk_keys_u
-10 wk_keys_m
diff --git a/confclient/windows/Win_c b/confclient/windows/Win_c
deleted file mode 100644
index b513c69..0000000
--- a/confclient/windows/Win_c
+++ /dev/null
@@ -1,8 +0,0 @@
-Inventory
-c
-5
-33
-100 drop
-259 inv_u
-258 inv_d
-117 use
diff --git a/confclient/windows/Win_i b/confclient/windows/Win_i
deleted file mode 100644
index dfc519f..0000000
--- a/confclient/windows/Win_i
+++ /dev/null
@@ -1,4 +0,0 @@
-Info
-i
-3
-33
diff --git a/confclient/windows/Win_k b/confclient/windows/Win_k
deleted file mode 100644
index ca67a5f..0000000
--- a/confclient/windows/Win_k
+++ /dev/null
@@ -1,4 +0,0 @@
-Available keys
-k
-0
-29
diff --git a/confclient/windows/Win_l b/confclient/windows/Win_l
deleted file mode 100644
index e2fff52..0000000
--- a/confclient/windows/Win_l
+++ /dev/null
@@ -1,4 +0,0 @@
-Log
-l
--10
-33
diff --git a/confclient/windows/Win_m b/confclient/windows/Win_m
deleted file mode 100644
index a83973f..0000000
--- a/confclient/windows/Win_m
+++ /dev/null
@@ -1,15 +0,0 @@
-Map
-m
-0
--64
-112 pick
-58 wait
-107 player_u
-106 player_d
-104 player_l
-108 player_r
-259 map_u
-258 map_d
-260 map_l
-261 map_r
-46 map_c
diff --git a/confclient/windows/toggle_order_and_active b/confclient/windows/toggle_order_and_active
deleted file mode 100644
index f188d83..0000000
--- a/confclient/windows/toggle_order_and_active
+++ /dev/null
@@ -1,2 +0,0 @@
-kmicl
-m
\ No newline at end of file
diff --git a/src/client/keybindings.c b/src/client/keybindings.c
index 500deec..e57e361 100644
--- a/src/client/keybindings.c
+++ b/src/client/keybindings.c
@@ -6,11 +6,8 @@
 #include <stdio.h> /* FILE, sprintf(), snprintf() */
 #include <stdint.h> /* uint8_t, uint16_t, uint32_t */
 #include <stdlib.h> /* free(), atoi() */
-#include <string.h> /* strlen(), strchr() */
-#include "../common/readwrite.h" /* try_fopen(), textfile_sizes(), try_fgets(),
-                                  * try_fclose(), try_fclose_unlink_rename(),
-                                  * try_fwrite()
-                                  */
+#include <string.h> /* strlen(), strchr(), strcmp() */
+#include "../common/readwrite.h" /* textfile_sizes(), try_fgets(),try_fwrite()*/
 #include "../common/try_malloc.h" /* try_malloc() */
 #include "wincontrol.h" /* get_winconf_by_win() */
 #include "windows.h" /* draw_all_wins() */
@@ -162,44 +159,10 @@ extern char * get_keyname_to_keycode(uint16_t keycode)
 
 
 
-extern void init_keybindings(char * path, struct KeyBindingDB * kbd)
+extern void write_keybindings_to_file(FILE * file, struct KeyBindingDB * kbd,
+                                      char * delim)
 {
-    char * f_name = "init_keybindings()";
-    FILE * file = try_fopen(path, "r", f_name);
-    uint32_t lines;
-    uint32_t linemax = textfile_sizes(file, &lines);
-    char command[linemax + 1];
-    char * cmdptr;
-    struct KeyBinding ** loc_last_ptr = &kbd->kbs;
-    * loc_last_ptr = 0;
-    while (try_fgets(command, linemax + 1, file, f_name))
-    {
-        if ('\n' == command[0] || 0 == command[0])
-        {
-            break;
-        }
-        * loc_last_ptr = try_malloc(sizeof(struct KeyBinding), f_name);
-        struct KeyBinding * kb_p = * loc_last_ptr;
-        kb_p->next = 0;
-        kb_p->key = atoi(command);
-        cmdptr = strchr(command, ' ') + 1;
-        cmdptr[strlen(cmdptr) - 1] = '\0';
-        kb_p->command = get_command(cmdptr);
-        loc_last_ptr = & kb_p->next;
-    }
-    try_fclose(file, f_name);
-    kbd->edit = 0;
-    kbd->select = 0;
-}
-
-
-
-extern void save_keybindings(char * path, struct KeyBindingDB * kbd)
-{
-    char * f_name = "save_keybindings()";
-    char path_tmp[strlen(path) + 4 + 1];
-    sprintf(path_tmp, "%s_tmp", path);
-    FILE * file = try_fopen(path_tmp, "w", f_name);
+    char * f_name = "write_keybindings_to_file()";
     uint16_t linemax = 0;
     struct KeyBinding * kb_p = kbd->kbs;
     while (0 != kb_p)
@@ -210,16 +173,44 @@ extern void save_keybindings(char * path, struct KeyBindingDB * kbd)
         }
         kb_p = kb_p->next;
     }
-    linemax = linemax + 6;         /* + 6 = + 3 digits + whitespace + \n + \0 */
+    linemax = linemax + 6;            /* + 6 = + 3 digits + ' ' + '\n' + '\0' */
     char line[linemax];
     kb_p = kbd->kbs;
     while (0 != kb_p)
     {
-        snprintf(line, linemax, "%d %s\n", kb_p->key, kb_p->command->dsc_short);
+        sprintf(line, "%d %s\n", kb_p->key, kb_p->command->dsc_short);
         try_fwrite(line, sizeof(char), strlen(line), file, f_name);
         kb_p = kb_p->next;
     }
-    try_fclose_unlink_rename(file, path_tmp, path, f_name);
+    try_fwrite(delim, strlen(delim), 1, file, f_name);
+}
+
+
+
+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;
+    struct KeyBinding ** loc_last_ptr = &kbd->kbs;
+    * loc_last_ptr = 0;
+    while (try_fgets(line, linemax + 1, file, f_name))
+    {
+        if (!strcmp("%\n", line))
+        {
+            break;
+        }
+        * loc_last_ptr = try_malloc(sizeof(struct KeyBinding), f_name);
+        struct KeyBinding * kb_p = * loc_last_ptr;
+        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;
+    }
+    kbd->edit = 0;
+    kbd->select = 0;
 }
 
 
diff --git a/src/client/keybindings.h b/src/client/keybindings.h
index b191c59..d0cc001 100644
--- a/src/client/keybindings.h
+++ b/src/client/keybindings.h
@@ -7,6 +7,7 @@
 #define KEYBINDINGS_H
 
 #include <stdint.h> /* uint8_t, uint16_t */
+#include <stdio.h> /* FILE */
 struct Command;
 
 
@@ -36,11 +37,11 @@ extern struct Command * get_command_to_keycode(struct KeyBinding * kb_p,
  */
 extern char * get_keyname_to_keycode(uint16_t keycode);
 
-/* Initialize/save keybindings data from/to file at "path" to/from keybindings
- * data pointer "kbd".
- */
-extern void init_keybindings(char * path, struct KeyBindingDB * kbd);
-extern void save_keybindings(char * path, struct KeyBindingDB * kbd);
+/* Read/write from/to "file" "kbd", delimited by "delim". */
+extern void write_keybindings_to_file(FILE * file, struct KeyBindingDB * kbd,
+                                      char * delim);
+extern void read_keybindings_from_file(char * line, uint32_t linemax,
+                                       FILE * file, struct KeyBindingDB * kbd);
 
 /* Free keybinding chain starting at "kb_start". */
 extern void free_keybindings(struct KeyBinding * kb_start);
diff --git a/src/client/main.c b/src/client/main.c
index 51d5606..473228c 100644
--- a/src/client/main.c
+++ b/src/client/main.c
@@ -17,12 +17,16 @@ struct World world;
 
 
 
-int main()
+int main(int argc, char * argv[])
 {
     char * f_name = "main()";
 
     /* Declare hard-coded paths here. */
     world.path_server_in = "server/in";
+    world.path_interface_conf = "confclient/interface_conf";
+
+    /* Parse command line arguments. */
+    obey_argv(argc, argv);
 
     /* So error exits also go through the client's cleanup() function. */
     set_cleanup_func(cleanup);
diff --git a/src/client/misc.c b/src/client/misc.c
index 01cf1d2..ff1600c 100644
--- a/src/client/misc.c
+++ b/src/client/misc.c
@@ -3,41 +3,91 @@
 #include "misc.h"
 #include <ncurses.h> /* delwin(), endwin(), refresh() */
 #include <stdint.h> /* uint8_t, uint16_t */
+#include <stdio.h> /* sprintf() */
+#include <stdlib.h> /* exit(), free() */
 #include <string.h> /* memset(), strlen() */
+#include <unistd.h> /* global optarg, getopt() */
+#include "../common/readwrite.h" /* try_fopen(), try_fclose(),
+                                  * try_fclose_unlink_rename(),
+                                  */
 #include "cleanup.h" /* for set_cleanup_flag() */
-#include "keybindings.h" /* init_keybindings(), free_keybindings(),
-                          * save_keybindings()
+#include "keybindings.h" /* free_keybindings(), read_keybindings_from_file(),
+                          * write_keybindings_to_file()
                           */
 #include "map_window.h" /* for map_center() */
-#include "wincontrol.h" /* struct WinConf, init_winconfs(), init_wins(),
-                         * sorted_wintoggle_and_activate(), get_win_by_id(),
-                         * get_winconf_by_win(), toggle_window(),
-                         * get_next_winconf_id()
+#include "wincontrol.h" /* struct WinConf, init_wins(), get_winconf_by_win(),
+                         * sorted_win_toggle_and_activate(), get_win_by_id(),
+                         * toggle_window(), write_winconf_of_id_to_file(),
+                         * read_winconf_from_file(), get_next_winconf_id(),
+                         * read_order_wins_visible_active(),
+                         * write_order_wins_visible_active()
                          */
 #include "windows.h" /* struct Win, make_pad(), suspend_win(), free_win() */
 #include "world.h" /* global world */
 
 
 
+extern void obey_argv(int argc, char * argv[])
+{
+    int opt;
+    while (-1 != (opt = getopt(argc, argv, "i:")))
+    {
+        if      ('i' == opt)
+        {
+            world.path_interface_conf = optarg;
+        }
+        else
+        {
+            exit(EXIT_FAILURE);
+        }
+    }
+}
+
+
+
 extern void save_interface_conf()
 {
-    save_keybindings("confclient/keybindings_global", &world.kb_global);
-    save_keybindings("confclient/keybindings_wingeom", &world.kb_wingeom);
-    save_keybindings("confclient/keybindings_winkeys", &world.kb_winkeys);
-    save_win_configs();
+    char * f_name = "save_interface_conf()";
+    char * path = world.path_interface_conf;
+    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);
+    uint8_t i;
+    for (i = 0; i < strlen(world.winconf_db.ids); i++)
+    {
+        write_winconf_of_id_to_file(file, world.winconf_db.ids[i], delim);
+    }
+    try_fclose_unlink_rename(file, path_tmp, path, f_name);
 }
 
 
 
 extern void load_interface_conf()
 {
-    init_keybindings("confclient/keybindings_global",  &world.kb_global);
-    init_keybindings("confclient/keybindings_wingeom", &world.kb_wingeom);
-    init_keybindings("confclient/keybindings_winkeys", &world.kb_winkeys);
-    init_winconfs();
+    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);
+    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);
+    while (read_winconf_from_file(line, linemax, file));
+    try_fclose(file, f_name);
+
+    /* Build windows as defined by read interface data and toggle them on. */
     make_pad();
     init_wins();
-    sorted_wintoggle_and_activate();
+    sorted_win_toggle_and_activate();
+
+    /* So that the interface config data and the window structs get freed. */
     set_cleanup_flag(CLEANUP_INTERFACE);
 }
 
@@ -46,8 +96,11 @@ extern void load_interface_conf()
 extern void unload_interface_conf()
 {
     free_keybindings(world.kb_global.kbs);
+    world.kb_global.kbs = NULL;
     free_keybindings(world.kb_wingeom.kbs);
+    world.kb_wingeom.kbs = NULL;
     free_keybindings(world.kb_winkeys.kbs);
+    world.kb_winkeys.kbs = NULL;
     while (0 != world.wmeta.active)
     {
         suspend_win(world.wmeta.active);
@@ -70,8 +123,8 @@ extern void reset_windows()
     endwin();  /* "[S]tandard way" to recalibrate ncurses post SIGWINCH, says */
     refresh(); /* <http://invisible-island.net/ncurses/ncurses-intro.html>.   */
     struct Win * w_p = world.wmeta.chain_start;
-    char win_ids[strlen(world.winconf_db.winconf_ids) + 1];
-    memset(win_ids, '\0', strlen(world.winconf_db.winconf_ids) + 1);
+    char win_ids[strlen(world.winconf_db.ids) + 1];
+    memset(win_ids, '\0', strlen(world.winconf_db.ids) + 1);
     uint8_t i = 0;
     char active = '\0';
     for (; NULL != w_p; w_p = w_p->next, i++)
diff --git a/src/client/misc.h b/src/client/misc.h
index 31e3ee0..e849703 100644
--- a/src/client/misc.h
+++ b/src/client/misc.h
@@ -11,6 +11,9 @@
 
 
 
+/* Parses command line argument -i into client configuration. */
+extern void obey_argv(int argc, char * argv[]);
+
 /* Save / load (init) / unload (free/dissolve) / reload interface configuration
  * data, world.wmeta.pad (initialized before opening any windows to the height
  * of the terminal screen and a width of 1) and window chains.
diff --git a/src/client/wincontrol.c b/src/client/wincontrol.c
index 01b9be8..275fc9c 100644
--- a/src/client/wincontrol.c
+++ b/src/client/wincontrol.c
@@ -2,15 +2,13 @@
 
 #include "wincontrol.h"
 #include <errno.h> /* global errno */
-#include <dirent.h> /* DIR, struct dirent, opendir(), closedir(), readdir() */
 #include <stddef.h> /* NULL */
 #include <stdint.h> /* uint8_t, uint16_t, uint32_t */
-#include <stdio.h> /* FILE */
+#include <stdio.h> /* FILE, sprintf() */
 #include <stdlib.h> /* free(), atoi() */
-#include <string.h> /* strlen(), strchr(), strstr(), memcpy() */
-#include "../common/readwrite.h" /* try_fopen(), textfile_sizes(), try_fgets(),
-                                  * textfile_sizes(), try_fwrite(), try_fgetc(),
-                                  * try_fclose_unlink_rename(), try_fputc()
+#include <string.h> /* strlen(), strchr(), memcpy() */
+#include "../common/readwrite.h" /* try_fgets(), try_fwrite(), try_fgetc(),
+                                  * try_fputc()
                                   */
 #include "../common/rexit.h" /* exit_err(), exit_trouble() */
 #include "../common/try_malloc.h" /* try_malloc() */
@@ -30,18 +28,9 @@
 
 
 
-/* Return string "prefix" + "id"; malloc()'s string, remember to call free()! */
-static char * string_prefixed_id(char * prefix, char id);
-
-/* Initialize Winconf of "id" from appropriate config file.*/
-static void init_winconf_from_file(char id, struct WinConf * winconf);
-
 /* Wrapper around init_win() called with values from Winconf of "id". */
 static void init_win_from_winconf(char id);
 
-/* Save title, draw function, size of window identified by "id" to conffile. */
-static void save_win_config(char id);
-
 /* Free data pointed to inside individual WinConf struct of "id". */
 static void free_winconf_data(char id);
 
@@ -50,7 +39,7 @@ static void free_winconf_data(char id);
  */
 static void set_winconf_geometry(char id);
 
-/* Get WinConf by "id"; get id of WinConf mothering "win". */
+/* Get WinConf by "id". */
 static struct WinConf * get_winconf_by_id(char id);
 
 /* Get (Win->draw) function identified by "c"; NULL if c not mapped to one. */
@@ -58,144 +47,6 @@ static void * get_drawfunc_by_char(char c);
 
 
 
-static char * string_prefixed_id(char * prefix, char id)
-{
-    uint8_t size = strlen(prefix) + 2;
-    char * path = try_malloc(size, "string_prefixed_id()");
-    sprintf(path, "%s_", prefix);
-    path[size - 2] = id;
-    return path;
-}
-
-
-
-static void init_winconf_from_file(char id, struct WinConf * winconf)
-{
-    /* Assign WinConf id to filename path, error message context, winconf->id.*/
-    char * tmp = "init_winconf_from_file() on window id '_'";
-    char * context = try_malloc(strlen(tmp) + 1, "init_winconf_from_file()");
-    memcpy(context, tmp, strlen(tmp) + 1);
-    context[strlen(tmp) - 2] = id;
-    char * path = string_prefixed_id("confclient/windows/Win_", id);
-    winconf->id = id;
-
-    /* Prepare reading in file line by line into "line" array. */
-    FILE * file = try_fopen(path, "r", context);
-    free(path);
-    uint32_t linemax = textfile_sizes(file, NULL);
-    char line[linemax + 1];
-
-    /* Read/determine winconf->title, ->draw, ->height(_type),->width(_type). */
-    try_fgets(line, linemax + 1, file, context);
-    winconf->title = try_malloc(strlen(line), context);
-    memcpy(winconf->title, line, strlen(line) - 1); /* Eliminate newline char */
-    winconf->title[strlen(line) - 1] = '\0';        /* char at end of string. */
-    try_fgets(line, linemax + 1, file, context);
-    winconf->draw = line[0];
-    try_fgets(line, linemax + 1, file, context);
-    winconf->height = atoi(line);
-    winconf->height_type = (0 >= winconf->height);
-    try_fgets(line, linemax + 1, file, context);
-    winconf->width = atoi(line);
-    winconf->width_type = (0 >= winconf->width);
-
-    /* Read in window-specific keybindings (winconf->kb). */
-    char command[linemax + 1];
-    char * cmdptr;
-    struct KeyBinding ** loc_last_ptr = &winconf->kb.kbs;
-    * loc_last_ptr = 0;
-    while (try_fgets(command, linemax + 1, file, context))
-    {
-        if ('\n' == command[0] || 0 == command[0])
-        {
-            break;
-        }
-        * loc_last_ptr = try_malloc(sizeof(struct KeyBinding), context);
-        struct KeyBinding * kb_p = * loc_last_ptr;
-        kb_p->next = 0;
-        kb_p->key = atoi(command);
-        cmdptr = strchr(command, ' ') + 1;
-        cmdptr[strlen(cmdptr) - 1] = '\0';
-        kb_p->command = get_command(cmdptr);
-        loc_last_ptr = & kb_p->next;
-    }
-
-    /* Init remaining values to zero and cleaning up. */
-    winconf->view = 0;
-    winconf->kb.edit = 0;
-    winconf->kb.select = 0;
-    try_fclose(file, context);
-    free(context);
-}
-
-
-
-static void init_win_from_winconf(char id)
-{
-    char * err = "get_drawfunc_by_char() returns NULL to init_win_from_file().";
-    struct WinConf * winconf = get_winconf_by_id(id);
-    void * f = get_drawfunc_by_char(winconf->draw);
-    exit_err(NULL == f, err);
-    init_win(&winconf->win, winconf->title, winconf->height, winconf->width, f);
-}
-
-
-
-static void save_win_config(char id)
-{
-    char * f_name = "save_win_config()";
-
-    /* Prepare atomic file saving. */
-    char * path_tmp = string_prefixed_id("confclient/windows/Win_tmp_", id);
-    FILE * file = try_fopen(path_tmp, "w", f_name);
-
-    /* Save, line by line, ->title, ->draw, ->height and ->width. */
-    struct WinConf * wc = get_winconf_by_id(id);
-    uint8_t size = strlen(wc->title) + 2;
-    if (size < 7)  /* Ensure that at least 5 + 2 char fit into line so that   */
-    {              /* the digit representation of any uint16_t may be stored. */
-        size = 7;
-    }
-    char line[size];
-    sprintf(line, "%s\n", wc->title);
-    try_fwrite(line, sizeof(char), strlen(line), file, f_name);
-    sprintf(line, "%c\n", wc->draw);
-    try_fwrite(line, sizeof(char), strlen(line), file, f_name);
-    sprintf(line, "%d\n", wc->height);
-    try_fwrite(line, sizeof(char), strlen(line), file, f_name);
-    sprintf(line, "%d\n", wc->width);
-    try_fwrite(line, sizeof(char), strlen(line), file, f_name);
-
-    /* Save window-specific keybindings (->kb.kbs). */
-    uint16_t linemax = 0;
-    struct KeyBinding * kb_p = wc->kb.kbs;
-    while (0 != kb_p)
-    {
-        if (strlen(kb_p->command->dsc_short) > linemax)
-        {
-            linemax = strlen(kb_p->command->dsc_short);
-        }
-        kb_p = kb_p->next;
-    }
-    linemax = linemax + 6;          /* + 6: + 3 digits + whitespace + \n + \0 */
-    char kb_line[linemax];
-    kb_p = wc->kb.kbs;
-    while (0 != kb_p)
-    {
-        sprintf(kb_line, "%d %s\n", kb_p->key, kb_p->command->dsc_short);
-        try_fwrite(kb_line, sizeof(char), strlen(kb_line), file, f_name);
-        kb_p = kb_p->next;
-    }
-
-    /* Finish atomic file saving and clean up. */
-    char * path = string_prefixed_id("confclient/windows/Win_", id);
-    try_fclose_unlink_rename(file, path_tmp, path, f_name);
-    free(path);
-    free(path_tmp);
-}
-
-
-
 static void free_winconf_data(char id)
 {
     struct WinConf * wc = get_winconf_by_id(id);
@@ -229,21 +80,6 @@ static void set_winconf_geometry(char id)
 
 
 
-static struct WinConf * get_winconf_by_id(char id)
-{
-    uint8_t i = 0;
-    while (1)
-    {
-        if (id == world.winconf_db.winconfs[i].id)
-        {
-            return &world.winconf_db.winconfs[i];
-        }
-        i++;
-    }
-}
-
-
-
 static void * get_drawfunc_by_char(char c)
 {
 
@@ -284,6 +120,32 @@ static void * get_drawfunc_by_char(char c)
 
 
 
+extern void init_win_from_winconf(char id)
+{
+    char * err = "get_drawfunc_by_char() returns NULL to init_win_from_file().";
+    struct WinConf * winconf = get_winconf_by_id(id);
+    void * f = get_drawfunc_by_char(winconf->draw);
+    exit_err(NULL == f, err);
+    init_win(&winconf->win, winconf->title, winconf->height, winconf->width, f);
+}
+
+
+
+static struct WinConf * get_winconf_by_id(char id)
+{
+    uint8_t i = 0;
+    while (1)
+    {
+        if (id == world.winconf_db.winconfs[i].id)
+        {
+            return &world.winconf_db.winconfs[i];
+        }
+        i++;
+    }
+}
+
+
+
 extern struct WinConf * get_winconf_by_win(struct Win * win)
 {
     uint8_t i = 0;
@@ -307,48 +169,123 @@ extern struct Win * get_win_by_id(char id)
 
 
 
-extern void init_winconfs()
+extern uint8_t read_winconf_from_file(char * line, uint32_t linemax, FILE * file)
 {
-    char * f_name = "init_winconfs()";
-
-    /* Fill world.winconf_db.winconf_ids with confclient/windows/Win_*
-     * filenames' end chars.
-     */
-    uint8_t max_wins = 255;         /* Maximum number of window ids to store. */
-    DIR * dp = opendir("confclient/windows");
-    exit_trouble(NULL == dp, f_name, "opendir()");
-    struct dirent * fn;
-    errno = 0;
-    char * winconf_ids = try_malloc(max_wins + 1, f_name);
-    uint8_t i = 0;
-    char id;
-    while (NULL != (fn = readdir(dp)) && i < max_wins)
+    char * f_name = "read_winconf_from_file()";
+    int test = try_fgetc(file, f_name);
+    if (EOF == test)
+    {
+        return 0;
+    }
+    struct WinConf winconf;
+    winconf.id = (char) test;
+    winconf.draw = winconf.id;
+    try_fgetc(file, f_name);
+    try_fgets(line, linemax + 1, file, f_name);
+    winconf.title = try_malloc(strlen(line), f_name);
+    memcpy(winconf.title, line, strlen(line) - 1);  /* Eliminate newline char */
+    winconf.title[strlen(line) - 1] = '\0';         /* char at end of string. */
+    try_fgets(line, linemax + 1, file, f_name);
+    winconf.height = atoi(line);
+    winconf.height_type = (0 >= winconf.height);
+    try_fgets(line, linemax + 1, file, f_name);
+    winconf.width = atoi(line);
+    winconf.width_type = (0 >= winconf.width);
+    read_keybindings_from_file(line, linemax, file, &winconf.kb);
+    winconf.win = NULL;
+    winconf.view = 0;
+    winconf.center.y = 0;
+    winconf.center.x = 0;
+    if (world.winconf_db.ids)
+    {
+        uint8_t old_ids_size = strlen(world.winconf_db.ids);
+        char * new_ids = try_malloc(old_ids_size + 1 + 1, f_name);
+        sprintf(new_ids, "%s%c", world.winconf_db.ids, winconf.id);
+        free(world.winconf_db.ids);
+        world.winconf_db.ids = new_ids;
+        uint16_t old_winconfs_size = old_ids_size * sizeof(struct WinConf);
+        uint16_t new_winconfs_size = old_winconfs_size + sizeof(struct WinConf);
+        struct WinConf * new_winconfs = try_malloc(new_winconfs_size, f_name);
+        memcpy(new_winconfs, world.winconf_db.winconfs, old_winconfs_size);
+        new_winconfs[old_ids_size] = winconf;
+        free(world.winconf_db.winconfs);
+        world.winconf_db.winconfs = new_winconfs;
+    }
+    else
     {
-        if (5 == strlen(fn->d_name) && fn->d_name == strstr(fn->d_name, "Win_"))
-        {
-            id = fn->d_name[4];
-            winconf_ids[i] = id;
-            i++;
-        }
+        world.winconf_db.ids = try_malloc(2, f_name);
+        sprintf(world.winconf_db.ids, "%c", winconf.id);
+        world.winconf_db.winconfs = try_malloc(sizeof(struct WinConf), f_name);
+        *world.winconf_db.winconfs = winconf;
     }
-    winconf_ids[i] = '\0';
-    exit_trouble(errno, f_name, "readdir()");
-    exit_trouble(closedir(dp), f_name, "closedir()");
-    world.winconf_db.winconf_ids = try_malloc(strlen(winconf_ids) + 1, f_name);
-    memcpy(world.winconf_db.winconf_ids, winconf_ids, strlen(winconf_ids) + 1);
-    free(winconf_ids);
-
-    /* Initialize world.winconf_db.winconfs from Win_* files named in
-     * world.winconf_db.winconf_ids.
-     */
-    size_t size = strlen(world.winconf_db.winconf_ids) * sizeof(struct WinConf);
-    world.winconf_db.winconfs = try_malloc(size, f_name);
-    i = 0;
-    while (0 != (id = get_next_winconf_id()))
+    return 1;
+}
+
+
+
+extern void write_winconf_of_id_to_file(FILE * file, char c, char * delim)
+{
+    char * f_name = "write_winconf_of_id_to_file()";
+    struct WinConf * wc = get_winconf_by_id(c);
+    uint8_t size = strlen(wc->title) + 2;
+    if (size < 7)  /* Ensure that at least 5 + 2 char fit into line so that   */
+    {              /* the digit representation of any uint16_t may be stored. */
+        size = 7;
+    }
+    char line[size];
+    sprintf(line, "%c\n", wc->draw);
+    try_fwrite(line, sizeof(char), strlen(line), file, f_name);
+    sprintf(line, "%s\n", wc->title);
+    try_fwrite(line, sizeof(char), strlen(line), file, f_name);
+    sprintf(line, "%d\n", wc->height);
+    try_fwrite(line, sizeof(char), strlen(line), file, f_name);
+    sprintf(line, "%d\n", wc->width);
+    try_fwrite(line, sizeof(char), strlen(line), file, f_name);
+    write_keybindings_to_file(file, &wc->kb, delim);
+}
+
+
+
+extern void read_order_wins_visible_active(char * line, uint32_t linemax, FILE * file)
+{
+    char * f_name = "read_order_wins_visible_active()";
+    char win_order[linemax + 1];
+    try_fgets(win_order, linemax + 1, file, f_name);
+    world.winconf_db.order = try_malloc(linemax, f_name);
+    win_order[strlen(win_order) - 1] = '\0';
+    sprintf(world.winconf_db.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.winconf_db.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);
+}
+
+
+
+extern void write_order_wins_visible_active(FILE * file, char * delim)
+{
+    char * f_name = "write_order_wins_visible_active()";
+    char line[strlen(world.winconf_db.ids) + 2];
+    struct Win * w_p = world.wmeta.chain_start;
+    char active = ' ';
+    uint8_t i;
+    for (; NULL != w_p; w_p = w_p->next, i++)
     {
-        init_winconf_from_file(id, &world.winconf_db.winconfs[i]);
-        i++;
+        struct WinConf * wc_p = get_winconf_by_win(w_p);
+        line[i] = wc_p->id;
+        if (w_p == world.wmeta.active)
+        {
+            active = wc_p->id;
+        }
     }
+    line[i] = '\n';
+    line[i + 1] = '\0';
+    try_fwrite(line, sizeof(char), strlen(line), file, f_name);
+    try_fputc(active, file, f_name);
+    try_fputc('\n', file, f_name);
+    try_fwrite(delim, strlen(delim), 1, file, f_name);
 }
 
 
@@ -360,8 +297,12 @@ extern void free_winconfs()
     {
         free_winconf_data(id);
     }
-    free(world.winconf_db.winconf_ids);
+    free(world.winconf_db.ids);
+    world.winconf_db.ids = NULL;
     free(world.winconf_db.winconfs);
+    world.winconf_db.winconfs = NULL;
+    free(world.winconf_db.order);
+    world.winconf_db.order = NULL;
 }
 
 
@@ -377,43 +318,28 @@ extern void init_wins()
 
 
 
-extern void sorted_wintoggle_and_activate()
+extern void sorted_win_toggle_and_activate()
 {
-    char * f_name = "sorted_wintoggle_and_activate()";
-
-    /* Read from file order of windows to be toggled + active win selection. */
-    char * path = "confclient/windows/toggle_order_and_active";
-    FILE * file = try_fopen(path, "r", f_name);
-    uint32_t linemax = textfile_sizes(file, NULL);
-    char win_order[linemax + 1];
-    try_fgets(win_order, linemax + 1, file, f_name);
-    int char_or_eof = try_fgetc(file, f_name);
-    exit_trouble(EOF==char_or_eof, f_name, "fgetc() unexpectedly hitting EOF");
-    uint8_t a = (uint8_t) char_or_eof;
-    try_fclose(file, f_name);
-
-    /* Toggle windows and set active window selection. */
     uint8_t i = 0;
-    for (; i < strlen(win_order) - 1; i++)
+    for (; i < strlen(world.winconf_db.order); i++)
     {
-        if (NULL == strchr(world.winconf_db.winconf_ids, win_order[i]))
+        if (NULL == strchr(world.winconf_db.ids, world.winconf_db.order[i]))
         {
             continue;
         }
-        toggle_window(win_order[i]);
-        if (a == (uint8_t) win_order[i])
+        toggle_window(world.winconf_db.order[i]);
+        if (world.winconf_db.active == (uint8_t) world.winconf_db.order[i])
         {
-            world.wmeta.active = get_win_by_id(win_order[i]);
+            world.wmeta.active = get_win_by_id(world.winconf_db.order[i]);
         }
     }
 }
 
 
-
 extern char get_next_winconf_id()
 {
     static uint8_t i = 0;
-    char c = world.winconf_db.winconf_ids[i];
+    char c = world.winconf_db.ids[i];
     if (0 == c)
     {
         i = 0;
@@ -425,45 +351,6 @@ extern char get_next_winconf_id()
 
 
 
-extern void save_win_configs()
-{
-    char * f_name = "save_win_configs()";
-
-    /* Save individual world.winconf_db.winconfs to their proper files. */
-    uint8_t max_wins = 255;     /* n of WinConf fitting into world.winconf_db */
-    char id;
-    while (0 != (id = get_next_winconf_id()))
-    {
-        save_win_config(id);
-    }
-
-    /* Save order of windows to toggle on start / which to select as active. */
-    char * path     = "confclient/windows/toggle_order_and_active";
-    char * path_tmp = "confclient/windows/toggle_order_and_active_tmp";
-    FILE * file = try_fopen(path_tmp, "w", f_name);
-    char line[max_wins + 2];
-    struct Win * w_p = world.wmeta.chain_start;
-    uint8_t i = 0;
-    while (0 != w_p && i < max_wins)
-    {
-        struct WinConf * wc = get_winconf_by_win(w_p);
-        line[i] = wc->id;
-        w_p = w_p->next;
-        i++;
-    }
-    line[i] = '\n';
-    line[i + 1] = '\0';
-    try_fwrite(line, sizeof(char), strlen(line), file, f_name);
-    if (0 != world.wmeta.active)
-    {
-        struct WinConf * wc = get_winconf_by_win(world.wmeta.active);
-        try_fputc(wc->id, file, f_name);
-    }
-    try_fclose_unlink_rename(file, path_tmp, path, f_name);
-}
-
-
-
 extern void toggle_window(char id)
 {
     struct Win * win = get_win_by_id(id);
diff --git a/src/client/wincontrol.h b/src/client/wincontrol.h
index e025cce..67c72bc 100644
--- a/src/client/wincontrol.h
+++ b/src/client/wincontrol.h
@@ -7,9 +7,9 @@
 #ifndef WINCONTROL_H
 #define WINCONTROL_H
 
-#include <stdint.h> /* for uint8_t, int16_t */
-#include "keybindings.h" /* for KeyBindingDB struct */
-#include "../common/yx_uint16.h" /* for yx_uint16 struct */
+#include <stdint.h> /* uint8_t, int16_t */
+#include "keybindings.h" /* struct KeyBindingDB */
+#include "../common/yx_uint16.h" /* yx_uint16 struct */
 struct Win;
 
 
@@ -17,7 +17,9 @@ struct Win;
 struct WinConfDB
 {
     struct WinConf * winconfs;
-    char * winconf_ids;
+    char * ids;
+    char active; /* id of window selected as active */
+    char * order; /* order of visible windows (identified by IDs) */
 };
 
 /* Stores a window's configuration (like geometry, keybindings) and a pointer to
@@ -46,26 +48,27 @@ struct WinConf
 extern struct WinConf * get_winconf_by_win(struct Win * win);
 extern struct Win * get_win_by_id(char id);
 
-/* Create, initialize (from config files)/free world.winconfs and their Wins. */
-extern void init_winconfs();
+/* Free all WinConf DB data. */
 extern void free_winconfs();
+
+/* Initialize  Win structs for WinConfs in WinConf database. */
 extern void init_wins();
 
-/* Toggle windows in the order desribed by 1st line of toggle_order_and_active
- * file in client config windows directory, where each char may fit a Winconf.id
- * in world.winconfs. Silently ignore id chars not found there. The 1st char of
- * the 2nd line of the same file determines which window (by its .id) to focus
- * as active (but only if this window belongs to the ones just toggled).
+/* Toggle windows in order set by world.win_order. Point active window selection
+ * to window identified by world.winconf_db.active.
  */
-extern void sorted_wintoggle_and_activate();
+extern void sorted_win_toggle_and_activate();
+
+/* Read/write world.win_order and world.winconf_db.active from/to "file". */
+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);
 
 /* Iterate over chars of world.winconf_db.winconf_ids array. Restart after \0.*/
 extern char get_next_winconf_id();
 
-/* Save world.winconfs, visible window chain and active window selection to the
- * respective configuration files in client config windows directory.
- */
-extern void save_win_configs();
+/* Read/write individual WinConf (identified by "c") from/to file. */
+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);
 
 /* Toggle "window configuration" view for active window. Sets sensible
  * Win.center values for the various configuration views (for winconf_geometry:
diff --git a/src/client/world.h b/src/client/world.h
index 80fae71..4e92bb2 100644
--- a/src/client/world.h
+++ b/src/client/world.h
@@ -30,6 +30,7 @@ struct World
     struct yx_uint16 player_pos;
     char * log;
     char * path_server_in;
+    char * path_interface_conf;
     char * player_inventory;
     uint16_t turn;
     uint16_t score;
-- 
2.30.2