Mercurial > emacs
comparison src/xterm.c @ 50237:160bd7db88a1
* xterm.c: Remove consolidated defines and code.
(BETWEEN): Remove unused macro.
(x_draw_vertical_window_border, x_shift_glyphs_for_insert)
(x_define_frame_cursor, x_clear_frame_area)
(x_draw_window_cursor): New X-specific functions for RIF.
(x_redisplay_interface): Add new members.
author | Kim F. Storm <storm@cua.dk> |
---|---|
date | Fri, 21 Mar 2003 13:52:48 +0000 |
parents | 297925dd73b1 |
children | 3fb54e5a7201 |
comparison
equal
deleted
inserted
replaced
50236:156baddab173 | 50237:160bd7db88a1 |
---|---|
156 #endif | 156 #endif |
157 #endif | 157 #endif |
158 | 158 |
159 #define abs(x) ((x) < 0 ? -(x) : (x)) | 159 #define abs(x) ((x) < 0 ? -(x) : (x)) |
160 | 160 |
161 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER)) | |
162 | |
163 | 161 |
164 | 162 |
165 extern Lisp_Object Qhelp_echo; | |
166 | |
167 /* Non-nil means Emacs uses toolkit scroll bars. */ | 163 /* Non-nil means Emacs uses toolkit scroll bars. */ |
168 | 164 |
169 Lisp_Object Vx_toolkit_scroll_bars; | 165 Lisp_Object Vx_toolkit_scroll_bars; |
170 | |
171 /* If a string, XTread_socket generates an event to display that string. | |
172 (The display is done in read_char.) */ | |
173 | |
174 static Lisp_Object help_echo; | |
175 static Lisp_Object help_echo_window; | |
176 static Lisp_Object help_echo_object; | |
177 static int help_echo_pos; | |
178 | |
179 /* Temporary variable for XTread_socket. */ | |
180 | |
181 static Lisp_Object previous_help_echo; | |
182 | 166 |
183 /* Non-zero means that a HELP_EVENT has been generated since Emacs | 167 /* Non-zero means that a HELP_EVENT has been generated since Emacs |
184 start. */ | 168 start. */ |
185 | 169 |
186 static int any_help_event_p; | 170 static int any_help_event_p; |
187 | 171 |
188 /* Non-zero means autoselect window with the mouse cursor. */ | |
189 | |
190 int mouse_autoselect_window; | |
191 | |
192 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */ | 172 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */ |
193 static Lisp_Object last_window; | 173 static Lisp_Object last_window; |
194 | |
195 /* Non-zero means draw block and hollow cursor as wide as the glyph | |
196 under it. For example, if a block cursor is over a tab, it will be | |
197 drawn as wide as that tab on the display. */ | |
198 | |
199 int x_stretch_cursor_p; | |
200 | 174 |
201 /* Non-zero means make use of UNDERLINE_POSITION font properties. */ | 175 /* Non-zero means make use of UNDERLINE_POSITION font properties. */ |
202 | 176 |
203 int x_use_underline_position_properties; | 177 int x_use_underline_position_properties; |
204 | 178 |
228 #ifdef USE_X_TOOLKIT | 202 #ifdef USE_X_TOOLKIT |
229 /* The application context for Xt use. */ | 203 /* The application context for Xt use. */ |
230 XtAppContext Xt_app_con; | 204 XtAppContext Xt_app_con; |
231 static String Xt_default_resources[] = {0}; | 205 static String Xt_default_resources[] = {0}; |
232 #endif /* USE_X_TOOLKIT */ | 206 #endif /* USE_X_TOOLKIT */ |
233 | |
234 /* Nominal cursor position -- where to draw output. | |
235 HPOS and VPOS are window relative glyph matrix coordinates. | |
236 X and Y are window relative pixel coordinates. */ | |
237 | |
238 struct cursor_pos output_cursor; | |
239 | 207 |
240 /* Non-zero means user is interacting with a toolkit scroll bar. */ | 208 /* Non-zero means user is interacting with a toolkit scroll bar. */ |
241 | 209 |
242 static int toolkit_scroll_bar_interaction; | 210 static int toolkit_scroll_bar_interaction; |
243 | 211 |
261 tracking is on, and I suspect only negligibly worse when tracking | 229 tracking is on, and I suspect only negligibly worse when tracking |
262 is off. */ | 230 is off. */ |
263 | 231 |
264 /* Where the mouse was last time we reported a mouse event. */ | 232 /* Where the mouse was last time we reported a mouse event. */ |
265 | 233 |
266 FRAME_PTR last_mouse_frame; | |
267 static XRectangle last_mouse_glyph; | 234 static XRectangle last_mouse_glyph; |
268 static Lisp_Object last_mouse_press_frame; | 235 static Lisp_Object last_mouse_press_frame; |
269 | 236 |
270 /* The scroll bar in which the last X motion event occurred. | 237 /* The scroll bar in which the last X motion event occurred. |
271 | 238 |
331 | 298 |
332 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *)); | 299 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *)); |
333 extern Lisp_Object x_icon_type P_ ((struct frame *)); | 300 extern Lisp_Object x_icon_type P_ ((struct frame *)); |
334 | 301 |
335 | 302 |
336 static int cursor_in_mouse_face_p P_ ((struct window *)); | |
337 static int clear_mouse_face P_ ((struct x_display_info *)); | |
338 static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *)); | 303 static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *)); |
339 static void x_set_window_size_1 P_ ((struct frame *, int, int, int)); | 304 static void x_set_window_size_1 P_ ((struct frame *, int, int, int)); |
340 static const XColor *x_color_cells P_ ((Display *, int *)); | 305 static const XColor *x_color_cells P_ ((Display *, int *)); |
341 static void x_update_window_end P_ ((struct window *, int, int)); | 306 static void x_update_window_end P_ ((struct window *, int, int)); |
342 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *)); | |
343 void x_delete_display P_ ((struct x_display_info *)); | 307 void x_delete_display P_ ((struct x_display_info *)); |
344 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *, | 308 static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *, |
345 unsigned)); | 309 unsigned)); |
346 static int fast_find_position P_ ((struct window *, int, int *, int *, | |
347 int *, int *, Lisp_Object)); | |
348 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object, | |
349 int *, int *, int *, int *, int)); | |
350 static void set_output_cursor P_ ((struct cursor_pos *)); | |
351 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int, | |
352 int *, int *, int *, int)); | |
353 static void note_mode_line_or_margin_highlight P_ ((struct window *, int, | |
354 int, int)); | |
355 static void note_mouse_highlight P_ ((struct frame *, int, int)); | |
356 static void note_tool_bar_highlight P_ ((struct frame *f, int, int)); | |
357 static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *)); | |
358 static void show_mouse_face P_ ((struct x_display_info *, | |
359 enum draw_glyphs_face)); | |
360 static int x_io_error_quitter P_ ((Display *)); | 310 static int x_io_error_quitter P_ ((Display *)); |
361 int x_catch_errors P_ ((Display *)); | 311 int x_catch_errors P_ ((Display *)); |
362 void x_uncatch_errors P_ ((Display *, int)); | 312 void x_uncatch_errors P_ ((Display *, int)); |
363 void x_lower_frame P_ ((struct frame *)); | 313 void x_lower_frame P_ ((struct frame *)); |
364 void x_scroll_bar_clear P_ ((struct frame *)); | 314 void x_scroll_bar_clear P_ ((struct frame *)); |
369 void x_wm_set_window_state P_ ((struct frame *, int)); | 319 void x_wm_set_window_state P_ ((struct frame *, int)); |
370 void x_wm_set_icon_pixmap P_ ((struct frame *, int)); | 320 void x_wm_set_icon_pixmap P_ ((struct frame *, int)); |
371 void x_initialize P_ ((void)); | 321 void x_initialize P_ ((void)); |
372 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *)); | 322 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *)); |
373 static int x_compute_min_glyph_bounds P_ ((struct frame *)); | 323 static int x_compute_min_glyph_bounds P_ ((struct frame *)); |
374 static void x_draw_phys_cursor_glyph P_ ((struct window *, | |
375 struct glyph_row *, | |
376 enum draw_glyphs_face)); | |
377 static void x_update_end P_ ((struct frame *)); | 324 static void x_update_end P_ ((struct frame *)); |
378 static void XTframe_up_to_date P_ ((struct frame *)); | 325 static void XTframe_up_to_date P_ ((struct frame *)); |
379 static void XTset_terminal_modes P_ ((void)); | 326 static void XTset_terminal_modes P_ ((void)); |
380 static void XTreset_terminal_modes P_ ((void)); | 327 static void XTreset_terminal_modes P_ ((void)); |
381 static void XTcursor_to P_ ((int, int, int, int)); | |
382 static void x_write_glyphs P_ ((struct glyph *, int)); | |
383 static void x_clear_end_of_line P_ ((int)); | |
384 static void x_clear_frame P_ ((void)); | 328 static void x_clear_frame P_ ((void)); |
385 static void x_clear_cursor P_ ((struct window *)); | |
386 static void frame_highlight P_ ((struct frame *)); | 329 static void frame_highlight P_ ((struct frame *)); |
387 static void frame_unhighlight P_ ((struct frame *)); | 330 static void frame_unhighlight P_ ((struct frame *)); |
388 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *)); | 331 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *)); |
389 static int x_focus_changed P_ ((int, | 332 static int x_focus_changed P_ ((int, |
390 int, | 333 int, |
399 static void XTframe_rehighlight P_ ((struct frame *)); | 342 static void XTframe_rehighlight P_ ((struct frame *)); |
400 static void x_frame_rehighlight P_ ((struct x_display_info *)); | 343 static void x_frame_rehighlight P_ ((struct x_display_info *)); |
401 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *)); | 344 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *)); |
402 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int, | 345 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int, |
403 enum text_cursor_kinds)); | 346 enum text_cursor_kinds)); |
404 static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *, | |
405 XRectangle *)); | |
406 static void expose_frame P_ ((struct frame *, int, int, int, int)); | |
407 static int expose_window_tree P_ ((struct window *, XRectangle *)); | |
408 static void expose_overlaps P_ ((struct window *, struct glyph_row *, | |
409 struct glyph_row *)); | |
410 static int expose_window P_ ((struct window *, XRectangle *)); | |
411 static void expose_area P_ ((struct window *, struct glyph_row *, | |
412 XRectangle *, enum glyph_row_area)); | |
413 static int expose_line P_ ((struct window *, struct glyph_row *, | |
414 XRectangle *)); | |
415 static void x_update_cursor_in_window_tree P_ ((struct window *, int)); | |
416 static void x_update_window_cursor P_ ((struct window *, int)); | |
417 static void x_erase_phys_cursor P_ ((struct window *)); | |
418 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int)); | |
419 | 347 |
420 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, | 348 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, |
421 GC, int)); | 349 GC, int)); |
422 static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *)); | |
423 static void x_flush P_ ((struct frame *f)); | 350 static void x_flush P_ ((struct frame *f)); |
424 static void x_update_begin P_ ((struct frame *)); | 351 static void x_update_begin P_ ((struct frame *)); |
425 static void x_update_window_begin P_ ((struct window *)); | 352 static void x_update_window_begin P_ ((struct window *)); |
426 static void x_draw_vertical_border P_ ((struct window *)); | |
427 static void x_after_update_window_line P_ ((struct glyph_row *)); | 353 static void x_after_update_window_line P_ ((struct glyph_row *)); |
428 static INLINE void take_vertical_position_into_account P_ ((struct it *)); | 354 static INLINE void take_vertical_position_into_account P_ ((struct it *)); |
429 static struct scroll_bar *x_window_to_scroll_bar P_ ((Window)); | 355 static struct scroll_bar *x_window_to_scroll_bar P_ ((Window)); |
430 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *, | 356 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *, |
431 enum scroll_bar_part *, | 357 enum scroll_bar_part *, |
594 | 520 |
595 UNBLOCK_INPUT; | 521 UNBLOCK_INPUT; |
596 } | 522 } |
597 | 523 |
598 | 524 |
599 /* Draw a vertical window border to the right of window W if W doesn't | 525 /* Draw a vertical window border from (x,y0) to (x,y1) */ |
600 have vertical scroll bars. */ | |
601 | 526 |
602 static void | 527 static void |
603 x_draw_vertical_border (w) | 528 x_draw_vertical_window_border (w, x, y0, y1) |
604 struct window *w; | 529 struct window *w; |
530 int x, y0, y1; | |
605 { | 531 { |
606 struct frame *f = XFRAME (WINDOW_FRAME (w)); | 532 struct frame *f = XFRAME (WINDOW_FRAME (w)); |
607 | 533 |
608 /* Redraw borders between horizontally adjacent windows. Don't | 534 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), |
609 do it for frames with vertical scroll bars because either the | 535 f->output_data.x->normal_gc, x, y0, x, y1); |
610 right scroll bar of a window, or the left scroll bar of its | 536 } |
611 neighbor will suffice as a border. */ | |
612 if (!WINDOW_RIGHTMOST_P (w) | |
613 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)) | |
614 { | |
615 int x0, x1, y0, y1; | |
616 | |
617 window_box_edges (w, -1, &x0, &y0, &x1, &y1); | |
618 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f); | |
619 y1 -= 1; | |
620 | |
621 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
622 f->output_data.x->normal_gc, x1, y0, x1, y1); | |
623 } | |
624 } | |
625 | |
626 | 537 |
627 /* End update of window W (which is equal to updated_window). | 538 /* End update of window W (which is equal to updated_window). |
628 | 539 |
629 Draw vertical borders between horizontally adjacent windows, and | 540 Draw vertical borders between horizontally adjacent windows, and |
630 display W's cursor if CURSOR_ON_P is non-zero. | 541 display W's cursor if CURSOR_ON_P is non-zero. |
647 if (!w->pseudo_window_p) | 558 if (!w->pseudo_window_p) |
648 { | 559 { |
649 BLOCK_INPUT; | 560 BLOCK_INPUT; |
650 | 561 |
651 if (cursor_on_p) | 562 if (cursor_on_p) |
652 x_display_and_set_cursor (w, 1, output_cursor.hpos, | 563 display_and_set_cursor (w, 1, output_cursor.hpos, |
653 output_cursor.vpos, | 564 output_cursor.vpos, |
654 output_cursor.x, output_cursor.y); | 565 output_cursor.x, output_cursor.y); |
655 | 566 |
656 x_draw_vertical_border (w); | 567 x_draw_vertical_border (w); |
657 UNBLOCK_INPUT; | 568 UNBLOCK_INPUT; |
658 } | 569 } |
659 | 570 |
678 struct frame *f; | 589 struct frame *f; |
679 { | 590 { |
680 /* Mouse highlight may be displayed again. */ | 591 /* Mouse highlight may be displayed again. */ |
681 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0; | 592 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0; |
682 | 593 |
594 #ifndef XFlush | |
683 BLOCK_INPUT; | 595 BLOCK_INPUT; |
684 XFlush (FRAME_X_DISPLAY (f)); | 596 XFlush (FRAME_X_DISPLAY (f)); |
685 UNBLOCK_INPUT; | 597 UNBLOCK_INPUT; |
598 #endif | |
686 } | 599 } |
687 | 600 |
688 | 601 |
689 /* This function is called from various places in xdisp.c whenever a | 602 /* This function is called from various places in xdisp.c whenever a |
690 complete update has been performed. The global variable | 603 complete update has been performed. The global variable |
836 the X-windows go away, and suspending requires no action. */ | 749 the X-windows go away, and suspending requires no action. */ |
837 | 750 |
838 static void | 751 static void |
839 XTreset_terminal_modes () | 752 XTreset_terminal_modes () |
840 { | 753 { |
841 } | |
842 | |
843 | |
844 | |
845 /*********************************************************************** | |
846 Output Cursor | |
847 ***********************************************************************/ | |
848 | |
849 /* Set the global variable output_cursor to CURSOR. All cursor | |
850 positions are relative to updated_window. */ | |
851 | |
852 static void | |
853 set_output_cursor (cursor) | |
854 struct cursor_pos *cursor; | |
855 { | |
856 output_cursor.hpos = cursor->hpos; | |
857 output_cursor.vpos = cursor->vpos; | |
858 output_cursor.x = cursor->x; | |
859 output_cursor.y = cursor->y; | |
860 } | |
861 | |
862 | |
863 /* Set a nominal cursor position. | |
864 | |
865 HPOS and VPOS are column/row positions in a window glyph matrix. X | |
866 and Y are window text area relative pixel positions. | |
867 | |
868 If this is done during an update, updated_window will contain the | |
869 window that is being updated and the position is the future output | |
870 cursor position for that window. If updated_window is null, use | |
871 selected_window and display the cursor at the given position. */ | |
872 | |
873 static void | |
874 XTcursor_to (vpos, hpos, y, x) | |
875 int vpos, hpos, y, x; | |
876 { | |
877 struct window *w; | |
878 | |
879 /* If updated_window is not set, work on selected_window. */ | |
880 if (updated_window) | |
881 w = updated_window; | |
882 else | |
883 w = XWINDOW (selected_window); | |
884 | |
885 /* Set the output cursor. */ | |
886 output_cursor.hpos = hpos; | |
887 output_cursor.vpos = vpos; | |
888 output_cursor.x = x; | |
889 output_cursor.y = y; | |
890 | |
891 /* If not called as part of an update, really display the cursor. | |
892 This will also set the cursor position of W. */ | |
893 if (updated_window == NULL) | |
894 { | |
895 BLOCK_INPUT; | |
896 x_display_cursor (w, 1, hpos, vpos, x, y); | |
897 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ())); | |
898 UNBLOCK_INPUT; | |
899 } | |
900 } | 754 } |
901 | 755 |
902 | 756 |
903 | 757 |
904 /*********************************************************************** | 758 /*********************************************************************** |
1043 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0; | 897 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0; |
1044 | 898 |
1045 return FONT_TYPE_UNKNOWN; | 899 return FONT_TYPE_UNKNOWN; |
1046 } | 900 } |
1047 | 901 |
1048 | |
1049 /* Estimate the pixel height of the mode or top line on frame F. | |
1050 FACE_ID specifies what line's height to estimate. */ | |
1051 | |
1052 int | |
1053 x_estimate_mode_line_height (f, face_id) | |
1054 struct frame *f; | |
1055 enum face_id face_id; | |
1056 { | |
1057 int height = FONT_HEIGHT (FRAME_FONT (f)); | |
1058 | |
1059 /* This function is called so early when Emacs starts that the face | |
1060 cache and mode line face are not yet initialized. */ | |
1061 if (FRAME_FACE_CACHE (f)) | |
1062 { | |
1063 struct face *face = FACE_FROM_ID (f, face_id); | |
1064 if (face) | |
1065 { | |
1066 if (face->font) | |
1067 height = FONT_HEIGHT (face->font); | |
1068 if (face->box_line_width > 0) | |
1069 height += 2 * face->box_line_width; | |
1070 } | |
1071 } | |
1072 | |
1073 return height; | |
1074 } | |
1075 | 902 |
1076 | 903 |
1077 /*********************************************************************** | 904 /*********************************************************************** |
1078 Glyph display | 905 Glyph display |
1079 ***********************************************************************/ | 906 ***********************************************************************/ |
1105 int, int, int)); | 932 int, int, int)); |
1106 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int, | 933 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int, |
1107 int, int, int, int, XRectangle *)); | 934 int, int, int, int, XRectangle *)); |
1108 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int, | 935 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int, |
1109 int, int, int, XRectangle *)); | 936 int, int, int, XRectangle *)); |
1110 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *, | |
1111 enum glyph_row_area)); | |
1112 | 937 |
1113 #if GLYPH_DEBUG | 938 #if GLYPH_DEBUG |
1114 static void x_check_font P_ ((struct frame *, XFontStruct *)); | 939 static void x_check_font P_ ((struct frame *, XFontStruct *)); |
1115 #endif | 940 #endif |
1116 | 941 |
1279 /* GC must have been set. */ | 1104 /* GC must have been set. */ |
1280 xassert (s->gc != 0); | 1105 xassert (s->gc != 0); |
1281 } | 1106 } |
1282 | 1107 |
1283 | 1108 |
1284 /* Return in *R the clipping rectangle for glyph string S. */ | |
1285 | |
1286 static void | |
1287 x_get_glyph_string_clip_rect (s, r) | |
1288 struct glyph_string *s; | |
1289 XRectangle *r; | |
1290 { | |
1291 if (s->row->full_width_p) | |
1292 { | |
1293 /* Draw full-width. X coordinates are relative to S->w->left. */ | |
1294 int canon_x = CANON_X_UNIT (s->f); | |
1295 | |
1296 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x; | |
1297 r->width = XFASTINT (s->w->width) * canon_x; | |
1298 | |
1299 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f)) | |
1300 { | |
1301 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x; | |
1302 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f)) | |
1303 r->x -= width; | |
1304 } | |
1305 | |
1306 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f); | |
1307 | |
1308 /* Unless displaying a mode or menu bar line, which are always | |
1309 fully visible, clip to the visible part of the row. */ | |
1310 if (s->w->pseudo_window_p) | |
1311 r->height = s->row->visible_height; | |
1312 else | |
1313 r->height = s->height; | |
1314 } | |
1315 else | |
1316 { | |
1317 /* This is a text line that may be partially visible. */ | |
1318 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0); | |
1319 r->width = window_box_width (s->w, s->area); | |
1320 r->height = s->row->visible_height; | |
1321 } | |
1322 | |
1323 /* If S draws overlapping rows, it's sufficient to use the top and | |
1324 bottom of the window for clipping because this glyph string | |
1325 intentionally draws over other lines. */ | |
1326 if (s->for_overlaps_p) | |
1327 { | |
1328 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w); | |
1329 r->height = window_text_bottom_y (s->w) - r->y; | |
1330 } | |
1331 else | |
1332 { | |
1333 /* Don't use S->y for clipping because it doesn't take partially | |
1334 visible lines into account. For example, it can be negative for | |
1335 partially visible lines at the top of a window. */ | |
1336 if (!s->row->full_width_p | |
1337 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row)) | |
1338 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w); | |
1339 else | |
1340 r->y = max (0, s->row->y); | |
1341 | |
1342 /* If drawing a tool-bar window, draw it over the internal border | |
1343 at the top of the window. */ | |
1344 if (s->w == XWINDOW (s->f->tool_bar_window)) | |
1345 r->y -= s->f->output_data.x->internal_border_width; | |
1346 } | |
1347 | |
1348 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y); | |
1349 } | |
1350 | |
1351 | |
1352 /* Set clipping for output of glyph string S. S may be part of a mode | 1109 /* Set clipping for output of glyph string S. S may be part of a mode |
1353 line or menu if we don't have X toolkit support. */ | 1110 line or menu if we don't have X toolkit support. */ |
1354 | 1111 |
1355 static INLINE void | 1112 static INLINE void |
1356 x_set_glyph_string_clipping (s) | 1113 x_set_glyph_string_clipping (s) |
1357 struct glyph_string *s; | 1114 struct glyph_string *s; |
1358 { | 1115 { |
1359 XRectangle r; | 1116 XRectangle r; |
1360 x_get_glyph_string_clip_rect (s, &r); | 1117 get_glyph_string_clip_rect (s, &r); |
1361 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted); | 1118 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted); |
1362 } | 1119 } |
1363 | 1120 |
1364 | 1121 |
1365 /* RIF: | 1122 /* RIF: |
2347 right_p = (last_glyph->right_box_line_p | 2104 right_p = (last_glyph->right_box_line_p |
2348 || (s->hl == DRAW_MOUSE_FACE | 2105 || (s->hl == DRAW_MOUSE_FACE |
2349 && (s->next == NULL | 2106 && (s->next == NULL |
2350 || s->next->hl != s->hl))); | 2107 || s->next->hl != s->hl))); |
2351 | 2108 |
2352 x_get_glyph_string_clip_rect (s, &clip_rect); | 2109 get_glyph_string_clip_rect (s, &clip_rect); |
2353 | 2110 |
2354 if (s->face->box == FACE_SIMPLE_BOX) | 2111 if (s->face->box == FACE_SIMPLE_BOX) |
2355 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width, | 2112 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width, |
2356 left_p, right_p, &clip_rect); | 2113 left_p, right_p, &clip_rect); |
2357 else | 2114 else |
2403 xgcv.clip_x_origin = x; | 2160 xgcv.clip_x_origin = x; |
2404 xgcv.clip_y_origin = y; | 2161 xgcv.clip_y_origin = y; |
2405 xgcv.function = GXcopy; | 2162 xgcv.function = GXcopy; |
2406 XChangeGC (s->display, s->gc, mask, &xgcv); | 2163 XChangeGC (s->display, s->gc, mask, &xgcv); |
2407 | 2164 |
2408 x_get_glyph_string_clip_rect (s, &clip_rect); | 2165 get_glyph_string_clip_rect (s, &clip_rect); |
2409 image_rect.x = x; | 2166 image_rect.x = x; |
2410 image_rect.y = y; | 2167 image_rect.y = y; |
2411 image_rect.width = s->img->width; | 2168 image_rect.width = s->img->width; |
2412 image_rect.height = s->img->height; | 2169 image_rect.height = s->img->height; |
2413 if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) | 2170 if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) |
2416 } | 2173 } |
2417 else | 2174 else |
2418 { | 2175 { |
2419 XRectangle clip_rect, image_rect, r; | 2176 XRectangle clip_rect, image_rect, r; |
2420 | 2177 |
2421 x_get_glyph_string_clip_rect (s, &clip_rect); | 2178 get_glyph_string_clip_rect (s, &clip_rect); |
2422 image_rect.x = x; | 2179 image_rect.x = x; |
2423 image_rect.y = y; | 2180 image_rect.y = y; |
2424 image_rect.width = s->img->width; | 2181 image_rect.width = s->img->width; |
2425 image_rect.height = s->img->height; | 2182 image_rect.height = s->img->height; |
2426 if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) | 2183 if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) |
2489 y0 = y - thick; | 2246 y0 = y - thick; |
2490 x1 = x + s->img->width + thick - 1; | 2247 x1 = x + s->img->width + thick - 1; |
2491 y1 = y + s->img->height + thick - 1; | 2248 y1 = y + s->img->height + thick - 1; |
2492 | 2249 |
2493 x_setup_relief_colors (s); | 2250 x_setup_relief_colors (s); |
2494 x_get_glyph_string_clip_rect (s, &r); | 2251 get_glyph_string_clip_rect (s, &r); |
2495 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r); | 2252 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r); |
2496 } | 2253 } |
2497 | 2254 |
2498 | 2255 |
2499 /* Draw the foreground of image glyph string S to PIXMAP. */ | 2256 /* Draw the foreground of image glyph string S to PIXMAP. */ |
2731 gc = s->gc; | 2488 gc = s->gc; |
2732 } | 2489 } |
2733 else | 2490 else |
2734 gc = s->face->gc; | 2491 gc = s->face->gc; |
2735 | 2492 |
2736 x_get_glyph_string_clip_rect (s, &r); | 2493 get_glyph_string_clip_rect (s, &r); |
2737 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted); | 2494 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted); |
2738 | 2495 |
2739 if (s->face->stipple) | 2496 if (s->face->stipple) |
2740 { | 2497 { |
2741 /* Fill background with a stipple pattern. */ | 2498 /* Fill background with a stipple pattern. */ |
2918 | 2675 |
2919 /* Reset clipping. */ | 2676 /* Reset clipping. */ |
2920 XSetClipMask (s->display, s->gc, None); | 2677 XSetClipMask (s->display, s->gc, None); |
2921 } | 2678 } |
2922 | 2679 |
2923 | 2680 /* Shift display to make room for inserted glyphs. */ |
2924 /* Fix the display of area AREA of overlapping row ROW in window W. */ | 2681 |
2925 | 2682 void |
2926 static void | 2683 x_shift_glyphs_for_insert (f, x, y, width, height, shift_by) |
2927 x_fix_overlapping_area (w, row, area) | 2684 struct frame *f; |
2928 struct window *w; | 2685 int x, y, width, height, shift_by; |
2929 struct glyph_row *row; | 2686 { |
2930 enum glyph_row_area area; | |
2931 { | |
2932 int i, x; | |
2933 | |
2934 BLOCK_INPUT; | |
2935 | |
2936 if (area == LEFT_MARGIN_AREA) | |
2937 x = 0; | |
2938 else if (area == TEXT_AREA) | |
2939 x = row->x + window_box_width (w, LEFT_MARGIN_AREA); | |
2940 else | |
2941 x = (window_box_width (w, LEFT_MARGIN_AREA) | |
2942 + window_box_width (w, TEXT_AREA)); | |
2943 | |
2944 for (i = 0; i < row->used[area];) | |
2945 { | |
2946 if (row->glyphs[area][i].overlaps_vertically_p) | |
2947 { | |
2948 int start = i, start_x = x; | |
2949 | |
2950 do | |
2951 { | |
2952 x += row->glyphs[area][i].pixel_width; | |
2953 ++i; | |
2954 } | |
2955 while (i < row->used[area] | |
2956 && row->glyphs[area][i].overlaps_vertically_p); | |
2957 | |
2958 x_draw_glyphs (w, start_x, row, area, start, i, | |
2959 DRAW_NORMAL_TEXT, 1); | |
2960 } | |
2961 else | |
2962 { | |
2963 x += row->glyphs[area][i].pixel_width; | |
2964 ++i; | |
2965 } | |
2966 } | |
2967 | |
2968 UNBLOCK_INPUT; | |
2969 } | |
2970 | |
2971 | |
2972 /* Output LEN glyphs starting at START at the nominal cursor position. | |
2973 Advance the nominal cursor over the text. The global variable | |
2974 updated_window contains the window being updated, updated_row is | |
2975 the glyph row being updated, and updated_area is the area of that | |
2976 row being updated. */ | |
2977 | |
2978 static void | |
2979 x_write_glyphs (start, len) | |
2980 struct glyph *start; | |
2981 int len; | |
2982 { | |
2983 int x, hpos; | |
2984 | |
2985 xassert (updated_window && updated_row); | |
2986 BLOCK_INPUT; | |
2987 | |
2988 /* Write glyphs. */ | |
2989 | |
2990 hpos = start - updated_row->glyphs[updated_area]; | |
2991 x = x_draw_glyphs (updated_window, output_cursor.x, | |
2992 updated_row, updated_area, | |
2993 hpos, hpos + len, | |
2994 DRAW_NORMAL_TEXT, 0); | |
2995 | |
2996 /* Invalidate old phys cursor if the glyph at its hpos is redrawn. */ | |
2997 if (updated_area == TEXT_AREA | |
2998 && updated_window->phys_cursor_on_p | |
2999 && updated_window->phys_cursor.vpos == output_cursor.vpos | |
3000 && updated_window->phys_cursor.hpos >= hpos | |
3001 && updated_window->phys_cursor.hpos < hpos + len) | |
3002 updated_window->phys_cursor_on_p = 0; | |
3003 | |
3004 UNBLOCK_INPUT; | |
3005 | |
3006 /* Advance the output cursor. */ | |
3007 output_cursor.hpos += len; | |
3008 output_cursor.x = x; | |
3009 } | |
3010 | |
3011 | |
3012 /* Insert LEN glyphs from START at the nominal cursor position. */ | |
3013 | |
3014 static void | |
3015 x_insert_glyphs (start, len) | |
3016 struct glyph *start; | |
3017 register int len; | |
3018 { | |
3019 struct frame *f; | |
3020 struct window *w; | |
3021 int line_height, shift_by_width, shifted_region_width; | |
3022 struct glyph_row *row; | |
3023 struct glyph *glyph; | |
3024 int frame_x, frame_y, hpos; | |
3025 | |
3026 xassert (updated_window && updated_row); | |
3027 BLOCK_INPUT; | |
3028 w = updated_window; | |
3029 f = XFRAME (WINDOW_FRAME (w)); | |
3030 | |
3031 /* Get the height of the line we are in. */ | |
3032 row = updated_row; | |
3033 line_height = row->height; | |
3034 | |
3035 /* Get the width of the glyphs to insert. */ | |
3036 shift_by_width = 0; | |
3037 for (glyph = start; glyph < start + len; ++glyph) | |
3038 shift_by_width += glyph->pixel_width; | |
3039 | |
3040 /* Get the width of the region to shift right. */ | |
3041 shifted_region_width = (window_box_width (w, updated_area) | |
3042 - output_cursor.x | |
3043 - shift_by_width); | |
3044 | |
3045 /* Shift right. */ | |
3046 frame_x = window_box_left (w, updated_area) + output_cursor.x; | |
3047 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y); | |
3048 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f), | 2687 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f), |
3049 f->output_data.x->normal_gc, | 2688 f->output_data.x->normal_gc, |
3050 frame_x, frame_y, | 2689 x, y, width, height, |
3051 shifted_region_width, line_height, | 2690 x + shift_by, y); |
3052 frame_x + shift_by_width, frame_y); | 2691 } |
3053 | |
3054 /* Write the glyphs. */ | |
3055 hpos = start - row->glyphs[updated_area]; | |
3056 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len, | |
3057 DRAW_NORMAL_TEXT, 0); | |
3058 | |
3059 /* Advance the output cursor. */ | |
3060 output_cursor.hpos += len; | |
3061 output_cursor.x += shift_by_width; | |
3062 UNBLOCK_INPUT; | |
3063 } | |
3064 | |
3065 | 2692 |
3066 /* Delete N glyphs at the nominal cursor position. Not implemented | 2693 /* Delete N glyphs at the nominal cursor position. Not implemented |
3067 for X frames. */ | 2694 for X frames. */ |
3068 | 2695 |
3069 static void | 2696 static void |
3085 int width, height; | 2712 int width, height; |
3086 int exposures; | 2713 int exposures; |
3087 { | 2714 { |
3088 xassert (width > 0 && height > 0); | 2715 xassert (width > 0 && height > 0); |
3089 XClearArea (dpy, window, x, y, width, height, exposures); | 2716 XClearArea (dpy, window, x, y, width, height, exposures); |
3090 } | |
3091 | |
3092 | |
3093 /* Erase the current text line from the nominal cursor position | |
3094 (inclusive) to pixel column TO_X (exclusive). The idea is that | |
3095 everything from TO_X onward is already erased. | |
3096 | |
3097 TO_X is a pixel position relative to updated_area of | |
3098 updated_window. TO_X == -1 means clear to the end of this area. */ | |
3099 | |
3100 static void | |
3101 x_clear_end_of_line (to_x) | |
3102 int to_x; | |
3103 { | |
3104 struct frame *f; | |
3105 struct window *w = updated_window; | |
3106 int max_x, min_y, max_y; | |
3107 int from_x, from_y, to_y; | |
3108 | |
3109 xassert (updated_window && updated_row); | |
3110 f = XFRAME (w->frame); | |
3111 | |
3112 if (updated_row->full_width_p) | |
3113 { | |
3114 max_x = XFASTINT (w->width) * CANON_X_UNIT (f); | |
3115 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) | |
3116 && !w->pseudo_window_p) | |
3117 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f); | |
3118 } | |
3119 else | |
3120 max_x = window_box_width (w, updated_area); | |
3121 max_y = window_text_bottom_y (w); | |
3122 | |
3123 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end | |
3124 of window. For TO_X > 0, truncate to end of drawing area. */ | |
3125 if (to_x == 0) | |
3126 return; | |
3127 else if (to_x < 0) | |
3128 to_x = max_x; | |
3129 else | |
3130 to_x = min (to_x, max_x); | |
3131 | |
3132 to_y = min (max_y, output_cursor.y + updated_row->height); | |
3133 | |
3134 /* Notice if the cursor will be cleared by this operation. */ | |
3135 if (!updated_row->full_width_p) | |
3136 notice_overwritten_cursor (w, updated_area, | |
3137 output_cursor.x, -1, | |
3138 updated_row->y, | |
3139 MATRIX_ROW_BOTTOM_Y (updated_row)); | |
3140 | |
3141 from_x = output_cursor.x; | |
3142 | |
3143 /* Translate to frame coordinates. */ | |
3144 if (updated_row->full_width_p) | |
3145 { | |
3146 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x); | |
3147 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x); | |
3148 } | |
3149 else | |
3150 { | |
3151 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x); | |
3152 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x); | |
3153 } | |
3154 | |
3155 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w); | |
3156 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y)); | |
3157 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y); | |
3158 | |
3159 /* Prevent inadvertently clearing to end of the X window. */ | |
3160 if (to_x > from_x && to_y > from_y) | |
3161 { | |
3162 BLOCK_INPUT; | |
3163 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
3164 from_x, from_y, to_x - from_x, to_y - from_y, | |
3165 False); | |
3166 UNBLOCK_INPUT; | |
3167 } | |
3168 } | 2717 } |
3169 | 2718 |
3170 | 2719 |
3171 /* Clear entire frame. If updating_frame is non-null, clear that | 2720 /* Clear entire frame. If updating_frame is non-null, clear that |
3172 frame. Otherwise clear the selected frame. */ | 2721 frame. Otherwise clear the selected frame. */ |
3497 | 3046 |
3498 /*********************************************************************** | 3047 /*********************************************************************** |
3499 Exposure Events | 3048 Exposure Events |
3500 ***********************************************************************/ | 3049 ***********************************************************************/ |
3501 | 3050 |
3502 /* Redisplay an exposed area of frame F. X and Y are the upper-left | |
3503 corner of the exposed rectangle. W and H are width and height of | |
3504 the exposed area. All are pixel values. W or H zero means redraw | |
3505 the entire frame. */ | |
3506 | |
3507 static void | |
3508 expose_frame (f, x, y, w, h) | |
3509 struct frame *f; | |
3510 int x, y, w, h; | |
3511 { | |
3512 XRectangle r; | |
3513 int mouse_face_overwritten_p = 0; | |
3514 | |
3515 TRACE ((stderr, "expose_frame ")); | |
3516 | |
3517 /* No need to redraw if frame will be redrawn soon. */ | |
3518 if (FRAME_GARBAGED_P (f)) | |
3519 { | |
3520 TRACE ((stderr, " garbaged\n")); | |
3521 return; | |
3522 } | |
3523 | |
3524 /* If basic faces haven't been realized yet, there is no point in | |
3525 trying to redraw anything. This can happen when we get an expose | |
3526 event while Emacs is starting, e.g. by moving another window. */ | |
3527 if (FRAME_FACE_CACHE (f) == NULL | |
3528 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL) | |
3529 { | |
3530 TRACE ((stderr, " no faces\n")); | |
3531 return; | |
3532 } | |
3533 | |
3534 if (w == 0 || h == 0) | |
3535 { | |
3536 r.x = r.y = 0; | |
3537 r.width = CANON_X_UNIT (f) * f->width; | |
3538 r.height = CANON_Y_UNIT (f) * f->height; | |
3539 } | |
3540 else | |
3541 { | |
3542 r.x = x; | |
3543 r.y = y; | |
3544 r.width = w; | |
3545 r.height = h; | |
3546 } | |
3547 | |
3548 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height)); | |
3549 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r); | |
3550 | |
3551 if (WINDOWP (f->tool_bar_window)) | |
3552 mouse_face_overwritten_p | |
3553 |= expose_window (XWINDOW (f->tool_bar_window), &r); | |
3554 | |
3555 #ifndef USE_X_TOOLKIT | |
3556 if (WINDOWP (f->menu_bar_window)) | |
3557 mouse_face_overwritten_p | |
3558 |= expose_window (XWINDOW (f->menu_bar_window), &r); | |
3559 #endif /* not USE_X_TOOLKIT */ | |
3560 | |
3561 /* Some window managers support a focus-follows-mouse style with | |
3562 delayed raising of frames. Imagine a partially obscured frame, | |
3563 and moving the mouse into partially obscured mouse-face on that | |
3564 frame. The visible part of the mouse-face will be highlighted, | |
3565 then the WM raises the obscured frame. With at least one WM, KDE | |
3566 2.1, Emacs is not getting any event for the raising of the frame | |
3567 (even tried with SubstructureRedirectMask), only Expose events. | |
3568 These expose events will draw text normally, i.e. not | |
3569 highlighted. Which means we must redo the highlight here. | |
3570 Subsume it under ``we love X''. --gerd 2001-08-15 */ | |
3571 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f)) | |
3572 { | |
3573 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
3574 if (f == dpyinfo->mouse_face_mouse_frame) | |
3575 { | |
3576 int x = dpyinfo->mouse_face_mouse_x; | |
3577 int y = dpyinfo->mouse_face_mouse_y; | |
3578 clear_mouse_face (dpyinfo); | |
3579 note_mouse_highlight (f, x, y); | |
3580 } | |
3581 } | |
3582 } | |
3583 | |
3584 | |
3585 /* Redraw (parts) of all windows in the window tree rooted at W that | |
3586 intersect R. R contains frame pixel coordinates. Value is | |
3587 non-zero if the exposure overwrites mouse-face. */ | |
3588 | |
3589 static int | |
3590 expose_window_tree (w, r) | |
3591 struct window *w; | |
3592 XRectangle *r; | |
3593 { | |
3594 struct frame *f = XFRAME (w->frame); | |
3595 int mouse_face_overwritten_p = 0; | |
3596 | |
3597 while (w && !FRAME_GARBAGED_P (f)) | |
3598 { | |
3599 if (!NILP (w->hchild)) | |
3600 mouse_face_overwritten_p | |
3601 |= expose_window_tree (XWINDOW (w->hchild), r); | |
3602 else if (!NILP (w->vchild)) | |
3603 mouse_face_overwritten_p | |
3604 |= expose_window_tree (XWINDOW (w->vchild), r); | |
3605 else | |
3606 mouse_face_overwritten_p |= expose_window (w, r); | |
3607 | |
3608 w = NILP (w->next) ? NULL : XWINDOW (w->next); | |
3609 } | |
3610 | |
3611 return mouse_face_overwritten_p; | |
3612 } | |
3613 | |
3614 | |
3615 /* Redraw the part of glyph row area AREA of glyph row ROW on window W | |
3616 which intersects rectangle R. R is in window-relative coordinates. */ | |
3617 | |
3618 static void | |
3619 expose_area (w, row, r, area) | |
3620 struct window *w; | |
3621 struct glyph_row *row; | |
3622 XRectangle *r; | |
3623 enum glyph_row_area area; | |
3624 { | |
3625 struct glyph *first = row->glyphs[area]; | |
3626 struct glyph *end = row->glyphs[area] + row->used[area]; | |
3627 struct glyph *last; | |
3628 int first_x, start_x, x; | |
3629 | |
3630 if (area == TEXT_AREA && row->fill_line_p) | |
3631 /* If row extends face to end of line write the whole line. */ | |
3632 x_draw_glyphs (w, 0, row, area, 0, row->used[area], | |
3633 DRAW_NORMAL_TEXT, 0); | |
3634 else | |
3635 { | |
3636 /* Set START_X to the window-relative start position for drawing glyphs of | |
3637 AREA. The first glyph of the text area can be partially visible. | |
3638 The first glyphs of other areas cannot. */ | |
3639 if (area == LEFT_MARGIN_AREA) | |
3640 start_x = 0; | |
3641 else if (area == TEXT_AREA) | |
3642 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA); | |
3643 else | |
3644 start_x = (window_box_width (w, LEFT_MARGIN_AREA) | |
3645 + window_box_width (w, TEXT_AREA)); | |
3646 x = start_x; | |
3647 | |
3648 /* Find the first glyph that must be redrawn. */ | |
3649 while (first < end | |
3650 && x + first->pixel_width < r->x) | |
3651 { | |
3652 x += first->pixel_width; | |
3653 ++first; | |
3654 } | |
3655 | |
3656 /* Find the last one. */ | |
3657 last = first; | |
3658 first_x = x; | |
3659 while (last < end | |
3660 && x < r->x + r->width) | |
3661 { | |
3662 x += last->pixel_width; | |
3663 ++last; | |
3664 } | |
3665 | |
3666 /* Repaint. */ | |
3667 if (last > first) | |
3668 x_draw_glyphs (w, first_x - start_x, row, area, | |
3669 first - row->glyphs[area], | |
3670 last - row->glyphs[area], | |
3671 DRAW_NORMAL_TEXT, 0); | |
3672 } | |
3673 } | |
3674 | |
3675 | |
3676 /* Redraw the parts of the glyph row ROW on window W intersecting | |
3677 rectangle R. R is in window-relative coordinates. Value is | |
3678 non-zero if mouse-face was overwritten. */ | |
3679 | |
3680 static int | |
3681 expose_line (w, row, r) | |
3682 struct window *w; | |
3683 struct glyph_row *row; | |
3684 XRectangle *r; | |
3685 { | |
3686 xassert (row->enabled_p); | |
3687 | |
3688 if (row->mode_line_p || w->pseudo_window_p) | |
3689 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA], | |
3690 DRAW_NORMAL_TEXT, 0); | |
3691 else | |
3692 { | |
3693 if (row->used[LEFT_MARGIN_AREA]) | |
3694 expose_area (w, row, r, LEFT_MARGIN_AREA); | |
3695 if (row->used[TEXT_AREA]) | |
3696 expose_area (w, row, r, TEXT_AREA); | |
3697 if (row->used[RIGHT_MARGIN_AREA]) | |
3698 expose_area (w, row, r, RIGHT_MARGIN_AREA); | |
3699 draw_row_fringe_bitmaps (w, row); | |
3700 } | |
3701 | |
3702 return row->mouse_face_p; | |
3703 } | |
3704 | |
3705 | |
3706 /* Return non-zero if W's cursor intersects rectangle R. */ | |
3707 | |
3708 static int | |
3709 x_phys_cursor_in_rect_p (w, r) | |
3710 struct window *w; | |
3711 XRectangle *r; | |
3712 { | |
3713 XRectangle cr, result; | |
3714 struct glyph *cursor_glyph; | |
3715 | |
3716 cursor_glyph = get_phys_cursor_glyph (w); | |
3717 if (cursor_glyph) | |
3718 { | |
3719 cr.x = w->phys_cursor.x; | |
3720 cr.y = w->phys_cursor.y; | |
3721 cr.width = cursor_glyph->pixel_width; | |
3722 cr.height = w->phys_cursor_height; | |
3723 return x_intersect_rectangles (&cr, r, &result); | |
3724 } | |
3725 else | |
3726 return 0; | |
3727 } | |
3728 | |
3729 | |
3730 /* Redraw those parts of glyphs rows during expose event handling that | |
3731 overlap other rows. Redrawing of an exposed line writes over parts | |
3732 of lines overlapping that exposed line; this function fixes that. | |
3733 | |
3734 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first | |
3735 row in W's current matrix that is exposed and overlaps other rows. | |
3736 LAST_OVERLAPPING_ROW is the last such row. */ | |
3737 | |
3738 static void | |
3739 expose_overlaps (w, first_overlapping_row, last_overlapping_row) | |
3740 struct window *w; | |
3741 struct glyph_row *first_overlapping_row; | |
3742 struct glyph_row *last_overlapping_row; | |
3743 { | |
3744 struct glyph_row *row; | |
3745 | |
3746 for (row = first_overlapping_row; row <= last_overlapping_row; ++row) | |
3747 if (row->overlapping_p) | |
3748 { | |
3749 xassert (row->enabled_p && !row->mode_line_p); | |
3750 | |
3751 if (row->used[LEFT_MARGIN_AREA]) | |
3752 x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA); | |
3753 | |
3754 if (row->used[TEXT_AREA]) | |
3755 x_fix_overlapping_area (w, row, TEXT_AREA); | |
3756 | |
3757 if (row->used[RIGHT_MARGIN_AREA]) | |
3758 x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA); | |
3759 } | |
3760 } | |
3761 | |
3762 | |
3763 /* Redraw the part of window W intersection rectangle FR. Pixel | |
3764 coordinates in FR are frame-relative. Call this function with | |
3765 input blocked. Value is non-zero if the exposure overwrites | |
3766 mouse-face. */ | |
3767 | |
3768 static int | |
3769 expose_window (w, fr) | |
3770 struct window *w; | |
3771 XRectangle *fr; | |
3772 { | |
3773 struct frame *f = XFRAME (w->frame); | |
3774 XRectangle wr, r; | |
3775 int mouse_face_overwritten_p = 0; | |
3776 | |
3777 /* If window is not yet fully initialized, do nothing. This can | |
3778 happen when toolkit scroll bars are used and a window is split. | |
3779 Reconfiguring the scroll bar will generate an expose for a newly | |
3780 created window. */ | |
3781 if (w->current_matrix == NULL) | |
3782 return 0; | |
3783 | |
3784 /* When we're currently updating the window, display and current | |
3785 matrix usually don't agree. Arrange for a thorough display | |
3786 later. */ | |
3787 if (w == updated_window) | |
3788 { | |
3789 SET_FRAME_GARBAGED (f); | |
3790 return 0; | |
3791 } | |
3792 | |
3793 /* Frame-relative pixel rectangle of W. */ | |
3794 wr.x = XFASTINT (w->left) * CANON_X_UNIT (f); | |
3795 wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f); | |
3796 wr.width = XFASTINT (w->width) * CANON_X_UNIT (f); | |
3797 wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f); | |
3798 | |
3799 if (x_intersect_rectangles (fr, &wr, &r)) | |
3800 { | |
3801 int yb = window_text_bottom_y (w); | |
3802 struct glyph_row *row; | |
3803 int cursor_cleared_p; | |
3804 struct glyph_row *first_overlapping_row, *last_overlapping_row; | |
3805 | |
3806 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n", | |
3807 r.x, r.y, r.width, r.height)); | |
3808 | |
3809 /* Convert to window coordinates. */ | |
3810 r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x); | |
3811 r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y); | |
3812 | |
3813 /* Turn off the cursor. */ | |
3814 if (!w->pseudo_window_p | |
3815 && x_phys_cursor_in_rect_p (w, &r)) | |
3816 { | |
3817 x_clear_cursor (w); | |
3818 cursor_cleared_p = 1; | |
3819 } | |
3820 else | |
3821 cursor_cleared_p = 0; | |
3822 | |
3823 /* Update lines intersecting rectangle R. */ | |
3824 first_overlapping_row = last_overlapping_row = NULL; | |
3825 for (row = w->current_matrix->rows; | |
3826 row->enabled_p; | |
3827 ++row) | |
3828 { | |
3829 int y0 = row->y; | |
3830 int y1 = MATRIX_ROW_BOTTOM_Y (row); | |
3831 | |
3832 if ((y0 >= r.y && y0 < r.y + r.height) | |
3833 || (y1 > r.y && y1 < r.y + r.height) | |
3834 || (r.y >= y0 && r.y < y1) | |
3835 || (r.y + r.height > y0 && r.y + r.height < y1)) | |
3836 { | |
3837 if (row->overlapping_p) | |
3838 { | |
3839 if (first_overlapping_row == NULL) | |
3840 first_overlapping_row = row; | |
3841 last_overlapping_row = row; | |
3842 } | |
3843 | |
3844 if (expose_line (w, row, &r)) | |
3845 mouse_face_overwritten_p = 1; | |
3846 } | |
3847 | |
3848 if (y1 >= yb) | |
3849 break; | |
3850 } | |
3851 | |
3852 /* Display the mode line if there is one. */ | |
3853 if (WINDOW_WANTS_MODELINE_P (w) | |
3854 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix), | |
3855 row->enabled_p) | |
3856 && row->y < r.y + r.height) | |
3857 { | |
3858 if (expose_line (w, row, &r)) | |
3859 mouse_face_overwritten_p = 1; | |
3860 } | |
3861 | |
3862 if (!w->pseudo_window_p) | |
3863 { | |
3864 /* Fix the display of overlapping rows. */ | |
3865 if (first_overlapping_row) | |
3866 expose_overlaps (w, first_overlapping_row, last_overlapping_row); | |
3867 | |
3868 /* Draw border between windows. */ | |
3869 x_draw_vertical_border (w); | |
3870 | |
3871 /* Turn the cursor on again. */ | |
3872 if (cursor_cleared_p) | |
3873 x_update_window_cursor (w, 1); | |
3874 } | |
3875 } | |
3876 | |
3877 return mouse_face_overwritten_p; | |
3878 } | |
3879 | |
3880 | |
3881 /* Determine the intersection of two rectangles R1 and R2. Return | |
3882 the intersection in *RESULT. Value is non-zero if RESULT is not | |
3883 empty. */ | |
3884 | |
3885 static int | |
3886 x_intersect_rectangles (r1, r2, result) | |
3887 XRectangle *r1, *r2, *result; | |
3888 { | |
3889 XRectangle *left, *right; | |
3890 XRectangle *upper, *lower; | |
3891 int intersection_p = 0; | |
3892 | |
3893 /* Rearrange so that R1 is the left-most rectangle. */ | |
3894 if (r1->x < r2->x) | |
3895 left = r1, right = r2; | |
3896 else | |
3897 left = r2, right = r1; | |
3898 | |
3899 /* X0 of the intersection is right.x0, if this is inside R1, | |
3900 otherwise there is no intersection. */ | |
3901 if (right->x <= left->x + left->width) | |
3902 { | |
3903 result->x = right->x; | |
3904 | |
3905 /* The right end of the intersection is the minimum of the | |
3906 the right ends of left and right. */ | |
3907 result->width = (min (left->x + left->width, right->x + right->width) | |
3908 - result->x); | |
3909 | |
3910 /* Same game for Y. */ | |
3911 if (r1->y < r2->y) | |
3912 upper = r1, lower = r2; | |
3913 else | |
3914 upper = r2, lower = r1; | |
3915 | |
3916 /* The upper end of the intersection is lower.y0, if this is inside | |
3917 of upper. Otherwise, there is no intersection. */ | |
3918 if (lower->y <= upper->y + upper->height) | |
3919 { | |
3920 result->y = lower->y; | |
3921 | |
3922 /* The lower end of the intersection is the minimum of the lower | |
3923 ends of upper and lower. */ | |
3924 result->height = (min (lower->y + lower->height, | |
3925 upper->y + upper->height) | |
3926 - result->y); | |
3927 intersection_p = 1; | |
3928 } | |
3929 } | |
3930 | |
3931 return intersection_p; | |
3932 } | |
3933 | |
3934 | |
3935 | |
3936 | |
3937 | 3051 |
3938 static void | 3052 static void |
3939 frame_highlight (f) | 3053 frame_highlight (f) |
3940 struct frame *f; | 3054 struct frame *f; |
3941 { | 3055 { |
4525 | 3639 |
4526 /************************************************************************ | 3640 /************************************************************************ |
4527 Mouse Face | 3641 Mouse Face |
4528 ************************************************************************/ | 3642 ************************************************************************/ |
4529 | 3643 |
4530 /* Find the glyph under window-relative coordinates X/Y in window W. | |
4531 Consider only glyphs from buffer text, i.e. no glyphs from overlay | |
4532 strings. Return in *HPOS and *VPOS the row and column number of | |
4533 the glyph found. Return in *AREA the glyph area containing X. | |
4534 Value is a pointer to the glyph found or null if X/Y is not on | |
4535 text, or we can't tell because W's current matrix is not up to | |
4536 date. */ | |
4537 | |
4538 static struct glyph * | |
4539 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p) | |
4540 struct window *w; | |
4541 int x, y; | |
4542 int *hpos, *vpos, *area; | |
4543 int buffer_only_p; | |
4544 { | |
4545 struct glyph *glyph, *end; | |
4546 struct glyph_row *row = NULL; | |
4547 int x0, i, left_area_width; | |
4548 | |
4549 /* Find row containing Y. Give up if some row is not enabled. */ | |
4550 for (i = 0; i < w->current_matrix->nrows; ++i) | |
4551 { | |
4552 row = MATRIX_ROW (w->current_matrix, i); | |
4553 if (!row->enabled_p) | |
4554 return NULL; | |
4555 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row)) | |
4556 break; | |
4557 } | |
4558 | |
4559 *vpos = i; | |
4560 *hpos = 0; | |
4561 | |
4562 /* Give up if Y is not in the window. */ | |
4563 if (i == w->current_matrix->nrows) | |
4564 return NULL; | |
4565 | |
4566 /* Get the glyph area containing X. */ | |
4567 if (w->pseudo_window_p) | |
4568 { | |
4569 *area = TEXT_AREA; | |
4570 x0 = 0; | |
4571 } | |
4572 else | |
4573 { | |
4574 left_area_width = window_box_width (w, LEFT_MARGIN_AREA); | |
4575 if (x < left_area_width) | |
4576 { | |
4577 *area = LEFT_MARGIN_AREA; | |
4578 x0 = 0; | |
4579 } | |
4580 else if (x < left_area_width + window_box_width (w, TEXT_AREA)) | |
4581 { | |
4582 *area = TEXT_AREA; | |
4583 x0 = row->x + left_area_width; | |
4584 } | |
4585 else | |
4586 { | |
4587 *area = RIGHT_MARGIN_AREA; | |
4588 x0 = left_area_width + window_box_width (w, TEXT_AREA); | |
4589 } | |
4590 } | |
4591 | |
4592 /* Find glyph containing X. */ | |
4593 glyph = row->glyphs[*area]; | |
4594 end = glyph + row->used[*area]; | |
4595 while (glyph < end) | |
4596 { | |
4597 if (x < x0 + glyph->pixel_width) | |
4598 { | |
4599 if (w->pseudo_window_p) | |
4600 break; | |
4601 else if (!buffer_only_p || BUFFERP (glyph->object)) | |
4602 break; | |
4603 } | |
4604 | |
4605 x0 += glyph->pixel_width; | |
4606 ++glyph; | |
4607 } | |
4608 | |
4609 if (glyph == end) | |
4610 return NULL; | |
4611 | |
4612 *hpos = glyph - row->glyphs[*area]; | |
4613 return glyph; | |
4614 } | |
4615 | |
4616 | |
4617 /* Convert frame-relative x/y to coordinates relative to window W. | |
4618 Takes pseudo-windows into account. */ | |
4619 | |
4620 static void | |
4621 frame_to_window_pixel_xy (w, x, y) | |
4622 struct window *w; | |
4623 int *x, *y; | |
4624 { | |
4625 if (w->pseudo_window_p) | |
4626 { | |
4627 /* A pseudo-window is always full-width, and starts at the | |
4628 left edge of the frame, plus a frame border. */ | |
4629 struct frame *f = XFRAME (w->frame); | |
4630 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f); | |
4631 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y); | |
4632 } | |
4633 else | |
4634 { | |
4635 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x); | |
4636 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y); | |
4637 } | |
4638 } | |
4639 | |
4640 | |
4641 /* Take proper action when mouse has moved to the mode or header line | |
4642 or marginal area of window W, x-position X and y-position Y. Area | |
4643 is 1, 3, 6 or 7 for the mode line, header line, left and right | |
4644 marginal area respectively. X is relative to the start of the text | |
4645 display area of W, so the width of bitmap areas and scroll bars | |
4646 must be subtracted to get a position relative to the start of the | |
4647 mode line. */ | |
4648 | |
4649 static void | |
4650 note_mode_line_or_margin_highlight (w, x, y, portion) | |
4651 struct window *w; | |
4652 int x, y, portion; | |
4653 { | |
4654 struct frame *f = XFRAME (w->frame); | |
4655 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
4656 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor; | |
4657 int charpos; | |
4658 Lisp_Object string, help, map, pos; | |
4659 | |
4660 if (portion == 1 || portion == 3) | |
4661 string = mode_line_string (w, x, y, portion == 1, &charpos); | |
4662 else | |
4663 string = marginal_area_string (w, x, y, portion, &charpos); | |
4664 | |
4665 if (STRINGP (string)) | |
4666 { | |
4667 pos = make_number (charpos); | |
4668 | |
4669 /* If we're on a string with `help-echo' text property, arrange | |
4670 for the help to be displayed. This is done by setting the | |
4671 global variable help_echo to the help string. */ | |
4672 help = Fget_text_property (pos, Qhelp_echo, string); | |
4673 if (!NILP (help)) | |
4674 { | |
4675 help_echo = help; | |
4676 XSETWINDOW (help_echo_window, w); | |
4677 help_echo_object = string; | |
4678 help_echo_pos = charpos; | |
4679 } | |
4680 | |
4681 /* Change the mouse pointer according to what is under X/Y. */ | |
4682 map = Fget_text_property (pos, Qlocal_map, string); | |
4683 if (!KEYMAPP (map)) | |
4684 map = Fget_text_property (pos, Qkeymap, string); | |
4685 if (KEYMAPP (map)) | |
4686 cursor = f->output_data.x->nontext_cursor; | |
4687 } | |
4688 | |
4689 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor); | |
4690 } | |
4691 | |
4692 | |
4693 /* Take proper action when the mouse has moved to position X, Y on | |
4694 frame F as regards highlighting characters that have mouse-face | |
4695 properties. Also de-highlighting chars where the mouse was before. | |
4696 X and Y can be negative or out of range. */ | |
4697 | |
4698 static void | |
4699 note_mouse_highlight (f, x, y) | |
4700 struct frame *f; | |
4701 int x, y; | |
4702 { | |
4703 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
4704 int portion; | |
4705 Lisp_Object window; | |
4706 struct window *w; | |
4707 Cursor cursor = None; | |
4708 struct buffer *b; | |
4709 | |
4710 /* When a menu is active, don't highlight because this looks odd. */ | |
4711 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) | |
4712 if (popup_activated ()) | |
4713 return; | |
4714 #endif | |
4715 | |
4716 if (NILP (Vmouse_highlight) | |
4717 || !f->glyphs_initialized_p) | |
4718 return; | |
4719 | |
4720 dpyinfo->mouse_face_mouse_x = x; | |
4721 dpyinfo->mouse_face_mouse_y = y; | |
4722 dpyinfo->mouse_face_mouse_frame = f; | |
4723 | |
4724 if (dpyinfo->mouse_face_defer) | |
4725 return; | |
4726 | |
4727 if (gc_in_progress) | |
4728 { | |
4729 dpyinfo->mouse_face_deferred_gc = 1; | |
4730 return; | |
4731 } | |
4732 | |
4733 /* Which window is that in? */ | |
4734 window = window_from_coordinates (f, x, y, &portion, 1); | |
4735 | |
4736 /* If we were displaying active text in another window, clear that. */ | |
4737 if (! EQ (window, dpyinfo->mouse_face_window)) | |
4738 clear_mouse_face (dpyinfo); | |
4739 | |
4740 /* Not on a window -> return. */ | |
4741 if (!WINDOWP (window)) | |
4742 return; | |
4743 | |
4744 /* Convert to window-relative pixel coordinates. */ | |
4745 w = XWINDOW (window); | |
4746 frame_to_window_pixel_xy (w, &x, &y); | |
4747 | |
4748 /* Handle tool-bar window differently since it doesn't display a | |
4749 buffer. */ | |
4750 if (EQ (window, f->tool_bar_window)) | |
4751 { | |
4752 note_tool_bar_highlight (f, x, y); | |
4753 return; | |
4754 } | |
4755 | |
4756 /* Mouse is on the mode, header line or margin? */ | |
4757 if (portion == 1 || portion == 3 || portion == 6 || portion == 7) | |
4758 { | |
4759 note_mode_line_or_margin_highlight (w, x, y, portion); | |
4760 return; | |
4761 } | |
4762 | |
4763 if (portion == 2) | |
4764 cursor = f->output_data.x->horizontal_drag_cursor; | |
4765 else | |
4766 cursor = f->output_data.x->text_cursor; | |
4767 | |
4768 /* Are we in a window whose display is up to date? | |
4769 And verify the buffer's text has not changed. */ | |
4770 b = XBUFFER (w->buffer); | |
4771 if (/* Within text portion of the window. */ | |
4772 portion == 0 | |
4773 && EQ (w->window_end_valid, w->buffer) | |
4774 && XFASTINT (w->last_modified) == BUF_MODIFF (b) | |
4775 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b)) | |
4776 { | |
4777 int hpos, vpos, pos, i, area; | |
4778 struct glyph *glyph; | |
4779 Lisp_Object object; | |
4780 Lisp_Object mouse_face = Qnil, overlay = Qnil, position; | |
4781 Lisp_Object *overlay_vec = NULL; | |
4782 int len, noverlays; | |
4783 struct buffer *obuf; | |
4784 int obegv, ozv, same_region; | |
4785 | |
4786 /* Find the glyph under X/Y. */ | |
4787 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0); | |
4788 | |
4789 /* Clear mouse face if X/Y not over text. */ | |
4790 if (glyph == NULL | |
4791 || area != TEXT_AREA | |
4792 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p) | |
4793 { | |
4794 if (clear_mouse_face (dpyinfo)) | |
4795 cursor = None; | |
4796 goto set_cursor; | |
4797 } | |
4798 | |
4799 pos = glyph->charpos; | |
4800 object = glyph->object; | |
4801 if (!STRINGP (object) && !BUFFERP (object)) | |
4802 goto set_cursor; | |
4803 | |
4804 /* If we get an out-of-range value, return now; avoid an error. */ | |
4805 if (BUFFERP (object) && pos > BUF_Z (b)) | |
4806 goto set_cursor; | |
4807 | |
4808 /* Make the window's buffer temporarily current for | |
4809 overlays_at and compute_char_face. */ | |
4810 obuf = current_buffer; | |
4811 current_buffer = b; | |
4812 obegv = BEGV; | |
4813 ozv = ZV; | |
4814 BEGV = BEG; | |
4815 ZV = Z; | |
4816 | |
4817 /* Is this char mouse-active or does it have help-echo? */ | |
4818 position = make_number (pos); | |
4819 | |
4820 if (BUFFERP (object)) | |
4821 { | |
4822 /* Put all the overlays we want in a vector in overlay_vec. | |
4823 Store the length in len. If there are more than 10, make | |
4824 enough space for all, and try again. */ | |
4825 len = 10; | |
4826 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); | |
4827 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0); | |
4828 if (noverlays > len) | |
4829 { | |
4830 len = noverlays; | |
4831 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); | |
4832 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0); | |
4833 } | |
4834 | |
4835 /* Sort overlays into increasing priority order. */ | |
4836 noverlays = sort_overlays (overlay_vec, noverlays, w); | |
4837 } | |
4838 else | |
4839 noverlays = 0; | |
4840 | |
4841 same_region = (EQ (window, dpyinfo->mouse_face_window) | |
4842 && vpos >= dpyinfo->mouse_face_beg_row | |
4843 && vpos <= dpyinfo->mouse_face_end_row | |
4844 && (vpos > dpyinfo->mouse_face_beg_row | |
4845 || hpos >= dpyinfo->mouse_face_beg_col) | |
4846 && (vpos < dpyinfo->mouse_face_end_row | |
4847 || hpos < dpyinfo->mouse_face_end_col | |
4848 || dpyinfo->mouse_face_past_end)); | |
4849 | |
4850 if (same_region) | |
4851 cursor = None; | |
4852 | |
4853 /* Check mouse-face highlighting. */ | |
4854 if (! same_region | |
4855 /* If there exists an overlay with mouse-face overlapping | |
4856 the one we are currently highlighting, we have to | |
4857 check if we enter the overlapping overlay, and then | |
4858 highlight only that. */ | |
4859 || (OVERLAYP (dpyinfo->mouse_face_overlay) | |
4860 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay))) | |
4861 { | |
4862 /* Find the highest priority overlay that has a mouse-face | |
4863 property. */ | |
4864 overlay = Qnil; | |
4865 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i) | |
4866 { | |
4867 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face); | |
4868 if (!NILP (mouse_face)) | |
4869 overlay = overlay_vec[i]; | |
4870 } | |
4871 | |
4872 /* If we're actually highlighting the same overlay as | |
4873 before, there's no need to do that again. */ | |
4874 if (!NILP (overlay) | |
4875 && EQ (overlay, dpyinfo->mouse_face_overlay)) | |
4876 goto check_help_echo; | |
4877 | |
4878 dpyinfo->mouse_face_overlay = overlay; | |
4879 | |
4880 /* Clear the display of the old active region, if any. */ | |
4881 if (clear_mouse_face (dpyinfo)) | |
4882 cursor = None; | |
4883 | |
4884 /* If no overlay applies, get a text property. */ | |
4885 if (NILP (overlay)) | |
4886 mouse_face = Fget_text_property (position, Qmouse_face, object); | |
4887 | |
4888 /* Handle the overlay case. */ | |
4889 if (!NILP (overlay)) | |
4890 { | |
4891 /* Find the range of text around this char that | |
4892 should be active. */ | |
4893 Lisp_Object before, after; | |
4894 int ignore; | |
4895 | |
4896 before = Foverlay_start (overlay); | |
4897 after = Foverlay_end (overlay); | |
4898 /* Record this as the current active region. */ | |
4899 fast_find_position (w, XFASTINT (before), | |
4900 &dpyinfo->mouse_face_beg_col, | |
4901 &dpyinfo->mouse_face_beg_row, | |
4902 &dpyinfo->mouse_face_beg_x, | |
4903 &dpyinfo->mouse_face_beg_y, Qnil); | |
4904 | |
4905 dpyinfo->mouse_face_past_end | |
4906 = !fast_find_position (w, XFASTINT (after), | |
4907 &dpyinfo->mouse_face_end_col, | |
4908 &dpyinfo->mouse_face_end_row, | |
4909 &dpyinfo->mouse_face_end_x, | |
4910 &dpyinfo->mouse_face_end_y, Qnil); | |
4911 dpyinfo->mouse_face_window = window; | |
4912 dpyinfo->mouse_face_face_id | |
4913 = face_at_buffer_position (w, pos, 0, 0, | |
4914 &ignore, pos + 1, | |
4915 !dpyinfo->mouse_face_hidden); | |
4916 | |
4917 /* Display it as active. */ | |
4918 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | |
4919 cursor = None; | |
4920 } | |
4921 /* Handle the text property case. */ | |
4922 else if (!NILP (mouse_face) && BUFFERP (object)) | |
4923 { | |
4924 /* Find the range of text around this char that | |
4925 should be active. */ | |
4926 Lisp_Object before, after, beginning, end; | |
4927 int ignore; | |
4928 | |
4929 beginning = Fmarker_position (w->start); | |
4930 end = make_number (BUF_Z (XBUFFER (object)) | |
4931 - XFASTINT (w->window_end_pos)); | |
4932 before | |
4933 = Fprevious_single_property_change (make_number (pos + 1), | |
4934 Qmouse_face, | |
4935 object, beginning); | |
4936 after | |
4937 = Fnext_single_property_change (position, Qmouse_face, | |
4938 object, end); | |
4939 | |
4940 /* Record this as the current active region. */ | |
4941 fast_find_position (w, XFASTINT (before), | |
4942 &dpyinfo->mouse_face_beg_col, | |
4943 &dpyinfo->mouse_face_beg_row, | |
4944 &dpyinfo->mouse_face_beg_x, | |
4945 &dpyinfo->mouse_face_beg_y, Qnil); | |
4946 dpyinfo->mouse_face_past_end | |
4947 = !fast_find_position (w, XFASTINT (after), | |
4948 &dpyinfo->mouse_face_end_col, | |
4949 &dpyinfo->mouse_face_end_row, | |
4950 &dpyinfo->mouse_face_end_x, | |
4951 &dpyinfo->mouse_face_end_y, Qnil); | |
4952 dpyinfo->mouse_face_window = window; | |
4953 | |
4954 if (BUFFERP (object)) | |
4955 dpyinfo->mouse_face_face_id | |
4956 = face_at_buffer_position (w, pos, 0, 0, | |
4957 &ignore, pos + 1, | |
4958 !dpyinfo->mouse_face_hidden); | |
4959 | |
4960 /* Display it as active. */ | |
4961 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | |
4962 cursor = None; | |
4963 } | |
4964 else if (!NILP (mouse_face) && STRINGP (object)) | |
4965 { | |
4966 Lisp_Object b, e; | |
4967 int ignore; | |
4968 | |
4969 b = Fprevious_single_property_change (make_number (pos + 1), | |
4970 Qmouse_face, | |
4971 object, Qnil); | |
4972 e = Fnext_single_property_change (position, Qmouse_face, | |
4973 object, Qnil); | |
4974 if (NILP (b)) | |
4975 b = make_number (0); | |
4976 if (NILP (e)) | |
4977 e = make_number (SCHARS (object) - 1); | |
4978 fast_find_string_pos (w, XINT (b), object, | |
4979 &dpyinfo->mouse_face_beg_col, | |
4980 &dpyinfo->mouse_face_beg_row, | |
4981 &dpyinfo->mouse_face_beg_x, | |
4982 &dpyinfo->mouse_face_beg_y, 0); | |
4983 fast_find_string_pos (w, XINT (e), object, | |
4984 &dpyinfo->mouse_face_end_col, | |
4985 &dpyinfo->mouse_face_end_row, | |
4986 &dpyinfo->mouse_face_end_x, | |
4987 &dpyinfo->mouse_face_end_y, 1); | |
4988 dpyinfo->mouse_face_past_end = 0; | |
4989 dpyinfo->mouse_face_window = window; | |
4990 dpyinfo->mouse_face_face_id | |
4991 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore, | |
4992 glyph->face_id, 1); | |
4993 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | |
4994 cursor = None; | |
4995 } | |
4996 else if (STRINGP (object) && NILP (mouse_face)) | |
4997 { | |
4998 /* A string which doesn't have mouse-face, but | |
4999 the text ``under'' it might have. */ | |
5000 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos); | |
5001 int start = MATRIX_ROW_START_CHARPOS (r); | |
5002 | |
5003 pos = string_buffer_position (w, object, start); | |
5004 if (pos > 0) | |
5005 mouse_face = get_char_property_and_overlay (make_number (pos), | |
5006 Qmouse_face, | |
5007 w->buffer, | |
5008 &overlay); | |
5009 if (!NILP (mouse_face) && !NILP (overlay)) | |
5010 { | |
5011 Lisp_Object before = Foverlay_start (overlay); | |
5012 Lisp_Object after = Foverlay_end (overlay); | |
5013 int ignore; | |
5014 | |
5015 /* Note that we might not be able to find position | |
5016 BEFORE in the glyph matrix if the overlay is | |
5017 entirely covered by a `display' property. In | |
5018 this case, we overshoot. So let's stop in | |
5019 the glyph matrix before glyphs for OBJECT. */ | |
5020 fast_find_position (w, XFASTINT (before), | |
5021 &dpyinfo->mouse_face_beg_col, | |
5022 &dpyinfo->mouse_face_beg_row, | |
5023 &dpyinfo->mouse_face_beg_x, | |
5024 &dpyinfo->mouse_face_beg_y, | |
5025 object); | |
5026 | |
5027 dpyinfo->mouse_face_past_end | |
5028 = !fast_find_position (w, XFASTINT (after), | |
5029 &dpyinfo->mouse_face_end_col, | |
5030 &dpyinfo->mouse_face_end_row, | |
5031 &dpyinfo->mouse_face_end_x, | |
5032 &dpyinfo->mouse_face_end_y, | |
5033 Qnil); | |
5034 dpyinfo->mouse_face_window = window; | |
5035 dpyinfo->mouse_face_face_id | |
5036 = face_at_buffer_position (w, pos, 0, 0, | |
5037 &ignore, pos + 1, | |
5038 !dpyinfo->mouse_face_hidden); | |
5039 | |
5040 /* Display it as active. */ | |
5041 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | |
5042 cursor = None; | |
5043 } | |
5044 } | |
5045 } | |
5046 | |
5047 check_help_echo: | |
5048 | |
5049 /* Look for a `help-echo' property. */ | |
5050 { | |
5051 Lisp_Object help, overlay; | |
5052 | |
5053 /* Check overlays first. */ | |
5054 help = overlay = Qnil; | |
5055 for (i = noverlays - 1; i >= 0 && NILP (help); --i) | |
5056 { | |
5057 overlay = overlay_vec[i]; | |
5058 help = Foverlay_get (overlay, Qhelp_echo); | |
5059 } | |
5060 | |
5061 if (!NILP (help)) | |
5062 { | |
5063 help_echo = help; | |
5064 help_echo_window = window; | |
5065 help_echo_object = overlay; | |
5066 help_echo_pos = pos; | |
5067 } | |
5068 else | |
5069 { | |
5070 Lisp_Object object = glyph->object; | |
5071 int charpos = glyph->charpos; | |
5072 | |
5073 /* Try text properties. */ | |
5074 if (STRINGP (object) | |
5075 && charpos >= 0 | |
5076 && charpos < SCHARS (object)) | |
5077 { | |
5078 help = Fget_text_property (make_number (charpos), | |
5079 Qhelp_echo, object); | |
5080 if (NILP (help)) | |
5081 { | |
5082 /* If the string itself doesn't specify a help-echo, | |
5083 see if the buffer text ``under'' it does. */ | |
5084 struct glyph_row *r | |
5085 = MATRIX_ROW (w->current_matrix, vpos); | |
5086 int start = MATRIX_ROW_START_CHARPOS (r); | |
5087 int pos = string_buffer_position (w, object, start); | |
5088 if (pos > 0) | |
5089 { | |
5090 help = Fget_char_property (make_number (pos), | |
5091 Qhelp_echo, w->buffer); | |
5092 if (!NILP (help)) | |
5093 { | |
5094 charpos = pos; | |
5095 object = w->buffer; | |
5096 } | |
5097 } | |
5098 } | |
5099 } | |
5100 else if (BUFFERP (object) | |
5101 && charpos >= BEGV | |
5102 && charpos < ZV) | |
5103 help = Fget_text_property (make_number (charpos), Qhelp_echo, | |
5104 object); | |
5105 | |
5106 if (!NILP (help)) | |
5107 { | |
5108 help_echo = help; | |
5109 help_echo_window = window; | |
5110 help_echo_object = object; | |
5111 help_echo_pos = charpos; | |
5112 } | |
5113 } | |
5114 } | |
5115 | |
5116 BEGV = obegv; | |
5117 ZV = ozv; | |
5118 current_buffer = obuf; | |
5119 } | |
5120 | |
5121 set_cursor: | |
5122 | |
5123 if (cursor != None) | |
5124 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor); | |
5125 } | |
5126 | |
5127 static void | 3644 static void |
5128 redo_mouse_highlight () | 3645 redo_mouse_highlight () |
5129 { | 3646 { |
5130 if (!NILP (last_mouse_motion_frame) | 3647 if (!NILP (last_mouse_motion_frame) |
5131 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame))) | 3648 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame))) |
5133 last_mouse_motion_event.x, | 3650 last_mouse_motion_event.x, |
5134 last_mouse_motion_event.y); | 3651 last_mouse_motion_event.y); |
5135 } | 3652 } |
5136 | 3653 |
5137 | 3654 |
5138 | |
5139 /*********************************************************************** | |
5140 Tool-bars | |
5141 ***********************************************************************/ | |
5142 | |
5143 static int x_tool_bar_item P_ ((struct frame *, int, int, | |
5144 struct glyph **, int *, int *, int *)); | |
5145 | |
5146 /* Tool-bar item index of the item on which a mouse button was pressed | |
5147 or -1. */ | |
5148 | |
5149 static int last_tool_bar_item; | |
5150 | |
5151 | |
5152 /* Get information about the tool-bar item at position X/Y on frame F. | |
5153 Return in *GLYPH a pointer to the glyph of the tool-bar item in | |
5154 the current matrix of the tool-bar window of F, or NULL if not | |
5155 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar | |
5156 item in F->tool_bar_items. Value is | |
5157 | |
5158 -1 if X/Y is not on a tool-bar item | |
5159 0 if X/Y is on the same item that was highlighted before. | |
5160 1 otherwise. */ | |
5161 | |
5162 static int | |
5163 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx) | |
5164 struct frame *f; | |
5165 int x, y; | |
5166 struct glyph **glyph; | |
5167 int *hpos, *vpos, *prop_idx; | |
5168 { | |
5169 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
5170 struct window *w = XWINDOW (f->tool_bar_window); | |
5171 int area; | |
5172 | |
5173 /* Find the glyph under X/Y. */ | |
5174 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0); | |
5175 if (*glyph == NULL) | |
5176 return -1; | |
5177 | |
5178 /* Get the start of this tool-bar item's properties in | |
5179 f->tool_bar_items. */ | |
5180 if (!tool_bar_item_info (f, *glyph, prop_idx)) | |
5181 return -1; | |
5182 | |
5183 /* Is mouse on the highlighted item? */ | |
5184 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window) | |
5185 && *vpos >= dpyinfo->mouse_face_beg_row | |
5186 && *vpos <= dpyinfo->mouse_face_end_row | |
5187 && (*vpos > dpyinfo->mouse_face_beg_row | |
5188 || *hpos >= dpyinfo->mouse_face_beg_col) | |
5189 && (*vpos < dpyinfo->mouse_face_end_row | |
5190 || *hpos < dpyinfo->mouse_face_end_col | |
5191 || dpyinfo->mouse_face_past_end)) | |
5192 return 0; | |
5193 | |
5194 return 1; | |
5195 } | |
5196 | |
5197 | |
5198 /* Handle mouse button event on the tool-bar of frame F, at | |
5199 frame-relative coordinates X/Y. EVENT_TYPE is either ButtonPress | |
5200 or ButtonRelase. */ | |
5201 | |
5202 static void | |
5203 x_handle_tool_bar_click (f, button_event) | |
5204 struct frame *f; | |
5205 XButtonEvent *button_event; | |
5206 { | |
5207 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
5208 struct window *w = XWINDOW (f->tool_bar_window); | |
5209 int hpos, vpos, prop_idx; | |
5210 struct glyph *glyph; | |
5211 Lisp_Object enabled_p; | |
5212 int x = button_event->x; | |
5213 int y = button_event->y; | |
5214 | |
5215 /* If not on the highlighted tool-bar item, return. */ | |
5216 frame_to_window_pixel_xy (w, &x, &y); | |
5217 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0) | |
5218 return; | |
5219 | |
5220 /* If item is disabled, do nothing. */ | |
5221 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P); | |
5222 if (NILP (enabled_p)) | |
5223 return; | |
5224 | |
5225 if (button_event->type == ButtonPress) | |
5226 { | |
5227 /* Show item in pressed state. */ | |
5228 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN); | |
5229 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN; | |
5230 last_tool_bar_item = prop_idx; | |
5231 } | |
5232 else | |
5233 { | |
5234 Lisp_Object key, frame; | |
5235 struct input_event event; | |
5236 | |
5237 /* Show item in released state. */ | |
5238 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED); | |
5239 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED; | |
5240 | |
5241 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY); | |
5242 | |
5243 XSETFRAME (frame, f); | |
5244 event.kind = TOOL_BAR_EVENT; | |
5245 event.frame_or_window = frame; | |
5246 event.arg = frame; | |
5247 kbd_buffer_store_event (&event); | |
5248 | |
5249 event.kind = TOOL_BAR_EVENT; | |
5250 event.frame_or_window = frame; | |
5251 event.arg = key; | |
5252 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), | |
5253 button_event->state); | |
5254 kbd_buffer_store_event (&event); | |
5255 last_tool_bar_item = -1; | |
5256 } | |
5257 } | |
5258 | |
5259 | |
5260 /* Possibly highlight a tool-bar item on frame F when mouse moves to | |
5261 tool-bar window-relative coordinates X/Y. Called from | |
5262 note_mouse_highlight. */ | |
5263 | |
5264 static void | |
5265 note_tool_bar_highlight (f, x, y) | |
5266 struct frame *f; | |
5267 int x, y; | |
5268 { | |
5269 Lisp_Object window = f->tool_bar_window; | |
5270 struct window *w = XWINDOW (window); | |
5271 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
5272 int hpos, vpos; | |
5273 struct glyph *glyph; | |
5274 struct glyph_row *row; | |
5275 int i; | |
5276 Lisp_Object enabled_p; | |
5277 int prop_idx; | |
5278 enum draw_glyphs_face draw; | |
5279 int mouse_down_p, rc; | |
5280 | |
5281 /* Function note_mouse_highlight is called with negative x(y | |
5282 values when mouse moves outside of the frame. */ | |
5283 if (x <= 0 || y <= 0) | |
5284 { | |
5285 clear_mouse_face (dpyinfo); | |
5286 return; | |
5287 } | |
5288 | |
5289 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx); | |
5290 if (rc < 0) | |
5291 { | |
5292 /* Not on tool-bar item. */ | |
5293 clear_mouse_face (dpyinfo); | |
5294 return; | |
5295 } | |
5296 else if (rc == 0) | |
5297 goto set_help_echo; | |
5298 | |
5299 clear_mouse_face (dpyinfo); | |
5300 | |
5301 /* Mouse is down, but on different tool-bar item? */ | |
5302 mouse_down_p = (dpyinfo->grabbed | |
5303 && f == last_mouse_frame | |
5304 && FRAME_LIVE_P (f)); | |
5305 if (mouse_down_p | |
5306 && last_tool_bar_item != prop_idx) | |
5307 return; | |
5308 | |
5309 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT; | |
5310 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED; | |
5311 | |
5312 /* If tool-bar item is not enabled, don't highlight it. */ | |
5313 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P); | |
5314 if (!NILP (enabled_p)) | |
5315 { | |
5316 /* Compute the x-position of the glyph. In front and past the | |
5317 image is a space. We include this is the highlighted area. */ | |
5318 row = MATRIX_ROW (w->current_matrix, vpos); | |
5319 for (i = x = 0; i < hpos; ++i) | |
5320 x += row->glyphs[TEXT_AREA][i].pixel_width; | |
5321 | |
5322 /* Record this as the current active region. */ | |
5323 dpyinfo->mouse_face_beg_col = hpos; | |
5324 dpyinfo->mouse_face_beg_row = vpos; | |
5325 dpyinfo->mouse_face_beg_x = x; | |
5326 dpyinfo->mouse_face_beg_y = row->y; | |
5327 dpyinfo->mouse_face_past_end = 0; | |
5328 | |
5329 dpyinfo->mouse_face_end_col = hpos + 1; | |
5330 dpyinfo->mouse_face_end_row = vpos; | |
5331 dpyinfo->mouse_face_end_x = x + glyph->pixel_width; | |
5332 dpyinfo->mouse_face_end_y = row->y; | |
5333 dpyinfo->mouse_face_window = window; | |
5334 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID; | |
5335 | |
5336 /* Display it as active. */ | |
5337 show_mouse_face (dpyinfo, draw); | |
5338 dpyinfo->mouse_face_image_state = draw; | |
5339 } | |
5340 | |
5341 set_help_echo: | |
5342 | |
5343 /* Set help_echo to a help string to display for this tool-bar item. | |
5344 XTread_socket does the rest. */ | |
5345 help_echo_object = help_echo_window = Qnil; | |
5346 help_echo_pos = -1; | |
5347 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP); | |
5348 if (NILP (help_echo)) | |
5349 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION); | |
5350 } | |
5351 | |
5352 | |
5353 | |
5354 /* Find the glyph matrix position of buffer position CHARPOS in window | |
5355 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's | |
5356 current glyphs must be up to date. If CHARPOS is above window | |
5357 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end | |
5358 of last line in W. In the row containing CHARPOS, stop before glyphs | |
5359 having STOP as object. */ | |
5360 | |
5361 #if 0 /* This is a version of fast_find_position that's more correct | |
5362 in the presence of hscrolling, for example. I didn't install | |
5363 it right away because the problem fixed is minor, it failed | |
5364 in 20.x as well, and I think it's too risky to install | |
5365 so near the release of 21.1. 2001-09-25 gerd. */ | |
5366 | |
5367 static int | |
5368 fast_find_position (w, charpos, hpos, vpos, x, y, stop) | |
5369 struct window *w; | |
5370 int charpos; | |
5371 int *hpos, *vpos, *x, *y; | |
5372 Lisp_Object stop; | |
5373 { | |
5374 struct glyph_row *row, *first; | |
5375 struct glyph *glyph, *end; | |
5376 int i, past_end = 0; | |
5377 | |
5378 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | |
5379 row = row_containing_pos (w, charpos, first, NULL, 0); | |
5380 if (row == NULL) | |
5381 { | |
5382 if (charpos < MATRIX_ROW_START_CHARPOS (first)) | |
5383 { | |
5384 *x = *y = *hpos = *vpos = 0; | |
5385 return 0; | |
5386 } | |
5387 else | |
5388 { | |
5389 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); | |
5390 past_end = 1; | |
5391 } | |
5392 } | |
5393 | |
5394 *x = row->x; | |
5395 *y = row->y; | |
5396 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix); | |
5397 | |
5398 glyph = row->glyphs[TEXT_AREA]; | |
5399 end = glyph + row->used[TEXT_AREA]; | |
5400 | |
5401 /* Skip over glyphs not having an object at the start of the row. | |
5402 These are special glyphs like truncation marks on terminal | |
5403 frames. */ | |
5404 if (row->displays_text_p) | |
5405 while (glyph < end | |
5406 && INTEGERP (glyph->object) | |
5407 && !EQ (stop, glyph->object) | |
5408 && glyph->charpos < 0) | |
5409 { | |
5410 *x += glyph->pixel_width; | |
5411 ++glyph; | |
5412 } | |
5413 | |
5414 while (glyph < end | |
5415 && !INTEGERP (glyph->object) | |
5416 && !EQ (stop, glyph->object) | |
5417 && (!BUFFERP (glyph->object) | |
5418 || glyph->charpos < charpos)) | |
5419 { | |
5420 *x += glyph->pixel_width; | |
5421 ++glyph; | |
5422 } | |
5423 | |
5424 *hpos = glyph - row->glyphs[TEXT_AREA]; | |
5425 return past_end; | |
5426 } | |
5427 | |
5428 #else /* not 0 */ | |
5429 | |
5430 static int | |
5431 fast_find_position (w, pos, hpos, vpos, x, y, stop) | |
5432 struct window *w; | |
5433 int pos; | |
5434 int *hpos, *vpos, *x, *y; | |
5435 Lisp_Object stop; | |
5436 { | |
5437 int i; | |
5438 int lastcol; | |
5439 int maybe_next_line_p = 0; | |
5440 int line_start_position; | |
5441 int yb = window_text_bottom_y (w); | |
5442 struct glyph_row *row, *best_row; | |
5443 int row_vpos, best_row_vpos; | |
5444 int current_x; | |
5445 | |
5446 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | |
5447 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix); | |
5448 | |
5449 while (row->y < yb) | |
5450 { | |
5451 if (row->used[TEXT_AREA]) | |
5452 line_start_position = row->glyphs[TEXT_AREA]->charpos; | |
5453 else | |
5454 line_start_position = 0; | |
5455 | |
5456 if (line_start_position > pos) | |
5457 break; | |
5458 /* If the position sought is the end of the buffer, | |
5459 don't include the blank lines at the bottom of the window. */ | |
5460 else if (line_start_position == pos | |
5461 && pos == BUF_ZV (XBUFFER (w->buffer))) | |
5462 { | |
5463 maybe_next_line_p = 1; | |
5464 break; | |
5465 } | |
5466 else if (line_start_position > 0) | |
5467 { | |
5468 best_row = row; | |
5469 best_row_vpos = row_vpos; | |
5470 } | |
5471 | |
5472 if (row->y + row->height >= yb) | |
5473 break; | |
5474 | |
5475 ++row; | |
5476 ++row_vpos; | |
5477 } | |
5478 | |
5479 /* Find the right column within BEST_ROW. */ | |
5480 lastcol = 0; | |
5481 current_x = best_row->x; | |
5482 for (i = 0; i < best_row->used[TEXT_AREA]; i++) | |
5483 { | |
5484 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i; | |
5485 int charpos = glyph->charpos; | |
5486 | |
5487 if (BUFFERP (glyph->object)) | |
5488 { | |
5489 if (charpos == pos) | |
5490 { | |
5491 *hpos = i; | |
5492 *vpos = best_row_vpos; | |
5493 *x = current_x; | |
5494 *y = best_row->y; | |
5495 return 1; | |
5496 } | |
5497 else if (charpos > pos) | |
5498 break; | |
5499 } | |
5500 else if (EQ (glyph->object, stop)) | |
5501 break; | |
5502 | |
5503 if (charpos > 0) | |
5504 lastcol = i; | |
5505 current_x += glyph->pixel_width; | |
5506 } | |
5507 | |
5508 /* If we're looking for the end of the buffer, | |
5509 and we didn't find it in the line we scanned, | |
5510 use the start of the following line. */ | |
5511 if (maybe_next_line_p) | |
5512 { | |
5513 ++best_row; | |
5514 ++best_row_vpos; | |
5515 lastcol = 0; | |
5516 current_x = best_row->x; | |
5517 } | |
5518 | |
5519 *vpos = best_row_vpos; | |
5520 *hpos = lastcol + 1; | |
5521 *x = current_x; | |
5522 *y = best_row->y; | |
5523 return 0; | |
5524 } | |
5525 | |
5526 #endif /* not 0 */ | |
5527 | |
5528 | |
5529 /* Find the position of the glyph for position POS in OBJECT in | |
5530 window W's current matrix, and return in *X, *Y the pixel | |
5531 coordinates, and return in *HPOS, *VPOS the column/row of the glyph. | |
5532 | |
5533 RIGHT_P non-zero means return the position of the right edge of the | |
5534 glyph, RIGHT_P zero means return the left edge position. | |
5535 | |
5536 If no glyph for POS exists in the matrix, return the position of | |
5537 the glyph with the next smaller position that is in the matrix, if | |
5538 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS | |
5539 exists in the matrix, return the position of the glyph with the | |
5540 next larger position in OBJECT. | |
5541 | |
5542 Value is non-zero if a glyph was found. */ | |
5543 | |
5544 static int | |
5545 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p) | |
5546 struct window *w; | |
5547 int pos; | |
5548 Lisp_Object object; | |
5549 int *hpos, *vpos, *x, *y; | |
5550 int right_p; | |
5551 { | |
5552 int yb = window_text_bottom_y (w); | |
5553 struct glyph_row *r; | |
5554 struct glyph *best_glyph = NULL; | |
5555 struct glyph_row *best_row = NULL; | |
5556 int best_x = 0; | |
5557 | |
5558 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | |
5559 r->enabled_p && r->y < yb; | |
5560 ++r) | |
5561 { | |
5562 struct glyph *g = r->glyphs[TEXT_AREA]; | |
5563 struct glyph *e = g + r->used[TEXT_AREA]; | |
5564 int gx; | |
5565 | |
5566 for (gx = r->x; g < e; gx += g->pixel_width, ++g) | |
5567 if (EQ (g->object, object)) | |
5568 { | |
5569 if (g->charpos == pos) | |
5570 { | |
5571 best_glyph = g; | |
5572 best_x = gx; | |
5573 best_row = r; | |
5574 goto found; | |
5575 } | |
5576 else if (best_glyph == NULL | |
5577 || ((abs (g->charpos - pos) | |
5578 < abs (best_glyph->charpos - pos)) | |
5579 && (right_p | |
5580 ? g->charpos < pos | |
5581 : g->charpos > pos))) | |
5582 { | |
5583 best_glyph = g; | |
5584 best_x = gx; | |
5585 best_row = r; | |
5586 } | |
5587 } | |
5588 } | |
5589 | |
5590 found: | |
5591 | |
5592 if (best_glyph) | |
5593 { | |
5594 *x = best_x; | |
5595 *hpos = best_glyph - best_row->glyphs[TEXT_AREA]; | |
5596 | |
5597 if (right_p) | |
5598 { | |
5599 *x += best_glyph->pixel_width; | |
5600 ++*hpos; | |
5601 } | |
5602 | |
5603 *y = best_row->y; | |
5604 *vpos = best_row - w->current_matrix->rows; | |
5605 } | |
5606 | |
5607 return best_glyph != NULL; | |
5608 } | |
5609 | |
5610 | |
5611 /* Display the active region described by mouse_face_* | |
5612 in its mouse-face if HL > 0, in its normal face if HL = 0. */ | |
5613 | |
5614 static void | |
5615 show_mouse_face (dpyinfo, draw) | |
5616 struct x_display_info *dpyinfo; | |
5617 enum draw_glyphs_face draw; | |
5618 { | |
5619 struct window *w = XWINDOW (dpyinfo->mouse_face_window); | |
5620 struct frame *f = XFRAME (WINDOW_FRAME (w)); | |
5621 | |
5622 if (/* If window is in the process of being destroyed, don't bother | |
5623 to do anything. */ | |
5624 w->current_matrix != NULL | |
5625 /* Don't update mouse highlight if hidden */ | |
5626 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden) | |
5627 /* Recognize when we are called to operate on rows that don't exist | |
5628 anymore. This can happen when a window is split. */ | |
5629 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows) | |
5630 { | |
5631 int phys_cursor_on_p = w->phys_cursor_on_p; | |
5632 struct glyph_row *row, *first, *last; | |
5633 | |
5634 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row); | |
5635 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row); | |
5636 | |
5637 for (row = first; row <= last && row->enabled_p; ++row) | |
5638 { | |
5639 int start_hpos, end_hpos, start_x; | |
5640 | |
5641 /* For all but the first row, the highlight starts at column 0. */ | |
5642 if (row == first) | |
5643 { | |
5644 start_hpos = dpyinfo->mouse_face_beg_col; | |
5645 start_x = dpyinfo->mouse_face_beg_x; | |
5646 } | |
5647 else | |
5648 { | |
5649 start_hpos = 0; | |
5650 start_x = 0; | |
5651 } | |
5652 | |
5653 if (row == last) | |
5654 end_hpos = dpyinfo->mouse_face_end_col; | |
5655 else | |
5656 end_hpos = row->used[TEXT_AREA]; | |
5657 | |
5658 if (end_hpos > start_hpos) | |
5659 { | |
5660 x_draw_glyphs (w, start_x, row, TEXT_AREA, | |
5661 start_hpos, end_hpos, draw, 0); | |
5662 | |
5663 row->mouse_face_p | |
5664 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED; | |
5665 } | |
5666 } | |
5667 | |
5668 /* When we've written over the cursor, arrange for it to | |
5669 be displayed again. */ | |
5670 if (phys_cursor_on_p && !w->phys_cursor_on_p) | |
5671 x_display_cursor (w, 1, | |
5672 w->phys_cursor.hpos, w->phys_cursor.vpos, | |
5673 w->phys_cursor.x, w->phys_cursor.y); | |
5674 } | |
5675 | |
5676 /* Change the mouse cursor. */ | |
5677 if (draw == DRAW_NORMAL_TEXT) | |
5678 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
5679 f->output_data.x->text_cursor); | |
5680 else if (draw == DRAW_MOUSE_FACE) | |
5681 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
5682 f->output_data.x->cross_cursor); | |
5683 else | |
5684 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
5685 f->output_data.x->nontext_cursor); | |
5686 } | |
5687 | |
5688 /* Clear out the mouse-highlighted active region. | |
5689 Redraw it un-highlighted first. Value is non-zero if mouse | |
5690 face was actually drawn unhighlighted. */ | |
5691 | |
5692 static int | |
5693 clear_mouse_face (dpyinfo) | |
5694 struct x_display_info *dpyinfo; | |
5695 { | |
5696 int cleared = 0; | |
5697 | |
5698 if (!NILP (dpyinfo->mouse_face_window)) | |
5699 { | |
5700 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT); | |
5701 cleared = 1; | |
5702 } | |
5703 | |
5704 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; | |
5705 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; | |
5706 dpyinfo->mouse_face_window = Qnil; | |
5707 dpyinfo->mouse_face_overlay = Qnil; | |
5708 return cleared; | |
5709 } | |
5710 | |
5711 | |
5712 /* Clear any mouse-face on window W. This function is part of the | |
5713 redisplay interface, and is called from try_window_id and similar | |
5714 functions to ensure the mouse-highlight is off. */ | |
5715 | |
5716 static void | |
5717 x_clear_mouse_face (w) | |
5718 struct window *w; | |
5719 { | |
5720 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame)); | |
5721 Lisp_Object window; | |
5722 | |
5723 BLOCK_INPUT; | |
5724 XSETWINDOW (window, w); | |
5725 if (EQ (window, dpyinfo->mouse_face_window)) | |
5726 clear_mouse_face (dpyinfo); | |
5727 UNBLOCK_INPUT; | |
5728 } | |
5729 | |
5730 | |
5731 /* Just discard the mouse face information for frame F, if any. | |
5732 This is used when the size of F is changed. */ | |
5733 | |
5734 void | |
5735 cancel_mouse_face (f) | |
5736 FRAME_PTR f; | |
5737 { | |
5738 Lisp_Object window; | |
5739 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
5740 | |
5741 window = dpyinfo->mouse_face_window; | |
5742 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f) | |
5743 { | |
5744 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; | |
5745 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; | |
5746 dpyinfo->mouse_face_window = Qnil; | |
5747 } | |
5748 } | |
5749 | |
5750 | |
5751 static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *)); | 3655 static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *)); |
5752 | 3656 |
5753 | 3657 |
5754 /* Try to determine frame pixel position and size of the glyph under | 3658 /* Try to determine frame pixel position and size of the glyph under |
5755 frame pixel coordinates X/Y on frame F . Return the position and | 3659 frame pixel coordinates X/Y on frame F . Return the position and |
5761 struct frame *f; | 3665 struct frame *f; |
5762 int x, y; | 3666 int x, y; |
5763 XRectangle *rect; | 3667 XRectangle *rect; |
5764 { | 3668 { |
5765 Lisp_Object window; | 3669 Lisp_Object window; |
5766 int part, found = 0; | 3670 int found = 0; |
5767 | 3671 |
5768 window = window_from_coordinates (f, x, y, &part, 0); | 3672 window = window_from_coordinates (f, x, y, 0, 0); |
5769 if (!NILP (window)) | 3673 if (!NILP (window)) |
5770 { | 3674 { |
5771 struct window *w = XWINDOW (window); | 3675 struct window *w = XWINDOW (window); |
5772 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | 3676 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); |
5773 struct glyph_row *end = r + w->current_matrix->nrows - 1; | 3677 struct glyph_row *end = r + w->current_matrix->nrows - 1; |
6020 | 3924 |
6021 UNBLOCK_INPUT; | 3925 UNBLOCK_INPUT; |
6022 } | 3926 } |
6023 | 3927 |
6024 | 3928 |
6025 #ifdef USE_X_TOOLKIT | |
6026 | |
6027 /* Atimer callback function for TIMER. Called every 0.1s to process | |
6028 Xt timeouts, if needed. We must avoid calling XtAppPending as | |
6029 much as possible because that function does an implicit XFlush | |
6030 that slows us down. */ | |
6031 | |
6032 static void | |
6033 x_process_timeouts (timer) | |
6034 struct atimer *timer; | |
6035 { | |
6036 if (toolkit_scroll_bar_interaction || popup_activated ()) | |
6037 { | |
6038 BLOCK_INPUT; | |
6039 while (XtAppPending (Xt_app_con) & XtIMTimer) | |
6040 XtAppProcessEvent (Xt_app_con, XtIMTimer); | |
6041 UNBLOCK_INPUT; | |
6042 } | |
6043 } | |
6044 | |
6045 #endif /* USE_X_TOOLKIT */ | |
6046 | |
6047 | 3929 |
3930 /*********************************************************************** | |
3931 Scroll bars | |
3932 ***********************************************************************/ | |
3933 | |
6048 /* Scroll bar support. */ | 3934 /* Scroll bar support. */ |
6049 | 3935 |
6050 /* Given an X window ID, find the struct scroll_bar which manages it. | 3936 /* Given an X window ID, find the struct scroll_bar which manages it. |
6051 This can be called in GC, so we have to make sure to strip off mark | 3937 This can be called in GC, so we have to make sure to strip off mark |
6052 bits. */ | 3938 bits. */ |
8809 { | 6695 { |
8810 Lisp_Object frame; | 6696 Lisp_Object frame; |
8811 int n; | 6697 int n; |
8812 | 6698 |
8813 XSETFRAME (frame, f); | 6699 XSETFRAME (frame, f); |
8814 help_echo = Qnil; | 6700 help_echo_string = Qnil; |
8815 n = gen_help_event (bufp, numchars, | 6701 n = gen_help_event (bufp, numchars, |
8816 Qnil, frame, Qnil, Qnil, 0); | 6702 Qnil, frame, Qnil, Qnil, 0); |
8817 bufp += n, count += n, numchars -= n; | 6703 bufp += n, count += n, numchars -= n; |
8818 } | 6704 } |
8819 | 6705 |
8833 | 6719 |
8834 goto OTHER; | 6720 goto OTHER; |
8835 | 6721 |
8836 case MotionNotify: | 6722 case MotionNotify: |
8837 { | 6723 { |
8838 previous_help_echo = help_echo; | 6724 previous_help_echo_string = help_echo_string; |
8839 help_echo = help_echo_object = help_echo_window = Qnil; | 6725 help_echo_string = help_echo_object = help_echo_window = Qnil; |
8840 help_echo_pos = -1; | 6726 help_echo_pos = -1; |
8841 | 6727 |
8842 if (dpyinfo->grabbed && last_mouse_frame | 6728 if (dpyinfo->grabbed && last_mouse_frame |
8843 && FRAME_LIVE_P (last_mouse_frame)) | 6729 && FRAME_LIVE_P (last_mouse_frame)) |
8844 f = last_mouse_frame; | 6730 f = last_mouse_frame; |
8856 | 6742 |
8857 /* Generate SELECT_WINDOW_EVENTs when needed. */ | 6743 /* Generate SELECT_WINDOW_EVENTs when needed. */ |
8858 if (mouse_autoselect_window) | 6744 if (mouse_autoselect_window) |
8859 { | 6745 { |
8860 Lisp_Object window; | 6746 Lisp_Object window; |
8861 int area; | |
8862 | 6747 |
8863 window = window_from_coordinates (f, | 6748 window = window_from_coordinates (f, |
8864 event.xmotion.x, event.xmotion.y, | 6749 event.xmotion.x, event.xmotion.y, |
8865 &area, 0); | 6750 0, 0); |
8866 | 6751 |
8867 /* Window will be selected only when it is not selected now and | 6752 /* Window will be selected only when it is not selected now and |
8868 last mouse movement event was not in it. Minibuffer window | 6753 last mouse movement event was not in it. Minibuffer window |
8869 will be selected iff it is active. */ | 6754 will be selected iff it is active. */ |
8870 if (WINDOWP(window) | 6755 if (WINDOWP(window) |
8895 /* If we move outside the frame, then we're | 6780 /* If we move outside the frame, then we're |
8896 certainly no longer on any text in the frame. */ | 6781 certainly no longer on any text in the frame. */ |
8897 clear_mouse_face (dpyinfo); | 6782 clear_mouse_face (dpyinfo); |
8898 } | 6783 } |
8899 | 6784 |
8900 /* If the contents of the global variable help_echo | 6785 /* If the contents of the global variable help_echo_string |
8901 has changed, generate a HELP_EVENT. */ | 6786 has changed, generate a HELP_EVENT. */ |
8902 if (!NILP (help_echo) | 6787 if (!NILP (help_echo_string) |
8903 || !NILP (previous_help_echo)) | 6788 || !NILP (previous_help_echo_string)) |
8904 { | 6789 { |
8905 Lisp_Object frame; | 6790 Lisp_Object frame; |
8906 int n; | 6791 int n; |
8907 | 6792 |
8908 if (f) | 6793 if (f) |
8909 XSETFRAME (frame, f); | 6794 XSETFRAME (frame, f); |
8910 else | 6795 else |
8911 frame = Qnil; | 6796 frame = Qnil; |
8912 | 6797 |
8913 any_help_event_p = 1; | 6798 any_help_event_p = 1; |
8914 n = gen_help_event (bufp, numchars, help_echo, frame, | 6799 n = gen_help_event (bufp, numchars, help_echo_string, frame, |
8915 help_echo_window, help_echo_object, | 6800 help_echo_window, help_echo_object, |
8916 help_echo_pos); | 6801 help_echo_pos); |
8917 bufp += n, count += n, numchars -= n; | 6802 bufp += n, count += n, numchars -= n; |
8918 } | 6803 } |
8919 | 6804 |
9020 /* Is this in the tool-bar? */ | 6905 /* Is this in the tool-bar? */ |
9021 if (WINDOWP (f->tool_bar_window) | 6906 if (WINDOWP (f->tool_bar_window) |
9022 && XFASTINT (XWINDOW (f->tool_bar_window)->height)) | 6907 && XFASTINT (XWINDOW (f->tool_bar_window)->height)) |
9023 { | 6908 { |
9024 Lisp_Object window; | 6909 Lisp_Object window; |
9025 int p, x, y; | 6910 int x = event.xbutton.x; |
9026 | 6911 int y = event.xbutton.y; |
9027 x = event.xbutton.x; | 6912 |
9028 y = event.xbutton.y; | 6913 window = window_from_coordinates (f, x, y, 0, 1); |
9029 | |
9030 /* Set x and y. */ | |
9031 window = window_from_coordinates (f, x, y, &p, 1); | |
9032 if (EQ (window, f->tool_bar_window)) | 6914 if (EQ (window, f->tool_bar_window)) |
9033 { | 6915 { |
9034 x_handle_tool_bar_click (f, &event.xbutton); | 6916 if (event.xbutton.type == ButtonPress) |
9035 tool_bar_p = 1; | 6917 handle_tool_bar_click (f, x, y, 1, 0); |
6918 else | |
6919 handle_tool_bar_click (f, x, y, 0, | |
6920 x_x_to_emacs_modifiers (dpyinfo, | |
6921 event.xbutton.state)); | |
6922 tool_bar_p = 1; | |
9036 } | 6923 } |
9037 } | 6924 } |
9038 | 6925 |
9039 if (!tool_bar_p) | 6926 if (!tool_bar_p) |
9040 if (!dpyinfo->x_focus_frame | 6927 if (!dpyinfo->x_focus_frame |
9530 the bar might not be in the window. */ | 7417 the bar might not be in the window. */ |
9531 if (cursor_glyph->type == IMAGE_GLYPH) | 7418 if (cursor_glyph->type == IMAGE_GLYPH) |
9532 { | 7419 { |
9533 struct glyph_row *row; | 7420 struct glyph_row *row; |
9534 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos); | 7421 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos); |
9535 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR); | 7422 draw_phys_cursor_glyph (w, row, DRAW_CURSOR); |
9536 } | 7423 } |
9537 else | 7424 else |
9538 { | 7425 { |
9539 Display *dpy = FRAME_X_DISPLAY (f); | 7426 Display *dpy = FRAME_X_DISPLAY (f); |
9540 Window window = FRAME_X_WINDOW (f); | 7427 Window window = FRAME_X_WINDOW (f); |
9585 XSetClipMask (dpy, gc, None); | 7472 XSetClipMask (dpy, gc, None); |
9586 } | 7473 } |
9587 } | 7474 } |
9588 | 7475 |
9589 | 7476 |
9590 /* Clear the cursor of window W to background color, and mark the | 7477 /* RIF: Define cursor CURSOR on frame F. */ |
9591 cursor as not shown. This is used when the text where the cursor | |
9592 is is about to be rewritten. */ | |
9593 | 7478 |
9594 static void | 7479 static void |
9595 x_clear_cursor (w) | 7480 x_define_frame_cursor (f, cursor) |
7481 struct frame *f; | |
7482 Cursor cursor; | |
7483 { | |
7484 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor); | |
7485 } | |
7486 | |
7487 | |
7488 /* RIF: Clear area on frame F. */ | |
7489 | |
7490 static void | |
7491 x_clear_frame_area (f, x, y, width, height) | |
7492 struct frame *f; | |
7493 int x, y, width, height; | |
7494 { | |
7495 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
7496 x, y, width, height, False); | |
7497 } | |
7498 | |
7499 | |
7500 /* RIF: Draw cursor on window W. */ | |
7501 | |
7502 static void | |
7503 x_draw_window_cursor (w, glyph_row, on, x, y, new_cursor_type, new_cursor_width) | |
9596 struct window *w; | 7504 struct window *w; |
9597 { | 7505 struct glyph_row *glyph_row; |
9598 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p) | 7506 int on, x, y; |
9599 x_update_window_cursor (w, 0); | 7507 int new_cursor_type, new_cursor_width; |
9600 } | 7508 { |
9601 | 7509 struct frame *f = XFRAME (WINDOW_FRAME (w)); |
9602 | 7510 |
9603 /* Draw the cursor glyph of window W in glyph row ROW. See the | |
9604 comment of x_draw_glyphs for the meaning of HL. */ | |
9605 | |
9606 static void | |
9607 x_draw_phys_cursor_glyph (w, row, hl) | |
9608 struct window *w; | |
9609 struct glyph_row *row; | |
9610 enum draw_glyphs_face hl; | |
9611 { | |
9612 /* If cursor hpos is out of bounds, don't draw garbage. This can | |
9613 happen in mini-buffer windows when switching between echo area | |
9614 glyphs and mini-buffer. */ | |
9615 if (w->phys_cursor.hpos < row->used[TEXT_AREA]) | |
9616 { | |
9617 int on_p = w->phys_cursor_on_p; | |
9618 int x1; | |
9619 | |
9620 x1 = x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, | |
9621 w->phys_cursor.hpos, w->phys_cursor.hpos + 1, | |
9622 hl, 0); | |
9623 w->phys_cursor_on_p = on_p; | |
9624 | |
9625 if (hl == DRAW_CURSOR) | |
9626 w->phys_cursor_width = x1 - w->phys_cursor.x; | |
9627 | |
9628 /* When we erase the cursor, and ROW is overlapped by other | |
9629 rows, make sure that these overlapping parts of other rows | |
9630 are redrawn. */ | |
9631 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p) | |
9632 { | |
9633 if (row > w->current_matrix->rows | |
9634 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1)) | |
9635 x_fix_overlapping_area (w, row - 1, TEXT_AREA); | |
9636 | |
9637 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w) | |
9638 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1)) | |
9639 x_fix_overlapping_area (w, row + 1, TEXT_AREA); | |
9640 } | |
9641 } | |
9642 } | |
9643 | |
9644 | |
9645 /* Erase the image of a cursor of window W from the screen. */ | |
9646 | |
9647 static void | |
9648 x_erase_phys_cursor (w) | |
9649 struct window *w; | |
9650 { | |
9651 struct frame *f = XFRAME (w->frame); | |
9652 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
9653 int hpos = w->phys_cursor.hpos; | |
9654 int vpos = w->phys_cursor.vpos; | |
9655 int mouse_face_here_p = 0; | |
9656 struct glyph_matrix *active_glyphs = w->current_matrix; | |
9657 struct glyph_row *cursor_row; | |
9658 struct glyph *cursor_glyph; | |
9659 enum draw_glyphs_face hl; | |
9660 | |
9661 /* No cursor displayed or row invalidated => nothing to do on the | |
9662 screen. */ | |
9663 if (w->phys_cursor_type == NO_CURSOR) | |
9664 goto mark_cursor_off; | |
9665 | |
9666 /* VPOS >= active_glyphs->nrows means that window has been resized. | |
9667 Don't bother to erase the cursor. */ | |
9668 if (vpos >= active_glyphs->nrows) | |
9669 goto mark_cursor_off; | |
9670 | |
9671 /* If row containing cursor is marked invalid, there is nothing we | |
9672 can do. */ | |
9673 cursor_row = MATRIX_ROW (active_glyphs, vpos); | |
9674 if (!cursor_row->enabled_p) | |
9675 goto mark_cursor_off; | |
9676 | |
9677 /* If row is completely invisible, don't attempt to delete a cursor which | |
9678 isn't there. This can happen if cursor is at top of a window, and | |
9679 we switch to a buffer with a header line in that window. */ | |
9680 if (cursor_row->visible_height <= 0) | |
9681 goto mark_cursor_off; | |
9682 | |
9683 /* This can happen when the new row is shorter than the old one. | |
9684 In this case, either x_draw_glyphs or clear_end_of_line | |
9685 should have cleared the cursor. Note that we wouldn't be | |
9686 able to erase the cursor in this case because we don't have a | |
9687 cursor glyph at hand. */ | |
9688 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA]) | |
9689 goto mark_cursor_off; | |
9690 | |
9691 /* If the cursor is in the mouse face area, redisplay that when | |
9692 we clear the cursor. */ | |
9693 if (! NILP (dpyinfo->mouse_face_window) | |
9694 && w == XWINDOW (dpyinfo->mouse_face_window) | |
9695 && (vpos > dpyinfo->mouse_face_beg_row | |
9696 || (vpos == dpyinfo->mouse_face_beg_row | |
9697 && hpos >= dpyinfo->mouse_face_beg_col)) | |
9698 && (vpos < dpyinfo->mouse_face_end_row | |
9699 || (vpos == dpyinfo->mouse_face_end_row | |
9700 && hpos < dpyinfo->mouse_face_end_col)) | |
9701 /* Don't redraw the cursor's spot in mouse face if it is at the | |
9702 end of a line (on a newline). The cursor appears there, but | |
9703 mouse highlighting does not. */ | |
9704 && cursor_row->used[TEXT_AREA] > hpos) | |
9705 mouse_face_here_p = 1; | |
9706 | |
9707 /* Maybe clear the display under the cursor. */ | |
9708 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR) | |
9709 { | |
9710 int x; | |
9711 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w); | |
9712 | |
9713 cursor_glyph = get_phys_cursor_glyph (w); | |
9714 if (cursor_glyph == NULL) | |
9715 goto mark_cursor_off; | |
9716 | |
9717 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); | |
9718 | |
9719 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
9720 x, | |
9721 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, | |
9722 cursor_row->y)), | |
9723 cursor_glyph->pixel_width, | |
9724 cursor_row->visible_height, | |
9725 False); | |
9726 } | |
9727 | |
9728 /* Erase the cursor by redrawing the character underneath it. */ | |
9729 if (mouse_face_here_p) | |
9730 hl = DRAW_MOUSE_FACE; | |
9731 else | |
9732 hl = DRAW_NORMAL_TEXT; | |
9733 x_draw_phys_cursor_glyph (w, cursor_row, hl); | |
9734 | |
9735 mark_cursor_off: | |
9736 w->phys_cursor_on_p = 0; | |
9737 w->phys_cursor_type = NO_CURSOR; | |
9738 } | |
9739 | |
9740 | |
9741 /* Non-zero if physical cursor of window W is within mouse face. */ | |
9742 | |
9743 static int | |
9744 cursor_in_mouse_face_p (w) | |
9745 struct window *w; | |
9746 { | |
9747 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame)); | |
9748 int in_mouse_face = 0; | |
9749 | |
9750 if (WINDOWP (dpyinfo->mouse_face_window) | |
9751 && XWINDOW (dpyinfo->mouse_face_window) == w) | |
9752 { | |
9753 int hpos = w->phys_cursor.hpos; | |
9754 int vpos = w->phys_cursor.vpos; | |
9755 | |
9756 if (vpos >= dpyinfo->mouse_face_beg_row | |
9757 && vpos <= dpyinfo->mouse_face_end_row | |
9758 && (vpos > dpyinfo->mouse_face_beg_row | |
9759 || hpos >= dpyinfo->mouse_face_beg_col) | |
9760 && (vpos < dpyinfo->mouse_face_end_row | |
9761 || hpos < dpyinfo->mouse_face_end_col | |
9762 || dpyinfo->mouse_face_past_end)) | |
9763 in_mouse_face = 1; | |
9764 } | |
9765 | |
9766 return in_mouse_face; | |
9767 } | |
9768 | |
9769 | |
9770 /* Display or clear cursor of window W. If ON is zero, clear the | |
9771 cursor. If it is non-zero, display the cursor. If ON is nonzero, | |
9772 where to put the cursor is specified by HPOS, VPOS, X and Y. */ | |
9773 | |
9774 void | |
9775 x_display_and_set_cursor (w, on, hpos, vpos, x, y) | |
9776 struct window *w; | |
9777 int on, hpos, vpos, x, y; | |
9778 { | |
9779 struct frame *f = XFRAME (w->frame); | |
9780 int new_cursor_type; | |
9781 int new_cursor_width; | |
9782 int active_cursor; | |
9783 struct glyph_matrix *current_glyphs; | |
9784 struct glyph_row *glyph_row; | |
9785 struct glyph *glyph; | |
9786 | |
9787 /* This is pointless on invisible frames, and dangerous on garbaged | |
9788 windows and frames; in the latter case, the frame or window may | |
9789 be in the midst of changing its size, and x and y may be off the | |
9790 window. */ | |
9791 if (! FRAME_VISIBLE_P (f) | |
9792 || FRAME_GARBAGED_P (f) | |
9793 || vpos >= w->current_matrix->nrows | |
9794 || hpos >= w->current_matrix->matrix_w) | |
9795 return; | |
9796 | |
9797 /* If cursor is off and we want it off, return quickly. */ | |
9798 if (!on && !w->phys_cursor_on_p) | |
9799 return; | |
9800 | |
9801 current_glyphs = w->current_matrix; | |
9802 glyph_row = MATRIX_ROW (current_glyphs, vpos); | |
9803 glyph = glyph_row->glyphs[TEXT_AREA] + hpos; | |
9804 | |
9805 /* If cursor row is not enabled, we don't really know where to | |
9806 display the cursor. */ | |
9807 if (!glyph_row->enabled_p) | |
9808 { | |
9809 w->phys_cursor_on_p = 0; | |
9810 return; | |
9811 } | |
9812 | |
9813 xassert (interrupt_input_blocked); | |
9814 | |
9815 /* Set new_cursor_type to the cursor we want to be displayed. */ | |
9816 new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor); | |
9817 | |
9818 /* If cursor is currently being shown and we don't want it to be or | |
9819 it is in the wrong place, or the cursor type is not what we want, | |
9820 erase it. */ | |
9821 if (w->phys_cursor_on_p | |
9822 && (!on | |
9823 || w->phys_cursor.x != x | |
9824 || w->phys_cursor.y != y | |
9825 || new_cursor_type != w->phys_cursor_type | |
9826 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR) | |
9827 && new_cursor_width != w->phys_cursor_width))) | |
9828 x_erase_phys_cursor (w); | |
9829 | |
9830 /* Don't check phys_cursor_on_p here because that flag is only set | |
9831 to zero in some cases where we know that the cursor has been | |
9832 completely erased, to avoid the extra work of erasing the cursor | |
9833 twice. In other words, phys_cursor_on_p can be 1 and the cursor | |
9834 still not be visible, or it has only been partly erased. */ | |
9835 if (on) | 7511 if (on) |
9836 { | 7512 { |
9837 w->phys_cursor_ascent = glyph_row->ascent; | |
9838 w->phys_cursor_height = glyph_row->height; | |
9839 | |
9840 /* Set phys_cursor_.* before x_draw_.* is called because some | |
9841 of them may need the information. */ | |
9842 w->phys_cursor.x = x; | |
9843 w->phys_cursor.y = glyph_row->y; | |
9844 w->phys_cursor.hpos = hpos; | |
9845 w->phys_cursor.vpos = vpos; | |
9846 w->phys_cursor_type = new_cursor_type; | 7513 w->phys_cursor_type = new_cursor_type; |
9847 w->phys_cursor_on_p = 1; | 7514 w->phys_cursor_on_p = 1; |
9848 | 7515 |
9849 switch (new_cursor_type) | 7516 switch (new_cursor_type) |
9850 { | 7517 { |
9851 case HOLLOW_BOX_CURSOR: | 7518 case HOLLOW_BOX_CURSOR: |
9852 x_draw_hollow_cursor (w, glyph_row); | 7519 x_draw_hollow_cursor (w, glyph_row); |
9853 break; | 7520 break; |
9854 | 7521 |
9855 case FILLED_BOX_CURSOR: | 7522 case FILLED_BOX_CURSOR: |
9856 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); | 7523 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); |
9857 break; | 7524 break; |
9858 | 7525 |
9859 case BAR_CURSOR: | 7526 case BAR_CURSOR: |
9860 x_draw_bar_cursor (w, glyph_row, new_cursor_width, BAR_CURSOR); | 7527 x_draw_bar_cursor (w, glyph_row, new_cursor_width, BAR_CURSOR); |
9861 break; | 7528 break; |
9882 #ifndef XFlush | 7549 #ifndef XFlush |
9883 if (updating_frame != f) | 7550 if (updating_frame != f) |
9884 XFlush (FRAME_X_DISPLAY (f)); | 7551 XFlush (FRAME_X_DISPLAY (f)); |
9885 #endif | 7552 #endif |
9886 } | 7553 } |
9887 | |
9888 | |
9889 /* Display the cursor on window W, or clear it. X and Y are window | |
9890 relative pixel coordinates. HPOS and VPOS are glyph matrix | |
9891 positions. If W is not the selected window, display a hollow | |
9892 cursor. ON non-zero means display the cursor at X, Y which | |
9893 correspond to HPOS, VPOS, otherwise it is cleared. */ | |
9894 | |
9895 void | |
9896 x_display_cursor (w, on, hpos, vpos, x, y) | |
9897 struct window *w; | |
9898 int on, hpos, vpos, x, y; | |
9899 { | |
9900 BLOCK_INPUT; | |
9901 x_display_and_set_cursor (w, on, hpos, vpos, x, y); | |
9902 UNBLOCK_INPUT; | |
9903 } | |
9904 | |
9905 | |
9906 /* Display the cursor on window W, or clear it, according to ON_P. | |
9907 Don't change the cursor's position. */ | |
9908 | |
9909 void | |
9910 x_update_cursor (f, on_p) | |
9911 struct frame *f; | |
9912 int on_p; | |
9913 { | |
9914 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p); | |
9915 } | |
9916 | |
9917 | |
9918 /* Call x_update_window_cursor with parameter ON_P on all leaf windows | |
9919 in the window tree rooted at W. */ | |
9920 | |
9921 static void | |
9922 x_update_cursor_in_window_tree (w, on_p) | |
9923 struct window *w; | |
9924 int on_p; | |
9925 { | |
9926 while (w) | |
9927 { | |
9928 if (!NILP (w->hchild)) | |
9929 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p); | |
9930 else if (!NILP (w->vchild)) | |
9931 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p); | |
9932 else | |
9933 x_update_window_cursor (w, on_p); | |
9934 | |
9935 w = NILP (w->next) ? 0 : XWINDOW (w->next); | |
9936 } | |
9937 } | |
9938 | |
9939 | |
9940 /* Switch the display of W's cursor on or off, according to the value | |
9941 of ON. */ | |
9942 | |
9943 static void | |
9944 x_update_window_cursor (w, on) | |
9945 struct window *w; | |
9946 int on; | |
9947 { | |
9948 /* Don't update cursor in windows whose frame is in the process | |
9949 of being deleted. */ | |
9950 if (w->current_matrix) | |
9951 { | |
9952 BLOCK_INPUT; | |
9953 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos, | |
9954 w->phys_cursor.x, w->phys_cursor.y); | |
9955 UNBLOCK_INPUT; | |
9956 } | |
9957 } | |
9958 | |
9959 | |
9960 | 7554 |
9961 | 7555 |
9962 /* Icons. */ | 7556 /* Icons. */ |
9963 | 7557 |
9964 /* Make the x-window of frame F use the gnu icon bitmap. */ | 7558 /* Make the x-window of frame F use the gnu icon bitmap. */ |
10850 SET_FRAME_GARBAGED (f); | 8444 SET_FRAME_GARBAGED (f); |
10851 cancel_mouse_face (f); | 8445 cancel_mouse_face (f); |
10852 | 8446 |
10853 /* Wait for the change of frame size to occur */ | 8447 /* Wait for the change of frame size to occur */ |
10854 f->output_data.x->want_fullscreen |= FULLSCREEN_WAIT; | 8448 f->output_data.x->want_fullscreen |= FULLSCREEN_WAIT; |
10855 | |
10856 } | 8449 } |
10857 } | 8450 } |
10858 } | 8451 } |
10859 | 8452 |
10860 /* If frame parameters are set after the frame is mapped, we need to move | 8453 /* If frame parameters are set after the frame is mapped, we need to move |
13150 xfree (dpyinfo->x_id_name); | 10743 xfree (dpyinfo->x_id_name); |
13151 xfree (dpyinfo->color_cells); | 10744 xfree (dpyinfo->color_cells); |
13152 xfree (dpyinfo); | 10745 xfree (dpyinfo); |
13153 } | 10746 } |
13154 | 10747 |
10748 #ifdef USE_X_TOOLKIT | |
10749 | |
10750 /* Atimer callback function for TIMER. Called every 0.1s to process | |
10751 Xt timeouts, if needed. We must avoid calling XtAppPending as | |
10752 much as possible because that function does an implicit XFlush | |
10753 that slows us down. */ | |
10754 | |
10755 static void | |
10756 x_process_timeouts (timer) | |
10757 struct atimer *timer; | |
10758 { | |
10759 if (toolkit_scroll_bar_interaction || popup_activated ()) | |
10760 { | |
10761 BLOCK_INPUT; | |
10762 while (XtAppPending (Xt_app_con) & XtIMTimer) | |
10763 XtAppProcessEvent (Xt_app_con, XtIMTimer); | |
10764 UNBLOCK_INPUT; | |
10765 } | |
10766 } | |
10767 | |
10768 #endif /* USE_X_TOOLKIT */ | |
10769 | |
13155 | 10770 |
13156 /* Set up use of X before we make the first connection. */ | 10771 /* Set up use of X before we make the first connection. */ |
13157 | 10772 |
13158 static struct redisplay_interface x_redisplay_interface = | 10773 static struct redisplay_interface x_redisplay_interface = |
13159 { | 10774 { |
13163 x_clear_end_of_line, | 10778 x_clear_end_of_line, |
13164 x_scroll_run, | 10779 x_scroll_run, |
13165 x_after_update_window_line, | 10780 x_after_update_window_line, |
13166 x_update_window_begin, | 10781 x_update_window_begin, |
13167 x_update_window_end, | 10782 x_update_window_end, |
13168 XTcursor_to, | 10783 x_cursor_to, |
13169 x_flush, | 10784 x_flush, |
13170 x_clear_mouse_face, | 10785 #ifndef XFlush |
10786 x_flush, | |
10787 #else | |
10788 0, /* flush_display_optional */ | |
10789 #endif | |
10790 x_clear_window_mouse_face, | |
13171 x_get_glyph_overhangs, | 10791 x_get_glyph_overhangs, |
13172 x_fix_overlapping_area, | 10792 x_fix_overlapping_area, |
13173 x_draw_fringe_bitmap, | 10793 x_draw_fringe_bitmap, |
13174 x_per_char_metric, | 10794 x_per_char_metric, |
13175 x_encode_char, | 10795 x_encode_char, |
13176 x_compute_glyph_string_overhangs, | 10796 x_compute_glyph_string_overhangs, |
13177 x_draw_glyph_string | 10797 x_draw_glyph_string, |
10798 x_define_frame_cursor, | |
10799 x_clear_frame_area, | |
10800 x_draw_window_cursor, | |
10801 x_draw_vertical_window_border, | |
10802 x_shift_glyphs_for_insert | |
13178 }; | 10803 }; |
13179 | 10804 |
13180 void | 10805 void |
13181 x_initialize () | 10806 x_initialize () |
13182 { | 10807 { |
13198 frame_raise_lower_hook = XTframe_raise_lower; | 10823 frame_raise_lower_hook = XTframe_raise_lower; |
13199 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar; | 10824 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar; |
13200 condemn_scroll_bars_hook = XTcondemn_scroll_bars; | 10825 condemn_scroll_bars_hook = XTcondemn_scroll_bars; |
13201 redeem_scroll_bar_hook = XTredeem_scroll_bar; | 10826 redeem_scroll_bar_hook = XTredeem_scroll_bar; |
13202 judge_scroll_bars_hook = XTjudge_scroll_bars; | 10827 judge_scroll_bars_hook = XTjudge_scroll_bars; |
13203 estimate_mode_line_height_hook = x_estimate_mode_line_height; | |
13204 | 10828 |
13205 scroll_region_ok = 1; /* we'll scroll partial frames */ | 10829 scroll_region_ok = 1; /* we'll scroll partial frames */ |
13206 char_ins_del_ok = 1; | 10830 char_ins_del_ok = 1; |
13207 line_ins_del_ok = 1; /* we'll just blt 'em */ | 10831 line_ins_del_ok = 1; /* we'll just blt 'em */ |
13208 fast_clear_end_of_line = 1; /* X does this well */ | 10832 fast_clear_end_of_line = 1; /* X does this well */ |
13289 staticpro (&Qlatin_1); | 10913 staticpro (&Qlatin_1); |
13290 Qlatin_1 = intern ("latin-1"); | 10914 Qlatin_1 = intern ("latin-1"); |
13291 | 10915 |
13292 staticpro (&last_mouse_press_frame); | 10916 staticpro (&last_mouse_press_frame); |
13293 last_mouse_press_frame = Qnil; | 10917 last_mouse_press_frame = Qnil; |
13294 | |
13295 help_echo = Qnil; | |
13296 staticpro (&help_echo); | |
13297 help_echo_object = Qnil; | |
13298 staticpro (&help_echo_object); | |
13299 help_echo_window = Qnil; | |
13300 staticpro (&help_echo_window); | |
13301 previous_help_echo = Qnil; | |
13302 staticpro (&previous_help_echo); | |
13303 help_echo_pos = -1; | |
13304 | |
13305 DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window, | |
13306 doc: /* *Non-nil means autoselect window with mouse pointer. */); | |
13307 mouse_autoselect_window = 0; | |
13308 | |
13309 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p, | |
13310 doc: /* *Non-nil means draw block cursor as wide as the glyph under it. | |
13311 For example, if a block cursor is over a tab, it will be drawn as | |
13312 wide as that tab on the display. */); | |
13313 x_stretch_cursor_p = 0; | |
13314 | 10918 |
13315 DEFVAR_BOOL ("x-use-underline-position-properties", | 10919 DEFVAR_BOOL ("x-use-underline-position-properties", |
13316 &x_use_underline_position_properties, | 10920 &x_use_underline_position_properties, |
13317 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties. | 10921 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties. |
13318 nil means ignore them. If you encounter fonts with bogus | 10922 nil means ignore them. If you encounter fonts with bogus |