7 bool text_range_valid(const Filerange
*r
) {
8 return r
->start
!= EPOS
&& r
->end
!= EPOS
&& r
->start
<= r
->end
;
11 size_t text_range_size(const Filerange
*r
) {
12 return text_range_valid(r
) ? r
->end
- r
->start
: 0;
15 Filerange
text_range_empty(void) {
16 return (Filerange
){ .start
= EPOS
, .end
= EPOS
};
19 Filerange
text_range_union(const Filerange
*r1
, const Filerange
*r2
) {
20 if (!text_range_valid(r1
))
22 if (!text_range_valid(r2
))
25 .start
= MIN(r1
->start
, r2
->start
),
26 .end
= MAX(r1
->end
, r2
->end
),
30 Filerange
text_range_intersect(const Filerange
*r1
, const Filerange
*r2
) {
31 if (!text_range_overlap(r1
, r2
))
32 return text_range_empty();
33 return text_range_new(MAX(r1
->start
, r2
->start
), MIN(r1
->end
, r2
->end
));
36 Filerange
text_range_new(size_t a
, size_t b
) {
43 bool text_range_equal(const Filerange
*r1
, const Filerange
*r2
) {
44 if (!text_range_valid(r1
) && !text_range_valid(r2
))
46 return r1
->start
== r2
->start
&& r1
->end
== r2
->end
;
49 bool text_range_overlap(const Filerange
*r1
, const Filerange
*r2
) {
50 if (!text_range_valid(r1
) || !text_range_valid(r2
))
52 return r1
->start
< r2
->end
&& r2
->start
< r1
->end
;
55 bool text_range_contains(const Filerange
*r
, size_t pos
) {
56 return text_range_valid(r
) && r
->start
<= pos
&& pos
<= r
->end
;
59 int text_char_count(const char *data
, size_t len
) {
64 size_t wclen
= mbrtowc(&wc
, data
, len
, &ps
);
65 if (wclen
== (size_t)-1 && errno
== EILSEQ
) {
67 while (!ISUTF8(*data
))
69 } else if (wclen
== (size_t)-2) {
71 } else if (wclen
== 0) {
76 int width
= wcwidth(wc
);
86 int text_string_width(const char *data
, size_t len
) {
94 size_t wclen
= mbrtowc(&wc
, s
, len
, &ps
);
95 if (wclen
== (size_t)-1 && errno
== EILSEQ
) {
96 /* assume a replacement symbol will be displayed */
99 } else if (wclen
== (size_t)-2) {
100 /* do nothing, advance to next character */
102 } else if (wclen
== 0) {
103 /* assume NUL byte will be displayed as ^@ */
106 } else if (wc
== L
'\t') {
112 w
= 2; /* assume non-printable will be displayed as ^{char} */