diff lib/cconv.c @ 0:92745d501b9a

initial import from kinput2-v3.1
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Mon, 08 Mar 2010 04:44:30 +0900
parents
children 983aff0dcf18
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/cconv.c	Mon Mar 08 04:44:30 2010 +0900
@@ -0,0 +1,2777 @@
+/*
+ *	cconv.c -- $BF~NOJ8;zJQ49%i%$%V%i%j(B (for X11)
+ *		ver 10.8
+ */
+
+/*
+ * Copyright (C) 1988  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
+ *		ishisone@sra.co.jp
+ */
+
+/*
+ * $B35MW(B
+ *
+ * $BF~NOJ8;zJQ49$O!"$+$J4A;zJQ49$NA0CJ3,$G$"$j!"$=$NL\E*$O%-!<%\!<%I$+$i(B
+ * $BF~NO$5$l$?%-!<%3!<%I$r2r<a$9$k$3$H$G$"$k!#(B
+ * $B=>$C$F!"Bg$-$/J,$1$k$H<!$N(B2$B$D$N5!G=$r;}$D$3$H$K$J$k!#(B
+ *
+ * 1. $B%m!<%^;z$+$JJQ49$J$IF~NO$5$l$?J8;z$rJL$NJ8;z$KJQ$($k5!G=(B
+ * 2. $B%-!<$NF~NO$K$h$j!"$+$J4A;zJQ49$G;H$o$l$k!VJQ49!W!"!V3NDj!W$J$I$N(B
+ *    $B3F<o5!G=$r8F$S=P$95!G=(B
+ *
+ * $B$3$N(B cconv $B%i%$%V%i%j$O(B X Window version 11 $B$N$b$H$G;H$o$l$k$3$H$r(B
+ * $BA[Dj$7$F$$$k!#(B
+ */
+
+/*
+ * $B%a%b(B
+ *
+ * version 6.0	88/06/05
+ *	$B$@$$$?$$$G$-$?(B
+ * version 6.1	88/06/06
+ *	$B%3%a%s%HF~$l(B
+ * version 6.2	88/06/07
+ *	$B$3$l$@$1F~$l$l$P%^%K%e%"%k=q$+$J$/$F$bBg>fIW$@$m$&(B
+ * version 6.4	88/09/05
+ *	$B2CF#;a(B@$BEl9)Bg$N0U8+$K$h$j(B redo $B5!G=$rF~$l$k(B
+ *	$B$D$$$G$K(B static function $B$N@k8@$r$D$1$k(B
+ *	$B$$$/$D$+$N4X?t$r(B external $B$+$i(B static $B$KJQ$($k(B
+ * version 6.5	88/09/07
+ *	function $B$,J#?t=q$1$k$h$&$K$7$?(B
+ *	$B$=$N$?$a%G!<%?9=B$$rJQ99$9$k(B
+ * version 6.6	88/10/07
+ *	$B$J$s$H(B readRuleFile() $B$G%*!<%W%s$7$?%U%!%$%k$r(B
+ *	$BJD$8$k$N$rK:$l$F$$$?(B -- $B$"!<$O$:$+$7$$(B
+ *	$B=>$C$F(B wterm $B$G2?2s$b(B KanjiConvert $B$N(B on/off $B$r7+$jJV$9$H(B
+ *	$B=i4|2=$K<:GT$9$k(B
+ * version 6.7	88/12/19
+ *	wstrlen() $B$O$3$N%i%$%V%i%j$GDj5A$9$k$Y$-$b$N$G$O$J$$$N$G30$9(B
+ * version 6.8	89/07/21
+ *	$B1F;3;a(B@$B>>2<EE4o$+$i%-!<%3!<%II=5-$,$&$^$/F0$+$J$$$H$NO"Mm$r<u$1$k(B
+ *	getKey() $B$G(B XKEY $BI=5-$N>l9g!"(B#0x$B#1#6?J?t(B $B$NFI$_$H$j$K%P%0$,(B
+ *	$B$"$k$3$H$,H=L@(B
+ * version 7.0	89/08/16
+ *	jclib $B$N(B Wnn version4 $BBP1~$K$h$j!"JQ49%P%C%U%!$,J#?t;}$F$k$h$&$K(B
+ *	$B$J$C$?(B
+ *	$B$=$l$K9g$o$;$F!"(Bcconv $B$b%P%C%U%!$,J#?t;}$F$k$h$&$K$7$J$1$l$P(B
+ *	$B$J$i$J$$(B
+ *	$B7k6IH>J,0J>e=q$-49$($F$7$^$C$?$h$&$@(B
+ * version 7.1	89/08/17
+ *	$B%P%0%U%#%C%/%9(B
+ *	$B%b!<%IJQ99DLCNMQ$N%3!<%k%P%C%/$rDI2C$9$k(B
+ * version 7.2	89/08/23
+ *	$B%U%!%s%/%7%g%s%F!<%V%k$O!"$d$O$j(B ccParseRule() $B$G$O$J$/!"(B
+ *	ccCreateBuf() $B$G;XDj$9$k$Y$-$b$N$J$N$G!"$=$N$h$&$KJQ99$9$k(B
+ * version 7.3 89/08/25
+ *	lint $B$G7Y9p$,=P$J$$$h$&$K=$@5(B
+ *	dumpAllRules() $B$G$A$c$s$HJQ49%k!<%k$,%@%s%W$5$l$k$h$&$K=$@5(B
+ * version 7.4 89/08/26
+ *	ccParseRule() $B$G!"JQ49Dj5A%U%!%$%k$,A0$HF1$8$G$"$l$P(B
+ *	$B%k!<%k$r6&MQ$9$k$h$&$KJQ99(B
+ *	ccParseRule/ccFreeRule $B$G$N(B memory leak $B$N=$@5(B
+ * version 7.5 89/09/26
+ *	$BJQ49Dj5A%U%!%$%k$G(B include $B$,;H$($k$h$&$K=$@5(B
+ * version 7.6 89/09/27
+ *	include $B$N@bL@$r=q$/$N$rK:$l$F$$$?$N$G$=$l$rDI2C(B
+ * version 7.7 89/10/26
+ *	getKey() $B$G(B #$B?t;z(B $B7?$NI=5-$r$7$?;~$K$^$@%P%0$,$"$C$?$N$G=$@5(B
+ *	$B$=$b$=$b$3$NJ}<0$NI=5-$G$O%^%9%/$,;XDj$G$-$J$$$H$$$&:,K\E*$J(B
+ *	$BLdBj$,$"$k$,!"$^$"$3$l$O$$$$$3$H$K$7$F!#(B
+ * version 8.0 89/10/27
+ *	R4 contrib $B8~$1$N(B Release $B$K$"$?$C$F%P!<%8%g%sHV9f$r=$@5(B
+ * version 8.1 89/12/25
+ *	include $B%U%!%$%k$,$J$+$C$?;~$K%3%"%@%s%W$9$k%P%0$r=$@5(B
+ * version 8.2 90/02/15
+ *	X11R4 keyboard group support $BDI2C(B
+ * version 8.3 90/02/16
+ *	keyboard group support $B$N7k2L!"Nc$($P(B
+ *		"" shift-Right "" foo
+ *		"" Right       "" bar
+ *	$B$H$$$&%k!<%k$,$"$C$?;~!"(Bshift-Right $B$r2!$7$?$K$b$+$+$o$i$:(B
+ *	$B$7$?$N%k!<%k$K%^%C%A$7$F$7$^$&$H$$$&%P%0$r=$@5(B
+ *	$BDj5A%U%!%$%k(B (include $B%U%!%$%k$b4^$`(B) $B$N%5!<%A%Q%9$H$7$F(B
+ *	$B4D6-JQ?t(B CC_DEF_PATH $B$r;H$&$h$&$K=$@5(B
+ * version 8.4 90/04/17
+ *	keyboard group support $B$N%3!<%I$N%1%"%l%9%_%9$r=$@5(B
+ *	$BJQ?tL>(B ks1 $B$H(B ks2 $B$r4V0c$($?(B
+ * version 8.5 90/05/31
+ *	keyboard group support $B$NIT6q9g$r=$@5(B
+ *	$BL1ED;a(B@$B%"%9%F%C%/$+$i$N%l%]!<%H(B
+ * version 8.6 91/03/20
+ *	$B$I$N%k!<%k$K$b%^%C%A$7$J$+$C$?;~$K$O%G%U%)%k%H%"%/%7%g%s$,8F$P$l$k$,!"(B
+ *	$B$3$N=hM}$G(B
+ *		+ $B0z?t$,4V0c$C$F$$$?(B
+ *		+ XLookupString() $B$N%j%?!<%s%P%j%e!<$,(B 0 $B$N$H$-(B ($B$D$^$j(B
+ *		  $B%-!<%$%Y%s%H$KBP1~$9$kJ8;zNs$,$J$+$C$?;~(B) $B$K%G%U%)%k%H(B
+ *		  $B%"%/%7%g%s$,8F$P$l$J$+$C$?(B
+ *	$B$H$$$&LdBj$r=$@5(B
+ *	$B%G%U%)%k%H%"%/%7%g%s$,(B NULL $B$N;~!"$I$N%k!<%k$K$b%^%C%A$7$J$1$l$P(B
+ *	ccConvchar() $B$,(B -1 $B$rJV$9$h$&$K=$@5(B
+ * version 8.7 91/03/25
+ *	$BA0$N%P!<%8%g%s$N=$@5$K$h$j!"C1$K%7%U%H%-!<$d%3%s%H%m!<%k%-!<$r(B
+ *	$B2!$7$?$@$1$G%G%U%)%k%H%"%/%7%g%s$,8F$P$l$k$h$&$K$J$C$?$,!"$3$l$O(B
+ *	$B%f!<%6$N4|BT$9$kF0:n$G$O$J$$$h$&$J5$$,$9$k$N$G!"(BXLookupString() $B$N(B
+ *	$B%j%?!<%s%P%j%e!<$,(B 0 $B$N;~$K$O%G%U%)%k%H%"%/%7%g%s$r8F$P$J$$$h$&$K(B
+ *	$B:F=$@5(B
+ *	$B$^$?!"%G%U%)%k%H%"%/%7%g%s$,(B NULL $B$G$+$D%k!<%k$K%^%C%A$7$J$$;~$K(B
+ *	ccConvchar() $B$,(B -1 $B$rJV$9$h$&$K$7$?$,!"%G%U%)%k%H%"%/%7%g%s$NCM$K(B
+ *	$B$h$C$F%j%?!<%s%P%j%e!<$,JQ$o$k$N$OJQ$@$7!"(B-1 $B$rJV$9$N$O%(%i!<$,(B
+ *	$B5/$3$C$?$_$?$$$J$N$G!"7k6I%G%U%)%k%H%"%/%7%g%s$,(B NULL $B$G$"$k$+(B
+ *	$B$I$&$+$K4X$o$i$:%^%C%A$7$?;~$O(B 1$B!"%^%C%A$7$J$$;~$O(B 0 $B$rJV$9(B
+ *	$B$h$&$K=$@5(B
+ *	$B$3$NJQ99$K$h$j(B ccConvchar() $B$N%j%?!<%s%P%j%e!<$,(B 0 $B$+$I$&$+%A%'%C%/(B
+ *	$B$7$F$$$?%"%W%j%1!<%7%g%s$OF0$+$J$/$J$k$,!":#$^$G(B ccConvchar() $B$N(B
+ *	$B%j%?!<%s%P%j%e!<$ODj5A$7$F$$$J$+$C$?$N$G$3$l$O$=$N%"%W%j%1!<%7%g%s$N(B
+ *	$B@UG$(B
+ * version 9.0 91/08/15
+ *	$BJ8;z$N%G!<%?7?$H$7$F:#$^$G$:$C$H(B wchar_t $B$r;H$C$F$$$?$,!"(Bwchar_t $B$N(B
+ *	$BDj5A$,5!<o$K$h$C$F0[$J$k$?$a!"(Bwchar $B$H$$$&7?$KJQ99$9$k!#K\Ev$O(B
+ *	Wnn $B$N<!4|%P!<%8%g%s$K9g$o$;$?$$$N$G8e$G:F$SJQ99$9$k2DG=@-$,$"$k(B
+ * version 9.1 91/09/18
+ *	Files $B9=B$BN$N(B index $B$H$$$&L>A0$N%U%#!<%k%I$,!"(BSystemV $B7O$N%^%7%s(B
+ *	$B$@$H(B strchr $B$KJQ$o$C$F$7$^$&$N$G(B findex $B$H$$$&L>A0$KJQ99(B
+ * version 9.2 91/09/23
+ *	DEBUG $B$,Dj5A$5$l$F$$$k$HJQ49%k!<%k$,%@%s%W$5$l$F$7$^$&$N$O(B kinput2
+ *	$B$G;HMQ$9$k>l9g:$$k$N$G!"(BDEBUG $B$r(B DEBUG_CCONV $B$KJQ99(B
+ * version 10.0 91/10/01
+ *	R5 contrib $B8~$1$N%j%j!<%9$K$"$?$C$F%P!<%8%g%sHV9f$r=$@5(B
+ * version 10.1 92/06/05
+ *	Display $B9=B$BN$N(B mode_switch $B$r;2>H$7$F$$$?$,!"(BDisplay $B9=B$BN$O(B
+ *	$BK\Mh(B opaque $B$G$"$j!"Cf$N%a%s%P!<$rD>@\%"%/%;%9$9$k$N$O$^$:$$$N$G(B
+ *	mode_switch $B$NCM$r<+J,$G7W;;$9$k$h$&$KJQ99(B
+ * version 10.2 94/04/21
+ *	$B4X?t(B eproc $B$O(B varargs.h/stdarg.h $B$r;H$o$:$K=q$+$l$F$$$?$,!"(B
+ *	$B0\?"@-$KLdBj$,$"$k(B (int $B$H(B long $B$N%5%$%:$,0[$J$k%^%7%s$J$I(B)
+ *	$B$N$G=$@5(B
+ * version 10.3 97/09/17
+ *	$B$J$f$?$5$s(B@$BElBg$K$h$k5!G=3HD%%Q%C%A(B ($B%U%!%s%/%7%g%s%G%#%9%Q%C%A%c$N(B
+ *	$BJV$jCM$G;D$j$N4X?t$N<B9T$r%9%-%C%W$G$-$k(B) $B$N<h$j9~$_(B
+ * version 10.4 97/11/20
+ *	$BF1$8%U%!%$%k$KBP$7$F(B fclose $B$rJ#?t2s8F$s$G$$$F!"(Blibc $B$N<BAu$K(B
+ *	$B$h$C$F$O%3%"%@%s%W$9$k$H$$$&%P%0$r=$@5!#$D$$$G$KDj5A%U%!%$%k$N(B
+ *	$BFI$_9~$_ESCf$G%(%i!<$K$J$C$?;~$K%/%m!<%:$7K:$l$F$$$?$N$G9g$o$;$F(B
+ *	$B=$@5!#(B
+ * version 10.5 98/12/28
+ *	$B$J$f$?$5$s(B@$BElBg$K$h$k$5$i$J$k5!G=3HD%%Q%C%A(B ($B<+F03NDj5!G=(B) $B$N<h$j9~$_(B
+ * version 10.6 99/01/07
+ *	$B%=!<%9$N4A;z%3!<%I$r(B SJIS $B$+$i(B EUC $B$KJQ49!#$?$@$7$3$l$OFbIt$N(B
+ *	$B4IM}>e$NOC$G!"G[I[MQ%=!<%9$O85!9(B JIS $B%3!<%I$K$J$C$F$$$k!#(B
+ * version 10.7 99/04/02
+ *	$B=i4|2=;~$N%(%i!<%A%'%C%/$N6/2=!"$H$$$&$+%P%0=$@5!#JQ49%k!<%kDj5A(B
+ *	$B%U%!%$%k$K%k!<%k$,Dj5A$5$l$F$$$J$+$C$?>l9g(B ($B$D$^$j4V0c$C$FA4A3(B
+ *	$BJL$N%U%!%$%k$rFI$_9~$s$G$7$^$C$?>l9g(B) $B$K%(%i!<$K$9$k!#(B
+ * version 10.8 99/05/07
+ *	$B<+F03NDj5!G=$,!"JQ49%k!<%kDj5A%U%!%$%k$G$N;XDj$K4X$o$i$:(B
+ *	$B>o$K%*%s$K$J$C$F$7$^$&$H$$$&%P%0$r=$@5!#(B
+ */
+
+/*
+ * $B;HMQK!(B
+ *
+ * $B;HMQK!$O3d9g4JC1$G$"$k!#:G=i$KJQ49%k!<%kDj5A%U%!%$%k$rFI$_9~$`$?$a$K(B
+ * ccParseRule() $B$r%3!<%k$9$k!#(B
+ * $B<!$KJQ49%P%C%U%!$r:n$k$?$a$K(B ccCreateBuf() $B$r8F$S!"%P%C%U%!$r:n$k!#(B
+ * $B$3$N;~$K!";HMQ$9$k%k!<%k$d<o!9$N%3!<%k%P%C%/4X?t$r;XDj$9$k!#(B
+ * $BJQ49%k!<%k$HJQ49%P%C%U%!$OJ#?t;}$D$3$H$,$G$-$k!#(B
+ * $B$^$?!"A0$N%P!<%8%g%s$H$N8_49@-$N$?$a$K!"JQ49%k!<%k$NFI$_9~$_$H(B
+ * $BJQ49%P%C%U%!$N:n@.$rF1;~$K9T$J$&!"(BccInit() $B$H$$$&4X?t$bMQ0U$5$l$F$$$k!#(B
+ *
+ * $B$"$H$O%-!<%W%l%9$N%$%Y%s%H$,Mh$?$i(B ccConvchar() $B$r8F$V$@$1$G$"$k!#(B
+ * $B$3$N%U%!%s%/%7%g%s$,JQ49$r9T$J$$!"E,Ev$J%3!<%k%P%C%/%k!<%A%s$r8F$V!#(B
+ *
+ * $B8e$OI,MW$K1~$8$FMQ0U$5$l$F$$$k$=$NB>$N%U%!%s%/%7%g%s$r8F$Y$P$h$$!#(B
+ */
+
+/*
+ * $BJQ49$N;EAH$_(B
+ *
+ * $B$3$NF~NOJ8;zJQ49$N;EAH$_$rM}2r$9$k$?$a$N%-!<%o!<%I$O<!$N(B3$B$D$G$"$k!#(B
+ *	$B!&%b!<%I(B
+ *	$B!&JQ49%k!<%k(B
+ *	$B!&%3%s%F%-%9%H(B
+ *
+ * $B!&%b!<%I(B
+ *	$BF~NOJ8;zJQ49$K$O!V%b!<%I!W$,$"$k!#$3$l$ONc$($P!"(B
+ *	$B!V%m!<%^;z2>L>JQ49$r$7$F$+$J$rF~NO$9$k%b!<%I!W$H$+(B
+ *	$B!V%"%k%U%!%Y%C%H$rF~NO$9$k%b!<%I!W$H$$$C$?$b$N$G$"$k!#(B
+ *	$B%b!<%I$4$H$K0[$J$kJQ49%k!<%k$,@_Dj$G$-$k!#EvA3%b!<%I$N@ZBX$($b(B
+ *	$BJQ49%k!<%k$H$7$F5-=R$G$-$k!#(B
+ * 
+ * $B!&JQ49%k!<%k(B
+ *	$BJQ49%k!<%k$O(B4$B$D$N9`L\$+$i9=@.$5$l$k!#(B
+ *		$BF~NO%-!<(B
+ *		$B%3%s%F%-%9%HJ8;zNs(B
+ *		$BJQ497k2LJ8;zNs(B
+ *		$B%U%!%s%/%7%g%s(B
+ *	$B$3$N$&$A!"F~NO%-!<$H%3%s%F%-%9%HJ8;zNs$,%k!<%k$N%^%C%A%s%0$K;H$o$l$k!#(B
+ * 
+ *	$BF~NO%-!<$O%-!<%3!<%I$r;XDj$9$k$b$N$G!"(BX $B$N%-!<%$%Y%s%H%3!<%I$G(B
+ *	$B;XDj$9$kJ}K!$H!"$=$l$r(B XLookupString $B$7$?7k2L$N%-%c%i%/%?%3!<%I$G(B
+ *	$B;XDj$9$kJ}K!$H$N(B2$BDL$j$,$"$k!#(B
+ *
+ *	$B%3%s%F%-%9%HJ8;zNs$O!"$=$l$^$G$K$I$N$h$&$JJ8;z$,F~NO$5$l$?$+$r(B
+ *	$B;XDj$9$k$b$N$G$"$k!#(B
+ *
+ *	$BJQ497k2LJ8;zNs$O$=$NL>$NDL$j!"JQ497k2L$N;XDj$G!"%^%C%A$7$?(B
+ *	$B%3%s%F%-%9%H$,$3$NJQ497k2L$KCV$-$+$o$k!#(B
+ *
+ *	$B%U%!%s%/%7%g%s$O%k!<%k$,%^%C%A$7$?$H$-$K<B9T$5$l$k%U%!%s%/%7%g%s(B 
+ *	("$BJQ49(B" $B$H$+(B "$B3NDj(B" $B$H$+(B) $B$N;XDj$G$"$k!#%U%!%s%/%7%g%s$OJ#?t(B
+ *	$B;XDj$9$k$3$H$b$G$-$k!#(B
+ * 
+ *	$BNc$r$"$2$k$H!"(B
+ *	$B!V(B"ky" $B$HF~$C$F$$$k$H$3$m$G(B 'a' $B$H$$$&%-!<$,2!$5$l$?$i(B
+ *	"$B$-$c$C(B!" $B$HJQ49$7!"%Y%k$rLD$i$9!W(B
+ *	$B$H$$$&%k!<%k(B ($B$"$s$^$j0UL#$J$$$1$I(B) $B$G!"(B
+ *		'a' $B$,F~NO%-!<!"(B
+ *		"ky" $B$,%3%s%F%-%9%H!"(B
+ *		"$B$-$c$C(B!" $B$,JQ497k2L!"(B
+ *		<$B%Y%k$rLD$i$9(B> $B$,%U%!%s%/%7%g%s(B
+ *	$B$H$$$&$3$H$K$J$k!#(B
+ *
+ * $B!&%3%s%F%-%9%H(B
+ *	$B0J>e$N$h$&$K!"%3%s%F%-%9%H$H$$$&$N$O$=$l$^$G$K$I$N$h$&$JJ8;z$,(B
+ *	$BF~NO$5$l$F$$$J$1$l$P$J$i$J$$$+$r;XDj$9$k$b$N$G$"$k!#(B
+ *	$B$=$l$HF1;~$K$=$NJ8;z$rJQ497k2L$HCV$-JQ$($k$3$H$r;XDj$9$k$b$N(B
+ *	$B$G$b$"$k!#(B
+ *
+ *	$B%3%s%F%-%9%H$O6uJ8;zNs$G$b$h$$!#$=$N$H$-$K$O$=$l$^$G$K$I$N$h$&$J(B
+ *	$BJ8;z$,F~NO$5$l$?$+$K$+$+$o$i$:!"%^%C%A%s%0$,5/$3$k!#(B
+ *
+ *	$B%3%s%F%-%9%H$OH>3Q$N>l9gBgJ8;z>.J8;z$r6hJL$7$J$$!#(B
+ *	$B$I$A$i$K$b%^%C%A$9$k!#$?$@$7!"(Bcasesensitive $B$r;XDj$9$k$3$H$G(B
+ *	$BBgJ8;z>.J8;z$r6hJL$9$k$h$&$K$9$k$3$H$b$G$-$k!#(B
+ *
+ *	autofix $B$r;XDj$9$k$H!"%3%s%F%-%9%H$,$J$$>uBV$G%3%s%F%-%9%H$KJ8(B
+ *	$B;z$,DI2C$5$l$kD>A0$K<+F03NDj%U%!%s%/%7%g%s$,8F$P$l$k!#(B
+ *
+ * $B!&JQ49$N<B:](B
+ *	$B$5$F!"$I$N$h$&$K$7$FJQ49$,9T$J$o$l$k$N$+$r4JC1$K=q$$$F$_$k!#(B
+ *
+ *	$B%-!<%W%l%9%$%Y%s%H$r0z?t$K$7$F(B ccConvchar() $B$,8F$P$l$k!#(B
+ *	$B$9$k$H!"$^$:$O%$%Y%s%H%3!<%I$G%+%l%s%H%b!<%I$GDj5A$5$l$F$$$k(B
+ *	$BJQ49%k!<%k$NCf$+$i%^%C%A$9$k$b$N$rC5$9!#C5:w$O%k!<%k$N5-=R=g$K(B
+ *	$B9T$J$o$l!":G=i$K%^%C%A$7$?$b$N$,A*$P$l$k!#(B
+ *	$B$b$7%^%C%A$9$k%k!<%k$,$J$1$l$P!":#EY$O%$%Y%s%H%3!<%I$r(B
+ *	XLookupString() $B$GJQ49$7$?%-%c%i%/%?%3!<%I$G!"%^%C%A$9$k$b$N$rC5$9!#(B
+ *
+ *	$B$=$l$G$b%^%C%A$9$k%k!<%k$,8+$D$+$i$J$+$C$?$H$-$K$O!"%G%U%)%k%H(B
+ *	$B%"%/%7%g%s$N%3!<%k%P%C%/%k!<%A%s$,8F$P$l$k!#(B
+ *
+ *	$B%^%C%A$9$k%k!<%k$,8+$D$+$l$P!"JQ497k2LJ8;zNs$X$NCV$-49$($r9T$J$&!#(B
+ *	$B$D$^$j!"$^$:%k!<%k$K5-=R$5$l$F$$$k%3%s%F%-%9%HJ8;zNs$NJ8;z?tJ,$@$1(B
+ *	1$BJ8;z:o=|MQ$N%3!<%k%P%C%/%k!<%A%s$,8F$P$l!"$=$N8eJQ497k2LJ8;zNs$,(B
+ *	1$BJ8;zF~NOMQ$N%3!<%k%P%C%/%k!<%A%s$r8F$s$GF~NO$5$l$k!#$=$N:]$K(B
+ *	$B%3%s%F%-%9%H$,6u$G$"$C$?>l9g$O!"<+F03NDjMQ$N%3!<%k%P%C%/%k!<%A%s$,(B
+ *	$B8F$P$l$k!#(B
+ *	$B$=$N%k!<%k$K%U%!%s%/%7%g%s$,;XDj$5$l$F$$$l$P%G%#%9%Q%C%AMQ$N(B
+ *	$B%3!<%k%P%C%/%k!<%A%s$,8F$S=P$5$l$k!#(B
+ *
+ *	$B%U%!%s%/%7%g%s$,B>$N%b!<%I$X$N@ZBX$($@$C$?>l9g$K$O>/$7J#;($G$"$k!#(B
+ *	$B$=$N$H$-$K$O!"$^$:(B EXITMODE $B$H$$$&5?;w%-!<$r0z?t$K$7$F(B ccConvchar()
+ *	$B$,8F$P$l$k!#$3$l$O$"$k%b!<%I$+$iH4$1$k:]$K2?$+=hM}$r$7$?$$!"(B
+ *	$B$H$$$&$H$-$N$?$a$K$"$k!#$=$N8e%+%l%s%H%b!<%I$r?7$7$$%b!<%I$K$7$F!"(B
+ *	$B:#EY$O(B ENTERMODE $B$H$$$&5?;w%-!<$r0z?t$K$7$F(B ccConvchar $B$,8F$P$l$k!#(B
+ *	$B$3$l$K$h$C$F$"$k%b!<%I$KF~$C$?$H$-$N=hM}$r$9$k$3$H$,$G$-$k!#(B
+ *	$B$=$N8e!"%3%s%F%-%9%H$,%/%j%"$5$l!":G8e$K!"%b!<%IJQ99DLCNMQ$N(B
+ *	$B%3!<%k%P%C%/4X?t$,;XDj$5$l$F$$$l$P$=$l$,8F$P$l$k!#(B
+ */
+
+/*
+ * ccdef $B%U%!%$%k$N=q$-J}(B
+ *
+ * $BF~NOJ8;zJQ49Dj5A%U%!%$%k(B (ccdef $B%U%!%$%k$H>JN,$9$k(B) $B$N=q$-J}$r4JC1$K5-$9!#(B
+ *
+ * ccdef $B%U%!%$%k$O<!$N(B3$B$D$N%Q!<%H$+$i9=@.$5$l$k!#(B
+ * $B$3$l$i$O$3$N=g$KJB$s$G$$$J$1$l$P$J$i$J$$!#(B
+ *
+ *	<$B%b!<%I@k8@(B>
+ *	<$B=i4|%b!<%I@k8@(B>
+ *	<$B3F%b!<%I$NJQ49%k!<%k5-=R(B>
+ *
+ * <$B%b!<%I@k8@(B> $B$O;HMQ$9$k%b!<%IL>$r@k8@$9$k$b$N$G!"%U%)!<%^%C%H$O<!$NDL$j!#(B
+ *	defmode Mode1 Mode2 Mode3...
+ * $B;HMQ$9$k%b!<%I$O$9$Y$F$3$3$G@k8@$7$F$*$+$J$/$F$O$J$i$J$$!#(B
+ *
+ * <$B=i4|%b!<%I@k8@(B> $B$O(B cconv $B$,=i4|2=$5$l$?$H$-$N%b!<%I$r;XDj$9$k$b$N$G$"$k!#(B
+ * $B%U%)!<%^%C%H$O<!$NDL$j!#(B
+ *	initialmode Mode3
+ *
+ *
+ * <$B3F%b!<%I$NJQ49%k!<%k5-=R(B> $B$,<B:]$NJQ49%k!<%k$r5-=R$9$kItJ,$G$"$k!#(B
+ * 1$B$D$N%b!<%I$KBP$9$k5-=R7A<0$O<!$NDL$j!#(B
+ *
+ *	mode <$B%b!<%IL>(B> "<$B%W%m%s%W%H(B>" [fallthrough <$B%b!<%IL>(B>]
+ *		"<$B%3%s%F%-%9%H(B>" <$B%-!<(B> "<$BJQ497k2L(B>" [<$B%U%!%s%/%7%g%s(B>...]
+ *			:
+ *			:
+ *	endmode
+ *
+ * <$B%b!<%IL>(B> $B$O(B <$B%b!<%I@k8@(B> $B$G@k8@$7$?%b!<%IL>$G$"$k!#(B
+ *
+ * <$B%W%m%s%W%H(B> $B$O%b!<%I$rI=$9J8;zNs$G$"$k!#$3$l$O%+%l%s%H%b!<%I$rI=<($9$k(B
+ * $B:]$K;HMQ$5$l$k$b$N$G!"4A;z$G$b$h$$!#D9$5$O<+M3$G$"$k$,!"M>$jD9$$$H(B
+ * $B$9$Y$FI=<($5$l$k$+$I$&$+5?Ld$G$"$k!#(B
+ * $B$=$N8e$N!"(B[ ] $B$K$/$k$^$l$?ItJ,$O>JN,2DG=$J$3$H$r<($9!#(B
+ * $B$b$7$"$l$P!"$3$N%b!<%I$G%^%C%A$9$k%k!<%k$,$J$+$C$?$H$-$K$O(B fallthrough $B$G(B
+ * $B;XDj$5$l$k%b!<%I$N%k!<%k$,0z$-B3$$$FC5$5$l$k!#(B
+ *
+ * mode $B$H(B endmode $B$K$O$5$^$l$?ItJ,$,8D!9$NJQ49%k!<%k$G$"$k!#(B
+ * <$B%3%s%F%-%9%H(B> $B$,%3%s%F%-%9%HJ8;zNs$G$"$k!#$3$3$G$O(B '^' $B$H(B '\' $B$,FC<l(B
+ * $B%-%c%i%/%?$H$7$F;HMQ$G$-$k!#(B"^C" $B$H=q$1$P$=$l$O(B $B%3%s%H%m!<%k(B-C $B$rI=$9!#(B
+ * $B%P%C%/%9%i%C%7%e(B '\' $B$O<!$NJ8;z$NFC<lJ8;z$H$7$F$N0UL#$r$J$/$9!#(B
+ * '^' $B<+?H$r;H$$$?$1$l$P(B "\^" $B$H%(%9%1!<%W$9$k!#F1MM$K(B '\' $B<+?H$r;H$$$?$1$l$P(B
+ * "\\" $B$H=E$M$l$P$h$$!#(B
+ *
+ * <$B%-!<(B> $B$OF~NO$5$l$?%-!<$G!"(BX $B$N%-!<%$%Y%s%H!"%-%c%i%/%?%3!<%I!"(B
+ * $B%a%?%-%c%i%/%?!"5?;w%-!<$N$$$:$l$+$G;XDj$9$k!#(B
+ *
+ * X $B$N%-!<%$%Y%s%H$O!"4pK\E*$K!"(B
+ *	$B%b%G%#%U%!%$%"(B-Keysym$BL>(B
+ * $B$GI=$9!#Nc$($P!"(B
+ *	Tab
+ *	control-a
+ *	shift-control-space
+ * $B$J$I$G$"$k!#(B
+ *
+ * $B%-%c%i%/%?%3!<%I$r=q$/$K$O!"%7%s%0%k%/%)!<%H$r;HMQ$9$k!#Nc$($P(B
+ *	'a'
+ *	'^['
+ *	'\''
+ * $B$J$I$G$"$k!#$o$+$k$H;W$&$,!"(B2$BHVL\$O(B ESCAPE$B!"(B3$BHVL\$O%7%s%0%k%/%)!<%H(B
+ * $B$=$N$b$N$r<($9!#(B
+ *
+ * $B%a%?%-%c%i%/%?$O<!$N(B10$B<oN`$,;HMQ$G$-$k!#(B
+ *  $B%-!<%$%Y%s%H$G$b%-%c%i%/%?%3!<%I$G$b%^%C%A$9$k$b$N(B
+ *	@any		- $B2?$K$G$b%^%C%A$9$k(B
+ *  $B%-!<%$%Y%s%H$K%^%C%A$9$k$b$N(B
+ *	@raw		- $B%-!<%$%Y%s%H$J$i2?$K$G$b%^%C%A(B
+ *	@func		- $B%U%!%s%/%7%g%s%-!<$K%^%C%A(B
+ *	@cursor		- $B%+!<%=%k%-!<$K%^%C%A(B
+ *	@keypad		- $B%F%s%-!<%Q%C%I$N%-!<$K%^%C%A(B
+ *	@modifier	- $B%b%G%#%U%!%$%"(B (shift, control $B$J$I(B) $B$K%^%C%A(B
+ *	@non-ascii	- $B%-!<%$%Y%s%H$N$&$A!"(BXLookupString() $B$N7k2L$,(B
+ *			  $BD9$5(B0$B!"$D$^$jBP1~$9$k%"%9%-!<J8;z$,$J$$$b$N$K%^%C%A(B
+ *  $B%-%c%i%/%?%3!<%I$K%^%C%A$9$k$b$N(B
+ *	@ascii		- $B%-%c%i%/%?%3!<%I$J$i2?$K$G$b%^%C%A(B
+ *	@printable	- $B0u;z2DG=J8;z(B (0x20 $B!e(B c $B!e(B 0x7e) $B$K%^%C%A(B
+ *	@control	- $B%3%s%H%m!<%kJ8;z(B (0x00 $B!e(B c $B!e(B 0x1f) $B$K%^%C%A(B
+ *
+ * $B5?;w%-!<$OK\Ev$N%-!<F~NO$G$O$J$$!#$3$l$K$O(B2$B<oN`$"$k!#(B
+ *	ENTERMODE	- $B$"$k%b!<%I$KF~$C$?$H$-$K2>A[E*$KF~NO$5$l$k%-!<(B
+ *	EXITMODE	- $B$"$k%b!<%I$+$iH4$1$k$H$-$K2>A[E*$KF~NO$5$l$k%-!<(B
+ *
+ * <$BJQ497k2L(B> $B$OJQ497k2L$r;XDj$9$k!#$3$3$G$O(B '&'$B!"(B'/'$B!"(B'^'$B!"(B'\' $B$N(B4$B<oN`$N(B
+ * $BFC<lJ8;z$,;HMQ$G$-$k!#(B'^' $B$H(B '\' $B$K$D$$$F$O(B <$B%3%s%F%-%9%H(B> $B$HF1$8$G$"$k!#(B
+ * '&' $B$O(B $B%^%C%A$7$?(B <$B%-!<(B> $B$HCV$-49$($i$l$k!#(B<$B%-!<(B> $B$,%$%Y%s%H$N>l9g$K$O(B
+ * $B$=$N%$%Y%s%H$r(B XLookupString() $B$7$?7k2L$NJ8;zNs$GCV$-49$o$k!#(B
+ * '/' $B$,=P$F$/$k$H!"$=$3$G%3%s%F%-%9%H$O%/%j%"$5$l$k!#(B
+ *
+ * <$B%U%!%s%/%7%g%s(B> $B$O$J$/$F$b$h$$!#$"$l$PJQ49$N8e!"%U%!%s%/%7%g%s$,(B
+ * $B<B9T$5$l$k!#%U%!%s%/%7%g%s$rJ#?t;XDj$9$k$3$H$b$G$-!"$=$N>l9g$K$O(B
+ * $B;XDj$5$l$?=g=x$G<B9T$5$l$k!#%U%!%s%/%7%g%s$N6h@Z$j$O6uGrJ8;z$G$"$k!#(B
+ *	func1 func2 func3
+ * $B$N$h$&$K;XDj$9$k!#(B
+ * $B%U%!%s%/%7%g%s$H$7$F%+%l%s%H%b!<%I$NJQ99$r;XDj$9$k$3$H$b$G$-$k!#(B
+ *	goto <$B%b!<%IL>(B>
+ * $B$G%+%l%s%H%b!<%I$,JQ$o$k!#$3$N%b!<%IL>$H$7$F(B "PREV" $B$,;HMQ$G$-$k!#(B
+ * $B$3$l$O0l$DA0$N%b!<%I$rI=$9!#(B
+ * $B$^$?!":FJQ49$r;XDj$9$k$3$H$b$G$-$k!#(B<$B%U%!%s%/%7%g%s(B>$B$H$7$F(B
+ *	redo
+ * $B$H=q$/$H!"$b$&0lEY%^%C%A$9$k%k!<%k$r:G=i$+$iC5$7$K$$$/!#$?$@$7$=$NA0$K(B
+ * <$B%3%s%F%-%9%H(B> $B$,(B <$BJQ497k2L(B> $B$KCV$-49$($i$l$F$$$k$3$H$KCm0U!#$3$N5!G=$r(B
+ * $B;H$&;~$K$OL58B%k!<%W$K4Y$i$J$$$h$&$KCm0U$7$F%k!<%k$r=q$+$J$1$l$P$J$i$J$$!#(B
+ * $B0l1~0BA4:v$H$7$F(B redo $B$,(B MAXREDO (=20) $B2s8F$P$l$k$H<:GT$9$k$h$&$K(B
+ * $B$J$C$F$$$k!#(B
+ * $BCm0U(B: goto $B$H(B redo $B$N$"$H$K;XDj$5$l$?%U%!%s%/%7%g%s$O<B9T$5$l$J$$!#(B
+ * $B$D$^$j!"(B
+ *	func1 goto XX func2
+ * $B$@$H!":G=i$K(B func1 $B$,<B9T$5$l!"<!$K%+%l%s%H%b!<%I$,(B XX $B$KJQ99$5$l$k$,(B
+ * func2 $B$O<B9T$5$l$J$$!#(B
+ * $B$^$?!"<!$KF~NO$7$?%-!<$K%b%G%#%U%!%$%d$rDI2C$9$k$3$H$b$G$-$k!#(B<$B%U%!(B
+ * $B%s%/%7%g%s(B>$B$H$7$F!"(B
+ *	add-modifier-shift
+ *	add-modifier-control
+ *	add-modifier-lock
+ *	add-modifier-mod1
+ *	add-modifier-mod2
+ *	add-modifier-mod3
+ *	add-modifier-mod4
+ *	add-modifier-mod5
+ * $B$r=q$/$H<!$KF~NO$7$?%-!<$K%b%G%#%U%!%$%d$rDI2C$9$k!#Nc$($P!"(B
+ *	""	'^['		""	add-modifier-mod1
+ *	""	mod1-i		""	shrink-s
+ * $B$H=q$$$F$*$/$H!"(Bmod1-i $B$HF~NO$7$F$b!"(B^[ i $B$HF~NO$7$F$b(B shrink-s $B$,(B
+ * $B<B9T$5$l$k!#(B
+ *
+ * $B:G8e$K=EMW$JCm0U$r0l$D!#(Bccdef $B%U%!%$%k$O(B EUC $B%3!<%I$G=q$+$l$F$$$J$1$l$P(B
+ * $B$J$i$J$$!#(B
+ *
+ * $B$J$*!"=q$-K:$l$?$,(B '#' $B$G;O$^$k9T$O%3%a%s%H9T$G$"$k!#(B
+ *
+ * $B$^$?!"B>$N%U%!%$%k$r(B include $BJ8$r;H$C$F%$%s%/%k!<%I$9$k$3$H$,$G$-$k!#(B
+ * $B=q<0$O(B
+ *	include	$B%U%!%$%kL>(B
+ * $B$G$"$k!#%U%!%$%kL>Cf$K6uGrJ8;z$,4^$^$l$k;~$K$O(B ' $B$+(B " $B$G0O$a$P$h$$!#(B
+ * $B%U%!%$%kL>$,AjBP%Q%9L>$N;~$K$O$^$:%+%l%s%H%G%#%l%/%H%j$,C5$5$l!"$J$1$l$P(B
+ * $B4D6-JQ?t(B CC_DEF_PATH $B$,Dj5A$5$l$F$$$l$P$=$l$K;XDj$5$l$?%G%#%l%/%H%j(B
+ * (':' $B$G6h@Z$C$FJ#?t;XDj$9$k$3$H$,$G$-$k(B) $B$N2<$,C5$5$l!"$=$l$G$b$J$1$l$P(B
+ * CCDEFPATH (/usr/lib/X11/ccdef/) $B$N2<$,C5$5$l$k!#(B
+ */
+
+/*
+ * $B%$%s%?!<%U%'%$%9!&%U%!%s%/%7%g%s(B 
+ *
+ * - $BJQ49%k!<%kFI$_9~$_(B -
+ *
+ * ccRule ccParseRule(char *deffile, void (*errprint)())
+ *	$BF~NOJ8;zJQ49%U%!%$%k$rFI$_9~$`!#(B
+ *	deffile $B$G;XDj$5$l$k%U%!%$%k$+$iJQ49%k!<%k$rFI$_9~$`!#$b$7$b(B
+ *	deffile $B$,(B NULL $B$N;~$O!"4D6-JQ?t(B CC_DEF $B$NCM$,;HMQ$5$l$k!#(B
+ *	deffile $B$,AjBP%Q%9L>$N;~$K$O$^$:%+%l%s%H%G%#%l%/%H%j$N2<$,C5$5$l!"(B
+ *	$B$J$1$l$P!"4D6-JQ?t(B CC_DEF_PATH $B$G;XDj$5$l$?%G%#%l%/%H%j$N2<$,(B
+ *	$BC5$5$l$k!#(BCC_DEF_PATH $B$K$O4D6-JQ?t(B PATH $B$J$I$HF1$8$/J#?t$N(B
+ *	$B%G%#%l%/%H%j$r(B ':' $B$G6h@Z$C$F;XDj$9$k$3$H$,$G$-$k!#(B
+ *	$B$J$1$l$P(B CCDEFPATH (/usr/lib/X11/ccdef) $B$N2<$,C5$5$l$k!#(B
+ *	$BF1$8JQ49%U%!%$%k$KBP$7$FJ#?t2s(B ccParseRule() $B$r9T$J$C$F$b!"(B
+ *	$B<B:]$KFI$_9~$^$l$k$N$O:G=i$N0l2s$@$1$G$"$k!#(B
+ *	errprint $B$O%(%i!<I=<(MQ$N%U%!%s%/%7%g%s$G$"$k$,!"(B NULL $B$N>l9g$K$O(B
+ *	stderr $B$X(B fprintf() $B$r;HMQ$7$F=PNO$5$l$k!#(B
+ *	$B@.8y;~$K$OJQ49%k!<%k$r!"<:GT;~$K$O(B NULL $B$rJV$9!#(B
+ *
+ * void ccFreeRule(ccRule rule)
+ *	$B;HMQ$7$J$/$J$C$?JQ49%k!<%k$G;H$o$l$F$$$?NN0h$r2rJ|$9$k!#(B
+ *
+ *
+ * - $BJQ49%P%C%U%!:n@.(B -
+ *
+ * ccBuf ccCreateBuf(ccRule rule, int contextsize,
+ *		     char *functable[], int functablesize,
+ *		     void (*default_action)(), void (*insert_char)(),
+ *		     void (*delete_char)(), int (*function_dispatch)(),
+ *		     void (*mode_notify)(), void (*auto_fix)(), 
+ *		     caddr_t client_data);
+ *	$BJQ49%P%C%U%!$r:n$j!"$=$l$rJV$9!#(B
+ *	rule $B$G!"$I$NJQ49%k!<%k$r;HMQ$9$k$+;XDj$9$k!#(B
+ *	contextsize $B$K$O%3%s%F%-%9%H$r2?J8;zJ];}$9$k$+$r;XDj$9$k!#(B
+ *	$B$h$[$IFC<l$J%k!<%k$,$J$$8B$j!"IaDL$O?tJ8;z$GB-$j$k$O$:$G$"$k!#(B
+ *	functable $B$O%U%!%s%/%7%g%sL>$N0lMwI=!"(Bfunctablesize $B$O$=$N%5%$%:(B
+ *	$B$G$"$k!#(B
+ *	default_action $B$O!"F~NO$5$l$?%-!<$,$I$N%k!<%k$K$b%^%C%A$7$J$+$C$?(B
+ *	$B$H$-$K8F$P$l$k%U%!%s%/%7%g%s$G$"$k!#(BNULL $B$r;XDj$9$k$H!"%^%C%A(B
+ *	$B$7$J$+$C$?$H$-$K$O2?$b5/$3$i$J$$!#(B
+ *	insert_char, delete_char $B$O$=$l$>$l(B 1$BJ8;zA^F~(B / 1$BJ8;z:o=|MQ$N(B
+ *	$B%U%!%s%/%7%g%s$G$"$k!#(B
+ *	function_dispatch $B$K$O%U%!%s%/%7%g%s%3!<%k$N$?$a$N%G%#%9%Q%C%A(B
+ *	$B%k!<%A%s$r;XDj$9$k!#%G%#%9%Q%C%A4X?t$,(B True $B$rJV$;$P<!$N%U%!%s%/%7%g(B
+ *	$B%s$r8F$V$,!"(BFalse $B$rJV$;$P(B goto $B$N$h$&$KB3$/4X?t$OL5;k$9$k!#(B
+ *	auto_fix $B$O!"<+F03NDj$N$?$a$N%k!<%A%s$r;XDj$9$k!#(BNULL $B$r;XDj$9$k$H(B
+ *	$B<+F03NDj$O$5$l$J$$!#(B
+ *	mode_notify $B$O!"%b!<%I$,JQ$o$C$?;~$K8F$S=P$5$l$k%U%!%s%/%7%g%s$G$"$k!#(B
+ *	$B%3!<%k%P%C%/$NI,MW$,$J$$$H$-$O(B NULL $B$r;XDj$7$F$*$1$P$h$$!#(B
+ *	client_data $B$O!"%3!<%k%P%C%/;~$K0z?t$H$7$FEO$5$l$k%G!<%?$G$"$k!#(B
+ *	$B@.8y;~$K$O%P%C%U%!$r!"%(%i!<$N;~$K$O(B NULL $B$,JV$5$l$k!#(B
+ *
+ *
+ * void ccDestroyBuf(ccBuf buf)
+ *	$B;HMQ$7$J$/$J$C$?JQ49%P%C%U%!$G;H$o$l$F$$$?NN0h$r2rJ|$9$k!#(B
+ *
+ *
+ * - $BJQ49(B -
+ *
+ * int ccConvchar(ccBuf buf, XKeyPressedEvent *event)
+ *	X11 $B$N%-!<%\!<%I$N%W%l%9%$%Y%s%H$r<u$1<h$j!"JQ49$r9T$J$&!#(B
+ *	$B9T$J$C$?7k2L!"J8;z$NA^F~!&:o=|$O(B ccCreateBuf() $B$G;XDj$5$l$?(B
+ *	insert_char, delete_char $B$,8F$S=P$5$l!"%U%!%s%/%7%g%s$K$D$$$F$O(B
+ *	$BF1$8$/(B ccCreateBuf() $B$G;XDj$5$l$k(B function_dispatch $B$,%G%#%9%Q%C%A$N(B
+ *	$B$?$a$K8F$P$l$k!#(B
+ *	$B$I$N%k!<%k$K$b%^%C%A$7$J$1$l$P!"(Bdefault_action $B$,8F$P$l$k!#(B
+ *	$B$I$N%k!<%k$K$b%^%C%A$7$J$+$C$?;~$K$O(B 0$B!"%^%C%A$7$?;~$K$O(B 1 $B$,(B
+ *	$BJV$5$l$k!#(B
+ *
+ *
+ * - $B%+%l%s%H%b!<%I(B -
+ *
+ * int ccGetMode(ccBuf buf)
+ *	$B%+%l%s%H%b!<%IHV9f$,JV$5$l$k!#(B
+ *
+ * wchar *ccGetModePrompt(ccBuf buf)
+ *	$B%+%l%s%H%b!<%IL>$,(B EUC$B%W%m%;%9%3!<%I$GJV$5$l$k!#(B
+ *
+ *
+ * - $B%P%C%U%!$N;HMQ$7$F$$$k%k!<%k(B -
+ *
+ * ccRule ccGetRule(ccBuf buf)
+ *	$B;XDj$5$l$?JQ49%P%C%U%!$,;HMQ$7$F$$$kJQ49%k!<%k$rJV$9!#(B
+ *
+ *
+ * - $B%3%s%F%-%9%H(B -
+ *
+ * $B%3%s%F%-%9%H$X$NJ8;z$NDI2C$d:o=|$O!"%k!<%k$K%^%C%A$7$?$H$-$K$O(B
+ * $B<+F0E*$K9T$J$o$l$k!#$^$?!"%+%l%s%H%b!<%I$NJQ99$K$H$b$J$C$F(B
+ * $B%3%s%F%-%9%H$O<+F0E*$K%/%j%"$5$l$k!#(B
+ * $B=>$C$FIaDL$O%f!<%6$,$3$l$i$N%U%!%s%/%7%g%s$r8F$VI,MW$O$J$$!#(B
+ * $B$?$@$7!"%^%C%A$7$J$+$C$?J8;z$r(B default_action $B$,A^F~$9$k$H$+!"(B
+ * $B%P%C%/%9%Z!<%9$N=hM}$r9T$J$&!"$J$I$N>l9g$K$O%f!<%6$,(B explicit $B$K(B
+ * $B8F$VI,MW$,$"$k!#(B
+ *
+ * void ccContextAppend(ccBuf buf, int c)
+ *	$B%3%s%F%-%9%H$N:G8e$KJ8;z(B c (EUC $B%W%m%;%9%3!<%I(B)$B$rIU$12C$($k!#(B
+ *
+ * void ccContextDelete(ccBuf buf)
+ *	$B%3%s%F%-%9%H$N:G8e$N(B1$BJ8;z$r:o=|$9$k!#(B
+ *
+ * void ccContextClear(ccBuf buf)
+ *	$B%3%s%F%-%9%H$r%/%j%"$9$k!#(B
+ *
+ * void ccContextSet(ccBuf buf, wchar *cstr)
+ *	$B%3%s%F%-%9%HJ8;zNs$r%;%C%H$9$k!#J8;zNs$O(B null $B%?!<%_%M!<%H$5$l$?(B
+ *	EUC $B%W%m%;%9%3!<%I$G$J$1$l$P$J$i$J$$!#(B
+ *	$BJ8;zNs$ND9$5$,(B ccCreateBuf() $B$G;XDj$5$l$?(B contextsize $B$h$j(B
+ *	$BD9$$$H$-$K$O!":G8e$N(B contextsize $BJ8;z$,%;%C%H$5$l$k!#(B
+ *
+ * void ccContextGet(ccBuf buf, wchar *cstr)
+ *	$B8=:_$N%3%s%F%-%9%HJ8;zNs$rJV$9!#J8;zNs$O(B null $B%?!<%_%M!<%H$5$l$?(B
+ *	EUC $B%W%m%;%9%3!<%I$G$"$k!#(B
+ */
+
+/*
+ * $B%3!<%k%P%C%/%U%!%s%/%7%g%s$H$=$N0z?t(B
+ *
+ *	$B%G%#%9%Q%C%A%U%!%s%/%7%g%s(B:
+ *	    function_dispatch(int func, unsigned char *str, int nbytes,
+ *			      caddr_t client_data)
+ *		$B%^%C%A$7$?%k!<%k$K%U%!%s%/%7%g%s$,=q$+$l$F$$$?$H$-$K(B
+ *		$B8F$S=P$5$l$k!#(B
+ *		$B0z?t(B func $B$O!"%U%!%s%/%7%g%sHV9f$G$"$k!#$3$l$O(B
+ *		ccParseRule() $B$N0z?t$H$7$FEO$5$l$?!"(Bfunctable[] $B$N(B
+ *		$B%$%s%G%C%/%9$G$"$k!#(Bstr, nbytes $B$O$3$N(B
+ *		$B%U%!%s%/%7%g%s$r0z$-5/$3$7$?%-!<$NI=$9J8;zNs!#(B
+ *		client_data $B$O(B ccCreateBuf() $B$N;~$K;XDj$5$l$?%G!<%?$G$"$k!#(B
+ *
+ *	$B%G%U%)%k%H%"%/%7%g%sMQ%U%!%s%/%7%g%s(B:
+ *	    default_action(unsigned char *str, int nbytes, caddr_t client_data)
+ *		$B2!$5$l$?%-!<$KBP$7$F%^%C%A$9$k%k!<%k$,$J$+$C$?$H$-$K(B
+ *		$B8F$S=P$5$l$k!#(B
+ *		str, nbytes $B$O%-!<$NI=$9J8;zNs!#(B
+ *		client_data $B$O(B ccCreateBuf() $B$N;~$K;XDj$5$l$?%G!<%?!#(B
+ *
+ *	$BJ8;zA^F~%U%!%s%/%7%g%s(B:
+ *	    insert_char(wchar c, caddr_t client_data)
+ *		$BJQ497k2L$NJ8;z$r%"%W%j%1!<%7%g%s$KEO$9$N$K;HMQ$5$l$k!#(B
+ *		c $B$O(B EUC $B%W%m%;%9%3!<%I$G$"$k!#$3$N%U%!%s%/%7%g%s$O(B
+ *		1$BJ8;z$4$H$K8F$P$l$k!#(B
+ *		client_data $B$O(B ccCreateBuf() $B$N;~$K;XDj$5$l$?%G!<%?!#(B
+ *
+ *	$BJ8;z:o=|%U%!%s%/%7%g%s(B:
+ *	    delete_char(caddr_t client_data)
+ *		$BJQ497k2L$K$7$?$,$C$F:o=|$9$kJ8;z$,$"$l$P$=$NJ8;z?tJ,(B
+ *		$B$3$N%U%!%s%/%7%g%s$,8F$P$l$k!#(B
+ *		client_data $B$O(B ccCreateBuf() $B$N;~$K;XDj$5$l$?%G!<%?!#(B
+ *
+ *	$B<+F03NDj%U%!%s%/%7%g%s(B:
+ *	    auto_fix(caddr_t client_data)
+ *		$B%3%s%F%-%9%H$,$J$$>uBV$G%3%s%F%-%9%H$KJ8;z$,DI2C$5$l$k(B
+ *		$BD>A0$K8F$P$l$k!#(B
+ *		client_data $B$O(B ccCreateBuf() $B$N;~$K;XDj$5$l$?%G!<%?!#(B
+ *
+ *	$B%b!<%IJQ99%U%!%s%/%7%g%s(B:
+ *	    mode_notify(int newmode, int oldmode, caddr_t client_data)
+ *		$B%+%l%s%H%b!<%I$,JQ99$5$l$?;~$K$3$N%U%!%s%/%7%g%s$,(B
+ *		$B8F$P$l$k!#(Bnewmode $B$,?7$7$$%+%l%s%H%b!<%I!"(Boldmode $B$,(B
+ *		$BA0$N%+%l%s%H%b!<%IHV9f$G$"$k!#(B
+ *
+ *	$B%(%i!<I=<(%U%!%s%/%7%g%s(B:
+ *	    error_handler(char *errstr)
+ *		ccParseRule() $BCf$G!"%(%i!<$,H/@8$7$?;~$K8F$S=P$5$l$k!#(B
+ */
+
+#ifndef lint
+static char	*rcsid = "$Id: cconv.c,v 10.10 1999/08/09 03:17:57 ishisone Exp $";
+#endif
+
+#include	<stdio.h>
+#include	<X11/Xlib.h>
+#include	<X11/keysym.h>
+#include	<X11/Xutil.h>
+#include	<X11/Xos.h>
+#include	"cconv.h"
+
+#define uchar	unsigned char
+#define ushort	unsigned short
+#define ulong	unsigned long
+
+#define Malloc(size)		malloc((unsigned int)(size))
+#define Realloc(p, size)	realloc((char *)(p), (unsigned int)(size))
+#define Free(p)			{ if (p) (void)free((char *)(p)); }
+
+#define Strcmp(s1, s2)		strcmp((char *)(s1), (char *)(s2))
+#define Strncmp(s1, s2, n)	strncmp((char *)(s1), (char *)(s2), n)
+#define Strcpy(s1, s2)		strcpy((char *)(s1), (char *)(s2))
+#define Strcat(s1, s2)		strcat((char *)(s1), (char *)(s2))
+#define Strlen(s)		strlen((char *)(s))
+
+#define EPROC2(efunc, format, a) { \
+	char tmp[1024]; \
+	(void)sprintf(tmp, format, a); \
+	eproc(efunc, tmp); }
+
+/* $B%-!<%3!<%I$N%(%s%3!<%IJ}K!(B */
+#define RAWKEY	(1L<<31)
+#define PSEUDO	(1L<<30)
+#define METAC	(1L<<29)
+#define META_ASCII	1	/* any ascii character (not useful) */
+#define META_CONTROL	2	/* any control character */
+#define META_RAW	3	/* any key event (not useful) */
+#define META_ANY	4	/* anything (character or event) */
+#define META_FUNC	5	/* any function key event */
+#define META_CURSOR	6	/* any cursor key event */
+#define META_KEYPAD	7	/* any keypad key event */
+#define META_MODIFIER	8	/* any modifier key event */
+#define META_PRINTABLE	9	/* any printable character */
+#define META_NONASCII	10	/* key event that has no ascii interpretation */
+
+/* pseudo key code */
+#define ENTERMODE	(ulong)(PSEUDO|1)
+#define EXITMODE	(ulong)(PSEUDO|2)
+
+/* function code */
+#define ENDFUNC		0xffff
+#define MODECHANGE	0x8000
+#define REDO		0x7fff
+#define PREVMODE	(MODECHANGE|0x1000)
+#define FUNC_MODIFIER_SHIFT		0x7ff0
+#define FUNC_MODIFIER_CONTROL	0x7ff1
+#define FUNC_MODIFIER_LOCK		0x7ff2
+#define FUNC_MODIFIER_MOD1		0x7ff3
+#define FUNC_MODIFIER_MOD2		0x7ff4
+#define FUNC_MODIFIER_MOD3		0x7ff5
+#define FUNC_MODIFIER_MOD4		0x7ff6
+#define FUNC_MODIFIER_MOD5		0x7ff7
+#define FUNC_MODIFIER_start		FUNC_MODIFIER_SHIFT
+#define FUNC_MODIFIER_end		FUNC_MODIFIER_MOD5
+
+#define MAXREDO		20
+
+/* key encoding */
+#define ccEncodeKey(ev) ((ulong)XLookupKeysym(ev, 0) | (ulong)RAWKEY)
+#define ccEncodeMask(ev) ((int)((ev)->state & 0xff))
+
+#define ccEncodeChar(c)	((ulong)(c))
+
+#define NOMODE		0xffff
+
+#define MATCHED_CHAR	0x8080	/* $B$3$l$O(B EUC $B$H$7$F$O(B illegal $B$J%3!<%I$J$N$G(B
+				 * $BFCJL$JL\E*$KMQ$$$k(B */
+#define CCLEAR_CHAR	0x8081	/* $B>e$KF1$8(B */
+
+#define CANONIC(c)	(((c) >= 'A' && (c) <= 'Z') ? c += ('a' - 'A') : c)
+
+/* $B%G!<%?9=B$(B */
+/* $BJQ49%k!<%k(B */
+typedef struct convdesc {
+	ulong	key;		/* $BF~NO%-!<(B */
+	ushort	mask;		/* modifier mask (of X KeyEvent) */
+	ushort	context;	/* context$BJ8;zNs(B ($B5U=g$K3JG<$5$l$k(B) */
+	ushort	result;		/* $BJQ497k2LJ8;zNs(B */
+	ushort	function;	/* function $B%Y%/%?$N%$%s%G%C%/%9(B */
+} ConvDesc;
+
+/* $B%b!<%I$4$H$N%F!<%V%k(B */
+typedef struct {
+	char		*name;		/* $B%b!<%IL>(B */
+	int		nrule;		/* $B%k!<%k$N?t(B */
+	ConvDesc	*cdbuf;		/* $B%k!<%k(B */
+	wchar		*prompt;	/* $B%W%m%s%W%HJ8;zNs(B */
+	ushort		fallthrough;
+} ModeTable;
+
+/* ccParseRule() $B$GFbItI=8=$KJQ49$5$l$?%k!<%k(B */
+typedef struct _ccRule {
+	char		*rulefile;	/* $BDj5A%U%!%$%kL>(B */
+	ccRule		next;		/* $B%k!<%k%j%9%H$N<!$NMWAG(B */
+	int		refcnt;		/* $B;2>H?t(B */
+	int		nmode;		/* $B%b!<%I$N?t(B */
+	int		initialmode;	/* $B=i4|%b!<%I(B */
+	ModeTable	*modes;		/* $B%b!<%I%F!<%V%k(B */
+	wchar		*strbuf;	/* $B%9%H%j%s%0%P%C%U%!(B */
+	ushort		*funcbuf;	/* $B%U%!%s%/%7%g%s%P%C%U%!(B */
+	int		nfunc;		/* $B%U%!%s%/%7%g%s$N?t(B */
+	char		*funcnamebuf;	/* $B%U%!%s%/%7%g%sL>$N%P%C%U%!(B */
+	void		(*errorfunc)();	/* $B%(%i!<%3!<%k%P%C%/(B */
+	int		casesensitive;	/* $BBgJ8;z>.J8;z$r6hJL$9$k$+$I$&$+(B */
+	int		autofix;	/* $B<+F03NDj$r$9$k$+$I$&$+(B */
+} ccRuleRec;
+
+static ccRule	ccrules;	/* $BJQ49%k!<%k$N%j%9%H(B */
+
+/* ccCreateBuf() $B$G:n$i$l$kJQ49%P%C%U%!(B */
+typedef struct _ccBuf {
+	ccRule	rule;			/* $BJQ49%k!<%k(B */
+	short	*functbl;
+	void	(*defaultaction)();	/* callback functions */
+	void	(*insertchar)();
+	void	(*deletechar)();
+	int	(*executefunction)();	/* True $B$rJV$;$P=>Mh$I$*$j<!$N%U%!%s%/(B
+					   $B%7%g%s$r8F$V$,!"(BFalse $B$rJV$;$P!"(B
+					   goto $B$N$h$&$K<!$N4X?t$OL5;k$9$k(B */
+	void	(*autofix)();
+	void	(*modenotify)();
+	caddr_t	client_data;
+	int	currentmode;		/* $B8=:_$N%b!<%I(B */
+	int	previousmode;		/* $B0l$DA0$N%b!<%I(B */
+	wchar	*context;
+	wchar	*contextend;
+	int	contextsize;
+	unsigned int modifier;	/* $B<!$NF~NO%-!<$r%b%G%#%U%!%$%d$D$-$K$9$k(B */
+} ccBufRec;
+
+#define STRSIZE		200
+#define MORESTRSIZE	100
+typedef struct {
+	wchar	*strbuf;
+	wchar	*strend;
+	wchar	*strp;
+} _strbufRec;
+
+#define	CDSIZE		10
+#define	MORECDSIZE	30
+typedef struct {
+	ConvDesc	*cdbuf;		/* ConvDesc $B%"%l%$(B */
+	ConvDesc	*cdend;
+	ConvDesc	*cdp;
+} _cdbufRec;
+
+#define FUNCSIZE	20
+#define MOREFUNCSIZE	20
+typedef struct {
+	ushort	*funcbuf;	/* $B%U%!%s%/%7%g%s%Y%/%?(B */
+	ushort	*funcend;
+	ushort	*funcp;
+} _funcbufRec;
+
+#define MAXFUNC			1024	/* $B%U%!%s%/%7%g%s$N<oN`$N>e8B(B */
+#define FUNCNAMESIZE		100
+#define MOREFUNCNAMESIZE	50
+typedef struct {
+	int	nfunc;
+	ushort	funcnames[MAXFUNC];
+	char	*funcnamebuf;
+	char	*funcnameend;
+	char	*funcnamep;
+	int	funcsize;
+} _funcnameRec;
+
+/* $BDj5A%U%!%$%k(B (for include directive) */
+#define MAXINC		10
+typedef struct {
+	int	findex;
+	FILE	*fp[MAXINC];
+} Files;
+
+#ifdef __STDC__
+static int wstrlen(wchar *);
+static wchar *wrev(wchar *);
+static void eproc(void (*)(), char *);
+static wchar *promptsave(wchar *);
+static int parseLine(uchar *, uchar **, int);
+static FILE *openfile(char *);
+static int doinclude(uchar *, Files *, void (*)());
+static uchar *getline(uchar *, int, Files *, void (*)());
+static int readRuleFile(ccRule, char *);
+static int registMode(ccRule, int, uchar **);
+static int newMode(ccRule, Files *, _strbufRec *, _funcbufRec *,
+		   _funcnameRec *, int, uchar **);
+static int getDesc(ccRule, uchar *, _funcbufRec *, _funcnameRec *,
+		   ulong *, int *, wchar *, wchar *, int *);
+static int getMode(ccRule, uchar *);
+static uchar *getQuote(uchar *, wchar *, int);
+static int getKey(uchar *, ulong *, int *);
+static int getmask(uchar *);
+static char *strinc(char *, char *);
+static ulong getcode(uchar *);
+static int getFunc(ccRule, _funcbufRec *, _funcnameRec *, int, uchar **);
+static ccRule findRule(char *);
+static void addRule(ccRule);
+static void deleteRule(ccRule);
+static int wstrsave(_strbufRec *, wchar *);
+static int wstralloc(_strbufRec *, int);
+static void wstradjust(_strbufRec *);
+static ConvDesc *cdalloc(_cdbufRec *);
+static void cdadjust(_cdbufRec *);
+static int funcalloc(_funcbufRec *, int);
+static void funcadjust(_funcbufRec *);
+static int funcsearch(_funcnameRec *, char *);
+static void funcnameadjust(_funcnameRec *);
+static int convchar(ccBuf, ulong, int, char *, int);
+static int cconvert(ccBuf, int, ulong, int, int *, char *, int);
+static int metamatch(ulong, ulong, int);
+static int contextMatch(ccBuf, wchar *);
+static void substStr(ccBuf, wchar *, wchar *, char *, int);
+#else
+static int wstrlen();
+static wchar *wrev();
+static void eproc();
+static wchar *promptsave();
+static int parseLine();
+static int readRuleFile();
+static int registMode();
+static int newMode();
+static int getDesc();
+static int getMode();
+static uchar *getQuote();
+static int getKey();
+static int getmask();
+static char *strinc();
+static ulong getcode();
+static int getFunc();
+static int wstrsave();
+static int wstralloc();
+static void wstradjust();
+static ConvDesc *cdalloc();
+static void cdadjust();
+static int funcalloc();
+static void funcadjust();
+static int funcsearch();
+static void funcnameadjust();
+static int convchar();
+static int cconvert();
+static int metamatch();
+static int contextMatch();
+static void substStr();
+#endif
+
+/*
+ *	Private Functions
+ */
+
+static int wstrlen(str)
+wchar *str;
+{
+	int	len = 0;
+
+	while (*str++)
+		len++;
+	return len;
+}
+
+static wchar *wrev(s)
+wchar *s;
+{
+	wchar	*str = s;
+	wchar	*end = str;
+	int	c;
+
+	while (*end++)
+		;
+	end -= 2;
+	while (str < end) {
+		c = *str;
+		*str++ = *end;
+		*end-- = c;
+	}
+	return s;
+}
+
+static void eproc(efunc, msg)
+void (*efunc)();
+char *msg;
+{
+	if (efunc == NULL) {
+		/* stderr $B$K%W%j%s%H(B */
+		(void)fprintf(stderr, "%s\n", msg);
+	} else {
+		/* $B%(%i!<%O%s%I%i$r8F$V(B */
+		(*efunc)(msg);
+	}
+}
+
+static wchar *promptsave(str)
+wchar *str;
+{
+	int	len = (wstrlen(str) + 1) * sizeof(wchar);
+	wchar	*p = (wchar *)Malloc(len);
+
+	if (p != NULL) {
+		wchar	*q = p;
+		while (*q++ = *str++)
+			;
+	}
+	return p;
+}
+
+static int parseLine(line, argv, argvsize)
+uchar *line;
+uchar **argv;
+int argvsize;
+{
+	int	c, qc;
+	int	argc;
+	int	state;
+#define IN_WORD		1	/* $B%o!<%I$NCf(B */
+#define IN_QUOTE	2	/* $B%o!<%I$NCf$G$5$i$K%/%)!<%H$NCf(B */
+
+	qc = 0;		/* not necessary, but for lint */
+	argc = 0;
+	state = 0;	/* $B%o!<%I$N30(B */
+	while (c = *line) {
+		/* $B%/%)!<%H$5$l$F$$$J$$6uGrJ8;z$O!"%o!<%I$r=*$i$;$k(B */
+		if (state != IN_QUOTE && (c == ' ' || c == '\t' || c == '\n')) {
+			/* NULL $B%?!<%_%M!<%H$5$;$k(B */
+			*line++ = '\0';
+			state = 0;
+			continue;
+		}
+		/* $B%o!<%I$N30$N6uGr0J30$NJ8;z$O!"%o!<%I$N;O$^$j$K$J$k(B */
+		if (state == 0) {
+			if (argc >= argvsize)
+				return argc;
+			argv[argc++] = line;
+			state = IN_WORD;
+		}
+		/* $B%P%C%/%9%i%C%7%e$O!"<!$NJ8;z$r%9%-%C%W$5$;$k(B */
+		if (c == '\\') {
+			/* $B$H$O$$$C$F$b<!$,(B Nul $BJ8;z$J$iOC$OJL(B */
+			if (*++line == '\0') {
+				*--line = '\0';
+				break;
+			}
+		} else if (state == IN_QUOTE) {
+			/* $B%/%)!<%H$O;O$^$j$HF1$8J8;z$G=*$k(B */
+			if (c == qc)
+				state = IN_WORD;
+		} else if (c == '\'' || c == '"') {
+			/* $B%/%)!<%H$N30$K%/%)!<%HJ8;z$,$"$l$P%/%)!<%H$N;O$^$j(B */
+			state = IN_QUOTE;
+			qc = c;
+		}
+		line++;
+	}
+
+	/* $B:G8e$N%/%)!<%H$,JD$8$F$$$J$$$+$b$7$l$J$$(B */
+	return state != IN_QUOTE ? argc : argc - 1;
+}
+
+/* openfile -- $BDj5A%U%!%$%k$r%*!<%W%s$9$k(B */
+static FILE *openfile(file)
+char *file;
+{
+	FILE	*fp;
+	char	filename[1024];
+	FILE	*fopen();
+	char	*getenv();
+
+	if ((fp = fopen(file, "r")) == NULL && *file != '/') {
+		char	*p, *q;
+		/* $B4D6-JQ?t(B CC_DEF_PATH $B$,$"$l$P$=$N%Q%9$N2<$r(B
+		 * $B%5!<%A$9$k(B
+		 */
+		if ((p = getenv("CC_DEF_PATH")) != NULL) {
+			while (*p != '\0') {
+				q = filename;
+				while (*p != '\0' && *p != ':')
+					*q++ = *p++;
+				if (*p == ':') p++;
+				if (q == filename) continue;
+				*q++ = '/';
+				*q = '\0';
+				(void)Strcat(filename, file);
+				if ((fp = fopen(filename, "r")) != NULL)
+					return fp;
+			}
+		}
+		/* $B%G%U%)%k%H$N%5!<%A%Q%9(B CCDEFPATH(/usr/lib/X11/ccdef) $B$N(B
+		 * $B2<$r%5!<%A$9$k(B
+		 */
+		(void)Strcpy(filename, CCDEFPATH);
+		(void)Strcat(filename, file);
+		fp = fopen(filename, "r");
+	}
+	return fp;
+}
+
+/* doinclude -- include $B9T$N=hM}$r$9$k(B */
+static int doinclude(line, files, efunc)
+uchar *line;
+Files *files;
+void (*efunc)();
+{
+	int	argc;
+	uchar	*argv[2];
+	char	*name;
+
+	argc = parseLine(line, argv, 2);
+	if (files->findex > MAXINC - 2) {
+		eproc(efunc, "include nesting too deep");
+		return -1;
+	}
+	if (argc < 2) {
+		eproc(efunc, "missing include filename");
+		return -1;
+	}
+	name = (char *)argv[1];
+	if (*name == '\'' || *name == '"') {
+		name++;
+		name[strlen(name) - 1] = '\0';
+	}
+	if ((files->fp[++files->findex] = openfile(name)) == NULL) {
+		EPROC2(efunc, "can't open %s", name);
+		--files->findex;
+		return -1;
+	}
+	return 0;
+}
+
+/* getline -- 1$B9TFI$_9~$`(B ($B$=$N:](B include $B$N=hM}$r9T$J$&(B) */
+static uchar *getline(line, linesize, files, efunc)
+uchar *line;
+int linesize;
+Files *files;
+void (*efunc)();
+{
+ redo:
+	if (fgets((char *)line, linesize, files->fp[files->findex])) {
+		register uchar	*p = line;
+		while (*p == ' ' || *p == '\t')
+			p++;
+		if (!Strncmp(p, "include", 7)) {
+			if (doinclude(p, files, efunc) < 0) {
+				return NULL;
+			} else {
+				goto redo;
+			}
+		}
+		return line;
+	}
+	(void)fclose(files->fp[files->findex]);
+	files->findex--;
+
+	if (files->findex >= 0) {
+		goto redo;
+	}
+
+	return NULL;
+}
+
+/* readRuleFile -- $BJQ49%k!<%kDj5A%U%!%$%k$rFI$_9~$`(B */
+static int readRuleFile(rule, file)
+ccRule rule;
+char *file;
+{
+	FILE		*fp;
+	int		moderegistered;
+	uchar	line[256], tmp[256];
+	uchar	*argv[20];
+	int		argc;
+	_strbufRec	strrec;
+	_funcbufRec	funcrec;
+	_funcnameRec	fnrec;
+	Files		files;
+	void		(*efunc)() = rule->errorfunc;
+	int		err = 0;
+
+	if ((fp = openfile(file)) == NULL) {
+		EPROC2(efunc, "can't open file %s", file);
+		return -1;
+	}
+	files.findex = 0;
+	files.fp[0] = fp;
+
+	moderegistered = 0;
+
+	strrec.strbuf = NULL;
+	funcrec.funcbuf = NULL;
+	fnrec.nfunc = 0;
+	fnrec.funcnamebuf = NULL;
+
+	rule->nmode = 0;
+	rule->initialmode = -1;
+
+	while (getline(line, sizeof(line), &files, efunc)) {
+		(void)Strcpy(tmp, line);
+		if ((argc = parseLine(tmp, argv, 20)) == 0)
+			continue;
+
+		/* '#' $B$G;O$^$k9T$O%3%a%s%H(B */
+		if (*line == '\0' || *line == '\n' || *line == '#') {
+			continue;
+		} else if (!moderegistered && argc > 1 &&
+			   !Strcmp(argv[0], "defmode")) {
+			/* $B%b!<%IDj5A9T(B */
+			if (registMode(rule, argc, argv) < 0) {
+				err++;
+				break;
+			}
+			moderegistered++;
+		} else if (!Strcmp(argv[0], "mode") && argc > 2) {
+			/* $B$"$k%b!<%I$KBP$9$kJQ49Dj5A(B */
+			if (!moderegistered) {
+				eproc(efunc, "'mode' before 'defmode'");
+				err++;
+				break;
+			}
+			if (newMode(rule, &files, &strrec, &funcrec, &fnrec,
+				    argc, argv) < 0) {
+				err++;
+				break;
+			}
+		} else if (!Strcmp(argv[0], "initialmode") &&
+			   argc > 1) {
+			if (!moderegistered) {
+				eproc(efunc, "'initialmode' before 'defmode'");
+				err++;
+				break;
+			}
+			rule->initialmode = getMode(rule, argv[1]);
+		} else if (!Strcmp(argv[0], "casesensitive")) {
+			rule->casesensitive = True;
+		} else if (!Strcmp(argv[0], "caseinsensitive")) {
+			rule->casesensitive = False;
+		} else if (!Strcmp(argv[0], "autofix")) {
+			rule->autofix = True;
+		} else if (!Strcmp(argv[0], "noautofix")) {
+			rule->autofix = False;
+		} else {
+			EPROC2(efunc, "syntax error - %s", line);
+		}
+	}
+
+	/* Close all opened files. */
+	while (files.findex >= 0) {
+		(void)fclose(files.fp[files.findex--]);
+	}
+
+	if (err) {
+		return -1;
+	}
+	if (rule->nmode == 0) {
+		eproc(efunc, "no modes defined");
+		return -1;
+	}
+	if (!moderegistered) {
+		eproc(efunc, "'defmode' required");
+		return -1;
+	}
+	if (rule->initialmode < 0) {
+		eproc(efunc, "'initialmode' required");
+		return -1;
+	}
+
+	wstradjust(&strrec);
+	funcadjust(&funcrec);
+	funcnameadjust(&fnrec);
+
+	rule->strbuf = strrec.strbuf;
+	rule->funcbuf = funcrec.funcbuf;
+	rule->funcnamebuf = fnrec.funcnamebuf;
+	rule->nfunc = fnrec.nfunc;
+#ifdef DEBUG_CCONV
+	dumpAllRules(rule);
+#endif
+
+	return 0;
+}
+
+static int registMode(rule, ac, av)
+ccRule rule;
+int ac;
+uchar **av;
+{
+	int		nmode;
+	ModeTable	*modes;
+	int		i;
+
+	ac--, av++;
+
+	nmode = ac;
+	modes = (ModeTable *)Malloc(nmode * sizeof(ModeTable));
+	if (modes == NULL) {
+		eproc(rule->errorfunc, "can't alloc memory");
+		return -1;
+	}
+	rule->modes = modes;
+
+	for (i = 0; i < nmode; i++) {
+		if ((modes[i].name = Malloc(Strlen(av[i]) + 1)) == NULL) {
+			eproc(rule->errorfunc, "can't alloc memory");
+			Free(modes);
+			return -1;
+		}
+		(void)Strcpy(modes[i].name, av[i]);
+		modes[i].nrule = 0;
+		modes[i].cdbuf = NULL;
+		modes[i].prompt = NULL;
+		modes[i].fallthrough = NOMODE;
+	}
+
+	rule->nmode = nmode;
+	return 0;
+}
+
+/* newMode -- $B$"$k%b!<%I$K$D$$$F$N%k!<%k$rFI$_9~$`(B */
+static int newMode(rule, files, srec, frec, fnrec, ac, av)
+ccRule rule;
+Files *files;
+_strbufRec *srec;
+_funcbufRec *frec;
+_funcnameRec *fnrec;
+int ac;
+uchar **av;
+{
+	uchar	line[256];
+	int		mode;
+	ulong		inkey;
+	int		modmask;
+	wchar		prompt[30], context[100], result[100];
+	int		func;
+	int		ndesc = 0;
+	ModeTable	*mp;
+	ConvDesc	*cdp;
+	_cdbufRec	cdbuf;
+	void		(*efunc)() = rule->errorfunc;
+
+	/* $B%U%)!<%^%C%H$O(B
+	 * "mode <$B%b!<%IL>(B> <"$B%W%m%s%W%HJ8;zNs(B"> [fallthrough <$B%b!<%IL>(B>]
+	 */
+	/* $B%b!<%I$N%A%'%C%/(B */
+	if ((mode = getMode(rule, av[1])) < 0) {
+		EPROC2(efunc, "illegal modename: %s", av[1]);
+		return -1;	/* No Such Mode */
+	}
+	mp = &rule->modes[mode];
+
+	if (getQuote(av[2], prompt, 0) == NULL) {
+		EPROC2(efunc, "illegal prompt: %s", av[2]);
+		return -1;
+	}
+	mp->prompt = promptsave(prompt);
+	mp->nrule = 0;
+	
+	if (ac > 4 && !Strcmp(av[3], "fallthrough")) {
+		mp->fallthrough = getMode(rule, av[4]);
+	} else {
+		mp->fallthrough = NOMODE;
+	}
+
+	cdbuf.cdbuf = NULL;
+
+	/* $B%k!<%k$rFI$s$G%9%H%"$9$k(B */
+	while (getline(line, sizeof(line), files, efunc)) {
+		/* '#' $B$G;O$^$k9T$O%3%a%s%H(B */
+		if (*line == '\0' || *line == '\n' || *line == '#')
+			continue;
+		if (!Strncmp(line, "endmode", 6))
+			break;
+		if (getDesc(rule, line, frec, fnrec, &inkey, &modmask,
+			    context, result, &func)) {
+			if ((cdp = cdalloc(&cdbuf)) == NULL) {
+				return -1;
+			}
+
+			/* $B%k!<%k$N%9%H%"(B */
+			cdp->key = inkey;
+			cdp->mask = modmask;
+			cdp->context = *context ? wstrsave(srec, wrev(context)) : 0;
+			cdp->result = *result ? wstrsave(srec, result) : 0;
+			cdp->function = func;
+			ndesc++;
+		} else
+			EPROC2(efunc, "illegal description - %s", line);
+	}
+
+	/* $B%k!<%k$,#1$D$b$J$1$l$P%(%i!<$K$9$Y$-$@$m$&(B */
+	/* $B$H;W$C$?$,Nc$($P(B ASCII $B%b!<%I$N$H$-$K$O%k!<%k$,#1$D$b$J$$$3$H$,(B
+	 * $B$"$j$&$k(B
+	 */
+
+	cdadjust(&cdbuf);
+
+	mp->nrule = ndesc;
+	mp->cdbuf = cdbuf.cdbuf;
+
+	return 0;
+}
+
+static int getDesc(rule, line, frec, fnrec, keyp, maskp, context, result, funcp)
+ccRule rule;
+uchar *line;
+_funcbufRec *frec;
+_funcnameRec *fnrec;
+ulong *keyp;
+int *maskp;
+wchar *context;
+wchar *result;
+int *funcp;
+{
+	uchar	tmp[256];
+	uchar	*av[20];
+	int		ac;
+	void		(*efunc)() = rule->errorfunc;
+
+	/* valid description format is:
+		"context"	key	"result"	[function...]
+	*/
+
+	(void)Strcpy(tmp, line);
+	ac = parseLine(tmp, av, 20);
+	if (ac < 3) {
+		EPROC2(efunc, "syntax error - %s", line);
+		return 0;
+	}
+
+	/* context $B$NFI$_9~$_(B */
+	if (getQuote(av[0], context, 0) == NULL)
+		return 0;
+
+	/* $B%-!<%3!<%I$rFI$_9~$s$G(B */
+	if (getKey(av[1], keyp, maskp) < 0) {
+		EPROC2(efunc, "no such key (%s)", av[1]);
+		return 0;
+	}
+
+	/* result $B$rFI$_9~$s$G(B */
+	if (getQuote(av[2], result, 1) == NULL)
+		return 0;
+
+	/* $B%U%!%s%/%7%g%s$N5-=R$,$"$l$P$=$l$rFI$_9~$`(B */
+	/* $B$b$7AjEv$9$k%U%!%s%/%7%g%s$,$J$/$F$b%(%i!<$K$7$J$$(B */
+	if (ac > 3) {
+		*funcp =  getFunc(rule, frec, fnrec, ac - 3, &av[3]);
+	} else {
+		*funcp = 0;
+	}
+
+	return 1;
+}
+
+static int getMode(rule, str)
+ccRule rule;
+uchar *str;
+{
+	ModeTable	*modes = rule->modes;
+	int	i;
+
+	for (i = 0; i < rule->nmode; i++) {
+		if (!Strcmp(str, modes[i].name))
+			return i;
+	}
+	EPROC2(rule->errorfunc, "undefined mode %s", str);
+	return -1;
+}
+
+/* getQuote -- $B%/%)!<%F!<%7%g%s5-9f$G0O$^$l$?J8;zNs$rFI$s$G(B wchar $B$K$9$k(B */
+static uchar *getQuote(line, str, metaf)
+uchar	*line;
+wchar		*str;
+int		metaf;	/* '&' $B$H(B '/' $B$r%a%?!&%-%c%i%/%?$H$9$k$+$I$&$+(B */
+{
+	int	c;
+	int	quote;		/* quote flag */
+	int	qc = *line++;	/* quote character */
+#define SS2	0x8e
+#define SS3	0x8f
+
+	if (qc != '\'' && qc != '"')
+		return((uchar *)NULL);
+	
+	quote = 0;
+	while ((c = *line++) && c != qc) {
+		if (c == '\\' && !quote) {
+			quote = 1;
+			continue;
+		}
+			
+		if (c == '^' && !quote) {
+			if (c = *line++)
+				*str++ = c - '@';
+			else
+				break;
+		} else if (metaf && c == '&' && !quote)
+			*str++ = MATCHED_CHAR;
+		else if (metaf && c == '/' && !quote)
+			*str++ = CCLEAR_CHAR;
+		else if (c < 0x80)
+			*str++ = c;
+		else if (c == SS2)
+			*str++ = *line++ | 0x80;
+		else if (c == SS3) {
+			c = *line++;
+			*str++ = (c << 8) | (*line++ & 0x7f) | 0x8000;
+		} else {
+			*str++ = (c << 8) | *line++ | 0x8080;
+		}
+	}
+	*str = 0;
+
+	return((c == qc) ? line : (uchar *)NULL);
+}
+
+/* getKey -- $B%-!<%3!<%I$rFI$`(B */
+static int getKey(line, keyp, maskp)
+uchar *line;
+ulong *keyp;
+int *maskp;
+{
+	/*
+	 * $B%-!<%3!<%I$N5-=RK!$O#2DL$j(B
+	 * 1. ASCII $BI=5-(B
+	 *	'a'
+	 *	'^H'
+	 *	'\033'
+	 *	'\xff'
+	 *
+	 * 2. XKEY $BI=5-(B
+	 *	#124
+	 *	#0132
+	 *	#0x58
+	 *	shift-A
+	 *	shift-control-meta-HENKAN
+	 *
+	 * pseudo code
+	 *	ENTERMODE
+	 *	EXITMODE
+	 *
+	 * wild character
+	 *	@ascii
+	 *	@control
+	 *	@raw
+	 *	@any
+	 */
+
+	int	key = 0;
+
+	*maskp = 0;
+
+	if (*line == '\'') {	/* $B%7%s%0%k%/%)!<%H$G;O$^$k$N$G(B ASCII $BI=5-(B */
+		if (*++line == '\\') {
+			/* '\'' $B$N>l9g(B($B%7%s%0%k%/%)!<%H<+?H(B)$B!"(B
+			 * '\\' $B$N>l9g(B($B%P%C%/%9%i%C%7%e(B)
+			 * '\033' $B$N$h$&$J#8?JI=5-$N>l9g$H(B
+			 * '\x27' $B$N$h$&$J#1#6?JI=5-$N>l9g$,$"$k(B
+			 */
+			if (*++line == '\'')	/* '\'' */
+				key = '\'';
+			else if (*line == '\\')	/* '\\' */
+				key = '\\';
+			else if (*line == 'x')	/* hexadecimal */
+				(void)sscanf((char *)++line, "%x", &key);
+			else			/* octal */
+				(void)sscanf((char *)line, "%o", &key);
+			key &= 0xff;
+		} else if (*line == '^') {
+			/* '^' ($B%+%l%C%H<+?H(B) $B$^$?$O%3%s%H%m!<%k%3!<%I(B */
+			if (*++line == '\'')
+				key = '^';
+			else
+				key = *line - '@';
+		} else {
+			key = *line;
+		}
+		*keyp = key;
+	} else if (*line == '#') {	/* event code */
+		if (*++line == '0') {	/* octal or hexadecimal */
+			if (*(line + 1) == 'x')	/* hexadecimal */
+				(void)sscanf((char *)line + 2, "%x", &key);
+			else			/* octal */
+				(void)sscanf((char *)line, "%o", &key);
+		} else {
+			key = atoi((char *)line);
+		}
+		*keyp = (ulong)key | (ulong)RAWKEY;
+	} else if (!Strcmp(line, "ENTERMODE")) {
+		*keyp = ENTERMODE;
+	} else if (!Strcmp(line, "EXITMODE")) {
+		*keyp = EXITMODE;
+	} else if (*line == '@') {
+		/* $B%o%$%k%I!&%-%c%i%/%?(B */
+		line++;
+		if (!Strcmp(line, "ascii"))
+			key = META_ASCII;
+		else if (!Strcmp(line, "printable"))
+			key = META_PRINTABLE;
+		else if (!Strcmp(line, "control"))
+			key = META_CONTROL;
+		else if (!Strcmp(line, "raw"))
+			key = META_RAW;
+		else if (!Strcmp(line, "any"))
+			key = META_ANY;
+		else if (!Strcmp(line, "func"))
+			key = META_FUNC;
+		else if (!Strcmp(line, "cursor"))
+			key = META_CURSOR;
+		else if (!Strcmp(line, "keypad"))
+			key = META_KEYPAD;
+		else if (!Strcmp(line, "modifier"))
+			key = META_MODIFIER;
+		else if (!Strcmp(line, "non-ascii"))
+			key = META_NONASCII;
+		else
+			return -1;
+		*keyp = (ulong)key | (ulong)METAC;
+	} else {
+		if ((key = getcode(line)) == 0)
+			return -1;
+		*keyp = (ulong)key | (ulong)RAWKEY;
+		*maskp = getmask(line);
+	}
+	return 0;
+}
+
+/* getmask -- $B%b%G%#%U%!%$%"!&%^%9%/$rJV$9(B */
+static int getmask(s)
+uchar *s;
+{
+	int	mask = 0;
+	char	buf[256];
+	uchar	*p;
+
+	if ((p = (uchar *)rindex((char *)s, '-')) == NULL)
+		return 0;
+	(void)strncpy(buf, (char *)s, p - s);
+	buf[p - s] = '\0';
+	
+	if (strinc(buf, "shift"))
+		mask |= ShiftMask;
+	if (strinc(buf, "control"))
+		mask |= ControlMask;
+	if (strinc(buf, "lock"))
+		mask |= LockMask;
+	if (strinc(buf, "mod1"))
+		mask |= Mod1Mask;
+	if (strinc(buf, "mod2"))
+		mask |= Mod2Mask;
+	if (strinc(buf, "mod3"))
+		mask |= Mod3Mask;
+	if (strinc(buf, "mod4"))
+		mask |= Mod4Mask;
+	if (strinc(buf, "mod5"))
+		mask |= Mod5Mask;
+	return mask;
+}
+
+static char *strinc(s, k)
+char *s;
+char *k;
+{
+	register int	len = Strlen(k);
+
+	while (s = index(s, *k))
+		if (!Strncmp(s, k, len))
+			return s;
+		else
+			s++;
+	return NULL;
+}
+
+
+/* getcode -- KeySym $B$rJV$9(B */
+static ulong getcode(s)
+uchar *s;
+{
+	register uchar	*t;
+	KeySym			keysym;
+	KeySym			XStringToKeysym();
+
+	if ((t = (uchar *)rindex((char *)s, '-')) == NULL)
+		t = s;
+	else
+		t++;
+	keysym = XStringToKeysym((char *)t);
+	if (keysym == NoSymbol)
+		return (ulong)0;
+	else
+		return (ulong)keysym;
+}
+
+static int getFunc(rule, frec, fnrec, n, args)
+ccRule rule;
+_funcbufRec *frec;
+_funcnameRec *fnrec;
+int	n;
+uchar	**args;
+{
+	int	i, j;
+	uchar	*func;
+	uchar	*arg;
+	ushort	*fp;
+	int	findex;
+	void	(*efunc)() = rule->errorfunc;
+
+	findex = funcalloc(frec, n + 1);
+	fp = frec->funcbuf + findex;
+
+	j = 0;
+	while (n > 0) {
+		func = *args++;
+		if (!Strcmp(func, "goto")) {
+			/* $B%b!<%I$NJQ99(B */
+			if (n < 2)
+			    break;	/* $B%b!<%IL>$,=q$$$F$J$$(B */
+			arg = *args++;
+			--n;
+			if (!Strcmp(arg, "PREV")) {
+				fp[j++] = PREVMODE;
+				break;
+			}
+			if ((i = getMode(rule, arg)) < 0) {
+				break;
+			}
+			fp[j++] = MODECHANGE | i;
+			break;
+		} else if (!Strcmp(func, "redo")) {
+			fp[j++] = REDO;
+			break;
+		} else if (!Strncmp(func, "add-modifier-",
+							sizeof("add-modifier-") - 1)) {
+			/* $B<!$NF~NO%-!<$r%b%G%#%U%!%$%d$D$-$K$9$k(B */
+			char *mod = func + sizeof("add-modifier-") - 1;
+			if      (!Strcmp(mod, "shift"  )) fp[j++] = FUNC_MODIFIER_SHIFT;
+			else if (!Strcmp(mod, "control")) fp[j++] = FUNC_MODIFIER_CONTROL;
+			else if (!Strcmp(mod, "lock"   )) fp[j++] = FUNC_MODIFIER_LOCK;
+			else if (!Strcmp(mod, "mod1"   )) fp[j++] = FUNC_MODIFIER_MOD1;
+			else if (!Strcmp(mod, "mod2"   )) fp[j++] = FUNC_MODIFIER_MOD2;
+			else if (!Strcmp(mod, "mod3"   )) fp[j++] = FUNC_MODIFIER_MOD3;
+			else if (!Strcmp(mod, "mod4"   )) fp[j++] = FUNC_MODIFIER_MOD4;
+			else if (!Strcmp(mod, "mod5"   )) fp[j++] = FUNC_MODIFIER_MOD5;
+			break;
+		} else {
+			/* $B%U%!%s%/%7%g%sI=$N8!:w(B */
+			int	fnum;
+			if ((fnum = funcsearch(fnrec, (char *)func)) < 0) {
+				EPROC2(efunc, "too many functions (> %d)", MAXFUNC);
+			} else {
+				fp[j++] = fnum;
+			}
+		}
+		--n;
+	}
+	fp[j++] = ENDFUNC;
+	frec->funcp = fp + j;	/* kludge */
+	return findex;
+}
+
+static ccRule
+findRule(rulefile)
+char *rulefile;
+{
+	ccRule	rule = ccrules;
+
+	while (rule) {
+		if (rule->rulefile && !strcmp(rulefile, rule->rulefile)) {
+			return rule;
+		}
+		rule = rule->next;
+	}
+	return NULL;
+}
+
+static void
+addRule(rule)
+ccRule rule;
+{
+	rule->refcnt = 1;
+	rule->next = ccrules;
+	ccrules = rule;
+}
+
+static void
+deleteRule(rule)
+ccRule	rule;
+{
+	ccRule	rp = ccrules;
+	ccRule	rp0 = NULL;
+
+	while (rp) {
+		if (rule == rp) {
+			if (rp0 == NULL) {
+				ccrules = rp->next;
+			} else {
+				rp0->next = rp->next;
+			}
+			return;
+		}
+		rp0 = rp;
+		rp = rp->next;
+	}
+}
+
+static int wstrsave(srec, str)
+_strbufRec *srec;
+wchar *str;
+{
+	int	len = wstrlen(str);
+	int	pos;
+	wchar	*p;
+
+	pos = wstralloc(srec, len + 1);
+	if (pos > 0) {
+		p = srec->strbuf + pos;
+		while (len-- > 0) {
+			*p++ = *str++;
+		}
+		*p = 0;
+	}
+	return pos;
+}
+
+/* $B%P%C%U%!%"%m%1!<%H%U%!%s%/%7%g%s(B */
+
+static int wstralloc(srec, len)
+_strbufRec *srec;
+int len;
+{
+	int	ret;
+
+	if (srec->strbuf == NULL) {
+		/* allocate srec->strbuf */
+		srec->strbuf = (wchar *)Malloc(STRSIZE * sizeof(wchar));
+		if (srec->strbuf == NULL)
+			return 0;
+		srec->strend = srec->strbuf + STRSIZE;
+		srec->strp = srec->strbuf;
+		*srec->strp++ = 0;	/* dummy */
+	}
+	if (srec->strp + len > srec->strend) {
+		/* allocate more memory */
+		int	size = (srec->strp + len) - srec->strend;
+		int	offset = srec->strp - srec->strbuf;
+		wchar	*wp;
+
+		if (size < MORESTRSIZE)
+			size = MORESTRSIZE;
+		size += srec->strend - srec->strbuf;
+		wp = (wchar *)Realloc(srec->strbuf, size * sizeof(wchar));
+		if (wp == NULL)
+			return 0;
+		srec->strp = wp + offset;
+		srec->strbuf = wp;
+		srec->strend = wp + size;
+	}
+
+	ret = srec->strp - srec->strbuf;
+	srec->strp += len;
+
+	return ret;
+}
+
+static void wstradjust(srec)
+_strbufRec *srec;
+{
+	int	size = srec->strp - srec->strbuf;
+	wchar	*wp;
+
+	if (size == 0) return;
+	wp = (wchar *)Realloc(srec->strbuf, size * sizeof(wchar));
+	if (wp != NULL) {
+		srec->strbuf = wp;
+		srec->strp = srec->strend = wp + size;
+	}
+}
+
+static ConvDesc *cdalloc(crec)
+_cdbufRec *crec;
+{
+	ConvDesc	*ret;
+
+	if (crec->cdbuf == NULL) {
+		crec->cdbuf = (ConvDesc *)Malloc(CDSIZE * sizeof(ConvDesc));
+		if (crec->cdbuf == NULL)
+			return NULL;
+		crec->cdend = crec->cdbuf + CDSIZE;
+		crec->cdp = crec->cdbuf;
+	}
+	if (crec->cdp >= crec->cdend) {
+		int	size = crec->cdend - crec->cdbuf + MORECDSIZE;
+		int	offset = crec->cdp - crec->cdbuf;
+		ConvDesc	*cdp;
+
+		cdp = (ConvDesc *)Realloc(crec->cdbuf, size * sizeof(ConvDesc));
+		if (cdp == NULL) {
+			return NULL;
+		}
+		crec->cdp = cdp + offset;
+		crec->cdbuf = cdp;
+		crec->cdend = cdp + size;
+	}
+
+	ret = crec->cdp++;
+	return ret;
+}
+
+static void cdadjust(crec)
+_cdbufRec *crec;
+{
+	int		size = crec->cdp - crec->cdbuf;
+	ConvDesc	*cdp;
+
+	if (size == 0) return;
+	cdp = (ConvDesc *)Realloc(crec->cdbuf, size * sizeof(ConvDesc));
+	if (cdp != NULL) {
+		crec->cdbuf = cdp;
+		crec->cdp = crec->cdend = cdp + size;
+	}
+}
+
+static int funcalloc(frec, n)
+_funcbufRec *frec;
+int n;
+{
+	int	ret;
+
+	if (frec->funcbuf == NULL) {
+		/* allocate funcbuf */
+		frec->funcbuf = (ushort *)Malloc(FUNCSIZE * sizeof(ushort));
+		if (frec->funcbuf == NULL)
+			return 0;
+		frec->funcend = frec->funcbuf + FUNCSIZE;
+		frec->funcp = frec->funcbuf;
+		*(frec->funcp)++ = ENDFUNC;	/* dummy */
+	}
+	if (frec->funcp + n > frec->funcend) {
+		/* allocate more memory */
+		int	size = (frec->funcp + n) - frec->funcend;
+		int	offset = frec->funcp - frec->funcbuf;
+		ushort	*up;
+
+		if (size < MOREFUNCSIZE)
+			size = MOREFUNCSIZE;
+		size += frec->funcend - frec->funcbuf;
+		up = (ushort *)Realloc(frec->funcbuf, size * sizeof(ushort));
+		if (up == NULL)
+			return 0;
+		frec->funcp = up + offset;
+		frec->funcbuf = up;
+		frec->funcend = up + size;
+	}
+
+	ret = frec->funcp - frec->funcbuf;
+	frec->funcp += n;
+
+	return ret;
+}
+
+static void funcadjust(frec)
+_funcbufRec *frec;
+{
+	int	size = frec->funcp - frec->funcbuf;
+	ushort	*fp;
+
+	if (size == 0) return;
+	fp = (ushort *)Realloc(frec->funcbuf, size * sizeof(ushort));
+	if (fp != NULL) {
+		frec->funcbuf = fp;
+		frec->funcp = frec->funcend = fp + size;
+	}
+}
+
+static int funcsearch(fnrec, funcname)
+_funcnameRec *fnrec;
+char *funcname;
+{
+	int	nfunc = fnrec->nfunc;
+	ushort	*fnames = fnrec->funcnames;
+	char	*fnbuf = fnrec->funcnamebuf;
+	int	i;
+	int	len;
+
+	for (i = 0; i < nfunc; i++) {
+		if (!strcmp(funcname, fnbuf + *fnames++))
+			return i;
+	}
+
+	if (nfunc >= MAXFUNC)
+		return -1;
+
+	len = strlen(funcname) + 1;
+
+	/* add new function */
+	if (fnrec->funcnamebuf == NULL) {
+		/* allocate funcnamebuf */
+		if ((fnrec->funcnamebuf = Malloc(FUNCNAMESIZE)) == NULL)
+			return -1;
+		fnrec->funcnameend = fnrec->funcnamebuf + FUNCNAMESIZE;
+		fnrec->funcnamep = fnrec->funcnamebuf;
+	}
+	if (fnrec->funcnamep + len > fnrec->funcnameend) {
+		/* allocate more memory */
+		int	size = (fnrec->funcnamep + len) - fnrec->funcnameend;
+		int	offset = fnrec->funcnamep - fnrec->funcnamebuf;
+		char	*cp;
+
+		if (size < MOREFUNCNAMESIZE)
+			size = MOREFUNCNAMESIZE;
+		size += fnrec->funcnameend - fnrec->funcnamebuf;
+		if ((cp = Realloc(fnrec->funcnamebuf, size)) == NULL)
+			return 0;
+		fnrec->funcnamep = cp + offset;
+		fnrec->funcnamebuf = cp;
+		fnrec->funcnameend = cp + size;
+	}
+
+	(void)strcpy(fnrec->funcnamep, funcname);
+	fnrec->funcnames[nfunc] = fnrec->funcnamep - fnrec->funcnamebuf;
+	fnrec->funcnamep += len;
+
+	return fnrec->nfunc++;
+}
+
+static void funcnameadjust(fnrec)
+_funcnameRec *fnrec;
+{
+	int	size = fnrec->funcnamep - fnrec->funcnamebuf;
+	char	*cp;
+
+	if (size == 0) return;
+	if (cp = Realloc(fnrec->funcnamebuf, size)) {
+		fnrec->funcnamebuf = cp;
+		fnrec->funcnamep = fnrec->funcnameend = cp + size;
+	}
+}
+
+static int convchar(buf, key, mask, str, len)
+ccBuf buf;
+ulong key;	/* keysym (RAWKEY) or ascii code */
+int mask;	/* modifier mask */
+char *str;	/* ascii interpretation */
+int len;	/* length of str */
+{
+	int	r;
+	int	func;
+	int	redocount = 0;
+	ushort	*fp;
+	ccRule	rule = buf->rule;
+
+ redo:
+	/* $B$^$:$O8=:_$N%b!<%I$N%k!<%k$GJQ49$7$F$_$k(B */
+	r = cconvert(buf, buf->currentmode, key, mask, &func, str, len);
+	if (r < 0) {
+		/* $B%^%C%A$9$k%k!<%k$,8+$D$+$i$J$+$C$?$N$G(B
+		 * fallthrough $B$G;XDj$5$l$k%b!<%I$N%k!<%k$rC5$9(B
+		 */
+		int	tmpmode = rule->modes[buf->currentmode].fallthrough;
+
+		while (tmpmode != NOMODE) {
+			r = cconvert(buf, tmpmode, key, mask, &func, str, len);
+			if (r >= 0)	/* $B%^%C%A$7$?(B */
+				break;
+			tmpmode = rule->modes[tmpmode].fallthrough;
+		}
+	}
+
+	if (r < 0)
+		return -1;	/* $B$I$l$K$b%^%C%A$7$J$+$C$?(B */
+
+	if (func == 0)
+		return 0;	/* $B2?$b$7$J$$(B */
+
+	fp = rule->funcbuf + func;
+	while ((func = *fp++) != ENDFUNC) {
+		if (func == REDO) {
+			if (redocount++ > MAXREDO)
+			    return -1;	/* $B$?$V$sL58B%k!<%W(B */
+			else
+			    goto redo;	/* redo -- $B$b$&0lEY(B */
+		} else if (func & MODECHANGE) {	/* $B%+%l%s%H%b!<%I$NJQ99(B */
+			int	tmpmode = buf->currentmode;
+			
+			/* pseudo-key $B$NF~NO(B */
+			(void)convchar(buf, EXITMODE, 0, (char *)NULL, 0);
+			
+			if (func == PREVMODE) {
+				buf->currentmode = buf->previousmode;
+			} else {
+				buf->currentmode = func & ~MODECHANGE;
+			}
+			buf->previousmode = tmpmode;
+			
+			/* pseudo-key $B$NF~NO(B */
+			(void)convchar(buf, ENTERMODE, 0, (char *)NULL, 0);
+			
+			/* $B%b!<%I$,JQ$o$C$?;~$K$O%3%s%F%-%9%H$r%/%j%"$9$k(B */
+			ccContextClear(buf);
+
+			/* $B%b!<%IJQ99%3!<%k%P%C%/$,$"$l$P8F$S=P$9(B */
+			if (buf->modenotify) {
+				(*buf->modenotify)(buf->currentmode,
+						  buf->previousmode,
+						  buf->client_data);
+			}
+			break;
+		} else if (FUNC_MODIFIER_start <= func &&
+				   func <= FUNC_MODIFIER_end) {
+			/* $B<!$NF~NO%-!<$r%b%G%#%U%!%$%d$D$-$K$9$k(B */
+		  switch (func) {
+		  case FUNC_MODIFIER_SHIFT:   buf->modifier |= ShiftMask; break;
+		  case FUNC_MODIFIER_CONTROL: buf->modifier |= ControlMask; break;
+		  case FUNC_MODIFIER_LOCK:    buf->modifier |= LockMask; break;
+		  case FUNC_MODIFIER_MOD1:    buf->modifier |= Mod1Mask; break;
+		  case FUNC_MODIFIER_MOD2:    buf->modifier |= Mod2Mask; break;
+		  case FUNC_MODIFIER_MOD3:    buf->modifier |= Mod3Mask; break;
+		  case FUNC_MODIFIER_MOD4:    buf->modifier |= Mod4Mask; break;
+		  case FUNC_MODIFIER_MOD5:    buf->modifier |= Mod5Mask; break;
+		  }
+		} else {
+			int	truefunc = buf->functbl[func];
+			/* $B%G%#%9%Q%C%A!&%k!<%A%s$r8F$V(B */
+			if (truefunc >= 0) {
+				if (!(*buf->executefunction)(truefunc, str, len,
+							buf->client_data))
+					break;
+			}
+		}
+	}
+	return 0;
+}
+
+static int cconvert(buf, mode, inkey, mask, func, str, len)
+ccBuf buf;
+int mode;	/* current mode */
+ulong inkey;	/* input key (raw/mapped) */
+int mask;
+int *func;	/* function */
+char *str;
+int len;
+{
+	ccRule		rule = buf->rule;
+	ConvDesc	*entry;
+	ulong		key;
+	int		n;
+	ModeTable	*modep;
+
+	if (mode < 0 || mode >= rule->nmode)
+		return -1;	/* No Such Mode */
+
+	modep = &rule->modes[mode];
+
+	if ((n = modep->nrule) <= 0)
+		return -1;	/* No Rules */
+
+	for (entry = modep->cdbuf; --n >= 0; entry++) {
+		key = entry->key;
+		if (key & (ulong)METAC) {
+			/* $B%o%$%k%I%+!<%IJ8;z$N%^%C%A%s%0(B */
+			if (!metamatch(key, inkey, len == 0))
+				continue;
+		} else if (key & (ulong)RAWKEY && mask != entry->mask) {
+			continue;
+		} else if (key != inkey) {
+			continue;
+		}
+
+		/* $B%-!<$,%^%C%A$7$?(B */
+		if (contextMatch(buf, rule->strbuf + entry->context)) {
+			substStr(buf, rule->strbuf + entry->context,
+				 rule->strbuf + entry->result, str, len);
+			*func = entry->function;
+			return 0;
+		}
+	}
+
+	return -1;	/* No Match */
+}
+
+static int metamatch(rkey, inkey, nonascii)
+ulong rkey;
+ulong inkey;
+int nonascii;
+{
+	int	type = (int)(rkey & 0xff);
+
+	switch (type) {
+	case META_ASCII:
+		return !(inkey & (ulong)(RAWKEY|PSEUDO));
+	case META_PRINTABLE:
+		return (0x20 <= inkey && inkey < 0x7f);
+	case META_CONTROL:
+		return inkey < 0x20;
+	case META_RAW:
+		return inkey & (ulong)RAWKEY;
+	case META_ANY:
+		return 1;
+	case META_FUNC:
+		return (inkey & (ulong)RAWKEY) && IsFunctionKey(inkey & 0xffff);
+	case META_CURSOR:
+		return (inkey & (ulong)RAWKEY) && IsCursorKey(inkey & 0xffff);
+	case META_KEYPAD:
+		return (inkey & (ulong)RAWKEY) && IsKeypadKey(inkey & 0xffff);
+	case META_MODIFIER:
+		return (inkey & (ulong)RAWKEY) && IsModifierKey(inkey & 0xffff);
+	case META_NONASCII:
+		return (inkey & (ulong)RAWKEY) && nonascii;
+	default:
+		return 0;
+	}
+	/* NOTREACHED */
+}
+
+static int contextMatch(buf, context)
+ccBuf buf;
+wchar *context;
+{
+	wchar	*c0 = buf->contextend;
+	wchar	*c1 = buf->context;
+	int	cs = buf->rule->casesensitive;
+
+	if (context == 0 || *context == 0)
+		return 1;	/* $BL5>r7o%^%C%A(B */
+	if (c0 - c1 < wstrlen(context))	/* $BD9$5$N%A%'%C%/(B */
+		return 0;	/* matching fail */
+	c0--;
+	while (*context) {
+		if ((!cs && CANONIC(*c0) == CANONIC(*context)) ||
+		    (cs && *c0 == *context))
+			c0--, context++;
+		else
+			return 0;	/* fail */
+	}
+	return 1;
+}
+
+static void substStr(buf, context, result, str, len)
+ccBuf buf;
+wchar *context;
+wchar *result;
+char *str;
+int len;
+{
+	register int	c;
+	int		nbytes;
+	uchar	*bufp;
+
+	/* $B%3%s%F%-%9%H$NJ,$r>C$9(B */
+	while (*context++) {
+		ccContextDelete(buf);
+		(*buf->deletechar)(buf->client_data);
+	}
+
+	while (c = *result++) {
+		if (c == MATCHED_CHAR) {
+			nbytes = len;
+			bufp = (uchar *)str;
+			while (nbytes-- > 0) {
+				c = *bufp++;
+				/* bufp $B$NCf?H$O(B ASCII $B$+(B $B%+%J$J$N$G(B
+				 * EUC $B%W%m%;%9%3!<%I$X$NJQ49$r$o$6$o$6(B
+				 * $B$d$kI,MW$O$J$$(B
+				 */
+				ccContextAppend(buf, c);
+				(*buf->insertchar)(c, buf->client_data);
+			}
+			continue;
+		} else if (c == CCLEAR_CHAR) {
+			/* $B%3%s%F%-%9%H$r%/%j%"$9$k(B */
+			ccContextClear(buf);
+			continue;
+		}
+		ccContextAppend(buf, c);
+		(*buf->insertchar)(c, buf->client_data);
+	}
+}
+
+/* getModeSwitchMask -- mode-switch $B$N%b%G%#%U%!%$%"%^%9%/$rD4$Y$k(B */
+int getModeSwitchMask(dpy)
+Display *dpy;
+{
+	KeyCode	modeswkey;
+	struct modesw {
+		Display		*dpy;
+		int		mode_switch;
+		struct modesw	*next;
+	} *msp;
+	static struct modesw	*modeswlist;
+
+	for (msp = modeswlist; msp != NULL; msp = msp->next) {
+		if (dpy == msp->dpy) return msp->mode_switch;
+	}
+	msp = (struct modesw *)Malloc(sizeof(struct modesw));
+	msp->dpy = dpy;
+	msp->next = modeswlist;
+	modeswlist = msp;
+
+	msp->mode_switch = 0;
+
+	if ((modeswkey = XKeysymToKeycode(dpy, XK_Mode_switch)) != 0) {
+		XModifierKeymap	*map = XGetModifierMapping(dpy);
+		int	keypermod = map->max_keypermod;
+		int	modbit;
+		int	i;
+
+		for (modbit = 3; modbit < 8; modbit++) {
+			for (i = 0; i < keypermod; i++) {
+				if (map->modifiermap[keypermod * modbit + i] == modeswkey) {
+					msp->mode_switch = 1 << modbit;
+					goto found;
+				}
+			}
+		}
+	found:
+		XFreeModifiermap(map);
+	}
+
+	return msp->mode_switch;
+}
+
+/*
+ *	Public Functions
+ */
+
+/* ccParseRule -- $BJQ49Dj5A%U%!%$%k$rFI$_9~$`(B */
+ccRule ccParseRule(deffile, errprint)
+char *deffile;		/* $BF~NOJ8;zJQ49Dj5A%U%!%$%k(B */
+void (*errprint)();	/* $B%(%i!<%a%C%;!<%8I=<(MQ%3!<%k%P%C%/(B */
+{
+	ccRule		rule;
+	extern char	*getenv();
+
+	/* $BJQ49Dj5A%U%!%$%k$NFI$_9~$_(B */
+	if (deffile == NULL) {
+		/* $B4D6-JQ?t(B CC_DEF $B$rD4$Y$k(B */
+		if ((deffile = getenv("CC_DEF")) == NULL) {
+			return (ccRule)NULL;
+		}
+	}
+
+	if (rule = findRule(deffile)) {
+		/* same rule found */
+		rule->refcnt++;
+		return rule;
+	}
+
+	/* ccRuleRec $B$N%"%m%1!<%H(B */
+	if ((rule = (ccRule)Malloc(sizeof(ccRuleRec))) == NULL) {
+		return (ccRule)NULL;
+	}
+
+	rule->errorfunc = errprint;
+	rule->rulefile = Malloc(Strlen(deffile) + 1);
+	if (rule->rulefile) {
+		(void)Strcpy(rule->rulefile, deffile);
+	}
+	rule->casesensitive = False;
+	rule->autofix = False;
+
+	if (readRuleFile(rule, deffile) < 0) {
+		Free(rule);
+		return (ccRule)NULL;
+	}
+
+	addRule(rule);
+
+	return rule;
+}
+
+/* ccCreateBuf -- $BJQ49%P%C%U%!$r:n$k(B */
+ccBuf ccCreateBuf(rule, csize, functable, nfunc,
+		  def_action, insert, delete, execute, autofix, modenotify,
+		  data)
+ccRule rule;		/* $B;HMQ$9$kF~NOJ8;zJQ49%k!<%k(B */
+int csize;		/* context size ($BJ8;z?t(B) */
+char *functable[];	/* $B%U%!%s%/%7%g%s!&%F!<%V%k(B */
+int nfunc;		/* functable $B$N%(%s%H%j?t(B */
+void (*def_action)();	/* $B%G%U%)%k%H!&%"%/%7%g%s!&%3!<%k%P%C%/(B */
+void (*insert)();	/* $BJ8;zF~NO%3!<%k%P%C%/(B */
+void (*delete)();	/* $BJ8;z:o=|%3!<%k%P%C%/(B */
+int (*execute)();	/* $B%U%!%s%/%7%g%s<B9T%3!<%k%P%C%/(B */
+void (*autofix)();	/* $B<+F03NDj%3!<%k%P%C%/(B */
+void (*modenotify)();	/* $B%b!<%IJQ99DLCN%3!<%k%P%C%/(B */
+caddr_t data;		/* callback $B%G!<%?(B */
+{
+	ccBuf	buf;
+	char	*funcnamep;
+	short	*functblp;
+	int	i, j;
+
+	/* ccBuf $B$N%"%m%1!<%H(B */
+	if ((buf = (ccBuf)Malloc(sizeof(ccBufRec))) == NULL) {
+		return (ccBuf)NULL;
+	}
+
+	buf->rule = rule;
+
+	/* context $B%P%C%U%!$N%"%m%1!<%H(B */
+	if (csize <= 0) csize = 1;
+	buf->context = (wchar *)Malloc(csize * sizeof(wchar));
+	if (buf->context == NULL) {
+		Free(buf);
+		return (ccBuf)NULL;
+	}
+	buf->contextend = buf->context;
+	buf->contextsize = csize;
+
+	/* function $B%3%s%P!<%H%F!<%V%k$N%"%m%1!<%H(B */
+	buf->functbl = (short *)Malloc(rule->nfunc * sizeof(short));
+	if (buf->functbl == NULL) {
+		Free(buf->context);
+		Free(buf);
+		return (ccBuf)NULL;
+	}
+	/* ccRule $B$KF~$C$F$$$k%U%!%s%/%7%g%sI=$H!"0z?t$GM?$($i$l$?(B
+	 * $B%U%!%s%/%7%g%sI=$+$i!"(BccRule $BFbIt$N%U%!%s%/%7%g%sHV9f$H(B
+	 * $B:#M?$($i$l$?%U%!%s%/%7%g%sHV9f$H$NBP1~I=$r:n$k(B
+	 */
+	funcnamep = rule->funcnamebuf;
+	functblp = buf->functbl;
+	for (i = rule->nfunc, functblp = buf->functbl; i > 0; i--, functblp++) {
+		for (j = 0; j < nfunc; j++) {
+			if (!strcmp(functable[j], funcnamep)) {
+				*functblp = j;
+				break;
+			}
+		}
+		if (j >= nfunc) *functblp = -1;
+
+		while (*funcnamep++)
+			;
+	}
+
+	buf->defaultaction = def_action;
+	buf->insertchar = insert;
+	buf->deletechar = delete;
+	buf->executefunction = execute;
+	buf->modenotify = modenotify;
+	buf->autofix = autofix;
+	buf->client_data = data;
+
+	/* $B%+%l%s%H%b!<%I$N@_Dj(B */
+	buf->previousmode = buf->currentmode = rule->initialmode;
+
+	buf->modifier = 0;
+
+	return buf;
+}
+
+/* ccFreeRule -- $B%k!<%k$r<N$F$k(B */
+void ccFreeRule(rule)
+ccRule rule;
+{
+	ModeTable	*modep;
+	int		i;
+
+	if (rule == NULL) return;
+	if (--rule->refcnt > 0) return;
+
+	deleteRule(rule);
+
+	for (modep = rule->modes, i = 0; i < rule->nmode; modep++, i++) {
+		Free(modep->name);
+		Free(modep->cdbuf);
+		Free(modep->prompt);
+	}
+	Free(rule->rulefile);
+	Free(rule->modes);
+	Free(rule->strbuf);
+	Free(rule->funcbuf);
+	Free(rule->funcnamebuf);
+	Free(rule);
+}
+
+/* ccDestroyBuf -- $BJQ49%P%C%U%!$r<N$F$k(B */
+void ccDestroyBuf(buf)
+ccBuf buf;
+{
+	if (buf == NULL) return;
+	Free(buf->context);
+	Free(buf->functbl);
+	Free(buf);
+}
+
+/* ccConvchar -- $BJQ49MQ%U%!%s%/%7%g%s(B */
+int ccConvchar(buf, event)
+ccBuf buf;
+XKeyPressedEvent *event;	/* $B%-!<%$%Y%s%H(B */
+{
+	int	r;
+	char	str[256];
+	char	*p;
+	int	nbytes;
+	int	n;
+	KeySym	ks1, ks2;
+	int	mask;
+
+	/* $B$H$j$"$($:(B LookupString $B$7$F$*$/(B */
+	nbytes = XLookupString(event, str, sizeof(str), &ks2, 0);
+
+	/* $BF~NO%-!<$r%b%G%#%U%!%$%d$D$-$K$9$k(B */
+	if (buf->modifier) {
+		if (!IsModifierKey(ks2)) {
+			event->state |= buf->modifier;
+			buf->modifier = 0;
+			nbytes = XLookupString(event, str, sizeof(str), &ks2, 0);
+		}
+	}
+
+	/* $B$^$:$O%$%Y%s%H%3!<%I$GJQ49$7$F$_$k(B */
+	r = -1;
+	mask = ccEncodeMask(event);
+
+	/* $B$^$:$O%b%G%#%U%!%$%"$r0l:]9MN8$7$J$$(B KeySym $B$r(B
+	 * $B%3!<%I$H$7$FJQ49$7$F$_$k(B
+	 */
+	ks1 = (ulong)XLookupKeysym(event, 0);
+	if (ks1 != NoSymbol) {
+		r = convchar(buf, (ulong)ks1 | (ulong)RAWKEY,
+			     mask, str, nbytes);
+	}
+
+	/* $B>e$,%^%C%A$7$J$1$l$P!"(BShift, Lock, ModeSwitch $B$r(B
+	 * $B9MN8$7$?(B KeySym ($B$D$^$j(B XLookupString() $B$,JV$9(B KeySym) $B$,(B
+	 * NoSymbol $B$G$J$1$l$P$=$N%3!<%I$GJQ49$7$F$_$k(B
+	 */
+	if (r < 0 && ks2 != NoSymbol) {
+		int	msw = getModeSwitchMask(event->display);
+
+		if (mask & (ShiftMask | LockMask | msw)) {
+			mask &= ~(ShiftMask | LockMask | msw);
+			r = convchar(buf, (ulong)ks2 | (ulong)RAWKEY,
+				     mask, str, nbytes);
+		}
+	}
+
+	if (r < 0) {
+		int	match = 0;
+
+		if (nbytes == 0) return 0;
+
+		/* ASCII $BI=5-$GJQ49$7$F$_$k(B */
+		p = str;
+		n = nbytes;
+		while (n-- > 0) {
+			r = convchar(buf, ccEncodeChar(*p), 0, p, 1);
+			if (r >= 0) match = 1;
+			p++;
+		}
+		if (!match) {
+			/* default action $B$N%U%!%s%/%7%g%s$r$h$V(B */
+			if (buf->defaultaction != NULL) {
+				(void)(*buf->defaultaction)(str, nbytes, buf->client_data);
+			}
+			return 0;
+		}
+	}
+	return 1;
+}
+
+/* ccGetMode -- $B8=:_$N%b!<%IHV9f$rJV$9(B */
+int ccGetMode(buf)
+ccBuf buf;
+{
+	return buf->currentmode;
+}
+
+/* ccGetModePrompt -- $B8=:_$N%b!<%I$N%W%m%s%W%HJ8;zNs$rJV$9(B */
+wchar *ccGetModePrompt(buf)
+ccBuf buf;
+{
+	return buf->rule->modes[buf->currentmode].prompt;
+}
+
+/* ccGetRule -- $BJQ49%P%C%U%!$G;H$o$l$F$$$kJQ49%k!<%k$rJV$9(B */
+ccRule ccGetRule(buf)
+ccBuf buf;
+{
+	return buf->rule;
+}
+
+/* ccContextAppend -- $B%3%s%F%-%9%H$K(B1$BJ8;z2C$($k(B */
+void ccContextAppend(buf, c)
+ccBuf buf;
+int c;
+{
+	wchar	*p;
+
+	/* $B<+F03NDj(B */
+	if (buf->context == buf->contextend &&
+	    buf->rule->autofix && buf->autofix) {
+		buf->autofix(buf->client_data);
+	}
+
+	/* $B%3%s%F%-%9%HJ8;zNs$KA^F~(B */
+	if (buf->contextend - buf->context < buf->contextsize) {
+		*buf->contextend++ = c;
+	} else {
+		/* $B%3%s%F%-%9%HJ8;zNs$,0lGU$J$N$G(B
+		 * $B@hF,$N#1J8;z$r<N$F$F$D$a$k(B
+		 */
+		p = buf->context + 1;
+		while (p < buf->contextend) {
+			*(p - 1) = *p;
+			p++;
+		}
+		/* $B$"$$$?=j$KA^F~(B */
+		*--p = c;
+	}
+}
+
+/* ccContextDelete -- $B%3%s%F%-%9%H$r(B1$BJ8;z:o=|$9$k(B */
+void ccContextDelete(buf)
+ccBuf buf;
+{
+	if (buf->contextend > buf->context)
+		buf->contextend--;
+}
+
+/* ccContextClear -- $B%3%s%F%-%9%H$r%/%j%"$9$k(B */
+void ccContextClear(buf)
+ccBuf buf;
+{
+	/* $B%b!<%I$,JQ$o$C$?;~$K$O<+F0E*$K%/%j%"$5$l$k$,$=$l0J30$K(B
+	 * $B8=:_$N%3%s%F%-%9%H$r6/@)E*$K%/%j%"$7$?$$>l9g$KMQ$$$k(B
+	 */
+	buf->contextend = buf->context;
+}
+
+/* ccContextSet -- $B%3%s%F%-%9%H$r%;%C%H$9$k(B */
+void ccContextSet(buf, cstr)
+ccBuf buf;
+wchar *cstr;
+{
+	int	len = wstrlen(cstr);
+	wchar	*p = buf->context;
+
+	if (len > buf->contextsize) {
+		cstr += len - buf->contextsize;
+		len = buf->contextsize;
+	}
+	while (len-- > 0) {
+		*p++ = *cstr++;
+	}
+}
+
+/* ccContextGet -- $B8=:_$N%3%s%F%-%9%H$rJV$9(B */
+void ccContextGet(buf, cstr)
+ccBuf buf;
+wchar	*cstr;
+{
+	register wchar	*wp = buf->context;
+
+	while (wp < buf->contextend)
+		*cstr++ = *wp++;
+	*cstr = 0;
+}
+
+
+/*
+ *	Obsolete Functions
+ */
+
+/* ccInit -- $BJQ49%k!<%k$rFI$_9~$s$G%P%C%U%!$r:n$k(B */
+ccBuf ccInit(deffile, contextsize, defactfunc, insertfunc, deletefunc, dofunc,
+	     errprint, functable, functablesize)
+char *deffile;
+int contextsize;
+void (*defactfunc)();
+void (*insertfunc)();
+void (*deletefunc)();
+int (*dofunc)();
+void (*errprint)();
+char *functable[];
+int functablesize;
+{
+	ccRule	rule;
+
+	if ((rule = ccParseRule(deffile, errprint)) == NULL) {
+		return (ccBuf)NULL;
+	}
+
+	return ccCreateBuf(rule, contextsize, functable, functablesize,
+			   defactfunc, insertfunc, deletefunc, dofunc,
+			   (void (*)())NULL, (void (*)())NULL, (caddr_t)NULL);
+}
+
+/* ccTerminate -- $BF~NOJ8;zJQ49$r=*N;$9$k(B */
+void ccTerminate(buf)
+ccBuf buf;
+{
+	ccFreeRule(buf->rule);
+	ccDestroyBuf(buf);
+}
+
+
+#ifdef DEBUG_CCONV
+/*
+ *	Debug Functions
+ */
+
+static void putws(s)
+wchar *s;
+{
+	unsigned char	line[256];
+
+	(void)convJWStoSJIS(s, line);
+	fputs(line, stdout);
+}
+
+static void puteuc(s)
+uchar *s;
+{
+	wchar	tmp[256];
+
+	(void)convEUCtoJWS(s, tmp);
+	putws(tmp);
+}
+
+void dumpRules(rule, mode)
+ccRule rule;
+int mode;
+{
+	int	nkey;
+	ModeTable	*modep;
+	ConvDesc	*cdp;
+	wchar		*strbuf = rule->strbuf;
+	ushort		*funcbuf = rule->funcbuf;
+	char		**funcnames;
+	wchar		*p, *q;
+	wchar		restmp[256];
+	ushort		*funcp;
+	int	i, j;
+
+	funcnames = (char **)__builtin_alloca(rule->nfunc * sizeof(char *));
+{	char	*cp, **fnp;
+	cp = rule->funcnamebuf;
+	fnp = funcnames;
+	for (i = 0; i < rule->nfunc; i++) {
+		*fnp++ = cp;
+		while (*cp++)
+			;
+	}
+}
+
+	if (mode < 0 || mode >= rule->nmode) {
+		printf("No such mode %d\n", mode);
+		return;
+	}
+	modep = &rule->modes[mode];
+
+	printf("mode: %s (%d) prompt: ", modep->name, mode);
+	putws(modep->prompt);
+	if (modep->fallthrough != NOMODE) {
+		printf(" fallthrough: %d", modep->fallthrough);
+	}
+	putchar('\n');
+	cdp = modep->cdbuf;
+	for (i = 0; i < modep->nrule; i++) {
+		printf("rule[%d]: \"", i);
+		putws(strbuf + cdp->context);
+		printf("\"\t");
+		if (cdp->key & RAWKEY) {
+			ulong	key = cdp->key & ~RAWKEY;
+			int	mask = cdp->mask;
+			char	*keysymname;
+			if (mask & ShiftMask) printf("shift-");
+			if (mask & ControlMask) printf("control-");
+			if (mask & LockMask) printf("lock-");
+			if (mask & Mod1Mask) printf("mod1-");
+			if (mask & Mod2Mask) printf("mod2-");
+			if (mask & Mod3Mask) printf("mod3-");
+			if (mask & Mod4Mask) printf("mod4-");
+			if (mask & Mod5Mask) printf("mod5-");
+			keysymname = XKeysymToString((KeySym)key);
+			printf(keysymname ? keysymname : "<illegal keysym>");
+		} else if (cdp->key & METAC) {
+			switch (cdp->key & ~METAC) {
+			case META_ASCII:	printf("@ascii"); break;
+			case META_CONTROL:	printf("@control"); break;
+			case META_RAW:		printf("@raw"); break;
+			case META_ANY:		printf("@any"); break;
+			case META_FUNC:		printf("@func"); break;
+			case META_CURSOR:	printf("@cursor"); break;
+			case META_KEYPAD:	printf("@keypad"); break;
+			case META_MODIFIER:	printf("@modifier"); break;
+			case META_NONASCII:	printf("@non-ascii"); break;
+			case META_PRINTABLE:	printf("@printable"); break;
+			default:		printf("<illegal meta>");
+			}
+		} else if (cdp->key & PSEUDO) {
+			switch (cdp->key) {
+			case ENTERMODE:	printf("ENTERMODE"); break;
+			case EXITMODE:	printf("EXITMODE"); break;
+			default:	printf("<illegal pseudo>");
+			}
+		} else {
+			putchar('\'');
+			if (cdp->key >= 0x80) {
+				printf("\\x%x", cdp->key);
+			} else if (cdp->key < 0x20) {
+				putchar('^');
+				putchar(cdp->key + '@');
+			} else if (cdp->key == 0x7f) {
+				printf("^?");
+			} else {
+				putchar(cdp->key);
+			}
+			putchar('\'');
+		}
+		printf("\t\"");
+		p = restmp;
+		q = strbuf + cdp->result;
+		while (*q) {
+			if (*q == MATCHED_CHAR) {
+				*p++ = '&';
+			} else if (*q == CCLEAR_CHAR) {
+				*p++ = '/';
+			} else {
+				*p++ = *q;
+			}
+			q++;
+		}
+		*p = 0;
+		putws(restmp);
+		printf("\"\t");
+		funcp = funcbuf + cdp->function;
+		while (*funcp != ENDFUNC) {
+			if (*funcp == REDO) {
+				printf("redo ");
+			} else if (*funcp == PREVMODE) {
+				printf("goto prev ");
+			} else if (*funcp & MODECHANGE) {
+				int	gotomode = *funcp & ~MODECHANGE;
+				if (gotomode < 0 || gotomode >= rule->nmode) {
+					printf("<illegal goto>");
+				} else {
+					printf("goto %s ",
+					       rule->modes[gotomode].name);
+				}
+			} else {
+				if (*funcp >= rule->nfunc) {
+					printf("<illegal function> ");
+				} else {
+					printf("%s ", funcnames[*funcp]);
+				}
+			}
+			funcp++;
+		}
+		putchar('\n');
+		cdp++;
+	}
+	putchar('\n');
+}
+
+void dumpAllRules(rule)
+ccRule rule;
+{
+	int	i;
+
+	printf("** RULE DUMP **\n");
+	printf("number of modes: %d  initialmode: %s (%d)\n\n",
+	       rule->nmode,
+	       rule->modes[rule->initialmode].name,
+	       rule->initialmode);
+	for (i = 0; i < rule->nmode; i++) {
+		dumpRules(rule, i);
+	}
+	fflush(stdout);
+}
+#endif