# HG changeset patch # User mikael # Date 1114029348 0 # Node ID f20831f7d34929bbb41f553d201021f445233b5f # Parent 191f4d00d19be5b4f65caf147e5c64e608797b9b [/trunk] Changeset 112 by mikael * Completion system enabled for commands. It almost works! ;-) diff -r 191f4d00d19b -r f20831f7d349 mcabber/src/TODO --- a/mcabber/src/TODO Wed Apr 20 20:30:09 2005 +0000 +++ b/mcabber/src/TODO Wed Apr 20 20:35:48 2005 +0000 @@ -4,6 +4,7 @@ * Should not stay on buddy buffer when one moves to a group * Pending message not displayed if buddy outside Contact window * Command not recognised if there is a trailing space! ("/quit ") +* Completion is buggy when we're not at the EOL... TODO: diff -r 191f4d00d19b -r f20831f7d349 mcabber/src/commands.c --- a/mcabber/src/commands.c Wed Apr 20 20:30:09 2005 +0000 +++ b/mcabber/src/commands.c Wed Apr 20 20:35:48 2005 +0000 @@ -121,7 +121,7 @@ int process_line(char *line) { if (*line != '/') { - send_message(line); + send_message(line); // FIXME: are we talking to a _buddy_? return 0; } if (!strcasecmp(line, "/quit")) { diff -r 191f4d00d19b -r f20831f7d349 mcabber/src/compl.c --- a/mcabber/src/compl.c Wed Apr 20 20:30:09 2005 +0000 +++ b/mcabber/src/compl.c Wed Apr 20 20:35:48 2005 +0000 @@ -79,7 +79,8 @@ for (sl_cat=compl_cat; sl_cat; sl_cat = g_slist_next(sl_cat)) { char *word = sl_cat->data; if (!strncmp(prefix, word, len)) { - c->list = g_slist_append(c->list, g_strdup(word+len)); // TODO sort + if (strlen(word) != len) + c->list = g_slist_append(c->list, g_strdup(word+len)); // TODO sort } } c->next = c->list; @@ -89,6 +90,8 @@ // done_completion(); void done_completion(void) { + if (!InputCompl) return; + // TODO free everything g_slist_free(InputCompl->list); g_free(InputCompl); @@ -100,6 +103,7 @@ //guint cancel_completion(compl *c) guint cancel_completion(void) { + if (!InputCompl) return 0; return InputCompl->len_compl; } @@ -108,6 +112,9 @@ { compl* c = InputCompl; char *r; + + if (!InputCompl) return NULL; + if (!c->next) { c->next = c->list; // back to the beginning c->len_compl = 0; diff -r 191f4d00d19b -r f20831f7d349 mcabber/src/compl.h --- a/mcabber/src/compl.h Wed Apr 20 20:30:09 2005 +0000 +++ b/mcabber/src/compl.h Wed Apr 20 20:35:48 2005 +0000 @@ -10,11 +10,12 @@ #define COMPL_STATUS 16 // Not implemented yet #define COMPL_FILENAME 32 // Not implemented yet -void compl_add_category_word(guint, const char *command); +void compl_add_category_word(guint, const char *command); +GSList *compl_get_category_list(guint cat_flags); -void new_completion(char *prefix, GSList *compl_cat); -void done_completion(void); -guint cancel_completion(void); +void new_completion(char *prefix, GSList *compl_cat); +void done_completion(void); +guint cancel_completion(void); const char *complete(void); #endif /* __COMPL_H__ */ diff -r 191f4d00d19b -r f20831f7d349 mcabber/src/screen.c --- a/mcabber/src/screen.c Wed Apr 20 20:30:09 2005 +0000 +++ b/mcabber/src/screen.c Wed Apr 20 20:35:48 2005 +0000 @@ -45,6 +45,7 @@ static char inputLine[INPUTLINE_LENGTH+1]; static char *ptr_inputline; static short int inputline_offset; +static int completion_started; /* Funciones */ @@ -582,6 +583,109 @@ doupdate(); } +// which_row() +// Tells which row our cursor is in, in the command line. +// -1 -> normal text +// 0 -> command +// 1 -> parameter 1 (etc.) +int which_row(void) +{ + int row = -1; + char *p; + int quote = FALSE; + + // Not a command? + if ((ptr_inputline == inputLine) || (inputLine[0] != '/')) + return -1; + + // This is a command + row = 0; + for (p = inputLine ; p < ptr_inputline ; p++) { + if (quote) { + if (*p == '"' && *(p-1) != '\\') + quote = FALSE; + continue; + } + if (*p == '"' && *(p-1) != '\\') { + quote = TRUE; + } else if (*p == ' ' && *(p-1) != ' ') + row++; + } + return row; +} + +void scr_insert_text(const char *text) +{ + char tmpLine[INPUTLINE_LENGTH+1]; + int len = strlen(text); + // Check the line isn't too long + if (strlen(inputLine) + len >= INPUTLINE_LENGTH) { + scr_LogPrint("Cannot insert text, line too long."); + return; + } + + strcpy(tmpLine, ptr_inputline); + strcpy(ptr_inputline, text); ptr_inputline += len; + strcpy(ptr_inputline, tmpLine); +} + +void scr_handle_tab(void) +{ + int row; + row = which_row(); + + if (row == -1) return; // No completion if no leading slash + + if (row == 0) { // Command completion + if (!completion_started) { + GSList *list = compl_get_category_list(COMPL_CMD); + if (list) { + const char *cchar; + char *prefix = g_strndup(&inputLine[1], ptr_inputline-inputLine); + new_completion(prefix, list); + cchar = complete(); + if (cchar) + scr_insert_text(cchar); + g_free(prefix); + completion_started = TRUE; + } + } else { + char *c; + const char *cchar; + guint back = cancel_completion(); + // Remove $back chars + ptr_inputline -= back; + c = ptr_inputline; + for ( ; *c ; c++) + *c = *(c+back); + // Now complete again + cchar = complete(); + if (cchar) + scr_insert_text(cchar); + } + return; + } + scr_LogPrint("I'm unable to complete that yet"); +} + +void scr_cancel_current_completion(void) +{ + char *c; + guint back = cancel_completion(); + // Remove $back chars + ptr_inputline -= back; + c = ptr_inputline; + for ( ; *c ; c++) + *c = *(c+back); +} + +void scr_end_current_completion(void) +{ + done_completion(); + completion_started = FALSE; + scr_LogPrint("Freeing completion data"); +} + // check_offset(int direction) // Check inputline_offset value, and make sure the cursor is inside the // screen. @@ -645,8 +749,14 @@ ptr_inputline++; check_offset(1); break; + case 7: // Ctrl-g + scr_cancel_current_completion(); + scr_end_current_completion(); + check_offset(-1); + break; case 9: // Tab - scr_LogPrint("I'm unable to complete yet"); + scr_handle_tab(); + check_offset(0); break; case '\n': // Enter chatmode = TRUE; @@ -711,6 +821,8 @@ scr_LogPrint("Unkown key=%d", key); } } + if (completion_started && key != 9) + scr_end_current_completion(); mvwprintw(inputWnd, 0,0, "%s", inputLine + inputline_offset); wclrtoeol(inputWnd); if (*ptr_inputline) {