comparison src/xterm.c @ 6616:951c8941b931

[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.
author Richard M. Stallman <rms@gnu.org>
date Thu, 31 Mar 1994 23:17:23 +0000
parents a071babfa9ea
children 59c44532d2a0
comparison
equal deleted inserted replaced
6615:96ddf85642d1 6616:951c8941b931
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
4 This file is part of GNU Emacs. 4 This file is part of GNU Emacs.
5 5
6 GNU Emacs is free software; you can redistribute it and/or modify 6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by 7 it under the terms of the GNU General Public License as published by
69 #endif /* ! defined (BSD) */ 69 #endif /* ! defined (BSD) */
70 70
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>
78 #include <sys/stat.h> 80 #include <sys/stat.h>
79 #include <sys/param.h> 81 #include <sys/param.h>
273 along with the position query. So, we just keep track of the time 275 along with the position query. So, we just keep track of the time
274 of the last movement we received, and return that in hopes that 276 of the last movement we received, and return that in hopes that
275 it's somewhat accurate. */ 277 it's somewhat accurate. */
276 static Time last_mouse_movement_time; 278 static 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. */
284 static int mouse_face_beg, mouse_face_end;
285 static Lisp_Object mouse_face_window;
286 static int mouse_face_face_id;
287
288 /* FRAME and X, Y position of mouse when last checked for highlighting. */
289 static FRAME_PTR mouse_face_mouse_frame;
290 static int mouse_face_mouse_x, mouse_face_mouse_y;
291
292 /* Nonzero means defer mouse-motion highlighting. */
293 static 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
281 extern Lisp_Object Vmouse_depressed; 298 extern Lisp_Object Vmouse_depressed;
282 299
290 /* ID of the window requesting selection data. */ 307 /* ID of the window requesting selection data. */
291 extern Window requestor_window; 308 extern Window requestor_window;
292 309
293 /* Nonzero enables some debugging for the X interface code. */ 310 /* Nonzero enables some debugging for the X interface code. */
294 extern int _Xdebug; 311 extern int _Xdebug;
312
313 extern Qface, Qmouse_face;
295 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. */
299 318
331 extern FONT_TYPE *XOpenFont (); 350 extern FONT_TYPE *XOpenFont ();
332 351
333 static void flashback (); 352 static void flashback ();
334 static void redraw_previous_char (); 353 static void redraw_previous_char ();
335 static unsigned int x_x_to_emacs_modifiers (); 354 static unsigned int x_x_to_emacs_modifiers ();
355
356 static void note_mouse_highlight ();
357 static void clear_mouse_face ();
358 static void show_mouse_face ();
336 359
337 #ifndef HAVE_X11 360 #ifndef HAVE_X11
338 static void dumpqueue (); 361 static void dumpqueue ();
339 #endif /* HAVE_X11 */ 362 #endif /* HAVE_X11 */
340 363
365 388
366 flexlines = f->height; 389 flexlines = f->height;
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 */
373 UNBLOCK_INPUT; 403 UNBLOCK_INPUT;
374 } 404 }
389 x_do_pending_expose (); 419 x_do_pending_expose ();
390 #endif /* HAVE_X11 */ 420 #endif /* HAVE_X11 */
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;
439 }
440
441 /* This is called when all windows on frame F are now up to date. */
442
443 static
444 XTframe_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);
396 } 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
400 and not change whether it is highlighted. */ 453 and not change whether it is highlighted. */
459 } 512 }
460 } 513 }
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
468 Since the display generation code is responsible for calling 522 Since the display generation code is responsible for calling
469 compute_char_face and compute_glyph_face on everything it puts in 523 compute_char_face and compute_glyph_face on everything it puts in
523 struct face *face = FRAME_DEFAULT_FACE (f); 577 struct face *face = FRAME_DEFAULT_FACE (f);
524 FONT_TYPE *font = FACE_FONT (face); 578 FONT_TYPE *font = FACE_FONT (face);
525 GC gc = FACE_GC (face); 579 GC gc = FACE_GC (face);
526 int defaulted = 1; 580 int defaulted = 1;
527 int gc_temporary = 0; 581 int gc_temporary = 0;
582
583 /* HL = 3 means use a mouse face previously chosen. */
584 if (hl == 3)
585 cf = mouse_face_face_id;
528 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 {
532 /* It's possible for the display table to specify 590 /* It's possible for the display table to specify
1200 if (top < intborder || left < intborder 1258 if (top < intborder || left < intborder
1201 || bottom > intborder + f->height * FONT_HEIGHT (f->display.x->font) 1259 || bottom > intborder + f->height * FONT_HEIGHT (f->display.x->font)
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. */
1209 top = PIXEL_TO_CHAR_ROW (f, top); 1267 top = PIXEL_TO_CHAR_ROW (f, top);
1210 left = PIXEL_TO_CHAR_COL (f, left); 1268 left = PIXEL_TO_CHAR_COL (f, left);
1808 1866
1809 We have received a mouse movement event, which is given in *event. 1867 We have received a mouse movement event, which is given in *event.
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
1813 static void 1872 static void
1814 note_mouse_movement (frame, event) 1873 note_mouse_movement (frame, event)
1815 FRAME_PTR frame; 1874 FRAME_PTR frame;
1816 XMotionEvent *event; 1875 XMotionEvent *event;
1817 1876
1824 || event->y < last_mouse_glyph.y 1883 || event->y < last_mouse_glyph.y
1825 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height) 1884 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
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 {
1832 /* It's on the same glyph. Call XQueryPointer so we'll get an 1903 /* It's on the same glyph. Call XQueryPointer so we'll get an
1833 event the next time the mouse moves and we can see if it's 1904 event the next time the mouse moves and we can see if it's
1839 &dummy, &dummy, &dummy, &dummy, 1910 &dummy, &dummy, &dummy, &dummy,
1840 (unsigned int *) &dummy); 1911 (unsigned int *) &dummy);
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
1919 static void
1920 note_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
2058 static int
2059 fast_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
2100 static void
2101 show_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
2138 static void
2139 clear_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
1844 static struct scroll_bar *x_window_to_scroll_bar (); 2149 static struct scroll_bar *x_window_to_scroll_bar ();
1845 static void x_scroll_bar_report_motion (); 2150 static void x_scroll_bar_report_motion ();
1846 2151
1847 /* Return the current position of the mouse. 2152 /* Return the current position of the mouse.
1848 2153
3385 3690
3386 3691
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)
3393 x_new_focus_frame (0); 3703 x_new_focus_frame (0);
3394 else 3704 else
3468 struct scroll_bar *bar 3778 struct scroll_bar *bar
3469 = x_window_to_scroll_bar (event.xmotion.window); 3779 = x_window_to_scroll_bar (event.xmotion.window);
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
3476 goto OTHER; 3790 goto OTHER;
3477 #endif /* USE_X_TOOLKIT */ 3791 #endif /* USE_X_TOOLKIT */
5391 set_terminal_modes_hook = XTset_terminal_modes; 5705 set_terminal_modes_hook = XTset_terminal_modes;
5392 update_begin_hook = XTupdate_begin; 5706 update_begin_hook = XTupdate_begin;
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;
5399 frame_rehighlight_hook = XTframe_rehighlight; 5714 frame_rehighlight_hook = XTframe_rehighlight;
5400 frame_raise_lower_hook = XTframe_raise_lower; 5715 frame_raise_lower_hook = XTframe_raise_lower;
5430 void 5745 void
5431 syms_of_xterm () 5746 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) */