00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef lint
00021 static const char rcsid[] = "$Id: help.c,v 1.20 2004-10-17 05:14:06 stdarg Exp $";
00022 #endif
00023
00024 #include <eggdrop/eggdrop.h>
00025
00026 static help_file_t **help_files = NULL;
00027 static int nhelp_files = 0;
00028
00029 static help_section_t *sections = NULL;
00030 static int nsections = 0;
00031
00032 static char *help_path = NULL;
00033 static char *help_lang_default = NULL;
00034 static char *help_lang_fallback = "en_US";
00035
00036 int help_init()
00037 {
00038 help_path = strdup("help/");
00039 help_lang_default = strdup("en_US");
00040 return(0);
00041 }
00042
00043 int help_shutdown()
00044 {
00045 return(0);
00046 }
00047
00048 int help_set_default_path(const char *path)
00049 {
00050 str_redup(&help_path, path);
00051 return(0);
00052 }
00053
00054 int help_set_default_lang(const char *lang)
00055 {
00056 str_redup(&help_lang_default, lang);
00057 return(0);
00058 }
00059
00060 char *help_parse_syntax(xml_node_t *node)
00061 {
00062 xml_node_t *arg;
00063 char *name, *syntax, *args, *args2, *argname;
00064 int optional;
00065
00066 xml_node_get_vars(node, "sn", "name", &name, "args.arg", &arg);
00067 args = strdup("");
00068 for (; arg; arg = arg->next_sibling) {
00069 xml_node_get_vars(arg, "si", "name", &argname, "optional", &optional);
00070 if (!name) continue;
00071 if (optional) args2 = egg_mprintf("%s [%s]", args, argname);
00072 else args2 = egg_mprintf("%s <%s>", args, argname);
00073 free(args);
00074 args = args2;
00075 }
00076 syntax = egg_mprintf("%s%s", name, args);
00077 free(args);
00078 return(syntax);
00079 }
00080
00081 help_summary_t *help_summarize_entry(xml_node_t *node)
00082 {
00083 help_summary_t *entry;
00084 char *name, *summary, *syntax;
00085 int len;
00086
00087 xml_node_get_vars(node, "ss", "name", &name, "summary", &summary);
00088 if (!name) return(NULL);
00089
00090 syntax = help_parse_syntax(node);
00091
00092
00093 len = strlen(name) + strlen(syntax);
00094 if (summary) len += strlen(summary);
00095 entry = malloc(sizeof(*entry) + len + 3);
00096 entry->name = ((char *)entry) + sizeof(*entry);
00097 entry->syntax = entry->name + strlen(name)+1;
00098 entry->summary = entry->syntax + strlen(syntax)+1;
00099 strcpy(entry->name, name);
00100 strcpy(entry->syntax, syntax);
00101 if (summary) strcpy(entry->summary, summary);
00102 else entry->summary[0] = 0;
00103 free(syntax);
00104 return(entry);
00105 }
00106
00107 int help_parse_file(const char *fname)
00108 {
00109 xml_node_t *root = xml_parse_file(fname);
00110 xml_node_t *node;
00111 char *secname;
00112 help_summary_t *entry;
00113 help_section_t *section;
00114 int i;
00115
00116 if (!root) return(-1);
00117
00118 xml_node_get_vars(root, "sn", "section", &secname, "help", &node);
00119 if (!secname || !node) {
00120 xml_node_delete(root);
00121 return(-1);
00122 }
00123
00124 for (i = 0; i < nsections; i++) {
00125 if (!strcasecmp(sections[i].name, secname)) break;
00126 }
00127 if (i == nsections) {
00128 sections = realloc(sections, sizeof(*sections) * (nsections+1));
00129 sections[nsections].name = strdup(secname);
00130 sections[nsections].entries = NULL;
00131 sections[nsections].nentries = 0;
00132 nsections++;
00133 }
00134 section = sections+i;
00135
00136 help_files = realloc(help_files, sizeof(*help_files) * (nhelp_files+1));
00137 help_files[nhelp_files] = malloc(sizeof(**help_files));
00138 help_files[nhelp_files]->name = strdup(fname);
00139 help_files[nhelp_files]->ref = 0;
00140
00141 for (; node; node = node->next_sibling) {
00142 entry = help_summarize_entry(node);
00143 if (!entry) continue;
00144 entry->file = help_files[nhelp_files];
00145 help_files[nhelp_files]->ref++;
00146 section->entries = realloc(section->entries, sizeof(entry) * (section->nentries+1));
00147 section->entries[section->nentries] = entry;
00148 section->nentries++;
00149 }
00150 nhelp_files++;
00151 xml_node_delete(root);
00152 return(0);
00153 }
00154
00155 help_summary_t *help_lookup_summary(const char *name)
00156 {
00157 int i, j;
00158 help_section_t *section;
00159
00160 for (i = 0; i < nsections; i++) {
00161 section = sections+i;
00162 for (j = 0; j < section->nentries; j++) {
00163 if (!strcasecmp(section->entries[j]->name, name)) {
00164 return(section->entries[j]);
00165 }
00166 }
00167 }
00168 return(NULL);
00169 }
00170
00171 xml_node_t *help_lookup_entry(help_summary_t *entry)
00172 {
00173 xml_node_t *root = xml_parse_file(entry->file->name);
00174 xml_node_t *node;
00175 char *name;
00176
00177 node = xml_node_lookup(root, 0, "help", 0, 0);
00178 for (; node; node = node->next_sibling) {
00179 xml_node_get_str(&name, node, "name", 0, 0);
00180 if (name && !strcasecmp(name, entry->name)) {
00181 xml_node_unlink(node);
00182 break;
00183 }
00184 }
00185 return(node);
00186 }
00187
00188 static void localized_help_fname(char *buf, size_t size, const char *filename)
00189 {
00190 char *lang;
00191 char *pos;
00192
00193 lang = getenv("LANG");
00194 if (lang) {
00195 lang = strdup(lang);
00196 pos = strchr(lang, '.');
00197 if (pos == NULL) {
00198 free(lang);
00199 lang = strdup(help_lang_default);
00200 }
00201 else *pos = 0;
00202 } else {
00203 lang = strdup(help_lang_default);
00204 }
00205
00206 snprintf(buf, size, "%s/%s/%s", help_path, lang, filename);
00207 free(lang);
00208 }
00209
00210 int help_load_by_module(const char *name)
00211 {
00212 char fullname[256], buf[256];
00213
00214 snprintf(fullname, sizeof(fullname), "%s-commands.xml", name);
00215 localized_help_fname(buf, sizeof(buf), fullname);
00216 if (help_parse_file(buf)) {
00217 snprintf(buf, sizeof(buf), "%s/%s/%s", help_path, help_lang_fallback, fullname);
00218 help_parse_file(buf);
00219 }
00220 return(0);
00221 }
00222
00223 help_search_t *help_search_new(const char *searchstr)
00224 {
00225 help_search_t *search;
00226
00227 search = calloc(1, sizeof(*search));
00228 search->search = strdup(searchstr);
00229 return(search);
00230 }
00231
00232 int help_search_end(help_search_t *search)
00233 {
00234 free(search->search);
00235 free(search);
00236 return(0);
00237 }
00238
00239 help_summary_t *help_search_result(help_search_t *search)
00240 {
00241 help_section_t *section;
00242 help_summary_t *entry;
00243
00244 if (search->cursection < 0 || search->curentry < 0 || !search->search) return(NULL);
00245
00246 while (search->cursection < nsections) {
00247 section = sections+search->cursection;
00248 while (search->curentry < section->nentries) {
00249 entry = section->entries[search->curentry++];
00250 if (wild_match(search->search, entry->name)) return(entry);
00251 }
00252 search->cursection++;
00253 search->curentry = 0;
00254 }
00255 search->cursection = search->curentry = -1;
00256 return(NULL);
00257 }