Skip to content

Instantly share code, notes, and snippets.

@andlabs
Created December 3, 2016 20:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andlabs/e5990d4f7e0b8e6071df49b5a951bff3 to your computer and use it in GitHub Desktop.
Save andlabs/e5990d4f7e0b8e6071df49b5a951bff3 to your computer and use it in GitHub Desktop.
// 3 december 2016
#include "../ui.h"
#include "uipriv.h"
struct uiAttributedString {
char *s;
size_t len;
// TODO attributes
// indiscriminately keep a UTF-16 copy of the string on all platforms so we can hand this off to the grapheme calculator
// this ensures no one platform has a speed advantage (sorry GTK+)
uint16_t *u16;
size_t u16len;
size_t *u8tou16;
size_t *u16tou8;
// TODO grapheme sequences?
};
static void resize(uiAttributedString *s, size_t u8, size_t u16)
{
s->len = u8;
s->s = (char *) uiRealloc(s->s, (s->len + 1) * sizeof (char), "char[] (uiAttributedString)");
s->u8tou16 = (size_t *) uiRealloc(s->u8tou16, (s->len + 1) * sizeof (size_t), "size_t[] (uiAttributedString)");
s->u16len = u16;
s->u16 = (uint16_t *) uiRealloc(s->u16, (s->u16len + 1) * sizeof (uint16_t), "uint16_t[] (uiAttributedString)");
s->u16tou8 = (size_t *) uiRealloc(s->u16tou8, (s->u16len + 1) * sizeof (size_t), "size_t[] (uiAttributedString)");
}
uiAttributedString *uiNewAttributedString(const char *initialString)
{
uiAttributedString *s;
s = uiNew(uiAttributedString);
uiAttributedStringAppendUnattributed(s, initialString);
return s;
}
void uiFreeAttributedString(uiAttributedString *s)
{
uiFree(s->u16tou8);
uiFree(s->u8tou16);
uiFree(s->u16);
uiFree(s->s);
uiFree(s);
}
const char *uiAttributedStringString(uiAttributedString *s)
{
return s->s;
}
void uiAttributedStringAppendUnattributed(uiAttributedString *s, const char *str)
{
const char *t;
uint32_t rune;
char buf[4];
uint16_t u16buf[2];
size_t n, n16;
size_t old, old;
// first figure out how much we need to grow by
// this includes post-validated UTF-8
t = str;
n = 0;
n16 = 0;
while (*t) {
t = utf8DecodeRune(t, 0, &rune);
n += utf8EncodeRune(rune, buf);
n16 += utf16EncodeRune(rune, buf16);
}
// and resize
old = s->len;
old16 = s->len16;
resize(s, s->len + n, s->u16len + n16);
// and copy
while (*str) {
str = utf8DecodeRune(str, 0, &rune);
n = utf8EncodeRune(rune, buf);
n16 = utf16EncodeRune(rune, buf16);
s->s[old] = buf[0];
s->u8tou16[old] = old16;
if (n > 1) {
s->s[old + 1] = buf[1];
s->u8tou16[old + 1] = old16;
}
if (n > 2) {
s->s[old + 2] = buf[2];
s->u8tou16[old + 2] = old16;
}
if (n > 3) {
s->s[old + 3] = buf[3];
s->u8tou16[old + 3] = old16;
}
s->u16[old16] = buf16[0];
s->u16tou8[old16] = old;
if (n16 > 1) {
s->u16[old16 + 1] = buf16[1];
s->u16tou8[old16 + 1] = old;
}
old += n;
old16 += n16;
}
// TODO invalidate the grapheme conversion?
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment