From 484aa21a6f9ec6090a78b111eb429f9d922e25b9 Mon Sep 17 00:00:00 2001 From: Thomas Koutcher Date: Sun, 12 Apr 2020 10:49:15 +0200 Subject: [PATCH] Fix wrapping of lines with multibyte characters Fixes #988 --- NEWS.adoc | 7 ++++ include/tig/string.h | 1 - src/pager.c | 4 ++- src/string.c | 21 ++---------- test/blob/wrap-lines-test | 67 +++++++++++++++++++++------------------ 5 files changed, 49 insertions(+), 51 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index b75e16a13..7dbea85eb 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -1,6 +1,13 @@ Release notes ============= +master +------ + +Bug fixes: + + - Fix wrapping of lines with multibyte characters. (#988) + tig-2.5.1 --------- diff --git a/include/tig/string.h b/include/tig/string.h index 7a2449988..290d313db 100644 --- a/include/tig/string.h +++ b/include/tig/string.h @@ -84,7 +84,6 @@ void string_copy_rev_from_commit_line(char *dst, const char *src); #define string_concat_path(dst, path1, path2) \ string_format(dst, !*path1 || path1[strlen(path1) - 1] == '/' ? "%s%s" : "%s/%s", path1, path2) -size_t string_expanded_length(const char *src, size_t srclen, size_t tabsize, size_t max_size); size_t string_expand(char *dst, size_t dstlen, const char *src, int srclen, int tabsize); char *string_trim_end(char *name); diff --git a/src/pager.c b/src/pager.c index 94ea70fb0..9386292e6 100644 --- a/src/pager.c +++ b/src/pager.c @@ -73,8 +73,10 @@ pager_wrap_line(struct view *view, const char *data, enum line_type type) size_t lineno = 0; while (datalen > 0 || !has_first_line) { + int width; + int trimmed; bool wrapped = !!first_line; - size_t linelen = string_expanded_length(data, datalen, opt_tab_size, view->width - !!wrapped); + size_t linelen = utf8_length(&data, datalen, 0, &width, view->width, &trimmed, wrapped, opt_tab_size); struct line *line; line = add_line_text_at_(view, view->lines, data, linelen, type, 1, wrapped); diff --git a/src/string.c b/src/string.c index 57f49cd00..7296508f7 100644 --- a/src/string.c +++ b/src/string.c @@ -85,24 +85,6 @@ string_copy_rev_from_commit_line(char *dst, const char *src) string_copy_rev(dst, src + STRING_SIZE("commit ")); } -size_t -string_expanded_length(const char *src, size_t srclen, size_t tabsize, size_t max_size) -{ - size_t size, pos; - - for (size = pos = 0; pos < srclen && size < max_size; pos++) { - if (src[pos] == '\t') { - size_t expanded = tabsize - (size % tabsize); - - size += expanded; - } else { - size++; - } - } - - return pos; -} - size_t string_expand(char *dst, size_t dstlen, const char *src, int srclen, int tabsize) { @@ -330,7 +312,8 @@ utf8_length(const char **start, int max_chars, size_t skip, int *width, size_t m if (!unicode) break; - ucwidth = unicode_width(unicode, tab_size); + ucwidth = unicode == '\t' ? tab_size - (*width % tab_size) : + utf8proc_charwidth((utf8proc_int32_t) unicode); if (skip > 0) { skip -= ucwidth <= skip ? ucwidth : skip; *start += bytes; diff --git a/test/blob/wrap-lines-test b/test/blob/wrap-lines-test index d6414ee83..9ee7a795d 100755 --- a/test/blob/wrap-lines-test +++ b/test/blob/wrap-lines-test @@ -17,38 +17,45 @@ set line-graphics = utf-8 set wrap-lines = true EOF -in_work_dir create_repo_from_tgz "$base_dir/files/scala-js-benchmarks.tgz" +git_init + +test_setup_work_dir() +{ + printf 'Как пуст, и вял, и ничтожен почти всякий прожитой день! Как мало следов оставляет он за собою! Как бессмысленно глупо пробежали эти часы за часами!\tИван Сергеевич Тургенев\n' >README.md + git add README.md + git_commit -m "tomorrow" +} test_tig assert_equals 'wrapped.screen' <