| 3978 g_object_unref(pixbuf); |
3978 g_object_unref(pixbuf); |
| 3979 g_free(alias_key); |
3979 g_free(alias_key); |
| 3980 } |
3980 } |
| 3981 |
3981 |
| 3982 static void |
3982 static void |
| 3983 tab_complete_process_item(int *most_matched, char *entered, char **partial, char *nick_partial, |
3983 tab_complete_process_item(int *most_matched, char *entered, gsize entered_bytes, char **partial, char *nick_partial, |
| 3984 GList **matches, gboolean command, char *name) |
3984 GList **matches, gboolean command, char *name) |
| 3985 { |
3985 { |
| 3986 strncpy(nick_partial, name, strlen(entered)); |
3986 memcpy(nick_partial, name, entered_bytes); |
| 3987 nick_partial[strlen(entered)] = '\0'; |
|
| 3988 if (purple_utf8_strcasecmp(nick_partial, entered)) |
3987 if (purple_utf8_strcasecmp(nick_partial, entered)) |
| 3989 return; |
3988 return; |
| 3990 |
3989 |
| 3991 /* if we're here, it's a possible completion */ |
3990 /* if we're here, it's a possible completion */ |
| 3992 |
3991 |
| 4027 char *text; |
4026 char *text; |
| 4028 char *nick_partial; |
4027 char *nick_partial; |
| 4029 const char *prefix; |
4028 const char *prefix; |
| 4030 GList *matches = NULL; |
4029 GList *matches = NULL; |
| 4031 gboolean command = FALSE; |
4030 gboolean command = FALSE; |
| |
4031 gsize entered_bytes = 0; |
| 4032 |
4032 |
| 4033 gtkconv = PIDGIN_CONVERSATION(conv); |
4033 gtkconv = PIDGIN_CONVERSATION(conv); |
| 4034 |
4034 |
| 4035 gtk_text_buffer_get_start_iter(gtkconv->entry_buffer, &start_buffer); |
4035 gtk_text_buffer_get_start_iter(gtkconv->entry_buffer, &start_buffer); |
| 4036 gtk_text_buffer_get_iter_at_mark(gtkconv->entry_buffer, &cursor, |
4036 gtk_text_buffer_get_iter_at_mark(gtkconv->entry_buffer, &cursor, |
| 4046 &cursor, FALSE); |
4046 &cursor, FALSE); |
| 4047 |
4047 |
| 4048 /* if we're at the end of ": " we need to move back 2 spaces */ |
4048 /* if we're at the end of ": " we need to move back 2 spaces */ |
| 4049 start = strlen(text) - 1; |
4049 start = strlen(text) - 1; |
| 4050 |
4050 |
| 4051 if (strlen(text) >= 2 && !strncmp(&text[start-1], ": ", 2)) { |
4051 if (start >= 1 && !strncmp(&text[start-1], ": ", 2)) { |
| 4052 gtk_text_iter_backward_chars(&word_start, 2); |
4052 gtk_text_iter_backward_chars(&word_start, 2); |
| 4053 start-=2; |
4053 } |
| 4054 } |
4054 |
| 4055 |
4055 /* find the start of the word that we're tabbing. |
| 4056 /* find the start of the word that we're tabbing */ |
4056 * Using gtk_text_iter_backward_word_start won't work, because a nick can contain |
| 4057 while (start >= 0 && text[start] != ' ') { |
4057 * characters (e.g. '.', '/' etc.) that Pango may think are word separators. */ |
| 4058 gtk_text_iter_backward_char(&word_start); |
4058 while (gtk_text_iter_backward_char(&word_start)) { |
| 4059 start--; |
4059 if (gtk_text_iter_get_char(&word_start) == ' ') { |
| |
4060 /* Reached the whitespace before the start of the word. Move forward once */ |
| |
4061 gtk_text_iter_forward_char(&word_start); |
| |
4062 break; |
| |
4063 } |
| 4060 } |
4064 } |
| 4061 |
4065 |
| 4062 prefix = pidgin_get_cmd_prefix(); |
4066 prefix = pidgin_get_cmd_prefix(); |
| 4063 if (start == -1 && (strlen(text) >= strlen(prefix)) && !strncmp(text, prefix, strlen(prefix))) { |
4067 if (gtk_text_iter_get_offset(&word_start) == 0 && |
| |
4068 (strlen(text) >= strlen(prefix)) && !strncmp(text, prefix, strlen(prefix))) { |
| 4064 command = TRUE; |
4069 command = TRUE; |
| 4065 gtk_text_iter_forward_chars(&word_start, strlen(prefix)); |
4070 gtk_text_iter_forward_chars(&word_start, strlen(prefix)); |
| 4066 } |
4071 } |
| 4067 |
4072 |
| 4068 g_free(text); |
4073 g_free(text); |
| 4069 |
4074 |
| 4070 entered = gtk_text_buffer_get_text(gtkconv->entry_buffer, &word_start, |
4075 entered = gtk_text_buffer_get_text(gtkconv->entry_buffer, &word_start, |
| 4071 &cursor, FALSE); |
4076 &cursor, FALSE); |
| |
4077 entered_bytes = strlen(entered); |
| 4072 |
4078 |
| 4073 if (!g_utf8_strlen(entered, -1)) { |
4079 if (!g_utf8_strlen(entered, -1)) { |
| 4074 g_free(entered); |
4080 g_free(entered); |
| 4075 return (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) ? TRUE : FALSE; |
4081 return (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) ? TRUE : FALSE; |
| 4076 } |
4082 } |
| 4077 |
4083 |
| 4078 nick_partial = g_malloc(strlen(entered)+1); |
4084 nick_partial = g_malloc0(entered_bytes + 1); |
| 4079 |
4085 |
| 4080 if (command) { |
4086 if (command) { |
| 4081 GList *list = purple_cmd_list(conv); |
4087 GList *list = purple_cmd_list(conv); |
| 4082 GList *l; |
4088 GList *l; |
| 4083 |
4089 |
| 4084 /* Commands */ |
4090 /* Commands */ |
| 4085 for (l = list; l != NULL; l = l->next) { |
4091 for (l = list; l != NULL; l = l->next) { |
| 4086 tab_complete_process_item(&most_matched, entered, &partial, nick_partial, |
4092 tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial, |
| 4087 &matches, TRUE, l->data); |
4093 &matches, TRUE, l->data); |
| 4088 } |
4094 } |
| 4089 g_list_free(list); |
4095 g_list_free(list); |
| 4090 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { |
4096 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { |
| 4091 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); |
4097 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); |
| 4112 CHAT_USERS_NAME_COLUMN, &name, |
4118 CHAT_USERS_NAME_COLUMN, &name, |
| 4113 CHAT_USERS_ALIAS_COLUMN, &alias, |
4119 CHAT_USERS_ALIAS_COLUMN, &alias, |
| 4114 -1); |
4120 -1); |
| 4115 |
4121 |
| 4116 if (name && alias && strcmp(name, alias)) |
4122 if (name && alias && strcmp(name, alias)) |
| 4117 tab_complete_process_item(&most_matched, entered, &partial, nick_partial, |
4123 tab_complete_process_item(&most_matched, entered, entered_bytes, &partial, nick_partial, |
| 4118 &matches, FALSE, alias); |
4124 &matches, FALSE, alias); |
| 4119 g_free(name); |
4125 g_free(name); |
| 4120 g_free(alias); |
4126 g_free(alias); |
| 4121 |
4127 |
| 4122 f = gtk_tree_model_iter_next(model, &iter); |
4128 f = gtk_tree_model_iter_next(model, &iter); |