diff options
author | Eli Zaretskii <eliz@gnu.org> | 2012-05-26 15:14:56 +0300 |
---|---|---|
committer | Eli Zaretskii <eliz@gnu.org> | 2012-05-26 15:14:56 +0300 |
commit | 53a63be64de2c4a28ffcd275398255976a380fee (patch) | |
tree | 8d131c07086847e5756ac31e140908bae1ccbb1d | |
parent | 4cfd81f6c9755fb87eaf9f529c2bcbb0a30edfcf (diff) | |
parent | c4aeb92ab4ffdc943f330c9cce22d65eaba743af (diff) | |
download | emacs-53a63be64de2c4a28ffcd275398255976a380fee.tar.gz |
Extend mouse support on W32 text-mode console.
src/xdisp.c (draw_row_with_mouse_face): Call
tty_draw_row_with_mouse_face for WINDOWSNT as well.
src/w32console.c: Include window.h.
(w32con_write_glyphs_with_face, tty_draw_row_with_mouse_face): New
functions.
(initialize_w32_display): Initialize mouse-highlight data.
src/w32inevt.c: Include termchar.h and window.h.
(do_mouse_event): Support mouse-autoselect-window. When the mouse
moves, call note_mouse_highlight. If help_echo changed, call
gen_help_event to produce help-echo message in the echo area.
Call clear_mouse_face if mouse_face_hidden is set in the mouse
highlight info.
etc/NEWS: Describe the changes.
-rw-r--r-- | etc/NEWS | 4 | ||||
-rw-r--r-- | src/ChangeLog | 18 | ||||
-rw-r--r-- | src/w32console.c | 89 | ||||
-rw-r--r-- | src/w32inevt.c | 59 | ||||
-rw-r--r-- | src/xdisp.c | 2 |
5 files changed, 167 insertions, 5 deletions
@@ -313,6 +313,10 @@ by the underlying C implementation. *** --without-libxml2 omits support for libxml2, even if its presence is detected. +** When invoked with the -nw switch to run on the Windows text-mode terminal, +Emacs now supports mouse highlight, help-echo (in the echo area), and +mouse-autoselect-window. + * Installation Changes in Emacs 24.1 diff --git a/src/ChangeLog b/src/ChangeLog index 2981e754c8a..c71ea45dded 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,21 @@ +2012-05-26 Eli Zaretskii <eliz@gnu.org> + + Extend mouse support on W32 text-mode console. + * xdisp.c (draw_row_with_mouse_face): Call + tty_draw_row_with_mouse_face for WINDOWSNT as well. + + * w32console.c: Include window.h. + (w32con_write_glyphs_with_face, tty_draw_row_with_mouse_face): New + functions. + (initialize_w32_display): Initialize mouse-highlight data. + + * w32inevt.c: Include termchar.h and window.h. + (do_mouse_event): Support mouse-autoselect-window. When the mouse + moves, call note_mouse_highlight. If help_echo changed, call + gen_help_event to produce help-echo message in the echo area. + Call clear_mouse_face if mouse_face_hidden is set in the mouse + highlight info. + 2012-05-26 Paul Eggert <eggert@cs.ucla.edu> * lread.c (read1): Simplify slightly to avoid an overflow warning diff --git a/src/w32console.c b/src/w32console.c index e8b0f621b4f..22f329e239d 100644 --- a/src/w32console.c +++ b/src/w32console.c @@ -33,6 +33,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "coding.h" #include "disptab.h" #include "frame.h" +#include "window.h" #include "termhooks.h" #include "termchar.h" #include "dispextern.h" @@ -339,6 +340,84 @@ w32con_write_glyphs (struct frame *f, register struct glyph *string, } } +/* Used for mouse highlight. */ +static void +w32con_write_glyphs_with_face (struct frame *f, register int x, register int y, + register struct glyph *string, register int len, + register int face_id) +{ + unsigned char *conversion_buffer; + struct coding_system *coding; + + if (len <= 0) + return; + + /* If terminal_coding does any conversion, use it, otherwise use + safe_terminal_coding. We can't use CODING_REQUIRE_ENCODING here + because it always return 1 if the member src_multibyte is 1. */ + coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK + ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding); + /* We are going to write the entire block of glyphs in one go, as + they all have the same face. So this _is_ the last block. */ + coding->mode |= CODING_MODE_LAST_BLOCK; + + conversion_buffer = encode_terminal_code (string, len, coding); + if (coding->produced > 0) + { + DWORD filled, written; + /* Compute the character attributes corresponding to the face. */ + DWORD char_attr = w32_face_attributes (f, face_id); + COORD start_coords; + + start_coords.X = x; + start_coords.Y = y; + /* Set the attribute for these characters. */ + if (!FillConsoleOutputAttribute (cur_screen, char_attr, + coding->produced, start_coords, + &filled)) + DebPrint (("Failed writing console attributes: %d\n", GetLastError ())); + else + { + /* Write the characters. */ + if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer, + filled, start_coords, &written)) + DebPrint (("Failed writing console characters: %d\n", + GetLastError ())); + } + } +} + +/* Implementation of draw_row_with_mouse_face for W32 console. */ +void +tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row, + int start_hpos, int end_hpos, + enum draw_glyphs_face draw) +{ + int nglyphs = end_hpos - start_hpos; + struct frame *f = XFRAME (WINDOW_FRAME (w)); + struct tty_display_info *tty = FRAME_TTY (f); + int face_id = tty->mouse_highlight.mouse_face_face_id; + int pos_x, pos_y; + + if (end_hpos >= row->used[TEXT_AREA]) + nglyphs = row->used[TEXT_AREA] - start_hpos; + + pos_y = row->y + WINDOW_TOP_EDGE_Y (w); + pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w); + + if (draw == DRAW_MOUSE_FACE) + w32con_write_glyphs_with_face (f, pos_x, pos_y, + row->glyphs[TEXT_AREA] + start_hpos, + nglyphs, face_id); + else if (draw == DRAW_NORMAL_TEXT) + { + COORD save_coords = cursor_coords; + + w32con_move_cursor (f, pos_y, pos_x); + write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs); + w32con_move_cursor (f, save_coords.Y, save_coords.X); + } +} static void w32con_delete_glyphs (struct frame *f, int n) @@ -570,6 +649,7 @@ void initialize_w32_display (struct terminal *term) { CONSOLE_SCREEN_BUFFER_INFO info; + Mouse_HLInfo *hlinfo; term->rif = 0; /* No window based redisplay on the console. */ term->cursor_to_hook = w32con_move_cursor; @@ -600,6 +680,15 @@ initialize_w32_display (struct terminal *term) term->judge_scroll_bars_hook = 0; term->frame_up_to_date_hook = 0; + /* Initialize the mouse-highlight data. */ + hlinfo = &term->display_info.tty->mouse_highlight; + hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; + hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; + hlinfo->mouse_face_face_id = DEFAULT_FACE_ID; + hlinfo->mouse_face_mouse_frame = NULL; + hlinfo->mouse_face_window = Qnil; + hlinfo->mouse_face_hidden = 0; + /* Initialize interrupt_handle. */ init_crit (); diff --git a/src/w32inevt.c b/src/w32inevt.c index e7a8bf629d6..a85fdbbe435 100644 --- a/src/w32inevt.c +++ b/src/w32inevt.c @@ -35,8 +35,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #include "keyboard.h" #include "frame.h" #include "dispextern.h" +#include "window.h" #include "blockinput.h" #include "termhooks.h" +#include "termchar.h" #include "w32heap.h" #include "w32term.h" @@ -566,7 +568,7 @@ w32_console_mouse_position (FRAME_PTR *f, static void mouse_moved_to (int x, int y) { - /* If we're in the same place, ignore it */ + /* If we're in the same place, ignore it. */ if (x != movement_pos.X || y != movement_pos.Y) { SELECTED_FRAME ()->mouse_moved = 1; @@ -599,14 +601,63 @@ do_mouse_event (MOUSE_EVENT_RECORD *event, struct input_event *emacs_ev) { static DWORD button_state = 0; + static Lisp_Object last_mouse_window; DWORD but_change, mask; int i; if (event->dwEventFlags == MOUSE_MOVED) { - /* For movement events we just note that the mouse has moved - so that emacs will generate drag events. */ - mouse_moved_to (event->dwMousePosition.X, event->dwMousePosition.Y); + FRAME_PTR f = SELECTED_FRAME (); + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); + int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y; + + mouse_moved_to (mx, my); + + if (f->mouse_moved) + { + if (hlinfo->mouse_face_hidden) + { + hlinfo->mouse_face_hidden = 0; + clear_mouse_face (hlinfo); + } + + /* Generate SELECT_WINDOW_EVENTs when needed. */ + if (!NILP (Vmouse_autoselect_window)) + { + Lisp_Object mouse_window = window_from_coordinates (f, mx, my, + 0, 0); + /* A window will be selected only when it is not + selected now, and the last mouse movement event was + not in it. A minibuffer window will be selected iff + it is active. */ + if (WINDOWP (mouse_window) + && !EQ (mouse_window, last_mouse_window) + && !EQ (mouse_window, selected_window)) + { + struct input_event event; + + EVENT_INIT (event); + event.kind = SELECT_WINDOW_EVENT; + event.frame_or_window = mouse_window; + event.arg = Qnil; + event.timestamp = movement_time; + kbd_buffer_store_event (&event); + } + last_mouse_window = mouse_window; + } + else + last_mouse_window = Qnil; + + previous_help_echo_string = help_echo_string; + help_echo_string = help_echo_object = help_echo_window = Qnil; + help_echo_pos = -1; + note_mouse_highlight (f, mx, my); + /* If the contents of the global variable help_echo has + changed (inside note_mouse_highlight), generate a HELP_EVENT. */ + if (!NILP (help_echo_string) || !NILP (previous_help_echo_string)) + gen_help_event (help_echo_string, selected_frame, help_echo_window, + help_echo_object, help_echo_pos); + } return 0; } diff --git a/src/xdisp.c b/src/xdisp.c index 0a25eab1cbc..794355af153 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -25832,7 +25832,7 @@ draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row, return; } #endif -#if defined (HAVE_GPM) || defined (MSDOS) +#if defined (HAVE_GPM) || defined (MSDOS) || defined (WINDOWSNT) tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw); #endif } |