Mercurial > ~mikael > mcabber > hg
view 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 |
line wrap: on
line source
/* * help.c -- Help command * * Copyright (C) 2006-2010 Mikael Berthe <mikael@lilotux.net> * Copyrigth (C) 2009 Myhailo Danylenko <isbear@ukrpost.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ /* * How it works * * Main calls help_init, that installs option guards. These guards do * nothing, but set help_dirs_stalled flag. When user issues help command, * it checks, if help_dirs_stalled flag is set, and if it is, it calls * init_help_dirs before performing help search. * * Options: * lang List of semicolon-separated language codes. If unset, will * be detected from locale, with fallback to english. * help_dirs List of semicolon-seaparated directories, where search for * help (in language subdirectories) will be performed. * Defaults to DATA_DIR/mcabber/help. * help_to_current Print help to current buddy's buffer. * * XXX: * Remove command list from hlp.txt and print detected list of all help * topics? */ #include <glib.h> #include <string.h> #include <locale.h> #include <sys/types.h> #include <dirent.h> #include "logprint.h" #include "screen.h" #include "hbuf.h" #include "settings.h" #include "utils.h" static GSList *help_dirs = NULL; static gboolean help_dirs_stalled = TRUE; void free_help_dirs(void) { GSList *hel; for (hel = help_dirs; hel; hel = hel->next) g_free(hel->data); g_slist_free(help_dirs); help_dirs = NULL; } void dir_push_languages(const char *langs, const char *dir) { const char *lstart = langs; const char *lend; char *path = expand_filename(dir); for (lend = strchr(lstart, ';'); lend; lend = strchr(lstart, ';')) { char *lang = g_strndup(lstart, lend - lstart); char *dir = g_strdup_printf("%s/%s", path, lang); help_dirs = g_slist_append(help_dirs, dir); g_free(lang); lstart = lend + 1; } { // finishing element char *dir = g_strdup_printf("%s/%s", path, lstart); help_dirs = g_slist_append(help_dirs, dir); } g_free(path); } void init_help_dirs(void) { const char *paths; const char *langs; char lang[6]; if (help_dirs) free_help_dirs(); // initialize variables paths = settings_opt_get("help_dirs"); if (!paths || !*paths) #ifdef DATA_DIR paths = DATA_DIR "/mcabber/help"; #else paths = "/usr/local/share/mcabber/help;/usr/share/mcabber/help"; #endif langs = settings_opt_get("lang"); if (!langs || !*langs) { char *locale = setlocale(LC_MESSAGES, NULL); // XXX crude method to distinguish between xx_XX xx xx@xxx // and C POSIX NULL etc. if (locale && isalpha(locale[0]) && isalpha(locale[1]) && !isalpha(locale[2])) { lang[0] = locale[0]; lang[1] = locale[1]; if (lang[0] == 'e' && lang[1] == 'n') lang[2] = '\0'; else { lang[2] = ';'; lang[3] = 'e'; lang[4] = 'n'; lang[5] = '\0'; } langs = lang; } else langs = "en"; } { // parse const char *pstart = paths; const char *pend; for (pend = strchr(pstart, ';'); pend; pend = strchr(pstart, ';')) { char *path = g_strndup(pstart, pend - pstart); dir_push_languages(langs, path); g_free(path); pstart = pend + 1; } // last element dir_push_languages(langs, pstart); } help_dirs_stalled = FALSE; } static gboolean do_help_in_dir(const char *arg, const char *path, const char *jid) { char *fname; GIOChannel *channel; GString *line; int lines = 0; if (arg && *arg) fname = g_strdup_printf("%s/hlp_%s.txt", path, arg); else fname = g_strdup_printf("%s/hlp.txt", path); channel = g_io_channel_new_file(fname, "r", NULL); if (!channel) return FALSE; line = g_string_new(NULL); while (TRUE) { gsize endpos; GIOStatus ret; ret = g_io_channel_read_line_string(channel, line, &endpos, NULL); if (ret != G_IO_STATUS_NORMAL) // XXX G_IO_STATUS_AGAIN? break; line->str[endpos] = '\0'; if (jid) scr_WriteIncomingMessage(jid, line->str, 0, HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); else scr_LogPrint(LPRINT_NORMAL, "%s", line->str); ++lines; } g_string_free(line, TRUE); if (!lines) return FALSE; if (!jid) { scr_setmsgflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE); scr_setattentionflag_if_needed(SPECIAL_BUFFER_STATUS_ID, TRUE, ROSTER_UI_PRIO_STATUS_WIN_MESSAGE, prio_max); } return TRUE; } void help_process(char *arg) { gchar *string; const char *jid = NULL; gboolean done = FALSE; if (help_dirs_stalled) init_help_dirs(); { // check input char *c; for (c = arg; *c; ++c) if (!isalnum(*c) && *c != '-' && *c != '_') { scr_LogPrint(LPRINT_NORMAL, "Wrong help expression, " "it can contain only alphbetic, numeric" " characters and symbols '-' and '_'."); return; } string = g_strdup(arg); mc_strtolower(string); } if (settings_opt_get_int("help_to_current") && CURRENT_JID) jid = CURRENT_JID; { // search GSList *hel; for (hel = help_dirs; hel && !done; hel = hel->next) { char *dir = (char *)hel->data; done = do_help_in_dir(string, dir, jid); } } if (!done && string && *string) { // match and print any similar topics GSList *hel; GSList *matches = NULL; for (hel = help_dirs; hel; hel = hel->next) { const char *path = (const char *)hel->data; DIR *dd = opendir(path); if (dd) { struct dirent *file; for (file = readdir(dd); file; file = readdir(dd)) { const char *name = file->d_name; if (name && name[0] == 'h' && name[1] == 'l' && name[2] == 'p' && name[3] == '_') { const char *nstart = name + 4; const char *nend = strrchr(nstart, '.'); if (nend) { gsize len = nend - nstart; if (g_strstr_len(nstart, len, string)) { gchar *match = g_strndup(nstart, len); if (!g_slist_find_custom(matches, match, (GCompareFunc)strcmp)) matches = g_slist_append(matches, match); else g_free(match); done = TRUE; } } } } closedir(dd); } } if (done) { GString *message = g_string_new("No exact match found. " "Keywords, that contain this word:"); GSList *wel; for (wel = matches; wel; wel = wel->next) { gchar *word = (gchar *)wel->data; g_string_append_printf(message, " %s,", word); g_free(wel->data); } message->str[message->len - 1] = '.'; g_slist_free(matches); { char *msg = g_string_free(message, FALSE); if (jid) scr_WriteIncomingMessage(jid, msg, 0, HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); else scr_LogPrint(LPRINT_NORMAL, "%s", msg); g_free(msg); } } } if (!done) { if (jid) // XXX scr_WriteIncomingMessage(jid, "No help found.", 0, HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); else scr_LogPrint(LPRINT_NORMAL, "No help found."); } g_free(string); } static gchar *help_guard(const gchar *key, const gchar *new_value) { help_dirs_stalled = TRUE; return g_strdup(new_value); } void help_init(void) { settings_set_guard("lang", help_guard); settings_set_guard("help_dirs", help_guard); } /* vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2: For Vim users... */