#include <config.h>
#include "lisp.h"
-#include <limits.h>
#include "buffer.h"
#include "commands.h"
#include "file-coding.h"
#endif
+#include "sysfile.h"
+
#ifdef HAVE_TTY
#include "console-tty.h"
-#ifdef HAVE_UNISTD_H
-#include <unistd.h> /* for isatty() */
-#endif
#endif /* HAVE_TTY */
/* Note: We have to be careful throughout this code to properly handle
#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. */
to be skipped before anything is displayed. */
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
- to be able to scroll over part of the glyph. */
+ be skipped. This is used for
+ 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
glyph differs from space_width (w).
struct extent_fragment *ef;
face_index findex;
- /* The height of a pixmap may either be predetermined if the user
- has set a baseline value, or it may be dependent on whatever the
- line ascent and descent values end up being, based just on font
- information. In the first case we can immediately update the
- values, thus their inclusion here. In the last case we cannot
- determine the actual contribution to the line height until we
- have finished laying out all text on the line. Thus we propagate
- the max height of such pixmaps and do a final calculation after
- all text has been added to the line. */
+ /* The height of a pixmap may either be predetermined if the user has set a
+ baseline value, or it may be dependent on whatever the line ascent and
+ descent values end up being, based just on font and pixmap-ascent
+ information. In the first case we can immediately update the values, thus
+ their inclusion here. In the last case we cannot determine the actual
+ contribution to the line height until we have finished laying out all text
+ on the line. Thus we propagate the max height of such pixmaps and do a
+ final calculation (in calculate_baseline()) after all text has been added
+ to the line. */
int new_ascent;
int new_descent;
int max_pixmap_height;
+ int need_baseline_computation;
+ int end_glyph_width; /* Well, it is the kitchen sink after all ... */
Lisp_Object result_str; /* String where we put the result of
generating a formatted string in the modeline. */
PROP_STRING,
PROP_CHAR,
PROP_MINIBUF_PROMPT,
- PROP_BLANK
+ PROP_BLANK,
+ PROP_GLYPH
};
/* Data that should be propagated to the next line. Either a single
- Emchar or a string of Bufbyte's.
+ Emchar, a string of Bufbyte's or a glyph.
The actual data that is propagated ends up as a Dynarr of these
blocks.
+ prop_blocks are used to indicate that data that was supposed to go
+ on the previous line couldn't actually be displayed. Generally this
+ shouldn't happen if we are clipping the end of lines. If we are
+ wrapping then we need to display the propagation data before moving
+ on. Its questionable whether we should wrap or clip glyphs in this
+ instance. Most e-lisp relies on clipping so we preserve this
+ behavior.
+
#### It's unclean that both Emchars and Bufbytes are here.
*/
int width;
face_index findex;
} p_blank;
+
+ struct
+ {
+ /* Not used as yet, but could be used to wrap rather than clip glyphs. */
+ int width;
+ Lisp_Object glyph;
+ } p_glyph;
+
} data;
};
static void update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
Bufpos point, int no_regen);
static int point_visible (struct window *w, Bufpos point, int type);
+static void calculate_yoffset (struct display_line *dl,
+ struct display_block *fixup);
+static void calculate_baseline (pos_data *data);
/* This used to be 10 but 30 seems to give much better performance. */
#define INIT_MAX_PREEMPTS 30
/* #### probably temporary */
-int cache_adjustment;
+Fixnum cache_adjustment;
/* This holds a string representing the text corresponding to a single
modeline % spec. */
static int preemption_count;
/* Minimum pixel height of clipped bottom display line. */
-int vertical_clip;
+Fixnum vertical_clip;
/* 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;
+Fixnum horizontal_clip;
/* Nonzero means reading single-character input with prompt
so put cursor on minibuffer after the prompt. */
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;
int toolbar_changed;
int toolbar_changed_set;
+/* Nonzero if some frame has changed the layout of internal elements
+ (gutters or toolbars). */
+int frame_layout_changed;
+
/* non-nil if any gutter has changed */
int gutter_changed;
int gutter_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,
/* The number of lines scroll a window by when point leaves the window; if
it is <=0 then point is centered in the window */
-int scroll_step;
+Fixnum scroll_step;
/* Scroll up to this many lines, to bring point back on screen. */
-int scroll_conservatively;
+Fixnum scroll_conservatively;
/* Marker for where to display an arrow on top of the buffer text. */
Lisp_Object Voverlay_arrow_position;
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
Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook;
#endif /* INHIBIT_REDISPLAY_HOOKS */
-static int last_display_warning_tick, display_warning_tick;
+static Fixnum last_display_warning_tick;
+static Fixnum display_warning_tick;
Lisp_Object Qdisplay_warning_buffer;
int inhibit_warning_display;
int column_number_start_at_one;
-#define WINDOW_SCROLLED(w) \
-(w->hscroll > 0 || w->left_xoffset)
+Lisp_Object Qtop_bottom;
+
+#define WINDOW_SCROLLED(w) ((w)->hscroll > 0 || (w)->left_xoffset)
\f
/***************************************************************************/
/***************************************************************************/
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
return bounds;
}
+/* This takes a display_block and its containing line and corrects the yoffset
+ of each glyph in the block to cater for the ascent of the line as a
+ whole. Must be called *after* the line-ascent is known! */
+
+static void
+calculate_yoffset (struct display_line *dl, struct display_block *fixup)
+{
+ int i;
+ for (i=0; i<Dynarr_length (fixup->runes); i++)
+ {
+ struct rune *r = Dynarr_atp (fixup->runes,i);
+ if (r->type == RUNE_DGLYPH)
+ {
+ if (r->object.dglyph.ascent < dl->ascent)
+ r->object.dglyph.yoffset = dl->ascent - r->object.dglyph.ascent +
+ r->object.dglyph.descent;
+ }
+ }
+}
+
+/* Calculate the textual baseline (the ascent and descent values for the
+ display_line as a whole).
+
+ If the baseline is completely blank, or contains no manually positioned
+ glyphs, then the textual baseline is simply the baseline of the default font.
+ (The `contains no manually positioned glyphs' part is actually done for
+ us by `add_emchar_rune'.)
+
+ If the baseline contains pixmaps, and they're all manually positioned, then
+ the textual baseline location is constrained that way, and we need do no
+ work.
+
+ If the baseline contains pixmaps, and at least one is automatically
+ positioned, then the textual ascent is the largest ascent on the line, and
+ the textual descent is the largest descent (which is how things are set up at
+ entry to this function anyway): except that if the max_ascent + max_descent
+ is too small for the height of the line (say you've adjusted the baseline of
+ a short glyph, and there's a tall one next to it), then take the ascent and
+ descent for the line individually from the largest of the explicitly set
+ ascent/descent, and the rescaled ascent/descent of the default font, scaled
+ such that the largest glyph will fit.
+
+ This means that if you have a short glyph (but taller than the default
+ font's descent) forced right under the baseline, and a really tall
+ automatically positioned glyph, that the descent for the line is just big
+ enough for the manually positioned short glyph, and the tall one uses as
+ much of that space as the default font would were it as tall as the tall
+ glyph; but that the ascent is big enough for the tall glyph to fit.
+
+ This behaviour means that under no circumstances will changing the baseline
+ of a short glyph cause a tall glyph to move around; nor will it move the
+ textual baseline more than necessary. (Changing a tall glyph's baseline
+ might move the text's baseline arbitrarily, of course.) */
+
+static void
+calculate_baseline (pos_data *data)
+{
+ /* Blank line: baseline is default font's baseline. */
+
+ if (!data->new_ascent && !data->new_descent)
+ {
+ /* We've got a blank line so initialize these values from the default
+ face. */
+ default_face_font_info (data->window, &data->new_ascent,
+ &data->new_descent, 0, 0, 0);
+ }
+
+ /* No automatically positioned glyphs? Return at once. */
+ if (!data->need_baseline_computation)
+ return;
+
+ /* Is the tallest glyph on the line automatically positioned?
+ If it's manually positioned, or it's automatically positioned
+ and there's enough room for it anyway, we need do no more work. */
+ if (data->max_pixmap_height > data->new_ascent + data->new_descent)
+ {
+ int default_font_ascent, default_font_descent, default_font_height;
+ int scaled_default_font_ascent, scaled_default_font_descent;
+
+ default_face_font_info (data->window, &default_font_ascent,
+ &default_font_descent, &default_font_height,
+ 0, 0);
+
+ scaled_default_font_ascent = data->max_pixmap_height *
+ default_font_ascent / default_font_height;
+
+ data->new_ascent = max (data->new_ascent, scaled_default_font_ascent);
+
+ /* The ascent may have expanded now. Do we still need to grow the descent,
+ or are things big enough?
+
+ The +1 caters for the baseline row itself. */
+ if (data->max_pixmap_height > data->new_ascent + data->new_descent)
+ {
+ scaled_default_font_descent = (data->max_pixmap_height *
+ default_font_descent / default_font_height) + 1;
+
+ data->new_descent = max (data->new_descent, scaled_default_font_descent);
+ }
+ }
+}
+
/* Given a display line and a starting position, ensure that the
contents of the display line accurately represent the visual
representation of the buffer contents starting from the given
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 =
return retval;
}
-/* Adds a character rune to a display block. If there is not enough
- room to fit the rune on the display block (as determined by the
- MAX_PIXPOS) then it adds nothing and returns ADD_FAILED. */
+/* Adds a character rune to a display block. If there is not enough room
+ to fit the rune on the display block (as determined by the MAX_PIXPOS)
+ then it adds nothing and returns ADD_FAILED. If
+ NO_CONTRIBUTE_TO_LINE_HEIGHT is non-zero, don't allow the char's height
+ to affect the total line height. (See add_intbyte_string_runes()). */
static prop_block_dynarr *
-add_emchar_rune (pos_data *data)
+add_emchar_rune_1 (pos_data *data, int no_contribute_to_line_height)
{
struct rune rb, *crb;
int width, local;
+ Charc char_glyph;
if (data->start_col)
{
if (data->ch == '\n')
{
+ char_glyph = ASCII_TO_CHARC ('\n');
data->font_is_bogus = 0;
/* Cheesy end-of-line pseudo-character. */
width = data->blank_width;
}
else
{
- Lisp_Object charset = CHAR_CHARSET (data->ch);
+ Lisp_Object charset;
+
+ char_glyph = CHAR_TO_CHARC (data->ch);
+ charset = CHARC_CHARSET (char_glyph);
if (!EQ (charset, data->last_charset) ||
data->findex != data->last_findex)
{
data->last_char_width = fi->width;
else
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);
+
+ if (!no_contribute_to_line_height)
+ {
+ 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_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;
+ crb->object.cglyph = data->font_is_bogus
+ ? ASCII_TO_CHARC ('~')
+ : char_glyph;
crb->endpos = 0;
if (data->cursor_type == CURSOR_ON)
return NULL;
}
-/* Given a string C_STRING of length C_LENGTH, call add_emchar_rune
- for each character in the string. Propagate any left-over data
- unless NO_PROP is non-zero. */
-
+static prop_block_dynarr *
+add_emchar_rune (pos_data *data)
+{
+ return add_emchar_rune_1 (data, 0);
+}
+
+/* Given a string C_STRING of length C_LENGTH, call add_emchar_rune for
+ each character in the string. Propagate any left-over data unless
+ NO_PROP is non-zero. If NO_CONTRIBUTE_TO_LINE_HEIGHT is non-zero, don't
+ allow this character to increase the total height of the line. (This is
+ used when the character is part of a text glyph. In that case, the
+ glyph code itself adjusts the line height as necessary, depending on
+ whether glyph-contrib-p is true.) */
+
static prop_block_dynarr *
add_bufbyte_string_runes (pos_data *data, Bufbyte *c_string,
- Bytecount c_length, int no_prop)
+ Bytecount c_length, int no_prop,
+ int no_contribute_to_line_height)
{
Bufbyte *pos, *end = c_string + c_length;
prop_block_dynarr *prop;
for (pos = c_string; pos < end;)
{
+ Bufbyte *old_pos = pos;
+
data->ch = charptr_emchar (pos);
- prop = add_emchar_rune (data);
+ prop = add_emchar_rune_1 (data, no_contribute_to_line_height);
if (prop)
{
}
INC_CHARPTR (pos);
assert (pos <= end);
+ /* #### Duplicate code from add_string_to_fstring_db_runes
+ should we do more?*/
+ data->bytepos += pos - old_pos;
}
return NULL;
static prop_block_dynarr *
add_octal_runes (pos_data *data)
{
- prop_block_dynarr *prop, *add_failed;
+ prop_block_dynarr *add_failed, *prop = 0;
Emchar orig_char = data->ch;
unsigned int orig_cursor_type = data->cursor_type;
/* Initialize */
- prop = NULL;
add_failed = NULL;
if (data->start_col)
ADD_NEXT_OCTAL_RUNE_CHAR;
data->cursor_type = orig_cursor_type;
- return prop;
+ return NULL;
}
#undef ADD_NEXT_OCTAL_RUNE_CHAR
prop = add_bufbyte_string_runes (data,
XSTRING_DATA (entry),
XSTRING_LENGTH (entry),
- 0);
+ 0, 0);
}
else if (GLYPHP (entry))
{
case '%':
dst += set_charptr_emchar (dst, '%');
break;
+ /* #### unimplemented */
}
}
}
- prop = add_bufbyte_string_runes (data, result, dst - result, 0);
+ prop = add_bufbyte_string_runes (data, result, dst - result, 0, 0);
}
}
}
break;
default:
- abort ();
+ ABORT ();
}
}
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;
+ prop_block_dynarr *retval = 0;
if (cachel)
width = cachel->width;
if (data->start_col || data->start_col_xoffset)
{
- prop_block_dynarr *retval;
int glyph_char_width = width / space_width (w);
/* If we still have not fully scrolled horizontally after
if (data->pixpos + width > data->max_pixpos)
{
/* If this is the first object we are attempting to add to
- the line then we ignore the horizontal_clip threshold.
- Otherwise we will loop until the bottom of the window
- continually failing to add this glyph because it is wider
- than the window. We could alternatively just completely
- ignore the glyph and proceed from there but I think that
- this is a better solution. */
+ the line then we ignore the horizontal_clip threshold.
+ Otherwise we will loop until the bottom of the window
+ continually failing to add this glyph because it is wider
+ than the window. We could alternatively just completely
+ ignore the glyph and proceed from there but I think that
+ this is a better solution.
+
+ This does, however, create a different problem in that we
+ can end up adding the object to every single line, never
+ getting any further - for instance an extent with a long
+ start-glyph that covers multitple following
+ characters. */
if (Dynarr_length (data->db->runes)
&& data->max_pixpos - data->pixpos < horizontal_clip)
return ADD_FAILED;
- else
+ else {
+ struct prop_block pb;
+
+ /* We need to account for the width of the end-of-line
+ glyph if there is nothing more in the line to display,
+ since we will not display it in this instance. It seems
+ kind of gross doing it here, but otherwise we have to
+ search the runes in create_text_block(). */
+ if (data->ch == '\n')
+ data->max_pixpos += data->end_glyph_width;
width = data->max_pixpos - data->pixpos;
+ /* Add the glyph we are displaying, but clipping, to the
+ propagation data so that we don't try and do it
+ again. */
+ retval = Dynarr_new (prop_block);
+ pb.type = PROP_GLYPH;
+ pb.data.p_glyph.glyph = gb->glyph;
+ pb.data.p_glyph.width = width;
+ Dynarr_add (retval, pb);
+ }
}
if (cachel)
baseline = glyph_baseline (gb->glyph, data->window);
+ rb.object.dglyph.descent = 0; /* Gets reset lower down, if it is known. */
+
if (glyph_contrib_p (gb->glyph, data->window))
{
/* A pixmap that has not had a baseline explicitly set. Its
if (NILP (baseline))
{
int height = ascent + descent;
+ data->need_baseline_computation = 1;
data->max_pixmap_height = max (data->max_pixmap_height, height);
}
data->new_ascent = max (data->new_ascent, pix_ascent);
data->new_descent = max (data->new_descent, pix_descent);
+ data->max_pixmap_height = max (data->max_pixmap_height, height);
+
+ rb.object.dglyph.descent = pix_descent;
}
/* Otherwise something is screwed up. */
else
- abort ();
+ ABORT ();
}
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, 1);
+ data->findex = orig_findex;
+ data->bi_bufpos = orig_bufpos;
+ data->bi_start_col_enabled = orig_start_col_enabled;
+ return retval;
+ }
+
+ 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;
+ rb.object.dglyph.ascent = ascent;
+ rb.object.dglyph.yoffset = 0; /* Until we know better, assume that it has
+ a normal (textual) baseline. */
if (allow_cursor)
{
Dynarr_add (data->db->runes, rb);
data->pixpos += width;
- return NULL;
+ return retval;
}
else
{
return NULL;
}
else
- abort (); /* there are no unknown types */
+ ABORT (); /* there are no unknown types */
}
- return NULL; /* shut up compiler */
+ return NULL;
}
/* Add all glyphs at position POS_TYPE that are contained in the given
is_surrogate_for_selected_frame (f));
int truncate_win = window_truncation_on (w);
- int end_glyph_width;
/* If the buffer's value of selective_display is an integer then
only lines that start with less than selective_display columns of
dl->used_prop_data = 0;
dl->num_chars = 0;
+ dl->line_continuation = 0;
xzero (data);
data.ef = extent_fragment_new (w->buffer, f);
glyph. Save the width of the end glyph for later use. */
data.max_pixpos = dl->bounds.right_in;
if (truncate_win)
- end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
+ data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
else
- end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
- data.max_pixpos -= end_glyph_width;
+ data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
+ data.max_pixpos -= data.end_glyph_width;
if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f))
{
/* Check for face changes. */
if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
{
+ Lisp_Object last_glyph = Qnil;
+
+ /* Deal with glyphs that we have already displayed. The
+ theory is that if we end up with a PROP_GLYPH in the
+ propagation data then we are clipping the glyph and there
+ can be no propagation data before that point. The theory
+ works because we always recalculate the extent-fragments
+ for propagated data, we never actually propagate the
+ fragments that still need to be displayed. */
+ if (*prop && Dynarr_atp (*prop, 0)->type == PROP_GLYPH)
+ {
+ last_glyph = Dynarr_atp (*prop, 0)->data.p_glyph.glyph;
+ Dynarr_free (*prop);
+ *prop = 0;
+ }
/* Now compute the face and begin/end-glyph information. */
data.findex =
/* Remember that the extent-fragment routines deal in Bytind's. */
- extent_fragment_update (w, data.ef, data.bi_bufpos);
+ extent_fragment_update (w, data.ef, data.bi_bufpos, last_glyph);
get_display_tables (w, data.findex, &face_dt, &window_dt);
}
/* If there is propagation data, then it represents the current
- buffer position being displayed. Add them and advance the
- position counter. This might also add the minibuffer
- prompt. */
+ buffer position being displayed. Add them and advance the
+ position counter. This might also add the minibuffer
+ prompt. */
else if (*prop)
{
dl->used_prop_data = 1;
here rather than doing them at the end of handling the
previous run so that glyphs at the beginning and end of
a line are handled correctly. */
- else if (Dynarr_length (data.ef->end_glyphs) > 0)
+ else if (Dynarr_length (data.ef->end_glyphs) > 0
+ || Dynarr_length (data.ef->begin_glyphs) > 0)
{
- *prop = add_glyph_runes (&data, END_GLYPHS);
- if (*prop)
- goto done;
- }
+ glyph_block_dynarr* tmpglyphs = 0;
+ /* #### I think this is safe, but could be wrong. */
+ data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
- /* If there are begin glyphs, add them to the line. */
- else if (Dynarr_length (data.ef->begin_glyphs) > 0)
- {
- *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
- if (*prop)
- goto done;
+ if (Dynarr_length (data.ef->end_glyphs) > 0)
+ {
+ *prop = add_glyph_runes (&data, END_GLYPHS);
+ tmpglyphs = data.ef->end_glyphs;
+ }
+
+ /* If there are begin glyphs, add them to the line. */
+ if (!*prop && Dynarr_length (data.ef->begin_glyphs) > 0)
+ {
+ *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
+ tmpglyphs = data.ef->begin_glyphs;
+ }
+
+ if (*prop)
+ {
+ /* If we just clipped a glyph and we are at the end of a
+ line and there are more glyphs to display then do
+ appropriate processing to not get a continuation
+ glyph. */
+ if (*prop != ADD_FAILED
+ && Dynarr_atp (*prop, 0)->type == PROP_GLYPH
+ && data.ch == '\n')
+ {
+ /* If there are no more glyphs then do the normal
+ processing.
+
+ #### This doesn't actually work if the same glyph is
+ present more than once in the block. To solve
+ this we would have to carry the index around
+ which might be problematic since the fragment is
+ recalculated for each line. */
+ if (EQ (Dynarr_end (tmpglyphs)->glyph,
+ Dynarr_atp (*prop, 0)->data.p_glyph.glyph))
+ {
+ Dynarr_free (*prop);
+ *prop = 0;
+ }
+ else {
+ data.blank_width = DEVMETH (d, eol_cursor_width, ());
+ add_emchar_rune (&data); /* discard prop data. */
+ goto done;
+ }
+ }
+ else
+ goto done;
+ }
}
/* If at end-of-buffer, we've already processed begin and
/* We aren't going to be adding an end glyph so give its
space back in order to make sure that the cursor can
fit. */
- data.max_pixpos += end_glyph_width;
+ data.max_pixpos += data.end_glyph_width;
if (selective > 0
&& (bi_spaces_at_point
/* We won't be adding a truncation or continuation glyph
so give up the room allocated for them. */
- data.max_pixpos += end_glyph_width;
+ data.max_pixpos += data.end_glyph_width;
if (!NILP (b->selective_display_ellipses))
{
/* This had better be a newline but doing it this way
we'll see obvious incorrect results if it isn't. No
- need to abort here. */
+ need to ABORT here. */
data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
goto done;
for the next newline. We also add the end-of-line glyph which
we know will fit because we adjusted the right border before
we starting laying out the line. */
- data.max_pixpos += end_glyph_width;
+ data.max_pixpos += data.end_glyph_width;
data.findex = DEFAULT_INDEX;
gb.extent = Qnil;
/* 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 && CHARC_ASCII_EQ (rb->object.cglyph, ' '))
|| 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 && CHARC_IS_SPACE (rb->object.cglyph))
&& !rb->type == RUNE_BLANK)
{
dl->bounds.right_white = rb->xpos + rb->width;
else
db->end_pos = dl->bounds.right_white;
- /* update line height parameters */
- if (!data.new_ascent && !data.new_descent)
- {
- /* We've got a blank line so initialize these values from the default
- face. */
- default_face_font_info (data.window, &data.new_ascent,
- &data.new_descent, 0, 0, 0);
- }
-
- 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);
- }
+ calculate_baseline (&data);
dl->ascent = data.new_ascent;
dl->descent = data.new_descent;
dl->descent = descent;
}
+ calculate_yoffset (dl, db);
+
dl->cursor_elt = data.cursor_x;
/* #### lossage lossage lossage! Fix this shit! */
if (data.bi_bufpos > BI_BUF_ZV (b))
(&data,
XSTRING_DATA (Voverlay_arrow_string),
XSTRING_LENGTH (Voverlay_arrow_string),
- 1);
+ 1, 0);
}
else if (GLYPHP (Voverlay_arrow_string))
{
add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0);
}
- 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);
- }
+ calculate_baseline (&data);
dl->ascent = data.new_ascent;
dl->descent = data.new_descent;
data.db->start_pos = dl->bounds.left_in;
data.db->end_pos = data.pixpos;
+ calculate_yoffset (dl, data.db);
+
return data.pixpos - dl->bounds.left_in;
}
? 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))
struct glyph_block *gb = Dynarr_atp (gbd, elt);
if (NILP (gb->extent))
- abort (); /* these should have been handled in add_glyph_rune */
+ ABORT (); /* these should have been handled in add_glyph_rune */
if (gb->active &&
((side == LEFT_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, window);
- descent = glyph_descent (gb->glyph, 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;
+ calculate_baseline (&data);
+
+ dl->ascent = data.new_ascent;
+ dl->descent = data.new_descent;
+
+ calculate_yoffset (dl, data.db);
+
+ return data.pixpos;
}
/* Add a blank to a margin display block. */
struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
if (NILP (gb->extent))
- abort (); /* these should have been handled in add_glyph_rune */
+ ABORT (); /* these should have been handled in add_glyph_rune */
if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
{
struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
if (NILP (gb->extent))
- abort (); /* these should have been handled in add_glyph_rune */
+ ABORT (); /* these should have been handled in add_glyph_rune */
if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
GL_INSIDE_MARGIN)
struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
if (NILP (gb->extent))
- abort (); /* these should have been handled in add_glyph_rune */
+ ABORT (); /* these should have been handled in add_glyph_rune */
if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
GL_INSIDE_MARGIN)
struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
if (NILP (gb->extent))
- abort (); /* these should have been handled in add_glyph_rune */
+ ABORT (); /* these should have been handled in add_glyph_rune */
if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
GL_OUTSIDE_MARGIN)
struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
if (NILP (gb->extent))
- abort (); /* these should have been handled in add_glyph_rune */
+ ABORT (); /* these should have been handled in add_glyph_rune */
if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
{
struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
if (NILP (gb->extent))
- abort (); /* these should have been handled in add_glyph_rune */
+ ABORT (); /* these should have been handled in add_glyph_rune */
if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
{
struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
if (NILP (gb->extent))
- abort (); /* these should have been handled in add_glyph_rune */
+ ABORT (); /* these should have been handled in add_glyph_rune */
if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
{
struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
if (NILP (gb->extent))
- abort (); /* these should have been handled in add_glyph_rune */
+ ABORT (); /* these should have been handled in add_glyph_rune */
if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN)
{
/* 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 */
+ horizontal scrolling amount */
if (! NILP (result_str))
offset = w->modeline_hscroll;
generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0,
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));
+ (strdata + len,
+ CHARC_TO_CHAR (Dynarr_atp (db->runes,
+ elt)->object.cglyph)));
}
}
Dynarr_at (formatted_string_extent_end_dynarr, elt),
result_str);
}
+
+ in_modeline_generation = 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;
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 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);
{
Charcount tmp_max = (max_pos == -1 ? pos + size - *offset :
min (pos + size - *offset, max_pos));
- CONST Bufbyte *tmp_last = charptr_n_addr (last, *offset);
+ const Bufbyte *tmp_last = charptr_n_addr (last, *offset);
pos = add_string_to_fstring_db_runes (data, tmp_last,
pos, pos, tmp_max);
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)
{
*offset -= size;
else
{
- CONST Bufbyte *tmp_str = charptr_n_addr (str, *offset);
+ 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
*offset -= size;
else
{
- CONST Bufbyte *tmp_str = charptr_n_addr (str, *offset);
+ 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
* - 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 a face, process the cdr recursively
- * without altering the depth.
+ * - If first element is an extent, process the cdr recursively
+ * and handle the extent's face.
*/
Lisp_Object car, tem;
*offset -= size;
else
{
- CONST Bufbyte *tmp_str =
- charptr_n_addr ((CONST Bufbyte *) str, *offset);
+ 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 */
if (min_pos > pos)
{
- add_string_to_fstring_db_runes (data, (CONST Bufbyte *) "", pos,
+ add_string_to_fstring_db_runes (data, (const Bufbyte *) "", pos,
min_pos, -1);
}
\f
/***************************************************************************/
-/* */
-/* displayable string routines */
-/* */
+/* */
+/* displayable string routines */
+/* */
/***************************************************************************/
/* Given a position for a string in a window, ensure that the given
pos_data data;
int truncate_win = b ? window_truncation_on (w) : 0;
- int end_glyph_width = 0;
- /* we're going to ditch selective display for static text, its an
- FSF thing and invisble extents are the way to go
- here. Implementing it also relies on a number of buffer-specific
+ /* We're going to ditch selective display for static text, it's an
+ FSF thing and invisible extents are the way to go here.
+ Implementing it also relies on a number of buffer-specific
functions that we don't have the luxury of being able to use
here. */
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 */
/* Set the right boundary adjusting it to take into account any end
glyph. Save the width of the end glyph for later use. */
data.max_pixpos = dl->bounds.right_in;
-#if 0
- if (truncate_win)
- end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
- else
- end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
-#endif
- data.max_pixpos -= end_glyph_width;
+ data.max_pixpos -= data.end_glyph_width;
data.cursor_type = NO_CURSOR;
data.cursor_x = -1;
/* Check for face changes. */
if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
{
+ Lisp_Object last_glyph = Qnil;
+ /* Deal with clipped glyphs that we have already displayed. */
+ if (*prop && Dynarr_atp (*prop, 0)->type == PROP_GLYPH)
+ {
+ last_glyph = Dynarr_atp (*prop, 0)->data.p_glyph.glyph;
+ Dynarr_free (*prop);
+ *prop = 0;
+ }
/* Now compute the face and begin/end-glyph information. */
data.findex =
/* Remember that the extent-fragment routines deal in Bytind's. */
- extent_fragment_update (w, data.ef, data.bi_bufpos);
+ extent_fragment_update (w, data.ef, data.bi_bufpos, last_glyph);
/* This is somewhat cheesy but the alternative is to
propagate default_face into extent_fragment_update. */
if (data.findex == DEFAULT_INDEX)
goto done;
}
- /* #### What if we we're dealing with a display table? */
+ /* #### What if we're dealing with a display table? */
if (data.start_col)
data.start_col--;
else if (data.bi_bufpos == bi_string_zv)
goto done;
else if (data.bi_bufpos < 0)
- /* #### urk urk urk! Aborts are not very fun! Fix this please! */
+ /* #### urk urk urk! ABORTs are not very fun! Fix this please! */
data.bi_bufpos = 0;
else
INC_CHARBYTIND (string_data (s), data.bi_bufpos);
a line are handled correctly. */
else if (Dynarr_length (data.ef->end_glyphs) > 0)
{
+ data.ch = string_char (s, data.bi_bufpos);
*prop = add_glyph_runes (&data, END_GLYPHS);
- if (*prop)
+
+ if (*prop) {
goto done;
+ }
}
/* If there are begin glyphs, add them to the line. */
else if (Dynarr_length (data.ef->begin_glyphs) > 0)
{
+ data.ch = string_char (s, data.bi_bufpos);
*prop = add_glyph_runes (&data, BEGIN_GLYPHS);
- if (*prop)
+
+ if (*prop) {
goto done;
+ }
}
/* If at end-of-buffer, we've already processed begin and
/* We aren't going to be adding an end glyph so give its
space back in order to make sure that the cursor can
fit. */
- data.max_pixpos += end_glyph_width;
+ data.max_pixpos += data.end_glyph_width;
goto done;
}
*prop = add_blank_rune (&data, w, char_tab_width);
/* add_blank_rune is only supposed to be called with
- sizes guaranteed to fit in the available space. */
+ sizes guaranteed to fit in the available space. */
assert (!(*prop));
if (prop_width)
}
}
-done:
+ done:
/* Determine the starting point of the next line if we did not hit the
end of the buffer. */
for the next newline. We also add the end-of-line glyph which
we know will fit because we adjusted the right border before
we starting laying out the line. */
- data.max_pixpos += end_glyph_width;
+ data.max_pixpos += data.end_glyph_width;
data.findex = default_face;
gb.extent = Qnil;
/* 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 (end_glyph_width)
+ if (data.end_glyph_width)
add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel);
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 && CHARC_ASCII_EQ (rb->object.cglyph, ' '))
|| 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 && CHARC_IS_SPACE (rb->object.cglyph))
&& !rb->type == RUNE_BLANK)
{
dl->bounds.right_white = rb->xpos + rb->width;
else
db->end_pos = dl->bounds.right_white;
- /* update line height parameters */
- if (!data.new_ascent && !data.new_descent)
- {
- /* We've got a blank line so initialize these values from the default
- face. */
- default_face_font_info (data.window, &data.new_ascent,
- &data.new_descent, 0, 0, 0);
- }
-
- 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);
- }
+ calculate_baseline (&data);
dl->ascent = data.new_ascent;
dl->descent = data.new_descent;
dl->descent = descent;
}
+ calculate_yoffset (dl, db);
+
dl->cursor_elt = data.cursor_x;
/* #### lossage lossage lossage! Fix this shit! */
if (data.bi_bufpos > bi_string_zv)
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;
/* The lines had better exist by this point. */
if (!(dla = window_display_lines (w, type)))
- abort ();
+ ABORT ();
Dynarr_reset (dla);
w->max_line_len = 0;
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;
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)
dla_start = 0; \
} \
else \
- abort (); /* structs differ */ \
+ ABORT (); /* structs differ */ \
\
dla_end = Dynarr_length (cdla) - 1; \
} \
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. */
&& !(MINI_WINDOW_P (w) && f->buffers_changed)
&& !f->frame_changed
&& !truncation_changed
- /* check whether start is really at the begining of a line GE */
+ /* check whether start is really at the beginning of a line GE */
&& (!w->start_at_line_beg || beginning_of_line_p (b, startp))
)
{
&& !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
/* 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);
- if (preemption_check)
+ if (preemption_check
+ && !DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY))
{
/* The preemption check itself takes a lot of time,
so normally don't do it here. We do it if called
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)
/* The menubar, toolbar, and icon updates must be done before
hold_frame_size_changes is called and we are officially
'in_display'. They may eval lisp code which may call Fsignal.
- If in_display is set Fsignal will abort. */
+ If in_display is set Fsignal will ABORT. */
#ifdef HAVE_MENUBARS
/* Update the menubar. It is done first since it could change
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);
+ /* Update the toolbars geometry. We don't update the toolbars
+ themselves at this point since the space they are trying to
+ occupy may currently by occupied by gutter elements. Instead we
+ update the geometry, then update the gutter geometry, then update
+ the gutters - which will cause mapped windows to be repositioned
+ - and finally update the toolbars. */
+ update_frame_toolbars_geometry (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
- cause subwindows to get instantiated. This is because
+ /* Invalidate the subwindow caches. 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->faces_changed
- || f->frame_changed)
+ if (f->frame_changed)
+ reset_frame_subwindow_instance_cache (f);
+
+ 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 ();
We need to remove them.
If Fsignal() is called during this critical section, we
- will abort().
+ will ABORT().
If garbage collection is called during this critical section,
- we simply return. #### We should abort instead.
+ we simply return. #### We should ABORT instead.
#### 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);
+#ifdef HAVE_TOOLBARS
+ /* Finally update the toolbars. It seems its possible to get in a
+ cycle between updating the gutter and the toolbars. Basically we
+ want to end up with both being up-to-date and this doesn't seem
+ possible in a single pass. */
+ update_frame_toolbars (f);
+#endif /* HAVE_TOOLBARS */
+
CLASS_RESET_CHANGED_FLAGS (f);
f->window_face_cache_reset = 0;
f->echo_area_garbaged = 0;
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))
+ if (automatic && DEVICE_IMPL_FLAG (d, XDEVIMPF_NO_AUTO_REDISPLAY))
return 0;
if (DEVICE_STREAM_P (d)) /* nothing to do */
return 0;
/* It is possible that redisplay has been called before the
- device is fully initialized. If so then continue with the
- next device. */
+ device is fully initialized, or that the console implementation
+ allows frameless devices. If so then continue with the next
+ device. */
if (NILP (DEVICE_SELECTED_FRAME (d)))
return 0;
- REDISPLAY_PREEMPTION_CHECK;
- if (preempted)
- return 1;
+ if (!DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY))
+ {
+ int preempted;
+ REDISPLAY_PREEMPTION_CHECK;
+ if (preempted)
+ return 1;
+ }
/* Always do the selected frame first. */
frame = DEVICE_SELECTED_FRAME (d);
{
if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f))
{
- preempted = redisplay_frame (f, 0);
+ int preempted = redisplay_frame (f, 0);
+ if (preempted)
+ return 1;
}
- if (preempted)
- return 1;
-
/* If the frame redisplay did not get preempted, then this flag
should have gotten set to 0. It might be possible for that
not to happen if a size change event were to occur at an odd
{
if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f))
{
- preempted = redisplay_frame (f, 0);
+ int preempted = redisplay_frame (f, 0);
+ if (preempted)
+ return 1;
}
- if (preempted)
- return 1;
-
if (f->size_change_pending)
size_change_failed = 1;
}
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);
FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
{
struct frame *f = XFRAME (XCAR (frmcons));
- update_frame_window_mirror (f);
mark_window_mirror (f->root_mirror);
+ mark_gutters (f);
}
}
\f
{
struct buffer *b = XBUFFER (w->buffer);
line_start_cache_dynarr *cache = w->line_start_cache;
- unsigned int top, bottom, pos;
+ unsigned int top, bottom;
+ EMACS_INT pos;
validate_line_start_cache (w);
w->line_cache_validation_override++;
int win_char_height = window_char_height (w, 1);
/* Occasionally we get here with a 0 height
- window. find_next_newline_no_quit will abort if we pass it a
+ window. find_next_newline_no_quit will ABORT if we pass it a
count of 0 so handle that case. */
if (!win_char_height)
win_char_height = 1;
while (1)
{
- unsigned int new_pos;
+ EMACS_INT new_pos;
Bufpos start, end;
pos = (bottom + top + 1) >> 1;
else if (point < start)
top = pos - 1;
else
- abort ();
+ ABORT ();
new_pos = (bottom + top + 1) >> 1;
if (pos == new_pos)
displayed. The end of the last line is also know as the window end
position.
+ WARNING: It is possible that redisplay 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. */
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'))
+ && CHARC_ASCII_EQ (rb->object.cglyph, '\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 flags 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);
}
}
redisplay_device (d, 0);
+ /* See the comment in Fredisplay_frame. */
+ RESET_CHANGED_SET_FLAGS;
+
return unbind_to (count, Qnil);
}
redisplay_device (d, 0);
+ /* See the comment in Fredisplay_frame. */
+ RESET_CHANGED_SET_FLAGS;
+
return unbind_to (count, Qnil);
}
}
#endif /* HAVE_X_WINDOWS */
+#ifdef HAVE_GTK
+ if (!strcmp (display_use, "gtk"))
+ {
+ Vwindow_system = Qgtk;
+ Vinitial_window_system = Qgtk;
+ return;
+ }
+#endif
+
#ifdef HAVE_MS_WINDOWS
if (!strcmp (display_use, "mswindows"))
{
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.
maybe a caret cursor, etc. */
DEFVAR_LISP ("bar-cursor", &Vbar_cursor /*
-Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2.
+*Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2.
*/ );
Vbar_cursor = Qnil;
#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
offsetof (struct window, left_margin_width),
some_window_value_changed,
offsetof (struct frame, left_margin_width),
- margin_width_changed_in_frame);
+ margin_width_changed_in_frame, 0);
DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /*
*Width of right margin.
offsetof (struct window, right_margin_width),
some_window_value_changed,
offsetof (struct frame, right_margin_width),
- margin_width_changed_in_frame);
+ margin_width_changed_in_frame, 0);
DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /*
*Minimum ascent height of lines.
set_specifier_caching (Vminimum_line_ascent,
offsetof (struct window, minimum_line_ascent),
some_window_value_changed,
- 0, 0);
+ 0, 0, 0);
DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /*
*Minimum descent height of lines.
set_specifier_caching (Vminimum_line_descent,
offsetof (struct window, minimum_line_descent),
some_window_value_changed,
- 0, 0);
+ 0, 0, 0);
DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /*
*Non-nil means use the left outside margin as extra whitespace when
set_specifier_caching (Vuse_left_overflow,
offsetof (struct window, use_left_overflow),
some_window_value_changed,
- 0, 0);
+ 0, 0, 0);
DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /*
*Non-nil means use the right outside margin as extra whitespace when
set_specifier_caching (Vuse_right_overflow,
offsetof (struct window, use_right_overflow),
some_window_value_changed,
- 0, 0);
+ 0, 0, 0);
DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /*
*Non-nil means the text cursor is visible (this is usually the case).
set_specifier_caching (Vtext_cursor_visible_p,
offsetof (struct window, text_cursor_visible_p),
text_cursor_visible_p_changed,
- 0, 0);
+ 0, 0, 0);
}