📄 gdkim.c
字号:
/* 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., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//* * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */#include <X11/Xlocale.h>#include "gdk.h"#include "gdkprivate.h"#include "gdki18n.h"#include "gdkx.h"#if HAVE_CONFIG_H# include <config.h># if STDC_HEADERS# include <string.h># endif#endif/* If this variable is FALSE, it indicates that we should * avoid trying to use multibyte conversion functions and * assume everything is 1-byte per character */static gboolean gdk_use_mb;#ifdef USE_XIM#include <stdarg.h>#include <X11/Xresource.h>/* The following routines duplicate functionality in Xlib to * translate from varargs to X's internal opaque XVaNestedList. * * If all vendors have stuck close to the reference implementation, * then we should hopefully be OK. */typedef struct { gchar *name; gpointer value;} GdkImArg;#ifdef USE_X11R6_XIMstatic void gdk_im_instantiate_cb (Display *display, XPointer client_data, XPointer call_data);#endifstatic void gdk_im_destroy_cb (XIM im, XPointer client_data, XPointer call_data);static gint gdk_im_real_open (void);static void gdk_ic_real_new (GdkIC *ic);static GdkICAttributesType gdk_ic_real_set_attr (GdkIC *ic, GdkICAttr *attr, GdkICAttributesType mask);static XIM xim_im; /* global IM */static XIMStyles* xim_styles; /* im supports these styles */static XIMStyle xim_best_allowed_style;static GList* xim_ic_list;#endif /* USE_XIM *//* *-------------------------------------------------------------- * gdk_set_locale * * Arguments: * * Results: * * Side effects: * *-------------------------------------------------------------- */gchar*gdk_set_locale (void){ wchar_t result; gchar *current_locale; gdk_use_mb = FALSE; if (!setlocale (LC_ALL,"")) g_warning ("locale not supported by C library"); if (!XSupportsLocale ()) { g_warning ("locale not supported by Xlib, locale set to C"); setlocale (LC_ALL, "C"); } if (!XSetLocaleModifiers ("")) g_warning ("can not set locale modifiers"); current_locale = setlocale (LC_ALL, NULL); if ((strcmp (current_locale, "C")) && (strcmp (current_locale, "POSIX"))) { gdk_use_mb = TRUE;#ifndef X_LOCALE /* Detect GNU libc, where mb == UTF8. Not useful unless it's * really a UTF8 locale. The below still probably will * screw up on Greek, Cyrillic, etc, encoded as UTF8. */ if ((MB_CUR_MAX == 2) && (mbstowcs (&result, "\xdd\xa5", 1) > 0) && result == 0x765) { if ((strlen (current_locale) < 4) || g_strcasecmp (current_locale + strlen(current_locale) - 4, "utf8")) gdk_use_mb = FALSE; }#endif /* X_LOCALE */ } GDK_NOTE (XIM, g_message ("%s multi-byte string functions.", gdk_use_mb ? "Using" : "Not using")); return current_locale;}#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){ GdkICPrivate *private; GdkICAttr attr; g_return_if_fail (ic != NULL); private = (GdkICPrivate *) ic; attr.focus_window = window; gdk_ic_set_attr (ic, &attr, GDK_IC_FOCUS_WINDOW); if (private != gdk_xim_ic) { gdk_im_end(); if (private->xic) { XSetICFocus (private->xic); GDK_NOTE (XIM, g_message ("im_begin icfocus : %p(%ld)\n", private->xic, GDK_WINDOW_XWINDOW(private->attr->focus_window))); } } gdk_xim_ic = private; gdk_xim_window = window;}/* *-------------------------------------------------------------- * 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){ if (gdk_xim_ic && gdk_xim_ic->xic) { XUnsetICFocus (gdk_xim_ic->xic); GDK_NOTE (XIM, g_message ("im_end unfocus : %p\n", gdk_xim_ic->xic)); } gdk_xim_ic = NULL; gdk_xim_window = NULL;}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 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK)) == (style2 & (GDK_IM_PREEDIT_MASK | GDK_IM_STATUS_MASK))) return style1; s1 = style1 & GDK_IM_PREEDIT_MASK; s2 = style2 & GDK_IM_PREEDIT_MASK; u = s1 | s2; if (s1 != s2) { if (u & GDK_IM_PREEDIT_CALLBACKS) return (s1 == GDK_IM_PREEDIT_CALLBACKS)? style1:style2; else if (u & GDK_IM_PREEDIT_POSITION) return (s1 == GDK_IM_PREEDIT_POSITION)? style1:style2; else if (u & GDK_IM_PREEDIT_AREA) return (s1 == GDK_IM_PREEDIT_AREA)? style1:style2; else if (u & GDK_IM_PREEDIT_NOTHING) return (s1 == GDK_IM_PREEDIT_NOTHING)? style1:style2; } else { s1 = style1 & GDK_IM_STATUS_MASK; s2 = style2 & GDK_IM_STATUS_MASK; u = s1 | s2; if ( u & GDK_IM_STATUS_CALLBACKS) return (s1 == GDK_IM_STATUS_CALLBACKS)? style1:style2; else if ( u & GDK_IM_STATUS_AREA) return (s1 == GDK_IM_STATUS_AREA)? style1:style2; else if ( u & GDK_IM_STATUS_NOTHING) return (s1 == GDK_IM_STATUS_NOTHING)? style1:style2; else if ( u & GDK_IM_STATUS_NONE) return (s1 == GDK_IM_STATUS_NONE)? style1:style2; } return 0; /* Get rid of stupid warning */}GdkIMStylegdk_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;}GdkIMStylegdk_im_set_best_style (GdkIMStyle style){ if (style & GDK_IM_PREEDIT_MASK) { xim_best_allowed_style &= ~GDK_IM_PREEDIT_MASK; xim_best_allowed_style |= GDK_IM_PREEDIT_NONE; if (!(style & GDK_IM_PREEDIT_NONE)) { xim_best_allowed_style |= GDK_IM_PREEDIT_NOTHING; if (!(style & GDK_IM_PREEDIT_NOTHING)) { xim_best_allowed_style |= GDK_IM_PREEDIT_AREA; if (!(style & GDK_IM_PREEDIT_AREA)) { xim_best_allowed_style |= GDK_IM_PREEDIT_POSITION; if (!(style & GDK_IM_PREEDIT_POSITION)) xim_best_allowed_style |= GDK_IM_PREEDIT_CALLBACKS; } } } } if (style & GDK_IM_STATUS_MASK) { xim_best_allowed_style &= ~GDK_IM_STATUS_MASK; xim_best_allowed_style |= GDK_IM_STATUS_NONE; if (!(style & GDK_IM_STATUS_NONE)) { xim_best_allowed_style |= GDK_IM_STATUS_NOTHING; if (!(style & GDK_IM_STATUS_NOTHING)) { xim_best_allowed_style |= GDK_IM_STATUS_AREA; if (!(style & GDK_IM_STATUS_AREA)) xim_best_allowed_style |= GDK_IM_STATUS_CALLBACKS; } } } return xim_best_allowed_style;}#ifdef USE_X11R6_XIMstatic voidgdk_im_destroy_cb (XIM im, XPointer client_data, XPointer call_data){ GList *node; GdkICPrivate *private; GDK_NOTE (XIM, g_message ("Ouch, Input Method is destroyed!!\n")); xim_im = NULL; if (xim_styles) { XFree (xim_styles); xim_styles = NULL; } for (node = xim_ic_list; node != NULL; node = g_list_next(node)) { private = (GdkICPrivate *) (node->data); private->xic = NULL; } XRegisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL, gdk_im_instantiate_cb, NULL);}static voidgdk_im_instantiate_cb (Display *display, XPointer client_data, XPointer call_data){ GDK_NOTE (XIM, g_message ("New IM is instantiated.")); if (display != gdk_display) return; gdk_im_real_open (); if (xim_im != NULL) XUnregisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL, gdk_im_instantiate_cb, NULL);}#endifstatic gintgdk_im_real_open (void){ GList *node; xim_im = XOpenIM (GDK_DISPLAY(), NULL, NULL, NULL); if (xim_im == NULL) { GDK_NOTE (XIM, g_warning ("Unable to open IM.")); return FALSE; } else {#ifdef USE_X11R6_XIM XIMCallback destroy_cb; destroy_cb.callback = gdk_im_destroy_cb; destroy_cb.client_data = NULL; if (NULL != (void *) XSetIMValues (xim_im, XNDestroyCallback, &destroy_cb, NULL)) GDK_NOTE (XIM, g_warning ("Could not set destroy callback to IM. Be careful to not destroy your input method."));#endif XGetIMValues (xim_im, XNQueryInputStyle, &xim_styles, NULL, NULL); for (node = xim_ic_list; node != NULL; node = g_list_next(node)) { GdkICPrivate *private = (GdkICPrivate *) (node->data); if (private->xic == NULL) gdk_ic_real_new ((GdkIC *)private); } return TRUE; }}gint gdk_im_open (void){ gdk_xim_ic = NULL; gdk_xim_window = (GdkWindow*)NULL; xim_im = NULL; xim_styles = NULL; /* initialize XIM Protocol variables */ if (!(xim_best_allowed_style & GDK_IM_PREEDIT_MASK)) gdk_im_set_best_style (GDK_IM_PREEDIT_CALLBACKS); if (!(xim_best_allowed_style & GDK_IM_STATUS_MASK)) gdk_im_set_best_style (GDK_IM_STATUS_CALLBACKS); if (gdk_im_real_open ()) return TRUE;#ifdef USE_X11R6_XIM XRegisterIMInstantiateCallback (gdk_display, NULL, NULL, NULL, gdk_im_instantiate_cb, NULL);#endif return FALSE;}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);}static voidgdk_ic_real_new (GdkIC *ic){ XPoint spot_location; XRectangle preedit_area; XRectangle status_area; XVaNestedList *preedit_attr = NULL; XVaNestedList *status_attr = NULL; GdkICAttr *attr; GdkICPrivate *private; GdkICAttributesType mask = GDK_IC_ALL_REQ; private = (GdkICPrivate *) ic; attr = private->attr; switch (attr->style & GDK_IM_PREEDIT_MASK) { case GDK_IM_PREEDIT_AREA: mask |= GDK_IC_PREEDIT_AREA_REQ; preedit_area.x = attr->preedit_area.x; preedit_area.y = attr->preedit_area.y; preedit_area.width = attr->preedit_area.width; preedit_area.height = attr->preedit_area.height; preedit_attr = XVaCreateNestedList (0, XNArea, &preedit_area, XNFontSet, GDK_FONT_XFONT(attr->preedit_fontset), NULL); break; case GDK_IM_PREEDIT_POSITION: mask |= GDK_IC_PREEDIT_POSITION_REQ; preedit_area.x = attr->preedit_area.x; preedit_area.y = attr->preedit_area.y; preedit_area.width = attr->preedit_area.width; preedit_area.height = attr->preedit_area.height; spot_location.x = attr->spot_location.x; spot_location.y = attr->spot_location.y; preedit_attr = XVaCreateNestedList (0, XNArea, &preedit_area, XNFontSet, GDK_FONT_XFONT(attr->preedit_fontset), XNSpotLocation, &spot_location, NULL); break; } switch (attr->style & GDK_IM_STATUS_MASK) { case GDK_IM_STATUS_AREA: mask |= GDK_IC_STATUS_AREA_REQ; status_area.x = attr->status_area.x; status_area.y = attr->status_area.y; status_area.width = attr->status_area.width; status_area.height = attr->status_area.height; status_attr = XVaCreateNestedList (0, XNArea, &status_area, XNFontSet, GDK_FONT_XFONT(attr->status_fontset), NULL); break; } /* We have to ensure that the client window is actually created on * the X server, or XCreateIC fails because the XIM server can't get * information about the client window. */ gdk_flush(); if (preedit_attr != NULL && status_attr != NULL) private->xic = XCreateIC (xim_im, XNInputStyle, attr->style, XNClientWindow, GDK_WINDOW_XWINDOW(attr->client_window),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -