Skip to content

Commit

Permalink
Fix loop when wrapping line with ISO8859-1 character
Browse files Browse the repository at this point in the history
  • Loading branch information
koutcher committed Feb 23, 2021
1 parent 9fb0a2f commit 09f8877
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 5 deletions.
3 changes: 3 additions & 0 deletions include/tig/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ 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);
Expand Down Expand Up @@ -125,5 +126,7 @@ int utf8_width_of(const char *text, int max_bytes, int max_width);

bool utf8_string_contains_uppercase(const char *text);

bool utf8_is_valid(const char *string);

#endif
/* vim: set ts=8 sw=8 noexpandtab: */
7 changes: 6 additions & 1 deletion src/pager.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,14 @@ pager_wrap_line(struct view *view, const char *data, enum line_type type)
int width;
int trimmed;
bool wrapped = !!first_line;
size_t linelen = utf8_length(&data, datalen, 0, &width, view->width, &trimmed, wrapped, opt_tab_size);
size_t linelen;
struct line *line;

if (utf8_is_valid(data))
linelen = utf8_length(&data, datalen, 0, &width, view->width, &trimmed, wrapped, opt_tab_size);
else
linelen = string_expanded_length(data, datalen, opt_tab_size, view->width - !!wrapped);

line = add_line_text_at_(view, view->lines, data, linelen, type, 1, wrapped);
if (!line)
break;
Expand Down
38 changes: 34 additions & 4 deletions src/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,24 @@ string_copy_rev_from_commit_line(char *dst, const char *src)
string_copy_rev(dst, src);
}

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)
{
Expand Down Expand Up @@ -311,10 +329,6 @@ utf8_length(const char **start, int max_chars, size_t skip, int *width, size_t m
* it is a single- or double-width character. */

unicode = utf8_to_unicode(string, bytes);
/* FIXME: Graceful handling of invalid Unicode character. */
if (!unicode)
break;

ucwidth = unicode == '\t' ? tab_size - (*width % tab_size) :
utf8proc_charwidth((utf8proc_int32_t) unicode);
if (skip > 0) {
Expand Down Expand Up @@ -385,4 +399,20 @@ utf8_string_contains_uppercase(const char *search)
return utf8_string_contains(search, UTF8PROC_CATEGORY_LU);
}

bool
utf8_is_valid(const char *string)
{
for (;;) {
int32_t unicode;
ssize_t slen = utf8proc_iterate((const unsigned char *) string, -1, &unicode);

if (slen <= 0 || !utf8proc_codepoint_valid(unicode))
break;
if (unicode == 0)
return true;
string += slen;
}
return false;
}

/* vim: set ts=8 sw=8 noexpandtab: */

0 comments on commit 09f8877

Please sign in to comment.