+ /* 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);
+
+ /* #### More not quite right, but close enough. */
+ /* #### 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? */
+ w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type];
+
+ if (need_modeline)
+ {
+ /* We know that this is the right thing to use because we put it
+ there when we first started working in this function. */
+ generate_modeline (w, Dynarr_atp (dla, 0), type);
+ }
+}
+
+#define REGEN_INC_FIND_START_END \
+ do { \
+ /* Determine start and end of lines. */ \
+ if (!Dynarr_length (cdla)) \
+ return 0; \
+ else \
+ { \
+ if (Dynarr_atp (cdla, 0)->modeline && Dynarr_atp (ddla, 0)->modeline) \
+ { \
+ dla_start = 1; \
+ } \
+ else if (!Dynarr_atp (cdla, 0)->modeline \
+ && !Dynarr_atp (ddla, 0)->modeline) \
+ { \
+ dla_start = 0; \
+ } \
+ else \
+ abort (); /* structs differ */ \
+ \
+ dla_end = Dynarr_length (cdla) - 1; \
+ } \
+ \
+ start_pos = (Dynarr_atp (cdla, dla_start)->bufpos \
+ + Dynarr_atp (cdla, dla_start)->offset); \