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",