# HG changeset patch # User Sadrul Habib Chowdhury # Date 1193405486 0 # Node ID 1f59065c606aac4e2c0e174e3e7630699cb2cef4 # Parent b2d3f529f500109c261088d4c463d3f69e6b0244 Add 'yank' action in the entry boxes. diff -r b2d3f529f500 -r 1f59065c606a ChangeLog --- a/ChangeLog Fri Oct 26 09:44:00 2007 +0000 +++ b/ChangeLog Fri Oct 26 13:31:26 2007 +0000 @@ -24,6 +24,7 @@ Read the 'Menus' section in the man-page for details. * 'transpose-chars' operation for the entry boxes. The default key-binding is ctrl+t. + * 'yank' operation for the entry boxes. The default binding is ctrl+y. version 2.2.2: http://developer.pidgin.im/query?status=closed&milestone=2.2.2 diff -r b2d3f529f500 -r 1f59065c606a ChangeLog.API --- a/ChangeLog.API Fri Oct 26 09:44:00 2007 +0000 +++ b/ChangeLog.API Fri Oct 26 13:31:26 2007 +0000 @@ -108,6 +108,7 @@ given id from a menu. * Added gnt_menuitem_activate, which triggers the 'activate' signal on the menuitem and calls the callback function, if available. + * Added GntEntryKillRing in GntEntry. version 2.2.2 (??/??/????): libpurple: diff -r b2d3f529f500 -r 1f59065c606a finch/libgnt/gntentry.c --- a/finch/libgnt/gntentry.c Fri Oct 26 09:44:00 2007 +0000 +++ b/finch/libgnt/gntentry.c Fri Oct 26 13:31:26 2007 +0000 @@ -36,6 +36,24 @@ SIG_COMPLETION, SIGS, }; + +typedef enum +{ + ENTRY_JAIL = -1, /* Suspend the kill ring. */ + ENTRY_DEL_BWD_WORD = 1, + ENTRY_DEL_BWD_CHAR, + ENTRY_DEL_FWD_WORD, + ENTRY_DEL_FWD_CHAR, + ENTRY_DEL_EOL, + ENTRY_DEL_BOL, +} GntEntryAction; + +struct _GntEntryKillRing +{ + GString *buffer; + GntEntryAction last; +}; + static guint signals[SIGS] = { 0 }; static GntWidgetClass *parent_class = NULL; @@ -43,6 +61,58 @@ static gboolean gnt_entry_key_pressed(GntWidget *widget, const char *text); static void gnt_entry_set_text_internal(GntEntry *entry, const char *text); +static gboolean +update_kill_ring(GntEntry *entry, GntEntryAction action, const char *text, int len) +{ + if (action < 0) { + entry->killring->last = action; + return FALSE; + } + + if (len == 0) + len = strlen(text); + else if (len < 0) { + text += len; + len = -len; + } + + if (action != entry->killring->last) { + struct { + GntEntryAction one; + GntEntryAction two; + } merges[] = { + {ENTRY_DEL_BWD_WORD, ENTRY_DEL_FWD_WORD}, + {ENTRY_DEL_BWD_CHAR, ENTRY_DEL_FWD_CHAR}, + {ENTRY_DEL_BOL, ENTRY_DEL_EOL}, + {ENTRY_JAIL, ENTRY_JAIL}, + }; + int i; + + for (i = 0; merges[i].one != ENTRY_JAIL; i++) { + if (merges[i].one == entry->killring->last && + merges[i].two == action) { + g_string_append_len(entry->killring->buffer, text, len); + break; + } else if (merges[i].one == action && + merges[i].two == entry->killring->last) { + g_string_prepend_len(entry->killring->buffer, text, len); + break; + } + } + if (merges[i].one == ENTRY_JAIL) { + g_string_assign(entry->killring->buffer, text); + g_string_truncate(entry->killring->buffer, len); + } + entry->killring->last = action; + } else { + if (action == ENTRY_DEL_BWD_CHAR || action == ENTRY_DEL_BWD_WORD) + g_string_prepend_len(entry->killring->buffer, text, len); + else + g_string_append_len(entry->killring->buffer, text, len); + } + return TRUE; +} + static void destroy_suggest(GntEntry *entry) { @@ -97,6 +167,7 @@ if (changed) g_signal_emit(G_OBJECT(entry), signals[SIG_COMPLETION], 0, entry->start + offstart, entry->start + offend); + update_kill_ring(entry, ENTRY_JAIL, NULL, 0); return changed; } @@ -264,6 +335,7 @@ entry->cursor = g_utf8_find_prev_char(entry->start, entry->cursor); if (entry->cursor < entry->scroll) entry->scroll = entry->cursor; + update_kill_ring(entry, ENTRY_JAIL, NULL, 0); entry_redraw(GNT_WIDGET(entry)); return TRUE; } @@ -277,6 +349,7 @@ entry->cursor = g_utf8_find_next_char(entry->cursor, NULL); while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= GNT_WIDGET(entry)->priv.width) entry->scroll = g_utf8_find_next_char(entry->scroll, NULL); + update_kill_ring(entry, ENTRY_JAIL, NULL, 0); entry_redraw(GNT_WIDGET(entry)); return TRUE; } @@ -289,9 +362,11 @@ if (entry->cursor <= entry->start) return TRUE; - + len = entry->cursor - g_utf8_find_prev_char(entry->start, entry->cursor); + update_kill_ring(entry, ENTRY_DEL_BWD_CHAR, entry->cursor, -len); entry->cursor -= len; + memmove(entry->cursor, entry->cursor + len, entry->end - entry->cursor); entry->end -= len; @@ -313,8 +388,9 @@ if (entry->cursor >= entry->end) return FALSE; - + len = g_utf8_find_next_char(entry->cursor, NULL) - entry->cursor; + update_kill_ring(entry, ENTRY_DEL_FWD_CHAR, entry->cursor, len); memmove(entry->cursor, entry->cursor + len, entry->end - entry->cursor - len + 1); entry->end -= len; entry_redraw(GNT_WIDGET(entry)); @@ -331,6 +407,7 @@ GntEntry *entry = GNT_ENTRY(bind); entry->scroll = entry->cursor = entry->start; entry_redraw(GNT_WIDGET(entry)); + update_kill_ring(entry, ENTRY_JAIL, NULL, 0); return TRUE; } @@ -343,6 +420,7 @@ while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= GNT_WIDGET(entry)->priv.width) entry->scroll = g_utf8_find_next_char(entry->scroll, NULL); entry_redraw(GNT_WIDGET(entry)); + update_kill_ring(entry, ENTRY_JAIL, NULL, 0); return TRUE; } @@ -357,6 +435,7 @@ destroy_suggest(entry); entry_text_changed(entry); + update_kill_ring(entry, ENTRY_JAIL, NULL, 0); return TRUE; } return FALSE; @@ -381,6 +460,7 @@ destroy_suggest(entry); entry_text_changed(entry); + update_kill_ring(entry, ENTRY_JAIL, NULL, 0); return TRUE; } return FALSE; @@ -400,6 +480,7 @@ a = g_strndup(entry->start, entry->cursor - entry->start); all = g_strconcat(a, text, entry->cursor, NULL); gnt_entry_set_text_internal(entry, all); + update_kill_ring(entry, ENTRY_JAIL, NULL, 0); g_free(a); g_free(text); g_free(all); @@ -445,6 +526,7 @@ GntEntry *entry = GNT_ENTRY(bind); if (entry->cursor <= entry->start) return TRUE; + update_kill_ring(entry, ENTRY_DEL_BOL, entry->start, entry->cursor - entry->start); memmove(entry->start, entry->cursor, entry->end - entry->cursor); entry->end -= (entry->cursor - entry->start); entry->cursor = entry->scroll = entry->start; @@ -460,6 +542,7 @@ GntEntry *entry = GNT_ENTRY(bind); if (entry->end <= entry->cursor) return TRUE; + update_kill_ring(entry, ENTRY_DEL_EOL, entry->cursor, entry->end - entry->cursor); entry->end = entry->cursor; memset(entry->end, '\0', entry->buffer - (entry->end - entry->start)); entry_redraw(GNT_WIDGET(bind)); @@ -517,6 +600,7 @@ entry->cursor = (char*)iter; if (entry->cursor < entry->scroll) entry->scroll = entry->cursor; + update_kill_ring(entry, ENTRY_JAIL, NULL, 0); entry_redraw(GNT_WIDGET(bind)); return TRUE; } @@ -533,6 +617,7 @@ return TRUE; iter = (char*)begin_word(iter, entry->start); count = entry->cursor - iter; + update_kill_ring(entry, ENTRY_DEL_BWD_WORD, iter, count); memmove(iter, entry->cursor, entry->end - entry->cursor); entry->end -= count; entry->cursor = iter; @@ -557,6 +642,7 @@ while (gnt_util_onscreen_width(entry->scroll, entry->cursor) >= widget->priv.width) { entry->scroll = g_utf8_find_next_char(entry->scroll, NULL); } + update_kill_ring(entry, ENTRY_JAIL, NULL, 0); entry_redraw(widget); return TRUE; } @@ -570,6 +656,7 @@ int len = entry->end - iter + 1; if (len <= 0) return TRUE; + update_kill_ring(entry, ENTRY_DEL_FWD_WORD, entry->cursor, iter - entry->cursor); memmove(entry->cursor, iter, len); len = iter - entry->cursor; entry->end -= len; @@ -601,12 +688,21 @@ memmove(prev, current, entry->cursor - current); memcpy(prev + (entry->cursor - current), hold, current - prev); + update_kill_ring(entry, ENTRY_JAIL, NULL, 0); entry_redraw(GNT_WIDGET(entry)); entry_text_changed(entry); return TRUE; } static gboolean +entry_yank(GntBindable *bind, GList *null) +{ + GntEntry *entry = GNT_ENTRY(bind); + gnt_entry_key_pressed(GNT_WIDGET(entry), entry->killring->buffer->str); + return TRUE; +} + +static gboolean gnt_entry_key_pressed(GntWidget *widget, const char *text) { GntEntry *entry = GNT_ENTRY(widget); @@ -629,6 +725,7 @@ destroy_suggest(entry); complete_suggest(entry, text); g_free(text); + update_kill_ring(entry, ENTRY_JAIL, NULL, 0); entry_text_changed(entry); return TRUE; } @@ -685,6 +782,7 @@ if (entry->ddown) show_suggest_dropdown(entry); } + update_kill_ring(entry, ENTRY_JAIL, NULL, 0); entry_redraw(widget); entry_text_changed(entry); return TRUE; @@ -695,6 +793,13 @@ } static void +jail_killring(GntEntryKillRing *kr) +{ + g_string_free(kr->buffer, TRUE); + g_free(kr); +} + +static void gnt_entry_destroy(GntWidget *widget) { GntEntry *entry = GNT_ENTRY(widget); @@ -717,6 +822,8 @@ { gnt_widget_destroy(entry->ddown->parent); } + + jail_killring(entry->killring); } static void @@ -791,6 +898,8 @@ "\033" "d", NULL); gnt_bindable_class_register_action(bindable, "transpose-chars", transpose_chars, GNT_KEY_CTRL_T, NULL); + gnt_bindable_class_register_action(bindable, "yank", entry_yank, + GNT_KEY_CTRL_Y, NULL); gnt_bindable_class_register_action(bindable, "suggest-show", suggest_show, "\t", NULL); gnt_bindable_class_register_action(bindable, "suggest-next", suggest_next, @@ -808,6 +917,14 @@ GNTDEBUG; } +static GntEntryKillRing * +new_killring() +{ + GntEntryKillRing *kr = g_new0(GntEntryKillRing, 1); + kr->buffer = g_string_new(NULL); + return kr; +} + static void gnt_entry_init(GTypeInstance *instance, gpointer class) { @@ -816,13 +933,14 @@ entry->flag = GNT_ENTRY_FLAG_ALL; entry->max = 0; - + entry->histlength = 0; entry->history = NULL; entry->word = TRUE; entry->always = FALSE; entry->suggests = NULL; + entry->killring = new_killring(); GNT_WIDGET_SET_FLAGS(GNT_WIDGET(entry), GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW | GNT_WIDGET_CAN_TAKE_FOCUS); @@ -830,7 +948,7 @@ widget->priv.minw = 3; widget->priv.minh = 1; - + GNTDEBUG; } @@ -1021,7 +1139,7 @@ if (!text || !*text) return; - + find = g_list_find_custom(entry->suggests, text, (GCompareFunc)g_utf8_collate); if (find) return; diff -r b2d3f529f500 -r 1f59065c606a finch/libgnt/gntentry.h --- a/finch/libgnt/gntentry.h Fri Oct 26 09:44:00 2007 +0000 +++ b/finch/libgnt/gntentry.h Fri Oct 26 13:31:26 2007 +0000 @@ -48,6 +48,7 @@ typedef struct _GntEntry GntEntry; typedef struct _GntEntryPriv GntEntryPriv; typedef struct _GntEntryClass GntEntryClass; +typedef struct _GntEntryKillRing GntEntryKillRing; typedef enum { @@ -71,9 +72,9 @@ char *scroll; /* Current scrolling position */ char *cursor; /* Cursor location */ /* 0 <= cursor - scroll < widget-width */ - + size_t buffer; /* Size of the buffer */ - + int max; /* 0 means infinite */ gboolean masked; @@ -84,6 +85,7 @@ gboolean word; /* Are the suggestions for only a word, or for the whole thing? */ gboolean always; /* Should the list of suggestions show at all times, or only on tab-press? */ GntWidget *ddown; /* The dropdown with the suggested list */ + GntEntryKillRing *killring; /**< @since 2.3.0 */ }; struct _GntEntryClass