X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/1391cd548782097e34d7856ec4f20ca90bdf2c26..76b6f7075970e492eba3cf3f4411fcfc4ff3bdcd:/src/xdisp.c diff --git a/src/xdisp.c b/src/xdisp.c index d6a96c4a72..cea8616f5f 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -1,7 +1,7 @@ /* Display generation from window structure and buffer text. Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -167,6 +167,7 @@ along with GNU Emacs. If not, see . */ #include #include +#include #include "lisp.h" #include "keyboard.h" @@ -187,6 +188,7 @@ along with GNU Emacs. If not, see . */ #include "coding.h" #include "process.h" #include "region-cache.h" +#include "font.h" #include "fontset.h" #include "blockinput.h" @@ -196,8 +198,11 @@ along with GNU Emacs. If not, see . */ #ifdef WINDOWSNT #include "w32term.h" #endif -#ifdef MAC_OS -#include "macterm.h" +#ifdef HAVE_NS +#include "nsterm.h" +#endif +#ifdef USE_GTK +#include "gtkutil.h" #endif #include "font.h" @@ -208,8 +213,8 @@ along with GNU Emacs. If not, see . */ #define INFINITY 10000000 -#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ - || defined (USE_GTK) +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \ + || defined(HAVE_NS) || defined (USE_GTK) extern void set_frame_menubar P_ ((struct frame *f, int, int)); extern int pending_menu_activation; #endif @@ -763,7 +768,6 @@ static enum prop_handled handle_display_prop P_ ((struct it *)); static enum prop_handled handle_composition_prop P_ ((struct it *)); static enum prop_handled handle_overlay_change P_ ((struct it *)); static enum prop_handled handle_fontified_prop P_ ((struct it *)); -static enum prop_handled handle_auto_composed_prop P_ ((struct it *)); /* Properties handled by iterators. */ @@ -775,7 +779,6 @@ static struct props it_props[] = {&Qface, FACE_PROP_IDX, handle_face_prop}, {&Qdisplay, DISPLAY_PROP_IDX, handle_display_prop}, {&Qinvisible, INVISIBLE_PROP_IDX, handle_invisible_prop}, - {&Qauto_composed, AUTO_COMPOSED_PROP_IDX, handle_auto_composed_prop}, {&Qcomposition, COMPOSITION_PROP_IDX, handle_composition_prop}, {NULL, 0, NULL} }; @@ -861,7 +864,7 @@ int display_hourglass_p; int hourglass_shown_p; /* If non-null, an asynchronous timer that, when it expires, displays - an hourglass cursor on all frames. */ + an hourglass cursor on all frames. */ struct atimer *hourglass_atimer; /* Number of seconds to wait before displaying an hourglass cursor. */ @@ -886,10 +889,6 @@ static Lisp_Object get_it_property P_ ((struct it *it, Lisp_Object prop)); static void handle_line_prefix P_ ((struct it *)); -#if 0 -static int invisible_text_between_p P_ ((struct it *, int, int)); -#endif - static void pint2str P_ ((char *, int, int)); static void pint2hrstr P_ ((char *, int, int)); static struct text_pos run_window_scroll_functions P_ ((Lisp_Object, @@ -1324,7 +1323,7 @@ pos_visible_p (w, charpos, x, y, rtop, rbot, rowh, vpos) int visible_p = 0; struct buffer *old_buffer = NULL; - if (noninteractive) + if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w)))) return visible_p; if (XBUFFER (w->buffer) != current_buffer) @@ -1757,9 +1756,7 @@ glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y) text, or we can't tell because W's current matrix is not up to date. */ -#ifndef HAVE_CARBON static -#endif struct glyph * x_y_to_hpos_vpos (w, x, y, hpos, vpos, dx, dy, area) struct window *w; @@ -2096,7 +2093,7 @@ get_phys_cursor_geometry (w, row, glyph, xp, yp, heightp) rectangle as wide as the glyph, but use a canonical character width instead. */ wd = glyph->pixel_width - 1; -#ifdef HAVE_NTGUI +#if defined(HAVE_NTGUI) || defined(HAVE_NS) wd++; /* Why? */ #endif @@ -2576,6 +2573,8 @@ init_iterator (it, w, charpos, bytepos, row, base_face_id) it->w = w; it->f = XFRAME (w->frame); + it->cmp_it.id = -1; + /* Extra space between lines (on window systems only). */ if (base_face_id == DEFAULT_FACE_ID && FRAME_WINDOW_P (it->f)) @@ -3000,25 +2999,6 @@ init_from_display_pos (it, w, pos) it->method = GET_FROM_STRING; } -#if 0 /* This is bogus because POS not having an overlay string - position does not mean it's after the string. Example: A - line starting with a before-string and initialization of IT - to the previous row's end position. */ - else if (it->current.overlay_string_index >= 0) - { - /* If POS says we're already after an overlay string ending at - POS, make sure to pop the iterator because it will be in - front of that overlay string. When POS is ZV, we've thereby - also ``processed'' overlay strings at ZV. */ - while (it->sp) - pop_it (it); - xassert (it->current.overlay_string_index == -1); - xassert (it->method == GET_FROM_BUFFER); - if (CHARPOS (pos->pos) == ZV) - it->overlay_strings_at_end_processed_p = 1; - } -#endif /* 0 */ - if (CHARPOS (pos->string_pos) >= 0) { /* Recorded position is not in an overlay string, but in another @@ -3107,6 +3087,7 @@ handle_stop (it) it->current.dpvec_index = -1; handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p; it->ignore_overlay_strings_at_pos_p = 0; + it->ellipsis_p = 0; /* Use face of preceding text for ellipsis (if invisible) */ if (it->selective_display_ellipsis_p) @@ -3127,13 +3108,29 @@ handle_stop (it) { /* We still want to show before and after strings from overlays even if the actual buffer text is replaced. */ - if (!handle_overlay_change_p || it->sp > 1) - return; - if (!get_overlay_strings_1 (it, 0, 0)) - return; - it->ignore_overlay_strings_at_pos_p = 1; - it->string_from_display_prop_p = 0; - handle_overlay_change_p = 0; + if (!handle_overlay_change_p + || it->sp > 1 + || !get_overlay_strings_1 (it, 0, 0)) + { + if (it->ellipsis_p) + setup_for_ellipsis (it, 0); + /* When handling a display spec, we might load an + empty string. In that case, discard it here. We + used to discard it in handle_single_display_spec, + but that causes get_overlay_strings_1, above, to + ignore overlay strings that we must check. */ + if (STRINGP (it->string) && !SCHARS (it->string)) + pop_it (it); + return; + } + else if (STRINGP (it->string) && !SCHARS (it->string)) + pop_it (it); + else + { + it->ignore_overlay_strings_at_pos_p = 1; + it->string_from_display_prop_p = 0; + handle_overlay_change_p = 0; + } handled = HANDLED_RECOMPUTE_PROPS; break; } @@ -3154,6 +3151,12 @@ handle_stop (it) if (handle_overlay_change_p) handled = handle_overlay_change (it); } + + if (it->ellipsis_p) + { + setup_for_ellipsis (it, 0); + break; + } } while (handled == HANDLED_RECOMPUTE_PROPS); @@ -3172,6 +3175,7 @@ compute_stop_pos (it) { register INTERVAL iv, next_iv; Lisp_Object object, limit, position; + EMACS_INT charpos, bytepos; /* If nowhere else, stop at the end. */ it->stop_charpos = it->end_charpos; @@ -3182,19 +3186,22 @@ compute_stop_pos (it) properties. */ object = it->string; limit = Qnil; - position = make_number (IT_STRING_CHARPOS (*it)); + charpos = IT_STRING_CHARPOS (*it); + bytepos = IT_STRING_BYTEPOS (*it); } else { - int charpos; + EMACS_INT pos; /* If next overlay change is in front of the current stop pos (which is IT->end_charpos), stop there. Note: value of next_overlay_change is point-max if no overlay change follows. */ - charpos = next_overlay_change (IT_CHARPOS (*it)); - if (charpos < it->stop_charpos) - it->stop_charpos = charpos; + charpos = IT_CHARPOS (*it); + bytepos = IT_BYTEPOS (*it); + pos = next_overlay_change (charpos); + if (pos < it->stop_charpos) + it->stop_charpos = pos; /* If showing the region, we have to stop at the region start or end because the face might change there. */ @@ -3210,12 +3217,11 @@ compute_stop_pos (it) property changes. */ XSETBUFFER (object, current_buffer); limit = make_number (IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT); - position = make_number (IT_CHARPOS (*it)); - } /* Get the interval containing IT's position. Value is a null interval if there isn't such an interval. */ + position = make_number (charpos); iv = validate_interval_range (object, &position, &position, 0); if (!NULL_INTERVAL_P (iv)) { @@ -3259,6 +3265,9 @@ compute_stop_pos (it) } } + composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, + it->stop_charpos, it->string); + xassert (STRINGP (it->string) || (it->stop_charpos >= BEGV && it->stop_charpos >= IT_CHARPOS (*it))); @@ -3591,7 +3600,8 @@ face_before_or_after_it_pos (it, before_p) /* For composition, we must check the character after the composition. */ pos = (it->what == IT_COMPOSITION - ? string_pos (IT_STRING_CHARPOS (*it) + it->cmp_len, it->string) + ? string_pos (IT_STRING_CHARPOS (*it) + + it->cmp_it.nchars, it->string) : string_pos (IT_STRING_CHARPOS (*it) + 1, it->string)); if (it->current.overlay_string_index >= 0) @@ -3641,7 +3651,7 @@ face_before_or_after_it_pos (it, before_p) if (it->what == IT_COMPOSITION) /* For composition, we must check the position after the composition. */ - pos.charpos += it->cmp_len, pos.bytepos += it->len; + pos.charpos += it->cmp_it.nchars, pos.bytepos += it->len; else INC_TEXT_POS (pos, it->multibyte_p); } @@ -3837,7 +3847,7 @@ handle_invisible_prop (it) it->position.charpos = IT_CHARPOS (*it) - 1; it->position.bytepos = CHAR_TO_BYTE (it->position.charpos); } - setup_for_ellipsis (it, 0); + it->ellipsis_p = 1; /* Let the ellipsis display before considering any properties of the following char. Fixes jasonr@gnu.org 01 Oct 07 bug. */ @@ -3985,11 +3995,8 @@ handle_display_prop (it) } else { - int ret = handle_single_display_spec (it, prop, object, overlay, - position, 0); - if (ret < 0) /* Replaced by "", i.e. nothing. */ - return HANDLED_RECOMPUTE_PROPS; - if (ret) + if (handle_single_display_spec (it, prop, object, overlay, + position, 0)) display_replaced_p = 1; } @@ -4036,8 +4043,7 @@ display_prop_end (it, object, start_pos) property ends. Value is non-zero if something was found which replaces the display - of buffer or string text. Specifically, the value is -1 if that - "something" is "nothing". */ + of buffer or string text. */ static int handle_single_display_spec (it, spec, object, overlay, position, @@ -4362,11 +4368,6 @@ handle_single_display_spec (it, spec, object, overlay, position, if (STRINGP (value)) { - if (SCHARS (value) == 0) - { - pop_it (it); - return -1; /* Replaced by "", i.e. nothing. */ - } it->string = value; it->multibyte_p = STRING_MULTIBYTE (it->string); it->current.overlay_string_index = -1; @@ -4615,97 +4616,6 @@ string_buffer_position (w, string, around_charpos) `composition' property ***********************************************************************/ -static enum prop_handled -handle_auto_composed_prop (it) - struct it *it; -{ - enum prop_handled handled = HANDLED_NORMALLY; - - if (FUNCTIONP (Vauto_composition_function)) - { - Lisp_Object val = Qnil; - EMACS_INT pos, limit = -1; - - if (STRINGP (it->string)) - pos = IT_STRING_CHARPOS (*it); - else - pos = IT_CHARPOS (*it); - - val = Fget_text_property (make_number (pos), Qauto_composed, it->string); - if (! NILP (val)) - { - Lisp_Object cmp_prop; - EMACS_INT cmp_start, cmp_end; - - if (get_property_and_range (pos, Qcomposition, &cmp_prop, - &cmp_start, &cmp_end, it->string) - && cmp_start == pos - && COMPOSITION_METHOD (cmp_prop) == COMPOSITION_WITH_GLYPH_STRING) - { - Lisp_Object gstring = COMPOSITION_COMPONENTS (cmp_prop); - Lisp_Object font_object = LGSTRING_FONT (gstring); - - if (! EQ (font_object, - font_at (-1, pos, FACE_FROM_ID (it->f, it->face_id), - it->w, it->string))) - /* We must re-compute the composition for the - different font. */ - val = Qnil; - } - - if (! NILP (val)) - { - Lisp_Object end; - - /* As Fnext_single_char_property_change is very slow, we - limit the search to the current line. */ - if (STRINGP (it->string)) - limit = SCHARS (it->string); - else - limit = find_next_newline_no_quit (pos, 1); - end = Fnext_single_char_property_change (make_number (pos), - Qauto_composed, - it->string, - make_number (limit)); - - if (XINT (end) < limit) - /* The current point is auto-composed, but there exist - characters not yet composed beyond the - auto-composed region. There's a possiblity that - the last characters in the region may be newly - composed. */ - val = Qnil; - } - } - if (NILP (val) && ! STRINGP (it->string)) - { - if (limit < 0) - limit = (STRINGP (it->string) ? SCHARS (it->string) - : find_next_newline_no_quit (pos, 1)); - if (pos < limit) - { - int count = SPECPDL_INDEX (); - Lisp_Object args[5]; - - if (FRAME_WINDOW_P (it->f)) - limit = font_range (pos, limit, - FACE_FROM_ID (it->f, it->face_id), - it->f, it->string); - args[0] = Vauto_composition_function; - specbind (Qauto_composition_function, Qnil); - args[1] = make_number (pos); - args[2] = make_number (limit); - args[3] = it->window; - args[4] = it->string; - safe_call (5, args); - unbind_to (count, Qnil); - } - } - } - - return handled; -} - /* Set up iterator IT from `composition' property at its current position. Called from handle_stop. */ @@ -4715,7 +4625,6 @@ handle_composition_prop (it) { Lisp_Object prop, string; EMACS_INT pos, pos_byte, start, end; - enum prop_handled handled = HANDLED_NORMALLY; if (STRINGP (it->string)) { @@ -4742,8 +4651,6 @@ handle_composition_prop (it) && COMPOSITION_VALID_P (start, end, prop) && (STRINGP (it->string) || (PT <= start || PT >= end))) { - int id; - if (start != pos) { if (STRINGP (it->string)) @@ -4751,63 +4658,18 @@ handle_composition_prop (it) else pos_byte = CHAR_TO_BYTE (start); } - id = get_composition_id (start, pos_byte, end - start, prop, string); + it->cmp_it.id = get_composition_id (start, pos_byte, end - start, + prop, string); - if (id >= 0) + if (it->cmp_it.id >= 0) { - struct composition *cmp = composition_table[id]; - - if (cmp->glyph_len == 0) - { - /* No glyph. */ - if (STRINGP (it->string)) - { - IT_STRING_CHARPOS (*it) = end; - IT_STRING_BYTEPOS (*it) = string_char_to_byte (it->string, - end); - } - else - { - IT_CHARPOS (*it) = end; - IT_BYTEPOS (*it) = CHAR_TO_BYTE (end); - } - return HANDLED_RECOMPUTE_PROPS; - } - - it->stop_charpos = end; - push_it (it); - - it->method = GET_FROM_COMPOSITION; - it->cmp_id = id; - it->cmp_len = COMPOSITION_LENGTH (prop); - /* For a terminal, draw only the first (non-TAB) character - of the components. */ - if (composition_table[id]->method == COMPOSITION_WITH_GLYPH_STRING) - { - /* FIXME: This doesn't do anything!?! */ - Lisp_Object lgstring = AREF (XHASH_TABLE (composition_hash_table) - ->key_and_value, - cmp->hash_index * 2); - } - else - { - int i; - - for (i = 0; i < cmp->glyph_len; i++) - if ((it->c = COMPOSITION_GLYPH (composition_table[id], i)) - != '\t') - break; - } - if (it->c == '\t') - it->c = ' '; - it->len = (STRINGP (it->string) - ? string_char_to_byte (it->string, end) - : CHAR_TO_BYTE (end)) - pos_byte; - handled = HANDLED_RETURN; + it->cmp_it.ch = -1; + it->cmp_it.nchars = COMPOSITION_LENGTH (prop); + it->cmp_it.nglyphs = -1; } } - return handled; + return HANDLED_NORMALLY; } @@ -4859,11 +4721,10 @@ next_overlay_string (it) /* No more overlay strings. Restore IT's settings to what they were before overlay strings were processed, and continue to deliver from current_buffer. */ - int display_ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p; + it->ellipsis_p = (it->stack[it->sp - 1].display_ellipsis_p != 0); pop_it (it); xassert (it->sp > 0 - || it->method == GET_FROM_COMPOSITION || (NILP (it->string) && it->method == GET_FROM_BUFFER && it->stop_charpos >= BEGV @@ -4876,11 +4737,6 @@ next_overlay_string (it) next_element_from_buffer doesn't try it again. */ if (NILP (it->string) && IT_CHARPOS (*it) >= it->end_charpos) it->overlay_strings_at_end_processed_p = 1; - - /* If we have to display `...' for invisible text, set - the iterator up for that. */ - if (display_ellipsis_p) - setup_for_ellipsis (it, 0); } else { @@ -4900,6 +4756,8 @@ next_overlay_string (it) SET_TEXT_POS (it->current.string_pos, 0, 0); it->method = GET_FROM_STRING; it->stop_charpos = 0; + if (it->cmp_it.stop_pos >= 0) + it->cmp_it.stop_pos = 0; } CHECK_IT (it); @@ -5158,7 +5016,11 @@ get_overlay_strings_1 (it, charpos, compute_stop_p) /* Save IT's settings. They are restored after all overlay strings have been processed. */ xassert (!compute_stop_p || it->sp == 0); - push_it (it); + + /* 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); /* Set up IT to deliver display elements from the first overlay string. */ @@ -5214,6 +5076,7 @@ push_it (it) p = it->stack + it->sp; p->stop_charpos = it->stop_charpos; + p->cmp_it = it->cmp_it; xassert (it->face_id >= 0); p->face_id = it->face_id; p->string = it->string; @@ -5226,13 +5089,6 @@ push_it (it) p->u.image.image_id = it->image_id; p->u.image.slice = it->slice; break; - case GET_FROM_COMPOSITION: - p->u.comp.object = it->object; - p->u.comp.c = it->c; - p->u.comp.len = it->len; - p->u.comp.cmp_id = it->cmp_id; - p->u.comp.cmp_len = it->cmp_len; - break; case GET_FROM_STRETCH: p->u.stretch.object = it->object; break; @@ -5269,6 +5125,7 @@ pop_it (it) --it->sp; p = it->stack + it->sp; it->stop_charpos = p->stop_charpos; + it->cmp_it = p->cmp_it; it->face_id = p->face_id; it->current = p->current; it->position = p->position; @@ -5284,13 +5141,6 @@ pop_it (it) it->object = p->u.image.object; it->slice = p->u.image.slice; break; - case GET_FROM_COMPOSITION: - it->object = p->u.comp.object; - it->c = p->u.comp.c; - it->len = p->u.comp.len; - it->cmp_id = p->u.comp.cmp_id; - it->cmp_len = p->u.comp.cmp_len; - break; case GET_FROM_STRETCH: it->object = p->u.comp.object; break; @@ -5750,7 +5600,6 @@ static int (* get_next_element[NUM_IT_METHODS]) P_ ((struct it *it)) = { next_element_from_buffer, next_element_from_display_vector, - next_element_from_composition, next_element_from_string, next_element_from_c_string, next_element_from_image, @@ -5759,6 +5608,19 @@ static int (* get_next_element[NUM_IT_METHODS]) P_ ((struct it *it)) = #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it) + +/* Return 1 iff a character at CHARPOS (and BYTEPOS) is composed + (possibly with the following characters). */ + +#define CHAR_COMPOSED_P(IT,CHARPOS,BYTEPOS) \ + ((IT)->cmp_it.id >= 0 \ + || ((IT)->cmp_it.stop_pos == (CHARPOS) \ + && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \ + (IT)->end_charpos, (IT)->w, \ + FACE_FROM_ID ((IT)->f, (IT)->face_id), \ + (IT)->string))) + + /* Load IT's display element fields with information about the next display element from the current position of IT. Value is zero if end of buffer (or C string) is reached. */ @@ -6033,6 +5895,7 @@ get_next_display_element (it) } } +#ifdef HAVE_WINDOW_SYSTEM /* Adjust face id for a multibyte character. There are no multibyte character in unibyte text. */ if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION) @@ -6041,26 +5904,75 @@ get_next_display_element (it) && FRAME_WINDOW_P (it->f)) { struct face *face = FACE_FROM_ID (it->f, it->face_id); - int pos = (it->s ? -1 - : STRINGP (it->string) ? IT_STRING_CHARPOS (*it) - : IT_CHARPOS (*it)); - it->face_id = FACE_FOR_CHAR (it->f, face, it->c, pos, it->string); + if (it->what == IT_COMPOSITION && it->cmp_it.ch >= 0) + { + /* Automatic composition with glyph-string. */ + Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id); + + it->face_id = face_for_font (it->f, LGSTRING_FONT (gstring), face); + } + else + { + int pos = (it->s ? -1 + : STRINGP (it->string) ? IT_STRING_CHARPOS (*it) + : IT_CHARPOS (*it)); + + it->face_id = FACE_FOR_CHAR (it->f, face, it->c, pos, it->string); + } } +#endif /* Is this character the last one of a run of characters with box? If yes, set IT->end_of_box_run_p to 1. */ if (it->face_box_p && it->s == NULL) { - int face_id; - struct face *face; + if (it->method == GET_FROM_STRING && it->sp) + { + int face_id = underlying_face_id (it); + struct face *face = FACE_FROM_ID (it->f, face_id); - it->end_of_box_run_p - = ((face_id = face_after_it_pos (it), - face_id != it->face_id) - && (face = FACE_FROM_ID (it->f, face_id), - face->box == FACE_NO_BOX)); + if (face) + { + if (face->box == FACE_NO_BOX) + { + /* If the box comes from face properties in a + display string, check faces in that string. */ + int string_face_id = face_after_it_pos (it); + it->end_of_box_run_p + = (FACE_FROM_ID (it->f, string_face_id)->box + == FACE_NO_BOX); + } + /* Otherwise, the box comes from the underlying face. + If this is the last string character displayed, check + the next buffer location. */ + else if ((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1) + && (it->current.overlay_string_index + == it->n_overlay_strings - 1)) + { + EMACS_INT ignore; + int next_face_id; + struct text_pos pos = it->current.pos; + INC_TEXT_POS (pos, it->multibyte_p); + + next_face_id = face_at_buffer_position + (it->w, CHARPOS (pos), it->region_beg_charpos, + it->region_end_charpos, &ignore, + (IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT), 0); + it->end_of_box_run_p + = (FACE_FROM_ID (it->f, next_face_id)->box + == FACE_NO_BOX); + } + } + } + else + { + int face_id = face_after_it_pos (it); + it->end_of_box_run_p + = (face_id != it->face_id + && FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX); + } } /* Value is 0 if end of buffer or string reached. */ @@ -6101,6 +6013,20 @@ set_iterator_to_next (it, reseat_p) invisible lines that are so because of selective display. */ if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p) reseat_at_next_visible_line_start (it, 0); + else if (it->cmp_it.id >= 0) + { + IT_CHARPOS (*it) += it->cmp_it.nchars; + IT_BYTEPOS (*it) += it->cmp_it.nbytes; + if (it->cmp_it.to < it->cmp_it.nglyphs) + it->cmp_it.from = it->cmp_it.to; + else + { + it->cmp_it.id = -1; + composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it), + IT_BYTEPOS (*it), it->stop_charpos, + Qnil); + } + } else { xassert (it->len != 0); @@ -6110,23 +6036,6 @@ set_iterator_to_next (it, reseat_p) } break; - case GET_FROM_COMPOSITION: - xassert (it->cmp_id >= 0 && it->cmp_id < n_compositions); - xassert (it->sp > 0); - pop_it (it); - if (it->method == GET_FROM_STRING) - { - IT_STRING_BYTEPOS (*it) += it->len; - IT_STRING_CHARPOS (*it) += it->cmp_len; - goto consider_string_end; - } - else if (it->method == GET_FROM_BUFFER) - { - IT_BYTEPOS (*it) += it->len; - IT_CHARPOS (*it) += it->cmp_len; - } - break; - case GET_FROM_C_STRING: /* Current display element of IT is from a C string. */ IT_BYTEPOS (*it) += it->len; @@ -6182,8 +6091,26 @@ set_iterator_to_next (it, reseat_p) case GET_FROM_STRING: /* Current display element is a character from a Lisp string. */ xassert (it->s == NULL && STRINGP (it->string)); - IT_STRING_BYTEPOS (*it) += it->len; - IT_STRING_CHARPOS (*it) += 1; + if (it->cmp_it.id >= 0) + { + IT_STRING_CHARPOS (*it) += it->cmp_it.nchars; + IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes; + if (it->cmp_it.to < it->cmp_it.nglyphs) + it->cmp_it.from = it->cmp_it.to; + else + { + it->cmp_it.id = -1; + composition_compute_stop_pos (&it->cmp_it, + IT_STRING_CHARPOS (*it), + IT_STRING_BYTEPOS (*it), + it->stop_charpos, it->string); + } + } + else + { + IT_STRING_BYTEPOS (*it) += it->len; + IT_STRING_CHARPOS (*it) += 1; + } consider_string_end: @@ -6192,7 +6119,12 @@ set_iterator_to_next (it, reseat_p) /* IT->string is an overlay string. Advance to the next, if there is one. */ if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)) - next_overlay_string (it); + { + it->ellipsis_p = 0; + next_overlay_string (it); + if (it->ellipsis_p) + setup_for_ellipsis (it, 0); + } } else { @@ -6321,6 +6253,12 @@ next_element_from_string (it) it->what = IT_EOB; return 0; } + else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it), + IT_STRING_BYTEPOS (*it)) + && next_element_from_composition (it)) + { + return 1; + } else if (STRING_MULTIBYTE (it->string)) { int remaining = SBYTES (it->string) - IT_STRING_BYTEPOS (*it); @@ -6351,6 +6289,12 @@ next_element_from_string (it) it->c = ' ', it->len = 1; CHARPOS (position) = BYTEPOS (position) = -1; } + else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it), + IT_STRING_BYTEPOS (*it)) + && next_element_from_composition (it)) + { + return 1; + } else if (STRING_MULTIBYTE (it->string)) { int maxlen = SBYTES (it->string) - IT_STRING_BYTEPOS (*it); @@ -6488,10 +6432,7 @@ next_element_from_buffer (it) { int success_p = 1; - /* Check this assumption, otherwise, we would never enter the - if-statement, below. */ - xassert (IT_CHARPOS (*it) >= BEGV - && IT_CHARPOS (*it) <= it->stop_charpos); + xassert (IT_CHARPOS (*it) >= BEGV); if (IT_CHARPOS (*it) >= it->stop_charpos) { @@ -6537,14 +6478,16 @@ next_element_from_buffer (it) && IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos) run_redisplay_end_trigger_hook (it); + if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it)) + && next_element_from_composition (it)) + { + return 1; + } + /* Get the next character, maybe multibyte. */ p = BYTE_POS_ADDR (IT_BYTEPOS (*it)); if (it->multibyte_p && !ASCII_BYTE_P (*p)) - { - int maxlen = ((IT_BYTEPOS (*it) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE) - - IT_BYTEPOS (*it)); - it->c = string_char_and_length (p, maxlen, &it->len); - } + it->c = STRING_CHAR_AND_LENGTH (p, 0, it->len); else it->c = *p, it->len = 1; @@ -6616,22 +6559,43 @@ run_redisplay_end_trigger_hook (it) } -/* Deliver a composition display element. The iterator IT is already - filled with composition information (done in - handle_composition_prop). Value is always 1. */ +/* Deliver a composition display element. Unlike the other + next_element_from_XXX, this function is not registered in the array + get_next_element[]. It is called from next_element_from_buffer and + next_element_from_string when necessary. */ static int next_element_from_composition (it) struct it *it; { it->what = IT_COMPOSITION; - it->position = (STRINGP (it->string) - ? it->current.string_pos - : it->current.pos); + it->len = it->cmp_it.nbytes; if (STRINGP (it->string)) - it->object = it->string; + { + if (it->c < 0) + { + IT_STRING_CHARPOS (*it) += it->cmp_it.nchars; + IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes; + return 0; + } + it->position = it->current.string_pos; + it->object = it->string; + it->c = composition_update_it (&it->cmp_it, IT_STRING_CHARPOS (*it), + IT_STRING_BYTEPOS (*it), it->string); + } else - it->object = it->w->buffer; + { + if (it->c < 0) + { + IT_CHARPOS (*it) += it->cmp_it.nchars; + IT_BYTEPOS (*it) += it->cmp_it.nbytes; + return 0; + } + it->position = it->current.pos; + it->object = it->w->buffer; + it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it), + IT_BYTEPOS (*it), Qnil); + } return 1; } @@ -7061,7 +7025,25 @@ move_it_in_display_line (struct it *it, EMACS_INT to_charpos, int to_x, enum move_operation_enum op) { - move_it_in_display_line_to (it, to_charpos, to_x, op); + if (it->line_wrap == WORD_WRAP + && (op & MOVE_TO_X)) + { + struct it save_it = *it; + int skip = move_it_in_display_line_to (it, to_charpos, to_x, op); + /* When word-wrap is on, TO_X may lie past the end + of a wrapped line. Then it->current is the + character on the next line, so backtrack to the + space before the wrap point. */ + if (skip == MOVE_LINE_CONTINUED) + { + int prev_x = max (it->current_x - 1, 0); + *it = save_it; + move_it_in_display_line_to + (it, -1, prev_x, MOVE_TO_X); + } + } + else + move_it_in_display_line_to (it, to_charpos, to_x, op); } @@ -7224,7 +7206,8 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op) break; } else if (BUFFERP (it->object) - && it->method == GET_FROM_BUFFER + && (it->method == GET_FROM_BUFFER + || it->method == GET_FROM_STRETCH) && IT_CHARPOS (*it) >= to_charpos) skip = MOVE_POS_MATCH_OR_ZV; else @@ -7257,8 +7240,19 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op) associated with the tab are displayed on the current line. Since it->current_x does not include these glyphs, we use it->last_visible_x instead. */ - it->continuation_lines_width += - (it->c == '\t') ? it->last_visible_x : it->current_x; + if (it->c == '\t') + { + it->continuation_lines_width += it->last_visible_x; + /* When moving by vpos, ensure that the iterator really + advances to the next line (bug#847, bug#969). Fixme: + do we need to do this in other circumstances? */ + if (it->current_x != it->last_visible_x + && (op & MOVE_TO_VPOS) + && !(op & (MOVE_TO_X | MOVE_TO_POS))) + set_iterator_to_next (it, 0); + } + else + it->continuation_lines_width += it->current_x; break; default: @@ -7277,6 +7271,30 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op) out: + /* On text terminals, we may stop at the end of a line in the middle + of a multi-character glyph. If the glyph itself is continued, + i.e. it is actually displayed on the next line, don't treat this + stopping point as valid; move to the next line instead (unless + that brings us offscreen). */ + if (!FRAME_WINDOW_P (it->f) + && op & MOVE_TO_POS + && IT_CHARPOS (*it) == to_charpos + && it->what == IT_CHARACTER + && it->nglyphs > 1 + && it->line_wrap == WINDOW_WRAP + && it->current_x == it->last_visible_x - 1 + && it->c != '\n' + && it->c != '\t' + && it->vpos < XFASTINT (it->w->window_end_vpos)) + { + it->continuation_lines_width += it->current_x; + it->current_x = it->hpos = it->max_ascent = it->max_descent = 0; + it->current_y += it->max_ascent + it->max_descent; + ++it->vpos; + last_height = it->max_ascent + it->max_descent; + last_max_ascent = it->max_ascent; + } + TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached)); } @@ -7459,41 +7477,6 @@ move_it_past_eol (it) } -#if 0 /* Currently not used. */ - -/* Return non-zero if some text between buffer positions START_CHARPOS - and END_CHARPOS is invisible. IT->window is the window for text - property lookup. */ - -static int -invisible_text_between_p (it, start_charpos, end_charpos) - struct it *it; - int start_charpos, end_charpos; -{ - Lisp_Object prop, limit; - int invisible_found_p; - - xassert (it != NULL && start_charpos <= end_charpos); - - /* Is text at START invisible? */ - prop = Fget_char_property (make_number (start_charpos), Qinvisible, - it->window); - if (TEXT_PROP_MEANS_INVISIBLE (prop)) - invisible_found_p = 1; - else - { - limit = Fnext_single_char_property_change (make_number (start_charpos), - Qinvisible, Qnil, - make_number (end_charpos)); - invisible_found_p = XFASTINT (limit) < end_charpos; - } - - return invisible_found_p; -} - -#endif /* 0 */ - - /* Move IT by a specified number DVPOS of screen lines down. DVPOS negative means move up. DVPOS == 0 means move to the start of the screen line. NEED_Y_P non-zero means calculate IT->current_y. If @@ -7909,7 +7892,7 @@ message2_nolog (m, nbytes, multibyte) struct frame *sf = SELECTED_FRAME (); message_enable_multibyte = multibyte; - if (noninteractive) + if (FRAME_INITIAL_P (sf)) { if (noninteractive_need_newline) putc ('\n', stderr); @@ -8008,7 +7991,7 @@ message3_nolog (m, nbytes, multibyte) struct frame *sf = SELECTED_FRAME (); message_enable_multibyte = multibyte; - if (noninteractive) + if (FRAME_INITIAL_P (sf)) { if (noninteractive_need_newline) putc ('\n', stderr); @@ -8106,7 +8089,7 @@ message_with_string (m, string, log) putc ('\n', stderr); noninteractive_need_newline = 0; fprintf (stderr, m, SDATA (string)); - if (cursor_in_echo_area == 0) + if (!cursor_in_echo_area) fprintf (stderr, "\n"); fflush (stderr); } @@ -8277,6 +8260,9 @@ ensure_echo_area_buffers () sprintf (name, " *Echo Area %d*", i); echo_buffer[i] = Fget_buffer_create (build_string (name)); XBUFFER (echo_buffer[i])->truncate_lines = Qnil; + /* to force word wrap in echo area - + it was decided to postpone this*/ + /* XBUFFER (echo_buffer[i])->word_wrap = Qt; */ for (j = 0; j < 2; ++j) if (EQ (old_buffer, echo_area_buffer[j])) @@ -9462,7 +9448,32 @@ x_consider_frame_title (frame) if (! STRINGP (f->name) || SBYTES (f->name) != len || bcmp (title, SDATA (f->name), len) != 0) - x_implicitly_set_name (f, make_string (title, len), Qnil); + { +#ifdef HAVE_NS + if (FRAME_NS_P (f)) + { + if (!MINI_WINDOW_P(XWINDOW(f->selected_window))) + { + if (EQ (fmt, Qt)) + ns_set_name_as_filename (f); + else + x_implicitly_set_name (f, make_string(title, len), + Qnil); + } + } + else +#endif + x_implicitly_set_name (f, make_string (title, len), Qnil); + } +#ifdef HAVE_NS + if (FRAME_NS_P (f)) + { + /* do this also for frames with explicit names */ + ns_implicitly_set_icon_type(f); + ns_set_doc_edited(f, Fbuffer_modified_p + (XWINDOW (f->selected_window)->buffer), Qnil); + } +#endif } } @@ -9547,7 +9558,8 @@ prepare_menu_bars () while (CONSP (functions)) { - call1 (XCAR (functions), frame); + if (!EQ (XCAR (functions), Qt)) + call1 (XCAR (functions), frame); functions = XCDR (functions); } UNGCPRO; @@ -9557,9 +9569,6 @@ prepare_menu_bars () menu_bar_hooks_run = update_menu_bar (f, 0, menu_bar_hooks_run); #ifdef HAVE_WINDOW_SYSTEM update_tool_bar (f, 0); -#ifdef MAC_OS - mac_update_title_bar (f, 0); -#endif #endif UNGCPRO; } @@ -9572,9 +9581,6 @@ prepare_menu_bars () update_menu_bar (sf, 1, 0); #ifdef HAVE_WINDOW_SYSTEM update_tool_bar (sf, 1); -#ifdef MAC_OS - mac_update_title_bar (sf, 1); -#endif #endif } @@ -9615,19 +9621,10 @@ update_menu_bar (f, save_match_data, hooks_run) window = FRAME_SELECTED_WINDOW (f); w = XWINDOW (window); -#if 0 /* The if statement below this if statement used to include the - condition !NILP (w->update_mode_line), rather than using - update_mode_lines directly, and this if statement may have - been added to make that condition work. Now the if - statement below matches its comment, this isn't needed. */ - if (update_mode_lines) - w->update_mode_line = Qt; -#endif - if (FRAME_WINDOW_P (f) ? -#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ - || defined (USE_GTK) +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \ + || defined (HAVE_NS) || defined (USE_GTK) FRAME_EXTERNAL_MENU_BAR (f) #else FRAME_MENU_BAR_LINES (f) > 0 @@ -9685,11 +9682,11 @@ update_menu_bar (f, save_match_data, hooks_run) FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f)); /* Redisplay the menu bar in case we changed it. */ -#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ - || defined (USE_GTK) +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \ + || defined (HAVE_NS) || defined (USE_GTK) if (FRAME_WINDOW_P (f)) - { -#ifdef MAC_OS + { +#if defined (HAVE_NS) /* All frames on Mac OS share the same menubar. So only the selected frame should be allowed to set it. */ if (f == SELECTED_FRAME ()) @@ -9700,11 +9697,11 @@ update_menu_bar (f, save_match_data, hooks_run) /* On a terminal screen, the menu bar is an ordinary screen line, and this makes it get updated. */ w->update_mode_line = Qt; -#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */ +#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || HAVE_NS || USE_GTK) */ /* In the non-toolkit version, the menu bar is an ordinary screen line, and this makes it get updated. */ w->update_mode_line = Qt; -#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */ +#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || HAVE_NS || USE_GTK) */ unbind_to (count, Qnil); set_buffer_internal_1 (prev); @@ -9805,6 +9802,14 @@ FRAME_PTR last_mouse_frame; int last_tool_bar_item; +static Lisp_Object +update_tool_bar_unwind (frame) + Lisp_Object frame; +{ + selected_frame = frame; + return Qnil; +} + /* Update the tool-bar item list for frame F. This has to be done before we start to fill in any display lines. Called from prepare_menu_bars. If SAVE_MATCH_DATA is non-zero, we must save @@ -9815,7 +9820,7 @@ update_tool_bar (f, save_match_data) struct frame *f; int save_match_data; { -#if defined (USE_GTK) || USE_MAC_TOOLBAR +#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR int do_update = FRAME_EXTERNAL_TOOL_BAR (f); #else int do_update = WINDOWP (f->tool_bar_window) @@ -9849,7 +9854,7 @@ update_tool_bar (f, save_match_data) { struct buffer *prev = current_buffer; int count = SPECPDL_INDEX (); - Lisp_Object new_tool_bar; + Lisp_Object frame, new_tool_bar; int new_n_tool_bar; struct gcpro gcpro1; @@ -9871,6 +9876,14 @@ update_tool_bar (f, save_match_data) GCPRO1 (new_tool_bar); + /* We must temporarily set the selected frame to this frame + before calling tool_bar_items, because the calculation of + the tool-bar keymap uses the selected frame (see + `tool-bar-make-keymap' in tool-bar.el). */ + record_unwind_protect (update_tool_bar_unwind, selected_frame); + XSETFRAME (frame, f); + selected_frame = frame; + /* Build desired tool-bar items from keymaps. */ new_tool_bar = tool_bar_items (Fcopy_sequence (f->tool_bar_items), &new_n_tool_bar); @@ -10281,7 +10294,7 @@ redisplay_tool_bar (f) struct it it; struct glyph_row *row; -#if defined (USE_GTK) || USE_MAC_TOOLBAR +#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR if (FRAME_EXTERNAL_TOOL_BAR (f)) update_frame_tool_bar (f); return 0; @@ -11288,7 +11301,7 @@ redisplay_internal (preserve_echo_area) /* No redisplay if running in batch mode or frame is not yet fully initialized, or redisplay is explicitly turned off by setting Vinhibit_redisplay. */ - if (noninteractive + if (FRAME_INITIAL_P (SELECTED_FRAME ()) || !NILP (Vinhibit_redisplay)) return; @@ -11311,7 +11324,7 @@ redisplay_internal (preserve_echo_area) return; } -#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (MAC_OS) +#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) if (popup_activated ()) return; #endif @@ -11367,7 +11380,7 @@ redisplay_internal (preserve_echo_area) if (face_change_count) ++windows_or_buffers_changed; - if (FRAME_TERMCAP_P (sf) + if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf)) && FRAME_TTY (sf)->previous_frame != sf) { /* Since frames on a single ASCII terminal share the same @@ -11375,7 +11388,7 @@ redisplay_internal (preserve_echo_area) the whole thing. */ windows_or_buffers_changed++; SET_FRAME_GARBAGED (sf); -#ifndef WINDOWSNT +#ifndef DOS_NT set_tty_color_mode (FRAME_TTY (sf), sf); #endif FRAME_TTY (sf)->previous_frame = sf; @@ -11501,6 +11514,10 @@ redisplay_internal (preserve_echo_area) /* Resized active mini-window to fit the size of what it is showing if its contents might have changed. */ must_finish = 1; +/* FIXME: this causes all frames to be updated, which seems unnecessary + since only the current frame needs to be considered. This function needs + to be rewritten with two variables, consider_all_windows and + consider_all_frames. */ consider_all_windows_p = 1; ++windows_or_buffers_changed; ++update_mode_lines; @@ -11810,11 +11827,6 @@ redisplay_internal (preserve_echo_area) /* Update the display. */ set_window_update_flags (XWINDOW (f->root_window), 1); pause |= update_frame (f, 0, 0); -#if 0 /* Exiting the loop can leave the wrong value for buffer_shared. */ - if (pause) - break; -#endif - f->updated_p = 1; } } @@ -12108,11 +12120,6 @@ mark_window_display_accurate_1 (w, accurate_p) if (accurate_p) { w->window_end_valid = w->buffer; -#if 0 /* This is incorrect with variable-height lines. */ - xassert (XINT (w->window_end_vpos) - < (WINDOW_TOTAL_LINES (w) - - (WINDOW_WANTS_MODELINE_P (w) ? 1 : 0))); -#endif w->update_mode_line = Qnil; } } @@ -12613,19 +12620,13 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, { struct window *w = XWINDOW (window); struct frame *f = XFRAME (w->frame); - struct text_pos scroll_margin_pos; - struct text_pos pos; - struct text_pos startp; + struct text_pos pos, startp; struct it it; - Lisp_Object window_end; - int this_scroll_margin; - int dy = 0; - int scroll_max; - int rc; - int amount_to_scroll = 0; - Lisp_Object aggressive; - int height; + int this_scroll_margin, scroll_max, rc, height; + int dy = 0, amount_to_scroll = 0, scroll_down_p = 0; int extra_scroll_margin_lines = last_line_misfit ? 1 : 0; + Lisp_Object aggressive; + int scroll_limit = INT_MAX / FRAME_LINE_HEIGHT (f); #if GLYPH_DEBUG debug_method_add (w, "try_scrolling"); @@ -12636,84 +12637,77 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, /* Compute scroll margin height in pixels. We scroll when point is within this distance from the top or bottom of the window. */ if (scroll_margin > 0) - { - this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4); - this_scroll_margin *= FRAME_LINE_HEIGHT (f); - } + this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4) + * FRAME_LINE_HEIGHT (f); else this_scroll_margin = 0; - /* Force scroll_conservatively to have a reasonable value so it doesn't - cause an overflow while computing how much to scroll. */ - if (scroll_conservatively) - scroll_conservatively = min (scroll_conservatively, - MOST_POSITIVE_FIXNUM / FRAME_LINE_HEIGHT (f)); - - /* Compute how much we should try to scroll maximally to bring point - into view. */ - if (scroll_step || scroll_conservatively || temp_scroll_step) - scroll_max = max (scroll_step, - max (scroll_conservatively, temp_scroll_step)); + /* Force scroll_conservatively to have a reasonable value, to avoid + overflow while computing how much to scroll. Note that the user + can supply scroll-conservatively equal to `most-positive-fixnum', + which can be larger than INT_MAX. */ + if (scroll_conservatively > scroll_limit) + { + scroll_conservatively = scroll_limit; + scroll_max = INT_MAX; + } + else if (scroll_step || scroll_conservatively || temp_scroll_step) + /* Compute how much we should try to scroll maximally to bring + point into view. */ + scroll_max = (max (scroll_step, + max (scroll_conservatively, temp_scroll_step)) + * FRAME_LINE_HEIGHT (f)); else if (NUMBERP (current_buffer->scroll_down_aggressively) || NUMBERP (current_buffer->scroll_up_aggressively)) - /* We're trying to scroll because of aggressive scrolling - but no scroll_step is set. Choose an arbitrary one. Maybe - there should be a variable for this. */ - scroll_max = 10; + /* We're trying to scroll because of aggressive scrolling but no + scroll_step is set. Choose an arbitrary one. */ + scroll_max = 10 * FRAME_LINE_HEIGHT (f); else scroll_max = 0; - scroll_max *= FRAME_LINE_HEIGHT (f); - - /* Decide whether we have to scroll down. Start at the window end - and move this_scroll_margin up to find the position of the scroll - margin. */ - window_end = Fwindow_end (window, Qt); too_near_end: - CHARPOS (scroll_margin_pos) = XINT (window_end); - BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos)); - - if (this_scroll_margin || extra_scroll_margin_lines) - { - start_display (&it, w, scroll_margin_pos); - if (this_scroll_margin) - move_it_vertically_backward (&it, this_scroll_margin); - if (extra_scroll_margin_lines) - move_it_by_lines (&it, - extra_scroll_margin_lines, 0); - scroll_margin_pos = it.current.pos; - } - - if (PT >= CHARPOS (scroll_margin_pos)) + /* Decide whether to scroll down. */ + if (PT > CHARPOS (startp)) { - int y0; + int scroll_margin_y; - /* Point is in the scroll margin at the bottom of the window, or - below. Compute a new window start that makes point visible. */ + /* Compute the pixel ypos of the scroll margin, then move it to + either that ypos or PT, whichever comes first. */ + start_display (&it, w, startp); + scroll_margin_y = it.last_visible_y - this_scroll_margin + - FRAME_LINE_HEIGHT (f) * extra_scroll_margin_lines; + move_it_to (&it, PT, -1, scroll_margin_y - 1, -1, + (MOVE_TO_POS | MOVE_TO_Y)); - /* Compute the distance from the scroll margin to PT. - Give up if the distance is greater than scroll_max. */ - start_display (&it, w, scroll_margin_pos); - y0 = it.current_y; - move_it_to (&it, PT, 0, it.last_visible_y, -1, - MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y); + if (PT > CHARPOS (it.current.pos)) + { + int y0 = line_bottom_y (&it); - /* To make point visible, we have to move the window start - down so that the line the cursor is in is visible, which - means we have to add in the height of the cursor line. */ - dy = line_bottom_y (&it) - y0; + /* Compute the distance from the scroll margin to PT + (including the height of the cursor line). Moving the + iterator unconditionally to PT can be slow if PT is far + away, so stop 10 lines past the window bottom (is there a + way to do the right thing quickly?). */ + move_it_to (&it, PT, -1, + it.last_visible_y + 10 * FRAME_LINE_HEIGHT (f), + -1, MOVE_TO_POS | MOVE_TO_Y); + dy = line_bottom_y (&it) - y0; - if (dy > scroll_max) - return SCROLLING_FAILED; + if (dy > scroll_max) + return SCROLLING_FAILED; - /* Move the window start down. If scrolling conservatively, - move it just enough down to make point visible. If - scroll_step is set, move it down by scroll_step. */ - start_display (&it, w, startp); + scroll_down_p = 1; + } + } + if (scroll_down_p) + { + /* Point is in or below the bottom scroll margin, so move the + window start down. If scrolling conservatively, move it just + enough down to make point visible. If scroll_step is set, + move it down by scroll_step. */ if (scroll_conservatively) - /* Set AMOUNT_TO_SCROLL to at least one line, - and at most scroll_conservatively lines. */ amount_to_scroll = min (max (dy, FRAME_LINE_HEIGHT (f)), FRAME_LINE_HEIGHT (f) * scroll_conservatively); @@ -12735,19 +12729,20 @@ try_scrolling (window, just_this_one_p, scroll_conservatively, if (amount_to_scroll <= 0) return SCROLLING_FAILED; - /* If moving by amount_to_scroll leaves STARTP unchanged, - move it down one screen line. */ - + start_display (&it, w, startp); move_it_vertically (&it, amount_to_scroll); + + /* If STARTP is unchanged, move it down another screen line. */ if (CHARPOS (it.current.pos) == CHARPOS (startp)) move_it_by_lines (&it, 1, 1); startp = it.current.pos; } else { + struct text_pos scroll_margin_pos = startp; + /* See if point is inside the scroll margin at the top of the window. */ - scroll_margin_pos = startp; if (this_scroll_margin) { start_display (&it, w, startp); @@ -12996,9 +12991,13 @@ try_cursor_movement (window, startp, scroll_step) /* Scroll if point within this distance from the top or bottom of the window. This is a pixel value. */ - this_scroll_margin = max (0, scroll_margin); - this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4); - this_scroll_margin *= FRAME_LINE_HEIGHT (f); + if (scroll_margin > 0) + { + this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4); + this_scroll_margin *= FRAME_LINE_HEIGHT (f); + } + else + this_scroll_margin = 0; top_scroll_margin = this_scroll_margin; if (WINDOW_WANTS_HEADER_LINE_P (w)) @@ -13442,7 +13441,6 @@ redisplay_window (window, just_this_one_p) { /* We set this later on if we have to adjust point. */ int new_vpos = -1; - int val; w->force_start = Qnil; w->vscroll = 0; @@ -13476,16 +13474,15 @@ redisplay_window (window, just_this_one_p) /* Redisplay, then check if cursor has been set during the redisplay. Give up if new fonts were loaded. */ - val = try_window (window, startp, 1); - if (!val) + /* We used to issue a CHECK_MARGINS argument to try_window here, + but this causes scrolling to fail when point begins inside + the scroll margin (bug#148) -- cyd */ + if (!try_window (window, startp, 0)) { w->force_start = Qt; clear_glyph_matrix (w->desired_matrix); goto need_larger_matrices; } - /* Point was outside the scroll margins. */ - if (val < 0) - new_vpos = window_box_height (w) / 2; if (w->cursor.vpos < 0 && !w->frozen_window_start_p) { @@ -13616,11 +13613,16 @@ redisplay_window (window, just_this_one_p) && NILP (do_mouse_tracking) && CHARPOS (startp) > BEGV && CHARPOS (startp) > BEG + beg_unchanged - && CHARPOS (startp) <= Z - end_unchanged) + && CHARPOS (startp) <= Z - end_unchanged + /* Even if w->start_at_line_beg is nil, a new window may + start at a line_beg, since that's how set_buffer_window + sets it. So, we need to check the return value of + compute_window_start_on_continuation_line. (See also + bug#197). */ + && XMARKER (w->start)->buffer == current_buffer + && compute_window_start_on_continuation_line (w)) { w->force_start = Qt; - if (XMARKER (w->start)->buffer == current_buffer) - compute_window_start_on_continuation_line (w); SET_TEXT_POS_FROM_MARKER (startp, w->start); goto force_start; } @@ -13747,11 +13749,6 @@ redisplay_window (window, just_this_one_p) { init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID); move_it_vertically_backward (&it, 0); -#if 0 - /* I think this assert is bogus if buffer contains - invisible text or images. KFS. */ - xassert (IT_CHARPOS (it) <= PT); -#endif it.current_y = 0; } @@ -13912,8 +13909,8 @@ redisplay_window (window, just_this_one_p) if (FRAME_WINDOW_P (f)) { -#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ - || defined (USE_GTK) +#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \ + || defined (HAVE_NS) || defined (USE_GTK) redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f); #else redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0; @@ -13928,7 +13925,7 @@ redisplay_window (window, just_this_one_p) #ifdef HAVE_WINDOW_SYSTEM if (FRAME_WINDOW_P (f)) { -#if defined (USE_GTK) || USE_MAC_TOOLBAR +#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f); #else redisplay_tool_bar_p = WINDOWP (f->tool_bar_window) @@ -14035,9 +14032,13 @@ try_window (window, pos, check_margins) { int this_scroll_margin; - this_scroll_margin = max (0, scroll_margin); - this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4); - this_scroll_margin *= FRAME_LINE_HEIGHT (it.f); + if (scroll_margin > 0) + { + this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4); + this_scroll_margin *= FRAME_LINE_HEIGHT (f); + } + else + this_scroll_margin = 0; if ((w->cursor.y >= 0 /* not vscrolled */ && w->cursor.y < this_scroll_margin @@ -14047,7 +14048,7 @@ try_window (window, pos, check_margins) seems to give wrong results. We don't want to recenter when the last line is partly visible, we want to allow that case to be handled in the usual way. */ - || (w->cursor.y + 1) > it.last_visible_y) + || w->cursor.y > it.last_visible_y - this_scroll_margin - 1) { w->cursor.vpos = -1; clear_glyph_matrix (w->desired_matrix); @@ -14393,13 +14394,6 @@ try_window_reusing_current_matrix (w) if (display_line (&it)) last_text_row = it.glyph_row - 1; - /* Give up If point isn't in a row displayed or reused. */ - if (w->cursor.vpos < 0) - { - clear_glyph_matrix (w->desired_matrix); - return 0; - } - /* If point is in a reused row, adjust y and vpos of the cursor position. */ if (pt_row) @@ -14408,6 +14402,16 @@ try_window_reusing_current_matrix (w) w->cursor.y -= first_reusable_row->y - start_row->y; } + /* Give up if point isn't in a row displayed or reused. (This + also handles the case where w->cursor.vpos < nrows_scrolled + after the calls to display_line, which can happen with scroll + margins. See bug#1295.) */ + if (w->cursor.vpos < 0) + { + clear_glyph_matrix (w->desired_matrix); + return 0; + } + /* Scroll the display. */ run.current_y = first_reusable_row->y; run.desired_y = WINDOW_HEADER_LINE_HEIGHT (w); @@ -15636,7 +15640,7 @@ dump_glyph (row, glyph, area) else if (glyph->type == COMPOSITE_GLYPH) { fprintf (stderr, - " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n", + " %5d %4c %6d %c %3d 0x%05x", glyph - row->glyphs[TEXT_AREA], '+', glyph->charpos, @@ -15646,8 +15650,12 @@ dump_glyph (row, glyph, area) ? 'S' : '-')), glyph->pixel_width, - glyph->u.cmp_id, - '.', + glyph->u.cmp.id); + if (glyph->u.cmp.automatic) + fprintf (stderr, + "[%d-%d]", + glyph->u.cmp.from, glyph->u.cmp.to); + fprintf (stderr, " . %4d %1.1d%1.1d\n" glyph->face_id, glyph->left_box_line_p, glyph->right_box_line_p); @@ -17067,10 +17075,11 @@ display_menu_bar (w) if (FRAME_X_P (f)) return; #endif -#ifdef MAC_OS - if (FRAME_MAC_P (f)) + +#ifdef HAVE_NS + if (FRAME_NS_P (f)) return; -#endif +#endif /* HAVE_NS */ #ifdef USE_X_TOOLKIT xassert (!FRAME_WINDOW_P (f)); @@ -19556,7 +19565,7 @@ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p) /* Fill glyph string S with composition components specified by S->cmp. BASE_FACE is the base face of the composition. - S->gidx is the index of the first component for S. + S->cmp_from is the index of the first component for S. OVERLAPS non-zero means S should draw the foreground only, and use its physical height for clipping. See also draw_glyphs. @@ -19570,70 +19579,45 @@ fill_composite_glyph_string (s, base_face, overlaps) int overlaps; { int i; + /* For all glyphs of this composition, starting at the offset + S->cmp_from, until we reach the end of the definition or encounter a + glyph that requires the different face, add it to S. */ + struct face *face; xassert (s); s->for_overlaps = overlaps; - - if (s->cmp->method == COMPOSITION_WITH_GLYPH_STRING) + s->face = NULL; + s->font = NULL; + for (i = s->cmp_from; i < s->cmp->glyph_len; i++) { - Lisp_Object gstring - = AREF (XHASH_TABLE (composition_hash_table)->key_and_value, - s->cmp->hash_index * 2); + int c = COMPOSITION_GLYPH (s->cmp, i); - s->face = base_face; - s->font = base_face->font; - for (i = 0, s->nchars = 0; i < s->cmp->glyph_len; i++, s->nchars++) + if (c != '\t') { - Lisp_Object g = LGSTRING_GLYPH (gstring, i); - unsigned code; - XChar2b * store_pos; - if (NILP (g)) - break; - code = LGLYPH_CODE (g); - store_pos = s->char2b + i; - STORE_XCHAR2B (store_pos, code >> 8, code & 0xFF); - } - s->width = s->cmp->pixel_width; - } - else - { - /* For all glyphs of this composition, starting at the offset - S->gidx, until we reach the end of the definition or encounter a - glyph that requires the different face, add it to S. */ - struct face *face; + int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c, + -1, Qnil); - s->face = NULL; - s->font = NULL; - for (i = s->gidx; i < s->cmp->glyph_len; i++) - { - int c = COMPOSITION_GLYPH (s->cmp, i); - - if (c != '\t') + face = get_char_face_and_encoding (s->f, c, face_id, + s->char2b + i, 1, 1); + if (face) { - int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c, - -1, Qnil); - - face = get_char_face_and_encoding (s->f, c, face_id, - s->char2b + i, 1, 1); - if (face) + if (! s->face) { - if (! s->face) - { - s->face = face; - s->font = s->face->font; - } - else if (s->face != face) - break; + s->face = face; + s->font = s->face->font; } + else if (s->face != face) + break; } - ++s->nchars; } - - /* All glyph strings for the same composition has the same width, - i.e. the width set for the first component of the composition. */ - s->width = s->first_glyph->pixel_width; + ++s->nchars; } + s->cmp_to = i; + + /* All glyph strings for the same composition has the same width, + i.e. the width set for the first component of the composition. */ + s->width = s->first_glyph->pixel_width; /* If the specified font could not be loaded, use the frame's default font, but record the fact that we couldn't load it in @@ -19651,7 +19635,43 @@ fill_composite_glyph_string (s, base_face, overlaps) /* This glyph string must always be drawn with 16-bit functions. */ s->two_byte_p = 1; - return s->gidx + s->nchars; + return s->cmp_to; +} + +static int +fill_gstring_glyph_string (s, face_id, start, end, overlaps) + struct glyph_string *s; + int face_id; + int start, end, overlaps; +{ + struct glyph *glyph, *last; + Lisp_Object lgstring; + int i; + + s->for_overlaps = overlaps; + glyph = s->row->glyphs[s->area] + start; + last = s->row->glyphs[s->area] + end; + s->cmp_id = glyph->u.cmp.id; + s->cmp_from = glyph->u.cmp.from; + s->cmp_to = glyph->u.cmp.to; + s->face = FACE_FROM_ID (s->f, face_id); + lgstring = composition_gstring_from_id (s->cmp_id); + s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring)); + glyph++; + while (glyph < last + && glyph->u.cmp.automatic + && glyph->u.cmp.id == s->cmp_id) + s->cmp_to = (glyph++)->u.cmp.to; + + for (i = s->cmp_from; i < s->cmp_to; i++) + { + Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i); + unsigned code = LGLYPH_CODE (lglyph); + + STORE_XCHAR2B ((s->char2b + i), code >> 8, code & 0xFF); + } + s->width = composition_gstring_width (lgstring, s->cmp_from, s->cmp_to, NULL); + return glyph - s->row->glyphs[s->area]; } @@ -19678,7 +19698,7 @@ fill_glyph_string (s, face_id, start, end, overlaps) xassert (s->nchars == 0); xassert (start >= 0 && end > start); - s->for_overlaps = overlaps, + s->for_overlaps = overlaps; glyph = s->row->glyphs[s->area] + start; last = s->row->glyphs[s->area] + end; voffset = glyph->voffset; @@ -19798,7 +19818,6 @@ get_per_char_metric (f, font, char2b) { static struct font_metrics metrics; unsigned code = (XCHAR2B_BYTE1 (char2b) << 8) | XCHAR2B_BYTE2 (char2b); - struct font *fontp; if (! font || code == FONT_INVALID_CODE) return NULL; @@ -19836,10 +19855,27 @@ x_get_glyph_overhangs (glyph, f, left, right) } else if (glyph->type == COMPOSITE_GLYPH) { - struct composition *cmp = composition_table[glyph->u.cmp_id]; + if (! glyph->u.cmp.automatic) + { + struct composition *cmp = composition_table[glyph->u.cmp.id]; - *right = cmp->rbearing - cmp->pixel_width; - *left = - cmp->lbearing; + if (cmp->rbearing - cmp->pixel_width) + *right = cmp->rbearing - cmp->pixel_width; + if (cmp->lbearing < 0); + *left = - cmp->lbearing; + } + else + { + Lisp_Object gstring = composition_gstring_from_id (glyph->u.cmp.id); + struct font_metrics metrics; + + composition_gstring_width (gstring, glyph->u.cmp.from, + glyph->u.cmp.to, &metrics); + if (metrics.rbearing > metrics.width) + *right = metrics.rbearing; + if (metrics.lbearing < 0) + *left = - metrics.lbearing; + } } } @@ -19900,7 +19936,7 @@ left_overwriting (s) /* Return the index of the last glyph following glyph string S that is - not overwritten by S because of S's right overhang. Value is -1 if + overwritten by S because of S's right overhang. Value is -1 if no such glyph is found. */ static int @@ -20103,7 +20139,7 @@ compute_overhangs_and_x (s, x, backward_p) INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ append_glyph_string (&HEAD, &TAIL, s); \ s->x = (X); \ - START = fill_glyph_string (s, face_id, START, END, overlaps); \ + START = fill_glyph_string (s, face_id, START, END, overlaps); \ } \ while (0) @@ -20121,7 +20157,7 @@ compute_overhangs_and_x (s, x, backward_p) do { \ int face_id = (row)->glyphs[area][START].face_id; \ struct face *base_face = FACE_FROM_ID (f, face_id); \ - int cmp_id = (row)->glyphs[area][START].u.cmp_id; \ + int cmp_id = (row)->glyphs[area][START].u.cmp.id; \ struct composition *cmp = composition_table[cmp_id]; \ XChar2b *char2b; \ struct glyph_string *first_s; \ @@ -20137,7 +20173,7 @@ compute_overhangs_and_x (s, x, backward_p) INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ append_glyph_string (&(HEAD), &(TAIL), s); \ s->cmp = cmp; \ - s->gidx = n; \ + s->cmp_from = n; \ s->x = (X); \ if (n == 0) \ first_s = s; \ @@ -20149,6 +20185,28 @@ compute_overhangs_and_x (s, x, backward_p) } while (0) +/* Add a glyph string for a glyph-string sequence to the list of strings + between HEAD and TAIL. */ + +#define BUILD_GSTRING_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \ + do { \ + int face_id; \ + XChar2b *char2b; \ + Lisp_Object gstring; \ + \ + face_id = (row)->glyphs[area][START].face_id; \ + gstring = (composition_gstring_from_id \ + ((row)->glyphs[area][START].u.cmp.id)); \ + s = (struct glyph_string *) alloca (sizeof *s); \ + char2b = (XChar2b *) alloca ((sizeof *char2b) \ + * LGSTRING_GLYPH_LEN (gstring)); \ + INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \ + append_glyph_string (&(HEAD), &(TAIL), s); \ + s->x = (X); \ + START = fill_gstring_glyph_string (s, face_id, START, END, overlaps); \ + } while (0) + + /* Build a list of glyph strings between HEAD and TAIL for the glyphs of AREA of glyph row ROW on window W between indices START and END. HL overrides the face for drawing glyph strings, e.g. it is @@ -20159,47 +20217,50 @@ compute_overhangs_and_x (s, x, backward_p) to allocate glyph strings (because draw_glyphs can be called asynchronously). */ -#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ - do \ - { \ - HEAD = TAIL = NULL; \ - while (START < END) \ - { \ - struct glyph *first_glyph = (row)->glyphs[area] + START; \ - switch (first_glyph->type) \ - { \ - case CHAR_GLYPH: \ - BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \ - HL, X, LAST_X); \ - break; \ - \ - case COMPOSITE_GLYPH: \ - BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \ - HL, X, LAST_X); \ - break; \ - \ - case STRETCH_GLYPH: \ - BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \ - HL, X, LAST_X); \ - break; \ - \ - case IMAGE_GLYPH: \ - BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \ - HL, X, LAST_X); \ - break; \ - \ - default: \ - abort (); \ - } \ - \ - if (s) \ - { \ - set_glyph_string_background_width (s, START, LAST_X); \ - (X) += s->width; \ - } \ - } \ - } \ - while (0) +#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \ + do \ + { \ + HEAD = TAIL = NULL; \ + while (START < END) \ + { \ + struct glyph *first_glyph = (row)->glyphs[area] + START; \ + switch (first_glyph->type) \ + { \ + case CHAR_GLYPH: \ + BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \ + HL, X, LAST_X); \ + break; \ + \ + case COMPOSITE_GLYPH: \ + if (first_glyph->u.cmp.automatic) \ + BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \ + HL, X, LAST_X); \ + else \ + BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \ + HL, X, LAST_X); \ + break; \ + \ + case STRETCH_GLYPH: \ + BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \ + HL, X, LAST_X); \ + break; \ + \ + case IMAGE_GLYPH: \ + BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \ + HL, X, LAST_X); \ + break; \ + \ + default: \ + abort (); \ + } \ + \ + if (s) \ + { \ + set_glyph_string_background_width (s, START, LAST_X); \ + (X) += s->width; \ + } \ + } \ + } while (0) /* Draw glyphs between START and END in AREA of ROW on window W, @@ -20426,6 +20487,9 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps) for (s = head; s; s = s->next) FRAME_RIF (f)->draw_glyph_string (s); +#ifndef HAVE_NS + /* When focus a sole frame and move horizontally, this sets on_p to 0 + causing a failure to erase prev cursor position. */ if (area == TEXT_AREA && !row->full_width_p /* When drawing overlapping rows, only the glyph strings' @@ -20442,6 +20506,7 @@ draw_glyphs (w, x, row, area, start, end, hl, overlaps) notice_overwritten_cursor (w, TEXT_AREA, x0, x1, row->y, MATRIX_ROW_BOTTOM_Y (row)); } +#endif /* Value is the x-position up to which drawn, relative to AREA of W. This doesn't include parts drawn because of overhangs. */ @@ -20520,8 +20585,9 @@ append_glyph (it) IT_EXPAND_MATRIX_WIDTH (it, area); } -/* Store one glyph for the composition IT->cmp_id in IT->glyph_row. - Called from x_produce_glyphs when IT->glyph_row is non-null. */ +/* Store one glyph for the composition IT->cmp_it.id in + IT->glyph_row. Called from x_produce_glyphs when IT->glyph_row is + non-null. */ static INLINE void append_composite_glyph (it) @@ -20542,6 +20608,18 @@ append_composite_glyph (it) glyph->descent = it->descent; glyph->voffset = it->voffset; glyph->type = COMPOSITE_GLYPH; + if (it->cmp_it.ch < 0) + { + glyph->u.cmp.automatic = 0; + glyph->u.cmp.id = it->cmp_it.id; + } + else + { + glyph->u.cmp.automatic = 1; + glyph->u.cmp.id = it->cmp_it.id; + glyph->u.cmp.from = it->cmp_it.from; + glyph->u.cmp.to = it->cmp_it.to; + } glyph->avoid_cursor_p = it->avoid_cursor_p; glyph->multibyte_p = it->multibyte_p; glyph->left_box_line_p = it->start_of_box_run_p; @@ -20551,7 +20629,6 @@ append_composite_glyph (it) glyph->padding_p = 0; glyph->glyph_not_available_p = 0; glyph->face_id = it->face_id; - glyph->u.cmp_id = it->cmp_id; glyph->slice = null_glyph_slice; glyph->font_type = FONT_TYPE_UNKNOWN; ++it->glyph_row->used[area]; @@ -21299,25 +21376,33 @@ x_produce_glyphs (it) } else if (it->char_to_display == '\t') { - int tab_width = it->tab_width * font->space_width; - int x = it->current_x + it->continuation_lines_width; - int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width; - - /* If the distance from the current position to the next tab - stop is less than a space character width, use the - tab stop after that. */ - if (next_tab_x - x < font->space_width) - next_tab_x += tab_width; - - it->pixel_width = next_tab_x - x; - it->nglyphs = 1; - it->ascent = it->phys_ascent = FONT_BASE (font) + boff; - it->descent = it->phys_descent = FONT_DESCENT (font) - boff; - - if (it->glyph_row) + if (font->space_width > 0) { - append_stretch_glyph (it, it->object, it->pixel_width, - it->ascent + it->descent, it->ascent); + int tab_width = it->tab_width * font->space_width; + int x = it->current_x + it->continuation_lines_width; + int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width; + + /* If the distance from the current position to the next tab + stop is less than a space character width, use the + tab stop after that. */ + if (next_tab_x - x < font->space_width) + next_tab_x += tab_width; + + it->pixel_width = next_tab_x - x; + it->nglyphs = 1; + it->ascent = it->phys_ascent = FONT_BASE (font) + boff; + it->descent = it->phys_descent = FONT_DESCENT (font) - boff; + + if (it->glyph_row) + { + append_stretch_glyph (it, it->object, it->pixel_width, + it->ascent + it->descent, it->ascent); + } + } + else + { + it->pixel_width = 0; + it->nglyphs = 1; } } else @@ -21400,9 +21485,11 @@ x_produce_glyphs (it) } it->multibyte_p = saved_multibyte_p; } - else if (it->what == IT_COMPOSITION) + else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0) { - /* Note: A composition is represented as one glyph in the + /* A static compositoin. + + Note: A composition is represented as one glyph in the glyph matrix. There are no padding glyphs. Important is that pixel_width, ascent, and descent are the @@ -21410,18 +21497,12 @@ x_produce_glyphs (it) the overall glyphs composed). */ struct face *face = FACE_FROM_ID (it->f, it->face_id); int boff; /* baseline offset */ - struct composition *cmp = composition_table[it->cmp_id]; + struct composition *cmp = composition_table[it->cmp_it.id]; int glyph_len = cmp->glyph_len; struct font *font = face->font; it->nglyphs = 1; - if (cmp->method == COMPOSITION_WITH_GLYPH_STRING) - { - PREPARE_FACE_FOR_DISPLAY (it->f, face); - font_prepare_composition (cmp, it->f); - } - else /* If we have not yet calculated pixel size data of glyphs of the composition for the current face font, calculate them now. Theoretically, we have to check all fonts for the @@ -21441,7 +21522,6 @@ x_produce_glyphs (it) int lbearing, rbearing; int i, width, ascent, descent; int left_padded = 0, right_padded = 0; - int face_id; int c; XChar2b char2b; struct font_metrics *pcm; @@ -21721,6 +21801,52 @@ x_produce_glyphs (it) if (it->descent < 0) it->descent = 0; + if (it->glyph_row) + append_composite_glyph (it); + } + else if (it->what == IT_COMPOSITION) + { + /* A dynamic (automatic) composition. */ + struct face *face = FACE_FROM_ID (it->f, it->face_id); + Lisp_Object gstring; + struct font_metrics metrics; + + gstring = composition_gstring_from_id (it->cmp_it.id); + it->pixel_width + = composition_gstring_width (gstring, it->cmp_it.from, it->cmp_it.to, + &metrics); + if (it->glyph_row + && (metrics.lbearing < 0 || metrics.rbearing > metrics.width)) + it->glyph_row->contains_overlapping_glyphs_p = 1; + it->ascent = it->phys_ascent = metrics.ascent; + it->descent = it->phys_descent = metrics.descent; + if (face->box != FACE_NO_BOX) + { + int thick = face->box_line_width; + + if (thick > 0) + { + it->ascent += thick; + it->descent += thick; + } + else + thick = - thick; + + if (it->start_of_box_run_p) + it->pixel_width += thick; + if (it->end_of_box_run_p) + it->pixel_width += thick; + } + /* If face has an overline, add the height of the overline + (1 pixel) and a 1 pixel margin to the character height. */ + if (face->overline_p) + it->ascent += overline_margin; + take_vertical_position_into_account (it); + if (it->ascent < 0) + it->ascent = 0; + if (it->descent < 0) + it->descent = 0; + if (it->glyph_row) append_composite_glyph (it); } @@ -22539,7 +22665,10 @@ display_and_set_cursor (w, on, hpos, vpos, x, y) /* Switch the display of W's cursor on or off, according to the value of ON. */ -static void +#ifndef HAVE_NS +static +#endif +void update_window_cursor (w, on) struct window *w; int on; @@ -22758,9 +22887,7 @@ cursor_in_mouse_face_p (w) in 20.x as well, and I think it's too risky to install so near the release of 21.1. 2001-09-25 gerd. */ -#ifndef HAVE_CARBON static -#endif int fast_find_position (w, charpos, hpos, vpos, x, y, stop) struct window *w; @@ -23472,7 +23599,7 @@ note_mouse_highlight (f, x, y) struct buffer *b; /* When a menu is active, don't highlight because this looks odd. */ -#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (MAC_OS) +#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) if (popup_activated ()) return; #endif @@ -24861,8 +24988,10 @@ otherwise, respect the value of `truncate-lines'. For any other non-nil value, truncate lines in all windows with less than the full frame width. -A value of nil means to respect the value of `truncate-lines'. */); - Vtruncate_partial_width_windows = make_number (30); +A value of nil means to respect the value of `truncate-lines'. + +If `word-wrap' is enabled, you might want to reduce this. */); + Vtruncate_partial_width_windows = make_number (50); DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video, doc: /* When nil, display the mode-line/header-line/menu-bar in the default face. @@ -24934,9 +25063,10 @@ all the functions in the list are called, with the frame as argument. */); DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions, doc: /* List of functions to call before redisplaying a window with scrolling. -Each function is called with two arguments, the window -and its new display-start position. Note that the value of `window-end' -is not valid when these functions are called. */); +Each function is called with two arguments, the window and its new +display-start position. Note that these functions are also called by +`set-window-buffer'. Also note that the value of `window-end' is not +valid when these functions are called. */); Vwindow_scroll_functions = Qnil; DEFVAR_LISP ("window-text-change-functions",