Merged branch utf8.
[neverball] / share / text.c
1 /*
2  * Copyright (C) 2003 Robert Kooima
3  *
4  * NEVERBALL is  free software; you can redistribute  it and/or modify
5  * it under the  terms of the GNU General  Public License as published
6  * by the Free  Software Foundation; either version 2  of the License,
7  * or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
11  * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
12  * General Public License for more details.
13  */
14
15 #include <stdio.h>
16 #include <string.h>
17 #include <errno.h>
18
19 #if ENABLE_NLS
20 #include <iconv.h>
21 #endif
22
23 #include "text.h"
24
25 /*---------------------------------------------------------------------------*/
26
27 #define MAXSTR 256
28
29 /*---------------------------------------------------------------------------*/
30
31 #if ENABLE_NLS
32 static iconv_t conv_from_locale = 0;
33 static iconv_t conv_to_locale = 0;
34 #endif
35
36 void text_init(void)
37 {
38 #if ENABLE_NLS
39     if ((conv_from_locale = iconv_open("UTF-8", "")) == (iconv_t) -1)
40         fprintf(stderr, "Error: %s\n", strerror(errno));
41
42     if ((conv_to_locale = iconv_open("", "UTF-8")) == (iconv_t) -1)
43         fprintf(stderr, "Error: %s\n", strerror(errno));
44 #else
45     return;
46 #endif
47 }
48
49 void text_quit(void)
50 {
51 #if ENABLE_NLS
52     if (conv_from_locale != (iconv_t) -1)
53         iconv_close(conv_from_locale);
54
55     if (conv_to_locale != (iconv_t) -1)
56         iconv_close(conv_to_locale);
57 #else
58     return;
59 #endif
60 }
61
62 /*---------------------------------------------------------------------------*/
63
64 char *text_from_locale(char *str0)
65 {
66 #if ENABLE_NLS
67     static char buffer[MAXSTR * 2];
68
69     char *str0p = str0;
70     char *str1p = buffer;
71
72     size_t l0 = strlen(str0);
73     size_t l1 = sizeof (buffer);
74
75     if (conv_from_locale == (iconv_t) -1)
76         return str0;
77
78     if (iconv(conv_from_locale, &str0p, &l0, &str1p, &l1) == (size_t) -1)
79         fprintf(stderr, "Error while converting to UTF-8: %s\n",
80                 strerror(errno));
81
82     *str1p = '\0';
83
84     return buffer;
85 #else
86     return str0;
87 #endif
88 }
89
90 char *text_to_locale(char *str0)
91 {
92 #if ENABLE_NLS
93     static char buffer[MAXSTR * 2];
94
95     char *str0p = str0;
96     char *str1p = buffer;
97
98     size_t l0 = strlen(str0);
99     size_t l1 = sizeof (buffer);
100
101     if (conv_to_locale == (iconv_t) -1)
102         return str0;
103
104     if (iconv(conv_to_locale, &str0p, &l0, &str1p, &l1) == (size_t) -1)
105         fprintf(stderr, "Error while converting from UTF-8: %s\n",
106                 strerror(errno));
107
108     *str1p = '\0';
109
110     return buffer;
111 #else
112     return str0;
113 #endif
114 }
115
116 /*---------------------------------------------------------------------------*/
117
118 int text_add_char(Uint32 unicode, char *string, int maxbytes, int maxchars)
119 {
120     size_t pos = strlen(string);
121     int l;
122
123     if      (unicode < 0x80)    l = 1;
124     else if (unicode < 0x0800)  l = 2;
125     else if (unicode < 0x10000) l = 3;
126     else                        l = 4;
127
128     if ((pos + l >= maxbytes) || (text_length(string) + 1 >= maxchars))
129         return 0;
130
131     if (unicode < 0x80)
132         string[pos++] = (char) unicode;
133     else if (unicode < 0x0800)
134     {
135         string[pos++] = (char) ((unicode >> 6) | 0xC0);
136         string[pos++] = (char) ((unicode & 0x3F) | 0x80);
137     }
138     else if (unicode < 0x10000)
139     {
140         string[pos++] = (char) ((unicode >> 12) | 0xE0);
141         string[pos++] = (char) (((unicode >> 6) & 0x3F) | 0x80);
142         string[pos++] = (char) ((unicode & 0x3F) | 0x80);
143     }
144     else
145     {
146         string[pos++] = (char) ((unicode >> 18) | 0xF0);
147         string[pos++] = (char) (((unicode >> 12) & 0x3F) | 0x80);
148         string[pos++] = (char) (((unicode >> 6) & 0x3F) | 0x80);
149         string[pos++] = (char) ((unicode & 0x3F) | 0x80);
150     }
151
152     string[pos++] = 0;
153
154     return l;
155 }
156
157 int text_del_char(char *string)
158 {
159     size_t pos = strlen(string) - 1;
160
161     while (pos >= 0 && ((string[pos] & 0xC0) == 0x80))
162         string[pos--] = 0;
163
164     if (pos >= 0)
165     {
166         string[pos] = 0;
167         return 1;
168     }
169
170     return 0;
171 }
172
173 int text_length(const char *string)
174 {
175     int result = 0;
176
177     while (*string != '\0')
178         if ((*string++ & 0xC0) != 0x80)
179             result++;
180
181     return result;
182 }
183
184 /*---------------------------------------------------------------------------*/