Mercurial > ~mikael > mcabber > hg
annotate mcabber/mcabber/help.c @ 2188:84252c616919
PGP: Encrypt messages with our own PGP key when carbons are enabled
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Sun, 04 Oct 2015 19:04:43 +0200 |
parents | 33483d3324cf |
children | f5402d705f67 |
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 | |
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 |
1912 | 198 g_io_channel_unref(channel); |
199 | |
1678 | 200 g_string_free(line, TRUE); |
868 | 201 |
1678 | 202 if (!lines) |
203 return FALSE; | |
204 | |
205 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
|
206 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
|
207 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
|
208 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
|
209 } |
94bb9e40e40b
Set the pending message flag on the status buffer when using /help
Mikael Berthe <mikael@lilotux.net>
parents:
882
diff
changeset
|
210 |
1678 | 211 return TRUE; |
868 | 212 } |
213 | |
1678 | 214 void help_process(char *arg) |
215 { | |
216 gchar *string; | |
217 const char *jid = NULL; | |
218 gboolean done = FALSE; | |
219 | |
220 if (help_dirs_stalled) | |
221 init_help_dirs(); | |
222 | |
223 { // check input | |
224 char *c; | |
225 | |
226 for (c = arg; *c; ++c) | |
227 if (!isalnum(*c) && *c != '-' && *c != '_') { | |
228 scr_LogPrint(LPRINT_NORMAL, "Wrong help expression, " | |
229 "it can contain only alphbetic, numeric" | |
230 " characters and symbols '-' and '_'."); | |
231 return; | |
232 } | |
233 | |
234 string = g_strdup(arg); | |
235 mc_strtolower(string); | |
236 } | |
237 | |
238 if (settings_opt_get_int("help_to_current") && CURRENT_JID) | |
239 jid = CURRENT_JID; | |
1729
e6e89b1d7831
Minor style and header updates
Mikael Berthe <mikael@lilotux.net>
parents:
1678
diff
changeset
|
240 |
1678 | 241 { // search |
242 GSList *hel; | |
243 | |
244 for (hel = help_dirs; hel && !done; hel = hel->next) { | |
245 char *dir = (char *)hel->data; | |
246 done = do_help_in_dir(string, dir, jid); | |
247 } | |
248 } | |
249 | |
250 if (!done && string && *string) { // match and print any similar topics | |
251 GSList *hel; | |
252 GSList *matches = NULL; | |
253 | |
254 for (hel = help_dirs; hel; hel = hel->next) { | |
255 const char *path = (const char *)hel->data; | |
256 DIR *dd = opendir(path); | |
257 | |
258 if (dd) { | |
259 struct dirent *file; | |
260 | |
261 for (file = readdir(dd); file; file = readdir(dd)) { | |
262 const char *name = file->d_name; | |
263 | |
264 if (name && name[0] == 'h' && name[1] == 'l' && | |
265 name[2] == 'p' && name[3] == '_') { | |
266 const char *nstart = name + 4; | |
267 const char *nend = strrchr(nstart, '.'); | |
268 | |
269 if (nend) { | |
270 gsize len = nend - nstart; | |
271 | |
272 if (g_strstr_len(nstart, len, string)) { | |
273 gchar *match = g_strndup(nstart, len); | |
1729
e6e89b1d7831
Minor style and header updates
Mikael Berthe <mikael@lilotux.net>
parents:
1678
diff
changeset
|
274 |
1678 | 275 if (!g_slist_find_custom(matches, match, |
276 (GCompareFunc)strcmp)) | |
277 matches = g_slist_append(matches, match); | |
278 else | |
279 g_free(match); | |
280 | |
281 done = TRUE; | |
282 } | |
283 } | |
284 } | |
285 } | |
286 | |
287 closedir(dd); | |
288 } | |
289 } | |
290 | |
291 if (done) { | |
292 GString *message = g_string_new("No exact match found. " | |
293 "Keywords, that contain this word:"); | |
294 GSList *wel; | |
295 | |
296 for (wel = matches; wel; wel = wel->next) { | |
297 gchar *word = (gchar *)wel->data; | |
298 | |
299 g_string_append_printf(message, " %s,", word); | |
300 | |
301 g_free(wel->data); | |
302 } | |
303 | |
304 message->str[message->len - 1] = '.'; | |
305 | |
306 g_slist_free(matches); | |
307 | |
308 { | |
309 char *msg = g_string_free(message, FALSE); | |
310 | |
311 if (jid) | |
312 scr_WriteIncomingMessage(jid, msg, 0, | |
313 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); | |
314 else | |
315 scr_LogPrint(LPRINT_NORMAL, "%s", msg); | |
316 | |
317 g_free(msg); | |
318 } | |
319 } | |
320 } | |
321 | |
322 if (!done) { | |
323 if (jid) // XXX | |
324 scr_WriteIncomingMessage(jid, "No help found.", 0, | |
325 HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); | |
326 else | |
327 scr_LogPrint(LPRINT_NORMAL, "No help found."); | |
328 } | |
329 | |
330 g_free(string); | |
331 } | |
332 | |
333 static gchar *help_guard(const gchar *key, const gchar *new_value) | |
334 { | |
335 help_dirs_stalled = TRUE; | |
336 return g_strdup(new_value); | |
337 } | |
338 | |
339 void help_init(void) | |
340 { | |
341 settings_set_guard("lang", help_guard); | |
342 settings_set_guard("help_dirs", help_guard); | |
343 } | |
344 | |
345 /* vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2: For Vim users... */ |