X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/ccedd25934d7e68a2dc7d1c75b2ed57ed56b03cd..d21d2e9a67b654e308dc2a8770b82c48a0539365:/src/xdisp.c
diff --git a/src/xdisp.c b/src/xdisp.c
index ad2de16c7b..ee5ecbab44 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -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
@@ -262,6 +267,9 @@ Lisp_Object Qfontification_functions;
cursor moves into it. */
Lisp_Object Vmouse_autoselect_window;
+Lisp_Object Vwrap_prefix, Qwrap_prefix;
+Lisp_Object Vline_prefix, Qline_prefix;
+
/* Non-zero means draw tool bar buttons raised when the mouse moves
over them. */
@@ -343,10 +351,17 @@ extern Lisp_Object Voverflow_newline_into_fringe;
(!NILP (Voverflow_newline_into_fringe) \
&& FRAME_WINDOW_P (it->f) \
&& WINDOW_RIGHT_FRINGE_WIDTH (it->w) > 0 \
- && it->current_x == it->last_visible_x)
+ && it->current_x == it->last_visible_x \
+ && it->line_wrap != WORD_WRAP)
#endif /* HAVE_WINDOW_SYSTEM */
+/* Test if the display element loaded in IT is a space or tab
+ character. This is used to determine word wrapping. */
+
+#define IT_DISPLAYING_WHITESPACE(it) \
+ (it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t'))
+
/* Non-nil means show the text cursor in void text areas
i.e. in blank areas after eol and eob. This used to be
the default in 21.3. */
@@ -753,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. */
@@ -765,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}
};
@@ -842,6 +855,25 @@ Lisp_Object previous_help_echo_string;
static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
+/* Platform-independent portion of hourglass implementation. */
+
+/* Non-zero means we're allowed to display a hourglass pointer. */
+int display_hourglass_p;
+
+/* Non-zero means an hourglass cursor is currently shown. */
+int hourglass_shown_p;
+
+/* If non-null, an asynchronous timer that, when it expires, displays
+ an hourglass cursor on all frames. */
+struct atimer *hourglass_atimer;
+
+/* Number of seconds to wait before displaying an hourglass cursor. */
+Lisp_Object Vhourglass_delay;
+
+/* Default number of seconds to wait before displaying an hourglass
+ cursor. */
+#define DEFAULT_HOURGLASS_DELAY 1
+
/* Function prototypes. */
@@ -853,9 +885,9 @@ static int cursor_row_p P_ ((struct window *, struct glyph_row *));
static int redisplay_mode_lines P_ ((Lisp_Object, int));
static char *decode_mode_spec_coding P_ ((Lisp_Object, char *, int));
-#if 0
-static int invisible_text_between_p P_ ((struct it *, int, int));
-#endif
+static Lisp_Object get_it_property P_ ((struct it *it, Lisp_Object prop));
+
+static void handle_line_prefix P_ ((struct it *));
static void pint2str P_ ((char *, int, int));
static void pint2hrstr P_ ((char *, int, int));
@@ -1291,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)
@@ -1724,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;
@@ -2063,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
@@ -2543,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))
@@ -2967,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
@@ -3074,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)
@@ -3094,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;
}
@@ -3121,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);
@@ -3139,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;
@@ -3149,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. */
@@ -3177,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))
{
@@ -3226,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)));
@@ -3558,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)
@@ -3608,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);
}
@@ -3804,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. */
@@ -3952,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;
}
@@ -4003,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,
@@ -4329,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;
@@ -4582,95 +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 (FRAME_WINDOW_P (it->f) && 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];
-
- 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. */
@@ -4680,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))
{
@@ -4707,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))
@@ -4716,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;
}
@@ -4824,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
@@ -4841,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
{
@@ -4865,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);
@@ -5123,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. */
@@ -5179,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;
@@ -5191,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;
@@ -5208,6 +5099,7 @@ push_it (it)
p->string_nchars = it->string_nchars;
p->area = it->area;
p->multibyte_p = it->multibyte_p;
+ p->avoid_cursor_p = it->avoid_cursor_p;
p->space_width = it->space_width;
p->font_height = it->font_height;
p->voffset = it->voffset;
@@ -5233,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;
@@ -5248,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;
@@ -5269,6 +5155,7 @@ pop_it (it)
it->string_nchars = p->string_nchars;
it->area = p->area;
it->multibyte_p = p->multibyte_p;
+ it->avoid_cursor_p = p->avoid_cursor_p;
it->space_width = p->space_width;
it->font_height = p->font_height;
it->voffset = p->voffset;
@@ -5713,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,
@@ -5722,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. */
@@ -5996,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)
@@ -6004,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. */
@@ -6064,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);
@@ -6073,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;
@@ -6145,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:
@@ -6155,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
{
@@ -6216,9 +6185,9 @@ next_element_from_display_vector (it)
/* KFS: This code used to check ip->dpvec[0] instead of the current element.
That seemed totally bogus - so I changed it... */
+ gc = it->dpvec[it->current.dpvec_index];
- if ((gc = it->dpvec[it->current.dpvec_index], GLYPH_CODE_P (gc))
- && GLYPH_CODE_CHAR_VALID_P (gc))
+ if (GLYPH_CODE_P (gc) && GLYPH_CODE_CHAR_VALID_P (gc))
{
it->c = GLYPH_CODE_CHAR (gc);
it->len = CHAR_BYTES (it->c);
@@ -6284,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);
@@ -6314,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);
@@ -6451,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)
{
@@ -6500,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;
@@ -6579,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;
}
@@ -6653,7 +6654,7 @@ move_it_in_display_line_to (struct it *it,
{
enum move_it_result result = MOVE_UNDEFINED;
struct glyph_row *saved_glyph_row;
- struct it wrap_it, atpos_it;
+ struct it wrap_it, atpos_it, atx_it;
int may_wrap = 0;
/* Don't produce glyphs in produce_glyphs. */
@@ -6661,11 +6662,13 @@ move_it_in_display_line_to (struct it *it,
it->glyph_row = NULL;
/* Use wrap_it to save a copy of IT wherever a word wrap could
- occur. Use atpos_it to save a copy of IT at the desired
+ occur. Use atpos_it to save a copy of IT at the desired buffer
position, if found, so that we can scan ahead and check if the
- word later overshoots the window edge. */
+ word later overshoots the window edge. Use atx_it similarly, for
+ pixel positions. */
wrap_it.sp = -1;
atpos_it.sp = -1;
+ atx_it.sp = -1;
#define BUFFER_POS_REACHED_P() \
((op & MOVE_TO_POS) != 0 \
@@ -6675,35 +6678,37 @@ move_it_in_display_line_to (struct it *it,
|| (it->method == GET_FROM_DISPLAY_VECTOR \
&& it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
+ /* If there's a line-/wrap-prefix, handle it. */
+ if (it->hpos == 0 && it->method == GET_FROM_BUFFER
+ && it->current_y < it->last_visible_y)
+ handle_line_prefix (it);
while (1)
{
int x, i, ascent = 0, descent = 0;
- /* Stop if we move beyond TO_CHARPOS (after an image or stretch glyph). */
+/* Utility macro to reset an iterator with x, ascent, and descent. */
+#define IT_RESET_X_ASCENT_DESCENT(IT) \
+ ((IT)->current_x = x, (IT)->max_ascent = ascent, \
+ (IT)->max_descent = descent)
+
+ /* Stop if we move beyond TO_CHARPOS (after an image or stretch
+ glyph). */
if ((op & MOVE_TO_POS) != 0
&& BUFFERP (it->object)
&& it->method == GET_FROM_BUFFER
&& IT_CHARPOS (*it) > to_charpos)
{
- if (it->line_wrap == WORD_WRAP)
- {
- /* If wrap_it is valid, the current position might be in
- a word that is wrapped to the next line, so continue
- to see if that happens. */
- if (wrap_it.sp < 0)
- {
- result = MOVE_POS_MATCH_OR_ZV;
- break;
- }
- if (atpos_it.sp < 0)
- atpos_it = *it;
- }
- else
+ if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
{
result = MOVE_POS_MATCH_OR_ZV;
break;
}
+ else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
+ /* If wrap_it is valid, the current position might be in a
+ word that is wrapped. So, save the iterator in
+ atpos_it and continue to see if wrapping happens. */
+ atpos_it = *it;
}
/* Stop when ZV reached.
@@ -6726,31 +6731,39 @@ move_it_in_display_line_to (struct it *it,
}
else
{
- /* Remember the line height so far in case the next element
- doesn't fit on the line. */
- ascent = it->max_ascent;
- descent = it->max_descent;
-
if (it->line_wrap == WORD_WRAP)
{
- if (it->what == IT_CHARACTER
- && (it->c == ' ' || it->c == '\t'))
+ if (IT_DISPLAYING_WHITESPACE (it))
may_wrap = 1;
else if (may_wrap)
{
- /* We are done if the position is already found. */
+ /* We have reached a glyph that follows one or more
+ whitespace characters. If the position is
+ already found, we are done. */
if (atpos_it.sp >= 0)
{
*it = atpos_it;
- atpos_it.sp = -1;
- goto buffer_pos_reached;
+ result = MOVE_POS_MATCH_OR_ZV;
+ goto done;
+ }
+ if (atx_it.sp >= 0)
+ {
+ *it = atx_it;
+ result = MOVE_X_REACHED;
+ goto done;
}
+ /* Otherwise, we can wrap here. */
wrap_it = *it;
may_wrap = 0;
}
}
}
+ /* Remember the line height for the current line, in case
+ the next element doesn't fit on the line. */
+ ascent = it->max_ascent;
+ descent = it->max_descent;
+
/* The call to produce_glyphs will get the metrics of the
display element IT is loaded with. Record the x-position
before this display element, in case it doesn't fit on the
@@ -6801,19 +6814,28 @@ move_it_in_display_line_to (struct it *it,
{
if (BUFFER_POS_REACHED_P ())
{
- if (it->line_wrap == WORD_WRAP)
+ if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
+ goto buffer_pos_reached;
+ if (atpos_it.sp < 0)
{
- if (wrap_it.sp < 0)
- goto buffer_pos_reached;
- if (atpos_it.sp < 0)
- atpos_it = *it;
+ atpos_it = *it;
+ IT_RESET_X_ASCENT_DESCENT (&atpos_it);
+ }
+ }
+ else
+ {
+ if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
+ {
+ it->current_x = x;
+ result = MOVE_X_REACHED;
+ break;
+ }
+ if (atx_it.sp < 0)
+ {
+ atx_it = *it;
+ IT_RESET_X_ASCENT_DESCENT (&atx_it);
}
- else
- goto buffer_pos_reached;
}
- it->current_x = x;
- result = MOVE_X_REACHED;
- break;
}
if (/* Lines are continued. */
@@ -6843,10 +6865,21 @@ move_it_in_display_line_to (struct it *it,
now that we know it fits in this row. */
if (BUFFER_POS_REACHED_P ())
{
- it->hpos = hpos_before_this_char;
- it->current_x = x_before_this_char;
- result = MOVE_POS_MATCH_OR_ZV;
- break;
+ if (it->line_wrap != WORD_WRAP
+ || wrap_it.sp < 0)
+ {
+ it->hpos = hpos_before_this_char;
+ it->current_x = x_before_this_char;
+ result = MOVE_POS_MATCH_OR_ZV;
+ break;
+ }
+ if (it->line_wrap == WORD_WRAP
+ && atpos_it.sp < 0)
+ {
+ atpos_it = *it;
+ atpos_it.current_x = x_before_this_char;
+ atpos_it.hpos = hpos_before_this_char;
+ }
}
set_iterator_to_next (it, 1);
@@ -6876,16 +6909,13 @@ move_it_in_display_line_to (struct it *it,
}
}
else
- {
- it->current_x = x;
- it->max_ascent = ascent;
- it->max_descent = descent;
- }
+ IT_RESET_X_ASCENT_DESCENT (it);
if (wrap_it.sp >= 0)
{
*it = wrap_it;
atpos_it.sp = -1;
+ atx_it.sp = -1;
}
TRACE_MOVE ((stderr, "move_it_in: continued at %d\n",
@@ -6896,15 +6926,13 @@ move_it_in_display_line_to (struct it *it,
if (BUFFER_POS_REACHED_P ())
{
- if (it->line_wrap == WORD_WRAP)
+ if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
+ goto buffer_pos_reached;
+ if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
{
- if (wrap_it.sp < 0)
- goto buffer_pos_reached;
- if (atpos_it.sp < 0)
- atpos_it = *it;
+ atpos_it = *it;
+ IT_RESET_X_ASCENT_DESCENT (&atpos_it);
}
- else
- goto buffer_pos_reached;
}
if (new_x > it->first_visible_x)
@@ -6921,9 +6949,7 @@ move_it_in_display_line_to (struct it *it,
else if (BUFFER_POS_REACHED_P ())
{
buffer_pos_reached:
- it->current_x = x;
- it->max_ascent = ascent;
- it->max_descent = descent;
+ IT_RESET_X_ASCENT_DESCENT (it);
result = MOVE_POS_MATCH_OR_ZV;
break;
}
@@ -6973,14 +6999,19 @@ move_it_in_display_line_to (struct it *it,
result = MOVE_LINE_TRUNCATED;
break;
}
+#undef IT_RESET_X_ASCENT_DESCENT
}
#undef BUFFER_POS_REACHED_P
/* If we scanned beyond to_pos and didn't find a point to wrap at,
- return iterator at to_pos. */
+ restore the saved iterator. */
if (atpos_it.sp >= 0)
*it = atpos_it;
+ else if (atx_it.sp >= 0)
+ *it = atx_it;
+
+ done:
/* Restore the iterator settings altered at the beginning of this
function. */
@@ -6994,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);
}
@@ -7069,6 +7118,9 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
{
struct it it_backup;
+ if (it->line_wrap == WORD_WRAP)
+ it_backup = *it;
+
/* TO_Y specified means stop at TO_X in the line containing
TO_Y---or at TO_CHARPOS if this is reached first. The
problem is that we can't really tell whether the line
@@ -7081,28 +7133,19 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
If we didn't use TO_X == 0, we would stop at the end of
the line which is probably not what a caller would expect
to happen. */
- skip = move_it_in_display_line_to (it, to_charpos,
- ((op & MOVE_TO_X)
- ? to_x : 0),
- (MOVE_TO_X
- | (op & MOVE_TO_POS)));
+ skip = move_it_in_display_line_to
+ (it, to_charpos, ((op & MOVE_TO_X) ? to_x : 0),
+ (MOVE_TO_X | (op & MOVE_TO_POS)));
/* If TO_CHARPOS is reached or ZV, we don't have to do more. */
if (skip == MOVE_POS_MATCH_OR_ZV)
+ reached = 5;
+ else if (skip == MOVE_X_REACHED)
{
- reached = 5;
- break;
- }
-
- /* If TO_X was reached, we would like to know whether TO_Y
- is in the line. This can only be said if we know the
- total line height which requires us to scan the rest of
- the line. */
- if (skip == MOVE_X_REACHED)
- {
- /* Wait! We can conclude that TO_Y is in the line if
- the already scanned glyphs make the line tall enough
- because further scanning doesn't make it shorter. */
+ /* If TO_X was reached, we want to know whether TO_Y is
+ in the line. We know this is the case if the already
+ scanned glyphs make the line tall enough. Otherwise,
+ we must check by scanning the rest of the line. */
line_height = it->max_ascent + it->max_descent;
if (to_y >= it->current_y
&& to_y < it->current_y + line_height)
@@ -7115,27 +7158,48 @@ move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
skip2 = move_it_in_display_line_to (it, to_charpos, -1,
op & MOVE_TO_POS);
TRACE_MOVE ((stderr, "move_it: to %d\n", IT_CHARPOS (*it)));
- }
-
- /* Now, decide whether TO_Y is in this line. */
- line_height = it->max_ascent + it->max_descent;
- TRACE_MOVE ((stderr, "move_it: line_height = %d\n", line_height));
+ line_height = it->max_ascent + it->max_descent;
+ TRACE_MOVE ((stderr, "move_it: line_height = %d\n", line_height));
- if (to_y >= it->current_y
- && to_y < it->current_y + line_height)
- {
- if (skip == MOVE_X_REACHED)
- /* If TO_Y is in this line and TO_X was reached above,
- we scanned too far. We have to restore IT's settings
- to the ones before skipping. */
- *it = it_backup;
- reached = 6;
+ if (to_y >= it->current_y
+ && to_y < it->current_y + line_height)
+ {
+ /* If TO_Y is in this line and TO_X was reached
+ above, we scanned too far. We have to restore
+ IT's settings to the ones before skipping. */
+ *it = it_backup;
+ reached = 6;
+ }
+ else
+ {
+ skip = skip2;
+ if (skip == MOVE_POS_MATCH_OR_ZV)
+ reached = 7;
+ }
}
- else if (skip == MOVE_X_REACHED)
+ else
{
- skip = skip2;
- if (skip == MOVE_POS_MATCH_OR_ZV)
- reached = 7;
+ /* Check whether TO_Y is in this line. */
+ line_height = it->max_ascent + it->max_descent;
+ TRACE_MOVE ((stderr, "move_it: line_height = %d\n", line_height));
+
+ if (to_y >= it->current_y
+ && to_y < it->current_y + line_height)
+ {
+ /* 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
+ && it->line_wrap == WORD_WRAP)
+ {
+ int prev_x = max (it->current_x - 1, 0);
+ *it = it_backup;
+ skip = move_it_in_display_line_to
+ (it, -1, prev_x, MOVE_TO_X);
+ }
+ reached = 6;
+ }
}
if (reached)
@@ -7175,8 +7239,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:
@@ -7195,6 +7270,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));
}
@@ -7377,41 +7476,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
@@ -7827,7 +7891,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);
@@ -7926,7 +7990,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);
@@ -8024,7 +8088,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);
}
@@ -8195,6 +8259,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]))
@@ -9380,7 +9447,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
}
}
@@ -9465,7 +9557,8 @@ prepare_menu_bars ()
while (CONSP (functions))
{
- call1 (XCAR (functions), frame);
+ if (!EQ (XCAR (functions), Qt))
+ call1 (XCAR (functions), frame);
functions = XCDR (functions);
}
UNGCPRO;
@@ -9475,9 +9568,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;
}
@@ -9490,9 +9580,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
}
@@ -9533,19 +9620,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
@@ -9603,11 +9681,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 ())
@@ -9618,11 +9696,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);
@@ -9723,6 +9801,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
@@ -9733,7 +9819,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)
@@ -9767,7 +9853,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;
@@ -9789,6 +9875,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);
@@ -10199,7 +10293,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;
@@ -11206,7 +11300,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;
@@ -11229,7 +11323,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
@@ -11285,7 +11379,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
@@ -11293,7 +11387,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;
@@ -11419,6 +11513,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;
@@ -11728,11 +11826,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;
}
}
@@ -12026,11 +12119,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;
}
}
@@ -12220,7 +12308,8 @@ set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
while (glyph < end
&& !INTEGERP (glyph->object)
&& (!BUFFERP (glyph->object)
- || (last_pos = glyph->charpos) < pt_old))
+ || (last_pos = glyph->charpos) < pt_old
+ || glyph->avoid_cursor_p))
{
if (! STRINGP (glyph->object))
{
@@ -12530,19 +12619,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");
@@ -12553,84 +12636,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);
@@ -12652,19 +12728,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);
@@ -12913,9 +12990,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))
@@ -13359,7 +13440,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;
@@ -13393,16 +13473,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)
{
@@ -13533,11 +13612,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;
}
@@ -13664,11 +13748,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;
}
@@ -13829,8 +13908,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;
@@ -13845,7 +13924,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)
@@ -13952,9 +14031,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
@@ -13964,7 +14047,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);
@@ -14310,13 +14393,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)
@@ -14325,6 +14401,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);
@@ -14485,9 +14571,10 @@ find_last_unchanged_at_beg_row (w)
int yb = window_text_bottom_y (w);
/* Find the last row displaying unchanged text. */
- row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
- while (MATRIX_ROW_DISPLAYS_TEXT_P (row)
- && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos)
+ for (row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+ MATRIX_ROW_DISPLAYS_TEXT_P (row)
+ && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos;
+ ++row)
{
if (/* If row ends before first_changed_pos, it is unchanged,
except in some case. */
@@ -14504,10 +14591,8 @@ find_last_unchanged_at_beg_row (w)
row_found = row;
/* Stop if last visible row. */
- if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
+ if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
break;
-
- ++row;
}
return row_found;
@@ -14823,6 +14908,12 @@ try_window_id (w)
if (overlay_arrows_changed_p ())
GIVE_UP (12);
+ /* When word-wrap is on, adding a space to the first word of a
+ wrapped line can change the wrap position, altering the line
+ above it. It might be worthwhile to handle this more
+ intelligently, but for now just redisplay from scratch. */
+ if (!NILP (XBUFFER (w->buffer)->word_wrap))
+ GIVE_UP (21);
/* Make sure beg_unchanged and end_unchanged are up to date. Do it
only if buffer has really changed. The reason is that the gap is
@@ -15548,7 +15639,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,
@@ -15558,8 +15649,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);
@@ -16086,8 +16181,7 @@ extend_face_to_end_of_line (it)
&& it->glyph_row->displays_text_p
&& face->box == FACE_NO_BOX
&& face->background == FRAME_BACKGROUND_PIXEL (f)
- && !face->stipple
- && it->line_wrap != WORD_WRAP)
+ && !face->stipple)
return;
/* Set the glyph row flag indicating that the face of the last glyph
@@ -16289,6 +16383,97 @@ cursor_row_p (w, row)
return cursor_row_p;
}
+
+
+/* Push the display property PROP so that it will be rendered at the
+ current position in IT. */
+
+static void
+push_display_prop (struct it *it, Lisp_Object prop)
+{
+ push_it (it);
+
+ /* Never display a cursor on the prefix. */
+ it->avoid_cursor_p = 1;
+
+ if (STRINGP (prop))
+ {
+ if (SCHARS (prop) == 0)
+ {
+ pop_it (it);
+ return;
+ }
+
+ it->string = prop;
+ it->multibyte_p = STRING_MULTIBYTE (it->string);
+ it->current.overlay_string_index = -1;
+ IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
+ it->end_charpos = it->string_nchars = SCHARS (it->string);
+ it->method = GET_FROM_STRING;
+ it->stop_charpos = 0;
+ }
+ else if (CONSP (prop) && EQ (XCAR (prop), Qspace))
+ {
+ it->method = GET_FROM_STRETCH;
+ it->object = prop;
+ }
+#ifdef HAVE_WINDOW_SYSTEM
+ else if (IMAGEP (prop))
+ {
+ it->what = IT_IMAGE;
+ it->image_id = lookup_image (it->f, prop);
+ it->method = GET_FROM_IMAGE;
+ }
+#endif /* HAVE_WINDOW_SYSTEM */
+ else
+ {
+ pop_it (it); /* bogus display property, give up */
+ return;
+ }
+}
+
+/* Return the character-property PROP at the current position in IT. */
+
+static Lisp_Object
+get_it_property (it, prop)
+ struct it *it;
+ Lisp_Object prop;
+{
+ Lisp_Object position;
+
+ if (STRINGP (it->object))
+ position = make_number (IT_STRING_CHARPOS (*it));
+ else if (BUFFERP (it->object))
+ position = make_number (IT_CHARPOS (*it));
+ else
+ return Qnil;
+
+ return Fget_char_property (position, prop, it->object);
+}
+
+/* See if there's a line- or wrap-prefix, and if so, push it on IT. */
+
+static void
+handle_line_prefix (struct it *it)
+{
+ Lisp_Object prefix;
+ if (it->continuation_lines_width > 0)
+ {
+ prefix = get_it_property (it, Qwrap_prefix);
+ if (NILP (prefix))
+ prefix = Vwrap_prefix;
+ }
+ else
+ {
+ prefix = get_it_property (it, Qline_prefix);
+ if (NILP (prefix))
+ prefix = Vline_prefix;
+ }
+ if (! NILP (prefix))
+ push_display_prop (it, prefix);
+}
+
+
/* Construct the glyph row IT->glyph_row in the desired matrix of
IT->w from text at the current position of IT. See dispextern.h
@@ -16347,6 +16532,13 @@ display_line (it)
move_it_in_display_line_to (it, ZV, it->first_visible_x,
MOVE_TO_POS | MOVE_TO_X);
}
+ else
+ {
+ /* We only do this when not calling `move_it_in_display_line_to'
+ above, because move_it_in_display_line_to calls
+ handle_line_prefix itself. */
+ handle_line_prefix (it);
+ }
/* Get the initial row height. This is either the height of the
text hscrolled, if there is any, or zero. */
@@ -16410,8 +16602,7 @@ display_line (it)
if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
{
- if (it->what == IT_CHARACTER
- && (it->c == ' ' || it->c == '\t'))
+ if (IT_DISPLAYING_WHITESPACE (it))
may_wrap = 1;
else if (may_wrap)
{
@@ -16508,6 +16699,18 @@ display_line (it)
++it->hpos;
if (i == nglyphs - 1)
{
+ /* If line-wrap is on, check if a previous
+ wrap point was found. */
+ if (wrap_row_used > 0
+ /* Even if there is a previous wrap
+ point, continue the line here as
+ usual, if (i) the previous character
+ was a space or tab AND (ii) the
+ current character is not. */
+ && (!may_wrap
+ || IT_DISPLAYING_WHITESPACE (it)))
+ goto back_to_wrap;
+
set_iterator_to_next (it, 1);
#ifdef HAVE_WINDOW_SYSTEM
if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
@@ -16526,8 +16729,6 @@ display_line (it)
}
}
#endif /* HAVE_WINDOW_SYSTEM */
- if (wrap_row_used > 0)
- goto back_to_wrap;
}
}
else if (CHAR_GLYPH_PADDING_P (*glyph)
@@ -16873,10 +17074,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));
@@ -19362,7 +19564,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.
@@ -19376,70 +19578,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)
- {
- Lisp_Object gstring
- = AREF (XHASH_TABLE (composition_hash_table)->key_and_value,
- s->cmp->hash_index * 2);
-
- s->face = base_face;
- s->font = base_face->font;
- for (i = 0, s->nchars = 0; i < s->cmp->glyph_len; i++, s->nchars++)
- {
- 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
+ s->face = NULL;
+ s->font = NULL;
+ for (i = s->cmp_from; i < s->cmp->glyph_len; i++)
{
- /* 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 c = COMPOSITION_GLYPH (s->cmp, i);
- s->face = NULL;
- s->font = NULL;
- for (i = s->gidx; i < s->cmp->glyph_len; i++)
+ if (c != '\t')
{
- int c = COMPOSITION_GLYPH (s->cmp, i);
+ int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c,
+ -1, Qnil);
- 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
@@ -19457,7 +19634,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];
}
@@ -19484,7 +19697,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;
@@ -19604,7 +19817,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;
@@ -19642,10 +19854,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];
+
+ 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;
- *right = cmp->rbearing - cmp->pixel_width;
- *left = - cmp->lbearing;
+ 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;
+ }
}
}
@@ -19706,7 +19935,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
@@ -19909,7 +20138,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)
@@ -19927,7 +20156,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; \
@@ -19943,7 +20172,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; \
@@ -19955,6 +20184,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
@@ -19965,47 +20216,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,
@@ -20232,6 +20486,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'
@@ -20248,6 +20505,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. */
@@ -20309,6 +20567,7 @@ append_glyph (it)
glyph->descent = it->descent;
glyph->voffset = it->voffset;
glyph->type = CHAR_GLYPH;
+ 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;
glyph->right_box_line_p = it->end_of_box_run_p;
@@ -20325,8 +20584,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)
@@ -20347,6 +20607,19 @@ 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;
glyph->right_box_line_p = it->end_of_box_run_p;
@@ -20355,7 +20628,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];
@@ -20528,6 +20800,7 @@ produce_image_glyph (it)
glyph->descent = it->descent;
glyph->voffset = it->voffset;
glyph->type = IMAGE_GLYPH;
+ 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;
glyph->right_box_line_p = it->end_of_box_run_p;
@@ -20572,6 +20845,7 @@ append_stretch_glyph (it, object, width, height, ascent)
glyph->descent = height - ascent;
glyph->voffset = it->voffset;
glyph->type = STRETCH_GLYPH;
+ 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;
glyph->right_box_line_p = it->end_of_box_run_p;
@@ -20739,27 +21013,6 @@ produce_stretch_glyph (it)
take_vertical_position_into_account (it);
}
-/* Get line-height and line-spacing property at point.
- If line-height has format (HEIGHT TOTAL), return TOTAL
- in TOTAL_HEIGHT. */
-
-static Lisp_Object
-get_line_height_property (it, prop)
- struct it *it;
- Lisp_Object prop;
-{
- Lisp_Object position;
-
- if (STRINGP (it->object))
- position = make_number (IT_STRING_CHARPOS (*it));
- else if (BUFFERP (it->object))
- position = make_number (IT_CHARPOS (*it));
- else
- return Qnil;
-
- return Fget_char_property (position, prop, it->object);
-}
-
/* Calculate line-height and line-spacing properties.
An integer value specifies explicit pixel value.
A float value specifies relative value to current face height.
@@ -21047,7 +21300,7 @@ x_produce_glyphs (it)
it->pixel_width = 0;
it->nglyphs = 0;
- height = get_line_height_property(it, Qline_height);
+ height = get_it_property(it, Qline_height);
/* Split (line-height total-height) list */
if (CONSP (height)
&& CONSP (XCDR (height))
@@ -21109,7 +21362,7 @@ x_produce_glyphs (it)
spacing = calc_line_height_property(it, total_height, font, boff, 0);
else
{
- spacing = get_line_height_property(it, Qline_spacing);
+ spacing = get_it_property(it, Qline_spacing);
spacing = calc_line_height_property(it, spacing, font, boff, 0);
}
if (INTEGERP (spacing))
@@ -21122,25 +21375,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)
+ {
+ 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
{
- append_stretch_glyph (it, it->object, it->pixel_width,
- it->ascent + it->descent, it->ascent);
+ it->pixel_width = 0;
+ it->nglyphs = 1;
}
}
else
@@ -21223,9 +21484,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
@@ -21233,18 +21496,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
@@ -21264,7 +21521,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;
@@ -21544,6 +21800,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);
}
@@ -22362,7 +22664,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;
@@ -22581,9 +22886,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;
@@ -23295,7 +23598,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
@@ -24684,8 +24987,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.
@@ -24757,9 +25062,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",
@@ -24923,6 +25229,32 @@ The enable predicate for a menu binding should check this variable. */);
doc: /* Non-nil means don't update menu bars. Internal use only. */);
inhibit_menubar_update = 0;
+ DEFVAR_LISP ("wrap-prefix", &Vwrap_prefix,
+ doc: /* Prefix added to the beginning of all continuation lines at display-time.
+May be a string, an image, or a stretch-glyph such as used by the
+`display' text-property.
+
+This variable is overridden by any `wrap-prefix' text-property.
+
+To add a prefix to non-continuation lines, use the `line-prefix' variable. */);
+ Vwrap_prefix = Qnil;
+ staticpro (&Qwrap_prefix);
+ Qwrap_prefix = intern ("wrap-prefix");
+ Fmake_variable_buffer_local (Qwrap_prefix);
+
+ DEFVAR_LISP ("line-prefix", &Vline_prefix,
+ doc: /* Prefix added to the beginning of all non-continuation lines at display-time.
+May be a string, an image, or a stretch-glyph such as used by the
+`display' text-property.
+
+This variable is overridden by any `line-prefix' text-property.
+
+To add a prefix to continuation lines, use the `wrap-prefix' variable. */);
+ Vline_prefix = Qnil;
+ staticpro (&Qline_prefix);
+ Qline_prefix = intern ("line-prefix");
+ Fmake_variable_buffer_local (Qline_prefix);
+
DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay,
doc: /* Non-nil means don't eval Lisp during redisplay. */);
inhibit_eval_during_redisplay = 0;
@@ -24959,6 +25291,18 @@ particularly when using variable `x-use-underline-position-properties'
with fonts that specify an UNDERLINE_POSITION relatively close to the
baseline. The default value is 1. */);
underline_minimum_offset = 1;
+
+ DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
+ doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
+ display_hourglass_p = 1;
+
+ DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
+ doc: /* *Seconds to wait before displaying an hourglass pointer.
+Value must be an integer or float. */);
+ Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
+
+ hourglass_atimer = NULL;
+ hourglass_shown_p = 0;
}
@@ -25014,6 +25358,67 @@ init_xdisp ()
help_echo_showing_p = 0;
}
+/* Since w32 does not support atimers, it defines its own implementation of
+ the following three functions in w32fns.c. */
+#ifndef WINDOWSNT
+
+/* Platform-independent portion of hourglass implementation. */
+
+/* Return non-zero if houglass timer has been started or hourglass is shown. */
+int
+hourglass_started ()
+{
+ return hourglass_shown_p || hourglass_atimer != NULL;
+}
+
+/* Cancel a currently active hourglass timer, and start a new one. */
+void
+start_hourglass ()
+{
+#if defined (HAVE_WINDOW_SYSTEM)
+ EMACS_TIME delay;
+ int secs, usecs = 0;
+
+ cancel_hourglass ();
+
+ if (INTEGERP (Vhourglass_delay)
+ && XINT (Vhourglass_delay) > 0)
+ secs = XFASTINT (Vhourglass_delay);
+ else if (FLOATP (Vhourglass_delay)
+ && XFLOAT_DATA (Vhourglass_delay) > 0)
+ {
+ Lisp_Object tem;
+ tem = Ftruncate (Vhourglass_delay, Qnil);
+ secs = XFASTINT (tem);
+ usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
+ }
+ else
+ secs = DEFAULT_HOURGLASS_DELAY;
+
+ EMACS_SET_SECS_USECS (delay, secs, usecs);
+ hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
+ show_hourglass, NULL);
+#endif
+}
+
+
+/* Cancel the hourglass cursor timer if active, hide a busy cursor if
+ shown. */
+void
+cancel_hourglass ()
+{
+#if defined (HAVE_WINDOW_SYSTEM)
+ if (hourglass_atimer)
+ {
+ cancel_atimer (hourglass_atimer);
+ hourglass_atimer = NULL;
+ }
+
+ if (hourglass_shown_p)
+ hide_hourglass ();
+#endif
+}
+#endif /* ! WINDOWSNT */
/* arch-tag: eacc864d-bb6a-4b74-894a-1a4399a1358b
(do not change this comment) */