Crossfire Client, Branches  R11627
keys.c
Go to the documentation of this file.
1 const char * const rcsid_gtk2_keys_c =
2  "$Id: keys.c 10827 2008-12-04 05:12:23Z kbulgrien $";
3 /*
4  Crossfire client, a client program for the crossfire program.
5 
6  Copyright (C) 2005 Mark Wedel & Crossfire Development Team
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 
22  The author can be reached via e-mail to crossfire@metalforge.org
23 */
24 
31 #include <config.h>
32 #include <stdlib.h>
33 #include <sys/stat.h>
34 #ifndef WIN32
35 #include <unistd.h>
36 #endif
37 
38 /* Pick up the gtk headers we need */
39 #include <gtk/gtk.h>
40 #include <glade/glade.h>
41 #ifndef WIN32
42 #include <gdk/gdkx.h>
43 #else
44 #include <gdk/gdkwin32.h>
45 #define NoSymbol 0L
46 typedef int KeyCode;
47 #endif
48 #include <gdk/gdkkeysyms.h>
49 
50 #include "client-types.h"
51 #include "main.h"
52 #include "client.h"
53 #include "proto.h"
54 #include "def-keys.h"
55 
56 #include "image.h"
57 #include "gtk2proto.h"
58 #include "p_cmd.h"
59 
65 static GtkWidget *fire_label, *run_label, *keybinding_window,
72 
73 static GtkListStore *keybinding_store;
74 static GtkTreeSelection *keybinding_selection;
75 
76 GtkWidget *spinbutton_count;
77 GtkWidget *entry_commands;
87 enum {
90 };
99 #define MAX_HISTORY 50
100 #define MAX_COMMAND_LEN 256
102 
113 typedef struct Keys {
114  uint8 flags;
115  sint8 direction;
116  uint32 keysym;
117  char *command;
118  struct Keys *next;
119 } Key_Entry;
124 /***********************************************************************
125  *
126  * Key board input translations are handled here. We don't deal with
127  * the events, but rather KeyCodes and KeySyms.
128  *
129  * It would be nice to deal with only KeySyms, but many keyboards
130  * have keys that do not correspond to a KeySym, so we do need to
131  * support KeyCodes.
132  *
133  ***********************************************************************/
134 
137  cancelkeysym;
138 
139 static int bind_flags=0;
140 static char bind_buf[MAX_BUF];
141 
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];
153 
154 #define KEYHASH 257
176 static void insert_key(uint32 keysym, int flags, const char *command)
177 {
178  Key_Entry *newkey;
179  int i, direction=-1, slot;
180 
181  slot = keysym % KEYHASH;
182 
183  if (keys[slot]==NULL) {
184  keys[slot]=malloc(sizeof(Key_Entry));
185  keys[slot]->command=NULL;
186  keys[slot]->next=NULL;
187  newkey=keys[slot];
188  } else {
189  newkey=keys[slot];
190  while (newkey->next!=NULL)
191  newkey = newkey->next;
192  newkey->next = calloc(1, sizeof(Key_Entry));
193  newkey = newkey->next;
194  }
195  /*
196  * Try to find out if the command is a direction command. If so, keep
197  * track of this fact, so in fire or run mode, things work correctly.
198  */
199  for (i=0; i<9; i++)
200  if (!strcmp(command, directions[i])) {
201  direction=i;
202  break;
203  }
204 
205  newkey->keysym = keysym;
206  newkey->flags = flags;
207  newkey->command = strdup_local(command);
208  newkey->direction = direction;
209 }
210 
218 static void parse_keybind_line(char *buf, int line, int standard)
219 {
220  char *cp, *cpnext;
221  uint32 keysym;
222  int flags;
223 
224  /*
225  * There may be a rare error case when cp is used uninitialized. So let's
226  * be safe
227  */
228  cp = NULL;
229 
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);
233  return;
234  }
235  /* Special keybinding line */
236  if (buf[0] == '!') {
237  char *cp1;
238  while (*cpnext == ' ') ++cpnext;
239  cp = strchr(cpnext, ' ');
240  if (!cp) {
241  LOG(LOG_WARNING,"gtk::parse_keybind_line","Line %d (%s) corrupted in keybinding file.", line,buf);
242  return;
243  }
244  *cp++ = 0; /* Null terminate it */
245  cp1 = strchr(cp, ' ');
246  if (!cp1) {
247  LOG(LOG_WARNING,"gtk::parse_keybind_line","Line %d (%s) corrupted in keybinding file.", line,buf);
248  return;
249  }
250  *cp1 ++ = 0;/* Null terminate it */
251  keysym = gdk_keyval_from_name(cp);
252  /* As of now, all these keys must have keysyms */
253  if (keysym == 0) {
254  LOG(LOG_WARNING,"gtk::parse_keybind_line","Could not convert %s into keysym", cp);
255  return;
256  }
257  if (!strcmp(cpnext,"commandkey")) {
259  return;
260  }
261  if (!strcmp(cpnext,"altkey0")) {
262  altkeysym[0] = keysym;
263  return;
264  }
265  if (!strcmp(cpnext,"altkey1")) {
266  altkeysym[1] = keysym;
267  return;
268  }
269  if (!strcmp(cpnext,"firekey0")) {
270  firekeysym[0] = keysym;
271  return;
272  }
273  if (!strcmp(cpnext,"firekey1")) {
274  firekeysym[1] = keysym;
275  return;
276  }
277  if (!strcmp(cpnext,"metakey0")) {
278  metakeysym[0] = keysym;
279  return;
280  }
281  if (!strcmp(cpnext,"metakey1")) {
282  metakeysym[1] = keysym;
283  return;
284  }
285  if (!strcmp(cpnext,"runkey0")) {
286  runkeysym[0] = keysym;
287  return;
288  }
289  if (!strcmp(cpnext,"runkey1")) {
290  runkeysym[1] = keysym;
291  return;
292  }
293  if (!strcmp(cpnext,"completekey")) {
295  return;
296  }
297  if (!strcmp(cpnext,"nextkey")) {
298  nextkeysym = keysym;
299  return;
300  }
301  if (!strcmp(cpnext,"prevkey")) {
302  prevkeysym = keysym;
303  return;
304  }
305  } else {
306  if (standard) standard=KEYF_STANDARD;
307  else standard=0;
308 
309  *cpnext++ = '\0';
310  keysym = gdk_keyval_from_name(buf);
311  if (!keysym) {
312  LOG(LOG_WARNING,"gtk::parse_keybind_line","Unable to convert line %d (%s) into keysym", line, cp);
313  return;
314  }
315  cp = cpnext;
316  if ((cpnext = strchr(cp,' '))==NULL) {
317  LOG(LOG_WARNING,"gtk::parse_keybind_line","Line %d (%s) corrupted in keybinding file.", line, cp);
318  return;
319  }
320  *cpnext++ = '\0';
321 
322  cp = cpnext;
323  if ((cpnext = strchr(cp,' '))==NULL) {
324  LOG(LOG_WARNING,"gtk::parse_keybind_line","Line %d (%s) corrupted in keybinding file.", line, cp);
325  return;
326  }
327  *cpnext++ = '\0';
328  flags = 0;
329  while (*cp!='\0') {
330  switch (*cp) {
331  case 'A':
332  flags |= KEYF_NORMAL | KEYF_FIRE | KEYF_RUN
333  | KEYF_META | KEYF_ALT;
334  break;
335  case 'E':
336  flags |= KEYF_EDIT;
337  break;
338  case 'F':
339  flags |= KEYF_FIRE;
340  break;
341  case 'L': /* A is used, so using L for alt */
342  flags |= KEYF_ALT;
343  break;
344  case 'M':
345  flags |= KEYF_META;
346  break;
347  case 'N':
348  flags |= KEYF_NORMAL;
349  break;
350  case 'R':
351  flags |= KEYF_RUN;
352  break;
353  case 'S':
354  flags |= KEYF_STANDARD;
355  break;
356  default:
357  LOG(LOG_WARNING,"gtk::parse_keybind_line","Unknown flag (%c) line %d in key binding file",
358  *cp, line);
359  }
360  cp++;
361  }
362 
363  /* Rest of the line is the actual command. Lets kill the newline */
364  cpnext[strlen(cpnext)-1]='\0';
365  if (strlen(cpnext)>(sizeof(bind_buf)-1)){
366  cpnext[sizeof(bind_buf)-1]='\0';
367  LOG(LOG_WARNING,"gtk::parse_keybind_line","Command too long! Truncated.");
368  }
369 
370  insert_key(keysym, flags | standard, cpnext);
371  } /* else if not special binding line */
372 }
373 
378 static void init_default_keybindings(void)
379 {
380  char buf[MAX_BUF];
381  int i;
382 
383  for(i=0;i< sizeof(def_keys)/sizeof(char *);i++) {
384  strcpy(buf,def_keys[i]);
385  parse_keybind_line(buf,i,1);
386  }
387 }
388 
398 void keys_init(GtkWidget *window_root)
399 {
400  int i, line = 0;
401  FILE *fp;
402  char buf[BIG_BUF];
403  GtkTreeViewColumn *column;
404  GtkCellRenderer *renderer;
405  GladeXML *xml_tree;
406  GtkWidget *widget;
407 
408  for (i = 0; i < MAX_HISTORY; i++) /* Clear out the bind history log */
409  history[i][0] = 0;
410 
411  commandkeysym = GDK_apostrophe;
412  firekeysym[0] = GDK_Shift_L;
413  firekeysym[1] = GDK_Shift_R;
414  runkeysym[0] = GDK_Control_L;
415  runkeysym[1] = GDK_Control_R;
416  metakeysym[0] = GDK_Meta_L;
417  metakeysym[1] = GDK_Meta_R;
418  altkeysym[0] = GDK_Alt_L;
419  altkeysym[1] = GDK_Alt_R;
420 
421  completekeysym = GDK_Tab;
422  cancelkeysym = GDK_Escape;
423 
424  /*
425  * Don't set these to anything by default. At least on Sun keyboards, the
426  * keysym for up on both the keypad and arrow keys is the same, so player
427  * needs to rebind this so we get proper keycode. Very unfriendly to log
428  * in and not be able to move north/south.
429  */
430  nextkeysym = NoSymbol;
431  prevkeysym = NoSymbol;
432 
433  for (i=0; i<KEYHASH; i++) {
434  keys[i] = NULL;
435  }
436 
437  /*
438  * We now try to load the keybindings. First place to look is the users
439  * home directory, "~/.crossfire/keys". Using a directory seems like a
440  * good idea, in the future, additional stuff may be stored.
441  *
442  * The format is described in the def_keys file. Note that this file is
443  * the same as what it was in the server distribution. To convert bindings
444  * in character files to this format, all that needs to be done is remove
445  * the 'key ' at the start of each line.
446  *
447  * We need at least one of these keybinding files to exist - this is where
448  * the various commands are defined. In theory, we actually don't need to
449  * have any of these defined -- the player could just bind everything.
450  * Probably not a good idea, however.
451  */
452 
453 #if 0
454  /* For Windows, use player name if defined for key file */
455  /* FIXME: keys_init() is called long before the player logs in, so until
456  * that is fixed, it is pointless to have this code check for cpl.name
457  * being set. Also, it is completely inappropriate for this to be a
458  * Windows only feature.
459  */
460  if ( strlen( cpl.name ) )
461  sprintf( buf, "%s/.crossfire/%s.keys", getenv( "HOME" ), cpl.name );
462  else
463  sprintf(buf,"%s/.crossfire/keys", getenv("HOME"));
464 #else
465  snprintf(buf, sizeof(buf), "%s/.crossfire/keys", getenv("HOME"));
466 #endif
467 
468  xml_tree = glade_get_widget_tree(GTK_WIDGET(window_root));
469 
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");
473  spinbutton_count = glade_xml_get_widget(xml_tree, "spinbutton_count");
474 
475  g_signal_connect ((gpointer) entry_commands, "activate",
476  G_CALLBACK (on_entry_commands_activate), NULL);
477 
478  keybinding_window = glade_xml_get_widget(dialog_xml, "keybinding_window");
479  xml_tree = glade_get_widget_tree(GTK_WIDGET(keybinding_window));
480 
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");
503 
504  g_signal_connect ((gpointer) keybinding_entry_key, "key_press_event",
505  G_CALLBACK (on_keybinding_entry_key_key_press_event), NULL);
506  g_signal_connect ((gpointer) keybinding_button_remove, "clicked",
507  G_CALLBACK (on_keybinding_button_remove_clicked), NULL);
508  g_signal_connect ((gpointer) keybinding_button_update, "clicked",
509  G_CALLBACK (on_keybinding_button_update_clicked), NULL);
510  g_signal_connect ((gpointer) keybinding_button_bind, "clicked",
511  G_CALLBACK (on_keybinding_button_bind_clicked), NULL);
512 
513  widget = glade_xml_get_widget(xml_tree, "keybinding_button_clear");
514  g_signal_connect ((gpointer) widget, "clicked",
515  G_CALLBACK (on_keybinding_button_clear_clicked), NULL);
516 
517  widget = glade_xml_get_widget(xml_tree, "keybinding_button_close");
518  g_signal_connect ((gpointer) widget, "clicked",
519  G_CALLBACK (on_keybinding_button_close_clicked), NULL);
520 
521  gtk_widget_set_sensitive(keybinding_button_remove, FALSE);
522  gtk_widget_set_sensitive(keybinding_button_update, FALSE);
523  keybinding_store = gtk_list_store_new(6,
524  G_TYPE_INT,
525  G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
526  G_TYPE_POINTER
527  );
528  gtk_tree_view_set_model(GTK_TREE_VIEW(keybinding_treeview), GTK_TREE_MODEL(keybinding_store));
529 
530  renderer = gtk_cell_renderer_text_new ();
531  column = gtk_tree_view_column_new_with_attributes ("Key", renderer,
532  "text", KLIST_KEY,
533  NULL);
534  gtk_tree_view_column_set_sort_column_id(column, KLIST_KEY);
535  gtk_tree_view_append_column (GTK_TREE_VIEW (keybinding_treeview), column);
536 
537  renderer = gtk_cell_renderer_text_new ();
538  column = gtk_tree_view_column_new_with_attributes ("Modifiers", renderer,
539  "text", KLIST_MODS,
540  NULL);
541  gtk_tree_view_column_set_sort_column_id(column, KLIST_MODS);
542  gtk_tree_view_append_column (GTK_TREE_VIEW (keybinding_treeview), column);
543 
544  renderer = gtk_cell_renderer_text_new ();
545  column = gtk_tree_view_column_new_with_attributes ("Edit Mode", renderer,
546  "text", KLIST_EDIT,
547  NULL);
548  gtk_tree_view_column_set_sort_column_id(column, KLIST_EDIT);
549  gtk_tree_view_append_column (GTK_TREE_VIEW (keybinding_treeview), column);
550 
551  renderer = gtk_cell_renderer_text_new ();
552  column = gtk_tree_view_column_new_with_attributes ("Command", renderer,
553  "text", KLIST_COMMAND,
554  NULL);
555  gtk_tree_view_column_set_sort_column_id(column, KLIST_COMMAND);
556  gtk_tree_view_append_column (GTK_TREE_VIEW (keybinding_treeview), column);
557 
558 
559  keybinding_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(keybinding_treeview));
560  gtk_tree_selection_set_mode (keybinding_selection, GTK_SELECTION_BROWSE);
561  gtk_tree_selection_set_select_function(keybinding_selection, keybinding_selection_func, NULL, NULL);
562 
563  gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(keybinding_store),
564  KLIST_KEY,
565  GTK_SORT_ASCENDING);
566 
567  if ((fp=fopen(buf,"r"))==NULL) {
568  LOG(LOG_INFO,"gtk::init_keys","Could not open ~/.crossfire/keys, trying to load global bindings");
569  if (client_libdir==NULL) {
571  return;
572  }
573  snprintf(buf, sizeof(buf), "%s/def_keys", client_libdir);
574  if ((fp=fopen(buf,"r"))==NULL) {
576  return;
577  }
578  }
579  while (fgets(buf, BIG_BUF, fp)) {
580  line++;
581  buf[BIG_BUF-1]='\0';
582  parse_keybind_line(buf,line,0);
583  }
584  fclose(fp);
585 }
586 
599 static void parse_key_release(uint32 ks) {
601  /*
602  * Only send stop firing/running commands if we are in actual play mode.
603  * Something smart does need to be done when the character enters a non
604  * play mode with fire or run mode already set, however.
605  */
606  if (ks==firekeysym[0] || ks==firekeysym[1]) {
607  cpl.fire_on=0;
608  clear_fire();
609  gtk_label_set (GTK_LABEL(fire_label)," ");
610  }
611  else if (ks==runkeysym[0] || ks==runkeysym[1]) {
612  cpl.run_on=0;
613  if (use_config[CONFIG_ECHO]) draw_info("stop run",NDI_BLACK);
614  clear_run();
615  gtk_label_set (GTK_LABEL(run_label)," ");
616  }
617  else if (ks==altkeysym[0] || ks==altkeysym[1]) {
618  cpl.alt_on=0;
619  }
620  else if (ks==metakeysym[0] || ks==metakeysym[1]) {
621  cpl.meta_on=0;
622  }
623  /*
624  * Firing is handled on server side. However, to keep more like the old
625  * version, if you release the direction key, you want the firing to stop.
626  * This should do that.
627  */
628  else if (cpl.fire_on)
629  clear_fire();
630 }
631 
638 static void parse_key(char key, uint32 keysym)
639 {
640  Key_Entry *keyentry, *first_match=NULL;
641  int present_flags=0;
642  char buf[MAX_BUF], tmpbuf[MAX_BUF];
643 
644  if (keysym==commandkeysym) {
645  gtk_widget_grab_focus (GTK_WIDGET(entry_commands));
646  gtk_entry_set_visibility(GTK_ENTRY(entry_commands), 1);
648  cpl.no_echo=FALSE;
649  return;
650  }
651  if (keysym==altkeysym[0] ||keysym==altkeysym[1]) {
652  cpl.alt_on=1;
653  return;
654  }
655  if (keysym==metakeysym[0] ||keysym==metakeysym[1]) {
656  cpl.meta_on=1;
657  return;
658  }
659  if (keysym==firekeysym[0] ||keysym==firekeysym[1]) {
660  cpl.fire_on=1;
661  gtk_label_set (GTK_LABEL(fire_label),"Fire");
662  return;
663  }
664  if (keysym==runkeysym[0] || keysym==runkeysym[1]) {
665  cpl.run_on=1;
666  gtk_label_set (GTK_LABEL(run_label),"Run");
667  return;
668  }
669 
670  if (cpl.run_on) present_flags |= KEYF_RUN;
671  if (cpl.fire_on) present_flags |= KEYF_FIRE;
672  if (cpl.alt_on) present_flags |= KEYF_ALT;
673  if (cpl.meta_on) present_flags |= KEYF_META;
674  if (present_flags == 0) present_flags = KEYF_NORMAL;
675 
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;
681  continue;
682  }
683  first_match = keyentry;
684 
685  /* Try to find a prefect match */
686  if ((keyentry->flags & KEYF_MODIFIERS)!= present_flags) {
687  keyentry=keyentry->next;
688  continue;
689  }
690  else break;
691  }
692  if (first_match!=NULL) {
693  if (first_match->flags & KEYF_EDIT) {
694  strcpy(cpl.input_text, first_match->command);
696  gtk_entry_set_text(GTK_ENTRY(entry_commands),cpl.input_text);
697  gtk_widget_grab_focus (GTK_WIDGET(entry_commands));
698  gtk_editable_select_region(GTK_EDITABLE(entry_commands), 0, 0);
699  gtk_editable_set_position(GTK_EDITABLE(entry_commands), -1);
700  return;
701  }
702 
703  if (first_match->direction>=0) {
704  if (cpl.fire_on) {
705  snprintf(buf, sizeof(buf), "fire %s", first_match->command);
706  /* Some spells (dimension door) need a valid count value */
707  cpl.count = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spinbutton_count));
708  fire_dir(first_match->direction);
709  }
710  else if (cpl.run_on) {
711  run_dir(first_match->direction);
712  snprintf(buf, sizeof(buf), "run %s", first_match->command);
713  }
714  else {
715  extended_command(first_match->command);
716  }
717  if (use_config[CONFIG_ECHO]) draw_info(first_match->command,NDI_BLACK);
718  }
719  else {
720  if (use_config[CONFIG_ECHO]) draw_info(first_match->command,NDI_BLACK);
721  extended_command(first_match->command);
722  }
723  return;
724  }
725  if (key>='0' && key<='9') {
726  cpl.count = cpl.count*10 + (key-'0');
727  if (cpl.count>100000) cpl.count%=100000;
728  gtk_spin_button_set_value (GTK_SPIN_BUTTON(spinbutton_count), (float) cpl.count );
729  return;
730  }
731  tmpbuf[0]=0;
732  if (cpl.fire_on) strcat(tmpbuf,"fire+");
733  if (cpl.run_on) strcat(tmpbuf,"run+");
734  if (cpl.alt_on) strcat(tmpbuf,"alt+");
735  if (cpl.meta_on) strcat(tmpbuf,"meta+");
736 
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));
739 #ifdef WIN32
740  if ( ( 65513 != keysym ) && ( 65511 != keysym ) )
741 #endif
742  draw_info(buf,NDI_BLACK);
743  cpl.count=0;
744 }
745 
754 static char * get_key_info(Key_Entry *key, int save_mode)
755 {
756  /* bind buf is the maximum space allowed for a
757  * binded command. We will add additional datas to
758  * it so we increase by MAX_BUF*/
759  static char buf[MAX_BUF+sizeof(bind_buf)];
760 
761  char buff[MAX_BUF];
762  int bi=0;
763 
764  if ((key->flags & KEYF_MODIFIERS) == KEYF_MODIFIERS)
765  buff[bi++] ='A';
766  else {
767  if (key->flags & KEYF_NORMAL)
768  buff[bi++] ='N';
769  if (key->flags & KEYF_FIRE)
770  buff[bi++] ='F';
771  if (key->flags & KEYF_RUN)
772  buff[bi++] ='R';
773  if (key->flags & KEYF_ALT)
774  buff[bi++] ='L';
775  if (key->flags & KEYF_META)
776  buff[bi++] ='M';
777  }
778  if (key->flags & KEYF_EDIT)
779  buff[bi++] ='E';
780  if (key->flags & KEYF_STANDARD)
781  buff[bi++] ='S';
782 
783  buff[bi]='\0';
784  if (save_mode) {
785  if(key->keysym == NoSymbol) {
786  snprintf(buf, sizeof(buf), "(null) %i %s %s",
787  0,buff, key->command);
788  }
789  else {
790  snprintf(buf, sizeof(buf), "%s %i %s %s",
791  gdk_keyval_name(key->keysym), 0,
792  buff, key->command);
793  }
794  }
795  else {
796  if(key->keysym == NoSymbol) {
797  snprintf(buf, sizeof(buf), "key (null) %s %s",
798  buff, key->command);
799  }
800  else {
801  snprintf(buf, sizeof(buf), "key %s %s %s",
802  gdk_keyval_name(key->keysym),
803  buff, key->command);
804  }
805  }
806  return buf;
807 }
808 
814 static void show_keys(int allbindings)
815 {
816  int i, count=1;
817  Key_Entry *key;
818  char buf[MAX_BUF];
819 
820  snprintf(buf, sizeof(buf), "Commandkey %s",
821  commandkeysym==NoSymbol?"unknown":gdk_keyval_name(commandkeysym));
822  draw_info(buf,NDI_BLACK);
823 
824  snprintf(buf, sizeof(buf), "Firekeys 1: %s, 2: %s",
825  firekeysym[0]==NoSymbol?"unknown":gdk_keyval_name(firekeysym[0]),
826  firekeysym[1]==NoSymbol?"unknown":gdk_keyval_name(firekeysym[1]));
827  draw_info(buf,NDI_BLACK);
828 
829  snprintf(buf, sizeof(buf), "Altkeys 1: %s, 2: %s",
830  altkeysym[0]==NoSymbol?"unknown":gdk_keyval_name(altkeysym[0]),
831  altkeysym[1]==NoSymbol?"unknown":gdk_keyval_name(altkeysym[1]));
832  draw_info(buf,NDI_BLACK);
833 
834  snprintf(buf, sizeof(buf), "Metakeys 1: %s, 2: %s",
835  metakeysym[0]==NoSymbol?"unknown":gdk_keyval_name(metakeysym[0]),
836  metakeysym[1]==NoSymbol?"unknown":gdk_keyval_name(metakeysym[1]));
837  draw_info(buf,NDI_BLACK);
838 
839  snprintf(buf, sizeof(buf), "Runkeys 1: %s, 2: %s",
840  runkeysym[0]==NoSymbol?"unknown":gdk_keyval_name(runkeysym[0]),
841  runkeysym[1]==NoSymbol?"unknown":gdk_keyval_name(runkeysym[1]));
842  draw_info(buf,NDI_BLACK);
843 
844  snprintf(buf, sizeof(buf), "Command Completion Key %s",
845  completekeysym==NoSymbol?"unknown":gdk_keyval_name(completekeysym));
846  draw_info(buf,NDI_BLACK);
847 
848  snprintf(buf, sizeof(buf), "Next Command in History Key %s",
849  nextkeysym==NoSymbol?"unknown":gdk_keyval_name(nextkeysym));
850  draw_info(buf,NDI_BLACK);
851 
852  snprintf(buf, sizeof(buf), "Previous Command in History Key %s",
853  prevkeysym==NoSymbol?"unknown":gdk_keyval_name(prevkeysym));
854  draw_info(buf,NDI_BLACK);
855 
856  /*
857  * Perhaps we should start at 8, so that we only show 'active' keybindings?
858  */
859  for (i=0; i<KEYHASH; i++) {
860  for (key=keys[i]; key!=NULL; key =key->next) {
861  if (key->flags & KEYF_STANDARD && !allbindings) continue;
862 
863  snprintf(buf, sizeof(buf), "%3d %s",count, get_key_info(key,0));
864  draw_info(buf,NDI_BLACK);
865  count++;
866  }
867  }
868 }
869 
878 void bind_key(char *params)
879 {
880  char buf[MAX_BUF + 16];
881 
882  if (!params) {
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);
886  return;
887  }
888 
889  /* Skip over any spaces we may have */
890  while (*params==' ') params++;
891 
892  if (!strcmp(params, "commandkey")) {
894  draw_info("Push key to bind new commandkey.",NDI_BLACK);
896  return;
897  }
898 
899  if (!strcmp(params, "firekey1")) {
900  bind_keysym = & firekeysym[0];
901  draw_info("Push key to bind new firekey 1.",NDI_BLACK);
903  return;
904  }
905  if (!strcmp(params, "firekey2")) {
906  bind_keysym = & firekeysym[1];
907  draw_info("Push key to bind new firekey 2.",NDI_BLACK);
909  return;
910  }
911  if (!strcmp(params, "metakey1")) {
912  bind_keysym = & metakeysym[0];
913  draw_info("Push key to bind new metakey 1.",NDI_BLACK);
915  return;
916  }
917  if (!strcmp(params, "metakey2")) {
918  bind_keysym = & metakeysym[1];
919  draw_info("Push key to bind new metakey 2.",NDI_BLACK);
921  return;
922  }
923  if (!strcmp(params, "altkey1")) {
924  bind_keysym = & altkeysym[0];
925  draw_info("Push key to bind new altkey 1.",NDI_BLACK);
927  return;
928  }
929  if (!strcmp(params, "altkey2")) {
930  bind_keysym = & altkeysym[1];
931  draw_info("Push key to bind new altkey 2.",NDI_BLACK);
933  return;
934  }
935  if (!strcmp(params, "runkey1")) {
936  bind_keysym = &runkeysym[0];
937  draw_info("Push key to bind new runkey 1.",NDI_BLACK);
939  return;
940  }
941 
942  if (!strcmp(params, "runkey2")) {
943  bind_keysym = &runkeysym[1];
944  draw_info("Push key to bind new runkey 2.",NDI_BLACK);
946  return;
947  }
948 
949  if (!strcmp(params, "completekey")) {
951  draw_info("Push key to bind new command completeion key",NDI_BLACK);
953  return;
954  }
955 
956  if (!strcmp(params, "prevkey")) {
958  draw_info("Push key to bind new previous command in history key.",NDI_BLACK);
960  return;
961  }
962 
963  if (!strcmp(params, "nextkey")) {
965  draw_info("Push key to bind new next command in history key.",NDI_BLACK);
967  return;
968  }
969 
970  if (params[0] != '-')
972  else {
973  bind_flags =0;
974  bind_keysym=NULL;
975  for (params++; *params != ' '; params++)
976  switch (*params) {
977  case 'a':
978  bind_flags |= KEYF_ALT;
979  break;
980  case 'e':
982  break;
983  case 'f':
985  break;
986  case 'm':
988  break;
989  case 'n':
991  break;
992  case 'r':
993  bind_flags |= KEYF_RUN;
994  break;
995  case '\0':
996  draw_info("Use unbind to remove bindings.",NDI_BLACK);
997  return;
998  default:
999  snprintf(buf, sizeof(buf), "Unsupported or invalid bind flag: '%c'", *params);
1000  draw_info(buf,NDI_BLACK);
1001  return;
1002  }
1003  params++;
1004  }
1005 
1006  if (! (bind_flags & KEYF_MODIFIERS))
1008 
1009  if (!params[0]) {
1010  draw_info("Use unbind to remove bindings.",NDI_BLACK);
1011  return;
1012  }
1013 
1014  if (strlen(params) >= sizeof(bind_buf)) {
1015  params[sizeof(bind_buf) - 1] = '\0';
1016  draw_info("Keybinding too long! Truncated:",NDI_RED);
1017  draw_info(params,NDI_RED);
1018  }
1019  snprintf(buf, sizeof(buf), "Push key to bind '%s'.", params);
1020  draw_info(buf,NDI_BLACK);
1021 
1022  strcpy(bind_buf, params);
1024  return;
1025 }
1026 
1039 static void save_individual_key(FILE *fp, Key_Entry *key, KeyCode kc)
1041  if (key==NULL) return;
1042  fprintf(fp, "%s\n", get_key_info(key, 1));
1043  save_individual_key(fp, key->next, kc);
1044 }
1045 
1055 static void save_keys(void)
1057  char buf[MAX_BUF], buf2[MAX_BUF];
1058  int i;
1059  FILE *fp;
1060 
1061 #if 0
1062  /* Use player's name if available */
1063  /* FIXME: keys_init() is called long before the player logs in, so until
1064  * that is fixed, it is pointless to have this code check for cpl.name
1065  * being set so that a file is written that cannot be opened by under
1066  * the existing code structure. That just means the keybindings saved
1067  * while logged in would be inaccessible until the file was copied to
1068  * the regular keys file. Also, this was originally under #ifdef WIN32,
1069  * but is completely inappropriate for this to be a Windows only feature.
1070  */
1071  if ( strlen( cpl.name ) )
1072  sprintf( buf,"%s/.crossfire/%s.keys", getenv("HOME"), cpl.name );
1073  else
1074  sprintf( buf,"%s/.crossfire/keys", getenv("HOME") );
1075 #else
1076  snprintf(buf, sizeof(buf), "%s/.crossfire/keys", getenv("HOME"));
1077 #endif
1078 
1079  if (make_path_to_file(buf)==-1) {
1080  LOG(LOG_WARNING,"gtk::save_keys","Could not create %s", buf);
1081  return;
1082  }
1083  if ((fp=fopen(buf,"w"))==NULL) {
1084  snprintf(buf2, sizeof(buf2), "Could not open %s, key bindings not saved\n", buf);
1085  draw_info(buf2,NDI_BLACK);
1086  return;
1087  }
1088  if (commandkeysym != GDK_apostrophe && commandkeysym != NoSymbol) {
1089  fprintf(fp, "! commandkey %s %d\n",
1090  gdk_keyval_name(commandkeysym), 0);
1091  }
1092  if (firekeysym[0] != GDK_Shift_L && firekeysym[0] != NoSymbol) {
1093  fprintf(fp, "! firekey0 %s %d\n",
1094  gdk_keyval_name(firekeysym[0]), 0);
1095  }
1096  if (firekeysym[1] != GDK_Shift_R && firekeysym[1] != NoSymbol) {
1097  fprintf(fp, "! firekey1 %s %d\n",
1098  gdk_keyval_name(firekeysym[1]), 0);
1099  }
1100  if (metakeysym[0] != GDK_Shift_L && metakeysym[0] != NoSymbol) {
1101  fprintf(fp, "! metakey0 %s %d\n",
1102  gdk_keyval_name(metakeysym[0]), 0);
1103  }
1104  if (metakeysym[1] != GDK_Shift_R && metakeysym[1] != NoSymbol) {
1105  fprintf(fp, "! metakey1 %s %d\n",
1106  gdk_keyval_name(metakeysym[1]), 0);
1107  }
1108  if (altkeysym[0] != GDK_Shift_L && altkeysym[0] != NoSymbol) {
1109  fprintf(fp, "! altkey0 %s %d\n",
1110  gdk_keyval_name(altkeysym[0]), 0);
1111  }
1112  if (altkeysym[1] != GDK_Shift_R && altkeysym[1] != NoSymbol) {
1113  fprintf(fp, "! altkey1 %s %d\n",
1114  gdk_keyval_name(altkeysym[1]), 0);
1115  }
1116  if (runkeysym[0] != GDK_Control_L && runkeysym[0] != NoSymbol) {
1117  fprintf(fp, "! runkey0 %s %d\n",
1118  gdk_keyval_name(runkeysym[0]), 0);
1119  }
1120  if (runkeysym[1] != GDK_Control_R && runkeysym[1] != NoSymbol) {
1121  fprintf(fp, "! runkey1 %s %d\n",
1122  gdk_keyval_name(runkeysym[1]), 0);
1123  }
1124  if (completekeysym != GDK_Tab && completekeysym != NoSymbol) {
1125  fprintf(fp, "! completekey %s %d\n",
1126  gdk_keyval_name(completekeysym), 0);
1127  }
1128  /* No defaults for these, so if it is set to anything, assume its valid */
1129  if (nextkeysym != NoSymbol) {
1130  fprintf(fp, "! nextkey %s %d\n",
1131  gdk_keyval_name(nextkeysym), 0);
1132  }
1133  if (prevkeysym != NoSymbol) {
1134  fprintf(fp, "! prevkey %s %d\n",
1135  gdk_keyval_name(prevkeysym), 0);
1136  }
1137 
1138  for (i = 0; i < KEYHASH; i++) {
1139  save_individual_key(fp, keys[i], 0);
1140  }
1141  fclose(fp);
1142  /* Should probably check return value on all writes to be sure, but... */
1143  draw_info("Key bindings saved.",NDI_BLACK);
1144 }
1145 
1150 static void configure_keys(uint32 keysym)
1152  char buf[MAX_BUF];
1153  Key_Entry *keyentry, *first_match=NULL;
1154 
1155  /*
1156  * I think that basically if we are not rebinding the special control keys
1157  * (in which case bind_kesym would be set to something) we just want to
1158  * handle these keypresses as normal events.
1159  */
1160  if (bind_keysym==NULL) {
1161  if(keysym == altkeysym[0] || keysym == altkeysym[1]) {
1162  cpl.alt_on =1;
1163  return;
1164  }
1165  if(keysym == metakeysym[0] || keysym == metakeysym[1]) {
1166  cpl.meta_on =1;
1167  return;
1168  }
1169  if(keysym == firekeysym[0] || keysym == firekeysym[1]) {
1170  cpl.fire_on =1;
1172  return;
1173  }
1174  if(keysym == runkeysym[0] || keysym == runkeysym[1]) {
1175  cpl.run_on =1;
1177  return;
1178  }
1179  }
1181  /*
1182  * Try to be clever - take into account shift/control keys being held down
1183  * when binding keys - in this way, player does not have to use -f and -r
1184  * flags to bind for many simple binds.
1185  */
1186  if ((cpl.fire_on || cpl.run_on || cpl.meta_on || cpl.alt_on) &&
1187  (bind_flags & KEYF_MODIFIERS)==KEYF_MODIFIERS) {
1188  bind_flags &= ~KEYF_MODIFIERS;
1189  if (cpl.fire_on) bind_flags |= KEYF_FIRE;
1190  if (cpl.run_on) bind_flags |= KEYF_RUN;
1191  if (cpl.meta_on) bind_flags |= KEYF_META;
1192  if (cpl.alt_on) bind_flags |= KEYF_ALT;
1193  }
1194 
1195  if (bind_keysym!=NULL) {
1197  bind_keysym=NULL;
1198  }
1199  else {
1200  keyentry = keys[keysym % KEYHASH];
1201  while (keyentry!=NULL) {
1202  if ((keyentry->keysym!=0 && keyentry->keysym!=keysym) ||
1203  (!(keyentry->flags & bind_flags))) {
1204  keyentry=keyentry->next;
1205  continue;
1206  }
1207  first_match = keyentry;
1208 
1209  /* Try to find a prefect match */
1210  if ((keyentry->flags & KEYF_MODIFIERS)!= bind_flags) {
1211  keyentry=keyentry->next;
1212  continue;
1213  }
1214  else break;
1215  }
1216  if (first_match) {
1217  snprintf(buf, sizeof(buf), "Warning: Keybind %s may conflict with new binding.", first_match->command);
1218  draw_info(buf,NDI_RED);
1219  }
1220 
1221  insert_key(keysym, bind_flags, bind_buf);
1222  }
1223 
1224  snprintf(buf, sizeof(buf), "Binded to key '%s' (%i)",
1225  keysym==NoSymbol?"unknown":gdk_keyval_name(keysym), keysym);
1226  draw_info(buf,NDI_BLACK);
1227  cpl.fire_on=0;
1228  cpl.run_on=0;
1230 
1231  /*
1232  * Do this each time a new key is bound. This way, we are never actually
1233  * storing any information that needs to be saved when the connection dies
1234  * or the player quits.
1235  */
1236  save_keys();
1237  return;
1238 }
1239 
1243 static void unbind_usage(void)
1245  draw_info("Usage: unbind <entry_number> or",NDI_BLACK);
1246  draw_info("Usage: unbind [-a] [-g] to show existing bindings", NDI_BLACK);
1247  draw_info(" -a shows all (global) bindings", NDI_BLACK);
1248  draw_info(" -g unbinds a global binding", NDI_BLACK);
1249 }
1250 
1255 void unbind_key(const char *params)
1257  int count=0, keyentry, onkey,global=0;
1258  Key_Entry *key, *tmp;
1259  char buf[MAX_BUF];
1260 
1261  if (params==NULL || params[0]=='\0') {
1262  show_keys(0);
1263  return;
1264  }
1265 
1266  /* Skip over any spaces we may have */
1267  while (*params==' ') params++;
1268 
1269  if (!strcmp(params,"-a")) {
1270  show_keys(1);
1271  return;
1272  }
1273  if (!strncmp(params,"-g",2)) {
1274  global=1;
1275  if (!(params=strchr(params,' '))) {
1276  unbind_usage();
1277  return;
1278  }
1279  }
1280  if ((keyentry=atoi(params))==0) {
1281  unbind_usage();
1282  return;
1283  }
1284 
1285  for (onkey=0; onkey<KEYHASH; onkey++) {
1286  for (key=keys[onkey]; key; key =key->next) {
1287  if (global || !(key->flags&KEYF_STANDARD)) count++;
1288  /* We found the key we want to unbind */
1289  if (keyentry==count) {
1290 
1291  /* If it is the first entry, it is easy */
1292  if (key == keys[onkey]) {
1293  keys[onkey] = key->next;
1294  goto unbinded;
1295  }
1296  /*
1297  * Otherwise, we need to figure out where in the link list the
1298  * entry is.
1299  */
1300  for (tmp=keys[onkey]; tmp->next!=NULL; tmp=tmp->next) {
1301  if (tmp->next == key) {
1302  tmp->next =key->next;
1303  goto unbinded;
1304  }
1305  }
1306  LOG(LOG_ERROR, "gtk:unbind_key",
1307  "found number entry, but could not find actual key");
1308  }
1309  }
1310  }
1311  /* Makes things look better to draw the blank line */
1312  draw_info("",NDI_BLACK);
1313  draw_info("Not found. Try 'unbind' with no options to find entry.",
1314  NDI_BLACK);
1315  return;
1316  /*
1317  * Found. Now remove it.
1318  */
1319 unbinded:
1320  snprintf(buf, sizeof(buf), "Removed binding: %3d %s", count, get_key_info(key,0));
1321 
1322  draw_info(buf,NDI_BLACK);
1323  free(key->command);
1324  free(key);
1325  save_keys();
1326 }
1327 
1335 void keyrelfunc(GtkWidget *widget, GdkEventKey *event, GtkWidget *window)
1337  if (event->keyval > 0 && ! GTK_WIDGET_HAS_FOCUS(entry_commands)) {
1338  parse_key_release(event->keyval);
1339  }
1340  g_signal_stop_emission_by_name(GTK_OBJECT (window), "key_release_event");
1341 }
1342 
1350 void keyfunc(GtkWidget *widget, GdkEventKey *event, GtkWidget *window) {
1351  char *text;
1352 
1353  if (!use_config[CONFIG_POPUPS]) {
1354  if ( ((cpl.input_state == Reply_One) || (cpl.input_state == Reply_Many))
1355  && (event->keyval == cancelkeysym) ) {
1356 
1357  /*
1358  * Player hit cancel button during input. Disconnect it (code from
1359  * menubar)
1360  */
1361 
1362  extern gint csocket_fd;
1363 
1364 #ifdef WIN32
1365  closesocket(csocket.fd);
1366 #else
1367  close(csocket.fd);
1368 #endif
1369  csocket.fd = -1;
1370  if (csocket_fd) {
1371  gdk_input_remove(csocket_fd);
1372  csocket_fd=0;
1373  gtk_main_quit();
1374  }
1375  g_signal_stop_emission_by_name(
1376  GTK_OBJECT (window), "key_press_event");
1377  return;
1378  }
1379  if (cpl.input_state == Reply_One) {
1380  text = gdk_keyval_name(event->keyval);
1381  send_reply(text);
1383  g_signal_stop_emission_by_name(
1384  GTK_OBJECT (window), "key_press_event");
1385  return;
1386  }
1387  else if (cpl.input_state == Reply_Many) {
1388  if (GTK_WIDGET_HAS_FOCUS (entry_commands))
1389  gtk_widget_event(GTK_WIDGET(entry_commands), (GdkEvent*)event);
1390  else
1391  gtk_widget_grab_focus (GTK_WIDGET(entry_commands));
1392  g_signal_stop_emission_by_name(
1393  GTK_OBJECT (window), "key_press_event");
1394  return;
1395  }
1396  }
1397  /*
1398  * Better check for really weirdo keys, X doesnt like keyval 0 so avoid
1399  * handling these key values.
1400  */
1401  if (event->keyval > 0) {
1402  if (GTK_WIDGET_HAS_FOCUS (entry_commands)) {
1403  if (event->keyval == completekeysym)
1405  if (event->keyval == prevkeysym || event->keyval == nextkeysym)
1406  gtk_command_history(event->keyval == nextkeysym?0:1);
1407  else
1408  gtk_widget_event(GTK_WIDGET(entry_commands), (GdkEvent*)event);
1409  } else {
1410  switch(cpl.input_state) {
1411  case Playing:
1412  /*
1413  * Specials - do command history - many times, the player
1414  * will want to go the previous command when nothing is
1415  * entered in the command window.
1416  */
1417  if (event->keyval == prevkeysym
1418  || event->keyval == nextkeysym) {
1419  gtk_command_history(event->keyval == nextkeysym?0:1);
1420  } else {
1421  if (cpl.run_on) {
1422  if (!(event->state & GDK_CONTROL_MASK)) {
1423  /* printf("Run is on while ctrl is not\n"); */
1424  gtk_label_set (GTK_LABEL(run_label)," ");
1425  cpl.run_on=0;
1426  stop_run();
1427  }
1428  }
1429  if (cpl.fire_on) {
1430  if (!(event->state & GDK_SHIFT_MASK)) {
1431  /* printf("Fire is on while shift is not\n");*/
1432  gtk_label_set (GTK_LABEL(fire_label)," ");
1433  cpl.fire_on = 0;
1434  stop_fire();
1435  }
1436  }
1437 
1438  if ( (event->state & GDK_CONTROL_MASK)
1439  && (event->state & GDK_SHIFT_MASK)
1440  && (event->keyval==GDK_i || event->keyval==GDK_I) ) {
1441  reset_map();
1442  }
1443 
1444  parse_key(event->string[0], event->keyval);
1445  }
1446  break;
1447 
1448  case Configure_Keys:
1449  configure_keys(event->keyval);
1450  break;
1451 
1452  case Command_Mode:
1453  if ( event->keyval == completekeysym )
1455  if ( event->keyval == prevkeysym
1456  || event->keyval == nextkeysym )
1457  gtk_command_history(event->keyval == nextkeysym?0:1);
1458  else {
1459  gtk_widget_grab_focus (GTK_WIDGET(entry_commands));
1460  /*
1461  * When running in split windows mode, entry_commands
1462  * can't get focus because it is in a different
1463  * window. So we have to pass the event to it
1464  * explicitly.
1465  */
1466  if (GTK_WIDGET_HAS_FOCUS(entry_commands) == 0)
1467  gtk_widget_event(
1468  GTK_WIDGET(entry_commands), (GdkEvent*)event);
1469  }
1470  /*
1471  * Don't pass signal along to default handlers -
1472  * otherwise, we get get crashes in the clist area (gtk
1473  * fault I believe)
1474  */
1475  break;
1476 
1477  case Metaserver_Select:
1478  gtk_widget_grab_focus (GTK_WIDGET(entry_commands));
1479  break;
1480 
1481  default:
1482  LOG(LOG_ERROR, "gtk:keyfunc",
1483  "Unknown input state: %d", cpl.input_state);
1484  }
1485  }
1486  }
1487  g_signal_stop_emission_by_name(
1488  GTK_OBJECT (window), "key_press_event");
1489 }
1490 
1496 void draw_keybindings (GtkWidget *keylist) {
1497  int i, count=1;
1498  Key_Entry *key;
1499  int allbindings=0;
1500  char buff[MAX_BUF];
1501  int bi=0;
1502  char buffer[5][MAX_BUF];
1503  char *buffers[5];
1504  gint tmprow;
1505 
1506  gtk_clist_clear (GTK_CLIST(keylist));
1507  for (i=0; i<KEYHASH; i++) {
1508  for (key=keys[i]; key!=NULL; key =key->next) {
1509  if (key->flags & KEYF_STANDARD && !allbindings) continue;
1510 
1511  bi=0;
1512 
1513  if ((key->flags & KEYF_MODIFIERS) == KEYF_MODIFIERS)
1514  buff[bi++] ='A';
1515  else {
1516  if (key->flags & KEYF_NORMAL)
1517  buff[bi++] ='N';
1518  if (key->flags & KEYF_FIRE)
1519  buff[bi++] ='F';
1520  if (key->flags & KEYF_RUN)
1521  buff[bi++] ='R';
1522  if (key->flags & KEYF_ALT)
1523  buff[bi++] ='L';
1524  if (key->flags & KEYF_META)
1525  buff[bi++] ='M';
1526  }
1527  if (key->flags & KEYF_EDIT)
1528  buff[bi++] ='E';
1529  if (key->flags & KEYF_STANDARD)
1530  buff[bi++] ='S';
1531 
1532  buff[bi]='\0';
1533 
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);
1546  }
1547  count++;
1548  }
1549  }
1550 }
1551 
1555 void x_set_echo(void)
1557  gtk_entry_set_visibility(GTK_ENTRY(entry_commands), !cpl.no_echo);
1558 }
1559 
1565 void draw_prompt(const char *str)
1567  draw_info(str, NDI_WHITE);
1568  gtk_widget_grab_focus (GTK_WIDGET(entry_commands));
1569 }
1570 
1579  if (direction) {
1580  i--;
1581  if (i<0) i+=MAX_HISTORY;
1582  if (i == cur_history_position) return;
1583  } else {
1584  i++;
1585  if (i>=MAX_HISTORY) i = 0;
1586  if (i == cur_history_position) {
1587  /*
1588  * User has forwarded to what should be current entry - reset it
1589  * now.
1590  */
1591  gtk_entry_set_text(GTK_ENTRY(entry_commands), "");
1592  gtk_entry_set_position(GTK_ENTRY(entry_commands), 0);
1594  return;
1595  }
1596  }
1597 
1598  if (history[i][0] == 0) return;
1599 
1601 /* fprintf(stderr,"resetting postion to %d, data = %s\n", i, history[i]);*/
1602  gtk_entry_set_text(GTK_ENTRY(entry_commands), history[i]);
1603  gtk_widget_grab_focus (GTK_WIDGET(entry_commands));
1604  gtk_editable_select_region(GTK_EDITABLE(entry_commands), 0, 0);
1605  gtk_editable_set_position(GTK_EDITABLE(entry_commands), -1);
1606 
1608 }
1609 
1616 void gtk_complete_command(void)
1618  const gchar *entry_text, *newcommand;
1619 
1620  entry_text = gtk_entry_get_text(GTK_ENTRY(entry_commands));
1621  newcommand = complete_command(entry_text);
1622  /* value differ, so update window */
1623  if (newcommand != NULL) {
1624  gtk_entry_set_text(GTK_ENTRY(entry_commands), newcommand);
1625  gtk_widget_grab_focus (GTK_WIDGET(entry_commands));
1626  gtk_editable_select_region(GTK_EDITABLE(entry_commands), 0, 0);
1627  gtk_editable_set_position(GTK_EDITABLE(entry_commands), -1);
1628  }
1629 }
1630 
1638 void
1639 on_entry_commands_activate (GtkEntry *entry,
1640  gpointer user_data)
1641 {
1642  const gchar *entry_text;
1643  extern GtkWidget *treeview_look;
1644 
1645  /* Next reply will reset this as necessary */
1646  if (!use_config[CONFIG_POPUPS])
1647  gtk_entry_set_visibility(GTK_ENTRY(entry), TRUE);
1648 
1649  entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
1650 
1652  strcpy(cpl.input_text, entry_text);
1653  } else if (cpl.input_state == Reply_One || cpl.input_state == Reply_Many) {
1655  strcpy(cpl.input_text, entry_text);
1656  if (cpl.input_state == Reply_One)
1657  cpl.input_text[1] = 0;
1658 
1660 
1661  } else {
1663  /* No reason to do anything for a null string */
1664  if (entry_text[0] != 0) {
1665  strncpy(history[cur_history_position], entry_text, MAX_COMMAND_LEN);
1667  cur_history_position++;
1668  cur_history_position %= MAX_HISTORY;
1670  extended_command(entry_text);
1671  }
1672  }
1673  gtk_entry_set_text(GTK_ENTRY(entry),"");
1674 
1675  /*
1676  * This grab focus is really just so the entry box doesn't have focus -
1677  * this way, keypresses are used to play the game, and not as stuff that
1678  * goes into the entry box. It doesn't make much difference what widget
1679  * this is set to, as long as it is something that can get focus.
1680  */
1681  gtk_widget_grab_focus (GTK_WIDGET(treeview_look));
1682 
1684  {
1686  /*
1687  * This is the gtk_main that is started up by get_metaserver The client
1688  * will start another one once it is connected to a crossfire server
1689  */
1690  gtk_main_quit();
1691  }
1692 }
1693 
1706 void update_keybinding_list(void)
1708  int i, allbindings=0;
1709  Key_Entry *key;
1710  char modifier_buf[256];
1711  GtkTreeIter iter;
1712 
1713  gtk_list_store_clear(keybinding_store);
1714 
1715  for (i=0; i<KEYHASH; i++) {
1716  for (key=keys[i]; key!=NULL; key =key->next) {
1717  if (key->flags & KEYF_STANDARD && !allbindings) continue;
1718 
1719  modifier_buf[0] = 0;
1720 
1721  if ((key->flags & KEYF_MODIFIERS) != KEYF_MODIFIERS) {
1722  if (key->flags & KEYF_ALT) strcat(modifier_buf,"Alt ");
1723  if (key->flags & KEYF_FIRE) strcat(modifier_buf,"Fire ");
1724  if (key->flags & KEYF_RUN) strcat(modifier_buf,"Run ");
1725  if (key->flags & KEYF_META) strcat(modifier_buf,"Meta ");
1726  } else {
1727  strcat(modifier_buf, "All ");
1728  }
1729  if (key->flags & KEYF_STANDARD) strcat(modifier_buf,"(Standard) ");
1730  gtk_list_store_append(keybinding_store, &iter);
1731  gtk_list_store_set(keybinding_store, &iter,
1732  KLIST_ENTRY, i,
1733  KLIST_KEY, gdk_keyval_name(key->keysym),
1734  KLIST_MODS, modifier_buf,
1735  KLIST_EDIT, (key->flags & KEYF_EDIT) ? "Yes":"No",
1736  KLIST_COMMAND, key->command,
1737  KLIST_KEY_ENTRY, key,
1738  -1);
1739  }
1740  }
1742 }
1743 
1750 void
1751 on_keybindings_activate (GtkMenuItem *menuitem,
1752  gpointer user_data)
1753 {
1754  gtk_widget_show(keybinding_window);
1756 }
1757 
1770 gboolean
1771 on_keybinding_entry_key_key_press_event(GtkWidget *widget,
1772  GdkEventKey *event,
1773  gpointer user_data)
1774 {
1775  gtk_entry_set_text(
1776  GTK_ENTRY(keybinding_entry_key), gdk_keyval_name(event->keyval));
1777  /*
1778  * This code is basically taken from the GTKv1 client. However, at some
1779  * level it is broken, since the control/shift/etc masks are hardcoded, yet
1780  * we do let the users redefine them.
1781  *
1782  * The clearing of the modifiers is disabled. In my basic testing, I
1783  * checked the modifiers and then pressed the key - have those modifiers go
1784  * away I think is less intuitive.
1785  */
1786  if (event->state & GDK_CONTROL_MASK)
1787  gtk_toggle_button_set_active(
1788  GTK_TOGGLE_BUTTON(keybinding_checkbutton_control), TRUE);
1789 
1790 #if 0
1791  else
1792  gtk_toggle_button_set_active(
1793  GTK_TOGGLE_BUTTON(keybinding_checkbutton_control), FALSE);
1794 #endif
1795 
1796  if (event->state & GDK_SHIFT_MASK)
1797  gtk_toggle_button_set_active(
1798  GTK_TOGGLE_BUTTON(keybinding_checkbutton_shift), TRUE);
1799 
1800 #if 0
1801  else
1802  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(keybinding_checkbutton_shift), FALSE);
1803 
1804  /* The GDK_MOD_MASK* will likely correspond to alt and meta, yet there is
1805  * no way to be sure what goes to what, so easiest to just not allow them.
1806  */
1807  gtk_toggle_button_set_active(
1808  GTK_TOGGLE_BUTTON(keybinding_checkbutton_alt), FALSE);
1809  gtk_toggle_button_set_active(
1810  GTK_TOGGLE_BUTTON(keybinding_checkbutton_meta), FALSE);
1811 #endif
1812 
1813  /* Returning TRUE prevents widget from getting this event */
1814  return TRUE;
1815 }
1816 
1824 void
1825 on_keybinding_button_remove_clicked (GtkButton *button,
1826  gpointer user_data)
1827 {
1828  GtkTreeModel *model;
1829  GtkTreeIter iter;
1830  Key_Entry *entry, *key, *tmp;
1831  int onkey;
1832 
1833  if (!gtk_tree_selection_get_selected(keybinding_selection, &model, &iter)) {
1834  LOG(LOG_ERROR, "keys.c:on_keybinding_button_remove_clicked",
1835  "Function called with nothing selected\n");
1836  return;
1837  }
1838  gtk_tree_model_get(model, &iter, KLIST_KEY_ENTRY, &entry, -1);
1839  for (onkey = 0; onkey < KEYHASH; onkey++) {
1840  for (key = keys[onkey]; key; key = key->next) {
1841  if (key == entry) {
1842  /*
1843  * This code is directly from unbind_key() above If it is the
1844  * first entry, it is easy
1845  */
1846  if (key == keys[onkey]) {
1847  keys[onkey] = key->next;
1848  goto unbinded;
1849  }
1850  /*
1851  * Otherwise, we need to figure out where in the link list the
1852  * entry is.
1853  */
1854  for (tmp = keys[onkey]; tmp->next != NULL; tmp = tmp->next) {
1855  if (tmp->next == key) {
1856  tmp->next = key->next;
1857  goto unbinded;
1858  }
1859  }
1860  }
1861  }
1862  }
1863  LOG(LOG_ERROR, "keys.c:on_keybinding_button_remove_clicked",
1864  "Unable to find matching key entry\n");
1865 
1866 unbinded:
1867  free(key->command);
1868  free(key);
1869  save_keys();
1871 }
1872 
1882 static void keybinding_get_data(uint32 *keysym, uint8 *flags, const char **command)
1884  static char bind_buf[MAX_BUF];
1885  const char *ed;
1886  *flags = 0;
1887 
1888  if (gtk_toggle_button_get_active(
1889  GTK_TOGGLE_BUTTON(keybinding_checkbutton_control)))
1890  *flags |= KEYF_RUN;
1891 
1892  if (gtk_toggle_button_get_active(
1893  GTK_TOGGLE_BUTTON(keybinding_checkbutton_shift)))
1894  *flags |= KEYF_FIRE;
1895 
1896  if (gtk_toggle_button_get_active(
1897  GTK_TOGGLE_BUTTON(keybinding_checkbutton_alt)))
1898  *flags |= KEYF_ALT;
1899 
1900  if (gtk_toggle_button_get_active(
1901  GTK_TOGGLE_BUTTON(keybinding_checkbutton_meta)))
1902  *flags |= KEYF_META;
1903 
1904  /* Set the KEYF_NORMAL flag when either none or all of the Run, Fire, Alt,
1905  * Meta checkboxes are checked. This closely matches the combined existing
1906  * logic in the parse_key() and get_key_info() functions.
1907  */
1908  if (! *flags || (*flags | KEYF_NORMAL) == KEYF_MODIFIERS)
1909  *flags |= KEYF_NORMAL;
1910 
1911  if (gtk_toggle_button_get_active(
1912  GTK_TOGGLE_BUTTON(keybinding_checkbutton_edit)))
1913  *flags |= KEYF_EDIT;
1914 
1915  ed = gtk_entry_get_text(GTK_ENTRY(keybinding_entry_command));
1916  if (strlen(ed) >= sizeof(bind_buf)) {
1917  draw_info("Keybinding too long! Truncated.",NDI_RED);
1918  strncpy(bind_buf, ed, MAX_BUF-1);
1919  bind_buf[MAX_BUF-1] = 0;
1920  *command = bind_buf;
1921  } else {
1922  *command = ed;
1923  }
1924 
1925  /*
1926  * This isn't ideal - when the key is pressed, we convert it to a string,
1927  * and now we are converting it back. It'd be nice to tuck the keysym
1928  * itself away someplace.
1929  */
1930  *keysym = gdk_keyval_from_name(
1931  gtk_entry_get_text(GTK_ENTRY(keybinding_entry_key)));
1932  if (*keysym == GDK_VoidSymbol) {
1933  LOG(LOG_ERROR, "keys.c:keybinding_get_data",
1934  "Cannot get valid keysym from selection");
1935  }
1936 }
1937 
1944 void
1945 on_keybinding_button_bind_clicked (GtkButton *button,
1946  gpointer user_data)
1947 {
1948  uint32 keysym;
1949  uint8 flags;
1950  const char *command;
1951 
1952  keybinding_get_data(&keysym, &flags, &command);
1953 
1954  /* insert_key will do a strdup of command for us */
1955  insert_key(keysym, flags, command);
1956 
1957  /*
1958  * I think it is more appropriate to clear the fields once the user adds
1959  * it. I suppose the ideal case would be to select the newly inserted
1960  * keybinding.
1961  */
1964  save_keys();
1965 }
1966 
1976 void
1977 on_keybinding_button_update_clicked (GtkButton *button,
1978  gpointer user_data)
1979 {
1980  GtkTreeIter iter;
1981  Key_Entry *entry;
1982  GtkTreeModel *model;
1983  const char *buf;
1984 
1985  if (gtk_tree_selection_get_selected(keybinding_selection, &model, &iter)) {
1986  gtk_tree_model_get(model, &iter, KLIST_KEY_ENTRY, &entry, -1);
1987 
1988  if (!entry) {
1989  LOG(LOG_ERROR, "keys.c:on_keybinding_button_update_clicked",
1990  "Unable to get key_entry structure\n");
1991  return;
1992  }
1993  free(entry->command);
1994  keybinding_get_data(&entry->keysym, &entry->flags, &buf);
1995  entry->command = strdup_local(buf);
1997  save_keys();
1998  } else {
1999  LOG(LOG_ERROR, "keys.c:on_keybinding_button_update_clicked",
2000  "Nothing selected to update\n");
2001  }
2002 }
2003 
2010 void
2011 on_keybinding_button_close_clicked (GtkButton *button,
2012  gpointer user_data)
2013 {
2014  gtk_widget_hide(keybinding_window);
2015 }
2016 
2029 gboolean keybinding_selection_func (
2030  GtkTreeSelection *selection,
2031  GtkTreeModel *model,
2032  GtkTreePath *path,
2033  gboolean path_currently_selected,
2034  gpointer userdata)
2035 {
2036  GtkTreeIter iter;
2037  Key_Entry *entry;
2038 
2039  gtk_widget_set_sensitive(keybinding_button_remove, TRUE);
2040  gtk_widget_set_sensitive(keybinding_button_update, TRUE);
2041 
2042  if (gtk_tree_model_get_iter(model, &iter, path)) {
2043 
2044  gtk_tree_model_get(model, &iter, KLIST_KEY_ENTRY, &entry, -1);
2045 
2046  if (!entry) {
2047  LOG(LOG_ERROR, "keys.c:keybinding_selection_func",
2048  "Unable to get key_entry structure\n");
2049  return FALSE;
2050  }
2051  if (entry->flags & KEYF_RUN)
2052  gtk_toggle_button_set_active(
2053  GTK_TOGGLE_BUTTON(keybinding_checkbutton_control), TRUE);
2054  else
2055  gtk_toggle_button_set_active(
2056  GTK_TOGGLE_BUTTON(keybinding_checkbutton_control), FALSE);
2057 
2058  if (entry->flags & KEYF_FIRE)
2059  gtk_toggle_button_set_active(
2060  GTK_TOGGLE_BUTTON(keybinding_checkbutton_shift), TRUE);
2061  else
2062  gtk_toggle_button_set_active(
2063  GTK_TOGGLE_BUTTON(keybinding_checkbutton_shift), FALSE);
2064 
2065  if (entry->flags & KEYF_ALT)
2066  gtk_toggle_button_set_active(
2067  GTK_TOGGLE_BUTTON(keybinding_checkbutton_alt), TRUE);
2068  else
2069  gtk_toggle_button_set_active(
2070  GTK_TOGGLE_BUTTON(keybinding_checkbutton_alt), FALSE);
2071 
2072  if (entry->flags & KEYF_META)
2073  gtk_toggle_button_set_active(
2074  GTK_TOGGLE_BUTTON(keybinding_checkbutton_meta), TRUE);
2075  else
2076  gtk_toggle_button_set_active(
2077  GTK_TOGGLE_BUTTON(keybinding_checkbutton_meta), FALSE);
2078 
2079  if (entry->flags & KEYF_EDIT)
2080  gtk_toggle_button_set_active(
2081  GTK_TOGGLE_BUTTON(keybinding_checkbutton_edit), TRUE);
2082  else
2083  gtk_toggle_button_set_active(
2084  GTK_TOGGLE_BUTTON(keybinding_checkbutton_edit), FALSE);
2085 
2086  gtk_entry_set_text(
2087  GTK_ENTRY(keybinding_entry_key), gdk_keyval_name(entry->keysym));
2088  gtk_entry_set_text(
2089  GTK_ENTRY(keybinding_entry_command), entry->command);
2090  }
2091  return TRUE;
2092 }
2093 
2099 void reset_keybinding_status(void)
2101  gtk_toggle_button_set_active(
2102  GTK_TOGGLE_BUTTON(keybinding_checkbutton_control), FALSE);
2103  gtk_toggle_button_set_active(
2104  GTK_TOGGLE_BUTTON(keybinding_checkbutton_shift), FALSE);
2105  gtk_toggle_button_set_active(
2106  GTK_TOGGLE_BUTTON(keybinding_checkbutton_alt), FALSE);
2107  gtk_toggle_button_set_active(
2108  GTK_TOGGLE_BUTTON(keybinding_checkbutton_meta), FALSE);
2109  gtk_toggle_button_set_active(
2110  GTK_TOGGLE_BUTTON(keybinding_checkbutton_edit), FALSE);
2111  gtk_entry_set_text (GTK_ENTRY(keybinding_entry_key), "");
2112  gtk_entry_set_text (GTK_ENTRY(keybinding_entry_command), "");
2113  gtk_widget_set_sensitive(keybinding_button_remove, FALSE);
2114  gtk_widget_set_sensitive(keybinding_button_update, FALSE);
2115 }
2116 
2125 void
2126 on_keybinding_button_clear_clicked (GtkButton *button,
2127  gpointer user_data)
2128 {
2129  GtkTreeModel *model;
2130  GtkTreeIter iter;
2131 
2132  /*
2133  * As the cleared state is not supposed to have a keybinding selected,
2134  * deselect the currently selected keybinding if there is one.
2135  */
2136  if (gtk_tree_selection_get_selected(keybinding_selection, &model, &iter)) {
2137  gtk_tree_selection_unselect_iter (keybinding_selection, &iter);
2138  }
2139  reset_keybinding_status(); /* Clear inputs and reset buttons. */
2140 }
2141 
static GtkTreeSelection * keybinding_selection
Definition: keys.c:74
char * client_libdir
Definition: client.c:61
static void parse_key_release(uint32 ks)
Definition: keys.c:600
struct Keys * next
Definition: image.c:104
static char bind_buf[MAX_BUF]
Definition: keys.c:140
static uint32 altkeysym[2]
Definition: keys.c:135
uint32 count
Definition: client.h:295
void unbind_key(const char *params)
Definition: keys.c:918
gboolean keybinding_selection_func(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean path_currently_selected, gpointer userdata)
Definition: keys.c:2030
GtkWidget * treeview_look
Definition: inventory.c:53
#define CONFIG_POPUPS
Definition: client.h:160
void on_entry_commands_activate(GtkEntry *entry, gpointer user_data)
Definition: keys.c:1640
void on_keybindings_activate(GtkMenuItem *menuitem, gpointer user_data)
Definition: keys.c:1752
#define KEYF_NORMAL
Definition: keys.c:142
static XEvent event
Definition: x11.c:193
void stop_fire(void)
Definition: player.c:116
GtkWidget * spinbutton_count
Definition: keys.c:76
void clear_fire(void)
Definition: player.c:134
#define CONFIG_ECHO
Definition: client.h:153
#define KEYF_FIRE
Definition: keys.c:143
void gtk_command_history(int direction)
Definition: keys.c:1577
void on_keybinding_button_remove_clicked(GtkButton *button, gpointer user_data)
Definition: keys.c:1826
void run_dir(int dir)
Definition: player.c:172
static GtkWidget * keybinding_entry_command
Definition: keys.c:65
void on_keybinding_button_clear_clicked(GtkButton *button, gpointer user_data)
Definition: keys.c:2127
snd_pcm_hw_params_t * params
Definition: alsa9.c:111
static uint32 commandkeysym
Definition: keys.c:135
static uint32 cancelkeysym
Definition: keys.c:135
ClientSocket csocket
Definition: client.c:78
void clear_run(void)
Definition: player.c:142
static int scroll_history_position
Definition: keys.c:103
int make_path_to_file(char *filename)
Definition: misc.c:94
void update_keybinding_list(void)
Definition: keys.c:1707
gboolean on_keybinding_entry_key_key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
Definition: keys.c:1772
static GtkWidget * fire_label
Definition: keys.c:65
uint32 no_echo
Definition: client.h:294
void on_keybinding_button_update_clicked(GtkButton *button, gpointer user_data)
Definition: keys.c:1978
static GtkListStore * keybinding_store
Definition: keys.c:73
const char *const directions[9]
Definition: player.c:48
gint csocket_fd
Definition: main.c:107
static GtkWidget * keybinding_checkbutton_edit
Definition: keys.c:65
static uint32 prevkeysym
Definition: keys.c:135
static GtkWidget * keybinding_checkbutton_alt
Definition: keys.c:65
void draw_keybindings(GtkWidget *keylist)
Definition: keys.c:1129
static void parse_keybind_line(char *buf, int line, int standard)
Definition: keys.c:219
#define KEYHASH
Definition: keys.c:155
GladeXML * dialog_xml
Definition: main.c:57
void LOG(LogLevel level, const char *origin, const char *format,...)
Definition: misc.c:178
#define NDI_RED
Definition: newclient.h:204
void on_keybinding_button_bind_clicked(GtkButton *button, gpointer user_data)
Definition: keys.c:1946
#define TRUE
Definition: client-types.h:71
void gtk_complete_command(void)
Definition: keys.c:1617
static uint32 runkeysym[2]
Definition: keys.c:135
#define MAX_COMMAND_LEN
Definition: keys.c:100
gchar * text
Definition: about.h:2
static void configure_keys(uint32 keysym)
Definition: keys.c:1151
GtkWidget * entry_commands
Definition: keys.c:77
static void parse_key(char key, uint32 keysym)
Definition: keys.c:639
const char *const rcsid_gtk2_keys_c
Definition: keys.c:1
void x_set_echo(void)
Definition: keys.c:1556
GtkWidget * window_root
Definition: main.c:56
static GtkWidget * keybinding_entry_key
Definition: keys.c:65
sint8 direction
Definition: image.c:101
void draw_message_window(int redraw)
Definition: gx11.c:2458
sint16 use_config[CONFIG_NUMS]
Definition: init.c:50
static int bind_flags
Definition: keys.c:139
void reset_map(void)
Definition: map.c:76
static GtkWidget * keybinding_checkbutton_meta
Definition: keys.c:65
static void save_keys(void)
Definition: keys.c:1056
Client_Player cpl
Definition: client.c:77
const char *const def_keys[]
Definition: def-keys.h:1
int fd
Definition: client.h:97
static Key_Entry * keys[KEYHASH]
Definition: keys.c:156
static void show_keys(int allbindings)
Definition: keys.c:815
char name[40]
Definition: client.h:306
static GtkWidget * keybinding_button_bind
Definition: keys.c:65
#define MAX_HISTORY
Definition: keys.c:99
void extended_command(const char *ocommand)
Definition: p_cmd.c:890
static int cur_history_position
Definition: keys.c:103
void keys_init(GtkWidget *window_root)
Definition: keys.c:399
void send_reply(const char *text)
Definition: commands.c:769
uint32 run_on
Definition: client.h:291
static void init_default_keybindings(void)
Definition: keys.c:379
struct Keys Key_Entry
char * command
Definition: image.c:103
static GtkWidget * keybinding_button_remove
Definition: keys.c:65
uint32 fire_on
Definition: client.h:290
static uint32 firekeysym[2]
Definition: keys.c:135
#define NDI_WHITE
Definition: newclient.h:202
const char * complete_command(const char *command)
Definition: p_cmd.c:972
static uint32 * bind_keysym
Definition: keys.c:135
#define MAX_BUF
Definition: client-types.h:128
static GtkWidget * run_label
Definition: keys.c:65
unsigned int uint32
Definition: client-types.h:77
void stop_run(void)
Definition: player.c:166
#define BIG_BUF
Definition: client-types.h:129
char * buffers
Definition: cfsndserv.c:133
static void keybinding_get_data(uint32 *keysym, uint8 *flags, const char **command)
Definition: keys.c:1883
static GtkWidget * keybinding_checkbutton_control
Definition: keys.c:65
#define KEYF_MODIFIERS
Definition: keys.c:149
#define KEYF_META
Definition: keys.c:148
static uint32 metakeysym[2]
Definition: keys.c:135
#define KEYF_EDIT
Definition: keys.c:145
#define KEYF_STANDARD
Definition: keys.c:146
char * strdup_local(const char *str)
Definition: misc.c:125
signed char sint8
Definition: client-types.h:82
void keyrelfunc(GtkWidget *widget, GdkEventKey *event, GtkWidget *window)
Definition: keys.c:994
static GtkWidget * keybinding_window
Definition: keys.c:65
static uint32 nextkeysym
Definition: keys.c:135
#define KEYF_ALT
Definition: keys.c:147
uint32 meta_on
Definition: client.h:292
void on_keybinding_button_close_clicked(GtkButton *button, gpointer user_data)
Definition: keys.c:2012
void bind_key(const char *params)
Definition: keys.c:648
static char * get_key_info(Key_Entry *key, int save_mode)
Definition: keys.c:755
static void unbind_usage(void)
Definition: keys.c:1244
Input_State input_state
Definition: client.h:277
char history[MAX_HISTORY][MAX_COMMAND_LEN]
Definition: keys.c:101
uint32 alt_on
Definition: client.h:293
void draw_info(const char *str, int color)
Definition: gx11.c:1773
static GtkWidget * keybinding_button_update
Definition: keys.c:65
uint8 flags
Definition: image.c:100
char input_text[MAX_BUF]
Definition: client.h:279
#define KEYF_RUN
Definition: keys.c:144
static void save_individual_key(FILE *fp, Key_Entry *key, KeyCode kc)
Definition: keys.c:1040
unsigned char uint8
Definition: client-types.h:81
void reset_keybinding_status(void)
Definition: keys.c:2100
#define NDI_BLACK
Definition: newclient.h:201
#define FALSE
Definition: client-types.h:68
void draw_prompt(const char *str)
Definition: keys.c:1566
void keyfunc(GtkWidget *widget, GdkEventKey *event, GtkWidget *window)
Definition: keys.c:1008
static void insert_key(uint32 keysym, int flags, const char *command)
Definition: keys.c:177
Definition: keys.c:88
static GtkWidget * keybinding_treeview
Definition: keys.c:65
KeySym keysym
Definition: image.c:102
static uint32 completekeysym
Definition: keys.c:135
void fire_dir(int dir)
Definition: player.c:151
Definition: image.c:99
static GtkWidget * keybinding_checkbutton_shift
Definition: keys.c:65