]> git.sur5r.net Git - i3/i3/blob - libi3/string.c
19039a23564f4ac43948c3acba568900e3262f98
[i3/i3] / libi3 / string.c
1 /*
2  * vim:ts=4:sw=4:expandtab
3  *
4  * i3 - an improved dynamic tiling window manager
5  * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
6  *
7  * string.c: Define an i3String type to automagically handle UTF-8/UCS-2
8  *           conversions. Some font backends need UCS-2 (X core fonts),
9  *           others want UTF-8 (Pango).
10  *
11  */
12
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include <glib.h>
17
18 #include "libi3.h"
19
20 struct _i3String {
21     char *utf8;
22     xcb_char2b_t *ucs2;
23     size_t num_glyphs;
24     size_t num_bytes;
25     bool pango_markup;
26 };
27
28 /*
29  * Build an i3String from an UTF-8 encoded string.
30  * Returns the newly-allocated i3String.
31  *
32  */
33 i3String *i3string_from_utf8(const char *from_utf8) {
34     i3String *str = scalloc(1, sizeof(i3String));
35
36     /* Get the text */
37     str->utf8 = sstrdup(from_utf8);
38
39     /* Compute and store the length */
40     str->num_bytes = strlen(str->utf8);
41
42     return str;
43 }
44
45 /*
46  * Build an i3String from an UTF-8 encoded string in Pango markup.
47  *
48  */
49 i3String *i3string_from_markup(const char *from_markup) {
50     i3String *str = i3string_from_utf8(from_markup);
51
52     /* Set the markup flag */
53     str->pango_markup = true;
54
55     return str;
56 }
57
58 /*
59  * Build an i3String from an UTF-8 encoded string with fixed length.
60  * To be used when no proper NUL-terminaison is available.
61  * Returns the newly-allocated i3String.
62  *
63  */
64 i3String *i3string_from_utf8_with_length(const char *from_utf8, size_t num_bytes) {
65     i3String *str = scalloc(1, sizeof(i3String));
66
67     /* Copy the actual text to our i3String */
68     str->utf8 = scalloc(num_bytes + 1, 1);
69     strncpy(str->utf8, from_utf8, num_bytes);
70     str->utf8[num_bytes] = '\0';
71
72     /* Store the length */
73     str->num_bytes = num_bytes;
74
75     return str;
76 }
77
78 /*
79  * Build an i3String from an UTF-8 encoded string in Pango markup with fixed
80  * length.
81  *
82  */
83 i3String *i3string_from_markup_with_length(const char *from_markup, size_t num_bytes) {
84     i3String *str = i3string_from_utf8_with_length(from_markup, num_bytes);
85
86     /* set the markup flag */
87     str->pango_markup = true;
88
89     return str;
90 }
91
92 /*
93  * Build an i3String from an UCS-2 encoded string.
94  * Returns the newly-allocated i3String.
95  *
96  */
97 i3String *i3string_from_ucs2(const xcb_char2b_t *from_ucs2, size_t num_glyphs) {
98     i3String *str = scalloc(1, sizeof(i3String));
99
100     /* Copy the actual text to our i3String */
101     str->ucs2 = scalloc(num_glyphs, sizeof(xcb_char2b_t));
102     memcpy(str->ucs2, from_ucs2, num_glyphs * sizeof(xcb_char2b_t));
103
104     /* Store the length */
105     str->num_glyphs = num_glyphs;
106
107     str->utf8 = NULL;
108     str->num_bytes = 0;
109
110     return str;
111 }
112
113 /**
114  * Copies the given i3string.
115  * Note that this will not free the source string.
116  */
117 i3String *i3string_copy(i3String *str) {
118     i3String *copy = i3string_from_utf8(i3string_as_utf8(str));
119     copy->pango_markup = str->pango_markup;
120     return copy;
121 }
122
123 /*
124  * Free an i3String.
125  *
126  */
127 void i3string_free(i3String *str) {
128     if (str == NULL)
129         return;
130     free(str->utf8);
131     free(str->ucs2);
132     free(str);
133 }
134
135 static void i3string_ensure_utf8(i3String *str) {
136     if (str->utf8 != NULL)
137         return;
138     if ((str->utf8 = convert_ucs2_to_utf8(str->ucs2, str->num_glyphs)) != NULL)
139         str->num_bytes = strlen(str->utf8);
140 }
141
142 static void i3string_ensure_ucs2(i3String *str) {
143     if (str->ucs2 != NULL)
144         return;
145     str->ucs2 = convert_utf8_to_ucs2(str->utf8, &str->num_glyphs);
146 }
147
148 /*
149  * Returns the UTF-8 encoded version of the i3String.
150  *
151  */
152 const char *i3string_as_utf8(i3String *str) {
153     i3string_ensure_utf8(str);
154     return str->utf8;
155 }
156
157 /*
158  * Returns the UCS-2 encoded version of the i3String.
159  *
160  */
161 const xcb_char2b_t *i3string_as_ucs2(i3String *str) {
162     i3string_ensure_ucs2(str);
163     return str->ucs2;
164 }
165
166 /*
167  * Returns the number of bytes (UTF-8 encoded) in an i3String.
168  *
169  */
170 size_t i3string_get_num_bytes(i3String *str) {
171     i3string_ensure_utf8(str);
172     return str->num_bytes;
173 }
174
175 /*
176  * Whether the given i3String is in Pango markup.
177  */
178 bool i3string_is_markup(i3String *str) {
179     return str->pango_markup;
180 }
181
182 /*
183  * Set whether the i3String should use Pango markup.
184  */
185 void i3string_set_markup(i3String *str, bool pango_markup) {
186     str->pango_markup = pango_markup;
187 }
188
189 /*
190  * Escape pango markup characters in the given string.
191  */
192 i3String *i3string_escape_markup(i3String *str) {
193     const char *text = i3string_as_utf8(str);
194     char *escaped = g_markup_escape_text(text, -1);
195     i3String *result = i3string_from_utf8(escaped);
196     free(escaped);
197     return result;
198 }
199
200 /*
201  * Returns the number of glyphs in an i3String.
202  *
203  */
204 size_t i3string_get_num_glyphs(i3String *str) {
205     i3string_ensure_ucs2(str);
206     return str->num_glyphs;
207 }