mcabber/mcabber/compl.c
changeset 1922 4ba68ad737bc
parent 1852 057b514b1f12
child 1923 924f4552996c
equal deleted inserted replaced
1921:7d72b7d2d93a 1922:4ba68ad737bc
    34 
    34 
    35 #include "compl.h"
    35 #include "compl.h"
    36 #include "utf8.h"
    36 #include "utf8.h"
    37 #include "roster.h"
    37 #include "roster.h"
    38 #include "events.h"
    38 #include "events.h"
       
    39 #include "logprint.h"
    39 
    40 
    40 // Completion structure
    41 // Completion structure
    41 typedef struct {
    42 typedef struct {
    42   GSList *list;         // list of matches
    43   GSList *list;         // list of matches
    43   guint len_prefix;     // length of text already typed by the user
    44   guint len_prefix;     // length of text already typed by the user
    45   GSList *next;         // pointer to next completion to try
    46   GSList *next;         // pointer to next completion to try
    46 } compl;
    47 } compl;
    47 
    48 
    48 // Category structure
    49 // Category structure
    49 typedef struct {
    50 typedef struct {
    50   guint flag;
    51   guint64 flag;
    51   GSList *words;
    52   GSList *words;
    52 } category;
    53 } category;
    53 
    54 
    54 static GSList *Categories;
    55 static GSList *Categories;
    55 static compl *InputCompl;
    56 static compl *InputCompl;
    56 
    57 
    57 #ifdef MODULES_ENABLE
    58 #ifdef MODULES_ENABLE
    58 guint registered_cats = COMPL_CMD|COMPL_JID|COMPL_URLJID|COMPL_NAME| \
    59 static guint64 registered_cats;
    59                         COMPL_STATUS|COMPL_FILENAME|COMPL_ROSTER|COMPL_BUFFER| \
    60 
    60                         COMPL_GROUP|COMPL_GROUPNAME|COMPL_MULTILINE|COMPL_ROOM| \
    61 static inline void register_builtin_cat(guint c) {
    61                         COMPL_RESOURCE|COMPL_AUTH|COMPL_REQUEST|COMPL_EVENTS| \
    62   registered_cats |= 1UL << (c-1);
    62                         COMPL_EVENTSID|COMPL_PGP|COMPL_COLOR| \
    63 }
    63                         COMPL_OTR|COMPL_OTRPOLICY| \
    64 
    64                         0;
    65 void compl_init_system(void)
       
    66 {
       
    67   // Builtin completion categories:
       
    68   register_builtin_cat(COMPL_CMD);
       
    69   register_builtin_cat(COMPL_JID);
       
    70   register_builtin_cat(COMPL_URLJID);
       
    71   register_builtin_cat(COMPL_NAME);
       
    72   register_builtin_cat(COMPL_STATUS);
       
    73   register_builtin_cat(COMPL_FILENAME);
       
    74   register_builtin_cat(COMPL_ROSTER);
       
    75   register_builtin_cat(COMPL_BUFFER);
       
    76   register_builtin_cat(COMPL_GROUP);
       
    77   register_builtin_cat(COMPL_GROUPNAME);
       
    78   register_builtin_cat(COMPL_MULTILINE);
       
    79   register_builtin_cat(COMPL_ROOM);
       
    80   register_builtin_cat(COMPL_RESOURCE);
       
    81   register_builtin_cat(COMPL_AUTH);
       
    82   register_builtin_cat(COMPL_REQUEST);
       
    83   register_builtin_cat(COMPL_EVENTS);
       
    84   register_builtin_cat(COMPL_EVENTSID);
       
    85   register_builtin_cat(COMPL_PGP);
       
    86   register_builtin_cat(COMPL_COLOR);
       
    87   register_builtin_cat(COMPL_OTR);
       
    88   register_builtin_cat(COMPL_OTRPOLICY);
       
    89 }
    65 
    90 
    66 //  compl_new_category()
    91 //  compl_new_category()
    67 // Reserves id for new completion category.
    92 // Reserves id for new completion category.
    68 // Returns 0, if no more categories can be allocated.
    93 // Returns 0, if no more categories can be allocated.
    69 // Note, that user should not make any assumptions about id nature,
    94 // Note, that user should not make any assumptions about id nature,
    71 guint compl_new_category(void)
    96 guint compl_new_category(void)
    72 {
    97 {
    73   guint i = 0;
    98   guint i = 0;
    74   while ((registered_cats >> i) & 1)
    99   while ((registered_cats >> i) & 1)
    75     i++;
   100     i++;
    76   if (i >= 8 * sizeof (guint))
   101   if (i >= 8 * sizeof (registered_cats))
    77     return 0;
   102     return 0;
    78   else {
   103   else {
    79     guint id = 1 << i;
   104     guint64 id = 1 << i;
    80     registered_cats |= id;
   105     registered_cats |= id;
    81     return id;
   106     return i+1;
    82   }
   107   }
    83 }
   108 }
    84 
   109 
    85 //  compl_del_category(id)
   110 //  compl_del_category(id)
    86 // Frees reserved id for category.
   111 // Frees reserved id for category.
    87 // Note, that for now it not validates its input, so, be careful
   112 // Note, that for now it not validates its input, so, be careful
    88 // and specify exactly what you get from compl_new_category.
   113 // and specify exactly what you get from compl_new_category.
    89 void compl_del_category(guint id)
   114 void compl_del_category(guint id)
    90 {
   115 {
    91   registered_cats &= ~id;
   116   if (!id) {
       
   117     scr_log_print(LPRINT_LOGNORM, "Error: compl_del_category() - "
       
   118                   "Invalid category.");
       
   119     return;
       
   120   }
       
   121   id--;
       
   122   registered_cats &= ~(1<<id);
    92 }
   123 }
    93 #endif
   124 #endif
    94 
   125 
    95 //  new_completion(prefix, compl_cat, suffix)
   126 //  new_completion(prefix, compl_cat, suffix)
    96 // . prefix    = beginning of the word, typed by the user
   127 // . prefix    = beginning of the word, typed by the user
   184 
   215 
   185 //  compl_add_category_word(categ, command)
   216 //  compl_add_category_word(categ, command)
   186 // Adds a keyword as a possible completion in category categ.
   217 // Adds a keyword as a possible completion in category categ.
   187 void compl_add_category_word(guint categ, const gchar *word)
   218 void compl_add_category_word(guint categ, const gchar *word)
   188 {
   219 {
       
   220   guint64 catv;
   189   GSList *sl_cat;
   221   GSList *sl_cat;
   190   category *cat;
   222   category *cat;
   191   char *nword;
   223   char *nword;
       
   224 
       
   225   if (!categ) {
       
   226     scr_log_print(LPRINT_LOGNORM, "Error: compl_add_category_word() - "
       
   227                   "Invalid category.");
       
   228     return;
       
   229   }
       
   230 
       
   231   categ--;
       
   232   catv = 1UL << categ;
       
   233 
   192   // Look for category
   234   // Look for category
   193   for (sl_cat=Categories; sl_cat; sl_cat = g_slist_next(sl_cat)) {
   235   for (sl_cat=Categories; sl_cat; sl_cat = g_slist_next(sl_cat)) {
   194     if (categ == ((category*)sl_cat->data)->flag)
   236     if (catv == ((category*)sl_cat->data)->flag)
   195       break;
   237       break;
   196   }
   238   }
   197   if (!sl_cat) {   // Category not found, let's create it
   239   if (!sl_cat) {   // Category not found, let's create it
   198     cat = g_new0(category, 1);
   240     cat = g_new0(category, 1);
   199     cat->flag = categ;
   241     cat->flag = catv;
   200     Categories = g_slist_append(Categories, cat);
   242     Categories = g_slist_append(Categories, cat);
   201   } else
   243   } else
   202     cat = (category*)sl_cat->data;
   244     cat = (category*)sl_cat->data;
   203 
   245 
   204   // If word is not space-terminated, we add one trailing space
   246   // If word is not space-terminated, we add one trailing space
   220 
   262 
   221 //  compl_del_category_word(categ, command)
   263 //  compl_del_category_word(categ, command)
   222 // Removes a keyword from category categ in completion list.
   264 // Removes a keyword from category categ in completion list.
   223 void compl_del_category_word(guint categ, const gchar *word)
   265 void compl_del_category_word(guint categ, const gchar *word)
   224 {
   266 {
       
   267   guint64 catv;
   225   GSList *sl_cat, *sl_elt;
   268   GSList *sl_cat, *sl_elt;
   226   category *cat;
   269   category *cat;
   227   char *nword;
   270   char *nword;
       
   271 
       
   272   if (!categ) {
       
   273     scr_log_print(LPRINT_LOGNORM, "Error: compl_del_category_word() - "
       
   274                   "Invalid category.");
       
   275     return;
       
   276   }
       
   277 
       
   278   categ--;
       
   279   catv = 1UL << categ;
       
   280 
   228   // Look for category
   281   // Look for category
   229   for (sl_cat=Categories; sl_cat; sl_cat = g_slist_next(sl_cat)) {
   282   for (sl_cat=Categories; sl_cat; sl_cat = g_slist_next(sl_cat)) {
   230     if (categ == ((category*)sl_cat->data)->flag)
   283     if (catv == ((category*)sl_cat->data)->flag)
   231       break;
   284       break;
   232   }
   285   }
   233   if (!sl_cat) return;   // Category not found, finished!
   286   if (!sl_cat) return;   // Category not found, finished!
   234 
   287 
   235   cat = (category*)sl_cat->data;
   288   cat = (category*)sl_cat->data;
   254     sl_elt = g_slist_next(sl_elt);
   307     sl_elt = g_slist_next(sl_elt);
   255   }
   308   }
   256 }
   309 }
   257 
   310 
   258 //  compl_get_category_list()
   311 //  compl_get_category_list()
   259 // Returns a slist of all words in the categories specified by the given flags
   312 // Returns a slist of all words in the specified categorie.
   260 // Iff this function sets *dynlist to TRUE, then the caller must free the
   313 // Iff this function sets *dynlist to TRUE, then the caller must free the
   261 // whole list after use.
   314 // whole list after use.
   262 GSList *compl_get_category_list(guint cat_flags, guint *dynlist)
   315 GSList *compl_get_category_list(guint categ, guint *dynlist)
   263 {
   316 {
       
   317   guint64 cat_flags;
   264   GSList *sl_cat;
   318   GSList *sl_cat;
   265 
   319 
       
   320   if (!categ) {
       
   321     scr_log_print(LPRINT_LOGNORM, "Error: compl_get_category_list() - "
       
   322                   "Invalid category.");
       
   323     return NULL;
       
   324   }
       
   325 
   266   *dynlist = FALSE;
   326   *dynlist = FALSE;
   267 
   327   cat_flags = 1UL << (categ - 1);
   268   // Look for category
   328 
   269   // XXX Actually that's not that simple... cat_flags can be a combination
   329   // Look for the category
   270   // of several flags!
       
   271   for (sl_cat=Categories; sl_cat; sl_cat = g_slist_next(sl_cat)) {
   330   for (sl_cat=Categories; sl_cat; sl_cat = g_slist_next(sl_cat)) {
   272     if (cat_flags == ((category*)sl_cat->data)->flag)
   331     if (cat_flags == ((category*)sl_cat->data)->flag)
   273       break;
   332       break;
   274   }
   333   }
   275   if (sl_cat)       // Category was found, easy...
   334   if (sl_cat)       // Category was found, easy...
   276     return ((category*)sl_cat->data)->words;
   335     return ((category*)sl_cat->data)->words;
   277 
   336 
   278   // Handle dynamic SLists
   337   // Handle dynamic SLists
   279   *dynlist = TRUE;
   338   *dynlist = TRUE;
   280   if (cat_flags == COMPL_GROUPNAME) {
   339   if (categ == COMPL_GROUPNAME) {
   281     return compl_list(ROSTER_TYPE_GROUP);
   340     return compl_list(ROSTER_TYPE_GROUP);
   282   }
   341   }
   283   if (cat_flags == COMPL_JID) {
   342   if (categ == COMPL_JID) {
   284     return compl_list(ROSTER_TYPE_USER);
   343     return compl_list(ROSTER_TYPE_USER);
   285   }
   344   }
   286   if (cat_flags == COMPL_RESOURCE) {
   345   if (categ == COMPL_RESOURCE) {
   287     return buddy_getresources_locale(NULL);
   346     return buddy_getresources_locale(NULL);
   288   }
   347   }
   289   if (cat_flags == COMPL_EVENTSID) {
   348   if (categ == COMPL_EVENTSID) {
   290     GSList *compl = evs_geteventslist();
   349     GSList *compl = evs_geteventslist();
   291     GSList *cel;
   350     GSList *cel;
   292     for (cel = compl; cel; cel = cel->next)
   351     for (cel = compl; cel; cel = cel->next)
   293       cel->data = g_strdup(cel->data);
   352       cel->data = g_strdup(cel->data);
   294     compl = g_slist_append(compl, g_strdup("list"));
   353     compl = g_slist_append(compl, g_strdup("list"));