#include "faces.h"
#include "frame.h"
#include "glyphs.h"
+#include "gutter.h"
#include "insdel.h"
#include "menubar.h"
#include "objects.h"
/* This information is normally filled in by the create_*_block
routines and is used by the add_*_rune routines. */
Lisp_Object window;
+ /* if we are working with strings rather than buffers we need a
+ handle to the string */
+ Lisp_Object string;
struct device *d;
struct display_block *db;
struct display_line *dl;
struct glyph_cachel *cachel);
static Bytind create_text_block (struct window *w, struct display_line *dl,
Bytind bi_start_pos, int start_col,
- prop_block_dynarr **prop, int type);
+ prop_block_dynarr **prop,
+ int type);
static int create_overlay_glyph_block (struct window *w,
struct display_line *dl);
static void create_left_glyph_block (struct window *w,
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);
+extern Bytind bi_find_next_emchar_in_string (struct Lisp_String* str, Emchar target,
+ Bytind st, EMACS_INT count);
+extern int string_column_at_point (struct Lisp_String* s, Bufpos init_pos, int tab_width);
/* This used to be 10 but 30 seems to give much better performance. */
#define INIT_MAX_PREEMPTS 30
int glyphs_changed;
int glyphs_changed_set;
+/* non-zero if any displayed subwindow is in need of updating
+ somewhere. */
+int subwindows_changed;
+int subwindows_changed_set;
+
/* This variable is 1 if the icon has to be updated.
It is set to 1 when `frame-icon-glyph' changes. */
int icon_changed;
int toolbar_changed;
int toolbar_changed_set;
+/* non-nil if any gutter has changed */
+int gutter_changed;
+int gutter_changed_set;
+
/* non-nil if any window has changed since the last time redisplay completed */
int windows_changed;
redisplay_text_width_emchar_string (struct window *w, int findex,
Emchar *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);
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;
static Bufpos
generate_display_line (struct window *w, struct display_line *dl, int bounds,
Bufpos start_pos, int start_col,
- prop_block_dynarr **prop, int type)
+ prop_block_dynarr **prop,
+ int type)
{
Bufpos ret_bufpos;
int overlay_width;
crb->xpos = data->pixpos;
crb->width = width;
if (data->bi_bufpos)
- crb->bufpos =
- bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
- data->bi_bufpos);
+ {
+ if (NILP (data->string))
+ crb->bufpos =
+ bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
+ data->bi_bufpos);
+ else
+ crb->bufpos =
+ bytecount_to_charcount (XSTRING_DATA (data->string), data->bi_bufpos);
+ }
else if (data->is_modeline)
crb->bufpos = data->modeline_charpos;
else
}
}
-/* Given a display table entry, call the appropriate functions to
- display each element of the entry. */
-
static prop_block_dynarr *
-add_disp_table_entry_runes (pos_data *data, Lisp_Object entry)
+add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry)
{
prop_block_dynarr *prop = NULL;
- if (VECTORP (entry))
- {
- struct Lisp_Vector *de = XVECTOR (entry);
- long len = vector_length (de);
- int elt;
-
- for (elt = 0; elt < len; elt++)
- {
- if (NILP (de->contents[elt]))
- continue;
- else if (STRINGP (de->contents[elt]))
- {
- prop =
- add_bufbyte_string_runes
- (data,
- XSTRING_DATA (de->contents[elt]),
- XSTRING_LENGTH (de->contents[elt]),
- 0);
- }
- else if (GLYPHP (de->contents[elt]))
- {
- if (data->start_col)
- data->start_col--;
-
- if (!data->start_col && data->bi_start_col_enabled)
- {
- prop = add_hscroll_rune (data);
- }
- else
- {
- struct glyph_block gb;
-
- gb.glyph = de->contents[elt];
- gb.extent = Qnil;
- prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
- }
- }
- else if (CHAR_OR_CHAR_INTP (de->contents[elt]))
- {
- data->ch = XCHAR_OR_CHAR_INT (de->contents[elt]);
- prop = add_emchar_rune (data);
- }
- /* Else blow it off because someone added a bad entry and we
- don't have any safe way of signaling an error. */
-
- /* #### Still need to add any remaining elements to the
- propagation information. */
- if (prop)
- return prop;
- }
- }
- else if (STRINGP (entry))
+ if (STRINGP (entry))
{
prop = add_bufbyte_string_runes (data,
XSTRING_DATA (entry),
data->ch = XCHAR_OR_CHAR_INT (entry);
prop = add_emchar_rune (data);
}
+ else if (CONSP (entry))
+ {
+ if (EQ (XCAR (entry), Qformat)
+ && CONSP (XCDR (entry))
+ && STRINGP (XCAR (XCDR (entry))))
+ {
+ Lisp_Object format = XCAR (XCDR (entry));
+ Bytind len = XSTRING_LENGTH (format);
+ Bufbyte *src = XSTRING_DATA (format), *end = src + len;
+ Bufbyte *result = alloca_array (Bufbyte, len);
+ Bufbyte *dst = result;
+
+ while (src < end)
+ {
+ Emchar c = charptr_emchar (src);
+ INC_CHARPTR (src);
+ if (c != '%' || src == end)
+ dst += set_charptr_emchar (dst, c);
+ else
+ {
+ c = charptr_emchar (src);
+ INC_CHARPTR (src);
+ switch (c)
+ {
+ /*case 'x':
+ dst += long_to_string_base ((char *)dst, data->ch, 16);
+ break;*/
+ case '%':
+ dst += set_charptr_emchar (dst, '%');
+ break;
+ }
+ }
+ }
+ prop = add_bufbyte_string_runes (data, result, dst - result, 0);
+ }
+ }
/* Else blow it off because someone added a bad entry and we don't
- have any safe way of signaling an error. Hey, this comment
- sounds familiar. */
+ have any safe way of signaling an error. */
+ return prop;
+}
+
+/* Given a display table entry, call the appropriate functions to
+ display each element of the entry. */
+
+static prop_block_dynarr *
+add_disp_table_entry_runes (pos_data *data, Lisp_Object entry)
+{
+ prop_block_dynarr *prop = NULL;
+ if (VECTORP (entry))
+ {
+ struct Lisp_Vector *de = XVECTOR (entry);
+ EMACS_INT len = vector_length (de);
+ int elt;
+
+ for (elt = 0; elt < len; elt++)
+ {
+ if (NILP (vector_data (de)[elt]))
+ continue;
+ else
+ prop = add_disp_table_entry_runes_1 (data, vector_data (de)[elt]);
+ /* Else blow it off because someone added a bad entry and we
+ don't have any safe way of signaling an error. Hey, this
+ comment sounds familiar. */
+
+ /* #### Still need to add any remaining elements to the
+ propagation information. */
+ if (prop)
+ return prop;
+ }
+ }
+ else
+ prop = add_disp_table_entry_runes_1 (data, entry);
return prop;
}
static Bytind
create_text_block (struct window *w, struct display_line *dl,
Bytind bi_start_pos, int start_col,
- prop_block_dynarr **prop, int type)
+ prop_block_dynarr **prop,
+ int type)
{
struct frame *f = XFRAME (w->frame);
struct buffer *b = XBUFFER (w->buffer);
struct device *d = XDEVICE (f->device);
pos_data data;
- struct Lisp_Vector *dt = 0;
/* Don't display anything in the minibuffer if this window is not on
a selected frame. We consider all other windows to be active
into a more general conversion mechanism. Ideally you
could specify a Lisp function that converts characters,
but this violates the Second Golden Rule and besides would
- make things way way way way slow. An idea I like is to
- be able to specify multiple display tables instead of just
- one. Each display table can specify conversions for some
- characters and leave others unchanged. The way the
- character gets displayed is determined by the first display
- table with a binding for that character. This way, you
- could call a function `enable-hex-display' that adds a
- pre-defined hex display-table (or maybe computes one if
- you give weird parameters to the function) and adds it
- to the list of display tables for the current buffer.
-
- Unfortunately there are still problems dealing with Mule
- characters. For example, maybe I want to specify that
- all extended characters (i.e. >= 256) are displayed in hex.
- It's not reasonable to create a mapping for all possible
- such characters, because there are about 2^19 of them.
- One way of dealing with this is to extend the concept
- of what a display table is. Currently it's only allowed
- to be a 256-entry vector. Instead, it should be something
- like:
-
- a) A 256-entry vector, for backward compatibility
- b) Some sort of hash table, mapping characters to values
- c) A list that specifies a range of values and the
- mapping to provide for those values.
-
- Also, extend the concept of "mapping" to include a
- printf-like spec. Then, you could make all extended
- characters show up as hex with a display table like
-
- ((256 . 524288) . "%x")
+ make things way way way way slow.
+
+ So instead, we extend the display-table concept, which was
+ historically limited to 256-byte vectors, to one of the
+ following:
+
+ a) A 256-entry vector, for backward compatibility;
+ b) char-table, mapping characters to values;
+ c) range-table, mapping ranges of characters to values;
+ d) a list of the above.
+
+ The (d) option allows you to specify multiple display tables
+ instead of just one. Each display table can specify conversions
+ for some characters and leave others unchanged. The way the
+ character gets displayed is determined by the first display table
+ with a binding for that character. This way, you could call a
+ function `enable-hex-display' that adds a hex display-table to
+ the list of display tables for the current buffer.
+
+ #### ...not yet implemented... Also, we extend the concept of
+ "mapping" to include a printf-like spec. Thus you can make all
+ extended characters show up as hex with a display table like
+ this:
+
+ #s(range-table data ((256 524288) (format "%x")))
Since more than one display table is possible, you have
- great flexibility in mapping ranges of characters.
- */
+ great flexibility in mapping ranges of characters. */
Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow)
? XCHAR_OR_CHAR_INT (b->ctl_arrow)
: ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
? 255 : 160));
+ Lisp_Object face_dt, window_dt;
+
/* The text display block for this display line. */
struct display_block *db = get_display_block_from_line (dl, TEXT);
them to this structure for ease of passing. */
data.d = d;
XSETWINDOW (data.window, w);
+ data.string = Qnil;
data.db = db;
data.dl = dl;
/* Remember that the extent-fragment routines deal in Bytind's. */
extent_fragment_update (w, data.ef, data.bi_bufpos);
+ get_display_tables (w, data.findex, &face_dt, &window_dt);
+
if (data.bi_bufpos == data.ef->end)
no_more_frags = 1;
-
- dt = get_display_table (w, data.findex);
}
initial = 0;
else
{
+ Lisp_Object entry = Qnil;
/* Get the character at the current buffer position. */
data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
+ if (!NILP (face_dt) || !NILP (window_dt))
+ entry = display_table_entry (data.ch, face_dt, window_dt);
/* If there is a display table entry for it, hand it off to
add_disp_table_entry_runes and let it worry about it. */
- if (dt && !NILP (DISP_CHAR_ENTRY (dt, data.ch)))
+ if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
{
- *prop =
- add_disp_table_entry_runes (&data,
- DISP_CHAR_ENTRY (dt, data.ch));
+ *prop = add_disp_table_entry_runes (&data, entry);
if (*prop)
goto done;
data.last_charset = Qunbound;
data.last_findex = DEFAULT_INDEX;
data.result_str = Qnil;
+ data.string = Qnil;
Dynarr_reset (data.db->runes);
/* 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 void
data.last_findex = DEFAULT_INDEX;
data.result_str = result_str;
data.is_modeline = 1;
+ data.string = Qnil;
XSETWINDOW (data.window, w);
Dynarr_reset (formatted_string_extent_dynarr);
\f
/***************************************************************************/
-/* */
-/* window-regeneration routines */
-/* */
+/* */
+/* displayable string routines */
+/* */
/***************************************************************************/
-/* For a given window and starting position in the buffer it contains,
- ensure that the TYPE display lines accurately represent the
- presentation of the window. We pass the buffer instead of getting
- it from the window since redisplay_window may have temporarily
- changed it to the echo area buffer. */
+/* Given a position for a string in a window, ensure that the given
+ display line DL accurately represents the text on a line starting
+ at the given position.
-static void
-regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type)
+ Yes, this is duplicating the code of create_text_block, but it
+ looked just too hard to change create_text_block to handle strings
+ *and* buffers. We already make a distinction between the two
+ elsewhere in the code so I think unifying them would require a
+ complete MULE rewrite. Besides, the other distinction is that these
+ functions cover text that the user *cannot edit* so we can remove
+ everything to do with cursors, minibuffers etc. Eventually the
+ modeline routines should be modified to use this code as it copes
+ with many more types of display situation. */
+
+static Bufpos
+create_string_text_block (struct window *w, Lisp_Object disp_string,
+ struct display_line *dl,
+ Bufpos start_pos,
+ prop_block_dynarr **prop,
+ face_index default_face)
{
struct frame *f = XFRAME (w->frame);
+ /* Note that a lot of the buffer controlled stuff has been left in
+ because you might well want to make use of it (selective display
+ etc), its just the buffer text that we do not use. */
struct buffer *b = XBUFFER (w->buffer);
- int ypos = WINDOW_TEXT_TOP (w);
- int yend; /* set farther down */
-
- prop_block_dynarr *prop;
- layout_bounds bounds;
- display_line_dynarr *dla;
- int need_modeline;
-
- /* The lines had better exist by this point. */
- if (!(dla = window_display_lines (w, type)))
- abort ();
- Dynarr_reset (dla);
- w->max_line_len = 0;
-
- /* Normally these get updated in redisplay_window but it is possible
- for this function to get called from some other points where that
- update may not have occurred. This acts as a safety check. */
- if (!Dynarr_length (w->face_cachels))
- reset_face_cachels (w);
- if (!Dynarr_length (w->glyph_cachels))
- reset_glyph_cachels (w);
+ struct device *d = XDEVICE (f->device);
+ struct Lisp_String* s = XSTRING (disp_string);
- Fset_marker (w->start[type], make_int (start_pos), w->buffer);
- Fset_marker (w->pointm[type], make_int (point), w->buffer);
- w->last_point_x[type] = -1;
- w->last_point_y[type] = -1;
+ /* we're working with these a lot so precalculate them */
+ Bytecount slen = XSTRING_LENGTH (disp_string);
+ Bytecount bi_string_zv = slen;
+ Bytind bi_start_pos = charcount_to_bytecount (string_data (s), start_pos);
- /* Make sure a modeline is in the structs if needed. */
- need_modeline = ensure_modeline_generated (w, type);
+ pos_data data;
- /* Wait until here to set this so that the structs have a modeline
- generated in the case where one didn't exist. */
- yend = WINDOW_TEXT_BOTTOM (w);
+ int truncate_win = window_truncation_on (w);
+ int end_glyph_width = 0;
- bounds = calculate_display_line_boundaries (w, 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
+ functions that we don't have the luxury of being able to use
+ here. */
- /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */
- if (MINI_WINDOW_P (w)
- && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt))
- && !echo_area_active (f)
- && start_pos == BUF_BEGV (b))
- {
- struct prop_block pb;
- Lisp_Object string;
- prop = Dynarr_new (prop_block);
+ /* The variable ctl-arrow allows the user to specify what characters
+ can actually be displayed and which octal should be used for.
+ #### This variable should probably have some rethought done to
+ it.
- string = concat2(Vminibuf_preprompt, Vminibuf_prompt);
- pb.type = PROP_MINIBUF_PROMPT;
- pb.data.p_string.str = XSTRING_DATA(string);
- pb.data.p_string.len = XSTRING_LENGTH(string);
- Dynarr_add (prop, pb);
- }
- else
- prop = 0;
+ #### It would also be really nice if you could specify that
+ the characters come out in hex instead of in octal. Mule
+ does that by adding a ctl-hexa variable similar to ctl-arrow,
+ but that's bogus -- we need a more general solution. I
+ think you need to extend the concept of display tables
+ into a more general conversion mechanism. Ideally you
+ could specify a Lisp function that converts characters,
+ but this violates the Second Golden Rule and besides would
+ make things way way way way slow.
- while (ypos < yend)
- {
- struct display_line dl;
- struct display_line *dlp;
- int local;
+ So instead, we extend the display-table concept, which was
+ historically limited to 256-byte vectors, to one of the
+ following:
- if (Dynarr_length (dla) < Dynarr_largest (dla))
- {
- dlp = Dynarr_atp (dla, Dynarr_length (dla));
- local = 0;
- }
- else
- {
- xzero (dl);
- dlp = &dl;
- local = 1;
- }
+ a) A 256-entry vector, for backward compatibility;
+ b) char-table, mapping characters to values;
+ c) range-table, mapping ranges of characters to values;
+ d) a list of the above.
- dlp->bounds = bounds;
- dlp->offset = 0;
- start_pos = generate_display_line (w, dlp, 1, start_pos,
- w->hscroll, &prop, type);
- dlp->ypos = ypos + dlp->ascent;
- ypos = dlp->ypos + dlp->descent;
+ The (d) option allows you to specify multiple display tables
+ instead of just one. Each display table can specify conversions
+ for some characters and leave others unchanged. The way the
+ character gets displayed is determined by the first display table
+ with a binding for that character. This way, you could call a
+ function `enable-hex-display' that adds a hex display-table to
+ the list of display tables for the current buffer.
- if (ypos > yend)
- {
- int visible_height = dlp->ascent + dlp->descent;
+ #### ...not yet implemented... Also, we extend the concept of
+ "mapping" to include a printf-like spec. Thus you can make all
+ extended characters show up as hex with a display table like
+ this:
- dlp->clip = (ypos - yend);
- visible_height -= dlp->clip;
+ #s(range-table data ((256 524288) (format "%x")))
- if (visible_height < VERTICAL_CLIP (w, 1))
- {
- if (local)
- free_display_line (dlp);
- break;
- }
- }
- else
- dlp->clip = 0;
+ Since more than one display table is possible, you have
+ great flexibility in mapping ranges of characters. */
+ Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow)
+ ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
+ : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
+ ? 255 : 160));
- if (dlp->cursor_elt != -1)
- {
- /* #### This check is steaming crap. Have to get things
- fixed so when create_text_block hits EOB, we're done,
- period. */
- if (w->last_point_x[type] == -1)
- {
- w->last_point_x[type] = dlp->cursor_elt;
- w->last_point_y[type] = Dynarr_length (dla);
- }
- else
- {
- /* #### This means that we've added a cursor at EOB
- twice. Yuck oh yuck. */
- struct display_block *db =
- get_display_block_from_line (dlp, TEXT);
+ Lisp_Object face_dt, window_dt;
- Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR;
- dlp->cursor_elt = -1;
- }
- }
+ /* The text display block for this display line. */
+ struct display_block *db = get_display_block_from_line (dl, TEXT);
- if (dlp->num_chars > w->max_line_len)
- w->max_line_len = dlp->num_chars;
+ /* The first time through the main loop we need to force the glyph
+ data to be updated. */
+ int initial = 1;
- Dynarr_add (dla, *dlp);
+ /* Apparently the new extent_fragment_update returns an end position
+ equal to the position passed in if there are no more runs to be
+ displayed. */
+ int no_more_frags = 0;
- /* #### This isn't right, but it is close enough for now. */
- w->window_end_pos[type] = start_pos;
+ dl->used_prop_data = 0;
+ dl->num_chars = 0;
- /* #### This type of check needs to be done down in the
- generate_display_line call. */
- if (start_pos > BUF_ZV (b))
- break;
+ /* set up faces to use for clearing areas, used by
+ output_display_line */
+ dl->default_findex = default_face;
+ if (default_face)
+ {
+ dl->left_margin_findex = default_face;
+ dl->right_margin_findex = default_face;
+ }
+ else
+ {
+ dl->left_margin_findex =
+ get_builtin_face_cache_index (w, Vleft_margin_face);
+ dl->right_margin_findex =
+ get_builtin_face_cache_index (w, Vright_margin_face);
+ }
+
+ xzero (data);
+ data.ef = extent_fragment_new (disp_string, f);
+
+ /* These values are used by all of the rune addition routines. We add
+ them to this structure for ease of passing. */
+ data.d = d;
+ XSETWINDOW (data.window, w);
+ data.db = db;
+ data.dl = dl;
+
+ data.bi_bufpos = bi_start_pos;
+ data.pixpos = dl->bounds.left_in;
+ data.last_charset = Qunbound;
+ data.last_findex = default_face;
+ data.result_str = Qnil;
+ data.string = disp_string;
+
+ /* 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.cursor_type = NO_CURSOR;
+ data.cursor_x = -1;
+
+ data.start_col = 0;
+ /* I don't think we want this, string areas should not scroll with
+ the window
+ data.start_col = w->hscroll;
+ data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
+ */
+ data.bi_start_col_enabled = 0;
+ data.hscroll_glyph_width_adjust = 0;
+
+ /* We regenerate the line from the very beginning. */
+ Dynarr_reset (db->runes);
+
+ /* Why is this less than or equal and not just less than? If the
+ starting position is already equal to the maximum we can't add
+ anything else, right? Wrong. We might still have a newline to
+ add. A newline can use the room allocated for an end glyph since
+ if we add it we know we aren't going to be adding any end
+ glyph. */
+
+ /* #### Chuck -- I think this condition should be while (1).
+ Otherwise if (e.g.) there is one begin-glyph and one end-glyph
+ and the begin-glyph ends exactly at the end of the window, the
+ end-glyph and text might not be displayed. while (1) ensures
+ that the loop terminates only when either (a) there is
+ propagation data or (b) the end-of-line or end-of-buffer is hit.
+
+ #### Also I think you need to ensure that the operation
+ "add begin glyphs; add end glyphs; add text" is atomic and
+ can't get interrupted in the middle. If you run off the end
+ of the line during that operation, then you keep accumulating
+ propagation data until you're done. Otherwise, if the (e.g.)
+ there's a begin glyph at a particular position and attempting
+ to display that glyph results in window-end being hit and
+ propagation data being generated, then the character at that
+ position won't be displayed.
+
+ #### See also the comment after the end of this loop, below.
+ */
+ while (data.pixpos <= data.max_pixpos)
+ {
+ /* #### This check probably should not be necessary. */
+ if (data.bi_bufpos > bi_string_zv)
+ {
+ /* #### urk! More of this lossage! */
+ data.bi_bufpos--;
+ goto done;
+ }
+
+ /* Check for face changes. */
+ if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
+ {
+ /* 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);
+ /* This is somewhat cheesy but the alternative is to
+ propagate default_face into extent_fragment_update. */
+ if (data.findex == DEFAULT_INDEX)
+ data.findex = default_face;
+
+ get_display_tables (w, data.findex, &face_dt, &window_dt);
+
+ if (data.bi_bufpos == data.ef->end)
+ no_more_frags = 1;
+ }
+ initial = 0;
+
+ /* Determine what is next to be displayed. We first handle any
+ glyphs returned by glyphs_at_bufpos. If there are no glyphs to
+ display then we determine what to do based on the character at the
+ current buffer position. */
+
+ /* If the current position is covered by an invisible extent, do
+ nothing (except maybe add some ellipses).
+
+ #### The behavior of begin and end-glyphs at the edge of an
+ invisible extent should be investigated further. This is
+ fairly low priority though. */
+ if (data.ef->invisible)
+ {
+ /* #### Chuck, perhaps you could look at this code? I don't
+ really know what I'm doing. */
+ if (*prop)
+ {
+ Dynarr_free (*prop);
+ *prop = 0;
+ }
+
+ /* The extent fragment code only sets this when we should
+ really display the ellipses. It makes sure the ellipses
+ don't get displayed more than once in a row. */
+ if (data.ef->invisible_ellipses)
+ {
+ struct glyph_block gb;
+
+ data.ef->invisible_ellipses_already_displayed = 1;
+ data.ef->invisible_ellipses = 0;
+ gb.extent = Qnil;
+ gb.glyph = Vinvisible_text_glyph;
+ *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
+ GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
+ /* Perhaps they shouldn't propagate if the very next thing
+ is to display a newline (for compatibility with
+ selective-display-ellipses)? Maybe that's too
+ abstruse. */
+ if (*prop)
+ goto done;
+ }
+
+ /* #### What if we we're dealing with a display table? */
+ if (data.start_col)
+ data.start_col--;
+
+ if (data.bi_bufpos == bi_string_zv)
+ goto done;
+ else
+ INC_CHARBYTIND (string_data (s), data.bi_bufpos);
+ }
+
+ /* 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. */
+ else if (*prop)
+ {
+ dl->used_prop_data = 1;
+ *prop = add_propagation_runes (prop, &data);
+
+ if (*prop)
+ goto done; /* gee, a really narrow window */
+ 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! */
+ data.bi_bufpos = 0;
+ else
+ INC_CHARBYTIND (string_data (s), data.bi_bufpos);
+ }
+
+ /* If there are end glyphs, add them to the line. These are
+ the end glyphs for the previous run of text. We add them
+ 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)
+ {
+ *prop = add_glyph_runes (&data, END_GLYPHS);
+ if (*prop)
+ goto done;
+ }
+
+ /* 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 at end-of-buffer, we've already processed begin and
+ end-glyphs at this point and there's no text to process,
+ so we're done. */
+ else if (data.bi_bufpos == bi_string_zv)
+ goto done;
+
+ else
+ {
+ Lisp_Object entry = Qnil;
+ /* Get the character at the current buffer position. */
+ data.ch = string_char (s, data.bi_bufpos);
+ if (!NILP (face_dt) || !NILP (window_dt))
+ entry = display_table_entry (data.ch, face_dt, window_dt);
+
+ /* If there is a display table entry for it, hand it off to
+ add_disp_table_entry_runes and let it worry about it. */
+ if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
+ {
+ *prop = add_disp_table_entry_runes (&data, entry);
+
+ if (*prop)
+ goto done;
+ }
+
+ /* Check if we have hit a newline character. If so, add a marker
+ to the line and end this loop. */
+ else if (data.ch == '\n')
+ {
+ /* 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;
+ goto done;
+ }
+
+ /* If the current character is considered to be printable, then
+ just add it. */
+ else if (data.ch >= printable_min)
+ {
+ *prop = add_emchar_rune (&data);
+ if (*prop)
+ goto done;
+ }
+
+ /* If the current character is a tab, determine the next tab
+ starting position and add a blank rune which extends from the
+ current pixel position to that starting position. */
+ else if (data.ch == '\t')
+ {
+ int tab_start_pixpos = data.pixpos;
+ int next_tab_start;
+ int char_tab_width;
+ int prop_width = 0;
+
+ if (data.start_col > 1)
+ tab_start_pixpos -= (space_width (w) * (data.start_col - 1));
+
+ next_tab_start =
+ next_tab_position (w, tab_start_pixpos,
+ dl->bounds.left_in +
+ data.hscroll_glyph_width_adjust);
+ if (next_tab_start > data.max_pixpos)
+ {
+ prop_width = next_tab_start - data.max_pixpos;
+ next_tab_start = data.max_pixpos;
+ }
+ data.blank_width = next_tab_start - data.pixpos;
+ char_tab_width =
+ (next_tab_start - tab_start_pixpos) / space_width (w);
+
+ *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. */
+ assert (!(*prop));
+
+ if (prop_width)
+ {
+ struct prop_block pb;
+ *prop = Dynarr_new (prop_block);
+
+ pb.type = PROP_BLANK;
+ pb.data.p_blank.width = prop_width;
+ pb.data.p_blank.findex = data.findex;
+ Dynarr_add (*prop, pb);
+
+ goto done;
+ }
+ }
+
+ /* If character is a control character, pass it off to
+ add_control_char_runes.
+
+ The is_*() routines have undefined results on
+ arguments outside of the range [-1, 255]. (This
+ often bites people who carelessly use `char' instead
+ of `unsigned char'.)
+ */
+ else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
+ {
+ *prop = add_control_char_runes (&data, b);
+
+ if (*prop)
+ goto done;
+ }
+
+ /* If the character is above the ASCII range and we have not
+ already handled it, then print it as an octal number. */
+ else if (data.ch >= 0200)
+ {
+ *prop = add_octal_runes (&data);
+
+ if (*prop)
+ goto done;
+ }
+
+ /* Assume the current character is considered to be printable,
+ then just add it. */
+ else
+ {
+ *prop = add_emchar_rune (&data);
+ if (*prop)
+ goto done;
+ }
+
+ INC_CHARBYTIND (string_data (s), data.bi_bufpos);
+ }
+ }
+
+done:
+
+ /* Determine the starting point of the next line if we did not hit the
+ end of the buffer. */
+ if (data.bi_bufpos < bi_string_zv)
+ {
+ /* #### This check is not correct. If the line terminated
+ due to a begin-glyph or end-glyph hitting window-end, then
+ data.ch will not point to the character at data.bi_bufpos. If
+ you make the two changes mentioned at the top of this loop,
+ you should be able to say '(if (*prop))'. That should also
+ make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
+ check. */
+
+ /* The common case is that the line ended because we hit a newline.
+ In that case, the next character is just the next buffer
+ position. */
+ if (data.ch == '\n')
+ {
+ INC_CHARBYTIND (string_data (s), data.bi_bufpos);
+ }
+
+ /* Otherwise we have a buffer line which cannot fit on one display
+ line. */
+ else
+ {
+ struct glyph_block gb;
+ struct glyph_cachel *cachel;
+
+ /* If the line is to be truncated then we actually have to look
+ 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.findex = default_face;
+ gb.extent = Qnil;
+
+ if (truncate_win)
+ {
+ Bytind bi_pos;
+
+ /* Now find the start of the next line. */
+ bi_pos = bi_find_next_emchar_in_string (s, '\n', data.bi_bufpos, 1);
+
+ data.cursor_type = NO_CURSOR;
+ data.bi_bufpos = bi_pos;
+ gb.glyph = Vtruncation_glyph;
+ cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
+ }
+ else
+ {
+ /* The cursor can never be on the continuation glyph. */
+ data.cursor_type = NO_CURSOR;
+
+ /* data.bi_bufpos is already at the start of the next line. */
+
+ gb.glyph = Vcontinuation_glyph;
+ cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
+ }
+
+ if (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);
+ DEC_CHARPTR (endb);
+ if (charptr_emchar (endb) != '\n')
+ {
+ /* #### Damn this losing shit. */
+ data.bi_bufpos++;
+ }
+ }
+ }
+ }
+ else if (data.bi_bufpos == bi_string_zv)
+ {
+ /* We need to add a marker to the end of the line since there is no
+ newline character in order for the cursor to get drawn. We label
+ it as a newline so that it gets handled correctly by the
+ whitespace routines below. */
+
+ data.ch = '\n';
+ data.blank_width = DEVMETH (d, eol_cursor_width, ());
+ data.findex = default_face;
+ data.start_col = 0;
+ data.bi_start_col_enabled = 0;
+
+ data.max_pixpos += data.blank_width;
+ add_emchar_rune (&data);
+ data.max_pixpos -= data.blank_width;
+
+ /* #### urk! Chuck, this shit is bad news. Going around
+ manipulating invalid positions is guaranteed to result in
+ trouble sooner or later. */
+ data.bi_bufpos = bi_string_zv + 1;
+ }
+
+ /* Calculate left whitespace boundary. */
+ {
+ int elt = 0;
+
+ /* Whitespace past a newline is considered right whitespace. */
+ while (elt < Dynarr_length (db->runes))
+ {
+ struct rune *rb = Dynarr_atp (db->runes, elt);
+
+ if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
+ || rb->type == RUNE_BLANK)
+ {
+ dl->bounds.left_white += rb->width;
+ elt++;
+ }
+ else
+ elt = Dynarr_length (db->runes);
+ }
+ }
+
+ /* Calculate right whitespace boundary. */
+ {
+ int elt = Dynarr_length (db->runes) - 1;
+ int done = 0;
+
+ while (!done && elt >= 0)
+ {
+ struct rune *rb = Dynarr_atp (db->runes, elt);
+
+ if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
+ && isspace (rb->object.chr.ch))
+ && !rb->type == RUNE_BLANK)
+ {
+ dl->bounds.right_white = rb->xpos + rb->width;
+ done = 1;
+ }
+
+ elt--;
+
+ }
+
+ /* The line is blank so everything is considered to be right
+ whitespace. */
+ if (!done)
+ dl->bounds.right_white = dl->bounds.left_in;
+ }
+
+ /* Set the display blocks bounds. */
+ db->start_pos = dl->bounds.left_in;
+ if (Dynarr_length (db->runes))
+ {
+ struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
+
+ db->end_pos = 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);
+ }
+
+ dl->ascent = data.new_ascent;
+ dl->descent = data.new_descent;
+
+ {
+ unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
+
+ if (dl->ascent < ascent)
+ dl->ascent = ascent;
+ }
+ {
+ unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
+
+ if (dl->descent < descent)
+ dl->descent = descent;
+ }
+
+ dl->cursor_elt = data.cursor_x;
+ /* #### lossage lossage lossage! Fix this shit! */
+ if (data.bi_bufpos > bi_string_zv)
+ dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, bi_string_zv);
+ else
+ dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, data.bi_bufpos) - 1;
+ if (truncate_win)
+ data.dl->num_chars =
+ string_column_at_point (s, dl->end_bufpos, XINT (b->tab_width));
+ else
+ /* This doesn't correctly take into account tabs and control
+ characters but if the window isn't being truncated then this
+ value isn't going to end up being used anyhow. */
+ data.dl->num_chars = dl->end_bufpos - dl->bufpos;
+
+ /* #### handle horizontally scrolled line with text none of which
+ was actually laid out. */
+
+ /* #### handle any remainder of overlay arrow */
+
+ if (*prop == ADD_FAILED)
+ *prop = NULL;
+
+ if (truncate_win && *prop)
+ {
+ Dynarr_free (*prop);
+ *prop = NULL;
+ }
+
+ extent_fragment_delete (data.ef);
+
+ /* #### If we started at EOB, then make sure we return a value past
+ it so that regenerate_window will exit properly. This is bogus.
+ The main loop should get fixed so that it isn't necessary to call
+ this function if we are already at EOB. */
+
+ if (data.bi_bufpos == bi_string_zv && bi_start_pos == bi_string_zv)
+ return bytecount_to_charcount (string_data (s), data.bi_bufpos) + 1; /* Yuck! */
+ else
+ return bytecount_to_charcount (string_data (s), data.bi_bufpos);
+}
+
+/* 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
+ 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.
+
+ 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.*/
+
+static Bufpos
+generate_string_display_line (struct window *w, Lisp_Object disp_string,
+ struct display_line *dl,
+ Bufpos start_pos,
+ prop_block_dynarr **prop,
+ face_index default_face)
+{
+ 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);
+ if (dl->left_glyphs)
+ {
+ Dynarr_free (dl->left_glyphs);
+ dl->left_glyphs = 0;
+ }
+ if (dl->right_glyphs)
+ {
+ Dynarr_free (dl->right_glyphs);
+ dl->right_glyphs = 0;
+ }
+
+ /* We aren't generating a modeline at the moment. */
+ dl->modeline = 0;
+
+ /* Create a display block for the text region of the line. */
+ ret_bufpos = create_string_text_block (w, disp_string, dl, start_pos,
+ prop, default_face);
+ dl->bufpos = start_pos;
+ if (dl->end_bufpos < dl->bufpos)
+ dl->end_bufpos = dl->bufpos;
+
+ /* If there are left glyphs associated with any character in the
+ text block, then create a display block to handle them. */
+ if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
+ create_left_glyph_block (w, dl, 0);
+
+ /* If there are right glyphs associated with any character in the
+ text block, then create a display block to handle them. */
+ if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
+ create_right_glyph_block (w, dl);
+
+ return ret_bufpos;
+}
+
+/* This is ripped off from regenerate_window. All we want to do is
+ loop through elements in the string creating display lines until we
+ have covered the provided area. Simple really. */
+void
+generate_displayable_area (struct window *w, Lisp_Object disp_string,
+ int xpos, int ypos, int width, int height,
+ display_line_dynarr* dla,
+ Bufpos start_pos,
+ face_index default_face)
+{
+ int yend = ypos + height;
+ Charcount s_zv;
+
+ prop_block_dynarr *prop = 0;
+ layout_bounds bounds;
+ assert (dla);
+
+ Dynarr_reset (dla);
+ /* if there's nothing to do then do nothing. code after this assumes
+ there is something to do. */
+ if (NILP (disp_string))
+ return;
+
+ s_zv = XSTRING_CHAR_LENGTH (disp_string) - 1;
+
+ bounds.left_out = xpos;
+ bounds.right_out = xpos + width;
+ /* The inner boundaries mark where the glyph margins are located. */
+ bounds.left_in = bounds.left_out + window_left_margin_width (w);
+ bounds.right_in = bounds.right_out - window_right_margin_width (w);
+ /* We cannot fully calculate the whitespace boundaries as they
+ depend on the contents of the line being displayed. */
+ bounds.left_white = bounds.left_in;
+ bounds.right_white = bounds.right_in;
+
+ while (ypos < yend)
+ {
+ struct display_line dl;
+ struct display_line *dlp;
+ Bufpos next_pos;
+ int local;
+
+ if (Dynarr_length (dla) < Dynarr_largest (dla))
+ {
+ dlp = Dynarr_atp (dla, Dynarr_length (dla));
+ local = 0;
+ }
+ else
+ {
+
+ xzero (dl);
+ dlp = &dl;
+ local = 1;
+ }
+
+ dlp->bounds = bounds;
+ dlp->offset = 0;
+ next_pos = generate_string_display_line (w, disp_string, dlp, start_pos,
+ &prop, default_face);
+ /* we need to make sure that we continue along the line if there
+ is more left to display otherwise we just end up redisplaying
+ the same chunk over and over again. */
+ if (next_pos == start_pos && next_pos < s_zv)
+ start_pos++;
+ else
+ start_pos = next_pos;
+
+ dlp->ypos = ypos + dlp->ascent;
+ ypos = dlp->ypos + dlp->descent;
+
+ if (ypos > yend)
+ {
+ int visible_height = dlp->ascent + dlp->descent;
+
+ dlp->clip = (ypos - yend);
+ visible_height -= dlp->clip;
+
+ if (visible_height < VERTICAL_CLIP (w, 1))
+ {
+ if (local)
+ free_display_line (dlp);
+ break;
+ }
+ }
+ else
+ dlp->clip = 0;
+
+ Dynarr_add (dla, *dlp);
+
+ /* #### This type of check needs to be done down in the
+ generate_display_line call. */
+ if (start_pos >= s_zv)
+ break;
+ }
+
+ if (prop)
+ Dynarr_free (prop);
+}
+
+\f
+/***************************************************************************/
+/* */
+/* window-regeneration routines */
+/* */
+/***************************************************************************/
+
+/* For a given window and starting position in the buffer it contains,
+ ensure that the TYPE display lines accurately represent the
+ presentation of the window. We pass the buffer instead of getting
+ it from the window since redisplay_window may have temporarily
+ changed it to the echo area buffer. */
+
+static void
+regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type)
+{
+ struct frame *f = XFRAME (w->frame);
+ struct buffer *b = XBUFFER (w->buffer);
+ int ypos = WINDOW_TEXT_TOP (w);
+ int yend; /* set farther down */
+
+ prop_block_dynarr *prop;
+ layout_bounds bounds;
+ display_line_dynarr *dla;
+ int need_modeline;
+
+ /* The lines had better exist by this point. */
+ if (!(dla = window_display_lines (w, type)))
+ abort ();
+ Dynarr_reset (dla);
+ w->max_line_len = 0;
+
+ /* Normally these get updated in redisplay_window but it is possible
+ for this function to get called from some other points where that
+ update may not have occurred. This acts as a safety check. */
+ if (!Dynarr_length (w->face_cachels))
+ reset_face_cachels (w);
+ if (!Dynarr_length (w->glyph_cachels))
+ reset_glyph_cachels (w);
+
+ Fset_marker (w->start[type], make_int (start_pos), w->buffer);
+ Fset_marker (w->pointm[type], make_int (point), w->buffer);
+ w->last_point_x[type] = -1;
+ w->last_point_y[type] = -1;
+
+ /* Make sure a modeline is in the structs if needed. */
+ need_modeline = ensure_modeline_generated (w, type);
+
+ /* Wait until here to set this so that the structs have a modeline
+ generated in the case where one didn't exist. */
+ yend = WINDOW_TEXT_BOTTOM (w);
+
+ bounds = calculate_display_line_boundaries (w, 0);
+
+ /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */
+ if (MINI_WINDOW_P (w)
+ && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt))
+ && !echo_area_active (f)
+ && start_pos == BUF_BEGV (b))
+ {
+ struct prop_block pb;
+ Lisp_Object string;
+ prop = Dynarr_new (prop_block);
+
+ string = concat2(Vminibuf_preprompt, Vminibuf_prompt);
+ pb.type = PROP_MINIBUF_PROMPT;
+ pb.data.p_string.str = XSTRING_DATA(string);
+ pb.data.p_string.len = XSTRING_LENGTH(string);
+ Dynarr_add (prop, pb);
+ }
+ else
+ prop = 0;
+
+ while (ypos < yend)
+ {
+ struct display_line dl;
+ struct display_line *dlp;
+ int local;
+
+ if (Dynarr_length (dla) < Dynarr_largest (dla))
+ {
+ dlp = Dynarr_atp (dla, Dynarr_length (dla));
+ local = 0;
+ }
+ else
+ {
+
+ xzero (dl);
+ dlp = &dl;
+ local = 1;
+ }
+
+ dlp->bounds = bounds;
+ dlp->offset = 0;
+ start_pos = generate_display_line (w, dlp, 1, start_pos,
+ w->hscroll, &prop, type);
+ dlp->ypos = ypos + dlp->ascent;
+ ypos = dlp->ypos + dlp->descent;
+
+ if (ypos > yend)
+ {
+ int visible_height = dlp->ascent + dlp->descent;
+
+ dlp->clip = (ypos - yend);
+ visible_height -= dlp->clip;
+
+ if (visible_height < VERTICAL_CLIP (w, 1))
+ {
+ if (local)
+ free_display_line (dlp);
+ break;
+ }
+ }
+ else
+ dlp->clip = 0;
+
+ if (dlp->cursor_elt != -1)
+ {
+ /* #### This check is steaming crap. Have to get things
+ fixed so when create_text_block hits EOB, we're done,
+ period. */
+ if (w->last_point_x[type] == -1)
+ {
+ w->last_point_x[type] = dlp->cursor_elt;
+ w->last_point_y[type] = Dynarr_length (dla);
+ }
+ else
+ {
+ /* #### This means that we've added a cursor at EOB
+ twice. Yuck oh yuck. */
+ struct display_block *db =
+ get_display_block_from_line (dlp, TEXT);
+
+ Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR;
+ dlp->cursor_elt = -1;
+ }
+ }
+
+ if (dlp->num_chars > w->max_line_len)
+ w->max_line_len = dlp->num_chars;
+
+ Dynarr_add (dla, *dlp);
+
+ /* #### This isn't right, but it is close enough for now. */
+ w->window_end_pos[type] = start_pos;
+
+ /* #### This type of check needs to be done down in the
+ generate_display_line call. */
+ if (start_pos > BUF_ZV (b))
+ break;
}
if (prop)
- Dynarr_free (prop);
+ Dynarr_free (prop);
/* #### More not quite right, but close enough. */
/* #### Ben sez: apparently window_end_pos[] is measured
/* If the changes are below the visible area then if point hasn't
moved return success otherwise fail in order to be safe. */
if (line > dla_end)
- {
- return regenerate_window_extents_only_changed (w, startp, pointm,
- extent_beg_unchanged,
- extent_end_unchanged);
- }
+ return regenerate_window_extents_only_changed (w, startp, pointm,
+ extent_beg_unchanged,
+ extent_end_unchanged);
else
/* At this point we know what line the changes first affect. We
now redraw that line. If the changes are contained within it
&& extent_end_unchanged != -1
&& ((extent_beg_unchanged < ddl->bufpos)
|| (extent_end_unchanged > ddl->end_bufpos)))
- {
- return
- regenerate_window_extents_only_changed (w, startp, pointm,
- extent_beg_unchanged,
- extent_end_unchanged);
- }
+ return regenerate_window_extents_only_changed (w, startp, pointm,
+ extent_beg_unchanged,
+ extent_end_unchanged);
else
return 1;
}
}
Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer);
- /* If the buffer has changed we have to invalid all of our face
+ /* If the buffer has changed we have to invalidate all of our face
cache elements. */
if ((!echo_active && b != window_display_buffer (w))
|| !Dynarr_length (w->face_cachels)
&& !f->extents_changed
&& !f->faces_changed
&& !f->glyphs_changed
+ && !f->subwindows_changed
&& !f->point_changed
&& !f->windows_structure_changed)
{
&& !f->extents_changed
&& !f->faces_changed
&& !f->glyphs_changed
+ && !f->subwindows_changed
&& !f->windows_structure_changed)
{
if (point_visible (w, pointm, CURRENT_DISP)
&& !f->clip_changed
&& !f->faces_changed
&& !f->glyphs_changed
+ && !f->subwindows_changed
&& !f->windows_structure_changed
&& !f->frame_changed
&& !truncation_changed
Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1
? BUF_ZV (b)
: BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1);
-
- update_line_start_cache (w, start, end, pointm, 1);
+ /* Don't pollute the cache if not sure if we are correct */
+ if (w->start_at_line_beg)
+ update_line_start_cache (w, start, end, pointm, 1);
redisplay_output_window (w);
/*
* If we just displayed the echo area, the line start cache is
being handled. */
update_frame_menubars (f);
#endif /* HAVE_MENUBARS */
-
+ update_frame_gutters (f);
+ /* 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);
/* Erase the frame before outputting its contents. */
if (f->clear)
- DEVMETH (d, clear_frame, (f));
+ {
+ DEVMETH (d, clear_frame, (f));
+ }
+
+ /* invalidate the subwindow cache. we are going to reuse the glyphs
+ flag here to cause subwindows to get instantiated. This is
+ because subwindows changed is less strict - dealing with things
+ like the clicked state of button. */
+ if (!Dynarr_length (f->subwindow_cachels)
+ || f->glyphs_changed
+ || f->frame_changed)
+ reset_subwindow_cachels (f);
+ else
+ mark_subwindow_cachels_as_not_updated (f);
/* Do the selected window first. */
redisplay_window (FRAME_SELECTED_WINDOW (f), 0);
f->faces_changed = 0;
f->frame_changed = 0;
f->glyphs_changed = 0;
+ f->subwindows_changed = 0;
f->icon_changed = 0;
f->menubar_changed = 0;
f->modeline_changed = 0;
f->point_changed = 0;
f->toolbar_changed = 0;
+ f->gutter_changed = 0;
f->windows_changed = 0;
f->windows_structure_changed = 0;
f->window_face_cache_reset = 0;
f->faces_changed || f->frame_changed || f->menubar_changed ||
f->modeline_changed || f->point_changed || f->size_changed ||
f->toolbar_changed || f->windows_changed || f->size_slipped ||
- f->windows_structure_changed || f->glyphs_changed)
+ f->windows_structure_changed || f->glyphs_changed ||
+ f->subwindows_changed || f->gutter_changed)
{
preempted = redisplay_frame (f, 0);
}
f->faces_changed || f->frame_changed || f->menubar_changed ||
f->modeline_changed || f->point_changed || f->size_changed ||
f->toolbar_changed || f->windows_changed ||
- f->windows_structure_changed ||
- f->glyphs_changed)
+ f->windows_structure_changed || f->gutter_changed ||
+ f->glyphs_changed || f->subwindows_changed)
{
preempted = redisplay_frame (f, 0);
}
d->faces_changed = 0;
d->frame_changed = 0;
d->glyphs_changed = 0;
+ d->subwindows_changed = 0;
d->icon_changed = 0;
d->menubar_changed = 0;
d->modeline_changed = 0;
d->point_changed = 0;
d->toolbar_changed = 0;
+ d->gutter_changed = 0;
d->windows_changed = 0;
d->windows_structure_changed = 0;
!faces_changed && !frame_changed && !icon_changed &&
!menubar_changed && !modeline_changed && !point_changed &&
!size_changed && !toolbar_changed && !windows_changed &&
- !glyphs_changed &&
- !windows_structure_changed && !disable_preemption &&
- preemption_count < max_preempts)
+ !glyphs_changed && !subwindows_changed &&
+ !gutter_changed && !windows_structure_changed &&
+ !disable_preemption && preemption_count < max_preempts)
goto done;
DEVICE_LOOP_NO_BREAK (devcons, concons)
d->faces_changed || d->frame_changed || d->icon_changed ||
d->menubar_changed || d->modeline_changed || d->point_changed ||
d->size_changed || d->toolbar_changed || d->windows_changed ||
- d->windows_structure_changed ||
- d->glyphs_changed)
+ d->windows_structure_changed || d->gutter_changed ||
+ d->glyphs_changed || d->subwindows_changed)
{
preempted = redisplay_device (d);
extents_changed = 0;
frame_changed = 0;
glyphs_changed = 0;
+ subwindows_changed = 0;
icon_changed = 0;
menubar_changed = 0;
modeline_changed = 0;
point_changed = 0;
toolbar_changed = 0;
+ gutter_changed = 0;
windows_changed = 0;
windows_structure_changed = 0;
RESET_CHANGED_SET_FLAGS;
else
{
struct line_start_cache lsc;
-
+
lsc.start = dl->bufpos;
lsc.end = dl->end_bufpos;
lsc.height = dl->ascent + dl->descent;