From: Fernando Tarlá Cardoso Lemos Date: Fri, 11 Nov 2011 23:18:37 +0000 (-0200) Subject: Consolidate all convert_* functions into libi3. X-Git-Tag: 4.2~246 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=fb11cc2d149bf49d54e29ee2b7ba0ef1a67bdf11;p=i3%2Fi3 Consolidate all convert_* functions into libi3. Some minor fixes along the way as well. Very minor stuff, unlikely to ever be visible to the user. --- diff --git a/i3-input/i3-input.h b/i3-input/i3-input.h index d97807d1..f494cbd5 100644 --- a/i3-input/i3-input.h +++ b/i3-input/i3-input.h @@ -14,7 +14,4 @@ while (0) extern xcb_window_t root; -char *convert_ucs_to_utf8(char *input); -char *convert_utf8_to_ucs2(char *input, int *real_strlen); - #endif diff --git a/i3-input/main.c b/i3-input/main.c index def68481..3eabd15d 100644 --- a/i3-input/main.c +++ b/i3-input/main.c @@ -260,14 +260,14 @@ static int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press printf("inp[0] = %02x, inp[1] = %02x, inp[2] = %02x\n", inp[0], inp[1], inp[2]); /* convert it to UTF-8 */ - char *out = convert_ucs_to_utf8((char*)inp); + char *out = convert_ucs2_to_utf8((xcb_char2b_t*)inp, 1); printf("converted to %s\n", out); glyphs_ucs[input_position] = malloc(3 * sizeof(uint8_t)); if (glyphs_ucs[input_position] == NULL) err(EXIT_FAILURE, "malloc() failed\n"); memcpy(glyphs_ucs[input_position], inp, 3); - glyphs_utf8[input_position] = strdup(out); + glyphs_utf8[input_position] = out; input_position++; if (input_position == limit) @@ -348,7 +348,7 @@ int main(int argc, char *argv[]) { sockfd = ipc_connect(socket_path); if (prompt != NULL) - prompt = convert_utf8_to_ucs2(prompt, &prompt_len); + prompt = (char*)convert_utf8_to_ucs2(prompt, &prompt_len); int screens; conn = xcb_connect(NULL, &screens); diff --git a/i3-input/ucs2_to_utf8.c b/i3-input/ucs2_to_utf8.c deleted file mode 100644 index df112eef..00000000 --- a/i3-input/ucs2_to_utf8.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * vim:ts=4:sw=4:expandtab - * - * i3 - an improved dynamic tiling window manager - * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE) - * - * ucs2_to_utf8.c: Converts between UCS-2 and UTF-8, both of which are used in - * different contexts in X11. - * - */ -#include -#include -#include -#include -#include - -#include "libi3.h" - -static iconv_t conversion_descriptor = 0; -static iconv_t conversion_descriptor2 = 0; - -/* - * Returns the input string, but converted from UCS-2 to UTF-8. Memory will be - * allocated, thus the caller has to free the output. - * - */ -char *convert_ucs_to_utf8(char *input) { - size_t input_size = 2; - /* UTF-8 may consume up to 4 byte */ - int buffer_size = 8; - - char *buffer = scalloc(buffer_size); - 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_descriptor == 0) { - conversion_descriptor = iconv_open("UTF-8", "UCS-2BE"); - if (conversion_descriptor == 0) - errx(EXIT_FAILURE, "Error opening the conversion context"); - } - - /* 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, &output, &output_size); - if (rc == (size_t)-1) { - free(buffer); - perror("Converting to UCS-2 failed"); - return NULL; - } - - return buffer; -} - -/* - * 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 = smalloc(buffer_size); - 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) - errx(EXIT_FAILURE, "Error opening the conversion context"); - } - - /* 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"); - free(buffer); - if (real_strlen != NULL) - *real_strlen = 0; - return NULL; - } - - if (real_strlen != NULL) - *real_strlen = ((buffer_size - output_size) / 2) - 1; - - return buffer; -} - diff --git a/i3bar/include/common.h b/i3bar/include/common.h index 3b6967fa..bce31a4d 100644 --- a/i3bar/include/common.h +++ b/i3bar/include/common.h @@ -31,7 +31,6 @@ struct rect_t { #include "workspaces.h" #include "trayclients.h" #include "xcb.h" -#include "ucs2_to_utf8.h" #include "config.h" #include "libi3.h" diff --git a/i3bar/include/ucs2_to_utf8.h b/i3bar/include/ucs2_to_utf8.h deleted file mode 100644 index a77ed20e..00000000 --- a/i3bar/include/ucs2_to_utf8.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * vim:ts=4:sw=4:expandtab - * - * i3 - an improved dynamic tiling window manager - * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE) - * - * ucs2_to_utf8.c: Converts between UCS-2 and UTF-8, both of which are used in - * different contexts in X11. - */ -#ifndef _UCS2_TO_UTF8 -#define _UCS2_TO_UTF8 - -char *convert_utf8_to_ucs2(char *input, int *real_strlen); - -#endif diff --git a/i3bar/src/ucs2_to_utf8.c b/i3bar/src/ucs2_to_utf8.c deleted file mode 100644 index 642a72fb..00000000 --- a/i3bar/src/ucs2_to_utf8.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * vim:ts=4:sw=4:expandtab - * - * i3 - an improved dynamic tiling window manager - * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE) - * - * ucs2_to_utf8.c: Converts between UCS-2 and UTF-8, both of which are used in - * different contexts in X11. - */ -#include -#include -#include -#include -#include - -#include "libi3.h" - -static iconv_t conversion_descriptor = 0; -static iconv_t conversion_descriptor2 = 0; - -/* - * Returns the input string, but converted from UCS-2 to UTF-8. Memory will be - * allocated, thus the caller has to free the output. - * - */ -char *convert_ucs_to_utf8(char *input) { - size_t input_size = 2; - /* UTF-8 may consume up to 4 byte */ - int buffer_size = 8; - - char *buffer = scalloc(buffer_size); - 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_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, &output, &output_size); - if (rc == (size_t)-1) { - perror("Converting to UCS-2 failed"); - free(buffer); - return NULL; - } - - return buffer; -} - -/* - * 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 = smalloc(buffer_size); - 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"); - free(buffer); - if (real_strlen != NULL) - *real_strlen = 0; - return NULL; - } - - if (real_strlen != NULL) - *real_strlen = ((buffer_size - output_size) / 2) - 1; - - return buffer; -} diff --git a/include/libi3.h b/include/libi3.h index 71fba764..c87ec3e3 100644 --- a/include/libi3.h +++ b/include/libi3.h @@ -179,4 +179,20 @@ uint32_t get_mod_mask_for(uint32_t keysym, */ i3Font load_font(const char *pattern, bool fallback); +/** + * Converts the given string to UTF-8 from UCS-2 big endian. The return value + * must be freed after use. + * + */ +char *convert_ucs2_to_utf8(xcb_char2b_t *text, size_t num_glyphs); + +/** + * 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. + * + */ +xcb_char2b_t *convert_utf8_to_ucs2(char *input, int *real_strlen); + #endif diff --git a/include/util.h b/include/util.h index 4a5920d2..cd88863c 100644 --- a/include/util.h +++ b/include/util.h @@ -91,15 +91,6 @@ void exec_i3_utility(char *name, char *argv[]); void check_error(xcb_connection_t *conn, xcb_void_cookie_t cookie, char *err_message); -/** - * 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); - /** * This function resolves ~ in pathnames. * It may resolve wildcards in the first part of the path, but if no match diff --git a/include/xcb.h b/include/xcb.h index 01e2b667..a1bd22fa 100644 --- a/include/xcb.h +++ b/include/xcb.h @@ -99,7 +99,7 @@ void xcb_raise_window(xcb_connection_t *conn, xcb_window_t window); * real length (amount of glyphs) using the given font. * */ -int predict_text_width(char *text, int length); +int predict_text_width(const xcb_char2b_t *text, int length); /** * Configures the given window to have the size/position specified by given rect diff --git a/libi3/ucs2_conversion.c b/libi3/ucs2_conversion.c new file mode 100644 index 00000000..99beb368 --- /dev/null +++ b/libi3/ucs2_conversion.c @@ -0,0 +1,103 @@ +/* + * vim:ts=4:sw=4:expandtab + * + * i3 - an improved dynamic tiling window manager + * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE) + * + */ +#include +#include +#include +#include +#include + +#include "libi3.h" + +static iconv_t utf8_conversion_descriptor = (iconv_t)-1; +static iconv_t ucs2_conversion_descriptor = (iconv_t)-1; + +/* + * Converts the given string to UTF-8 from UCS-2 big endian. The return value + * must be freed after use. + * + */ +char *convert_ucs2_to_utf8(xcb_char2b_t *text, size_t num_glyphs) { + /* Allocate the output buffer (UTF-8 is at most 4 bytes per glyph) */ + size_t buffer_size = num_glyphs * 4 * sizeof(char) + 1; + char *buffer = scalloc(buffer_size * sizeof(char)); + + /* We need to use an additional pointer, because iconv() modifies it */ + char *output = buffer; + size_t output_size = buffer_size - 1; + + if (utf8_conversion_descriptor == (iconv_t)-1) { + /* Get a new conversion descriptor */ + utf8_conversion_descriptor = iconv_open("UTF-8", "UCS-2BE"); + if (utf8_conversion_descriptor == (iconv_t)-1) + err(EXIT_FAILURE, "Error opening the conversion context"); + } + else { + /* Reset the existing conversion descriptor */ + iconv(utf8_conversion_descriptor, NULL, NULL, NULL, NULL); + } + + /* Do the conversion */ + size_t input_len = num_glyphs * sizeof(xcb_char2b_t); + size_t rc = iconv(utf8_conversion_descriptor, (char**)&text, + &input_len, &output, &output_size); + if (rc == (size_t)-1) { + perror("Converting to UTF-8 failed"); + free(buffer); + return NULL; + } + + return buffer; +} + +/* + * 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. + * + */ +xcb_char2b_t *convert_utf8_to_ucs2(char *input, int *real_strlen) { + /* Calculate the input buffer size (UTF-8 is strlen-safe) */ + size_t input_size = strlen(input); + + /* Calculate the output buffer size and allocate the buffer */ + size_t buffer_size = input_size * sizeof(xcb_char2b_t); + xcb_char2b_t *buffer = smalloc(buffer_size); + + /* We need to use an additional pointer, because iconv() modifies it */ + size_t output_size = buffer_size; + xcb_char2b_t *output = buffer; + + if (ucs2_conversion_descriptor == (iconv_t)-1) { + /* Get a new conversion descriptor */ + ucs2_conversion_descriptor = iconv_open("UCS-2BE", "UTF-8"); + if (ucs2_conversion_descriptor == (iconv_t)-1) + err(EXIT_FAILURE, "Error opening the conversion context"); + } + else { + /* Reset the existing conversion descriptor */ + iconv(ucs2_conversion_descriptor, NULL, NULL, NULL, NULL); + } + + /* Do the conversion */ + size_t rc = iconv(ucs2_conversion_descriptor, (char**)&input, + &input_size, (char**)&output, &output_size); + if (rc == (size_t)-1) { + perror("Converting to UCS-2 failed"); + free(buffer); + if (real_strlen != NULL) + *real_strlen = 0; + return NULL; + } + + /* Return the resulting string's length */ + if (real_strlen != NULL) + *real_strlen = (buffer_size - output_size) / sizeof(xcb_char2b_t); + + return buffer; +} diff --git a/src/sighandler.c b/src/sighandler.c index a029422b..ef8a514b 100644 --- a/src/sighandler.c +++ b/src/sighandler.c @@ -51,7 +51,7 @@ static int sig_draw_window(xcb_window_t win, int width, int height, int font_hei for (int i = 0; i < sizeof(crash_text) / sizeof(char*); i++) { int text_len = strlen(crash_text[i]); - char *full_text = convert_utf8_to_ucs2(crash_text[i], &text_len); + xcb_char2b_t *full_text = convert_utf8_to_ucs2(crash_text[i], &text_len); xcb_image_text_16(conn, text_len, pixmap, pixmap_gc, 8 /* X */, 3 + (i + 1) * font_height /* Y = baseline of font */, (xcb_char2b_t*)full_text); @@ -151,7 +151,7 @@ void handle_signal(int sig, siginfo_t *info, void *data) { /* calculate width for longest text */ int text_len = strlen(crash_text[crash_text_longest]); - char *longest_text = convert_utf8_to_ucs2(crash_text[crash_text_longest], &text_len); + xcb_char2b_t *longest_text = convert_utf8_to_ucs2(crash_text[crash_text_longest], &text_len); int font_width = predict_text_width(longest_text, text_len); int width = font_width + 20; diff --git a/src/util.c b/src/util.c index 72146bff..57bfa89b 100644 --- a/src/util.c +++ b/src/util.c @@ -12,7 +12,6 @@ #include #include -#include #if defined(__OpenBSD__) #include #endif @@ -24,8 +23,6 @@ #define SN_API_NOT_YET_FROZEN 1 #include -static iconv_t conversion_descriptor = 0; - int min(int a, int b) { return (a < b ? a : b); } @@ -120,51 +117,6 @@ void check_error(xcb_connection_t *conn, xcb_void_cookie_t cookie, char *err_mes } } -/* - * 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 = smalloc(buffer_size); - 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_descriptor == 0) { - conversion_descriptor = iconv_open("UCS-2BE", "UTF-8"); - 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, &output, &output_size); - if (rc == (size_t)-1) { - perror("Converting to UCS-2 failed"); - FREE(buffer); - if (real_strlen != NULL) - *real_strlen = 0; - return NULL; - } - - if (real_strlen != NULL) - *real_strlen = ((buffer_size - output_size) / 2) - 1; - - return buffer; -} - /* * This function resolves ~ in pathnames. * It may resolve wildcards in the first part of the path, but if no match diff --git a/src/window.c b/src/window.c index 30957a4b..17f2d4a2 100644 --- a/src/window.c +++ b/src/window.c @@ -69,7 +69,7 @@ void window_update_name(i3Window *win, xcb_get_property_reply_t *prop, bool befo } /* Convert it to UCS-2 here for not having to convert it later every time we want to pass it to X */ int len; - char *ucs2_name = convert_utf8_to_ucs2(new_name, &len); + xcb_char2b_t *ucs2_name = convert_utf8_to_ucs2(new_name, &len); if (ucs2_name == NULL) { LOG("Could not convert _NET_WM_NAME to UCS-2, ignoring new hint\n"); FREE(new_name); @@ -79,7 +79,7 @@ void window_update_name(i3Window *win, xcb_get_property_reply_t *prop, bool befo FREE(win->name_x); FREE(win->name_json); win->name_json = new_name; - win->name_x = ucs2_name; + win->name_x = (char*)ucs2_name; win->name_len = len; win->name_x_changed = true; LOG("_NET_WM_NAME changed to \"%s\"\n", win->name_json); diff --git a/src/xcb.c b/src/xcb.c index aa761cac..739bf9e7 100644 --- a/src/xcb.c +++ b/src/xcb.c @@ -135,13 +135,13 @@ void xcb_raise_window(xcb_connection_t *conn, xcb_window_t window) { * length (amount of glyphs) using the given font. * */ -int predict_text_width(char *text, int length) { +int predict_text_width(const xcb_char2b_t *text, int length) { xcb_query_text_extents_cookie_t cookie; xcb_query_text_extents_reply_t *reply; xcb_generic_error_t *error; int width; - cookie = xcb_query_text_extents(conn, config.font.id, length, (xcb_char2b_t*)text); + cookie = xcb_query_text_extents(conn, config.font.id, length, text); if ((reply = xcb_query_text_extents_reply(conn, cookie, &error)) == NULL) { ELOG("Could not get text extents (X error code %d)\n", error->error_code);