Patches to support internationalized input by:

Takashi Matsuda <matsu@arch.comp.kyutech.ac.jp>
  TANAKA Shinya <shinya@race.u-tokyo.ac.jp>

See ChangeLog entries for further details.

Also some small fixes to event handling in gdk/gdk.c; sending
clear events in gtk/gtkselection.c and cut-and-paste in
gtk/gtkentry.c
This commit is contained in:
Gnome CVS User
1997-11-27 04:16:39 +00:00
parent e522ad46ba
commit dd34bcca5e
24 changed files with 2418 additions and 185 deletions

View File

@ -14,6 +14,11 @@ libgdk_la_SOURCES = \
gdkglobals.c \
gdkimage.c \
gdkinput.c \
gdkinput.h \
gdkinputnone.h \
gdkinputcommon.h\
gdkinputgxi.h \
gdkinputxfree.h \
gdkpixmap.c \
gdkproperty.c \
gdkrectangle.c \
@ -21,6 +26,8 @@ libgdk_la_SOURCES = \
gdkvisual.c \
gdkwindow.c \
gdkxid.c \
gxid_lib.h \
gxid_proto.h \
gxid_lib.c
## this last one is ifdef'd out unless XINPUT_GXI is defined
## It's easier than trying to get automake to handle compiling
@ -29,16 +36,10 @@ libgdk_la_SOURCES = \
gdkinclude_HEADERS = \
gdk.h \
gdkcursors.h \
gdki18n.h \
gdkkeysyms.h \
gdkprivate.h \
gdktypes.h \
gdkinput.h \
gdkinputnone.h \
gdkinputcommon.h\
gdkinputgxi.h \
gdkinputxfree.h \
gxid_lib.h \
gxid_proto.h \
gdkx.h
libgdk_la_LDFLAGS = -version-info 1:0:0 \

699
gdk/gdk.c
View File

@ -17,13 +17,16 @@
*/
#include "../config.h"
#include <X11/Xlocale.h>
#include <ctype.h>
#include <locale.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#ifdef USE_XIM
#include <stdarg.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
@ -35,10 +38,17 @@
#include <X11/Xos.h>
#include <X11/Xutil.h>
#include <X11/Xmu/WinUtil.h>
#ifdef USE_XIM
#include <X11/Xresource.h>
#endif
#include <X11/cursorfont.h>
#include "gdk.h"
#include "gdkprivate.h"
#include "gdkinput.h"
#ifdef USE_XIM
#include "gdkx.h"
#include "gdkkeysyms.h"
#endif
#ifndef X_GETTIMEOFDAY
@ -120,6 +130,15 @@ static int gdk_x_io_error (Display *display);
static RETSIGTYPE gdk_signal (int signum);
#ifdef USE_XIM
static GdkIM gdk_im_get (void);
static gint gdk_im_open (XrmDatabase db,
gchar* res_name,
gchar* rec_class);
static void gdk_im_close (void);
static void gdk_ic_cleanup (void);
#endif /* USE_XIM */
/* Private variable declarations
*/
static int initialized = 0; /* 1 if the library is initialized,
@ -178,6 +197,17 @@ static GdkWindow *button_window[2]; /* The last 2 windows to rec
static guint button_number[2]; /* The last 2 buttons to be pressed.
*/
#ifdef USE_XIM
static gint xim_using; /* using XIM Protocol if TRUE */
static GdkIM xim_im; /* global IM */
static XIMStyles* xim_styles; /* im supports these styles */
static XIMStyle xim_best_allowed_style;
static GdkICPrivate *xim_ic; /* currently using IC */
static GdkWindow* xim_window; /* currently using Widow */
static GList* xim_ic_list;
#endif
#define OTHER_XEVENT_BUFSIZE 4
static XEvent other_xevent[OTHER_XEVENT_BUFSIZE]; /* XEvents passed along to user */
static int other_xevent_i = 0;
@ -326,6 +356,41 @@ gdk_init (int *argc,
}
}
#endif
#ifdef USE_XIM
else if (strcmp ("--xim-preedit", (*argv)[i]) == 0)
{
if ((i + 1) < *argc)
{
(*argv)[i++] = NULL;
if (strcmp ("none", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMPreeditNone);
else if (strcmp ("nothing", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMPreeditNothing);
else if (strcmp ("area", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMPreeditArea);
else if (strcmp ("position", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMPreeditPosition);
else if (strcmp ("callbacks", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMPreeditCallbacks);
}
}
else if (strcmp ("--xim-status", (*argv)[i]) == 0)
{
if ((i + 1) < *argc)
{
(*argv)[i++] = NULL;
if (strcmp ("none", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMStatusNone);
else if (strcmp ("nothing", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMStatusNothing);
else if (strcmp ("area", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMStatusArea);
else if (strcmp ("callbacks", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMStatusCallbacks);
}
}
#endif
i += 1;
}
@ -418,6 +483,23 @@ gdk_init (int *argc,
gdk_image_init ();
gdk_input_init ();
#ifdef USE_XIM
/* initialize XIM Protocol variables */
xim_using = FALSE;
xim_im = NULL;
xim_styles = NULL;
if (!(xim_best_allowed_style & GdkIMPreeditMask))
gdk_im_set_best_style (GdkIMPreeditCallbacks);
if (!(xim_best_allowed_style & GdkIMStatusMask))
gdk_im_set_best_style (GdkIMStatusCallbacks);
xim_ic = NULL;
xim_window = (GdkWindow*)NULL;
gdk_im_open (NULL, NULL, NULL);
if (gdk_im_get () == NULL)
g_warning ("unable to open input method.");
#endif
initialized = 1;
}
@ -623,7 +705,20 @@ gdk_event_get (GdkEvent *event,
/* If we get here we can rest assurred that an event
* has occurred. Read it.
*/
#ifdef USE_XIM
gint filter_status;
if (xim_using && xim_window)
do
{ /* dont dispatch events used by IM */
XNextEvent (gdk_display, &xevent);
filter_status = XFilterEvent (&xevent,
GDK_WINDOW_XWINDOW (xim_window));
} while (filter_status == True);
else
XNextEvent (gdk_display, &xevent);
#else
XNextEvent (gdk_display, &xevent);
#endif
event->any.send_event = xevent.xany.send_event;
@ -1370,7 +1465,12 @@ gdk_event_translate (GdkEvent *event,
GdkWindowPrivate *window_private;
XComposeStatus compose;
int charcount;
#ifdef USE_XIM
static gchar* buf = NULL;
static gint buf_len= 0;
#else
char buf[16];
#endif
gint return_val;
/* Are static variables used for this purpose thread-safe? */
@ -1421,24 +1521,78 @@ gdk_event_translate (GdkEvent *event,
case KeyPress:
/* Lookup the string corresponding to the given keysym.
*/
#ifdef USE_XIM
if (buf_len == 0)
{
buf_len = 128;
buf = g_new (gchar, buf_len);
}
if (xim_using == TRUE && xim_ic)
{
Status status;
/* Clear keyval. Depending on status, may not be set */
event->key.keyval = GDK_VoidSymbol;
charcount = XmbLookupString(xim_ic->xic,
&xevent->xkey, buf, buf_len-1,
(KeySym*) &event->key.keyval,
&status);
if (status == XBufferOverflow)
{ /* retry */
/* alloc adequate size of buffer */
if (gdk_debug_level >= 1)
g_print("XIM: overflow(required %i)\n", charcount);
while (buf_len <= charcount)
buf_len *= 2;
buf = (gchar *) g_realloc (buf, buf_len);
charcount = XmbLookupString (xim_ic->xic,
&xevent->xkey, buf, buf_len-1,
(KeySym*) &event->key.keyval,
&status);
}
if (status == XLookupNone)
{
return_val = FALSE;
break;
}
}
else
charcount = XLookupString (&xevent->xkey, buf, buf_len,
(KeySym*) &event->key.keyval,
&compose);
#else
charcount = XLookupString (&xevent->xkey, buf, 16,
(KeySym*) &event->key.keyval,
&compose);
#endif
if (charcount > 0 && buf[charcount-1] == '\0')
charcount --;
else
buf[charcount] = '\0';
/* Print debugging info.
*/
if (gdk_show_events)
g_print ("key press:\t\twindow: %ld key: %12s %d\n",
xevent->xkey.window - base_id,
XKeysymToString (event->key.keyval),
event->key.keyval);
{
g_print ("key press:\twindow: %ld key: %12s %d\n",
xevent->xkey.window - base_id,
event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
event->key.keyval);
if (charcount > 0)
g_print ("\t\tlength: %4d string: \"%s\"\n",
charcount, buf);
}
event->key.type = GDK_KEY_PRESS;
event->key.window = window;
event->key.time = xevent->xkey.time;
event->key.state = (GdkModifierType) xevent->xkey.state;
event->key.string = buf;
event->key.length = charcount;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case KeyRelease:
@ -1460,8 +1614,10 @@ gdk_event_translate (GdkEvent *event,
event->key.window = window;
event->key.time = xevent->xkey.time;
event->key.state = (GdkModifierType) xevent->xkey.state;
event->key.length = 0;
event->key.string = NULL;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case ButtonPress:
@ -1563,7 +1719,7 @@ gdk_event_translate (GdkEvent *event,
CWEventMask, &dnd_setwinattr);
}
}
return_val = window_private?(!window_private->destroyed):FALSE;
return_val = window_private && !window_private->destroyed;
break;
case ButtonRelease:
@ -1632,7 +1788,7 @@ gdk_event_translate (GdkEvent *event,
dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
dnd_drag_curwin = None;
}
return_val = window ? (!window_private->destroyed) : FALSE;
return_val = window_private && !window_private->destroyed;
break;
case MotionNotify:
@ -1728,7 +1884,7 @@ gdk_event_translate (GdkEvent *event,
return_val = FALSE;
}
else
return_val = window?(!window_private->destroyed):FALSE;
return_val = window_private && !window_private->destroyed;
break;
case EnterNotify:
@ -1789,7 +1945,7 @@ gdk_event_translate (GdkEvent *event,
XUngrabPointer(gdk_display, CurrentTime);
}
return_val = (window ? !window_private->destroyed : FALSE);
return_val = window_private && !window_private->destroyed;
break;
case LeaveNotify:
@ -1839,7 +1995,7 @@ gdk_event_translate (GdkEvent *event,
gdk_dnd.gdk_cursor_dragdefault, CurrentTime);
gdk_dnd.drag_really = 1;
}
return_val = window ? (!window_private->destroyed) : FALSE;
return_val = window_private && !window_private->destroyed;
break;
case FocusIn:
@ -1853,7 +2009,7 @@ gdk_event_translate (GdkEvent *event,
event->focus_change.window = window;
event->focus_change.in = TRUE;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case FocusOut:
@ -1867,7 +2023,7 @@ gdk_event_translate (GdkEvent *event,
event->focus_change.window = window;
event->focus_change.in = FALSE;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case KeymapNotify:
@ -1896,7 +2052,7 @@ gdk_event_translate (GdkEvent *event,
event->expose.area.height = xevent->xexpose.height;
event->expose.count = xevent->xexpose.count;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case GraphicsExpose:
@ -1914,7 +2070,7 @@ gdk_event_translate (GdkEvent *event,
event->expose.area.height = xevent->xgraphicsexpose.height;
event->expose.count = xevent->xexpose.count;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case NoExpose:
@ -1972,7 +2128,7 @@ gdk_event_translate (GdkEvent *event,
received_destroy_notify = TRUE;
window_to_destroy = window;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case UnmapNotify:
@ -1985,7 +2141,7 @@ gdk_event_translate (GdkEvent *event,
event->any.type = GDK_UNMAP;
event->any.window = window;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case MapNotify:
@ -1998,7 +2154,7 @@ gdk_event_translate (GdkEvent *event,
event->any.type = GDK_MAP;
event->any.window = window;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case ReparentNotify:
@ -2025,30 +2181,32 @@ gdk_event_translate (GdkEvent *event,
xevent->xconfigure.x, xevent->xconfigure.y,
xevent->xconfigure.width, xevent->xconfigure.height);
if (window_private &&
(window_private->extension_events != 0) &&
gdk_input_vtable.configure_event)
gdk_input_vtable.configure_event (&xevent->xconfigure, window);
if ((window_private->window_type != GDK_WINDOW_CHILD) &&
((window_private->width != xevent->xconfigure.width) ||
(window_private->height != xevent->xconfigure.height)))
if (window_private)
{
event->configure.type = GDK_CONFIGURE;
event->configure.window = window;
event->configure.x = xevent->xconfigure.x;
event->configure.y = xevent->xconfigure.y;
event->configure.width = xevent->xconfigure.width;
event->configure.height = xevent->xconfigure.height;
if ((window_private->extension_events != 0) &&
gdk_input_vtable.configure_event)
gdk_input_vtable.configure_event (&xevent->xconfigure, window);
window_private->x = xevent->xconfigure.x;
window_private->y = xevent->xconfigure.y;
window_private->width = xevent->xconfigure.width;
window_private->height = xevent->xconfigure.height;
if (window_private->resize_count > 1)
window_private->resize_count -= 1;
if ((window_private->window_type != GDK_WINDOW_CHILD) &&
((window_private->width != xevent->xconfigure.width) ||
(window_private->height != xevent->xconfigure.height)))
{
event->configure.type = GDK_CONFIGURE;
event->configure.window = window;
event->configure.x = xevent->xconfigure.x;
event->configure.y = xevent->xconfigure.y;
event->configure.width = xevent->xconfigure.width;
event->configure.height = xevent->xconfigure.height;
return_val = !window_private->destroyed;
window_private->x = xevent->xconfigure.x;
window_private->y = xevent->xconfigure.y;
window_private->width = xevent->xconfigure.width;
window_private->height = xevent->xconfigure.height;
if (window_private->resize_count > 1)
window_private->resize_count -= 1;
return_val = !window_private->destroyed;
}
}
break;
@ -2065,7 +2223,7 @@ gdk_event_translate (GdkEvent *event,
event->property.time = xevent->xproperty.time;
event->property.state = xevent->xproperty.state;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case SelectionClear:
@ -2078,7 +2236,7 @@ gdk_event_translate (GdkEvent *event,
event->selection.selection = xevent->xselectionclear.selection;
event->selection.time = xevent->xselectionclear.time;
return_val = !((GdkWindowPrivate*) window)->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case SelectionRequest:
@ -2094,7 +2252,7 @@ gdk_event_translate (GdkEvent *event,
event->selection.requestor = xevent->xselectionrequest.requestor;
event->selection.time = xevent->xselectionrequest.time;
return_val = !((GdkWindowPrivate*) window)->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case SelectionNotify:
@ -2110,7 +2268,7 @@ gdk_event_translate (GdkEvent *event,
event->selection.property = xevent->xselection.property;
event->selection.time = xevent->xselection.time;
return_val = !((GdkWindowPrivate*) window)->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case ColormapNotify:
@ -2157,7 +2315,7 @@ gdk_event_translate (GdkEvent *event,
event->any.type = GDK_DELETE;
event->any.window = window;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
}
else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
{
@ -2353,6 +2511,8 @@ gdk_event_translate (GdkEvent *event,
(window_private->extension_events != 0) &&
gdk_input_vtable.other_event)
return_val = gdk_input_vtable.other_event(event, xevent, window);
else
return_val = -1;
if (return_val < 0) /* not an XInput event, convert */
{
@ -2363,8 +2523,9 @@ gdk_event_translate (GdkEvent *event,
other_xevent_i = (other_xevent_i+1) % OTHER_XEVENT_BUFSIZE;
return_val = TRUE;
}
else
return_val = return_val && !window_private->destroyed;
return_val = return_val && !window_private->destroyed;
break;
}
@ -2424,6 +2585,12 @@ gdk_exit_func ()
{
if (initialized)
{
#ifdef USE_XIM
/* cleanup IC */
gdk_ic_cleanup ();
/* close IM */
gdk_im_close ();
#endif
gdk_image_exit ();
gdk_input_exit ();
gdk_key_repeat_restore ();
@ -2615,6 +2782,446 @@ gdk_dnd_drag_enter (Window dest)
}
}
#ifdef USE_XIM
/*
*--------------------------------------------------------------
* gdk_im_begin
*
* Begin using input method with XIM Protocol(X11R6 standard)
*
* Arguments:
* "ic" is the "Input Context" which is created by gtk_ic_new.
* The input area is specified with "window".
*
* Results:
* The gdk's event handling routine is switched to XIM based routine.
* XIM based routine uses XFilterEvent to get rid of events used by IM,
* and uses XmbLookupString instead of XLookupString.
*
* Side effects:
*
*--------------------------------------------------------------
*/
void gdk_im_begin (GdkIC ic, GdkWindow* window)
{
GdkEventMask event;
GdkICPrivate *private;
Window xwin;
g_return_if_fail (ic != NULL);
g_return_if_fail (window);
private = (GdkICPrivate *) ic;
xim_using = TRUE;
xim_ic = private;
xim_window = window;
if (gdk_im_ready())
{
XGetICValues (private->xic, XNFocusWindow, &xwin, NULL);
if (xwin != GDK_WINDOW_XWINDOW(window))
XSetICValues (private->xic, XNFocusWindow,
GDK_WINDOW_XWINDOW(window), NULL);
if (private != xim_ic)
XSetICFocus (private->xic);
}
}
/*
*--------------------------------------------------------------
* gdk_im_end
*
* End using input method with XIM Protocol(X11R6 standard)
*
* Arguments:
*
* Results:
* The gdk's event handling routine is switched to normal routine.
* User should call this function before ic and window will be destroyed.
*
* Side effects:
*
*--------------------------------------------------------------
*/
void gdk_im_end (void)
{
xim_using = FALSE;
xim_ic = NULL;
xim_window = NULL;
}
static GdkIM gdk_im_get (void)
{
return xim_im;
}
static GdkIMStyle
gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
{
GdkIMStyle s1, s2, u;
if (style1 == 0) return style2;
if (style2 == 0) return style1;
if ((style1 & (GdkIMPreeditMask | GdkIMStatusMask))
== (style2 & (GdkIMPreeditMask | GdkIMStatusMask)))
return style1;
s1 = style1 & GdkIMPreeditMask;
s2 = style2 & GdkIMPreeditMask;
u = s1 | s2;
if (s1 != s2) {
if (u & GdkIMPreeditCallbacks)
return (s1 == GdkIMPreeditCallbacks)? style1:style2;
else if (u & GdkIMPreeditPosition)
return (s1 == GdkIMPreeditPosition)? style1:style2;
else if (u & GdkIMPreeditArea)
return (s1 == GdkIMPreeditArea)? style1:style2;
else if (u & GdkIMPreeditNothing)
return (s1 == GdkIMPreeditNothing)? style1:style2;
} else {
s1 = style1 & GdkIMStatusMask;
s2 = style2 & GdkIMStatusMask;
u = s1 | s2;
if ( u & GdkIMStatusCallbacks)
return (s1 == GdkIMStatusCallbacks)? style1:style2;
else if ( u & GdkIMStatusArea)
return (s1 == GdkIMStatusArea)? style1:style2;
else if ( u & GdkIMStatusNothing)
return (s1 == GdkIMStatusNothing)? style1:style2;
else if ( u & GdkIMStatusNone)
return (s1 == GdkIMStatusNone)? style1:style2;
}
}
GdkIMStyle
gdk_im_decide_style (GdkIMStyle supported_style)
{
gint i;
GdkIMStyle style, tmp;
g_return_val_if_fail (xim_styles != NULL, 0);
style = 0;
for (i=0; i<xim_styles->count_styles; i++)
{
tmp = xim_styles->supported_styles[i];
if (tmp == (tmp & supported_style & xim_best_allowed_style))
style = gdk_im_choose_better_style (style, tmp);
}
return style;
}
GdkIMStyle
gdk_im_set_best_style (GdkIMStyle style)
{
if (style & GdkIMPreeditMask)
{
xim_best_allowed_style &= ~GdkIMPreeditMask;
xim_best_allowed_style |= GdkIMPreeditNone;
if (!(style & GdkIMPreeditNone))
{
xim_best_allowed_style |= GdkIMPreeditNothing;
if (!(style & GdkIMPreeditNothing))
{
xim_best_allowed_style |= GdkIMPreeditArea;
if (!(style & GdkIMPreeditArea))
{
xim_best_allowed_style |= GdkIMPreeditPosition;
if (!(style & GdkIMPreeditPosition))
xim_best_allowed_style |= GdkIMPreeditCallbacks;
}
}
}
}
if (style & GdkIMStatusMask)
{
xim_best_allowed_style &= ~GdkIMStatusMask;
xim_best_allowed_style |= GdkIMStatusNone;
if (!(style & GdkIMStatusNone))
{
xim_best_allowed_style |= GdkIMStatusNothing;
if (!(style & GdkIMStatusNothing))
{
xim_best_allowed_style |= GdkIMStatusArea;
if (!(style & GdkIMStatusArea))
xim_best_allowed_style |= GdkIMStatusCallbacks;
}
}
}
return xim_best_allowed_style;
}
static gint gdk_im_open (XrmDatabase db, gchar* res_name, gchar* res_class)
{
XIMStyle style;
int i;
xim_im = XOpenIM (GDK_DISPLAY(), db, res_name, res_class);
if (xim_im == NULL)
{
g_warning ("Don\'t open IM.");
return FALSE;
}
XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL);
return TRUE;
}
static void gdk_im_close (void)
{
if (xim_im)
{
XCloseIM (xim_im);
xim_im = NULL;
}
if (xim_styles)
{
XFree (xim_styles);
xim_styles = NULL;
}
}
gint gdk_im_ready (void)
{
return (xim_im != NULL);
}
GdkIC gdk_ic_new (GdkWindow* client_window,
GdkWindow* focus_window,
GdkIMStyle style, ...)
{
va_list list;
GdkICPrivate *private;
XVaNestedList preedit_attr;
g_return_val_if_fail (client_window != NULL, NULL);
g_return_val_if_fail (focus_window != NULL, NULL);
g_return_val_if_fail (gdk_im_ready(), NULL);
private = g_new (GdkICPrivate, 1);
va_start (list, style);
preedit_attr = (XVaNestedList) & (va_arg (list, void *));
va_end (list);
private->style = gdk_im_decide_style (style);
if (private->style != style)
{
g_warning ("can not create input context with specified input style.");
g_free (private);
return NULL;
}
private->xic = XCreateIC(gdk_im_get (),
XNInputStyle, style,
XNClientWindow, GDK_WINDOW_XWINDOW (client_window),
XNFocusWindow, GDK_WINDOW_XWINDOW (focus_window),
preedit_attr? XNPreeditAttributes : NULL, preedit_attr,
NULL);
if (!private->xic)
{
g_free (private);
return NULL;
}
xim_ic_list = g_list_append (xim_ic_list, private);
return private;
}
void gdk_ic_destroy (GdkIC ic)
{
GdkICPrivate *private;
g_return_if_fail (ic != NULL);
private = (GdkICPrivate *) ic;
if (xim_ic == private)
gdk_im_end ();
XDestroyIC (private->xic);
xim_ic_list = g_list_remove (xim_ic_list, private);
}
GdkIMStyle
gdk_ic_get_style (GdkIC ic)
{
GdkICPrivate *private;
g_return_val_if_fail (ic != NULL, 0);
private = (GdkICPrivate *) ic;
return private->style;
}
void
gdk_ic_set_values (GdkIC ic, ...)
{
va_list list;
XVaNestedList args;
GdkICPrivate *private;
g_return_if_fail (ic != NULL);
private = (GdkICPrivate *) ic;
va_start (list, ic);
args = (XVaNestedList) & (va_arg (list, void *));
va_end (list);
XSetICValues (private->xic, XNVaNestedList, args, NULL);
}
void
gdk_ic_get_values (GdkIC ic, ...)
{
va_list list;
XVaNestedList args;
GdkICPrivate *private;
g_return_if_fail (ic != NULL);
private = (GdkICPrivate *) ic;
va_start (list, ic);
args = (XVaNestedList) & (va_arg (list, void *));
va_end (list);
XGetICValues (private->xic, XNVaNestedList, args, NULL);
}
void gdk_ic_set_attr (GdkIC ic, const char *target, ...)
{
va_list list;
XVaNestedList attr;
GdkICPrivate *private;
g_return_if_fail (ic != NULL);
g_return_if_fail (target != NULL);
private = (GdkICPrivate *) ic;
va_start (list, target);
attr = (XVaNestedList) & (va_arg (list, void *));
va_end (list);
XSetICValues (private->xic, target, attr, NULL);
}
void gdk_ic_get_attr (GdkIC ic, const char *target, ...)
{
va_list list;
XVaNestedList attr;
GdkICPrivate *private;
g_return_if_fail (ic != NULL);
g_return_if_fail (target != NULL);
private = (GdkICPrivate *) ic;
va_start (list, target);
attr = (XVaNestedList) & (va_arg (list, void *));
va_end (list);
XGetICValues (private->xic, target, attr, NULL);
}
GdkEventMask
gdk_ic_get_events (GdkIC ic)
{
GdkEventMask mask;
glong xmask;
glong bit;
GdkICPrivate *private;
gint i;
/* From gdkwindow.c */
extern int nevent_masks;
extern int event_mask_table[];
g_return_val_if_fail (ic != NULL, 0);
private = (GdkICPrivate *) ic;
XGetICValues (private->xic, XNFilterEvents, &xmask, NULL);
mask = 0;
for (i=0, bit=2; i < nevent_masks; i++, bit <<= 1)
if (xmask & event_mask_table [i])
{
mask |= bit;
xmask &= ~ event_mask_table [i];
}
if (xmask)
g_warning ("ic requires the events not supported by the application (%04x)", xmask);
return mask;
}
static void gdk_ic_cleanup (void)
{
GList* node;
gint destroyed;
GdkICPrivate *private;
destroyed = 0;
for (node = xim_ic_list; node != NULL; node = node->next)
{
if (node->data)
{
private = (GdkICPrivate *) (node->data);
XDestroyIC (private->xic);
g_free (private);
destroyed++;
}
}
if (gdk_debug_level >= 1 && destroyed > 0)
{
g_warning ("Cleanuped %i IC\n", destroyed);
}
g_list_free(xim_ic_list);
xim_ic_list = NULL;
}
#ifdef X_LOCALE
gint
_g_mbtowc (wchar_t *wstr, const char *str, size_t len)
{
static wchar_t wcs[MB_CUR_MAX + 1];
static gchar mbs[MB_CUR_MAX + 1];
wcs[0] = (wchar_t) NULL;
mbs[0] = '\0';
len = _Xmbstowcs (wcs, str, (len<MB_CUR_MAX)? len:MB_CUR_MAX);
if (len < 1)
return len;
else if (wcs[0] == (wchar_t) NULL)
return -1;
len = _Xwctomb (mbs, wcs[0]);
if (mbs[0] == '\0')
return -1;
if (wstr)
*wstr = wcs[0];
return len;
}
#endif /* X_LOCALE */
#endif /* USE_XIM */
static void
gdk_dnd_drag_leave (Window dest)
{

View File

@ -20,6 +20,8 @@
#include <gdk/gdktypes.h>
#include <gdk/gdki18n.h>
#ifdef __cplusplus
extern "C" {
@ -540,6 +542,15 @@ void gdk_selection_send_notify (guint32 requestor,
GdkAtom property,
guint32 time);
gint gdk_text_property_to_text_list (GdkAtom encoding, gint format,
guchar *text, gint length,
gchar ***list);
void gdk_free_text_list (gchar **list);
gint gdk_string_to_compound_text (gchar *str,
GdkAtom *encoding, gint *format,
guchar **ctext, gint *length);
void gdk_free_compound_text (guchar *ctext);
/* Properties
*/
GdkAtom gdk_atom_intern (const gchar *atom_name,
@ -588,6 +599,10 @@ gint gdk_input_set_mode (guint32 deviceid,
GdkInputMode mode);
void gdk_input_set_axes (guint32 deviceid,
GdkAxisUse *axes);
void gdk_input_set_key (guint32 deviceid,
guint index,
guint keyval,
GdkModifierType modifiers);
void gdk_input_window_get_pointer (GdkWindow *window,
guint32 deviceid,
gdouble *x,
@ -603,6 +618,28 @@ GdkTimeCoord *gdk_input_motion_events (GdkWindow *window,
guint32 stop,
gint *nevents_return);
#ifdef USE_XIM
/* International Input Method Support Functions
*/
gint gdk_im_ready (void);
void gdk_im_begin (GdkIC ic, GdkWindow* window);
void gdk_im_end (void);
GdkIMStyle gdk_im_decide_style (GdkIMStyle supported_style);
GdkIMStyle gdk_im_set_best_style (GdkIMStyle best_allowed_style);
GdkIC gdk_ic_new (GdkWindow* client_window,
GdkWindow* focus_window,
GdkIMStyle style, ...);
void gdk_ic_destroy (GdkIC ic);
void gdk_ic_set_values (GdkIC ic, ...);
void gdk_ic_get_values (GdkIC ic, ...);
void gdk_ic_set_attr (GdkIC ic, const char *target, ...);
void gdk_ic_get_attr (GdkIC ic, const char *target, ...);
GdkEventMask gdk_ic_get_events (GdkIC ic);
#endif /* USE_XIM */
/* Miscellaneous */
void gdk_event_send_clientmessage_toall(GdkEvent *event);

144
gdk/gdki18n.h Normal file
View File

@ -0,0 +1,144 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __GDK_I18N_H__
#define __GDK_I18N_H__
/* international string support */
#include <stdlib.h>
#include <wchar.h>
#ifdef X_LOCALE
#include <X11/Xfuncproto.h>
#include <X11/Xosdefs.h>
#ifdef __cplusplus
extern "C" {
#endif
_XFUNCPROTOBEGIN
extern int _Xmblen (
#if NeedFunctionPrototypes
const char *s, size_t n
#endif
);
_XFUNCPROTOEND
_XFUNCPROTOBEGIN
extern int _Xmbtowc (
#if NeedFunctionPrototypes
wchar_t *wstr, const char *str, size_t len
#endif
);
_XFUNCPROTOEND
_XFUNCPROTOBEGIN
extern int _Xwctomb (
#if NeedFunctionPrototypes
char *str, wchar_t wc
#endif
);
_XFUNCPROTOEND
_XFUNCPROTOBEGIN
extern size_t _Xmbstowcs (
#if NeedFunctionPrototypes
wchar_t *wstr, const char *str, size_t len
#endif
);
_XFUNCPROTOEND
_XFUNCPROTOBEGIN
extern size_t _Xwcstombs (
#if NeedFunctionPrototypes
char *str, const wchar_t *wstr, size_t len
#endif
);
_XFUNCPROTOEND
_XFUNCPROTOBEGIN
extern size_t _Xwcslen (
#if NeedFunctionPrototypes
const wchar_t *wstr
#endif
);
_XFUNCPROTOEND
_XFUNCPROTOBEGIN
extern wchar_t* _Xwcscpy (
#if NeedFunctionPrototypes
wchar_t *wstr1, const wchar_t *wstr2
#endif
);
_XFUNCPROTOEND
_XFUNCPROTOBEGIN
extern wchar_t* _Xwcsncpy (
#if NeedFunctionPrototypes
wchar_t *wstr1, const wchar_t *wstr2, size_t len
#endif
);
_XFUNCPROTOEND
_XFUNCPROTOBEGIN
extern int _Xwcscmp (
#if NeedFunctionPrototypes
const wchar_t *wstr1, const wchar_t *wstr2
#endif
);
_XFUNCPROTOEND
_XFUNCPROTOBEGIN
extern int _Xwcsncmp (
#if NeedFunctionPrototypes
const wchar_t *wstr1, const wchar_t *wstr2, size_t len
#endif
);
_XFUNCPROTOEND
/*
* mblen, mbtowc, and mbstowcs of the locale "ja_JP.eucJP" are buggy.
*/
#ifdef MB_CUR_MAX
# undef MB_CUR_MAX
#endif
#define MB_CUR_MAX 4
extern int _g_mbtowc (wchar_t *wstr, const char *str, size_t len);
/* #define mblen _Xmblen */
/* #define mbtowc _Xmbtowc */
#define mblen(a,b) _g_mbtowc ((wchar_t *)(NULL), (a), (b))
#define mbtowc(a,b,c) _g_mbtowc ((a),(b),(c))
#define wctomb(a,b) _Xwctomb ((a),(b))
#define mbstowcs(a,b,c) _Xmbstowcs ((a),(b),(c))
#define wcstombs(a,b,c) _Xwcstombs ((a),(b),(c))
#define wcslen(a) _Xwcslen ((a))
#define wcscpy(a,b) _Xwcscpy ((a),(b))
#define wcsncpy(a,b,c) _Xwcsnpy ((a),(b),(c))
#ifdef __cplusplus
}
#endif
#endif /* X_LOCALE */
#endif __GDK_I18N_H__

View File

@ -148,6 +148,19 @@ struct _GdkDndGlobals {
};
typedef struct _GdkDndGlobals GdkDndGlobals;
#ifdef USE_XIM
struct _GdkICPrivate
{
XIC xic;
GdkIMStyle style;
};
typedef struct _GdkICPrivate GdkICPrivate;
#endif /* USE_XIM */
void gdk_window_init (void);
void gdk_visual_init (void);

View File

@ -20,6 +20,7 @@
#include <string.h>
#include "gdk.h"
#include "gdkprivate.h"
#include "gdkx.h"
gint
@ -166,3 +167,71 @@ gdk_selection_send_notify (guint32 requestor,
XSendEvent (gdk_display, requestor, False, NoEventMask, (XEvent*) &xevent);
}
gint
gdk_text_property_to_text_list (GdkAtom encoding, gint format,
guchar *text, gint length,
gchar ***list)
{
XTextProperty property;
gint count = 0;
gint res;
if (!list)
return 0;
property.value = text;
property.encoding = encoding;
property.format = format;
property.nitems = length;
res = XmbTextPropertyToTextList (GDK_DISPLAY(), &property, list, &count);
if (res == XNoMemory || res == XLocaleNotSupported ||
res == XConverterNotFound)
return 0;
else
return count;
}
void
gdk_free_text_list (gchar **list)
{
XFreeStringList (list);
}
gint
gdk_string_to_compound_text (gchar *str,
GdkAtom *encoding, gint *format,
guchar **ctext, gint *length)
{
gint res;
XTextProperty property;
res = XmbTextListToTextProperty (GDK_DISPLAY(),
&str, 1, XCompoundTextStyle,
&property);
if (res != Success)
{
property.encoding = None;
property.format = None;
property.value = NULL;
property.nitems = 0;
}
if (encoding)
*encoding = property.encoding;
if (format)
*format = property.format;
if (ctext)
*ctext = property.value;
if (length)
*length = property.nitems;
return res;
}
void gdk_free_compound_text (guchar *ctext)
{
if (ctext)
XFree (ctext);
}

View File

@ -86,7 +86,6 @@ gdk_window_new (GdkWindow *parent,
long xattributes_mask;
XSizeHints size_hints;
XWMHints wm_hints;
XTextProperty text_property;
XClassHint *class_hint;
int x, y, depth;
unsigned int class;
@ -262,12 +261,10 @@ gdk_window_new (GdkWindow *parent,
else
title = gdk_progname;
if (XStringListToTextProperty (&title, 1, &text_property))
{
XSetWMName (private->xdisplay, private->xwindow, &text_property);
XSetWMIconName (private->xdisplay, private->xwindow, &text_property);
XFree (text_property.value);
}
XmbSetWMProperties (private->xdisplay, private->xwindow,
title, title,
NULL, 0,
NULL, NULL, NULL);
if (attributes_mask & GDK_WA_WMCLASS)
{
@ -734,8 +731,8 @@ gdk_window_set_title (GdkWindow *window,
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
XStoreName (private->xdisplay, private->xwindow, title);
XSetIconName (private->xdisplay, private->xwindow, title);
XmbSetWMProperties (private->xdisplay, private->xwindow,
title, title, NULL, 0, NULL, NULL, NULL);
}
void

View File

@ -17,13 +17,16 @@
*/
#include "../config.h"
#include <X11/Xlocale.h>
#include <ctype.h>
#include <locale.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#ifdef USE_XIM
#include <stdarg.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
@ -35,10 +38,17 @@
#include <X11/Xos.h>
#include <X11/Xutil.h>
#include <X11/Xmu/WinUtil.h>
#ifdef USE_XIM
#include <X11/Xresource.h>
#endif
#include <X11/cursorfont.h>
#include "gdk.h"
#include "gdkprivate.h"
#include "gdkinput.h"
#ifdef USE_XIM
#include "gdkx.h"
#include "gdkkeysyms.h"
#endif
#ifndef X_GETTIMEOFDAY
@ -120,6 +130,15 @@ static int gdk_x_io_error (Display *display);
static RETSIGTYPE gdk_signal (int signum);
#ifdef USE_XIM
static GdkIM gdk_im_get (void);
static gint gdk_im_open (XrmDatabase db,
gchar* res_name,
gchar* rec_class);
static void gdk_im_close (void);
static void gdk_ic_cleanup (void);
#endif /* USE_XIM */
/* Private variable declarations
*/
static int initialized = 0; /* 1 if the library is initialized,
@ -178,6 +197,17 @@ static GdkWindow *button_window[2]; /* The last 2 windows to rec
static guint button_number[2]; /* The last 2 buttons to be pressed.
*/
#ifdef USE_XIM
static gint xim_using; /* using XIM Protocol if TRUE */
static GdkIM xim_im; /* global IM */
static XIMStyles* xim_styles; /* im supports these styles */
static XIMStyle xim_best_allowed_style;
static GdkICPrivate *xim_ic; /* currently using IC */
static GdkWindow* xim_window; /* currently using Widow */
static GList* xim_ic_list;
#endif
#define OTHER_XEVENT_BUFSIZE 4
static XEvent other_xevent[OTHER_XEVENT_BUFSIZE]; /* XEvents passed along to user */
static int other_xevent_i = 0;
@ -326,6 +356,41 @@ gdk_init (int *argc,
}
}
#endif
#ifdef USE_XIM
else if (strcmp ("--xim-preedit", (*argv)[i]) == 0)
{
if ((i + 1) < *argc)
{
(*argv)[i++] = NULL;
if (strcmp ("none", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMPreeditNone);
else if (strcmp ("nothing", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMPreeditNothing);
else if (strcmp ("area", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMPreeditArea);
else if (strcmp ("position", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMPreeditPosition);
else if (strcmp ("callbacks", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMPreeditCallbacks);
}
}
else if (strcmp ("--xim-status", (*argv)[i]) == 0)
{
if ((i + 1) < *argc)
{
(*argv)[i++] = NULL;
if (strcmp ("none", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMStatusNone);
else if (strcmp ("nothing", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMStatusNothing);
else if (strcmp ("area", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMStatusArea);
else if (strcmp ("callbacks", (*argv)[i]) == 0)
gdk_im_set_best_style (GdkIMStatusCallbacks);
}
}
#endif
i += 1;
}
@ -418,6 +483,23 @@ gdk_init (int *argc,
gdk_image_init ();
gdk_input_init ();
#ifdef USE_XIM
/* initialize XIM Protocol variables */
xim_using = FALSE;
xim_im = NULL;
xim_styles = NULL;
if (!(xim_best_allowed_style & GdkIMPreeditMask))
gdk_im_set_best_style (GdkIMPreeditCallbacks);
if (!(xim_best_allowed_style & GdkIMStatusMask))
gdk_im_set_best_style (GdkIMStatusCallbacks);
xim_ic = NULL;
xim_window = (GdkWindow*)NULL;
gdk_im_open (NULL, NULL, NULL);
if (gdk_im_get () == NULL)
g_warning ("unable to open input method.");
#endif
initialized = 1;
}
@ -623,7 +705,20 @@ gdk_event_get (GdkEvent *event,
/* If we get here we can rest assurred that an event
* has occurred. Read it.
*/
#ifdef USE_XIM
gint filter_status;
if (xim_using && xim_window)
do
{ /* dont dispatch events used by IM */
XNextEvent (gdk_display, &xevent);
filter_status = XFilterEvent (&xevent,
GDK_WINDOW_XWINDOW (xim_window));
} while (filter_status == True);
else
XNextEvent (gdk_display, &xevent);
#else
XNextEvent (gdk_display, &xevent);
#endif
event->any.send_event = xevent.xany.send_event;
@ -1370,7 +1465,12 @@ gdk_event_translate (GdkEvent *event,
GdkWindowPrivate *window_private;
XComposeStatus compose;
int charcount;
#ifdef USE_XIM
static gchar* buf = NULL;
static gint buf_len= 0;
#else
char buf[16];
#endif
gint return_val;
/* Are static variables used for this purpose thread-safe? */
@ -1421,24 +1521,78 @@ gdk_event_translate (GdkEvent *event,
case KeyPress:
/* Lookup the string corresponding to the given keysym.
*/
#ifdef USE_XIM
if (buf_len == 0)
{
buf_len = 128;
buf = g_new (gchar, buf_len);
}
if (xim_using == TRUE && xim_ic)
{
Status status;
/* Clear keyval. Depending on status, may not be set */
event->key.keyval = GDK_VoidSymbol;
charcount = XmbLookupString(xim_ic->xic,
&xevent->xkey, buf, buf_len-1,
(KeySym*) &event->key.keyval,
&status);
if (status == XBufferOverflow)
{ /* retry */
/* alloc adequate size of buffer */
if (gdk_debug_level >= 1)
g_print("XIM: overflow(required %i)\n", charcount);
while (buf_len <= charcount)
buf_len *= 2;
buf = (gchar *) g_realloc (buf, buf_len);
charcount = XmbLookupString (xim_ic->xic,
&xevent->xkey, buf, buf_len-1,
(KeySym*) &event->key.keyval,
&status);
}
if (status == XLookupNone)
{
return_val = FALSE;
break;
}
}
else
charcount = XLookupString (&xevent->xkey, buf, buf_len,
(KeySym*) &event->key.keyval,
&compose);
#else
charcount = XLookupString (&xevent->xkey, buf, 16,
(KeySym*) &event->key.keyval,
&compose);
#endif
if (charcount > 0 && buf[charcount-1] == '\0')
charcount --;
else
buf[charcount] = '\0';
/* Print debugging info.
*/
if (gdk_show_events)
g_print ("key press:\t\twindow: %ld key: %12s %d\n",
xevent->xkey.window - base_id,
XKeysymToString (event->key.keyval),
event->key.keyval);
{
g_print ("key press:\twindow: %ld key: %12s %d\n",
xevent->xkey.window - base_id,
event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
event->key.keyval);
if (charcount > 0)
g_print ("\t\tlength: %4d string: \"%s\"\n",
charcount, buf);
}
event->key.type = GDK_KEY_PRESS;
event->key.window = window;
event->key.time = xevent->xkey.time;
event->key.state = (GdkModifierType) xevent->xkey.state;
event->key.string = buf;
event->key.length = charcount;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case KeyRelease:
@ -1460,8 +1614,10 @@ gdk_event_translate (GdkEvent *event,
event->key.window = window;
event->key.time = xevent->xkey.time;
event->key.state = (GdkModifierType) xevent->xkey.state;
event->key.length = 0;
event->key.string = NULL;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case ButtonPress:
@ -1563,7 +1719,7 @@ gdk_event_translate (GdkEvent *event,
CWEventMask, &dnd_setwinattr);
}
}
return_val = window_private?(!window_private->destroyed):FALSE;
return_val = window_private && !window_private->destroyed;
break;
case ButtonRelease:
@ -1632,7 +1788,7 @@ gdk_event_translate (GdkEvent *event,
dnd_drag_dropzone.width = dnd_drag_dropzone.height = 0;
dnd_drag_curwin = None;
}
return_val = window ? (!window_private->destroyed) : FALSE;
return_val = window_private && !window_private->destroyed;
break;
case MotionNotify:
@ -1728,7 +1884,7 @@ gdk_event_translate (GdkEvent *event,
return_val = FALSE;
}
else
return_val = window?(!window_private->destroyed):FALSE;
return_val = window_private && !window_private->destroyed;
break;
case EnterNotify:
@ -1789,7 +1945,7 @@ gdk_event_translate (GdkEvent *event,
XUngrabPointer(gdk_display, CurrentTime);
}
return_val = (window ? !window_private->destroyed : FALSE);
return_val = window_private && !window_private->destroyed;
break;
case LeaveNotify:
@ -1839,7 +1995,7 @@ gdk_event_translate (GdkEvent *event,
gdk_dnd.gdk_cursor_dragdefault, CurrentTime);
gdk_dnd.drag_really = 1;
}
return_val = window ? (!window_private->destroyed) : FALSE;
return_val = window_private && !window_private->destroyed;
break;
case FocusIn:
@ -1853,7 +2009,7 @@ gdk_event_translate (GdkEvent *event,
event->focus_change.window = window;
event->focus_change.in = TRUE;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case FocusOut:
@ -1867,7 +2023,7 @@ gdk_event_translate (GdkEvent *event,
event->focus_change.window = window;
event->focus_change.in = FALSE;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case KeymapNotify:
@ -1896,7 +2052,7 @@ gdk_event_translate (GdkEvent *event,
event->expose.area.height = xevent->xexpose.height;
event->expose.count = xevent->xexpose.count;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case GraphicsExpose:
@ -1914,7 +2070,7 @@ gdk_event_translate (GdkEvent *event,
event->expose.area.height = xevent->xgraphicsexpose.height;
event->expose.count = xevent->xexpose.count;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case NoExpose:
@ -1972,7 +2128,7 @@ gdk_event_translate (GdkEvent *event,
received_destroy_notify = TRUE;
window_to_destroy = window;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case UnmapNotify:
@ -1985,7 +2141,7 @@ gdk_event_translate (GdkEvent *event,
event->any.type = GDK_UNMAP;
event->any.window = window;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case MapNotify:
@ -1998,7 +2154,7 @@ gdk_event_translate (GdkEvent *event,
event->any.type = GDK_MAP;
event->any.window = window;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case ReparentNotify:
@ -2025,30 +2181,32 @@ gdk_event_translate (GdkEvent *event,
xevent->xconfigure.x, xevent->xconfigure.y,
xevent->xconfigure.width, xevent->xconfigure.height);
if (window_private &&
(window_private->extension_events != 0) &&
gdk_input_vtable.configure_event)
gdk_input_vtable.configure_event (&xevent->xconfigure, window);
if ((window_private->window_type != GDK_WINDOW_CHILD) &&
((window_private->width != xevent->xconfigure.width) ||
(window_private->height != xevent->xconfigure.height)))
if (window_private)
{
event->configure.type = GDK_CONFIGURE;
event->configure.window = window;
event->configure.x = xevent->xconfigure.x;
event->configure.y = xevent->xconfigure.y;
event->configure.width = xevent->xconfigure.width;
event->configure.height = xevent->xconfigure.height;
if ((window_private->extension_events != 0) &&
gdk_input_vtable.configure_event)
gdk_input_vtable.configure_event (&xevent->xconfigure, window);
window_private->x = xevent->xconfigure.x;
window_private->y = xevent->xconfigure.y;
window_private->width = xevent->xconfigure.width;
window_private->height = xevent->xconfigure.height;
if (window_private->resize_count > 1)
window_private->resize_count -= 1;
if ((window_private->window_type != GDK_WINDOW_CHILD) &&
((window_private->width != xevent->xconfigure.width) ||
(window_private->height != xevent->xconfigure.height)))
{
event->configure.type = GDK_CONFIGURE;
event->configure.window = window;
event->configure.x = xevent->xconfigure.x;
event->configure.y = xevent->xconfigure.y;
event->configure.width = xevent->xconfigure.width;
event->configure.height = xevent->xconfigure.height;
return_val = !window_private->destroyed;
window_private->x = xevent->xconfigure.x;
window_private->y = xevent->xconfigure.y;
window_private->width = xevent->xconfigure.width;
window_private->height = xevent->xconfigure.height;
if (window_private->resize_count > 1)
window_private->resize_count -= 1;
return_val = !window_private->destroyed;
}
}
break;
@ -2065,7 +2223,7 @@ gdk_event_translate (GdkEvent *event,
event->property.time = xevent->xproperty.time;
event->property.state = xevent->xproperty.state;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case SelectionClear:
@ -2078,7 +2236,7 @@ gdk_event_translate (GdkEvent *event,
event->selection.selection = xevent->xselectionclear.selection;
event->selection.time = xevent->xselectionclear.time;
return_val = !((GdkWindowPrivate*) window)->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case SelectionRequest:
@ -2094,7 +2252,7 @@ gdk_event_translate (GdkEvent *event,
event->selection.requestor = xevent->xselectionrequest.requestor;
event->selection.time = xevent->xselectionrequest.time;
return_val = !((GdkWindowPrivate*) window)->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case SelectionNotify:
@ -2110,7 +2268,7 @@ gdk_event_translate (GdkEvent *event,
event->selection.property = xevent->xselection.property;
event->selection.time = xevent->xselection.time;
return_val = !((GdkWindowPrivate*) window)->destroyed;
return_val = window_private && !window_private->destroyed;
break;
case ColormapNotify:
@ -2157,7 +2315,7 @@ gdk_event_translate (GdkEvent *event,
event->any.type = GDK_DELETE;
event->any.window = window;
return_val = !window_private->destroyed;
return_val = window_private && !window_private->destroyed;
}
else if ((Atom) xevent->xclient.data.l[0] == gdk_wm_take_focus)
{
@ -2353,6 +2511,8 @@ gdk_event_translate (GdkEvent *event,
(window_private->extension_events != 0) &&
gdk_input_vtable.other_event)
return_val = gdk_input_vtable.other_event(event, xevent, window);
else
return_val = -1;
if (return_val < 0) /* not an XInput event, convert */
{
@ -2363,8 +2523,9 @@ gdk_event_translate (GdkEvent *event,
other_xevent_i = (other_xevent_i+1) % OTHER_XEVENT_BUFSIZE;
return_val = TRUE;
}
else
return_val = return_val && !window_private->destroyed;
return_val = return_val && !window_private->destroyed;
break;
}
@ -2424,6 +2585,12 @@ gdk_exit_func ()
{
if (initialized)
{
#ifdef USE_XIM
/* cleanup IC */
gdk_ic_cleanup ();
/* close IM */
gdk_im_close ();
#endif
gdk_image_exit ();
gdk_input_exit ();
gdk_key_repeat_restore ();
@ -2615,6 +2782,446 @@ gdk_dnd_drag_enter (Window dest)
}
}
#ifdef USE_XIM
/*
*--------------------------------------------------------------
* gdk_im_begin
*
* Begin using input method with XIM Protocol(X11R6 standard)
*
* Arguments:
* "ic" is the "Input Context" which is created by gtk_ic_new.
* The input area is specified with "window".
*
* Results:
* The gdk's event handling routine is switched to XIM based routine.
* XIM based routine uses XFilterEvent to get rid of events used by IM,
* and uses XmbLookupString instead of XLookupString.
*
* Side effects:
*
*--------------------------------------------------------------
*/
void gdk_im_begin (GdkIC ic, GdkWindow* window)
{
GdkEventMask event;
GdkICPrivate *private;
Window xwin;
g_return_if_fail (ic != NULL);
g_return_if_fail (window);
private = (GdkICPrivate *) ic;
xim_using = TRUE;
xim_ic = private;
xim_window = window;
if (gdk_im_ready())
{
XGetICValues (private->xic, XNFocusWindow, &xwin, NULL);
if (xwin != GDK_WINDOW_XWINDOW(window))
XSetICValues (private->xic, XNFocusWindow,
GDK_WINDOW_XWINDOW(window), NULL);
if (private != xim_ic)
XSetICFocus (private->xic);
}
}
/*
*--------------------------------------------------------------
* gdk_im_end
*
* End using input method with XIM Protocol(X11R6 standard)
*
* Arguments:
*
* Results:
* The gdk's event handling routine is switched to normal routine.
* User should call this function before ic and window will be destroyed.
*
* Side effects:
*
*--------------------------------------------------------------
*/
void gdk_im_end (void)
{
xim_using = FALSE;
xim_ic = NULL;
xim_window = NULL;
}
static GdkIM gdk_im_get (void)
{
return xim_im;
}
static GdkIMStyle
gdk_im_choose_better_style (GdkIMStyle style1, GdkIMStyle style2)
{
GdkIMStyle s1, s2, u;
if (style1 == 0) return style2;
if (style2 == 0) return style1;
if ((style1 & (GdkIMPreeditMask | GdkIMStatusMask))
== (style2 & (GdkIMPreeditMask | GdkIMStatusMask)))
return style1;
s1 = style1 & GdkIMPreeditMask;
s2 = style2 & GdkIMPreeditMask;
u = s1 | s2;
if (s1 != s2) {
if (u & GdkIMPreeditCallbacks)
return (s1 == GdkIMPreeditCallbacks)? style1:style2;
else if (u & GdkIMPreeditPosition)
return (s1 == GdkIMPreeditPosition)? style1:style2;
else if (u & GdkIMPreeditArea)
return (s1 == GdkIMPreeditArea)? style1:style2;
else if (u & GdkIMPreeditNothing)
return (s1 == GdkIMPreeditNothing)? style1:style2;
} else {
s1 = style1 & GdkIMStatusMask;
s2 = style2 & GdkIMStatusMask;
u = s1 | s2;
if ( u & GdkIMStatusCallbacks)
return (s1 == GdkIMStatusCallbacks)? style1:style2;
else if ( u & GdkIMStatusArea)
return (s1 == GdkIMStatusArea)? style1:style2;
else if ( u & GdkIMStatusNothing)
return (s1 == GdkIMStatusNothing)? style1:style2;
else if ( u & GdkIMStatusNone)
return (s1 == GdkIMStatusNone)? style1:style2;
}
}
GdkIMStyle
gdk_im_decide_style (GdkIMStyle supported_style)
{
gint i;
GdkIMStyle style, tmp;
g_return_val_if_fail (xim_styles != NULL, 0);
style = 0;
for (i=0; i<xim_styles->count_styles; i++)
{
tmp = xim_styles->supported_styles[i];
if (tmp == (tmp & supported_style & xim_best_allowed_style))
style = gdk_im_choose_better_style (style, tmp);
}
return style;
}
GdkIMStyle
gdk_im_set_best_style (GdkIMStyle style)
{
if (style & GdkIMPreeditMask)
{
xim_best_allowed_style &= ~GdkIMPreeditMask;
xim_best_allowed_style |= GdkIMPreeditNone;
if (!(style & GdkIMPreeditNone))
{
xim_best_allowed_style |= GdkIMPreeditNothing;
if (!(style & GdkIMPreeditNothing))
{
xim_best_allowed_style |= GdkIMPreeditArea;
if (!(style & GdkIMPreeditArea))
{
xim_best_allowed_style |= GdkIMPreeditPosition;
if (!(style & GdkIMPreeditPosition))
xim_best_allowed_style |= GdkIMPreeditCallbacks;
}
}
}
}
if (style & GdkIMStatusMask)
{
xim_best_allowed_style &= ~GdkIMStatusMask;
xim_best_allowed_style |= GdkIMStatusNone;
if (!(style & GdkIMStatusNone))
{
xim_best_allowed_style |= GdkIMStatusNothing;
if (!(style & GdkIMStatusNothing))
{
xim_best_allowed_style |= GdkIMStatusArea;
if (!(style & GdkIMStatusArea))
xim_best_allowed_style |= GdkIMStatusCallbacks;
}
}
}
return xim_best_allowed_style;
}
static gint gdk_im_open (XrmDatabase db, gchar* res_name, gchar* res_class)
{
XIMStyle style;
int i;
xim_im = XOpenIM (GDK_DISPLAY(), db, res_name, res_class);
if (xim_im == NULL)
{
g_warning ("Don\'t open IM.");
return FALSE;
}
XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL);
return TRUE;
}
static void gdk_im_close (void)
{
if (xim_im)
{
XCloseIM (xim_im);
xim_im = NULL;
}
if (xim_styles)
{
XFree (xim_styles);
xim_styles = NULL;
}
}
gint gdk_im_ready (void)
{
return (xim_im != NULL);
}
GdkIC gdk_ic_new (GdkWindow* client_window,
GdkWindow* focus_window,
GdkIMStyle style, ...)
{
va_list list;
GdkICPrivate *private;
XVaNestedList preedit_attr;
g_return_val_if_fail (client_window != NULL, NULL);
g_return_val_if_fail (focus_window != NULL, NULL);
g_return_val_if_fail (gdk_im_ready(), NULL);
private = g_new (GdkICPrivate, 1);
va_start (list, style);
preedit_attr = (XVaNestedList) & (va_arg (list, void *));
va_end (list);
private->style = gdk_im_decide_style (style);
if (private->style != style)
{
g_warning ("can not create input context with specified input style.");
g_free (private);
return NULL;
}
private->xic = XCreateIC(gdk_im_get (),
XNInputStyle, style,
XNClientWindow, GDK_WINDOW_XWINDOW (client_window),
XNFocusWindow, GDK_WINDOW_XWINDOW (focus_window),
preedit_attr? XNPreeditAttributes : NULL, preedit_attr,
NULL);
if (!private->xic)
{
g_free (private);
return NULL;
}
xim_ic_list = g_list_append (xim_ic_list, private);
return private;
}
void gdk_ic_destroy (GdkIC ic)
{
GdkICPrivate *private;
g_return_if_fail (ic != NULL);
private = (GdkICPrivate *) ic;
if (xim_ic == private)
gdk_im_end ();
XDestroyIC (private->xic);
xim_ic_list = g_list_remove (xim_ic_list, private);
}
GdkIMStyle
gdk_ic_get_style (GdkIC ic)
{
GdkICPrivate *private;
g_return_val_if_fail (ic != NULL, 0);
private = (GdkICPrivate *) ic;
return private->style;
}
void
gdk_ic_set_values (GdkIC ic, ...)
{
va_list list;
XVaNestedList args;
GdkICPrivate *private;
g_return_if_fail (ic != NULL);
private = (GdkICPrivate *) ic;
va_start (list, ic);
args = (XVaNestedList) & (va_arg (list, void *));
va_end (list);
XSetICValues (private->xic, XNVaNestedList, args, NULL);
}
void
gdk_ic_get_values (GdkIC ic, ...)
{
va_list list;
XVaNestedList args;
GdkICPrivate *private;
g_return_if_fail (ic != NULL);
private = (GdkICPrivate *) ic;
va_start (list, ic);
args = (XVaNestedList) & (va_arg (list, void *));
va_end (list);
XGetICValues (private->xic, XNVaNestedList, args, NULL);
}
void gdk_ic_set_attr (GdkIC ic, const char *target, ...)
{
va_list list;
XVaNestedList attr;
GdkICPrivate *private;
g_return_if_fail (ic != NULL);
g_return_if_fail (target != NULL);
private = (GdkICPrivate *) ic;
va_start (list, target);
attr = (XVaNestedList) & (va_arg (list, void *));
va_end (list);
XSetICValues (private->xic, target, attr, NULL);
}
void gdk_ic_get_attr (GdkIC ic, const char *target, ...)
{
va_list list;
XVaNestedList attr;
GdkICPrivate *private;
g_return_if_fail (ic != NULL);
g_return_if_fail (target != NULL);
private = (GdkICPrivate *) ic;
va_start (list, target);
attr = (XVaNestedList) & (va_arg (list, void *));
va_end (list);
XGetICValues (private->xic, target, attr, NULL);
}
GdkEventMask
gdk_ic_get_events (GdkIC ic)
{
GdkEventMask mask;
glong xmask;
glong bit;
GdkICPrivate *private;
gint i;
/* From gdkwindow.c */
extern int nevent_masks;
extern int event_mask_table[];
g_return_val_if_fail (ic != NULL, 0);
private = (GdkICPrivate *) ic;
XGetICValues (private->xic, XNFilterEvents, &xmask, NULL);
mask = 0;
for (i=0, bit=2; i < nevent_masks; i++, bit <<= 1)
if (xmask & event_mask_table [i])
{
mask |= bit;
xmask &= ~ event_mask_table [i];
}
if (xmask)
g_warning ("ic requires the events not supported by the application (%04x)", xmask);
return mask;
}
static void gdk_ic_cleanup (void)
{
GList* node;
gint destroyed;
GdkICPrivate *private;
destroyed = 0;
for (node = xim_ic_list; node != NULL; node = node->next)
{
if (node->data)
{
private = (GdkICPrivate *) (node->data);
XDestroyIC (private->xic);
g_free (private);
destroyed++;
}
}
if (gdk_debug_level >= 1 && destroyed > 0)
{
g_warning ("Cleanuped %i IC\n", destroyed);
}
g_list_free(xim_ic_list);
xim_ic_list = NULL;
}
#ifdef X_LOCALE
gint
_g_mbtowc (wchar_t *wstr, const char *str, size_t len)
{
static wchar_t wcs[MB_CUR_MAX + 1];
static gchar mbs[MB_CUR_MAX + 1];
wcs[0] = (wchar_t) NULL;
mbs[0] = '\0';
len = _Xmbstowcs (wcs, str, (len<MB_CUR_MAX)? len:MB_CUR_MAX);
if (len < 1)
return len;
else if (wcs[0] == (wchar_t) NULL)
return -1;
len = _Xwctomb (mbs, wcs[0]);
if (mbs[0] == '\0')
return -1;
if (wstr)
*wstr = wcs[0];
return len;
}
#endif /* X_LOCALE */
#endif /* USE_XIM */
static void
gdk_dnd_drag_leave (Window dest)
{

View File

@ -20,6 +20,7 @@
#include <string.h>
#include "gdk.h"
#include "gdkprivate.h"
#include "gdkx.h"
gint
@ -166,3 +167,71 @@ gdk_selection_send_notify (guint32 requestor,
XSendEvent (gdk_display, requestor, False, NoEventMask, (XEvent*) &xevent);
}
gint
gdk_text_property_to_text_list (GdkAtom encoding, gint format,
guchar *text, gint length,
gchar ***list)
{
XTextProperty property;
gint count = 0;
gint res;
if (!list)
return 0;
property.value = text;
property.encoding = encoding;
property.format = format;
property.nitems = length;
res = XmbTextPropertyToTextList (GDK_DISPLAY(), &property, list, &count);
if (res == XNoMemory || res == XLocaleNotSupported ||
res == XConverterNotFound)
return 0;
else
return count;
}
void
gdk_free_text_list (gchar **list)
{
XFreeStringList (list);
}
gint
gdk_string_to_compound_text (gchar *str,
GdkAtom *encoding, gint *format,
guchar **ctext, gint *length)
{
gint res;
XTextProperty property;
res = XmbTextListToTextProperty (GDK_DISPLAY(),
&str, 1, XCompoundTextStyle,
&property);
if (res != Success)
{
property.encoding = None;
property.format = None;
property.value = NULL;
property.nitems = 0;
}
if (encoding)
*encoding = property.encoding;
if (format)
*format = property.format;
if (ctext)
*ctext = property.value;
if (length)
*length = property.nitems;
return res;
}
void gdk_free_compound_text (guchar *ctext)
{
if (ctext)
XFree (ctext);
}

View File

@ -86,7 +86,6 @@ gdk_window_new (GdkWindow *parent,
long xattributes_mask;
XSizeHints size_hints;
XWMHints wm_hints;
XTextProperty text_property;
XClassHint *class_hint;
int x, y, depth;
unsigned int class;
@ -262,12 +261,10 @@ gdk_window_new (GdkWindow *parent,
else
title = gdk_progname;
if (XStringListToTextProperty (&title, 1, &text_property))
{
XSetWMName (private->xdisplay, private->xwindow, &text_property);
XSetWMIconName (private->xdisplay, private->xwindow, &text_property);
XFree (text_property.value);
}
XmbSetWMProperties (private->xdisplay, private->xwindow,
title, title,
NULL, 0,
NULL, NULL, NULL);
if (attributes_mask & GDK_WA_WMCLASS)
{
@ -734,8 +731,8 @@ gdk_window_set_title (GdkWindow *window,
g_return_if_fail (window != NULL);
private = (GdkWindowPrivate*) window;
XStoreName (private->xdisplay, private->xwindow, title);
XSetIconName (private->xdisplay, private->xwindow, title);
XmbSetWMProperties (private->xdisplay, private->xwindow,
title, title, NULL, 0, NULL, NULL, NULL);
}
void