X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/e6c3da2065ac72cc4e1a2bef22d367cd75401892..727e958ef0548f3d8ce02a4a971247f52cc548ce:/src/xdisp.c diff --git a/src/xdisp.c b/src/xdisp.c index 91d1b6ea2e..02467c7bed 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -254,7 +254,7 @@ along with GNU Emacs. If not, see . */ still left to right, i.e. the iterator "thinks" the first character is at the leftmost pixel position. The iterator does not know that PRODUCE_GLYPHS reverses the order of the glyphs that the iterator - delivers. This is important when functions from the the move_it_* + delivers. This is important when functions from the move_it_* family are used to get to certain screen position or to match screen coordinates with buffer coordinates: these functions use the iterator geometry, which is left to right even in R2L paragraphs. @@ -779,7 +779,6 @@ static void store_mode_line_noprop_char (char); static int store_mode_line_noprop (const char *, int, int); static void handle_stop (struct it *); static void handle_stop_backwards (struct it *, EMACS_INT); -static int single_display_spec_intangible_p (Lisp_Object); static void vmessage (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0); static void ensure_echo_area_buffers (void); static Lisp_Object unwind_with_echo_area_buffer (Lisp_Object); @@ -812,7 +811,7 @@ static int try_scrolling (Lisp_Object, int, EMACS_INT, EMACS_INT, int, int); static int try_cursor_movement (Lisp_Object, struct text_pos, int *); static int trailing_whitespace_p (EMACS_INT); static unsigned long int message_log_check_duplicate (EMACS_INT, EMACS_INT); -static void push_it (struct it *); +static void push_it (struct it *, struct text_pos *); static void pop_it (struct it *); static void sync_frame_with_window_matrix_rows (struct window *); static void select_frame_for_redisplay (Lisp_Object); @@ -884,9 +883,11 @@ static void compute_string_pos (struct text_pos *, struct text_pos, Lisp_Object); static int face_before_or_after_it_pos (struct it *, int); static EMACS_INT next_overlay_change (EMACS_INT); +static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object, + Lisp_Object, struct text_pos *, EMACS_INT, int); static int handle_single_display_spec (struct it *, Lisp_Object, Lisp_Object, Lisp_Object, - struct text_pos *, int); + struct text_pos *, EMACS_INT, int, int); static int underlying_face_id (struct it *); static int in_ellipses_for_invisible_text_p (struct display_pos *, struct window *); @@ -926,7 +927,7 @@ static int coords_in_mouse_face_p (struct window *, int, int); This is the height of W minus the height of a mode line, if any. */ -INLINE int +inline int window_text_bottom_y (struct window *w) { int height = WINDOW_TOTAL_HEIGHT (w); @@ -940,7 +941,7 @@ window_text_bottom_y (struct window *w) means return the total width of W, not including fringes to the left and right of the window. */ -INLINE int +inline int window_box_width (struct window *w, int area) { int cols = XFASTINT (w->total_cols); @@ -979,7 +980,7 @@ window_box_width (struct window *w, int area) /* Return the pixel height of the display area of window W, not including mode lines of W, if any. */ -INLINE int +inline int window_box_height (struct window *w) { struct frame *f = XFRAME (w->frame); @@ -1026,7 +1027,7 @@ window_box_height (struct window *w) area AREA of window W. AREA < 0 means return the left edge of the whole window, to the right of the left fringe of W. */ -INLINE int +inline int window_box_left_offset (struct window *w, int area) { int x; @@ -1058,7 +1059,7 @@ window_box_left_offset (struct window *w, int area) area AREA of window W. AREA < 0 means return the right edge of the whole window, to the left of the right fringe of W. */ -INLINE int +inline int window_box_right_offset (struct window *w, int area) { return window_box_left_offset (w, area) + window_box_width (w, area); @@ -1068,7 +1069,7 @@ window_box_right_offset (struct window *w, int area) area AREA of window W. AREA < 0 means return the left edge of the whole window, to the right of the left fringe of W. */ -INLINE int +inline int window_box_left (struct window *w, int area) { struct frame *f = XFRAME (w->frame); @@ -1088,7 +1089,7 @@ window_box_left (struct window *w, int area) area AREA of window W. AREA < 0 means return the right edge of the whole window, to the left of the right fringe of W. */ -INLINE int +inline int window_box_right (struct window *w, int area) { return window_box_left (w, area) + window_box_width (w, area); @@ -1101,7 +1102,7 @@ window_box_right (struct window *w, int area) coordinates of the upper-left corner of the box. Return in *BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box. */ -INLINE void +inline void window_box (struct window *w, int area, int *box_x, int *box_y, int *box_width, int *box_height) { @@ -1128,7 +1129,7 @@ window_box (struct window *w, int area, int *box_x, int *box_y, *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the box. */ -static INLINE void +static inline void window_box_edges (struct window *w, int area, int *top_left_x, int *top_left_y, int *bottom_right_x, int *bottom_right_y) { @@ -1328,7 +1329,7 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y, returns an invalid character. If we find one, we return a `?', but with the length of the invalid character. */ -static INLINE int +static inline int string_char_and_length (const unsigned char *str, int *len) { int c; @@ -1376,7 +1377,7 @@ string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, EMACS_INT ncha /* Value is the text position, i.e. character and byte position, for character position CHARPOS in STRING. */ -static INLINE struct text_pos +static inline struct text_pos string_pos (EMACS_INT charpos, Lisp_Object string) { struct text_pos pos; @@ -2564,7 +2565,7 @@ init_iterator (struct it *it, struct window *w, it->paragraph_embedding = R2L; else it->paragraph_embedding = NEUTRAL_DIR; - bidi_init_it (charpos, bytepos, &it->bidi_it); + bidi_init_it (charpos, bytepos, FRAME_WINDOW_P (it->f), &it->bidi_it); } /* If a buffer position was specified, set the iterator there, @@ -3085,6 +3086,82 @@ next_overlay_change (EMACS_INT pos) return endpos; } +/* Return the character position of a display string at or after CHARPOS. + If no display string exists at or after CHARPOS, return ZV. A + display string is either an overlay with `display' property whose + value is a string, or a `display' text property whose value is a + string. FRAME_WINDOW_P is non-zero when we are displaying a window + on a GUI frame. */ +EMACS_INT +compute_display_string_pos (EMACS_INT charpos, int frame_window_p) +{ + /* FIXME: Support display properties on strings (object = Qnil means + current buffer). */ + Lisp_Object object = Qnil; + Lisp_Object pos, spec; + struct text_pos position; + EMACS_INT bufpos; + + if (charpos >= ZV) + return ZV; + + /* If the character at CHARPOS is where the display string begins, + return CHARPOS. */ + pos = make_number (charpos); + CHARPOS (position) = charpos; + BYTEPOS (position) = CHAR_TO_BYTE (charpos); + bufpos = charpos; /* FIXME! support strings as well */ + if (!NILP (spec = Fget_char_property (pos, Qdisplay, object)) + && (charpos <= BEGV + || !EQ (Fget_char_property (make_number (charpos - 1), Qdisplay, + object), + spec)) + && handle_display_spec (NULL, spec, object, Qnil, &position, bufpos, + frame_window_p)) + return charpos; + + /* Look forward for the first character with a `display' property + that will replace the underlying text when displayed. */ + do { + pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil); + CHARPOS (position) = XFASTINT (pos); + BYTEPOS (position) = CHAR_TO_BYTE (CHARPOS (position)); + if (CHARPOS (position) >= ZV) + break; + spec = Fget_char_property (pos, Qdisplay, object); + bufpos = CHARPOS (position); /* FIXME! support strings as well */ + } while (NILP (spec) + || !handle_display_spec (NULL, spec, object, Qnil, &position, bufpos, + frame_window_p)); + + return CHARPOS (position); +} + +/* Return the character position of the end of the display string that + started at CHARPOS. A display string is either an overlay with + `display' property whose value is a string or a `display' text + property whose value is a string. */ +EMACS_INT +compute_display_string_end (EMACS_INT charpos) +{ + /* FIXME: Support display properties on strings (object = Qnil means + current buffer). */ + Lisp_Object object = Qnil; + Lisp_Object pos = make_number (charpos); + + if (charpos >= ZV) + return ZV; + + if (NILP (Fget_char_property (pos, Qdisplay, object))) + abort (); + + /* Look forward for the first character where the `display' property + changes. */ + pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil); + + return XFASTINT (pos); +} + /*********************************************************************** @@ -3705,7 +3782,7 @@ setup_for_ellipsis (struct it *it, int len) { struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp)); it->dpvec = v->contents; - it->dpend = v->contents + v->size; + it->dpend = v->contents + v->header.size; } else { @@ -3743,8 +3820,9 @@ setup_for_ellipsis (struct it *it, int len) static enum prop_handled handle_display_prop (struct it *it) { - Lisp_Object prop, object, overlay; + Lisp_Object propval, object, overlay; struct text_pos *position; + EMACS_INT bufpos; /* Nonzero if some property replaces the display of the text itself. */ int display_replaced_p = 0; @@ -3752,11 +3830,13 @@ handle_display_prop (struct it *it) { object = it->string; position = &it->current.string_pos; + bufpos = CHARPOS (it->current.pos); } else { XSETWINDOW (object, it->w); position = &it->current.pos; + bufpos = CHARPOS (*position); } /* Reset those iterator values set from display property values. */ @@ -3771,9 +3851,9 @@ handle_display_prop (struct it *it) if (!it->string_from_display_prop_p) it->area = TEXT_AREA; - prop = get_char_property_and_overlay (make_number (position->charpos), - Qdisplay, object, &overlay); - if (NILP (prop)) + propval = get_char_property_and_overlay (make_number (position->charpos), + Qdisplay, object, &overlay); + if (NILP (propval)) return HANDLED_NORMALLY; /* Now OVERLAY is the overlay that gave us this property, or nil if it was a text property. */ @@ -3781,59 +3861,88 @@ handle_display_prop (struct it *it) if (!STRINGP (it->string)) object = it->w->buffer; - if (CONSP (prop) - /* Simple properties. */ - && !EQ (XCAR (prop), Qimage) - && !EQ (XCAR (prop), Qspace) - && !EQ (XCAR (prop), Qwhen) - && !EQ (XCAR (prop), Qslice) - && !EQ (XCAR (prop), Qspace_width) - && !EQ (XCAR (prop), Qheight) - && !EQ (XCAR (prop), Qraise) + display_replaced_p = handle_display_spec (it, propval, object, overlay, + position, bufpos, + FRAME_WINDOW_P (it->f)); + + return display_replaced_p ? HANDLED_RETURN : HANDLED_NORMALLY; +} + +/* Subroutine of handle_display_prop. Returns non-zero if the display + specification in SPEC is a replacing specification, i.e. it would + replace the text covered by `display' property with something else, + such as an image or a display string. + + See handle_single_display_spec for documentation of arguments. + frame_window_p is non-zero if the window being redisplayed is on a + GUI frame; this argument is used only if IT is NULL, see below. + + IT can be NULL, if this is called by the bidi reordering code + through compute_display_string_pos, which see. In that case, this + function only examines SPEC, but does not otherwise "handle" it, in + the sense that it doesn't set up members of IT from the display + spec. */ +static int +handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, + Lisp_Object overlay, struct text_pos *position, + EMACS_INT bufpos, int frame_window_p) +{ + int replacing_p = 0; + + if (CONSP (spec) + /* Simple specerties. */ + && !EQ (XCAR (spec), Qimage) + && !EQ (XCAR (spec), Qspace) + && !EQ (XCAR (spec), Qwhen) + && !EQ (XCAR (spec), Qslice) + && !EQ (XCAR (spec), Qspace_width) + && !EQ (XCAR (spec), Qheight) + && !EQ (XCAR (spec), Qraise) /* Marginal area specifications. */ - && !(CONSP (XCAR (prop)) && EQ (XCAR (XCAR (prop)), Qmargin)) - && !EQ (XCAR (prop), Qleft_fringe) - && !EQ (XCAR (prop), Qright_fringe) - && !NILP (XCAR (prop))) + && !(CONSP (XCAR (spec)) && EQ (XCAR (XCAR (spec)), Qmargin)) + && !EQ (XCAR (spec), Qleft_fringe) + && !EQ (XCAR (spec), Qright_fringe) + && !NILP (XCAR (spec))) { - for (; CONSP (prop); prop = XCDR (prop)) + for (; CONSP (spec); spec = XCDR (spec)) { - if (handle_single_display_spec (it, XCAR (prop), object, overlay, - position, display_replaced_p)) + if (handle_single_display_spec (it, XCAR (spec), object, overlay, + position, bufpos, replacing_p, + frame_window_p)) { - display_replaced_p = 1; + replacing_p = 1; /* If some text in a string is replaced, `position' no longer points to the position of `object'. */ - if (STRINGP (object)) + if (!it || STRINGP (object)) break; } } } - else if (VECTORP (prop)) + else if (VECTORP (spec)) { int i; - for (i = 0; i < ASIZE (prop); ++i) - if (handle_single_display_spec (it, AREF (prop, i), object, overlay, - position, display_replaced_p)) + for (i = 0; i < ASIZE (spec); ++i) + if (handle_single_display_spec (it, AREF (spec, i), object, overlay, + position, bufpos, replacing_p, + frame_window_p)) { - display_replaced_p = 1; + replacing_p = 1; /* If some text in a string is replaced, `position' no longer points to the position of `object'. */ - if (STRINGP (object)) + if (!it || STRINGP (object)) break; } } else { - if (handle_single_display_spec (it, prop, object, overlay, - position, 0)) - display_replaced_p = 1; + if (handle_single_display_spec (it, spec, object, overlay, + position, bufpos, 0, frame_window_p)) + replacing_p = 1; } - return display_replaced_p ? HANDLED_RETURN : HANDLED_NORMALLY; + return replacing_p; } - /* Value is the position of the end of the `display' property starting at START_POS in OBJECT. */ @@ -3855,31 +3964,38 @@ display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos) } -/* Set up IT from a single `display' specification PROP. OBJECT +/* Set up IT from a single `display' property specification SPEC. OBJECT is the object in which the `display' property was found. *POSITION - is the position at which it was found. DISPLAY_REPLACED_P non-zero - means that we previously saw a display specification which already - replaced text display with something else, for example an image; - we ignore such properties after the first one has been processed. + is the position in OBJECT at which the `display' property was found. + BUFPOS is the buffer position of OBJECT (different from POSITION if + OBJECT is not a buffer). DISPLAY_REPLACED_P non-zero means that we + previously saw a display specification which already replaced text + display with something else, for example an image; we ignore such + properties after the first one has been processed. OVERLAY is the overlay this `display' property came from, or nil if it was a text property. - If PROP is a `space' or `image' specification, and in some other + If SPEC is a `space' or `image' specification, and in some other cases too, set *POSITION to the position where the `display' property ends. + If IT is NULL, only examine the property specification in SPEC, but + don't set up IT. In that case, FRAME_WINDOW_P non-zero means SPEC + is intended to be displayed in a window on a GUI frame. + Value is non-zero if something was found which replaces the display of buffer or string text. */ static int handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, Lisp_Object overlay, struct text_pos *position, - int display_replaced_before_p) + EMACS_INT bufpos, int display_replaced_p, + int frame_window_p) { Lisp_Object form; Lisp_Object location, value; - struct text_pos start_pos, save_pos; + struct text_pos start_pos = *position; int valid_p; /* If SPEC is a list of the form `(when FORM . VALUE)', evaluate FORM. @@ -3903,11 +4019,12 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, buffer or string. Bind `position' to the position in the object where the property was found, and `buffer-position' to the current position in the buffer. */ + + if (NILP (object)) + XSETBUFFER (object, current_buffer); specbind (Qobject, object); specbind (Qposition, make_number (CHARPOS (*position))); - specbind (Qbuffer_position, - make_number (STRINGP (object) - ? IT_CHARPOS (*it) : CHARPOS (*position))); + specbind (Qbuffer_position, make_number (bufpos)); GCPRO1 (form); form = safe_eval (form); UNGCPRO; @@ -3922,63 +4039,66 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, && EQ (XCAR (spec), Qheight) && CONSP (XCDR (spec))) { - if (!FRAME_WINDOW_P (it->f)) - return 0; - - it->font_height = XCAR (XCDR (spec)); - if (!NILP (it->font_height)) + if (it) { - struct face *face = FACE_FROM_ID (it->f, it->face_id); - int new_height = -1; + if (!FRAME_WINDOW_P (it->f)) + return 0; - if (CONSP (it->font_height) - && (EQ (XCAR (it->font_height), Qplus) - || EQ (XCAR (it->font_height), Qminus)) - && CONSP (XCDR (it->font_height)) - && INTEGERP (XCAR (XCDR (it->font_height)))) + it->font_height = XCAR (XCDR (spec)); + if (!NILP (it->font_height)) { - /* `(+ N)' or `(- N)' where N is an integer. */ - int steps = XINT (XCAR (XCDR (it->font_height))); - if (EQ (XCAR (it->font_height), Qplus)) - steps = - steps; - it->face_id = smaller_face (it->f, it->face_id, steps); - } - else if (FUNCTIONP (it->font_height)) - { - /* Call function with current height as argument. - Value is the new height. */ - Lisp_Object height; - height = safe_call1 (it->font_height, - face->lface[LFACE_HEIGHT_INDEX]); - if (NUMBERP (height)) - new_height = XFLOATINT (height); - } - else if (NUMBERP (it->font_height)) - { - /* Value is a multiple of the canonical char height. */ - struct face *f; + struct face *face = FACE_FROM_ID (it->f, it->face_id); + int new_height = -1; + + if (CONSP (it->font_height) + && (EQ (XCAR (it->font_height), Qplus) + || EQ (XCAR (it->font_height), Qminus)) + && CONSP (XCDR (it->font_height)) + && INTEGERP (XCAR (XCDR (it->font_height)))) + { + /* `(+ N)' or `(- N)' where N is an integer. */ + int steps = XINT (XCAR (XCDR (it->font_height))); + if (EQ (XCAR (it->font_height), Qplus)) + steps = - steps; + it->face_id = smaller_face (it->f, it->face_id, steps); + } + else if (FUNCTIONP (it->font_height)) + { + /* Call function with current height as argument. + Value is the new height. */ + Lisp_Object height; + height = safe_call1 (it->font_height, + face->lface[LFACE_HEIGHT_INDEX]); + if (NUMBERP (height)) + new_height = XFLOATINT (height); + } + else if (NUMBERP (it->font_height)) + { + /* Value is a multiple of the canonical char height. */ + struct face *f; - f = FACE_FROM_ID (it->f, - lookup_basic_face (it->f, DEFAULT_FACE_ID)); - new_height = (XFLOATINT (it->font_height) - * XINT (f->lface[LFACE_HEIGHT_INDEX])); - } - else - { - /* Evaluate IT->font_height with `height' bound to the - current specified height to get the new height. */ - int count = SPECPDL_INDEX (); + f = FACE_FROM_ID (it->f, + lookup_basic_face (it->f, DEFAULT_FACE_ID)); + new_height = (XFLOATINT (it->font_height) + * XINT (f->lface[LFACE_HEIGHT_INDEX])); + } + else + { + /* Evaluate IT->font_height with `height' bound to the + current specified height to get the new height. */ + int count = SPECPDL_INDEX (); - specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]); - value = safe_eval (it->font_height); - unbind_to (count, Qnil); + specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]); + value = safe_eval (it->font_height); + unbind_to (count, Qnil); - if (NUMBERP (value)) - new_height = XFLOATINT (value); - } + if (NUMBERP (value)) + new_height = XFLOATINT (value); + } - if (new_height > 0) - it->face_id = face_with_height (it->f, it->face_id, new_height); + if (new_height > 0) + it->face_id = face_with_height (it->f, it->face_id, new_height); + } } return 0; @@ -3989,12 +4109,15 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, && EQ (XCAR (spec), Qspace_width) && CONSP (XCDR (spec))) { - if (!FRAME_WINDOW_P (it->f)) - return 0; + if (it) + { + if (!FRAME_WINDOW_P (it->f)) + return 0; - value = XCAR (XCDR (spec)); - if (NUMBERP (value) && XFLOATINT (value) > 0) - it->space_width = value; + value = XCAR (XCDR (spec)); + if (NUMBERP (value) && XFLOATINT (value) > 0) + it->space_width = value; + } return 0; } @@ -4005,20 +4128,23 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, { Lisp_Object tem; - if (!FRAME_WINDOW_P (it->f)) - return 0; - - if (tem = XCDR (spec), CONSP (tem)) + if (it) { - it->slice.x = XCAR (tem); - if (tem = XCDR (tem), CONSP (tem)) + if (!FRAME_WINDOW_P (it->f)) + return 0; + + if (tem = XCDR (spec), CONSP (tem)) { - it->slice.y = XCAR (tem); + it->slice.x = XCAR (tem); if (tem = XCDR (tem), CONSP (tem)) { - it->slice.width = XCAR (tem); + it->slice.y = XCAR (tem); if (tem = XCDR (tem), CONSP (tem)) - it->slice.height = XCAR (tem); + { + it->slice.width = XCAR (tem); + if (tem = XCDR (tem), CONSP (tem)) + it->slice.height = XCAR (tem); + } } } } @@ -4031,36 +4157,43 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, && EQ (XCAR (spec), Qraise) && CONSP (XCDR (spec))) { - if (!FRAME_WINDOW_P (it->f)) - return 0; + if (it) + { + if (!FRAME_WINDOW_P (it->f)) + return 0; #ifdef HAVE_WINDOW_SYSTEM - value = XCAR (XCDR (spec)); - if (NUMBERP (value)) - { - struct face *face = FACE_FROM_ID (it->f, it->face_id); - it->voffset = - (XFLOATINT (value) - * (FONT_HEIGHT (face->font))); - } + value = XCAR (XCDR (spec)); + if (NUMBERP (value)) + { + struct face *face = FACE_FROM_ID (it->f, it->face_id); + it->voffset = - (XFLOATINT (value) + * (FONT_HEIGHT (face->font))); + } #endif /* HAVE_WINDOW_SYSTEM */ + } return 0; } /* Don't handle the other kinds of display specifications inside a string that we got from a `display' property. */ - if (it->string_from_display_prop_p) + if (it && it->string_from_display_prop_p) return 0; /* Characters having this form of property are not displayed, so we have to find the end of the property. */ - start_pos = *position; - *position = display_prop_end (it, object, start_pos); + if (it) + { + start_pos = *position; + *position = display_prop_end (it, object, start_pos); + } value = Qnil; /* Stop the scan at that end position--we assume that all text properties change there. */ - it->stop_charpos = position->charpos; + if (it) + it->stop_charpos = position->charpos; /* Handle `(left-fringe BITMAP [FACE])' and `(right-fringe BITMAP [FACE])'. */ @@ -4069,12 +4202,16 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, || EQ (XCAR (spec), Qright_fringe)) && CONSP (XCDR (spec))) { - int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID); int fringe_bitmap; - if (!FRAME_WINDOW_P (it->f)) - /* If we return here, POSITION has been advanced - across the text with this property. */ + if (it) + { + if (!FRAME_WINDOW_P (it->f)) + /* If we return here, POSITION has been advanced + across the text with this property. */ + return 0; + } + else if (!frame_window_p) return 0; #ifdef HAVE_WINDOW_SYSTEM @@ -4085,46 +4222,47 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, across the text with this property. */ return 0; - if (CONSP (XCDR (XCDR (spec)))) + if (it) { - Lisp_Object face_name = XCAR (XCDR (XCDR (spec))); - int face_id2 = lookup_derived_face (it->f, face_name, - FRINGE_FACE_ID, 0); - if (face_id2 >= 0) - face_id = face_id2; - } + int face_id = lookup_basic_face (it->f, DEFAULT_FACE_ID);; - /* Save current settings of IT so that we can restore them - when we are finished with the glyph property value. */ + if (CONSP (XCDR (XCDR (spec)))) + { + Lisp_Object face_name = XCAR (XCDR (XCDR (spec))); + int face_id2 = lookup_derived_face (it->f, face_name, + FRINGE_FACE_ID, 0); + if (face_id2 >= 0) + face_id = face_id2; + } - save_pos = it->position; - it->position = *position; - push_it (it); - it->position = save_pos; + /* Save current settings of IT so that we can restore them + when we are finished with the glyph property value. */ + push_it (it, position); - it->area = TEXT_AREA; - it->what = IT_IMAGE; - it->image_id = -1; /* no image */ - it->position = start_pos; - it->object = NILP (object) ? it->w->buffer : object; - it->method = GET_FROM_IMAGE; - it->from_overlay = Qnil; - it->face_id = face_id; + it->area = TEXT_AREA; + it->what = IT_IMAGE; + it->image_id = -1; /* no image */ + it->position = start_pos; + it->object = NILP (object) ? it->w->buffer : object; + it->method = GET_FROM_IMAGE; + it->from_overlay = Qnil; + it->face_id = face_id; - /* Say that we haven't consumed the characters with - `display' property yet. The call to pop_it in - set_iterator_to_next will clean this up. */ - *position = start_pos; + /* Say that we haven't consumed the characters with + `display' property yet. The call to pop_it in + set_iterator_to_next will clean this up. */ + *position = start_pos; - if (EQ (XCAR (spec), Qleft_fringe)) - { - it->left_user_fringe_bitmap = fringe_bitmap; - it->left_user_fringe_face_id = face_id; - } - else - { - it->right_user_fringe_bitmap = fringe_bitmap; - it->right_user_fringe_face_id = face_id; + if (EQ (XCAR (spec), Qleft_fringe)) + { + it->left_user_fringe_bitmap = fringe_bitmap; + it->left_user_fringe_face_id = face_id; + } + else + { + it->right_user_fringe_bitmap = fringe_bitmap; + it->right_user_fringe_face_id = face_id; + } } #endif /* HAVE_WINDOW_SYSTEM */ return 1; @@ -4167,18 +4305,19 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, valid_p = (STRINGP (value) #ifdef HAVE_WINDOW_SYSTEM - || (FRAME_WINDOW_P (it->f) && valid_image_p (value)) + || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p) + && valid_image_p (value)) #endif /* not HAVE_WINDOW_SYSTEM */ || (CONSP (value) && EQ (XCAR (value), Qspace))); - if (valid_p && !display_replaced_before_p) + if (valid_p && !display_replaced_p) { + if (!it) + return 1; + /* Save current settings of IT so that we can restore them when we are finished with the glyph property value. */ - save_pos = it->position; - it->position = *position; - push_it (it); - it->position = save_pos; + push_it (it, position); it->from_overlay = overlay; if (NILP (location)) @@ -4235,83 +4374,31 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, return 0; } - -/* Check if SPEC is a display sub-property value whose text should be - treated as intangible. */ - -static int -single_display_spec_intangible_p (Lisp_Object prop) -{ - /* Skip over `when FORM'. */ - if (CONSP (prop) && EQ (XCAR (prop), Qwhen)) - { - prop = XCDR (prop); - if (!CONSP (prop)) - return 0; - prop = XCDR (prop); - } - - if (STRINGP (prop)) - return 1; - - if (!CONSP (prop)) - return 0; - - /* Skip over `margin LOCATION'. If LOCATION is in the margins, - we don't need to treat text as intangible. */ - if (EQ (XCAR (prop), Qmargin)) - { - prop = XCDR (prop); - if (!CONSP (prop)) - return 0; - - prop = XCDR (prop); - if (!CONSP (prop) - || EQ (XCAR (prop), Qleft_margin) - || EQ (XCAR (prop), Qright_margin)) - return 0; - } - - return (CONSP (prop) - && (EQ (XCAR (prop), Qimage) - || EQ (XCAR (prop), Qspace))); -} - - /* Check if PROP is a display property value whose text should be - treated as intangible. */ + treated as intangible. OVERLAY is the overlay from which PROP + came, or nil if it came from a text property. CHARPOS and BYTEPOS + specify the buffer position covered by PROP. */ int -display_prop_intangible_p (Lisp_Object prop) +display_prop_intangible_p (Lisp_Object prop, Lisp_Object overlay, + EMACS_INT charpos, EMACS_INT bytepos) { - if (CONSP (prop) - && CONSP (XCAR (prop)) - && !EQ (Qmargin, XCAR (XCAR (prop)))) - { - /* A list of sub-properties. */ - while (CONSP (prop)) - { - if (single_display_spec_intangible_p (XCAR (prop))) - return 1; - prop = XCDR (prop); - } - } - else if (VECTORP (prop)) - { - /* A vector of sub-properties. */ - int i; - for (i = 0; i < ASIZE (prop); ++i) - if (single_display_spec_intangible_p (AREF (prop, i))) - return 1; - } - else - return single_display_spec_intangible_p (prop); + int frame_window_p = FRAME_WINDOW_P (XFRAME (selected_frame)); + struct text_pos position; - return 0; + SET_TEXT_POS (position, charpos, bytepos); + return handle_display_spec (NULL, prop, Qnil, overlay, + &position, charpos, frame_window_p); } -/* Return 1 if PROP is a display sub-property value containing STRING. */ +/* Return 1 if PROP is a display sub-property value containing STRING. + + Implementation note: this and the following function are really + special cases of handle_display_spec and + handle_single_display_spec, and should ideally use the same code. + Until they do, these two pairs must be consistent and must be + modified in sync. */ static int single_display_spec_string_p (Lisp_Object prop, Lisp_Object string) @@ -4325,6 +4412,16 @@ single_display_spec_string_p (Lisp_Object prop, Lisp_Object string) prop = XCDR (prop); if (!CONSP (prop)) return 0; + /* Actually, the condition following `when' should be eval'ed, + like handle_single_display_spec does, and we should return + zero if it evaluates to nil. However, this function is + called only when the buffer was already displayed and some + glyph in the glyph matrix was found to come from a display + string. Therefore, the condition was already evaluated, and + the result was non-nil, otherwise the display string wouldn't + have been displayed and we would have never been called for + this property. Thus, we can skip the evaluation and assume + its result is non-nil. */ prop = XCDR (prop); } @@ -4341,7 +4438,7 @@ single_display_spec_string_p (Lisp_Object prop, Lisp_Object string) return 0; } - return CONSP (prop) && EQ (XCAR (prop), string); + return EQ (prop, string) || (CONSP (prop) && EQ (XCAR (prop), string)); } @@ -4351,8 +4448,8 @@ static int display_prop_string_p (Lisp_Object prop, Lisp_Object string) { if (CONSP (prop) - && CONSP (XCAR (prop)) - && !EQ (Qmargin, XCAR (XCAR (prop)))) + && !EQ (XCAR (prop), Qwhen) + && !(CONSP (XCAR (prop)) && EQ (Qmargin, XCAR (XCAR (prop))))) { /* A list of sub-properties. */ while (CONSP (prop)) @@ -4852,7 +4949,7 @@ get_overlay_strings_1 (struct it *it, EMACS_INT charpos, int compute_stop_p) /* When called from handle_stop, there might be an empty display string loaded. In that case, don't bother saving it. */ if (!STRINGP (it->string) || SCHARS (it->string)) - push_it (it); + push_it (it, NULL); /* Set up IT to deliver display elements from the first overlay string. */ @@ -4894,10 +4991,11 @@ get_overlay_strings (struct it *it, EMACS_INT charpos) /* Save current settings of IT on IT->stack. Called, for example, before setting up IT for an overlay string, to be able to restore IT's settings to what they were after the overlay string has been - processed. */ + processed. If POSITION is non-NULL, it is the position to save on + the stack instead of IT->position. */ static void -push_it (struct it *it) +push_it (struct it *it, struct text_pos *position) { struct iterator_stack_entry *p; @@ -4924,7 +5022,7 @@ push_it (struct it *it) p->u.stretch.object = it->object; break; } - p->position = it->position; + p->position = position ? *position : it->position; p->current = it->current; p->end_charpos = it->end_charpos; p->string_nchars = it->string_nchars; @@ -5382,6 +5480,7 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p) { it->bidi_it.first_elt = 1; it->bidi_it.paragraph_dir = NEUTRAL_DIR; + it->bidi_it.disp_pos = -1; } if (set_stop_p) @@ -5659,11 +5758,11 @@ get_next_display_element (struct it *it) /* Return the first character from the display table entry, if not empty. If empty, don't display the current character. */ - if (v->size) + if (v->header.size) { it->dpvec_char_len = it->len; it->dpvec = v->contents; - it->dpend = v->contents + v->size; + it->dpend = v->contents + v->header.size; it->current.dpvec_index = 0; it->dpvec_face_id = -1; it->saved_face_id = it->face_id; @@ -5890,11 +5989,23 @@ get_next_display_element (struct it *it) else { EMACS_INT pos = (it->s ? -1 - : STRINGP (it->string) ? IT_STRING_CHARPOS (*it) - : IT_CHARPOS (*it)); + : STRINGP (it->string) ? IT_STRING_CHARPOS (*it) + : IT_CHARPOS (*it)); + int c; - it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display, pos, - it->string); + if (it->what == IT_CHARACTER) + c = it->char_to_display; + else + { + struct composition *cmp = composition_table[it->cmp_it.id]; + int i; + + c = ' '; + for (i = 0; i < cmp->glyph_len; i++) + if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t') + break; + } + it->face_id = FACE_FOR_CHAR (it->f, face, c, pos, it->string); } } @@ -8737,7 +8848,7 @@ display_echo_area (struct window *w) window_height_changed_p = with_echo_area_buffer (w, display_last_displayed_message_p, display_echo_area_1, - (EMACS_INT) w, Qnil, 0, 0); + (intptr_t) w, Qnil, 0, 0); if (no_message_p) echo_area_buffer[i] = Qnil; @@ -8756,7 +8867,8 @@ display_echo_area (struct window *w) static int display_echo_area_1 (EMACS_INT a1, Lisp_Object a2, EMACS_INT a3, EMACS_INT a4) { - struct window *w = (struct window *) a1; + intptr_t i1 = a1; + struct window *w = (struct window *) i1; Lisp_Object window; struct text_pos start; int window_height_changed_p = 0; @@ -8798,7 +8910,8 @@ resize_echo_area_exactly (void) resize_exactly = Qnil; resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1, - (EMACS_INT) w, resize_exactly, 0, 0); + (intptr_t) w, resize_exactly, + 0, 0); if (resized_p) { ++windows_or_buffers_changed; @@ -8818,7 +8931,8 @@ resize_echo_area_exactly (void) static int resize_mini_window_1 (EMACS_INT a1, Lisp_Object exactly, EMACS_INT a3, EMACS_INT a4) { - return resize_mini_window ((struct window *) a1, !NILP (exactly)); + intptr_t i1 = a1; + return resize_mini_window ((struct window *) i1, !NILP (exactly)); } @@ -8984,7 +9098,7 @@ current_message (void) else { with_echo_area_buffer (0, 0, current_message_1, - (EMACS_INT) &msg, Qnil, 0, 0); + (intptr_t) &msg, Qnil, 0, 0); if (NILP (msg)) echo_area_buffer[0] = Qnil; } @@ -8996,7 +9110,8 @@ current_message (void) static int current_message_1 (EMACS_INT a1, Lisp_Object a2, EMACS_INT a3, EMACS_INT a4) { - Lisp_Object *msg = (Lisp_Object *) a1; + intptr_t i1 = a1; + Lisp_Object *msg = (Lisp_Object *) i1; if (Z > BEG) *msg = make_buffer_string (BEG, Z, 1); @@ -9127,7 +9242,7 @@ set_message (const char *s, Lisp_Object string, || (STRINGP (string) && STRING_MULTIBYTE (string))); with_echo_area_buffer (0, -1, set_message_1, - (EMACS_INT) s, string, nbytes, multibyte_p); + (intptr_t) s, string, nbytes, multibyte_p); message_buf_print = 0; help_echo_showing_p = 0; } @@ -9141,7 +9256,8 @@ set_message (const char *s, Lisp_Object string, static int set_message_1 (EMACS_INT a1, Lisp_Object a2, EMACS_INT nbytes, EMACS_INT multibyte_p) { - const char *s = (const char *) a1; + intptr_t i1 = a1; + const char *s = (const char *) i1; const unsigned char *msg = (const unsigned char *) s; Lisp_Object string = a2; @@ -11044,7 +11160,7 @@ debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9) buffer position, END is given as a distance from Z. Used in redisplay_internal for display optimization. */ -static INLINE int +static inline int text_outside_line_unchanged_p (struct window *w, EMACS_INT start, EMACS_INT end) { @@ -11305,7 +11421,7 @@ check_point_in_composition (struct buffer *prev_buf, EMACS_INT prev_pt, /* Reconsider the setting of B->clip_changed which is displayed in window W. */ -static INLINE void +static inline void reconsider_clip_changes (struct window *w, struct buffer *b) { if (b->clip_changed @@ -12671,11 +12787,30 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, GLYPH_BEFORE and GLYPH_AFTER, and it came from a string positioned between POS_BEFORE and POS_AFTER in the buffer. */ - struct glyph *stop = glyph_after; + struct glyph *start, *stop; EMACS_INT pos = pos_before; x = -1; - for (glyph = glyph_before + incr; + + /* GLYPH_BEFORE and GLYPH_AFTER are the glyphs that + correspond to POS_BEFORE and POS_AFTER, respectively. We + need START and STOP in the order that corresponds to the + row's direction as given by its reversed_p flag. If the + directionality of characters between POS_BEFORE and + POS_AFTER is the opposite of the row's base direction, + these characters will have been reordered for display, + and we need to reverse START and STOP. */ + if (!row->reversed_p) + { + start = min (glyph_before, glyph_after); + stop = max (glyph_before, glyph_after); + } + else + { + start = max (glyph_before, glyph_after); + stop = min (glyph_before, glyph_after); + } + for (glyph = start + incr; row->reversed_p ? glyph > stop : glyph < stop; ) { @@ -12866,7 +13001,7 @@ set_cursor_from_row (struct window *w, struct glyph_row *row, We assume that the window's buffer is really current. */ -static INLINE struct text_pos +static inline struct text_pos run_window_scroll_functions (Lisp_Object window, struct text_pos startp) { struct window *w = XWINDOW (window); @@ -14812,7 +14947,8 @@ try_window_reusing_current_matrix (struct window *w) row->visible_height -= min_y - row->y; if (row->y + row->height > max_y) row->visible_height -= row->y + row->height - max_y; - row->redraw_fringe_bitmaps_p = 1; + if (row->fringe_bitmap_periodic_p) + row->redraw_fringe_bitmaps_p = 1; it.current_y += row->height; @@ -14974,7 +15110,8 @@ try_window_reusing_current_matrix (struct window *w) row->visible_height -= min_y - row->y; if (row->y + row->height > max_y) row->visible_height -= row->y + row->height - max_y; - row->redraw_fringe_bitmaps_p = 1; + if (row->fringe_bitmap_periodic_p) + row->redraw_fringe_bitmaps_p = 1; } /* Scroll the current matrix. */ @@ -17092,7 +17229,7 @@ cursor_row_p (struct glyph_row *row) static int push_display_prop (struct it *it, Lisp_Object prop) { - push_it (it); + push_it (it, NULL); if (STRINGP (prop)) { @@ -18021,6 +18158,8 @@ See also `bidi-paragraph-direction'. */) bytepos--; itb.charpos = pos; itb.bytepos = bytepos; + itb.nchars = -1; + itb.frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ()); /* guesswork */ itb.first_elt = 1; itb.separator_limit = -1; itb.paragraph_dir = NEUTRAL_DIR; @@ -18124,7 +18263,7 @@ display_menu_bar (struct window *w) /* Display all items of the menu bar. */ items = FRAME_MENU_BAR_ITEMS (it.f); - for (i = 0; i < XVECTOR (items)->size; i += 4) + for (i = 0; i < ASIZE (items); i += 4) { Lisp_Object string; @@ -19562,7 +19701,7 @@ decode_mode_spec (struct window *w, register int c, int field_width, so get us a 2-digit number that is close. */ if (total == 100) total = 99; - sprintf (decode_mode_spec_buf, "%2ld%%", (long)total); + sprintf (decode_mode_spec_buf, "%2"pI"d%%", total); return decode_mode_spec_buf; } } @@ -19593,9 +19732,9 @@ decode_mode_spec (struct window *w, register int c, int field_width, if (total == 100) total = 99; if (toppos <= BUF_BEGV (b)) - sprintf (decode_mode_spec_buf, "Top%2ld%%", (long)total); + sprintf (decode_mode_spec_buf, "Top%2"pI"d%%", total); else - sprintf (decode_mode_spec_buf, "%2ld%%", (long)total); + sprintf (decode_mode_spec_buf, "%2"pI"d%%", total); return decode_mode_spec_buf; } } @@ -20398,7 +20537,7 @@ init_glyph_string (struct glyph_string *s, /* Append the list of glyph strings with head H and tail T to the list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */ -static INLINE void +static inline void append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail, struct glyph_string *h, struct glyph_string *t) { @@ -20418,7 +20557,7 @@ append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tai list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */ -static INLINE void +static inline void prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail, struct glyph_string *h, struct glyph_string *t) { @@ -20437,7 +20576,7 @@ prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **ta /* Append glyph string S to the list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the resulting list. */ -static INLINE void +static inline void append_glyph_string (struct glyph_string **head, struct glyph_string **tail, struct glyph_string *s) { @@ -20452,7 +20591,7 @@ append_glyph_string (struct glyph_string **head, struct glyph_string **tail, Value is a pointer to a realized face that is ready for display if DISPLAY_P is non-zero. */ -static INLINE struct face * +static inline struct face * get_char_face_and_encoding (struct frame *f, int c, int face_id, XChar2b *char2b, int display_p) { @@ -20485,7 +20624,7 @@ get_char_face_and_encoding (struct frame *f, int c, int face_id, The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is a pointer to a realized face that is ready for display. */ -static INLINE struct face * +static inline struct face * get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph, XChar2b *char2b, int *two_byte_p) { @@ -20522,7 +20661,7 @@ get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph, /* Get glyph code of character C in FONT in the two-byte form CHAR2B. Retunr 1 if FONT has a glyph for C, otherwise return 0. */ -static INLINE int +static inline int get_char_glyph_code (int c, struct font *font, XChar2b *char2b) { unsigned code; @@ -20986,7 +21125,7 @@ right_overwriting (struct glyph_string *s) first glyph following S. LAST_X is the right-most x-position + 1 in the drawing area. */ -static INLINE void +static inline void set_glyph_string_background_width (struct glyph_string *s, int start, int last_x) { /* If the face of this glyph string has to be drawn to the end of @@ -21548,7 +21687,7 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row, /* Store one glyph for IT->char_to_display in IT->glyph_row. Called from x_produce_glyphs when IT->glyph_row is non-null. */ -static INLINE void +static inline void append_glyph (struct it *it) { struct glyph *glyph; @@ -21622,7 +21761,7 @@ append_glyph (struct it *it) IT->glyph_row. Called from x_produce_glyphs when IT->glyph_row is non-null. */ -static INLINE void +static inline void append_composite_glyph (struct it *it) { struct glyph *glyph; @@ -21691,7 +21830,7 @@ append_composite_glyph (struct it *it) /* Change IT->ascent and IT->height according to the setting of IT->voffset. */ -static INLINE void +static inline void take_vertical_position_into_account (struct it *it) { if (it->voffset) @@ -24816,7 +24955,7 @@ on_hot_spot_p (Lisp_Object hot_spot, int x, int y) { struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot)); Lisp_Object *poly = v->contents; - int n = v->size; + int n = v->header.size; int i; int inside = 0; Lisp_Object lx, ly; @@ -26249,7 +26388,7 @@ x_intersect_rectangles (XRectangle *r1, XRectangle *r2, XRectangle *result) { result->x = right->x; - /* The right end of the intersection is the minimum of the + /* The right end of the intersection is the minimum of the right ends of left and right. */ result->width = (min (left->x + left->width, right->x + right->width) - result->x);