Skip to content

Commit

Permalink
vis: improve replacement of combining characters
Browse files Browse the repository at this point in the history
  • Loading branch information
martanne committed Nov 23, 2015
1 parent 0613073 commit c158469
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 6 deletions.
29 changes: 29 additions & 0 deletions text-util.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "text-util.h"
#include "util.h"
#include <wchar.h>
#include <errno.h>

bool text_range_valid(Filerange *r) {
return r->start != EPOS && r->end != EPOS && r->start <= r->end;
Expand Down Expand Up @@ -46,3 +48,30 @@ bool text_range_overlap(Filerange *r1, Filerange *r2) {
bool text_range_contains(Filerange *r, size_t pos) {
return text_range_valid(r) && r->start <= pos && pos <= r->end;
}

int text_char_count(const char *data, size_t len) {
int count = 0;
mbstate_t ps = { 0 };
while (len > 0) {
wchar_t wc;
size_t wclen = mbrtowc(&wc, data, len, &ps);
if (wclen == (size_t)-1 && errno == EILSEQ) {
count++;
while (!ISUTF8(*data))
data++, len--;
} else if (wclen == (size_t)-2) {
break;
} else if (wclen == 0) {
count++;
data++;
len--;
} else {
int width = wcwidth(wc);
if (width != 0)
count++;
data += wclen;
len -= wclen;
}
}
return count;
}
2 changes: 2 additions & 0 deletions text-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,7 @@ bool text_range_equal(Filerange*, Filerange*);
bool text_range_overlap(Filerange*, Filerange*);
/* test whether a given position is within a certain range */
bool text_range_contains(Filerange*, size_t pos);
/* count the number of graphemes in data */
int text_char_count(const char *data, size_t len);

#endif
7 changes: 1 addition & 6 deletions vis.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,14 +435,9 @@ void vis_insert_key(Vis *vis, const char *data, size_t len) {
}

void vis_replace(Vis *vis, size_t pos, const char *data, size_t len) {
size_t chars = 0;
for (size_t i = 0; i < len; i++) {
if (ISUTF8(data[i]))
chars++;
}

Text *txt = vis->win->file->text;
Iterator it = text_iterator_get(txt, pos);
int chars = text_char_count(data, len);
for (char c; chars-- > 0 && text_iterator_byte_get(&it, &c) && c != '\r' && c != '\n'; )
text_iterator_char_next(&it, NULL);

Expand Down

0 comments on commit c158469

Please sign in to comment.