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 "gdkprivate.h"
41 /* If this variable is FALSE, it indicates that we should
42 * avoid trying to use multibyte conversion functions and
43 * assume everything is 1-byte per character
45 static gboolean gdk_use_mb;
50 #include <X11/Xresource.h>
52 /* The following routines duplicate functionality in Xlib to
53 * translate from varargs to X's internal opaque XVaNestedList.
55 * If all vendors have stuck close to the reference implementation,
56 * then we should hopefully be OK.
65 static void gdk_im_instantiate_cb (Display *display,
69 static void gdk_im_destroy_cb (XIM im,
72 static gint gdk_im_real_open (void);
73 static void gdk_ic_real_new (GdkIC *ic);
75 static GdkICAttributesType gdk_ic_real_set_attr (GdkIC *ic,
77 GdkICAttributesType mask);
79 static XIM xim_im; /* global IM */
80 static XIMStyles* xim_styles; /* im supports these styles */
81 static XIMStyle xim_best_allowed_style;
82 static GList* xim_ic_list;
87 *--------------------------------------------------------------
96 *--------------------------------------------------------------
100 gdk_set_locale (void)
103 gchar *current_locale;
107 if (!setlocale (LC_ALL,""))
108 g_warning ("locale not supported by C library");
110 if (!XSupportsLocale ())
112 g_warning ("locale not supported by Xlib, locale set to C");
113 setlocale (LC_ALL, "C");
116 if (!XSetLocaleModifiers (""))
117 g_warning ("can not set locale modifiers");
119 current_locale = setlocale (LC_ALL, NULL);
121 if ((strcmp (current_locale, "C")) && (strcmp (current_locale, "POSIX")))
126 /* Detect GNU libc, where mb == UTF8. Not useful unless it's
127 * really a UTF8 locale. The below still probably will
128 * screw up on Greek, Cyrillic, etc, encoded as UTF8.
131 if ((MB_CUR_MAX == 2) &&
132 (mbstowcs (&result, "\xdd\xa5", 1) > 0) &&
135 if ((strlen (current_locale) < 4) ||
136 g_strcasecmp (current_locale + strlen(current_locale) - 4, "utf8"))
139 #endif /* X_LOCALE */
143 g_message ("%s multi-byte string functions.",
144 gdk_use_mb ? "Using" : "Not using"));
146 return current_locale;
152 *--------------------------------------------------------------
155 * Begin using input method with XIM Protocol(X11R6 standard)
158 * "ic" is the "Input Context" which is created by gtk_ic_new.
159 * The input area is specified with "window".
162 * The gdk's event handling routine is switched to XIM based routine.
163 * XIM based routine uses XFilterEvent to get rid of events used by IM,
164 * and uses XmbLookupString instead of XLookupString.
168 *--------------------------------------------------------------
172 gdk_im_begin (GdkIC *ic, GdkWindow* window)
174 GdkICPrivate *private;
177 g_return_if_fail (ic != NULL);
179 private = (GdkICPrivate *) ic;
181 attr.focus_window = window;
182 gdk_ic_set_attr (ic, &attr, GDK_IC_FOCUS_WINDOW);
184 if (private != gdk_xim_ic)
189 XSetICFocus (private->xic);
190 GDK_NOTE (XIM, g_message ("im_begin icfocus : %p(%ld)\n",
192 GDK_WINDOW_XWINDOW(private->attr->focus_window)));
195 gdk_xim_ic = private;
196 gdk_xim_window = window;
200 *--------------------------------------------------------------
203 * End using input method with XIM Protocol(X11R6 standard)
208 * The gdk's event handling routine is switched to normal routine.
209 * User should call this function before ic and window will be destroyed.
213 *--------------------------------------------------------------
219 if (gdk_xim_ic && gdk_xim_ic->xic)
221 XUnsetICFocus (gdk_xim_ic->xic);
222 GDK_NOTE (XIM, g_message ("im_end unfocus : %p\n", gdk_xim_ic->xic));
225 gdk_xim_window = NULL;
229 gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
231 GdkIMStyle s1, s2, u;
233 if (style1 == 0) return style2;
234 if (style2 == 0) return style1;
235 if ((style1 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK))
236 == (style2 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK)))
239 s1 = style1 & GDK_IM_PREEDIT_MASK;
240 s2 = style2 & GDK_IM_PREEDIT_MASK;
243 if (u & GDK_IM_PREEDIT_CALLBACKS)
244 return (s1 == GDK_IM_PREEDIT_CALLBACKS)? style1:style2;
245 else if (u & GDK_IM_PREEDIT_POSITION)
246 return (s1 == GDK_IM_PREEDIT_POSITION)? style1:style2;
247 else if (u & GDK_IM_PREEDIT_AREA)
248 return (s1 == GDK_IM_PREEDIT_AREA)? style1:style2;
249 else if (u & GDK_IM_PREEDIT_NOTHING)
250 return (s1 == GDK_IM_PREEDIT_NOTHING)? style1:style2;
252 s1 = style1 & GDK_IM_STATUS_MASK;
253 s2 = style2 & GDK_IM_STATUS_MASK;
255 if ( u & GDK_IM_STATUS_CALLBACKS)
256 return (s1 == GDK_IM_STATUS_CALLBACKS)? style1:style2;
257 else if ( u & GDK_IM_STATUS_AREA)
258 return (s1 == GDK_IM_STATUS_AREA)? style1:style2;
259 else if ( u & GDK_IM_STATUS_NOTHING)
260 return (s1 == GDK_IM_STATUS_NOTHING)? style1:style2;
261 else if ( u & GDK_IM_STATUS_NONE)
262 return (s1 == GDK_IM_STATUS_NONE)? style1:style2;
264 return 0; /* Get rid of stupid warning */
268 gdk_im_decide_style (GdkIMStyle supported_style)
271 GdkIMStyle style, tmp;
273 g_return_val_if_fail (xim_styles != NULL, 0);
276 for (i=0; i<xim_styles->count_styles; i++)
278 tmp = xim_styles->supported_styles[i];
279 if (tmp == (tmp & supported_style & xim_best_allowed_style))
280 style = gdk_im_choose_better_style (style, tmp);
286 gdk_im_set_best_style (GdkIMStyle style)
288 if (style & GDK_IM_PREEDIT_MASK)
290 xim_best_allowed_style &= ~GDK_IM_PREEDIT_MASK;
292 xim_best_allowed_style |= GDK_IM_PREEDIT_NONE;
293 if (!(style & GDK_IM_PREEDIT_NONE))
295 xim_best_allowed_style |= GDK_IM_PREEDIT_NOTHING;
296 if (!(style & GDK_IM_PREEDIT_NOTHING))
298 xim_best_allowed_style |= GDK_IM_PREEDIT_AREA;
299 if (!(style & GDK_IM_PREEDIT_AREA))
301 xim_best_allowed_style |= GDK_IM_PREEDIT_POSITION;
302 if (!(style & GDK_IM_PREEDIT_POSITION))
303 xim_best_allowed_style |= GDK_IM_PREEDIT_CALLBACKS;
308 if (style & GDK_IM_STATUS_MASK)
310 xim_best_allowed_style &= ~GDK_IM_STATUS_MASK;
312 xim_best_allowed_style |= GDK_IM_STATUS_NONE;
313 if (!(style & GDK_IM_STATUS_NONE))
315 xim_best_allowed_style |= GDK_IM_STATUS_NOTHING;
316 if (!(style & GDK_IM_STATUS_NOTHING))
318 xim_best_allowed_style |= GDK_IM_STATUS_AREA;
319 if (!(style & GDK_IM_STATUS_AREA))
320 xim_best_allowed_style |= GDK_IM_STATUS_CALLBACKS;
325 return xim_best_allowed_style;
330 gdk_im_destroy_cb (XIM im, XPointer client_data, XPointer call_data)
333 GdkICPrivate *private;
335 GDK_NOTE (XIM, g_message ("Ouch, Input Method is destroyed!!\n"));
345 for (node = xim_ic_list; node != NULL; node = g_list_next(node))
347 private = (GdkICPrivate *) (node->data);
351 XRegisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL,
352 gdk_im_instantiate_cb, NULL);
356 gdk_im_instantiate_cb (Display *display,
357 XPointer client_data, XPointer call_data)
359 GDK_NOTE (XIM, g_message ("New IM is instantiated."));
360 if (display != gdk_display)
366 XUnregisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL,
367 gdk_im_instantiate_cb, NULL);
372 gdk_im_real_open (void)
376 xim_im = XOpenIM (GDK_DISPLAY(), NULL, NULL, NULL);
379 GDK_NOTE (XIM, g_warning ("Unable to open IM."));
385 XIMCallback destroy_cb;
387 destroy_cb.callback = gdk_im_destroy_cb;
388 destroy_cb.client_data = NULL;
389 if (NULL != (void *) XSetIMValues (xim_im, XNDestroyCallback, &destroy_cb, NULL))
390 GDK_NOTE (XIM, g_warning ("Could not set destroy callback to IM. Be careful to not destroy your input method."));
393 XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL);
395 for (node = xim_ic_list; node != NULL; node = g_list_next(node))
397 GdkICPrivate *private = (GdkICPrivate *) (node->data);
398 if (private->xic == NULL)
399 gdk_ic_real_new ((GdkIC *)private);
409 gdk_xim_window = (GdkWindow*)NULL;
413 /* initialize XIM Protocol variables */
414 if (!(xim_best_allowed_style & GDK_IM_PREEDIT_MASK))
415 gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS);
416 if (!(xim_best_allowed_style & GDK_IM_STATUS_MASK))
417 gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS);
419 if (gdk_im_real_open ())
423 XRegisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL,
424 gdk_im_instantiate_cb, NULL);
448 return (xim_im != NULL);
452 gdk_ic_real_new (GdkIC *ic)
454 XPoint spot_location;
455 XRectangle preedit_area;
456 XRectangle status_area;
457 XVaNestedList *preedit_attr = NULL;
458 XVaNestedList *status_attr = NULL;
460 GdkICPrivate *private;
461 GdkICAttributesType mask = GDK_IC_ALL_REQ;
463 private = (GdkICPrivate *) ic;
464 attr = private->attr;
466 switch (attr->style & GDK_IM_PREEDIT_MASK)
468 case GDK_IM_PREEDIT_AREA:
469 mask |= GDK_IC_PREEDIT_AREA_REQ;
471 preedit_area.x = attr->preedit_area.x;
472 preedit_area.y = attr->preedit_area.y;
473 preedit_area.width = attr->preedit_area.width;
474 preedit_area.height = attr->preedit_area.height;
476 preedit_attr = XVaCreateNestedList (0,
477 XNArea, &preedit_area,
479 GDK_FONT_XFONT(attr->preedit_fontset),
483 case GDK_IM_PREEDIT_POSITION:
484 mask |= GDK_IC_PREEDIT_POSITION_REQ;
486 preedit_area.x = attr->preedit_area.x;
487 preedit_area.y = attr->preedit_area.y;
488 preedit_area.width = attr->preedit_area.width;
489 preedit_area.height = attr->preedit_area.height;
491 spot_location.x = attr->spot_location.x;
492 spot_location.y = attr->spot_location.y;
494 preedit_attr = XVaCreateNestedList (0,
495 XNArea, &preedit_area,
497 GDK_FONT_XFONT(attr->preedit_fontset),
498 XNSpotLocation, &spot_location,
503 switch (attr->style & GDK_IM_STATUS_MASK)
505 case GDK_IM_STATUS_AREA:
506 mask |= GDK_IC_STATUS_AREA_REQ;
508 status_area.x = attr->status_area.x;
509 status_area.y = attr->status_area.y;
510 status_area.width = attr->status_area.width;
511 status_area.height = attr->status_area.height;
513 status_attr = XVaCreateNestedList (0,
514 XNArea, &status_area,
516 GDK_FONT_XFONT(attr->status_fontset),
521 /* We have to ensure that the client window is actually created on
522 * the X server, or XCreateIC fails because the XIM server can't get
523 * information about the client window.
527 if (preedit_attr != NULL && status_attr != NULL)
528 private->xic = XCreateIC (xim_im,
532 GDK_WINDOW_XWINDOW(attr->client_window),
538 else if (preedit_attr != NULL)
539 private->xic = XCreateIC (xim_im,
543 GDK_WINDOW_XWINDOW(attr->client_window),
547 else if (status_attr != NULL)
548 private->xic = XCreateIC (xim_im,
552 GDK_WINDOW_XWINDOW(attr->client_window),
557 private->xic = XCreateIC (xim_im,
561 GDK_WINDOW_XWINDOW(attr->client_window),
565 XFree (preedit_attr);
569 if (private->xic == NULL)
570 g_warning ("can not create input context with specified input style.");
572 gdk_ic_real_set_attr (ic, private->attr, private->mask & ~mask);
576 gdk_ic_new (GdkICAttr *attr, GdkICAttributesType mask)
578 GdkICPrivate *private;
580 GdkICAttributesType invalid_mask;
583 g_return_val_if_fail (attr != NULL, NULL);
584 g_return_val_if_fail ((mask & GDK_IC_ALL_REQ) == GDK_IC_ALL_REQ, NULL);
586 switch (attr->style & GDK_IM_PREEDIT_MASK)
589 g_warning ("preedit style is not specified.\n");
593 case GDK_IM_PREEDIT_AREA:
594 if ((mask & GDK_IC_PREEDIT_AREA_REQ) != GDK_IC_PREEDIT_AREA_REQ)
598 case GDK_IM_PREEDIT_POSITION:
599 if ((mask & GDK_IC_PREEDIT_POSITION_REQ) != GDK_IC_PREEDIT_POSITION_REQ)
604 switch (attr->style & GDK_IM_STATUS_MASK)
607 g_warning ("status style is not specified.\n");
611 case GDK_IM_STATUS_AREA:
612 if ((mask & GDK_IC_STATUS_AREA_REQ) != GDK_IC_STATUS_AREA_REQ)
620 g_warning ("IC attribute is not enough to required input style.\n");
624 if (attr->client_window == NULL ||
625 ((GdkWindowPrivate *)attr->client_window)->destroyed)
627 g_warning ("Client_window is null or already destroyed.\n");
631 private = g_new0 (GdkICPrivate, 1);
632 private->attr = pattr = gdk_ic_attr_new ();
634 gdk_window_ref (attr->client_window);
635 pattr->client_window = attr->client_window;
636 pattr->style = attr->style;
637 private->mask = GDK_IC_STYLE | GDK_IC_CLIENT_WINDOW;
639 /* XIC is still not created, so following call only copies attributes */
640 invalid_mask = gdk_ic_set_attr ((GdkIC *)private, attr, mask & ~GDK_IC_ALL_REQ);
642 switch (attr->style & GDK_IM_PREEDIT_MASK)
644 case GDK_IM_PREEDIT_AREA:
645 if (invalid_mask & GDK_IC_PREEDIT_AREA_REQ)
649 case GDK_IM_PREEDIT_POSITION:
650 if (invalid_mask & GDK_IC_PREEDIT_POSITION_REQ)
655 switch (attr->style & GDK_IM_STATUS_MASK)
657 case GDK_IM_STATUS_AREA:
658 if (invalid_mask & GDK_IC_STATUS_AREA_REQ)
665 g_warning ("Essential attributes for required style are invalid.\n");
666 gdk_ic_destroy ((GdkIC *)private);
671 gdk_ic_real_new ((GdkIC *)private);
673 xim_ic_list = g_list_append (xim_ic_list, private);
675 return (GdkIC *)private;
679 gdk_ic_destroy (GdkIC *ic)
681 GdkICPrivate *private;
683 g_return_if_fail (ic != NULL);
685 private = (GdkICPrivate *) ic;
687 if (gdk_xim_ic == private)
690 GDK_NOTE (XIM, g_message ("ic_destroy %p\n", private->xic));
691 if (private->xic != NULL)
692 XDestroyIC (private->xic);
694 if (private->mask & GDK_IC_CLIENT_WINDOW)
695 gdk_window_unref (private->attr->client_window);
696 if (private->mask & GDK_IC_FOCUS_WINDOW)
697 gdk_window_unref (private->attr->focus_window);
699 if (private->mask & GDK_IC_PREEDIT_FONTSET)
700 gdk_font_unref (private->attr->preedit_fontset);
701 if (private->mask & GDK_IC_PREEDIT_PIXMAP)
702 gdk_pixmap_unref (private->attr->preedit_pixmap);
703 if (private->mask & GDK_IC_PREEDIT_COLORMAP)
704 gdk_colormap_unref (private->attr->preedit_colormap);
706 if (private->mask & GDK_IC_STATUS_FONTSET)
707 gdk_font_unref (private->attr->status_fontset);
708 if (private->mask & GDK_IC_STATUS_PIXMAP)
709 gdk_pixmap_unref (private->attr->status_pixmap);
710 if (private->mask & GDK_IC_STATUS_COLORMAP)
711 gdk_colormap_unref (private->attr->status_colormap);
713 xim_ic_list = g_list_remove (xim_ic_list, private);
714 gdk_ic_attr_destroy (private->attr);
719 gdk_ic_get_style (GdkIC *ic)
721 GdkICPrivate *private;
723 g_return_val_if_fail (ic != NULL, 0);
725 private = (GdkICPrivate *) ic;
727 return private->attr->style;
731 * for keeping binary compatibility if member of ic attributes is added.
734 gdk_ic_attr_new (void)
736 return g_new0 (GdkICAttr, 1);
740 gdk_ic_attr_destroy (GdkICAttr *attr)
742 g_return_if_fail (attr != NULL);
747 static GdkICAttributesType
748 gdk_ic_real_set_attr (GdkIC *ic,
750 GdkICAttributesType mask)
752 GdkICPrivate *private = (GdkICPrivate *)ic;
753 XIC xic = private->xic;
754 GdkICAttributesType error = 0;
755 GdkImArg arg[2] = {{NULL, NULL}, {NULL, NULL}};
757 if (mask & GDK_IC_FOCUS_WINDOW)
759 if (XSetICValues (xic, XNFocusWindow,
760 GDK_WINDOW_XWINDOW(attr->focus_window), NULL) != NULL)
761 error |= GDK_IC_FOCUS_WINDOW;
764 if (mask & GDK_IC_SPOT_LOCATION)
768 point.x = attr->spot_location.x;
769 point.y = attr->spot_location.y;
771 arg->name = XNSpotLocation;
772 arg->value = (gpointer) &point;
774 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
775 error |= GDK_IC_SPOT_LOCATION;
778 if (mask & GDK_IC_LINE_SPACING)
780 arg->name = XNLineSpace;
781 arg->value = GINT_TO_POINTER( attr->line_spacing );
783 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
784 error |= GDK_IC_LINE_SPACING;
787 if (mask & GDK_IC_CURSOR)
789 GdkCursorPrivate *cursor = (GdkCursorPrivate *) attr->cursor;
791 if (XSetICValues (xic, XNCursor, cursor->xcursor, NULL))
792 error |= GDK_IC_CURSOR;
795 if (mask & GDK_IC_PREEDIT_FONTSET)
797 arg->name = XNFontSet;
798 arg->value = (gpointer) GDK_FONT_XFONT(attr->preedit_fontset);
800 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
801 error |= GDK_IC_PREEDIT_FONTSET;
804 if (mask & GDK_IC_PREEDIT_AREA)
808 rect.x = attr->preedit_area.x;
809 rect.y = attr->preedit_area.y;
810 rect.width = attr->preedit_area.width;
811 rect.height = attr->preedit_area.height;
814 arg->value = (gpointer) ▭
816 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
817 error |= GDK_IC_PREEDIT_AREA;
820 if (mask & GDK_IC_PREEDIT_AREA_NEEDED)
824 rect.x = attr->preedit_area_needed.x;
825 rect.y = attr->preedit_area_needed.y;
826 rect.width = attr->preedit_area_needed.width;
827 rect.height = attr->preedit_area_needed.height;
830 arg->value = (gpointer) ▭
832 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
833 error |= GDK_IC_PREEDIT_AREA_NEEDED;
835 private->mask &= ~GDK_IC_PREEDIT_AREA_NEEDED;
838 if (mask & GDK_IC_PREEDIT_FOREGROUND)
840 arg->name = XNForeground;
841 arg->value = (gpointer) attr->preedit_foreground.pixel;
843 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
844 error |= GDK_IC_PREEDIT_FOREGROUND;
847 if (mask & GDK_IC_PREEDIT_BACKGROUND)
849 arg->name = XNBackground;
850 arg->value = (gpointer) attr->preedit_background.pixel;
852 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
853 error |= GDK_IC_PREEDIT_BACKGROUND;
856 if (mask & GDK_IC_PREEDIT_PIXMAP)
858 arg->name = XNBackgroundPixmap;
859 arg->value = (gpointer) GDK_WINDOW_XWINDOW(attr->preedit_pixmap);
861 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
862 error |= GDK_IC_PREEDIT_PIXMAP;
865 if (mask & GDK_IC_PREEDIT_COLORMAP)
867 arg->name = XNColormap;
868 arg->value = (gpointer) GDK_COLORMAP_XCOLORMAP(attr->preedit_colormap);
870 if (XSetICValues (xic, XNPreeditAttributes, arg, NULL))
871 error |= GDK_IC_PREEDIT_COLORMAP;
875 if (mask & GDK_IC_STATUS_FONTSET)
877 arg->name = XNFontSet;
878 arg->value = (gpointer) GDK_FONT_XFONT(attr->status_fontset);
880 if (XSetICValues (xic, XNStatusAttributes, arg, NULL))
881 error |= GDK_IC_STATUS_FONTSET;
884 if (mask & GDK_IC_STATUS_AREA)
888 rect.x = attr->status_area.x;
889 rect.y = attr->status_area.y;
890 rect.width = attr->status_area.width;
891 rect.height = attr->status_area.height;
894 arg->value = (gpointer) ▭
896 if (XSetICValues (xic, XNStatusAttributes, arg, NULL))
897 error |= GDK_IC_STATUS_AREA;
900 if (mask & GDK_IC_STATUS_AREA_NEEDED)
904 rect.x = attr->status_area_needed.x;
905 rect.y = attr->status_area_needed.y;
906 rect.width = attr->status_area_needed.width;
907 rect.height = attr->status_area_needed.height;
910 arg->value = (gpointer) ▭
912 if (XSetICValues (xic, XNStatusAttributes, arg, NULL))
913 error |= GDK_IC_STATUS_AREA_NEEDED;
915 private->mask &= ~GDK_IC_STATUS_AREA_NEEDED;
918 if (mask & GDK_IC_STATUS_FOREGROUND)
920 arg->name = XNForeground;
921 arg->value = (gpointer) attr->status_foreground.pixel;
923 if (XSetICValues (xic, XNStatusAttributes, arg, NULL))
924 error |= GDK_IC_STATUS_FOREGROUND;
927 if (mask & GDK_IC_STATUS_BACKGROUND)
929 arg->name = XNBackground;
930 arg->value = (gpointer) attr->status_background.pixel;
932 if (XSetICValues (xic, XNStatusAttributes, arg, NULL))
933 error |= GDK_IC_STATUS_BACKGROUND;
936 if (mask & GDK_IC_STATUS_PIXMAP)
938 arg->name = XNBackgroundPixmap;
939 arg->value = (gpointer) GDK_WINDOW_XWINDOW(attr->status_pixmap);
941 if (XSetICValues (xic, XNStatusAttributes, arg, NULL))
942 error |= GDK_IC_STATUS_PIXMAP;
945 if (mask & GDK_IC_STATUS_COLORMAP)
947 arg->name = XNColormap;
948 arg->value = (gpointer) GDK_COLORMAP_XCOLORMAP(attr->status_colormap);
950 if (XSetICValues (xic, XNStatusAttributes, arg, NULL))
951 error |= GDK_IC_STATUS_COLORMAP;
958 gdk_ic_set_attr (GdkIC *ic,
960 GdkICAttributesType mask)
962 GdkICPrivate *private;
964 GdkICAttributesType error = 0;
965 GdkICAttributesType newattr = 0;
967 g_return_val_if_fail (ic != NULL, 0);
968 g_return_val_if_fail (attr != NULL, 0);
970 private = (GdkICPrivate *) ic;
971 pattr = private->attr;
973 /* Check and copy new attributes */
975 if (mask & GDK_IC_STYLE)
977 g_warning ("input style can be specified only when creating new ic.\n");
978 error |= GDK_IC_STYLE;
981 if (mask & GDK_IC_FILTER_EVENTS)
983 g_warning ("filter events is read only attributes.\n");
984 error |= GDK_IC_FILTER_EVENTS;
987 if (mask & GDK_IC_CLIENT_WINDOW)
989 g_warning ("client window can be specified only when creating new ic.\n");
990 error |= GDK_IC_CLIENT_WINDOW;
993 if (mask & GDK_IC_FOCUS_WINDOW)
995 if (attr->focus_window == NULL)
997 g_warning ("specified focus_window is invalid.\n");
998 error |= GDK_IC_FOCUS_WINDOW;
1000 else if (pattr->focus_window != attr->focus_window)
1002 if (pattr->focus_window != NULL)
1003 gdk_window_unref (pattr->focus_window);
1004 if (attr->focus_window != NULL)
1005 gdk_window_ref (attr->focus_window);
1006 pattr->focus_window = attr->focus_window;
1007 newattr |= GDK_IC_FOCUS_WINDOW;
1011 if (mask & GDK_IC_SPOT_LOCATION)
1013 pattr->spot_location = attr->spot_location;
1014 newattr |= GDK_IC_SPOT_LOCATION;
1017 if (mask & GDK_IC_LINE_SPACING)
1019 pattr->line_spacing = attr->line_spacing;
1020 newattr |= GDK_IC_LINE_SPACING;
1023 if (mask & GDK_IC_CURSOR)
1025 pattr->cursor = attr->cursor;
1026 newattr |= GDK_IC_CURSOR;
1029 if (mask & GDK_IC_PREEDIT_FONTSET)
1031 if (attr->preedit_fontset == NULL ||
1032 attr->preedit_fontset->type != GDK_FONT_FONTSET)
1034 g_warning ("gdk_font is NULL or not a fontset.\n");
1035 error |= GDK_IC_PREEDIT_FONTSET;
1037 else if (pattr->preedit_fontset != attr->preedit_fontset)
1039 if (pattr->preedit_fontset != NULL)
1040 gdk_font_unref (pattr->preedit_fontset);
1041 if (attr->preedit_fontset != NULL)
1042 gdk_font_ref (attr->preedit_fontset);
1043 pattr->preedit_fontset = attr->preedit_fontset;
1044 newattr |= GDK_IC_PREEDIT_FONTSET;
1048 if (mask & GDK_IC_PREEDIT_AREA)
1050 pattr->preedit_area = attr->preedit_area;
1051 newattr |= GDK_IC_PREEDIT_AREA;
1054 if (mask & GDK_IC_PREEDIT_AREA_NEEDED)
1056 if (attr->preedit_area_needed.width == 0 ||
1057 attr->preedit_area_needed.height == 0)
1059 g_warning ("width and height of preedit_area_needed must be non 0.\n");
1060 error |= GDK_IC_PREEDIT_AREA_NEEDED;
1064 pattr->preedit_area_needed = attr->preedit_area_needed;
1065 newattr |= GDK_IC_PREEDIT_AREA_NEEDED;
1069 if (mask & GDK_IC_PREEDIT_FOREGROUND)
1071 pattr->preedit_foreground = attr->preedit_foreground;
1072 newattr |= GDK_IC_PREEDIT_FOREGROUND;
1075 if (mask & GDK_IC_PREEDIT_BACKGROUND)
1077 pattr->preedit_background = attr->preedit_background;
1078 newattr |= GDK_IC_PREEDIT_BACKGROUND;
1081 if (mask & GDK_IC_PREEDIT_PIXMAP)
1083 if (attr->preedit_pixmap != NULL &&
1084 ((GdkPixmapPrivate *)attr->preedit_pixmap)->destroyed)
1086 g_warning ("Preedit pixmap is already destroyed.\n");
1087 error |= GDK_IC_PREEDIT_PIXMAP;
1091 if (pattr->preedit_pixmap != attr->preedit_pixmap)
1093 if (pattr->preedit_pixmap != NULL)
1094 gdk_pixmap_unref (pattr->preedit_pixmap);
1095 if (attr->preedit_pixmap)
1096 gdk_pixmap_ref (attr->preedit_pixmap);
1097 pattr->preedit_pixmap = attr->preedit_pixmap;
1098 newattr |= GDK_IC_PREEDIT_PIXMAP;
1103 if (mask & GDK_IC_PREEDIT_COLORMAP)
1105 if (pattr->preedit_colormap != attr->preedit_colormap)
1107 if (pattr->preedit_colormap != NULL)
1108 gdk_colormap_unref (pattr->preedit_colormap);
1109 if (attr->preedit_colormap != NULL)
1110 gdk_colormap_ref (attr->preedit_colormap);
1111 pattr->preedit_colormap = attr->preedit_colormap;
1112 newattr |= GDK_IC_PREEDIT_COLORMAP;
1116 if (mask & GDK_IC_STATUS_FONTSET)
1118 if (attr->status_fontset == NULL ||
1119 attr->status_fontset->type != GDK_FONT_FONTSET)
1121 g_warning ("gdk_font is NULL or not a fontset.\n");
1122 error |= GDK_IC_STATUS_FONTSET;
1124 else if (pattr->status_fontset != attr->status_fontset)
1126 if (pattr->status_fontset != NULL)
1127 gdk_font_unref (pattr->status_fontset);
1128 if (attr->status_fontset != NULL)
1129 gdk_font_ref (attr->status_fontset);
1130 pattr->status_fontset = attr->status_fontset;
1131 newattr |= GDK_IC_STATUS_FONTSET;
1135 if (mask & GDK_IC_STATUS_AREA)
1137 pattr->status_area = attr->status_area;
1138 newattr |= GDK_IC_STATUS_AREA;
1141 if (mask & GDK_IC_STATUS_AREA_NEEDED)
1143 if (attr->status_area_needed.width == 0 ||
1144 attr->status_area_needed.height == 0)
1146 g_warning ("width and height of status_area_needed must be non 0.\n");
1147 error |= GDK_IC_STATUS_AREA_NEEDED;
1151 pattr->status_area_needed = attr->status_area_needed;
1152 newattr |= GDK_IC_STATUS_AREA_NEEDED;
1156 if (mask & GDK_IC_STATUS_FOREGROUND)
1158 pattr->status_foreground = attr->status_foreground;
1159 newattr |= GDK_IC_STATUS_FOREGROUND;
1162 if (mask & GDK_IC_STATUS_BACKGROUND)
1164 pattr->status_background = attr->status_background;
1165 newattr |= GDK_IC_STATUS_BACKGROUND;
1168 if (mask & GDK_IC_STATUS_PIXMAP)
1170 if (attr->status_pixmap != NULL &&
1171 ((GdkPixmapPrivate *)attr->status_pixmap)->destroyed)
1173 g_warning ("Preedit pixmap is already destroyed.\n");
1174 error |= GDK_IC_STATUS_PIXMAP;
1178 if (pattr->status_pixmap != attr->status_pixmap)
1180 if (pattr->status_pixmap != NULL)
1181 gdk_pixmap_unref (pattr->status_pixmap);
1182 if (attr->status_pixmap)
1183 gdk_pixmap_ref (attr->status_pixmap);
1184 pattr->status_pixmap = attr->status_pixmap;
1185 newattr |= GDK_IC_STATUS_PIXMAP;
1190 if (mask & GDK_IC_STATUS_COLORMAP)
1192 if (pattr->status_colormap != attr->status_colormap)
1194 if (pattr->status_colormap != NULL)
1195 gdk_colormap_unref (pattr->status_colormap);
1196 if (attr->status_colormap != NULL)
1197 gdk_colormap_ref (attr->status_colormap);
1198 pattr->status_colormap = attr->status_colormap;
1199 newattr |= GDK_IC_STATUS_COLORMAP;
1203 if (private->xic == NULL)
1206 error |= gdk_ic_real_set_attr (ic, pattr, newattr);
1212 gdk_ic_get_attr (GdkIC *ic,
1214 GdkICAttributesType mask)
1216 GdkICPrivate *private;
1218 GdkICAttributesType known, unknown = 0;
1220 g_return_val_if_fail (ic != NULL, -1);
1221 g_return_val_if_fail (attr != NULL, -1);
1223 private = (GdkICPrivate *) ic;
1224 pattr = private->attr;
1226 known = mask & private->mask;
1228 if (known & GDK_IC_STYLE)
1229 attr->style = pattr->style;
1230 if (known & GDK_IC_CLIENT_WINDOW)
1231 attr->client_window = pattr->client_window;
1232 if (known & GDK_IC_FOCUS_WINDOW)
1233 attr->focus_window = pattr->focus_window;
1234 if (known & GDK_IC_FILTER_EVENTS)
1235 attr->filter_events = pattr->filter_events;
1236 if (known & GDK_IC_LINE_SPACING)
1237 attr->line_spacing = pattr->line_spacing;
1238 if (known & GDK_IC_CURSOR)
1239 attr->cursor = pattr->cursor;
1241 if (known & GDK_IC_PREEDIT_FONTSET)
1242 attr->preedit_fontset = pattr->preedit_fontset;
1243 if (known & GDK_IC_PREEDIT_AREA)
1244 attr->preedit_area = pattr->preedit_area;
1245 if (known & GDK_IC_PREEDIT_AREA_NEEDED)
1246 attr->preedit_area_needed = pattr->preedit_area_needed;
1247 if (known & GDK_IC_PREEDIT_FOREGROUND)
1248 attr->preedit_foreground = pattr->preedit_foreground;
1249 if (known & GDK_IC_PREEDIT_BACKGROUND)
1250 attr->preedit_background = pattr->preedit_background;
1251 if (known & GDK_IC_PREEDIT_PIXMAP)
1252 attr->preedit_pixmap = pattr->preedit_pixmap;
1253 if (known & GDK_IC_PREEDIT_COLORMAP)
1254 attr->preedit_colormap = pattr->preedit_colormap;
1256 if (known & GDK_IC_STATUS_FONTSET)
1257 attr->status_fontset = pattr->status_fontset;
1258 if (known & GDK_IC_STATUS_AREA)
1259 attr->status_area = pattr->status_area;
1260 if (known & GDK_IC_STATUS_AREA_NEEDED)
1261 attr->status_area_needed = pattr->status_area_needed;
1262 if (known & GDK_IC_STATUS_FOREGROUND)
1263 attr->status_foreground = pattr->status_foreground;
1264 if (known & GDK_IC_STATUS_BACKGROUND)
1265 attr->status_background = pattr->status_background;
1266 if (known & GDK_IC_STATUS_PIXMAP)
1267 attr->status_pixmap = pattr->status_pixmap;
1268 if (known & GDK_IC_STATUS_COLORMAP)
1269 attr->status_colormap = pattr->status_colormap;
1273 unknown = mask & ~(private->mask);
1275 if (unknown & GDK_IC_FOCUS_WINDOW)
1276 attr->focus_window = pattr->client_window;
1277 if (unknown & GDK_IC_FILTER_EVENTS)
1279 gdk_ic_get_events (ic);
1280 attr->filter_events = pattr->filter_events;
1282 if (mask & GDK_IC_SPOT_LOCATION)
1285 XVaNestedList *list;
1287 list = XVaCreateNestedList (0, XNSpotLocation, &point, NULL);
1288 if (XGetICValues (private->xic, XNPreeditAttributes, list, NULL))
1289 unknown &= ~GDK_IC_SPOT_LOCATION;
1292 pattr->spot_location.x = point.x;
1293 pattr->spot_location.y = point.y;
1294 private->mask |= GDK_IC_SPOT_LOCATION;
1296 attr->spot_location = pattr->spot_location;
1300 if (unknown & GDK_IC_PREEDIT_AREA_NEEDED)
1303 XVaNestedList *list;
1305 list = XVaCreateNestedList (0, XNAreaNeeded, &rect, NULL);
1306 if (XGetICValues (private->xic, XNPreeditAttributes, list, NULL))
1307 unknown &= ~GDK_IC_PREEDIT_AREA_NEEDED;
1310 pattr->preedit_area_needed.x = rect.x;
1311 pattr->preedit_area_needed.y = rect.y;
1312 pattr->preedit_area_needed.width = rect.width;
1313 pattr->preedit_area_needed.height = rect.height;
1314 private->mask |= GDK_IC_PREEDIT_AREA_NEEDED;
1316 attr->preedit_area = pattr->preedit_area;
1320 if (unknown & GDK_IC_STATUS_AREA_NEEDED)
1323 XVaNestedList *list;
1325 list = XVaCreateNestedList (0, XNAreaNeeded, &rect, NULL);
1326 if (XGetICValues (private->xic, XNStatusAttributes, list, NULL))
1327 unknown &= ~GDK_IC_STATUS_AREA_NEEDED;
1330 pattr->status_area_needed.x = rect.x;
1331 pattr->status_area_needed.y = rect.y;
1332 pattr->status_area_needed.width = rect.width;
1333 pattr->status_area_needed.height = rect.height;
1334 private->mask |= GDK_IC_STATUS_AREA_NEEDED;
1336 attr->status_area = pattr->status_area;
1342 return mask & ~known & ~unknown;
1346 gdk_ic_get_events (GdkIC *ic)
1351 GdkICPrivate *private;
1354 /* From gdkwindow.c */
1356 g_return_val_if_fail (ic != NULL, 0);
1358 private = (GdkICPrivate *) ic;
1360 if (private->mask & GDK_IC_FILTER_EVENTS)
1361 return private->attr->filter_events;
1363 if (XGetICValues (private->xic, XNFilterEvents, &xmask, NULL) != NULL)
1365 GDK_NOTE (XIM, g_warning ("Call to XGetICValues: %s failed", XNFilterEvents));
1370 for (i=0, bit=2; i < gdk_nevent_masks; i++, bit <<= 1)
1371 if (xmask & gdk_event_mask_table [i])
1374 xmask &= ~ gdk_event_mask_table [i];
1378 g_warning ("ic requires events not supported by the application (%#04lx)", xmask);
1380 private->attr->filter_events = mask;
1381 private->mask |= GDK_IC_FILTER_EVENTS;
1387 gdk_ic_cleanup (void)
1392 while (xim_ic_list != NULL)
1394 gdk_ic_destroy ((GdkIC *) xim_ic_list->data);
1397 #ifdef G_ENABLE_DEBUG
1398 if ((gdk_debug_flags & GDK_DEBUG_XIM) && destroyed > 0)
1400 g_warning ("Cleaned up %i IC(s)\n", destroyed);
1402 #endif /* G_ENABLE_DEBUG */
1405 #else /* !USE_XIM */
1408 gdk_im_begin (GdkIC *ic, GdkWindow* window)
1418 gdk_im_decide_style (GdkIMStyle supported_style)
1420 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
1424 gdk_im_set_best_style (GdkIMStyle style)
1426 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
1436 gdk_ic_new (GdkICAttr *attr, GdkICAttributesType mask)
1442 gdk_ic_destroy (GdkIC *ic)
1447 gdk_ic_get_style (GdkIC *ic)
1449 return GDK_IM_PREEDIT_NONE | GDK_IM_STATUS_NONE;
1453 gdk_ic_set_values (GdkIC *ic, ...)
1458 gdk_ic_get_values (GdkIC *ic, ...)
1463 gdk_ic_set_attr (GdkIC *ic, GdkICAttr *attr, GdkICAttributesType mask)
1469 gdk_ic_get_attr (GdkIC *ic, GdkICAttr *attr, GdkICAttributesType mask)
1475 gdk_ic_get_events (GdkIC *ic)
1480 #endif /* USE_XIM */
1485 * Returns a multi-byte string converted from the specified array
1486 * of wide characters. The string is newly allocated. The array of
1487 * wide characters must be null-terminated. If the conversion is
1488 * failed, it returns NULL.
1491 gdk_wcstombs (const GdkWChar *src)
1499 if (sizeof(wchar_t) != sizeof(GdkWChar))
1503 for (i=0; src[i]; i++);
1504 src_alt = g_new (wchar_t, i+1);
1506 src_alt[i] = src[i];
1507 if (XwcTextListToTextProperty (gdk_display, &src_alt, 1, XTextStyle, &tpr)
1517 if (XwcTextListToTextProperty (gdk_display, (wchar_t**)&src, 1,
1518 XTextStyle, &tpr) != Success)
1524 * We must copy the string into an area allocated by glib, because
1525 * the string 'tpr.value' must be freed by XFree().
1527 mbstr = g_strdup(tpr.value);
1535 while (src[length] != 0)
1538 mbstr = g_new (gchar, length + 1);
1540 for (i=0; i<length+1; i++)
1550 * Converts the specified string into wide characters, and, returns the
1551 * number of wide characters written. The string 'src' must be
1552 * null-terminated. If the conversion is failed, it returns -1.
1555 gdk_mbstowcs (GdkWChar *dest, const gchar *src, gint dest_max)
1560 wchar_t **wstrs, *wstr_src;
1563 if (XmbTextListToTextProperty (gdk_display, (char **)&src, 1, XTextStyle,
1567 /* NoMem or LocaleNotSupp */
1570 if (XwcTextPropertyToTextList (gdk_display, &tpr, &wstrs, &num_wstrs)
1580 wstr_src = wstrs[0];
1581 for (len_cpy=0; len_cpy<dest_max && wstr_src[len_cpy]; len_cpy++)
1582 dest[len_cpy] = wstr_src[len_cpy];
1583 XwcFreeStringList (wstrs);
1590 for (i=0; i<dest_max && src[i]; i++)