diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/xdisp.c | 2658 |
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; | |||
| 220 | extern Lisp_Object Voverriding_local_map_menu_flag; | 221 | extern Lisp_Object Voverriding_local_map_menu_flag; |
| 221 | extern Lisp_Object Qmenu_item; | 222 | extern Lisp_Object Qmenu_item; |
| 222 | extern Lisp_Object Qwhen; | 223 | extern Lisp_Object Qwhen; |
| 224 | extern Lisp_Object Qhelp_echo; | ||
| 223 | 225 | ||
| 224 | Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; | 226 | Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map; |
| 225 | Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; | 227 | Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; |
| @@ -244,6 +246,10 @@ Lisp_Object list_of_error; | |||
| 244 | Lisp_Object Vfontification_functions; | 246 | Lisp_Object Vfontification_functions; |
| 245 | Lisp_Object Qfontification_functions; | 247 | Lisp_Object Qfontification_functions; |
| 246 | 248 | ||
| 249 | /* Non-zero means automatically select any window when the mouse | ||
| 250 | cursor moves into it. */ | ||
| 251 | int 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 | ||
| 263 | int auto_resize_tool_bars_p; | 269 | int 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 | |||
| 275 | int 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 | ||
| 267 | Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay; | 279 | Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay; |
| @@ -724,6 +736,19 @@ int redisplaying_p; | |||
| 724 | int inhibit_free_realized_faces; | 736 | int inhibit_free_realized_faces; |
| 725 | Lisp_Object Qinhibit_free_realized_faces; | 737 | Lisp_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 | |||
| 742 | Lisp_Object help_echo_string; | ||
| 743 | Lisp_Object help_echo_window; | ||
| 744 | Lisp_Object help_echo_object; | ||
| 745 | int help_echo_pos; | ||
| 746 | |||
| 747 | /* Temporary variable for XTread_socket. */ | ||
| 748 | |||
| 749 | Lisp_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)); | |||
| 858 | static void build_desired_tool_bar_string P_ ((struct frame *f)); | 883 | static void build_desired_tool_bar_string P_ ((struct frame *f)); |
| 859 | static int redisplay_tool_bar P_ ((struct frame *)); | 884 | static int redisplay_tool_bar P_ ((struct frame *)); |
| 860 | static void display_tool_bar_line P_ ((struct it *)); | 885 | static void display_tool_bar_line P_ ((struct it *)); |
| 886 | static 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 | |||
| 1370 | int | ||
| 1371 | estimate_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 | |||
| 1411 | static struct glyph * | ||
| 1412 | x_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 | |||
| 1494 | void | ||
| 1495 | frame_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 | |||
| 1517 | void | ||
| 1518 | get_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 | |||
| 7895 | struct 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 | |||
| 7902 | void | ||
| 7903 | set_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 | |||
| 7924 | void | ||
| 7925 | x_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 | |||
| 7964 | FRAME_PTR last_mouse_frame; | ||
| 7965 | |||
| 7966 | /* Tool-bar item index of the item on which a mouse button was pressed | ||
| 7967 | or -1. */ | ||
| 7968 | |||
| 7969 | int 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 | ||
| 8105 | int | 8455 | static int |
| 8106 | tool_bar_item_info (f, glyph, prop_idx) | 8456 | tool_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 | |||
| 8498 | static int | ||
| 8499 | get_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 | |||
| 8540 | void | ||
| 8541 | handle_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 | |||
| 8600 | static void | ||
| 8601 | note_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 | ||
| 16549 | int | 17101 | static int |
| 16550 | x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p) | 17102 | draw_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 | |||
| 18210 | void | ||
| 18211 | x_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 | |||
| 18251 | void | ||
| 18252 | x_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 | |||
| 18310 | void | ||
| 18311 | x_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 | ||
| 17862 | void | 18591 | static void |
| 17863 | notice_overwritten_cursor (w, area, x0, x1, y0, y1) | 18592 | notice_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 | |||
| 18652 | void | ||
| 18653 | x_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 | |||
| 18703 | void | ||
| 18704 | draw_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 | |||
| 18747 | void | ||
| 18748 | erase_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 | |||
| 18842 | void | ||
| 18843 | display_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 | |||
| 18924 | static void | ||
| 18925 | update_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 | |||
| 18944 | static void | ||
| 18945 | update_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 | |||
| 18967 | void | ||
| 18968 | x_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 | |||
| 18981 | void | ||
| 18982 | x_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 | |||
| 18993 | void | ||
| 18994 | show_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 | |||
| 19074 | int | ||
| 19075 | clear_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 | |||
| 19097 | int | ||
| 19098 | cursor_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 | |||
| 19139 | static int | ||
| 19140 | fast_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 | |||
| 19202 | static int | ||
| 19203 | fast_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 | |||
| 19316 | static int | ||
| 19317 | fast_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 | |||
| 19393 | static void | ||
| 19394 | note_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 | |||
| 19473 | static void | ||
| 19474 | note_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 | |||
| 19526 | void | ||
| 19527 | note_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 | |||
| 19983 | void | ||
| 19984 | x_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 | |||
| 20002 | void | ||
| 20003 | cancel_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 | |||
| 20031 | static void | ||
| 20032 | expose_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 | |||
| 20093 | static int | ||
| 20094 | expose_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 | |||
| 20128 | static void | ||
| 20129 | expose_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 | |||
| 20155 | static int | ||
| 20156 | phys_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 | |||
| 20183 | void | ||
| 20184 | x_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 | |||
| 20212 | static int | ||
| 20213 | expose_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 | |||
| 20344 | static int | ||
| 20345 | expose_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 | |||
| 20376 | void | ||
| 20377 | expose_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 | |||
| 20476 | int | ||
| 20477 | x_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. | ||
| 20689 | For example, if a block cursor is over a tab, it will be drawn as | ||
| 20690 | wide 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. |
| 18062 | The face used for trailing whitespace is `trailing-whitespace'. */); | 20696 | The 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' | |||
| 18182 | is not valid when these functions are called. */); | 20816 | is 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. |
| 18187 | This increases a tool-bar's height if not all tool-bar items are visible. | 20825 | This increases a tool-bar's height if not all tool-bar items are visible. |