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_entry
- 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_FRAME_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 CORE_SHADOW_COLOR);
198
199 tty_setcolor (MENU_FRAME_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
732
733
734 static gboolean
735 menubar_mouse_on_menu_entry (const WMenuBar *menubar, int y, int x)
736 {
737 const WRect *w = &CONST_WIDGET (menubar)->rect;
738 menu_t *menu;
739 menu_entry_t *entry;
740 int left_x, right_x, bottom_y;
741
742 if (!menubar->is_dropped)
743 return FALSE;
744
745 menu = MENU (g_list_nth_data (menubar->menu, menubar->current));
746 entry = MENUENTRY (g_list_nth_data (menu->entries, y - 2));
747 if (entry == NULL)
748 return FALSE;
749
750 left_x = menu->start_x;
751 right_x = left_x + menu->max_entry_len + 2;
752 if (right_x > w->cols - 1)
753 {
754 left_x = w->cols - 1 - (menu->max_entry_len + 2);
755 right_x = w->cols - 1;
756 }
757
758 bottom_y = g_list_length (menu->entries) + 2;
759
760 return (x >= left_x && x < right_x && y > 1 && y < bottom_y);
761 }
762
763
764
765 static void
766 menubar_change_selected_item (WMenuBar *menubar, int y)
767 {
768 menu_t *menu;
769 menu_entry_t *entry;
770
771 y -= 2;
772 menu = MENU (g_list_nth_data (menubar->menu, menubar->current));
773 entry = MENUENTRY (g_list_nth_data (menu->entries, y));
774
775 if (entry != NULL && entry->command != CK_IgnoreKey)
776 {
777 menubar_paint_idx (menubar, menu->current, MENU_ENTRY_COLOR);
778 menu->current = y;
779 menubar_paint_idx (menubar, menu->current, MENU_SELECTED_COLOR);
780 }
781 }
782
783
784
785 static void
786 menubar_mouse_callback (Widget *w, mouse_msg_t msg, mouse_event_t *event)
787 {
788 static gboolean was_drag = FALSE;
789
790 WMenuBar *menubar = MENUBAR (w);
791 gboolean mouse_on_drop;
792
793 mouse_on_drop = menubar_mouse_on_menu_entry (menubar, event->y, event->x);
794
795 switch (msg)
796 {
797 case MSG_MOUSE_DOWN:
798 was_drag = FALSE;
799
800 if (event->y == 0)
801 {
802
803 unsigned int selected;
804
805 selected = menubar_get_menu_by_x_coord (menubar, event->x);
806 menubar_activate (menubar, TRUE, selected);
807 menubar_remove (menubar);
808 menubar_drop (menubar, selected);
809 }
810 else if (mouse_on_drop)
811 menubar_change_selected_item (menubar, event->y);
812 else
813 {
814
815 menubar_finish (menubar);
816
817
818
819
820
821
822
823
824
825
826
827
828
829 w->mouse.capture = FALSE;
830 }
831 break;
832
833 case MSG_MOUSE_UP:
834 if (was_drag && mouse_on_drop)
835 menubar_execute (menubar);
836 was_drag = FALSE;
837 break;
838
839 case MSG_MOUSE_CLICK:
840 was_drag = FALSE;
841
842 if ((event->buttons & GPM_B_MIDDLE) != 0 && event->y > 0 && menubar->is_dropped)
843 {
844
845 menubar_execute (menubar);
846 }
847 else if (mouse_on_drop)
848 menubar_execute (menubar);
849 else if (event->y > 0)
850
851 menubar_finish (menubar);
852 break;
853
854 case MSG_MOUSE_DRAG:
855 if (event->y == 0)
856 {
857 menubar_remove (menubar);
858 menubar_drop (menubar, menubar_get_menu_by_x_coord (menubar, event->x));
859 }
860 else if (mouse_on_drop)
861 menubar_change_selected_item (menubar, event->y);
862
863 was_drag = TRUE;
864 break;
865
866 case MSG_MOUSE_SCROLL_UP:
867 case MSG_MOUSE_SCROLL_DOWN:
868 was_drag = FALSE;
869
870 if (widget_get_state (w, WST_FOCUSED))
871 {
872 if (event->y == 0)
873 {
874
875 if (msg == MSG_MOUSE_SCROLL_UP)
876 menubar_left (menubar);
877 else
878 menubar_right (menubar);
879 }
880 else if (mouse_on_drop)
881 {
882
883 if (msg == MSG_MOUSE_SCROLL_UP)
884 menubar_up (menubar);
885 else
886 menubar_down (menubar);
887 }
888 }
889 break;
890
891 default:
892 was_drag = FALSE;
893 break;
894 }
895 }
896
897
898
899
900
901 menu_entry_t *
902 menu_entry_new (const char *name, long command)
903 {
904 menu_entry_t *entry;
905
906 entry = g_new (menu_entry_t, 1);
907 entry->first_letter = ' ';
908 entry->text = hotkey_new (name);
909 entry->command = command;
910 entry->shortcut = NULL;
911
912 return entry;
913 }
914
915
916
917 void
918 menu_entry_free (menu_entry_t *entry)
919 {
920 if (entry != NULL)
921 {
922 hotkey_free (entry->text);
923 g_free (entry->shortcut);
924 g_free (entry);
925 }
926 }
927
928
929
930 menu_t *
931 menu_new (const char *name, GList *entries, const char *help_node)
932 {
933 menu_t *menu;
934
935 menu = g_new (menu_t, 1);
936 menu->start_x = 0;
937 menu->text = hotkey_new (name);
938 menu->entries = entries;
939 menu->max_entry_len = 1;
940 menu->max_hotkey_len = 0;
941 menu->current = 0;
942 menu->help_node = g_strdup (help_node);
943
944 return menu;
945 }
946
947
948
949 void
950 menu_set_name (menu_t *menu, const char *name)
951 {
952 hotkey_free (menu->text);
953 menu->text = hotkey_new (name);
954 }
955
956
957
958 void
959 menu_free (menu_t *menu)
960 {
961 hotkey_free (menu->text);
962 g_list_free_full (menu->entries, (GDestroyNotify) menu_entry_free);
963 g_free (menu->help_node);
964 g_free (menu);
965 }
966
967
968
969 WMenuBar *
970 menubar_new (GList *menu)
971 {
972 WRect r = { 0, 0, 1, COLS };
973 WMenuBar *menubar;
974 Widget *w;
975
976 menubar = g_new0 (WMenuBar, 1);
977 w = WIDGET (menubar);
978 widget_init (w, &r, menubar_callback, menubar_mouse_callback);
979 w->pos_flags = WPOS_KEEP_HORZ | WPOS_KEEP_TOP;
980 w->options |= WOP_TOP_SELECT;
981 w->keymap = menu_map;
982 menubar_set_menu (menubar, menu);
983
984 return menubar;
985 }
986
987
988
989 void
990 menubar_set_menu (WMenuBar *menubar, GList *menu)
991 {
992
993 menubar_free_menu (menubar);
994
995 menubar->is_dropped = FALSE;
996 menubar->menu = menu;
997 menubar->current = 0;
998 menubar_arrange (menubar);
999 widget_set_state (WIDGET (menubar), WST_FOCUSED, FALSE);
1000 }
1001
1002
1003
1004 void
1005 menubar_add_menu (WMenuBar *menubar, menu_t *menu)
1006 {
1007 if (menu != NULL)
1008 {
1009 menu_arrange (menu, DIALOG (WIDGET (menubar)->owner)->get_shortcut);
1010 menubar->menu = g_list_append (menubar->menu, menu);
1011 }
1012
1013 menubar_arrange (menubar);
1014 }
1015
1016
1017
1018
1019
1020
1021
1022 void
1023 menubar_arrange (WMenuBar *menubar)
1024 {
1025 int start_x = 1;
1026 GList *i;
1027 int gap;
1028
1029 if (menubar->menu == NULL)
1030 return;
1031
1032 gap = WIDGET (menubar)->rect.cols - 2;
1033
1034
1035 for (i = menubar->menu; i != NULL; i = g_list_next (i))
1036 {
1037 menu_t *menu = MENU (i->data);
1038
1039
1040 menu->start_x = hotkey_width (menu->text) + 2;
1041 gap -= menu->start_x;
1042 }
1043
1044 if (g_list_next (menubar->menu) == NULL)
1045 gap = 1;
1046 else
1047 gap /= (g_list_length (menubar->menu) - 1);
1048
1049 if (gap <= 0)
1050 {
1051
1052 gap = 1;
1053 }
1054 else if (gap >= 3)
1055 gap = 3;
1056
1057
1058 for (i = menubar->menu; i != NULL; i = g_list_next (i))
1059 {
1060 menu_t *menu = MENU (i->data);
1061 int len = menu->start_x;
1062
1063 menu->start_x = start_x;
1064 start_x += len + gap;
1065 }
1066 }
1067
1068
1069
1070
1071 WMenuBar *
1072 menubar_find (const WDialog *h)
1073 {
1074 return MENUBAR (widget_find_by_type (CONST_WIDGET (h), menubar_callback));
1075 }
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086 void
1087 menubar_activate (WMenuBar *menubar, gboolean dropped, int which)
1088 {
1089 Widget *w = WIDGET (menubar);
1090
1091 widget_show (w);
1092
1093 if (!widget_get_state (w, WST_FOCUSED))
1094 {
1095 widget_set_options (w, WOP_SELECTABLE, TRUE);
1096
1097 menubar->is_dropped = dropped;
1098 if (which >= 0)
1099 menubar->current = (guint) which;
1100
1101 menubar->previous_widget = group_get_current_widget_id (w->owner);
1102
1103
1104
1105 widget_select (w);
1106 }
1107 }
1108
1109