Mercurial > ~mikael > mcabber > hg
annotate mcabber/mcabber/help.c @ 1898:e25cec543da1
Fix two MUC issues (reported by VarLog)
- Reason sometimes missing after kick/ban (fixed by isbear)
- mcabber not realizing it's been kicked
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Mon, 12 Apr 2010 23:24:20 +0200 |
parents | 60db836ad98a |
children | 84bb3e893586 |
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); |
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... */ |