This source file includes following definitions.
- menu_arrange
- menubar_paint_idx
- menubar_draw_drop
- menubar_set_color
- menubar_draw
- menubar_remove
- menubar_left
- menubar_right
- menubar_finish
- menubar_drop
- menubar_execute
- menubar_down
- menubar_up
- menubar_first
- menubar_last
- menubar_try_drop_menu
- menubar_try_exec_menu
- menubar_execute_cmd
- menubar_handle_key
- menubar_refresh
- menubar_free_menu
- menubar_callback
- menubar_get_menu_by_x_coord
- menubar_mouse_on_menu
- menubar_change_selected_item
- menubar_mouse_callback
- menu_entry_create
- menu_entry_free
- create_menu
- menu_set_name
- destroy_menu
- menubar_new
- menubar_set_menu
- menubar_add_menu
- menubar_arrange
- find_menubar
- menubar_activate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include <config.h>
31
32 #include <ctype.h>
33 #include <stdarg.h>
34 #include <string.h>
35 #include <sys/types.h>
36
37 #include "lib/global.h"
38
39 #include "lib/tty/tty.h"
40 #include "lib/skin.h"
41 #include "lib/tty/key.h"
42 #include "lib/strutil.h"
43 #include "lib/widget.h"
44 #include "lib/event.h"
45
46
47
48 const global_keymap_t *menu_map = NULL;
49
50
51
52 #define MENUENTRY(x) ((menu_entry_t *)(x))
53 #define MENU(x) ((menu_t *)(x))
54
55
56
57 struct menu_entry_t
58 {
59 unsigned char first_letter;
60 hotkey_t text;
61 long command;
62 char *shortcut;
63 };
64
65 struct menu_t
66 {
67 int start_x;
68 hotkey_t text;
69 GList *entries;
70 size_t max_entry_len;
71 size_t max_hotkey_len;
72 unsigned int selected;
73 char *help_node;
74 };
75
76
77
78
79
80
81 static void
82 menu_arrange (menu_t * menu, dlg_shortcut_str get_shortcut)
83 {
84 if (menu != NULL)
85 {
86 GList *i;
87 size_t max_shortcut_len = 0;
88
89 menu->max_entry_len = 1;
90 menu->max_hotkey_len = 1;
91
92 for (i = menu->entries; i != NULL; i = g_list_next (i))
93 {
94 menu_entry_t *entry = MENUENTRY (i->data);
95
96 if (entry != NULL)
97 {
98 size_t len;
99
100 len = (size_t) hotkey_width (entry->text);
101 menu->max_hotkey_len = MAX (menu->max_hotkey_len, len);
102
103 if (get_shortcut != NULL)
104 entry->shortcut = get_shortcut (entry->command);
105
106 if (entry->shortcut != NULL)
107 {
108 len = (size_t) str_term_width1 (entry->shortcut);
109 max_shortcut_len = MAX (max_shortcut_len, len);
110 }
111 }
112 }
113
114 menu->max_entry_len = menu->max_hotkey_len + max_shortcut_len;
115 }
116 }
117
118
119
120 static void
121 menubar_paint_idx (const WMenuBar * menubar, unsigned int idx, int color)
122 {
123 const Widget *w = CONST_WIDGET (menubar);
124 const menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->selected));
125 const menu_entry_t *entry = MENUENTRY (g_list_nth_data (menu->entries, idx));
126 const int y = 2 + idx;
127 int x = menu->start_x;
128
129 if (x + menu->max_entry_len + 4 > (gsize) w->cols)
130 x = w->cols - menu->max_entry_len - 4;
131
132 if (entry == NULL)
133 {
134
135 tty_setcolor (MENU_ENTRY_COLOR);
136
137 widget_gotoyx (w, y, x - 1);
138 tty_print_alt_char (ACS_LTEE, FALSE);
139 tty_draw_hline (w->y + y, w->x + x, ACS_HLINE, menu->max_entry_len + 3);
140 widget_gotoyx (w, y, x + menu->max_entry_len + 3);
141 tty_print_alt_char (ACS_RTEE, FALSE);
142 }
143 else
144 {
145 int yt, xt;
146
147
148 tty_setcolor (color);
149 widget_gotoyx (w, y, x);
150 tty_print_char ((unsigned char) entry->first_letter);
151 tty_getyx (&yt, &xt);
152 tty_draw_hline (yt, xt, ' ', menu->max_entry_len + 2);
153 tty_print_string (entry->text.start);
154
155 if (entry->text.hotkey != NULL)
156 {
157 tty_setcolor (color == MENU_SELECTED_COLOR ? MENU_HOTSEL_COLOR : MENU_HOT_COLOR);
158 tty_print_string (entry->text.hotkey);
159 tty_setcolor (color);
160 }
161
162 if (entry->text.end != NULL)
163 tty_print_string (entry->text.end);
164
165 if (entry->shortcut != NULL)
166 {
167 widget_gotoyx (w, y, x + menu->max_hotkey_len + 3);
168 tty_print_string (entry->shortcut);
169 }
170
171
172 widget_gotoyx (w, y, x + 1);
173 }
174 }
175
176
177
178 static void
179 menubar_draw_drop (const WMenuBar * menubar)
180 {
181 const Widget *w = CONST_WIDGET (menubar);
182 const menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->selected));
183 const unsigned int count = g_list_length (menu->entries);
184 int column = menu->start_x - 1;
185 unsigned int i;
186
187 if (column + menu->max_entry_len + 5 > (gsize) w->cols)
188 column = w->cols - menu->max_entry_len - 5;
189
190 if (mc_global.tty.shadows)
191 tty_draw_box_shadow (w->y + 1, w->x + column, count + 2, menu->max_entry_len + 5,
192 SHADOW_COLOR);
193
194 tty_setcolor (MENU_ENTRY_COLOR);
195 tty_draw_box (w->y + 1, w->x + column, count + 2, menu->max_entry_len + 5, FALSE);
196
197 for (i = 0; i < count; i++)
198 menubar_paint_idx (menubar, i,
199 i == menu->selected ? MENU_SELECTED_COLOR : MENU_ENTRY_COLOR);
200 }
201
202
203
204 static void
205 menubar_set_color (const WMenuBar * menubar, gboolean current, gboolean hotkey)
206 {
207 if (!widget_get_state (CONST_WIDGET (menubar), WST_FOCUSED))
208 tty_setcolor (MENU_INACTIVE_COLOR);
209 else if (current)
210 tty_setcolor (hotkey ? MENU_HOTSEL_COLOR : MENU_SELECTED_COLOR);
211 else
212 tty_setcolor (hotkey ? MENU_HOT_COLOR : MENU_ENTRY_COLOR);
213 }
214
215
216
217 static void
218 menubar_draw (const WMenuBar * menubar)
219 {
220 const Widget *w = CONST_WIDGET (menubar);
221 GList *i;
222
223
224 tty_setcolor (widget_get_state (w, WST_FOCUSED) ? MENU_ENTRY_COLOR : MENU_INACTIVE_COLOR);
225 tty_draw_hline (w->y, w->x, ' ', w->cols);
226
227
228 for (i = menubar->menu; i != NULL; i = g_list_next (i))
229 {
230 menu_t *menu = MENU (i->data);
231 gboolean is_selected = (menubar->selected == (gsize) g_list_position (menubar->menu, i));
232
233 menubar_set_color (menubar, is_selected, FALSE);
234 widget_gotoyx (w, 0, menu->start_x);
235
236 tty_print_char (' ');
237 tty_print_string (menu->text.start);
238
239 if (menu->text.hotkey != NULL)
240 {
241 menubar_set_color (menubar, is_selected, TRUE);
242 tty_print_string (menu->text.hotkey);
243 menubar_set_color (menubar, is_selected, FALSE);
244 }
245
246 if (menu->text.end != NULL)
247 tty_print_string (menu->text.end);
248
249 tty_print_char (' ');
250 }
251
252 if (menubar->is_dropped)
253 menubar_draw_drop (menubar);
254 else
255 widget_gotoyx (w, 0, MENU (g_list_nth_data (menubar->menu, menubar->selected))->start_x);
256 }
257
258
259
260 static void
261 menubar_remove (WMenuBar * menubar)
262 {
263 Widget *g;
264
265 if (!menubar->is_dropped)
266 return;
267
268
269
270
271
272 g = WIDGET (WIDGET (menubar)->owner);
273 GROUP (g)->current = widget_find (g, widget_find_by_id (g, menubar->previous_widget));
274
275 menubar->is_dropped = FALSE;
276 do_refresh ();
277 menubar->is_dropped = TRUE;
278
279
280 GROUP (g)->current = widget_find (g, WIDGET (menubar));
281 }
282
283
284
285 static void
286 menubar_left (WMenuBar * menubar)
287 {
288 menubar_remove (menubar);
289 if (menubar->selected == 0)
290 menubar->selected = g_list_length (menubar->menu) - 1;
291 else
292 menubar->selected--;
293 menubar_draw (menubar);
294 }
295
296
297
298 static void
299 menubar_right (WMenuBar * menubar)
300 {
301 menubar_remove (menubar);
302 menubar->selected = (menubar->selected + 1) % g_list_length (menubar->menu);
303 menubar_draw (menubar);
304 }
305
306
307
308 static void
309 menubar_finish (WMenuBar * menubar)
310 {
311 Widget *w = WIDGET (menubar);
312
313 menubar->is_dropped = FALSE;
314 w->lines = 1;
315 widget_want_hotkey (w, FALSE);
316 widget_set_options (w, WOP_SELECTABLE, FALSE);
317
318 if (!mc_global.keybar_visible)
319 widget_hide (w);
320 else
321 {
322
323
324 widget_set_bottom (w);
325 }
326
327
328 if (DIALOG (w->owner)->bg != NULL)
329 widget_set_bottom (WIDGET (DIALOG (w->owner)->bg));
330
331 group_select_widget_by_id (w->owner, menubar->previous_widget);
332 do_refresh ();
333 }
334
335
336
337 static void
338 menubar_drop (WMenuBar * menubar, unsigned int selected)
339 {
340 menubar->is_dropped = TRUE;
341 menubar->selected = selected;
342 menubar_draw (menubar);
343 }
344
345
346
347 static void
348 menubar_execute (WMenuBar * menubar)
349 {
350 const menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->selected));
351 const menu_entry_t *entry = MENUENTRY (g_list_nth_data (menu->entries, menu->selected));
352
353 if ((entry != NULL) && (entry->command != CK_IgnoreKey))
354 {
355 Widget *w = WIDGET (menubar);
356
357 mc_global.widget.is_right = (menubar->selected != 0);
358 menubar_finish (menubar);
359 send_message (w->owner, w, MSG_ACTION, entry->command, NULL);
360 do_refresh ();
361 }
362 }
363
364
365
366 static void
367 menubar_down (WMenuBar * menubar)
368 {
369 menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->selected));
370 const unsigned int len = g_list_length (menu->entries);
371 menu_entry_t *entry;
372
373 menubar_paint_idx (menubar, menu->selected, MENU_ENTRY_COLOR);
374
375 do
376 {
377 menu->selected = (menu->selected + 1) % len;
378 entry = MENUENTRY (g_list_nth_data (menu->entries, menu->selected));
379 }
380 while ((entry == NULL) || (entry->command == CK_IgnoreKey));
381
382 menubar_paint_idx (menubar, menu->selected, MENU_SELECTED_COLOR);
383 }
384
385
386
387 static void
388 menubar_up (WMenuBar * menubar)
389 {
390 menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->selected));
391 const unsigned int len = g_list_length (menu->entries);
392 menu_entry_t *entry;
393
394 menubar_paint_idx (menubar, menu->selected, MENU_ENTRY_COLOR);
395
396 do
397 {
398 if (menu->selected == 0)
399 menu->selected = len - 1;
400 else
401 menu->selected--;
402 entry = MENUENTRY (g_list_nth_data (menu->entries, menu->selected));
403 }
404 while ((entry == NULL) || (entry->command == CK_IgnoreKey));
405
406 menubar_paint_idx (menubar, menu->selected, MENU_SELECTED_COLOR);
407 }
408
409
410
411 static void
412 menubar_first (WMenuBar * menubar)
413 {
414 if (menubar->is_dropped)
415 {
416 menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->selected));
417
418 if (menu->selected == 0)
419 return;
420
421 menubar_paint_idx (menubar, menu->selected, MENU_ENTRY_COLOR);
422
423 menu->selected = 0;
424
425 while (TRUE)
426 {
427 menu_entry_t *entry;
428
429 entry = MENUENTRY (g_list_nth_data (menu->entries, menu->selected));
430
431 if ((entry == NULL) || (entry->command == CK_IgnoreKey))
432 menu->selected++;
433 else
434 break;
435 }
436
437 menubar_paint_idx (menubar, menu->selected, MENU_SELECTED_COLOR);
438 }
439 else
440 {
441 menubar->selected = 0;
442 menubar_draw (menubar);
443 }
444 }
445
446
447
448 static void
449 menubar_last (WMenuBar * menubar)
450 {
451 if (menubar->is_dropped)
452 {
453 menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->selected));
454 const unsigned int len = g_list_length (menu->entries);
455 menu_entry_t *entry;
456
457 if (menu->selected == len - 1)
458 return;
459
460 menubar_paint_idx (menubar, menu->selected, MENU_ENTRY_COLOR);
461
462 menu->selected = len;
463
464 do
465 {
466 menu->selected--;
467 entry = MENUENTRY (g_list_nth_data (menu->entries, menu->selected));
468 }
469 while ((entry == NULL) || (entry->command == CK_IgnoreKey));
470
471 menubar_paint_idx (menubar, menu->selected, MENU_SELECTED_COLOR);
472 }
473 else
474 {
475 menubar->selected = g_list_length (menubar->menu) - 1;
476 menubar_draw (menubar);
477 }
478 }
479
480
481
482 static cb_ret_t
483 menubar_try_drop_menu (WMenuBar * menubar, int hotkey)
484 {
485 GList *i;
486
487 for (i = menubar->menu; i != NULL; i = g_list_next (i))
488 {
489 menu_t *menu = MENU (i->data);
490
491 if (menu->text.hotkey != NULL && hotkey == g_ascii_tolower (menu->text.hotkey[0]))
492 {
493 menubar_drop (menubar, g_list_position (menubar->menu, i));
494 return MSG_HANDLED;
495 }
496 }
497
498 return MSG_NOT_HANDLED;
499 }
500
501
502
503 static cb_ret_t
504 menubar_try_exec_menu (WMenuBar * menubar, int hotkey)
505 {
506 menu_t *menu;
507 GList *i;
508
509 menu = g_list_nth_data (menubar->menu, menubar->selected);
510
511 for (i = menu->entries; i != NULL; i = g_list_next (i))
512 {
513 const menu_entry_t *entry = MENUENTRY (i->data);
514
515 if (entry != NULL && entry->text.hotkey != NULL
516 && hotkey == g_ascii_tolower (entry->text.hotkey[0]))
517 {
518 menu->selected = g_list_position (menu->entries, i);
519 menubar_execute (menubar);
520 return MSG_HANDLED;
521 }
522 }
523
524 return MSG_NOT_HANDLED;
525 }
526
527
528
529 static cb_ret_t
530 menubar_execute_cmd (WMenuBar * menubar, long command)
531 {
532 cb_ret_t ret = MSG_HANDLED;
533
534 switch (command)
535 {
536 case CK_Help:
537 {
538 ev_help_t event_data = { NULL, NULL };
539
540 if (menubar->is_dropped)
541 event_data.node =
542 MENU (g_list_nth_data (menubar->menu, menubar->selected))->help_node;
543 else
544 event_data.node = "[Menu Bar]";
545
546 mc_event_raise (MCEVENT_GROUP_CORE, "help", &event_data);
547 menubar_draw (menubar);
548 }
549 break;
550
551 case CK_Left:
552 menubar_left (menubar);
553 break;
554 case CK_Right:
555 menubar_right (menubar);
556 break;
557 case CK_Up:
558 if (menubar->is_dropped)
559 menubar_up (menubar);
560 break;
561 case CK_Down:
562 if (menubar->is_dropped)
563 menubar_down (menubar);
564 else
565 menubar_drop (menubar, menubar->selected);
566 break;
567 case CK_Home:
568 menubar_first (menubar);
569 break;
570 case CK_End:
571 menubar_last (menubar);
572 break;
573
574 case CK_Enter:
575 if (menubar->is_dropped)
576 menubar_execute (menubar);
577 else
578 menubar_drop (menubar, menubar->selected);
579 break;
580 case CK_Quit:
581 menubar_finish (menubar);
582 break;
583
584 default:
585 ret = MSG_NOT_HANDLED;
586 break;
587 }
588
589 return ret;
590 }
591
592
593
594 static int
595 menubar_handle_key (WMenuBar * menubar, int key)
596 {
597 long cmd;
598 cb_ret_t ret = MSG_NOT_HANDLED;
599
600 cmd = widget_lookup_key (WIDGET (menubar), key);
601
602 if (cmd != CK_IgnoreKey)
603 ret = menubar_execute_cmd (menubar, cmd);
604
605 if (ret != MSG_HANDLED)
606 {
607 if (menubar->is_dropped)
608 ret = menubar_try_exec_menu (menubar, key);
609 else
610 ret = menubar_try_drop_menu (menubar, key);
611 }
612
613 return ret;
614 }
615
616
617
618 static gboolean
619 menubar_refresh (WMenuBar * menubar)
620 {
621 Widget *w = WIDGET (menubar);
622
623 if (!widget_get_state (w, WST_FOCUSED))
624 return FALSE;
625
626
627 w->lines = LINES;
628
629
630 widget_want_hotkey (w, TRUE);
631 return TRUE;
632 }
633
634
635
636 static inline void
637 menubar_free_menu (WMenuBar * menubar)
638 {
639 g_clear_list (&menubar->menu, (GDestroyNotify) destroy_menu);
640 }
641
642
643
644 static cb_ret_t
645 menubar_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
646 {
647 WMenuBar *menubar = MENUBAR (w);
648
649 switch (msg)
650 {
651
652 case MSG_FOCUS:
653 if (menubar_refresh (menubar))
654 {
655 menubar_draw (menubar);
656 return MSG_HANDLED;
657 }
658 return MSG_NOT_HANDLED;
659
660 case MSG_UNFOCUS:
661 return widget_get_state (w, WST_FOCUSED) ? MSG_NOT_HANDLED : MSG_HANDLED;
662
663
664 case MSG_HOTKEY:
665 case MSG_KEY:
666 if (widget_get_state (w, WST_FOCUSED))
667 {
668 menubar_handle_key (menubar, parm);
669 return MSG_HANDLED;
670 }
671 return MSG_NOT_HANDLED;
672
673 case MSG_CURSOR:
674
675 return MSG_NOT_HANDLED;
676
677 case MSG_DRAW:
678 if (widget_get_state (w, WST_VISIBLE) || menubar_refresh (menubar))
679 menubar_draw (menubar);
680 return MSG_HANDLED;
681
682 case MSG_RESIZE:
683
684 widget_default_callback (w, NULL, MSG_RESIZE, 0, data);
685 menubar_refresh (menubar);
686 return MSG_HANDLED;
687
688 case MSG_DESTROY:
689 menubar_free_menu (menubar);
690 return MSG_HANDLED;
691
692 default:
693 return widget_default_callback (w, sender, msg, parm, data);
694 }
695 }
696
697
698
699 static unsigned int
700 menubar_get_menu_by_x_coord (const WMenuBar * menubar, int x)
701 {
702 unsigned int i;
703 GList *menu;
704
705 for (i = 0, menu = menubar->menu;
706 menu != NULL && x >= MENU (menu->data)->start_x; i++, menu = g_list_next (menu))
707 ;
708
709
710 if (i != 0)
711 i--;
712
713 return i;
714 }
715
716
717
718 static gboolean
719 menubar_mouse_on_menu (const WMenuBar * menubar, int y, int x)
720 {
721 Widget *w = WIDGET (menubar);
722 menu_t *menu;
723 int left_x, right_x, bottom_y;
724
725 if (!menubar->is_dropped)
726 return FALSE;
727
728 menu = MENU (g_list_nth_data (menubar->menu, menubar->selected));
729 left_x = menu->start_x;
730 right_x = left_x + menu->max_entry_len + 3;
731 if (right_x > w->cols)
732 {
733 left_x = w->cols - (menu->max_entry_len + 3);
734 right_x = w->cols;
735 }
736
737 bottom_y = g_list_length (menu->entries) + 2;
738
739 return (x >= left_x && x < right_x && y > 1 && y < bottom_y);
740 }
741
742
743
744 static void
745 menubar_change_selected_item (WMenuBar * menubar, int y)
746 {
747 menu_t *menu;
748 menu_entry_t *entry;
749
750 y -= 2;
751 menu = MENU (g_list_nth_data (menubar->menu, menubar->selected));
752 entry = MENUENTRY (g_list_nth_data (menu->entries, y));
753
754 if (entry != NULL && entry->command != CK_IgnoreKey)
755 {
756 menubar_paint_idx (menubar, menu->selected, MENU_ENTRY_COLOR);
757 menu->selected = y;
758 menubar_paint_idx (menubar, menu->selected, MENU_SELECTED_COLOR);
759 }
760 }
761
762
763
764 static void
765 menubar_mouse_callback (Widget * w, mouse_msg_t msg, mouse_event_t * event)
766 {
767 static gboolean was_drag = FALSE;
768
769 WMenuBar *menubar = MENUBAR (w);
770 gboolean mouse_on_drop;
771
772 mouse_on_drop = menubar_mouse_on_menu (menubar, event->y, event->x);
773
774 switch (msg)
775 {
776 case MSG_MOUSE_DOWN:
777 was_drag = FALSE;
778
779 if (event->y == 0)
780 {
781
782 unsigned int selected;
783
784 selected = menubar_get_menu_by_x_coord (menubar, event->x);
785 menubar_activate (menubar, TRUE, selected);
786 menubar_remove (menubar);
787 menubar_drop (menubar, selected);
788 }
789 else if (mouse_on_drop)
790 menubar_change_selected_item (menubar, event->y);
791 else
792 {
793
794 menubar_finish (menubar);
795
796
797
798
799
800
801
802
803
804
805
806
807
808 w->mouse.capture = FALSE;
809 }
810 break;
811
812 case MSG_MOUSE_UP:
813 if (was_drag && mouse_on_drop)
814 menubar_execute (menubar);
815 was_drag = FALSE;
816 break;
817
818 case MSG_MOUSE_CLICK:
819 was_drag = FALSE;
820
821 if ((event->buttons & GPM_B_MIDDLE) != 0 && event->y > 0 && menubar->is_dropped)
822 {
823
824 menubar_execute (menubar);
825 }
826 else if (mouse_on_drop)
827 menubar_execute (menubar);
828 else if (event->y > 0)
829
830 menubar_finish (menubar);
831 break;
832
833 case MSG_MOUSE_DRAG:
834 if (event->y == 0)
835 {
836 menubar_remove (menubar);
837 menubar_drop (menubar, menubar_get_menu_by_x_coord (menubar, event->x));
838 }
839 else if (mouse_on_drop)
840 menubar_change_selected_item (menubar, event->y);
841
842 was_drag = TRUE;
843 break;
844
845 case MSG_MOUSE_SCROLL_UP:
846 case MSG_MOUSE_SCROLL_DOWN:
847 was_drag = FALSE;
848
849 if (widget_get_state (w, WST_FOCUSED))
850 {
851 if (event->y == 0)
852 {
853
854 if (msg == MSG_MOUSE_SCROLL_UP)
855 menubar_left (menubar);
856 else
857 menubar_right (menubar);
858 }
859 else if (mouse_on_drop)
860 {
861
862 if (msg == MSG_MOUSE_SCROLL_UP)
863 menubar_up (menubar);
864 else
865 menubar_down (menubar);
866 }
867 }
868 break;
869
870 default:
871 was_drag = FALSE;
872 break;
873 }
874 }
875
876
877
878
879
880 menu_entry_t *
881 menu_entry_create (const char *name, long command)
882 {
883 menu_entry_t *entry;
884
885 entry = g_new (menu_entry_t, 1);
886 entry->first_letter = ' ';
887 entry->text = hotkey_new (name);
888 entry->command = command;
889 entry->shortcut = NULL;
890
891 return entry;
892 }
893
894
895
896 void
897 menu_entry_free (menu_entry_t * entry)
898 {
899 if (entry != NULL)
900 {
901 hotkey_free (entry->text);
902 g_free (entry->shortcut);
903 g_free (entry);
904 }
905 }
906
907
908
909 menu_t *
910 create_menu (const char *name, GList * entries, const char *help_node)
911 {
912 menu_t *menu;
913
914 menu = g_new (menu_t, 1);
915 menu->start_x = 0;
916 menu->text = hotkey_new (name);
917 menu->entries = entries;
918 menu->max_entry_len = 1;
919 menu->max_hotkey_len = 0;
920 menu->selected = 0;
921 menu->help_node = g_strdup (help_node);
922
923 return menu;
924 }
925
926
927
928 void
929 menu_set_name (menu_t * menu, const char *name)
930 {
931 hotkey_free (menu->text);
932 menu->text = hotkey_new (name);
933 }
934
935
936
937 void
938 destroy_menu (menu_t * menu)
939 {
940 hotkey_free (menu->text);
941 g_list_free_full (menu->entries, (GDestroyNotify) menu_entry_free);
942 g_free (menu->help_node);
943 g_free (menu);
944 }
945
946
947
948 WMenuBar *
949 menubar_new (GList * menu)
950 {
951 WMenuBar *menubar;
952 Widget *w;
953
954 menubar = g_new0 (WMenuBar, 1);
955 w = WIDGET (menubar);
956 widget_init (w, 0, 0, 1, COLS, menubar_callback, menubar_mouse_callback);
957 w->pos_flags = WPOS_KEEP_HORZ | WPOS_KEEP_TOP;
958
959 widget_set_options (w, WOP_SELECTABLE, FALSE);
960 w->options |= WOP_TOP_SELECT;
961 w->keymap = menu_map;
962 menubar_set_menu (menubar, menu);
963
964 return menubar;
965 }
966
967
968
969 void
970 menubar_set_menu (WMenuBar * menubar, GList * menu)
971 {
972
973 menubar_free_menu (menubar);
974
975 menubar->is_dropped = FALSE;
976 menubar->menu = menu;
977 menubar->selected = 0;
978 menubar_arrange (menubar);
979 widget_set_state (WIDGET (menubar), WST_FOCUSED, FALSE);
980 }
981
982
983
984 void
985 menubar_add_menu (WMenuBar * menubar, menu_t * menu)
986 {
987 if (menu != NULL)
988 {
989 menu_arrange (menu, DIALOG (WIDGET (menubar)->owner)->get_shortcut);
990 menubar->menu = g_list_append (menubar->menu, menu);
991 }
992
993 menubar_arrange (menubar);
994 }
995
996
997
998
999
1000
1001
1002 void
1003 menubar_arrange (WMenuBar * menubar)
1004 {
1005 int start_x = 1;
1006 GList *i;
1007 int gap;
1008
1009 if (menubar->menu == NULL)
1010 return;
1011
1012 gap = WIDGET (menubar)->cols - 2;
1013
1014
1015 for (i = menubar->menu; i != NULL; i = g_list_next (i))
1016 {
1017 menu_t *menu = MENU (i->data);
1018
1019
1020 menu->start_x = hotkey_width (menu->text) + 2;
1021 gap -= menu->start_x;
1022 }
1023
1024 if (g_list_next (menubar->menu) == NULL)
1025 gap = 1;
1026 else
1027 gap /= (g_list_length (menubar->menu) - 1);
1028
1029 if (gap <= 0)
1030 {
1031
1032 gap = 1;
1033 }
1034 else if (gap >= 3)
1035 gap = 3;
1036
1037
1038 for (i = menubar->menu; i != NULL; i = g_list_next (i))
1039 {
1040 menu_t *menu = MENU (i->data);
1041 int len = menu->start_x;
1042
1043 menu->start_x = start_x;
1044 start_x += len + gap;
1045 }
1046 }
1047
1048
1049
1050
1051 WMenuBar *
1052 find_menubar (const WDialog * h)
1053 {
1054 return MENUBAR (widget_find_by_type (CONST_WIDGET (h), menubar_callback));
1055 }
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066 void
1067 menubar_activate (WMenuBar * menubar, gboolean dropped, int which)
1068 {
1069 Widget *w = WIDGET (menubar);
1070
1071 widget_show (w);
1072
1073 if (!widget_get_state (w, WST_FOCUSED))
1074 {
1075 widget_set_options (w, WOP_SELECTABLE, TRUE);
1076
1077 menubar->is_dropped = dropped;
1078 if (which >= 0)
1079 menubar->selected = (guint) which;
1080
1081 menubar->previous_widget = group_get_current_widget_id (w->owner);
1082
1083
1084
1085 widget_select (w);
1086 }
1087 }
1088
1089