aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKim F. Storm2003-03-21 13:52:28 +0000
committerKim F. Storm2003-03-21 13:52:28 +0000
commitfa3c6b4da4179157ea4c4a295a554dea8794f846 (patch)
treef70a89d0f6a108a7c2acbc4769070ef020d64424 /src
parentb74b839745c7a1a09e5f8d14069032a0d9d065c5 (diff)
downloademacs-fa3c6b4da4179157ea4c4a295a554dea8794f846.tar.gz
emacs-fa3c6b4da4179157ea4c4a295a554dea8794f846.zip
The following changes consolidate code related to writing and
inserting glyphs, exposing frame, the tool bar, the mouse face, the output cursor, and help echo from xterm.c, w32term.c and macterm.c into xdisp.c. It also generalizes the use of the window_part enum instead of using numeric values throughout. * xdisp.c: Consolidate gui-independent code here. Include keymap.h. (Qhelp_echo): Import. (mouse_autoselect_window, x_stretch_cursor_p): Declare here. (help_echo_string, help_echo_window, help_echo_object) (previous_help_echo_string, help_echo_pos): Declare here. (output_cursor, last_mouse_frame, last_tool_bar_item): Declare here. (estimate_mode_line_height): Define here. Handle windowing systems directly (without using estimate_mode_line_height_hook). (x_y_to_hpos_vpos, get_tool_bar_item, note_tool_bar_highlight): (update_window_cursor, update_cursor_in_window_tree) (fast_find_position, fast_find_string_pos) (note_mode_line_highlight, note_mode_line_or_margin_highlight) (expose_area, expose_line, expose_overlaps, expose_window) (expose_window_tree, phys_cursor_in_rect_p): New generic versions; declared static as they are only used locally in xdisp.c. (draw_glyphs): Rename from x_draw_glyphs and make static. (tool_bar_item_info, notice_overwritten_cursor): Make static. (frame_to_window_pixel_xy, get_glyph_string_clip_rect) (set_output_cursor, x_cursor_to, handle_tool_bar_click) (x_write_glyphs, x_insert_glyphs, x_clear_end_of_line): (x_fix_overlapping_area, draw_phys_cursor_glyph, erase_phys_cursor) (display_and_set_cursor, x_update_cursor, x_clear_cursor) (show_mouse_face, clear_mouse_face, cursor_in_mouse_face_p) (note_mouse_highlight, x_clear_window_mouse_face) (cancel_mouse_face, x_draw_vertical_border, expose_frame) (x_intersect_rectangles): New generic functions for use by xdisp.c and GUI front-ends. (syms_of_xdisp): Initialize and staticpro help_echo* variables. Defvar_bool "x-streach-cursor" and "mouse-autoselect-window" here.
Diffstat (limited to 'src')
-rw-r--r--src/xdisp.c2658
1 files changed, 2648 insertions, 10 deletions
diff --git a/src/xdisp.c b/src/xdisp.c
index 20111e4988a..f80073788a9 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -179,6 +179,7 @@ Boston, MA 02111-1307, USA. */
179#include "charset.h" 179#include "charset.h"
180#include "indent.h" 180#include "indent.h"
181#include "commands.h" 181#include "commands.h"
182#include "keymap.h"
182#include "macros.h" 183#include "macros.h"
183#include "disptab.h" 184#include "disptab.h"
184#include "termhooks.h" 185#include "termhooks.h"
@@ -220,6 +221,7 @@ extern Lisp_Object Voverriding_local_map;
220extern Lisp_Object Voverriding_local_map_menu_flag; 221extern Lisp_Object Voverriding_local_map_menu_flag;
221extern Lisp_Object Qmenu_item; 222extern Lisp_Object Qmenu_item;
222extern Lisp_Object Qwhen; 223extern Lisp_Object Qwhen;
224extern Lisp_Object Qhelp_echo;
223 225
224Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; 226Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
225Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; 227Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
@@ -244,6 +246,10 @@ Lisp_Object list_of_error;
244Lisp_Object Vfontification_functions; 246Lisp_Object Vfontification_functions;
245Lisp_Object Qfontification_functions; 247Lisp_Object Qfontification_functions;
246 248
249/* Non-zero means automatically select any window when the mouse
250 cursor moves into it. */
251int mouse_autoselect_window;
252
247/* Non-zero means draw tool bar buttons raised when the mouse moves 253/* Non-zero means draw tool bar buttons raised when the mouse moves
248 over them. */ 254 over them. */
249 255
@@ -262,6 +268,12 @@ EMACS_INT tool_bar_button_relief;
262 268
263int auto_resize_tool_bars_p; 269int auto_resize_tool_bars_p;
264 270
271/* Non-zero means draw block and hollow cursor as wide as the glyph
272 under it. For example, if a block cursor is over a tab, it will be
273 drawn as wide as that tab on the display. */
274
275int x_stretch_cursor_p;
276
265/* Non-nil means don't actually do any redisplay. */ 277/* Non-nil means don't actually do any redisplay. */
266 278
267Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay; 279Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay;
@@ -724,6 +736,19 @@ int redisplaying_p;
724int inhibit_free_realized_faces; 736int inhibit_free_realized_faces;
725Lisp_Object Qinhibit_free_realized_faces; 737Lisp_Object Qinhibit_free_realized_faces;
726 738
739/* If a string, XTread_socket generates an event to display that string.
740 (The display is done in read_char.) */
741
742Lisp_Object help_echo_string;
743Lisp_Object help_echo_window;
744Lisp_Object help_echo_object;
745int help_echo_pos;
746
747/* Temporary variable for XTread_socket. */
748
749Lisp_Object previous_help_echo_string;
750
751
727 752
728/* Function prototypes. */ 753/* Function prototypes. */
729 754
@@ -858,6 +883,11 @@ static void update_tool_bar P_ ((struct frame *, int));
858static void build_desired_tool_bar_string P_ ((struct frame *f)); 883static void build_desired_tool_bar_string P_ ((struct frame *f));
859static int redisplay_tool_bar P_ ((struct frame *)); 884static int redisplay_tool_bar P_ ((struct frame *));
860static void display_tool_bar_line P_ ((struct it *)); 885static void display_tool_bar_line P_ ((struct it *));
886static void notice_overwritten_cursor P_ ((struct window *,
887 enum glyph_row_area,
888 int, int, int, int));
889
890
861 891
862#endif /* HAVE_WINDOW_SYSTEM */ 892#endif /* HAVE_WINDOW_SYSTEM */
863 893
@@ -1333,6 +1363,246 @@ compute_string_pos (newpos, pos, string)
1333 BYTEPOS (*newpos) = CHARPOS (*newpos); 1363 BYTEPOS (*newpos) = CHARPOS (*newpos);
1334} 1364}
1335 1365
1366/* EXPORT:
1367 Return an estimation of the pixel height of mode or top lines on
1368 frame F. FACE_ID specifies what line's height to estimate. */
1369
1370int
1371estimate_mode_line_height (f, face_id)
1372 struct frame *f;
1373 enum face_id face_id;
1374{
1375#ifdef HAVE_WINDOW_SYSTEM
1376 if (FRAME_WINDOW_P (f))
1377 {
1378 int height = FONT_HEIGHT (FRAME_FONT (f));
1379
1380 /* This function is called so early when Emacs starts that the face
1381 cache and mode line face are not yet initialized. */
1382 if (FRAME_FACE_CACHE (f))
1383 {
1384 struct face *face = FACE_FROM_ID (f, face_id);
1385 if (face)
1386 {
1387 if (face->font)
1388 height = FONT_HEIGHT (face->font);
1389 if (face->box_line_width > 0)
1390 height += 2 * face->box_line_width;
1391 }
1392 }
1393
1394 return height;
1395 }
1396#endif
1397
1398 return 1;
1399}
1400
1401#ifdef HAVE_WINDOW_SYSTEM
1402
1403/* Find the glyph under window-relative coordinates X/Y in window W.
1404 Consider only glyphs from buffer text, i.e. no glyphs from overlay
1405 strings. Return in *HPOS and *VPOS the row and column number of
1406 the glyph found. Return in *AREA the glyph area containing X.
1407 Value is a pointer to the glyph found or null if X/Y is not on
1408 text, or we can't tell because W's current matrix is not up to
1409 date. */
1410
1411static struct glyph *
1412x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
1413 struct window *w;
1414 int x, y;
1415 int *hpos, *vpos, *area;
1416 int buffer_only_p;
1417{
1418 struct glyph *glyph, *end;
1419 struct glyph_row *row = NULL;
1420 int x0, i, left_area_width;
1421
1422 /* Find row containing Y. Give up if some row is not enabled. */
1423 for (i = 0; i < w->current_matrix->nrows; ++i)
1424 {
1425 row = MATRIX_ROW (w->current_matrix, i);
1426 if (!row->enabled_p)
1427 return NULL;
1428 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
1429 break;
1430 }
1431
1432 *vpos = i;
1433 *hpos = 0;
1434
1435 /* Give up if Y is not in the window. */
1436 if (i == w->current_matrix->nrows)
1437 return NULL;
1438
1439 /* Get the glyph area containing X. */
1440 if (w->pseudo_window_p)
1441 {
1442 *area = TEXT_AREA;
1443 x0 = 0;
1444 }
1445 else
1446 {
1447 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
1448 if (x < left_area_width)
1449 {
1450 *area = LEFT_MARGIN_AREA;
1451 x0 = 0;
1452 }
1453 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
1454 {
1455 *area = TEXT_AREA;
1456 x0 = row->x + left_area_width;
1457 }
1458 else
1459 {
1460 *area = RIGHT_MARGIN_AREA;
1461 x0 = left_area_width + window_box_width (w, TEXT_AREA);
1462 }
1463 }
1464
1465 /* Find glyph containing X. */
1466 glyph = row->glyphs[*area];
1467 end = glyph + row->used[*area];
1468 while (glyph < end)
1469 {
1470 if (x < x0 + glyph->pixel_width)
1471 {
1472 if (w->pseudo_window_p)
1473 break;
1474 else if (!buffer_only_p || BUFFERP (glyph->object))
1475 break;
1476 }
1477
1478 x0 += glyph->pixel_width;
1479 ++glyph;
1480 }
1481
1482 if (glyph == end)
1483 return NULL;
1484
1485 *hpos = glyph - row->glyphs[*area];
1486 return glyph;
1487}
1488
1489
1490/* EXPORT:
1491 Convert frame-relative x/y to coordinates relative to window W.
1492 Takes pseudo-windows into account. */
1493
1494void
1495frame_to_window_pixel_xy (w, x, y)
1496 struct window *w;
1497 int *x, *y;
1498{
1499 if (w->pseudo_window_p)
1500 {
1501 /* A pseudo-window is always full-width, and starts at the
1502 left edge of the frame, plus a frame border. */
1503 struct frame *f = XFRAME (w->frame);
1504 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
1505 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
1506 }
1507 else
1508 {
1509 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
1510 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
1511 }
1512}
1513
1514/* EXPORT:
1515 Return in *R the clipping rectangle for glyph string S. */
1516
1517void
1518get_glyph_string_clip_rect (s, nr)
1519 struct glyph_string *s;
1520 NativeRectangle *nr;
1521{
1522 XRectangle r;
1523
1524 if (s->row->full_width_p)
1525 {
1526 /* Draw full-width. X coordinates are relative to S->w->left. */
1527 int canon_x = CANON_X_UNIT (s->f);
1528
1529 r.x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
1530 r.width = XFASTINT (s->w->width) * canon_x;
1531
1532 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
1533 {
1534 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
1535 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
1536 r.x -= width;
1537 }
1538
1539 r.x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
1540
1541 /* Unless displaying a mode or menu bar line, which are always
1542 fully visible, clip to the visible part of the row. */
1543 if (s->w->pseudo_window_p)
1544 r.height = s->row->visible_height;
1545 else
1546 r.height = s->height;
1547 }
1548 else
1549 {
1550 /* This is a text line that may be partially visible. */
1551 r.x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
1552 r.width = window_box_width (s->w, s->area);
1553 r.height = s->row->visible_height;
1554 }
1555
1556 /* If S draws overlapping rows, it's sufficient to use the top and
1557 bottom of the window for clipping because this glyph string
1558 intentionally draws over other lines. */
1559 if (s->for_overlaps_p)
1560 {
1561 r.y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
1562 r.height = window_text_bottom_y (s->w) - r.y;
1563 }
1564 else
1565 {
1566 /* Don't use S->y for clipping because it doesn't take partially
1567 visible lines into account. For example, it can be negative for
1568 partially visible lines at the top of a window. */
1569 if (!s->row->full_width_p
1570 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
1571 r.y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
1572 else
1573 r.y = max (0, s->row->y);
1574
1575 /* If drawing a tool-bar window, draw it over the internal border
1576 at the top of the window. */
1577 if (s->w == XWINDOW (s->f->tool_bar_window))
1578 r.y -= s->f->output_data.x->internal_border_width;
1579 }
1580
1581 r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
1582
1583#ifdef HAVE_NTGUI
1584 /* ++KFS: From W32 port, but it looks ok for all platforms to me. */
1585 /* If drawing the cursor, don't let glyph draw outside its
1586 advertised boundaries. Cleartype does this under some circumstances. */
1587 if (s->hl == DRAW_CURSOR)
1588 {
1589 if (s->x > r.x)
1590 {
1591 r.width -= s->x - r.x;
1592 r.x = s->x;
1593 }
1594 r.width = min (r.width, s->first_glyph->pixel_width);
1595 }
1596#endif
1597
1598#ifdef CONVERT_FROM_XRECT
1599 CONVERT_FROM_XRECT (r, *nr);
1600#else
1601 *nr = r;
1602#endif;
1603}
1604
1605#endif /* HAVE_WINDOW_SYSTEM */
1336 1606
1337 1607
1338/*********************************************************************** 1608/***********************************************************************
@@ -6711,7 +6981,7 @@ resize_mini_window (w, exact_p)
6711 6981
6712 /* Nil means don't try to resize. */ 6982 /* Nil means don't try to resize. */
6713 if (NILP (Vresize_mini_windows) 6983 if (NILP (Vresize_mini_windows)
6714 || (FRAME_X_P (f) && f->output_data.x == NULL)) 6984 || (FRAME_X_P (f) && FRAME_X_OUTPUT (f) == NULL))
6715 return 0; 6985 return 0;
6716 6986
6717 if (!FRAME_MINIBUF_ONLY_P (f)) 6987 if (!FRAME_MINIBUF_ONLY_P (f))
@@ -7614,11 +7884,91 @@ update_menu_bar (f, save_match_data)
7614 7884
7615 7885
7616/*********************************************************************** 7886/***********************************************************************
7887 Output Cursor
7888 ***********************************************************************/
7889
7890/* EXPORT:
7891 Nominal cursor position -- where to draw output.
7892 HPOS and VPOS are window relative glyph matrix coordinates.
7893 X and Y are window relative pixel coordinates. */
7894
7895struct cursor_pos output_cursor;
7896
7897
7898/* EXPORT:
7899 Set the global variable output_cursor to CURSOR. All cursor
7900 positions are relative to updated_window. */
7901
7902void
7903set_output_cursor (cursor)
7904 struct cursor_pos *cursor;
7905{
7906 output_cursor.hpos = cursor->hpos;
7907 output_cursor.vpos = cursor->vpos;
7908 output_cursor.x = cursor->x;
7909 output_cursor.y = cursor->y;
7910}
7911
7912
7913/* EXPORT for RIF:
7914 Set a nominal cursor position.
7915
7916 HPOS and VPOS are column/row positions in a window glyph matrix. X
7917 and Y are window text area relative pixel positions.
7918
7919 If this is done during an update, updated_window will contain the
7920 window that is being updated and the position is the future output
7921 cursor position for that window. If updated_window is null, use
7922 selected_window and display the cursor at the given position. */
7923
7924void
7925x_cursor_to (vpos, hpos, y, x)
7926 int vpos, hpos, y, x;
7927{
7928 struct window *w;
7929
7930 /* If updated_window is not set, work on selected_window. */
7931 if (updated_window)
7932 w = updated_window;
7933 else
7934 w = XWINDOW (selected_window);
7935
7936 /* Set the output cursor. */
7937 output_cursor.hpos = hpos;
7938 output_cursor.vpos = vpos;
7939 output_cursor.x = x;
7940 output_cursor.y = y;
7941
7942 /* If not called as part of an update, really display the cursor.
7943 This will also set the cursor position of W. */
7944 if (updated_window == NULL)
7945 {
7946 BLOCK_INPUT;
7947 display_and_set_cursor (w, 1, hpos, vpos, x, y);
7948 if (rif->flush_display_optional)
7949 rif->flush_display_optional (SELECTED_FRAME ());
7950 UNBLOCK_INPUT;
7951 }
7952}
7953
7954
7955
7956/***********************************************************************
7617 Tool-bars 7957 Tool-bars
7618 ***********************************************************************/ 7958 ***********************************************************************/
7619 7959
7620#ifdef HAVE_WINDOW_SYSTEM 7960#ifdef HAVE_WINDOW_SYSTEM
7621 7961
7962/* Where the mouse was last time we reported a mouse event. */
7963
7964FRAME_PTR last_mouse_frame;
7965
7966/* Tool-bar item index of the item on which a mouse button was pressed
7967 or -1. */
7968
7969int last_tool_bar_item;
7970
7971
7622/* Update the tool-bar item list for frame F. This has to be done 7972/* Update the tool-bar item list for frame F. This has to be done
7623 before we start to fill in any display lines. Called from 7973 before we start to fill in any display lines. Called from
7624 prepare_menu_bars. If SAVE_MATCH_DATA is non-zero, we must save 7974 prepare_menu_bars. If SAVE_MATCH_DATA is non-zero, we must save
@@ -8102,7 +8452,7 @@ redisplay_tool_bar (f)
8102 properties start in F->tool_bar_items. Value is zero if 8452 properties start in F->tool_bar_items. Value is zero if
8103 GLYPH doesn't display a tool-bar item. */ 8453 GLYPH doesn't display a tool-bar item. */
8104 8454
8105int 8455static int
8106tool_bar_item_info (f, glyph, prop_idx) 8456tool_bar_item_info (f, glyph, prop_idx)
8107 struct frame *f; 8457 struct frame *f;
8108 struct glyph *glyph; 8458 struct glyph *glyph;
@@ -8134,6 +8484,208 @@ tool_bar_item_info (f, glyph, prop_idx)
8134 return success_p; 8484 return success_p;
8135} 8485}
8136 8486
8487
8488/* Get information about the tool-bar item at position X/Y on frame F.
8489 Return in *GLYPH a pointer to the glyph of the tool-bar item in
8490 the current matrix of the tool-bar window of F, or NULL if not
8491 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
8492 item in F->tool_bar_items. Value is
8493
8494 -1 if X/Y is not on a tool-bar item
8495 0 if X/Y is on the same item that was highlighted before.
8496 1 otherwise. */
8497
8498static int
8499get_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
8500 struct frame *f;
8501 int x, y;
8502 struct glyph **glyph;
8503 int *hpos, *vpos, *prop_idx;
8504{
8505 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8506 struct window *w = XWINDOW (f->tool_bar_window);
8507 int area;
8508
8509 /* Find the glyph under X/Y. */
8510 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
8511 if (*glyph == NULL)
8512 return -1;
8513
8514 /* Get the start of this tool-bar item's properties in
8515 f->tool_bar_items. */
8516 if (!tool_bar_item_info (f, *glyph, prop_idx))
8517 return -1;
8518
8519 /* Is mouse on the highlighted item? */
8520 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
8521 && *vpos >= dpyinfo->mouse_face_beg_row
8522 && *vpos <= dpyinfo->mouse_face_end_row
8523 && (*vpos > dpyinfo->mouse_face_beg_row
8524 || *hpos >= dpyinfo->mouse_face_beg_col)
8525 && (*vpos < dpyinfo->mouse_face_end_row
8526 || *hpos < dpyinfo->mouse_face_end_col
8527 || dpyinfo->mouse_face_past_end))
8528 return 0;
8529
8530 return 1;
8531}
8532
8533
8534/* EXPORT:
8535 Handle mouse button event on the tool-bar of frame F, at
8536 frame-relative coordinates X/Y. DOWN_P is 1 for a button press,
8537 0 for button release. MODIFIERS is event modifiers for button
8538 release. */
8539
8540void
8541handle_tool_bar_click (f, x, y, down_p, modifiers)
8542 struct frame *f;
8543 int x, y, down_p;
8544 unsigned int modifiers;
8545{
8546 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8547 struct window *w = XWINDOW (f->tool_bar_window);
8548 int hpos, vpos, prop_idx;
8549 struct glyph *glyph;
8550 Lisp_Object enabled_p;
8551
8552 /* If not on the highlighted tool-bar item, return. */
8553 frame_to_window_pixel_xy (w, &x, &y);
8554 if (get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
8555 return;
8556
8557 /* If item is disabled, do nothing. */
8558 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
8559 if (NILP (enabled_p))
8560 return;
8561
8562 if (down_p)
8563 {
8564 /* Show item in pressed state. */
8565 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
8566 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
8567 last_tool_bar_item = prop_idx;
8568 }
8569 else
8570 {
8571 Lisp_Object key, frame;
8572 struct input_event event;
8573
8574 /* Show item in released state. */
8575 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
8576 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
8577
8578 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
8579
8580 XSETFRAME (frame, f);
8581 event.kind = TOOL_BAR_EVENT;
8582 event.frame_or_window = frame;
8583 event.arg = frame;
8584 kbd_buffer_store_event (&event);
8585
8586 event.kind = TOOL_BAR_EVENT;
8587 event.frame_or_window = frame;
8588 event.arg = key;
8589 event.modifiers = modifiers;
8590 kbd_buffer_store_event (&event);
8591 last_tool_bar_item = -1;
8592 }
8593}
8594
8595
8596/* Possibly highlight a tool-bar item on frame F when mouse moves to
8597 tool-bar window-relative coordinates X/Y. Called from
8598 note_mouse_highlight. */
8599
8600static void
8601note_tool_bar_highlight (f, x, y)
8602 struct frame *f;
8603 int x, y;
8604{
8605 Lisp_Object window = f->tool_bar_window;
8606 struct window *w = XWINDOW (window);
8607 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8608 int hpos, vpos;
8609 struct glyph *glyph;
8610 struct glyph_row *row;
8611 int i;
8612 Lisp_Object enabled_p;
8613 int prop_idx;
8614 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
8615 int mouse_down_p, rc;
8616
8617 /* Function note_mouse_highlight is called with negative x(y
8618 values when mouse moves outside of the frame. */
8619 if (x <= 0 || y <= 0)
8620 {
8621 clear_mouse_face (dpyinfo);
8622 return;
8623 }
8624
8625 rc = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
8626 if (rc < 0)
8627 {
8628 /* Not on tool-bar item. */
8629 clear_mouse_face (dpyinfo);
8630 return;
8631 }
8632 else if (rc == 0)
8633 /* On same tool-bar item as before. */
8634 goto set_help_echo;
8635
8636 clear_mouse_face (dpyinfo);
8637
8638 /* Mouse is down, but on different tool-bar item? */
8639 mouse_down_p = (dpyinfo->grabbed
8640 && f == last_mouse_frame
8641 && FRAME_LIVE_P (f));
8642 if (mouse_down_p
8643 && last_tool_bar_item != prop_idx)
8644 return;
8645
8646 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
8647 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
8648
8649 /* If tool-bar item is not enabled, don't highlight it. */
8650 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
8651 if (!NILP (enabled_p))
8652 {
8653 /* Compute the x-position of the glyph. In front and past the
8654 image is a space. We include this is the highlighted area. */
8655 row = MATRIX_ROW (w->current_matrix, vpos);
8656 for (i = x = 0; i < hpos; ++i)
8657 x += row->glyphs[TEXT_AREA][i].pixel_width;
8658
8659 /* Record this as the current active region. */
8660 dpyinfo->mouse_face_beg_col = hpos;
8661 dpyinfo->mouse_face_beg_row = vpos;
8662 dpyinfo->mouse_face_beg_x = x;
8663 dpyinfo->mouse_face_beg_y = row->y;
8664 dpyinfo->mouse_face_past_end = 0;
8665
8666 dpyinfo->mouse_face_end_col = hpos + 1;
8667 dpyinfo->mouse_face_end_row = vpos;
8668 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
8669 dpyinfo->mouse_face_end_y = row->y;
8670 dpyinfo->mouse_face_window = window;
8671 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
8672
8673 /* Display it as active. */
8674 show_mouse_face (dpyinfo, draw);
8675 dpyinfo->mouse_face_image_state = draw;
8676 }
8677
8678 set_help_echo:
8679
8680 /* Set help_echo_string to a help string to display for this tool-bar item.
8681 XTread_socket does the rest. */
8682 help_echo_object = help_echo_window = Qnil;
8683 help_echo_pos = -1;
8684 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
8685 if (NILP (help_echo_string))
8686 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
8687}
8688
8137#endif /* HAVE_WINDOW_SYSTEM */ 8689#endif /* HAVE_WINDOW_SYSTEM */
8138 8690
8139 8691
@@ -11463,7 +12015,7 @@ try_window_reusing_current_matrix (w)
11463 { 12015 {
11464 update_begin (f); 12016 update_begin (f);
11465 rif->update_window_begin_hook (w); 12017 rif->update_window_begin_hook (w);
11466 rif->clear_mouse_face (w); 12018 rif->clear_window_mouse_face (w);
11467 rif->scroll_run_hook (w, &run); 12019 rif->scroll_run_hook (w, &run);
11468 rif->update_window_end_hook (w, 0, 0); 12020 rif->update_window_end_hook (w, 0, 0);
11469 update_end (f); 12021 update_end (f);
@@ -11635,7 +12187,7 @@ try_window_reusing_current_matrix (w)
11635 struct frame *f = XFRAME (WINDOW_FRAME (w)); 12187 struct frame *f = XFRAME (WINDOW_FRAME (w));
11636 update_begin (f); 12188 update_begin (f);
11637 rif->update_window_begin_hook (w); 12189 rif->update_window_begin_hook (w);
11638 rif->clear_mouse_face (w); 12190 rif->clear_window_mouse_face (w);
11639 rif->scroll_run_hook (w, &run); 12191 rif->scroll_run_hook (w, &run);
11640 rif->update_window_end_hook (w, 0, 0); 12192 rif->update_window_end_hook (w, 0, 0);
11641 update_end (f); 12193 update_end (f);
@@ -12463,7 +13015,7 @@ try_window_id (w)
12463 if (FRAME_WINDOW_P (f)) 13015 if (FRAME_WINDOW_P (f))
12464 { 13016 {
12465 rif->update_window_begin_hook (w); 13017 rif->update_window_begin_hook (w);
12466 rif->clear_mouse_face (w); 13018 rif->clear_window_mouse_face (w);
12467 rif->scroll_run_hook (w, &run); 13019 rif->scroll_run_hook (w, &run);
12468 rif->update_window_end_hook (w, 0, 0); 13020 rif->update_window_end_hook (w, 0, 0);
12469 } 13021 }
@@ -16337,7 +16889,7 @@ compute_overhangs_and_x (s, x, backward_p)
16337 16889
16338 16890
16339 16891
16340/* The following macros are only called from x_draw_glyphs below. 16892/* The following macros are only called from draw_glyphs below.
16341 They reference the following parameters of that function directly: 16893 They reference the following parameters of that function directly:
16342 `w', `row', `area', and `overlap_p' 16894 `w', `row', `area', and `overlap_p'
16343 as well as the following local variables: 16895 as well as the following local variables:
@@ -16487,7 +17039,7 @@ compute_overhangs_and_x (s, x, backward_p)
16487 x-positions of the drawing area. 17039 x-positions of the drawing area.
16488 17040
16489 This is an ugly monster macro construct because we must use alloca 17041 This is an ugly monster macro construct because we must use alloca
16490 to allocate glyph strings (because x_draw_glyphs can be called 17042 to allocate glyph strings (because draw_glyphs can be called
16491 asynchronously). */ 17043 asynchronously). */
16492 17044
16493#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ 17045#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
@@ -16546,8 +17098,8 @@ compute_overhangs_and_x (s, x, backward_p)
16546 17098
16547 Value is the x-position reached, relative to AREA of W. */ 17099 Value is the x-position reached, relative to AREA of W. */
16548 17100
16549int 17101static int
16550x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) 17102draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
16551 struct window *w; 17103 struct window *w;
16552 int x; 17104 int x;
16553 struct glyph_row *row; 17105 struct glyph_row *row;
@@ -17648,6 +18200,181 @@ x_produce_glyphs (it)
17648 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent); 18200 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
17649} 18201}
17650 18202
18203/* EXPORT for RIF:
18204 Output LEN glyphs starting at START at the nominal cursor position.
18205 Advance the nominal cursor over the text. The global variable
18206 updated_window contains the window being updated, updated_row is
18207 the glyph row being updated, and updated_area is the area of that
18208 row being updated. */
18209
18210void
18211x_write_glyphs (start, len)
18212 struct glyph *start;
18213 int len;
18214{
18215 int x, hpos;
18216
18217 xassert (updated_window && updated_row);
18218 BLOCK_INPUT;
18219
18220 /* Write glyphs. */
18221
18222 hpos = start - updated_row->glyphs[updated_area];
18223 x = draw_glyphs (updated_window, output_cursor.x,
18224 updated_row, updated_area,
18225 hpos, hpos + len,
18226 DRAW_NORMAL_TEXT, 0);
18227
18228#ifndef HAVE_CARBON
18229 /* ++KFS: Why not on MAC ? */
18230
18231 /* Invalidate old phys cursor if the glyph at its hpos is redrawn. */
18232 if (updated_area == TEXT_AREA
18233 && updated_window->phys_cursor_on_p
18234 && updated_window->phys_cursor.vpos == output_cursor.vpos
18235 && updated_window->phys_cursor.hpos >= hpos
18236 && updated_window->phys_cursor.hpos < hpos + len)
18237 updated_window->phys_cursor_on_p = 0;
18238#endif
18239
18240 UNBLOCK_INPUT;
18241
18242 /* Advance the output cursor. */
18243 output_cursor.hpos += len;
18244 output_cursor.x = x;
18245}
18246
18247
18248/* EXPORT for RIF:
18249 Insert LEN glyphs from START at the nominal cursor position. */
18250
18251void
18252x_insert_glyphs (start, len)
18253 struct glyph *start;
18254 int len;
18255{
18256 struct frame *f;
18257 struct window *w;
18258 int line_height, shift_by_width, shifted_region_width;
18259 struct glyph_row *row;
18260 struct glyph *glyph;
18261 int frame_x, frame_y, hpos;
18262
18263 xassert (updated_window && updated_row);
18264 BLOCK_INPUT;
18265 w = updated_window;
18266 f = XFRAME (WINDOW_FRAME (w));
18267
18268 /* Get the height of the line we are in. */
18269 row = updated_row;
18270 line_height = row->height;
18271
18272 /* Get the width of the glyphs to insert. */
18273 shift_by_width = 0;
18274 for (glyph = start; glyph < start + len; ++glyph)
18275 shift_by_width += glyph->pixel_width;
18276
18277 /* Get the width of the region to shift right. */
18278 shifted_region_width = (window_box_width (w, updated_area)
18279 - output_cursor.x
18280 - shift_by_width);
18281
18282 /* Shift right. */
18283 frame_x = window_box_left (w, updated_area) + output_cursor.x;
18284 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
18285
18286 rif->shift_glyphs_for_insert (f, frame_x, frame_y, line_height,
18287 shifted_region_width, shift_by_width);
18288
18289 /* Write the glyphs. */
18290 hpos = start - row->glyphs[updated_area];
18291 draw_glyphs (w, output_cursor.x, row, updated_area,
18292 hpos, hpos + len,
18293 DRAW_NORMAL_TEXT, 0);
18294
18295 /* Advance the output cursor. */
18296 output_cursor.hpos += len;
18297 output_cursor.x += shift_by_width;
18298 UNBLOCK_INPUT;
18299}
18300
18301
18302/* EXPORT for RIF:
18303 Erase the current text line from the nominal cursor position
18304 (inclusive) to pixel column TO_X (exclusive). The idea is that
18305 everything from TO_X onward is already erased.
18306
18307 TO_X is a pixel position relative to updated_area of
18308 updated_window. TO_X == -1 means clear to the end of this area. */
18309
18310void
18311x_clear_end_of_line (to_x)
18312 int to_x;
18313{
18314 struct frame *f;
18315 struct window *w = updated_window;
18316 int max_x, min_y, max_y;
18317 int from_x, from_y, to_y;
18318
18319 xassert (updated_window && updated_row);
18320 f = XFRAME (w->frame);
18321
18322 if (updated_row->full_width_p)
18323 {
18324 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
18325 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
18326 && !w->pseudo_window_p)
18327 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
18328 }
18329 else
18330 max_x = window_box_width (w, updated_area);
18331 max_y = window_text_bottom_y (w);
18332
18333 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
18334 of window. For TO_X > 0, truncate to end of drawing area. */
18335 if (to_x == 0)
18336 return;
18337 else if (to_x < 0)
18338 to_x = max_x;
18339 else
18340 to_x = min (to_x, max_x);
18341
18342 to_y = min (max_y, output_cursor.y + updated_row->height);
18343
18344 /* Notice if the cursor will be cleared by this operation. */
18345 if (!updated_row->full_width_p)
18346 notice_overwritten_cursor (w, updated_area,
18347 output_cursor.x, -1,
18348 updated_row->y,
18349 MATRIX_ROW_BOTTOM_Y (updated_row));
18350
18351 from_x = output_cursor.x;
18352
18353 /* Translate to frame coordinates. */
18354 if (updated_row->full_width_p)
18355 {
18356 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
18357 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
18358 }
18359 else
18360 {
18361 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
18362 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
18363 }
18364
18365 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
18366 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
18367 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
18368
18369 /* Prevent inadvertently clearing to end of the X window. */
18370 if (to_x > from_x && to_y > from_y)
18371 {
18372 BLOCK_INPUT;
18373 rif->clear_frame_area (f, from_x, from_y,
18374 to_x - from_x, to_y - from_y);
18375 UNBLOCK_INPUT;
18376 }
18377}
17651 18378
17652#endif /* HAVE_WINDOW_SYSTEM */ 18379#endif /* HAVE_WINDOW_SYSTEM */
17653 18380
@@ -17852,6 +18579,8 @@ get_window_cursor_type (w, width, active_cursor)
17852} 18579}
17853 18580
17854 18581
18582#ifdef HAVE_WINDOW_SYSTEM
18583
17855/* Notice when the text cursor of window W has been completely 18584/* Notice when the text cursor of window W has been completely
17856 overwritten by a drawing operation that outputs glyphs in AREA 18585 overwritten by a drawing operation that outputs glyphs in AREA
17857 starting at X0 and ending at X1 in the line starting at Y0 and 18586 starting at X0 and ending at X1 in the line starting at Y0 and
@@ -17859,7 +18588,7 @@ get_window_cursor_type (w, width, active_cursor)
17859 the rest of the line after X0 has been written. Y coordinates 18588 the rest of the line after X0 has been written. Y coordinates
17860 are window-relative. */ 18589 are window-relative. */
17861 18590
17862void 18591static void
17863notice_overwritten_cursor (w, area, x0, x1, y0, y1) 18592notice_overwritten_cursor (w, area, x0, x1, y0, y1)
17864 struct window *w; 18593 struct window *w;
17865 enum glyph_row_area area; 18594 enum glyph_row_area area;
@@ -17908,6 +18637,1893 @@ notice_overwritten_cursor (w, area, x0, x1, y0, y1)
17908#endif 18637#endif
17909} 18638}
17910 18639
18640#endif /* HAVE_WINDOW_SYSTEM */
18641
18642
18643/************************************************************************
18644 Mouse Face
18645 ************************************************************************/
18646
18647#ifdef HAVE_WINDOW_SYSTEM
18648
18649/* EXPORT for RIF:
18650 Fix the display of area AREA of overlapping row ROW in window W. */
18651
18652void
18653x_fix_overlapping_area (w, row, area)
18654 struct window *w;
18655 struct glyph_row *row;
18656 enum glyph_row_area area;
18657{
18658 int i, x;
18659
18660 BLOCK_INPUT;
18661
18662 if (area == LEFT_MARGIN_AREA)
18663 x = 0;
18664 else if (area == TEXT_AREA)
18665 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
18666 else
18667 x = (window_box_width (w, LEFT_MARGIN_AREA)
18668 + window_box_width (w, TEXT_AREA));
18669
18670 for (i = 0; i < row->used[area];)
18671 {
18672 if (row->glyphs[area][i].overlaps_vertically_p)
18673 {
18674 int start = i, start_x = x;
18675
18676 do
18677 {
18678 x += row->glyphs[area][i].pixel_width;
18679 ++i;
18680 }
18681 while (i < row->used[area]
18682 && row->glyphs[area][i].overlaps_vertically_p);
18683
18684 draw_glyphs (w, start_x, row, area,
18685 start, i,
18686 DRAW_NORMAL_TEXT, 1);
18687 }
18688 else
18689 {
18690 x += row->glyphs[area][i].pixel_width;
18691 ++i;
18692 }
18693 }
18694
18695 UNBLOCK_INPUT;
18696}
18697
18698
18699/* EXPORT:
18700 Draw the cursor glyph of window W in glyph row ROW. See the
18701 comment of draw_glyphs for the meaning of HL. */
18702
18703void
18704draw_phys_cursor_glyph (w, row, hl)
18705 struct window *w;
18706 struct glyph_row *row;
18707 enum draw_glyphs_face hl;
18708{
18709 /* If cursor hpos is out of bounds, don't draw garbage. This can
18710 happen in mini-buffer windows when switching between echo area
18711 glyphs and mini-buffer. */
18712 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
18713 {
18714 int on_p = w->phys_cursor_on_p;
18715 int x1;
18716 x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
18717 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
18718 hl, 0);
18719 w->phys_cursor_on_p = on_p;
18720
18721#ifndef HAVE_CARBON
18722 /* ++KFS: MAC version did not adjust phys_cursor_width (bug?) */
18723 if (hl == DRAW_CURSOR)
18724 w->phys_cursor_width = x1 - w->phys_cursor.x;
18725 else
18726#endif
18727 /* When we erase the cursor, and ROW is overlapped by other
18728 rows, make sure that these overlapping parts of other rows
18729 are redrawn. */
18730 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
18731 {
18732 if (row > w->current_matrix->rows
18733 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
18734 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
18735
18736 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
18737 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
18738 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
18739 }
18740 }
18741}
18742
18743
18744/* EXPORT:
18745 Erase the image of a cursor of window W from the screen. */
18746
18747void
18748erase_phys_cursor (w)
18749 struct window *w;
18750{
18751 struct frame *f = XFRAME (w->frame);
18752 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
18753 int hpos = w->phys_cursor.hpos;
18754 int vpos = w->phys_cursor.vpos;
18755 int mouse_face_here_p = 0;
18756 struct glyph_matrix *active_glyphs = w->current_matrix;
18757 struct glyph_row *cursor_row;
18758 struct glyph *cursor_glyph;
18759 enum draw_glyphs_face hl;
18760
18761 /* No cursor displayed or row invalidated => nothing to do on the
18762 screen. */
18763 if (w->phys_cursor_type == NO_CURSOR)
18764 goto mark_cursor_off;
18765
18766 /* VPOS >= active_glyphs->nrows means that window has been resized.
18767 Don't bother to erase the cursor. */
18768 if (vpos >= active_glyphs->nrows)
18769 goto mark_cursor_off;
18770
18771 /* If row containing cursor is marked invalid, there is nothing we
18772 can do. */
18773 cursor_row = MATRIX_ROW (active_glyphs, vpos);
18774 if (!cursor_row->enabled_p)
18775 goto mark_cursor_off;
18776
18777 /* If row is completely invisible, don't attempt to delete a cursor which
18778 isn't there. This can happen if cursor is at top of a window, and
18779 we switch to a buffer with a header line in that window. */
18780 if (cursor_row->visible_height <= 0)
18781 goto mark_cursor_off;
18782
18783 /* This can happen when the new row is shorter than the old one.
18784 In this case, either draw_glyphs or clear_end_of_line
18785 should have cleared the cursor. Note that we wouldn't be
18786 able to erase the cursor in this case because we don't have a
18787 cursor glyph at hand. */
18788 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
18789 goto mark_cursor_off;
18790
18791 /* If the cursor is in the mouse face area, redisplay that when
18792 we clear the cursor. */
18793 if (! NILP (dpyinfo->mouse_face_window)
18794 && w == XWINDOW (dpyinfo->mouse_face_window)
18795 && (vpos > dpyinfo->mouse_face_beg_row
18796 || (vpos == dpyinfo->mouse_face_beg_row
18797 && hpos >= dpyinfo->mouse_face_beg_col))
18798 && (vpos < dpyinfo->mouse_face_end_row
18799 || (vpos == dpyinfo->mouse_face_end_row
18800 && hpos < dpyinfo->mouse_face_end_col))
18801 /* Don't redraw the cursor's spot in mouse face if it is at the
18802 end of a line (on a newline). The cursor appears there, but
18803 mouse highlighting does not. */
18804 && cursor_row->used[TEXT_AREA] > hpos)
18805 mouse_face_here_p = 1;
18806
18807 /* Maybe clear the display under the cursor. */
18808 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
18809 {
18810 int x, y;
18811 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
18812
18813 cursor_glyph = get_phys_cursor_glyph (w);
18814 if (cursor_glyph == NULL)
18815 goto mark_cursor_off;
18816
18817 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
18818 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y));
18819
18820 rif->clear_frame_area (f, x, y,
18821 cursor_glyph->pixel_width, cursor_row->visible_height);
18822 }
18823
18824 /* Erase the cursor by redrawing the character underneath it. */
18825 if (mouse_face_here_p)
18826 hl = DRAW_MOUSE_FACE;
18827 else
18828 hl = DRAW_NORMAL_TEXT;
18829 draw_phys_cursor_glyph (w, cursor_row, hl);
18830
18831 mark_cursor_off:
18832 w->phys_cursor_on_p = 0;
18833 w->phys_cursor_type = NO_CURSOR;
18834}
18835
18836
18837/* EXPORT:
18838 Display or clear cursor of window W. If ON is zero, clear the
18839 cursor. If it is non-zero, display the cursor. If ON is nonzero,
18840 where to put the cursor is specified by HPOS, VPOS, X and Y. */
18841
18842void
18843display_and_set_cursor (w, on, hpos, vpos, x, y)
18844 struct window *w;
18845 int on, hpos, vpos, x, y;
18846{
18847 struct frame *f = XFRAME (w->frame);
18848 int new_cursor_type;
18849 int new_cursor_width;
18850 int active_cursor;
18851 struct glyph_matrix *current_glyphs;
18852 struct glyph_row *glyph_row;
18853 struct glyph *glyph;
18854
18855 /* This is pointless on invisible frames, and dangerous on garbaged
18856 windows and frames; in the latter case, the frame or window may
18857 be in the midst of changing its size, and x and y may be off the
18858 window. */
18859 if (! FRAME_VISIBLE_P (f)
18860 || FRAME_GARBAGED_P (f)
18861 || vpos >= w->current_matrix->nrows
18862 || hpos >= w->current_matrix->matrix_w)
18863 return;
18864
18865 /* If cursor is off and we want it off, return quickly. */
18866 if (!on && !w->phys_cursor_on_p)
18867 return;
18868
18869 current_glyphs = w->current_matrix;
18870 glyph_row = MATRIX_ROW (current_glyphs, vpos);
18871 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
18872
18873 /* If cursor row is not enabled, we don't really know where to
18874 display the cursor. */
18875 if (!glyph_row->enabled_p)
18876 {
18877 w->phys_cursor_on_p = 0;
18878 return;
18879 }
18880
18881 xassert (interrupt_input_blocked);
18882
18883 /* Set new_cursor_type to the cursor we want to be displayed. */
18884 new_cursor_type = get_window_cursor_type (w, &new_cursor_width, &active_cursor);
18885
18886 /* If cursor is currently being shown and we don't want it to be or
18887 it is in the wrong place, or the cursor type is not what we want,
18888 erase it. */
18889 if (w->phys_cursor_on_p
18890 && (!on
18891 || w->phys_cursor.x != x
18892 || w->phys_cursor.y != y
18893 || new_cursor_type != w->phys_cursor_type
18894 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
18895 && new_cursor_width != w->phys_cursor_width)))
18896 erase_phys_cursor (w);
18897
18898 /* Don't check phys_cursor_on_p here because that flag is only set
18899 to zero in some cases where we know that the cursor has been
18900 completely erased, to avoid the extra work of erasing the cursor
18901 twice. In other words, phys_cursor_on_p can be 1 and the cursor
18902 still not be visible, or it has only been partly erased. */
18903 if (on)
18904 {
18905 w->phys_cursor_ascent = glyph_row->ascent;
18906 w->phys_cursor_height = glyph_row->height;
18907
18908 /* Set phys_cursor_.* before x_draw_.* is called because some
18909 of them may need the information. */
18910 w->phys_cursor.x = x;
18911 w->phys_cursor.y = glyph_row->y;
18912 w->phys_cursor.hpos = hpos;
18913 w->phys_cursor.vpos = vpos;
18914 }
18915
18916 rif->draw_window_cursor (w, glyph_row, on, x, y,
18917 new_cursor_type, new_cursor_width);
18918}
18919
18920
18921/* Switch the display of W's cursor on or off, according to the value
18922 of ON. */
18923
18924static void
18925update_window_cursor (w, on)
18926 struct window *w;
18927 int on;
18928{
18929 /* Don't update cursor in windows whose frame is in the process
18930 of being deleted. */
18931 if (w->current_matrix)
18932 {
18933 BLOCK_INPUT;
18934 display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
18935 w->phys_cursor.x, w->phys_cursor.y);
18936 UNBLOCK_INPUT;
18937 }
18938}
18939
18940
18941/* Call update_window_cursor with parameter ON_P on all leaf windows
18942 in the window tree rooted at W. */
18943
18944static void
18945update_cursor_in_window_tree (w, on_p)
18946 struct window *w;
18947 int on_p;
18948{
18949 while (w)
18950 {
18951 if (!NILP (w->hchild))
18952 update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
18953 else if (!NILP (w->vchild))
18954 update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
18955 else
18956 update_window_cursor (w, on_p);
18957
18958 w = NILP (w->next) ? 0 : XWINDOW (w->next);
18959 }
18960}
18961
18962
18963/* EXPORT:
18964 Display the cursor on window W, or clear it, according to ON_P.
18965 Don't change the cursor's position. */
18966
18967void
18968x_update_cursor (f, on_p)
18969 struct frame *f;
18970 int on_p;
18971{
18972 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
18973}
18974
18975
18976/* EXPORT:
18977 Clear the cursor of window W to background color, and mark the
18978 cursor as not shown. This is used when the text where the cursor
18979 is is about to be rewritten. */
18980
18981void
18982x_clear_cursor (w)
18983 struct window *w;
18984{
18985 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
18986 update_window_cursor (w, 0);
18987}
18988
18989
18990/* EXPORT:
18991 Display the active region described by mouse_face_* according to DRAW. */
18992
18993void
18994show_mouse_face (dpyinfo, draw)
18995 Display_Info *dpyinfo;
18996 enum draw_glyphs_face draw;
18997{
18998 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
18999 struct frame *f = XFRAME (WINDOW_FRAME (w));
19000
19001 if (/* If window is in the process of being destroyed, don't bother
19002 to do anything. */
19003 w->current_matrix != NULL
19004 /* Don't update mouse highlight if hidden */
19005 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
19006 /* Recognize when we are called to operate on rows that don't exist
19007 anymore. This can happen when a window is split. */
19008 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
19009 {
19010 int phys_cursor_on_p = w->phys_cursor_on_p;
19011 struct glyph_row *row, *first, *last;
19012
19013 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
19014 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
19015
19016 for (row = first; row <= last && row->enabled_p; ++row)
19017 {
19018 int start_hpos, end_hpos, start_x;
19019
19020 /* For all but the first row, the highlight starts at column 0. */
19021 if (row == first)
19022 {
19023 start_hpos = dpyinfo->mouse_face_beg_col;
19024 start_x = dpyinfo->mouse_face_beg_x;
19025 }
19026 else
19027 {
19028 start_hpos = 0;
19029 start_x = 0;
19030 }
19031
19032 if (row == last)
19033 end_hpos = dpyinfo->mouse_face_end_col;
19034 else
19035 end_hpos = row->used[TEXT_AREA];
19036
19037 if (end_hpos > start_hpos)
19038 {
19039 draw_glyphs (w, start_x, row, TEXT_AREA,
19040 start_hpos, end_hpos,
19041 draw, 0);
19042
19043 row->mouse_face_p
19044 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
19045 }
19046 }
19047
19048 /* When we've written over the cursor, arrange for it to
19049 be displayed again. */
19050 if (phys_cursor_on_p && !w->phys_cursor_on_p)
19051 {
19052 BLOCK_INPUT;
19053 display_and_set_cursor (w, 1,
19054 w->phys_cursor.hpos, w->phys_cursor.vpos,
19055 w->phys_cursor.x, w->phys_cursor.y);
19056 UNBLOCK_INPUT;
19057 }
19058 }
19059
19060 /* Change the mouse cursor. */
19061 if (draw == DRAW_NORMAL_TEXT)
19062 rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
19063 else if (draw == DRAW_MOUSE_FACE)
19064 rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor);
19065 else
19066 rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor);
19067}
19068
19069/* EXPORT:
19070 Clear out the mouse-highlighted active region.
19071 Redraw it un-highlighted first. Value is non-zero if mouse
19072 face was actually drawn unhighlighted. */
19073
19074int
19075clear_mouse_face (dpyinfo)
19076 Display_Info *dpyinfo;
19077{
19078 int cleared = 0;
19079
19080 if (!NILP (dpyinfo->mouse_face_window))
19081 {
19082 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
19083 cleared = 1;
19084 }
19085
19086 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
19087 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
19088 dpyinfo->mouse_face_window = Qnil;
19089 dpyinfo->mouse_face_overlay = Qnil;
19090 return cleared;
19091}
19092
19093
19094/* EXPORT:
19095 Non-zero if physical cursor of window W is within mouse face. */
19096
19097int
19098cursor_in_mouse_face_p (w)
19099 struct window *w;
19100{
19101 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
19102 int in_mouse_face = 0;
19103
19104 if (WINDOWP (dpyinfo->mouse_face_window)
19105 && XWINDOW (dpyinfo->mouse_face_window) == w)
19106 {
19107 int hpos = w->phys_cursor.hpos;
19108 int vpos = w->phys_cursor.vpos;
19109
19110 if (vpos >= dpyinfo->mouse_face_beg_row
19111 && vpos <= dpyinfo->mouse_face_end_row
19112 && (vpos > dpyinfo->mouse_face_beg_row
19113 || hpos >= dpyinfo->mouse_face_beg_col)
19114 && (vpos < dpyinfo->mouse_face_end_row
19115 || hpos < dpyinfo->mouse_face_end_col
19116 || dpyinfo->mouse_face_past_end))
19117 in_mouse_face = 1;
19118 }
19119
19120 return in_mouse_face;
19121}
19122
19123
19124
19125
19126/* Find the glyph matrix position of buffer position CHARPOS in window
19127 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
19128 current glyphs must be up to date. If CHARPOS is above window
19129 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
19130 of last line in W. In the row containing CHARPOS, stop before glyphs
19131 having STOP as object. */
19132
19133#if 0 /* This is a version of fast_find_position that's more correct
19134 in the presence of hscrolling, for example. I didn't install
19135 it right away because the problem fixed is minor, it failed
19136 in 20.x as well, and I think it's too risky to install
19137 so near the release of 21.1. 2001-09-25 gerd. */
19138
19139static int
19140fast_find_position (w, charpos, hpos, vpos, x, y, stop)
19141 struct window *w;
19142 int charpos;
19143 int *hpos, *vpos, *x, *y;
19144 Lisp_Object stop;
19145{
19146 struct glyph_row *row, *first;
19147 struct glyph *glyph, *end;
19148 int i, past_end = 0;
19149
19150 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19151 row = row_containing_pos (w, charpos, first, NULL, 0);
19152 if (row == NULL)
19153 {
19154 if (charpos < MATRIX_ROW_START_CHARPOS (first))
19155 {
19156 *x = *y = *hpos = *vpos = 0;
19157 return 0;
19158 }
19159 else
19160 {
19161 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
19162 past_end = 1;
19163 }
19164 }
19165
19166 *x = row->x;
19167 *y = row->y;
19168 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
19169
19170 glyph = row->glyphs[TEXT_AREA];
19171 end = glyph + row->used[TEXT_AREA];
19172
19173 /* Skip over glyphs not having an object at the start of the row.
19174 These are special glyphs like truncation marks on terminal
19175 frames. */
19176 if (row->displays_text_p)
19177 while (glyph < end
19178 && INTEGERP (glyph->object)
19179 && !EQ (stop, glyph->object)
19180 && glyph->charpos < 0)
19181 {
19182 *x += glyph->pixel_width;
19183 ++glyph;
19184 }
19185
19186 while (glyph < end
19187 && !INTEGERP (glyph->object)
19188 && !EQ (stop, glyph->object)
19189 && (!BUFFERP (glyph->object)
19190 || glyph->charpos < charpos))
19191 {
19192 *x += glyph->pixel_width;
19193 ++glyph;
19194 }
19195
19196 *hpos = glyph - row->glyphs[TEXT_AREA];
19197 return past_end;
19198}
19199
19200#else /* not 0 */
19201
19202static int
19203fast_find_position (w, pos, hpos, vpos, x, y, stop)
19204 struct window *w;
19205 int pos;
19206 int *hpos, *vpos, *x, *y;
19207 Lisp_Object stop;
19208{
19209 int i;
19210 int lastcol;
19211 int maybe_next_line_p = 0;
19212 int line_start_position;
19213 int yb = window_text_bottom_y (w);
19214 struct glyph_row *row, *best_row;
19215 int row_vpos, best_row_vpos;
19216 int current_x;
19217
19218 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19219 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
19220
19221 while (row->y < yb)
19222 {
19223 if (row->used[TEXT_AREA])
19224 line_start_position = row->glyphs[TEXT_AREA]->charpos;
19225 else
19226 line_start_position = 0;
19227
19228 if (line_start_position > pos)
19229 break;
19230 /* If the position sought is the end of the buffer,
19231 don't include the blank lines at the bottom of the window. */
19232 else if (line_start_position == pos
19233 && pos == BUF_ZV (XBUFFER (w->buffer)))
19234 {
19235 maybe_next_line_p = 1;
19236 break;
19237 }
19238 else if (line_start_position > 0)
19239 {
19240 best_row = row;
19241 best_row_vpos = row_vpos;
19242 }
19243
19244 if (row->y + row->height >= yb)
19245 break;
19246
19247 ++row;
19248 ++row_vpos;
19249 }
19250
19251 /* Find the right column within BEST_ROW. */
19252 lastcol = 0;
19253 current_x = best_row->x;
19254 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
19255 {
19256 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
19257 int charpos = glyph->charpos;
19258
19259 if (BUFFERP (glyph->object))
19260 {
19261 if (charpos == pos)
19262 {
19263 *hpos = i;
19264 *vpos = best_row_vpos;
19265 *x = current_x;
19266 *y = best_row->y;
19267 return 1;
19268 }
19269 else if (charpos > pos)
19270 break;
19271 }
19272 else if (EQ (glyph->object, stop))
19273 break;
19274
19275 if (charpos > 0)
19276 lastcol = i;
19277 current_x += glyph->pixel_width;
19278 }
19279
19280 /* If we're looking for the end of the buffer,
19281 and we didn't find it in the line we scanned,
19282 use the start of the following line. */
19283 if (maybe_next_line_p)
19284 {
19285 ++best_row;
19286 ++best_row_vpos;
19287 lastcol = 0;
19288 current_x = best_row->x;
19289 }
19290
19291 *vpos = best_row_vpos;
19292 *hpos = lastcol + 1;
19293 *x = current_x;
19294 *y = best_row->y;
19295 return 0;
19296}
19297
19298#endif /* not 0 */
19299
19300
19301/* Find the position of the glyph for position POS in OBJECT in
19302 window W's current matrix, and return in *X, *Y the pixel
19303 coordinates, and return in *HPOS, *VPOS the column/row of the glyph.
19304
19305 RIGHT_P non-zero means return the position of the right edge of the
19306 glyph, RIGHT_P zero means return the left edge position.
19307
19308 If no glyph for POS exists in the matrix, return the position of
19309 the glyph with the next smaller position that is in the matrix, if
19310 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
19311 exists in the matrix, return the position of the glyph with the
19312 next larger position in OBJECT.
19313
19314 Value is non-zero if a glyph was found. */
19315
19316static int
19317fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
19318 struct window *w;
19319 int pos;
19320 Lisp_Object object;
19321 int *hpos, *vpos, *x, *y;
19322 int right_p;
19323{
19324 int yb = window_text_bottom_y (w);
19325 struct glyph_row *r;
19326 struct glyph *best_glyph = NULL;
19327 struct glyph_row *best_row = NULL;
19328 int best_x = 0;
19329
19330 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19331 r->enabled_p && r->y < yb;
19332 ++r)
19333 {
19334 struct glyph *g = r->glyphs[TEXT_AREA];
19335 struct glyph *e = g + r->used[TEXT_AREA];
19336 int gx;
19337
19338 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
19339 if (EQ (g->object, object))
19340 {
19341 if (g->charpos == pos)
19342 {
19343 best_glyph = g;
19344 best_x = gx;
19345 best_row = r;
19346 goto found;
19347 }
19348 else if (best_glyph == NULL
19349 || ((abs (g->charpos - pos)
19350 < abs (best_glyph->charpos - pos))
19351 && (right_p
19352 ? g->charpos < pos
19353 : g->charpos > pos)))
19354 {
19355 best_glyph = g;
19356 best_x = gx;
19357 best_row = r;
19358 }
19359 }
19360 }
19361
19362 found:
19363
19364 if (best_glyph)
19365 {
19366 *x = best_x;
19367 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
19368
19369 if (right_p)
19370 {
19371 *x += best_glyph->pixel_width;
19372 ++*hpos;
19373 }
19374
19375 *y = best_row->y;
19376 *vpos = best_row - w->current_matrix->rows;
19377 }
19378
19379 return best_glyph != NULL;
19380}
19381
19382
19383#ifdef HAVE_CARBON
19384
19385/* ++KFS: Why does MAC have its own version here? Looks like OLD CODE!! */
19386
19387/* Take proper action when mouse has moved to the mode or header line of
19388 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
19389 mode line. X is relative to the start of the text display area of
19390 W, so the width of fringes and scroll bars must be subtracted
19391 to get a position relative to the start of the mode line. */
19392
19393static void
19394note_mode_line_highlight (w, x, mode_line_p)
19395 struct window *w;
19396 int x, mode_line_p;
19397{
19398 struct frame *f = XFRAME (w->frame);
19399 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
19400 Cursor *cursor = dpyinfo->vertical_scroll_bar_cursor;
19401 struct glyph_row *row;
19402
19403 if (mode_line_p)
19404 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
19405 else
19406 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
19407
19408 if (row->enabled_p)
19409 {
19410 struct glyph *glyph, *end;
19411 Lisp_Object help, map;
19412 int x0;
19413
19414 /* Find the glyph under X. */
19415 glyph = row->glyphs[TEXT_AREA];
19416 end = glyph + row->used[TEXT_AREA];
19417 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
19418 + FRAME_X_LEFT_FRINGE_WIDTH (f));
19419
19420 while (glyph < end
19421 && x >= x0 + glyph->pixel_width)
19422 {
19423 x0 += glyph->pixel_width;
19424 ++glyph;
19425 }
19426
19427 if (glyph < end
19428 && STRINGP (glyph->object)
19429 && STRING_INTERVALS (glyph->object)
19430 && glyph->charpos >= 0
19431 && glyph->charpos < SCHARS (glyph->object))
19432 {
19433 /* If we're on a string with `help-echo' text property,
19434 arrange for the help to be displayed. This is done by
19435 setting the global variable help_echo_string to the help
19436 string. */
19437 help = Fget_text_property (make_number (glyph->charpos),
19438 Qhelp_echo, glyph->object);
19439 if (!NILP (help))
19440 {
19441 help_echo_string = help;
19442 XSETWINDOW (help_echo_window, w);
19443 help_echo_object = glyph->object;
19444 help_echo_pos = glyph->charpos;
19445 }
19446
19447 /* Change the mouse pointer according to what is under X/Y. */
19448 map = Fget_text_property (make_number (glyph->charpos),
19449 Qlocal_map, glyph->object);
19450 if (KEYMAPP (map))
19451 cursor = f->output_data.mac->nontext_cursor;
19452 else
19453 {
19454 map = Fget_text_property (make_number (glyph->charpos),
19455 Qkeymap, glyph->object);
19456 if (KEYMAPP (map))
19457 cursor = f->output_data.mac->nontext_cursor;
19458 }
19459 }
19460 }
19461
19462 rif->define_frame_cursor (f, cursor);
19463}
19464
19465#else
19466
19467/* Take proper action when mouse has moved to the mode or header line
19468 or marginal area AREA of window W, x-position X and y-position Y.
19469 X is relative to the start of the text display area of W, so the
19470 width of bitmap areas and scroll bars must be subtracted to get a
19471 position relative to the start of the mode line. */
19472
19473static void
19474note_mode_line_or_margin_highlight (w, x, y, area)
19475 struct window *w;
19476 int x, y;
19477 enum window_part area;
19478{
19479 struct frame *f = XFRAME (w->frame);
19480 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
19481 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
19482 int charpos;
19483 Lisp_Object string, help, map, pos;
19484
19485 if (area == ON_MODE_LINE || area == ON_HEADER_LINE)
19486 string = mode_line_string (w, x, y, area, &charpos);
19487 else
19488 string = marginal_area_string (w, x, y, area, &charpos);
19489
19490 if (STRINGP (string))
19491 {
19492 pos = make_number (charpos);
19493
19494 /* If we're on a string with `help-echo' text property, arrange
19495 for the help to be displayed. This is done by setting the
19496 global variable help_echo_string to the help string. */
19497 help = Fget_text_property (pos, Qhelp_echo, string);
19498 if (!NILP (help))
19499 {
19500 help_echo_string = help;
19501 XSETWINDOW (help_echo_window, w);
19502 help_echo_object = string;
19503 help_echo_pos = charpos;
19504 }
19505
19506 /* Change the mouse pointer according to what is under X/Y. */
19507 map = Fget_text_property (pos, Qlocal_map, string);
19508 if (!KEYMAPP (map))
19509 map = Fget_text_property (pos, Qkeymap, string);
19510 if (KEYMAPP (map))
19511 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
19512 }
19513
19514 rif->define_frame_cursor (f, cursor);
19515}
19516
19517#endif /* !HAVE_CARBON */
19518
19519
19520/* EXPORT:
19521 Take proper action when the mouse has moved to position X, Y on
19522 frame F as regards highlighting characters that have mouse-face
19523 properties. Also de-highlighting chars where the mouse was before.
19524 X and Y can be negative or out of range. */
19525
19526void
19527note_mouse_highlight (f, x, y)
19528 struct frame *f;
19529 int x, y;
19530{
19531 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
19532 enum window_part part;
19533 Lisp_Object window;
19534 struct window *w;
19535 Cursor cursor = No_Cursor;
19536 struct buffer *b;
19537
19538 /* When a menu is active, don't highlight because this looks odd. */
19539#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
19540 if (popup_activated ())
19541 return;
19542#endif
19543
19544 if (NILP (Vmouse_highlight)
19545 || !f->glyphs_initialized_p)
19546 return;
19547
19548 dpyinfo->mouse_face_mouse_x = x;
19549 dpyinfo->mouse_face_mouse_y = y;
19550 dpyinfo->mouse_face_mouse_frame = f;
19551
19552 if (dpyinfo->mouse_face_defer)
19553 return;
19554
19555 if (gc_in_progress)
19556 {
19557 dpyinfo->mouse_face_deferred_gc = 1;
19558 return;
19559 }
19560
19561 /* Which window is that in? */
19562 window = window_from_coordinates (f, x, y, &part, 1);
19563
19564 /* If we were displaying active text in another window, clear that. */
19565 if (! EQ (window, dpyinfo->mouse_face_window))
19566 clear_mouse_face (dpyinfo);
19567
19568 /* Not on a window -> return. */
19569 if (!WINDOWP (window))
19570 return;
19571
19572 /* Reset help_echo_string. It will get recomputed below. */
19573 /* ++KFS: X version didn't do this, but it looks harmless. */
19574 help_echo_string = Qnil;
19575
19576 /* Convert to window-relative pixel coordinates. */
19577 w = XWINDOW (window);
19578 frame_to_window_pixel_xy (w, &x, &y);
19579
19580 /* Handle tool-bar window differently since it doesn't display a
19581 buffer. */
19582 if (EQ (window, f->tool_bar_window))
19583 {
19584 note_tool_bar_highlight (f, x, y);
19585 return;
19586 }
19587
19588#ifdef HAVE_CARBON
19589 /* ++KFS: Why does MAC have its own version here? Looks like OLD CODE!! */
19590
19591 /* Mouse is on the mode or header line? */
19592 if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
19593 {
19594 note_mode_line_highlight (w, x, part == ON_MODE_LINE);
19595 return;
19596 }
19597#else
19598 /* Mouse is on the mode, header line or margin? */
19599 if (part == ON_MODE_LINE || part == ON_HEADER_LINE
19600 || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
19601 {
19602 note_mode_line_or_margin_highlight (w, x, y, part);
19603 return;
19604 }
19605#endif
19606
19607 if (part == ON_VERTICAL_BORDER)
19608 cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
19609 else
19610 cursor = FRAME_X_OUTPUT (f)->text_cursor;
19611
19612 /* Are we in a window whose display is up to date?
19613 And verify the buffer's text has not changed. */
19614 b = XBUFFER (w->buffer);
19615 if (part == ON_TEXT
19616 && EQ (w->window_end_valid, w->buffer)
19617 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
19618 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
19619 {
19620 int hpos, vpos, pos, i, area;
19621 struct glyph *glyph;
19622 Lisp_Object object;
19623 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
19624 Lisp_Object *overlay_vec = NULL;
19625 int len, noverlays;
19626 struct buffer *obuf;
19627 int obegv, ozv, same_region;
19628
19629 /* Find the glyph under X/Y. */
19630 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
19631
19632 /* Clear mouse face if X/Y not over text. */
19633 if (glyph == NULL
19634 || area != TEXT_AREA
19635 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
19636 {
19637#if defined (HAVE_NTGUI)
19638 /* ++KFS: Why is this necessary on W32 ? */
19639 clear_mouse_face (dpyinfo);
19640 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
19641#else
19642 if (clear_mouse_face (dpyinfo))
19643 cursor = No_Cursor;
19644#endif
19645 goto set_cursor;
19646 }
19647
19648 pos = glyph->charpos;
19649 object = glyph->object;
19650 if (!STRINGP (object) && !BUFFERP (object))
19651 goto set_cursor;
19652
19653 /* If we get an out-of-range value, return now; avoid an error. */
19654 if (BUFFERP (object) && pos > BUF_Z (b))
19655 goto set_cursor;
19656
19657 /* Make the window's buffer temporarily current for
19658 overlays_at and compute_char_face. */
19659 obuf = current_buffer;
19660 current_buffer = b;
19661 obegv = BEGV;
19662 ozv = ZV;
19663 BEGV = BEG;
19664 ZV = Z;
19665
19666 /* Is this char mouse-active or does it have help-echo? */
19667 position = make_number (pos);
19668
19669 if (BUFFERP (object))
19670 {
19671 /* Put all the overlays we want in a vector in overlay_vec.
19672 Store the length in len. If there are more than 10, make
19673 enough space for all, and try again. */
19674 len = 10;
19675 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
19676 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
19677 if (noverlays > len)
19678 {
19679 len = noverlays;
19680 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
19681 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
19682 }
19683
19684 /* Sort overlays into increasing priority order. */
19685 noverlays = sort_overlays (overlay_vec, noverlays, w);
19686 }
19687 else
19688 noverlays = 0;
19689
19690 same_region = (EQ (window, dpyinfo->mouse_face_window)
19691 && vpos >= dpyinfo->mouse_face_beg_row
19692 && vpos <= dpyinfo->mouse_face_end_row
19693 && (vpos > dpyinfo->mouse_face_beg_row
19694 || hpos >= dpyinfo->mouse_face_beg_col)
19695 && (vpos < dpyinfo->mouse_face_end_row
19696 || hpos < dpyinfo->mouse_face_end_col
19697 || dpyinfo->mouse_face_past_end));
19698
19699 if (same_region)
19700 cursor = No_Cursor;
19701
19702 /* Check mouse-face highlighting. */
19703 if (! same_region
19704 /* If there exists an overlay with mouse-face overlapping
19705 the one we are currently highlighting, we have to
19706 check if we enter the overlapping overlay, and then
19707 highlight only that. */
19708 || (OVERLAYP (dpyinfo->mouse_face_overlay)
19709 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
19710 {
19711 /* Find the highest priority overlay that has a mouse-face
19712 property. */
19713 overlay = Qnil;
19714 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
19715 {
19716 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
19717 if (!NILP (mouse_face))
19718 overlay = overlay_vec[i];
19719 }
19720
19721 /* If we're actually highlighting the same overlay as
19722 before, there's no need to do that again. */
19723 if (!NILP (overlay)
19724 && EQ (overlay, dpyinfo->mouse_face_overlay))
19725 goto check_help_echo;
19726
19727 dpyinfo->mouse_face_overlay = overlay;
19728
19729 /* Clear the display of the old active region, if any. */
19730 if (clear_mouse_face (dpyinfo))
19731 cursor = No_Cursor;
19732
19733 /* If no overlay applies, get a text property. */
19734 if (NILP (overlay))
19735 mouse_face = Fget_text_property (position, Qmouse_face, object);
19736
19737 /* Handle the overlay case. */
19738 if (!NILP (overlay))
19739 {
19740 /* Find the range of text around this char that
19741 should be active. */
19742 Lisp_Object before, after;
19743 int ignore;
19744
19745 before = Foverlay_start (overlay);
19746 after = Foverlay_end (overlay);
19747 /* Record this as the current active region. */
19748 fast_find_position (w, XFASTINT (before),
19749 &dpyinfo->mouse_face_beg_col,
19750 &dpyinfo->mouse_face_beg_row,
19751 &dpyinfo->mouse_face_beg_x,
19752 &dpyinfo->mouse_face_beg_y, Qnil);
19753
19754 dpyinfo->mouse_face_past_end
19755 = !fast_find_position (w, XFASTINT (after),
19756 &dpyinfo->mouse_face_end_col,
19757 &dpyinfo->mouse_face_end_row,
19758 &dpyinfo->mouse_face_end_x,
19759 &dpyinfo->mouse_face_end_y, Qnil);
19760 dpyinfo->mouse_face_window = window;
19761
19762 dpyinfo->mouse_face_face_id
19763 = face_at_buffer_position (w, pos, 0, 0,
19764 &ignore, pos + 1,
19765 !dpyinfo->mouse_face_hidden);
19766
19767 /* Display it as active. */
19768 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
19769 cursor = No_Cursor;
19770 }
19771 /* Handle the text property case. */
19772 else if (!NILP (mouse_face) && BUFFERP (object))
19773 {
19774 /* Find the range of text around this char that
19775 should be active. */
19776 Lisp_Object before, after, beginning, end;
19777 int ignore;
19778
19779 beginning = Fmarker_position (w->start);
19780 end = make_number (BUF_Z (XBUFFER (object))
19781 - XFASTINT (w->window_end_pos));
19782 before
19783 = Fprevious_single_property_change (make_number (pos + 1),
19784 Qmouse_face,
19785 object, beginning);
19786 after
19787 = Fnext_single_property_change (position, Qmouse_face,
19788 object, end);
19789
19790 /* Record this as the current active region. */
19791 fast_find_position (w, XFASTINT (before),
19792 &dpyinfo->mouse_face_beg_col,
19793 &dpyinfo->mouse_face_beg_row,
19794 &dpyinfo->mouse_face_beg_x,
19795 &dpyinfo->mouse_face_beg_y, Qnil);
19796 dpyinfo->mouse_face_past_end
19797 = !fast_find_position (w, XFASTINT (after),
19798 &dpyinfo->mouse_face_end_col,
19799 &dpyinfo->mouse_face_end_row,
19800 &dpyinfo->mouse_face_end_x,
19801 &dpyinfo->mouse_face_end_y, Qnil);
19802 dpyinfo->mouse_face_window = window;
19803
19804 if (BUFFERP (object))
19805 dpyinfo->mouse_face_face_id
19806 = face_at_buffer_position (w, pos, 0, 0,
19807 &ignore, pos + 1,
19808 !dpyinfo->mouse_face_hidden);
19809
19810 /* Display it as active. */
19811 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
19812 cursor = No_Cursor;
19813 }
19814 else if (!NILP (mouse_face) && STRINGP (object))
19815 {
19816 Lisp_Object b, e;
19817 int ignore;
19818
19819 b = Fprevious_single_property_change (make_number (pos + 1),
19820 Qmouse_face,
19821 object, Qnil);
19822 e = Fnext_single_property_change (position, Qmouse_face,
19823 object, Qnil);
19824 if (NILP (b))
19825 b = make_number (0);
19826 if (NILP (e))
19827 e = make_number (SCHARS (object) - 1);
19828 fast_find_string_pos (w, XINT (b), object,
19829 &dpyinfo->mouse_face_beg_col,
19830 &dpyinfo->mouse_face_beg_row,
19831 &dpyinfo->mouse_face_beg_x,
19832 &dpyinfo->mouse_face_beg_y, 0);
19833 fast_find_string_pos (w, XINT (e), object,
19834 &dpyinfo->mouse_face_end_col,
19835 &dpyinfo->mouse_face_end_row,
19836 &dpyinfo->mouse_face_end_x,
19837 &dpyinfo->mouse_face_end_y, 1);
19838 dpyinfo->mouse_face_past_end = 0;
19839 dpyinfo->mouse_face_window = window;
19840 dpyinfo->mouse_face_face_id
19841 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
19842 glyph->face_id, 1);
19843 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
19844 cursor = No_Cursor;
19845 }
19846 else if (STRINGP (object) && NILP (mouse_face))
19847 {
19848 /* A string which doesn't have mouse-face, but
19849 the text ``under'' it might have. */
19850 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
19851 int start = MATRIX_ROW_START_CHARPOS (r);
19852
19853 pos = string_buffer_position (w, object, start);
19854 if (pos > 0)
19855 mouse_face = get_char_property_and_overlay (make_number (pos),
19856 Qmouse_face,
19857 w->buffer,
19858 &overlay);
19859 if (!NILP (mouse_face) && !NILP (overlay))
19860 {
19861 Lisp_Object before = Foverlay_start (overlay);
19862 Lisp_Object after = Foverlay_end (overlay);
19863 int ignore;
19864
19865 /* Note that we might not be able to find position
19866 BEFORE in the glyph matrix if the overlay is
19867 entirely covered by a `display' property. In
19868 this case, we overshoot. So let's stop in
19869 the glyph matrix before glyphs for OBJECT. */
19870 fast_find_position (w, XFASTINT (before),
19871 &dpyinfo->mouse_face_beg_col,
19872 &dpyinfo->mouse_face_beg_row,
19873 &dpyinfo->mouse_face_beg_x,
19874 &dpyinfo->mouse_face_beg_y,
19875 object);
19876
19877 dpyinfo->mouse_face_past_end
19878 = !fast_find_position (w, XFASTINT (after),
19879 &dpyinfo->mouse_face_end_col,
19880 &dpyinfo->mouse_face_end_row,
19881 &dpyinfo->mouse_face_end_x,
19882 &dpyinfo->mouse_face_end_y,
19883 Qnil);
19884 dpyinfo->mouse_face_window = window;
19885 dpyinfo->mouse_face_face_id
19886 = face_at_buffer_position (w, pos, 0, 0,
19887 &ignore, pos + 1,
19888 !dpyinfo->mouse_face_hidden);
19889
19890 /* Display it as active. */
19891 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
19892 cursor = No_Cursor;
19893 }
19894 }
19895 }
19896
19897 check_help_echo:
19898
19899 /* Look for a `help-echo' property. */
19900 {
19901 Lisp_Object help, overlay;
19902
19903 /* Check overlays first. */
19904 help = overlay = Qnil;
19905 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
19906 {
19907 overlay = overlay_vec[i];
19908 help = Foverlay_get (overlay, Qhelp_echo);
19909 }
19910
19911 if (!NILP (help))
19912 {
19913 help_echo_string = help;
19914 help_echo_window = window;
19915 help_echo_object = overlay;
19916 help_echo_pos = pos;
19917 }
19918 else
19919 {
19920 Lisp_Object object = glyph->object;
19921 int charpos = glyph->charpos;
19922
19923 /* Try text properties. */
19924 if (STRINGP (object)
19925 && charpos >= 0
19926 && charpos < SCHARS (object))
19927 {
19928 help = Fget_text_property (make_number (charpos),
19929 Qhelp_echo, object);
19930 if (NILP (help))
19931 {
19932 /* If the string itself doesn't specify a help-echo,
19933 see if the buffer text ``under'' it does. */
19934 struct glyph_row *r
19935 = MATRIX_ROW (w->current_matrix, vpos);
19936 int start = MATRIX_ROW_START_CHARPOS (r);
19937 int pos = string_buffer_position (w, object, start);
19938 if (pos > 0)
19939 {
19940 help = Fget_char_property (make_number (pos),
19941 Qhelp_echo, w->buffer);
19942 if (!NILP (help))
19943 {
19944 charpos = pos;
19945 object = w->buffer;
19946 }
19947 }
19948 }
19949 }
19950 else if (BUFFERP (object)
19951 && charpos >= BEGV
19952 && charpos < ZV)
19953 help = Fget_text_property (make_number (charpos), Qhelp_echo,
19954 object);
19955
19956 if (!NILP (help))
19957 {
19958 help_echo_string = help;
19959 help_echo_window = window;
19960 help_echo_object = object;
19961 help_echo_pos = charpos;
19962 }
19963 }
19964 }
19965
19966 BEGV = obegv;
19967 ZV = ozv;
19968 current_buffer = obuf;
19969 }
19970
19971 set_cursor:
19972
19973 if (cursor != No_Cursor)
19974 rif->define_frame_cursor (f, cursor);
19975}
19976
19977
19978/* EXPORT for RIF:
19979 Clear any mouse-face on window W. This function is part of the
19980 redisplay interface, and is called from try_window_id and similar
19981 functions to ensure the mouse-highlight is off. */
19982
19983void
19984x_clear_window_mouse_face (w)
19985 struct window *w;
19986{
19987 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
19988 Lisp_Object window;
19989
19990 BLOCK_INPUT;
19991 XSETWINDOW (window, w);
19992 if (EQ (window, dpyinfo->mouse_face_window))
19993 clear_mouse_face (dpyinfo);
19994 UNBLOCK_INPUT;
19995}
19996
19997
19998/* EXPORT:
19999 Just discard the mouse face information for frame F, if any.
20000 This is used when the size of F is changed. */
20001
20002void
20003cancel_mouse_face (f)
20004 struct frame *f;
20005{
20006 Lisp_Object window;
20007 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
20008
20009 window = dpyinfo->mouse_face_window;
20010 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
20011 {
20012 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
20013 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
20014 dpyinfo->mouse_face_window = Qnil;
20015 }
20016}
20017
20018
20019#endif /* HAVE_WINDOW_SYSTEM */
20020
20021
20022/***********************************************************************
20023 Exposure Events
20024 ***********************************************************************/
20025
20026#ifdef HAVE_WINDOW_SYSTEM
20027
20028/* Redraw the part of glyph row area AREA of glyph row ROW on window W
20029 which intersects rectangle R. R is in window-relative coordinates. */
20030
20031static void
20032expose_area (w, row, r, area)
20033 struct window *w;
20034 struct glyph_row *row;
20035 XRectangle *r;
20036 enum glyph_row_area area;
20037{
20038 struct glyph *first = row->glyphs[area];
20039 struct glyph *end = row->glyphs[area] + row->used[area];
20040 struct glyph *last;
20041 int first_x, start_x, x;
20042
20043 if (area == TEXT_AREA && row->fill_line_p)
20044 /* If row extends face to end of line write the whole line. */
20045 draw_glyphs (w, 0, row, area,
20046 0, row->used[area],
20047 DRAW_NORMAL_TEXT, 0);
20048 else
20049 {
20050 /* Set START_X to the window-relative start position for drawing glyphs of
20051 AREA. The first glyph of the text area can be partially visible.
20052 The first glyphs of other areas cannot. */
20053 if (area == LEFT_MARGIN_AREA)
20054 start_x = 0;
20055 else if (area == TEXT_AREA)
20056 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
20057 else
20058 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
20059 + window_box_width (w, TEXT_AREA));
20060 x = start_x;
20061
20062 /* Find the first glyph that must be redrawn. */
20063 while (first < end
20064 && x + first->pixel_width < r->x)
20065 {
20066 x += first->pixel_width;
20067 ++first;
20068 }
20069
20070 /* Find the last one. */
20071 last = first;
20072 first_x = x;
20073 while (last < end
20074 && x < r->x + r->width)
20075 {
20076 x += last->pixel_width;
20077 ++last;
20078 }
20079
20080 /* Repaint. */
20081 if (last > first)
20082 draw_glyphs (w, first_x - start_x, row, area,
20083 first - row->glyphs[area], last - row->glyphs[area],
20084 DRAW_NORMAL_TEXT, 0);
20085 }
20086}
20087
20088
20089/* Redraw the parts of the glyph row ROW on window W intersecting
20090 rectangle R. R is in window-relative coordinates. Value is
20091 non-zero if mouse-face was overwritten. */
20092
20093static int
20094expose_line (w, row, r)
20095 struct window *w;
20096 struct glyph_row *row;
20097 XRectangle *r;
20098{
20099 xassert (row->enabled_p);
20100
20101 if (row->mode_line_p || w->pseudo_window_p)
20102 draw_glyphs (w, 0, row, TEXT_AREA,
20103 0, row->used[TEXT_AREA],
20104 DRAW_NORMAL_TEXT, 0);
20105 else
20106 {
20107 if (row->used[LEFT_MARGIN_AREA])
20108 expose_area (w, row, r, LEFT_MARGIN_AREA);
20109 if (row->used[TEXT_AREA])
20110 expose_area (w, row, r, TEXT_AREA);
20111 if (row->used[RIGHT_MARGIN_AREA])
20112 expose_area (w, row, r, RIGHT_MARGIN_AREA);
20113 draw_row_fringe_bitmaps (w, row);
20114 }
20115
20116 return row->mouse_face_p;
20117}
20118
20119
20120/* Redraw those parts of glyphs rows during expose event handling that
20121 overlap other rows. Redrawing of an exposed line writes over parts
20122 of lines overlapping that exposed line; this function fixes that.
20123
20124 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
20125 row in W's current matrix that is exposed and overlaps other rows.
20126 LAST_OVERLAPPING_ROW is the last such row. */
20127
20128static void
20129expose_overlaps (w, first_overlapping_row, last_overlapping_row)
20130 struct window *w;
20131 struct glyph_row *first_overlapping_row;
20132 struct glyph_row *last_overlapping_row;
20133{
20134 struct glyph_row *row;
20135
20136 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
20137 if (row->overlapping_p)
20138 {
20139 xassert (row->enabled_p && !row->mode_line_p);
20140
20141 if (row->used[LEFT_MARGIN_AREA])
20142 x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
20143
20144 if (row->used[TEXT_AREA])
20145 x_fix_overlapping_area (w, row, TEXT_AREA);
20146
20147 if (row->used[RIGHT_MARGIN_AREA])
20148 x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
20149 }
20150}
20151
20152
20153/* Return non-zero if W's cursor intersects rectangle R. */
20154
20155static int
20156phys_cursor_in_rect_p (w, r)
20157 struct window *w;
20158 XRectangle *r;
20159{
20160 XRectangle cr, result;
20161 struct glyph *cursor_glyph;
20162
20163 cursor_glyph = get_phys_cursor_glyph (w);
20164 if (cursor_glyph)
20165 {
20166 cr.x = w->phys_cursor.x;
20167 cr.y = w->phys_cursor.y;
20168 cr.width = cursor_glyph->pixel_width;
20169 cr.height = w->phys_cursor_height;
20170 /* ++KFS: W32 version used W32-specific IntersectRect here, but
20171 I assume the effect is the same -- and this is portable. */
20172 return x_intersect_rectangles (&cr, r, &result);
20173 }
20174 else
20175 return 0;
20176}
20177
20178
20179/* EXPORT:
20180 Draw a vertical window border to the right of window W if W doesn't
20181 have vertical scroll bars. */
20182
20183void
20184x_draw_vertical_border (w)
20185 struct window *w;
20186{
20187 struct frame *f = XFRAME (WINDOW_FRAME (w));
20188
20189 /* Redraw borders between horizontally adjacent windows. Don't
20190 do it for frames with vertical scroll bars because either the
20191 right scroll bar of a window, or the left scroll bar of its
20192 neighbor will suffice as a border. */
20193 if (!WINDOW_RIGHTMOST_P (w)
20194 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
20195 {
20196 int x0, x1, y0, y1;
20197
20198 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
20199 x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
20200 y1 -= 1;
20201
20202 rif->draw_vertical_window_border (w, x1, y0, y1);
20203 }
20204}
20205
20206
20207/* Redraw the part of window W intersection rectangle FR. Pixel
20208 coordinates in FR are frame-relative. Call this function with
20209 input blocked. Value is non-zero if the exposure overwrites
20210 mouse-face. */
20211
20212static int
20213expose_window (w, fr)
20214 struct window *w;
20215 XRectangle *fr;
20216{
20217 struct frame *f = XFRAME (w->frame);
20218 XRectangle wr, r;
20219 int mouse_face_overwritten_p = 0;
20220
20221 /* If window is not yet fully initialized, do nothing. This can
20222 happen when toolkit scroll bars are used and a window is split.
20223 Reconfiguring the scroll bar will generate an expose for a newly
20224 created window. */
20225 if (w->current_matrix == NULL)
20226 return 0;
20227
20228 /* When we're currently updating the window, display and current
20229 matrix usually don't agree. Arrange for a thorough display
20230 later. */
20231 if (w == updated_window)
20232 {
20233 SET_FRAME_GARBAGED (f);
20234 return 0;
20235 }
20236
20237 /* Frame-relative pixel rectangle of W. */
20238 wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
20239 wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
20240 wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
20241 wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
20242
20243 if (x_intersect_rectangles (fr, &wr, &r))
20244 {
20245 int yb = window_text_bottom_y (w);
20246 struct glyph_row *row;
20247 int cursor_cleared_p;
20248 struct glyph_row *first_overlapping_row, *last_overlapping_row;
20249
20250 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
20251 r.x, r.y, r.width, r.height));
20252
20253 /* Convert to window coordinates. */
20254 r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
20255 r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
20256
20257 /* Turn off the cursor. */
20258 if (!w->pseudo_window_p
20259 && phys_cursor_in_rect_p (w, &r))
20260 {
20261 x_clear_cursor (w);
20262 cursor_cleared_p = 1;
20263 }
20264 else
20265 cursor_cleared_p = 0;
20266
20267 /* Update lines intersecting rectangle R. */
20268 first_overlapping_row = last_overlapping_row = NULL;
20269 for (row = w->current_matrix->rows;
20270 row->enabled_p;
20271 ++row)
20272 {
20273 int y0 = row->y;
20274 int y1 = MATRIX_ROW_BOTTOM_Y (row);
20275
20276 if ((y0 >= r.y && y0 < r.y + r.height)
20277 || (y1 > r.y && y1 < r.y + r.height)
20278 || (r.y >= y0 && r.y < y1)
20279 || (r.y + r.height > y0 && r.y + r.height < y1))
20280 {
20281 if (row->overlapping_p)
20282 {
20283 if (first_overlapping_row == NULL)
20284 first_overlapping_row = row;
20285 last_overlapping_row = row;
20286 }
20287
20288 if (expose_line (w, row, &r))
20289 mouse_face_overwritten_p = 1;
20290 }
20291
20292 if (y1 >= yb)
20293 break;
20294 }
20295
20296 /* Display the mode line if there is one. */
20297 if (WINDOW_WANTS_MODELINE_P (w)
20298 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
20299 row->enabled_p)
20300 && row->y < r.y + r.height)
20301 {
20302 if (expose_line (w, row, &r))
20303 mouse_face_overwritten_p = 1;
20304 }
20305
20306 if (!w->pseudo_window_p)
20307 {
20308 /* Fix the display of overlapping rows. */
20309 if (first_overlapping_row)
20310 expose_overlaps (w, first_overlapping_row, last_overlapping_row);
20311
20312 /* Draw border between windows. */
20313 x_draw_vertical_border (w);
20314
20315 /* Turn the cursor on again. */
20316 if (cursor_cleared_p)
20317 update_window_cursor (w, 1);
20318 }
20319 }
20320
20321#ifdef HAVE_CARBON
20322 /* Display scroll bar for this window. */
20323 if (!NILP (w->vertical_scroll_bar))
20324 {
20325 /* ++KFS:
20326 If this doesn't work here (maybe some header files are missing),
20327 make a function in macterm.c and call it to do the job! */
20328 ControlHandle ch
20329 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
20330
20331 Draw1Control (ch);
20332 }
20333#endif
20334
20335 return mouse_face_overwritten_p;
20336}
20337
20338
20339
20340/* Redraw (parts) of all windows in the window tree rooted at W that
20341 intersect R. R contains frame pixel coordinates. Value is
20342 non-zero if the exposure overwrites mouse-face. */
20343
20344static int
20345expose_window_tree (w, r)
20346 struct window *w;
20347 XRectangle *r;
20348{
20349 struct frame *f = XFRAME (w->frame);
20350 int mouse_face_overwritten_p = 0;
20351
20352 while (w && !FRAME_GARBAGED_P (f))
20353 {
20354 if (!NILP (w->hchild))
20355 mouse_face_overwritten_p
20356 |= expose_window_tree (XWINDOW (w->hchild), r);
20357 else if (!NILP (w->vchild))
20358 mouse_face_overwritten_p
20359 |= expose_window_tree (XWINDOW (w->vchild), r);
20360 else
20361 mouse_face_overwritten_p |= expose_window (w, r);
20362
20363 w = NILP (w->next) ? NULL : XWINDOW (w->next);
20364 }
20365
20366 return mouse_face_overwritten_p;
20367}
20368
20369
20370/* EXPORT:
20371 Redisplay an exposed area of frame F. X and Y are the upper-left
20372 corner of the exposed rectangle. W and H are width and height of
20373 the exposed area. All are pixel values. W or H zero means redraw
20374 the entire frame. */
20375
20376void
20377expose_frame (f, x, y, w, h)
20378 struct frame *f;
20379 int x, y, w, h;
20380{
20381 XRectangle r;
20382 int mouse_face_overwritten_p = 0;
20383
20384 TRACE ((stderr, "expose_frame "));
20385
20386 /* No need to redraw if frame will be redrawn soon. */
20387 if (FRAME_GARBAGED_P (f))
20388 {
20389 TRACE ((stderr, " garbaged\n"));
20390 return;
20391 }
20392
20393#ifdef HAVE_CARBON
20394 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
20395 or deactivated here, for unknown reasons, activated scroll bars
20396 are shown in deactivated frames in some instances. */
20397 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
20398 activate_scroll_bars (f);
20399 else
20400 deactivate_scroll_bars (f);
20401#endif
20402
20403 /* If basic faces haven't been realized yet, there is no point in
20404 trying to redraw anything. This can happen when we get an expose
20405 event while Emacs is starting, e.g. by moving another window. */
20406 if (FRAME_FACE_CACHE (f) == NULL
20407 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
20408 {
20409 TRACE ((stderr, " no faces\n"));
20410 return;
20411 }
20412
20413 if (w == 0 || h == 0)
20414 {
20415 r.x = r.y = 0;
20416 r.width = CANON_X_UNIT (f) * f->width;
20417 r.height = CANON_Y_UNIT (f) * f->height;
20418 }
20419 else
20420 {
20421 r.x = x;
20422 r.y = y;
20423 r.width = w;
20424 r.height = h;
20425 }
20426
20427 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
20428 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
20429
20430 if (WINDOWP (f->tool_bar_window))
20431 mouse_face_overwritten_p
20432 |= expose_window (XWINDOW (f->tool_bar_window), &r);
20433
20434#ifdef HAVE_X_WINDOWS
20435#ifndef MSDOS
20436#ifndef USE_X_TOOLKIT
20437 if (WINDOWP (f->menu_bar_window))
20438 mouse_face_overwritten_p
20439 |= expose_window (XWINDOW (f->menu_bar_window), &r);
20440#endif /* not USE_X_TOOLKIT */
20441#endif
20442#endif
20443
20444 /* Some window managers support a focus-follows-mouse style with
20445 delayed raising of frames. Imagine a partially obscured frame,
20446 and moving the mouse into partially obscured mouse-face on that
20447 frame. The visible part of the mouse-face will be highlighted,
20448 then the WM raises the obscured frame. With at least one WM, KDE
20449 2.1, Emacs is not getting any event for the raising of the frame
20450 (even tried with SubstructureRedirectMask), only Expose events.
20451 These expose events will draw text normally, i.e. not
20452 highlighted. Which means we must redo the highlight here.
20453 Subsume it under ``we love X''. --gerd 2001-08-15 */
20454 /* Included in Windows version because Windows most likely does not
20455 do the right thing if any third party tool offers
20456 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
20457 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
20458 {
20459 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
20460 if (f == dpyinfo->mouse_face_mouse_frame)
20461 {
20462 int x = dpyinfo->mouse_face_mouse_x;
20463 int y = dpyinfo->mouse_face_mouse_y;
20464 clear_mouse_face (dpyinfo);
20465 note_mouse_highlight (f, x, y);
20466 }
20467 }
20468}
20469
20470
20471/* EXPORT:
20472 Determine the intersection of two rectangles R1 and R2. Return
20473 the intersection in *RESULT. Value is non-zero if RESULT is not
20474 empty. */
20475
20476int
20477x_intersect_rectangles (r1, r2, result)
20478 XRectangle *r1, *r2, *result;
20479{
20480 XRectangle *left, *right;
20481 XRectangle *upper, *lower;
20482 int intersection_p = 0;
20483
20484 /* Rearrange so that R1 is the left-most rectangle. */
20485 if (r1->x < r2->x)
20486 left = r1, right = r2;
20487 else
20488 left = r2, right = r1;
20489
20490 /* X0 of the intersection is right.x0, if this is inside R1,
20491 otherwise there is no intersection. */
20492 if (right->x <= left->x + left->width)
20493 {
20494 result->x = right->x;
20495
20496 /* The right end of the intersection is the minimum of the
20497 the right ends of left and right. */
20498 result->width = (min (left->x + left->width, right->x + right->width)
20499 - result->x);
20500
20501 /* Same game for Y. */
20502 if (r1->y < r2->y)
20503 upper = r1, lower = r2;
20504 else
20505 upper = r2, lower = r1;
20506
20507 /* The upper end of the intersection is lower.y0, if this is inside
20508 of upper. Otherwise, there is no intersection. */
20509 if (lower->y <= upper->y + upper->height)
20510 {
20511 result->y = lower->y;
20512
20513 /* The lower end of the intersection is the minimum of the lower
20514 ends of upper and lower. */
20515 result->height = (min (lower->y + lower->height,
20516 upper->y + upper->height)
20517 - result->y);
20518 intersection_p = 1;
20519 }
20520 }
20521
20522 return intersection_p;
20523}
20524
20525#endif /* HAVE_WINDOW_SYSTEM */
20526
17911 20527
17912/*********************************************************************** 20528/***********************************************************************
17913 Initialization 20529 Initialization
@@ -18057,6 +20673,24 @@ syms_of_xdisp ()
18057 mode_line_string_list = Qnil; 20673 mode_line_string_list = Qnil;
18058 staticpro (&mode_line_string_list); 20674 staticpro (&mode_line_string_list);
18059 20675
20676 help_echo_string = Qnil;
20677 staticpro (&help_echo_string);
20678 help_echo_object = Qnil;
20679 staticpro (&help_echo_object);
20680 help_echo_window = Qnil;
20681 staticpro (&help_echo_window);
20682 previous_help_echo_string = Qnil;
20683 staticpro (&previous_help_echo_string);
20684 help_echo_pos = -1;
20685
20686#ifdef HAVE_WINDOW_SYSTEM
20687 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
20688 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
20689For example, if a block cursor is over a tab, it will be drawn as
20690wide as that tab on the display. */);
20691 x_stretch_cursor_p = 0;
20692#endif
20693
18060 DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace, 20694 DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
18061 doc: /* Non-nil means highlight trailing whitespace. 20695 doc: /* Non-nil means highlight trailing whitespace.
18062The face used for trailing whitespace is `trailing-whitespace'. */); 20696The face used for trailing whitespace is `trailing-whitespace'. */);
@@ -18182,6 +20816,10 @@ and its new display-start position. Note that the value of `window-end'
18182is not valid when these functions are called. */); 20816is not valid when these functions are called. */);
18183 Vwindow_scroll_functions = Qnil; 20817 Vwindow_scroll_functions = Qnil;
18184 20818
20819 DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
20820 doc: /* *Non-nil means autoselect window with mouse pointer. */);
20821 mouse_autoselect_window = 0;
20822
18185 DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p, 20823 DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
18186 doc: /* *Non-nil means automatically resize tool-bars. 20824 doc: /* *Non-nil means automatically resize tool-bars.
18187This increases a tool-bar's height if not all tool-bar items are visible. 20825This increases a tool-bar's height if not all tool-bar items are visible.