#define LEFT_GLYPHS 2
#define RIGHT_GLYPHS 3
-/* Set the vertical clip to 0 if we are currently updating the line
- start cache. Otherwise for buffers of line height 1 it may fail to
- be able to work properly because regenerate_window will not layout
- a single line. */
#define VERTICAL_CLIP(w, display) \
- (updating_line_start_cache \
- ? 0 \
- : ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \
+ ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \
? INT_MAX \
- : vertical_clip))
+ : vertical_clip)
/* The following structures are completely private to redisplay.c so
we put them here instead of in a header file, for modularity. */
Bytind bi_start_col_enabled;
int start_col_xoffset; /* Number of pixels that still need to
be skipped. This is used for
- horizontal scrolling of glyphs, where we want
+ horizontal scrolling of glyphs, where we want
to be able to scroll over part of the glyph. */
int hscroll_glyph_width_adjust; /* how much the width of the hscroll
} prop_block_dynarr;
-static void generate_formatted_string_db (Lisp_Object format_str,
- Lisp_Object result_str,
- struct window *w,
- struct display_line *dl,
- struct display_block *db,
- face_index findex, int min_pixpos,
- int max_pixpos, int type);
static Charcount generate_fstring_runes (struct window *w, pos_data *data,
Charcount pos, Charcount min_pos,
Charcount max_pos, Lisp_Object elt,
int depth, int max_pixsize,
- face_index findex, int type);
+ face_index findex, int type,
+ Charcount *offset,
+ Lisp_Object cur_ext);
static prop_block_dynarr *add_glyph_rune (pos_data *data,
struct glyph_block *gb,
int pos_type, int allow_cursor,
isn't any reason we need more than a single set. */
display_line_dynarr *cmotion_display_lines;
-/* Used by generate_formatted_string. Global because they get used so
- much that the dynamic allocation time adds up. */
-static Emchar_dynarr *formatted_string_emchar_dynarr;
-static struct display_line formatted_string_display_line;
/* We store the extents that we need to generate in a Dynarr and then
frob them all on at the end of generating the string. We do it
this way rather than adding them as we generate the string because
/* Minimum visible pixel width of clipped glyphs at right margin. */
int horizontal_clip;
-/* Set if currently inside update_line_start_cache. */
-static int updating_line_start_cache;
-
/* Nonzero means reading single-character input with prompt
so put cursor on minibuffer after the prompt. */
int cursor_in_echo_area;
int glyphs_changed;
int glyphs_changed_set;
-/* non-zero if any displayed subwindow is in need of updating
- somewhere. */
+/* non-zero if any subwindow has been deleted. */
int subwindows_changed;
int subwindows_changed_set;
Lisp_Object Vbar_cursor;
Lisp_Object Qbar_cursor;
-
-int visible_bell; /* If true and the terminal will support it
- then the frame will flash instead of
- beeping when an error occurs */
+Lisp_Object Vvisible_bell; /* If true and the terminal will support it
+ then the frame will flash instead of
+ beeping when an error occurs */
/* Nonzero means no need to redraw the entire frame on resuming
a suspended Emacs. This is useful on terminals with multiple pages,
Lisp_Object Vwindow_scroll_functions;
Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
+Lisp_Object Qbuffer_list_changed_hook, Vbuffer_list_changed_hook;
+
+
#define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about
this more. */
#ifndef INHIBIT_REDISPLAY_HOOKS
int column_number_start_at_one;
+Lisp_Object Qtop_bottom;
+
#define WINDOW_SCROLLED(w) \
(w->hscroll > 0 || w->left_xoffset)
/***************************************************************************/
static int
-redisplay_text_width_emchar_string (struct window *w, int findex,
- Emchar *str, Charcount len)
+redisplay_text_width_charc_string (struct window *w, int findex,
+ Charc *str, Charcount len)
{
- unsigned char charsets[NUM_LEADING_BYTES];
+ Charset_ID charsets[NUM_LEADING_BYTES];
Lisp_Object window;
- find_charsets_in_emchar_string (charsets, str, len);
+ find_charsets_in_charc_string (charsets, str, len);
XSETWINDOW (window, w);
ensure_face_cachel_complete (WINDOW_FACE_CACHEL (w, findex), window,
charsets);
WINDOW_FACE_CACHEL (w, findex), str, len));
}
-static Emchar_dynarr *rtw_emchar_dynarr;
+static Charc_dynarr *rtw_charc_dynarr;
int
redisplay_text_width_string (struct window *w, int findex,
Bufbyte *nonreloc, Lisp_Object reloc,
Bytecount offset, Bytecount len)
{
- if (!rtw_emchar_dynarr)
- rtw_emchar_dynarr = Dynarr_new (Emchar);
- Dynarr_reset (rtw_emchar_dynarr);
+ if (!rtw_charc_dynarr)
+ rtw_charc_dynarr = Dynarr_new (Charc);
+ Dynarr_reset (rtw_charc_dynarr);
fixup_internal_substring (nonreloc, reloc, offset, &len);
if (STRINGP (reloc))
nonreloc = XSTRING_DATA (reloc);
- convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
- return redisplay_text_width_emchar_string
- (w, findex, Dynarr_atp (rtw_emchar_dynarr, 0),
- Dynarr_length (rtw_emchar_dynarr));
+ convert_bufbyte_string_into_charc_dynarr (nonreloc, len, rtw_charc_dynarr);
+ return redisplay_text_width_charc_string
+ (w, findex, Dynarr_atp (rtw_charc_dynarr, 0),
+ Dynarr_length (rtw_charc_dynarr));
}
int
Bufbyte *nonreloc, Lisp_Object reloc,
Bytecount offset, Bytecount len)
{
- unsigned char charsets[NUM_LEADING_BYTES];
+ Charset_ID charsets[NUM_LEADING_BYTES];
Lisp_Object frame;
struct face_cachel cachel;
- if (!rtw_emchar_dynarr)
- rtw_emchar_dynarr = Dynarr_new (Emchar);
- Dynarr_reset (rtw_emchar_dynarr);
+ if (!rtw_charc_dynarr)
+ rtw_charc_dynarr = Dynarr_new (Charc);
+ Dynarr_reset (rtw_charc_dynarr);
fixup_internal_substring (nonreloc, reloc, offset, &len);
if (STRINGP (reloc))
nonreloc = XSTRING_DATA (reloc);
- convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
+ convert_bufbyte_string_into_charc_dynarr (nonreloc, len, rtw_charc_dynarr);
find_charsets_in_bufbyte_string (charsets, nonreloc, len);
reset_face_cachel (&cachel);
cachel.face = face;
XSETFRAME (frame, f);
ensure_face_cachel_complete (&cachel, frame, charsets);
return DEVMETH (XDEVICE (FRAME_DEVICE (f)),
- text_width, (f, &cachel, Dynarr_atp (rtw_emchar_dynarr, 0),
- Dynarr_length (rtw_emchar_dynarr)));
+ text_width, (f, &cachel, Dynarr_atp (rtw_charc_dynarr, 0),
+ Dynarr_length (rtw_charc_dynarr)));
}
/* Return the display block from DL of the given TYPE. A display line
gb.glyph = Vhscroll_glyph;
{
int oldpixpos = data->pixpos;
- retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
+ retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0,
GLYPH_CACHEL (XWINDOW (data->window),
HSCROLL_GLYPH_INDEX));
data->hscroll_glyph_width_adjust =
{
struct rune rb, *crb;
int width, local;
+ Charc char_glyph;
if (data->start_col)
{
if (data->ch == '\n')
{
+ char_glyph.charset = Vcharset_ascii;
+ char_glyph.code_point = '\n';
data->font_is_bogus = 0;
/* Cheesy end-of-line pseudo-character. */
width = data->blank_width;
}
else
{
- Lisp_Object charset = CHAR_CHARSET (data->ch);
- if (!EQ (charset, data->last_charset) ||
+ char_glyph.code_point = ENCODE_CHAR (data->ch, char_glyph.charset);
+ if (!EQ (char_glyph.charset, data->last_charset) ||
data->findex != data->last_findex)
{
/* OK, we need to do things the hard way. */
struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex);
Lisp_Object font_instance =
ensure_face_cachel_contains_charset (cachel, data->window,
- charset);
- struct Lisp_Font_Instance *fi;
+ char_glyph.charset);
+ Lisp_Font_Instance *fi;
if (EQ (font_instance, Vthe_null_font_instance))
{
data->last_char_width = -1;
data->new_ascent = max (data->new_ascent, (int) fi->ascent);
data->new_descent = max (data->new_descent, (int) fi->descent);
- data->last_charset = charset;
+ data->last_charset = char_glyph.charset;
data->last_findex = data->findex;
}
if (width < 0)
{
/* bummer. Proportional fonts. */
- width = redisplay_text_width_emchar_string (XWINDOW (data->window),
- data->findex,
- &data->ch, 1);
+ width = redisplay_text_width_charc_string (XWINDOW (data->window),
+ data->findex,
+ &char_glyph, 1);
}
}
data->bi_bufpos);
else
crb->bufpos =
- bytecount_to_charcount (XSTRING_DATA (data->string), data->bi_bufpos);
+ bytecount_to_charcount (XSTRING_DATA (data->string),
+ data->bi_bufpos);
}
else if (data->is_modeline)
crb->bufpos = data->modeline_charpos;
else
- /* fuckme if this shouldn't be an abort. */
- /* abort (); fuckme harder, this abort gets tripped quite often,
- in propagation and whatnot. #### fixme */
+ /* Text but not in buffer */
crb->bufpos = 0;
crb->type = RUNE_CHAR;
- crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch;
+ if (data->font_is_bogus)
+ {
+ char_glyph.charset = Vcharset_ascii;
+ char_glyph.code_point = '~';
+ crb->object.cglyph = char_glyph;
+ }
+ else
+ crb->object.cglyph = char_glyph;
crb->endpos = 0;
if (data->cursor_type == CURSOR_ON)
case '%':
dst += set_charptr_emchar (dst, '%');
break;
+ /* #### unimplemented */
}
}
}
prop_block_dynarr *prop = NULL;
if (VECTORP (entry))
{
- struct Lisp_Vector *de = XVECTOR (entry);
+ Lisp_Vector *de = XVECTOR (entry);
EMACS_INT len = vector_length (de);
int elt;
{
struct window *w = XWINDOW (data->window);
+ /* If window faces changed, and glyph instance is text, then
+ glyph sizes might have changed too */
+ invalidate_glyph_geometry_maybe (gb->glyph, w);
+
+ /* This makes sure the glyph is in the cachels.
+
+ #### We do this to make sure the glyph is in the glyph cachels,
+ so that the dirty flag can be reset after redisplay has
+ finished. We should do this some other way, maybe by iterating
+ over the window cache of subwindows. */
+ get_glyph_cachel_index (w, gb->glyph);
+
/* A nil extent indicates a special glyph (ex. truncator). */
if (NILP (gb->extent)
|| (pos_type == BEGIN_GLYPHS &&
extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
|| (pos_type == END_GLYPHS &&
- extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT))
+ extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
+ || pos_type == LEFT_GLYPHS || pos_type == RIGHT_GLYPHS)
{
struct rune rb;
int width;
int ascent, descent;
Lisp_Object baseline;
Lisp_Object face;
+ Lisp_Object instance;
+ face_index findex;
if (cachel)
width = cachel->width;
else
- width = glyph_width (gb->glyph, Qnil, data->findex, data->window);
+ width = glyph_width (gb->glyph, data->window);
if (!width)
return NULL;
}
else
{
- ascent = glyph_ascent (gb->glyph, Qnil, data->findex, data->window);
- descent = glyph_descent (gb->glyph, Qnil, data->findex,
- data->window);
+ ascent = glyph_ascent (gb->glyph, data->window);
+ descent = glyph_descent (gb->glyph, data->window);
}
baseline = glyph_baseline (gb->glyph, data->window);
face = glyph_face (gb->glyph, data->window);
if (NILP (face))
- rb.findex = data->findex;
+ findex = data->findex;
else
- rb.findex = get_builtin_face_cache_index (w, face);
+ findex = get_builtin_face_cache_index (w, face);
+
+ instance = glyph_image_instance (gb->glyph, data->window,
+ ERROR_ME_NOT, 1);
+ if (TEXT_IMAGE_INSTANCEP (instance))
+ {
+ Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance);
+ face_index orig_findex = data->findex;
+ Bytind orig_bufpos = data->bi_bufpos;
+ Bytind orig_start_col_enabled = data->bi_start_col_enabled;
+
+ data->findex = findex;
+ data->bi_start_col_enabled = 0;
+ if (!allow_cursor)
+ data->bi_bufpos = 0;
+ add_bufbyte_string_runes (data, XSTRING_DATA (string),
+ XSTRING_LENGTH (string), 0);
+ data->findex = orig_findex;
+ data->bi_bufpos = orig_bufpos;
+ data->bi_start_col_enabled = orig_start_col_enabled;
+ return NULL;
+ }
+ rb.findex = findex;
rb.xpos = data->pixpos;
rb.width = width;
rb.bufpos = 0; /* glyphs are never "at" anywhere */
else
rb.endpos = 0;
rb.type = RUNE_DGLYPH;
- /* #### Ben sez: this is way bogus if the glyph is a string.
- You should not make the output routines have to cope with
- this. The string could contain Mule characters, or non-
- printable characters, or characters to be passed through
- the display table, or non-character objects (when this gets
- implemented), etc. Instead, this routine here should parse
- the string into a series of runes. */
rb.object.dglyph.glyph = gb->glyph;
rb.object.dglyph.extent = gb->extent;
rb.object.dglyph.xoffset = xoffset;
after a ^M is invisible. */
int selective = (INTP (b->selective_display)
? XINT (b->selective_display)
- : ((!NILP (b->selective_display) ? -1 : 0)));
+ : (!NILP (b->selective_display) ? -1 : 0));
/* The variable ctl-arrow allows the user to specify what characters
can actually be displayed and which octal should be used for.
dl->used_prop_data = 0;
dl->num_chars = 0;
+ dl->line_continuation = 0;
xzero (data);
data.ef = extent_fragment_new (w->buffer, f);
int prop_width = 0;
if (data.start_col > 1)
- tab_start_pixpos -= (space_width (w) * (data.start_col - 1))
+ tab_start_pixpos -= (space_width (w) * (data.start_col - 1))
+ data.start_col_xoffset;
next_tab_start =
/* data.bi_bufpos is already at the start of the next line. */
+ dl->line_continuation = 1;
gb.glyph = Vcontinuation_glyph;
cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
}
- add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, cachel);
+ add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel);
if (truncate_win && data.bi_bufpos == BI_BUF_ZV (b)
&& BI_BUF_FETCH_CHAR (b, prev_bytind (b, BI_BUF_ZV (b))) != '\n')
{
struct rune *rb = Dynarr_atp (db->runes, elt);
- if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
+ if ((rb->type == RUNE_CHAR
+ && EQ (rb->object.cglyph.charset, Vcharset_ascii)
+ && rb->object.cglyph.code_point == ' ')
|| rb->type == RUNE_BLANK)
{
dl->bounds.left_white += rb->width;
{
struct rune *rb = Dynarr_atp (db->runes, elt);
- if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
- && isspace (rb->object.chr.ch))
+ if (!(rb->type == RUNE_CHAR
+ && (EQ (rb->object.cglyph.charset, Vcharset_ascii)
+ || EQ (rb->object.cglyph.charset, Vcharset_control_1)
+ || EQ (rb->object.cglyph.charset, Vcharset_latin_iso8859_1))
+ && isspace (rb->object.cglyph.code_point))
&& !rb->type == RUNE_BLANK)
{
dl->bounds.right_white = rb->xpos + rb->width;
? dl->left_glyphs
: dl->right_glyphs);
int elt, end;
- int xpos = start;
int reverse;
+ struct window *w = XWINDOW (window);
+ struct frame *f = XFRAME (w->frame);
+ struct device *d = XDEVICE (f->device);
+ pos_data data;
+
+ xzero (data);
+ data.d = d;
+ data.window = window;
+ data.db = db;
+ data.dl = dl;
+ data.pixpos = start;
+ data.cursor_type = NO_CURSOR;
+ data.cursor_x = -1;
+ data.last_charset = Qunbound;
+ data.last_findex = DEFAULT_INDEX;
+ data.result_str = Qnil;
+ data.string = Qnil;
+ data.new_ascent = dl->ascent;
+ data.new_descent = dl->descent;
if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS)
|| (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS))
|| (side == RIGHT_GLYPHS &&
extent_end_glyph_layout (XEXTENT (gb->extent)) == layout)))
{
- struct rune rb;
-
- rb.width = gb->width;
- rb.findex = gb->findex;
- rb.xpos = xpos;
- rb.bufpos = -1;
- rb.endpos = 0;
- rb.type = RUNE_DGLYPH;
- rb.object.dglyph.glyph = gb->glyph;
- rb.object.dglyph.extent = gb->extent;
- rb.object.dglyph.xoffset = 0;
- rb.cursor_type = CURSOR_OFF;
-
- Dynarr_add (db->runes, rb);
- xpos += rb.width;
+ data.findex = gb->findex;
+ data.max_pixpos = data.pixpos + gb->width;
+ add_glyph_rune (&data, gb, side, 0, NULL);
count--;
gb->active = 0;
-
- if (glyph_contrib_p (gb->glyph, window))
- {
- unsigned short ascent, descent;
- Lisp_Object baseline = glyph_baseline (gb->glyph, window);
-
- ascent = glyph_ascent (gb->glyph, Qnil, gb->findex, window);
- descent = glyph_descent (gb->glyph, Qnil, gb->findex, window);
-
- /* A pixmap that has not had a baseline explicitly set.
- We use the existing ascent / descent ratio of the
- line. */
- if (NILP (baseline))
- {
- int gheight = ascent + descent;
- int line_height = dl->ascent + dl->descent;
- int pix_ascent, pix_descent;
-
- pix_descent = (int) (gheight * dl->descent) / line_height;
- pix_ascent = gheight - pix_descent;
-
- dl->ascent = max ((int) dl->ascent, pix_ascent);
- dl->descent = max ((int) dl->descent, pix_descent);
- }
-
- /* A string so determine contribution normally. */
- else if (EQ (baseline, Qt))
- {
- dl->ascent = max (dl->ascent, ascent);
- dl->descent = max (dl->descent, descent);
- }
-
- /* A pixmap with an explicitly set baseline. We determine the
- contribution here. */
- else if (INTP (baseline))
- {
- int height = ascent + descent;
- int pix_ascent, pix_descent;
-
- pix_ascent = height * XINT (baseline) / 100;
- pix_descent = height - pix_ascent;
-
- dl->ascent = max ((int) dl->ascent, pix_ascent);
- dl->descent = max ((int) dl->descent, pix_descent);
- }
-
- /* Otherwise something is screwed up. */
- else
- abort ();
- }
}
(reverse ? elt-- : elt++);
}
- return xpos;
+ if (data.max_pixmap_height)
+ {
+ int height = data.new_ascent + data.new_descent;
+ int pix_ascent, pix_descent;
+
+ pix_descent = data.max_pixmap_height * data.new_descent / height;
+ pix_ascent = data.max_pixmap_height - pix_descent;
+ data.new_ascent = max (data.new_ascent, pix_ascent);
+ data.new_descent = max (data.new_descent, pix_descent);
+ }
+
+ dl->ascent = data.new_ascent;
+ dl->descent = data.new_descent;
+
+ return data.pixpos;
}
/* Add a blank to a margin display block. */
{
int width;
- width = glyph_width (gb->glyph, Qnil, gb->findex, window);
+ width = glyph_width (gb->glyph, window);
if (white_in_start - width >= left_in_end)
{
if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
GL_INSIDE_MARGIN)
{
- gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window);
+ gb->width = glyph_width (gb->glyph, window);
used_in += gb->width;
Dynarr_add (ib, *gb);
}
if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
GL_INSIDE_MARGIN)
{
- int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
+ int width = glyph_width (gb->glyph, window);
if (used_out)
{
if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
GL_OUTSIDE_MARGIN)
{
- int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
+ int width = glyph_width (gb->glyph, window);
if (out_end + width <= in_out_start)
{
if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
{
- int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
+ int width = glyph_width (gb->glyph, window);
if (white_in_end + width <= dl->bounds.right_in)
{
if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
{
- gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window);
+ gb->width = glyph_width (gb->glyph, window);
used_in += gb->width;
Dynarr_add (ib, *gb);
}
if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
{
- int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
+ int width = glyph_width (gb->glyph, window);
if (used_out)
{
if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN)
{
- int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
+ int width = glyph_width (gb->glyph, window);
if (out_start - width >= in_out_end)
{
/* */
/***************************************************************************/
-/* Ensure that the given display line DL accurately represents the
- modeline for the given window. */
-
-static void
-generate_modeline (struct window *w, struct display_line *dl, int type)
-{
- struct buffer *b = XBUFFER (w->buffer);
- struct frame *f = XFRAME (w->frame);
- struct device *d = XDEVICE (f->device);
-
- /* Unlike display line and rune pointers, this one can't change underneath
- our feet. */
- struct display_block *db = get_display_block_from_line (dl, TEXT);
- int max_pixpos, min_pixpos, ypos_adj;
- Lisp_Object font_inst;
-
- /* This will actually determine incorrect inside boundaries for the
- modeline since it ignores the margins. However being aware of this fact
- we never use those values anywhere so it doesn't matter. */
- dl->bounds = calculate_display_line_boundaries (w, 1);
-
- /* We are generating a modeline. */
- dl->modeline = 1;
- dl->cursor_elt = -1;
-
- /* Reset the runes on the modeline. */
- Dynarr_reset (db->runes);
-
- if (!WINDOW_HAS_MODELINE_P (w))
- {
- struct rune rb;
-
- /* If there is a horizontal scrollbar, don't add anything. */
- if (window_scrollbar_height (w))
- return;
-
- dl->ascent = DEVMETH (d, divider_height, ());
- dl->descent = 0;
- /* The modeline is at the bottom of the gutters. */
- dl->ypos = WINDOW_BOTTOM (w);
-
- /* adjust for the bottom gutter */
- if (window_is_lowest (w))
- dl->ypos -= FRAME_BOTTOM_GUTTER_BOUNDS (f);
-
- rb.findex = MODELINE_INDEX;
- rb.xpos = dl->bounds.left_out;
- rb.width = dl->bounds.right_out - dl->bounds.left_out;
- rb.bufpos = 0;
- rb.endpos = 0;
- rb.type = RUNE_HLINE;
- rb.object.hline.thickness = 1;
- rb.object.hline.yoffset = 0;
- rb.cursor_type = NO_CURSOR;
-
- if (!EQ (Qzero, w->modeline_shadow_thickness)
- && FRAME_WIN_P (f))
- {
- int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
-
- dl->ypos -= shadow_thickness;
- rb.xpos += shadow_thickness;
- rb.width -= 2 * shadow_thickness;
- }
-
- Dynarr_add (db->runes, rb);
- return;
- }
-
- /* !!#### not right; needs to compute the max height of
- all the charsets */
- font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii);
-
- dl->ascent = XFONT_INSTANCE (font_inst)->ascent;
- dl->descent = XFONT_INSTANCE (font_inst)->descent;
-
- min_pixpos = dl->bounds.left_out;
- max_pixpos = dl->bounds.right_out;
-
- if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
- {
- int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
-
- ypos_adj = shadow_thickness;
- min_pixpos += shadow_thickness;
- max_pixpos -= shadow_thickness;
- }
- else
- ypos_adj = 0;
-
- generate_formatted_string_db (b->modeline_format,
- b->generated_modeline_string, w, dl, db,
- MODELINE_INDEX, min_pixpos, max_pixpos, type);
-
- /* The modeline is at the bottom of the gutters. We have to wait to
- set this until we've generated the modeline in order to account
- for any embedded faces. */
- dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
- /* adjust for the bottom gutter */
- if (window_is_lowest (w))
- dl->ypos -= FRAME_BOTTOM_GUTTER_BOUNDS (f);
-}
-
-static void
+/* This function is also used in frame.c by `generate_title_string' */
+void
generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
struct window *w, struct display_line *dl,
struct display_block *db, face_index findex,
pos_data data;
int c_pixpos;
+ Charcount offset = 0;
xzero (data);
data.d = d;
Dynarr_reset (formatted_string_extent_start_dynarr);
Dynarr_reset (formatted_string_extent_end_dynarr);
- /* This recursively builds up the modeline. */
+ /* result_str is nil when we're building a frame or icon title. Otherwise,
+ we're building a modeline, so the offset starts at the modeline
+ horizontal scrolling ammount */
+ if (! NILP (result_str))
+ offset = w->modeline_hscroll;
generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0,
- max_pixpos - min_pixpos, findex, type);
+ max_pixpos - min_pixpos, findex, type, &offset,
+ Qnil);
if (Dynarr_length (db->runes))
{
Bufbyte *strdata;
struct buffer *buf = XBUFFER (WINDOW_BUFFER (w));
+ in_modeline_generation = 1;
+
detach_all_extents (result_str);
resize_string (XSTRING (result_str), -1,
data.bytepos - XSTRING_LENGTH (result_str));
{
if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
{
- len += (set_charptr_emchar
- (strdata + len, Dynarr_atp (db->runes,
- elt)->object.chr.ch));
+ Charc ec = Dynarr_atp (db->runes, elt)->object.cglyph;
+
+ len += (set_charptr_emchar (strdata + len,
+ DECODE_CHAR (ec.charset,
+ ec.code_point)));
}
}
Dynarr_at (formatted_string_extent_end_dynarr, elt),
result_str);
}
+
+ in_modeline_generation = 0;
}
}
+/* Ensure that the given display line DL accurately represents the
+ modeline for the given window. */
+static void
+generate_modeline (struct window *w, struct display_line *dl, int type)
+{
+ struct buffer *b = XBUFFER (w->buffer);
+ struct frame *f = XFRAME (w->frame);
+ struct device *d = XDEVICE (f->device);
+
+ /* Unlike display line and rune pointers, this one can't change underneath
+ our feet. */
+ struct display_block *db = get_display_block_from_line (dl, TEXT);
+ int max_pixpos, min_pixpos, ypos_adj;
+ Lisp_Object font_inst;
+
+ /* This will actually determine incorrect inside boundaries for the
+ modeline since it ignores the margins. However being aware of this fact
+ we never use those values anywhere so it doesn't matter. */
+ dl->bounds = calculate_display_line_boundaries (w, 1);
+
+ /* We are generating a modeline. */
+ dl->modeline = 1;
+ dl->cursor_elt = -1;
+
+ /* Reset the runes on the modeline. */
+ Dynarr_reset (db->runes);
+
+ if (!WINDOW_HAS_MODELINE_P (w))
+ {
+ struct rune rb;
+
+ /* If there is a horizontal scrollbar, don't add anything. */
+ if (window_scrollbar_height (w))
+ return;
+
+ dl->ascent = DEVMETH (d, divider_height, ());
+ dl->descent = 0;
+ /* The modeline is at the bottom of the gutters. */
+ dl->ypos = WINDOW_BOTTOM (w);
+
+ rb.findex = MODELINE_INDEX;
+ rb.xpos = dl->bounds.left_out;
+ rb.width = dl->bounds.right_out - dl->bounds.left_out;
+ rb.bufpos = 0;
+ rb.endpos = 0;
+ rb.type = RUNE_HLINE;
+ rb.object.hline.thickness = 1;
+ rb.object.hline.yoffset = 0;
+ rb.cursor_type = NO_CURSOR;
+
+ if (!EQ (Qzero, w->modeline_shadow_thickness)
+ && FRAME_WIN_P (f))
+ {
+ int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
+
+ dl->ypos -= shadow_thickness;
+ rb.xpos += shadow_thickness;
+ rb.width -= 2 * shadow_thickness;
+ }
+
+ Dynarr_add (db->runes, rb);
+ return;
+ }
+
+ /* !!#### not right; needs to compute the max height of
+ all the charsets */
+ font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii);
+
+ dl->ascent = XFONT_INSTANCE (font_inst)->ascent;
+ dl->descent = XFONT_INSTANCE (font_inst)->descent;
+
+ min_pixpos = dl->bounds.left_out;
+ max_pixpos = dl->bounds.right_out;
+
+ if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
+ {
+ int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
+
+ ypos_adj = shadow_thickness;
+ min_pixpos += shadow_thickness;
+ max_pixpos -= shadow_thickness;
+ }
+ else
+ ypos_adj = 0;
+
+ generate_formatted_string_db (b->modeline_format,
+ b->generated_modeline_string, w, dl, db,
+ MODELINE_INDEX, min_pixpos, max_pixpos, type);
+
+ /* The modeline is at the bottom of the gutters. We have to wait to
+ set this until we've generated the modeline in order to account
+ for any embedded faces. */
+ dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
+}
+
static Charcount
-add_string_to_fstring_db_runes (pos_data *data, CONST Bufbyte *str,
+add_string_to_fstring_db_runes (pos_data *data, const Bufbyte *str,
Charcount pos, Charcount min_pos, Charcount max_pos)
{
/* This function has been Mule-ized. */
Charcount end;
- CONST Bufbyte *cur_pos = str;
+ const Bufbyte *cur_pos = str;
struct display_block *db = data->db;
data->blank_width = space_width (XWINDOW (data->window));
add_blank_rune (data, NULL, 0);
end = (Dynarr_length (db->runes) +
- bytecount_to_charcount (str, strlen ((CONST char *) str)));
+ bytecount_to_charcount (str, strlen ((const char *) str)));
if (max_pos != -1)
end = min (max_pos, end);
while (pos < end && *cur_pos)
{
- CONST Bufbyte *old_cur_pos = cur_pos;
+ const Bufbyte *old_cur_pos = cur_pos;
int succeeded;
data->ch = charptr_emchar (cur_pos);
modeline extents. */
static Charcount
add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph,
- Charcount pos, Charcount min_pos, Charcount max_pos)
+ Charcount pos, Charcount min_pos,
+ Charcount max_pos, Lisp_Object extent)
{
/* This function has been Mule-ized. */
Charcount end;
end = min (max_pos, end);
gb.glyph = glyph;
- gb.extent = Qnil;
+ gb.extent = extent;
add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
pos++;
generate_fstring_runes (struct window *w, pos_data *data, Charcount pos,
Charcount min_pos, Charcount max_pos,
Lisp_Object elt, int depth, int max_pixsize,
- face_index findex, int type)
+ face_index findex, int type, Charcount *offset,
+ Lisp_Object cur_ext)
{
/* This function has been Mule-ized. */
/* #### The other losing things in this function are:
if (this != last)
{
- /* The string is just a string. */
+ /* No %-construct */
Charcount size =
- bytecount_to_charcount (last, this - last) + pos;
- Charcount tmp_max = (max_pos == -1 ? size : min (size, max_pos));
+ bytecount_to_charcount (last, this - last);
- pos = add_string_to_fstring_db_runes (data, last, pos, pos,
- tmp_max);
+ if (size <= *offset)
+ *offset -= size;
+ else
+ {
+ Charcount tmp_max = (max_pos == -1 ? pos + size - *offset :
+ min (pos + size - *offset, max_pos));
+ const Bufbyte *tmp_last = charptr_n_addr (last, *offset);
+
+ pos = add_string_to_fstring_db_runes (data, tmp_last,
+ pos, pos, tmp_max);
+ *offset = 0;
+ }
}
else /* *this == '%' */
{
pos = generate_fstring_runes (w, data, pos, spec_width,
max_pos, Vglobal_mode_string,
depth, max_pixsize, findex,
- type);
+ type, offset, cur_ext);
}
else if (*this == '-')
{
while (num_to_add--)
pos = add_string_to_fstring_db_runes
- (data, (CONST Bufbyte *) "-", pos, pos, max_pos);
+ (data, (const Bufbyte *) "-", pos, pos, max_pos);
}
else if (*this != 0)
{
- Bufbyte *str;
Emchar ch = charptr_emchar (this);
+ Bufbyte *str;
+ Charcount size;
+
decode_mode_spec (w, ch, type);
str = Dynarr_atp (mode_spec_bufbyte_string, 0);
- pos = add_string_to_fstring_db_runes (data,str, pos, pos,
- max_pos);
+ size = bytecount_to_charcount
+ /* Skip the null character added by `decode_mode_spec' */
+ (str, Dynarr_length (mode_spec_bufbyte_string)) - 1;
+
+ if (size <= *offset)
+ *offset -= size;
+ else
+ {
+ const Bufbyte *tmp_str = charptr_n_addr (str, *offset);
+
+ /* #### NOTE: I don't understand why a tmp_max is not
+ computed and used here as in the plain string case
+ above. -- dv */
+ pos = add_string_to_fstring_db_runes (data, tmp_str,
+ pos, pos,
+ max_pos);
+ *offset = 0;
+ }
}
/* NOT this++. There could be any sort of character at
if (!UNBOUNDP (tem))
{
- /* If value is a string, output that string literally:
+ /* If value is a string, output that string literally:
don't check for % within it. */
if (STRINGP (tem))
{
- pos =
- add_string_to_fstring_db_runes
- (data, XSTRING_DATA (tem), pos, min_pos, max_pos);
+ Bufbyte *str = XSTRING_DATA (tem);
+ Charcount size = XSTRING_CHAR_LENGTH (tem);
+
+ if (size <= *offset)
+ *offset -= size;
+ else
+ {
+ const Bufbyte *tmp_str = charptr_n_addr (str, *offset);
+
+ /* #### NOTE: I don't understand why a tmp_max is not
+ computed and used here as in the plain string case
+ above. -- dv */
+ pos = add_string_to_fstring_db_runes (data, tmp_str, pos,
+ min_pos, max_pos);
+ *offset = 0;
+ }
}
/* Give up right away for nil or t. */
else if (!EQ (tem, elt))
else if (CONSP (elt))
{
/* A cons cell: four distinct cases.
- * If first element is a string or a cons, process all the elements
- * and effectively concatenate them.
- * If first element is a negative number, truncate displaying cdr to
- * at most that many characters. If positive, pad (with spaces)
- * to at least that many characters.
- * If first element is a symbol, process the cadr or caddr recursively
- * according to whether the symbol's value is non-nil or nil.
- * If first element is a face, process the cdr recursively
- * without altering the depth.
+ * - If first element is a string or a cons, process all the elements
+ * and effectively concatenate them.
+ * - If first element is a negative number, truncate displaying cdr to
+ * at most that many characters. If positive, pad (with spaces)
+ * to at least that many characters.
+ * - If first element is another symbol, process the cadr or caddr
+ * recursively according to whether the symbol's value is non-nil or
+ * nil.
+ * - If first element is an extent, process the cdr recursively
+ * and handle the extent's face.
*/
+
Lisp_Object car, tem;
car = XCAR (elt);
if (SYMBOLP (car))
- {
- elt = XCDR (elt);
- if (!CONSP (elt))
- goto invalid;
- tem = symbol_value_in_buffer (car, w->buffer);
- /* elt is now the cdr, and we know it is a cons cell.
- Use its car if CAR has a non-nil value. */
- if (!UNBOUNDP (tem))
- {
- if (!NILP (tem))
- {
- elt = XCAR (elt);
- goto tail_recurse;
- }
- }
- /* Symbol's value is nil (or symbol is unbound)
- * Get the cddr of the original list
- * and if possible find the caddr and use that.
- */
- elt = XCDR (elt);
- if (NILP (elt))
- ;
- else if (!CONSP (elt))
- goto invalid;
- else
- {
- elt = XCAR (elt);
- goto tail_recurse;
- }
- }
+ {
+ elt = XCDR (elt);
+ if (!CONSP (elt))
+ goto invalid;
+
+ tem = symbol_value_in_buffer (car, w->buffer);
+ /* elt is now the cdr, and we know it is a cons cell.
+ Use its car if CAR has a non-nil value. */
+ if (!UNBOUNDP (tem))
+ {
+ if (!NILP (tem))
+ {
+ elt = XCAR (elt);
+ goto tail_recurse;
+ }
+ }
+ /* Symbol's value is nil (or symbol is unbound)
+ * Get the cddr of the original list
+ * and if possible find the caddr and use that.
+ */
+ elt = XCDR (elt);
+ if (NILP (elt))
+ ;
+ else if (!CONSP (elt))
+ goto invalid;
+ else
+ {
+ elt = XCAR (elt);
+ goto tail_recurse;
+ }
+ }
else if (INTP (car))
{
Charcount lim = XINT (car);
else if (STRINGP (car) || CONSP (car))
{
int limit = 50;
+
/* LIMIT is to protect against circular lists. */
while (CONSP (elt) && --limit > 0
&& (pos < max_pos || max_pos == -1))
{
pos = generate_fstring_runes (w, data, pos, pos, max_pos,
- XCAR (elt), depth,
- max_pixsize, findex, type);
+ XCAR (elt), depth, max_pixsize,
+ findex, type, offset, cur_ext);
elt = XCDR (elt);
}
}
data->findex = new_findex;
pos = generate_fstring_runes (w, data, pos, pos, max_pos,
XCDR (elt), depth - 1,
- max_pixsize, new_findex, type);
+ max_pixsize, new_findex, type,
+ offset, car);
data->findex = old_findex;
Dynarr_add (formatted_string_extent_dynarr, ext);
Dynarr_add (formatted_string_extent_start_dynarr, start);
}
else if (GLYPHP (elt))
{
- pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos);
+ /* Glyphs are considered as one character with respect to the modeline
+ horizontal scrolling facility. -- dv */
+ if (*offset > 0)
+ *offset -= 1;
+ else
+ pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos,
+ cur_ext);
}
else
{
invalid:
- pos =
- add_string_to_fstring_db_runes
- (data, (CONST Bufbyte *) GETTEXT ("*invalid*"), pos, min_pos,
- max_pos);
+ {
+ char *str = GETTEXT ("*invalid*");
+ Charcount size = (Charcount) strlen (str); /* is this ok ?? -- dv */
+
+ if (size <= *offset)
+ *offset -= size;
+ else
+ {
+ const Bufbyte *tmp_str =
+ charptr_n_addr ((const Bufbyte *) str, *offset);
+
+ /* #### NOTE: I don't understand why a tmp_max is not computed and
+ used here as in the plain string case above. -- dv */
+ pos = add_string_to_fstring_db_runes (data, tmp_str, pos,
+ min_pos, max_pos);
+ *offset = 0;
+ }
+ }
}
if (min_pos > pos)
{
- add_string_to_fstring_db_runes (data, (CONST Bufbyte *) "", pos, min_pos,
- -1);
+ add_string_to_fstring_db_runes (data, (const Bufbyte *) "", pos,
+ min_pos, -1);
}
return pos;
}
-/* The caller is responsible for freeing the returned string. */
-Bufbyte *
-generate_formatted_string (struct window *w, Lisp_Object format_str,
- Lisp_Object result_str, face_index findex, int type)
-{
- struct display_line *dl;
- struct display_block *db;
- int elt = 0;
-
- dl = &formatted_string_display_line;
- db = get_display_block_from_line (dl, TEXT);
- Dynarr_reset (db->runes);
-
- generate_formatted_string_db (format_str, result_str, w, dl, db, findex, 0,
- -1, type);
-
- Dynarr_reset (formatted_string_emchar_dynarr);
- while (elt < Dynarr_length (db->runes))
- {
- if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
- Dynarr_add (formatted_string_emchar_dynarr,
- Dynarr_atp (db->runes, elt)->object.chr.ch);
- elt++;
- }
-
- return
- convert_emchar_string_into_malloced_string
- ( Dynarr_atp (formatted_string_emchar_dynarr, 0),
- Dynarr_length (formatted_string_emchar_dynarr), 0);
-}
-
/* Update just the modeline. Assumes the desired display structs. If
they do not have a modeline block, it does nothing. */
static void
against this case. */
struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0;
struct device *d = XDEVICE (f->device);
- struct Lisp_String* s = XSTRING (disp_string);
+ Lisp_String* s = XSTRING (disp_string);
/* we're working with these a lot so precalculate them */
Bytecount slen = XSTRING_LENGTH (disp_string);
dl->used_prop_data = 0;
dl->num_chars = 0;
+ dl->line_continuation = 0;
/* set up faces to use for clearing areas, used by
output_display_line */
}
else
{
- dl->left_margin_findex =
+ dl->left_margin_findex =
get_builtin_face_cache_index (w, Vleft_margin_face);
- dl->right_margin_findex =
+ dl->right_margin_findex =
get_builtin_face_cache_index (w, Vright_margin_face);
}
data.start_col = 0;
/* I don't think we want this, string areas should not scroll with
- the window
+ the window
data.start_col = w->hscroll;
data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
*/
/* data.bi_bufpos is already at the start of the next line. */
+ dl->line_continuation = 1;
gb.glyph = Vcontinuation_glyph;
cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
}
if (truncate_win && data.bi_bufpos == bi_string_zv)
{
- CONST Bufbyte* endb = charptr_n_addr (string_data (s), bi_string_zv);
+ const Bufbyte* endb = charptr_n_addr (string_data (s), bi_string_zv);
DEC_CHARPTR (endb);
if (charptr_emchar (endb) != '\n')
{
{
struct rune *rb = Dynarr_atp (db->runes, elt);
- if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
+ if ((rb->type == RUNE_CHAR
+ && EQ (rb->object.cglyph.charset, Vcharset_ascii)
+ && rb->object.cglyph.code_point == ' ')
|| rb->type == RUNE_BLANK)
{
dl->bounds.left_white += rb->width;
{
struct rune *rb = Dynarr_atp (db->runes, elt);
- if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
- && isspace (rb->object.chr.ch))
+ if (!(rb->type == RUNE_CHAR
+ && (EQ (rb->object.cglyph.charset, Vcharset_ascii)
+ || EQ (rb->object.cglyph.charset, Vcharset_control_1)
+ || EQ (rb->object.cglyph.charset, Vcharset_latin_iso8859_1))
+ && isspace (rb->object.cglyph.code_point))
&& !rb->type == RUNE_BLANK)
{
dl->bounds.right_white = rb->xpos + rb->width;
else
dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, data.bi_bufpos) - 1;
if (truncate_win)
- data.dl->num_chars =
+ data.dl->num_chars =
string_column_at_point (s, dl->end_bufpos, b ? XINT (b->tab_width) : 8);
else
/* This doesn't correctly take into account tabs and control
representation of the buffer contents starting from the given
position when displayed in the given window. The display line ends
when the contents of the line reach the right boundary of the given
- window.
-
+ window.
+
This is very similar to generate_display_line but with the same
limitations as create_string_text_block. I have taken the liberty
of fixing the bytind stuff though.*/
Bufpos ret_bufpos;
/* you must set bounds before calling this. */
-
+
/* Reset what this line is using. */
if (dl->display_blocks)
Dynarr_reset (dl->display_blocks);
int ypos = WINDOW_TEXT_TOP (w);
int yend; /* set farther down */
int yclip = WINDOW_TEXT_TOP_CLIP (w);
+ int force;
prop_block_dynarr *prop;
layout_bounds bounds;
else
prop = 0;
- while (ypos < yend)
+ /* When we are computing things for scrolling purposes, make
+ sure at least one line is always generated */
+ force = (type == CMOTION_DISP);
+
+ /* Make sure this is set always */
+ /* Note the conversion at end */
+ w->window_end_pos[type] = start_pos;
+ while (ypos < yend || force)
{
struct display_line dl;
struct display_line *dlp;
/* See if we've been asked to start midway through a line, for
partial display line scrolling. */
- if (yclip)
+ if (yclip)
{
dlp->top_clip = yclip;
yclip = 0;
the top clip and the bottom clip. */
visible_height -= (dlp->clip + dlp->top_clip);
- if (visible_height < VERTICAL_CLIP (w, 1))
+ if (visible_height < VERTICAL_CLIP (w, 1) && !force)
{
if (local)
free_display_line (dlp);
generate_display_line call. */
if (start_pos > BUF_ZV (b))
break;
+
+ force = 0;
}
if (prop)
Dynarr_free (prop);
/* #### More not quite right, but close enough. */
- /* #### Ben sez: apparently window_end_pos[] is measured
+ /* Ben sez: apparently window_end_pos[] is measured
as the number of characters between the window end and the
end of the buffer? This seems rather weirdo. What's
- the justification for this? */
+ the justification for this?
+
+ JV sez: Because BUF_Z (b) would be a good initial value, however
+ that can change. This representation allows initalizing with 0.
+ */
w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type];
if (need_modeline)
assert (cdl->end_bufpos == ddl->end_bufpos);
assert (cdl->offset == ddl->offset);
- /* If the last rune is already a continuation glyph, fail.
- #### We should be able to handle this better. */
- {
- struct display_block *db = get_display_block_from_line (ddl, TEXT);
- if (Dynarr_length (db->runes))
- {
- struct rune *rb =
- Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
-
- if (rb->type == RUNE_DGLYPH
- && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
- return 0;
- }
- }
+ /* If the line continues to next display line, fail. */
+ if (ddl->line_continuation)
+ return 0;
/* If the line was generated using propagation data, fail. */
if (ddl->used_prop_data)
return 0;
}
- /* If the last rune is now a continuation glyph, fail. */
- {
- struct display_block *db = get_display_block_from_line (ddl, TEXT);
- if (Dynarr_length (db->runes))
- {
- struct rune *rb =
- Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
-
- if (rb->type == RUNE_DGLYPH
- && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
- return 0;
- }
- }
+ /* If the line continues to next display line, fail. */
+ if (ddl->line_continuation)
+ return 0;
/* If any line position parameters have changed or a
cursor has disappeared or disappeared, fail. */
the cache purely because glyphs have changed - this is now
handled by the dirty flag.*/
if ((!echo_active && b != window_display_buffer (w))
- || !Dynarr_length (w->glyph_cachels))
+ || !Dynarr_length (w->glyph_cachels) || f->faces_changed)
reset_glyph_cachels (w);
else
mark_glyph_cachels_as_not_updated (w);
&& !f->faces_changed
&& !f->glyphs_changed
&& !f->subwindows_changed
- && !f->subwindows_state_changed
+ /* && !f->subwindows_state_changed*/
&& !f->point_changed
&& !f->windows_structure_changed)
{
&& !f->faces_changed
&& !f->glyphs_changed
&& !f->subwindows_changed
- && !f->subwindows_state_changed
+ /* && !f->subwindows_state_changed*/
&& !f->windows_structure_changed)
{
if (point_visible (w, pointm, CURRENT_DISP)
&& !f->faces_changed
&& !f->glyphs_changed
&& !f->subwindows_changed
- && !f->subwindows_state_changed
+ /* && !f->subwindows_state_changed*/
&& !f->windows_structure_changed
&& !f->frame_changed
&& !truncation_changed
somewhere else once tty updates occur on a per-frame basis. */
mark_face_cachels_as_clean (w);
- /* The glyph cachels only get dirty if someone changed something. */
+ /* The glyph cachels only get dirty if someone changed something.
+ Since redisplay has now effectively ended we can reset the dirty
+ flag since everything must be up-to-date. */
if (glyphs_changed)
mark_glyph_cachels_as_clean (w);
/* Ensure that all windows on the given frame are correctly displayed. */
-static int
+int
redisplay_frame (struct frame *f, int preemption_check)
{
struct device *d = XDEVICE (f->device);
return 1;
}
+ if (!internal_equal (f->old_buffer_alist, f->buffer_alist, 0))
+ {
+ Lisp_Object frame;
+
+ f->old_buffer_alist = Freplace_list (f->old_buffer_alist,
+ f->buffer_alist);
+ XSETFRAME (frame, f);
+ va_run_hook_with_args (Qbuffer_list_changed_hook, 1, frame);
+ }
+
/* Before we put a hold on frame size changes, attempt to process
any which are already pending. */
if (f->size_change_pending)
being handled. */
update_frame_menubars (f);
#endif /* HAVE_MENUBARS */
- /* widgets are similar to menus in that they can call lisp to
- determine activation etc. Therefore update them before we get
- into redisplay. This is primarily for connected widgets such as
- radio buttons. */
- update_frame_subwindows (f);
#ifdef HAVE_TOOLBARS
/* Update the toolbars. */
update_frame_toolbars (f);
#endif /* HAVE_TOOLBARS */
+ /* Gutter update proper has to be done inside display when no frame
+ size changes can occur, thus we separately update the gutter
+ geometry here if it needs it. */
+ update_frame_gutter_geometry (f);
/* If we clear the frame we have to force its contents to be redrawn. */
if (f->clear)
f->frame_changed = 1;
- /* invalidate the subwindow cache. We use subwindows_changed here to
+ /* Invalidate the subwindow cache. We use subwindows_changed here to
cause subwindows to get instantiated. This is because
subwindows_state_changed is less strict - dealing with things
like the clicked state of button. We have to do this before
redisplaying the gutters as subwindows get unmapped in the
process.*/
- if (!Dynarr_length (f->subwindow_cachels)
- || f->subwindows_changed
- || f->frame_changed)
+ if (f->frame_changed || f->subwindows_changed)
{
- reset_subwindow_cachels (f);
/* we have to do this so the gutter gets regenerated. */
reset_gutter_display_lines (f);
}
- else
- mark_subwindow_cachels_as_not_updated (f);
- /* We can now update the gutters, safe in the knowledge that our
- efforts won't get undone. */
- update_frame_gutters (f);
hold_frame_size_changes ();
#### If a frame-size change does occur we should probably
actually be preempting redisplay. */
+ MAYBE_DEVMETH (d, frame_output_begin, (f));
+
+ /* We can now update the gutters, safe in the knowledge that our
+ efforts won't get undone. */
+
+ /* This can call lisp, but redisplay is protected by binding
+ inhibit_quit. More importantly the code involving display lines
+ *assumes* that GC will not happen and so does not GCPRO
+ anything. Since we use this code the whole time with the gutters
+ we cannot allow GC to happen when manipulating the gutters. */
+ update_frame_gutters (f);
+
/* Erase the frame before outputting its contents. */
if (f->clear)
{
- DEVMETH (d, clear_frame, (f));
+ MAYBE_DEVMETH (d, clear_frame, (f));
}
/* Do the selected window first. */
/* Then do the rest. */
redisplay_windows (f->root_window, 1);
- /* We now call the output_end routine for tty frames. We delay
- doing so in order to avoid cursor flicker. So much for 100%
- encapsulation. */
- if (FRAME_TTY_P (f))
- DEVMETH (d, output_end, (d));
+ MAYBE_DEVMETH (d, frame_output_end, (f));
update_frame_title (f);
return 0;
}
-/* Ensure that all frames on the given device are correctly displayed. */
+/* Ensure that all frames on the given device are correctly displayed.
+ If AUTOMATIC is non-zero, and the device implementation indicates
+ no automatic redisplay, as printers do, then the device is not
+ redisplayed. AUTOMATIC is set to zero when called from lisp
+ functions (redraw-device) and (redisplay-device), and to non-zero
+ when called from "lazy" redisplay();
+*/
static int
-redisplay_device (struct device *d)
+redisplay_device (struct device *d, int automatic)
{
Lisp_Object frame, frmcons;
int preempted = 0;
int size_change_failed = 0;
struct frame *f;
+ if (automatic
+ && (MAYBE_INT_DEVMETH (d, device_implementation_flags, ())
+ & XDEVIMPF_NO_AUTO_REDISPLAY))
+ return 0;
+
if (DEVICE_STREAM_P (d)) /* nothing to do */
return 0;
if (FRAME_REPAINT_P (f))
{
- if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)
- || f->size_changed)
+ if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f))
{
preempted = redisplay_frame (f, 0);
}
handle_asynch_device_change ();
if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP &&
- !size_changed && !disable_preemption && preemption_count < max_preempts)
+ !disable_preemption && preemption_count < max_preempts)
goto done;
DEVICE_LOOP_NO_BREAK (devcons, concons)
struct device *d = XDEVICE (XCAR (devcons));
int preempted;
- if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d)
- || d->size_changed)
+ if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d))
{
- preempted = redisplay_device (d);
+ preempted = redisplay_device (d, 1);
if (preempted)
{
decode_mode_spec (struct window *w, Emchar spec, int type)
{
Lisp_Object obj = Qnil;
- CONST char *str = NULL;
+ const char *str = NULL;
struct buffer *b = XBUFFER (w->buffer);
Dynarr_reset (mode_spec_bufbyte_string);
long_to_string (buf, col);
Dynarr_add_many (mode_spec_bufbyte_string,
- (CONST Bufbyte *) buf, strlen (buf));
+ (const Bufbyte *) buf, strlen (buf));
goto decode_mode_spec_done;
}
}
}
-static void
+/* See the comment in image_instantiate_cache_result as to why marking
+ the glyph will also mark the image_instance. */
+void
mark_redisplay_structs (display_line_dynarr *dla)
{
display_line *dl = Dynarr_atp (dla, 0);
struct frame *f = XFRAME (XCAR (frmcons));
update_frame_window_mirror (f);
mark_window_mirror (f->root_mirror);
+ mark_gutters (f);
}
}
\f
else
{
struct line_start_cache lsc;
-
+
lsc.start = dl->bufpos;
lsc.end = dl->end_bufpos;
lsc.height = dl->ascent + dl->descent;
point_would_be_visible (struct window *w, Bufpos startp, Bufpos point)
{
struct buffer *b = XBUFFER (w->buffer);
- int pixpos = 0;
+ int pixpos = -WINDOW_TEXT_TOP_CLIP(w);
int bottom = WINDOW_TEXT_HEIGHT (w);
int start_elt;
displayed. The end of the last line is also know as the window end
position.
+ WARNING: It is possible that rediplay failed to layout any lines for the
+ windows. Under normal circumstances this is rare. However it seems that it
+ does occur in the following situation: A mouse event has come in and we
+ need to compute its location in a window. That code (in
+ pixel_to_glyph_translation) already can handle 0 as an error return value.
+
#### With a little work this could probably be reworked as just a
call to start_with_line_at_pixpos. */
static Bufpos
-start_end_of_last_line (struct window *w, Bufpos startp, int end)
+start_end_of_last_line (struct window *w, Bufpos startp, int end,
+ int may_error)
{
struct buffer *b = XBUFFER (w->buffer);
line_start_cache_dynarr *cache = w->line_start_cache;
start_elt = point_in_line_start_cache (w, cur_start, 0);
if (start_elt == -1)
- abort (); /* this had better never happen */
+ return may_error ? 0 : startp;
while (1)
{
Bufpos
start_of_last_line (struct window *w, Bufpos startp)
{
- return start_end_of_last_line (w, startp, 0);
+ return start_end_of_last_line (w, startp, 0 , 0);
}
/* For the given window W, if display starts at STARTP, what will be
Bufpos
end_of_last_line (struct window *w, Bufpos startp)
{
- return start_end_of_last_line (w, startp, 1);
+ return start_end_of_last_line (w, startp, 1, 0);
+}
+
+static Bufpos
+end_of_last_line_may_error (struct window *w, Bufpos startp)
+{
+ return start_end_of_last_line (w, startp, 1, 1);
}
+
/* For window W, what does the starting position have to be so that
the line containing POINT will cover pixel position PIXPOS. */
assert (cur_elt >= -1);
/* This used to be cur_elt>=0 under the assumption that if
point is in the top line and not at BUF_BEGV, then
- setting the window_start to a newline before the start of
+ setting the window_start to a newline before the start of
the first line will always cause scrolling.
However in my (jv) opinion this is wrong. That new line
on that assert. So we have no option but to continue the
search if we found point at the top of the line_start_cache
again. */
- cur_pos = Dynarr_atp (w->line_start_cache,0)->start;
+ cur_pos = Dynarr_atp (w->line_start_cache,0)->start;
}
prev_pos = cur_pos;
}
validate_line_start_cache (w);
w->line_cache_validation_override++;
- updating_line_start_cache = 1;
if (from < BUF_BEGV (b))
from = BUF_BEGV (b);
if (from > to)
{
- updating_line_start_cache = 0;
w->line_cache_validation_override--;
return;
}
/* Check to see if the desired range is already in the cache. */
if (from >= low_bound && to <= high_bound)
{
- updating_line_start_cache = 0;
w->line_cache_validation_override--;
return;
}
update_internal_cache_list (w, DESIRED_DISP);
if (!Dynarr_length (internal_cache))
{
- updating_line_start_cache = 0;
w->line_cache_validation_override--;
return;
}
{
Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
Dynarr_length (internal_cache));
- updating_line_start_cache = 0;
w->line_cache_validation_override--;
return;
}
the bounds of the DESIRED structs in the first place. */
if (start >= low_bound && end <= high_bound)
{
- updating_line_start_cache = 0;
w->line_cache_validation_override--;
return;
}
Dynarr_reset (cache);
Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
Dynarr_length (internal_cache));
- updating_line_start_cache = 0;
w->line_cache_validation_override--;
return;
}
Dynarr_reset (cache);
Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
Dynarr_length (internal_cache));
- updating_line_start_cache = 0;
w->line_cache_validation_override--;
return;
}
Dynarr_length (internal_cache) - ic_elt);
}
- updating_line_start_cache = 0;
w->line_cache_validation_override--;
return;
}
update_internal_cache_list (w, CMOTION_DISP);
/* If this assert is triggered then regenerate_window failed
- to layout a single line. That is not supposed to be
- possible because we impose a minimum height on the buffer
- and override vertical clip when we are in here. */
- /* #### Ah, but it is because the window may temporarily
- exist but not have any lines at all if the minibuffer is
- real big. Look into that situation better. */
- if (!Dynarr_length (internal_cache))
- {
- if (old_lb == -1 && low_bound == -1)
- {
- updating_line_start_cache = 0;
- w->line_cache_validation_override--;
- return;
- }
-
- assert (Dynarr_length (internal_cache));
- }
+ to layout a single line. This is not possible since we
+ force at least a single line to be layout for CMOTION_DISP */
+ assert (Dynarr_length (internal_cache));
assert (startp == Dynarr_atp (internal_cache, 0)->start);
ic_elt = Dynarr_length (internal_cache) - 1;
startp = new_startp;
if (startp > BUF_ZV (b))
{
- updating_line_start_cache = 0;
w->line_cache_validation_override--;
return;
}
while (to > high_bound);
}
- updating_line_start_cache = 0;
w->line_cache_validation_override--;
assert (to <= high_bound);
}
}
else if (past_end
|| (rb->type == RUNE_CHAR
- && rb->object.chr.ch == '\n'))
+ && EQ (rb->object.cglyph.charset,
+ Vcharset_ascii)
+ && rb->object.cglyph.code_point == '\n'))
{
(*row)--;
/* At this point we may have glyphs in the right
if (!MARKERP ((*w)->start[CURRENT_DISP]))
*closest = 0;
else
- *closest = end_of_last_line (*w,
+ *closest = end_of_last_line_may_error (*w,
marker_position ((*w)->start[CURRENT_DISP]));
*col = 0;
UPDATE_CACHE_RETURN;
if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f))
{
Lisp_Object window = FRAME_MINIBUF_WINDOW (f);
+
+ MAYBE_DEVMETH (d, frame_output_begin, (f));
+
/*
* If the frame size has changed, there may be random
* chud on the screen left from previous messages
*/
if (f->echo_area_garbaged)
{
- DEVMETH (d, clear_frame, (f));
+ MAYBE_DEVMETH (d, clear_frame, (f));
f->echo_area_garbaged = 0;
}
redisplay_window (window, 0);
+ MAYBE_DEVMETH (d, frame_output_end, (f));
+
call_redisplay_end_triggers (XWINDOW (window), 0);
}
}
-
- /* We now call the output_end routine for tty frames. We delay
- doing so in order to avoid cursor flicker. So much for 100%
- encapsulation. */
- if (DEVICE_TTY_P (d))
- DEVMETH (d, output_end, (d));
}
return Qnil;
f->clear = 1;
redisplay_frame (f, 1);
+ /* See the comment in Fredisplay_frame. */
+ RESET_CHANGED_SET_FLAGS;
+
return unbind_to (count, Qnil);
}
redisplay_frame (f, 1);
+ /* If we don't reset the global redisplay flafs here, subsequent
+ changes to the display will not get registered by redisplay
+ because it thinks it already has registered changes. If you
+ really knew what you were doing you could confuse redisplay by
+ calling Fredisplay_frame while updating another frame. We assume
+ that if you know what you are doing you will not be that
+ stupid. */
+ RESET_CHANGED_SET_FLAGS;
+
return unbind_to (count, Qnil);
}
{
XFRAME (XCAR (frmcons))->clear = 1;
}
- redisplay_device (d);
+ redisplay_device (d, 0);
+
+ /* See the comment in Fredisplay_frame. */
+ RESET_CHANGED_SET_FLAGS;
return unbind_to (count, Qnil);
}
disable_preemption++;
}
- redisplay_device (d);
+ redisplay_device (d, 0);
+
+ /* See the comment in Fredisplay_frame. */
+ RESET_CHANGED_SET_FLAGS;
return unbind_to (count, Qnil);
}
if (!initialized)
#endif
{
- cmotion_display_lines = Dynarr_new (display_line);
- mode_spec_bufbyte_string = Dynarr_new (Bufbyte);
- formatted_string_emchar_dynarr = Dynarr_new (Emchar);
- formatted_string_extent_dynarr = Dynarr_new (EXTENT);
- formatted_string_extent_start_dynarr = Dynarr_new (Bytecount);
- formatted_string_extent_end_dynarr = Dynarr_new (Bytecount);
- internal_cache = Dynarr_new (line_start_cache);
- xzero (formatted_string_display_line);
+ if (!cmotion_display_lines)
+ cmotion_display_lines = Dynarr_new (display_line);
+ if (!mode_spec_bufbyte_string)
+ mode_spec_bufbyte_string = Dynarr_new (Bufbyte);
+ if (!formatted_string_extent_dynarr)
+ formatted_string_extent_dynarr = Dynarr_new (EXTENT);
+ if (!formatted_string_extent_start_dynarr)
+ formatted_string_extent_start_dynarr = Dynarr_new (Bytecount);
+ if (!formatted_string_extent_end_dynarr)
+ formatted_string_extent_end_dynarr = Dynarr_new (Bytecount);
+ if (!internal_cache)
+ internal_cache = Dynarr_new (line_start_cache);
}
/* window system is nil when in -batch mode */
defsymbol (&Qbar_cursor, "bar-cursor");
defsymbol (&Qredisplay_end_trigger_functions,
"redisplay-end-trigger-functions");
+ defsymbol (&Qtop_bottom, "top-bottom");
+ defsymbol (&Qbuffer_list_changed_hook, "buffer-list-changed-hook");
DEFSUBR (Fredisplay_echo_area);
DEFSUBR (Fredraw_frame);
}
void
-reinit_vars_of_redisplay (void)
-{
- updating_line_start_cache = 0;
-}
-
-void
vars_of_redisplay (void)
{
- reinit_vars_of_redisplay ();
#if 0
staticpro (&last_arrow_position);
Voverlay_arrow_position = Qnil;
DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /*
-String to display as an arrow. See also `overlay-arrow-position'.
+String or glyph to display as an arrow. See also `overlay-arrow-position'.
+(Note that despite the name of this variable, it can be set to a glyph as
+well as a string.)
*/ ,
redisplay_variable_changed);
Voverlay_arrow_string = Qnil;
redisplay_variable_changed);
truncate_partial_width_windows = 1;
- DEFVAR_BOOL ("visible-bell", &visible_bell /*
-*Non-nil means try to flash the frame to represent a bell.
+ DEFVAR_LISP ("visible-bell", &Vvisible_bell /*
+*Non-nil substitutes a visual signal for the audible bell.
+
+Default behavior is to flash the whole screen. On some platforms,
+special effects are available using the following values:
+
+'display Flash the whole screen (ie, the default behavior).
+'top-bottom Flash only the top and bottom lines of the selected frame.
+
+When effects are unavailable on a platform, the visual bell is the
+default, whole screen. (Currently only X supports any special effects.)
*/ );
- visible_bell = 0;
+ Vvisible_bell = Qnil;
DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /*
*Non-nil means no need to redraw entire frame after suspending.
#ifndef INHIBIT_REDISPLAY_HOOKS
xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /*
Function or functions to run before every redisplay.
-Functions on this hook must be careful to avoid signalling errors!
*/ );
Vpre_redisplay_hook = Qnil;
xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /*
Function or functions to run after every redisplay.
-Functions on this hook must be careful to avoid signalling errors!
*/ );
Vpost_redisplay_hook = Qnil;
#endif /* INHIBIT_REDISPLAY_HOOKS */
+ DEFVAR_LISP ("buffer-list-changed-hook", &Vbuffer_list_changed_hook /*
+Function or functions to call when a frame's buffer list has changed.
+This is called during redisplay, before redisplaying each frame.
+Functions on this hook are called with one argument, the frame.
+*/ );
+ Vbuffer_list_changed_hook = Qnil;
+
DEFVAR_INT ("display-warning-tick", &display_warning_tick /*
Bump this to tell the C code to call `display-warning-buffer'
at next redisplay. You should not normally change this; the function
Vleft_margin_width = Fmake_specifier (Qnatnum);
set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero)));
set_specifier_caching (Vleft_margin_width,
- slot_offset (struct window, left_margin_width),
+ offsetof (struct window, left_margin_width),
some_window_value_changed,
- slot_offset (struct frame, left_margin_width),
+ offsetof (struct frame, left_margin_width),
margin_width_changed_in_frame);
DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /*
Vright_margin_width = Fmake_specifier (Qnatnum);
set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero)));
set_specifier_caching (Vright_margin_width,
- slot_offset (struct window, right_margin_width),
+ offsetof (struct window, right_margin_width),
some_window_value_changed,
- slot_offset (struct frame, right_margin_width),
+ offsetof (struct frame, right_margin_width),
margin_width_changed_in_frame);
DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /*
Vminimum_line_ascent = Fmake_specifier (Qnatnum);
set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero)));
set_specifier_caching (Vminimum_line_ascent,
- slot_offset (struct window, minimum_line_ascent),
+ offsetof (struct window, minimum_line_ascent),
some_window_value_changed,
0, 0);
Vminimum_line_descent = Fmake_specifier (Qnatnum);
set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero)));
set_specifier_caching (Vminimum_line_descent,
- slot_offset (struct window, minimum_line_descent),
+ offsetof (struct window, minimum_line_descent),
some_window_value_changed,
0, 0);
Vuse_left_overflow = Fmake_specifier (Qboolean);
set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil)));
set_specifier_caching (Vuse_left_overflow,
- slot_offset (struct window, use_left_overflow),
+ offsetof (struct window, use_left_overflow),
some_window_value_changed,
0, 0);
Vuse_right_overflow = Fmake_specifier (Qboolean);
set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil)));
set_specifier_caching (Vuse_right_overflow,
- slot_offset (struct window, use_right_overflow),
+ offsetof (struct window, use_right_overflow),
some_window_value_changed,
0, 0);
Vtext_cursor_visible_p = Fmake_specifier (Qboolean);
set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt)));
set_specifier_caching (Vtext_cursor_visible_p,
- slot_offset (struct window, text_cursor_visible_p),
+ offsetof (struct window, text_cursor_visible_p),
text_cursor_visible_p_changed,
0, 0);