summaryrefslogtreecommitdiff
path: root/ucs2_to_utf8.c
diff options
context:
space:
mode:
authorMichael Stapelberg <michael@stapelberg.de>2010-07-16 17:35:51 +0200
committerMichael Stapelberg <michael@stapelberg.de>2010-07-16 17:35:51 +0200
commit1dc3fd7bf000b57f8462416ae3e17f2f580d2020 (patch)
treec99f60831281a1ac59aecf2cc21f22c106798608 /ucs2_to_utf8.c
parentb4c10df0fc8440804d87e4df2f68a860b0bb08af (diff)
Initial commit of the XCB rewrite of i3lock
Changes: - Uses XCB instead of Xlib (like i3), thus cleaner/faster code - Uses cairo to load PNG images (*much* faster than XPM)
Diffstat (limited to 'ucs2_to_utf8.c')
-rw-r--r--ucs2_to_utf8.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/ucs2_to_utf8.c b/ucs2_to_utf8.c
new file mode 100644
index 0000000..4624ee6
--- /dev/null
+++ b/ucs2_to_utf8.c
@@ -0,0 +1,111 @@
+/*
+ * vim:ts=8:expandtab
+ *
+ * i3 - an improved dynamic tiling window manager
+ *
+ * © 2009-2010 Michael Stapelberg and contributors
+ *
+ * See file LICENSE for license information.
+ *
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <iconv.h>
+
+static iconv_t conversion_descriptor = 0;
+static iconv_t conversion_descriptor2 = 0;
+
+/* isutf, u8_dec © 2005 Jeff Bezanson, public domain */
+#define isutf(c) (((c) & 0xC0) != 0x80)
+
+/*
+ * Decrements i to point to the previous unicode glyph
+ *
+ */
+void u8_dec(char *s, int *i) {
+ (void)(isutf(s[--(*i)]) || isutf(s[--(*i)]) || isutf(s[--(*i)]) || --(*i));
+}
+
+/*
+ * Returns the input string, but converted from UCS-2 to UTF-8. Memory will be
+ * allocated, thus the caller has to free the output.
+ *
+ */
+int convert_ucs_to_utf8(char *input, char *output) {
+ size_t input_size = 2;
+
+ /* UTF-8 may consume up to 4 byte */
+ size_t output_size = 8;
+ /* We need to use an additional pointer, because iconv() modifies it */
+ char *outptr = output;
+
+ /* We convert the input into UCS-2 big endian */
+ if (conversion_descriptor == 0) {
+ conversion_descriptor = iconv_open("UTF-8", "UCS-2BE");
+ if (conversion_descriptor == 0) {
+ fprintf(stderr, "error opening the conversion context\n");
+ exit(1);
+ }
+ }
+
+ /* Get the conversion descriptor back to original state */
+ iconv(conversion_descriptor, NULL, NULL, NULL, NULL);
+
+ /* Convert our text */
+ int rc = iconv(conversion_descriptor, (void*)&input, &input_size, &outptr, &output_size);
+ if (rc == (size_t)-1) {
+ perror("Converting to UCS-2 failed");
+ return 0;
+ }
+
+ return (8 - output_size);
+}
+
+/*
+ * Converts the given string to UCS-2 big endian for use with
+ * xcb_image_text_16(). The amount of real glyphs is stored in real_strlen,
+ * a buffer containing the UCS-2 encoded string (16 bit per glyph) is
+ * returned. It has to be freed when done.
+ *
+ */
+char *convert_utf8_to_ucs2(char *input, int *real_strlen) {
+ size_t input_size = strlen(input) + 1;
+ /* UCS-2 consumes exactly two bytes for each glyph */
+ int buffer_size = input_size * 2;
+
+ char *buffer = malloc(buffer_size);
+ if (buffer == NULL)
+ err(EXIT_FAILURE, "malloc() failed\n");
+ size_t output_size = buffer_size;
+ /* We need to use an additional pointer, because iconv() modifies it */
+ char *output = buffer;
+
+ /* We convert the input into UCS-2 big endian */
+ if (conversion_descriptor2 == 0) {
+ conversion_descriptor2 = iconv_open("UCS-2BE", "UTF-8");
+ if (conversion_descriptor2 == 0) {
+ fprintf(stderr, "error opening the conversion context\n");
+ exit(1);
+ }
+ }
+
+ /* Get the conversion descriptor back to original state */
+ iconv(conversion_descriptor2, NULL, NULL, NULL, NULL);
+
+ /* Convert our text */
+ int rc = iconv(conversion_descriptor2, (void*)&input, &input_size, &output, &output_size);
+ if (rc == (size_t)-1) {
+ perror("Converting to UCS-2 failed");
+ if (real_strlen != NULL)
+ *real_strlen = 0;
+ return NULL;
+ }
+
+ if (real_strlen != NULL)
+ *real_strlen = ((buffer_size - output_size) / 2) - 1;
+
+ return buffer;
+}
+