2011-10-15 14:56:47 +04:00
|
|
|
/*
|
|
|
|
Pulldown menu code
|
2009-05-04 20:11:51 +04:00
|
|
|
|
2024-01-01 09:46:17 +03:00
|
|
|
Copyright (C) 1994-2024
|
2014-02-12 10:33:10 +04:00
|
|
|
Free Software Foundation, Inc.
|
2009-05-04 20:11:51 +04:00
|
|
|
|
2012-06-12 17:44:39 +04:00
|
|
|
Written by:
|
2022-05-01 10:43:33 +03:00
|
|
|
Andrew Borodin <aborodin@vmail.ru>, 2012-2022
|
2012-06-12 17:44:39 +04:00
|
|
|
|
2011-10-15 14:56:47 +04:00
|
|
|
This file is part of the Midnight Commander.
|
|
|
|
|
|
|
|
The Midnight Commander is free software: you can redistribute it
|
|
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
|
|
published by the Free Software Foundation, either version 3 of the License,
|
|
|
|
or (at your option) any later version.
|
|
|
|
|
|
|
|
The Midnight Commander is distributed in the hope that it will be useful,
|
1998-02-27 07:54:42 +03:00
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
2011-10-15 14:56:47 +04:00
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2009-02-05 21:28:18 +03:00
|
|
|
/** \file menu.c
|
|
|
|
* \brief Source: pulldown menu code
|
|
|
|
*/
|
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
#include <config.h>
|
2005-02-08 12:04:03 +03:00
|
|
|
|
|
|
|
#include <ctype.h>
|
1998-02-27 07:54:42 +03:00
|
|
|
#include <stdarg.h>
|
2005-02-08 12:04:03 +03:00
|
|
|
#include <string.h>
|
1998-02-27 07:54:42 +03:00
|
|
|
#include <sys/types.h>
|
2005-02-08 12:04:03 +03:00
|
|
|
|
2010-01-20 18:11:52 +03:00
|
|
|
#include "lib/global.h"
|
2009-05-09 19:17:57 +04:00
|
|
|
|
2010-01-08 17:47:19 +03:00
|
|
|
#include "lib/tty/tty.h"
|
2010-01-21 16:06:15 +03:00
|
|
|
#include "lib/skin.h"
|
2010-04-06 11:16:11 +04:00
|
|
|
#include "lib/tty/key.h" /* key macros */
|
2010-01-21 15:17:26 +03:00
|
|
|
#include "lib/strutil.h"
|
2010-11-12 11:03:57 +03:00
|
|
|
#include "lib/widget.h"
|
2011-02-17 15:02:31 +03:00
|
|
|
#include "lib/event.h" /* mc_event_raise() */
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/*** global variables ****************************************************************************/
|
|
|
|
|
2019-11-23 17:41:58 +03:00
|
|
|
const global_keymap_t *menu_map = NULL;
|
2011-07-17 00:07:07 +04:00
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/*** file scope macro definitions ****************************************************************/
|
2009-11-01 12:23:15 +03:00
|
|
|
|
2012-10-11 12:41:29 +04:00
|
|
|
#define MENUENTRY(x) ((menu_entry_t *)(x))
|
|
|
|
#define MENU(x) ((menu_t *)(x))
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/*** file scope type declarations ****************************************************************/
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2012-10-11 12:41:29 +04:00
|
|
|
struct menu_entry_t
|
|
|
|
{
|
|
|
|
unsigned char first_letter;
|
|
|
|
hotkey_t text;
|
2015-11-21 18:15:11 +03:00
|
|
|
long command;
|
2012-10-11 12:41:29 +04:00
|
|
|
char *shortcut;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct menu_t
|
|
|
|
{
|
|
|
|
int start_x; /* position relative to menubar start */
|
|
|
|
hotkey_t text;
|
|
|
|
GList *entries;
|
|
|
|
size_t max_entry_len; /* cached max length of entry texts (text + shortcut) */
|
|
|
|
size_t max_hotkey_len; /* cached max length of shortcuts */
|
2023-04-15 15:01:49 +03:00
|
|
|
unsigned int current; /* pointer to current menu entry */
|
2012-10-11 12:41:29 +04:00
|
|
|
char *help_node;
|
|
|
|
};
|
|
|
|
|
Update template for .c files.
Add section for forward declarations of local functions. This section is
located before file scope variables because functions can be used in
strucutres (see find.c for example):
/*** forward declarations (file scope functions) *************************************************/
/* button callbacks */
static int start_stop (WButton * button, int action);
static int find_do_view_file (WButton * button, int action);
static int find_do_edit_file (WButton * button, int action);
/*** file scope variables ************************************************************************/
static struct
{
...
bcback_fn callback;
} fbuts[] =
{
...
{ B_STOP, NORMAL_BUTTON, N_("S&uspend"), 0, 0, NULL, start_stop },
...
{ B_VIEW, NORMAL_BUTTON, N_("&View - F3"), 0, 0, NULL, find_do_view_file },
{ B_VIEW, NORMAL_BUTTON, N_("&Edit - F4"), 0, 0, NULL, find_do_edit_file }
};
Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
2023-02-24 09:27:11 +03:00
|
|
|
/*** forward declarations (file scope functions) *************************************************/
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/*** file scope variables ************************************************************************/
|
2009-05-04 20:11:51 +04:00
|
|
|
|
Update template for .c files.
Add section for forward declarations of local functions. This section is
located before file scope variables because functions can be used in
strucutres (see find.c for example):
/*** forward declarations (file scope functions) *************************************************/
/* button callbacks */
static int start_stop (WButton * button, int action);
static int find_do_view_file (WButton * button, int action);
static int find_do_edit_file (WButton * button, int action);
/*** file scope variables ************************************************************************/
static struct
{
...
bcback_fn callback;
} fbuts[] =
{
...
{ B_STOP, NORMAL_BUTTON, N_("S&uspend"), 0, 0, NULL, start_stop },
...
{ B_VIEW, NORMAL_BUTTON, N_("&View - F3"), 0, 0, NULL, find_do_view_file },
{ B_VIEW, NORMAL_BUTTON, N_("&Edit - F4"), 0, 0, NULL, find_do_edit_file }
};
Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
2023-02-24 09:27:11 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2010-11-10 14:09:42 +03:00
|
|
|
/*** file scope functions ************************************************************************/
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2009-05-04 20:11:51 +04:00
|
|
|
|
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menu_arrange (menu_t *menu, dlg_shortcut_str get_shortcut)
|
2009-05-04 20:11:51 +04:00
|
|
|
{
|
2010-04-06 11:16:11 +04:00
|
|
|
if (menu != NULL)
|
|
|
|
{
|
|
|
|
GList *i;
|
|
|
|
size_t max_shortcut_len = 0;
|
2009-10-24 12:58:02 +04:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
menu->max_entry_len = 1;
|
|
|
|
menu->max_hotkey_len = 1;
|
2009-05-04 20:11:51 +04:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
for (i = menu->entries; i != NULL; i = g_list_next (i))
|
|
|
|
{
|
2012-10-11 12:41:29 +04:00
|
|
|
menu_entry_t *entry = MENUENTRY (i->data);
|
2009-05-04 20:11:51 +04:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
if (entry != NULL)
|
|
|
|
{
|
|
|
|
size_t len;
|
2009-10-24 12:58:02 +04:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
len = (size_t) hotkey_width (entry->text);
|
2016-04-07 10:52:04 +03:00
|
|
|
menu->max_hotkey_len = MAX (menu->max_hotkey_len, len);
|
2009-10-24 12:58:02 +04:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
if (get_shortcut != NULL)
|
|
|
|
entry->shortcut = get_shortcut (entry->command);
|
2009-10-24 12:58:02 +04:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
if (entry->shortcut != NULL)
|
|
|
|
{
|
|
|
|
len = (size_t) str_term_width1 (entry->shortcut);
|
2016-04-07 10:52:04 +03:00
|
|
|
max_shortcut_len = MAX (max_shortcut_len, len);
|
2010-04-06 11:16:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-10-24 12:58:02 +04:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
menu->max_entry_len = menu->max_hotkey_len + max_shortcut_len;
|
1999-08-01 15:37:25 +04:00
|
|
|
}
|
2009-05-04 20:11:51 +04:00
|
|
|
}
|
1998-03-31 00:59:37 +04:00
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2009-05-04 20:11:51 +04:00
|
|
|
|
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_paint_idx (const WMenuBar *menubar, unsigned int idx, int color)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2022-05-01 10:43:33 +03:00
|
|
|
const WRect *w = &CONST_WIDGET (menubar)->rect;
|
2023-04-15 15:01:49 +03:00
|
|
|
const menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->current));
|
2012-10-11 12:41:29 +04:00
|
|
|
const menu_entry_t *entry = MENUENTRY (g_list_nth_data (menu->entries, idx));
|
1998-02-27 07:54:42 +03:00
|
|
|
const int y = 2 + idx;
|
2008-12-29 01:57:59 +03:00
|
|
|
int x = menu->start_x;
|
1998-03-31 00:59:37 +04:00
|
|
|
|
2012-06-20 15:09:44 +04:00
|
|
|
if (x + menu->max_entry_len + 4 > (gsize) w->cols)
|
|
|
|
x = w->cols - menu->max_entry_len - 4;
|
2010-04-06 11:16:11 +04:00
|
|
|
|
|
|
|
if (entry == NULL)
|
|
|
|
{
|
|
|
|
/* menu separator */
|
|
|
|
tty_setcolor (MENU_ENTRY_COLOR);
|
|
|
|
|
2022-05-01 10:43:33 +03:00
|
|
|
widget_gotoyx (menubar, y, x - 1);
|
2010-04-06 11:16:11 +04:00
|
|
|
tty_print_alt_char (ACS_LTEE, FALSE);
|
2012-06-20 15:09:44 +04:00
|
|
|
tty_draw_hline (w->y + y, w->x + x, ACS_HLINE, menu->max_entry_len + 3);
|
2022-05-01 10:43:33 +03:00
|
|
|
widget_gotoyx (menubar, y, x + menu->max_entry_len + 3);
|
2010-04-06 11:16:11 +04:00
|
|
|
tty_print_alt_char (ACS_RTEE, FALSE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-01-14 20:52:40 +03:00
|
|
|
int yt, xt;
|
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
/* menu text */
|
|
|
|
tty_setcolor (color);
|
2022-05-01 10:43:33 +03:00
|
|
|
widget_gotoyx (menubar, y, x);
|
2010-04-06 11:16:11 +04:00
|
|
|
tty_print_char ((unsigned char) entry->first_letter);
|
2011-01-14 20:52:40 +03:00
|
|
|
tty_getyx (&yt, &xt);
|
|
|
|
tty_draw_hline (yt, xt, ' ', menu->max_entry_len + 2); /* clear line */
|
2010-04-06 11:16:11 +04:00
|
|
|
tty_print_string (entry->text.start);
|
|
|
|
|
|
|
|
if (entry->text.hotkey != NULL)
|
|
|
|
{
|
|
|
|
tty_setcolor (color == MENU_SELECTED_COLOR ? MENU_HOTSEL_COLOR : MENU_HOT_COLOR);
|
|
|
|
tty_print_string (entry->text.hotkey);
|
|
|
|
tty_setcolor (color);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (entry->text.end != NULL)
|
|
|
|
tty_print_string (entry->text.end);
|
|
|
|
|
|
|
|
if (entry->shortcut != NULL)
|
|
|
|
{
|
2022-05-01 10:43:33 +03:00
|
|
|
widget_gotoyx (menubar, y, x + menu->max_hotkey_len + 3);
|
2010-04-06 11:16:11 +04:00
|
|
|
tty_print_string (entry->shortcut);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* move cursor to the start of entry text */
|
2022-05-01 10:43:33 +03:00
|
|
|
widget_gotoyx (menubar, y, x + 1);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_draw_drop (const WMenuBar *menubar)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2022-05-01 10:43:33 +03:00
|
|
|
const WRect *w = &CONST_WIDGET (menubar)->rect;
|
2023-04-15 15:01:49 +03:00
|
|
|
const menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->current));
|
2009-08-25 13:08:18 +04:00
|
|
|
const unsigned int count = g_list_length (menu->entries);
|
2009-05-04 20:11:51 +04:00
|
|
|
int column = menu->start_x - 1;
|
|
|
|
unsigned int i;
|
1998-03-31 00:59:37 +04:00
|
|
|
|
2012-06-20 15:09:44 +04:00
|
|
|
if (column + menu->max_entry_len + 5 > (gsize) w->cols)
|
|
|
|
column = w->cols - menu->max_entry_len - 5;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2020-07-19 19:47:15 +03:00
|
|
|
if (mc_global.tty.shadows)
|
|
|
|
tty_draw_box_shadow (w->y + 1, w->x + column, count + 2, menu->max_entry_len + 5,
|
|
|
|
SHADOW_COLOR);
|
|
|
|
|
2009-08-26 13:19:44 +04:00
|
|
|
tty_setcolor (MENU_ENTRY_COLOR);
|
2013-04-23 14:10:20 +04:00
|
|
|
tty_draw_box (w->y + 1, w->x + column, count + 2, menu->max_entry_len + 5, FALSE);
|
2009-04-26 18:22:53 +04:00
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
2023-07-16 18:03:15 +03:00
|
|
|
menubar_paint_idx (menubar, i, i == menu->current ? MENU_SELECTED_COLOR : MENU_ENTRY_COLOR);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_set_color (const WMenuBar *menubar, gboolean current, gboolean hotkey)
|
2009-08-26 13:19:44 +04:00
|
|
|
{
|
2019-11-09 14:37:00 +03:00
|
|
|
if (!widget_get_state (CONST_WIDGET (menubar), WST_FOCUSED))
|
2010-04-06 11:16:11 +04:00
|
|
|
tty_setcolor (MENU_INACTIVE_COLOR);
|
2010-02-23 14:13:23 +03:00
|
|
|
else if (current)
|
2010-04-06 11:16:11 +04:00
|
|
|
tty_setcolor (hotkey ? MENU_HOTSEL_COLOR : MENU_SELECTED_COLOR);
|
2010-02-23 14:13:23 +03:00
|
|
|
else
|
2010-04-06 11:16:11 +04:00
|
|
|
tty_setcolor (hotkey ? MENU_HOT_COLOR : MENU_ENTRY_COLOR);
|
2009-08-26 13:19:44 +04:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_draw (const WMenuBar *menubar)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2022-05-01 10:43:33 +03:00
|
|
|
const WRect *w = &CONST_WIDGET (menubar)->rect;
|
2009-08-25 13:08:18 +04:00
|
|
|
GList *i;
|
2009-04-26 18:22:53 +04:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
/* First draw the complete menubar */
|
2022-05-01 10:43:33 +03:00
|
|
|
tty_setcolor (widget_get_state (WIDGET (menubar), WST_FOCUSED) ? MENU_ENTRY_COLOR :
|
|
|
|
MENU_INACTIVE_COLOR);
|
2012-06-20 15:09:44 +04:00
|
|
|
tty_draw_hline (w->y, w->x, ' ', w->cols);
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
/* Now each one of the entries */
|
2010-04-06 11:16:11 +04:00
|
|
|
for (i = menubar->menu; i != NULL; i = g_list_next (i))
|
|
|
|
{
|
2012-10-11 12:41:29 +04:00
|
|
|
menu_t *menu = MENU (i->data);
|
2023-04-15 15:01:49 +03:00
|
|
|
gboolean is_selected = (menubar->current == (gsize) g_list_position (menubar->menu, i));
|
2009-05-04 20:11:51 +04:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
menubar_set_color (menubar, is_selected, FALSE);
|
2022-05-01 10:43:33 +03:00
|
|
|
widget_gotoyx (menubar, 0, menu->start_x);
|
2009-04-26 18:22:53 +04:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
tty_print_char (' ');
|
|
|
|
tty_print_string (menu->text.start);
|
2009-04-26 18:22:53 +04:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
if (menu->text.hotkey != NULL)
|
|
|
|
{
|
|
|
|
menubar_set_color (menubar, is_selected, TRUE);
|
|
|
|
tty_print_string (menu->text.hotkey);
|
|
|
|
menubar_set_color (menubar, is_selected, FALSE);
|
|
|
|
}
|
2009-05-04 20:11:51 +04:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
if (menu->text.end != NULL)
|
|
|
|
tty_print_string (menu->text.end);
|
2009-10-24 12:58:02 +04:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
tty_print_char (' ');
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
if (menubar->is_dropped)
|
2010-04-06 11:16:11 +04:00
|
|
|
menubar_draw_drop (menubar);
|
2009-04-26 18:22:53 +04:00
|
|
|
else
|
2022-05-01 10:43:33 +03:00
|
|
|
widget_gotoyx (menubar, 0,
|
2023-04-15 15:01:49 +03:00
|
|
|
MENU (g_list_nth_data (menubar->menu, menubar->current))->start_x);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_remove (WMenuBar *menubar)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2016-09-29 11:16:17 +03:00
|
|
|
Widget *g;
|
2011-08-07 18:37:18 +04:00
|
|
|
|
|
|
|
if (!menubar->is_dropped)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* HACK: before refresh the dialog, change the current widget to keep the order
|
|
|
|
of overlapped widgets. This is useful in multi-window editor.
|
|
|
|
In general, menubar should be a special object, not an ordinary widget
|
|
|
|
in the current dialog. */
|
2016-09-29 11:16:17 +03:00
|
|
|
g = WIDGET (WIDGET (menubar)->owner);
|
|
|
|
GROUP (g)->current = widget_find (g, widget_find_by_id (g, menubar->previous_widget));
|
2011-08-07 18:37:18 +04:00
|
|
|
|
|
|
|
menubar->is_dropped = FALSE;
|
|
|
|
do_refresh ();
|
|
|
|
menubar->is_dropped = TRUE;
|
|
|
|
|
|
|
|
/* restore current widget */
|
2016-09-29 11:16:17 +03:00
|
|
|
GROUP (g)->current = widget_find (g, WIDGET (menubar));
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_left (WMenuBar *menubar)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2009-05-04 20:11:51 +04:00
|
|
|
menubar_remove (menubar);
|
2023-04-15 15:01:49 +03:00
|
|
|
if (menubar->current == 0)
|
|
|
|
menubar->current = g_list_length (menubar->menu) - 1;
|
2009-05-04 20:11:51 +04:00
|
|
|
else
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar->current--;
|
2009-05-04 20:11:51 +04:00
|
|
|
menubar_draw (menubar);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_right (WMenuBar *menubar)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2009-05-04 20:11:51 +04:00
|
|
|
menubar_remove (menubar);
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar->current = (menubar->current + 1) % g_list_length (menubar->menu);
|
2009-05-04 20:11:51 +04:00
|
|
|
menubar_draw (menubar);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2003-09-13 02:45:51 +04:00
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_finish (WMenuBar *menubar)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2012-06-20 15:09:44 +04:00
|
|
|
Widget *w = WIDGET (menubar);
|
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
menubar->is_dropped = FALSE;
|
2022-05-01 10:43:33 +03:00
|
|
|
w->rect.lines = 1;
|
2016-05-08 19:54:04 +03:00
|
|
|
widget_want_hotkey (w, FALSE);
|
2016-06-07 16:38:20 +03:00
|
|
|
widget_set_options (w, WOP_SELECTABLE, FALSE);
|
2003-09-13 11:43:20 +04:00
|
|
|
|
2019-08-11 19:14:49 +03:00
|
|
|
if (!mc_global.keybar_visible)
|
|
|
|
widget_hide (w);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Move the menubar to the bottom so that widgets displayed on top of
|
|
|
|
* an "invisible" menubar get the first chance to respond to mouse events. */
|
|
|
|
widget_set_bottom (w);
|
|
|
|
}
|
|
|
|
|
2016-10-16 19:45:50 +03:00
|
|
|
/* background must be bottom */
|
|
|
|
if (DIALOG (w->owner)->bg != NULL)
|
|
|
|
widget_set_bottom (WIDGET (DIALOG (w->owner)->bg));
|
2016-02-23 09:49:58 +03:00
|
|
|
|
2016-09-27 16:16:38 +03:00
|
|
|
group_select_widget_by_id (w->owner, menubar->previous_widget);
|
1998-02-27 07:54:42 +03:00
|
|
|
do_refresh ();
|
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_drop (WMenuBar *menubar, unsigned int selected)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2009-05-04 20:11:51 +04:00
|
|
|
menubar->is_dropped = TRUE;
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar->current = selected;
|
1998-02-27 07:54:42 +03:00
|
|
|
menubar_draw (menubar);
|
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_execute (WMenuBar *menubar)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2023-04-15 15:01:49 +03:00
|
|
|
const menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->current));
|
|
|
|
const menu_entry_t *entry = MENUENTRY (g_list_nth_data (menu->entries, menu->current));
|
2009-05-04 20:11:51 +04:00
|
|
|
|
2011-02-20 18:23:32 +03:00
|
|
|
if ((entry != NULL) && (entry->command != CK_IgnoreKey))
|
2010-04-06 11:16:11 +04:00
|
|
|
{
|
2012-06-20 15:09:44 +04:00
|
|
|
Widget *w = WIDGET (menubar);
|
|
|
|
|
2023-04-15 15:01:49 +03:00
|
|
|
mc_global.widget.is_right = (menubar->current != 0);
|
2010-04-06 11:16:11 +04:00
|
|
|
menubar_finish (menubar);
|
2012-09-28 15:05:43 +04:00
|
|
|
send_message (w->owner, w, MSG_ACTION, entry->command, NULL);
|
2010-04-06 11:16:11 +04:00
|
|
|
do_refresh ();
|
2009-10-01 22:23:50 +04:00
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_down (WMenuBar *menubar)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2023-04-15 15:01:49 +03:00
|
|
|
menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->current));
|
2009-08-25 13:08:18 +04:00
|
|
|
const unsigned int len = g_list_length (menu->entries);
|
2009-05-04 20:11:51 +04:00
|
|
|
menu_entry_t *entry;
|
|
|
|
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar_paint_idx (menubar, menu->current, MENU_ENTRY_COLOR);
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
do
|
|
|
|
{
|
2023-04-15 15:01:49 +03:00
|
|
|
menu->current = (menu->current + 1) % len;
|
|
|
|
entry = MENUENTRY (g_list_nth_data (menu->entries, menu->current));
|
2010-04-06 11:16:11 +04:00
|
|
|
}
|
2011-02-20 18:23:32 +03:00
|
|
|
while ((entry == NULL) || (entry->command == CK_IgnoreKey));
|
2009-05-04 20:11:51 +04:00
|
|
|
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar_paint_idx (menubar, menu->current, MENU_SELECTED_COLOR);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_up (WMenuBar *menubar)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2023-04-15 15:01:49 +03:00
|
|
|
menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->current));
|
2009-08-25 13:08:18 +04:00
|
|
|
const unsigned int len = g_list_length (menu->entries);
|
2009-05-04 20:11:51 +04:00
|
|
|
menu_entry_t *entry;
|
|
|
|
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar_paint_idx (menubar, menu->current, MENU_ENTRY_COLOR);
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
do
|
|
|
|
{
|
2023-04-15 15:01:49 +03:00
|
|
|
if (menu->current == 0)
|
|
|
|
menu->current = len - 1;
|
2010-04-06 11:16:11 +04:00
|
|
|
else
|
2023-04-15 15:01:49 +03:00
|
|
|
menu->current--;
|
|
|
|
entry = MENUENTRY (g_list_nth_data (menu->entries, menu->current));
|
2010-04-06 11:16:11 +04:00
|
|
|
}
|
2011-02-20 18:23:32 +03:00
|
|
|
while ((entry == NULL) || (entry->command == CK_IgnoreKey));
|
2009-05-04 20:11:51 +04:00
|
|
|
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar_paint_idx (menubar, menu->current, MENU_SELECTED_COLOR);
|
2009-05-04 20:11:51 +04:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-07-19 13:21:03 +04:00
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_first (WMenuBar *menubar)
|
2009-07-19 13:21:03 +04:00
|
|
|
{
|
2019-05-30 11:22:38 +03:00
|
|
|
if (menubar->is_dropped)
|
|
|
|
{
|
2023-04-15 15:01:49 +03:00
|
|
|
menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->current));
|
2009-07-19 13:21:03 +04:00
|
|
|
|
2023-04-15 15:01:49 +03:00
|
|
|
if (menu->current == 0)
|
2019-05-30 11:22:38 +03:00
|
|
|
return;
|
2009-07-19 13:21:03 +04:00
|
|
|
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar_paint_idx (menubar, menu->current, MENU_ENTRY_COLOR);
|
2009-07-19 13:21:03 +04:00
|
|
|
|
2023-04-15 15:01:49 +03:00
|
|
|
menu->current = 0;
|
2009-07-19 13:21:03 +04:00
|
|
|
|
2019-05-30 11:22:38 +03:00
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
menu_entry_t *entry;
|
2013-10-15 10:34:04 +04:00
|
|
|
|
2023-04-15 15:01:49 +03:00
|
|
|
entry = MENUENTRY (g_list_nth_data (menu->entries, menu->current));
|
2009-07-19 13:21:03 +04:00
|
|
|
|
2019-05-30 11:22:38 +03:00
|
|
|
if ((entry == NULL) || (entry->command == CK_IgnoreKey))
|
2023-04-15 15:01:49 +03:00
|
|
|
menu->current++;
|
2019-05-30 11:22:38 +03:00
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
2009-07-19 13:21:03 +04:00
|
|
|
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar_paint_idx (menubar, menu->current, MENU_SELECTED_COLOR);
|
2019-05-30 11:22:38 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar->current = 0;
|
2019-05-30 11:22:38 +03:00
|
|
|
menubar_draw (menubar);
|
|
|
|
}
|
2009-07-19 13:21:03 +04:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-07-19 13:21:03 +04:00
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_last (WMenuBar *menubar)
|
2009-07-19 13:21:03 +04:00
|
|
|
{
|
2019-05-30 11:22:38 +03:00
|
|
|
if (menubar->is_dropped)
|
|
|
|
{
|
2023-04-15 15:01:49 +03:00
|
|
|
menu_t *menu = MENU (g_list_nth_data (menubar->menu, menubar->current));
|
2019-05-30 11:22:38 +03:00
|
|
|
const unsigned int len = g_list_length (menu->entries);
|
|
|
|
menu_entry_t *entry;
|
2009-07-19 13:21:03 +04:00
|
|
|
|
2023-04-15 15:01:49 +03:00
|
|
|
if (menu->current == len - 1)
|
2019-05-30 11:22:38 +03:00
|
|
|
return;
|
2009-07-19 13:21:03 +04:00
|
|
|
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar_paint_idx (menubar, menu->current, MENU_ENTRY_COLOR);
|
2009-07-19 13:21:03 +04:00
|
|
|
|
2023-04-15 15:01:49 +03:00
|
|
|
menu->current = len;
|
2009-07-19 13:21:03 +04:00
|
|
|
|
2019-05-30 11:22:38 +03:00
|
|
|
do
|
|
|
|
{
|
2023-04-15 15:01:49 +03:00
|
|
|
menu->current--;
|
|
|
|
entry = MENUENTRY (g_list_nth_data (menu->entries, menu->current));
|
2019-05-30 11:22:38 +03:00
|
|
|
}
|
|
|
|
while ((entry == NULL) || (entry->command == CK_IgnoreKey));
|
|
|
|
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar_paint_idx (menubar, menu->current, MENU_SELECTED_COLOR);
|
2019-05-30 11:22:38 +03:00
|
|
|
}
|
|
|
|
else
|
2010-04-06 11:16:11 +04:00
|
|
|
{
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar->current = g_list_length (menubar->menu) - 1;
|
2019-05-30 11:22:38 +03:00
|
|
|
menubar_draw (menubar);
|
2010-04-06 11:16:11 +04:00
|
|
|
}
|
2009-07-19 13:21:03 +04:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2011-07-17 00:07:07 +04:00
|
|
|
static cb_ret_t
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_try_drop_menu (WMenuBar *menubar, int hotkey)
|
2011-07-17 00:07:07 +04:00
|
|
|
{
|
|
|
|
GList *i;
|
|
|
|
|
|
|
|
for (i = menubar->menu; i != NULL; i = g_list_next (i))
|
|
|
|
{
|
|
|
|
menu_t *menu = MENU (i->data);
|
|
|
|
|
|
|
|
if (menu->text.hotkey != NULL && hotkey == g_ascii_tolower (menu->text.hotkey[0]))
|
|
|
|
{
|
|
|
|
menubar_drop (menubar, g_list_position (menubar->menu, i));
|
|
|
|
return MSG_HANDLED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return MSG_NOT_HANDLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static cb_ret_t
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_try_exec_menu (WMenuBar *menubar, int hotkey)
|
2011-07-17 00:07:07 +04:00
|
|
|
{
|
|
|
|
menu_t *menu;
|
|
|
|
GList *i;
|
|
|
|
|
2023-04-15 15:01:49 +03:00
|
|
|
menu = g_list_nth_data (menubar->menu, menubar->current);
|
2011-07-17 00:07:07 +04:00
|
|
|
|
|
|
|
for (i = menu->entries; i != NULL; i = g_list_next (i))
|
|
|
|
{
|
|
|
|
const menu_entry_t *entry = MENUENTRY (i->data);
|
|
|
|
|
|
|
|
if (entry != NULL && entry->text.hotkey != NULL
|
|
|
|
&& hotkey == g_ascii_tolower (entry->text.hotkey[0]))
|
|
|
|
{
|
2023-04-15 15:01:49 +03:00
|
|
|
menu->current = g_list_position (menu->entries, i);
|
2011-07-17 00:07:07 +04:00
|
|
|
menubar_execute (menubar);
|
|
|
|
return MSG_HANDLED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return MSG_NOT_HANDLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2023-12-09 17:29:12 +03:00
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_help (const WMenuBar *menubar)
|
2023-12-09 17:29:12 +03:00
|
|
|
{
|
|
|
|
ev_help_t event_data;
|
|
|
|
|
|
|
|
event_data.filename = NULL;
|
|
|
|
|
|
|
|
if (menubar->is_dropped)
|
|
|
|
event_data.node = MENU (g_list_nth_data (menubar->menu, menubar->current))->help_node;
|
|
|
|
else
|
|
|
|
event_data.node = "[Menu Bar]";
|
|
|
|
|
|
|
|
mc_event_raise (MCEVENT_GROUP_CORE, "help", &event_data);
|
|
|
|
menubar_draw (menubar);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2011-07-17 00:07:07 +04:00
|
|
|
static cb_ret_t
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_execute_cmd (WMenuBar *menubar, long command)
|
2009-05-04 20:11:51 +04:00
|
|
|
{
|
2011-07-17 00:07:07 +04:00
|
|
|
cb_ret_t ret = MSG_HANDLED;
|
2009-05-04 20:11:51 +04:00
|
|
|
|
2011-07-17 00:07:07 +04:00
|
|
|
switch (command)
|
2010-04-06 11:16:11 +04:00
|
|
|
{
|
2011-07-17 00:07:07 +04:00
|
|
|
case CK_Help:
|
2023-12-09 17:29:12 +03:00
|
|
|
menubar_help (menubar);
|
2011-07-17 00:07:07 +04:00
|
|
|
break;
|
2015-04-19 13:57:38 +03:00
|
|
|
|
2011-07-17 00:07:07 +04:00
|
|
|
case CK_Left:
|
2010-04-06 11:16:11 +04:00
|
|
|
menubar_left (menubar);
|
2011-07-17 00:07:07 +04:00
|
|
|
break;
|
|
|
|
case CK_Right:
|
2010-04-06 11:16:11 +04:00
|
|
|
menubar_right (menubar);
|
2015-04-19 13:57:38 +03:00
|
|
|
break;
|
2011-07-17 00:07:07 +04:00
|
|
|
case CK_Up:
|
|
|
|
if (menubar->is_dropped)
|
|
|
|
menubar_up (menubar);
|
|
|
|
break;
|
|
|
|
case CK_Down:
|
|
|
|
if (menubar->is_dropped)
|
|
|
|
menubar_down (menubar);
|
|
|
|
else
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar_drop (menubar, menubar->current);
|
2011-07-17 00:07:07 +04:00
|
|
|
break;
|
|
|
|
case CK_Home:
|
2019-05-30 11:22:38 +03:00
|
|
|
menubar_first (menubar);
|
2011-07-17 00:07:07 +04:00
|
|
|
break;
|
|
|
|
case CK_End:
|
2019-05-30 11:22:38 +03:00
|
|
|
menubar_last (menubar);
|
2011-07-17 00:07:07 +04:00
|
|
|
break;
|
2009-05-04 20:11:51 +04:00
|
|
|
|
2011-07-17 00:07:07 +04:00
|
|
|
case CK_Enter:
|
|
|
|
if (menubar->is_dropped)
|
2010-04-06 11:16:11 +04:00
|
|
|
menubar_execute (menubar);
|
2011-07-17 00:07:07 +04:00
|
|
|
else
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar_drop (menubar, menubar->current);
|
2011-07-17 00:07:07 +04:00
|
|
|
break;
|
|
|
|
case CK_Quit:
|
|
|
|
menubar_finish (menubar);
|
|
|
|
break;
|
2010-04-06 11:16:11 +04:00
|
|
|
|
2011-07-17 00:07:07 +04:00
|
|
|
default:
|
2019-06-18 09:34:00 +03:00
|
|
|
ret = MSG_NOT_HANDLED;
|
2011-07-17 00:07:07 +04:00
|
|
|
break;
|
|
|
|
}
|
2010-04-06 11:16:11 +04:00
|
|
|
|
2011-07-17 00:07:07 +04:00
|
|
|
return ret;
|
|
|
|
}
|
2010-04-06 11:16:11 +04:00
|
|
|
|
2011-07-17 00:07:07 +04:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2010-04-06 11:16:11 +04:00
|
|
|
|
2011-07-17 00:07:07 +04:00
|
|
|
static int
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_handle_key (WMenuBar *menubar, int key)
|
2011-07-17 00:07:07 +04:00
|
|
|
{
|
2020-03-14 13:04:31 +03:00
|
|
|
long cmd;
|
2019-06-18 09:34:00 +03:00
|
|
|
cb_ret_t ret = MSG_NOT_HANDLED;
|
2015-04-19 13:57:38 +03:00
|
|
|
|
2017-03-08 14:41:35 +03:00
|
|
|
cmd = widget_lookup_key (WIDGET (menubar), key);
|
2009-05-04 20:11:51 +04:00
|
|
|
|
2019-06-18 09:34:00 +03:00
|
|
|
if (cmd != CK_IgnoreKey)
|
|
|
|
ret = menubar_execute_cmd (menubar, cmd);
|
|
|
|
|
|
|
|
if (ret != MSG_HANDLED)
|
|
|
|
{
|
|
|
|
if (menubar->is_dropped)
|
|
|
|
ret = menubar_try_exec_menu (menubar, key);
|
|
|
|
else
|
|
|
|
ret = menubar_try_drop_menu (menubar, key);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2016-06-13 11:30:57 +03:00
|
|
|
static gboolean
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_refresh (WMenuBar *menubar)
|
2016-06-11 17:01:13 +03:00
|
|
|
{
|
|
|
|
Widget *w = WIDGET (menubar);
|
|
|
|
|
2016-06-22 14:30:49 +03:00
|
|
|
if (!widget_get_state (w, WST_FOCUSED))
|
2016-06-13 11:30:57 +03:00
|
|
|
return FALSE;
|
2016-06-11 17:01:13 +03:00
|
|
|
|
|
|
|
/* Trick to get all the mouse events */
|
2022-05-01 10:43:33 +03:00
|
|
|
w->rect.lines = LINES;
|
2016-06-11 17:01:13 +03:00
|
|
|
|
|
|
|
/* Trick to get all of the hotkeys */
|
|
|
|
widget_want_hotkey (w, TRUE);
|
2016-06-13 11:30:57 +03:00
|
|
|
return TRUE;
|
2016-06-11 17:01:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2019-12-01 14:59:35 +03:00
|
|
|
static inline void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_free_menu (WMenuBar *menubar)
|
2016-06-22 14:30:49 +03:00
|
|
|
{
|
2023-03-18 09:32:45 +03:00
|
|
|
g_clear_list (&menubar->menu, (GDestroyNotify) menu_free);
|
2016-06-22 14:30:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2003-09-11 02:48:54 +04:00
|
|
|
static cb_ret_t
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2012-10-11 12:25:07 +04:00
|
|
|
WMenuBar *menubar = MENUBAR (w);
|
2005-05-23 20:39:52 +04:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
/* We do not want the focus unless we have been activated */
|
2012-09-28 15:05:43 +04:00
|
|
|
case MSG_FOCUS:
|
2016-06-13 11:30:57 +03:00
|
|
|
if (menubar_refresh (menubar))
|
|
|
|
{
|
|
|
|
menubar_draw (menubar);
|
|
|
|
return MSG_HANDLED;
|
|
|
|
}
|
|
|
|
return MSG_NOT_HANDLED;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2016-06-11 17:01:13 +03:00
|
|
|
case MSG_UNFOCUS:
|
2016-06-22 14:30:49 +03:00
|
|
|
return widget_get_state (w, WST_FOCUSED) ? MSG_NOT_HANDLED : MSG_HANDLED;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
/* We don't want the buttonbar to activate while using the menubar */
|
2012-09-28 15:05:43 +04:00
|
|
|
case MSG_HOTKEY:
|
|
|
|
case MSG_KEY:
|
2016-06-22 14:30:49 +03:00
|
|
|
if (widget_get_state (w, WST_FOCUSED))
|
2010-04-06 11:16:11 +04:00
|
|
|
{
|
|
|
|
menubar_handle_key (menubar, parm);
|
|
|
|
return MSG_HANDLED;
|
|
|
|
}
|
|
|
|
return MSG_NOT_HANDLED;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2012-09-28 15:05:43 +04:00
|
|
|
case MSG_CURSOR:
|
2010-04-06 11:16:11 +04:00
|
|
|
/* Put the cursor in a suitable place */
|
|
|
|
return MSG_NOT_HANDLED;
|
2003-09-11 02:48:54 +04:00
|
|
|
|
2012-09-28 15:05:43 +04:00
|
|
|
case MSG_DRAW:
|
2019-08-11 19:14:49 +03:00
|
|
|
if (widget_get_state (w, WST_VISIBLE) || menubar_refresh (menubar))
|
2010-04-06 11:16:11 +04:00
|
|
|
menubar_draw (menubar);
|
2016-06-11 17:01:13 +03:00
|
|
|
return MSG_HANDLED;
|
2003-09-11 02:48:54 +04:00
|
|
|
|
2012-09-28 15:05:43 +04:00
|
|
|
case MSG_RESIZE:
|
2010-04-06 11:16:11 +04:00
|
|
|
/* try show menu after screen resize */
|
2016-10-13 10:15:03 +03:00
|
|
|
widget_default_callback (w, NULL, MSG_RESIZE, 0, data);
|
2016-06-11 17:01:13 +03:00
|
|
|
menubar_refresh (menubar);
|
2010-04-06 11:16:11 +04:00
|
|
|
return MSG_HANDLED;
|
|
|
|
|
2012-09-28 15:05:43 +04:00
|
|
|
case MSG_DESTROY:
|
2016-06-22 14:30:49 +03:00
|
|
|
menubar_free_menu (menubar);
|
2010-04-06 11:16:11 +04:00
|
|
|
return MSG_HANDLED;
|
2009-05-04 20:11:51 +04:00
|
|
|
|
2003-09-11 02:48:54 +04:00
|
|
|
default:
|
2012-09-28 15:05:43 +04:00
|
|
|
return widget_default_callback (w, sender, msg, parm, data);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2016-01-19 15:05:14 +03:00
|
|
|
static unsigned int
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_get_menu_by_x_coord (const WMenuBar *menubar, int x)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2016-01-19 15:05:14 +03:00
|
|
|
unsigned int i;
|
|
|
|
GList *menu;
|
2011-03-21 16:43:56 +03:00
|
|
|
|
2016-01-19 15:05:14 +03:00
|
|
|
for (i = 0, menu = menubar->menu;
|
2019-09-08 11:38:51 +03:00
|
|
|
menu != NULL && x >= MENU (menu->data)->start_x; i++, menu = g_list_next (menu))
|
2016-01-19 15:05:14 +03:00
|
|
|
;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2016-01-19 15:05:14 +03:00
|
|
|
/* Don't set the invalid value -1 */
|
|
|
|
if (i != 0)
|
|
|
|
i--;
|
2009-08-26 22:31:54 +04:00
|
|
|
|
2016-01-19 15:05:14 +03:00
|
|
|
return i;
|
|
|
|
}
|
2010-04-06 11:16:11 +04:00
|
|
|
|
2016-01-19 15:05:14 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2012-06-12 17:44:39 +04:00
|
|
|
|
2016-01-19 15:05:14 +03:00
|
|
|
static gboolean
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_mouse_on_menu (const WMenuBar *menubar, int y, int x)
|
2016-01-19 15:05:14 +03:00
|
|
|
{
|
2022-05-01 10:43:33 +03:00
|
|
|
const WRect *w = &CONST_WIDGET (menubar)->rect;
|
2016-01-19 15:05:14 +03:00
|
|
|
menu_t *menu;
|
|
|
|
int left_x, right_x, bottom_y;
|
2012-06-12 17:44:39 +04:00
|
|
|
|
2016-02-05 03:30:57 +03:00
|
|
|
if (!menubar->is_dropped)
|
|
|
|
return FALSE;
|
|
|
|
|
2023-04-15 15:01:49 +03:00
|
|
|
menu = MENU (g_list_nth_data (menubar->menu, menubar->current));
|
2016-01-19 15:05:14 +03:00
|
|
|
left_x = menu->start_x;
|
|
|
|
right_x = left_x + menu->max_entry_len + 3;
|
|
|
|
if (right_x > w->cols)
|
2010-04-06 11:16:11 +04:00
|
|
|
{
|
2016-01-19 15:05:14 +03:00
|
|
|
left_x = w->cols - (menu->max_entry_len + 3);
|
|
|
|
right_x = w->cols;
|
|
|
|
}
|
|
|
|
|
|
|
|
bottom_y = g_list_length (menu->entries) + 2; /* skip bar and top frame */
|
|
|
|
|
|
|
|
return (x >= left_x && x < right_x && y > 1 && y < bottom_y);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2013-02-21 16:20:12 +04:00
|
|
|
|
2016-01-19 15:05:14 +03:00
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_change_selected_item (WMenuBar *menubar, int y)
|
2016-01-19 15:05:14 +03:00
|
|
|
{
|
|
|
|
menu_t *menu;
|
|
|
|
menu_entry_t *entry;
|
|
|
|
|
|
|
|
y -= 2; /* skip bar and top frame */
|
2023-04-15 15:01:49 +03:00
|
|
|
menu = MENU (g_list_nth_data (menubar->menu, menubar->current));
|
2016-01-19 15:05:14 +03:00
|
|
|
entry = MENUENTRY (g_list_nth_data (menu->entries, y));
|
|
|
|
|
|
|
|
if (entry != NULL && entry->command != CK_IgnoreKey)
|
|
|
|
{
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar_paint_idx (menubar, menu->current, MENU_ENTRY_COLOR);
|
|
|
|
menu->current = y;
|
|
|
|
menubar_paint_idx (menubar, menu->current, MENU_SELECTED_COLOR);
|
2009-09-22 16:11:37 +04:00
|
|
|
}
|
2016-01-19 15:05:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
static void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_mouse_callback (Widget *w, mouse_msg_t msg, mouse_event_t *event)
|
2016-01-19 15:05:14 +03:00
|
|
|
{
|
2016-02-07 11:42:42 +03:00
|
|
|
static gboolean was_drag = FALSE;
|
|
|
|
|
2016-01-19 15:05:14 +03:00
|
|
|
WMenuBar *menubar = MENUBAR (w);
|
2016-02-05 03:30:57 +03:00
|
|
|
gboolean mouse_on_drop;
|
|
|
|
|
|
|
|
mouse_on_drop = menubar_mouse_on_menu (menubar, event->y, event->x);
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2016-01-19 15:05:14 +03:00
|
|
|
switch (msg)
|
2010-04-06 11:16:11 +04:00
|
|
|
{
|
2016-01-19 15:05:14 +03:00
|
|
|
case MSG_MOUSE_DOWN:
|
2016-02-07 11:42:42 +03:00
|
|
|
was_drag = FALSE;
|
|
|
|
|
2016-01-19 15:05:14 +03:00
|
|
|
if (event->y == 0)
|
2010-04-06 11:16:11 +04:00
|
|
|
{
|
2016-02-05 03:30:57 +03:00
|
|
|
/* events on menubar */
|
2016-01-19 15:05:14 +03:00
|
|
|
unsigned int selected;
|
2010-04-06 11:16:11 +04:00
|
|
|
|
2016-01-19 15:05:14 +03:00
|
|
|
selected = menubar_get_menu_by_x_coord (menubar, event->x);
|
2016-02-23 09:49:58 +03:00
|
|
|
menubar_activate (menubar, TRUE, selected);
|
2016-02-05 03:30:57 +03:00
|
|
|
menubar_remove (menubar); /* if already shown */
|
|
|
|
menubar_drop (menubar, selected);
|
2010-04-06 11:16:11 +04:00
|
|
|
}
|
2016-02-05 03:30:57 +03:00
|
|
|
else if (mouse_on_drop)
|
2016-01-19 15:05:14 +03:00
|
|
|
menubar_change_selected_item (menubar, event->y);
|
2016-02-05 03:30:57 +03:00
|
|
|
else
|
2016-01-19 15:05:14 +03:00
|
|
|
{
|
2016-02-05 03:30:57 +03:00
|
|
|
/* mouse click outside menubar or dropdown -- close menu */
|
|
|
|
menubar_finish (menubar);
|
2010-04-06 11:16:11 +04:00
|
|
|
|
2016-02-05 03:30:57 +03:00
|
|
|
/*
|
|
|
|
* @FIXME.
|
|
|
|
*
|
|
|
|
* Unless we clear the 'capture' flag, we'll receive MSG_MOUSE_DRAG
|
|
|
|
* events belonging to this click (in case the user drags the mouse,
|
|
|
|
* of course).
|
|
|
|
*
|
|
|
|
* For the time being, we mark this with FIXME as this flag should
|
|
|
|
* preferably be regarded as "implementation detail" and not be
|
|
|
|
* touched by us. We should think of some other way of communicating
|
|
|
|
* this to the system.
|
|
|
|
*/
|
2016-03-06 09:44:16 +03:00
|
|
|
w->mouse.capture = FALSE;
|
2010-04-06 11:16:11 +04:00
|
|
|
}
|
2016-02-05 03:30:57 +03:00
|
|
|
break;
|
|
|
|
|
2016-02-07 11:42:42 +03:00
|
|
|
case MSG_MOUSE_UP:
|
|
|
|
if (was_drag && mouse_on_drop)
|
|
|
|
menubar_execute (menubar);
|
|
|
|
was_drag = FALSE;
|
|
|
|
break;
|
|
|
|
|
2016-02-05 03:30:57 +03:00
|
|
|
case MSG_MOUSE_CLICK:
|
2016-02-07 11:42:42 +03:00
|
|
|
was_drag = FALSE;
|
|
|
|
|
2016-02-05 03:30:57 +03:00
|
|
|
if ((event->buttons & GPM_B_MIDDLE) != 0 && event->y > 0 && menubar->is_dropped)
|
2010-04-06 11:16:11 +04:00
|
|
|
{
|
2016-01-19 15:05:14 +03:00
|
|
|
/* middle click -- everywhere */
|
|
|
|
menubar_execute (menubar);
|
2010-04-06 11:16:11 +04:00
|
|
|
}
|
2016-02-05 03:30:57 +03:00
|
|
|
else if (mouse_on_drop)
|
2016-01-19 15:05:14 +03:00
|
|
|
menubar_execute (menubar);
|
2016-02-05 03:30:57 +03:00
|
|
|
else if (event->y > 0)
|
|
|
|
/* releasing the mouse button outside the menu -- close menu */
|
2016-01-19 15:05:14 +03:00
|
|
|
menubar_finish (menubar);
|
|
|
|
break;
|
2010-04-06 11:16:11 +04:00
|
|
|
|
2016-01-19 15:05:14 +03:00
|
|
|
case MSG_MOUSE_DRAG:
|
|
|
|
if (event->y == 0)
|
2010-04-06 11:16:11 +04:00
|
|
|
{
|
2016-01-19 15:05:14 +03:00
|
|
|
menubar_remove (menubar);
|
|
|
|
menubar_drop (menubar, menubar_get_menu_by_x_coord (menubar, event->x));
|
|
|
|
}
|
2016-02-05 03:30:57 +03:00
|
|
|
else if (mouse_on_drop)
|
2016-01-19 15:05:14 +03:00
|
|
|
menubar_change_selected_item (menubar, event->y);
|
2016-02-07 11:42:42 +03:00
|
|
|
|
|
|
|
was_drag = TRUE;
|
2016-01-19 15:05:14 +03:00
|
|
|
break;
|
2010-04-06 11:16:11 +04:00
|
|
|
|
2016-01-19 15:05:14 +03:00
|
|
|
case MSG_MOUSE_SCROLL_UP:
|
|
|
|
case MSG_MOUSE_SCROLL_DOWN:
|
2016-02-07 11:42:42 +03:00
|
|
|
was_drag = FALSE;
|
|
|
|
|
2016-06-22 14:30:49 +03:00
|
|
|
if (widget_get_state (w, WST_FOCUSED))
|
2016-01-19 15:05:14 +03:00
|
|
|
{
|
|
|
|
if (event->y == 0)
|
|
|
|
{
|
|
|
|
/* menubar: left/right */
|
|
|
|
if (msg == MSG_MOUSE_SCROLL_UP)
|
|
|
|
menubar_left (menubar);
|
|
|
|
else
|
|
|
|
menubar_right (menubar);
|
|
|
|
}
|
2016-02-05 03:30:57 +03:00
|
|
|
else if (mouse_on_drop)
|
2016-01-19 15:05:14 +03:00
|
|
|
{
|
|
|
|
/* drop-down menu: up/down */
|
|
|
|
if (msg == MSG_MOUSE_SCROLL_UP)
|
|
|
|
menubar_up (menubar);
|
|
|
|
else
|
|
|
|
menubar_down (menubar);
|
|
|
|
}
|
2010-04-06 11:16:11 +04:00
|
|
|
}
|
2016-01-19 15:05:14 +03:00
|
|
|
break;
|
2009-08-26 22:31:54 +04:00
|
|
|
|
2016-01-19 15:05:14 +03:00
|
|
|
default:
|
2016-02-07 11:42:42 +03:00
|
|
|
was_drag = FALSE;
|
2016-01-19 15:05:14 +03:00
|
|
|
break;
|
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/*** public functions ****************************************************************************/
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
menu_entry_t *
|
2023-03-18 09:32:45 +03:00
|
|
|
menu_entry_new (const char *name, long command)
|
2010-11-10 14:09:42 +03:00
|
|
|
{
|
|
|
|
menu_entry_t *entry;
|
|
|
|
|
|
|
|
entry = g_new (menu_entry_t, 1);
|
|
|
|
entry->first_letter = ' ';
|
2019-12-14 11:50:04 +03:00
|
|
|
entry->text = hotkey_new (name);
|
2010-11-10 14:09:42 +03:00
|
|
|
entry->command = command;
|
|
|
|
entry->shortcut = NULL;
|
|
|
|
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
void
|
2024-06-01 21:12:14 +03:00
|
|
|
menu_entry_free (menu_entry_t *entry)
|
2010-11-10 14:09:42 +03:00
|
|
|
{
|
|
|
|
if (entry != NULL)
|
|
|
|
{
|
2019-12-14 11:50:04 +03:00
|
|
|
hotkey_free (entry->text);
|
2010-11-10 14:09:42 +03:00
|
|
|
g_free (entry->shortcut);
|
|
|
|
g_free (entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2012-10-11 12:41:29 +04:00
|
|
|
menu_t *
|
2024-06-01 21:12:14 +03:00
|
|
|
menu_new (const char *name, GList *entries, const char *help_node)
|
2010-11-10 14:09:42 +03:00
|
|
|
{
|
2012-10-11 12:41:29 +04:00
|
|
|
menu_t *menu;
|
2010-11-10 14:09:42 +03:00
|
|
|
|
2012-10-11 12:41:29 +04:00
|
|
|
menu = g_new (menu_t, 1);
|
2010-11-10 14:09:42 +03:00
|
|
|
menu->start_x = 0;
|
2019-12-14 11:50:04 +03:00
|
|
|
menu->text = hotkey_new (name);
|
2010-11-10 14:09:42 +03:00
|
|
|
menu->entries = entries;
|
|
|
|
menu->max_entry_len = 1;
|
|
|
|
menu->max_hotkey_len = 0;
|
2023-04-15 15:01:49 +03:00
|
|
|
menu->current = 0;
|
2010-11-10 14:09:42 +03:00
|
|
|
menu->help_node = g_strdup (help_node);
|
|
|
|
|
|
|
|
return menu;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2010-11-14 11:35:56 +03:00
|
|
|
void
|
2024-06-01 21:12:14 +03:00
|
|
|
menu_set_name (menu_t *menu, const char *name)
|
2010-11-14 11:35:56 +03:00
|
|
|
{
|
2019-12-14 11:50:04 +03:00
|
|
|
hotkey_free (menu->text);
|
|
|
|
menu->text = hotkey_new (name);
|
2010-11-14 11:35:56 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
void
|
2024-06-01 21:12:14 +03:00
|
|
|
menu_free (menu_t *menu)
|
2010-11-10 14:09:42 +03:00
|
|
|
{
|
2019-12-14 11:50:04 +03:00
|
|
|
hotkey_free (menu->text);
|
2013-11-04 12:09:13 +04:00
|
|
|
g_list_free_full (menu->entries, (GDestroyNotify) menu_entry_free);
|
2010-11-10 14:09:42 +03:00
|
|
|
g_free (menu->help_node);
|
|
|
|
g_free (menu);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
WMenuBar *
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_new (GList *menu)
|
2009-05-04 20:11:51 +04:00
|
|
|
{
|
2022-05-21 16:11:06 +03:00
|
|
|
WRect r = { 0, 0, 1, COLS };
|
2010-11-14 11:35:56 +03:00
|
|
|
WMenuBar *menubar;
|
2012-06-20 15:09:44 +04:00
|
|
|
Widget *w;
|
2009-05-04 20:11:51 +04:00
|
|
|
|
2010-11-14 11:35:56 +03:00
|
|
|
menubar = g_new0 (WMenuBar, 1);
|
2012-06-20 15:09:44 +04:00
|
|
|
w = WIDGET (menubar);
|
2022-05-21 16:11:06 +03:00
|
|
|
widget_init (w, &r, menubar_callback, menubar_mouse_callback);
|
2019-08-14 11:37:50 +03:00
|
|
|
w->pos_flags = WPOS_KEEP_HORZ | WPOS_KEEP_TOP;
|
2016-04-12 13:35:12 +03:00
|
|
|
w->options |= WOP_TOP_SELECT;
|
2017-03-08 14:41:35 +03:00
|
|
|
w->keymap = menu_map;
|
2009-05-04 20:11:51 +04:00
|
|
|
menubar_set_menu (menubar, menu);
|
2010-11-14 11:35:56 +03:00
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
return menubar;
|
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_set_menu (WMenuBar *menubar, GList *menu)
|
2009-05-04 20:11:51 +04:00
|
|
|
{
|
|
|
|
/* delete previous menu */
|
2016-06-22 14:30:49 +03:00
|
|
|
menubar_free_menu (menubar);
|
2009-05-04 20:11:51 +04:00
|
|
|
/* add new menu */
|
|
|
|
menubar->is_dropped = FALSE;
|
|
|
|
menubar->menu = menu;
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar->current = 0;
|
2009-05-04 20:11:51 +04:00
|
|
|
menubar_arrange (menubar);
|
2016-06-22 14:30:49 +03:00
|
|
|
widget_set_state (WIDGET (menubar), WST_FOCUSED, FALSE);
|
2009-05-04 20:11:51 +04:00
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_add_menu (WMenuBar *menubar, menu_t *menu)
|
2009-05-04 20:11:51 +04:00
|
|
|
{
|
2010-04-06 11:16:11 +04:00
|
|
|
if (menu != NULL)
|
|
|
|
{
|
2016-09-27 13:53:17 +03:00
|
|
|
menu_arrange (menu, DIALOG (WIDGET (menubar)->owner)->get_shortcut);
|
2010-04-06 11:16:11 +04:00
|
|
|
menubar->menu = g_list_append (menubar->menu, menu);
|
2009-10-24 12:58:02 +04:00
|
|
|
}
|
2009-05-04 20:11:51 +04:00
|
|
|
|
|
|
|
menubar_arrange (menubar);
|
|
|
|
}
|
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/**
|
1998-03-31 00:59:37 +04:00
|
|
|
* Properly space menubar items. Should be called when menubar is created
|
|
|
|
* and also when widget width is changed (i.e. upon xterm resize).
|
|
|
|
*/
|
2010-11-10 14:09:42 +03:00
|
|
|
|
1998-03-31 00:59:37 +04:00
|
|
|
void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_arrange (WMenuBar *menubar)
|
1998-03-31 00:59:37 +04:00
|
|
|
{
|
2009-05-04 20:11:51 +04:00
|
|
|
int start_x = 1;
|
2009-08-25 13:08:18 +04:00
|
|
|
GList *i;
|
2009-05-04 20:11:51 +04:00
|
|
|
int gap;
|
|
|
|
|
2009-08-25 13:08:18 +04:00
|
|
|
if (menubar->menu == NULL)
|
2010-04-06 11:16:11 +04:00
|
|
|
return;
|
1998-05-08 06:25:00 +04:00
|
|
|
|
2022-05-01 10:43:33 +03:00
|
|
|
gap = WIDGET (menubar)->rect.cols - 2;
|
2009-05-04 20:11:51 +04:00
|
|
|
|
|
|
|
/* First, calculate gap between items... */
|
2011-07-27 12:41:36 +04:00
|
|
|
for (i = menubar->menu; i != NULL; i = g_list_next (i))
|
2010-04-06 11:16:11 +04:00
|
|
|
{
|
2012-10-11 12:41:29 +04:00
|
|
|
menu_t *menu = MENU (i->data);
|
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
/* preserve length here, to be used below */
|
|
|
|
menu->start_x = hotkey_width (menu->text) + 2;
|
|
|
|
gap -= menu->start_x;
|
2008-12-29 01:57:59 +03:00
|
|
|
}
|
|
|
|
|
2012-01-21 12:44:38 +04:00
|
|
|
if (g_list_next (menubar->menu) == NULL)
|
|
|
|
gap = 1;
|
|
|
|
else
|
|
|
|
gap /= (g_list_length (menubar->menu) - 1);
|
1998-03-31 00:59:37 +04:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
if (gap <= 0)
|
|
|
|
{
|
|
|
|
/* We are out of luck - window is too narrow... */
|
|
|
|
gap = 1;
|
2009-05-04 20:11:51 +04:00
|
|
|
}
|
2012-03-21 17:56:25 +04:00
|
|
|
else if (gap >= 3)
|
|
|
|
gap = 3;
|
2003-09-01 03:29:49 +04:00
|
|
|
|
2009-05-04 20:11:51 +04:00
|
|
|
/* ...and now fix start positions of menubar items */
|
2011-07-27 12:41:36 +04:00
|
|
|
for (i = menubar->menu; i != NULL; i = g_list_next (i))
|
2010-04-06 11:16:11 +04:00
|
|
|
{
|
2012-10-11 12:41:29 +04:00
|
|
|
menu_t *menu = MENU (i->data);
|
2010-04-06 11:16:11 +04:00
|
|
|
int len = menu->start_x;
|
1998-03-31 00:59:37 +04:00
|
|
|
|
2010-04-06 11:16:11 +04:00
|
|
|
menu->start_x = start_x;
|
|
|
|
start_x += len + gap;
|
2009-05-04 20:11:51 +04:00
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
2009-11-08 13:49:27 +03:00
|
|
|
|
2010-11-10 14:09:42 +03:00
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
|
|
/** Find MenuBar widget in the dialog */
|
|
|
|
|
2009-11-08 13:49:27 +03:00
|
|
|
WMenuBar *
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_find (const WDialog *h)
|
2009-11-08 13:49:27 +03:00
|
|
|
{
|
2016-09-29 11:16:17 +03:00
|
|
|
return MENUBAR (widget_find_by_type (CONST_WIDGET (h), menubar_callback));
|
2009-11-08 13:49:27 +03:00
|
|
|
}
|
2010-11-10 14:09:42 +03:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
2016-03-09 11:56:16 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Activate menu bar.
|
|
|
|
*
|
|
|
|
* @param menubar menu bar object
|
|
|
|
* @param dropped whether dropdown menus should be drooped or not
|
|
|
|
* @which number of active dropdown menu
|
|
|
|
*/
|
|
|
|
void
|
2024-06-01 21:12:14 +03:00
|
|
|
menubar_activate (WMenuBar *menubar, gboolean dropped, int which)
|
2016-03-09 11:56:16 +03:00
|
|
|
{
|
|
|
|
Widget *w = WIDGET (menubar);
|
|
|
|
|
2019-08-11 19:14:49 +03:00
|
|
|
widget_show (w);
|
|
|
|
|
2016-06-22 14:30:49 +03:00
|
|
|
if (!widget_get_state (w, WST_FOCUSED))
|
2016-03-09 11:56:16 +03:00
|
|
|
{
|
2016-06-07 16:38:20 +03:00
|
|
|
widget_set_options (w, WOP_SELECTABLE, TRUE);
|
|
|
|
|
2016-03-09 11:56:16 +03:00
|
|
|
menubar->is_dropped = dropped;
|
|
|
|
if (which >= 0)
|
2023-04-15 15:01:49 +03:00
|
|
|
menubar->current = (guint) which;
|
2016-03-09 11:56:16 +03:00
|
|
|
|
2016-09-30 11:31:44 +03:00
|
|
|
menubar->previous_widget = group_get_current_widget_id (w->owner);
|
2016-02-23 09:49:58 +03:00
|
|
|
|
|
|
|
/* Bring it to the top so it receives all mouse events before any other widget.
|
|
|
|
* See also comment in menubar_finish(). */
|
2016-08-09 09:35:27 +03:00
|
|
|
widget_select (w);
|
2016-03-09 11:56:16 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|