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 Library 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 | * Library General Public License for more details. |
---|
13 | * |
---|
14 | * You should have received a copy of the GNU Library 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-1999. 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 <X11/Xlocale.h> |
---|
28 | #include "gdk.h" |
---|
29 | #include "gdkprivate.h" |
---|
30 | #include "gdki18n.h" |
---|
31 | #include "gdkx.h" |
---|
32 | |
---|
33 | #if HAVE_CONFIG_H |
---|
34 | # include <config.h> |
---|
35 | # if STDC_HEADERS |
---|
36 | # include <string.h> |
---|
37 | # endif |
---|
38 | #endif |
---|
39 | |
---|
40 | #ifdef USE_NATIVE_LOCALE |
---|
41 | #include <stdlib.h> |
---|
42 | #endif |
---|
43 | |
---|
44 | /* If this variable is FALSE, it indicates that we should |
---|
45 | * avoid trying to use multibyte conversion functions and |
---|
46 | * assume everything is 1-byte per character |
---|
47 | */ |
---|
48 | static gboolean gdk_use_mb; |
---|
49 | |
---|
50 | #ifdef USE_XIM |
---|
51 | |
---|
52 | #include <stdarg.h> |
---|
53 | #include <X11/Xresource.h> |
---|
54 | |
---|
55 | /* The following routines duplicate functionality in Xlib to |
---|
56 | * translate from varargs to X's internal opaque XVaNestedList. |
---|
57 | * |
---|
58 | * If all vendors have stuck close to the reference implementation, |
---|
59 | * then we should hopefully be OK. |
---|
60 | */ |
---|
61 | |
---|
62 | typedef struct { |
---|
63 | gchar *name; |
---|
64 | gpointer value; |
---|
65 | } GdkImArg; |
---|
66 | |
---|
67 | #ifdef USE_X11R6_XIM |
---|
68 | static void gdk_im_instantiate_cb (Display *display, |
---|
69 | XPointer client_data, |
---|
70 | XPointer call_data); |
---|
71 | #endif |
---|
72 | static void gdk_im_destroy_cb (XIM im, |
---|
73 | XPointer client_data, |
---|
74 | XPointer call_data); |
---|
75 | static gint gdk_im_real_open (void); |
---|
76 | static void gdk_ic_real_new (GdkIC *ic); |
---|
77 | |
---|
78 | static GdkICAttributesType gdk_ic_real_set_attr (GdkIC *ic, |
---|
79 | GdkICAttr *attr, |
---|
80 | GdkICAttributesType mask); |
---|
81 | |
---|
82 | static XIM xim_im; /* global IM */ |
---|
83 | static XIMStyles* xim_styles; /* im supports these styles */ |
---|
84 | static XIMStyle xim_best_allowed_style; |
---|
85 | static GList* xim_ic_list; |
---|
86 | |
---|
87 | #endif /* USE_XIM */ |
---|
88 | |
---|
89 | /* |
---|
90 | *-------------------------------------------------------------- |
---|
91 | * gdk_set_locale |
---|
92 | * |
---|
93 | * Arguments: |
---|
94 | * |
---|
95 | * Results: |
---|
96 | * |
---|
97 | * Side effects: |
---|
98 | * |
---|
99 | *-------------------------------------------------------------- |
---|
100 | */ |
---|
101 | |
---|
102 | gchar* |
---|
103 | gdk_set_locale (void) |
---|
104 | { |
---|
105 | wchar_t result; |
---|
106 | gchar *current_locale; |
---|
107 | |
---|
108 | gdk_use_mb = FALSE; |
---|
109 | |
---|
110 | if (!setlocale (LC_ALL,"")) |
---|
111 | g_warning ("locale not supported by C library"); |
---|
112 | |
---|
113 | if (!XSupportsLocale ()) |
---|
114 | { |
---|
115 | g_warning ("locale not supported by Xlib, locale set to C"); |
---|
116 | setlocale (LC_ALL, "C"); |
---|
117 | } |
---|
118 | |
---|
119 | if (!XSetLocaleModifiers ("")) |
---|
120 | g_warning ("can not set locale modifiers"); |
---|
121 | |
---|
122 | current_locale = setlocale (LC_ALL, NULL); |
---|
123 | |
---|
124 | if ((strcmp (current_locale, "C")) && (strcmp (current_locale, "POSIX"))) |
---|
125 | { |
---|
126 | gdk_use_mb = TRUE; |
---|
127 | |
---|
128 | #ifndef X_LOCALE |
---|
129 | /* Detect GNU libc, where mb == UTF8. Not useful unless it's |
---|
130 | * really a UTF8 locale. The below still probably will |
---|
131 | * screw up on Greek, Cyrillic, etc, encoded as UTF8. |
---|
132 | */ |
---|
133 | |
---|
134 | if ((MB_CUR_MAX == 2) && |
---|
135 | (mbstowcs (&result, "\xdd\xa5", 1) > 0) && |
---|
136 | result == 0x765) |
---|
137 | { |
---|
138 | if ((strlen (current_locale) < 4) || |
---|
139 | g_strcasecmp (current_locale + strlen(current_locale) - 4, "utf8")) |
---|
140 | gdk_use_mb = FALSE; |
---|
141 | } |
---|
142 | #endif /* X_LOCALE */ |
---|
143 | } |
---|
144 | |
---|
145 | GDK_NOTE (XIM, |
---|
146 | g_message ("%s multi-byte string functions.", |
---|
147 | gdk_use_mb ? "Using" : "Not using")); |
---|
148 | |
---|
149 | return current_locale; |
---|
150 | } |
---|
151 | |
---|
152 | #ifdef USE_XIM |
---|
153 | |
---|
154 | /* |
---|
155 | *-------------------------------------------------------------- |
---|
156 | * gdk_im_begin |
---|
157 | * |
---|
158 | * Begin using input method with XIM Protocol(X11R6 standard) |
---|
159 | * |
---|
160 | * Arguments: |
---|
161 | * "ic" is the "Input Context" which is created by gtk_ic_new. |
---|
162 | * The input area is specified with "window". |
---|
163 | * |
---|
164 | * Results: |
---|
165 | * The gdk's event handling routine is switched to XIM based routine. |
---|
166 | * XIM based routine uses XFilterEvent to get rid of events used by IM, |
---|
167 | * and uses XmbLookupString instead of XLookupString. |
---|
168 | * |
---|
169 | * Side effects: |
---|
170 | * |
---|
171 | *-------------------------------------------------------------- |
---|
172 | */ |
---|
173 | |
---|
174 | void |
---|
175 | gdk_im_begin (GdkIC *ic, GdkWindow* window) |
---|
176 | { |
---|
177 | GdkICPrivate *private; |
---|
178 | GdkICAttr attr; |
---|
179 | |
---|
180 | g_return_if_fail (ic != NULL); |
---|
181 | |
---|
182 | private = (GdkICPrivate *) ic; |
---|
183 | |
---|
184 | attr.focus_window = window; |
---|
185 | gdk_ic_set_attr (ic, &attr, GDK_IC_FOCUS_WINDOW); |
---|
186 | |
---|
187 | if (private != gdk_xim_ic) |
---|
188 | { |
---|
189 | gdk_im_end(); |
---|
190 | if (private->xic) |
---|
191 | { |
---|
192 | XSetICFocus (private->xic); |
---|
193 | GDK_NOTE (XIM, g_message ("im_begin icfocus : %p(%ld)\n", |
---|
194 | private->xic, |
---|
195 | GDK_WINDOW_XWINDOW(private->attr->focus_window))); |
---|
196 | } |
---|
197 | } |
---|
198 | gdk_xim_ic = private; |
---|
199 | gdk_xim_window = window; |
---|
200 | } |
---|
201 | |
---|
202 | /* |
---|
203 | *-------------------------------------------------------------- |
---|
204 | * gdk_im_end |
---|
205 | * |
---|
206 | * End using input method with XIM Protocol(X11R6 standard) |
---|
207 | * |
---|
208 | * Arguments: |
---|
209 | * |
---|
210 | * Results: |
---|
211 | * The gdk's event handling routine is switched to normal routine. |
---|
212 | * User should call this function before ic and window will be destroyed. |
---|
213 | * |
---|
214 | * Side effects: |
---|
215 | * |
---|
216 | *-------------------------------------------------------------- |
---|
217 | */ |
---|
218 | |
---|
219 | void |
---|
220 | gdk_im_end (void) |
---|
221 | { |
---|
222 | if (gdk_xim_ic && gdk_xim_ic->xic) |
---|
223 | { |
---|
224 | XUnsetICFocus (gdk_xim_ic->xic); |
---|
225 | GDK_NOTE (XIM, g_message ("im_end unfocus : %p\n", gdk_xim_ic->xic)); |
---|
226 | } |
---|
227 | gdk_xim_ic = NULL; |
---|
228 | gdk_xim_window = NULL; |
---|
229 | } |
---|
230 | |
---|
231 | static GdkIMStyle |
---|
232 | gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2) |
---|
233 | { |
---|
234 | GdkIMStyle s1, s2, u; |
---|
235 | |
---|
236 | if (style1 == 0) return style2; |
---|
237 | if (style2 == 0) return style1; |
---|
238 | if ((style1 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK)) |
---|
239 | == (style2 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK))) |
---|
240 | return style1; |
---|
241 | |
---|
242 | s1 = style1 & GDK_IM_PREEDIT_MASK; |
---|
243 | s2 = style2 & GDK_IM_PREEDIT_MASK; |
---|
244 | u = s1 | s2; |
---|
245 | if (s1 != s2) { |
---|
246 | if (u & GDK_IM_PREEDIT_CALLBACKS) |
---|
247 | return (s1 == GDK_IM_PREEDIT_CALLBACKS)? style1:style2; |
---|
248 | else if (u & GDK_IM_PREEDIT_POSITION) |
---|
249 | return (s1 == GDK_IM_PREEDIT_POSITION)? style1:style2; |
---|
250 | else if (u & GDK_IM_PREEDIT_AREA) |
---|
251 | return (s1 == GDK_IM_PREEDIT_AREA)? style1:style2; |
---|
252 | else if (u & GDK_IM_PREEDIT_NOTHING) |
---|
253 | return (s1 == GDK_IM_PREEDIT_NOTHING)? style1:style2; |
---|
254 | } else { |
---|
255 | s1 = style1 & GDK_IM_STATUS_MASK; |
---|
256 | s2 = style2 & GDK_IM_STATUS_MASK; |
---|
257 | u = s1 | s2; |
---|
258 | if ( u & GDK_IM_STATUS_CALLBACKS) |
---|
259 | return (s1 == GDK_IM_STATUS_CALLBACKS)? style1:style2; |
---|
260 | else if ( u & GDK_IM_STATUS_AREA) |
---|
261 | return (s1 == GDK_IM_STATUS_AREA)? style1:style2; |
---|
262 | else if ( u & GDK_IM_STATUS_NOTHING) |
---|
263 | return (s1 == GDK_IM_STATUS_NOTHING)? style1:style2; |
---|
264 | else if ( u & GDK_IM_STATUS_NONE) |
---|
265 | return (s1 == GDK_IM_STATUS_NONE)? style1:style2; |
---|
266 | } |
---|
267 | return 0; /* Get rid of stupid warning */ |
---|
268 | } |
---|
269 | |
---|
270 | GdkIMStyle |
---|
271 | gdk_im_decide_style (GdkIMStyle supported_style) |
---|
272 | { |
---|
273 | gint i; |
---|
274 | GdkIMStyle style, tmp; |
---|
275 | |
---|
276 | g_return_val_if_fail (xim_styles != NULL, 0); |
---|
277 | |
---|
278 | style = 0; |
---|
279 | for (i=0; i<xim_styles->count_styles; i++) |
---|
280 | { |
---|
281 | tmp = xim_styles->supported_styles[i]; |
---|
282 | if (tmp == (tmp & supported_style & xim_best_allowed_style)) |
---|
283 | style = gdk_im_choose_better_style (style, tmp); |
---|
284 | } |
---|
285 | return style; |
---|
286 | } |
---|
287 | |
---|
288 | GdkIMStyle |
---|
289 | gdk_im_set_best_style (GdkIMStyle style) |
---|
290 | { |
---|
291 | if (style & GDK_IM_PREEDIT_MASK) |
---|
292 | { |
---|
293 | xim_best_allowed_style &= ~GDK_IM_PREEDIT_MASK; |
---|
294 | |
---|
295 | xim_best_allowed_style |= GDK_IM_PREEDIT_NONE; |
---|
296 | if (!(style & GDK_IM_PREEDIT_NONE)) |
---|
297 | { |
---|
298 | xim_best_allowed_style |= GDK_IM_PREEDIT_NOTHING; |
---|
299 | if (!(style & GDK_IM_PREEDIT_NOTHING)) |
---|
300 | { |
---|
301 | xim_best_allowed_style |= GDK_IM_PREEDIT_AREA; |
---|
302 | if (!(style & GDK_IM_PREEDIT_AREA)) |
---|
303 | { |
---|
304 | xim_best_allowed_style |= GDK_IM_PREEDIT_POSITION; |
---|
305 | if (!(style & GDK_IM_PREEDIT_POSITION)) |
---|
306 | xim_best_allowed_style |= GDK_IM_PREEDIT_CALLBACKS; |
---|
307 | } |
---|
308 | } |
---|
309 | } |
---|
310 | } |
---|
311 | if (style & GDK_IM_STATUS_MASK) |
---|
312 | { |
---|
313 | xim_best_allowed_style &= ~GDK_IM_STATUS_MASK; |
---|
314 | |
---|
315 | xim_best_allowed_style |= GDK_IM_STATUS_NONE; |
---|
316 | if (!(style & GDK_IM_STATUS_NONE)) |
---|
317 | { |
---|
318 | xim_best_allowed_style |= GDK_IM_STATUS_NOTHING; |
---|
319 | if (!(style & GDK_IM_STATUS_NOTHING)) |
---|
320 | { |
---|
321 | xim_best_allowed_style |= GDK_IM_STATUS_AREA; |
---|
322 | if (!(style & GDK_IM_STATUS_AREA)) |
---|
323 | xim_best_allowed_style |= GDK_IM_STATUS_CALLBACKS; |
---|
324 | } |
---|
325 | } |
---|
326 | } |
---|
327 | |
---|
328 | return xim_best_allowed_style; |
---|
329 | } |
---|
330 | |
---|
331 | #ifdef USE_X11R6_XIM |
---|
332 | static void |
---|
333 | gdk_im_destroy_cb (XIM im, XPointer client_data, XPointer call_data) |
---|
334 | { |
---|
335 | GList *node; |
---|
336 | GdkICPrivate *private; |
---|
337 | |
---|
338 | GDK_NOTE (XIM, g_message ("Ouch, Input Method is destroyed!!\n")); |
---|
339 | |
---|
340 | xim_im = NULL; |
---|
341 | |
---|
342 | if (xim_styles) |
---|
343 | { |
---|
344 | XFree (xim_styles); |
---|
345 | xim_styles = NULL; |
---|
346 | } |
---|
347 | |
---|
348 | for (node = xim_ic_list; node != NULL; node = g_list_next(node)) |
---|
349 | { |
---|
350 | private = (GdkICPrivate *) (node->data); |
---|
351 | private->xic = NULL; |
---|
352 | } |
---|
353 | |
---|
354 | XRegisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL, |
---|
355 | gdk_im_instantiate_cb, NULL); |
---|
356 | } |
---|
357 | |
---|
358 | static void |
---|
359 | gdk_im_instantiate_cb (Display *display, |
---|
360 | XPointer client_data, XPointer call_data) |
---|
361 | { |
---|
362 | GDK_NOTE (XIM, g_message ("New IM is instantiated.")); |
---|
363 | if (display != gdk_display) |
---|
364 | return; |
---|
365 | |
---|
366 | gdk_im_real_open (); |
---|
367 | |
---|
368 | if (xim_im != NULL) |
---|
369 | XUnregisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL, |
---|
370 | gdk_im_instantiate_cb, NULL); |
---|
371 | } |
---|
372 | #endif |
---|
373 | |
---|
374 | static gint |
---|
375 | gdk_im_real_open (void) |
---|
376 | { |
---|
377 | GList *node; |
---|
378 | |
---|
379 | xim_im = XOpenIM (GDK_DISPLAY(), NULL, NULL, NULL); |
---|
380 | if (xim_im == NULL) |
---|
381 | { |
---|
382 | GDK_NOTE (XIM, g_warning ("Unable to open IM.")); |
---|
383 | return FALSE; |
---|
384 | } |
---|
385 | else |
---|
386 | { |
---|
387 | #ifdef USE_X11R6_XIM |
---|
388 | XIMCallback destroy_cb; |
---|
389 | |
---|
390 | destroy_cb.callback = gdk_im_destroy_cb; |
---|
391 | destroy_cb.client_data = NULL; |
---|
392 | if (NULL != (void *) XSetIMValues (xim_im, XNDestroyCallback, &destroy_cb, NULL)) |
---|
393 | GDK_NOTE (XIM, g_warning ("Could not set destroy callback to IM. Be careful to not destroy your input method.")); |
---|
394 | #endif |
---|
395 | |
---|
396 | XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL); |
---|
397 | |
---|
398 | for (node = xim_ic_list; node != NULL; node = g_list_next(node)) |
---|
399 | { |
---|
400 | GdkICPrivate *private = (GdkICPrivate *) (node->data); |
---|
401 | if (private->xic == NULL) |
---|
402 | gdk_ic_real_new ((GdkIC *)private); |
---|
403 | } |
---|
404 | return TRUE; |
---|
405 | } |
---|
406 | } |
---|
407 | |
---|
408 | gint |
---|
409 | gdk_im_open (void) |
---|
410 | { |
---|
411 | gdk_xim_ic = NULL; |
---|
412 | gdk_xim_window = (GdkWindow*)NULL; |
---|
413 | xim_im = NULL; |
---|
414 | xim_styles = NULL; |
---|
415 | |
---|
416 | /* initialize XIM Protocol variables */ |
---|
417 | if (!(xim_best_allowed_style & GDK_IM_PREEDIT_MASK)) |
---|
418 | gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS); |
---|
419 | if (!(xim_best_allowed_style & GDK_IM_STATUS_MASK)) |
---|
420 | gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS); |
---|
421 | |
---|
422 | if (gdk_im_real_open ()) |
---|
423 | return TRUE; |
---|
424 | |
---|
425 | #ifdef USE_X11R6_XIM |
---|
426 | XRegisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL, |
---|
427 | gdk_im_instantiate_cb, NULL); |
---|
428 | #endif |
---|
429 | |
---|
430 | return FALSE; |
---|
431 | } |
---|
432 | |
---|
433 | void |
---|
434 | gdk_im_close (void) |
---|
435 | { |
---|
436 | if (xim_im) |
---|
437 | { |
---|
438 | XCloseIM (xim_im); |
---|
439 | xim_im = NULL; |
---|
440 | } |
---|
441 | if (xim_styles) |
---|
442 | { |
---|
443 | XFree (xim_styles); |
---|
444 | xim_styles = NULL; |
---|
445 | } |
---|
446 | } |
---|
447 | |
---|
448 | gboolean |
---|
449 | gdk_im_ready (void) |
---|
450 | { |
---|
451 | return (xim_im != NULL); |
---|
452 | } |
---|
453 | |
---|
454 | static void |
---|
455 | gdk_ic_real_new (GdkIC *ic) |
---|
456 | { |
---|
457 | XPoint spot_location; |
---|
458 | XRectangle preedit_area; |
---|
459 | XRectangle status_area; |
---|
460 | XVaNestedList *preedit_attr = NULL; |
---|
461 | XVaNestedList *status_attr = NULL; |
---|
462 | GdkICAttr *attr; |
---|
463 | GdkICPrivate *private; |
---|
464 | GdkICAttributesType mask = GDK_IC_ALL_REQ; |
---|
465 | |
---|
466 | private = (GdkICPrivate *) ic; |
---|
467 | attr = private->attr; |
---|
468 | |
---|
469 | switch (attr->style & GDK_IM_PREEDIT_MASK) |
---|
470 | { |
---|
471 | case GDK_IM_PREEDIT_AREA: |
---|
472 | mask |= GDK_IC_PREEDIT_AREA_REQ; |
---|
473 | |
---|
474 | preedit_area.x = attr->preedit_area.x; |
---|
475 | preedit_area.y = attr->preedit_area.y; |
---|
476 | preedit_area.width = attr->preedit_area.width; |
---|
477 | preedit_area.height = attr->preedit_area.height; |
---|
478 | |
---|
479 | preedit_attr = XVaCreateNestedList (0, |
---|
480 | XNArea, &preedit_area, |
---|
481 | XNFontSet, |
---|
482 | GDK_FONT_XFONT(attr->preedit_fontset), |
---|
483 | NULL); |
---|
484 | break; |
---|
485 | |
---|
486 | case GDK_IM_PREEDIT_POSITION: |
---|
487 | mask |= GDK_IC_PREEDIT_POSITION_REQ; |
---|
488 | |
---|
489 | preedit_area.x = attr->preedit_area.x; |
---|
490 | preedit_area.y = attr->preedit_area.y; |
---|
491 | preedit_area.width = attr->preedit_area.width; |
---|
492 | preedit_area.height = attr->preedit_area.height; |
---|
493 | |
---|
494 | spot_location.x = attr->spot_location.x; |
---|
495 | spot_location.y = attr->spot_location.y; |
---|
496 | |
---|
497 | preedit_attr = XVaCreateNestedList (0, |
---|
498 | XNArea, &preedit_area, |
---|
499 | XNFontSet, |
---|
500 | GDK_FONT_XFONT(attr->preedit_fontset), |
---|
501 | XNSpotLocation, &spot_location, |
---|
502 | NULL); |
---|
503 | break; |
---|
504 | } |
---|
505 | |
---|
506 | switch (attr->style & GDK_IM_STATUS_MASK) |
---|
507 | { |
---|
508 | case GDK_IM_STATUS_AREA: |
---|
509 | mask |= GDK_IC_STATUS_AREA_REQ; |
---|
510 | |
---|
511 | status_area.x = attr->status_area.x; |
---|
512 | status_area.y = attr->status_area.y; |
---|
513 | status_area.width = attr->status_area.width; |
---|
514 | status_area.height = attr->status_area.height; |
---|
515 | |
---|
516 | status_attr = XVaCreateNestedList (0, |
---|
517 | XNArea, &status_area, |
---|
518 | XNFontSet, |
---|
519 | GDK_FONT_XFONT(attr->status_fontset), |
---|
520 | NULL); |
---|
521 | break; |
---|
522 | } |
---|
523 | |
---|
524 | /* We have to ensure that the client window is actually created on |
---|
525 | * the X server, or XCreateIC fails because the XIM server can't get |
---|
526 | * information about the client window. |
---|
527 | */ |
---|
528 | gdk_flush(); |
---|
529 | |
---|
530 | if (preedit_attr != NULL && status_attr != NULL) |
---|
531 | private->xic = XCreateIC (xim_im, |
---|
532 | XNInputStyle, |
---|
533 | attr->style, |
---|
534 | XNClientWindow, |
---|
535 | GDK_WINDOW_XWINDOW(attr->client_window), |
---|
536 | XNPreeditAttributes, |
---|
537 | preedit_attr, |
---|
538 | XNStatusAttributes, |
---|
539 | status_attr, |
---|
540 | NULL); |
---|
541 | else if (preedit_attr != NULL) |
---|
542 | private->xic = XCreateIC (xim_im, |
---|
543 | XNInputStyle, |
---|
544 | attr->style, |
---|
545 | XNClientWindow, |
---|
546 | GDK_WINDOW_XWINDOW(attr->client_window), |
---|
547 | XNPreeditAttributes, |
---|
548 | preedit_attr, |
---|
549 | NULL); |
---|
550 | else if (status_attr != NULL) |
---|
551 | private->xic = XCreateIC (xim_im, |
---|
552 | XNInputStyle, |
---|
553 | attr->style, |
---|
554 | XNClientWindow, |
---|
555 | GDK_WINDOW_XWINDOW(attr->client_window), |
---|
556 | XNStatusAttributes, |
---|
557 | status_attr, |
---|
558 | NULL); |
---|
559 | else |
---|
560 | private->xic = XCreateIC (xim_im, |
---|
561 | XNInputStyle, |
---|
562 | attr->style, |
---|
563 | XNClientWindow, |
---|
564 | GDK_WINDOW_XWINDOW(attr->client_window), |
---|
565 | NULL); |
---|
566 | |
---|
567 | if (preedit_attr) |
---|
568 | XFree (preedit_attr); |
---|
569 | if (status_attr) |
---|
570 | XFree (status_attr); |
---|
571 | |
---|
572 | if (private->xic == NULL) |
---|
573 | g_warning ("can not create input context with specified input style."); |
---|
574 | else |
---|
575 | gdk_ic_real_set_attr (ic, private->attr, private->mask & ~mask); |
---|
576 | } |
---|
577 | |
---|
578 | GdkIC * |
---|
579 | gdk_ic_new (GdkICAttr *attr, GdkICAttributesType mask) |
---|
580 | { |
---|
581 | GdkICPrivate *private; |
---|
582 | gboolean error = 0; |
---|
583 | GdkICAttributesType invalid_mask; |
---|
584 | GdkICAttr *pattr; |
---|
585 | |
---|
586 | g_return_val_if_fail (attr != NULL, NULL); |
---|
587 | g_return_val_if_fail ((mask & GDK_IC_ALL_REQ) == GDK_IC_ALL_REQ, NULL); |
---|
588 | |
---|
589 | switch (attr->style & GDK_IM_PREEDIT_MASK) |
---|
590 | { |
---|
591 | case 0: |
---|
592 | g_warning ("preedit style is not specified.\n"); |
---|
593 | error = 1; |
---|
594 | break; |
---|
595 | |
---|
596 | case GDK_IM_PREEDIT_AREA: |
---|
597 | if ((mask & GDK_IC_PREEDIT_AREA_REQ) != GDK_IC_PREEDIT_AREA_REQ) |
---|
598 | error = 4; |
---|
599 | break; |
---|
600 | |
---|
601 | case GDK_IM_PREEDIT_POSITION: |
---|
602 | if ((mask & GDK_IC_PREEDIT_POSITION_REQ) != GDK_IC_PREEDIT_POSITION_REQ) |
---|
603 | error = 4; |
---|
604 | break; |
---|
605 | } |
---|
606 | |
---|
607 | switch (attr->style & GDK_IM_STATUS_MASK) |
---|
608 | { |
---|
609 | case 0: |
---|
610 | g_warning ("status style is not specified.\n"); |
---|
611 | error = 2; |
---|
612 | break; |
---|
613 | |
---|
614 | case GDK_IM_STATUS_AREA: |
---|
615 | if ((mask & GDK_IC_STATUS_AREA_REQ) != GDK_IC_STATUS_AREA_REQ) |
---|
616 | error = 8; |
---|
617 | break; |
---|
618 | } |
---|
619 | |
---|
620 | if (error) |
---|
621 | { |
---|
622 | if (error & 12) |
---|
623 | g_warning ("IC attribute is not enough to required input style.\n"); |
---|
624 | return NULL; |
---|
625 | } |
---|
626 | |
---|
627 | if (attr->client_window == NULL || |
---|
628 | ((GdkWindowPrivate *)attr->client_window)->destroyed) |
---|
629 | { |
---|
630 | g_warning ("Client_window is null or already destroyed.\n"); |
---|
631 | return NULL; |
---|
632 | } |
---|
633 | |
---|
634 | private = g_new0 (GdkICPrivate, 1); |
---|
635 | private->attr = pattr = gdk_ic_attr_new (); |
---|
636 | |
---|
637 | gdk_window_ref (attr->client_window); |
---|
638 | pattr->client_window = attr->client_window; |
---|
639 | pattr->style = attr->style; |
---|
640 | private->mask = GDK_IC_STYLE | GDK_IC_CLIENT_WINDOW; |
---|
641 | |
---|
642 | /* XIC is still not created, so following call only copies attributes */ |
---|
643 | invalid_mask = gdk_ic_set_attr ((GdkIC *)private, attr, mask & ~GDK_IC_ALL_REQ); |
---|
644 | |
---|
645 | switch (attr->style & GDK_IM_PREEDIT_MASK) |
---|
646 | { |
---|
647 | case GDK_IM_PREEDIT_AREA: |
---|
648 | if (invalid_mask & GDK_IC_PREEDIT_AREA_REQ) |
---|
649 | error = TRUE; |
---|
650 | break; |
---|
651 | |
---|
652 | case GDK_IM_PREEDIT_POSITION: |
---|
653 | if (invalid_mask & GDK_IC_PREEDIT_POSITION_REQ) |
---|
654 | error = TRUE; |
---|
655 | break; |
---|
656 | } |
---|
657 | |
---|
658 | switch (attr->style & GDK_IM_STATUS_MASK) |
---|
659 | { |
---|
660 | case GDK_IM_STATUS_AREA: |
---|
661 | if (invalid_mask & GDK_IC_STATUS_AREA_REQ) |
---|
662 | error = TRUE; |
---|
663 | break; |
---|
664 | } |
---|
665 | |
---|
666 | if (error == TRUE) |
---|
667 | { |
---|
668 | g_warning ("Essential attributes for required style are invalid.\n"); |
---|
669 | gdk_ic_destroy ((GdkIC *)private); |
---|
670 | return NULL; |
---|
671 | } |
---|
672 | |
---|
673 | if (gdk_im_ready ()) |
---|
674 | gdk_ic_real_new ((GdkIC *)private); |
---|
675 | |
---|
676 | xim_ic_list = g_list_append (xim_ic_list, private); |
---|
677 | |
---|
678 | return (GdkIC *)private; |
---|
679 | } |
---|
680 | |
---|
681 | void |
---|
682 | gdk_ic_destroy (GdkIC *ic) |
---|
683 | { |
---|
684 | GdkICPrivate *private; |
---|
685 | |
---|
686 | g_return_if_fail (ic != NULL); |
---|
687 | |
---|
688 | private = (GdkICPrivate *) ic; |
---|
689 | |
---|
690 | if (gdk_xim_ic == private) |
---|
691 | gdk_im_end (); |
---|
692 | |
---|
693 | GDK_NOTE (XIM, g_message ("ic_destroy %p\n", private->xic)); |
---|
694 | if (private->xic != NULL) |
---|
695 | XDestroyIC (private->xic); |
---|
696 | |
---|
697 | if (private->attr->client_window) |
---|
698 | gdk_window_unref (private->attr->client_window); |
---|
699 | if (private->attr->focus_window) |
---|
700 | gdk_window_unref (private->attr->focus_window); |
---|
701 | |
---|
702 | if (private->attr->preedit_fontset) |
---|
703 | gdk_font_unref (private->attr->preedit_fontset); |
---|
704 | if (private->attr->preedit_pixmap) |
---|
705 | gdk_pixmap_unref (private->attr->preedit_pixmap); |
---|
706 | if (private->attr->preedit_colormap) |
---|
707 | gdk_colormap_unref (private->attr->preedit_colormap); |
---|
708 | |
---|
709 | if (private->attr->status_fontset) |
---|
710 | gdk_font_unref (private->attr->status_fontset); |
---|
711 | if (private->attr->status_pixmap) |
---|
712 | gdk_pixmap_unref (private->attr->status_pixmap); |
---|
713 | if (private->attr->status_colormap) |
---|
714 | gdk_colormap_unref (private->attr->status_colormap); |
---|
715 | |
---|
716 | xim_ic_list = g_list_remove (xim_ic_list, private); |
---|
717 | gdk_ic_attr_destroy (private->attr); |
---|
718 | g_free (private); |
---|
719 | } |
---|
720 | |
---|
721 | GdkIMStyle |
---|
722 | gdk_ic_get_style (GdkIC *ic) |
---|
723 | { |
---|
724 | GdkICPrivate *private; |
---|
725 | |
---|
726 | g_return_val_if_fail (ic != NULL, 0); |
---|
727 | |
---|
728 | private = (GdkICPrivate *) ic; |
---|
729 | |
---|
730 | return private->attr->style; |
---|
731 | } |
---|
732 | |
---|
733 | /* |
---|
734 | * for keeping binary compatibility if member of ic attributes is added. |
---|
735 | */ |
---|
736 | GdkICAttr * |
---|
737 | gdk_ic_attr_new (void) |
---|
738 | { |
---|
739 | return g_new0 (GdkICAttr, 1); |
---|
740 | } |
---|
741 | |
---|
742 | void |
---|
743 | gdk_ic_attr_destroy (GdkICAttr *attr) |
---|
744 | { |
---|
745 | g_return_if_fail (attr != NULL); |
---|
746 | |
---|
747 | g_free (attr); |
---|
748 | } |
---|
749 | |
---|
750 | static GdkICAttributesType |
---|
751 | gdk_ic_real_set_attr (GdkIC *ic, |
---|
752 | GdkICAttr *attr, |
---|
753 | GdkICAttributesType mask) |
---|
754 | { |
---|
755 | GdkICPrivate *private = (GdkICPrivate *)ic; |
---|
756 | XIC xic = private->xic; |
---|
757 | GdkICAttributesType error = 0; |
---|
758 | GdkImArg arg[2] = {{NULL, NULL}, {NULL, NULL}}; |
---|
759 | |
---|
760 | if (mask & GDK_IC_FOCUS_WINDOW) |
---|
761 | { |
---|
762 | if (XSetICValues (xic, XNFocusWindow, |
---|
763 | GDK_WINDOW_XWINDOW(attr->focus_window), NULL) != NULL) |
---|
764 | error |= GDK_IC_FOCUS_WINDOW; |
---|
765 | } |
---|
766 | |
---|
767 | if (mask & GDK_IC_SPOT_LOCATION) |
---|
768 | { |
---|
769 | XPoint point; |
---|
770 | |
---|
771 | point.x = attr->spot_location.x; |
---|
772 | point.y = attr->spot_location.y; |
---|
773 | |
---|
774 | arg->name = XNSpotLocation; |
---|
775 | arg->value = (gpointer) &point; |
---|
776 | |
---|
777 | if (XSetICValues (xic, XNPreeditAttributes, arg, NULL)) |
---|
778 | error |= GDK_IC_SPOT_LOCATION; |
---|
779 | } |
---|
780 | |
---|
781 | if (mask & GDK_IC_LINE_SPACING) |
---|
782 | { |
---|
783 | arg->name = XNLineSpace; |
---|
784 | arg->value = GINT_TO_POINTER( attr->line_spacing ); |
---|
785 | |
---|
786 | if (XSetICValues (xic, XNPreeditAttributes, arg, NULL)) |
---|
787 | error |= GDK_IC_LINE_SPACING; |
---|
788 | } |
---|
789 | |
---|
790 | if (mask & GDK_IC_CURSOR) |
---|
791 | { |
---|
792 | GdkCursorPrivate *cursor = (GdkCursorPrivate *) attr->cursor; |
---|
793 | |
---|
794 | if (XSetICValues (xic, XNCursor, cursor->xcursor, NULL)) |
---|
795 | error |= GDK_IC_CURSOR; |
---|
796 | } |
---|
797 | |
---|
798 | if (mask & GDK_IC_PREEDIT_FONTSET) |
---|
799 | { |
---|
800 | arg->name = XNFontSet; |
---|
801 | arg->value = (gpointer) GDK_FONT_XFONT(attr->preedit_fontset); |
---|
802 | |
---|
803 | if (XSetICValues (xic, XNPreeditAttributes, arg, NULL)) |
---|
804 | error |= GDK_IC_PREEDIT_FONTSET; |
---|
805 | } |
---|
806 | |
---|
807 | if (mask & GDK_IC_PREEDIT_AREA) |
---|
808 | { |
---|
809 | XRectangle rect; |
---|
810 | |
---|
811 | rect.x = attr->preedit_area.x; |
---|
812 | rect.y = attr->preedit_area.y; |
---|
813 | rect.width = attr->preedit_area.width; |
---|
814 | rect.height = attr->preedit_area.height; |
---|
815 | |
---|
816 | arg->name = XNArea; |
---|
817 | arg->value = (gpointer) ▭ |
---|
818 | |
---|
819 | if (XSetICValues (xic, XNPreeditAttributes, arg, NULL)) |
---|
820 | error |= GDK_IC_PREEDIT_AREA; |
---|
821 | } |
---|
822 | |
---|
823 | if (mask & GDK_IC_PREEDIT_AREA_NEEDED) |
---|
824 | { |
---|
825 | XRectangle rect; |
---|
826 | |
---|
827 | rect.x = attr->preedit_area_needed.x; |
---|
828 | rect.y = attr->preedit_area_needed.y; |
---|
829 | rect.width = attr->preedit_area_needed.width; |
---|
830 | rect.height = attr->preedit_area_needed.height; |
---|
831 | |
---|
832 | arg->name = XNArea; |
---|
833 | arg->value = (gpointer) ▭ |
---|
834 | |
---|
835 | if (XSetICValues (xic, XNPreeditAttributes, arg, NULL)) |
---|
836 | error |= GDK_IC_PREEDIT_AREA_NEEDED; |
---|
837 | else |
---|
838 | private->mask &= ~GDK_IC_PREEDIT_AREA_NEEDED; |
---|
839 | } |
---|
840 | |
---|
841 | if (mask & GDK_IC_PREEDIT_FOREGROUND) |
---|
842 | { |
---|
843 | arg->name = XNForeground; |
---|
844 | arg->value = (gpointer) attr->preedit_foreground.pixel; |
---|
845 | |
---|
846 | if (XSetICValues (xic, XNPreeditAttributes, arg, NULL)) |
---|
847 | error |= GDK_IC_PREEDIT_FOREGROUND; |
---|
848 | } |
---|
849 | |
---|
850 | if (mask & GDK_IC_PREEDIT_BACKGROUND) |
---|
851 | { |
---|
852 | arg->name = XNBackground; |
---|
853 | arg->value = (gpointer) attr->preedit_background.pixel; |
---|
854 | |
---|
855 | if (XSetICValues (xic, XNPreeditAttributes, arg, NULL)) |
---|
856 | error |= GDK_IC_PREEDIT_BACKGROUND; |
---|
857 | } |
---|
858 | |
---|
859 | if (mask & GDK_IC_PREEDIT_PIXMAP) |
---|
860 | { |
---|
861 | arg->name = XNBackgroundPixmap; |
---|
862 | arg->value = (gpointer) GDK_WINDOW_XWINDOW(attr->preedit_pixmap); |
---|
863 | |
---|
864 | if (XSetICValues (xic, XNPreeditAttributes, arg, NULL)) |
---|
865 | error |= GDK_IC_PREEDIT_PIXMAP; |
---|
866 | } |
---|
867 | |
---|
868 | if (mask & GDK_IC_PREEDIT_COLORMAP) |
---|
869 | { |
---|
870 | arg->name = XNColormap; |
---|
871 | arg->value = (gpointer) GDK_COLORMAP_XCOLORMAP(attr->preedit_colormap); |
---|
872 | |
---|
873 | if (XSetICValues (xic, XNPreeditAttributes, arg, NULL)) |
---|
874 | error |= GDK_IC_PREEDIT_COLORMAP; |
---|
875 | } |
---|
876 | |
---|
877 | |
---|
878 | if (mask & GDK_IC_STATUS_FONTSET) |
---|
879 | { |
---|
880 | arg->name = XNFontSet; |
---|
881 | arg->value = (gpointer) GDK_FONT_XFONT(attr->status_fontset); |
---|
882 | |
---|
883 | if (XSetICValues (xic, XNStatusAttributes, arg, NULL)) |
---|
884 | error |= GDK_IC_STATUS_FONTSET; |
---|
885 | } |
---|
886 | |
---|
887 | if (mask & GDK_IC_STATUS_AREA) |
---|
888 | { |
---|
889 | XRectangle rect; |
---|
890 | |
---|
891 | rect.x = attr->status_area.x; |
---|
892 | rect.y = attr->status_area.y; |
---|
893 | rect.width = attr->status_area.width; |
---|
894 | rect.height = attr->status_area.height; |
---|
895 | |
---|
896 | arg->name = XNArea; |
---|
897 | arg->value = (gpointer) ▭ |
---|
898 | |
---|
899 | if (XSetICValues (xic, XNStatusAttributes, arg, NULL)) |
---|
900 | error |= GDK_IC_STATUS_AREA; |
---|
901 | } |
---|
902 | |
---|
903 | if (mask & GDK_IC_STATUS_AREA_NEEDED) |
---|
904 | { |
---|
905 | XRectangle rect; |
---|
906 | |
---|
907 | rect.x = attr->status_area_needed.x; |
---|
908 | rect.y = attr->status_area_needed.y; |
---|
909 | rect.width = attr->status_area_needed.width; |
---|
910 | rect.height = attr->status_area_needed.height; |
---|
911 | |
---|
912 | arg->name = XNArea; |
---|
913 | arg->value = (gpointer) ▭ |
---|
914 | |
---|
915 | if (XSetICValues (xic, XNStatusAttributes, arg, NULL)) |
---|
916 | error |= GDK_IC_STATUS_AREA_NEEDED; |
---|
917 | else |
---|
918 | private->mask &= ~GDK_IC_STATUS_AREA_NEEDED; |
---|
919 | } |
---|
920 | |
---|
921 | if (mask & GDK_IC_STATUS_FOREGROUND) |
---|
922 | { |
---|
923 | arg->name = XNForeground; |
---|
924 | arg->value = (gpointer) attr->status_foreground.pixel; |
---|
925 | |
---|
926 | if (XSetICValues (xic, XNStatusAttributes, arg, NULL)) |
---|
927 | error |= GDK_IC_STATUS_FOREGROUND; |
---|
928 | } |
---|
929 | |
---|
930 | if (mask & GDK_IC_STATUS_BACKGROUND) |
---|
931 | { |
---|
932 | arg->name = XNBackground; |
---|
933 | arg->value = (gpointer) attr->status_background.pixel; |
---|
934 | |
---|
935 | if (XSetICValues (xic, XNStatusAttributes, arg, NULL)) |
---|
936 | error |= GDK_IC_STATUS_BACKGROUND; |
---|
937 | } |
---|
938 | |
---|
939 | if (mask & GDK_IC_STATUS_PIXMAP) |
---|
940 | { |
---|
941 | arg->name = XNBackgroundPixmap; |
---|
942 | arg->value = (gpointer) GDK_WINDOW_XWINDOW(attr->status_pixmap); |
---|
943 | |
---|
944 | if (XSetICValues (xic, XNStatusAttributes, arg, NULL)) |
---|
945 | error |= GDK_IC_STATUS_PIXMAP; |
---|
946 | } |
---|
947 | |
---|
948 | if (mask & GDK_IC_STATUS_COLORMAP) |
---|
949 | { |
---|
950 | arg->name = XNColormap; |
---|
951 | arg->value = (gpointer) GDK_COLORMAP_XCOLORMAP(attr->status_colormap); |
---|
952 | |
---|
953 | if (XSetICValues (xic, XNStatusAttributes, arg, NULL)) |
---|
954 | error |= GDK_IC_STATUS_COLORMAP; |
---|
955 | } |
---|
956 | |
---|
957 | return error; |
---|
958 | } |
---|
959 | |
---|
960 | GdkICAttributesType |
---|
961 | gdk_ic_set_attr (GdkIC *ic, |
---|
962 | GdkICAttr *attr, |
---|
963 | GdkICAttributesType mask) |
---|
964 | { |
---|
965 | GdkICPrivate *private; |
---|
966 | GdkICAttr *pattr; |
---|
967 | GdkICAttributesType error = 0; |
---|
968 | GdkICAttributesType newattr = 0; |
---|
969 | |
---|
970 | g_return_val_if_fail (ic != NULL, 0); |
---|
971 | g_return_val_if_fail (attr != NULL, 0); |
---|
972 | |
---|
973 | private = (GdkICPrivate *) ic; |
---|
974 | pattr = private->attr; |
---|
975 | |
---|
976 | /* Check and copy new attributes */ |
---|
977 | |
---|
978 | if (mask & GDK_IC_STYLE) |
---|
979 | { |
---|
980 | g_warning ("input style can be specified only when creating new ic.\n"); |
---|
981 | error |= GDK_IC_STYLE; |
---|
982 | } |
---|
983 | |
---|
984 | if (mask & GDK_IC_FILTER_EVENTS) |
---|
985 | { |
---|
986 | g_warning ("filter events is read only attributes.\n"); |
---|
987 | error |= GDK_IC_FILTER_EVENTS; |
---|
988 | } |
---|
989 | |
---|
990 | if (mask & GDK_IC_CLIENT_WINDOW) |
---|
991 | { |
---|
992 | g_warning ("client window can be specified only when creating new ic.\n"); |
---|
993 | error |= GDK_IC_CLIENT_WINDOW; |
---|
994 | } |
---|
995 | |
---|
996 | if (mask & GDK_IC_FOCUS_WINDOW) |
---|
997 | { |
---|
998 | if (attr->focus_window == NULL) |
---|
999 | { |
---|
1000 | g_warning ("specified focus_window is invalid.\n"); |
---|
1001 | error |= GDK_IC_FOCUS_WINDOW; |
---|
1002 | } |
---|
1003 | else if (pattr->focus_window != attr->focus_window) |
---|
1004 | { |
---|
1005 | if (pattr->focus_window != NULL) |
---|
1006 | gdk_window_unref (pattr->focus_window); |
---|
1007 | if (attr->focus_window != NULL) |
---|
1008 | gdk_window_ref (attr->focus_window); |
---|
1009 | pattr->focus_window = attr->focus_window; |
---|
1010 | newattr |= GDK_IC_FOCUS_WINDOW; |
---|
1011 | } |
---|
1012 | } |
---|
1013 | |
---|
1014 | if (mask & GDK_IC_SPOT_LOCATION) |
---|
1015 | { |
---|
1016 | pattr->spot_location = attr->spot_location; |
---|
1017 | newattr |= GDK_IC_SPOT_LOCATION; |
---|
1018 | } |
---|
1019 | |
---|
1020 | if (mask & GDK_IC_LINE_SPACING) |
---|
1021 | { |
---|
1022 | pattr->line_spacing = attr->line_spacing; |
---|
1023 | newattr |= GDK_IC_LINE_SPACING; |
---|
1024 | } |
---|
1025 | |
---|
1026 | if (mask & GDK_IC_CURSOR) |
---|
1027 | { |
---|
1028 | pattr->cursor = attr->cursor; |
---|
1029 | newattr |= GDK_IC_CURSOR; |
---|
1030 | } |
---|
1031 | |
---|
1032 | if (mask & GDK_IC_PREEDIT_FONTSET) |
---|
1033 | { |
---|
1034 | if (attr->preedit_fontset == NULL || |
---|
1035 | attr->preedit_fontset->type != GDK_FONT_FONTSET) |
---|
1036 | { |
---|
1037 | g_warning ("gdk_font is NULL or not a fontset.\n"); |
---|
1038 | error |= GDK_IC_PREEDIT_FONTSET; |
---|
1039 | } |
---|
1040 | else if (pattr->preedit_fontset != attr->preedit_fontset) |
---|
1041 | { |
---|
1042 | if (pattr->preedit_fontset != NULL) |
---|
1043 | gdk_font_unref (pattr->preedit_fontset); |
---|
1044 | if (attr->preedit_fontset != NULL) |
---|
1045 | gdk_font_ref (attr->preedit_fontset); |
---|
1046 | pattr->preedit_fontset = attr->preedit_fontset; |
---|
1047 | newattr |= GDK_IC_PREEDIT_FONTSET; |
---|
1048 | } |
---|
1049 | } |
---|
1050 | |
---|
1051 | if (mask & GDK_IC_PREEDIT_AREA) |
---|
1052 | { |
---|
1053 | pattr->preedit_area = attr->preedit_area; |
---|
1054 | newattr |= GDK_IC_PREEDIT_AREA; |
---|
1055 | } |
---|
1056 | |
---|
1057 | if (mask & GDK_IC_PREEDIT_AREA_NEEDED) |
---|
1058 | { |
---|
1059 | if (attr->preedit_area_needed.width == 0 || |
---|
1060 | attr->preedit_area_needed.height == 0) |
---|
1061 | { |
---|
1062 | g_warning ("width and height of preedit_area_needed must be non 0.\n"); |
---|
1063 | error |= GDK_IC_PREEDIT_AREA_NEEDED; |
---|
1064 | } |
---|
1065 | else |
---|
1066 | { |
---|
1067 | pattr->preedit_area_needed = attr->preedit_area_needed; |
---|
1068 | newattr |= GDK_IC_PREEDIT_AREA_NEEDED; |
---|
1069 | } |
---|
1070 | } |
---|
1071 | |
---|
1072 | if (mask & GDK_IC_PREEDIT_FOREGROUND) |
---|
1073 | { |
---|
1074 | pattr->preedit_foreground = attr->preedit_foreground; |
---|
1075 | newattr |= GDK_IC_PREEDIT_FOREGROUND; |
---|
1076 | } |
---|
1077 | |
---|
1078 | if (mask & GDK_IC_PREEDIT_BACKGROUND) |
---|
1079 | { |
---|
1080 | pattr->preedit_background = attr->preedit_background; |
---|
1081 | newattr |= GDK_IC_PREEDIT_BACKGROUND; |
---|
1082 | } |
---|
1083 | |
---|
1084 | if (mask & GDK_IC_PREEDIT_PIXMAP) |
---|
1085 | { |
---|
1086 | if (attr->preedit_pixmap != NULL && |
---|
1087 | ((GdkPixmapPrivate *)attr->preedit_pixmap)->destroyed) |
---|
1088 | { |
---|
1089 | g_warning ("Preedit pixmap is already destroyed.\n"); |
---|
1090 | error |= GDK_IC_PREEDIT_PIXMAP; |
---|
1091 | } |
---|
1092 | else |
---|
1093 | { |
---|
1094 | if (pattr->preedit_pixmap != attr->preedit_pixmap) |
---|
1095 | { |
---|
1096 | if (pattr->preedit_pixmap != NULL) |
---|
1097 | gdk_pixmap_unref (pattr->preedit_pixmap); |
---|
1098 | if (attr->preedit_pixmap) |
---|
1099 | gdk_pixmap_ref (attr->preedit_pixmap); |
---|
1100 | pattr->preedit_pixmap = attr->preedit_pixmap; |
---|
1101 | newattr |= GDK_IC_PREEDIT_PIXMAP; |
---|
1102 | } |
---|
1103 | } |
---|
1104 | } |
---|
1105 | |
---|
1106 | if (mask & GDK_IC_PREEDIT_COLORMAP) |
---|
1107 | { |
---|
1108 | if (pattr->preedit_colormap != attr->preedit_colormap) |
---|
1109 | { |
---|
1110 | if (pattr->preedit_colormap != NULL) |
---|
1111 | gdk_colormap_unref (pattr->preedit_colormap); |
---|
1112 | if (attr->preedit_colormap != NULL) |
---|
1113 | gdk_colormap_ref (attr->preedit_colormap); |
---|
1114 | pattr->preedit_colormap = attr->preedit_colormap; |
---|
1115 | newattr |= GDK_IC_PREEDIT_COLORMAP; |
---|
1116 | } |
---|
1117 | } |
---|
1118 | |
---|
1119 | if (mask & GDK_IC_STATUS_FONTSET) |
---|
1120 | { |
---|
1121 | if (attr->status_fontset == NULL || |
---|
1122 | attr->status_fontset->type != GDK_FONT_FONTSET) |
---|
1123 | { |
---|
1124 | g_warning ("gdk_font is NULL or not a fontset.\n"); |
---|
1125 | error |= GDK_IC_STATUS_FONTSET; |
---|
1126 | } |
---|
1127 | else if (pattr->status_fontset != attr->status_fontset) |
---|
1128 | { |
---|
1129 | if (pattr->status_fontset != NULL) |
---|
1130 | gdk_font_unref (pattr->status_fontset); |
---|
1131 | if (attr->status_fontset != NULL) |
---|
1132 | gdk_font_ref (attr->status_fontset); |
---|
1133 | pattr->status_fontset = attr->status_fontset; |
---|
1134 | newattr |= GDK_IC_STATUS_FONTSET; |
---|
1135 | } |
---|
1136 | } |
---|
1137 | |
---|
1138 | if (mask & GDK_IC_STATUS_AREA) |
---|
1139 | { |
---|
1140 | pattr->status_area = attr->status_area; |
---|
1141 | newattr |= GDK_IC_STATUS_AREA; |
---|
1142 | } |
---|
1143 | |
---|
1144 | if (mask & GDK_IC_STATUS_AREA_NEEDED) |
---|
1145 | { |
---|
1146 | if (attr->status_area_needed.width == 0 || |
---|
1147 | attr->status_area_needed.height == 0) |
---|
1148 | { |
---|
1149 | g_warning ("width and height of status_area_needed must be non 0.\n"); |
---|
1150 | error |= GDK_IC_STATUS_AREA_NEEDED; |
---|
1151 | } |
---|
1152 | else |
---|
1153 | { |
---|
1154 | pattr->status_area_needed = attr->status_area_needed; |
---|
1155 | newattr |= GDK_IC_STATUS_AREA_NEEDED; |
---|
1156 | } |
---|
1157 | } |
---|
1158 | |
---|
1159 | if (mask & GDK_IC_STATUS_FOREGROUND) |
---|
1160 | { |
---|
1161 | pattr->status_foreground = attr->status_foreground; |
---|
1162 | newattr |= GDK_IC_STATUS_FOREGROUND; |
---|
1163 | } |
---|
1164 | |
---|
1165 | if (mask & GDK_IC_STATUS_BACKGROUND) |
---|
1166 | { |
---|
1167 | pattr->status_background = attr->status_background; |
---|
1168 | newattr |= GDK_IC_STATUS_BACKGROUND; |
---|
1169 | } |
---|
1170 | |
---|
1171 | if (mask & GDK_IC_STATUS_PIXMAP) |
---|
1172 | { |
---|
1173 | if (attr->status_pixmap != NULL && |
---|
1174 | ((GdkPixmapPrivate *)attr->status_pixmap)->destroyed) |
---|
1175 | { |
---|
1176 | g_warning ("Preedit pixmap is already destroyed.\n"); |
---|
1177 | error |= GDK_IC_STATUS_PIXMAP; |
---|
1178 | } |
---|
1179 | else |
---|
1180 | { |
---|
1181 | if (pattr->status_pixmap != attr->status_pixmap) |
---|
1182 | { |
---|
1183 | if (pattr->status_pixmap != NULL) |
---|
1184 | gdk_pixmap_unref (pattr->status_pixmap); |
---|
1185 | if (attr->status_pixmap) |
---|
1186 | gdk_pixmap_ref (attr->status_pixmap); |
---|
1187 | pattr->status_pixmap = attr->status_pixmap; |
---|
1188 | newattr |= GDK_IC_STATUS_PIXMAP; |
---|
1189 | } |
---|
1190 | } |
---|
1191 | } |
---|
1192 | |
---|
1193 | if (mask & GDK_IC_STATUS_COLORMAP) |
---|
1194 | { |
---|
1195 | if (pattr->status_colormap != attr->status_colormap) |
---|
1196 | { |
---|
1197 | if (pattr->status_colormap != NULL) |
---|
1198 | gdk_colormap_unref (pattr->status_colormap); |
---|
1199 | if (attr->status_colormap != NULL) |
---|
1200 | gdk_colormap_ref (attr->status_colormap); |
---|
1201 | pattr->status_colormap = attr->status_colormap; |
---|
1202 | newattr |= GDK_IC_STATUS_COLORMAP; |
---|
1203 | } |
---|
1204 | } |
---|
1205 | |
---|
1206 | if (private->xic == NULL) |
---|
1207 | return error; |
---|
1208 | |
---|
1209 | error |= gdk_ic_real_set_attr (ic, pattr, newattr); |
---|
1210 | |
---|
1211 | return error; |
---|
1212 | } |
---|
1213 | |
---|
1214 | GdkICAttributesType |
---|
1215 | gdk_ic_get_attr (GdkIC *ic, |
---|
1216 | GdkICAttr *attr, |
---|
1217 | GdkICAttributesType mask) |
---|
1218 | { |
---|
1219 | GdkICPrivate *private; |
---|
1220 | GdkICAttr *pattr; |
---|
1221 | GdkICAttributesType known, unknown = 0; |
---|
1222 | |
---|
1223 | g_return_val_if_fail (ic != NULL, -1); |
---|
1224 | g_return_val_if_fail (attr != NULL, -1); |
---|
1225 | |
---|
1226 | private = (GdkICPrivate *) ic; |
---|
1227 | pattr = private->attr; |
---|
1228 | |
---|
1229 | known = mask & private->mask; |
---|
1230 | |
---|
1231 | if (known & GDK_IC_STYLE) |
---|
1232 | attr->style = pattr->style; |
---|
1233 | if (known & GDK_IC_CLIENT_WINDOW) |
---|
1234 | attr->client_window = pattr->client_window; |
---|
1235 | if (known & GDK_IC_FOCUS_WINDOW) |
---|
1236 | attr->focus_window = pattr->focus_window; |
---|
1237 | if (known & GDK_IC_FILTER_EVENTS) |
---|
1238 | attr->filter_events = pattr->filter_events; |
---|
1239 | if (known & GDK_IC_LINE_SPACING) |
---|
1240 | attr->line_spacing = pattr->line_spacing; |
---|
1241 | if (known & GDK_IC_CURSOR) |
---|
1242 | attr->cursor = pattr->cursor; |
---|
1243 | |
---|
1244 | if (known & GDK_IC_PREEDIT_FONTSET) |
---|
1245 | attr->preedit_fontset = pattr->preedit_fontset; |
---|
1246 | if (known & GDK_IC_PREEDIT_AREA) |
---|
1247 | attr->preedit_area = pattr->preedit_area; |
---|
1248 | if (known & GDK_IC_PREEDIT_AREA_NEEDED) |
---|
1249 | attr->preedit_area_needed = pattr->preedit_area_needed; |
---|
1250 | if (known & GDK_IC_PREEDIT_FOREGROUND) |
---|
1251 | attr->preedit_foreground = pattr->preedit_foreground; |
---|
1252 | if (known & GDK_IC_PREEDIT_BACKGROUND) |
---|
1253 | attr->preedit_background = pattr->preedit_background; |
---|
1254 | if (known & GDK_IC_PREEDIT_PIXMAP) |
---|
1255 | attr->preedit_pixmap = pattr->preedit_pixmap; |
---|
1256 | if (known & GDK_IC_PREEDIT_COLORMAP) |
---|
1257 | attr->preedit_colormap = pattr->preedit_colormap; |
---|
1258 | |
---|
1259 | if (known & GDK_IC_STATUS_FONTSET) |
---|
1260 | attr->status_fontset = pattr->status_fontset; |
---|
1261 | if (known & GDK_IC_STATUS_AREA) |
---|
1262 | attr->status_area = pattr->status_area; |
---|
1263 | if (known & GDK_IC_STATUS_AREA_NEEDED) |
---|
1264 | attr->status_area_needed = pattr->status_area_needed; |
---|
1265 | if (known & GDK_IC_STATUS_FOREGROUND) |
---|
1266 | attr->status_foreground = pattr->status_foreground; |
---|
1267 | if (known & GDK_IC_STATUS_BACKGROUND) |
---|
1268 | attr->status_background = pattr->status_background; |
---|
1269 | if (known & GDK_IC_STATUS_PIXMAP) |
---|
1270 | attr->status_pixmap = pattr->status_pixmap; |
---|
1271 | if (known & GDK_IC_STATUS_COLORMAP) |
---|
1272 | attr->status_colormap = pattr->status_colormap; |
---|
1273 | |
---|
1274 | if (private->xic) |
---|
1275 | { |
---|
1276 | unknown = mask & ~(private->mask); |
---|
1277 | |
---|
1278 | if (unknown & GDK_IC_FOCUS_WINDOW) |
---|
1279 | attr->focus_window = pattr->client_window; |
---|
1280 | if (unknown & GDK_IC_FILTER_EVENTS) |
---|
1281 | { |
---|
1282 | gdk_ic_get_events (ic); |
---|
1283 | attr->filter_events = pattr->filter_events; |
---|
1284 | } |
---|
1285 | if (mask & GDK_IC_SPOT_LOCATION) |
---|
1286 | { |
---|
1287 | XPoint point; |
---|
1288 | XVaNestedList *list; |
---|
1289 | |
---|
1290 | list = XVaCreateNestedList (0, XNSpotLocation, &point, NULL); |
---|
1291 | if (XGetICValues (private->xic, XNPreeditAttributes, list, NULL)) |
---|
1292 | unknown &= ~GDK_IC_SPOT_LOCATION; |
---|
1293 | else |
---|
1294 | { |
---|
1295 | pattr->spot_location.x = point.x; |
---|
1296 | pattr->spot_location.y = point.y; |
---|
1297 | private->mask |= GDK_IC_SPOT_LOCATION; |
---|
1298 | |
---|
1299 | attr->spot_location = pattr->spot_location; |
---|
1300 | } |
---|
1301 | XFree (list); |
---|
1302 | } |
---|
1303 | if (unknown & GDK_IC_PREEDIT_AREA_NEEDED) |
---|
1304 | { |
---|
1305 | XRectangle rect; |
---|
1306 | XVaNestedList *list; |
---|
1307 | |
---|
1308 | list = XVaCreateNestedList (0, XNAreaNeeded, &rect, NULL); |
---|
1309 | if (XGetICValues (private->xic, XNPreeditAttributes, list, NULL)) |
---|
1310 | unknown &= ~GDK_IC_PREEDIT_AREA_NEEDED; |
---|
1311 | else |
---|
1312 | { |
---|
1313 | pattr->preedit_area_needed.x = rect.x; |
---|
1314 | pattr->preedit_area_needed.y = rect.y; |
---|
1315 | pattr->preedit_area_needed.width = rect.width; |
---|
1316 | pattr->preedit_area_needed.height = rect.height; |
---|
1317 | private->mask |= GDK_IC_PREEDIT_AREA_NEEDED; |
---|
1318 | |
---|
1319 | attr->preedit_area = pattr->preedit_area; |
---|
1320 | } |
---|
1321 | XFree (list); |
---|
1322 | } |
---|
1323 | if (unknown & GDK_IC_STATUS_AREA_NEEDED) |
---|
1324 | { |
---|
1325 | XRectangle rect; |
---|
1326 | XVaNestedList *list; |
---|
1327 | |
---|
1328 | list = XVaCreateNestedList (0, XNAreaNeeded, &rect, NULL); |
---|
1329 | if (XGetICValues (private->xic, XNStatusAttributes, list, NULL)) |
---|
1330 | unknown &= ~GDK_IC_STATUS_AREA_NEEDED; |
---|
1331 | else |
---|
1332 | { |
---|
1333 | pattr->status_area_needed.x = rect.x; |
---|
1334 | pattr->status_area_needed.y = rect.y; |
---|
1335 | pattr->status_area_needed.width = rect.width; |
---|
1336 | pattr->status_area_needed.height = rect.height; |
---|
1337 | private->mask |= GDK_IC_STATUS_AREA_NEEDED; |
---|
1338 | |
---|
1339 | attr->status_area = pattr->status_area; |
---|
1340 | } |
---|
1341 | XFree (list); |
---|
1342 | } |
---|
1343 | } |
---|
1344 | |
---|
1345 | return mask & ~known & ~unknown; |
---|
1346 | } |
---|
1347 | |
---|
1348 | GdkEventMask |
---|
1349 | gdk_ic_get_events (GdkIC *ic) |
---|
1350 | { |
---|
1351 | GdkEventMask mask; |
---|
1352 | glong xmask; |
---|
1353 | glong bit; |
---|
1354 | GdkICPrivate *private; |
---|
1355 | gint i; |
---|
1356 | |
---|
1357 | /* From gdkwindow.c */ |
---|
1358 | |
---|
1359 | g_return_val_if_fail (ic != NULL, 0); |
---|
1360 | |
---|
1361 | private = (GdkICPrivate *) ic; |
---|
1362 | |
---|
1363 | if (private->mask & GDK_IC_FILTER_EVENTS) |
---|
1364 | return private->attr->filter_events; |
---|
1365 | |
---|
1366 | if (XGetICValues (private->xic, XNFilterEvents, &xmask, NULL) != NULL) |
---|
1367 | { |
---|
1368 | GDK_NOTE (XIM, g_warning ("Call to XGetICValues: %s failed", XNFilterEvents)); |
---|
1369 | return 0; |
---|
1370 | } |
---|
1371 | |
---|
1372 | mask = 0; |
---|
1373 | for (i=0, bit=2; i < gdk_nevent_masks; i++, bit <<= 1) |
---|
1374 | if (xmask & gdk_event_mask_table [i]) |
---|
1375 | { |
---|
1376 | mask |= bit; |
---|
1377 | xmask &= ~ gdk_event_mask_table [i]; |
---|
1378 | } |
---|
1379 | |
---|
1380 | if (xmask) |
---|
1381 | g_warning ("ic requires events not supported by the application (%#04lx)", xmask); |
---|
1382 | |
---|
1383 | private->attr->filter_events = mask; |
---|
1384 | private->mask |= GDK_IC_FILTER_EVENTS; |
---|
1385 | |
---|
1386 | return mask; |
---|
1387 | } |
---|
1388 | |
---|
1389 | void |
---|
1390 | gdk_ic_cleanup (void) |
---|
1391 | { |
---|
1392 | gint destroyed; |
---|
1393 | |
---|
1394 | destroyed = 0; |
---|
1395 | while (xim_ic_list != NULL) |
---|
1396 | { |
---|
1397 | gdk_ic_destroy ((GdkIC *) xim_ic_list->data); |
---|
1398 | destroyed ++; |
---|
1399 | } |
---|
1400 | #ifdef G_ENABLE_DEBUG |
---|
1401 | if ((gdk_debug_flags & GDK_DEBUG_XIM) && destroyed > 0) |
---|
1402 | { |
---|
1403 | g_warning ("Cleaned up %i IC(s)\n", destroyed); |
---|
1404 | } |
---|
1405 | #endif /* G_ENABLE_DEBUG */ |
---|
1406 | } |
---|
1407 | |
---|
1408 | #else /* !USE_XIM */ |
---|
1409 | |
---|
1410 | void |
---|
1411 | gdk_im_begin (GdkIC *ic, GdkWindow* window) |
---|
1412 | { |
---|
1413 | } |
---|
1414 | |
---|
1415 | void |
---|
1416 | gdk_im_end (void) |
---|
1417 | { |
---|
1418 | } |
---|
1419 | |
---|
1420 | GdkIMStyle |
---|
1421 | gdk_im_decide_style (GdkIMStyle supported_style) |
---|
1422 | { |
---|
1423 | return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE; |
---|
1424 | } |
---|
1425 | |
---|
1426 | GdkIMStyle |
---|
1427 | gdk_im_set_best_style (GdkIMStyle style) |
---|
1428 | { |
---|
1429 | return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE; |
---|
1430 | } |
---|
1431 | |
---|
1432 | gint |
---|
1433 | gdk_im_ready (void) |
---|
1434 | { |
---|
1435 | return FALSE; |
---|
1436 | } |
---|
1437 | |
---|
1438 | GdkIC * |
---|
1439 | gdk_ic_new (GdkICAttr *attr, GdkICAttributesType mask) |
---|
1440 | { |
---|
1441 | return NULL; |
---|
1442 | } |
---|
1443 | |
---|
1444 | void |
---|
1445 | gdk_ic_destroy (GdkIC *ic) |
---|
1446 | { |
---|
1447 | } |
---|
1448 | |
---|
1449 | GdkIMStyle |
---|
1450 | gdk_ic_get_style (GdkIC *ic) |
---|
1451 | { |
---|
1452 | return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE; |
---|
1453 | } |
---|
1454 | |
---|
1455 | GdkICAttr * |
---|
1456 | gdk_ic_attr_new (void) |
---|
1457 | { |
---|
1458 | return NULL; |
---|
1459 | } |
---|
1460 | |
---|
1461 | void |
---|
1462 | gdk_ic_attr_destroy (GdkICAttr *attr) |
---|
1463 | { |
---|
1464 | } |
---|
1465 | |
---|
1466 | void |
---|
1467 | gdk_ic_set_values (GdkIC *ic, ...) |
---|
1468 | { |
---|
1469 | } |
---|
1470 | |
---|
1471 | void |
---|
1472 | gdk_ic_get_values (GdkIC *ic, ...) |
---|
1473 | { |
---|
1474 | } |
---|
1475 | |
---|
1476 | GdkICAttributesType |
---|
1477 | gdk_ic_set_attr (GdkIC *ic, GdkICAttr *attr, GdkICAttributesType mask) |
---|
1478 | { |
---|
1479 | return 0; |
---|
1480 | } |
---|
1481 | |
---|
1482 | GdkICAttributesType |
---|
1483 | gdk_ic_get_attr (GdkIC *ic, GdkICAttr *attr, GdkICAttributesType mask) |
---|
1484 | { |
---|
1485 | return 0; |
---|
1486 | } |
---|
1487 | |
---|
1488 | GdkEventMask |
---|
1489 | gdk_ic_get_events (GdkIC *ic) |
---|
1490 | { |
---|
1491 | return 0; |
---|
1492 | } |
---|
1493 | |
---|
1494 | #endif /* USE_XIM */ |
---|
1495 | |
---|
1496 | /* |
---|
1497 | * gdk_wcstombs_len |
---|
1498 | * |
---|
1499 | * Returns a multi-byte string converted from the specified array |
---|
1500 | * of wide characters. The string is newly allocated. The array of |
---|
1501 | * wide characters is nul-terminated, if len < 0 |
---|
1502 | */ |
---|
1503 | |
---|
1504 | #ifdef USE_NATIVE_LOCALE |
---|
1505 | gchar * |
---|
1506 | _gdk_wcstombs_len (const GdkWChar *src, |
---|
1507 | gint src_len) |
---|
1508 | { |
---|
1509 | gint len = 0; |
---|
1510 | gint i; |
---|
1511 | gchar *result = NULL; |
---|
1512 | gchar buf[16]; |
---|
1513 | gchar *p; |
---|
1514 | |
---|
1515 | if (MB_CUR_MAX <= 16) |
---|
1516 | p = buf; |
---|
1517 | else |
---|
1518 | p = g_malloc (MB_CUR_MAX); /* Presumably never hit */ |
---|
1519 | |
---|
1520 | wctomb (NULL, 0); |
---|
1521 | |
---|
1522 | for (i=0; (src_len < 0 || i < src_len) && src[i]; i++) |
---|
1523 | { |
---|
1524 | gint charlen = wctomb (p, src[i]); |
---|
1525 | if (charlen < 0) |
---|
1526 | goto out; |
---|
1527 | |
---|
1528 | len += charlen; |
---|
1529 | } |
---|
1530 | |
---|
1531 | result = g_malloc (len + 1); |
---|
1532 | |
---|
1533 | /* Old versions of GNU libc apparently can't handle a max of 0 here |
---|
1534 | */ |
---|
1535 | if (len > 0) |
---|
1536 | wcstombs (result, (wchar_t *)src, len); |
---|
1537 | |
---|
1538 | result[len] = '\0'; |
---|
1539 | |
---|
1540 | out: |
---|
1541 | if (p != buf) |
---|
1542 | g_free (p); |
---|
1543 | |
---|
1544 | return result; |
---|
1545 | } |
---|
1546 | #else /* !USE_NATIVE_LOCALE */ |
---|
1547 | |
---|
1548 | gchar * |
---|
1549 | _gdk_wcstombs_len (const GdkWChar *src, |
---|
1550 | int len) |
---|
1551 | { |
---|
1552 | gchar *mbstr = NULL; |
---|
1553 | gint length; |
---|
1554 | |
---|
1555 | if (len < 0) |
---|
1556 | { |
---|
1557 | length = 0; |
---|
1558 | |
---|
1559 | while (src[length] != 0) |
---|
1560 | length++; |
---|
1561 | } |
---|
1562 | else |
---|
1563 | length = len; |
---|
1564 | |
---|
1565 | if (gdk_use_mb) |
---|
1566 | { |
---|
1567 | XTextProperty tpr; |
---|
1568 | wchar_t *src_wc; |
---|
1569 | |
---|
1570 | /* The len < 0 part is to ensure nul termination |
---|
1571 | */ |
---|
1572 | if (len < 0 && sizeof(wchar_t) == sizeof(GdkWChar)) |
---|
1573 | { |
---|
1574 | src_wc = (wchar_t *)src; |
---|
1575 | } |
---|
1576 | else |
---|
1577 | { |
---|
1578 | gint i; |
---|
1579 | |
---|
1580 | src_wc = g_new (wchar_t, length + 1); |
---|
1581 | |
---|
1582 | for (i = 0; i < length; i++) |
---|
1583 | src_wc[i] = src[i]; |
---|
1584 | |
---|
1585 | src_wc[i] = 0; |
---|
1586 | } |
---|
1587 | |
---|
1588 | if (XwcTextListToTextProperty (gdk_display, &src_wc, 1, |
---|
1589 | XTextStyle, &tpr) == Success) |
---|
1590 | { |
---|
1591 | /* |
---|
1592 | * We must copy the string into an area allocated by glib, because |
---|
1593 | * the string 'tpr.value' must be freed by XFree(). |
---|
1594 | */ |
---|
1595 | mbstr = g_strdup(tpr.value); |
---|
1596 | XFree (tpr.value); |
---|
1597 | } |
---|
1598 | |
---|
1599 | if (src_wc != (wchar_t *)src) |
---|
1600 | g_free (src_wc); |
---|
1601 | } |
---|
1602 | else |
---|
1603 | { |
---|
1604 | gint i; |
---|
1605 | |
---|
1606 | mbstr = g_new (gchar, length + 1); |
---|
1607 | |
---|
1608 | for (i=0; i < length; i++) |
---|
1609 | mbstr[i] = src[i]; |
---|
1610 | |
---|
1611 | mbstr[i] = '\0'; |
---|
1612 | } |
---|
1613 | |
---|
1614 | return mbstr; |
---|
1615 | } |
---|
1616 | #endif /* !USE_NATIVE_LOCALE */ |
---|
1617 | |
---|
1618 | /* |
---|
1619 | * gdk_wcstombs |
---|
1620 | * |
---|
1621 | * Returns a multi-byte string converted from the specified array |
---|
1622 | * of wide characters. The string is newly allocated. The array of |
---|
1623 | * wide characters must be null-terminated. If the conversion is |
---|
1624 | * failed, it returns NULL. |
---|
1625 | */ |
---|
1626 | gchar * |
---|
1627 | gdk_wcstombs (const GdkWChar *src) |
---|
1628 | { |
---|
1629 | return _gdk_wcstombs_len (src, -1); |
---|
1630 | } |
---|
1631 | |
---|
1632 | /* |
---|
1633 | * gdk_mbstowcs |
---|
1634 | * |
---|
1635 | * Converts the specified string into wide characters, and, returns the |
---|
1636 | * number of wide characters written. The string 'src' must be |
---|
1637 | * null-terminated. If the conversion is failed, it returns -1. |
---|
1638 | */ |
---|
1639 | gint |
---|
1640 | gdk_mbstowcs (GdkWChar *dest, const gchar *src, gint dest_max) |
---|
1641 | { |
---|
1642 | #ifdef USE_NATIVE_LOCALE |
---|
1643 | return mbstowcs ((wchar_t *)dest, src, dest_max); |
---|
1644 | #else |
---|
1645 | if (gdk_use_mb) |
---|
1646 | { |
---|
1647 | XTextProperty tpr; |
---|
1648 | wchar_t **wstrs, *wstr_src; |
---|
1649 | gint num_wstrs; |
---|
1650 | gint len_cpy; |
---|
1651 | if (XmbTextListToTextProperty (gdk_display, (char **)&src, 1, XTextStyle, |
---|
1652 | &tpr) |
---|
1653 | != Success) |
---|
1654 | { |
---|
1655 | /* NoMem or LocaleNotSupp */ |
---|
1656 | return -1; |
---|
1657 | } |
---|
1658 | if (XwcTextPropertyToTextList (gdk_display, &tpr, &wstrs, &num_wstrs) |
---|
1659 | != Success) |
---|
1660 | { |
---|
1661 | /* InvalidChar */ |
---|
1662 | XFree(tpr.value); |
---|
1663 | return -1; |
---|
1664 | } |
---|
1665 | XFree(tpr.value); |
---|
1666 | if (num_wstrs == 0) |
---|
1667 | return 0; |
---|
1668 | wstr_src = wstrs[0]; |
---|
1669 | for (len_cpy=0; len_cpy<dest_max && wstr_src[len_cpy]; len_cpy++) |
---|
1670 | dest[len_cpy] = wstr_src[len_cpy]; |
---|
1671 | XwcFreeStringList (wstrs); |
---|
1672 | return len_cpy; |
---|
1673 | } |
---|
1674 | else |
---|
1675 | { |
---|
1676 | gint i; |
---|
1677 | |
---|
1678 | for (i=0; i<dest_max && src[i]; i++) |
---|
1679 | dest[i] = (guchar)src[i]; |
---|
1680 | |
---|
1681 | return i; |
---|
1682 | } |
---|
1683 | #endif |
---|
1684 | } |
---|