109 lines
2.6 KiB
C
Executable File
109 lines
2.6 KiB
C
Executable File
#include "tim.h"
|
|
|
|
i32 tim_ztrlen(cstr s) {
|
|
if(s == NULL)
|
|
return 0;
|
|
i32 n = strlen(s);
|
|
if(n < 0)
|
|
n = 0;
|
|
return n;
|
|
}
|
|
|
|
i32 tim_bsr8(u8 x) {
|
|
#if defined __GNUC__ || defined __clang__
|
|
unsigned int b = x;
|
|
b <<= sizeof(b) * CHAR_BIT - 8;
|
|
b |= 1 << (sizeof(b) * CHAR_BIT - 9);
|
|
return __builtin_clz(b);
|
|
#elif defined _MSC_VER
|
|
unsigned long n = 0;
|
|
unsigned long b = x;
|
|
b <<= sizeof(b) * CHAR_BIT - 8;
|
|
b |= 1 << (sizeof(b) * CHAR_BIT - 9);
|
|
_BitScanReverse(&n, b);
|
|
return n;
|
|
#else
|
|
i32 n = 0;
|
|
for (; n < 8 && !(x & 128); n++, x <<= 1) {}
|
|
return n;
|
|
#endif
|
|
}
|
|
|
|
|
|
i32 tim_utf8_to_i32(cstr s) {
|
|
s = s ? s : "";
|
|
// use bit magic to mask out leading utf8 1s
|
|
u32 c = s[0] & ((1 << (8 - tim_bsr8(~s[0]))) - 1);
|
|
for (i32 i = 1; s[0] && s[i] && i < 4; i++) {
|
|
c = (c << 6) | (s[i] & 63);
|
|
}
|
|
return (i32)c;
|
|
}
|
|
|
|
i32 tim_utf8_len(cstr s) {
|
|
i32 n = 0;
|
|
for (i32 i = 0; s && s[i]; i++) {
|
|
n += (s[i] & 192) != 128;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
i32 tim_utf8_pos(cstr s, i32 pos) {
|
|
i32 i = 0;
|
|
for (i32 n = 0; pos >= 0 && s && s[i]; i++) {
|
|
n += (s[i] & 192) != 128;
|
|
if (n == pos + 1) {
|
|
return i;
|
|
}
|
|
}
|
|
return i;
|
|
}
|
|
|
|
bool tim_utf8_is_wide_perhaps(const u8* s, i32 n) {
|
|
// Character width depends on character, terminal and font. There is no
|
|
// reliable method, however most frequently used characters are narrow.
|
|
// Zero with characters are ignored, and hope that user input is benign.
|
|
if (n < 3 || s[0] < 225) {
|
|
// u+0000 - u+1000, basic latin - tibetan
|
|
return false;
|
|
} else if (s[0] == 226 && s[1] >= 148 && s[1] < 152) {
|
|
// u+2500 - u+2600 box drawing, block elements, geometric shapes
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
TimText tim_scan_str(cstr s) {
|
|
if(s == NULL)
|
|
s = "";
|
|
TimText t = {
|
|
.width = 0,
|
|
.lines = (s[0] != 0),
|
|
};
|
|
i32 width = 0;
|
|
for (t.size = 0; s[t.size]; t.size++) {
|
|
char ch = s[t.size];
|
|
i32 newline = (ch == '\n');
|
|
width = newline ? 0 : width;
|
|
width += (ch & 192) != 128 && (u8)ch > 31;
|
|
t.lines += newline;
|
|
t.width = MAX(t.width, width);
|
|
}
|
|
return t;
|
|
}
|
|
|
|
bool tim_next_line(TimLine* l) {
|
|
if (!l->s || !l->s[0]) {
|
|
return false;
|
|
}
|
|
l->line = l->s;
|
|
l->size = 0;
|
|
l->width = 0;
|
|
for (cstr s = l->s; s[0] && s[0] != '\n'; s++) {
|
|
l->size += 1;
|
|
l->width += (s[0] & 192) != 128 && (u8)s[0] > 31;
|
|
}
|
|
l->s += l->size + !!l->s[l->size];
|
|
return true;
|
|
}
|