summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2013-10-14 18:37:12 +0300
committerEli Zaretskii <eliz@gnu.org>2013-10-14 18:37:12 +0300
commitccd4a7833f341e2c22d6933357282954af6a57b2 (patch)
treee28e73f9b0e1b85ee9d81adb79d7389c04e4473f
parent77e3b1b7095b3376dbddd22cbca4827b797767c0 (diff)
downloademacs-ccd4a7833f341e2c22d6933357282954af6a57b2.tar.gz
Implement scrolling of TTY menus when the screen is too short.
src/term.c (tty_menu_display): Accept an additional argument, the menu item from which to start displaying the menu. Account for the value of Y when limiting the menu to the number of available screen lines. (mi_result): New enumeration. (read_menu_input): Return enumerated value. When the y coordinate hits min_y or max_y, return scroll indication instead of wrapping around the menu. (tty_menu_activate): Handle the scrolling indications from read_menu_input. Compute the first menu item to display and pass it to tty_menu_display. lisp/menu-bar.el (tty-menu-navigation-map): Bind shifted mouse clicks to commands that scroll the menu.
-rw-r--r--lisp/ChangeLog5
-rw-r--r--lisp/menu-bar.el12
-rw-r--r--src/ChangeLog16
-rw-r--r--src/term.c114
4 files changed, 103 insertions, 44 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 120fbb197eb..4471d4c2b25 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,8 @@
+2013-10-14 Eli Zaretskii <eliz@gnu.org>
+
+ * menu-bar.el (tty-menu-navigation-map): Bind shifted mouse clicks
+ to commands that scroll the menu.
+
2013-10-14 Dmitry Gutov <dgutov@yandex.ru>
* progmodes/ruby-mode.el (ruby-smie--args-separator-p): Handle
diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el
index 851e9b24649..7a53f968d69 100644
--- a/lisp/menu-bar.el
+++ b/lisp/menu-bar.el
@@ -2341,20 +2341,26 @@ If FRAME is nil or not given, use the selected frame."
(define-key map [linefeed] 'tty-menu-select)
(define-key map [down-mouse-1] 'tty-menu-select)
(define-key map [drag-mouse-1] 'tty-menu-select)
+ ;; The following 4 bindings are for those whose text-mode mouse
+ ;; lack the wheel.
+ (define-key map [S-down-mouse-1] 'tty-menu-next-item)
+ (define-key map [S-drag-mouse-1] 'tty-menu-next-item)
+ (define-key map [S-down-mouse-2] 'tty-menu-prev-item)
+ (define-key map [S-drag-mouse-2] 'tty-menu-prev-item)
(define-key map [mode-line drag-mouse-1] 'tty-menu-select)
(define-key map [mode-line down-mouse-1] 'tty-menu-select)
(define-key map [header-line mouse-1] 'tty-menu-select)
(define-key map [header-line drag-mouse-1] 'tty-menu-select)
(define-key map [header-line down-mouse-1] 'tty-menu-select)
+ ;; The mouse events must be bound to tty-menu-ignore, otherwise
+ ;; the initial mouse click will select and immediately pop down
+ ;; the menu.
(define-key map [mode-line mouse-1] 'tty-menu-ignore)
(define-key map [mode-line mouse-2] 'tty-menu-ignore)
(define-key map [mode-line mouse-3] 'tty-menu-ignore)
(define-key map [mode-line C-mouse-1] 'tty-menu-ignore)
(define-key map [mode-line C-mouse-2] 'tty-menu-ignore)
(define-key map [mode-line C-mouse-3] 'tty-menu-ignore)
- ;; The mouse events must be bound to tty-menu-ignore, otherwise
- ;; the initial mouse click will select and immediately pop down
- ;; the menu.
(define-key map [mouse-1] 'tty-menu-ignore)
(define-key map [C-mouse-1] 'tty-menu-ignore)
(define-key map [C-mouse-2] 'tty-menu-ignore)
diff --git a/src/ChangeLog b/src/ChangeLog
index d9264f6a691..018489bdbc2 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,19 @@
+2013-10-14 Eli Zaretskii <eliz@gnu.org>
+
+ Implement scrolling of TTY menus when the screen is too short.
+
+ * term.c (tty_menu_display): Accept an additional argument, the
+ menu item from which to start displaying the menu. Account for
+ the value of Y when limiting the menu to the number of available
+ screen lines.
+ (mi_result): New enumeration.
+ (read_menu_input): Return enumerated value. When the y coordinate
+ hits min_y or max_y, return scroll indication instead of wrapping
+ around the menu.
+ (tty_menu_activate): Handle the scrolling indications from
+ read_menu_input. Compute the first menu item to display and pass
+ it to tty_menu_display.
+
2013-10-14 Dmitry Antipov <dmantipov@yandex.ru>
* termhooks.h (FRAME_MUST_WRITE_SPACES, FRAME_LINE_INS_DEL_OK)
diff --git a/src/term.c b/src/term.c
index 58e0f2abd45..ee81c59dcd4 100644
--- a/src/term.c
+++ b/src/term.c
@@ -2781,10 +2781,10 @@ DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
However, unlike on MSDOS, where the menu text is drawn directly to
the display video memory, on a TTY we use display_string (see
display_tty_menu_item in xdisp.c) to put the glyphs produced from
- the menu items directly into the frame's 'desired_matrix' glyph
- matrix, and then call update_frame_with_menu to deliver the results
- to the glass. The previous contents of the screen, in the form of
- the current_matrix, is stashed away, and used to restore screen
+ the menu items into the frame's 'desired_matrix' glyph matrix, and
+ then call update_frame_with_menu to deliver the results to the
+ glass. The previous contents of the screen, in the form of the
+ current_matrix, is stashed away, and used to restore screen
contents when the menu selection changes or when the final
selection is made and the menu should be popped down.
@@ -2911,11 +2911,12 @@ mouse_get_xy (int *x, int *y)
}
}
-/* Display MENU at (X,Y) using FACES. */
+/* Display MENU at (X,Y) using FACES, starting with FIRST_ITEM
+ (zero-based). */
static void
tty_menu_display (tty_menu *menu, int x, int y, int pn, int *faces,
- int mx, int my, int disp_help)
+ int mx, int my, int first_item, int disp_help)
{
int i, face, width, enabled, mousehere, row, col;
struct frame *sf = SELECTED_FRAME ();
@@ -2923,7 +2924,7 @@ tty_menu_display (tty_menu *menu, int x, int y, int pn, int *faces,
/* Don't try to display more menu items than the console can display
using the available screen lines. Exclude the echo area line, as
it will be overwritten by the help-echo anyway. */
- int max_items = min (menu->count, FRAME_LINES (sf) - 1);
+ int max_items = min (menu->count - first_item, FRAME_LINES (sf) - 1 - y);
menu_help_message = NULL;
@@ -2933,11 +2934,12 @@ tty_menu_display (tty_menu *menu, int x, int y, int pn, int *faces,
for (i = 0; i < max_items; i++)
{
int max_width = width + 2; /* +2 for padding blanks on each side */
+ int j = i + first_item;
- if (menu->submenu[i])
+ if (menu->submenu[j])
max_width += 2; /* for displaying " >" after the item */
enabled
- = (!menu->submenu[i] && menu->panenumber[i]) || (menu->submenu[i]);
+ = (!menu->submenu[j] && menu->panenumber[j]) || (menu->submenu[j]);
mousehere = (y + i == my && x <= mx && mx < x + max_width);
face = faces[enabled + mousehere * 2];
/* Display the menu help string for the i-th menu item even if
@@ -2945,12 +2947,12 @@ tty_menu_display (tty_menu *menu, int x, int y, int pn, int *faces,
code does. */
if (disp_help && enabled + mousehere * 2 >= 2)
{
- menu_help_message = menu->help_text[i];
+ menu_help_message = menu->help_text[j];
menu_help_paneno = pn - 1;
- menu_help_itemno = i;
+ menu_help_itemno = j;
}
- display_tty_menu_item (menu->text[i], max_width, face, x, y + i,
- menu->submenu[i] != NULL);
+ display_tty_menu_item (menu->text[j], max_width, face, x, y + i,
+ menu->submenu[j] != NULL);
}
update_frame_with_menu (sf);
cursor_to (sf, row, col);
@@ -3124,14 +3126,20 @@ screen_update (struct frame *f, struct glyph_matrix *mtx)
update_frame_with_menu (f);
}
-/* Read user input and return X and Y coordinates where that input
- puts us. We only consider mouse movement and click events and
- keyboard movement commands; the rest are ignored.
+typedef enum {
+ MI_QUIT_MENU = -1,
+ MI_CONTINUE = 0,
+ MI_ITEM_SELECTED = 1,
+ MI_NEXT_ITEM = 2,
+ MI_PREV_ITEM = 3,
+ MI_SCROLL_FORWARD = 4,
+ MI_SCROLL_BACK = 5
+} mi_result;
- Value is -1 if C-g was pressed, 1 if an item was selected, 2 or 3
- if we need to move to the next or previous menu-bar menu, zero
- otherwise. */
-static int
+/* Read user input and return X and Y coordinates where that input
+ puts us. We only consider mouse movement and click events, and
+ keyboard movement commands; the rest are ignored. */
+static mi_result
read_menu_input (struct frame *sf, int *x, int *y, int min_y, int max_y,
bool *first_time)
{
@@ -3144,7 +3152,7 @@ read_menu_input (struct frame *sf, int *x, int *y, int min_y, int max_y,
{
Lisp_Object cmd;
int usable_input = 1;
- int st = 0;
+ mi_result st = MI_CONTINUE;
struct tty_display_info *tty = FRAME_TTY (sf);
Lisp_Object saved_mouse_tracking = do_mouse_tracking;
@@ -3160,42 +3168,42 @@ read_menu_input (struct frame *sf, int *x, int *y, int min_y, int max_y,
do_mouse_tracking = saved_mouse_tracking;
if (EQ (cmd, Qt) || EQ (cmd, Qtty_menu_exit))
- return -1;
+ return MI_QUIT_MENU;
if (EQ (cmd, Qtty_menu_mouse_movement))
mouse_get_xy (x, y);
else if (EQ (cmd, Qtty_menu_next_menu))
{
usable_input = 0;
- st = 2;
+ st = MI_NEXT_ITEM;
}
else if (EQ (cmd, Qtty_menu_prev_menu))
{
usable_input = 0;
- st = 3;
+ st = MI_PREV_ITEM;
}
else if (EQ (cmd, Qtty_menu_next_item))
{
if (*y < max_y)
*y += 1;
else
- *y = min_y;
+ st = MI_SCROLL_FORWARD;
}
else if (EQ (cmd, Qtty_menu_prev_item))
{
if (*y > min_y)
*y -= 1;
else
- *y = max_y;
+ st = MI_SCROLL_BACK;
}
else if (EQ (cmd, Qtty_menu_select))
- st = 1;
+ st = MI_ITEM_SELECTED;
else if (!EQ (cmd, Qtty_menu_ignore))
usable_input = 0;
if (usable_input)
sf->mouse_moved = 1;
return st;
}
- return 0;
+ return MI_CONTINUE;
}
/* Display menu, wait for user's response, and return that response. */
@@ -3214,6 +3222,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
struct tty_display_info *tty = FRAME_TTY (sf);
bool first_time;
Lisp_Object selectface;
+ int first_item = 0;
/* Don't allow non-positive x0 and y0, lest the menu will wrap
around the display. */
@@ -3265,7 +3274,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
want to interpret them as zero-based column and row coordinates,
and also because we want the first item of the menu, not its
title, to appear at x0,y0. */
- tty_menu_display (menu, x0 - 1, y0 - 1, 1, title_faces, x0 - 1, y0 - 1, 0);
+ tty_menu_display (menu, x0 - 1, y0 - 1, 1, title_faces, x0 - 1, y0 - 1, 0, 0);
/* Turn off the cursor. Otherwise it shows through the menu
panes, which is ugly. */
@@ -3292,7 +3301,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
leave = 0;
while (!leave)
{
- int input_status;
+ mi_result input_status;
int min_y = state[0].y;
int max_y = min (min_y + state[0].menu->count, FRAME_LINES (sf) - 1) - 1;
@@ -3300,36 +3309,59 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
if (input_status)
{
leave = 1;
- if (input_status == -1)
+ switch (input_status)
{
+ case MI_QUIT_MENU:
/* Remove the last help-echo, so that it doesn't
re-appear after "Quit". */
show_help_echo (Qnil, Qnil, Qnil, Qnil);
result = TTYM_NO_SELECT;
- }
- else if (input_status == 2)
- {
+ break;
+ case MI_NEXT_ITEM:
if (kbd_navigation)
result = TTYM_NEXT;
else
leave = 0;
- }
- else if (input_status == 3)
- {
+ break;
+ case MI_PREV_ITEM:
if (kbd_navigation)
result = TTYM_PREV;
else
leave = 0;
+ break;
+ case MI_SCROLL_FORWARD:
+ if (y - min_y == state[0].menu->count - 1 - first_item)
+ {
+ y = min_y;
+ first_item = 0;
+ }
+ else
+ first_item++;
+ leave = 0;
+ break;
+ case MI_SCROLL_BACK:
+ if (first_item == 0)
+ {
+ y = max_y;
+ first_item = state[0].menu->count - 1 - (y - min_y);
+ }
+ else
+ first_item--;
+ leave = 0;
+ break;
+ default:
+ /* MI_ITEM_SELECTED is handled below, so nothing to do. */
+ break;
}
}
- if (sf->mouse_moved && input_status != -1)
+ if (sf->mouse_moved && input_status != MI_QUIT_MENU)
{
sf->mouse_moved = 0;
result = TTYM_IA_SELECT;
for (i = 0; i < statecount; i++)
if (state[i].x <= x && x < state[i].x + state[i].menu->width + 2)
{
- int dy = y - state[i].y;
+ int dy = y - state[i].y + first_item;
if (0 <= dy && dy < state[i].menu->count)
{
if (!state[i].menu->submenu[dy])
@@ -3358,7 +3390,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
state[i].x,
state[i].y,
state[i].pane,
- faces, x, y, 1);
+ faces, x, y, first_item, 1);
state[statecount].menu = state[i].menu->submenu[dy];
state[statecount].pane = state[i].menu->panenumber[dy];
state[statecount].screen_behind
@@ -3374,7 +3406,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
state[statecount - 1].x,
state[statecount - 1].y,
state[statecount - 1].pane,
- faces, x, y, 1);
+ faces, x, y, first_item, 1);
tty_hide_cursor (tty);
fflush (tty->output);
}