1998-02-27 07:54:42 +03:00
|
|
|
/* Pulldown menu code.
|
2007-09-26 14:22:25 +04:00
|
|
|
Copyright (C) 1994, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
|
|
|
2007 Free Software Foundation, Inc.
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
This program 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 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
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
|
|
|
|
along with this program; if not, write to the Free Software
|
2005-05-27 07:35:10 +04:00
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
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
|
|
|
|
Glibing..... (2)
Wed Jan 27 03:17:44 1999 Timur Bakeyev <mc@bat.ru>
* Converted memory managment to Glib. Now we use g_new()/g_malloc()/
g_strdup()/g_free() routings. Also, copy_strings() replaced by
g_strconcat(), strcasecmp() -> g_strcasecmp(),and sprintf() by
g_snprintf().
* Some sequences of malloc()/sprintf() changed to g_strdup_printf().
* mad.[ch]: Modified, to work with new GLib's memory managment. Fixed
a missing #undef for tempnam, which caused dead loop. Add several new
functions to emulate GLib memory managment.
*main.c, mad.[ch]: Add a new switch "-M", which allows to redirect MAD
messages to the file.
* util.[ch], utilunix.c: Modified, deleted our variants of strcasecmp()
and strdup() - we have g_ equivalences. Remove get_full_name() - it is
similar to concat_dir_and_file(). Some other tricks with g_* functions.
* global.h: Modified, extended. Now it is main memory mangment include -
i.e. all inclusions of <stdlib.h>, <malloc.h>, <glib.h>, "fs.h", "mem.h",
"util.h" and "mad.h" done there. This elimanates problem with proper or-
der of #include's.
* All around the source - changed order of #include's, most of them gone
to global.h (see above), minor changes, like "0" -> NULL in string func-
tions.
1999-01-27 04:08:30 +03:00
|
|
|
#include "global.h"
|
2009-05-09 19:17:57 +04:00
|
|
|
|
2009-05-08 14:01:05 +04:00
|
|
|
#include "../src/tty/tty.h"
|
2009-05-09 19:17:57 +04:00
|
|
|
#include "../src/tty/color.h"
|
|
|
|
#include "../src/tty/mouse.h"
|
|
|
|
#include "../src/tty/key.h" /* For mi_getch() */
|
|
|
|
#include "../src/tty/win.h"
|
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
#include "menu.h"
|
2001-08-07 02:22:04 +04:00
|
|
|
#include "help.h"
|
1998-02-27 07:54:42 +03:00
|
|
|
#include "dialog.h"
|
|
|
|
#include "main.h"
|
2008-12-29 01:57:59 +03:00
|
|
|
#include "strutil.h"
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
int menubar_visible = 1; /* This is the new default */
|
|
|
|
|
2002-11-13 00:01:50 +03:00
|
|
|
Menu *
|
2004-08-29 20:42:40 +04:00
|
|
|
create_menu (const char *name, menu_entry *entries, int count, const char *help_node)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2002-11-13 00:01:50 +03:00
|
|
|
Menu *menu;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2008-12-29 01:57:59 +03:00
|
|
|
menu = g_new (Menu, 1);
|
1998-02-27 07:54:42 +03:00
|
|
|
menu->count = count;
|
1999-08-03 09:17:47 +04:00
|
|
|
menu->max_entry_len = 20;
|
1998-02-27 07:54:42 +03:00
|
|
|
menu->entries = entries;
|
2008-12-29 01:57:59 +03:00
|
|
|
menu->text = parse_hotkey (name);
|
1998-03-31 00:59:37 +04:00
|
|
|
|
1999-08-01 15:37:25 +04:00
|
|
|
if (entries != (menu_entry*) NULL) {
|
2008-12-29 01:57:59 +03:00
|
|
|
int len;
|
1999-08-01 15:37:25 +04:00
|
|
|
register menu_entry* mp;
|
|
|
|
for (mp = entries; count--; mp++) {
|
2008-12-29 01:57:59 +03:00
|
|
|
if (mp->label[0] != '\0') {
|
2009-05-01 21:08:21 +04:00
|
|
|
mp->text = parse_hotkey (_(mp->label));
|
2008-12-29 01:57:59 +03:00
|
|
|
len = hotkey_width (mp->text);
|
|
|
|
menu->max_entry_len = max (len, menu->max_entry_len);
|
1999-08-01 15:37:25 +04:00
|
|
|
}
|
Fri Apr 3 05:23:20 1998 Alex Tkachenko <alex@bcs.zp.ua>
* configure.in: ALL_LINGUAS test added, to allow specify list
of languages to be installed by setting env variable before
configure. If it is empty, it defaults to full list.
* src/menu.h menu_entry.{hot_pos, is_dupped} dropped
* src/menu.c: consistency fixes: pull-down menu items are now
accessible either with arrow keys or with hotkeys, denoted with &
(and highlighted). (key combinations, placed to the right of items
intended to be used from outside the menus). Freeing menu entries
removed as it no longer needed
* src/main.c, edit/editmenu.c: menubar init code is changed to conform
above fixes.
* edit/edit.h: use of "Cancel" in error_dialogs replaced with
"Dismiss", to avoid collisions in translation of "Cancel" in other
places with this case.
* src/boxes.c: select_format() and it's support removed, as it is
obsoleted by input line history feature. display_init()/display_callback
fixed to suite i18n changes. sort_box() - alike.
* src/option.c: pause_options added &'s and gettext calls to expand
statically assigned values.
* src/widget.c: (radio_callback) hotkey recognition is changed to
&-notation, rather than simple uppercase.
* src/dlg.c: (dlg_try_hotkey) plain symbol comparison replaced with
call to isalpha(), this fixes errorneous exit from input line, when
button hotkey is 8-bit NLS char.
1998-04-04 00:00:00 +04:00
|
|
|
}
|
1999-08-01 15:37:25 +04:00
|
|
|
}
|
1998-03-31 00:59:37 +04:00
|
|
|
|
1998-06-08 04:33:31 +04:00
|
|
|
menu->start_x = 0;
|
2009-02-06 01:40:32 +03:00
|
|
|
menu->help_node = g_strdup (help_node);
|
1998-02-27 07:54:42 +03:00
|
|
|
return menu;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void menubar_drop_compute (WMenu *menubar)
|
|
|
|
{
|
1999-08-01 15:37:25 +04:00
|
|
|
menubar->max_entry_len = menubar->menu [menubar->selected]->max_entry_len;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void menubar_paint_idx (WMenu *menubar, int idx, int color)
|
|
|
|
{
|
2008-12-29 01:57:59 +03:00
|
|
|
const Menu *menu = menubar->menu[menubar->selected];
|
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;
|
|
|
|
const menu_entry *entry = &menu->entries[idx];
|
1998-03-31 00:59:37 +04:00
|
|
|
|
2009-04-26 18:22:53 +04:00
|
|
|
if (x + menubar->max_entry_len + 3 > menubar->widget.cols)
|
|
|
|
x = menubar->widget.cols - menubar->max_entry_len - 3;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2008-12-29 01:57:59 +03:00
|
|
|
if (entry->text.start == NULL) {
|
2009-04-26 18:22:53 +04:00
|
|
|
/* menu separator */
|
2009-05-11 16:13:58 +04:00
|
|
|
tty_setcolor (SELECTED_COLOR);
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2009-04-26 18:22:53 +04:00
|
|
|
if (!slow_terminal) {
|
|
|
|
widget_move (&menubar->widget, y, x - 1);
|
|
|
|
tty_print_alt_char (ACS_LTEE);
|
|
|
|
}
|
|
|
|
|
|
|
|
tty_print_hline (menubar->widget.y + y, menubar->widget.x + x,
|
|
|
|
menubar->max_entry_len + 2);
|
|
|
|
|
|
|
|
if (!slow_terminal)
|
|
|
|
tty_print_alt_char (ACS_RTEE);
|
|
|
|
} else {
|
|
|
|
/* menu text */
|
2009-05-11 16:13:58 +04:00
|
|
|
tty_setcolor (color);
|
2009-04-26 18:22:53 +04:00
|
|
|
widget_move (&menubar->widget, y, x);
|
|
|
|
addch ((unsigned char) entry->first_letter);
|
|
|
|
hline (' ', menubar->max_entry_len + 1); /* clear line */
|
2008-12-29 01:57:59 +03:00
|
|
|
addstr (str_term_form (entry->text.start));
|
2009-04-04 23:50:46 +04:00
|
|
|
|
2008-12-29 01:57:59 +03:00
|
|
|
if (entry->text.hotkey != NULL) {
|
2009-05-11 16:13:58 +04:00
|
|
|
tty_setcolor (color == MENU_SELECTED_COLOR ?
|
2009-04-26 18:22:53 +04:00
|
|
|
MENU_HOTSEL_COLOR : MENU_HOT_COLOR);
|
2008-12-29 01:57:59 +03:00
|
|
|
addstr (str_term_form (entry->text.hotkey));
|
2009-05-11 16:13:58 +04:00
|
|
|
tty_setcolor(color);
|
2009-04-26 18:22:53 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (entry->text.end != NULL)
|
2008-12-29 01:57:59 +03:00
|
|
|
addstr (str_term_form (entry->text.end));
|
2009-04-26 18:22:53 +04:00
|
|
|
|
|
|
|
/* move cursor to the start of entry text */
|
|
|
|
widget_move (&menubar->widget, y, x + 1);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-08-01 23:40:43 +04:00
|
|
|
static inline void menubar_draw_drop (WMenu *menubar)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2009-04-26 18:22:53 +04:00
|
|
|
const int count = menubar->menu [menubar->selected]->count;
|
|
|
|
int column = menubar->menu [menubar->selected]->start_x - 1;
|
|
|
|
int i;
|
1998-03-31 00:59:37 +04:00
|
|
|
|
2009-04-26 18:22:53 +04:00
|
|
|
if (column + menubar->max_entry_len + 4 > menubar->widget.cols)
|
|
|
|
column = menubar->widget.cols - menubar->max_entry_len - 4;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2009-05-11 16:13:58 +04:00
|
|
|
tty_setcolor (SELECTED_COLOR);
|
1998-02-27 07:54:42 +03:00
|
|
|
draw_box (menubar->widget.parent,
|
2009-04-26 18:22:53 +04:00
|
|
|
menubar->widget.y + 1, menubar->widget.x + column,
|
|
|
|
count + 2, menubar->max_entry_len + 4);
|
|
|
|
|
|
|
|
/* draw items except selected */
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
if (i != menubar->subsel)
|
|
|
|
menubar_paint_idx (menubar, i, MENU_ENTRY_COLOR);
|
|
|
|
|
|
|
|
/* draw selected item at last to move cursot to the nice location */
|
|
|
|
menubar_paint_idx (menubar, menubar->subsel, MENU_SELECTED_COLOR);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void menubar_draw (WMenu *menubar)
|
|
|
|
{
|
|
|
|
const int items = menubar->items;
|
|
|
|
int i;
|
2009-04-26 18:22:53 +04:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
/* First draw the complete menubar */
|
2009-05-11 16:13:58 +04:00
|
|
|
tty_setcolor (SELECTED_COLOR);
|
1998-02-27 07:54:42 +03:00
|
|
|
widget_move (&menubar->widget, 0, 0);
|
|
|
|
|
2005-08-05 16:01:47 +04:00
|
|
|
hline (' ', menubar->widget.cols);
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2009-05-11 16:13:58 +04:00
|
|
|
tty_setcolor (SELECTED_COLOR);
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Now each one of the entries */
|
|
|
|
for (i = 0; i < items; i++){
|
2009-05-11 16:13:58 +04:00
|
|
|
tty_setcolor ((menubar->active && i == menubar->selected) ?
|
2008-12-29 01:57:59 +03:00
|
|
|
MENU_SELECTED_COLOR : SELECTED_COLOR);
|
1998-03-31 00:59:37 +04:00
|
|
|
widget_move (&menubar->widget, 0, menubar->menu [i]->start_x);
|
2009-04-26 18:22:53 +04:00
|
|
|
|
2008-12-29 01:57:59 +03:00
|
|
|
addstr (str_term_form (menubar->menu[i]->text.start));
|
2009-04-26 18:22:53 +04:00
|
|
|
|
2008-12-29 01:57:59 +03:00
|
|
|
if (menubar->menu[i]->text.hotkey != NULL) {
|
2009-05-11 16:13:58 +04:00
|
|
|
tty_setcolor ((menubar->active && i == menubar->selected) ?
|
2008-12-29 01:57:59 +03:00
|
|
|
MENU_HOTSEL_COLOR : COLOR_HOT_FOCUS);
|
|
|
|
addstr (str_term_form (menubar->menu[i]->text.hotkey));
|
2009-05-11 16:13:58 +04:00
|
|
|
tty_setcolor ((menubar->active && i == menubar->selected) ?
|
2008-12-29 01:57:59 +03:00
|
|
|
MENU_SELECTED_COLOR : SELECTED_COLOR);
|
|
|
|
}
|
|
|
|
if (menubar->menu[i]->text.end != NULL) {
|
|
|
|
addstr (str_term_form (menubar->menu[i]->text.end));
|
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (menubar->dropped)
|
|
|
|
menubar_draw_drop (menubar);
|
2009-04-26 18:22:53 +04:00
|
|
|
else
|
|
|
|
widget_move (&menubar->widget, 0,
|
1998-03-31 00:59:37 +04:00
|
|
|
menubar-> menu[menubar->selected]->start_x);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
2002-08-01 23:40:43 +04:00
|
|
|
static inline void menubar_remove (WMenu *menubar)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
menubar->subsel = 0;
|
|
|
|
if (menubar->dropped){
|
|
|
|
menubar->dropped = 0;
|
|
|
|
do_refresh ();
|
|
|
|
menubar->dropped = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void menubar_left (WMenu *menu)
|
|
|
|
{
|
|
|
|
menubar_remove (menu);
|
|
|
|
menu->selected = (menu->selected - 1) % menu->items;
|
|
|
|
if (menu->selected < 0)
|
|
|
|
menu->selected = menu->items -1;
|
|
|
|
menubar_drop_compute (menu);
|
|
|
|
menubar_draw (menu);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void menubar_right (WMenu *menu)
|
|
|
|
{
|
|
|
|
menubar_remove (menu);
|
|
|
|
menu->selected = (menu->selected + 1) % menu->items;
|
|
|
|
menubar_drop_compute (menu);
|
|
|
|
menubar_draw (menu);
|
|
|
|
}
|
|
|
|
|
2003-09-13 02:45:51 +04:00
|
|
|
static void
|
|
|
|
menubar_finish (WMenu *menubar)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
menubar->dropped = 0;
|
|
|
|
menubar->active = 0;
|
|
|
|
menubar->widget.lines = 1;
|
|
|
|
widget_want_hotkey (menubar->widget, 0);
|
2003-09-13 11:43:20 +04:00
|
|
|
|
|
|
|
dlg_select_by_id (menubar->widget.parent, menubar->previous_widget);
|
1998-02-27 07:54:42 +03:00
|
|
|
do_refresh ();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void menubar_drop (WMenu *menubar, int selected)
|
|
|
|
{
|
|
|
|
menubar->dropped = 1;
|
|
|
|
menubar->selected = selected;
|
|
|
|
menubar->subsel = 0;
|
|
|
|
menubar_drop_compute (menubar);
|
|
|
|
menubar_draw (menubar);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void menubar_execute (WMenu *menubar, int entry)
|
|
|
|
{
|
2002-11-13 00:01:50 +03:00
|
|
|
const Menu *menu = menubar->menu [menubar->selected];
|
1999-06-22 14:29:29 +04:00
|
|
|
const callfn call_back = menu->entries [entry].call_back;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
is_right = menubar->selected != 0;
|
1999-06-22 14:29:29 +04:00
|
|
|
|
|
|
|
/* This used to be the other way round, i.e. first callback and
|
|
|
|
then menubar_finish. The new order (hack?) is needed to make
|
|
|
|
change_panel () work which is used in quick_view_cmd () -- Norbert
|
|
|
|
*/
|
1998-02-27 07:54:42 +03:00
|
|
|
menubar_finish (menubar);
|
2002-11-14 09:30:16 +03:00
|
|
|
(*call_back) ();
|
1999-06-24 10:47:02 +04:00
|
|
|
do_refresh ();
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void menubar_move (WMenu *menubar, int step)
|
|
|
|
{
|
2002-11-13 00:01:50 +03:00
|
|
|
const Menu *menu = menubar->menu [menubar->selected];
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
menubar_paint_idx (menubar, menubar->subsel, MENU_ENTRY_COLOR);
|
|
|
|
do {
|
|
|
|
menubar->subsel += step;
|
|
|
|
if (menubar->subsel < 0)
|
|
|
|
menubar->subsel = menu->count - 1;
|
|
|
|
|
|
|
|
menubar->subsel %= menu->count;
|
|
|
|
} while (!menu->entries [menubar->subsel].call_back);
|
|
|
|
menubar_paint_idx (menubar, menubar->subsel, MENU_SELECTED_COLOR);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int menubar_handle_key (WMenu *menubar, int key)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Lowercase */
|
2008-12-29 01:57:59 +03:00
|
|
|
if (isascii (key)) key = g_ascii_tolower (key);
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
if (is_abort_char (key)){
|
|
|
|
menubar_finish (menubar);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2001-08-07 02:22:04 +04:00
|
|
|
if (key == KEY_F(1)) {
|
|
|
|
if (menubar->dropped) {
|
2002-08-21 01:30:06 +04:00
|
|
|
interactive_display (NULL,
|
|
|
|
(menubar->menu [menubar->selected])->help_node);
|
2001-08-07 02:22:04 +04:00
|
|
|
} else {
|
|
|
|
interactive_display (NULL, "[Menu Bar]");
|
|
|
|
}
|
|
|
|
menubar_draw (menubar);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
if (key == KEY_LEFT || key == XCTRL('b')){
|
|
|
|
menubar_left (menubar);
|
|
|
|
return 1;
|
|
|
|
} else if (key == KEY_RIGHT || key == XCTRL ('f')){
|
|
|
|
menubar_right (menubar);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!menubar->dropped){
|
|
|
|
const int items = menubar->items;
|
2008-12-29 01:57:59 +03:00
|
|
|
for (i = 0; i < items; i++) {
|
2002-11-13 00:01:50 +03:00
|
|
|
const Menu *menu = menubar->menu [i];
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2008-12-29 01:57:59 +03:00
|
|
|
if (menu->text.hotkey != NULL) {
|
|
|
|
if (g_ascii_tolower(menu->text.hotkey[0]) == key) {
|
1998-02-27 07:54:42 +03:00
|
|
|
menubar_drop (menubar, i);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2008-12-29 01:57:59 +03:00
|
|
|
}
|
|
|
|
if (key == KEY_ENTER || key == XCTRL ('n')
|
|
|
|
|| key == KEY_DOWN || key == '\n') {
|
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
menubar_drop (menubar, menubar->selected);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
const int selected = menubar->selected;
|
2002-11-13 00:01:50 +03:00
|
|
|
const Menu *menu = menubar->menu [selected];
|
1998-02-27 07:54:42 +03:00
|
|
|
const int items = menu->count;
|
|
|
|
|
2008-12-29 01:57:59 +03:00
|
|
|
for (i = 0; i < items; i++) {
|
1998-02-27 07:54:42 +03:00
|
|
|
if (!menu->entries [i].call_back)
|
|
|
|
continue;
|
|
|
|
|
2008-12-29 01:57:59 +03:00
|
|
|
if (menu->entries[i].text.hotkey != NULL) {
|
|
|
|
if (key != g_ascii_tolower (menu->entries[i].text.hotkey[0]))
|
Fri Apr 3 05:23:20 1998 Alex Tkachenko <alex@bcs.zp.ua>
* configure.in: ALL_LINGUAS test added, to allow specify list
of languages to be installed by setting env variable before
configure. If it is empty, it defaults to full list.
* src/menu.h menu_entry.{hot_pos, is_dupped} dropped
* src/menu.c: consistency fixes: pull-down menu items are now
accessible either with arrow keys or with hotkeys, denoted with &
(and highlighted). (key combinations, placed to the right of items
intended to be used from outside the menus). Freeing menu entries
removed as it no longer needed
* src/main.c, edit/editmenu.c: menubar init code is changed to conform
above fixes.
* edit/edit.h: use of "Cancel" in error_dialogs replaced with
"Dismiss", to avoid collisions in translation of "Cancel" in other
places with this case.
* src/boxes.c: select_format() and it's support removed, as it is
obsoleted by input line history feature. display_init()/display_callback
fixed to suite i18n changes. sort_box() - alike.
* src/option.c: pause_options added &'s and gettext calls to expand
statically assigned values.
* src/widget.c: (radio_callback) hotkey recognition is changed to
&-notation, rather than simple uppercase.
* src/dlg.c: (dlg_try_hotkey) plain symbol comparison replaced with
call to isalpha(), this fixes errorneous exit from input line, when
button hotkey is 8-bit NLS char.
1998-04-04 00:00:00 +04:00
|
|
|
continue;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
menubar_execute (menubar, i);
|
|
|
|
return 1;
|
|
|
|
}
|
2008-12-29 01:57:59 +03:00
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2008-12-29 01:57:59 +03:00
|
|
|
if (key == KEY_ENTER || key == '\n') {
|
1998-02-27 07:54:42 +03:00
|
|
|
menubar_execute (menubar, menubar->subsel);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (key == KEY_DOWN || key == XCTRL ('n'))
|
|
|
|
menubar_move (menubar, 1);
|
|
|
|
|
|
|
|
if (key == KEY_UP || key == XCTRL ('p'))
|
|
|
|
menubar_move (menubar, -1);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-09-11 02:48:54 +04:00
|
|
|
static cb_ret_t
|
2005-05-23 20:39:52 +04:00
|
|
|
menubar_callback (Widget *w, widget_msg_t msg, int parm)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2005-05-23 20:39:52 +04:00
|
|
|
WMenu *menubar = (WMenu *) w;
|
|
|
|
|
2003-09-11 02:48:54 +04:00
|
|
|
switch (msg) {
|
1998-02-27 07:54:42 +03:00
|
|
|
/* We do not want the focus unless we have been activated */
|
|
|
|
case WIDGET_FOCUS:
|
2003-09-11 02:48:54 +04:00
|
|
|
if (!menubar->active)
|
|
|
|
return MSG_NOT_HANDLED;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2003-09-11 02:48:54 +04:00
|
|
|
widget_want_cursor (menubar->widget, 1);
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2003-09-11 02:48:54 +04:00
|
|
|
/* Trick to get all the mouse events */
|
|
|
|
menubar->widget.lines = LINES;
|
|
|
|
|
|
|
|
/* Trick to get all of the hotkeys */
|
|
|
|
widget_want_hotkey (menubar->widget, 1);
|
|
|
|
menubar->subsel = 0;
|
|
|
|
menubar_drop_compute (menubar);
|
|
|
|
menubar_draw (menubar);
|
|
|
|
return MSG_HANDLED;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
/* We don't want the buttonbar to activate while using the menubar */
|
|
|
|
case WIDGET_HOTKEY:
|
|
|
|
case WIDGET_KEY:
|
2003-09-11 02:48:54 +04:00
|
|
|
if (menubar->active) {
|
|
|
|
menubar_handle_key (menubar, parm);
|
|
|
|
return MSG_HANDLED;
|
1998-02-27 07:54:42 +03:00
|
|
|
} else
|
2003-09-11 02:48:54 +04:00
|
|
|
return MSG_NOT_HANDLED;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
case WIDGET_CURSOR:
|
|
|
|
/* Put the cursor in a suitable place */
|
2003-09-11 02:48:54 +04:00
|
|
|
return MSG_NOT_HANDLED;
|
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
case WIDGET_UNFOCUS:
|
|
|
|
if (menubar->active)
|
2003-09-11 02:48:54 +04:00
|
|
|
return MSG_NOT_HANDLED;
|
1998-02-27 07:54:42 +03:00
|
|
|
else {
|
|
|
|
widget_want_cursor (menubar->widget, 0);
|
2003-09-11 02:48:54 +04:00
|
|
|
return MSG_HANDLED;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
case WIDGET_DRAW:
|
2009-08-09 19:25:40 +04:00
|
|
|
if (menubar_visible) {
|
1998-02-27 07:54:42 +03:00
|
|
|
menubar_draw (menubar);
|
2009-08-09 19:25:40 +04:00
|
|
|
return MSG_HANDLED;
|
|
|
|
}
|
|
|
|
/* fall through */
|
2003-09-11 02:48:54 +04:00
|
|
|
|
2009-08-09 19:25:40 +04:00
|
|
|
case WIDGET_RESIZED:
|
|
|
|
/* try show menu after screen resize */
|
|
|
|
send_message (w, WIDGET_FOCUS, 0);
|
|
|
|
return MSG_HANDLED;
|
|
|
|
|
2003-09-11 02:48:54 +04:00
|
|
|
default:
|
|
|
|
return default_proc (msg, parm);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-13 00:01:50 +03:00
|
|
|
static int
|
2005-05-23 20:39:52 +04:00
|
|
|
menubar_event (Gpm_Event *event, void *data)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2005-05-23 20:39:52 +04:00
|
|
|
WMenu *menubar = data;
|
1998-02-27 07:54:42 +03:00
|
|
|
int was_active;
|
|
|
|
int new_selection;
|
|
|
|
int left_x, right_x, bottom_y;
|
|
|
|
|
|
|
|
if (!(event->type & (GPM_UP|GPM_DOWN|GPM_DRAG)))
|
|
|
|
return MOU_NORMAL;
|
|
|
|
|
|
|
|
if (!menubar->dropped){
|
2003-09-13 11:43:20 +04:00
|
|
|
menubar->previous_widget = menubar->widget.parent->current->dlg_id;
|
1998-02-27 07:54:42 +03:00
|
|
|
menubar->active = 1;
|
|
|
|
menubar->dropped = 1;
|
|
|
|
was_active = 0;
|
|
|
|
} else
|
|
|
|
was_active = 1;
|
|
|
|
|
|
|
|
/* Mouse operations on the menubar */
|
|
|
|
if (event->y == 1 || !was_active){
|
|
|
|
if (event->type & GPM_UP)
|
|
|
|
return MOU_NORMAL;
|
|
|
|
|
|
|
|
new_selection = 0;
|
1998-03-31 00:59:37 +04:00
|
|
|
while (new_selection < menubar->items
|
|
|
|
&& event->x > menubar->menu[new_selection]->start_x
|
|
|
|
)
|
|
|
|
new_selection++;
|
|
|
|
|
1998-05-21 02:34:13 +04:00
|
|
|
if (new_selection) /* Don't set the invalid value -1 */
|
|
|
|
--new_selection;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
if (!was_active){
|
|
|
|
menubar->selected = new_selection;
|
2005-05-21 00:22:06 +04:00
|
|
|
dlg_select_widget (menubar);
|
1998-02-27 07:54:42 +03:00
|
|
|
menubar_drop_compute (menubar);
|
|
|
|
menubar_draw (menubar);
|
|
|
|
return MOU_NORMAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
menubar_remove (menubar);
|
|
|
|
|
|
|
|
menubar->selected = new_selection;
|
|
|
|
|
|
|
|
menubar_drop_compute (menubar);
|
|
|
|
menubar_draw (menubar);
|
|
|
|
return MOU_NORMAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!menubar->dropped)
|
|
|
|
return MOU_NORMAL;
|
|
|
|
|
|
|
|
/* Ignore the events on anything below the third line */
|
|
|
|
if (event->y <= 2)
|
|
|
|
return MOU_NORMAL;
|
|
|
|
|
|
|
|
/* Else, the mouse operation is on the menus or it is not */
|
1998-03-31 00:59:37 +04:00
|
|
|
left_x = menubar->menu[menubar->selected]->start_x;
|
|
|
|
right_x = left_x + menubar->max_entry_len + 4;
|
|
|
|
if (right_x > menubar->widget.cols)
|
|
|
|
{
|
|
|
|
left_x = menubar->widget.cols - menubar->max_entry_len - 3;
|
|
|
|
right_x = menubar->widget.cols - 1;
|
|
|
|
}
|
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
bottom_y = (menubar->menu [menubar->selected])->count + 3;
|
|
|
|
|
|
|
|
if ((event->x > left_x) && (event->x < right_x) && (event->y < bottom_y)){
|
|
|
|
int pos = event->y - 3;
|
|
|
|
|
|
|
|
if (!menubar->menu [menubar->selected]->entries [pos].call_back)
|
|
|
|
return MOU_NORMAL;
|
|
|
|
|
|
|
|
menubar_paint_idx (menubar, menubar->subsel, MENU_ENTRY_COLOR);
|
|
|
|
menubar->subsel = pos;
|
|
|
|
menubar_paint_idx (menubar, menubar->subsel, MENU_SELECTED_COLOR);
|
|
|
|
|
|
|
|
if (event->type & GPM_UP)
|
|
|
|
menubar_execute (menubar, pos);
|
|
|
|
} else
|
|
|
|
if (event->type & GPM_DOWN)
|
|
|
|
menubar_finish (menubar);
|
|
|
|
|
|
|
|
return MOU_NORMAL;
|
|
|
|
}
|
|
|
|
|
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).
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
menubar_arrange(WMenu* menubar)
|
|
|
|
{
|
1998-05-08 06:25:00 +04:00
|
|
|
register int i, start_x = 1;
|
1998-03-31 00:59:37 +04:00
|
|
|
int items = menubar->items;
|
1998-05-08 06:25:00 +04:00
|
|
|
|
|
|
|
#ifndef RESIZABLE_MENUBAR
|
|
|
|
int gap = 3;
|
|
|
|
|
|
|
|
for (i = 0; i < items; i++)
|
|
|
|
{
|
2008-12-29 01:57:59 +03:00
|
|
|
int len = hotkey_width (menubar->menu[i]->text);
|
1998-05-08 06:25:00 +04:00
|
|
|
menubar->menu[i]->start_x = start_x;
|
|
|
|
start_x += len + gap;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else /* RESIZABLE_MENUBAR */
|
|
|
|
|
1998-03-31 00:59:37 +04:00
|
|
|
int gap = menubar->widget.cols - 2;
|
|
|
|
|
|
|
|
/* First, calculate gap between items... */
|
|
|
|
for (i = 0; i < items; i++)
|
|
|
|
{
|
|
|
|
/* preserve length here, to be used below */
|
2008-12-29 01:57:59 +03:00
|
|
|
gap -= (menubar->menu[i]->start_x = hotkey_width (menubar->menu[i]->text));
|
1998-03-31 00:59:37 +04:00
|
|
|
}
|
1998-05-08 06:25:00 +04:00
|
|
|
|
1998-03-31 00:59:37 +04:00
|
|
|
gap /= (items - 1);
|
|
|
|
|
|
|
|
if (gap <= 0)
|
|
|
|
{
|
|
|
|
/* We are out of luck - window is too narrow... */
|
|
|
|
gap = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ...and now fix start positions of menubar items */
|
1998-05-08 06:25:00 +04:00
|
|
|
for (i = 0; i < items; i++)
|
1998-03-31 00:59:37 +04:00
|
|
|
{
|
|
|
|
int len = menubar->menu[i]->start_x;
|
|
|
|
menubar->menu[i]->start_x = start_x;
|
|
|
|
start_x += len + gap;
|
|
|
|
}
|
1998-05-08 06:25:00 +04:00
|
|
|
#endif /* RESIZABLE_MENUBAR */
|
|
|
|
}
|
1998-03-31 00:59:37 +04:00
|
|
|
|
|
|
|
void
|
2002-11-13 00:01:50 +03:00
|
|
|
destroy_menu (Menu *menu)
|
1998-03-31 00:59:37 +04:00
|
|
|
{
|
2008-12-29 01:57:59 +03:00
|
|
|
release_hotkey (menu->text);
|
|
|
|
if (menu->entries != NULL) {
|
|
|
|
int me;
|
|
|
|
for (me = 0; me < menu->count; me++) {
|
|
|
|
if (menu->entries[me].label[0] != '\0') {
|
|
|
|
release_hotkey (menu->entries[me].text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-06 01:27:37 +03:00
|
|
|
g_free (menu->help_node);
|
|
|
|
g_free (menu);
|
1998-03-31 00:59:37 +04:00
|
|
|
}
|
|
|
|
|
2003-09-01 03:29:49 +04:00
|
|
|
WMenu *
|
|
|
|
menubar_new (int y, int x, int cols, Menu *menu[], int items)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2009-04-21 20:20:52 +04:00
|
|
|
WMenu *menubar = g_new0 (WMenu, 1);
|
2003-09-01 03:29:49 +04:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
init_widget (&menubar->widget, y, x, 1, cols,
|
2005-05-23 20:39:52 +04:00
|
|
|
menubar_callback, menubar_event);
|
1998-02-27 07:54:42 +03:00
|
|
|
menubar->menu = menu;
|
|
|
|
menubar->active = 0;
|
|
|
|
menubar->dropped = 0;
|
|
|
|
menubar->items = items;
|
|
|
|
menubar->selected = 0;
|
2009-04-21 20:20:52 +04:00
|
|
|
menubar->subsel = 0;
|
1998-02-27 07:54:42 +03:00
|
|
|
widget_want_cursor (menubar->widget, 0);
|
2003-09-01 03:29:49 +04:00
|
|
|
menubar_arrange (menubar);
|
1998-03-31 00:59:37 +04:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
return menubar;
|
|
|
|
}
|