# HG changeset patch # User Pavel Jank # Date 1019242611 0 # Node ID 3444517c6483db98bcc4fd294798735f68413b52 # Parent e697e304aa68eefc903c674cb5ca2a1f18dd67ed (xlwMenuTranslations, xlwMenuActionsList): Add translations for cursor keys and RET. (find_next_selectable, find_prev_selectable): New functions used for finding menu-items. (Down, Up, Left, Right): New functions. diff -r e697e304aa68 -r 3444517c6483 lwlib/xlwmenu.c --- a/lwlib/xlwmenu.c Fri Apr 19 18:38:16 2002 +0000 +++ b/lwlib/xlwmenu.c Fri Apr 19 18:56:51 2002 +0000 @@ -1,5 +1,6 @@ /* Implements a lightweight menubar widget. Copyright (C) 1992 Lucid, Inc. + Copyright (C) 2002 Free Software Foundation, Inc. This file is part of the Lucid Widget Library. @@ -114,10 +115,21 @@ Alt_R: nothing()\n\ Caps_Lock: nothing()\n\ Shift_Lock:nothing()\n\ +Return: select()\n\ +Down: down()\n\ +Up: up()\n\ +Left: left()\n\ +Right: right()\n\ : key()\n\ : key()\n\ "; +/* FIXME: Space should toggle toggleable menu item but not remove the menu + so you can toggle the next one without entering the menu again. */ + +/* FIXME: Should ESC close one level of menu structure or the complete menu? */ + + #define offset(field) XtOffset(XlwMenuWidget, field) static XtResource xlwMenuResources[] = @@ -174,6 +186,10 @@ static void XlwMenuClassInitialize(); static void Start(); static void Drag(); +static void Down(); +static void Up(); +static void Left(); +static void Right(); static void Select(); static void Key(); static void Nothing(); @@ -184,6 +200,10 @@ { {"start", Start}, {"drag", Drag}, + {"down", Down}, + {"up", Up}, + {"left", Left}, + {"right", Right}, {"select", Select}, {"key", Key}, {"nothing", Nothing}, @@ -1984,6 +2004,146 @@ { } +widget_value * +find_next_selectable (mw, item) + XlwMenuWidget mw; + widget_value *item; +{ + widget_value *current = item; + enum menu_separator separator; + + while (current->next && (current=current->next) && + (lw_separator_p (current->name, &separator, 0) || !current->enabled)) + ; + + if (current == item) + { + current = mw->menu.old_stack [mw->menu.old_depth - 2]->contents; + + while (lw_separator_p (current->name, &separator, 0) || !current->enabled) + if (current->next) + current=current->next; + } + + return current; +} + +widget_value * +find_prev_selectable (mw, item) + XlwMenuWidget mw; + widget_value *item; +{ + widget_value *current = item; + widget_value *prev = item; + + while ((current=find_next_selectable (mw, current)) != item) + prev=current; + + return prev; +} + +static void +Down (w, ev, params, num_params) + Widget w; + XEvent *ev; + String *params; + Cardinal *num_params; +{ + XlwMenuWidget mw = (XlwMenuWidget) w; + widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; + + /* Inside top-level menu-bar? */ + if (mw->menu.old_depth == 2) + /* When in the menu-bar is pressed, display the corresponding + sub-menu and select the first menu item there. */ + set_new_state (mw, selected_item->contents, mw->menu.old_depth); + else + /* Highlight next possible (enabled and not separator) menu item. */ + set_new_state (mw, find_next_selectable (mw, selected_item), mw->menu.old_depth - 1); + + remap_menubar (mw); +} + +static void +Up (w, ev, params, num_params) + Widget w; + XEvent *ev; + String *params; + Cardinal *num_params; +{ + XlwMenuWidget mw = (XlwMenuWidget) w; + widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; + + /* Inside top-level menu-bar? */ + if (mw->menu.old_depth == 2) + { + /* FIXME: this is tricky. in the menu-bar should select the + last selectable item in the list. So we select the first one and + find the previous selectable item. Is there a better way? */ + set_new_state (mw, selected_item->contents, mw->menu.old_depth); + remap_menubar (mw); + selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; + set_new_state (mw, find_prev_selectable (mw, selected_item), mw->menu.old_depth - 1); + } + else + /* Highlight previous (enabled and not separator) menu item. */ + set_new_state (mw, find_prev_selectable (mw, selected_item), mw->menu.old_depth - 1); + + remap_menubar (mw); +} + +static void +Left (w, ev, params, num_params) + Widget w; + XEvent *ev; + String *params; + Cardinal *num_params; +{ + XlwMenuWidget mw = (XlwMenuWidget) w; + widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; + + /* Inside top-level menu-bar? */ + if (mw->menu.old_depth == 2) + /* When in the menu-bar is pressed, display the previous item on + the menu-bar. If the current item is the first one, highlight the + last item in the menubar (probably Help). */ + set_new_state (mw, find_prev_selectable (mw, selected_item), mw->menu.old_depth - 1); + else + { + pop_new_stack_if_no_contents (mw); + set_new_state (mw, mw->menu.old_stack [mw->menu.old_depth - 2], mw->menu.old_depth - 2); + } + + remap_menubar (mw); +} + +static void +Right (w, ev, params, num_params) + Widget w; + XEvent *ev; + String *params; + Cardinal *num_params; +{ + XlwMenuWidget mw = (XlwMenuWidget) w; + widget_value* selected_item = mw->menu.old_stack [mw->menu.old_depth - 1]; + + /* Inside top-level menu-bar? */ + if (mw->menu.old_depth == 2) + /* When in the menu-bar is pressed, display the next item on + the menu-bar. If the current item is the last one, highlight the + first item (probably File). */ + set_new_state (mw, find_next_selectable (mw, selected_item), mw->menu.old_depth - 1); + else if (selected_item->contents) /* Is this menu item expandable? */ + set_new_state (mw, selected_item->contents, mw->menu.old_depth); + else + { + pop_new_stack_if_no_contents (mw); + set_new_state (mw, mw->menu.old_stack [mw->menu.old_depth - 2], mw->menu.old_depth - 2); + } + + remap_menubar (mw); +} + /* Handle key press and release events while menu is popped up. Our action is to get rid of the menu. */ static void