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")); |