Mercurial > ~mikael > mcabber > hg
annotate mcabber/mcabber/help.c @ 2270:5d05e8128ef4
Use nick to set the role
This should fix issue #152, reported by Stefan Haller.
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Sat, 17 Sep 2016 10:02:56 +0200 |
parents | f5402d705f67 |
children |
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> |
2019
33483d3324cf
s/Copyrigth/Copyright/ and so on
Myhailo Danylenko <isbear@ukrpost.net>
parents:
1912
diff
changeset
|
5 * Copyright (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 | |
2268
f5402d705f67
Fix FSF addresses in all files
Mikael Berthe <mikael@lilotux.net>
parents:
2019
diff
changeset
|
18 * along with this program; if not, see <http://www.gnu.org/licenses/>. |
868 | 19 */ |
20 | |
1678 | 21 /* |
22 * How it works | |
23 * | |
24 * Main calls help_init, that installs option guards. These guards do | |
25 * nothing, but set help_dirs_stalled flag. When user issues help command, | |
26 * it checks, if help_dirs_stalled flag is set, and if it is, it calls | |
27 * init_help_dirs before performing help search. | |
28 * | |
29 * Options: | |
30 * lang List of semicolon-separated language codes. If unset, will | |
31 * be detected from locale, with fallback to english. | |
32 * help_dirs List of semicolon-seaparated directories, where search for | |
33 * help (in language subdirectories) will be performed. | |
34 * Defaults to DATA_DIR/mcabber/help. | |
35 * help_to_current Print help to current buddy's buffer. | |
36 * | |
37 * XXX: | |
38 * Remove command list from hlp.txt and print detected list of all help | |
39 * topics? | |
40 */ | |
868 | 41 |
1678 | 42 #include <glib.h> |
43 #include <string.h> | |
44 #include <locale.h> | |
45 #include <sys/types.h> | |
46 #include <dirent.h> | |
47 | |
48 #include "logprint.h" | |
49 #include "screen.h" | |
50 #include "hbuf.h" | |
868 | 51 #include "settings.h" |
52 #include "utils.h" | |
53 | |
1678 | 54 static GSList *help_dirs = NULL; |
55 static gboolean help_dirs_stalled = TRUE; | |
868 | 56 |
1678 | 57 void free_help_dirs(void) |
58 { | |
59 GSList *hel; | |
60 | |
61 for (hel = help_dirs; hel; hel = hel->next) | |
62 g_free(hel->data); | |
63 | |
64 g_slist_free(help_dirs); | |
65 | |
66 help_dirs = NULL; | |
67 } | |
68 | |
69 void dir_push_languages(const char *langs, const char *dir) | |
70 { | |
71 const char *lstart = langs; | |
72 const char *lend; | |
73 char *path = expand_filename(dir); | |
74 | |
75 for (lend = strchr(lstart, ';'); lend; lend = strchr(lstart, ';')) { | |
76 char *lang = g_strndup(lstart, lend - lstart); | |
77 char *dir = g_strdup_printf("%s/%s", path, lang); | |
78 | |
79 help_dirs = g_slist_append(help_dirs, dir); | |
80 | |
81 g_free(lang); | |
82 lstart = lend + 1; | |
868 | 83 } |
1678 | 84 |
85 { // finishing element | |
86 char *dir = g_strdup_printf("%s/%s", path, lstart); | |
87 | |
88 help_dirs = g_slist_append(help_dirs, dir); | |
89 } | |
90 | |
91 g_free(path); | |
868 | 92 } |
93 | |
1678 | 94 void init_help_dirs(void) |
868 | 95 { |
1678 | 96 const char *paths; |
97 const char *langs; | |
98 char lang[6]; | |
99 | |
100 if (help_dirs) | |
101 free_help_dirs(); | |
102 | |
103 // initialize variables | |
104 paths = settings_opt_get("help_dirs"); | |
105 if (!paths || !*paths) | |
106 #ifdef DATA_DIR | |
107 paths = DATA_DIR "/mcabber/help"; | |
868 | 108 #else |
1678 | 109 paths = "/usr/local/share/mcabber/help;/usr/share/mcabber/help"; |
110 #endif | |
111 | |
112 langs = settings_opt_get("lang"); | |
113 | |
114 if (!langs || !*langs) { | |
115 char *locale = setlocale(LC_MESSAGES, NULL); | |
868 | 116 |
1678 | 117 // XXX crude method to distinguish between xx_XX xx xx@xxx |
118 // and C POSIX NULL etc. | |
119 if (locale && isalpha(locale[0]) && isalpha(locale[1]) | |
120 && !isalpha(locale[2])) { | |
121 lang[0] = locale[0]; | |
122 lang[1] = locale[1]; | |
123 | |
124 if (lang[0] == 'e' && lang[1] == 'n') | |
125 lang[2] = '\0'; | |
126 else { | |
127 lang[2] = ';'; | |
128 lang[3] = 'e'; | |
129 lang[4] = 'n'; | |
130 lang[5] = '\0'; | |
131 } | |
132 | |
133 langs = lang; | |
134 } else | |
135 langs = "en"; | |
868 | 136 } |
137 | |
1678 | 138 { // parse |
139 const char *pstart = paths; | |
140 const char *pend; | |
1650
cd81806b5947
Try fallback language (en) when help file with current language is not found
Nixtrian
parents:
1599
diff
changeset
|
141 |
1678 | 142 for (pend = strchr(pstart, ';'); pend; pend = strchr(pstart, ';')) { |
143 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
|
144 |
1678 | 145 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
|
146 |
1678 | 147 g_free(path); |
148 pstart = pend + 1; | |
149 } | |
868 | 150 |
1678 | 151 // last element |
152 dir_push_languages(langs, pstart); | |
868 | 153 } |
154 | |
1678 | 155 help_dirs_stalled = FALSE; |
156 } | |
157 | |
158 static gboolean do_help_in_dir(const char *arg, const char *path, const char *jid) | |
159 { | |
160 char *fname; | |
161 GIOChannel *channel; | |
162 GString *line; | |
163 int lines = 0; | |
164 | |
165 if (arg && *arg) | |
166 fname = g_strdup_printf("%s/hlp_%s.txt", path, arg); | |
167 else | |
168 fname = g_strdup_printf("%s/hlp.txt", path); | |
1729
e6e89b1d7831
Minor style and header updates
Mikael Berthe <mikael@lilotux.net>
parents:
1678
diff
changeset
|
169 |
1678 | 170 channel = g_io_channel_new_file(fname, "r", NULL); |
171 | |
172 if (!channel) | |
173 return FALSE; | |
174 | |
175 line = g_string_new(NULL); | |
176 | |
177 while (TRUE) { | |
178 gsize endpos; | |
179 GIOStatus ret; | |
1729
e6e89b1d7831
Minor style and header updates
Mikael Berthe <mikael@lilotux.net>
parents:
1678
diff
changeset
|
180 |
1678 | 181 ret = g_io_channel_read_line_string(channel, line, &endpos, NULL); |
182 if (ret != G_IO_STATUS_NORMAL) // XXX G_IO_STATUS_AGAIN? | |
183 break; | |
184 | |
185 line->str[endpos] = '\0'; | |
186 | |
187 if (jid) | |
188 scr_WriteIncomingMessage(jid, line->str, 0, | |
189 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); | |
190 else | |
191 scr_LogPrint(LPRINT_NORMAL, "%s", line->str); | |
192 | |
193 ++lines; | |
868 | 194 } |
1678 | 195 |
1912 | 196 g_io_channel_unref(channel); |
197 | |
1678 | 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... */ |