C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
Menu Engine

Main loop and command processor for the C-Menu menu system. More...

Functions

unsigned int menu_cmd_processor (Init *init)
 Processes user input for the menu system.
unsigned int menu_engine (Init *init)
 The main loop of the menu system.

Detailed Description

Main loop and command processor for the C-Menu menu system.

This module contains the core functionality for displaying menus, processing user input, and executing commands associated with menu choices. It handles navigation through menu options, responding to special keys, and managing the display of submenus, pick lists, forms, and views.

Function Documentation

◆ menu_cmd_processor()

unsigned int menu_cmd_processor ( Init * init)

Processes user input for the menu system.

Parameters
initA pointer to an Init structure containing initialization data for the menu system.
Returns
an integer indicating the action taken by the user, such as returning to the main menu, displaying a submenu, or executing a command associated with a menu choice.

handles navigation through the menu options, executing commands associated with menu choices, and responding to special keys such as function keys and mouse clicks.

Move up to the previous menu choice

Move down to the next menu choice

Select the current menu choice and execute its associated command

Display help information for the menu system

Exit the menu and return to the previous menu or exit if at top

send default printer output file to printer

open the default editor

process mouse event

If the user presses a key that corresponds to a menu choice's letter, select that menu choice

Execute the command associated with the selected menu choice

Display help information for the menu system

Display a submenu or perform an action associated with the selected menu choice

Display a pick list or form associated with the selected menu choice

Display a form associated with the selected menu choice

Display a view associated with the selected menu choice

open ckeys (test curses keys)

return to calling program

write the current menu configuration to a file

Definition at line 133 of file menu_engine.c.

133 {
134 int i, c;
135 int len;
136 char *d;
137 int in_key;
138 char tmp_str[MAXLEN];
139 char earg_str[MAXLEN];
140 char *eargv[MAXARGS];
141 int eargc;
142 mbstate_t mbstate;
143 memset(&mbstate, 0, sizeof(mbstate));
144 cchar_t cc = {0};
145 Menu *menu = init->menu;
146 keypad(menu->win, TRUE);
147 immedok(menu->win, TRUE);
148 mousemask(BUTTON1_CLICKED | BUTTON1_DOUBLE_CLICKED, nullptr);
149 MEVENT event;
150 scrollok(menu->win, FALSE);
151
152 // Highlight the currently selected menu choice
153
154 while (1) {
155 wattron(menu->win, A_REVERSE);
156 mvwaddstr_fill(menu->win, menu->line_idx, 0,
157 menu->line[menu->line_idx]->choice_text, menu->cols);
158 wattroff(menu->win, A_REVERSE);
159 // Highlight the letter of the currently selected menu choice
160 wchar_t wstr[2] = {L'\0', L'\0'};
161 len = mbrtowc(wstr, &menu->line[menu->line_idx]->choice_letter,
162 MB_CUR_MAX, &mbstate);
163 if (len < 0) {
164 wstr[0] = L'?';
165 wstr[1] = L'\0';
166 }
167 setcchar(&cc, wstr, WA_BOLD, cp_nt_hl_rev, nullptr);
168 mvwadd_wch(menu->win, menu->line_idx,
169 menu->line[menu->line_idx]->letter_pos, &cc);
170 wrefresh(menu->win);
171
172 // Wait for user input and process it
173 event.y = event.x = -1;
174 wmove(menu->win, menu->line_idx, 1);
175 in_key = xwgetch(menu->win, nullptr, -1);
176
177 // Remove the highlight from the currently selected menu choice
178 mvwaddstr_fill(menu->win, menu->line_idx, 0,
179 menu->line[menu->line_idx]->choice_text, menu->cols);
180 len = mbrtowc(wstr, &menu->line[menu->line_idx]->choice_letter,
181 MB_CUR_MAX, &mbstate);
182 if (len < 0) {
183 wstr[0] = L'?';
184 wstr[1] = L'\0';
185 }
186 setcchar(&cc, wstr, WA_NORMAL, cp_nt_hl, nullptr);
187 mvwadd_wch(menu->win, menu->line_idx,
188 menu->line[menu->line_idx]->letter_pos, &cc);
189 // Initialize the mouse event coordinates to -1 to indicate no mouse
190 // event
191 event.y = event.x = -1;
192 switch (in_key) {
194 case KEY_UP:
195 i = menu->line_idx;
196 while (i > 0) {
197 i--;
198 if (menu->line[i]->type == MT_CHOICE) {
199 menu->line_idx = i;
200 break;
201 }
202 }
203 return (MA_CONTINUE);
205 case KEY_DOWN:
206 i = menu->line_idx;
207 while (i < menu->item_count - 1) {
208 i++;
209 if (menu->line[i]->type == MT_CHOICE) {
210 menu->line_idx = i;
211 break;
212 }
213 }
214 return (MA_CONTINUE);
217 case '\n':
218 case KEY_ENTER:
219 break;
221 case '?':
222 case KEY_F(1):
223 if (menu->f_help_spec && menu->help_spec[0] != '\0')
224 strnz__cpy(tmp_str, menu->help_spec, MAXLEN - 1);
225 else {
226 strnz__cpy(tmp_str, init->mapp_help, MAXLEN - 1);
227 strnz__cat(tmp_str, "/", MAXLEN - 1);
228 strnz__cat(tmp_str, MENU_HELP_FILE, MAXLEN - 1);
229 }
230 eargc = 0;
231 eargv[eargc++] = strdup("view");
232 eargv[eargc++] = strdup("-Nf");
233 eargv[eargc++] = strdup(tmp_str);
234 eargv[eargc] = nullptr;
235 init->lines = 51;
236 init->cols = 86;
237 init->begy = menu->begy + 1;
238 init->begx = menu->begx + 1;
239 strnz__cpy(init->title, "Menu Help", MAXLEN - 1);
240 popup_view(init, eargc, eargv, init->lines, init->cols, init->begy,
241 init->begx);
243 return (MA_DISPLAY_MENU);
246 case KEY_F(9):
247 case KEY_BREAK:
248 return (MA_RETURN);
250 case KEY_ALTF(9):
251 d = getenv("PRTCMD");
252 if (d == nullptr || *d == '\0')
254 else
255 strnz__cpy(earg_str, d, MAXLEN - 1);
256 strnz__cat(earg_str, " ", MAXLEN - 1);
257 d = getenv("PRTFILE");
258 if (d == nullptr || *d == '\0') {
259 d = getenv("HOME");
260 if (d == nullptr || *d == '\0')
262 else {
263 strnz__cat(earg_str, d, MAXLEN - 1);
264 strnz__cat(earg_str, "/", MAXLEN - 1);
266 }
267 } else
268 strnz__cat(earg_str, d, MAXLEN - 1);
270 return (MA_RESET_MENU);
272 case KEY_ALTF(10):
273 restore_wins();
274 return (MA_DISPLAY_MENU);
276 case KEY_MOUSE:
277 if (click_y == -1 || click_x == -1)
278 return (MA_CONTINUE);
279 if (click_y < 0 || click_y >= menu->item_count)
280 return (MA_CONTINUE);
281 menu->line_idx = click_y;
282 break;
283 default:
286 if (in_key == 'q')
287 return (MA_RETURN);
288 for (i = 0; i < menu->item_count; i++) {
289 if (menu->line[i]->raw_text[0] == '_') {
290 if (menu->line[i]->choice_letter == (char)in_key) {
291 menu->line_idx = i;
292 break;
293 }
294 } else {
295 if (menu->line[i]->choice_letter == (char)in_key) {
296 menu->line_idx = i;
297 break;
298 }
299 }
300 }
301 if (i >= menu->item_count)
302 return (MA_CONTINUE);
303 break;
304 }
305 char *s;
306 c = (int)menu->line[menu->line_idx]->command_type;
307 switch (c) {
311 case CT_DMON:
312 s = strpbrk(menu->line[menu->line_idx]->command_str, " \t\f\v");
313 strnz__cpy(earg_str, s, MAXLEN - 1);
314 trim(earg_str);
316 dmon(eargv);
318 return (MA_RESET_MENU);
319 case CT_EXEC:
320 s = strpbrk(menu->line[menu->line_idx]->command_str, " \t\f\v");
321 strnz__cpy(earg_str, s, MAXLEN - 1);
322 trim(earg_str);
326 return (MA_RESET_MENU);
328 case CT_HELP:
329 if (menu->f_help_spec && menu->help_spec[0] != '\0')
330 strnz__cpy(tmp_str, menu->help_spec, MAXLEN - 1);
331 else {
332 strnz__cpy(tmp_str, init->mapp_help, MAXLEN - 1);
333 strnz__cat(tmp_str, "/", MAXLEN - 1);
334 strnz__cat(tmp_str, MENU_HELP_FILE, MAXLEN - 1);
335 }
336 eargc = 0;
337 eargv[eargc++] = strdup("view");
338 eargv[eargc++] = strdup("-N");
339 eargv[eargc++] = strdup("f");
340 eargv[eargc++] = strdup(tmp_str);
341 eargv[eargc] = nullptr;
342 init->lines = 40;
343 init->cols = 60;
344 init->begy = menu->begy + 1;
345 init->begx = menu->begx + 1;
346 strnz__cpy(init->title, "Menu Help", MAXLEN - 1);
347 popup_view(init, eargc, eargv, init->lines, init->cols, init->begy,
348 init->begx);
350 return (MA_DISPLAY_MENU);
353 case CT_MENU:
354 strnz__cpy(earg_str, menu->line[menu->line_idx]->command_str,
355 MAXLEN - 1);
357 if (eargc == 0)
358 return (MA_DISPLAY_MENU);
359 popup_menu(init, eargc, eargv, menu->begy + 1, menu->begx + 1);
361 return (MA_RESET_MENU);
364 case CT_PICK:
365 strnz__cpy(earg_str, menu->line[menu->line_idx]->command_str,
366 MAXLEN - 1);
368 popup_pick(init, eargc, eargv, menu->begy + 1, menu->begx + 1);
370 return (MA_DISPLAY_MENU);
373 case CT_FORM:
374 strnz__cpy(earg_str, menu->line[menu->line_idx]->command_str,
375 MAXLEN - 1);
377 popup_form(init, eargc, eargv, menu->begy + 1, menu->begx + 1);
379 return (MA_RESET_MENU);
382 case CT_VIEW:
383 strnz__cpy(earg_str, menu->line[menu->line_idx]->command_str,
384 MAXLEN - 1);
386 init->lines = 66;
387 init->cols = 80;
388 init->begy = menu->begy + 1;
389 init->begx = menu->begx + 1;
390 strnz__cpy(init->title, menu->line[menu->line_idx]->raw_text,
391 MAXLEN - 1);
392 popup_view(init, eargc, eargv, init->lines, init->cols, init->begy,
393 init->begx);
395 return (MA_DISPLAY_MENU);
397 case CT_CKEYS:
398 popup_ckeys();
399 return (MA_DISPLAY_MENU);
401 case CT_RETURN:
402 return (MA_RETURN);
404 case CT_WRITE_CONFIG:
406 return (MA_CONTINUE);
407 default:
408 return (MA_CONTINUE);
409 }
410 }
411 return 0;
412}
#define PRINTCMD
Definition common.h:44
#define VIEW_PRT_FILE
Definition common.h:38
Init * init
Definition init.c:74
int popup_form(Init *, int, char **, int, int)
instantiate a form popup window
Definition popups.c:113
#define MENU_HELP_FILE
Definition common.h:34
int popup_menu(Init *, int, char **, int, int)
instantiate a menu popup window
Definition popups.c:53
int popup_view(Init *, int, char **, int, int, int, int)
instantiate a view popup window
Definition popups.c:146
int popup_pick(Init *, int, char **, int, int)
instantiate a pick popup window
Definition popups.c:83
#define MAX_ARGS
Definition cm.h:28
#define MAXARGS
Definition cm.h:30
#define KEY_ALTF(n)
Definition cm.h:403
Menu * menu
Definition mem.c:45
@ MT_CHOICE
Definition menu.h:24
@ CT_PICK
Definition menu.h:46
@ CT_FORM
Definition menu.h:42
@ CT_MENU
Definition menu.h:45
@ CT_RETURN
Definition menu.h:49
@ CT_HELP
Definition menu.h:40
@ CT_WRITE_CONFIG
Definition menu.h:51
@ CT_EXEC
Definition menu.h:39
@ CT_VIEW
Definition menu.h:47
@ CT_DMON
Definition menu.h:38
@ CT_CKEYS
Definition menu.h:48
@ MA_RETURN
Definition menu.h:29
@ MA_DISPLAY_MENU
Definition menu.h:30
@ MA_RESET_MENU
Definition menu.h:31
@ MA_CONTINUE
Definition menu.h:32
#define TRUE
Definition iloan.c:19
#define FALSE
Definition iloan.c:18
int popup_ckeys()
Display Curses Keys Responds to curses keys and mouse events, displaying the key code and description...
Definition curskeys.c:23
#define MAXLEN
Definition curskeys.c:15
int eargc
Definition futil.c:51
char earg_str[MAXLEN]
Definition futil.c:50
char * eargv[MAXARGS]
Definition futil.c:52
int cp_nt_hl
Definition dwin.c:150
int click_x
Definition dwin.c:49
int cp_nt_hl_rev
Definition dwin.c:151
int click_y
Definition dwin.c:48
int xwgetch(WINDOW *, Chyron *, int)
Wrapper for wgetch that handles signals, mouse events, checks for clicks on the chyron line,...
Definition dwin.c:1651
void restore_wins()
Restore all windows after a screen resize.
Definition dwin.c:933
void mvwaddstr_fill(WINDOW *, int, int, char *, int)
For lines shorter than their display area, fill the rest with spaces.
Definition dwin.c:1515
int dmon(char **)
Fork and execute a command as a daemon.
Definition exec.c:226
int full_screen_fork_exec(char **)
Execute a command in full screen mode.
Definition exec.c:46
int full_screen_shell(char *)
Execute a shell command in full screen mode.
Definition exec.c:62
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition futil.c:435
int destroy_argv(int argc, char **argv)
Deallocates memory allocated for argument strings in argv.
Definition futil.c:385
size_t trim(char *)
Trims leading and trailing spaces from string s in place.
Definition futil.c:282
size_t strnz__cat(char *, const char *, size_t)
safer alternative to strncat
Definition futil.c:464
int str_to_args(char **, char *, int)
Converts a string into an array of argument strings.
Definition futil.c:331
int write_config(Init *)
Write the current configuration to a file specified in init->minitrc.
Definition init.c:797
The Menu structure is the main data structure for the menu application, containing all the informatio...
Definition menu.h:90

References Init::begx, Menu::begx, Init::begy, Menu::begy, Line::choice_letter, Line::choice_text, click_x, click_y, Init::cols, Menu::cols, Line::command_str, Line::command_type, cp_nt_hl, cp_nt_hl_rev, CT_CKEYS, CT_DMON, CT_EXEC, CT_FORM, CT_HELP, CT_MENU, CT_PICK, CT_RETURN, CT_VIEW, CT_WRITE_CONFIG, destroy_argv(), dmon(), Menu::f_help_spec, full_screen_fork_exec(), full_screen_shell(), Menu::help_spec, Menu::item_count, Line::letter_pos, Menu::line, Menu::line_idx, Init::lines, MA_CONTINUE, MA_DISPLAY_MENU, MA_RESET_MENU, MA_RETURN, Init::mapp_help, Init::menu, MT_CHOICE, mvwaddstr_fill(), popup_ckeys(), popup_form(), popup_menu(), popup_pick(), popup_view(), Line::raw_text, restore_wins(), str_to_args(), strnz__cat(), strnz__cpy(), Init::title, trim(), Line::type, Menu::win, write_config(), and xwgetch().

Referenced by menu_engine().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ menu_engine()

unsigned int menu_engine ( Init * init)

The main loop of the menu system.

Parameters
initA pointer to an Init structure containing initialization data for the menu system.
Returns
an integer indicating the action taken by the user, such as returning to the main menu or exiting the menu system.

displays the menu and processes user input until the user exits the menu or returns to the main menu.

Definition at line 38 of file menu_engine.c.

38 {
39 int action;
40 int i;
41 char tmp_str[MAXLEN];
42 Menu *menu = init->menu;
43 if (menu == nullptr) {
44 Perror("menu_engine: menu is nullptr");
45 return (1);
46 }
47 menu->lines = 0;
48 menu->cols = 0;
49 menu->line_idx = 0;
50 menu->item_count = 0;
51 menu->title[0] = '\0';
52 menu->choice_max_len = 0;
53 menu->text_max_len = 0;
55 if (box_new(menu->lines, menu->cols, menu->begy, menu->begx, menu->title,
56 true)) {
57 ssnprintf(tmp_str, MAXLEN - 1, "box_new(%d, %d, %d, %d, %s) failed",
58 menu->lines, menu->cols, menu->begy, menu->begx, menu->title);
59 Perror(tmp_str);
60 return 1;
61 }
62 menu->win = win_win[win_ptr];
63 menu->box = win_box[win_ptr];
64
65 int len;
66 mbstate_t mbstate;
67 memset(&mbstate, 0, sizeof(mbstate));
68 cchar_t cc = {0};
69
70 action = MA_DISPLAY_MENU;
71 while (action) {
72 switch (action) {
73 case MA_RETURN:
74 win_del();
75 if (win_ptr < 0) {
77 return 0;
78 }
79 menu->win = win_win[win_ptr];
80 menu->box = win_box[win_ptr];
82 return 0;
83 case MA_DISPLAY_MENU:
84 for (menu->line_idx = 0; menu->line_idx < menu->item_count;
85 menu->line_idx++) {
86 mvwaddstr(menu->win, menu->line_idx, 0,
87 menu->line[menu->line_idx]->choice_text);
88 // Highlight the letter of the menu choice
89 wchar_t wstr[2] = {L'\0', L'\0'};
90 len = mbrtowc(wstr, &menu->line[menu->line_idx]->choice_letter,
91 MB_CUR_MAX, &mbstate);
92 if (len < 0) {
93 wstr[0] = L'?';
94 wstr[1] = L'\0';
95 }
96 setcchar(&cc, wstr, WA_NORMAL, cp_nt_hl, nullptr);
97 mvwadd_wch(menu->win, menu->line_idx,
98 menu->line[menu->line_idx]->letter_pos, &cc);
99 }
100 action = MA_RESET_MENU;
101 break;
102 case MA_RESET_MENU:
103 menu->line_idx = 0;
104 for (i = 0; i < menu->item_count; i++) {
105 if (menu->line[i]->type == MT_CHOICE) {
106 menu->line_idx = i;
107 break;
108 }
109 }
110 action = MA_CONTINUE;
111 break;
112 case MA_CONTINUE:
113 action = menu_cmd_processor(init);
114 break;
115 default:
116 break;
117 }
118 }
120 return 0;
121}
WINDOW * win_win[MAXWIN]
Definition dwin.c:122
int win_ptr
Definition dwin.c:130
WINDOW * win_box[MAXWIN]
Definition dwin.c:124
int box_new(int, int, int, int, char *, bool)
Create a new window with optional box and title.
Definition dwin.c:745
WINDOW * win_del()
Delete the current window and its associated box window.
Definition dwin.c:893
int Perror(char *)
Display a simple error message window or print to stderr.
Definition dwin.c:1162
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition futil.c:311
Menu * destroy_menu(Init *init)
Destroy Menu structure.
Definition mem.c:169
unsigned int menu_cmd_processor(Init *)
Processes user input for the menu system.
unsigned int parse_menu_description(Init *)
Parse menu description file and create Menu.

References Menu::begx, Menu::begy, Menu::box, box_new(), Line::choice_letter, Menu::choice_max_len, Line::choice_text, Menu::cols, cp_nt_hl, destroy_menu(), Menu::item_count, Line::letter_pos, Menu::line, Menu::line_idx, Menu::lines, MA_CONTINUE, MA_DISPLAY_MENU, MA_RESET_MENU, MA_RETURN, Init::menu, menu_cmd_processor(), MT_CHOICE, parse_menu_description(), Perror(), restore_wins(), ssnprintf(), Menu::text_max_len, Menu::title, Line::type, Menu::win, win_box, win_del(), win_ptr, and win_win.

Referenced by main(), and popup_menu().

Here is the call graph for this function:
Here is the caller graph for this function: