Mercurial > emacs
comparison src/macterm.c @ 50222:90e10bfd8bfa
* macterm.c: Remove consolidated defines and code.
(BETWEEN): Remove unused macro.
(mac_draw_vertical_window_border, mac_shift_glyphs_for_insert)
(mac_define_frame_cursor, mac_clear_frame_area)
(mac_draw_window_cursor): New Mac-specific functions for RIF.
(x_redisplay_interface): Add new members.
author | Kim F. Storm <storm@cua.dk> |
---|---|
date | Fri, 21 Mar 2003 13:50:10 +0000 |
parents | 203d5a0f77a8 |
children | 3fb54e5a7201 |
comparison
equal
deleted
inserted
replaced
50221:609980fd9f79 | 50222:90e10bfd8bfa |
---|---|
106 #include "window.h" | 106 #include "window.h" |
107 #include "intervals.h" | 107 #include "intervals.h" |
108 #include "composite.h" | 108 #include "composite.h" |
109 #include "coding.h" | 109 #include "coding.h" |
110 | 110 |
111 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER)) | |
112 | |
113 /* Set of macros that handle mapping of Mac modifier keys to emacs. */ | 111 /* Set of macros that handle mapping of Mac modifier keys to emacs. */ |
114 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \ | 112 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \ |
115 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey)) | 113 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey)) |
116 #define macShiftKey (shiftKey) | 114 #define macShiftKey (shiftKey) |
117 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \ | 115 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \ |
119 : controlKey) | 117 : controlKey) |
120 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey) | 118 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey) |
121 | 119 |
122 | 120 |
123 | 121 |
124 extern Lisp_Object Qhelp_echo; | |
125 | |
126 /* Non-nil means Emacs uses toolkit scroll bars. */ | 122 /* Non-nil means Emacs uses toolkit scroll bars. */ |
127 | 123 |
128 Lisp_Object Vx_toolkit_scroll_bars; | 124 Lisp_Object Vx_toolkit_scroll_bars; |
129 | |
130 /* If a string, XTread_socket generates an event to display that string. | |
131 (The display is done in read_char.) */ | |
132 | |
133 static Lisp_Object help_echo; | |
134 static Lisp_Object help_echo_window; | |
135 static Lisp_Object help_echo_object; | |
136 static int help_echo_pos; | |
137 | |
138 /* Temporary variable for XTread_socket. */ | |
139 | |
140 static Lisp_Object previous_help_echo; | |
141 | 125 |
142 /* Non-zero means that a HELP_EVENT has been generated since Emacs | 126 /* Non-zero means that a HELP_EVENT has been generated since Emacs |
143 start. */ | 127 start. */ |
144 | 128 |
145 static int any_help_event_p; | 129 static int any_help_event_p; |
150 | 134 |
151 /* Non-zero means draw block and hollow cursor as wide as the glyph | 135 /* Non-zero means draw block and hollow cursor as wide as the glyph |
152 under it. For example, if a block cursor is over a tab, it will be | 136 under it. For example, if a block cursor is over a tab, it will be |
153 drawn as wide as that tab on the display. */ | 137 drawn as wide as that tab on the display. */ |
154 | 138 |
155 int x_stretch_cursor_p; | |
156 | |
157 /* Non-zero means make use of UNDERLINE_POSITION font properties. */ | |
158 | |
159 int x_use_underline_position_properties; | |
160 | 139 |
161 /* This is a chain of structures for all the X displays currently in | 140 /* This is a chain of structures for all the X displays currently in |
162 use. */ | 141 use. */ |
163 | 142 |
164 struct x_display_info *x_display_list; | 143 struct x_display_info *x_display_list; |
183 extern int waiting_for_input; | 162 extern int waiting_for_input; |
184 | 163 |
185 /* This is a frame waiting to be auto-raised, within XTread_socket. */ | 164 /* This is a frame waiting to be auto-raised, within XTread_socket. */ |
186 | 165 |
187 struct frame *pending_autoraise_frame; | 166 struct frame *pending_autoraise_frame; |
188 | |
189 /* Nominal cursor position -- where to draw output. | |
190 HPOS and VPOS are window relative glyph matrix coordinates. | |
191 X and Y are window relative pixel coordinates. */ | |
192 | |
193 struct cursor_pos output_cursor; | |
194 | 167 |
195 /* Non-zero means user is interacting with a toolkit scroll bar. */ | 168 /* Non-zero means user is interacting with a toolkit scroll bar. */ |
196 | 169 |
197 static int toolkit_scroll_bar_interaction; | 170 static int toolkit_scroll_bar_interaction; |
198 | 171 |
216 tracking is on, and I suspect only negligibly worse when tracking | 189 tracking is on, and I suspect only negligibly worse when tracking |
217 is off. */ | 190 is off. */ |
218 | 191 |
219 /* Where the mouse was last time we reported a mouse event. */ | 192 /* Where the mouse was last time we reported a mouse event. */ |
220 | 193 |
221 FRAME_PTR last_mouse_frame; | |
222 static Rect last_mouse_glyph; | 194 static Rect last_mouse_glyph; |
223 static Lisp_Object last_mouse_press_frame; | 195 static Lisp_Object last_mouse_press_frame; |
224 | 196 |
225 /* The scroll bar in which the last X motion event occurred. | 197 /* The scroll bar in which the last X motion event occurred. |
226 | 198 |
301 | 273 |
302 | 274 |
303 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr); | 275 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr); |
304 struct mac_display_info *mac_display_info_for_display (Display *); | 276 struct mac_display_info *mac_display_info_for_display (Display *); |
305 static void x_update_window_end P_ ((struct window *, int, int)); | 277 static void x_update_window_end P_ ((struct window *, int, int)); |
306 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *)); | 278 static void mac_handle_tool_bar_click P_ ((struct frame *, EventRecord *)); |
307 static int fast_find_position P_ ((struct window *, int, int *, int *, | |
308 int *, int *, Lisp_Object)); | |
309 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object, | |
310 int *, int *, int *, int *, int)); | |
311 static void set_output_cursor P_ ((struct cursor_pos *)); | |
312 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int, | |
313 int *, int *, int *, int)); | |
314 static void note_mode_line_highlight P_ ((struct window *, int, int)); | |
315 static void note_mouse_highlight P_ ((struct frame *, int, int)); | |
316 static void note_tool_bar_highlight P_ ((struct frame *f, int, int)); | |
317 static void x_handle_tool_bar_click P_ ((struct frame *, EventRecord *)); | |
318 static void show_mouse_face P_ ((struct x_display_info *, | |
319 enum draw_glyphs_face)); | |
320 static int cursor_in_mouse_face_p P_ ((struct window *)); | |
321 static int clear_mouse_face P_ ((struct mac_display_info *)); | |
322 static int x_io_error_quitter P_ ((Display *)); | 279 static int x_io_error_quitter P_ ((Display *)); |
323 int x_catch_errors P_ ((Display *)); | 280 int x_catch_errors P_ ((Display *)); |
324 void x_uncatch_errors P_ ((Display *, int)); | 281 void x_uncatch_errors P_ ((Display *, int)); |
325 void x_lower_frame P_ ((struct frame *)); | 282 void x_lower_frame P_ ((struct frame *)); |
326 void x_scroll_bar_clear P_ ((struct frame *)); | 283 void x_scroll_bar_clear P_ ((struct frame *)); |
331 void x_wm_set_window_state P_ ((struct frame *, int)); | 288 void x_wm_set_window_state P_ ((struct frame *, int)); |
332 void x_wm_set_icon_pixmap P_ ((struct frame *, int)); | 289 void x_wm_set_icon_pixmap P_ ((struct frame *, int)); |
333 void mac_initialize P_ ((void)); | 290 void mac_initialize P_ ((void)); |
334 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *)); | 291 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *)); |
335 static int x_compute_min_glyph_bounds P_ ((struct frame *)); | 292 static int x_compute_min_glyph_bounds P_ ((struct frame *)); |
336 static void x_draw_phys_cursor_glyph P_ ((struct window *, | |
337 struct glyph_row *, | |
338 enum draw_glyphs_face)); | |
339 static void x_update_end P_ ((struct frame *)); | 293 static void x_update_end P_ ((struct frame *)); |
340 static void XTframe_up_to_date P_ ((struct frame *)); | 294 static void XTframe_up_to_date P_ ((struct frame *)); |
341 static void XTreassert_line_highlight P_ ((int, int)); | 295 static void XTreassert_line_highlight P_ ((int, int)); |
342 static void x_change_line_highlight P_ ((int, int, int, int)); | 296 static void x_change_line_highlight P_ ((int, int, int, int)); |
343 static void XTset_terminal_modes P_ ((void)); | 297 static void XTset_terminal_modes P_ ((void)); |
344 static void XTreset_terminal_modes P_ ((void)); | 298 static void XTreset_terminal_modes P_ ((void)); |
345 static void XTcursor_to P_ ((int, int, int, int)); | |
346 static void x_write_glyphs P_ ((struct glyph *, int)); | |
347 static void x_clear_end_of_line P_ ((int)); | |
348 static void x_clear_frame P_ ((void)); | 299 static void x_clear_frame P_ ((void)); |
349 static void x_clear_cursor P_ ((struct window *)); | |
350 static void frame_highlight P_ ((struct frame *)); | 300 static void frame_highlight P_ ((struct frame *)); |
351 static void frame_unhighlight P_ ((struct frame *)); | 301 static void frame_unhighlight P_ ((struct frame *)); |
352 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *)); | 302 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *)); |
353 static void XTframe_rehighlight P_ ((struct frame *)); | 303 static void XTframe_rehighlight P_ ((struct frame *)); |
354 static void x_frame_rehighlight P_ ((struct x_display_info *)); | 304 static void x_frame_rehighlight P_ ((struct x_display_info *)); |
355 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *)); | 305 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *)); |
356 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int)); | 306 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int)); |
357 static int x_intersect_rectangles P_ ((Rect *, Rect *, Rect *)); | |
358 static void expose_frame P_ ((struct frame *, int, int, int, int)); | |
359 static int expose_window_tree P_ ((struct window *, Rect *)); | |
360 static void expose_overlaps P_ ((struct window *, struct glyph_row *, | |
361 struct glyph_row *)); | |
362 static int expose_window P_ ((struct window *, Rect *)); | |
363 static void expose_area P_ ((struct window *, struct glyph_row *, | |
364 Rect *, enum glyph_row_area)); | |
365 static int expose_line P_ ((struct window *, struct glyph_row *, | |
366 Rect *)); | |
367 void x_display_cursor (struct window *, int, int, int, int, int); | |
368 void x_update_cursor P_ ((struct frame *, int)); | |
369 static void x_update_cursor_in_window_tree P_ ((struct window *, int)); | |
370 static void x_update_window_cursor P_ ((struct window *, int)); | |
371 static void x_erase_phys_cursor P_ ((struct window *)); | |
372 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int)); | |
373 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, | 307 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, |
374 GC, int)); | 308 GC, int)); |
375 static int x_phys_cursor_in_rect_p P_ ((struct window *, Rect *)); | |
376 static void x_flush P_ ((struct frame *f)); | 309 static void x_flush P_ ((struct frame *f)); |
377 static void x_update_begin P_ ((struct frame *)); | 310 static void x_update_begin P_ ((struct frame *)); |
378 static void x_update_window_begin P_ ((struct window *)); | 311 static void x_update_window_begin P_ ((struct window *)); |
379 static void x_draw_vertical_border P_ ((struct window *)); | |
380 static void x_after_update_window_line P_ ((struct glyph_row *)); | 312 static void x_after_update_window_line P_ ((struct glyph_row *)); |
381 | 313 |
382 static void activate_scroll_bars (FRAME_PTR); | 314 void activate_scroll_bars (FRAME_PTR); |
383 static void deactivate_scroll_bars (FRAME_PTR); | 315 void deactivate_scroll_bars (FRAME_PTR); |
384 | 316 |
385 static int is_emacs_window (WindowPtr); | 317 static int is_emacs_window (WindowPtr); |
386 | 318 |
387 extern int image_ascent (struct image *, struct face *); | 319 extern int image_ascent (struct image *, struct face *); |
388 void x_set_offset (struct frame *, int, int, int); | 320 void x_set_offset (struct frame *, int, int, int); |
1167 | 1099 |
1168 UNBLOCK_INPUT; | 1100 UNBLOCK_INPUT; |
1169 } | 1101 } |
1170 | 1102 |
1171 | 1103 |
1172 /* Draw a vertical window border to the right of window W if W doesn't | 1104 /* Draw a vertical window border from (x,y0) to (x,y1) */ |
1173 have vertical scroll bars. */ | 1105 |
1174 | 1106 static void |
1175 static void | 1107 mac_draw_vertical_window_border (w, x, y0, y1) |
1176 x_draw_vertical_border (w) | |
1177 struct window *w; | 1108 struct window *w; |
1109 int x, y0, y1; | |
1178 { | 1110 { |
1179 struct frame *f = XFRAME (WINDOW_FRAME (w)); | 1111 struct frame *f = XFRAME (WINDOW_FRAME (w)); |
1180 | 1112 |
1181 /* Redraw borders between horizontally adjacent windows. Don't | 1113 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), |
1182 do it for frames with vertical scroll bars because either the | 1114 f->output_data.mac->normal_gc, x, y0, x, y1); |
1183 right scroll bar of a window, or the left scroll bar of its | |
1184 neighbor will suffice as a border. */ | |
1185 if (!WINDOW_RIGHTMOST_P (w) | |
1186 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)) | |
1187 { | |
1188 int x0, x1, y0, y1; | |
1189 | |
1190 window_box_edges (w, -1, &x0, &y0, &x1, &y1); | |
1191 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f); | |
1192 y1 -= 1; | |
1193 | |
1194 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), | |
1195 f->output_data.mac->normal_gc, x1, y0, x1, y1); | |
1196 } | |
1197 } | 1115 } |
1198 | 1116 |
1199 | 1117 |
1200 /* End update of window W (which is equal to updated_window). | 1118 /* End update of window W (which is equal to updated_window). |
1201 | 1119 |
1213 static void | 1131 static void |
1214 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p) | 1132 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p) |
1215 struct window *w; | 1133 struct window *w; |
1216 int cursor_on_p, mouse_face_overwritten_p; | 1134 int cursor_on_p, mouse_face_overwritten_p; |
1217 { | 1135 { |
1218 struct mac_display_info *dpyinfo | 1136 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame)); |
1219 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame)); | |
1220 | 1137 |
1221 if (!w->pseudo_window_p) | 1138 if (!w->pseudo_window_p) |
1222 { | 1139 { |
1223 BLOCK_INPUT; | 1140 BLOCK_INPUT; |
1224 | 1141 |
1225 if (cursor_on_p) | 1142 if (cursor_on_p) |
1226 x_display_and_set_cursor (w, 1, output_cursor.hpos, | 1143 display_and_set_cursor (w, 1, output_cursor.hpos, |
1227 output_cursor.vpos, | 1144 output_cursor.vpos, |
1228 output_cursor.x, output_cursor.y); | 1145 output_cursor.x, output_cursor.y); |
1229 | 1146 |
1230 x_draw_vertical_border (w); | 1147 x_draw_vertical_border (w); |
1231 UNBLOCK_INPUT; | 1148 UNBLOCK_INPUT; |
1232 } | 1149 } |
1233 | 1150 |
1443 | 1360 |
1444 static void | 1361 static void |
1445 XTreset_terminal_modes () | 1362 XTreset_terminal_modes () |
1446 { | 1363 { |
1447 } | 1364 } |
1448 | |
1449 | |
1450 | |
1451 /*********************************************************************** | |
1452 Output Cursor | |
1453 ***********************************************************************/ | |
1454 | |
1455 /* Set the global variable output_cursor to CURSOR. All cursor | |
1456 positions are relative to updated_window. */ | |
1457 | |
1458 static void | |
1459 set_output_cursor (cursor) | |
1460 struct cursor_pos *cursor; | |
1461 { | |
1462 output_cursor.hpos = cursor->hpos; | |
1463 output_cursor.vpos = cursor->vpos; | |
1464 output_cursor.x = cursor->x; | |
1465 output_cursor.y = cursor->y; | |
1466 } | |
1467 | |
1468 | |
1469 /* Set a nominal cursor position. | |
1470 | |
1471 HPOS and VPOS are column/row positions in a window glyph matrix. X | |
1472 and Y are window text area relative pixel positions. | |
1473 | |
1474 If this is done during an update, updated_window will contain the | |
1475 window that is being updated and the position is the future output | |
1476 cursor position for that window. If updated_window is null, use | |
1477 selected_window and display the cursor at the given position. */ | |
1478 | |
1479 static void | |
1480 XTcursor_to (vpos, hpos, y, x) | |
1481 int vpos, hpos, y, x; | |
1482 { | |
1483 struct window *w; | |
1484 | |
1485 /* If updated_window is not set, work on selected_window. */ | |
1486 if (updated_window) | |
1487 w = updated_window; | |
1488 else | |
1489 w = XWINDOW (selected_window); | |
1490 | |
1491 /* Set the output cursor. */ | |
1492 output_cursor.hpos = hpos; | |
1493 output_cursor.vpos = vpos; | |
1494 output_cursor.x = x; | |
1495 output_cursor.y = y; | |
1496 | |
1497 /* If not called as part of an update, really display the cursor. | |
1498 This will also set the cursor position of W. */ | |
1499 if (updated_window == NULL) | |
1500 { | |
1501 BLOCK_INPUT; | |
1502 x_display_cursor (w, 1, hpos, vpos, x, y); | |
1503 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ())); | |
1504 UNBLOCK_INPUT; | |
1505 } | |
1506 } | |
1507 | |
1508 | 1365 |
1509 | 1366 |
1510 /*********************************************************************** | 1367 /*********************************************************************** |
1511 Display Iterator | 1368 Display Iterator |
1512 ***********************************************************************/ | 1369 ***********************************************************************/ |
1682 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0; | 1539 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0; |
1683 | 1540 |
1684 return FONT_TYPE_UNKNOWN; | 1541 return FONT_TYPE_UNKNOWN; |
1685 } | 1542 } |
1686 | 1543 |
1687 | |
1688 /* Estimate the pixel height of the mode or top line on frame F. | |
1689 FACE_ID specifies what line's height to estimate. */ | |
1690 | |
1691 int | |
1692 x_estimate_mode_line_height (f, face_id) | |
1693 struct frame *f; | |
1694 enum face_id face_id; | |
1695 { | |
1696 int height = FONT_HEIGHT (FRAME_FONT (f)); | |
1697 | |
1698 /* This function is called so early when Emacs starts that the face | |
1699 cache and mode line face are not yet initialized. */ | |
1700 if (FRAME_FACE_CACHE (f)) | |
1701 { | |
1702 struct face *face = FACE_FROM_ID (f, face_id); | |
1703 if (face) | |
1704 { | |
1705 if (face->font) | |
1706 height = FONT_HEIGHT (face->font); | |
1707 if (face->box_line_width > 0) | |
1708 height += 2 * face->box_line_width; | |
1709 } | |
1710 } | |
1711 | |
1712 return height; | |
1713 } | |
1714 | 1544 |
1715 | 1545 |
1716 /*********************************************************************** | 1546 /*********************************************************************** |
1717 Glyph display | 1547 Glyph display |
1718 ***********************************************************************/ | 1548 ***********************************************************************/ |
1742 int, int, int)); | 1572 int, int, int)); |
1743 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int, | 1573 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int, |
1744 int, int, int, int, Rect *)); | 1574 int, int, int, int, Rect *)); |
1745 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int, | 1575 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int, |
1746 int, int, int, Rect *)); | 1576 int, int, int, Rect *)); |
1747 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *, | |
1748 enum glyph_row_area)); | |
1749 | 1577 |
1750 #if GLYPH_DEBUG | 1578 #if GLYPH_DEBUG |
1751 static void x_check_font P_ ((struct frame *, XFontStruct *)); | 1579 static void x_check_font P_ ((struct frame *, XFontStruct *)); |
1752 #endif | 1580 #endif |
1753 | 1581 |
1914 /* GC must have been set. */ | 1742 /* GC must have been set. */ |
1915 xassert (s->gc != 0); | 1743 xassert (s->gc != 0); |
1916 } | 1744 } |
1917 | 1745 |
1918 | 1746 |
1919 /* Return in *R the clipping rectangle for glyph string S. */ | |
1920 | |
1921 static void | |
1922 x_get_glyph_string_clip_rect (s, r) | |
1923 struct glyph_string *s; | |
1924 Rect *r; | |
1925 { | |
1926 int r_height, r_width; | |
1927 | |
1928 if (s->row->full_width_p) | |
1929 { | |
1930 /* Draw full-width. X coordinates are relative to S->w->left. */ | |
1931 int canon_x = CANON_X_UNIT (s->f); | |
1932 | |
1933 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x; | |
1934 r_width = XFASTINT (s->w->width) * canon_x; | |
1935 | |
1936 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f)) | |
1937 { | |
1938 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x; | |
1939 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f)) | |
1940 r->left -= width; | |
1941 } | |
1942 | |
1943 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f); | |
1944 | |
1945 /* Unless displaying a mode or menu bar line, which are always | |
1946 fully visible, clip to the visible part of the row. */ | |
1947 if (s->w->pseudo_window_p) | |
1948 r_height = s->row->visible_height; | |
1949 else | |
1950 r_height = s->height; | |
1951 } | |
1952 else | |
1953 { | |
1954 /* This is a text line that may be partially visible. */ | |
1955 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0); | |
1956 r_width = window_box_width (s->w, s->area); | |
1957 r_height = s->row->visible_height; | |
1958 } | |
1959 | |
1960 /* If S draws overlapping rows, it's sufficient to use the top and | |
1961 bottom of the window for clipping because this glyph string | |
1962 intentionally draws over other lines. */ | |
1963 if (s->for_overlaps_p) | |
1964 { | |
1965 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w); | |
1966 r_height = window_text_bottom_y (s->w) - r->top; | |
1967 } | |
1968 else | |
1969 { | |
1970 /* Don't use S->y for clipping because it doesn't take partially | |
1971 visible lines into account. For example, it can be negative for | |
1972 partially visible lines at the top of a window. */ | |
1973 if (!s->row->full_width_p | |
1974 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row)) | |
1975 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w); | |
1976 else | |
1977 r->top = max (0, s->row->y); | |
1978 | |
1979 /* If drawing a tool-bar window, draw it over the internal border | |
1980 at the top of the window. */ | |
1981 if (s->w == XWINDOW (s->f->tool_bar_window)) | |
1982 r->top -= s->f->output_data.mac->internal_border_width; | |
1983 } | |
1984 | |
1985 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top); | |
1986 | |
1987 r->bottom = r->top + r_height; | |
1988 r->right = r->left + r_width; | |
1989 } | |
1990 | |
1991 | |
1992 /* Set clipping for output of glyph string S. S may be part of a mode | 1747 /* Set clipping for output of glyph string S. S may be part of a mode |
1993 line or menu if we don't have X toolkit support. */ | 1748 line or menu if we don't have X toolkit support. */ |
1994 | 1749 |
1995 static INLINE void | 1750 static INLINE void |
1996 x_set_glyph_string_clipping (s) | 1751 x_set_glyph_string_clipping (s) |
1997 struct glyph_string *s; | 1752 struct glyph_string *s; |
1998 { | 1753 { |
1999 Rect r; | 1754 Rect r; |
2000 x_get_glyph_string_clip_rect (s, &r); | 1755 get_glyph_string_clip_rect (s, &r); |
2001 mac_set_clip_rectangle (s->display, s->window, &r); | 1756 mac_set_clip_rectangle (s->display, s->window, &r); |
2002 } | 1757 } |
2003 | 1758 |
2004 | 1759 |
2005 /* RIF: | 1760 /* RIF: |
2622 right_p = (last_glyph->right_box_line_p | 2377 right_p = (last_glyph->right_box_line_p |
2623 || (s->hl == DRAW_MOUSE_FACE | 2378 || (s->hl == DRAW_MOUSE_FACE |
2624 && (s->next == NULL | 2379 && (s->next == NULL |
2625 || s->next->hl != s->hl))); | 2380 || s->next->hl != s->hl))); |
2626 | 2381 |
2627 x_get_glyph_string_clip_rect (s, &clip_rect); | 2382 get_glyph_string_clip_rect (s, &clip_rect); |
2628 | 2383 |
2629 if (s->face->box == FACE_SIMPLE_BOX) | 2384 if (s->face->box == FACE_SIMPLE_BOX) |
2630 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width, | 2385 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width, |
2631 left_p, right_p, &clip_rect); | 2386 left_p, right_p, &clip_rect); |
2632 else | 2387 else |
2679 xgcv.clip_x_origin = x; | 2434 xgcv.clip_x_origin = x; |
2680 xgcv.clip_y_origin = y; | 2435 xgcv.clip_y_origin = y; |
2681 xgcv.function = GXcopy; | 2436 xgcv.function = GXcopy; |
2682 XChangeGC (s->display, s->gc, mask, &xgcv); | 2437 XChangeGC (s->display, s->gc, mask, &xgcv); |
2683 | 2438 |
2684 x_get_glyph_string_clip_rect (s, &clip_rect); | 2439 get_glyph_string_clip_rect (s, &clip_rect); |
2685 image_rect.x = x; | 2440 image_rect.x = x; |
2686 image_rect.y = y; | 2441 image_rect.y = y; |
2687 image_rect.width = s->img->width; | 2442 image_rect.width = s->img->width; |
2688 image_rect.height = s->img->height; | 2443 image_rect.height = s->img->height; |
2689 if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) | 2444 if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) |
2759 y0 = y - thick; | 2514 y0 = y - thick; |
2760 x1 = x + s->img->width + thick - 1; | 2515 x1 = x + s->img->width + thick - 1; |
2761 y1 = y + s->img->height + thick - 1; | 2516 y1 = y + s->img->height + thick - 1; |
2762 | 2517 |
2763 x_setup_relief_colors (s); | 2518 x_setup_relief_colors (s); |
2764 x_get_glyph_string_clip_rect (s, &r); | 2519 get_glyph_string_clip_rect (s, &r); |
2765 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r); | 2520 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r); |
2766 } | 2521 } |
2767 | 2522 |
2768 | 2523 |
2769 /* Draw the foreground of image glyph string S to PIXMAP. */ | 2524 /* Draw the foreground of image glyph string S to PIXMAP. */ |
3008 gc = s->gc; | 2763 gc = s->gc; |
3009 } | 2764 } |
3010 else | 2765 else |
3011 gc = s->face->gc; | 2766 gc = s->face->gc; |
3012 | 2767 |
3013 x_get_glyph_string_clip_rect (s, &r); | 2768 get_glyph_string_clip_rect (s, &r); |
3014 mac_set_clip_rectangle (s->display, s->window, &r); | 2769 mac_set_clip_rectangle (s->display, s->window, &r); |
3015 | 2770 |
3016 #if 0 /* MAC_TODO: stipple */ | 2771 #if 0 /* MAC_TODO: stipple */ |
3017 if (s->face->stipple) | 2772 if (s->face->stipple) |
3018 { | 2773 { |
3180 | 2935 |
3181 /* Reset clipping. */ | 2936 /* Reset clipping. */ |
3182 mac_reset_clipping (s->display, s->window); | 2937 mac_reset_clipping (s->display, s->window); |
3183 } | 2938 } |
3184 | 2939 |
3185 | 2940 /* Shift display to make room for inserted glyphs. */ |
3186 /* Fix the display of area AREA of overlapping row ROW in window W. */ | 2941 |
3187 | 2942 void |
3188 static void | 2943 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by) |
3189 x_fix_overlapping_area (w, row, area) | 2944 struct frame *f; |
3190 struct window *w; | 2945 int x, y, width, height, shift_by; |
3191 struct glyph_row *row; | 2946 { |
3192 enum glyph_row_area area; | |
3193 { | |
3194 int i, x; | |
3195 | |
3196 BLOCK_INPUT; | |
3197 | |
3198 if (area == LEFT_MARGIN_AREA) | |
3199 x = 0; | |
3200 else if (area == TEXT_AREA) | |
3201 x = row->x + window_box_width (w, LEFT_MARGIN_AREA); | |
3202 else | |
3203 x = (window_box_width (w, LEFT_MARGIN_AREA) | |
3204 + window_box_width (w, TEXT_AREA)); | |
3205 | |
3206 for (i = 0; i < row->used[area];) | |
3207 { | |
3208 if (row->glyphs[area][i].overlaps_vertically_p) | |
3209 { | |
3210 int start = i, start_x = x; | |
3211 | |
3212 do | |
3213 { | |
3214 x += row->glyphs[area][i].pixel_width; | |
3215 ++i; | |
3216 } | |
3217 while (i < row->used[area] | |
3218 && row->glyphs[area][i].overlaps_vertically_p); | |
3219 | |
3220 x_draw_glyphs (w, start_x, row, area, start, i, | |
3221 DRAW_NORMAL_TEXT, 1); | |
3222 } | |
3223 else | |
3224 { | |
3225 x += row->glyphs[area][i].pixel_width; | |
3226 ++i; | |
3227 } | |
3228 } | |
3229 | |
3230 UNBLOCK_INPUT; | |
3231 } | |
3232 | |
3233 | |
3234 /* Output LEN glyphs starting at START at the nominal cursor position. | |
3235 Advance the nominal cursor over the text. The global variable | |
3236 updated_window contains the window being updated, updated_row is | |
3237 the glyph row being updated, and updated_area is the area of that | |
3238 row being updated. */ | |
3239 | |
3240 static void | |
3241 x_write_glyphs (start, len) | |
3242 struct glyph *start; | |
3243 int len; | |
3244 { | |
3245 int x, hpos; | |
3246 | |
3247 xassert (updated_window && updated_row); | |
3248 BLOCK_INPUT; | |
3249 | |
3250 /* Write glyphs. */ | |
3251 | |
3252 hpos = start - updated_row->glyphs[updated_area]; | |
3253 x = x_draw_glyphs (updated_window, output_cursor.x, | |
3254 updated_row, updated_area, | |
3255 hpos, hpos + len, | |
3256 DRAW_NORMAL_TEXT, 0); | |
3257 | |
3258 UNBLOCK_INPUT; | |
3259 | |
3260 /* Advance the output cursor. */ | |
3261 output_cursor.hpos += len; | |
3262 output_cursor.x = x; | |
3263 } | |
3264 | |
3265 | |
3266 /* Insert LEN glyphs from START at the nominal cursor position. */ | |
3267 | |
3268 static void | |
3269 x_insert_glyphs (start, len) | |
3270 struct glyph *start; | |
3271 register int len; | |
3272 { | |
3273 struct frame *f; | |
3274 struct window *w; | |
3275 int line_height, shift_by_width, shifted_region_width; | |
3276 struct glyph_row *row; | |
3277 struct glyph *glyph; | |
3278 int frame_x, frame_y, hpos; | |
3279 | |
3280 xassert (updated_window && updated_row); | |
3281 BLOCK_INPUT; | |
3282 w = updated_window; | |
3283 f = XFRAME (WINDOW_FRAME (w)); | |
3284 | |
3285 /* Get the height of the line we are in. */ | |
3286 row = updated_row; | |
3287 line_height = row->height; | |
3288 | |
3289 /* Get the width of the glyphs to insert. */ | |
3290 shift_by_width = 0; | |
3291 for (glyph = start; glyph < start + len; ++glyph) | |
3292 shift_by_width += glyph->pixel_width; | |
3293 | |
3294 /* Get the width of the region to shift right. */ | |
3295 shifted_region_width = (window_box_width (w, updated_area) | |
3296 - output_cursor.x | |
3297 - shift_by_width); | |
3298 | |
3299 /* Shift right. */ | |
3300 frame_x = window_box_left (w, updated_area) + output_cursor.x; | |
3301 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y); | |
3302 | |
3303 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), | 2947 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), |
3304 f->output_data.mac->normal_gc, | 2948 f->output_data.mac->normal_gc, |
3305 frame_x, frame_y, | 2949 x, y, width, height, |
3306 shifted_region_width, line_height, | 2950 x + shift_by, y); |
3307 frame_x + shift_by_width, frame_y); | |
3308 | |
3309 /* Write the glyphs. */ | |
3310 hpos = start - row->glyphs[updated_area]; | |
3311 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len, | |
3312 DRAW_NORMAL_TEXT, 0); | |
3313 | |
3314 /* Advance the output cursor. */ | |
3315 output_cursor.hpos += len; | |
3316 output_cursor.x += shift_by_width; | |
3317 UNBLOCK_INPUT; | |
3318 } | 2951 } |
3319 | 2952 |
3320 | 2953 |
3321 /* Delete N glyphs at the nominal cursor position. Not implemented | 2954 /* Delete N glyphs at the nominal cursor position. Not implemented |
3322 for X frames. */ | 2955 for X frames. */ |
3324 static void | 2957 static void |
3325 x_delete_glyphs (n) | 2958 x_delete_glyphs (n) |
3326 register int n; | 2959 register int n; |
3327 { | 2960 { |
3328 abort (); | 2961 abort (); |
3329 } | |
3330 | |
3331 | |
3332 /* Erase the current text line from the nominal cursor position | |
3333 (inclusive) to pixel column TO_X (exclusive). The idea is that | |
3334 everything from TO_X onward is already erased. | |
3335 | |
3336 TO_X is a pixel position relative to updated_area of | |
3337 updated_window. TO_X == -1 means clear to the end of this area. */ | |
3338 | |
3339 static void | |
3340 x_clear_end_of_line (to_x) | |
3341 int to_x; | |
3342 { | |
3343 struct frame *f; | |
3344 struct window *w = updated_window; | |
3345 int max_x, min_y, max_y; | |
3346 int from_x, from_y, to_y; | |
3347 | |
3348 xassert (updated_window && updated_row); | |
3349 f = XFRAME (w->frame); | |
3350 | |
3351 if (updated_row->full_width_p) | |
3352 { | |
3353 max_x = XFASTINT (w->width) * CANON_X_UNIT (f); | |
3354 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) | |
3355 && !w->pseudo_window_p) | |
3356 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f); | |
3357 } | |
3358 else | |
3359 max_x = window_box_width (w, updated_area); | |
3360 max_y = window_text_bottom_y (w); | |
3361 | |
3362 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end | |
3363 of window. For TO_X > 0, truncate to end of drawing area. */ | |
3364 if (to_x == 0) | |
3365 return; | |
3366 else if (to_x < 0) | |
3367 to_x = max_x; | |
3368 else | |
3369 to_x = min (to_x, max_x); | |
3370 | |
3371 to_y = min (max_y, output_cursor.y + updated_row->height); | |
3372 | |
3373 /* Notice if the cursor will be cleared by this operation. */ | |
3374 if (!updated_row->full_width_p) | |
3375 notice_overwritten_cursor (w, updated_area, | |
3376 output_cursor.x, -1, | |
3377 updated_row->y, | |
3378 MATRIX_ROW_BOTTOM_Y (updated_row)); | |
3379 | |
3380 from_x = output_cursor.x; | |
3381 | |
3382 /* Translate to frame coordinates. */ | |
3383 if (updated_row->full_width_p) | |
3384 { | |
3385 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x); | |
3386 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x); | |
3387 } | |
3388 else | |
3389 { | |
3390 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x); | |
3391 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x); | |
3392 } | |
3393 | |
3394 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w); | |
3395 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y)); | |
3396 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y); | |
3397 | |
3398 /* Prevent inadvertently clearing to end of the X window. */ | |
3399 if (to_x > from_x && to_y > from_y) | |
3400 { | |
3401 BLOCK_INPUT; | |
3402 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), | |
3403 from_x, from_y, to_x - from_x, to_y - from_y, | |
3404 0); | |
3405 UNBLOCK_INPUT; | |
3406 } | |
3407 } | 2962 } |
3408 | 2963 |
3409 | 2964 |
3410 /* Clear entire frame. If updating_frame is non-null, clear that | 2965 /* Clear entire frame. If updating_frame is non-null, clear that |
3411 frame. Otherwise clear the selected frame. */ | 2966 frame. Otherwise clear the selected frame. */ |
3635 | 3190 |
3636 | 3191 |
3637 /*********************************************************************** | 3192 /*********************************************************************** |
3638 Exposure Events | 3193 Exposure Events |
3639 ***********************************************************************/ | 3194 ***********************************************************************/ |
3640 | |
3641 /* Redisplay an exposed area of frame F. X and Y are the upper-left | |
3642 corner of the exposed rectangle. W and H are width and height of | |
3643 the exposed area. All are pixel values. W or H zero means redraw | |
3644 the entire frame. */ | |
3645 | |
3646 static void | |
3647 expose_frame (f, x, y, w, h) | |
3648 struct frame *f; | |
3649 int x, y, w, h; | |
3650 { | |
3651 Rect r; | |
3652 int mouse_face_overwritten_p = 0; | |
3653 | |
3654 TRACE ((stderr, "expose_frame ")); | |
3655 | |
3656 /* No need to redraw if frame will be redrawn soon. */ | |
3657 if (FRAME_GARBAGED_P (f)) | |
3658 { | |
3659 TRACE ((stderr, " garbaged\n")); | |
3660 return; | |
3661 } | |
3662 | |
3663 /* MAC_TODO: this is a kludge, but if scroll bars are not activated | |
3664 or deactivated here, for unknown reasons, activated scroll bars | |
3665 are shown in deactivated frames in some instances. */ | |
3666 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame) | |
3667 activate_scroll_bars (f); | |
3668 else | |
3669 deactivate_scroll_bars (f); | |
3670 | |
3671 /* If basic faces haven't been realized yet, there is no point in | |
3672 trying to redraw anything. This can happen when we get an expose | |
3673 event while Emacs is starting, e.g. by moving another window. */ | |
3674 if (FRAME_FACE_CACHE (f) == NULL | |
3675 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL) | |
3676 { | |
3677 TRACE ((stderr, " no faces\n")); | |
3678 return; | |
3679 } | |
3680 | |
3681 if (w == 0 || h == 0) | |
3682 { | |
3683 r.left = r.top = 0; | |
3684 r.right = CANON_X_UNIT (f) * f->width; | |
3685 r.bottom = CANON_Y_UNIT (f) * f->height; | |
3686 } | |
3687 else | |
3688 { | |
3689 r.left = x; | |
3690 r.top = y; | |
3691 r.right = x + w; | |
3692 r.bottom = y + h; | |
3693 } | |
3694 | |
3695 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom)); | |
3696 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r); | |
3697 | |
3698 if (WINDOWP (f->tool_bar_window)) | |
3699 mouse_face_overwritten_p | |
3700 |= expose_window (XWINDOW (f->tool_bar_window), &r); | |
3701 | |
3702 /* Some window managers support a focus-follows-mouse style with | |
3703 delayed raising of frames. Imagine a partially obscured frame, | |
3704 and moving the mouse into partially obscured mouse-face on that | |
3705 frame. The visible part of the mouse-face will be highlighted, | |
3706 then the WM raises the obscured frame. With at least one WM, KDE | |
3707 2.1, Emacs is not getting any event for the raising of the frame | |
3708 (even tried with SubstructureRedirectMask), only Expose events. | |
3709 These expose events will draw text normally, i.e. not | |
3710 highlighted. Which means we must redo the highlight here. | |
3711 Subsume it under ``we love X''. --gerd 2001-08-15 */ | |
3712 /* Included in Windows version because Windows most likely does not | |
3713 do the right thing if any third party tool offers | |
3714 focus-follows-mouse with delayed raise. --jason 2001-10-12 */ | |
3715 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f)) | |
3716 { | |
3717 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); | |
3718 if (f == dpyinfo->mouse_face_mouse_frame) | |
3719 { | |
3720 int x = dpyinfo->mouse_face_mouse_x; | |
3721 int y = dpyinfo->mouse_face_mouse_y; | |
3722 clear_mouse_face (dpyinfo); | |
3723 note_mouse_highlight (f, x, y); | |
3724 } | |
3725 } | |
3726 } | |
3727 | |
3728 | |
3729 /* Redraw (parts) of all windows in the window tree rooted at W that | |
3730 intersect R. R contains frame pixel coordinates. */ | |
3731 | |
3732 static int | |
3733 expose_window_tree (w, r) | |
3734 struct window *w; | |
3735 Rect *r; | |
3736 { | |
3737 struct frame *f = XFRAME (w->frame); | |
3738 int mouse_face_overwritten_p = 0; | |
3739 | |
3740 while (w && !FRAME_GARBAGED_P (f)) | |
3741 { | |
3742 if (!NILP (w->hchild)) | |
3743 mouse_face_overwritten_p | |
3744 |= expose_window_tree (XWINDOW (w->hchild), r); | |
3745 else if (!NILP (w->vchild)) | |
3746 mouse_face_overwritten_p | |
3747 |= expose_window_tree (XWINDOW (w->vchild), r); | |
3748 else | |
3749 mouse_face_overwritten_p |= expose_window (w, r); | |
3750 | |
3751 w = NILP (w->next) ? NULL : XWINDOW (w->next); | |
3752 } | |
3753 | |
3754 return mouse_face_overwritten_p; | |
3755 } | |
3756 | |
3757 | |
3758 /* Redraw the part of glyph row area AREA of glyph row ROW on window W | |
3759 which intersects rectangle R. R is in window-relative coordinates. */ | |
3760 | |
3761 static void | |
3762 expose_area (w, row, r, area) | |
3763 struct window *w; | |
3764 struct glyph_row *row; | |
3765 Rect *r; | |
3766 enum glyph_row_area area; | |
3767 { | |
3768 struct glyph *first = row->glyphs[area]; | |
3769 struct glyph *end = row->glyphs[area] + row->used[area]; | |
3770 struct glyph *last; | |
3771 int first_x, start_x, x; | |
3772 | |
3773 if (area == TEXT_AREA && row->fill_line_p) | |
3774 /* If row extends face to end of line write the whole line. */ | |
3775 x_draw_glyphs (w, 0, row, area, | |
3776 0, row->used[area], | |
3777 DRAW_NORMAL_TEXT, 0); | |
3778 else | |
3779 { | |
3780 /* Set START_X to the window-relative start position for drawing glyphs of | |
3781 AREA. The first glyph of the text area can be partially visible. | |
3782 The first glyphs of other areas cannot. */ | |
3783 if (area == LEFT_MARGIN_AREA) | |
3784 start_x = 0; | |
3785 else if (area == TEXT_AREA) | |
3786 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA); | |
3787 else | |
3788 start_x = (window_box_width (w, LEFT_MARGIN_AREA) | |
3789 + window_box_width (w, TEXT_AREA)); | |
3790 x = start_x; | |
3791 | |
3792 /* Find the first glyph that must be redrawn. */ | |
3793 while (first < end | |
3794 && x + first->pixel_width < r->left) | |
3795 { | |
3796 x += first->pixel_width; | |
3797 ++first; | |
3798 } | |
3799 | |
3800 /* Find the last one. */ | |
3801 last = first; | |
3802 first_x = x; | |
3803 while (last < end | |
3804 && x < r->right) | |
3805 { | |
3806 x += last->pixel_width; | |
3807 ++last; | |
3808 } | |
3809 | |
3810 /* Repaint. */ | |
3811 if (last > first) | |
3812 x_draw_glyphs (w, first_x - start_x, row, area, | |
3813 first - row->glyphs[area], | |
3814 last - row->glyphs[area], | |
3815 DRAW_NORMAL_TEXT, 0); | |
3816 } | |
3817 } | |
3818 | |
3819 | |
3820 /* Redraw the parts of the glyph row ROW on window W intersecting | |
3821 rectangle R. R is in window-relative coordinates. Value is | |
3822 non-zero if mouse face was overwritten. */ | |
3823 | |
3824 static int | |
3825 expose_line (w, row, r) | |
3826 struct window *w; | |
3827 struct glyph_row *row; | |
3828 Rect *r; | |
3829 { | |
3830 xassert (row->enabled_p); | |
3831 | |
3832 if (row->mode_line_p || w->pseudo_window_p) | |
3833 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA], | |
3834 DRAW_NORMAL_TEXT, 0); | |
3835 else | |
3836 { | |
3837 if (row->used[LEFT_MARGIN_AREA]) | |
3838 expose_area (w, row, r, LEFT_MARGIN_AREA); | |
3839 if (row->used[TEXT_AREA]) | |
3840 expose_area (w, row, r, TEXT_AREA); | |
3841 if (row->used[RIGHT_MARGIN_AREA]) | |
3842 expose_area (w, row, r, RIGHT_MARGIN_AREA); | |
3843 draw_row_fringe_bitmaps (w, row); | |
3844 } | |
3845 | |
3846 return row->mouse_face_p; | |
3847 } | |
3848 | |
3849 | |
3850 /* Return non-zero if W's cursor intersects rectangle R. */ | |
3851 | |
3852 static int | |
3853 x_phys_cursor_in_rect_p (w, r) | |
3854 struct window *w; | |
3855 Rect *r; | |
3856 { | |
3857 Rect cr, result; | |
3858 struct glyph *cursor_glyph; | |
3859 | |
3860 cursor_glyph = get_phys_cursor_glyph (w); | |
3861 if (cursor_glyph) | |
3862 { | |
3863 cr.left = w->phys_cursor.x; | |
3864 cr.top = w->phys_cursor.y; | |
3865 cr.right = cr.left + cursor_glyph->pixel_width; | |
3866 cr.bottom = cr.top + w->phys_cursor_height; | |
3867 return x_intersect_rectangles (&cr, r, &result); | |
3868 } | |
3869 else | |
3870 return 0; | |
3871 } | |
3872 | |
3873 | |
3874 /* Redraw those parts of glyphs rows during expose event handling that | |
3875 overlap other rows. Redrawing of an exposed line writes over parts | |
3876 of lines overlapping that exposed line; this function fixes that. | |
3877 | |
3878 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first | |
3879 row in W's current matrix that is exposed and overlaps other rows. | |
3880 LAST_OVERLAPPING_ROW is the last such row. */ | |
3881 | |
3882 static void | |
3883 expose_overlaps (w, first_overlapping_row, last_overlapping_row) | |
3884 struct window *w; | |
3885 struct glyph_row *first_overlapping_row; | |
3886 struct glyph_row *last_overlapping_row; | |
3887 { | |
3888 struct glyph_row *row; | |
3889 | |
3890 for (row = first_overlapping_row; row <= last_overlapping_row; ++row) | |
3891 if (row->overlapping_p) | |
3892 { | |
3893 xassert (row->enabled_p && !row->mode_line_p); | |
3894 | |
3895 if (row->used[LEFT_MARGIN_AREA]) | |
3896 x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA); | |
3897 | |
3898 if (row->used[TEXT_AREA]) | |
3899 x_fix_overlapping_area (w, row, TEXT_AREA); | |
3900 | |
3901 if (row->used[RIGHT_MARGIN_AREA]) | |
3902 x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA); | |
3903 } | |
3904 } | |
3905 | |
3906 | |
3907 /* Redraw the part of window W intersection rectangle FR. Pixel | |
3908 coordinates in FR are frame-relative. Call this function with | |
3909 input blocked. Value is non-zero if the exposure overwrites | |
3910 mouse-face. */ | |
3911 | |
3912 static int | |
3913 expose_window (w, fr) | |
3914 struct window *w; | |
3915 Rect *fr; | |
3916 { | |
3917 struct frame *f = XFRAME (w->frame); | |
3918 Rect wr, r; | |
3919 int mouse_face_overwritten_p = 0; | |
3920 | |
3921 /* If window is not yet fully initialized, do nothing. This can | |
3922 happen when toolkit scroll bars are used and a window is split. | |
3923 Reconfiguring the scroll bar will generate an expose for a newly | |
3924 created window. */ | |
3925 if (w->current_matrix == NULL) | |
3926 return 0; | |
3927 | |
3928 /* When we're currently updating the window, display and current | |
3929 matrix usually don't agree. Arrange for a thorough display | |
3930 later. */ | |
3931 if (w == updated_window) | |
3932 { | |
3933 SET_FRAME_GARBAGED (f); | |
3934 return 0; | |
3935 } | |
3936 | |
3937 /* Frame-relative pixel rectangle of W. */ | |
3938 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f); | |
3939 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f); | |
3940 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f); | |
3941 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f); | |
3942 | |
3943 if (x_intersect_rectangles (fr, &wr, &r)) | |
3944 { | |
3945 int yb = window_text_bottom_y (w); | |
3946 struct glyph_row *row; | |
3947 int cursor_cleared_p; | |
3948 struct glyph_row *first_overlapping_row, *last_overlapping_row; | |
3949 | |
3950 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n", | |
3951 r.left, r.top, r.right, r.bottom)); | |
3952 | |
3953 /* Convert to window coordinates. */ | |
3954 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left); | |
3955 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right); | |
3956 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top); | |
3957 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom); | |
3958 | |
3959 /* Turn off the cursor. */ | |
3960 if (!w->pseudo_window_p | |
3961 && x_phys_cursor_in_rect_p (w, &r)) | |
3962 { | |
3963 x_clear_cursor (w); | |
3964 cursor_cleared_p = 1; | |
3965 } | |
3966 else | |
3967 cursor_cleared_p = 0; | |
3968 | |
3969 /* Update lines intersecting rectangle R. */ | |
3970 first_overlapping_row = last_overlapping_row = NULL; | |
3971 for (row = w->current_matrix->rows; | |
3972 row->enabled_p; | |
3973 ++row) | |
3974 { | |
3975 int y0 = row->y; | |
3976 int y1 = MATRIX_ROW_BOTTOM_Y (row); | |
3977 | |
3978 if ((y0 >= r.top && y0 < r.bottom) | |
3979 || (y1 > r.top && y1 < r.bottom) | |
3980 || (r.top >= y0 && r.top < y1) | |
3981 || (r.bottom > y0 && r.bottom < y1)) | |
3982 { | |
3983 if (row->overlapping_p) | |
3984 { | |
3985 if (first_overlapping_row == NULL) | |
3986 first_overlapping_row = row; | |
3987 last_overlapping_row = row; | |
3988 } | |
3989 | |
3990 if (expose_line (w, row, &r)) | |
3991 mouse_face_overwritten_p = 1; | |
3992 } | |
3993 | |
3994 if (y1 >= yb) | |
3995 break; | |
3996 } | |
3997 | |
3998 /* Display the mode line if there is one. */ | |
3999 if (WINDOW_WANTS_MODELINE_P (w) | |
4000 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix), | |
4001 row->enabled_p) | |
4002 && row->y < r.bottom) | |
4003 { | |
4004 if (expose_line (w, row, &r)) | |
4005 mouse_face_overwritten_p = 1; | |
4006 } | |
4007 | |
4008 if (!w->pseudo_window_p) | |
4009 { | |
4010 /* Fix the display of overlapping rows. */ | |
4011 if (first_overlapping_row) | |
4012 expose_overlaps (w, first_overlapping_row, last_overlapping_row); | |
4013 | |
4014 /* Draw border between windows. */ | |
4015 x_draw_vertical_border (w); | |
4016 | |
4017 /* Turn the cursor on again. */ | |
4018 if (cursor_cleared_p) | |
4019 x_update_window_cursor (w, 1); | |
4020 } | |
4021 } | |
4022 | |
4023 /* Display scroll bar for this window. */ | |
4024 if (!NILP (w->vertical_scroll_bar)) | |
4025 { | |
4026 ControlHandle ch | |
4027 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar)); | |
4028 | |
4029 Draw1Control (ch); | |
4030 } | |
4031 | |
4032 return mouse_face_overwritten_p; | |
4033 } | |
4034 | |
4035 static int | |
4036 x_intersect_rectangles (r1, r2, result) | |
4037 Rect *r1, *r2, *result; | |
4038 { | |
4039 Rect *left, *right; | |
4040 Rect *upper, *lower; | |
4041 int intersection_p = 0; | |
4042 | |
4043 /* Rerrange so that R1 is the left-most rectangle. */ | |
4044 if (r1->left < r2->left) | |
4045 left = r1, right = r2; | |
4046 else | |
4047 left = r2, right = r1; | |
4048 | |
4049 /* X0 of the intersection is right.x0, if this is inside R1, | |
4050 otherwise there is no intersection. */ | |
4051 if (right->left <= left->right) | |
4052 { | |
4053 result->left = right->left; | |
4054 | |
4055 /* The right end of the intersection is the minimum of the | |
4056 the right ends of left and right. */ | |
4057 result->right = min (left->right, right->right); | |
4058 | |
4059 /* Same game for Y. */ | |
4060 if (r1->top < r2->top) | |
4061 upper = r1, lower = r2; | |
4062 else | |
4063 upper = r2, lower = r1; | |
4064 | |
4065 /* The upper end of the intersection is lower.y0, if this is inside | |
4066 of upper. Otherwise, there is no intersection. */ | |
4067 if (lower->top <= upper->bottom) | |
4068 { | |
4069 result->top = lower->top; | |
4070 | |
4071 /* The lower end of the intersection is the minimum of the lower | |
4072 ends of upper and lower. */ | |
4073 result->bottom = min (lower->bottom, upper->bottom); | |
4074 intersection_p = 1; | |
4075 } | |
4076 } | |
4077 | |
4078 return intersection_p; | |
4079 } | |
4080 | |
4081 | |
4082 | |
4083 | 3195 |
4084 | 3196 |
4085 static void | 3197 static void |
4086 frame_highlight (f) | 3198 frame_highlight (f) |
4087 struct frame *f; | 3199 struct frame *f; |
4154 | 3266 |
4155 static void | 3267 static void |
4156 XTframe_rehighlight (frame) | 3268 XTframe_rehighlight (frame) |
4157 struct frame *frame; | 3269 struct frame *frame; |
4158 { | 3270 { |
3271 | |
3272 | |
4159 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame)); | 3273 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame)); |
4160 } | 3274 } |
4161 | 3275 |
4162 static void | 3276 static void |
4163 x_frame_rehighlight (dpyinfo) | 3277 x_frame_rehighlight (dpyinfo) |
4542 | 3656 |
4543 /************************************************************************ | 3657 /************************************************************************ |
4544 Mouse Face | 3658 Mouse Face |
4545 ************************************************************************/ | 3659 ************************************************************************/ |
4546 | 3660 |
4547 /* Find the glyph under window-relative coordinates X/Y in window W. | 3661 static struct scroll_bar *x_window_to_scroll_bar (); |
4548 Consider only glyphs from buffer text, i.e. no glyphs from overlay | 3662 static void x_scroll_bar_report_motion (); |
4549 strings. Return in *HPOS and *VPOS the row and column number of | 3663 static void x_check_fullscreen P_ ((struct frame *)); |
4550 the glyph found. Return in *AREA the glyph area containing X. | 3664 static void x_check_fullscreen_move P_ ((struct frame *)); |
4551 Value is a pointer to the glyph found or null if X/Y is not on | 3665 static int glyph_rect P_ ((struct frame *f, int, int, Rect *)); |
4552 text, or we can't tell because W's current matrix is not up to | 3666 |
4553 date. */ | 3667 |
4554 | 3668 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */ |
4555 static struct glyph * | |
4556 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p) | |
4557 struct window *w; | |
4558 int x, y; | |
4559 int *hpos, *vpos, *area; | |
4560 int buffer_only_p; | |
4561 { | |
4562 struct glyph *glyph, *end; | |
4563 struct glyph_row *row = NULL; | |
4564 int x0, i, left_area_width; | |
4565 | |
4566 /* Find row containing Y. Give up if some row is not enabled. */ | |
4567 for (i = 0; i < w->current_matrix->nrows; ++i) | |
4568 { | |
4569 row = MATRIX_ROW (w->current_matrix, i); | |
4570 if (!row->enabled_p) | |
4571 return NULL; | |
4572 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row)) | |
4573 break; | |
4574 } | |
4575 | |
4576 *vpos = i; | |
4577 *hpos = 0; | |
4578 | |
4579 /* Give up if Y is not in the window. */ | |
4580 if (i == w->current_matrix->nrows) | |
4581 return NULL; | |
4582 | |
4583 /* Get the glyph area containing X. */ | |
4584 if (w->pseudo_window_p) | |
4585 { | |
4586 *area = TEXT_AREA; | |
4587 x0 = 0; | |
4588 } | |
4589 else | |
4590 { | |
4591 left_area_width = window_box_width (w, LEFT_MARGIN_AREA); | |
4592 if (x < left_area_width) | |
4593 { | |
4594 *area = LEFT_MARGIN_AREA; | |
4595 x0 = 0; | |
4596 } | |
4597 else if (x < left_area_width + window_box_width (w, TEXT_AREA)) | |
4598 { | |
4599 *area = TEXT_AREA; | |
4600 x0 = row->x + left_area_width; | |
4601 } | |
4602 else | |
4603 { | |
4604 *area = RIGHT_MARGIN_AREA; | |
4605 x0 = left_area_width + window_box_width (w, TEXT_AREA); | |
4606 } | |
4607 } | |
4608 | |
4609 /* Find glyph containing X. */ | |
4610 glyph = row->glyphs[*area]; | |
4611 end = glyph + row->used[*area]; | |
4612 while (glyph < end) | |
4613 { | |
4614 if (x < x0 + glyph->pixel_width) | |
4615 { | |
4616 if (w->pseudo_window_p) | |
4617 break; | |
4618 else if (!buffer_only_p || BUFFERP (glyph->object)) | |
4619 break; | |
4620 } | |
4621 | |
4622 x0 += glyph->pixel_width; | |
4623 ++glyph; | |
4624 } | |
4625 | |
4626 if (glyph == end) | |
4627 return NULL; | |
4628 | |
4629 *hpos = glyph - row->glyphs[*area]; | |
4630 return glyph; | |
4631 } | |
4632 | |
4633 | |
4634 /* Convert frame-relative x/y to coordinates relative to window W. | |
4635 Takes pseudo-windows into account. */ | |
4636 | |
4637 static void | |
4638 frame_to_window_pixel_xy (w, x, y) | |
4639 struct window *w; | |
4640 int *x, *y; | |
4641 { | |
4642 if (w->pseudo_window_p) | |
4643 { | |
4644 /* A pseudo-window is always full-width, and starts at the | |
4645 left edge of the frame, plus a frame border. */ | |
4646 struct frame *f = XFRAME (w->frame); | |
4647 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f); | |
4648 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y); | |
4649 } | |
4650 else | |
4651 { | |
4652 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x); | |
4653 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y); | |
4654 } | |
4655 } | |
4656 | |
4657 | |
4658 /* Take proper action when mouse has moved to the mode or header line of | |
4659 window W, x-position X. MODE_LINE_P non-zero means mouse is on the | |
4660 mode line. X is relative to the start of the text display area of | |
4661 W, so the width of fringes and scroll bars must be subtracted | |
4662 to get a position relative to the start of the mode line. */ | |
4663 | |
4664 static void | |
4665 note_mode_line_highlight (w, x, mode_line_p) | |
4666 struct window *w; | |
4667 int x, mode_line_p; | |
4668 { | |
4669 struct frame *f = XFRAME (w->frame); | |
4670 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); | |
4671 struct Cursor *cursor = dpyinfo->vertical_scroll_bar_cursor; | |
4672 struct glyph_row *row; | |
4673 | |
4674 if (mode_line_p) | |
4675 row = MATRIX_MODE_LINE_ROW (w->current_matrix); | |
4676 else | |
4677 row = MATRIX_HEADER_LINE_ROW (w->current_matrix); | |
4678 | |
4679 if (row->enabled_p) | |
4680 { | |
4681 struct glyph *glyph, *end; | |
4682 Lisp_Object help, map; | |
4683 int x0; | |
4684 | |
4685 /* Find the glyph under X. */ | |
4686 glyph = row->glyphs[TEXT_AREA]; | |
4687 end = glyph + row->used[TEXT_AREA]; | |
4688 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f) | |
4689 + FRAME_X_LEFT_FRINGE_WIDTH (f)); | |
4690 | |
4691 while (glyph < end | |
4692 && x >= x0 + glyph->pixel_width) | |
4693 { | |
4694 x0 += glyph->pixel_width; | |
4695 ++glyph; | |
4696 } | |
4697 | |
4698 if (glyph < end | |
4699 && STRINGP (glyph->object) | |
4700 && STRING_INTERVALS (glyph->object) | |
4701 && glyph->charpos >= 0 | |
4702 && glyph->charpos < SCHARS (glyph->object)) | |
4703 { | |
4704 /* If we're on a string with `help-echo' text property, | |
4705 arrange for the help to be displayed. This is done by | |
4706 setting the global variable help_echo to the help string. */ | |
4707 help = Fget_text_property (make_number (glyph->charpos), | |
4708 Qhelp_echo, glyph->object); | |
4709 if (!NILP (help)) | |
4710 { | |
4711 help_echo = help; | |
4712 XSETWINDOW (help_echo_window, w); | |
4713 help_echo_object = glyph->object; | |
4714 help_echo_pos = glyph->charpos; | |
4715 } | |
4716 | |
4717 /* Change the mouse pointer according to what is under X/Y. */ | |
4718 map = Fget_text_property (make_number (glyph->charpos), | |
4719 Qlocal_map, glyph->object); | |
4720 if (KEYMAPP (map)) | |
4721 cursor = f->output_data.mac->nontext_cursor; | |
4722 else | |
4723 { | |
4724 map = Fget_text_property (make_number (glyph->charpos), | |
4725 Qkeymap, glyph->object); | |
4726 if (KEYMAPP (map)) | |
4727 cursor = f->output_data.mac->nontext_cursor; | |
4728 } | |
4729 } | |
4730 } | |
4731 | |
4732 #if 0 /* MAC_TODO: mouse cursor */ | |
4733 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor); | |
4734 #endif | |
4735 } | |
4736 | |
4737 | |
4738 /* Take proper action when the mouse has moved to position X, Y on | |
4739 frame F as regards highlighting characters that have mouse-face | |
4740 properties. Also de-highlighting chars where the mouse was before. | |
4741 X and Y can be negative or out of range. */ | |
4742 | |
4743 static void | |
4744 note_mouse_highlight (f, x, y) | |
4745 struct frame *f; | |
4746 int x, y; | |
4747 { | |
4748 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); | |
4749 int portion; | |
4750 Lisp_Object window; | |
4751 struct window *w; | |
4752 struct buffer *b; | |
4753 | |
4754 #if 0 | |
4755 /* When a menu is active, don't highlight because this looks odd. */ | |
4756 if (popup_activated ()) | |
4757 return; | |
4758 #endif | |
4759 | |
4760 if (NILP (Vmouse_highlight) | |
4761 || !f->glyphs_initialized_p) | |
4762 return; | |
4763 | |
4764 dpyinfo->mouse_face_mouse_x = x; | |
4765 dpyinfo->mouse_face_mouse_y = y; | |
4766 dpyinfo->mouse_face_mouse_frame = f; | |
4767 | |
4768 if (dpyinfo->mouse_face_defer) | |
4769 return; | |
4770 | |
4771 if (gc_in_progress) | |
4772 { | |
4773 dpyinfo->mouse_face_deferred_gc = 1; | |
4774 return; | |
4775 } | |
4776 | |
4777 /* Which window is that in? */ | |
4778 window = window_from_coordinates (f, x, y, &portion, 1); | |
4779 | |
4780 /* If we were displaying active text in another window, clear that. */ | |
4781 if (! EQ (window, dpyinfo->mouse_face_window)) | |
4782 clear_mouse_face (dpyinfo); | |
4783 | |
4784 /* Not on a window -> return. */ | |
4785 if (!WINDOWP (window)) | |
4786 return; | |
4787 | |
4788 /* Reset help_echo. It will get recomputed below. */ | |
4789 help_echo = Qnil; | |
4790 | |
4791 /* Convert to window-relative pixel coordinates. */ | |
4792 w = XWINDOW (window); | |
4793 frame_to_window_pixel_xy (w, &x, &y); | |
4794 | |
4795 /* Handle tool-bar window differently since it doesn't display a | |
4796 buffer. */ | |
4797 if (EQ (window, f->tool_bar_window)) | |
4798 { | |
4799 note_tool_bar_highlight (f, x, y); | |
4800 return; | |
4801 } | |
4802 | |
4803 /* Mouse is on the mode or header line? */ | |
4804 if (portion == 1 || portion == 3) | |
4805 { | |
4806 note_mode_line_highlight (w, x, portion == 1); | |
4807 return; | |
4808 } | |
4809 #if 0 /* TODO: mouse cursor */ | |
4810 if (portion == 2) | |
4811 cursor = f->output_data.x->horizontal_drag_cursor; | |
4812 else | |
4813 cursor = f->output_data.x->text_cursor; | |
4814 #endif | |
4815 /* Are we in a window whose display is up to date? | |
4816 And verify the buffer's text has not changed. */ | |
4817 b = XBUFFER (w->buffer); | |
4818 if (/* Within text portion of the window. */ | |
4819 portion == 0 | |
4820 && EQ (w->window_end_valid, w->buffer) | |
4821 && XFASTINT (w->last_modified) == BUF_MODIFF (b) | |
4822 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b)) | |
4823 { | |
4824 int hpos, vpos, pos, i, area; | |
4825 struct glyph *glyph; | |
4826 Lisp_Object object; | |
4827 Lisp_Object mouse_face = Qnil, overlay = Qnil, position; | |
4828 Lisp_Object *overlay_vec = NULL; | |
4829 int len, noverlays; | |
4830 struct buffer *obuf; | |
4831 int obegv, ozv, same_region; | |
4832 | |
4833 /* Find the glyph under X/Y. */ | |
4834 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0); | |
4835 | |
4836 /* Clear mouse face if X/Y not over text. */ | |
4837 if (glyph == NULL | |
4838 || area != TEXT_AREA | |
4839 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p) | |
4840 { | |
4841 clear_mouse_face (dpyinfo); | |
4842 /* TODO: mouse cursor */ | |
4843 goto set_cursor; | |
4844 } | |
4845 | |
4846 pos = glyph->charpos; | |
4847 object = glyph->object; | |
4848 if (!STRINGP (object) && !BUFFERP (object)) | |
4849 goto set_cursor; | |
4850 | |
4851 /* If we get an out-of-range value, return now; avoid an error. */ | |
4852 if (BUFFERP (object) && pos > BUF_Z (b)) | |
4853 goto set_cursor; | |
4854 | |
4855 /* Make the window's buffer temporarily current for | |
4856 overlays_at and compute_char_face. */ | |
4857 obuf = current_buffer; | |
4858 current_buffer = b; | |
4859 obegv = BEGV; | |
4860 ozv = ZV; | |
4861 BEGV = BEG; | |
4862 ZV = Z; | |
4863 | |
4864 /* Is this char mouse-active or does it have help-echo? */ | |
4865 position = make_number (pos); | |
4866 | |
4867 if (BUFFERP (object)) | |
4868 { | |
4869 /* Put all the overlays we want in a vector in overlay_vec. | |
4870 Store the length in len. If there are more than 10, make | |
4871 enough space for all, and try again. */ | |
4872 len = 10; | |
4873 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); | |
4874 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0); | |
4875 if (noverlays > len) | |
4876 { | |
4877 len = noverlays; | |
4878 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object)); | |
4879 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0); | |
4880 } | |
4881 | |
4882 /* Sort overlays into increasing priority order. */ | |
4883 noverlays = sort_overlays (overlay_vec, noverlays, w); | |
4884 } | |
4885 else | |
4886 noverlays = 0; | |
4887 | |
4888 same_region = (EQ (window, dpyinfo->mouse_face_window) | |
4889 && vpos >= dpyinfo->mouse_face_beg_row | |
4890 && vpos <= dpyinfo->mouse_face_end_row | |
4891 && (vpos > dpyinfo->mouse_face_beg_row | |
4892 || hpos >= dpyinfo->mouse_face_beg_col) | |
4893 && (vpos < dpyinfo->mouse_face_end_row | |
4894 || hpos < dpyinfo->mouse_face_end_col | |
4895 || dpyinfo->mouse_face_past_end)); | |
4896 | |
4897 /* TODO: if (same_region) | |
4898 mouse cursor */ | |
4899 | |
4900 /* Check mouse-face highlighting. */ | |
4901 if (! same_region | |
4902 /* If there exists an overlay with mouse-face overlapping | |
4903 the one we are currently highlighting, we have to | |
4904 check if we enter the overlapping overlay, and then | |
4905 highlight that. */ | |
4906 || (OVERLAYP (dpyinfo->mouse_face_overlay) | |
4907 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay))) | |
4908 { | |
4909 /* Find the highest priority overlay that has a mouse-face | |
4910 property. */ | |
4911 overlay = Qnil; | |
4912 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i) | |
4913 { | |
4914 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face); | |
4915 if (!NILP (mouse_face)) | |
4916 overlay = overlay_vec[i]; | |
4917 } | |
4918 | |
4919 /* If we're actually highlighting the same overlay as | |
4920 before, there's no need to do that again. */ | |
4921 if (!NILP (overlay) | |
4922 && EQ (overlay, dpyinfo->mouse_face_overlay)) | |
4923 goto check_help_echo; | |
4924 | |
4925 dpyinfo->mouse_face_overlay = overlay; | |
4926 | |
4927 /* Clear the display of the old active region, if any. */ | |
4928 clear_mouse_face (dpyinfo); | |
4929 /* TODO: mouse cursor changes. */ | |
4930 | |
4931 /* If no overlay applies, get a text property. */ | |
4932 if (NILP (overlay)) | |
4933 mouse_face = Fget_text_property (position, Qmouse_face, object); | |
4934 | |
4935 /* Handle the overlay case. */ | |
4936 if (!NILP (overlay)) | |
4937 { | |
4938 /* Find the range of text around this char that | |
4939 should be active. */ | |
4940 Lisp_Object before, after; | |
4941 int ignore; | |
4942 | |
4943 before = Foverlay_start (overlay); | |
4944 after = Foverlay_end (overlay); | |
4945 /* Record this as the current active region. */ | |
4946 fast_find_position (w, XFASTINT (before), | |
4947 &dpyinfo->mouse_face_beg_col, | |
4948 &dpyinfo->mouse_face_beg_row, | |
4949 &dpyinfo->mouse_face_beg_x, | |
4950 &dpyinfo->mouse_face_beg_y, Qnil); | |
4951 | |
4952 dpyinfo->mouse_face_past_end | |
4953 = !fast_find_position (w, XFASTINT (after), | |
4954 &dpyinfo->mouse_face_end_col, | |
4955 &dpyinfo->mouse_face_end_row, | |
4956 &dpyinfo->mouse_face_end_x, | |
4957 &dpyinfo->mouse_face_end_y, Qnil); | |
4958 dpyinfo->mouse_face_window = window; | |
4959 | |
4960 dpyinfo->mouse_face_face_id | |
4961 = face_at_buffer_position (w, pos, 0, 0, | |
4962 &ignore, pos + 1, | |
4963 !dpyinfo->mouse_face_hidden); | |
4964 | |
4965 /* Display it as active. */ | |
4966 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | |
4967 /* TODO: mouse cursor changes. */ | |
4968 } | |
4969 /* Handle the text property case. */ | |
4970 else if (! NILP (mouse_face) && BUFFERP (object)) | |
4971 { | |
4972 /* Find the range of text around this char that | |
4973 should be active. */ | |
4974 Lisp_Object before, after, beginning, end; | |
4975 int ignore; | |
4976 | |
4977 beginning = Fmarker_position (w->start); | |
4978 end = make_number (BUF_Z (XBUFFER (object)) | |
4979 - XFASTINT (w->window_end_pos)); | |
4980 before | |
4981 = Fprevious_single_property_change (make_number (pos + 1), | |
4982 Qmouse_face, | |
4983 object, beginning); | |
4984 after | |
4985 = Fnext_single_property_change (position, Qmouse_face, | |
4986 object, end); | |
4987 | |
4988 /* Record this as the current active region. */ | |
4989 fast_find_position (w, XFASTINT (before), | |
4990 &dpyinfo->mouse_face_beg_col, | |
4991 &dpyinfo->mouse_face_beg_row, | |
4992 &dpyinfo->mouse_face_beg_x, | |
4993 &dpyinfo->mouse_face_beg_y, Qnil); | |
4994 dpyinfo->mouse_face_past_end | |
4995 = !fast_find_position (w, XFASTINT (after), | |
4996 &dpyinfo->mouse_face_end_col, | |
4997 &dpyinfo->mouse_face_end_row, | |
4998 &dpyinfo->mouse_face_end_x, | |
4999 &dpyinfo->mouse_face_end_y, Qnil); | |
5000 dpyinfo->mouse_face_window = window; | |
5001 | |
5002 if (BUFFERP (object)) | |
5003 dpyinfo->mouse_face_face_id | |
5004 = face_at_buffer_position (w, pos, 0, 0, | |
5005 &ignore, pos + 1, | |
5006 !dpyinfo->mouse_face_hidden); | |
5007 | |
5008 /* Display it as active. */ | |
5009 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | |
5010 /* TODO: mouse cursor changes. */ | |
5011 } | |
5012 else if (!NILP (mouse_face) && STRINGP (object)) | |
5013 { | |
5014 Lisp_Object b, e; | |
5015 int ignore; | |
5016 | |
5017 b = Fprevious_single_property_change (make_number (pos + 1), | |
5018 Qmouse_face, | |
5019 object, Qnil); | |
5020 e = Fnext_single_property_change (position, Qmouse_face, | |
5021 object, Qnil); | |
5022 if (NILP (b)) | |
5023 b = make_number (0); | |
5024 if (NILP (e)) | |
5025 e = make_number (SCHARS (object) - 1); | |
5026 fast_find_string_pos (w, XINT (b), object, | |
5027 &dpyinfo->mouse_face_beg_col, | |
5028 &dpyinfo->mouse_face_beg_row, | |
5029 &dpyinfo->mouse_face_beg_x, | |
5030 &dpyinfo->mouse_face_beg_y, 0); | |
5031 fast_find_string_pos (w, XINT (e), object, | |
5032 &dpyinfo->mouse_face_end_col, | |
5033 &dpyinfo->mouse_face_end_row, | |
5034 &dpyinfo->mouse_face_end_x, | |
5035 &dpyinfo->mouse_face_end_y, 1); | |
5036 dpyinfo->mouse_face_past_end = 0; | |
5037 dpyinfo->mouse_face_window = window; | |
5038 dpyinfo->mouse_face_face_id | |
5039 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore, | |
5040 glyph->face_id, 1); | |
5041 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | |
5042 /* TODO: mouse cursor changes. */ | |
5043 } | |
5044 else if (STRINGP (object) && NILP (mouse_face)) | |
5045 { | |
5046 /* A string which doesn't have mouse-face, but | |
5047 the text ``under'' it might have. */ | |
5048 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos); | |
5049 int start = MATRIX_ROW_START_CHARPOS (r); | |
5050 | |
5051 pos = string_buffer_position (w, object, start); | |
5052 if (pos > 0) | |
5053 mouse_face = get_char_property_and_overlay (make_number (pos), | |
5054 Qmouse_face, | |
5055 w->buffer, | |
5056 &overlay); | |
5057 if (!NILP (mouse_face) && !NILP (overlay)) | |
5058 { | |
5059 Lisp_Object before = Foverlay_start (overlay); | |
5060 Lisp_Object after = Foverlay_end (overlay); | |
5061 int ignore; | |
5062 | |
5063 /* Note that we might not be able to find position | |
5064 BEFORE in the glyph matrix if the overlay is | |
5065 entirely covered by a `display' property. In | |
5066 this case, we overshoot. So let's stop in | |
5067 the glyph matrix before glyphs for OBJECT. */ | |
5068 fast_find_position (w, XFASTINT (before), | |
5069 &dpyinfo->mouse_face_beg_col, | |
5070 &dpyinfo->mouse_face_beg_row, | |
5071 &dpyinfo->mouse_face_beg_x, | |
5072 &dpyinfo->mouse_face_beg_y, | |
5073 object); | |
5074 | |
5075 dpyinfo->mouse_face_past_end | |
5076 = !fast_find_position (w, XFASTINT (after), | |
5077 &dpyinfo->mouse_face_end_col, | |
5078 &dpyinfo->mouse_face_end_row, | |
5079 &dpyinfo->mouse_face_end_x, | |
5080 &dpyinfo->mouse_face_end_y, | |
5081 Qnil); | |
5082 dpyinfo->mouse_face_window = window; | |
5083 dpyinfo->mouse_face_face_id | |
5084 = face_at_buffer_position (w, pos, 0, 0, | |
5085 &ignore, pos + 1, | |
5086 !dpyinfo->mouse_face_hidden); | |
5087 | |
5088 /* Display it as active. */ | |
5089 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE); | |
5090 /* TODO: mouse cursor changes. */ | |
5091 } | |
5092 } | |
5093 } | |
5094 | |
5095 check_help_echo: | |
5096 | |
5097 /* Look for a `help-echo' property. */ | |
5098 { | |
5099 Lisp_Object help, overlay; | |
5100 | |
5101 /* Check overlays first. */ | |
5102 help = overlay = Qnil; | |
5103 for (i = noverlays - 1; i >= 0 && NILP (help); --i) | |
5104 { | |
5105 overlay = overlay_vec[i]; | |
5106 help = Foverlay_get (overlay, Qhelp_echo); | |
5107 } | |
5108 | |
5109 if (!NILP (help)) | |
5110 { | |
5111 help_echo = help; | |
5112 help_echo_window = window; | |
5113 help_echo_object = overlay; | |
5114 help_echo_pos = pos; | |
5115 } | |
5116 else | |
5117 { | |
5118 Lisp_Object object = glyph->object; | |
5119 int charpos = glyph->charpos; | |
5120 | |
5121 /* Try text properties. */ | |
5122 if (STRINGP (object) | |
5123 && charpos >= 0 | |
5124 && charpos < SCHARS (object)) | |
5125 { | |
5126 help = Fget_text_property (make_number (charpos), | |
5127 Qhelp_echo, object); | |
5128 if (NILP (help)) | |
5129 { | |
5130 /* If the string itself doesn't specify a help-echo, | |
5131 see if the buffer text ``under'' it does. */ | |
5132 struct glyph_row *r | |
5133 = MATRIX_ROW (w->current_matrix, vpos); | |
5134 int start = MATRIX_ROW_START_CHARPOS (r); | |
5135 int pos = string_buffer_position (w, object, start); | |
5136 if (pos > 0) | |
5137 { | |
5138 help = Fget_char_property (make_number (pos), | |
5139 Qhelp_echo, w->buffer); | |
5140 if (!NILP (help)) | |
5141 { | |
5142 charpos = pos; | |
5143 object = w->buffer; | |
5144 } | |
5145 } | |
5146 } | |
5147 } | |
5148 else if (BUFFERP (object) | |
5149 && charpos >= BEGV | |
5150 && charpos < ZV) | |
5151 help = Fget_text_property (make_number (charpos), Qhelp_echo, | |
5152 object); | |
5153 | |
5154 if (!NILP (help)) | |
5155 { | |
5156 help_echo = help; | |
5157 help_echo_window = window; | |
5158 help_echo_object = object; | |
5159 help_echo_pos = charpos; | |
5160 } | |
5161 } | |
5162 } | |
5163 | |
5164 BEGV = obegv; | |
5165 ZV = ozv; | |
5166 current_buffer = obuf; | |
5167 } | |
5168 | |
5169 set_cursor: | |
5170 /* TODO: mouse cursor changes. */ | |
5171 ; | |
5172 } | |
5173 | 3669 |
5174 static void | 3670 static void |
5175 redo_mouse_highlight () | 3671 redo_mouse_highlight () |
5176 { | 3672 { |
5177 if (!NILP (last_mouse_motion_frame) | 3673 if (!NILP (last_mouse_motion_frame) |
5180 last_mouse_motion_position.h, | 3676 last_mouse_motion_position.h, |
5181 last_mouse_motion_position.v); | 3677 last_mouse_motion_position.v); |
5182 } | 3678 } |
5183 | 3679 |
5184 | 3680 |
5185 | |
5186 /*********************************************************************** | |
5187 Tool-bars | |
5188 ***********************************************************************/ | |
5189 | |
5190 static int x_tool_bar_item P_ ((struct frame *, int, int, | |
5191 struct glyph **, int *, int *, int *)); | |
5192 | |
5193 /* Tool-bar item index of the item on which a mouse button was pressed | |
5194 or -1. */ | |
5195 | |
5196 static int last_tool_bar_item; | |
5197 | |
5198 | |
5199 /* Get information about the tool-bar item at position X/Y on frame F. | |
5200 Return in *GLYPH a pointer to the glyph of the tool-bar item in | |
5201 the current matrix of the tool-bar window of F, or NULL if not | |
5202 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar | |
5203 item in F->current_tool_bar_items. Value is | |
5204 | |
5205 -1 if X/Y is not on a tool-bar item | |
5206 0 if X/Y is on the same item that was highlighted before. | |
5207 1 otherwise. */ | |
5208 | |
5209 static int | |
5210 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx) | |
5211 struct frame *f; | |
5212 int x, y; | |
5213 struct glyph **glyph; | |
5214 int *hpos, *vpos, *prop_idx; | |
5215 { | |
5216 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); | |
5217 struct window *w = XWINDOW (f->tool_bar_window); | |
5218 int area; | |
5219 | |
5220 /* Find the glyph under X/Y. */ | |
5221 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0); | |
5222 if (*glyph == NULL) | |
5223 return -1; | |
5224 | |
5225 /* Get the start of this tool-bar item's properties in | |
5226 f->current_tool_bar_items. */ | |
5227 if (!tool_bar_item_info (f, *glyph, prop_idx)) | |
5228 return -1; | |
5229 | |
5230 /* Is mouse on the highlighted item? */ | |
5231 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window) | |
5232 && *vpos >= dpyinfo->mouse_face_beg_row | |
5233 && *vpos <= dpyinfo->mouse_face_end_row | |
5234 && (*vpos > dpyinfo->mouse_face_beg_row | |
5235 || *hpos >= dpyinfo->mouse_face_beg_col) | |
5236 && (*vpos < dpyinfo->mouse_face_end_row | |
5237 || *hpos < dpyinfo->mouse_face_end_col | |
5238 || dpyinfo->mouse_face_past_end)) | |
5239 return 0; | |
5240 | |
5241 return 1; | |
5242 } | |
5243 | |
5244 | |
5245 /* Handle mouse button event on the tool-bar of frame F, at | |
5246 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress | |
5247 or ButtonRelase. */ | |
5248 | |
5249 static void | |
5250 x_handle_tool_bar_click (f, button_event) | |
5251 struct frame *f; | |
5252 EventRecord *button_event; | |
5253 { | |
5254 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); | |
5255 struct window *w = XWINDOW (f->tool_bar_window); | |
5256 int hpos, vpos, prop_idx; | |
5257 struct glyph *glyph; | |
5258 Lisp_Object enabled_p; | |
5259 int x = button_event->where.h; | |
5260 int y = button_event->where.v; | |
5261 | |
5262 /* If not on the highlighted tool-bar item, return. */ | |
5263 frame_to_window_pixel_xy (w, &x, &y); | |
5264 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0) | |
5265 return; | |
5266 | |
5267 /* If item is disabled, do nothing. */ | |
5268 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P); | |
5269 if (NILP (enabled_p)) | |
5270 return; | |
5271 | |
5272 if (button_event->what == mouseDown) | |
5273 { | |
5274 /* Show item in pressed state. */ | |
5275 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN); | |
5276 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN; | |
5277 last_tool_bar_item = prop_idx; | |
5278 } | |
5279 else | |
5280 { | |
5281 Lisp_Object key, frame; | |
5282 struct input_event event; | |
5283 | |
5284 /* Show item in released state. */ | |
5285 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED); | |
5286 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED; | |
5287 | |
5288 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY); | |
5289 | |
5290 XSETFRAME (frame, f); | |
5291 event.kind = TOOL_BAR_EVENT; | |
5292 event.frame_or_window = frame; | |
5293 event.arg = frame; | |
5294 kbd_buffer_store_event (&event); | |
5295 | |
5296 event.kind = TOOL_BAR_EVENT; | |
5297 event.frame_or_window = frame; | |
5298 event.arg = key; | |
5299 event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), | |
5300 button_event->modifiers); | |
5301 kbd_buffer_store_event (&event); | |
5302 last_tool_bar_item = -1; | |
5303 } | |
5304 } | |
5305 | |
5306 | |
5307 /* Possibly highlight a tool-bar item on frame F when mouse moves to | |
5308 tool-bar window-relative coordinates X/Y. Called from | |
5309 note_mouse_highlight. */ | |
5310 | |
5311 static void | |
5312 note_tool_bar_highlight (f, x, y) | |
5313 struct frame *f; | |
5314 int x, y; | |
5315 { | |
5316 Lisp_Object window = f->tool_bar_window; | |
5317 struct window *w = XWINDOW (window); | |
5318 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); | |
5319 int hpos, vpos; | |
5320 struct glyph *glyph; | |
5321 struct glyph_row *row; | |
5322 int i; | |
5323 Lisp_Object enabled_p; | |
5324 int prop_idx; | |
5325 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED; | |
5326 int mouse_down_p, rc; | |
5327 | |
5328 /* Function note_mouse_highlight is called with negative x(y | |
5329 values when mouse moves outside of the frame. */ | |
5330 if (x <= 0 || y <= 0) | |
5331 { | |
5332 clear_mouse_face (dpyinfo); | |
5333 return; | |
5334 } | |
5335 | |
5336 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx); | |
5337 if (rc < 0) | |
5338 { | |
5339 /* Not on tool-bar item. */ | |
5340 clear_mouse_face (dpyinfo); | |
5341 return; | |
5342 } | |
5343 else if (rc == 0) | |
5344 /* On same tool-bar item as before. */ | |
5345 goto set_help_echo; | |
5346 | |
5347 clear_mouse_face (dpyinfo); | |
5348 | |
5349 /* Mouse is down, but on different tool-bar item? */ | |
5350 mouse_down_p = (dpyinfo->grabbed | |
5351 && f == last_mouse_frame | |
5352 && FRAME_LIVE_P (f)); | |
5353 if (mouse_down_p | |
5354 && last_tool_bar_item != prop_idx) | |
5355 return; | |
5356 | |
5357 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT; | |
5358 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED; | |
5359 | |
5360 /* If tool-bar item is not enabled, don't highlight it. */ | |
5361 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P); | |
5362 if (!NILP (enabled_p)) | |
5363 { | |
5364 /* Compute the x-position of the glyph. In front and past the | |
5365 image is a space. We include this is the highlighted area. */ | |
5366 row = MATRIX_ROW (w->current_matrix, vpos); | |
5367 for (i = x = 0; i < hpos; ++i) | |
5368 x += row->glyphs[TEXT_AREA][i].pixel_width; | |
5369 | |
5370 /* Record this as the current active region. */ | |
5371 dpyinfo->mouse_face_beg_col = hpos; | |
5372 dpyinfo->mouse_face_beg_row = vpos; | |
5373 dpyinfo->mouse_face_beg_x = x; | |
5374 dpyinfo->mouse_face_beg_y = row->y; | |
5375 dpyinfo->mouse_face_past_end = 0; | |
5376 | |
5377 dpyinfo->mouse_face_end_col = hpos + 1; | |
5378 dpyinfo->mouse_face_end_row = vpos; | |
5379 dpyinfo->mouse_face_end_x = x + glyph->pixel_width; | |
5380 dpyinfo->mouse_face_end_y = row->y; | |
5381 dpyinfo->mouse_face_window = window; | |
5382 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID; | |
5383 | |
5384 /* Display it as active. */ | |
5385 show_mouse_face (dpyinfo, draw); | |
5386 dpyinfo->mouse_face_image_state = draw; | |
5387 } | |
5388 | |
5389 set_help_echo: | |
5390 | |
5391 /* Set help_echo to a help string.to display for this tool-bar item. | |
5392 XTread_socket does the rest. */ | |
5393 help_echo_object = help_echo_window = Qnil; | |
5394 help_echo_pos = -1; | |
5395 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP); | |
5396 if (NILP (help_echo)) | |
5397 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION); | |
5398 } | |
5399 | |
5400 | |
5401 | |
5402 /* Find the glyph matrix position of buffer position CHARPOS in window | |
5403 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's | |
5404 current glyphs must be up to date. If CHARPOS is above window | |
5405 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end | |
5406 of last line in W. In the row containing CHARPOS, stop before glyphs | |
5407 having STOP as object. */ | |
5408 | |
5409 #if 0 /* This is a version of fast_find_position that's more correct | |
5410 in the presence of hscrolling, for example. I didn't install | |
5411 it right away because the problem fixed is minor, it failed | |
5412 in 20.x as well, and I think it's too risky to install | |
5413 so near the release of 21.1. 2001-09-25 gerd. */ | |
5414 | |
5415 static int | |
5416 fast_find_position (w, charpos, hpos, vpos, x, y, stop) | |
5417 struct window *w; | |
5418 int charpos; | |
5419 int *hpos, *vpos, *x, *y; | |
5420 Lisp_Object stop; | |
5421 { | |
5422 struct glyph_row *row, *first; | |
5423 struct glyph *glyph, *end; | |
5424 int i, past_end = 0; | |
5425 | |
5426 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | |
5427 row = row_containing_pos (w, charpos, first, NULL, 0); | |
5428 if (row == NULL) | |
5429 { | |
5430 if (charpos < MATRIX_ROW_START_CHARPOS (first)) | |
5431 { | |
5432 *x = *y = *hpos = *vpos = 0; | |
5433 return 0; | |
5434 } | |
5435 else | |
5436 { | |
5437 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos)); | |
5438 past_end = 1; | |
5439 } | |
5440 } | |
5441 | |
5442 *x = row->x; | |
5443 *y = row->y; | |
5444 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix); | |
5445 | |
5446 glyph = row->glyphs[TEXT_AREA]; | |
5447 end = glyph + row->used[TEXT_AREA]; | |
5448 | |
5449 /* Skip over glyphs not having an object at the start of the row. | |
5450 These are special glyphs like truncation marks on terminal | |
5451 frames. */ | |
5452 if (row->displays_text_p) | |
5453 while (glyph < end | |
5454 && INTEGERP (glyph->object) | |
5455 && !EQ (stop, glyph->object) | |
5456 && glyph->charpos < 0) | |
5457 { | |
5458 *x += glyph->pixel_width; | |
5459 ++glyph; | |
5460 } | |
5461 | |
5462 while (glyph < end | |
5463 && !INTEGERP (glyph->object) | |
5464 && !EQ (stop, glyph->object) | |
5465 && (!BUFFERP (glyph->object) | |
5466 || glyph->charpos < charpos)) | |
5467 { | |
5468 *x += glyph->pixel_width; | |
5469 ++glyph; | |
5470 } | |
5471 | |
5472 *hpos = glyph - row->glyphs[TEXT_AREA]; | |
5473 return past_end; | |
5474 } | |
5475 | |
5476 #else /* not 0 */ | |
5477 | |
5478 static int | |
5479 fast_find_position (w, pos, hpos, vpos, x, y, stop) | |
5480 struct window *w; | |
5481 int pos; | |
5482 int *hpos, *vpos, *x, *y; | |
5483 Lisp_Object stop; | |
5484 { | |
5485 int i; | |
5486 int lastcol; | |
5487 int maybe_next_line_p = 0; | |
5488 int line_start_position; | |
5489 int yb = window_text_bottom_y (w); | |
5490 struct glyph_row *row, *best_row; | |
5491 int row_vpos, best_row_vpos; | |
5492 int current_x; | |
5493 | |
5494 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | |
5495 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix); | |
5496 | |
5497 while (row->y < yb) | |
5498 { | |
5499 if (row->used[TEXT_AREA]) | |
5500 line_start_position = row->glyphs[TEXT_AREA]->charpos; | |
5501 else | |
5502 line_start_position = 0; | |
5503 | |
5504 if (line_start_position > pos) | |
5505 break; | |
5506 /* If the position sought is the end of the buffer, | |
5507 don't include the blank lines at the bottom of the window. */ | |
5508 else if (line_start_position == pos | |
5509 && pos == BUF_ZV (XBUFFER (w->buffer))) | |
5510 { | |
5511 maybe_next_line_p = 1; | |
5512 break; | |
5513 } | |
5514 else if (line_start_position > 0) | |
5515 { | |
5516 best_row = row; | |
5517 best_row_vpos = row_vpos; | |
5518 } | |
5519 | |
5520 if (row->y + row->height >= yb) | |
5521 break; | |
5522 | |
5523 ++row; | |
5524 ++row_vpos; | |
5525 } | |
5526 | |
5527 /* Find the right column within BEST_ROW. */ | |
5528 lastcol = 0; | |
5529 current_x = best_row->x; | |
5530 for (i = 0; i < best_row->used[TEXT_AREA]; i++) | |
5531 { | |
5532 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i; | |
5533 int charpos = glyph->charpos; | |
5534 | |
5535 if (BUFFERP (glyph->object)) | |
5536 { | |
5537 if (charpos == pos) | |
5538 { | |
5539 *hpos = i; | |
5540 *vpos = best_row_vpos; | |
5541 *x = current_x; | |
5542 *y = best_row->y; | |
5543 return 1; | |
5544 } | |
5545 else if (charpos > pos) | |
5546 break; | |
5547 } | |
5548 else if (EQ (glyph->object, stop)) | |
5549 break; | |
5550 | |
5551 if (charpos > 0) | |
5552 lastcol = i; | |
5553 current_x += glyph->pixel_width; | |
5554 } | |
5555 | |
5556 /* If we're looking for the end of the buffer, | |
5557 and we didn't find it in the line we scanned, | |
5558 use the start of the following line. */ | |
5559 if (maybe_next_line_p) | |
5560 { | |
5561 ++best_row; | |
5562 ++best_row_vpos; | |
5563 lastcol = 0; | |
5564 current_x = best_row->x; | |
5565 } | |
5566 | |
5567 *vpos = best_row_vpos; | |
5568 *hpos = lastcol + 1; | |
5569 *x = current_x; | |
5570 *y = best_row->y; | |
5571 return 0; | |
5572 } | |
5573 | |
5574 #endif /* not 0 */ | |
5575 | |
5576 | |
5577 /* Find the position of the glyph for position POS in OBJECT in | |
5578 window W's current matrix, and return in *X/*Y the pixel | |
5579 coordinates, and return in *HPOS/*VPOS the column/row of the glyph. | |
5580 | |
5581 RIGHT_P non-zero means return the position of the right edge of the | |
5582 glyph, RIGHT_P zero means return the left edge position. | |
5583 | |
5584 If no glyph for POS exists in the matrix, return the position of | |
5585 the glyph with the next smaller position that is in the matrix, if | |
5586 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS | |
5587 exists in the matrix, return the position of the glyph with the | |
5588 next larger position in OBJECT. | |
5589 | |
5590 Value is non-zero if a glyph was found. */ | |
5591 | |
5592 static int | |
5593 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p) | |
5594 struct window *w; | |
5595 int pos; | |
5596 Lisp_Object object; | |
5597 int *hpos, *vpos, *x, *y; | |
5598 int right_p; | |
5599 { | |
5600 int yb = window_text_bottom_y (w); | |
5601 struct glyph_row *r; | |
5602 struct glyph *best_glyph = NULL; | |
5603 struct glyph_row *best_row = NULL; | |
5604 int best_x = 0; | |
5605 | |
5606 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | |
5607 r->enabled_p && r->y < yb; | |
5608 ++r) | |
5609 { | |
5610 struct glyph *g = r->glyphs[TEXT_AREA]; | |
5611 struct glyph *e = g + r->used[TEXT_AREA]; | |
5612 int gx; | |
5613 | |
5614 for (gx = r->x; g < e; gx += g->pixel_width, ++g) | |
5615 if (EQ (g->object, object)) | |
5616 { | |
5617 if (g->charpos == pos) | |
5618 { | |
5619 best_glyph = g; | |
5620 best_x = gx; | |
5621 best_row = r; | |
5622 goto found; | |
5623 } | |
5624 else if (best_glyph == NULL | |
5625 || ((abs (g->charpos - pos) | |
5626 < abs (best_glyph->charpos - pos)) | |
5627 && (right_p | |
5628 ? g->charpos < pos | |
5629 : g->charpos > pos))) | |
5630 { | |
5631 best_glyph = g; | |
5632 best_x = gx; | |
5633 best_row = r; | |
5634 } | |
5635 } | |
5636 } | |
5637 | |
5638 found: | |
5639 | |
5640 if (best_glyph) | |
5641 { | |
5642 *x = best_x; | |
5643 *hpos = best_glyph - best_row->glyphs[TEXT_AREA]; | |
5644 | |
5645 if (right_p) | |
5646 { | |
5647 *x += best_glyph->pixel_width; | |
5648 ++*hpos; | |
5649 } | |
5650 | |
5651 *y = best_row->y; | |
5652 *vpos = best_row - w->current_matrix->rows; | |
5653 } | |
5654 | |
5655 return best_glyph != NULL; | |
5656 } | |
5657 | |
5658 | |
5659 /* Display the active region described by mouse_face_* | |
5660 in its mouse-face if HL > 0, in its normal face if HL = 0. */ | |
5661 | |
5662 static void | |
5663 show_mouse_face (dpyinfo, draw) | |
5664 struct mac_display_info *dpyinfo; | |
5665 enum draw_glyphs_face draw; | |
5666 { | |
5667 struct window *w = XWINDOW (dpyinfo->mouse_face_window); | |
5668 struct frame *f = XFRAME (WINDOW_FRAME (w)); | |
5669 | |
5670 if (/* If window is in the process of being destroyed, don't bother | |
5671 to do anything. */ | |
5672 w->current_matrix != NULL | |
5673 /* Don't update mouse highlight if hidden */ | |
5674 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden) | |
5675 /* Recognize when we are called to operate on rows that don't exist | |
5676 anymore. This can happen when a window is split. */ | |
5677 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows) | |
5678 { | |
5679 int phys_cursor_on_p = w->phys_cursor_on_p; | |
5680 struct glyph_row *row, *first, *last; | |
5681 | |
5682 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row); | |
5683 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row); | |
5684 | |
5685 for (row = first; row <= last && row->enabled_p; ++row) | |
5686 { | |
5687 int start_hpos, end_hpos, start_x; | |
5688 | |
5689 /* For all but the first row, the highlight starts at column 0. */ | |
5690 if (row == first) | |
5691 { | |
5692 start_hpos = dpyinfo->mouse_face_beg_col; | |
5693 start_x = dpyinfo->mouse_face_beg_x; | |
5694 } | |
5695 else | |
5696 { | |
5697 start_hpos = 0; | |
5698 start_x = 0; | |
5699 } | |
5700 | |
5701 if (row == last) | |
5702 end_hpos = dpyinfo->mouse_face_end_col; | |
5703 else | |
5704 end_hpos = row->used[TEXT_AREA]; | |
5705 | |
5706 if (end_hpos > start_hpos) | |
5707 { | |
5708 x_draw_glyphs (w, start_x, row, TEXT_AREA, | |
5709 start_hpos, end_hpos, draw, 0); | |
5710 | |
5711 row->mouse_face_p | |
5712 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED; | |
5713 } | |
5714 } | |
5715 | |
5716 /* When we've written over the cursor, arrange for it to | |
5717 be displayed again. */ | |
5718 if (phys_cursor_on_p && !w->phys_cursor_on_p) | |
5719 x_display_cursor (w, 1, | |
5720 w->phys_cursor.hpos, w->phys_cursor.vpos, | |
5721 w->phys_cursor.x, w->phys_cursor.y); | |
5722 } | |
5723 | |
5724 #if 0 /* MAC_TODO: mouse cursor */ | |
5725 /* Change the mouse cursor. */ | |
5726 if (draw == DRAW_NORMAL_TEXT) | |
5727 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
5728 f->output_data.x->text_cursor); | |
5729 else if (draw == DRAW_MOUSE_FACE) | |
5730 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
5731 f->output_data.x->cross_cursor); | |
5732 else | |
5733 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), | |
5734 f->output_data.x->nontext_cursor); | |
5735 #endif | |
5736 } | |
5737 | |
5738 /* Clear out the mouse-highlighted active region. | |
5739 Redraw it un-highlighted first. */ | |
5740 | |
5741 static int | |
5742 clear_mouse_face (dpyinfo) | |
5743 struct mac_display_info *dpyinfo; | |
5744 { | |
5745 int cleared = 0; | |
5746 | |
5747 if (! NILP (dpyinfo->mouse_face_window)) | |
5748 { | |
5749 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT); | |
5750 cleared = 1; | |
5751 } | |
5752 | |
5753 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; | |
5754 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; | |
5755 dpyinfo->mouse_face_window = Qnil; | |
5756 dpyinfo->mouse_face_overlay = Qnil; | |
5757 return cleared; | |
5758 } | |
5759 | |
5760 | |
5761 /* Clear any mouse-face on window W. This function is part of the | |
5762 redisplay interface, and is called from try_window_id and similar | |
5763 functions to ensure the mouse-highlight is off. */ | |
5764 | |
5765 static void | |
5766 x_clear_mouse_face (w) | |
5767 struct window *w; | |
5768 { | |
5769 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame)); | |
5770 Lisp_Object window; | |
5771 | |
5772 BLOCK_INPUT; | |
5773 XSETWINDOW (window, w); | |
5774 if (EQ (window, dpyinfo->mouse_face_window)) | |
5775 clear_mouse_face (dpyinfo); | |
5776 UNBLOCK_INPUT; | |
5777 } | |
5778 | |
5779 | |
5780 /* Just discard the mouse face information for frame F, if any. | |
5781 This is used when the size of F is changed. */ | |
5782 | |
5783 void | |
5784 cancel_mouse_face (f) | |
5785 FRAME_PTR f; | |
5786 { | |
5787 Lisp_Object window; | |
5788 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); | |
5789 | |
5790 window = dpyinfo->mouse_face_window; | |
5791 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f) | |
5792 { | |
5793 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; | |
5794 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; | |
5795 dpyinfo->mouse_face_window = Qnil; | |
5796 } | |
5797 } | |
5798 | |
5799 static struct scroll_bar *x_window_to_scroll_bar (); | |
5800 static void x_scroll_bar_report_motion (); | |
5801 static void x_check_fullscreen P_ ((struct frame *)); | |
5802 static void x_check_fullscreen_move P_ ((struct frame *)); | |
5803 static int glyph_rect P_ ((struct frame *f, int, int, Rect *)); | |
5804 | |
5805 | |
5806 /* Try to determine frame pixel position and size of the glyph under | 3681 /* Try to determine frame pixel position and size of the glyph under |
5807 frame pixel coordinates X/Y on frame F . Return the position and | 3682 frame pixel coordinates X/Y on frame F . Return the position and |
5808 size in *RECT. Value is non-zero if we could compute these | 3683 size in *RECT. Value is non-zero if we could compute these |
5809 values. */ | 3684 values. */ |
5810 | 3685 |
5813 struct frame *f; | 3688 struct frame *f; |
5814 int x, y; | 3689 int x, y; |
5815 Rect *rect; | 3690 Rect *rect; |
5816 { | 3691 { |
5817 Lisp_Object window; | 3692 Lisp_Object window; |
5818 int part; | 3693 |
5819 | 3694 window = window_from_coordinates (f, x, y, 0, 0); |
5820 window = window_from_coordinates (f, x, y, &part, 0); | |
5821 if (!NILP (window)) | 3695 if (!NILP (window)) |
5822 { | 3696 { |
5823 struct window *w = XWINDOW (window); | 3697 struct window *w = XWINDOW (window); |
5824 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | 3698 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); |
5825 struct glyph_row *end = r + w->current_matrix->nrows - 1; | 3699 struct glyph_row *end = r + w->current_matrix->nrows - 1; |
5862 } | 3736 } |
5863 | 3737 |
5864 /* The y is not on any row. */ | 3738 /* The y is not on any row. */ |
5865 return 0; | 3739 return 0; |
5866 } | 3740 } |
3741 | |
3742 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */ | |
5867 | 3743 |
5868 /* Record the position of the mouse in last_mouse_glyph. */ | 3744 /* Record the position of the mouse in last_mouse_glyph. */ |
5869 static void | 3745 static void |
5870 remember_mouse_glyph (f1, gx, gy) | 3746 remember_mouse_glyph (f1, gx, gy) |
5871 struct frame * f1; | 3747 struct frame * f1; |
5898 last_mouse_glyph.right = gx + width; | 3774 last_mouse_glyph.right = gx + width; |
5899 last_mouse_glyph.bottom = gy + height; | 3775 last_mouse_glyph.bottom = gy + height; |
5900 } | 3776 } |
5901 } | 3777 } |
5902 | 3778 |
3779 | |
5903 /* Return the current position of the mouse. | 3780 /* Return the current position of the mouse. |
5904 *fp should be a frame which indicates which display to ask about. | 3781 *fp should be a frame which indicates which display to ask about. |
5905 | 3782 |
5906 If the mouse movement started in a scroll bar, set *fp, *bar_window, | 3783 If the mouse movement started in a scroll bar, set *fp, *bar_window, |
5907 and *part to the frame, window, and scroll bar part that the mouse | 3784 and *part to the frame, window, and scroll bar part that the mouse |
5968 XSETINT (*y, mouse_pos.v); | 3845 XSETINT (*y, mouse_pos.v); |
5969 *time = last_mouse_movement_time; | 3846 *time = last_mouse_movement_time; |
5970 } | 3847 } |
5971 | 3848 |
5972 UNBLOCK_INPUT; | 3849 UNBLOCK_INPUT; |
3850 } | |
3851 | |
3852 | |
3853 /*********************************************************************** | |
3854 Tool-bars | |
3855 ***********************************************************************/ | |
3856 | |
3857 /* Handle mouse button event on the tool-bar of frame F, at | |
3858 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress | |
3859 or ButtonRelase. */ | |
3860 | |
3861 static void | |
3862 mac_handle_tool_bar_click (f, button_event) | |
3863 struct frame *f; | |
3864 EventRecord *button_event; | |
3865 { | |
3866 int x = button_event->where.h; | |
3867 int y = button_event->where.v; | |
3868 | |
3869 if (button_event->what == mouseDown) | |
3870 handle_tool_bar_click (f, x, y, 1, 0); | |
3871 else | |
3872 handle_tool_bar_click (f, x, y, 0, | |
3873 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f), | |
3874 button_event->modifiers)); | |
5973 } | 3875 } |
5974 | 3876 |
5975 | 3877 |
5976 /************************************************************************ | 3878 /************************************************************************ |
5977 Scroll bars, general | 3879 Scroll bars, general |
6370 /* Now there should be no references to the condemned scroll bars, | 4272 /* Now there should be no references to the condemned scroll bars, |
6371 and they should get garbage-collected. */ | 4273 and they should get garbage-collected. */ |
6372 } | 4274 } |
6373 | 4275 |
6374 | 4276 |
6375 static void | 4277 void |
6376 activate_scroll_bars (frame) | 4278 activate_scroll_bars (frame) |
6377 FRAME_PTR frame; | 4279 FRAME_PTR frame; |
6378 { | 4280 { |
6379 Lisp_Object bar; | 4281 Lisp_Object bar; |
6380 ControlHandle ch; | 4282 ControlHandle ch; |
6394 bar = XSCROLL_BAR (bar)->next; | 4296 bar = XSCROLL_BAR (bar)->next; |
6395 } | 4297 } |
6396 } | 4298 } |
6397 | 4299 |
6398 | 4300 |
6399 static void | 4301 void |
6400 deactivate_scroll_bars (frame) | 4302 deactivate_scroll_bars (frame) |
6401 FRAME_PTR frame; | 4303 FRAME_PTR frame; |
6402 { | 4304 { |
6403 Lisp_Object bar; | 4305 Lisp_Object bar; |
6404 ControlHandle ch; | 4306 ControlHandle ch; |
6718 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f)); | 4620 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f)); |
6719 } | 4621 } |
6720 } | 4622 } |
6721 | 4623 |
6722 | 4624 |
6723 /* Clear the cursor of window W to background color, and mark the | 4625 /* RIF: Define cursor CURSOR on frame F. */ |
6724 cursor as not shown. This is used when the text where the cursor | 4626 |
6725 is is about to be rewritten. */ | 4627 static void |
6726 | 4628 mac_define_frame_cursor (f, cursor) |
6727 static void | 4629 struct frame *f; |
6728 x_clear_cursor (w) | 4630 Cursor cursor; |
4631 { | |
4632 /* MAC TODO */ | |
4633 } | |
4634 | |
4635 | |
4636 /* RIF: Clear area on frame F. */ | |
4637 | |
4638 static void | |
4639 mac_clear_frame_area (f, x, y, width, height) | |
4640 struct frame *f; | |
4641 int x, y, width, height; | |
4642 { | |
4643 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), | |
4644 x, y, width, height, 0); | |
4645 } | |
4646 | |
4647 | |
4648 /* RIF: Draw cursor on window W. */ | |
4649 | |
4650 static void | |
4651 mac_draw_window_cursor (w, glyph_row, on, x, y, new_cursor_type, new_cursor_width) | |
6729 struct window *w; | 4652 struct window *w; |
6730 { | 4653 struct glyph_row *glyph_row; |
6731 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p) | 4654 int on, x, y; |
6732 x_update_window_cursor (w, 0); | 4655 int new_cursor_type, new_cursor_width; |
6733 } | 4656 { |
6734 | 4657 if (on) |
6735 | 4658 { |
6736 /* Draw the cursor glyph of window W in glyph row ROW. See the | |
6737 comment of x_draw_glyphs for the meaning of HL. */ | |
6738 | |
6739 static void | |
6740 x_draw_phys_cursor_glyph (w, row, hl) | |
6741 struct window *w; | |
6742 struct glyph_row *row; | |
6743 enum draw_glyphs_face hl; | |
6744 { | |
6745 /* If cursor hpos is out of bounds, don't draw garbage. This can | |
6746 happen in mini-buffer windows when switching between echo area | |
6747 glyphs and mini-buffer. */ | |
6748 if (w->phys_cursor.hpos < row->used[TEXT_AREA]) | |
6749 { | |
6750 int on_p = w->phys_cursor_on_p; | |
6751 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, | |
6752 w->phys_cursor.hpos, w->phys_cursor.hpos + 1, | |
6753 hl, 0); | |
6754 w->phys_cursor_on_p = on_p; | |
6755 | |
6756 /* When we erase the cursor, and ROW is overlapped by other | |
6757 rows, make sure that these overlapping parts of other rows | |
6758 are redrawn. */ | |
6759 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p) | |
6760 { | |
6761 if (row > w->current_matrix->rows | |
6762 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1)) | |
6763 x_fix_overlapping_area (w, row - 1, TEXT_AREA); | |
6764 | |
6765 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w) | |
6766 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1)) | |
6767 x_fix_overlapping_area (w, row + 1, TEXT_AREA); | |
6768 } | |
6769 } | |
6770 } | |
6771 | |
6772 | |
6773 /* Erase the image of a cursor of window W from the screen. */ | |
6774 | |
6775 static void | |
6776 x_erase_phys_cursor (w) | |
6777 struct window *w; | |
6778 { | |
6779 struct frame *f = XFRAME (w->frame); | |
6780 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); | |
6781 int hpos = w->phys_cursor.hpos; | |
6782 int vpos = w->phys_cursor.vpos; | |
6783 int mouse_face_here_p = 0; | |
6784 struct glyph_matrix *active_glyphs = w->current_matrix; | |
6785 struct glyph_row *cursor_row; | |
6786 struct glyph *cursor_glyph; | |
6787 enum draw_glyphs_face hl; | |
6788 | |
6789 /* No cursor displayed or row invalidated => nothing to do on the | |
6790 screen. */ | |
6791 if (w->phys_cursor_type == NO_CURSOR) | |
6792 goto mark_cursor_off; | |
6793 | |
6794 /* VPOS >= active_glyphs->nrows means that window has been resized. | |
6795 Don't bother to erase the cursor. */ | |
6796 if (vpos >= active_glyphs->nrows) | |
6797 goto mark_cursor_off; | |
6798 | |
6799 /* If row containing cursor is marked invalid, there is nothing we | |
6800 can do. */ | |
6801 cursor_row = MATRIX_ROW (active_glyphs, vpos); | |
6802 if (!cursor_row->enabled_p) | |
6803 goto mark_cursor_off; | |
6804 | |
6805 /* If row is completely invisible, don't attempt to delete a cursor which | |
6806 isn't there. This may happen if cursor is at top of window, and | |
6807 we switch to a buffer with a header line in that window. */ | |
6808 if (cursor_row->visible_height <= 0) | |
6809 goto mark_cursor_off; | |
6810 | |
6811 /* This can happen when the new row is shorter than the old one. | |
6812 In this case, either x_draw_glyphs or clear_end_of_line | |
6813 should have cleared the cursor. Note that we wouldn't be | |
6814 able to erase the cursor in this case because we don't have a | |
6815 cursor glyph at hand. */ | |
6816 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA]) | |
6817 goto mark_cursor_off; | |
6818 | |
6819 /* If the cursor is in the mouse face area, redisplay that when | |
6820 we clear the cursor. */ | |
6821 if (! NILP (dpyinfo->mouse_face_window) | |
6822 && w == XWINDOW (dpyinfo->mouse_face_window) | |
6823 && (vpos > dpyinfo->mouse_face_beg_row | |
6824 || (vpos == dpyinfo->mouse_face_beg_row | |
6825 && hpos >= dpyinfo->mouse_face_beg_col)) | |
6826 && (vpos < dpyinfo->mouse_face_end_row | |
6827 || (vpos == dpyinfo->mouse_face_end_row | |
6828 && hpos < dpyinfo->mouse_face_end_col)) | |
6829 /* Don't redraw the cursor's spot in mouse face if it is at the | |
6830 end of a line (on a newline). The cursor appears there, but | |
6831 mouse highlighting does not. */ | |
6832 && cursor_row->used[TEXT_AREA] > hpos) | |
6833 mouse_face_here_p = 1; | |
6834 | |
6835 /* Maybe clear the display under the cursor. */ | |
6836 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR) | |
6837 { | |
6838 int x; | |
6839 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w); | |
6840 | |
6841 cursor_glyph = get_phys_cursor_glyph (w); | |
6842 if (cursor_glyph == NULL) | |
6843 goto mark_cursor_off; | |
6844 | |
6845 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x), | |
6846 | |
6847 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), | |
6848 x, | |
6849 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, | |
6850 cursor_row->y)), | |
6851 cursor_glyph->pixel_width, | |
6852 cursor_row->visible_height, | |
6853 0); | |
6854 } | |
6855 | |
6856 /* Erase the cursor by redrawing the character underneath it. */ | |
6857 if (mouse_face_here_p) | |
6858 hl = DRAW_MOUSE_FACE; | |
6859 else | |
6860 hl = DRAW_NORMAL_TEXT; | |
6861 x_draw_phys_cursor_glyph (w, cursor_row, hl); | |
6862 | |
6863 mark_cursor_off: | |
6864 w->phys_cursor_on_p = 0; | |
6865 w->phys_cursor_type = NO_CURSOR; | |
6866 } | |
6867 | |
6868 | |
6869 /* Non-zero if physical cursor of window W is within mouse face. */ | |
6870 | |
6871 static int | |
6872 cursor_in_mouse_face_p (w) | |
6873 struct window *w; | |
6874 { | |
6875 struct mac_display_info *dpyinfo | |
6876 = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame)); | |
6877 int in_mouse_face = 0; | |
6878 | |
6879 if (WINDOWP (dpyinfo->mouse_face_window) | |
6880 && XWINDOW (dpyinfo->mouse_face_window) == w) | |
6881 { | |
6882 int hpos = w->phys_cursor.hpos; | |
6883 int vpos = w->phys_cursor.vpos; | |
6884 | |
6885 if (vpos >= dpyinfo->mouse_face_beg_row | |
6886 && vpos <= dpyinfo->mouse_face_end_row | |
6887 && (vpos > dpyinfo->mouse_face_beg_row | |
6888 || hpos >= dpyinfo->mouse_face_beg_col) | |
6889 && (vpos < dpyinfo->mouse_face_end_row | |
6890 || hpos < dpyinfo->mouse_face_end_col | |
6891 || dpyinfo->mouse_face_past_end)) | |
6892 in_mouse_face = 1; | |
6893 } | |
6894 | |
6895 return in_mouse_face; | |
6896 } | |
6897 | |
6898 | |
6899 /* Display or clear cursor of window W. If ON is zero, clear the | |
6900 cursor. If it is non-zero, display the cursor. If ON is nonzero, | |
6901 where to put the cursor is specified by HPOS, VPOS, X and Y. */ | |
6902 | |
6903 void | |
6904 x_display_and_set_cursor (w, on, hpos, vpos, x, y) | |
6905 struct window *w; | |
6906 int on, hpos, vpos, x, y; | |
6907 { | |
6908 struct frame *f = XFRAME (w->frame); | |
6909 int new_cursor_type; | |
6910 int new_cursor_width; | |
6911 int active_cursor; | |
6912 struct glyph_matrix *current_glyphs; | |
6913 struct glyph_row *glyph_row; | |
6914 struct glyph *glyph; | |
6915 | |
6916 /* This is pointless on invisible frames, and dangerous on garbaged | |
6917 windows and frames; in the latter case, the frame or window may | |
6918 be in the midst of changing its size, and x and y may be off the | |
6919 window. */ | |
6920 if (! FRAME_VISIBLE_P (f) | |
6921 || FRAME_GARBAGED_P (f) | |
6922 || vpos >= w->current_matrix->nrows | |
6923 || hpos >= w->current_matrix->matrix_w) | |
6924 return; | |
6925 | |
6926 /* If cursor is off and we want it off, return quickly. */ | |
6927 if (!on && !w->phys_cursor_on_p) | |
6928 return; | |
6929 | |
6930 current_glyphs = w->current_matrix; | |
6931 glyph_row = MATRIX_ROW (current_glyphs, vpos); | |
6932 glyph = glyph_row->glyphs[TEXT_AREA] + hpos; | |
6933 | |
6934 /* If cursor row is not enabled, we don't really know where to | |
6935 display the cursor. */ | |
6936 if (!glyph_row->enabled_p) | |
6937 { | |
6938 w->phys_cursor_on_p = 0; | |
6939 return; | |
6940 } | |
6941 | |
6942 xassert (interrupt_input_blocked); | |
6943 | |
6944 /* Set new_cursor_type to the cursor we want to be displayed. */ | |
6945 new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor); | |
6946 | |
6947 | |
6948 /* If cursor is currently being shown and we don't want it to be or | |
6949 it is in the wrong place, or the cursor type is not what we want, | |
6950 erase it. */ | |
6951 if (w->phys_cursor_on_p | |
6952 && (!on | |
6953 || w->phys_cursor.x != x | |
6954 || w->phys_cursor.y != y | |
6955 || new_cursor_type != w->phys_cursor_type | |
6956 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR) | |
6957 && new_cursor_width != w->phys_cursor_width))) | |
6958 x_erase_phys_cursor (w); | |
6959 | |
6960 /* If the cursor is now invisible and we want it to be visible, | |
6961 display it. */ | |
6962 if (on && !w->phys_cursor_on_p) | |
6963 { | |
6964 w->phys_cursor_ascent = glyph_row->ascent; | |
6965 w->phys_cursor_height = glyph_row->height; | |
6966 | |
6967 /* Set phys_cursor_.* before x_draw_.* is called because some | |
6968 of them may need the information. */ | |
6969 w->phys_cursor.x = x; | |
6970 w->phys_cursor.y = glyph_row->y; | |
6971 w->phys_cursor.hpos = hpos; | |
6972 w->phys_cursor.vpos = vpos; | |
6973 w->phys_cursor_type = new_cursor_type; | 4659 w->phys_cursor_type = new_cursor_type; |
6974 w->phys_cursor_width = new_cursor_width; | 4660 w->phys_cursor_width = new_cursor_width; |
6975 w->phys_cursor_on_p = 1; | 4661 w->phys_cursor_on_p = 1; |
6976 | 4662 |
6977 switch (new_cursor_type) | 4663 switch (new_cursor_type) |
6979 case HOLLOW_BOX_CURSOR: | 4665 case HOLLOW_BOX_CURSOR: |
6980 x_draw_hollow_cursor (w, glyph_row); | 4666 x_draw_hollow_cursor (w, glyph_row); |
6981 break; | 4667 break; |
6982 | 4668 |
6983 case FILLED_BOX_CURSOR: | 4669 case FILLED_BOX_CURSOR: |
6984 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); | 4670 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); |
6985 break; | 4671 break; |
6986 | 4672 |
6987 case HBAR_CURSOR: | 4673 case HBAR_CURSOR: |
6988 /* TODO. For now, just draw bar cursor. */ | 4674 /* TODO. For now, just draw bar cursor. */ |
6989 case BAR_CURSOR: | 4675 case BAR_CURSOR: |
6996 default: | 4682 default: |
6997 abort (); | 4683 abort (); |
6998 } | 4684 } |
6999 } | 4685 } |
7000 } | 4686 } |
7001 | |
7002 | |
7003 /* Display the cursor on window W, or clear it. X and Y are window | |
7004 relative pixel coordinates. HPOS and VPOS are glyph matrix | |
7005 positions. If W is not the selected window, display a hollow | |
7006 cursor. ON non-zero means display the cursor at X, Y which | |
7007 correspond to HPOS, VPOS, otherwise it is cleared. */ | |
7008 | |
7009 void | |
7010 x_display_cursor (w, on, hpos, vpos, x, y) | |
7011 struct window *w; | |
7012 int on, hpos, vpos, x, y; | |
7013 { | |
7014 BLOCK_INPUT; | |
7015 x_display_and_set_cursor (w, on, hpos, vpos, x, y); | |
7016 UNBLOCK_INPUT; | |
7017 } | |
7018 | |
7019 | |
7020 /* Display the cursor on window W, or clear it, according to ON_P. | |
7021 Don't change the cursor's position. */ | |
7022 | |
7023 void | |
7024 x_update_cursor (f, on_p) | |
7025 struct frame *f; | |
7026 int on_p; | |
7027 { | |
7028 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p); | |
7029 } | |
7030 | |
7031 | |
7032 /* Call x_update_window_cursor with parameter ON_P on all leaf windows | |
7033 in the window tree rooted at W. */ | |
7034 | |
7035 static void | |
7036 x_update_cursor_in_window_tree (w, on_p) | |
7037 struct window *w; | |
7038 int on_p; | |
7039 { | |
7040 while (w) | |
7041 { | |
7042 if (!NILP (w->hchild)) | |
7043 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p); | |
7044 else if (!NILP (w->vchild)) | |
7045 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p); | |
7046 else | |
7047 x_update_window_cursor (w, on_p); | |
7048 | |
7049 w = NILP (w->next) ? 0 : XWINDOW (w->next); | |
7050 } | |
7051 } | |
7052 | |
7053 | |
7054 /* Switch the display of W's cursor on or off, according to the value | |
7055 of ON. */ | |
7056 | |
7057 static void | |
7058 x_update_window_cursor (w, on) | |
7059 struct window *w; | |
7060 int on; | |
7061 { | |
7062 /* Don't update cursor in windows whose frame is in the process | |
7063 of being deleted. */ | |
7064 if (w->current_matrix) | |
7065 { | |
7066 BLOCK_INPUT; | |
7067 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, | |
7068 w->phys_cursor.vpos, w->phys_cursor.x, | |
7069 w->phys_cursor.y); | |
7070 UNBLOCK_INPUT; | |
7071 } | |
7072 } | |
7073 | |
7074 | |
7075 | 4687 |
7076 | 4688 |
7077 /* Icons. */ | 4689 /* Icons. */ |
7078 | 4690 |
7079 #if 0 /* MAC_TODO: no icon support yet. */ | 4691 #if 0 /* MAC_TODO: no icon support yet. */ |
11105 x_clear_end_of_line, | 8717 x_clear_end_of_line, |
11106 x_scroll_run, | 8718 x_scroll_run, |
11107 x_after_update_window_line, | 8719 x_after_update_window_line, |
11108 x_update_window_begin, | 8720 x_update_window_begin, |
11109 x_update_window_end, | 8721 x_update_window_end, |
11110 XTcursor_to, | 8722 x_cursor_to, |
11111 x_flush, | 8723 x_flush, |
11112 x_clear_mouse_face, | 8724 x_flush, |
8725 x_clear_window_mouse_face, | |
11113 x_get_glyph_overhangs, | 8726 x_get_glyph_overhangs, |
11114 x_fix_overlapping_area, | 8727 x_fix_overlapping_area, |
11115 x_draw_fringe_bitmap, | 8728 x_draw_fringe_bitmap, |
11116 mac_per_char_metric, | 8729 mac_per_char_metric, |
11117 mac_encode_char, | 8730 mac_encode_char, |
11118 NULL, /* mac_compute_glyph_string_overhangs */ | 8731 NULL, /* mac_compute_glyph_string_overhangs */ |
11119 x_draw_glyph_string | 8732 x_draw_glyph_string, |
8733 mac_define_frame_cursor, | |
8734 mac_clear_frame_area, | |
8735 mac_draw_window_cursor, | |
8736 mac_shift_glyphs_for_insert | |
11120 }; | 8737 }; |
11121 | 8738 |
11122 void | 8739 void |
11123 mac_initialize () | 8740 mac_initialize () |
11124 { | 8741 { |
11142 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar; | 8759 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar; |
11143 condemn_scroll_bars_hook = XTcondemn_scroll_bars; | 8760 condemn_scroll_bars_hook = XTcondemn_scroll_bars; |
11144 redeem_scroll_bar_hook = XTredeem_scroll_bar; | 8761 redeem_scroll_bar_hook = XTredeem_scroll_bar; |
11145 judge_scroll_bars_hook = XTjudge_scroll_bars; | 8762 judge_scroll_bars_hook = XTjudge_scroll_bars; |
11146 | 8763 |
11147 estimate_mode_line_height_hook = x_estimate_mode_line_height; | |
11148 | |
11149 scroll_region_ok = 1; /* we'll scroll partial frames */ | 8764 scroll_region_ok = 1; /* we'll scroll partial frames */ |
11150 char_ins_del_ok = 1; | 8765 char_ins_del_ok = 1; |
11151 line_ins_del_ok = 1; /* we'll just blt 'em */ | 8766 line_ins_del_ok = 1; /* we'll just blt 'em */ |
11152 fast_clear_end_of_line = 1; /* X does this well */ | 8767 fast_clear_end_of_line = 1; /* X does this well */ |
11153 memory_below_frame = 0; /* we don't remember what scrolls | 8768 memory_below_frame = 0; /* we don't remember what scrolls |
11241 last_mouse_press_frame = Qnil; | 8856 last_mouse_press_frame = Qnil; |
11242 | 8857 |
11243 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop"); | 8858 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop"); |
11244 staticpro (&Qmac_ready_for_drag_n_drop); | 8859 staticpro (&Qmac_ready_for_drag_n_drop); |
11245 | 8860 |
11246 help_echo = Qnil; | |
11247 staticpro (&help_echo); | |
11248 help_echo_object = Qnil; | |
11249 staticpro (&help_echo_object); | |
11250 help_echo_window = Qnil; | |
11251 staticpro (&help_echo_window); | |
11252 previous_help_echo = Qnil; | |
11253 staticpro (&previous_help_echo); | |
11254 help_echo_pos = -1; | |
11255 | |
11256 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p, | 8861 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p, |
11257 doc: /* *Non-nil means autoselect window with mouse pointer. */); | 8862 doc: /* *Non-nil means autoselect window with mouse pointer. */); |
11258 x_autoselect_window_p = 0; | 8863 x_autoselect_window_p = 0; |
11259 | |
11260 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p, | |
11261 doc: /* *Non-nil means draw block cursor as wide as the glyph under it. | |
11262 For example, if a block cursor is over a tab, it will be drawn as | |
11263 wide as that tab on the display. */); | |
11264 x_stretch_cursor_p = 0; | |
11265 | |
11266 #if 0 /* TODO: Setting underline position from font properties. */ | |
11267 DEFVAR_BOOL ("x-use-underline-position-properties", | |
11268 &x_use_underline_position_properties, | |
11269 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties. | |
11270 nil means ignore them. If you encounter fonts with bogus | |
11271 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior | |
11272 to 4.1, set this to nil. */); | |
11273 x_use_underline_position_properties = 1; | |
11274 #endif | |
11275 | 8864 |
11276 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars, | 8865 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars, |
11277 doc: /* If not nil, Emacs uses toolkit scroll bars. */); | 8866 doc: /* If not nil, Emacs uses toolkit scroll bars. */); |
11278 Vx_toolkit_scroll_bars = Qt; | 8867 Vx_toolkit_scroll_bars = Qt; |
11279 | 8868 |