1 #include "menu.h"
2 #include "creation.h"
3 #include "layout.h"
4 #include "list.h"
5
6 form_t *root_form = 0;
7
menu_set_form(form_t * form)8 void menu_set_form(form_t *form)
9 {
10 root_form = form;
11 }
12
menu_draw_help(item_t * item)13 void menu_draw_help(item_t *item)
14 {
15 char
16 buffer[80*4],
17 *p_text,
18 *p_break,
19 *p_start;
20
21 int
22 line = 20;
23
24 bool in_word=true;
25
26 if (!item) return;
27
28 video_clear_box(1,20,78,4,' ',MENUATTR_NORMAL);
29
30 if (item->help_text)
31 {
32 /* Reformat help so that it word-wraps */
33 buffer[0] = 0;
34
35 strcpy(buffer, item->help_text);
36
37 p_text = p_break = p_start = buffer;
38 in_word = true;
39
40 for (;;)
41 {
42 if (*p_text == ' ' && in_word == true)
43 {
44 in_word = false;
45 p_break = p_text;
46 }
47 else if (*p_text != ' ')
48 {
49 in_word = true;
50 }
51 if ((p_text - p_start >= 72) || *p_text == 0) // flush
52 {
53 if (*p_text == '\0') p_break = p_text;
54 *p_break = 0;
55 video_draw_text(2,line++, MENUATTR_NORMAL, p_start, -1);
56 if (*p_text == '\0') return;
57 p_break++;
58 while (p_break < p_text && *p_break == ' ')
59 {
60 p_break++;
61 }
62 p_start = p_break;
63 if (*p_break == '\0') return;
64 }
65 else p_text++;
66 }
67 }
68 }
69
menu_draw(menu_t * menu)70 void menu_draw(menu_t *menu)
71 {
72 if (menu && menu->needs_layout)
73 {
74 menu_layout(menu);
75 }
76 if (menu)
77 {
78 item_t *item = (item_t *)(menu->item_list.first);
79
80 if (menu->type == MENUTYPE_POPUP)
81 {
82 video_clear_box(menu->x-1, menu->y-1, menu->w, menu->h, ' ', MENUATTR_NORMAL);
83 }
84
85 while (item)
86 {
87 item->f_render(menu, item,
88 (item->disabled==true)?MENUATTR_DISABLED:
89 (item == menu->current_item)?MENUATTR_HILITE : MENUATTR_ITEM);
90 item = (item_t *)(item->link.next);
91 }
92 if (menu->type == MENUTYPE_FORM)
93 {
94 menu_draw_help(menu->current_item);
95 }
96 else
97 {
98 video_draw_box(SINGLE_BOX, MENUATTR_NORMAL, NULL, 0, menu->x-1, menu->y-1,
99 menu->w+2, menu->h+3);
100 }
101 }
102 }
103
menu_draw_form(form_t * form)104 void menu_draw_form(form_t *form)
105 {
106 char
107 *title;
108 menu_t
109 *menu = form->current_menu;
110
111 /* Prefer current menu title if set, otherwise use the form title */
112 if (menu && menu->menu_title) title = menu->menu_title;
113 else if (form->form_title) title = form->form_title;
114 else title = NULL; //"Untitled";
115
116 video_draw_box(SINGLE_BOX, MENUATTR_NORMAL, title, 1, 0,0, 80, 19);
117 video_draw_box(SINGLE_BOX, MENUATTR_NORMAL, NULL, 0, 0, 19, 80, 6);
118
119 /* If we have a menu, draw it too */
120 if (menu)
121 {
122 video_clear_box(1, 3, 78, 15, ' ', MENUATTR_NORMAL);
123 menu_draw(menu);
124 }
125 }
126
menu_draw_current_form(void)127 void menu_draw_current_form(void)
128 {
129 menu_draw_form(root_form);
130 }
131
menu_form_switch_menu(form_t * form,char * name)132 void menu_form_switch_menu(form_t *form, char *name)
133 {
134 menu_t *menu = menu_form_find_menu(form, name);
135 if (!menu)
136 return;
137 menu_form_set_menu(form, menu);
138 }
139
menu_form_popup(form_t * form,menu_t * menu)140 void menu_form_popup(form_t *form, menu_t* menu)
141 {
142 if (menu && MENUTYPE_POPUP == menu->type)
143 {
144 form->popup_save = form->current_menu;
145 form->popup_item_save = form->current_menu->current_item;
146 form->current_menu = menu;
147 menu_draw(menu);
148 }
149 }
150
menu_form_popup_name(form_t * form,char * name)151 void menu_form_popup_name(form_t *form, char *name)
152 {
153 menu_t *menu = menu_form_find_menu(form, name);
154 if (!menu)
155 return;
156 menu_form_popup(form, menu);
157 }
158
menu_form_popdown(form_t * form)159 void menu_form_popdown(form_t *form)
160 {
161 if (form->current_menu && form->current_menu->type == MENUTYPE_POPUP)
162 {
163 form->current_menu = form->popup_save;
164 if (form->current_menu)
165 form->current_menu->current_item = form->popup_item_save;
166 video_clear_box(1, 3, 78, 15, ' ', MENUATTR_NORMAL);
167 if (form->current_menu)
168 menu_draw(form->current_menu);
169 }
170 }
171
menu_set_active_item(menu_t * menu,int nr)172 void menu_set_active_item(menu_t *menu, int nr)
173 {
174 item_t
175 *item = (item_t *)(menu->item_list.first);
176
177 while (item && nr > 0)
178 {
179 nr--;
180 item = (item_t *)(item->link.next);
181 }
182 if (nr == 0)
183 {
184 menu->current_item = item;
185 }
186 }
187
menu_perform_save(form_t * form)188 static void menu_perform_save(form_t *form)
189 {
190 menu_t
191 *menu;
192
193 menu = (menu_t *)(form->menu_list.first);
194 while (menu)
195 {
196 item_t
197 *item;
198
199 item = (item_t *)(menu->item_list.first);
200 while (item)
201 {
202 if (item->f_save) item->f_save(menu, item);
203 item = (item_t *)(item->link.next);
204 }
205 menu = (menu_t *)(menu->link.next);
206 }
207 }
208
209 static int leave_select = -1;
210
leave_func(item_t * item,void * dummy,int arg)211 void leave_func(item_t *item, void *dummy, int arg)
212 {
213 leave_select = arg;
214 }
215
make_leave_menu(form_t * form)216 menu_t *make_leave_menu(form_t *form)
217 {
218 menu_t
219 *menu = new_menu(MENUTYPE_POPUP, "Exit Menu", form, NULL);
220
221 if (menu)
222 {
223 item_t
224 *item;
225 item = menu_item_create(ITEMTYPE_FUNC, menu, "Save settings and exit", leave_func, NULL, EXIT_SAVE_PERMANENT);
226 item = menu_item_create(ITEMTYPE_FUNC, menu, "Use settings for this session only", leave_func, NULL, EXIT_AND_SAVE);
227 item = menu_item_create(ITEMTYPE_FUNC, menu, "Leave without saving", leave_func, NULL, EXIT_AND_NO_SAVE);
228 //item = menu_item_create(ITEMTYPE_FUNC, menu, "Return to menu", leave_func, NULL, EXIT_NOT);
229 item = menu_item_create(ITEMTYPE_FUNC, menu, "Abort boot and enter U-Boot shell", leave_func, NULL, EXIT_TO_SHELL);
230 }
231
232 menu_form_add_menu(form, menu);
233
234 menu_set_position(menu, 6, 6);
235
236 return menu;
237 }
238
239
menu_handle_single_key(form_t * form,int key)240 bool menu_handle_single_key(form_t *form, int key)
241 {
242 /*
243 Keys below 10 or so are specially mapped by us to mean one of the functions
244 of the menu system (like next item, prev item etc). All other keys are verbatim
245 keypresses that might be needed for e.g. string entry
246 */
247 item_t
248 *c_item,
249 *n_item;
250 menu_t
251 *menu = form->current_menu;
252
253 switch(key)
254 {
255 case KEY_NEXT_ITEM:
256 /* Move one item forward */
257 c_item = menu->current_item;
258 n_item = (item_t *)(c_item->link.next);
259 while (n_item && n_item->disabled == true)
260 {
261 n_item = (item_t *)(n_item->link.next);
262 }
263
264 if (n_item)
265 {
266 /* redraw the old item un-highlit */
267 c_item->f_render(menu, c_item, MENUATTR_ITEM);
268 n_item->f_render(menu, n_item, MENUATTR_HILITE);
269 menu_draw_help(n_item);
270 menu->current_item = n_item;
271 }
272 break;
273 case KEY_PREV_ITEM:
274 /* Move one item backward */
275 c_item = menu->current_item;
276 n_item = (item_t *)(c_item->link.prev);
277 while (n_item && n_item->disabled == true)
278 {
279 n_item = (item_t *)(n_item->link.prev);
280 }
281 if (n_item)
282 {
283 /* redraw the old item un-highlit */
284 c_item->f_render(menu, c_item, MENUATTR_ITEM);
285 n_item->f_render(menu, n_item, MENUATTR_HILITE);
286 menu_draw_help(n_item);
287 menu->current_item = n_item;
288 }
289 break;
290 case KEY_ABORT:
291 if (menu->type == MENUTYPE_POPUP)
292 {
293 menu_form_popdown(form);
294 }
295 else
296 {
297 if (menu->parent_menu)
298 {
299 menu_form_switch_menu(menu->parent_form, menu->parent_menu);
300 }
301 else
302 {
303 /* TODO: Implement exit from menu */
304 menu_form_popup_name(root_form, "Exit Menu");
305 return true;
306 }
307 }
308 break;
309 default:
310 if (menu->current_item)
311 {
312 menu->current_item->f_invoke(menu, menu->current_item, key);
313 }
314 if (key == KEY_ACTIVATE && menu->type == MENUTYPE_POPUP)
315 {
316 menu_form_popdown(form);
317 /* Check if we want to exit */
318 if (leave_select != -1)
319 {
320 switch(leave_select)
321 {
322 case EXIT_AND_NO_SAVE:
323 return false;
324 case EXIT_SAVE_PERMANENT:
325 menu_perform_save(form);
326 #ifndef SIM
327 saveenv();
328 #endif
329 return false;
330 case EXIT_AND_SAVE:
331 menu_perform_save(form);
332 return false;
333 case EXIT_NOT:
334 return true;
335 case EXIT_TO_SHELL:
336 {
337 char *mboot = getenv("menuboot_cmd");
338 if ((mboot) && (strlen(mboot)>2)) SETENV("menuboot_cmd", "noboot");
339 else SETENV("menuboot_cmd", "boota");
340 return false;
341 }
342 }
343 }
344 }
345 break;
346 }
347
348 return true;
349 }
350
351
menu_do(bool do_leave_menu)352 void menu_do(bool do_leave_menu)
353 {
354 bool running=true;
355 int key;
356
357 running = true;
358 leave_select = -1;
359
360 if (do_leave_menu)
361 make_leave_menu(root_form);
362
363 if (root_form)
364 {
365 menu_draw_form(root_form);
366
367 while (running)
368 {
369 key = video_get_key();
370 running = menu_handle_single_key(root_form, key);
371 }
372 }
373 }
374
375