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

Annotation of /lbbs/src/menu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.62 - (hide annotations)
Fri May 30 02:57:09 2025 UTC (9 months, 2 weeks ago) by sysadm
Branch: MAIN
Changes since 1.61: +31 -4 lines
Content type: text/x-csrc
Add s_favor based filter

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

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