From 1dc3fd7bf000b57f8462416ae3e17f2f580d2020 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Fri, 16 Jul 2010 17:35:51 +0200 Subject: 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) --- ucs2_to_utf8.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 ucs2_to_utf8.c (limited to 'ucs2_to_utf8.c') 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 +#include +#include +#include +#include + +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; +} + -- cgit v1.1