1 /*
2 * cmd_ac.c
3 * vim: expandtab:ts=4:sts=4:sw=4
4 *
5 * Copyright (C) 2012 - 2019 James Booth <boothj5@gmail.com>
6 * Copyright (C) 2019 Michael Vetter <jubalh@iodoru.org>
7 *
8 * This file is part of Profanity.
9 *
10 * Profanity is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * Profanity is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Profanity. If not, see <https://www.gnu.org/licenses/>.
22 *
23 * In addition, as a special exception, the copyright holders give permission to
24 * link the code of portions of this program with the OpenSSL library under
25 * certain conditions as described in each individual source file, and
26 * distribute linked combinations including the two.
27 *
28 * You must obey the GNU General Public License in all respects for all of the
29 * code used other than OpenSSL. If you modify file(s) with this exception, you
30 * may extend this exception to your version of the file(s), but you are not
31 * obligated to do so. If you do not wish to do so, delete this exception
32 * statement from your version. If you delete this exception statement from all
33 * source files in the program, then also delete it here.
34 *
35 */
36
37 #include "config.h"
38
39 #include <stdlib.h>
40 #include <string.h>
41 #include <assert.h>
42 #include <libgen.h>
43 #include <dirent.h>
44
45 #include "common.h"
46 #include "config/preferences.h"
47 #include "config/scripts.h"
48 #include "command/cmd_ac.h"
49 #include "command/cmd_funcs.h"
50 #include "tools/parser.h"
51 #include "plugins/plugins.h"
52 #include "ui/win_types.h"
53 #include "ui/window_list.h"
54 #include "xmpp/muc.h"
55 #include "xmpp/xmpp.h"
56 #include "xmpp/roster_list.h"
57 #include "ui/buffer.h"
58
59 #ifdef HAVE_LIBGPGME
60 #include "pgp/gpg.h"
61 #endif
62
63 #ifdef HAVE_OMEMO
64 #include "omemo/omemo.h"
65 #endif
66
67 static char* _sub_autocomplete(ProfWin* window, const char* const input, gboolean previous);
68 static char* _notify_autocomplete(ProfWin* window, const char* const input, gboolean previous);
69 static char* _theme_autocomplete(ProfWin* window, const char* const input, gboolean previous);
70 static char* _autoaway_autocomplete(ProfWin* window, const char* const input, gboolean previous);
71 static char* _autoconnect_autocomplete(ProfWin* window, const char* const input, gboolean previous);
72 static char* _account_autocomplete(ProfWin* window, const char* const input, gboolean previous);
73 static char* _who_autocomplete(ProfWin* window, const char* const input, gboolean previous);
74 static char* _roster_autocomplete(ProfWin* window, const char* const input, gboolean previous);
75 static char* _bookmark_autocomplete(ProfWin* window, const char* const input, gboolean previous);
76 #ifdef HAVE_LIBOTR
77 static char* _otr_autocomplete(ProfWin* window, const char* const input, gboolean previous);
78 #endif
79 #ifdef HAVE_LIBGPGME
80 static char* _pgp_autocomplete(ProfWin* window, const char* const input, gboolean previous);
81 static char* _ox_autocomplete(ProfWin* window, const char* const input, gboolean previous);
82 #endif
83 #ifdef HAVE_OMEMO
84 static char* _omemo_autocomplete(ProfWin* window, const char* const input, gboolean previous);
85 #endif
86 static char* _connect_autocomplete(ProfWin* window, const char* const input, gboolean previous);
87 static char* _alias_autocomplete(ProfWin* window, const char* const input, gboolean previous);
88 static char* _join_autocomplete(ProfWin* window, const char* const input, gboolean previous);
89 static char* _log_autocomplete(ProfWin* window, const char* const input, gboolean previous);
90 static char* _form_autocomplete(ProfWin* window, const char* const input, gboolean previous);
91 static char* _form_field_autocomplete(ProfWin* window, const char* const input, gboolean previous);
92 static char* _occupants_autocomplete(ProfWin* window, const char* const input, gboolean previous);
93 static char* _kick_autocomplete(ProfWin* window, const char* const input, gboolean previous);
94 static char* _ban_autocomplete(ProfWin* window, const char* const input, gboolean previous);
95 static char* _affiliation_autocomplete(ProfWin* window, const char* const input, gboolean previous);
96 static char* _role_autocomplete(ProfWin* window, const char* const input, gboolean previous);
97 static char* _resource_autocomplete(ProfWin* window, const char* const input, gboolean previous);
98 static char* _wintitle_autocomplete(ProfWin* window, const char* const input, gboolean previous);
99 static char* _inpblock_autocomplete(ProfWin* window, const char* const input, gboolean previous);
100 static char* _time_autocomplete(ProfWin* window, const char* const input, gboolean previous);
101 static char* _receipts_autocomplete(ProfWin* window, const char* const input, gboolean previous);
102 static char* _help_autocomplete(ProfWin* window, const char* const input, gboolean previous);
103 static char* _wins_autocomplete(ProfWin* window, const char* const input, gboolean previous);
104 static char* _tls_autocomplete(ProfWin* window, const char* const input, gboolean previous);
105 static char* _titlebar_autocomplete(ProfWin* window, const char* const input, gboolean previous);
106 static char* _script_autocomplete(ProfWin* window, const char* const input, gboolean previous);
107 static char* _subject_autocomplete(ProfWin* window, const char* const input, gboolean previous);
108 static char* _console_autocomplete(ProfWin* window, const char* const input, gboolean previous);
109 static char* _win_autocomplete(ProfWin* window, const char* const input, gboolean previous);
110 static char* _close_autocomplete(ProfWin* window, const char* const input, gboolean previous);
111 static char* _plugins_autocomplete(ProfWin* window, const char* const input, gboolean previous);
112 static char* _sendfile_autocomplete(ProfWin* window, const char* const input, gboolean previous);
113 static char* _blocked_autocomplete(ProfWin* window, const char* const input, gboolean previous);
114 static char* _tray_autocomplete(ProfWin* window, const char* const input, gboolean previous);
115 static char* _presence_autocomplete(ProfWin* window, const char* const input, gboolean previous);
116 static char* _rooms_autocomplete(ProfWin* window, const char* const input, gboolean previous);
117 static char* _statusbar_autocomplete(ProfWin* window, const char* const input, gboolean previous);
118 static char* _clear_autocomplete(ProfWin* window, const char* const input, gboolean previous);
119 static char* _invite_autocomplete(ProfWin* window, const char* const input, gboolean previous);
120 static char* _status_autocomplete(ProfWin* window, const char* const input, gboolean previous);
121 static char* _logging_autocomplete(ProfWin* window, const char* const input, gboolean previous);
122 static char* _color_autocomplete(ProfWin* window, const char* const input, gboolean previous);
123 static char* _avatar_autocomplete(ProfWin* window, const char* const input, gboolean previous);
124 static char* _correction_autocomplete(ProfWin* window, const char* const input, gboolean previous);
125 static char* _correct_autocomplete(ProfWin* window, const char* const input, gboolean previous);
126 static char* _software_autocomplete(ProfWin* window, const char* const input, gboolean previous);
127 static char* _url_autocomplete(ProfWin* window, const char* const input, gboolean previous);
128 static char* _executable_autocomplete(ProfWin* window, const char* const input, gboolean previous);
129 static char* _lastactivity_autocomplete(ProfWin* window, const char* const input, gboolean previous);
130 static char* _intype_autocomplete(ProfWin* window, const char* const input, gboolean previous);
131
132 static char* _script_autocomplete_func(const char* const prefix, gboolean previous, void* context);
133
134 static char* _cmd_ac_complete_params(ProfWin* window, const char* const input, gboolean previous);
135
136 static Autocomplete commands_ac;
137 static Autocomplete who_room_ac;
138 static Autocomplete who_roster_ac;
139 static Autocomplete help_ac;
140 static Autocomplete help_commands_ac;
141 static Autocomplete notify_ac;
142 static Autocomplete notify_chat_ac;
143 static Autocomplete notify_room_ac;
144 static Autocomplete notify_typing_ac;
145 static Autocomplete notify_mention_ac;
146 static Autocomplete notify_trigger_ac;
147 static Autocomplete prefs_ac;
148 static Autocomplete sub_ac;
149 static Autocomplete log_ac;
150 static Autocomplete autoaway_ac;
151 static Autocomplete autoaway_mode_ac;
152 static Autocomplete autoaway_presence_ac;
153 static Autocomplete autoconnect_ac;
154 static Autocomplete wintitle_ac;
155 static Autocomplete theme_ac;
156 static Autocomplete theme_load_ac;
157 static Autocomplete account_ac;
158 static Autocomplete account_set_ac;
159 static Autocomplete account_clear_ac;
160 static Autocomplete account_default_ac;
161 static Autocomplete account_status_ac;
162 static Autocomplete disco_ac;
163 static Autocomplete wins_ac;
164 static Autocomplete roster_ac;
165 static Autocomplete roster_show_ac;
166 static Autocomplete roster_by_ac;
167 static Autocomplete roster_count_ac;
168 static Autocomplete roster_order_ac;
169 static Autocomplete roster_header_ac;
170 static Autocomplete roster_contact_ac;
171 static Autocomplete roster_resource_ac;
172 static Autocomplete roster_presence_ac;
173 static Autocomplete roster_char_ac;
174 static Autocomplete roster_remove_all_ac;
175 static Autocomplete roster_room_ac;
176 static Autocomplete roster_room_show_ac;
177 static Autocomplete roster_room_use_ac;
178 static Autocomplete roster_room_position_ac;
179 static Autocomplete roster_room_by_ac;
180 static Autocomplete roster_room_order_ac;
181 static Autocomplete roster_unread_ac;
182 static Autocomplete roster_private_ac;
183 static Autocomplete group_ac;
184 static Autocomplete bookmark_ac;
185 static Autocomplete bookmark_property_ac;
186 static Autocomplete bookmark_ignore_ac;
187 #ifdef HAVE_LIBOTR
188 static Autocomplete otr_ac;
189 static Autocomplete otr_log_ac;
190 static Autocomplete otr_policy_ac;
191 static Autocomplete otr_sendfile_ac;
192 #endif
193 #ifdef HAVE_OMEMO
194 static Autocomplete omemo_ac;
195 static Autocomplete omemo_log_ac;
196 static Autocomplete omemo_policy_ac;
197 static Autocomplete omemo_trustmode_ac;
198 #endif
199 static Autocomplete connect_property_ac;
200 static Autocomplete tls_property_ac;
201 static Autocomplete auth_property_ac;
202 static Autocomplete alias_ac;
203 static Autocomplete aliases_ac;
204 static Autocomplete join_property_ac;
205 static Autocomplete room_ac;
206 static Autocomplete rooms_all_ac;
207 static Autocomplete rooms_list_ac;
208 static Autocomplete rooms_cache_ac;
209 static Autocomplete affiliation_ac;
210 static Autocomplete role_ac;
211 static Autocomplete affiliation_cmd_ac;
212 static Autocomplete role_cmd_ac;
213 static Autocomplete subject_ac;
214 static Autocomplete form_ac;
215 static Autocomplete form_field_multi_ac;
216 static Autocomplete occupants_ac;
217 static Autocomplete occupants_default_ac;
218 static Autocomplete occupants_show_ac;
219 static Autocomplete occupants_header_ac;
220 static Autocomplete occupants_header_char_ac;
221 static Autocomplete occupants_char_ac;
222 static Autocomplete time_ac;
223 static Autocomplete time_format_ac;
224 static Autocomplete resource_ac;
225 static Autocomplete inpblock_ac;
226 static Autocomplete receipts_ac;
227 #ifdef HAVE_LIBGPGME
228 static Autocomplete pgp_ac;
229 static Autocomplete pgp_log_ac;
230 static Autocomplete pgp_sendfile_ac;
231 static Autocomplete ox_ac;
232 static Autocomplete ox_log_ac;
233 static Autocomplete ox_sendfile_ac;
234 #endif
235 static Autocomplete tls_ac;
236 static Autocomplete titlebar_ac;
237 static Autocomplete titlebar_show_ac;
238 static Autocomplete tls_certpath_ac;
239 static Autocomplete script_ac;
240 static Autocomplete script_show_ac;
241 static Autocomplete console_ac;
242 static Autocomplete console_msg_ac;
243 static Autocomplete autoping_ac;
244 static Autocomplete plugins_ac;
245 static Autocomplete plugins_sourcepath_ac;
246 static Autocomplete plugins_load_ac;
247 static Autocomplete plugins_unload_ac;
248 static Autocomplete plugins_reload_ac;
249 static Autocomplete filepath_ac;
250 static Autocomplete blocked_ac;
251 static Autocomplete tray_ac;
252 static Autocomplete presence_ac;
253 static Autocomplete presence_setting_ac;
254 static Autocomplete winpos_ac;
255 static Autocomplete statusbar_ac;
256 static Autocomplete statusbar_self_ac;
257 static Autocomplete statusbar_chat_ac;
258 static Autocomplete statusbar_room_ac;
259 static Autocomplete statusbar_show_ac;
260 static Autocomplete clear_ac;
261 static Autocomplete invite_ac;
262 static Autocomplete status_ac;
263 static Autocomplete status_state_ac;
264 static Autocomplete logging_ac;
265 static Autocomplete logging_group_ac;
266 static Autocomplete color_ac;
267 static Autocomplete correction_ac;
268 static Autocomplete avatar_ac;
269 static Autocomplete url_ac;
270 static Autocomplete executable_ac;
271 static Autocomplete intype_ac;
272
273 /*!
274 * \brief Initialization of auto completion for commands.
275 *
276 * This function implements the auto completion for profanity's commands.
277 *
278 */
279
280 void
cmd_ac_init(void)281 cmd_ac_init(void)
282 {
283 commands_ac = autocomplete_new();
284 aliases_ac = autocomplete_new();
285
286 help_ac = autocomplete_new();
287 autocomplete_add(help_ac, "commands");
288 autocomplete_add(help_ac, "navigation");
289 autocomplete_add(help_ac, "search_all");
290 autocomplete_add(help_ac, "search_any");
291
292 help_commands_ac = autocomplete_new();
293 autocomplete_add(help_commands_ac, "chat");
294 autocomplete_add(help_commands_ac, "groupchat");
295 autocomplete_add(help_commands_ac, "roster");
296 autocomplete_add(help_commands_ac, "presence");
297 autocomplete_add(help_commands_ac, "discovery");
298 autocomplete_add(help_commands_ac, "connection");
299 autocomplete_add(help_commands_ac, "ui");
300 autocomplete_add(help_commands_ac, "plugins");
301
302 prefs_ac = autocomplete_new();
303 autocomplete_add(prefs_ac, "ui");
304 autocomplete_add(prefs_ac, "desktop");
305 autocomplete_add(prefs_ac, "chat");
306 autocomplete_add(prefs_ac, "log");
307 autocomplete_add(prefs_ac, "conn");
308 autocomplete_add(prefs_ac, "presence");
309 #ifdef HAVE_LIBOTR
310 autocomplete_add(prefs_ac, "otr");
311 #endif
312 #ifdef HAVE_LIBGPGME
313 autocomplete_add(prefs_ac, "pgp");
314 #endif
315 #ifdef HAVE_OMEMO
316 autocomplete_add(prefs_ac, "omemo");
317 #endif
318
319 notify_ac = autocomplete_new();
320 autocomplete_add(notify_ac, "chat");
321 autocomplete_add(notify_ac, "room");
322 autocomplete_add(notify_ac, "typing");
323 autocomplete_add(notify_ac, "remind");
324 autocomplete_add(notify_ac, "invite");
325 autocomplete_add(notify_ac, "sub");
326 autocomplete_add(notify_ac, "on");
327 autocomplete_add(notify_ac, "off");
328 autocomplete_add(notify_ac, "mention");
329 autocomplete_add(notify_ac, "trigger");
330 autocomplete_add(notify_ac, "reset");
331
332 notify_chat_ac = autocomplete_new();
333 autocomplete_add(notify_chat_ac, "on");
334 autocomplete_add(notify_chat_ac, "off");
335 autocomplete_add(notify_chat_ac, "current");
336 autocomplete_add(notify_chat_ac, "text");
337
338 notify_room_ac = autocomplete_new();
339 autocomplete_add(notify_room_ac, "on");
340 autocomplete_add(notify_room_ac, "off");
341 autocomplete_add(notify_room_ac, "mention");
342 autocomplete_add(notify_room_ac, "current");
343 autocomplete_add(notify_room_ac, "text");
344 autocomplete_add(notify_room_ac, "trigger");
345
346 notify_typing_ac = autocomplete_new();
347 autocomplete_add(notify_typing_ac, "on");
348 autocomplete_add(notify_typing_ac, "off");
349 autocomplete_add(notify_typing_ac, "current");
350
351 notify_mention_ac = autocomplete_new();
352 autocomplete_add(notify_mention_ac, "on");
353 autocomplete_add(notify_mention_ac, "off");
354 autocomplete_add(notify_mention_ac, "case_sensitive");
355 autocomplete_add(notify_mention_ac, "case_insensitive");
356 autocomplete_add(notify_mention_ac, "word_whole");
357 autocomplete_add(notify_mention_ac, "word_part");
358
359 notify_trigger_ac = autocomplete_new();
360 autocomplete_add(notify_trigger_ac, "add");
361 autocomplete_add(notify_trigger_ac, "remove");
362 autocomplete_add(notify_trigger_ac, "list");
363 autocomplete_add(notify_trigger_ac, "on");
364 autocomplete_add(notify_trigger_ac, "off");
365
366 sub_ac = autocomplete_new();
367 autocomplete_add(sub_ac, "request");
368 autocomplete_add(sub_ac, "allow");
369 autocomplete_add(sub_ac, "deny");
370 autocomplete_add(sub_ac, "show");
371 autocomplete_add(sub_ac, "sent");
372 autocomplete_add(sub_ac, "received");
373
374 wintitle_ac = autocomplete_new();
375 autocomplete_add(wintitle_ac, "show");
376 autocomplete_add(wintitle_ac, "goodbye");
377
378 log_ac = autocomplete_new();
379 autocomplete_add(log_ac, "maxsize");
380 autocomplete_add(log_ac, "rotate");
381 autocomplete_add(log_ac, "shared");
382 autocomplete_add(log_ac, "where");
383
384 autoaway_ac = autocomplete_new();
385 autocomplete_add(autoaway_ac, "mode");
386 autocomplete_add(autoaway_ac, "time");
387 autocomplete_add(autoaway_ac, "message");
388 autocomplete_add(autoaway_ac, "check");
389
390 autoaway_mode_ac = autocomplete_new();
391 autocomplete_add(autoaway_mode_ac, "away");
392 autocomplete_add(autoaway_mode_ac, "idle");
393 autocomplete_add(autoaway_mode_ac, "off");
394
395 autoaway_presence_ac = autocomplete_new();
396 autocomplete_add(autoaway_presence_ac, "away");
397 autocomplete_add(autoaway_presence_ac, "xa");
398
399 autoconnect_ac = autocomplete_new();
400 autocomplete_add(autoconnect_ac, "set");
401 autocomplete_add(autoconnect_ac, "off");
402
403 theme_ac = autocomplete_new();
404 autocomplete_add(theme_ac, "load");
405 autocomplete_add(theme_ac, "full-load");
406 autocomplete_add(theme_ac, "list");
407 autocomplete_add(theme_ac, "colours");
408 autocomplete_add(theme_ac, "properties");
409
410 disco_ac = autocomplete_new();
411 autocomplete_add(disco_ac, "info");
412 autocomplete_add(disco_ac, "items");
413
414 account_ac = autocomplete_new();
415 autocomplete_add(account_ac, "list");
416 autocomplete_add(account_ac, "show");
417 autocomplete_add(account_ac, "add");
418 autocomplete_add(account_ac, "remove");
419 autocomplete_add(account_ac, "enable");
420 autocomplete_add(account_ac, "disable");
421 autocomplete_add(account_ac, "default");
422 autocomplete_add(account_ac, "rename");
423 autocomplete_add(account_ac, "set");
424 autocomplete_add(account_ac, "clear");
425
426 account_set_ac = autocomplete_new();
427 autocomplete_add(account_set_ac, "jid");
428 autocomplete_add(account_set_ac, "server");
429 autocomplete_add(account_set_ac, "port");
430 autocomplete_add(account_set_ac, "status");
431 autocomplete_add(account_set_ac, "online");
432 autocomplete_add(account_set_ac, "chat");
433 autocomplete_add(account_set_ac, "away");
434 autocomplete_add(account_set_ac, "xa");
435 autocomplete_add(account_set_ac, "dnd");
436 autocomplete_add(account_set_ac, "resource");
437 autocomplete_add(account_set_ac, "password");
438 autocomplete_add(account_set_ac, "eval_password");
439 autocomplete_add(account_set_ac, "muc");
440 autocomplete_add(account_set_ac, "nick");
441 autocomplete_add(account_set_ac, "otr");
442 autocomplete_add(account_set_ac, "pgpkeyid");
443 autocomplete_add(account_set_ac, "startscript");
444 autocomplete_add(account_set_ac, "tls");
445 autocomplete_add(account_set_ac, "auth");
446 autocomplete_add(account_set_ac, "theme");
447
448 account_clear_ac = autocomplete_new();
449 autocomplete_add(account_clear_ac, "password");
450 autocomplete_add(account_clear_ac, "eval_password");
451 autocomplete_add(account_clear_ac, "server");
452 autocomplete_add(account_clear_ac, "port");
453 autocomplete_add(account_clear_ac, "otr");
454 autocomplete_add(account_clear_ac, "pgpkeyid");
455 autocomplete_add(account_clear_ac, "startscript");
456 autocomplete_add(account_clear_ac, "theme");
457 autocomplete_add(account_clear_ac, "muc");
458 autocomplete_add(account_clear_ac, "resource");
459
460 account_default_ac = autocomplete_new();
461 autocomplete_add(account_default_ac, "set");
462 autocomplete_add(account_default_ac, "off");
463
464 account_status_ac = autocomplete_new();
465 autocomplete_add(account_status_ac, "online");
466 autocomplete_add(account_status_ac, "chat");
467 autocomplete_add(account_status_ac, "away");
468 autocomplete_add(account_status_ac, "xa");
469 autocomplete_add(account_status_ac, "dnd");
470 autocomplete_add(account_status_ac, "last");
471
472 wins_ac = autocomplete_new();
473 autocomplete_add(wins_ac, "unread");
474 autocomplete_add(wins_ac, "attention");
475 autocomplete_add(wins_ac, "prune");
476 autocomplete_add(wins_ac, "swap");
477
478 roster_ac = autocomplete_new();
479 autocomplete_add(roster_ac, "add");
480 autocomplete_add(roster_ac, "online");
481 autocomplete_add(roster_ac, "nick");
482 autocomplete_add(roster_ac, "clearnick");
483 autocomplete_add(roster_ac, "remove");
484 autocomplete_add(roster_ac, "remove_all");
485 autocomplete_add(roster_ac, "show");
486 autocomplete_add(roster_ac, "hide");
487 autocomplete_add(roster_ac, "by");
488 autocomplete_add(roster_ac, "count");
489 autocomplete_add(roster_ac, "color");
490 autocomplete_add(roster_ac, "order");
491 autocomplete_add(roster_ac, "unread");
492 autocomplete_add(roster_ac, "room");
493 autocomplete_add(roster_ac, "size");
494 autocomplete_add(roster_ac, "wrap");
495 autocomplete_add(roster_ac, "header");
496 autocomplete_add(roster_ac, "contact");
497 autocomplete_add(roster_ac, "resource");
498 autocomplete_add(roster_ac, "presence");
499 autocomplete_add(roster_ac, "private");
500 autocomplete_add(roster_ac, "group");
501
502 roster_private_ac = autocomplete_new();
503 autocomplete_add(roster_private_ac, "room");
504 autocomplete_add(roster_private_ac, "group");
505 autocomplete_add(roster_private_ac, "off");
506 autocomplete_add(roster_private_ac, "char");
507
508 roster_header_ac = autocomplete_new();
509 autocomplete_add(roster_header_ac, "char");
510
511 roster_contact_ac = autocomplete_new();
512 autocomplete_add(roster_contact_ac, "char");
513 autocomplete_add(roster_contact_ac, "indent");
514
515 roster_resource_ac = autocomplete_new();
516 autocomplete_add(roster_resource_ac, "char");
517 autocomplete_add(roster_resource_ac, "indent");
518 autocomplete_add(roster_resource_ac, "join");
519
520 roster_presence_ac = autocomplete_new();
521 autocomplete_add(roster_presence_ac, "indent");
522
523 roster_char_ac = autocomplete_new();
524 autocomplete_add(roster_char_ac, "none");
525
526 roster_show_ac = autocomplete_new();
527 autocomplete_add(roster_show_ac, "offline");
528 autocomplete_add(roster_show_ac, "resource");
529 autocomplete_add(roster_show_ac, "presence");
530 autocomplete_add(roster_show_ac, "status");
531 autocomplete_add(roster_show_ac, "empty");
532 autocomplete_add(roster_show_ac, "priority");
533 autocomplete_add(roster_show_ac, "contacts");
534 autocomplete_add(roster_show_ac, "unsubscribed");
535 autocomplete_add(roster_show_ac, "rooms");
536
537 roster_by_ac = autocomplete_new();
538 autocomplete_add(roster_by_ac, "group");
539 autocomplete_add(roster_by_ac, "presence");
540 autocomplete_add(roster_by_ac, "none");
541
542 roster_count_ac = autocomplete_new();
543 autocomplete_add(roster_count_ac, "unread");
544 autocomplete_add(roster_count_ac, "items");
545 autocomplete_add(roster_count_ac, "off");
546 autocomplete_add(roster_count_ac, "zero");
547
548 roster_order_ac = autocomplete_new();
549 autocomplete_add(roster_order_ac, "name");
550 autocomplete_add(roster_order_ac, "presence");
551
552 roster_unread_ac = autocomplete_new();
553 autocomplete_add(roster_unread_ac, "before");
554 autocomplete_add(roster_unread_ac, "after");
555 autocomplete_add(roster_unread_ac, "off");
556
557 roster_room_ac = autocomplete_new();
558 autocomplete_add(roster_room_ac, "char");
559 autocomplete_add(roster_room_ac, "position");
560 autocomplete_add(roster_room_ac, "by");
561 autocomplete_add(roster_room_ac, "order");
562 autocomplete_add(roster_room_ac, "unread");
563 autocomplete_add(roster_room_ac, "private");
564 autocomplete_add(roster_room_ac, "show");
565 autocomplete_add(roster_room_ac, "hide");
566 autocomplete_add(roster_room_ac, "use");
567
568 roster_room_show_ac = autocomplete_new();
569 autocomplete_add(roster_room_show_ac, "server");
570
571 roster_room_by_ac = autocomplete_new();
572 autocomplete_add(roster_room_by_ac, "service");
573 autocomplete_add(roster_room_by_ac, "none");
574
575 roster_room_use_ac = autocomplete_new();
576 autocomplete_add(roster_room_use_ac, "jid");
577 autocomplete_add(roster_room_use_ac, "name");
578
579 roster_room_order_ac = autocomplete_new();
580 autocomplete_add(roster_room_order_ac, "name");
581 autocomplete_add(roster_room_order_ac, "unread");
582
583 roster_room_position_ac = autocomplete_new();
584 autocomplete_add(roster_room_position_ac, "first");
585 autocomplete_add(roster_room_position_ac, "last");
586
587 roster_remove_all_ac = autocomplete_new();
588 autocomplete_add(roster_remove_all_ac, "contacts");
589
590 group_ac = autocomplete_new();
591 autocomplete_add(group_ac, "show");
592 autocomplete_add(group_ac, "add");
593 autocomplete_add(group_ac, "remove");
594
595 theme_load_ac = NULL;
596 plugins_load_ac = NULL;
597 plugins_unload_ac = NULL;
598 plugins_reload_ac = NULL;
599
600 who_roster_ac = autocomplete_new();
601 autocomplete_add(who_roster_ac, "chat");
602 autocomplete_add(who_roster_ac, "online");
603 autocomplete_add(who_roster_ac, "away");
604 autocomplete_add(who_roster_ac, "xa");
605 autocomplete_add(who_roster_ac, "dnd");
606 autocomplete_add(who_roster_ac, "offline");
607 autocomplete_add(who_roster_ac, "available");
608 autocomplete_add(who_roster_ac, "unavailable");
609 autocomplete_add(who_roster_ac, "any");
610
611 who_room_ac = autocomplete_new();
612 autocomplete_add(who_room_ac, "chat");
613 autocomplete_add(who_room_ac, "online");
614 autocomplete_add(who_room_ac, "away");
615 autocomplete_add(who_room_ac, "xa");
616 autocomplete_add(who_room_ac, "dnd");
617 autocomplete_add(who_room_ac, "available");
618 autocomplete_add(who_room_ac, "unavailable");
619 autocomplete_add(who_room_ac, "moderator");
620 autocomplete_add(who_room_ac, "participant");
621 autocomplete_add(who_room_ac, "visitor");
622 autocomplete_add(who_room_ac, "owner");
623 autocomplete_add(who_room_ac, "admin");
624 autocomplete_add(who_room_ac, "member");
625
626 bookmark_ac = autocomplete_new();
627 autocomplete_add(bookmark_ac, "list");
628 autocomplete_add(bookmark_ac, "add");
629 autocomplete_add(bookmark_ac, "update");
630 autocomplete_add(bookmark_ac, "remove");
631 autocomplete_add(bookmark_ac, "join");
632 autocomplete_add(bookmark_ac, "invites");
633 autocomplete_add(bookmark_ac, "ignore");
634
635 bookmark_property_ac = autocomplete_new();
636 autocomplete_add(bookmark_property_ac, "nick");
637 autocomplete_add(bookmark_property_ac, "password");
638 autocomplete_add(bookmark_property_ac, "autojoin");
639 autocomplete_add(bookmark_property_ac, "name");
640
641 bookmark_ignore_ac = autocomplete_new();
642 autocomplete_add(bookmark_ignore_ac, "add");
643 autocomplete_add(bookmark_ignore_ac, "remove");
644
645 #ifdef HAVE_LIBOTR
646 otr_ac = autocomplete_new();
647 autocomplete_add(otr_ac, "gen");
648 autocomplete_add(otr_ac, "start");
649 autocomplete_add(otr_ac, "end");
650 autocomplete_add(otr_ac, "myfp");
651 autocomplete_add(otr_ac, "theirfp");
652 autocomplete_add(otr_ac, "trust");
653 autocomplete_add(otr_ac, "untrust");
654 autocomplete_add(otr_ac, "secret");
655 autocomplete_add(otr_ac, "log");
656 autocomplete_add(otr_ac, "libver");
657 autocomplete_add(otr_ac, "policy");
658 autocomplete_add(otr_ac, "question");
659 autocomplete_add(otr_ac, "answer");
660 autocomplete_add(otr_ac, "char");
661 autocomplete_add(otr_ac, "sendfile");
662
663 otr_log_ac = autocomplete_new();
664 autocomplete_add(otr_log_ac, "on");
665 autocomplete_add(otr_log_ac, "off");
666 autocomplete_add(otr_log_ac, "redact");
667
668 otr_policy_ac = autocomplete_new();
669 autocomplete_add(otr_policy_ac, "manual");
670 autocomplete_add(otr_policy_ac, "opportunistic");
671 autocomplete_add(otr_policy_ac, "always");
672
673 otr_sendfile_ac = autocomplete_new();
674 autocomplete_add(otr_sendfile_ac, "on");
675 autocomplete_add(otr_sendfile_ac, "off");
676 #endif
677
678 #ifdef HAVE_OMEMO
679 omemo_ac = autocomplete_new();
680 autocomplete_add(omemo_ac, "gen");
681 autocomplete_add(omemo_ac, "log");
682 autocomplete_add(omemo_ac, "start");
683 autocomplete_add(omemo_ac, "end");
684 autocomplete_add(omemo_ac, "trust");
685 autocomplete_add(omemo_ac, "untrust");
686 autocomplete_add(omemo_ac, "fingerprint");
687 autocomplete_add(omemo_ac, "clear_device_list");
688 autocomplete_add(omemo_ac, "policy");
689 autocomplete_add(omemo_ac, "trustmode");
690 autocomplete_add(omemo_ac, "char");
691
692 omemo_log_ac = autocomplete_new();
693 autocomplete_add(omemo_log_ac, "on");
694 autocomplete_add(omemo_log_ac, "off");
695 autocomplete_add(omemo_log_ac, "redact");
696
697 omemo_policy_ac = autocomplete_new();
698 autocomplete_add(omemo_policy_ac, "manual");
699 autocomplete_add(omemo_policy_ac, "automatic");
700 autocomplete_add(omemo_policy_ac, "always");
701
702 // Autocomplete OMEMO trustmode
703 omemo_trustmode_ac = autocomplete_new();
704 autocomplete_add(omemo_trustmode_ac, "manual");
705 autocomplete_add(omemo_trustmode_ac, "firstusage");
706 autocomplete_add(omemo_trustmode_ac, "blind");
707 #endif
708
709 connect_property_ac = autocomplete_new();
710 autocomplete_add(connect_property_ac, "auth");
711 autocomplete_add(connect_property_ac, "server");
712 autocomplete_add(connect_property_ac, "port");
713 autocomplete_add(connect_property_ac, "tls");
714
715 tls_property_ac = autocomplete_new();
716 autocomplete_add(tls_property_ac, "force");
717 autocomplete_add(tls_property_ac, "allow");
718 autocomplete_add(tls_property_ac, "trust");
719 autocomplete_add(tls_property_ac, "legacy");
720 autocomplete_add(tls_property_ac, "disable");
721
722 auth_property_ac = autocomplete_new();
723 autocomplete_add(auth_property_ac, "default");
724 autocomplete_add(auth_property_ac, "legacy");
725
726 join_property_ac = autocomplete_new();
727 autocomplete_add(join_property_ac, "nick");
728 autocomplete_add(join_property_ac, "password");
729
730 alias_ac = autocomplete_new();
731 autocomplete_add(alias_ac, "add");
732 autocomplete_add(alias_ac, "remove");
733 autocomplete_add(alias_ac, "list");
734
735 room_ac = autocomplete_new();
736 autocomplete_add(room_ac, "accept");
737 autocomplete_add(room_ac, "destroy");
738 autocomplete_add(room_ac, "config");
739
740 rooms_all_ac = autocomplete_new();
741 autocomplete_add(rooms_all_ac, "service");
742 autocomplete_add(rooms_all_ac, "filter");
743 autocomplete_add(rooms_all_ac, "cache");
744
745 rooms_list_ac = autocomplete_new();
746 autocomplete_add(rooms_list_ac, "service");
747 autocomplete_add(rooms_list_ac, "filter");
748
749 rooms_cache_ac = autocomplete_new();
750 autocomplete_add(rooms_cache_ac, "on");
751 autocomplete_add(rooms_cache_ac, "off");
752 autocomplete_add(rooms_cache_ac, "clear");
753
754 affiliation_ac = autocomplete_new();
755 autocomplete_add(affiliation_ac, "owner");
756 autocomplete_add(affiliation_ac, "admin");
757 autocomplete_add(affiliation_ac, "member");
758 autocomplete_add(affiliation_ac, "none");
759 autocomplete_add(affiliation_ac, "outcast");
760
761 role_ac = autocomplete_new();
762 autocomplete_add(role_ac, "moderator");
763 autocomplete_add(role_ac, "participant");
764 autocomplete_add(role_ac, "visitor");
765 autocomplete_add(role_ac, "none");
766
767 affiliation_cmd_ac = autocomplete_new();
768 autocomplete_add(affiliation_cmd_ac, "list");
769 autocomplete_add(affiliation_cmd_ac, "request");
770 autocomplete_add(affiliation_cmd_ac, "register");
771 autocomplete_add(affiliation_cmd_ac, "set");
772
773 role_cmd_ac = autocomplete_new();
774 autocomplete_add(role_cmd_ac, "list");
775 autocomplete_add(role_cmd_ac, "set");
776
777 subject_ac = autocomplete_new();
778 autocomplete_add(subject_ac, "set");
779 autocomplete_add(subject_ac, "edit");
780 autocomplete_add(subject_ac, "prepend");
781 autocomplete_add(subject_ac, "append");
782 autocomplete_add(subject_ac, "clear");
783
784 form_ac = autocomplete_new();
785 autocomplete_add(form_ac, "submit");
786 autocomplete_add(form_ac, "cancel");
787 autocomplete_add(form_ac, "show");
788 autocomplete_add(form_ac, "help");
789
790 form_field_multi_ac = autocomplete_new();
791 autocomplete_add(form_field_multi_ac, "add");
792 autocomplete_add(form_field_multi_ac, "remove");
793
794 occupants_ac = autocomplete_new();
795 autocomplete_add(occupants_ac, "show");
796 autocomplete_add(occupants_ac, "hide");
797 autocomplete_add(occupants_ac, "default");
798 autocomplete_add(occupants_ac, "size");
799 autocomplete_add(occupants_ac, "indent");
800 autocomplete_add(occupants_ac, "header");
801 autocomplete_add(occupants_ac, "wrap");
802 autocomplete_add(occupants_ac, "char");
803 autocomplete_add(occupants_ac, "color");
804
805 occupants_default_ac = autocomplete_new();
806 autocomplete_add(occupants_default_ac, "show");
807 autocomplete_add(occupants_default_ac, "hide");
808
809 occupants_show_ac = autocomplete_new();
810 autocomplete_add(occupants_show_ac, "jid");
811 autocomplete_add(occupants_show_ac, "offline");
812
813 occupants_char_ac = autocomplete_new();
814 autocomplete_add(occupants_char_ac, "none");
815
816 occupants_header_ac = autocomplete_new();
817 autocomplete_add(occupants_header_ac, "char");
818
819 occupants_header_char_ac = autocomplete_new();
820 autocomplete_add(occupants_header_char_ac, "none");
821
822 time_ac = autocomplete_new();
823 autocomplete_add(time_ac, "console");
824 autocomplete_add(time_ac, "chat");
825 autocomplete_add(time_ac, "muc");
826 autocomplete_add(time_ac, "config");
827 autocomplete_add(time_ac, "private");
828 autocomplete_add(time_ac, "xml");
829 autocomplete_add(time_ac, "statusbar");
830 autocomplete_add(time_ac, "lastactivity");
831 autocomplete_add(time_ac, "all");
832
833 time_format_ac = autocomplete_new();
834 autocomplete_add(time_format_ac, "set");
835 autocomplete_add(time_format_ac, "off");
836
837 resource_ac = autocomplete_new();
838 autocomplete_add(resource_ac, "set");
839 autocomplete_add(resource_ac, "off");
840 autocomplete_add(resource_ac, "title");
841 autocomplete_add(resource_ac, "message");
842
843 inpblock_ac = autocomplete_new();
844 autocomplete_add(inpblock_ac, "timeout");
845 autocomplete_add(inpblock_ac, "dynamic");
846
847 receipts_ac = autocomplete_new();
848 autocomplete_add(receipts_ac, "send");
849 autocomplete_add(receipts_ac, "request");
850
851 #ifdef HAVE_LIBGPGME
852 pgp_ac = autocomplete_new();
853 autocomplete_add(pgp_ac, "keys");
854 autocomplete_add(pgp_ac, "contacts");
855 autocomplete_add(pgp_ac, "setkey");
856 autocomplete_add(pgp_ac, "libver");
857 autocomplete_add(pgp_ac, "start");
858 autocomplete_add(pgp_ac, "end");
859 autocomplete_add(pgp_ac, "log");
860 autocomplete_add(pgp_ac, "char");
861 autocomplete_add(pgp_ac, "sendfile");
862
863 pgp_log_ac = autocomplete_new();
864 autocomplete_add(pgp_log_ac, "on");
865 autocomplete_add(pgp_log_ac, "off");
866 autocomplete_add(pgp_log_ac, "redact");
867
868 pgp_sendfile_ac = autocomplete_new();
869 autocomplete_add(pgp_sendfile_ac, "on");
870 autocomplete_add(pgp_sendfile_ac, "off");
871
872 // XEP-0373: OX
873 ox_ac = autocomplete_new();
874 autocomplete_add(ox_ac, "keys");
875 autocomplete_add(ox_ac, "contacts");
876 autocomplete_add(ox_ac, "start");
877 autocomplete_add(ox_ac, "end");
878 autocomplete_add(ox_ac, "log");
879 autocomplete_add(ox_ac, "char");
880 autocomplete_add(ox_ac, "sendfile");
881 autocomplete_add(ox_ac, "announce");
882 autocomplete_add(ox_ac, "discover");
883 autocomplete_add(ox_ac, "request");
884 #endif
885
886 tls_ac = autocomplete_new();
887 autocomplete_add(tls_ac, "allow");
888 autocomplete_add(tls_ac, "always");
889 autocomplete_add(tls_ac, "deny");
890 autocomplete_add(tls_ac, "cert");
891 autocomplete_add(tls_ac, "trust");
892 autocomplete_add(tls_ac, "trusted");
893 autocomplete_add(tls_ac, "revoke");
894 autocomplete_add(tls_ac, "certpath");
895
896 titlebar_ac = autocomplete_new();
897 autocomplete_add(titlebar_ac, "up");
898 autocomplete_add(titlebar_ac, "down");
899 autocomplete_add(titlebar_ac, "show");
900 autocomplete_add(titlebar_ac, "hide");
901
902 titlebar_show_ac = autocomplete_new();
903 autocomplete_add(titlebar_show_ac, "tls");
904 autocomplete_add(titlebar_show_ac, "encwarn");
905 autocomplete_add(titlebar_show_ac, "resource");
906 autocomplete_add(titlebar_show_ac, "presence");
907 autocomplete_add(titlebar_show_ac, "jid");
908 autocomplete_add(titlebar_show_ac, "name");
909
910 tls_certpath_ac = autocomplete_new();
911 autocomplete_add(tls_certpath_ac, "set");
912 autocomplete_add(tls_certpath_ac, "clear");
913 autocomplete_add(tls_certpath_ac, "default");
914
915 script_ac = autocomplete_new();
916 autocomplete_add(script_ac, "run");
917 autocomplete_add(script_ac, "list");
918 autocomplete_add(script_ac, "show");
919
920 script_show_ac = NULL;
921
922 console_ac = autocomplete_new();
923 autocomplete_add(console_ac, "chat");
924 autocomplete_add(console_ac, "muc");
925 autocomplete_add(console_ac, "private");
926
927 console_msg_ac = autocomplete_new();
928 autocomplete_add(console_msg_ac, "all");
929 autocomplete_add(console_msg_ac, "first");
930 autocomplete_add(console_msg_ac, "mention");
931 autocomplete_add(console_msg_ac, "none");
932
933 autoping_ac = autocomplete_new();
934 autocomplete_add(autoping_ac, "set");
935 autocomplete_add(autoping_ac, "timeout");
936
937 plugins_ac = autocomplete_new();
938 autocomplete_add(plugins_ac, "install");
939 autocomplete_add(plugins_ac, "load");
940 autocomplete_add(plugins_ac, "unload");
941 autocomplete_add(plugins_ac, "reload");
942 autocomplete_add(plugins_ac, "python_version");
943 autocomplete_add(plugins_ac, "sourcepath");
944
945 plugins_sourcepath_ac = autocomplete_new();
946 autocomplete_add(plugins_sourcepath_ac, "set");
947 autocomplete_add(plugins_sourcepath_ac, "clear");
948
949 filepath_ac = autocomplete_new();
950
951 blocked_ac = autocomplete_new();
952 autocomplete_add(blocked_ac, "add");
953 autocomplete_add(blocked_ac, "remove");
954 autocomplete_add(blocked_ac, "report-abuse");
955 autocomplete_add(blocked_ac, "report-spam");
956
957 clear_ac = autocomplete_new();
958 autocomplete_add(clear_ac, "persist_history");
959
960 tray_ac = autocomplete_new();
961 autocomplete_add(tray_ac, "on");
962 autocomplete_add(tray_ac, "off");
963 autocomplete_add(tray_ac, "read");
964 autocomplete_add(tray_ac, "timer");
965
966 presence_ac = autocomplete_new();
967 autocomplete_add(presence_ac, "titlebar");
968 autocomplete_add(presence_ac, "console");
969 autocomplete_add(presence_ac, "chat");
970 autocomplete_add(presence_ac, "room");
971
972 presence_setting_ac = autocomplete_new();
973 autocomplete_add(presence_setting_ac, "all");
974 autocomplete_add(presence_setting_ac, "online");
975 autocomplete_add(presence_setting_ac, "none");
976
977 winpos_ac = autocomplete_new();
978 autocomplete_add(winpos_ac, "up");
979 autocomplete_add(winpos_ac, "down");
980
981 statusbar_ac = autocomplete_new();
982 autocomplete_add(statusbar_ac, "up");
983 autocomplete_add(statusbar_ac, "down");
984 autocomplete_add(statusbar_ac, "show");
985 autocomplete_add(statusbar_ac, "hide");
986 autocomplete_add(statusbar_ac, "maxtabs");
987 autocomplete_add(statusbar_ac, "tablen");
988 autocomplete_add(statusbar_ac, "self");
989 autocomplete_add(statusbar_ac, "chat");
990 autocomplete_add(statusbar_ac, "room");
991
992 invite_ac = autocomplete_new();
993 autocomplete_add(invite_ac, "send");
994 autocomplete_add(invite_ac, "list");
995 autocomplete_add(invite_ac, "decline");
996
997 statusbar_self_ac = autocomplete_new();
998 autocomplete_add(statusbar_self_ac, "user");
999 autocomplete_add(statusbar_self_ac, "barejid");
1000 autocomplete_add(statusbar_self_ac, "fulljid");
1001 autocomplete_add(statusbar_self_ac, "off");
1002
1003 statusbar_chat_ac = autocomplete_new();
1004 autocomplete_add(statusbar_chat_ac, "user");
1005 autocomplete_add(statusbar_chat_ac, "jid");
1006
1007 statusbar_room_ac = autocomplete_new();
1008 autocomplete_add(statusbar_room_ac, "room");
1009 autocomplete_add(statusbar_room_ac, "jid");
1010
1011 statusbar_show_ac = autocomplete_new();
1012 autocomplete_add(statusbar_show_ac, "name");
1013 autocomplete_add(statusbar_show_ac, "number");
1014 autocomplete_add(statusbar_show_ac, "read");
1015
1016 status_ac = autocomplete_new();
1017 autocomplete_add(status_ac, "set");
1018 autocomplete_add(status_ac, "get");
1019
1020 status_state_ac = autocomplete_new();
1021 autocomplete_add(status_state_ac, "online");
1022 autocomplete_add(status_state_ac, "chat");
1023 autocomplete_add(status_state_ac, "away");
1024 autocomplete_add(status_state_ac, "xa");
1025 autocomplete_add(status_state_ac, "dnd");
1026
1027 logging_ac = autocomplete_new();
1028 autocomplete_add(logging_ac, "chat");
1029 autocomplete_add(logging_ac, "group");
1030
1031 logging_group_ac = autocomplete_new();
1032 autocomplete_add(logging_group_ac, "on");
1033 autocomplete_add(logging_group_ac, "off");
1034 autocomplete_add(logging_group_ac, "color");
1035
1036 color_ac = autocomplete_new();
1037 autocomplete_add(color_ac, "on");
1038 autocomplete_add(color_ac, "off");
1039 autocomplete_add(color_ac, "redgreen");
1040 autocomplete_add(color_ac, "blue");
1041 autocomplete_add(color_ac, "own");
1042
1043 correction_ac = autocomplete_new();
1044 autocomplete_add(correction_ac, "on");
1045 autocomplete_add(correction_ac, "off");
1046 autocomplete_add(correction_ac, "char");
1047
1048 avatar_ac = autocomplete_new();
1049 autocomplete_add(avatar_ac, "get");
1050 autocomplete_add(avatar_ac, "open");
1051
1052 url_ac = autocomplete_new();
1053 autocomplete_add(url_ac, "open");
1054 autocomplete_add(url_ac, "save");
1055
1056 executable_ac = autocomplete_new();
1057 autocomplete_add(executable_ac, "avatar");
1058 autocomplete_add(executable_ac, "urlopen");
1059 autocomplete_add(executable_ac, "urlsave");
1060 autocomplete_add(executable_ac, "editor");
1061
1062 intype_ac = autocomplete_new();
1063 autocomplete_add(intype_ac, "console");
1064 autocomplete_add(intype_ac, "titlebar");
1065 }
1066
1067 void
cmd_ac_add(const char * const value)1068 cmd_ac_add(const char* const value)
1069 {
1070 if (commands_ac == NULL) {
1071 return;
1072 }
1073
1074 autocomplete_add(commands_ac, value);
1075 }
1076
1077 void
cmd_ac_add_help(const char * const value)1078 cmd_ac_add_help(const char* const value)
1079 {
1080 if (help_ac == NULL) {
1081 return;
1082 }
1083
1084 autocomplete_add(help_ac, value);
1085 }
1086
1087 void
cmd_ac_add_cmd(Command * command)1088 cmd_ac_add_cmd(Command* command)
1089 {
1090 autocomplete_add(commands_ac, command->cmd);
1091 autocomplete_add(help_ac, command->cmd + 1);
1092 }
1093
1094 void
cmd_ac_add_alias(ProfAlias * alias)1095 cmd_ac_add_alias(ProfAlias* alias)
1096 {
1097 GString* ac_alias = g_string_new("/");
1098 g_string_append(ac_alias, alias->name);
1099 autocomplete_add(commands_ac, ac_alias->str);
1100 autocomplete_add(aliases_ac, alias->name);
1101 g_string_free(ac_alias, TRUE);
1102 }
1103
1104 void
cmd_ac_add_alias_value(char * value)1105 cmd_ac_add_alias_value(char* value)
1106 {
1107 if (aliases_ac == NULL) {
1108 return;
1109 }
1110
1111 autocomplete_add(aliases_ac, value);
1112 }
1113
1114 void
cmd_ac_remove_alias_value(char * value)1115 cmd_ac_remove_alias_value(char* value)
1116 {
1117 if (aliases_ac == NULL) {
1118 return;
1119 }
1120 autocomplete_remove(aliases_ac, value);
1121 }
1122
1123 void
cmd_ac_remove(const char * const value)1124 cmd_ac_remove(const char* const value)
1125 {
1126 if (commands_ac == NULL) {
1127 return;
1128 }
1129
1130 autocomplete_remove(commands_ac, value);
1131 }
1132
1133 void
cmd_ac_remove_help(const char * const value)1134 cmd_ac_remove_help(const char* const value)
1135 {
1136 if (help_ac == NULL) {
1137 return;
1138 }
1139
1140 autocomplete_remove(help_ac, value);
1141 }
1142
1143 gboolean
cmd_ac_exists(char * cmd)1144 cmd_ac_exists(char* cmd)
1145 {
1146 if (commands_ac == NULL) {
1147 return FALSE;
1148 }
1149
1150 return autocomplete_contains(commands_ac, cmd);
1151 }
1152
1153 void
cmd_ac_add_form_fields(DataForm * form)1154 cmd_ac_add_form_fields(DataForm* form)
1155 {
1156 if (form == NULL) {
1157 return;
1158 }
1159
1160 GList* fields = autocomplete_create_list(form->tag_ac);
1161 GList* curr_field = fields;
1162 while (curr_field) {
1163 GString* field_str = g_string_new("/");
1164 g_string_append(field_str, curr_field->data);
1165 cmd_ac_add(field_str->str);
1166 g_string_free(field_str, TRUE);
1167 curr_field = g_list_next(curr_field);
1168 }
1169 g_list_free_full(fields, free);
1170 }
1171
1172 void
cmd_ac_remove_form_fields(DataForm * form)1173 cmd_ac_remove_form_fields(DataForm* form)
1174 {
1175 if (form == NULL) {
1176 return;
1177 }
1178
1179 GList* fields = autocomplete_create_list(form->tag_ac);
1180 GList* curr_field = fields;
1181 while (curr_field) {
1182 GString* field_str = g_string_new("/");
1183 g_string_append(field_str, curr_field->data);
1184 cmd_ac_remove(field_str->str);
1185 g_string_free(field_str, TRUE);
1186 curr_field = g_list_next(curr_field);
1187 }
1188 g_list_free_full(fields, free);
1189 }
1190
1191 char*
cmd_ac_complete(ProfWin * window,const char * const input,gboolean previous)1192 cmd_ac_complete(ProfWin* window, const char* const input, gboolean previous)
1193 {
1194 char* found = NULL;
1195 // autocomplete command
1196 if ((strncmp(input, "/", 1) == 0) && (!strchr(input, ' '))) {
1197 found = autocomplete_complete(commands_ac, input, TRUE, previous);
1198
1199 // autocomplete parameters
1200 } else {
1201 found = _cmd_ac_complete_params(window, input, previous);
1202 }
1203
1204 return found;
1205 }
1206
1207 void
cmd_ac_reset(ProfWin * window)1208 cmd_ac_reset(ProfWin* window)
1209 {
1210 jabber_conn_status_t conn_status = connection_get_status();
1211 if (conn_status == JABBER_CONNECTED) {
1212 roster_reset_search_attempts();
1213
1214 if (window->type == WIN_CHAT) {
1215 ProfChatWin* chatwin = (ProfChatWin*)window;
1216 assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
1217 PContact contact = roster_get_contact(chatwin->barejid);
1218 if (contact) {
1219 p_contact_resource_ac_reset(contact);
1220 }
1221 }
1222 }
1223
1224 muc_invites_reset_ac();
1225 muc_confserver_reset_ac();
1226 accounts_reset_all_search();
1227 accounts_reset_enabled_search();
1228 tlscerts_reset_ac();
1229 prefs_reset_boolean_choice();
1230 presence_reset_sub_request_search();
1231 #ifdef HAVE_LIBGPGME
1232 p_gpg_autocomplete_key_reset();
1233 #endif
1234 #ifdef HAVE_OMEMO
1235 omemo_fingerprint_autocomplete_reset();
1236 #endif
1237 autocomplete_reset(help_ac);
1238 autocomplete_reset(help_commands_ac);
1239 autocomplete_reset(notify_ac);
1240 autocomplete_reset(notify_chat_ac);
1241 autocomplete_reset(notify_room_ac);
1242 autocomplete_reset(notify_typing_ac);
1243 autocomplete_reset(notify_mention_ac);
1244 autocomplete_reset(notify_trigger_ac);
1245 autocomplete_reset(sub_ac);
1246 autocomplete_reset(filepath_ac);
1247
1248 autocomplete_reset(who_room_ac);
1249 autocomplete_reset(who_roster_ac);
1250 autocomplete_reset(prefs_ac);
1251 autocomplete_reset(log_ac);
1252 autocomplete_reset(commands_ac);
1253 autocomplete_reset(autoaway_ac);
1254 autocomplete_reset(autoaway_mode_ac);
1255 autocomplete_reset(autoaway_presence_ac);
1256 autocomplete_reset(autoconnect_ac);
1257 autocomplete_reset(theme_ac);
1258 if (theme_load_ac) {
1259 autocomplete_free(theme_load_ac);
1260 theme_load_ac = NULL;
1261 }
1262 if (plugins_load_ac) {
1263 autocomplete_free(plugins_load_ac);
1264 plugins_load_ac = NULL;
1265 }
1266 if (plugins_unload_ac) {
1267 autocomplete_free(plugins_unload_ac);
1268 plugins_unload_ac = NULL;
1269 }
1270 if (plugins_reload_ac) {
1271 autocomplete_free(plugins_reload_ac);
1272 plugins_reload_ac = NULL;
1273 }
1274 autocomplete_reset(account_ac);
1275 autocomplete_reset(account_set_ac);
1276 autocomplete_reset(account_clear_ac);
1277 autocomplete_reset(account_default_ac);
1278 autocomplete_reset(account_status_ac);
1279 autocomplete_reset(disco_ac);
1280 autocomplete_reset(wins_ac);
1281 autocomplete_reset(roster_ac);
1282 autocomplete_reset(roster_header_ac);
1283 autocomplete_reset(roster_contact_ac);
1284 autocomplete_reset(roster_resource_ac);
1285 autocomplete_reset(roster_presence_ac);
1286 autocomplete_reset(roster_char_ac);
1287 autocomplete_reset(roster_show_ac);
1288 autocomplete_reset(roster_by_ac);
1289 autocomplete_reset(roster_count_ac);
1290 autocomplete_reset(roster_order_ac);
1291 autocomplete_reset(roster_room_ac);
1292 autocomplete_reset(roster_room_show_ac);
1293 autocomplete_reset(roster_room_use_ac);
1294 autocomplete_reset(roster_room_by_ac);
1295 autocomplete_reset(roster_unread_ac);
1296 autocomplete_reset(roster_room_position_ac);
1297 autocomplete_reset(roster_room_order_ac);
1298 autocomplete_reset(roster_remove_all_ac);
1299 autocomplete_reset(roster_private_ac);
1300 autocomplete_reset(group_ac);
1301 autocomplete_reset(wintitle_ac);
1302 autocomplete_reset(bookmark_ac);
1303 autocomplete_reset(bookmark_property_ac);
1304 autocomplete_reset(bookmark_ignore_ac);
1305 #ifdef HAVE_LIBOTR
1306 autocomplete_reset(otr_ac);
1307 autocomplete_reset(otr_log_ac);
1308 autocomplete_reset(otr_policy_ac);
1309 autocomplete_reset(otr_sendfile_ac);
1310 #endif
1311 #ifdef HAVE_OMEMO
1312 autocomplete_reset(omemo_ac);
1313 autocomplete_reset(omemo_log_ac);
1314 autocomplete_reset(omemo_policy_ac);
1315 autocomplete_reset(omemo_trustmode_ac);
1316 #endif
1317 autocomplete_reset(connect_property_ac);
1318 autocomplete_reset(tls_property_ac);
1319 autocomplete_reset(auth_property_ac);
1320 autocomplete_reset(alias_ac);
1321 autocomplete_reset(aliases_ac);
1322 autocomplete_reset(join_property_ac);
1323 autocomplete_reset(room_ac);
1324 autocomplete_reset(rooms_all_ac);
1325 autocomplete_reset(rooms_list_ac);
1326 autocomplete_reset(rooms_cache_ac);
1327 autocomplete_reset(affiliation_ac);
1328 autocomplete_reset(role_ac);
1329 autocomplete_reset(affiliation_cmd_ac);
1330 autocomplete_reset(role_cmd_ac);
1331 autocomplete_reset(subject_ac);
1332 autocomplete_reset(form_ac);
1333 autocomplete_reset(form_field_multi_ac);
1334 autocomplete_reset(occupants_ac);
1335 autocomplete_reset(occupants_char_ac);
1336 autocomplete_reset(occupants_default_ac);
1337 autocomplete_reset(occupants_show_ac);
1338 autocomplete_reset(occupants_header_ac);
1339 autocomplete_reset(occupants_header_char_ac);
1340 autocomplete_reset(time_ac);
1341 autocomplete_reset(time_format_ac);
1342 autocomplete_reset(resource_ac);
1343 autocomplete_reset(inpblock_ac);
1344 autocomplete_reset(receipts_ac);
1345 #ifdef HAVE_LIBGPGME
1346 autocomplete_reset(pgp_ac);
1347 autocomplete_reset(pgp_log_ac);
1348 autocomplete_reset(pgp_sendfile_ac);
1349 #endif
1350 autocomplete_reset(tls_ac);
1351 autocomplete_reset(titlebar_ac);
1352 autocomplete_reset(titlebar_show_ac);
1353 autocomplete_reset(tls_certpath_ac);
1354 autocomplete_reset(console_ac);
1355 autocomplete_reset(console_msg_ac);
1356 autocomplete_reset(autoping_ac);
1357 autocomplete_reset(plugins_ac);
1358 autocomplete_reset(plugins_sourcepath_ac);
1359 autocomplete_reset(blocked_ac);
1360 autocomplete_reset(tray_ac);
1361 autocomplete_reset(presence_ac);
1362 autocomplete_reset(presence_setting_ac);
1363 autocomplete_reset(winpos_ac);
1364 autocomplete_reset(statusbar_ac);
1365 autocomplete_reset(statusbar_self_ac);
1366 autocomplete_reset(statusbar_chat_ac);
1367 autocomplete_reset(statusbar_room_ac);
1368 autocomplete_reset(statusbar_show_ac);
1369 autocomplete_reset(clear_ac);
1370 autocomplete_reset(invite_ac);
1371 autocomplete_reset(status_ac);
1372 autocomplete_reset(status_state_ac);
1373 autocomplete_reset(logging_ac);
1374 autocomplete_reset(logging_group_ac);
1375 autocomplete_reset(color_ac);
1376 autocomplete_reset(correction_ac);
1377 autocomplete_reset(avatar_ac);
1378 autocomplete_reset(url_ac);
1379 autocomplete_reset(executable_ac);
1380 autocomplete_reset(intype_ac);
1381
1382 autocomplete_reset(script_ac);
1383 if (script_show_ac) {
1384 autocomplete_free(script_show_ac);
1385 script_show_ac = NULL;
1386 }
1387
1388 if (window->type == WIN_MUC) {
1389 ProfMucWin* mucwin = (ProfMucWin*)window;
1390 assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
1391 muc_autocomplete_reset(mucwin->roomjid);
1392 muc_jid_autocomplete_reset(mucwin->roomjid);
1393 }
1394
1395 if (window->type == WIN_CONFIG) {
1396 ProfConfWin* confwin = (ProfConfWin*)window;
1397 assert(confwin->memcheck == PROFCONFWIN_MEMCHECK);
1398 if (confwin->form) {
1399 form_reset_autocompleters(confwin->form);
1400 }
1401 }
1402
1403 bookmark_autocomplete_reset();
1404 blocked_ac_reset();
1405 prefs_reset_room_trigger_ac();
1406 win_reset_search_attempts();
1407 win_close_reset_search_attempts();
1408 plugins_reset_autocomplete();
1409 }
1410
1411 void
cmd_ac_uninit(void)1412 cmd_ac_uninit(void)
1413 {
1414 autocomplete_free(commands_ac);
1415 autocomplete_free(who_room_ac);
1416 autocomplete_free(who_roster_ac);
1417 autocomplete_free(help_ac);
1418 autocomplete_free(help_commands_ac);
1419 autocomplete_free(notify_ac);
1420 autocomplete_free(notify_chat_ac);
1421 autocomplete_free(notify_room_ac);
1422 autocomplete_free(notify_typing_ac);
1423 autocomplete_free(notify_mention_ac);
1424 autocomplete_free(notify_trigger_ac);
1425 autocomplete_free(sub_ac);
1426 autocomplete_free(wintitle_ac);
1427 autocomplete_free(log_ac);
1428 autocomplete_free(prefs_ac);
1429 autocomplete_free(autoaway_ac);
1430 autocomplete_free(autoaway_mode_ac);
1431 autocomplete_free(autoaway_presence_ac);
1432 autocomplete_free(autoconnect_ac);
1433 autocomplete_free(theme_ac);
1434 autocomplete_free(theme_load_ac);
1435 autocomplete_free(account_ac);
1436 autocomplete_free(account_set_ac);
1437 autocomplete_free(account_clear_ac);
1438 autocomplete_free(account_default_ac);
1439 autocomplete_free(account_status_ac);
1440 autocomplete_free(disco_ac);
1441 autocomplete_free(wins_ac);
1442 autocomplete_free(roster_ac);
1443 autocomplete_free(roster_header_ac);
1444 autocomplete_free(roster_contact_ac);
1445 autocomplete_free(roster_resource_ac);
1446 autocomplete_free(roster_presence_ac);
1447 autocomplete_free(roster_char_ac);
1448 autocomplete_free(roster_show_ac);
1449 autocomplete_free(roster_by_ac);
1450 autocomplete_free(roster_count_ac);
1451 autocomplete_free(roster_order_ac);
1452 autocomplete_free(roster_room_ac);
1453 autocomplete_free(roster_room_show_ac);
1454 autocomplete_free(roster_room_use_ac);
1455 autocomplete_free(roster_room_by_ac);
1456 autocomplete_free(roster_unread_ac);
1457 autocomplete_free(roster_room_position_ac);
1458 autocomplete_free(roster_room_order_ac);
1459 autocomplete_free(roster_remove_all_ac);
1460 autocomplete_free(roster_private_ac);
1461 autocomplete_free(group_ac);
1462 autocomplete_free(bookmark_ac);
1463 autocomplete_free(bookmark_property_ac);
1464 autocomplete_free(bookmark_ignore_ac);
1465 #ifdef HAVE_LIBOTR
1466 autocomplete_free(otr_ac);
1467 autocomplete_free(otr_log_ac);
1468 autocomplete_free(otr_policy_ac);
1469 autocomplete_free(otr_sendfile_ac);
1470 #endif
1471 #ifdef HAVE_OMEMO
1472 autocomplete_free(omemo_ac);
1473 autocomplete_free(omemo_log_ac);
1474 autocomplete_free(omemo_policy_ac);
1475 autocomplete_free(omemo_trustmode_ac);
1476 #endif
1477 autocomplete_free(connect_property_ac);
1478 autocomplete_free(tls_property_ac);
1479 autocomplete_free(auth_property_ac);
1480 autocomplete_free(alias_ac);
1481 autocomplete_free(aliases_ac);
1482 autocomplete_free(join_property_ac);
1483 autocomplete_free(room_ac);
1484 autocomplete_free(rooms_all_ac);
1485 autocomplete_free(rooms_list_ac);
1486 autocomplete_free(rooms_cache_ac);
1487 autocomplete_free(affiliation_ac);
1488 autocomplete_free(role_ac);
1489 autocomplete_free(affiliation_cmd_ac);
1490 autocomplete_free(role_cmd_ac);
1491 autocomplete_free(subject_ac);
1492 autocomplete_free(form_ac);
1493 autocomplete_free(form_field_multi_ac);
1494 autocomplete_free(occupants_ac);
1495 autocomplete_free(occupants_char_ac);
1496 autocomplete_free(occupants_default_ac);
1497 autocomplete_free(occupants_show_ac);
1498 autocomplete_free(occupants_header_ac);
1499 autocomplete_free(time_ac);
1500 autocomplete_free(time_format_ac);
1501 autocomplete_free(resource_ac);
1502 autocomplete_free(inpblock_ac);
1503 autocomplete_free(receipts_ac);
1504 #ifdef HAVE_LIBGPGME
1505 autocomplete_free(pgp_ac);
1506 autocomplete_free(pgp_log_ac);
1507 autocomplete_free(pgp_sendfile_ac);
1508 #endif
1509 autocomplete_free(tls_ac);
1510 autocomplete_free(titlebar_ac);
1511 autocomplete_free(titlebar_show_ac);
1512 autocomplete_free(tls_certpath_ac);
1513 autocomplete_free(script_ac);
1514 autocomplete_free(script_show_ac);
1515 autocomplete_free(console_ac);
1516 autocomplete_free(console_msg_ac);
1517 autocomplete_free(autoping_ac);
1518 autocomplete_free(plugins_ac);
1519 autocomplete_free(plugins_load_ac);
1520 autocomplete_free(plugins_unload_ac);
1521 autocomplete_free(plugins_reload_ac);
1522 autocomplete_free(filepath_ac);
1523 autocomplete_free(blocked_ac);
1524 autocomplete_free(tray_ac);
1525 autocomplete_free(presence_ac);
1526 autocomplete_free(presence_setting_ac);
1527 autocomplete_free(winpos_ac);
1528 autocomplete_free(statusbar_ac);
1529 autocomplete_free(statusbar_self_ac);
1530 autocomplete_free(statusbar_chat_ac);
1531 autocomplete_free(statusbar_room_ac);
1532 autocomplete_free(statusbar_show_ac);
1533 autocomplete_free(clear_ac);
1534 autocomplete_free(invite_ac);
1535 autocomplete_free(status_ac);
1536 autocomplete_free(status_state_ac);
1537 autocomplete_free(logging_ac);
1538 autocomplete_free(logging_group_ac);
1539 autocomplete_free(color_ac);
1540 autocomplete_free(correction_ac);
1541 autocomplete_free(avatar_ac);
1542 autocomplete_free(url_ac);
1543 autocomplete_free(executable_ac);
1544 autocomplete_free(intype_ac);
1545 }
1546
1547 static void
_filepath_item_free(char ** ptr)1548 _filepath_item_free(char** ptr)
1549 {
1550 char* item = *ptr;
1551 free(item);
1552 }
1553
1554 char*
cmd_ac_complete_filepath(const char * const input,char * const startstr,gboolean previous)1555 cmd_ac_complete_filepath(const char* const input, char* const startstr, gboolean previous)
1556 {
1557 unsigned int output_off = 0;
1558 char* tmp;
1559
1560 // strip command
1561 char* inpcp = (char*)input + strlen(startstr);
1562 while (*inpcp == ' ') {
1563 inpcp++;
1564 }
1565
1566 inpcp = strdup(inpcp);
1567
1568 // strip quotes
1569 if (*inpcp == '"') {
1570 tmp = strchr(inpcp + 1, '"');
1571 if (tmp) {
1572 *tmp = '\0';
1573 }
1574 tmp = strdup(inpcp + 1);
1575 free(inpcp);
1576 inpcp = tmp;
1577 }
1578
1579 // expand ~ to $HOME
1580 if (inpcp[0] == '~' && inpcp[1] == '/') {
1581 tmp = g_strdup_printf("%s/%sfoo", getenv("HOME"), inpcp + 2);
1582 if (!tmp) {
1583 free(inpcp);
1584 return NULL;
1585 }
1586 output_off = strlen(getenv("HOME")) + 1;
1587 } else {
1588 tmp = g_strdup_printf("%sfoo", inpcp);
1589 if (!tmp) {
1590 free(inpcp);
1591 return NULL;
1592 }
1593 }
1594 free(inpcp);
1595 inpcp = tmp;
1596
1597 char* inpcp2 = strdup(inpcp);
1598 char* foofile = strdup(basename(inpcp2));
1599 char* directory = strdup(dirname(inpcp));
1600 free(inpcp);
1601 free(inpcp2);
1602
1603 GArray* files = g_array_new(TRUE, FALSE, sizeof(char*));
1604 g_array_set_clear_func(files, (GDestroyNotify)_filepath_item_free);
1605
1606 DIR* d = opendir(directory);
1607 if (d) {
1608 struct dirent* dir;
1609
1610 while ((dir = readdir(d)) != NULL) {
1611 if (strcmp(dir->d_name, ".") == 0) {
1612 continue;
1613 } else if (strcmp(dir->d_name, "..") == 0) {
1614 continue;
1615 } else if (*(dir->d_name) == '.' && *foofile != '.') {
1616 // only show hidden files on explicit request
1617 continue;
1618 }
1619
1620 char* acstring;
1621 if (output_off) {
1622 tmp = g_strdup_printf("%s/%s", directory, dir->d_name);
1623 if(!tmp) {
1624 free(directory);
1625 free(foofile);
1626 return NULL;
1627 }
1628 acstring = g_strdup_printf("~/%s", tmp + output_off);
1629 if (!acstring) {
1630 free(directory);
1631 free(foofile);
1632 return NULL;
1633 }
1634 free(tmp);
1635 } else if (strcmp(directory, "/") == 0) {
1636 acstring = g_strdup_printf("/%s", dir->d_name);
1637 if (!acstring) {
1638 free(directory);
1639 free(foofile);
1640 return NULL;
1641 }
1642 } else {
1643 acstring = g_strdup_printf("%s/%s", directory, dir->d_name);
1644 if (!acstring) {
1645 free(directory);
1646 free(foofile);
1647 return NULL;
1648 }
1649 }
1650
1651 char* acstring_cpy = strdup(acstring);
1652 g_array_append_val(files, acstring_cpy);
1653 free(acstring);
1654 }
1655 closedir(d);
1656 }
1657 free(directory);
1658 free(foofile);
1659
1660 autocomplete_update(filepath_ac, (char**)files->data);
1661 g_array_free(files, TRUE);
1662
1663 return autocomplete_param_with_ac(input, startstr, filepath_ac, TRUE, previous);
1664 }
1665
1666 static char*
_cmd_ac_complete_params(ProfWin * window,const char * const input,gboolean previous)1667 _cmd_ac_complete_params(ProfWin* window, const char* const input, gboolean previous)
1668 {
1669 char* result = NULL;
1670
1671 jabber_conn_status_t conn_status = connection_get_status();
1672
1673 // autocomplete boolean settings
1674 gchar* boolean_choices[] = { "/beep", "/states", "/outtype", "/flash", "/splash",
1675 "/history", "/vercheck", "/privileges", "/wrap",
1676 "/carbons", "/os", "/slashguard", "/mam", "/silence" };
1677
1678 for (int i = 0; i < ARRAY_SIZE(boolean_choices); i++) {
1679 result = autocomplete_param_with_func(input, boolean_choices[i], prefs_autocomplete_boolean_choice, previous, NULL);
1680 if (result) {
1681 return result;
1682 }
1683 }
1684
1685 // autocomplete nickname in chat rooms
1686 if (window->type == WIN_MUC) {
1687 ProfMucWin* mucwin = (ProfMucWin*)window;
1688 assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
1689 Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid);
1690 if (nick_ac) {
1691 gchar* nick_choices[] = { "/msg", "/info", "/caps" };
1692
1693 // Remove quote character before and after names when doing autocomplete
1694 char* unquoted = strip_arg_quotes(input);
1695 for (int i = 0; i < ARRAY_SIZE(nick_choices); i++) {
1696 result = autocomplete_param_with_ac(unquoted, nick_choices[i], nick_ac, TRUE, previous);
1697 if (result) {
1698 free(unquoted);
1699 return result;
1700 }
1701 }
1702 free(unquoted);
1703 }
1704
1705 // otherwise autocomplete using roster
1706 } else if (conn_status == JABBER_CONNECTED) {
1707 gchar* contact_choices[] = { "/msg", "/info" };
1708 // Remove quote character before and after names when doing autocomplete
1709 char* unquoted = strip_arg_quotes(input);
1710 for (int i = 0; i < ARRAY_SIZE(contact_choices); i++) {
1711 result = autocomplete_param_with_func(unquoted, contact_choices[i], roster_contact_autocomplete, previous, NULL);
1712 if (result) {
1713 free(unquoted);
1714 return result;
1715 }
1716 }
1717 free(unquoted);
1718
1719 gchar* resource_choices[] = { "/caps", "/ping" };
1720 for (int i = 0; i < ARRAY_SIZE(resource_choices); i++) {
1721 result = autocomplete_param_with_func(input, resource_choices[i], roster_fulljid_autocomplete, previous, NULL);
1722 if (result) {
1723 return result;
1724 }
1725 }
1726 }
1727
1728 gchar* invite_choices[] = { "/join" };
1729 for (int i = 0; i < ARRAY_SIZE(invite_choices); i++) {
1730 result = autocomplete_param_with_func(input, invite_choices[i], muc_invites_find, previous, NULL);
1731 if (result) {
1732 return result;
1733 }
1734 }
1735
1736 gchar* cmds[] = { "/prefs", "/disco", "/room", "/autoping", "/mainwin", "/inputwin" };
1737 Autocomplete completers[] = { prefs_ac, disco_ac, room_ac, autoping_ac, winpos_ac, winpos_ac };
1738
1739 for (int i = 0; i < ARRAY_SIZE(cmds); i++) {
1740 result = autocomplete_param_with_ac(input, cmds[i], completers[i], TRUE, previous);
1741 if (result) {
1742 return result;
1743 }
1744 }
1745
1746 GHashTable* ac_funcs = g_hash_table_new(g_str_hash, g_str_equal);
1747 g_hash_table_insert(ac_funcs, "/help", _help_autocomplete);
1748 g_hash_table_insert(ac_funcs, "/who", _who_autocomplete);
1749 g_hash_table_insert(ac_funcs, "/sub", _sub_autocomplete);
1750 g_hash_table_insert(ac_funcs, "/notify", _notify_autocomplete);
1751 g_hash_table_insert(ac_funcs, "/autoaway", _autoaway_autocomplete);
1752 g_hash_table_insert(ac_funcs, "/theme", _theme_autocomplete);
1753 g_hash_table_insert(ac_funcs, "/log", _log_autocomplete);
1754 g_hash_table_insert(ac_funcs, "/account", _account_autocomplete);
1755 g_hash_table_insert(ac_funcs, "/roster", _roster_autocomplete);
1756 g_hash_table_insert(ac_funcs, "/bookmark", _bookmark_autocomplete);
1757 g_hash_table_insert(ac_funcs, "/autoconnect", _autoconnect_autocomplete);
1758 #ifdef HAVE_LIBOTR
1759 g_hash_table_insert(ac_funcs, "/otr", _otr_autocomplete);
1760 #endif
1761 #ifdef HAVE_LIBGPGME
1762 g_hash_table_insert(ac_funcs, "/pgp", _pgp_autocomplete);
1763 g_hash_table_insert(ac_funcs, "/ox", _ox_autocomplete);
1764 #endif
1765 #ifdef HAVE_OMEMO
1766 g_hash_table_insert(ac_funcs, "/omemo", _omemo_autocomplete);
1767 #endif
1768 g_hash_table_insert(ac_funcs, "/connect", _connect_autocomplete);
1769 g_hash_table_insert(ac_funcs, "/alias", _alias_autocomplete);
1770 g_hash_table_insert(ac_funcs, "/join", _join_autocomplete);
1771 g_hash_table_insert(ac_funcs, "/form", _form_autocomplete);
1772 g_hash_table_insert(ac_funcs, "/occupants", _occupants_autocomplete);
1773 g_hash_table_insert(ac_funcs, "/kick", _kick_autocomplete);
1774 g_hash_table_insert(ac_funcs, "/ban", _ban_autocomplete);
1775 g_hash_table_insert(ac_funcs, "/affiliation", _affiliation_autocomplete);
1776 g_hash_table_insert(ac_funcs, "/role", _role_autocomplete);
1777 g_hash_table_insert(ac_funcs, "/resource", _resource_autocomplete);
1778 g_hash_table_insert(ac_funcs, "/wintitle", _wintitle_autocomplete);
1779 g_hash_table_insert(ac_funcs, "/inpblock", _inpblock_autocomplete);
1780 g_hash_table_insert(ac_funcs, "/time", _time_autocomplete);
1781 g_hash_table_insert(ac_funcs, "/receipts", _receipts_autocomplete);
1782 g_hash_table_insert(ac_funcs, "/wins", _wins_autocomplete);
1783 g_hash_table_insert(ac_funcs, "/tls", _tls_autocomplete);
1784 g_hash_table_insert(ac_funcs, "/titlebar", _titlebar_autocomplete);
1785 g_hash_table_insert(ac_funcs, "/script", _script_autocomplete);
1786 g_hash_table_insert(ac_funcs, "/subject", _subject_autocomplete);
1787 g_hash_table_insert(ac_funcs, "/console", _console_autocomplete);
1788 g_hash_table_insert(ac_funcs, "/win", _win_autocomplete);
1789 g_hash_table_insert(ac_funcs, "/close", _close_autocomplete);
1790 g_hash_table_insert(ac_funcs, "/plugins", _plugins_autocomplete);
1791 g_hash_table_insert(ac_funcs, "/sendfile", _sendfile_autocomplete);
1792 g_hash_table_insert(ac_funcs, "/blocked", _blocked_autocomplete);
1793 g_hash_table_insert(ac_funcs, "/tray", _tray_autocomplete);
1794 g_hash_table_insert(ac_funcs, "/presence", _presence_autocomplete);
1795 g_hash_table_insert(ac_funcs, "/rooms", _rooms_autocomplete);
1796 g_hash_table_insert(ac_funcs, "/statusbar", _statusbar_autocomplete);
1797 g_hash_table_insert(ac_funcs, "/clear", _clear_autocomplete);
1798 g_hash_table_insert(ac_funcs, "/invite", _invite_autocomplete);
1799 g_hash_table_insert(ac_funcs, "/status", _status_autocomplete);
1800 g_hash_table_insert(ac_funcs, "/logging", _logging_autocomplete);
1801 g_hash_table_insert(ac_funcs, "/color", _color_autocomplete);
1802 g_hash_table_insert(ac_funcs, "/avatar", _avatar_autocomplete);
1803 g_hash_table_insert(ac_funcs, "/correction", _correction_autocomplete);
1804 g_hash_table_insert(ac_funcs, "/correct", _correct_autocomplete);
1805 g_hash_table_insert(ac_funcs, "/software", _software_autocomplete);
1806 g_hash_table_insert(ac_funcs, "/url", _url_autocomplete);
1807 g_hash_table_insert(ac_funcs, "/executable", _executable_autocomplete);
1808 g_hash_table_insert(ac_funcs, "/lastactivity", _lastactivity_autocomplete);
1809 g_hash_table_insert(ac_funcs, "/intype", _intype_autocomplete);
1810
1811 int len = strlen(input);
1812 char parsed[len + 1];
1813 int i = 0;
1814 while (i < len) {
1815 if (input[i] == ' ') {
1816 break;
1817 } else {
1818 parsed[i] = input[i];
1819 }
1820 i++;
1821 }
1822 parsed[i] = '\0';
1823
1824 char* (*ac_func)(ProfWin*, const char* const, gboolean) = g_hash_table_lookup(ac_funcs, parsed);
1825 if (ac_func) {
1826 result = ac_func(window, input, previous);
1827 if (result) {
1828 g_hash_table_destroy(ac_funcs);
1829 return result;
1830 }
1831 }
1832 g_hash_table_destroy(ac_funcs);
1833
1834 result = plugins_autocomplete(input, previous);
1835 if (result) {
1836 return result;
1837 }
1838
1839 if (g_str_has_prefix(input, "/field")) {
1840 result = _form_field_autocomplete(window, input, previous);
1841 if (result) {
1842 return result;
1843 }
1844 }
1845
1846 return NULL;
1847 }
1848
1849 static char*
_sub_autocomplete(ProfWin * window,const char * const input,gboolean previous)1850 _sub_autocomplete(ProfWin* window, const char* const input, gboolean previous)
1851 {
1852 char* result = NULL;
1853 result = autocomplete_param_with_func(input, "/sub allow", presence_sub_request_find, previous, NULL);
1854 if (result) {
1855 return result;
1856 }
1857 result = autocomplete_param_with_func(input, "/sub deny", presence_sub_request_find, previous, NULL);
1858 if (result) {
1859 return result;
1860 }
1861 result = autocomplete_param_with_ac(input, "/sub", sub_ac, TRUE, previous);
1862 return result;
1863 }
1864
1865 static char*
_tray_autocomplete(ProfWin * window,const char * const input,gboolean previous)1866 _tray_autocomplete(ProfWin* window, const char* const input, gboolean previous)
1867 {
1868 char* result = NULL;
1869 result = autocomplete_param_with_func(input, "/tray read", prefs_autocomplete_boolean_choice, previous, NULL);
1870 if (result) {
1871 return result;
1872 }
1873
1874 result = autocomplete_param_with_ac(input, "/tray", tray_ac, FALSE, previous);
1875 return result;
1876 }
1877
1878 static char*
_who_autocomplete(ProfWin * window,const char * const input,gboolean previous)1879 _who_autocomplete(ProfWin* window, const char* const input, gboolean previous)
1880 {
1881 char* result = NULL;
1882
1883 if (window->type == WIN_MUC) {
1884 result = autocomplete_param_with_ac(input, "/who", who_room_ac, TRUE, previous);
1885 if (result) {
1886 return result;
1887 }
1888 } else {
1889 jabber_conn_status_t conn_status = connection_get_status();
1890 if (conn_status == JABBER_CONNECTED) {
1891 gchar* group_commands[] = { "/who any", "/who online", "/who offline",
1892 "/who chat", "/who away", "/who xa", "/who dnd", "/who available",
1893 "/who unavailable" };
1894
1895 for (int i = 0; i < ARRAY_SIZE(group_commands); i++) {
1896 result = autocomplete_param_with_func(input, group_commands[i], roster_group_autocomplete, previous, NULL);
1897 if (result) {
1898 return result;
1899 }
1900 }
1901 }
1902
1903 result = autocomplete_param_with_ac(input, "/who", who_roster_ac, TRUE, previous);
1904 }
1905
1906 return result;
1907 }
1908
1909 static char*
_roster_autocomplete(ProfWin * window,const char * const input,gboolean previous)1910 _roster_autocomplete(ProfWin* window, const char* const input, gboolean previous)
1911 {
1912 char* result = NULL;
1913 result = autocomplete_param_with_ac(input, "/roster room private char", roster_char_ac, TRUE, previous);
1914 if (result) {
1915 return result;
1916 }
1917 result = autocomplete_param_with_ac(input, "/roster room private", roster_header_ac, TRUE, previous);
1918 if (result) {
1919 return result;
1920 }
1921 result = autocomplete_param_with_ac(input, "/roster header char", roster_char_ac, TRUE, previous);
1922 if (result) {
1923 return result;
1924 }
1925 result = autocomplete_param_with_ac(input, "/roster contact char", roster_char_ac, TRUE, previous);
1926 if (result) {
1927 return result;
1928 }
1929 result = autocomplete_param_with_ac(input, "/roster room char", roster_char_ac, TRUE, previous);
1930 if (result) {
1931 return result;
1932 }
1933 result = autocomplete_param_with_ac(input, "/roster private char", roster_char_ac, TRUE, previous);
1934 if (result) {
1935 return result;
1936 }
1937 result = autocomplete_param_with_ac(input, "/roster resource char", roster_char_ac, TRUE, previous);
1938 if (result) {
1939 return result;
1940 }
1941 result = autocomplete_param_with_func(input, "/roster resource join", prefs_autocomplete_boolean_choice, previous, NULL);
1942 if (result) {
1943 return result;
1944 }
1945 result = autocomplete_param_with_ac(input, "/roster room position", roster_room_position_ac, TRUE, previous);
1946 if (result) {
1947 return result;
1948 }
1949 result = autocomplete_param_with_ac(input, "/roster room by", roster_room_by_ac, TRUE, previous);
1950 if (result) {
1951 return result;
1952 }
1953 result = autocomplete_param_with_ac(input, "/roster room order", roster_room_order_ac, TRUE, previous);
1954 if (result) {
1955 return result;
1956 }
1957 result = autocomplete_param_with_ac(input, "/roster room unread", roster_unread_ac, TRUE, previous);
1958 if (result) {
1959 return result;
1960 }
1961 result = autocomplete_param_with_ac(input, "/roster room show", roster_room_show_ac, TRUE, previous);
1962 if (result) {
1963 return result;
1964 }
1965 result = autocomplete_param_with_ac(input, "/roster room hide", roster_room_show_ac, TRUE, previous);
1966 if (result) {
1967 return result;
1968 }
1969 result = autocomplete_param_with_ac(input, "/roster room use", roster_room_use_ac, TRUE, previous);
1970 if (result) {
1971 return result;
1972 }
1973 result = autocomplete_param_with_func(input, "/roster count zero", prefs_autocomplete_boolean_choice, previous, NULL);
1974 if (result) {
1975 return result;
1976 }
1977 result = autocomplete_param_with_func(input, "/roster color", prefs_autocomplete_boolean_choice, previous, NULL);
1978 if (result) {
1979 return result;
1980 }
1981
1982 jabber_conn_status_t conn_status = connection_get_status();
1983 if (conn_status == JABBER_CONNECTED) {
1984 result = autocomplete_param_with_func(input, "/roster nick", roster_barejid_autocomplete, previous, NULL);
1985 if (result) {
1986 return result;
1987 }
1988 result = autocomplete_param_with_func(input, "/roster clearnick", roster_barejid_autocomplete, previous, NULL);
1989 if (result) {
1990 return result;
1991 }
1992 result = autocomplete_param_with_func(input, "/roster remove", roster_barejid_autocomplete, previous, NULL);
1993 if (result) {
1994 return result;
1995 }
1996
1997 result = autocomplete_param_with_func(input, "/roster group show", roster_group_autocomplete, previous, NULL);
1998 if (result) {
1999 return result;
2000 }
2001 result = autocomplete_param_no_with_func(input, "/roster group add", 5, roster_contact_autocomplete, previous, NULL);
2002 if (result) {
2003 return result;
2004 }
2005 result = autocomplete_param_no_with_func(input, "/roster group remove", 5, roster_contact_autocomplete, previous, NULL);
2006 if (result) {
2007 return result;
2008 }
2009 result = autocomplete_param_with_func(input, "/roster group add", roster_group_autocomplete, previous, NULL);
2010 if (result) {
2011 return result;
2012 }
2013 result = autocomplete_param_with_func(input, "/roster group remove", roster_group_autocomplete, previous, NULL);
2014 if (result) {
2015 return result;
2016 }
2017 }
2018
2019 result = autocomplete_param_with_ac(input, "/roster remove_all", roster_remove_all_ac, TRUE, previous);
2020 if (result) {
2021 return result;
2022 }
2023 result = autocomplete_param_with_ac(input, "/roster show", roster_show_ac, TRUE, previous);
2024 if (result) {
2025 return result;
2026 }
2027 result = autocomplete_param_with_ac(input, "/roster hide", roster_show_ac, TRUE, previous);
2028 if (result) {
2029 return result;
2030 }
2031 result = autocomplete_param_with_ac(input, "/roster by", roster_by_ac, TRUE, previous);
2032 if (result) {
2033 return result;
2034 }
2035 result = autocomplete_param_with_ac(input, "/roster count", roster_count_ac, TRUE, previous);
2036 if (result) {
2037 return result;
2038 }
2039 result = autocomplete_param_with_ac(input, "/roster order", roster_order_ac, TRUE, previous);
2040 if (result) {
2041 return result;
2042 }
2043 result = autocomplete_param_with_ac(input, "/roster unread", roster_unread_ac, TRUE, previous);
2044 if (result) {
2045 return result;
2046 }
2047 result = autocomplete_param_with_ac(input, "/roster room", roster_room_ac, TRUE, previous);
2048 if (result) {
2049 return result;
2050 }
2051 result = autocomplete_param_with_func(input, "/roster wrap", prefs_autocomplete_boolean_choice, previous, NULL);
2052 if (result) {
2053 return result;
2054 }
2055 result = autocomplete_param_with_ac(input, "/roster header", roster_header_ac, TRUE, previous);
2056 if (result) {
2057 return result;
2058 }
2059 result = autocomplete_param_with_ac(input, "/roster contact", roster_contact_ac, TRUE, previous);
2060 if (result) {
2061 return result;
2062 }
2063 result = autocomplete_param_with_ac(input, "/roster resource", roster_resource_ac, TRUE, previous);
2064 if (result) {
2065 return result;
2066 }
2067 result = autocomplete_param_with_ac(input, "/roster presence", roster_presence_ac, TRUE, previous);
2068 if (result) {
2069 return result;
2070 }
2071 result = autocomplete_param_with_ac(input, "/roster private", roster_private_ac, TRUE, previous);
2072 if (result) {
2073 return result;
2074 }
2075 result = autocomplete_param_with_ac(input, "/roster group", group_ac, TRUE, previous);
2076 if (result) {
2077 return result;
2078 }
2079 result = autocomplete_param_with_ac(input, "/roster", roster_ac, TRUE, previous);
2080 if (result) {
2081 return result;
2082 }
2083
2084 return NULL;
2085 }
2086
2087 static char*
_blocked_autocomplete(ProfWin * window,const char * const input,gboolean previous)2088 _blocked_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2089 {
2090 char* result = NULL;
2091
2092 result = autocomplete_param_with_func(input, "/blocked remove", blocked_ac_find, previous, NULL);
2093 if (result) {
2094 return result;
2095 }
2096
2097 result = autocomplete_param_with_ac(input, "/blocked", blocked_ac, FALSE, previous);
2098 if (result) {
2099 return result;
2100 }
2101
2102 return NULL;
2103 }
2104
2105 static char*
_bookmark_autocomplete(ProfWin * window,const char * const input,gboolean previous)2106 _bookmark_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2107 {
2108 char* found = NULL;
2109
2110 gboolean result;
2111 gchar** args = parse_args(input, 2, 8, &result);
2112
2113 if (result && ((strcmp(args[0], "add") == 0) || (strcmp(args[0], "update") == 0))) {
2114 gboolean space_at_end = g_str_has_suffix(input, " ");
2115 int num_args = g_strv_length(args);
2116 if ((num_args == 2 && space_at_end) || (num_args == 3 && !space_at_end)) {
2117 GString* beginning = g_string_new("/bookmark");
2118 g_string_append_printf(beginning, " %s %s", args[0], args[1]);
2119 found = autocomplete_param_with_ac(input, beginning->str, bookmark_property_ac, TRUE, previous);
2120 g_string_free(beginning, TRUE);
2121 if (found) {
2122 g_strfreev(args);
2123 return found;
2124 }
2125 }
2126 if ((num_args == 3 && space_at_end && (g_strcmp0(args[2], "autojoin") == 0))
2127 || (num_args == 4 && (g_strcmp0(args[2], "autojoin") == 0) && !space_at_end)) {
2128 GString* beginning = g_string_new("/bookmark");
2129 g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]);
2130 found = autocomplete_param_with_func(input, beginning->str, prefs_autocomplete_boolean_choice, previous, NULL);
2131 g_string_free(beginning, TRUE);
2132 if (found) {
2133 g_strfreev(args);
2134 return found;
2135 }
2136 }
2137 if ((num_args == 4 && space_at_end) || (num_args == 5 && !space_at_end)) {
2138 GString* beginning = g_string_new("/bookmark");
2139 g_string_append_printf(beginning, " %s %s %s %s", args[0], args[1], args[2], args[3]);
2140 found = autocomplete_param_with_ac(input, beginning->str, bookmark_property_ac, TRUE, previous);
2141 g_string_free(beginning, TRUE);
2142 if (found) {
2143 g_strfreev(args);
2144 return found;
2145 }
2146 }
2147 if ((num_args == 5 && space_at_end && (g_strcmp0(args[4], "autojoin") == 0))
2148 || (num_args == 6 && (g_strcmp0(args[4], "autojoin") == 0) && !space_at_end)) {
2149 GString* beginning = g_string_new("/bookmark");
2150 g_string_append_printf(beginning, " %s %s %s %s %s", args[0], args[1], args[2], args[3], args[4]);
2151 found = autocomplete_param_with_func(input, beginning->str, prefs_autocomplete_boolean_choice, previous, NULL);
2152 g_string_free(beginning, TRUE);
2153 if (found) {
2154 g_strfreev(args);
2155 return found;
2156 }
2157 }
2158 if ((num_args == 6 && space_at_end) || (num_args == 7 && !space_at_end)) {
2159 GString* beginning = g_string_new("/bookmark");
2160 g_string_append_printf(beginning, " %s %s %s %s %s %s", args[0], args[1], args[2], args[3], args[4], args[5]);
2161 found = autocomplete_param_with_ac(input, beginning->str, bookmark_property_ac, TRUE, previous);
2162 g_string_free(beginning, TRUE);
2163 if (found) {
2164 g_strfreev(args);
2165 return found;
2166 }
2167 }
2168 if ((num_args == 7 && space_at_end && (g_strcmp0(args[6], "autojoin") == 0))
2169 || (num_args == 8 && (g_strcmp0(args[6], "autojoin") == 0) && !space_at_end)) {
2170 GString* beginning = g_string_new("/bookmark");
2171 g_string_append_printf(beginning, " %s %s %s %s %s %s %s", args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
2172 found = autocomplete_param_with_func(input, beginning->str, prefs_autocomplete_boolean_choice, previous, NULL);
2173 g_string_free(beginning, TRUE);
2174 if (found) {
2175 g_strfreev(args);
2176 return found;
2177 }
2178 }
2179 }
2180
2181 g_strfreev(args);
2182
2183 found = autocomplete_param_with_func(input, "/bookmark remove", bookmark_find, previous, NULL);
2184 if (found) {
2185 return found;
2186 }
2187 found = autocomplete_param_with_func(input, "/bookmark join", bookmark_find, previous, NULL);
2188 if (found) {
2189 return found;
2190 }
2191 found = autocomplete_param_with_func(input, "/bookmark update", bookmark_find, previous, NULL);
2192 if (found) {
2193 return found;
2194 }
2195 found = autocomplete_param_with_func(input, "/bookmark invites", prefs_autocomplete_boolean_choice, previous, NULL);
2196 if (found) {
2197 return found;
2198 }
2199
2200 found = autocomplete_param_with_ac(input, "/bookmark ignore", bookmark_ignore_ac, TRUE, previous);
2201 if (found) {
2202 return found;
2203 }
2204 found = autocomplete_param_with_func(input, "/bookmark ignore add", bookmark_find, previous, NULL);
2205 if (found) {
2206 return found;
2207 }
2208 found = autocomplete_param_with_func(input, "/bookmark ignore remove", bookmark_find, previous, NULL);
2209 if (found) {
2210 return found;
2211 }
2212 found = autocomplete_param_with_func(input, "/bookmark list", bookmark_find, previous, NULL);
2213 if (found) {
2214 return found;
2215 }
2216
2217 found = autocomplete_param_with_ac(input, "/bookmark", bookmark_ac, TRUE, previous);
2218 return found;
2219 }
2220
2221 static char*
_notify_autocomplete(ProfWin * window,const char * const input,gboolean previous)2222 _notify_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2223 {
2224 char* result = NULL;
2225
2226 result = autocomplete_param_with_func(input, "/notify room trigger remove", prefs_autocomplete_room_trigger, previous, NULL);
2227 if (result) {
2228 return result;
2229 }
2230
2231 gchar* boolean_choices1[] = { "/notify room current", "/notify chat current", "/notify typing current",
2232 "/notify room text", "/notify chat text" };
2233 for (int i = 0; i < ARRAY_SIZE(boolean_choices1); i++) {
2234 result = autocomplete_param_with_func(input, boolean_choices1[i], prefs_autocomplete_boolean_choice, previous, NULL);
2235 if (result) {
2236 return result;
2237 }
2238 }
2239
2240 result = autocomplete_param_with_ac(input, "/notify room mention", notify_mention_ac, TRUE, previous);
2241 if (result) {
2242 return result;
2243 }
2244
2245 result = autocomplete_param_with_ac(input, "/notify room trigger", notify_trigger_ac, TRUE, previous);
2246 if (result) {
2247 return result;
2248 }
2249
2250 result = autocomplete_param_with_ac(input, "/notify room", notify_room_ac, TRUE, previous);
2251 if (result) {
2252 return result;
2253 }
2254
2255 result = autocomplete_param_with_ac(input, "/notify chat", notify_chat_ac, TRUE, previous);
2256 if (result) {
2257 return result;
2258 }
2259
2260 result = autocomplete_param_with_ac(input, "/notify typing", notify_typing_ac, TRUE, previous);
2261 if (result) {
2262 return result;
2263 }
2264
2265 gchar* boolean_choices2[] = { "/notify invite", "/notify sub", "/notify mention", "/notify trigger" };
2266 for (int i = 0; i < ARRAY_SIZE(boolean_choices2); i++) {
2267 result = autocomplete_param_with_func(input, boolean_choices2[i], prefs_autocomplete_boolean_choice, previous, NULL);
2268 if (result) {
2269 return result;
2270 }
2271 }
2272
2273 result = autocomplete_param_with_ac(input, "/notify", notify_ac, TRUE, previous);
2274 if (result) {
2275 return result;
2276 }
2277
2278 return NULL;
2279 }
2280
2281 static char*
_autoaway_autocomplete(ProfWin * window,const char * const input,gboolean previous)2282 _autoaway_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2283 {
2284 char* result = NULL;
2285
2286 result = autocomplete_param_with_ac(input, "/autoaway mode", autoaway_mode_ac, TRUE, previous);
2287 if (result) {
2288 return result;
2289 }
2290
2291 result = autocomplete_param_with_ac(input, "/autoaway time", autoaway_presence_ac, TRUE, previous);
2292 if (result) {
2293 return result;
2294 }
2295
2296 result = autocomplete_param_with_ac(input, "/autoaway message", autoaway_presence_ac, TRUE, previous);
2297 if (result) {
2298 return result;
2299 }
2300
2301 result = autocomplete_param_with_func(input, "/autoaway check", prefs_autocomplete_boolean_choice, previous, NULL);
2302 if (result) {
2303 return result;
2304 }
2305 result = autocomplete_param_with_ac(input, "/autoaway", autoaway_ac, TRUE, previous);
2306 if (result) {
2307 return result;
2308 }
2309
2310 return NULL;
2311 }
2312
2313 static char*
_log_autocomplete(ProfWin * window,const char * const input,gboolean previous)2314 _log_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2315 {
2316 char* result = NULL;
2317
2318 result = autocomplete_param_with_func(input, "/log rotate", prefs_autocomplete_boolean_choice, previous, NULL);
2319 if (result) {
2320 return result;
2321 }
2322 result = autocomplete_param_with_func(input, "/log shared", prefs_autocomplete_boolean_choice, previous, NULL);
2323 if (result) {
2324 return result;
2325 }
2326 result = autocomplete_param_with_ac(input, "/log", log_ac, TRUE, previous);
2327 if (result) {
2328 return result;
2329 }
2330
2331 return NULL;
2332 }
2333
2334 static char*
_autoconnect_autocomplete(ProfWin * window,const char * const input,gboolean previous)2335 _autoconnect_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2336 {
2337 char* result = NULL;
2338
2339 result = autocomplete_param_with_func(input, "/autoconnect set", accounts_find_enabled, previous, NULL);
2340 if (result) {
2341 return result;
2342 }
2343
2344 result = autocomplete_param_with_ac(input, "/autoconnect", autoconnect_ac, TRUE, previous);
2345 if (result) {
2346 return result;
2347 }
2348
2349 return NULL;
2350 }
2351
2352 #ifdef HAVE_LIBOTR
2353 static char*
_otr_autocomplete(ProfWin * window,const char * const input,gboolean previous)2354 _otr_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2355 {
2356 char* found = NULL;
2357
2358 jabber_conn_status_t conn_status = connection_get_status();
2359
2360 if (conn_status == JABBER_CONNECTED) {
2361 found = autocomplete_param_with_func(input, "/otr start", roster_contact_autocomplete, previous, NULL);
2362 if (found) {
2363 return found;
2364 }
2365 }
2366
2367 found = autocomplete_param_with_ac(input, "/otr log", otr_log_ac, TRUE, previous);
2368 if (found) {
2369 return found;
2370 }
2371
2372 // /otr policy always user@server.com
2373 if (conn_status == JABBER_CONNECTED) {
2374 gboolean result;
2375 gchar** args = parse_args(input, 2, 3, &result);
2376 if (result && (strcmp(args[0], "policy") == 0)) {
2377 GString* beginning = g_string_new("/otr ");
2378 g_string_append(beginning, args[0]);
2379 g_string_append(beginning, " ");
2380 if (args[1]) {
2381 g_string_append(beginning, args[1]);
2382 }
2383
2384 found = autocomplete_param_with_func(input, beginning->str, roster_contact_autocomplete, previous, NULL);
2385 g_string_free(beginning, TRUE);
2386 if (found) {
2387 g_strfreev(args);
2388 return found;
2389 }
2390 }
2391 g_strfreev(args);
2392 }
2393
2394 found = autocomplete_param_with_ac(input, "/otr policy", otr_policy_ac, TRUE, previous);
2395 if (found) {
2396 return found;
2397 }
2398
2399 found = autocomplete_param_with_ac(input, "/otr sendfile", otr_sendfile_ac, TRUE, previous);
2400 if (found) {
2401 return found;
2402 }
2403
2404 found = autocomplete_param_with_ac(input, "/otr", otr_ac, TRUE, previous);
2405 if (found) {
2406 return found;
2407 }
2408
2409 return NULL;
2410 }
2411 #endif
2412
2413 #ifdef HAVE_LIBGPGME
2414 static char*
_pgp_autocomplete(ProfWin * window,const char * const input,gboolean previous)2415 _pgp_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2416 {
2417 char* found = NULL;
2418
2419 jabber_conn_status_t conn_status = connection_get_status();
2420
2421 if (conn_status == JABBER_CONNECTED) {
2422 found = autocomplete_param_with_func(input, "/pgp start", roster_contact_autocomplete, previous, NULL);
2423 if (found) {
2424 return found;
2425 }
2426 }
2427
2428 found = autocomplete_param_with_ac(input, "/pgp log", pgp_log_ac, TRUE, previous);
2429 if (found) {
2430 return found;
2431 }
2432
2433 found = autocomplete_param_with_ac(input, "/pgp sendfile", pgp_sendfile_ac, TRUE, previous);
2434 if (found) {
2435 return found;
2436 }
2437
2438 gboolean result;
2439 gchar** args = parse_args(input, 2, 3, &result);
2440 if ((strncmp(input, "/pgp", 4) == 0) && (result == TRUE)) {
2441 GString* beginning = g_string_new("/pgp ");
2442 g_string_append(beginning, args[0]);
2443 if (args[1]) {
2444 g_string_append(beginning, " ");
2445 g_string_append(beginning, args[1]);
2446 }
2447 found = autocomplete_param_with_func(input, beginning->str, p_gpg_autocomplete_key, previous, NULL);
2448 g_string_free(beginning, TRUE);
2449 if (found) {
2450 g_strfreev(args);
2451 return found;
2452 }
2453 }
2454 g_strfreev(args);
2455
2456 if (conn_status == JABBER_CONNECTED) {
2457 found = autocomplete_param_with_func(input, "/pgp setkey", roster_barejid_autocomplete, previous, NULL);
2458 if (found) {
2459 return found;
2460 }
2461 }
2462
2463 found = autocomplete_param_with_ac(input, "/pgp", pgp_ac, TRUE, previous);
2464 if (found) {
2465 return found;
2466 }
2467
2468 return NULL;
2469 }
2470
2471 /*!
2472 * \brief Auto completion for XEP-0373: OpenPGP for XMPP command.
2473 *
2474 *
2475 */
2476 static char*
_ox_autocomplete(ProfWin * window,const char * const input,gboolean previous)2477 _ox_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2478 {
2479 char* found = NULL;
2480
2481 jabber_conn_status_t conn_status = connection_get_status();
2482
2483 if (conn_status == JABBER_CONNECTED) {
2484 found = autocomplete_param_with_func(input, "/ox start", roster_contact_autocomplete, previous, NULL);
2485 if (found) {
2486 return found;
2487 }
2488 }
2489
2490 if (conn_status == JABBER_CONNECTED) {
2491 found = autocomplete_param_with_func(input, "/ox discover", roster_contact_autocomplete, previous, NULL);
2492 if (found) {
2493 return found;
2494 }
2495 }
2496
2497 found = autocomplete_param_with_ac(input, "/ox log", ox_log_ac, TRUE, previous);
2498 if (found) {
2499 return found;
2500 }
2501
2502 found = autocomplete_param_with_ac(input, "/ox sendfile", ox_sendfile_ac, TRUE, previous);
2503 if (found) {
2504 return found;
2505 }
2506
2507 gboolean result;
2508 gchar** args = parse_args(input, 2, 3, &result);
2509 if ((strncmp(input, "/ox", 4) == 0) && (result == TRUE)) {
2510 GString* beginning = g_string_new("/ox ");
2511 g_string_append(beginning, args[0]);
2512 if (args[1]) {
2513 g_string_append(beginning, " ");
2514 g_string_append(beginning, args[1]);
2515 }
2516 found = autocomplete_param_with_func(input, beginning->str, p_gpg_autocomplete_key, previous, NULL);
2517 g_string_free(beginning, TRUE);
2518 if (found) {
2519 g_strfreev(args);
2520 return found;
2521 }
2522 }
2523 g_strfreev(args);
2524
2525 if (conn_status == JABBER_CONNECTED) {
2526 found = autocomplete_param_with_func(input, "/ox setkey", roster_barejid_autocomplete, previous, NULL);
2527 if (found) {
2528 return found;
2529 }
2530 }
2531
2532 found = autocomplete_param_with_ac(input, "/ox", ox_ac, TRUE, previous);
2533
2534 return found;
2535 }
2536 #endif
2537
2538 #ifdef HAVE_OMEMO
2539 static char*
_omemo_autocomplete(ProfWin * window,const char * const input,gboolean previous)2540 _omemo_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2541 {
2542 char* found = NULL;
2543
2544 found = autocomplete_param_with_ac(input, "/omemo log", omemo_log_ac, TRUE, previous);
2545 if (found) {
2546 return found;
2547 }
2548
2549 found = autocomplete_param_with_ac(input, "/omemo policy", omemo_policy_ac, TRUE, previous);
2550 if (found) {
2551 return found;
2552 }
2553
2554 found = autocomplete_param_with_ac(input, "/omemo trustmode", omemo_trustmode_ac, TRUE, previous);
2555 if (found) {
2556 return found;
2557 }
2558
2559 jabber_conn_status_t conn_status = connection_get_status();
2560
2561 if (conn_status == JABBER_CONNECTED) {
2562 found = autocomplete_param_with_func(input, "/omemo start", roster_contact_autocomplete, previous, NULL);
2563 if (found) {
2564 return found;
2565 }
2566
2567 found = autocomplete_param_with_func(input, "/omemo fingerprint", roster_contact_autocomplete, previous, NULL);
2568 if (found) {
2569 return found;
2570 }
2571
2572 if (window->type == WIN_CHAT) {
2573 ProfChatWin* chatwin = (ProfChatWin*)window;
2574 assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
2575 found = autocomplete_param_with_func(input, "/omemo trust", omemo_fingerprint_autocomplete, previous, chatwin->barejid);
2576 if (found) {
2577 return found;
2578 }
2579 } else {
2580 found = autocomplete_param_with_func(input, "/omemo trust", roster_contact_autocomplete, previous, NULL);
2581 if (found) {
2582 return found;
2583 }
2584
2585 int num_tokens = count_tokens(input);
2586 if (num_tokens == 4) {
2587 gboolean result;
2588 gchar** args = parse_args(input, 2, 3, &result);
2589 if (result) {
2590 gchar* jid = g_strdup(args[1]);
2591 found = autocomplete_param_no_with_func(input, "/omemo trust", 4, omemo_fingerprint_autocomplete, previous, jid);
2592 if (found) {
2593 return found;
2594 }
2595 }
2596 }
2597 }
2598
2599 if (window->type == WIN_CHAT) {
2600 ProfChatWin* chatwin = (ProfChatWin*)window;
2601 assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
2602 found = autocomplete_param_with_func(input, "/omemo untrust", omemo_fingerprint_autocomplete, previous, chatwin->barejid);
2603 if (found) {
2604 return found;
2605 }
2606 } else {
2607 found = autocomplete_param_with_func(input, "/omemo untrust", roster_contact_autocomplete, previous, NULL);
2608 if (found) {
2609 return found;
2610 }
2611
2612 int num_tokens = count_tokens(input);
2613 if (num_tokens == 4) {
2614 gboolean result;
2615 gchar** args = parse_args(input, 2, 3, &result);
2616 if (result) {
2617 gchar* jid = g_strdup(args[1]);
2618 found = autocomplete_param_no_with_func(input, "/omemo untrust", 4, omemo_fingerprint_autocomplete, previous, jid);
2619 if (found) {
2620 return found;
2621 }
2622 }
2623 }
2624 }
2625 }
2626
2627 found = autocomplete_param_with_ac(input, "/omemo", omemo_ac, TRUE, previous);
2628 if (found) {
2629 return found;
2630 }
2631
2632 return NULL;
2633 }
2634 #endif
2635
2636 static char*
_plugins_autocomplete(ProfWin * window,const char * const input,gboolean previous)2637 _plugins_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2638 {
2639 char* result = NULL;
2640
2641 if (strncmp(input, "/plugins sourcepath set ", 24) == 0) {
2642 return cmd_ac_complete_filepath(input, "/plugins sourcepath set", previous);
2643 }
2644
2645 if (strncmp(input, "/plugins install ", 17) == 0) {
2646 return cmd_ac_complete_filepath(input, "/plugins install", previous);
2647 }
2648
2649 if (strncmp(input, "/plugins sourcepath ", 20) == 0) {
2650 result = autocomplete_param_with_ac(input, "/plugins sourcepath", plugins_sourcepath_ac, TRUE, previous);
2651 if (result) {
2652 return result;
2653 }
2654 }
2655
2656 if (strncmp(input, "/plugins load ", 14) == 0) {
2657 if (plugins_load_ac == NULL) {
2658 plugins_load_ac = autocomplete_new();
2659 GSList* plugins = plugins_unloaded_list();
2660 GSList* curr = plugins;
2661 while (curr) {
2662 autocomplete_add(plugins_load_ac, curr->data);
2663 curr = g_slist_next(curr);
2664 }
2665 g_slist_free_full(plugins, g_free);
2666 }
2667 result = autocomplete_param_with_ac(input, "/plugins load", plugins_load_ac, TRUE, previous);
2668 if (result) {
2669 return result;
2670 }
2671 }
2672
2673 if (strncmp(input, "/plugins reload ", 16) == 0) {
2674 if (plugins_reload_ac == NULL) {
2675 plugins_reload_ac = autocomplete_new();
2676 GList* plugins = plugins_loaded_list();
2677 GList* curr = plugins;
2678 while (curr) {
2679 autocomplete_add(plugins_reload_ac, curr->data);
2680 curr = g_list_next(curr);
2681 }
2682 g_list_free(plugins);
2683 }
2684 result = autocomplete_param_with_ac(input, "/plugins reload", plugins_reload_ac, TRUE, previous);
2685 if (result) {
2686 return result;
2687 }
2688 }
2689
2690 if (strncmp(input, "/plugins unload ", 16) == 0) {
2691 if (plugins_unload_ac == NULL) {
2692 plugins_unload_ac = autocomplete_new();
2693 GList* plugins = plugins_loaded_list();
2694 GList* curr = plugins;
2695 while (curr) {
2696 autocomplete_add(plugins_unload_ac, curr->data);
2697 curr = g_list_next(curr);
2698 }
2699 g_list_free(plugins);
2700 }
2701 result = autocomplete_param_with_ac(input, "/plugins unload", plugins_unload_ac, TRUE, previous);
2702 if (result) {
2703 return result;
2704 }
2705 }
2706
2707 result = autocomplete_param_with_ac(input, "/plugins", plugins_ac, TRUE, previous);
2708 if (result) {
2709 return result;
2710 }
2711
2712 return NULL;
2713 }
2714
2715 static char*
_theme_autocomplete(ProfWin * window,const char * const input,gboolean previous)2716 _theme_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2717 {
2718 char* result = NULL;
2719
2720 if (strncmp(input, "/theme load ", 12) == 0) {
2721 if (theme_load_ac == NULL) {
2722 theme_load_ac = autocomplete_new();
2723 GSList* themes = theme_list();
2724 GSList* curr = themes;
2725
2726 while (curr) {
2727 autocomplete_add(theme_load_ac, curr->data);
2728 curr = g_slist_next(curr);
2729 }
2730
2731 g_slist_free_full(themes, g_free);
2732 autocomplete_add(theme_load_ac, "default");
2733 }
2734
2735 result = autocomplete_param_with_ac(input, "/theme load", theme_load_ac, TRUE, previous);
2736 if (result) {
2737 return result;
2738 }
2739 }
2740
2741 if (strncmp(input, "/theme full-load ", 17) == 0) {
2742 if (theme_load_ac == NULL) {
2743 theme_load_ac = autocomplete_new();
2744 GSList* themes = theme_list();
2745 GSList* curr = themes;
2746
2747 while (curr) {
2748 autocomplete_add(theme_load_ac, curr->data);
2749 curr = g_slist_next(curr);
2750 }
2751
2752 g_slist_free_full(themes, g_free);
2753 autocomplete_add(theme_load_ac, "default");
2754 }
2755
2756 result = autocomplete_param_with_ac(input, "/theme full-load", theme_load_ac, TRUE, previous);
2757 if (result) {
2758 return result;
2759 }
2760 }
2761
2762 result = autocomplete_param_with_ac(input, "/theme", theme_ac, TRUE, previous);
2763 if (result) {
2764 return result;
2765 }
2766
2767 return NULL;
2768 }
2769
2770 static char*
_script_autocomplete_func(const char * const prefix,gboolean previous,void * context)2771 _script_autocomplete_func(const char* const prefix, gboolean previous, void* context)
2772 {
2773 if (script_show_ac == NULL) {
2774 script_show_ac = autocomplete_new();
2775 GSList* scripts = scripts_list();
2776 GSList* curr = scripts;
2777 while (curr) {
2778 autocomplete_add(script_show_ac, curr->data);
2779 curr = g_slist_next(curr);
2780 }
2781 g_slist_free_full(scripts, g_free);
2782 }
2783
2784 return autocomplete_complete(script_show_ac, prefix, FALSE, previous);
2785 }
2786
2787 static char*
_script_autocomplete(ProfWin * window,const char * const input,gboolean previous)2788 _script_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2789 {
2790 char* result = NULL;
2791 if (strncmp(input, "/script show ", 13) == 0) {
2792 result = autocomplete_param_with_func(input, "/script show", _script_autocomplete_func, previous, NULL);
2793 if (result) {
2794 return result;
2795 }
2796 }
2797
2798 if (strncmp(input, "/script run ", 12) == 0) {
2799 result = autocomplete_param_with_func(input, "/script run", _script_autocomplete_func, previous, NULL);
2800 if (result) {
2801 return result;
2802 }
2803 }
2804
2805 result = autocomplete_param_with_ac(input, "/script", script_ac, TRUE, previous);
2806 if (result) {
2807 return result;
2808 }
2809
2810 return NULL;
2811 }
2812
2813 static char*
_resource_autocomplete(ProfWin * window,const char * const input,gboolean previous)2814 _resource_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2815 {
2816 char* found = NULL;
2817
2818 jabber_conn_status_t conn_status = connection_get_status();
2819 if (conn_status == JABBER_CONNECTED && window->type == WIN_CHAT) {
2820 ProfChatWin* chatwin = (ProfChatWin*)window;
2821 assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
2822 PContact contact = roster_get_contact(chatwin->barejid);
2823 if (contact) {
2824 Autocomplete ac = p_contact_resource_ac(contact);
2825 found = autocomplete_param_with_ac(input, "/resource set", ac, FALSE, previous);
2826 if (found) {
2827 return found;
2828 }
2829 }
2830 }
2831
2832 found = autocomplete_param_with_func(input, "/resource title", prefs_autocomplete_boolean_choice, previous, NULL);
2833 if (found) {
2834 return found;
2835 }
2836
2837 found = autocomplete_param_with_func(input, "/resource message", prefs_autocomplete_boolean_choice, previous, NULL);
2838 if (found) {
2839 return found;
2840 }
2841
2842 found = autocomplete_param_with_ac(input, "/resource", resource_ac, FALSE, previous);
2843 if (found) {
2844 return found;
2845 }
2846
2847 return NULL;
2848 }
2849
2850 static char*
_wintitle_autocomplete(ProfWin * window,const char * const input,gboolean previous)2851 _wintitle_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2852 {
2853 char* found = NULL;
2854
2855 found = autocomplete_param_with_func(input, "/wintitle show", prefs_autocomplete_boolean_choice, previous, NULL);
2856 if (found) {
2857 return found;
2858 }
2859
2860 found = autocomplete_param_with_func(input, "/wintitle goodbye", prefs_autocomplete_boolean_choice, previous, NULL);
2861 if (found) {
2862 return found;
2863 }
2864
2865 found = autocomplete_param_with_ac(input, "/wintitle", wintitle_ac, FALSE, previous);
2866 if (found) {
2867 return found;
2868 }
2869
2870 return NULL;
2871 }
2872
2873 static char*
_inpblock_autocomplete(ProfWin * window,const char * const input,gboolean previous)2874 _inpblock_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2875 {
2876 char* found = NULL;
2877
2878 found = autocomplete_param_with_func(input, "/inpblock dynamic", prefs_autocomplete_boolean_choice, previous, NULL);
2879 if (found) {
2880 return found;
2881 }
2882
2883 found = autocomplete_param_with_ac(input, "/inpblock", inpblock_ac, FALSE, previous);
2884 if (found) {
2885 return found;
2886 }
2887
2888 return NULL;
2889 }
2890
2891 static char*
_form_autocomplete(ProfWin * window,const char * const input,gboolean previous)2892 _form_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2893 {
2894 if (window->type != WIN_CONFIG) {
2895 return NULL;
2896 }
2897
2898 char* found = NULL;
2899
2900 ProfConfWin* confwin = (ProfConfWin*)window;
2901 DataForm* form = confwin->form;
2902 if (form) {
2903 found = autocomplete_param_with_ac(input, "/form help", form->tag_ac, TRUE, previous);
2904 if (found) {
2905 return found;
2906 }
2907 }
2908
2909 found = autocomplete_param_with_ac(input, "/form", form_ac, TRUE, previous);
2910 if (found) {
2911 return found;
2912 }
2913
2914 return NULL;
2915 }
2916
2917 static char*
_form_field_autocomplete(ProfWin * window,const char * const input,gboolean previous)2918 _form_field_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2919 {
2920 if (window->type != WIN_CONFIG) {
2921 return NULL;
2922 }
2923
2924 char* found = NULL;
2925
2926 ProfConfWin* confwin = (ProfConfWin*)window;
2927 DataForm* form = confwin->form;
2928 if (form == NULL) {
2929 return NULL;
2930 }
2931
2932 gchar** split = g_strsplit(input, " ", 0);
2933
2934 if (g_strv_length(split) == 3) {
2935 char* field_tag = split[0] + 1;
2936 if (form_tag_exists(form, field_tag)) {
2937 form_field_type_t field_type = form_get_field_type(form, field_tag);
2938 Autocomplete value_ac = form_get_value_ac(form, field_tag);
2939 ;
2940 GString* beginning = g_string_new(split[0]);
2941 g_string_append(beginning, " ");
2942 g_string_append(beginning, split[1]);
2943
2944 if (((g_strcmp0(split[1], "add") == 0) || (g_strcmp0(split[1], "remove") == 0))
2945 && field_type == FIELD_LIST_MULTI) {
2946 found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE, previous);
2947
2948 } else if ((g_strcmp0(split[1], "remove") == 0) && field_type == FIELD_TEXT_MULTI) {
2949 found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE, previous);
2950
2951 } else if ((g_strcmp0(split[1], "remove") == 0) && field_type == FIELD_JID_MULTI) {
2952 found = autocomplete_param_with_ac(input, beginning->str, value_ac, TRUE, previous);
2953 }
2954
2955 g_string_free(beginning, TRUE);
2956 }
2957
2958 } else if (g_strv_length(split) == 2) {
2959 char* field_tag = split[0] + 1;
2960 if (form_tag_exists(form, field_tag)) {
2961 form_field_type_t field_type = form_get_field_type(form, field_tag);
2962 Autocomplete value_ac = form_get_value_ac(form, field_tag);
2963 ;
2964
2965 switch (field_type) {
2966 case FIELD_BOOLEAN:
2967 found = autocomplete_param_with_func(input, split[0], prefs_autocomplete_boolean_choice, previous, NULL);
2968 break;
2969 case FIELD_LIST_SINGLE:
2970 found = autocomplete_param_with_ac(input, split[0], value_ac, TRUE, previous);
2971 break;
2972 case FIELD_LIST_MULTI:
2973 case FIELD_JID_MULTI:
2974 case FIELD_TEXT_MULTI:
2975 found = autocomplete_param_with_ac(input, split[0], form_field_multi_ac, TRUE, previous);
2976 break;
2977 default:
2978 break;
2979 }
2980 }
2981 }
2982
2983 g_strfreev(split);
2984
2985 return found;
2986 }
2987
2988 static char*
_occupants_autocomplete(ProfWin * window,const char * const input,gboolean previous)2989 _occupants_autocomplete(ProfWin* window, const char* const input, gboolean previous)
2990 {
2991 char* found = NULL;
2992
2993 found = autocomplete_param_with_ac(input, "/occupants default show", occupants_show_ac, TRUE, previous);
2994 if (found) {
2995 return found;
2996 }
2997
2998 found = autocomplete_param_with_ac(input, "/occupants char", occupants_char_ac, TRUE, previous);
2999 if (found) {
3000 return found;
3001 }
3002
3003 found = autocomplete_param_with_func(input, "/occupants color", prefs_autocomplete_boolean_choice, previous, NULL);
3004 if (found) {
3005 return found;
3006 }
3007
3008 found = autocomplete_param_with_ac(input, "/occupants default hide", occupants_show_ac, TRUE, previous);
3009 if (found) {
3010 return found;
3011 }
3012
3013 found = autocomplete_param_with_ac(input, "/occupants default", occupants_default_ac, TRUE, previous);
3014 if (found) {
3015 return found;
3016 }
3017
3018 found = autocomplete_param_with_ac(input, "/occupants show", occupants_show_ac, TRUE, previous);
3019 if (found) {
3020 return found;
3021 }
3022
3023 found = autocomplete_param_with_ac(input, "/occupants hide", occupants_show_ac, TRUE, previous);
3024 if (found) {
3025 return found;
3026 }
3027
3028 found = autocomplete_param_with_ac(input, "/occupants header char", roster_char_ac, TRUE, previous);
3029 if (found) {
3030 return found;
3031 }
3032
3033 found = autocomplete_param_with_ac(input, "/occupants header", occupants_header_ac, TRUE, previous);
3034 if (found) {
3035 return found;
3036 }
3037
3038 found = autocomplete_param_with_func(input, "/occupants wrap", prefs_autocomplete_boolean_choice, previous, NULL);
3039 if (found) {
3040 return found;
3041 }
3042
3043 found = autocomplete_param_with_ac(input, "/occupants", occupants_ac, TRUE, previous);
3044 if (found) {
3045 return found;
3046 }
3047
3048 return NULL;
3049 }
3050
3051 static char*
_time_autocomplete(ProfWin * window,const char * const input,gboolean previous)3052 _time_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3053 {
3054 char* found = NULL;
3055
3056 found = autocomplete_param_with_ac(input, "/time statusbar", time_format_ac, TRUE, previous);
3057 if (found) {
3058 return found;
3059 }
3060
3061 found = autocomplete_param_with_ac(input, "/time lastactivity", time_format_ac, TRUE, previous);
3062 if (found) {
3063 return found;
3064 }
3065
3066 found = autocomplete_param_with_ac(input, "/time console", time_format_ac, TRUE, previous);
3067 if (found) {
3068 return found;
3069 }
3070
3071 found = autocomplete_param_with_ac(input, "/time chat", time_format_ac, TRUE, previous);
3072 if (found) {
3073 return found;
3074 }
3075
3076 found = autocomplete_param_with_ac(input, "/time muc", time_format_ac, TRUE, previous);
3077 if (found) {
3078 return found;
3079 }
3080
3081 found = autocomplete_param_with_ac(input, "/time config", time_format_ac, TRUE, previous);
3082 if (found) {
3083 return found;
3084 }
3085
3086 found = autocomplete_param_with_ac(input, "/time private", time_format_ac, TRUE, previous);
3087 if (found) {
3088 return found;
3089 }
3090
3091 found = autocomplete_param_with_ac(input, "/time xml", time_format_ac, TRUE, previous);
3092 if (found) {
3093 return found;
3094 }
3095
3096 found = autocomplete_param_with_ac(input, "/time all", time_format_ac, TRUE, previous);
3097 if (found) {
3098 return found;
3099 }
3100
3101 found = autocomplete_param_with_ac(input, "/time", time_ac, TRUE, previous);
3102 if (found) {
3103 return found;
3104 }
3105
3106 return NULL;
3107 }
3108
3109 static char*
_kick_autocomplete(ProfWin * window,const char * const input,gboolean previous)3110 _kick_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3111 {
3112 if (window->type != WIN_MUC) {
3113 return NULL;
3114 }
3115
3116 ProfMucWin* mucwin = (ProfMucWin*)window;
3117 assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
3118 Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid);
3119 if (nick_ac == NULL) {
3120 return NULL;
3121 }
3122
3123 char* result = autocomplete_param_with_ac(input, "/kick", nick_ac, TRUE, previous);
3124
3125 return result;
3126 }
3127
3128 static char*
_ban_autocomplete(ProfWin * window,const char * const input,gboolean previous)3129 _ban_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3130 {
3131 if (window->type != WIN_MUC) {
3132 return NULL;
3133 }
3134
3135 ProfMucWin* mucwin = (ProfMucWin*)window;
3136 assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
3137 Autocomplete jid_ac = muc_roster_jid_ac(mucwin->roomjid);
3138 if (jid_ac == NULL) {
3139 return NULL;
3140 }
3141
3142 char* result = autocomplete_param_with_ac(input, "/ban", jid_ac, TRUE, previous);
3143
3144 return result;
3145 }
3146
3147 static char*
_affiliation_autocomplete(ProfWin * window,const char * const input,gboolean previous)3148 _affiliation_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3149 {
3150 char* result = NULL;
3151
3152 if (window->type == WIN_MUC) {
3153 ProfMucWin* mucwin = (ProfMucWin*)window;
3154 assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
3155 gboolean parse_result;
3156 Autocomplete jid_ac = muc_roster_jid_ac(mucwin->roomjid);
3157
3158 gchar** args = parse_args(input, 2, 3, &parse_result);
3159
3160 if ((strncmp(input, "/affiliation", 12) == 0) && (parse_result == TRUE)) {
3161 GString* beginning = g_string_new("/affiliation ");
3162 g_string_append(beginning, args[0]);
3163 g_string_append(beginning, " ");
3164 if (args[1]) {
3165 g_string_append(beginning, args[1]);
3166 }
3167
3168 result = autocomplete_param_with_ac(input, beginning->str, jid_ac, TRUE, previous);
3169 g_string_free(beginning, TRUE);
3170 if (result) {
3171 g_strfreev(args);
3172 return result;
3173 }
3174 }
3175
3176 g_strfreev(args);
3177 }
3178
3179 result = autocomplete_param_with_ac(input, "/affiliation set", affiliation_ac, TRUE, previous);
3180 if (result) {
3181 return result;
3182 }
3183
3184 result = autocomplete_param_with_ac(input, "/affiliation list", affiliation_ac, TRUE, previous);
3185 if (result) {
3186 return result;
3187 }
3188
3189 result = autocomplete_param_with_ac(input, "/affiliation", affiliation_cmd_ac, TRUE, previous);
3190
3191 return result;
3192 }
3193
3194 static char*
_role_autocomplete(ProfWin * window,const char * const input,gboolean previous)3195 _role_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3196 {
3197 char* result = NULL;
3198
3199 if (window->type == WIN_MUC) {
3200 ProfMucWin* mucwin = (ProfMucWin*)window;
3201 assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
3202 gboolean parse_result;
3203 Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid);
3204
3205 gchar** args = parse_args(input, 2, 3, &parse_result);
3206
3207 if ((strncmp(input, "/role", 5) == 0) && (parse_result == TRUE)) {
3208 GString* beginning = g_string_new("/role ");
3209 g_string_append(beginning, args[0]);
3210 g_string_append(beginning, " ");
3211 if (args[1]) {
3212 g_string_append(beginning, args[1]);
3213 }
3214
3215 result = autocomplete_param_with_ac(input, beginning->str, nick_ac, TRUE, previous);
3216 g_string_free(beginning, TRUE);
3217 if (result) {
3218 g_strfreev(args);
3219 return result;
3220 }
3221 }
3222
3223 g_strfreev(args);
3224 }
3225
3226 result = autocomplete_param_with_ac(input, "/role set", role_ac, TRUE, previous);
3227 if (result) {
3228 return result;
3229 }
3230
3231 result = autocomplete_param_with_ac(input, "/role list", role_ac, TRUE, previous);
3232 if (result) {
3233 return result;
3234 }
3235
3236 result = autocomplete_param_with_ac(input, "/role", role_cmd_ac, TRUE, previous);
3237
3238 return result;
3239 }
3240
3241 static char*
_wins_autocomplete(ProfWin * window,const char * const input,gboolean previous)3242 _wins_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3243 {
3244 char* result = NULL;
3245
3246 result = autocomplete_param_with_ac(input, "/wins", wins_ac, TRUE, previous);
3247
3248 return result;
3249 }
3250
3251 static char*
_tls_autocomplete(ProfWin * window,const char * const input,gboolean previous)3252 _tls_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3253 {
3254 char* result = NULL;
3255
3256 result = autocomplete_param_with_func(input, "/tls revoke", tlscerts_complete, previous, NULL);
3257 if (result) {
3258 return result;
3259 }
3260
3261 result = autocomplete_param_with_func(input, "/tls cert", tlscerts_complete, previous, NULL);
3262 if (result) {
3263 return result;
3264 }
3265
3266 result = autocomplete_param_with_ac(input, "/tls certpath", tls_certpath_ac, TRUE, previous);
3267 if (result) {
3268 return result;
3269 }
3270
3271 result = autocomplete_param_with_ac(input, "/tls", tls_ac, TRUE, previous);
3272
3273 return result;
3274 }
3275
3276 static char*
_titlebar_autocomplete(ProfWin * window,const char * const input,gboolean previous)3277 _titlebar_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3278 {
3279 char* result = NULL;
3280
3281 result = autocomplete_param_with_ac(input, "/titlebar show", titlebar_show_ac, TRUE, previous);
3282 if (result) {
3283 return result;
3284 }
3285
3286 result = autocomplete_param_with_ac(input, "/titlebar hide", titlebar_show_ac, TRUE, previous);
3287 if (result) {
3288 return result;
3289 }
3290
3291 result = autocomplete_param_with_ac(input, "/titlebar", titlebar_ac, TRUE, previous);
3292
3293 return result;
3294 }
3295
3296 static char*
_receipts_autocomplete(ProfWin * window,const char * const input,gboolean previous)3297 _receipts_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3298 {
3299 char* result = NULL;
3300
3301 result = autocomplete_param_with_func(input, "/receipts send", prefs_autocomplete_boolean_choice, previous, NULL);
3302 if (result) {
3303 return result;
3304 }
3305
3306 result = autocomplete_param_with_func(input, "/receipts request", prefs_autocomplete_boolean_choice, previous, NULL);
3307 if (result) {
3308 return result;
3309 }
3310
3311 result = autocomplete_param_with_ac(input, "/receipts", receipts_ac, TRUE, previous);
3312
3313 return result;
3314 }
3315
3316 static char*
_alias_autocomplete(ProfWin * window,const char * const input,gboolean previous)3317 _alias_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3318 {
3319 char* result = NULL;
3320
3321 result = autocomplete_param_with_ac(input, "/alias remove", aliases_ac, TRUE, previous);
3322 if (result) {
3323 return result;
3324 }
3325
3326 result = autocomplete_param_with_ac(input, "/alias", alias_ac, TRUE, previous);
3327
3328 return result;
3329 }
3330
3331 static char*
_connect_autocomplete(ProfWin * window,const char * const input,gboolean previous)3332 _connect_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3333 {
3334 char* found = NULL;
3335 gboolean result = FALSE;
3336
3337 gchar** args = parse_args(input, 1, 9, &result);
3338
3339 if (result) {
3340 gboolean space_at_end = g_str_has_suffix(input, " ");
3341 int num_args = g_strv_length(args);
3342 if ((num_args == 1 && space_at_end) || (num_args == 2 && !space_at_end)) {
3343 GString* beginning = g_string_new("/connect");
3344 g_string_append_printf(beginning, " %s", args[0]);
3345 found = autocomplete_param_with_ac(input, beginning->str, connect_property_ac, TRUE, previous);
3346 g_string_free(beginning, TRUE);
3347 if (found) {
3348 g_strfreev(args);
3349 return found;
3350 }
3351 }
3352 if ((num_args == 2 && space_at_end && (g_strcmp0(args[1], "tls") == 0))
3353 || (num_args == 3 && (g_strcmp0(args[1], "tls") == 0) && !space_at_end)) {
3354 GString* beginning = g_string_new("/connect");
3355 g_string_append_printf(beginning, " %s %s", args[0], args[1]);
3356 found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE, previous);
3357 g_string_free(beginning, TRUE);
3358 if (found) {
3359 g_strfreev(args);
3360 return found;
3361 }
3362 }
3363 if ((num_args == 3 && space_at_end) || (num_args == 4 && !space_at_end)) {
3364 GString* beginning = g_string_new("/connect");
3365 g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]);
3366 found = autocomplete_param_with_ac(input, beginning->str, connect_property_ac, TRUE, previous);
3367 g_string_free(beginning, TRUE);
3368 if (found) {
3369 g_strfreev(args);
3370 return found;
3371 }
3372 }
3373 if ((num_args == 4 && space_at_end && (g_strcmp0(args[3], "tls") == 0))
3374 || (num_args == 5 && (g_strcmp0(args[3], "tls") == 0) && !space_at_end)) {
3375 GString* beginning = g_string_new("/connect");
3376 g_string_append_printf(beginning, " %s %s %s %s", args[0], args[1], args[2], args[3]);
3377 found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE, previous);
3378 g_string_free(beginning, TRUE);
3379 if (found) {
3380 g_strfreev(args);
3381 return found;
3382 }
3383 }
3384 if ((num_args == 5 && space_at_end) || (num_args == 6 && !space_at_end)) {
3385 GString* beginning = g_string_new("/connect");
3386 g_string_append_printf(beginning, " %s %s %s %s %s", args[0], args[1], args[2], args[3], args[4]);
3387 found = autocomplete_param_with_ac(input, beginning->str, connect_property_ac, TRUE, previous);
3388 g_string_free(beginning, TRUE);
3389 if (found) {
3390 g_strfreev(args);
3391 return found;
3392 }
3393 }
3394 if ((num_args == 6 && space_at_end && (g_strcmp0(args[5], "tls") == 0))
3395 || (num_args == 7 && (g_strcmp0(args[5], "tls") == 0) && !space_at_end)) {
3396 GString* beginning = g_string_new("/connect");
3397 g_string_append_printf(beginning, " %s %s %s %s %s %s", args[0], args[1], args[2], args[3], args[4], args[5]);
3398 found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE, previous);
3399 g_string_free(beginning, TRUE);
3400 if (found) {
3401 g_strfreev(args);
3402 return found;
3403 }
3404 }
3405 if ((num_args == 7 && space_at_end) || (num_args == 8 && !space_at_end)) {
3406 GString* beginning = g_string_new("/connect");
3407 g_string_append_printf(beginning, " %s %s %s %s %s %s %s", args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
3408 found = autocomplete_param_with_ac(input, beginning->str, connect_property_ac, TRUE, previous);
3409 g_string_free(beginning, TRUE);
3410 if (found) {
3411 g_strfreev(args);
3412 return found;
3413 }
3414 }
3415 if ((num_args == 8 && space_at_end && (g_strcmp0(args[7], "tls") == 0))
3416 || (num_args == 9 && (g_strcmp0(args[7], "tls") == 0) && !space_at_end)) {
3417 GString* beginning = g_string_new("/connect");
3418 g_string_append_printf(beginning, " %s %s %s %s %s %s %s %s", args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
3419 found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE, previous);
3420 g_string_free(beginning, TRUE);
3421 if (found) {
3422 g_strfreev(args);
3423 return found;
3424 }
3425 }
3426
3427 /* auth option */
3428
3429 if ((num_args == 2 && space_at_end && (g_strcmp0(args[1], "auth") == 0))
3430 || (num_args == 3 && (g_strcmp0(args[1], "auth") == 0) && !space_at_end)) {
3431 GString* beginning = g_string_new("/connect");
3432 g_string_append_printf(beginning, " %s %s", args[0], args[1]);
3433 found = autocomplete_param_with_ac(input, beginning->str, auth_property_ac, TRUE, previous);
3434 g_string_free(beginning, TRUE);
3435 if (found) {
3436 g_strfreev(args);
3437 return found;
3438 }
3439 }
3440 if ((num_args == 4 && space_at_end && (g_strcmp0(args[3], "auth") == 0))
3441 || (num_args == 5 && (g_strcmp0(args[3], "auth") == 0) && !space_at_end)) {
3442 GString* beginning = g_string_new("/connect");
3443 g_string_append_printf(beginning, " %s %s %s %s", args[0], args[1], args[2], args[3]);
3444 found = autocomplete_param_with_ac(input, beginning->str, auth_property_ac, TRUE, previous);
3445 g_string_free(beginning, TRUE);
3446 if (found) {
3447 g_strfreev(args);
3448 return found;
3449 }
3450 }
3451 if ((num_args == 6 && space_at_end && (g_strcmp0(args[5], "auth") == 0))
3452 || (num_args == 7 && (g_strcmp0(args[5], "auth") == 0) && !space_at_end)) {
3453 GString* beginning = g_string_new("/connect");
3454 g_string_append_printf(beginning, " %s %s %s %s %s %s", args[0], args[1], args[2], args[3], args[4], args[5]);
3455 found = autocomplete_param_with_ac(input, beginning->str, auth_property_ac, TRUE, previous);
3456 g_string_free(beginning, TRUE);
3457 if (found) {
3458 g_strfreev(args);
3459 return found;
3460 }
3461 }
3462 if ((num_args == 8 && space_at_end && (g_strcmp0(args[7], "auth") == 0))
3463 || (num_args == 9 && (g_strcmp0(args[7], "auth") == 0) && !space_at_end)) {
3464 GString* beginning = g_string_new("/connect");
3465 g_string_append_printf(beginning, " %s %s %s %s %s %s %s %s", args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
3466 found = autocomplete_param_with_ac(input, beginning->str, auth_property_ac, TRUE, previous);
3467 g_string_free(beginning, TRUE);
3468 if (found) {
3469 g_strfreev(args);
3470 return found;
3471 }
3472 }
3473 }
3474
3475 g_strfreev(args);
3476
3477 found = autocomplete_param_with_func(input, "/connect", accounts_find_enabled, previous, NULL);
3478 if (found) {
3479 return found;
3480 }
3481
3482 return NULL;
3483 }
3484
3485 static char*
_help_autocomplete(ProfWin * window,const char * const input,gboolean previous)3486 _help_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3487 {
3488 char* result = NULL;
3489
3490 result = autocomplete_param_with_ac(input, "/help commands", help_commands_ac, TRUE, previous);
3491 if (result) {
3492 return result;
3493 }
3494
3495 result = autocomplete_param_with_ac(input, "/help", help_ac, TRUE, previous);
3496 return result;
3497 }
3498
3499 static char*
_join_autocomplete(ProfWin * window,const char * const input,gboolean previous)3500 _join_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3501 {
3502 char* found = NULL;
3503 gboolean result = FALSE;
3504
3505 gchar** args = parse_args(input, 1, 5, &result);
3506
3507 if (result) {
3508 gboolean space_at_end = g_str_has_suffix(input, " ");
3509 int num_args = g_strv_length(args);
3510 if ((num_args == 1 && space_at_end) || (num_args == 2 && !space_at_end)) {
3511 GString* beginning = g_string_new("/join");
3512 g_string_append_printf(beginning, " %s", args[0]);
3513 found = autocomplete_param_with_ac(input, beginning->str, join_property_ac, TRUE, previous);
3514 g_string_free(beginning, TRUE);
3515 if (found) {
3516 g_strfreev(args);
3517 return found;
3518 }
3519 }
3520 if ((num_args == 3 && space_at_end) || (num_args == 4 && !space_at_end)) {
3521 GString* beginning = g_string_new("/join");
3522 g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]);
3523 found = autocomplete_param_with_ac(input, beginning->str, join_property_ac, TRUE, previous);
3524 g_string_free(beginning, TRUE);
3525 if (found) {
3526 g_strfreev(args);
3527 return found;
3528 }
3529 }
3530 }
3531
3532 g_strfreev(args);
3533
3534 found = autocomplete_param_with_func(input, "/join", bookmark_find, previous, NULL);
3535
3536 return found;
3537 }
3538
3539 static char*
_console_autocomplete(ProfWin * window,const char * const input,gboolean previous)3540 _console_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3541 {
3542 char* result = NULL;
3543
3544 result = autocomplete_param_with_ac(input, "/console chat", console_msg_ac, TRUE, previous);
3545 if (result) {
3546 return result;
3547 }
3548 result = autocomplete_param_with_ac(input, "/console muc", console_msg_ac, TRUE, previous);
3549 if (result) {
3550 return result;
3551 }
3552 result = autocomplete_param_with_ac(input, "/console private", console_msg_ac, TRUE, previous);
3553 if (result) {
3554 return result;
3555 }
3556
3557 result = autocomplete_param_with_ac(input, "/console", console_ac, TRUE, previous);
3558 return result;
3559 }
3560
3561 static char*
_win_autocomplete(ProfWin * window,const char * const input,gboolean previous)3562 _win_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3563 {
3564 return autocomplete_param_with_func(input, "/win", win_autocomplete, previous, NULL);
3565 }
3566
3567 static char*
_close_autocomplete(ProfWin * window,const char * const input,gboolean previous)3568 _close_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3569 {
3570 return autocomplete_param_with_func(input, "/close", win_close_autocomplete, previous, NULL);
3571 }
3572
3573 static char*
_sendfile_autocomplete(ProfWin * window,const char * const input,gboolean previous)3574 _sendfile_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3575 {
3576 return cmd_ac_complete_filepath(input, "/sendfile", previous);
3577 }
3578
3579 static char*
_subject_autocomplete(ProfWin * window,const char * const input,gboolean previous)3580 _subject_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3581 {
3582 char* result = NULL;
3583
3584 if (window->type == WIN_MUC) {
3585 if ((g_strcmp0(input, "/subject e") == 0)
3586 || (g_strcmp0(input, "/subject ed") == 0)
3587 || (g_strcmp0(input, "/subject edi") == 0)
3588 || (g_strcmp0(input, "/subject edit") == 0)
3589 || (g_strcmp0(input, "/subject edit ") == 0)
3590 || (g_strcmp0(input, "/subject edit \"") == 0)) {
3591 ProfMucWin* mucwin = (ProfMucWin*)window;
3592 assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
3593
3594 char* subject = muc_subject(mucwin->roomjid);
3595 if (subject) {
3596 GString* result_str = g_string_new("/subject edit \"");
3597 g_string_append(result_str, subject);
3598 g_string_append(result_str, "\"");
3599
3600 result = result_str->str;
3601 g_string_free(result_str, FALSE);
3602 }
3603 }
3604 }
3605 if (result) {
3606 return result;
3607 }
3608
3609 result = autocomplete_param_with_ac(input, "/subject", subject_ac, TRUE, previous);
3610
3611 return result;
3612 }
3613
3614 static char*
_account_autocomplete(ProfWin * window,const char * const input,gboolean previous)3615 _account_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3616 {
3617 char* found = NULL;
3618 gboolean result = FALSE;
3619
3620 gchar** args = parse_args(input, 2, 4, &result);
3621 if (result && (strcmp(args[0], "set") == 0)) {
3622 gboolean space_at_end = g_str_has_suffix(input, " ");
3623 int num_args = g_strv_length(args);
3624 if ((num_args == 2 && space_at_end) || (num_args == 3 && !space_at_end)) {
3625 GString* beginning = g_string_new("/account");
3626 g_string_append_printf(beginning, " %s %s", args[0], args[1]);
3627 found = autocomplete_param_with_ac(input, beginning->str, account_set_ac, TRUE, previous);
3628 g_string_free(beginning, TRUE);
3629 if (found) {
3630 g_strfreev(args);
3631 return found;
3632 }
3633 }
3634 #ifdef HAVE_LIBOTR
3635 if ((num_args == 3 && space_at_end && (g_strcmp0(args[2], "otr") == 0))
3636 || (num_args == 4 && (g_strcmp0(args[2], "otr") == 0) && !space_at_end)) {
3637 GString* beginning = g_string_new("/account");
3638 g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]);
3639 found = autocomplete_param_with_ac(input, beginning->str, otr_policy_ac, TRUE, previous);
3640 g_string_free(beginning, TRUE);
3641 if (found) {
3642 g_strfreev(args);
3643 return found;
3644 }
3645 }
3646 #endif
3647 if ((num_args == 3 && space_at_end && (g_strcmp0(args[2], "status") == 0))
3648 || (num_args == 4 && (g_strcmp0(args[2], "status") == 0) && !space_at_end)) {
3649 GString* beginning = g_string_new("/account");
3650 g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]);
3651 found = autocomplete_param_with_ac(input, beginning->str, account_status_ac, TRUE, previous);
3652 g_string_free(beginning, TRUE);
3653 if (found) {
3654 g_strfreev(args);
3655 return found;
3656 }
3657 }
3658 if ((num_args == 3 && space_at_end && (g_strcmp0(args[2], "tls") == 0))
3659 || (num_args == 4 && (g_strcmp0(args[2], "tls") == 0) && !space_at_end)) {
3660 GString* beginning = g_string_new("/account");
3661 g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]);
3662 found = autocomplete_param_with_ac(input, beginning->str, tls_property_ac, TRUE, previous);
3663 g_string_free(beginning, TRUE);
3664 if (found) {
3665 g_strfreev(args);
3666 return found;
3667 }
3668 }
3669 if ((num_args == 3 && space_at_end && (g_strcmp0(args[2], "auth") == 0))
3670 || (num_args == 4 && (g_strcmp0(args[2], "auth") == 0) && !space_at_end)) {
3671 GString* beginning = g_string_new("/account");
3672 g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]);
3673 found = autocomplete_param_with_ac(input, beginning->str, auth_property_ac, TRUE, previous);
3674 g_string_free(beginning, TRUE);
3675 if (found) {
3676 g_strfreev(args);
3677 return found;
3678 }
3679 }
3680 if ((num_args == 3 && space_at_end && (g_strcmp0(args[2], "startscript") == 0))
3681 || (num_args == 4 && (g_strcmp0(args[2], "startscript") == 0) && !space_at_end)) {
3682 GString* beginning = g_string_new("/account");
3683 g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]);
3684 found = autocomplete_param_with_func(input, beginning->str, _script_autocomplete_func, previous, NULL);
3685 g_string_free(beginning, TRUE);
3686 if (found) {
3687 g_strfreev(args);
3688 return found;
3689 }
3690 }
3691 if ((num_args == 3 && space_at_end && (g_strcmp0(args[2], "theme") == 0))
3692 || (num_args == 4 && (g_strcmp0(args[2], "theme") == 0) && !space_at_end)) {
3693 GString* beginning = g_string_new("/account");
3694 g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]);
3695 if (theme_load_ac == NULL) {
3696 theme_load_ac = autocomplete_new();
3697 GSList* themes = theme_list();
3698 GSList* curr = themes;
3699 while (curr) {
3700 autocomplete_add(theme_load_ac, curr->data);
3701 curr = g_slist_next(curr);
3702 }
3703 g_slist_free_full(themes, g_free);
3704 autocomplete_add(theme_load_ac, "default");
3705 }
3706 found = autocomplete_param_with_ac(input, beginning->str, theme_load_ac, TRUE, previous);
3707 g_string_free(beginning, TRUE);
3708 if (found) {
3709 g_strfreev(args);
3710 return found;
3711 }
3712 }
3713 #ifdef HAVE_LIBGPGME
3714 if ((num_args == 3 && space_at_end && (g_strcmp0(args[2], "pgpkeyid") == 0))
3715 || (num_args == 4 && (g_strcmp0(args[2], "pgpkeyid") == 0) && !space_at_end)) {
3716 GString* beginning = g_string_new("/account");
3717 g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]);
3718 found = autocomplete_param_with_func(input, beginning->str, p_gpg_autocomplete_key, previous, NULL);
3719 g_string_free(beginning, TRUE);
3720 if (found) {
3721 g_strfreev(args);
3722 return found;
3723 }
3724 }
3725 #endif
3726 }
3727
3728 if ((strncmp(input, "/account clear", 14) == 0) && (result == TRUE)) {
3729 GString* beginning = g_string_new("/account clear ");
3730 g_string_append(beginning, args[1]);
3731 found = autocomplete_param_with_ac(input, beginning->str, account_clear_ac, TRUE, previous);
3732 g_string_free(beginning, TRUE);
3733 if (found) {
3734 g_strfreev(args);
3735 return found;
3736 }
3737 }
3738
3739 g_strfreev(args);
3740
3741 found = autocomplete_param_with_ac(input, "/account default", account_default_ac, TRUE, previous);
3742 if (found) {
3743 return found;
3744 }
3745
3746 gchar* account_choice[] = { "/account set", "/account show", "/account enable",
3747 "/account disable", "/account rename", "/account clear", "/account remove",
3748 "/account default set" };
3749
3750 for (int i = 0; i < ARRAY_SIZE(account_choice); i++) {
3751 found = autocomplete_param_with_func(input, account_choice[i], accounts_find_all, previous, NULL);
3752 if (found) {
3753 return found;
3754 }
3755 }
3756
3757 found = autocomplete_param_with_ac(input, "/account", account_ac, TRUE, previous);
3758 return found;
3759 }
3760
3761 static char*
_presence_autocomplete(ProfWin * window,const char * const input,gboolean previous)3762 _presence_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3763 {
3764 char* found = NULL;
3765
3766 found = autocomplete_param_with_func(input, "/presence titlebar", prefs_autocomplete_boolean_choice, previous, NULL);
3767 if (found) {
3768 return found;
3769 }
3770
3771 found = autocomplete_param_with_ac(input, "/presence console", presence_setting_ac, TRUE, previous);
3772 if (found) {
3773 return found;
3774 }
3775
3776 found = autocomplete_param_with_ac(input, "/presence chat", presence_setting_ac, TRUE, previous);
3777 if (found) {
3778 return found;
3779 }
3780
3781 found = autocomplete_param_with_ac(input, "/presence room", presence_setting_ac, TRUE, previous);
3782 if (found) {
3783 return found;
3784 }
3785
3786 found = autocomplete_param_with_ac(input, "/presence", presence_ac, TRUE, previous);
3787
3788 return found;
3789 }
3790
3791 static char*
_rooms_autocomplete(ProfWin * window,const char * const input,gboolean previous)3792 _rooms_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3793 {
3794 char* found = NULL;
3795 gboolean result = FALSE;
3796
3797 gchar** args = parse_args(input, 0, 4, &result);
3798
3799 if (result) {
3800 gboolean space_at_end = g_str_has_suffix(input, " ");
3801 int num_args = g_strv_length(args);
3802 if (num_args <= 1) {
3803 found = autocomplete_param_with_ac(input, "/rooms", rooms_all_ac, TRUE, previous);
3804 if (found) {
3805 g_strfreev(args);
3806 return found;
3807 }
3808 }
3809 if ((num_args == 1 && g_strcmp0(args[0], "service") == 0 && space_at_end) || (num_args == 2 && g_strcmp0(args[0], "service") == 0 && !space_at_end)) {
3810 found = autocomplete_param_with_func(input, "/rooms service", muc_confserver_find, previous, NULL);
3811 if (found) {
3812 g_strfreev(args);
3813 return found;
3814 }
3815 }
3816 if ((num_args == 1 && g_strcmp0(args[0], "cache") == 0 && space_at_end) || (num_args == 2 && g_strcmp0(args[0], "cache") == 0 && !space_at_end)) {
3817 found = autocomplete_param_with_ac(input, "/rooms cache", rooms_cache_ac, TRUE, previous);
3818 if (found) {
3819 g_strfreev(args);
3820 return found;
3821 }
3822 }
3823 if ((num_args == 2 && space_at_end) || (num_args == 3 && !space_at_end)) {
3824 GString* beginning = g_string_new("/rooms");
3825 g_string_append_printf(beginning, " %s %s", args[0], args[1]);
3826 found = autocomplete_param_with_ac(input, beginning->str, rooms_list_ac, TRUE, previous);
3827 g_string_free(beginning, TRUE);
3828 if (found) {
3829 g_strfreev(args);
3830 return found;
3831 }
3832 }
3833 if ((num_args == 3 && g_strcmp0(args[2], "service") == 0 && space_at_end) || (num_args == 4 && g_strcmp0(args[2], "service") == 0 && !space_at_end)) {
3834 GString* beginning = g_string_new("/rooms");
3835 g_string_append_printf(beginning, " %s %s %s", args[0], args[1], args[2]);
3836 found = autocomplete_param_with_func(input, beginning->str, muc_confserver_find, previous, NULL);
3837 g_string_free(beginning, TRUE);
3838 if (found) {
3839 g_strfreev(args);
3840 return found;
3841 }
3842 }
3843 if ((num_args >= 2) && g_strcmp0(args[0], "cache") == 0) {
3844 g_strfreev(args);
3845 return NULL;
3846 }
3847 }
3848
3849 g_strfreev(args);
3850
3851 return NULL;
3852 }
3853
3854 static char*
_statusbar_autocomplete(ProfWin * window,const char * const input,gboolean previous)3855 _statusbar_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3856 {
3857 char* found = NULL;
3858
3859 found = autocomplete_param_with_ac(input, "/statusbar", statusbar_ac, TRUE, previous);
3860 if (found) {
3861 return found;
3862 }
3863
3864 found = autocomplete_param_with_ac(input, "/statusbar show", statusbar_show_ac, TRUE, previous);
3865 if (found) {
3866 return found;
3867 }
3868
3869 found = autocomplete_param_with_ac(input, "/statusbar hide", statusbar_show_ac, TRUE, previous);
3870 if (found) {
3871 return found;
3872 }
3873
3874 found = autocomplete_param_with_ac(input, "/statusbar self", statusbar_self_ac, TRUE, previous);
3875 if (found) {
3876 return found;
3877 }
3878
3879 found = autocomplete_param_with_ac(input, "/statusbar chat", statusbar_chat_ac, TRUE, previous);
3880 if (found) {
3881 return found;
3882 }
3883
3884 found = autocomplete_param_with_ac(input, "/statusbar room", statusbar_room_ac, TRUE, previous);
3885
3886 return found;
3887 }
3888
3889 static char*
_clear_autocomplete(ProfWin * window,const char * const input,gboolean previous)3890 _clear_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3891 {
3892 char* result = NULL;
3893
3894 result = autocomplete_param_with_ac(input, "/clear", clear_ac, TRUE, previous);
3895 if (result) {
3896 return result;
3897 }
3898
3899 result = autocomplete_param_with_func(input, "/clear persist_history", prefs_autocomplete_boolean_choice, previous, NULL);
3900 return result;
3901 }
3902
3903 static char*
_invite_autocomplete(ProfWin * window,const char * const input,gboolean previous)3904 _invite_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3905 {
3906 char* result = NULL;
3907
3908 result = autocomplete_param_with_ac(input, "/invite", invite_ac, TRUE, previous);
3909 if (result) {
3910 return result;
3911 }
3912
3913 jabber_conn_status_t conn_status = connection_get_status();
3914
3915 if (conn_status == JABBER_CONNECTED) {
3916 result = autocomplete_param_with_func(input, "/invite send", roster_contact_autocomplete, previous, NULL);
3917 if (result) {
3918 return result;
3919 }
3920
3921 result = autocomplete_param_with_func(input, "/invite decline", muc_invites_find, previous, NULL);
3922 if (result) {
3923 return result;
3924 }
3925 }
3926
3927 return NULL;
3928 }
3929
3930 static char*
_status_autocomplete(ProfWin * window,const char * const input,gboolean previous)3931 _status_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3932 {
3933 char* result = NULL;
3934
3935 result = autocomplete_param_with_ac(input, "/status", status_ac, TRUE, previous);
3936 if (result) {
3937 return result;
3938 }
3939
3940 jabber_conn_status_t conn_status = connection_get_status();
3941
3942 if (conn_status == JABBER_CONNECTED) {
3943
3944 // complete with: online, away etc.
3945 result = autocomplete_param_with_ac(input, "/status set", account_status_ac, TRUE, previous);
3946 if (result) {
3947 return result;
3948 }
3949
3950 // Remove quote character before and after names when doing autocomplete
3951 char* unquoted = strip_arg_quotes(input);
3952
3953 // MUC completion with nicknames
3954 if (window->type == WIN_MUC) {
3955 ProfMucWin* mucwin = (ProfMucWin*)window;
3956 assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
3957 Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid);
3958 if (nick_ac) {
3959 result = autocomplete_param_with_ac(unquoted, "/status get", nick_ac, TRUE, previous);
3960 if (result) {
3961 free(unquoted);
3962 return result;
3963 }
3964 }
3965 // roster completion
3966 } else {
3967 result = autocomplete_param_with_func(unquoted, "/status get", roster_contact_autocomplete, previous, NULL);
3968 if (result) {
3969 free(unquoted);
3970 return result;
3971 }
3972 }
3973
3974 free(unquoted);
3975 }
3976
3977 return NULL;
3978 }
3979
3980 static char*
_logging_autocomplete(ProfWin * window,const char * const input,gboolean previous)3981 _logging_autocomplete(ProfWin* window, const char* const input, gboolean previous)
3982 {
3983 char* result = NULL;
3984
3985 result = autocomplete_param_with_ac(input, "/logging", logging_ac, TRUE, previous);
3986 if (result) {
3987 return result;
3988 }
3989
3990 result = autocomplete_param_with_func(input, "/logging chat", prefs_autocomplete_boolean_choice, previous, NULL);
3991 if (result) {
3992 return result;
3993 }
3994
3995 result = autocomplete_param_with_ac(input, "/logging group", logging_group_ac, TRUE, previous);
3996 return result;
3997 }
3998
3999 static char*
_color_autocomplete(ProfWin * window,const char * const input,gboolean previous)4000 _color_autocomplete(ProfWin* window, const char* const input, gboolean previous)
4001 {
4002 char* result = NULL;
4003
4004 result = autocomplete_param_with_func(input, "/color own", prefs_autocomplete_boolean_choice, previous, NULL);
4005 if (result) {
4006 return result;
4007 }
4008
4009 result = autocomplete_param_with_ac(input, "/color", color_ac, TRUE, previous);
4010 return result;
4011 }
4012
4013 static char*
_avatar_autocomplete(ProfWin * window,const char * const input,gboolean previous)4014 _avatar_autocomplete(ProfWin* window, const char* const input, gboolean previous)
4015 {
4016 char* result = NULL;
4017
4018 result = autocomplete_param_with_ac(input, "/avatar", avatar_ac, TRUE, previous);
4019 if (result) {
4020 return result;
4021 }
4022
4023 jabber_conn_status_t conn_status = connection_get_status();
4024 if (conn_status == JABBER_CONNECTED) {
4025 result = autocomplete_param_with_func(input, "/avatar get", roster_barejid_autocomplete, previous, NULL);
4026 if (result) {
4027 return result;
4028 }
4029
4030 result = autocomplete_param_with_func(input, "/avatar open", roster_barejid_autocomplete, previous, NULL);
4031 if (result) {
4032 return result;
4033 }
4034 }
4035
4036 return NULL;
4037 }
4038
4039 static char*
_correction_autocomplete(ProfWin * window,const char * const input,gboolean previous)4040 _correction_autocomplete(ProfWin* window, const char* const input, gboolean previous)
4041 {
4042 char* result = NULL;
4043
4044 result = autocomplete_param_with_ac(input, "/correction", correction_ac, TRUE, previous);
4045
4046 return result;
4047 }
4048
4049 static char*
_correct_autocomplete(ProfWin * window,const char * const input,gboolean previous)4050 _correct_autocomplete(ProfWin* window, const char* const input, gboolean previous)
4051 {
4052 char* last_message = NULL;
4053 switch (window->type) {
4054 case WIN_CHAT:
4055 {
4056 ProfChatWin* chatwin = (ProfChatWin*)window;
4057 assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
4058 last_message = chatwin->last_message;
4059 break;
4060 }
4061 case WIN_MUC:
4062 {
4063 ProfMucWin* mucwin = (ProfMucWin*)window;
4064 assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
4065 last_message = mucwin->last_message;
4066 }
4067 default:
4068 break;
4069 }
4070
4071 if (last_message == NULL) {
4072 return NULL;
4073 }
4074
4075 GString* result_str = g_string_new("/correct ");
4076 g_string_append(result_str, last_message);
4077 char* result = result_str->str;
4078 g_string_free(result_str, FALSE);
4079
4080 return result;
4081 }
4082
4083 static char*
_software_autocomplete(ProfWin * window,const char * const input,gboolean previous)4084 _software_autocomplete(ProfWin* window, const char* const input, gboolean previous)
4085 {
4086 char* result = NULL;
4087
4088 if (window->type == WIN_CHAT) {
4089 ProfChatWin* chatwin = (ProfChatWin*)window;
4090 assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
4091
4092 GString* search_str = g_string_new("/software ");
4093 g_string_append(search_str, chatwin->barejid);
4094 result = autocomplete_param_with_func(search_str->str, "/software", roster_fulljid_autocomplete, previous, NULL);
4095 g_string_free(search_str, TRUE);
4096 } else if (window->type == WIN_MUC) {
4097 ProfMucWin* mucwin = (ProfMucWin*)window;
4098 assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
4099
4100 Autocomplete nick_ac = muc_roster_ac(mucwin->roomjid);
4101
4102 if (nick_ac) {
4103 result = autocomplete_param_with_ac(input, "/software", nick_ac, TRUE, previous);
4104 if (result) {
4105 return result;
4106 }
4107 }
4108 } else {
4109 result = autocomplete_param_with_func(input, "/software", roster_fulljid_autocomplete, previous, NULL);
4110 if (result) {
4111 return result;
4112 }
4113 }
4114
4115 return result;
4116 }
4117
4118 static char*
_url_autocomplete(ProfWin * window,const char * const input,gboolean previous)4119 _url_autocomplete(ProfWin* window, const char* const input, gboolean previous)
4120 {
4121 char* result = NULL;
4122
4123 result = autocomplete_param_with_ac(input, "/url", url_ac, TRUE, previous);
4124 if (result) {
4125 return result;
4126 }
4127
4128 if (window->type == WIN_CHAT || window->type == WIN_MUC || window->type == WIN_PRIVATE) {
4129 result = autocomplete_param_with_func(input, "/url open", wins_get_url, previous, window);
4130 if (result) {
4131 return result;
4132 }
4133
4134 result = autocomplete_param_with_func(input, "/url save", wins_get_url, previous, window);
4135 }
4136
4137 return result;
4138 }
4139
4140 static char*
_executable_autocomplete(ProfWin * window,const char * const input,gboolean previous)4141 _executable_autocomplete(ProfWin* window, const char* const input, gboolean previous)
4142 {
4143 char* result = NULL;
4144
4145 result = autocomplete_param_with_ac(input, "/executable", executable_ac, TRUE, previous);
4146
4147 return result;
4148 }
4149
4150 static char*
_lastactivity_autocomplete(ProfWin * window,const char * const input,gboolean previous)4151 _lastactivity_autocomplete(ProfWin* window, const char* const input, gboolean previous)
4152 {
4153 char* result = NULL;
4154
4155 result = autocomplete_param_with_ac(input, "/lastactivity", status_ac, TRUE, previous);
4156 if (!result) {
4157 return result;
4158 }
4159
4160 jabber_conn_status_t conn_status = connection_get_status();
4161
4162 if (conn_status == JABBER_CONNECTED) {
4163
4164 result = autocomplete_param_with_func(input, "/lastactivity set", prefs_autocomplete_boolean_choice, previous, NULL);
4165 if (!result) {
4166 result = autocomplete_param_with_func(input, "/lastactivity get", roster_barejid_autocomplete, previous, NULL);
4167 }
4168 }
4169
4170 return result;
4171 }
4172
4173 static char*
_intype_autocomplete(ProfWin * window,const char * const input,gboolean previous)4174 _intype_autocomplete(ProfWin* window, const char* const input, gboolean previous)
4175 {
4176 char* result = NULL;
4177 result = autocomplete_param_with_func(input, "/intype console", prefs_autocomplete_boolean_choice, previous, NULL);
4178 if (result) {
4179 return result;
4180 }
4181
4182 result = autocomplete_param_with_func(input, "/intype titlebar", prefs_autocomplete_boolean_choice, previous, NULL);
4183 if (result) {
4184 return result;
4185 }
4186
4187 result = autocomplete_param_with_ac(input, "/intype", intype_ac, FALSE, previous);
4188 return result;
4189 }
4190