Code

screen_*: eliminate redundant wrefresh() calls
[ncmpc.git] / src / screen_keydef.c
index 92c5d3c1ed037a8cbb07bfd4398729b2aeb1e8dc..44b191c26d0a40672473faf6c94b7193b66ca8f7 100644 (file)
@@ -1,5 +1,5 @@
 /* ncmpc (Ncurses MPD Client)
- * (c) 2004-2010 The Music Player Daemon Project
+ * (c) 2004-2017 The Music Player Daemon Project
  * Project homepage: http://musicpd.org
  *
  * This program is free software; you can redistribute it and/or modify
@@ -25,6 +25,8 @@
 #include "conf.h"
 #include "screen.h"
 #include "screen_utils.h"
+#include "options.h"
+#include "Compiler.h"
 
 #include <assert.h>
 #include <errno.h>
@@ -42,13 +44,28 @@ static unsigned command_n_commands = 0;
  * the position of the "apply" item. It's the same as command_n_commands,
  * because array subscripts start at 0, while numbers of items start at 1.
  */
-#define command_item_apply (command_n_commands)
+gcc_pure
+static inline unsigned
+command_item_apply(void)
+{
+       return command_n_commands;
+}
 
 /** the position of the "apply and save" item */
-#define command_item_save  (command_item_apply + 1)
+gcc_pure
+static inline unsigned
+command_item_save(void)
+{
+       return command_item_apply() + 1;
+}
 
-/** the number of items on the "command" view */
-#define command_length     (command_item_save + 1)
+/** the number of items in the "command" view */
+gcc_pure
+static inline unsigned
+command_length(void)
+{
+       return command_item_save() + 1;
+}
 
 
 /**
@@ -61,23 +78,47 @@ static int subcmd = -1;
 static unsigned subcmd_n_keys = 0;
 
 /** The position of the up ("[..]") item */
-#define subcmd_item_up 0
+gcc_const
+static inline unsigned
+subcmd_item_up(void)
+{
+       return 0;
+}
 
 /** The position of the "add a key" item */
-#define subcmd_item_add (subcmd_n_keys + 1)
+gcc_pure
+static inline unsigned
+subcmd_item_add(void)
+{
+       return subcmd_n_keys + 1;
+}
 
 /** The number of items in the list_window, if there's a command being edited */
-#define subcmd_length  (subcmd_item_add + 1)
+gcc_pure
+static inline unsigned
+subcmd_length(void)
+{
+       return subcmd_item_add() + 1;
+}
 
 /** Check whether a given item is a key */
-#define subcmd_item_is_key(i) \
-                       ((i) > subcmd_item_up && (i) < subcmd_item_add)
+gcc_pure
+static inline bool
+subcmd_item_is_key(unsigned i)
+{
+       return (i > subcmd_item_up() && i < subcmd_item_add());
+}
 
 /**
  * Convert an item id (as in lw->selected) into a "key id", which is an array
  * subscript to cmds[subcmd].keys.
  */
-#define subcmd_item_to_key_id(i) ((i) - 1)
+gcc_const
+static inline unsigned
+subcmd_item_to_key_id(unsigned i)
+{
+       return i - 1;
+}
 
 
 static int
@@ -105,31 +146,33 @@ apply_keys(void)
 static int
 save_keys(void)
 {
-       FILE *f;
-       char *filename;
+       char *allocated = NULL;
+       const char *filename = options.key_file;
+       if (filename == NULL) {
+               if (!check_user_conf_dir()) {
+                       screen_status_printf(_("Error: Unable to create directory ~/.ncmpc - %s"),
+                                            strerror(errno));
+                       screen_bell();
+                       return -1;
+               }
 
-       if (check_user_conf_dir()) {
-               screen_status_printf(_("Error: Unable to create directory ~/.ncmpc - %s"),
-                                    strerror(errno));
-               screen_bell();
-               return -1;
+               filename = allocated = build_user_key_binding_filename();
        }
 
-       filename = get_user_key_binding_filename();
-
-       if ((f = fopen(filename,"w")) == NULL) {
+       FILE *f = fopen(filename, "w");
+       if (f == NULL) {
                screen_status_printf(_("Error: %s - %s"), filename, strerror(errno));
                screen_bell();
-               g_free(filename);
+               g_free(allocated);
                return -1;
        }
 
        if (write_key_bindings(f, KEYDEF_WRITE_HEADER))
-               screen_status_printf(_("Error: %s - %s"), filename, strerror(errno));
-       else
                screen_status_printf(_("Wrote %s"), filename);
+       else
+               screen_status_printf(_("Error: %s - %s"), filename, strerror(errno));
 
-       g_free(filename);
+       g_free(allocated);
        return fclose(f);
 }
 
@@ -146,17 +189,41 @@ check_subcmd_length(void)
                        break;
        subcmd_n_keys = i;
 
-       list_window_set_length(lw, subcmd_length);
+       list_window_set_length(lw, subcmd_length());
 }
 
 static void
 keydef_paint(void);
 
+/** lw->start the last time switch_to_subcmd_mode() was called */
+static unsigned saved_start = 0;
+
 static void
-keydef_repaint(void)
+switch_to_subcmd_mode(int cmd)
 {
+       assert(subcmd == -1);
+
+       saved_start = lw->start;
+
+       subcmd = cmd;
+       list_window_reset(lw);
+       check_subcmd_length();
+
+       keydef_paint();
+}
+
+static void
+switch_to_command_mode(void)
+{
+       assert(subcmd != -1);
+
+       list_window_set_length(lw, command_length());
+       list_window_set_cursor(lw, subcmd);
+       subcmd = -1;
+
+       lw->start = saved_start;
+
        keydef_paint();
-       wrefresh(lw->w);
 }
 
 /**
@@ -183,33 +250,37 @@ delete_key(int cmd_index, int key_index)
        screen_status_printf(_("Deleted"));
 
        /* repaint */
-       keydef_repaint();
+       keydef_paint();
 
        /* update key conflict flags */
        check_key_bindings(cmds, NULL, 0);
 }
 
+/* assigns a new key to a key slot */
 static void
-assign_new_key(int cmd_index, int key_index)
+overwrite_key(int cmd_index, int key_index)
 {
-       int key;
-       char *buf;
-       command_t cmd;
+       assert(key_index < MAX_COMMAND_KEYS);
 
-       buf = g_strdup_printf(_("Enter new key for %s: "), cmds[cmd_index].name);
-       key = screen_getch(buf);
+       char *buf = g_strdup_printf(_("Enter new key for %s: "),
+                                   cmds[cmd_index].name);
+       const int key = screen_getch(buf);
        g_free(buf);
 
-       if (key==ERR) {
+       if (key == ERR) {
                screen_status_printf(_("Aborted"));
                return;
        }
 
-       cmd = find_key_command(key, cmds);
+       if (key == '\0') {
+               screen_status_printf(_("Ctrl-Space can't be used"));
+               return;
+       }
+
+       const command_t cmd = find_key_command(key, cmds);
        if (cmd != CMD_NONE) {
                screen_status_printf(_("Error: key %s is already used for %s"),
-                                    key2str(key),
-                                    get_key_command_name(cmd));
+                                    key2str(key), get_key_command_name(cmd));
                screen_bell();
                return;
        }
@@ -222,21 +293,29 @@ assign_new_key(int cmd_index, int key_index)
        check_subcmd_length();
 
        /* repaint */
-       keydef_repaint();
+       keydef_paint();
 
        /* update key conflict flags */
        check_key_bindings(cmds, NULL, 0);
 }
 
+/* assign a new key to a new slot */
+static void
+add_key(int cmd_index)
+{
+       if (subcmd_n_keys < MAX_COMMAND_KEYS)
+               overwrite_key(cmd_index, subcmd_n_keys);
+}
+
 static const char *
-list_callback(unsigned idx, G_GNUC_UNUSED void *data)
+list_callback(unsigned idx, gcc_unused void *data)
 {
        static char buf[256];
 
        if (subcmd == -1) {
-               if (idx == command_item_apply)
+               if (idx == command_item_apply())
                        return _("===> Apply key bindings ");
-               if (idx == command_item_save)
+               if (idx == command_item_save())
                        return _("===> Apply & Save key bindings  ");
 
                assert(idx < (unsigned) command_n_commands);
@@ -260,10 +339,10 @@ list_callback(unsigned idx, G_GNUC_UNUSED void *data)
 
                return buf;
        } else {
-               if (idx == subcmd_item_up)
+               if (idx == subcmd_item_up())
                        return "[..]";
 
-               if (idx == subcmd_item_add) {
+               if (idx == subcmd_item_add()) {
                        g_snprintf(buf, sizeof(buf), "%d. %s",
                                   idx, _("Add new key"));
                        return buf;
@@ -302,24 +381,23 @@ keydef_exit(void)
 }
 
 static void
-keydef_open(G_GNUC_UNUSED struct mpdclient *c)
+keydef_open(gcc_unused struct mpdclient *c)
 {
        if (cmds == NULL) {
                command_definition_t *current_cmds = get_command_definitions();
-               size_t cmds_size;
-
                command_n_commands = 0;
                while (current_cmds[command_n_commands].name)
                        command_n_commands++;
 
                /* +1 for the terminator element */
-               cmds_size = (command_n_commands + 1) * sizeof(command_definition_t);
+               size_t cmds_size = (command_n_commands + 1)
+                       * sizeof(command_definition_t);
                cmds = g_malloc0(cmds_size);
                memcpy(cmds, current_cmds, cmds_size);
        }
 
        subcmd = -1;
-       list_window_set_length(lw, command_length);
+       list_window_set_length(lw, command_length());
 }
 
 static void
@@ -349,59 +427,53 @@ keydef_paint(void)
 }
 
 static bool
-keydef_cmd(G_GNUC_UNUSED struct mpdclient *c, command_t cmd)
+keydef_cmd(gcc_unused struct mpdclient *c, command_t cmd)
 {
        if (cmd == CMD_LIST_RANGE_SELECT)
                return false;
 
        if (list_window_cmd(lw, cmd)) {
-               keydef_repaint();
+               keydef_paint();
                return true;
        }
 
        switch(cmd) {
        case CMD_PLAY:
                if (subcmd == -1) {
-                       if (lw->selected == command_item_apply) {
+                       if (lw->selected == command_item_apply()) {
                                apply_keys();
-                       } else if (lw->selected == command_item_save) {
+                       } else if (lw->selected == command_item_save()) {
                                apply_keys();
                                save_keys();
                        } else {
-                               subcmd = lw->selected;
-                               list_window_reset(lw);
-                               check_subcmd_length();
-
-                               keydef_repaint();
+                               switch_to_subcmd_mode(lw->selected);
                        }
                } else {
-                       if (lw->selected == subcmd_item_up) {
-                               list_window_set_length(lw, command_length);
-                               list_window_set_cursor(lw, subcmd);
-                               subcmd = -1;
-
-                               keydef_repaint();
+                       if (lw->selected == subcmd_item_up()) {
+                               switch_to_command_mode();
+                       } else if (lw->selected == subcmd_item_add()) {
+                               add_key(subcmd);
                        } else {
-                               /* TODO: subcmd_item_add should be handled
-                                  separately, just for clarity */
-                               assign_new_key(subcmd, subcmd_item_to_key_id(lw->selected));
+                               /* just to be sure ;-) */
+                               assert(subcmd_item_is_key(lw->selected));
+                               overwrite_key(subcmd, subcmd_item_to_key_id(lw->selected));
                        }
                }
                return true;
        case CMD_GO_PARENT_DIRECTORY:
-               if (subcmd != -1) {
-                       list_window_set_length(lw, command_length);
-                       list_window_set_cursor(lw, subcmd);
-                       subcmd = -1;
-
-                       keydef_repaint();
-               }
+       case CMD_GO_ROOT_DIRECTORY:
+               if (subcmd != -1)
+                       switch_to_command_mode();
                return true;
        case CMD_DELETE:
                if (subcmd != -1 && subcmd_item_is_key(lw->selected))
                        delete_key(subcmd, subcmd_item_to_key_id(lw->selected));
 
                return true;
+       case CMD_ADD:
+               if (subcmd != -1)
+                       add_key(subcmd);
+               return true;
        case CMD_SAVE_PLAYLIST:
                apply_keys();
                save_keys();
@@ -411,7 +483,7 @@ keydef_cmd(G_GNUC_UNUSED struct mpdclient *c, command_t cmd)
        case CMD_LIST_FIND_NEXT:
        case CMD_LIST_RFIND_NEXT:
                screen_find(lw, cmd, list_callback, NULL);
-               keydef_repaint();
+               keydef_paint();
                return true;
 
        default: