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