From b5c1981842402f6fe8d4c02176db923e1955175b Mon Sep 17 00:00:00 2001
From: Lukas Fleischer <calcurse@cryptocrack.de>
Date: Mon, 20 Feb 2012 06:05:08 +0100
Subject: Revamp key bindings display

Refactor the logic inside keys_display_bindings_bar() and remove the
need to place the "show next page" key binding at the right positions.

This used to be a pain to maintain, since we always had to move key
bindings around when introducing a new key. Fix this by passing the
actual key bindings in an array and using a separate parameter for the
"show next page" key binding (which is automatically inserted at the
right places from now on).

Signed-off-by: Lukas Fleischer <calcurse@cryptocrack.de>
---
 src/calcurse.h |  3 ++-
 src/custom.c   | 38 ++++++++++++++++++------------
 src/keys.c     | 50 +++++++++++++++++++--------------------
 src/wins.c     | 74 ++++++++++++++++++++++++++++++++++++----------------------
 4 files changed, 96 insertions(+), 69 deletions(-)

(limited to 'src')

diff --git a/src/calcurse.h b/src/calcurse.h
index 16ef558..e475627 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -739,7 +739,8 @@ int       keys_action_count_keys (enum key);
 char     *keys_action_firstkey (enum key);
 char     *keys_action_nkey (enum key, int);
 char     *keys_action_allkeys (enum key);
-void      keys_display_bindings_bar (WINDOW *, struct binding **, int, int);
+void      keys_display_bindings_bar (WINDOW *, struct binding *[], int, int,
+                                     int, struct binding *);
 void      keys_popup_info (enum key);
 void      keys_save_bindings (FILE *);
 int       keys_check_missing_bindings (void);
diff --git a/src/custom.c b/src/custom.c
index 7e5ded3..6dc6f04 100644
--- a/src/custom.c
+++ b/src/custom.c
@@ -137,10 +137,13 @@ layout_selection_bar (void)
   struct binding right   = {_("Right"),    KEY_MOVE_RIGHT};
   struct binding help    = {_("Help"),     KEY_GENERIC_HELP};
 
-  struct binding *binding[] = {&quit, &select, &up, &down, &left, &right, &help};
-  int binding_size = sizeof (binding) / sizeof (binding[0]);
+  struct binding *bindings[] = {
+      &quit, &select, &up, &down, &left, &right, &help
+  };
+  int bindings_size = sizeof (bindings) / sizeof (bindings[0]);
 
-  keys_display_bindings_bar (win[STA].p, binding, 0, binding_size);
+  keys_display_bindings_bar (win[STA].p, bindings, bindings_size, 0,
+                             bindings_size, NULL);
 }
 
 #define NBLAYOUTS     8
@@ -298,7 +301,9 @@ custom_sidebar_config (void)
   struct binding inc  = {_("Width +"),    KEY_MOVE_UP};
   struct binding dec  = {_("Width -"),    KEY_MOVE_DOWN};
   struct binding help = {_("Help"),       KEY_GENERIC_HELP};
-  struct binding *binding[] = {&inc, &dec, &help, &quit};
+  struct binding *bindings[] = {
+      &inc, &dec, &help, &quit
+  };
   char *help_text =
     _("This configuration screen is used to change the width of the side bar.\n"
       "The side bar is the part of the screen which contains two panels:\n"
@@ -306,11 +311,12 @@ custom_sidebar_config (void)
       "or the appointment list.\n\n"
       "The side bar width can be up to 50% of the total screen width, but\n"
       "can't be smaller than " TOSTRING(SBARMINWIDTH) " characters wide.\n\n");
-  int ch, binding_size;
+  int ch, bindings_size;
 
-  binding_size = sizeof (binding) / sizeof (binding[0]);
+  bindings_size = sizeof (bindings) / sizeof (bindings[0]);
 
-  keys_display_bindings_bar (win[STA].p, binding, 0, binding_size);
+  keys_display_bindings_bar (win[STA].p, bindings, bindings_size, 0,
+                             bindings_size, NULL);
   wins_doupdate ();
 
   while ((ch = keys_getch (win[STA].p, NULL)) != KEY_GENERIC_QUIT)
@@ -348,7 +354,8 @@ custom_sidebar_config (void)
           wins_reinit_panels ();
           wins_update_border (FLAG_ALL);
           wins_update_panels (FLAG_ALL);
-          keys_display_bindings_bar (win[STA].p, binding, 0, binding_size);
+          keys_display_bindings_bar (win[STA].p, bindings, bindings_size, 0,
+                                     bindings_size, NULL);
           wins_doupdate ();
         }
     }
@@ -402,13 +409,13 @@ color_selection_bar (void)
   struct binding left    = {_("Left"),     KEY_MOVE_LEFT};
   struct binding right   = {_("Right"),    KEY_MOVE_RIGHT};
 
-
-  struct binding *binding[] = {
+  struct binding *bindings[] = {
     &quit, &nocolor, &up, &down, &left, &right, &select
   };
-  int binding_size = sizeof (binding) / sizeof (binding[0]);
+  int bindings_size = sizeof (bindings) / sizeof (bindings[0]);
 
-  keys_display_bindings_bar (win[STA].p, binding, 0, binding_size);
+  keys_display_bindings_bar (win[STA].p, bindings, bindings_size, 0,
+                             bindings_size, NULL);
 }
 
 /*
@@ -940,12 +947,13 @@ custom_keys_config_bar (void)
   struct binding left  = {_("Prev Key"), KEY_MOVE_LEFT};
   struct binding right = {_("Next Key"), KEY_MOVE_RIGHT};
 
-  struct binding *binding[] = {
+  struct binding *bindings[] = {
     &quit, &info, &add, &del, &up, &down, &left, &right
   };
-  int binding_size = sizeof (binding) / sizeof (binding[0]);
+  int bindings_size = sizeof (bindings) / sizeof (bindings[0]);
 
-  keys_display_bindings_bar (win[STA].p, binding, 0, binding_size);
+  keys_display_bindings_bar (win[STA].p, bindings, bindings_size, 0,
+                             bindings_size, NULL);
 }
 
 void
diff --git a/src/keys.c b/src/keys.c
index 2bfb97d..657b412 100644
--- a/src/keys.c
+++ b/src/keys.c
@@ -461,41 +461,41 @@ keys_format_label (char *key, int keylen)
 }
 
 void
-keys_display_bindings_bar (WINDOW *win, struct binding **binding, int first_key,
-                           int last_key)
+keys_display_bindings_bar (WINDOW *win, struct binding *bindings[], int count,
+                           int page_base, int page_size, struct binding *more)
 {
-  int i, j, cmdlen, space_between_cmds;
+  /* Padding between two key bindings. */
+  const int padding = (col * 2) / page_size - (KEYS_KEYLEN + KEYS_LABELEN + 1);
+  /* Total length of a key binding (including padding). */
+  const int cmd_len = KEYS_KEYLEN + KEYS_LABELEN + 1 + padding;
 
-  /* Total length of a command. */
-  cmdlen =  KEYS_KEYLEN + 1 + KEYS_LABELEN;
-  space_between_cmds = floor (col / KEYS_CMDS_PER_LINE - cmdlen);
-  cmdlen += space_between_cmds;
+  int i;
 
-  j = 0;
   wins_erase_status_bar ();
-  for (i = first_key; i < last_key; i += 2)
+  for (i = 0; i < page_size && page_base + i < count; i++)
     {
+      /* Location of key and label. */
+      const int key_pos_x = (i / 2) * cmd_len;
+      const int key_pos_y = i % 2;
+      const int label_pos_x = key_pos_x + KEYS_KEYLEN + 1;
+      const int label_pos_y = key_pos_y;
+
+      struct binding *binding;
       char key[KEYS_KEYLEN + 1], *fmtkey;
-      const int KEY_POS = j * cmdlen;
-      const int LABEL_POS = j * cmdlen + KEYS_KEYLEN + 1;
 
-      strncpy (key, keys_action_firstkey (binding[i]->action), KEYS_KEYLEN);
+      if (!more || i < page_size - 1 || page_base + i == count - 1)
+        binding = bindings[page_base + i];
+      else
+        binding = more;
+
+      strncpy (key, keys_action_firstkey (binding->action), KEYS_KEYLEN);
+      key[KEYS_KEYLEN] = '\0';
       fmtkey = keys_format_label (key, KEYS_KEYLEN);
+
       custom_apply_attr (win, ATTR_HIGHEST);
-      mvwprintw (win, 0, KEY_POS, fmtkey);
-      if (i + 1 != last_key)
-        {
-          strncpy (key, keys_action_firstkey (binding[i + 1]->action),
-                   KEYS_KEYLEN);
-          key[KEYS_KEYLEN] = 0;
-          fmtkey = keys_format_label (key, KEYS_KEYLEN);
-          mvwprintw (win, 1, KEY_POS, fmtkey);
-        }
+      mvwprintw (win, key_pos_y, key_pos_x, fmtkey);
       custom_remove_attr (win, ATTR_HIGHEST);
-      mvwprintw (win, 0, LABEL_POS, binding[i]->label);
-      if (i + 1 != last_key)
-        mvwprintw (win, 1, LABEL_POS, binding[i + 1]->label);
-      j++;
+      mvwprintw (win, label_pos_y, label_pos_x, binding->label);
     }
   wnoutrefresh (win);
 }
diff --git a/src/wins.c b/src/wins.c
index 0cbe95a..fa53dcb 100644
--- a/src/wins.c
+++ b/src/wins.c
@@ -645,11 +645,9 @@ wins_launch_external (char *file, char *cmd)
   wins_unprepare_external ();
 }
 
-#define NB_CAL_CMDS	27	/* number of commands while in cal view */
-#define NB_APP_CMDS	32	/* same thing while in appointment view */
-#define NB_TOD_CMDS	31	/* same thing while in todo view */
-#define TOTAL_CMDS	NB_CAL_CMDS + NB_APP_CMDS + NB_TOD_CMDS
-#define CMDS_PER_LINE	6	/* max number of commands per line */
+#define NB_CAL_CMDS    27      /* number of commands while in cal view */
+#define NB_APP_CMDS    32      /* same thing while in appointment view */
+#define NB_TOD_CMDS    31      /* same thing while in todo view */
 
 static unsigned status_page;
 
@@ -663,10 +661,7 @@ void
 wins_status_bar (void)
 {
 #define NB_PANELS	3	/* 3 panels: CALENDAR, APPOINTMENT, TODO */
-  enum win which_pan;
-  int start, end;
-  const int pos[NB_PANELS + 1] =
-      { 0, NB_CAL_CMDS, NB_CAL_CMDS + NB_APP_CMDS, TOTAL_CMDS };
+  const int pos[NB_PANELS] = { 0, 0, 0 };
 
   struct binding help   = {_("Help"),     KEY_GENERIC_HELP};
   struct binding quit   = {_("Quit"),     KEY_GENERIC_QUIT};
@@ -677,7 +672,6 @@ wins_status_bar (void)
   struct binding import = {_("Import"),   KEY_GENERIC_IMPORT};
   struct binding export = {_("Export"),   KEY_GENERIC_EXPORT};
   struct binding togo   = {_("Go to"),    KEY_GENERIC_GOTO};
-  struct binding othr   = {_("OtherCmd"), KEY_GENERIC_OTHER_CMD};
   struct binding conf   = {_("Config"),   KEY_GENERIC_CONFIG_MENU};
   struct binding draw   = {_("Redraw"),   KEY_GENERIC_REDRAW};
   struct binding appt   = {_("Add Appt"), KEY_GENERIC_ADD_APPT};
@@ -706,29 +700,53 @@ wins_status_bar (void)
   struct binding vnote  = {_("ViewNote"), KEY_VIEW_NOTE};
   struct binding rprio  = {_("Prio.+"),   KEY_RAISE_PRIORITY};
   struct binding lprio  = {_("Prio.-"),   KEY_LOWER_PRIORITY};
+  struct binding othr   = {_("OtherCmd"), KEY_GENERIC_OTHER_CMD};
 
-  struct binding *binding[TOTAL_CMDS] = {
-    /* calendar keys */
+  struct binding *bindings_cal[] = {
     &help, &quit, &save, &chgvu, &nview, &pview, &up, &down, &left, &right,
-    &togo, &othr, &import, &export, &weekb, &weeke, &appt, &todo,
-    &gnday, &gpday, &gnweek, &gpweek, &draw, &othr, &today, &conf, &othr,
-    /* appointment keys */
+    &togo, &import, &export, &weekb, &weeke, &appt, &todo, &gnday, &gpday,
+    &gnweek, &gpweek, &draw, &today, &conf
+  };
+
+  struct binding *bindings_apoint[] = {
     &help, &quit, &save, &chgvu, &import, &export, &add, &del, &edit, &view,
-    &pipe, &othr, &draw, &rept, &flag, &enote, &vnote, &up, &down, &gnday,
-    &gpday, &gnweek, &gpweek, &othr, &togo, &today, &conf, &appt, &todo, &cut,
-    &paste, &othr,
-    /* todo keys */
+    &pipe, &draw, &rept, &flag, &enote, &vnote, &up, &down, &gnday, &gpday,
+    &gnweek, &gpweek, &togo, &today, &conf, &appt, &todo, &cut, &paste
+  };
+
+  struct binding *bindings_todo[] = {
     &help, &quit, &save, &chgvu, &import, &export, &add, &del, &edit, &view,
-    &pipe, &othr, &flag, &rprio, &lprio, &enote, &vnote, &up, &down, &gnday,
-    &gpday, &gnweek, &gpweek, &othr, &togo, &today, &conf, &appt, &todo, &draw,
-    &othr
+    &pipe, &flag, &rprio, &lprio, &enote, &vnote, &up, &down, &gnday, &gpday,
+    &gnweek, &gpweek, &togo, &today, &conf, &appt, &todo, &draw
   };
 
-  /* Drawing the keybinding with attribute and label without. */
-  which_pan = wins_slctd ();
-  start = pos[which_pan] + 2 * KEYS_CMDS_PER_LINE * (status_page - 1);
-  end = MIN (start + 2 * KEYS_CMDS_PER_LINE, pos[which_pan + 1]);
-  keys_display_bindings_bar (win[STA].p, binding, start, end);
+  enum win active_panel = wins_slctd ();
+
+  struct binding **bindings;
+  int bindings_size;
+
+  switch (active_panel)
+    {
+    case CAL:
+      bindings = bindings_cal;
+      bindings_size = sizeof (bindings_cal) / sizeof (bindings_cal[0]);
+      break;
+    case APP:
+      bindings = bindings_apoint;
+      bindings_size = sizeof (bindings_apoint) / sizeof (bindings_apoint[0]);
+      break;
+    case TOD:
+      bindings = bindings_todo;
+      bindings_size = sizeof (bindings_todo) / sizeof (bindings_todo[0]);
+      break;
+    default:
+      EXIT (_("unknown panel"));
+      /* NOTREACHED */
+    }
+
+  keys_display_bindings_bar (win[STA].p, bindings, bindings_size,
+                             pos[active_panel] + (KEYS_CMDS_PER_LINE * 2 - 1) *
+                             (status_page - 1), KEYS_CMDS_PER_LINE * 2, &othr);
 }
 
 /* Erase status bar. */
@@ -759,7 +777,7 @@ wins_other_status_page (int panel)
       EXIT (_("unknown panel"));
       /* NOTREACHED */
     }
-  max_page = ceil (nb_item / (2 * CMDS_PER_LINE + 1)) + 1;
+  max_page = nb_item / (KEYS_CMDS_PER_LINE * 2 - 1) + 1;
   if (status_page < max_page)
     status_page++;
   else
-- 
cgit v1.2.3-70-g09d2