📄 fkeys.c
字号:
int i; if (key_dialog) { wins_bring_tofront (key_dialog); return; } key_dialog = maingui_window ("editkeys", _("X-Chat: Edit Key Bindings"), TRUE, FALSE, key_dialog_close, NULL, 560, 330, NULL); vbox = wins_get_vbox (key_dialog); hbox = gtk_hbox_new (0, 2); gtk_box_pack_start (GTK_BOX (vbox), hbox, 1, 1, 0); list = gtkutil_clist_new (5, titles, hbox, 0, key_dialog_sel_row, 0, NULL, 0, 0); gtk_widget_set_usize (list, 400, 0); key_dialog_kb_clist = list; gtk_widget_show (hbox); kb = keys_root; gtk_clist_set_column_width (GTK_CLIST (list), 1, 50); gtk_clist_set_column_width (GTK_CLIST (list), 2, 120); gtk_clist_set_column_width (GTK_CLIST (list), 3, 50); gtk_clist_set_column_width (GTK_CLIST (list), 4, 50); while (kb) { titles[0] = key_make_mod_str (kb->mod, temp); titles[1] = kb->keyname; if (kb->action < 0 || kb->action > KEY_MAX_ACTIONS) titles[2] = _("<none>"); else titles[2] = key_actions[kb->action].name; if (kb->data1) titles[3] = kb->data1; else titles[3] = _("<none>"); if (kb->data2) titles[4] = kb->data2; else titles[4] = _("<none>"); gtk_clist_set_row_data (GTK_CLIST (list), gtk_clist_append (GTK_CLIST (list), titles), kb); kb = kb->next; } vbox2 = gtk_vbox_new (0, 2); gtk_box_pack_end (GTK_BOX (hbox), vbox2, 1, 1, 0); wid = gtk_button_new_with_label (_("Add new")); gtk_box_pack_start (GTK_BOX (vbox2), wid, 0, 0, 0); gtk_signal_connect (GTK_OBJECT (wid), "clicked", GTK_SIGNAL_FUNC (key_dialog_add_new), list); gtk_widget_show (wid); wid = gtk_button_new_with_label (_("Delete")); gtk_box_pack_start (GTK_BOX (vbox2), wid, 0, 0, 0); gtk_signal_connect (GTK_OBJECT (wid), "clicked", GTK_SIGNAL_FUNC (key_dialog_delete), list); gtk_widget_show (wid); gtk_widget_show (vbox2); wid = gtk_option_menu_new (); wid2 = gtk_menu_new (); for (i = 0; i <= KEY_MAX_ACTIONS; i++) { wid3 = gtk_menu_item_new_with_label (_(key_actions[i].name)); gtk_widget_show (wid3); gtk_menu_append (GTK_MENU (wid2), wid3); gtk_signal_connect (GTK_OBJECT (wid3), "activate", GTK_SIGNAL_FUNC (key_dialog_sel_act), (void *) i); } gtk_option_menu_set_menu (GTK_OPTION_MENU (wid), wid2); gtk_option_menu_set_history (GTK_OPTION_MENU (wid), 0); gtk_box_pack_end (GTK_BOX (vbox2), wid, 0, 0, 0); gtk_widget_show (wid); key_dialog_act_menu = wid; key_dialog_tog_s = key_dialog_make_toggle (_("Shift"), key_dialog_tog_key, (void *) STATE_SHIFT, vbox2); key_dialog_tog_a = key_dialog_make_toggle (_("Alt"), key_dialog_tog_key, (void *) STATE_ALT, vbox2); key_dialog_tog_c = key_dialog_make_toggle (_("Ctrl"), key_dialog_tog_key, (void *) STATE_CTRL, vbox2); key_dialog_ent_key = key_dialog_make_entry (_("Key"), "key_press_event", key_dialog_set_key, NULL, vbox2); key_dialog_ent_d1 = key_dialog_make_entry (_("Data 1"), "activate", key_dialog_set_data, NULL, vbox2); key_dialog_ent_d2 = key_dialog_make_entry (_("Data 2"), "activate", key_dialog_set_data, (void *) 1, vbox2); hbox2 = gtk_hbox_new (0, 2); gtk_box_pack_end (GTK_BOX (vbox), hbox2, 0, 0, 1); wid = gtk_xtext_new (0, 0); gtk_xtext_set_palette (GTK_XTEXT (wid), colors); gtk_xtext_set_font (GTK_XTEXT (wid), font_normal, 0); gtk_xtext_set_background (GTK_XTEXT (wid), channelwin_pix, prefs.transparent, prefs.tint); gtk_widget_set_usize (wid, 0, 75); gtk_box_pack_start (GTK_BOX (hbox2), wid, 1, 1, 1); gtk_widget_show (wid); wid2 = gtk_vscrollbar_new (GTK_XTEXT (wid)->adj); gtk_box_pack_start (GTK_BOX (hbox2), wid2, 0, 0, 0); gtk_widget_show (wid2); gtk_widget_show (hbox2); key_dialog_text = wid; gtk_widget_show_all (key_dialog);}static voidkey_save_kbs (char *fn){ int fd, i; char buf[512]; struct key_binding *kb; if (!fn) snprintf (buf, 510, "%s/keybindings.conf", get_xdir ()); else strncpy (buf, fn, 510); fd = open (buf, O_CREAT | O_TRUNC | O_WRONLY | OFLAGS, 0x180); if (fd < 0) { gtkutil_simpledialog (_("Error opening keys config file\n")); return; } write (fd, buf, snprintf (buf, 510, "# XChat key bindings config file\n\n")); kb = keys_root; i = 0; while (kb) { if (kb->keyval == -1 || kb->keyname == NULL || kb->action < 0) { kb = kb->next; continue; } i = 0; if (kb->mod & STATE_CTRL) { i++; write (fd, "C", 1); } if (kb->mod & STATE_ALT) { i++; write (fd, "A", 1); } if (kb->mod & STATE_SHIFT) { i++; write (fd, "S", 1); } if (i == 0) write (fd, "None\n", 5); else write (fd, "\n", 1); write (fd, buf, snprintf (buf, 510, "%s\n%s\n", kb->keyname, key_actions[kb->action].name)); if (kb->data1 && kb->data1[0]) write (fd, buf, snprintf (buf, 510, "D1:%s\n", kb->data1)); else write (fd, "D1!\n", 4); if (kb->data2 && kb->data2[0]) write (fd, buf, snprintf (buf, 510, "D2:%s\n", kb->data2)); else write (fd, "D2!\n", 4); write (fd, "\n", 1); kb = kb->next; } close (fd);}/* I just know this is going to be a nasty parse, if you think it's bugged it almost certainly is so contact the XChat dev team --AGL */static inline intkey_load_kbs_helper_mod (char *in, int *out){ int n, len, mod = 0; /* First strip off the fluff */ while (in[0] == ' ' || in[0] == '\t') in++; len = strlen (in); while (in[len] == ' ' || in[len] == '\t') { in[len] = 0; len--; } if (strcmp (in, "None") == 0) { *out = 0; return 0; } for (n = 0; n < len; n++) { switch (in[n]) { case 'C': mod |= STATE_CTRL; break; case 'A': mod |= STATE_ALT; break; case 'S': mod |= STATE_SHIFT; break; default: return 1; } } *out = mod; return 0;}/* These are just local defines to keep me sane --AGL */#define KBSTATE_MOD 0#define KBSTATE_KEY 1#define KBSTATE_ACT 2#define KBSTATE_DT1 3#define KBSTATE_DT2 4/* *** Warning, Warning! - massive function ahead! --AGL */static intkey_load_kbs (char *filename){ char *buf, *ibuf; struct stat st; struct key_binding *kb = NULL, *last = NULL; int fd, len, pnt = 0, state = 0, n; buf = malloc (1000); if (filename == NULL) snprintf (buf, 1000, "%s/keybindings.conf", get_xdir ()); else strcpy (buf, filename); fd = open (buf, O_RDONLY | OFLAGS); free (buf); if (fd < 0) return 1; if (fstat (fd, &st) != 0) return 1; ibuf = malloc (st.st_size); read (fd, ibuf, st.st_size); close (fd); while (buf_get_line (ibuf, &buf, &pnt, st.st_size)) { if (buf[0] == '#') continue; if (strlen (buf) == 0) continue; switch (state) { case KBSTATE_MOD: kb = (struct key_binding *) malloc (sizeof (struct key_binding)); if (key_load_kbs_helper_mod (buf, &kb->mod)) goto corrupt_file; state = KBSTATE_KEY; continue; case KBSTATE_KEY: /* First strip off the fluff */ while (buf[0] == ' ' || buf[0] == '\t') buf++; len = strlen (buf); while (buf[len] == ' ' || buf[len] == '\t') { buf[len] = 0; len--; } n = gdk_keyval_from_name (buf); if (n == 0) { /* Unknown keyname, abort */ if (last) last->next = NULL; free (ibuf); ibuf = malloc (1024); snprintf (ibuf, 1024, _("Unknown keyname %s in key bindings config file\nLoad aborted, please fix ~/.xchat/keybindings.conf\n"), buf); gtkutil_simpledialog (ibuf); free (ibuf); return 2; } kb->keyname = gdk_keyval_name (n); kb->keyval = n; state = KBSTATE_ACT; continue; case KBSTATE_ACT: /* First strip off the fluff */ while (buf[0] == ' ' || buf[0] == '\t') buf++; len = strlen (buf); while (buf[len] == ' ' || buf[len] == '\t') { buf[len] = 0; len--; } for (n = 0; n < KEY_MAX_ACTIONS + 1; n++) { if (strcmp (key_actions[n].name, buf) == 0) { kb->action = n; break; } } if (n == KEY_MAX_ACTIONS + 1) { if (last) last->next = NULL; free (ibuf); ibuf = malloc (1024); snprintf (ibuf, 1024, _("Unknown action %s in key bindings config file\nLoad aborted, Please fix ~/.xchat/keybindings\n"), buf); gtkutil_simpledialog (ibuf); free (ibuf); return 3; } state = KBSTATE_DT1; continue; case KBSTATE_DT1: case KBSTATE_DT2: if (state == KBSTATE_DT1) kb->data1 = kb->data2 = NULL; while (buf[0] == ' ' || buf[0] == '\t') buf++; if (buf[0] != 'D') { free (ibuf); ibuf = malloc (1024); snprintf (ibuf, 1024, _("Expecting Data line (beginning Dx{:|!}) but got:\n%s\n\nLoad aborted, Please fix ~/.xchat/keybindings\n"), buf); gtkutil_simpledialog (ibuf); free (ibuf); return 4; } switch (buf[1]) { case '1': if (state != KBSTATE_DT1) goto corrupt_file; break; case '2': if (state != KBSTATE_DT2) goto corrupt_file; break; default: goto corrupt_file; } if (buf[2] == ':') { len = strlen (buf); /* Add one for the NULL, subtract 3 for the "Dx:" */ len++; len -= 3; if (state == KBSTATE_DT1) { kb->data1 = malloc (len); memcpy (kb->data1, &buf[3], len); } else { kb->data2 = malloc (len); memcpy (kb->data2, &buf[3], len); } } else if (buf[2] == '!') { if (state == KBSTATE_DT1) kb->data1 = NULL; else kb->data2 = NULL; } if (state == KBSTATE_DT1) { state = KBSTATE_DT2; continue; } else { if (last) last->next = kb; else keys_root = kb; last = kb; state = KBSTATE_MOD; } continue; } } if (last) last->next = NULL; free (ibuf); return 0; corrupt_file: /*if (getenv ("XCHAT_DEBUG")) abort ();*/ free (ibuf); gtkutil_simpledialog ("Key bindings config file is corrupt, load aborted\n" "Please fix ~/.xchat/keybindings.conf\n"); return 5;}/* ***** Key actions start here *********** *//* See the NOTES above --AGL *//* "Run command" */static intkey_action_handle_command (GtkWidget * wid, GdkEventKey * evt, char *d1, char *d2, struct session *sess){ int ii, oi, len; char out[2048], d = 0; if (!d1) return 0; len = strlen (d1); /* Replace each "\n" substring with '\n' */ for (ii = oi = 0; ii < len; ii++) { d = d1[ii]; if (d == '\\') { ii++; d = d1[ii]; if (d == 'n') out[oi++] = '\n'; else if (d == '\\') out[oi++] = '\\'; else { out[oi++] = '\\'; out[oi++] = d; } continue; } out[oi++] = d; } out[oi] = 0; handle_multiline (sess, out, 0, 0); return 0;}static intkey_action_page_switch (GtkWidget * wid, GdkEventKey * evt, char *d1, char *d2, struct session *sess){ int len, i, num; if (!d1) return 1; if (!main_window) return 1; len = strlen (d1); if (!len) return 1; for (i = 0; i < len; i++) { if (d1[i] < '0' || d1[i] > '9') { if (i == 0 && (d1[i] == '+' || d1[i] == '-')) continue; else return 1; } } num = atoi (d1); if (!d2) num--; if (!d2 || d2[0] == 0) gtk_notebook_set_page (GTK_NOTEBOOK (main_book), num); else { len = g_list_length (((GtkNotebook *) main_book)->children); i = gtk_notebook_get_current_page (GTK_NOTEBOOK (main_book)) + num; if (i >= len) i = 0; if (i < 0) i = len - 1; gtk_notebook_set_page (GTK_NOTEBOOK (main_book), i); } return 0;}intkey_action_insert (GtkWidget * wid, GdkEventKey * evt, char *d1, char *d2, struct session *sess){ int tmp_pos; if (!d1) return 1; tmp_pos = GTK_EDITABLE (wid)->current_pos; gtk_editable_insert_text (GTK_EDITABLE (wid), d1, strlen (d1), &tmp_pos); GTK_EDITABLE (wid)->current_pos = tmp_pos; return 2;}/* handles PageUp/Down keys */static intkey_action_scroll_page (GtkWidget * wid, GdkEventKey * evt, char *d1, char *d2, struct session *sess){ int value, end; GtkAdjustment *adj; int up = 0; if (d1 && d1[0] != 0) up++; if (sess) { adj = GTK_RANGE (sess->gui->vscrollbar)->adjustment; if (up) /* PageUp */ { value = adj->value - adj->page_size; if (value < 0) value = 0; } else { /* PageDown */ end = adj->upper - adj->lower - adj->page_size; value = adj->value + adj->page_size; if (value > end) value = end; } gtk_adjustment_set_value (adj, value); } return 0;}static intkey_action_set_buffer (GtkWidget * wid, GdkEventKey * evt, char *d1, char *d2, struct session *sess){ if (!d1) return 1; if (d1[0] == 0) return 1; gtk_entry_set_text (GTK_ENTRY (wid), d1); return 2;}static intkey_action_history_up (GtkWidget * wid, GdkEventKey * ent, char *d1, char *d2, struct session *sess){ char *new_line; new_line = history_up (&sess->history); if (new_line) gtk_entry_set_text (GTK_ENTRY (wid), new_line); return 2;}static intkey_action_history_down (GtkWidget * wid, GdkEventKey * ent, char *d1, char *d2, struct session *sess){ char *new_line; new_line = history_down (&sess->history); if (new_line) gtk_entry_set_text (GTK_ENTRY (wid), new_line); return 2;}static intkey_action_tab_comp (GtkWidget * wid, GdkEventKey * ent, char *d1, char *d2, struct session *sess)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -