diff options
| author | Chong Yidong | 2008-07-05 05:31:12 +0000 |
|---|---|---|
| committer | Chong Yidong | 2008-07-05 05:31:12 +0000 |
| commit | 4636d4bd844e7e2e3f0bb3ca827dcbe3f6ca60bb (patch) | |
| tree | b11e012f7d9e5b2c9f2ffe390f56a71638d4d55d /src | |
| parent | 59230395e9d1545c54bd2e99908c4d78edfdc360 (diff) | |
| download | emacs-4636d4bd844e7e2e3f0bb3ca827dcbe3f6ca60bb.tar.gz emacs-4636d4bd844e7e2e3f0bb3ca827dcbe3f6ca60bb.zip | |
(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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xdisp.c | 172 |
1 files changed, 106 insertions, 66 deletions
diff --git a/src/xdisp.c b/src/xdisp.c index c0f0ca9df1b..28a5c4e0c0a 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -346,10 +346,17 @@ extern Lisp_Object Voverflow_newline_into_fringe; | |||
| 346 | (!NILP (Voverflow_newline_into_fringe) \ | 346 | (!NILP (Voverflow_newline_into_fringe) \ |
| 347 | && FRAME_WINDOW_P (it->f) \ | 347 | && FRAME_WINDOW_P (it->f) \ |
| 348 | && WINDOW_RIGHT_FRINGE_WIDTH (it->w) > 0 \ | 348 | && WINDOW_RIGHT_FRINGE_WIDTH (it->w) > 0 \ |
| 349 | && it->current_x == it->last_visible_x) | 349 | && it->current_x == it->last_visible_x \ |
| 350 | && it->line_wrap != WORD_WRAP) | ||
| 350 | 351 | ||
| 351 | #endif /* HAVE_WINDOW_SYSTEM */ | 352 | #endif /* HAVE_WINDOW_SYSTEM */ |
| 352 | 353 | ||
| 354 | /* Test if the display element loaded in IT is a space or tab | ||
| 355 | character. This is used to determine word wrapping. */ | ||
| 356 | |||
| 357 | #define IT_DISPLAYING_WHITESPACE(it) \ | ||
| 358 | (it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t')) | ||
| 359 | |||
| 353 | /* Non-nil means show the text cursor in void text areas | 360 | /* Non-nil means show the text cursor in void text areas |
| 354 | i.e. in blank areas after eol and eob. This used to be | 361 | i.e. in blank areas after eol and eob. This used to be |
| 355 | the default in 21.3. */ | 362 | the default in 21.3. */ |
| @@ -6664,7 +6671,7 @@ move_it_in_display_line_to (struct it *it, | |||
| 6664 | { | 6671 | { |
| 6665 | enum move_it_result result = MOVE_UNDEFINED; | 6672 | enum move_it_result result = MOVE_UNDEFINED; |
| 6666 | struct glyph_row *saved_glyph_row; | 6673 | struct glyph_row *saved_glyph_row; |
| 6667 | struct it wrap_it, atpos_it; | 6674 | struct it wrap_it, atpos_it, atx_it; |
| 6668 | int may_wrap = 0; | 6675 | int may_wrap = 0; |
| 6669 | 6676 | ||
| 6670 | /* Don't produce glyphs in produce_glyphs. */ | 6677 | /* Don't produce glyphs in produce_glyphs. */ |
| @@ -6672,11 +6679,13 @@ move_it_in_display_line_to (struct it *it, | |||
| 6672 | it->glyph_row = NULL; | 6679 | it->glyph_row = NULL; |
| 6673 | 6680 | ||
| 6674 | /* Use wrap_it to save a copy of IT wherever a word wrap could | 6681 | /* Use wrap_it to save a copy of IT wherever a word wrap could |
| 6675 | occur. Use atpos_it to save a copy of IT at the desired | 6682 | occur. Use atpos_it to save a copy of IT at the desired buffer |
| 6676 | position, if found, so that we can scan ahead and check if the | 6683 | position, if found, so that we can scan ahead and check if the |
| 6677 | word later overshoots the window edge. */ | 6684 | word later overshoots the window edge. Use atx_it similarly, for |
| 6685 | pixel positions. */ | ||
| 6678 | wrap_it.sp = -1; | 6686 | wrap_it.sp = -1; |
| 6679 | atpos_it.sp = -1; | 6687 | atpos_it.sp = -1; |
| 6688 | atx_it.sp = -1; | ||
| 6680 | 6689 | ||
| 6681 | #define BUFFER_POS_REACHED_P() \ | 6690 | #define BUFFER_POS_REACHED_P() \ |
| 6682 | ((op & MOVE_TO_POS) != 0 \ | 6691 | ((op & MOVE_TO_POS) != 0 \ |
| @@ -6689,38 +6698,34 @@ move_it_in_display_line_to (struct it *it, | |||
| 6689 | /* If there's a line-/wrap-prefix, handle it. */ | 6698 | /* If there's a line-/wrap-prefix, handle it. */ |
| 6690 | if (it->hpos == 0 && it->method == GET_FROM_BUFFER | 6699 | if (it->hpos == 0 && it->method == GET_FROM_BUFFER |
| 6691 | && it->current_y < it->last_visible_y) | 6700 | && it->current_y < it->last_visible_y) |
| 6692 | { | 6701 | handle_line_prefix (it); |
| 6693 | handle_line_prefix (it); | ||
| 6694 | } | ||
| 6695 | 6702 | ||
| 6696 | while (1) | 6703 | while (1) |
| 6697 | { | 6704 | { |
| 6698 | int x, i, ascent = 0, descent = 0; | 6705 | int x, i, ascent = 0, descent = 0; |
| 6699 | 6706 | ||
| 6700 | /* Stop if we move beyond TO_CHARPOS (after an image or stretch glyph). */ | 6707 | /* Utility macro to reset an iterator with x, ascent, and descent. */ |
| 6708 | #define IT_RESET_X_ASCENT_DESCENT(IT) \ | ||
| 6709 | ((IT)->current_x = x, (IT)->max_ascent = ascent, \ | ||
| 6710 | (IT)->max_descent = descent) | ||
| 6711 | |||
| 6712 | /* Stop if we move beyond TO_CHARPOS (after an image or stretch | ||
| 6713 | glyph). */ | ||
| 6701 | if ((op & MOVE_TO_POS) != 0 | 6714 | if ((op & MOVE_TO_POS) != 0 |
| 6702 | && BUFFERP (it->object) | 6715 | && BUFFERP (it->object) |
| 6703 | && it->method == GET_FROM_BUFFER | 6716 | && it->method == GET_FROM_BUFFER |
| 6704 | && IT_CHARPOS (*it) > to_charpos) | 6717 | && IT_CHARPOS (*it) > to_charpos) |
| 6705 | { | 6718 | { |
| 6706 | if (it->line_wrap == WORD_WRAP) | 6719 | if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0) |
| 6707 | { | ||
| 6708 | /* If wrap_it is valid, the current position might be in | ||
| 6709 | a word that is wrapped to the next line, so continue | ||
| 6710 | to see if that happens. */ | ||
| 6711 | if (wrap_it.sp < 0) | ||
| 6712 | { | ||
| 6713 | result = MOVE_POS_MATCH_OR_ZV; | ||
| 6714 | break; | ||
| 6715 | } | ||
| 6716 | if (atpos_it.sp < 0) | ||
| 6717 | atpos_it = *it; | ||
| 6718 | } | ||
| 6719 | else | ||
| 6720 | { | 6720 | { |
| 6721 | result = MOVE_POS_MATCH_OR_ZV; | 6721 | result = MOVE_POS_MATCH_OR_ZV; |
| 6722 | break; | 6722 | break; |
| 6723 | } | 6723 | } |
| 6724 | else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0) | ||
| 6725 | /* If wrap_it is valid, the current position might be in a | ||
| 6726 | word that is wrapped. So, save the iterator in | ||
| 6727 | atpos_it and continue to see if wrapping happens. */ | ||
| 6728 | atpos_it = *it; | ||
| 6724 | } | 6729 | } |
| 6725 | 6730 | ||
| 6726 | /* Stop when ZV reached. | 6731 | /* Stop when ZV reached. |
| @@ -6743,31 +6748,39 @@ move_it_in_display_line_to (struct it *it, | |||
| 6743 | } | 6748 | } |
| 6744 | else | 6749 | else |
| 6745 | { | 6750 | { |
| 6746 | /* Remember the line height so far in case the next element | ||
| 6747 | doesn't fit on the line. */ | ||
| 6748 | ascent = it->max_ascent; | ||
| 6749 | descent = it->max_descent; | ||
| 6750 | |||
| 6751 | if (it->line_wrap == WORD_WRAP) | 6751 | if (it->line_wrap == WORD_WRAP) |
| 6752 | { | 6752 | { |
| 6753 | if (it->what == IT_CHARACTER | 6753 | if (IT_DISPLAYING_WHITESPACE (it)) |
| 6754 | && (it->c == ' ' || it->c == '\t')) | ||
| 6755 | may_wrap = 1; | 6754 | may_wrap = 1; |
| 6756 | else if (may_wrap) | 6755 | else if (may_wrap) |
| 6757 | { | 6756 | { |
| 6758 | /* We are done if the position is already found. */ | 6757 | /* We have reached a glyph that follows one or more |
| 6758 | whitespace characters. If the position is | ||
| 6759 | already found, we are done. */ | ||
| 6759 | if (atpos_it.sp >= 0) | 6760 | if (atpos_it.sp >= 0) |
| 6760 | { | 6761 | { |
| 6761 | *it = atpos_it; | 6762 | *it = atpos_it; |
| 6762 | atpos_it.sp = -1; | 6763 | result = MOVE_POS_MATCH_OR_ZV; |
| 6763 | goto buffer_pos_reached; | 6764 | goto done; |
| 6764 | } | 6765 | } |
| 6766 | if (atx_it.sp >= 0) | ||
| 6767 | { | ||
| 6768 | *it = atx_it; | ||
| 6769 | result = MOVE_X_REACHED; | ||
| 6770 | goto done; | ||
| 6771 | } | ||
| 6772 | /* Otherwise, we can wrap here. */ | ||
| 6765 | wrap_it = *it; | 6773 | wrap_it = *it; |
| 6766 | may_wrap = 0; | 6774 | may_wrap = 0; |
| 6767 | } | 6775 | } |
| 6768 | } | 6776 | } |
| 6769 | } | 6777 | } |
| 6770 | 6778 | ||
| 6779 | /* Remember the line height for the current line, in case | ||
| 6780 | the next element doesn't fit on the line. */ | ||
| 6781 | ascent = it->max_ascent; | ||
| 6782 | descent = it->max_descent; | ||
| 6783 | |||
| 6771 | /* The call to produce_glyphs will get the metrics of the | 6784 | /* The call to produce_glyphs will get the metrics of the |
| 6772 | display element IT is loaded with. Record the x-position | 6785 | display element IT is loaded with. Record the x-position |
| 6773 | before this display element, in case it doesn't fit on the | 6786 | before this display element, in case it doesn't fit on the |
| @@ -6818,19 +6831,28 @@ move_it_in_display_line_to (struct it *it, | |||
| 6818 | { | 6831 | { |
| 6819 | if (BUFFER_POS_REACHED_P ()) | 6832 | if (BUFFER_POS_REACHED_P ()) |
| 6820 | { | 6833 | { |
| 6821 | if (it->line_wrap == WORD_WRAP) | 6834 | if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0) |
| 6835 | goto buffer_pos_reached; | ||
| 6836 | if (atpos_it.sp < 0) | ||
| 6822 | { | 6837 | { |
| 6823 | if (wrap_it.sp < 0) | 6838 | atpos_it = *it; |
| 6824 | goto buffer_pos_reached; | 6839 | IT_RESET_X_ASCENT_DESCENT (&atpos_it); |
| 6825 | if (atpos_it.sp < 0) | 6840 | } |
| 6826 | atpos_it = *it; | 6841 | } |
| 6842 | else | ||
| 6843 | { | ||
| 6844 | if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0) | ||
| 6845 | { | ||
| 6846 | it->current_x = x; | ||
| 6847 | result = MOVE_X_REACHED; | ||
| 6848 | break; | ||
| 6849 | } | ||
| 6850 | if (atx_it.sp < 0) | ||
| 6851 | { | ||
| 6852 | atx_it = *it; | ||
| 6853 | IT_RESET_X_ASCENT_DESCENT (&atx_it); | ||
| 6827 | } | 6854 | } |
| 6828 | else | ||
| 6829 | goto buffer_pos_reached; | ||
| 6830 | } | 6855 | } |
| 6831 | it->current_x = x; | ||
| 6832 | result = MOVE_X_REACHED; | ||
| 6833 | break; | ||
| 6834 | } | 6856 | } |
| 6835 | 6857 | ||
| 6836 | if (/* Lines are continued. */ | 6858 | if (/* Lines are continued. */ |
| @@ -6860,10 +6882,21 @@ move_it_in_display_line_to (struct it *it, | |||
| 6860 | now that we know it fits in this row. */ | 6882 | now that we know it fits in this row. */ |
| 6861 | if (BUFFER_POS_REACHED_P ()) | 6883 | if (BUFFER_POS_REACHED_P ()) |
| 6862 | { | 6884 | { |
| 6863 | it->hpos = hpos_before_this_char; | 6885 | if (it->line_wrap != WORD_WRAP |
| 6864 | it->current_x = x_before_this_char; | 6886 | || wrap_it.sp < 0) |
| 6865 | result = MOVE_POS_MATCH_OR_ZV; | 6887 | { |
| 6866 | break; | 6888 | it->hpos = hpos_before_this_char; |
| 6889 | it->current_x = x_before_this_char; | ||
| 6890 | result = MOVE_POS_MATCH_OR_ZV; | ||
| 6891 | break; | ||
| 6892 | } | ||
| 6893 | if (it->line_wrap == WORD_WRAP | ||
| 6894 | && atpos_it.sp < 0) | ||
| 6895 | { | ||
| 6896 | atpos_it = *it; | ||
| 6897 | atpos_it.current_x = x_before_this_char; | ||
| 6898 | atpos_it.hpos = hpos_before_this_char; | ||
| 6899 | } | ||
| 6867 | } | 6900 | } |
| 6868 | 6901 | ||
| 6869 | set_iterator_to_next (it, 1); | 6902 | set_iterator_to_next (it, 1); |
| @@ -6893,16 +6926,13 @@ move_it_in_display_line_to (struct it *it, | |||
| 6893 | } | 6926 | } |
| 6894 | } | 6927 | } |
| 6895 | else | 6928 | else |
| 6896 | { | 6929 | IT_RESET_X_ASCENT_DESCENT (it); |
| 6897 | it->current_x = x; | ||
| 6898 | it->max_ascent = ascent; | ||
| 6899 | it->max_descent = descent; | ||
| 6900 | } | ||
| 6901 | 6930 | ||
| 6902 | if (wrap_it.sp >= 0) | 6931 | if (wrap_it.sp >= 0) |
| 6903 | { | 6932 | { |
| 6904 | *it = wrap_it; | 6933 | *it = wrap_it; |
| 6905 | atpos_it.sp = -1; | 6934 | atpos_it.sp = -1; |
| 6935 | atx_it.sp = -1; | ||
| 6906 | } | 6936 | } |
| 6907 | 6937 | ||
| 6908 | TRACE_MOVE ((stderr, "move_it_in: continued at %d\n", | 6938 | TRACE_MOVE ((stderr, "move_it_in: continued at %d\n", |
| @@ -6913,15 +6943,13 @@ move_it_in_display_line_to (struct it *it, | |||
| 6913 | 6943 | ||
| 6914 | if (BUFFER_POS_REACHED_P ()) | 6944 | if (BUFFER_POS_REACHED_P ()) |
| 6915 | { | 6945 | { |
| 6916 | if (it->line_wrap == WORD_WRAP) | 6946 | if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0) |
| 6947 | goto buffer_pos_reached; | ||
| 6948 | if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0) | ||
| 6917 | { | 6949 | { |
| 6918 | if (wrap_it.sp < 0) | 6950 | atpos_it = *it; |
| 6919 | goto buffer_pos_reached; | 6951 | IT_RESET_X_ASCENT_DESCENT (&atpos_it); |
| 6920 | if (atpos_it.sp < 0) | ||
| 6921 | atpos_it = *it; | ||
| 6922 | } | 6952 | } |
| 6923 | else | ||
| 6924 | goto buffer_pos_reached; | ||
| 6925 | } | 6953 | } |
| 6926 | 6954 | ||
| 6927 | if (new_x > it->first_visible_x) | 6955 | if (new_x > it->first_visible_x) |
| @@ -6938,9 +6966,7 @@ move_it_in_display_line_to (struct it *it, | |||
| 6938 | else if (BUFFER_POS_REACHED_P ()) | 6966 | else if (BUFFER_POS_REACHED_P ()) |
| 6939 | { | 6967 | { |
| 6940 | buffer_pos_reached: | 6968 | buffer_pos_reached: |
| 6941 | it->current_x = x; | 6969 | IT_RESET_X_ASCENT_DESCENT (it); |
| 6942 | it->max_ascent = ascent; | ||
| 6943 | it->max_descent = descent; | ||
| 6944 | result = MOVE_POS_MATCH_OR_ZV; | 6970 | result = MOVE_POS_MATCH_OR_ZV; |
| 6945 | break; | 6971 | break; |
| 6946 | } | 6972 | } |
| @@ -6990,14 +7016,19 @@ move_it_in_display_line_to (struct it *it, | |||
| 6990 | result = MOVE_LINE_TRUNCATED; | 7016 | result = MOVE_LINE_TRUNCATED; |
| 6991 | break; | 7017 | break; |
| 6992 | } | 7018 | } |
| 7019 | #undef IT_RESET_X_ASCENT_DESCENT | ||
| 6993 | } | 7020 | } |
| 6994 | 7021 | ||
| 6995 | #undef BUFFER_POS_REACHED_P | 7022 | #undef BUFFER_POS_REACHED_P |
| 6996 | 7023 | ||
| 6997 | /* If we scanned beyond to_pos and didn't find a point to wrap at, | 7024 | /* If we scanned beyond to_pos and didn't find a point to wrap at, |
| 6998 | return iterator at to_pos. */ | 7025 | restore the saved iterator. */ |
| 6999 | if (atpos_it.sp >= 0) | 7026 | if (atpos_it.sp >= 0) |
| 7000 | *it = atpos_it; | 7027 | *it = atpos_it; |
| 7028 | else if (atx_it.sp >= 0) | ||
| 7029 | *it = atx_it; | ||
| 7030 | |||
| 7031 | done: | ||
| 7001 | 7032 | ||
| 7002 | /* Restore the iterator settings altered at the beginning of this | 7033 | /* Restore the iterator settings altered at the beginning of this |
| 7003 | function. */ | 7034 | function. */ |
| @@ -16506,8 +16537,7 @@ display_line (it) | |||
| 16506 | 16537 | ||
| 16507 | if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA) | 16538 | if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA) |
| 16508 | { | 16539 | { |
| 16509 | if (it->what == IT_CHARACTER | 16540 | if (IT_DISPLAYING_WHITESPACE (it)) |
| 16510 | && (it->c == ' ' || it->c == '\t')) | ||
| 16511 | may_wrap = 1; | 16541 | may_wrap = 1; |
| 16512 | else if (may_wrap) | 16542 | else if (may_wrap) |
| 16513 | { | 16543 | { |
| @@ -16604,6 +16634,18 @@ display_line (it) | |||
| 16604 | ++it->hpos; | 16634 | ++it->hpos; |
| 16605 | if (i == nglyphs - 1) | 16635 | if (i == nglyphs - 1) |
| 16606 | { | 16636 | { |
| 16637 | /* If line-wrap is on, check if a previous | ||
| 16638 | wrap point was found. */ | ||
| 16639 | if (wrap_row_used > 0 | ||
| 16640 | /* Even if there is a previous wrap | ||
| 16641 | point, continue the line here as | ||
| 16642 | usual, if (i) the previous character | ||
| 16643 | was a space or tab AND (ii) the | ||
| 16644 | current character is not. */ | ||
| 16645 | && (!may_wrap | ||
| 16646 | || IT_DISPLAYING_WHITESPACE (it))) | ||
| 16647 | goto back_to_wrap; | ||
| 16648 | |||
| 16607 | set_iterator_to_next (it, 1); | 16649 | set_iterator_to_next (it, 1); |
| 16608 | #ifdef HAVE_WINDOW_SYSTEM | 16650 | #ifdef HAVE_WINDOW_SYSTEM |
| 16609 | if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)) | 16651 | if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)) |
| @@ -16622,8 +16664,6 @@ display_line (it) | |||
| 16622 | } | 16664 | } |
| 16623 | } | 16665 | } |
| 16624 | #endif /* HAVE_WINDOW_SYSTEM */ | 16666 | #endif /* HAVE_WINDOW_SYSTEM */ |
| 16625 | if (wrap_row_used > 0) | ||
| 16626 | goto back_to_wrap; | ||
| 16627 | } | 16667 | } |
| 16628 | } | 16668 | } |
| 16629 | else if (CHAR_GLYPH_PADDING_P (*glyph) | 16669 | else if (CHAR_GLYPH_PADDING_P (*glyph) |