comparison src/xdisp.c @ 53333:c23cf5520cd9

(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.
author Kim F. Storm <storm@cua.dk>
date Sun, 28 Dec 2003 00:12:27 +0000
parents a0409e91c835
children 09ea561dfa8c 57e2656285e7
comparison
equal deleted inserted replaced
53332:21301d0e0505 53333:c23cf5520cd9
240 Lisp_Object Qbuffer_position, Qposition, Qobject; 240 Lisp_Object Qbuffer_position, Qposition, Qobject;
241 241
242 /* Cursor shapes */ 242 /* Cursor shapes */
243 Lisp_Object Qbar, Qhbar, Qbox, Qhollow; 243 Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
244 244
245 /* Pointer shapes */
246 Lisp_Object Qarrow, Qhand, Qtext;
247
245 Lisp_Object Qrisky_local_variable; 248 Lisp_Object Qrisky_local_variable;
246 249
247 /* Holds the list (error). */ 250 /* Holds the list (error). */
248 Lisp_Object list_of_error; 251 Lisp_Object list_of_error;
249 252
288 291
289 int inhibit_eval_during_redisplay; 292 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
293 Lisp_Object Qdisplay, Qrelative_width, Qalign_to; 296 Lisp_Object Qdisplay;
294 extern Lisp_Object Qface, Qinvisible, Qwidth; 297 extern Lisp_Object Qface, Qinvisible, Qwidth;
295 298
296 /* Symbols used in text property values. */ 299 /* Symbols used in text property values. */
297 300
298 Lisp_Object Vdisplay_pixels_per_inch; 301 Lisp_Object Vdisplay_pixels_per_inch;
299 Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height; 302 Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
300 Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise; 303 Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
301 Lisp_Object Qmargin; 304 Lisp_Object Qmargin, Qpointer;
302 extern Lisp_Object Qheight; 305 extern Lisp_Object Qheight;
303 extern Lisp_Object QCwidth, QCheight, QCascent; 306 extern Lisp_Object QCwidth, QCheight, QCascent;
304 extern Lisp_Object Qscroll_bar; 307 extern Lisp_Object Qscroll_bar;
305 308
306 /* Non-nil means highlight trailing whitespace. */ 309 /* Non-nil means highlight trailing whitespace. */
309 312
310 /* Non-nil means show the text cursor in void text areas 313 /* Non-nil means show the text cursor in void text areas
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
314 Lisp_Object Vshow_text_cursor_in_void; 317 Lisp_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
318 Lisp_Object Qtrailing_whitespace; 321 Lisp_Object Qtrailing_whitespace;
319 322
320 /* The symbol `image' which is the car of the lists used to represent 323 /* The symbol `image' which is the car of the lists used to represent
321 images in Lisp. */ 324 images in Lisp. */
322 325
323 Lisp_Object Qimage; 326 Lisp_Object Qimage;
327
328 /* The image map types. */
329 Lisp_Object QCmap, QCpointer;
330 Lisp_Object Qrect, Qcircle, Qpoly;
324 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
328 int noninteractive_need_newline; 335 int noninteractive_need_newline;
1580 Value is a pointer to the glyph found or null if X/Y is not on 1587 Value is a pointer to the glyph found or null if X/Y is not on
1581 text, or we can't tell because W's current matrix is not up to 1588 text, or we can't tell because W's current matrix is not up to
1582 date. */ 1589 date. */
1583 1590
1584 static struct glyph * 1591 static struct glyph *
1585 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p) 1592 x_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;
1593 int x0, i; 1599 int x0, i;
1594 1600
1635 } 1641 }
1636 1642
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;
1641 { 1647 while (glyph < end && x >= glyph->pixel_width)
1642 if (x < x0 + glyph->pixel_width) 1648 {
1643 { 1649 x -= glyph->pixel_width;
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;
1655
1656 if (dx)
1657 {
1658 *dx = x;
1659 *dy = y - (row->y + row->ascent - glyph->ascent);
1660 }
1656 1661
1657 *hpos = glyph - row->glyphs[*area]; 1662 *hpos = glyph - row->glyphs[*area];
1658 return glyph; 1663 return glyph;
1659 } 1664 }
1660 1665
1739 r.y -= FRAME_INTERNAL_BORDER_WIDTH (s->f); 1744 r.y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
1740 } 1745 }
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);
1756 } 1762
1757 #endif 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 }
1770 }
1758 1771
1759 #ifdef CONVERT_FROM_XRECT 1772 #ifdef CONVERT_FROM_XRECT
1760 CONVERT_FROM_XRECT (r, *nr); 1773 CONVERT_FROM_XRECT (r, *nr);
1761 #else 1774 #else
1762 *nr = r; 1775 *nr = r;
8277 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX)) 8290 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
8278 8291
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. */
8286 image = PROP (TOOL_BAR_ITEM_IMAGES); 8299 image = PROP (TOOL_BAR_ITEM_IMAGES);
8287 if (VECTORP (image)) 8300 if (VECTORP (image))
8694 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); 8707 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8695 struct window *w = XWINDOW (f->tool_bar_window); 8708 struct window *w = XWINDOW (f->tool_bar_window);
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
8703 /* Get the start of this tool-bar item's properties in 8716 /* Get the start of this tool-bar item's properties in
8704 f->tool_bar_items. */ 8717 f->tool_bar_items. */
17683 if (glyph < it->glyph_row->glyphs[area + 1]) 17696 if (glyph < it->glyph_row->glyphs[area + 1])
17684 { 17697 {
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;
17691 glyph->left_box_line_p = it->start_of_box_run_p; 17706 glyph->left_box_line_p = it->start_of_box_run_p;
17692 glyph->right_box_line_p = it->end_of_box_run_p; 17707 glyph->right_box_line_p = it->end_of_box_run_p;
17717 if (glyph < it->glyph_row->glyphs[area + 1]) 17732 if (glyph < it->glyph_row->glyphs[area + 1])
17718 { 17733 {
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;
17725 glyph->left_box_line_p = it->start_of_box_run_p; 17742 glyph->left_box_line_p = it->start_of_box_run_p;
17726 glyph->right_box_line_p = it->end_of_box_run_p; 17743 glyph->right_box_line_p = it->end_of_box_run_p;
17765 produce_image_glyph (it) 17782 produce_image_glyph (it)
17766 struct it *it; 17783 struct it *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
17773 face = FACE_FROM_ID (it->f, it->face_id); 17791 face = FACE_FROM_ID (it->f, it->face_id);
17774 img = IMAGE_FROM_ID (it->f, it->image_id); 17792 img = IMAGE_FROM_ID (it->f, it->image_id);
17776 17794
17777 /* Make sure X resources of the face and image are loaded. */ 17795 /* Make sure X resources of the face and image are loaded. */
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;
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;
17784 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)
17788 { 17811 {
17809 if (glyph < it->glyph_row->glyphs[area + 1]) 17832 if (glyph < it->glyph_row->glyphs[area + 1])
17810 { 17833 {
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;
17817 glyph->left_box_line_p = it->start_of_box_run_p; 17842 glyph->left_box_line_p = it->start_of_box_run_p;
17818 glyph->right_box_line_p = it->end_of_box_run_p; 17843 glyph->right_box_line_p = it->end_of_box_run_p;
17848 if (glyph < it->glyph_row->glyphs[area + 1]) 17873 if (glyph < it->glyph_row->glyphs[area + 1])
17849 { 17874 {
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;
17856 glyph->left_box_line_p = it->start_of_box_run_p; 17883 glyph->left_box_line_p = it->start_of_box_run_p;
17857 glyph->right_box_line_p = it->end_of_box_run_p; 17884 glyph->right_box_line_p = it->end_of_box_run_p;
19943 19970
19944 return best_glyph != NULL; 19971 return best_glyph != NULL;
19945 } 19972 }
19946 19973
19947 19974
19975 /* See if position X, Y is within a hot-spot of an image. */
19976
19977 static int
19978 on_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
20076 Lisp_Object
20077 find_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
20092 DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
20093 3, 3, 0,
20094 doc: /* Lookup in image map MAP coordinates X and Y.
20095 An image map is an alist where each element has the format (AREA ID PLIST).
20096 An AREA is specified as either a rectangle, a circle, or a polygon:
20097 A rectangle is a cons (rect . ((x0 . y0) . (x1 . y1))) specifying the
20098 pixel coordinates of the upper left and bottom right corners.
20099 A circle is a cons (circle . ((x0 . y0) . r)) specifying the center
20100 and the radius of the circle; r may be a float or integer.
20101 A polygon is a cons (poly . [x0 y0 x1 y1 ...]) where each pair in the
20102 vector describes one corner in the polygon.
20103 Returns 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. */
20122 static void
20123 define_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
19951 width of bitmap areas and scroll bars must be subtracted to get a 20161 width of bitmap areas and scroll bars must be subtracted to get a
19952 position relative to the start of the mode line. */ 20162 position relative to the start of the mode line. */
19958 enum window_part area; 20168 enum window_part area;
19959 { 20169 {
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. */
19978 help = Fget_text_property (pos, Qhelp_echo, string); 20194 help = Fget_text_property (pos, Qhelp_echo, string);
19979 if (!NILP (help)) 20195 if (!NILP (help))
19982 XSETWINDOW (help_echo_window, w); 20198 XSETWINDOW (help_echo_window, w);
19983 help_echo_object = string; 20199 help_echo_object = string;
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);
19993 if (!KEYMAPP (map)) 20213 if (!KEYMAPP (map))
19994 cursor = dpyinfo->vertical_scroll_bar_cursor; 20214 cursor = dpyinfo->vertical_scroll_bar_cursor;
19995 } 20215 }
19996 } 20216 }
19997 20217 else if (IMAGEP (string))
19998 rif->define_frame_cursor (f, cursor); 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;
20227
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
20002 /* EXPORT: 20256 /* EXPORT:
20003 Take proper action when the mouse has moved to position X, Y on 20257 Take proper action when the mouse has moved to position X, Y on
20013 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); 20267 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
20014 enum window_part part; 20268 enum window_part part;
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. */
20021 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI) 20276 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
20022 if (popup_activated ()) 20277 if (popup_activated ())
20050 /* Not on a window -> return. */ 20305 /* Not on a window -> return. */
20051 if (!WINDOWP (window)) 20306 if (!WINDOWP (window))
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. */
20059 w = XWINDOW (window); 20313 w = XWINDOW (window);
20060 frame_to_window_pixel_xy (w, &x, &y); 20314 frame_to_window_pixel_xy (w, &x, &y);
20088 if (part == ON_TEXT 20342 if (part == ON_TEXT
20089 && EQ (w->window_end_valid, w->buffer) 20343 && EQ (w->window_end_valid, w->buffer)
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;
20097 Lisp_Object *overlay_vec = NULL; 20351 Lisp_Object *overlay_vec = NULL;
20098 int len, noverlays; 20352 int len, noverlays;
20099 struct buffer *obuf; 20353 struct buffer *obuf;
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
20107 || area != TEXT_AREA 20399 || area != TEXT_AREA
20108 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p) 20400 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
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
20117 pos = glyph->charpos; 20414 pos = glyph->charpos;
20118 object = glyph->object; 20415 object = glyph->object;
20120 goto set_cursor; 20417 goto set_cursor;
20121 20418
20122 /* If we get an out-of-range value, return now; avoid an error. */ 20419 /* If we get an out-of-range value, return now; avoid an error. */
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
20126 if (glyph->type == IMAGE_GLYPH)
20127 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
20128 20422
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;
20132 current_buffer = b; 20426 current_buffer = b;
20367 } 20661 }
20368 20662
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. */
20376 help = overlay = Qnil; 20670 help = overlay = Qnil;
20377 for (i = noverlays - 1; i >= 0 && NILP (help); --i) 20671 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
20433 help_echo_pos = charpos; 20727 help_echo_pos = charpos;
20434 } 20728 }
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;
20441 } 20775 }
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
20454 /* EXPORT for RIF: 20783 /* EXPORT for RIF:
20455 Clear any mouse-face on window W. This function is part of the 20784 Clear any mouse-face on window W. This function is part of the
21041 defsubr (&Strace_redisplay); 21370 defsubr (&Strace_redisplay);
21042 defsubr (&Strace_to_stderr); 21371 defsubr (&Strace_to_stderr);
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
21049 staticpro (&Qmenu_bar_update_hook); 21379 staticpro (&Qmenu_bar_update_hook);
21050 Qmenu_bar_update_hook = intern ("menu-bar-update-hook"); 21380 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
21074 staticpro (&Qraise); 21404 staticpro (&Qraise);
21075 Qspace = intern ("space"); 21405 Qspace = intern ("space");
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");
21092 staticpro (&QCrelative_height); 21420 staticpro (&QCrelative_height);
21093 QCeval = intern (":eval"); 21421 QCeval = intern (":eval");
21102 staticpro (&Qfontification_functions); 21430 staticpro (&Qfontification_functions);
21103 Qtrailing_whitespace = intern ("trailing-whitespace"); 21431 Qtrailing_whitespace = intern ("trailing-whitespace");
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");
21110 staticpro (&Qcursor_in_non_selected_windows); 21448 staticpro (&Qcursor_in_non_selected_windows);
21111 Qgrow_only = intern ("grow-only"); 21449 Qgrow_only = intern ("grow-only");
21126 staticpro (&Qhbar); 21464 staticpro (&Qhbar);
21127 Qbox = intern ("box"); 21465 Qbox = intern ("box");
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");
21134 staticpro (&Qinhibit_free_realized_faces); 21478 staticpro (&Qinhibit_free_realized_faces);
21135 21479
21179 DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace, 21523 DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
21180 doc: /* Non-nil means highlight trailing whitespace. 21524 doc: /* Non-nil means highlight trailing whitespace.
21181 The face used for trailing whitespace is `trailing-whitespace'. */); 21525 The 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.
21186 The default is to show the non-text (typically arrow) cursor. */); 21530 Nil 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.
21191 This is used for internal purposes. */); 21536 This is used for internal purposes. */);
21192 Vinhibit_redisplay = Qnil; 21537 Vinhibit_redisplay = Qnil;