aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii1999-12-28 15:59:34 +0000
committerEli Zaretskii1999-12-28 15:59:34 +0000
commit41ad069bdc70ca9afbdddc7076038f9d5566af97 (patch)
tree225f3c91ec83cd41d1f53e357cfc0693fbb58283 /src
parentadb9900f35b2f0b64a039af7fba2d295fc1ad6b5 (diff)
downloademacs-41ad069bdc70ca9afbdddc7076038f9d5566af97.tar.gz
emacs-41ad069bdc70ca9afbdddc7076038f9d5566af97.zip
Changes for supporting mouse/modeline highlight and help echo features:
(dos_set_window_size) [__DJGPP__ > 1]: If the frame dimensions changed, invalidate the mouse highlight info. (disable_mouse_highlight, help_echo, previous_help_echo): New variables. (IT_set_mouse_pointer, show_mouse_face, clear_mouse_face) (fast_find_position, IT_note_mode_line_highlight) (IT_note_mouse_highlight): New functions. (IT_update_begin): If the redisplay affects the window where the mouse highlight is, clear the highlight. If the frame where the highlight was displayed was killed, invalidate the highlight info. (IT_update_end): Reset the highlight flag. Reset the mouse highlight-defer flag. (IT_frame_up_to_date): New function, if mouse highlight was deferred due to GC, do it now. (internal_terminal_init): Initialize mouse-highlight related members of the_only_x_display. Assign IT_frame_up_to_date to frame_up_to_date_hook. (dos_rawgetc): If the mouse moved, update mouse highlight. If help_echo changed value, generate a HELP_EVENT event. (syms_of_msdos): Staticpro help_echo and previous_help_echo.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog22
-rw-r--r--src/msdos.c670
2 files changed, 688 insertions, 4 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index b9331c53ff4..3de622a7d14 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,27 @@
11999-12-28 Eli Zaretskii <eliz@is.elta.co.il> 11999-12-28 Eli Zaretskii <eliz@is.elta.co.il>
2 2
3 * msdos.c (dos_set_window_size) [__DJGPP__ > 1]: If the frame
4 dimensions changed, invalidate the mouse highlight info.
5 (disable_mouse_highlight, help_echo, previous_help_echo): New
6 variables.
7 (IT_set_mouse_pointer, show_mouse_face, clear_mouse_face)
8 (fast_find_position, IT_note_mode_line_highlight)
9 (IT_note_mouse_highlight): New functions.
10 (IT_update_begin): If the redisplay affects the window where the
11 mouse highlight is, clear the highlight. If the frame where the
12 highlight was displayed was killed, invalidate the highlight
13 info.
14 (IT_update_end): Reset the highlight flag. Reset the mouse
15 highlight-defer flag.
16 (IT_frame_up_to_date): New function, if mouse highlight was
17 deferred due to GC, do it now.
18 (internal_terminal_init): Initialize mouse-highlight related
19 members of the_only_x_display. Assign IT_frame_up_to_date to
20 frame_up_to_date_hook.
21 (dos_rawgetc): If the mouse moved, update mouse highlight. If
22 help_echo changed value, generate a HELP_EVENT event.
23 (syms_of_msdos): Staticpro help_echo and previous_help_echo.
24
3 * msdos.h (struct display_info): New. 25 * msdos.h (struct display_info): New.
4 (struct x_output): Add the display_info member. 26 (struct x_output): Add the display_info member.
5 (FRAME_X_DISPLAY_INFO): New macro. 27 (FRAME_X_DISPLAY_INFO): New macro.
diff --git a/src/msdos.c b/src/msdos.c
index 21d72623127..b1cbb6b5580 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -60,6 +60,7 @@ Boston, MA 02111-1307, USA. */
60#include "window.h" 60#include "window.h"
61#include "buffer.h" 61#include "buffer.h"
62#include "commands.h" 62#include "commands.h"
63#include "blockinput.h"
63#include <go32.h> 64#include <go32.h>
64#include <pc.h> 65#include <pc.h>
65#include <ctype.h> 66#include <ctype.h>
@@ -611,6 +612,23 @@ dos_set_window_size (rows, cols)
611 *rows = ScreenRows (); 612 *rows = ScreenRows ();
612 *cols = ScreenCols (); 613 *cols = ScreenCols ();
613 614
615#if __DJGPP__ > 1
616 /* If the dimensions changed, the mouse highlight info is invalid. */
617 if (current_rows != *rows || current_cols != *cols)
618 {
619 struct frame *f = SELECTED_FRAME();
620 struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
621 Lisp_Object window = dpyinfo->mouse_face_window;
622
623 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
624 {
625 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
626 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
627 dpyinfo->mouse_face_window = Qnil;
628 }
629 }
630#endif
631
614 /* Enable bright background colors. */ 632 /* Enable bright background colors. */
615 bright_bg (); 633 bright_bg ();
616 634
@@ -930,6 +948,548 @@ IT_write_glyphs (struct glyph *str, int str_len)
930 } 948 }
931} 949}
932 950
951/************************************************************************
952 Mouse Highlight (and friends..)
953 ************************************************************************/
954
955/* This is used for debugging, to turn off note_mouse_highlight. */
956int disable_mouse_highlight;
957
958/* If a string, dos_rawgetc generates an event to display that string.
959 (The display is done in keyboard.c:read_char.) */
960static Lisp_Object help_echo;
961static Lisp_Object previous_help_echo; /* a helper temporary variable */
962
963static int mouse_preempted = 0; /* non-zero when XMenu gobbles mouse events */
964
965/* Set the mouse pointer shape according to whether it is in the
966 area where the mouse highlight is in effect. */
967static void
968IT_set_mouse_pointer (int mode)
969{
970 /* A no-op for now. DOS text-mode mouse pointer doesn't offer too
971 many possibilities to change its shape, and the available
972 functionality pretty much sucks (e.g., almost every reasonable
973 shape will conceal the character it is on). Since the color of
974 the pointer changes in the highlighted area, it is not clear to
975 me whether anything else is required, anyway. */
976}
977
978/* Display the active region described by mouse_face_*
979 in its mouse-face if HL > 0, in its normal face if HL = 0. */
980static void
981show_mouse_face (struct display_info *dpyinfo, int hl)
982{
983 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
984 struct frame *f = XFRAME (WINDOW_FRAME (w));
985 int i;
986 struct face *fp;
987
988
989 /* If window is in the process of being destroyed, don't bother
990 doing anything. */
991 if (w->current_matrix == NULL)
992 goto set_cursor_shape;
993
994 /* Recognize when we are called to operate on rows that don't exist
995 anymore. This can happen when a window is split. */
996 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
997 goto set_cursor_shape;
998
999 /* There's no sense to do anything if the mouse face isn't realized. */
1000 if (hl > 0)
1001 {
1002 fp = FACE_FROM_ID (SELECTED_FRAME(), dpyinfo->mouse_face_face_id);
1003 if (!fp)
1004 goto set_cursor_shape;
1005 }
1006
1007 /* Note that mouse_face_beg_row etc. are window relative. */
1008 for (i = dpyinfo->mouse_face_beg_row;
1009 i <= dpyinfo->mouse_face_end_row;
1010 i++)
1011 {
1012 int start_hpos, end_hpos;
1013 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
1014
1015 /* Don't do anything if row doesn't have valid contents. */
1016 if (!row->enabled_p)
1017 continue;
1018
1019 /* For all but the first row, the highlight starts at column 0. */
1020 if (i == dpyinfo->mouse_face_beg_row)
1021 start_hpos = dpyinfo->mouse_face_beg_col;
1022 else
1023 start_hpos = 0;
1024
1025 if (i == dpyinfo->mouse_face_end_row)
1026 end_hpos = dpyinfo->mouse_face_end_col;
1027 else
1028 end_hpos = row->used[TEXT_AREA];
1029
1030 if (end_hpos <= start_hpos)
1031 continue;
1032 if (hl > 0)
1033 {
1034 int vpos = row->y + WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
1035 int kstart = start_hpos + WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
1036 int nglyphs = end_hpos - start_hpos;
1037 int offset = ScreenPrimary + 2*(vpos*screen_size_X + kstart) + 1;
1038 int start_offset = offset;
1039
1040 if (termscript)
1041 fprintf (termscript, "\n<MH+ %d-%d:%d>",
1042 kstart, kstart + nglyphs - 1, vpos);
1043
1044 mouse_off ();
1045 IT_set_face (dpyinfo->mouse_face_face_id);
1046 /* Since we are going to change only the _colors_ of the
1047 displayed text, there's no need to go through all the
1048 pain of generating and encoding the text from the glyphs.
1049 Instead, we simply poke the attribute byte of each
1050 affected position in video memory with the colors
1051 computed by IT_set_face! */
1052 _farsetsel (_dos_ds);
1053 while (nglyphs--)
1054 {
1055 _farnspokeb (offset, ScreenAttrib);
1056 offset += 2;
1057 }
1058 if (screen_virtual_segment)
1059 dosv_refresh_virtual_screen (start_offset, end_hpos - start_hpos);
1060 mouse_on ();
1061 }
1062 else
1063 {
1064 /* We are removing a previously-drawn mouse highlight. The
1065 safest way to do so is to redraw the glyphs anew, since
1066 all kinds of faces and display tables could have changed
1067 behind our back. */
1068 int nglyphs = end_hpos - start_hpos;
1069 int save_x = new_pos_X, save_y = new_pos_Y;
1070
1071 if (end_hpos >= row->used[TEXT_AREA])
1072 nglyphs = row->used[TEXT_AREA] - start_hpos;
1073
1074 /* IT_write_glyphs writes at cursor position, so we need to
1075 temporarily move cursor coordinates to the beginning of
1076 the highlight region. */
1077 new_pos_X = start_hpos + WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
1078 new_pos_Y = row->y + WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
1079
1080 if (termscript)
1081 fprintf (termscript, "<MH- %d-%d:%d>",
1082 new_pos_X, new_pos_X + nglyphs - 1, new_pos_Y);
1083 IT_write_glyphs (row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
1084 if (termscript)
1085 fputs ("\n", termscript);
1086 new_pos_X = save_x;
1087 new_pos_Y = save_y;
1088 }
1089 }
1090
1091 set_cursor_shape:
1092
1093 /* Change the mouse pointer shape. */
1094 IT_set_mouse_pointer (hl);
1095}
1096
1097/* Clear out the mouse-highlighted active region.
1098 Redraw it un-highlighted first. */
1099static void
1100clear_mouse_face (struct display_info *dpyinfo)
1101{
1102 if (! NILP (dpyinfo->mouse_face_window))
1103 show_mouse_face (dpyinfo, 0);
1104
1105 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1106 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1107 dpyinfo->mouse_face_window = Qnil;
1108}
1109
1110/* Find the glyph matrix position of buffer position POS in window W.
1111 *HPOS and *VPOS are set to the positions found. W's current glyphs
1112 must be up to date. If POS is above window start return (0, 0).
1113 If POS is after end of W, return end of last line in W. */
1114static int
1115fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
1116{
1117 int i;
1118 int lastcol;
1119 int maybe_next_line_p = 0;
1120 int line_start_position;
1121 int yb = window_text_bottom_y (w);
1122 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
1123 struct glyph_row *best_row = row;
1124
1125 while (row->y < yb)
1126 {
1127 if (row->used[TEXT_AREA])
1128 line_start_position = row->glyphs[TEXT_AREA]->charpos;
1129 else
1130 line_start_position = 0;
1131
1132 if (line_start_position > pos)
1133 break;
1134 /* If the position sought is the end of the buffer,
1135 don't include the blank lines at the bottom of the window. */
1136 else if (line_start_position == pos
1137 && pos == BUF_ZV (XBUFFER (w->buffer)))
1138 {
1139 maybe_next_line_p = 1;
1140 break;
1141 }
1142 else if (line_start_position > 0)
1143 best_row = row;
1144
1145 ++row;
1146 }
1147
1148 /* Find the right column within BEST_ROW. */
1149 lastcol = 0;
1150 row = best_row;
1151 for (i = 0; i < row->used[TEXT_AREA]; i++)
1152 {
1153 struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
1154 int charpos;
1155
1156 charpos = glyph->charpos;
1157 if (charpos == pos)
1158 {
1159 *hpos = i;
1160 *vpos = row->y;
1161 return 1;
1162 }
1163 else if (charpos > pos)
1164 break;
1165 else if (charpos > 0)
1166 lastcol = i;
1167 }
1168
1169 /* If we're looking for the end of the buffer,
1170 and we didn't find it in the line we scanned,
1171 use the start of the following line. */
1172 if (maybe_next_line_p)
1173 {
1174 ++row;
1175 lastcol = 0;
1176 }
1177
1178 *vpos = row->y;
1179 *hpos = lastcol + 1;
1180 return 0;
1181}
1182
1183/* Take proper action when mouse has moved to the mode or top line of
1184 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
1185 mode line. X is relative to the start of the text display area of
1186 W, so the width of bitmap areas and scroll bars must be subtracted
1187 to get a position relative to the start of the mode line. */
1188static void
1189IT_note_mode_line_highlight (struct window *w, int x, int mode_line_p)
1190{
1191 struct frame *f = XFRAME (w->frame);
1192 struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1193 struct glyph_row *row;
1194
1195 if (mode_line_p)
1196 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
1197 else
1198 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1199
1200 if (row->enabled_p)
1201 {
1202 extern Lisp_Object Qhelp_echo;
1203 struct glyph *glyph, *end;
1204 Lisp_Object help, map;
1205
1206 /* Find the glyph under X. */
1207 glyph = row->glyphs[TEXT_AREA]
1208 + x - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
1209 end = glyph + row->used[TEXT_AREA];
1210 if (glyph < end
1211 && STRINGP (glyph->object)
1212 && XSTRING (glyph->object)->intervals
1213 && glyph->charpos >= 0
1214 && glyph->charpos < XSTRING (glyph->object)->size)
1215 {
1216 /* If we're on a string with `help-echo' text property,
1217 arrange for the help to be displayed. This is done by
1218 setting the global variable help_echo to the help string. */
1219 help = Fget_text_property (make_number (glyph->charpos),
1220 Qhelp_echo, glyph->object);
1221 if (STRINGP (help))
1222 help_echo = help;
1223 }
1224 }
1225}
1226
1227/* Take proper action when the mouse has moved to position X, Y on
1228 frame F as regards highlighting characters that have mouse-face
1229 properties. Also de-highlighting chars where the mouse was before.
1230 X and Y can be negative or out of range. */
1231static void
1232IT_note_mouse_highlight (struct frame *f, int x, int y)
1233{
1234 struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1235 int portion;
1236 Lisp_Object window;
1237 struct window *w;
1238
1239 /* When a menu is active, don't highlight because this looks odd. */
1240 if (mouse_preempted)
1241 return;
1242
1243 if (disable_mouse_highlight)
1244 return;
1245
1246 dpyinfo->mouse_face_mouse_x = x;
1247 dpyinfo->mouse_face_mouse_y = y;
1248 dpyinfo->mouse_face_mouse_frame = f;
1249
1250 if (dpyinfo->mouse_face_defer)
1251 return;
1252
1253 if (gc_in_progress)
1254 {
1255 dpyinfo->mouse_face_deferred_gc = 1;
1256 return;
1257 }
1258
1259 /* Which window is that in? */
1260 window = window_from_coordinates (f, x, y, &portion, 0);
1261
1262 /* If we were displaying active text in another window, clear that. */
1263 if (! EQ (window, dpyinfo->mouse_face_window))
1264 clear_mouse_face (dpyinfo);
1265
1266 /* Not on a window -> return. */
1267 if (!WINDOWP (window))
1268 return;
1269
1270 /* Convert to window-relative coordinates. */
1271 w = XWINDOW (window);
1272 x -= WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
1273 y -= WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
1274
1275 if (portion == 1 || portion == 3)
1276 {
1277 /* Mouse is on the mode or top line. */
1278 IT_note_mode_line_highlight (w, x, portion == 1);
1279 return;
1280 }
1281 else
1282 IT_set_mouse_pointer (0);
1283
1284 /* Are we in a window whose display is up to date?
1285 And verify the buffer's text has not changed. */
1286 if (/* Within text portion of the window. */
1287 portion == 0
1288 && EQ (w->window_end_valid, w->buffer)
1289 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
1290 && (XFASTINT (w->last_overlay_modified)
1291 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
1292 {
1293 int pos, i, area;
1294 struct glyph_row *row;
1295 struct glyph *glyph;
1296
1297 /* Find the glyph under X/Y. */
1298 glyph = NULL;
1299 if (y < w->current_matrix->nrows)
1300 {
1301 row = MATRIX_ROW (w->current_matrix, y);
1302 if (row->enabled_p
1303 && row->displays_text_p
1304 && x < window_box_width (w, TEXT_AREA))
1305 {
1306 glyph = row->glyphs[TEXT_AREA];
1307 if (x >= row->used[TEXT_AREA])
1308 glyph = NULL;
1309 else
1310 {
1311 glyph += x;
1312 if (!BUFFERP (glyph->object))
1313 glyph = NULL;
1314 }
1315 }
1316 }
1317
1318 /* Clear mouse face if X/Y not over text. */
1319 if (glyph == NULL)
1320 {
1321 clear_mouse_face (dpyinfo);
1322 return;
1323 }
1324
1325 if (!BUFFERP (glyph->object))
1326 abort ();
1327 pos = glyph->charpos;
1328
1329 /* Check for mouse-face and help-echo. */
1330 {
1331 extern Lisp_Object Qmouse_face;
1332 Lisp_Object mouse_face, overlay, position;
1333 Lisp_Object *overlay_vec;
1334 int len, noverlays;
1335 struct buffer *obuf;
1336 int obegv, ozv;
1337
1338 /* If we get an out-of-range value, return now; avoid an error. */
1339 if (pos > BUF_Z (XBUFFER (w->buffer)))
1340 return;
1341
1342 /* Make the window's buffer temporarily current for
1343 overlays_at and compute_char_face. */
1344 obuf = current_buffer;
1345 current_buffer = XBUFFER (w->buffer);
1346 obegv = BEGV;
1347 ozv = ZV;
1348 BEGV = BEG;
1349 ZV = Z;
1350
1351 /* Is this char mouse-active or does it have help-echo? */
1352 XSETINT (position, pos);
1353
1354 /* Put all the overlays we want in a vector in overlay_vec.
1355 Store the length in len. If there are more than 10, make
1356 enough space for all, and try again. */
1357 len = 10;
1358 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
1359 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
1360 if (noverlays > len)
1361 {
1362 len = noverlays;
1363 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
1364 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
1365 }
1366
1367 noverlays = sort_overlays (overlay_vec, noverlays, w);
1368
1369 /* Check mouse-face highlighting. */
1370 if (! (EQ (window, dpyinfo->mouse_face_window)
1371 && y >= dpyinfo->mouse_face_beg_row
1372 && y <= dpyinfo->mouse_face_end_row
1373 && (y > dpyinfo->mouse_face_beg_row
1374 || x >= dpyinfo->mouse_face_beg_col)
1375 && (y < dpyinfo->mouse_face_end_row
1376 || x < dpyinfo->mouse_face_end_col
1377 || dpyinfo->mouse_face_past_end)))
1378 {
1379 /* Clear the display of the old active region, if any. */
1380 clear_mouse_face (dpyinfo);
1381
1382 /* Find highest priority overlay that has a mouse-face prop. */
1383 overlay = Qnil;
1384 for (i = 0; i < noverlays; i++)
1385 {
1386 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
1387 if (!NILP (mouse_face))
1388 {
1389 overlay = overlay_vec[i];
1390 break;
1391 }
1392 }
1393
1394 /* If no overlay applies, get a text property. */
1395 if (NILP (overlay))
1396 mouse_face = Fget_text_property (position, Qmouse_face,
1397 w->buffer);
1398
1399 /* Handle the overlay case. */
1400 if (! NILP (overlay))
1401 {
1402 /* Find the range of text around this char that
1403 should be active. */
1404 Lisp_Object before, after;
1405 int ignore;
1406
1407 before = Foverlay_start (overlay);
1408 after = Foverlay_end (overlay);
1409 /* Record this as the current active region. */
1410 fast_find_position (w, XFASTINT (before),
1411 &dpyinfo->mouse_face_beg_col,
1412 &dpyinfo->mouse_face_beg_row);
1413 dpyinfo->mouse_face_past_end
1414 = !fast_find_position (w, XFASTINT (after),
1415 &dpyinfo->mouse_face_end_col,
1416 &dpyinfo->mouse_face_end_row);
1417 dpyinfo->mouse_face_window = window;
1418 dpyinfo->mouse_face_face_id
1419 = face_at_buffer_position (w, pos, 0, 0,
1420 &ignore, pos + 1, 1);
1421
1422 /* Display it as active. */
1423 show_mouse_face (dpyinfo, 1);
1424 }
1425 /* Handle the text property case. */
1426 else if (! NILP (mouse_face))
1427 {
1428 /* Find the range of text around this char that
1429 should be active. */
1430 Lisp_Object before, after, beginning, end;
1431 int ignore;
1432
1433 beginning = Fmarker_position (w->start);
1434 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
1435 - XFASTINT (w->window_end_pos)));
1436 before
1437 = Fprevious_single_property_change (make_number (pos + 1),
1438 Qmouse_face,
1439 w->buffer, beginning);
1440 after
1441 = Fnext_single_property_change (position, Qmouse_face,
1442 w->buffer, end);
1443 /* Record this as the current active region. */
1444 fast_find_position (w, XFASTINT (before),
1445 &dpyinfo->mouse_face_beg_col,
1446 &dpyinfo->mouse_face_beg_row);
1447 dpyinfo->mouse_face_past_end
1448 = !fast_find_position (w, XFASTINT (after),
1449 &dpyinfo->mouse_face_end_col,
1450 &dpyinfo->mouse_face_end_row);
1451 dpyinfo->mouse_face_window = window;
1452 dpyinfo->mouse_face_face_id
1453 = face_at_buffer_position (w, pos, 0, 0,
1454 &ignore, pos + 1, 1);
1455
1456 /* Display it as active. */
1457 show_mouse_face (dpyinfo, 1);
1458 }
1459 }
1460
1461 /* Look for a `help-echo' property. */
1462 {
1463 Lisp_Object help;
1464 extern Lisp_Object Qhelp_echo;
1465
1466 /* Check overlays first. */
1467 help = Qnil;
1468 for (i = 0; i < noverlays && !STRINGP (help); ++i)
1469 help = Foverlay_get (overlay_vec[i], Qhelp_echo);
1470
1471 /* Try text properties. */
1472 if (!STRINGP (help)
1473 && ((STRINGP (glyph->object)
1474 && glyph->charpos >= 0
1475 && glyph->charpos < XSTRING (glyph->object)->size)
1476 || (BUFFERP (glyph->object)
1477 && glyph->charpos >= BEGV
1478 && glyph->charpos < ZV)))
1479 help = Fget_text_property (make_number (glyph->charpos),
1480 Qhelp_echo, glyph->object);
1481
1482 if (STRINGP (help))
1483 help_echo = help;
1484 }
1485
1486 BEGV = obegv;
1487 ZV = ozv;
1488 current_buffer = obuf;
1489 }
1490 }
1491}
1492
933static void 1493static void
934IT_clear_end_of_line (int first_unused) 1494IT_clear_end_of_line (int first_unused)
935{ 1495{
@@ -1117,14 +1677,81 @@ IT_change_line_highlight (int new_highlight, int y, int vpos, int first_unused_h
1117} 1677}
1118 1678
1119static void 1679static void
1120IT_update_begin (struct frame *foo) 1680IT_update_begin (struct frame *f)
1121{ 1681{
1682 struct display_info *display_info = FRAME_X_DISPLAY_INFO (f);
1683
1122 highlight = 0; 1684 highlight = 0;
1685
1686 BLOCK_INPUT;
1687
1688 if (f == display_info->mouse_face_mouse_frame)
1689 {
1690 /* Don't do highlighting for mouse motion during the update. */
1691 display_info->mouse_face_defer = 1;
1692
1693 /* If F needs to be redrawn, simply forget about any prior mouse
1694 highlighting. */
1695 if (FRAME_GARBAGED_P (f))
1696 display_info->mouse_face_window = Qnil;
1697
1698 /* Can we tell that this update does not affect the window
1699 where the mouse highlight is? If so, no need to turn off.
1700 Likewise, don't do anything if the frame is garbaged;
1701 in that case, the frame's current matrix that we would use
1702 is all wrong, and we will redisplay that line anyway. */
1703 if (!NILP (display_info->mouse_face_window))
1704 {
1705 struct window *w = XWINDOW (display_info->mouse_face_window);
1706 int i;
1707
1708 for (i = 0; i < w->desired_matrix->nrows; ++i)
1709 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1710 break;
1711
1712 if (i < w->desired_matrix->nrows)
1713 clear_mouse_face (display_info);
1714 }
1715 }
1716 else if (!FRAME_LIVE_P (display_info->mouse_face_mouse_frame))
1717 {
1718 /* If the frame with mouse highlight was deleted, invalidate the
1719 highlight info. */
1720 display_info->mouse_face_beg_row = display_info->mouse_face_beg_col = -1;
1721 display_info->mouse_face_end_row = display_info->mouse_face_end_col = -1;
1722 display_info->mouse_face_window = Qnil;
1723 display_info->mouse_face_deferred_gc = 0;
1724 display_info->mouse_face_mouse_frame = NULL;
1725 }
1726
1727 UNBLOCK_INPUT;
1123} 1728}
1124 1729
1125static void 1730static void
1126IT_update_end (struct frame *foo) 1731IT_update_end (struct frame *f)
1127{ 1732{
1733 highlight = 0;
1734 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
1735}
1736
1737static void
1738IT_frame_up_to_date (struct frame *f)
1739{
1740 struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
1741
1742 if (dpyinfo->mouse_face_deferred_gc
1743 || f == dpyinfo->mouse_face_mouse_frame)
1744 {
1745 BLOCK_INPUT;
1746 if (dpyinfo->mouse_face_mouse_frame)
1747 IT_note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1748 dpyinfo->mouse_face_mouse_x,
1749 dpyinfo->mouse_face_mouse_y);
1750 dpyinfo->mouse_face_deferred_gc = 0;
1751 UNBLOCK_INPUT;
1752 }
1753
1754 IT_cmgoto (f); /* position cursor when update is done */
1128} 1755}
1129 1756
1130/* Copy LEN glyphs displayed on a single line whose vertical position 1757/* Copy LEN glyphs displayed on a single line whose vertical position
@@ -1581,6 +2208,17 @@ internal_terminal_init ()
1581 } 2208 }
1582 the_only_x_display.line_height = 1; 2209 the_only_x_display.line_height = 1;
1583 the_only_x_display.font = (XFontStruct *)1; /* must *not* be zero */ 2210 the_only_x_display.font = (XFontStruct *)1; /* must *not* be zero */
2211 the_only_x_display.display_info.mouse_face_mouse_frame = NULL;
2212 the_only_x_display.display_info.mouse_face_deferred_gc = 0;
2213 the_only_x_display.display_info.mouse_face_beg_row =
2214 the_only_x_display.display_info.mouse_face_beg_col = -1;
2215 the_only_x_display.display_info.mouse_face_end_row =
2216 the_only_x_display.display_info.mouse_face_end_col = -1;
2217 the_only_x_display.display_info.mouse_face_face_id = DEFAULT_FACE_ID;
2218 the_only_x_display.display_info.mouse_face_window = Qnil;
2219 the_only_x_display.display_info.mouse_face_mouse_x =
2220 the_only_x_display.display_info.mouse_face_mouse_y = 0;
2221 the_only_x_display.display_info.mouse_face_defer = 0;
1584 2222
1585 init_frame_faces (sf); 2223 init_frame_faces (sf);
1586 2224
@@ -1596,7 +2234,7 @@ internal_terminal_init ()
1596 update_begin_hook = IT_update_begin; 2234 update_begin_hook = IT_update_begin;
1597 update_end_hook = IT_update_end; 2235 update_end_hook = IT_update_end;
1598 reassert_line_highlight_hook = IT_reassert_line_highlight; 2236 reassert_line_highlight_hook = IT_reassert_line_highlight;
1599 frame_up_to_date_hook = IT_cmgoto; /* position cursor when update is done */ 2237 frame_up_to_date_hook = IT_frame_up_to_date;
1600 2238
1601 /* These hooks are called by term.c without being checked. */ 2239 /* These hooks are called by term.c without being checked. */
1602 set_terminal_modes_hook = IT_set_terminal_modes; 2240 set_terminal_modes_hook = IT_set_terminal_modes;
@@ -2150,7 +2788,6 @@ and then the scan code.")
2150/* Get a char from keyboard. Function keys are put into the event queue. */ 2788/* Get a char from keyboard. Function keys are put into the event queue. */
2151 2789
2152extern void kbd_buffer_store_event (struct input_event *); 2790extern void kbd_buffer_store_event (struct input_event *);
2153static int mouse_preempted = 0; /* non-zero when XMenu gobbles mouse events */
2154 2791
2155static int 2792static int
2156dos_rawgetc () 2793dos_rawgetc ()
@@ -2381,10 +3018,30 @@ dos_rawgetc ()
2381 if (have_mouse > 0 && !mouse_preempted) 3018 if (have_mouse > 0 && !mouse_preempted)
2382 { 3019 {
2383 int but, press, x, y, ok; 3020 int but, press, x, y, ok;
3021 int mouse_prev_x = mouse_last_x, mouse_prev_y = mouse_last_y;
2384 3022
2385 /* Check for mouse movement *before* buttons. */ 3023 /* Check for mouse movement *before* buttons. */
2386 mouse_check_moved (); 3024 mouse_check_moved ();
2387 3025
3026 /* If the mouse moved from the spot of its last sighting, we
3027 might need to update mouse highlight. */
3028 if (mouse_last_x != mouse_prev_x || mouse_last_y != mouse_prev_y)
3029 {
3030 previous_help_echo = help_echo;
3031 help_echo = Qnil;
3032 IT_note_mouse_highlight (SELECTED_FRAME(),
3033 mouse_last_x, mouse_last_y);
3034 /* If the contents of the global variable help_echo has
3035 changed, generate a HELP_EVENT. */
3036 if (STRINGP (help_echo) || STRINGP (previous_help_echo))
3037 {
3038 event.kind = HELP_EVENT;
3039 event.frame_or_window = Fcons (selected_frame, help_echo);
3040 event.timestamp = event_timestamp ();
3041 kbd_buffer_store_event (&event);
3042 }
3043 }
3044
2388 for (but = 0; but < NUM_MOUSE_BUTTONS; but++) 3045 for (but = 0; but < NUM_MOUSE_BUTTONS; but++)
2389 for (press = 0; press < 2; press++) 3046 for (press = 0; press < 2; press++)
2390 { 3047 {
@@ -4173,6 +4830,11 @@ syms_of_msdos ()
4173 recent_doskeys = Fmake_vector (make_number (NUM_RECENT_DOSKEYS), Qnil); 4830 recent_doskeys = Fmake_vector (make_number (NUM_RECENT_DOSKEYS), Qnil);
4174 staticpro (&recent_doskeys); 4831 staticpro (&recent_doskeys);
4175#ifndef HAVE_X_WINDOWS 4832#ifndef HAVE_X_WINDOWS
4833 staticpro (&help_echo);
4834 help_echo = Qnil;
4835 staticpro (&previous_help_echo);
4836 previous_help_echo = Qnil;
4837
4176 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path, 4838 DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
4177 "List of directories to search for bitmap files for X."); 4839 "List of directories to search for bitmap files for X.");
4178 Vx_bitmap_file_path = decode_env_path ((char *) 0, "."); 4840 Vx_bitmap_file_path = decode_env_path ((char *) 0, ".");