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"
34 /* If this variable is FALSE, it indicates that we should
35 * avoid trying to use multibyte conversion functions and
36 * assume everything is 1-byte per character
38 static gboolean gdk_use_mb;
43 #include <X11/Xresource.h>
45 /* The following routines duplicate functionality in Xlib to
46 * translate from varargs to X's internal opaque XVaNestedList.
48 * If all vendors have stuck close to the reference implementation,
49 * then we should hopefully be OK.
57 static void gdk_im_instantiate_cb (Display *display,
60 static void gdk_im_destroy_cb (XIM im,
64 static void gdk_ic_real_new (GdkIC *ic);
66 static GdkICAttributesType gdk_ic_real_set_attr (GdkIC *ic,
68 GdkICAttributesType mask);
70 static XIM xim_im; /* global IM */
71 static XIMStyles* xim_styles; /* im supports these styles */
72 static XIMStyle xim_best_allowed_style;
73 static GList* xim_ic_list;
78 *--------------------------------------------------------------
87 *--------------------------------------------------------------
94 gchar *current_locale;
98 if (!setlocale (LC_ALL,""))
99 g_message ("locale not supported by C library");
101 if (!XSupportsLocale ())
103 g_message ("locale not supported by Xlib, locale set to C");
104 setlocale (LC_ALL, "C");
107 if (!XSetLocaleModifiers (""))
108 g_message ("can not set locale modifiers");
110 current_locale = setlocale (LC_ALL, NULL);
112 if ((strcmp (current_locale, "C")) && (strcmp (current_locale, "POSIX")))
117 /* Detect GNU libc, where mb == UTF8. Not useful unless it's
118 * really a UTF8 locale. The below still probably will
119 * screw up on Greek, Cyrillic, etc, encoded as UTF8.
122 if ((MB_CUR_MAX == 2) &&
123 (mbstowcs (&result, "\xdd\xa5", 1) > 0) &&
126 if ((strlen (current_locale) < 4) ||
127 g_strcasecmp (current_locale + strlen(current_locale) - 4, "utf8"))
130 #endif /* X_LOCALE */
134 g_message ("%s multi-byte string functions.",
135 gdk_use_mb ? "Using" : "Not using"));
137 return current_locale;
143 *--------------------------------------------------------------
146 * Begin using input method with XIM Protocol(X11R6 standard)
149 * "ic" is the "Input Context" which is created by gtk_ic_new.
150 * The input area is specified with "window".
153 * The gdk's event handling routine is switched to XIM based routine.
154 * XIM based routine uses XFilterEvent to get rid of events used by IM,
155 * and uses XmbLookupString instead of XLookupString.
159 *--------------------------------------------------------------
163 gdk_im_begin (GdkIC *ic, GdkWindow* window)
165 GdkICPrivate *private;
168 g_return_if_fail (ic != NULL);
170 private = (GdkICPrivate *) ic;
172 attr.focus_window = window;
173 gdk_ic_set_attr (ic, &attr, GDK_IC_FOCUS_WINDOW);
175 if (private != gdk_xim_ic)
180 XSetICFocus (private->xic);
181 GDK_NOTE (XIM, g_print ("im_begin icfocus : %p(%ld)\n",
183 GDK_WINDOW_XWINDOW(private->attr->focus_window)));
186 gdk_xim_ic = private;
187 gdk_xim_window = window;
191 *--------------------------------------------------------------
194 * End using input method with XIM Protocol(X11R6 standard)
199 * The gdk's event handling routine is switched to normal routine.
200 * User should call this function before ic and window will be destroyed.
204 *--------------------------------------------------------------
210 if (gdk_xim_ic && gdk_xim_ic->xic)
212 XUnsetICFocus (gdk_xim_ic->xic);
213 GDK_NOTE (XIM, g_print ("im_end unfocus : %p\n", gdk_xim_ic->xic));
216 gdk_xim_window = NULL;
220 gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
222 GdkIMStyle s1, s2, u;
224 if (style1 == 0) return style2;
225 if (style2 == 0) return style1;
226 if ((style1 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK))
227 == (style2 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK)))
230 s1 = style1 & GDK_IM_PREEDIT_MASK;
231 s2 = style2 & GDK_IM_PREEDIT_MASK;
234 if (u & GDK_IM_PREEDIT_CALLBACKS)
235 return (s1 == GDK_IM_PREEDIT_CALLBACKS)? style1:style2;
236 else if (u & GDK_IM_PREEDIT_POSITION)
237 return (s1 == GDK_IM_PREEDIT_POSITION)? style1:style2;
238 else if (u & GDK_IM_PREEDIT_AREA)
239 return (s1 == GDK_IM_PREEDIT_AREA)? style1:style2;
240 else if (u & GDK_IM_PREEDIT_NOTHING)
241 return (s1 == GDK_IM_PREEDIT_NOTHING)? style1:style2;
243 s1 = style1 & GDK_IM_STATUS_MASK;
244 s2 = style2 & GDK_IM_STATUS_MASK;
246 if ( u & GDK_IM_STATUS_CALLBACKS)
247 return (s1 == GDK_IM_STATUS_CALLBACKS)? style1:style2;
248 else if ( u & GDK_IM_STATUS_AREA)
249 return (s1 == GDK_IM_STATUS_AREA)? style1:style2;
250 else if ( u & GDK_IM_STATUS_NOTHING)
251 return (s1 == GDK_IM_STATUS_NOTHING)? style1:style2;
252 else if ( u & GDK_IM_STATUS_NONE)
253 return (s1 == GDK_IM_STATUS_NONE)? style1:style2;
255 return 0; /* Get rid of stupid warning */
259 gdk_im_decide_style (GdkIMStyle supported_style)
262 GdkIMStyle style, tmp;
264 g_return_val_if_fail (xim_styles != NULL, 0);
267 for (i=0; i<xim_styles->count_styles; i++)
269 tmp = xim_styles->supported_styles[i];
270 if (tmp == (tmp & supported_style & xim_best_allowed_style))
271 style = gdk_im_choose_better_style (style, tmp);
277 gdk_im_set_best_style (GdkIMStyle style)
279 if (style & GDK_IM_PREEDIT_MASK)
281 xim_best_allowed_style &= ~GDK_IM_PREEDIT_MASK;
283 xim_best_allowed_style |= GDK_IM_PREEDIT_NONE;
284 if (!(style & GDK_IM_PREEDIT_NONE))
286 xim_best_allowed_style |= GDK_IM_PREEDIT_NOTHING;
287 if (!(style & GDK_IM_PREEDIT_NOTHING))
289 xim_best_allowed_style |= GDK_IM_PREEDIT_AREA;
290 if (!(style & GDK_IM_PREEDIT_AREA))
292 xim_best_allowed_style |= GDK_IM_PREEDIT_POSITION;
293 if (!(style & GDK_IM_PREEDIT_POSITION))
294 xim_best_allowed_style |= GDK_IM_PREEDIT_CALLBACKS;
299 if (style & GDK_IM_STATUS_MASK)
301 xim_best_allowed_style &= ~GDK_IM_STATUS_MASK;
303 xim_best_allowed_style |= GDK_IM_STATUS_NONE;
304 if (!(style & GDK_IM_STATUS_NONE))
306 xim_best_allowed_style |= GDK_IM_STATUS_NOTHING;
307 if (!(style & GDK_IM_STATUS_NOTHING))
309 xim_best_allowed_style |= GDK_IM_STATUS_AREA;
310 if (!(style & GDK_IM_STATUS_AREA))
311 xim_best_allowed_style |= GDK_IM_STATUS_CALLBACKS;
316 return xim_best_allowed_style;
320 gdk_im_destroy_cb (XIM im, XPointer client_data, XPointer call_data)
323 GdkICPrivate *private;
325 GDK_NOTE (XIM, g_message ("Ouch, Input Method is destroyed!!\n"));
335 for (node = xim_ic_list; node != NULL; node = g_list_next(node))
337 private = (GdkICPrivate *) (node->data);
341 XRegisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL,
342 gdk_im_instantiate_cb, NULL);
346 gdk_im_instantiate_cb (Display *display,
347 XPointer client_data, XPointer call_data)
349 XIMCallback destroy_cb;
352 GDK_NOTE (XIM, g_message ("New IM is instantiated."));
353 if (display != gdk_display)
356 XUnregisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL,
357 gdk_im_instantiate_cb, NULL);
359 xim_im = XOpenIM (GDK_DISPLAY(), NULL, NULL, NULL);
361 GDK_NOTE (XIM, g_warning ("Unable to open open IM."));
363 destroy_cb.callback = gdk_im_destroy_cb;
364 destroy_cb.client_data = NULL;
365 XSetIMValues (xim_im, XNDestroyCallback, &destroy_cb, NULL);
367 XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL);
369 for (node = xim_ic_list; node != NULL; node = g_list_next(node))
371 GdkICPrivate *private = (GdkICPrivate *) (node->data);
372 if (private->xic == NULL)
373 gdk_ic_real_new ((GdkIC *)private);
381 gdk_xim_window = (GdkWindow*)NULL;
385 /* initialize XIM Protocol variables */
386 if (!(xim_best_allowed_style & GDK_IM_PREEDIT_MASK))
387 gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
388 if (!(xim_best_allowed_style & GDK_IM_STATUS_MASK))
389 gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
391 XRegisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL,
392 gdk_im_instantiate_cb, NULL);
394 return (xim_im != NULL);
415 return (xim_im != NULL);
419 gdk_ic_real_new (GdkIC *ic)
421 XPoint spot_location;
422 XRectangle preedit_area;
423 XRectangle status_area;
424 XVaNestedList *preedit_attr = NULL;
425 XVaNestedList *status_attr = NULL;
427 GdkICPrivate *private;
428 GdkICAttributesType mask = GDK_IC_ALL_REQ;
430 private = (GdkICPrivate *) ic;
431 attr = private->attr;
433 switch (attr->style & GDK_IM_PREEDIT_MASK)
435 case GDK_IM_PREEDIT_AREA:
436 mask |= GDK_IC_PREEDIT_AREA_REQ;
438 preedit_area.x = attr->preedit_area.x;
439 preedit_area.y = attr->preedit_area.x;
440 preedit_area.width = attr->preedit_area.width;
441 preedit_area.height = attr->preedit_area.height;
443 preedit_attr = XVaCreateNestedList (0,
444 XNArea, &preedit_area,
446 GDK_FONT_XFONT(attr->preedit_fontset),
450 case GDK_IM_PREEDIT_POSITION:
451 mask |= GDK_IC_PREEDIT_POSITION_REQ;
453 preedit_area.x = attr->preedit_area.x;
454 preedit_area.y = attr->preedit_area.x;
455 preedit_area.width = attr->preedit_area.width;
456 preedit_area.height = attr->preedit_area.height;
458 spot_location.x = attr->spot_location.x;
459 spot_location.y = attr->spot_location.y;
461 preedit_attr = XVaCreateNestedList (0,
462 XNArea, &preedit_area,
464 GDK_FONT_XFONT(attr->preedit_fontset),
465 XNSpotLocation, &spot_location,
470 switch (attr->style & GDK_IM_STATUS_MASK)
472 case GDK_IM_STATUS_AREA:
473 mask |= GDK_IC_STATUS_AREA_REQ;
475 status_area.x = attr->status_area.x;
476 status_area.y = attr->status_area.x;
477 status_area.width = attr->status_area.width;
478 status_area.height = attr->status_area.height;
480 status_attr = XVaCreateNestedList (0,
481 XNArea, &status_area,
483 GDK_FONT_XFONT(attr->status_fontset),
488 if (preedit_attr != NULL && status_attr != NULL)
489 private->xic = XCreateIC (xim_im,
493 GDK_WINDOW_XWINDOW(attr->client_window),
499 else if (preedit_attr != NULL)
500 private->xic = XCreateIC (xim_im,
504 GDK_WINDOW_XWINDOW(attr->client_window),
508 else if (status_attr != NULL)
509 private->xic = XCreateIC (xim_im,
513 GDK_WINDOW_XWINDOW(attr->client_window),
518 private->xic = XCreateIC (xim_im,
522 GDK_WINDOW_XWINDOW(attr->client_window),
526 XFree (preedit_attr);
530 if (private->xic == NULL)
531 g_warning ("can not create input context with specified input style.");
533 gdk_ic_real_set_attr (ic, private->attr, private->mask & ~mask);
537 gdk_ic_new (GdkICAttr *attr, GdkICAttributesType mask)
539 GdkICPrivate *private;
541 GdkICAttributesType invalid_mask;
544 g_return_val_if_fail (attr != NULL, NULL);
545 g_return_val_if_fail ((mask & GDK_IC_ALL_REQ) == GDK_IC_ALL_REQ, NULL);
547 switch (attr->style & GDK_IM_PREEDIT_MASK)
550 g_warning ("preedit style is not specified.\n");
554 case GDK_IM_PREEDIT_AREA:
555 if ((mask & GDK_IC_PREEDIT_AREA_REQ) != GDK_IC_PREEDIT_AREA_REQ)
559 case GDK_IM_PREEDIT_POSITION:
560 if ((mask & GDK_IC_PREEDIT_POSITION_REQ) != GDK_IC_PREEDIT_POSITION_REQ)
565 switch (attr->style & GDK_IM_STATUS_MASK)
568 g_warning ("status style is not specified.\n");
572 case GDK_IM_STATUS_AREA:
573 if ((mask & GDK_IC_STATUS_AREA_REQ) != GDK_IC_STATUS_AREA_REQ)
581 g_warning ("IC attribute is not enough to required input style.\n");
585 if (attr->client_window == NULL ||
586 ((GdkWindowPrivate *)attr->client_window)->destroyed)
588 g_warning ("Client_window is null or already destroyed.\n");
592 private = g_new0 (GdkICPrivate, 1);
593 private->attr = pattr = gdk_ic_attr_new ();
595 gdk_window_ref (attr->client_window);
596 pattr->client_window = attr->client_window;
597 pattr->style = attr->style;
598 private->mask = GDK_IC_STYLE | GDK_IC_CLIENT_WINDOW;
600 /* XIC is still not created, so following call only copies attributes */
601 invalid_mask = gdk_ic_set_attr ((GdkIC *)private, attr, mask & ~GDK_IC_ALL_REQ);
603 switch (attr->style & GDK_IM_PREEDIT_MASK)
605 case GDK_IM_PREEDIT_AREA:
606 if (invalid_mask & GDK_IC_PREEDIT_AREA_REQ)
610 case GDK_IM_PREEDIT_POSITION:
611 if (invalid_mask & GDK_IC_PREEDIT_POSITION_REQ)
616 switch (attr->style & GDK_IM_STATUS_MASK)
618 case GDK_IM_STATUS_AREA:
619 if (invalid_mask & GDK_IC_STATUS_AREA_REQ)
626 g_warning ("Essential attributes for required style are invalid.\n");
627 gdk_ic_destroy ((GdkIC *)private);
632 gdk_ic_real_new ((GdkIC *)private);
634 xim_ic_list = g_list_append (xim_ic_list, private);
636 return (GdkIC *)private;
640 gdk_ic_destroy (GdkIC *ic)
642 GdkICPrivate *private;
644 g_return_if_fail (ic != NULL);
646 private = (GdkICPrivate *) ic;
648 if (gdk_xim_ic == private)
651 GDK_NOTE (XIM, g_print("ic_destroy %p\n", private->xic));
652 if (private->xic != NULL)
653 XDestroyIC (private->xic);
655 if (private->mask & GDK_IC_CLIENT_WINDOW)
656 gdk_window_unref (private->attr->client_window);
657 if (private->mask & GDK_IC_FOCUS_WINDOW)
658 gdk_window_unref (private->attr->focus_window);
660 if (private->mask & GDK_IC_PREEDIT_FONTSET)
661 gdk_font_unref (private->attr->preedit_fontset);
662 if (private->mask & GDK_IC_PREEDIT_PIXMAP)
663 gdk_pixmap_unref (private->attr->preedit_pixmap);
664 if (private->mask & GDK_IC_PREEDIT_COLORMAP)
665 gdk_colormap_unref (private->attr->preedit_colormap);
667 if (private->mask & GDK_IC_STATUS_FONTSET)
668 gdk_font_unref (private->attr->status_fontset);
669 if (private->mask & GDK_IC_STATUS_PIXMAP)
670 gdk_pixmap_unref (private->attr->status_pixmap);
671 if (private->mask & GDK_IC_STATUS_COLORMAP)
672 gdk_colormap_unref (private->attr->status_colormap);
674 xim_ic_list = g_list_remove (xim_ic_list, private);
675 gdk_ic_attr_destroy (private->attr);
680 gdk_ic_get_style (GdkIC *ic)
682 GdkICPrivate *private;
684 g_return_val_if_fail (ic != NULL, 0);
686 private = (GdkICPrivate *) ic;
688 return private->attr->style;
692 * for keeping binary compatibility if member of ic attributes is added.
695 gdk_ic_attr_new (void)
697 return g_new0 (GdkICAttr, 1);
701 gdk_ic_attr_destroy (GdkICAttr *attr)
703 g_return_if_fail (attr != NULL);
708 static GdkICAttributesType
709 gdk_ic_real_set_attr (GdkIC *ic,
711 GdkICAttributesType mask)
713 GdkICPrivate *private = (GdkICPrivate *)ic;
714 XIC xic = private->xic;
715 GdkICAttributesType error = 0;
716 GdkImArg arg[2] = {{NULL, NULL}, {NULL, NULL}};
718 if (mask & GDK_IC_FOCUS_WINDOW)
720 if (XSetICValues (xic, XNFocusWindow,
721 GDK_WINDOW_XWINDOW(attr->focus_window), NULL) != NULL)
722 error |= GDK_IC_FOCUS_WINDOW;
725 if (mask & GDK_IC_SPOT_LOCATION)
729 point.x = attr->spot_location.x;
730 point.y = attr->spot_location.y;
732 arg->name = XNSpotLocation;
733 arg->value = (gpointer) &point;
735 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
736 error |= GDK_IC_SPOT_LOCATION;
739 if (mask & GDK_IC_LINE_SPACING)
741 arg->name = XNLineSpace;
742 arg->value = GINT_TO_POINTER( attr->line_spacing );
744 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
745 error |= GDK_IC_LINE_SPACING;
748 if (mask & GDK_IC_CURSOR)
750 GdkCursorPrivate *cursor = (GdkCursorPrivate *) attr->cursor;
752 if (XSetICValues (xic, XNCursor, cursor->xcursor, NULL))
753 error |= GDK_IC_CURSOR;
756 if (mask & GDK_IC_PREEDIT_FONTSET)
758 arg->name = XNFontSet;
759 arg->value = (gpointer) GDK_FONT_XFONT(attr->preedit_fontset);
761 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
762 error |= GDK_IC_PREEDIT_FONTSET;
765 if (mask & GDK_IC_PREEDIT_AREA)
769 rect.x = attr->preedit_area.x;
770 rect.y = attr->preedit_area.y;
771 rect.width = attr->preedit_area.width;
772 rect.height = attr->preedit_area.height;
775 arg->value = (gpointer) ▭
777 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
778 error |= GDK_IC_PREEDIT_AREA;
781 if (mask & GDK_IC_PREEDIT_AREA_NEEDED)
785 rect.x = attr->preedit_area_needed.x;
786 rect.y = attr->preedit_area_needed.y;
787 rect.width = attr->preedit_area_needed.width;
788 rect.height = attr->preedit_area_needed.height;
791 arg->value = (gpointer) ▭
793 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
794 error |= GDK_IC_PREEDIT_AREA_NEEDED;
796 private->mask &= ~GDK_IC_PREEDIT_AREA_NEEDED;
799 if (mask & GDK_IC_PREEDIT_FOREGROUND)
801 arg->name = XNForeground;
802 arg->value = (gpointer) attr->preedit_foreground.pixel;
804 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
805 error |= GDK_IC_PREEDIT_FOREGROUND;
808 if (mask & GDK_IC_PREEDIT_BACKGROUND)
810 arg->name = XNBackground;
811 arg->value = (gpointer) attr->preedit_background.pixel;
813 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
814 error |= GDK_IC_PREEDIT_BACKGROUND;
817 if (mask & GDK_IC_PREEDIT_PIXMAP)
819 arg->name = XNBackgroundPixmap;
820 arg->value = (gpointer) GDK_WINDOW_XWINDOW(attr->preedit_pixmap);
822 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
823 error |= GDK_IC_PREEDIT_PIXMAP;
826 if (mask & GDK_IC_PREEDIT_COLORMAP)
828 arg->name = XNColormap;
829 arg->value = (gpointer) GDK_COLORMAP_XCOLORMAP(attr->preedit_colormap);
831 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
832 error |= GDK_IC_PREEDIT_COLORMAP;
836 if (mask & GDK_IC_STATUS_FONTSET)
838 arg->name = XNFontSet;
839 arg->value = (gpointer) GDK_FONT_XFONT(attr->status_fontset);
841 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
842 error |= GDK_IC_STATUS_FONTSET;
845 if (mask & GDK_IC_STATUS_AREA)
849 rect.x = attr->status_area.x;
850 rect.y = attr->status_area.y;
851 rect.width = attr->status_area.width;
852 rect.height = attr->status_area.height;
855 arg->value = (gpointer) ▭
857 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
858 error |= GDK_IC_STATUS_AREA;
861 if (mask & GDK_IC_STATUS_AREA_NEEDED)
865 rect.x = attr->status_area_needed.x;
866 rect.y = attr->status_area_needed.y;
867 rect.width = attr->status_area_needed.width;
868 rect.height = attr->status_area_needed.height;
871 arg->value = (gpointer) ▭
873 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
874 error |= GDK_IC_STATUS_AREA_NEEDED;
876 private->mask &= ~GDK_IC_STATUS_AREA_NEEDED;
879 if (mask & GDK_IC_STATUS_FOREGROUND)
881 arg->name = XNForeground;
882 arg->value = (gpointer) attr->status_foreground.pixel;
884 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
885 error |= GDK_IC_STATUS_FOREGROUND;
888 if (mask & GDK_IC_STATUS_BACKGROUND)
890 arg->name = XNBackground;
891 arg->value = (gpointer) attr->status_background.pixel;
893 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
894 error |= GDK_IC_STATUS_BACKGROUND;
897 if (mask & GDK_IC_STATUS_PIXMAP)
899 arg->name = XNBackgroundPixmap;
900 arg->value = (gpointer) GDK_WINDOW_XWINDOW(attr->status_pixmap);
902 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
903 error |= GDK_IC_STATUS_PIXMAP;
906 if (mask & GDK_IC_STATUS_COLORMAP)
908 arg->name = XNColormap;
909 arg->value = (gpointer) GDK_COLORMAP_XCOLORMAP(attr->status_colormap);
911 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
912 error |= GDK_IC_STATUS_COLORMAP;
919 gdk_ic_set_attr (GdkIC *ic,
921 GdkICAttributesType mask)
923 GdkICPrivate *private;
925 GdkICAttributesType error = 0;
926 GdkICAttributesType newattr = 0;
928 g_return_val_if_fail (ic != NULL, 0);
929 g_return_val_if_fail (attr != NULL, 0);
931 private = (GdkICPrivate *) ic;
932 pattr = private->attr;
934 /* Check and copy new attributes */
936 if (mask & GDK_IC_STYLE)
938 g_warning ("input style can be specified only when creating new ic.\n");
939 error |= GDK_IC_STYLE;
942 if (mask & GDK_IC_FILTER_EVENTS)
944 g_warning ("filter events is read only attributes.\n");
945 error |= GDK_IC_FILTER_EVENTS;
948 if (mask & GDK_IC_CLIENT_WINDOW)
950 g_warning ("client window can be specified only when creating new ic.\n");
951 error |= GDK_IC_CLIENT_WINDOW;
954 if (mask & GDK_IC_FOCUS_WINDOW)
956 if (attr->focus_window == NULL)
958 g_warning ("specified focus_window is invalid.\n");
959 error |= GDK_IC_FOCUS_WINDOW;
961 else if (pattr->focus_window != attr->focus_window)
963 if (pattr->focus_window != NULL)
964 gdk_window_unref (pattr->focus_window);
965 if (attr->focus_window != NULL)
966 gdk_window_ref (attr->focus_window);
967 pattr->focus_window = attr->focus_window;
968 newattr |= GDK_IC_FOCUS_WINDOW;
972 if (mask & GDK_IC_SPOT_LOCATION)
974 pattr->spot_location = attr->spot_location;
975 newattr |= GDK_IC_SPOT_LOCATION;
978 if (mask & GDK_IC_LINE_SPACING)
980 pattr->line_spacing = attr->line_spacing;
981 newattr |= GDK_IC_LINE_SPACING;
984 if (mask & GDK_IC_CURSOR)
986 pattr->cursor = attr->cursor;
987 newattr |= GDK_IC_CURSOR;
990 if (mask & GDK_IC_PREEDIT_FONTSET)
992 if (attr->preedit_fontset == NULL ||
993 attr->preedit_fontset->type != GDK_FONT_FONTSET)
995 g_warning ("gdk_font is NULL or not a fontset.\n");
996 error |= GDK_IC_PREEDIT_FONTSET;
998 else if (pattr->preedit_fontset != attr->preedit_fontset)
1000 if (pattr->preedit_fontset != NULL)
1001 gdk_font_unref (pattr->preedit_fontset);
1002 if (attr->preedit_fontset != NULL)
1003 gdk_font_ref (attr->preedit_fontset);
1004 pattr->preedit_fontset = attr->preedit_fontset;
1005 newattr |= GDK_IC_PREEDIT_FONTSET;
1009 if (mask & GDK_IC_PREEDIT_AREA)
1011 pattr->preedit_area = attr->preedit_area;
1012 newattr |= GDK_IC_PREEDIT_AREA;
1015 if (mask & GDK_IC_PREEDIT_AREA_NEEDED)
1017 if (attr->preedit_area_needed.width == 0 ||
1018 attr->preedit_area_needed.height == 0)
1020 g_warning ("width and height of preedit_area_needed must be non 0.\n");
1021 error |= GDK_IC_PREEDIT_AREA_NEEDED;
1025 pattr->preedit_area_needed = attr->preedit_area_needed;
1026 newattr |= GDK_IC_PREEDIT_AREA_NEEDED;
1030 if (mask & GDK_IC_PREEDIT_FOREGROUND)
1032 pattr->preedit_foreground = attr->preedit_foreground;
1033 newattr |= GDK_IC_PREEDIT_FOREGROUND;
1036 if (mask & GDK_IC_PREEDIT_BACKGROUND)
1038 pattr->preedit_background = attr->preedit_background;
1039 newattr |= GDK_IC_PREEDIT_BACKGROUND;
1042 if (mask & GDK_IC_PREEDIT_PIXMAP)
1044 if (attr->preedit_pixmap != NULL &&
1045 ((GdkPixmapPrivate *)attr->preedit_pixmap)->destroyed)
1047 g_warning ("Preedit pixmap is already destroyed.\n");
1048 error |= GDK_IC_PREEDIT_PIXMAP;
1052 if (pattr->preedit_pixmap != attr->preedit_pixmap)
1054 if (pattr->preedit_pixmap != NULL)
1055 gdk_pixmap_unref (pattr->preedit_pixmap);
1056 if (attr->preedit_pixmap)
1057 gdk_pixmap_ref (attr->preedit_pixmap);
1058 pattr->preedit_pixmap = attr->preedit_pixmap;
1059 newattr |= GDK_IC_PREEDIT_PIXMAP;
1064 if (mask & GDK_IC_PREEDIT_COLORMAP)
1066 if (pattr->preedit_colormap != attr->preedit_colormap)
1068 if (pattr->preedit_colormap != NULL)
1069 gdk_colormap_unref (pattr->preedit_colormap);
1070 if (attr->preedit_colormap != NULL)
1071 gdk_colormap_ref (attr->preedit_colormap);
1072 pattr->preedit_colormap = attr->preedit_colormap;
1073 newattr |= GDK_IC_PREEDIT_COLORMAP;
1077 if (mask & GDK_IC_STATUS_FONTSET)
1079 if (attr->status_fontset == NULL ||
1080 attr->status_fontset->type != GDK_FONT_FONTSET)
1082 g_warning ("gdk_font is NULL or not a fontset.\n");
1083 error |= GDK_IC_STATUS_FONTSET;
1085 else if (pattr->status_fontset != attr->status_fontset)
1087 if (pattr->status_fontset != NULL)
1088 gdk_font_unref (pattr->status_fontset);
1089 if (attr->status_fontset != NULL)
1090 gdk_font_ref (attr->status_fontset);
1091 pattr->status_fontset = attr->status_fontset;
1092 newattr |= GDK_IC_STATUS_FONTSET;
1096 if (mask & GDK_IC_STATUS_AREA)
1098 pattr->status_area = attr->status_area;
1099 newattr |= GDK_IC_STATUS_AREA;
1102 if (mask & GDK_IC_STATUS_AREA_NEEDED)
1104 if (attr->status_area_needed.width == 0 ||
1105 attr->status_area_needed.height == 0)
1107 g_warning ("width and height of status_area_needed must be non 0.\n");
1108 error |= GDK_IC_STATUS_AREA_NEEDED;
1112 pattr->status_area_needed = attr->status_area_needed;
1113 newattr |= GDK_IC_STATUS_AREA_NEEDED;
1117 if (mask & GDK_IC_STATUS_FOREGROUND)
1119 pattr->status_foreground = attr->status_foreground;
1120 newattr |= GDK_IC_STATUS_FOREGROUND;
1123 if (mask & GDK_IC_STATUS_BACKGROUND)
1125 pattr->status_background = attr->status_background;
1126 newattr |= GDK_IC_STATUS_BACKGROUND;
1129 if (mask & GDK_IC_STATUS_PIXMAP)
1131 if (attr->status_pixmap != NULL &&
1132 ((GdkPixmapPrivate *)attr->status_pixmap)->destroyed)
1134 g_warning ("Preedit pixmap is already destroyed.\n");
1135 error |= GDK_IC_STATUS_PIXMAP;
1139 if (pattr->status_pixmap != attr->status_pixmap)
1141 if (pattr->status_pixmap != NULL)
1142 gdk_pixmap_unref (pattr->status_pixmap);
1143 if (attr->status_pixmap)
1144 gdk_pixmap_ref (attr->status_pixmap);
1145 pattr->status_pixmap = attr->status_pixmap;
1146 newattr |= GDK_IC_STATUS_PIXMAP;
1151 if (mask & GDK_IC_STATUS_COLORMAP)
1153 if (pattr->status_colormap != attr->status_colormap)
1155 if (pattr->status_colormap != NULL)
1156 gdk_colormap_unref (pattr->status_colormap);
1157 if (attr->status_colormap != NULL)
1158 gdk_colormap_ref (attr->status_colormap);
1159 pattr->status_colormap = attr->status_colormap;
1160 newattr |= GDK_IC_STATUS_COLORMAP;
1164 if (private->xic == NULL)
1167 error |= gdk_ic_real_set_attr (ic, pattr, newattr);
1173 gdk_ic_get_attr (GdkIC *ic,
1175 GdkICAttributesType mask)
1177 GdkICPrivate *private;
1179 GdkICAttributesType known, unknown = 0;
1181 g_return_val_if_fail (ic != NULL, -1);
1182 g_return_val_if_fail (attr != NULL, -1);
1184 private = (GdkICPrivate *) ic;
1185 pattr = private->attr;
1187 known = mask & private->mask;
1189 if (known & GDK_IC_STYLE)
1190 attr->style = pattr->style;
1191 if (known & GDK_IC_CLIENT_WINDOW)
1192 attr->client_window = pattr->client_window;
1193 if (known & GDK_IC_FOCUS_WINDOW)
1194 attr->focus_window = pattr->focus_window;
1195 if (known & GDK_IC_FILTER_EVENTS)
1196 attr->filter_events = pattr->filter_events;
1197 if (known & GDK_IC_LINE_SPACING)
1198 attr->line_spacing = pattr->line_spacing;
1199 if (known & GDK_IC_CURSOR)
1200 attr->cursor = pattr->cursor;
1202 if (known & GDK_IC_PREEDIT_FONTSET)
1203 attr->preedit_fontset = pattr->preedit_fontset;
1204 if (known & GDK_IC_PREEDIT_AREA)
1205 attr->preedit_area = pattr->preedit_area;
1206 if (known & GDK_IC_PREEDIT_AREA_NEEDED)
1207 attr->preedit_area_needed = pattr->preedit_area_needed;
1208 if (known & GDK_IC_PREEDIT_FOREGROUND)
1209 attr->preedit_foreground = pattr->preedit_foreground;
1210 if (known & GDK_IC_PREEDIT_BACKGROUND)
1211 attr->preedit_background = pattr->preedit_background;
1212 if (known & GDK_IC_PREEDIT_PIXMAP)
1213 attr->preedit_pixmap = pattr->preedit_pixmap;
1214 if (known & GDK_IC_PREEDIT_COLORMAP)
1215 attr->preedit_colormap = pattr->preedit_colormap;
1217 if (known & GDK_IC_STATUS_FONTSET)
1218 attr->status_fontset = pattr->status_fontset;
1219 if (known & GDK_IC_STATUS_AREA)
1220 attr->status_area = pattr->status_area;
1221 if (known & GDK_IC_STATUS_AREA_NEEDED)
1222 attr->status_area_needed = pattr->status_area_needed;
1223 if (known & GDK_IC_STATUS_FOREGROUND)
1224 attr->status_foreground = pattr->status_foreground;
1225 if (known & GDK_IC_STATUS_BACKGROUND)
1226 attr->status_background = pattr->status_background;
1227 if (known & GDK_IC_STATUS_PIXMAP)
1228 attr->status_pixmap = pattr->status_pixmap;
1229 if (known & GDK_IC_STATUS_COLORMAP)
1230 attr->status_colormap = pattr->status_colormap;
1234 unknown = mask & ~(private->mask);
1236 if (unknown & GDK_IC_FOCUS_WINDOW)
1237 attr->focus_window = pattr->client_window;
1238 if (unknown & GDK_IC_FILTER_EVENTS)
1240 gdk_ic_get_events (ic);
1241 attr->filter_events = pattr->filter_events;
1243 if (mask & GDK_IC_SPOT_LOCATION)
1246 XVaNestedList *list;
1248 list = XVaCreateNestedList (0, XNSpotLocation, &point, NULL);
1249 if (XGetICValues (private->xic, XNPreeditAttributes, list, NULL))
1250 unknown &= ~GDK_IC_SPOT_LOCATION;
1253 pattr->spot_location.x = point.x;
1254 pattr->spot_location.y = point.y;
1255 private->mask |= GDK_IC_SPOT_LOCATION;
1257 attr->spot_location = pattr->spot_location;
1261 if (unknown & GDK_IC_PREEDIT_AREA_NEEDED)
1264 XVaNestedList *list;
1266 list = XVaCreateNestedList (0, XNAreaNeeded, &rect, NULL);
1267 if (XGetICValues (private->xic, XNPreeditAttributes, list, NULL))
1268 unknown &= ~GDK_IC_PREEDIT_AREA_NEEDED;
1271 pattr->preedit_area_needed.x = rect.x;
1272 pattr->preedit_area_needed.y = rect.y;
1273 pattr->preedit_area_needed.width = rect.width;
1274 pattr->preedit_area_needed.height = rect.height;
1275 private->mask |= GDK_IC_PREEDIT_AREA_NEEDED;
1277 attr->preedit_area = pattr->preedit_area;
1281 if (unknown & GDK_IC_STATUS_AREA_NEEDED)
1284 XVaNestedList *list;
1286 list = XVaCreateNestedList (0, XNAreaNeeded, &rect, NULL);
1287 if (XGetICValues (private->xic, XNStatusAttributes, list, NULL))
1288 unknown &= ~GDK_IC_STATUS_AREA_NEEDED;
1291 pattr->status_area_needed.x = rect.x;
1292 pattr->status_area_needed.y = rect.y;
1293 pattr->status_area_needed.width = rect.width;
1294 pattr->status_area_needed.height = rect.height;
1295 private->mask |= GDK_IC_STATUS_AREA_NEEDED;
1297 attr->status_area = pattr->status_area;
1303 return mask & ~known & ~unknown;
1307 gdk_ic_get_events (GdkIC *ic)
1312 GdkICPrivate *private;
1315 /* From gdkwindow.c */
1317 g_return_val_if_fail (ic != NULL, 0);
1319 private = (GdkICPrivate *) ic;
1321 if (private->mask & GDK_IC_FILTER_EVENTS)
1322 return private->attr->filter_events;
1324 if (XGetICValues (private->xic, XNFilterEvents, &xmask, NULL) != NULL)
1326 GDK_NOTE (XIM, g_warning ("Call to XGetICValues: %s failed", XNFilterEvents));
1331 for (i=0, bit=2; i < gdk_nevent_masks; i++, bit <<= 1)
1332 if (xmask & gdk_event_mask_table [i])
1335 xmask &= ~ gdk_event_mask_table [i];
1339 g_warning ("ic requires events not supported by the application (%#04lx)", xmask);
1341 private->attr->filter_events = mask;
1342 private->mask |= GDK_IC_FILTER_EVENTS;
1348 gdk_ic_cleanup (void)
1353 while (xim_ic_list != NULL)
1355 gdk_ic_destroy ((GdkIC *) xim_ic_list->data);
1358 #ifdef G_ENABLE_DEBUG
1359 if ((gdk_debug_flags & GDK_DEBUG_XIM) && destroyed > 0)
1361 g_warning ("Cleaned up %i IC(s)\n", destroyed);
1363 #endif /* G_ENABLE_DEBUG */
1366 #else /* !USE_XIM */
1369 gdk_im_begin (GdkIC *ic, GdkWindow* window)
1379 gdk_im_decide_style (GdkIMStyle supported_style)
1381 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
1385 gdk_im_set_best_style (GdkIMStyle style)
1387 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
1397 gdk_ic_new (GdkICAttr *attr, GdkICAttributesType mask)
1403 gdk_ic_destroy (GdkIC *ic)
1408 gdk_ic_get_style (GdkIC *ic)
1410 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
1414 gdk_ic_set_values (GdkIC *ic, ...)
1419 gdk_ic_get_values (GdkIC *ic, ...)
1424 gdk_ic_set_attr (GdkIC *ic, GdkICAttr *attr, GdkICAttributesType mask)
1430 gdk_ic_get_attr (GdkIC *ic, GdkICAttr *attr, GdkICAttributesType mask)
1436 gdk_ic_get_events (GdkIC *ic)
1441 #endif /* USE_XIM */
1446 * Returns a multi-byte string converted from the specified array
1447 * of wide characters. The string is newly allocated. The array of
1448 * wide characters must be null-terminated. If the conversion is
1449 * failed, it returns NULL.
1452 gdk_wcstombs (const GdkWChar *src)
1460 if (sizeof(wchar_t) != sizeof(GdkWChar))
1464 for (i=0; src[i]; i++);
1465 src_alt = g_new (wchar_t, i+1);
1467 src_alt[i] = src[i];
1468 if (XwcTextListToTextProperty (gdk_display, &src_alt, 1, XTextStyle, &tpr)
1478 if (XwcTextListToTextProperty (gdk_display, (wchar_t**)&src, 1,
1479 XTextStyle, &tpr) != Success)
1485 * We must copy the string into an area allocated by glib, because
1486 * the string 'tpr.value' must be freed by XFree().
1488 mbstr = g_strdup(tpr.value);
1496 while (src[length] != 0)
1499 mbstr = g_new (gchar, length + 1);
1501 for (i=0; i<length+1; i++)
1511 * Converts the specified string into wide characters, and, returns the
1512 * number of wide characters written. The string 'src' must be
1513 * null-terminated. If the conversion is failed, it returns -1.
1516 gdk_mbstowcs (GdkWChar *dest, const gchar *src, gint dest_max)
1521 wchar_t **wstrs, *wstr_src;
1524 if (XmbTextListToTextProperty (gdk_display, (char **)&src, 1, XTextStyle,
1528 /* NoMem or LocaleNotSupp */
1531 if (XwcTextPropertyToTextList (gdk_display, &tpr, &wstrs, &num_wstrs)
1539 wstr_src = wstrs[0];
1540 for (len_cpy=0; len_cpy<dest_max && wstr_src[len_cpy]; len_cpy++)
1541 dest[len_cpy] = wstr_src[len_cpy];
1542 XwcFreeStringList (wstrs);
1549 for (i=0; i<dest_max && src[i]; i++)