]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkim-win32.c
Merge from stable:
[~andy/gtk] / gdk / win32 / gdkim-win32.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  * Copyright (C) 1998-2002 Tor Lillqvist
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 #include <config.h>
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <locale.h>
33
34 #include "gdkpixmap.h"
35 #include "gdkinternals.h"
36 #include "gdki18n.h"
37 #include "gdkwin32.h"
38
39 /*
40  *--------------------------------------------------------------
41  * gdk_set_locale
42  *
43  * Arguments:
44  *
45  * Results:
46  *
47  * Side effects:
48  *
49  *--------------------------------------------------------------
50  */
51
52 gchar*
53 gdk_set_locale (void)
54 {
55   if (!setlocale (LC_ALL, ""))
56     g_warning ("locale not supported by C library");
57   
58   return g_win32_getlocale ();
59 }
60
61 /*
62  * gdk_wcstombs 
63  *
64  * Returns a multi-byte string converted from the specified array
65  * of wide characters. The string is newly allocated. The array of
66  * wide characters must be null-terminated. If the conversion is
67  * failed, it returns NULL.
68  *
69  * On Win32, we always use UTF-8.
70  */
71 gchar *
72 gdk_wcstombs (const GdkWChar *src)
73 {
74   gint len;
75   const GdkWChar *wcp;
76   guchar *mbstr, *bp;
77
78   wcp = src;
79   len = 0;
80   while (*wcp)
81     {
82       const GdkWChar c = *wcp++;
83
84       if (c < 0x80)
85         len += 1;
86       else if (c < 0x800)
87         len += 2;
88       else if (c < 0x10000)
89         len += 3;
90       else if (c < 0x200000)
91         len += 4;
92       else if (c < 0x4000000)
93         len += 5;
94       else
95         len += 6;
96     }
97
98   mbstr = g_malloc (len + 1);
99   
100   wcp = src;
101   bp = mbstr;
102   while (*wcp)
103     {
104       int first;
105       GdkWChar c = *wcp++;
106
107       if (c < 0x80)
108         {
109           first = 0;
110           len = 1;
111         }
112       else if (c < 0x800)
113         {
114           first = 0xc0;
115           len = 2;
116         }
117       else if (c < 0x10000)
118         {
119           first = 0xe0;
120           len = 3;
121         }
122       else if (c < 0x200000)
123         {
124           first = 0xf0;
125           len = 4;
126         }
127       else if (c < 0x4000000)
128         {
129           first = 0xf8;
130           len = 5;
131         }
132       else
133         {
134           first = 0xfc;
135           len = 6;
136         }
137       
138       /* Woo-hoo! */
139       switch (len)
140         {
141         case 6: bp[5] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
142         case 5: bp[4] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
143         case 4: bp[3] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
144         case 3: bp[2] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
145         case 2: bp[1] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
146         case 1: bp[0] = c | first;
147         }
148
149       bp += len;
150     }
151   *bp = 0;
152   return mbstr;
153 }
154
155 /* A vesion that converts from wchar_t strings to UTF-8 */
156
157 gchar *
158 _gdk_ucs2_to_utf8 (const wchar_t *src,
159                    gint           src_len)
160 {
161   gint len;
162   const wchar_t *wcp;
163   guchar *mbstr, *bp;
164
165   wcp = src;
166   len = 0;
167   while (wcp < src + src_len)
168     {
169       const wchar_t c = *wcp++;
170
171       if (c < 0x80)
172         len += 1;
173       else if (c < 0x800)
174         len += 2;
175       else
176         len += 3;
177     }
178
179   mbstr = g_malloc (len + 1);
180   
181   wcp = src;
182   bp = mbstr;
183   while (wcp < src + src_len)
184     {
185       int first;
186       wchar_t c = *wcp++;
187
188       if (c < 0x80)
189         {
190           first = 0;
191           len = 1;
192         }
193       else if (c < 0x800)
194         {
195           first = 0xc0;
196           len = 2;
197         }
198       else
199         {
200           first = 0xe0;
201           len = 3;
202         }
203       
204       /* Woo-hoo! */
205       switch (len)
206         {
207         case 3: bp[2] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
208         case 2: bp[1] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
209         case 1: bp[0] = c | first;
210         }
211
212       bp += len;
213     }
214   *bp = 0;
215
216   return mbstr;
217 }
218   
219 /* Convert from UTF-8 to GdkWChar */
220
221 gint
222 _gdk_utf8_to_wcs (GdkWChar    *dest,
223                   const gchar *src,
224                   gint         src_len,
225                   gint         dest_max)
226 {
227   guchar *cp, *end;
228   gint n;
229   
230   cp = (guchar *) src;
231   end = cp + src_len;
232   n = 0;
233   while (cp != end && dest != dest + dest_max)
234     {
235       gint i, mask = 0, len;
236       guchar c = *cp;
237
238       if (c < 0x80)
239         {
240           len = 1;
241           mask = 0x7f;
242         }
243       else if ((c & 0xe0) == 0xc0)
244         {
245           len = 2;
246           mask = 0x1f;
247         }
248       else if ((c & 0xf0) == 0xe0)
249         {
250           len = 3;
251           mask = 0x0f;
252         }
253       else if ((c & 0xf8) == 0xf0)
254         {
255           len = 4;
256           mask = 0x07;
257         }
258       else if ((c & 0xfc) == 0xf8)
259         {
260           len = 5;
261           mask = 0x03;
262         }
263       else if ((c & 0xfc) == 0xfc)
264         {
265           len = 6;
266           mask = 0x01;
267         }
268       else
269         return -1;
270
271       if (cp + len > end)
272         return -1;
273
274       *dest = (cp[0] & mask);
275       for (i = 1; i < len; i++)
276         {
277           if ((cp[i] & 0xc0) != 0x80)
278             return -1;
279           *dest <<= 6;
280           *dest |= (cp[i] & 0x3f);
281         }
282       if (*dest == -1)
283         return -1;
284
285       cp += len;
286       dest++;
287       n++;
288     }
289   if (cp != end)
290     return -1;
291
292   return n;
293 }
294
295 /*
296  * gdk_mbstowcs
297  *
298  * Converts the specified string into GDK wide characters, and,
299  * returns the number of wide characters written. The string 'src'
300  * must be null-terminated. If the conversion is failed, it returns
301  * -1.
302  *
303  * On Win32, the string is assumed to be in UTF-8.  Also note that
304  * GdkWChar is 32 bits, while wchar_t, and the wide characters the
305  * Windows API uses, are 16 bits!
306  */
307
308 gint
309 gdk_mbstowcs (GdkWChar    *dest,
310               const gchar *src,
311               gint         dest_max)
312 {
313   return _gdk_utf8_to_wcs (dest, src, strlen (src), dest_max);
314 }
315
316
317 /* A version that converts to a wchar_t string */
318
319 gint
320 _gdk_utf8_to_ucs2 (wchar_t     *dest,
321                    const gchar *src,
322                    gint         src_len,
323                    gint         dest_max)
324 {
325   wchar_t *wcp;
326   guchar *cp, *end;
327   gint n;
328   
329   wcp = dest;
330   cp = (guchar *) src;
331   end = cp + src_len;
332   n = 0;
333   while (cp != end && wcp != dest + dest_max)
334     {
335       gint i, mask = 0, len;
336       guchar c = *cp;
337
338       if (c < 0x80)
339         {
340           len = 1;
341           mask = 0x7f;
342         }
343       else if ((c & 0xe0) == 0xc0)
344         {
345           len = 2;
346           mask = 0x1f;
347         }
348       else if ((c & 0xf0) == 0xe0)
349         {
350           len = 3;
351           mask = 0x0f;
352         }
353       else /* Other lengths are not possible with 16-bit wchar_t! */
354         return -1;
355
356       if (cp + len > end)
357         return -1;
358
359       *wcp = (cp[0] & mask);
360       for (i = 1; i < len; i++)
361         {
362           if ((cp[i] & 0xc0) != 0x80)
363             return -1;
364           *wcp <<= 6;
365           *wcp |= (cp[i] & 0x3f);
366         }
367       if (*wcp == 0xFFFF)
368         return -1;
369
370       cp += len;
371       wcp++;
372       n++;
373     }
374   if (cp != end)
375     return -1;
376
377   return n;
378 }