Atrinik Client  4.0
help.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
32 #include <global.h>
33 #include <toolkit/string.h>
34 
38 static hfile_struct *hfiles = NULL;
42 static UT_array *command_matches = NULL;
47 static size_t command_index = 0;
51 static char command_buf[HUGE_BUF];
52 
56 static void hfile_free(hfile_struct *hfile)
57 {
58  efree(hfile->key);
59 
60  if (hfile->msg != NULL) {
61  efree(hfile->msg);
62  }
63 
64  efree(hfile);
65 }
66 
70 void hfiles_deinit(void)
71 {
72  hfile_struct *hfile, *tmp;
73 
74  HASH_ITER(hh, hfiles, hfile, tmp)
75  {
76  HASH_DEL(hfiles, hfile);
77  hfile_free(hfile);
78  }
79 
80  if (command_matches) {
81  utarray_free(command_matches);
82  command_matches = NULL;
83  }
84 }
85 
89 void hfiles_init(void)
90 {
91  FILE *fp;
92  char buf[HUGE_BUF], *key, *value, *end;
93  hfile_struct *hfile;
94  StringBuffer *sb;
95 
96  fp = server_file_open_name(SERVER_FILE_HFILES);
97 
98  if (fp == NULL) {
99  LOG(BUG, "Could not open help files: %s", strerror(errno));
100  return;
101  }
102 
103  hfiles_deinit();
104  hfile = NULL;
105 
106  while (fgets(buf, sizeof(buf), fp)) {
107  key = buf;
108 
109  while (isspace(*key)) {
110  key++;
111  }
112 
113  end = strchr(buf, '\n');
114 
115  if (end != NULL) {
116  *end = '\0';
117  }
118 
119  /* Empty line or a comment */
120  if (*key == '\0' || *key == '#') {
121  continue;
122  }
123 
124  value = strchr(key, ' ');
125 
126  if (value != NULL) {
127  *value = '\0';
128  value++;
129 
130  while (isspace(*value)) {
131  value++;
132  }
133  }
134 
135  if (hfile == NULL) {
136  if (strcmp(key, "help") == 0 && !string_isempty(value)) {
137  hfile = ecalloc(1, sizeof(*hfile));
138  hfile->key = estrdup(value);
139  } else {
140  LOG(DEVEL, "Unrecognised line: %s %s", buf,
141  value ? value : "");
142  }
143  } else if (value == NULL) {
144  if (strcmp(key, "msg") == 0) {
145  sb = stringbuffer_new();
146 
147  if (hfile->msg != NULL) {
148  stringbuffer_append_string(sb, hfile->msg);
149  efree(hfile->msg);
150  }
151 
152  while (fgets(buf, sizeof(buf), fp)) {
153  if (strcmp(buf, "endmsg\n") == 0) {
154  break;
155  }
156 
157  stringbuffer_append_string(sb, buf);
158  }
159 
160  hfile->msg = stringbuffer_finish(sb);
161  } else if (strcmp(key, "end") == 0) {
162  if (hfile->msg != NULL) {
163  hfile->msg_len = strlen(hfile->msg);
164  }
165 
166  HASH_ADD_KEYPTR(hh, hfiles, hfile->key, strlen(hfile->key),
167  hfile);
168  hfile = NULL;
169  } else {
170  LOG(DEVEL, "Unrecognised line: %s %s", buf,
171  value ? value : "");
172  }
173  } else if (strcmp(key, "autocomplete") == 0) {
174  hfile->autocomplete = atoi(value);
175  } else if (strcmp(key, "autocomplete_wiz") == 0) {
176  hfile->autocomplete_wiz = atoi(value);
177  } else if (strcmp(key, "title") == 0) {
178  sb = stringbuffer_new();
179  stringbuffer_append_printf(sb, "[book]%s[/book]", value);
180  hfile->msg = stringbuffer_finish(sb);
181  } else {
182  LOG(DEVEL, "Unrecognised line: %s %s", buf,
183  value ? value : "");
184  }
185  }
186 
187  fclose(fp);
188 
189  if (hfile != NULL) {
190  LOG(BUG, "Help block without end: %s", hfile->key);
191  hfile_free(hfile);
192  }
193 
194  command_buf[0] = '\0';
195  utarray_new(command_matches, &ut_str_icd);
196 }
197 
205 hfile_struct *help_find(const char *name)
206 {
207  hfile_struct *hfile;
208 
209  HASH_FIND_STR(hfiles, name, hfile);
210 
211  return hfile;
212 }
213 
219 void help_show(const char *name)
220 {
221  hfile_struct *hfile;
222 
223  hfile = help_find(name);
224  book_add_help_history(name);
225 
226  if (hfile == NULL) {
227  char buf[HUGE_BUF];
228 
229  snprintf(VS(buf), "[book]Help not found[/book][title]\n[center]The "
230  "specified help file could not be found.[/center]"
231  "[/title]");
232  book_load(buf, strlen(buf));
233  } else {
234  book_load(hfile->msg, hfile->msg_len);
235  }
236 }
237 
241 static int command_match_cmp(const void *a, const void *b)
242 {
243  return strcmp(*(char * const *) a, *(char * const *) b);
244 }
245 
250 {
251  size_t len;
252  char buf[sizeof(text_input->str)], *space;
253 
254  /* No help files or text input doesn't start with a forward slash. */
255  if (command_matches == NULL || *text_input->str != '/') {
256  return;
257  }
258 
259  space = strrchr(text_input->str, ' ');
260 
261  /* Cannot have anything after a space (if any). */
262  if (space != NULL && *(space + 1) != '\0') {
263  return;
264  }
265 
266  /* Does not match the previous command buffer, so rebuild the array. */
267  if (strcmp(command_buf, text_input->str) != 0) {
268  hfile_struct *hfile, *tmp;
269 
270  utarray_clear(command_matches);
271 
272  HASH_ITER(hh, hfiles, hfile, tmp)
273  {
274  if ((hfile->autocomplete ||
276  hfile->autocomplete_wiz)
277  ) && strncasecmp(hfile->key, text_input->str + 1,
278  text_input->num - 1) == 0) {
279 
280  utarray_push_back(command_matches, &hfile->key);
281  }
282  }
283 
284  utarray_sort(command_matches, command_match_cmp);
285  command_index = 0;
286 
287  snprintf(VS(command_buf), "%s", text_input->str);
288  }
289 
290  len = utarray_len(command_matches);
291 
292  if (len == 0) {
293  return;
294  }
295 
296  snprintf(VS(buf), "/%s ", *((char **) utarray_eltptr(command_matches,
297  command_index)));
298  text_input_set(text_input, buf);
299  snprintf(VS(command_buf), "%s", buf);
300 
301  command_index++;
302 
303  if (command_index >= len) {
304  command_index = 0;
305  }
306 }
void hfiles_deinit(void)
Definition: help.c:70
void hfiles_init(void)
Definition: help.c:89
void book_add_help_history(const char *name)
Definition: book.c:296
hfile_struct * help_find(const char *name)
Definition: help.c:205
static text_input_struct text_input
Definition: interface.c:59
static char command_buf[HUGE_BUF]
Definition: help.c:51
static hfile_struct * hfiles
Definition: help.c:38
static void hfile_free(hfile_struct *hfile)
Definition: help.c:56
void help_handle_tabulator(text_input_struct *text_input)
Definition: help.c:249
FILE * server_file_open_name(const char *name)
Definition: server_files.c:437
void book_load(const char *data, int len)
Definition: book.c:209
void help_show(const char *name)
Definition: help.c:219
static size_t command_index
Definition: help.c:47
int64_t setting_get_int(int cat, int setting)
Definition: settings.c:414
static UT_array * command_matches
Definition: help.c:42
static int command_match_cmp(const void *a, const void *b)
Definition: help.c:241
char str[HUGE_BUF]
Definition: text_input.h:55