]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkim-x11.c
Start of integration of Erwann Chenede's multihead work from the
[~andy/gtk] / gdk / x11 / gdkim-x11.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include <locale.h>
28 #include <stdlib.h>
29
30 #include "gdkx.h"
31 #include "gdk.h"                /* For gdk_flush() */
32 #include "gdkx.h"
33 #include "gdkpixmap.h"
34 #include "gdkinternals.h"
35 #include "gdkdisplay-x11.h"
36
37 #if HAVE_CONFIG_H
38 #  include <config.h>
39 #  if STDC_HEADERS
40 #    include <string.h>
41 #  endif
42 #endif
43
44
45 /* If this variable is FALSE, it indicates that we should
46  * avoid trying to use multibyte conversion functions and
47  * assume everything is 1-byte per character
48  */
49 static gboolean gdk_use_mb;
50
51 void
52 _gdk_x11_initialize_locale (void)
53 {
54   wchar_t result;
55   gchar *current_locale;
56   static char *last_locale = NULL;
57
58   gdk_use_mb = FALSE;
59
60   current_locale = setlocale (LC_ALL, NULL);
61
62   if (last_locale && strcmp (last_locale, current_locale) == 0)
63     return;
64
65   g_free (last_locale);
66   last_locale = g_strdup (current_locale);
67
68   if (!XSupportsLocale ())
69     g_warning ("locale not supported by Xlib");
70   
71   if (!XSetLocaleModifiers (""))
72     g_warning ("can not set locale modifiers");
73
74   if ((strcmp (current_locale, "C")) && (strcmp (current_locale, "POSIX")))
75     {
76       gdk_use_mb = TRUE;
77
78 #ifndef X_LOCALE
79       /* Detect ancient GNU libc, where mb == UTF8. Not useful unless it's
80        * really a UTF8 locale. The below still probably will
81        * screw up on Greek, Cyrillic, etc, encoded as UTF8.
82        */
83       
84       if ((MB_CUR_MAX == 2) &&
85           (mbstowcs (&result, "\xdd\xa5", 1) > 0) &&
86           result == 0x765)
87         {
88           if ((strlen (current_locale) < 4) ||
89               g_ascii_strcasecmp (current_locale + strlen(current_locale) - 4, "utf8"))
90             gdk_use_mb = FALSE;
91         }
92 #endif /* X_LOCALE */
93     }
94
95   GDK_NOTE (XIM,
96             g_message ("%s multi-byte string functions.", 
97                        gdk_use_mb ? "Using" : "Not using"));
98   
99   return;
100 }
101
102 gchar*
103 gdk_set_locale (void)
104 {
105   if (!setlocale (LC_ALL,""))
106     g_warning ("locale not supported by C library");
107
108   _gdk_x11_initialize_locale ();
109   
110   return setlocale (LC_ALL, NULL);
111 }
112
113 static GdkDisplay *
114 find_a_display ()
115 {
116   GdkDisplay *display = gdk_get_default_display ();
117
118   if (!display)
119     display = _gdk_displays->data;
120
121   return display;
122 }
123
124 /*
125  * gdk_wcstombs 
126  *
127  * Returns a multi-byte string converted from the specified array
128  * of wide characters. The string is newly allocated. The array of
129  * wide characters must be null-terminated. If the conversion is
130  * failed, it returns NULL.
131  */
132 gchar *
133 gdk_wcstombs (const GdkWChar *src)
134 {
135   gchar *mbstr;
136
137   if (gdk_use_mb)
138     {
139       GdkDisplay *display = find_a_display ();
140       Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
141       XTextProperty tpr;
142
143       if (sizeof(wchar_t) != sizeof(GdkWChar))
144         {
145           gint i;
146           wchar_t *src_alt;
147           for (i=0; src[i]; i++);
148           src_alt = g_new (wchar_t, i+1);
149           for (; i>=0; i--)
150             src_alt[i] = src[i];
151           if (XwcTextListToTextProperty (xdisplay, &src_alt, 1, XTextStyle, &tpr)
152               != Success)
153             {
154               g_free (src_alt);
155               return NULL;
156             }
157           g_free (src_alt);
158         }
159       else
160         {
161           if (XwcTextListToTextProperty (xdisplay, (wchar_t**)&src, 1,
162                                          XTextStyle, &tpr) != Success)
163             {
164               return NULL;
165             }
166         }
167       /*
168        * We must copy the string into an area allocated by glib, because
169        * the string 'tpr.value' must be freed by XFree().
170        */
171       mbstr = g_strdup(tpr.value);
172       XFree (tpr.value);
173     }
174   else
175     {
176       gint length = 0;
177       gint i;
178
179       while (src[length] != 0)
180         length++;
181       
182       mbstr = g_new (gchar, length + 1);
183
184       for (i=0; i<length+1; i++)
185         mbstr[i] = src[i];
186     }
187
188   return mbstr;
189 }
190   
191 /*
192  * gdk_mbstowcs
193  *
194  * Converts the specified string into wide characters, and, returns the
195  * number of wide characters written. The string 'src' must be
196  * null-terminated. If the conversion is failed, it returns -1.
197  */
198 gint
199 gdk_mbstowcs (GdkWChar *dest, const gchar *src, gint dest_max)
200 {
201   if (gdk_use_mb)
202     {
203       GdkDisplay *display = find_a_display ();
204       Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
205       XTextProperty tpr;
206       wchar_t **wstrs, *wstr_src;
207       gint num_wstrs;
208       gint len_cpy;
209       if (XmbTextListToTextProperty (xdisplay, (char **)&src, 1, XTextStyle,
210                                      &tpr)
211           != Success)
212         {
213           /* NoMem or LocaleNotSupp */
214           return -1;
215         }
216       if (XwcTextPropertyToTextList (xdisplay, &tpr, &wstrs, &num_wstrs)
217           != Success)
218         {
219           /* InvalidChar */
220           XFree(tpr.value);
221           return -1;
222         }
223       XFree(tpr.value);
224       if (num_wstrs == 0)
225         return 0;
226       wstr_src = wstrs[0];
227       for (len_cpy=0; len_cpy<dest_max && wstr_src[len_cpy]; len_cpy++)
228         dest[len_cpy] = wstr_src[len_cpy];
229       XwcFreeStringList (wstrs);
230       return len_cpy;
231     }
232   else
233     {
234       gint i;
235
236       for (i=0; i<dest_max && src[i]; i++)
237         dest[i] = src[i];
238
239       return i;
240     }
241 }