Add a backward completion (Oleg)
When we skip some needed item with tab, we can back with shift+tab.
--- 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 {
--- 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 {
--- 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__ */
--- 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();
--- 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);