Mercurial > ~mikael > mcabber > hg
annotate mcabber/mcabber/help.c @ 1909:9c14153e2580
Do not display unhandled IQ result messages to the log window
We display the message only in the debug log file, because these messages
are usually ignored anyway (ideally we would create a handler explicitly
when sending the initial IQ request).
Thanks to VarLog for the report!
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Sun, 18 Apr 2010 14:14:05 +0200 |
parents | 84bb3e893586 |
children | ee8657ff9aa8 |
rev | line source |
---|---|
868 | 1 /* |
2 * help.c -- Help command | |
3 * | |
1901
84bb3e893586
Update some file headers
Mikael Berthe <mikael@lilotux.net>
parents:
1821
diff
changeset
|
4 * Copyright (C) 2006-2010 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); |
1815
6abca6000762
Make use of ROSTER_UI_PRIO_STATUS_WIN_MESSAGE
Mikael Berthe <mikael@lilotux.net>
parents:
1729
diff
changeset
|
205 scr_setattentionflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE, |
6abca6000762
Make use of ROSTER_UI_PRIO_STATUS_WIN_MESSAGE
Mikael Berthe <mikael@lilotux.net>
parents:
1729
diff
changeset
|
206 ROSTER_UI_PRIO_STATUS_WIN_MESSAGE, prio_max); |
892
94bb9e40e40b
Set the pending message flag on the status buffer when using /help
Mikael Berthe <mikael@lilotux.net>
parents:
882
diff
changeset
|
207 } |
94bb9e40e40b
Set the pending message flag on the status buffer when using /help
Mikael Berthe <mikael@lilotux.net>
parents:
882
diff
changeset
|
208 |
1678 | 209 return TRUE; |
868 | 210 } |
211 | |
1678 | 212 void help_process(char *arg) |
213 { | |
214 gchar *string; | |
215 const char *jid = NULL; | |
216 gboolean done = FALSE; | |
217 | |
218 if (help_dirs_stalled) | |
219 init_help_dirs(); | |
220 | |
221 { // check input | |
222 char *c; | |
223 | |
224 for (c = arg; *c; ++c) | |
225 if (!isalnum(*c) && *c != '-' && *c != '_') { | |
226 scr_LogPrint(LPRINT_NORMAL, "Wrong help expression, " | |
227 "it can contain only alphbetic, numeric" | |
228 " characters and symbols '-' and '_'."); | |
229 return; | |
230 } | |
231 | |
232 string = g_strdup(arg); | |
233 mc_strtolower(string); | |
234 } | |
235 | |
236 if (settings_opt_get_int("help_to_current") && CURRENT_JID) | |
237 jid = CURRENT_JID; | |
1729
e6e89b1d7831
Minor style and header updates
Mikael Berthe <mikael@lilotux.net>
parents:
1678
diff
changeset
|
238 |
1678 | 239 { // search |
240 GSList *hel; | |
241 | |
242 for (hel = help_dirs; hel && !done; hel = hel->next) { | |
243 char *dir = (char *)hel->data; | |
244 done = do_help_in_dir(string, dir, jid); | |
245 } | |
246 } | |
247 | |
248 if (!done && string && *string) { // match and print any similar topics | |
249 GSList *hel; | |
250 GSList *matches = NULL; | |
251 | |
252 for (hel = help_dirs; hel; hel = hel->next) { | |
253 const char *path = (const char *)hel->data; | |
254 DIR *dd = opendir(path); | |
255 | |
256 if (dd) { | |
257 struct dirent *file; | |
258 | |
259 for (file = readdir(dd); file; file = readdir(dd)) { | |
260 const char *name = file->d_name; | |
261 | |
262 if (name && name[0] == 'h' && name[1] == 'l' && | |
263 name[2] == 'p' && name[3] == '_') { | |
264 const char *nstart = name + 4; | |
265 const char *nend = strrchr(nstart, '.'); | |
266 | |
267 if (nend) { | |
268 gsize len = nend - nstart; | |
269 | |
270 if (g_strstr_len(nstart, len, string)) { | |
271 gchar *match = g_strndup(nstart, len); | |
1729
e6e89b1d7831
Minor style and header updates
Mikael Berthe <mikael@lilotux.net>
parents:
1678
diff
changeset
|
272 |
1678 | 273 if (!g_slist_find_custom(matches, match, |
274 (GCompareFunc)strcmp)) | |
275 matches = g_slist_append(matches, match); | |
276 else | |
277 g_free(match); | |
278 | |
279 done = TRUE; | |
280 } | |
281 } | |
282 } | |
283 } | |
284 | |
285 closedir(dd); | |
286 } | |
287 } | |
288 | |
289 if (done) { | |
290 GString *message = g_string_new("No exact match found. " | |
291 "Keywords, that contain this word:"); | |
292 GSList *wel; | |
293 | |
294 for (wel = matches; wel; wel = wel->next) { | |
295 gchar *word = (gchar *)wel->data; | |
296 | |
297 g_string_append_printf(message, " %s,", word); | |
298 | |
299 g_free(wel->data); | |
300 } | |
301 | |
302 message->str[message->len - 1] = '.'; | |
303 | |
304 g_slist_free(matches); | |
305 | |
306 { | |
307 char *msg = g_string_free(message, FALSE); | |
308 | |
309 if (jid) | |
310 scr_WriteIncomingMessage(jid, msg, 0, | |
311 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); | |
312 else | |
313 scr_LogPrint(LPRINT_NORMAL, "%s", msg); | |
314 | |
315 g_free(msg); | |
316 } | |
317 } | |
318 } | |
319 | |
320 if (!done) { | |
321 if (jid) // XXX | |
322 scr_WriteIncomingMessage(jid, "No help found.", 0, | |
323 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); | |
324 else | |
325 scr_LogPrint(LPRINT_NORMAL, "No help found."); | |
326 } | |
327 | |
328 g_free(string); | |
329 } | |
330 | |
331 static gchar *help_guard(const gchar *key, const gchar *new_value) | |
332 { | |
333 help_dirs_stalled = TRUE; | |
334 return g_strdup(new_value); | |
335 } | |
336 | |
337 void help_init(void) | |
338 { | |
339 settings_set_guard("lang", help_guard); | |
340 settings_set_guard("help_dirs", help_guard); | |
341 } | |
342 | |
343 /* vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2: For Vim users... */ |