Submitted By: Archaic (archaic -aT- linuxfromscratch -DoT- org)
Date: 2006-03-07
Initial Package Version: 1.18.1.1
Origin: http://ftp.debian.org/debian/pool/main/g/groff/groff_1.18.1.1-11.diff.gz
Upstream Status: This is a debian-specific patch
Description: Adds the ascii8 and nippon devices to groff for man-db.

--- groff-1.18.1.1.orig/README.jp
+++ groff-1.18.1.1/README.jp
@@ -0,0 +1,142 @@
+
+                日本語対応版 groff-1.12 (jgroff-0.101)
+
+
+                                           北川 信亨 (Kitagawa Toshiyuki)
+                                                     tm-kita@kh.rim.or.jp
+
+                                           柳原 良亮 (Yanagihara Yoshiaki)
+                                                      yochi@debian.or.jp
+
+ GNUのroffフォーマッタgroff(version 1.12)の日本語対応を行ないました。
+ 上位互換となっていますので、日本語を含まないroffデータはオリジナルど
+おりの動作になります。日本語化に関する修正部分についての著作権はGNU
+General Public License Version 2 に従います(詳細はCOPYINGを御覧ください)。
+
+ 日本語groff(jgroff)の現バージョンは0.101(最終β版)です。このバージョン
+では以下のモジュールが日本語化されています。
+
+	groff	  ...	groffドライバ
+ 	gtroff	  ...	groff本体
+	grotty	  ...	端末用ポストプロセッサ
+	grops	  ...	PostScript用ポストプロセッサ
+        grohtml   ...   HTML用ポストプロセッサ(Thanks HANATAKA Shinya
+                                               <hanataka@abyss.rim.or.jp>)
+	grodvi	  ...	DVI用ポストプロセッサ (NTT JTeX or ASCII日本語TeX)
+	gxditview ...	Xウィンドウ用ポストプロセッサ
+	gtbl	  ...	tblマクロ用プリプロセッサ
+	gpic	  ...	picマクロ用プリプロセッサ
+	geqn	  ...	eqnマクロ用プリプロセッサ
+	xtotroff  ...	Xのフォントからgroff用フォントファイルを作成す
+	            	るツール
+
+＃ lj4ポストプロセッサ、bib関連のコマンドは日本語未対応です。
+
+
+◎ インストール
+
+ 以下の環境でmake出来ることを確認しています。
+
+	☆  FreeBSD 2.1.0-RELEASE
+	    XFree86-3.1.2, gcc 2.6.3
+
+	☆  Debian GNU/Linux 2.2
+
+	☆  NEC EWS/4800/310
+	    SVR4.2 Release9.1 Rev.B, X11R5, gcc 2.6.0
+
+ (1) オリジナルと同様configureを実行した後、make & installして下さい。
+    詳しくはINSTALLを参照してください。
+
+    *) grodviはNTT JTeX形式またはASCII日本語TeX形式のDVIファイルをサポー
+       トしています。groffが出力するDVIファイルをASCII日本語TeX形式に
+       したい場合はconfigure --JTeX=ASCIIとしてください。
+       --JTeXオプションを指定しなかった場合はNTT JTeX形式になります。
+
+ (2) groffのmakeの後、gxditview(groffのXウィンドウ用ポストプロセッサ)
+    をmakeします。トップディレクトリ直下のxditviewへcdして、
+
+	% xmkmf
+	% make depend
+	% make all
+	% make install install.man
+
+    で、インストール完了です。
+
+
+◎ 使い方
+
+ groffの-Tオプションに-Tnippon(端末表示)を追加した以外はオリジナルのま
+まです。
+以下は使用例。
+
+ (１)  groff -Tnippon -man groff.jman
+
+ 日本語を含むroffファイル(groff.jman)をmanマクロを使ってフォーマットし、
+端末に表示します。
+ 
+ (２)  groff -Tps -man groff.jman
+
+ 日本語を含むroffファイルをフォーマットし、PostScriptに変換します。
+
+ (３)  groff -TX100 -man groff.jman
+
+ 日本語を含むroffファイルをフォーマットし、Xウィンドウに表示します。
+
+ (４)  groff -Tdvi -man groff.jman
+
+ 日本語を含むroffファイルをフォーマットし、DVIファイルを出力します。
+
+
+◎ 日本語化について
+
+・ 日本語文字コードは日本語EUC(のコードセット1)のみサポートしています。
+
+・ 日本語フォントについては、カレントフォントがボールド体の時はゴシッ
+   ク体に、それ以外のフォント(ローマン、イタリック、イタリックボールド
+   等)がカレントフォントの時は明朝体に、自動的に切り替わります。日本語
+   フォントを直接指定することは出来ません。
+
+   (注) フォントファイル名が'B'で終っているフォント(B、TB、HNBなど)を
+        ボールドフォントとしています。
+
+・ 行頭、および行末禁則に対応しています。それぞれの禁則文字は、
+
+   行頭禁則文字:	 、 。，．・：；？！）〕］｝」』】
+			ぁぃぅぇぉっゃゅょァィゥェォッャュョ
+			. ? ! " ' ) ] * , : ; > }
+   行末禁則文字:	（ 〔［｛「『【
+
+   を定義しています。
+
+・ -Tpsを指定した場合、EUC文字とASCII文字の間には、幅の狭い空白が自動
+   的に挿入されます。この空白の幅はdevps/DESCのwcharkernで指定します。
+   unit単位です。0を指定すると空白は挿入されなくなります。
+
+・ -Tpsを指定した場合、EUC文字はASCII文字に対して少し下げて出力されま
+   す(そのままだとASCII文字が落ち込んで見えるため)。この下げ幅は
+   devps/DESCのlowerwcharで指定します。unit単位です。0を指定すると字下
+   げは行なわれません。
+
+・ オリジナルでは改行コードは無条件にスペース文字に変換されますが、EUC
+   文字で囲まれた改行コードはスペースに変換せず無視するようにしました。
+
+・ EUCのスペース文字(0xa1a1)はASCIIのスペース文字として処理されます。
+
+
+◎ 謝辞
+
+grodviのASCII日本語TeX対応は、宇都宮大学の横田さんが行なってくださいま
+した。grohtmlの日本語(EUC)対応は、花嵩信哉さんが行ってくれました。
+また、多くの方からバグに関する報告、修正イメージを送って頂きました。
+御協力くださった皆様にはとても感謝しております。有難うございました。
+
+
+◎ お願い
+
+現バージョンではlj4ポストプロセッサ、bib関連のコマンド群が日本語化され
+ておりません。これらの日本語化を行ってくださる方を募集致しております。
+ぜひ御協力ください。また、日本語対応groffに関して御意見、御希望等を
+是非お聞かせください。今後の参考にさせて頂きます(もちろんバグ報告も
+歓迎です！)。
+以上はE-Mailにて、tm-kita@kh.rim.or.jp宛にお送りください。
--- groff-1.18.1.1.orig/src/include/config.hin
+++ groff-1.18.1.1/src/include/config.hin
@@ -1,84 +1,96 @@
-/* src/include/config.hin.  Generated automatically from configure.ac by autoheader.  */
+/* src/include/config.hin.  Generated from configure.ac by autoheader.  */
 
 /* Define if your C++ doesn't understand `delete []'. */
 #undef ARRAY_DELETE_NEEDS_SIZE
 
+/* Define if you want to use multibyte extension. */
+#undef ENABLE_MULTIBYTE
+
 /* Define if you have a C++ <limits.h>. */
 #undef HAVE_CC_LIMITS_H
 
 /* Define if you have a C++ <osfcn.h>. */
 #undef HAVE_CC_OSFCN_H
 
-/* Define if you have the <dirent.h> header file. */
+/* Define to 1 if you have the <dirent.h> header file. */
 #undef HAVE_DIRENT_H
 
-/* Define if you have the `fmod' function. */
+/* Define to 1 if you have the `fmod' function. */
 #undef HAVE_FMOD
 
-/* Define if you have the `getcwd' function. */
+/* Define to 1 if you have the `getcwd' function. */
 #undef HAVE_GETCWD
 
-/* Define if you have the `getpagesize' function. */
+/* Define to 1 if you have the `getpagesize' function. */
 #undef HAVE_GETPAGESIZE
 
-/* Define if you have the `gettimeofday' function. */
+/* Define to 1 if you have the `gettimeofday' function. */
 #undef HAVE_GETTIMEOFDAY
 
-/* Define if you have the <limits.h> header file. */
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `isatty' function. */
+#undef HAVE_ISATTY
+
+/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+#undef HAVE_LANGINFO_CODESET
+
+/* Define to 1 if you have the <limits.h> header file. */
 #undef HAVE_LIMITS_H
 
-/* Define if you have the <math.h> header file. */
+/* Define to 1 if you have the <math.h> header file. */
 #undef HAVE_MATH_H
 
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
 /* Define if you have mkstemp(). */
 #undef HAVE_MKSTEMP
 
-/* Define if you have a working `mmap' system call. */
+/* Define to 1 if you have a working `mmap' system call. */
 #undef HAVE_MMAP
 
-/* Define if you have the `putenv' function. */
+/* Define to 1 if you have the `putenv' function. */
 #undef HAVE_PUTENV
 
-/* Define if you have the `rename' function. */
+/* Define to 1 if you have the `rename' function. */
 #undef HAVE_RENAME
 
-/* Define if you have the `snprintf' function. */
+/* Define to 1 if you have the `snprintf' function. */
 #undef HAVE_SNPRINTF
 
-/* Define if you have the `isatty' function. */
-#undef HAVE_ISATTY
-
-/* Define if you have the <stdint.h> header file. */
+/* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H
 
-/* Define if you have the <stdlib.h> header file. */
+/* Define to 1 if you have the <stdlib.h> header file. */
 #undef HAVE_STDLIB_H
 
-/* Define if you have the `strcasecmp' function. */
+/* Define to 1 if you have the `strcasecmp' function. */
 #undef HAVE_STRCASECMP
 
-/* Define if you have the `strerror' function. */
+/* Define to 1 if you have the `strerror' function. */
 #undef HAVE_STRERROR
 
-/* Define if you have the <strings.h> header file. */
+/* Define to 1 if you have the <strings.h> header file. */
 #undef HAVE_STRINGS_H
 
-/* Define if you have the <string.h> header file. */
+/* Define to 1 if you have the <string.h> header file. */
 #undef HAVE_STRING_H
 
-/* Define if you have the `strncasecmp' function. */
+/* Define to 1 if you have the `strncasecmp' function. */
 #undef HAVE_STRNCASECMP
 
-/* Define if you have the `strsep' function. */
+/* Define to 1 if you have the `strsep' function. */
 #undef HAVE_STRSEP
 
-/* Define if you have the `strtol' function. */
+/* Define to 1 if you have the `strtol' function. */
 #undef HAVE_STRTOL
 
 /* Define if <math.h> defines struct exception. */
 #undef HAVE_STRUCT_EXCEPTION
 
-/* Define if you have the <sys/dir.h> header file. */
+/* Define to 1 if you have the <sys/dir.h> header file. */
 #undef HAVE_SYS_DIR_H
 
 /* Define if you have sys_errlist in <errno.h> or in <stdio.h>. */
@@ -87,10 +99,16 @@
 /* Define if you have sysnerr in <errno.h> or <stdio.h>. */
 #undef HAVE_SYS_NERR
 
-/* Define if you have the <sys/time.h> header file. */
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
 #undef HAVE_SYS_TIME_H
 
-/* Define if you have the <unistd.h> header file. */
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
 /* Define if the host's encoding is EBCDIC. */
@@ -120,6 +138,21 @@
 /* Define if your C++ doesn't declare strncasecmp(). */
 #undef NEED_DECLARATION_STRNCASECMP
 
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
 /* Define if the printer's page size is A4. */
 #undef PAGEA4
 
@@ -129,7 +162,10 @@
 /* Define if srand() returns void not int. */
 #undef RET_TYPE_SRAND_IS_VOID
 
-/* Define if `sys_siglist' is declared by <signal.h> or <unistd.h>. */
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if `sys_siglist' is declared by <signal.h> or <unistd.h>. */
 #undef SYS_SIGLIST_DECLARED
 
 /* Define if your C++ compiler uses a traditional (Reiser) preprocessor. */
--- groff-1.18.1.1.orig/src/include/encoding.h
+++ groff-1.18.1.1/src/include/encoding.h
@@ -0,0 +1,175 @@
+// -*- C++ -*-
+/* Copyright (c) 2001 Fumitoshi UKAI <ukai@debian.or.jp>
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef ENCODING_H
+#define ENCODING_H
+
+#include <config.h>
+
+#ifdef ENABLE_MULTIBYTE
+typedef int wchar;	// negative is used for charcode & index
+#else
+typedef char wchar;
+#endif
+
+#include <stdio.h>
+
+#ifdef __cplusplus
+class encoding_istream {
+public:
+  encoding_istream() {};
+  virtual ~encoding_istream() {};
+  virtual int getbyte() = 0;
+  virtual int peekbyte() = 0;
+  virtual void ungetbyte(int ch) = 0;
+};
+
+class encoding_istream_str: public encoding_istream {
+private:
+  const unsigned char *s;
+  int *i;
+  encoding_istream_str() {};
+public:
+  encoding_istream_str(const unsigned char *s0, int *i0) : s(s0), i(i0) {};
+  ~encoding_istream_str() {};
+  inline int getbyte() { return s[(*i)++]; };
+  inline int peekbyte() { return s[(*i)]; };
+  inline void ungetbyte(int ch) { --(*i); };
+};
+
+class encoding_istream_fp: public encoding_istream {
+private:
+  FILE *fp;
+public:
+  encoding_istream_fp(FILE *fp0) : fp(fp0) {};
+  ~encoding_istream_fp() {};
+  inline int getbyte() { return fgetc(fp); };
+  inline int peekbyte() { int ch = fgetc(fp); ungetc(ch, fp); return ch; };
+  inline void ungetbyte(int ch) { ungetc(ch, fp); };
+};
+
+class encoding_ostream {
+public:
+  encoding_ostream() {};
+  virtual ~encoding_ostream() {};
+  virtual void putbyte(unsigned char ch) = 0;
+};
+
+class encoding_ostream_str: public encoding_ostream {
+private:
+  unsigned char *s;
+  int *i;
+  int len;
+  encoding_ostream_str() {};
+public:
+  encoding_ostream_str(unsigned char *s0, int *i0, int max) : s(s0), i(i0), len(max) {};
+  ~encoding_ostream_str() {};
+  inline void putbyte(unsigned char ch) {
+    if (*i < len)
+      s[(*i)++] = ch;
+  }
+};
+
+class encoding_ostream_fp: public encoding_ostream {
+private:
+  FILE *fp;
+  const char *format;
+public:
+  encoding_ostream_fp(FILE *ofp, const char *fmt = "%c") : fp(ofp), format(fmt) {};
+  ~encoding_ostream_fp() {};
+  inline void putbyte(unsigned char ch) {
+    fprintf(fp, format, ch);
+  }
+};
+
+class encoding_handler {
+public:
+  encoding_handler() {};
+  virtual ~encoding_handler() {};
+
+  // name of this encoding_handler
+  virtual const char *name() { return ""; };
+
+  // check if this byte is byte in multibyte character in this encoding?
+  virtual int is_wchar_byte(unsigned char c) { return 0; };
+
+  // make new wchar from c0 (beginning of multibytes) and rest from `in'
+  virtual wchar make_wchar(unsigned char c0, encoding_istream& in) { 
+    return wchar(c0);
+  }
+  // make new wchar from c0 (beginning of multibytes) and rest from `fp'
+  virtual wchar make_wchar(unsigned char c0, FILE *fp) {
+    encoding_istream_fp in(fp);
+    return make_wchar(c0, in);
+  }
+  // make new wchar from c0 (beginning of multibtyes) and rest from
+  // s[*i], *i will be changed to point the byte of next character.
+  virtual wchar make_wchar(unsigned char c0, const unsigned char *s, int *i) {
+    encoding_istream_str in(s, i);
+    return make_wchar(c0, in);
+  }
+
+  // put wchar to outputstream
+  // returns number of bytes written
+  virtual int put_wchar(wchar wc, encoding_ostream& eos) {
+    eos.putbyte((unsigned char)wc);
+    return 1;
+  }
+  // put wchar to `fp' using `fmt'
+  // returns number of bytes written
+  virtual int put_wchar(wchar wc, FILE *fp, const char *fmt = "%c") {
+    encoding_ostream_fp out(fp, fmt);
+    return put_wchar(wc, out);
+  }
+  // put wchar to s[*i] (until maxlen)
+  // *i will be changed to point the byte of next character.
+  virtual int put_wchar(wchar wc, unsigned char *s, int *i, int maxlen) {
+    encoding_ostream_str out(s, i, maxlen);
+    return put_wchar(wc, out);
+  }
+
+  // maximum number of bytes of multibyte character in this encoding
+  virtual int max_wchar_len() { return 1; };
+
+};
+
+encoding_handler* select_input_encoding_handler(const char* encoding_name);
+encoding_handler* select_output_encoding_handler(const char* encoding_name);
+extern encoding_handler* input_encoding;
+extern encoding_handler* output_encoding;
+void init_encoding_handler();
+
+// check if wc is wchar?
+int is_wchar_code(wchar wc);
+
+// check if wc is wchar & can be represented in single byte?
+int is_wchar_singlebyte(wchar wc);
+
+// get singlebyte representation of wchar (if is_wchar_singlebyte(wc))
+unsigned char wchar_singlebyte(wchar wc);
+
+// get actual wide character code
+int wchar_code(wchar wc);
+
+// make wchar from wide character code
+int make_wchar(int w);
+
+#endif
+
+#endif /* ENCODING_H */
--- groff-1.18.1.1.orig/src/include/lib.h
+++ groff-1.18.1.1/src/include/lib.h
@@ -88,8 +88,15 @@
 
 extern char invalid_char_table[];
 
+#include "encoding.h" /* XXX: ukai */
+
 inline int invalid_input_char(int c)
 {
+#ifdef ENABLE_MULTIBYTE
+  if (input_encoding->is_wchar_byte(c))
+      return 0;
+  else
+#endif
   return c >= 0 && invalid_char_table[c];
 }
 
--- groff-1.18.1.1.orig/src/include/device.h
+++ groff-1.18.1.1/src/include/device.h
@@ -18,4 +18,9 @@
 with groff; see the file COPYING.  If not, write to the Free Software
 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 
+#ifndef _DEVICE_H
+#define _DEVICE_H
+
 extern const char *device;
+
+#endif /* _DEVICE_H */
--- groff-1.18.1.1.orig/src/include/config.h
+++ groff-1.18.1.1/src/include/config.h
@@ -0,0 +1,187 @@
+/* src/include/config.h.  Generated by configure.  */
+/* src/include/config.hin.  Generated from configure.ac by autoheader.  */
+
+/* Define if your C++ doesn't understand `delete []'. */
+/* #undef ARRAY_DELETE_NEEDS_SIZE */
+
+/* Define if you want to use multibyte extension. */
+#define ENABLE_MULTIBYTE 1
+
+/* Define if you have a C++ <limits.h>. */
+#define HAVE_CC_LIMITS_H 1
+
+/* Define if you have a C++ <osfcn.h>. */
+/* #undef HAVE_CC_OSFCN_H */
+
+/* Define to 1 if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the `fmod' function. */
+#define HAVE_FMOD 1
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `isatty' function. */
+#define HAVE_ISATTY 1
+
+/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+#define HAVE_LANGINFO_CODESET 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <math.h> header file. */
+#define HAVE_MATH_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have mkstemp(). */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* Define to 1 if you have the `putenv' function. */
+#define HAVE_PUTENV 1
+
+/* Define to 1 if you have the `rename' function. */
+#define HAVE_RENAME 1
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the `strsep' function. */
+#define HAVE_STRSEP 1
+
+/* Define to 1 if you have the `strtol' function. */
+#define HAVE_STRTOL 1
+
+/* Define if <math.h> defines struct exception. */
+#define HAVE_STRUCT_EXCEPTION 1
+
+/* Define to 1 if you have the <sys/dir.h> header file. */
+#define HAVE_SYS_DIR_H 1
+
+/* Define if you have sys_errlist in <errno.h> or in <stdio.h>. */
+#define HAVE_SYS_ERRLIST 1
+
+/* Define if you have sysnerr in <errno.h> or <stdio.h>. */
+#define HAVE_SYS_NERR 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if the host's encoding is EBCDIC. */
+/* #undef IS_EBCDIC_HOST */
+
+/* Define if localtime() takes a long * not a time_t *. */
+/* #undef LONG_FOR_TIME_T */
+
+/* Define if your C++ doesn't declare gettimeofday(). */
+/* #undef NEED_DECLARATION_GETTIMEOFDAY */
+
+/* Define if your C++ doesn't declare hypot(). */
+/* #undef NEED_DECLARATION_HYPOT */
+
+/* Define if your C++ doesn't declare pclose(). */
+/* #undef NEED_DECLARATION_PCLOSE */
+
+/* Define if your C++ doesn't declare popen(). */
+/* #undef NEED_DECLARATION_POPEN */
+
+/* Define if your C++ doesn't declare putenv(). */
+/* #undef NEED_DECLARATION_PUTENV */
+
+/* Define if your C++ doesn't declare strcasecmp(). */
+/* #undef NEED_DECLARATION_STRCASECMP */
+
+/* Define if your C++ doesn't declare strncasecmp(). */
+/* #undef NEED_DECLARATION_STRNCASECMP */
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME ""
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING ""
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION ""
+
+/* Define if the printer's page size is A4. */
+#define PAGEA4 1
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* Define if srand() returns void not int. */
+#define RET_TYPE_SRAND_IS_VOID 1
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if `sys_siglist' is declared by <signal.h> or <unistd.h>. */
+#define SYS_SIGLIST_DECLARED 1
+
+/* Define if your C++ compiler uses a traditional (Reiser) preprocessor. */
+/* #undef TRADITIONAL_CPP */
+
+/* Define if the 0200 bit of the status returned by wait() indicates whether a
+   core image was produced for a process that was terminated by a signal. */
+/* #undef WCOREFLAG */
+
+/* Define if -D_POSIX_SOURCE is necessary. */
+/* #undef _POSIX_SOURCE */
+
+/* Define if you have ISC 3.x or 4.x. */
+/* #undef _SYSV3 */
+
+/* Define uintmax_t to `unsigned long' or `unsigned long long' if <inttypes.h>
+   does not exist. */
+/* #undef uintmax_t */
--- groff-1.18.1.1.orig/src/include/printer.h
+++ groff-1.18.1.1/src/include/printer.h
@@ -38,6 +38,8 @@
 
 #include "color.h"
 
+#include "encoding.h"
+
 struct environment {
   int fontno;
   int size;
@@ -63,6 +65,9 @@
   printer();
   virtual ~printer();
   void load_font(int i, const char *name);
+#ifdef	ENABLE_MULTIBYTE
+  void set_wchar_char(wchar c, char *s, int i0, int len, const environment *env, int *widthp = 0);
+#endif
   void set_ascii_char(unsigned char c, const environment *env,
 		      int *widthp = 0);
   void set_special_char(const char *nm, const environment *env,
--- groff-1.18.1.1.orig/src/include/font.h
+++ groff-1.18.1.1/src/include/font.h
@@ -18,11 +18,17 @@
 with groff; see the file COPYING.  If not, write to the Free Software
 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 
+#include "encoding.h"
+
 typedef void (*FONT_COMMAND_HANDLER)(const char *, const char *,
 				     const char *, int);
 
 struct font_kern_list;
 struct font_char_metric;
+#ifdef ENABLE_MULTIBYTE
+struct fontset_list;
+struct font_wchar_metric;
+#endif
 struct font_widths_cache;
 
 class font {
@@ -53,6 +59,9 @@
   const char *get_special_device_encoding(int index);
   const char *get_name();
   const char *get_internal_name();
+#ifdef	ENABLE_MULTIBYTE
+  const char *get_subfont_name(int index);
+#endif
 
   static int scan_papersize(const char *, const char **, double *, double *);
 
@@ -62,6 +71,9 @@
   static int load_desc();
   static int name_to_index(const char *);
   static int number_to_index(int);
+#ifdef	ENABLE_MULTIBYTE
+  static int wchar_index(wchar);
+#endif
   static FONT_COMMAND_HANDLER
     set_unknown_desc_command_handler(FONT_COMMAND_HANDLER);
 
@@ -76,6 +88,11 @@
   static int spare2;
   static int sizescale;
   static int tcommand;
+#ifdef	ENABLE_MULTIBYTE
+  // XXX: should be in charinfo or font_wchar_metric?
+  static int lowerwchar;
+  static int wcharkern;
+#endif
   static int pass_filenames;
   static int use_charnames_in_special;
 
@@ -83,13 +100,27 @@
   static const char **style_table;
   static const char *family;
   static int *sizes;
+#ifdef	ENABLE_MULTIBYTE
+  // fontsets - sub font list
+  static fontset_list *fontsets;
+  // get fontset for `wc' in current font `fname'
+  static int get_fontset_font(const char *fname, wchar wc);
+  // is the fontno's font load on demand?
+  static int is_on_demand(int fontno);
+#endif
 private:
   unsigned ligatures;
   font_kern_list **kern_hash_table;
   int space_width;
-  short *ch_index;
+  short *ch_index;	/* XXX: this is used unless font_wchar_metric. */
   int nindices;
   font_char_metric *ch;
+#ifdef ENABLE_MULTIBYTE
+  // font metric for wchar
+  font_wchar_metric *wch;
+  // get font metric for wchar indexed by c
+  font_wchar_metric *get_font_wchar_metric(int c);
+#endif
   int ch_used;
   int ch_size;
   int special;
--- groff-1.18.1.1.orig/src/include/driver.h
+++ groff-1.18.1.1/src/include/driver.h
@@ -27,6 +27,7 @@
 #include <errno.h>
 #include <assert.h>
 #include <math.h>
+#include "encoding.h" // XXX: ukai
 #include "errarg.h"
 #include "error.h"
 #include "font.h"
--- groff-1.18.1.1.orig/src/libs/libdriver/input.cc
+++ groff-1.18.1.1/src/libs/libdriver/input.cc
@@ -250,6 +250,7 @@
 
 #include "driver.h"
 #include "device.h"
+#include "encoding.h"
 
 #include <stdlib.h>
 #include <errno.h>
@@ -1439,6 +1440,19 @@
   char *subcmd_str = get_string_arg();
   char subcmd = subcmd_str[0];
   switch (subcmd) {
+#ifdef ENABLE_MULTIBYTE
+  case 'e':			// x encoding: select encoding
+    {
+      char *str_arg = get_string_arg();
+      if (str_arg == 0)
+	warning("empty argument for `x encoding' command");
+      else {
+	select_input_encoding_handler(str_arg);
+	delete str_arg;
+      }
+      break;
+    }
+#endif
   case 'f':			// x font: mount font
     {
       IntArg n = get_integer_arg();
@@ -1517,7 +1531,7 @@
   return stopped;
 }
 
-
+////////////////////////////////////////////////////////////////
 /**********************************************************************
                      exported part (by driver.h)
  **********************************************************************/
@@ -1625,6 +1639,18 @@
     if (str_arg[0] != 'i')
       fatal("the third command must be `x init'");
     delete str_arg;
+#ifdef ENABLE_MULTIBYTE
+    Char c = get_char();
+    while (is_space_or_tab(c) && c != Char('\n') && c != Char(EOF))
+	c = get_char();
+    unget_char(c);
+    if (c != Char('\n') && c != Char(EOF)) {
+	const char *tmp_encoding = get_string_arg();
+	if (tmp_encoding && *tmp_encoding)
+	    select_input_encoding_handler(tmp_encoding);
+	delete tmp_encoding;
+    }
+#endif
     skip_line_x();
   }
 
@@ -1763,6 +1789,18 @@
 	size_t i = 0;
 	while ((c = str_arg[i++]) != '\0') {
 	  EnvInt w;
+#ifdef	ENABLE_MULTIBYTE
+ 	  if (input_encoding->is_wchar_byte(c)) {
+	    int i0 = i - 1;
+ 	    wchar wc = input_encoding->make_wchar(c, (const unsigned char *)str_arg, (int *)&i);
+ 	    if (is_wchar_code(wc)) {
+	      /* XXX: singlebyte check? */
+ 	      pr->set_wchar_char(wc, str_arg, i0, i - i0, current_env, &w);
+ 	    } else {
+ 	      pr->set_ascii_char((unsigned char) c, current_env, &w);
+ 	    }
+ 	  } else
+#endif
 	  pr->set_ascii_char((unsigned char) c, current_env, &w);
 	  current_env->hpos += w;
 	}
--- groff-1.18.1.1.orig/src/libs/libdriver/printer.cc
+++ groff-1.18.1.1/src/libs/libdriver/printer.cc
@@ -27,6 +27,7 @@
 */
 
 #include "driver.h"
+#include "encoding.h"
 
 printer *pr = 0;
 
@@ -138,6 +139,24 @@
   }
 }
 
+#ifdef	ENABLE_MULTIBYTE
+void printer::set_wchar_char(wchar c, char *s, int i0, int len, const environment *env, int *widthp)
+{
+  unsigned char *buf = new unsigned char[len+1];
+  memset(buf, 0, len+1);
+  memcpy(buf, s+i0, len);
+  font *f;
+  int w;
+  int i = set_char_and_width((const char *)buf, env, &w, &f);
+  if (i != -1) {
+      set_char(c, f, env, w, (const char *)buf);
+      if (widthp)
+	  *widthp = w;
+  }
+  delete [] buf;
+}
+#endif
+
 void printer::set_special_char(const char *nm, const environment *env,
 			       int *widthp)
 {
--- groff-1.18.1.1.orig/src/libs/libgroff/fontfile.cc
+++ groff-1.18.1.1/src/libs/libgroff/fontfile.cc
@@ -24,6 +24,7 @@
 #include <assert.h>
 #include <stdlib.h>
 #include <errno.h>
+#include "encoding.h" // XXX: ukai
 #include "font.h"
 #include "searchpath.h"
 #include "device.h"
@@ -36,6 +37,10 @@
 int font::res = 0;
 int font::hor = 1;
 int font::vert = 1;
+#ifdef	ENABLE_MULTIBYTE
+int font::lowerwchar = 0;
+int font::wcharkern = 0;
+#endif
 int font::unitwidth = 0;
 int font::paperwidth = 0;
 int font::paperlength = 0;
--- groff-1.18.1.1.orig/src/libs/libgroff/font.cc
+++ groff-1.18.1.1/src/libs/libgroff/font.cc
@@ -25,6 +25,7 @@
 #include <assert.h>
 #include <math.h>
 #include <stdlib.h>
+#include "encoding.h" // XXX: ukai
 #include "errarg.h"
 #include "error.h"
 #include "cset.h"
@@ -43,8 +44,39 @@
   int italic_correction;
   int subscript_correction;
   char *special_device_coding;
+#ifdef ENABLE_MULTIBYTE
+  char *subfont_name;
+#endif
 };
 
+#ifdef ENABLE_MULTIBYTE
+struct fontset_list {
+  struct fontset_list *next;
+  char *primary_font_name;
+  int fontset_font;
+  wchar start_code;
+  wchar end_code;
+  int on_demand;
+};
+
+fontset_list *font::fontsets = NULL;
+
+struct font_wchar_metric {
+  struct font_wchar_metric *next;
+  char type;
+  int start_code;
+  int end_code;
+  int width;
+  int height;
+  int depth;
+  int pre_math_space;
+  int italic_correction;
+  int subscript_correction;
+  char *special_device_coding;
+  char *subfont_name;
+};
+#endif
+
 struct font_kern_list {
   int i1;
   int i2;
@@ -149,7 +181,11 @@
 
 font::font(const char *s)
 : ligatures(0), kern_hash_table(0), space_width(0), ch_index(0), nindices(0),
-  ch(0), ch_used(0), ch_size(0), special(0), widths_cache(0)
+  ch(0), 
+#ifdef ENABLE_MULTIBYTE
+  wch(0),
+#endif
+  ch_used(0), ch_size(0), special(0), widths_cache(0)
 {
   name = new char[strlen(s) + 1];
   strcpy(name, s);
@@ -183,6 +219,17 @@
     widths_cache = widths_cache->next;
     delete tem;
   }
+#ifdef ENABLE_MULTIBYTE
+  struct font_wchar_metric *wcp, *nwcp;
+  for (wcp = wch; wcp != NULL; wcp = nwcp) {
+    nwcp = wcp->next;
+    if (wcp->special_device_coding)
+      delete [] wcp->special_device_coding;
+    if (wcp->subfont_name)
+      delete [] wcp->subfont_name;
+    delete wcp;
+  }
+#endif
 }
 
 static int scale_round(int n, int x, int y)
@@ -244,6 +291,11 @@
 
 int font::contains(int c)
 {
+#ifdef ENABLE_MULTIBYTE
+  font_wchar_metric *wcp = get_font_wchar_metric(c);
+  if (wcp != NULL)
+    return 1;
+#endif
   return c >= 0 && c < nindices && ch_index[c] >= 0;
 }
 
@@ -266,8 +318,31 @@
   a_delete width;
 }
 
+#ifdef ENABLE_MULTIBYTE
+struct font_wchar_metric *
+font::get_font_wchar_metric(int c)
+{
+  /* XXX: c is font index, not char code... */
+  /* XXX: we assume wchar_code == font index code for wchars */
+  /* XXX: does really code conflicts with index? */
+  struct font_wchar_metric *wcp;
+  for (wcp = wch; wcp != NULL; wcp = wcp->next) {
+    if (wcp->start_code <= wchar_code(c) && wchar_code(c) <= wcp->end_code) {
+      return wcp;
+    }
+  }
+  return NULL;
+}
+#endif
+
 int font::get_width(int c, int point_size)
 {
+#ifdef ENABLE_MULTIBYTE
+  font_wchar_metric *wcp = get_font_wchar_metric(c);
+  if (wcp != NULL) {
+    return scale(wcp->width, point_size);
+  }
+#endif
   assert(c >= 0 && c < nindices);
   int i = ch_index[c];
   assert(i >= 0);
@@ -299,30 +374,60 @@
 
 int font::get_height(int c, int point_size)
 {
+#ifdef ENABLE_MULTIBYTE
+  font_wchar_metric *wcp = get_font_wchar_metric(c);
+  if (wcp != NULL) {
+    return scale(wcp->height, point_size);
+  }
+#endif
   assert(c >= 0 && c < nindices && ch_index[c] >= 0);
   return scale(ch[ch_index[c]].height, point_size);
 }
 
 int font::get_depth(int c, int point_size)
 {
+#ifdef ENABLE_MULTIBYTE
+  font_wchar_metric *wcp = get_font_wchar_metric(c);
+  if (wcp != NULL) {
+    return scale(wcp->depth, point_size);
+  }
+#endif
   assert(c >= 0 && c < nindices && ch_index[c] >= 0);
   return scale(ch[ch_index[c]].depth, point_size);
 }
 
 int font::get_italic_correction(int c, int point_size)
 {
+#ifdef ENABLE_MULTIBYTE
+  font_wchar_metric *wcp = get_font_wchar_metric(c);
+  if (wcp != NULL) {
+    return scale(wcp->italic_correction, point_size);
+  }
+#endif
   assert(c >= 0 && c < nindices && ch_index[c] >= 0);
   return scale(ch[ch_index[c]].italic_correction, point_size);
 }
 
 int font::get_left_italic_correction(int c, int point_size)
 {
+#ifdef ENABLE_MULTIBYTE
+  font_wchar_metric *wcp = get_font_wchar_metric(c);
+  if (wcp != NULL) {
+    return scale(wcp->pre_math_space, point_size);
+  }
+#endif
   assert(c >= 0 && c < nindices && ch_index[c] >= 0);
   return scale(ch[ch_index[c]].pre_math_space, point_size);
 }
 
 int font::get_subscript_correction(int c, int point_size)
 {
+#ifdef ENABLE_MULTIBYTE
+  font_wchar_metric *wcp = get_font_wchar_metric(c);
+  if (wcp != NULL) {
+    return scale(wcp->subscript_correction, point_size);
+  }
+#endif
   assert(c >= 0 && c < nindices && ch_index[c] >= 0);
   return scale(ch[ch_index[c]].subscript_correction, point_size);
 }
@@ -371,12 +476,24 @@
 
 int font::get_character_type(int c)
 {
+#ifdef ENABLE_MULTIBYTE
+  font_wchar_metric *wcp = get_font_wchar_metric(c);
+  if (wcp != NULL) {
+    return wcp->type;
+  }
+#endif
   assert(c >= 0 && c < nindices && ch_index[c] >= 0);
   return ch[ch_index[c]].type;
 }
 
 int font::get_code(int c)
 {
+#ifdef ENABLE_MULTIBYTE
+  font_wchar_metric *wcp = get_font_wchar_metric(c);
+  if (wcp != NULL) {
+    return c;
+  }
+#endif
   assert(c >= 0 && c < nindices && ch_index[c] >= 0);
   return ch[ch_index[c]].code;
 }
@@ -393,10 +510,26 @@
 
 const char *font::get_special_device_encoding(int c)
 {
+#ifdef ENABLE_MULTIBYTE
+  font_wchar_metric *wcp = get_font_wchar_metric(c);
+  if (wcp != NULL)
+    return wcp->special_device_coding;
+#endif
   assert(c >= 0 && c < nindices && ch_index[c] >= 0);
   return( ch[ch_index[c]].special_device_coding );
 }
 
+#ifdef	ENABLE_MULTIBYTE
+const char *font::get_subfont_name(int c)
+{
+  font_wchar_metric *wcp = get_font_wchar_metric(c);
+  if (wcp != NULL)
+    return wcp->subfont_name;
+  assert(c >= 0 && c < nindices && ch_index[c] >= 0);
+  return ch[ch_index[c]].subfont_name;
+}
+#endif
+
 void font::alloc_ch_index(int index)
 {
   if (nindices == 0) {
@@ -554,9 +687,11 @@
   return 0;
 }
 
+
 // If the font can't be found, then if not_found is non-NULL, it will be set
 // to 1 otherwise a message will be printed.
 
+
 int font::load(int *not_found)
 {
   char *path;
@@ -570,7 +705,7 @@
   }
   text_file t(fp, path);
   t.skip_comments = 1;
-  char *p;
+  char *p = NULL;
   for (;;) {
     if (!t.next()) {
       t.error("missing charset command");
@@ -681,6 +816,9 @@
     }
     else if (strcmp(command, "charset") == 0) {
       had_charset = 1;
+#ifdef ENABLE_MULTIBYTE
+      int had_range = 0;
+#endif
       int last_index = -1;
       for (;;) {
 	if (!t.next()) {
@@ -695,6 +833,11 @@
 	  command = nm;
 	  break;
 	}
+#ifdef ENABLE_MULTIBYTE
+	int start_code = 0;
+	int end_code = 0;
+	int nrange = sscanf(nm, "u%X..u%X", &start_code, &end_code);
+#endif
 	if (p[0] == '"') {
 	  if (last_index == -1) {
 	    t.error("first charset entry is duplicate");
@@ -711,7 +854,64 @@
 	  }
 	  copy_entry(index, last_index);
 	}
+#ifdef ENABLE_MULTIBYTE
+	else if (nrange == 2) {
+	  had_range = 1;
+	  font_wchar_metric *wcp = new font_wchar_metric;
+	  wcp->start_code = start_code;
+	  wcp->end_code = end_code;
+	  wcp->height = 0;
+	  wcp->depth = 0;
+	  wcp->pre_math_space = 0;
+	  wcp->italic_correction = 0;
+	  wcp->subscript_correction = 0;
+	  int nparms = sscanf(p, "%d,%d,%d,%d,%d,%d",
+			      &wcp->width, &wcp->height, &wcp->depth,
+			      &wcp->italic_correction,
+			      &wcp->pre_math_space,
+			      &wcp->subscript_correction);
+	  if (nparms < 1) {
+	    t.error("bad width for `%1'", nm);
+	    return 0;
+	  }
+	  p = strtok(0, WS);
+	  if (p == 0) {
+	    t.error("missing character type for `%1'", nm);
+	    return 0;
+	  }
+	  int type;
+	  if (sscanf(p, "%d", &type) != 1) {
+	    t.error("bad character type for `%1'", nm);
+	    return 0;
+	  }
+	  if (type < 0 || type > 255) {
+	    t.error("character type `%1' out of range", type);
+	    return 0;
+	  }
+	  wcp->type = type;
+
+	  p = strtok(0, WS);
+	  if ((p == 0) || (strcmp(p, "--") == 0)) {
+	    wcp->subfont_name = NULL;
+	  } else {
+	    wcp->subfont_name = new char[strlen(p) + 1];
+	    strcpy(wcp->subfont_name, p);
+	  }
+
+	  p = strtok(0, WS);
+	  if ((p == NULL) || (strcmp(p, "--") == 0)) {
+	    wcp->special_device_coding = NULL;
+	  } else {
+	    wcp->special_device_coding = new char[strlen(p) + 1];
+	    strcpy(wcp->special_device_coding, p);
+	  }
+	  wcp->next = wch;
+	  wch = wcp;
+	  p = NULL;
+	}
+#endif
 	else {
+	  
 	  font_char_metric metric;
 	  metric.height = 0;
 	  metric.depth = 0;
@@ -747,6 +947,16 @@
 	    t.error("missing code for `%1'", nm);
 	    return 0;
 	  }
+#ifdef	ENABLE_MULTIBYTE
+	  char *subp = strchr(p, ':');
+	  if (subp) {
+	    *subp++ = '\0';
+	    metric.subfont_name = new char[strlen(subp) + 1];
+	    strcpy(metric.subfont_name, subp);
+	  } else {
+	    metric.subfont_name = NULL;
+	  }
+#endif
 	  char *ptr;
 	  metric.code = (int)strtol(p, &ptr, 0);
 	  if (metric.code == 0 && ptr == p) {
@@ -777,7 +987,11 @@
 	  }
 	}
       }
+#ifdef ENABLE_MULTIBYTE
+      if (!had_range && last_index == -1) {
+#else
       if (last_index == -1) {
+#endif
 	t.error("I didn't seem to find any characters");
 	return 0;
       }
@@ -811,6 +1025,11 @@
   { "biggestfont", &font::biggestfont },
   { "spare2", &font::spare2 },
   { "sizescale", &font::sizescale }
+#ifdef	ENABLE_MULTIBYTE
+  ,
+  { "lowerwchar", &font::lowerwchar },
+  { "wcharkern", &font::wcharkern }
+#endif
   };
 
 int font::load_desc()
@@ -981,6 +1200,67 @@
       tcommand = 1;
     else if (strcmp("use_charnames_in_special", p) == 0)
       use_charnames_in_special = 1;
+#ifdef	ENABLE_MULTIBYTE
+    else if (strcmp("fontset", p) == 0) {
+      /* fontset <primary-fontname> <fontname> <code>..<code> [ondemand] */
+      p = strtok(0, WS);
+      if (p == NULL) {
+	t.error("no primary font for fontset");
+	return 0;
+      }
+      char *pfont = NULL;
+      if (strcmp(p, "-") != 0) {
+	pfont = new char[strlen(p)+1];
+	strcpy(pfont, p);
+      }
+      p = strtok(0, WS);
+      if (p == NULL) {
+	t.error("no fontset font for `%1'", 
+		pfont ? pfont : "-");
+	return 0;
+      }
+      int fontset_font = 0;
+      for (int i = 0; i < nfonts; i++) {
+	if (strcmp(p, font_name_table[i]) == 0) {
+	  fontset_font = i;
+	  break;
+	}
+      }
+      if (fontset_font == nfonts) {
+	t.error("fontset font `%1' for font `%2' not defined", 
+		p, pfont ? pfont : "-");
+	return 0;
+      }
+      p = strtok(0, WS);
+      if (p == NULL) {
+	t.error("no range for fontset font `%1' for font `%2'",
+		font_name_table[fontset_font],
+		pfont ? pfont : "-");
+	return 0;
+      }
+      wchar start_code = 0;
+      wchar end_code = 0;
+      int nparms = sscanf(p, "%x..%x", &start_code, &end_code);
+      if (nparms != 2) {
+	t.error("invalid range format `%1'", p);
+	return 0;
+      }
+      p = strtok(0, WS);
+      int on_demand = 0;
+      if (p != NULL && strcmp(p, "ondemand") == 0) {
+	on_demand = 1;
+      }
+      /* XXX */
+      fontset_list *fl = new fontset_list;
+      fl->primary_font_name = pfont;
+      fl->fontset_font = fontset_font;
+      fl->start_code = start_code;
+      fl->end_code = end_code;
+      fl->on_demand = on_demand;
+      fl->next = fontsets;
+      fontsets = fl;
+    }
+#endif
     else if (strcmp("charset", p) == 0)
       break;
     else if (unknown_desc_command_handler) {
@@ -1020,6 +1300,39 @@
   return 1;
 }      
 
+#ifdef ENABLE_MULTIBYTE
+int
+font::get_fontset_font(const char *fname, wchar wc) {
+  fontset_list *fl;
+  int avail_fontno = -1;
+  wc = wchar_code(wc);
+  for (fl = fontsets; fl != NULL; fl = fl->next) {
+    if (fl->primary_font_name == NULL) {
+      if (fl->start_code <= wc && wc <= fl->end_code) {
+	avail_fontno = fl->fontset_font;
+      }
+    }
+    else if (fname && strcmp(fl->primary_font_name, fname) == 0) {
+      if (fl->start_code <= wc && wc <= fl->end_code) {
+	return fl->fontset_font;
+      }
+    }
+  }
+  return avail_fontno;
+}
+
+int
+font::is_on_demand(int fontno) {
+  fontset_list *fl;
+  for (fl = fontsets; fl != NULL; fl = fl->next) {
+    if (fl->fontset_font == fontno) {
+      return fl->on_demand;
+    }
+  }
+  return 0;
+}
+#endif
+
 void font::handle_unknown_font_command(const char *, const char *,
 				       const char *, int)
 {
--- groff-1.18.1.1.orig/src/libs/libgroff/searchpath.cc
+++ groff-1.18.1.1/src/libs/libgroff/searchpath.cc
@@ -19,6 +19,7 @@
 with groff; see the file COPYING.  If not, write to the Free Software
 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 
+#include "encoding.h"
 #include "lib.h"
 
 #include <stdlib.h>
--- groff-1.18.1.1.orig/src/libs/libgroff/nametoindex.cc
+++ groff-1.18.1.1/src/libs/libgroff/nametoindex.cc
@@ -24,6 +24,7 @@
 #include <ctype.h>
 #include <assert.h>
 #include <stdlib.h>
+#include "encoding.h" // XXX: ukai
 #include "errarg.h"
 #include "error.h"
 #include "font.h"
@@ -37,6 +38,9 @@
   character_indexer();
   ~character_indexer();
   int ascii_char_index(unsigned char);
+#ifdef	ENABLE_MULTIBYTE
+  int wchar_index(wchar);
+#endif
   int named_char_index(const char *);
   int numbered_char_index(int);
 private:
@@ -68,6 +72,13 @@
   return ascii_index[c];
 }
 
+#ifdef	ENABLE_MULTIBYTE
+int character_indexer::wchar_index(wchar wc)
+{
+  return wc; /* XXX: wchar code == index */
+}
+#endif
+
 int character_indexer::numbered_char_index(int n)
 {
   if (n >= 0 && n < NSMALL) {
@@ -103,6 +114,30 @@
 int font::name_to_index(const char *s)
 {
   assert(s != 0 && s[0] != '\0' && s[0] != ' ');
+#ifdef	ENABLE_MULTIBYTE
+ {
+   int i = 1;
+   wchar wc = input_encoding->make_wchar(s[0], (const unsigned char *)s, &i);
+   /* XXX 
+    * if wchar can be represented in single byte (<256),
+    * it should be the same as char<wc>.
+    */
+   if (is_wchar_singlebyte(wc)) {
+       return indexer.ascii_char_index(wchar_singlebyte(wc));
+   }
+   if (is_wchar_code(wc)) {
+    return indexer.wchar_index(wc);
+   }
+   /* XXX: uA1A1 and \xa1a1 are synonyms */
+   if (s[0] == 'u') {
+     char *res;
+     long n = strtol(s + 1, &res, 16);
+     if (res != s + 1 && *res == '\0') {
+       return indexer.wchar_index(n);
+     }
+   }
+ }
+#endif
   if (s[1] == '\0')
     return indexer.ascii_char_index(s[0]);
   /* char128 and \200 are synonyms */
@@ -115,3 +150,9 @@
   return indexer.named_char_index(s);
 }
 
+#ifdef	ENABLE_MULTIBYTE
+int font::wchar_index(wchar wc)
+{
+  return indexer.wchar_index(wc);
+}
+#endif
--- groff-1.18.1.1.orig/src/libs/libgroff/encoding.cc
+++ groff-1.18.1.1/src/libs/libgroff/encoding.cc
@@ -0,0 +1,441 @@
+// -*- C++ -*-
+/* Copyright (C) 2001 Fumitoshi UKAI <ukai@debian.or.jp>
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#include "encoding.h"
+#include "device.h"
+
+#include <string.h>
+#ifdef ENABLE_MULTIBYTE
+#include <locale.h>
+#include <wchar.h>
+#ifdef HAVE_LANGINFO_CODESET
+#include <langinfo.h>
+#else
+#include <stdlib.h>
+#endif
+#endif
+
+class ascii8_handler : public encoding_handler {
+  // encoding handler for 8bit ascii
+  // no multibyte support
+public:
+  ascii8_handler() {}
+  ~ascii8_handler() {}
+
+  const char *name() { return "C"; }; /* ??? */
+
+  inline int is_wchar_byte(unsigned char c) { return 0; }
+  inline wchar make_wchar(unsigned char c0, encoding_istream& eis) {
+    return wchar(c0);
+  }
+  inline int put_wchar(wchar wc, encoding_ostream& eos) {
+    eos.putbyte((unsigned char)wchar_code(wc));
+    return 1;
+  }
+  inline int max_wchar_len() { return 1; };
+
+};
+
+#ifdef ENABLE_MULTIBYTE
+class utf8_handler: public encoding_handler {
+public:
+  utf8_handler() { } 
+  ~utf8_handler() { }
+
+  const char *name() { return "UTF-8"; };
+
+  inline int is_wchar_byte(unsigned char c) {
+    return (c >= 0x80);
+  }
+
+  /*
+   0000 0000-0000 007F   0xxxxxxx
+   0000 0080-0000 07FF   110xxxxx 10xxxxxx
+   0000 0800-0000 FFFF   1110xxxx 10xxxxxx 10xxxxxx
+
+   0001 0000-001F FFFF   11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+   0020 0000-03FF FFFF   111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+   0400 0000-7FFF FFFF   1111110x 10xxxxxx ... 10xxxxxx
+  */
+
+  inline wchar make_wchar(unsigned char c0, encoding_istream& eis) {
+    wchar wc = 0;
+    int count = 0;
+    if (! is_wchar_byte(c0)) {
+      return c0;
+    }
+    if ((c0 & 0xFC) == 0xFC) {
+      wc = c0 & 0x01;
+      count = 5;
+    } else if ((c0 & 0xF8) == 0xF8) {
+      wc = c0 & 0x03;
+      count = 4;
+    } else if ((c0 & 0xF0) == 0xF0) {
+      wc = c0 & 0x07;
+      count = 3;
+    } else if ((c0 & 0xE0) == 0xE0) {
+      wc = c0 & 0x0F;
+      count = 2;
+    } else if ((c0 & 0xC0) == 0xC0) {
+      wc = c0 & 0x1F;
+      count = 1;
+    }
+    for (; count > 0; count--) {
+      wc <<= 6;
+      int c1 = eis.getbyte();
+      if (! is_wchar_byte(c1)) {
+	/* illegal utf8 sequence? */
+      }
+      wc |= (c1 & 0x3F);
+    }
+    return -wc;	// XXX: negative
+  }
+
+  inline int put_wchar(wchar wc, encoding_ostream& eos) {
+    int count = 0;
+    if (! is_wchar_code(wc)) {
+      eos.putbyte(wc);
+      return 1;
+    }
+    wc = -wc;	// XXX: negative -> character code
+
+    if (wc < 0x800) {
+      count = 1; eos.putbyte((wc >> 6) | 0xC0);
+    } else if (wc < 0x10000) {
+      count = 2; eos.putbyte((wc >> 12) | 0xE0);
+    } else if (wc < 0x200000) {
+      count = 3; eos.putbyte((wc >> 18) | 0xF0);
+    } else if (wc < 0x4000000) {
+      count = 4; eos.putbyte((wc >> 24) | 0xf8);
+    } else if (wc <= 0x7fffffff) {
+      count = 5; eos.putbyte((wc >> 30) | 0xFC);
+    }
+    for (int i = 0; i < count; i++) {
+      eos.putbyte(((wc >> 6 * (count - i - 1)) & 0x3f) | 0x80);
+    }
+    return count;
+  }
+  inline int max_wchar_len() { return 6; }; /* XXX 3?*/
+
+};
+
+#define USE_ICONV
+#ifdef USE_ICONV
+#include <iconv.h>
+#include <errno.h>
+
+class iconv_handler : public encoding_handler {
+private:
+  iconv_t icd, ocd;
+  const char *encoding_name;
+  static iconv_handler *ih_header;
+
+public:
+  iconv_handler *next;
+
+  static iconv_handler *new_iconv_handler(const char *ename) {
+    iconv_handler *ip;
+    // if already created, use it.
+    for (ip = ih_header; ip != NULL; ip = ip->next) {
+      if (strcmp(ip->name(), ename) == 0) {
+	return ip;
+      }
+    }
+    // not found, create new one.
+    ip = new iconv_handler(ename);
+    ip->next = ih_header;
+    ih_header = ip;
+    return ip;
+  }
+  iconv_handler(const char *ename) : encoding_name(ename) {
+    // internal code is UCS-2BE
+    icd = iconv_open("UCS-2BE", encoding_name);
+    ocd = iconv_open(encoding_name, "UCS-2BE");
+  };
+  ~iconv_handler() {};
+
+  const char *name() { return encoding_name; };
+
+  inline int is_wchar_byte(unsigned char c) {
+    return (c >= 0x80); /* ??? */
+  }
+
+  inline wchar make_wchar(unsigned char c0, encoding_istream& eis) {
+    wchar wc = 0;
+    char inbuf[8], outbuf[8];
+    char *inp, *outp;
+    size_t inbytesleft, outbytesleft;
+    int i = 0;
+    
+    if (! is_wchar_byte(c0)) {
+      return c0;
+    }
+    for (inbuf[i++] = c0; ;inbuf[i++] = eis.getbyte()) {
+      inbytesleft = i;
+      outbytesleft = sizeof(outbuf);
+      inp = inbuf;
+      outp = outbuf;
+      size_t r = iconv(icd, &inp, &inbytesleft, &outp, &outbytesleft);
+      if (r == (size_t)-1) {
+	if (errno == EILSEQ) {
+	  /* illegal sequence? */
+	  return '?';
+	} else if (errno == EINVAL) {
+	  /* incomplete sequence? */
+	  continue;
+	} else if (errno == E2BIG) {
+	  /* no room to output? */
+	  return '?';
+	}
+      }
+      /* ok */
+      /* UCS-2 is 2 bytes */
+      wc = ((outbuf[0] & 0x0ff) << 8) | (outbuf[1] & 0x0ff);
+      return -wc;	// XXX: negative
+    }
+  }
+
+
+  inline int put_wchar(wchar wc, encoding_ostream& eos) {
+    char inbuf[4], outbuf[4];
+    char *inp, *outp;
+    size_t inbytesleft, outbytesleft;
+
+    if (!is_wchar_code(wc)) {
+      eos.putbyte(wc & 0x0ff);
+      return 1;
+    }
+    wc = -wc;	// XXX: negative -> character code
+
+    inbuf[0] = (wc >> 8) & 0x0ff;
+    inbuf[1] = (wc >> 0) & 0x0ff;
+    inbuf[2] = 0;
+    inbytesleft = 2;
+    outbytesleft = 4;
+    inp = inbuf;
+    outp = outbuf;
+    size_t r = iconv(ocd, &inp, &inbytesleft, &outp, &outbytesleft);
+    if (r == (size_t)-1) {
+      if (errno == EILSEQ) {
+	/* illegal sequence? */;
+      } else if (errno == EINVAL) {
+	/* incomplete sequence? */;
+      } else if (errno == E2BIG) {
+	/* no room to output? */;
+      }
+      eos.putbyte('?');
+      return 1;
+    }
+    char *op = outbuf;
+    int n = 0;
+    for (; op < outp; op++, n++) {
+      eos.putbyte(*op & 0x0ff);
+    }
+    return outp - outbuf;
+  }
+  inline int max_wchar_len() { return 6; }; /* XXX */
+
+};
+#else
+class euc_handler : public encoding_handler {
+  static const int WCTABLE_OFFSET = 0xa1;
+  static const int WCTABLE_SIZE = 94;
+  static const int EUCMASK = 0x8080;
+
+public:
+  euc_handler() {}
+  ~euc_handler() {};
+
+  const char *name() { return "EUC-JP"; };
+
+  inline int is_wchar_byte(unsigned char c) {
+    return (c >= 0xa1 && c <= 0xfe);
+  }
+
+  inline wchar make_wchar(unsigned char c0, encoding_istream& eis) {
+    wchar wc;
+    if (! is_wchar_byte(c0)) {
+      return c0;
+    }
+    int c1 = eis.peekbyte();
+    if (! is_wchar_byte(c1)) {
+      eis.ungetbyte(c1);
+      return c0;
+    }
+    c1 = eis.getbyte();
+    wc = (c0 & 0xff) << 8;
+    wc |= (c1 & 0xff);
+
+    if (wc == 0xa1a1)
+      return ' ';
+    return -wc;
+  }
+
+  inline int put_wchar(wchar wc, encoding_ostream& eos) {
+    if (is_wchar_code(wc)) {
+      wc = -wc;
+      eos.putbyte((wc >> 8) & 0x0ff);
+      eos.putbyte((wc >> 0) & 0x0ff);
+      return 2;    
+    } else {
+      eos.putbyte(wc & 0x0ff);
+      return 1;
+    }
+  }
+  inline int max_wchar_len() { return 2; }; /* XXX */
+};
+#endif /* USE_ICONV */
+#endif
+
+static ascii8_handler ascii8;
+#ifdef ENABLE_MULTIBYTE
+static utf8_handler utf8;
+#ifdef USE_ICONV
+iconv_handler *iconv_handler::ih_header = NULL;
+#else
+static euc_handler eucjp;
+#endif
+#endif
+
+encoding_handler *input_encoding = &ascii8;
+encoding_handler *output_encoding = &ascii8;
+
+static void
+new_encoding_handler(encoding_handler **eptr, const char *encoding_name)
+{
+  if (!encoding_name) {
+    *eptr = &ascii8;
+    return;
+  }
+#ifdef ENABLE_MULTIBYTE
+  if (strcmp(encoding_name, "UTF-8") == 0) {
+    *eptr = &utf8;
+    return;
+  }
+#ifdef USE_ICONV
+  if (strcmp(encoding_name, "C") != 0) {
+    *eptr = iconv_handler::new_iconv_handler(encoding_name);
+    return;
+  }
+#else
+  // printf("encoding request: [%s]\n", encoding_name);
+  if (strcmp(encoding_name, "EUC-JP") == 0) {
+    // printf("encoding: [EUC-JP]\n");
+    *eptr = &eucjp;
+    return;
+  }
+#endif
+#endif
+  // default
+  *eptr = &ascii8;
+  return;
+}
+
+encoding_handler *
+select_input_encoding_handler(const char *encoding_name)
+{
+  new_encoding_handler(&input_encoding, encoding_name);
+  return input_encoding;
+}
+
+encoding_handler *
+select_output_encoding_handler(const char *encoding_name)
+{
+  new_encoding_handler(&output_encoding, encoding_name);
+  return output_encoding;
+}
+
+void
+init_encoding_handler()
+{
+#ifdef ENABLE_MULTIBYTE
+  const char *locale, *charset;
+  // groff 1 defines ISO-8859-1 as the input encoding, so this is required
+  // for compatibility. groff 2 will define UTF-8 (or possibly officially
+  // allow it to be switchable?)
+  select_input_encoding_handler("ISO-8859-1");
+  select_output_encoding_handler("C");
+
+  locale = setlocale(LC_ALL, "");
+  if (locale == NULL ||
+      strcmp(locale, "C") == 0 || strcmp(locale, "POSIX") == 0) {
+    return;
+  }
+  /* check LC_CTYPE is C or POSIX */
+  locale = setlocale(LC_CTYPE, NULL);
+  if (strcmp(locale, "C") == 0 || strcmp(locale, "POSIX") == 0) {
+    return;
+  }
+  /* otherwise */
+#if HAVE_LANGINFO_CODESET
+  charset = nl_langinfo(CODESET);
+#else
+  charset = strchr(locale, '.');
+  if (charset)
+    ++charset;
+  else
+    charset = "";
+#endif
+  if (strncmp(locale, "ja", 2) == 0 || strncmp(locale, "zh", 2) == 0 ||
+      (strncmp(locale, "ko", 2) == 0 && strcmp(charset, "UTF-8") == 0)) {
+    select_input_encoding_handler(charset);
+    select_output_encoding_handler(charset);
+  } else if ((!device || strcmp(device, "ascii8") == 0)) {
+    select_input_encoding_handler(NULL);
+    select_output_encoding_handler(NULL);
+  }
+#endif
+  return;
+}
+
+int
+is_wchar_code(wchar wc)
+{
+  return (wc < 0);
+}
+
+int
+is_wchar_singlebyte(wchar wc)
+{
+    return ((-256 < wc) && (wc < 0));
+}
+
+unsigned char
+wchar_singlebyte(wchar wc)
+{
+    if (wc >= 0)
+	return (unsigned char)wc;
+    else
+	return (unsigned char)-wc;
+}
+
+int
+wchar_code(wchar wc)
+{
+    if (wc >= 0)
+	return wc;
+    else
+	return -wc;
+}
+
+int
+make_wchar(int w)
+{
+    return -w;
+}
--- groff-1.18.1.1.orig/src/libs/libgroff/Makefile.sub
+++ groff-1.18.1.1/src/libs/libgroff/Makefile.sub
@@ -6,6 +6,7 @@
   color.$(OBJEXT) \
   cset.$(OBJEXT) \
   device.$(OBJEXT) \
+  encoding.$(OBJEXT) \
   errarg.$(OBJEXT) \
   error.$(OBJEXT) \
   fatal.$(OBJEXT) \
@@ -45,6 +46,7 @@
   $(srcdir)/color.cc \
   $(srcdir)/cset.cc \
   $(srcdir)/device.cc \
+  $(srcdir)/encoding.cc \
   $(srcdir)/errarg.cc \
   $(srcdir)/error.cc \
   $(srcdir)/fatal.cc \
--- groff-1.18.1.1.orig/src/libs/libgroff/tmpfile.cc
+++ groff-1.18.1.1/src/libs/libgroff/tmpfile.cc
@@ -24,6 +24,7 @@
 #include <errno.h>
 #include <stdlib.h>
 
+#include "encoding.h"
 #include "posix.h"
 #include "errarg.h"
 #include "error.h"
--- groff-1.18.1.1.orig/src/utils/tfmtodit/tfmtodit.cc
+++ groff-1.18.1.1/src/utils/tfmtodit/tfmtodit.cc
@@ -650,7 +650,7 @@
 gives the groff name of the character, `i' gives its index in
 the encoding, which is filled in later  (-1 if it does not appear). */
 
-struct {
+struct S {
   const char *ch;
   int i;
 } lig_chars[] = {
@@ -670,7 +670,7 @@
 
 // Each possible ligature appears in this table.
 
-struct {
+struct S2 {
   unsigned char c1, c2, res;
   const char *ch;
 } lig_table[] = {
--- groff-1.18.1.1.orig/src/preproc/eqn/eqn.y
+++ groff-1.18.1.1/src/preproc/eqn/eqn.y
@@ -21,6 +21,7 @@
 #include <string.h>
 #include <stdlib.h>
 
+#include "encoding.h" /* XXX */
 #include "lib.h"
 #include "box.h"
 extern int non_empty_flag;
--- groff-1.18.1.1.orig/src/preproc/eqn/lex.cc
+++ groff-1.18.1.1/src/preproc/eqn/lex.cc
@@ -23,6 +23,7 @@
 #include "eqn_tab.h"
 #include "stringclass.h"
 #include "ptable.h"
+#include "encoding.h"
 
 struct definition {
   char is_macro;
@@ -375,6 +376,11 @@
 	lex_error("invalid input character code %1", c);
       else {
 	line += char(c);
+#ifdef	ENABLE_MULTIBYTE
+	if (input_encoding->is_wchar_byte(c)) {
+	  line += char(getc(fp));
+	}
+#endif
 	if (c == '\n') 
 	  break;
       }
--- groff-1.18.1.1.orig/src/preproc/eqn/main.cc
+++ groff-1.18.1.1/src/preproc/eqn/main.cc
@@ -258,6 +258,7 @@
   program_name = argv[0];
   static char stderr_buf[BUFSIZ];
   setbuf(stderr, stderr_buf);
+  init_encoding_handler();
   int opt;
   int load_startup_file = 1;
   static const struct option long_options[] = {
--- groff-1.18.1.1.orig/src/preproc/eqn/text.cc
+++ groff-1.18.1.1/src/preproc/eqn/text.cc
@@ -21,13 +21,20 @@
 #include "eqn.h"
 #include "pbox.h"
 #include "ptable.h"
+#include "encoding.h"
 
 class char_box : public simple_box {
   unsigned char c;
+#ifdef	ENABLE_MULTIBYTE
+  wchar wc;
+#endif
   char next_is_italic;
   char prev_is_italic;
 public:
   char_box(unsigned char);
+#ifdef	ENABLE_MULTIBYTE
+  char_box(unsigned char, wchar);
+#endif
   void debug_print();
   void output();
   int is_char();
@@ -165,11 +172,22 @@
 }
 
 char_box::char_box(unsigned char cc)
-: c(cc), next_is_italic(0), prev_is_italic(0)
+: c(cc),
+#ifdef	ENABLE_MULTIBYTE
+  wc(cc),
+#endif
+  next_is_italic(0), prev_is_italic(0)
 {
   spacing_type = char_table[c].spacing_type;
 }
 
+#ifdef	ENABLE_MULTIBYTE
+char_box::char_box(unsigned char cc, wchar wc)
+: c(cc), wc(wc), next_is_italic(0), prev_is_italic(0)
+{
+}
+#endif
+
 void char_box::hint(unsigned flags)
 {
   if (flags & HINT_PREV_IS_ITALIC)
@@ -188,7 +206,11 @@
   if (c == '\\')
     fputs("\\e", stdout);
   else
+#ifdef	ENABLE_MULTIBYTE
+    output_encoding->put_wchar(wc, stdout);
+#else
     putchar(c);
+#endif
   if (!next_is_italic)
     fputs("\\/", stdout);
   else
@@ -497,6 +519,14 @@
       break;
     default:
     normal_char:
+#ifdef	ENABLE_MULTIBYTE
+      if (input_encoding->is_wchar_byte(c)) {
+        int i = 1;
+	wchar wc = input_encoding->make_wchar(c, (unsigned char *)s, &i);
+	b = new char_box('A', wc); // char_info of wc is same the 'A'.
+	s += i;
+      } else
+#endif
       b = new char_box(c);
       break;
     }
--- groff-1.18.1.1.orig/src/preproc/eqn/box.cc
+++ groff-1.18.1.1/src/preproc/eqn/box.cc
@@ -80,7 +80,7 @@
 
 int nroff = 0;			// should we grok ndefine or tdefine?
 
-struct {
+struct S {
   const char *name;
   int *ptr;
 } param_table[] = {
--- groff-1.18.1.1.orig/src/preproc/html/pre-html.cc
+++ groff-1.18.1.1/src/preproc/html/pre-html.cc
@@ -63,6 +63,10 @@
 #define DEFAULT_IMAGE_RES        100   // number of pixels per inch resolution
 #define IMAGE_BOARDER_PIXELS       0
 #define INLINE_LEADER_CHAR      '\\'
+#define A4_LENGTH             841890   // taken from devps/Makefile.sub
+#define LETTER_LENGTH         792000   // taken from devps/Makefile.sub
+#define A4_OFFSET                  0
+#define LETTER_OFFSET             50   // 50/72 of an inch
 
 #define TRANSPARENT  "-background white -transparent white"
 #define MIN_ALPHA_BITS             0
@@ -104,6 +108,7 @@
 static char *macroset_template= NULL;           // image template passed to troff by -D
 static int   troff_arg        = 0;              // troff arg index
 static char *image_dir        = NULL;           // user specified image directory
+static char *gsPaper          = NULL;           // the paper size that gs must use
 static int   textAlphaBits    = MAX_ALPHA_BITS;
 static int   graphicAlphaBits = MAX_ALPHA_BITS;
 static char *antiAlias        = NULL;           // antialias arguments we pass to gs.
@@ -211,6 +216,54 @@
 }
 
 /*
+ *  get_papersize - returns an integer determining the paper length from
+ *  devps/DESC
+ */
+
+static int get_papersize (void)
+{
+  char *pathp;
+  FILE *f;
+  int res;
+  f = font_path.open_file("devps/DESC", &pathp);
+  if (f == 0)
+    fatal("can't open devps/DESC");
+  while (get_line(f)) {
+    int n = sscanf(linebuf, "paperlength %d", &res);
+    if (n >= 1) {
+      fclose(f);
+      return res;
+    }
+    if (!strncmp(linebuf, "papersize", 9)) {
+      double length;
+      char *p = linebuf + 9;
+      while (*p == ' ' || *p == '\t')
+        p++;
+      for (p = strtok(p, " \t"); p; p = strtok(0, " \t")) {
+        if (font::scan_papersize(p, 0, &length, 0)) {
+          fclose(f);
+          return int(length * postscriptRes + 0.5);
+        }
+      }
+      fatal("bad argument to `papersize' keyword in devps/DESC");
+    }
+  }
+  fatal("can't find `papersize' or `paperlength' keyword in devps/DESC");
+  return 0;
+}
+
+/*
+ *  determine_vertical_offset - works out the default vertical offset from
+ *                              the page length
+ */
+
+static void determine_vertical_offset (void)
+{
+  vertical_offset = ((A4_LENGTH-get_papersize())*72)/postscriptRes;
+  gsPaper = "-sPAPERSIZE=a4";
+}
+
+/*
  *  html_system - a wrapper for system()
  */
 
@@ -1469,6 +1522,7 @@
   int ok=1;
 
   postscriptRes = get_resolution();
+  determine_vertical_offset();
   i = scanArguments(argc, argv);
   setupAntiAlias();
   checkImageDir();
--- groff-1.18.1.1.orig/src/preproc/grn/hdb.cc
+++ groff-1.18.1.1/src/preproc/grn/hdb.cc
@@ -115,7 +115,6 @@
     type = DBGetType(string);	/* interpret element type */
     if (type < 0) {		/* no more data */
       done = TRUE;
-      (void) fclose(file);
     } else {
 #ifdef UW_FASTSCAN
       (void) xscanf(file, &x, &y);		/* always one point */
--- groff-1.18.1.1.orig/src/preproc/refer/command.cc
+++ groff-1.18.1.1/src/preproc/refer/command.cc
@@ -632,7 +632,7 @@
 ? means that the previous argument is optional, * means that the
 previous argument can occur any number of times. */
 
-struct {
+struct S {
   const char *name;
   command_t func;
   const char *arg_types;
--- groff-1.18.1.1.orig/src/devices/grotty/grotty.man
+++ groff-1.18.1.1/src/devices/grotty/grotty.man
@@ -50,7 +50,9 @@
 command
 with a
 .BR \-Tascii ,
-.B \-Tlatin1
+.BR \-Tascii8 ,
+.BR \-Tlatin1 ,
+.B \-Tnippon
 or
 .B \-Tutf8
 option on ASCII based systems, and with
@@ -235,8 +237,10 @@
 .I name
 is the name of the device, usually
 .BR ascii ,
+.BR ascii8 ,
 .BR latin1 ,
 .BR utf8 ,
+.B  nippon
 or
 .BR cp1047 .
 .TP
@@ -315,10 +319,20 @@
 device.
 .
 .TP
+.B @FONTDIR@/devascii8/DESC
+Device description file for
+.B ascii8
+device.
+.TP
 .B @FONTDIR@/devlatin1/DESC
 Device description file for
 .B latin1
 device.
+.TP
+.B @FONTDIR@/devnippon/DESC
+Device description file for
+.B nippon
+device.
 .
 .TP
 .BI @FONTDIR@/devlatin1/ F
--- groff-1.18.1.1.orig/src/devices/grotty/tty.cc
+++ groff-1.18.1.1/src/devices/grotty/tty.cc
@@ -20,6 +20,7 @@
 
 #include "driver.h"
 #include "device.h"
+#include "encoding.h"
 
 extern "C" const char *Version_string;
 
@@ -51,8 +52,18 @@
   HDRAW_MODE = 0x08,
   CU_MODE = 0x10,
   COLOR_CHANGE = 0x20
+#ifdef ENABLE_MULTIBYTE
+  , WCHAR_MODE = 0x100
+#endif
 };
 
+#ifdef ENABLE_MULTIBYTE
+# ifdef putchar
+#  undef putchar
+# endif
+#define putchar(wc)	output_encoding->put_wchar((wc), stdout)
+#endif
+
 // Mode to use for bold-underlining.
 static unsigned char bold_underline_mode = BOLD_MODE|UNDERLINE_MODE;
 
@@ -89,6 +100,7 @@
   static tty_font *load_tty_font(const char *);
 };
 
+
 tty_font *tty_font::load_tty_font(const char *s)
 {
   tty_font *f = new tty_font(s);
@@ -98,8 +110,26 @@
   }
   const char *num = f->get_internal_name();
   long n;
+#ifdef ENABLE_MULTIBYTE
+  if (num != 0) {
+    n = strtol(num, 0, 0);
+    switch (n) {
+    case 1:
+      f->mode = int(UNDERLINE_MODE);
+      break;
+    case 2:
+    case 5:
+      f->mode = int(BOLD_MODE);
+      break;
+    case 3:
+      f->mode = int(BOLD_MODE|UNDERLINE_MODE);
+      break;
+    }
+  }
+#else
   if (num != 0 && (n = strtol(num, 0, 0)) != 0)
     f->mode = int(n & (BOLD_MODE|UNDERLINE_MODE));
+#endif
   if (!underline_flag)
     f->mode &= ~UNDERLINE_MODE;
   if (!bold_flag)
@@ -135,6 +165,9 @@
   short hpos;
   unsigned int code;
   unsigned char mode;
+#ifdef ENABLE_MULTIBYTE
+  short cols;
+#endif
   unsigned char back_color_idx;
   unsigned char fore_color_idx;
   void *operator new(size_t);
@@ -184,7 +217,7 @@
   void make_underline();
   void make_bold(unsigned int);
   unsigned char color_to_idx(color *col);
-  void add_char(unsigned int, int, int, color *, color *, unsigned char);
+  void add_char(unsigned int, int, int, color *, color *, font *, unsigned char);
 public:
   tty_printer(const char *device);
   ~tty_printer();
@@ -193,7 +226,7 @@
   void special(char *arg, const environment *env, char type);
   void change_color(const environment *env);
   void change_fill_color(const environment *env);
-  void put_char(unsigned int);
+  int put_char(unsigned int);
   void put_color(unsigned char, int);
   void begin_page(int) { }
   void end_page(int page_length);
@@ -203,6 +236,10 @@
 tty_printer::tty_printer(const char *device) : cached_v(0)
 {
   is_utf8 = !strcmp(device, "utf8");
+#ifdef ENABLE_MULTIBYTE
+  if (is_utf8)
+      select_output_encoding_handler("UTF-8");
+#endif
   tty_colors[0].set_rgb(0,			// black
  			0,
 			0);
@@ -242,8 +279,18 @@
 void tty_printer::make_underline()
 {
   if (old_drawing_scheme) {
+#if 0 /* def ENABLE_MULTIBYTE XXX: not necessary? */
+    if ((p->mode & WCHAR_MODE)) {
+	putchar('_'); putchar('_');
+	putchar('\b'); putchar('\b');
+    } else {
+	putchar('_');
+	putchar('\b');
+    }
+#else
     putchar('_');
     putchar('\b');
+#endif
   }
   else {
     if (!is_underline) {
@@ -285,17 +332,25 @@
 void tty_printer::set_char(int i, font *f, const environment *env,
 			   int w, const char *name)
 {
+#ifdef ENABLE_MULTIBYTE
+  if (is_wchar_code(i)) {
+    add_char(wchar_code(i), env->hpos, env->vpos, env->col, env->fill, 
+	     f, ((tty_font *)f)->get_mode());
+    return;
+  }
+#endif
   if (w != font::hor)
     fatal("width of character not equal to horizontal resolution");
   add_char(f->get_code(i),
 	   env->hpos, env->vpos,
 	   env->col, env->fill,
-	   ((tty_font *)f)->get_mode());
+	   f, ((tty_font *)f)->get_mode());
 }
 
 void tty_printer::add_char(unsigned int c,
 			   int h, int v,
 			   color *fore, color *back,
+			   font *curfont,
 			   unsigned char mode)
 {
 #if 0
@@ -338,6 +393,16 @@
   g->code = c;
   g->fore_color_idx = color_to_idx(fore);
   g->back_color_idx = color_to_idx(back);
+#ifdef ENABLE_MULTIBYTE
+  if (is_wchar_code(c))
+    mode |= WCHAR_MODE;
+  if (curfont && curfont->contains(c)) {
+      int gw0 = curfont->get_space_width(font::unitwidth);
+      int gw = curfont->get_width(c, font::unitwidth);
+      g->cols = gw/gw0;
+  } else
+      g->cols = 1;	/* XXX */
+#endif
   g->mode = mode;
 
   // The list will be reversed later.  After reversal, it must be in
@@ -357,7 +422,7 @@
 void tty_printer::special(char *arg, const environment *env, char type)
 {
   if (type == 'u') {
-    add_char(*arg - '0', env->hpos, env->vpos, env->col, env->fill, CU_MODE);
+    add_char(*arg - '0', env->hpos, env->vpos, env->col, env->fill, get_font_from_index(env->fontno), CU_MODE);
     return;
   }
   if (type != 'p')
@@ -395,12 +460,12 @@
 
 void tty_printer::change_color(const environment *env)
 {
-  add_char(0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE);
+  add_char(0, env->hpos, env->vpos, env->col, env->fill, get_font_from_index(env->fontno), COLOR_CHANGE);
 }
 
 void tty_printer::change_fill_color(const environment *env)
 {
-  add_char(0, env->hpos, env->vpos, env->col, env->fill, COLOR_CHANGE);
+  add_char(0, env->hpos, env->vpos, env->col, env->fill, get_font_from_index(env->fontno), COLOR_CHANGE);
 }
 
 void tty_printer::draw(int code, int *p, int np, const environment *env)
@@ -420,7 +485,7 @@
       len = -len;
     }
     while (len >= 0) {
-      add_char('|', env->hpos, v, env->col, env->fill, VDRAW_MODE);
+      add_char('|', env->hpos, v, env->col, env->fill, get_font_from_index(env->fontno), VDRAW_MODE);
       len -= font::vert;
       v += font::vert;
     }
@@ -434,18 +499,24 @@
       len = -len;
     }
     while (len >= 0) {
-      add_char('-', h, env->vpos, env->col, env->fill, HDRAW_MODE);
+      add_char('-', h, env->vpos, env->col, env->fill, get_font_from_index(env->fontno), HDRAW_MODE);
       len -= font::hor;
       h += font::hor;
     }
   }
 }
 
-void tty_printer::put_char(unsigned int wc)
+int tty_printer::put_char(unsigned int wc)
 {
+#ifdef ENABLE_MULTIBYTE
+  if (wc >= 0x80) {
+    return output_encoding->put_wchar(make_wchar(wc), stdout);
+  }
+#else
   if (is_utf8 && wc >= 0x80) {
     char buf[6 + 1];
     int count;
+    int len;
     char *p = buf;
     if (wc < 0x800)
       count = 1, *p = (unsigned char)((wc >> 6) | 0xc0);
@@ -458,14 +529,18 @@
     else if (wc <= 0x7fffffff)
       count = 5, *p = (unsigned char)((wc >> 30) | 0xfC);
     else
-      return;
+      return 0;
+    len = count;
     do *++p = (unsigned char)(((wc >> (6 * --count)) & 0x3f) | 0x80);
       while (count > 0);
     *++p = '\0';
     putstring(buf);
+    return len;
   }
+#endif
   else
     putchar(wc);
+  return 1;
 }
 
 void tty_printer::put_color(unsigned char color_index, int back)
@@ -629,7 +704,11 @@
 	}
       }
       put_char(p->code);
+#ifdef ENABLE_MULTIBYTE
+      hpos += p->cols;
+#else
       hpos++;
+#endif
     }
     if (!old_drawing_scheme
 	&& (is_bold || is_underline
@@ -667,6 +746,7 @@
   if (getenv("GROFF_NO_SGR"))
     old_drawing_scheme = 1;
   setbuf(stderr, stderr_buf);
+  init_encoding_handler();
   int c;
   static const struct option long_options[] = {
     { "help", no_argument, 0, CHAR_MAX + 1 },
--- groff-1.18.1.1.orig/src/devices/grops/ps.cc
+++ groff-1.18.1.1/src/devices/grops/ps.cc
@@ -24,6 +24,7 @@
 #include "cset.h"
 #include "nonposix.h"
 #include "paper.h"
+#include "encoding.h"
 
 #include "ps.h"
 #include <time.h>
@@ -193,12 +194,23 @@
   return *this;
 }
 
+#ifdef ENABLE_MULTIBYTE
+ps_output &ps_output::put_string(const wchar *s, int n)
+#else
 ps_output &ps_output::put_string(const char *s, int n)
+#endif
 {
   int len = 0;
   int i;
   for (i = 0; i < n; i++) {
+#ifdef ENABLE_MULTIBYTE
+    wchar wc = s[i];
+    char c = 0;
+    if (is_wchar_singlebyte(wc))
+      c = wchar_singlebyte(wc);
+#else
     char c = s[i];
+#endif
     if (is_ascii(c) && csprint(c)) {
       if (c == '(' || c == ')' || c == '\\')
 	len += 2;
@@ -224,8 +236,13 @@
 	putc('\n', fp);
 	col = 0;
       }
+#ifdef	ENABLE_MULTIBYTE
+      int nb = output_encoding->put_wchar(s[i], fp, "%02x");
+      col += nb * 2;
+#else
       fprintf(fp, "%02x", s[i] & 0377);
       col += 2;
+#endif
     }
     putc('>', fp);
     col++;
@@ -396,6 +413,9 @@
   int encoding_index;
   char *encoding;
   char *reencoded_name;
+#ifdef ENABLE_MULTIBYTE
+  char *encodingname;
+#endif
   ~ps_font();
   void handle_unknown_font_command(const char *command, const char *arg,
 				   const char *filename, int lineno);
@@ -414,6 +434,9 @@
 
 ps_font::ps_font(const char *nm)
 : font(nm), encoding_index(-1), encoding(0), reencoded_name(0)
+#ifdef ENABLE_MULTIBYTE
+  , encodingname(0)
+#endif
 {
 }
 
@@ -421,6 +444,9 @@
 {
   a_delete encoding;
   a_delete reencoded_name;
+#ifdef ENABLE_MULTIBYTE
+  a_delete encodingname;
+#endif
 }
 
 void ps_font::handle_unknown_font_command(const char *command, const char *arg,
@@ -433,6 +459,15 @@
     else
       encoding = strsave(arg);
   }
+#ifdef ENABLE_MULTIBYTE
+  if (strcmp(command, "encodingname") == 0) {
+    if (arg == 0)
+      error_with_file_and_line(filename, lineno,
+			       "`encodingname' command requires an argument");
+    else
+      encodingname = strsave(arg);
+  }
+#endif
 }
 
 static void handle_unknown_desc_command(const char *command, const char *arg,
@@ -487,7 +522,11 @@
   int paper_length;
   int equalise_spaces;
   enum { SBUF_SIZE = 256 };
+#ifdef	ENABLE_MULTIBYTE
+  wchar sbuf[SBUF_SIZE];
+#else
   char sbuf[SBUF_SIZE];
+#endif
   int sbuf_len;
   int sbuf_start_hpos;
   int sbuf_vpos;
@@ -606,7 +645,11 @@
 {
   if (i == space_char_index || invis_count > 0)
     return;
+#ifdef	ENABLE_MULTIBYTE
+  wchar code = f->get_code(i);
+#else
   unsigned char code = f->get_code(i);
+#endif
   style sty(f, env->size, env->height, env->slant);
   if (sty.slant != 0) {
     if (sty.slant > 80 || sty.slant < -80) {
@@ -763,6 +806,14 @@
     if (sty == defined_styles[i]) {
       sprintf(buf, "F%d", i);
       out.put_symbol(buf);
+#ifdef ENABLE_MULTIBYTE
+      char *encodingname = ((ps_font *)sty.f)->encodingname;
+      if (encodingname != 0) {
+	select_output_encoding_handler(encodingname);
+      } else {
+	select_output_encoding_handler("LATIN1");
+      }
+#endif
       return;
     }
   if (ndefined_styles >= MAX_DEFINED_STYLES)
@@ -772,6 +823,14 @@
   const char *psname = sty.f->get_internal_name();
   if (psname == 0)
     fatal("no internalname specified for font `%1'", sty.f->get_name());
+#ifdef ENABLE_MULTIBYTE
+  char *encodingname = ((ps_font *)sty.f)->encodingname;
+  if (encodingname != 0) {
+    select_output_encoding_handler(encodingname);
+  } else {
+    select_output_encoding_handler("LATIN1");
+  }
+#endif
   char *encoding = ((ps_font *)sty.f)->encoding;
   if (encoding != 0) {
     char *s = ((ps_font *)sty.f)->reencoded_name;
@@ -1555,6 +1614,7 @@
   string env;
   static char stderr_buf[BUFSIZ];
   setbuf(stderr, stderr_buf);
+  init_encoding_handler();
   int c;
   static const struct option long_options[] = {
     { "help", no_argument, 0, CHAR_MAX + 1 },
--- groff-1.18.1.1.orig/src/devices/grops/ps.h
+++ groff-1.18.1.1/src/devices/grops/ps.h
@@ -18,10 +18,16 @@
 with groff; see the file COPYING.  If not, write to the Free Software
 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 
+#include "encoding.h" // XXX
+
 class ps_output {
 public:
   ps_output(FILE *, int max_line_length);
+#ifdef	ENABLE_MULTIBYTE
+  ps_output &put_string(const wchar *, int);
+#else
   ps_output &put_string(const char *, int);
+#endif
   ps_output &put_number(int);
   ps_output &put_fix_number(int);
   ps_output &put_float(double);
--- groff-1.18.1.1.orig/src/devices/grohtml/html.h
+++ groff-1.18.1.1/src/devices/grohtml/html.h
@@ -49,6 +49,9 @@
 class simple_output {
 public:
   simple_output(FILE *, int max_line_length);
+#ifdef ENABLE_MULTIBYTE
+  simple_output &put_string(const wchar *, int);
+#endif
   simple_output &put_string(const char *, int);
   simple_output &put_string(const char *s);
   simple_output &put_string(const string &s);
--- groff-1.18.1.1.orig/src/devices/grohtml/post-html.cc
+++ groff-1.18.1.1/src/devices/grohtml/post-html.cc
@@ -29,6 +29,7 @@
 #include "html.h"
 #include "html-text.h"
 #include "html-table.h"
+#include "encoding.h" // XXX: ukai
 
 #include <time.h>
 
@@ -280,6 +281,9 @@
 public:
   char_buffer();
   ~char_buffer();
+#ifdef ENABLE_MULTIBYTE
+  char  *add_string(const wchar *, unsigned int);
+#endif
   char  *add_string(const char *, unsigned int);
   char  *add_string(const string &);
 private:
@@ -301,6 +305,43 @@
   }
 }
 
+#ifdef ENABLE_MULTIBYTE
+char *char_buffer::add_string (const wchar *s, unsigned int length)
+{
+  int i=0;
+  unsigned int old_used;
+
+  if (tail == 0) {
+    tail = new char_block;
+    head = tail;
+  } else {
+    if (tail->used + length*2 + 1 > char_block::SIZE) {
+      tail->next = new char_block;
+      tail       = tail->next;
+    }
+  }
+  // at this point we have a tail which is ready for the string.
+  if (tail->used + length*2 + 1 > char_block::SIZE) {
+    fatal("need to increase char_block::SIZE");
+  }
+
+  old_used = tail->used;
+  do {
+    length -= output_encoding->put_wchar(s[i], (unsigned char *)tail->buffer, &tail->used, length*2);
+    i++;
+  } while (length>0);
+
+  // add terminating nul character
+
+  tail->buffer[tail->used] = '\0';
+  tail->used++;
+
+  // and return start of new string
+
+  return( &tail->buffer[old_used] );
+}
+#endif
+
 char *char_buffer::add_string (const char *s, unsigned int length)
 {
   int i=0;
@@ -320,6 +361,7 @@
   }
 
   old_used = tail->used;
+  /* XXX: encoding - ukai */
   do {
     tail->buffer[tail->used] = s[i];
     tail->used++;
@@ -1917,6 +1959,15 @@
 
     current_paragraph->do_para(&html, "", indentation, pageoffset, linelength);
   }
+#if 0 // def ENABLE_MULTIBYTE /* XXX */
+  else if (strcmp(fontname, "M") == 0) {
+    current_paragraph->done_bold();
+    current_paragraph->done_italic();
+    current_paragraph->done_tt();
+  } else if (strcmp(fontname, "G") == 0) {
+    current_paragraph->do_bold();
+  }
+#endif
 }
 
 void html_printer::determine_header_level (int level)
@@ -2948,6 +2999,11 @@
     current_paragraph->done_italic();
     current_paragraph->done_tt();
   }
+#ifdef ENABLE_MULTIBYTE
+  else if (strcmp(fontname, "G") == 0) {
+    current_paragraph->done_bold();
+  }
+#endif
 }
 
 /*
@@ -2992,6 +3048,15 @@
     current_paragraph->do_italic();
     current_paragraph->do_bold();
   }
+#ifdef ENABLE_MULTIBYTE
+  else if (strcmp(fontname, "M") == 0) {
+    current_paragraph->done_bold();
+    current_paragraph->done_italic();
+    current_paragraph->done_tt();
+  } else if (strcmp(fontname, "G") == 0) {
+    current_paragraph->do_bold();
+  }
+#endif
 }
 
 /*
@@ -3331,7 +3396,23 @@
 
   last_sbuf_length = sbuf.length();
   if (html_glyph == NULL)
+#ifdef ENABLE_MULTIBYTE
+    {
+      if (is_wchar_code(code)) {
+	int mblen = output_encoding->max_wchar_len();
+	unsigned char *wbuf = new unsigned char[mblen];
+	int i = 0, j = 0;
+	output_encoding->put_wchar(code, wbuf, &j, mblen);
+	for (i = 0; i < j; i++) {
+	  sbuf += wbuf[i];
+	}
+      }
+      else
+	sbuf += ((char)code);
+    }
+#else
     sbuf += ((char)code);
+#endif
   else
     sbuf += html_glyph;
 }
@@ -3445,12 +3526,12 @@
     return;
   
   flush_sbuf();
+  sbuf_style = sty; /* XXX? */
   add_to_sbuf(i, name);
   sbuf_end_hpos = env->hpos + w;
   sbuf_start_hpos = env->hpos;
   sbuf_prev_hpos = env->hpos;
   sbuf_vpos = env->vpos;
-  sbuf_style = sty;
   sbuf_kern = 0;
 }
 
@@ -3659,6 +3740,7 @@
   program_name = argv[0];
   static char stderr_buf[BUFSIZ];
   setbuf(stderr, stderr_buf);
+  init_encoding_handler();
   int c;
   static const struct option long_options[] = {
     { "help", no_argument, 0, CHAR_MAX + 1 },
--- groff-1.18.1.1.orig/src/devices/grodvi/dvi.cc
+++ groff-1.18.1.1/src/devices/grodvi/dvi.cc
@@ -21,6 +21,7 @@
 
 #include "driver.h"
 #include "nonposix.h"
+#include "encoding.h" 
 
 extern "C" const char *Version_string;
 
@@ -104,6 +105,9 @@
 struct output_font {
   dvi_font *f;
   int point_size;
+#ifdef	ENABLE_MULTIBYTE
+  const char *sf;		// subfont name
+#endif
   output_font() : f(0) { }
 };
 
@@ -121,6 +125,9 @@
   output_font output_font_table[FONTS_MAX];
   font *cur_font;
   int cur_point_size;
+#ifdef ENABLE_MULTIBYTE
+  const char *cur_subfont;
+#endif
   color cur_color;
   int pushed;
   int pushed_h;
@@ -341,9 +348,18 @@
   if (*env->col != cur_color)
     set_color(env->col);
   int code = f->get_code(index);
+#ifdef ENABLE_MULTIBYTE
+  const char *sf = f->get_subfont_name(index);
+  if (env->size != cur_point_size || f != cur_font ||
+     (sf != cur_subfont && strcmp(sf, cur_subfont))) {
+#else
   if (env->size != cur_point_size || f != cur_font) {
+#endif
     cur_font = f;
     cur_point_size = env->size;
+#ifdef ENABLE_MULTIBYTE
+    cur_subfont = sf;
+#endif
     int i;
     for (i = 0;; i++) {
       if (i >= FONTS_MAX) {
@@ -352,9 +368,16 @@
       if (output_font_table[i].f == 0) {
 	output_font_table[i].f = (dvi_font *)cur_font;
 	output_font_table[i].point_size = cur_point_size;
+#ifdef	ENABLE_MULTIBYTE
+	output_font_table[i].sf = cur_subfont;
+#endif
 	define_font(i);
       }
       if (output_font_table[i].f == cur_font
+#ifdef	ENABLE_MULTIBYTE
+	  && (output_font_table[i].sf == cur_subfont ||
+	      strcmp(output_font_table[i].sf, cur_subfont) == 0)
+#endif
 	  && output_font_table[i].point_size == cur_point_size)
 	break;
     }
@@ -398,7 +421,13 @@
   out4(f->checksum);
   out4(output_font_table[i].point_size*RES_7227);
   out4(int((double(f->design_size)/(1<<20))*RES_7227*100 + .5));
+#ifdef	ENABLE_MULTIBYTE
+  const char *nm;
+  if (!(nm = output_font_table[i].sf))
+    nm = f->get_internal_name();
+#else
   const char *nm = f->get_internal_name();
+#endif
   out1(0);
   out_string(nm);
 }
@@ -889,6 +918,7 @@
   program_name = argv[0];
   static char stderr_buf[BUFSIZ];
   setbuf(stderr, stderr_buf);
+  init_encoding_handler();
   int c;
   static const struct option long_options[] = {
     { "help", no_argument, 0, CHAR_MAX + 1 },
--- groff-1.18.1.1.orig/src/xditview/encoding.h
+++ groff-1.18.1.1/src/xditview/encoding.h
@@ -0,0 +1,31 @@
+// -*- C++ -*-
+/* Copyright (c) 2001 Fumitoshi UKAI <ukai@debian.or.jp>
+
+This file is part of groff.
+
+groff 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.
+
+groff 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 this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#ifndef ENCODING_H
+#define ENCODING_H
+
+#include "config.h"
+
+#ifdef ENABLE_MULTIBYTE
+typedef unsigned int wchar;
+#else
+typedef char wchar;
+#endif
+
+#endif
--- groff-1.18.1.1.orig/src/xditview/lex.c
+++ groff-1.18.1.1/src/xditview/lex.c
@@ -2,8 +2,10 @@
 #include <X11/IntrinsicP.h>
 #include <X11/StringDefs.h>
 #include <stdio.h>
+#include "config.h"
 #include "DviP.h"
 
+int
 DviGetAndPut(dw, cp)
     DviWidget	dw;
     int		*cp;
@@ -67,6 +69,7 @@
 	return Buffer;
 } 
 
+int
 GetNumber(dw)
 	DviWidget	dw;
 {
@@ -90,6 +93,98 @@
 		DviUngetC(dw, c);
 	return i;
 }
+
+#ifdef ENABLE_MULTIBYTE
+#include <locale.h>
+#include <langinfo.h>
+#include <iconv.h>
+#include <errno.h>
+
+static iconv_t icd;
+void
+DviInitLocale()
+{
+	char *enc;
+	setlocale(LC_ALL, "");
+	enc = nl_langinfo(CODESET);
+	icd = iconv_open("UCS-2BE", enc);
+}
+
+int
+DviGetCharacter(dw, cp)
+	DviWidget	dw;
+	char   *cp;
+{
+	char inbuf[8];
+	char outbuf[8];
+	char *inp, *outp;
+	size_t inbytesleft, outbytesleft = 8;
+	int i = 0;
+	int j;
+	int wc = 0;
+	int c;
+	size_t r;
+
+	while (wc == 0) {
+		DviGetC(dw, &c);
+		if (c == EOF)
+			return EOF;
+		inbuf[i++] = c;
+		inbytesleft = i;
+		outbytesleft = BUFSIZ;
+		inp = inbuf;
+		outp = outbuf;
+		r = iconv(icd, &inp, &inbytesleft, &outp, &outbytesleft);
+		if (r == (size_t)-1) {
+			if (errno == EILSEQ) {
+				/* illegal sequence */
+			} else if (errno == EINVAL) {
+				/* incomplete sequence */
+				continue;
+			} else if (errno == E2BIG) {
+				/* no room to output? */
+				
+			}
+			DviUngetC(dw, c);
+		}
+		/* ok - pass inbuf to cp */
+		for (j = 0; j < i; j++) {
+			cp[j] = inbuf[j];
+		}
+		cp[j] = '\0';
+		return i;
+	}
+	/* NOT REACHED */
+}
+
+int
+DviWCharP(char *name, int *wc)
+{
+	char outbuf[BUFSIZ];
+	char *inp, *outp;
+	int inbytesleft, outbytesleft;
+	size_t r;
+	*wc = 0;
+	inp = name;
+	inbytesleft = strlen(name);
+	outp = outbuf;
+	outbytesleft = sizeof(outbuf)-1;
+	r = iconv(icd, &inp, &inbytesleft, &outp, &outbytesleft);
+	if (r < 0) {
+		return 0;
+	}
+	/* UCS-2 check */
+	if (outbuf + 2 != outp) {
+		return 0;
+	}
+	for (inp = outbuf; inp < outp; inp++) {
+		*wc <<= 8;
+		*wc |= (*inp) & 0x0ff;
+	}
+	return 1;
+}
+
+#endif
 	
 /*
 Local Variables:
--- groff-1.18.1.1.orig/src/xditview/Dvi.c
+++ groff-1.18.1.1/src/xditview/Dvi.c
@@ -4,6 +4,8 @@
 #endif /* lint */
 #endif /* SABER */
 
+#include "config.h"
+
 /*
  * Dvi.c - Dvi display widget
  *
@@ -49,6 +51,8 @@
 NBI	-adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
 S	-adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
 SS	-adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
+M	-misc-fixed-medium-r-normal--*-100-*-*-*-*-jisx0208.1983-0\n\
+G	-misc-fixed-medium-r-normal--*-100-*-*-*-*-jisx0208.1983-0\
 ";
 
 #define offset(field) XtOffset(DviWidget, field)
@@ -94,6 +98,20 @@
 
 static void		SaveToFile ();
 
+/* font.c */
+extern void ParseFontMap();
+extern void DestroyFontMap();
+extern void ForgetFonts();
+
+/* page.c */
+extern void DestroyFileMap();
+extern int SearchPagePosition();
+extern void FileSeek();
+extern void ForgetPagePositions();
+
+/* parse.c */
+extern int ParseInput();
+
 DviClassRec dviClassRec = {
 {
 	&widgetClassRec,		/* superclass		  */	
@@ -406,6 +424,7 @@
 	return ret;
 }
 
+void
 SetDevice (dw, name)
 	DviWidget	dw;
 	char 		*name;
@@ -559,6 +578,9 @@
 	DviWidgetClass super = (DviWidgetClass) wc->core_class.superclass;
 	if (wc->command_class.save == InheritSaveToFile)
 		wc->command_class.save = super->command_class.save;
+#ifdef ENABLE_MULTIBYTE
+	DviInitLocale();
+#endif
 }
 	
 /*
--- groff-1.18.1.1.orig/src/xditview/parse.c
+++ groff-1.18.1.1/src/xditview/parse.c
@@ -9,15 +9,49 @@
 #include <X11/StringDefs.h>
 #include <stdio.h>
 #include <ctype.h>
+#include "config.h"
 #include "DviP.h"
+#include "encoding.h"
 
 static int StopSeen = 0;
-static ParseDrawFunction(), ParseDeviceControl();
-static push_env(), pop_env();
+static void ParseDrawFunction(), ParseDeviceControl();
+static void push_env(), pop_env();
+
+/* draw.c */
+extern int PutCharacter();
+extern int PutNumberedCharacter();
+extern void HorizontalGoto();
+extern void Word();
+extern void VerticalGoto();
+extern void VerticalMove();
+extern void FlushCharCache();
+extern void Newline();
+extern void DrawLine();
+extern void DrawCircle();
+extern void DrawFilledCircle();
+extern void DrawEllipse();
+extern void DrawFilledEllipse();
+extern void DrawArc();
+extern void DrawPolygon();
+extern void DrawFilledPolygon();
+extern void DrawSpline();
+
+/* Dvi.c */
+extern void SetDevice();
+
+/* page.c */
+extern void RememberPagePosition();
+
+/* font.c */
+extern void SetFontPosition();
+
+/* lex.c */
+extern int GetNumber();
 
 #define HorizontalMove(dw, delta)	((dw)->dvi.state->x += (delta))
 
 
+int
 ParseInput(dw)
     register DviWidget	dw;
 {
@@ -57,11 +91,17 @@
 					   DviGetC(dw,&otherc)-'0');
 			/* fall through */
 		case 'c':	/* single ascii character */
+#ifdef ENABLE_MULTIBYTE
+			DviGetCharacter(dw, Buffer);
+			if (Buffer[0] == ' ')
+			    break;
+#else
 			DviGetC(dw,&c);
 		    	if (c == ' ')
 			    break;
 			Buffer[0] = c;
 			Buffer[1] = '\0';
+#endif
 			(void) PutCharacter (dw, Buffer);
 			break;
 		case 'C':
@@ -69,10 +109,15 @@
 			(void) PutCharacter (dw, Buffer);
 			break;
 		case 't':
+#ifdef ENABLE_MULTIBYTE
+			while (DviGetCharacter(dw, Buffer) != EOF
+			       && Buffer[0] != ' ' && Buffer[0] != '\n') {
+#else
 			Buffer[1] = '\0';
 			while (DviGetC (dw, &c) != EOF
 			       && c != ' ' && c != '\n') {
 				Buffer[0] = c;
+#endif
 				HorizontalMove (dw, PutCharacter (dw, Buffer));
 			}
 			break;
@@ -158,7 +203,7 @@
 	}
 }
 
-static
+static void
 push_env(dw)
 	DviWidget	dw;
 {
@@ -177,7 +222,7 @@
 	dw->dvi.state = new;
 }
 
-static
+static void
 pop_env(dw)
 	DviWidget	dw;
 {
@@ -188,7 +233,7 @@
 	XtFree ((char *) old);
 }
 
-static
+static void
 InitTypesetter (dw)
 	DviWidget	dw;
 {
@@ -200,7 +245,7 @@
 
 #define DRAW_ARGS_MAX 128
 
-static
+static void
 ParseDrawFunction(dw, buf)
 DviWidget	dw;
 char		*buf;
@@ -284,13 +329,12 @@
 	}
 } 
 
-static
+static void
 ParseDeviceControl(dw)				/* Parse the x commands */
 	DviWidget	dw;
 {
         char str[20], str1[50];
 	int c, n;
-	extern int LastPage, CurrentPage;
 
 	GetWord (dw, str, 20);
 	switch (str[0]) {			/* crude for now */
--- groff-1.18.1.1.orig/src/xditview/DviChar.c
+++ groff-1.18.1.1/src/xditview/DviChar.c
@@ -5,7 +5,10 @@
  * font indexes and back
  */
 
-#include   "DviChar.h"
+#include <stdlib.h>
+#include "config.h"
+#include "DviChar.h"
+#include "encoding.h"
 
 extern char *xmalloc();
 
@@ -21,7 +24,7 @@
 static int	standard_maps_loaded = 0;
 static void	load_standard_maps ();
 static int	hash_name ();
-static		dispose_hash(), compute_hash();
+static void	dispose_hash(), compute_hash();
 
 DviCharNameMap *
 DviFindMap (encoding)
@@ -58,7 +61,7 @@
 	compute_hash (map);
 }
 
-static
+static void
 dispose_hash (map)
 	DviCharNameMap	*map;
 {
@@ -88,7 +91,7 @@
 	return i;
 }
 
-static
+static void
 compute_hash (map)
 	DviCharNameMap	*map;
 {
@@ -120,7 +123,10 @@
 {
 	int		i;
 	DviCharNameHash	*h;
-
+#ifdef ENABLE_MULTIBYTE
+	if (map->char_index)
+	    return (*map->char_index)(map, name);
+#endif
 	i = hash_name (name) % DVI_HASH_SIZE;
 	for (h = map->buckets[i]; h; h=h->next)
 		if (!strcmp (h->name, name))
@@ -128,9 +134,47 @@
 	return -1;
 }
 
+#ifdef ENABLE_MULTIBYTE
+#include <X11/Xlib.h>
+void
+DviChar2XChar2b(int c, XChar2b *xc)
+{
+    /* XXX: can we assume 'c' is EUC-JP ? */
+	xc->byte1 = (c >> 8) & 0x7f;
+	xc->byte2 = (c) &0x7f;
+	return;
+}
+
+int
+DviCharIndexJISX0208_1983(map, name)
+	DviCharNameMap	*map;
+	char		*name;
+{
+    /* XXX: can we assume name points EUC-JP chars? */
+	unsigned char ub = *name, lb = *(name + 1);
+	int wc;
+	wc = (name[0] & 0xff) << 8;
+	wc |= (name[1] & 0xff);
+	return(wc);
+}
+
+static DviCharNameMap JISX0208_1983_0_map = {
+	"jisx0208.1983-0",
+	0,
+	DviChar2XChar2b,
+	DviCharIndexJISX0208_1983,
+{
+{	"DummyEntry",		/* 0 */},
+}};
+#endif
+
 static DviCharNameMap ISO8859_1_map = {
 	"iso8859-1",
 	0,
+#ifdef ENABLE_MULTIBYTE
+	0,
+	0,
+#endif
 {
 {	0,			/* 0 */},
 {	0,			/* 1 */},
@@ -393,6 +437,10 @@
 static DviCharNameMap Adobe_Symbol_map = {
 	"adobe-fontspecific",
 	1,
+#ifdef ENABLE_MULTIBYTE
+	0,
+	0,
+#endif
 {
 {	0,					/* 0 */},
 {	0,					/* 1 */},
@@ -659,4 +707,7 @@
 	standard_maps_loaded = 1;
 	DviRegisterMap (&ISO8859_1_map);
 	DviRegisterMap (&Adobe_Symbol_map);
+#ifdef ENABLE_MULTIBYTE
+	DviRegisterMap (&JISX0208_1983_0_map);
+#endif
 }
--- groff-1.18.1.1.orig/src/xditview/config.h
+++ groff-1.18.1.1/src/xditview/config.h
@@ -0,0 +1,4 @@
+#ifndef _config_h
+#include "../include/config.h"
+#define _config_h
+#endif
--- groff-1.18.1.1.orig/src/xditview/XFontName.c
+++ groff-1.18.1.1/src/xditview/XFontName.c
@@ -225,6 +225,7 @@
 	return True;
 }
 
+Bool
 XCopyFontName (name1, name2, fontNameAttributes)
 	XFontName	*name1, *name2;
 	unsigned int	fontNameAttributes;
--- groff-1.18.1.1.orig/src/xditview/GXditview.ad
+++ groff-1.18.1.1/src/xditview/GXditview.ad
@@ -55,3 +55,25 @@
 GXditview.promptShell.promptDialog.cancel.label: Cancel
 GXditview.promptShell.promptDialog.cancel.translations: #override \
 	<BtnUp>:	Cancel() unset()
+
+GXditview*fontMap: \
+TR	-adobe-times-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
+TI	-adobe-times-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
+TB	-adobe-times-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
+TBI	-adobe-times-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
+CR	-adobe-courier-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
+CI	-adobe-courier-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
+CB	-adobe-courier-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
+CBI	-adobe-courier-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
+HR	-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
+HI	-adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\n\
+HB	-adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
+HBI	-adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\n\
+NR	-adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\n\
+NI	-adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\n\
+NB	-adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\n\
+NBI	-adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\n\
+S	-adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
+SS	-adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\n\
+M	-misc-fixed-medium-r-normal--*-100-*-*-*-*-jisx0208.1983-0\n\
+G	-misc-fixed-medium-r-normal--*-100-*-*-*-*-jisx0208.1983-0
--- groff-1.18.1.1.orig/src/xditview/GXditview-ad.h
+++ groff-1.18.1.1/src/xditview/GXditview-ad.h
@@ -50,3 +50,24 @@
 "GXditview.promptShell.promptDialog.cancel.label: Cancel",
 "GXditview.promptShell.promptDialog.cancel.translations: #override \
 	<BtnUp>:	Cancel() unset()",
+"GXditview*fontMap: \
+TR	-adobe-times-medium-r-normal--*-100-*-*-*-*-iso8859-1\\n\
+TI	-adobe-times-medium-i-normal--*-100-*-*-*-*-iso8859-1\\n\
+TB	-adobe-times-bold-r-normal--*-100-*-*-*-*-iso8859-1\\n\
+TBI	-adobe-times-bold-i-normal--*-100-*-*-*-*-iso8859-1\\n\
+CR	-adobe-courier-medium-r-normal--*-100-*-*-*-*-iso8859-1\\n\
+CI	-adobe-courier-medium-o-normal--*-100-*-*-*-*-iso8859-1\\n\
+CB	-adobe-courier-bold-r-normal--*-100-*-*-*-*-iso8859-1\\n\
+CBI	-adobe-courier-bold-o-normal--*-100-*-*-*-*-iso8859-1\\n\
+HR	-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1\\n\
+HI	-adobe-helvetica-medium-o-normal--*-100-*-*-*-*-iso8859-1\\n\
+HB	-adobe-helvetica-bold-r-normal--*-100-*-*-*-*-iso8859-1\\n\
+HBI	-adobe-helvetica-bold-o-normal--*-100-*-*-*-*-iso8859-1\\n\
+NR	-adobe-new century schoolbook-medium-r-normal--*-100-*-*-*-*-iso8859-1\\n\
+NI	-adobe-new century schoolbook-medium-i-normal--*-100-*-*-*-*-iso8859-1\\n\
+NB	-adobe-new century schoolbook-bold-r-normal--*-100-*-*-*-*-iso8859-1\\n\
+NBI	-adobe-new century schoolbook-bold-i-normal--*-100-*-*-*-*-iso8859-1\\n\
+S	-adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\\n\
+SS	-adobe-symbol-medium-r-normal--*-100-*-*-*-*-adobe-fontspecific\\n\
+M	-misc-fixed-medium-r-normal--*-100-*-*-*-*-jisx0208.1983-0\\n\
+G	-misc-fixed-medium-r-normal--*-100-*-*-*-*-jisx0208.1983-0",
--- groff-1.18.1.1.orig/src/xditview/DviP.h
+++ groff-1.18.1.1/src/xditview/DviP.h
@@ -8,6 +8,7 @@
 
 #ifndef _XtDviP_h
 #define _XtDviP_h
+#include "config.h"
 
 #include "Dvi.h"
 #include "DviChar.h"
@@ -89,9 +90,17 @@
 #define DVI_CHAR_CACHE_SIZE	1024
 
 typedef struct _dviCharCache {
+#ifdef ENABLE_MULTIBYTE
+	XTextItem16	cache[DVI_TEXT_CACHE_SIZE];
+#else
 	XTextItem	cache[DVI_TEXT_CACHE_SIZE];
+#endif
 	char		adjustable[DVI_TEXT_CACHE_SIZE];
+#ifdef ENABLE_MULTIBYTE
+	XChar2b		char_cache[DVI_CHAR_CACHE_SIZE];
+#else
 	char		char_cache[DVI_CHAR_CACHE_SIZE];
+#endif
 	int		index;
 	int		max;
 	int		char_index;
@@ -182,6 +191,7 @@
 	int		word_flag;
 } DviPart;
 
+extern int DviGetAndPut();
 #define DviGetIn(dw,cp)\
     (dw->dvi.tmpFile ? (\
 	DviGetAndPut (dw, cp) \
@@ -228,6 +238,11 @@
 extern DeviceFont	*QueryDeviceFont ();
 
 extern char *GetWord(), *GetLine();
+
+#ifdef ENABLE_MULTIBYTE
+extern void DviInitLocale();
+extern int DviGEtCharacter();
+#endif
 #endif /* _XtDviP_h */
 
 
--- groff-1.18.1.1.orig/src/xditview/device.c
+++ groff-1.18.1.1/src/xditview/device.c
@@ -2,10 +2,12 @@
 
 #include <stdio.h>
 #include <ctype.h>
+#include <stdlib.h>
 
 #include <X11/Xos.h>
 #include <X11/Intrinsic.h>
 
+#include "config.h"
 #include "device.h"
 
 #ifndef FONTPATH
@@ -48,6 +50,9 @@
     Device *dev;
     struct charinfo *char_table[CHAR_TABLE_SIZE];
     struct charinfo *code_table[256];
+#ifdef ENABLE_MULTIBYTE
+    struct charrange *range;
+#endif
 };
 
 struct charinfo {
@@ -71,6 +76,15 @@
 static struct charinfo *add_char();
 static int read_charset_section();
 static char *canonicalize_name();
+#ifdef ENABLE_MULTIBYTE
+struct charrange {
+	struct charrange *next;
+	int width;
+	int start_code;
+	int end_code;
+};
+static void add_charrange();
+#endif
 
 static
 Device *new_device(name)
@@ -256,6 +270,9 @@
 	f->char_table[i] = 0;
     for (i = 0; i < 256; i++)
 	f->code_table[i] = 0;
+#ifdef ENABLE_MULTIBYTE
+    f->range = 0;
+#endif
     return f;
 }
 
@@ -267,6 +284,15 @@
 
     if (!f)
 	return;
+#ifdef ENABLE_MULTIBYTE
+    {
+	struct charrange *cp, *cp2;
+	for (cp = f->range; cp != NULL; cp = cp2) {
+		cp2 = cp->next;
+		XtFree((char *)cp);
+	}
+    }
+#endif
     XtFree(f->name);
     for (i = 0; i < CHAR_TABLE_SIZE; i++) {
 	struct charinfo *ptr = f->char_table[i];
@@ -342,6 +368,20 @@
 {
     struct charinfo *p;
 
+#ifdef ENABLE_MULTIBYTE
+    int wc;
+    extern DviWCharP();
+    if (DviWCharP(name, &wc)) {
+	    struct charrange *rp;
+	    for (rp = f->range; rp != NULL; rp = rp->next) {
+		    if (rp->start_code <= wc && wc <= rp->end_code) {
+			    *widthp = scale_round(rp->width, ps, 
+						  f->dev->unitwidth);
+			    return 1;
+		    }
+	    }
+    }
+#endif
     name = canonicalize_name(name);
     for (p = f->char_table[hash_name(name) % CHAR_TABLE_SIZE];; p = p->next) {
 	if (!p)
@@ -424,6 +464,22 @@
     return ci;
 }
 
+#ifdef ENABLE_MULTIBYTE
+static void
+add_charrange(f, width, start_code, end_code)
+    DeviceFont *f;
+    int width, start_code, end_code;
+{
+	struct charrange *ci;
+	ci = (struct charrange *)XtMalloc(sizeof(struct charrange));
+	ci->start_code = start_code;
+	ci->end_code = end_code;
+	ci->width = width;
+	ci->next = f->range;
+	f->range = ci;
+}
+#endif
+
 /* Return non-zero for success. */
 
 static
@@ -439,11 +495,31 @@
 	int width;
 	int code;
 	char *p;
+#ifdef ENABLE_MULTIBYTE
+	int scode, ecode;
+#endif
 
 	current_lineno++;
 	name = strtok(buf, WS);
 	if (!name)
 	    continue;		/* ignore blank lines */
+#ifdef ENABLE_MULTIBYTE
+	if (sscanf(name, "u%X..u%X", &scode, &ecode) == 2) {
+		p = strtok((char *)0, WS);
+		if (!p)
+			break;
+		if (sscanf(p, "%d", &width) != 1) {
+			error("bad width field");
+			return 0;
+		}
+		p = strtok((char *)0, WS);
+		if (!p) {
+			error("missing type field");
+			return 0;
+		}
+		add_charrange(f, width, scode, ecode); 
+	} else {
+#endif
 	p = strtok((char *)0, WS);
 	if (!p)			/* end of charset section */
 	    break;
@@ -479,6 +555,9 @@
 	    }
 	    last_charinfo = add_char(f, name, width, code);
 	}
+#ifdef ENABLE_MULTIBYTE
+	}
+#endif
     }
     return 1;
 }
@@ -559,7 +638,7 @@
 FILE *open_device_file(device_name, file_name, result)
      char *device_name, *file_name, **result;
 {
-  char *buf, *path;
+  char *buf;
   FILE *fp;
 
   buf = XtMalloc(3 + strlen(device_name) + 1 + strlen(file_name) + 1);
--- groff-1.18.1.1.orig/src/xditview/page.c
+++ groff-1.18.1.1/src/xditview/page.c
@@ -28,6 +28,7 @@
 	return m;
 }
 
+void
 DestroyFileMap (m)
 	DviFileMap	*m;
 {
@@ -39,6 +40,7 @@
 	}
 }
 
+void
 ForgetPagePositions (dw)
 	DviWidget	dw;
 {
@@ -46,6 +48,7 @@
 	dw->dvi.file_map = 0;
 }
 
+void
 RememberPagePosition(dw, number)
 	DviWidget	dw;
 	int		number;
@@ -64,6 +67,7 @@
 		m->position = ftell (dw->dvi.file);
 }
 
+int
 SearchPagePosition (dw, number)
 	DviWidget	dw;
 	int		number;
@@ -75,6 +79,7 @@
 	return m->position;
 }
 
+void
 FileSeek(dw, position)
 DviWidget	dw;
 long		position;
--- groff-1.18.1.1.orig/src/xditview/FontMap.jisx0208
+++ groff-1.18.1.1/src/xditview/FontMap.jisx0208
@@ -0,0 +1,2 @@
+M	-misc-fixed-medium-r-normal--*-100-*-*-*-*-jisx0208.1983-0
+G	-misc-fixed-medium-r-normal--*-100-*-*-*-*-jisx0208.1983-0
--- groff-1.18.1.1.orig/src/xditview/xditview.c
+++ groff-1.18.1.1/src/xditview/xditview.c
@@ -46,6 +46,7 @@
 #include <X11/Xaw/SimpleMenu.h>
 #include <X11/Xaw/SmeBSB.h>
 
+#include <stdlib.h>
 #include <signal.h>
 
 #include "Dvi.h"
@@ -101,7 +102,7 @@
  * Report the syntax for calling xditview.
  */
 
-static
+static void
 Syntax(call)
 	char *call;
 {
@@ -126,12 +127,12 @@
     char    *name;
     void    (*function)();
 } menuEntries[] = {
-    "nextPage",	    NextPage,
-    "previousPage", PreviousPage,
-    "selectPage",   SelectPage,
-    "print",	    Print,
-    "openFile",	    OpenFile,
-    "quit",	    Quit,
+    {"nextPage",    NextPage},
+    {"previousPage",PreviousPage},
+    {"selectPage",  SelectPage},
+    {"print",	    Print},
+    {"openFile",    OpenFile},
+    {"quit",	    Quit},
 };
 
 static void	NextPageAction(), PreviousPageAction(), SelectPageAction();
@@ -139,17 +140,18 @@
 static void	AcceptAction(), CancelAction();
 static void	PrintAction();
 static void	RerasterizeAction();
+static void     MakePrompt();
 
 XtActionsRec xditview_actions[] = {
-    "NextPage",	    NextPageAction,
-    "PreviousPage", PreviousPageAction,
-    "SelectPage",   SelectPageAction,
-    "Print",	    PrintAction,
-    "OpenFile",	    OpenFileAction,
-    "Rerasterize",  RerasterizeAction,
-    "Quit",	    QuitAction,
-    "Accept",	    AcceptAction,
-    "Cancel",	    CancelAction,
+    {"NextPage",     NextPageAction},
+    {"PreviousPage", PreviousPageAction},
+    {"SelectPage",   SelectPageAction},
+    {"Print",	     PrintAction},
+    {"OpenFile",     OpenFileAction},
+    {"Rerasterize",  RerasterizeAction},
+    {"Quit",	     QuitAction},
+    {"Accept",	     AcceptAction},
+    {"Cancel",	     CancelAction},
 };
 
 #define MenuNextPage		0
@@ -318,6 +320,7 @@
 
 static char fileBuf[1024];
 
+static void
 ResetMenuEntry (entry)
     Widget  entry;
 {
@@ -516,6 +519,7 @@
     CancelAction (widget, event, params, num_params);
 }
 
+static void
 MakePrompt(centerw, prompt, func, def)
 Widget	centerw;
 char *prompt;
--- groff-1.18.1.1.orig/src/xditview/xtotroff.c
+++ groff-1.18.1.1/src/xditview/xtotroff.c
@@ -2,6 +2,7 @@
  * xtotroff
  *
  * convert X font metrics into troff font metrics
+ * XXX: ENABLE_MULTIBYTE may not work yet
  */
 
 #include	<X11/Xlib.h>
@@ -10,6 +11,7 @@
 #include	<unistd.h>
 #include	<stdlib.h>
 #include	<fcntl.h>
+#include	"config.h"
 #include	"XFontName.h"
 #include	"DviChar.h"
 
@@ -171,6 +173,47 @@
 			fprintf (out, "spacewidth %d\n", w);
 	}
 	fprintf (out, "charset\n");
+#if 0 /* def	ENABLE_MULTIBYTE */
+	if (fi->min_byte1 != 0 || fi->max_byte1 != 0) {
+		/*
+		 * 2 byte code font.
+		 */
+		int N;
+		int D = fi->max_char_or_byte2 -	fi->min_char_or_byte2 + 1;
+		int max = (fi->max_byte1 - fi->min_byte1 + 1) *
+			(fi->max_char_or_byte2 - fi->min_char_or_byte2 + 1);
+		unsigned byte1;
+		unsigned byte2;
+		unsigned int euc_code;
+
+		for (N = 0; N < max; N++) {
+			byte1 = N / D + fi->min_byte1;
+			byte2 = N % D + fi->min_char_or_byte2;
+			euc_code = ((byte1 << 8) | byte2) & 0xffff | 0x8080;
+			wid = fi->max_bounds.width;
+			fputc(byte1 & 0xff | 0x80, out);/* output EUC code */
+			fputc(byte2 & 0xff | 0x80, out);/* output EUC code */
+			fprintf (out, "\t%d", wid);
+			if (groff_flag) {
+				int	param[5];
+				param[0] = fi->max_bounds.ascent;
+				param[1] = fi->max_bounds.descent;
+				param[2] = 0 /* charRBearing (fi, c) - wid */;
+				param[3] = 0 /* charLBearing (fi, c) */;
+				param[4] = 0; /* XXX */
+				for (j = 0; j < 5; j++)
+					if (param[j] < 0)
+						param[j] = 0;
+				for (j = 4; j >= 0; j--)
+					if (param[j] != 0)
+						break;
+				for (k = 0; k <= j; k++)
+					fprintf (out, ",%d", param[k]);
+			}
+			fprintf (out, "\t0\t%#x\n", euc_code);
+		}
+	} else
+#endif /* ENABLE_MULTIBYTE */
 	for (c = fi->min_char_or_byte2; c <= fi->max_char_or_byte2; c++) {
 		char *name = DviCharName (char_map,c,0);
 		if (charExists (fi, c) && (groff_flag || name)) {
--- groff-1.18.1.1.orig/src/xditview/DviChar.h
+++ groff-1.18.1.1/src/xditview/DviChar.h
@@ -10,6 +10,8 @@
  * CharSetRegistry from the CharSetEncoding
  */
 
+#include "config.h"
+
 # define DVI_MAX_SYNONYMS	10
 # define DVI_MAP_SIZE		256
 # define DVI_HASH_SIZE		256
@@ -23,6 +25,10 @@
 typedef struct _dviCharNameMap {
     char		*encoding;
     int			special;
+#ifdef ENABLE_MULTIBYTE
+    void (*char2XChar2b)(/* int c, XChar2b *xc */);
+    int (*char_index)(/* struct _dviCharNameMap *map, char *name */);
+#endif
     char		*dvi_names[DVI_MAP_SIZE][DVI_MAX_SYNONYMS];
     DviCharNameHash	*buckets[DVI_HASH_SIZE];
 } DviCharNameMap;
--- groff-1.18.1.1.orig/src/xditview/draw.c
+++ groff-1.18.1.1/src/xditview/draw.c
@@ -10,6 +10,7 @@
 #include <stdio.h>
 #include <ctype.h>
 #include <math.h>
+#include "config.h"
 
 /* math.h on a Sequent doesn't define M_PI, apparently */
 #ifndef M_PI
@@ -17,6 +18,7 @@
 #endif
 
 #include "DviP.h"
+#include "encoding.h" /* XXX */
 
 #define DeviceToX(dw, n) ((int)((n) * (dw)->dvi.scale_factor + .5))
 #define XPos(dw) (DeviceToX((dw), (dw)->dvi.state->x - \
@@ -25,6 +27,10 @@
 
 static int FakeCharacter();
 
+/* font.c */
+extern int MaxFontPosition();
+
+void
 HorizontalMove(dw, delta)
 	DviWidget	dw;
 	int		delta;
@@ -32,6 +38,7 @@
 	dw->dvi.state->x += delta;
 }
 
+void
 HorizontalGoto(dw, NewPosition)
 	DviWidget	dw;
 	int		NewPosition;
@@ -39,6 +46,7 @@
 	dw->dvi.state->x = NewPosition;
 }
 
+void
 VerticalMove(dw, delta)
 	DviWidget	dw;
 	int		delta;
@@ -46,6 +54,7 @@
 	dw->dvi.state->y += delta;
 }
 
+void
 VerticalGoto(dw, NewPosition)
 	DviWidget	dw;
 	int		NewPosition;
@@ -53,6 +62,7 @@
 	dw->dvi.state->y = NewPosition;
 }
 
+void
 AdjustCacheDeltas (dw)
 	DviWidget	dw;
 {
@@ -94,14 +104,21 @@
 		}
 }
 
+void
 FlushCharCache (dw)
 	DviWidget	dw;
 {
 	if (dw->dvi.cache.char_index != 0) {
 		AdjustCacheDeltas (dw);
+#ifdef ENABLE_MULTIBYTE
+		XDrawText16 (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
+			   dw->dvi.cache.start_x, dw->dvi.cache.start_y,
+			   dw->dvi.cache.cache, dw->dvi.cache.index + 1);
+#else
 		XDrawText (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
 			   dw->dvi.cache.start_x, dw->dvi.cache.start_y,
 			   dw->dvi.cache.cache, dw->dvi.cache.index + 1);
+#endif
 	}	
 	dw->dvi.cache.index = 0;
 	dw->dvi.cache.max = DVI_TEXT_CACHE_SIZE;
@@ -115,6 +132,7 @@
 	dw->dvi.cache.start_y = dw->dvi.cache.y = YPos (dw);
 }
 
+void
 Newline (dw)
 	DviWidget	dw;
 {
@@ -123,6 +141,7 @@
 	dw->dvi.word_flag = 0;
 }
 
+void
 Word (dw)
 	DviWidget	dw;
 {
@@ -135,7 +154,6 @@
     :\
 	(fi)->max_bounds.width\
 )
- 
 
 static
 int charExists (fi, c)
@@ -152,14 +170,25 @@
 		|| p->ascent != 0 || p->descent != 0 || p->attributes != 0);
 }
 
-static
+static void
+#ifdef ENABLE_MULTIBYTE
+DoCharacter (dw, c, wid, char2xchar2b)
+#else
 DoCharacter (dw, c, wid)
+#endif
 	DviWidget dw;
 	int c;
 	int wid;    /* width in device units */
+#ifdef ENABLE_MULTIBYTE
+	void (*char2xchar2b)();
+#endif
 {
 	register XFontStruct	*font;
+#ifdef ENABLE_MULTIBYTE
+	register XTextItem16	*text;
+#else
 	register XTextItem	*text;
+#endif
 	int	x, y;
 	
 	x = XPos(dw);
@@ -225,9 +254,25 @@
 			text->font = None;
 		dw->dvi.cache.x += text->delta;
 	}
+#ifdef ENABLE_MULTIBYTE
+	if (charExists(font, c) || char2xchar2b) {
+#else
 	if (charExists(font, c)) {
+#endif
 		int w;
+#ifdef ENABLE_MULTIBYTE
+		if (char2xchar2b) {
+		    (*char2xchar2b)(c,
+				    &dw->dvi.cache.char_cache[dw->dvi.cache.char_index++]);
+		} else {
+			dw->dvi.cache.char_cache[dw->dvi.cache.char_index].
+				byte1 =	(unsigned char)'\0';
+			dw->dvi.cache.char_cache[dw->dvi.cache.char_index++].
+				byte2 =	(unsigned char)c;
+		}
+#else
 		dw->dvi.cache.char_cache[dw->dvi.cache.char_index++] = (char) c;
+#endif
 		++text->nchars;
 		w = charWidth(font, c);
 		dw->dvi.cache.x += w;
@@ -291,7 +336,11 @@
 	if (map)
 		c = DviCharIndex (map, buf);
 	if (c >= 0)
+#ifdef ENABLE_MULTIBYTE
+		DoCharacter (dw, c, wid, map->char2XChar2b);
+#else
 		DoCharacter (dw, c, wid);
+#endif
 	else
 		(void) FakeCharacter (dw, buf, wid);
 	dw->dvi.state->font_number = prevFont;
@@ -345,6 +394,7 @@
 	return 1;
 }
 
+void
 PutNumberedCharacter (dw, c)
 	DviWidget dw;
 	int c;
@@ -368,7 +418,11 @@
 				   dw->dvi.state->font_size, c, &wid))
 		return;
 	if (dw->dvi.native) {
+#ifdef ENABLE_MULTIBYTE
+		DoCharacter (dw, c, wid, NULL);
+#else
 		DoCharacter (dw, c, wid);
+#endif
 		return;
 	}
 	map = QueryFontMap (dw, dw->dvi.state->font_number);
@@ -379,7 +433,11 @@
 	     name = device_name_for_code ((DeviceFont *)0, c)) {
 		int code = DviCharIndex (map, name);
 		if (code >= 0) {
+#ifdef ENABLE_MULTIBYTE
+			DoCharacter (dw, code, wid, map->char2XChar2b);
+#else
 			DoCharacter (dw, code, wid);
+#endif
 			break;
 		}
 		if (FakeCharacter (dw, name, wid))
@@ -387,13 +445,14 @@
 	}
 }
 
+void
 ClearPage (dw)
 	DviWidget	dw;
 {
 	XClearWindow (XtDisplay (dw), XtWindow (dw));
 }
 
-static
+static void
 setGC (dw)
 	DviWidget	dw;
 {
@@ -417,7 +476,7 @@
 	}
 }
 
-static
+static void
 setFillGC (dw)
 	DviWidget	dw;
 {
@@ -444,6 +503,7 @@
 	}
 }
 
+void
 DrawLine (dw, x, y)
 	DviWidget	dw;
 	int		x, y;
@@ -459,6 +519,7 @@
 		   xp + DeviceToX (dw, x), yp + DeviceToX (dw, y));
 }
 
+void
 DrawCircle (dw, diam)
 	DviWidget	dw;
 	int		diam;
@@ -473,6 +534,7 @@
 		  d, d, 0, 64*360);
 }
 
+void
 DrawFilledCircle (dw, diam)
 	DviWidget	dw;
 	int		diam;
@@ -490,6 +552,7 @@
 		  d, d, 0, 64*360);
 }
 
+void
 DrawEllipse (dw, a, b)
 	DviWidget	dw;
 	int		a, b;
@@ -501,6 +564,7 @@
 		  DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
 }
 
+void
 DrawFilledEllipse (dw, a, b)
 	DviWidget	dw;
 	int		a, b;
@@ -515,6 +579,7 @@
 		  DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
 }
 
+void
 DrawArc (dw, x0, y0, x1, y1)
 	DviWidget	dw;
 	int		x0, y0, x1, y1;
@@ -541,6 +606,7 @@
 		  rad*2, rad*2, angle1, angle2);
 }
 
+void
 DrawPolygon (dw, v, n)
 	DviWidget	dw;
 	int		*v;
@@ -572,7 +638,7 @@
 	XtFree((char *)p);
 }
 
-
+void
 DrawFilledPolygon (dw, v, n)
 	DviWidget	dw;
 	int		*v;
@@ -608,7 +674,7 @@
 
 #define POINTS_MAX 10000
 
-static
+static void
 appendPoint(points, pointi, x, y)
 	XPoint	*points;
 	int	*pointi;
@@ -623,7 +689,7 @@
 
 #define FLATNESS 1
 
-static
+static void
 flattenCurve(points, pointi, x2, y2, x3, y3, x4, y4)
 	XPoint	*points;
 	int	*pointi;
@@ -659,7 +725,7 @@
 	}
 }
 
-
+void
 DrawSpline (dw, v, n)
 	DviWidget	dw;
 	int		*v;
--- groff-1.18.1.1.orig/src/xditview/font.c
+++ groff-1.18.1.1/src/xditview/font.c
@@ -9,10 +9,16 @@
 #include <X11/StringDefs.h>
 #include <stdio.h>
 #include <ctype.h>
+#include <stdlib.h>
 #include "DviP.h"
 #include "XFontName.h"
 
-static DisposeFontSizes();
+static void DisposeFontSizes();
+void DestroyFontMap();
+
+/* XFontName.c */
+extern Bool XParseFontName();
+extern Bool XFormatFontName();
 
 static char *
 savestr (s)
@@ -115,7 +121,7 @@
 # define SizePosition		8
 # define EncodingPosition	13
 
-static
+static int
 ConvertFontNameToSize (n)
 	char	*n;
 {
@@ -191,7 +197,7 @@
 	return sizes;
 }
 
-static
+static void
 DisposeFontSizes (dw, fs)
 	DviWidget	dw;
 	DviFontSizeList	*fs;
@@ -263,6 +269,7 @@
 	return f;
 }
 
+void
 ForgetFonts (dw)
 	DviWidget dw;
 {
@@ -322,6 +329,7 @@
 }
 #endif
 
+void
 ParseFontMap (dw)
 	DviWidget	dw;
 {
@@ -357,6 +365,7 @@
 	dw->dvi.font_map = fm;
 }
 
+void
 DestroyFontMap (font_map)
 	DviFontMap	*font_map;
 {
@@ -374,6 +383,7 @@
 
 /* ARGSUSED */
 
+void
 SetFontPosition (dw, position, dvi_name, extra)
 	DviWidget	dw;
 	int		position;
--- groff-1.18.1.1.orig/src/roff/troff/charinfo.h
+++ groff-1.18.1.1/src/roff/troff/charinfo.h
@@ -29,9 +29,16 @@
   macro *mac;
   unsigned char special_translation;
   unsigned char hyphenation_code;
+#ifdef ENABLE_MULTIBYTE
+  unsigned short flags;
+#else
   unsigned char flags;
+#endif
   unsigned char ascii_code;
   unsigned char asciify_code;
+#ifdef ENABLE_MULTIBYTE
+  wchar wchar_code;
+#endif
   char not_found;
   char transparent_translate;	// non-zero means translation applies
 				// to transparent throughput
@@ -47,6 +54,11 @@
     OVERLAPS_VERTICALLY = 16,
     TRANSPARENT = 32,
     NUMBERED = 64
+#ifdef	ENABLE_MULTIBYTE
+    ,
+    DONT_BREAK_BEFORE = 0x100,	// 256, pre kinsoku
+    DONT_BREAK_AFTER = 0x200	// 512, post kinsoku
+#endif
     };
   enum {
     TRANSLATE_NONE,
@@ -74,7 +86,11 @@
   int get_translation_input();
   charinfo *get_translation(int = 0);
   void set_translation(charinfo *, int, int);
+#ifdef ENABLE_MULTIBYTE
+  void set_flags(unsigned short);
+#else
   void set_flags(unsigned char);
+#endif
   void set_special_translation(int, int);
   int get_special_translation(int = 0);
   macro *set_macro(macro *, int = 0);
@@ -84,6 +100,12 @@
   int get_number();
   int numbered();
   int is_fallback();
+#ifdef	ENABLE_MULTIBYTE
+  wchar get_wchar_code();
+  void set_wchar_code(wchar);
+  int cannot_break_before(); // pre kinsoku
+  int cannot_break_after(); // post kinsoku
+#endif
   symbol *get_symbol();
 };
 
@@ -131,6 +153,18 @@
   return fallback;
 }
 
+#ifdef	ENABLE_MULTIBYTE
+inline int charinfo::cannot_break_before()
+{
+  return flags & DONT_BREAK_BEFORE;
+}
+
+inline int charinfo::cannot_break_after()
+{
+  return flags & DONT_BREAK_AFTER;
+}
+#endif
+
 inline charinfo *charinfo::get_translation(int transparent_throughput)
 {
   return (transparent_throughput && !transparent_translate
@@ -153,7 +187,18 @@
   return (translate_input ? asciify_code : 0);
 }
 
+#ifdef	ENABLE_MULTIBYTE
+inline wchar charinfo::get_wchar_code()
+{
+  return wchar_code;
+}
+#endif
+
+#ifdef	ENABLE_MULTIBYTE
+inline void charinfo::set_flags(unsigned short c)
+#else
 inline void charinfo::set_flags(unsigned char c)
+#endif
 {
   flags = c;
 }
--- groff-1.18.1.1.orig/src/roff/troff/troff.h
+++ groff-1.18.1.1/src/roff/troff/troff.h
@@ -28,6 +28,7 @@
 #include <stdlib.h>
 #include <errno.h>
 
+#include "encoding.h"
 #include "assert.h"
 #include "color.h"
 #include "device.h"
--- groff-1.18.1.1.orig/src/roff/troff/env.cc
+++ groff-1.18.1.1/src/roff/troff/env.cc
@@ -32,6 +32,7 @@
 #include "charinfo.h"
 #include "macropath.h"
 #include "input.h"
+#include "font.h" // ENABLE_MULTIBYTE only?
 #include <math.h>
 
 symbol default_family("T");
@@ -264,6 +265,13 @@
 void environment::add_char(charinfo *ci)
 {
   int s;
+#ifdef ENABLE_MULTIBYTE
+  int fontno = get_font(); // current font #
+  int fontset_font = get_fontset_fontno(fontno, ci->get_wchar_code());
+  if (fontno >= 0 && fontno != fontset_font) {
+    change_curfont(fontset_font);
+  }
+#endif
   if (interrupted)
     ;
   // don't allow fields in dummy environments
@@ -286,11 +294,95 @@
   else {
     if (line == 0)
       start_line();
+#ifdef	ENABLE_MULTIBYTE
+    /* 
+     * XXX: NEED REWRITE TO BE MORE GENERIC
+     * This code is based on jgroff
+     * about kerning between ASCII and EUC-JP 
+     */
+    if (!ci->get_wchar_code()) {
+      /*
+       * This node is a ASCII character node.
+       */
+      if (!pre_char_is_ascii && enable_wcharkern && !hwkern.is_zero()) {
+	/*
+	 * Insert a little space node between EUC and ASCII.
+	 */
+	word_space_node *ws;
+
+	if (ci->ends_sentence() || ci->transparent() || ci->cannot_break_before())
+	  ws = new unbreakable_space_node(hwkern.to_units(), get_fill_color());
+	else
+	  ws = new word_space_node(hwkern.to_units(),
+				   get_fill_color(),
+				   new width_list(env_space_width(this),
+						  env_sentence_space_width(this)));
+	curenv->add_node(ws);
+      }
+      pre_char_is_ascii = 1;
+      pre_wchar_cannot_break_after = 0;
+    } else {
+      /*
+       * This node is a EUC charcater node.
+       */
+      if (!pre_char_is_ascii && line->get_node_type() == NODE_NEWLINE_SPACE) {
+	/*
+	 * remove a newline-node.
+	 */
+	node *ns_node = line;
+	line = line->next;
+	width_total -= ns_node->width();
+	space_total -= ns_node->nspaces();
+	delete ns_node;
+      }
+
+      if (!pre_wchar_cannot_break_after && !ci->cannot_break_before()) {
+	/*
+	 * add a zero-width-space-node before EUC charcater node.
+	 */
+	add_node(new kword_space_node(get_fill_color()));
+	met_with_kword_space = 1;
+      }
+      pre_wchar_cannot_break_after = ci->cannot_break_after();
+
+      if (pre_char_is_ascii && enable_wcharkern && !hwkern.is_zero()) {
+	/*
+	 * Insert a little space node between ASCII and EUC.
+	 */
+	unbreakable_space_node *ws =
+	  new unbreakable_space_node(hwkern.to_units(), get_fill_color());
+	curenv->add_node(ws);
+      }
+      pre_char_is_ascii = 0;
+
+      if (!vlower.is_zero()) {
+	/*
+	 * Lower a EUC charcater node.
+	 */
+	curenv->add_node(new vmotion_node(vlower.to_units(), 
+					  get_fill_color())); // lower
+      }
+    }
+#endif
     if (ci != hyphen_indicator_char)
       line = line->add_char(ci, this, &width_total, &space_total);
     else
       line = line->add_discretionary_hyphen();
+#ifdef	ENABLE_MULTIBYTE
+    enable_wcharkern = 1;
+    if (!vlower.is_zero() && ci->get_wchar_code()) {
+      /*
+       * Raise a EUC charcater node.
+       */
+      curenv->add_node(new vmotion_node(-vlower.to_units(), 
+					get_fill_color())); // raise
+    }
+#endif
   }
+#ifdef ENABLE_MULTIBYTE
+  if (fontset_font >= 0 && fontno != fontset_font)
+      change_curfont(fontno); /* restore saved font # */
+#endif
 }
 
 node *environment::make_char_node(charinfo *ci)
@@ -394,7 +486,11 @@
     width_total += x;
     return;
   }
+#ifdef ENABLE_MULTIBYTE
+  add_node(new newline_space_node(x, get_fill_color())); // This node may be removed
+#else
   add_node(new word_space_node(x, get_fill_color(), w));
+#endif
   possibly_break_line(0, spread_flag);
   spread_flag = 0;
 }
@@ -480,6 +576,35 @@
     warning(WARN_FONT, "bad font number");
 }
 
+#ifdef	ENABLE_MULTIBYTE
+void environment::change_curfont(symbol nm)
+{
+  int n = symbol_fontno(nm);
+  if (n < 0) {
+    n = next_available_font_position();
+    if (!mount_font(n, nm))
+      return;
+  }
+  fontno = n;
+}
+
+void environment::change_curfont(int n)
+{
+  if (is_good_fontno(n))
+    fontno = n;
+  else
+    error("bad font number");
+}
+
+void environment::set_encoding(symbol enc)
+{
+  if (enc.is_null() || enc.is_empty())
+    return;
+  select_input_encoding_handler(enc.contents());
+  select_output_encoding_handler(enc.contents());
+}
+#endif /* ENABLE_MULTIBYTE */
+
 void environment::set_family(symbol fam)
 {
   if (interrupted)
@@ -649,6 +774,16 @@
   control_char('.'),
   no_break_control_char('\''),
   hyphen_indicator_char(0)
+#ifdef	ENABLE_MULTIBYTE
+  ,
+  stretch_threshold(0),
+  pre_wchar_cannot_break_after(0),
+  pre_char_is_ascii(-1),
+  enable_wcharkern(0),
+  met_with_kword_space(0),
+  hwkern(font::wcharkern),
+  vlower(font::lowerwchar)
+#endif
 {
   prev_family = family = lookup_family(default_family);
   prev_fontno = fontno = 1;
@@ -739,6 +874,16 @@
   control_char(e->control_char),
   no_break_control_char(e->no_break_control_char),
   hyphen_indicator_char(e->hyphen_indicator_char)
+#ifdef	ENABLE_MULTIBYTE
+  ,
+  stretch_threshold(e->stretch_threshold),
+  pre_wchar_cannot_break_after(0),
+  pre_char_is_ascii(-1),
+  enable_wcharkern(0),
+  met_with_kword_space(0),
+  hwkern(font::wcharkern),
+  vlower(font::lowerwchar)
+#endif
 {
 }
 
@@ -1781,6 +1926,9 @@
   target_text_length = line_length - saved_indent;
   width_total = H0;
   space_total = 0;
+#ifdef	ENABLE_MULTIBYTE
+  enable_wcharkern = 0;
+#endif
 }
 
 hunits environment::get_hyphenation_space()
@@ -1819,6 +1967,23 @@
   skip_line();
 }
 
+#ifdef ENABLE_MULTIBYTE
+void stretch_threshold_request()
+{
+  int n;
+  if (has_arg() && get_integer(&n)) {
+      if (n < 0 || n > 100) {
+	  warning(WARN_RANGE, "stretch threshold value %1 out of range", n);
+      } else {
+	  curenv->stretch_threshold = n;
+      }
+  } else {
+      curenv->stretch_threshold = 0;
+  }
+  skip_line();
+}
+#endif
+
 breakpoint *environment::choose_breakpoint()
 {
   hunits x = width_total;
@@ -2014,6 +2179,30 @@
 	     // When a macro follows a paragraph in fill mode, the
 	     // current line should not be empty.
 	     || (width_total - line->width()) > target_text_length)) {
+#ifdef ENABLE_MULTIBYTE
+    if (met_with_kword_space) {
+      node *linep = line;
+      node *prep = 0;
+      while (linep->next) {
+	if (linep->next->get_node_type() == NODE_GLYPH)
+	  prep = 0;
+	else if (linep->next->get_node_type() == NODE_KWORD_SPACE)
+	  prep = linep;
+        linep = linep->next;
+      }
+      if (prep) {
+        /*
+         * delete a kword_space_node which is in the top of line.
+         */
+        linep = prep->next;
+        prep->next = linep->next;
+        width_total -= linep->width();
+        space_total -= linep->nspaces();
+        delete linep;
+      }
+      met_with_kword_space = 0;
+    }
+#endif
     hyphenate_line(start_here);
     breakpoint *bp = choose_breakpoint();
     if (bp == 0)
@@ -2026,6 +2215,15 @@
     bp->nd->split(bp->index, &pre, &post);
     *ndp = post;
     hunits extra_space_width = H0;
+#ifdef ENABLE_MULTIBYTE
+    int sv_adjust_mode = adjust_mode;
+    if (stretch_threshold) {
+	int ratio = bp->width * 100 / target_text_length;
+	if (ratio < stretch_threshold) {
+	    adjust_mode = ADJUST_LEFT;
+	}
+    }
+#endif
     switch(adjust_mode) {
     case ADJUST_BOTH:
       if (bp->nspaces != 0)
@@ -2041,6 +2239,9 @@
       saved_indent += target_text_length - bp->width;
       break;
     }
+#ifdef ENABLE_MULTIBYTE
+    adjust_mode = sv_adjust_mode;
+#endif
     distribute_space(pre, bp->nspaces, extra_space_width);
     hunits output_width = bp->width + extra_space_width;
     input_line_start -= output_width;
@@ -3237,6 +3438,9 @@
   init_request("hys", hyphenation_space_request);
   init_request("hym", hyphenation_margin_request);
   init_request("pvs", post_vertical_spacing);
+#ifdef ENABLE_MULTIBYTE
+  init_request("stt", stretch_threshold_request);
+#endif
   init_int_env_reg(".f", get_font);
   init_int_env_reg(".b", get_bold);
   init_hunits_env_reg(".i", get_indent);
--- groff-1.18.1.1.orig/src/roff/troff/node.h
+++ groff-1.18.1.1/src/roff/troff/node.h
@@ -20,6 +20,8 @@
 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 
 
+#include "config.h"
+
 struct hyphen_list {
   unsigned char hyphen;
   unsigned char breakable;
@@ -31,6 +33,9 @@
 void hyphenate(hyphen_list *, unsigned);
 
 enum hyphenation_type { HYPHEN_MIDDLE, HYPHEN_BOUNDARY, HYPHEN_INHIBIT };
+#ifdef	ENABLE_MULTIBYTE
+enum node_type {NODE_GLYPH, NODE_KWORD_SPACE, NODE_NEWLINE_SPACE, NODE_ANOTHER};
+#endif
 
 class ascii_output_file;
 
@@ -106,6 +111,9 @@
 
   virtual int same(node *) = 0;
   virtual const char *type() = 0;
+#ifdef	ENABLE_MULTIBYTE
+  virtual node_type get_node_type();
+#endif
 };
 
 inline node::node()
@@ -212,6 +220,24 @@
   int force_tprint();
 };
 
+#ifdef	ENABLE_MULTIBYTE
+class kword_space_node : public word_space_node {
+public:
+  kword_space_node(color *, node * = 0);
+  node *copy();
+  const char *type();
+  node_type get_node_type();
+};
+
+class newline_space_node : public word_space_node {
+public:
+  newline_space_node(hunits, color *, node * = 0);
+  node *copy();
+  const char *type();
+  node_type get_node_type();
+};
+#endif
+
 class unbreakable_space_node : public word_space_node {
   unbreakable_space_node(hunits, int, color *, node * = 0);
 public:
@@ -538,6 +564,9 @@
 node *copy_node_list(node *);
 
 int get_bold_fontno(int f);
+#ifdef ENABLE_MULTIBYTE
+int get_fontset_fontno(int f, wchar wc);
+#endif
 
 inline hyphen_list::hyphen_list(unsigned char code, hyphen_list *p)
 : hyphen(0), breakable(0), hyphenation_code(code), next(p)
@@ -595,3 +624,4 @@
 
 font_family *lookup_family(symbol);
 symbol get_font_name(int, environment *);
+
--- groff-1.18.1.1.orig/src/roff/troff/env.h
+++ groff-1.18.1.1/src/roff/troff/env.h
@@ -213,6 +213,15 @@
   unsigned char control_char;
   unsigned char no_break_control_char;
   charinfo *hyphen_indicator_char;
+#ifdef	ENABLE_MULTIBYTE
+  int stretch_threshold;
+  int pre_wchar_cannot_break_after;
+  int pre_char_is_ascii;
+  int enable_wcharkern;
+  int met_with_kword_space;
+  hunits hwkern;
+  vunits vlower;
+#endif
   
   environment(symbol);
   environment(const environment *);	// for temporary environment
@@ -279,6 +288,10 @@
   void wrap_up_tab();
   void set_font(int);
   void set_font(symbol);
+#ifdef	ENABLE_MULTIBYTE
+  void change_curfont(int);
+  void change_curfont(symbol);
+#endif
   void set_family(symbol);
   void set_size(int);
   void set_char_height(int);
@@ -309,6 +322,9 @@
   const char *get_point_size_string();
   const char *get_requested_point_size_string();
   void output_pending_lines();
+#ifdef ENABLE_MULTIBYTE
+  void set_encoding(symbol);
+#endif
   
   friend void title_length();
   friend void space_size();
@@ -347,6 +363,9 @@
 #ifdef WIDOW_CONTROL
   friend void widow_control_request();
 #endif /* WIDOW_CONTROL */
+#ifdef	ENABLE_MULTIBYTE
+  friend void stretch_threshold_request();
+#endif
 
   friend void do_divert(int append, int boxing);
 };
--- groff-1.18.1.1.orig/src/roff/troff/input.cc
+++ groff-1.18.1.1/src/roff/troff/input.cc
@@ -35,6 +35,7 @@
 #include "macropath.h"
 #include "defs.h"
 #include "input.h"
+#include "encoding.h" // XXX: ukai
 
 // Needed for getpid() and isatty()
 #include "posix.h"
@@ -89,6 +90,11 @@
 charinfo *charset_table[256];
 unsigned char hpf_code_table[256];
 
+#ifdef	ENABLE_MULTIBYTE
+charinfo *wcharset_table_entry(wchar wc);
+
+#endif /* ENABLE_MULTIBYTE */
+
 static int warning_mask = DEFAULT_WARNING_MASK;
 static int inhibit_errors = 0;
 static int ignoring = 0;
@@ -148,6 +154,20 @@
 input_iterator *make_temp_iterator(const char *);
 const char *input_char_description(int);
 
+#ifdef ENABLE_MULTIBYTE
+static void
+select_encoding()
+{
+    symbol e = get_long_name(1);
+    if (e.is_null()) {
+	skip_line();
+	return;
+    }
+    curenv->set_encoding(e);
+    skip_line();
+    
+}
+#endif
 
 void set_escape_char()
 {
@@ -1524,6 +1544,19 @@
   type = TOKEN_NEWLINE;
 }
 
+#ifdef ENABLE_MULTIBYTE
+class encoding_istream_input : public encoding_istream {
+private:
+  node **np;
+public:
+  encoding_istream_input(node **n) : np(n) {};
+  ~encoding_istream_input() {};
+  int getbyte() { return input_stack::get(np); };
+  int peekbyte() { return input_stack::peek(); };
+  void ungetbyte(int ch) { return; };
+};
+#endif
+
 void token::next()
 {
   if (nd) {
@@ -1533,6 +1566,10 @@
   units x;
   for (;;) {
     node *n;
+#ifdef ENABLE_MULTIBYTE
+    encoding_istream_input einput(&n);
+#endif
+
     int cc = input_stack::get(&n);
     if (cc != escape_char || escape_char == 0) {
     handle_normal_char:
@@ -1686,8 +1723,22 @@
 	}
 	return;
       default:
+#ifdef	ENABLE_MULTIBYTE
+	wc = input_encoding->make_wchar(cc, einput);
+	if (is_wchar_code(wc)) {
+	  type = TOKEN_WCHAR;
+	  c = 0;
+	} else if (wc == ' ') {
+	  type = TOKEN_SPACE;
+	  c = cc;
+	} else {
+	  type = TOKEN_CHAR;
+	  c = cc;
+	}
+#else
 	type = TOKEN_CHAR;
 	c = cc;
+#endif
 	return;
       }
     }
@@ -2057,6 +2108,10 @@
   switch(type) {
   case TOKEN_CHAR:
     return c == t.c;
+#ifdef	ENABLE_MULTIBYTE
+  case TOKEN_WCHAR:
+    return wc == t.wc;
+#endif
   case TOKEN_SPECIAL:
     return nm == t.nm;
   case TOKEN_NUMBERED_CHAR:
@@ -2563,6 +2618,27 @@
 	}
 	break;
       }
+#ifdef	ENABLE_MULTIBYTE
+    case token::TOKEN_WCHAR:
+      {
+	wchar wch = tok.wc;
+
+	if (possibly_handle_first_page_transition())
+	  ;
+	else {
+	  for (;;) {
+	    curenv->add_char(wcharset_table_entry(wch));
+	    tok.next();
+	    if (tok.type != token::TOKEN_WCHAR)
+	      break;
+	    wch = tok.wc;
+	  }
+	  suppress_next = 1;
+	  bol = 0;
+	}
+	break;
+      }
+#endif	/* ENABLE_MULTIBYTE */
     case token::TOKEN_TRANSPARENT:
       {
 	if (bol) {
@@ -6018,6 +6094,10 @@
 {
   if (type == TOKEN_CHAR)
     return charset_table[c];
+#ifdef	ENABLE_MULTIBYTE
+  if (type == TOKEN_WCHAR)
+    return wcharset_table_entry(wc);
+#endif
   if (type == TOKEN_SPECIAL)
     return get_charinfo(nm);
   if (type == TOKEN_NUMBERED_CHAR)
@@ -6070,6 +6150,11 @@
   case TOKEN_CHAR:
     *pp = (*pp)->add_char(charset_table[c], curenv, &w, &s);
     break;
+#ifdef	ENABLE_MULTIBYTE
+  case TOKEN_WCHAR:
+    *pp = (*pp)->add_char(wcharset_table_entry(wc), curenv, &w, &s);
+    break;
+#endif
   case TOKEN_DUMMY:
     n = new dummy_node;
     break;
@@ -6142,6 +6227,11 @@
   case TOKEN_CHAR:
     curenv->add_char(charset_table[c]);
     break;
+#ifdef	ENABLE_MULTIBYTE
+  case TOKEN_WCHAR:
+    curenv->add_char(wcharset_table_entry(wc));
+    break;
+#endif
   case TOKEN_DUMMY:
     curenv->add_node(new dummy_node);
     break;
@@ -6900,6 +6990,7 @@
   if (!safer_flag)
     mac_path = &macro_path;
   set_string(".T", device);
+  init_encoding_handler();
   init_charset_table();
   init_hpf_code_table();
   if (!font::load_desc())
@@ -6924,6 +7015,9 @@
     // In the DESC file a font name of 0 (zero) means leave this
     // position empty.
     if (strcmp(font::font_name_table[i], "0") != 0)
+#ifdef ENABLE_MULTIBYTE
+      if (!font::is_on_demand(i))
+#endif
       mount_font(j, symbol(font::font_name_table[i]));
   curdiv = topdiv = new top_level_diversion;
   if (nflag)
@@ -7081,6 +7175,9 @@
   init_request("ecs", save_escape_char);
   init_request("el", else_request);
   init_request("em", end_macro);
+#ifdef ENABLE_MULTIBYTE
+  init_request("encoding", select_encoding);
+#endif
   init_request("eo", escape_off);
   init_request("ex", exit_request);
   init_request("fchar", define_fallback_character);
@@ -7533,12 +7630,92 @@
 
 dictionary charinfo_dictionary(501);
 
+#ifdef ENABLE_MULTIBYTE
+struct charinfo_list {
+  struct charinfo_list *next;
+  charinfo *ci;
+} *wcharset_table = NULL;
+
+/* XXX: use more efficient method? */
+static charinfo*
+lookup_wcharset_table(wchar wc)
+{
+  struct charinfo_list *cl;
+  for (cl = wcharset_table; cl; cl = cl->next) {
+    if (cl->ci && cl->ci->get_wchar_code() == wc)
+      return cl->ci;
+  }
+  return NULL;
+}
+
+static void
+add_wcharset_table(charinfo *ci)
+{
+  struct charinfo_list *cl = new struct charinfo_list;
+  cl->next = wcharset_table;
+  cl->ci = ci;
+  wcharset_table = cl;
+}
+
+charinfo *wcharset_table_entry(wchar wc)
+{
+  if (! is_wchar_code(wc))
+    return NULL;
+  charinfo *cp = lookup_wcharset_table(wc);
+  if (cp == NULL) {
+    int i = wchar_code(wc);
+    char buf[16];
+    if (i > 0x100)
+      sprintf(buf, "u%04X", i);
+    else {
+      cp = get_charinfo_by_number(i);
+      if (cp != NULL)
+	return cp;
+      sprintf(buf, "char%d", i); // ???
+    }
+    symbol nm = symbol(buf);
+    cp = new charinfo(nm);
+    (void)charinfo_dictionary.lookup(nm, cp);
+    cp->set_wchar_code(wc);
+    add_wcharset_table(cp);
+  }
+  return cp;
+}
+
+static charinfo *
+wchar_charinfo(symbol nm)
+{
+  const char *p = nm.contents();
+  if (*p != 'u') {
+    return NULL;
+  }
+  char *pp;
+  wchar wc = make_wchar(strtol(p + 1, &pp, 16));
+  if (pp < p + 5)
+      return NULL;
+  charinfo *cp = lookup_wcharset_table(wc);
+  if (cp)
+    return cp;
+  /* create on demand */
+  cp = new charinfo(nm);
+  cp->set_wchar_code(wc);
+  add_wcharset_table(cp);
+  return cp;
+}
+#endif
+
 charinfo *get_charinfo(symbol nm)
 {
   void *p = charinfo_dictionary.lookup(nm);
   if (p != 0)
     return (charinfo *)p;
+#ifdef ENABLE_MULTIBYTE
+  charinfo *cp = wchar_charinfo(nm);
+  if (cp == NULL)
+    cp = new charinfo(nm);
+#else
   charinfo *cp = new charinfo(nm);
+#endif
   (void)charinfo_dictionary.lookup(nm, cp);
   return cp;
 }
@@ -7548,6 +7725,9 @@
 charinfo::charinfo(symbol s)
 : translation(0)