/[LeafOK_CVS]/lbbs/src/menu.c
ViewVC logotype

Contents of /lbbs/src/menu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.22 - (show annotations)
Wed Apr 30 09:18:19 2025 UTC (10 months, 2 weeks ago) by sysadm
Branch: MAIN
Changes since 1.21: +7 -2 lines
Content type: text/x-csrc
Add missing header files
Update compile dependency

1 /***************************************************************************
2 menu.c - description
3 -------------------
4 begin : Wed Mar 16 2004
5 copyright : (C) 2005 by Leaflet
6 email : leaflet@leafok.com
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "bbs.h"
19 #include "bbs_cmd.h"
20 #include "user_priv.h"
21 #include "reg_ex.h"
22 #include "bbs_cmd.h"
23 #include "menu.h"
24 #include "log.h"
25 #include "io.h"
26 #include "screen.h"
27 #include "common.h"
28 #include <string.h>
29 #include <stdio.h>
30 #include <ctype.h>
31 #include <regex.h>
32 #include <stdlib.h>
33
34 MENU_SET bbs_menu;
35
36 int load_menu(MENU_SET *p_menu_set, const char *conf_file)
37 {
38 FILE *fin, *fout;
39 int i = 0, j;
40 char buffer[256], screen_filename[256], temp[256];
41 regmatch_t pmatch[10];
42
43 if ((fin = fopen(conf_file, "r")) == NULL)
44 {
45 log_error("Open %s failed", conf_file);
46 return -1;
47 }
48
49 strcpy(p_menu_set->conf_file, conf_file);
50
51 while (fgets(buffer, 255, fin))
52 {
53 switch (buffer[0])
54 {
55 case '#':
56 break;
57 case '%':
58 if (ireg("^%S_([A-Za-z0-9_]+)", buffer, 2, pmatch) == 0)
59 {
60 strncpy(temp, buffer + pmatch[1].rm_so,
61 pmatch[1].rm_eo - pmatch[1].rm_so);
62 temp[pmatch[1].rm_eo - pmatch[1].rm_so] = '\0';
63 sprintf(screen_filename, "%sMENU_SCR_%s", app_temp_dir, temp);
64
65 if ((fout = fopen(screen_filename, "w")) == NULL)
66 {
67 log_error("Open %s failed", screen_filename);
68 return -2;
69 }
70
71 while (fgets(buffer, 255, fin))
72 {
73 if (buffer[0] != '%')
74 fputs(buffer, fout);
75 else
76 break;
77 }
78
79 fclose(fout);
80 break;
81 }
82
83 if (ireg("^%menu ([A-Za-z0-9_]+)", buffer, 2, pmatch) == 0)
84 {
85 p_menu_set->p_menu[i] = malloc(sizeof(MENU));
86 p_menu_set->p_menu[i]->title.show = 0;
87 p_menu_set->p_menu[i]->screen.show = 0;
88
89 strncpy(p_menu_set->p_menu[i]->name,
90 buffer + pmatch[1].rm_so,
91 pmatch[1].rm_eo - pmatch[1].rm_so);
92 p_menu_set->p_menu[i]->name[pmatch[1].rm_eo - pmatch[1].rm_so] =
93 '\0';
94
95 j = 0;
96
97 while (fgets(buffer, 255, fin))
98 {
99 if (buffer[0] == '#')
100 {
101 continue;
102 }
103 if (buffer[0] == '%')
104 {
105 p_menu_set->p_menu[i]->item_count = j;
106 p_menu_set->p_menu[i]->item_cur_pos = 0;
107 i++;
108 break;
109 }
110 if (ireg("^!([A-Za-z0-9_.]+)[[:space:]]*([0-9]+),"
111 "[[:space:]]*([0-9]+),[[:space:]]*([0-9]+),"
112 "[[:space:]]*([0-9]+),[[:space:]]*\"([^\"]+)\","
113 "[[:space:]]*\"([^\"]+)\"",
114 buffer, 8, pmatch) == 0)
115 {
116 p_menu_set->p_menu[i]->items[j] =
117 malloc(sizeof(MENU_ITEM));
118 p_menu_set->p_menu[i]->items[j]->submenu = 1;
119 strncpy(p_menu_set->p_menu[i]->items[j]->action,
120 buffer + pmatch[1].rm_so,
121 pmatch[1].rm_eo - pmatch[1].rm_so);
122 p_menu_set->p_menu[i]->items[j]->action[pmatch[1].rm_eo -
123 pmatch[1].rm_so] = '\0';
124 strncpy(temp, buffer + pmatch[2].rm_so,
125 pmatch[2].rm_eo - pmatch[2].rm_so);
126 temp[pmatch[2].rm_eo - pmatch[2].rm_so] = '\0';
127 p_menu_set->p_menu[i]->items[j]->row = atoi(temp);
128 strncpy(temp,
129 buffer + pmatch[3].rm_so,
130 pmatch[3].rm_eo - pmatch[3].rm_so);
131 temp[pmatch[3].rm_eo - pmatch[3].rm_so] = '\0';
132 p_menu_set->p_menu[i]->items[j]->col = atoi(temp);
133 strncpy(temp,
134 buffer + pmatch[4].rm_so,
135 pmatch[4].rm_eo - pmatch[4].rm_so);
136 temp[pmatch[4].rm_eo - pmatch[4].rm_so] = '\0';
137 p_menu_set->p_menu[i]->items[j]->priv = atoi(temp);
138 strncpy(temp,
139 buffer + pmatch[5].rm_so,
140 pmatch[5].rm_eo - pmatch[5].rm_so);
141 temp[pmatch[5].rm_eo - pmatch[5].rm_so] = '\0';
142 p_menu_set->p_menu[i]->items[j]->level = atoi(temp);
143 strncpy(p_menu_set->p_menu[i]->items[j]->name,
144 buffer + pmatch[6].rm_so,
145 pmatch[6].rm_eo - pmatch[6].rm_so);
146 p_menu_set->p_menu[i]->items[j]->name[pmatch[6].rm_eo -
147 pmatch[6].rm_so] =
148 '\0';
149 strncpy(p_menu_set->p_menu[i]->items[j]->text,
150 buffer + pmatch[7].rm_so,
151 pmatch[7].rm_eo - pmatch[7].rm_so);
152 p_menu_set->p_menu[i]->items[j]->text[pmatch[7].rm_eo -
153 pmatch[7].rm_so] =
154 '\0';
155 j++;
156 continue;
157 }
158 if (ireg("^@([A-Za-z0-9_]+)[[:space:]]*([0-9]+),"
159 "[[:space:]]*([0-9]+),[[:space:]]*([0-9]+),"
160 "[[:space:]]*([0-9]+),[[:space:]]*\"([^\"]+)\","
161 "[[:space:]]*\"([^\"]+)\"",
162 buffer, 8, pmatch) == 0)
163 {
164 p_menu_set->p_menu[i]->items[j] =
165 malloc(sizeof(MENU_ITEM));
166 p_menu_set->p_menu[i]->items[j]->submenu = 0;
167 strncpy(p_menu_set->p_menu[i]->items[j]->action,
168 buffer + pmatch[1].rm_so,
169 pmatch[1].rm_eo - pmatch[1].rm_so);
170 p_menu_set->p_menu[i]->items[j]->action[pmatch[1].rm_eo -
171 pmatch[1].rm_so] = '\0';
172 strncpy(temp, buffer + pmatch[2].rm_so,
173 pmatch[2].rm_eo - pmatch[2].rm_so);
174 temp[pmatch[2].rm_eo - pmatch[2].rm_so] = '\0';
175 p_menu_set->p_menu[i]->items[j]->row = atoi(temp);
176 strncpy(temp,
177 buffer + pmatch[3].rm_so,
178 pmatch[3].rm_eo - pmatch[3].rm_so);
179 temp[pmatch[3].rm_eo - pmatch[3].rm_so] = '\0';
180 p_menu_set->p_menu[i]->items[j]->col = atoi(temp);
181 strncpy(temp,
182 buffer + pmatch[4].rm_so,
183 pmatch[4].rm_eo - pmatch[4].rm_so);
184 temp[pmatch[4].rm_eo - pmatch[4].rm_so] = '\0';
185 p_menu_set->p_menu[i]->items[j]->priv = atoi(temp);
186 strncpy(temp,
187 buffer + pmatch[5].rm_so,
188 pmatch[5].rm_eo - pmatch[5].rm_so);
189 temp[pmatch[5].rm_eo - pmatch[5].rm_so] = '\0';
190 p_menu_set->p_menu[i]->items[j]->level = atoi(temp);
191 strncpy(p_menu_set->p_menu[i]->items[j]->name,
192 buffer + pmatch[6].rm_so,
193 pmatch[6].rm_eo - pmatch[6].rm_so);
194 p_menu_set->p_menu[i]->items[j]->name[pmatch[6].rm_eo -
195 pmatch[6].rm_so] =
196 '\0';
197 strncpy(p_menu_set->p_menu[i]->items[j]->text,
198 buffer + pmatch[7].rm_so,
199 pmatch[7].rm_eo - pmatch[7].rm_so);
200 p_menu_set->p_menu[i]->items[j]->text[pmatch[7].rm_eo -
201 pmatch[7].rm_so] =
202 '\0';
203 j++;
204 continue;
205 }
206 if (ireg("^title[[:space:]]*([0-9]+),"
207 "[[:space:]]*([0-9]+),[[:space:]]*\"([^\"]+)\"",
208 buffer, 4, pmatch) == 0)
209 {
210 p_menu_set->p_menu[i]->title.show = 1;
211 strncpy(temp,
212 buffer + pmatch[1].rm_so,
213 pmatch[1].rm_eo - pmatch[1].rm_so);
214 temp[pmatch[1].rm_eo - pmatch[1].rm_so] = '\0';
215 p_menu_set->p_menu[i]->title.row = atoi(temp);
216 strncpy(temp,
217 buffer + pmatch[2].rm_so,
218 pmatch[2].rm_eo - pmatch[2].rm_so);
219 temp[pmatch[2].rm_eo - pmatch[2].rm_so] = '\0';
220 p_menu_set->p_menu[i]->title.col = atoi(temp);
221 strncpy(p_menu_set->p_menu[i]->title.text,
222 buffer + pmatch[3].rm_so,
223 pmatch[3].rm_eo - pmatch[3].rm_so);
224 p_menu_set->p_menu[i]->title.text[pmatch[3].rm_eo -
225 pmatch[3].rm_so] =
226 '\0';
227 continue;
228 }
229 if (ireg("^screen[[:space:]]*([0-9]+),"
230 "[[:space:]]*([0-9]+),[[:space:]]*S_([A-Za-z0-9_]+)",
231 buffer, 4, pmatch) == 0)
232 {
233 p_menu_set->p_menu[i]->screen.show = 1;
234 strncpy(temp,
235 buffer + pmatch[1].rm_so,
236 pmatch[1].rm_eo - pmatch[1].rm_so);
237 temp[pmatch[1].rm_eo - pmatch[1].rm_so] = '\0';
238 p_menu_set->p_menu[i]->screen.row = atoi(temp);
239 strncpy(temp,
240 buffer + pmatch[2].rm_so,
241 pmatch[2].rm_eo - pmatch[2].rm_so);
242 temp[pmatch[2].rm_eo - pmatch[2].rm_so] = '\0';
243 p_menu_set->p_menu[i]->screen.col = atoi(temp);
244 strncpy(temp,
245 buffer + pmatch[3].rm_so,
246 pmatch[3].rm_eo - pmatch[3].rm_so);
247 temp[pmatch[3].rm_eo - pmatch[3].rm_so] = '\0';
248 sprintf(p_menu_set->p_menu[i]->screen.filename,
249 "%sMENU_SCR_%s", app_temp_dir, temp);
250 continue;
251 }
252 }
253 }
254 break;
255 }
256 }
257 fclose(fin);
258
259 p_menu_set->menu_count = i;
260 p_menu_set->menu_select_depth = 0;
261 p_menu_set->p_menu_select[p_menu_set->menu_select_depth] = (i == 0 ? NULL : p_menu_set->p_menu[0]);
262
263 return 0;
264 }
265
266 MENU *
267 get_menu(MENU_SET *p_menu_set, const char *menu_name)
268 {
269 int i;
270
271 for (i = 0; i < p_menu_set->menu_count; i++)
272 {
273 if (strcmp(p_menu_set->p_menu[i]->name, menu_name) == 0)
274 {
275 return p_menu_set->p_menu[i];
276 }
277 }
278
279 return NULL;
280 }
281
282 static void display_menu_cursor(MENU *p_menu, int show)
283 {
284 moveto((p_menu->items[p_menu->item_cur_pos])->r_row,
285 (p_menu->items[p_menu->item_cur_pos])->r_col - 2);
286 prints(show ? ">" : " ");
287 iflush();
288 }
289
290 int display_menu(MENU *p_menu)
291 {
292 int i, row, col, menu_selectable = 0;
293
294 if (p_menu == NULL)
295 return -1;
296
297 if (p_menu->title.show)
298 show_top(p_menu->title.text);
299
300 if (p_menu->screen.show)
301 {
302 moveto(p_menu->screen.row, p_menu->screen.col);
303 if (display_file(p_menu->screen.filename) != 0)
304 log_error("Display menu screen <%s> failed!\n",
305 p_menu->screen.filename);
306 }
307
308 row = p_menu->items[0]->row;
309 col = p_menu->items[0]->col;
310
311 for (i = 0; i < p_menu->item_count; i++)
312 {
313 if (checkpriv(&BBS_priv, 0, p_menu->items[i]->priv) == 0 || checklevel(&BBS_priv, p_menu->items[i]->level) == 0)
314 {
315 p_menu->items[i]->display = 0;
316 }
317 else
318 {
319 p_menu->items[i]->display = 1;
320
321 menu_selectable = 1;
322
323 if (p_menu->items[i]->row != 0)
324 row = p_menu->items[i]->row;
325 else
326 row++;
327 p_menu->items[i]->r_row = row;
328 if (p_menu->items[i]->col != 0)
329 col = p_menu->items[i]->col;
330 p_menu->items[i]->r_col = col;
331 moveto(row, col);
332 prints(p_menu->items[i]->text);
333 iflush();
334 }
335 }
336
337 if (!menu_selectable)
338 return -1;
339
340 display_menu_cursor(p_menu, 1);
341
342 return 0;
343 }
344
345 int display_current_menu(MENU_SET *p_menu_set)
346 {
347 MENU *p_menu;
348
349 p_menu = p_menu_set->p_menu_select[p_menu_set->menu_select_depth];
350
351 return display_menu(p_menu);
352 }
353
354 int menu_control(MENU_SET *p_menu_set, int key)
355 {
356 int i;
357 MENU *p_menu;
358
359 if (p_menu_set->menu_count == 0)
360 return 0;
361
362 p_menu = p_menu_set->p_menu_select[p_menu_set->menu_select_depth];
363
364 switch (key)
365 {
366 case CR:
367 case KEY_RIGHT:
368 if (p_menu->items[p_menu->item_cur_pos]->submenu)
369 {
370 if (strcmp(p_menu->items[p_menu->item_cur_pos]->action, "..") == 0)
371 return menu_control(p_menu_set, KEY_LEFT);
372 p_menu_set->menu_select_depth++;
373 p_menu =
374 p_menu_set->p_menu_select[p_menu_set->menu_select_depth] =
375 get_menu(p_menu_set,
376 p_menu->items[p_menu->item_cur_pos]->action);
377 if (display_menu(p_menu) != 0)
378 return menu_control(p_menu_set, KEY_LEFT);
379 break;
380 }
381 else
382 {
383 return (exec_cmd(p_menu->items[p_menu->item_cur_pos]->action,
384 p_menu->items[p_menu->item_cur_pos]->name));
385 }
386 case KEY_LEFT:
387 if (p_menu_set->menu_select_depth > 0)
388 {
389 p_menu_set->menu_select_depth--;
390 if (display_current_menu(p_menu_set) != 0)
391 return menu_control(p_menu_set, KEY_LEFT);
392 break;
393 }
394 else
395 {
396 display_menu_cursor(p_menu, 0);
397 p_menu->item_cur_pos = p_menu->item_count - 1;
398 while (!p_menu->items[p_menu->item_cur_pos]->display || p_menu->items[p_menu->item_cur_pos]->priv != 0 || p_menu->items[p_menu->item_cur_pos]->level != 0)
399 p_menu->item_cur_pos--;
400 display_menu_cursor(p_menu, 1);
401 break;
402 }
403 case KEY_UP:
404 display_menu_cursor(p_menu, 0);
405 do
406 {
407 p_menu->item_cur_pos--;
408 if (p_menu->item_cur_pos < 0)
409 p_menu->item_cur_pos = p_menu->item_count - 1;
410 } while (!p_menu->items[p_menu->item_cur_pos]->display);
411 display_menu_cursor(p_menu, 1);
412 break;
413 case KEY_DOWN:
414 display_menu_cursor(p_menu, 0);
415 do
416 {
417 p_menu->item_cur_pos++;
418 if (p_menu->item_cur_pos >= p_menu->item_count)
419 p_menu->item_cur_pos = 0;
420 } while (!p_menu->items[p_menu->item_cur_pos]->display);
421 display_menu_cursor(p_menu, 1);
422 break;
423 default:
424 for (i = 0; i < p_menu->item_count; i++)
425 {
426 if (key == p_menu->items[i]->name[0] &&
427 p_menu->items[i]->display)
428 {
429 display_menu_cursor(p_menu, 0);
430 p_menu->item_cur_pos = i;
431 display_menu_cursor(p_menu, 1);
432 return 0;
433 }
434 }
435 if (isalpha(key))
436 {
437 for (i = 0; i < p_menu->item_count; i++)
438 {
439 if (toupper(key) == toupper(p_menu->items[i]->name[0]) &&
440 p_menu->items[i]->display)
441 {
442 display_menu_cursor(p_menu, 0);
443 p_menu->item_cur_pos = i;
444 display_menu_cursor(p_menu, 1);
445 return 0;
446 }
447 }
448 }
449 }
450
451 return 0;
452 }
453
454 void unload_menu(MENU_SET *p_menu_set)
455 {
456 MENU *p_menu;
457 MENU_ITEM *p_menuitem;
458 int i, j;
459
460 for (i = 0; i < p_menu_set->menu_count; i++)
461 {
462 p_menu = p_menu_set->p_menu[i];
463 for (j = 0; j < p_menu->item_count; j++)
464 {
465 free(p_menu->items[j]);
466 }
467 remove(p_menu->screen.filename);
468 free(p_menu);
469 }
470
471 p_menu_set->menu_count = 0;
472 p_menu_set->menu_select_depth = 0;
473 }
474
475 int reload_menu(MENU_SET *p_menu_set)
476 {
477 int result;
478 char conf_file[256];
479
480 strcpy(conf_file, p_menu_set->conf_file);
481 unload_menu(p_menu_set);
482 result = load_menu(p_menu_set, conf_file);
483
484 return result;
485 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1