[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