From: Eli Zaretskii Date: Sat, 7 Jul 2012 16:36:02 +0000 (+0300) Subject: Fix bug #11832 with truncated lines when fringes are disabled on GUI frames. X-Git-Tag: emacs-24.2.90~1199^2~149 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=58dd0aa4c5a1e67d5b78a14e98b9da1a1433fbb4;p=emacs.git Fix bug #11832 with truncated lines when fringes are disabled on GUI frames. src/xdisp.c (init_iterator): Get dimensions of truncation and continuation glyphs even if on GUI frames. Adjust it->last_visible_x on GUI frames when the left or right fringes, or both, are absent. (start_display, move_it_in_display_line_to): Handle the case of a GUI frame without a fringe to display continuation or truncation glyphs. (insert_left_trunc_glyphs): Support GUI frames: make sure truncation glyphs overwrite enough glyphs from the current line to have sufficient space in pixels. (display_line): Support truncation and continuation glyphs on GUI frames. If some spare pixels are left on the line after inserting the truncation glyphs, fill that space with a stretch glyph of a suitably computed width. src/term.c (produce_special_glyphs): Call PRODUCE_GLYPHS, not produce_glyphs, to support GUI sessions. --- diff --git a/src/ChangeLog b/src/ChangeLog index 9b76d795249..5eeace9beaf 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,25 @@ +2012-07-07 Eli Zaretskii + + Support truncation and continuation glyphs on GUI frames, when + fringes are disabled. (Bug#11832) + * xdisp.c (init_iterator): Get dimensions of truncation and + continuation glyphs even if on GUI frames. Adjust + it->last_visible_x on GUI frames when the left or right fringes, + or both, are absent. + (start_display, move_it_in_display_line_to): Handle the case of a + GUI frame without a fringe to display continuation or truncation + glyphs. + (insert_left_trunc_glyphs): Support GUI frames: make sure + truncation glyphs overwrite enough glyphs from the current line to + have sufficient space in pixels. + (display_line): Support truncation and continuation glyphs on GUI + frames. If some spare pixels are left on the line after inserting + the truncation glyphs, fill that space with a stretch glyph of a + suitably computed width. + + * term.c (produce_special_glyphs): Call PRODUCE_GLYPHS, not + produce_glyphs, to support GUI sessions. + 2012-07-07 Paul Eggert * sysdep.c (ULLONG_MAX): Define if not already defined (Bug#11781). diff --git a/src/term.c b/src/term.c index 5e48cbbfc64..900818559cd 100644 --- a/src/term.c +++ b/src/term.c @@ -1940,7 +1940,7 @@ produce_special_glyphs (struct it *it, enum display_element_type what) temp_it.face_id = GLYPH_FACE (glyph); temp_it.len = CHAR_BYTES (temp_it.c); - produce_glyphs (&temp_it); + PRODUCE_GLYPHS (&temp_it); it->pixel_width = temp_it.pixel_width; it->nglyphs = temp_it.pixel_width; } diff --git a/src/xdisp.c b/src/xdisp.c index 0684a68444e..87f2e365198 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -2731,31 +2731,28 @@ init_iterator (struct it *it, struct window *w, it->line_wrap = TRUNCATE; /* Get dimensions of truncation and continuation glyphs. These are - displayed as fringe bitmaps under X, so we don't need them for such - frames. */ - if (!FRAME_WINDOW_P (it->f)) + displayed as fringe bitmaps under X, but we need them for such + frames when the fringes are turned off. */ + if (it->line_wrap == TRUNCATE) { - if (it->line_wrap == TRUNCATE) - { - /* We will need the truncation glyph. */ - eassert (it->glyph_row == NULL); - produce_special_glyphs (it, IT_TRUNCATION); - it->truncation_pixel_width = it->pixel_width; - } - else - { - /* We will need the continuation glyph. */ - eassert (it->glyph_row == NULL); - produce_special_glyphs (it, IT_CONTINUATION); - it->continuation_pixel_width = it->pixel_width; - } - - /* Reset these values to zero because the produce_special_glyphs - above has changed them. */ - it->pixel_width = it->ascent = it->descent = 0; - it->phys_ascent = it->phys_descent = 0; + /* We will need the truncation glyph. */ + eassert (it->glyph_row == NULL); + produce_special_glyphs (it, IT_TRUNCATION); + it->truncation_pixel_width = it->pixel_width; + } + else + { + /* We will need the continuation glyph. */ + eassert (it->glyph_row == NULL); + produce_special_glyphs (it, IT_CONTINUATION); + it->continuation_pixel_width = it->pixel_width; } + /* Reset these values to zero because the produce_special_glyphs + above has changed them. */ + it->pixel_width = it->ascent = it->descent = 0; + it->phys_ascent = it->phys_descent = 0; + /* Set this after getting the dimensions of truncation and continuation glyphs, so that we don't produce glyphs when calling produce_special_glyphs, above. */ @@ -2783,11 +2780,14 @@ init_iterator (struct it *it, struct window *w, it->last_visible_x = (it->first_visible_x + window_box_width (w, TEXT_AREA)); - /* If we truncate lines, leave room for the truncator glyph(s) at + /* If we truncate lines, leave room for the truncation glyph(s) at the right margin. Otherwise, leave room for the continuation - glyph(s). Truncation and continuation glyphs are not inserted - for window-based redisplay. */ - if (!FRAME_WINDOW_P (it->f)) + glyph(s). Done only if the window has no fringes. Since we + don't know at this point whether there will be any R2L lines in + the window, we reserve space for truncation/continuation glyphs + even if only one of the fringes is absent. */ + if (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0 + || (it->bidi_p && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)) { if (it->line_wrap == TRUNCATE) it->last_visible_x -= it->truncation_pixel_width; @@ -2923,7 +2923,10 @@ start_display (struct it *it, struct window *w, struct text_pos pos) /* Or it fits exactly and we're on a window system frame. */ || (new_x == it->last_visible_x - && FRAME_WINDOW_P (it->f)))) + && FRAME_WINDOW_P (it->f) + && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L) + ? WINDOW_LEFT_FRINGE_WIDTH (it->w) + : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))) { if ((it->current.dpvec_index >= 0 || it->current.overlay_string_index >= 0) @@ -8327,7 +8330,10 @@ move_it_in_display_line_to (struct it *it, /* Or it fits exactly and we're on a window system frame. */ || (new_x == it->last_visible_x - && FRAME_WINDOW_P (it->f)))) + && FRAME_WINDOW_P (it->f) + && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L) + ? WINDOW_LEFT_FRINGE_WIDTH (it->w) + : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))) { if (/* IT->hpos == 0 means the very first glyph doesn't fit on the line, e.g. a wide image. */ @@ -8509,6 +8515,9 @@ move_it_in_display_line_to (struct it *it, && it->current_x >= it->last_visible_x) { if (!FRAME_WINDOW_P (it->f) + || ((it->bidi_p && it->bidi_it.paragraph_dir == R2L) + ? WINDOW_LEFT_FRINGE_WIDTH (it->w) + : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)) { int at_eob_p = 0; @@ -18203,11 +18212,8 @@ get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string) } -/* Insert truncation glyphs at the start of IT->glyph_row. Truncation - glyphs are only inserted for terminal frames since we can't really - win with truncation glyphs when partially visible glyphs are - involved. Which glyphs to insert is determined by - produce_special_glyphs. */ +/* Insert truncation glyphs at the start of IT->glyph_row. Which + glyphs to insert is determined by produce_special_glyphs. */ static void insert_left_trunc_glyphs (struct it *it) @@ -18215,7 +18221,11 @@ insert_left_trunc_glyphs (struct it *it) struct it truncate_it; struct glyph *from, *end, *to, *toend; - eassert (!FRAME_WINDOW_P (it->f)); + eassert (!FRAME_WINDOW_P (it->f) + || (!it->glyph_row->reversed_p + && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0) + || (it->glyph_row->reversed_p + && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)); /* Get the truncation glyphs. */ truncate_it = *it; @@ -18230,20 +18240,66 @@ insert_left_trunc_glyphs (struct it *it) /* Overwrite glyphs from IT with truncation glyphs. */ if (!it->glyph_row->reversed_p) { + short tused = truncate_it.glyph_row->used[TEXT_AREA]; + from = truncate_it.glyph_row->glyphs[TEXT_AREA]; - end = from + truncate_it.glyph_row->used[TEXT_AREA]; + end = from + tused; to = it->glyph_row->glyphs[TEXT_AREA]; toend = to + it->glyph_row->used[TEXT_AREA]; + if (FRAME_WINDOW_P (it->f)) + { + /* On GUI frames, when variable-size fonts are displayed, + the truncation glyphs may need more pixels than the row's + glyphs they overwrite. We overwrite more glyphs to free + enough screen real estate, and enlarge the stretch glyph + on the right (see display_line), if there is one, to + preserve the screen position of the truncation glyphs on + the right. */ + int w = 0; + struct glyph *g = to; + short used; + + while (g < toend && it->glyph_row->x + w < 0) + { + w += g->pixel_width; + ++g; + } + it->glyph_row->x = 0; + w = 0; + while (g < toend && w < it->truncation_pixel_width) + { + w += g->pixel_width; + ++g; + } + if (g - to - tused > 0) + { + memmove (to + tused, g, toend - g); + it->glyph_row->used[TEXT_AREA] -= g - to - tused; + } + used = it->glyph_row->used[TEXT_AREA]; + if (it->glyph_row->truncated_on_right_p + && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0 + && it->glyph_row->glyphs[TEXT_AREA][used - 2].type + == STRETCH_GLYPH) + { + int extra = w - it->truncation_pixel_width; + + it->glyph_row->glyphs[TEXT_AREA][used - 2].pixel_width += extra; + } + } while (from < end) *to++ = *from++; /* There may be padding glyphs left over. Overwrite them too. */ - while (to < toend && CHAR_GLYPH_PADDING_P (*to)) + if (!FRAME_WINDOW_P (it->f)) { - from = truncate_it.glyph_row->glyphs[TEXT_AREA]; - while (from < end) - *to++ = *from++; + while (to < toend && CHAR_GLYPH_PADDING_P (*to)) + { + from = truncate_it.glyph_row->glyphs[TEXT_AREA]; + while (from < end) + *to++ = *from++; + } } if (to > toend) @@ -18251,22 +18307,48 @@ insert_left_trunc_glyphs (struct it *it) } else { + short tused = truncate_it.glyph_row->used[TEXT_AREA]; + /* In R2L rows, overwrite the last (rightmost) glyphs, and do that back to front. */ end = truncate_it.glyph_row->glyphs[TEXT_AREA]; from = end + truncate_it.glyph_row->used[TEXT_AREA] - 1; toend = it->glyph_row->glyphs[TEXT_AREA]; to = toend + it->glyph_row->used[TEXT_AREA] - 1; + if (FRAME_WINDOW_P (it->f)) + { + int w = 0; + struct glyph *g = to; + + while (g >= toend && w < it->truncation_pixel_width) + { + w += g->pixel_width; + --g; + } + if (to - g - tused > 0) + to = g + tused; + if (it->glyph_row->truncated_on_right_p + && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0 + && it->glyph_row->glyphs[TEXT_AREA][1].type == STRETCH_GLYPH) + { + int extra = w - it->truncation_pixel_width; + + it->glyph_row->glyphs[TEXT_AREA][1].pixel_width += extra; + } + } while (from >= end && to >= toend) *to-- = *from--; - while (to >= toend && CHAR_GLYPH_PADDING_P (*to)) + if (!FRAME_WINDOW_P (it->f)) { - from = - truncate_it.glyph_row->glyphs[TEXT_AREA] - + truncate_it.glyph_row->used[TEXT_AREA] - 1; - while (from >= end && to >= toend) - *to-- = *from--; + while (to >= toend && CHAR_GLYPH_PADDING_P (*to)) + { + from = + truncate_it.glyph_row->glyphs[TEXT_AREA] + + truncate_it.glyph_row->used[TEXT_AREA] - 1; + while (from >= end && to >= toend) + *to-- = *from--; + } } if (from >= end) { @@ -19392,13 +19474,19 @@ display_line (struct it *it) new_x > it->last_visible_x /* Or it fits exactly on a window system frame. */ || (new_x == it->last_visible_x - && FRAME_WINDOW_P (it->f)))) + && FRAME_WINDOW_P (it->f) + && (row->reversed_p + ? WINDOW_LEFT_FRINGE_WIDTH (it->w) + : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))) { /* End of a continued line. */ if (it->hpos == 0 || (new_x == it->last_visible_x - && FRAME_WINDOW_P (it->f))) + && FRAME_WINDOW_P (it->f) + && (row->reversed_p + ? WINDOW_LEFT_FRINGE_WIDTH (it->w) + : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))) { /* Current glyph is the only one on the line or fits exactly on the line. We must continue @@ -19509,6 +19597,10 @@ display_line (struct it *it) window system frames. We leave the glyph in this row and let it fill the row, but don't consume the TAB. */ + if ((row->reversed_p + ? WINDOW_LEFT_FRINGE_WIDTH (it->w) + : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0) + produce_special_glyphs (it, IT_CONTINUATION); it->continuation_lines_width += it->last_visible_x; row->ends_in_middle_of_char_p = 1; row->continued_p = 1; @@ -19526,7 +19618,10 @@ display_line (struct it *it) row->used[TEXT_AREA] = n_glyphs_before + i; /* Display continuation glyphs. */ - if (!FRAME_WINDOW_P (it->f)) + if (!FRAME_WINDOW_P (it->f) + || (row->reversed_p + ? WINDOW_LEFT_FRINGE_WIDTH (it->w) + : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0) produce_special_glyphs (it, IT_CONTINUATION); row->continued_p = 1; @@ -19633,12 +19728,15 @@ display_line (struct it *it) /* If we truncate lines, we are done when the last displayed glyphs reach past the right margin of the window. */ if (it->line_wrap == TRUNCATE - && (FRAME_WINDOW_P (it->f) + && (FRAME_WINDOW_P (it->f) && WINDOW_RIGHT_FRINGE_WIDTH (it->w) ? (it->current_x >= it->last_visible_x) : (it->current_x > it->last_visible_x))) { /* Maybe add truncation glyphs. */ - if (!FRAME_WINDOW_P (it->f)) + if (!FRAME_WINDOW_P (it->f) + || (row->reversed_p + ? WINDOW_LEFT_FRINGE_WIDTH (it->w) + : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0) { int i, n; @@ -19663,9 +19761,36 @@ display_line (struct it *it) i = row->used[TEXT_AREA] - (i + 1); } - for (n = row->used[TEXT_AREA]; i < n; ++i) + it->current_x = x_before; + if (!FRAME_WINDOW_P (it->f)) + { + for (n = row->used[TEXT_AREA]; i < n; ++i) + { + row->used[TEXT_AREA] = i; + produce_special_glyphs (it, IT_TRUNCATION); + } + } + else { + int stretch_width = it->last_visible_x - it->current_x; + row->used[TEXT_AREA] = i; + if (stretch_width > 0) + { + struct face *face = FACE_FROM_ID (it->f, it->face_id); + struct font *font = + face->font ? face->font : FRAME_FONT (it->f); + int stretch_ascent = + (((it->ascent + it->descent) + * FONT_BASE (font)) / FONT_HEIGHT (font)); + struct text_pos saved_pos = it->position; + + memset (&it->position, 0, sizeof it->position); + append_stretch_glyph (it, make_number (0), stretch_width, + it->ascent + it->descent, + stretch_ascent); + it->position = saved_pos; + } produce_special_glyphs (it, IT_TRUNCATION); } } @@ -19684,6 +19809,7 @@ display_line (struct it *it) row->exact_window_width_line_p = 1; goto at_end_of_line; } + it->current_x = x_before; } row->truncated_on_right_p = 1; @@ -19691,7 +19817,6 @@ display_line (struct it *it) reseat_at_next_visible_line_start (it, 0); row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n'; it->hpos = hpos_before; - it->current_x = x_before; break; } } @@ -19704,7 +19829,10 @@ display_line (struct it *it) if (it->first_visible_x && IT_CHARPOS (*it) != CHARPOS (row->start.pos)) { - if (!FRAME_WINDOW_P (it->f)) + if (!FRAME_WINDOW_P (it->f) + || (row->reversed_p + ? WINDOW_RIGHT_FRINGE_WIDTH (it->w) + : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0) insert_left_trunc_glyphs (it); row->truncated_on_left_p = 1; } @@ -21913,7 +22041,10 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st if (it->first_visible_x && it_charpos > 0) { - if (!FRAME_WINDOW_P (it->f)) + if (!FRAME_WINDOW_P (it->f) + || (row->reversed_p + ? WINDOW_RIGHT_FRINGE_WIDTH (it->w) + : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0) insert_left_trunc_glyphs (it); row->truncated_on_left_p = 1; }