# HG changeset patch # User Yoshiki Yazawa # Date 1268048297 -32400 # Node ID 598fcbe482b597e5fd7c29fd1a75b6b178fcb373 # Parent 89750191b165251d62fe42fe9f421995d9fdfefb imported patch 19_kinput2-v3.1-ruby.patch diff -r 89750191b165 -r 598fcbe482b5 ChangeLog --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ChangeLog Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,120 @@ +2003-03-25 Hiroyuki Komatsu + + * lib/ruby/kinput2_prime.rb (Repository): + - Change lookup method from lookup_prefix to lookup_hybrid. + +2003-02-03 Hiroyuki Komatsu + + * lib/Ruby.c (Repository): + - Get $LOAD_PATH in Ruby by execution of ruby command. + +2003-01-20 Hiroyuki Komatsu + + * lib/Ruby.c (Repository): + - Create `rubyDialogDisplay', `rubySelectionDisplay' and + `rubySelectionEvent' functions. + - Refine the code. + + * lib/Ruby.rb (Repository): + - Create `ConvMode' class. + - Create `Window', and `Selection' class. + - Create `JEditText' class. + +2003-01-19 Hiroyuki Komatsu + + * lib/Ruby.c (Repository): + - Add some methods for Selection. + - Fix SEGV error in `ConvertedString' + + * lib/Ruby.rb (Repository): + - Add PRIME! + + +2003-01-18 Hiroyuki Komatsu + + * lib/Ruby.rb (Repository): + - Change name dialog to selection. + - Create new dialog as AUXSegment. + + * lib/Ruby.c (Repository): + - Create `GetAuxSegments' function for Ruby. + - Modify `rubyDisplayPreEdit' for AuxSegments. + - Commentout all debug messages which have variables, + because of a unknown bug. + + +2003-01-17 Hiroyuki Komatsu + + * lib/Ruby.rb (Repository): + - Create a class `TextEdit'. + - Improving class structures. + - Add methods for input events. + - Create Segment functions for cursor motion. + + * lib/Ruby.c (Repository): + - Change `InputEvent'. + - Modify `GetSegment' function for cursor motion. + + +2003-01-16 Hiroyuki Komatsu + + * lib/Ruby.c (Repository): + - Change `displayPreEdit' to `rubyDisplayPreEdit'. + - Modify `NumSegments' for Ruby. + + * lib/Ruby.rb (Repository): + - Add `clear' function. + - Modify `segment_length' function. + + * lib/Ruby.c (Repository): + - Modified a function `CursorPos' for Ruby. + - Modifying a function `GetAuxSegments' for Ruby. + To finish the modification, it is required that + a definition about a data structure for word parts. + + * lib/Ruby.rb (Repository): + Add a new variable 'cand_list'. + + * lib/Ruby.c (Repository): + Add a new function 'rubyEUCArraytoICStringArray'. + +2003-01-15 Hiroyuki Komatsu + + * .cvsignore: [NEW FILE] + + * lib/Ruby.c (Repository): + Finish to make a function 'rubyEUC2ICString'. It's been working. + +2003-01-14 Hiroyuki Komatsu + + * lib/Xrubylib/memo.txt (Repository): + Add a description about ICString and it's Memory management. + + * lib/Ruby.c (Repository): Add a function 'rubyEUC2ICString'. + However, it has not been working. + + * lib/Ruby.rb (Repository): Add space-key action. + +2003-01-12 Hiroyuki Komatsu + + * lib/Ruby.rb (Repository): Add comment about keycodes. + +2003-01-11 Hiroyuki Komatsu + + * lib/Ruby.c (Repository): + Trap InputEvent and ConvertedString for test. + + * lib/Ruby.rb (Repository): [NEW FILE] + Ruby script for Ruby.c + + * lib/Xrubylib/misc.c (Repository): [NEW FILE] + Copy euc2wcs and wcs2euc functions from Xatoklib/misc.c + +2003-01-10 Hiroyuki Komatsu + + * lib/ruby-c.c: [NEW FILE] a library to invoke ruby. + * lib/ruby-c.h: [NEW FILE] a library to invoke ruby. + * lib/Ruby.c: Early stage to use ruby. + Almost all functions for canna are not modified yet. + + diff -r 89750191b165 -r 598fcbe482b5 Kinput2.conf --- a/Kinput2.conf Mon Mar 08 20:38:16 2010 +0900 +++ b/Kinput2.conf Mon Mar 08 20:38:17 2010 +0900 @@ -20,6 +20,7 @@ #define UseCanna /* define if you are going to use Canna */ #define UseSj3 /* define if you are going to use Sj3 */ /* #define UseAtok */ /* define if you are going to use Atok */ +/* #define UseRuby */ /* define if you are going to use Ruby */ XCOMM Wnn configuration @@ -137,6 +138,23 @@ ATOKLIB = -latok12n -latok12util +XCOMM Ruby configuration +/* + * If you define UseRuby, set following 2 variables: + * RUBYSRC: Ruby source directory (or directory of installed headers) + * RUBYLIB: Ruby user library + */ + +/* + * If you have already installed Ruby header files and libraries.. + */ +XCOMM use installed headers/libraries + +RUBYDIR = /usr/local/lib/site_ruby +RUBYLIB = -lruby ../lib/Xrubylib/libXrubylib.a +RUBYINSTDIR = /usr/lib/ruby +RUBYSRC = $(RUBYINSTDIR)/1.6/i386-linux + /** ** Transport configuration: ** Kinput2 X Input Method Protocol handler supports diff -r 89750191b165 -r 598fcbe482b5 autogen.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/autogen.sh Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,7 @@ +#!/bin/sh + +xmkmf +make Makefiles +make depend +echo "----------" +echo "Execute 'make' and 'make install'." diff -r 89750191b165 -r 598fcbe482b5 cmd/Imakefile --- a/cmd/Imakefile Mon Mar 08 20:38:16 2010 +0900 +++ b/cmd/Imakefile Mon Mar 08 20:38:17 2010 +0900 @@ -38,10 +38,14 @@ XATOKLIB = ../lib/Xatoklib/libXatoklib.a LIBS = $(XATOKLIB) -L$(ATOKLIBDIR) $(ATOKLIB) #endif +#ifdef UseRuby + DEFR = -DUSE_RUBY + LIBR = $(RUBYLIB) +#endif DEPLIBS = $(KI2LIB) $(IMLIB) $(XSJ3CLIB) $(XATOKLIB) XawClientDepLibs - LOCAL_LIBRARIES = $(KI2LIB) $(IMLIB) $(LIBW) $(LIBI) $(LIBS) XawClientLibs - DEFINES = $(SIGNAL_DEFINES) $(DEFW) $(DEFI) $(DEFS) + LOCAL_LIBRARIES = $(KI2LIB) $(IMLIB) $(LIBW) $(LIBI) $(LIBS) $(LIBR) XawClientLibs + DEFINES = $(SIGNAL_DEFINES) $(DEFW) $(DEFI) $(DEFS) $(DEFR) SRCS = kinput2.c OBJS = kinput2.o diff -r 89750191b165 -r 598fcbe482b5 cmd/kinput2.c --- a/cmd/kinput2.c Mon Mar 08 20:38:16 2010 +0900 +++ b/cmd/kinput2.c Mon Mar 08 20:38:17 2010 +0900 @@ -38,7 +38,7 @@ #include "XimpProto.h" #include "IMProto.h" -#if !defined(USE_WNN) && !defined(USE_CANNA) && !defined(USE_SJ3) && !defined(USE_ATOK) +#if !defined(USE_WNN) && !defined(USE_CANNA) && !defined(USE_SJ3) && !defined(USE_ATOK) && !defined(USE_RUBY) #define USE_WNN /* default */ #endif @@ -58,6 +58,10 @@ #include "Atok.h" #include "WcharDisp.h" #endif +#ifdef USE_RUBY +#include "Ruby.h" +#include "WcharDisp.h" +#endif #include "DebugPrint.h" @@ -155,6 +159,12 @@ {"-atokconf", "*Atok.conf", XrmoptionSepArg, NULL}, {"-atokstyle", "*Atok.style", XrmoptionSepArg, NULL}, #endif +#ifdef USE_RUBY + {"-ruby", ".conversionEngine", XrmoptionNoArg, "ruby"}, + {"-rubyserver", "*Canna.cannahost", XrmoptionSepArg, NULL}, + {"-rs", "*Canna.cannahost", XrmoptionSepArg, NULL}, + {"-rubyfile", "*Canna.cannafile", XrmoptionSepArg, NULL}, +#endif }; XtAppContext apc; @@ -392,6 +402,11 @@ return atokObjectClass; } #endif +#ifdef USE_RUBY + if (!strcmp(appres.conversionEngine, "ruby")) { + return rubyObjectClass; + } +#endif /* set default input object */ #ifdef USE_ATOK @@ -406,6 +421,9 @@ #ifdef USE_WNN class = ccWnnObjectClass; #endif +#ifdef USE_RUBY + class = rubyObjectClass; +#endif return class; } @@ -560,6 +578,11 @@ "-atokconf ", "specify atok customize file", "-atokstyle ", "specify atok style file", #endif +#ifdef USE_RUBY + "-ruby", "use Canna (Iroha) as the conversion engine", + "{-rubyserver|-rs} [:n]", "specify cannaserver host", + "-rubyfile ", "specify canna customize file", +#endif "-bc", "backward compatible mode", "-font ", "ASCII font to be used", "-kanjifont ", "KANJI font to be used", @@ -623,6 +646,9 @@ #ifdef USE_ATOK printf("[Atok] "); #endif +#ifdef USE_RUBY + printf("[Ruby] "); +#endif #ifdef DEBUG printf("[DEBUG] "); #endif diff -r 89750191b165 -r 598fcbe482b5 include/Ruby.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/Ruby.h Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,73 @@ +/* $Id: Ruby.h,v 1.2 2003/06/10 02:11:19 komatsu Exp $ */ +/* + * Copyright (c) 1990 Software Research Associates, Inc. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Software Research Associates not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Software Research + * Associates makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * Author: Makoto Ishisone, Software Research Associates, Inc., Japan + */ + +/* Copyright 1991 NEC Corporation, Tokyo, Japan. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of NEC Corporation + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. NEC + * Corporation makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * NEC CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NEC CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Akira Kon, NEC Corporation. (kon@d1.bs2.mt.nec.co.jp) + */ + +#ifndef _Ruby_h +#define _Ruby_h + +#include "InputConv.h" + +/* + Ruby new resources: + + name class type default access + ---------------------------------------------------------------------------- + rubyhost Rubyhost String *1 CG + rubyfile Rubyfile String *2 CG + + note: *1) if not specified, use value of an environment variable "RUBYHOST" + *2) if not specified, use value of an environment variable "RUBYFILE" +*/ + +#define XtNrubyhost "rubyhost" +#define XtCRubyhost "Rubyhost" +#define XtNrubyfile "rubyfile" +#define XtCRubyfile "Rubyfile" +#define XtNsendReturnByString "sendReturnByString" +#define XtCSendReturnByString "SendReturnByString" + +typedef struct _RubyClassRec *RubyObjectClass; +typedef struct _RubyRec *RubyObject; + +extern WidgetClass rubyObjectClass; + +#endif /* _Ruby_h */ + diff -r 89750191b165 -r 598fcbe482b5 include/RubyP.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/RubyP.h Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,111 @@ +/* $Id: RubyP.h,v 1.2 2003/06/10 02:11:19 komatsu Exp $ */ +/* + * Copyright (c) 1990 Software Research Associates, Inc. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Software Research Associates not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Software Research + * Associates makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * Author: Makoto Ishisone, Software Research Associates, Inc., Japan + */ + +/* Copyright 1991 NEC Corporation, Tokyo, Japan. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of NEC Corporation + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. NEC + * Corporation makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * NEC CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NEC CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Akira Kon, NEC Corporation. (kon@d1.bs2.mt.nec.co.jp) + */ + + +#ifndef _RubyP_h +#define _RubyP_h + +#include "InputConvP.h" + +#include "WStr.h" +#include "Ruby.h" + +typedef struct { + int foo; +} RubyClassPart; + +typedef struct _RubyClassRec { + ObjectClassPart object_class; + InputConvClassPart inputConv_class; + RubyClassPart ruby_class; +} RubyClassRec; + +#define NConvertedSegments 3 + +typedef struct { + wchar *str[NConvertedSegments + 3]; + int size[NConvertedSegments + 3]; + int len[NConvertedSegments + 3]; + int offset; + int curseg; + int nseg; + int candstat; /* $B8uJd0lMw9T$N>uBV!#0J2<$r8+$h(B */ + ICString ics[3]; + wchar *gline[3]; + int glsize[3], gllen[3]; + int curgseg, ngseg; + wchar *curmode; + int modesize, modelen; +} iBuf; + +#define RUBY_GLINE_Empty 0 +#define RUBY_GLINE_Start 1 +#define RUBY_GLINE_End 2 +#define RUBY_GLINE_Change 3 + +typedef struct { + /* resources */ + String rubyhost; + String rubyfile; + Boolean sendReturnByString; + /* private data */ + iBuf *ibuf; + Boolean textchanged; /* $BJQ49%F%-%9%H$,JQ$o$C$?$+(B */ + Boolean selectionending;/* $BA*Br%b!<%I$r=*N;$7$h$&$H$7$F$$$k$+(B */ + ICString *symbollist; + int numsymbols; + int cursymbol; /* $B5-9fA*Br;~!"8=:_A*Br$5$l$F$$$k5-9f(B */ + ICString *candlist; + int candlistsize; + int numcand; /* $BA*Br%b!<%I$N;~!"8uJd?t(B */ + int curcand; /* $B8uJdA*Br;~!"8=:_A*Br$5$l$F$$$k8uJd(B */ + int *cur_addr; /* $B8uJdA*Br;~8uJdHV9f$rF~$l$k%"%I%l%9(B */ + Boolean lastTextLengthIsZero; +} RubyPart; + +typedef struct _RubyRec { + ObjectPart object; + InputConvPart inputConv; + RubyPart ruby; +} RubyRec; + +#endif diff -r 89750191b165 -r 598fcbe482b5 lib/Imakefile --- a/lib/Imakefile Mon Mar 08 20:38:16 2010 +0900 +++ b/lib/Imakefile Mon Mar 08 20:38:17 2010 +0900 @@ -54,14 +54,21 @@ ATOKINCS = -I$(ATOKINCDIR) SUBDIRS = imlib Xatoklib #endif +#ifdef UseRuby + RUBYSRCS = Ruby.c ruby-c.c + RUBYOBJS = Ruby.o ruby-c.o + RUBYINCS = -I$(RUBYSRC) + SUBDIRS = imlib Xrubylib ruby +# SUBDIRS = imlib Xrubylib +#endif SRCS = $(WIDGETSRCS) $(UTILSRCS) \ - $(WNNSRCS) $(CANNASRCS) $(SJ3SRCS) $(ATOKSRCS) + $(WNNSRCS) $(CANNASRCS) $(SJ3SRCS) $(ATOKSRCS) $(RUBYSRCS) OBJS = $(WIDGETOBJS) $(UTILOBJS) \ - $(WNNOBJS) $(CANNAOBJS) $(SJ3OBJS) $(ATOKOBJS) + $(WNNOBJS) $(CANNAOBJS) $(SJ3OBJS) $(ATOKOBJS) $(RUBYOBJS) LOCAL_INCLUDES = -I../include -Iimlib - INCLUDES = $(LOCAL_INCLUDES) $(WNNINCS) $(CANNAINCS) $(SJ3INCS) $(ATOKINCS) + INCLUDES = $(LOCAL_INCLUDES) $(WNNINCS) $(CANNAINCS) $(SJ3INCS) $(ATOKINCS) $(RUBYINCS) DEFINES = $(WNNDEFS) $(SJ3DEFS) $(TRANSPORTDEFS) diff -r 89750191b165 -r 598fcbe482b5 lib/Prime.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/Prime.rb Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,303 @@ +PRIME_PATH = '/home/komatsu/src/prime' +$LOAD_PATH.push (PRIME_PATH) + +require 'prime/prime' + +class KanjiConv < KanjiConvCore + attr_reader :input, :selection, :dialog + + def initialize + super + @useprime = false +# @useprime = true + + if @useprime then + @prime = Prime.new + end + @input = JTextEdit.new + + @selection = Selection.new (self) + @dialog = Dialog.new (self) + @mode = ModeMaster.new (self) + + @fundMode = FundMode.new(self) + @inputMode = InputMode.new(self) + @convMode = ConvMode.new(self) + @mode.set(:fund, @fundMode) + @mode.set(:input, @inputMode) + @mode.set(:conv, @convMode) + @mode.change(:fund) + + puts "Initialize Done." + end + + def reset + super + @mode.change(:fund) + @input.reset + reset_cand_list + end + + def convert (word) + if @useprime then + cand_list = @prime.lookup_prefix(word).split("\n").map {|line| + line.split("\t")[1] + } + else + cand_list = [word, "Taiyaki", "Hiroyuki", "Komatsu", "$B4A;z(B"] + end + return cand_list[0,5] + end + + ## inputEvent (keynum, keysym = nil, state = nil) + ## ReturnValue 1:Pass 0:Trap + def inputEvent (keynum, keysym = nil, state = nil) + puts "KeyNum: #{keynum}, KeySym: #{keysym}, Status: #{state}" + + if keynum == 0 then + return 1 + end + key = [keynum] + + if @mode.current then + trap = @mode.current.call (keynum, keysym, state) + return ((trap == true) ? 0 : 1) + end + return 1; + end + + def selection_fix (index) + fix (index) + @mode.change(:fund) + end + + def fix (fixed_arg) + ### Must NOT chage @mode here, because exceptional case can exist. + super (fixed_arg) + @input.reset + reset_cand_list + end + + def insert (keysym, modifiers) + puts "insert '#{keysym.chr}'" + @input.insert(keysym.chr) + set_cand_list (convert(@input.text), 0) + end +end + +class PrimeModeCore < ModeCore + def initialize (parent) + super + end + + private + def insert (keysym, modifiers) + @parent.insert(keysym, modifiers) + @parent.mode.change(:input) + return true + end + + def fix (keysym, modifiers) + fix_internal(keysym, modifiers) + @parent.mode.change(:fund) + return true + end + + def fix_and_insert (keysym, modifiers) + fix_internal (keysym, modifiers) + insert (keysym, modifiers) + return true + end + + def cursor_right (keysym, modifiers) + @parent.input.cursor_right + return true + end + def cursor_left (keysym, modifiers) + @parent.input.cursor_left + return true + end + def cursor_beginning (keysym, modifiers) + @parent.input.cursor_beginning + return true + end + def cursor_end (keysym, modifiers) + @parent.input.cursor_end + return true + end + + def selection_right (keysym, modifiers) + @parent.selection.right + return true + end + def selection_left (keysym, modifiers) + @parent.selection.left + return true + end + def selection_beginning (keysym, modifiers) + @parent.selection.line_beginning + return true + end + def selection_end (keysym, modifiers) + @parent.selection.line_end + return true + end + def selection_up (keysym, modifiers) + @parent.selection.up + return true + end + def selection_down (keysym, modifiers) + @parent.selection.down + return true + end +end + +class FundMode < PrimeModeCore + def initialize (parent) + super + @label = '[ $B$"(B ]' + @trap = false + end + + def initialize_keys + (33..126).each {|char| + @keymap.add(char, :insert) + } + end + + def on (prev_mode = nil) + @parent.selection.close + @parent.dialog.close + end +end + +class InputMode < PrimeModeCore + def initialize (parent) + super + @label = "[$BF~NO(B]" + end + + def initialize_keys + (33..126).each {|char| + @keymap.add(char, :insert) + } + (?A..?Z).each {|char| + @keymap.add(char, :fix_and_insert) + } + @keymap.add(:enter, :fix) + @keymap.add([?m, :ctrl], :fix) + @keymap.add(:space, :convert) + @keymap.add(:backspace, :backspace) + @keymap.add([?h, :ctrl], :backspace) + @keymap.add(:delete, :delete) + @keymap.add([?d, :ctrl], :delete) + @keymap.add(:left, :cursor_left) + @keymap.add([?b, :ctrl], :cursor_left) + @keymap.add(:right, :cursor_right) + @keymap.add([?f, :ctrl], :cursor_right) + @keymap.add([?a, :ctrl], :cursor_beginning) + @keymap.add([?e, :ctrl], :cursor_end) + @keymap.add([?g, :ctrl], :cancel) + @keymap.add(:esc, :cancel) + end + + def on (prev_mode = nil) + @parent.selection.close + @parent.dialog.open + end + + def entries + return @parent.input.segments + end + + private + def fix_internal (keysym, modifiers) + @parent.fix(@parent.input.text) + end + + def backspace (keysym, modifiers) + @parent.input.backspace + if @parent.input.text.length == 0 then + @parent.mode.change(:fund) + end + return true + end + + def delete (keysym, modifiers) + @parent.input.delete + if @parent.input.text.length == 0 then + @parent.mode.change(:fund) + end + return true + end + + def cancel (keysym, modifiers) + @parent.input.reset + @parent.mode.change(:fund) + return true + end + + def convert (keysym, modifiers) + if @parent.set_cand_list (@parent.convert(@parent.input.text)) then + @parent.set_cand_index(0) + @parent.mode.change(:conv) + end + return true + end +end + +class ConvMode < PrimeModeCore + def initialize (parent) + super + @label = "[$BJQ49(B]" + end + + def initialize_keys + (33..126).each {|char| + @keymap.add(char, :fix_and_insert) + } + @keymap.add(:enter, :fix) + @keymap.add([?m, :ctrl], :fix) + @keymap.add(:space, :convert) +# @keymap.add(:backspace, :backspace) +# @keymap.add([?h, :ctrl], :backspace) +# @keymap.add(:delete, :delete) +# @keymap.add([?d, :ctrl], :delete) + @keymap.add(:left, :selection_left) + @keymap.add([?b, :ctrl], :selection_left) + @keymap.add(:right, :selection_right) + @keymap.add([?f, :ctrl], :selection_right) + @keymap.add(:down, :selection_down) + @keymap.add([?n, :ctrl], :selection_down) + @keymap.add(:up, :selection_up) + @keymap.add([?p, :ctrl], :selection_up) + @keymap.add([?a, :ctrl], :selection_beginning) + @keymap.add([?e, :ctrl], :selection_end) + @keymap.add([?g, :ctrl], :cancel) + @keymap.add(:esc, :cancel) + end + + def on (prev_mode = nil) + @parent.selection.open + @parent.dialog.close + end + + def entries + return ['', @parent.cand_list[@parent.cand_index]] + end + + private + def fix_internal (keysym, modifiers) + @parent.fix(@parent.cand_list[@parent.cand_index]) + end + + def cancel (keysym, modifiers) + @parent.mode.change(:input) + return true + end + + def convert (keysym, modifiers) + return selection_right(keysym, modifiers) + end +end + diff -r 89750191b165 -r 598fcbe482b5 lib/Ruby.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/Ruby.c Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,947 @@ +/* + * Copyright (c) 1990 Software Research Associates, Inc. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Software Research Associates not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Software Research + * Associates makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * Author: Makoto Ishisone, Software Research Associates, Inc., Japan + */ + +/* Copyright 1991 NEC Corporation, Tokyo, Japan. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of NEC Corporation + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. NEC + * Corporation makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * NEC CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NEC CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Akira Kon, NEC Corporation. (kon@d1.bs2.mt.nec.co.jp) + */ + +/* Copyright 2003 Hiroyuki Komatsu (Ruby.c) */ + +/* 直さなければならないところ + + ・Destroy が呼ばれないので CloseUIContext できない。 + ・モード領域の大きさ。(これは他のファイルだろうな) + + */ + +#ifndef lint +static char *rcsid = "$Id: Ruby.c,v 1.2 2003/06/10 02:11:23 komatsu Exp $"; +#endif + +#include +#include +#include +#define XK_KATAKANA +#include +#if XtSpecificationRelease > 4 +#include +#endif + +#include "RubyP.h" +#include "DebugPrint.h" + +#define wchar_t wchar + +#include "ruby-c.h" + +static XtResource resources[] = { +#define offset(field) XtOffset(RubyObject, ruby.field) + { XtNrubyhost, XtCRubyhost, XtRString, sizeof(String), + offset(rubyhost), XtRString, NULL }, + { XtNrubyfile, XtCRubyfile, XtRString, sizeof(String), + offset(rubyfile), XtRString, NULL }, + { XtNsendReturnByString, XtCSendReturnByString, + XtRBoolean, sizeof(Boolean), + offset(sendReturnByString), XtRBoolean, False }, +#undef offset +}; + +static void ClassInitialize(); +static void Initialize(), Destroy(); +static Boolean SetValues(); +static int InputEvent(); +static ICString *GetMode(); +static int CursorPos(); +static int NumSegments(); +static ICString *GetSegment(); +static int CompareSegment(); +static ICString *GetItemList(); +static int SelectItem(); +static int ConvertedString(); +static int ClearConversion(); +static int GetTriggerKeys(); +static int PreeditString(); +static int StatusString(); + +static void convend(); + +#if 1 /* KC_SETLISTCALLBACK */ +static void openSelection(); +#define SELECTION_SET 0 /* SelectionStart をしても良いと言う情報を設定する */ +#define SELECTION_DO 1 /* 実際に SelectionStart を開始する */ +#else /* !KC_SETLISTCALLBACK */ +#define openSelection(x, y, z) +#endif /* !KC_SETLISTCALLBACK */ + +static ICString *GetAuxSegments(); + +RubyClassRec rubyClassRec = { + { /* object fields */ + /* superclass */ (WidgetClass) &inputConvClassRec, + /* class_name */ "Ruby", + /* widget_size */ sizeof(RubyRec), + /* class_initialize */ ClassInitialize, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* obj1 */ NULL, + /* obj2 */ NULL, + /* obj3 */ 0, + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* obj4 */ FALSE, + /* obj5 */ FALSE, + /* obj6 */ FALSE, + /* obj7 */ FALSE, + /* destroy */ Destroy, + /* obj8 */ NULL, + /* obj9 */ NULL, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* obj10 */ NULL, + /* get_values_hook */ NULL, + /* obj11 */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* obj12 */ NULL, + /* obj13 */ NULL, + /* obj14 */ NULL, + /* extension */ NULL + }, + { /* inputConv fields */ + /* InputEvent */ InputEvent, + /* GetMode */ GetMode, + /* CursorPos */ CursorPos, + /* NumSegments */ NumSegments, + /* GetSegment */ GetSegment, + /* CompareSegment */ CompareSegment, + /* GetItemList */ GetItemList, + /* SelectItem */ SelectItem, + /* GetConvertedString */ ConvertedString, + /* ClearConversion */ ClearConversion, + /* GetAuxSegments */ GetAuxSegments, + /* SupportMultipleObjects */ True, + /* GetTriggerKeys */ GetTriggerKeys, + /* num_trigger_keys */ 0, + /* trigger_keys */ NULL, + /* GetPreeditString */ PreeditString, + /* GetStatusString */ StatusString, + /* NoMoreObjects */ False, + }, + { /* ruby fields */ + /* foo */ 0, + } +}; + +WidgetClass rubyObjectClass = (WidgetClass)&rubyClassRec; + +static void fix(); + +static ICString *SymbolList; +static int NumSymbols; + +static void addObject(); +static void deleteObject(); + +static Display *displaybell = (Display *)0; + +static void rubyEUCtoICString(); +static void rubyEUCArraytoICStringArray(); +static void rubySelectionEvent(); +static void rubySelectionDisplay(); +static void rubyDialogDisplay(); +static void rubyDisplayPreEdit(); + +typedef struct { + ICString *array; + int length; +} ICStringArray; + +static ICString *ruby_tmp_seg; +static ICStringArray *ruby_cand_list; + +static void +ClassInitialize() +{ + ruby_init(); + + ruby_tmp_seg = XtMalloc(sizeof(ICString)); + ruby_tmp_seg->nchars = 0; + ruby_tmp_seg->nbytes = 0; + ruby_cand_list = XtMalloc(sizeof(ICStringArray)); + ruby_cand_list->length = 0; + + ruby_eval("$LOAD_PATH.concat(eval(`ruby -e 'p $LOAD_PATH'`))"); + ruby_eval("$LOAD_PATH.uniq!"); + + if (ruby_eval("ENV['KINPUT2_RUBY']") != Qnil) { + ruby_eval("require ENV['KINPUT2_RUBY']"); + } else { + ruby_eval("require 'kinput2_default'"); + } + if (ruby_eval("global_variables.member?('$kanjiConv')") == Qfalse) { + fprintf(stderr, "Abort: KanjiConv was not initialized.\n"); + exit (-1); + } + ruby_eval("kanjiConv = $kanjiConv"); + TRACE(("RubyObjectClass initialized\n")); +} + +static int +InputEvent(w, event) +Widget w; +XEvent *event; +{ + RubyObject obj = (RubyObject)w; + char key_buf[200]; + KeySym keysym; + int len, nbytes, functionalChar; + + /* KeyPress以外は捨てる */ + if (event->type != KeyPress /*&& event->type != KeyRelease*/) return 0; + + /* 取りあえず文字に直してしまう */ + key_buf[0] = '\0'; + key_buf[1] = '\0'; + key_buf[2] = '\0'; + nbytes = XLookupString(event, key_buf, 20, &keysym, NULL); + + if (keysym == XK_space && (event->xkey.state & ShiftMask)) { + convend(obj); + return 0; + } + + /* ベルを鳴らすディスプレイの設定 */ + displaybell = XtDisplayOfObject((Widget)obj); + + /* かな漢字変換する */ + { + VALUE pass; + printf ("key_buf: `%d'\n", key_buf[0]); + printf ("strlen(key_buf): `%d'\n", strlen(key_buf)); + printf ("nbytes: `%d'\n", nbytes); + pass = ruby_evalf ("kanjiConv.inputEvent(%d, %d, %d)", + key_buf[0], (int)keysym, (int)(event->xkey.state)); + printf ("Input: done\n"); + + rubyDisplayPreEdit(obj); + + return NUM2INT(pass); /* 1: pass the key / 0: trap the key */ + } +} + + +static void +rubyDialogDisplay(obj) +RubyObject obj; +{ + ICAuxControlArg arg; + + /* I'm not sure about Aux. */ + if (ruby_eval("kanjiConv.dialog.visible") == Qfalse) { + if (ruby_eval("kanjiConv.dialog.call_open") == Qtrue && + ruby_eval ("kanjiConv.dialog.text.length > 0") == Qtrue) { + printf ("Dialog: open\n"); + arg.command = ICAuxStart; + XtCallCallbackList((Widget)obj, obj->inputConv.auxcallback, + (XtPointer)&arg); + ruby_eval("kanjiConv.dialog.open_end"); + } + } else { /* value_dialog_visible == true */ + if (ruby_eval("kanjiConv.dialog.call_close") == Qtrue) { + printf ("Dialog: close\n"); + arg.command = ICAuxEnd; + XtCallCallbackList((Widget)obj, obj->inputConv.auxcallback, + (XtPointer)&arg); + ruby_eval("kanjiConv.dialog.close_end"); + printf ("Dialog: close...done\n"); + } else { + arg.command = ICAuxChange; + XtCallCallbackList((Widget)obj, obj->inputConv.auxcallback, + (XtPointer)&arg); + } + } +} + +static void +rubySelectionEvent(obj) +RubyObject obj; +{ + /*** Right ***/ + if (ruby_eval("kanjiConv.selection.call_right") == Qtrue) { + moveSelection(obj, ICMoveRight); + ruby_eval("kanjiConv.selection.right_end"); + } + + /*** Left ***/ + if (ruby_eval("kanjiConv.selection.call_left") == Qtrue) { + moveSelection(obj, ICMoveLeft); + ruby_eval("kanjiConv.selection.left_end"); + } + + /*** Down ***/ + if (ruby_eval("kanjiConv.selection.call_down") == Qtrue) { + moveSelection(obj, ICMoveDown); + ruby_eval("kanjiConv.selection.down_end"); + } + + /*** Up ***/ + if (ruby_eval("kanjiConv.selection.call_up") == Qtrue) { + moveSelection(obj, ICMoveUp); + ruby_eval("kanjiConv.selection.up_end"); + } + + /*** Beginning Line ***/ + if (ruby_eval("kanjiConv.selection.call_line_beginning") == Qtrue) { + moveSelection(obj, ICMoveLeftMost); + ruby_eval("kanjiConv.selection.line_beginning_end"); + } + + /*** End Line ***/ + if (ruby_eval("kanjiConv.selection.call_line_end") == Qtrue) { + moveSelection(obj, ICMoveRightMost); + ruby_eval("kanjiConv.selection.line_end_end"); + } + + /*** Get Index ***/ + { + ICSelectionControlArg arg; + arg.command = ICSelectionGet; + arg.u.current_item = -1; + + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); + + if (arg.u.current_item >= 0) { + ruby_evalf ("kanjiConv.set_cand_index (%d)", arg.u.current_item); + } + } +} + +static void +moveSelection(obj, dir) +RubyObject obj; +int dir; +{ + ICSelectionControlArg arg; + + arg.command = ICSelectionMove; + arg.u.dir = dir; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); +} + +static void +rubySelectionDisplay(obj) +RubyObject obj; +{ + ICSelectionControlArg arg; + + if (ruby_eval("kanjiConv.selection.call_open") == Qtrue) { + printf ("Selection: open\n"); + arg.command = ICSelectionStart; + arg.u.selection_kind = ICSelectionCandidates; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); + + /* set current item */ + arg.command = ICSelectionSet; + arg.u.current_item = 0; /* INDEX of ITEM */ + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); + + ruby_eval("kanjiConv.selection.open_end"); + } else if (ruby_eval("kanjiConv.selection.call_close") == Qtrue) { + printf ("Selection: close\n"); + arg.command = ICSelectionEnd; + arg.u.current_item = -1; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); + ruby_eval("kanjiConv.selection.close_end"); + } +} + + +static void +rubyDisplayPreEdit(obj) +RubyObject obj; +{ + Widget w = (Widget)obj; + + if (ruby_eval("kanjiConv.call_fix") == Qtrue) { + fix(obj); + } + + /* 入力モードをチェックする */ +/* #if 0 */ +/* if (ks->info & KanjiModeInfo) { */ +/* printf("modechangecallback\n"); */ + XtCallCallbackList(w, obj->inputConv.modechangecallback, + (XtPointer)NULL); +/* } */ +/* #endif */ + + rubyDialogDisplay(obj); + rubySelectionEvent(obj); + rubySelectionDisplay(obj); + + XtCallCallbackList(w, obj->inputConv.textchangecallback, + (XtPointer)NULL); +} + + + + +static ICString * +GetMode(w) +Widget w; +{ + rubyEUCtoICString (ruby_eval ("kanjiConv.modeline"), ruby_tmp_seg); + ruby_tmp_seg->attr = ICAttrNormalString; + return ruby_tmp_seg; +} + +static int +CursorPos(w, nsegp, ncharp) +Widget w; +Cardinal *nsegp; +Cardinal *ncharp; +{ + /* + return value : =0 corsor ON / =1 OFF + nseg: >0 segment index / =0 no segment + nchar: number of chars; 'テs' == 2 + */ + *ncharp = NUM2INT(ruby_eval("kanjiConv.input.cursor")); + *nsegp = 0; + +/* printf ("CursorPos: nseg=%d, nchar=%d\n", (int)*nsegp, (int)*ncharp); */ + + return (*ncharp == 0) ? 1: 0; +} + +static int +NumSegments(w) +Widget w; +{ + int num; + printf ("NumSegments\n"); + num = NUM2INT(ruby_eval("kanjiConv.segment_length")); +/* printf ("NumSegments: num=%d\n", num); */ + return num; +} + +static ICString * +GetSegment(w, n) +Widget w; +Cardinal n; +{ + RubyObject obj = (RubyObject)w; + static ICString seg; + + printf("GetSegment\n"); + + rubyEUCtoICString (ruby_evalf ("kanjiConv.segment_word(%d)", n), + ruby_tmp_seg); + if (ruby_evalf("kanjiConv.segment_status(%d) == :highlight", n) == Qtrue) { + ruby_tmp_seg->attr = ICAttrConverted | ICAttrCurrentSegment; + } else { + ruby_tmp_seg->attr = ICAttrNotConverted; + } + /* ICAttrConverted | ICAttrCurrentSegment : Inversion. */ + /* |= ICAttrChanged : Non-Underline. */ + return ruby_tmp_seg; +} + +/* ARGSUSED */ +static int +CompareSegment(w, seg1, seg2, n) +Widget w; +ICString *seg1; +ICString *seg2; +Cardinal *n; +{ + wchar *p, *q; + int len, nsame; + int result = 0; + + printf("CompareSegment\n"); + + if (seg1->attr != seg2->attr) result |= ICAttrChanged; + + len = seg1->nchars > seg2->nchars ? seg2->nchars : seg1->nchars; + nsame = 0; + p = (wchar *)seg1->data; + q = (wchar *)seg2->data; + while (nsame < len && *p++ == *q++) nsame++; + + if (nsame != len || len != seg1->nchars || len != seg2->nchars) + result |= ICStringChanged; + + if (n) *n = nsame; + + return result; +} + +static ICString * +GetItemList(w, n) +Widget w; +Cardinal *n; +{ + RubyObject obj = (RubyObject)w; + + printf("GetItemList\n"); + rubyEUCArraytoICStringArray(ruby_eval("kanjiConv.cand_list"), + ruby_cand_list); + *n = ruby_cand_list->length; + return ruby_cand_list->array; +} + +static int +SelectItem(w, n) +Widget w; +int n; +{ + + RubyObject obj = (RubyObject)w; + printf ("selectItem\n"); + ruby_evalf("kanjiConv.selection_fix (%d)", n); + /* FIXME: Create new fix function in the feature. */ + fix (obj); + XtCallCallbackList(w, obj->inputConv.textchangecallback, + (XtPointer)NULL); + return 0; +} + +static int +ConvertedString(w, encoding, format, length, string) +Widget w; +Atom *encoding; +int *format; +int *length; +XtPointer *string; +{ + RubyObject obj = (RubyObject)w; + wchar *wbuf, *wp; + int len, wlen; + extern int convJWStoCT(); + + /* メモリの解放は自動的に行われる. str を直接書き換えてはいけない. */ + unsigned char *str = STR2CSTR(ruby_eval("kanjiConv.value_fixed")); + + printf("ConvertedString\n"); + + wbuf = XtMalloc((strlen(str) + 1) * sizeof(wchar)); + euc2wcs(str, strlen(str), wbuf); + wlen = wstrlen(wbuf); + + /* + * Ruby オブジェクトは COMPOUND_TEXT エンコーディングしかサポートしない + * COMPOUND_TEXT に変換する + */ + *encoding = XA_COMPOUND_TEXT(XtDisplayOfObject((Widget)obj)); + *format = 8; + + /* COMPOUND_TEXT は \r が送れないので \n に変換しておく */ + for (wp = wbuf; *wp != 0; wp++) { + if (*wp == '\r') *wp = '\n'; + } + + *length = len = convJWStoCT(wbuf, (unsigned char *)NULL, 0); + *string = XtMalloc(len + 1); + (void)convJWStoCT(wbuf, (unsigned char *)*string, 0); + + XtFree(wbuf); + + return 0; +} + +static int +ClearConversion(w) +Widget w; +{ + ruby_eval ("kanjiConv.clear"); + return 0; +} + +static ICString * +GetAuxSegments(w, n, ns, nc) +Widget w; +Cardinal *n, *ns, *nc; +{ + /* I'm not sure about this function's purpose. */ + /* n => ngseg ; number of segments (1 <= n <= 3). */ + /* ns => nseg ; index of reversed segment (0 or 1). */ + /* nc => nchar ; length of current segment??? */ + printf ("GetAuxSegments\n"); + + if ((ruby_eval ("kanjiConv.dialog.visible") == Qtrue || + ruby_eval ("kanjiConv.dialog.call_open") == Qtrue) && + ruby_eval ("kanjiConv.dialog.text.length > 0") == Qtrue) { + if (n) { + *n = 1; + } + + if (ns) { + *ns = 0; + } + + rubyEUCtoICString (ruby_eval ("kanjiConv.dialog.text"), + ruby_tmp_seg); + ruby_tmp_seg->attr = ICAttrConverted; + + if (nc) { + *nc = ruby_tmp_seg->nchars; + } + + return ruby_tmp_seg; + } else { + if (n) { + *n = 0; + } + if (ns) { + *ns = 0; + } + if (nc) { + *nc = 0; + } + return NULL; + } +} + +/* ARGSUSED */ +static void +Initialize(req, new, args, num_args) +Widget req; +Widget new; +ArgList args; +Cardinal *num_args; +{ + RubyObject obj = (RubyObject)new; + + obj->ruby.selectionending = False; + obj->ruby.textchanged = False; + obj->ruby.symbollist = SymbolList; + obj->ruby.numsymbols = NumSymbols; + obj->ruby.cursymbol = 0; + obj->ruby.candlist = NULL; + obj->ruby.candlistsize = 0; + obj->ruby.numcand = 0; + obj->ruby.lastTextLengthIsZero = False; + + addObject(obj); +} + +static int +bell() +{ + if (displaybell) { + XBell(displaybell, 0); + } + return 0; +} + +static int nRubyContexts = 0; + +static void +Destroy(w) +Widget w; +{ + RubyObject obj = (RubyObject)w; + wchar buf[512]; + int i; + + if (obj->ruby.candlist) { + for (i = 0 ; i < obj->ruby.candlistsize ; i++) { + if ((obj->ruby.candlist + i)->data) { + XtFree((obj->ruby.candlist + i)->data); + } + } + + XtFree((char *)obj->ruby.candlist); + } + + /* Ruby 用終了処理をここに書く */ + + deleteObject(obj); +} + +static Boolean +SetValues(cur, req, wid, args, num_args) +Widget cur; +Widget req; +Widget wid; +ArgList args; +Cardinal *num_args; +/* ARGSUSED */ +{ + RubyObject old = (RubyObject)cur; + RubyObject new = (RubyObject)wid; + + return False; +} + +static void +fix(obj) +RubyObject obj; +{ + /* 確定の処理 */ + XtCallCallbackList((Widget)obj, obj->inputConv.fixcallback, + (XtPointer)NULL); + ruby_eval("kanjiConv.fix_end"); +} + +static void +convend(obj) +RubyObject obj; +{ + XtCallCallbackList((Widget)obj, obj->inputConv.endcallback, + (XtPointer)NULL); + ruby_eval("kanjiConv.reset"); +} + +/* + * keeping list of objects + */ +typedef struct _oblist_ { + RubyObject obj; + struct _oblist_ *next; +} ObjRec; + +static ObjRec *ObjList = NULL; + +static void +addObject(obj) +RubyObject obj; +{ + ObjRec *objp = XtNew(ObjRec); + + objp->obj = obj; + objp->next = ObjList; + ObjList = objp; +} + +static void +deleteObject(obj) +RubyObject obj; +{ + ObjRec *objp, *objp0; + + for (objp0 = NULL, objp = ObjList; + objp != NULL; + objp0 = objp, objp = objp->next) { + if (objp->obj == obj) { + if (objp0 == NULL) { + ObjList = objp->next; + } else { + objp0->next = objp->next; + } + XtFree((char *)objp); + return; + } + } +} + +/* ARGSUSED */ +static int +GetTriggerKeys(w, keys_return) +Widget w; +ICTriggerKey **keys_return; +{ + /* 何をする関数なのか不明 (komatsu) */ + + *keys_return = NULL; + return 0; +} + +/* ARGSUSED */ + + +/* + * int ICGetPreeditString(Widget object, int segn, int offset, + * Atom *encoding, int *format, + * int *length, XtPointer *string) + * 変換途中の segn 番目の セグメントの offset 文字からのテキストを + * string に返す + * encoding には、テキストのエンコーディングを指定しておく + * ただしこれは単なるリクエストであって、変換オブジェクトは + * 別のエンコーディングで返してもよい + * encoding には実際のエンコーディングが返される + * 変換オブジェクトは少なくとも COMPOUND_TEXT エンコーディングは + * サポートしなくてはならない + * format には 8/16/32 のいずれか、length は string のエレメント数が + * それぞれ返される + * テキストの領域は malloc されているのでこの関数を呼んだ側で + * free しなければならない + * 変換テキストがない時やエラーの場合には -1、そうでなければ 0 が + * 関数の値として返される + */ +/* まだ, 未検討 (komatsu) */ +static int +PreeditString(w, segn, offset, encoding, format, length, string) +Widget w; +int segn; +int offset; +Atom *encoding; +int *format; +int *length; +XtPointer *string; +{ + RubyObject obj = (RubyObject)w; + + return -1; +} + +/* ARGSUSED */ +static int +StatusString(w, encoding, format, length, string, nchars) +Widget w; +Atom *encoding; +int *format; +int *length; +XtPointer *string; +int *nchars; +{ + ICString *seg; + wchar *wbuf, *wp; + int len, wlen; + extern int convJWStoCT(); + + printf("StatusString\n"); + + seg = GetMode(w); + if (seg == NULL) { + *length = *nchars = 0; + return -1; + } + + wlen = seg->nchars; + if (wlen <= 0) { + *length = *nchars = 0; + return -1; + } + + /* + * data に入っている変換テキストは null ターミネートされていないかも + * しれないので、まずコピーして null ターミネートする + */ + wbuf = (wchar *)XtMalloc((wlen + 1) * sizeof(wchar)); + (void)bcopy(seg->data, (char *)wbuf, sizeof(wchar) * wlen); + wbuf[wlen] = 0; + + /* + * Ruby オブジェクトは COMPOUND_TEXT エンコーディングしかサポートしない + * COMPOUND_TEXT に変換する + */ + *encoding = XA_COMPOUND_TEXT(XtDisplayOfObject(w)); + *format = 8; + + /* COMPOUND_TEXT は \r が送れないので \n に変換しておく */ + for (wp = wbuf; *wp != 0; wp++) { + if (*wp == '\r') *wp = '\n'; + } + + *length = len = convJWStoCT(wbuf, (unsigned char *)NULL, 0); + *string = XtMalloc(len + 1); + (void)convJWStoCT(wbuf, (unsigned char *)*string, 0); + *nchars = seg->nchars; + + /* wbuf を free しておく */ + XtFree((char *)wbuf); + + return 0; +} + +/*** +ic_str->nbytes が 0 の場合 ic_str->data は自動的に確保 (XtMalloc) される. + 0 以外の場合 ic_str->data は (XtRealloc) される. + */ +static void +rubyEUCtoICString(ruby_str, ic_str) +VALUE ruby_str; +ICString *ic_str; +{ + unsigned char *euc_str; + int euc_len; + wchar *wc_str; + +/* printf("String_Len: %d\n", RSTRING(ruby_str)->len); */ + + euc_str = STR2CSTR(ruby_str); + euc_len = strlen(euc_str); + + if (ic_str->nbytes == 0) { + wc_str = (wchar *)XtMalloc((euc_len + 1) * sizeof(wchar)); + } else { + wc_str = (wchar *)XtRealloc(ic_str->data, (euc_len + 1) * sizeof(wchar)); + } + euc2wcs(euc_str, euc_len, wc_str); + + ic_str->data = (char *)wc_str; + ic_str->nchars = wstrlen(wc_str); + ic_str->nbytes = (euc_len + 1) * sizeof(wchar); + ic_str->attr = ICAttrNotConverted; +} + +static void +rubyEUCArraytoICStringArray(ruby_str_ary, ic_str_ary) +VALUE ruby_str_ary; +ICStringArray *ic_str_ary; +{ + VALUE ruby_str; + int i, array_length; + ICString ic_str; + + array_length = RARRAY(ruby_str_ary)->len; + if ((ic_str_ary->length) < array_length) { + ic_str_ary->array = (ICString *)XtRealloc((char *)ic_str_ary->array, + array_length * sizeof(ICString)); + for (i = ic_str_ary->length; i < array_length; i++) { +/* ic_str_ary->array[i] = (ICString *)XtMalloc(1 * sizeof(ICString)); */ + ic_str_ary->array[i].nbytes = 0; + } + } + ic_str_ary->length = array_length; + +/* printf("array_length: %d\n", array_length); */ + + for (i = 0; i < array_length; i++) { + rubyEUCtoICString(rb_ary_entry(ruby_str_ary, i), &(ic_str_ary->array[i])); + } +} diff -r 89750191b165 -r 598fcbe482b5 lib/Ruby.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/Ruby.rb Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,444 @@ +$LOAD_PATH.push(ENV['KINPUT2_RUBY']) + +$KCODE = 'e' +require "jcode" +require "kconv" +require 'suikyo/suikyo' + +class TextEdit + attr_reader :cursor + def initialize (text = "", cursor = 0) + set (text, cursor) + end + + def set (data, cursor = 0) + @data = data + @cursor = cursor + end + + def text + return @data + end + + def reset + set ("", 0) + end + + def insert (string) + @data = @data[0,@cursor] + string + @data[@cursor..-1] + @cursor += string.length; + end + + def delete + if (@cursor < @data.length) then + @data = @data[0,@cursor] + @data[(@cursor + 1)..-1] + end + end + + def backspace + if (@cursor > 0) then + @data = @data[0,(@cursor - 1)] + @data[@cursor..-1] + @cursor -= 1 + end + end + + def cursor_left + if (@cursor > 0) then + @cursor -= 1 + end + end + + def cursor_right + if (@cursor < @data.length) then + @cursor += 1 + end + end + + def cursor_beginning + @cursor = 0 + end + + def cursor_end + @cursor = @data.length + end + + def segments + # [text before the cursor, text on the cursor, text after the cursor] + return [@data[0,@cursor], @data[@cursor,1], @data[(@cursor + 1)..-1]] + end +end + +class JTextEdit < TextEdit + def initialize (text = "", cursor = 0) + super + @suikyo = Suikyo.new + @suikyo.table.loadfile("romaji-kana") + end + + def text + if @cursor == @data.length then + return @suikyo.convert (@data) + else + return super + end + end + + def segments + if @cursor == @data.length then + return [@suikyo.convert (@data), '', ''] + else + return super + end + end +end + +class Window + attr_reader :call_open, :call_close, :visible + + def initialize (parent) + @parent = parent + @visible = false + end + + def open + @call_open = true unless @visible + end + def open_end + @call_open = false + @visible = true + end + + def close + @call_close = true if @visible + end + def close_end + @call_close = false + @visible = false + end +end + +class Dialog < Window + def text + @parent.cand_list.join(" ") + end +end + +class Selection < Window + attr_reader :call_right, :call_left, :call_line_beginning, :call_line_end, + :call_up, :call_down + + def right + @call_right = true + end + def right_end + @call_right = false + end + + def left + @call_left = true + end + def left_end + @call_left = false + end + + def line_beginning + @call_line_beginning = true + end + def line_beginning_end + @call_line_beginning = false + end + + def line_end + @call_line_end = true + end + def line_end_end + @call_line_end = false + end + + def up + @call_up = true + end + def up_end + @call_up = false + end + + def down + @call_down = true + end + def down_end + @call_down = false + end +end + +class KeyMap + @@keysym = { + :enter => 65293, + :space => 32, + :tab => 65289, + :delete => 65535, + :insert => 65379, + :home => 65360, + :end => 65367, + :page_up => 65365, + :page_down => 65366, + :esc => 65307, + :f1 => 65470, + :f2 => 65471, + :f3 => 65472, + :f4 => 65473, + :f5 => 65474, + :f6 => 65475, + :f7 => 65476, + :f8 => 65477, + :f9 => 65478, + :f10 => 65479, + :f11 => 65480, + :f12 => 65481, + :backspace => 65288, + :muhenkan => 65314, + :henkan => 65315, + :hankaku_zenkaku => 65322, + :katakana_hiragana => 65319, + :up => 65362, + :down => 65364, + :right => 65363, + :left => 65361, + :ctrl_l => 65507, + :ctrl_r => 65508, + :alt_l => 65513, + :alt_r => 65514, + :shift_l => 65505, + :shift_r => 65506, + } + +# @@enter = [13, 65293, 0] +# @@ctrl_a = [1, 97, 4]; @@alt_a = [97, 97, 8] +# @@ctrl_b = [2, 98, 4]; @@alt_b = [98, 98, 8] +# @@ctrl_c = [3, 99, 4]; @@alt_c = [99, 99, 8] +# @@ctrl_d = [4, 100, 4]; @@alt_d = [100, 100, 8] +# @@ctrl_e = [5, 101, 4]; @@alt_e = [101, 101, 8] +# @@ctrl_f = [6, 102, 4]; @@alt_f = [102, 102, 8] +# @@ctrl_g = [7, 103, 4]; @@alt_g = [103, 103, 8] +# @@ctrl_h = [8, 104, 4]; @@alt_h = [104, 104, 8] +# @@ctrl_i = [9, 105, 4]; @@alt_i = [105, 105, 8] +# @@ctrl_j = [10, 106, 4]; @@alt_j = [106, 106, 8] +# @@ctrl_k = [11, 107, 4]; @@alt_k = [107, 107, 8] +# @@ctrl_l = [12, 108, 4]; @@alt_l = [108, 108, 8] +# @@ctrl_m = [13, 109, 4]; @@alt_m = [109, 109, 8] +# @@ctrl_n = [14, 110, 4]; @@alt_n = [110, 110, 8] +# @@ctrl_o = [15, 111, 4]; @@alt_o = [111, 111, 8] +# @@ctrl_p = [16, 112, 4]; @@alt_p = [112, 112, 8] +# @@ctrl_q = [17, 113, 4]; @@alt_q = [113, 113, 8] +# @@ctrl_r = [18, 114, 4]; @@alt_r = [114, 114, 8] +# @@ctrl_s = [19, 115, 4]; @@alt_s = [115, 115, 8] +# @@ctrl_t = [20, 116, 4]; @@alt_t = [116, 116, 8] +# @@ctrl_u = [21, 117, 4]; @@alt_u = [117, 117, 8] +# @@ctrl_v = [22, 118, 4]; @@alt_v = [118, 118, 8] +# @@ctrl_w = [23, 119, 4]; @@alt_w = [119, 119, 8] +# @@ctrl_x = [24, 120, 4]; @@alt_x = [120, 120, 8] +# @@ctrl_y = [25, 121, 4]; @@alt_y = [121, 121, 8] +# @@ctrl_z = [26, 122, 4]; @@alt_z = [122, 122, 8] + + @@modifier = { :shift => 1, :ctrl => 4, :alt => 8 } + + def initialize + @keymap = Hash.new + end + + def key (stroke) + modifiers = 0 + if stroke.kind_of?(Array) then + main_key = stroke[0] + stroke[1..-1].each {|modifier| + modifiers |= + (modifier.kind_of?(Symbol) ? @@modifier[modifier] : modifier) + } + else + main_key = stroke + end + if main_key.kind_of?(Symbol) then + main_key = @@keysym[main_key] + end + return [main_key, modifiers] + end + + def ignore_shift (key) + (main_key, modifiers) = key + return [main_key, (modifiers & ~@@modifier[:shift])] + end + + def add (stroke, command) + @keymap[key(stroke)] = command + end + + def del (stroke) + @keymap.delete(key(stroke)) + end + + def command (stroke) + return @keymap[key(stroke)] || @keymap[ignore_shift(key(stroke))] + end +end + + +class ModeCore + attr_accessor :trap + attr_reader :label, :keymap + def initialize (parent) + @parent = parent + @label = "" + @keymap = KeyMap.new + initialize_keys + @trap = true + end + + def on (prev_mode = nil) + end + + def off (next_mode = nil) + end + + def entries + return [] + end + + def call (char, keysym, modifiers) + command = @keymap.command([keysym, modifiers]) + if command then + return send(command, keysym, modifiers) + else + return @trap + end + end +end + +class ModeMaster + attr_reader :current_name + + def initialize (parent, mode = :fund) + @parent = parent + @mode = Hash.new + @current_name = nil + end + + def set (name, mode) + @mode[name] = mode + unless @current then + @current_name = name + end + end + + def current + return @mode[@current_name] + end + + def change (name) + if @mode.key?(name) then + @current_name = name + current.on + return true + else + return false + end + end + + def label (name = @current_name) + if name then + mode = @mode[name] + else + mode = current + end + + if mode then + return mode.label.toeuc + else + return "NOMODE" + end + end +end + +class KanjiConvCore + attr_reader :cand_list, :cand_index, + :value_fixed, :call_fix, :mode + + def initialize + @textEdit = TextEdit.new + @mode = ModeMaster.new (self) + clear + end + + def reset + clear + end + + def clear + @cand_list = [] + @cand_index = 0 + + @call_fix = false + @value_fixed = "" + end + + ## inputEvent (keynum, keysym = nil, state = nil) + ## ReturnValue 1:Pass 0:Trap + def inputEvent (keynum, keysym = nil, state = nil) + return 1 + end + + def fix (fixed_arg) + # fixed_arg is a string or an index number of cand_list. + @call_fix = true + if fixed_arg.kind_of?(Integer) then + word = @cand_list[fixed_arg] + else + word = fixed_arg + end + @value_fixed = word + end + def fix_end + @call_fix = false + @value_fixed = "" + end + + def modeline + return @mode.label + end + + def set_cand_list (list, index = nil) + if (list.is_a?(Array) && list.length > 0) then + @cand_list = list.map {|cand| cand.toeuc} + @cand_index = index if index + return true + else + reset_cand_list + return false + end + end + def set_cand_index (index) + puts "<> #{index}" + @cand_index = index + end + def reset_cand_list + @cand_list = [] + @cand_index = 0 + end + + def segment_length + segments = (@mode.current.entries - ['']) + return segments.length + end + def segment_word (n) + segments = (@mode.current.entries - ['']) + return segments[n] + end + def segment_status (n) + segments = @mode.current.entries + offset = 0 + if segments[0] == "" then + offset += 1 + end + return ((n + offset) % 3 == 1) ? :highlight : :normal + end +end + +require 'Prime' diff -r 89750191b165 -r 598fcbe482b5 lib/Xrubylib/Imakefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/Xrubylib/Imakefile Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,14 @@ +#include "../../Kinput2.conf" + + SRCS = \ + misc.c + + OBJS = $(SRCS:%.c=%.o) + +INCLUDES = -I../../include -I$(RUBYSRC) + + DEFINES = + +NormalLibraryObjectRule() +NormalLibraryTarget(Xrubylib,$(OBJS)) +DependTarget() diff -r 89750191b165 -r 598fcbe482b5 lib/Xrubylib/callbacks.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/Xrubylib/callbacks.txt Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,134 @@ +:342: + /* $B%F%-%9%H$NJQ2=$r%A%'%C%/$9$k(B */ + if (obj->ruby.textchanged) { + XtCallCallbackList(w, obj->inputConv.textchangecallback, + (XtPointer)NULL); + obj->ruby.textchanged = False; + } + +:351: + /* $BF~NO%b!<%I$r%A%'%C%/$9$k(B */ + if (ks->info & KanjiModeInfo) { + XtCallCallbackList(w, obj->inputConv.modechangecallback, + (XtPointer)NULL); + } + +:357: + if (ks->info & KanjiGLineInfo) { /* $B0lMw9T$,$"$k>l9g(B */ + ICAuxControlArg arg; + + switch (obj->ruby.ibuf->candstat) { + case RUBY_GLINE_Start: + arg.command = ICAuxStart; + XtCallCallbackList((Widget)obj, obj->inputConv.auxcallback, + (XtPointer)&arg); + break; + case RUBY_GLINE_End: + arg.command = ICAuxEnd; + XtCallCallbackList((Widget)obj, obj->inputConv.auxcallback, + (XtPointer)&arg); + break; + case RUBY_GLINE_Change: + arg.command = ICAuxChange; + XtCallCallbackList((Widget)obj, obj->inputConv.auxcallback, + (XtPointer)&arg); + break; + } + } + +:831: + /* $B3NDj$N=hM}(B */ + XtCallCallbackList((Widget)obj, obj->inputConv.fixcallback, + (XtPointer)NULL); /* $B!)!)!)(B */ + +:837: +static void +convend(obj) +RubyObject obj; +{ + XtCallCallbackList((Widget)obj, obj->inputConv.endcallback, + (XtPointer)NULL); +} + +:1442: +static void +moveSelection(obj, dir) +RubyObject obj; +int dir; +{ + ICSelectionControlArg arg; + + arg.command = ICSelectionMove; + arg.u.dir = dir; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); +} + +:1466: +static void +endSelection(obj, abort) +RubyObject obj; +int abort; +{ + ICSelectionControlArg arg; + int selected; + + if (ignoreListfunc) return; /* SelectItem $B$G=hM}$5$l$k$N$G$3$3$OITMW(B */ + arg.command = ICSelectionEnd; + arg.u.current_item = -1; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); + + if (!abort && (selected = arg.u.current_item) >= 0) { + insertSelection(obj, selected); + } +} + +:1486: +static void +querySelection(obj) +RubyObject obj; +{ + ICSelectionControlArg arg; + int selected; + + if (ignoreListfunc) return; /* SelectItem $B$G=hM}$5$l$k$N$G$3$3$OITMW(B */ + arg.command = ICSelectionGet; + arg.u.current_item = -1; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); + + if ((selected = arg.u.current_item) >= 0) { + insertSelection(obj, selected); + } +} + +:1505: +static void +openSelection(obj, func, curitem) +RubyObject obj; +int func; /* $B0lHV>e$r8+$h(B */ +int curitem; +{ + ICSelectionControlArg arg; + static int current = 0; + static int doit = 0; + + if (func == SELECTION_SET) { + current = curitem; + doit = 1; + } + else if (func == SELECTION_DO && doit) { + doit = 0; + arg.command = ICSelectionStart; + arg.u.selection_kind = ICSelectionCandidates; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); + + /* set current item */ + arg.command = ICSelectionSet; + arg.u.current_item = current; + XtCallCallbackList((Widget)obj, obj->inputConv.selectioncallback, + (XtPointer)&arg); + } +} diff -r 89750191b165 -r 598fcbe482b5 lib/Xrubylib/memo.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/Xrubylib/memo.txt Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,14 @@ +copyInWchar $B$N(B wssize $B$H(B wslen $B$NN>J}$,$"$k$3$H$,M}2r$7$,$?$$(B. + wssize $B$O(B byte $B?t$G$O$J$/$F(B, $B$?$@$N(B wslen + 1. + +ICString: Kinput2 $B$G$NJ8;zNs$N%U%)!<%^%C%H(B + VALUE(Ruby $B$NJ8;zNs(B) $B$r(B ICString $B$KJQ49$9$k4X?t$H(B + VALUE(Ruby $B$NJ8;zNs(B) $B$N%j%9%H$r(B ICString $B$N%j%9%H$KJQ49$9$k4X?t$,I,MW(B. + + ICString.data $BMQ$N%a%b%j4IM}$,$d$C$+$$$@(B. + GetSegment $BMQ(B + candList $BMQ(B + +The way to negotiate about current selection between Ruby and upper widget(s). + + cur_addr is used. (curcand is not used?) diff -r 89750191b165 -r 598fcbe482b5 lib/Xrubylib/misc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/Xrubylib/misc.c Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,143 @@ +/* + * Copyright 1999 Justsystem Corporation, Japan. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Justsystem Corporation + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. Justsystem + * Corporation makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * Author: Atsushi Irisawa + */ + +#ifndef lint +static char rcsid[] = "$Id: misc.c,v 1.2 2003/06/10 02:11:27 komatsu Exp $" ; +#endif /* !lint */ +#include "WStr.h" + +/* Page */ +/* + * [$B4X?tL>(B] + * wcs2euc( ) + * [$BI=Bj(B] + * WCHAR $B7?$+$i(BEUC$BJ8;zNs$X$NJQ49(B + * [$B8F=P7A<0(B] + * int wcs2euc( wchar *wbuf, int wlen, unsigned char *euc ) + * + * [$B0z?t(B] + * $B7?(B : $BL>(B $B>N(B : I O : $B@b(B $BL@(B + * wchar : *wbuf : i : WCHAR $B7?J8;zNs(B + * int : wlen : i : wchar $B7?J8;zNs$ND9$5(B + * unsigned char : *euc : o : EUC $BJ8;zNs3JG> 8 ; + if ( c ) { + *euc++ = c ; + n++ ; + } + else if (( *wbuf & 0xff ) & 0x80 ) { + *euc++ = 0x8e ; + n++ ; + } + *euc++ = *wbuf & 0xff ; + wbuf++ ; + n++ ; + } + *euc = 0 ; + + return n ; +} +/* Page */ +/* + * [$B4X?tL>(B] + * euc2wcs( ) + * [$BI=Bj(B] + * EUC$BJ8;zNs$+$i(B wchar $B7?J8;zNs$X$NJQ49(B + * [$B8F=P7A<0(B] + * int euc2wcs( unsigned char *euc, int elen, wchar *wbuf ) + * + * [$B0z?t(B] + * $B7?(B : $BL>(B $B>N(B : I O : $B@b(B $BL@(B + * unsigned char : *euc : i : EUC $BJ8;zNs(B + * int : elen : i : EUC $BJ8;zNs$ND9$5(B + * wchar : *wbuf : o : wchar $B7?J8;zNs3JGo$K#1(B + * + * [$B;HMQ4X?t(B] + * $B$J$7(B + * [$B5!G=(B] + * unsigined char $B7?$N(BEUC $BJ8;zNs$r(Bwchar $B7?$KJQ49$9$k!#(B + * EUC $BJ8;zNs$K$O!"(B0x8f $B$NFCJL$J%3!<%I$,4^$^$l$F$$$k$N$G(B + * wchar $B$KJQ49$9$k;~$K8DJL=hM}$r$9$k!#(B + */ +int euc2wcs(euc, elen, wbuf) +unsigned char *euc; +int elen; +wchar *wbuf; +{ + int lb = 0, hb = 0 ; + int i ; + int n = 0 ; + int isSkip ; + + for( i = 0 ; i < elen ; i++ ) { + isSkip = 0 ; + if ( *euc == 0x8e ) { + euc++ ; + hb = *euc ; + lb = 0 ; + i++ ; + } + else if ( *euc & 0x80 ) { + if ( *euc == 0x8f ) { + isSkip=1 ; + } + else { + lb = *euc ; + euc++ ; + hb = *euc ; + i++ ; + } + } + else { + hb = *euc ; + lb = 0 ; + } + euc++ ; + if ( !isSkip ) { + *wbuf = (( lb << 8 ) | hb ) & 0xffff ; + wbuf++ ; + n++ ; + } + } + + *wbuf = 0 ; + return n ; +} +/* End of misc.c */ diff -r 89750191b165 -r 598fcbe482b5 lib/imlib/imxport.c --- a/lib/imlib/imxport.c Mon Mar 08 20:38:16 2010 +0900 +++ b/lib/imlib/imxport.c Mon Mar 08 20:38:17 2010 +0900 @@ -37,6 +37,9 @@ #include #endif +#ifdef DEBUG +#include +#endif extern int errno; /* diff -r 89750191b165 -r 598fcbe482b5 lib/ruby-c.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/ruby-c.c Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,65 @@ +/* $Id: ruby-c.c,v 1.2 2003/06/10 02:11:25 komatsu Exp $ */ +/* + * AUTHOR: Hiroyuki Komatsu http://taiyaki.org/ + * LICENSE: GPL2 + */ + +#include +#include "ruby-c.h" +#define RUBY_EVALF_BUF 1024 + +VALUE +ruby_eval (char *statement) +{ + int state; + VALUE result; + + result = rb_eval_string_protect (statement, &state); + if (state) { + EXTERN VALUE ruby_errinfo; + + fprintf(stderr, "Eval Error in \"%s\"\n", statement); + fprintf(stderr, "%s\n", STR2CSTR(ruby_errinfo)); + } + return result; +} + +VALUE +ruby_evalf (char *statement_format, ...) +{ + va_list ap; + char statement[RUBY_EVALF_BUF]; + int length; + + va_start (ap, statement_format); + length = vsnprintf (statement, RUBY_EVALF_BUF, statement_format, ap); + va_end (ap); + + if (length == -1) { /* Before glibc 2.0.6 */ + fprintf (stderr, "ruby_evalf: Error, Out of Buffer\n"); + fprintf (stderr, "Buffer size is %d\n", RUBY_EVALF_BUF); + return Qnil; + } else if (length > RUBY_EVALF_BUF -1) { /* C99 */ + VALUE result; + char *d_statement = malloc (sizeof (char) * length + 1); + va_start (ap, statement_format); + vsnprintf (d_statement, length + 1, statement_format, ap); + va_end (ap); + result = ruby_eval (d_statement); + free (d_statement); + return result; + } else { + return ruby_eval (statement); + } +} + +void +ruby_load (char *filename) +{ + int state; + rb_load_protect (rb_str_new2 (filename), 0, &state); + if (state) { + fprintf(stderr, "Load Error for \"%s\"\n", filename); + fprintf(stderr, "%s\n", STR2CSTR(ruby_errinfo)); + } +} diff -r 89750191b165 -r 598fcbe482b5 lib/ruby-c.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/ruby-c.h Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,12 @@ +#ifndef _RUBY_C_H_ +#define _RUBY_C_H_ + +#include +void +ruby_load (char *filename); +VALUE +ruby_eval (char *statement); +VALUE +ruby_evalf (char *statement_format, ...); + +#endif diff -r 89750191b165 -r 598fcbe482b5 lib/ruby/Imakefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/ruby/Imakefile Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,14 @@ +#include "../../Kinput2.conf" + + RUBY_FILES = kinput2.rb kinput2_default.rb kinput2_prime.rb + +all:: +depend:: +clean:: + +#ifdef UseRuby +MakeDirectories(install,$(RUBYDIR)) +InstallMultiple($(RUBY_FILES),$(RUBYDIR)) +#else +install:: +#endif diff -r 89750191b165 -r 598fcbe482b5 lib/ruby/kinput2.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/ruby/kinput2.rb Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,465 @@ +$KCODE = 'e' +require "jcode" +require "kconv" +require 'suikyo/suikyo' + +module Debug + attr_accessor :debug_mode + def debug_message (message, output = nil) + if Debug::debug_mode?(output) || @debug_mode then + puts "#{self.class}[#{self.id}]: #{message}" + end + end + + def Debug::message (message, output = nil) + if Debug::debug_mode?(output) then + puts message + end + end + + def Debug::debug_mode? (output = nil) + return (ENV['RUBY_DEBUG'] || $DEBUG || output) + end +end + +class TextEdit + include Debug + + attr_reader :cursor + def initialize (text = "", cursor = 0) + @debug_mode = false + set (text, cursor) + end + + def set (data, cursor = 0) + @data = data + @cursor = cursor + end + + def text + return @data + end + + def reset + set ("", 0) + end + + def insert (string) + @data = @data[0,@cursor] + string + @data[@cursor..-1] + @cursor += string.length; + end + + def delete + if (@cursor < @data.length) then + @data = @data[0,@cursor] + @data[(@cursor + 1)..-1] + end + end + + def backspace + if (@cursor > 0) then + @data = @data[0,(@cursor - 1)] + @data[@cursor..-1] + @cursor -= 1 + end + end + + def cursor_left + if (@cursor > 0) then + @cursor -= 1 + end + end + + def cursor_right + if (@cursor < @data.length) then + @cursor += 1 + end + end + + def cursor_beginning + @cursor = 0 + end + + def cursor_end + @cursor = @data.length + end + + def segments + # [text before the cursor, text on the cursor, text after the cursor] + return [@data[0,@cursor], @data[@cursor,1], @data[(@cursor + 1)..-1]] + end +end + +class JTextEdit < TextEdit + def initialize (text = "", cursor = 0) + super + @suikyo = Suikyo.new + @suikyo.table.loadfile("romaji-kana") + end + + def text + if @cursor == @data.length then + return @suikyo.convert (@data) + else + return super + end + end + + def segments + if @cursor == @data.length then + return [@suikyo.convert (@data), '', ''] + else + return super + end + end +end + +class Window + attr_reader :call_open, :call_close, :visible + + def initialize (parent) + @parent = parent + @visible = false + end + + def open + @call_open = true unless @visible + end + def open_end + @call_open = false + @visible = true + end + + def close + @call_close = true if @visible + end + def close_end + @call_close = false + @visible = false + end +end + +class Dialog < Window + def text + @parent.cand_list.join(" ") + end +end + +class Selection < Window + attr_reader :call_right, :call_left, :call_line_beginning, :call_line_end, + :call_up, :call_down + + def right + @call_right = true + end + def right_end + @call_right = false + end + + def left + @call_left = true + end + def left_end + @call_left = false + end + + def line_beginning + @call_line_beginning = true + end + def line_beginning_end + @call_line_beginning = false + end + + def line_end + @call_line_end = true + end + def line_end_end + @call_line_end = false + end + + def up + @call_up = true + end + def up_end + @call_up = false + end + + def down + @call_down = true + end + def down_end + @call_down = false + end +end + +class KeyMap + @@keysym = { + :enter => 65293, + :space => 32, + :tab => 65289, + :delete => 65535, + :insert => 65379, + :home => 65360, + :end => 65367, + :page_up => 65365, + :page_down => 65366, + :esc => 65307, + :f1 => 65470, + :f2 => 65471, + :f3 => 65472, + :f4 => 65473, + :f5 => 65474, + :f6 => 65475, + :f7 => 65476, + :f8 => 65477, + :f9 => 65478, + :f10 => 65479, + :f11 => 65480, + :f12 => 65481, + :backspace => 65288, + :muhenkan => 65314, + :henkan => 65315, + :hankaku_zenkaku => 65322, + :katakana_hiragana => 65319, + :up => 65362, + :down => 65364, + :right => 65363, + :left => 65361, + :ctrl_l => 65507, + :ctrl_r => 65508, + :alt_l => 65513, + :alt_r => 65514, + :shift_l => 65505, + :shift_r => 65506, + } + +# @@enter = [13, 65293, 0] +# @@ctrl_a = [1, 97, 4]; @@alt_a = [97, 97, 8] +# @@ctrl_b = [2, 98, 4]; @@alt_b = [98, 98, 8] +# @@ctrl_c = [3, 99, 4]; @@alt_c = [99, 99, 8] +# @@ctrl_d = [4, 100, 4]; @@alt_d = [100, 100, 8] +# @@ctrl_e = [5, 101, 4]; @@alt_e = [101, 101, 8] +# @@ctrl_f = [6, 102, 4]; @@alt_f = [102, 102, 8] +# @@ctrl_g = [7, 103, 4]; @@alt_g = [103, 103, 8] +# @@ctrl_h = [8, 104, 4]; @@alt_h = [104, 104, 8] +# @@ctrl_i = [9, 105, 4]; @@alt_i = [105, 105, 8] +# @@ctrl_j = [10, 106, 4]; @@alt_j = [106, 106, 8] +# @@ctrl_k = [11, 107, 4]; @@alt_k = [107, 107, 8] +# @@ctrl_l = [12, 108, 4]; @@alt_l = [108, 108, 8] +# @@ctrl_m = [13, 109, 4]; @@alt_m = [109, 109, 8] +# @@ctrl_n = [14, 110, 4]; @@alt_n = [110, 110, 8] +# @@ctrl_o = [15, 111, 4]; @@alt_o = [111, 111, 8] +# @@ctrl_p = [16, 112, 4]; @@alt_p = [112, 112, 8] +# @@ctrl_q = [17, 113, 4]; @@alt_q = [113, 113, 8] +# @@ctrl_r = [18, 114, 4]; @@alt_r = [114, 114, 8] +# @@ctrl_s = [19, 115, 4]; @@alt_s = [115, 115, 8] +# @@ctrl_t = [20, 116, 4]; @@alt_t = [116, 116, 8] +# @@ctrl_u = [21, 117, 4]; @@alt_u = [117, 117, 8] +# @@ctrl_v = [22, 118, 4]; @@alt_v = [118, 118, 8] +# @@ctrl_w = [23, 119, 4]; @@alt_w = [119, 119, 8] +# @@ctrl_x = [24, 120, 4]; @@alt_x = [120, 120, 8] +# @@ctrl_y = [25, 121, 4]; @@alt_y = [121, 121, 8] +# @@ctrl_z = [26, 122, 4]; @@alt_z = [122, 122, 8] + + @@modifier = { :shift => 1, :ctrl => 4, :alt => 8 } + + def initialize + @keymap = Hash.new + end + + def key (stroke) + modifiers = 0 + if stroke.kind_of?(Array) then + main_key = stroke[0] + stroke[1..-1].each {|modifier| + modifiers |= + (modifier.kind_of?(Symbol) ? @@modifier[modifier] : modifier) + } + else + main_key = stroke + end + if main_key.kind_of?(Symbol) then + main_key = @@keysym[main_key] + end + return [main_key, modifiers] + end + + def ignore_shift (key) + (main_key, modifiers) = key + return [main_key, (modifiers & ~@@modifier[:shift])] + end + + def add (stroke, command) + @keymap[key(stroke)] = command + end + + def del (stroke) + @keymap.delete(key(stroke)) + end + + def command (stroke) + return @keymap[key(stroke)] || @keymap[ignore_shift(key(stroke))] + end +end + + +class ModeCore + attr_accessor :trap + attr_reader :label, :keymap + def initialize (parent) + @parent = parent + @label = "" + @keymap = KeyMap.new + initialize_keys + @trap = true + end + + def on (prev_mode = nil) + end + + def off (next_mode = nil) + end + + def entries + return [] + end + + def call (char, keysym, modifiers) + command = @keymap.command([keysym, modifiers]) + if command then + return send(command, keysym, modifiers) + else + return @trap + end + end +end + +class ModeMaster + attr_reader :current_name + + def initialize (parent, mode = :fund) + @parent = parent + @mode = Hash.new + @current_name = nil + end + + def set (name, mode) + @mode[name] = mode + unless @current then + @current_name = name + end + end + + def current + return @mode[@current_name] + end + + def change (name) + if @mode.key?(name) then + @current_name = name + current.on + return true + else + return false + end + end + + def label (name = @current_name) + if name then + mode = @mode[name] + else + mode = current + end + + if mode then + return mode.label.toeuc + else + return "NOMODE" + end + end +end + +class KanjiConvCore + include Debug + attr_reader :cand_list, :cand_index, + :value_fixed, :call_fix, :mode + + def initialize + @debug_mode = false + + @textEdit = TextEdit.new + @mode = ModeMaster.new (self) + clear + end + + def reset + clear + end + + def clear + @cand_list = [] + @cand_index = 0 + + @call_fix = false + @value_fixed = "" + end + + ## inputEvent (keynum, keysym = nil, state = nil) + ## ReturnValue 1:Pass 0:Trap + def inputEvent (keynum, keysym = nil, state = nil) + return 1 + end + + def fix (fixed_arg) + # fixed_arg is a string or an index number of cand_list. + @call_fix = true + if fixed_arg.kind_of?(Integer) then + word = @cand_list[fixed_arg] + else + word = fixed_arg + end + @value_fixed = word + end + def fix_end + @call_fix = false + @value_fixed = "" + end + + def modeline + return @mode.label + end + + def set_cand_list (list, index = nil) + if (list.is_a?(Array) && list.length > 0) then + @cand_list = list.map {|cand| cand.toeuc} + @cand_index = index if index + return true + else + reset_cand_list + return false + end + end + def set_cand_index (index) + debug_message("<> #{index}") + @cand_index = index + end + def reset_cand_list + @cand_list = [] + @cand_index = 0 + end + + def segment_length + segments = (@mode.current.entries - ['']) + return segments.length + end + def segment_word (n) + segments = (@mode.current.entries - ['']) + return segments[n] + end + def segment_status (n) + segments = @mode.current.entries + offset = 0 + if segments[0] == "" then + offset += 1 + end + return ((n + offset) % 3 == 1) ? :highlight : :normal + end +end diff -r 89750191b165 -r 598fcbe482b5 lib/ruby/kinput2_default.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/ruby/kinput2_default.rb Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,287 @@ +require 'kinput2' + +class KanjiConv < KanjiConvCore + attr_reader :input, :selection, :dialog + + def initialize + super + @input = JTextEdit.new + + @selection = Selection.new (self) + @dialog = Dialog.new (self) + @mode = ModeMaster.new (self) + + @fundMode = FundMode.new(self) + @inputMode = InputMode.new(self) + @convMode = ConvMode.new(self) + @mode.set(:fund, @fundMode) + @mode.set(:input, @inputMode) + @mode.set(:conv, @convMode) + @mode.change(:fund) + + debug_message("Initialize Done.") + end + + def reset + super + @mode.change(:fund) + @input.reset + reset_cand_list + end + + def convert (word) + cand_list = [word, word.upcase] + return cand_list + end + + ## inputEvent (keynum, keysym = nil, state = nil) + ## ReturnValue 1:Pass 0:Trap + def inputEvent (keynum, keysym = nil, state = nil) + debug_message("KeyNum: #{keynum}, KeySym: #{keysym}, Status: #{state}") + + if keynum == 0 then + return 1 + end + key = [keynum] + + if @mode.current then + trap = @mode.current.call (keynum, keysym, state) + return ((trap == true) ? 0 : 1) + end + return 1; + end + + def selection_fix (index) + fix (index) + @mode.change(:fund) + end + + def fix (fixed_arg) + ### Must NOT chage @mode here, because exceptional case can exist. + super (fixed_arg) + @input.reset + reset_cand_list + end + + def insert (keysym, modifiers) + debug_message("insert '#{keysym.chr}'") + @input.insert(keysym.chr) + set_cand_list (convert(@input.text), 0) + end +end + +class PrimeModeCore < ModeCore + def initialize (parent) + super + end + + private + def insert (keysym, modifiers) + @parent.insert(keysym, modifiers) + @parent.mode.change(:input) + return true + end + + def fix (keysym, modifiers) + fix_internal(keysym, modifiers) + @parent.mode.change(:fund) + return true + end + + def fix_and_insert (keysym, modifiers) + fix_internal (keysym, modifiers) + insert (keysym, modifiers) + return true + end + + def cursor_right (keysym, modifiers) + @parent.input.cursor_right + return true + end + def cursor_left (keysym, modifiers) + @parent.input.cursor_left + return true + end + def cursor_beginning (keysym, modifiers) + @parent.input.cursor_beginning + return true + end + def cursor_end (keysym, modifiers) + @parent.input.cursor_end + return true + end + + def selection_right (keysym, modifiers) + @parent.selection.right + return true + end + def selection_left (keysym, modifiers) + @parent.selection.left + return true + end + def selection_beginning (keysym, modifiers) + @parent.selection.line_beginning + return true + end + def selection_end (keysym, modifiers) + @parent.selection.line_end + return true + end + def selection_up (keysym, modifiers) + @parent.selection.up + return true + end + def selection_down (keysym, modifiers) + @parent.selection.down + return true + end +end + +class FundMode < PrimeModeCore + def initialize (parent) + super + @label = '[ $B$"(B ]' + @trap = false + end + + def initialize_keys + (33..126).each {|char| + @keymap.add(char, :insert) + } + end + + def on (prev_mode = nil) + @parent.selection.close + end +end + +class InputMode < PrimeModeCore + def initialize (parent) + super + @label = "[$BF~NO(B]" + end + + def initialize_keys + (33..126).each {|char| + @keymap.add(char, :insert) + } + (?A..?Z).each {|char| + @keymap.add(char, :fix_and_insert) + } + @keymap.add(:enter, :fix) + @keymap.add([?m, :ctrl], :fix) + @keymap.add(:space, :convert) + @keymap.add(:backspace, :backspace) + @keymap.add([?h, :ctrl], :backspace) + @keymap.add(:delete, :delete) + @keymap.add([?d, :ctrl], :delete) + @keymap.add(:left, :cursor_left) + @keymap.add([?b, :ctrl], :cursor_left) + @keymap.add(:right, :cursor_right) + @keymap.add([?f, :ctrl], :cursor_right) + @keymap.add([?a, :ctrl], :cursor_beginning) + @keymap.add([?e, :ctrl], :cursor_end) + @keymap.add([?g, :ctrl], :cancel) + @keymap.add(:esc, :cancel) + end + + def on (prev_mode = nil) + @parent.selection.close + end + + def entries + return @parent.input.segments + end + + private + def fix_internal (keysym, modifiers) + @parent.fix(@parent.input.text) + end + + def backspace (keysym, modifiers) + @parent.input.backspace + if @parent.input.text.length == 0 then + @parent.mode.change(:fund) + end + return true + end + + def delete (keysym, modifiers) + @parent.input.delete + if @parent.input.text.length == 0 then + @parent.mode.change(:fund) + end + return true + end + + def cancel (keysym, modifiers) + @parent.input.reset + @parent.mode.change(:fund) + return true + end + + def convert (keysym, modifiers) + if @parent.set_cand_list (@parent.convert(@parent.input.text)) then + @parent.set_cand_index(0) + @parent.mode.change(:conv) + end + return true + end +end + +class ConvMode < PrimeModeCore + def initialize (parent) + super + @label = "[$BJQ49(B]" + end + + def initialize_keys + (33..126).each {|char| + @keymap.add(char, :fix_and_insert) + } + @keymap.add(:enter, :fix) + @keymap.add([?m, :ctrl], :fix) + @keymap.add(:space, :convert) +# @keymap.add(:backspace, :backspace) +# @keymap.add([?h, :ctrl], :backspace) +# @keymap.add(:delete, :delete) +# @keymap.add([?d, :ctrl], :delete) + @keymap.add(:left, :selection_left) + @keymap.add([?b, :ctrl], :selection_left) + @keymap.add(:right, :selection_right) + @keymap.add([?f, :ctrl], :selection_right) + @keymap.add(:down, :selection_down) + @keymap.add([?n, :ctrl], :selection_down) + @keymap.add(:up, :selection_up) + @keymap.add([?p, :ctrl], :selection_up) + @keymap.add([?a, :ctrl], :selection_beginning) + @keymap.add([?e, :ctrl], :selection_end) + @keymap.add([?g, :ctrl], :cancel) + @keymap.add(:esc, :cancel) + end + + def on (prev_mode = nil) + @parent.selection.open + end + + def entries + return ['', @parent.cand_list[@parent.cand_index]] + end + + private + def fix_internal (keysym, modifiers) + @parent.fix(@parent.cand_list[@parent.cand_index]) + end + + def cancel (keysym, modifiers) + @parent.mode.change(:input) + return true + end + + def convert (keysym, modifiers) + return selection_right(keysym, modifiers) + end +end + +$kanjiConv = KanjiConv.new +#p local_variables diff -r 89750191b165 -r 598fcbe482b5 lib/ruby/kinput2_prime.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/ruby/kinput2_prime.rb Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,307 @@ +# $LOAD_PATH.push ('/home/komatsu/src/prime/prime-xim/lib/ruby/') + +# PRIME_USER_DIR = ENV['HOME'] + '/.prime' +# PRIME_PATH = '/home/komatsu/src/prime' +# $LOAD_PATH.push (PRIME_PATH) + +require 'kinput2' +require 'prime/prime' + +class KanjiConv < KanjiConvCore + attr_reader :input, :selection, :dialog + + def initialize + super +# @useprime = false + @useprime = true + + if @useprime then + @prime = Prime.new + end + @input = JTextEdit.new + + @selection = Selection.new (self) + @dialog = Dialog.new (self) + @mode = ModeMaster.new (self) + + @fundMode = FundMode.new(self) + @inputMode = InputMode.new(self) + @convMode = ConvMode.new(self) + @mode.set(:fund, @fundMode) + @mode.set(:input, @inputMode) + @mode.set(:conv, @convMode) + @mode.change(:fund) + + debug_message("Initialize Done.") + end + + def reset + super + @mode.change(:fund) + @input.reset + reset_cand_list + end + + def convert (word) + if @useprime then + cand_list = @prime.lookup_hybrid(word).values + else + cand_list = [word, "Taiyaki", "Hiroyuki", "Komatsu", "$B4A;z(B"] + end + return cand_list[0,5] + end + + ## inputEvent (keynum, keysym = nil, state = nil) + ## ReturnValue 1:Pass 0:Trap + def inputEvent (keynum, keysym = nil, state = nil) + debug_message("KeyNum: #{keynum}, KeySym: #{keysym}, Status: #{state}") + + if keynum == 0 then + return 1 + end + key = [keynum] + + if @mode.current then + trap = @mode.current.call (keynum, keysym, state) + return ((trap == true) ? 0 : 1) + end + return 1; + end + + def selection_fix (index) + fix (index) + @mode.change(:fund) + end + + def fix (fixed_arg) + ### Must NOT chage @mode here, because exceptional case can exist. + super (fixed_arg) + @input.reset + reset_cand_list + end + + def insert (keysym, modifiers) + debug_message("insert '#{keysym.chr}'") + @input.insert(keysym.chr) + set_cand_list (convert(@input.text), 0) + end +end + +class PrimeModeCore < ModeCore + def initialize (parent) + super + end + + private + def insert (keysym, modifiers) + @parent.insert(keysym, modifiers) + @parent.mode.change(:input) + return true + end + + def fix (keysym, modifiers) + fix_internal(keysym, modifiers) + @parent.mode.change(:fund) + return true + end + + def fix_and_insert (keysym, modifiers) + fix_internal (keysym, modifiers) + insert (keysym, modifiers) + return true + end + + def cursor_right (keysym, modifiers) + @parent.input.cursor_right + return true + end + def cursor_left (keysym, modifiers) + @parent.input.cursor_left + return true + end + def cursor_beginning (keysym, modifiers) + @parent.input.cursor_beginning + return true + end + def cursor_end (keysym, modifiers) + @parent.input.cursor_end + return true + end + + def selection_right (keysym, modifiers) + @parent.selection.right + return true + end + def selection_left (keysym, modifiers) + @parent.selection.left + return true + end + def selection_beginning (keysym, modifiers) + @parent.selection.line_beginning + return true + end + def selection_end (keysym, modifiers) + @parent.selection.line_end + return true + end + def selection_up (keysym, modifiers) + @parent.selection.up + return true + end + def selection_down (keysym, modifiers) + @parent.selection.down + return true + end +end + +class FundMode < PrimeModeCore + def initialize (parent) + super + @label = '[ $B$"(B ]' + @trap = false + end + + def initialize_keys + (33..126).each {|char| + @keymap.add(char, :insert) + } + end + + def on (prev_mode = nil) + @parent.selection.close + @parent.dialog.close + end +end + +class InputMode < PrimeModeCore + def initialize (parent) + super + @label = "[$BF~NO(B]" + end + + def initialize_keys + (33..126).each {|char| + @keymap.add(char, :insert) + } + (?A..?Z).each {|char| + @keymap.add(char, :fix_and_insert) + } + @keymap.add(:enter, :fix) + @keymap.add([?m, :ctrl], :fix) + @keymap.add(:space, :convert) + @keymap.add(:backspace, :backspace) + @keymap.add([?h, :ctrl], :backspace) + @keymap.add(:delete, :delete) + @keymap.add([?d, :ctrl], :delete) + @keymap.add(:left, :cursor_left) + @keymap.add([?b, :ctrl], :cursor_left) + @keymap.add(:right, :cursor_right) + @keymap.add([?f, :ctrl], :cursor_right) + @keymap.add([?a, :ctrl], :cursor_beginning) + @keymap.add([?e, :ctrl], :cursor_end) + @keymap.add([?g, :ctrl], :cancel) + @keymap.add(:esc, :cancel) + end + + def on (prev_mode = nil) + @parent.selection.close + @parent.dialog.open + end + + def entries + return @parent.input.segments + end + + private + def fix_internal (keysym, modifiers) + @parent.fix(@parent.input.text) + end + + def backspace (keysym, modifiers) + @parent.input.backspace + if @parent.input.text.length == 0 then + @parent.mode.change(:fund) + end + return true + end + + def delete (keysym, modifiers) + @parent.input.delete + if @parent.input.text.length == 0 then + @parent.mode.change(:fund) + end + return true + end + + def cancel (keysym, modifiers) + @parent.input.reset + @parent.mode.change(:fund) + return true + end + + def convert (keysym, modifiers) + if @parent.set_cand_list (@parent.convert(@parent.input.text)) then + @parent.set_cand_index(0) + @parent.mode.change(:conv) + end + return true + end +end + +class ConvMode < PrimeModeCore + def initialize (parent) + super + @label = "[$BJQ49(B]" + end + + def initialize_keys + (33..126).each {|char| + @keymap.add(char, :fix_and_insert) + } + @keymap.add(:enter, :fix) + @keymap.add([?m, :ctrl], :fix) + @keymap.add(:space, :convert) +# @keymap.add(:backspace, :backspace) +# @keymap.add([?h, :ctrl], :backspace) +# @keymap.add(:delete, :delete) +# @keymap.add([?d, :ctrl], :delete) + @keymap.add(:left, :selection_left) + @keymap.add([?b, :ctrl], :selection_left) + @keymap.add(:right, :selection_right) + @keymap.add([?f, :ctrl], :selection_right) + @keymap.add(:down, :selection_down) + @keymap.add([?n, :ctrl], :selection_down) + @keymap.add(:up, :selection_up) + @keymap.add([?p, :ctrl], :selection_up) + @keymap.add([?a, :ctrl], :selection_beginning) + @keymap.add([?e, :ctrl], :selection_end) + @keymap.add([?g, :ctrl], :cancel) + @keymap.add(:esc, :cancel) + end + + def on (prev_mode = nil) + @parent.selection.open + @parent.dialog.close + end + + def entries + return ['', @parent.cand_list[@parent.cand_index]] + end + + private + def fix_internal (keysym, modifiers) + @parent.fix(@parent.cand_list[@parent.cand_index]) + end + + def cancel (keysym, modifiers) + @parent.mode.change(:input) + return true + end + + def convert (keysym, modifiers) + return selection_right(keysym, modifiers) + end +end + +$kanjiConv = KanjiConv.new +#p local_variables diff -r 89750191b165 -r 598fcbe482b5 lib/ruby/test/testPrime.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/ruby/test/testPrime.rb Mon Mar 08 20:38:17 2010 +0900 @@ -0,0 +1,13 @@ +require '/home/komatsu/src/prime/prime-xim/lib/Ruby.rb' + +kanjiConv = KanjiConv.new +p kanjiConv.mode.current_name +puts kanjiConv.modeline +kanjiConv.inputEvent (97, 97, 0) +p kanjiConv.mode.current_name +puts kanjiConv.modeline +kanjiConv.inputEvent (97, 97, 0) +p kanjiConv.mode.current_name +puts kanjiConv.modeline +p kanjiConv.segment_length +p kanjiConv.segment_status(0)