]> git.sur5r.net Git - i3/i3lock/blob - ucs2_to_utf8.c
Update README
[i3/i3lock] / ucs2_to_utf8.c
1 /*
2  * vim:ts=8:expandtab
3  *
4  * i3 - an improved dynamic tiling window manager
5  *
6  * © 2009-2010 Michael Stapelberg and contributors
7  *
8  * See file LICENSE for license information.
9  *
10  */
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <err.h>
15 #include <iconv.h>
16
17 static iconv_t conversion_descriptor = 0;
18 static iconv_t conversion_descriptor2 = 0;
19
20 /* isutf, u8_dec © 2005 Jeff Bezanson, public domain */
21 #define isutf(c) (((c) & 0xC0) != 0x80)
22
23 /*
24  * Decrements i to point to the previous unicode glyph
25  *
26  */
27 void u8_dec(char *s, int *i) {
28     (void)(isutf(s[--(*i)]) || isutf(s[--(*i)]) || isutf(s[--(*i)]) || --(*i));
29 }
30
31 /*
32  * Returns the input string, but converted from UCS-2 to UTF-8. Memory will be
33  * allocated, thus the caller has to free the output.
34  *
35  */
36 int convert_ucs_to_utf8(char *input, char *output) {
37         size_t input_size = 2;
38
39         /* UTF-8 may consume up to 4 byte */
40         size_t output_size = 8;
41         /* We need to use an additional pointer, because iconv() modifies it */
42         char *outptr = output;
43
44         /* We convert the input into UCS-2 big endian */
45         if (conversion_descriptor == 0) {
46                 conversion_descriptor = iconv_open("UTF-8", "UCS-2BE");
47                 if (conversion_descriptor == 0) {
48                         fprintf(stderr, "error opening the conversion context\n");
49                         exit(1);
50                 }
51         }
52
53         /* Get the conversion descriptor back to original state */
54         iconv(conversion_descriptor, NULL, NULL, NULL, NULL);
55
56         /* Convert our text */
57         int rc = iconv(conversion_descriptor, (void*)&input, &input_size, &outptr, &output_size);
58         if (rc == (size_t)-1) {
59                 perror("Converting to UCS-2 failed");
60                 return 0;
61         }
62
63         return (8 - output_size);
64 }
65
66 /*
67  * Converts the given string to UCS-2 big endian for use with
68  * xcb_image_text_16(). The amount of real glyphs is stored in real_strlen,
69  * a buffer containing the UCS-2 encoded string (16 bit per glyph) is
70  * returned. It has to be freed when done.
71  *
72  */
73 char *convert_utf8_to_ucs2(char *input, int *real_strlen) {
74         size_t input_size = strlen(input) + 1;
75         /* UCS-2 consumes exactly two bytes for each glyph */
76         int buffer_size = input_size * 2;
77
78         char *buffer = malloc(buffer_size);
79         if (buffer == NULL)
80                 err(EXIT_FAILURE, "malloc() failed\n");
81         size_t output_size = buffer_size;
82         /* We need to use an additional pointer, because iconv() modifies it */
83         char *output = buffer;
84
85         /* We convert the input into UCS-2 big endian */
86         if (conversion_descriptor2 == 0) {
87                 conversion_descriptor2 = iconv_open("UCS-2BE", "UTF-8");
88                 if (conversion_descriptor2 == 0) {
89                         fprintf(stderr, "error opening the conversion context\n");
90                         exit(1);
91                 }
92         }
93
94         /* Get the conversion descriptor back to original state */
95         iconv(conversion_descriptor2, NULL, NULL, NULL, NULL);
96
97         /* Convert our text */
98         int rc = iconv(conversion_descriptor2, (void*)&input, &input_size, &output, &output_size);
99         if (rc == (size_t)-1) {
100                 perror("Converting to UCS-2 failed");
101                 if (real_strlen != NULL)
102                         *real_strlen = 0;
103                 return NULL;
104         }
105
106         if (real_strlen != NULL)
107                 *real_strlen = ((buffer_size - output_size) / 2) - 1;
108
109         return buffer;
110 }
111