aboutsummaryrefslogtreecommitdiff
path: root/libutf.c
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2015-07-18 10:35:32 +0200
committerMarc André Tanner <mat@brain-dump.org>2015-07-20 12:05:45 +0200
commit38f00e3e8a50e1690dcb78cf1eca8b6befb7173b (patch)
treef613eec7ee39a312229e97d22557623ef7a2510f /libutf.c
parent0fa9885cda0778467ca5737ac888ece5ef371b3d (diff)
downloadvis-38f00e3e8a50e1690dcb78cf1eca8b6befb7173b.tar.gz
vis-38f00e3e8a50e1690dcb78cf1eca8b6befb7173b.tar.xz
vis: improve insertion of verbatim characters via CTRL-V in insert mode
Recognized formats are: CTRL-V nnn decimal value nnn CTRL-V onnn or CTRL-V Onnn octal value nnn CTRL-V xnn or CTRL-V Xnn hex value nn CTRL-V unnnn Unicode codepoint nnnn CTRL-V Unnnnnnnn Unicode codepoint nnnnnnnn Leading zeros can be omitted, any illegal character for the given format will be ignored and terminates the numerical code.
Diffstat (limited to 'libutf.c')
-rw-r--r--libutf.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/libutf.c b/libutf.c
new file mode 100644
index 0000000..5f6ff45
--- /dev/null
+++ b/libutf.c
@@ -0,0 +1,52 @@
+/* libutf8 © 2012-2015 Connor Lane Smith <cls@lubutu.com> */
+#include "libutf.h"
+
+int
+runelen(Rune r)
+{
+ if(r <= 0x7F)
+ return 1;
+ else if(r <= 0x07FF)
+ return 2;
+ else if(r <= 0xD7FF)
+ return 3;
+ else if(r <= 0xDFFF)
+ return 0; /* surrogate character */
+ else if(r <= 0xFFFD)
+ return 3;
+ else if(r <= 0xFFFF)
+ return 0; /* illegal character */
+ else if(r <= Runemax)
+ return 4;
+ else
+ return 0; /* rune too large */
+}
+
+int
+runetochar(char *s, const Rune *p)
+{
+ Rune r = *p;
+
+ switch(runelen(r)) {
+ case 1: /* 0aaaaaaa */
+ s[0] = r;
+ return 1;
+ case 2: /* 00000aaa aabbbbbb */
+ s[0] = 0xC0 | ((r & 0x0007C0) >> 6); /* 110aaaaa */
+ s[1] = 0x80 | (r & 0x00003F); /* 10bbbbbb */
+ return 2;
+ case 3: /* aaaabbbb bbcccccc */
+ s[0] = 0xE0 | ((r & 0x00F000) >> 12); /* 1110aaaa */
+ s[1] = 0x80 | ((r & 0x000FC0) >> 6); /* 10bbbbbb */
+ s[2] = 0x80 | (r & 0x00003F); /* 10cccccc */
+ return 3;
+ case 4: /* 000aaabb bbbbcccc ccdddddd */
+ s[0] = 0xF0 | ((r & 0x1C0000) >> 18); /* 11110aaa */
+ s[1] = 0x80 | ((r & 0x03F000) >> 12); /* 10bbbbbb */
+ s[2] = 0x80 | ((r & 0x000FC0) >> 6); /* 10cccccc */
+ s[3] = 0x80 | (r & 0x00003F); /* 10dddddd */
+ return 4;
+ default:
+ return 0; /* error */
+ }
+}