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 + ) + 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(端末表示)を追加した以外はオリジナルのま +まです。 +以下は使用例。 + + (1) groff -Tnippon -man groff.jman + + 日本語を含むroffファイル(groff.jman)をmanマクロを使ってフォーマットし、 +端末に表示します。 + + (2) groff -Tps -man groff.jman + + 日本語を含むroffファイルをフォーマットし、PostScriptに変換します。 + + (3) groff -TX100 -man groff.jman + + 日本語を含むroffファイルをフォーマットし、Xウィンドウに表示します。 + + (4) 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++ . */ #undef HAVE_CC_LIMITS_H /* Define if you have a C++ . */ #undef HAVE_CC_OSFCN_H -/* Define if you have the header file. */ +/* Define to 1 if you have the 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 header file. */ +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `isatty' function. */ +#undef HAVE_ISATTY + +/* Define if you have and nl_langinfo(CODESET). */ +#undef HAVE_LANGINFO_CODESET + +/* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_MATH_H +/* Define to 1 if you have the 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 header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H -/* Define if you have the header file. */ +/* Define to 1 if you have the 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 header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H -/* Define if you have the header file. */ +/* Define to 1 if you have the 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 defines struct exception. */ #undef HAVE_STRUCT_EXCEPTION -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ #undef HAVE_SYS_DIR_H /* Define if you have sys_errlist in or in . */ @@ -87,10 +99,16 @@ /* Define if you have sysnerr in or . */ #undef HAVE_SYS_NERR -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H -/* Define if you have the header file. */ +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the 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 or . */ +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if `sys_siglist' is declared by or . */ #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 + +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 + +#ifdef ENABLE_MULTIBYTE +typedef int wchar; // negative is used for charcode & index +#else +typedef char wchar; +#endif + +#include + +#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++ . */ +#define HAVE_CC_LIMITS_H 1 + +/* Define if you have a C++ . */ +/* #undef HAVE_CC_OSFCN_H */ + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `isatty' function. */ +#define HAVE_ISATTY 1 + +/* Define if you have and nl_langinfo(CODESET). */ +#define HAVE_LANGINFO_CODESET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MATH_H 1 + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the 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 header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the 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 defines struct exception. */ +#define HAVE_STRUCT_EXCEPTION 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_DIR_H 1 + +/* Define if you have sys_errlist in or in . */ +#define HAVE_SYS_ERRLIST 1 + +/* Define if you have sysnerr in or . */ +#define HAVE_SYS_NERR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the 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 or . */ +#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 + 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 #include #include +#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 #include @@ -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 #include #include +#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 #include #include +#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 .. [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 --- 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 #include #include +#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. + */ + 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 + +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 +#ifdef ENABLE_MULTIBYTE +#include +#include +#ifdef HAVE_LANGINFO_CODESET +#include +#else +#include +#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 +#include + +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 #include +#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 #include +#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 @@ -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 @@ -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 + +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 #include #include +#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 +#include +#include +#include + +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 #include #include +#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 +#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 +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 \ : 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 \ : 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 #include +#include #include #include +#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 #include +#include #include #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 @@ -10,6 +11,7 @@ #include #include #include +#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 #include #include +#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 #include #include +#include #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 #include +#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 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 = ¯o_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) : tr