# HG changeset patch # User mikael # Date 1113941394 0 # Node ID 9a4aa2797f027aa2a062b59d4fdddaf613c0435c # Parent b3618cb3bf65689f095f739b41192d99191cd75b [/trunk] Changeset 108 by mikael * Add completion functions. (Not integrated to the UI yet) diff -r b3618cb3bf65 -r 9a4aa2797f02 mcabber/src/Makefile.am --- a/mcabber/src/Makefile.am Mon Apr 18 19:27:16 2005 +0000 +++ b/mcabber/src/Makefile.am Tue Apr 19 20:09:54 2005 +0000 @@ -1,6 +1,7 @@ bin_PROGRAMS = mcabber -mcabber_SOURCES = main.c jabglue.c jabglue.h commands.c commands.h \ - roster.c roster.h hbuf.c hbuf.h screen.c screen.h \ +mcabber_SOURCES = main.c jabglue.c jabglue.h roster.c roster.h \ + commands.c commands.h compl.c compl.h \ + hbuf.c hbuf.h screen.c screen.h \ parsecfg.c parsecfg.h utf8.c utf8.h \ utils.c utils.h lang.c lang.h list.h harddefines.h diff -r b3618cb3bf65 -r 9a4aa2797f02 mcabber/src/commands.c --- a/mcabber/src/commands.c Mon Apr 18 19:27:16 2005 +0000 +++ b/mcabber/src/commands.c Tue Apr 19 20:09:54 2005 +0000 @@ -27,6 +27,15 @@ #include "utils.h" +// Command structure +typedef struct { + char name[32]; + char *help; // ? + guint completion_flags; + void *(*func)(); +} cmd; + + // send_message(msg) // Write the message in the buddy's window and send the message on // the network. diff -r b3618cb3bf65 -r 9a4aa2797f02 mcabber/src/commands.h --- a/mcabber/src/commands.h Mon Apr 18 19:27:16 2005 +0000 +++ b/mcabber/src/commands.h Tue Apr 19 20:09:54 2005 +0000 @@ -1,6 +1,8 @@ #ifndef __COMMANDS_H__ #define __COMMANDS_H__ 1 +#include + int process_line(char *line); #endif /* __COMMANDS_H__ */ diff -r b3618cb3bf65 -r 9a4aa2797f02 mcabber/src/compl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mcabber/src/compl.c Tue Apr 19 20:09:54 2005 +0000 @@ -0,0 +1,233 @@ +/* + * compl.c -- Completion system + * + * Copyright (C) 2005 Mikael Berthe + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +/* Usage, basically: + * - new_completion(); // 1. Initialization + * - complete(); // 2. 1st completion + * - cancel_completion(); // 3a. 2nd completion / cancel previous + * - complete(); // 3b. 2nd completion / complete + * ... + * - done_completion(); // n. finished -- free allocated areas + * + */ + +#include + +#include "compl.h" + +// Completion structure +typedef struct { + GSList *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 +} compl; + +// Category structure +typedef struct { + guint flag; + GSList *words; +} category; + +static GSList *Categories; +static compl *InputCompl; + +// XXX Should not be there (?) +// jid_list(type) +// Returns a list of jid's. If type is COMPL_URLJID, urls are surrounded with +// '<' and '>'. +GSList *jid_list(guint type) // bool urlstyle? +{ +} + +// new_completion(prefix, compl_cat) +// . prefix = beginning of the word, typed by the user +// . compl_cat = pointer to a completion category list (list of *char) +// Returns a pointer to an allocated compl structure. This structure should +// be freed by the caller when not used anymore. +//compl *new_completion(char *prefix, GSList *compl_cat) +void new_completion(char *prefix, GSList *compl_cat) +{ + compl *c; + GSList *sl_cat; + int len = strlen(prefix); + + if (InputCompl) { // This should not happen, but hey... + cancel_completion(); + } + + c = g_new0(compl, 1); + // Build the list of matches + 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 + } + } + c->next = c->list; + InputCompl = c; +} + +// done_completion(); +void done_completion(void) +{ + // TODO free everything + g_slist_free(InputCompl->list); + g_free(InputCompl); + InputCompl = NULL; +} + +// cancel_completion() +// Returns the number of chars to delete to cancel the completion +//guint cancel_completion(compl *c) +guint cancel_completion(void) +{ + return InputCompl->len_compl; +} + +// Returns pointer to text to insert, NULL if no completion. +const char *complete() +{ + compl* c = InputCompl; + char *r; + if (!c->next) { + c->next = c->list; // back to the beginning + c->len_compl = 0; + return NULL; + } + r = (char*)c->next->data; + c->next = g_slist_next(c->next); + c->len_compl = strlen(r); + return r; +} + + +/* Categories functions */ + +// compl_add_category_command(categ, command) +// Adds command as a possible completion in category categ. +void compl_add_category_command(guint categ, char *command) +{ + GSList *sl_cat; + category *cat; + // Look for category + for (sl_cat=Categories; sl_cat; sl_cat = g_slist_next(sl_cat)) { + if (categ == ((category*)sl_cat->data)->flag) + break; + } + if (!sl_cat) { // Category not found, let's create it + cat = g_new0(category, 1); + cat->flag = categ; + Categories = g_slist_append(Categories, cat); + } else + cat = (category*)sl_cat->data; + + // TODO Check word does not already exist + cat->words = g_slist_append(cat->words, g_strdup(command)); // TODO sort +} + +GSList *compl_get_category_list(guint cat_flags) +{ + GSList *sl_cat; + // Look for category + // XXX Actually that's not that simple... cat_flags can be a combination + // of several flags! + for (sl_cat=Categories; sl_cat; sl_cat = g_slist_next(sl_cat)) { + if (cat_flags == ((category*)sl_cat->data)->flag) + break; + } + if (sl_cat) // Category was found, easy... + return ((category*)sl_cat->data)->words; + + // TODO handle dynamic SLists :) + return NULL; +} + + +/* +void test_dump_categories(void) +{ + GSList *sl_cat; + // Look for category + for (sl_cat=Categories; sl_cat; sl_cat = g_slist_next(sl_cat)) { + GSList *sl_words; + category *cat = (category*)sl_cat->data; + printf("Category: %u\n", cat->flag); + for (sl_words=cat->words; sl_words; sl_words = g_slist_next(sl_words)) { + char *word = sl_words->data; + printf(" Keyword: [%s]\n", word); + } + } +} + +void test_comp(guint cat_flags, char *prefix) +{ + GSList *list = compl_get_category_list(cat_flags); + if (list) { + const char *cchar; + guint back; + int i; + new_completion(prefix, list); + cchar = complete(); + printf("Complete -> \"%s\"\n", cchar); + for (i=0 ; i<5; i++) { + back = cancel_completion(); + printf("Back: %d\n", back); + cchar = complete(); + printf("Complete -> \"%s\"\n", cchar); + } + back = cancel_completion(); + printf("Back: %d\n", back); + done_completion(); + } +} + +int main() +{ + compl_add_category_command(COMPL_CMD, "add"); + compl_add_category_command(COMPL_CMD, "clear"); + compl_add_category_command(COMPL_CMD, "del"); + compl_add_category_command(COMPL_CMD, "group"); + compl_add_category_command(COMPL_CMD, "info"); + compl_add_category_command(COMPL_CMD, "move"); + compl_add_category_command(COMPL_CMD, "rename"); + compl_add_category_command(COMPL_CMD, "request_auth"); + compl_add_category_command(COMPL_CMD, "say"); + compl_add_category_command(COMPL_CMD, "search"); + compl_add_category_command(COMPL_CMD, "send_auth"); + compl_add_category_command(COMPL_CMD, "status"); + compl_add_category_command(COMPL_STATUS, "online"); + compl_add_category_command(COMPL_STATUS, "avail"); + compl_add_category_command(COMPL_STATUS, "invisible"); + compl_add_category_command(COMPL_STATUS, "free"); + compl_add_category_command(COMPL_STATUS, "dnd"); + compl_add_category_command(COMPL_STATUS, "busy"); + compl_add_category_command(COMPL_STATUS, "notavail"); + compl_add_category_command(COMPL_STATUS, "away"); + + //test_dump_categories(); + + test_comp(COMPL_STATUS, "d"); + test_comp(COMPL_CMD, "s"); + + return 0; +} +*/ diff -r b3618cb3bf65 -r 9a4aa2797f02 mcabber/src/compl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mcabber/src/compl.h Tue Apr 19 20:09:54 2005 +0000 @@ -0,0 +1,20 @@ +#ifndef __COMPL_H__ +#define __COMPL_H__ 1 + +#include + +#define COMPL_CMD 1 // Not implemented yet +#define COMPL_JID 2 // Not implemented yet +#define COMPL_URLJID 4 // Not implemented yet +#define COMPL_NAME 8 // Not implemented yet +#define COMPL_STATUS 16 // Not implemented yet +#define COMPL_FILENAME 32 // Not implemented yet + +void compl_add_category_command(guint, char *command); + +void new_completion(char *prefix, GSList *compl_cat); +void done_completion(void); +guint cancel_completion(void); +const char *complete(void); + +#endif /* __COMPL_H__ */