// This file is part of the loginx project
//
// Copyright (c) 2013 by Mike Sharov <msharov@users.sourceforge.net>
// This file is free software, distributed under the ISC license.
#include "utf8.h"
// Returns the number of bytes in the character whose first char is c
static unsigned utf8_ibytes (char c)
{
// Count the leading bits. Header bits are 1 * nBytes followed by a 0.
// 0 - single byte character. Take 7 bits (0xff >> 1)
// 1 - error, in the middle of the character. Take 6 bits (0xff >> 2)
// so you will keep reading invalid entries until you hit the next character.
// >2 - multibyte character. Take remaining bits, and get the next bytes.
//
unsigned n = 0u;
for (uint8_t mask = 0x80; c & mask; ++n)
mask >>= 1;
return n+!n; // A sequence is always at least 1 byte.
}
static wchar_t utf8_next (const char** pt)
{
const char* i = *pt;
unsigned n = utf8_ibytes (*i);
wchar_t v = *i & (0xff >> n); // First byte contains bits after the header.
while (--n && *++i) // Each subsequent byte has 6 bits.
v = (v << 6) | (*i & 0x3f);
*pt = ++i;
return v;
}
unsigned utf8_length (const char* s)
{
unsigned l = 0;
while (utf8_next (&s))
++l;
return l;
}
unsigned utf8_range_length (const char* f, const char* l)
{
unsigned rl = 0;
while (f < l && utf8_next (&f))
++rl;
return rl;
}
void waddn_utf8 (WINDOW* w, const char* s, unsigned n)
{
#if NCURSES_WIDECHAR
attr_t attr = 0;
short cpair = 0;
attr_get (&attr, &cpair, NULL);
wchar_t wchzs[2] = { 0, 0 };
cchar_t ch = {};
while (n-- && (wchzs[0] = utf8_next (&s))) {
setcchar (&ch, wchzs, attr, cpair, NULL);
wadd_wch (w, &ch);
}
#else
wchar_t wc;
while (n-- && (wc = utf8_next (&s)))
waddch (w, wc < CHAR_MAX ? (char) wc : '?');
#endif
}
void wadd_utf8 (WINDOW* w, const char* s)
{
int x = getcurx (w);
unsigned ww = getmaxx (w);
waddn_utf8 (w, s, ww-x);
}
void mvwaddn_utf8 (WINDOW* w, int y, int x, const char* s, unsigned n)
{
wmove (w, y, x);
waddn_utf8 (w, s, n);
}
void mvwadd_utf8 (WINDOW* w, int y, int x, const char* s)
{
wmove (w, y, x);
wadd_utf8 (w, s);
}