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

Annotation of /lbbs/src/menu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.76 - (hide annotations)
Sat Oct 18 13:23:50 2025 UTC (4 months, 4 weeks ago) by sysadm
Branch: MAIN
Changes since 1.75: +2 -1 lines
Content type: text/x-csrc
Refine log for debug

1 sysadm 1.1 /***************************************************************************
2 sysadm 1.21 menu.c - description
3     -------------------
4 sysadm 1.30 Copyright : (C) 2004-2025 by Leaflet
5     Email : leaflet@leafok.com
6 sysadm 1.1 ***************************************************************************/
7    
8     /***************************************************************************
9     * *
10     * This program is free software; you can redistribute it and/or modify *
11     * it under the terms of the GNU General Public License as published by *
12 sysadm 1.30 * the Free Software Foundation; either version 3 of the License, or *
13 sysadm 1.1 * (at your option) any later version. *
14     * *
15     ***************************************************************************/
16    
17 sysadm 1.3 #include "bbs.h"
18 sysadm 1.17 #include "bbs_cmd.h"
19 sysadm 1.22 #include "bbs_cmd.h"
20 sysadm 1.67 #include "common.h"
21     #include "io.h"
22     #include "log.h"
23 sysadm 1.1 #include "menu.h"
24 sysadm 1.22 #include "screen.h"
25 sysadm 1.67 #include "user_priv.h"
26     #include <ctype.h>
27     #include <errno.h>
28 sysadm 1.1 #include <stdio.h>
29 sysadm 1.6 #include <stdlib.h>
30 sysadm 1.67 #include <string.h>
31 sysadm 1.40 #include <unistd.h>
32 sysadm 1.67 #include <sys/ipc.h>
33 sysadm 1.40 #include <sys/shm.h>
34 sysadm 1.1
35 sysadm 1.31 #define MENU_SCREEN_PATH_PREFIX "var/MENU_SCR_"
36     #define MENU_CONF_DELIM_WITH_SPACE " ,\t\r\n"
37     #define MENU_CONF_DELIM_WITHOUT_SPACE "\r\n"
38 sysadm 1.25
39 sysadm 1.40 #define MENU_SET_RESERVED_LENGTH (sizeof(int16_t) * 4)
40    
41 sysadm 1.69 MENU_SET bbs_menu;
42 sysadm 1.73 MENU_SET top10_menu;
43 sysadm 1.1
44 sysadm 1.21 int load_menu(MENU_SET *p_menu_set, const char *conf_file)
45 sysadm 1.1 {
46 sysadm 1.40 FILE *fin;
47 sysadm 1.31 int fin_line = 0;
48 sysadm 1.23 char buffer[LINE_BUFFER_LEN];
49 sysadm 1.33 char temp[LINE_BUFFER_LEN];
50 sysadm 1.31 char *p = NULL;
51     char *q = NULL;
52 sysadm 1.48 char *r = NULL;
53 sysadm 1.31 char *saveptr = NULL;
54     MENU *p_menu = NULL;
55 sysadm 1.40 MENU_ITEM *p_menu_item = NULL;
56     MENU_SCREEN *p_screen = NULL;
57     MENU_ID menu_id;
58     MENU_ITEM_ID menu_item_id;
59     MENU_SCREEN_ID screen_id;
60     int proj_id;
61     key_t key;
62     size_t size;
63 sysadm 1.31
64 sysadm 1.69 // Initialize the data structure
65     memset(p_menu_set, 0, sizeof(*p_menu_set));
66    
67 sysadm 1.40 // Use trie_dict to search menu_id by menu name
68 sysadm 1.39 p_menu_set->p_menu_name_dict = trie_dict_create();
69 sysadm 1.40 if (p_menu_set->p_menu_name_dict == NULL)
70     {
71     log_error("trie_dict_create() error\n");
72     return -3;
73     }
74    
75     // Use trie_dict to search screen_id by menu screen name
76     p_menu_set->p_menu_screen_dict = trie_dict_create();
77     if (p_menu_set->p_menu_screen_dict == NULL)
78     {
79     log_error("trie_dict_create() error\n");
80     return -3;
81     }
82 sysadm 1.21
83     if ((fin = fopen(conf_file, "r")) == NULL)
84     {
85 sysadm 1.68 log_error("Open %s failed\n", conf_file);
86 sysadm 1.31 return -2;
87 sysadm 1.21 }
88    
89 sysadm 1.40 // Allocate shared memory
90     proj_id = (int)(time(NULL) % getpid());
91     key = ftok(conf_file, proj_id);
92     if (key == -1)
93     {
94     log_error("ftok(%s %d) error (%d)\n", conf_file, proj_id, errno);
95     return -2;
96     }
97    
98     size = MENU_SET_RESERVED_LENGTH +
99     sizeof(MENU) * MAX_MENUS +
100     sizeof(MENU_ITEM) * MAX_MENUITEMS +
101     sizeof(MENU_SCREEN) * MAX_MENUS +
102     MAX_MENU_SCR_BUF_LENGTH * MAX_MENUS;
103     p_menu_set->shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0600);
104     if (p_menu_set->shmid == -1)
105     {
106 sysadm 1.76 log_error("shmget(conf_file=%s, proj_id=%d, key=%d, size=%d) error (%d)\n",
107     conf_file, proj_id, key, size, errno);
108 sysadm 1.40 return -3;
109     }
110     p_menu_set->p_reserved = shmat(p_menu_set->shmid, NULL, 0);
111     if (p_menu_set->p_reserved == (void *)-1)
112     {
113     log_error("shmat() error (%d)\n", errno);
114     return -3;
115     }
116 sysadm 1.75 p_menu_set->p_menu_pool = (char *)(p_menu_set->p_reserved) + MENU_SET_RESERVED_LENGTH;
117     p_menu_set->p_menu_item_pool = (char *)(p_menu_set->p_menu_pool) + sizeof(MENU) * MAX_MENUS;
118     p_menu_set->p_menu_screen_pool = (char *)(p_menu_set->p_menu_item_pool) + sizeof(MENU_ITEM) * MAX_MENUITEMS;
119     p_menu_set->p_menu_screen_buf = (char *)(p_menu_set->p_menu_screen_pool) + sizeof(MENU_SCREEN) * MAX_MENUS;
120 sysadm 1.40 p_menu_set->p_menu_screen_buf_free = p_menu_set->p_menu_screen_buf;
121    
122     p_menu_set->menu_count = 0;
123     p_menu_set->menu_item_count = 0;
124     p_menu_set->menu_screen_count = 0;
125     p_menu_set->choose_step = 0;
126     p_menu_set->menu_id_path[0] = 0;
127 sysadm 1.69 p_menu_set->menu_item_pos[0] = 0;
128 sysadm 1.68 p_menu_set->allow_exit = 0;
129 sysadm 1.21
130 sysadm 1.23 while (fgets(buffer, sizeof(buffer), fin))
131 sysadm 1.3 {
132 sysadm 1.31 fin_line++;
133    
134     p = strtok_r(buffer, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
135     if (p == NULL) // Blank line
136 sysadm 1.21 {
137 sysadm 1.31 continue;
138     }
139    
140     if (*p == '#' || *p == '\r' || *p == '\n') // Comment or blank line
141     {
142     continue;
143     }
144    
145     if (*p == '%')
146     {
147     p++;
148    
149     if (strcmp(p, "menu") == 0) // BEGIN of sub-menu
150 sysadm 1.21 {
151 sysadm 1.31 if (p_menu != NULL)
152     {
153 sysadm 1.33 log_error("Incomplete menu definition in menu config line %d\n", fin_line);
154 sysadm 1.31 return -1;
155     }
156 sysadm 1.40
157     if (p_menu_set->menu_count >= MAX_MENUS)
158 sysadm 1.31 {
159 sysadm 1.40 log_error("Menu count (%d) exceed limit (%d)\n", p_menu_set->menu_count, MAX_MENUS);
160 sysadm 1.31 return -3;
161     }
162 sysadm 1.40 menu_id = (MENU_ID)p_menu_set->menu_count;
163     p_menu_set->menu_count++;
164    
165     p_menu = get_menu_by_id(p_menu_set, menu_id);
166 sysadm 1.21
167 sysadm 1.31 p_menu->item_count = 0;
168     p_menu->title.show = 0;
169 sysadm 1.40 p_menu->screen_show = 0;
170 sysadm 1.51 p_menu->page_item_limit = 0;
171 sysadm 1.62 p_menu->use_filter = 0;
172     p_menu->filter_handler = NULL;
173 sysadm 1.31
174     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
175     if (q == NULL)
176     {
177     log_error("Error menu name in menu config line %d\n", fin_line);
178     return -1;
179     }
180     p = q;
181 sysadm 1.48 while (isalnum(*q) || *q == '_' || *q == '-')
182 sysadm 1.31 {
183     q++;
184     }
185     if (*q != '\0')
186 sysadm 1.21 {
187 sysadm 1.31 log_error("Error menu name in menu config line %d\n", fin_line);
188     return -1;
189 sysadm 1.21 }
190    
191 sysadm 1.31 if (q - p > sizeof(p_menu->name) - 1)
192 sysadm 1.21 {
193 sysadm 1.31 log_error("Too longer menu name in menu config line %d\n", fin_line);
194     return -1;
195 sysadm 1.21 }
196 sysadm 1.31 strncpy(p_menu->name, p, sizeof(p_menu->name) - 1);
197     p_menu->name[sizeof(p_menu->name) - 1] = '\0';
198 sysadm 1.40
199     if (trie_dict_set(p_menu_set->p_menu_name_dict, p_menu->name, (int64_t)menu_id) != 1)
200 sysadm 1.39 {
201     log_error("Error set menu dict [%s]\n", p_menu->name);
202     }
203 sysadm 1.21
204 sysadm 1.31 // Check syntax
205     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
206     if (q != NULL)
207     {
208     log_error("Unknown extra content in menu config line %d\n", fin_line);
209     return -1;
210     }
211 sysadm 1.21
212 sysadm 1.31 while (fgets(buffer, sizeof(buffer), fin))
213     {
214     fin_line++;
215 sysadm 1.21
216 sysadm 1.31 p = strtok_r(buffer, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
217     if (p == NULL) // Blank line
218     {
219     continue;
220     }
221 sysadm 1.21
222 sysadm 1.31 if (*p == '#' || *p == '\r' || *p == '\n') // Comment or blank line
223 sysadm 1.21 {
224     continue;
225     }
226 sysadm 1.31
227     if (*p == '%') // END of sub-menu
228 sysadm 1.21 {
229 sysadm 1.31 p_menu = NULL;
230 sysadm 1.21 break;
231     }
232 sysadm 1.31 else if (*p == '!' || *p == '@')
233 sysadm 1.21 {
234 sysadm 1.31 // BEGIN of menu item
235 sysadm 1.40 if (p_menu->item_count >= MAX_ITEMS_PER_MENU)
236     {
237     log_error("Menuitem count per menu (%d) exceed limit (%d)\n", p_menu->item_count, MAX_ITEMS_PER_MENU);
238     return -1;
239     }
240     if (p_menu_set->menu_item_count >= MAX_MENUITEMS)
241 sysadm 1.31 {
242 sysadm 1.40 log_error("Menuitem count (%d) exceed limit (%d)\n", p_menu_set->menu_item_count, MAX_MENUITEMS);
243 sysadm 1.31 return -3;
244     }
245 sysadm 1.40 menu_item_id = (MENU_ITEM_ID)p_menu_set->menu_item_count;
246     p_menu_set->menu_item_count++;
247 sysadm 1.31
248 sysadm 1.40 p_menu->items[p_menu->item_count] = menu_item_id;
249     p_menu->item_count++;
250    
251     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
252    
253     p_menu_item->submenu = (*p == '!' ? 1 : 0);
254 sysadm 1.31
255     // Menu item action
256     p++;
257     if (strcmp(p, "..") == 0) // Return to parent menu
258     {
259     q = p + 2; // strlen("..")
260     }
261     else
262     {
263     q = p;
264 sysadm 1.48 while (isalnum(*q) || *q == '_' || *q == '-')
265 sysadm 1.31 {
266     q++;
267     }
268     if (*q != '\0')
269     {
270     log_error("Error menu item action in menu config line %d\n", fin_line);
271     return -1;
272     }
273     }
274    
275 sysadm 1.40 if (q - p > sizeof(p_menu_item->action) - 1)
276 sysadm 1.31 {
277     log_error("Too longer menu action in menu config line %d\n", fin_line);
278     return -1;
279     }
280 sysadm 1.40 strncpy(p_menu_item->action, p, sizeof(p_menu_item->action) - 1);
281     p_menu_item->action[sizeof(p_menu_item->action) - 1] = '\0';
282 sysadm 1.31
283     // Menu item row
284     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
285     if (q == NULL)
286     {
287     log_error("Error menu item row in menu config line %d\n", fin_line);
288     return -1;
289     }
290     p = q;
291     while (isdigit(*q))
292     {
293     q++;
294     }
295     if (*q != '\0')
296     {
297     log_error("Error menu item row in menu config line %d\n", fin_line);
298     return -1;
299     }
300 sysadm 1.40 p_menu_item->row = (int16_t)atoi(p);
301 sysadm 1.31
302     // Menu item col
303     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
304     if (q == NULL)
305     {
306     log_error("Error menu item col in menu config line %d\n", fin_line);
307     return -1;
308     }
309     p = q;
310     while (isdigit(*q))
311     {
312     q++;
313     }
314     if (*q != '\0')
315     {
316     log_error("Error menu item col in menu config line %d\n", fin_line);
317     return -1;
318     }
319 sysadm 1.40 p_menu_item->col = (int16_t)atoi(p);
320 sysadm 1.31
321     // Menu item priv
322     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
323     if (q == NULL)
324     {
325     log_error("Error menu item priv in menu config line %d\n", fin_line);
326     return -1;
327     }
328     p = q;
329     while (isdigit(*q))
330     {
331     q++;
332     }
333     if (*q != '\0')
334     {
335     log_error("Error menu item priv in menu config line %d\n", fin_line);
336     return -1;
337     }
338 sysadm 1.40 p_menu_item->priv = atoi(p);
339 sysadm 1.31
340     // Menu item level
341     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
342     if (q == NULL)
343     {
344     log_error("Error menu item level in menu config line %d\n", fin_line);
345     return -1;
346     }
347     p = q;
348     while (isdigit(*q))
349     {
350     q++;
351     }
352     if (*q != '\0')
353     {
354     log_error("Error menu item level in menu config line %d\n", fin_line);
355     return -1;
356     }
357 sysadm 1.40 p_menu_item->level = atoi(p);
358 sysadm 1.31
359     // Menu item name
360     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
361     if (q == NULL || *q != '\"')
362     {
363     log_error("Error menu item name in menu config line %d\n", fin_line);
364     return -1;
365     }
366     q++;
367     p = q;
368     while (*q != '\0' && *q != '\"')
369     {
370 sysadm 1.48 if (*q == '\\')
371     {
372     r = q;
373     while (*r != '\0')
374     {
375     *r = *(r + 1);
376     r++;
377     }
378     }
379 sysadm 1.31 q++;
380     }
381     if (*q != '\"' || *(q + 1) != '\0')
382     {
383     log_error("Error menu item name in menu config line %d\n", fin_line);
384     return -1;
385     }
386     *q = '\0';
387    
388 sysadm 1.40 if (q - p > sizeof(p_menu_item->name) - 1)
389 sysadm 1.31 {
390     log_error("Too longer menu name in menu config line %d\n", fin_line);
391     return -1;
392     }
393 sysadm 1.40 strncpy(p_menu_item->name, p, sizeof(p_menu_item->name) - 1);
394     p_menu_item->name[sizeof(p_menu_item->name) - 1] = '\0';
395 sysadm 1.31
396     // Menu item text
397     q = strtok_r(NULL, MENU_CONF_DELIM_WITHOUT_SPACE, &saveptr);
398     if (q == NULL || (q = strchr(q, '\"')) == NULL)
399     {
400 sysadm 1.32 log_error("Error menu item text in menu config line %d\n", fin_line);
401 sysadm 1.31 return -1;
402     }
403     q++;
404     p = q;
405     while (*q != '\0' && *q != '\"')
406     {
407 sysadm 1.48 if (*q == '\\')
408     {
409     r = q;
410     while (*r != '\0')
411     {
412     *r = *(r + 1);
413     r++;
414     }
415     }
416 sysadm 1.31 q++;
417     }
418     if (*q != '\"')
419     {
420     log_error("Error menu item text in menu config line %d\n", fin_line);
421     return -1;
422     }
423     *q = '\0';
424    
425 sysadm 1.40 if (q - p > sizeof(p_menu_item->text) - 1)
426 sysadm 1.31 {
427     log_error("Too longer menu item text in menu config line %d\n", fin_line);
428     return -1;
429     }
430 sysadm 1.40 strncpy(p_menu_item->text, p, sizeof(p_menu_item->text) - 1);
431     p_menu_item->text[sizeof(p_menu_item->text) - 1] = '\0';
432 sysadm 1.31
433     // Check syntax
434     q = strtok_r(q + 1, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
435     if (q != NULL)
436     {
437     log_error("Unknown extra content in menu config line %d\n", fin_line);
438     return -1;
439     }
440     }
441     else if (strcmp(p, "title") == 0)
442     {
443     p_menu->title.show = 1;
444    
445     // Menu title row
446     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
447     if (q == NULL)
448     {
449     log_error("Error menu title row in menu config line %d\n", fin_line);
450     return -1;
451     }
452     p = q;
453     while (isdigit(*q))
454     {
455     q++;
456     }
457     if (*q != '\0')
458     {
459     log_error("Error menu title row in menu config line %d\n", fin_line);
460     return -1;
461     }
462 sysadm 1.40 p_menu->title.row = (int16_t)atoi(p);
463 sysadm 1.31
464     // Menu title col
465     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
466     if (q == NULL)
467     {
468     log_error("Error menu title col in menu config line %d\n", fin_line);
469     return -1;
470     }
471     p = q;
472     while (isdigit(*q))
473     {
474     q++;
475     }
476     if (*q != '\0')
477     {
478     log_error("Error menu title col in menu config line %d\n", fin_line);
479     return -1;
480     }
481 sysadm 1.40 p_menu->title.col = (int16_t)atoi(p);
482 sysadm 1.31
483     // Menu title text
484     q = strtok_r(NULL, MENU_CONF_DELIM_WITHOUT_SPACE, &saveptr);
485     if (q == NULL || (q = strchr(q, '\"')) == NULL)
486     {
487     log_error("Error menu title text in menu config line %d\n", fin_line);
488     return -1;
489     }
490     q++;
491     p = q;
492     while (*q != '\0' && *q != '\"')
493     {
494 sysadm 1.48 if (*q == '\\')
495     {
496     r = q;
497     while (*r != '\0')
498     {
499     *r = *(r + 1);
500     r++;
501     }
502     }
503 sysadm 1.31 q++;
504     }
505     if (*q != '\"')
506     {
507     log_error("Error menu title text in menu config line %d\n", fin_line);
508     return -1;
509     }
510     *q = '\0';
511    
512 sysadm 1.48 if (q - p > sizeof(p_menu->title.text) - 1)
513 sysadm 1.31 {
514     log_error("Too longer menu title text in menu config line %d\n", fin_line);
515     return -1;
516     }
517     strncpy(p_menu->title.text, p, sizeof(p_menu->title.text) - 1);
518     p_menu->title.text[sizeof(p_menu->title.text) - 1] = '\0';
519    
520     // Check syntax
521     q = strtok_r(q + 1, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
522     if (q != NULL)
523     {
524     log_error("Unknown extra content in menu config line %d\n", fin_line);
525     return -1;
526     }
527 sysadm 1.21 }
528 sysadm 1.31 else if (strcmp(p, "screen") == 0)
529 sysadm 1.21 {
530 sysadm 1.40 p_menu->screen_show = 1;
531 sysadm 1.31
532     // Menu screen row
533     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
534     if (q == NULL)
535     {
536     log_error("Error menu screen row in menu config line %d\n", fin_line);
537     return -1;
538     }
539     p = q;
540     while (isdigit(*q))
541     {
542     q++;
543     }
544     if (*q != '\0')
545     {
546     log_error("Error menu screen row in menu config line %d\n", fin_line);
547     return -1;
548     }
549 sysadm 1.40 p_menu->screen_row = (int16_t)atoi(p);
550 sysadm 1.31
551     // Menu screen col
552     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
553     if (q == NULL)
554     {
555     log_error("Error menu screen col in menu config line %d\n", fin_line);
556     return -1;
557     }
558     p = q;
559     while (isdigit(*q))
560     {
561     q++;
562     }
563     if (*q != '\0')
564     {
565     log_error("Error menu screen col in menu config line %d\n", fin_line);
566     return -1;
567     }
568 sysadm 1.40 p_menu->screen_col = (int16_t)atoi(p);
569 sysadm 1.31
570     // Menu screen name
571     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
572     if (q == NULL)
573     {
574     log_error("Error menu screen name in menu config line %d\n", fin_line);
575     return -1;
576     }
577     p = q;
578 sysadm 1.48 while (isalnum(*q) || *q == '_' || *q == '-')
579 sysadm 1.31 {
580     q++;
581     }
582     if (*q != '\0')
583     {
584     log_error("Error menu screen name in menu config line %d\n", fin_line);
585     return -1;
586     }
587 sysadm 1.47 strncpy(p_menu->screen_name, p, sizeof(p_menu->screen_name) - 1);
588     p_menu->screen_name[sizeof(p_menu->screen_name) - 1] = '\0';
589 sysadm 1.31
590     // Check syntax
591     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
592     if (q != NULL)
593     {
594     log_error("Unknown extra content in menu config line %d\n", fin_line);
595     return -1;
596     }
597 sysadm 1.21 }
598 sysadm 1.51 else if (strcmp(p, "page") == 0)
599     {
600     // Menu page row
601     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
602     if (q == NULL)
603     {
604     log_error("Error menu page row in menu config line %d\n", fin_line);
605     return -1;
606     }
607     p = q;
608     while (isdigit(*q))
609     {
610     q++;
611     }
612     if (*q != '\0')
613     {
614     log_error("Error menu page row in menu config line %d\n", fin_line);
615     return -1;
616     }
617     p_menu->page_row = (int16_t)atoi(p);
618    
619     // Menu page col
620     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
621     if (q == NULL)
622     {
623     log_error("Error menu page col in menu config line %d\n", fin_line);
624     return -1;
625     }
626     p = q;
627     while (isdigit(*q))
628     {
629     q++;
630     }
631     if (*q != '\0')
632     {
633     log_error("Error menu page col in menu config line %d\n", fin_line);
634     return -1;
635     }
636     p_menu->page_col = (int16_t)atoi(p);
637    
638     // Menu page item limit
639     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
640     if (q == NULL)
641     {
642     log_error("Error menu page item limit in menu config line %d\n", fin_line);
643     return -1;
644     }
645     p = q;
646     while (isdigit(*q))
647     {
648     q++;
649     }
650     if (*q != '\0')
651     {
652     log_error("Error menu page item limit in menu config line %d\n", fin_line);
653     return -1;
654     }
655     p_menu->page_item_limit = (int16_t)atoi(p);
656    
657     // Check syntax
658     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
659     if (q != NULL)
660     {
661     log_error("Unknown extra content in menu config line %d\n", fin_line);
662     return -1;
663     }
664     }
665 sysadm 1.62 else if (strcmp(p, "use_filter") == 0)
666     {
667     p_menu->use_filter = 1;
668    
669     // Check syntax
670     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
671     if (q != NULL)
672     {
673     log_error("Unknown extra content in menu config line %d\n", fin_line);
674     return -1;
675     }
676     }
677 sysadm 1.31 }
678     }
679     else // BEGIN of menu screen
680     {
681 sysadm 1.40 if (p_menu_set->menu_item_count >= MAX_MENUS)
682     {
683     log_error("Menu screen count (%d) exceed limit (%d)\n", p_menu_set->menu_screen_count, MAX_MENUS);
684     return -3;
685     }
686     screen_id = (MENU_SCREEN_ID)p_menu_set->menu_screen_count;
687     p_menu_set->menu_screen_count++;
688    
689     p_screen = get_menu_screen_by_id(p_menu_set, screen_id);
690    
691 sysadm 1.31 q = p;
692 sysadm 1.48 while (isalnum(*q) || *q == '_' || *q == '-')
693 sysadm 1.31 {
694     q++;
695     }
696     if (*q != '\0')
697     {
698     log_error("Error menu screen name in menu config line %d\n", fin_line);
699     return -1;
700     }
701 sysadm 1.40 strncpy(p_screen->name, p, sizeof(p_screen->name) - 1);
702     p_screen->name[sizeof(p_screen->name) - 1] = '\0';
703 sysadm 1.31
704 sysadm 1.40 if (trie_dict_set(p_menu_set->p_menu_screen_dict, p_screen->name, (int64_t)screen_id) != 1)
705     {
706     log_error("Error set menu screen dict [%s]\n", p_screen->name);
707     }
708 sysadm 1.31
709     // Check syntax
710     q = strtok_r(NULL, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
711     if (q != NULL)
712     {
713     log_error("Unknown extra content in menu config line %d\n", fin_line);
714     return -1;
715     }
716    
717 sysadm 1.40 p_screen->buf_offset = p_menu_set->p_menu_screen_buf_free - p_menu_set->p_menu_screen_buf;
718     p_screen->buf_length = -1;
719    
720     // safety appending boundary
721     q = p_menu_set->p_menu_screen_buf + MAX_MENU_SCR_BUF_LENGTH * MAX_MENUS - 1;
722 sysadm 1.31
723     while (fgets(buffer, sizeof(buffer), fin))
724     {
725     fin_line++;
726    
727 sysadm 1.40 strncpy(temp, buffer, sizeof(temp) - 1); // Duplicate line for strtok_r
728     temp[sizeof(temp) - 1] = '\0';
729 sysadm 1.33 p = strtok_r(temp, MENU_CONF_DELIM_WITH_SPACE, &saveptr);
730 sysadm 1.31 if (p != NULL && *p == '%') // END of menu screen
731 sysadm 1.21 {
732 sysadm 1.40 if (p_menu_set->p_menu_screen_buf_free + 1 > q)
733     {
734     log_error("Menu screen buffer depleted (%p + 1 > %p)\n", p_menu_set->p_menu_screen_buf_free, q);
735     return -3;
736     }
737    
738     *(p_menu_set->p_menu_screen_buf_free) = '\0';
739     p_menu_set->p_menu_screen_buf_free++;
740     p_screen->buf_length = p_menu_set->p_menu_screen_buf_free - p_menu_set->p_menu_screen_buf - p_screen->buf_offset;
741 sysadm 1.31 break;
742 sysadm 1.21 }
743 sysadm 1.31
744 sysadm 1.47 // Clear line
745     if (p_menu_set->p_menu_screen_buf_free + strlen(CTRL_SEQ_CLR_LINE) > q)
746     {
747     log_error("Menu screen buffer depleted (%p + %d > %p)\n", p_menu_set->p_menu_screen_buf_free, q, strlen(CTRL_SEQ_CLR_LINE));
748     return -3;
749     }
750     p_menu_set->p_menu_screen_buf_free = stpcpy(p_menu_set->p_menu_screen_buf_free, CTRL_SEQ_CLR_LINE);
751    
752 sysadm 1.40 p = buffer;
753     while (*p != '\0')
754 sysadm 1.21 {
755 sysadm 1.40 if (p_menu_set->p_menu_screen_buf_free + 2 > q)
756     {
757     log_error("Menu screen buffer depleted (%p + 2 > %p)\n", p_menu_set->p_menu_screen_buf_free, q);
758     return -3;
759     }
760    
761     if (*p == '\n' && p > buffer && *(p - 1) != '\r')
762     {
763     *(p_menu_set->p_menu_screen_buf_free) = '\r';
764     p_menu_set->p_menu_screen_buf_free++;
765     }
766    
767     *(p_menu_set->p_menu_screen_buf_free) = *p;
768     p++;
769     p_menu_set->p_menu_screen_buf_free++;
770 sysadm 1.21 }
771     }
772 sysadm 1.31
773 sysadm 1.40 if (p_screen->buf_length == -1)
774     {
775     log_error("End of menu screen [%s] not found\n", p_screen->name);
776     }
777 sysadm 1.21 }
778 sysadm 1.31 }
779     else // Invalid prefix
780     {
781     log_error("Error in menu config line %d\n", fin_line);
782     return -1;
783 sysadm 1.10 }
784 sysadm 1.3 }
785 sysadm 1.21 fclose(fin);
786 sysadm 1.3
787 sysadm 1.47 for (menu_id = 0; menu_id < p_menu_set->menu_count; menu_id++)
788     {
789     p_menu = get_menu_by_id(p_menu_set, menu_id);
790    
791     if (trie_dict_get(p_menu_set->p_menu_screen_dict, p_menu->screen_name, (int64_t *)(&(p_menu->screen_id))) != 1)
792     {
793     log_error("Undefined menu screen [%s]\n", p);
794     return -1;
795     }
796 sysadm 1.62
797     // Set menu->filter_handler of each menu pointing to filter
798     if (p_menu->use_filter == 1)
799     {
800     if ((p_menu->filter_handler = get_cmd_handler(p_menu->name)) == NULL)
801     {
802     log_error("Undefined menu filter handler [%s]\n", p_menu->name);
803     return -1;
804     }
805     }
806 sysadm 1.47 }
807    
808 sysadm 1.40 for (menu_item_id = 0; menu_item_id < p_menu_set->menu_item_count; menu_item_id++)
809     {
810     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
811 sysadm 1.44
812     // Set menu_item->action_cmd_handler of each menu item pointing to bbs_cmd
813     if (p_menu_item->submenu == 0)
814     {
815     if ((p_menu_item->action_cmd_handler = get_cmd_handler(p_menu_item->action)) == NULL)
816     {
817     log_error("Undefined menu action cmd handler [%s]\n", p_menu_item->action);
818     return -1;
819     }
820     }
821     // Set menu_item->action_menu_id of each menu item pointing to a submenu to the menu_id of the corresponding submenu
822     else if (strcmp(p_menu_item->action, "..") != 0)
823 sysadm 1.40 {
824     if (trie_dict_get(p_menu_set->p_menu_name_dict, p_menu_item->action, (int64_t *)&menu_id) != 1)
825     {
826 sysadm 1.48 log_error("Undefined sub menu id [%s]\n", p_menu_item->action);
827 sysadm 1.40 return -1;
828     }
829     p_menu_item->action_menu_id = menu_id;
830     }
831     }
832    
833     // Save status varaibles into reserved memory area
834     *((int16_t *)p_menu_set->p_reserved) = p_menu_set->menu_count;
835     *(((int16_t *)p_menu_set->p_reserved) + 1) = p_menu_set->menu_item_count;
836     *(((int16_t *)p_menu_set->p_reserved) + 2) = p_menu_set->menu_screen_count;
837 sysadm 1.2
838 sysadm 1.21 return 0;
839 sysadm 1.1 }
840    
841 sysadm 1.61 int display_menu_cursor(MENU_SET *p_menu_set, int show)
842 sysadm 1.3 {
843 sysadm 1.40 MENU_ID menu_id;
844     MENU_ITEM_ID menu_item_id;
845     MENU *p_menu;
846     MENU_ITEM *p_menu_item;
847     int16_t menu_item_pos;
848 sysadm 1.39
849 sysadm 1.40 menu_id = p_menu_set->menu_id_path[p_menu_set->choose_step];
850     p_menu = get_menu_by_id(p_menu_set, menu_id);
851     if (p_menu == NULL)
852     {
853     log_error("get_menu_by_id(%d) return NULL pointer\n", menu_id);
854     return -1;
855     }
856 sysadm 1.5
857 sysadm 1.40 menu_item_pos = p_menu_set->menu_item_pos[p_menu_set->choose_step];
858     menu_item_id = p_menu->items[menu_item_pos];
859     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
860     if (p_menu_item == NULL)
861 sysadm 1.10 {
862 sysadm 1.40 log_error("get_menu_item_by_id(%d) return NULL pointer\n", menu_item_id);
863     return -1;
864 sysadm 1.10 }
865 sysadm 1.5
866 sysadm 1.41 moveto(p_menu_set->menu_item_r_row[menu_item_pos], p_menu_set->menu_item_r_col[menu_item_pos] - 2);
867 sysadm 1.26 outc(show ? '>' : ' ');
868 sysadm 1.40
869     return 0;
870 sysadm 1.1 }
871    
872 sysadm 1.51 static int display_menu_current_page(MENU_SET *p_menu_set)
873 sysadm 1.1 {
874 sysadm 1.40 int16_t row = 0;
875     int16_t col = 0;
876     MENU_ID menu_id;
877     MENU_ITEM_ID menu_item_id;
878     MENU *p_menu;
879     MENU_ITEM *p_menu_item;
880 sysadm 1.51 int16_t menu_item_pos;
881     int16_t page_id = 0;
882 sysadm 1.40 MENU_SCREEN *p_menu_screen;
883 sysadm 1.3
884 sysadm 1.40 menu_id = p_menu_set->menu_id_path[p_menu_set->choose_step];
885     p_menu = get_menu_by_id(p_menu_set, menu_id);
886 sysadm 1.21 if (p_menu == NULL)
887 sysadm 1.26 {
888 sysadm 1.40 log_error("get_menu_by_id(%d) return NULL pointer\n", menu_id);
889 sysadm 1.21 return -1;
890 sysadm 1.26 }
891 sysadm 1.5
892 sysadm 1.51 clrline(p_menu->page_row, p_menu->page_row + p_menu->page_item_limit - 1);
893 sysadm 1.35
894 sysadm 1.21 if (p_menu->title.show)
895 sysadm 1.26 {
896 sysadm 1.48 if (p_menu->title.row == 0 && p_menu->title.col == 0)
897     {
898 sysadm 1.59 show_top(p_menu->title.text, BBS_name, "");
899 sysadm 1.48 }
900     else
901     {
902     moveto(p_menu->title.row, p_menu->title.col);
903     prints("%s", p_menu->title.text);
904     }
905 sysadm 1.26 }
906 sysadm 1.3
907 sysadm 1.40 if (p_menu->screen_show)
908 sysadm 1.10 {
909 sysadm 1.40 p_menu_screen = get_menu_screen_by_id(p_menu_set, p_menu->screen_id);
910     if (p_menu_screen == NULL)
911 sysadm 1.26 {
912 sysadm 1.40 log_error("get_menu_screen_by_id(%d) return NULL pointer\n", p_menu->screen_id);
913     return -1;
914 sysadm 1.26 }
915 sysadm 1.40
916 sysadm 1.48 row = p_menu->screen_row;
917     col = p_menu->screen_col;
918    
919     moveto(row, col);
920 sysadm 1.40 prints("%s", p_menu_set->p_menu_screen_buf + p_menu_screen->buf_offset);
921 sysadm 1.10 }
922 sysadm 1.21
923 sysadm 1.51 menu_item_pos = p_menu_set->menu_item_pos[p_menu_set->choose_step];
924     page_id = p_menu_set->menu_item_page_id[menu_item_pos];
925    
926     while (menu_item_pos >= 0)
927     {
928     if (p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
929     {
930     menu_item_pos++;
931     break;
932     }
933    
934     if (menu_item_pos == 0)
935     {
936     break;
937     }
938    
939     menu_item_pos--;
940     }
941    
942     for (; menu_item_pos < p_menu->item_count; menu_item_pos++)
943     {
944     if (p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
945     {
946     break;
947     }
948    
949     menu_item_id = p_menu->items[menu_item_pos];
950     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
951    
952     if (p_menu_set->menu_item_display[menu_item_pos] == 0)
953     {
954     continue;
955     }
956    
957     row = p_menu_set->menu_item_r_row[menu_item_pos];
958     col = p_menu_set->menu_item_r_col[menu_item_pos];
959    
960     moveto(row, col);
961     prints("%s", p_menu_item->text);
962     }
963    
964     return 0;
965     }
966    
967     int display_menu(MENU_SET *p_menu_set)
968     {
969     int16_t row = 0;
970     int16_t col = 0;
971     int menu_selectable = 0;
972     MENU_ID menu_id;
973     MENU_ITEM_ID menu_item_id;
974     MENU *p_menu;
975     MENU_ITEM *p_menu_item;
976     int16_t menu_item_pos;
977     int16_t page_id = 0;
978     int page_item_count = 0;
979    
980     menu_id = p_menu_set->menu_id_path[p_menu_set->choose_step];
981     p_menu = get_menu_by_id(p_menu_set, menu_id);
982     if (p_menu == NULL)
983     {
984     log_error("get_menu_by_id(%d) return NULL pointer\n", menu_id);
985 sysadm 1.53 if (p_menu_set->choose_step > 0)
986     {
987     p_menu_set->choose_step--;
988     return REDRAW;
989     }
990 sysadm 1.68 return EXITMENU;
991 sysadm 1.51 }
992    
993 sysadm 1.75 if (p_menu->item_count <= 0) // empty menu
994 sysadm 1.70 {
995     moveto(p_menu->screen_row, p_menu->screen_col);
996     clrtoeol();
997 sysadm 1.71 prints("没有可选项");
998 sysadm 1.70 press_any_key();
999     return -1;
1000     }
1001    
1002 sysadm 1.51 menu_item_pos = p_menu_set->menu_item_pos[p_menu_set->choose_step];
1003     menu_item_id = p_menu->items[menu_item_pos];
1004     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1005     if (p_menu_item == NULL)
1006     {
1007     log_error("get_menu_item_by_id(%d) return NULL pointer\n", menu_item_id);
1008 sysadm 1.68 return EXITMENU;
1009 sysadm 1.51 }
1010    
1011     if (menu_item_pos > 0 &&
1012 sysadm 1.62 !(p_menu->use_filter ? (p_menu->filter_handler((void *)p_menu_item) == 0)
1013     : (checkpriv(&BBS_priv, 0, p_menu_item->priv) == 0 ||
1014     checklevel2(&BBS_priv, p_menu_item->level) == 0)))
1015 sysadm 1.51 {
1016     menu_selectable = 1;
1017     }
1018    
1019 sysadm 1.41 for (menu_item_pos = 0; menu_item_pos < p_menu->item_count; menu_item_pos++)
1020 sysadm 1.26 {
1021 sysadm 1.41 menu_item_id = p_menu->items[menu_item_pos];
1022 sysadm 1.40 p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1023    
1024     if (p_menu_item->row != 0)
1025 sysadm 1.26 {
1026 sysadm 1.40 row = p_menu_item->row;
1027 sysadm 1.26 }
1028 sysadm 1.40 if (p_menu_item->col != 0)
1029 sysadm 1.26 {
1030 sysadm 1.40 col = p_menu_item->col;
1031 sysadm 1.26 }
1032 sysadm 1.21
1033 sysadm 1.51 p_menu_set->menu_item_page_id[menu_item_pos] = page_id;
1034    
1035 sysadm 1.62 if (p_menu->use_filter ? (p_menu->filter_handler((void *)p_menu_item) == 0)
1036     : (checkpriv(&BBS_priv, 0, p_menu_item->priv) == 0 ||
1037     checklevel2(&BBS_priv, p_menu_item->level) == 0))
1038 sysadm 1.21 {
1039 sysadm 1.41 p_menu_set->menu_item_display[menu_item_pos] = 0;
1040     p_menu_set->menu_item_r_row[menu_item_pos] = 0;
1041     p_menu_set->menu_item_r_col[menu_item_pos] = 0;
1042 sysadm 1.21 }
1043     else
1044     {
1045 sysadm 1.41 p_menu_set->menu_item_display[menu_item_pos] = 1;
1046 sysadm 1.10
1047 sysadm 1.26 if (!menu_selectable)
1048     {
1049 sysadm 1.41 p_menu_set->menu_item_pos[p_menu_set->choose_step] = menu_item_pos;
1050 sysadm 1.26 menu_selectable = 1;
1051     }
1052 sysadm 1.3
1053 sysadm 1.41 p_menu_set->menu_item_r_row[menu_item_pos] = row;
1054     p_menu_set->menu_item_r_col[menu_item_pos] = col;
1055 sysadm 1.26
1056 sysadm 1.51 row++;
1057 sysadm 1.26
1058 sysadm 1.51 page_item_count++;
1059     if (p_menu->page_item_limit > 0 && page_item_count >= p_menu->page_item_limit)
1060     {
1061     page_id++;
1062     page_item_count = 0;
1063     row = p_menu->page_row;
1064     col = p_menu->page_col;
1065     }
1066 sysadm 1.21 }
1067 sysadm 1.10 }
1068    
1069 sysadm 1.21 if (!menu_selectable)
1070 sysadm 1.26 {
1071 sysadm 1.63 moveto(p_menu->screen_row, p_menu->screen_col);
1072 sysadm 1.66 clrtoeol();
1073 sysadm 1.71 prints("没有可选项");
1074 sysadm 1.63 press_any_key();
1075 sysadm 1.21 return -1;
1076 sysadm 1.26 }
1077 sysadm 1.3
1078 sysadm 1.53 if (display_menu_current_page(p_menu_set) != 0)
1079     {
1080     return -1;
1081     }
1082 sysadm 1.51
1083 sysadm 1.40 display_menu_cursor(p_menu_set, 1);
1084 sysadm 1.1
1085 sysadm 1.21 return 0;
1086 sysadm 1.1 }
1087    
1088 sysadm 1.40 int menu_control(MENU_SET *p_menu_set, int key)
1089 sysadm 1.12 {
1090 sysadm 1.40 MENU_ID menu_id;
1091     MENU_ITEM_ID menu_item_id;
1092 sysadm 1.21 MENU *p_menu;
1093 sysadm 1.40 MENU_ITEM *p_menu_item;
1094     int16_t menu_item_pos;
1095 sysadm 1.51 int16_t page_id;
1096     int require_page_change = 0;
1097 sysadm 1.12
1098 sysadm 1.40 if (p_menu_set->menu_count == 0)
1099     {
1100 sysadm 1.53 log_error("Empty menu set\n");
1101     return EXITBBS;
1102 sysadm 1.40 }
1103 sysadm 1.12
1104 sysadm 1.40 menu_id = p_menu_set->menu_id_path[p_menu_set->choose_step];
1105     p_menu = get_menu_by_id(p_menu_set, menu_id);
1106     if (p_menu == NULL)
1107     {
1108     log_error("get_menu_by_id(%d) return NULL pointer\n", menu_id);
1109 sysadm 1.53 if (p_menu_set->choose_step > 0)
1110     {
1111     p_menu_set->choose_step--;
1112     return REDRAW;
1113     }
1114     return EXITBBS;
1115 sysadm 1.40 }
1116 sysadm 1.12
1117 sysadm 1.40 if (p_menu->item_count == 0)
1118 sysadm 1.26 {
1119 sysadm 1.68 #ifdef _DEBUG
1120 sysadm 1.53 log_error("Empty menu (%s)\n", p_menu->name);
1121 sysadm 1.68 #endif
1122 sysadm 1.53 if (p_menu_set->choose_step > 0)
1123     {
1124     p_menu_set->choose_step--;
1125     return REDRAW;
1126     }
1127     return EXITBBS;
1128 sysadm 1.26 }
1129 sysadm 1.3
1130 sysadm 1.40 menu_item_pos = p_menu_set->menu_item_pos[p_menu_set->choose_step];
1131 sysadm 1.51 page_id = p_menu_set->menu_item_page_id[menu_item_pos];
1132    
1133 sysadm 1.40 menu_item_id = p_menu->items[menu_item_pos];
1134     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1135     if (p_menu_item == NULL)
1136     {
1137     log_error("get_menu_item_by_id(%d) return NULL pointer\n", menu_item_id);
1138 sysadm 1.53 p_menu_set->menu_item_pos[p_menu_set->choose_step] = 0;
1139     return REDRAW;
1140 sysadm 1.40 }
1141 sysadm 1.3
1142 sysadm 1.21 switch (key)
1143 sysadm 1.10 {
1144 sysadm 1.21 case CR:
1145     case KEY_RIGHT:
1146 sysadm 1.40 if (p_menu_item->submenu)
1147 sysadm 1.21 {
1148 sysadm 1.40 if (strcmp(p_menu_item->action, "..") == 0)
1149 sysadm 1.26 {
1150 sysadm 1.21 return menu_control(p_menu_set, KEY_LEFT);
1151 sysadm 1.26 }
1152 sysadm 1.40 p_menu_set->choose_step++;
1153     p_menu_set->menu_id_path[p_menu_set->choose_step] = p_menu_item->action_menu_id;
1154     p_menu_set->menu_item_pos[p_menu_set->choose_step] = 0;
1155 sysadm 1.26
1156 sysadm 1.40 if (display_menu(p_menu_set) != 0)
1157 sysadm 1.26 {
1158 sysadm 1.21 return menu_control(p_menu_set, KEY_LEFT);
1159 sysadm 1.26 }
1160 sysadm 1.21 }
1161     else
1162     {
1163 sysadm 1.44 return ((*(p_menu_item->action_cmd_handler))((void *)(p_menu_item->name)));
1164 sysadm 1.21 }
1165 sysadm 1.38 break;
1166 sysadm 1.60 case KEY_ESC:
1167 sysadm 1.21 case KEY_LEFT:
1168 sysadm 1.40 if (p_menu_set->choose_step > 0)
1169 sysadm 1.21 {
1170 sysadm 1.40 p_menu_set->choose_step--;
1171 sysadm 1.72 return REDRAW;
1172 sysadm 1.21 }
1173     else
1174     {
1175 sysadm 1.68 if (p_menu_set->allow_exit)
1176     {
1177     return EXITMENU;
1178     }
1179    
1180 sysadm 1.40 display_menu_cursor(p_menu_set, 0);
1181     menu_item_pos = p_menu->item_count - 1;
1182     while (menu_item_pos >= 0)
1183 sysadm 1.26 {
1184 sysadm 1.40 menu_item_id = p_menu->items[menu_item_pos];
1185     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1186     if (p_menu_item == NULL)
1187     {
1188     log_error("get_menu_item_by_id(%d) return NULL pointer\n", menu_item_id);
1189     return -1;
1190     }
1191    
1192 sysadm 1.41 if (!p_menu_set->menu_item_display[menu_item_pos] || p_menu_item->priv != 0 || p_menu_item->level != 0)
1193 sysadm 1.40 {
1194     menu_item_pos--;
1195     }
1196     else
1197     {
1198     break;
1199     }
1200 sysadm 1.26 }
1201 sysadm 1.40 p_menu_set->menu_item_pos[p_menu_set->choose_step] = menu_item_pos;
1202     display_menu_cursor(p_menu_set, 1);
1203 sysadm 1.21 }
1204 sysadm 1.38 break;
1205 sysadm 1.51 case KEY_PGUP:
1206     require_page_change = 1;
1207 sysadm 1.21 case KEY_UP:
1208 sysadm 1.40 display_menu_cursor(p_menu_set, 0);
1209 sysadm 1.21 do
1210     {
1211 sysadm 1.40 menu_item_pos--;
1212     if (menu_item_pos < 0)
1213     {
1214     menu_item_pos = p_menu->item_count - 1;
1215 sysadm 1.51 require_page_change = 0;
1216 sysadm 1.40 }
1217     menu_item_id = p_menu->items[menu_item_pos];
1218     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1219     if (p_menu_item == NULL)
1220 sysadm 1.26 {
1221 sysadm 1.40 log_error("get_menu_item_by_id(%d) return NULL pointer\n", menu_item_id);
1222     return -1;
1223 sysadm 1.26 }
1224 sysadm 1.51 if (require_page_change && p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
1225     {
1226     require_page_change = 0;
1227     }
1228     } while (require_page_change || !p_menu_set->menu_item_display[menu_item_pos]);
1229 sysadm 1.40 p_menu_set->menu_item_pos[p_menu_set->choose_step] = menu_item_pos;
1230 sysadm 1.51 if (p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
1231     {
1232     display_menu_current_page(p_menu_set);
1233     }
1234 sysadm 1.40 display_menu_cursor(p_menu_set, 1);
1235 sysadm 1.21 break;
1236 sysadm 1.51 case KEY_PGDN:
1237     require_page_change = 1;
1238 sysadm 1.21 case KEY_DOWN:
1239 sysadm 1.40 display_menu_cursor(p_menu_set, 0);
1240 sysadm 1.21 do
1241     {
1242 sysadm 1.40 menu_item_pos++;
1243     if (menu_item_pos >= p_menu->item_count)
1244     {
1245     menu_item_pos = 0;
1246 sysadm 1.51 require_page_change = 0;
1247 sysadm 1.40 }
1248     menu_item_id = p_menu->items[menu_item_pos];
1249     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1250     if (p_menu_item == NULL)
1251 sysadm 1.26 {
1252 sysadm 1.40 log_error("get_menu_item_by_id(%d) return NULL pointer\n", menu_item_id);
1253     return -1;
1254 sysadm 1.26 }
1255 sysadm 1.51 if (require_page_change && p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
1256     {
1257     require_page_change = 0;
1258     }
1259     } while (require_page_change || !p_menu_set->menu_item_display[menu_item_pos]);
1260 sysadm 1.40 p_menu_set->menu_item_pos[p_menu_set->choose_step] = menu_item_pos;
1261 sysadm 1.51 if (p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
1262     {
1263     display_menu_current_page(p_menu_set);
1264     }
1265 sysadm 1.40 display_menu_cursor(p_menu_set, 1);
1266 sysadm 1.21 break;
1267 sysadm 1.43 case KEY_HOME:
1268 sysadm 1.42 display_menu_cursor(p_menu_set, 0);
1269     menu_item_pos = 0;
1270     while (menu_item_pos < p_menu->item_count - 1)
1271     {
1272     menu_item_id = p_menu->items[menu_item_pos];
1273     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1274     if (p_menu_item == NULL)
1275     {
1276     log_error("get_menu_item_by_id(%d) return NULL pointer\n", menu_item_id);
1277     return -1;
1278     }
1279    
1280     if (p_menu_set->menu_item_display[menu_item_pos])
1281     {
1282     break;
1283     }
1284    
1285     menu_item_pos++;
1286     }
1287     p_menu_set->menu_item_pos[p_menu_set->choose_step] = menu_item_pos;
1288 sysadm 1.51 if (p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
1289     {
1290     display_menu_current_page(p_menu_set);
1291     }
1292 sysadm 1.42 display_menu_cursor(p_menu_set, 1);
1293     break;
1294 sysadm 1.43 case KEY_END:
1295 sysadm 1.42 display_menu_cursor(p_menu_set, 0);
1296     menu_item_pos = p_menu->item_count - 1;
1297     while (menu_item_pos > 0)
1298     {
1299     menu_item_id = p_menu->items[menu_item_pos];
1300     p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1301     if (p_menu_item == NULL)
1302     {
1303     log_error("get_menu_item_by_id(%d) return NULL pointer\n", menu_item_id);
1304     return -1;
1305     }
1306    
1307     if (p_menu_set->menu_item_display[menu_item_pos])
1308     {
1309     break;
1310     }
1311    
1312     menu_item_pos--;
1313     }
1314     p_menu_set->menu_item_pos[p_menu_set->choose_step] = menu_item_pos;
1315 sysadm 1.51 if (p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
1316     {
1317     display_menu_current_page(p_menu_set);
1318     }
1319 sysadm 1.42 display_menu_cursor(p_menu_set, 1);
1320     break;
1321 sysadm 1.21 default:
1322 sysadm 1.31 if (isalnum(key))
1323 sysadm 1.21 {
1324 sysadm 1.41 for (menu_item_pos = 0; menu_item_pos < p_menu->item_count; menu_item_pos++)
1325 sysadm 1.21 {
1326 sysadm 1.41 menu_item_id = p_menu->items[menu_item_pos];
1327 sysadm 1.40 p_menu_item = get_menu_item_by_id(p_menu_set, menu_item_id);
1328     if (p_menu_item == NULL)
1329     {
1330     log_error("get_menu_item_by_id(%d) return NULL pointer\n", menu_item_id);
1331     return -1;
1332     }
1333    
1334 sysadm 1.41 if (toupper(key) == toupper(p_menu_item->name[0]) && p_menu_set->menu_item_display[menu_item_pos])
1335 sysadm 1.21 {
1336 sysadm 1.40 display_menu_cursor(p_menu_set, 0);
1337 sysadm 1.41 p_menu_set->menu_item_pos[p_menu_set->choose_step] = menu_item_pos;
1338 sysadm 1.51 if (p_menu_set->menu_item_page_id[menu_item_pos] != page_id)
1339     {
1340     display_menu_current_page(p_menu_set);
1341     }
1342 sysadm 1.40 display_menu_cursor(p_menu_set, 1);
1343 sysadm 1.51 break;
1344 sysadm 1.21 }
1345     }
1346 sysadm 1.16 }
1347 sysadm 1.38 break;
1348 sysadm 1.3 }
1349 sysadm 1.1
1350 sysadm 1.48 return NOREDRAW;
1351 sysadm 1.1 }
1352 sysadm 1.15
1353 sysadm 1.40 int unload_menu(MENU_SET *p_menu_set)
1354 sysadm 1.15 {
1355 sysadm 1.57 int shmid;
1356    
1357 sysadm 1.60 if (p_menu_set == NULL)
1358     {
1359     return -1;
1360     }
1361    
1362 sysadm 1.39 if (p_menu_set->p_menu_name_dict != NULL)
1363     {
1364     trie_dict_destroy(p_menu_set->p_menu_name_dict);
1365 sysadm 1.46 p_menu_set->p_menu_name_dict = NULL;
1366 sysadm 1.39 }
1367    
1368 sysadm 1.40 if (p_menu_set->p_menu_screen_dict != NULL)
1369     {
1370     trie_dict_destroy(p_menu_set->p_menu_screen_dict);
1371 sysadm 1.46 p_menu_set->p_menu_screen_dict = NULL;
1372 sysadm 1.40 }
1373    
1374 sysadm 1.57 shmid = p_menu_set->shmid;
1375    
1376 sysadm 1.56 detach_menu_shm(p_menu_set);
1377 sysadm 1.40
1378 sysadm 1.57 if (shmctl(shmid, IPC_RMID, NULL) == -1)
1379 sysadm 1.40 {
1380 sysadm 1.57 log_error("shmctl(shmid=%d, IPC_RMID) error (%d)\n", shmid, errno);
1381 sysadm 1.40 return -1;
1382     }
1383    
1384     return 0;
1385     }
1386    
1387 sysadm 1.68 int get_menu_shm_readonly(MENU_SET *p_menu_set)
1388     {
1389     void *p_shm;
1390    
1391     p_shm = shmat(p_menu_set->shmid, NULL, SHM_RDONLY);
1392     if (p_shm == (void *)-1)
1393     {
1394     log_error("shmat(menu_shm shmid = %d) error (%d)\n", p_menu_set->shmid, errno);
1395     return -1;
1396     }
1397    
1398     p_menu_set->p_reserved = p_shm;
1399 sysadm 1.75 p_menu_set->p_menu_pool = (char *)(p_menu_set->p_reserved) + MENU_SET_RESERVED_LENGTH;
1400     p_menu_set->p_menu_item_pool = (char *)(p_menu_set->p_menu_pool) + sizeof(MENU) * MAX_MENUS;
1401     p_menu_set->p_menu_screen_pool = (char *)(p_menu_set->p_menu_item_pool) + sizeof(MENU_ITEM) * MAX_MENUITEMS;
1402     p_menu_set->p_menu_screen_buf = (char *)(p_menu_set->p_menu_screen_pool) + sizeof(MENU_SCREEN) * MAX_MENUS;
1403 sysadm 1.68 p_menu_set->p_menu_screen_buf_free = p_menu_set->p_menu_screen_buf;
1404    
1405 sysadm 1.69 p_menu_set->choose_step = 0;
1406     p_menu_set->menu_id_path[0] = 0;
1407     p_menu_set->menu_item_pos[0] = 0;
1408    
1409 sysadm 1.68 return 0;
1410     }
1411    
1412 sysadm 1.56 int set_menu_shm_readonly(MENU_SET *p_menu_set)
1413 sysadm 1.40 {
1414 sysadm 1.54 void *p_shm;
1415    
1416 sysadm 1.55 // Remap shared memory in read-only mode
1417     p_shm = shmat(p_menu_set->shmid, p_menu_set->p_reserved, SHM_RDONLY | SHM_REMAP);
1418 sysadm 1.54 if (p_shm == (void *)-1)
1419 sysadm 1.41 {
1420 sysadm 1.57 log_error("shmat(menu_shm shmid = %d) error (%d)\n", p_menu_set->shmid, errno);
1421 sysadm 1.54 return -1;
1422     }
1423 sysadm 1.62
1424 sysadm 1.54 p_menu_set->p_reserved = p_shm;
1425 sysadm 1.41
1426 sysadm 1.40 return 0;
1427 sysadm 1.15 }
1428 sysadm 1.18
1429 sysadm 1.56 int detach_menu_shm(MENU_SET *p_menu_set)
1430 sysadm 1.18 {
1431 sysadm 1.40 p_menu_set->menu_count = 0;
1432     p_menu_set->menu_item_count = 0;
1433     p_menu_set->menu_screen_count = 0;
1434     p_menu_set->choose_step = 0;
1435    
1436     p_menu_set->p_menu_pool = NULL;
1437     p_menu_set->p_menu_item_pool = NULL;
1438     p_menu_set->p_menu_screen_pool = NULL;
1439     p_menu_set->p_menu_screen_buf = NULL;
1440     p_menu_set->p_menu_screen_buf_free = NULL;
1441 sysadm 1.21
1442 sysadm 1.56 p_menu_set->p_menu_name_dict = NULL;
1443     p_menu_set->p_menu_screen_dict = NULL;
1444    
1445 sysadm 1.41 if (p_menu_set->p_reserved != NULL && shmdt(p_menu_set->p_reserved) == -1)
1446 sysadm 1.40 {
1447     log_error("shmdt() error (%d)\n", errno);
1448     return -1;
1449     }
1450 sysadm 1.56
1451 sysadm 1.40 p_menu_set->p_reserved = NULL;
1452 sysadm 1.18
1453 sysadm 1.40 return 0;
1454 sysadm 1.18 }

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