2 "$Id: keys.c 10827 2008-12-04 05:12:23Z kbulgrien $";
40 #include <glade/glade.h>
44 #include <gdk/gdkwin32.h>
48 #include <gdk/gdkkeysyms.h>
99 #define MAX_HISTORY 50
100 #define MAX_COMMAND_LEN 256
113 typedef struct Keys {
142 #define KEYF_NORMAL 0x01
143 #define KEYF_FIRE 0x02
144 #define KEYF_RUN 0x04
145 #define KEYF_EDIT 0x08
146 #define KEYF_STANDARD 0x10
147 #define KEYF_ALT 0x20
148 #define KEYF_META 0x40
149 #define KEYF_MODIFIERS 0x67
152 extern const char *const directions[9];
183 if (keys[slot]==NULL) {
186 keys[slot]->
next=NULL;
190 while (newkey->
next!=NULL)
191 newkey = newkey->
next;
193 newkey = newkey->
next;
230 if (buf[0]==
'#' || buf[0]==
'\n')
return;
231 if ((cpnext = strchr(buf,
' '))==NULL) {
232 LOG(
LOG_WARNING,
"gtk::parse_keybind_line",
"Line %d (%s) corrupted in keybinding file.", line,buf);
238 while (*cpnext ==
' ') ++cpnext;
239 cp = strchr(cpnext,
' ');
241 LOG(
LOG_WARNING,
"gtk::parse_keybind_line",
"Line %d (%s) corrupted in keybinding file.", line,buf);
245 cp1 = strchr(cp,
' ');
247 LOG(
LOG_WARNING,
"gtk::parse_keybind_line",
"Line %d (%s) corrupted in keybinding file.", line,buf);
251 keysym = gdk_keyval_from_name(cp);
254 LOG(
LOG_WARNING,
"gtk::parse_keybind_line",
"Could not convert %s into keysym", cp);
257 if (!strcmp(cpnext,
"commandkey")) {
261 if (!strcmp(cpnext,
"altkey0")) {
265 if (!strcmp(cpnext,
"altkey1")) {
269 if (!strcmp(cpnext,
"firekey0")) {
273 if (!strcmp(cpnext,
"firekey1")) {
277 if (!strcmp(cpnext,
"metakey0")) {
281 if (!strcmp(cpnext,
"metakey1")) {
285 if (!strcmp(cpnext,
"runkey0")) {
289 if (!strcmp(cpnext,
"runkey1")) {
293 if (!strcmp(cpnext,
"completekey")) {
297 if (!strcmp(cpnext,
"nextkey")) {
301 if (!strcmp(cpnext,
"prevkey")) {
310 keysym = gdk_keyval_from_name(buf);
312 LOG(
LOG_WARNING,
"gtk::parse_keybind_line",
"Unable to convert line %d (%s) into keysym", line, cp);
316 if ((cpnext = strchr(cp,
' '))==NULL) {
317 LOG(
LOG_WARNING,
"gtk::parse_keybind_line",
"Line %d (%s) corrupted in keybinding file.", line, cp);
323 if ((cpnext = strchr(cp,
' '))==NULL) {
324 LOG(
LOG_WARNING,
"gtk::parse_keybind_line",
"Line %d (%s) corrupted in keybinding file.", line, cp);
357 LOG(
LOG_WARNING,
"gtk::parse_keybind_line",
"Unknown flag (%c) line %d in key binding file",
364 cpnext[strlen(cpnext)-1]=
'\0';
365 if (strlen(cpnext)>(
sizeof(
bind_buf)-1)){
367 LOG(
LOG_WARNING,
"gtk::parse_keybind_line",
"Command too long! Truncated.");
383 for(i=0;i<
sizeof(
def_keys)/
sizeof(
char *);i++) {
403 GtkTreeViewColumn *column;
404 GtkCellRenderer *renderer;
461 sprintf( buf,
"%s/.crossfire/%s.keys", getenv(
"HOME" ),
cpl.
name );
463 sprintf(buf,
"%s/.crossfire/keys", getenv(
"HOME"));
465 snprintf(buf,
sizeof(buf),
"%s/.crossfire/keys", getenv(
"HOME"));
468 xml_tree = glade_get_widget_tree(GTK_WIDGET(window_root));
470 fire_label = glade_xml_get_widget(xml_tree,
"fire_label");
471 run_label = glade_xml_get_widget(xml_tree,
"run_label");
472 entry_commands = glade_xml_get_widget(xml_tree,
"entry_commands");
482 glade_xml_get_widget(xml_tree,
"keybinding_checkbutton_control");
484 glade_xml_get_widget(xml_tree,
"keybinding_checkbutton_shift");
486 glade_xml_get_widget(xml_tree,
"keybinding_checkbutton_alt");
488 glade_xml_get_widget(xml_tree,
"keybinding_checkbutton_meta");
490 glade_xml_get_widget(xml_tree,
"keybinding_checkbutton_stayinedit");
492 glade_xml_get_widget(xml_tree,
"keybinding_entry_key");
494 glade_xml_get_widget(xml_tree,
"keybinding_entry_command");
496 glade_xml_get_widget(xml_tree,
"keybinding_treeview");
498 glade_xml_get_widget(xml_tree,
"keybinding_button_remove");
500 glade_xml_get_widget(xml_tree,
"keybinding_button_update");
502 glade_xml_get_widget(xml_tree,
"keybinding_button_bind");
513 widget = glade_xml_get_widget(xml_tree,
"keybinding_button_clear");
514 g_signal_connect ((gpointer) widget,
"clicked",
517 widget = glade_xml_get_widget(xml_tree,
"keybinding_button_close");
518 g_signal_connect ((gpointer) widget,
"clicked",
521 gtk_widget_set_sensitive(keybinding_button_remove,
FALSE);
522 gtk_widget_set_sensitive(keybinding_button_update,
FALSE);
525 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
530 renderer = gtk_cell_renderer_text_new ();
531 column = gtk_tree_view_column_new_with_attributes (
"Key", renderer,
534 gtk_tree_view_column_set_sort_column_id(column,
KLIST_KEY);
537 renderer = gtk_cell_renderer_text_new ();
538 column = gtk_tree_view_column_new_with_attributes (
"Modifiers", renderer,
541 gtk_tree_view_column_set_sort_column_id(column,
KLIST_MODS);
544 renderer = gtk_cell_renderer_text_new ();
545 column = gtk_tree_view_column_new_with_attributes (
"Edit Mode", renderer,
548 gtk_tree_view_column_set_sort_column_id(column,
KLIST_EDIT);
551 renderer = gtk_cell_renderer_text_new ();
552 column = gtk_tree_view_column_new_with_attributes (
"Command", renderer,
555 gtk_tree_view_column_set_sort_column_id(column,
KLIST_COMMAND);
567 if ((fp=fopen(buf,
"r"))==NULL) {
568 LOG(
LOG_INFO,
"gtk::init_keys",
"Could not open ~/.crossfire/keys, trying to load global bindings");
574 if ((fp=fopen(buf,
"r"))==NULL) {
579 while (fgets(buf,
BIG_BUF, fp)) {
615 gtk_label_set (GTK_LABEL(
run_label),
" ");
666 gtk_label_set (GTK_LABEL(
run_label),
"Run");
674 if (present_flags == 0) present_flags =
KEYF_NORMAL;
676 keyentry = keys[keysym %
KEYHASH];
677 while (keyentry!=NULL) {
678 if ((keyentry->
keysym!=0 && keyentry->
keysym!=keysym) ||
679 (!(keyentry->
flags & present_flags))) {
680 keyentry=keyentry->
next;
683 first_match = keyentry;
687 keyentry=keyentry->
next;
692 if (first_match!=NULL) {
705 snprintf(buf,
sizeof(buf),
"fire %s", first_match->
command);
712 snprintf(buf,
sizeof(buf),
"run %s", first_match->
command);
725 if (key>=
'0' && key<=
'9') {
737 snprintf(buf,
sizeof(buf),
"Key %s%s is not bound to any command. Use bind to associate this keypress with a command",
738 tmpbuf, keysym==NoSymbol?
"unknown": gdk_keyval_name(keysym));
740 if ( ( 65513 != keysym ) && ( 65511 != keysym ) )
785 if(key->
keysym == NoSymbol) {
786 snprintf(buf,
sizeof(buf),
"(null) %i %s %s",
790 snprintf(buf,
sizeof(buf),
"%s %i %s %s",
791 gdk_keyval_name(key->
keysym), 0,
796 if(key->
keysym == NoSymbol) {
797 snprintf(buf,
sizeof(buf),
"key (null) %s %s",
801 snprintf(buf,
sizeof(buf),
"key %s %s %s",
802 gdk_keyval_name(key->
keysym),
820 snprintf(buf,
sizeof(buf),
"Commandkey %s",
824 snprintf(buf,
sizeof(buf),
"Firekeys 1: %s, 2: %s",
829 snprintf(buf,
sizeof(buf),
"Altkeys 1: %s, 2: %s",
834 snprintf(buf,
sizeof(buf),
"Metakeys 1: %s, 2: %s",
839 snprintf(buf,
sizeof(buf),
"Runkeys 1: %s, 2: %s",
844 snprintf(buf,
sizeof(buf),
"Command Completion Key %s",
848 snprintf(buf,
sizeof(buf),
"Next Command in History Key %s",
852 snprintf(buf,
sizeof(buf),
"Previous Command in History Key %s",
860 for (key=keys[i]; key!=NULL; key =key->
next) {
863 snprintf(buf,
sizeof(buf),
"%3d %s",count,
get_key_info(key,0));
883 draw_info(
"Usage: bind [-aefmnr] {<commandline>/commandkey/firekey{1/2}"
884 "/runkey{1/2}/altkey{1/2}/metakey{1/2}"
885 "completekey/nextkey/prevkey}",
NDI_BLACK);
890 while (*params==
' ') params++;
892 if (!strcmp(params,
"commandkey")) {
899 if (!strcmp(params,
"firekey1")) {
905 if (!strcmp(params,
"firekey2")) {
911 if (!strcmp(params,
"metakey1")) {
917 if (!strcmp(params,
"metakey2")) {
923 if (!strcmp(params,
"altkey1")) {
929 if (!strcmp(params,
"altkey2")) {
935 if (!strcmp(params,
"runkey1")) {
942 if (!strcmp(params,
"runkey2")) {
949 if (!strcmp(params,
"completekey")) {
956 if (!strcmp(params,
"prevkey")) {
963 if (!strcmp(params,
"nextkey")) {
970 if (params[0] !=
'-')
975 for (params++; *params !=
' '; params++)
999 snprintf(buf,
sizeof(buf),
"Unsupported or invalid bind flag: '%c'", *params);
1014 if (strlen(params) >=
sizeof(
bind_buf)) {
1015 params[
sizeof(
bind_buf) - 1] =
'\0';
1019 snprintf(buf,
sizeof(buf),
"Push key to bind '%s'.", params);
1041 if (key==NULL)
return;
1072 sprintf( buf,
"%s/.crossfire/%s.keys", getenv(
"HOME"),
cpl.
name );
1074 sprintf( buf,
"%s/.crossfire/keys", getenv(
"HOME") );
1076 snprintf(buf,
sizeof(buf),
"%s/.crossfire/keys", getenv(
"HOME"));
1083 if ((fp=fopen(buf,
"w"))==NULL) {
1084 snprintf(buf2,
sizeof(buf2),
"Could not open %s, key bindings not saved\n", buf);
1089 fprintf(fp,
"! commandkey %s %d\n",
1093 fprintf(fp,
"! firekey0 %s %d\n",
1097 fprintf(fp,
"! firekey1 %s %d\n",
1101 fprintf(fp,
"! metakey0 %s %d\n",
1105 fprintf(fp,
"! metakey1 %s %d\n",
1109 fprintf(fp,
"! altkey0 %s %d\n",
1113 fprintf(fp,
"! altkey1 %s %d\n",
1117 fprintf(fp,
"! runkey0 %s %d\n",
1121 fprintf(fp,
"! runkey1 %s %d\n",
1125 fprintf(fp,
"! completekey %s %d\n",
1130 fprintf(fp,
"! nextkey %s %d\n",
1134 fprintf(fp,
"! prevkey %s %d\n",
1138 for (i = 0; i <
KEYHASH; i++) {
1200 keyentry = keys[keysym %
KEYHASH];
1201 while (keyentry!=NULL) {
1202 if ((keyentry->
keysym!=0 && keyentry->
keysym!=keysym) ||
1204 keyentry=keyentry->
next;
1207 first_match = keyentry;
1211 keyentry=keyentry->
next;
1217 snprintf(buf,
sizeof(buf),
"Warning: Keybind %s may conflict with new binding.", first_match->
command);
1224 snprintf(buf,
sizeof(buf),
"Binded to key '%s' (%i)",
1225 keysym==NoSymbol?
"unknown":gdk_keyval_name(keysym), keysym);
1257 int count=0, keyentry, onkey,global=0;
1261 if (params==NULL || params[0]==
'\0') {
1267 while (*params==
' ') params++;
1269 if (!strcmp(params,
"-a")) {
1273 if (!strncmp(params,
"-g",2)) {
1275 if (!(params=strchr(params,
' '))) {
1280 if ((keyentry=atoi(params))==0) {
1285 for (onkey=0; onkey<
KEYHASH; onkey++) {
1286 for (key=keys[onkey]; key; key =key->
next) {
1289 if (keyentry==count) {
1292 if (key == keys[onkey]) {
1293 keys[onkey] = key->
next;
1300 for (tmp=keys[onkey]; tmp->
next!=NULL; tmp=tmp->
next) {
1301 if (tmp->
next == key) {
1307 "found number entry, but could not find actual key");
1313 draw_info(
"Not found. Try 'unbind' with no options to find entry.",
1320 snprintf(buf,
sizeof(buf),
"Removed binding: %3d %s", count,
get_key_info(key,0));
1335 void keyrelfunc(GtkWidget *widget, GdkEventKey *
event, GtkWidget *window)
1337 if (event->keyval > 0 && ! GTK_WIDGET_HAS_FOCUS(
entry_commands)) {
1340 g_signal_stop_emission_by_name(GTK_OBJECT (window),
"key_release_event");
1350 void keyfunc(GtkWidget *widget, GdkEventKey *
event, GtkWidget *window) {
1371 gdk_input_remove(csocket_fd);
1375 g_signal_stop_emission_by_name(
1376 GTK_OBJECT (window),
"key_press_event");
1380 text = gdk_keyval_name(event->keyval);
1383 g_signal_stop_emission_by_name(
1384 GTK_OBJECT (window),
"key_press_event");
1392 g_signal_stop_emission_by_name(
1393 GTK_OBJECT (window),
"key_press_event");
1401 if (event->keyval > 0) {
1422 if (!(event->state & GDK_CONTROL_MASK)) {
1424 gtk_label_set (GTK_LABEL(
run_label),
" ");
1430 if (!(event->state & GDK_SHIFT_MASK)) {
1438 if ( (event->state & GDK_CONTROL_MASK)
1439 && (event->state & GDK_SHIFT_MASK)
1440 && (event->keyval==GDK_i || event->keyval==GDK_I) ) {
1444 parse_key(event->string[0], event->keyval);
1487 g_signal_stop_emission_by_name(
1488 GTK_OBJECT (window),
"key_press_event");
1506 gtk_clist_clear (GTK_CLIST(keylist));
1508 for (key=keys[i]; key!=NULL; key =key->
next) {
1534 if(key->
keysym != NoSymbol) {
1535 snprintf(buffer[0],
sizeof(buffer[0]),
"%i",count);
1536 snprintf(buffer[1],
sizeof(buffer[1]),
"%s", gdk_keyval_name(key->
keysym));
1537 snprintf(buffer[2],
sizeof(buffer[2]),
"%i",i);
1538 snprintf(buffer[3],
sizeof(buffer[3]),
"%s",buff);
1539 snprintf(buffer[4],
sizeof(buffer[4]),
"%s", key->
command);
1540 buffers[0] = buffer[0];
1541 buffers[1] = buffer[1];
1542 buffers[2] = buffer[2];
1543 buffers[3] = buffer[3];
1544 buffers[4] = buffer[4];
1545 tmprow = gtk_clist_append (GTK_CLIST (keylist), buffers);
1598 if (
history[i][0] == 0)
return;
1618 const gchar *entry_text, *newcommand;
1623 if (newcommand != NULL) {
1642 const gchar *entry_text;
1647 gtk_entry_set_visibility(GTK_ENTRY(entry),
TRUE);
1649 entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
1664 if (entry_text[0] != 0) {
1667 cur_history_position++;
1673 gtk_entry_set_text(GTK_ENTRY(entry),
"");
1681 gtk_widget_grab_focus (GTK_WIDGET(treeview_look));
1708 int i, allbindings=0;
1710 char modifier_buf[256];
1716 for (key=keys[i]; key!=NULL; key =key->
next) {
1719 modifier_buf[0] = 0;
1727 strcat(modifier_buf,
"All ");
1786 if (event->state & GDK_CONTROL_MASK)
1787 gtk_toggle_button_set_active(
1792 gtk_toggle_button_set_active(
1796 if (event->state & GDK_SHIFT_MASK)
1797 gtk_toggle_button_set_active(
1807 gtk_toggle_button_set_active(
1809 gtk_toggle_button_set_active(
1828 GtkTreeModel *model;
1834 LOG(
LOG_ERROR,
"keys.c:on_keybinding_button_remove_clicked",
1835 "Function called with nothing selected\n");
1839 for (onkey = 0; onkey <
KEYHASH; onkey++) {
1840 for (key = keys[onkey]; key; key = key->
next) {
1846 if (key == keys[onkey]) {
1847 keys[onkey] = key->
next;
1854 for (tmp = keys[onkey]; tmp->
next != NULL; tmp = tmp->
next) {
1855 if (tmp->
next == key) {
1863 LOG(
LOG_ERROR,
"keys.c:on_keybinding_button_remove_clicked",
1864 "Unable to find matching key entry\n");
1888 if (gtk_toggle_button_get_active(
1892 if (gtk_toggle_button_get_active(
1896 if (gtk_toggle_button_get_active(
1900 if (gtk_toggle_button_get_active(
1911 if (gtk_toggle_button_get_active(
1916 if (strlen(ed) >=
sizeof(bind_buf)) {
1918 strncpy(bind_buf, ed,
MAX_BUF-1);
1930 *keysym = gdk_keyval_from_name(
1932 if (*keysym == GDK_VoidSymbol) {
1934 "Cannot get valid keysym from selection");
1982 GtkTreeModel *model;
1989 LOG(
LOG_ERROR,
"keys.c:on_keybinding_button_update_clicked",
1990 "Unable to get key_entry structure\n");
1999 LOG(
LOG_ERROR,
"keys.c:on_keybinding_button_update_clicked",
2000 "Nothing selected to update\n");
2030 GtkTreeSelection *selection,
2031 GtkTreeModel *model,
2033 gboolean path_currently_selected,
2042 if (gtk_tree_model_get_iter(model, &iter, path)) {
2048 "Unable to get key_entry structure\n");
2052 gtk_toggle_button_set_active(
2055 gtk_toggle_button_set_active(
2059 gtk_toggle_button_set_active(
2062 gtk_toggle_button_set_active(
2066 gtk_toggle_button_set_active(
2069 gtk_toggle_button_set_active(
2073 gtk_toggle_button_set_active(
2076 gtk_toggle_button_set_active(
2080 gtk_toggle_button_set_active(
2083 gtk_toggle_button_set_active(
2101 gtk_toggle_button_set_active(
2103 gtk_toggle_button_set_active(
2105 gtk_toggle_button_set_active(
2107 gtk_toggle_button_set_active(
2109 gtk_toggle_button_set_active(
2129 GtkTreeModel *model;
static GtkTreeSelection * keybinding_selection
static void parse_key_release(uint32 ks)
static char bind_buf[MAX_BUF]
static uint32 altkeysym[2]
void unbind_key(const char *params)
gboolean keybinding_selection_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata)
GtkWidget * treeview_look
void on_entry_commands_activate(GtkEntry *entry, gpointer user_data)
void on_keybindings_activate(GtkMenuItem *menuitem, gpointer user_data)
GtkWidget * spinbutton_count
void gtk_command_history(int direction)
void on_keybinding_button_remove_clicked(GtkButton *button, gpointer user_data)
static GtkWidget * keybinding_entry_command
void on_keybinding_button_clear_clicked(GtkButton *button, gpointer user_data)
snd_pcm_hw_params_t * params
static uint32 commandkeysym
static uint32 cancelkeysym
static int scroll_history_position
int make_path_to_file(char *filename)
void update_keybinding_list(void)
gboolean on_keybinding_entry_key_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
static GtkWidget * fire_label
void on_keybinding_button_update_clicked(GtkButton *button, gpointer user_data)
static GtkListStore * keybinding_store
const char *const directions[9]
static GtkWidget * keybinding_checkbutton_edit
static GtkWidget * keybinding_checkbutton_alt
void draw_keybindings(GtkWidget *keylist)
static void parse_keybind_line(char *buf, int line, int standard)
void LOG(LogLevel level, const char *origin, const char *format,...)
void on_keybinding_button_bind_clicked(GtkButton *button, gpointer user_data)
void gtk_complete_command(void)
static uint32 runkeysym[2]
static void configure_keys(uint32 keysym)
GtkWidget * entry_commands
static void parse_key(char key, uint32 keysym)
const char *const rcsid_gtk2_keys_c
static GtkWidget * keybinding_entry_key
void draw_message_window(int redraw)
sint16 use_config[CONFIG_NUMS]
static GtkWidget * keybinding_checkbutton_meta
static void save_keys(void)
const char *const def_keys[]
static Key_Entry * keys[KEYHASH]
static void show_keys(int allbindings)
static GtkWidget * keybinding_button_bind
void extended_command(const char *ocommand)
static int cur_history_position
void keys_init(GtkWidget *window_root)
void send_reply(const char *text)
static void init_default_keybindings(void)
static GtkWidget * keybinding_button_remove
static uint32 firekeysym[2]
const char * complete_command(const char *command)
static uint32 * bind_keysym
static GtkWidget * run_label
static void keybinding_get_data(uint32 *keysym, uint8 *flags, const char **command)
static GtkWidget * keybinding_checkbutton_control
static uint32 metakeysym[2]
char * strdup_local(const char *str)
void keyrelfunc(GtkWidget *widget, GdkEventKey *event, GtkWidget *window)
static GtkWidget * keybinding_window
void on_keybinding_button_close_clicked(GtkButton *button, gpointer user_data)
void bind_key(const char *params)
static char * get_key_info(Key_Entry *key, int save_mode)
static void unbind_usage(void)
char history[MAX_HISTORY][MAX_COMMAND_LEN]
void draw_info(const char *str, int color)
static GtkWidget * keybinding_button_update
static void save_individual_key(FILE *fp, Key_Entry *key, KeyCode kc)
void reset_keybinding_status(void)
void draw_prompt(const char *str)
void keyfunc(GtkWidget *widget, GdkEventKey *event, GtkWidget *window)
static void insert_key(uint32 keysym, int flags, const char *command)
static GtkWidget * keybinding_treeview
static uint32 completekeysym
static GtkWidget * keybinding_checkbutton_shift