From abdd94745a788288c022a017233014a1eedcaf80 Mon Sep 17 00:00:00 2001
From: Christian Heller <c.heller@plomlompom.de>
Date: Tue, 17 Sep 2013 03:13:24 +0200
Subject: [PATCH] New window "Available keys" shows keybindings available on
 current selection.

---
 README                      |  20 ++++---
 config/commands             |   1 +
 config/keybindings_global   |  13 ++---
 config/windows/Win_k        |   4 ++
 config/windows/toggle_order |   2 +-
 src/control.c               |   5 ++
 src/draw_wins.c             | 101 +++++++++++++++++++++++++++++++++++-
 src/draw_wins.h             |   1 +
 src/wincontrol.c            |   5 ++
 9 files changed, 135 insertions(+), 17 deletions(-)
 create mode 100644 config/windows/Win_k

diff --git a/README b/README
index 8a73d7f..8a9f93d 100644
--- a/README
+++ b/README
@@ -28,14 +28,18 @@ make
 Keybindings and window configuration
 ------------------------------------
 
-In the default window configuration, globally available keybinings are shown at
-game start in the three windows on the left of the screen. The lower two windows
-describe keybindings / actions only available in a window's window configuration
-views -- hit "w" (per default keybindings) to switch the selected / "active"
-window to a view that allows changing its geometry. One further hit on "w"
-switches the window to a view that lists keybindings available specifically for
-that window -- such as for map scrolling actions in the "map" window. All
-keybindings can be changed.
+In the default window configuration, the window appearing on the left sports a
+list of keybindings available globally and additionally via the window currently
+selected as active.
+
+Hit "w" (per default keybindings) to switch the "active" window to a view that
+allows changing its geometry. One further hit on "w" switches the window to a
+view that allows changing its window-specific keybindings. The global
+keybindings may be changed in the "Global keys" window, those of the window
+geometry configuration in the "Window geometry keys" window" and those of the
+window-specific keybindings configuration in the "Window keybinding keys"
+window; by default, these three windows are not visible, but may be turned on by
+hitting the "F5", "F6" and "F7" keys.
 
 What actions are available globally or only in specific windows can be further
 manipulated by editing the files config/keybindings_global and
diff --git a/config/commands b/config/commands
index 0798687..50da77c 100644
--- a/config/commands
+++ b/config/commands
@@ -43,3 +43,4 @@
 43 map_l map left
 44 map_r map right
 45 map_c map center player
+46 to_a_keywin toggle view of available keybindings
diff --git a/config/keybindings_global b/config/keybindings_global
index f272302..68c9b89 100644
--- a/config/keybindings_global
+++ b/config/keybindings_global
@@ -4,12 +4,13 @@
 106 player_d
 104 player_l
 108 player_r
-265 to_g_keywin
-266 to_wg_keywin
-267 to_wk_keywin
-268 to_mapwin
-269 to_infowin
-270 to_logwin
+265 to_a_keywin
+266 to_mapwin
+267 to_infowin
+268 to_logwin
+269 to_g_keywin
+270 to_wg_keywin
+271 to_wk_keywin
 119 winconf
 62 cyc_win_f
 60 cyc_win_b
diff --git a/config/windows/Win_k b/config/windows/Win_k
new file mode 100644
index 0000000..ca67a5f
--- /dev/null
+++ b/config/windows/Win_k
@@ -0,0 +1,4 @@
+Available keys
+k
+0
+29
diff --git a/config/windows/toggle_order b/config/windows/toggle_order
index 0ee8c5e..0b431e9 100644
--- a/config/windows/toggle_order
+++ b/config/windows/toggle_order
@@ -1 +1 @@
-012mil
+kmil
diff --git a/src/control.c b/src/control.c
index a4479ce..c1e295f 100644
--- a/src/control.c
+++ b/src/control.c
@@ -206,6 +206,11 @@ extern uint8_t meta_control(int key, struct World * world)
     {
         scroll_pad(win_meta, '-');
     }
+    else if (key == get_available_keycode_to_action(world, "to_a_keywin"))
+    {
+        uint8_t test = toggle_window(win_meta, get_win_by_id(world, 'k'));
+        exit_err(test, world, err_toggle);
+    }
     else if (key == get_available_keycode_to_action(world, "to_g_keywin"))
     {
         exit_err(toggle_window(win_meta, win_keys), world, err_toggle);
diff --git a/src/draw_wins.c b/src/draw_wins.c
index f0397d9..5b6de1b 100644
--- a/src/draw_wins.c
+++ b/src/draw_wins.c
@@ -17,10 +17,15 @@
 
 
 
-/* Write "text" into window "win" as far as possible. Start on row "start_y". */
+/* Write "text" into window "win" as far as possible. Start on row "start_y".
+ * Break lines at newlines.
+ */
 static void draw_with_linebreaks(struct Win * win, char * text,
                                  uint16_t start_y);
 
+/* Write "line" into window "win" at line "y" as far as it fits into it. */
+static void draw_line(struct Win * win, uint16_t y, char * line);
+
 /* Write "text" not starting from the top but from the bottom of "win". */
 static void draw_text_from_bottom(struct Win * win, char * text);
 
@@ -32,6 +37,17 @@ static void draw_map_objects(struct World * world, struct MapObj * start,
 static void draw_kb_view(struct World * world, struct Win * win,
                          char * f_name, struct KeyBiData * kb, uint8_t start);
 
+/* Draw into window "win" from line "start" on a "title" followed by an empty
+ * line followed by a list of all keybindings starting at kb_p.
+ */
+static uint16_t draw_titled_keybinding_list(struct World * world,
+                                            struct Win * win, uint16_t start,
+                                            char * title,
+                                            struct KeyBinding * kb_p);
+
+
+
+
 
 
 static void draw_with_linebreaks(struct Win * win, char * text,
@@ -78,6 +94,17 @@ static void draw_with_linebreaks(struct Win * win, char * text,
 
 
 
+static void draw_line(struct Win * win, uint16_t y, char * line)
+{
+    uint16_t x = 0;
+    for (; x < win->frame.size.x && x < strlen(line); x++)
+    {
+        mvwaddch(win->frame.curses_win, y, x, line[x]);
+    }
+}
+
+
+
 static void draw_text_from_bottom (struct Win * win, char * text)
 {
     /* Determine number of lines text would have in a window of win's width,
@@ -233,6 +260,51 @@ static void draw_kb_view(struct World * world, struct Win * win,
 
 
 
+static uint16_t draw_titled_keybinding_list(struct World * world,
+                                            struct Win * win, uint16_t start,
+                                            char * title,
+                                            struct KeyBinding * kb_p)
+{
+    uint16_t x, y;
+    uint16_t i = 0;
+    uint8_t state = 0;
+    for (y = start; y < win->frame.size.y && (0 == state || 0 != kb_p); y++)
+    {
+        if (0 == state)
+        {
+            for (x = 0; x < win->frame.size.x; x++)
+            {
+                if (i == strlen(title))
+                {
+                    y++;
+                    state = 1 + (0 == kb_p);
+                    i = 0;
+                    break;
+                }
+                mvwaddch(win->frame.curses_win, y, x, title[i]);
+                i++;
+            }
+            continue;
+        }
+        char * keyname = get_name_to_keycode(world, kb_p->key);
+        char * cmd_dsc = get_command_longdsc(world, kb_p->name);
+        char line[9 + 1 + strlen(cmd_dsc) + 1];
+        sprintf(line, "%-9s %s", keyname, cmd_dsc);
+        free(keyname);
+        kb_p = kb_p->next;
+        draw_line(win, y, line);
+    }
+    if (2 == state)
+    {
+        char * line = "(none)";
+        draw_line(win, y, line);
+        y++;
+    }
+    return y;
+}
+
+
+
 extern void draw_win_log(struct Win * win)
 {
     struct World * world = (struct World *) win->data;
@@ -295,6 +367,31 @@ extern void draw_win_info(struct Win * win)
 
 
 
+extern void draw_win_available_keybindings(struct Win * win)
+{
+    struct World * world = (struct World *) win->data;
+    char * title = "Active window's keybindings:";
+    struct KeyBinding * kb_p;
+    struct WinConf * wc = get_winconf_by_win(world, world->wmeta->active);
+    if     (0 == wc->view)
+    {
+        kb_p = wc->kb.kbs;
+    }
+    else if (1 == wc->view)
+    {
+        kb_p = world->kb_wingeom.kbs;
+    }
+    else if (2 == wc->view)
+    {
+        kb_p = world->kb_winkeys.kbs;
+    }
+    uint16_t offset = draw_titled_keybinding_list(world, win, 0, title, kb_p);
+    draw_titled_keybinding_list(world, win, offset + 1, "Global keybindings:",
+                                world->kb_global.kbs);
+}
+
+
+
 extern void draw_win_keybindings_global(struct Win * win)
 {
     char * f_name = "draw_win_keybindings_global()";
@@ -329,7 +426,7 @@ extern void draw_winconf_keybindings(struct Win * win)
     struct WinConf * wc = get_winconf_by_win(world, win);
     char * title = "Window's keybindings:";
     uint8_t title_space = strlen(title) / win->frame.size.x + 2;
-    mvwaddstr(win->frame.curses_win, 0, 0, "Window's keybindings:");
+    mvwaddstr(win->frame.curses_win, 0, 0, title);
     draw_kb_view(world, win, f_name, &wc->kb, title_space);
 }
 
diff --git a/src/draw_wins.h b/src/draw_wins.h
index d209d82..c0a156c 100644
--- a/src/draw_wins.h
+++ b/src/draw_wins.h
@@ -17,6 +17,7 @@ struct Win;
 extern void draw_win_log(struct Win * win);
 extern void draw_win_map(struct Win * win);
 extern void draw_win_info(struct Win * win);
+extern void draw_win_available_keybindings(struct Win * win);
 extern void draw_win_keybindings_global(struct Win * win);
 extern void draw_win_keybindings_winconf_geometry(struct Win * win);
 extern void draw_win_keybindings_winconf_keybindings(struct Win * win);
diff --git a/src/wincontrol.c b/src/wincontrol.c
index 6095d36..0fbb33c 100644
--- a/src/wincontrol.c
+++ b/src/wincontrol.c
@@ -17,6 +17,7 @@
 #include "rexit.h" /* for exit_err() */
 #include "main.h" /* for World struct */
 #include "draw_wins.h" /* for draw_win_map(), draw_win_info(), draw_win_og(),
+                        * draw_win_available_keybindings(),
                         * draw_win_keybindings_global(),
                         * draw_win_keybindings_winconf_geometry(),
                         * draw_win_keybindings_winconf_keybindings(),
@@ -287,6 +288,10 @@ static void * get_drawfunc_by_char(char c)
     {
         return draw_win_map;
     }
+    else if ('k' == c)
+    {
+        return draw_win_available_keybindings;
+    }
     else if ('0' == c)
     {
         return draw_win_keybindings_global;
-- 
2.30.2