diff options
| author | Stefan Monnier | 2010-12-10 19:13:08 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2010-12-10 19:13:08 -0500 |
| commit | 2c302df3a13236bfbf8ea1b771d13618fcda8d71 (patch) | |
| tree | f26dc9f22861dc37610de319d05255de058c221b /src/xdisp.c | |
| parent | 0c747cb143fa227e78f350ac353d703f489209df (diff) | |
| parent | 175069efeb080517afefdd44a06f7a779ea8c25c (diff) | |
| download | emacs-2c302df3a13236bfbf8ea1b771d13618fcda8d71.tar.gz emacs-2c302df3a13236bfbf8ea1b771d13618fcda8d71.zip | |
Merge from trunk
Diffstat (limited to 'src/xdisp.c')
| -rw-r--r-- | src/xdisp.c | 1850 |
1 files changed, 1424 insertions, 426 deletions
diff --git a/src/xdisp.c b/src/xdisp.c index 4c007e572ce..77e9db2e5eb 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | /* Display generation from window structure and buffer text. | 1 | /* Display generation from window structure and buffer text. |
| 2 | Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, | 2 | |
| 3 | 1997, 1998, 1999, 2000, 2001, 2002, 2003, | 3 | Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1997, 1998, |
| 4 | 2004, 2005, 2006, 2007, 2008, 2009, 2010 | 4 | 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, |
| 5 | Free Software Foundation, Inc. | 5 | 2010 Free Software Foundation, Inc. |
| 6 | 6 | ||
| 7 | This file is part of GNU Emacs. | 7 | This file is part of GNU Emacs. |
| 8 | 8 | ||
| @@ -214,11 +214,41 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 214 | leftmost character with special glyphs, which will display as, | 214 | leftmost character with special glyphs, which will display as, |
| 215 | well, empty. On text terminals, these special glyphs are simply | 215 | well, empty. On text terminals, these special glyphs are simply |
| 216 | blank characters. On graphics terminals, there's a single stretch | 216 | blank characters. On graphics terminals, there's a single stretch |
| 217 | glyph with suitably computed width. Both the blanks and the | 217 | glyph of a suitably computed width. Both the blanks and the |
| 218 | stretch glyph are given the face of the background of the line. | 218 | stretch glyph are given the face of the background of the line. |
| 219 | This way, the terminal-specific back-end can still draw the glyphs | 219 | This way, the terminal-specific back-end can still draw the glyphs |
| 220 | left to right, even for R2L lines. | 220 | left to right, even for R2L lines. |
| 221 | 221 | ||
| 222 | Bidirectional display and character compositions | ||
| 223 | |||
| 224 | Some scripts cannot be displayed by drawing each character | ||
| 225 | individually, because adjacent characters change each other's shape | ||
| 226 | on display. For example, Arabic and Indic scripts belong to this | ||
| 227 | category. | ||
| 228 | |||
| 229 | Emacs display supports this by providing "character compositions", | ||
| 230 | most of which is implemented in composite.c. During the buffer | ||
| 231 | scan that delivers characters to PRODUCE_GLYPHS, if the next | ||
| 232 | character to be delivered is a composed character, the iteration | ||
| 233 | calls composition_reseat_it and next_element_from_composition. If | ||
| 234 | they succeed to compose the character with one or more of the | ||
| 235 | following characters, the whole sequence of characters that where | ||
| 236 | composed is recorded in the `struct composition_it' object that is | ||
| 237 | part of the buffer iterator. The composed sequence could produce | ||
| 238 | one or more font glyphs (called "grapheme clusters") on the screen. | ||
| 239 | Each of these grapheme clusters is then delivered to PRODUCE_GLYPHS | ||
| 240 | in the direction corresponding to the current bidi scan direction | ||
| 241 | (recorded in the scan_dir member of the `struct bidi_it' object | ||
| 242 | that is part of the buffer iterator). In particular, if the bidi | ||
| 243 | iterator currently scans the buffer backwards, the grapheme | ||
| 244 | clusters are delivered back to front. This reorders the grapheme | ||
| 245 | clusters as appropriate for the current bidi context. Note that | ||
| 246 | this means that the grapheme clusters are always stored in the | ||
| 247 | LGSTRING object (see composite.c) in the logical order. | ||
| 248 | |||
| 249 | Moving an iterator in bidirectional text | ||
| 250 | without producing glyphs | ||
| 251 | |||
| 222 | Note one important detail mentioned above: that the bidi reordering | 252 | Note one important detail mentioned above: that the bidi reordering |
| 223 | engine, driven by the iterator, produces characters in R2L rows | 253 | engine, driven by the iterator, produces characters in R2L rows |
| 224 | starting at the character that will be the rightmost on display. | 254 | starting at the character that will be the rightmost on display. |
| @@ -888,6 +918,9 @@ static int clear_face_cache_count; | |||
| 888 | #ifdef HAVE_WINDOW_SYSTEM | 918 | #ifdef HAVE_WINDOW_SYSTEM |
| 889 | #define CLEAR_IMAGE_CACHE_COUNT 101 | 919 | #define CLEAR_IMAGE_CACHE_COUNT 101 |
| 890 | static int clear_image_cache_count; | 920 | static int clear_image_cache_count; |
| 921 | |||
| 922 | /* Null glyph slice */ | ||
| 923 | static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 }; | ||
| 891 | #endif | 924 | #endif |
| 892 | 925 | ||
| 893 | /* Non-zero while redisplay_internal is in progress. */ | 926 | /* Non-zero while redisplay_internal is in progress. */ |
| @@ -913,10 +946,6 @@ EMACS_INT help_echo_pos; | |||
| 913 | 946 | ||
| 914 | Lisp_Object previous_help_echo_string; | 947 | Lisp_Object previous_help_echo_string; |
| 915 | 948 | ||
| 916 | /* Null glyph slice */ | ||
| 917 | |||
| 918 | static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 }; | ||
| 919 | |||
| 920 | /* Platform-independent portion of hourglass implementation. */ | 949 | /* Platform-independent portion of hourglass implementation. */ |
| 921 | 950 | ||
| 922 | /* Non-zero means we're allowed to display a hourglass pointer. */ | 951 | /* Non-zero means we're allowed to display a hourglass pointer. */ |
| @@ -932,6 +961,21 @@ struct atimer *hourglass_atimer; | |||
| 932 | /* Number of seconds to wait before displaying an hourglass cursor. */ | 961 | /* Number of seconds to wait before displaying an hourglass cursor. */ |
| 933 | Lisp_Object Vhourglass_delay; | 962 | Lisp_Object Vhourglass_delay; |
| 934 | 963 | ||
| 964 | /* Name of the face used to display glyphless characters. */ | ||
| 965 | Lisp_Object Qglyphless_char; | ||
| 966 | |||
| 967 | /* Char-table to control the display of glyphless characters. */ | ||
| 968 | Lisp_Object Vglyphless_char_display; | ||
| 969 | |||
| 970 | /* Symbol for the purpose of Vglyphless_char_display. */ | ||
| 971 | Lisp_Object Qglyphless_char_display; | ||
| 972 | |||
| 973 | /* Method symbols for Vglyphless_char_display. */ | ||
| 974 | static Lisp_Object Qhex_code, Qempty_box, Qthin_space, Qzero_width; | ||
| 975 | |||
| 976 | /* Default pixel width of `thin-space' display method. */ | ||
| 977 | #define THIN_SPACE_WIDTH 1 | ||
| 978 | |||
| 935 | /* Default number of seconds to wait before displaying an hourglass | 979 | /* Default number of seconds to wait before displaying an hourglass |
| 936 | cursor. */ | 980 | cursor. */ |
| 937 | #define DEFAULT_HOURGLASS_DELAY 1 | 981 | #define DEFAULT_HOURGLASS_DELAY 1 |
| @@ -960,10 +1004,8 @@ static int text_outside_line_unchanged_p (struct window *, | |||
| 960 | EMACS_INT, EMACS_INT); | 1004 | EMACS_INT, EMACS_INT); |
| 961 | static void store_mode_line_noprop_char (char); | 1005 | static void store_mode_line_noprop_char (char); |
| 962 | static int store_mode_line_noprop (const unsigned char *, int, int); | 1006 | static int store_mode_line_noprop (const unsigned char *, int, int); |
| 963 | static void x_consider_frame_title (Lisp_Object); | ||
| 964 | static void handle_stop (struct it *); | 1007 | static void handle_stop (struct it *); |
| 965 | static void handle_stop_backwards (struct it *, EMACS_INT); | 1008 | static void handle_stop_backwards (struct it *, EMACS_INT); |
| 966 | static int tool_bar_lines_needed (struct frame *, int *); | ||
| 967 | static int single_display_spec_intangible_p (Lisp_Object); | 1009 | static int single_display_spec_intangible_p (Lisp_Object); |
| 968 | static void ensure_echo_area_buffers (void); | 1010 | static void ensure_echo_area_buffers (void); |
| 969 | static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object); | 1011 | static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object); |
| @@ -1076,6 +1118,8 @@ static int in_ellipses_for_invisible_text_p (struct display_pos *, | |||
| 1076 | 1118 | ||
| 1077 | #ifdef HAVE_WINDOW_SYSTEM | 1119 | #ifdef HAVE_WINDOW_SYSTEM |
| 1078 | 1120 | ||
| 1121 | static void x_consider_frame_title (Lisp_Object); | ||
| 1122 | static int tool_bar_lines_needed (struct frame *, int *); | ||
| 1079 | static void update_tool_bar (struct frame *, int); | 1123 | static void update_tool_bar (struct frame *, int); |
| 1080 | static void build_desired_tool_bar_string (struct frame *f); | 1124 | static void build_desired_tool_bar_string (struct frame *f); |
| 1081 | static int redisplay_tool_bar (struct frame *); | 1125 | static int redisplay_tool_bar (struct frame *); |
| @@ -1087,9 +1131,11 @@ static void append_stretch_glyph (struct it *, Lisp_Object, | |||
| 1087 | int, int, int); | 1131 | int, int, int); |
| 1088 | 1132 | ||
| 1089 | 1133 | ||
| 1090 | |||
| 1091 | #endif /* HAVE_WINDOW_SYSTEM */ | 1134 | #endif /* HAVE_WINDOW_SYSTEM */ |
| 1092 | 1135 | ||
| 1136 | static int coords_in_mouse_face_p (struct window *, int, int); | ||
| 1137 | |||
| 1138 | |||
| 1093 | 1139 | ||
| 1094 | /*********************************************************************** | 1140 | /*********************************************************************** |
| 1095 | Window display dimensions | 1141 | Window display dimensions |
| @@ -1781,8 +1827,6 @@ glyph_to_pixel_coords (struct window *w, int hpos, int vpos, | |||
| 1781 | } | 1827 | } |
| 1782 | 1828 | ||
| 1783 | 1829 | ||
| 1784 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 1785 | |||
| 1786 | /* Find the glyph under window-relative coordinates X/Y in window W. | 1830 | /* Find the glyph under window-relative coordinates X/Y in window W. |
| 1787 | Consider only glyphs from buffer text, i.e. no glyphs from overlay | 1831 | Consider only glyphs from buffer text, i.e. no glyphs from overlay |
| 1788 | strings. Return in *HPOS and *VPOS the row and column number of | 1832 | strings. Return in *HPOS and *VPOS the row and column number of |
| @@ -1865,7 +1909,6 @@ x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos, | |||
| 1865 | return glyph; | 1909 | return glyph; |
| 1866 | } | 1910 | } |
| 1867 | 1911 | ||
| 1868 | |||
| 1869 | /* EXPORT: | 1912 | /* EXPORT: |
| 1870 | Convert frame-relative x/y to coordinates relative to window W. | 1913 | Convert frame-relative x/y to coordinates relative to window W. |
| 1871 | Takes pseudo-windows into account. */ | 1914 | Takes pseudo-windows into account. */ |
| @@ -1888,6 +1931,8 @@ frame_to_window_pixel_xy (struct window *w, int *x, int *y) | |||
| 1888 | } | 1931 | } |
| 1889 | } | 1932 | } |
| 1890 | 1933 | ||
| 1934 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 1935 | |||
| 1891 | /* EXPORT: | 1936 | /* EXPORT: |
| 1892 | Return in RECTS[] at most N clipping rectangles for glyph string S. | 1937 | Return in RECTS[] at most N clipping rectangles for glyph string S. |
| 1893 | Return the number of stored rectangles. */ | 1938 | Return the number of stored rectangles. */ |
| @@ -2173,7 +2218,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) | |||
| 2173 | frame pixel coordinates X/Y on frame F. */ | 2218 | frame pixel coordinates X/Y on frame F. */ |
| 2174 | 2219 | ||
| 2175 | if (!f->glyphs_initialized_p | 2220 | if (!f->glyphs_initialized_p |
| 2176 | || (window = window_from_coordinates (f, gx, gy, &part, &x, &y, 0), | 2221 | || (window = window_from_coordinates (f, gx, gy, &part, 0), |
| 2177 | NILP (window))) | 2222 | NILP (window))) |
| 2178 | { | 2223 | { |
| 2179 | width = FRAME_SMALLEST_CHAR_WIDTH (f); | 2224 | width = FRAME_SMALLEST_CHAR_WIDTH (f); |
| @@ -2185,6 +2230,9 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect) | |||
| 2185 | width = WINDOW_FRAME_COLUMN_WIDTH (w); | 2230 | width = WINDOW_FRAME_COLUMN_WIDTH (w); |
| 2186 | height = WINDOW_FRAME_LINE_HEIGHT (w); | 2231 | height = WINDOW_FRAME_LINE_HEIGHT (w); |
| 2187 | 2232 | ||
| 2233 | x = window_relative_x_coord (w, part, gx); | ||
| 2234 | y = gy - WINDOW_TOP_EDGE_Y (w); | ||
| 2235 | |||
| 2188 | r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | 2236 | r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); |
| 2189 | end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w); | 2237 | end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w); |
| 2190 | 2238 | ||
| @@ -5731,6 +5779,57 @@ static int (* get_next_element[NUM_IT_METHODS]) (struct it *it) = | |||
| 5731 | (IT)->string))) | 5779 | (IT)->string))) |
| 5732 | 5780 | ||
| 5733 | 5781 | ||
| 5782 | /* Lookup the char-table Vglyphless_char_display for character C (-1 | ||
| 5783 | if we want information for no-font case), and return the display | ||
| 5784 | method symbol. By side-effect, update it->what and | ||
| 5785 | it->glyphless_method. This function is called from | ||
| 5786 | get_next_display_element for each character element, and from | ||
| 5787 | x_produce_glyphs when no suitable font was found. */ | ||
| 5788 | |||
| 5789 | Lisp_Object | ||
| 5790 | lookup_glyphless_char_display (int c, struct it *it) | ||
| 5791 | { | ||
| 5792 | Lisp_Object glyphless_method = Qnil; | ||
| 5793 | |||
| 5794 | if (CHAR_TABLE_P (Vglyphless_char_display) | ||
| 5795 | && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) >= 1) | ||
| 5796 | glyphless_method = (c >= 0 | ||
| 5797 | ? CHAR_TABLE_REF (Vglyphless_char_display, c) | ||
| 5798 | : XCHAR_TABLE (Vglyphless_char_display)->extras[0]); | ||
| 5799 | retry: | ||
| 5800 | if (NILP (glyphless_method)) | ||
| 5801 | { | ||
| 5802 | if (c >= 0) | ||
| 5803 | /* The default is to display the character by a proper font. */ | ||
| 5804 | return Qnil; | ||
| 5805 | /* The default for the no-font case is to display an empty box. */ | ||
| 5806 | glyphless_method = Qempty_box; | ||
| 5807 | } | ||
| 5808 | if (EQ (glyphless_method, Qzero_width)) | ||
| 5809 | { | ||
| 5810 | if (c >= 0) | ||
| 5811 | return glyphless_method; | ||
| 5812 | /* This method can't be used for the no-font case. */ | ||
| 5813 | glyphless_method = Qempty_box; | ||
| 5814 | } | ||
| 5815 | if (EQ (glyphless_method, Qthin_space)) | ||
| 5816 | it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE; | ||
| 5817 | else if (EQ (glyphless_method, Qempty_box)) | ||
| 5818 | it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX; | ||
| 5819 | else if (EQ (glyphless_method, Qhex_code)) | ||
| 5820 | it->glyphless_method = GLYPHLESS_DISPLAY_HEX_CODE; | ||
| 5821 | else if (STRINGP (glyphless_method)) | ||
| 5822 | it->glyphless_method = GLYPHLESS_DISPLAY_ACRONYM; | ||
| 5823 | else | ||
| 5824 | { | ||
| 5825 | /* Invalid value. We use the default method. */ | ||
| 5826 | glyphless_method = Qnil; | ||
| 5827 | goto retry; | ||
| 5828 | } | ||
| 5829 | it->what = IT_GLYPHLESS; | ||
| 5830 | return glyphless_method; | ||
| 5831 | } | ||
| 5832 | |||
| 5734 | /* Load IT's display element fields with information about the next | 5833 | /* Load IT's display element fields with information about the next |
| 5735 | display element from the current position of IT. Value is zero if | 5834 | display element from the current position of IT. Value is zero if |
| 5736 | end of buffer (or C string) is reached. */ | 5835 | end of buffer (or C string) is reached. */ |
| @@ -5739,6 +5838,10 @@ static struct frame *last_escape_glyph_frame = NULL; | |||
| 5739 | static unsigned last_escape_glyph_face_id = (1 << FACE_ID_BITS); | 5838 | static unsigned last_escape_glyph_face_id = (1 << FACE_ID_BITS); |
| 5740 | static int last_escape_glyph_merged_face_id = 0; | 5839 | static int last_escape_glyph_merged_face_id = 0; |
| 5741 | 5840 | ||
| 5841 | struct frame *last_glyphless_glyph_frame = NULL; | ||
| 5842 | unsigned last_glyphless_glyph_face_id = (1 << FACE_ID_BITS); | ||
| 5843 | int last_glyphless_glyph_merged_face_id = 0; | ||
| 5844 | |||
| 5742 | int | 5845 | int |
| 5743 | get_next_display_element (struct it *it) | 5846 | get_next_display_element (struct it *it) |
| 5744 | { | 5847 | { |
| @@ -5817,6 +5920,15 @@ get_next_display_element (struct it *it) | |||
| 5817 | goto get_next; | 5920 | goto get_next; |
| 5818 | } | 5921 | } |
| 5819 | 5922 | ||
| 5923 | if (! NILP (lookup_glyphless_char_display (c, it))) | ||
| 5924 | { | ||
| 5925 | if (it->what == IT_GLYPHLESS) | ||
| 5926 | goto done; | ||
| 5927 | /* Don't display this character. */ | ||
| 5928 | set_iterator_to_next (it, 0); | ||
| 5929 | goto get_next; | ||
| 5930 | } | ||
| 5931 | |||
| 5820 | if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display)) | 5932 | if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display)) |
| 5821 | nbsp_or_shy = (c == 0xA0 ? char_is_nbsp | 5933 | nbsp_or_shy = (c == 0xA0 ? char_is_nbsp |
| 5822 | : c == 0xAD ? char_is_soft_hyphen | 5934 | : c == 0xAD ? char_is_soft_hyphen |
| @@ -6031,6 +6143,7 @@ get_next_display_element (struct it *it) | |||
| 6031 | } | 6143 | } |
| 6032 | #endif | 6144 | #endif |
| 6033 | 6145 | ||
| 6146 | done: | ||
| 6034 | /* Is this character the last one of a run of characters with | 6147 | /* Is this character the last one of a run of characters with |
| 6035 | box? If yes, set IT->end_of_box_run_p to 1. */ | 6148 | box? If yes, set IT->end_of_box_run_p to 1. */ |
| 6036 | if (it->face_box_p | 6149 | if (it->face_box_p |
| @@ -9271,6 +9384,8 @@ set_message_1 (EMACS_INT a1, Lisp_Object a2, EMACS_INT nbytes, EMACS_INT multiby | |||
| 9271 | Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil); | 9384 | Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil); |
| 9272 | 9385 | ||
| 9273 | current_buffer->truncate_lines = message_truncate_lines ? Qt : Qnil; | 9386 | current_buffer->truncate_lines = message_truncate_lines ? Qt : Qnil; |
| 9387 | if (!NILP (current_buffer->bidi_display_reordering)) | ||
| 9388 | current_buffer->bidi_paragraph_direction = Qleft_to_right; | ||
| 9274 | 9389 | ||
| 9275 | /* Insert new message at BEG. */ | 9390 | /* Insert new message at BEG. */ |
| 9276 | TEMP_SET_PT_BOTH (BEG, BEG_BYTE); | 9391 | TEMP_SET_PT_BOTH (BEG, BEG_BYTE); |
| @@ -10737,7 +10852,7 @@ static int | |||
| 10737 | get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph, | 10852 | get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph, |
| 10738 | int *hpos, int *vpos, int *prop_idx) | 10853 | int *hpos, int *vpos, int *prop_idx) |
| 10739 | { | 10854 | { |
| 10740 | Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | 10855 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); |
| 10741 | struct window *w = XWINDOW (f->tool_bar_window); | 10856 | struct window *w = XWINDOW (f->tool_bar_window); |
| 10742 | int area; | 10857 | int area; |
| 10743 | 10858 | ||
| @@ -10752,14 +10867,14 @@ get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph, | |||
| 10752 | return -1; | 10867 | return -1; |
| 10753 | 10868 | ||
| 10754 | /* Is mouse on the highlighted item? */ | 10869 | /* Is mouse on the highlighted item? */ |
| 10755 | if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window) | 10870 | if (EQ (f->tool_bar_window, hlinfo->mouse_face_window) |
| 10756 | && *vpos >= dpyinfo->mouse_face_beg_row | 10871 | && *vpos >= hlinfo->mouse_face_beg_row |
| 10757 | && *vpos <= dpyinfo->mouse_face_end_row | 10872 | && *vpos <= hlinfo->mouse_face_end_row |
| 10758 | && (*vpos > dpyinfo->mouse_face_beg_row | 10873 | && (*vpos > hlinfo->mouse_face_beg_row |
| 10759 | || *hpos >= dpyinfo->mouse_face_beg_col) | 10874 | || *hpos >= hlinfo->mouse_face_beg_col) |
| 10760 | && (*vpos < dpyinfo->mouse_face_end_row | 10875 | && (*vpos < hlinfo->mouse_face_end_row |
| 10761 | || *hpos < dpyinfo->mouse_face_end_col | 10876 | || *hpos < hlinfo->mouse_face_end_col |
| 10762 | || dpyinfo->mouse_face_past_end)) | 10877 | || hlinfo->mouse_face_past_end)) |
| 10763 | return 0; | 10878 | return 0; |
| 10764 | 10879 | ||
| 10765 | return 1; | 10880 | return 1; |
| @@ -10776,7 +10891,7 @@ void | |||
| 10776 | handle_tool_bar_click (struct frame *f, int x, int y, int down_p, | 10891 | handle_tool_bar_click (struct frame *f, int x, int y, int down_p, |
| 10777 | unsigned int modifiers) | 10892 | unsigned int modifiers) |
| 10778 | { | 10893 | { |
| 10779 | Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | 10894 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); |
| 10780 | struct window *w = XWINDOW (f->tool_bar_window); | 10895 | struct window *w = XWINDOW (f->tool_bar_window); |
| 10781 | int hpos, vpos, prop_idx; | 10896 | int hpos, vpos, prop_idx; |
| 10782 | struct glyph *glyph; | 10897 | struct glyph *glyph; |
| @@ -10795,8 +10910,8 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, | |||
| 10795 | if (down_p) | 10910 | if (down_p) |
| 10796 | { | 10911 | { |
| 10797 | /* Show item in pressed state. */ | 10912 | /* Show item in pressed state. */ |
| 10798 | show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN); | 10913 | show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN); |
| 10799 | dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN; | 10914 | hlinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN; |
| 10800 | last_tool_bar_item = prop_idx; | 10915 | last_tool_bar_item = prop_idx; |
| 10801 | } | 10916 | } |
| 10802 | else | 10917 | else |
| @@ -10806,8 +10921,8 @@ handle_tool_bar_click (struct frame *f, int x, int y, int down_p, | |||
| 10806 | EVENT_INIT (event); | 10921 | EVENT_INIT (event); |
| 10807 | 10922 | ||
| 10808 | /* Show item in released state. */ | 10923 | /* Show item in released state. */ |
| 10809 | show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED); | 10924 | show_mouse_face (hlinfo, DRAW_IMAGE_RAISED); |
| 10810 | dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED; | 10925 | hlinfo->mouse_face_image_state = DRAW_IMAGE_RAISED; |
| 10811 | 10926 | ||
| 10812 | key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY); | 10927 | key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY); |
| 10813 | 10928 | ||
| @@ -10837,6 +10952,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y) | |||
| 10837 | Lisp_Object window = f->tool_bar_window; | 10952 | Lisp_Object window = f->tool_bar_window; |
| 10838 | struct window *w = XWINDOW (window); | 10953 | struct window *w = XWINDOW (window); |
| 10839 | Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | 10954 | Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); |
| 10955 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); | ||
| 10840 | int hpos, vpos; | 10956 | int hpos, vpos; |
| 10841 | struct glyph *glyph; | 10957 | struct glyph *glyph; |
| 10842 | struct glyph_row *row; | 10958 | struct glyph_row *row; |
| @@ -10850,7 +10966,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y) | |||
| 10850 | values when mouse moves outside of the frame. */ | 10966 | values when mouse moves outside of the frame. */ |
| 10851 | if (x <= 0 || y <= 0) | 10967 | if (x <= 0 || y <= 0) |
| 10852 | { | 10968 | { |
| 10853 | clear_mouse_face (dpyinfo); | 10969 | clear_mouse_face (hlinfo); |
| 10854 | return; | 10970 | return; |
| 10855 | } | 10971 | } |
| 10856 | 10972 | ||
| @@ -10858,14 +10974,14 @@ note_tool_bar_highlight (struct frame *f, int x, int y) | |||
| 10858 | if (rc < 0) | 10974 | if (rc < 0) |
| 10859 | { | 10975 | { |
| 10860 | /* Not on tool-bar item. */ | 10976 | /* Not on tool-bar item. */ |
| 10861 | clear_mouse_face (dpyinfo); | 10977 | clear_mouse_face (hlinfo); |
| 10862 | return; | 10978 | return; |
| 10863 | } | 10979 | } |
| 10864 | else if (rc == 0) | 10980 | else if (rc == 0) |
| 10865 | /* On same tool-bar item as before. */ | 10981 | /* On same tool-bar item as before. */ |
| 10866 | goto set_help_echo; | 10982 | goto set_help_echo; |
| 10867 | 10983 | ||
| 10868 | clear_mouse_face (dpyinfo); | 10984 | clear_mouse_face (hlinfo); |
| 10869 | 10985 | ||
| 10870 | /* Mouse is down, but on different tool-bar item? */ | 10986 | /* Mouse is down, but on different tool-bar item? */ |
| 10871 | mouse_down_p = (dpyinfo->grabbed | 10987 | mouse_down_p = (dpyinfo->grabbed |
| @@ -10875,7 +10991,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y) | |||
| 10875 | && last_tool_bar_item != prop_idx) | 10991 | && last_tool_bar_item != prop_idx) |
| 10876 | return; | 10992 | return; |
| 10877 | 10993 | ||
| 10878 | dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT; | 10994 | hlinfo->mouse_face_image_state = DRAW_NORMAL_TEXT; |
| 10879 | draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED; | 10995 | draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED; |
| 10880 | 10996 | ||
| 10881 | /* If tool-bar item is not enabled, don't highlight it. */ | 10997 | /* If tool-bar item is not enabled, don't highlight it. */ |
| @@ -10889,22 +11005,22 @@ note_tool_bar_highlight (struct frame *f, int x, int y) | |||
| 10889 | x += row->glyphs[TEXT_AREA][i].pixel_width; | 11005 | x += row->glyphs[TEXT_AREA][i].pixel_width; |
| 10890 | 11006 | ||
| 10891 | /* Record this as the current active region. */ | 11007 | /* Record this as the current active region. */ |
| 10892 | dpyinfo->mouse_face_beg_col = hpos; | 11008 | hlinfo->mouse_face_beg_col = hpos; |
| 10893 | dpyinfo->mouse_face_beg_row = vpos; | 11009 | hlinfo->mouse_face_beg_row = vpos; |
| 10894 | dpyinfo->mouse_face_beg_x = x; | 11010 | hlinfo->mouse_face_beg_x = x; |
| 10895 | dpyinfo->mouse_face_beg_y = row->y; | 11011 | hlinfo->mouse_face_beg_y = row->y; |
| 10896 | dpyinfo->mouse_face_past_end = 0; | 11012 | hlinfo->mouse_face_past_end = 0; |
| 10897 | 11013 | ||
| 10898 | dpyinfo->mouse_face_end_col = hpos + 1; | 11014 | hlinfo->mouse_face_end_col = hpos + 1; |
| 10899 | dpyinfo->mouse_face_end_row = vpos; | 11015 | hlinfo->mouse_face_end_row = vpos; |
| 10900 | dpyinfo->mouse_face_end_x = x + glyph->pixel_width; | 11016 | hlinfo->mouse_face_end_x = x + glyph->pixel_width; |
| 10901 | dpyinfo->mouse_face_end_y = row->y; | 11017 | hlinfo->mouse_face_end_y = row->y; |
| 10902 | dpyinfo->mouse_face_window = window; | 11018 | hlinfo->mouse_face_window = window; |
| 10903 | dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID; | 11019 | hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID; |
| 10904 | 11020 | ||
| 10905 | /* Display it as active. */ | 11021 | /* Display it as active. */ |
| 10906 | show_mouse_face (dpyinfo, draw); | 11022 | show_mouse_face (hlinfo, draw); |
| 10907 | dpyinfo->mouse_face_image_state = draw; | 11023 | hlinfo->mouse_face_image_state = draw; |
| 10908 | } | 11024 | } |
| 10909 | 11025 | ||
| 10910 | set_help_echo: | 11026 | set_help_echo: |
| @@ -11578,6 +11694,8 @@ redisplay_internal (int preserve_echo_area) | |||
| 11578 | reconsider_clip_changes (w, current_buffer); | 11694 | reconsider_clip_changes (w, current_buffer); |
| 11579 | last_escape_glyph_frame = NULL; | 11695 | last_escape_glyph_frame = NULL; |
| 11580 | last_escape_glyph_face_id = (1 << FACE_ID_BITS); | 11696 | last_escape_glyph_face_id = (1 << FACE_ID_BITS); |
| 11697 | last_glyphless_glyph_frame = NULL; | ||
| 11698 | last_glyphless_glyph_face_id = (1 << FACE_ID_BITS); | ||
| 11581 | 11699 | ||
| 11582 | /* If new fonts have been loaded that make a glyph matrix adjustment | 11700 | /* If new fonts have been loaded that make a glyph matrix adjustment |
| 11583 | necessary, do it. */ | 11701 | necessary, do it. */ |
| @@ -12723,6 +12841,15 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, | |||
| 12723 | && BUFFERP (glyph->object) && glyph->charpos == pt_old) | 12841 | && BUFFERP (glyph->object) && glyph->charpos == pt_old) |
| 12724 | && bpos_covered < pt_old) | 12842 | && bpos_covered < pt_old) |
| 12725 | { | 12843 | { |
| 12844 | /* An empty line has a single glyph whose OBJECT is zero and | ||
| 12845 | whose CHARPOS is the position of a newline on that line. | ||
| 12846 | Note that on a TTY, there are more glyphs after that, which | ||
| 12847 | were produced by extend_face_to_end_of_line, but their | ||
| 12848 | CHARPOS is zero or negative. */ | ||
| 12849 | int empty_line_p = | ||
| 12850 | (row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end) | ||
| 12851 | && INTEGERP (glyph->object) && glyph->charpos > 0; | ||
| 12852 | |||
| 12726 | if (row->ends_in_ellipsis_p && pos_after == last_pos) | 12853 | if (row->ends_in_ellipsis_p && pos_after == last_pos) |
| 12727 | { | 12854 | { |
| 12728 | EMACS_INT ellipsis_pos; | 12855 | EMACS_INT ellipsis_pos; |
| @@ -12758,10 +12885,11 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, | |||
| 12758 | || (row->truncated_on_left_p && pt_old < bpos_min) | 12885 | || (row->truncated_on_left_p && pt_old < bpos_min) |
| 12759 | || (row->truncated_on_right_p && pt_old > bpos_max) | 12886 | || (row->truncated_on_right_p && pt_old > bpos_max) |
| 12760 | /* Zero-width characters produce no glyphs. */ | 12887 | /* Zero-width characters produce no glyphs. */ |
| 12761 | || ((row->reversed_p | 12888 | || (!string_seen |
| 12762 | ? glyph_after > glyphs_end | 12889 | && !empty_line_p |
| 12763 | : glyph_after < glyphs_end) | 12890 | && (row->reversed_p |
| 12764 | && eabs (glyph_after - glyph_before) == 1)) | 12891 | ? glyph_after > glyphs_end |
| 12892 | : glyph_after < glyphs_end))) | ||
| 12765 | { | 12893 | { |
| 12766 | cursor = glyph_after; | 12894 | cursor = glyph_after; |
| 12767 | x = -1; | 12895 | x = -1; |
| @@ -12815,8 +12943,9 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, | |||
| 12815 | cursor on that character's glyph. */ | 12943 | cursor on that character's glyph. */ |
| 12816 | EMACS_INT strpos = glyph->charpos; | 12944 | EMACS_INT strpos = glyph->charpos; |
| 12817 | 12945 | ||
| 12818 | cursor = glyph; | 12946 | if (tem) |
| 12819 | for (glyph += incr; | 12947 | cursor = glyph; |
| 12948 | for ( ; | ||
| 12820 | (row->reversed_p ? glyph > stop : glyph < stop) | 12949 | (row->reversed_p ? glyph > stop : glyph < stop) |
| 12821 | && EQ (glyph->object, str); | 12950 | && EQ (glyph->object, str); |
| 12822 | glyph += incr) | 12951 | glyph += incr) |
| @@ -12832,7 +12961,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, | |||
| 12832 | cursor = glyph; | 12961 | cursor = glyph; |
| 12833 | break; | 12962 | break; |
| 12834 | } | 12963 | } |
| 12835 | if (glyph->charpos < strpos) | 12964 | if (tem && glyph->charpos < strpos) |
| 12836 | { | 12965 | { |
| 12837 | strpos = glyph->charpos; | 12966 | strpos = glyph->charpos; |
| 12838 | cursor = glyph; | 12967 | cursor = glyph; |
| @@ -12847,10 +12976,9 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, | |||
| 12847 | } | 12976 | } |
| 12848 | /* This string is not what we want; skip all of the | 12977 | /* This string is not what we want; skip all of the |
| 12849 | glyphs that came from it. */ | 12978 | glyphs that came from it. */ |
| 12850 | do | ||
| 12851 | glyph += incr; | ||
| 12852 | while ((row->reversed_p ? glyph > stop : glyph < stop) | 12979 | while ((row->reversed_p ? glyph > stop : glyph < stop) |
| 12853 | && EQ (glyph->object, str)); | 12980 | && EQ (glyph->object, str)) |
| 12981 | glyph += incr; | ||
| 12854 | } | 12982 | } |
| 12855 | else | 12983 | else |
| 12856 | glyph += incr; | 12984 | glyph += incr; |
| @@ -15333,10 +15461,12 @@ row_containing_pos (struct window *w, EMACS_INT charpos, | |||
| 15333 | { | 15461 | { |
| 15334 | struct glyph *g; | 15462 | struct glyph *g; |
| 15335 | 15463 | ||
| 15336 | if (NILP (XBUFFER (w->buffer)->bidi_display_reordering)) | 15464 | if (NILP (XBUFFER (w->buffer)->bidi_display_reordering) |
| 15465 | || (!best_row && !row->continued_p)) | ||
| 15337 | return row; | 15466 | return row; |
| 15338 | /* In bidi-reordered rows, there could be several rows | 15467 | /* In bidi-reordered rows, there could be several rows |
| 15339 | occluding point. We need to find the one which fits | 15468 | occluding point, all of them belonging to the same |
| 15469 | continued line. We need to find the row which fits | ||
| 15340 | CHARPOS the best. */ | 15470 | CHARPOS the best. */ |
| 15341 | for (g = row->glyphs[TEXT_AREA]; | 15471 | for (g = row->glyphs[TEXT_AREA]; |
| 15342 | g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; | 15472 | g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]; |
| @@ -15348,11 +15478,14 @@ row_containing_pos (struct window *w, EMACS_INT charpos, | |||
| 15348 | { | 15478 | { |
| 15349 | mindif = eabs (g->charpos - charpos); | 15479 | mindif = eabs (g->charpos - charpos); |
| 15350 | best_row = row; | 15480 | best_row = row; |
| 15481 | /* Exact match always wins. */ | ||
| 15482 | if (mindif == 0) | ||
| 15483 | return best_row; | ||
| 15351 | } | 15484 | } |
| 15352 | } | 15485 | } |
| 15353 | } | 15486 | } |
| 15354 | } | 15487 | } |
| 15355 | else if (best_row) | 15488 | else if (best_row && !row->continued_p) |
| 15356 | return best_row; | 15489 | return best_row; |
| 15357 | ++row; | 15490 | ++row; |
| 15358 | } | 15491 | } |
| @@ -15897,6 +16030,9 @@ try_window_id (struct window *w) | |||
| 15897 | + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0) | 16030 | + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0) |
| 15898 | + window_internal_height (w)); | 16031 | + window_internal_height (w)); |
| 15899 | 16032 | ||
| 16033 | #if defined (HAVE_GPM) || defined (MSDOS) | ||
| 16034 | x_clear_window_mouse_face (w); | ||
| 16035 | #endif | ||
| 15900 | /* Perform the operation on the screen. */ | 16036 | /* Perform the operation on the screen. */ |
| 15901 | if (dvpos > 0) | 16037 | if (dvpos > 0) |
| 15902 | { | 16038 | { |
| @@ -20651,6 +20787,42 @@ fill_gstring_glyph_string (struct glyph_string *s, int face_id, | |||
| 20651 | } | 20787 | } |
| 20652 | 20788 | ||
| 20653 | 20789 | ||
| 20790 | /* Fill glyph string S from a sequence glyphs for glyphless characters. | ||
| 20791 | See the comment of fill_glyph_string for arguments. | ||
| 20792 | Value is the index of the first glyph not in S. */ | ||
| 20793 | |||
| 20794 | |||
| 20795 | static int | ||
| 20796 | fill_glyphless_glyph_string (struct glyph_string *s, int face_id, | ||
| 20797 | int start, int end, int overlaps) | ||
| 20798 | { | ||
| 20799 | struct glyph *glyph, *last; | ||
| 20800 | int voffset; | ||
| 20801 | |||
| 20802 | xassert (s->first_glyph->type == GLYPHLESS_GLYPH); | ||
| 20803 | s->for_overlaps = overlaps; | ||
| 20804 | glyph = s->row->glyphs[s->area] + start; | ||
| 20805 | last = s->row->glyphs[s->area] + end; | ||
| 20806 | voffset = glyph->voffset; | ||
| 20807 | s->face = FACE_FROM_ID (s->f, face_id); | ||
| 20808 | s->font = s->face->font; | ||
| 20809 | s->nchars = 1; | ||
| 20810 | s->width = glyph->pixel_width; | ||
| 20811 | glyph++; | ||
| 20812 | while (glyph < last | ||
| 20813 | && glyph->type == GLYPHLESS_GLYPH | ||
| 20814 | && glyph->voffset == voffset | ||
| 20815 | && glyph->face_id == face_id) | ||
| 20816 | { | ||
| 20817 | s->nchars++; | ||
| 20818 | s->width += glyph->pixel_width; | ||
| 20819 | glyph++; | ||
| 20820 | } | ||
| 20821 | s->ybase += voffset; | ||
| 20822 | return glyph - s->row->glyphs[s->area]; | ||
| 20823 | } | ||
| 20824 | |||
| 20825 | |||
| 20654 | /* Fill glyph string S from a sequence of character glyphs. | 20826 | /* Fill glyph string S from a sequence of character glyphs. |
| 20655 | 20827 | ||
| 20656 | FACE_ID is the face id of the string. START is the index of the | 20828 | FACE_ID is the face id of the string. START is the index of the |
| @@ -21161,6 +21333,28 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p) | |||
| 21161 | } while (0) | 21333 | } while (0) |
| 21162 | 21334 | ||
| 21163 | 21335 | ||
| 21336 | /* Add a glyph string for a sequence of glyphless character's glyphs | ||
| 21337 | to the list of strings between HEAD and TAIL. The meanings of | ||
| 21338 | arguments are the same as those of BUILD_CHAR_GLYPH_STRINGS. */ | ||
| 21339 | |||
| 21340 | #define BUILD_GLYPHLESS_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \ | ||
| 21341 | do \ | ||
| 21342 | { \ | ||
| 21343 | int face_id; \ | ||
| 21344 | XChar2b *char2b; \ | ||
| 21345 | \ | ||
| 21346 | face_id = (row)->glyphs[area][START].face_id; \ | ||
| 21347 | \ | ||
| 21348 | s = (struct glyph_string *) alloca (sizeof *s); \ | ||
| 21349 | INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \ | ||
| 21350 | append_glyph_string (&HEAD, &TAIL, s); \ | ||
| 21351 | s->x = (X); \ | ||
| 21352 | START = fill_glyphless_glyph_string (s, face_id, START, END, \ | ||
| 21353 | overlaps); \ | ||
| 21354 | } \ | ||
| 21355 | while (0) | ||
| 21356 | |||
| 21357 | |||
| 21164 | /* Build a list of glyph strings between HEAD and TAIL for the glyphs | 21358 | /* Build a list of glyph strings between HEAD and TAIL for the glyphs |
| 21165 | of AREA of glyph row ROW on window W between indices START and END. | 21359 | of AREA of glyph row ROW on window W between indices START and END. |
| 21166 | HL overrides the face for drawing glyph strings, e.g. it is | 21360 | HL overrides the face for drawing glyph strings, e.g. it is |
| @@ -21184,7 +21378,7 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p) | |||
| 21184 | BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \ | 21378 | BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \ |
| 21185 | HL, X, LAST_X); \ | 21379 | HL, X, LAST_X); \ |
| 21186 | break; \ | 21380 | break; \ |
| 21187 | \ | 21381 | \ |
| 21188 | case COMPOSITE_GLYPH: \ | 21382 | case COMPOSITE_GLYPH: \ |
| 21189 | if (first_glyph->u.cmp.automatic) \ | 21383 | if (first_glyph->u.cmp.automatic) \ |
| 21190 | BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \ | 21384 | BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \ |
| @@ -21193,21 +21387,26 @@ compute_overhangs_and_x (struct glyph_string *s, int x, int backward_p) | |||
| 21193 | BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \ | 21387 | BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \ |
| 21194 | HL, X, LAST_X); \ | 21388 | HL, X, LAST_X); \ |
| 21195 | break; \ | 21389 | break; \ |
| 21196 | \ | 21390 | \ |
| 21197 | case STRETCH_GLYPH: \ | 21391 | case STRETCH_GLYPH: \ |
| 21198 | BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \ | 21392 | BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \ |
| 21199 | HL, X, LAST_X); \ | 21393 | HL, X, LAST_X); \ |
| 21200 | break; \ | 21394 | break; \ |
| 21201 | \ | 21395 | \ |
| 21202 | case IMAGE_GLYPH: \ | 21396 | case IMAGE_GLYPH: \ |
| 21203 | BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \ | 21397 | BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \ |
| 21204 | HL, X, LAST_X); \ | 21398 | HL, X, LAST_X); \ |
| 21205 | break; \ | 21399 | break; \ |
| 21206 | \ | 21400 | \ |
| 21401 | case GLYPHLESS_GLYPH: \ | ||
| 21402 | BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \ | ||
| 21403 | HL, X, LAST_X); \ | ||
| 21404 | break; \ | ||
| 21405 | \ | ||
| 21207 | default: \ | 21406 | default: \ |
| 21208 | abort (); \ | 21407 | abort (); \ |
| 21209 | } \ | 21408 | } \ |
| 21210 | \ | 21409 | \ |
| 21211 | if (s) \ | 21410 | if (s) \ |
| 21212 | { \ | 21411 | { \ |
| 21213 | set_glyph_string_background_width (s, START, LAST_X); \ | 21412 | set_glyph_string_background_width (s, START, LAST_X); \ |
| @@ -21291,7 +21490,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, | |||
| 21291 | if (head && !overlaps && row->contains_overlapping_glyphs_p) | 21490 | if (head && !overlaps && row->contains_overlapping_glyphs_p) |
| 21292 | { | 21491 | { |
| 21293 | struct glyph_string *h, *t; | 21492 | struct glyph_string *h, *t; |
| 21294 | Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | 21493 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); |
| 21295 | int mouse_beg_col, mouse_end_col, check_mouse_face = 0; | 21494 | int mouse_beg_col, mouse_end_col, check_mouse_face = 0; |
| 21296 | int dummy_x = 0; | 21495 | int dummy_x = 0; |
| 21297 | 21496 | ||
| @@ -21301,16 +21500,16 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, | |||
| 21301 | { | 21500 | { |
| 21302 | struct glyph_row *mouse_beg_row, *mouse_end_row; | 21501 | struct glyph_row *mouse_beg_row, *mouse_end_row; |
| 21303 | 21502 | ||
| 21304 | mouse_beg_row = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row); | 21503 | mouse_beg_row = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row); |
| 21305 | mouse_end_row = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row); | 21504 | mouse_end_row = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row); |
| 21306 | 21505 | ||
| 21307 | if (row >= mouse_beg_row && row <= mouse_end_row) | 21506 | if (row >= mouse_beg_row && row <= mouse_end_row) |
| 21308 | { | 21507 | { |
| 21309 | check_mouse_face = 1; | 21508 | check_mouse_face = 1; |
| 21310 | mouse_beg_col = (row == mouse_beg_row) | 21509 | mouse_beg_col = (row == mouse_beg_row) |
| 21311 | ? dpyinfo->mouse_face_beg_col : 0; | 21510 | ? hlinfo->mouse_face_beg_col : 0; |
| 21312 | mouse_end_col = (row == mouse_end_row) | 21511 | mouse_end_col = (row == mouse_end_row) |
| 21313 | ? dpyinfo->mouse_face_end_col | 21512 | ? hlinfo->mouse_face_end_col |
| 21314 | : row->used[TEXT_AREA]; | 21513 | : row->used[TEXT_AREA]; |
| 21315 | } | 21514 | } |
| 21316 | } | 21515 | } |
| @@ -22103,6 +22302,229 @@ calc_line_height_property (struct it *it, Lisp_Object val, struct font *font, | |||
| 22103 | } | 22302 | } |
| 22104 | 22303 | ||
| 22105 | 22304 | ||
| 22305 | /* Append a glyph for a glyphless character to IT->glyph_row. FACE_ID | ||
| 22306 | is a face ID to be used for the glyph. FOR_NO_FONT is nonzero if | ||
| 22307 | and only if this is for a character for which no font was found. | ||
| 22308 | |||
| 22309 | If the display method (it->glyphless_method) is | ||
| 22310 | GLYPHLESS_DISPLAY_ACRONYM or GLYPHLESS_DISPLAY_HEX_CODE, LEN is a | ||
| 22311 | length of the acronym or the hexadecimal string, UPPER_XOFF and | ||
| 22312 | UPPER_YOFF are pixel offsets for the upper part of the string, | ||
| 22313 | LOWER_XOFF and LOWER_YOFF are for the lower part. | ||
| 22314 | |||
| 22315 | For the other display methods, LEN through LOWER_YOFF are zero. */ | ||
| 22316 | |||
| 22317 | static void | ||
| 22318 | append_glyphless_glyph (struct it *it, int face_id, int for_no_font, int len, | ||
| 22319 | short upper_xoff, short upper_yoff, | ||
| 22320 | short lower_xoff, short lower_yoff) | ||
| 22321 | { | ||
| 22322 | struct glyph *glyph; | ||
| 22323 | enum glyph_row_area area = it->area; | ||
| 22324 | |||
| 22325 | glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area]; | ||
| 22326 | if (glyph < it->glyph_row->glyphs[area + 1]) | ||
| 22327 | { | ||
| 22328 | /* If the glyph row is reversed, we need to prepend the glyph | ||
| 22329 | rather than append it. */ | ||
| 22330 | if (it->glyph_row->reversed_p && area == TEXT_AREA) | ||
| 22331 | { | ||
| 22332 | struct glyph *g; | ||
| 22333 | |||
| 22334 | /* Make room for the additional glyph. */ | ||
| 22335 | for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--) | ||
| 22336 | g[1] = *g; | ||
| 22337 | glyph = it->glyph_row->glyphs[area]; | ||
| 22338 | } | ||
| 22339 | glyph->charpos = CHARPOS (it->position); | ||
| 22340 | glyph->object = it->object; | ||
| 22341 | glyph->pixel_width = it->pixel_width; | ||
| 22342 | glyph->ascent = it->ascent; | ||
| 22343 | glyph->descent = it->descent; | ||
| 22344 | glyph->voffset = it->voffset; | ||
| 22345 | glyph->type = GLYPHLESS_GLYPH; | ||
| 22346 | glyph->u.glyphless.method = it->glyphless_method; | ||
| 22347 | glyph->u.glyphless.for_no_font = for_no_font; | ||
| 22348 | glyph->u.glyphless.len = len; | ||
| 22349 | glyph->u.glyphless.ch = it->c; | ||
| 22350 | glyph->slice.glyphless.upper_xoff = upper_xoff; | ||
| 22351 | glyph->slice.glyphless.upper_yoff = upper_yoff; | ||
| 22352 | glyph->slice.glyphless.lower_xoff = lower_xoff; | ||
| 22353 | glyph->slice.glyphless.lower_yoff = lower_yoff; | ||
| 22354 | glyph->avoid_cursor_p = it->avoid_cursor_p; | ||
| 22355 | glyph->multibyte_p = it->multibyte_p; | ||
| 22356 | glyph->left_box_line_p = it->start_of_box_run_p; | ||
| 22357 | glyph->right_box_line_p = it->end_of_box_run_p; | ||
| 22358 | glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent | ||
| 22359 | || it->phys_descent > it->descent); | ||
| 22360 | glyph->padding_p = 0; | ||
| 22361 | glyph->glyph_not_available_p = 0; | ||
| 22362 | glyph->face_id = face_id; | ||
| 22363 | glyph->font_type = FONT_TYPE_UNKNOWN; | ||
| 22364 | if (it->bidi_p) | ||
| 22365 | { | ||
| 22366 | glyph->resolved_level = it->bidi_it.resolved_level; | ||
| 22367 | if ((it->bidi_it.type & 7) != it->bidi_it.type) | ||
| 22368 | abort (); | ||
| 22369 | glyph->bidi_type = it->bidi_it.type; | ||
| 22370 | } | ||
| 22371 | ++it->glyph_row->used[area]; | ||
| 22372 | } | ||
| 22373 | else | ||
| 22374 | IT_EXPAND_MATRIX_WIDTH (it, area); | ||
| 22375 | } | ||
| 22376 | |||
| 22377 | |||
| 22378 | /* Produce a glyph for a glyphless character for iterator IT. | ||
| 22379 | IT->glyphless_method specifies which method to use for displaying | ||
| 22380 | the character. See the description of enum | ||
| 22381 | glyphless_display_method in dispextern.h for the detail. | ||
| 22382 | |||
| 22383 | FOR_NO_FONT is nonzero if and only if this is for a character for | ||
| 22384 | which no font was found. ACRONYM, if non-nil, is an acronym string | ||
| 22385 | for the character. */ | ||
| 22386 | |||
| 22387 | static void | ||
| 22388 | produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym) | ||
| 22389 | { | ||
| 22390 | int face_id; | ||
| 22391 | struct face *face; | ||
| 22392 | struct font *font; | ||
| 22393 | int base_width, base_height, width, height; | ||
| 22394 | short upper_xoff, upper_yoff, lower_xoff, lower_yoff; | ||
| 22395 | int len; | ||
| 22396 | |||
| 22397 | /* Get the metrics of the base font. We always refer to the current | ||
| 22398 | ASCII face. */ | ||
| 22399 | face = FACE_FROM_ID (it->f, it->face_id)->ascii_face; | ||
| 22400 | font = face->font ? face->font : FRAME_FONT (it->f); | ||
| 22401 | it->ascent = FONT_BASE (font) + font->baseline_offset; | ||
| 22402 | it->descent = FONT_DESCENT (font) - font->baseline_offset; | ||
| 22403 | base_height = it->ascent + it->descent; | ||
| 22404 | base_width = font->average_width; | ||
| 22405 | |||
| 22406 | /* Get a face ID for the glyph by utilizing a cache (the same way as | ||
| 22407 | doen for `escape-glyph' in get_next_display_element). */ | ||
| 22408 | if (it->f == last_glyphless_glyph_frame | ||
| 22409 | && it->face_id == last_glyphless_glyph_face_id) | ||
| 22410 | { | ||
| 22411 | face_id = last_glyphless_glyph_merged_face_id; | ||
| 22412 | } | ||
| 22413 | else | ||
| 22414 | { | ||
| 22415 | /* Merge the `glyphless-char' face into the current face. */ | ||
| 22416 | face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id); | ||
| 22417 | last_glyphless_glyph_frame = it->f; | ||
| 22418 | last_glyphless_glyph_face_id = it->face_id; | ||
| 22419 | last_glyphless_glyph_merged_face_id = face_id; | ||
| 22420 | } | ||
| 22421 | |||
| 22422 | if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE) | ||
| 22423 | { | ||
| 22424 | it->pixel_width = THIN_SPACE_WIDTH; | ||
| 22425 | len = 0; | ||
| 22426 | upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0; | ||
| 22427 | } | ||
| 22428 | else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX) | ||
| 22429 | { | ||
| 22430 | width = CHAR_WIDTH (it->c); | ||
| 22431 | if (width == 0) | ||
| 22432 | width = 1; | ||
| 22433 | else if (width > 4) | ||
| 22434 | width = 4; | ||
| 22435 | it->pixel_width = base_width * width; | ||
| 22436 | len = 0; | ||
| 22437 | upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0; | ||
| 22438 | } | ||
| 22439 | else | ||
| 22440 | { | ||
| 22441 | char buf[7], *str; | ||
| 22442 | unsigned int code[6]; | ||
| 22443 | int upper_len; | ||
| 22444 | int ascent, descent; | ||
| 22445 | struct font_metrics metrics_upper, metrics_lower; | ||
| 22446 | |||
| 22447 | face = FACE_FROM_ID (it->f, face_id); | ||
| 22448 | font = face->font ? face->font : FRAME_FONT (it->f); | ||
| 22449 | PREPARE_FACE_FOR_DISPLAY (it->f, face); | ||
| 22450 | |||
| 22451 | if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM) | ||
| 22452 | { | ||
| 22453 | if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display)) | ||
| 22454 | acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c); | ||
| 22455 | str = STRINGP (acronym) ? (char *) SDATA (acronym) : ""; | ||
| 22456 | } | ||
| 22457 | else | ||
| 22458 | { | ||
| 22459 | xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE); | ||
| 22460 | sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c); | ||
| 22461 | str = buf; | ||
| 22462 | } | ||
| 22463 | for (len = 0; str[len] && ASCII_BYTE_P (str[len]); len++) | ||
| 22464 | code[len] = font->driver->encode_char (font, str[len]); | ||
| 22465 | upper_len = (len + 1) / 2; | ||
| 22466 | font->driver->text_extents (font, code, upper_len, | ||
| 22467 | &metrics_upper); | ||
| 22468 | font->driver->text_extents (font, code + upper_len, len - upper_len, | ||
| 22469 | &metrics_lower); | ||
| 22470 | |||
| 22471 | |||
| 22472 | |||
| 22473 | /* +4 is for vertical bars of a box plus 1-pixel spaces at both side. */ | ||
| 22474 | width = max (metrics_upper.width, metrics_lower.width) + 4; | ||
| 22475 | upper_xoff = upper_yoff = 2; /* the typical case */ | ||
| 22476 | if (base_width >= width) | ||
| 22477 | { | ||
| 22478 | /* Align the upper to the left, the lower to the right. */ | ||
| 22479 | it->pixel_width = base_width; | ||
| 22480 | lower_xoff = base_width - 2 - metrics_lower.width; | ||
| 22481 | } | ||
| 22482 | else | ||
| 22483 | { | ||
| 22484 | /* Center the shorter one. */ | ||
| 22485 | it->pixel_width = width; | ||
| 22486 | if (metrics_upper.width >= metrics_lower.width) | ||
| 22487 | lower_xoff = (width - metrics_lower.width) / 2; | ||
| 22488 | else | ||
| 22489 | upper_xoff = (width - metrics_upper.width) / 2; | ||
| 22490 | } | ||
| 22491 | |||
| 22492 | /* +5 is for horizontal bars of a box plus 1-pixel spaces at | ||
| 22493 | top, bottom, and between upper and lower strings. */ | ||
| 22494 | height = (metrics_upper.ascent + metrics_upper.descent | ||
| 22495 | + metrics_lower.ascent + metrics_lower.descent) + 5; | ||
| 22496 | /* Center vertically. | ||
| 22497 | H:base_height, D:base_descent | ||
| 22498 | h:height, ld:lower_descent, la:lower_ascent, ud:upper_descent | ||
| 22499 | |||
| 22500 | ascent = - (D - H/2 - h/2 + 1); "+ 1" for rounding up | ||
| 22501 | descent = D - H/2 + h/2; | ||
| 22502 | lower_yoff = descent - 2 - ld; | ||
| 22503 | upper_yoff = lower_yoff - la - 1 - ud; */ | ||
| 22504 | ascent = - (it->descent - (base_height + height + 1) / 2); | ||
| 22505 | descent = it->descent - (base_height - height) / 2; | ||
| 22506 | lower_yoff = descent - 2 - metrics_lower.descent; | ||
| 22507 | upper_yoff = (lower_yoff - metrics_lower.ascent - 1 | ||
| 22508 | - metrics_upper.descent); | ||
| 22509 | /* Don't make the height shorter than the base height. */ | ||
| 22510 | if (height > base_height) | ||
| 22511 | { | ||
| 22512 | it->ascent = ascent; | ||
| 22513 | it->descent = descent; | ||
| 22514 | } | ||
| 22515 | } | ||
| 22516 | |||
| 22517 | it->phys_ascent = it->ascent; | ||
| 22518 | it->phys_descent = it->descent; | ||
| 22519 | if (it->glyph_row) | ||
| 22520 | append_glyphless_glyph (it, face_id, for_no_font, len, | ||
| 22521 | upper_xoff, upper_yoff, | ||
| 22522 | lower_xoff, lower_yoff); | ||
| 22523 | it->nglyphs = 1; | ||
| 22524 | take_vertical_position_into_account (it); | ||
| 22525 | } | ||
| 22526 | |||
| 22527 | |||
| 22106 | /* RIF: | 22528 | /* RIF: |
| 22107 | Produce glyphs/get display metrics for the display element IT is | 22529 | Produce glyphs/get display metrics for the display element IT is |
| 22108 | loaded with. See the description of struct it in dispextern.h | 22530 | loaded with. See the description of struct it in dispextern.h |
| @@ -22120,29 +22542,25 @@ x_produce_glyphs (struct it *it) | |||
| 22120 | XChar2b char2b; | 22542 | XChar2b char2b; |
| 22121 | struct face *face = FACE_FROM_ID (it->f, it->face_id); | 22543 | struct face *face = FACE_FROM_ID (it->f, it->face_id); |
| 22122 | struct font *font = face->font; | 22544 | struct font *font = face->font; |
| 22123 | int font_not_found_p = font == NULL; | ||
| 22124 | struct font_metrics *pcm = NULL; | 22545 | struct font_metrics *pcm = NULL; |
| 22125 | int boff; /* baseline offset */ | 22546 | int boff; /* baseline offset */ |
| 22126 | 22547 | ||
| 22127 | if (font_not_found_p) | 22548 | if (font == NULL) |
| 22128 | { | ||
| 22129 | /* When no suitable font found, display an empty box based | ||
| 22130 | on the metrics of the font of the default face (or what | ||
| 22131 | remapped). */ | ||
| 22132 | struct face *no_font_face | ||
| 22133 | = FACE_FROM_ID (it->f, | ||
| 22134 | NILP (Vface_remapping_alist) ? DEFAULT_FACE_ID | ||
| 22135 | : lookup_basic_face (it->f, DEFAULT_FACE_ID)); | ||
| 22136 | font = no_font_face->font; | ||
| 22137 | boff = font->baseline_offset; | ||
| 22138 | } | ||
| 22139 | else | ||
| 22140 | { | 22549 | { |
| 22141 | boff = font->baseline_offset; | 22550 | /* When no suitable font is found, display this character by |
| 22142 | if (font->vertical_centering) | 22551 | the method specified in the first extra slot of |
| 22143 | boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff; | 22552 | Vglyphless_char_display. */ |
| 22553 | Lisp_Object acronym = lookup_glyphless_char_display (-1, it); | ||
| 22554 | |||
| 22555 | xassert (it->what == IT_GLYPHLESS); | ||
| 22556 | produce_glyphless_glyph (it, 1, STRINGP (acronym) ? acronym : Qnil); | ||
| 22557 | goto done; | ||
| 22144 | } | 22558 | } |
| 22145 | 22559 | ||
| 22560 | boff = font->baseline_offset; | ||
| 22561 | if (font->vertical_centering) | ||
| 22562 | boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff; | ||
| 22563 | |||
| 22146 | if (it->char_to_display != '\n' && it->char_to_display != '\t') | 22564 | if (it->char_to_display != '\n' && it->char_to_display != '\t') |
| 22147 | { | 22565 | { |
| 22148 | int stretched_p; | 22566 | int stretched_p; |
| @@ -22161,8 +22579,7 @@ x_produce_glyphs (struct it *it) | |||
| 22161 | it->descent = FONT_DESCENT (font) - boff; | 22579 | it->descent = FONT_DESCENT (font) - boff; |
| 22162 | } | 22580 | } |
| 22163 | 22581 | ||
| 22164 | if (! font_not_found_p | 22582 | if (get_char_glyph_code (it->char_to_display, font, &char2b)) |
| 22165 | && get_char_glyph_code (it->char_to_display, font, &char2b)) | ||
| 22166 | { | 22583 | { |
| 22167 | pcm = get_per_char_metric (it->f, font, &char2b); | 22584 | pcm = get_per_char_metric (it->f, font, &char2b); |
| 22168 | if (pcm->width == 0 | 22585 | if (pcm->width == 0 |
| @@ -22752,11 +23169,14 @@ x_produce_glyphs (struct it *it) | |||
| 22752 | if (it->glyph_row) | 23169 | if (it->glyph_row) |
| 22753 | append_composite_glyph (it); | 23170 | append_composite_glyph (it); |
| 22754 | } | 23171 | } |
| 23172 | else if (it->what == IT_GLYPHLESS) | ||
| 23173 | produce_glyphless_glyph (it, 0, Qnil); | ||
| 22755 | else if (it->what == IT_IMAGE) | 23174 | else if (it->what == IT_IMAGE) |
| 22756 | produce_image_glyph (it); | 23175 | produce_image_glyph (it); |
| 22757 | else if (it->what == IT_STRETCH) | 23176 | else if (it->what == IT_STRETCH) |
| 22758 | produce_stretch_glyph (it); | 23177 | produce_stretch_glyph (it); |
| 22759 | 23178 | ||
| 23179 | done: | ||
| 22760 | /* Accumulate dimensions. Note: can't assume that it->descent > 0 | 23180 | /* Accumulate dimensions. Note: can't assume that it->descent > 0 |
| 22761 | because this isn't true for images with `:ascent 100'. */ | 23181 | because this isn't true for images with `:ascent 100'. */ |
| 22762 | xassert (it->ascent >= 0 && it->descent >= 0); | 23182 | xassert (it->ascent >= 0 && it->descent >= 0); |
| @@ -23028,6 +23448,8 @@ set_frame_cursor_types (struct frame *f, Lisp_Object arg) | |||
| 23028 | } | 23448 | } |
| 23029 | 23449 | ||
| 23030 | 23450 | ||
| 23451 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 23452 | |||
| 23031 | /* Return the cursor we want to be displayed in window W. Return | 23453 | /* Return the cursor we want to be displayed in window W. Return |
| 23032 | width of bar/hbar cursor through WIDTH arg. Return with | 23454 | width of bar/hbar cursor through WIDTH arg. Return with |
| 23033 | ACTIVE_CURSOR arg set to 1 if cursor in window W is `active' | 23455 | ACTIVE_CURSOR arg set to 1 if cursor in window W is `active' |
| @@ -23073,10 +23495,7 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width, | |||
| 23073 | 23495 | ||
| 23074 | /* Detect a nonselected window or nonselected frame. */ | 23496 | /* Detect a nonselected window or nonselected frame. */ |
| 23075 | else if (w != XWINDOW (f->selected_window) | 23497 | else if (w != XWINDOW (f->selected_window) |
| 23076 | #ifdef HAVE_WINDOW_SYSTEM | 23498 | || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame) |
| 23077 | || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame | ||
| 23078 | #endif | ||
| 23079 | ) | ||
| 23080 | { | 23499 | { |
| 23081 | *active_cursor = 0; | 23500 | *active_cursor = 0; |
| 23082 | 23501 | ||
| @@ -23117,7 +23536,6 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width, | |||
| 23117 | /* Use normal cursor if not blinked off. */ | 23536 | /* Use normal cursor if not blinked off. */ |
| 23118 | if (!w->cursor_off_p) | 23537 | if (!w->cursor_off_p) |
| 23119 | { | 23538 | { |
| 23120 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 23121 | if (glyph != NULL && glyph->type == IMAGE_GLYPH) | 23539 | if (glyph != NULL && glyph->type == IMAGE_GLYPH) |
| 23122 | { | 23540 | { |
| 23123 | if (cursor_type == FILLED_BOX_CURSOR) | 23541 | if (cursor_type == FILLED_BOX_CURSOR) |
| @@ -23145,7 +23563,6 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width, | |||
| 23145 | cursor_type = HOLLOW_BOX_CURSOR; | 23563 | cursor_type = HOLLOW_BOX_CURSOR; |
| 23146 | } | 23564 | } |
| 23147 | } | 23565 | } |
| 23148 | #endif | ||
| 23149 | return cursor_type; | 23566 | return cursor_type; |
| 23150 | } | 23567 | } |
| 23151 | 23568 | ||
| @@ -23187,8 +23604,6 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width, | |||
| 23187 | } | 23604 | } |
| 23188 | 23605 | ||
| 23189 | 23606 | ||
| 23190 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 23191 | |||
| 23192 | /* Notice when the text cursor of window W has been completely | 23607 | /* Notice when the text cursor of window W has been completely |
| 23193 | overwritten by a drawing operation that outputs glyphs in AREA | 23608 | overwritten by a drawing operation that outputs glyphs in AREA |
| 23194 | starting at X0 and ending at X1 in the line starting at Y0 and | 23609 | starting at X0 and ending at X1 in the line starting at Y0 and |
| @@ -23354,7 +23769,7 @@ void | |||
| 23354 | erase_phys_cursor (struct window *w) | 23769 | erase_phys_cursor (struct window *w) |
| 23355 | { | 23770 | { |
| 23356 | struct frame *f = XFRAME (w->frame); | 23771 | struct frame *f = XFRAME (w->frame); |
| 23357 | Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | 23772 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); |
| 23358 | int hpos = w->phys_cursor.hpos; | 23773 | int hpos = w->phys_cursor.hpos; |
| 23359 | int vpos = w->phys_cursor.vpos; | 23774 | int vpos = w->phys_cursor.vpos; |
| 23360 | int mouse_face_here_p = 0; | 23775 | int mouse_face_here_p = 0; |
| @@ -23410,14 +23825,8 @@ erase_phys_cursor (struct window *w) | |||
| 23410 | 23825 | ||
| 23411 | /* If the cursor is in the mouse face area, redisplay that when | 23826 | /* If the cursor is in the mouse face area, redisplay that when |
| 23412 | we clear the cursor. */ | 23827 | we clear the cursor. */ |
| 23413 | if (! NILP (dpyinfo->mouse_face_window) | 23828 | if (! NILP (hlinfo->mouse_face_window) |
| 23414 | && w == XWINDOW (dpyinfo->mouse_face_window) | 23829 | && coords_in_mouse_face_p (w, hpos, vpos) |
| 23415 | && (vpos > dpyinfo->mouse_face_beg_row | ||
| 23416 | || (vpos == dpyinfo->mouse_face_beg_row | ||
| 23417 | && hpos >= dpyinfo->mouse_face_beg_col)) | ||
| 23418 | && (vpos < dpyinfo->mouse_face_end_row | ||
| 23419 | || (vpos == dpyinfo->mouse_face_end_row | ||
| 23420 | && hpos < dpyinfo->mouse_face_end_col)) | ||
| 23421 | /* Don't redraw the cursor's spot in mouse face if it is at the | 23830 | /* Don't redraw the cursor's spot in mouse face if it is at the |
| 23422 | end of a line (on a newline). The cursor appears there, but | 23831 | end of a line (on a newline). The cursor appears there, but |
| 23423 | mouse highlighting does not. */ | 23832 | mouse highlighting does not. */ |
| @@ -23608,30 +24017,50 @@ x_clear_cursor (struct window *w) | |||
| 23608 | update_window_cursor (w, 0); | 24017 | update_window_cursor (w, 0); |
| 23609 | } | 24018 | } |
| 23610 | 24019 | ||
| 24020 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 24021 | |||
| 24022 | /* Implementation of draw_row_with_mouse_face for GUI sessions, GPM, | ||
| 24023 | and MSDOS. */ | ||
| 24024 | void | ||
| 24025 | draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row, | ||
| 24026 | int start_hpos, int end_hpos, | ||
| 24027 | enum draw_glyphs_face draw) | ||
| 24028 | { | ||
| 24029 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 24030 | if (FRAME_WINDOW_P (XFRAME (w->frame))) | ||
| 24031 | { | ||
| 24032 | draw_glyphs (w, start_x, row, TEXT_AREA, start_hpos, end_hpos, draw, 0); | ||
| 24033 | return; | ||
| 24034 | } | ||
| 24035 | #endif | ||
| 24036 | #if defined (HAVE_GPM) || defined (MSDOS) | ||
| 24037 | tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw); | ||
| 24038 | #endif | ||
| 24039 | } | ||
| 23611 | 24040 | ||
| 23612 | /* EXPORT: | 24041 | /* EXPORT: |
| 23613 | Display the active region described by mouse_face_* according to DRAW. */ | 24042 | Display the active region described by mouse_face_* according to DRAW. */ |
| 23614 | 24043 | ||
| 23615 | void | 24044 | void |
| 23616 | show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) | 24045 | show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) |
| 23617 | { | 24046 | { |
| 23618 | struct window *w = XWINDOW (dpyinfo->mouse_face_window); | 24047 | struct window *w = XWINDOW (hlinfo->mouse_face_window); |
| 23619 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | 24048 | struct frame *f = XFRAME (WINDOW_FRAME (w)); |
| 23620 | 24049 | ||
| 23621 | if (/* If window is in the process of being destroyed, don't bother | 24050 | if (/* If window is in the process of being destroyed, don't bother |
| 23622 | to do anything. */ | 24051 | to do anything. */ |
| 23623 | w->current_matrix != NULL | 24052 | w->current_matrix != NULL |
| 23624 | /* Don't update mouse highlight if hidden */ | 24053 | /* Don't update mouse highlight if hidden */ |
| 23625 | && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden) | 24054 | && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden) |
| 23626 | /* Recognize when we are called to operate on rows that don't exist | 24055 | /* Recognize when we are called to operate on rows that don't exist |
| 23627 | anymore. This can happen when a window is split. */ | 24056 | anymore. This can happen when a window is split. */ |
| 23628 | && dpyinfo->mouse_face_end_row < w->current_matrix->nrows) | 24057 | && hlinfo->mouse_face_end_row < w->current_matrix->nrows) |
| 23629 | { | 24058 | { |
| 23630 | int phys_cursor_on_p = w->phys_cursor_on_p; | 24059 | int phys_cursor_on_p = w->phys_cursor_on_p; |
| 23631 | struct glyph_row *row, *first, *last; | 24060 | struct glyph_row *row, *first, *last; |
| 23632 | 24061 | ||
| 23633 | first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row); | 24062 | first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row); |
| 23634 | last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row); | 24063 | last = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row); |
| 23635 | 24064 | ||
| 23636 | for (row = first; row <= last && row->enabled_p; ++row) | 24065 | for (row = first; row <= last && row->enabled_p; ++row) |
| 23637 | { | 24066 | { |
| @@ -23640,8 +24069,30 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) | |||
| 23640 | /* For all but the first row, the highlight starts at column 0. */ | 24069 | /* For all but the first row, the highlight starts at column 0. */ |
| 23641 | if (row == first) | 24070 | if (row == first) |
| 23642 | { | 24071 | { |
| 23643 | start_hpos = dpyinfo->mouse_face_beg_col; | 24072 | /* R2L rows have BEG and END in reversed order, but the |
| 23644 | start_x = dpyinfo->mouse_face_beg_x; | 24073 | screen drawing geometry is always left to right. So |
| 24074 | we need to mirror the beginning and end of the | ||
| 24075 | highlighted area in R2L rows. */ | ||
| 24076 | if (!row->reversed_p) | ||
| 24077 | { | ||
| 24078 | start_hpos = hlinfo->mouse_face_beg_col; | ||
| 24079 | start_x = hlinfo->mouse_face_beg_x; | ||
| 24080 | } | ||
| 24081 | else if (row == last) | ||
| 24082 | { | ||
| 24083 | start_hpos = hlinfo->mouse_face_end_col; | ||
| 24084 | start_x = hlinfo->mouse_face_end_x; | ||
| 24085 | } | ||
| 24086 | else | ||
| 24087 | { | ||
| 24088 | start_hpos = 0; | ||
| 24089 | start_x = 0; | ||
| 24090 | } | ||
| 24091 | } | ||
| 24092 | else if (row->reversed_p && row == last) | ||
| 24093 | { | ||
| 24094 | start_hpos = hlinfo->mouse_face_end_col; | ||
| 24095 | start_x = hlinfo->mouse_face_end_x; | ||
| 23645 | } | 24096 | } |
| 23646 | else | 24097 | else |
| 23647 | { | 24098 | { |
| @@ -23650,7 +24101,20 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) | |||
| 23650 | } | 24101 | } |
| 23651 | 24102 | ||
| 23652 | if (row == last) | 24103 | if (row == last) |
| 23653 | end_hpos = dpyinfo->mouse_face_end_col; | 24104 | { |
| 24105 | if (!row->reversed_p) | ||
| 24106 | end_hpos = hlinfo->mouse_face_end_col; | ||
| 24107 | else if (row == first) | ||
| 24108 | end_hpos = hlinfo->mouse_face_beg_col; | ||
| 24109 | else | ||
| 24110 | { | ||
| 24111 | end_hpos = row->used[TEXT_AREA]; | ||
| 24112 | if (draw == DRAW_NORMAL_TEXT) | ||
| 24113 | row->fill_line_p = 1; /* Clear to end of line */ | ||
| 24114 | } | ||
| 24115 | } | ||
| 24116 | else if (row->reversed_p && row == first) | ||
| 24117 | end_hpos = hlinfo->mouse_face_beg_col; | ||
| 23654 | else | 24118 | else |
| 23655 | { | 24119 | { |
| 23656 | end_hpos = row->used[TEXT_AREA]; | 24120 | end_hpos = row->used[TEXT_AREA]; |
| @@ -23660,18 +24124,19 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) | |||
| 23660 | 24124 | ||
| 23661 | if (end_hpos > start_hpos) | 24125 | if (end_hpos > start_hpos) |
| 23662 | { | 24126 | { |
| 23663 | draw_glyphs (w, start_x, row, TEXT_AREA, | 24127 | draw_row_with_mouse_face (w, start_x, row, |
| 23664 | start_hpos, end_hpos, | 24128 | start_hpos, end_hpos, draw); |
| 23665 | draw, 0); | ||
| 23666 | 24129 | ||
| 23667 | row->mouse_face_p | 24130 | row->mouse_face_p |
| 23668 | = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED; | 24131 | = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED; |
| 23669 | } | 24132 | } |
| 23670 | } | 24133 | } |
| 23671 | 24134 | ||
| 24135 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 23672 | /* When we've written over the cursor, arrange for it to | 24136 | /* When we've written over the cursor, arrange for it to |
| 23673 | be displayed again. */ | 24137 | be displayed again. */ |
| 23674 | if (phys_cursor_on_p && !w->phys_cursor_on_p) | 24138 | if (FRAME_WINDOW_P (f) |
| 24139 | && phys_cursor_on_p && !w->phys_cursor_on_p) | ||
| 23675 | { | 24140 | { |
| 23676 | BLOCK_INPUT; | 24141 | BLOCK_INPUT; |
| 23677 | display_and_set_cursor (w, 1, | 24142 | display_and_set_cursor (w, 1, |
| @@ -23679,15 +24144,22 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) | |||
| 23679 | w->phys_cursor.x, w->phys_cursor.y); | 24144 | w->phys_cursor.x, w->phys_cursor.y); |
| 23680 | UNBLOCK_INPUT; | 24145 | UNBLOCK_INPUT; |
| 23681 | } | 24146 | } |
| 24147 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 23682 | } | 24148 | } |
| 23683 | 24149 | ||
| 24150 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 23684 | /* Change the mouse cursor. */ | 24151 | /* Change the mouse cursor. */ |
| 23685 | if (draw == DRAW_NORMAL_TEXT && !EQ (dpyinfo->mouse_face_window, f->tool_bar_window)) | 24152 | if (FRAME_WINDOW_P (f)) |
| 23686 | FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor); | 24153 | { |
| 23687 | else if (draw == DRAW_MOUSE_FACE) | 24154 | if (draw == DRAW_NORMAL_TEXT |
| 23688 | FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor); | 24155 | && !EQ (hlinfo->mouse_face_window, f->tool_bar_window)) |
| 23689 | else | 24156 | FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor); |
| 23690 | FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor); | 24157 | else if (draw == DRAW_MOUSE_FACE) |
| 24158 | FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor); | ||
| 24159 | else | ||
| 24160 | FRAME_RIF (f)->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor); | ||
| 24161 | } | ||
| 24162 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 23691 | } | 24163 | } |
| 23692 | 24164 | ||
| 23693 | /* EXPORT: | 24165 | /* EXPORT: |
| @@ -23696,23 +24168,70 @@ show_mouse_face (Display_Info *dpyinfo, enum draw_glyphs_face draw) | |||
| 23696 | face was actually drawn unhighlighted. */ | 24168 | face was actually drawn unhighlighted. */ |
| 23697 | 24169 | ||
| 23698 | int | 24170 | int |
| 23699 | clear_mouse_face (Display_Info *dpyinfo) | 24171 | clear_mouse_face (Mouse_HLInfo *hlinfo) |
| 23700 | { | 24172 | { |
| 23701 | int cleared = 0; | 24173 | int cleared = 0; |
| 23702 | 24174 | ||
| 23703 | if (!dpyinfo->mouse_face_hidden && !NILP (dpyinfo->mouse_face_window)) | 24175 | if (!hlinfo->mouse_face_hidden && !NILP (hlinfo->mouse_face_window)) |
| 23704 | { | 24176 | { |
| 23705 | show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT); | 24177 | show_mouse_face (hlinfo, DRAW_NORMAL_TEXT); |
| 23706 | cleared = 1; | 24178 | cleared = 1; |
| 23707 | } | 24179 | } |
| 23708 | 24180 | ||
| 23709 | dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; | 24181 | hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; |
| 23710 | dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; | 24182 | hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; |
| 23711 | dpyinfo->mouse_face_window = Qnil; | 24183 | hlinfo->mouse_face_window = Qnil; |
| 23712 | dpyinfo->mouse_face_overlay = Qnil; | 24184 | hlinfo->mouse_face_overlay = Qnil; |
| 23713 | return cleared; | 24185 | return cleared; |
| 23714 | } | 24186 | } |
| 23715 | 24187 | ||
| 24188 | /* Return non-zero if the coordinates HPOS and VPOS on windows W are | ||
| 24189 | within the mouse face on that window. */ | ||
| 24190 | static int | ||
| 24191 | coords_in_mouse_face_p (struct window *w, int hpos, int vpos) | ||
| 24192 | { | ||
| 24193 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); | ||
| 24194 | |||
| 24195 | /* Quickly resolve the easy cases. */ | ||
| 24196 | if (!(WINDOWP (hlinfo->mouse_face_window) | ||
| 24197 | && XWINDOW (hlinfo->mouse_face_window) == w)) | ||
| 24198 | return 0; | ||
| 24199 | if (vpos < hlinfo->mouse_face_beg_row | ||
| 24200 | || vpos > hlinfo->mouse_face_end_row) | ||
| 24201 | return 0; | ||
| 24202 | if (vpos > hlinfo->mouse_face_beg_row | ||
| 24203 | && vpos < hlinfo->mouse_face_end_row) | ||
| 24204 | return 1; | ||
| 24205 | |||
| 24206 | if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p) | ||
| 24207 | { | ||
| 24208 | if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row) | ||
| 24209 | { | ||
| 24210 | if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col) | ||
| 24211 | return 1; | ||
| 24212 | } | ||
| 24213 | else if ((vpos == hlinfo->mouse_face_beg_row | ||
| 24214 | && hpos >= hlinfo->mouse_face_beg_col) | ||
| 24215 | || (vpos == hlinfo->mouse_face_end_row | ||
| 24216 | && hpos < hlinfo->mouse_face_end_col)) | ||
| 24217 | return 1; | ||
| 24218 | } | ||
| 24219 | else | ||
| 24220 | { | ||
| 24221 | if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row) | ||
| 24222 | { | ||
| 24223 | if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col) | ||
| 24224 | return 1; | ||
| 24225 | } | ||
| 24226 | else if ((vpos == hlinfo->mouse_face_beg_row | ||
| 24227 | && hpos <= hlinfo->mouse_face_beg_col) | ||
| 24228 | || (vpos == hlinfo->mouse_face_end_row | ||
| 24229 | && hpos > hlinfo->mouse_face_end_col)) | ||
| 24230 | return 1; | ||
| 24231 | } | ||
| 24232 | return 0; | ||
| 24233 | } | ||
| 24234 | |||
| 23716 | 24235 | ||
| 23717 | /* EXPORT: | 24236 | /* EXPORT: |
| 23718 | Non-zero if physical cursor of window W is within mouse face. */ | 24237 | Non-zero if physical cursor of window W is within mouse face. */ |
| @@ -23720,32 +24239,135 @@ clear_mouse_face (Display_Info *dpyinfo) | |||
| 23720 | int | 24239 | int |
| 23721 | cursor_in_mouse_face_p (struct window *w) | 24240 | cursor_in_mouse_face_p (struct window *w) |
| 23722 | { | 24241 | { |
| 23723 | Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame)); | 24242 | return coords_in_mouse_face_p (w, w->phys_cursor.hpos, w->phys_cursor.vpos); |
| 23724 | int in_mouse_face = 0; | 24243 | } |
| 23725 | 24244 | ||
| 23726 | if (WINDOWP (dpyinfo->mouse_face_window) | ||
| 23727 | && XWINDOW (dpyinfo->mouse_face_window) == w) | ||
| 23728 | { | ||
| 23729 | int hpos = w->phys_cursor.hpos; | ||
| 23730 | int vpos = w->phys_cursor.vpos; | ||
| 23731 | 24245 | ||
| 23732 | if (vpos >= dpyinfo->mouse_face_beg_row | 24246 | |
| 23733 | && vpos <= dpyinfo->mouse_face_end_row | 24247 | /* Find the glyph rows START_ROW and END_ROW of window W that display |
| 23734 | && (vpos > dpyinfo->mouse_face_beg_row | 24248 | characters between buffer positions START_CHARPOS and END_CHARPOS |
| 23735 | || hpos >= dpyinfo->mouse_face_beg_col) | 24249 | (excluding END_CHARPOS). This is similar to row_containing_pos, |
| 23736 | && (vpos < dpyinfo->mouse_face_end_row | 24250 | but is more accurate when bidi reordering makes buffer positions |
| 23737 | || hpos < dpyinfo->mouse_face_end_col | 24251 | change non-linearly with glyph rows. */ |
| 23738 | || dpyinfo->mouse_face_past_end)) | 24252 | static void |
| 23739 | in_mouse_face = 1; | 24253 | rows_from_pos_range (struct window *w, |
| 23740 | } | 24254 | EMACS_INT start_charpos, EMACS_INT end_charpos, |
| 24255 | struct glyph_row **start, struct glyph_row **end) | ||
| 24256 | { | ||
| 24257 | struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | ||
| 24258 | int last_y = window_text_bottom_y (w); | ||
| 24259 | struct glyph_row *row; | ||
| 23741 | 24260 | ||
| 23742 | return in_mouse_face; | 24261 | *start = NULL; |
| 23743 | } | 24262 | *end = NULL; |
| 24263 | |||
| 24264 | while (!first->enabled_p | ||
| 24265 | && first < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)) | ||
| 24266 | first++; | ||
| 24267 | |||
| 24268 | /* Find the START row. */ | ||
| 24269 | for (row = first; | ||
| 24270 | row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; | ||
| 24271 | row++) | ||
| 24272 | { | ||
| 24273 | /* A row can potentially be the START row if the range of the | ||
| 24274 | characters it displays intersects the range | ||
| 24275 | [START_CHARPOS..END_CHARPOS). */ | ||
| 24276 | if (! ((start_charpos < MATRIX_ROW_START_CHARPOS (row) | ||
| 24277 | && end_charpos < MATRIX_ROW_START_CHARPOS (row)) | ||
| 24278 | /* See the commentary in row_containing_pos, for the | ||
| 24279 | explanation of the complicated way to check whether | ||
| 24280 | some position is beyond the end of the characters | ||
| 24281 | displayed by a row. */ | ||
| 24282 | || ((start_charpos > MATRIX_ROW_END_CHARPOS (row) | ||
| 24283 | || (start_charpos == MATRIX_ROW_END_CHARPOS (row) | ||
| 24284 | && !row->ends_at_zv_p | ||
| 24285 | && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))) | ||
| 24286 | && (end_charpos > MATRIX_ROW_END_CHARPOS (row) | ||
| 24287 | || (end_charpos == MATRIX_ROW_END_CHARPOS (row) | ||
| 24288 | && !row->ends_at_zv_p | ||
| 24289 | && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))))) | ||
| 24290 | { | ||
| 24291 | /* Found a candidate row. Now make sure at least one of the | ||
| 24292 | glyphs it displays has a charpos from the range | ||
| 24293 | [START_CHARPOS..END_CHARPOS). | ||
| 24294 | |||
| 24295 | This is not obvious because bidi reordering could make | ||
| 24296 | buffer positions of a row be 1,2,3,102,101,100, and if we | ||
| 24297 | want to highlight characters in [50..60), we don't want | ||
| 24298 | this row, even though [50..60) does intersect [1..103), | ||
| 24299 | the range of character positions given by the row's start | ||
| 24300 | and end positions. */ | ||
| 24301 | struct glyph *g = row->glyphs[TEXT_AREA]; | ||
| 24302 | struct glyph *e = g + row->used[TEXT_AREA]; | ||
| 24303 | |||
| 24304 | while (g < e) | ||
| 24305 | { | ||
| 24306 | if (BUFFERP (g->object) | ||
| 24307 | && start_charpos <= g->charpos && g->charpos < end_charpos) | ||
| 24308 | *start = row; | ||
| 24309 | g++; | ||
| 24310 | } | ||
| 24311 | if (*start) | ||
| 24312 | break; | ||
| 24313 | } | ||
| 24314 | } | ||
| 23744 | 24315 | ||
| 24316 | /* Find the END row. */ | ||
| 24317 | if (!*start | ||
| 24318 | /* If the last row is partially visible, start looking for END | ||
| 24319 | from that row, instead of starting from FIRST. */ | ||
| 24320 | && !(row->enabled_p | ||
| 24321 | && row->y < last_y && MATRIX_ROW_BOTTOM_Y (row) > last_y)) | ||
| 24322 | row = first; | ||
| 24323 | for ( ; row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; row++) | ||
| 24324 | { | ||
| 24325 | struct glyph_row *next = row + 1; | ||
| 24326 | |||
| 24327 | if (!next->enabled_p | ||
| 24328 | || next >= MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w) | ||
| 24329 | /* The first row >= START whose range of displayed characters | ||
| 24330 | does NOT intersect the range [START_CHARPOS..END_CHARPOS] | ||
| 24331 | is the row END + 1. */ | ||
| 24332 | || (start_charpos < MATRIX_ROW_START_CHARPOS (next) | ||
| 24333 | && end_charpos < MATRIX_ROW_START_CHARPOS (next)) | ||
| 24334 | || ((start_charpos > MATRIX_ROW_END_CHARPOS (next) | ||
| 24335 | || (start_charpos == MATRIX_ROW_END_CHARPOS (next) | ||
| 24336 | && !next->ends_at_zv_p | ||
| 24337 | && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next))) | ||
| 24338 | && (end_charpos > MATRIX_ROW_END_CHARPOS (next) | ||
| 24339 | || (end_charpos == MATRIX_ROW_END_CHARPOS (next) | ||
| 24340 | && !next->ends_at_zv_p | ||
| 24341 | && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next))))) | ||
| 24342 | { | ||
| 24343 | *end = row; | ||
| 24344 | break; | ||
| 24345 | } | ||
| 24346 | else | ||
| 24347 | { | ||
| 24348 | /* If the next row's edges intersect [START_CHARPOS..END_CHARPOS], | ||
| 24349 | but none of the characters it displays are in the range, it is | ||
| 24350 | also END + 1. */ | ||
| 24351 | struct glyph *g = next->glyphs[TEXT_AREA]; | ||
| 24352 | struct glyph *e = g + next->used[TEXT_AREA]; | ||
| 23745 | 24353 | ||
| 24354 | while (g < e) | ||
| 24355 | { | ||
| 24356 | if (BUFFERP (g->object) | ||
| 24357 | && start_charpos <= g->charpos && g->charpos < end_charpos) | ||
| 24358 | break; | ||
| 24359 | g++; | ||
| 24360 | } | ||
| 24361 | if (g == e) | ||
| 24362 | { | ||
| 24363 | *end = row; | ||
| 24364 | break; | ||
| 24365 | } | ||
| 24366 | } | ||
| 24367 | } | ||
| 24368 | } | ||
| 23746 | 24369 | ||
| 23747 | 24370 | /* This function sets the mouse_face_* elements of HLINFO, assuming | |
| 23748 | /* This function sets the mouse_face_* elements of DPYINFO, assuming | ||
| 23749 | the mouse cursor is on a glyph with buffer charpos MOUSE_CHARPOS in | 24371 | the mouse cursor is on a glyph with buffer charpos MOUSE_CHARPOS in |
| 23750 | window WINDOW. START_CHARPOS and END_CHARPOS are buffer positions | 24372 | window WINDOW. START_CHARPOS and END_CHARPOS are buffer positions |
| 23751 | for the overlay or run of text properties specifying the mouse | 24373 | for the overlay or run of text properties specifying the mouse |
| @@ -23756,7 +24378,7 @@ cursor_in_mouse_face_p (struct window *w) | |||
| 23756 | 24378 | ||
| 23757 | static void | 24379 | static void |
| 23758 | mouse_face_from_buffer_pos (Lisp_Object window, | 24380 | mouse_face_from_buffer_pos (Lisp_Object window, |
| 23759 | Display_Info *dpyinfo, | 24381 | Mouse_HLInfo *hlinfo, |
| 23760 | EMACS_INT mouse_charpos, | 24382 | EMACS_INT mouse_charpos, |
| 23761 | EMACS_INT start_charpos, | 24383 | EMACS_INT start_charpos, |
| 23762 | EMACS_INT end_charpos, | 24384 | EMACS_INT end_charpos, |
| @@ -23766,166 +24388,313 @@ mouse_face_from_buffer_pos (Lisp_Object window, | |||
| 23766 | { | 24388 | { |
| 23767 | struct window *w = XWINDOW (window); | 24389 | struct window *w = XWINDOW (window); |
| 23768 | struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | 24390 | struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); |
| 23769 | struct glyph_row *row; | 24391 | struct glyph_row *r1, *r2; |
| 23770 | struct glyph *glyph, *end; | 24392 | struct glyph *glyph, *end; |
| 23771 | EMACS_INT ignore; | 24393 | EMACS_INT ignore, pos; |
| 23772 | int x; | 24394 | int x; |
| 23773 | 24395 | ||
| 23774 | xassert (NILP (display_string) || STRINGP (display_string)); | 24396 | xassert (NILP (display_string) || STRINGP (display_string)); |
| 23775 | xassert (NILP (before_string) || STRINGP (before_string)); | 24397 | xassert (NILP (before_string) || STRINGP (before_string)); |
| 23776 | xassert (NILP (after_string) || STRINGP (after_string)); | 24398 | xassert (NILP (after_string) || STRINGP (after_string)); |
| 23777 | 24399 | ||
| 23778 | /* Find the first highlighted glyph. */ | 24400 | /* Find the rows corresponding to START_CHARPOS and END_CHARPOS. */ |
| 23779 | if (start_charpos < MATRIX_ROW_START_CHARPOS (first)) | 24401 | rows_from_pos_range (w, start_charpos, end_charpos, &r1, &r2); |
| 24402 | if (r1 == NULL) | ||
| 24403 | r1 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); | ||
| 24404 | /* If the before-string or display-string contains newlines, | ||
| 24405 | rows_from_pos_range skips to its last row. Move back. */ | ||
| 24406 | if (!NILP (before_string) || !NILP (display_string)) | ||
| 24407 | { | ||
| 24408 | struct glyph_row *prev; | ||
| 24409 | while ((prev = r1 - 1, prev >= first) | ||
| 24410 | && MATRIX_ROW_END_CHARPOS (prev) == start_charpos | ||
| 24411 | && prev->used[TEXT_AREA] > 0) | ||
| 24412 | { | ||
| 24413 | struct glyph *beg = prev->glyphs[TEXT_AREA]; | ||
| 24414 | glyph = beg + prev->used[TEXT_AREA]; | ||
| 24415 | while (--glyph >= beg && INTEGERP (glyph->object)); | ||
| 24416 | if (glyph < beg | ||
| 24417 | || !(EQ (glyph->object, before_string) | ||
| 24418 | || EQ (glyph->object, display_string))) | ||
| 24419 | break; | ||
| 24420 | r1 = prev; | ||
| 24421 | } | ||
| 24422 | } | ||
| 24423 | if (r2 == NULL) | ||
| 23780 | { | 24424 | { |
| 23781 | dpyinfo->mouse_face_beg_col = 0; | 24425 | r2 = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); |
| 23782 | dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (first, w->current_matrix); | 24426 | hlinfo->mouse_face_past_end = 1; |
| 23783 | dpyinfo->mouse_face_beg_x = first->x; | ||
| 23784 | dpyinfo->mouse_face_beg_y = first->y; | ||
| 23785 | } | 24427 | } |
| 23786 | else | 24428 | else if (!NILP (after_string)) |
| 23787 | { | 24429 | { |
| 23788 | row = row_containing_pos (w, start_charpos, first, NULL, 0); | 24430 | /* If the after-string has newlines, advance to its last row. */ |
| 23789 | if (row == NULL) | 24431 | struct glyph_row *next; |
| 23790 | row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); | 24432 | struct glyph_row *last |
| 23791 | 24433 | = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); | |
| 23792 | /* If the before-string or display-string contains newlines, | ||
| 23793 | row_containing_pos skips to its last row. Move back. */ | ||
| 23794 | if (!NILP (before_string) || !NILP (display_string)) | ||
| 23795 | { | ||
| 23796 | struct glyph_row *prev; | ||
| 23797 | while ((prev = row - 1, prev >= first) | ||
| 23798 | && MATRIX_ROW_END_CHARPOS (prev) == start_charpos | ||
| 23799 | && prev->used[TEXT_AREA] > 0) | ||
| 23800 | { | ||
| 23801 | struct glyph *beg = prev->glyphs[TEXT_AREA]; | ||
| 23802 | glyph = beg + prev->used[TEXT_AREA]; | ||
| 23803 | while (--glyph >= beg && INTEGERP (glyph->object)); | ||
| 23804 | if (glyph < beg | ||
| 23805 | || !(EQ (glyph->object, before_string) | ||
| 23806 | || EQ (glyph->object, display_string))) | ||
| 23807 | break; | ||
| 23808 | row = prev; | ||
| 23809 | } | ||
| 23810 | } | ||
| 23811 | 24434 | ||
| 23812 | glyph = row->glyphs[TEXT_AREA]; | 24435 | for (next = r2 + 1; |
| 23813 | end = glyph + row->used[TEXT_AREA]; | 24436 | next <= last |
| 23814 | x = row->x; | 24437 | && next->used[TEXT_AREA] > 0 |
| 23815 | dpyinfo->mouse_face_beg_y = row->y; | 24438 | && EQ (next->glyphs[TEXT_AREA]->object, after_string); |
| 23816 | dpyinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (row, w->current_matrix); | 24439 | ++next) |
| 24440 | r2 = next; | ||
| 24441 | } | ||
| 24442 | /* The rest of the display engine assumes that mouse_face_beg_row is | ||
| 24443 | either above below mouse_face_end_row or identical to it. But | ||
| 24444 | with bidi-reordered continued lines, the row for START_CHARPOS | ||
| 24445 | could be below the row for END_CHARPOS. If so, swap the rows and | ||
| 24446 | store them in correct order. */ | ||
| 24447 | if (r1->y > r2->y) | ||
| 24448 | { | ||
| 24449 | struct glyph_row *tem = r2; | ||
| 24450 | |||
| 24451 | r2 = r1; | ||
| 24452 | r1 = tem; | ||
| 24453 | } | ||
| 24454 | |||
| 24455 | hlinfo->mouse_face_beg_y = r1->y; | ||
| 24456 | hlinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix); | ||
| 24457 | hlinfo->mouse_face_end_y = r2->y; | ||
| 24458 | hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix); | ||
| 24459 | |||
| 24460 | /* For a bidi-reordered row, the positions of BEFORE_STRING, | ||
| 24461 | AFTER_STRING, DISPLAY_STRING, START_CHARPOS, and END_CHARPOS | ||
| 24462 | could be anywhere in the row and in any order. The strategy | ||
| 24463 | below is to find the leftmost and the rightmost glyph that | ||
| 24464 | belongs to either of these 3 strings, or whose position is | ||
| 24465 | between START_CHARPOS and END_CHARPOS, and highlight all the | ||
| 24466 | glyphs between those two. This may cover more than just the text | ||
| 24467 | between START_CHARPOS and END_CHARPOS if the range of characters | ||
| 24468 | strides the bidi level boundary, e.g. if the beginning is in R2L | ||
| 24469 | text while the end is in L2R text or vice versa. */ | ||
| 24470 | if (!r1->reversed_p) | ||
| 24471 | { | ||
| 24472 | /* This row is in a left to right paragraph. Scan it left to | ||
| 24473 | right. */ | ||
| 24474 | glyph = r1->glyphs[TEXT_AREA]; | ||
| 24475 | end = glyph + r1->used[TEXT_AREA]; | ||
| 24476 | x = r1->x; | ||
| 23817 | 24477 | ||
| 23818 | /* Skip truncation glyphs at the start of the glyph row. */ | 24478 | /* Skip truncation glyphs at the start of the glyph row. */ |
| 23819 | if (row->displays_text_p) | 24479 | if (r1->displays_text_p) |
| 23820 | for (; glyph < end | 24480 | for (; glyph < end |
| 23821 | && INTEGERP (glyph->object) | 24481 | && INTEGERP (glyph->object) |
| 23822 | && glyph->charpos < 0; | 24482 | && glyph->charpos < 0; |
| 23823 | ++glyph) | 24483 | ++glyph) |
| 23824 | x += glyph->pixel_width; | 24484 | x += glyph->pixel_width; |
| 23825 | 24485 | ||
| 23826 | /* Scan the glyph row, stopping before BEFORE_STRING or | 24486 | /* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING, |
| 23827 | DISPLAY_STRING or START_CHARPOS. */ | 24487 | or DISPLAY_STRING, and the first glyph from buffer whose |
| 24488 | position is between START_CHARPOS and END_CHARPOS. */ | ||
| 23828 | for (; glyph < end | 24489 | for (; glyph < end |
| 23829 | && !INTEGERP (glyph->object) | 24490 | && !INTEGERP (glyph->object) |
| 23830 | && !EQ (glyph->object, before_string) | ||
| 23831 | && !EQ (glyph->object, display_string) | 24491 | && !EQ (glyph->object, display_string) |
| 23832 | && !(BUFFERP (glyph->object) | 24492 | && !(BUFFERP (glyph->object) |
| 23833 | && glyph->charpos >= start_charpos); | 24493 | && (glyph->charpos >= start_charpos |
| 24494 | && glyph->charpos < end_charpos)); | ||
| 23834 | ++glyph) | 24495 | ++glyph) |
| 23835 | x += glyph->pixel_width; | 24496 | { |
| 23836 | 24497 | /* BEFORE_STRING or AFTER_STRING are only relevant if they | |
| 23837 | dpyinfo->mouse_face_beg_x = x; | 24498 | are present at buffer positions between START_CHARPOS and |
| 23838 | dpyinfo->mouse_face_beg_col = glyph - row->glyphs[TEXT_AREA]; | 24499 | END_CHARPOS, or if they come from an overlay. */ |
| 23839 | } | 24500 | if (EQ (glyph->object, before_string)) |
| 23840 | 24501 | { | |
| 23841 | /* Find the last highlighted glyph. */ | 24502 | pos = string_buffer_position (w, before_string, |
| 23842 | row = row_containing_pos (w, end_charpos, first, NULL, 0); | 24503 | start_charpos); |
| 23843 | if (row == NULL) | 24504 | /* If pos == 0, it means before_string came from an |
| 23844 | { | 24505 | overlay, not from a buffer position. */ |
| 23845 | row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); | 24506 | if (!pos || (pos >= start_charpos && pos < end_charpos)) |
| 23846 | dpyinfo->mouse_face_past_end = 1; | 24507 | break; |
| 24508 | } | ||
| 24509 | else if (EQ (glyph->object, after_string)) | ||
| 24510 | { | ||
| 24511 | pos = string_buffer_position (w, after_string, end_charpos); | ||
| 24512 | if (!pos || (pos >= start_charpos && pos < end_charpos)) | ||
| 24513 | break; | ||
| 24514 | } | ||
| 24515 | x += glyph->pixel_width; | ||
| 24516 | } | ||
| 24517 | hlinfo->mouse_face_beg_x = x; | ||
| 24518 | hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA]; | ||
| 23847 | } | 24519 | } |
| 23848 | else if (!NILP (after_string)) | 24520 | else |
| 23849 | { | 24521 | { |
| 23850 | /* If the after-string has newlines, advance to its last row. */ | 24522 | /* This row is in a right to left paragraph. Scan it right to |
| 23851 | struct glyph_row *next; | 24523 | left. */ |
| 23852 | struct glyph_row *last | 24524 | struct glyph *g; |
| 23853 | = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); | ||
| 23854 | 24525 | ||
| 23855 | for (next = row + 1; | 24526 | end = r1->glyphs[TEXT_AREA] - 1; |
| 23856 | next <= last | 24527 | glyph = end + r1->used[TEXT_AREA]; |
| 23857 | && next->used[TEXT_AREA] > 0 | ||
| 23858 | && EQ (next->glyphs[TEXT_AREA]->object, after_string); | ||
| 23859 | ++next) | ||
| 23860 | row = next; | ||
| 23861 | } | ||
| 23862 | 24528 | ||
| 23863 | glyph = row->glyphs[TEXT_AREA]; | 24529 | /* Skip truncation glyphs at the start of the glyph row. */ |
| 23864 | end = glyph + row->used[TEXT_AREA]; | 24530 | if (r1->displays_text_p) |
| 23865 | x = row->x; | 24531 | for (; glyph > end |
| 23866 | dpyinfo->mouse_face_end_y = row->y; | 24532 | && INTEGERP (glyph->object) |
| 23867 | dpyinfo->mouse_face_end_row = MATRIX_ROW_VPOS (row, w->current_matrix); | 24533 | && glyph->charpos < 0; |
| 24534 | --glyph) | ||
| 24535 | ; | ||
| 23868 | 24536 | ||
| 23869 | /* Skip truncation glyphs at the start of the row. */ | 24537 | /* Scan the glyph row, looking for BEFORE_STRING, AFTER_STRING, |
| 23870 | if (row->displays_text_p) | 24538 | or DISPLAY_STRING, and the first glyph from buffer whose |
| 23871 | for (; glyph < end | 24539 | position is between START_CHARPOS and END_CHARPOS. */ |
| 23872 | && INTEGERP (glyph->object) | 24540 | for (; glyph > end |
| 23873 | && glyph->charpos < 0; | 24541 | && !INTEGERP (glyph->object) |
| 23874 | ++glyph) | 24542 | && !EQ (glyph->object, display_string) |
| 23875 | x += glyph->pixel_width; | 24543 | && !(BUFFERP (glyph->object) |
| 23876 | 24544 | && (glyph->charpos >= start_charpos | |
| 23877 | /* Scan the glyph row, stopping at END_CHARPOS or when we encounter | 24545 | && glyph->charpos < end_charpos)); |
| 23878 | AFTER_STRING. */ | 24546 | --glyph) |
| 23879 | for (; glyph < end | 24547 | { |
| 23880 | && !INTEGERP (glyph->object) | 24548 | /* BEFORE_STRING or AFTER_STRING are only relevant if they |
| 23881 | && !EQ (glyph->object, after_string) | 24549 | are present at buffer positions between START_CHARPOS and |
| 23882 | && !(BUFFERP (glyph->object) && glyph->charpos >= end_charpos); | 24550 | END_CHARPOS, or if they come from an overlay. */ |
| 23883 | ++glyph) | 24551 | if (EQ (glyph->object, before_string)) |
| 23884 | x += glyph->pixel_width; | 24552 | { |
| 24553 | pos = string_buffer_position (w, before_string, start_charpos); | ||
| 24554 | /* If pos == 0, it means before_string came from an | ||
| 24555 | overlay, not from a buffer position. */ | ||
| 24556 | if (!pos || (pos >= start_charpos && pos < end_charpos)) | ||
| 24557 | break; | ||
| 24558 | } | ||
| 24559 | else if (EQ (glyph->object, after_string)) | ||
| 24560 | { | ||
| 24561 | pos = string_buffer_position (w, after_string, end_charpos); | ||
| 24562 | if (!pos || (pos >= start_charpos && pos < end_charpos)) | ||
| 24563 | break; | ||
| 24564 | } | ||
| 24565 | } | ||
| 24566 | |||
| 24567 | glyph++; /* first glyph to the right of the highlighted area */ | ||
| 24568 | for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++) | ||
| 24569 | x += g->pixel_width; | ||
| 24570 | hlinfo->mouse_face_beg_x = x; | ||
| 24571 | hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA]; | ||
| 24572 | } | ||
| 23885 | 24573 | ||
| 23886 | /* If we found AFTER_STRING, consume it and stop. */ | 24574 | /* If the highlight ends in a different row, compute GLYPH and END |
| 23887 | if (EQ (glyph->object, after_string)) | 24575 | for the end row. Otherwise, reuse the values computed above for |
| 24576 | the row where the highlight begins. */ | ||
| 24577 | if (r2 != r1) | ||
| 23888 | { | 24578 | { |
| 23889 | for (; EQ (glyph->object, after_string) && glyph < end; ++glyph) | 24579 | if (!r2->reversed_p) |
| 24580 | { | ||
| 24581 | glyph = r2->glyphs[TEXT_AREA]; | ||
| 24582 | end = glyph + r2->used[TEXT_AREA]; | ||
| 24583 | x = r2->x; | ||
| 24584 | } | ||
| 24585 | else | ||
| 24586 | { | ||
| 24587 | end = r2->glyphs[TEXT_AREA] - 1; | ||
| 24588 | glyph = end + r2->used[TEXT_AREA]; | ||
| 24589 | } | ||
| 24590 | } | ||
| 24591 | |||
| 24592 | if (!r2->reversed_p) | ||
| 24593 | { | ||
| 24594 | /* Skip truncation and continuation glyphs near the end of the | ||
| 24595 | row, and also blanks and stretch glyphs inserted by | ||
| 24596 | extend_face_to_end_of_line. */ | ||
| 24597 | while (end > glyph | ||
| 24598 | && INTEGERP ((end - 1)->object) | ||
| 24599 | && (end - 1)->charpos <= 0) | ||
| 24600 | --end; | ||
| 24601 | /* Scan the rest of the glyph row from the end, looking for the | ||
| 24602 | first glyph that comes from BEFORE_STRING, AFTER_STRING, or | ||
| 24603 | DISPLAY_STRING, or whose position is between START_CHARPOS | ||
| 24604 | and END_CHARPOS */ | ||
| 24605 | for (--end; | ||
| 24606 | end > glyph | ||
| 24607 | && !INTEGERP (end->object) | ||
| 24608 | && !EQ (end->object, display_string) | ||
| 24609 | && !(BUFFERP (end->object) | ||
| 24610 | && (end->charpos >= start_charpos | ||
| 24611 | && end->charpos < end_charpos)); | ||
| 24612 | --end) | ||
| 24613 | { | ||
| 24614 | /* BEFORE_STRING or AFTER_STRING are only relevant if they | ||
| 24615 | are present at buffer positions between START_CHARPOS and | ||
| 24616 | END_CHARPOS, or if they come from an overlay. */ | ||
| 24617 | if (EQ (end->object, before_string)) | ||
| 24618 | { | ||
| 24619 | pos = string_buffer_position (w, before_string, start_charpos); | ||
| 24620 | if (!pos || (pos >= start_charpos && pos < end_charpos)) | ||
| 24621 | break; | ||
| 24622 | } | ||
| 24623 | else if (EQ (end->object, after_string)) | ||
| 24624 | { | ||
| 24625 | pos = string_buffer_position (w, after_string, end_charpos); | ||
| 24626 | if (!pos || (pos >= start_charpos && pos < end_charpos)) | ||
| 24627 | break; | ||
| 24628 | } | ||
| 24629 | } | ||
| 24630 | /* Find the X coordinate of the last glyph to be highlighted. */ | ||
| 24631 | for (; glyph <= end; ++glyph) | ||
| 23890 | x += glyph->pixel_width; | 24632 | x += glyph->pixel_width; |
| 24633 | |||
| 24634 | hlinfo->mouse_face_end_x = x; | ||
| 24635 | hlinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA]; | ||
| 23891 | } | 24636 | } |
| 23892 | else | 24637 | else |
| 23893 | { | 24638 | { |
| 23894 | /* If there's no after-string, we must check if we overshot, | 24639 | /* Skip truncation and continuation glyphs near the end of the |
| 23895 | which might be the case if we stopped after a string glyph. | 24640 | row, and also blanks and stretch glyphs inserted by |
| 23896 | That glyph may belong to a before-string or display-string | 24641 | extend_face_to_end_of_line. */ |
| 23897 | associated with the end position, which must not be | 24642 | x = r2->x; |
| 23898 | highlighted. */ | 24643 | end++; |
| 23899 | Lisp_Object prev_object; | 24644 | while (end < glyph |
| 23900 | EMACS_INT pos; | 24645 | && INTEGERP (end->object) |
| 23901 | 24646 | && end->charpos <= 0) | |
| 23902 | while (glyph > row->glyphs[TEXT_AREA]) | 24647 | { |
| 23903 | { | 24648 | x += end->pixel_width; |
| 23904 | prev_object = (glyph - 1)->object; | 24649 | ++end; |
| 23905 | if (!STRINGP (prev_object) || EQ (prev_object, display_string)) | 24650 | } |
| 23906 | break; | 24651 | /* Scan the rest of the glyph row from the end, looking for the |
| 23907 | 24652 | first glyph that comes from BEFORE_STRING, AFTER_STRING, or | |
| 23908 | pos = string_buffer_position (w, prev_object, end_charpos); | 24653 | DISPLAY_STRING, or whose position is between START_CHARPOS |
| 23909 | if (pos && pos < end_charpos) | 24654 | and END_CHARPOS */ |
| 23910 | break; | 24655 | for ( ; |
| 23911 | 24656 | end < glyph | |
| 23912 | for (; glyph > row->glyphs[TEXT_AREA] | 24657 | && !INTEGERP (end->object) |
| 23913 | && EQ ((glyph - 1)->object, prev_object); | 24658 | && !EQ (end->object, display_string) |
| 23914 | --glyph) | 24659 | && !(BUFFERP (end->object) |
| 23915 | x -= (glyph - 1)->pixel_width; | 24660 | && (end->charpos >= start_charpos |
| 24661 | && end->charpos < end_charpos)); | ||
| 24662 | ++end) | ||
| 24663 | { | ||
| 24664 | /* BEFORE_STRING or AFTER_STRING are only relevant if they | ||
| 24665 | are present at buffer positions between START_CHARPOS and | ||
| 24666 | END_CHARPOS, or if they come from an overlay. */ | ||
| 24667 | if (EQ (end->object, before_string)) | ||
| 24668 | { | ||
| 24669 | pos = string_buffer_position (w, before_string, start_charpos); | ||
| 24670 | if (!pos || (pos >= start_charpos && pos < end_charpos)) | ||
| 24671 | break; | ||
| 24672 | } | ||
| 24673 | else if (EQ (end->object, after_string)) | ||
| 24674 | { | ||
| 24675 | pos = string_buffer_position (w, after_string, end_charpos); | ||
| 24676 | if (!pos || (pos >= start_charpos && pos < end_charpos)) | ||
| 24677 | break; | ||
| 24678 | } | ||
| 24679 | x += end->pixel_width; | ||
| 23916 | } | 24680 | } |
| 24681 | hlinfo->mouse_face_end_x = x; | ||
| 24682 | hlinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA]; | ||
| 23917 | } | 24683 | } |
| 23918 | 24684 | ||
| 23919 | dpyinfo->mouse_face_end_x = x; | 24685 | hlinfo->mouse_face_window = window; |
| 23920 | dpyinfo->mouse_face_end_col = glyph - row->glyphs[TEXT_AREA]; | 24686 | hlinfo->mouse_face_face_id |
| 23921 | dpyinfo->mouse_face_window = window; | ||
| 23922 | dpyinfo->mouse_face_face_id | ||
| 23923 | = face_at_buffer_position (w, mouse_charpos, 0, 0, &ignore, | 24687 | = face_at_buffer_position (w, mouse_charpos, 0, 0, &ignore, |
| 23924 | mouse_charpos + 1, | 24688 | mouse_charpos + 1, |
| 23925 | !dpyinfo->mouse_face_hidden, -1); | 24689 | !hlinfo->mouse_face_hidden, -1); |
| 23926 | show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | 24690 | show_mouse_face (hlinfo, DRAW_MOUSE_FACE); |
| 23927 | } | 24691 | } |
| 23928 | 24692 | ||
| 24693 | /* The following function is not used anymore (replaced with | ||
| 24694 | mouse_face_from_string_pos), but I leave it here for the time | ||
| 24695 | being, in case someone would. */ | ||
| 24696 | |||
| 24697 | #if 0 /* not used */ | ||
| 23929 | 24698 | ||
| 23930 | /* Find the position of the glyph for position POS in OBJECT in | 24699 | /* Find the position of the glyph for position POS in OBJECT in |
| 23931 | window W's current matrix, and return in *X, *Y the pixel | 24700 | window W's current matrix, and return in *X, *Y the pixel |
| @@ -24003,7 +24772,132 @@ fast_find_string_pos (struct window *w, EMACS_INT pos, Lisp_Object object, | |||
| 24003 | 24772 | ||
| 24004 | return best_glyph != NULL; | 24773 | return best_glyph != NULL; |
| 24005 | } | 24774 | } |
| 24775 | #endif /* not used */ | ||
| 24006 | 24776 | ||
| 24777 | /* Find the positions of the first and the last glyphs in window W's | ||
| 24778 | current matrix that occlude positions [STARTPOS..ENDPOS] in OBJECT | ||
| 24779 | (assumed to be a string), and return in HLINFO's mouse_face_* | ||
| 24780 | members the pixel and column/row coordinates of those glyphs. */ | ||
| 24781 | |||
| 24782 | static void | ||
| 24783 | mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo, | ||
| 24784 | Lisp_Object object, | ||
| 24785 | EMACS_INT startpos, EMACS_INT endpos) | ||
| 24786 | { | ||
| 24787 | int yb = window_text_bottom_y (w); | ||
| 24788 | struct glyph_row *r; | ||
| 24789 | struct glyph *g, *e; | ||
| 24790 | int gx; | ||
| 24791 | int found = 0; | ||
| 24792 | |||
| 24793 | /* Find the glyph row with at least one position in the range | ||
| 24794 | [STARTPOS..ENDPOS], and the first glyph in that row whose | ||
| 24795 | position belongs to that range. */ | ||
| 24796 | for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | ||
| 24797 | r->enabled_p && r->y < yb; | ||
| 24798 | ++r) | ||
| 24799 | { | ||
| 24800 | if (!r->reversed_p) | ||
| 24801 | { | ||
| 24802 | g = r->glyphs[TEXT_AREA]; | ||
| 24803 | e = g + r->used[TEXT_AREA]; | ||
| 24804 | for (gx = r->x; g < e; gx += g->pixel_width, ++g) | ||
| 24805 | if (EQ (g->object, object) | ||
| 24806 | && startpos <= g->charpos && g->charpos <= endpos) | ||
| 24807 | { | ||
| 24808 | hlinfo->mouse_face_beg_row = r - w->current_matrix->rows; | ||
| 24809 | hlinfo->mouse_face_beg_y = r->y; | ||
| 24810 | hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA]; | ||
| 24811 | hlinfo->mouse_face_beg_x = gx; | ||
| 24812 | found = 1; | ||
| 24813 | break; | ||
| 24814 | } | ||
| 24815 | } | ||
| 24816 | else | ||
| 24817 | { | ||
| 24818 | struct glyph *g1; | ||
| 24819 | |||
| 24820 | e = r->glyphs[TEXT_AREA]; | ||
| 24821 | g = e + r->used[TEXT_AREA]; | ||
| 24822 | for ( ; g > e; --g) | ||
| 24823 | if (EQ ((g-1)->object, object) | ||
| 24824 | && startpos <= (g-1)->charpos && (g-1)->charpos <= endpos) | ||
| 24825 | { | ||
| 24826 | hlinfo->mouse_face_beg_row = r - w->current_matrix->rows; | ||
| 24827 | hlinfo->mouse_face_beg_y = r->y; | ||
| 24828 | hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA]; | ||
| 24829 | for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1) | ||
| 24830 | gx += g1->pixel_width; | ||
| 24831 | hlinfo->mouse_face_beg_x = gx; | ||
| 24832 | found = 1; | ||
| 24833 | break; | ||
| 24834 | } | ||
| 24835 | } | ||
| 24836 | if (found) | ||
| 24837 | break; | ||
| 24838 | } | ||
| 24839 | |||
| 24840 | if (!found) | ||
| 24841 | return; | ||
| 24842 | |||
| 24843 | /* Starting with the next row, look for the first row which does NOT | ||
| 24844 | include any glyphs whose positions are in the range. */ | ||
| 24845 | for (++r; r->enabled_p && r->y < yb; ++r) | ||
| 24846 | { | ||
| 24847 | g = r->glyphs[TEXT_AREA]; | ||
| 24848 | e = g + r->used[TEXT_AREA]; | ||
| 24849 | found = 0; | ||
| 24850 | for ( ; g < e; ++g) | ||
| 24851 | if (EQ (g->object, object) | ||
| 24852 | && startpos <= g->charpos && g->charpos <= endpos) | ||
| 24853 | { | ||
| 24854 | found = 1; | ||
| 24855 | break; | ||
| 24856 | } | ||
| 24857 | if (!found) | ||
| 24858 | break; | ||
| 24859 | } | ||
| 24860 | |||
| 24861 | /* The highlighted region ends on the previous row. */ | ||
| 24862 | r--; | ||
| 24863 | |||
| 24864 | /* Set the end row and its vertical pixel coordinate. */ | ||
| 24865 | hlinfo->mouse_face_end_row = r - w->current_matrix->rows; | ||
| 24866 | hlinfo->mouse_face_end_y = r->y; | ||
| 24867 | |||
| 24868 | /* Compute and set the end column and the end column's horizontal | ||
| 24869 | pixel coordinate. */ | ||
| 24870 | if (!r->reversed_p) | ||
| 24871 | { | ||
| 24872 | g = r->glyphs[TEXT_AREA]; | ||
| 24873 | e = g + r->used[TEXT_AREA]; | ||
| 24874 | for ( ; e > g; --e) | ||
| 24875 | if (EQ ((e-1)->object, object) | ||
| 24876 | && startpos <= (e-1)->charpos && (e-1)->charpos <= endpos) | ||
| 24877 | break; | ||
| 24878 | hlinfo->mouse_face_end_col = e - g; | ||
| 24879 | |||
| 24880 | for (gx = r->x; g < e; ++g) | ||
| 24881 | gx += g->pixel_width; | ||
| 24882 | hlinfo->mouse_face_end_x = gx; | ||
| 24883 | } | ||
| 24884 | else | ||
| 24885 | { | ||
| 24886 | e = r->glyphs[TEXT_AREA]; | ||
| 24887 | g = e + r->used[TEXT_AREA]; | ||
| 24888 | for (gx = r->x ; e < g; ++e) | ||
| 24889 | { | ||
| 24890 | if (EQ (e->object, object) | ||
| 24891 | && startpos <= e->charpos && e->charpos <= endpos) | ||
| 24892 | break; | ||
| 24893 | gx += e->pixel_width; | ||
| 24894 | } | ||
| 24895 | hlinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA]; | ||
| 24896 | hlinfo->mouse_face_end_x = gx; | ||
| 24897 | } | ||
| 24898 | } | ||
| 24899 | |||
| 24900 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 24007 | 24901 | ||
| 24008 | /* See if position X, Y is within a hot-spot of an image. */ | 24902 | /* See if position X, Y is within a hot-spot of an image. */ |
| 24009 | 24903 | ||
| @@ -24175,6 +25069,8 @@ define_frame_cursor1 (struct frame *f, Cursor cursor, Lisp_Object pointer) | |||
| 24175 | FRAME_RIF (f)->define_frame_cursor (f, cursor); | 25069 | FRAME_RIF (f)->define_frame_cursor (f, cursor); |
| 24176 | } | 25070 | } |
| 24177 | 25071 | ||
| 25072 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 25073 | |||
| 24178 | /* Take proper action when mouse has moved to the mode or header line | 25074 | /* Take proper action when mouse has moved to the mode or header line |
| 24179 | or marginal area AREA of window W, x-position X and y-position Y. | 25075 | or marginal area AREA of window W, x-position X and y-position Y. |
| 24180 | X is relative to the start of the text display area of W, so the | 25076 | X is relative to the start of the text display area of W, so the |
| @@ -24187,8 +25083,11 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, | |||
| 24187 | { | 25083 | { |
| 24188 | struct window *w = XWINDOW (window); | 25084 | struct window *w = XWINDOW (window); |
| 24189 | struct frame *f = XFRAME (w->frame); | 25085 | struct frame *f = XFRAME (w->frame); |
| 24190 | Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | 25086 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); |
| 24191 | Cursor cursor = FRAME_X_OUTPUT (f)->nontext_cursor; | 25087 | #ifdef HAVE_WINDOW_SYSTEM |
| 25088 | Display_Info *dpyinfo; | ||
| 25089 | #endif | ||
| 25090 | Cursor cursor = No_Cursor; | ||
| 24192 | Lisp_Object pointer = Qnil; | 25091 | Lisp_Object pointer = Qnil; |
| 24193 | int dx, dy, width, height; | 25092 | int dx, dy, width, height; |
| 24194 | EMACS_INT charpos; | 25093 | EMACS_INT charpos; |
| @@ -24205,6 +25104,8 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, | |||
| 24205 | int x0; | 25104 | int x0; |
| 24206 | struct glyph *end; | 25105 | struct glyph *end; |
| 24207 | 25106 | ||
| 25107 | /* Kludge alert: mode_line_string takes X/Y in pixels, but | ||
| 25108 | returns them in row/column units! */ | ||
| 24208 | string = mode_line_string (w, area, &x, &y, &charpos, | 25109 | string = mode_line_string (w, area, &x, &y, &charpos, |
| 24209 | &object, &dx, &dy, &width, &height); | 25110 | &object, &dx, &dy, &width, &height); |
| 24210 | 25111 | ||
| @@ -24212,7 +25113,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, | |||
| 24212 | ? MATRIX_MODE_LINE_ROW (w->current_matrix) | 25113 | ? MATRIX_MODE_LINE_ROW (w->current_matrix) |
| 24213 | : MATRIX_HEADER_LINE_ROW (w->current_matrix)); | 25114 | : MATRIX_HEADER_LINE_ROW (w->current_matrix)); |
| 24214 | 25115 | ||
| 24215 | /* Find glyph */ | 25116 | /* Find the glyph under the mouse pointer. */ |
| 24216 | if (row->mode_line_p && row->enabled_p) | 25117 | if (row->mode_line_p && row->enabled_p) |
| 24217 | { | 25118 | { |
| 24218 | glyph = row_start_glyph = row->glyphs[TEXT_AREA]; | 25119 | glyph = row_start_glyph = row->glyphs[TEXT_AREA]; |
| @@ -24230,12 +25131,15 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, | |||
| 24230 | else | 25131 | else |
| 24231 | { | 25132 | { |
| 24232 | x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w); | 25133 | x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w); |
| 25134 | /* Kludge alert: marginal_area_string takes X/Y in pixels, but | ||
| 25135 | returns them in row/column units! */ | ||
| 24233 | string = marginal_area_string (w, area, &x, &y, &charpos, | 25136 | string = marginal_area_string (w, area, &x, &y, &charpos, |
| 24234 | &object, &dx, &dy, &width, &height); | 25137 | &object, &dx, &dy, &width, &height); |
| 24235 | } | 25138 | } |
| 24236 | 25139 | ||
| 24237 | help = Qnil; | 25140 | help = Qnil; |
| 24238 | 25141 | ||
| 25142 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 24239 | if (IMAGEP (object)) | 25143 | if (IMAGEP (object)) |
| 24240 | { | 25144 | { |
| 24241 | Lisp_Object image_map, hotspot; | 25145 | Lisp_Object image_map, hotspot; |
| @@ -24272,6 +25176,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, | |||
| 24272 | if (NILP (pointer)) | 25176 | if (NILP (pointer)) |
| 24273 | pointer = Fplist_get (XCDR (object), QCpointer); | 25177 | pointer = Fplist_get (XCDR (object), QCpointer); |
| 24274 | } | 25178 | } |
| 25179 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 24275 | 25180 | ||
| 24276 | if (STRINGP (string)) | 25181 | if (STRINGP (string)) |
| 24277 | { | 25182 | { |
| @@ -24291,19 +25196,27 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, | |||
| 24291 | } | 25196 | } |
| 24292 | } | 25197 | } |
| 24293 | 25198 | ||
| 24294 | if (NILP (pointer)) | 25199 | #ifdef HAVE_WINDOW_SYSTEM |
| 24295 | pointer = Fget_text_property (pos, Qpointer, string); | 25200 | if (FRAME_WINDOW_P (f)) |
| 24296 | |||
| 24297 | /* Change the mouse pointer according to what is under X/Y. */ | ||
| 24298 | if (NILP (pointer) && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE))) | ||
| 24299 | { | 25201 | { |
| 24300 | Lisp_Object map; | 25202 | dpyinfo = FRAME_X_DISPLAY_INFO (f); |
| 24301 | map = Fget_text_property (pos, Qlocal_map, string); | 25203 | cursor = FRAME_X_OUTPUT (f)->nontext_cursor; |
| 24302 | if (!KEYMAPP (map)) | 25204 | if (NILP (pointer)) |
| 24303 | map = Fget_text_property (pos, Qkeymap, string); | 25205 | pointer = Fget_text_property (pos, Qpointer, string); |
| 24304 | if (!KEYMAPP (map)) | 25206 | |
| 24305 | cursor = dpyinfo->vertical_scroll_bar_cursor; | 25207 | /* Change the mouse pointer according to what is under X/Y. */ |
| 25208 | if (NILP (pointer) | ||
| 25209 | && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE))) | ||
| 25210 | { | ||
| 25211 | Lisp_Object map; | ||
| 25212 | map = Fget_text_property (pos, Qlocal_map, string); | ||
| 25213 | if (!KEYMAPP (map)) | ||
| 25214 | map = Fget_text_property (pos, Qkeymap, string); | ||
| 25215 | if (!KEYMAPP (map)) | ||
| 25216 | cursor = dpyinfo->vertical_scroll_bar_cursor; | ||
| 25217 | } | ||
| 24306 | } | 25218 | } |
| 25219 | #endif | ||
| 24307 | 25220 | ||
| 24308 | /* Change the mouse face according to what is under X/Y. */ | 25221 | /* Change the mouse face according to what is under X/Y. */ |
| 24309 | mouse_face = Fget_text_property (pos, Qmouse_face, string); | 25222 | mouse_face = Fget_text_property (pos, Qmouse_face, string); |
| @@ -24318,102 +25231,128 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, | |||
| 24318 | int gpos; | 25231 | int gpos; |
| 24319 | int gseq_length; | 25232 | int gseq_length; |
| 24320 | int total_pixel_width; | 25233 | int total_pixel_width; |
| 24321 | EMACS_INT ignore; | 25234 | EMACS_INT begpos, endpos, ignore; |
| 24322 | 25235 | ||
| 24323 | int vpos, hpos; | 25236 | int vpos, hpos; |
| 24324 | 25237 | ||
| 24325 | b = Fprevious_single_property_change (make_number (charpos + 1), | 25238 | b = Fprevious_single_property_change (make_number (charpos + 1), |
| 24326 | Qmouse_face, string, Qnil); | 25239 | Qmouse_face, string, Qnil); |
| 24327 | if (NILP (b)) | 25240 | if (NILP (b)) |
| 24328 | b = make_number (0); | 25241 | begpos = 0; |
| 25242 | else | ||
| 25243 | begpos = XINT (b); | ||
| 24329 | 25244 | ||
| 24330 | e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil); | 25245 | e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil); |
| 24331 | if (NILP (e)) | 25246 | if (NILP (e)) |
| 24332 | e = make_number (SCHARS (string)); | 25247 | endpos = SCHARS (string); |
| 24333 | 25248 | else | |
| 24334 | /* Calculate the position(glyph position: GPOS) of GLYPH in | 25249 | endpos = XINT (e); |
| 24335 | displayed string. GPOS is different from CHARPOS. | 25250 | |
| 24336 | 25251 | /* Calculate the glyph position GPOS of GLYPH in the | |
| 24337 | CHARPOS is the position of glyph in internal string | 25252 | displayed string, relative to the beginning of the |
| 24338 | object. A mode line string format has structures which | 25253 | highlighted part of the string. |
| 24339 | is converted to a flatten by emacs lisp interpreter. | 25254 | |
| 24340 | The internal string is an element of the structures. | 25255 | Note: GPOS is different from CHARPOS. CHARPOS is the |
| 24341 | The displayed string is the flatten string. */ | 25256 | position of GLYPH in the internal string object. A mode |
| 24342 | gpos = 0; | 25257 | line string format has structures which are converted to |
| 24343 | if (glyph > row_start_glyph) | 25258 | a flattened string by the Emacs Lisp interpreter. The |
| 24344 | { | 25259 | internal string is an element of those structures. The |
| 24345 | tmp_glyph = glyph - 1; | 25260 | displayed string is the flattened string. */ |
| 24346 | while (tmp_glyph >= row_start_glyph | 25261 | tmp_glyph = row_start_glyph; |
| 24347 | && tmp_glyph->charpos >= XINT (b) | 25262 | while (tmp_glyph < glyph |
| 24348 | && EQ (tmp_glyph->object, glyph->object)) | 25263 | && (!(EQ (tmp_glyph->object, glyph->object) |
| 24349 | { | 25264 | && begpos <= tmp_glyph->charpos |
| 24350 | tmp_glyph--; | 25265 | && tmp_glyph->charpos < endpos))) |
| 24351 | gpos++; | 25266 | tmp_glyph++; |
| 24352 | } | 25267 | gpos = glyph - tmp_glyph; |
| 24353 | } | 25268 | |
| 24354 | 25269 | /* Calculate the length GSEQ_LENGTH of the glyph sequence of | |
| 24355 | /* Calculate the lenght(glyph sequence length: GSEQ_LENGTH) of | 25270 | the highlighted part of the displayed string to which |
| 24356 | displayed string holding GLYPH. | 25271 | GLYPH belongs. Note: GSEQ_LENGTH is different from |
| 24357 | 25272 | SCHARS (STRING), because the latter returns the length of | |
| 24358 | GSEQ_LENGTH is different from SCHARS (STRING). | 25273 | the internal string. */ |
| 24359 | SCHARS (STRING) returns the length of the internal string. */ | 25274 | for (tmp_glyph = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1; |
| 24360 | for (tmp_glyph = glyph, gseq_length = gpos; | 25275 | tmp_glyph > glyph |
| 24361 | tmp_glyph->charpos < XINT (e); | 25276 | && (!(EQ (tmp_glyph->object, glyph->object) |
| 24362 | tmp_glyph++, gseq_length++) | 25277 | && begpos <= tmp_glyph->charpos |
| 24363 | { | 25278 | && tmp_glyph->charpos < endpos)); |
| 24364 | if (!EQ (tmp_glyph->object, glyph->object)) | 25279 | tmp_glyph--) |
| 24365 | break; | 25280 | ; |
| 24366 | } | 25281 | gseq_length = gpos + (tmp_glyph - glyph) + 1; |
| 24367 | 25282 | ||
| 25283 | /* Calculate the total pixel width of all the glyphs between | ||
| 25284 | the beginning of the highlighted area and GLYPH. */ | ||
| 24368 | total_pixel_width = 0; | 25285 | total_pixel_width = 0; |
| 24369 | for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++) | 25286 | for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++) |
| 24370 | total_pixel_width += tmp_glyph->pixel_width; | 25287 | total_pixel_width += tmp_glyph->pixel_width; |
| 24371 | 25288 | ||
| 24372 | /* Pre calculation of re-rendering position */ | 25289 | /* Pre calculation of re-rendering position. Note: X is in |
| 24373 | vpos = (x - gpos); | 25290 | column units here, after the call to mode_line_string or |
| 24374 | hpos = (area == ON_MODE_LINE | 25291 | marginal_area_string. */ |
| 25292 | hpos = x - gpos; | ||
| 25293 | vpos = (area == ON_MODE_LINE | ||
| 24375 | ? (w->current_matrix)->nrows - 1 | 25294 | ? (w->current_matrix)->nrows - 1 |
| 24376 | : 0); | 25295 | : 0); |
| 24377 | 25296 | ||
| 24378 | /* If the re-rendering position is included in the last | 25297 | /* If GLYPH's position is included in the region that is |
| 24379 | re-rendering area, we should do nothing. */ | 25298 | already drawn in mouse face, we have nothing to do. */ |
| 24380 | if ( EQ (window, dpyinfo->mouse_face_window) | 25299 | if ( EQ (window, hlinfo->mouse_face_window) |
| 24381 | && dpyinfo->mouse_face_beg_col <= vpos | 25300 | && (!row->reversed_p |
| 24382 | && vpos < dpyinfo->mouse_face_end_col | 25301 | ? (hlinfo->mouse_face_beg_col <= hpos |
| 24383 | && dpyinfo->mouse_face_beg_row == hpos ) | 25302 | && hpos < hlinfo->mouse_face_end_col) |
| 25303 | /* In R2L rows we swap BEG and END, see below. */ | ||
| 25304 | : (hlinfo->mouse_face_end_col <= hpos | ||
| 25305 | && hpos < hlinfo->mouse_face_beg_col)) | ||
| 25306 | && hlinfo->mouse_face_beg_row == vpos ) | ||
| 24384 | return; | 25307 | return; |
| 24385 | 25308 | ||
| 24386 | if (clear_mouse_face (dpyinfo)) | 25309 | if (clear_mouse_face (hlinfo)) |
| 24387 | cursor = No_Cursor; | 25310 | cursor = No_Cursor; |
| 24388 | 25311 | ||
| 24389 | dpyinfo->mouse_face_beg_col = vpos; | 25312 | if (!row->reversed_p) |
| 24390 | dpyinfo->mouse_face_beg_row = hpos; | 25313 | { |
| 24391 | 25314 | hlinfo->mouse_face_beg_col = hpos; | |
| 24392 | dpyinfo->mouse_face_beg_x = original_x_pixel - (total_pixel_width + dx); | 25315 | hlinfo->mouse_face_beg_x = original_x_pixel |
| 24393 | dpyinfo->mouse_face_beg_y = 0; | 25316 | - (total_pixel_width + dx); |
| 24394 | 25317 | hlinfo->mouse_face_end_col = hpos + gseq_length; | |
| 24395 | dpyinfo->mouse_face_end_col = vpos + gseq_length; | 25318 | hlinfo->mouse_face_end_x = 0; |
| 24396 | dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_beg_row; | 25319 | } |
| 24397 | 25320 | else | |
| 24398 | dpyinfo->mouse_face_end_x = 0; | 25321 | { |
| 24399 | dpyinfo->mouse_face_end_y = 0; | 25322 | /* In R2L rows, show_mouse_face expects BEG and END |
| 24400 | 25323 | coordinates to be swapped. */ | |
| 24401 | dpyinfo->mouse_face_past_end = 0; | 25324 | hlinfo->mouse_face_end_col = hpos; |
| 24402 | dpyinfo->mouse_face_window = window; | 25325 | hlinfo->mouse_face_end_x = original_x_pixel |
| 25326 | - (total_pixel_width + dx); | ||
| 25327 | hlinfo->mouse_face_beg_col = hpos + gseq_length; | ||
| 25328 | hlinfo->mouse_face_beg_x = 0; | ||
| 25329 | } | ||
| 24403 | 25330 | ||
| 24404 | dpyinfo->mouse_face_face_id = face_at_string_position (w, string, | 25331 | hlinfo->mouse_face_beg_row = vpos; |
| 24405 | charpos, | 25332 | hlinfo->mouse_face_end_row = hlinfo->mouse_face_beg_row; |
| 24406 | 0, 0, 0, &ignore, | 25333 | hlinfo->mouse_face_beg_y = 0; |
| 24407 | glyph->face_id, 1); | 25334 | hlinfo->mouse_face_end_y = 0; |
| 24408 | show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | 25335 | hlinfo->mouse_face_past_end = 0; |
| 25336 | hlinfo->mouse_face_window = window; | ||
| 25337 | |||
| 25338 | hlinfo->mouse_face_face_id = face_at_string_position (w, string, | ||
| 25339 | charpos, | ||
| 25340 | 0, 0, 0, | ||
| 25341 | &ignore, | ||
| 25342 | glyph->face_id, | ||
| 25343 | 1); | ||
| 25344 | show_mouse_face (hlinfo, DRAW_MOUSE_FACE); | ||
| 24409 | 25345 | ||
| 24410 | if (NILP (pointer)) | 25346 | if (NILP (pointer)) |
| 24411 | pointer = Qhand; | 25347 | pointer = Qhand; |
| 24412 | } | 25348 | } |
| 24413 | else if ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)) | 25349 | else if ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)) |
| 24414 | clear_mouse_face (dpyinfo); | 25350 | clear_mouse_face (hlinfo); |
| 24415 | } | 25351 | } |
| 24416 | define_frame_cursor1 (f, cursor, pointer); | 25352 | #ifdef HAVE_WINDOW_SYSTEM |
| 25353 | if (FRAME_WINDOW_P (f)) | ||
| 25354 | define_frame_cursor1 (f, cursor, pointer); | ||
| 25355 | #endif | ||
| 24417 | } | 25356 | } |
| 24418 | 25357 | ||
| 24419 | 25358 | ||
| @@ -24426,7 +25365,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, | |||
| 24426 | void | 25365 | void |
| 24427 | note_mouse_highlight (struct frame *f, int x, int y) | 25366 | note_mouse_highlight (struct frame *f, int x, int y) |
| 24428 | { | 25367 | { |
| 24429 | Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | 25368 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); |
| 24430 | enum window_part part; | 25369 | enum window_part part; |
| 24431 | Lisp_Object window; | 25370 | Lisp_Object window; |
| 24432 | struct window *w; | 25371 | struct window *w; |
| @@ -24435,7 +25374,7 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24435 | struct buffer *b; | 25374 | struct buffer *b; |
| 24436 | 25375 | ||
| 24437 | /* When a menu is active, don't highlight because this looks odd. */ | 25376 | /* When a menu is active, don't highlight because this looks odd. */ |
| 24438 | #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) | 25377 | #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (MSDOS) |
| 24439 | if (popup_activated ()) | 25378 | if (popup_activated ()) |
| 24440 | return; | 25379 | return; |
| 24441 | #endif | 25380 | #endif |
| @@ -24445,28 +25384,28 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24445 | || f->pointer_invisible) | 25384 | || f->pointer_invisible) |
| 24446 | return; | 25385 | return; |
| 24447 | 25386 | ||
| 24448 | dpyinfo->mouse_face_mouse_x = x; | 25387 | hlinfo->mouse_face_mouse_x = x; |
| 24449 | dpyinfo->mouse_face_mouse_y = y; | 25388 | hlinfo->mouse_face_mouse_y = y; |
| 24450 | dpyinfo->mouse_face_mouse_frame = f; | 25389 | hlinfo->mouse_face_mouse_frame = f; |
| 24451 | 25390 | ||
| 24452 | if (dpyinfo->mouse_face_defer) | 25391 | if (hlinfo->mouse_face_defer) |
| 24453 | return; | 25392 | return; |
| 24454 | 25393 | ||
| 24455 | if (gc_in_progress) | 25394 | if (gc_in_progress) |
| 24456 | { | 25395 | { |
| 24457 | dpyinfo->mouse_face_deferred_gc = 1; | 25396 | hlinfo->mouse_face_deferred_gc = 1; |
| 24458 | return; | 25397 | return; |
| 24459 | } | 25398 | } |
| 24460 | 25399 | ||
| 24461 | /* Which window is that in? */ | 25400 | /* Which window is that in? */ |
| 24462 | window = window_from_coordinates (f, x, y, &part, 0, 0, 1); | 25401 | window = window_from_coordinates (f, x, y, &part, 1); |
| 24463 | 25402 | ||
| 24464 | /* If we were displaying active text in another window, clear that. | 25403 | /* If we were displaying active text in another window, clear that. |
| 24465 | Also clear if we move out of text area in same window. */ | 25404 | Also clear if we move out of text area in same window. */ |
| 24466 | if (! EQ (window, dpyinfo->mouse_face_window) | 25405 | if (! EQ (window, hlinfo->mouse_face_window) |
| 24467 | || (part != ON_TEXT && part != ON_MODE_LINE && part != ON_HEADER_LINE | 25406 | || (part != ON_TEXT && part != ON_MODE_LINE && part != ON_HEADER_LINE |
| 24468 | && !NILP (dpyinfo->mouse_face_window))) | 25407 | && !NILP (hlinfo->mouse_face_window))) |
| 24469 | clear_mouse_face (dpyinfo); | 25408 | clear_mouse_face (hlinfo); |
| 24470 | 25409 | ||
| 24471 | /* Not on a window -> return. */ | 25410 | /* Not on a window -> return. */ |
| 24472 | if (!WINDOWP (window)) | 25411 | if (!WINDOWP (window)) |
| @@ -24479,6 +25418,7 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24479 | w = XWINDOW (window); | 25418 | w = XWINDOW (window); |
| 24480 | frame_to_window_pixel_xy (w, &x, &y); | 25419 | frame_to_window_pixel_xy (w, &x, &y); |
| 24481 | 25420 | ||
| 25421 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 24482 | /* Handle tool-bar window differently since it doesn't display a | 25422 | /* Handle tool-bar window differently since it doesn't display a |
| 24483 | buffer. */ | 25423 | buffer. */ |
| 24484 | if (EQ (window, f->tool_bar_window)) | 25424 | if (EQ (window, f->tool_bar_window)) |
| @@ -24486,6 +25426,7 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24486 | note_tool_bar_highlight (f, x, y); | 25426 | note_tool_bar_highlight (f, x, y); |
| 24487 | return; | 25427 | return; |
| 24488 | } | 25428 | } |
| 25429 | #endif | ||
| 24489 | 25430 | ||
| 24490 | /* Mouse is on the mode, header line or margin? */ | 25431 | /* Mouse is on the mode, header line or margin? */ |
| 24491 | if (part == ON_MODE_LINE || part == ON_HEADER_LINE | 25432 | if (part == ON_MODE_LINE || part == ON_HEADER_LINE |
| @@ -24495,6 +25436,7 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24495 | return; | 25436 | return; |
| 24496 | } | 25437 | } |
| 24497 | 25438 | ||
| 25439 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 24498 | if (part == ON_VERTICAL_BORDER) | 25440 | if (part == ON_VERTICAL_BORDER) |
| 24499 | { | 25441 | { |
| 24500 | cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor; | 25442 | cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor; |
| @@ -24505,6 +25447,7 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24505 | cursor = FRAME_X_OUTPUT (f)->nontext_cursor; | 25447 | cursor = FRAME_X_OUTPUT (f)->nontext_cursor; |
| 24506 | else | 25448 | else |
| 24507 | cursor = FRAME_X_OUTPUT (f)->text_cursor; | 25449 | cursor = FRAME_X_OUTPUT (f)->text_cursor; |
| 25450 | #endif | ||
| 24508 | 25451 | ||
| 24509 | /* Are we in a window whose display is up to date? | 25452 | /* Are we in a window whose display is up to date? |
| 24510 | And verify the buffer's text has not changed. */ | 25453 | And verify the buffer's text has not changed. */ |
| @@ -24528,6 +25471,7 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24528 | /* Find the glyph under X/Y. */ | 25471 | /* Find the glyph under X/Y. */ |
| 24529 | glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area); | 25472 | glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area); |
| 24530 | 25473 | ||
| 25474 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 24531 | /* Look for :pointer property on image. */ | 25475 | /* Look for :pointer property on image. */ |
| 24532 | if (glyph != NULL && glyph->type == IMAGE_GLYPH) | 25476 | if (glyph != NULL && glyph->type == IMAGE_GLYPH) |
| 24533 | { | 25477 | { |
| @@ -24569,21 +25513,38 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24569 | pointer = Fplist_get (XCDR (img->spec), QCpointer); | 25513 | pointer = Fplist_get (XCDR (img->spec), QCpointer); |
| 24570 | } | 25514 | } |
| 24571 | } | 25515 | } |
| 25516 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 24572 | 25517 | ||
| 24573 | /* Clear mouse face if X/Y not over text. */ | 25518 | /* Clear mouse face if X/Y not over text. */ |
| 24574 | if (glyph == NULL | 25519 | if (glyph == NULL |
| 24575 | || area != TEXT_AREA | 25520 | || area != TEXT_AREA |
| 24576 | || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p) | 25521 | || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p |
| 24577 | { | 25522 | /* Glyph's OBJECT is an integer for glyphs inserted by the |
| 24578 | if (clear_mouse_face (dpyinfo)) | 25523 | display engine for its internal purposes, like truncation |
| 25524 | and continuation glyphs and blanks beyond the end of | ||
| 25525 | line's text on text terminals. If we are over such a | ||
| 25526 | glyph, we are not over any text. */ | ||
| 25527 | || INTEGERP (glyph->object) | ||
| 25528 | /* R2L rows have a stretch glyph at their front, which | ||
| 25529 | stands for no text, whereas L2R rows have no glyphs at | ||
| 25530 | all beyond the end of text. Treat such stretch glyphs | ||
| 25531 | like we do with NULL glyphs in L2R rows. */ | ||
| 25532 | || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p | ||
| 25533 | && glyph == MATRIX_ROW (w->current_matrix, vpos)->glyphs[TEXT_AREA] | ||
| 25534 | && glyph->type == STRETCH_GLYPH | ||
| 25535 | && glyph->avoid_cursor_p)) | ||
| 25536 | { | ||
| 25537 | if (clear_mouse_face (hlinfo)) | ||
| 24579 | cursor = No_Cursor; | 25538 | cursor = No_Cursor; |
| 24580 | if (NILP (pointer)) | 25539 | #ifdef HAVE_WINDOW_SYSTEM |
| 25540 | if (FRAME_WINDOW_P (f) && NILP (pointer)) | ||
| 24581 | { | 25541 | { |
| 24582 | if (area != TEXT_AREA) | 25542 | if (area != TEXT_AREA) |
| 24583 | cursor = FRAME_X_OUTPUT (f)->nontext_cursor; | 25543 | cursor = FRAME_X_OUTPUT (f)->nontext_cursor; |
| 24584 | else | 25544 | else |
| 24585 | pointer = Vvoid_text_area_pointer; | 25545 | pointer = Vvoid_text_area_pointer; |
| 24586 | } | 25546 | } |
| 25547 | #endif | ||
| 24587 | goto set_cursor; | 25548 | goto set_cursor; |
| 24588 | } | 25549 | } |
| 24589 | 25550 | ||
| @@ -24618,14 +25579,7 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24618 | else | 25579 | else |
| 24619 | noverlays = 0; | 25580 | noverlays = 0; |
| 24620 | 25581 | ||
| 24621 | same_region = (EQ (window, dpyinfo->mouse_face_window) | 25582 | same_region = coords_in_mouse_face_p (w, hpos, vpos); |
| 24622 | && vpos >= dpyinfo->mouse_face_beg_row | ||
| 24623 | && vpos <= dpyinfo->mouse_face_end_row | ||
| 24624 | && (vpos > dpyinfo->mouse_face_beg_row | ||
| 24625 | || hpos >= dpyinfo->mouse_face_beg_col) | ||
| 24626 | && (vpos < dpyinfo->mouse_face_end_row | ||
| 24627 | || hpos < dpyinfo->mouse_face_end_col | ||
| 24628 | || dpyinfo->mouse_face_past_end)); | ||
| 24629 | 25583 | ||
| 24630 | if (same_region) | 25584 | if (same_region) |
| 24631 | cursor = No_Cursor; | 25585 | cursor = No_Cursor; |
| @@ -24636,8 +25590,8 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24636 | the one we are currently highlighting, we have to | 25590 | the one we are currently highlighting, we have to |
| 24637 | check if we enter the overlapping overlay, and then | 25591 | check if we enter the overlapping overlay, and then |
| 24638 | highlight only that. */ | 25592 | highlight only that. */ |
| 24639 | || (OVERLAYP (dpyinfo->mouse_face_overlay) | 25593 | || (OVERLAYP (hlinfo->mouse_face_overlay) |
| 24640 | && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay))) | 25594 | && mouse_face_overlay_overlaps (hlinfo->mouse_face_overlay))) |
| 24641 | { | 25595 | { |
| 24642 | /* Find the highest priority overlay with a mouse-face. */ | 25596 | /* Find the highest priority overlay with a mouse-face. */ |
| 24643 | overlay = Qnil; | 25597 | overlay = Qnil; |
| @@ -24650,12 +25604,12 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24650 | 25604 | ||
| 24651 | /* If we're highlighting the same overlay as before, there's | 25605 | /* If we're highlighting the same overlay as before, there's |
| 24652 | no need to do that again. */ | 25606 | no need to do that again. */ |
| 24653 | if (!NILP (overlay) && EQ (overlay, dpyinfo->mouse_face_overlay)) | 25607 | if (!NILP (overlay) && EQ (overlay, hlinfo->mouse_face_overlay)) |
| 24654 | goto check_help_echo; | 25608 | goto check_help_echo; |
| 24655 | dpyinfo->mouse_face_overlay = overlay; | 25609 | hlinfo->mouse_face_overlay = overlay; |
| 24656 | 25610 | ||
| 24657 | /* Clear the display of the old active region, if any. */ | 25611 | /* Clear the display of the old active region, if any. */ |
| 24658 | if (clear_mouse_face (dpyinfo)) | 25612 | if (clear_mouse_face (hlinfo)) |
| 24659 | cursor = No_Cursor; | 25613 | cursor = No_Cursor; |
| 24660 | 25614 | ||
| 24661 | /* If no overlay applies, get a text property. */ | 25615 | /* If no overlay applies, get a text property. */ |
| @@ -24679,23 +25633,14 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24679 | b = make_number (0); | 25633 | b = make_number (0); |
| 24680 | if (NILP (e)) | 25634 | if (NILP (e)) |
| 24681 | e = make_number (SCHARS (object) - 1); | 25635 | e = make_number (SCHARS (object) - 1); |
| 24682 | 25636 | mouse_face_from_string_pos (w, hlinfo, object, | |
| 24683 | fast_find_string_pos (w, XINT (b), object, | 25637 | XINT (b), XINT (e)); |
| 24684 | &dpyinfo->mouse_face_beg_col, | 25638 | hlinfo->mouse_face_past_end = 0; |
| 24685 | &dpyinfo->mouse_face_beg_row, | 25639 | hlinfo->mouse_face_window = window; |
| 24686 | &dpyinfo->mouse_face_beg_x, | 25640 | hlinfo->mouse_face_face_id |
| 24687 | &dpyinfo->mouse_face_beg_y, 0); | ||
| 24688 | fast_find_string_pos (w, XINT (e), object, | ||
| 24689 | &dpyinfo->mouse_face_end_col, | ||
| 24690 | &dpyinfo->mouse_face_end_row, | ||
| 24691 | &dpyinfo->mouse_face_end_x, | ||
| 24692 | &dpyinfo->mouse_face_end_y, 1); | ||
| 24693 | dpyinfo->mouse_face_past_end = 0; | ||
| 24694 | dpyinfo->mouse_face_window = window; | ||
| 24695 | dpyinfo->mouse_face_face_id | ||
| 24696 | = face_at_string_position (w, object, pos, 0, 0, 0, &ignore, | 25641 | = face_at_string_position (w, object, pos, 0, 0, 0, &ignore, |
| 24697 | glyph->face_id, 1); | 25642 | glyph->face_id, 1); |
| 24698 | show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | 25643 | show_mouse_face (hlinfo, DRAW_MOUSE_FACE); |
| 24699 | cursor = No_Cursor; | 25644 | cursor = No_Cursor; |
| 24700 | } | 25645 | } |
| 24701 | else | 25646 | else |
| @@ -24729,17 +25674,33 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24729 | { | 25674 | { |
| 24730 | Lisp_Object before, after; | 25675 | Lisp_Object before, after; |
| 24731 | Lisp_Object before_string, after_string; | 25676 | Lisp_Object before_string, after_string; |
| 25677 | /* To correctly find the limits of mouse highlight | ||
| 25678 | in a bidi-reordered buffer, we must not use the | ||
| 25679 | optimization of limiting the search in | ||
| 25680 | previous-single-property-change and | ||
| 25681 | next-single-property-change, because | ||
| 25682 | rows_from_pos_range needs the real start and end | ||
| 25683 | positions to DTRT in this case. That's because | ||
| 25684 | the first row visible in a window does not | ||
| 25685 | necessarily display the character whose position | ||
| 25686 | is the smallest. */ | ||
| 25687 | Lisp_Object lim1 = | ||
| 25688 | NILP (XBUFFER (buffer)->bidi_display_reordering) | ||
| 25689 | ? Fmarker_position (w->start) | ||
| 25690 | : Qnil; | ||
| 25691 | Lisp_Object lim2 = | ||
| 25692 | NILP (XBUFFER (buffer)->bidi_display_reordering) | ||
| 25693 | ? make_number (BUF_Z (XBUFFER (buffer)) | ||
| 25694 | - XFASTINT (w->window_end_pos)) | ||
| 25695 | : Qnil; | ||
| 24732 | 25696 | ||
| 24733 | if (NILP (overlay)) | 25697 | if (NILP (overlay)) |
| 24734 | { | 25698 | { |
| 24735 | /* Handle the text property case. */ | 25699 | /* Handle the text property case. */ |
| 24736 | before = Fprevious_single_property_change | 25700 | before = Fprevious_single_property_change |
| 24737 | (make_number (pos + 1), Qmouse_face, buffer, | 25701 | (make_number (pos + 1), Qmouse_face, buffer, lim1); |
| 24738 | Fmarker_position (w->start)); | ||
| 24739 | after = Fnext_single_property_change | 25702 | after = Fnext_single_property_change |
| 24740 | (make_number (pos), Qmouse_face, buffer, | 25703 | (make_number (pos), Qmouse_face, buffer, lim2); |
| 24741 | make_number (BUF_Z (XBUFFER (buffer)) | ||
| 24742 | - XFASTINT (w->window_end_pos))); | ||
| 24743 | before_string = after_string = Qnil; | 25704 | before_string = after_string = Qnil; |
| 24744 | } | 25705 | } |
| 24745 | else | 25706 | else |
| @@ -24754,7 +25715,7 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24754 | if (!STRINGP (after_string)) after_string = Qnil; | 25715 | if (!STRINGP (after_string)) after_string = Qnil; |
| 24755 | } | 25716 | } |
| 24756 | 25717 | ||
| 24757 | mouse_face_from_buffer_pos (window, dpyinfo, pos, | 25718 | mouse_face_from_buffer_pos (window, hlinfo, pos, |
| 24758 | XFASTINT (before), | 25719 | XFASTINT (before), |
| 24759 | XFASTINT (after), | 25720 | XFASTINT (after), |
| 24760 | before_string, after_string, | 25721 | before_string, after_string, |
| @@ -24833,8 +25794,9 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24833 | } | 25794 | } |
| 24834 | } | 25795 | } |
| 24835 | 25796 | ||
| 25797 | #ifdef HAVE_WINDOW_SYSTEM | ||
| 24836 | /* Look for a `pointer' property. */ | 25798 | /* Look for a `pointer' property. */ |
| 24837 | if (NILP (pointer)) | 25799 | if (FRAME_WINDOW_P (f) && NILP (pointer)) |
| 24838 | { | 25800 | { |
| 24839 | /* Check overlays first. */ | 25801 | /* Check overlays first. */ |
| 24840 | for (i = noverlays - 1; i >= 0 && NILP (pointer); --i) | 25802 | for (i = noverlays - 1; i >= 0 && NILP (pointer); --i) |
| @@ -24873,6 +25835,7 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24873 | Qpointer, object); | 25835 | Qpointer, object); |
| 24874 | } | 25836 | } |
| 24875 | } | 25837 | } |
| 25838 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 24876 | 25839 | ||
| 24877 | BEGV = obegv; | 25840 | BEGV = obegv; |
| 24878 | ZV = ozv; | 25841 | ZV = ozv; |
| @@ -24881,7 +25844,14 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24881 | 25844 | ||
| 24882 | set_cursor: | 25845 | set_cursor: |
| 24883 | 25846 | ||
| 24884 | define_frame_cursor1 (f, cursor, pointer); | 25847 | #ifdef HAVE_WINDOW_SYSTEM |
| 25848 | if (FRAME_WINDOW_P (f)) | ||
| 25849 | define_frame_cursor1 (f, cursor, pointer); | ||
| 25850 | #else | ||
| 25851 | /* This is here to prevent a compiler error, about "label at end of | ||
| 25852 | compound statement". */ | ||
| 25853 | return; | ||
| 25854 | #endif | ||
| 24885 | } | 25855 | } |
| 24886 | 25856 | ||
| 24887 | 25857 | ||
| @@ -24893,13 +25863,13 @@ note_mouse_highlight (struct frame *f, int x, int y) | |||
| 24893 | void | 25863 | void |
| 24894 | x_clear_window_mouse_face (struct window *w) | 25864 | x_clear_window_mouse_face (struct window *w) |
| 24895 | { | 25865 | { |
| 24896 | Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame)); | 25866 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); |
| 24897 | Lisp_Object window; | 25867 | Lisp_Object window; |
| 24898 | 25868 | ||
| 24899 | BLOCK_INPUT; | 25869 | BLOCK_INPUT; |
| 24900 | XSETWINDOW (window, w); | 25870 | XSETWINDOW (window, w); |
| 24901 | if (EQ (window, dpyinfo->mouse_face_window)) | 25871 | if (EQ (window, hlinfo->mouse_face_window)) |
| 24902 | clear_mouse_face (dpyinfo); | 25872 | clear_mouse_face (hlinfo); |
| 24903 | UNBLOCK_INPUT; | 25873 | UNBLOCK_INPUT; |
| 24904 | } | 25874 | } |
| 24905 | 25875 | ||
| @@ -24912,20 +25882,18 @@ void | |||
| 24912 | cancel_mouse_face (struct frame *f) | 25882 | cancel_mouse_face (struct frame *f) |
| 24913 | { | 25883 | { |
| 24914 | Lisp_Object window; | 25884 | Lisp_Object window; |
| 24915 | Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | 25885 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); |
| 24916 | 25886 | ||
| 24917 | window = dpyinfo->mouse_face_window; | 25887 | window = hlinfo->mouse_face_window; |
| 24918 | if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f) | 25888 | if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f) |
| 24919 | { | 25889 | { |
| 24920 | dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; | 25890 | hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; |
| 24921 | dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; | 25891 | hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; |
| 24922 | dpyinfo->mouse_face_window = Qnil; | 25892 | hlinfo->mouse_face_window = Qnil; |
| 24923 | } | 25893 | } |
| 24924 | } | 25894 | } |
| 24925 | 25895 | ||
| 24926 | 25896 | ||
| 24927 | #endif /* HAVE_WINDOW_SYSTEM */ | ||
| 24928 | |||
| 24929 | 25897 | ||
| 24930 | /*********************************************************************** | 25898 | /*********************************************************************** |
| 24931 | Exposure Events | 25899 | Exposure Events |
| @@ -25382,12 +26350,12 @@ expose_frame (struct frame *f, int x, int y, int w, int h) | |||
| 25382 | focus-follows-mouse with delayed raise. --jason 2001-10-12 */ | 26350 | focus-follows-mouse with delayed raise. --jason 2001-10-12 */ |
| 25383 | if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f)) | 26351 | if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f)) |
| 25384 | { | 26352 | { |
| 25385 | Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | 26353 | Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); |
| 25386 | if (f == dpyinfo->mouse_face_mouse_frame) | 26354 | if (f == hlinfo->mouse_face_mouse_frame) |
| 25387 | { | 26355 | { |
| 25388 | int x = dpyinfo->mouse_face_mouse_x; | 26356 | int x = hlinfo->mouse_face_mouse_x; |
| 25389 | int y = dpyinfo->mouse_face_mouse_y; | 26357 | int y = hlinfo->mouse_face_mouse_y; |
| 25390 | clear_mouse_face (dpyinfo); | 26358 | clear_mouse_face (hlinfo); |
| 25391 | note_mouse_highlight (f, x, y); | 26359 | note_mouse_highlight (f, x, y); |
| 25392 | } | 26360 | } |
| 25393 | } | 26361 | } |
| @@ -25974,7 +26942,9 @@ the frame's other specifications determine how to blink the cursor off. */); | |||
| 25974 | Vblink_cursor_alist = Qnil; | 26942 | Vblink_cursor_alist = Qnil; |
| 25975 | 26943 | ||
| 25976 | DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p, | 26944 | DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p, |
| 25977 | doc: /* *Non-nil means scroll the display automatically to make point visible. */); | 26945 | doc: /* Allow or disallow automatic horizontal scrolling of windows. |
| 26946 | If non-nil, windows are automatically scrolled horizontally to make | ||
| 26947 | point visible. */); | ||
| 25978 | automatic_hscrolling_p = 1; | 26948 | automatic_hscrolling_p = 1; |
| 25979 | Qauto_hscroll_mode = intern_c_string ("auto-hscroll-mode"); | 26949 | Qauto_hscroll_mode = intern_c_string ("auto-hscroll-mode"); |
| 25980 | staticpro (&Qauto_hscroll_mode); | 26950 | staticpro (&Qauto_hscroll_mode); |
| @@ -26089,16 +27059,46 @@ baseline. The default value is 1. */); | |||
| 26089 | underline_minimum_offset = 1; | 27059 | underline_minimum_offset = 1; |
| 26090 | 27060 | ||
| 26091 | DEFVAR_BOOL ("display-hourglass", &display_hourglass_p, | 27061 | DEFVAR_BOOL ("display-hourglass", &display_hourglass_p, |
| 26092 | doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */); | 27062 | doc: /* Non-nil means show an hourglass pointer, when Emacs is busy. |
| 27063 | This feature only works when on a window system that can change | ||
| 27064 | cursor shapes. */); | ||
| 26093 | display_hourglass_p = 1; | 27065 | display_hourglass_p = 1; |
| 26094 | 27066 | ||
| 26095 | DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay, | 27067 | DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay, |
| 26096 | doc: /* *Seconds to wait before displaying an hourglass pointer. | 27068 | doc: /* *Seconds to wait before displaying an hourglass pointer when Emacs is busy. */); |
| 26097 | Value must be an integer or float. */); | ||
| 26098 | Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY); | 27069 | Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY); |
| 26099 | 27070 | ||
| 26100 | hourglass_atimer = NULL; | 27071 | hourglass_atimer = NULL; |
| 26101 | hourglass_shown_p = 0; | 27072 | hourglass_shown_p = 0; |
| 27073 | |||
| 27074 | DEFSYM (Qglyphless_char, "glyphless-char"); | ||
| 27075 | DEFSYM (Qhex_code, "hex-code"); | ||
| 27076 | DEFSYM (Qempty_box, "empty-box"); | ||
| 27077 | DEFSYM (Qthin_space, "thin-space"); | ||
| 27078 | DEFSYM (Qzero_width, "zero-width"); | ||
| 27079 | |||
| 27080 | DEFSYM (Qglyphless_char_display, "glyphless-char-display"); | ||
| 27081 | /* Intern this now in case it isn't already done. | ||
| 27082 | Setting this variable twice is harmless. | ||
| 27083 | But don't staticpro it here--that is done in alloc.c. */ | ||
| 27084 | Qchar_table_extra_slots = intern_c_string ("char-table-extra-slots"); | ||
| 27085 | Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_number (1)); | ||
| 27086 | |||
| 27087 | DEFVAR_LISP ("glyphless-char-display", &Vglyphless_char_display, | ||
| 27088 | doc: /* Char-table to control displaying of glyphless characters. | ||
| 27089 | Each element, if non-nil, is an ASCII acronym string (displayed in a box) | ||
| 27090 | or one of these symbols: | ||
| 27091 | hex-code: display the hexadecimal code of a character in a box | ||
| 27092 | empty-box: display as an empty box | ||
| 27093 | thin-space: display as 1-pixel width space | ||
| 27094 | zero-width: don't display | ||
| 27095 | |||
| 27096 | It has one extra slot to control the display of a character for which | ||
| 27097 | no font is found. The value of the slot is `hex-code' or `empty-box'. | ||
| 27098 | The default is `empty-box'. */); | ||
| 27099 | Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil); | ||
| 27100 | Fset_char_table_extra_slot (Vglyphless_char_display, make_number (0), | ||
| 27101 | Qempty_box); | ||
| 26102 | } | 27102 | } |
| 26103 | 27103 | ||
| 26104 | 27104 | ||
| @@ -26216,5 +27216,3 @@ cancel_hourglass (void) | |||
| 26216 | } | 27216 | } |
| 26217 | #endif /* ! WINDOWSNT */ | 27217 | #endif /* ! WINDOWSNT */ |
| 26218 | 27218 | ||
| 26219 | /* arch-tag: eacc864d-bb6a-4b74-894a-1a4399a1358b | ||
| 26220 | (do not change this comment) */ | ||