aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman1994-03-31 23:17:23 +0000
committerRichard M. Stallman1994-03-31 23:17:23 +0000
commitb8009dd11c657bac01ca1ab43fed44ab896448a5 (patch)
tree18b95f2e58f7792e2e0a8c6d6ea2a234fc1dd576 /src
parent6f13448620a9b66c014947fbfe3834c72f7b7f30 (diff)
downloademacs-b8009dd11c657bac01ca1ab43fed44ab896448a5.tar.gz
emacs-b8009dd11c657bac01ca1ab43fed44ab896448a5.zip
[INCLUDED_FCNTL]: Don't include fcntl.h again.
(XTread_socket, MotionNotify and LeaveNotify cases): If not in any frame, call clear_mouse_face. (x_term_init): Set frame_up_to_date_hook. (XTframe_up_to_date): New function. (XTupdate_begin): Turn off mouse face display, and defer it. (XTupdate_end): Undefer. (mouse_face_defer): New variable. (mouse_face_mouse_frame, mouse_face_mouse_x, mouse_face_mouse_y): New variables. (dumpglyphs): Handle HL = 3 by using mouse_face_face_id. (note_mouse_movement): Check for mouse face. (show_mouse_face, fast_find_position): New functions. (clear_mouse_face): New functions. (mouse_face_beg, mouse_face_end, mouse_face_face_id): New variables. (mouse_face_window): New variable. (syms_of_xterm): Init and staticpro it.
Diffstat (limited to 'src')
-rw-r--r--src/xterm.c323
1 files changed, 320 insertions, 3 deletions
diff --git a/src/xterm.c b/src/xterm.c
index 474082d7b47..799a3068b6f 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1,5 +1,5 @@
1/* X Communication module for terminals which understand the X protocol. 1/* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993 Free Software Foundation, Inc. 2 Copyright (C) 1989, 1993, 1994 Free Software Foundation, Inc.
3 3
4This file is part of GNU Emacs. 4This file is part of GNU Emacs.
5 5
@@ -71,7 +71,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
71#include "systty.h" 71#include "systty.h"
72#include "systime.h" 72#include "systime.h"
73 73
74#ifndef INCLUDED_FCNTL
74#include <fcntl.h> 75#include <fcntl.h>
76#endif
75#include <ctype.h> 77#include <ctype.h>
76#include <errno.h> 78#include <errno.h>
77#include <setjmp.h> 79#include <setjmp.h>
@@ -275,6 +277,21 @@ unsigned int x_mouse_grabbed;
275 it's somewhat accurate. */ 277 it's somewhat accurate. */
276static Time last_mouse_movement_time; 278static Time last_mouse_movement_time;
277 279
280/* These variables describe the range of text currently shown
281 in its mouse-face, together with the window they apply to.
282 As long as the mouse stays within this range, we need not
283 redraw anything on its account. */
284static int mouse_face_beg, mouse_face_end;
285static Lisp_Object mouse_face_window;
286static int mouse_face_face_id;
287
288/* FRAME and X, Y position of mouse when last checked for highlighting. */
289static FRAME_PTR mouse_face_mouse_frame;
290static int mouse_face_mouse_x, mouse_face_mouse_y;
291
292/* Nonzero means defer mouse-motion highlighting. */
293static int mouse_face_defer;
294
278#ifdef HAVE_X11 295#ifdef HAVE_X11
279/* `t' if a mouse button is depressed. */ 296/* `t' if a mouse button is depressed. */
280 297
@@ -293,6 +310,8 @@ extern Window requestor_window;
293/* Nonzero enables some debugging for the X interface code. */ 310/* Nonzero enables some debugging for the X interface code. */
294extern int _Xdebug; 311extern int _Xdebug;
295 312
313extern Qface, Qmouse_face;
314
296#else /* ! defined (HAVE_X11) */ 315#else /* ! defined (HAVE_X11) */
297 316
298/* Bit patterns for the mouse cursor. */ 317/* Bit patterns for the mouse cursor. */
@@ -334,6 +353,10 @@ static void flashback ();
334static void redraw_previous_char (); 353static void redraw_previous_char ();
335static unsigned int x_x_to_emacs_modifiers (); 354static unsigned int x_x_to_emacs_modifiers ();
336 355
356static void note_mouse_highlight ();
357static void clear_mouse_face ();
358static void show_mouse_face ();
359
337#ifndef HAVE_X11 360#ifndef HAVE_X11
338static void dumpqueue (); 361static void dumpqueue ();
339#endif /* HAVE_X11 */ 362#endif /* HAVE_X11 */
@@ -367,6 +390,13 @@ XTupdate_begin (f)
367 highlight = 0; 390 highlight = 0;
368 391
369 BLOCK_INPUT; 392 BLOCK_INPUT;
393
394 if (f == mouse_face_mouse_frame)
395 {
396 mouse_face_defer = 1;
397 if (!NILP (mouse_face_window))
398 clear_mouse_face ();
399 }
370#ifndef HAVE_X11 400#ifndef HAVE_X11
371 dumpqueue (); 401 dumpqueue ();
372#endif /* HAVE_X11 */ 402#endif /* HAVE_X11 */
@@ -391,9 +421,32 @@ XTupdate_end (f)
391 421
392 x_display_cursor (f, 1); 422 x_display_cursor (f, 1);
393 423
424 if (f == mouse_face_mouse_frame)
425 mouse_face_defer = 0;
426#if 0
427 /* This fails in the case of having updated only the echo area
428 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
429 has no relation to the current contents, and its charstarts
430 have no relation to the contents of the window-buffer.
431 I don't know a clean way to check
432 for that case. window_end_valid isn't set up yet. */
433 if (f == mouse_face_mouse_frame)
434 note_mouse_highlight (f, mouse_face_mouse_x, mouse_face_mouse_y);
435#endif
436
394 XFlushQueue (); 437 XFlushQueue ();
395 UNBLOCK_INPUT; 438 UNBLOCK_INPUT;
396} 439}
440
441/* This is called when all windows on frame F are now up to date. */
442
443static
444XTframe_up_to_date (f)
445 FRAME_PTR f;
446{
447 if (f == mouse_face_mouse_frame)
448 note_mouse_highlight (f, mouse_face_mouse_x, mouse_face_mouse_y);
449}
397 450
398/* External interface to control of standout mode. 451/* External interface to control of standout mode.
399 Call this when about to modify line at position VPOS 452 Call this when about to modify line at position VPOS
@@ -461,7 +514,8 @@ XTcursor_to (row, col)
461 514
462/* Display a sequence of N glyphs found at GP. 515/* Display a sequence of N glyphs found at GP.
463 WINDOW is the x-window to output to. LEFT and TOP are starting coords. 516 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
464 HL is 1 if this text is highlighted, 2 if the cursor is on it. 517 HL is 1 if this text is highlighted, 2 if the cursor is on it,
518 3 if should appear in its mouse-face.
465 519
466 FONT is the default font to use (for glyphs whose font-code is 0). 520 FONT is the default font to use (for glyphs whose font-code is 0).
467 521
@@ -526,6 +580,10 @@ dumpglyphs (f, left, top, gp, n, hl)
526 int defaulted = 1; 580 int defaulted = 1;
527 int gc_temporary = 0; 581 int gc_temporary = 0;
528 582
583 /* HL = 3 means use a mouse face previously chosen. */
584 if (hl == 3)
585 cf = mouse_face_face_id;
586
529 /* First look at the face of the text itself. */ 587 /* First look at the face of the text itself. */
530 if (cf != 0) 588 if (cf != 0)
531 { 589 {
@@ -1202,7 +1260,7 @@ dumprectangle (f, left, top, cols, rows)
1202 || right > intborder + f->width * FONT_WIDTH (f->display.x->font)) 1260 || right > intborder + f->width * FONT_WIDTH (f->display.x->font))
1203 dumpborder (f, 0); 1261 dumpborder (f, 0);
1204 } 1262 }
1205#endif /* HAVE_X11 Window manger does this for X11. */ 1263#endif /* not HAVE_X11 Window manger does this for X11. */
1206 1264
1207 /* Convert rectangle edges in pixels to edges in chars. 1265 /* Convert rectangle edges in pixels to edges in chars.
1208 Round down for left and top, up for right and bottom. */ 1266 Round down for left and top, up for right and bottom. */
@@ -1810,6 +1868,7 @@ construct_menu_click (result, event, f)
1810 If the mouse is over a different glyph than it was last time, tell 1868 If the mouse is over a different glyph than it was last time, tell
1811 the mainstream emacs code by setting mouse_moved. If not, ask for 1869 the mainstream emacs code by setting mouse_moved. If not, ask for
1812 another motion event, so we can check again the next time it moves. */ 1870 another motion event, so we can check again the next time it moves. */
1871
1813static void 1872static void
1814note_mouse_movement (frame, event) 1873note_mouse_movement (frame, event)
1815 FRAME_PTR frame; 1874 FRAME_PTR frame;
@@ -1826,6 +1885,18 @@ note_mouse_movement (frame, event)
1826 { 1885 {
1827 mouse_moved = 1; 1886 mouse_moved = 1;
1828 last_mouse_scroll_bar = Qnil; 1887 last_mouse_scroll_bar = Qnil;
1888
1889 note_mouse_highlight (frame, event->x, event->y);
1890
1891 /* Ask for another mouse motion event. */
1892 {
1893 int dummy;
1894
1895 XQueryPointer (event->display, event->window,
1896 (Window *) &dummy, (Window *) &dummy,
1897 &dummy, &dummy, &dummy, &dummy,
1898 (unsigned int *) &dummy);
1899 }
1829 } 1900 }
1830 else 1901 else
1831 { 1902 {
@@ -1841,6 +1912,240 @@ note_mouse_movement (frame, event)
1841 } 1912 }
1842} 1913}
1843 1914
1915/* Take proper action when the mouse has moved to position X, Y on frame F
1916 as regards highlighting characters that have mouse-face properties.
1917 Also dehighlighting chars where the mouse was before. */
1918
1919static void
1920note_mouse_highlight (f, x, y)
1921 FRAME_PTR f;
1922{
1923 int row, column, portion;
1924 XRectangle new_glyph;
1925 Lisp_Object window;
1926 struct window *w;
1927
1928 mouse_face_mouse_x = x;
1929 mouse_face_mouse_y = y;
1930 mouse_face_mouse_frame = f;
1931
1932 if (mouse_face_defer)
1933 return;
1934
1935 /* Find out which glyph the mouse is on. */
1936 pixel_to_glyph_coords (f, x, y, &column, &row,
1937 &new_glyph, x_mouse_grabbed);
1938
1939 /* Which window is that in? */
1940 window = window_from_coordinates (f, column, row, &portion);
1941 w = XWINDOW (window);
1942
1943 /* If we were displaying active text in another window, clear that. */
1944 if (! EQ (window, mouse_face_window))
1945 clear_mouse_face ();
1946
1947 /* Are we in a window whose display is up to date? */
1948 if (WINDOWP (window) && portion == 0
1949 && EQ (w->window_end_valid, Qt))
1950 {
1951 int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
1952 int i, pos;
1953
1954 /* Find which buffer position the mouse corresponds to. */
1955 for (i = column; i >= 0; i--)
1956 if (ptr[i] > 0)
1957 break;
1958 pos = ptr[i];
1959 /* Is it outside the displayed active region (if any)? */
1960 if (pos > 0
1961 && ! (EQ (window, mouse_face_window)
1962 && pos >= mouse_face_beg && pos < mouse_face_end))
1963 {
1964 Lisp_Object mouse_face, overlay, position;
1965 Lisp_Object *overlay_vec;
1966 int len, noverlays, ignor1;
1967
1968 /* Yes. Clear the display of the old active region, if any. */
1969 clear_mouse_face ();
1970
1971 /* Is this char mouse-active? */
1972 XSET (position, Lisp_Int, pos);
1973
1974 len = 10;
1975 overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
1976
1977 /* Put all the overlays we want in a vector in overlay_vec.
1978 Store the length in len. */
1979 noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, &ignor1);
1980 sort_overlays (overlay_vec, noverlays, w);
1981
1982 /* Find the highest priority overlay that has a mouse-face prop. */
1983 overlay = Qnil;
1984 for (i = 0; i < noverlays; i++)
1985 {
1986 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
1987 if (!NILP (mouse_face))
1988 {
1989 overlay = overlay_vec[i];
1990 break;
1991 }
1992 }
1993 free (overlay_vec);
1994 /* If no overlay applies, get a text property. */
1995 if (NILP (overlay))
1996 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
1997
1998 /* Handle the overlay case. */
1999 if (! NILP (overlay))
2000 {
2001 /* Find the range of text around this char that
2002 should be active. */
2003 Lisp_Object before, after;
2004 int ignore;
2005
2006 before = Foverlay_start (overlay);
2007 after = Foverlay_end (overlay);
2008 /* Record this as the current active region. */
2009 mouse_face_beg = XFASTINT (before);
2010 mouse_face_end = XFASTINT (after);
2011 mouse_face_window = window;
2012 mouse_face_face_id = compute_char_face (f, w, pos, 0, 0,
2013 &ignore, pos + 1, 1);
2014
2015 /* Display it as active. */
2016 show_mouse_face (1);
2017 }
2018 /* Handle the text property case. */
2019 else if (! NILP (mouse_face))
2020 {
2021 /* Find the range of text around this char that
2022 should be active. */
2023 Lisp_Object before, after, beginning, end;
2024 int ignore;
2025
2026 beginning = Fmarker_position (w->start);
2027 XSET (end, Lisp_Int,
2028 (BUF_ZV (XBUFFER (w->buffer))
2029 - XFASTINT (w->window_end_pos)));
2030 before
2031 = Fprevious_single_property_change (make_number (pos + 1),
2032 Qmouse_face,
2033 w->buffer, beginning);
2034 after
2035 = Fnext_single_property_change (position, Qmouse_face,
2036 w->buffer, end);
2037 /* Record this as the current active region. */
2038 mouse_face_beg = XFASTINT (before);
2039 mouse_face_end = XFASTINT (after);
2040 mouse_face_window = window;
2041 mouse_face_face_id
2042 = compute_char_face (f, w, pos, 0, 0,
2043 &ignore, pos + 1, 1);
2044
2045 /* Display it as active. */
2046 show_mouse_face (1);
2047 }
2048 }
2049 else if (pos <= 0)
2050 clear_mouse_face ();
2051 }
2052}
2053
2054/* Find the row and column of position POS in window WINDOW.
2055 Store them in *COLUMNP and *ROWP.
2056 This assumes display in WINDOW is up to date. */
2057
2058static int
2059fast_find_position (window, pos, columnp, rowp)
2060 Lisp_Object window;
2061 int pos;
2062 int *columnp, *rowp;
2063{
2064 struct window *w = XWINDOW (window);
2065 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2066 int i;
2067 int row;
2068 int left = w->left;
2069 int top = w->top;
2070 int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
2071 int width = window_internal_width (w);
2072 int *charstarts;
2073
2074 for (i = 0;
2075 i < height;
2076 i++)
2077 {
2078 int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left];
2079 if (linestart > pos)
2080 break;
2081 if (linestart > 0)
2082 row = i;
2083 }
2084
2085 charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row];
2086 for (i = 0; i < width; i++)
2087 if (charstarts[left + i] == pos)
2088 {
2089 *rowp = row + top;
2090 *columnp = i + left;
2091 return 1;
2092 }
2093
2094 return 0;
2095}
2096
2097/* Display the active region described by mouse_face_*
2098 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2099
2100static void
2101show_mouse_face (hl)
2102 int hl;
2103{
2104 int begcol, begrow, endcol, endrow;
2105 struct window *w = XWINDOW (mouse_face_window);
2106 int width = window_internal_width (w);
2107 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2108 int i;
2109
2110 fast_find_position (mouse_face_window, mouse_face_beg,
2111 &begcol, &begrow);
2112 fast_find_position (mouse_face_window, mouse_face_end,
2113 &endcol, &endrow);
2114
2115 x_display_cursor (f, 0);
2116
2117 for (i = begrow; i <= endrow; i++)
2118 {
2119 int column = (i == begrow ? begcol : w->left);
2120 int endcolumn = (i == endrow ? endcol : w->left + width);
2121 endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i] - w->left),
2122
2123 dumpglyphs (f,
2124 CHAR_TO_PIXEL_COL (f, column),
2125 CHAR_TO_PIXEL_ROW (f, i),
2126 FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
2127 endcolumn - column,
2128 /* Highlight with mouse face if hl > 0. */
2129 hl > 0 ? 3 : 0);
2130 }
2131
2132 x_display_cursor (f, 1);
2133}
2134
2135/* Clear out the mouse-highlighted active region.
2136 Redraw it unhighlighted first. */
2137
2138static void
2139clear_mouse_face ()
2140{
2141 if (! NILP (mouse_face_window))
2142 show_mouse_face (0);
2143
2144 mouse_face_beg = -1;
2145 mouse_face_end = -1;
2146 mouse_face_window = Qnil;
2147}
2148
1844static struct scroll_bar *x_window_to_scroll_bar (); 2149static struct scroll_bar *x_window_to_scroll_bar ();
1845static void x_scroll_bar_report_motion (); 2150static void x_scroll_bar_report_motion ();
1846 2151
@@ -3387,6 +3692,11 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
3387 case LeaveNotify: 3692 case LeaveNotify:
3388 f = x_any_window_to_frame (event.xcrossing.window); 3693 f = x_any_window_to_frame (event.xcrossing.window);
3389 3694
3695 if (f == mouse_face_mouse_frame)
3696 /* If we move outside the frame,
3697 then we're certainly no longer on any text in the frame. */
3698 clear_mouse_face ();
3699
3390 if (event.xcrossing.focus) 3700 if (event.xcrossing.focus)
3391 { 3701 {
3392 if (! x_focus_event_frame) 3702 if (! x_focus_event_frame)
@@ -3470,6 +3780,10 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
3470 3780
3471 if (bar) 3781 if (bar)
3472 x_scroll_bar_note_movement (bar, &event); 3782 x_scroll_bar_note_movement (bar, &event);
3783
3784 /* If we move outside the frame,
3785 then we're certainly no longer on any text in the frame. */
3786 clear_mouse_face ();
3473 } 3787 }
3474 } 3788 }
3475#ifdef USE_X_TOOLKIT 3789#ifdef USE_X_TOOLKIT
@@ -5393,6 +5707,7 @@ Check the DISPLAY environment variable or use \"-d\"\n",
5393 update_end_hook = XTupdate_end; 5707 update_end_hook = XTupdate_end;
5394 set_terminal_window_hook = XTset_terminal_window; 5708 set_terminal_window_hook = XTset_terminal_window;
5395 read_socket_hook = XTread_socket; 5709 read_socket_hook = XTread_socket;
5710 frame_up_to_date_hook = XTframe_up_to_date;
5396 cursor_to_hook = XTcursor_to; 5711 cursor_to_hook = XTcursor_to;
5397 reassert_line_highlight_hook = XTreassert_line_highlight; 5712 reassert_line_highlight_hook = XTreassert_line_highlight;
5398 mouse_position_hook = XTmouse_position; 5713 mouse_position_hook = XTmouse_position;
@@ -5432,6 +5747,8 @@ syms_of_xterm ()
5432{ 5747{
5433 staticpro (&last_mouse_scroll_bar); 5748 staticpro (&last_mouse_scroll_bar);
5434 last_mouse_scroll_bar = Qnil; 5749 last_mouse_scroll_bar = Qnil;
5750 staticpro (&mouse_face_window);
5751 mouse_face_window = Qnil;
5435} 5752}
5436#endif /* ! defined (HAVE_X11) */ 5753#endif /* ! defined (HAVE_X11) */
5437#endif /* ! defined (HAVE_X_WINDOWS) */ 5754#endif /* ! defined (HAVE_X_WINDOWS) */