view src/mule-wnnfns.c @ 2367:ecf1ebac70d8

[xemacs-hg @ 2004-11-04 23:05:23 by ben] commit mega-patch configure.in: Turn off -Winline and -Wchar-subscripts. Use the right set of cflags when compiling modules. Rewrite ldap configuration to separate the inclusion of lber (needed in recent Cygwin) from the basic checks for the needed libraries. add a function for MAKE_JUNK_C; initially code was added to generate xemacs.def using this, but it will need to be rewritten. add an rm -f for junk.c to avoid weird Cygwin bug with cp -f onto an existing file. Sort list of auto-detected functions and eliminate unused checks for stpcpy, setlocale and getwd. Add autodetection of Cygwin scanf problems BETA: Rewrite section on configure to indicate what flags are important and what not. digest-doc.c, make-dump-id.c, profile.c, sorted-doc.c: Add proper decls for main(). make-msgfile.c: Document that this is old junk. Move proposal to text.c. make-msgfile.lex: Move proposal to text.c. make-mswin-unicode.pl: Convert error-generating code so that the entire message will be seen as a single unrecognized token. mule/mule-ccl.el: Update docs. lispref/mule.texi: Update CCL docs. ldap/eldap.c: Mule-ize. Use EXTERNAL_LIST_LOOP_2 instead of deleted EXTERNAL_LIST_LOOP. * XEmacs 21.5.18 "chestnut" is released. --------------------------------------------------------------- MULE-RELATED WORK: --------------------------------------------------------------- --------------------------- byte-char conversion --------------------------- buffer.c, buffer.h, insdel.c, text.c: Port FSF algorithm for byte-char conversion, replacing broken previous version. Track the char position of the gap. Add functions to do char-byte conversion downwards as well as upwards. Move comments about algorithm workings to internals manual. --------------------------- work on types --------------------------- alloc.c, console-x-impl.h, dump-data.c, dump-data.h, dumper.c, dialog-msw.c, dired-msw.c, doc.c, editfns.c, esd.c, event-gtk.h, event-msw.c, events.c, file-coding.c, file-coding.h, fns.c, glyphs-eimage.c, glyphs-gtk.c, glyphs-msw.c, glyphs-shared.c, glyphs-x.c, glyphs.c, glyphs.h, gui.c, hpplay.c, imgproc.c, intl-win32.c, lrecord.h, lstream.c, keymap.c, lisp.h, libsst.c, linuxplay.c, miscplay.c, miscplay.h, mule-coding.c, nas.c, nt.c, ntheap.c, ntplay.c, objects-msw.c, objects-tty.c, objects-x.c, print.c, process-nt.c, process.c, redisplay.h, select-common.h, select-gtk.c, select-x.c, sgiplay.c, sound.c, sound.h, sunplay.c, sysfile.h, sysdep.c, syswindows.h, text.c, unexnt.c, win32.c, xgccache.c: Further work on types. This creates a full set of types for all the basic semantics of `char' that I have so far identified, so that its semantics can always be identified for the purposes of proper Mule-safe code, and the raw use of `char' always avoided. (1) More type renaming, for consistency of naming. Char_ASCII -> Ascbyte UChar_ASCII -> UAscbyte Char_Binary -> CBinbyte UChar_Binary -> Binbyte SChar_Binary -> SBinbyte (2) Introduce Rawbyte, CRawbyte, Boolbyte, Chbyte, UChbyte, and Bitbyte and use them. (3) New types Itext, Wexttext and Textcount for separating out the concepts of bytes and textual units (different under UTF-16 and UTF-32, which are potential internal encodings). (4) qxestr*_c -> qxestr*_ascii. lisp.h: New; goes with other qxe() functions. #### Maybe goes in a different section. lisp.h: Group generic int-type defs together with EMACS_INT defs. lisp.h: * lisp.h (WEXTTEXT_IS_WIDE) New defns. lisp.h: New type to replace places where int occurs as a boolean. It's signed because occasionally people may want to use -1 as an error value, and because unsigned ints are viral -- see comments in the internals manual against using them. dynarr.c: int -> Bytecount. --------------------------- Mule-izing --------------------------- device-x.c: Partially Mule-ize. dumper.c, dumper.h: Mule-ize. Use Rawbyte. Use stderr_out not printf. Use wext_*(). sysdep.c, syswindows.h, text.c: New Wexttext API for manipulation of external text that may be Unicode (e.g. startup code under Windows). emacs.c: Mule-ize. Properly deal with argv in external encoding. Use wext_*() and Wexttext. Use Rawbyte. #if 0 some old junk on SCO that is unlikely to be correct. Rewrite allocation code in run-temacs. emacs.c, symsinit.h, win32.c: Rename win32 init function and call it even earlier, to initialize mswindows_9x_p even earlier, for use in startup code (XEUNICODE_P). process.c: Use _wenviron not environ under Windows, to get Unicode environment variables. event-Xt.c: Mule-ize drag-n-drop related stuff. dragdrop.c, dragdrop.h, frame-x.c: Mule-ize. text.h: Add some more stand-in defines for particular kinds of conversion; use in Mule-ization work in frame-x.c etc. --------------------------- Freshening --------------------------- intl-auto-encap-win32.c, intl-auto-encap-win32.h: Regenerate. --------------------------- Unicode-work --------------------------- intl-win32.c, syswindows.h: Factor out common options to MultiByteToWideChar and WideCharToMultiByte. Add convert_unicode_to_multibyte_malloc() and convert_unicode_to_multibyte_dynarr() and use. Add stuff for alloca() conversion of multibyte/unicode. alloc.c: Use dfc_external_data_len() in case of unicode coding system. alloc.c, mule-charset.c: Don't zero out and reinit charset Unicode tables. This fucks up dump-time loading. Anyway, either we load them at dump time or run time, never both. unicode.c: Dump the blank tables as well. --------------------------------------------------------------- DOCUMENTATION, MOSTLY MULE-RELATED: --------------------------------------------------------------- EmacsFrame.c, emodules.c, event-Xt.c, fileio.c, input-method-xlib.c, mule-wnnfns.c, redisplay-gtk.c, redisplay-tty.c, redisplay-x.c, regex.c, sysdep.c: Add comment about Mule work needed. text.h: Add more documentation describing why DFC routines were not written to return their value. Add some other DFC documentation. console-msw.c, console-msw.h: Add pointer to docs in win32.c. emacs.c: Add comments on sources of doc info. text.c, charset.h, unicode.c, intl-win32.c, intl-encap-win32.c, text.h, file-coding.c, mule-coding.c: Collect background comments and related to text matters and internationalization, and proposals for work to be done, in text.c or Internals manual, stuff related to specific textual API's in text.h, and stuff related to internal implementation of Unicode conversion in unicode.c. Put lots of pointers to the comments to make them easier to find. s/mingw32.h, s/win32-common.h, s/win32-native.h, s/windowsnt.h, win32.c: Add bunches of new documentation on the different kinds of builds and environments under Windows and how they work. Collect this info in win32.c. Add pointers to these docs in the relevant s/* files. emacs.c: Document places with long comments. Remove comment about exiting, move to internals manual, put in pointer. event-stream.c: Move docs about event queues and focus to internals manual, put in pointer. events.h: Move docs about event stream callbacks to internals manual, put in pointer. profile.c, redisplay.c, signal.c: Move documentation to the Internals manual. process-nt.c: Add pointer to comment in win32-native.el. lisp.h: Add comments about some comment conventions. lisp.h: Add comment about the second argument. device-msw.c, redisplay-msw.c: @@#### comments are out-of-date. --------------------------------------------------------------- PDUMP WORK (MOTIVATED BY UNICODE CHANGES) --------------------------------------------------------------- alloc.c, buffer.c, bytecode.c, console-impl.h, console.c, device.c, dumper.c, lrecord.h, elhash.c, emodules.h, events.c, extents.c, frame.c, glyphs.c, glyphs.h, mule-charset.c, mule-coding.c, objects.c, profile.c, rangetab.c, redisplay.c, specifier.c, specifier.h, window.c, lstream.c, file-coding.h, file-coding.c: PDUMP: Properly implement dump_add_root_block(), which never worked before, and is necessary for dumping Unicode tables. Pdump name changes for accuracy: XD_STRUCT_PTR -> XD_BLOCK_PTR. XD_STRUCT_ARRAY -> XD_BLOCK_ARRAY. XD_C_STRING -> XD_ASCII_STRING. *_structure_* -> *_block_*. lrecord.h: some comments added about dump_add_root_block() vs dump_add_root_block_ptr(). extents.c: remove incorrect comment about pdump problems with gap array. --------------------------------------------------------------- ALLOCATION --------------------------------------------------------------- abbrev.c, alloc.c, bytecode.c, casefiddle.c, device-msw.c, device-x.c, dired-msw.c, doc.c, doprnt.c, dragdrop.c, editfns.c, emodules.c, file-coding.c, fileio.c, filelock.c, fns.c, glyphs-eimage.c, glyphs-gtk.c, glyphs-msw.c, glyphs-x.c, gui-msw.c, gui-x.c, imgproc.c, intl-win32.c, lread.c, menubar-gtk.c, menubar.c, nt.c, objects-msw.c, objects-x.c, print.c, process-nt.c, process-unix.c, process.c, realpath.c, redisplay.c, search.c, select-common.c, symbols.c, sysdep.c, syswindows.h, text.c, text.h, ui-byhand.c: New macros {alloca,xnew}_{itext,{i,ext,raw,bin,asc}bytes} for more convenient allocation of these commonly requested items. Modify functions to use alloca_ibytes, alloca_array, alloca_extbytes, xnew_ibytes, etc. also XREALLOC_ARRAY, xnew. alloc.c: Rewrite the allocation functions to factor out repeated code. Add assertions for freeing dumped data. lisp.h: Moved down and consolidated with other allocation stuff. lisp.h, dynarr.c: New functions for allocation that's very efficient when mostly in LIFO order. lisp.h, text.c, text.h: Factor out some stuff for general use by alloca()-conversion funs. text.h, lisp.h: Fill out convenience routines for allocating various kinds of bytes and put them in lisp.h. Use them in place of xmalloc(), ALLOCA(). text.h: Fill out the convenience functions so the _MALLOC() kinds match the alloca() kinds. --------------------------------------------------------------- ERROR-CHECKING --------------------------------------------------------------- text.h: Create ASSERT_ASCTEXT_ASCII() and ASSERT_ASCTEXT_ASCII_LEN() from similar Eistring checkers and change the Eistring checkers to use them instead. --------------------------------------------------------------- MACROS IN LISP.H --------------------------------------------------------------- lisp.h: Redo GCPRO declarations. Create a "base" set of functions that can be used to generate any kind of gcpro sets -- regular, ngcpro, nngcpro, private ones used in GC_EXTERNAL_LIST_LOOP_2. buffer.c, callint.c, chartab.c, console-msw.c, device-x.c, dialog-msw.c, dired.c, extents.c, ui-gtk.c, rangetab.c, nt.c, mule-coding.c, minibuf.c, menubar-msw.c, menubar.c, menubar-gtk.c, lread.c, lisp.h, gutter.c, glyphs.c, glyphs-widget.c, fns.c, fileio.c, file-coding.c, specifier.c: Eliminate EXTERNAL_LIST_LOOP, which does not check for circularities. Use EXTERNAL_LIST_LOOP_2 instead or EXTERNAL_LIST_LOOP_3 or EXTERNAL_PROPERTY_LIST_LOOP_3 or GC_EXTERNAL_LIST_LOOP_2 (new macro). Removed/redid comments on EXTERNAL_LIST_LOOP. --------------------------------------------------------------- SPACING FIXES --------------------------------------------------------------- callint.c, hftctl.c, number-gmp.c, process-unix.c: Spacing fixes. --------------------------------------------------------------- FIX FOR GEOMETRY PROBLEM IN FIRST FRAME --------------------------------------------------------------- unicode.c: Add workaround for newlib bug in sscanf() [should be fixed by release 1.5.12 of Cygwin]. toolbar.c: bug fix for problem of initial frame being 77 chars wide on Windows. will be overridden by my other ws. --------------------------------------------------------------- FIX FOR LEAKING PROCESS HANDLES: --------------------------------------------------------------- process-nt.c: Fixes for leaking handles. Inspired by work done by Adrian Aichner <adrian@xemacs.org>. --------------------------------------------------------------- FIX FOR CYGWIN BUG (Unicode-related): --------------------------------------------------------------- unicode.c: Add workaround for newlib bug in sscanf() [should be fixed by release 1.5.12 of Cygwin]. --------------------------------------------------------------- WARNING FIXES: --------------------------------------------------------------- console-stream.c: `reinit' is unused. compiler.h, event-msw.c, frame-msw.c, intl-encap-win32.c, text.h: Add stuff to deal with ANSI-aliasing warnings I got. regex.c: Gather includes together to avoid warning. --------------------------------------------------------------- CHANGES TO INITIALIZATION ROUTINES: --------------------------------------------------------------- buffer.c, emacs.c, console.c, debug.c, device-x.c, device.c, dragdrop.c, emodules.c, eval.c, event-Xt.c, event-gtk.c, event-msw.c, event-stream.c, event-tty.c, events.c, extents.c, faces.c, file-coding.c, fileio.c, font-lock.c, frame-msw.c, glyphs-widget.c, glyphs.c, gui-x.c, insdel.c, lread.c, lstream.c, menubar-gtk.c, menubar-x.c, minibuf.c, mule-wnnfns.c, objects-msw.c, objects.c, print.c, scrollbar-x.c, search.c, select-x.c, text.c, undo.c, unicode.c, window.c, symsinit.h: Call reinit_*() functions directly from emacs.c, for clarity. Factor out some redundant init code. Move disallowed stuff that had crept into vars_of_glyphs() into complex_vars_of_glyphs(). Call init_eval_semi_early() from eval.c not in the middle of vars_of_() in emacs.c since there should be no order dependency in the latter calls. --------------------------------------------------------------- ARMAGEDDON: --------------------------------------------------------------- alloc.c, emacs.c, lisp.h, print.c: Rename inhibit_non_essential_printing_operations to inhibit_non_essential_conversion_operations. text.c: Assert on !inhibit_non_essential_conversion_operations. console-msw.c, print.c: Don't do conversion in SetConsoleTitle or FindWindow to avoid problems during armageddon. Put #errors for NON_ASCII_INTERNAL_FORMAT in places where problems would arise. --------------------------------------------------------------- CHANGES TO THE BUILD PROCEDURE: --------------------------------------------------------------- config.h.in, s/cxux.h, s/usg5-4-2.h, m/powerpc.h: Add comment about correct ordering of this file. Rearrange everything to follow this -- put all #undefs together and before the s&m files. Add undefs for HAVE_ALLOCA, C_ALLOCA, BROKEN_ALLOCA_IN_FUNCTION_CALLS, STACK_DIRECTION. Remove unused HAVE_STPCPY, HAVE_GETWD, HAVE_SETLOCALE. m/gec63.h: Deleted; totally broken, not used at all, not in FSF. m/7300.h, m/acorn.h, m/alliant-2800.h, m/alliant.h, m/altos.h, m/amdahl.h, m/apollo.h, m/att3b.h, m/aviion.h, m/celerity.h, m/clipper.h, m/cnvrgnt.h, m/convex.h, m/cydra5.h, m/delta.h, m/delta88k.h, m/dpx2.h, m/elxsi.h, m/ews4800r.h, m/gould.h, m/hp300bsd.h, m/hp800.h, m/hp9000s300.h, m/i860.h, m/ibmps2-aix.h, m/ibmrs6000.h, m/ibmrt-aix.h, m/ibmrt.h, m/intel386.h, m/iris4d.h, m/iris5d.h, m/iris6d.h, m/irist.h, m/isi-ov.h, m/luna88k.h, m/m68k.h, m/masscomp.h, m/mg1.h, m/mips-nec.h, m/mips-siemens.h, m/mips.h, m/news.h, m/nh3000.h, m/nh4000.h, m/ns32000.h, m/orion105.h, m/pfa50.h, m/plexus.h, m/pmax.h, m/powerpc.h, m/pyrmips.h, m/sequent-ptx.h, m/sequent.h, m/sgi-challenge.h, m/symmetry.h, m/tad68k.h, m/tahoe.h, m/targon31.h, m/tekxd88.h, m/template.h, m/tower32.h, m/tower32v3.h, m/ustation.h, m/vax.h, m/wicat.h, m/xps100.h: Delete C_ALLOCA, HAVE_ALLOCA, STACK_DIRECTION, BROKEN_ALLOCA_IN_FUNCTION_CALLS. All of this is auto-detected. When in doubt, I followed recent FSF sources, which also have these things deleted.
author ben
date Thu, 04 Nov 2004 23:08:28 +0000
parents 34abfb24e891
children c0934cef10c6
line wrap: on
line source

/* -*- coding: iso-2022-jp -*-
   Copyright (C) 1995 Free Software Foundation, Inc.
   Copyright (C) 1995 Sun Microsystems, Inc.

This file is part of XEmacs.

XEmacs is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.

XEmacs is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with XEmacs; see the file COPYING.  If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.  */

/* Synched up with: Mule 2.3.  Not in FSF. */

/*      Jserver Interface for Mule
        Coded by Yutaka Ishikawa at ETL (yisikawa@etl.go.jp)
                 Satoru Tomura   at ETL (tomura@etl.go.jp)
	Modified for Wnn4 library by
		 Toshiaki Shingu (shingu@cpr.canon.co.jp)
		 Hiroshi Kuribayashi (kuri@nff.ncl.omron.co.jp) */

/*
 *	Functions defined in this file are
 *	   (wnn-server-open wnn-host-name login-name)
 *		wnn-host-name: STRING or NIL
 *		login-name: STRING
 *		RETURNS: BOOLEAN
 *		DESCRIPTION:
 *		jserver $B$H@\B3$7!"%5!<%P!<FbIt$K@5JQ49!?5UJQ49#2$D$N4D6-$r(B
 *		$B:n$k!#%(%i!<$N;~$O(B nil $B$rJV$9!#(B
 *
 *	   (wnn-server-close)
 *		RETURNS: BOOLEAN
 *		DESCRIPTION:
 *		jserver $B$H$N@\B3$r@Z$k!#<-=q!"IQEY$O%;!<%V$5$l$J$$!#(B
 *
 *	   (wnn-server-dict-add dict-file-name hindo-file-name priority
 *		dict-file-mode hindo-file-mode pw1 pw2)
 *		dict-file-name: STRING
 *		hindo-file-name: STRING or NULL-STRING
 *		priority: INTEGER
 *		dict-file-mode: BOOLEAN
 *		hindo-file-mode: BOOLEAN
 *		pw1: STRING or NIL
 *		pw2: STRING or NIL
 *		DESCRIPTION:
 *		$B<-=q%U%!%$%kL>!"IQEY%U%!%$%kL>!"M%@hEY!"<-=q%U%!%$%k%b!<%I(B
 *		$BIQEY%U%!%$%k%b!<%I$G;XDj$7$?<-=q$r%P%C%U%!$KDI2C$9$k!#(B
 *		pw1, pw2 $B$O<-=q%U%!%$%k!"IQEY%U%!%$%k$N%Q%9%o!<%I!#(B
 *
 *	   (wnn-server-dict-delete dic-no)
 *		dic-no: INTEGER
 *		RETURNS: $B%(%i!<$N;~(B nil
 *		DESCRIPTION: dic-no $B$N<-=qHV9f$N<-=q$r!"%P%C%U%!$+$i(B
 *		$B:o=|$9$k!#(B
 *
 *	   (wnn-server-dict-list)
 *		RETURNS: ((dic-no1 file-name1 comment1 word-no1 nice1)
 *			  (dic-no2 file-name2 comment2 word-no2 nice2)...)
 *		DESCRIPTION: $B%P%C%U%!>e$N<-=q$N%j%9%H$rF@$k!#(B
 *
 *	   (wnn-server-dict-comment dic-no comment)
 *		RETURNS: $B%(%i!<$N;~(B nil
 *		DESCRIPTION: dic-no $B$N<-=q$K%3%a%s%H$r$D$1$k!#(B
 *
 *	   (wnn-server-set-rev rev)
 *		rev: BOOLEAN
 *		rev $B$,(B nil $B$N;~$O@5JQ49!"$=$l0J30$N;~$O5UJQ49(B
 *
 *	   (wnn-server-henkan-begin henkan-string)
 *		henkan-string: STRING
 *		RETURNS: bunsetu-suu
 *		DESCRIPTION:
 *		$B2>L>4A;zJQ49$r$7!"Bh0l8uJd$NJ8@a?t$rJV$9!#(B
 *
 *	   (wnn-server-zenkouho bunsetu-no dai)
 *		bunsetu-no: INTEGER
 *		dai: BOOLEAN
 *		RETURNS: offset
 *		DESCRIPTION:
 *		$BJ8@aHV9f$G;XDj$5$l$?J8@a$NA48uJd$r$H$j$@$7(B
 *		$B!"8=:_$N%*%U%;%C%H$rJV$9!#(B
 *
 *	   (wnn-server-get-zenkouho offset)
 *		bunsetu-no: INTEGER
 *		dai: BOOLEAN
 *		RETURNS: list of zenkouho
 *		DESCRIPTION:
 *		$B%*%U%;%C%H$G;XDj$5$l$?8uJd$rF@$k!#(B
 *
 *	   (wnn-server-zenkouho-bun)
 *		RETURNS: INTEGER
 *		DESCRIPTION:
 *		$BA48uJd$rI=<($7$F$$$kJ8@aHV9f$rF@$k!#(B
 *
 *	   (wnn-server-zenkouho-suu)
 *		RETURNS: INTEGER
 *		DESCRIPTION:
 *		$BA48uJd$rI=<($7$F$$$kJ8@a$NA48uJd?t$rF@$k!#(B
 *
 *	   (wnn-server-dai-top bun-no)
 *		bun-no: INTEGER
 *		RETURNS: BOOLEAN
 *		DESCRIPTION:
 *		$BJ8@a$,BgJ8@a$N@hF,$J$i(B t
 *
 *	   (wnn-server-dai-end bun-no)
 *		bun-no: INTEGER
 *		RETURNS: INTEGER
 *		DESCRIPTION:
 *		$B<!$NBgJ8@a$NJ8@aHV9f$rF@$k!#(B
 *
 *	   (wnn-server-henkan-kakutei kouho-no dai)
 *		kouho-no: INTEGER
 *		dai: BOOLEAN
 *		RETURNS: BOOLEAN
 *		DESCRIPTION:
 *		$B8uJdHV9f$G<($5$l$?8uJd$rA*Br$9$k!#(B
 *		(wnn-server-zenkouho) $B$r8F$s$F$+$i$G$J$$$H$$$1$J$$!#(B
 *
 *	   (wnn-server-bunsetu-henkou bunsetu-no bunsetu-length dai)
 *		bunsetu-no: INTEGER
 *		bunsetu-length: INTEGER
 *		dai: BOOLEAN
 *		RETURNS:
 *		DESCRIPTION:
 *		$BJ8@a$ND9$5$rJQ99$9$k!#(B
 *
 *         (wnn-bunsetu-kouho-inspect bunsetu-no)
 *              bunsetu-no: INTEGER
 *              RETURNS: (kanji yomi jisho-no serial-no hinsi hindo
 *		ima hyoka daihyoka kangovect)
 *		DESCRIPTION:
 *		$BJ8@a$N?'!9$J>pJs$rJQ49%P%C%U%!$+$i$H$j=P$9!#(B
 *
 *	   (wnn-server-henkan-quit)
 *		RETURNS: BOOLEAN
 *		DESCRIPTION:
 *		$B2?$b$7$J$$!#(B
 *
 *	   (wnn-server-bunsetu-kanji bun-no)
 *		RETURNS: (bunsetu-kanji length)
 *		DESCRIPTION:
 *
 *	   (wnn-server-bunsetu-yomi bun-no)
 *		RETURNS: (bunsetu-yomi length)
 *		DESCRIPTION:
 *
 *	   (wnn-server-bunsetu-suu)
 *		RETURNS: bunsetu-suu
 *		DESCRIPTION:
 *
 *	   (wnn-server-hindo-update &optional bunsetu-no)
 *              bunsetu-no: INTEGER
 *		RETURNS: BOOLEAN
 *		DESCRIPTION:
 *		$BIQEY>pJs$r99?7$9$k!#(B
 *
 *	   (wnn-server-word-add dic-no tango yomi comment hinsi)
 *		dic-no: INTEGER
 *		tango: STRING
 *		yoni: STRING
 *		comment: STRING
 *		hinsi: INTEGER
 *		RETURNS: BOOLEAN
 *		DESCRIPTION:
 *		$B<-=q$KC18l$rEPO?$9$k!#(B
 *
 *	   (wnn-server-word-delete dic-no entry)
 *		dic-no: INTEGER
 *		entry: INTEGER
 *		RETURNS: BOOLEAN
 *		DESCRIPTION:
 *		$B<-=q$+$i%(%s%H%jHV9f$G<($5$l$kC18l$r:o=|$9$k!#(B
 *
 *	   (wnn-server-word-use dic-no entry)
 *		dic-no: INTEGER
 *		entry: INTEGER
 *		RETURNS: BOOLEAN
 *		DESCRIPTION:
 *		$B<-=q$+$i%(%s%H%jHV9f$G<($5$l$kC18l$NM-8z!?L58z$r%H%0%k$9$k!#(B
  *
 *	   (wnn-server-word-info dic-no entry)
 *		dic-no: INTEGER
 *		entry: INTEGER
 *		RETURNS: (yomi kanji comment hindo hinsi)
 *		DESCRIPTION:
 *		$B<-=q$+$i%(%s%H%jHV9f$G<($5$l$kC18l$N>pJs$rF@$k!#(B
 *
 *	   (wnn-server-word-hindo-set dic-no entry hindo)
 *		dic-no: INTEGER
 *		entry: INTEGER
 *		hindo: INTEGER
 *		RETURNS: BOOLEAN
 *		DESCRIPTION:
 *		$B<-=q$+$i%(%s%H%jHV9f$G<($5$l$kC18l$NIQEY$r@_Dj$9$k!#(B
 *
 *	   (wnn-server-word-search yomi)
 *		yomi: STRING
 *		RETURNS: a LIST of dict-joho
 *		DESCRIPTION:
 *		$BA4$F$N<-=q$+$iC18l8!:w$r9T$J$&!#(B
 *
 *         (wnn-server-dict-save)
 *              RETURNS: BOOLEAN
 *              DESCRIPTION:
 *		$BA4$F$N<-=q$HIQEY%U%!%$%k$r%;!<%V$9$k!#(B
 *
 *	   (wnn-server-get-param)
 *		RETURNS: (n nsho p1 p2 p3 ... p15)
 *		DESCRIPTION: $BJQ49%Q%i%a!<%?$rF@$k!#(B
 *
 *	   (wnn-server-set-param n sho p1 ... p15)
 *		RETURNS: $B%(%i!<$N;~(B nil
 *		DESCRIPTION: $BJQ49%Q%i%a!<%?$r@_Dj$9$k!#(B
 *
 *	   (wnn-server-get-msg error-no)
 *		RETURNS: $B%(%i!<%a225;!<%8(B
 *		DESCRIPTION: $B%(%i!<HV9f$+$i%a%C%;!<%8$rF@$k!#(B
 *
 *	   (wnn-server-fuzokugo-set fname)
 *		RETURNS: $B%(%i!<$N;~(B nil
 *		DESCRIPTION: $B%P%C%U%!$KImB08l%U%!%$%k$rFI$_9~$`!#(B
 *
 *	   (wnn-server-fuzokugo-get)
 *		RETURNS: $B%U%!%$%kL>(B
 *		DESCRIPTION: $B%P%C%U%!$NImB08l%U%!%$%kL>$rF@$k!#(B
 *
 *	   (wnn-server-isconnect)
 *		RETURNS: $B%3%M%/%H$7$F$l$P(B t, $B$7$F$J$1$l$P(B nil
 *		DESCRIPTION: $B%5!<%P$H7Q$C$F$$$k$+D4$Y$k!#(B
 *
 *	   (wnn-server-hinsi-dicts hinsi-no)
 *		RETURNS: (dic-no1 dic-no2 ...)
 *		DESCRIPTION: hinsi-no $B$NIJ;l$,EPO?$G$-$k<-=q$N%j%9%H$rF@$k!#(B
 *		hinsi-no = -1 $B$N$H$-$K$O!"EPO?2DG=$JA4<-=q$rF@$k!#(B
 *
 *	   (wnn-server-hinsi-list dic-no name)
 *		RETURNS: (name1 name2 ... )
 *		DESCRIPTION: dic-no $B$N<-=q$G!"IJ;l%N!<%I$KB0$9$k(B
 *		$BIJ;l%N!<%I!JL>!K$N%j%9%H$rF@$k!#(B
 *		$BIJ;lL>$rM?$($?;~$O!"#0$rJV$9!#(B
 *
 *	   (wnn-server-hinsi-name hinsi-no)
 *		RETURNS: hinsi-name
 *		DESCRIPTION: $BIJ;lHV9f$+$iL>A0$r<h$k!#(B
 *
 *	   (wnn-server-hinsi-number hinsi-name)
 *		RETURNS: hinsi-no
 *		DESCRIPTION: $BIJ;lL>$rIJ;lHV9f$KJQ49$9$k!#(B
 *
 *         (wnn-server-version)
 *              RETURNS: version ID(int)
 *
 */

#include <config.h>
#include "lisp.h"

#include "buffer.h"
#include "window.h"
#include "sysdep.h"

#include "wnn/commonhd.h"
#include "charset.h"
#include "wnn/jllib.h"
#include "wnn/cplib.h"

/* UCHAR $B$,Fs=EDj5A$5$l$k$N$G(B */
#define _UCHAR_T

#define EGG_TIMEOUT 5
#define NSERVER 4
#define WNNSERVER_J 0
#define WNNSERVER_C 1
#define WNNSERVER_T 2
#define WNNSERVER_K 3

int check_wnn_server_type (void);
void w2m (w_char *wp, unsigned char *mp, unsigned char lb);
void m2w (unsigned char *mp, w_char *wp);
void w2y (w_char *w);
void c2m (unsigned char *cp, unsigned char *mp, unsigned char lb);
static void puts2 (char *s);
static int dai_end (int no, int server);
static int yes_or_no (unsigned char *s);

 /* Why doesn't wnn have a prototype for these? */
typedef unsigned int letter;
int cwnn_yincod_pzy(w_char *, w_char, int);
int cwnn_pzy_yincod(letter *, letter *, int);

static struct wnn_buf *wnnfns_buf[NSERVER];
static struct wnn_env *wnnfns_env_norm[NSERVER];
static struct wnn_env *wnnfns_env_rev[NSERVER];
static int wnnfns_norm;
static unsigned char lb_wnn_server_type[NSERVER] =
{LEADING_BYTE_JAPANESE_JISX0208, LEADING_BYTE_CHINESE_GB2312, LEADING_BYTE_THAI_TIS620, LEADING_BYTE_KOREAN_KSC5601};

/* Lisp Variables and Constants Definition */
Lisp_Object	Qjserver;
Lisp_Object	Qcserver;
/*Lisp_Object	Qtserver;*/
Lisp_Object	Qkserver;
Lisp_Object	Qwnn_no_uniq;
Lisp_Object	Qwnn_uniq;
Lisp_Object	Qwnn_uniq_kanji;
Lisp_Object	Qwnn_n, Qwnn_nsho, Qwnn_hindo, Qwnn_len, Qwnn_jiri, Qwnn_flag;
Lisp_Object	Qwnn_jisho, Qwnn_sbn, Qwnn_dbn_len, Qwnn_sbn_cnt, Qwnn_suuji;
Lisp_Object	Qwnn_kana, Qwnn_eisuu, Qwnn_kigou, Qwnn_toji_kakko, Qwnn_fuzokogo, Qwnn_kaikakko;
Lisp_Object	Vwnn_server_type;
Lisp_Object	Vcwnn_zhuyin;
Lisp_Object	Vwnnenv_sticky;
Lisp_Object	Vwnn_uniq_level;
Fixnum		lb_sisheng;

/* Lisp functions definition */

DEFUN ("wnn-server-open", Fwnn_open, 2, 2, 0, /*
Connect to jserver of host HNAME, make an environment with
login name LNAME in the server.
Return nil if error occurs.
*/
     (hname, lname))
{
  char *envname;
  char *langname;
  char *hostname;
  int	snum;
  int size;
  CHECK_STRING (lname);

  snum = check_wnn_server_type ();
  switch (snum)
    {
    case WNNSERVER_J:
      langname = "ja_JP";
      break;
    case WNNSERVER_C:
      langname = "zh_CN";
      break;
/*
    case WNNSERVER_T:
    strcpy (langname, "zh_TW");
    break;
    */
    case WNNSERVER_K:
      langname = "ko_KR";
      break;
    case -1:
    default:
      return Qnil;
    }
  size = XSTRING_LENGTH (lname) > 1024 ? 1026 : XSTRING_LENGTH (lname) + 2;
  /* !!#### */
  envname = (char *) ALLOCA (size);
  strncpy (envname, (char *) XSTRING_DATA (lname), size-2);
  envname[size-2] = '\0';
  if (NILP (hname)) hostname = "";
  else
    {
      CHECK_STRING (hname);
      size = XSTRING_LENGTH(hname) > 1024 ? 1025 : XSTRING_LENGTH(hname) + 1;

      hostname = (char *) ALLOCA (size);
      strncpy (hostname, (char *) XSTRING_DATA (hname), size-1);
      hostname[size-1] = '\0';
    }
  CHECK_STRING (lname);
  /* 97/4/16 jhod@po.iijnet.or.jp
   * libwnn uses SIGALRM, so we need to stop and start interrupts.
   */
  stop_interrupts();
  if (!(wnnfns_buf[snum] = jl_open_lang (envname, hostname, langname,
					 0, 0, 0, EGG_TIMEOUT)))
    {
      start_interrupts();
      return Qnil;
    }
  if (!jl_isconnect (wnnfns_buf[snum]))
    {
      start_interrupts();
      return Qnil;
    }
  wnnfns_env_norm[snum] = jl_env_get (wnnfns_buf[snum]);
/*  if (Vwnnenv_sticky == Qt) jl_env_sticky_e (wnnfns_env_norm[snum]);
    else jl_env_un_sticky_e (wnnfns_env_norm[snum]);*/
  strcat (envname, "R");
  if (!(wnnfns_env_rev[snum] = jl_connect_lang (envname, hostname, langname,
						0, 0, 0, EGG_TIMEOUT)))
    {
      start_interrupts();
      return Qnil;
    }
/*  if (Vwnnenv_sticky == Qt) jl_env_sticky_e (wnnfns_env_rev[snum]);
    else jl_env_un_sticky_e (wnnfns_env_rev[snum]);*/
  start_interrupts();
  return Qt;
}


DEFUN ("wnn-server-close", Fwnn_close, 0, 0, 0, /*
Close the connection to jserver, Dictionary and frequency files
are not saved.
*/
     ())
{
  int	snum;
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  if (wnnfns_env_norm[snum])
    {
      if (NILP (Vwnnenv_sticky)) jl_env_un_sticky_e (wnnfns_env_norm[snum]);
      else jl_env_sticky_e (wnnfns_env_norm[snum]);
      jl_disconnect (wnnfns_env_norm[snum]);
    }
  if (wnnfns_env_rev[snum])
    {
      if (NILP (Vwnnenv_sticky)) jl_env_un_sticky_e (wnnfns_env_rev[snum]);
      else jl_env_sticky_e (wnnfns_env_rev[snum]);
      jl_disconnect (wnnfns_env_rev[snum]);
    }
  jl_env_set (wnnfns_buf[snum], 0);
  jl_close (wnnfns_buf[snum]);
  wnnfns_buf[snum] = (struct wnn_buf *) 0;
  wnnfns_env_norm[snum] = wnnfns_env_rev[snum] = (struct wnn_env *) 0;
  return Qt;
}

DEFUN ("wnn-server-dict-add", Fwnn_dict_add, 5, MANY, 0, /*
Add dictionary specified by DICT-FILE-NAME, FREQ-FILE-NAME,
PRIORITY, DICT-FILE-MODE, FREQ-FILE-MODE.
Specify password files of dictionary and frequency, PW1 and PW2, if needed.
*/
     (int nargs, Lisp_Object *args))
{
  struct gcpro gcpro1;
  int	snum;
  CHECK_STRING (args[0]);
  CHECK_STRING (args[1]);
  CHECK_INT (args[2]);
  if (! NILP (args[5])) CHECK_STRING (args[5]);
  if (! NILP (args[6])) CHECK_STRING (args[6]);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  GCPRO1 (*args);
  gcpro1.nvars = nargs;
  if (jl_dic_add (wnnfns_buf[snum],
		  XSTRING_DATA (args[0]),
		  XSTRING_DATA (args[1]),
		  wnnfns_norm ? WNN_DIC_ADD_NOR : WNN_DIC_ADD_REV,
		  XINT (args[2]),
		  NILP (args[3]) ? WNN_DIC_RDONLY : WNN_DIC_RW,
		  NILP (args[4]) ? WNN_DIC_RDONLY : WNN_DIC_RW,
		  NILP (args[5]) ? 0 : XSTRING_DATA (args[5]),
		  NILP (args[6]) ? 0 : XSTRING_DATA (args[6]),
		  yes_or_no,
		  puts2 ) < 0)
    {
      UNGCPRO;
      return Qnil;
    }
  UNGCPRO;
  return Qt;
}

DEFUN ("wnn-server-dict-delete", Fwnn_dict_delete, 1, 1, 0, /*
Remove dictionary specified by DIC-NUMBER from buffer.
*/
     (dicno))
{
  int	no;
  int	snum;
  CHECK_INT (dicno);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  no = XINT (dicno);
  if (!wnnfns_buf[snum]) return Qnil;
  if (jl_dic_delete (wnnfns_buf[snum], no) < 0) return Qnil;
  return Qt;
}

DEFUN ("wnn-server-dict-list", Fwnn_dict_list, 0, 0, 0, /*
Return information of dictionaries.
*/
     ())
{
  WNN_DIC_INFO	*dicinfo;
  int		cnt, i;
  unsigned char	comment[1024];
  Lisp_Object	val;
  int	snum;
  unsigned char lb;

  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  lb = lb_wnn_server_type[snum];
  if (!wnnfns_buf[snum]) return Qnil;
#ifdef	WNN6
  if((cnt = jl_fi_dic_list (wnnfns_buf[snum], 0x3f, &dicinfo)) < 0)
    return Qnil;
#else
  if((cnt = jl_dic_list (wnnfns_buf[snum], &dicinfo)) < 0) return Qnil;
#endif
  val = Qnil;
  for (i = 0, dicinfo += cnt; i < cnt; i++)
    {
      dicinfo--;
      w2m (dicinfo->comment, comment, lb);
      /* #### The following has not been Mule-ized!!
         fname and comment must be ASCII strings! */
      val =
	Fcons (Fcons (make_int (dicinfo->dic_no),
		      list4 (make_string ((Ibyte *) (dicinfo->fname),
					  strlen (dicinfo->fname)),
			     make_string (comment, strlen ((char *) comment)),
			     make_int (dicinfo->gosuu),
			     make_int (dicinfo->nice))), val);
    }
  return val;
}

DEFUN ("wnn-server-dict-comment", Fwnn_dict_comment, 2, 2, 0, /*
Set comment to dictionary specified by DIC-NUMBER.
Comment string COMMENT.
*/
     (dicno, comment))
{
  w_char wbuf[512];
  int snum;
  CHECK_INT (dicno);
  CHECK_STRING (comment);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  m2w (XSTRING_DATA (comment), wbuf);
  if (jl_dic_comment_set (wnnfns_buf[snum], XINT (dicno), wbuf) < 0)
    return Qnil;
  return Qt;
}


DEFUN ("wnn-server-set-rev", Fwnn_set_rev, 1, 1, 0, /*
Switch the translation mode to normal if T, or reverse if NIL.
*/
     (rev))
{
  int	snum;
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (NILP (rev))
    {
      if ((!wnnfns_buf[snum]) || (!wnnfns_env_norm[snum])) return Qnil;
      jl_env_set (wnnfns_buf[snum], wnnfns_env_norm[snum]);
      wnnfns_norm = 1;
    }
  else
    {
      if ((!wnnfns_buf[snum]) || (!wnnfns_env_rev[snum])) return Qnil;
      jl_env_set (wnnfns_buf[snum], wnnfns_env_rev[snum]);
      wnnfns_norm = 0;
    }
  return Qt;
}

DEFUN ("wnn-server-henkan-begin", Fwnn_begin_henkan, 1, 1, 0, /*
Translate YOMI string to kanji. Retuen the number of bunsetsu.
*/
     (hstring))
{
  int			cnt;
  w_char		wbuf[5000];
  int	snum;
  CHECK_STRING (hstring);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  m2w (XSTRING_DATA (hstring), wbuf);
  if (snum == WNNSERVER_C)
    w2y (wbuf);

#ifdef	WNN6
  if ((cnt = jl_fi_ren_conv (wnnfns_buf[snum], wbuf,	0, -1, WNN_USE_MAE)) < 0)
    return Qnil;
#else
  if ((cnt = jl_ren_conv (wnnfns_buf[snum], wbuf,	0, -1, WNN_USE_MAE)) < 0)
    return Qnil;
#endif
  return make_int (cnt);
}

DEFUN ("wnn-server-zenkouho", Fwnn_zenkouho, 2, 2, 0, /*
Get zenkouho at BUNSETSU-NUMBER. Second argument DAI is t.
if dai-bunsetsu, NIL if sho-bunsetsu. Return the current offset of zenkouho.
*/
     (bunNo, dai))
{
  int	no, offset;
  int	snum;
  int	uniq_level;
  CHECK_INT (bunNo);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  no = XINT (bunNo);
  if (EQ(Vwnn_uniq_level, Qwnn_no_uniq)) uniq_level = WNN_NO_UNIQ;
  else if (EQ(Vwnn_uniq_level, Qwnn_uniq)) uniq_level = WNN_UNIQ;
  else uniq_level = WNN_UNIQ_KNJ;
  if (NILP (dai))
    {
      if ((offset = jl_zenkouho (wnnfns_buf[snum],no,WNN_USE_MAE,
				 uniq_level)) < 0)
	return Qnil;
    }
  else
    {
      if ((offset = jl_zenkouho_dai (wnnfns_buf[snum], no, dai_end (no, snum),
				     WNN_USE_MAE, uniq_level)) < 0)
	return Qnil;
    }
  return make_int (offset);
}


DEFUN ("wnn-server-get-zenkouho", Fwnn_get_zenkouho, 1, 1, 0, /*
Get kanji string of KOUHO-NUMBER.
*/
     (kouhoNo))
{
  unsigned char	kanji_buf[256];
  w_char	wbuf[256];
  int	snum;
  unsigned char lb;
  CHECK_INT (kouhoNo);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  lb = lb_wnn_server_type[snum];
  if (!wnnfns_buf[snum]) return Qnil;
  jl_get_zenkouho_kanji (wnnfns_buf[snum], XINT (kouhoNo), wbuf);
  w2m (wbuf, kanji_buf, lb);
  return make_string (kanji_buf, strlen ((char *) kanji_buf));
}

DEFUN ("wnn-server-zenkouho-bun", Fwnn_zenkouho_bun, 0, 0, 0, /*
For Wnn.
*/
     ())
{
  int	snum;
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  return make_int (jl_zenkouho_bun (wnnfns_buf[snum]));
}

DEFUN ("wnn-server-zenkouho-suu", Fwnn_zenkouho_suu, 0, 0, 0, /*
Return the number of zen kouho.
*/
     ())
{
  int	snum;
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  return make_int (jl_zenkouho_suu (wnnfns_buf[snum]));
}

DEFUN ("wnn-server-dai-top", Fwnn_dai_top, 1, 1, 0, /*
Return t if bunsetsu BUN-NUMBER is dai-bunsetsu.
*/
     (bunNo))
{
  int	snum;
  CHECK_INT (bunNo);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  if (jl_dai_top (wnnfns_buf[snum], XINT (bunNo)) == 1) return Qt;
  else return Qnil;
}

DEFUN ("wnn-server-dai-end", Fwnn_dai_end, 1, 1, 0, /*
Return the bunsetu number of the next dai-bunsetsu after BUN-NUMBER.
*/
     (bunNo))
{
  int	snum;
  CHECK_INT (bunNo);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  return make_int (dai_end (XINT (bunNo), snum));
}

DEFUN ("wnn-server-henkan-kakutei", Fwnn_kakutei, 2, 2, 0, /*
Set candidate with OFFSET, DAI. DAI is T if dai-bunsetsu.
*/
     (offset, dai))
{
  int	snum;
  CHECK_INT (offset);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  if (NILP (dai))
    {
      if (jl_set_jikouho (wnnfns_buf[snum], XINT (offset)) < 0) return Qnil;
    }
  else
    {
      if (jl_set_jikouho_dai (wnnfns_buf[snum], XINT (offset)) < 0)
	return Qnil;
    }
  return Qt;
}

DEFUN ("wnn-server-bunsetu-henkou", Fwnn_bunsetu_henkou, 3, 3, 0, /*
Change length of BUN-NUMBER bunsetu to LEN. DAI is T if dai-bunsetsu.
*/
     (bunNo, len, dai))
{
  int		cnt, no;
  int	snum;
  CHECK_INT (bunNo);
  CHECK_INT (len);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  no = XINT (bunNo);
#ifdef	WNN6
  if ((cnt = jl_fi_nobi_conv (wnnfns_buf[snum], no, XINT(len), -1, WNN_USE_MAE,
			      NILP (dai) ? WNN_SHO : WNN_DAI)) < 0)
    return Qnil;
#else
  if ((cnt = jl_nobi_conv (wnnfns_buf[snum], no, XINT(len), -1, WNN_USE_MAE,
			   NILP (dai) ? WNN_SHO : WNN_DAI)) < 0)
    return Qnil;
#endif
  return make_int (cnt);
}

DEFUN ("wnn-server-inspect", Fwnn_inspect, 1, 1, 0, /*
Get bunsetsu information specified by BUN-NUMBER.
*/
     (bunNo))
{
  Lisp_Object		val;
  unsigned char		cbuf[512];
  w_char		wbuf[256];
  int			bun_no, yomilen, jirilen, i;
  int	snum;
  unsigned char		lb;
  CHECK_INT (bunNo);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  lb = lb_wnn_server_type[snum];
  if (!wnnfns_buf[snum]) return Qnil;
  bun_no = XINT (bunNo);
  val = Qnil;
  val = Fcons (make_int (wnnfns_buf[snum]->bun[bun_no]->kangovect), val);
  val = Fcons (make_int (wnnfns_buf[snum]->bun[bun_no]->daihyoka), val);
  val = Fcons (make_int (wnnfns_buf[snum]->bun[bun_no]->hyoka), val);
  val = Fcons (make_int (wnnfns_buf[snum]->bun[bun_no]->ima), val);
  val = Fcons (make_int (wnnfns_buf[snum]->bun[bun_no]->hindo), val);
  val = Fcons (make_int (wnnfns_buf[snum]->bun[bun_no]->hinsi), val);
  val = Fcons (make_int (wnnfns_buf[snum]->bun[bun_no]->entry), val);
  val = Fcons (make_int (wnnfns_buf[snum]->bun[bun_no]->dic_no), val);
  yomilen = jl_get_yomi (wnnfns_buf[snum], bun_no, bun_no + 1, wbuf);
  jirilen = wnnfns_buf[snum]->bun[bun_no]->jirilen;
  for (i = yomilen; i >= jirilen; i--) wbuf[i+1] = wbuf[i];
  wbuf[jirilen] = '+';
  w2m (wbuf, cbuf, lb);
  val = Fcons (make_string (cbuf, strlen ((char *) cbuf)), val);
  jl_get_kanji (wnnfns_buf[snum], bun_no, bun_no + 1, wbuf);
  w2m (wbuf, cbuf, lb);
  return Fcons (make_string (cbuf, strlen ((char *) cbuf)), val);
}


DEFUN ("wnn-server-henkan-quit", Fwnn_quit_henkan, 0, 0, 0, /*
do nothing.
*/
     ())
{
  int	snum;
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  return Qt;
}

DEFUN ("wnn-server-bunsetu-kanji", Fwnn_bunsetu_kanji, 1, 1, 0, /*
Get the pair of kanji and length of bunsetsu specified by BUN-NUMBER.
*/
     (bunNo))
{
  int		no;
  unsigned char		kanji_buf[256];
  w_char		wbuf[256];
  int			kanji_len;
  int			snum;
  unsigned char		lb;
  CHECK_INT (bunNo);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  lb = lb_wnn_server_type[snum];
  if (!wnnfns_buf[snum]) return Qnil;
  no = XINT (bunNo);
  kanji_len = jl_get_kanji (wnnfns_buf[snum], no, no + 1, wbuf);
  w2m (wbuf, kanji_buf, lb);
  return Fcons (make_string (kanji_buf, strlen ((char *) kanji_buf)),
		make_int (kanji_len));
}

DEFUN ("wnn-server-bunsetu-yomi", Fwnn_bunsetu_yomi, 1, 1, 0, /*
Get the pair of yomi and length of bunsetsu specified by BUN-NUMBER.
*/
     (bunNo))
{
  int		no;
  unsigned char		yomi_buf[256];
  w_char		wbuf[256];
  int			yomi_len;
  int			snum;
  unsigned char		lb;
  CHECK_INT (bunNo);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  lb = lb_wnn_server_type[snum];
  if (!wnnfns_buf[snum]) return Qnil;
  no = XINT (bunNo);
  yomi_len = jl_get_yomi (wnnfns_buf[snum], no, no + 1, wbuf);
  w2m (wbuf, yomi_buf, lb);
  return Fcons (make_string (yomi_buf, strlen ((char *) yomi_buf)),
		make_int (yomi_len));
}

DEFUN ("wnn-server-bunsetu-suu", Fwnn_bunsetu_suu, 0, 0, 0, /*
Get the number of bunsetsu.
*/
     ())
{
  int	snum;
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  return make_int (jl_bun_suu (wnnfns_buf[snum]));
}

DEFUN ("wnn-server-hindo-update", Fwnn_hindo_update, 0, 1, 0, /*
Update frequency of bunsetsu specified by NUM-NUMBER.
*/
     (bunNo))
{
  int		no;
  int	snum;
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (NILP (bunNo)) no = -1;
  else
    {
      CHECK_INT (bunNo);
      no = XINT (bunNo);
    }
  if (!wnnfns_buf[snum]) return Qnil;
#ifdef	WNN6
  if (jl_optimize_fi (wnnfns_buf[snum], 0, no) < 0) return Qnil;
#else
  if (jl_update_hindo (wnnfns_buf[snum], 0, no) < 0) return Qnil;
#endif
  return Qt;
}


DEFUN ("wnn-server-word-add", Fwnn_word_toroku, 5, 5, 0, /*
Add a word to dictionary. Arguments are
DIC-NUMBER, KANJI, YOMI, COMMENT, HINSI-NUMBER.
*/
     (dicno, kanji, yomi, comment, hinsi))
{
  w_char		yomi_buf[256], kanji_buf[256], comment_buf[256];
  int	snum;
  CHECK_INT (dicno);
  CHECK_STRING (kanji);
  CHECK_STRING (yomi);
  CHECK_STRING (comment);
  CHECK_INT (hinsi);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  m2w (XSTRING_DATA (yomi), yomi_buf);
  if (snum == WNNSERVER_C)
    w2y (yomi_buf);
  m2w (XSTRING_DATA (kanji), kanji_buf);
  m2w (XSTRING_DATA (comment), comment_buf);
  if (jl_word_add (wnnfns_buf[snum], XINT (dicno), yomi_buf, kanji_buf,
		   comment_buf, XINT (hinsi), 0) < 0)
    return Qnil;
  else return Qt;
}


DEFUN ("wnn-server-word-delete", Fwnn_word_sakujo, 2, 2, 0, /*
Delete a word from dictionary, specified by DIC-NUMBER, SERIAL-NUMBER.
*/
     (no, serial))
{
  int	snum;
  CHECK_INT (no);
  CHECK_INT (serial);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  if (jl_word_delete (wnnfns_buf[snum], XINT (no), XINT (serial)) < 0)
    return Qnil;
  else return Qt;
}


DEFUN ("wnn-server-word-use", Fwnn_word_use, 2, 2, 0, /*
Toggle on/off word, specified by DIC-NUMBER and SERIAL-NUMBER.
*/
     (no, serial))
{
  int	snum;
  CHECK_INT (no);
  CHECK_INT (serial);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  if (jl_word_use (wnnfns_buf[snum], XINT (no), XINT (serial)) < 0)
    return Qnil;
  else return Qt;
}

DEFUN ("wnn-server-word-info", Fwnn_word_info, 2, 2, 0, /*
Return list of yomi, kanji, comment, hindo, hinshi.
*/
     (no, serial))
{
  Lisp_Object		val;
  struct wnn_jdata	*info_buf;
  unsigned char		cbuf[512];
  int			snum;
  unsigned char		lb;
  CHECK_INT (no);
  CHECK_INT (serial);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  lb = lb_wnn_server_type[snum];
  if (!wnnfns_buf[snum]) return Qnil;
  if ((info_buf =  jl_word_info (wnnfns_buf[snum],
				 XINT (no), XINT (serial))) != NULL)
    {
      return Qnil;
    }
  else
    {
      val = Qnil;
      val = Fcons (make_int (info_buf->hinshi), val);
      val = Fcons (make_int (info_buf->hindo), val);
      w2m (info_buf->com, cbuf, lb);
      val = Fcons (make_string (cbuf, strlen ((char *) cbuf)), val);
      w2m (info_buf->kanji, cbuf, lb);
      val = Fcons (make_string (cbuf, strlen ((char *) cbuf)), val);
      w2m (info_buf->yomi, cbuf, lb);
      val = Fcons (make_string (cbuf, strlen ((char *) cbuf)), val);
      return val;
    }
}

DEFUN ("wnn-server-word-hindo-set", Fwnn_hindo_set, 3, 3, 0, /*
Set frequency to arbitrary value. Specified by DIC-NUMBER,
SERIAL-NUMBER, FREQUENCY.
*/
     (no, serial, hindo))
{
  int	snum;
  CHECK_INT (no);
  CHECK_INT (serial);
  CHECK_INT (hindo);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  if (js_hindo_set (jl_env_get (wnnfns_buf[snum]),
		    XINT (no),
		    XINT (serial),
		    WNN_HINDO_NOP,
		    XINT (hindo)) < 0)
    return Qnil;
  else return Qt;
}


DEFUN ("wnn-server-word-search", Fwnn_dict_search, 1, 1, 0, /*
Search a word YOMI from buffer.
Return list of (kanji hinshi freq dic_no serial).
*/
     (yomi))
{
  Lisp_Object		val;
  struct wnn_jdata	*wordinfo;
  int			i, count;
  w_char			wbuf[256];
  unsigned char		kanji_buf[256];
  int			snum;
  unsigned char		lb;
  CHECK_STRING (yomi);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  lb = lb_wnn_server_type[snum];
  if (!wnnfns_buf[snum]) return Qnil;
  m2w (XSTRING_DATA (yomi), wbuf);
  if (snum == WNNSERVER_C)
    w2y (wbuf);
  if ((count = jl_word_search_by_env (wnnfns_buf[snum],
				      wbuf, &wordinfo)) < 0)
    return Qnil;
  val = Qnil;
  for (i = 0, wordinfo += count; i < count; i++)
    {
      wordinfo--;
      w2m (wordinfo->kanji, kanji_buf, lb);
      val = Fcons (Fcons (make_string (kanji_buf, strlen ((char *) kanji_buf)),
			  list4 (make_int (wordinfo->hinshi),
				 make_int (wordinfo->hindo),
				 make_int (wordinfo->dic_no),
				 make_int (wordinfo->serial))),
		   val);
    }
  return val;
}

DEFUN ("wnn-server-dict-save", Fwnn_dict_save, 0, 0, 0, /*
Save all dictionaries and frequency files.
*/
     ())
{
  int	snum;
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  if (jl_dic_save_all (wnnfns_buf[snum]) < 0) return Qnil;
  else return Qt;
}

DEFUN ("wnn-server-get-param", Fwnn_get_param, 0, 0, 0, /*
Returns (n nsho hindo len jiri flag jisho sbn dbn_len sbn_cnt
suuji kana eisuu kigou toji_kakko fuzokogo kaikakko)
*/
     ())
{
  struct wnn_param	param;
  int	snum;
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  if (jl_param_get (wnnfns_buf[snum], &param) < 0) return Qnil;
  return Fcons (make_int (param.n),
	 Fcons (make_int (param.nsho),
	 Fcons (make_int (param.p1),
	 Fcons (make_int (param.p2),
	 Fcons (make_int (param.p3),
	 Fcons (make_int (param.p4),
	 Fcons (make_int (param.p5),
	 Fcons (make_int (param.p6),
	 Fcons (make_int (param.p7),
	 Fcons (make_int (param.p8),
	 Fcons (make_int (param.p9),
	 Fcons (make_int (param.p10),
	 Fcons (make_int (param.p11),
	 Fcons (make_int (param.p12),
	 Fcons (make_int (param.p13),
	 Fcons (make_int (param.p14),
	 Fcons (make_int (param.p15),Qnil)))))))))))))))));
}

DEFUN ("wnn-server-set-param", Fwnn_set_param, 1, 1, 0, /*
Set parameters using an alist, where the CAR contains one of
wnn_n, wnn_nsho, wnn_hindo, wnn_len, wnn_jiri, wnn_flag,
wnn_jisho, wnn_sbn, wnn_dbn_len, wnn_sbn_cnt, wnn_suuji,
wnn_kana, wnn_eisuu, wnn_kigou, wnn_toji_kakko, wnn_fuzokogo,
or wnn_kaikakko and the CDR contains the value.
*/
     (Vsetvalues_alist))
{
  int             rc;
  struct wnn_param	param;
  int	snum;

  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  rc = jl_param_get (wnnfns_buf[snum], &param);
  if (rc < 0) return Qnil;

  {
    EXTERNAL_PROPERTY_LIST_LOOP_3 (key, val, Vsetvalues_alist)
      {
	int setval;
	CHECK_INT (val);
	setval = XINT (val);
	if (EQ (key, Qwnn_n)) param.n = setval;
	else if (EQ (key, Qwnn_nsho)) param.nsho = setval;
	else if (EQ (key, Qwnn_hindo)) param.p1 = setval;
	else if (EQ (key, Qwnn_len)) param.p2 = setval;
	else if (EQ (key, Qwnn_jiri)) param.p3 = setval;
	else if (EQ (key, Qwnn_flag)) param.p4 = setval;
	else if (EQ (key, Qwnn_jisho)) param.p5 = setval;
	else if (EQ (key, Qwnn_sbn)) param.p6 = setval;
	else if (EQ (key, Qwnn_dbn_len)) param.p7 = setval;
	else if (EQ (key, Qwnn_sbn_cnt)) param.p8 = setval;
	else if (EQ (key, Qwnn_suuji)) param.p9 = setval;
	else if (EQ (key, Qwnn_kana)) param.p10 = setval;
	else if (EQ (key, Qwnn_eisuu)) param.p11 = setval;
	else if (EQ (key, Qwnn_kigou)) param.p12 = setval;
	else if (EQ (key, Qwnn_toji_kakko)) param.p13 = setval;
	else if (EQ (key, Qwnn_fuzokogo)) param.p14 = setval;
	else if (EQ (key, Qwnn_kaikakko)) param.p15 = setval;
	else
	  {
	    invalid_constant ("Invalid wnn keyword", key);
	    return Qnil;
	  }
      }
  }

#if 0
  printf("wnn_n = %d\n",param.n);
  printf("wnn_nsho = %d\n",param.nsho);
  printf("wnn_hindo = %d\n",param.p1);
  printf("wnn_len = %d\n",param.p2);
  printf("wnn_jiri = %d\n",param.p3);
  printf("wnn_flag = %d\n",param.p4);
  printf("wnn_jisho = %d\n",param.p5);
  printf("wnn_sbn = %d\n",param.p6);
  printf("wnn_dbn_len = %d\n",param.p7);
  printf("wnn_sbn_cnt = %d\n",param.p8);
  printf("wnn_suuji = %d\n",param.p9);
  printf("wnn_kana = %d\n",param.p10);
  printf("wnn_eisuu = %d\n",param.p11);
  printf("wnn_kigou = %d\n",param.p12);
  printf("wnn_toji_kakko = %d\n",param.p13);
  printf("wnn_fuzokogo = %d\n",param.p14);
  printf("wnn_kaikakko = %d\n",param.p15);
#endif

  rc = jl_param_set (wnnfns_buf[snum], &param);
  if (rc < 0) return Qnil;
  return Qt;
}

DEFUN ("wnn-server-get-msg", Fwnn_get_msg, 0, 0, 0, /*
Get message string from wnn_perror.
*/
     ())
{
  unsigned char mbuf[256];
  char 			*msgp;
  int			snum;
  unsigned char		lb;
  char  langname[32];
/*  CHECK_INT (errno);*/
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  lb = lb_wnn_server_type[snum];
  switch (snum)
    {
    case WNNSERVER_J:
      strcpy (langname, "ja_JP");
      break;
    case WNNSERVER_C:
      strcpy (langname, "zh_CN");
      break;
/*
  case WNNSERVER_T:
  strcpy (langname, "zh_TW");
  break;
  */
    case WNNSERVER_K:
      strcpy (langname, "ko_KR");
      break;
    }
  if (!wnnfns_buf[snum]) return Qnil;
/*  msgp = msg_get (wnn_msg_cat, XINT (errno), 0, 0);*/
  msgp = wnn_perror_lang (langname);
  c2m ((unsigned char *) msgp, mbuf, lb);
  return make_string (mbuf, strlen ((char *) mbuf));
}


DEFUN ("wnn-server-fuzokugo-set", Fwnn_fuzokugo_set, 1, 1, 0, /*
For Wnn.
*/
     (file))
{
  int	snum;
  CHECK_STRING (file);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  if (jl_fuzokugo_set (wnnfns_buf[snum], XSTRING_DATA (file)) < 0)
    return Qnil;
  return Qt;
}

DEFUN ("wnn-server-fuzokugo-get", Fwnn_fuzokugo_get, 0, 0, 0, /*
For Wnn.
*/
     ())
{
  char	fname[256];
  int	snum;
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  if (jl_fuzokugo_get (wnnfns_buf[snum], fname) < 0) return Qnil;
  return make_string ((Ibyte *) fname, strlen (fname));
}


DEFUN ("wnn-server-isconnect", Fwnn_isconnect, 0, 0, 0, /*
For Wnn.
*/
     ())
{
  int	snum;
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  if (jl_isconnect (wnnfns_buf[snum])) return Qt;
  else return Qnil;
}

DEFUN ("wnn-server-hinsi-dicts", Fwnn_hinsi_dicts, 1, 1, 0, /*
For Wnn.
*/
     (hinsi))
{
  int		*area;
  int		cnt;
  Lisp_Object	val;
  int	snum;
  CHECK_INT (hinsi);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  if ((cnt = jl_hinsi_dicts (wnnfns_buf[snum], XINT (hinsi), &area)) < 0)
    return Qnil;
  val = Qnil;
  for (area += cnt; cnt > 0; cnt--)
    {
      area--;
      val = Fcons (make_int (*area), val);
    }
  return val;
}

DEFUN ("wnn-server-hinsi-list", Fwnn_hinsi_list, 2, 2, 0, /*
For Wnn.
*/
     (dicno, name))
{
  int		cnt;
  Lisp_Object	val;
  w_char		wbuf[256];
  w_char		**area;
  unsigned char	cbuf[512];
  int		snum;
  unsigned char lb;
  CHECK_INT (dicno);
  CHECK_STRING (name);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  lb = lb_wnn_server_type[snum];
  if (!wnnfns_buf[snum]) return Qnil;
  m2w (XSTRING_DATA (name), wbuf);
  if ((cnt = jl_hinsi_list (wnnfns_buf[snum], XINT (dicno), wbuf, &area)) < 0)
    return Qnil;
  if (cnt == 0) return make_int (0);
  val = Qnil;
  for (area += cnt; cnt > 0; cnt--)
    {
      area--;
      w2m (*area, cbuf, lb);
      val = Fcons (make_string (cbuf, strlen ((char *) cbuf)), val);
    }
  return val;
}

DEFUN ("wnn-server-hinsi-name", Fwnn_hinsi_name, 1, 1, 0, /*
For Wnn.
*/
     (no))
{
  unsigned char	name[256];
  w_char		*wname;
  int			snum;
  unsigned char		lb;
  CHECK_INT (no);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  lb = lb_wnn_server_type[snum];
  if (!wnnfns_buf[snum]) return Qnil;
  if ((wname = jl_hinsi_name (wnnfns_buf[snum], XINT (no))) == 0) return Qnil;
  w2m (wname, name, lb);
  return make_string (name, strlen ((char *) name));
}
#ifdef	WNN6
DEFUN ("wnn-server-fisys-dict-add", Fwnn_fisys_dict_add, 3, MANY, 0, /*
Add dictionary specified by FISYS-DICT-FILE-NAME, FISYS-FREQ-FILE-NAME,
FISYS-FREQ-FILE-MODE.
Specify password files of dictionary and frequency, PW1 and PW2, if needed.
*/
     (int nargs, Lisp_Object *args))
{
  struct gcpro gcpro1;
  int   snum;
  CHECK_STRING (args[0]);
  CHECK_STRING (args[1]);
  if (! NILP (args[3])) CHECK_STRING (args[3]);
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  GCPRO1 (*args);
  gcpro1.nvars = nargs;
  if(jl_fi_dic_add(wnnfns_buf[snum],
		   XSTRING_DATA (args[0]),
		   XSTRING_DATA (args[1]),
		   WNN_FI_SYSTEM_DICT,
		   WNN_DIC_RDONLY,
		   NILP (args[2]) ? WNN_DIC_RDONLY : WNN_DIC_RW,
		   0,
		   NILP (args[3]) ? 0 : XSTRING_DATA (args[3]),
		   yes_or_no,
		   puts2 ) < 0) {
    UNGCPRO;
    return Qnil;
  }
  UNGCPRO;
  return Qt;
}

DEFUN ("wnn-server-fiusr-dict-add", Fwnn_fiusr_dict_add, 4, MANY, 0, /*
Add dictionary specified by FIUSR-DICT-FILE-NAME, FIUSR-FREQ-FILE-NAME,
FIUSR-DICT-FILE-MODE, FIUSR-FREQ-FILE-MODE.
Specify password files of dictionary and frequency, PW1 and PW2, if needed.
*/
     (int nargs, Lisp_Object *args))
{
  struct gcpro gcpro1;
  int   snum;
  CHECK_STRING (args[0]);
  CHECK_STRING (args[1]);
  if (! NILP (args[4])) CHECK_STRING (args[4]);
  if (! NILP (args[5])) CHECK_STRING (args[5]);
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  GCPRO1 (*args);
  gcpro1.nvars = nargs;
  if(jl_fi_dic_add(wnnfns_buf[snum],
		   XSTRING_DATA (args[0]),
		   XSTRING_DATA (args[1]),
		   WNN_FI_USER_DICT,
		   NILP (args[2]) ? WNN_DIC_RDONLY : WNN_DIC_RW,
		   NILP (args[3]) ? WNN_DIC_RDONLY : WNN_DIC_RW,
		   NILP (args[4]) ? 0 : XSTRING_DATA (args[4]),
		   NILP (args[5]) ? 0 : XSTRING_DATA (args[5]),
		   yes_or_no,
		   puts2 ) < 0) {
    UNGCPRO;
    return Qnil;
  }
  UNGCPRO;
  return Qt;
}

DEFUN ("wnn-server-notrans-dict-add", Fwnn_notrans_dict_add, 3, MANY, 0, /*
Add dictionary specified by NOTRANS-DICT-FILE-NAME, PRIORITY, DICT-FILE-MODE.
Specify password files of dictionary and frequency PW1 if needed.
*/
     (int nargs, Lisp_Object *args))
{
  struct gcpro gcpro1;
  int   snum;
  int	dic_no;
  struct wnn_env *cur_env;
  unsigned long vmask = 0;
  struct wnn_henkan_env henv;
  CHECK_STRING (args[0]);
  CHECK_INT (args[1]);
  if (! NILP (args[3])) CHECK_STRING (args[3]);
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  GCPRO1 (*args);
  gcpro1.nvars = nargs;
  if(wnnfns_norm)
      cur_env = wnnfns_env_norm[snum];
  else
      cur_env = wnnfns_env_rev[snum];
  dic_no = js_get_autolearning_dic(cur_env, WNN_MUHENKAN_LEARNING);
  if (dic_no == WNN_NO_LEARNING) {
      if((dic_no = jl_dic_add(wnnfns_buf[snum],
			      XSTRING_DATA (args[0]),
			      0,
			      wnnfns_norm ? WNN_DIC_ADD_NOR : WNN_DIC_ADD_REV,
			      XINT(args[1]),
			      WNN_DIC_RW, WNN_DIC_RW,
			      NILP (args[3]) ? 0 : XSTRING_DATA (args[3]),
			      0,
			      yes_or_no,
			      puts2)) < 0) {
	  UNGCPRO;
	  return Qnil;
      }
      js_set_autolearning_dic(cur_env, WNN_MUHENKAN_LEARNING, dic_no);
  }
  if(!js_is_loaded_temporary_dic(cur_env)) {
      if(js_temporary_dic_add(cur_env,
			      wnnfns_norm ? WNN_DIC_ADD_NOR : WNN_DIC_ADD_REV) < 0) {
	  UNGCPRO;
          return Qnil;
      }
  }
  vmask |= WNN_ENV_MUHENKAN_LEARN_MASK;
  henv.muhenkan_flag = NILP (args[2]) ? WNN_DIC_RDONLY : WNN_DIC_RW;
  if(jl_set_henkan_env(wnnfns_buf[snum],
                       vmask,
                       &henv) < 0) {
      UNGCPRO;
      return Qnil;
  }
  UNGCPRO;
  return Qt;
}

DEFUN ("wnn-server-bmodify-dict-add", Fwnn_bmodify_dict_add, 3, MANY, 0, /*
Add dictionary specified by BMODIFY-DICT-FILE-NAME, PRIORITY, DICT-FILE-MODE.
Specify password files of dictionary and frequency PW1 if needed.
*/
     (int nargs, Lisp_Object *args))
{
  struct gcpro gcpro1;
  int   snum;
  int   dic_no;
  struct wnn_env *cur_env;
  unsigned long vmask = 0;
  struct wnn_henkan_env henv;
  CHECK_STRING (args[0]);
  CHECK_INT (args[1]);
  if (! NILP (args[3])) CHECK_STRING (args[3]);
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  GCPRO1 (*args);
  gcpro1.nvars = nargs;
  if(wnnfns_norm)
      cur_env = wnnfns_env_norm[snum];
  else
      cur_env = wnnfns_env_rev[snum];
  dic_no = js_get_autolearning_dic(cur_env, WNN_BUNSETSUGIRI_LEARNING);
  if (dic_no == WNN_NO_LEARNING) {
      if((dic_no = jl_dic_add(wnnfns_buf[snum],
                              XSTRING_DATA (args[0]),
                              0,
                              wnnfns_norm ? WNN_DIC_ADD_NOR : WNN_DIC_ADD_REV,
                              XINT(args[1]),
                              WNN_DIC_RW, WNN_DIC_RW,
                              NILP (args[3]) ? 0 : XSTRING_DATA (args[3]),
                              0,
                              yes_or_no,
                              puts2)) < 0) {
          UNGCPRO;
          return Qnil;
      }
      js_set_autolearning_dic(cur_env, WNN_BUNSETSUGIRI_LEARNING, dic_no);
  }
  if(!js_is_loaded_temporary_dic(cur_env)) {
      if(js_temporary_dic_add(cur_env,
                              wnnfns_norm ? WNN_DIC_ADD_NOR : WNN_DIC_ADD_REV) < 0) {
          UNGCPRO;
          return Qnil;
      }
  }
  vmask |= WNN_ENV_BUNSETSUGIRI_LEARN_MASK;
  henv.bunsetsugiri_flag = NILP (args[2]) ? WNN_DIC_RDONLY : WNN_DIC_RW;
  if(jl_set_henkan_env(wnnfns_buf[snum],
                       vmask,
                       &henv) < 0) {
      UNGCPRO;
      return Qnil;
  }
  UNGCPRO;
  return Qt;
}

DEFUN ("wnn-server-set-last-is-first", Fwnn_last_is_first, 1, 1, 0, /*
For FI-Wnn.
*/
     (mode))
{
  int   snum;
  unsigned long vmask = 0;
  struct wnn_henkan_env henv;
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  vmask |= WNN_ENV_LAST_IS_FIRST_MASK;
  henv.last_is_first_flag = NILP (mode) ? False : True;
  if(jl_set_henkan_env(wnnfns_buf[snum],
		       vmask,
		       &henv) < 0) return Qnil;
  return Qt;
}

DEFUN ("wnn-server-set-complex-conv-mode", Fwnn_complex_conv, 1, 1, 0, /*
For FI-Wnn.
*/
     (mode))
{
  int   snum;
  unsigned long vmask = 0;
  struct wnn_henkan_env henv;
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  vmask |= WNN_ENV_COMPLEX_CONV_MASK;
  henv.complex_flag = NILP (mode) ? False : True;
  if(jl_set_henkan_env(wnnfns_buf[snum],
                       vmask,
                       &henv) < 0) return Qnil;
  return Qt;
}

DEFUN ("wnn-server-set-okuri-learn-mode", Fwnn_okuri_learn, 1, 1, 0, /*
For FI-Wnn.
*/
     (mode))
{
  int   snum;
  unsigned long vmask = 0;
  struct wnn_henkan_env henv;
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  vmask |= WNN_ENV_OKURI_LEARN_MASK;
  henv.okuri_learn_flag = NILP (mode) ? False : True;
  if(jl_set_henkan_env(wnnfns_buf[snum],
                       vmask,
                       &henv) < 0) return Qnil;
  return Qt;
}

DEFUN ("wnn-server-set-okuri-flag", Fwnn_okuri_flag, 1, 1, 0, /*
For FI-Wnn.
*/
     (lmode))
{
  int   snum, mode;
  unsigned long vmask = 0;
  struct wnn_henkan_env henv;
  CHECK_INT (lmode);
  mode = XINT (lmode);
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  if(mode != WNN_OKURI_REGULATION &&
     mode != WNN_OKURI_NO &&
     mode != WNN_OKURI_YES)
      return Qnil;
  else
      henv.okuri_flag = mode;
  vmask |= WNN_ENV_OKURI_MASK;
  if(jl_set_henkan_env(wnnfns_buf[snum],
                       vmask,
                       &henv) < 0) return Qnil;
  return Qt;
}

DEFUN ("wnn-server-set-prefix-learn-mode", Fwnn_prefix_learn, 1, 1, 0, /*
For FI-Wnn.
*/
     (mode))
{
  int   snum;
  unsigned long vmask = 0;
  struct wnn_henkan_env henv;
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  vmask |= WNN_ENV_PREFIX_LEARN_MASK;
  henv.prefix_learn_flag = NILP (mode) ? False : True;
  if(jl_set_henkan_env(wnnfns_buf[snum],
                       vmask,
                       &henv) < 0) return Qnil;
  return Qt;
}

DEFUN ("wnn-server-set-prefix-flag", Fwnn_prefix_flag, 1, 1, 0, /*
For FI-Wnn.
*/
     (lmode))
{
  int   snum, mode;
  unsigned long vmask = 0;
  struct wnn_henkan_env henv;
  CHECK_INT (lmode);
  mode = XINT (lmode);
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  if(mode != WNN_KANA_KOUHO && mode != WNN_KANJI_KOUHO)
      return Qnil;
  else
      henv.prefix_flag = mode;
  vmask |= WNN_ENV_PREFIX_MASK;
  if(jl_set_henkan_env(wnnfns_buf[snum],
                       vmask,
                       &henv) < 0) return Qnil;
  return Qt;
}

DEFUN ("wnn-server-set-suffix-learn-mode", Fwnn_suffix_learn, 1, 1, 0, /*
For FI-Wnn.
*/
     (mode))
{
  int   snum;
  unsigned long vmask = 0;
  struct wnn_henkan_env henv;
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  vmask |= WNN_ENV_SUFFIX_LEARN_MASK;
  henv.suffix_learn_flag = NILP (mode) ? False : True;
  if(jl_set_henkan_env(wnnfns_buf[snum],
                       vmask,
                       &henv) < 0) return Qnil;
  return Qt;
}

DEFUN ("wnn-server-set-common-learn-mode", Fwnn_common_learn, 1, 1, 0, /*
For FI-Wnn.
*/
     (mode))
{
  int   snum;
  unsigned long vmask = 0;
  struct wnn_henkan_env henv;
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  vmask |= WNN_ENV_COMMON_LAERN_MASK;
  henv.common_learn_flag = NILP (mode) ? False : True;
  if(jl_set_henkan_env(wnnfns_buf[snum],
                       vmask,
                       &henv) < 0) return Qnil;
  return Qt;
}

DEFUN ("wnn-server-set-freq-func-mode", Fwnn_freq_func, 1, 1, 0, /*
For FI-Wnn.
*/
     (lmode))
{
  int   snum, mode;
  unsigned long vmask = 0;
  struct wnn_henkan_env henv;
  CHECK_INT (lmode);
  mode = XINT (lmode);
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  if(mode != 0 && mode != 1 && mode != 2 && mode != 3 && mode != 4)
      return Qnil;
  else
      henv.freq_func_flag = mode;
  vmask |= WNN_ENV_FREQ_FUNC_MASK;
  if(jl_set_henkan_env(wnnfns_buf[snum],
                       vmask,
                       &henv) < 0) return Qnil;
  return Qt;
}

DEFUN ("wnn-server-set-numeric-mode", Fwnn_numeric, 1, 1, 0, /*
For FI-Wnn.
*/
     (lmode))
{
  int   snum, mode;
  unsigned long vmask = 0;
  struct wnn_henkan_env henv;
  CHECK_INT (lmode);
  mode = XINT (lmode);
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  if(mode != WNN_NUM_KANSUUJI &&
     mode != WNN_NUM_KANOLD &&
     mode != WNN_NUM_HANCAN &&
     mode != WNN_NUM_ZENCAN &&
     mode != WNN_NUM_HAN &&
     mode != WNN_NUM_ZEN &&
     mode != WNN_NUM_KAN)
      return Qnil;
  else
      henv.numeric_flag = mode;
  vmask |= WNN_ENV_NUMERIC_MASK;
  if(jl_set_henkan_env(wnnfns_buf[snum],
                       vmask,
                       &henv) < 0) return Qnil;
  return Qt;
}

DEFUN ("wnn-server-set-alphabet-mode", Fwnn_alphabet, 1, 1, 0, /*
For FI-Wnn.
*/
     (lmode))
{
  int   snum, mode;
  unsigned long vmask = 0;
  struct wnn_henkan_env henv;
  CHECK_INT (lmode);
  mode = XINT (lmode);
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  if(mode != WNN_ALP_HAN && mode != WNN_ALP_ZEN)
      return Qnil;
  else
      henv.alphabet_flag = mode;
  vmask |= WNN_ENV_ALPHABET_MASK;
  if(jl_set_henkan_env(wnnfns_buf[snum],
                       vmask,
                       &henv) < 0) return Qnil;
  return Qt;
}

DEFUN ("wnn-server-set-symbol-mode", Fwnn_symbol, 1, 1, 0, /*
For FI-Wnn.
*/
     (lmode))
{
  int   snum, mode;
  unsigned long vmask = 0;
  struct wnn_henkan_env henv;
  CHECK_INT (lmode);
  mode = XINT (lmode);
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  if(mode != WNN_KIG_HAN && mode != WNN_KIG_JIS && mode != WNN_KIG_ASC)
      return Qnil;
  else
      henv.symbol_flag = mode;
  vmask |= WNN_ENV_SYMBOL_MASK;
  if(jl_set_henkan_env(wnnfns_buf[snum],
                       vmask,
                       &henv) < 0) return Qnil;
  return Qt;
}

DEFUN ("wnn-server-set-yuragi-mode", Fwnn_yuragi, 1, 1, 0, /*
For FI-Wnn.
*/
     (mode))
{
  int   snum;
  unsigned long vmask = 0;
  struct wnn_henkan_env henv;
  if ((snum = check_wnn_server_type()) == -1) return Qnil;
  if(!wnnfns_buf[snum]) return Qnil;
  vmask |= WNN_ENV_YURAGI_MASK;
  henv.yuragi_flag = NILP (mode) ? False : True;
  if(jl_set_henkan_env(wnnfns_buf[snum],
                       vmask,
                       &henv) < 0) return Qnil;
  return Qt;
}

DEFUN ("wnn-reset-previous-info", Fwnn_reset_prev, 0, 0, 0, /*
For FI-Wnn.
*/
    ())
{
    int   snum;
    if ((snum = check_wnn_server_type()) == -1) return Qnil;
    if(!wnnfns_buf[snum]) return Qnil;
    if(jl_reset_prev_bun(wnnfns_buf[snum]) < 0) return Qnil;
    return Qt;
}
#endif	/* Wnn6 */

DEFUN ("wnn-server-version", Fwnn_version, 0, 0, 0, /*
Returns Wnn server version ID.
*/
    ())
{
    int   snum;
    int   serv;
    int   libv;
    struct wnn_env *cur_env;
    if ((snum = check_wnn_server_type()) == -1) return Qnil;
    if(!wnnfns_buf[snum]) return Qnil;
    if(wnnfns_norm)
      cur_env = wnnfns_env_norm[snum];
    else
      cur_env = wnnfns_env_rev[snum];
    if(js_version (cur_env->js_id,&serv,&libv) < 0) return Qnil;
    return make_int (serv);
}

DEFUN ("wnn-server-hinsi-number", Fwnn_hinsi_number, 1, 1, 0, /*
For Wnn.
*/
     (name))
{
  w_char		w_buf[256];
  int		no;
  int	snum;
  CHECK_STRING (name);
  if ((snum = check_wnn_server_type ()) == -1) return Qnil;
  if (!wnnfns_buf[snum]) return Qnil;
  m2w (XSTRING_DATA (name), w_buf);
  if ((no = jl_hinsi_number (wnnfns_buf[snum], w_buf)) < 0) return Qnil;
  return make_int (no);
}

void
syms_of_mule_wnn (void)
{
  DEFSUBR (Fwnn_open);
  DEFSUBR (Fwnn_close);
  DEFSUBR (Fwnn_dict_add);
  DEFSUBR (Fwnn_dict_delete);
  DEFSUBR (Fwnn_dict_list);
  DEFSUBR (Fwnn_dict_comment);
  DEFSUBR (Fwnn_set_rev);
  DEFSUBR (Fwnn_begin_henkan);
  DEFSUBR (Fwnn_zenkouho);
  DEFSUBR (Fwnn_get_zenkouho);
  DEFSUBR (Fwnn_zenkouho_bun);
  DEFSUBR (Fwnn_zenkouho_suu);
  DEFSUBR (Fwnn_dai_top);
  DEFSUBR (Fwnn_dai_end);
  DEFSUBR (Fwnn_kakutei);
  DEFSUBR (Fwnn_bunsetu_henkou);
  DEFSUBR (Fwnn_inspect);
  DEFSUBR (Fwnn_quit_henkan);
  DEFSUBR (Fwnn_bunsetu_kanji);
  DEFSUBR (Fwnn_bunsetu_yomi);
  DEFSUBR (Fwnn_bunsetu_suu);
  DEFSUBR (Fwnn_hindo_update);
  DEFSUBR (Fwnn_word_toroku);
  DEFSUBR (Fwnn_word_sakujo);
  DEFSUBR (Fwnn_word_use);
  DEFSUBR (Fwnn_word_info);
  DEFSUBR (Fwnn_hindo_set);
  DEFSUBR (Fwnn_dict_search);
  DEFSUBR (Fwnn_dict_save);
  DEFSUBR (Fwnn_get_param);
  DEFSUBR (Fwnn_set_param);
  DEFSUBR (Fwnn_get_msg);
  DEFSUBR (Fwnn_fuzokugo_set);
  DEFSUBR (Fwnn_fuzokugo_get);
  DEFSUBR (Fwnn_isconnect);
  DEFSUBR (Fwnn_hinsi_dicts);
  DEFSUBR (Fwnn_hinsi_list);
  DEFSUBR (Fwnn_hinsi_name);
  DEFSUBR (Fwnn_hinsi_number);
#ifdef	WNN6
  DEFSUBR (Fwnn_fisys_dict_add);
  DEFSUBR (Fwnn_fiusr_dict_add);
  DEFSUBR (Fwnn_notrans_dict_add);
  DEFSUBR (Fwnn_bmodify_dict_add);
  DEFSUBR (Fwnn_last_is_first);
  DEFSUBR (Fwnn_complex_conv);
  DEFSUBR (Fwnn_okuri_learn);
  DEFSUBR (Fwnn_okuri_flag);
  DEFSUBR (Fwnn_prefix_learn);
  DEFSUBR (Fwnn_prefix_flag);
  DEFSUBR (Fwnn_suffix_learn);
  DEFSUBR (Fwnn_common_learn);
  DEFSUBR (Fwnn_freq_func);
  DEFSUBR (Fwnn_numeric);
  DEFSUBR (Fwnn_alphabet);
  DEFSUBR (Fwnn_symbol);
  DEFSUBR (Fwnn_yuragi);
  DEFSUBR (Fwnn_reset_prev);
#endif	/* Wnn6 */
  DEFSUBR (Fwnn_version);

  DEFSYMBOL (Qjserver);
  DEFSYMBOL (Qcserver);
  /* DEFSYMBOL (Qtserver); */
  DEFSYMBOL (Qkserver);

  DEFSYMBOL (Qwnn_no_uniq);
  DEFSYMBOL (Qwnn_uniq);
  DEFSYMBOL (Qwnn_uniq_kanji);
  defsymbol (&Qwnn_n, "wnn_n");
  defsymbol (&Qwnn_nsho, "wnn_nsho");
  defsymbol (&Qwnn_hindo, "wnn_hindo");
  defsymbol (&Qwnn_len, "wnn_len");
  defsymbol (&Qwnn_jiri, "wnn_jiri");
  defsymbol (&Qwnn_flag, "wnn_flag");
  defsymbol (&Qwnn_jisho, "wnn_jisho");
  defsymbol (&Qwnn_sbn, "wnn_sbn");
  defsymbol (&Qwnn_dbn_len, "wnn_dbn_len");
  defsymbol (&Qwnn_sbn_cnt, "wnn_sbn_cnt");
  defsymbol (&Qwnn_suuji, "wnn_suuji");
  defsymbol (&Qwnn_kana, "wnn_kana");
  defsymbol (&Qwnn_eisuu, "wnn_eisuu");
  defsymbol (&Qwnn_kigou, "wnn_kigou");
  defsymbol (&Qwnn_toji_kakko, "wnn_toji_kakko");
  defsymbol (&Qwnn_fuzokogo, "wnn_fuzokogo");
  defsymbol (&Qwnn_kaikakko, "wnn_kaikakko");
}

void
reinit_vars_of_mule_wnn (void)
{
  int i;

  for (i = 0; i < NSERVER; i++)
    {
      wnnfns_buf[i] = (struct wnn_buf *) 0;
      wnnfns_env_norm[i] = (struct wnn_env *) 0;
      wnnfns_env_rev[i] = (struct wnn_env *) 0;
    }
}

void
vars_of_mule_wnn (void)
{
  DEFVAR_INT ("lb-sisheng", &lb_sisheng /*
Leading character for Sisheng.
*/ );
  DEFVAR_LISP ("wnn-server-type", &Vwnn_server_type /*
*jserver, cserver ..
*/ );
  DEFVAR_LISP ("cwnn-zhuyin", &Vcwnn_zhuyin /*
*pinyin or zhuyin
*/ );
  DEFVAR_LISP ("wnnenv-sticky", &Vwnnenv_sticky /*
*If non-nil, make environment sticky
*/ );
  DEFVAR_LISP ("wnn-uniq-level", &Vwnn_uniq_level /*
*Uniq level
*/ );

  Vwnn_server_type = Qjserver;
  Vcwnn_zhuyin = Qnil;
  Vwnnenv_sticky = Qnil;

  Vwnn_uniq_level = Qwnn_uniq;

  Fprovide (intern ("wnn"));
}

void
w2m (w_char *wp, unsigned char *mp, unsigned char lb)
{
  w_char	wc;
  w_char	pzy[10];
  int		i, len;

  while ((wc = *wp++) != 0)
    {
      switch (wc & 0x8080)
	{
	case 0x80:
	  if (EQ(Vwnn_server_type, Qcserver))
	    {
	      len = cwnn_yincod_pzy (pzy, wc,
				     NILP (Vcwnn_zhuyin)
				     ? CWNN_PINYIN
				     : CWNN_ZHUYIN);
	      for (i = 0; i < len; i++)
		{
		  if (pzy[i] & 0x80)
		    {
		      *mp++ = PRE_LEADING_BYTE_PRIVATE_1; /* #### Not sure about this one... */
		      *mp++ = lb_sisheng;
		    }
		  *mp++ = pzy[i];
		}
	    }
	  else
	    {
	      *mp++ = LEADING_BYTE_KATAKANA_JISX0201;
	      *mp++ = (wc & 0xff);
	    }
	  break;
	case 0x8080:
	  *mp++ = lb;
	  *mp++ = (wc & 0xff00) >> 8;
	  *mp++ = wc & 0x00ff;
	  break;
	case 0x8000:
	  if (lb == LEADING_BYTE_JAPANESE_JISX0208)
	    *mp++ = LEADING_BYTE_JAPANESE_JISX0212;
	  else if (lb == LEADING_BYTE_CHINESE_BIG5_1)
	    *mp++ = LEADING_BYTE_CHINESE_BIG5_2;
	  else
	    *mp++ = lb;
	  *mp++ = (wc & 0xff00) >> 8;
	  *mp++ = (wc & 0x00ff) | 0x80;
	  break;
	default:
	  *mp++ = wc & 0x00ff;
	  break;
	}
    }
  *mp = 0;
}

void
m2w (unsigned char *mp, w_char *wp)
{
  int ch;

  while ((ch = *mp++) != 0)
    {
      if (ibyte_leading_byte_p (ch))
	{
	  switch (ch)
	    {
	    case LEADING_BYTE_KATAKANA_JISX0201:
	      *wp++ = *mp++; break;
	    case LEADING_BYTE_LATIN_JISX0201:
	      *wp++ = *mp++ & 0x7F; break;
	    case LEADING_BYTE_JAPANESE_JISX0208_1978:
	    case LEADING_BYTE_CHINESE_GB2312:
	    case LEADING_BYTE_JAPANESE_JISX0208:
	    case LEADING_BYTE_KOREAN_KSC5601:
	      /* case LEADING_BYTE_TW: */
	      ch = *mp++;
	      *wp++ = (ch << 8) | *mp++;
	      break;
	    case LEADING_BYTE_JAPANESE_JISX0212:
	      ch = *mp++;
	      *wp++ = (ch << 8) | (*mp++ & 0x7f);
	      break;
	    case PRE_LEADING_BYTE_PRIVATE_1: /* #### Not sure about this one... */
	      ch = *mp++;
	      if (ch == lb_sisheng)
		*wp++ = 0x8e80 | *mp++;
	      else
		mp++;
	      break;
	    default:			/* ignore this character */
	      mp += rep_bytes_by_first_byte(ch) - 1;
	    }
	}
      else
        {
	  *wp++ = ch;
	}
    }
  *wp = 0;
}

void
w2y (w_char *w)
{
  letter		pbuf[5000], ybuf[5000];
  unsigned int		*pin;
  w_char *y;
  int len;

  pin = pbuf;
  y = w;
  while (1)
    {
      if (*w == 0)
	{*pin =0; break;}
      else	       *pin = *w;
      w++; pin++;
    }
  len = cwnn_pzy_yincod (ybuf, pbuf,
			 NILP (Vcwnn_zhuyin) ? CWNN_PINYIN : CWNN_ZHUYIN);
  if (len <= 0)
    return;

  pin = ybuf;
  while (1)
    {
      if (*pin == 0 || len == 0)
	{*y = 0;break;}
      *y = *pin;
      y++; pin++; len--;
    }
}

void
c2m (unsigned char *cp, unsigned char *mp, unsigned char lb)
{
  unsigned char	ch;
  while ((ch = *cp) != 0)
    {
      if (ch & 0x80)
	{
	  *mp++ = lb;
	  *mp++ = *cp++;
	}
      *mp++ = *cp++;
    }
  *mp = 0;
}

static int
dai_end (int no, int server)
{
  for (no++; no < jl_bun_suu (wnnfns_buf[server])
	       && !jl_dai_top (wnnfns_buf[server], no); no++);
  return (no);
}

static int
yes_or_no (unsigned char *s)
{
  unsigned char		mbuf[512];
  unsigned char		lb;
  int			len;
  int			snum;
  if ((snum  = check_wnn_server_type ()) == -1) return 0;
  lb = lb_wnn_server_type[snum];
  /* if no message found, create file without query */
  /* if (wnn_msg_cat->msg_bd == 0) return 1;*/
  if (*s == 0) return 1;
  c2m (s, mbuf, lb);
  /* truncate "(Y/N)" */
  for (len = 0; (mbuf[len]) && (len < 512); len++);
  for (; (mbuf[len] != '(') && (len > 0); len--);
  {
     Lisp_Object yes, str;
     struct gcpro gcpro1;

     str = make_string (mbuf, len);
     GCPRO1 (str);
     yes = call1(Qyes_or_no_p, str);
     UNGCPRO;
     if (NILP (yes)) return 0;
     else return (1);
  }
}

static void
puts2 (char *s)
{
#if 0 /* jhod: We don't really need this echoed... */
#if 0
  Lisp_Object		args[1];
  char			mbuf[512];
  unsigned char		lb;
  extern Lisp_Object 	Fmessage ();
  int			snum;
  if ((snum = check_wnn_server_type ()) == -1) return;
  lb = lb_wnn_server_type[snum];
  c2m (s, mbuf, lb);
  args[0] = make_string (mbuf, strlen (mbuf));
  Fmessage (1, args);
#else
  message("%s",s);
#endif
#endif
}

int
check_wnn_server_type (void)
{
  if (EQ(Vwnn_server_type, Qjserver))
    {
      return WNNSERVER_J;
    }
  else if (EQ(Vwnn_server_type, Qcserver))
    {
      return WNNSERVER_C;
    }
  /* else if (Vwnn_server_type == Qtserver)
     {
     return WNNSERVER_T;
     } */
  else if (EQ(Vwnn_server_type, Qkserver))
    {
      return WNNSERVER_K;
    }
  else return -1;
}