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

Annotation of /lbbs/src/menu.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.51 - (hide annotations)
Mon May 19 06:26:07 2025 UTC (9 months, 4 weeks ago) by sysadm
Branch: MAIN
Changes since 1.50: +207 -26 lines
Content type: text/x-csrc
Add menu paging feature

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

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