diff options
Diffstat (limited to 'src/fe-gtk/fkeys.c')
-rw-r--r-- | src/fe-gtk/fkeys.c | 153 |
1 files changed, 87 insertions, 66 deletions
diff --git a/src/fe-gtk/fkeys.c b/src/fe-gtk/fkeys.c index 59086a5e..e762d208 100644 --- a/src/fe-gtk/fkeys.c +++ b/src/fe-gtk/fkeys.c @@ -198,6 +198,7 @@ static const struct key_action key_actions[KEY_MAX_ACTIONS + 1] = { "ACCEL=Down\nNext Command\nD1!\nD2!\n\n"\ "ACCEL=Up\nLast Command\nD1!\nD2!\n\n"\ "ACCEL=Tab\nComplete nick/command\nD1!\nD2!\n\n"\ + "ACCEL=<Shift>ISO_Left_Tab\nComplete nick/command\nD1:Previous\nD2!\n\n"\ "ACCEL=space\nCheck For Replace\nD1!\nD2!\n\n"\ "ACCEL=Return\nCheck For Replace\nD1!\nD2!\n\n"\ "ACCEL=KP_Enter\nCheck For Replace\nD1!\nD2!\n\n"\ @@ -241,10 +242,8 @@ key_free (gpointer data) g_return_if_fail (kb != NULL); - if (kb->data1) - g_free (kb->data1); - if (kb->data2) - g_free (kb->data2); + g_free (kb->data1); + g_free (kb->data2); g_free (kb); } @@ -323,7 +322,7 @@ key_handle_key_press (GtkWidget *wid, GdkEventKey *evt, session *sess) return FALSE; current_sess = sess; - if (plugin_emit_keypress (sess, evt->state, evt->keyval, evt->length, evt->string)) + if (plugin_emit_keypress (sess, evt->state, evt->keyval, gdk_keyval_to_unicode (evt->keyval))) return 1; /* maybe the plugin closed this tab? */ @@ -567,7 +566,7 @@ key_dialog_save (GtkWidget *wid, gpointer userdata) { do { - kb = (struct key_binding *) g_malloc0 (sizeof (struct key_binding)); + kb = g_new0 (struct key_binding, 1); gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, ACCEL_COLUMN, &accel, ACTION_COLUMN, &actiontext, @@ -598,7 +597,8 @@ key_dialog_save (GtkWidget *wid, gpointer userdata) else keybind_list = g_slist_append (keybind_list, kb); - } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter)); + } + while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter)); } if (key_save_kbs () == 0) @@ -666,6 +666,7 @@ key_dialog_treeview_new (GtkWidget *box) view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store)); gtk_tree_view_set_fixed_height_mode (GTK_TREE_VIEW (view), TRUE); gtk_tree_view_set_enable_search (GTK_TREE_VIEW (view), FALSE); + gtk_tree_view_set_reorderable (GTK_TREE_VIEW (view), TRUE); g_signal_connect (G_OBJECT (view), "key-press-event", G_CALLBACK (key_dialog_keypress), NULL); @@ -850,7 +851,7 @@ key_save_kbs (void) 0x180, XOF_DOMODE); if (fd < 0) return 1; - write (fd, buf, snprintf (buf, 510, "# HexChat key bindings config file\n\n")); + write (fd, buf, g_snprintf (buf, 510, "# HexChat key bindings config file\n\n")); while (list) { @@ -858,17 +859,17 @@ key_save_kbs (void) accel_text = gtk_accelerator_name (kb->keyval, kb->mod); - snprintf (buf, 510, "ACCEL=%s\n%s\n", accel_text, key_actions[kb->action].name); + g_snprintf (buf, 510, "ACCEL=%s\n%s\n", accel_text, key_actions[kb->action].name); write (fd, buf, strlen (buf)); g_free (accel_text); if (kb->data1 && kb->data1[0]) - write (fd, buf, snprintf (buf, 510, "D1:%s\n", kb->data1)); + write (fd, buf, g_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)); + write (fd, buf, g_snprintf (buf, 510, "D2:%s\n", kb->data2)); else write (fd, "D2!\n", 4); @@ -946,7 +947,7 @@ key_load_kbs (void) fd = hexchat_open_file ("keybindings.conf", O_RDONLY, 0, 0); if (fd < 0) { - ibuf = strdup (default_kb_cfg); + ibuf = g_strdup (default_kb_cfg); size = strlen (default_kb_cfg); } else @@ -957,7 +958,7 @@ key_load_kbs (void) return 1; } - ibuf = malloc (st.st_size); + ibuf = g_malloc(st.st_size); read (fd, ibuf, st.st_size); size = st.st_size; close (fd); @@ -979,7 +980,7 @@ key_load_kbs (void) switch (state) { case KBSTATE_MOD: - kb = (struct key_binding *) g_malloc0 (sizeof (struct key_binding)); + kb = g_new0 (struct key_binding, 1); /* New format */ if (strncmp (buf, "ACCEL=", 6) == 0) @@ -1010,7 +1011,7 @@ key_load_kbs (void) keyval = gdk_keyval_from_name (buf); if (keyval == 0) { - free (ibuf); + g_free (ibuf); return 2; } @@ -1026,7 +1027,7 @@ key_load_kbs (void) if (kb->action == KEY_MAX_ACTIONS + 1) { - free (ibuf); + g_free (ibuf); return 3; } @@ -1043,7 +1044,7 @@ key_load_kbs (void) if (buf[0] != 'D') { - free (ibuf); + g_free (ibuf); return 4; } @@ -1069,12 +1070,10 @@ key_load_kbs (void) len -= 3; if (state == KBSTATE_DT1) { - kb->data1 = g_malloc (len); - memcpy (kb->data1, &buf[3], len); + kb->data1 = g_strndup (&buf[3], len); } else { - kb->data2 = g_malloc (len); - memcpy (kb->data2, &buf[3], len); + kb->data2 = g_strndup (&buf[3], len); } } else if (buf[2] == '!') { @@ -1097,12 +1096,12 @@ key_load_kbs (void) continue; } } - free (ibuf); + g_free (ibuf); return 0; corrupt_file: - free (ibuf); - free (kb); + g_free (ibuf); + g_free (kb); return 5; } @@ -1410,9 +1409,6 @@ key_action_tab_clean(void) } } -/* Used in the followig completers */ -#define COMP_BUF 2048 - /* For use in sorting the user list for completion */ static int talked_recent_cmp (struct User *a, struct User *b) @@ -1426,16 +1422,31 @@ talked_recent_cmp (struct User *a, struct User *b) return 0; } +#define COMP_BUF 2048 + +static inline glong +len_to_offset (const char *str, glong len) +{ + return g_utf8_pointer_to_offset (str, str + len); +} + +static inline glong +offset_to_len (const char *str, glong offset) +{ + return g_utf8_offset_to_pointer (str, offset) - str; +} + static int key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2, struct session *sess) { - int len = 0, elen = 0, i = 0, cursor_pos, ent_start = 0, comp = 0, found = 0, - prefix_len, skip_len = 0, is_nick, is_cmd = 0; - char buf[COMP_BUF], ent[CHANLEN], *postfix = NULL, *result, *ch; + int len = 0, elen = 0, i = 0, cursor_pos, ent_start = 0, comp = 0, prefix_len, skip_len = 0; + gboolean is_nick = FALSE, is_cmd = FALSE, found = FALSE, has_nick_prefix = FALSE; + char ent[CHANLEN], *postfix = NULL, *result, *ch; GList *list = NULL, *tmp_list = NULL; const char *text; GCompletion *gcomp = NULL; + GString *buf; /* force the IM Context to reset */ SPELL_ENTRY_SET_EDITABLE (t, FALSE); @@ -1449,8 +1460,6 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2, cursor_pos = SPELL_ENTRY_GET_POS (t); - buf[0] = 0; /* make sure we don't get garbage in the buffer */ - /* handle "nick: " or "nick " or "#channel "*/ ch = g_utf8_find_prev_char(text, g_utf8_offset_to_pointer(text,cursor_pos)); if (ch && ch[0] == ' ') @@ -1489,15 +1498,23 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2, if (ent_start == 0 && text[0] == prefs.hex_input_command_char[0]) { ent_start++; - is_cmd = 1; + is_cmd = TRUE; } - + else if (strchr (sess->server->chantypes, text[ent_start]) == NULL) + { + is_nick = TRUE; + if (strchr (sess->server->nick_prefixes, text[ent_start]) != NULL) + { + if (ent_start == 0) + has_nick_prefix = TRUE; + ent_start++; + } + } + prefix_len = ent_start; elen = cursor_pos - ent_start; g_utf8_strncpy (ent, g_utf8_offset_to_pointer (text, prefix_len), elen); - - is_nick = (ent[0] == '#' || ent[0] == '&' || is_cmd) ? 0 : 1; if (sess->type == SESS_DIALOG && is_nick) { @@ -1505,7 +1522,7 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2, if (rfc_ncasecmp (sess->channel, ent, elen) == 0) { result = sess->channel; - is_nick = 0; + is_nick = FALSE; } else return 2; @@ -1562,7 +1579,7 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2, { if(rfc_ncasecmp(list->data, ent, elen) == 0) { - found = 1; + found = TRUE; break; } list = list->next; @@ -1600,7 +1617,7 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2, old_gcomp.elen = elen; /* Get the first nick and put out the data for future nickcompletes */ - if (prefs.hex_completion_amount && g_list_length (list) <= prefs.hex_completion_amount) + if (prefs.hex_completion_amount > 0 && g_list_length (list) <= (guint) prefs.hex_completion_amount) { g_free(result); result = (char*)list->data; @@ -1610,40 +1627,42 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2, /* bash style completion */ if (g_list_next(list) != NULL) { + buf = g_string_sized_new (MAX(COMP_BUF, len + NICKLEN)); if (strlen (result) > elen) /* the largest common prefix is larger than nick, change the data */ { if (prefix_len) - g_utf8_strncpy (buf, text, prefix_len); - strncat (buf, result, COMP_BUF - prefix_len); - cursor_pos = strlen (buf); + g_string_append_len (buf, text, offset_to_len (text, prefix_len)); + g_string_append (buf, result); + cursor_pos = buf->len; g_free(result); if (postfix) { - strcat (buf, " "); - strncat (buf, postfix, COMP_BUF - cursor_pos -1); + g_string_append_c (buf, ' '); + g_string_append (buf, postfix); } - SPELL_ENTRY_SET_TEXT (t, buf); - SPELL_ENTRY_SET_POS (t, g_utf8_pointer_to_offset(buf, buf + cursor_pos)); - buf[0] = 0; + SPELL_ENTRY_SET_TEXT (t, buf->str); + SPELL_ENTRY_SET_POS (t, len_to_offset (buf->str, cursor_pos)); + g_string_erase (buf, 0, -1); } else g_free(result); + while (list) { - len = strlen (buf); /* current buffer */ + len = buf->len; elen = strlen (list->data); /* next item to add */ if (len + elen + 2 >= COMP_BUF) /* +2 is space + null */ { - PrintText (sess, buf); - buf[0] = 0; - len = 0; + PrintText (sess, buf->str); + g_string_erase (buf, 0, -1); } - strcpy (buf + len, (char *) list->data); - strcpy (buf + len + elen, " "); + g_string_append (buf, (char*)list->data); + g_string_append_c (buf, ' '); list = list->next; } - PrintText (sess, buf); + PrintText (sess, buf->str); g_completion_free(gcomp); + g_string_free (buf, TRUE); return 2; } /* Only one matching entry */ @@ -1655,17 +1674,19 @@ key_action_tab_comp (GtkWidget *t, GdkEventKey *entry, char *d1, char *d2, if(result) { + buf = g_string_sized_new (len + NICKLEN); if (prefix_len) - g_utf8_strncpy(buf, text, prefix_len); - strncat (buf, result, COMP_BUF - (prefix_len + 3)); /* make sure nicksuffix and space fits */ - if(!prefix_len && is_nick) - strcat (buf, &prefs.hex_completion_suffix[0]); - strcat (buf, " "); - cursor_pos = strlen (buf); + g_string_append_len (buf, text, offset_to_len (text, prefix_len)); + g_string_append (buf, result); + if((!prefix_len || has_nick_prefix) && is_nick && prefs.hex_completion_suffix[0] != '\0') + g_string_append_unichar (buf, g_utf8_get_char_validated (prefs.hex_completion_suffix, -1)); + g_string_append_c (buf, ' '); + cursor_pos = buf->len; if (postfix) - strncat (buf, postfix, COMP_BUF - cursor_pos - 2); - SPELL_ENTRY_SET_TEXT (t, buf); - SPELL_ENTRY_SET_POS (t, g_utf8_pointer_to_offset(buf, buf + cursor_pos)); + g_string_append (buf, postfix); + SPELL_ENTRY_SET_TEXT (t, buf->str); + SPELL_ENTRY_SET_POS (t, len_to_offset (buf->str, cursor_pos)); + g_string_free (buf, TRUE); } if (gcomp) g_completion_free(gcomp); @@ -1794,10 +1815,10 @@ replace_handle (GtkWidget *t) memcpy (outbuf, text, xlen); outbuf[xlen] = 0; if (postfix_pnt == NULL) - snprintf (word, sizeof (word), "%s", pop->cmd); + g_snprintf (word, sizeof (word), "%s", pop->cmd); else - snprintf (word, sizeof (word), "%s%s", pop->cmd, postfix); - strcat (outbuf, word); + g_snprintf (word, sizeof (word), "%s%s", pop->cmd, postfix); + g_strlcat (outbuf, word, sizeof(outbuf)); SPELL_ENTRY_SET_TEXT (t, outbuf); SPELL_ENTRY_SET_POS (t, -1); return; |