aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2010-11-02 21:35:12 +0200
committerEli Zaretskii2010-11-02 21:35:12 +0200
commitcf482c50792a60e9fa015f4cb95a8ff1cbb5e108 (patch)
tree3be1a1a03a80c3b68ba1c10df1ca386132014f9c /src
parent34574c0221167dd73b20cd645e240316e83dd6f8 (diff)
downloademacs-cf482c50792a60e9fa015f4cb95a8ff1cbb5e108.tar.gz
emacs-cf482c50792a60e9fa015f4cb95a8ff1cbb5e108.zip
Reflect mouse-highlight redesign in term.c
term.c: Remove static mouse_face_* variables. All users changed. (term_show_mouse_face, term_clear_mouse_face) (fast_find_position, term_mouse_highlight): Functions deleted. (tty_draw_row_with_mouse_face): New function. (term_mouse_movement): Call note_mouse_highlight instead of term_mouse_highlight.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog10
-rw-r--r--src/term.c448
2 files changed, 36 insertions, 422 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 43167c12a63..0e9d549e54a 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,13 @@
12010-11-02 Eli Zaretskii <eliz@gnu.org>
2
3 * term.c: Remove static mouse_face_* variables. All users
4 changed.
5 (term_show_mouse_face, term_clear_mouse_face)
6 (fast_find_position, term_mouse_highlight): Functions deleted.
7 (tty_draw_row_with_mouse_face): New function.
8 (term_mouse_movement): Call note_mouse_highlight instead of
9 term_mouse_highlight.
10
12010-11-01 Eli Zaretskii <eliz@gnu.org> 112010-11-01 Eli Zaretskii <eliz@gnu.org>
2 12
3 * msdos.c (dos_set_window_size, draw_row_with_mouse_face) 13 * msdos.c (dos_set_window_size, draw_row_with_mouse_face)
diff --git a/src/term.c b/src/term.c
index 4baea231de3..f99cf5751a0 100644
--- a/src/term.c
+++ b/src/term.c
@@ -184,24 +184,10 @@ extern char *tgetstr (char *, char **);
184#ifdef HAVE_GPM 184#ifdef HAVE_GPM
185#include <sys/fcntl.h> 185#include <sys/fcntl.h>
186 186
187static void term_clear_mouse_face (void);
188static void term_mouse_highlight (struct frame *f, int x, int y);
189
190/* The device for which we have enabled gpm support (or NULL). */ 187/* The device for which we have enabled gpm support (or NULL). */
191struct tty_display_info *gpm_tty = NULL; 188struct tty_display_info *gpm_tty = NULL;
192 189
193/* These variables describe the range of text currently shown in its 190/* Last recorded mouse coordinates. */
194 mouse-face, together with the window they apply to. As long as
195 the mouse stays within this range, we need not redraw anything on
196 its account. Rows and columns are glyph matrix positions in
197 MOUSE_FACE_WINDOW. */
198static int mouse_face_beg_row, mouse_face_beg_col;
199static int mouse_face_end_row, mouse_face_end_col;
200static int mouse_face_past_end;
201static Lisp_Object mouse_face_window;
202static int mouse_face_face_id;
203
204static int pos_x, pos_y;
205static int last_mouse_x, last_mouse_y; 191static int last_mouse_x, last_mouse_y;
206#endif /* HAVE_GPM */ 192#endif /* HAVE_GPM */
207 193
@@ -2517,416 +2503,36 @@ term_mouse_moveto (int x, int y)
2517 last_mouse_y = y; */ 2503 last_mouse_y = y; */
2518} 2504}
2519 2505
2520static void 2506/* Implementation of draw_row_with_mouse_face for TTY/GPM. */
2521term_show_mouse_face (enum draw_glyphs_face draw) 2507void
2508tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
2509 int start_hpos, int end_hpos,
2510 enum draw_glyphs_face draw)
2522{ 2511{
2523 struct window *w = XWINDOW (mouse_face_window); 2512 int nglyphs = end_hpos - start_hpos;
2524 int save_x, save_y; 2513 struct frame *f = XFRAME (WINDOW_FRAME (w));
2525 int i;
2526
2527 struct frame *f = XFRAME (w->frame);
2528 struct tty_display_info *tty = FRAME_TTY (f); 2514 struct tty_display_info *tty = FRAME_TTY (f);
2515 int face_id = tty->mouse_highlight.mouse_face_face_id;
2516 int save_x, save_y, pos_x, pos_y;
2529 2517
2530 if (/* If window is in the process of being destroyed, don't bother 2518 if (end_hpos >= row->used[TEXT_AREA])
2531 to do anything. */ 2519 nglyphs = row->used[TEXT_AREA] - start_hpos;
2532 w->current_matrix != NULL
2533 /* Recognize when we are called to operate on rows that don't exist
2534 anymore. This can happen when a window is split. */
2535 && mouse_face_end_row < w->current_matrix->nrows)
2536 {
2537 /* write_glyphs writes at cursor position, so we need to
2538 temporarily move cursor coordinates to the beginning of
2539 the highlight region. */
2540
2541 /* Save current cursor co-ordinates */
2542 save_y = curY (tty);
2543 save_x = curX (tty);
2544
2545 /* Note that mouse_face_beg_row etc. are window relative. */
2546 for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++)
2547 {
2548 int start_hpos, end_hpos, nglyphs;
2549 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
2550
2551 /* Don't do anything if row doesn't have valid contents. */
2552 if (!row->enabled_p)
2553 continue;
2554
2555 /* For all but the first row, the highlight starts at column 0. */
2556 if (i == mouse_face_beg_row)
2557 start_hpos = mouse_face_beg_col;
2558 else
2559 start_hpos = 0;
2560
2561 if (i == mouse_face_end_row)
2562 end_hpos = mouse_face_end_col;
2563 else
2564 {
2565 end_hpos = row->used[TEXT_AREA];
2566 if (draw == DRAW_NORMAL_TEXT)
2567 row->fill_line_p = 1; /* Clear to end of line */
2568 }
2569
2570 if (end_hpos <= start_hpos)
2571 continue;
2572 /* Record that some glyphs of this row are displayed in
2573 mouse-face. */
2574 row->mouse_face_p = draw > 0;
2575
2576 nglyphs = end_hpos - start_hpos;
2577 2520
2578 if (end_hpos >= row->used[TEXT_AREA]) 2521 pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
2579 nglyphs = row->used[TEXT_AREA] - start_hpos; 2522 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
2580 2523
2581 pos_y = row->y + WINDOW_TOP_EDGE_Y (w); 2524 /* Save current cursor co-ordinates. */
2582 pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos 2525 save_y = curY (tty);
2583 + WINDOW_LEFT_EDGE_X (w); 2526 save_x = curX (tty);
2584 2527 cursor_to (f, pos_y, pos_x);
2585 cursor_to (f, pos_y, pos_x);
2586
2587 if (draw == DRAW_MOUSE_FACE)
2588 {
2589 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2590 nglyphs, mouse_face_face_id);
2591 }
2592 else /* draw == DRAW_NORMAL_TEXT */
2593 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2594 }
2595 cursor_to (f, save_y, save_x);
2596 }
2597}
2598 2528
2599static void 2529 if (draw == DRAW_MOUSE_FACE)
2600term_clear_mouse_face (void) 2530 tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
2601{ 2531 nglyphs, face_id);
2602 if (!NILP (mouse_face_window)) 2532 else if (draw == DRAW_NORMAL_TEXT)
2603 term_show_mouse_face (DRAW_NORMAL_TEXT); 2533 write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
2604 2534
2605 mouse_face_beg_row = mouse_face_beg_col = -1; 2535 cursor_to (f, save_y, save_x);
2606 mouse_face_end_row = mouse_face_end_col = -1;
2607 mouse_face_window = Qnil;
2608}
2609
2610/* Find the glyph matrix position of buffer position POS in window W.
2611 *HPOS and *VPOS are set to the positions found. W's current glyphs
2612 must be up to date. If POS is above window start return (0, 0).
2613 If POS is after end of W, return end of last line in W.
2614 - taken from msdos.c */
2615static int
2616fast_find_position (struct window *w, EMACS_INT pos, int *hpos, int *vpos)
2617{
2618 int i, lastcol, maybe_next_line_p = 0;
2619 EMACS_INT line_start_position;
2620 int yb = window_text_bottom_y (w);
2621 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row;
2622
2623 while (row->y < yb)
2624 {
2625 if (row->used[TEXT_AREA])
2626 line_start_position = row->glyphs[TEXT_AREA]->charpos;
2627 else
2628 line_start_position = 0;
2629
2630 if (line_start_position > pos)
2631 break;
2632 /* If the position sought is the end of the buffer,
2633 don't include the blank lines at the bottom of the window. */
2634 else if (line_start_position == pos
2635 && pos == BUF_ZV (XBUFFER (w->buffer)))
2636 {
2637 maybe_next_line_p = 1;
2638 break;
2639 }
2640 else if (line_start_position > 0)
2641 best_row = row;
2642
2643 /* Don't overstep the last matrix row, lest we get into the
2644 never-never land... */
2645 if (row->y + 1 >= yb)
2646 break;
2647
2648 ++row;
2649 }
2650
2651 /* Find the right column within BEST_ROW. */
2652 lastcol = 0;
2653 row = best_row;
2654 for (i = 0; i < row->used[TEXT_AREA]; i++)
2655 {
2656 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
2657 EMACS_INT charpos;
2658
2659 charpos = glyph->charpos;
2660 if (charpos == pos)
2661 {
2662 *hpos = i;
2663 *vpos = row->y;
2664 return 1;
2665 }
2666 else if (charpos > pos)
2667 break;
2668 else if (charpos > 0)
2669 lastcol = i;
2670 }
2671
2672 /* If we're looking for the end of the buffer,
2673 and we didn't find it in the line we scanned,
2674 use the start of the following line. */
2675 if (maybe_next_line_p)
2676 {
2677 ++row;
2678 lastcol = 0;
2679 }
2680
2681 *vpos = row->y;
2682 *hpos = lastcol + 1;
2683 return 0;
2684}
2685
2686static void
2687term_mouse_highlight (struct frame *f, int x, int y)
2688{
2689 enum window_part part;
2690 Lisp_Object window;
2691 struct window *w;
2692 struct buffer *b;
2693
2694 if (NILP (Vmouse_highlight)
2695 || !f->glyphs_initialized_p)
2696 return;
2697
2698 /* Which window is that in? */
2699 window = window_from_coordinates (f, x, y, &part, &x, &y, 0);
2700
2701 /* Not on a window -> return. */
2702 if (!WINDOWP (window))
2703 return;
2704
2705 if (!EQ (window, mouse_face_window))
2706 term_clear_mouse_face ();
2707
2708 w = XWINDOW (window);
2709
2710 /* Are we in a window whose display is up to date?
2711 And verify the buffer's text has not changed. */
2712 b = XBUFFER (w->buffer);
2713 if (part == ON_TEXT
2714 && EQ (w->window_end_valid, w->buffer)
2715 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
2716 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
2717 {
2718 int i, nrows = w->current_matrix->nrows;
2719 EMACS_INT pos;
2720 struct glyph_row *row;
2721 struct glyph *glyph;
2722
2723 /* Find the glyph under X/Y. */
2724 glyph = NULL;
2725 if (y >= 0 && y < nrows)
2726 {
2727 row = MATRIX_ROW (w->current_matrix, y);
2728 /* Give up if some row before the one we are looking for is
2729 not enabled. */
2730 for (i = 0; i <= y; i++)
2731 if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
2732 break;
2733 if (i > y /* all rows upto and including the one at Y are enabled */
2734 && row->displays_text_p
2735 && x < window_box_width (w, TEXT_AREA))
2736 {
2737 glyph = row->glyphs[TEXT_AREA];
2738 if (x >= row->used[TEXT_AREA])
2739 glyph = NULL;
2740 else
2741 {
2742 glyph += x;
2743 if (!BUFFERP (glyph->object))
2744 glyph = NULL;
2745 }
2746 }
2747 }
2748
2749 /* Clear mouse face if X/Y not over text. */
2750 if (glyph == NULL)
2751 {
2752 term_clear_mouse_face ();
2753 return;
2754 }
2755
2756 if (!BUFFERP (glyph->object))
2757 abort ();
2758 pos = glyph->charpos;
2759
2760 /* Check for mouse-face. */
2761 {
2762 Lisp_Object mouse_face, overlay, position, *overlay_vec;
2763 int noverlays;
2764 EMACS_INT obegv, ozv;
2765 struct buffer *obuf;
2766
2767 /* If we get an out-of-range value, return now; avoid an error. */
2768 if (pos > BUF_Z (b))
2769 return;
2770
2771 /* Make the window's buffer temporarily current for
2772 overlays_at and compute_char_face. */
2773 obuf = current_buffer;
2774 current_buffer = b;
2775 obegv = BEGV;
2776 ozv = ZV;
2777 BEGV = BEG;
2778 ZV = Z;
2779
2780 /* Is this char mouse-active? */
2781 XSETINT (position, pos);
2782
2783 /* Put all the overlays we want in a vector in overlay_vec. */
2784 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0);
2785 /* Sort overlays into increasing priority order. */
2786 noverlays = sort_overlays (overlay_vec, noverlays, w);
2787
2788 /* Check mouse-face highlighting. */
2789 if (!(EQ (window, mouse_face_window)
2790 && y >= mouse_face_beg_row
2791 && y <= mouse_face_end_row
2792 && (y > mouse_face_beg_row
2793 || x >= mouse_face_beg_col)
2794 && (y < mouse_face_end_row
2795 || x < mouse_face_end_col
2796 || mouse_face_past_end)))
2797 {
2798 /* Clear the display of the old active region, if any. */
2799 term_clear_mouse_face ();
2800
2801 /* Find the highest priority overlay that has a mouse-face
2802 property. */
2803 overlay = Qnil;
2804 for (i = noverlays - 1; i >= 0; --i)
2805 {
2806 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2807 if (!NILP (mouse_face))
2808 {
2809 overlay = overlay_vec[i];
2810 break;
2811 }
2812 }
2813
2814 /* If no overlay applies, get a text property. */
2815 if (NILP (overlay))
2816 mouse_face = Fget_text_property (position, Qmouse_face,
2817 w->buffer);
2818
2819 /* Handle the overlay case. */
2820 if (!NILP (overlay))
2821 {
2822 /* Find the range of text around this char that
2823 should be active. */
2824 Lisp_Object before, after;
2825 EMACS_INT ignore;
2826
2827
2828 before = Foverlay_start (overlay);
2829 after = Foverlay_end (overlay);
2830 /* Record this as the current active region. */
2831 fast_find_position (w, XFASTINT (before),
2832 &mouse_face_beg_col,
2833 &mouse_face_beg_row);
2834
2835 mouse_face_past_end
2836 = !fast_find_position (w, XFASTINT (after),
2837 &mouse_face_end_col,
2838 &mouse_face_end_row);
2839 mouse_face_window = window;
2840
2841 mouse_face_face_id
2842 = face_at_buffer_position (w, pos, 0, 0,
2843 &ignore, pos + 1, 1, -1);
2844
2845 /* Display it as active. */
2846 term_show_mouse_face (DRAW_MOUSE_FACE);
2847 }
2848 /* Handle the text property case. */
2849 else if (!NILP (mouse_face))
2850 {
2851 /* Find the range of text around this char that
2852 should be active. */
2853 Lisp_Object before, after, beginning, end;
2854 EMACS_INT ignore;
2855
2856 beginning = Fmarker_position (w->start);
2857 XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos)));
2858 before
2859 = Fprevious_single_property_change (make_number (pos + 1),
2860 Qmouse_face,
2861 w->buffer, beginning);
2862 after
2863 = Fnext_single_property_change (position, Qmouse_face,
2864 w->buffer, end);
2865
2866 /* Record this as the current active region. */
2867 fast_find_position (w, XFASTINT (before),
2868 &mouse_face_beg_col,
2869 &mouse_face_beg_row);
2870 mouse_face_past_end
2871 = !fast_find_position (w, XFASTINT (after),
2872 &mouse_face_end_col,
2873 &mouse_face_end_row);
2874 mouse_face_window = window;
2875
2876 mouse_face_face_id
2877 = face_at_buffer_position (w, pos, 0, 0,
2878 &ignore, pos + 1, 1, -1);
2879
2880 /* Display it as active. */
2881 term_show_mouse_face (DRAW_MOUSE_FACE);
2882 }
2883 }
2884
2885 /* Look for a `help-echo' property. */
2886 {
2887 Lisp_Object help;
2888
2889 /* Check overlays first. */
2890 help = Qnil;
2891 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
2892 {
2893 overlay = overlay_vec[i];
2894 help = Foverlay_get (overlay, Qhelp_echo);
2895 }
2896
2897 if (!NILP (help))
2898 {
2899 help_echo_string = help;
2900 help_echo_window = window;
2901 help_echo_object = overlay;
2902 help_echo_pos = pos;
2903 }
2904 /* Try text properties. */
2905 else if (NILP (help)
2906 && ((STRINGP (glyph->object)
2907 && glyph->charpos >= 0
2908 && glyph->charpos < SCHARS (glyph->object))
2909 || (BUFFERP (glyph->object)
2910 && glyph->charpos >= BEGV
2911 && glyph->charpos < ZV)))
2912 {
2913 help = Fget_text_property (make_number (glyph->charpos),
2914 Qhelp_echo, glyph->object);
2915 if (!NILP (help))
2916 {
2917 help_echo_string = help;
2918 help_echo_window = window;
2919 help_echo_object = glyph->object;
2920 help_echo_pos = glyph->charpos;
2921 }
2922 }
2923 }
2924
2925 BEGV = obegv;
2926 ZV = ozv;
2927 current_buffer = obuf;
2928 }
2929 }
2930} 2536}
2931 2537
2932static int 2538static int
@@ -2936,7 +2542,7 @@ term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
2936 if (event->x != last_mouse_x || event->y != last_mouse_y) 2542 if (event->x != last_mouse_x || event->y != last_mouse_y)
2937 { 2543 {
2938 frame->mouse_moved = 1; 2544 frame->mouse_moved = 1;
2939 term_mouse_highlight (frame, event->x, event->y); 2545 note_mouse_highlight (frame, event->x, event->y);
2940 /* Remember which glyph we're now on. */ 2546 /* Remember which glyph we're now on. */
2941 last_mouse_x = event->x; 2547 last_mouse_x = event->x;
2942 last_mouse_y = event->y; 2548 last_mouse_y = event->y;
@@ -3407,7 +3013,7 @@ init_tty (const char *name, const char *terminal_type, int must_succeed)
3407 3013
3408#ifdef HAVE_GPM 3014#ifdef HAVE_GPM
3409 terminal->mouse_position_hook = term_mouse_position; 3015 terminal->mouse_position_hook = term_mouse_position;
3410 mouse_face_window = Qnil; 3016 tty->mouse_highlight.mouse_face_window = Qnil;
3411#endif 3017#endif
3412 3018
3413 3019
@@ -4042,8 +3648,6 @@ bigger, or it may make it blink, or it may do nothing at all. */);
4042#ifdef HAVE_GPM 3648#ifdef HAVE_GPM
4043 defsubr (&Sgpm_mouse_start); 3649 defsubr (&Sgpm_mouse_start);
4044 defsubr (&Sgpm_mouse_stop); 3650 defsubr (&Sgpm_mouse_stop);
4045
4046 staticpro (&mouse_face_window);
4047#endif /* HAVE_GPM */ 3651#endif /* HAVE_GPM */
4048 3652
4049#ifndef DOS_NT 3653#ifndef DOS_NT