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

Contents of /lbbs/src/menu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.23 - (show annotations)
Fri May 2 03:34:58 2025 UTC (10 months, 2 weeks ago) by sysadm
Branch: MAIN
Changes since 1.22: +8 -6 lines
Content type: text/x-csrc
Refine

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

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