Forum #1 - Topic #152 - Message List

[賀!] gcin patch for rxvt-unicode

kanru 今天寫了 gcin patch for rxvt-unicode (他說要註明是「測試用」,No Warranty),
類似劉老大寫的 gcin patch for mrxvt / rxvt。

效果是「不需要」任何設定、不需要 XIM,仍可使用 gcin 輸入所有 UTF-8 字元。
此 patch 是針對 cvs 寫的,不過可直接套用在 rxvt-unicode 8.1 沒問題。
編譯方法:

1. 安裝 gcin
2. patch
3. bootstrap (run autogen.sh)
4. ./configure --enable-gcin --disable-utmp --disable-xim
5. make

測試過可在任何 UTF-8 locale 顯示/輸入 UTF-8,
POSIX / C locale 輸入正常,但顯示會變成 latin1 / ASCII
完整 patch 可在這裡下載,或直接複製下面內容:

Index: configure.ac
===================================================================
RCS file: /schmorpforge/rxvt-unicode/configure.ac,v
retrieving revision 1.36
diff -u -r1.36 configure.ac
--- configure.ac	8 Feb 2006 22:49:03 -0000	1.36
+++ configure.ac	7 Feb 2007 13:48:37 -0000
@@ -112,6 +112,7 @@
 support_scroll_xterm=yes
 support_scroll_plain=yes
 support_xim=yes
+support_gcin=yes
 support_xpm=yes
 support_xft=yes
 support_unicode3=no
@@ -156,6 +157,7 @@
        support_utmp=no
        support_wtmp=no
        support_xim=no
+       support_gcin=no
        support_xpm=no
        support_xft=no
        support_unicode3=no
@@ -185,6 +187,7 @@
        support_utmp=yes
        support_wtmp=yes
        support_xim=yes
+       support_gcin=yes
        support_xpm=yes
        support_xft=yes
        support_unicode3=yes
@@ -284,6 +287,11 @@
   [if test x$enableval = xyes -o x$enableval = xno; then
     support_xim=$enableval
   fi])
+AC_ARG_ENABLE(gcin,
+  [  --enable-gcin            GCIN (gcin IM) protocol support],
+  [if test x$enableval = xyes -o x$enableval = xno; then
+    support_gcin=$enableval
+  fi])
 
 AC_ARG_ENABLE(backspace-key,
   [  --disable-backspace-key disable handling of the backspace key],
@@ -502,6 +510,7 @@
 LIBS=`echo "$LIBS $X_LIBS $X_EXTRA_LIBS -lX11" | sed "$R_TRANSLATE"`
 AC_CACHE_CHECK([for -rpath dynamic library path recording], rxvt_cv_rpath,
 [AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include<stdlib.h>
 main()
 {
     exit(0);
@@ -515,6 +524,7 @@
   LIBS=`echo "$ac_save_LIBS $X_LIBS $X_EXTRA_LIBS -lX11" | sed "$R_TRANSLATE"`
   AC_CACHE_CHECK([for -R dynamic library path recording], rxvt_cv_R,
 [AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include<stdlib.h>
 main()
 {
     exit(0);
@@ -686,6 +696,7 @@
 fi
 AC_CACHE_CHECK(for working Xlocale, rxvt_cv_func_xlocale,
 [AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <X11/Xlib.h>
+#include <stdlib.h>
 main() {
 char *p;
 if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p)
@@ -802,6 +813,11 @@
     AC_DEFINE(USE_XIM, 1, Define if you want to have XIM (X Input Method) protocol support - required for multibyte characters input)
   fi
 fi
+if test x$support_gcin = xyes -o x$multichar_set = xyes; then
+  if test x$rxvt_cv_func_xlocale = xyes; then
+    AC_DEFINE(USE_GCIN, 1, Define if you want to have GCIN (gcin IM) protocol support - required for multibyte characters input)
+  fi
+fi
 if test x$support_xpm = xyes; then
   AC_DEFINE(XPM_BACKGROUND, 1, Define if you want to have sexy-looking background pixmaps. Needs libXpm)
 fi
@@ -918,6 +934,9 @@
   X_EXTRA_LIBS=`echo $X_EXTRA_LIBS | sed "$R_TRANSLATE"`
   XPM_LIBS=`echo $XPM_LIBS | sed "$R_TRANSLATE"`
 fi
+if test x$support_gcin = xyes; then
+  LIBS=`echo $LIBS -L/usr/lib/gcin -lgcin-im-client | sed "$R_TRANSLATE"`
+fi
 AC_SUBST(DLIB)
 AC_SUBST(LIBS)
 AC_SUBST(X_LIBS)
@@ -1001,6 +1020,13 @@
   echo ".          XIM is now being DISABLED!                            ."
   echo ".----------------------------------------------------------------."
 fi
+if test x$support_gcin = xyes -a x$rxvt_cv_func_xlocale = xno; then
+  echo ".----------------------------------------------------------------."
+  echo ". WARNING: --enable-gcin was specified however the locale support ."
+  echo ".          functions could not be found.                         ."
+  echo ".          GCIN is now being DISABLED!                            ."
+  echo ".----------------------------------------------------------------."
+fi
 
 echo "*** Optionally check src/feature.h for further, rarely used options ***"
 echo
Index: src/command.C
===================================================================
RCS file: /schmorpforge/rxvt-unicode/src/command.C,v
retrieving revision 1.318
diff -u -r1.318 command.C
--- src/command.C	13 Jan 2007 15:26:56 -0000	1.318
+++ src/command.C	7 Feb 2007 13:48:38 -0000
@@ -384,6 +384,38 @@
       valid_keysym = status_return == XLookupKeySym
                      || status_return == XLookupBoth;
     }
+#endif
+#if defined(USE_XIM) && defined(USE_GCIN)
+  else if (Gcin_Handle)
+#elif defined(USE_GCIN)
+  if (Gcin_Handle)
+    {
+      char *rstr = NULL;
+      len = XLookupString (&ev, kbuf, KBUFSZ, &keysym, &compose);
+      //      valid_keysym = 1;
+      valid_keysym = keysym != NoSymbol;
+      if (gcin_im_client_forward_key_press (Gcin_Handle, keysym, ev.state, &rstr))
+	{
+	  if (rstr)
+	    {
+	      len = strlen (rstr);
+	      strncpy (kbuf, rstr, len);
+	      kbuf[len] = '\0';
+	      keysym = ' ';
+	      shft = ctrl = meta = 0;
+	    }
+	  else
+	    {
+#if 0
+	      len = 0;
+	      valid_keysym = 0;
+#endif
+	      return;
+	    }
+	}
+      if (rstr)
+	free (rstr);
+    }
   else
 #endif
     {
@@ -917,10 +949,15 @@
 void
 rxvt_term::key_release (XKeyEvent &ev)
 {
-#if (MOUSE_WHEEL && MOUSE_SLIP_WHEELING) || ISO_14755 || ENABLE_PERL
+#if (MOUSE_WHEEL && MOUSE_SLIP_WHEELING) || ISO_14755 || ENABLE_PERL || USE_GCIN
   KeySym keysym;
 
   keysym = XLookupKeysym (&ev, ev.state & ShiftMask ? 1 : 0); // sorry, only shift supported :/
+#if defined(USE_GCIN)
+  char *rstr = NULL;
+  gcin_im_client_forward_key_release (Gcin_Handle, keysym, ev.state, &rstr);
+  free (rstr);
+#endif
 #endif
 
 #if ENABLE_FRILLS || ISO_14755
@@ -1080,7 +1117,7 @@
 
       scr_refresh ();
       scrollbar_show (1);
-#ifdef USE_XIM
+#if defined(USE_XIM) || defined(USE_GCIN)
       IMSendSpot ();
 #endif
     }
@@ -1727,6 +1764,15 @@
           XSetICFocus (Input_Context);
         }
 #endif
+#if USE_GCIN
+      if (Gcin_Handle != NULL)
+	{
+#if 0
+	  IMSetPosition ();
+#endif
+	  gcin_im_client_focus_in(Gcin_Handle);
+	}
+#endif
 #if CURSOR_BLINK
       if (OPTION (Opt_cursorBlink))
         cursor_blink_ev.start (NOW + CURSOR_BLINK_INTERVAL);
@@ -1764,6 +1810,10 @@
       if (Input_Context != NULL)
         XUnsetICFocus (Input_Context);
 #endif
+#if USE_GCIN
+      if (Gcin_Handle != NULL)
+	gcin_im_client_focus_out(Gcin_Handle);
+#endif
 #if CURSOR_BLINK
       if (OPTION (Opt_cursorBlink))
         cursor_blink_ev.stop ();
Index: src/init.C
===================================================================
RCS file: /schmorpforge/rxvt-unicode/src/init.C,v
retrieving revision 1.179
diff -u -r1.179 init.C
--- src/init.C	20 Jan 2007 12:29:35 -0000	1.179
+++ src/init.C	7 Feb 2007 13:48:39 -0000
@@ -246,6 +246,10 @@
       if (i == 4 || i == 7)
         continue;
 #endif
+#ifdef USE_GCIN
+      if (i == Gcin_Handle->fd)
+	continue;
+#endif
       close (i);
     }
 #endif
@@ -592,7 +596,7 @@
 {
   set_environ (envv);
 
-#ifdef USE_XIM
+#if defined(USE_XIM) || defined(USE_GCIN)
   if (!locale)
     rxvt_warn ("setting locale failed, working without locale support.\n");
   else
@@ -990,7 +994,7 @@
 
   XSelectInput (dpy, top,
                 KeyPressMask
-#if (MOUSE_WHEEL && MOUSE_SLIP_WHEELING) || ENABLE_FRILLS || ISO_14755
+#if (MOUSE_WHEEL && MOUSE_SLIP_WHEELING) || ENABLE_FRILLS || ISO_14755 || USE_GCIN
                 | KeyReleaseMask
 #endif
                 | FocusChangeMask | VisibilityChangeMask
@@ -1316,6 +1320,9 @@
                 if ((*t)->pty->pty > 2) close ((*t)->pty->pty);
                 if ((*t)->pty->tty > 2) close ((*t)->pty->tty);
               }
+#ifdef USE_GCIN
+	    close (Gcin_Handle->fd);
+#endif
 
             run_child (argv);
             fprintf (stderr, "%s: unable to exec child.", RESNAME);
Index: src/main.C
===================================================================
RCS file: /schmorpforge/rxvt-unicode/src/main.C,v
retrieving revision 1.231
diff -u -r1.231 main.C
--- src/main.C	27 Aug 2006 10:14:47 -0000	1.231
+++ src/main.C	7 Feb 2007 13:48:39 -0000
@@ -174,7 +174,7 @@
 #ifdef POINTER_BLANK
     pointer_ev (this, &rxvt_term::pointer_cb),
 #endif
-#ifdef USE_XIM
+#if defined(USE_XIM) || defined(USE_GCIN)
     im_ev (this, &rxvt_term::im_cb),
 #endif
 #ifndef NO_BELL     
@@ -327,7 +327,7 @@
 
   if (display)
     {
-#if USE_XIM
+#if defined(USE_XIM) || defined(USE_GCIN)
       im_ev.stop (display);
 #endif
 #if HAVE_SCROLLBARS
@@ -1159,7 +1159,7 @@
 /* -------------------------------------------------------------------- *
  * -                      X INPUT METHOD ROUTINES                     - *
  * -------------------------------------------------------------------- */
-#ifdef USE_XIM
+#if defined(USE_XIM) || defined(USE_GCIN)
 
 void
 rxvt_term::im_set_color (unsigned long &fg, unsigned long &bg)
@@ -1202,7 +1202,11 @@
   Atom atom;
   Window win;
   char server[IMBUFSIZ];
-
+#if defined(USE_GCIN)
+  if (Gcin_Handle)
+    return True;
+#endif
+#ifdef USE_XIM
   /* get current locale modifier */
   if ((p = XSetLocaleModifiers (NULL)) != NULL)
     {
@@ -1218,7 +1222,7 @@
       if (win != None)
         return True;
     }
-
+#endif
   return False;
 }
 
@@ -1228,9 +1232,18 @@
   XPoint nspot;
   XVaNestedList preedit_attr;
 
-  if (!Input_Context
-      || !focus
-      || !(input_style & (XIMPreeditPosition | XIMPreeditCallbacks)))
+  if (
+      !focus
+#if defined(USE_XIM)
+      || !Input_Context
+#endif
+#if defined(USE_GCIN)
+      || !Gcin_Handle
+#endif
+#if defined(USE_XIM)
+      || !(input_style & (XIMPreeditPosition | XIMPreeditCallbacks))
+#endif
+      )
     return;
 
   im_set_position (nspot);
@@ -1240,11 +1253,23 @@
 
   spot = nspot;
 
-  preedit_attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
-  XSetICValues (Input_Context, XNPreeditAttributes, preedit_attr, NULL);
-  XFree (preedit_attr);
+#if defined(USE_XIM)
+  if (Input_Context)
+    {
+      preedit_attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL);
+      XSetICValues (Input_Context, XNPreeditAttributes, preedit_attr, NULL);
+      XFree (preedit_attr);
+    }
+#endif
+#if defined(USE_GCIN)
+  if (Gcin_Handle)
+    {
+      gcin_im_client_set_cursor_location(Gcin_Handle, nspot.x, nspot.y);
+    }
+#endif
 }
 
+#ifdef USE_XIM
 void
 rxvt_term::im_destroy ()
 {
@@ -1259,6 +1284,7 @@
 
   Input_Context = 0;
 }
+#endif
 
 #ifdef ENABLE_XIM_ONTHESPOT
 
@@ -1341,6 +1367,10 @@
 bool
 rxvt_term::IM_get_IC (const char *modifiers)
 {
+#if defined(USE_GCIN)
+  Gcin_Handle = gcin_im_client_open(display->dpy);
+  gcin_im_client_set_window(Gcin_Handle, parent[0]);
+#else
   int i, j, found;
   XIM xim;
   XPoint spot;
@@ -1352,7 +1382,6 @@
 #ifdef ENABLE_XIM_ONTHESPOT
   XIMCallback xcb[4];
 #endif
-
   set_environ (envv);
 
   if (! ((p = XSetLocaleModifiers (modifiers)) && *p))
@@ -1549,13 +1578,14 @@
 #endif
 
   IMSetPosition ();
-
+#endif
   return true;
 }
 
 void
 rxvt_term::im_cb ()
 {
+#ifdef USE_XIM
   int i;
   const char *p;
   char **s;
@@ -1599,7 +1629,7 @@
       if (found)
         goto done;
     }
-
+#endif
   /* try with XMODIFIERS env. var. */
   if (IM_get_IC (""))
     goto done;
@@ -1615,6 +1645,7 @@
 #endif
 }
 
+#ifdef USE_XIM
 void
 rxvt_term::IMSetPosition ()
 {
@@ -1658,6 +1689,7 @@
 
    XFree (preedit_attr);
 }
+#endif
 #endif                          /* USE_XIM */
 
 /*----------------------- end-of-file (C source) -----------------------*/
Index: src/rxvt.h
===================================================================
RCS file: /schmorpforge/rxvt-unicode/src/rxvt.h,v
retrieving revision 1.266
diff -u -r1.266 rxvt.h
--- src/rxvt.h	20 Jan 2007 00:45:30 -0000	1.266
+++ src/rxvt.h	7 Feb 2007 13:48:39 -0000
@@ -34,6 +34,10 @@
 # include <X11/Xmd.h>
 #endif
 
+#ifdef USE_GCIN
+#include <gcin-im-client.h>
+#endif
+
 #include "encoding.h"
 #include "rxvtutil.h"
 #include "rxvtfont.h"
@@ -1193,10 +1197,13 @@
   rxvt_xim *input_method;
   XIC      Input_Context;
   XIMStyle input_style;
+  
+#endif
+#if defined(USE_XIM) | defined(USE_GCIN)
   XPoint   spot; // most recently sent spot position
-
+  im_watcher im_ev;
   void im_destroy ();
-  void im_cb (); im_watcher im_ev;
+  void im_cb ();
   void im_set_size (XRectangle &size);
   void im_set_position (XPoint &pos) NOTHROW;
   void im_set_color (unsigned long &fg, unsigned long &bg);
@@ -1207,6 +1214,9 @@
   bool IM_get_IC (const char *modifiers);
   void IMSetPosition ();
 #endif
+#ifdef USE_GCIN
+  GCIN_client_handle *Gcin_Handle;
+#endif
 
   void resize_scrollbar ();
 
Index: src/rxvttoolkit.C
===================================================================
RCS file: /schmorpforge/rxvt-unicode/src/rxvttoolkit.C,v
retrieving revision 1.63
diff -u -r1.63 rxvttoolkit.C
--- src/rxvttoolkit.C	18 Aug 2006 23:03:31 -0000	1.63
+++ src/rxvttoolkit.C	7 Feb 2007 13:48:39 -0000
@@ -62,8 +62,10 @@
   "_NET_WM_ICON_NAME",
   "_NET_WM_PING",
 #endif
-#if USE_XIM
+#if defined(USE_XIM) || defined(USE_GCIN)
   "WM_LOCALE_NAME",
+#endif
+#ifdef USE_XIM
   "XIM_SERVERS",
 #endif
 #ifdef TRANSPARENT
@@ -507,13 +509,15 @@
   XCloseDisplay (dpy);
 }
 
-#ifdef USE_XIM
+#if defined(USE_XIM) || defined(USE_GCIN)
 void rxvt_display::im_change_cb ()
 {
   for (im_watcher **i = imw.begin (); i != imw.end (); ++i)
     (*i)->call ();
 }
+#endif
 
+#ifdef USE_XIM
 void rxvt_display::im_change_check ()
 {
   // try to only call im_change_cb when a new input method
@@ -605,7 +609,7 @@
   selection_owner = owner;
 }
 
-#ifdef USE_XIM
+#if defined(USE_XIM) || defined(USE_GCIN)
 
 void rxvt_display::reg (im_watcher *w)
 {
@@ -616,7 +620,9 @@
 {
   imw.erase (find (imw.begin (), imw.end (), w));
 }
+#endif
 
+#ifdef USE_XIM
 rxvt_xim *rxvt_display::get_xim (const char *locale, const char *modifiers)
 {
   char *id;
Index: src/rxvttoolkit.h
===================================================================
RCS file: /schmorpforge/rxvt-unicode/src/rxvttoolkit.h,v
retrieving revision 1.29
diff -u -r1.29 rxvttoolkit.h
--- src/rxvttoolkit.h	5 Jul 2006 20:31:48 -0000	1.29
+++ src/rxvttoolkit.h	7 Feb 2007 13:48:39 -0000
@@ -63,8 +63,10 @@
   XA_NET_WM_ICON_NAME,
   XA_NET_WM_PING,
 #endif
-#if USE_XIM
+#if defined(USE_XIM) || defined(USE_GCIN)
   XA_WM_LOCALE_NAME,
+#endif
+#ifdef USE_XIM
   XA_XIM_SERVERS,
 #endif
 #if TRANSPARENT
@@ -196,11 +198,12 @@
 
 #ifdef USE_XIM
   refcache<rxvt_xim> xims;
-  vector<im_watcher *> imw;
-
-  void im_change_cb ();
   void im_change_check ();
 #endif
+#if defined(USE_GCIN) || defined(USE_XIM)
+  void im_change_cb ();
+  vector<im_watcher *> imw;
+#endif
 
 //public
   Display   *dpy;
@@ -226,16 +229,18 @@
   void reg (xevent_watcher *w);
   void unreg (xevent_watcher *w);
 
-#ifdef USE_XIM
+#if defined(USE_XIM) || defined(USE_GCIN)
   void reg (im_watcher *w);
   void unreg (im_watcher *w);
+#endif
 
+#ifdef USE_XIM
   rxvt_xim *get_xim (const char *locale, const char *modifiers);
   void put_xim (rxvt_xim *xim);
 #endif
 };
 
-#ifdef USE_XIM
+#if defined(USE_XIM) || defined(USE_GCIN)
 struct im_watcher : watcher, callback<void (void)> {
   template<class O, class M>
   im_watcher (O object, M method)
Index: src/screen.C
===================================================================
RCS file: /schmorpforge/rxvt-unicode/src/screen.C,v
retrieving revision 1.267
diff -u -r1.267 screen.C
--- src/screen.C	2 Nov 2006 17:23:50 -0000	1.267
+++ src/screen.C	7 Feb 2007 13:48:39 -0000
@@ -3681,7 +3681,7 @@
 }
 
 /* ------------------------------------------------------------------------- */
-#ifdef USE_XIM
+#if defined(USE_XIM) | defined(USE_GCIN)
 void
 rxvt_term::im_set_position (XPoint &pos) NOTHROW
 {
  • Message #667

    哇!這正是我想要的,一直懶得去弄。 這樣就快要可以把討厭的 XIM 幹掉了。 現在只剩 wine,有時候還是要在 wine 上面輸入中文 。

    我在想要不要改成用 GTK_IM_MODULE,GTK_IM_MODULE 的介面其實比 XIM 簡單很多, 而且是大家共有的標準,這樣比較有機會變成 official,不用 patch。那有人會問 GTK 會不會讓 program 的 memory 大很多。

    由於 GTK 現在算是主流,許多主流的軟體都是 GTK,例如 firefox, gaim, gimp, flashplayer9 實在太多了,基本上 GTK 是非用不可的。由於 shared library load 進memory後在不同程式間可以共用的,所以其實還好。

    而且還支援 KeyRelease event,這樣詞音上用 Shift 切換中英就可以用。

    • Message #671

      這樣就快要可以把討厭的 XIM 幹掉了

      啊啊啊,這個請千萬要保留一下呀!因為有些 X 軟體有一定的族群在使用,例如 texmacs/emacs。而且 qt/kde 的程式目前還是有很多 OS/distro 靠的是 xim。或許成為選項?

      • Message #672

        不用緊張,早就已經可以用 configure

        --use_xim=N : disable the support of XIM, exec size is 50k smaller

        決定要不要支援 XIM。 目前我的系統用XIM的只有 urxvt 及 wine。

        • Message #673

          說到 wine,wine 何時才能支援 OverTheSpot 呀?

          • Message #676

            說到 wine,wine 何時才能支援 OverTheSpot 呀?

            今天試了一下,發現 wine 是可以支援 OverTheSpot,但輸入視窗會被固定在左上角。看來又是和 Mozilla 家族類似的情況。

            但據說 oxim/scim 是 OK 的... 怪哉。

        • Message #675

          不用緊張,早就已經可以用 configure --use_xim=N : disable the support of XIM, exec size is 50k smaller

          好家在,我就是怕連這個也沒有了呀!:D

          因為一些 TeX/字型 相關的 GUI 都還是使用 X 在寫的,所以,可能還需要尾大不掉一陣子。