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