diff options
Diffstat (limited to 'src/term.c')
| -rw-r--r-- | src/term.c | 635 |
1 files changed, 200 insertions, 435 deletions
diff --git a/src/term.c b/src/term.c index 4baea231de3..a684edc5a85 100644 --- a/src/term.c +++ b/src/term.c | |||
| @@ -66,6 +66,10 @@ extern int tgetent (char *, const char *); | |||
| 66 | extern int tgetflag (char *id); | 66 | extern int tgetflag (char *id); |
| 67 | extern int tgetnum (char *id); | 67 | extern int tgetnum (char *id); |
| 68 | 68 | ||
| 69 | char *tparam (char *, char *, int, int, ...); | ||
| 70 | |||
| 71 | extern char *tgetstr (char *, char **); | ||
| 72 | |||
| 69 | #include "cm.h" | 73 | #include "cm.h" |
| 70 | #ifdef HAVE_X_WINDOWS | 74 | #ifdef HAVE_X_WINDOWS |
| 71 | #include "xterm.h" | 75 | #include "xterm.h" |
| @@ -176,32 +180,15 @@ static int no_controlling_tty; | |||
| 176 | 180 | ||
| 177 | static int system_uses_terminfo; | 181 | static int system_uses_terminfo; |
| 178 | 182 | ||
| 179 | char *tparam (char *, char *, int, int, ...); | ||
| 180 | |||
| 181 | extern char *tgetstr (char *, char **); | ||
| 182 | 183 | ||
| 183 | 184 | ||
| 184 | #ifdef HAVE_GPM | 185 | #ifdef HAVE_GPM |
| 185 | #include <sys/fcntl.h> | 186 | #include <sys/fcntl.h> |
| 186 | 187 | ||
| 187 | static void term_clear_mouse_face (void); | ||
| 188 | static void term_mouse_highlight (struct frame *f, int x, int y); | ||
| 189 | |||
| 190 | /* The device for which we have enabled gpm support (or NULL). */ | 188 | /* The device for which we have enabled gpm support (or NULL). */ |
| 191 | struct tty_display_info *gpm_tty = NULL; | 189 | struct tty_display_info *gpm_tty = NULL; |
| 192 | 190 | ||
| 193 | /* These variables describe the range of text currently shown in its | 191 | /* Last recorded mouse coordinates. */ |
| 194 | mouse-face, together with the window they apply to. As long as | ||
| 195 | the mouse stays within this range, we need not redraw anything on | ||
| 196 | its account. Rows and columns are glyph matrix positions in | ||
| 197 | MOUSE_FACE_WINDOW. */ | ||
| 198 | static int mouse_face_beg_row, mouse_face_beg_col; | ||
| 199 | static int mouse_face_end_row, mouse_face_end_col; | ||
| 200 | static int mouse_face_past_end; | ||
| 201 | static Lisp_Object mouse_face_window; | ||
| 202 | static int mouse_face_face_id; | ||
| 203 | |||
| 204 | static int pos_x, pos_y; | ||
| 205 | static int last_mouse_x, last_mouse_y; | 192 | static int last_mouse_x, last_mouse_y; |
| 206 | #endif /* HAVE_GPM */ | 193 | #endif /* HAVE_GPM */ |
| 207 | 194 | ||
| @@ -1501,6 +1488,8 @@ static void append_glyph (struct it *); | |||
| 1501 | static void produce_stretch_glyph (struct it *); | 1488 | static void produce_stretch_glyph (struct it *); |
| 1502 | static void append_composite_glyph (struct it *); | 1489 | static void append_composite_glyph (struct it *); |
| 1503 | static void produce_composite_glyph (struct it *); | 1490 | static void produce_composite_glyph (struct it *); |
| 1491 | static void append_glyphless_glyph (struct it *, int, char *); | ||
| 1492 | static void produce_glyphless_glyph (struct it *, int, Lisp_Object); | ||
| 1504 | 1493 | ||
| 1505 | /* Append glyphs to IT's glyph_row. Called from produce_glyphs for | 1494 | /* Append glyphs to IT's glyph_row. Called from produce_glyphs for |
| 1506 | terminal frames if IT->glyph_row != NULL. IT->char_to_display is | 1495 | terminal frames if IT->glyph_row != NULL. IT->char_to_display is |
| @@ -1609,6 +1598,12 @@ produce_glyphs (struct it *it) | |||
| 1609 | goto done; | 1598 | goto done; |
| 1610 | } | 1599 | } |
| 1611 | 1600 | ||
| 1601 | if (it->what == IT_GLYPHLESS) | ||
| 1602 | { | ||
| 1603 | produce_glyphless_glyph (it, 0, Qnil); | ||
| 1604 | goto done; | ||
| 1605 | } | ||
| 1606 | |||
| 1612 | if (it->char_to_display >= 040 && it->char_to_display < 0177) | 1607 | if (it->char_to_display >= 040 && it->char_to_display < 0177) |
| 1613 | { | 1608 | { |
| 1614 | it->pixel_width = it->nglyphs = 1; | 1609 | it->pixel_width = it->nglyphs = 1; |
| @@ -1660,11 +1655,22 @@ produce_glyphs (struct it *it) | |||
| 1660 | } | 1655 | } |
| 1661 | else | 1656 | else |
| 1662 | { | 1657 | { |
| 1663 | it->pixel_width = CHAR_WIDTH (it->char_to_display); | 1658 | Lisp_Object charset_list = FRAME_TERMINAL (it->f)->charset_list; |
| 1664 | it->nglyphs = it->pixel_width; | ||
| 1665 | 1659 | ||
| 1666 | if (it->glyph_row) | 1660 | if (char_charset (it->char_to_display, charset_list, NULL)) |
| 1667 | append_glyph (it); | 1661 | { |
| 1662 | it->pixel_width = CHAR_WIDTH (it->char_to_display); | ||
| 1663 | it->nglyphs = it->pixel_width; | ||
| 1664 | if (it->glyph_row) | ||
| 1665 | append_glyph (it); | ||
| 1666 | } | ||
| 1667 | else | ||
| 1668 | { | ||
| 1669 | Lisp_Object acronym = lookup_glyphless_char_display (-1, it); | ||
| 1670 | |||
| 1671 | xassert (it->what == IT_GLYPHLESS); | ||
| 1672 | produce_glyphless_glyph (it, 1, acronym); | ||
| 1673 | } | ||
| 1668 | } | 1674 | } |
| 1669 | 1675 | ||
| 1670 | done: | 1676 | done: |
| @@ -1844,6 +1850,152 @@ produce_composite_glyph (struct it *it) | |||
| 1844 | } | 1850 | } |
| 1845 | 1851 | ||
| 1846 | 1852 | ||
| 1853 | /* Append a glyph for a glyphless character to IT->glyph_row. FACE_ID | ||
| 1854 | is a face ID to be used for the glyph. What is actually appended | ||
| 1855 | are glyphs of type CHAR_GLYPH whose characters are in STR (which | ||
| 1856 | comes from it->nglyphs bytes). */ | ||
| 1857 | |||
| 1858 | static void | ||
| 1859 | append_glyphless_glyph (struct it *it, int face_id, char *str) | ||
| 1860 | { | ||
| 1861 | struct glyph *glyph, *end; | ||
| 1862 | int i; | ||
| 1863 | |||
| 1864 | xassert (it->glyph_row); | ||
| 1865 | glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area]; | ||
| 1866 | end = it->glyph_row->glyphs[1 + it->area]; | ||
| 1867 | |||
| 1868 | /* If the glyph row is reversed, we need to prepend the glyph rather | ||
| 1869 | than append it. */ | ||
| 1870 | if (it->glyph_row->reversed_p && it->area == TEXT_AREA) | ||
| 1871 | { | ||
| 1872 | struct glyph *g; | ||
| 1873 | int move_by = it->pixel_width; | ||
| 1874 | |||
| 1875 | /* Make room for the new glyphs. */ | ||
| 1876 | if (move_by > end - glyph) /* don't overstep end of this area */ | ||
| 1877 | move_by = end - glyph; | ||
| 1878 | for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--) | ||
| 1879 | g[move_by] = *g; | ||
| 1880 | glyph = it->glyph_row->glyphs[it->area]; | ||
| 1881 | end = glyph + move_by; | ||
| 1882 | } | ||
| 1883 | |||
| 1884 | if (glyph >= end) | ||
| 1885 | return; | ||
| 1886 | glyph->type = CHAR_GLYPH; | ||
| 1887 | glyph->pixel_width = 1; | ||
| 1888 | glyph->face_id = face_id; | ||
| 1889 | glyph->padding_p = 0; | ||
| 1890 | glyph->charpos = CHARPOS (it->position); | ||
| 1891 | glyph->object = it->object; | ||
| 1892 | if (it->bidi_p) | ||
| 1893 | { | ||
| 1894 | glyph->resolved_level = it->bidi_it.resolved_level; | ||
| 1895 | if ((it->bidi_it.type & 7) != it->bidi_it.type) | ||
| 1896 | abort (); | ||
| 1897 | glyph->bidi_type = it->bidi_it.type; | ||
| 1898 | } | ||
| 1899 | else | ||
| 1900 | { | ||
| 1901 | glyph->resolved_level = 0; | ||
| 1902 | glyph->bidi_type = UNKNOWN_BT; | ||
| 1903 | } | ||
| 1904 | |||
| 1905 | /* BIDI Note: we put the glyphs of characters left to right, even in | ||
| 1906 | the REVERSED_P case because we write to the terminal | ||
| 1907 | left-to-right. */ | ||
| 1908 | for (i = 0; i < it->nglyphs && glyph < end; ++i) | ||
| 1909 | { | ||
| 1910 | if (i > 0) | ||
| 1911 | glyph[0] = glyph[-1]; | ||
| 1912 | glyph->u.ch = str[i]; | ||
| 1913 | ++it->glyph_row->used[it->area]; | ||
| 1914 | ++glyph; | ||
| 1915 | } | ||
| 1916 | } | ||
| 1917 | |||
| 1918 | /* Produce glyphs for a glyphless character for iterator IT. | ||
| 1919 | IT->glyphless_method specifies which method to use for displaying | ||
| 1920 | the character. See the description of enum | ||
| 1921 | glyphless_display_method in dispextern.h for the details. | ||
| 1922 | |||
| 1923 | FOR_NO_FONT is nonzero if and only if this is for a character that | ||
| 1924 | is not supproted by the coding system of the terminal. ACRONYM, if | ||
| 1925 | non-nil, is an acronym string for the character. | ||
| 1926 | |||
| 1927 | The glyphs actually produced are of type CHAR_GLYPH. */ | ||
| 1928 | |||
| 1929 | static void | ||
| 1930 | produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym) | ||
| 1931 | { | ||
| 1932 | int face_id; | ||
| 1933 | int len; | ||
| 1934 | char buf[9], *str = " "; | ||
| 1935 | |||
| 1936 | /* Get a face ID for the glyph by utilizing a cache (the same way as | ||
| 1937 | done for `escape-glyph' in get_next_display_element). */ | ||
| 1938 | if (it->f == last_glyphless_glyph_frame | ||
| 1939 | && it->face_id == last_glyphless_glyph_face_id) | ||
| 1940 | { | ||
| 1941 | face_id = last_glyphless_glyph_merged_face_id; | ||
| 1942 | } | ||
| 1943 | else | ||
| 1944 | { | ||
| 1945 | /* Merge the `glyphless-char' face into the current face. */ | ||
| 1946 | face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id); | ||
| 1947 | last_glyphless_glyph_frame = it->f; | ||
| 1948 | last_glyphless_glyph_face_id = it->face_id; | ||
| 1949 | last_glyphless_glyph_merged_face_id = face_id; | ||
| 1950 | } | ||
| 1951 | |||
| 1952 | if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE) | ||
| 1953 | { | ||
| 1954 | /* As there's no way to produce a thin space, we produce a space | ||
| 1955 | of canonical width. */ | ||
| 1956 | len = 1; | ||
| 1957 | } | ||
| 1958 | else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX) | ||
| 1959 | { | ||
| 1960 | len = CHAR_WIDTH (it->c); | ||
| 1961 | if (len == 0) | ||
| 1962 | len = 1; | ||
| 1963 | else if (len > 4) | ||
| 1964 | len = 4; | ||
| 1965 | sprintf (buf, "[%.*s]", len, str); | ||
| 1966 | len += 2; | ||
| 1967 | str = buf; | ||
| 1968 | } | ||
| 1969 | else | ||
| 1970 | { | ||
| 1971 | if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM) | ||
| 1972 | { | ||
| 1973 | if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display)) | ||
| 1974 | acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c); | ||
| 1975 | buf[0] = '['; | ||
| 1976 | str = STRINGP (acronym) ? (char *) SDATA (acronym) : ""; | ||
| 1977 | for (len = 0; len < 6 && str[len] && ASCII_BYTE_P (str[len]); len++) | ||
| 1978 | buf[1 + len] = str[len]; | ||
| 1979 | buf[1 + len] = ']'; | ||
| 1980 | len += 2; | ||
| 1981 | } | ||
| 1982 | else | ||
| 1983 | { | ||
| 1984 | xassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE); | ||
| 1985 | len = (it->c < 0x10000 ? sprintf (buf, "\\u%04X", it->c) | ||
| 1986 | : it->c <= MAX_UNICODE_CHAR ? sprintf (buf, "\\U%06X", it->c) | ||
| 1987 | : sprintf (buf, "\\x%06X", it->c)); | ||
| 1988 | } | ||
| 1989 | str = buf; | ||
| 1990 | } | ||
| 1991 | |||
| 1992 | it->pixel_width = len; | ||
| 1993 | it->nglyphs = len; | ||
| 1994 | if (len > 0 && it->glyph_row) | ||
| 1995 | append_glyphless_glyph (it, face_id, str); | ||
| 1996 | } | ||
| 1997 | |||
| 1998 | |||
| 1847 | /* Get information about special display element WHAT in an | 1999 | /* Get information about special display element WHAT in an |
| 1848 | environment described by IT. WHAT is one of IT_TRUNCATION or | 2000 | environment described by IT. WHAT is one of IT_TRUNCATION or |
| 1849 | IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a | 2001 | IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a |
| @@ -2517,416 +2669,36 @@ term_mouse_moveto (int x, int y) | |||
| 2517 | last_mouse_y = y; */ | 2669 | last_mouse_y = y; */ |
| 2518 | } | 2670 | } |
| 2519 | 2671 | ||
| 2520 | static void | 2672 | /* Implementation of draw_row_with_mouse_face for TTY/GPM. */ |
| 2521 | term_show_mouse_face (enum draw_glyphs_face draw) | 2673 | void |
| 2674 | tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row, | ||
| 2675 | int start_hpos, int end_hpos, | ||
| 2676 | enum draw_glyphs_face draw) | ||
| 2522 | { | 2677 | { |
| 2523 | struct window *w = XWINDOW (mouse_face_window); | 2678 | int nglyphs = end_hpos - start_hpos; |
| 2524 | int save_x, save_y; | 2679 | struct frame *f = XFRAME (WINDOW_FRAME (w)); |
| 2525 | int i; | ||
| 2526 | |||
| 2527 | struct frame *f = XFRAME (w->frame); | ||
| 2528 | struct tty_display_info *tty = FRAME_TTY (f); | 2680 | struct tty_display_info *tty = FRAME_TTY (f); |
| 2681 | int face_id = tty->mouse_highlight.mouse_face_face_id; | ||
| 2682 | int save_x, save_y, pos_x, pos_y; | ||
| 2529 | 2683 | ||
| 2530 | if (/* If window is in the process of being destroyed, don't bother | 2684 | if (end_hpos >= row->used[TEXT_AREA]) |
| 2531 | to do anything. */ | 2685 | nglyphs = row->used[TEXT_AREA] - start_hpos; |
| 2532 | w->current_matrix != NULL | ||
| 2533 | /* Recognize when we are called to operate on rows that don't exist | ||
| 2534 | anymore. This can happen when a window is split. */ | ||
| 2535 | && mouse_face_end_row < w->current_matrix->nrows) | ||
| 2536 | { | ||
| 2537 | /* write_glyphs writes at cursor position, so we need to | ||
| 2538 | temporarily move cursor coordinates to the beginning of | ||
| 2539 | the highlight region. */ | ||
| 2540 | |||
| 2541 | /* Save current cursor co-ordinates */ | ||
| 2542 | save_y = curY (tty); | ||
| 2543 | save_x = curX (tty); | ||
| 2544 | 2686 | ||
| 2545 | /* Note that mouse_face_beg_row etc. are window relative. */ | 2687 | pos_y = row->y + WINDOW_TOP_EDGE_Y (w); |
| 2546 | for (i = mouse_face_beg_row; i <= mouse_face_end_row; i++) | 2688 | pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w); |
| 2547 | { | ||
| 2548 | int start_hpos, end_hpos, nglyphs; | ||
| 2549 | struct glyph_row *row = MATRIX_ROW (w->current_matrix, i); | ||
| 2550 | |||
| 2551 | /* Don't do anything if row doesn't have valid contents. */ | ||
| 2552 | if (!row->enabled_p) | ||
| 2553 | continue; | ||
| 2554 | 2689 | ||
| 2555 | /* For all but the first row, the highlight starts at column 0. */ | 2690 | /* Save current cursor co-ordinates. */ |
| 2556 | if (i == mouse_face_beg_row) | 2691 | save_y = curY (tty); |
| 2557 | start_hpos = mouse_face_beg_col; | 2692 | save_x = curX (tty); |
| 2558 | else | 2693 | cursor_to (f, pos_y, pos_x); |
| 2559 | start_hpos = 0; | ||
| 2560 | 2694 | ||
| 2561 | if (i == mouse_face_end_row) | 2695 | if (draw == DRAW_MOUSE_FACE) |
| 2562 | end_hpos = mouse_face_end_col; | 2696 | tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos, |
| 2563 | else | 2697 | nglyphs, face_id); |
| 2564 | { | 2698 | else if (draw == DRAW_NORMAL_TEXT) |
| 2565 | end_hpos = row->used[TEXT_AREA]; | 2699 | write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs); |
| 2566 | if (draw == DRAW_NORMAL_TEXT) | ||
| 2567 | row->fill_line_p = 1; /* Clear to end of line */ | ||
| 2568 | } | ||
| 2569 | 2700 | ||
| 2570 | if (end_hpos <= start_hpos) | 2701 | cursor_to (f, save_y, save_x); |
| 2571 | continue; | ||
| 2572 | /* Record that some glyphs of this row are displayed in | ||
| 2573 | mouse-face. */ | ||
| 2574 | row->mouse_face_p = draw > 0; | ||
| 2575 | |||
| 2576 | nglyphs = end_hpos - start_hpos; | ||
| 2577 | |||
| 2578 | if (end_hpos >= row->used[TEXT_AREA]) | ||
| 2579 | nglyphs = row->used[TEXT_AREA] - start_hpos; | ||
| 2580 | |||
| 2581 | pos_y = row->y + WINDOW_TOP_EDGE_Y (w); | ||
| 2582 | pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos | ||
| 2583 | + WINDOW_LEFT_EDGE_X (w); | ||
| 2584 | |||
| 2585 | cursor_to (f, pos_y, pos_x); | ||
| 2586 | |||
| 2587 | if (draw == DRAW_MOUSE_FACE) | ||
| 2588 | { | ||
| 2589 | tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos, | ||
| 2590 | nglyphs, mouse_face_face_id); | ||
| 2591 | } | ||
| 2592 | else /* draw == DRAW_NORMAL_TEXT */ | ||
| 2593 | write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs); | ||
| 2594 | } | ||
| 2595 | cursor_to (f, save_y, save_x); | ||
| 2596 | } | ||
| 2597 | } | ||
| 2598 | |||
| 2599 | static void | ||
| 2600 | term_clear_mouse_face (void) | ||
| 2601 | { | ||
| 2602 | if (!NILP (mouse_face_window)) | ||
| 2603 | term_show_mouse_face (DRAW_NORMAL_TEXT); | ||
| 2604 | |||
| 2605 | mouse_face_beg_row = mouse_face_beg_col = -1; | ||
| 2606 | mouse_face_end_row = mouse_face_end_col = -1; | ||
| 2607 | mouse_face_window = Qnil; | ||
| 2608 | } | ||
| 2609 | |||
| 2610 | /* Find the glyph matrix position of buffer position POS in window W. | ||
| 2611 | *HPOS and *VPOS are set to the positions found. W's current glyphs | ||
| 2612 | must be up to date. If POS is above window start return (0, 0). | ||
| 2613 | If POS is after end of W, return end of last line in W. | ||
| 2614 | - taken from msdos.c */ | ||
| 2615 | static int | ||
| 2616 | fast_find_position (struct window *w, EMACS_INT pos, int *hpos, int *vpos) | ||
| 2617 | { | ||
| 2618 | int i, lastcol, maybe_next_line_p = 0; | ||
| 2619 | EMACS_INT line_start_position; | ||
| 2620 | int yb = window_text_bottom_y (w); | ||
| 2621 | struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0), *best_row = row; | ||
| 2622 | |||
| 2623 | while (row->y < yb) | ||
| 2624 | { | ||
| 2625 | if (row->used[TEXT_AREA]) | ||
| 2626 | line_start_position = row->glyphs[TEXT_AREA]->charpos; | ||
| 2627 | else | ||
| 2628 | line_start_position = 0; | ||
| 2629 | |||
| 2630 | if (line_start_position > pos) | ||
| 2631 | break; | ||
| 2632 | /* If the position sought is the end of the buffer, | ||
| 2633 | don't include the blank lines at the bottom of the window. */ | ||
| 2634 | else if (line_start_position == pos | ||
| 2635 | && pos == BUF_ZV (XBUFFER (w->buffer))) | ||
| 2636 | { | ||
| 2637 | maybe_next_line_p = 1; | ||
| 2638 | break; | ||
| 2639 | } | ||
| 2640 | else if (line_start_position > 0) | ||
| 2641 | best_row = row; | ||
| 2642 | |||
| 2643 | /* Don't overstep the last matrix row, lest we get into the | ||
| 2644 | never-never land... */ | ||
| 2645 | if (row->y + 1 >= yb) | ||
| 2646 | break; | ||
| 2647 | |||
| 2648 | ++row; | ||
| 2649 | } | ||
| 2650 | |||
| 2651 | /* Find the right column within BEST_ROW. */ | ||
| 2652 | lastcol = 0; | ||
| 2653 | row = best_row; | ||
| 2654 | for (i = 0; i < row->used[TEXT_AREA]; i++) | ||
| 2655 | { | ||
| 2656 | struct glyph *glyph = row->glyphs[TEXT_AREA] + i; | ||
| 2657 | EMACS_INT charpos; | ||
| 2658 | |||
| 2659 | charpos = glyph->charpos; | ||
| 2660 | if (charpos == pos) | ||
| 2661 | { | ||
| 2662 | *hpos = i; | ||
| 2663 | *vpos = row->y; | ||
| 2664 | return 1; | ||
| 2665 | } | ||
| 2666 | else if (charpos > pos) | ||
| 2667 | break; | ||
| 2668 | else if (charpos > 0) | ||
| 2669 | lastcol = i; | ||
| 2670 | } | ||
| 2671 | |||
| 2672 | /* If we're looking for the end of the buffer, | ||
| 2673 | and we didn't find it in the line we scanned, | ||
| 2674 | use the start of the following line. */ | ||
| 2675 | if (maybe_next_line_p) | ||
| 2676 | { | ||
| 2677 | ++row; | ||
| 2678 | lastcol = 0; | ||
| 2679 | } | ||
| 2680 | |||
| 2681 | *vpos = row->y; | ||
| 2682 | *hpos = lastcol + 1; | ||
| 2683 | return 0; | ||
| 2684 | } | ||
| 2685 | |||
| 2686 | static void | ||
| 2687 | term_mouse_highlight (struct frame *f, int x, int y) | ||
| 2688 | { | ||
| 2689 | enum window_part part; | ||
| 2690 | Lisp_Object window; | ||
| 2691 | struct window *w; | ||
| 2692 | struct buffer *b; | ||
| 2693 | |||
| 2694 | if (NILP (Vmouse_highlight) | ||
| 2695 | || !f->glyphs_initialized_p) | ||
| 2696 | return; | ||
| 2697 | |||
| 2698 | /* Which window is that in? */ | ||
| 2699 | window = window_from_coordinates (f, x, y, &part, &x, &y, 0); | ||
| 2700 | |||
| 2701 | /* Not on a window -> return. */ | ||
| 2702 | if (!WINDOWP (window)) | ||
| 2703 | return; | ||
| 2704 | |||
| 2705 | if (!EQ (window, mouse_face_window)) | ||
| 2706 | term_clear_mouse_face (); | ||
| 2707 | |||
| 2708 | w = XWINDOW (window); | ||
| 2709 | |||
| 2710 | /* Are we in a window whose display is up to date? | ||
| 2711 | And verify the buffer's text has not changed. */ | ||
| 2712 | b = XBUFFER (w->buffer); | ||
| 2713 | if (part == ON_TEXT | ||
| 2714 | && EQ (w->window_end_valid, w->buffer) | ||
| 2715 | && XFASTINT (w->last_modified) == BUF_MODIFF (b) | ||
| 2716 | && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b)) | ||
| 2717 | { | ||
| 2718 | int i, nrows = w->current_matrix->nrows; | ||
| 2719 | EMACS_INT pos; | ||
| 2720 | struct glyph_row *row; | ||
| 2721 | struct glyph *glyph; | ||
| 2722 | |||
| 2723 | /* Find the glyph under X/Y. */ | ||
| 2724 | glyph = NULL; | ||
| 2725 | if (y >= 0 && y < nrows) | ||
| 2726 | { | ||
| 2727 | row = MATRIX_ROW (w->current_matrix, y); | ||
| 2728 | /* Give up if some row before the one we are looking for is | ||
| 2729 | not enabled. */ | ||
| 2730 | for (i = 0; i <= y; i++) | ||
| 2731 | if (!MATRIX_ROW (w->current_matrix, i)->enabled_p) | ||
| 2732 | break; | ||
| 2733 | if (i > y /* all rows upto and including the one at Y are enabled */ | ||
| 2734 | && row->displays_text_p | ||
| 2735 | && x < window_box_width (w, TEXT_AREA)) | ||
| 2736 | { | ||
| 2737 | glyph = row->glyphs[TEXT_AREA]; | ||
| 2738 | if (x >= row->used[TEXT_AREA]) | ||
| 2739 | glyph = NULL; | ||
| 2740 | else | ||
| 2741 | { | ||
| 2742 | glyph += x; | ||
| 2743 | if (!BUFFERP (glyph->object)) | ||
| 2744 | glyph = NULL; | ||
| 2745 | } | ||
| 2746 | } | ||
| 2747 | } | ||
| 2748 | |||
| 2749 | /* Clear mouse face if X/Y not over text. */ | ||
| 2750 | if (glyph == NULL) | ||
| 2751 | { | ||
| 2752 | term_clear_mouse_face (); | ||
| 2753 | return; | ||
| 2754 | } | ||
| 2755 | |||
| 2756 | if (!BUFFERP (glyph->object)) | ||
| 2757 | abort (); | ||
| 2758 | pos = glyph->charpos; | ||
| 2759 | |||
| 2760 | /* Check for mouse-face. */ | ||
| 2761 | { | ||
| 2762 | Lisp_Object mouse_face, overlay, position, *overlay_vec; | ||
| 2763 | int noverlays; | ||
| 2764 | EMACS_INT obegv, ozv; | ||
| 2765 | struct buffer *obuf; | ||
| 2766 | |||
| 2767 | /* If we get an out-of-range value, return now; avoid an error. */ | ||
| 2768 | if (pos > BUF_Z (b)) | ||
| 2769 | return; | ||
| 2770 | |||
| 2771 | /* Make the window's buffer temporarily current for | ||
| 2772 | overlays_at and compute_char_face. */ | ||
| 2773 | obuf = current_buffer; | ||
| 2774 | current_buffer = b; | ||
| 2775 | obegv = BEGV; | ||
| 2776 | ozv = ZV; | ||
| 2777 | BEGV = BEG; | ||
| 2778 | ZV = Z; | ||
| 2779 | |||
| 2780 | /* Is this char mouse-active? */ | ||
| 2781 | XSETINT (position, pos); | ||
| 2782 | |||
| 2783 | /* Put all the overlays we want in a vector in overlay_vec. */ | ||
| 2784 | GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL, 0); | ||
| 2785 | /* Sort overlays into increasing priority order. */ | ||
| 2786 | noverlays = sort_overlays (overlay_vec, noverlays, w); | ||
| 2787 | |||
| 2788 | /* Check mouse-face highlighting. */ | ||
| 2789 | if (!(EQ (window, mouse_face_window) | ||
| 2790 | && y >= mouse_face_beg_row | ||
| 2791 | && y <= mouse_face_end_row | ||
| 2792 | && (y > mouse_face_beg_row | ||
| 2793 | || x >= mouse_face_beg_col) | ||
| 2794 | && (y < mouse_face_end_row | ||
| 2795 | || x < mouse_face_end_col | ||
| 2796 | || mouse_face_past_end))) | ||
| 2797 | { | ||
| 2798 | /* Clear the display of the old active region, if any. */ | ||
| 2799 | term_clear_mouse_face (); | ||
| 2800 | |||
| 2801 | /* Find the highest priority overlay that has a mouse-face | ||
| 2802 | property. */ | ||
| 2803 | overlay = Qnil; | ||
| 2804 | for (i = noverlays - 1; i >= 0; --i) | ||
| 2805 | { | ||
| 2806 | mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face); | ||
| 2807 | if (!NILP (mouse_face)) | ||
| 2808 | { | ||
| 2809 | overlay = overlay_vec[i]; | ||
| 2810 | break; | ||
| 2811 | } | ||
| 2812 | } | ||
| 2813 | |||
| 2814 | /* If no overlay applies, get a text property. */ | ||
| 2815 | if (NILP (overlay)) | ||
| 2816 | mouse_face = Fget_text_property (position, Qmouse_face, | ||
| 2817 | w->buffer); | ||
| 2818 | |||
| 2819 | /* Handle the overlay case. */ | ||
| 2820 | if (!NILP (overlay)) | ||
| 2821 | { | ||
| 2822 | /* Find the range of text around this char that | ||
| 2823 | should be active. */ | ||
| 2824 | Lisp_Object before, after; | ||
| 2825 | EMACS_INT ignore; | ||
| 2826 | |||
| 2827 | |||
| 2828 | before = Foverlay_start (overlay); | ||
| 2829 | after = Foverlay_end (overlay); | ||
| 2830 | /* Record this as the current active region. */ | ||
| 2831 | fast_find_position (w, XFASTINT (before), | ||
| 2832 | &mouse_face_beg_col, | ||
| 2833 | &mouse_face_beg_row); | ||
| 2834 | |||
| 2835 | mouse_face_past_end | ||
| 2836 | = !fast_find_position (w, XFASTINT (after), | ||
| 2837 | &mouse_face_end_col, | ||
| 2838 | &mouse_face_end_row); | ||
| 2839 | mouse_face_window = window; | ||
| 2840 | |||
| 2841 | mouse_face_face_id | ||
| 2842 | = face_at_buffer_position (w, pos, 0, 0, | ||
| 2843 | &ignore, pos + 1, 1, -1); | ||
| 2844 | |||
| 2845 | /* Display it as active. */ | ||
| 2846 | term_show_mouse_face (DRAW_MOUSE_FACE); | ||
| 2847 | } | ||
| 2848 | /* Handle the text property case. */ | ||
| 2849 | else if (!NILP (mouse_face)) | ||
| 2850 | { | ||
| 2851 | /* Find the range of text around this char that | ||
| 2852 | should be active. */ | ||
| 2853 | Lisp_Object before, after, beginning, end; | ||
| 2854 | EMACS_INT ignore; | ||
| 2855 | |||
| 2856 | beginning = Fmarker_position (w->start); | ||
| 2857 | XSETINT (end, (BUF_Z (b) - XFASTINT (w->window_end_pos))); | ||
| 2858 | before | ||
| 2859 | = Fprevious_single_property_change (make_number (pos + 1), | ||
| 2860 | Qmouse_face, | ||
| 2861 | w->buffer, beginning); | ||
| 2862 | after | ||
| 2863 | = Fnext_single_property_change (position, Qmouse_face, | ||
| 2864 | w->buffer, end); | ||
| 2865 | |||
| 2866 | /* Record this as the current active region. */ | ||
| 2867 | fast_find_position (w, XFASTINT (before), | ||
| 2868 | &mouse_face_beg_col, | ||
| 2869 | &mouse_face_beg_row); | ||
| 2870 | mouse_face_past_end | ||
| 2871 | = !fast_find_position (w, XFASTINT (after), | ||
| 2872 | &mouse_face_end_col, | ||
| 2873 | &mouse_face_end_row); | ||
| 2874 | mouse_face_window = window; | ||
| 2875 | |||
| 2876 | mouse_face_face_id | ||
| 2877 | = face_at_buffer_position (w, pos, 0, 0, | ||
| 2878 | &ignore, pos + 1, 1, -1); | ||
| 2879 | |||
| 2880 | /* Display it as active. */ | ||
| 2881 | term_show_mouse_face (DRAW_MOUSE_FACE); | ||
| 2882 | } | ||
| 2883 | } | ||
| 2884 | |||
| 2885 | /* Look for a `help-echo' property. */ | ||
| 2886 | { | ||
| 2887 | Lisp_Object help; | ||
| 2888 | |||
| 2889 | /* Check overlays first. */ | ||
| 2890 | help = Qnil; | ||
| 2891 | for (i = noverlays - 1; i >= 0 && NILP (help); --i) | ||
| 2892 | { | ||
| 2893 | overlay = overlay_vec[i]; | ||
| 2894 | help = Foverlay_get (overlay, Qhelp_echo); | ||
| 2895 | } | ||
| 2896 | |||
| 2897 | if (!NILP (help)) | ||
| 2898 | { | ||
| 2899 | help_echo_string = help; | ||
| 2900 | help_echo_window = window; | ||
| 2901 | help_echo_object = overlay; | ||
| 2902 | help_echo_pos = pos; | ||
| 2903 | } | ||
| 2904 | /* Try text properties. */ | ||
| 2905 | else if (NILP (help) | ||
| 2906 | && ((STRINGP (glyph->object) | ||
| 2907 | && glyph->charpos >= 0 | ||
| 2908 | && glyph->charpos < SCHARS (glyph->object)) | ||
| 2909 | || (BUFFERP (glyph->object) | ||
| 2910 | && glyph->charpos >= BEGV | ||
| 2911 | && glyph->charpos < ZV))) | ||
| 2912 | { | ||
| 2913 | help = Fget_text_property (make_number (glyph->charpos), | ||
| 2914 | Qhelp_echo, glyph->object); | ||
| 2915 | if (!NILP (help)) | ||
| 2916 | { | ||
| 2917 | help_echo_string = help; | ||
| 2918 | help_echo_window = window; | ||
| 2919 | help_echo_object = glyph->object; | ||
| 2920 | help_echo_pos = glyph->charpos; | ||
| 2921 | } | ||
| 2922 | } | ||
| 2923 | } | ||
| 2924 | |||
| 2925 | BEGV = obegv; | ||
| 2926 | ZV = ozv; | ||
| 2927 | current_buffer = obuf; | ||
| 2928 | } | ||
| 2929 | } | ||
| 2930 | } | 2702 | } |
| 2931 | 2703 | ||
| 2932 | static int | 2704 | static int |
| @@ -2936,7 +2708,7 @@ term_mouse_movement (FRAME_PTR frame, Gpm_Event *event) | |||
| 2936 | if (event->x != last_mouse_x || event->y != last_mouse_y) | 2708 | if (event->x != last_mouse_x || event->y != last_mouse_y) |
| 2937 | { | 2709 | { |
| 2938 | frame->mouse_moved = 1; | 2710 | frame->mouse_moved = 1; |
| 2939 | term_mouse_highlight (frame, event->x, event->y); | 2711 | note_mouse_highlight (frame, event->x, event->y); |
| 2940 | /* Remember which glyph we're now on. */ | 2712 | /* Remember which glyph we're now on. */ |
| 2941 | last_mouse_x = event->x; | 2713 | last_mouse_x = event->x; |
| 2942 | last_mouse_y = event->y; | 2714 | last_mouse_y = event->y; |
| @@ -3309,8 +3081,7 @@ static void | |||
| 3309 | dissociate_if_controlling_tty (int fd) | 3081 | dissociate_if_controlling_tty (int fd) |
| 3310 | { | 3082 | { |
| 3311 | #ifndef DOS_NT | 3083 | #ifndef DOS_NT |
| 3312 | int pgid; | 3084 | int pgid = tcgetpgrp (fd); /* If tcgetpgrp succeeds, fd is the ctty. */ |
| 3313 | EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */ | ||
| 3314 | if (pgid != -1) | 3085 | if (pgid != -1) |
| 3315 | { | 3086 | { |
| 3316 | #if defined (USG5) | 3087 | #if defined (USG5) |
| @@ -3407,7 +3178,7 @@ init_tty (const char *name, const char *terminal_type, int must_succeed) | |||
| 3407 | 3178 | ||
| 3408 | #ifdef HAVE_GPM | 3179 | #ifdef HAVE_GPM |
| 3409 | terminal->mouse_position_hook = term_mouse_position; | 3180 | terminal->mouse_position_hook = term_mouse_position; |
| 3410 | mouse_face_window = Qnil; | 3181 | tty->mouse_highlight.mouse_face_window = Qnil; |
| 3411 | #endif | 3182 | #endif |
| 3412 | 3183 | ||
| 3413 | 3184 | ||
| @@ -4042,8 +3813,6 @@ bigger, or it may make it blink, or it may do nothing at all. */); | |||
| 4042 | #ifdef HAVE_GPM | 3813 | #ifdef HAVE_GPM |
| 4043 | defsubr (&Sgpm_mouse_start); | 3814 | defsubr (&Sgpm_mouse_start); |
| 4044 | defsubr (&Sgpm_mouse_stop); | 3815 | defsubr (&Sgpm_mouse_stop); |
| 4045 | |||
| 4046 | staticpro (&mouse_face_window); | ||
| 4047 | #endif /* HAVE_GPM */ | 3816 | #endif /* HAVE_GPM */ |
| 4048 | 3817 | ||
| 4049 | #ifndef DOS_NT | 3818 | #ifndef DOS_NT |
| @@ -4056,7 +3825,3 @@ bigger, or it may make it blink, or it may do nothing at all. */); | |||
| 4056 | encode_terminal_dst = NULL; | 3825 | encode_terminal_dst = NULL; |
| 4057 | } | 3826 | } |
| 4058 | 3827 | ||
| 4059 | |||
| 4060 | |||
| 4061 | /* arch-tag: 498e7449-6f2e-45e2-91dd-b7d4ca488193 | ||
| 4062 | (do not change this comment) */ | ||