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

Annotation of /lbbs/src/menu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.74 - (hide annotations)
Fri Oct 17 01:25:08 2025 UTC (5 months ago) by sysadm
Branch: MAIN
Changes since 1.73: +0 -1 lines
Content type: text/x-csrc
No longer use igetch_reset() to skip remaining \n after \r
\r\n -> \r and \n -> \r conversions have already been implemented in igetch()

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

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