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.
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/.
27 #include <X11/Xlocale.h>
29 #include "gdk.h" /* For gdk_flush() */
31 #include "gdkpixmap.h"
32 #include "gdkprivate.h"
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
48 static gboolean gdk_use_mb;
53 #include <X11/Xresource.h>
55 /* The following routines duplicate functionality in Xlib to
56 * translate from varargs to X's internal opaque XVaNestedList.
58 * If all vendors have stuck close to the reference implementation,
59 * then we should hopefully be OK.
68 static void gdk_im_instantiate_cb (Display *display,
72 static void gdk_im_destroy_cb (XIM im,
75 static gint gdk_im_real_open (void);
76 static void gdk_ic_real_new (GdkIC *ic);
78 static GdkICAttributesType gdk_ic_real_set_attr (GdkIC *ic,
80 GdkICAttributesType mask);
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;
90 *--------------------------------------------------------------
99 *--------------------------------------------------------------
103 gdk_set_locale (void)
106 gchar *current_locale;
110 if (!setlocale (LC_ALL,""))
111 g_warning ("locale not supported by C library");
113 if (!XSupportsLocale ())
115 g_warning ("locale not supported by Xlib, locale set to C");
116 setlocale (LC_ALL, "C");
119 if (!XSetLocaleModifiers (""))
120 g_warning ("can not set locale modifiers");
122 current_locale = setlocale (LC_ALL, NULL);
124 if ((strcmp (current_locale, "C")) && (strcmp (current_locale, "POSIX")))
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.
134 if ((MB_CUR_MAX == 2) &&
135 (mbstowcs (&result, "\xdd\xa5", 1) > 0) &&
138 if ((strlen (current_locale) < 4) ||
139 g_strcasecmp (current_locale + strlen(current_locale) - 4, "utf8"))
142 #endif /* X_LOCALE */
146 g_message ("%s multi-byte string functions.",
147 gdk_use_mb ? "Using" : "Not using"));
149 return current_locale;
155 *--------------------------------------------------------------
158 * Begin using input method with XIM Protocol(X11R6 standard)
161 * "ic" is the "Input Context" which is created by gtk_ic_new.
162 * The input area is specified with "window".
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.
171 *--------------------------------------------------------------
175 gdk_im_begin (GdkIC *ic, GdkWindow* window)
177 GdkICPrivate *private;
180 g_return_if_fail (ic != NULL);
182 private = (GdkICPrivate *) ic;
184 attr.focus_window = window;
185 gdk_ic_set_attr (ic, &attr, GDK_IC_FOCUS_WINDOW);
187 if (private != gdk_xim_ic)
192 XSetICFocus (private->xic);
193 GDK_NOTE (XIM, g_message ("im_begin icfocus : %p(%ld)\n",
195 GDK_WINDOW_XWINDOW(private->attr->focus_window)));
198 gdk_xim_ic = private;
199 gdk_xim_window = window;
203 *--------------------------------------------------------------
206 * End using input method with XIM Protocol(X11R6 standard)
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.
216 *--------------------------------------------------------------
222 if (gdk_xim_ic && gdk_xim_ic->xic)
224 XUnsetICFocus (gdk_xim_ic->xic);
225 GDK_NOTE (XIM, g_message ("im_end unfocus : %p\n", gdk_xim_ic->xic));
228 gdk_xim_window = NULL;
232 gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
234 GdkIMStyle s1, s2, u;
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)))
242 s1 = style1 & GDK_IM_PREEDIT_MASK;
243 s2 = style2 & GDK_IM_PREEDIT_MASK;
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;
255 s1 = style1 & GDK_IM_STATUS_MASK;
256 s2 = style2 & GDK_IM_STATUS_MASK;
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;
267 return 0; /* Get rid of stupid warning */
271 gdk_im_decide_style (GdkIMStyle supported_style)
274 GdkIMStyle style, tmp;
276 g_return_val_if_fail (xim_styles != NULL, 0);
279 for (i=0; i<xim_styles->count_styles; i++)
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);
289 gdk_im_set_best_style (GdkIMStyle style)
291 if (style & GDK_IM_PREEDIT_MASK)
293 xim_best_allowed_style &= ~GDK_IM_PREEDIT_MASK;
295 xim_best_allowed_style |= GDK_IM_PREEDIT_NONE;
296 if (!(style & GDK_IM_PREEDIT_NONE))
298 xim_best_allowed_style |= GDK_IM_PREEDIT_NOTHING;
299 if (!(style & GDK_IM_PREEDIT_NOTHING))
301 xim_best_allowed_style |= GDK_IM_PREEDIT_AREA;
302 if (!(style & GDK_IM_PREEDIT_AREA))
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;
311 if (style & GDK_IM_STATUS_MASK)
313 xim_best_allowed_style &= ~GDK_IM_STATUS_MASK;
315 xim_best_allowed_style |= GDK_IM_STATUS_NONE;
316 if (!(style & GDK_IM_STATUS_NONE))
318 xim_best_allowed_style |= GDK_IM_STATUS_NOTHING;
319 if (!(style & GDK_IM_STATUS_NOTHING))
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;
328 return xim_best_allowed_style;
333 gdk_im_destroy_cb (XIM im, XPointer client_data, XPointer call_data)
336 GdkICPrivate *private;
338 GDK_NOTE (XIM, g_message ("Ouch, Input Method is destroyed!!\n"));
348 for (node = xim_ic_list; node != NULL; node = g_list_next(node))
350 private = (GdkICPrivate *) (node->data);
354 XRegisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL,
355 gdk_im_instantiate_cb, NULL);
359 gdk_im_instantiate_cb (Display *display,
360 XPointer client_data, XPointer call_data)
362 GDK_NOTE (XIM, g_message ("New IM is instantiated."));
363 if (display != gdk_display)
369 XUnregisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL,
370 gdk_im_instantiate_cb, NULL);
375 gdk_im_real_open (void)
379 xim_im = XOpenIM (GDK_DISPLAY(), NULL, NULL, NULL);
382 GDK_NOTE (XIM, g_warning ("Unable to open IM."));
388 XIMCallback destroy_cb;
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."));
396 XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL);
398 for (node = xim_ic_list; node != NULL; node = g_list_next(node))
400 GdkICPrivate *private = (GdkICPrivate *) (node->data);
401 if (private->xic == NULL)
402 gdk_ic_real_new ((GdkIC *)private);
412 gdk_xim_window = (GdkWindow*)NULL;
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);
422 if (gdk_im_real_open ())
426 XRegisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL,
427 gdk_im_instantiate_cb, NULL);
451 return (xim_im != NULL);
455 gdk_ic_real_new (GdkIC *ic)
457 XPoint spot_location;
458 XRectangle preedit_area;
459 XRectangle status_area;
460 XVaNestedList *preedit_attr = NULL;
461 XVaNestedList *status_attr = NULL;
463 GdkICPrivate *private;
464 GdkICAttributesType mask = GDK_IC_ALL_REQ;
466 private = (GdkICPrivate *) ic;
467 attr = private->attr;
469 switch (attr->style & GDK_IM_PREEDIT_MASK)
471 case GDK_IM_PREEDIT_AREA:
472 mask |= GDK_IC_PREEDIT_AREA_REQ;
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;
479 preedit_attr = XVaCreateNestedList (0,
480 XNArea, &preedit_area,
482 GDK_FONT_XFONT(attr->preedit_fontset),
486 case GDK_IM_PREEDIT_POSITION:
487 mask |= GDK_IC_PREEDIT_POSITION_REQ;
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;
494 spot_location.x = attr->spot_location.x;
495 spot_location.y = attr->spot_location.y;
497 preedit_attr = XVaCreateNestedList (0,
498 XNArea, &preedit_area,
500 GDK_FONT_XFONT(attr->preedit_fontset),
501 XNSpotLocation, &spot_location,
506 switch (attr->style & GDK_IM_STATUS_MASK)
508 case GDK_IM_STATUS_AREA:
509 mask |= GDK_IC_STATUS_AREA_REQ;
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;
516 status_attr = XVaCreateNestedList (0,
517 XNArea, &status_area,
519 GDK_FONT_XFONT(attr->status_fontset),
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.
530 if (preedit_attr != NULL && status_attr != NULL)
531 private->xic = XCreateIC (xim_im,
535 GDK_WINDOW_XWINDOW(attr->client_window),
541 else if (preedit_attr != NULL)
542 private->xic = XCreateIC (xim_im,
546 GDK_WINDOW_XWINDOW(attr->client_window),
550 else if (status_attr != NULL)
551 private->xic = XCreateIC (xim_im,
555 GDK_WINDOW_XWINDOW(attr->client_window),
560 private->xic = XCreateIC (xim_im,
564 GDK_WINDOW_XWINDOW(attr->client_window),
568 XFree (preedit_attr);
572 if (private->xic == NULL)
573 g_warning ("can not create input context with specified input style.");
575 gdk_ic_real_set_attr (ic, private->attr, private->mask & ~mask);
579 gdk_ic_new (GdkICAttr *attr, GdkICAttributesType mask)
581 GdkICPrivate *private;
583 GdkICAttributesType invalid_mask;
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);
589 switch (attr->style & GDK_IM_PREEDIT_MASK)
592 g_warning ("preedit style is not specified.\n");
596 case GDK_IM_PREEDIT_AREA:
597 if ((mask & GDK_IC_PREEDIT_AREA_REQ) != GDK_IC_PREEDIT_AREA_REQ)
601 case GDK_IM_PREEDIT_POSITION:
602 if ((mask & GDK_IC_PREEDIT_POSITION_REQ) != GDK_IC_PREEDIT_POSITION_REQ)
607 switch (attr->style & GDK_IM_STATUS_MASK)
610 g_warning ("status style is not specified.\n");
614 case GDK_IM_STATUS_AREA:
615 if ((mask & GDK_IC_STATUS_AREA_REQ) != GDK_IC_STATUS_AREA_REQ)
623 g_warning ("IC attribute is not enough to required input style.\n");
627 if (attr->client_window == NULL ||
628 GDK_DRAWABLE_DESTROYED (attr->client_window))
630 g_warning ("Client_window is null or already destroyed.\n");
634 private = g_new0 (GdkICPrivate, 1);
635 private->attr = pattr = gdk_ic_attr_new ();
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;
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);
645 switch (attr->style & GDK_IM_PREEDIT_MASK)
647 case GDK_IM_PREEDIT_AREA:
648 if (invalid_mask & GDK_IC_PREEDIT_AREA_REQ)
652 case GDK_IM_PREEDIT_POSITION:
653 if (invalid_mask & GDK_IC_PREEDIT_POSITION_REQ)
658 switch (attr->style & GDK_IM_STATUS_MASK)
660 case GDK_IM_STATUS_AREA:
661 if (invalid_mask & GDK_IC_STATUS_AREA_REQ)
668 g_warning ("Essential attributes for required style are invalid.\n");
669 gdk_ic_destroy ((GdkIC *)private);
674 gdk_ic_real_new ((GdkIC *)private);
676 xim_ic_list = g_list_append (xim_ic_list, private);
678 return (GdkIC *)private;
682 gdk_ic_destroy (GdkIC *ic)
684 GdkICPrivate *private;
686 g_return_if_fail (ic != NULL);
688 private = (GdkICPrivate *) ic;
690 if (gdk_xim_ic == private)
693 GDK_NOTE (XIM, g_message ("ic_destroy %p\n", private->xic));
694 if (private->xic != NULL)
695 XDestroyIC (private->xic);
697 if (private->mask & GDK_IC_CLIENT_WINDOW)
698 gdk_window_unref (private->attr->client_window);
699 if (private->mask & GDK_IC_FOCUS_WINDOW)
700 gdk_window_unref (private->attr->focus_window);
702 if (private->mask & GDK_IC_PREEDIT_FONTSET)
703 gdk_font_unref (private->attr->preedit_fontset);
704 if (private->mask & GDK_IC_PREEDIT_PIXMAP)
705 gdk_pixmap_unref (private->attr->preedit_pixmap);
706 if (private->mask & GDK_IC_PREEDIT_COLORMAP)
707 gdk_colormap_unref (private->attr->preedit_colormap);
709 if (private->mask & GDK_IC_STATUS_FONTSET)
710 gdk_font_unref (private->attr->status_fontset);
711 if (private->mask & GDK_IC_STATUS_PIXMAP)
712 gdk_pixmap_unref (private->attr->status_pixmap);
713 if (private->mask & GDK_IC_STATUS_COLORMAP)
714 gdk_colormap_unref (private->attr->status_colormap);
716 xim_ic_list = g_list_remove (xim_ic_list, private);
717 gdk_ic_attr_destroy (private->attr);
722 gdk_ic_get_style (GdkIC *ic)
724 GdkICPrivate *private;
726 g_return_val_if_fail (ic != NULL, 0);
728 private = (GdkICPrivate *) ic;
730 return private->attr->style;
734 * for keeping binary compatibility if member of ic attributes is added.
737 gdk_ic_attr_new (void)
739 return g_new0 (GdkICAttr, 1);
743 gdk_ic_attr_destroy (GdkICAttr *attr)
745 g_return_if_fail (attr != NULL);
750 static GdkICAttributesType
751 gdk_ic_real_set_attr (GdkIC *ic,
753 GdkICAttributesType mask)
755 GdkICPrivate *private = (GdkICPrivate *)ic;
756 XIC xic = private->xic;
757 GdkICAttributesType error = 0;
758 GdkImArg arg[2] = {{NULL, NULL}, {NULL, NULL}};
760 if (mask & GDK_IC_FOCUS_WINDOW)
762 if (XSetICValues (xic, XNFocusWindow,
763 GDK_WINDOW_XWINDOW(attr->focus_window), NULL) != NULL)
764 error |= GDK_IC_FOCUS_WINDOW;
767 if (mask & GDK_IC_SPOT_LOCATION)
771 point.x = attr->spot_location.x;
772 point.y = attr->spot_location.y;
774 arg->name = XNSpotLocation;
775 arg->value = (gpointer) &point;
777 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
778 error |= GDK_IC_SPOT_LOCATION;
781 if (mask & GDK_IC_LINE_SPACING)
783 arg->name = XNLineSpace;
784 arg->value = GINT_TO_POINTER( attr->line_spacing );
786 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
787 error |= GDK_IC_LINE_SPACING;
790 if (mask & GDK_IC_CURSOR)
792 GdkCursorPrivate *cursor = (GdkCursorPrivate *) attr->cursor;
794 if (XSetICValues (xic, XNCursor, cursor->xcursor, NULL))
795 error |= GDK_IC_CURSOR;
798 if (mask & GDK_IC_PREEDIT_FONTSET)
800 arg->name = XNFontSet;
801 arg->value = (gpointer) GDK_FONT_XFONT(attr->preedit_fontset);
803 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
804 error |= GDK_IC_PREEDIT_FONTSET;
807 if (mask & GDK_IC_PREEDIT_AREA)
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;
817 arg->value = (gpointer) ▭
819 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
820 error |= GDK_IC_PREEDIT_AREA;
823 if (mask & GDK_IC_PREEDIT_AREA_NEEDED)
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;
833 arg->value = (gpointer) ▭
835 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
836 error |= GDK_IC_PREEDIT_AREA_NEEDED;
838 private->mask &= ~GDK_IC_PREEDIT_AREA_NEEDED;
841 if (mask & GDK_IC_PREEDIT_FOREGROUND)
843 arg->name = XNForeground;
844 arg->value = (gpointer) attr->preedit_foreground.pixel;
846 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
847 error |= GDK_IC_PREEDIT_FOREGROUND;
850 if (mask & GDK_IC_PREEDIT_BACKGROUND)
852 arg->name = XNBackground;
853 arg->value = (gpointer) attr->preedit_background.pixel;
855 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
856 error |= GDK_IC_PREEDIT_BACKGROUND;
859 if (mask & GDK_IC_PREEDIT_PIXMAP)
861 arg->name = XNBackgroundPixmap;
862 arg->value = (gpointer) GDK_WINDOW_XWINDOW(attr->preedit_pixmap);
864 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
865 error |= GDK_IC_PREEDIT_PIXMAP;
868 if (mask & GDK_IC_PREEDIT_COLORMAP)
870 arg->name = XNColormap;
871 arg->value = (gpointer) GDK_COLORMAP_XCOLORMAP(attr->preedit_colormap);
873 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
874 error |= GDK_IC_PREEDIT_COLORMAP;
878 if (mask & GDK_IC_STATUS_FONTSET)
880 arg->name = XNFontSet;
881 arg->value = (gpointer) GDK_FONT_XFONT(attr->status_fontset);
883 if (XSetICValues (xic, XNStatusAttributes, arg, NULL))
884 error |= GDK_IC_STATUS_FONTSET;
887 if (mask & GDK_IC_STATUS_AREA)
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;
897 arg->value = (gpointer) ▭
899 if (XSetICValues (xic, XNStatusAttributes, arg, NULL))
900 error |= GDK_IC_STATUS_AREA;
903 if (mask & GDK_IC_STATUS_AREA_NEEDED)
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;
913 arg->value = (gpointer) ▭
915 if (XSetICValues (xic, XNStatusAttributes, arg, NULL))
916 error |= GDK_IC_STATUS_AREA_NEEDED;
918 private->mask &= ~GDK_IC_STATUS_AREA_NEEDED;
921 if (mask & GDK_IC_STATUS_FOREGROUND)
923 arg->name = XNForeground;
924 arg->value = (gpointer) attr->status_foreground.pixel;
926 if (XSetICValues (xic, XNStatusAttributes, arg, NULL))
927 error |= GDK_IC_STATUS_FOREGROUND;
930 if (mask & GDK_IC_STATUS_BACKGROUND)
932 arg->name = XNBackground;
933 arg->value = (gpointer) attr->status_background.pixel;
935 if (XSetICValues (xic, XNStatusAttributes, arg, NULL))
936 error |= GDK_IC_STATUS_BACKGROUND;
939 if (mask & GDK_IC_STATUS_PIXMAP)
941 arg->name = XNBackgroundPixmap;
942 arg->value = (gpointer) GDK_WINDOW_XWINDOW(attr->status_pixmap);
944 if (XSetICValues (xic, XNStatusAttributes, arg, NULL))
945 error |= GDK_IC_STATUS_PIXMAP;
948 if (mask & GDK_IC_STATUS_COLORMAP)
950 arg->name = XNColormap;
951 arg->value = (gpointer) GDK_COLORMAP_XCOLORMAP(attr->status_colormap);
953 if (XSetICValues (xic, XNStatusAttributes, arg, NULL))
954 error |= GDK_IC_STATUS_COLORMAP;
961 gdk_ic_set_attr (GdkIC *ic,
963 GdkICAttributesType mask)
965 GdkICPrivate *private;
967 GdkICAttributesType error = 0;
968 GdkICAttributesType newattr = 0;
970 g_return_val_if_fail (ic != NULL, 0);
971 g_return_val_if_fail (attr != NULL, 0);
973 private = (GdkICPrivate *) ic;
974 pattr = private->attr;
976 /* Check and copy new attributes */
978 if (mask & GDK_IC_STYLE)
980 g_warning ("input style can be specified only when creating new ic.\n");
981 error |= GDK_IC_STYLE;
984 if (mask & GDK_IC_FILTER_EVENTS)
986 g_warning ("filter events is read only attributes.\n");
987 error |= GDK_IC_FILTER_EVENTS;
990 if (mask & GDK_IC_CLIENT_WINDOW)
992 g_warning ("client window can be specified only when creating new ic.\n");
993 error |= GDK_IC_CLIENT_WINDOW;
996 if (mask & GDK_IC_FOCUS_WINDOW)
998 if (attr->focus_window == NULL)
1000 g_warning ("specified focus_window is invalid.\n");
1001 error |= GDK_IC_FOCUS_WINDOW;
1003 else if (pattr->focus_window != attr->focus_window)
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;
1014 if (mask & GDK_IC_SPOT_LOCATION)
1016 pattr->spot_location = attr->spot_location;
1017 newattr |= GDK_IC_SPOT_LOCATION;
1020 if (mask & GDK_IC_LINE_SPACING)
1022 pattr->line_spacing = attr->line_spacing;
1023 newattr |= GDK_IC_LINE_SPACING;
1026 if (mask & GDK_IC_CURSOR)
1028 pattr->cursor = attr->cursor;
1029 newattr |= GDK_IC_CURSOR;
1032 if (mask & GDK_IC_PREEDIT_FONTSET)
1034 if (attr->preedit_fontset == NULL ||
1035 attr->preedit_fontset->type != GDK_FONT_FONTSET)
1037 g_warning ("gdk_font is NULL or not a fontset.\n");
1038 error |= GDK_IC_PREEDIT_FONTSET;
1040 else if (pattr->preedit_fontset != attr->preedit_fontset)
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;
1051 if (mask & GDK_IC_PREEDIT_AREA)
1053 pattr->preedit_area = attr->preedit_area;
1054 newattr |= GDK_IC_PREEDIT_AREA;
1057 if (mask & GDK_IC_PREEDIT_AREA_NEEDED)
1059 if (attr->preedit_area_needed.width == 0 ||
1060 attr->preedit_area_needed.height == 0)
1062 g_warning ("width and height of preedit_area_needed must be non 0.\n");
1063 error |= GDK_IC_PREEDIT_AREA_NEEDED;
1067 pattr->preedit_area_needed = attr->preedit_area_needed;
1068 newattr |= GDK_IC_PREEDIT_AREA_NEEDED;
1072 if (mask & GDK_IC_PREEDIT_FOREGROUND)
1074 pattr->preedit_foreground = attr->preedit_foreground;
1075 newattr |= GDK_IC_PREEDIT_FOREGROUND;
1078 if (mask & GDK_IC_PREEDIT_BACKGROUND)
1080 pattr->preedit_background = attr->preedit_background;
1081 newattr |= GDK_IC_PREEDIT_BACKGROUND;
1084 if (mask & GDK_IC_PREEDIT_PIXMAP)
1086 if (attr->preedit_pixmap != NULL &&
1087 GDK_DRAWABLE_DESTROYED (attr->preedit_pixmap))
1089 g_warning ("Preedit pixmap is already destroyed.\n");
1090 error |= GDK_IC_PREEDIT_PIXMAP;
1094 if (pattr->preedit_pixmap != attr->preedit_pixmap)
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;
1106 if (mask & GDK_IC_PREEDIT_COLORMAP)
1108 if (pattr->preedit_colormap != attr->preedit_colormap)
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;
1119 if (mask & GDK_IC_STATUS_FONTSET)
1121 if (attr->status_fontset == NULL ||
1122 attr->status_fontset->type != GDK_FONT_FONTSET)
1124 g_warning ("gdk_font is NULL or not a fontset.\n");
1125 error |= GDK_IC_STATUS_FONTSET;
1127 else if (pattr->status_fontset != attr->status_fontset)
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;
1138 if (mask & GDK_IC_STATUS_AREA)
1140 pattr->status_area = attr->status_area;
1141 newattr |= GDK_IC_STATUS_AREA;
1144 if (mask & GDK_IC_STATUS_AREA_NEEDED)
1146 if (attr->status_area_needed.width == 0 ||
1147 attr->status_area_needed.height == 0)
1149 g_warning ("width and height of status_area_needed must be non 0.\n");
1150 error |= GDK_IC_STATUS_AREA_NEEDED;
1154 pattr->status_area_needed = attr->status_area_needed;
1155 newattr |= GDK_IC_STATUS_AREA_NEEDED;
1159 if (mask & GDK_IC_STATUS_FOREGROUND)
1161 pattr->status_foreground = attr->status_foreground;
1162 newattr |= GDK_IC_STATUS_FOREGROUND;
1165 if (mask & GDK_IC_STATUS_BACKGROUND)
1167 pattr->status_background = attr->status_background;
1168 newattr |= GDK_IC_STATUS_BACKGROUND;
1171 if (mask & GDK_IC_STATUS_PIXMAP)
1173 if (attr->status_pixmap != NULL &&
1174 GDK_DRAWABLE_DESTROYED (attr->status_pixmap))
1176 g_warning ("Preedit pixmap is already destroyed.\n");
1177 error |= GDK_IC_STATUS_PIXMAP;
1181 if (pattr->status_pixmap != attr->status_pixmap)
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;
1193 if (mask & GDK_IC_STATUS_COLORMAP)
1195 if (pattr->status_colormap != attr->status_colormap)
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;
1206 if (private->xic == NULL)
1209 error |= gdk_ic_real_set_attr (ic, pattr, newattr);
1215 gdk_ic_get_attr (GdkIC *ic,
1217 GdkICAttributesType mask)
1219 GdkICPrivate *private;
1221 GdkICAttributesType known, unknown = 0;
1223 g_return_val_if_fail (ic != NULL, -1);
1224 g_return_val_if_fail (attr != NULL, -1);
1226 private = (GdkICPrivate *) ic;
1227 pattr = private->attr;
1229 known = mask & private->mask;
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;
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;
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;
1276 unknown = mask & ~(private->mask);
1278 if (unknown & GDK_IC_FOCUS_WINDOW)
1279 attr->focus_window = pattr->client_window;
1280 if (unknown & GDK_IC_FILTER_EVENTS)
1282 gdk_ic_get_events (ic);
1283 attr->filter_events = pattr->filter_events;
1285 if (mask & GDK_IC_SPOT_LOCATION)
1288 XVaNestedList *list;
1290 list = XVaCreateNestedList (0, XNSpotLocation, &point, NULL);
1291 if (XGetICValues (private->xic, XNPreeditAttributes, list, NULL))
1292 unknown &= ~GDK_IC_SPOT_LOCATION;
1295 pattr->spot_location.x = point.x;
1296 pattr->spot_location.y = point.y;
1297 private->mask |= GDK_IC_SPOT_LOCATION;
1299 attr->spot_location = pattr->spot_location;
1303 if (unknown & GDK_IC_PREEDIT_AREA_NEEDED)
1306 XVaNestedList *list;
1308 list = XVaCreateNestedList (0, XNAreaNeeded, &rect, NULL);
1309 if (XGetICValues (private->xic, XNPreeditAttributes, list, NULL))
1310 unknown &= ~GDK_IC_PREEDIT_AREA_NEEDED;
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;
1319 attr->preedit_area = pattr->preedit_area;
1323 if (unknown & GDK_IC_STATUS_AREA_NEEDED)
1326 XVaNestedList *list;
1328 list = XVaCreateNestedList (0, XNAreaNeeded, &rect, NULL);
1329 if (XGetICValues (private->xic, XNStatusAttributes, list, NULL))
1330 unknown &= ~GDK_IC_STATUS_AREA_NEEDED;
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;
1339 attr->status_area = pattr->status_area;
1345 return mask & ~known & ~unknown;
1349 gdk_ic_get_events (GdkIC *ic)
1354 GdkICPrivate *private;
1357 /* From gdkwindow.c */
1359 g_return_val_if_fail (ic != NULL, 0);
1361 private = (GdkICPrivate *) ic;
1363 if (private->mask & GDK_IC_FILTER_EVENTS)
1364 return private->attr->filter_events;
1366 if (XGetICValues (private->xic, XNFilterEvents, &xmask, NULL) != NULL)
1368 GDK_NOTE (XIM, g_warning ("Call to XGetICValues: %s failed", XNFilterEvents));
1373 for (i=0, bit=2; i < gdk_nevent_masks; i++, bit <<= 1)
1374 if (xmask & gdk_event_mask_table [i])
1377 xmask &= ~ gdk_event_mask_table [i];
1381 g_warning ("ic requires events not supported by the application (%#04lx)", xmask);
1383 private->attr->filter_events = mask;
1384 private->mask |= GDK_IC_FILTER_EVENTS;
1390 gdk_ic_cleanup (void)
1395 while (xim_ic_list != NULL)
1397 gdk_ic_destroy ((GdkIC *) xim_ic_list->data);
1400 #ifdef G_ENABLE_DEBUG
1401 if ((gdk_debug_flags & GDK_DEBUG_XIM) && destroyed > 0)
1403 g_warning ("Cleaned up %i IC(s)\n", destroyed);
1405 #endif /* G_ENABLE_DEBUG */
1408 #else /* !USE_XIM */
1411 gdk_im_begin (GdkIC *ic, GdkWindow* window)
1421 gdk_im_decide_style (GdkIMStyle supported_style)
1423 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
1427 gdk_im_set_best_style (GdkIMStyle style)
1429 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
1439 gdk_ic_new (GdkICAttr *attr, GdkICAttributesType mask)
1445 gdk_ic_destroy (GdkIC *ic)
1450 gdk_ic_get_style (GdkIC *ic)
1452 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
1456 gdk_ic_set_values (GdkIC *ic, ...)
1461 gdk_ic_get_values (GdkIC *ic, ...)
1466 gdk_ic_set_attr (GdkIC *ic, GdkICAttr *attr, GdkICAttributesType mask)
1472 gdk_ic_get_attr (GdkIC *ic, GdkICAttr *attr, GdkICAttributesType mask)
1478 gdk_ic_get_events (GdkIC *ic)
1483 #endif /* USE_XIM */
1488 * Returns a multi-byte string converted from the specified array
1489 * of wide characters. The string is newly allocated. The array of
1490 * wide characters must be null-terminated. If the conversion is
1491 * failed, it returns NULL.
1494 gdk_wcstombs (const GdkWChar *src)
1502 if (sizeof(wchar_t) != sizeof(GdkWChar))
1506 for (i=0; src[i]; i++);
1507 src_alt = g_new (wchar_t, i+1);
1509 src_alt[i] = src[i];
1510 if (XwcTextListToTextProperty (gdk_display, &src_alt, 1, XTextStyle, &tpr)
1520 if (XwcTextListToTextProperty (gdk_display, (wchar_t**)&src, 1,
1521 XTextStyle, &tpr) != Success)
1527 * We must copy the string into an area allocated by glib, because
1528 * the string 'tpr.value' must be freed by XFree().
1530 mbstr = g_strdup(tpr.value);
1538 while (src[length] != 0)
1541 mbstr = g_new (gchar, length + 1);
1543 for (i=0; i<length+1; i++)
1553 * Converts the specified string into wide characters, and, returns the
1554 * number of wide characters written. The string 'src' must be
1555 * null-terminated. If the conversion is failed, it returns -1.
1558 gdk_mbstowcs (GdkWChar *dest, const gchar *src, gint dest_max)
1563 wchar_t **wstrs, *wstr_src;
1566 if (XmbTextListToTextProperty (gdk_display, (char **)&src, 1, XTextStyle,
1570 /* NoMem or LocaleNotSupp */
1573 if (XwcTextPropertyToTextList (gdk_display, &tpr, &wstrs, &num_wstrs)
1583 wstr_src = wstrs[0];
1584 for (len_cpy=0; len_cpy<dest_max && wstr_src[len_cpy]; len_cpy++)
1585 dest[len_cpy] = wstr_src[len_cpy];
1586 XwcFreeStringList (wstrs);
1593 for (i=0; i<dest_max && src[i]; i++)