2
* $Id: xmpp-completion.c,v 1.27 2010/10/24 16:16:25 cdidier Exp $
4
* Copyright (C) 2007 Colin DIDIER
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2 as
8
* published by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License along
16
* with this program; if not, write to the Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24
#include "channels-setup.h"
28
#include "window-items.h"
30
#include "xmpp-servers.h"
31
#include "xmpp-commands.h"
32
#include "rosters-tools.h"
36
quoted_if_space(const char *name, const char *res)
39
return g_utf8_strchr(res, -1, ' ') == NULL ?
40
g_strconcat(name, "/", res, (void *)NULL) :
41
g_strconcat("\"", name, "/", res, "\"", (void *)NULL);
43
return g_utf8_strchr(name, -1, ' ') == NULL ?
44
g_strdup(name) : g_strconcat("\"", name, "\"", (void *)NULL);
48
get_resources(XMPP_SERVER_REC *server, const char *nick,
49
const char *resource_name, gboolean quoted)
53
XMPP_ROSTER_USER_REC *user;
54
XMPP_ROSTER_RESOURCE_REC *resource;
57
g_return_val_if_fail(IS_XMPP_SERVER(server), NULL);
58
g_return_val_if_fail(nick != NULL, NULL);
59
len = resource_name != NULL ? strlen(resource_name) : 0;
61
user = rosters_find_user(server->roster, nick, NULL, NULL);
64
for(rl = user->resources; rl != NULL; rl = rl->next) {
66
if (resource_name == NULL
67
|| g_strncasecmp(resource->name, resource_name, len) == 0)
68
list = g_list_append(list, quoted ?
69
quoted_if_space(nick, resource->name) :
70
g_strconcat(nick, "/", resource->name, (void *)NULL));
76
get_jids(XMPP_SERVER_REC *server, const char *jid)
79
GList *list, *list_case, *offlist, *offlist_case;
80
XMPP_ROSTER_USER_REC *user;
83
list = list_case = offlist = offlist_case = NULL;
85
for (gl = server->roster; gl != NULL; gl = gl->next) {
86
for (ul = ((XMPP_ROSTER_GROUP_REC *)gl->data)->users;
87
ul != NULL ; ul = ul->next) {
88
user = (XMPP_ROSTER_USER_REC *)ul->data;
89
if (strncmp(user->jid, jid, len) == 0) {
90
if (user->resources != NULL)
91
list = g_list_append(list,
94
offlist = g_list_append(offlist,
96
} else if (g_strncasecmp(user->jid, jid, len) == 0) {
97
if (user->resources != NULL)
98
list_case = g_list_append(list_case,
101
offlist_case = g_list_append(offlist_case,
102
g_strdup(user->jid));
106
/* TODO: temporary list of jids */
107
list = g_list_concat(list, list_case);
108
list = g_list_concat(list, offlist);
109
list = g_list_concat(list, offlist_case);
114
get_nicks(XMPP_SERVER_REC *server, const char *nick, gboolean quoted,
115
gboolean complete_names)
119
XMPP_ROSTER_USER_REC *user;
120
char *jid, *resource;
125
/* resources completion */
126
resource = xmpp_extract_resource(nick);
127
if (resource != NULL) {
128
jid = xmpp_strip_resource(nick);
129
list = get_resources(server, jid, resource, quoted);
137
/* first complete with online contacts
138
* then complete with offline contacts */
139
for (gl = server->roster; gl != NULL; gl = gl->next) {
140
for (ul = ((XMPP_ROSTER_GROUP_REC *)gl->data)->users;
141
ul != NULL ; ul = ul->next) {
142
user = (XMPP_ROSTER_USER_REC *)ul->data;
143
if ((!pass2 && user->resources == NULL)
144
|| (pass2 && user->resources != NULL))
146
if (complete_names && user->name != NULL
147
&& g_strncasecmp(user->name, nick, len) == 0)
148
list = g_list_prepend(list, quoted ?
149
quoted_if_space(user->name, NULL) :
150
g_strdup(user->name));
151
if (g_strncasecmp(user->jid, nick, len) == 0)
152
list = g_list_prepend(list, quoted ?
153
quoted_if_space(user->jid, NULL) :
154
g_strdup(user->jid));
157
if ((pass2 = !pass2))
159
/* TODO: rewrite this function */
164
sig_complete_word(GList **list, WINDOW_REC *window, const char *word,
165
const char *linestart, int *want_space)
167
XMPP_SERVER_REC *server;
169
g_return_if_fail(list != NULL);
170
g_return_if_fail(window != NULL);
171
g_return_if_fail(word != NULL);
172
if ((server = XMPP_SERVER(window->active_server)) == NULL)
174
if (g_ascii_strncasecmp(linestart,
175
settings_get_str("cmdchars"), 1) == 0) {
176
*list = g_list_concat(*list, get_nicks(server, *word == '"' ?
177
word+1 : word , TRUE, TRUE));
178
} else if (!IS_CHANNEL(window->active))
179
*list = g_list_concat(*list, get_nicks(server, word, FALSE,
184
sig_complete_command_roster_group(GList **list, WINDOW_REC *window,
185
const char *word, const char *args, int *want_space)
188
XMPP_SERVER_REC *server;
189
XMPP_ROSTER_GROUP_REC *group;
193
g_return_if_fail(list != NULL);
194
g_return_if_fail(window != NULL);
195
g_return_if_fail(word != NULL);
196
g_return_if_fail(args != NULL);
197
server = XMPP_SERVER(window->active_server);
201
tmp = g_strsplit(args, " ", 2);
204
*list = g_list_concat(*list, get_nicks(server, *word == '"' ?
205
word+1 : word , TRUE, FALSE));
206
/* complete groups */
207
else if (tmp[0] != NULL && tmp[1] == NULL) {
208
for (gl = server->roster; gl != NULL; gl = gl->next) {
209
group = (XMPP_ROSTER_GROUP_REC *)gl->data;
210
if (group->name != NULL &&
211
g_ascii_strncasecmp(word, group->name, len) == 0)
212
*list = g_list_append(*list,
213
g_strdup(group->name));
222
sig_complete_command_roster_others(GList **list, WINDOW_REC *window,
223
const char *word, const char *args, int *want_space)
225
XMPP_SERVER_REC *server;
229
g_return_if_fail(list != NULL);
230
g_return_if_fail(window != NULL);
231
g_return_if_fail(word != NULL);
232
g_return_if_fail(args != NULL);
233
if ((server = XMPP_SERVER(window->active_server)) == NULL)
236
tmp = g_strsplit(args, " ", 2);
239
*list = g_list_concat(*list, get_nicks(server, *word == '"' ?
240
word+1 : word , TRUE, FALSE));
247
sig_complete_command_presence(GList **list, WINDOW_REC *window,
248
const char *word, const char *args, int *want_space)
250
XMPP_SERVER_REC *server;
254
g_return_if_fail(list != NULL);
255
g_return_if_fail(window != NULL);
256
g_return_if_fail(word != NULL);
257
g_return_if_fail(args != NULL);
258
if ((server = XMPP_SERVER(window->active_server)) == NULL)
261
tmp = g_strsplit(args, " ", 2);
264
*list = g_list_concat(*list, get_jids(server, *word == '"' ?
272
get_channels(XMPP_SERVER_REC *server, const char *word)
276
CHANNEL_REC *channel;
277
CHANNEL_SETUP_REC *channel_setup;
280
g_return_val_if_fail(IS_XMPP_SERVER(server), NULL);
281
g_return_val_if_fail(word != NULL, NULL);
284
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
285
channel = CHANNEL(tmp->data);
286
if (channel != NULL &&
287
g_strncasecmp(channel->name, word, len) == 0)
288
list = g_list_append(list, g_strdup(channel->name));
290
for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) {
291
channel_setup = tmp->data;
292
if ((PROTO_CHECK_CAST(channel_setup, CHANNEL_SETUP_REC,
293
chat_type, XMPP_PROTOCOL_NAME)
294
|| *channel_setup->name != '#')
295
&& g_strncasecmp(channel_setup->name, word, len) == 0
296
&& glist_find_string(list, channel_setup->name) == NULL)
297
list = g_list_append(list,
298
g_strdup(channel_setup->name));
304
sig_complete_command_channels(GList **list, WINDOW_REC *window,
305
const char *word, const char *args, int *want_space)
307
XMPP_SERVER_REC *server;
309
g_return_if_fail(list != NULL);
310
g_return_if_fail(window != NULL);
311
g_return_if_fail(word != NULL);
312
server = XMPP_SERVER(window->active_server);
315
*list = get_channels(server, word);
321
sig_complete_command_invite(GList **list, WINDOW_REC *window,
322
const char *word, const char *args, int *want_space)
324
XMPP_SERVER_REC *server;
327
g_return_if_fail(list != NULL);
328
g_return_if_fail(window != NULL);
329
g_return_if_fail(word != NULL);
330
server = XMPP_SERVER(window->active_server);
333
/* complete channels */
334
tmp = g_strsplit(args, " ", 2);
335
if (tmp[0] != NULL && tmp[1] == NULL)
336
*list = get_channels(server, word);
343
sig_complete_command_away(GList **list, WINDOW_REC *window,
344
const char *word, const char *args, int *want_space)
346
XMPP_SERVER_REC *server;
349
g_return_if_fail(list != NULL);
350
g_return_if_fail(window != NULL);
351
g_return_if_fail(word != NULL);
352
server = XMPP_SERVER(window->active_server);
356
if (g_strncasecmp(word,
357
xmpp_presence_show[XMPP_PRESENCE_AWAY], len) == 0)
358
*list = g_list_append(*list,
359
g_strdup(xmpp_presence_show[XMPP_PRESENCE_AWAY]));
360
if (g_strncasecmp(word,
361
xmpp_presence_show[XMPP_PRESENCE_XA], len) == 0)
362
*list = g_list_append(*list,
363
g_strdup(xmpp_presence_show[XMPP_PRESENCE_XA]));
364
if (g_strncasecmp(word,
365
xmpp_presence_show[XMPP_PRESENCE_DND], len) == 0)
366
*list = g_list_append(*list,
367
g_strdup(xmpp_presence_show[XMPP_PRESENCE_DND]));
368
if (g_strncasecmp(word,
369
xmpp_presence_show[XMPP_PRESENCE_CHAT], len) == 0)
370
*list = g_list_append(*list,
371
g_strdup(xmpp_presence_show[XMPP_PRESENCE_CHAT]));
372
if (g_strncasecmp(word,
373
xmpp_presence_show[XMPP_PRESENCE_ONLINE], len) == 0)
374
*list = g_list_append(*list, g_strdup("online"));
379
xmpp_completion_init(void)
381
signal_add("complete word", sig_complete_word);
382
signal_add("complete command roster group",
383
sig_complete_command_roster_group);
384
signal_add("complete command roster add",
385
sig_complete_command_roster_others);
386
signal_add("complete command roster remove",
387
sig_complete_command_roster_others);
388
signal_add("complete command roster name",
389
sig_complete_command_roster_others);
390
signal_add("complete command presence accept",
391
sig_complete_command_presence);
392
signal_add("complete command presence deny",
393
sig_complete_command_presence);
394
signal_add("complete command presence subscribe",
395
sig_complete_command_presence);
396
signal_add("complete command presence unsubscribe",
397
sig_complete_command_presence);
398
signal_add("complete command join", sig_complete_command_channels);
399
signal_add("complete command part", sig_complete_command_channels);
400
signal_add("complete command invite", sig_complete_command_invite);
401
signal_add("complete command away", sig_complete_command_away);
405
xmpp_completion_deinit(void)
407
signal_remove("complete word", sig_complete_word);
408
signal_remove("complete command roster group",
409
sig_complete_command_roster_group);
410
signal_remove("complete command roster add",
411
sig_complete_command_roster_others);
412
signal_remove("complete command roster remove",
413
sig_complete_command_roster_others);
414
signal_remove("complete command roster name",
415
sig_complete_command_roster_others);
416
signal_remove("complete command presence accept",
417
sig_complete_command_presence);
418
signal_remove("complete command presence deny",
419
sig_complete_command_presence);
420
signal_remove("complete command presence subscribe",
421
sig_complete_command_presence);
422
signal_remove("complete command presence unsubscribe",
423
sig_complete_command_presence);
424
signal_remove("complete command join", sig_complete_command_channels);
425
signal_remove("complete command part", sig_complete_command_channels);
426
signal_remove("complete command invite", sig_complete_command_invite);
427
signal_remove("complete command away", sig_complete_command_away);