1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
20 #include <X11/Xlocale.h>
22 #include "gdkprivate.h"
26 /* If this variable is FALSE, it indicates that we should
27 * avoid trying to use multibyte conversion functions and
28 * assume everything is 1-byte per character
30 static gboolean gdk_use_mb;
35 #include <X11/Xresource.h>
37 /* The following routines duplicate functionality in Xlib to
38 * translate from varargs to X's internal opaque XVaNestedList.
40 * If all vendors have stuck close to the reference implementation,
41 * then we should hopefully be OK.
49 static void gdk_im_instantiate_cb (Display *display,
52 static void gdk_im_destroy_cb (XIM im,
56 static void gdk_ic_real_new (GdkIC *ic);
58 static GdkICAttributesType gdk_ic_real_set_attr (GdkIC *ic,
60 GdkICAttributesType mask);
62 static XIM xim_im; /* global IM */
63 static XIMStyles* xim_styles; /* im supports these styles */
64 static XIMStyle xim_best_allowed_style;
65 static GList* xim_ic_list;
70 *--------------------------------------------------------------
79 *--------------------------------------------------------------
86 gchar *current_locale;
90 if (!setlocale (LC_ALL,""))
91 g_message ("locale not supported by C library");
93 if (!XSupportsLocale ())
95 g_message ("locale not supported by Xlib, locale set to C");
96 setlocale (LC_ALL, "C");
99 if (!XSetLocaleModifiers (""))
100 g_message ("can not set locale modifiers");
102 current_locale = setlocale (LC_ALL, NULL);
104 if ((strcmp (current_locale, "C")) && (strcmp (current_locale, "POSIX")))
109 /* Detect GNU libc, where mb == UTF8. Not useful unless it's
110 * really a UTF8 locale. The below still probably will
111 * screw up on Greek, Cyrillic, etc, encoded as UTF8.
114 if ((MB_CUR_MAX == 2) &&
115 (mbstowcs (&result, "\xdd\xa5", 1) > 0) &&
118 if ((strlen (current_locale) < 4) ||
119 g_strcasecmp (current_locale + strlen(current_locale) - 4, "utf8"))
122 #endif /* X_LOCALE */
126 g_message ("%s multi-byte string functions.",
127 gdk_use_mb ? "Using" : "Not using"));
129 return current_locale;
135 *--------------------------------------------------------------
138 * Begin using input method with XIM Protocol(X11R6 standard)
141 * "ic" is the "Input Context" which is created by gtk_ic_new.
142 * The input area is specified with "window".
145 * The gdk's event handling routine is switched to XIM based routine.
146 * XIM based routine uses XFilterEvent to get rid of events used by IM,
147 * and uses XmbLookupString instead of XLookupString.
151 *--------------------------------------------------------------
155 gdk_im_begin (GdkIC *ic, GdkWindow* window)
157 GdkICPrivate *private;
160 g_return_if_fail (ic != NULL);
162 private = (GdkICPrivate *) ic;
164 attr.focus_window = window;
165 gdk_ic_set_attr (ic, &attr, GDK_IC_FOCUS_WINDOW);
167 if (private != gdk_xim_ic)
172 XSetICFocus (private->xic);
173 GDK_NOTE (XIM, g_print ("im_begin icfocus : %p(%ld)\n",
175 GDK_WINDOW_XWINDOW(private->attr->focus_window)));
178 gdk_xim_ic = private;
179 gdk_xim_window = window;
183 *--------------------------------------------------------------
186 * End using input method with XIM Protocol(X11R6 standard)
191 * The gdk's event handling routine is switched to normal routine.
192 * User should call this function before ic and window will be destroyed.
196 *--------------------------------------------------------------
202 if (gdk_xim_ic && gdk_xim_ic->xic)
204 XUnsetICFocus (gdk_xim_ic->xic);
205 GDK_NOTE (XIM, g_print ("im_end unfocus : %p\n", gdk_xim_ic->xic));
208 gdk_xim_window = NULL;
212 gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
214 GdkIMStyle s1, s2, u;
216 if (style1 == 0) return style2;
217 if (style2 == 0) return style1;
218 if ((style1 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK))
219 == (style2 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK)))
222 s1 = style1 & GDK_IM_PREEDIT_MASK;
223 s2 = style2 & GDK_IM_PREEDIT_MASK;
226 if (u & GDK_IM_PREEDIT_CALLBACKS)
227 return (s1 == GDK_IM_PREEDIT_CALLBACKS)? style1:style2;
228 else if (u & GDK_IM_PREEDIT_POSITION)
229 return (s1 == GDK_IM_PREEDIT_POSITION)? style1:style2;
230 else if (u & GDK_IM_PREEDIT_AREA)
231 return (s1 == GDK_IM_PREEDIT_AREA)? style1:style2;
232 else if (u & GDK_IM_PREEDIT_NOTHING)
233 return (s1 == GDK_IM_PREEDIT_NOTHING)? style1:style2;
235 s1 = style1 & GDK_IM_STATUS_MASK;
236 s2 = style2 & GDK_IM_STATUS_MASK;
238 if ( u & GDK_IM_STATUS_CALLBACKS)
239 return (s1 == GDK_IM_STATUS_CALLBACKS)? style1:style2;
240 else if ( u & GDK_IM_STATUS_AREA)
241 return (s1 == GDK_IM_STATUS_AREA)? style1:style2;
242 else if ( u & GDK_IM_STATUS_NOTHING)
243 return (s1 == GDK_IM_STATUS_NOTHING)? style1:style2;
244 else if ( u & GDK_IM_STATUS_NONE)
245 return (s1 == GDK_IM_STATUS_NONE)? style1:style2;
247 return 0; /* Get rid of stupid warning */
251 gdk_im_decide_style (GdkIMStyle supported_style)
254 GdkIMStyle style, tmp;
256 g_return_val_if_fail (xim_styles != NULL, 0);
259 for (i=0; i<xim_styles->count_styles; i++)
261 tmp = xim_styles->supported_styles[i];
262 if (tmp == (tmp & supported_style & xim_best_allowed_style))
263 style = gdk_im_choose_better_style (style, tmp);
269 gdk_im_set_best_style (GdkIMStyle style)
271 if (style & GDK_IM_PREEDIT_MASK)
273 xim_best_allowed_style &= ~GDK_IM_PREEDIT_MASK;
275 xim_best_allowed_style |= GDK_IM_PREEDIT_NONE;
276 if (!(style & GDK_IM_PREEDIT_NONE))
278 xim_best_allowed_style |= GDK_IM_PREEDIT_NOTHING;
279 if (!(style & GDK_IM_PREEDIT_NOTHING))
281 xim_best_allowed_style |= GDK_IM_PREEDIT_AREA;
282 if (!(style & GDK_IM_PREEDIT_AREA))
284 xim_best_allowed_style |= GDK_IM_PREEDIT_POSITION;
285 if (!(style & GDK_IM_PREEDIT_POSITION))
286 xim_best_allowed_style |= GDK_IM_PREEDIT_CALLBACKS;
291 if (style & GDK_IM_STATUS_MASK)
293 xim_best_allowed_style &= ~GDK_IM_STATUS_MASK;
295 xim_best_allowed_style |= GDK_IM_STATUS_NONE;
296 if (!(style & GDK_IM_STATUS_NONE))
298 xim_best_allowed_style |= GDK_IM_STATUS_NOTHING;
299 if (!(style & GDK_IM_STATUS_NOTHING))
301 xim_best_allowed_style |= GDK_IM_STATUS_AREA;
302 if (!(style & GDK_IM_STATUS_AREA))
303 xim_best_allowed_style |= GDK_IM_STATUS_CALLBACKS;
308 return xim_best_allowed_style;
312 gdk_im_destroy_cb (XIM im, XPointer client_data, XPointer call_data)
315 GdkICPrivate *private;
317 GDK_NOTE (XIM, g_message ("Ouch, Input Method is destroyed!!\n"));
327 for (node = xim_ic_list; node != NULL; node = g_list_next(node))
329 private = (GdkICPrivate *) (node->data);
333 XRegisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL,
334 gdk_im_instantiate_cb, NULL);
338 gdk_im_instantiate_cb (Display *display,
339 XPointer client_data, XPointer call_data)
341 XIMCallback destroy_cb;
344 GDK_NOTE (XIM, g_message ("New IM is instantiated."));
345 if (display != gdk_display)
348 XUnregisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL,
349 gdk_im_instantiate_cb, NULL);
351 xim_im = XOpenIM (GDK_DISPLAY(), NULL, NULL, NULL);
353 GDK_NOTE (XIM, g_warning ("Unable to open open IM."));
355 destroy_cb.callback = gdk_im_destroy_cb;
356 destroy_cb.client_data = NULL;
357 XSetIMValues (xim_im, XNDestroyCallback, &destroy_cb, NULL);
359 XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL);
361 for (node = xim_ic_list; node != NULL; node = g_list_next(node))
363 GdkICPrivate *private = (GdkICPrivate *) (node->data);
364 if (private->xic == NULL)
365 gdk_ic_real_new ((GdkIC *)private);
373 gdk_xim_window = (GdkWindow*)NULL;
377 /* initialize XIM Protocol variables */
378 if (!(xim_best_allowed_style & GDK_IM_PREEDIT_MASK))
379 gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
380 if (!(xim_best_allowed_style & GDK_IM_STATUS_MASK))
381 gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
383 XRegisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL,
384 gdk_im_instantiate_cb, NULL);
386 return (xim_im != NULL);
407 return (xim_im != NULL);
411 gdk_ic_real_new (GdkIC *ic)
413 XPoint spot_location;
414 XRectangle preedit_area;
415 XRectangle status_area;
416 XVaNestedList *preedit_attr = NULL;
417 XVaNestedList *status_attr = NULL;
419 GdkICPrivate *private;
420 GdkICAttributesType mask = GDK_IC_ALL_REQ;
422 private = (GdkICPrivate *) ic;
423 attr = private->attr;
425 switch (attr->style & GDK_IM_PREEDIT_MASK)
427 case GDK_IM_PREEDIT_AREA:
428 mask |= GDK_IC_PREEDIT_AREA_REQ;
430 preedit_area.x = attr->preedit_area.x;
431 preedit_area.y = attr->preedit_area.x;
432 preedit_area.width = attr->preedit_area.width;
433 preedit_area.height = attr->preedit_area.height;
435 preedit_attr = XVaCreateNestedList (0,
436 XNArea, &preedit_area,
438 GDK_FONT_XFONT(attr->preedit_fontset),
442 case GDK_IM_PREEDIT_POSITION:
443 mask |= GDK_IC_PREEDIT_POSITION_REQ;
445 preedit_area.x = attr->preedit_area.x;
446 preedit_area.y = attr->preedit_area.x;
447 preedit_area.width = attr->preedit_area.width;
448 preedit_area.height = attr->preedit_area.height;
450 spot_location.x = attr->spot_location.x;
451 spot_location.y = attr->spot_location.y;
453 preedit_attr = XVaCreateNestedList (0,
454 XNArea, &preedit_area,
456 GDK_FONT_XFONT(attr->preedit_fontset),
457 XNSpotLocation, &spot_location,
462 switch (attr->style & GDK_IM_STATUS_MASK)
464 case GDK_IM_STATUS_AREA:
465 mask |= GDK_IC_STATUS_AREA_REQ;
467 status_area.x = attr->status_area.x;
468 status_area.y = attr->status_area.x;
469 status_area.width = attr->status_area.width;
470 status_area.height = attr->status_area.height;
472 status_attr = XVaCreateNestedList (0,
473 XNArea, &status_area,
475 GDK_FONT_XFONT(attr->status_fontset),
480 if (preedit_attr != NULL && status_attr != NULL)
481 private->xic = XCreateIC (xim_im,
485 GDK_WINDOW_XWINDOW(attr->client_window),
491 else if (preedit_attr != NULL)
492 private->xic = XCreateIC (xim_im,
496 GDK_WINDOW_XWINDOW(attr->client_window),
500 else if (status_attr != NULL)
501 private->xic = XCreateIC (xim_im,
505 GDK_WINDOW_XWINDOW(attr->client_window),
510 private->xic = XCreateIC (xim_im,
514 GDK_WINDOW_XWINDOW(attr->client_window),
518 XFree (preedit_attr);
522 if (private->xic == NULL)
523 g_warning ("can not create input context with specified input style.");
525 gdk_ic_real_set_attr (ic, private->attr, private->mask & ~mask);
529 gdk_ic_new (GdkICAttr *attr, GdkICAttributesType mask)
531 GdkICPrivate *private;
533 GdkICAttributesType invalid_mask;
536 g_return_val_if_fail (attr != NULL, NULL);
537 g_return_val_if_fail ((mask & GDK_IC_ALL_REQ) == GDK_IC_ALL_REQ, NULL);
539 switch (attr->style & GDK_IM_PREEDIT_MASK)
542 g_warning ("preedit style is not specified.\n");
546 case GDK_IM_PREEDIT_AREA:
547 if ((mask & GDK_IC_PREEDIT_AREA_REQ) != GDK_IC_PREEDIT_AREA_REQ)
551 case GDK_IM_PREEDIT_POSITION:
552 if ((mask & GDK_IC_PREEDIT_POSITION_REQ) != GDK_IC_PREEDIT_POSITION_REQ)
557 switch (attr->style & GDK_IM_STATUS_MASK)
560 g_warning ("status style is not specified.\n");
564 case GDK_IM_STATUS_AREA:
565 if ((mask & GDK_IC_STATUS_AREA_REQ) != GDK_IC_STATUS_AREA_REQ)
573 g_warning ("IC attribute is not enough to required input style.\n");
577 if (attr->client_window == NULL ||
578 ((GdkWindowPrivate *)attr->client_window)->destroyed)
580 g_warning ("Client_window is null or already destroyed.\n");
584 private = g_new0 (GdkICPrivate, 1);
585 private->attr = pattr = gdk_ic_attr_new ();
587 gdk_window_ref (attr->client_window);
588 pattr->client_window = attr->client_window;
589 pattr->style = attr->style;
590 private->mask = GDK_IC_STYLE | GDK_IC_CLIENT_WINDOW;
592 /* XIC is still not created, so following call only copies attributes */
593 invalid_mask = gdk_ic_set_attr ((GdkIC *)private, attr, mask & ~GDK_IC_ALL_REQ);
595 switch (attr->style & GDK_IM_PREEDIT_MASK)
597 case GDK_IM_PREEDIT_AREA:
598 if (invalid_mask & GDK_IC_PREEDIT_AREA_REQ)
602 case GDK_IM_PREEDIT_POSITION:
603 if (invalid_mask & GDK_IC_PREEDIT_POSITION_REQ)
608 switch (attr->style & GDK_IM_STATUS_MASK)
610 case GDK_IM_STATUS_AREA:
611 if (invalid_mask & GDK_IC_STATUS_AREA_REQ)
618 g_warning ("Essential attributes for required style are invalid.\n");
619 gdk_ic_destroy ((GdkIC *)private);
624 gdk_ic_real_new ((GdkIC *)private);
626 xim_ic_list = g_list_append (xim_ic_list, private);
628 return (GdkIC *)private;
632 gdk_ic_destroy (GdkIC *ic)
634 GdkICPrivate *private;
636 g_return_if_fail (ic != NULL);
638 private = (GdkICPrivate *) ic;
640 if (gdk_xim_ic == private)
643 GDK_NOTE (XIM, g_print("ic_destroy %p\n", private->xic));
644 if (private->xic != NULL)
645 XDestroyIC (private->xic);
647 if (private->mask & GDK_IC_CLIENT_WINDOW)
648 gdk_window_unref (private->attr->client_window);
649 if (private->mask & GDK_IC_FOCUS_WINDOW)
650 gdk_window_unref (private->attr->focus_window);
652 if (private->mask & GDK_IC_PREEDIT_FONTSET)
653 gdk_font_unref (private->attr->preedit_fontset);
654 if (private->mask & GDK_IC_PREEDIT_PIXMAP)
655 gdk_pixmap_unref (private->attr->preedit_pixmap);
656 if (private->mask & GDK_IC_PREEDIT_COLORMAP)
657 gdk_colormap_unref (private->attr->preedit_colormap);
659 if (private->mask & GDK_IC_STATUS_FONTSET)
660 gdk_font_unref (private->attr->status_fontset);
661 if (private->mask & GDK_IC_STATUS_PIXMAP)
662 gdk_pixmap_unref (private->attr->status_pixmap);
663 if (private->mask & GDK_IC_STATUS_COLORMAP)
664 gdk_colormap_unref (private->attr->status_colormap);
666 xim_ic_list = g_list_remove (xim_ic_list, private);
667 gdk_ic_attr_destroy (private->attr);
672 gdk_ic_get_style (GdkIC *ic)
674 GdkICPrivate *private;
676 g_return_val_if_fail (ic != NULL, 0);
678 private = (GdkICPrivate *) ic;
680 return private->attr->style;
684 * for keeping binary compatibility if member of ic attributes is added.
687 gdk_ic_attr_new (void)
689 return g_new0 (GdkICAttr, 1);
693 gdk_ic_attr_destroy (GdkICAttr *attr)
695 g_return_if_fail (attr != NULL);
700 static GdkICAttributesType
701 gdk_ic_real_set_attr (GdkIC *ic,
703 GdkICAttributesType mask)
705 GdkICPrivate *private = (GdkICPrivate *)ic;
706 XIC xic = private->xic;
707 GdkICAttributesType error = 0;
708 GdkImArg arg[2] = {{NULL, NULL}, {NULL, NULL}};
710 if (mask & GDK_IC_FOCUS_WINDOW)
712 if (XSetICValues (xic, XNFocusWindow,
713 GDK_WINDOW_XWINDOW(attr->focus_window), NULL) != NULL)
714 error |= GDK_IC_FOCUS_WINDOW;
717 if (mask & GDK_IC_SPOT_LOCATION)
721 point.x = attr->spot_location.x;
722 point.y = attr->spot_location.y;
724 arg->name = XNSpotLocation;
725 arg->value = (gpointer) &point;
727 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
728 error |= GDK_IC_SPOT_LOCATION;
731 if (mask & GDK_IC_LINE_SPACING)
733 arg->name = XNLineSpace;
734 arg->value = GINT_TO_POINTER( attr->line_spacing );
736 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
737 error |= GDK_IC_LINE_SPACING;
740 if (mask & GDK_IC_CURSOR)
742 GdkCursorPrivate *cursor = (GdkCursorPrivate *) attr->cursor;
744 if (XSetICValues (xic, XNCursor, cursor->xcursor, NULL))
745 error |= GDK_IC_CURSOR;
748 if (mask & GDK_IC_PREEDIT_FONTSET)
750 arg->name = XNFontSet;
751 arg->value = (gpointer) GDK_FONT_XFONT(attr->preedit_fontset);
753 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
754 error |= GDK_IC_PREEDIT_FONTSET;
757 if (mask & GDK_IC_PREEDIT_AREA)
761 rect.x = attr->preedit_area.x;
762 rect.y = attr->preedit_area.y;
763 rect.width = attr->preedit_area.width;
764 rect.height = attr->preedit_area.height;
767 arg->value = (gpointer) ▭
769 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
770 error |= GDK_IC_PREEDIT_AREA;
773 if (mask & GDK_IC_PREEDIT_AREA_NEEDED)
777 rect.x = attr->preedit_area_needed.x;
778 rect.y = attr->preedit_area_needed.y;
779 rect.width = attr->preedit_area_needed.width;
780 rect.height = attr->preedit_area_needed.height;
783 arg->value = (gpointer) ▭
785 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
786 error |= GDK_IC_PREEDIT_AREA_NEEDED;
788 private->mask &= ~GDK_IC_PREEDIT_AREA_NEEDED;
791 if (mask & GDK_IC_PREEDIT_FOREGROUND)
793 arg->name = XNForeground;
794 arg->value = (gpointer) attr->preedit_foreground.pixel;
796 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
797 error |= GDK_IC_PREEDIT_FOREGROUND;
800 if (mask & GDK_IC_PREEDIT_BACKGROUND)
802 arg->name = XNBackground;
803 arg->value = (gpointer) attr->preedit_background.pixel;
805 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
806 error |= GDK_IC_PREEDIT_BACKGROUND;
809 if (mask & GDK_IC_PREEDIT_PIXMAP)
811 arg->name = XNBackgroundPixmap;
812 arg->value = (gpointer) GDK_WINDOW_XWINDOW(attr->preedit_pixmap);
814 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
815 error |= GDK_IC_PREEDIT_PIXMAP;
818 if (mask & GDK_IC_PREEDIT_COLORMAP)
820 arg->name = XNColormap;
821 arg->value = (gpointer) GDK_COLORMAP_XCOLORMAP(attr->preedit_colormap);
823 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
824 error |= GDK_IC_PREEDIT_COLORMAP;
828 if (mask & GDK_IC_STATUS_FONTSET)
830 arg->name = XNFontSet;
831 arg->value = (gpointer) GDK_FONT_XFONT(attr->status_fontset);
833 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
834 error |= GDK_IC_STATUS_FONTSET;
837 if (mask & GDK_IC_STATUS_AREA)
841 rect.x = attr->status_area.x;
842 rect.y = attr->status_area.y;
843 rect.width = attr->status_area.width;
844 rect.height = attr->status_area.height;
847 arg->value = (gpointer) ▭
849 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
850 error |= GDK_IC_STATUS_AREA;
853 if (mask & GDK_IC_STATUS_AREA_NEEDED)
857 rect.x = attr->status_area_needed.x;
858 rect.y = attr->status_area_needed.y;
859 rect.width = attr->status_area_needed.width;
860 rect.height = attr->status_area_needed.height;
863 arg->value = (gpointer) ▭
865 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
866 error |= GDK_IC_STATUS_AREA_NEEDED;
868 private->mask &= ~GDK_IC_STATUS_AREA_NEEDED;
871 if (mask & GDK_IC_STATUS_FOREGROUND)
873 arg->name = XNForeground;
874 arg->value = (gpointer) attr->status_foreground.pixel;
876 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
877 error |= GDK_IC_STATUS_FOREGROUND;
880 if (mask & GDK_IC_STATUS_BACKGROUND)
882 arg->name = XNBackground;
883 arg->value = (gpointer) attr->status_background.pixel;
885 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
886 error |= GDK_IC_STATUS_BACKGROUND;
889 if (mask & GDK_IC_STATUS_PIXMAP)
891 arg->name = XNBackgroundPixmap;
892 arg->value = (gpointer) GDK_WINDOW_XWINDOW(attr->status_pixmap);
894 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
895 error |= GDK_IC_STATUS_PIXMAP;
898 if (mask & GDK_IC_STATUS_COLORMAP)
900 arg->name = XNColormap;
901 arg->value = (gpointer) GDK_COLORMAP_XCOLORMAP(attr->status_colormap);
903 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
904 error |= GDK_IC_STATUS_COLORMAP;
911 gdk_ic_set_attr (GdkIC *ic,
913 GdkICAttributesType mask)
915 GdkICPrivate *private;
917 GdkICAttributesType error = 0;
918 GdkICAttributesType newattr = 0;
920 g_return_val_if_fail (ic != NULL, 0);
921 g_return_val_if_fail (attr != NULL, 0);
923 private = (GdkICPrivate *) ic;
924 pattr = private->attr;
926 /* Check and copy new attributes */
928 if (mask & GDK_IC_STYLE)
930 g_warning ("input style can be specified only when creating new ic.\n");
931 error |= GDK_IC_STYLE;
934 if (mask & GDK_IC_FILTER_EVENTS)
936 g_warning ("filter events is read only attributes.\n");
937 error |= GDK_IC_FILTER_EVENTS;
940 if (mask & GDK_IC_CLIENT_WINDOW)
942 g_warning ("client window can be specified only when creating new ic.\n");
943 error |= GDK_IC_CLIENT_WINDOW;
946 if (mask & GDK_IC_FOCUS_WINDOW)
948 if (attr->focus_window == NULL)
950 g_warning ("specified focus_window is invalid.\n");
951 error |= GDK_IC_FOCUS_WINDOW;
953 else if (pattr->focus_window != attr->focus_window)
955 if (pattr->focus_window != NULL)
956 gdk_window_unref (pattr->focus_window);
957 if (attr->focus_window != NULL)
958 gdk_window_ref (attr->focus_window);
959 pattr->focus_window = attr->focus_window;
960 newattr |= GDK_IC_FOCUS_WINDOW;
964 if (mask & GDK_IC_SPOT_LOCATION)
966 pattr->spot_location = attr->spot_location;
967 newattr |= GDK_IC_SPOT_LOCATION;
970 if (mask & GDK_IC_LINE_SPACING)
972 pattr->line_spacing = attr->line_spacing;
973 newattr |= GDK_IC_LINE_SPACING;
976 if (mask & GDK_IC_CURSOR)
978 pattr->cursor = attr->cursor;
979 newattr |= GDK_IC_CURSOR;
982 if (mask & GDK_IC_PREEDIT_FONTSET)
984 if (attr->preedit_fontset == NULL ||
985 attr->preedit_fontset->type != GDK_FONT_FONTSET)
987 g_warning ("gdk_font is NULL or not a fontset.\n");
988 error |= GDK_IC_PREEDIT_FONTSET;
990 else if (pattr->preedit_fontset != attr->preedit_fontset)
992 if (pattr->preedit_fontset != NULL)
993 gdk_font_unref (pattr->preedit_fontset);
994 if (attr->preedit_fontset != NULL)
995 gdk_font_ref (attr->preedit_fontset);
996 pattr->preedit_fontset = attr->preedit_fontset;
997 newattr |= GDK_IC_PREEDIT_FONTSET;
1001 if (mask & GDK_IC_PREEDIT_AREA)
1003 pattr->preedit_area = attr->preedit_area;
1004 newattr |= GDK_IC_PREEDIT_AREA;
1007 if (mask & GDK_IC_PREEDIT_AREA_NEEDED)
1009 if (attr->preedit_area_needed.width == 0 ||
1010 attr->preedit_area_needed.height == 0)
1012 g_warning ("width and height of preedit_area_needed must be non 0.\n");
1013 error |= GDK_IC_PREEDIT_AREA_NEEDED;
1017 pattr->preedit_area_needed = attr->preedit_area_needed;
1018 newattr |= GDK_IC_PREEDIT_AREA_NEEDED;
1022 if (mask & GDK_IC_PREEDIT_FOREGROUND)
1024 pattr->preedit_foreground = attr->preedit_foreground;
1025 newattr |= GDK_IC_PREEDIT_FOREGROUND;
1028 if (mask & GDK_IC_PREEDIT_BACKGROUND)
1030 pattr->preedit_background = attr->preedit_background;
1031 newattr |= GDK_IC_PREEDIT_BACKGROUND;
1034 if (mask & GDK_IC_PREEDIT_PIXMAP)
1036 if (attr->preedit_pixmap != NULL &&
1037 ((GdkPixmapPrivate *)attr->preedit_pixmap)->destroyed)
1039 g_warning ("Preedit pixmap is already destroyed.\n");
1040 error |= GDK_IC_PREEDIT_PIXMAP;
1044 if (pattr->preedit_pixmap != attr->preedit_pixmap)
1046 if (pattr->preedit_pixmap != NULL)
1047 gdk_pixmap_unref (pattr->preedit_pixmap);
1048 if (attr->preedit_pixmap)
1049 gdk_pixmap_ref (attr->preedit_pixmap);
1050 pattr->preedit_pixmap = attr->preedit_pixmap;
1051 newattr |= GDK_IC_PREEDIT_PIXMAP;
1056 if (mask & GDK_IC_PREEDIT_COLORMAP)
1058 if (pattr->preedit_colormap != attr->preedit_colormap)
1060 if (pattr->preedit_colormap != NULL)
1061 gdk_colormap_unref (pattr->preedit_colormap);
1062 if (attr->preedit_colormap != NULL)
1063 gdk_colormap_ref (attr->preedit_colormap);
1064 pattr->preedit_colormap = attr->preedit_colormap;
1065 newattr |= GDK_IC_PREEDIT_COLORMAP;
1069 if (mask & GDK_IC_STATUS_FONTSET)
1071 if (attr->status_fontset == NULL ||
1072 attr->status_fontset->type != GDK_FONT_FONTSET)
1074 g_warning ("gdk_font is NULL or not a fontset.\n");
1075 error |= GDK_IC_STATUS_FONTSET;
1077 else if (pattr->status_fontset != attr->status_fontset)
1079 if (pattr->status_fontset != NULL)
1080 gdk_font_unref (pattr->status_fontset);
1081 if (attr->status_fontset != NULL)
1082 gdk_font_ref (attr->status_fontset);
1083 pattr->status_fontset = attr->status_fontset;
1084 newattr |= GDK_IC_STATUS_FONTSET;
1088 if (mask & GDK_IC_STATUS_AREA)
1090 pattr->status_area = attr->status_area;
1091 newattr |= GDK_IC_STATUS_AREA;
1094 if (mask & GDK_IC_STATUS_AREA_NEEDED)
1096 if (attr->status_area_needed.width == 0 ||
1097 attr->status_area_needed.height == 0)
1099 g_warning ("width and height of status_area_needed must be non 0.\n");
1100 error |= GDK_IC_STATUS_AREA_NEEDED;
1104 pattr->status_area_needed = attr->status_area_needed;
1105 newattr |= GDK_IC_STATUS_AREA_NEEDED;
1109 if (mask & GDK_IC_STATUS_FOREGROUND)
1111 pattr->status_foreground = attr->status_foreground;
1112 newattr |= GDK_IC_STATUS_FOREGROUND;
1115 if (mask & GDK_IC_STATUS_BACKGROUND)
1117 pattr->status_background = attr->status_background;
1118 newattr |= GDK_IC_STATUS_BACKGROUND;
1121 if (mask & GDK_IC_STATUS_PIXMAP)
1123 if (attr->status_pixmap != NULL &&
1124 ((GdkPixmapPrivate *)attr->status_pixmap)->destroyed)
1126 g_warning ("Preedit pixmap is already destroyed.\n");
1127 error |= GDK_IC_STATUS_PIXMAP;
1131 if (pattr->status_pixmap != attr->status_pixmap)
1133 if (pattr->status_pixmap != NULL)
1134 gdk_pixmap_unref (pattr->status_pixmap);
1135 if (attr->status_pixmap)
1136 gdk_pixmap_ref (attr->status_pixmap);
1137 pattr->status_pixmap = attr->status_pixmap;
1138 newattr |= GDK_IC_STATUS_PIXMAP;
1143 if (mask & GDK_IC_STATUS_COLORMAP)
1145 if (pattr->status_colormap != attr->status_colormap)
1147 if (pattr->status_colormap != NULL)
1148 gdk_colormap_unref (pattr->status_colormap);
1149 if (attr->status_colormap != NULL)
1150 gdk_colormap_ref (attr->status_colormap);
1151 pattr->status_colormap = attr->status_colormap;
1152 newattr |= GDK_IC_STATUS_COLORMAP;
1156 if (private->xic == NULL)
1159 error |= gdk_ic_real_set_attr (ic, pattr, newattr);
1165 gdk_ic_get_attr (GdkIC *ic,
1167 GdkICAttributesType mask)
1169 GdkICPrivate *private;
1171 GdkICAttributesType known, unknown = 0;
1173 g_return_val_if_fail (ic != NULL, -1);
1174 g_return_val_if_fail (attr != NULL, -1);
1176 private = (GdkICPrivate *) ic;
1177 pattr = private->attr;
1179 known = mask & private->mask;
1181 if (known & GDK_IC_STYLE)
1182 attr->style = pattr->style;
1183 if (known & GDK_IC_CLIENT_WINDOW)
1184 attr->client_window = pattr->client_window;
1185 if (known & GDK_IC_FOCUS_WINDOW)
1186 attr->focus_window = pattr->focus_window;
1187 if (known & GDK_IC_FILTER_EVENTS)
1188 attr->filter_events = pattr->filter_events;
1189 if (known & GDK_IC_LINE_SPACING)
1190 attr->line_spacing = pattr->line_spacing;
1191 if (known & GDK_IC_CURSOR)
1192 attr->cursor = pattr->cursor;
1194 if (known & GDK_IC_PREEDIT_FONTSET)
1195 attr->preedit_fontset = pattr->preedit_fontset;
1196 if (known & GDK_IC_PREEDIT_AREA)
1197 attr->preedit_area = pattr->preedit_area;
1198 if (known & GDK_IC_PREEDIT_AREA_NEEDED)
1199 attr->preedit_area_needed = pattr->preedit_area_needed;
1200 if (known & GDK_IC_PREEDIT_FOREGROUND)
1201 attr->preedit_foreground = pattr->preedit_foreground;
1202 if (known & GDK_IC_PREEDIT_BACKGROUND)
1203 attr->preedit_background = pattr->preedit_background;
1204 if (known & GDK_IC_PREEDIT_PIXMAP)
1205 attr->preedit_pixmap = pattr->preedit_pixmap;
1206 if (known & GDK_IC_PREEDIT_COLORMAP)
1207 attr->preedit_colormap = pattr->preedit_colormap;
1209 if (known & GDK_IC_STATUS_FONTSET)
1210 attr->status_fontset = pattr->status_fontset;
1211 if (known & GDK_IC_STATUS_AREA)
1212 attr->status_area = pattr->status_area;
1213 if (known & GDK_IC_STATUS_AREA_NEEDED)
1214 attr->status_area_needed = pattr->status_area_needed;
1215 if (known & GDK_IC_STATUS_FOREGROUND)
1216 attr->status_foreground = pattr->status_foreground;
1217 if (known & GDK_IC_STATUS_BACKGROUND)
1218 attr->status_background = pattr->status_background;
1219 if (known & GDK_IC_STATUS_PIXMAP)
1220 attr->status_pixmap = pattr->status_pixmap;
1221 if (known & GDK_IC_STATUS_COLORMAP)
1222 attr->status_colormap = pattr->status_colormap;
1226 unknown = mask & ~(private->mask);
1228 if (unknown & GDK_IC_FOCUS_WINDOW)
1229 attr->focus_window = pattr->client_window;
1230 if (unknown & GDK_IC_FILTER_EVENTS)
1232 gdk_ic_get_events (ic);
1233 attr->filter_events = pattr->filter_events;
1235 if (mask & GDK_IC_SPOT_LOCATION)
1238 XVaNestedList *list;
1240 list = XVaCreateNestedList (0, XNSpotLocation, &point, NULL);
1241 if (XGetICValues (private->xic, XNPreeditAttributes, list, NULL))
1242 unknown &= ~GDK_IC_SPOT_LOCATION;
1245 pattr->spot_location.x = point.x;
1246 pattr->spot_location.y = point.y;
1247 private->mask |= GDK_IC_SPOT_LOCATION;
1249 attr->spot_location = pattr->spot_location;
1253 if (unknown & GDK_IC_PREEDIT_AREA_NEEDED)
1256 XVaNestedList *list;
1258 list = XVaCreateNestedList (0, XNAreaNeeded, &rect, NULL);
1259 if (XGetICValues (private->xic, XNPreeditAttributes, list, NULL))
1260 unknown &= ~GDK_IC_PREEDIT_AREA_NEEDED;
1263 pattr->preedit_area_needed.x = rect.x;
1264 pattr->preedit_area_needed.y = rect.y;
1265 pattr->preedit_area_needed.width = rect.width;
1266 pattr->preedit_area_needed.height = rect.height;
1267 private->mask |= GDK_IC_PREEDIT_AREA_NEEDED;
1269 attr->preedit_area = pattr->preedit_area;
1273 if (unknown & GDK_IC_STATUS_AREA_NEEDED)
1276 XVaNestedList *list;
1278 list = XVaCreateNestedList (0, XNAreaNeeded, &rect, NULL);
1279 if (XGetICValues (private->xic, XNStatusAttributes, list, NULL))
1280 unknown &= ~GDK_IC_STATUS_AREA_NEEDED;
1283 pattr->status_area_needed.x = rect.x;
1284 pattr->status_area_needed.y = rect.y;
1285 pattr->status_area_needed.width = rect.width;
1286 pattr->status_area_needed.height = rect.height;
1287 private->mask |= GDK_IC_STATUS_AREA_NEEDED;
1289 attr->status_area = pattr->status_area;
1295 return mask & ~known & ~unknown;
1299 gdk_ic_get_events (GdkIC *ic)
1304 GdkICPrivate *private;
1307 /* From gdkwindow.c */
1309 g_return_val_if_fail (ic != NULL, 0);
1311 private = (GdkICPrivate *) ic;
1313 if (private->mask & GDK_IC_FILTER_EVENTS)
1314 return private->attr->filter_events;
1316 if (XGetICValues (private->xic, XNFilterEvents, &xmask, NULL) != NULL)
1318 GDK_NOTE (XIM, g_warning ("Call to XGetICValues: %s failed", XNFilterEvents));
1323 for (i=0, bit=2; i < gdk_nevent_masks; i++, bit <<= 1)
1324 if (xmask & gdk_event_mask_table [i])
1327 xmask &= ~ gdk_event_mask_table [i];
1331 g_warning ("ic requires events not supported by the application (%#04lx)", xmask);
1333 private->attr->filter_events = mask;
1334 private->mask |= GDK_IC_FILTER_EVENTS;
1340 gdk_ic_cleanup (void)
1345 while (xim_ic_list != NULL)
1347 gdk_ic_destroy ((GdkIC *) xim_ic_list->data);
1350 #ifdef G_ENABLE_DEBUG
1351 if ((gdk_debug_flags & GDK_DEBUG_XIM) && destroyed > 0)
1353 g_warning ("Cleaned up %i IC(s)\n", destroyed);
1355 #endif /* G_ENABLE_DEBUG */
1358 #else /* !USE_XIM */
1361 gdk_im_begin (GdkIC *ic, GdkWindow* window)
1371 gdk_im_decide_style (GdkIMStyle supported_style)
1373 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
1377 gdk_im_set_best_style (GdkIMStyle style)
1379 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
1389 gdk_ic_new (GdkICAttr *attr, GdkICAttributesType mask)
1395 gdk_ic_destroy (GdkIC *ic)
1400 gdk_ic_get_style (GdkIC *ic)
1402 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
1406 gdk_ic_set_values (GdkIC *ic, ...)
1411 gdk_ic_get_values (GdkIC *ic, ...)
1416 gdk_ic_set_attr (GdkIC *ic, GdkICAttr *attr, GdkICAttributesType mask)
1422 gdk_ic_get_attr (GdkIC *ic, GdkICAttr *attr, GdkICAttributesType mask)
1428 gdk_ic_get_events (GdkIC *ic)
1433 #endif /* USE_XIM */
1438 * Returns a multi-byte string converted from the specified array
1439 * of wide characters. The string is newly allocated. The array of
1440 * wide characters must be null-terminated. If the conversion is
1441 * failed, it returns NULL.
1444 gdk_wcstombs (const GdkWChar *src)
1452 if (sizeof(wchar_t) != sizeof(GdkWChar))
1456 for (i=0; src[i]; i++);
1457 src_alt = g_new (wchar_t, i+1);
1459 src_alt[i] = src[i];
1460 if (XwcTextListToTextProperty (gdk_display, &src_alt, 1, XTextStyle, &tpr)
1470 if (XwcTextListToTextProperty (gdk_display, (wchar_t**)&src, 1,
1471 XTextStyle, &tpr) != Success)
1477 * We must copy the string into an area allocated by glib, because
1478 * the string 'tpr.value' must be freed by XFree().
1480 mbstr = g_strdup(tpr.value);
1488 while (src[length++] != 0)
1491 mbstr = g_new (gchar, length + 1);
1493 for (i=0; i<length+1; i++)
1503 * Converts the specified string into wide characters, and, returns the
1504 * number of wide characters written. The string 'src' must be
1505 * null-terminated. If the conversion is failed, it returns -1.
1508 gdk_mbstowcs (GdkWChar *dest, const gchar *src, gint dest_max)
1513 wchar_t **wstrs, *wstr_src;
1516 if (XmbTextListToTextProperty (gdk_display, (char **)&src, 1, XTextStyle,
1520 /* NoMem or LocaleNotSupp */
1523 if (XwcTextPropertyToTextList (gdk_display, &tpr, &wstrs, &num_wstrs)
1531 wstr_src = wstrs[0];
1532 for (len_cpy=0; len_cpy<dest_max && wstr_src[len_cpy]; len_cpy++)
1533 dest[len_cpy] = wstr_src[len_cpy];
1534 XwcFreeStringList (wstrs);
1541 for (i=0; i<dest_max && src[i]; i++)