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