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

Contents of /lbbs/src/menu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.21 - (show annotations)
Mon Apr 28 03:31:00 2025 UTC (10 months, 2 weeks ago) by sysadm
Branch: MAIN
Changes since 1.20: +397 -413 lines
Content type: text/x-csrc
Update

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

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