You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
3.3 KiB

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