diff options
-rw-r--r-- | libempathy-gtk/empathy-chat.c | 192 |
1 files changed, 109 insertions, 83 deletions
diff --git a/libempathy-gtk/empathy-chat.c b/libempathy-gtk/empathy-chat.c index a9f4c499e..b6356f834 100644 --- a/libempathy-gtk/empathy-chat.c +++ b/libempathy-gtk/empathy-chat.c @@ -73,8 +73,8 @@ typedef struct { EmpathyLogManager *log_manager; EmpathyAccountManager *account_manager; - GSList *input_history; - gint input_history_index; + GList *input_history; + GList *input_history_current; GList *compositors; GCompletion *completion; guint composing_stop_timeout_id; @@ -367,13 +367,23 @@ chat_input_history_entry_get_text (InputHistoryEntry *entry) return entry->text; } +static GList * +chat_input_history_remove_item (GList *list, + GList *item) +{ + list = g_list_remove_link (list, item); + chat_input_history_entry_free (item->data); + g_list_free_1 (item); + return list; +} + static void chat_input_history_revert (EmpathyChat *chat) { - EmpathyChatPriv *priv; - GSList *list; - GSList *item1; - GSList *item2; + EmpathyChatPriv *priv; + GList *list; + GList *item1; + GList *item2; InputHistoryEntry *entry; priv = GET_PRIV (chat); @@ -385,92 +395,98 @@ chat_input_history_revert (EmpathyChat *chat) } /* Delete temporary entry */ - if (priv->input_history_index != -1) { + if (priv->input_history_current != NULL) { item1 = list; - list = g_slist_remove_link (list, item1); - chat_input_history_entry_free (item1->data); - g_slist_free_1 (item1); - priv->input_history_index--; + list = chat_input_history_remove_item (list, item1); + if (priv->input_history_current == item1) { + /* Removed temporary entry was current entry */ + priv->input_history = list; + priv->input_history_current = NULL; + return; + } + } + else { + /* There is no entry to revert */ + return; } - /* Restore the current history message to original value */ - if (priv->input_history_index >= 0) { - item1 = g_slist_nth (list, priv->input_history_index); - entry = item1->data; - chat_input_history_entry_revert (entry); + /* Restore the current history entry to original value */ + item1 = priv->input_history_current; + entry = item1->data; + chat_input_history_entry_revert (entry); - /* Remove restored entry if there is other occurance before this entry */ - item2 = g_slist_find_custom (list, chat_input_history_entry_get_text (entry), + /* Remove restored entry if there is other occurance before this entry */ + item2 = g_list_find_custom (list, chat_input_history_entry_get_text (entry), + (GCompareFunc) chat_input_history_entry_cmp); + if (item2 != item1) { + list = chat_input_history_remove_item (list, item1); + } + else { + /* Remove other occurance of the restored entry */ + item2 = g_list_find_custom (item1->next, + chat_input_history_entry_get_text (entry), (GCompareFunc) chat_input_history_entry_cmp); - if (item2 != item1) { - list = g_slist_remove_link (list, item1); - chat_input_history_entry_free (item1->data); - g_slist_free1 (item1); + if (item2 != NULL) { + list = chat_input_history_remove_item (list, item2); } - else { - /* Remove other occurance of the restored entry */ - item2 = g_slist_find_custom (item1->next, - chat_input_history_entry_get_text (entry), - (GCompareFunc) chat_input_history_entry_cmp); - if (item2 != NULL) { - list = g_slist_remove_link (list, item2); - chat_input_history_entry_free (item2->data); - g_slist_free1 (item2); - } - } - } - priv->input_history_index = -1; + priv->input_history_current = NULL; priv->input_history = list; - } static void chat_input_history_add (EmpathyChat *chat, - const gchar *str) + const gchar *str, + gboolean temporary) { - EmpathyChatPriv *priv; - GSList *list; - GSList *item; + EmpathyChatPriv *priv; + GList *list; + GList *item; InputHistoryEntry *entry; priv = GET_PRIV (chat); list = priv->input_history; - /* Remove any other occurances of this entry */ - while ((item = g_slist_find_custom (list, str, (GCompareFunc) chat_input_history_entry_cmp)) != NULL) { - list = g_slist_remove_link (list, item); - chat_input_history_entry_free (item->data); - g_slist_free1 (item); - } + /* Remove any other occurances of this entry, if not temporary */ + if (!temporary) { + while ((item = g_list_find_custom (list, str, + (GCompareFunc) chat_input_history_entry_cmp)) != NULL) { + list = chat_input_history_remove_item (list, item); + } - /* Trim the list to the last 10 items */ - while (g_slist_length (list) > 10) { - item = g_slist_last (list); - if (item != NULL) { - list = g_slist_remove_link (list, item); - chat_input_history_entry_free (item->data); - g_slist_free1 (item); + /* Trim the list to the last 10 items */ + while (g_list_length (list) > 10) { + item = g_list_last (list); + if (item != NULL) { + list = chat_input_history_remove_item (list, item); + } } } + + /* Add new entry */ entry = chat_input_history_entry_new_with_text (str); - list = g_slist_prepend (list, entry); + list = g_list_prepend (list, entry); - /* Set list and reset the index */ + /* Set the list and the current item pointer */ priv->input_history = list; - priv->input_history_index = -1; + if (temporary) { + priv->input_history_current = list; + } + else { + priv->input_history_current = NULL; + } } static const gchar * chat_input_history_get_next (EmpathyChat *chat) { EmpathyChatPriv *priv; - gint max; - InputHistoryEntry *entry; + GList *item; + const gchar *msg; priv = GET_PRIV (chat); @@ -478,42 +494,54 @@ chat_input_history_get_next (EmpathyChat *chat) DEBUG ("No input history, next entry is NULL"); return NULL; } + g_assert (priv->input_history_current != NULL); - max = g_slist_length (priv->input_history) - 1; - - if (priv->input_history_index < max) { - priv->input_history_index++; + if ((item = g_list_next (priv->input_history_current)) == NULL) + { + item = priv->input_history_current; } - DEBUG ("Returning next entry index:%d", priv->input_history_index); + msg = chat_input_history_entry_get_text (item->data); + + DEBUG ("Returning next entry: '%s'", msg); - entry = g_slist_nth_data (priv->input_history, priv->input_history_index); - return chat_input_history_entry_get_text (entry); + priv->input_history_current = item; + + return msg; } static const gchar * -chat_input_history_get_last (EmpathyChat *chat) +chat_input_history_get_prev (EmpathyChat *chat) { EmpathyChatPriv *priv; - InputHistoryEntry *entry; + GList *item; + const gchar *msg; g_return_val_if_fail (EMPATHY_IS_CHAT (chat), NULL); priv = GET_PRIV (chat); if (priv->input_history == NULL) { - DEBUG ("No input history, last entry is NULL"); + DEBUG ("No input history, previous entry is NULL"); return NULL; } - if (priv->input_history_index > 0) { - priv->input_history_index--; + if (priv->input_history_current == NULL) + { + return NULL; + } + else if ((item = g_list_previous (priv->input_history_current)) == NULL) + { + item = priv->input_history_current; } - DEBUG ("Returning last entry index:%d", priv->input_history_index); + msg = chat_input_history_entry_get_text (item->data); - entry = g_slist_nth_data (priv->input_history, priv->input_history_index); - return chat_input_history_entry_get_text (entry); + DEBUG ("Returning previous entry: '%s'", msg); + + priv->input_history_current = item; + + return msg; } static void @@ -530,17 +558,15 @@ chat_input_history_update (EmpathyChat *chat, gtk_text_buffer_get_bounds (buffer, &start, &end); text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE); - if (priv->input_history_index == -1) { + if (priv->input_history_current == NULL) { /* Add the current text temporarily to the history */ - chat_input_history_add (chat, text); - priv->input_history_index++; - + chat_input_history_add (chat, text, TRUE); g_free (text); return; } /* Save the changes in the history */ - entry = g_slist_nth_data (priv->input_history, priv->input_history_index); + entry = priv->input_history_current->data; if (tp_strdiff (chat_input_history_entry_get_text (entry), text)) { chat_input_history_entry_update_text (entry, text); } @@ -561,7 +587,7 @@ chat_send (EmpathyChat *chat, priv = GET_PRIV (chat); - chat_input_history_add (chat, msg); + chat_input_history_add (chat, msg, FALSE); if (strcmp (msg, "/clear") == 0) { empathy_chat_view_clear (chat->view); @@ -874,7 +900,7 @@ chat_input_key_press_event_cb (GtkWidget *widget, if (event->keyval == GDK_Up) { str = chat_input_history_get_next (chat); } else { - str = chat_input_history_get_last (chat); + str = chat_input_history_get_prev (chat); } g_signal_handlers_block_by_func (buffer, @@ -1707,8 +1733,8 @@ chat_finalize (GObject *object) DEBUG ("Finalized: %p", object); - g_slist_foreach (priv->input_history, (GFunc) chat_input_history_entry_free, NULL); - g_slist_free (priv->input_history); + g_list_foreach (priv->input_history, (GFunc) chat_input_history_entry_free, NULL); + g_list_free (priv->input_history); g_list_foreach (priv->compositors, (GFunc) g_object_unref, NULL); g_list_free (priv->compositors); @@ -1883,7 +1909,7 @@ empathy_chat_init (EmpathyChat *chat) priv->log_manager = empathy_log_manager_dup_singleton (); priv->contacts_width = -1; priv->input_history = NULL; - priv->input_history_index = -1; + priv->input_history_current = NULL; priv->account_manager = empathy_account_manager_dup_singleton (); g_signal_connect (priv->account_manager, |