# HG changeset patch # User Mikael Berthe # Date 1404651077 -7200 # Node ID 2f294c2b6778108e4e595cbe83b0a5459f230ad3 # Parent 0e8a25503ee126ca980bc9bafb7627397106d528 Add a backward completion (Oleg) When we skip some needed item with tab, we can back with shift+tab. diff -r 0e8a25503ee1 -r 2f294c2b6778 mcabber/mcabber/commands.c --- a/mcabber/mcabber/commands.c Sun Jul 06 14:51:14 2014 +0200 +++ b/mcabber/mcabber/commands.c Sun Jul 06 14:51:17 2014 +0200 @@ -4078,7 +4078,9 @@ } else if (!strcasecmp(arg, "compl_cancel")) { readline_cancel_completion(); } else if (!strcasecmp(arg, "compl_do")) { - readline_do_completion(); + readline_do_completion(TRUE); + } else if (!strcasecmp(arg, "compl_do_bwd")) { + readline_do_completion(FALSE); } else if (!strcasecmp(arg, "clear_history")) { readline_clear_history(); } else { diff -r 0e8a25503ee1 -r 2f294c2b6778 mcabber/mcabber/compl.c --- a/mcabber/mcabber/compl.c Sun Jul 06 14:51:14 2014 +0200 +++ b/mcabber/mcabber/compl.c Sun Jul 06 14:51:17 2014 +0200 @@ -41,10 +41,10 @@ // Completion structure typedef struct { - GSList *list; // list of matches + GList *list; // list of matches guint len_prefix; // length of text already typed by the user guint len_compl; // length of the last completion - GSList *next; // pointer to next completion to try + GList *next; // pointer to next completion to try } compl; typedef GSList *(*compl_handler_t) (void); // XXX userdata? *dynlist? @@ -233,12 +233,13 @@ else compval = g_strdup(word+len); // for a bit of efficiency, will reverse order afterwards - c->list = g_slist_prepend(c->list, compval); + c->list = g_list_prepend(c->list, compval); ret_len ++; } } } - c->next = c->list = g_slist_reverse (c->list); + c->list = g_list_reverse(c->list); + c->next = NULL; InputCompl = c; return ret_len; } @@ -246,14 +247,14 @@ // done_completion(); void done_completion(void) { - GSList *clp; + GList *clp; if (!InputCompl) return; // Free the current completion list - for (clp = InputCompl->list; clp; clp = g_slist_next(clp)) + for (clp = InputCompl->list; clp; clp = g_list_next(clp)) g_free(clp->data); - g_slist_free(InputCompl->list); + g_list_free(InputCompl->list); g_free(InputCompl); InputCompl = NULL; } @@ -267,7 +268,7 @@ } // Returns pointer to text to insert, NULL if no completion. -const char *complete() +const char *complete(gboolean fwd) { compl* c = InputCompl; char *r; @@ -275,12 +276,25 @@ if (!InputCompl) return NULL; if (!c->next) { - c->next = c->list; // back to the beginning + if (fwd) + c->next = c->list; // back to the beginning + else + c->next = g_list_last(c->list); // back to the ending + } else { + if (fwd) + c->next = g_list_next(c->next); + else + c->next = g_list_previous(c->next); + } + + if (!c->next) { + c->next = NULL; c->len_compl = 0; return NULL; } + r = (char*)c->next->data; - c->next = g_slist_next(c->next); + if (!utf8_mode) { c->len_compl = strlen(r); } else { diff -r 0e8a25503ee1 -r 2f294c2b6778 mcabber/mcabber/compl.h --- a/mcabber/mcabber/compl.h Sun Jul 06 14:51:14 2014 +0200 +++ b/mcabber/mcabber/compl.h Sun Jul 06 14:51:17 2014 +0200 @@ -51,7 +51,7 @@ const gchar *suffix); void done_completion(void); guint cancel_completion(void); -const char *complete(void); +const char *complete(gboolean fwd); #endif /* __MCABBER_COMPL_H__ */ diff -r 0e8a25503ee1 -r 2f294c2b6778 mcabber/mcabber/screen.c --- a/mcabber/mcabber/screen.c Sun Jul 06 14:51:14 2014 +0200 +++ b/mcabber/mcabber/screen.c Sun Jul 06 14:51:17 2014 +0200 @@ -84,7 +84,7 @@ static void scr_cancel_current_completion(void); static void scr_end_current_completion(void); static void scr_insert_text(const char*); -static void scr_handle_tab(void); +static void scr_handle_tab(gboolean fwd); #if defined XEP0022 || defined XEP0085 static gboolean scr_chatstates_timeout(); @@ -3673,13 +3673,13 @@ check_offset(-1); } -void readline_do_completion(void) +void readline_do_completion(gboolean fwd) { int i, n; if (multimode != 2) { // Not in verbatim multi-line mode - scr_handle_tab(); + scr_handle_tab(fwd); } else { // Verbatim multi-line mode: expand tab char tabstr[9]; @@ -3888,7 +3888,8 @@ // scr_handle_tab() // Function called when tab is pressed. // Initiate or continue a completion... -static void scr_handle_tab(void) +// If fwd is false, a backward-completion is requested. +static void scr_handle_tab(gboolean fwd) { int nrow; const char *row; @@ -3973,7 +3974,7 @@ g_slist_free(list); } // Now complete - cchar = complete(); + cchar = complete(fwd); if (cchar) scr_insert_text(cchar); completion_started = TRUE; @@ -3981,7 +3982,7 @@ } else { // Completion already initialized scr_cancel_current_completion(); // Now complete again - cchar = complete(); + cchar = complete(fwd); if (cchar) scr_insert_text(cchar); } @@ -4362,7 +4363,10 @@ case ERR: break; case 9: // Tab - readline_do_completion(); + readline_do_completion(TRUE); // Forward-completion + break; + case 353: // Shift-Tab + readline_do_completion(FALSE); // Backward-completion break; case 13: // Enter case 343: // Enter on Maemo @@ -4423,7 +4427,7 @@ } } - if (completion_started && key != 9 && key != KEY_RESIZE) + if (completion_started && key != 9 && key != 353 && key != KEY_RESIZE) scr_end_current_completion(); refresh_inputline(); diff -r 0e8a25503ee1 -r 2f294c2b6778 mcabber/mcabber/screen.h --- a/mcabber/mcabber/screen.h Sun Jul 06 14:51:14 2014 +0200 +++ b/mcabber/mcabber/screen.h Sun Jul 06 14:51:17 2014 +0200 @@ -181,7 +181,7 @@ int readline_accept_line(int down_history); void readline_clear_history(void); void readline_cancel_completion(void); -void readline_do_completion(void); +void readline_do_completion(gboolean fwd); void readline_refresh_screen(void); void readline_disable_chat_mode(guint show_roster); void readline_hist_beginning_search_bwd(void);