comparison mcabber/mcabber/compl.c @ 1922:4ba68ad737bc

Increase the number of available categories for completions
author Mikael Berthe <mikael@lilotux.net>
date Wed, 10 Nov 2010 14:08:24 +0100
parents 057b514b1f12
children 924f4552996c
comparison
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"));