#include "termchar.h"
#include "dispextern.h"
#include "buffer.h"
+#include "character.h"
#include "charset.h"
#include "indent.h"
#include "commands.h"
#include "macterm.h"
#endif
+#ifdef HAVE_WINDOW_SYSTEM
+#ifdef USE_FONT_BACKEND
+#include "font.h"
+#endif /* USE_FONT_BACKEND */
+#endif /* HAVE_WINDOW_SYSTEM */
+
#ifndef FRAME_X_OUTPUT
#define FRAME_X_OUTPUT(f) ((f)->output_data.x)
#endif
struct buffer *displayed_buffer;
+/* Space between overline and text. */
+
+EMACS_INT overline_margin;
+
/* Value returned from text property handlers (see below). */
enum prop_handled
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. */
{&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}
};
static Lisp_Object redisplay_window_error ();
static Lisp_Object redisplay_window_0 P_ ((Lisp_Object));
static Lisp_Object redisplay_window_1 P_ ((Lisp_Object));
-static void update_menu_bar P_ ((struct frame *, int));
+static int update_menu_bar P_ ((struct frame *, int, int));
static int try_window_reusing_current_matrix P_ ((struct window *));
static int try_window_id P_ ((struct window *));
static int display_line P_ ((struct it *));
static void compute_line_metrics P_ ((struct it *));
static void run_redisplay_end_trigger_hook P_ ((struct it *));
static int get_overlay_strings P_ ((struct it *, int));
+static int get_overlay_strings_1 P_ ((struct it *, int, int));
static void next_overlay_string P_ ((struct it *));
static void reseat P_ ((struct it *, struct text_pos, int));
static void reseat_1 P_ ((struct it *, struct text_pos, int));
Set w->phys_cursor_width to width of phys cursor.
*/
-int
-get_phys_cursor_geometry (w, row, glyph, heightp)
+void
+get_phys_cursor_geometry (w, row, glyph, xp, yp, heightp)
struct window *w;
struct glyph_row *row;
struct glyph *glyph;
- int *heightp;
+ int *xp, *yp, *heightp;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
- int y, wd, h, h0, y0;
+ int x, y, wd, h, h0, y0;
/* Compute the width of the rectangle to draw. If on a stretch
glyph, and `x-stretch-block-cursor' is nil, don't draw a
#ifdef HAVE_NTGUI
wd++; /* Why? */
#endif
+
+ x = w->phys_cursor.x;
+ if (x < 0)
+ {
+ wd += x;
+ x = 0;
+ }
+
if (glyph->type == STRETCH_GLYPH
&& !x_stretch_cursor_p)
wd = min (FRAME_COLUMN_WIDTH (f), wd);
}
}
+ *xp = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
+ *yp = WINDOW_TO_FRAME_PIXEL_Y (w, y);
*heightp = h;
- return WINDOW_TO_FRAME_PIXEL_Y (w, y);
}
/*
also ``processed'' overlay strings at ZV. */
while (it->sp)
pop_it (it);
- it->current.overlay_string_index = -1;
- it->method = GET_FROM_BUFFER;
+ 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;
}
if (handled == HANDLED_RECOMPUTE_PROPS)
break;
else if (handled == HANDLED_RETURN)
- return;
+ {
+ /* 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;
+ handled = HANDLED_RECOMPUTE_PROPS;
+ break;
+ }
else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
handle_overlay_change_p = 0;
}
struct face *face = FACE_FROM_ID (it->f, face_id);
c = string_char_and_length (p, rest, &len);
- face_id = FACE_FOR_CHAR (it->f, face, c);
+ face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), it->string);
}
}
else
{
int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
struct face *face = FACE_FROM_ID (it->f, face_id);
- face_id = FACE_FOR_CHAR (it->f, face, c);
+ face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), Qnil);
}
}
{
Lisp_Object form;
Lisp_Object location, value;
- struct text_pos start_pos;
+ struct text_pos start_pos, save_pos;
int valid_p;
/* If SPEC is a list of the form `(when FORM . VALUE)', evaluate FORM.
{
Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
int face_id2 = lookup_derived_face (it->f, face_name,
- 'A', FRINGE_FACE_ID, 0);
+ FRINGE_FACE_ID, 0);
if (face_id2 >= 0)
face_id = face_id2;
}
/* Save current settings of IT so that we can restore them
when we are finished with the glyph property value. */
+ save_pos = it->position;
+ it->position = *position;
push_it (it);
+ it->position = save_pos;
it->area = TEXT_AREA;
it->what = IT_IMAGE;
{
/* Save current settings of IT so that we can restore them
when we are finished with the glyph property value. */
+ save_pos = it->position;
+ it->position = *position;
push_it (it);
+ it->position = save_pos;
if (NILP (location))
it->area = TEXT_AREA;
`composition' property
***********************************************************************/
+static enum prop_handled
+handle_auto_composed_prop (it)
+ struct it *it;
+{
+ enum prop_handled handled = HANDLED_NORMALLY;
+
+ if (FUNCTIONP (Vauto_composition_function))
+ {
+ Lisp_Object val;
+ EMACS_INT pos, this_pos;
+
+ if (STRINGP (it->string))
+ pos = IT_STRING_CHARPOS (*it);
+ else
+ pos = IT_CHARPOS (*it);
+ this_pos = pos;
+
+ val =Fget_char_property (make_number (pos), Qauto_composed, it->string);
+ if (! NILP (val))
+ {
+ Lisp_Object limit = Qnil, next;
+
+ /* As Fnext_single_char_property_change is very slow, we
+ limit the search to the current line. */
+ if (STRINGP (it->string))
+ limit = make_number (SCHARS (it->string));
+ else
+ limit = make_number (find_next_newline_no_quit (pos, 1));
+
+ next = (Fnext_single_property_change
+ (make_number (pos), Qauto_composed, it->string, limit));
+ if (XINT (next) < XINT (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. */
+ int charpos = XINT (next) - 1, bytepos, c;
+
+ if (STRINGP (it->string))
+ {
+ bytepos = string_char_to_byte (it->string, charpos);
+ c = SDATA (it->string)[bytepos];
+ }
+ else
+ {
+ bytepos = CHAR_TO_BYTE (charpos);
+ c = FETCH_BYTE (bytepos);
+ }
+ if (c != '\n')
+ /* If the last character is not newline, it may be
+ composed with the following characters. */
+ val = Qnil, pos = charpos + 1;
+ }
+ }
+ if (NILP (val))
+ {
+ int count = SPECPDL_INDEX ();
+ Lisp_Object args[4];
+
+ args[0] = Vauto_composition_function;
+ specbind (Qauto_composition_function, Qnil);
+ args[1] = make_number (pos);
+ args[2] = it->string;
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend)
+ {
+ struct face *face = FACE_FROM_ID (it->f, it->face_id);
+ int c;
+
+ if (STRINGP (it->string))
+ {
+ EMACS_INT pos_byte = IT_STRING_BYTEPOS (*it);
+ const unsigned char *s = SDATA (it->string) + pos_byte;
+
+ if (STRING_MULTIBYTE (it->string))
+ it->c = STRING_CHAR (s, 0);
+ else
+ it->c = *s;
+ }
+ else
+ {
+ EMACS_INT pos_byte = IT_BYTEPOS (*it);
+
+ it->c = FETCH_CHAR (pos_byte);
+ }
+ args[3] = font_at (it->c, this_pos, face, it->w, it->string);
+ }
+ else
+#endif /* USE_FONT_BACKEND */
+ args[3] = Qnil;
+ safe_call (4, args);
+ unbind_to (count, Qnil);
+
+ if (this_pos == pos)
+ {
+ val = Fget_char_property (args[1], Qauto_composed, it->string);
+ /* Return HANDLED_RECOMPUTE_PROPS only if function composed
+ something. This avoids an endless loop if they failed to
+ fontify the text for which reason ever. */
+ if (! NILP (val))
+ handled = HANDLED_RECOMPUTE_PROPS;
+ }
+ else
+ handled = HANDLED_RECOMPUTE_PROPS;
+ }
+ }
+
+ return handled;
+}
+
/* Set up iterator IT from `composition' property at its current
position. Called from handle_stop. */
struct it *it;
{
Lisp_Object prop, string;
- int pos, pos_byte, end;
+ EMACS_INT pos, pos_byte, start, end;
enum prop_handled handled = HANDLED_NORMALLY;
if (STRINGP (it->string))
/* If there's a valid composition and point is not inside of the
composition (in the case that the composition is from the current
buffer), draw a glyph composed from the composition components. */
- if (find_composition (pos, -1, &pos, &end, &prop, string)
- && COMPOSITION_VALID_P (pos, end, prop)
- && (STRINGP (it->string) || (PT <= pos || PT >= end)))
+ if (find_composition (pos, -1, &start, &end, &prop, string)
+ && COMPOSITION_VALID_P (start, end, prop)
+ && (STRINGP (it->string) || (PT <= start || PT >= end)))
{
- int id = get_composition_id (pos, pos_byte, end - pos, prop, string);
+ int id;
+
+ if (start != pos)
+ {
+ if (STRINGP (it->string))
+ pos_byte = string_char_to_byte (it->string, start);
+ else
+ pos_byte = CHAR_TO_BYTE (start);
+ }
+ id = get_composition_id (start, pos_byte, end - start, prop, string);
if (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);
+#ifdef USE_FONT_BACKEND
+ if (composition_table[id]->method == COMPOSITION_WITH_GLYPH_STRING)
+ {
+ Lisp_Object lgstring = AREF (XHASH_TABLE (composition_hash_table)
+ ->key_and_value,
+ cmp->hash_index * 2);
+ Lisp_Object font_object = LGSTRING_FONT (lgstring);
+ struct font *font = XSAVE_VALUE (font_object)->pointer;
+ struct face *face = FACE_FROM_ID (it->f, it->face_id);
+
+ it->face_id = face_for_font (it->f, font, face);
+ it->c = ' ';
+ }
+ else
+#endif /* USE_FONT_BACKEND */
/* For a terminal, draw only the first character of the
components. */
it->c = COMPOSITION_GLYPH (composition_table[id], 0);
it->len = (STRINGP (it->string)
? string_char_to_byte (it->string, end)
: CHAR_TO_BYTE (end)) - pos_byte;
- it->stop_charpos = end;
handled = HANDLED_RETURN;
}
}
int display_ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
pop_it (it);
- xassert (it->stop_charpos >= BEGV
- && it->stop_charpos <= it->end_charpos);
- it->string = Qnil;
+ xassert (it->sp > 0
+ || it->method == GET_FROM_COMPOSITION
+ || (NILP (it->string)
+ && it->method == GET_FROM_BUFFER
+ && it->stop_charpos >= BEGV
+ && it->stop_charpos <= it->end_charpos));
it->current.overlay_string_index = -1;
- SET_TEXT_POS (it->current.string_pos, -1, -1);
it->n_overlay_strings = 0;
- it->method = GET_FROM_BUFFER;
/* If we're at the end of the buffer, record that we have
processed the overlay strings there already, so that
least one overlay string was found. */
static int
-get_overlay_strings (it, charpos)
+get_overlay_strings_1 (it, charpos, compute_stop_p)
struct it *it;
int charpos;
{
/* Make sure we know settings in current_buffer, so that we can
restore meaningful values when we're done with the overlay
strings. */
- compute_stop_pos (it);
+ if (compute_stop_p)
+ compute_stop_pos (it);
xassert (it->face_id >= 0);
/* Save IT's settings. They are restored after all overlay
strings have been processed. */
- xassert (it->sp == 0);
+ xassert (!compute_stop_p || it->sp == 0);
push_it (it);
/* Set up IT to deliver display elements from the first overlay
it->end_charpos = SCHARS (it->string);
it->multibyte_p = STRING_MULTIBYTE (it->string);
it->method = GET_FROM_STRING;
+ return 1;
}
- else
- {
- it->string = Qnil;
- it->current.overlay_string_index = -1;
- it->method = GET_FROM_BUFFER;
- }
+
+ it->current.overlay_string_index = -1;
+ return 0;
+}
+
+static int
+get_overlay_strings (it, charpos)
+ struct it *it;
+ int charpos;
+{
+ it->string = Qnil;
+ it->method = GET_FROM_BUFFER;
+
+ (void) get_overlay_strings_1 (it, charpos, 1);
CHECK_IT (it);
{
struct iterator_stack_entry *p;
- xassert (it->sp < 2);
+ xassert (it->sp < IT_STACK_SIZE);
p = it->stack + it->sp;
p->stop_charpos = it->stop_charpos;
xassert (it->face_id >= 0);
p->face_id = it->face_id;
p->string = it->string;
- p->pos = it->current;
+ p->method = it->method;
+ switch (p->method)
+ {
+ case GET_FROM_IMAGE:
+ p->u.image.object = it->object;
+ 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;
+ }
+ p->position = it->position;
+ p->current = it->current;
p->end_charpos = it->end_charpos;
p->string_nchars = it->string_nchars;
p->area = it->area;
p->multibyte_p = it->multibyte_p;
- p->slice = it->slice;
p->space_width = it->space_width;
p->font_height = it->font_height;
p->voffset = it->voffset;
p = it->stack + it->sp;
it->stop_charpos = p->stop_charpos;
it->face_id = p->face_id;
+ it->current = p->current;
+ it->position = p->position;
it->string = p->string;
- it->current = p->pos;
+ if (NILP (it->string))
+ SET_TEXT_POS (it->current.string_pos, -1, -1);
+ it->method = p->method;
+ switch (it->method)
+ {
+ case GET_FROM_IMAGE:
+ it->image_id = p->u.image.image_id;
+ 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;
+ case GET_FROM_BUFFER:
+ it->object = it->w->buffer;
+ break;
+ case GET_FROM_STRING:
+ it->object = it->string;
+ break;
+ }
it->end_charpos = p->end_charpos;
it->string_nchars = p->string_nchars;
it->area = p->area;
it->multibyte_p = p->multibyte_p;
- it->slice = p->slice;
it->space_width = p->space_width;
it->font_height = p->font_height;
it->voffset = p->voffset;
while (IT_CHARPOS (*it) > BEGV)
{
back_to_previous_line_start (it);
+
if (IT_CHARPOS (*it) <= BEGV)
break;
continue;
}
- /* If newline has a display property that replaces the newline with something
- else (image or text), find start of overlay or interval and continue search
- from that point. */
- if (IT_CHARPOS (*it) > BEGV)
- {
- struct it it2 = *it;
- int pos;
- int beg, end;
- Lisp_Object val, overlay;
-
- pos = --IT_CHARPOS (it2);
- --IT_BYTEPOS (it2);
- it2.sp = 0;
- if (handle_display_prop (&it2) == HANDLED_RETURN
- && !NILP (val = get_char_property_and_overlay
- (make_number (pos), Qdisplay, Qnil, &overlay))
- && (OVERLAYP (overlay)
- ? (beg = OVERLAY_POSITION (OVERLAY_START (overlay)))
- : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
- {
- if (beg < BEGV)
- beg = BEGV;
- IT_CHARPOS (*it) = beg;
- IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
- continue;
- }
- }
+ if (IT_CHARPOS (*it) <= BEGV)
+ break;
- break;
+ {
+ struct it it2;
+ int pos;
+ int beg, end;
+ Lisp_Object val, overlay;
+
+ /* If newline is part of a composition, continue from start of composition */
+ if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil)
+ && beg < IT_CHARPOS (*it))
+ goto replaced;
+
+ /* If newline is replaced by a display property, find start of overlay
+ or interval and continue search from that point. */
+ it2 = *it;
+ pos = --IT_CHARPOS (it2);
+ --IT_BYTEPOS (it2);
+ it2.sp = 0;
+ if (handle_display_prop (&it2) == HANDLED_RETURN
+ && !NILP (val = get_char_property_and_overlay
+ (make_number (pos), Qdisplay, Qnil, &overlay))
+ && (OVERLAYP (overlay)
+ ? (beg = OVERLAY_POSITION (OVERLAY_START (overlay)))
+ : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
+ goto replaced;
+
+ /* Newline is not replaced by anything -- so we are done. */
+ break;
+
+ replaced:
+ if (beg < BEGV)
+ beg = BEGV;
+ IT_CHARPOS (*it) = beg;
+ IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
+ }
}
+ it->continuation_lines_width = 0;
+
xassert (IT_CHARPOS (*it) >= BEGV);
xassert (IT_CHARPOS (*it) == BEGV
|| FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
it->current.pos = it->position = pos;
- XSETBUFFER (it->object, current_buffer);
it->end_charpos = ZV;
it->dpvec = NULL;
it->current.dpvec_index = -1;
IT_STRING_BYTEPOS (*it) = -1;
it->string = Qnil;
it->method = GET_FROM_BUFFER;
- /* RMS: I added this to fix a bug in move_it_vertically_backward
- where it->area continued to relate to the starting point
- for the backward motion. Bug report from
- Nick Roberts <nick@nick.uklinux.net> on 19 May 2003.
- However, I am not sure whether reseat still does the right thing
- in general after this change. */
+ it->object = it->w->buffer;
it->area = TEXT_AREA;
it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
it->sp = 0;
+ it->string_from_display_prop_p = 0;
it->face_before_selective_p = 0;
if (set_stop_p)
the translation. This could easily be changed but I
don't believe that it is worth doing.
- If it->multibyte_p is nonzero, eight-bit characters and
- non-printable multibyte characters are also translated to
- octal form.
+ If it->multibyte_p is nonzero, non-printable non-ASCII
+ characters are also translated to octal form.
If it->multibyte_p is zero, eight-bit characters that
don't have corresponding multibyte char code are also
translated to octal form. */
else if ((it->c < ' '
- && (it->area != TEXT_AREA
- /* In mode line, treat \n like other crl chars. */
- || (it->c != '\t'
- && it->glyph_row && it->glyph_row->mode_line_p)
- || (it->c != '\n' && it->c != '\t')))
- || (it->multibyte_p
- ? ((it->c >= 127
- && it->len == 1)
- || !CHAR_PRINTABLE_P (it->c)
+ ? (it->area != TEXT_AREA
+ /* In mode line, treat \n, \t like other crl chars. */
+ || (it->c != '\t'
+ && it->glyph_row && it->glyph_row->mode_line_p)
+ || (it->c != '\n' && it->c != '\t'))
+ : (it->multibyte_p
+ ? (!CHAR_PRINTABLE_P (it->c)
|| (!NILP (Vnobreak_char_display)
- && (it->c == 0x8a0 || it->c == 0x8ad
- || it->c == 0x920 || it->c == 0x92d
- || it->c == 0xe20 || it->c == 0xe2d
- || it->c == 0xf20 || it->c == 0xf2d)))
+ && (it->c == 0xA0 /* NO-BREAK SPACE */
+ || it->c == 0xAD /* SOFT HYPHEN */)))
: (it->c >= 127
- && (!unibyte_display_via_language_environment
- || it->c == unibyte_char_to_multibyte (it->c)))))
+ && (! unibyte_display_via_language_environment
+ || (UNIBYTE_CHAR_HAS_MULTIBYTE_P (it->c)))))))
{
/* IT->c is a control character which must be displayed
either as '\003' or as `^C' where the '\\' and '^'
highlighting. */
if (EQ (Vnobreak_char_display, Qt)
- && (it->c == 0x8a0 || it->c == 0x920
- || it->c == 0xe20 || it->c == 0xf20))
+ && it->c == 0xA0)
{
/* Merge the no-break-space face into the current face. */
face_id = merge_faces (it->f, Qnobreak_space, 0,
highlighting. */
if (EQ (Vnobreak_char_display, Qt)
- && (it->c == 0x8ad || it->c == 0x92d
- || it->c == 0xe2d || it->c == 0xf2d))
+ && it->c == 0xAD)
{
g = it->c = '-';
XSETINT (it->ctl_chars[0], g);
/* Handle non-break space and soft hyphen
with the escape glyph. */
- if (it->c == 0x8a0 || it->c == 0x8ad
- || it->c == 0x920 || it->c == 0x92d
- || it->c == 0xe20 || it->c == 0xe2d
- || it->c == 0xf20 || it->c == 0xf2d)
+ if (it->c == 0xA0 || it->c == 0xAD)
{
XSETINT (it->ctl_chars[0], escape_glyph);
- g = it->c = ((it->c & 0xf) == 0 ? ' ' : '-');
+ g = it->c = (it->c == 0xA0 ? ' ' : '-');
XSETINT (it->ctl_chars[1], g);
ctl_len = 2;
goto display_control;
int i;
/* Set IT->ctl_chars[0] to the glyph for `\\'. */
- if (SINGLE_BYTE_CHAR_P (it->c))
- str[0] = it->c, len = 1;
+ if (CHAR_BYTE8_P (it->c))
+ {
+ str[0] = CHAR_TO_BYTE8 (it->c);
+ len = 1;
+ }
+ else if (it->c < 256)
+ {
+ str[0] = it->c;
+ len = 1;
+ }
else
{
- len = CHAR_STRING_NO_SIGNAL (it->c, str);
- if (len < 0)
- {
- /* It's an invalid character, which shouldn't
- happen actually, but due to bugs it may
- happen. Let's print the char as is, there's
- not much meaningful we can do with it. */
- str[0] = it->c;
- str[1] = it->c >> 8;
- str[2] = it->c >> 16;
- str[3] = it->c >> 24;
- len = 4;
- }
+ /* It's an invalid character, which shouldn't
+ happen actually, but due to bugs it may
+ happen. Let's print the char as is, there's
+ not much meaningful we can do with it. */
+ str[0] = it->c;
+ str[1] = it->c >> 8;
+ str[2] = it->c >> 16;
+ str[3] = it->c >> 24;
+ len = 4;
}
for (i = 0; i < len; i++)
&& FRAME_WINDOW_P (it->f))
{
struct face *face = FACE_FROM_ID (it->f, it->face_id);
- it->face_id = FACE_FOR_CHAR (it->f, face, it->c);
+ 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);
}
}
case GET_FROM_COMPOSITION:
xassert (it->cmp_id >= 0 && it->cmp_id < n_compositions);
- if (STRINGP (it->string))
+ 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;
- it->method = GET_FROM_STRING;
goto consider_string_end;
}
- else
+ else if (it->method == GET_FROM_BUFFER)
{
IT_BYTEPOS (*it) += it->len;
IT_CHARPOS (*it) += it->cmp_len;
- it->method = GET_FROM_BUFFER;
}
break;
else if (STRINGP (it->string))
it->method = GET_FROM_STRING;
else
- it->method = GET_FROM_BUFFER;
+ {
+ it->method = GET_FROM_BUFFER;
+ it->object = it->w->buffer;
+ }
it->dpvec = NULL;
it->current.dpvec_index = -1;
&& it->sp > 0)
{
pop_it (it);
- if (STRINGP (it->string))
+ if (it->method == GET_FROM_STRING)
goto consider_string_end;
- it->method = GET_FROM_BUFFER;
}
}
break;
if the `display' property takes up the whole string. */
xassert (it->sp > 0);
pop_it (it);
- it->image_id = 0;
- if (STRINGP (it->string))
- {
- it->method = GET_FROM_STRING;
- goto consider_string_end;
- }
- it->method = GET_FROM_BUFFER;
+ if (it->method == GET_FROM_STRING)
+ goto consider_string_end;
break;
default:
}
}
- /* Record what we have and where it came from. Note that we store a
- buffer position in IT->position although it could arguably be a
- string position. */
+ /* Record what we have and where it came from. */
it->what = IT_CHARACTER;
it->object = it->string;
it->position = position;
setting face_before_selective_p. */
it->saved_face_id = it->face_id;
it->method = GET_FROM_BUFFER;
+ it->object = it->w->buffer;
reseat_at_next_visible_line_start (it, 1);
it->face_before_selective_p = 1;
}
it->position = (STRINGP (it->string)
? it->current.string_pos
: it->current.pos);
+ if (STRINGP (it->string))
+ it->object = it->string;
+ else
+ it->object = it->w->buffer;
return 1;
}
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. */
+ line_height = it->max_ascent + it->max_descent;
+ if (to_y >= it->current_y
+ && to_y < it->current_y + line_height)
+ {
+ reached = 6;
+ break;
+ }
it_backup = *it;
TRACE_MOVE ((stderr, "move_it: from %d\n", IT_CHARPOS (*it)));
skip2 = move_it_in_display_line_to (it, to_charpos, -1,
if (reached)
break;
}
+ else if (BUFFERP (it->object)
+ && it->method == GET_FROM_BUFFER
+ && IT_CHARPOS (*it) >= to_charpos)
+ skip = MOVE_POS_MATCH_OR_ZV;
else
skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
for (i = 0; i < nbytes; i += char_bytes)
{
c = string_char_and_length (m + i, nbytes - i, &char_bytes);
- work[0] = (SINGLE_BYTE_CHAR_P (c)
+ work[0] = (ASCII_CHAR_P (c)
? c
: multibyte_char_to_unibyte (c, Qnil));
insert_1_both (work, 1, 1, 1, 0, 0);
for the *Message* buffer. */
for (i = 0; i < nbytes; i++)
{
- c = unibyte_char_to_multibyte (msg[i]);
+ c = msg[i];
+ c = unibyte_char_to_multibyte (c);
char_bytes = CHAR_STRING (c, str);
insert_1_both (str, 1, char_bytes, 1, 0, 0);
}
for (i = 0; i < nbytes; i += n)
{
c = string_char_and_length (s + i, nbytes - i, &n);
- work[0] = (SINGLE_BYTE_CHAR_P (c)
+ work[0] = (ASCII_CHAR_P (c)
? c
: multibyte_char_to_unibyte (c, Qnil));
insert_1_both (work, 1, 1, 1, 0, 0);
/* Convert a single-byte string to multibyte. */
for (i = 0; i < nbytes; i++)
{
- c = unibyte_char_to_multibyte (msg[i]);
+ c = msg[i];
+ c = unibyte_char_to_multibyte (c);
n = CHAR_STRING (c, str);
insert_1_both (str, 1, n, 1, 0, 0);
}
{
Lisp_Object tail, frame;
int count = SPECPDL_INDEX ();
+ /* 1 means that update_menu_bar has run its hooks
+ so any further calls to update_menu_bar shouldn't do so again. */
+ int menu_bar_hooks_run = 0;
record_unwind_save_match_data ();
}
GCPRO1 (tail);
- update_menu_bar (f, 0);
+ 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;
}
else
{
struct frame *sf = SELECTED_FRAME ();
- update_menu_bar (sf, 1);
+ 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
}
before we start to fill in any display lines, because it can call
eval.
- If SAVE_MATCH_DATA is non-zero, we must save and restore it here. */
+ If SAVE_MATCH_DATA is non-zero, we must save and restore it here.
-static void
-update_menu_bar (f, save_match_data)
+ If HOOKS_RUN is 1, that means a previous call to update_menu_bar
+ already ran the menu bar hooks for this redisplay, so there
+ is no need to run them again. The return value is the
+ updated value of this flag, to pass to the next call. */
+
+static int
+update_menu_bar (f, save_match_data, hooks_run)
struct frame *f;
int save_match_data;
+ int hooks_run;
{
Lisp_Object window;
register struct window *w;
specbind (Qoverriding_local_map, Qnil);
}
- /* Run the Lucid hook. */
- safe_run_hooks (Qactivate_menubar_hook);
+ if (!hooks_run)
+ {
+ /* Run the Lucid hook. */
+ safe_run_hooks (Qactivate_menubar_hook);
+
+ /* If it has changed current-menubar from previous value,
+ really recompute the menu-bar from the value. */
+ if (! NILP (Vlucid_menu_bar_dirty_flag))
+ call0 (Qrecompute_lucid_menubar);
+
+ safe_run_hooks (Qmenu_bar_update_hook);
- /* If it has changed current-menubar from previous value,
- really recompute the menu-bar from the value. */
- if (! NILP (Vlucid_menu_bar_dirty_flag))
- call0 (Qrecompute_lucid_menubar);
+ hooks_run = 1;
+ }
- safe_run_hooks (Qmenu_bar_update_hook);
FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
/* Redisplay the menu bar in case we changed it. */
set_buffer_internal_1 (prev);
}
}
+
+ return hooks_run;
}
&new_n_tool_bar);
/* Redisplay the tool-bar if we changed it. */
- if (NILP (Fequal (new_tool_bar, f->tool_bar_items)))
+ if (new_n_tool_bar != f->n_tool_bar_items
+ || NILP (Fequal (new_tool_bar, f->tool_bar_items)))
{
/* Redisplay that happens asynchronously due to an expose event
may access f->tool_bar_items. Make sure we update both
while (it->current_x < max_x)
{
- int x_before, x, n_glyphs_before, i, nglyphs;
+ int x, n_glyphs_before, i, nglyphs;
+ struct it it_before;
/* Get the next display element. */
if (!get_next_display_element (it))
}
/* Produce glyphs. */
- x_before = it->current_x;
- n_glyphs_before = it->glyph_row->used[TEXT_AREA];
+ n_glyphs_before = row->used[TEXT_AREA];
+ it_before = *it;
+
PRODUCE_GLYPHS (it);
- nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
+ nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
i = 0;
- x = x_before;
+ x = it_before.current_x;
while (i < nglyphs)
{
struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
if (x + glyph->pixel_width > max_x)
{
- /* Glyph doesn't fit on line. */
- it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
- it->current_x = x;
+ /* Glyph doesn't fit on line. Backtrack. */
+ row->used[TEXT_AREA] = n_glyphs_before;
+ *it = it_before;
+ /* If this is the only glyph on this line, it will never fit on the
+ toolbar, so skip it. But ensure there is at least one glyph,
+ so we don't accidentally disable the tool-bar. */
+ if (n_glyphs_before == 0
+ && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
+ break;
goto out;
}
/* Make line the desired height and center it vertically. */
if ((height -= it->max_ascent + it->max_descent) > 0)
{
+ /* Don't add more than one line height. */
+ height %= FRAME_LINE_HEIGHT (it->f);
it->max_ascent += height / 2;
it->max_descent += (height + 1) / 2;
}
}
+/* Max tool-bar height. */
+
+#define MAX_FRAME_TOOL_BAR_HEIGHT(f) \
+ ((FRAME_LINE_HEIGHT (f) * FRAME_LINES (f)))
+
/* Value is the number of screen lines needed to make all tool-bar
items of frame F visible. The number of actual rows needed is
returned in *N_ROWS if non-NULL. */
{
struct window *w = XWINDOW (f->tool_bar_window);
struct it it;
+ /* tool_bar_lines_needed is called from redisplay_tool_bar after building
+ the desired matrix, so use (unused) mode-line row as temporary row to
+ avoid destroying the first tool-bar row. */
+ struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
/* Initialize an iterator for iteration over
F->desired_tool_bar_string in the tool-bar window of frame F. */
- init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
+ init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
it.first_visible_x = 0;
it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
while (!ITERATOR_AT_END_P (&it))
{
- it.glyph_row = w->desired_matrix->rows;
- clear_glyph_row (it.glyph_row);
+ clear_glyph_row (temp_row);
+ it.glyph_row = temp_row;
display_tool_bar_line (&it, -1);
}
+ clear_glyph_row (temp_row);
/* f->n_tool_bar_rows == 0 means "unknown"; -1 means no tool-bar. */
if (n_rows)
reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
if (f->n_tool_bar_rows == 0)
- (void)tool_bar_lines_needed (f, &f->n_tool_bar_rows);
+ {
+ int nlines;
+
+ if ((nlines = tool_bar_lines_needed (f, &f->n_tool_bar_rows),
+ nlines != WINDOW_TOTAL_LINES (w)))
+ {
+ extern Lisp_Object Qtool_bar_lines;
+ Lisp_Object frame;
+ int old_height = WINDOW_TOTAL_LINES (w);
+
+ XSETFRAME (frame, f);
+ Fmodify_frame_parameters (frame,
+ Fcons (Fcons (Qtool_bar_lines,
+ make_number (nlines)),
+ Qnil));
+ if (WINDOW_TOTAL_LINES (w) != old_height)
+ {
+ clear_glyph_matrix (w->desired_matrix);
+ fonts_changed_p = 1;
+ return 1;
+ }
+ }
+ }
/* Display as many lines as needed to display all tool-bar items. */
border = 0;
rows = f->n_tool_bar_rows;
- height = (it.last_visible_y - border) / rows;
+ height = max (1, (it.last_visible_y - border) / rows);
extra = it.last_visible_y - border - height * rows;
while (it.current_y < it.last_visible_y)
if (auto_resize_tool_bars_p)
{
- int nlines;
+ int nlines, nrows;
+ int max_tool_bar_height = MAX_FRAME_TOOL_BAR_HEIGHT (f);
/* If we couldn't display everything, change the tool-bar's
- height. */
- if (IT_STRING_CHARPOS (it) < it.end_charpos)
+ height if there is room for more. */
+ if (IT_STRING_CHARPOS (it) < it.end_charpos
+ && it.current_y < max_tool_bar_height)
change_height_p = 1;
+ row = it.glyph_row - 1;
+
/* If there are blank lines at the end, except for a partially
visible blank line at the end that is smaller than
FRAME_LINE_HEIGHT, change the tool-bar's height. */
- row = it.glyph_row - 1;
if (!row->displays_text_p
&& row->height >= FRAME_LINE_HEIGHT (f))
change_height_p = 1;
/* If row displays tool-bar items, but is partially visible,
change the tool-bar's height. */
if (row->displays_text_p
- && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
+ && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y
+ && MATRIX_ROW_BOTTOM_Y (row) < max_tool_bar_height)
change_height_p = 1;
/* Resize windows as needed by changing the `tool-bar-lines'
frame parameter. */
if (change_height_p
- && (nlines = tool_bar_lines_needed (f, &f->n_tool_bar_rows),
+ && (nlines = tool_bar_lines_needed (f, &nrows),
nlines != WINDOW_TOTAL_LINES (w)))
{
extern Lisp_Object Qtool_bar_lines;
int old_height = WINDOW_TOTAL_LINES (w);
XSETFRAME (frame, f);
- clear_glyph_matrix (w->desired_matrix);
Fmodify_frame_parameters (frame,
Fcons (Fcons (Qtool_bar_lines,
make_number (nlines)),
Qnil));
if (WINDOW_TOTAL_LINES (w) != old_height)
- fonts_changed_p = 1;
+ {
+ clear_glyph_matrix (w->desired_matrix);
+ f->n_tool_bar_rows = nrows;
+ fonts_changed_p = 1;
+ }
}
}
struct buffer *prev_buf, *buf;
int prev_pt, pt;
{
- int start, end;
+ EMACS_INT start, end;
Lisp_Object prop;
Lisp_Object buffer;
struct Lisp_Char_Table *dp;
int c;
{
- int code[4], i;
Lisp_Object val;
- if (SINGLE_BYTE_CHAR_P (c))
- return (dp->contents[c]);
-
- SPLIT_CHAR (c, code[0], code[1], code[2]);
- if (code[1] < 32)
- code[1] = -1;
- else if (code[2] < 32)
- code[2] = -1;
-
- /* Here, the possible range of code[0] (== charset ID) is
- 128..max_charset. Since the top level char table contains data
- for multibyte characters after 256th element, we must increment
- code[0] by 128 to get a correct index. */
- code[0] += 128;
- code[3] = -1; /* anchor */
-
- for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val))
+ if (ASCII_CHAR_P (c))
{
- val = dp->contents[code[i]];
- if (!SUB_CHAR_TABLE_P (val))
- return (NILP (val) ? dp->defalt : val);
+ val = dp->ascii;
+ if (SUB_CHAR_TABLE_P (val))
+ val = XSUB_CHAR_TABLE (val)->contents[c];
}
+ else
+ {
+ Lisp_Object table;
- /* Here, val is a sub char table. We return the default value of
- it. */
- return (dp->defalt);
+ XSETCHAR_TABLE (table, dp);
+ val = char_table_ref (table, c);
+ }
+ if (NILP (val))
+ val = dp->defalt;
+ return val;
}
/* Set cursor position of W. PT is assumed to be displayed in ROW.
DELTA is the number of bytes by which positions recorded in ROW
- differ from current buffer positions. */
+ differ from current buffer positions.
-void
+ Return 0 if cursor is not on this row. 1 otherwise. */
+
+int
set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
struct window *w;
struct glyph_row *row;
}
else
{
- string_before_pos = last_pos;
- string_start = glyph;
- string_start_x = x;
+ if (string_start == NULL)
+ {
+ string_before_pos = last_pos;
+ string_start = glyph;
+ string_start_x = x;
+ }
/* Skip all glyphs from string. */
do
{
glyph on point by scanning from string_start again. */
Lisp_Object limit;
Lisp_Object string;
+ struct glyph *stop = glyph;
int pos;
limit = make_number (pt_old + 1);
- end = glyph;
glyph = string_start;
x = string_start_x;
string = glyph->object;
pos = string_buffer_position (w, string, string_before_pos);
/* If STRING is from overlay, LAST_POS == 0. We skip such glyphs
because we always put cursor after overlay strings. */
- while (pos == 0 && glyph < end)
+ while (pos == 0 && glyph < stop)
{
string = glyph->object;
- SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
- if (glyph < end)
+ SKIP_GLYPHS (glyph, stop, x, EQ (glyph->object, string));
+ if (glyph < stop)
pos = string_buffer_position (w, glyph->object, string_before_pos);
}
- while (glyph < end)
+ while (glyph < stop)
{
pos = XINT (Fnext_single_char_property_change
(make_number (pos), Qdisplay, Qnil, limit));
break;
/* Skip glyphs from the same string. */
string = glyph->object;
- SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
+ SKIP_GLYPHS (glyph, stop, x, EQ (glyph->object, string));
/* Skip glyphs from an overlay. */
- while (glyph < end
+ while (glyph < stop
&& ! string_buffer_position (w, glyph->object, pos))
{
string = glyph->object;
- SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
+ SKIP_GLYPHS (glyph, stop, x, EQ (glyph->object, string));
}
}
+
+ /* If we reached the end of the line, and end was from a string,
+ cursor is not on this line. */
+ if (glyph == end && row->continued_p)
+ return 0;
}
w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
else
CHARPOS (this_line_start_pos) = 0;
}
+
+ return 1;
}
rc = CURSOR_MOVEMENT_MUST_SCROLL;
else
{
- set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
- rc = CURSOR_MOVEMENT_SUCCESS;
+ do
+ {
+ if (set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0))
+ {
+ rc = CURSOR_MOVEMENT_SUCCESS;
+ break;
+ }
+ ++row;
+ }
+ while (MATRIX_ROW_BOTTOM_Y (row) < last_y
+ && MATRIX_ROW_START_CHARPOS (row) == PT
+ && cursor_row_p (w, row));
}
}
}
/* IT may overshoot PT if text at PT is invisible. */
else if (IT_CHARPOS (it) > PT && CHARPOS (startp) <= PT)
w->force_start = Qt;
-
-
}
/* Handle case where place to start displaying has been specified,
|| (XFASTINT (w->last_modified) >= MODIFF
&& XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
{
+
+ /* If first window line is a continuation line, and window start
+ is inside the modified region, but the first change is before
+ current window start, we must select a new window start.*/
+ if (NILP (w->start_at_line_beg)
+ && CHARPOS (startp) > BEGV)
+ {
+ /* Make sure beg_unchanged and end_unchanged are up to date.
+ Do it only if buffer has really changed. This may or may
+ not have been done by try_window_id (see which) already. */
+ if (MODIFF > SAVE_MODIFF
+ /* This seems to happen sometimes after saving a buffer. */
+ || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
+ {
+ if (GPT - BEG < BEG_UNCHANGED)
+ BEG_UNCHANGED = GPT - BEG;
+ if (Z - GPT < END_UNCHANGED)
+ END_UNCHANGED = Z - GPT;
+ }
+
+ if (CHARPOS (startp) > BEG + BEG_UNCHANGED
+ && CHARPOS (startp) <= Z - END_UNCHANGED)
+ {
+ /* There doesn't seems to be a simple way to find a new
+ window start that is near the old window start, so
+ we just recenter. */
+ goto recenter;
+ }
+ }
+
#if GLYPH_DEBUG
debug_method_add (w, "same window start");
#endif
glyph->left_box_line_p,
glyph->right_box_line_p);
}
+ else if (glyph->type == COMPOSITE_GLYPH)
+ {
+ fprintf (stderr,
+ " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
+ glyph - row->glyphs[TEXT_AREA],
+ '+',
+ glyph->charpos,
+ (BUFFERP (glyph->object)
+ ? 'B'
+ : (STRINGP (glyph->object)
+ ? 'S'
+ : '-')),
+ glyph->pixel_width,
+ glyph->u.cmp_id,
+ '.',
+ glyph->face_id,
+ glyph->left_box_line_p,
+ glyph->right_box_line_p);
+ }
}
else if (it->face_before_selective_p)
it->face_id = it->saved_face_id;
face = FACE_FROM_ID (it->f, it->face_id);
- it->face_id = FACE_FOR_CHAR (it->f, face, 0);
+ it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
PRODUCE_GLYPHS (it);
ASCII face. This will be automatically undone the next time
get_next_display_element returns a multibyte character. Note
that the character will always be single byte in unibyte text. */
- if (!SINGLE_BYTE_CHAR_P (it->c))
+ if (!ASCII_CHAR_P (it->c))
{
- it->face_id = FACE_FOR_CHAR (f, face, 0);
+ it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
}
if (FRAME_WINDOW_P (f))
&& glyph->u.ch == ' '))
&& trailing_whitespace_p (glyph->charpos))
{
- int face_id = lookup_named_face (f, Qtrailing_whitespace, 0, 0);
+ int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
if (face_id < 0)
return;
kboard-local variables in the mode_line_format will get the right
values. */
push_frame_kboard (it.f);
+ record_unwind_save_match_data ();
display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
pop_frame_kboard ();
{
if (EQ (face, Qt))
face = (EQ (window, selected_window) ? Qmode_line : Qmode_line_inactive);
- face_id = lookup_named_face (XFRAME (WINDOW_FRAME (w)), face, 0, 0);
+ face_id = lookup_named_face (XFRAME (WINDOW_FRAME (w)), face, 0);
}
if (face_id < 0)
/* The EOL conversion we are using. */
Lisp_Object eoltype;
- val = Fget (coding_system, Qcoding_system);
+ val = CODING_SYSTEM_SPEC (coding_system);
eoltype = Qnil;
if (!VECTORP (val)) /* Not yet decided. */
}
else
{
+ Lisp_Object attrs;
Lisp_Object eolvalue;
- eolvalue = Fget (coding_system, Qeol_type);
+ attrs = AREF (val, 0);
+ eolvalue = AREF (val, 2);
if (multibyte)
- *buf++ = XFASTINT (AREF (val, 1));
+ *buf++ = XFASTINT (CODING_ATTR_MNEMONIC (attrs));
if (eol_flag)
{
eoltype = eol_mnemonic_undecided;
else if (VECTORP (eolvalue)) /* Not yet decided. */
eoltype = eol_mnemonic_undecided;
- else /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */
- eoltype = (XFASTINT (eolvalue) == 0
+ else /* eolvalue is Qunix, Qdos, or Qmac. */
+ eoltype = (EQ (eolvalue, Qunix)
? eol_mnemonic_unix
- : (XFASTINT (eolvalue) == 1
+ : (EQ (eolvalue, Qdos) == 1
? eol_mnemonic_dos : eol_mnemonic_mac));
}
}
eol_str = SDATA (eoltype);
eol_str_len = SBYTES (eoltype);
}
- else if (INTEGERP (eoltype)
- && CHAR_VALID_P (XINT (eoltype), 0))
+ else if (CHARACTERP (eoltype))
{
unsigned char *tmp = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
eol_str_len = CHAR_STRING (XINT (eoltype), tmp);
{
/* No need to mention EOL here--the terminal never needs
to do EOL conversion. */
- p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0);
- p = decode_mode_spec_coding (terminal_coding.symbol, p, 0);
+ p = decode_mode_spec_coding (CODING_ID_NAME (keyboard_coding.id),
+ p, 0);
+ p = decode_mode_spec_coding (CODING_ID_NAME (terminal_coding.id),
+ p, 0);
}
p = decode_mode_spec_coding (b->buffer_file_coding_system,
p, eol_flag);
}
break;
}
- else if (x + glyph->pixel_width > it->first_visible_x)
+ else if (x + glyph->pixel_width >= it->first_visible_x)
{
/* Glyph is at least partially visible. */
++it->hpos;
if (two_byte_p)
*two_byte_p = 0;
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend)
+ {
+ struct font *font = (struct font *) face->font_info;
+
+ if (font)
+ {
+ unsigned code = font->driver->encode_char (font, glyph->u.ch);
+
+ if (code != FONT_INVALID_CODE)
+ STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
+ else
+ STORE_XCHAR2B (char2b, 0, code);
+ }
+ }
+ else
+#endif /* USE_FONT_BACKEND */
if (!glyph->multibyte_p)
{
/* Unibyte case. We don't have to encode, but we have to make
sure to use a face suitable for unibyte. */
STORE_XCHAR2B (char2b, 0, glyph->u.ch);
}
- else if (glyph->u.ch < 128
- && glyph->face_id < BASIC_FACE_ID_SENTINEL)
+ else if (glyph->u.ch < 128)
{
/* Case of ASCII in a face known to fit ASCII. */
STORE_XCHAR2B (char2b, 0, glyph->u.ch);
}
else
{
- int c1, c2, charset;
+ struct font_info *font_info
+ = FONT_INFO_FROM_ID (f, face->font_info_id);
+ if (font_info)
+ {
+ struct charset *charset = CHARSET_FROM_ID (font_info->charset);
+ unsigned code = ENCODE_CHAR (charset, glyph->u.ch);
- /* Split characters into bytes. If c2 is -1 afterwards, C is
- really a one-byte character so that byte1 is zero. */
- SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
- if (c2 > 0)
- STORE_XCHAR2B (char2b, c1, c2);
- else
- STORE_XCHAR2B (char2b, 0, c1);
+ if (CHARSET_DIMENSION (charset) == 1)
+ STORE_XCHAR2B (char2b, 0, code);
+ else
+ STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
- /* Maybe encode the character in *CHAR2B. */
- if (charset != CHARSET_ASCII)
- {
- struct font_info *font_info
- = FONT_INFO_FROM_ID (f, face->font_info_id);
- if (font_info)
- glyph->font_type
- = rif->encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
+ /* Maybe encode the character in *CHAR2B. */
+ if (CHARSET_ID (charset) != charset_ascii)
+ {
+ glyph->font_type
+ = rif->encode_char (glyph->u.ch, char2b, font_info, charset,
+ two_byte_p);
+ }
}
}
s->for_overlaps = overlaps;
s->face = faces[s->gidx];
- s->font = s->face->font;
- s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
+ if (s->face == NULL)
+ {
+ s->font = NULL;
+ s->font_info = NULL;
+ }
+ else
+ {
+ s->font = s->face->font;
+ s->font_info = FONT_INFO_FROM_FACE (s->f, s->face);
+ }
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend && s->cmp->method == COMPOSITION_WITH_GLYPH_STRING)
+ {
+ Lisp_Object gstring
+ = AREF (XHASH_TABLE (composition_hash_table)->key_and_value,
+ s->cmp->hash_index * 2);
+
+ for (i = 0, s->nchars = 0; i < s->cmp->glyph_len; i++, s->nchars++)
+ {
+ Lisp_Object g = LGSTRING_GLYPH (gstring, i);
+ unsigned code;
+
+ if (NILP (LGLYPH_FROM (g)))
+ break;
+ code = XUINT (LGLYPH_CODE (g));
+ STORE_XCHAR2B (s->char2b + i, code >> 8, code & 0xFF);
+ }
+ s->width = s->cmp->pixel_width;
+ }
+ else
+ {
+#endif /* USE_FONT_BACKEND */
/* 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. */
++s->nchars;
- for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
+ for (i = s->gidx + 1;
+ i < s->cmp->glyph_len && (faces[i] == s->face || ! faces[i] || ! s->face);
+ ++i)
++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;
+#ifdef USE_FONT_BACKEND
+ }
+#endif /* USE_FONT_BACKEND */
/* 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
/* Adjust base line for subscript/superscript text. */
s->ybase += s->first_glyph->voffset;
- xassert (s->face && s->face->gc);
-
/* This glyph string must always be drawn with 16-bit functions. */
s->two_byte_p = 1;
}
s->font = s->face->font;
- s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
+ s->font_info = FONT_INFO_FROM_FACE (s->f, s->face);
/* If the specified font could not be loaded, use the frame's font,
but record the fact that we couldn't load it in
face_id = glyph->face_id;
s->face = FACE_FROM_ID (s->f, face_id);
s->font = s->face->font;
- s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
+ s->font_info = FONT_INFO_FROM_FACE (s->f, s->face);
s->width = glyph->pixel_width;
+ s->nchars = 1;
voffset = glyph->voffset;
for (++glyph;
return glyph - s->row->glyphs[s->area];
}
+static XCharStruct *
+get_per_char_metric (font, font_info, char2b, font_type)
+ XFontStruct *font;
+ struct font_info *font_info;
+ XChar2b *char2b;
+ int font_type;
+{
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend)
+ {
+ static XCharStruct pcm_value;
+ unsigned code = (XCHAR2B_BYTE1 (char2b) << 8) | XCHAR2B_BYTE2 (char2b);
+ struct font *fontp;
+ struct font_metrics metrics;
+
+ if (! font_info || code == FONT_INVALID_CODE)
+ return NULL;
+ fontp = (struct font *) font_info;
+ fontp->driver->text_extents (fontp, &code, 1, &metrics);
+ pcm_value.lbearing = metrics.lbearing;
+ pcm_value.rbearing = metrics.rbearing;
+ pcm_value.ascent = metrics.ascent;
+ pcm_value.descent = metrics.descent;
+ pcm_value.width = metrics.width;
+ return &pcm_value;
+ }
+#endif /* USE_FONT_BACKEND */
+ return rif->per_char_metric (font, char2b, font_type);
+}
/* EXPORT for RIF:
Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
face = get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
font = face->font;
- font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
+ font_info = FONT_INFO_FROM_FACE (f, face);
if (font /* ++KFS: Should this be font_info ? */
- && (pcm = rif->per_char_metric (font, &char2b, glyph->font_type)))
+ && (pcm = get_per_char_metric (font, font_info, &char2b, glyph->font_type)))
{
if (pcm->rbearing > pcm->width)
*right = pcm->rbearing - pcm->width;
*left = -pcm->lbearing;
}
}
+ else if (glyph->type == COMPOSITE_GLYPH)
+ {
+ struct composition *cmp = composition_table[glyph->u.cmp_id];
+
+ *right = cmp->rbearing - cmp->pixel_width;
+ *left = - cmp->lbearing;
+ }
}
{
struct face *face = FACE_FROM_ID (f, face_id);
+#ifdef USE_FONT_BACKEND
+ if (enable_font_backend)
+ {
+ struct font *font = (struct font *) face->font_info;
+
+ if (font)
+ {
+ unsigned code = font->driver->encode_char (font, c);
+
+ if (code != FONT_INVALID_CODE)
+ STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
+ else
+ STORE_XCHAR2B (char2b, 0, 0);
+ }
+ }
+ else
+#endif /* USE_FONT_BACKEND */
if (!multibyte_p)
{
/* Unibyte case. We don't have to encode, but we have to make
sure to use a face suitable for unibyte. */
STORE_XCHAR2B (char2b, 0, c);
- face_id = FACE_FOR_CHAR (f, face, c);
+ face_id = FACE_FOR_CHAR (f, face, c, -1, Qnil);
face = FACE_FROM_ID (f, face_id);
}
- else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
+ else if (c < 128)
{
/* Case of ASCII in a face known to fit ASCII. */
STORE_XCHAR2B (char2b, 0, c);
}
- else
+ else if (face->font != NULL)
{
- int c1, c2, charset;
+ struct font_info *font_info
+ = FONT_INFO_FROM_ID (f, face->font_info_id);
+ struct charset *charset = CHARSET_FROM_ID (font_info->charset);
+ unsigned code = ENCODE_CHAR (charset, c);
- /* Split characters into bytes. If c2 is -1 afterwards, C is
- really a one-byte character so that byte1 is zero. */
- SPLIT_CHAR (c, charset, c1, c2);
- if (c2 > 0)
- STORE_XCHAR2B (char2b, c1, c2);
+ if (CHARSET_DIMENSION (charset) == 1)
+ STORE_XCHAR2B (char2b, 0, code);
else
- STORE_XCHAR2B (char2b, 0, c1);
-
- /* Maybe encode the character in *CHAR2B. */
- if (face->font != NULL)
- {
- struct font_info *font_info
- = FONT_INFO_FROM_ID (f, face->font_info_id);
- if (font_info)
- rif->encode_char (c, char2b, font_info, 0);
- }
+ STORE_XCHAR2B (char2b, (code >> 8), (code & 0xFF));
+ /* Maybe encode the character in *CHAR2B. */
+ rif->encode_char (c, char2b, font_info, charset, NULL);
}
/* Make sure X resources of the face are allocated. */
#define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
do \
{ \
- int c, face_id; \
+ int face_id; \
XChar2b *char2b; \
\
- c = (row)->glyphs[area][START].u.ch; \
face_id = (row)->glyphs[area][START].face_id; \
\
s = (struct glyph_string *) alloca (sizeof *s); \
struct glyph_string *first_s = NULL; \
int n; \
\
+ if (cmp->method > COMPOSITION_WITH_RULE_ALTCHARS) \
+ { \
+ /* This happens only when USE_FONT_BACKEND is defined. */ \
+ char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
+ faces = &base_face; \
+ } \
+ else \
+ { \
base_face = base_face->ascii_face; \
char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
for (n = 0; n < glyph_len; n++) \
{ \
int c = COMPOSITION_GLYPH (cmp, n); \
- int this_face_id = FACE_FOR_CHAR (f, base_face, c); \
- faces[n] = FACE_FROM_ID (f, this_face_id); \
- get_char_face_and_encoding (f, c, this_face_id, \
+ \
+ if (c == '\t') \
+ faces[n] = NULL; \
+ else \
+ { \
+ int this_face_id = FACE_FOR_CHAR (f, base_face, c, -1, Qnil); \
+ faces[n] = FACE_FROM_ID (f, this_face_id); \
+ get_char_face_and_encoding (f, c, this_face_id, \
char2b + n, 1, 1); \
+ } \
} \
+ } \
\
/* Make glyph_strings for each glyph sequence that is drawable by \
the same face, and append them to HEAD/TAIL. */ \
abort (); \
} \
\
- set_glyph_string_background_width (s, START, LAST_X); \
- (X) += s->width; \
+ if (s) \
+ { \
+ set_glyph_string_background_width (s, START, LAST_X); \
+ (X) += s->width; \
+ } \
} \
} \
while (0)
int x;
struct glyph_row *row;
enum glyph_row_area area;
- int start, end;
+ EMACS_INT start, end;
enum draw_glyphs_face hl;
int overlaps;
{
if (i >= 0)
{
clip_tail = tail;
+ i++; /* We must include the Ith glyph. */
BUILD_GLYPH_STRINGS (end, i, h, t,
DRAW_NORMAL_TEXT, x, last_x);
for (s = h; s; s = s->next)
it->descent = it->phys_descent = height - it->ascent;
it->nglyphs = width > 0 && height > 0 ? 1 : 0;
- if (width > 0 && height > 0 && face->box != FACE_NO_BOX)
- {
- if (face->box_line_width > 0)
- {
- it->ascent += face->box_line_width;
- it->descent += face->box_line_width;
- }
-
- if (it->start_of_box_run_p)
- it->pixel_width += abs (face->box_line_width);
- if (it->end_of_box_run_p)
- it->pixel_width += abs (face->box_line_width);
- }
-
take_vertical_position_into_account (it);
}
struct face *face;
struct font_info *font_info;
- face_id = lookup_named_face (it->f, face_name, ' ', 0);
+ face_id = lookup_named_face (it->f, face_name, 0);
if (face_id < 0)
return make_number (-1);
if (font == NULL)
return make_number (-1);
- font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+ font_info = FONT_INFO_FROM_FACE (it->f, face);
boff = font_info->baseline_offset;
if (font_info->vertical_centering)
boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
/* Maybe translate single-byte characters to multibyte, or the
other way. */
it->char_to_display = it->c;
- if (!ASCII_BYTE_P (it->c))
+ if (!ASCII_BYTE_P (it->c)
+ && ! it->multibyte_p)
{
- if (unibyte_display_via_language_environment
- && SINGLE_BYTE_CHAR_P (it->c)
- && (it->c >= 0240
- || !NILP (Vnonascii_translation_table)))
- {
- it->char_to_display = unibyte_char_to_multibyte (it->c);
- it->multibyte_p = 1;
- it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
- face = FACE_FROM_ID (it->f, it->face_id);
- }
- else if (!SINGLE_BYTE_CHAR_P (it->c)
- && !it->multibyte_p)
+ if (SINGLE_BYTE_CHAR_P (it->c)
+ && unibyte_display_via_language_environment)
+ it->char_to_display = unibyte_char_to_multibyte (it->c);
+ if (! SINGLE_BYTE_CHAR_P (it->c))
{
it->multibyte_p = 1;
- it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+ it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display,
+ -1, Qnil);
face = FACE_FROM_ID (it->f, it->face_id);
}
}
}
else
{
- font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+ font_info = FONT_INFO_FROM_FACE (it->f, face);
boff = font_info->baseline_offset;
if (font_info->vertical_centering)
boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
it->nglyphs = 1;
- pcm = rif->per_char_metric (font, &char2b,
+ pcm = get_per_char_metric (font, font_info, &char2b,
FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
if (it->override_ascent >= 0)
/* 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 += 2;
+ it->ascent += overline_margin;
if (it->constrain_row_ascent_descent_p)
{
/* If we found a font, this font should give us the right
metrics. If we didn't find a font, use the frame's
- default font and calculate the width of the character
- from the charset width; this is what old redisplay code
- did. */
+ default font and calculate the width of the character by
+ multiplying the width of font by the width of the
+ character. */
- pcm = rif->per_char_metric (font, &char2b,
+ pcm = get_per_char_metric (font, font_info, &char2b,
FONT_TYPE_FOR_MULTIBYTE (font, it->c));
if (font_not_found_p || !pcm)
{
- int charset = CHAR_CHARSET (it->char_to_display);
-
it->glyph_not_available_p = 1;
it->pixel_width = (FRAME_COLUMN_WIDTH (it->f)
- * CHARSET_WIDTH (charset));
+ * CHAR_WIDTH (it->char_to_display));
it->phys_ascent = FONT_BASE (font) + boff;
it->phys_descent = FONT_DESCENT (font) - boff;
}
/* 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 += 2;
+ it->ascent += overline_margin;
take_vertical_position_into_account (it);
struct font_info *font_info;
int boff; /* baseline offset */
struct composition *cmp = composition_table[it->cmp_id];
+ int pos;
/* Maybe translate single-byte characters to multibyte. */
it->char_to_display = it->c;
if (unibyte_display_via_language_environment
- && SINGLE_BYTE_CHAR_P (it->c)
- && (it->c >= 0240
- || (it->c >= 0200
- && !NILP (Vnonascii_translation_table))))
+ && it->c >= 0200)
{
it->char_to_display = unibyte_char_to_multibyte (it->c);
}
+#ifdef USE_FONT_BACKEND
+ if (cmp->method != COMPOSITION_WITH_GLYPH_STRING)
+ {
+#endif /* USE_FONT_BACKEND */
/* Get face and font to use. Encode IT->char_to_display. */
- it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+ pos = STRINGP (it->string) ? IT_STRING_CHARPOS (*it) : IT_CHARPOS (*it);
+ it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display,
+ pos, it->string);
face = FACE_FROM_ID (it->f, it->face_id);
get_char_face_and_encoding (it->f, it->char_to_display, it->face_id,
&char2b, it->multibyte_p, 0);
}
else
{
- font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+ font_info = FONT_INFO_FROM_FACE (it->f, face);
boff = font_info->baseline_offset;
if (font_info->vertical_centering)
boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
}
+#ifdef USE_FONT_BACKEND
+ }
+#endif
/* There are no padding glyphs, so there is only one glyph to
produce for the composition. Important is that pixel_width,
now. Theoretically, we have to check all fonts for the
glyphs, but that requires much time and memory space. So,
here we check only the font of the first glyph. This leads
- to incorrect display very rarely, and C-l (recenter) can
- correct the display anyway. */
- if (cmp->font != (void *) font)
+ to incorrect display, but it's very rare, and C-l (recenter)
+ can correct the display anyway. */
+ if (cmp->glyph_len == 0)
+ {
+ cmp->lbearing = cmp->rbearing = 0;
+ cmp->pixel_width = cmp->ascent = cmp->descent = 0;
+ }
+#ifdef USE_FONT_BACKEND
+ else if (cmp->method == COMPOSITION_WITH_GLYPH_STRING)
+ {
+ if (! cmp->font)
+ font_prepare_composition (cmp);
+ }
+#endif /* USE_FONT_BACKEND */
+ else if (cmp->font != (void *) font)
{
/* Ascent and descent of the font of the first character of
this composition (adjusted by baseline offset). Ascent
them respectively. */
int font_ascent = FONT_BASE (font) + boff;
int font_descent = FONT_DESCENT (font) - boff;
+ int font_height = FONT_HEIGHT (font);
/* Bounding box of the overall glyphs. */
int leftmost, rightmost, lowest, highest;
+ int lbearing, rbearing;
int i, width, ascent, descent;
+ int fully_padded = 0;
cmp->font = (void *) font;
/* Initialize the bounding box. */
if (font_info
- && (pcm = rif->per_char_metric (font, &char2b,
+ && (pcm = get_per_char_metric (font, font_info, &char2b,
FONT_TYPE_FOR_MULTIBYTE (font, it->c))))
{
width = pcm->width;
ascent = pcm->ascent;
descent = pcm->descent;
+ lbearing = pcm->lbearing;
+ if (lbearing > 0)
+ lbearing = 0;
+ rbearing = pcm->rbearing;
+ if (rbearing < width)
+ rbearing = width;
}
else
{
width = FONT_WIDTH (font);
ascent = FONT_BASE (font);
descent = FONT_DESCENT (font);
+ lbearing = 0;
+ rbearing = width;
}
rightmost = width;
the left. */
cmp->offsets[0] = 0;
cmp->offsets[1] = boff;
+ cmp->lbearing = lbearing;
+ cmp->rbearing = rbearing;
/* Set cmp->offsets for the remaining glyphs. */
for (i = 1; i < cmp->glyph_len; i++)
{
int left, right, btm, top;
int ch = COMPOSITION_GLYPH (cmp, i);
- int face_id = FACE_FOR_CHAR (it->f, face, ch);
+ int face_id;
+
+ if (ch == '\t')
+ {
+ fully_padded = 1;
+ cmp->offsets[i * 2] = 0;
+ cmp->offsets[i * 2 + 1] = boff;
+ continue;
+ }
+ face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
face = FACE_FROM_ID (it->f, face_id);
get_char_face_and_encoding (it->f, ch, face->id,
&char2b, it->multibyte_p, 0);
else
{
font_info
- = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+ = FONT_INFO_FROM_FACE (it->f, face);
boff = font_info->baseline_offset;
if (font_info->vertical_centering)
boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
}
if (font_info
- && (pcm = rif->per_char_metric (font, &char2b,
+ && (pcm = get_per_char_metric (font, font_info, &char2b,
FONT_TYPE_FOR_MULTIBYTE (font, ch))))
{
width = pcm->width;
ascent = pcm->ascent;
descent = pcm->descent;
+ lbearing = pcm->lbearing;
+ if (lbearing > 0)
+ lbearing = 0;
+ rbearing = pcm->rbearing;
+ if (rbearing < width)
+ rbearing = width;
}
else
{
width = FONT_WIDTH (font);
ascent = 1;
descent = 0;
+ lbearing = 0;
+ rbearing = width;
}
if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
6---7---8 -- descent
*/
int rule = COMPOSITION_RULE (cmp, i);
- int gref, nref, grefx, grefy, nrefx, nrefy;
+ int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
- COMPOSITION_DECODE_RULE (rule, gref, nref);
+ COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
grefx = gref % 3, nrefx = nref % 3;
grefy = gref / 3, nrefy = nref / 3;
+ if (xoff)
+ xoff = font_height * (xoff - 128) / 256;
+ if (yoff)
+ yoff = font_height * (yoff - 128) / 256;
left = (leftmost
+ grefx * (rightmost - leftmost) / 2
- - nrefx * width / 2);
+ - nrefx * width / 2
+ + xoff);
+
btm = ((grefy == 0 ? highest
: grefy == 1 ? 0
: grefy == 2 ? lowest
- (nrefy == 0 ? ascent + descent
: nrefy == 1 ? descent - boff
: nrefy == 2 ? 0
- : (ascent + descent) / 2));
+ : (ascent + descent) / 2)
+ + yoff);
}
cmp->offsets[i * 2] = left;
cmp->offsets[i * 2 + 1] = btm + descent;
/* Update the bounding box of the overall glyphs. */
- right = left + width;
+ if (width > 0)
+ {
+ right = left + width;
+ if (left < leftmost)
+ leftmost = left;
+ if (right > rightmost)
+ rightmost = right;
+ }
top = btm + descent + ascent;
- if (left < leftmost)
- leftmost = left;
- if (right > rightmost)
- rightmost = right;
if (top > highest)
highest = top;
if (btm < lowest)
lowest = btm;
+
+ if (cmp->lbearing > left + lbearing)
+ cmp->lbearing = left + lbearing;
+ if (cmp->rbearing < left + rbearing)
+ cmp->rbearing = left + rbearing;
}
/* If there are glyphs whose x-offsets are negative,
for (i = 0; i < cmp->glyph_len; i++)
cmp->offsets[i * 2] -= leftmost;
rightmost -= leftmost;
+ cmp->lbearing -= leftmost;
+ cmp->rbearing -= leftmost;
+ }
+
+ if (fully_padded)
+ {
+ for (i = 0; i < cmp->glyph_len; i++)
+ cmp->offsets[i * 2] -= cmp->lbearing;
+ rightmost = cmp->rbearing - cmp->lbearing;
+ cmp->lbearing = 0;
+ cmp->rbearing = rightmost;
}
cmp->pixel_width = rightmost;
cmp->descent = font_descent;
}
+ if (it->glyph_row
+ && (cmp->lbearing < 0
+ || cmp->rbearing > cmp->pixel_width))
+ it->glyph_row->contains_overlapping_glyphs_p = 1;
+
it->pixel_width = cmp->pixel_width;
it->ascent = it->phys_ascent = cmp->ascent;
it->descent = it->phys_descent = cmp->descent;
/* 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 += 2;
+ it->ascent += overline_margin;
take_vertical_position_into_account (it);
int line_height, shift_by_width, shifted_region_width;
struct glyph_row *row;
struct glyph *glyph;
- int frame_x, frame_y, hpos;
+ int frame_x, frame_y;
+ EMACS_INT hpos;
xassert (updated_window && updated_row);
BLOCK_INPUT;
/* Use normal cursor if not blinked off. */
if (!w->cursor_off_p)
{
- if (glyph != NULL && glyph->type == IMAGE_GLYPH) {
- if (cursor_type == FILLED_BOX_CURSOR)
- cursor_type = HOLLOW_BOX_CURSOR;
+#ifdef HAVE_WINDOW_SYSTEM
+ if (glyph != NULL && glyph->type == IMAGE_GLYPH)
+ {
+ if (cursor_type == FILLED_BOX_CURSOR)
+ {
+ /* Using a block cursor on large images can be very annoying.
+ So use a hollow cursor for "large" images. */
+ struct image *img = IMAGE_FROM_ID (f, glyph->u.img_id);
+ if (img != NULL && IMAGEP (img->spec))
+ {
+ /* Arbitrarily, interpret "Large" as >32x32 and >NxN
+ where N = size of default frame font size.
+ This should cover most of the "tiny" icons people may use. */
+ if (img->width > max (32, WINDOW_FRAME_COLUMN_WIDTH (w))
+ || img->height > max (32, WINDOW_FRAME_LINE_HEIGHT (w)))
+ cursor_type = HOLLOW_BOX_CURSOR;
+ }
+ }
+ else if (cursor_type != NO_CURSOR)
+ {
+ /* Display current only supports BOX and HOLLOW cursors for images.
+ So for now, unconditionally use a HOLLOW cursor when cursor is
+ not a solid box cursor. */
+ cursor_type = HOLLOW_BOX_CURSOR;
+ }
}
+#endif
return cursor_type;
}
/* Maybe clear the display under the cursor. */
if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
{
- int x, y;
+ int x, y, left_x;
int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
int width;
if (cursor_glyph == NULL)
goto mark_cursor_off;
- x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+ width = cursor_glyph->pixel_width;
+ left_x = window_box_left_offset (w, TEXT_AREA);
+ x = w->phys_cursor.x;
+ if (x < left_x)
+ width -= left_x - x;
+ width = min (width, window_box_width (w, TEXT_AREA) - x);
y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y));
- width = min (cursor_glyph->pixel_width,
- window_box_width (w, TEXT_AREA) - w->phys_cursor.x);
+ x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, max (x, left_x));
+ if (width > 0)
rif->clear_frame_area (f, x, y, width, cursor_row->visible_height);
}
static int
fast_find_position (w, charpos, hpos, vpos, x, y, stop)
struct window *w;
- int charpos;
+ EMACS_INT charpos;
int *hpos, *vpos, *x, *y;
Lisp_Object stop;
{
static int
fast_find_position (w, pos, hpos, vpos, x, y, stop)
struct window *w;
- int pos;
+ EMACS_INT pos;
int *hpos, *vpos, *x, *y;
Lisp_Object stop;
{
static int
fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
struct window *w;
- int pos;
+ EMACS_INT pos;
Lisp_Object object;
int *hpos, *vpos, *x, *y;
int right_p;
}
if (part == ON_VERTICAL_BORDER)
- cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
+ {
+ cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
+ help_echo_string = build_string ("drag-mouse-1: resize");
+ }
else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
|| part == ON_SCROLL_BAR)
cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
doc: /* Inhibit try_cursor_movement display optimization. */);
inhibit_try_cursor_movement = 0;
#endif /* GLYPH_DEBUG */
+
+ DEFVAR_INT ("overline-margin", &overline_margin,
+ doc: /* *Space between overline and text, in pixels.
+The default value is 2: the height of the overline (1 pixel) plus 1 pixel
+margin to the caracter height. */);
+ overline_margin = 2;
}