aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKim F. Storm2003-12-28 00:12:27 +0000
committerKim F. Storm2003-12-28 00:12:27 +0000
commit493fdc3cc3fad407c3ad3476d88658f6be8eb244 (patch)
tree3a9776a0ede43e4ab6d59c831cd1470a5fc1bb58 /src
parent82cf95a792459f8dd7a1118f47c1a1dbec962bc9 (diff)
downloademacs-493fdc3cc3fad407c3ad3476d88658f6be8eb244.tar.gz
emacs-493fdc3cc3fad407c3ad3476d88658f6be8eb244.zip
(Qarrow, Qhand, Qtext, Qpointer): New variables for
pointer types. (Qrelative_width, Qalign_to): Remove unused variables. (Vvoid_text_area_pointer): Replace Vshow_text_cursor_in_void. (QCmap, QCpointer, Qrect, Qcircle, Qpoly): New variables for image maps. (x_y_to_hpos_vpos): Return glyph relative coordinates through new dx and dy args. Remove buffer_only_p arg (always 0). Simplify code accordingly. (get_glyph_string_clip_rect): Draw cursor using glyph's rather than row's ascent and height, to get sensible height on tall rows. (build_desired_tool_bar_string): Remove Qimage extern. (get_tool_bar_item): Fix call to x_y_to_hpos_vpos. (produce_image_glyph): Adjust it.ascent to minimum row ascent if image glyph is alone on the last line. (append_glyph, append_composite_glyph, produce_image_glyph) (append_stretch_glyph): Set glyph's ascent and descent. (on_hot_spot_p): New function to check if position is inside an rectangular, circular, or polygon-shaped image hot-spot, (find_hot_spot): New function to search for image hot-spot. (Flookup_image_map): New defun to search for image hot-spot. (define_frame_cursor1): New aux function to determine frame pointer. (note_mode_line_or_margin_highlight, note_mouse_highlight): Handle `pointer' text property and :pointer image property to control frame pointer shape. Detect image hot-spots for pointer and help_echo properties. Use define_frame_cursor1. (note_mouse_highlight): Use Vvoid_text_area_pointer. (syms_of_xdisp): Defsubr new defun. Intern and staticpro new variables. DEFVAR_LISP Vvoid_text_area_pointer instead of Vshow_text_cursor_in_void.
Diffstat (limited to 'src')
-rw-r--r--src/xdisp.c449
1 files changed, 397 insertions, 52 deletions
diff --git a/src/xdisp.c b/src/xdisp.c
index c2717552cc5..8a6f36ef17b 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -242,6 +242,9 @@ Lisp_Object Qbuffer_position, Qposition, Qobject;
242/* Cursor shapes */ 242/* Cursor shapes */
243Lisp_Object Qbar, Qhbar, Qbox, Qhollow; 243Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
244 244
245/* Pointer shapes */
246Lisp_Object Qarrow, Qhand, Qtext;
247
245Lisp_Object Qrisky_local_variable; 248Lisp_Object Qrisky_local_variable;
246 249
247/* Holds the list (error). */ 250/* Holds the list (error). */
@@ -290,7 +293,7 @@ int inhibit_eval_during_redisplay;
290 293
291/* Names of text properties relevant for redisplay. */ 294/* Names of text properties relevant for redisplay. */
292 295
293Lisp_Object Qdisplay, Qrelative_width, Qalign_to; 296Lisp_Object Qdisplay;
294extern Lisp_Object Qface, Qinvisible, Qwidth; 297extern Lisp_Object Qface, Qinvisible, Qwidth;
295 298
296/* Symbols used in text property values. */ 299/* Symbols used in text property values. */
@@ -298,7 +301,7 @@ extern Lisp_Object Qface, Qinvisible, Qwidth;
298Lisp_Object Vdisplay_pixels_per_inch; 301Lisp_Object Vdisplay_pixels_per_inch;
299Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height; 302Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
300Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise; 303Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
301Lisp_Object Qmargin; 304Lisp_Object Qmargin, Qpointer;
302extern Lisp_Object Qheight; 305extern Lisp_Object Qheight;
303extern Lisp_Object QCwidth, QCheight, QCascent; 306extern Lisp_Object QCwidth, QCheight, QCascent;
304extern Lisp_Object Qscroll_bar; 307extern Lisp_Object Qscroll_bar;
@@ -311,7 +314,7 @@ Lisp_Object Vshow_trailing_whitespace;
311 i.e. in blank areas after eol and eob. This used to be 314 i.e. in blank areas after eol and eob. This used to be
312 the default in 21.3. */ 315 the default in 21.3. */
313 316
314Lisp_Object Vshow_text_cursor_in_void; 317Lisp_Object Vvoid_text_area_pointer;
315 318
316/* Name of the face used to highlight trailing whitespace. */ 319/* Name of the face used to highlight trailing whitespace. */
317 320
@@ -322,6 +325,10 @@ Lisp_Object Qtrailing_whitespace;
322 325
323Lisp_Object Qimage; 326Lisp_Object Qimage;
324 327
328/* The image map types. */
329Lisp_Object QCmap, QCpointer;
330Lisp_Object Qrect, Qcircle, Qpoly;
331
325/* Non-zero means print newline to stdout before next mini-buffer 332/* Non-zero means print newline to stdout before next mini-buffer
326 message. */ 333 message. */
327 334
@@ -1582,11 +1589,10 @@ glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
1582 date. */ 1589 date. */
1583 1590
1584static struct glyph * 1591static struct glyph *
1585x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p) 1592x_y_to_hpos_vpos (w, x, y, hpos, vpos, dx, dy, area)
1586 struct window *w; 1593 struct window *w;
1587 int x, y; 1594 int x, y;
1588 int *hpos, *vpos, *area; 1595 int *hpos, *vpos, *dx, *dy, *area;
1589 int buffer_only_p;
1590{ 1596{
1591 struct glyph *glyph, *end; 1597 struct glyph *glyph, *end;
1592 struct glyph_row *row = NULL; 1598 struct glyph_row *row = NULL;
@@ -1637,23 +1643,22 @@ x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
1637 /* Find glyph containing X. */ 1643 /* Find glyph containing X. */
1638 glyph = row->glyphs[*area]; 1644 glyph = row->glyphs[*area];
1639 end = glyph + row->used[*area]; 1645 end = glyph + row->used[*area];
1640 while (glyph < end) 1646 x -= x0;
1647 while (glyph < end && x >= glyph->pixel_width)
1641 { 1648 {
1642 if (x < x0 + glyph->pixel_width) 1649 x -= glyph->pixel_width;
1643 {
1644 if (w->pseudo_window_p)
1645 break;
1646 else if (!buffer_only_p || BUFFERP (glyph->object))
1647 break;
1648 }
1649
1650 x0 += glyph->pixel_width;
1651 ++glyph; 1650 ++glyph;
1652 } 1651 }
1653 1652
1654 if (glyph == end) 1653 if (glyph == end)
1655 return NULL; 1654 return NULL;
1656 1655
1656 if (dx)
1657 {
1658 *dx = x;
1659 *dy = y - (row->y + row->ascent - glyph->ascent);
1660 }
1661
1657 *hpos = glyph - row->glyphs[*area]; 1662 *hpos = glyph - row->glyphs[*area];
1658 return glyph; 1663 return glyph;
1659} 1664}
@@ -1741,20 +1746,28 @@ get_glyph_string_clip_rect (s, nr)
1741 1746
1742 r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y); 1747 r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
1743 1748
1744#ifdef HAVE_NTGUI
1745 /* ++KFS: From W32 port, but it looks ok for all platforms to me. */
1746 /* If drawing the cursor, don't let glyph draw outside its 1749 /* If drawing the cursor, don't let glyph draw outside its
1747 advertised boundaries. Cleartype does this under some circumstances. */ 1750 advertised boundaries. Cleartype does this under some circumstances. */
1748 if (s->hl == DRAW_CURSOR) 1751 if (s->hl == DRAW_CURSOR)
1749 { 1752 {
1753 struct glyph *glyph = s->first_glyph;
1754 int height;
1755
1750 if (s->x > r.x) 1756 if (s->x > r.x)
1751 { 1757 {
1752 r.width -= s->x - r.x; 1758 r.width -= s->x - r.x;
1753 r.x = s->x; 1759 r.x = s->x;
1754 } 1760 }
1755 r.width = min (r.width, s->first_glyph->pixel_width); 1761 r.width = min (r.width, glyph->pixel_width);
1762
1763 /* Don't draw cursor glyph taller than our actual glyph. */
1764 height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
1765 if (height < r.height)
1766 {
1767 r.y = s->ybase + glyph->descent - height;
1768 r.height = height;
1769 }
1756 } 1770 }
1757#endif
1758 1771
1759#ifdef CONVERT_FROM_XRECT 1772#ifdef CONVERT_FROM_XRECT
1760 CONVERT_FROM_XRECT (r, *nr); 1773 CONVERT_FROM_XRECT (r, *nr);
@@ -8279,7 +8292,7 @@ build_desired_tool_bar_string (f)
8279 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P)); 8292 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
8280 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P)); 8293 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
8281 int hmargin, vmargin, relief, idx, end; 8294 int hmargin, vmargin, relief, idx, end;
8282 extern Lisp_Object QCrelief, QCmargin, QCconversion, Qimage; 8295 extern Lisp_Object QCrelief, QCmargin, QCconversion;
8283 8296
8284 /* If image is a vector, choose the image according to the 8297 /* If image is a vector, choose the image according to the
8285 button state. */ 8298 button state. */
@@ -8696,7 +8709,7 @@ get_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
8696 int area; 8709 int area;
8697 8710
8698 /* Find the glyph under X/Y. */ 8711 /* Find the glyph under X/Y. */
8699 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0); 8712 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
8700 if (*glyph == NULL) 8713 if (*glyph == NULL)
8701 return -1; 8714 return -1;
8702 8715
@@ -17685,6 +17698,8 @@ append_glyph (it)
17685 glyph->charpos = CHARPOS (it->position); 17698 glyph->charpos = CHARPOS (it->position);
17686 glyph->object = it->object; 17699 glyph->object = it->object;
17687 glyph->pixel_width = it->pixel_width; 17700 glyph->pixel_width = it->pixel_width;
17701 glyph->ascent = it->ascent;
17702 glyph->descent = it->descent;
17688 glyph->voffset = it->voffset; 17703 glyph->voffset = it->voffset;
17689 glyph->type = CHAR_GLYPH; 17704 glyph->type = CHAR_GLYPH;
17690 glyph->multibyte_p = it->multibyte_p; 17705 glyph->multibyte_p = it->multibyte_p;
@@ -17719,6 +17734,8 @@ append_composite_glyph (it)
17719 glyph->charpos = CHARPOS (it->position); 17734 glyph->charpos = CHARPOS (it->position);
17720 glyph->object = it->object; 17735 glyph->object = it->object;
17721 glyph->pixel_width = it->pixel_width; 17736 glyph->pixel_width = it->pixel_width;
17737 glyph->ascent = it->ascent;
17738 glyph->descent = it->descent;
17722 glyph->voffset = it->voffset; 17739 glyph->voffset = it->voffset;
17723 glyph->type = COMPOSITE_GLYPH; 17740 glyph->type = COMPOSITE_GLYPH;
17724 glyph->multibyte_p = it->multibyte_p; 17741 glyph->multibyte_p = it->multibyte_p;
@@ -17767,6 +17784,7 @@ produce_image_glyph (it)
17767{ 17784{
17768 struct image *img; 17785 struct image *img;
17769 struct face *face; 17786 struct face *face;
17787 int face_ascent, glyph_ascent;
17770 17788
17771 xassert (it->what == IT_IMAGE); 17789 xassert (it->what == IT_IMAGE);
17772 17790
@@ -17778,10 +17796,15 @@ produce_image_glyph (it)
17778 PREPARE_FACE_FOR_DISPLAY (it->f, face); 17796 PREPARE_FACE_FOR_DISPLAY (it->f, face);
17779 prepare_image_for_display (it->f, img); 17797 prepare_image_for_display (it->f, img);
17780 17798
17781 it->ascent = it->phys_ascent = image_ascent (img, face); 17799 it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face);
17782 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent; 17800 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
17783 it->pixel_width = img->width + 2 * img->hmargin; 17801 it->pixel_width = img->width + 2 * img->hmargin;
17784 17802
17803 /* If this glyph is alone on the last line, adjust it.ascent to minimum row ascent. */
17804 face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f);
17805 if (face_ascent > it->ascent)
17806 it->ascent = it->phys_ascent = face_ascent;
17807
17785 it->nglyphs = 1; 17808 it->nglyphs = 1;
17786 17809
17787 if (face->box != FACE_NO_BOX) 17810 if (face->box != FACE_NO_BOX)
@@ -17811,6 +17834,8 @@ produce_image_glyph (it)
17811 glyph->charpos = CHARPOS (it->position); 17834 glyph->charpos = CHARPOS (it->position);
17812 glyph->object = it->object; 17835 glyph->object = it->object;
17813 glyph->pixel_width = it->pixel_width; 17836 glyph->pixel_width = it->pixel_width;
17837 glyph->ascent = glyph_ascent;
17838 glyph->descent = it->descent;
17814 glyph->voffset = it->voffset; 17839 glyph->voffset = it->voffset;
17815 glyph->type = IMAGE_GLYPH; 17840 glyph->type = IMAGE_GLYPH;
17816 glyph->multibyte_p = it->multibyte_p; 17841 glyph->multibyte_p = it->multibyte_p;
@@ -17850,6 +17875,8 @@ append_stretch_glyph (it, object, width, height, ascent)
17850 glyph->charpos = CHARPOS (it->position); 17875 glyph->charpos = CHARPOS (it->position);
17851 glyph->object = object; 17876 glyph->object = object;
17852 glyph->pixel_width = width; 17877 glyph->pixel_width = width;
17878 glyph->ascent = ascent;
17879 glyph->descent = height - ascent;
17853 glyph->voffset = it->voffset; 17880 glyph->voffset = it->voffset;
17854 glyph->type = STRETCH_GLYPH; 17881 glyph->type = STRETCH_GLYPH;
17855 glyph->multibyte_p = it->multibyte_p; 17882 glyph->multibyte_p = it->multibyte_p;
@@ -19945,6 +19972,189 @@ fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
19945} 19972}
19946 19973
19947 19974
19975/* See if position X, Y is within a hot-spot of an image. */
19976
19977static int
19978on_hot_spot_p (hot_spot, x, y)
19979 Lisp_Object hot_spot;
19980 int x, y;
19981{
19982 if (!CONSP (hot_spot))
19983 return 0;
19984
19985 if (EQ (XCAR (hot_spot), Qrect))
19986 {
19987 /* CDR is (Top-Left . Bottom-Right) = ((x0 . y0) . (x1 . y1)) */
19988 Lisp_Object rect = XCDR (hot_spot);
19989 Lisp_Object tem;
19990 if (!CONSP (rect))
19991 return 0;
19992 if (!CONSP (XCAR (rect)))
19993 return 0;
19994 if (!CONSP (XCDR (rect)))
19995 return 0;
19996 if (!(tem = XCAR (XCAR (rect)), INTEGERP (tem) && x >= XINT (tem)))
19997 return 0;
19998 if (!(tem = XCDR (XCAR (rect)), INTEGERP (tem) && y >= XINT (tem)))
19999 return 0;
20000 if (!(tem = XCAR (XCDR (rect)), INTEGERP (tem) && x <= XINT (tem)))
20001 return 0;
20002 if (!(tem = XCDR (XCDR (rect)), INTEGERP (tem) && y <= XINT (tem)))
20003 return 0;
20004 return 1;
20005 }
20006 else if (EQ (XCAR (hot_spot), Qcircle))
20007 {
20008 /* CDR is (Center . Radius) = ((x0 . y0) . r) */
20009 Lisp_Object circ = XCDR (hot_spot);
20010 Lisp_Object lr, lx0, ly0;
20011 if (CONSP (circ)
20012 && CONSP (XCAR (circ))
20013 && (lr = XCDR (circ), INTEGERP (lr) || FLOATP (lr))
20014 && (lx0 = XCAR (XCAR (circ)), INTEGERP (lx0))
20015 && (ly0 = XCDR (XCAR (circ)), INTEGERP (ly0)))
20016 {
20017 double r = XFLOATINT (lr);
20018 double dx = XINT (lx0) - x;
20019 double dy = XINT (ly0) - y;
20020 return (dx * dx + dy * dy <= r * r);
20021 }
20022 }
20023 else if (EQ (XCAR (hot_spot), Qpoly))
20024 {
20025 /* CDR is [x0 y0 x1 y1 x2 y2 ...x(n-1) y(n-1)] */
20026 if (VECTORP (XCDR (hot_spot)))
20027 {
20028 struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
20029 Lisp_Object *poly = v->contents;
20030 int n = v->size;
20031 int i;
20032 int inside = 0;
20033 Lisp_Object lx, ly;
20034 int x0, y0;
20035
20036 /* Need an even number of coordinates, and at least 3 edges. */
20037 if (n < 6 || n & 1)
20038 return 0;
20039
20040 /* Count edge segments intersecting line from (X,Y) to (X,infinity).
20041 If count is odd, we are inside polygon. Pixels on edges
20042 may or may not be included depending on actual geometry of the
20043 polygon. */
20044 if ((lx = poly[n-2], !INTEGERP (lx))
20045 || (ly = poly[n-1], !INTEGERP (lx)))
20046 return 0;
20047 x0 = XINT (lx), y0 = XINT (ly);
20048 for (i = 0; i < n; i += 2)
20049 {
20050 int x1 = x0, y1 = y0;
20051 if ((lx = poly[i], !INTEGERP (lx))
20052 || (ly = poly[i+1], !INTEGERP (ly)))
20053 return 0;
20054 x0 = XINT (lx), y0 = XINT (ly);
20055
20056 /* Does this segment cross the X line? */
20057 if (x0 >= x)
20058 {
20059 if (x1 >= x)
20060 continue;
20061 }
20062 else if (x1 < x)
20063 continue;
20064 if (y > y0 && y > y1)
20065 continue;
20066 if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0))
20067 inside = !inside;
20068 }
20069 return inside;
20070 }
20071 }
20072 else
20073 return 0;
20074}
20075
20076Lisp_Object
20077find_hot_spot (map, x, y)
20078 Lisp_Object map;
20079 int x, y;
20080{
20081 while (CONSP (map))
20082 {
20083 if (CONSP (XCAR (map))
20084 && on_hot_spot_p (XCAR (XCAR (map)), x, y))
20085 return XCAR (map);
20086 map = XCDR (map);
20087 }
20088
20089 return Qnil;
20090}
20091
20092DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
20093 3, 3, 0,
20094 doc: /* Lookup in image map MAP coordinates X and Y.
20095An image map is an alist where each element has the format (AREA ID PLIST).
20096An AREA is specified as either a rectangle, a circle, or a polygon:
20097A rectangle is a cons (rect . ((x0 . y0) . (x1 . y1))) specifying the
20098pixel coordinates of the upper left and bottom right corners.
20099A circle is a cons (circle . ((x0 . y0) . r)) specifying the center
20100and the radius of the circle; r may be a float or integer.
20101A polygon is a cons (poly . [x0 y0 x1 y1 ...]) where each pair in the
20102vector describes one corner in the polygon.
20103Returns the alist element for the first matching AREA in MAP. */)
20104 (map, x, y)
20105 Lisp_Object map;
20106 Lisp_Object x, y;
20107{
20108 int ix, iy;
20109 if (NILP (map))
20110 return Qnil;
20111
20112 if (!INTEGERP (x))
20113 wrong_type_argument (Qintegerp, x);
20114 if (!INTEGERP (y))
20115 wrong_type_argument (Qintegerp, y);
20116
20117 return find_hot_spot (map, XINT (x), XINT (y));
20118}
20119
20120
20121/* Display frame CURSOR, optionally using shape defined by POINTER. */
20122static void
20123define_frame_cursor1 (f, cursor, pointer)
20124 struct frame *f;
20125 Cursor cursor;
20126 Lisp_Object pointer;
20127{
20128 if (!NILP (pointer))
20129 {
20130 if (EQ (pointer, Qarrow))
20131 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
20132 else if (EQ (pointer, Qhand))
20133 cursor = FRAME_X_OUTPUT (f)->hand_cursor;
20134 else if (EQ (pointer, Qtext))
20135 cursor = FRAME_X_OUTPUT (f)->text_cursor;
20136 else if (EQ (pointer, intern ("hdrag")))
20137 cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
20138#ifdef HAVE_X_WINDOWS
20139 else if (EQ (pointer, intern ("vdrag")))
20140 cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
20141#endif
20142 else if (EQ (pointer, intern ("hourglass")))
20143 cursor = FRAME_X_OUTPUT (f)->hourglass_cursor;
20144 else if (EQ (pointer, Qmodeline))
20145 cursor = FRAME_X_OUTPUT (f)->modeline_cursor;
20146 else
20147 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
20148 }
20149
20150#ifndef HAVE_CARBON
20151 if (cursor != No_Cursor)
20152#else
20153 if (bcmp (&cursor, &No_Cursor, sizeof (Cursor)))
20154#endif
20155 rif->define_frame_cursor (f, cursor);
20156}
20157
19948/* Take proper action when mouse has moved to the mode or header line 20158/* Take proper action when mouse has moved to the mode or header line
19949 or marginal area AREA of window W, x-position X and y-position Y. 20159 or marginal area AREA of window W, x-position X and y-position Y.
19950 X is relative to the start of the text display area of W, so the 20160 X is relative to the start of the text display area of W, so the
@@ -19960,18 +20170,24 @@ note_mode_line_or_margin_highlight (w, x, y, area)
19960 struct frame *f = XFRAME (w->frame); 20170 struct frame *f = XFRAME (w->frame);
19961 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); 20171 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
19962 Cursor cursor = FRAME_X_OUTPUT (f)->nontext_cursor; 20172 Cursor cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
19963 int charpos; 20173 Lisp_Object pointer = Qnil;
19964 Lisp_Object string, help, map, pos; 20174 int charpos, dx, dy;
20175 Lisp_Object string;
20176 Lisp_Object pos, help, image;
19965 20177
19966 if (area == ON_MODE_LINE || area == ON_HEADER_LINE) 20178 if (area == ON_MODE_LINE || area == ON_HEADER_LINE)
19967 string = mode_line_string (w, &x, &y, 0, 0, area, &charpos); 20179 string = mode_line_string (w, &x, &y, 0, 0, area, &charpos);
19968 else 20180 else
19969 string = marginal_area_string (w, &x, &y, 0, 0, area, &charpos); 20181 {
20182 x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
20183 string = marginal_area_string (w, &x, &y, &dx, &dy, area, &charpos);
20184 }
20185
20186 help = Qnil;
19970 20187
19971 if (STRINGP (string)) 20188 if (STRINGP (string))
19972 { 20189 {
19973 pos = make_number (charpos); 20190 pos = make_number (charpos);
19974
19975 /* If we're on a string with `help-echo' text property, arrange 20191 /* If we're on a string with `help-echo' text property, arrange
19976 for the help to be displayed. This is done by setting the 20192 for the help to be displayed. This is done by setting the
19977 global variable help_echo_string to the help string. */ 20193 global variable help_echo_string to the help string. */
@@ -19984,9 +20200,13 @@ note_mode_line_or_margin_highlight (w, x, y, area)
19984 help_echo_pos = charpos; 20200 help_echo_pos = charpos;
19985 } 20201 }
19986 20202
20203 if (NILP (pointer))
20204 pointer = Fget_text_property (pos, Qpointer, string);
20205
19987 /* Change the mouse pointer according to what is under X/Y. */ 20206 /* Change the mouse pointer according to what is under X/Y. */
19988 if (area == ON_MODE_LINE) 20207 if (NILP (pointer) && area == ON_MODE_LINE)
19989 { 20208 {
20209 Lisp_Object map;
19990 map = Fget_text_property (pos, Qlocal_map, string); 20210 map = Fget_text_property (pos, Qlocal_map, string);
19991 if (!KEYMAPP (map)) 20211 if (!KEYMAPP (map))
19992 map = Fget_text_property (pos, Qkeymap, string); 20212 map = Fget_text_property (pos, Qkeymap, string);
@@ -19994,8 +20214,42 @@ note_mode_line_or_margin_highlight (w, x, y, area)
19994 cursor = dpyinfo->vertical_scroll_bar_cursor; 20214 cursor = dpyinfo->vertical_scroll_bar_cursor;
19995 } 20215 }
19996 } 20216 }
20217 else if (IMAGEP (string))
20218 {
20219 Lisp_Object image_map, hotspot;
20220 if ((image_map = Fplist_get (XCDR (string), QCmap),
20221 !NILP (image_map))
20222 && (hotspot = find_hot_spot (image_map, dx, dy),
20223 CONSP (hotspot))
20224 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
20225 {
20226 Lisp_Object area_id, plist;
19997 20227
19998 rif->define_frame_cursor (f, cursor); 20228 area_id = XCAR (hotspot);
20229 /* Could check AREA_ID to see if we enter/leave this hot-spot.
20230 If so, we could look for mouse-enter, mouse-leave
20231 properties in PLIST (and do something...). */
20232 if ((plist = XCDR (hotspot), CONSP (plist)))
20233 {
20234 pointer = Fplist_get (plist, Qpointer);
20235 if (NILP (pointer))
20236 pointer = Qhand;
20237 help = Fplist_get (plist, Qhelp_echo);
20238 if (!NILP (help))
20239 {
20240 help_echo_string = help;
20241 /* Is this correct? ++kfs */
20242 XSETWINDOW (help_echo_window, w);
20243 help_echo_object = w->buffer;
20244 help_echo_pos = charpos;
20245 }
20246 }
20247 if (NILP (pointer))
20248 pointer = Fplist_get (XCDR (string), QCpointer);
20249 }
20250 }
20251
20252 define_frame_cursor1 (f, cursor, pointer);
19999} 20253}
20000 20254
20001 20255
@@ -20015,6 +20269,7 @@ note_mouse_highlight (f, x, y)
20015 Lisp_Object window; 20269 Lisp_Object window;
20016 struct window *w; 20270 struct window *w;
20017 Cursor cursor = No_Cursor; 20271 Cursor cursor = No_Cursor;
20272 Lisp_Object pointer = Qnil; /* Takes precedence over cursor! */
20018 struct buffer *b; 20273 struct buffer *b;
20019 20274
20020 /* When a menu is active, don't highlight because this looks odd. */ 20275 /* When a menu is active, don't highlight because this looks odd. */
@@ -20052,7 +20307,6 @@ note_mouse_highlight (f, x, y)
20052 return; 20307 return;
20053 20308
20054 /* Reset help_echo_string. It will get recomputed below. */ 20309 /* Reset help_echo_string. It will get recomputed below. */
20055 /* ++KFS: X version didn't do this, but it looks harmless. */
20056 help_echo_string = Qnil; 20310 help_echo_string = Qnil;
20057 20311
20058 /* Convert to window-relative pixel coordinates. */ 20312 /* Convert to window-relative pixel coordinates. */
@@ -20090,7 +20344,7 @@ note_mouse_highlight (f, x, y)
20090 && XFASTINT (w->last_modified) == BUF_MODIFF (b) 20344 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
20091 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b)) 20345 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
20092 { 20346 {
20093 int hpos, vpos, pos, i, area; 20347 int hpos, vpos, pos, i, dx, dy, area;
20094 struct glyph *glyph; 20348 struct glyph *glyph;
20095 Lisp_Object object; 20349 Lisp_Object object;
20096 Lisp_Object mouse_face = Qnil, overlay = Qnil, position; 20350 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
@@ -20100,7 +20354,45 @@ note_mouse_highlight (f, x, y)
20100 int obegv, ozv, same_region; 20354 int obegv, ozv, same_region;
20101 20355
20102 /* Find the glyph under X/Y. */ 20356 /* Find the glyph under X/Y. */
20103 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0); 20357 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area);
20358
20359 /* Look for :pointer property on image. */
20360 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
20361 {
20362 struct image *img = IMAGE_FROM_ID (f, glyph->u.img_id);
20363 if (img != NULL && IMAGEP (img->spec))
20364 {
20365 Lisp_Object image_map, hotspot;
20366 if ((image_map = Fplist_get (XCDR (img->spec), QCmap),
20367 !NILP (image_map))
20368 && (hotspot = find_hot_spot (image_map, dx, dy),
20369 CONSP (hotspot))
20370 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
20371 {
20372 Lisp_Object area_id, plist;
20373
20374 area_id = XCAR (hotspot);
20375 /* Could check AREA_ID to see if we enter/leave this hot-spot.
20376 If so, we could look for mouse-enter, mouse-leave
20377 properties in PLIST (and do something...). */
20378 if ((plist = XCDR (hotspot), CONSP (plist)))
20379 {
20380 pointer = Fplist_get (plist, Qpointer);
20381 if (NILP (pointer))
20382 pointer = Qhand;
20383 help_echo_string = Fplist_get (plist, Qhelp_echo);
20384 if (!NILP (help_echo_string))
20385 {
20386 help_echo_window = window;
20387 help_echo_object = glyph->object;
20388 help_echo_pos = glyph->charpos;
20389 }
20390 }
20391 }
20392 if (NILP (pointer))
20393 pointer = Fplist_get (XCDR (img->spec), QCpointer);
20394 }
20395 }
20104 20396
20105 /* Clear mouse face if X/Y not over text. */ 20397 /* Clear mouse face if X/Y not over text. */
20106 if (glyph == NULL 20398 if (glyph == NULL
@@ -20109,8 +20401,13 @@ note_mouse_highlight (f, x, y)
20109 { 20401 {
20110 if (clear_mouse_face (dpyinfo)) 20402 if (clear_mouse_face (dpyinfo))
20111 cursor = No_Cursor; 20403 cursor = No_Cursor;
20112 if (NILP (Vshow_text_cursor_in_void)) 20404 if (NILP (pointer))
20113 cursor = FRAME_X_OUTPUT (f)->nontext_cursor; 20405 {
20406 if (area != TEXT_AREA)
20407 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
20408 else
20409 pointer = Vvoid_text_area_pointer;
20410 }
20114 goto set_cursor; 20411 goto set_cursor;
20115 } 20412 }
20116 20413
@@ -20123,9 +20420,6 @@ note_mouse_highlight (f, x, y)
20123 if (BUFFERP (object) && pos > BUF_Z (b)) 20420 if (BUFFERP (object) && pos > BUF_Z (b))
20124 goto set_cursor; 20421 goto set_cursor;
20125 20422
20126 if (glyph->type == IMAGE_GLYPH)
20127 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
20128
20129 /* Make the window's buffer temporarily current for 20423 /* Make the window's buffer temporarily current for
20130 overlays_at and compute_char_face. */ 20424 overlays_at and compute_char_face. */
20131 obuf = current_buffer; 20425 obuf = current_buffer;
@@ -20369,7 +20663,7 @@ note_mouse_highlight (f, x, y)
20369 check_help_echo: 20663 check_help_echo:
20370 20664
20371 /* Look for a `help-echo' property. */ 20665 /* Look for a `help-echo' property. */
20372 { 20666 if (NILP (help_echo_string)) {
20373 Lisp_Object help, overlay; 20667 Lisp_Object help, overlay;
20374 20668
20375 /* Check overlays first. */ 20669 /* Check overlays first. */
@@ -20435,6 +20729,46 @@ note_mouse_highlight (f, x, y)
20435 } 20729 }
20436 } 20730 }
20437 20731
20732 /* Look for a `pointer' property. */
20733 if (NILP (pointer))
20734 {
20735 /* Check overlays first. */
20736 for (i = noverlays - 1; i >= 0 && NILP (pointer); --i)
20737 pointer = Foverlay_get (overlay_vec[i], Qpointer);
20738
20739 if (NILP (pointer))
20740 {
20741 Lisp_Object object = glyph->object;
20742 int charpos = glyph->charpos;
20743
20744 /* Try text properties. */
20745 if (STRINGP (object)
20746 && charpos >= 0
20747 && charpos < SCHARS (object))
20748 {
20749 pointer = Fget_text_property (make_number (charpos),
20750 Qpointer, object);
20751 if (NILP (pointer))
20752 {
20753 /* If the string itself doesn't specify a pointer,
20754 see if the buffer text ``under'' it does. */
20755 struct glyph_row *r
20756 = MATRIX_ROW (w->current_matrix, vpos);
20757 int start = MATRIX_ROW_START_CHARPOS (r);
20758 int pos = string_buffer_position (w, object, start);
20759 if (pos > 0)
20760 pointer = Fget_char_property (make_number (pos),
20761 Qpointer, w->buffer);
20762 }
20763 }
20764 else if (BUFFERP (object)
20765 && charpos >= BEGV
20766 && charpos < ZV)
20767 pointer = Fget_text_property (make_number (charpos),
20768 Qpointer, object);
20769 }
20770 }
20771
20438 BEGV = obegv; 20772 BEGV = obegv;
20439 ZV = ozv; 20773 ZV = ozv;
20440 current_buffer = obuf; 20774 current_buffer = obuf;
@@ -20442,12 +20776,7 @@ note_mouse_highlight (f, x, y)
20442 20776
20443 set_cursor: 20777 set_cursor:
20444 20778
20445#ifndef HAVE_CARBON 20779 define_frame_cursor1 (f, cursor, pointer);
20446 if (cursor != No_Cursor)
20447#else
20448 if (bcmp (&cursor, &No_Cursor, sizeof (Cursor)))
20449#endif
20450 rif->define_frame_cursor (f, cursor);
20451} 20780}
20452 20781
20453 20782
@@ -21043,6 +21372,7 @@ syms_of_xdisp ()
21043#endif 21372#endif
21044#ifdef HAVE_WINDOW_SYSTEM 21373#ifdef HAVE_WINDOW_SYSTEM
21045 defsubr (&Stool_bar_lines_needed); 21374 defsubr (&Stool_bar_lines_needed);
21375 defsubr (&Slookup_image_map);
21046#endif 21376#endif
21047 defsubr (&Sformat_mode_line); 21377 defsubr (&Sformat_mode_line);
21048 21378
@@ -21076,16 +21406,14 @@ syms_of_xdisp ()
21076 staticpro (&Qspace); 21406 staticpro (&Qspace);
21077 Qmargin = intern ("margin"); 21407 Qmargin = intern ("margin");
21078 staticpro (&Qmargin); 21408 staticpro (&Qmargin);
21409 Qpointer = intern ("pointer");
21410 staticpro (&Qpointer);
21079 Qleft_margin = intern ("left-margin"); 21411 Qleft_margin = intern ("left-margin");
21080 staticpro (&Qleft_margin); 21412 staticpro (&Qleft_margin);
21081 Qright_margin = intern ("right-margin"); 21413 Qright_margin = intern ("right-margin");
21082 staticpro (&Qright_margin); 21414 staticpro (&Qright_margin);
21083 Qalign_to = intern ("align-to");
21084 staticpro (&Qalign_to);
21085 QCalign_to = intern (":align-to"); 21415 QCalign_to = intern (":align-to");
21086 staticpro (&QCalign_to); 21416 staticpro (&QCalign_to);
21087 Qrelative_width = intern ("relative-width");
21088 staticpro (&Qrelative_width);
21089 QCrelative_width = intern (":relative-width"); 21417 QCrelative_width = intern (":relative-width");
21090 staticpro (&QCrelative_width); 21418 staticpro (&QCrelative_width);
21091 QCrelative_height = intern (":relative-height"); 21419 QCrelative_height = intern (":relative-height");
@@ -21104,6 +21432,16 @@ syms_of_xdisp ()
21104 staticpro (&Qtrailing_whitespace); 21432 staticpro (&Qtrailing_whitespace);
21105 Qimage = intern ("image"); 21433 Qimage = intern ("image");
21106 staticpro (&Qimage); 21434 staticpro (&Qimage);
21435 QCmap = intern (":map");
21436 staticpro (&QCmap);
21437 QCpointer = intern (":pointer");
21438 staticpro (&QCpointer);
21439 Qrect = intern ("rect");
21440 staticpro (&Qrect);
21441 Qcircle = intern ("circle");
21442 staticpro (&Qcircle);
21443 Qpoly = intern ("poly");
21444 staticpro (&Qpoly);
21107 Qmessage_truncate_lines = intern ("message-truncate-lines"); 21445 Qmessage_truncate_lines = intern ("message-truncate-lines");
21108 staticpro (&Qmessage_truncate_lines); 21446 staticpro (&Qmessage_truncate_lines);
21109 Qcursor_in_non_selected_windows = intern ("cursor-in-non-selected-windows"); 21447 Qcursor_in_non_selected_windows = intern ("cursor-in-non-selected-windows");
@@ -21128,6 +21466,12 @@ syms_of_xdisp ()
21128 staticpro (&Qbox); 21466 staticpro (&Qbox);
21129 Qhollow = intern ("hollow"); 21467 Qhollow = intern ("hollow");
21130 staticpro (&Qhollow); 21468 staticpro (&Qhollow);
21469 Qhand = intern ("hand");
21470 staticpro (&Qhand);
21471 Qarrow = intern ("arrow");
21472 staticpro (&Qarrow);
21473 Qtext = intern ("text");
21474 staticpro (&Qtext);
21131 Qrisky_local_variable = intern ("risky-local-variable"); 21475 Qrisky_local_variable = intern ("risky-local-variable");
21132 staticpro (&Qrisky_local_variable); 21476 staticpro (&Qrisky_local_variable);
21133 Qinhibit_free_realized_faces = intern ("inhibit-free-realized-faces"); 21477 Qinhibit_free_realized_faces = intern ("inhibit-free-realized-faces");
@@ -21181,10 +21525,11 @@ wide as that tab on the display. */);
21181The face used for trailing whitespace is `trailing-whitespace'. */); 21525The face used for trailing whitespace is `trailing-whitespace'. */);
21182 Vshow_trailing_whitespace = Qnil; 21526 Vshow_trailing_whitespace = Qnil;
21183 21527
21184 DEFVAR_LISP ("show-text-cursor-in-void", &Vshow_text_cursor_in_void, 21528 DEFVAR_LISP ("void-text-area-pointer", &Vvoid_text_area_pointer,
21185 doc: /* Non-nil means show the text cursor in void text areas. 21529 doc: /* The pointer shape to show in void text areas.
21186The default is to show the non-text (typically arrow) cursor. */); 21530Nil means to show the text pointer. Other options are `arrow', `text',
21187 Vshow_text_cursor_in_void = Qnil; 21531`hand', `vdrag', `hdrag', `modeline', and `hourglass'. */);
21532 Vvoid_text_area_pointer = Qarrow;
21188 21533
21189 DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay, 21534 DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
21190 doc: /* Non-nil means don't actually do any redisplay. 21535 doc: /* Non-nil means don't actually do any redisplay.