[crossfire] [RFC 3/3] character-specific keybinding files

Arvid Brodin arvidb at kth.se
Mon Oct 28 18:20:49 CDT 2013


As the Subject says. Also removes the weird MULTKEYS definition...


Signed-off-by: Arvid Brodin <arvidb at kth.se>
---
 common/client.h          |  13 ++--
 common/metaserver.c      |   4 --
 gtk-v2/src/account.c     |   5 ++
 gtk-v2/src/create_char.c |   4 ++
 gtk-v2/src/gtk2proto.h   |   1 +
 gtk-v2/src/keys.c        | 165 ++++++++++++++++++++++++-----------------------
 6 files changed, 100 insertions(+), 92 deletions(-)

diff --git a/common/client.h b/common/client.h
index 75d3a54..cb0779a 100644
--- a/common/client.h
+++ b/common/client.h
@@ -40,8 +40,6 @@
 #  include <dmalloc.h>
 #endif
 
-#define MULTKEYS
-
 #define VERSION_CS 1023
 #define VERSION_SC 1029
 
@@ -349,10 +347,13 @@ typedef struct Player_Struct {
     uint16      mapxres,mapyres;        /**< Resolution to draw on the magic
                                          *   map. Only used in client-specific
                                          *   code, so it should move there. */
-#ifdef MULTKEYS
-    char    name[ 40 ];                 /**< Player's name, for player-specific
-                                         *   key files */
-#endif
+    char        *name;                  /**< Name of PC, set and freed in account.c
+                                         *   play_character() (using data returned
+                                         *   from server to AccountPlayersCmd, via
+                                         *   character_choose window,
+                                         *   OR in
+                                         *   send_create_player_to_server() when
+                                         *   new character created. */
 } Client_Player;
 
 /**
diff --git a/common/metaserver.c b/common/metaserver.c
index 3170335..2d68972 100644
--- a/common/metaserver.c
+++ b/common/metaserver.c
@@ -1041,11 +1041,7 @@ int metaserver_select(char *sel)
 
     snprintf(buf, sizeof(buf), "Trying to connect to %s:%d", server_name, port);
     draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_METASERVER, buf);
-#ifdef MULTKEYS
     csocket.fd = init_connection(server_name, port);
-#else
-    csocket.fd = init_connection(server_ip, port);
-#endif
     if (csocket.fd == -1) {
         draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_METASERVER,
                       "Unable to connect to server.");
diff --git a/gtk-v2/src/account.c b/gtk-v2/src/account.c
index 0ed45b8..59c4d64 100644
--- a/gtk-v2/src/account.c
+++ b/gtk-v2/src/account.c
@@ -502,6 +502,11 @@ static void play_character(const char *name)
     SockList_AddString(&sl, "accountplay ");
     SockList_AddString(&sl, name);
     SockList_Send(&sl, csocket.fd);
+
+    if (cpl.name)
+        free(cpl.name);
+    cpl.name = strdup(name);
+    keybindings_init();
 }
 
 /**
diff --git a/gtk-v2/src/create_char.c b/gtk-v2/src/create_char.c
index 567d11a..ef6e709 100644
--- a/gtk-v2/src/create_char.c
+++ b/gtk-v2/src/create_char.c
@@ -357,6 +357,10 @@ static void send_create_player_to_server()
 
     SockList_Send(&sl, csocket.fd);
 
+    if (cpl.name)
+        free(cpl.name);
+    cpl.name = strdup(char_name);
+    keybindings_init();
 }
 
 
diff --git a/gtk-v2/src/gtk2proto.h b/gtk-v2/src/gtk2proto.h
index 26f7c6e..0e894a5 100644
--- a/gtk-v2/src/gtk2proto.h
+++ b/gtk-v2/src/gtk2proto.h
@@ -112,6 +112,7 @@ extern void animate_inventory(void);
 extern void animate_look(void);
 extern void inventory_tick(void);
 /* keys.c */
+extern void keybindings_init();
 extern void keys_init(GtkWidget *window_root);
 extern void bind_key(char *params);
 extern void unbind_key(const char *params);
diff --git a/gtk-v2/src/keys.c b/gtk-v2/src/keys.c
index fa91675..7b2ee61 100644
--- a/gtk-v2/src/keys.c
+++ b/gtk-v2/src/keys.c
@@ -470,24 +470,40 @@ static void init_default_keybindings(void)
     }
 }
 
+static int parse_keys_file(char *filename)
+{
+    int line = 0;
+    FILE *fp;
+    char buf[BIG_BUF];
+
+    CONVERT_FILESPEC_TO_OS_FORMAT(filename);
+    LOG(LOG_INFO, "gtk-v2::init_keys",
+        "Trying to open keybinding file %s", filename);
+
+    fp = fopen(filename, "r");
+    if (fp == NULL)
+        return -1;
+
+    while (fgets(buf, BIG_BUF, fp)) {
+        line++;
+        buf[BIG_BUF - 1] = '\0';
+        parse_keybind_line(buf, line);
+    }
+
+    fclose(fp);
+    return 0;
+}
+
 /**
- * Reads in the keybindings, and initializes special values.  It is called
+ * Reads in the keybindings, and initializes special values. Called
  * from main() as part of the client start up. The function is common to both
  * the x11 and gdk clients.
- *
- * @param window_root The client's main window.
- *
- * @todo Fix the per-character keys file support that is under \#if 0.
  */
-void keys_init(GtkWidget *window_root)
+void keybindings_init()
 {
-    int i, line = 0;
-    FILE *fp;
+    int i;
     char buf[BIG_BUF];
-    GtkTreeViewColumn *column;
-    GtkCellRenderer *renderer;
-    GladeXML *xml_tree;
-    GtkWidget *widget;
+    int res;
 
     for (i = 0; i < MAX_HISTORY; i++) { /* Clear out the bind history log */
         history[i][0] = 0;
@@ -516,7 +532,8 @@ void keys_init(GtkWidget *window_root)
     prevkeysym = NoSymbol;
 
     for (i = 0; i < KEYHASH; i++) {
-        keys[i] = NULL;
+        while (keys[i])
+            keybind_remove(keys[i]);
     }
 
     /*
@@ -528,29 +545,44 @@ void keys_init(GtkWidget *window_root)
      * the same as what it was in the server distribution.  To convert bindings
      * in character files to this format, all that needs to be done is remove
      * the 'key ' at the start of each line.
-     *
-     * We need at least one of these keybinding files to exist - this is where
-     * the various commands are defined.  In theory, we actually don't need to
-     * have any of these defined -- the player could just bind everything.
-     * Probably not a good idea, however.
      */
 
-#if 0
-    /* For Windows, use player name if defined for key file */
-    /* FIXME:  keys_init() is called long before the player logs in, so until
-     * that is fixed, it is pointless to have this code check for cpl.name
-     * being set.  Also, it is completely inappropriate for this to be a
-     * Windows only feature.
-     */
-    if ( strlen( cpl.name ) ) {
-        sprintf( buf, "%s/.crossfire/%s.keys", getenv( "HOME" ), cpl.name );
-    } else {
-        sprintf(buf,"%s/.crossfire/keys", getenv("HOME"));
+    /* Try the character-specific keys file */
+    snprintf(buf, sizeof(buf), "%s/.crossfire/%s.keys", getenv("HOME"), cpl.name);
+    res = parse_keys_file(buf);
+    if (res < 0) {
+        /* Try the user-specific keys file */
+        snprintf(buf, sizeof(buf), "%s/.crossfire/keys", getenv("HOME"));
+        res = parse_keys_file(buf);
     }
-#else
-    snprintf(buf, sizeof(buf), "%s/.crossfire/keys", getenv("HOME"));
-    CONVERT_FILESPEC_TO_OS_FORMAT(buf);
-#endif
+    if ((res < 0) && (client_libdir != NULL)) {
+        /* Try the installation-specific keys file */
+        snprintf(buf, sizeof(buf), "%s/def_keys", client_libdir);
+        res = parse_keys_file(buf);
+    }
+    if (res < 0) {
+        /* Use built-in defaults */
+        LOG(LOG_INFO, "gtk-v2::init_keys",
+            "Could not open any keybindings file; using defaults");
+        init_default_keybindings();
+    }
+}
+
+
+/**
+ * One-time initialization of windows and signals for the keybindings
+ * dialog. It is called from main() as part of the client start up. The
+ * function is common to both the x11 and gdk clients.
+ *
+ * @param window_root The client's main window.
+ */
+void keys_init(GtkWidget *window_root)
+{
+    GtkTreeViewColumn *column;
+    GtkCellRenderer *renderer;
+    GladeXML *xml_tree;
+    GtkWidget *widget;
+    int i;
 
     xml_tree = glade_get_widget_tree(GTK_WIDGET(window_root));
 
@@ -658,34 +690,8 @@ void keys_init(GtkWidget *window_root)
                                          KLIST_KEY,
                                          GTK_SORT_ASCENDING);
 
-    /* Try to read user keybindings and load defaults if that fails. */
-    fp = fopen(buf, "r");
-    if (fp == NULL) {
-        LOG(LOG_INFO, "gtk-v2::init_keys",
-            "Could not open user keybindings; using defaults");
-
-        /* Use built-in defaults if there is no system directory. */
-        if (client_libdir == NULL) {
-            init_default_keybindings();
-            return;
-        }
-
-        /* Try to read system keybindings before using built-in defaults. */
-        snprintf(buf, sizeof(buf), "%s/def_keys", client_libdir);
-        fp = fopen(buf, "r");
-        if (fp == NULL) {
-            init_default_keybindings();
-            return;
-        }
-    }
-
-    while (fgets(buf, BIG_BUF, fp)) {
-        line++;
-        buf[BIG_BUF - 1] = '\0';
-        parse_keybind_line(buf, line);
-    }
-
-    fclose(fp);
+    for (i = 0; i < KEYHASH; i++)
+        keys[i] = NULL;
 }
 
 /**
@@ -1122,8 +1128,6 @@ static void save_individual_key(FILE *fp, struct keybind *kb, KeyCode kc)
  * Next, the entire key hash is traversed and the contents of each slot is
  * dumped to the file, and the output file is closed.  Success or failure is
  * reported to the message pane.
- *
- * @todo Fix the per-character keys file support that is under \#if 0.
  */
 static void save_keys(void)
 {
@@ -1131,31 +1135,15 @@ static void save_keys(void)
     int i;
     FILE *fp;
 
-#if 0
-    /* Use player's name if available */
-    /* FIXME:  keys_init() is called long before the player logs in, so until
-     * that is fixed, it is pointless to have this code check for cpl.name
-     * being set so that a file is written that cannot be opened by under
-     * the existing code structure.  That just means the keybindings saved
-     * while logged in would be inaccessible until the file was copied to
-     * the regular keys file.  Also, this was originally under #ifdef WIN32,
-     * but is completely inappropriate for this to be a Windows only feature.
-     */
-    if ( strlen( cpl.name ) ) {
-        sprintf( buf,"%s/.crossfire/%s.keys", getenv("HOME"), cpl.name );
-    } else {
-        sprintf( buf,"%s/.crossfire/keys", getenv("HOME") );
-    }
-#else
-    snprintf(buf, sizeof(buf), "%s/.crossfire/keys", getenv("HOME"));
+    snprintf(buf, sizeof(buf), "%s/.crossfire/%s.keys", getenv("HOME"), cpl.name);
     CONVERT_FILESPEC_TO_OS_FORMAT(buf);
-#endif
+    LOG(LOG_WARNING, "gtk-v2::save_keys", "Saving keybindings to %s", buf);
 
     if (make_path_to_file(buf) == -1) {
         LOG(LOG_WARNING, "gtk-v2::save_keys", "Could not create %s", buf);
         return;
     }
-    fp = fopen(buf,"w");
+    fp = fopen(buf, "w");
     if (fp == NULL) {
         snprintf(buf2, sizeof(buf2), "Could not open %s, key bindings not saved\n", buf);
         draw_ext_info(NDI_BLACK, MSG_TYPE_CLIENT, MSG_TYPE_CLIENT_ERROR, buf2);
-- 
1.8.1.5


-- 
Arvid


More information about the crossfire mailing list