Mercurial > hg
annotate mcabber/mcabber/help.c @ 1731:4fbfae993c24
Improve login process
The roster and private storage elements are requested before broadcasting
our presence, because we want the roster before we receive our contacts
presence notifications.
This is more efficients, and also solves an issue with entity capabilities
(as we do not store caps for unknown items).
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Sun, 28 Feb 2010 18:50:30 +0100 |
parents | e6e89b1d7831 |
children | 6abca6000762 |
rev | line source |
---|---|
868 | 1 /* |
2 * help.c -- Help command | |
3 * | |
1599 | 4 * Copyright (C) 2006-2009 Mikael Berthe <mikael@lilotux.net> |
1678 | 5 * Copyrigth (C) 2009 Myhailo Danylenko <isbear@ukrpost.net> |
868 | 6 * |
7 * This program is free software; you can redistribute it and/or modify | |
8 * it under the terms of the GNU General Public License as published by | |
9 * the Free Software Foundation; either version 2 of the License, or (at | |
10 * your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU General Public License | |
18 * along with this program; if not, write to the Free Software | |
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | |
20 * USA | |
21 */ | |
22 | |
1678 | 23 /* |
24 * How it works | |
25 * | |
26 * Main calls help_init, that installs option guards. These guards do | |
27 * nothing, but set help_dirs_stalled flag. When user issues help command, | |
28 * it checks, if help_dirs_stalled flag is set, and if it is, it calls | |
29 * init_help_dirs before performing help search. | |
30 * | |
31 * Options: | |
32 * lang List of semicolon-separated language codes. If unset, will | |
33 * be detected from locale, with fallback to english. | |
34 * help_dirs List of semicolon-seaparated directories, where search for | |
35 * help (in language subdirectories) will be performed. | |
36 * Defaults to DATA_DIR/mcabber/help. | |
37 * help_to_current Print help to current buddy's buffer. | |
38 * | |
39 * XXX: | |
40 * Remove command list from hlp.txt and print detected list of all help | |
41 * topics? | |
42 */ | |
868 | 43 |
1678 | 44 #include <glib.h> |
45 #include <string.h> | |
46 #include <locale.h> | |
47 #include <sys/types.h> | |
48 #include <dirent.h> | |
49 | |
50 #include "logprint.h" | |
51 #include "screen.h" | |
52 #include "hbuf.h" | |
868 | 53 #include "settings.h" |
54 #include "utils.h" | |
55 | |
1678 | 56 static GSList *help_dirs = NULL; |
57 static gboolean help_dirs_stalled = TRUE; | |
868 | 58 |
1678 | 59 void free_help_dirs(void) |
60 { | |
61 GSList *hel; | |
62 | |
63 for (hel = help_dirs; hel; hel = hel->next) | |
64 g_free(hel->data); | |
65 | |
66 g_slist_free(help_dirs); | |
67 | |
68 help_dirs = NULL; | |
69 } | |
70 | |
71 void dir_push_languages(const char *langs, const char *dir) | |
72 { | |
73 const char *lstart = langs; | |
74 const char *lend; | |
75 char *path = expand_filename(dir); | |
76 | |
77 for (lend = strchr(lstart, ';'); lend; lend = strchr(lstart, ';')) { | |
78 char *lang = g_strndup(lstart, lend - lstart); | |
79 char *dir = g_strdup_printf("%s/%s", path, lang); | |
80 | |
81 help_dirs = g_slist_append(help_dirs, dir); | |
82 | |
83 g_free(lang); | |
84 lstart = lend + 1; | |
868 | 85 } |
1678 | 86 |
87 { // finishing element | |
88 char *dir = g_strdup_printf("%s/%s", path, lstart); | |
89 | |
90 help_dirs = g_slist_append(help_dirs, dir); | |
91 } | |
92 | |
93 g_free(path); | |
868 | 94 } |
95 | |
1678 | 96 void init_help_dirs(void) |
868 | 97 { |
1678 | 98 const char *paths; |
99 const char *langs; | |
100 char lang[6]; | |
101 | |
102 if (help_dirs) | |
103 free_help_dirs(); | |
104 | |
105 // initialize variables | |
106 paths = settings_opt_get("help_dirs"); | |
107 if (!paths || !*paths) | |
108 #ifdef DATA_DIR | |
109 paths = DATA_DIR "/mcabber/help"; | |
868 | 110 #else |
1678 | 111 paths = "/usr/local/share/mcabber/help;/usr/share/mcabber/help"; |
112 #endif | |
113 | |
114 langs = settings_opt_get("lang"); | |
115 | |
116 if (!langs || !*langs) { | |
117 char *locale = setlocale(LC_MESSAGES, NULL); | |
868 | 118 |
1678 | 119 // XXX crude method to distinguish between xx_XX xx xx@xxx |
120 // and C POSIX NULL etc. | |
121 if (locale && isalpha(locale[0]) && isalpha(locale[1]) | |
122 && !isalpha(locale[2])) { | |
123 lang[0] = locale[0]; | |
124 lang[1] = locale[1]; | |
125 | |
126 if (lang[0] == 'e' && lang[1] == 'n') | |
127 lang[2] = '\0'; | |
128 else { | |
129 lang[2] = ';'; | |
130 lang[3] = 'e'; | |
131 lang[4] = 'n'; | |
132 lang[5] = '\0'; | |
133 } | |
134 | |
135 langs = lang; | |
136 } else | |
137 langs = "en"; | |
868 | 138 } |
139 | |
1678 | 140 { // parse |
141 const char *pstart = paths; | |
142 const char *pend; | |
1650
cd81806b5947
Try fallback language (en) when help file with current language is not found
Nixtrian
parents:
1599
diff
changeset
|
143 |
1678 | 144 for (pend = strchr(pstart, ';'); pend; pend = strchr(pstart, ';')) { |
145 char *path = g_strndup(pstart, pend - pstart); | |
1650
cd81806b5947
Try fallback language (en) when help file with current language is not found
Nixtrian
parents:
1599
diff
changeset
|
146 |
1678 | 147 dir_push_languages(langs, path); |
1650
cd81806b5947
Try fallback language (en) when help file with current language is not found
Nixtrian
parents:
1599
diff
changeset
|
148 |
1678 | 149 g_free(path); |
150 pstart = pend + 1; | |
151 } | |
868 | 152 |
1678 | 153 // last element |
154 dir_push_languages(langs, pstart); | |
868 | 155 } |
156 | |
1678 | 157 help_dirs_stalled = FALSE; |
158 } | |
159 | |
160 static gboolean do_help_in_dir(const char *arg, const char *path, const char *jid) | |
161 { | |
162 char *fname; | |
163 GIOChannel *channel; | |
164 GString *line; | |
165 int lines = 0; | |
166 | |
167 if (arg && *arg) | |
168 fname = g_strdup_printf("%s/hlp_%s.txt", path, arg); | |
169 else | |
170 fname = g_strdup_printf("%s/hlp.txt", path); | |
1729
e6e89b1d7831
Minor style and header updates
Mikael Berthe <mikael@lilotux.net>
parents:
1678
diff
changeset
|
171 |
1678 | 172 channel = g_io_channel_new_file(fname, "r", NULL); |
173 | |
174 if (!channel) | |
175 return FALSE; | |
176 | |
177 line = g_string_new(NULL); | |
178 | |
179 while (TRUE) { | |
180 gsize endpos; | |
181 GIOStatus ret; | |
1729
e6e89b1d7831
Minor style and header updates
Mikael Berthe <mikael@lilotux.net>
parents:
1678
diff
changeset
|
182 |
1678 | 183 ret = g_io_channel_read_line_string(channel, line, &endpos, NULL); |
184 if (ret != G_IO_STATUS_NORMAL) // XXX G_IO_STATUS_AGAIN? | |
185 break; | |
186 | |
187 line->str[endpos] = '\0'; | |
188 | |
189 if (jid) | |
190 scr_WriteIncomingMessage(jid, line->str, 0, | |
191 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); | |
192 else | |
193 scr_LogPrint(LPRINT_NORMAL, "%s", line->str); | |
194 | |
195 ++lines; | |
868 | 196 } |
1678 | 197 |
198 g_string_free(line, TRUE); | |
868 | 199 |
1678 | 200 if (!lines) |
201 return FALSE; | |
202 | |
203 if (!jid) { | |
892
94bb9e40e40b
Set the pending message flag on the status buffer when using /help
Mikael Berthe <mikael@lilotux.net>
parents:
882
diff
changeset
|
204 scr_setmsgflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE); |
94bb9e40e40b
Set the pending message flag on the status buffer when using /help
Mikael Berthe <mikael@lilotux.net>
parents:
882
diff
changeset
|
205 update_roster = TRUE; |
94bb9e40e40b
Set the pending message flag on the status buffer when using /help
Mikael Berthe <mikael@lilotux.net>
parents:
882
diff
changeset
|
206 } |
94bb9e40e40b
Set the pending message flag on the status buffer when using /help
Mikael Berthe <mikael@lilotux.net>
parents:
882
diff
changeset
|
207 |
1678 | 208 return TRUE; |
868 | 209 } |
210 | |
1678 | 211 void help_process(char *arg) |
212 { | |
213 gchar *string; | |
214 const char *jid = NULL; | |
215 gboolean done = FALSE; | |
216 | |
217 if (help_dirs_stalled) | |
218 init_help_dirs(); | |
219 | |
220 { // check input | |
221 char *c; | |
222 | |
223 for (c = arg; *c; ++c) | |
224 if (!isalnum(*c) && *c != '-' && *c != '_') { | |
225 scr_LogPrint(LPRINT_NORMAL, "Wrong help expression, " | |
226 "it can contain only alphbetic, numeric" | |
227 " characters and symbols '-' and '_'."); | |
228 return; | |
229 } | |
230 | |
231 string = g_strdup(arg); | |
232 mc_strtolower(string); | |
233 } | |
234 | |
235 if (settings_opt_get_int("help_to_current") && CURRENT_JID) | |
236 jid = CURRENT_JID; | |
1729
e6e89b1d7831
Minor style and header updates
Mikael Berthe <mikael@lilotux.net>
parents:
1678
diff
changeset
|
237 |
1678 | 238 { // search |
239 GSList *hel; | |
240 | |
241 for (hel = help_dirs; hel && !done; hel = hel->next) { | |
242 char *dir = (char *)hel->data; | |
243 done = do_help_in_dir(string, dir, jid); | |
244 } | |
245 } | |
246 | |
247 if (!done && string && *string) { // match and print any similar topics | |
248 GSList *hel; | |
249 GSList *matches = NULL; | |
250 | |
251 for (hel = help_dirs; hel; hel = hel->next) { | |
252 const char *path = (const char *)hel->data; | |
253 DIR *dd = opendir(path); | |
254 | |
255 if (dd) { | |
256 struct dirent *file; | |
257 | |
258 for (file = readdir(dd); file; file = readdir(dd)) { | |
259 const char *name = file->d_name; | |
260 | |
261 if (name && name[0] == 'h' && name[1] == 'l' && | |
262 name[2] == 'p' && name[3] == '_') { | |
263 const char *nstart = name + 4; | |
264 const char *nend = strrchr(nstart, '.'); | |
265 | |
266 if (nend) { | |
267 gsize len = nend - nstart; | |
268 | |
269 if (g_strstr_len(nstart, len, string)) { | |
270 gchar *match = g_strndup(nstart, len); | |
1729
e6e89b1d7831
Minor style and header updates
Mikael Berthe <mikael@lilotux.net>
parents:
1678
diff
changeset
|
271 |
1678 | 272 if (!g_slist_find_custom(matches, match, |
273 (GCompareFunc)strcmp)) | |
274 matches = g_slist_append(matches, match); | |
275 else | |
276 g_free(match); | |
277 | |
278 done = TRUE; | |
279 } | |
280 } | |
281 } | |
282 } | |
283 | |
284 closedir(dd); | |
285 } | |
286 } | |
287 | |
288 if (done) { | |
289 GString *message = g_string_new("No exact match found. " | |
290 "Keywords, that contain this word:"); | |
291 GSList *wel; | |
292 | |
293 for (wel = matches; wel; wel = wel->next) { | |
294 gchar *word = (gchar *)wel->data; | |
295 | |
296 g_string_append_printf(message, " %s,", word); | |
297 | |
298 g_free(wel->data); | |
299 } | |
300 | |
301 message->str[message->len - 1] = '.'; | |
302 | |
303 g_slist_free(matches); | |
304 | |
305 { | |
306 char *msg = g_string_free(message, FALSE); | |
307 | |
308 if (jid) | |
309 scr_WriteIncomingMessage(jid, msg, 0, | |
310 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); | |
311 else | |
312 scr_LogPrint(LPRINT_NORMAL, "%s", msg); | |
313 | |
314 g_free(msg); | |
315 } | |
316 } | |
317 } | |
318 | |
319 if (!done) { | |
320 if (jid) // XXX | |
321 scr_WriteIncomingMessage(jid, "No help found.", 0, | |
322 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); | |
323 else | |
324 scr_LogPrint(LPRINT_NORMAL, "No help found."); | |
325 } | |
326 | |
327 g_free(string); | |
328 } | |
329 | |
330 static gchar *help_guard(const gchar *key, const gchar *new_value) | |
331 { | |
332 help_dirs_stalled = TRUE; | |
333 return g_strdup(new_value); | |
334 } | |
335 | |
336 void help_init(void) | |
337 { | |
338 settings_set_guard("lang", help_guard); | |
339 settings_set_guard("help_dirs", help_guard); | |
340 } | |
341 | |
342 /* vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2: For Vim users... */ |