summaryrefslogtreecommitdiff
path: root/pugl/pugl_internal.h
diff options
context:
space:
mode:
Diffstat (limited to 'pugl/pugl_internal.h')
-rw-r--r--pugl/pugl_internal.h34
1 files changed, 34 insertions, 0 deletions
diff --git a/pugl/pugl_internal.h b/pugl/pugl_internal.h
index 5b2b1c7..993f319 100644
--- a/pugl/pugl_internal.h
+++ b/pugl/pugl_internal.h
@@ -213,6 +213,40 @@ puglEnterContext(PuglView* view);
void
puglLeaveContext(PuglView* view, bool flush);
+/** Return the code point for buf, or the replacement character on error. */
+static uint32_t
+puglDecodeUTF8(const uint8_t* buf)
+{
+#define FAIL_IF(cond) { if (cond) return 0xFFFD; }
+
+ /* http://en.wikipedia.org/wiki/UTF-8 */
+
+ if (buf[0] < 0x80) {
+ return buf[0];
+ } else if (buf[0] < 0xC2) {
+ return 0xFFFD;
+ } else if (buf[0] < 0xE0) {
+ FAIL_IF((buf[1] & 0xC0) != 0x80);
+ return (buf[0] << 6) + buf[1] - 0x3080;
+ } else if (buf[0] < 0xF0) {
+ FAIL_IF((buf[1] & 0xC0) != 0x80);
+ FAIL_IF(buf[0] == 0xE0 && buf[1] < 0xA0);
+ FAIL_IF((buf[2] & 0xC0) != 0x80);
+ return (buf[0] << 12) + (buf[1] << 6) + buf[2] - 0xE2080;
+ } else if (buf[0] < 0xF5) {
+ FAIL_IF((buf[1] & 0xC0) != 0x80);
+ FAIL_IF(buf[0] == 0xF0 && buf[1] < 0x90);
+ FAIL_IF(buf[0] == 0xF4 && buf[1] >= 0x90);
+ FAIL_IF((buf[2] & 0xC0) != 0x80);
+ FAIL_IF((buf[3] & 0xC0) != 0x80);
+ return ((buf[0] << 18) +
+ (buf[1] << 12) +
+ (buf[2] << 6) +
+ buf[3] - 0x3C82080);
+ }
+ return 0xFFFD;
+}
+
static void
puglDispatchEvent(PuglView* view, const PuglEvent* event)
{