mirror of
				https://github.com/i3/i3.git
				synced 2025-10-29 19:35:06 +00:00 
			
		
		
		
	Enforces a rule that we have followed for years now. Yes, the diff is quite big but we get it over with once and we prevent having to nit-pick future PRs.
		
			
				
	
	
		
			110 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			110 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * vim:ts=4:sw=4:expandtab
 | |
|  *
 | |
|  * i3 - an improved dynamic tiling window manager
 | |
|  * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
 | |
|  *
 | |
|  */
 | |
| #include "libi3.h"
 | |
| 
 | |
| #include <err.h>
 | |
| #include <iconv.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.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 + 1;
 | |
|     char *buffer = scalloc(buffer_size, 1);
 | |
| 
 | |
|     /* 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, size_t *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_bytes_left = buffer_size;
 | |
|     xcb_char2b_t *output = buffer;
 | |
| 
 | |
|     if (ucs2_conversion_descriptor == (iconv_t)-1) {
 | |
|         /* Get a new conversion descriptor. //IGNORE is a GNU suffix that makes
 | |
|          * iconv to silently discard characters that cannot be represented in
 | |
|          * the target character set. */
 | |
|         ucs2_conversion_descriptor = iconv_open("UCS-2BE//IGNORE", "UTF-8");
 | |
|         if (ucs2_conversion_descriptor == (iconv_t)-1) {
 | |
|             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, &input, &input_size,
 | |
|                       (char **)&output, &output_bytes_left);
 | |
|     if (rc == (size_t)-1) {
 | |
|         /* Conversion will only be partial. */
 | |
|         perror("Converting to UCS-2 failed");
 | |
|     }
 | |
| 
 | |
|     /* If no bytes where converted, this is equivalent to freeing buffer. */
 | |
|     buffer_size -= output_bytes_left;
 | |
|     buffer = srealloc(buffer, buffer_size);
 | |
| 
 | |
|     /* Return the resulting string's length */
 | |
|     if (real_strlen != NULL) {
 | |
|         *real_strlen = buffer_size / sizeof(xcb_char2b_t);
 | |
|     }
 | |
| 
 | |
|     return buffer;
 | |
| }
 |