Mercurial > emacs
changeset 96512:a8382026762a
(IT_OVERFLOW_NEWLINE_INTO_FRINGE): Turn it off if word-wrapping.
(IT_DISPLAYING_WHITESPACE): New macro.
(move_it_in_display_line_to): Handle MOVE_TO_X requests properly
when word-wrapping. Simplify word-wrapping logic. Use correct
pixel positions when saving copies of the iterator.
(display_line): Use proper wrap point if the last character on a
line was preceded by whitespace.
author | Chong Yidong <cyd@stupidchicken.com> |
---|---|
date | Sat, 05 Jul 2008 05:31:12 +0000 |
parents | b91f578d3ace |
children | 1411a65023df |
files | src/xdisp.c |
diffstat | 1 files changed, 106 insertions(+), 66 deletions(-) [+] |
line wrap: on
line diff
--- a/src/xdisp.c Sat Jul 05 05:30:46 2008 +0000 +++ b/src/xdisp.c Sat Jul 05 05:31:12 2008 +0000 @@ -346,10 +346,17 @@ (!NILP (Voverflow_newline_into_fringe) \ && FRAME_WINDOW_P (it->f) \ && WINDOW_RIGHT_FRINGE_WIDTH (it->w) > 0 \ - && it->current_x == it->last_visible_x) + && it->current_x == it->last_visible_x \ + && it->line_wrap != WORD_WRAP) #endif /* HAVE_WINDOW_SYSTEM */ +/* Test if the display element loaded in IT is a space or tab + character. This is used to determine word wrapping. */ + +#define IT_DISPLAYING_WHITESPACE(it) \ + (it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t')) + /* Non-nil means show the text cursor in void text areas i.e. in blank areas after eol and eob. This used to be the default in 21.3. */ @@ -6664,7 +6671,7 @@ { enum move_it_result result = MOVE_UNDEFINED; struct glyph_row *saved_glyph_row; - struct it wrap_it, atpos_it; + struct it wrap_it, atpos_it, atx_it; int may_wrap = 0; /* Don't produce glyphs in produce_glyphs. */ @@ -6672,11 +6679,13 @@ it->glyph_row = NULL; /* Use wrap_it to save a copy of IT wherever a word wrap could - occur. Use atpos_it to save a copy of IT at the desired + occur. Use atpos_it to save a copy of IT at the desired buffer position, if found, so that we can scan ahead and check if the - word later overshoots the window edge. */ + word later overshoots the window edge. Use atx_it similarly, for + pixel positions. */ wrap_it.sp = -1; atpos_it.sp = -1; + atx_it.sp = -1; #define BUFFER_POS_REACHED_P() \ ((op & MOVE_TO_POS) != 0 \ @@ -6689,38 +6698,34 @@ /* If there's a line-/wrap-prefix, handle it. */ if (it->hpos == 0 && it->method == GET_FROM_BUFFER && it->current_y < it->last_visible_y) - { - handle_line_prefix (it); - } + handle_line_prefix (it); while (1) { int x, i, ascent = 0, descent = 0; - /* Stop if we move beyond TO_CHARPOS (after an image or stretch glyph). */ +/* Utility macro to reset an iterator with x, ascent, and descent. */ +#define IT_RESET_X_ASCENT_DESCENT(IT) \ + ((IT)->current_x = x, (IT)->max_ascent = ascent, \ + (IT)->max_descent = descent) + + /* Stop if we move beyond TO_CHARPOS (after an image or stretch + glyph). */ if ((op & MOVE_TO_POS) != 0 && BUFFERP (it->object) && it->method == GET_FROM_BUFFER && IT_CHARPOS (*it) > to_charpos) { - if (it->line_wrap == WORD_WRAP) - { - /* If wrap_it is valid, the current position might be in - a word that is wrapped to the next line, so continue - to see if that happens. */ - if (wrap_it.sp < 0) - { - result = MOVE_POS_MATCH_OR_ZV; - break; - } - if (atpos_it.sp < 0) - atpos_it = *it; - } - else + if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0) { result = MOVE_POS_MATCH_OR_ZV; break; } + else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0) + /* If wrap_it is valid, the current position might be in a + word that is wrapped. So, save the iterator in + atpos_it and continue to see if wrapping happens. */ + atpos_it = *it; } /* Stop when ZV reached. @@ -6743,31 +6748,39 @@ } else { - /* Remember the line height so far in case the next element - doesn't fit on the line. */ - ascent = it->max_ascent; - descent = it->max_descent; - if (it->line_wrap == WORD_WRAP) { - if (it->what == IT_CHARACTER - && (it->c == ' ' || it->c == '\t')) + if (IT_DISPLAYING_WHITESPACE (it)) may_wrap = 1; else if (may_wrap) { - /* We are done if the position is already found. */ + /* We have reached a glyph that follows one or more + whitespace characters. If the position is + already found, we are done. */ if (atpos_it.sp >= 0) { *it = atpos_it; - atpos_it.sp = -1; - goto buffer_pos_reached; + result = MOVE_POS_MATCH_OR_ZV; + goto done; } + if (atx_it.sp >= 0) + { + *it = atx_it; + result = MOVE_X_REACHED; + goto done; + } + /* Otherwise, we can wrap here. */ wrap_it = *it; may_wrap = 0; } } } + /* Remember the line height for the current line, in case + the next element doesn't fit on the line. */ + ascent = it->max_ascent; + descent = it->max_descent; + /* The call to produce_glyphs will get the metrics of the display element IT is loaded with. Record the x-position before this display element, in case it doesn't fit on the @@ -6818,19 +6831,28 @@ { if (BUFFER_POS_REACHED_P ()) { - if (it->line_wrap == WORD_WRAP) + if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0) + goto buffer_pos_reached; + if (atpos_it.sp < 0) { - if (wrap_it.sp < 0) - goto buffer_pos_reached; - if (atpos_it.sp < 0) - atpos_it = *it; + atpos_it = *it; + IT_RESET_X_ASCENT_DESCENT (&atpos_it); } - else - goto buffer_pos_reached; } - it->current_x = x; - result = MOVE_X_REACHED; - break; + else + { + if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0) + { + it->current_x = x; + result = MOVE_X_REACHED; + break; + } + if (atx_it.sp < 0) + { + atx_it = *it; + IT_RESET_X_ASCENT_DESCENT (&atx_it); + } + } } if (/* Lines are continued. */ @@ -6860,10 +6882,21 @@ now that we know it fits in this row. */ if (BUFFER_POS_REACHED_P ()) { - it->hpos = hpos_before_this_char; - it->current_x = x_before_this_char; - result = MOVE_POS_MATCH_OR_ZV; - break; + if (it->line_wrap != WORD_WRAP + || wrap_it.sp < 0) + { + it->hpos = hpos_before_this_char; + it->current_x = x_before_this_char; + result = MOVE_POS_MATCH_OR_ZV; + break; + } + if (it->line_wrap == WORD_WRAP + && atpos_it.sp < 0) + { + atpos_it = *it; + atpos_it.current_x = x_before_this_char; + atpos_it.hpos = hpos_before_this_char; + } } set_iterator_to_next (it, 1); @@ -6893,16 +6926,13 @@ } } else - { - it->current_x = x; - it->max_ascent = ascent; - it->max_descent = descent; - } + IT_RESET_X_ASCENT_DESCENT (it); if (wrap_it.sp >= 0) { *it = wrap_it; atpos_it.sp = -1; + atx_it.sp = -1; } TRACE_MOVE ((stderr, "move_it_in: continued at %d\n", @@ -6913,15 +6943,13 @@ if (BUFFER_POS_REACHED_P ()) { - if (it->line_wrap == WORD_WRAP) + if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0) + goto buffer_pos_reached; + if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0) { - if (wrap_it.sp < 0) - goto buffer_pos_reached; - if (atpos_it.sp < 0) - atpos_it = *it; + atpos_it = *it; + IT_RESET_X_ASCENT_DESCENT (&atpos_it); } - else - goto buffer_pos_reached; } if (new_x > it->first_visible_x) @@ -6938,9 +6966,7 @@ else if (BUFFER_POS_REACHED_P ()) { buffer_pos_reached: - it->current_x = x; - it->max_ascent = ascent; - it->max_descent = descent; + IT_RESET_X_ASCENT_DESCENT (it); result = MOVE_POS_MATCH_OR_ZV; break; } @@ -6990,14 +7016,19 @@ result = MOVE_LINE_TRUNCATED; break; } +#undef IT_RESET_X_ASCENT_DESCENT } #undef BUFFER_POS_REACHED_P /* If we scanned beyond to_pos and didn't find a point to wrap at, - return iterator at to_pos. */ + restore the saved iterator. */ if (atpos_it.sp >= 0) *it = atpos_it; + else if (atx_it.sp >= 0) + *it = atx_it; + + done: /* Restore the iterator settings altered at the beginning of this function. */ @@ -16506,8 +16537,7 @@ if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA) { - if (it->what == IT_CHARACTER - && (it->c == ' ' || it->c == '\t')) + if (IT_DISPLAYING_WHITESPACE (it)) may_wrap = 1; else if (may_wrap) { @@ -16604,6 +16634,18 @@ ++it->hpos; if (i == nglyphs - 1) { + /* If line-wrap is on, check if a previous + wrap point was found. */ + if (wrap_row_used > 0 + /* Even if there is a previous wrap + point, continue the line here as + usual, if (i) the previous character + was a space or tab AND (ii) the + current character is not. */ + && (!may_wrap + || IT_DISPLAYING_WHITESPACE (it))) + goto back_to_wrap; + set_iterator_to_next (it, 1); #ifdef HAVE_WINDOW_SYSTEM if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)) @@ -16622,8 +16664,6 @@ } } #endif /* HAVE_WINDOW_SYSTEM */ - if (wrap_row_used > 0) - goto back_to_wrap; } } else if (CHAR_GLYPH_PADDING_P (*glyph)