diff -Nru slrn-0.9.6.2.orig/configure slrn-0.9.6.2/configure --- slrn-0.9.6.2.orig/configure Fri Dec 24 02:24:32 1999 +++ slrn-0.9.6.2/configure Mon Dec 27 10:46:03 1999 @@ -3087,6 +3087,7 @@ slrnpull : \$(OBJDIR)/slrnpull @echo slrnpull created in \$(OBJDIR) \$(OBJDIR)/slrnpull : \$(OBJDIR)/slrnpull.o \$("slrnpull"_DEPS) \$(EXECDEPS) + cd \$(OBJDIR); \$(COMPILE_CMD) -DSLRNPULL_CODE \$(SRCDIR)/ttymsg.c \$(CC) -o \$(OBJDIR)/slrnpull \$(LDFLAGS) \$(OBJDIR)/slrnpull.o \$("slrnpull"_LIBS) \$(EXECLIBS) \$(OBJDIR)/slrnpull.o : \$(SRCDIR)/slrnpull.c \$(DOT_O_DEPS) \$("slrnpull"_O_DEP) cd \$(OBJDIR); \$(COMPILE_CMD) \$("slrnpull"_INC) \$(EXECINC) \$(SRCDIR)/slrnpull.c diff -Nru slrn-0.9.6.2.orig/doc/slrn.rc slrn-0.9.6.2/doc/slrn.rc --- slrn-0.9.6.2.orig/doc/slrn.rc Fri Dec 24 02:24:33 1999 +++ slrn-0.9.6.2/doc/slrn.rc Mon Jan 31 21:57:10 2000 @@ -20,9 +20,36 @@ %hostname "YOUR.HOSTNAME" %set username "jd" +%realnameはFrom:行に付く。FromフィールドにJISはまずいので +% set use_mime 1 以外では日本語を入れないほうがいいでしょう。 +% (あるいはmimeエンコードした後の文字列を入れる) +%set realname "菊谷 誠/Kikutani Makoto" %set realname "John Doe" %set replyto "jd@somthing.com" +%--------------------- 日本語版での拡張 begin --------------------- +% メッセージを日本語で出力する。default は0(無効)。 +set japanese_messages 1 + +% ディスプレイコードの指定。default は 1。 +% 1(euc), 2(jis), 3(sjis) のどれかを指定 +% set display_code 1 + +% 記事の編集に使用するエディタが読み込むコードの指定(指定しなければ +% display_code と同じ値)。display_code と異なる場合に指定する。 +% set editor_code 1 + +% SJISで投稿された記事のカタカナとひらがなを交換。default は1(交換する)。 +% set detect_SJIS 1 + +% GMTからローカルタイムへの変換。default は0(変換しない)。 +% set gmt_to_local 1 + +% 1にすると、記事中の URL が highlight 表示され、マウスでクリックすると +% ブラウザに渡される(default は 1)。 +% set click_on_url 1 +%--------------------- 日本語版での拡張 end --------------------- + % Name of signature file to use %set signature ".signature" @@ -46,6 +73,8 @@ % specifiers are recognized: % %d:date, %r:real name, %f:email address, %s:subject, % %m:msgid, %n:newsgroups, %%: percent +% set followup_string "日時%dにおいて\n %r<%f> さんは書きました:\n" +% set followup_string "%r<%f>さんは\n記事%mでこう書きました:\n" set followup_string "On %d, %r <%f> wrote:" set reply_string "In %n, you wrote:" @@ -136,6 +165,7 @@ % If non-zero, you will be prompted whether or not a Cc header will be % generated on the followup. set cc_followup 0 +% set cc_followup_string "[このメッセージはnewsにもポストされています]" set cc_followup_string "[This message has also been posted.]" % Set to 0 to turn off display of ~ at end of article @@ -244,8 +274,12 @@ %--------------------------------------------------------------------------- % Mime support %--------------------------------------------------------------------------- +% use_mime を2(0と1以外)に設定すると、mimeデコードのみ行なう +% (したがって、このときsubjectに日本語があると生JISで出る) set use_mime 1 -set mime_charset "iso-8859-1" +% set mime_charset "iso-8859-1" +% 日本語では +set mime_charset "ISO-2022-JP" % If non-zero, call metamail for mime formats that slrn does not handle set use_metamail 1 set metamail_command "metamail" @@ -258,6 +292,7 @@ % attempt reconnection without asking user. set query_reconnect 1 +% ^Lで制御されるページで使われる % Character to use to hide spoiler text: set spoiler_char '*' @@ -342,6 +377,84 @@ %--------------------------------------------------------------------------- % Colors %--------------------------------------------------------------------------- +#if$TERM vt100 kon linux console +% ---- 16色液晶でのLinux konの設定 +color article "white" "black" +color author "magenta" "black" +color boldtext "brightblue" "black" +color box "black" "white" +color cursor "green" "black" +color description "blue" "white" +color error "red" "black" +color group "brightgreen" "black" +color grouplens_display "blue" "black" +color header_name "green" "black" +color header_number "white" "black" +color headers "brightcyan" "black" +color high_score "red" "black" +color italicstext "magenta" "black" +color menu "yellow" "blue" +color menu_press "blue" "yellow" +color normal "white" "black " +color pgpsignature "blue" "black" +color quotes "brown" "black" +color quotes1 "magenta" "black" +color quotes2 "brown" "black" +color quotes3 "brown" "black" +color quotes4 "brown" "black" +color quotes5 "brown" "black" +color quotes6 "brown" "black" +color quotes7 "brown" "black" +color response_char "green" "black" +color signature "blue" "white" +color selection "yellow" "blue" +color status "yellow" "blue" +color subject "white" "black" +color thread_number "blue" "black" +color tilde "green" "white" +color tree "red" "black" +color underlinetext "cyan" "black" +color verbatum "green" "black" +#elif$TERM kterm +% ---- kterm ---- +color article "black" "white" +color author "magenta" "white" +color boldtext "brightblue" "white" +color box "white" "black" +color cursor "brightgreen" "white" +color description "blue" "white" +color error "red" "white" +color frame "blue" "yellow" +color group "blue" "white" +color grouplens_display "blue" "white" +color header_name "green" "white" +color header_number "black" "white" +color headers "gray" "white" +color high_score "red" "white" +color italicstext "magenta" "white" +color menu "yellow" "blue" +color menu_press "blue" "yellow" +color normal "black" "white" +color quotes "red" "white" +color quotes1 "magenta" "white" +color quotes2 "brown" "white" +color quotes3 "brown" "white" +color quotes4 "brown" "white" +color quotes5 "brown" "white" +color quotes6 "brown" "white" +color quotes7 "brown" "white" +color response_char "green" "white" +color signature "blue" "white" +color selection "yellow" "blue" +color status "yellow" "blue" +color subject "black" "white" +color thread_number "blue" "white" +color tilde "green" "white" +color tree "red" "white" +color underlinetext "cyan" "white" +color verbatum "green" "white" +#elif$TERM rxvt +% rxvtのときは以下の(標準の)設定がいいよ color article "blue" "black" color author "magenta" "black" color boldtext "brightblue" "black" @@ -379,6 +492,7 @@ color tree "red" "black" color underlinetext "cyan" "black" color verbatum "green" "black" +#endif %----------------------------------------------------- % Monochrome attributes for monochrom terminals. One or more attributes % may be specified. diff -Nru slrn-0.9.6.2.orig/src/Makefile.g32 slrn-0.9.6.2/src/Makefile.g32 --- slrn-0.9.6.2.orig/src/Makefile.g32 Fri Dec 24 02:24:37 1999 +++ slrn-0.9.6.2/src/Makefile.g32 Mon Dec 27 10:46:03 1999 @@ -2,9 +2,9 @@ # Makefile for CYGWIN32 or MINGW32 CC = gcc -CCFLAGS = -O2 -fno-strength-reduce -W -Wall -LDFLAGS = -Wl,--subsystem,console -MISCLIBS = -lwsock32 -lwinspool +CCFLAGS = -O2 -fno-strength-reduce -W -Wall -mno-cygwin +LDFLAGS = -Wl,--subsystem,console -mno-cygwin +MISCLIBS = -lcrtdll -lwsock32 -lwinspool #----------------------------------------------------------------------------- # Directory where the slang library, slanglib.a, is located. diff -Nru slrn-0.9.6.2.orig/src/art.c slrn-0.9.6.2/src/art.c --- slrn-0.9.6.2.orig/src/art.c Fri Dec 24 02:24:41 1999 +++ slrn-0.9.6.2/src/art.c Mon Jan 17 16:06:45 2000 @@ -19,6 +19,9 @@ Mass Ave, Cambridge, MA 02139, USA. */ #include "config.h" +#if defined(__os2__) +#include +#endif #include "slrnfeat.h" /*{{{ system include files */ @@ -120,6 +123,12 @@ #if SLRN_HAS_TILDE_FEATURE int Slrn_Use_Tildes = 1; #endif +#ifdef KANJI +int Slrn_Gmt2local = 0; +int Slrn_Detect_SJIS = 1; +Charset_Type Slrn_Default_Charset; +Slrn_Article_Buf_Type Slrn_Article_Buf = {NULL, NULL, 0}; +#endif int Slrn_Startup_With_Article = 0; int Slrn_Followup_Strip_Sig; @@ -235,7 +244,11 @@ static int Largest_Header_Number; static int Article_Window_Nrows; static int Article_Window_HScroll; +#ifdef KANJI +static Charset_Type Header_Charset; +#else static SLKeymap_Function_Type *Art_Functions_Ptr; +#endif static int Header_Window_HScroll; static Slrn_Header_Type *At_End_Of_Article; @@ -271,6 +284,11 @@ #if SLRN_HAS_SPOILERS static void show_spoilers (void); #endif +#ifdef KANJI +#define smg_write_nchars(s, n) SLsmg_write_nchars((s), (n)) +#define smg_write_string(s) SLsmg_write_string((s)) +#define smg_write_char(c) SLsmg_write_char((c)) +#endif /*}}}*/ /*{{{ utility functions */ @@ -349,7 +367,11 @@ Slrn_Article_Window.nrows = Article_Window_Nrows; Slrn_Header_Window.nrows = Header_Window_Nrows; +#ifdef KANJI + if (Slrn_Current_Article != NULL && Header_Showing != NULL) +#else if (Slrn_Current_Article != NULL) +#endif { if (Slrn_Wrap_Mode & 0x4) _slrn_art_wrap_article (Slrn_Current_Article); @@ -737,6 +759,11 @@ { ch = *ptr; +#ifdef KANJI + if (ch & 0x80) { + break; + } +#endif switch (ch) { case '.': @@ -757,7 +784,9 @@ case '}': case '{': case ')': +#ifndef KANJI case ',': +#endif case ';': case '>': case '<': @@ -798,11 +827,18 @@ Slrn_Article_Line_Type *l; Slrn_Article_Type *a; unsigned int argc; +#ifdef KANJI + int is_wrapped; +#endif if (NULL == (a = Slrn_Current_Article)) return -1; l = a->lines; +#ifdef KANJI + is_wrapped = a->is_wrapped; + if (is_wrapped) unwrap_article (); +#endif *start = 0; argc = 0; @@ -835,6 +871,9 @@ l = l->next; } +#ifdef KANJI + if (is_wrapped) wrap_article (); +#endif *argc_ptr = argc; return 0; } @@ -860,6 +899,11 @@ if (browser == NULL) { +#ifdef KANJI + if (Slrn_Japanese_Messages) + slrn_error ("Webブラウザが定義されていません。"); + else +#endif slrn_error ("No Web Browser has been defined."); return; } @@ -906,6 +950,11 @@ if (0 == argc) { +#ifdef KANJI + if (Slrn_Japanese_Messages) + slrn_error ("URL がありません。"); + else +#endif slrn_error ("No URLs found."); return; } @@ -944,11 +993,23 @@ static char search_str[256]; Slrn_Article_Line_Type *l; +#ifdef KANJI + if (slrn_read_input (Slrn_Japanese_Messages + ? "検索" + : "Search", search_str, NULL, 0, 0) <= 0) return; +#else if (slrn_read_input ("Search", search_str, NULL, 0, 0) <= 0) return; +#endif l = slrn_search_article (search_str, NULL, 0, 1); +#ifdef KANJI + if (l == NULL) slrn_error (Slrn_Japanese_Messages + ? "見つかりません。" + : "Not found."); +#else if (l == NULL) slrn_error ("Not found."); +#endif } /*}}}*/ @@ -1050,10 +1111,22 @@ if (Slrn_Current_Header->next == NULL) { if (Slrn_Query_Next_Group) +#ifdef KANJI + msg = Slrn_Japanese_Messages + ? "記事の終りです、%s を押すと次のグループへ。" + : "At end of article, press %s for next group."; +#else msg = "At end of article, press %s for next group."; +#endif } else if (Slrn_Query_Next_Article) +#ifdef KANJI + msg = Slrn_Japanese_Messages + ? "記事の終りです、%s を押すと次の未読記事へ。" + : "At end of article, press %s for next unread article."; +#else msg = "At end of article, press %s for next unread article."; +#endif if ((ch1 = SLang_Last_Key_Char) == 27) ch1 = ' '; ch = ch1; @@ -1555,11 +1628,35 @@ /*}}}*/ /*{{{ fixup_realname */ +#ifdef KANJI +static int strip_backslash(char *p) /*{{{*/ +{ + int skip = 0; + + while(*p != '\0') { + if (*p == '\\') { + skip++; + p++; + } + if (skip > 0) { + *(p - skip) = *p; + } + p++; + } + *(p - skip) = '\0'; + return (skip); +} + +/*}}}*/ +#endif static void fixup_realname (Slrn_Header_Type *h) /*{{{*/ { char *p, *pmin, *pmax; if ((h->realname == NULL) || (h->realname_len == 0)) return; pmin = h->realname; +#ifdef KANJI + h->realname_len -= strip_backslash(pmin); +#endif p = pmin + (h->realname_len - 1); while ((p >= pmin) && ((*p == ' ') || (*p == '\t'))) p--; p++; @@ -1588,6 +1685,9 @@ { char ch = *p; +#ifdef KANJI + if ((unsigned char)ch & 0x80) return; +#endif if (isalpha ((unsigned char)ch)) return; p++; } @@ -1619,7 +1719,21 @@ int n; f = from; +#ifdef KANJI + while (((ch = *f) != 0) && (ch != '<') && (ch != '(')) { + if (ch == '"') { + f0 = f + 1; + while(((ch = *f0) != 0) && ((ch != '"') || (*(f0 - 1) == '\\'))) f0++; + h->realname = f; + h->realname_len = (unsigned int) (f0 - f + 1); + fixup_realname (h); + return; + } + f++; + } +#else while (((ch = *f) != 0) && (ch != '<') && (ch != '(')) f++; +#endif if (ch == '(') { /* Look for a '<'. There is some probability that this is of the @@ -1748,6 +1862,11 @@ h = h->next; } +#ifdef KANJI + if (Slrn_Japanese_Messages) + slrn_error ("記事が見つかりません。"); + else +#endif slrn_error ("Article not found."); } @@ -1807,13 +1926,422 @@ +#ifdef KANJI +static int fixup_from_line(unsigned char *d, char *s, int dlen) /*{{{*/ +{ + int ret; + + /* From: に生 JIS が含まれていると、realname を抽出する事が出来ない場合 + があるので、JIS は EUC に直す。*/ + ret = slrn_jis2int(d, (unsigned char *)s, dlen); + if (ret == 2) { /* 不正な JIS */ + /* 生 JIS に backslash を入れているかも知れない */ + (void)strip_backslash(s); + ret = slrn_jis2int(d, (unsigned char *)s, dlen); + } + return ret; +} + +/*}}}*/ + + /* 簡易版 gmt2local。GMT 表示の時刻のみを local timezone に変換する。*/ +/* + [Tue,] 28 Nov [19]96 08:07:32 [GMT|[-+]0000[ (GMT)]] の形式を + + 28 Nov 1996 17:07:32 JST の形式に変換 + */ +static char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL}; +typedef enum {JAN, FEB, MAR, APR, MAY, JUN, + JUL, AUG, SEP, OCT, NOV, DEC, NUL} Month_Type; + +static int get_month_days(Month_Type mon, int year) /*{{{*/ +{ + if (mon == FEB) { + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) { + return 29; /* a leap year */ + } + return 28; + } else if (mon == APR || mon == JUN || mon == SEP || mon == NOV) { + return 30; + } + return 31; +} +/*}}}*/ + +/* Date: ヘッダを含めて、d に変換した日付の文字列を返す。 + * 返却値は変換した場合は 1 を返す。 + * 変換できない、あるいは変換不要な場合は 0 を返す。 */ +static int gmt2local(char *d, char *s) /*{{{*/ +{ + int i, date, year, hour, min, sec; + Month_Type mon; + char *f; + + if (s == NULL || *s == '\0') { /* Date: field is null */ + return 0; + } + + s += 6; /* skip "Date: " */ + if (*(s + 3) == ',' && isdigit(*(s + 5))) { /* 1st field is day */ + s += 5; /* skip day field */ + } else if (!isdigit(*s)) { /* 1st field not is date */ + return 0; /* irregular format */ + } + + f = s; + for (i = 0; i < 4; i++) { /* get timezone field */ + f = strchr(f, ' '); + if (f == NULL) { + break; + } + f++; + } + if (f != NULL) { /* timezone exists */ + if (*f == '+' || *f == '-') { + f++; + } + if (strncmp(f, "0000", 4) != 0 && strncmp(f, "GMT", 3) != 0) { + return 0; /* timezone is specified other than GMT */ + } + } else if (i < 3) { + return 0; /* irregular format */ + } + + if (sscanf(s, "%d %s %d %d:%d:%d", + &date, d, &year, &hour, &min, &sec) != 6) { + return 0; + } + + for (mon = JAN; mon < NUL; mon++) { /* search month name */ + if (strcmp(d, months[mon]) == 0) { + break; + } + } + if (mon == NUL) { + return 0; /* month name not found */ + } + + if (year < 100) { /* normalize short year */ + if (year < 70) { + year += 2000; + } else { + year += 1900; + } + } + + min -= Slrn_Timezone.offset; /* add local time */ + if (min < 0) { + min += 24 * 60; + date--; + } + hour += min / 60; + min %= 60; + if (hour > 23) { + hour -= 24; + date++; + } + if (date < 1) { + if (mon == JAN) { + mon = DEC; + year--; + } else { + mon--; + } + date = get_month_days(mon, year); + } else if (date > 28) { + i = get_month_days(mon, year); + if (date > i) { + date -= i; + if (mon == DEC) { + mon = JAN; + year++; + } else { + mon++; + } + } + } + + sprintf(d, "Date: %d %s %d %02d:%02d:%02d %s", + date, months[mon], year, hour, min, sec, Slrn_Timezone.std); + + return 1; +} + +/*}}}*/ + +/* ひらがな <-> カタカナ変換 */ +static void exchange_kana(unsigned char *d, unsigned char *s) /*{{{*/ +{ + int ch, ch2; + while ((ch = *s++) != 0) { + if (ch & 0x80) { + ch2 = *s++; + if ((ch == 0xa4 || ch == 0xa5) && ch2 >= 0xa1 && ch2 <= 0xf3) { + ch = (0xa4 + 0xa5) - ch; + } + *d++ = ch; + *d++ = ch2; + } else { + *d++ = ch; + } + } + *d = '\0'; +} + +/*}}}*/ + +static void convert_unprintable(unsigned char *s) +{ + while (*s) { + if (*s & 0x80) *s = '?'; + s++; + } +} + +static void copy_article_line(Slrn_Article_Line_Type *l, unsigned char *str, int sjis) +{ + char *new_buf; + unsigned int new_len = strlen((char *)str); + + if (new_len > strlen(l->buf)) { + new_buf = slrn_realloc(l->buf, new_len + 1, 1); + if (new_buf == NULL) { + return; + } + l->buf = new_buf; + } + if (sjis && Slrn_Detect_SJIS) { + exchange_kana((unsigned char *)l->buf, str); + } else { + strcpy(l->buf, (char *)str); + } +} + +void slrn_convert_body(Slrn_Article_Line_Type *beg, Slrn_Article_Line_Type *end, Charset_Type charset) +{ + Slrn_Article_Line_Type *l = beg; + int esc = 0, jis8 = 0, ret; + unsigned char *b; + + if (end != NULL) { + end = end->next; + } + + if (charset == USASCII || charset == UNKNOWN_CHARSET) { + charset = Slrn_Default_Charset; + } + + Header_Charset = charset; /* pass for header charset */ + + if (charset >= ISO2022JP && charset < UNKNOWN_CHARSET) { + while (l != NULL && l != end) { + b = (unsigned char *)l->buf; + ret = slrn_all2int(Slrn_Tmp_Str, b, SLRN_TMP_STR_LEN, charset); + if (!esc && (ret == 1 || ret == 2)) { + esc++; + } else if (ret > 2) { + /* evaluate whether 8bit JIS(SJIS or EUC) or ISO-8859-1 */ + /* (ret:jis8) = (3:+3, 4:+1, 5:-1, 6:-3) */ + jis8 += (9 - ret * 2); + } + if (ret > 0 && (ret < 5 || esc)) { + copy_article_line(l, Slrn_Tmp_Str, (ret == 4)); + } + l = l->next; + } + charset = ISO2022JP; + + if (esc == 0 && jis8 < 0) { + charset = ISO88591; + } + } else if (charset == KOI8R) { + l = beg; /* koi8-r の場合、kterm 用に変換する */ + while (l != NULL && l != end) { + slrn_convert_koi8_r2iso8859_5((unsigned char *)l->buf); + l = l->next; + } + charset = ISO88595; + } + + l = beg; + while (l != NULL && l != end) { +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + if (Slang_Use_ISO8859) { + l->charset = charset; + } else +#endif + if (charset > USASCII && charset < ISO2022JP) { + convert_unprintable((unsigned char *)l->buf); + } else { + break; + } + l = l->next; + } +} + +/* header および body を内部コードに変換する */ +static void convert_lines(Slrn_Header_Type *h) /*{{{*/ +{ + Slrn_Article_Line_Type *l, *subject, *from, *date; + int ret = 0, esc = 0, jis8 = 0; + unsigned char *b; + +#if SLRN_HAS_MIME + if (!Slrn_Mime_Was_Modified) { +#endif + l = Slrn_Current_Article->lines; + while (l != NULL && (l->flags & HEADER_LINE)) { + l = l->next; + } + slrn_convert_body(l, NULL, USASCII); +#if SLRN_HAS_MIME + } +#endif + + from = slrn_extract_header_line(Slrn_Current_Article, "From: ", 6); + if (h->charset == ISO2022JP) { + ret = fixup_from_line(Slrn_Tmp_Str, from->buf, SLRN_TMP_STR_LEN); + if (ret > 4) { + h->charset = ISO88591; + } else if (ret > 0) { + copy_article_line(from, Slrn_Tmp_Str, (ret == 4)); + } + } + + if (h->charset < ISO2022JP) { + (void)strip_backslash(from->buf); + } + if (Header_Charset != USASCII && + (h->charset == Slrn_Default_Charset || + (h->charset == ISO88591 && Header_Charset < ISO2022JP))) { + h->charset = Header_Charset; + } else if (Header_Charset == USASCII) { + Header_Charset = Slrn_Default_Charset; + } else if (Header_Charset == Slrn_Default_Charset) { + Header_Charset = h->charset; + } + + subject = slrn_extract_header_line (Slrn_Current_Article, "Subject: ", 8); + date = slrn_extract_header_line(Slrn_Current_Article, "Date: ", 6); + + l = Slrn_Current_Article->lines; + while (l != NULL && (l->flags & HEADER_LINE)) { + if (l->charset == USASCII) { + l->charset = Header_Charset; + } + b = (unsigned char *)l->buf; + if (l == date) { + if (Slrn_Gmt2local && gmt2local((char *)Slrn_Tmp_Str, l->buf) > 0) { + copy_article_line(l, Slrn_Tmp_Str, 0); + } + } else if (l->charset >= ISO2022JP && l->charset <= SHIFTJIS) { + if (l == subject) { + ret = slrn_recover_jis(Slrn_Tmp_Str, b, SLRN_TMP_STR_LEN); + if (l->charset == SHIFTJIS && ret > 0 && ret < 4) { + ret = 4; + } + } else if (l == from) { + ret = 0; + } else { + ret = slrn_jis2int(Slrn_Tmp_Str, b, SLRN_TMP_STR_LEN); + } + if (!esc && ret > 0) { + if (ret >= 1 && ret <= 3) { + esc = 1; + jis8 = 0; + } else if (ret == 4) { + jis8++; + } else if (ret == 5) { + jis8--; + } + } + if (ret > 0 && (ret < 5 || esc)) { + copy_article_line(l, Slrn_Tmp_Str, (ret == 4)); + } + } else if (l->charset == KOI8R) { + slrn_convert_koi8_r2iso8859_5(b); + l->charset = ISO88595; + } else if (l == subject && l->charset == ISO88591) { + /* Subject: の encoding が ISO-8859-1 と */ + /* なっているが間違いかも知れないのでとりあえず日本語変換を試みる */ + ret = slrn_recover_jis(Slrn_Tmp_Str, b, SLRN_TMP_STR_LEN); + if (ret > 0 && ret < 5) { + copy_article_line(l, Slrn_Tmp_Str, (ret == 4)); + l->charset = ISO2022JP; + } + } + l = l->next; + } + if (h->charset == KOI8R) { + slrn_convert_koi8_r2iso8859_5((unsigned char *)h->subject); + h->charset = ISO88595; + Header_Charset = ISO88595; + } + + l = Slrn_Current_Article->lines; + while (l != NULL && (l->flags & HEADER_LINE)) { + if (jis8 < 0 && h->charset == l->charset) { + l->charset = ISO88591; /* force to change charset to ISO-8859-1 */ + } +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + if (!Slang_Use_ISO8859) +#endif + if (l->charset > USASCII && l->charset < ISO2022JP) { + convert_unprintable((unsigned char *)l->buf); + } + l = l->next; + } +} +/*}}}*/ + +static int read_from_article_buffer (Slrn_Article_Type *a) +{ + Slrn_Article_Line_Type *l; + char *buf = Slrn_Article_Buf.buf; + int i; + + while (*buf != '\0') { + i = 0; + l = (Slrn_Article_Line_Type *) slrn_malloc (sizeof(Slrn_Article_Line_Type), 1, 1); + if (l == NULL) { + return -1; + } + while (buf[i] != '\n' && buf[i] != '\0') i++; + l->buf = slrn_malloc(i + 1, 0, 1); + if (l->buf == NULL) { + slrn_free ((char *) l); + return -1; + } + strncpy(l->buf, buf, i); + l->buf[i] = '\0'; + l->next = l->prev = NULL; + l->flags = 0; + l->charset = USASCII; + if (a->lines == NULL) { + a->lines = l; + } else { + l->prev = a->cline; + a->cline->next = l; + } + a->cline = l; + buf += i; + if (*buf == '\n') buf++; + } + return 0; +} +#endif static int read_article (Slrn_Header_Type *h, int kill_refs, int do_mime) /*{{{*/ { Slrn_Article_Type *a; +#ifdef KANJI + unsigned int total_lines; +#else Slrn_Article_Line_Type *l, *cline; unsigned int total_lines; char buf[NNTP_BUFFER_SIZE], *b, *b1, ch; +#endif unsigned int len; int n = h->number; Slrn_Header_Type *last_header_showing; @@ -1834,10 +2362,19 @@ return 0; /* The cached copy is good */ } +#ifdef KANJI + if (Slrn_Article_Buf.header != h) { +#endif if (h->tag_number) slrn_message_now ("#%2d/%-2d: Retrieving... %s", h->tag_number, Num_Tag_List.len, h->subject); +#ifdef KANJI + else slrn_message_now (Slrn_Japanese_Messages + ? "[%d]読み込み中..." + : "[%d]Reading...", h->number); +#else else slrn_message_now ("[%d]Reading...", h->number); +#endif status = Slrn_Server_Obj->sv_select_article (n, h->msgid); if (status != OK_ARTICLE) @@ -1848,7 +2385,13 @@ return -1; } +#ifdef KANJI + slrn_error(Slrn_Japanese_Messages + ? "記事 %d はありません。" + : "Article %d unavailable.", n); +#else slrn_error ("Article %d unavailable.", n); +#endif if (kill_refs && ((h->flags & HEADER_READ) == 0)) { @@ -1857,6 +2400,9 @@ } return -1; } +#ifdef KANJI + } +#endif At_End_Of_Article = NULL; @@ -1879,19 +2425,49 @@ if (a == NULL) return -1; +#ifdef KANJI + if (Slrn_Article_Buf.header != h) { + char *buf = Slrn_Article_Buf.buf; +#else cline = NULL; +#endif total_lines = 0; while (1) { +#ifdef KANJI + len = buf - Slrn_Article_Buf.buf; + if (len + NNTP_BUFFER_SIZE > Slrn_Article_Buf.len) { + buf = slrn_realloc(Slrn_Article_Buf.buf, Slrn_Article_Buf.len + NNTP_BUFFER_SIZE, 0); + if (buf == NULL) { + return -1; + } + Slrn_Article_Buf.buf = buf; + Slrn_Article_Buf.len += NNTP_BUFFER_SIZE; + buf += len; + } + status = Slrn_Server_Obj->sv_read_line(buf, Slrn_Article_Buf.len - len); + if (status == 0) { + if (*buf == '.' && buf[1] == '\0') { + *buf = '\0'; + } + break; + } +#else status = Slrn_Server_Obj->sv_read_line(buf, sizeof(buf)); if (status == 0) break; +#endif if ((status == -1) || (SLang_Error == USER_BREAK)) { if (Slrn_Server_Obj->sv_reset != NULL) Slrn_Server_Obj->sv_reset (); +#ifdef KANJI + if (Slrn_Japanese_Messages) + slrn_error ("記事の転送を中止、または接続が切れました"); + else +#endif slrn_error ("Article transfer aborted or connection lost"); if (Slrn_Current_Article == NULL) return -1; @@ -1906,16 +2482,41 @@ && (total_lines < (unsigned int) h->lines)) { if (h->tag_number) +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "#%2d/%-2d: %4d/%-4d 行読み込み中 (%s)" + : "#%2d/%-2d: Read %4d/%-4d lines (%s)", + h->tag_number, Num_Tag_List.len, + total_lines, h->lines, h->subject); +#else slrn_message_now ("#%2d/%-2d: Read %4d/%-4d lines (%s)", h->tag_number, Num_Tag_List.len, total_lines, h->lines, h->subject); +#endif else +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "[%d]これまで %d/%d 行読み込み中..." + : "[%d]Read %d/%d lines so far...", + h->number, total_lines, h->lines); +#else slrn_message_now ("[%d]Read %d/%d lines so far...", h->number, total_lines, h->lines); +#endif } len = strlen (buf); +#ifdef KANJI + if ((*buf == '.') && (buf[1] == '.')) { + strcpy(buf, buf + 1); + } else { + len++; + } + buf += len; + *(buf - 1) = '\n'; + *buf = '\0'; +#else l = (Slrn_Article_Line_Type *) slrn_malloc (sizeof(Slrn_Article_Line_Type), 1, 1); if ((l == NULL) @@ -1955,8 +2556,17 @@ cline->next = l; } cline = l; +#endif } +#ifdef KANJI + Slrn_Article_Buf.header = h; + } + if (read_from_article_buffer(a) < 0) { + free_article(); + return -1; + } +#endif Slrn_Current_Article = a; a->cline = a->lines; a->needs_sync = 1; @@ -1981,6 +2591,9 @@ init_article_window_struct (); +#ifdef KANJI + Header_Charset = USASCII; +#endif #if SLRN_HAS_MIME if (Slrn_Use_Mime && (h == Slrn_Current_Header)) { @@ -1990,9 +2603,19 @@ slrn_mime_article_init (); if (do_mime) slrn_mime_process_article (Slrn_Current_Article); } +#ifdef KANJI + else Slrn_Mime_Was_Modified = 0; +#endif #endif +#ifdef KANJI + if (!do_mime) { + return 0; + } + convert_lines(h); +#else slrn_chmap_fix_body (Slrn_Current_Article); +#endif if (last_header_showing != h) { @@ -2019,8 +2642,12 @@ int slrn_string_to_article (char *str) { +#ifdef KANJI + int len; +#else char *estr; Slrn_Article_Line_Type *l, *cline = NULL; +#endif Slrn_Article_Type *a; if (str == NULL) @@ -2033,6 +2660,24 @@ a->is_modified = 1; a->needs_sync = 1; +#ifdef KANJI + len = strlen(str) + 1; + if (Slrn_Article_Buf.len < len) { + char *buf; + buf = slrn_realloc(Slrn_Article_Buf.buf, len, 0); + if (buf == NULL) { + return -1; + } + Slrn_Article_Buf.buf = buf; + Slrn_Article_Buf.len = len; + } + strcpy(Slrn_Article_Buf.buf, str); + if (read_from_article_buffer (a) < 0) { + free_article (); + return -1; + } + Slrn_Article_Buf.header = Slrn_Current_Header; +#else while (1) { unsigned int len; @@ -2072,6 +2717,7 @@ break; else str++; /* skip \n */ } +#endif Header_Showing = Slrn_Current_Header; a->cline = a->lines; @@ -2097,6 +2743,18 @@ /*{{{ reply, reply_cmd, forward, followup */ int slrn_insert_followup_format (char *f, FILE *fp) /*{{{*/ +#ifdef KANJI +{ + int ret; + char *buf = (char *)Slrn_Tmp_Str; + + ret = slrn_insert_followup_format_string (buf, f); + fputs(buf, fp); + return ret; +} + +int slrn_insert_followup_format_string (char *buf, char *f) +#endif { char ch, *s, *smax; @@ -2110,7 +2768,11 @@ { if (ch != '%') { +#ifdef KANJI + *buf++ = ch; +#else putc (ch, fp); +#endif continue; } s = smax = NULL; @@ -2144,13 +2806,31 @@ break; case '%': default: +#ifdef KANJI + *buf++ = ch; +#else putc (ch, fp); +#endif } if (s == NULL) continue; +#ifdef KANJI + if (smax == NULL) { + strcpy(buf, s); + buf += strlen(s); + } else { + int len = smax - s; + strncpy(buf, s, len); + buf += len; + } +#else if (smax == NULL) fputs (s, fp); else fwrite (s, 1, (unsigned int) (smax - s), fp); +#endif } +#ifdef KANJI + *buf = '\0'; +#endif return 0; } @@ -2176,6 +2856,11 @@ return -1; if (Slrn_Current_Article == NULL) { +#ifdef KANJI + if (Slrn_Japanese_Messages) + slrn_error ("この操作は記事が必要です"); + else +#endif slrn_error ("This operation requires an article"); return -1; } @@ -2198,6 +2883,9 @@ FILE *fp; char file[256]; unsigned int n; +#ifdef KANJI + int is_wrapped; +#endif if (-1 == slrn_check_batch ()) return; @@ -2283,7 +2971,11 @@ } #if SLRN_GEN_FROM_EMAIL_HEADER +#ifdef KANJI + fprintf (fp, "From: %s\n", slrn_make_from_string (EUC)); +#else fprintf (fp, "From: %s\n", slrn_make_from_string ()); +#endif n += 1; #endif @@ -2301,6 +2993,10 @@ n += 2; +#ifdef KANJI + is_wrapped = Slrn_Current_Article->is_wrapped; + if (is_wrapped) unwrap_article (); +#endif l = Slrn_Current_Article->lines; if (Slrn_Prefix_Arg_Ptr == NULL) { @@ -2317,6 +3013,9 @@ } slrn_add_signature (fp); slrn_fclose (fp); +#ifdef KANJI + if (is_wrapped) wrap_article (); +#endif slrn_mail_file (file, 1, n, from, subject); if (Slrn_Use_Tmpdir) (void) slrn_delete_file (file); @@ -2334,7 +3033,13 @@ if (read_article (Slrn_Current_Header, Slrn_Del_Article_Upon_Read, 1) < 0) return; if (Slrn_User_Wants_Confirmation +#ifdef KANJI + && (slrn_get_yesno_cancel (Slrn_Japanese_Messages + ? "本当に返事しますか" + : "Are you sure you want to reply") <= 0)) +#else && (slrn_get_yesno_cancel ("Are you sure you want to reply") <= 0)) +#endif return; reply (NULL); } @@ -2349,6 +3054,9 @@ char file[256]; char to[256]; int edit; +#ifdef KANJI + int is_wrapped; +#endif if (-1 == slrn_check_batch ()) return; @@ -2362,13 +3070,30 @@ #endif *to = 0; +#ifdef KANJI + if (slrn_read_input (Slrn_Japanese_Messages + ? "転送先 (^G で中止)" + : "Forward to (^G aborts)", NULL, to, 1, 0) <= 0) { + slrn_error (Slrn_Japanese_Messages + ? "中止しました。emailアドレスが必要です。" + : "Aborted. An email address is required."); + return; + } +#else if (slrn_read_input ("Forward to (^G aborts)", NULL, to, 1, 0) <= 0) { slrn_error ("Aborted. An email address is required."); return; } +#endif +#ifdef KANJI + if (-1 == (edit = slrn_get_yesno_cancel (Slrn_Japanese_Messages + ? "送る前にメッセージを編集しますか" + : "Edit the message before sending"))) +#else if (-1 == (edit = slrn_get_yesno_cancel ("Edit the message before sending"))) +#endif return; @@ -2390,15 +3115,24 @@ to, subject == NULL ? "" : subject); #if defined(IBMPC_SYSTEM) +#ifdef KANJI + fprintf (fp, "From: %s\n", slrn_make_from_string (EUC)); +#else fprintf (fp, "From: %s\n", slrn_make_from_string ()); #endif +#endif if (0 != *Slrn_User_Info.replyto) fprintf (fp, "Reply-To: %s (%s)\n", Slrn_User_Info.replyto, Slrn_User_Info.realname); putc ('\n', fp); +#ifdef KANJI + is_wrapped = Slrn_Current_Article->is_wrapped; + if (is_wrapped) unwrap_article (); + /* 内部コード(EUC)で editor に渡すため、l->buf をそのまま出力 */ +#endif l = Slrn_Current_Article->lines; while (l != NULL) { @@ -2406,6 +3140,9 @@ l = l->next; } slrn_fclose (fp); +#ifdef KANJI + if (is_wrapped) wrap_article (); +#endif (void) slrn_mail_file (file, edit, 3, to, subject); @@ -2432,6 +3169,10 @@ int free_cc_string = 0; #endif int strip_sig; +#ifdef KANJI + Slrn_Header_Type *h; + int i = 0, tagged_num = 1; +#endif /* The perform_cc testing is ugly. Is there an easier way?? */ @@ -2439,6 +3180,23 @@ return; slrn_uncollapse_this_thread (Slrn_Current_Header, 1); +#ifdef KANJI + h = Slrn_Current_Header; + if (Num_Tag_List.len) { + tagged_num = slrn_get_yesno_cancel (Slrn_Japanese_Messages + ? "タグ付けした記事にフォローしますか" + : "followup tagged articles"); + if (tagged_num < 0) { + return; + } + if (tagged_num) { + Slrn_Current_Header = Num_Tag_List.headers[0]; + tagged_num = Num_Tag_List.len; + } else { + tagged_num = 0; + } + } +#endif if (read_article (Slrn_Current_Header, Slrn_Del_Article_Upon_Read, 1) < 0) return; if (-1 == _slrn_art_unwrap_article (Slrn_Current_Article)) @@ -2459,7 +3217,14 @@ strip_sig = ((prefix_arg == -1) && Slrn_Followup_Strip_Sig); if (Slrn_User_Wants_Confirmation +#ifdef KANJI + && tagged_num == 0 + && (slrn_get_yesno_cancel (Slrn_Japanese_Messages + ? "本当にフォローアップしますか" + : "Are you sure you want to followup") <= 0)) +#else && (slrn_get_yesno_cancel ("Are you sure you want to followup") <= 0)) +#endif return; /* Here is the logic: @@ -2473,6 +3238,13 @@ perform_cc = -1; /* Don't know */ cc_address = NULL; +#ifdef KANJI + do { + if (i > 0) { + Slrn_Current_Header = Num_Tag_List.headers[i]; + if (read_article (Slrn_Current_Header, Slrn_Del_Article_Upon_Read, 1) < 0) return; + } else { +#endif if (NULL != (newsgroups = slrn_extract_header ("Followup-To: ", 13))) { newsgroups = slrn_skip_whitespace (newsgroups); @@ -2490,7 +3262,13 @@ { if (is_poster) cc_address = parse_reply_address (); +#ifdef KANJI + if (slrn_get_yesno (1, Slrn_Japanese_Messages + ? "投稿者の指定通り、投稿者(poster)に返事を出しますか" + : "Do you want to reply to POSTER as poster prefers")) +#else if (slrn_get_yesno (1, "Do you want to reply to POSTER as poster prefers")) +#endif { reply (cc_address); return; @@ -2524,7 +3302,13 @@ if (Slrn_Post_Obj->po_can_post == 0) { +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages + ? "サーバで投稿が許可されていません。" + : "Posting not allowed by server."); +#else slrn_error ("Posting not allowed by server"); +#endif return; } @@ -2589,8 +3373,15 @@ #endif if (perform_cc) { +#ifdef KANJI + if ((0 != (perform_cc = Slrn_Auto_CC_To_Poster)) + && (-1 == (perform_cc = slrn_get_yesno_cancel (Slrn_Japanese_Messages + ? "投稿者にカーボンコピー(Cc)を送りますか" + : "Cc message to poster")))) +#else if ((0 != (perform_cc = Slrn_Auto_CC_To_Poster)) && (-1 == (perform_cc = slrn_get_yesno_cancel ("Cc message to poster")))) +#endif goto free_and_return; } @@ -2603,7 +3394,13 @@ || (0 == slrn_is_fqdn (ff + 1)) || (strlen (ff + 1) < 5)) { +#ifdef KANJI + perform_cc = slrn_get_yesno_cancel (Slrn_Japanese_Messages + ? "%s は無効のようです。それでも CC を送りますか" + : "%s appears invalid. CC anyway", cc_address); +#else perform_cc = slrn_get_yesno_cancel ("%s appears invalid. CC anyway", cc_address); +#endif if (perform_cc < 0) goto free_and_return; } @@ -2670,6 +3467,9 @@ n++; n += slrn_add_custom_headers (fp, Slrn_Followup_Custom_Headers, slrn_insert_followup_format); +#ifdef KANJI + } +#endif fputs ("\n", fp); @@ -2704,6 +3504,11 @@ l = l->next; } +#ifdef KANJI + i++; + } while (i < tagged_num); + Slrn_Current_Header = h; +#endif if (prefix_arg != 2) slrn_add_signature (fp); slrn_fclose (fp); @@ -2727,6 +3532,9 @@ if (Slrn_Use_Tmpdir) (void) slrn_delete_file (file); free_and_return: +#ifdef KANJI + ; +#endif #if SLRN_HAS_SLANG if (free_cc_string && (cc_address != NULL)) SLang_free_slstring (cc_address); @@ -2763,8 +3571,15 @@ return; #endif +#ifdef KANJI + if (Slrn_User_Wants_Confirmation + && (slrn_get_yesno_cancel (Slrn_Japanese_Messages ? + "本当に supersede しますか" : + "Are you sure you want to supersede") <= 0)) +#else if (Slrn_User_Wants_Confirmation && (slrn_get_yesno_cancel ("Are you sure you want to supersede") <= 0)) +#endif return; from = slrn_extract_header ("From: ", 6); @@ -2773,7 +3588,13 @@ sprintf (me, "%s@%s", Slrn_User_Info.username, Slrn_User_Info.hostname); if (slrn_case_strcmp ((unsigned char *) from, (unsigned char *) me)) { +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages + ? "不可: 名前 %s が %s と異なる" + : "Failed: Your name: '%s' is not '%s'", me, from); +#else slrn_error ("Failed: Your name: '%s' is not '%s'", me, from); +#endif return; } @@ -2945,7 +3766,13 @@ if (h == NULL) { +#ifdef KANJI + slrn_message (Slrn_Japanese_Messages + ? "前に未読記事はありません。" + : "No previous unread articles."); +#else slrn_message ("No previous unread articles."); +#endif return 0; } @@ -2989,7 +3816,13 @@ if (h == NULL) { +#ifdef KANJI + slrn_message (Slrn_Japanese_Messages + ? "次の未読記事はありません" + : "No following unread articles."); +#else slrn_message ("No following unread articles."); +#endif return 0; } @@ -3025,7 +3858,13 @@ ch1 = SLang_Last_Key_Char; if (ch1 == 27) ch1 = 'n'; +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "次の未読記事はありません。%s を押すと次のグループへ。" + : "No following unread articles. Press %s for next group.", +#else slrn_message_now ("No following unread articles. Press %s for next group.", +#endif map_char_to_string (ch1)); ch = SLang_getkey (); @@ -3110,7 +3949,13 @@ if (l == NULL) { +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages + ? "このサブジェクトの記事はもうありません。" + : "No more articles on that subject."); +#else slrn_error ("No more articles on that subject."); +#endif l = Same_Subject_Start_Header; Same_Subject_Start_Header = NULL; } @@ -3168,6 +4013,11 @@ static int write_article_lines (Slrn_Article_Type *a, FILE *fp) { +#ifdef KANJI + if (EOF == fputs (Slrn_Article_Buf.buf, fp)) { + return -1; + } +#else Slrn_Article_Line_Type *l; if (a == NULL) @@ -3193,6 +4043,7 @@ } l = next; } +#endif return 0; } @@ -3204,6 +4055,9 @@ if (Slrn_Current_Header == NULL) return -1; +#ifdef KANJI + if (Header_Showing != Slrn_Current_Header) +#endif if (read_article (Slrn_Current_Header, Slrn_Del_Article_Upon_Read, 0) < 0) return -1; @@ -3233,6 +4087,7 @@ { char *from; time_t now; +#ifndef KANJI Slrn_Article_Line_Type *l; int is_wrapped; @@ -3240,6 +4095,10 @@ is_wrapped = Slrn_Current_Article->is_wrapped; if (is_wrapped) unwrap_article (); +#else + if ((Header_Showing != Slrn_Current_Header) && + read_article (h, Slrn_Del_Article_Upon_Read, 0) < 0) return -1; +#endif from = slrn_extract_header ("From: ", 6); if (from != NULL) from = parse_from (from); @@ -3248,6 +4107,20 @@ time (&now); fprintf (fp, "From %s %s", from, ctime(&now)); +#ifdef KANJI + from = Slrn_Article_Buf.buf; + while(*from != '\0') { + if (*from == 'F' + && !strncmp("From", from, 4) + && (unsigned char)from[4] <= ' ') { + putc('>' ,fp); + } + do { + putc(*from, fp); + } while(*from++ != '\n'); + } + fputs ("\n\n", fp); +#else l = Slrn_Current_Article->lines; while (l != NULL) { @@ -3265,6 +4138,7 @@ fputs ("\n\n", fp); if (is_wrapped) wrap_article (); +#endif return 0; } @@ -3285,7 +4159,13 @@ if (Num_Tag_List.len) { +#ifdef KANJI + save_tagged = slrn_get_yesno_cancel (Slrn_Japanese_Messages + ? "タグ付けした記事をセーブしますか" + : "Save tagged articles"); +#else save_tagged = slrn_get_yesno_cancel ("Save tagged articles"); +#endif if (save_tagged < 0) return NULL; } @@ -3293,7 +4173,13 @@ && (Slrn_Current_Header->child != NULL) && (Slrn_Current_Header->child->flags & HEADER_HIDDEN)) { +#ifdef KANJI + save_thread = slrn_get_yesno_cancel (Slrn_Japanese_Messages + ? "このスレッドをセーブしますか" + : "Save this thread"); +#else save_thread = slrn_get_yesno_cancel ("Save this thread"); +#endif if (save_thread == -1) return NULL; } @@ -3404,7 +4290,13 @@ static void save_article (void) /*{{{*/ { +#ifdef KANJI + (void) save_article_to_file (Slrn_Save_Directory, Slrn_Japanese_Messages + ? "ファイルに保存しますか(^Gで中止)" + : "Save to file (^G aborts)"); +#else (void) save_article_to_file (Slrn_Save_Directory, "Save to file (^G aborts)"); +#endif } /*}}}*/ @@ -3495,11 +4387,23 @@ } else *Output_Filename = 0; /* force it to use this directory */ +#ifdef KANJI + file = save_article_to_file(uu_dir, Slrn_Japanese_Messages + ? "ファイル名(^Gで中止)" + : "Filename (^G aborts)"); +#else file = save_article_to_file(uu_dir, "Filename (^G aborts)"); +#endif if (file == NULL) return; +#ifdef KANJI + if (1 == slrn_get_yesno (1, Slrn_Japanese_Messages + ? "%s をデコードしますか" + : "decode %s", file)) +#else if (1 == slrn_get_yesno (1, "decode %s", file)) +#endif { # if SLRN_HAS_UUDEVIEW (void) do_slrn_uudeview (uu_dir, file); @@ -3509,7 +4413,13 @@ if (SLang_Error == 0) { +#ifdef KANJI + if (1 == slrn_get_yesno (1, Slrn_Japanese_Messages + ? "%s を消しますか" + : "Delete %s", file)) +#else if (1 == slrn_get_yesno (1, "Delete %s", file)) +#endif { if (-1 == slrn_delete_file (file)) slrn_error ("Unable to delete %s", file); @@ -3581,22 +4491,46 @@ { Slrn_Print_Type *p; Slrn_Article_Line_Type *l; +#ifdef KANJI + int is_wrapped, len; +#endif if (-1 == select_article (1)) return -1; +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "記事を印刷中..." + : "Printing article..."); +#else slrn_message_now ("Printing article..."); +#endif p = slrn_open_printer (); if (p == NULL) return -1; +#ifdef KANJI + is_wrapped = Slrn_Current_Article->is_wrapped; + if (is_wrapped) unwrap_article (); +#endif l = Slrn_Current_Article->lines; while (l != NULL) { +#ifdef KANJI + char *buf = (char *)Slrn_Tmp_Str; + strcpy(buf, l->buf); + if (Slrn_Editor_Code != EUC) { + slrn_conv_string(buf, Slrn_Editor_Code); + } + len = strlen(buf); + buf[len] = '\n'; + if (-1 == slrn_write_to_printer (p, buf, len + 1)) +#else if ((-1 == slrn_write_to_printer (p, l->buf, strlen (l->buf))) || (-1 == slrn_write_to_printer (p, "\n", 1))) +#endif { slrn_close_printer (p); return -1; @@ -3608,7 +4542,14 @@ if (-1 == slrn_close_printer (p)) return -1; +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "記事を印刷中...終了" + : "Printing article...done"); + if (is_wrapped) wrap_article (); +#else slrn_message_now ("Printing article...done"); +#endif return 0; } @@ -3617,7 +4558,13 @@ static void print_article_cmd (void) /*{{{*/ { if (Slrn_User_Wants_Confirmation +#ifdef KANJI + && (slrn_get_yesno_cancel (Slrn_Japanese_Messages + ? "本当に記事を印刷しますか" + : "Are you sure you want to print the article") <= 0)) +#else && (slrn_get_yesno_cancel ("Are you sure you want to print the article") <= 0)) +#endif return; (void) print_article (); @@ -4595,7 +5542,13 @@ if (rparent == h) { /* self referencing!!! */ +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages ? + "記事 %d の Reference がループしている!" : + "Article %d is part of reference loop!", h->number); +#else slrn_error ("Article %d is part of reference loop!", h->number); +#endif } else { @@ -4686,6 +5639,11 @@ static void mark_spot (void) /*{{{*/ { Mark_Header = Slrn_Current_Header; +#ifdef KANJI + if (Slrn_Japanese_Messages) + slrn_message ("マークを設定しました。"); + else +#endif slrn_message ("Mark set."); } @@ -4696,6 +5654,11 @@ { if (Mark_Header == NULL) { +#ifdef KANJI + if (Slrn_Japanese_Messages) + slrn_error ("マークが設定されていません。"); + else +#endif slrn_error ("Mark not set."); return; } @@ -4716,6 +5679,13 @@ Slrn_Header_Type *l; char prompt[80]; +#ifdef KANJI + if (Slrn_Japanese_Messages) + sprintf (prompt, "%s の%s検索", + type == 's' ? "Subject" : "Author", + dir > 0 ? "前方" : "後方"); + else +#endif sprintf (prompt, "%s Search %s", type == 's' ? "Subject" : "Author", dir > 0 ? "Forward" : "Backward"); @@ -4749,7 +5719,13 @@ if (l == NULL) { +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages + ? "見つかりません。" + : "Not found."); +#else slrn_error ("Not found."); +#endif return; } @@ -4817,7 +5793,11 @@ if ((root == NULL) || (root->num_used == MAX_DKILLS)) { Kill_List_Type *k; +#ifdef KANJI + k = (Kill_List_Type *)slrn_malloc(sizeof (Kill_List_Type), 0, 1); +#else k = (Kill_List_Type *) SLMALLOC (sizeof (Kill_List_Type)); +#endif if (k == NULL) return root; k->num_used = 0; k->next = root; @@ -4951,7 +5931,13 @@ percent = (100 * num) / Total_Num_Headers; if (percent >= last_percent + delta_percent) { +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "スコアを付けた記事: %2d%%, 削除: %u, 高スコア: %u, 低スコア: %u" + : "Scoring articles: %2d%%, Killed: %u, High: %u, Low: %u", +#else slrn_message_now ("Scoring articles: %2d%%, Killed: %u, High: %u, Low: %u", +#endif percent, Number_Score_Killed, Number_High_Scored, Number_Low_Scored); last_percent = percent; } @@ -4996,7 +5982,13 @@ if (-1 == slrn_edit_score (h, Slrn_Current_Group_Name)) return; +#ifdef KANJI + if (1 != slrn_get_yesno_cancel (Slrn_Japanese_Messages + ? "今スコアファイルを適用しますか" + : "Apply scorefile now")) +#else if (1 != slrn_get_yesno_cancel ("Apply scorefile now")) +#endif return; slrn_close_score (); @@ -5019,14 +6011,88 @@ /*{{{ get headers from server and process_xover */ +#ifdef KANJI +static void copy_subject_header(Slrn_Header_Type *h, char *str, int len) +{ + char *buf, *from; + int new_len = strlen(str), i; + + if (len < new_len) { + i = (h->xref - h->from) + strlen(h->xref) + 1; + buf = slrn_realloc (h->subject, new_len + i + 1, 1); + if (buf == NULL) { + return; + } + while (i > 0) { + buf[new_len + i] = buf[len + i]; + i--; + } + from = buf + new_len + 1; + i = from - h->from; + h->date += i; + h->msgid += i; + h->refs += i; + h->xref += i; + h->from = from; + h->subject = buf; + } + if (Slrn_Detect_SJIS && h->charset == SHIFTJIS) { + exchange_kana((unsigned char *)h->subject, (unsigned char *)str); + } else { + strcpy(h->subject, str); + } +} +#endif static Slrn_Header_Type *process_xover (Slrn_XOver_Type *xov) { Slrn_Header_Type *h; +#ifdef KANJI + Charset_Type charset; + int len, ret; +#endif h = (Slrn_Header_Type *) slrn_safe_malloc (sizeof (Slrn_Header_Type)); slrn_map_xover_to_header (xov, h); +#ifdef KANJI + h->charset = Slrn_Default_Charset; + len = strlen(h->subject); +#if SLRN_HAS_MIME + if (Slrn_Use_Mime) { + charset = slrn_rfc1522_decode_string (h->from); + if (charset > USASCII) { + h->charset = charset; + } + charset = slrn_rfc1522_decode_string (h->subject); + if (charset > USASCII) { + h->charset = charset; + } + } +#endif + + if (h->charset >= ISO2022JP && h->charset < UNKNOWN_CHARSET) { + if (slrn_recover_jis(Slrn_Tmp_Str, (unsigned char *)h->subject, SLRN_TMP_STR_LEN) < 5) { + copy_subject_header(h, (char *)Slrn_Tmp_Str, len); + len = strlen(h->from); + ret = fixup_from_line(Slrn_Tmp_Str, h->from, SLRN_TMP_STR_LEN); + if (ret > 4) { + h->charset = ISO88591; + } else if (ret > 0) { + strncpy(h->from, (char *)Slrn_Tmp_Str, len); + } + } else { + h->charset = ISO88591; + } + } +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + if (!Slang_Use_ISO8859) +#endif + if (h->charset < ISO2022JP) { /* 8bit 文字を '?' にする */ + convert_unprintable((unsigned char *)h->subject); + convert_unprintable((unsigned char *)h->from); + } +#else #if SLRN_HAS_MIME if (Slrn_Use_Mime) { @@ -5034,6 +6100,7 @@ slrn_rfc1522_decode_string (h->from); } #endif +#endif if ((Slrn_Score_After_XOver == 0) && Perform_Scoring) { @@ -5127,12 +6194,26 @@ { if (scoring) { +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "%s: 受け取ったヘッダ: %3d/%-3d, 削除: %u, 高スコア: %u, 低スコア: %u" + : "%s: headers received: %3d/%-3d, Killed: %u, High: %u, Low: %u", + Slrn_Current_Group_Name, num, total, + Number_Score_Killed, Number_High_Scored, Number_Low_Scored); +#else slrn_message_now ("%s: headers received: %3d/%-3d, Killed: %u, High: %u, Low: %u", Slrn_Current_Group_Name, num, total, Number_Score_Killed, Number_High_Scored, Number_Low_Scored); +#endif } else +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "%s: 受け取ったヘッダ: %2d/%d" + : "%s: headers Received: %2d/%d", Slrn_Current_Group_Name, num, total); +#else slrn_message_now ("%s: headers received: %2d/%d", Slrn_Current_Group_Name, num, total); +#endif } if (h == NULL) continue; @@ -5265,14 +6346,26 @@ if (query_server == 0) return -1; +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "サーバから %s を探索中..." + : "Finding %s from server...", msgid); +#else slrn_message_now ("Finding %s from server...", msgid); +#endif /* Try reading it from the server */ if (-1 == slrn_xover_for_msgid (msgid, &xov)) { if (no_error_no_thread == 0) { +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages + ? "記事 %s はありません。" + : "Article %s not available.", msgid); +#else slrn_error ("Article %s not available.", msgid); +#endif return -1; } return 1; @@ -5304,7 +6397,13 @@ char buf[NNTP_BUFFER_SIZE]; int id_array[1000]; int num_ids, i, id; +#ifdef KANJI + char *fmt = Slrn_Japanese_Messages + ? "サーバから子記事を探索中...[%c]" + : "Finding children from server...[%c]"; +#else char *fmt = "Finding children from server...[%c]"; +#endif char *meter_chars = "|/-\\"; static unsigned int last_meter_char; @@ -5312,7 +6411,13 @@ Slrn_Server_Min, Slrn_Server_Max, parent->msgid)) { +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages + ? "サーバでこの機能はサポートされていません。" + : "Your server does not provide support for this feature."); +#else slrn_error ("Your server does not provide support for this feature."); +#endif return -1; } @@ -5475,7 +6580,13 @@ if ((r0 < rmin) || (r1 == rmin)) { if (no_error_no_thread) break; +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages + ? "親記事への参照がありません。" + : "Article has no parent reference."); +#else slrn_error ("Article has no parent reference."); +#endif return; } @@ -5494,7 +6605,9 @@ } slrn_uncollapse_this_thread (Slrn_Current_Header, 1); +#ifndef KANJI slrn_chmap_fix_headers (); /* We didn't decode parent headers */ +#endif } /*}}}*/ @@ -5524,7 +6637,13 @@ { char msgid[256]; *msgid = 0; +#ifdef KANJI + if (slrn_read_input (Slrn_Japanese_Messages ? + "Message-ID を入力" : + "Enter Message-Id", NULL, msgid, 1, 0) <= 0) return; +#else if (slrn_read_input ("Enter Message-Id", NULL, msgid, 1, 0) <= 0) return; +#endif (void) slrn_locate_header_by_msgid (msgid, 1); } @@ -5957,6 +7076,9 @@ } Slrn_First_Header = Headers = Slrn_Current_Header = NULL; +#ifdef KANJI + Slrn_Article_Buf.header = NULL; +#endif SLMEMSET ((char *) &Slrn_Header_Window, 0, sizeof (SLscroll_Window_Type)); Total_Num_Headers = 0; @@ -6158,10 +7280,22 @@ slrn_update_screen (); +#ifdef KANJI + if (slrn_get_yesno (0, Slrn_Japanese_Messages + ? "本当にこの記事をキャンセルしますか" + : "Are you sure that you want to cancel this article") <= 0) +#else if (slrn_get_yesno (0, "Are you sure that you want to cancel this article") <= 0) +#endif return; +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "キャンセル中..." + : "Cancelling..."); +#else slrn_message_now ("Cancelling..."); +#endif /* TO cancel, we post a cancel message with a 'control' header. First, check to * see if this is really the owner of the message. @@ -6174,7 +7308,13 @@ if (slrn_case_strcmp ((unsigned char *) from, (unsigned char *) me)) { +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages + ? "不可: 名前 %s が %s と異なる" + : "Failed: Your name: '%s' is not '%s'", me, from); +#else slrn_error ("Failed: Your name: '%s' is not '%s'", me, from); +#endif return; } @@ -6204,7 +7344,13 @@ if (0 == Slrn_Post_Obj->po_end ()) { +#ifdef KANJI + slrn_message (Slrn_Japanese_Messages + ? "終了。" + : "Done."); +#else slrn_message ("Done."); +#endif } } @@ -6339,6 +7485,378 @@ #endif /*}}}*/ +#ifdef KANJI +#ifdef SLRN_HAS_MIME +static void toggle_mime (void) +{ + Slrn_Use_Mime = !Slrn_Use_Mime; + + Header_Showing = NULL; + select_article (1); + slrn_redraw(); +} + +static int Slrn_Mime_Total; + +#define HEADER_SIZE 40 +static void retrieve_header() +{ + Slrn_Article_Line_Type *l = Slrn_Current_Article->lines, *orig, *sep; + char *b; + int i; + + while (l != NULL && (l->flags & HEADER_LINE)) { /* skip header */ + l = l->next; + } + sep = l; + while (l != NULL && *l->buf == '\0') { /* skip blank line */ + l->flags |= HIDDEN_LINE; /* marked as delete later */ + l = l->next; + } + while (l != NULL && *l->buf != '\0') { + b = l->buf; + for (i = 0; i < HEADER_SIZE; i++) { + if (b[i] == ':') { + break; + } else if (b[i] <= ' ' || (b[i] & 0x80)) { + i = HEADER_SIZE; + } + } + if (i >= HEADER_SIZE) { /* not a header line */ + break; + } + orig = slrn_extract_header_line(Slrn_Current_Article, b, i + 2); + if (orig != NULL) { /* exchange orig and new header */ + l->buf = orig->buf; + orig->buf = b; + l->flags |= HIDDEN_LINE; /* marked as delete later */ + } + l = l->next; + } + while (sep != NULL && (sep->flags & HIDDEN_LINE || *sep->buf != '\0')) { + l = sep->prev; + if (sep->flags & HIDDEN_LINE) { /* delete hidden line */ + l->next = sep->next; + sep->next->prev = l; + SLFREE(sep->buf); + SLFREE(sep); + } else { + sep->flags |= HEADER_LINE; /* marked as a header */ + } + sep = sep->next; + } +} + +static int check_partial_article(char *id) +{ + char *b; + int id_found = 0, number = 0, total = 0; + + b = slrn_art_extract_header (Slrn_Current_Article, "Content-Type: ", 14); + if (b == NULL) { + return (0); + } + /* ensure mime partial article */ + b = slrn_strchr(b, '/'); + if (slrn_case_strncmp((unsigned char *)b + 1, + (unsigned char *)"partial;", 7) != 0) { + return (0); + } + while (*b != '\0' || ((b = slrn_strchr(b, ';')) != NULL)) { + b = slrn_skip_whitespace(b + 1); + if (slrn_case_strncmp((unsigned char *)b, + (unsigned char *)"id=", 3) == 0) { + b += 3; + if (*b == '"') { + b++; + } + if (strncmp(b, id, strlen(id)) != 0) { /* id not identical */ + return (0); + } + id_found = 1; + } else if (slrn_case_strncmp((unsigned char *)b, + (unsigned char *)"number=", 7) == 0) { + b += 7; + number = atoi(b); + } else if (slrn_case_strncmp((unsigned char *)b, + (unsigned char *)"total=", 6) == 0) { + b += 6; + total = atoi(b); + if (Slrn_Mime_Total != 0 && Slrn_Mime_Total != total) { + return (0); /* total is not identical */ + } + } + } + if (id_found) { + if (Slrn_Mime_Total == 0) { + if (total != 0) { + Slrn_Mime_Total = total; + } + } else if (number > Slrn_Mime_Total) { + return (0); + } + return (number); + } + return (0); +} + +/* concatenate articles in order of pline[i] */ +/* returns 0 if success, otherwise returns the number of missing message */ +static int concat_article(Slrn_Article_Line_Type *pline[]) +{ + Slrn_Article_Line_Type *line; + int i; + + for (i = 0; i < Slrn_Mime_Total; i++) { + if (pline[i] == NULL) { + return (i + 1); /* return missing number */ + } + if (i == 0) { + Slrn_Current_Article->lines = line = pline[0]; + } else { + while (line != NULL && line->next != NULL) { + line = line->next; /* search last line of previous article */ + } + line->next = pline[i]; + pline[i]->prev = line; + line = line->next; + while (line != NULL) { /* these lines are deleted after */ + line->flags |= HIDDEN_LINE; + if (*line->buf == '\0') { + break; + } + line = line->next; + } + } + pline[i] = NULL; /* mark as concatenated */ + } + return (0); +} + +#define MAX_PARTIAL_MESSAGE 64 +static void free_and_mark_articles(Slrn_Article_Line_Type *pline[], Slrn_Header_Type *pheader[], int mark_header) +{ + int i; + + for (i = 0; i < MAX_PARTIAL_MESSAGE; i++) { + if (pline[i] != NULL) { + Slrn_Current_Article->lines = pline[i]; + free_article(); + } + if (mark_header && i < Slrn_Mime_Total) { + delete_header(pheader[i]); /* marks as read on only retrieved articles */ + } + } +} + +static int is_all_collected(Slrn_Article_Line_Type *pline[]) +{ + int i; + + if (Slrn_Mime_Total > 0) { + for (i = 0; i < Slrn_Mime_Total; i++) { + if (pline[i] == NULL) { + return (0); + } + } + return (1); + } + return (0); +} + +/* returns 0 if partial messages are successfully retrieved */ +int slrn_mime_retrieve_partial_messages(char *id) +{ + Slrn_Article_Line_Type *partial_line[MAX_PARTIAL_MESSAGE]; + Slrn_Header_Type *partial_header[MAX_PARTIAL_MESSAGE], *orig_h; + unsigned int i; + int number; + + orig_h = Slrn_Current_Header; + if (Num_Tag_List.len && (Slrn_Current_Header->flags & HEADER_NTAGGED)) { + if (slrn_get_yesno (0, "Retrieve MIME partial message from tagged") == 0) { + return 1; + } + Slrn_Current_Header = Num_Tag_List.headers[0]; + } else if ((Slrn_Current_Header->child == NULL) + /* || !(Slrn_Current_Header->child->flags & HEADER_HIDDEN) */ + || slrn_get_yesno (0, "Retrieve MIME partial message from this thread") == 0) { + return 1; + } + + /* initialization */ + Slrn_Mime_Total = 0; + for (i = 0; i < MAX_PARTIAL_MESSAGE; i++) { + partial_line[i] = NULL; + } + i = 0; + + do { + if (-1 == read_article (Slrn_Current_Header, 0, 0)) { + return 1; + } + number = check_partial_article(id); + if (number > 0) { + partial_line[number - 1] = Slrn_Current_Article->lines; + partial_header[number - 1] = Slrn_Current_Header; + } + + Slrn_Current_Article->lines = NULL; + Header_Showing = NULL; + + if (is_all_collected(partial_line)) { + Slrn_Current_Header = NULL; + } else if (Num_Tag_List.len) { + i++; + if (i < Num_Tag_List.len) { + Slrn_Current_Header = Num_Tag_List.headers[i]; + } else { + Slrn_Current_Header = NULL; + } + } else { + Slrn_Current_Header = Slrn_Current_Header->next; + } + } while ((Slrn_Current_Header != NULL) + && (Num_Tag_List.len || Slrn_Current_Header->parent != NULL)); + + Slrn_Current_Header = orig_h; + + number = concat_article(partial_line); + + if (Slrn_Mime_Total == 0) { + slrn_error ("Total number of MIME partial messages not found."); + } else if (number) { + slrn_error ("MIME partial message #%d is lacking.", number); + } else { /* no error */ + Slrn_Current_Article->cline = Slrn_Current_Article->lines; + free_and_mark_articles(partial_line, partial_header, 1); + retrieve_header(); + init_article_window_struct (); + return 0; + } + + /* recover error */ + if (Slrn_Current_Article->lines != NULL) { + free_article(); + } + free_and_mark_articles(partial_line, partial_header, 0); + (void)read_article (Slrn_Current_Header, Slrn_Del_Article_Upon_Read, 0); + return 1; +} +#endif + +/*{{{ click URL */ +int Slrn_Click_On_Url = 1; + +static int click_on_url (int r, int c) +{ + int old_row, old_col; + old_row = SLsmg_get_row(); + old_col = SLsmg_get_column(); + + SLsmg_gotorc (r - 1, c - 1); + if ((unsigned)SLsmg_char_at () >> 8 == URL_COLOR) + { + /* the user has clicked on something painted "URL color" */ + int row = (r - 2) - Header_Window_Nrows; /* counting from 1 */ + int col = c - 1 + Article_Window_HScroll; + int pos; + Slrn_Article_Line_Type *l; + char *p, *str; + + /* Find the corresponding line from the article */ + l = (Slrn_Article_Line_Type*)Slrn_Article_Window.top_window_line; + while (--row) + { + do { + l = l->next; + if (NULL == l) return 0; /* didn't find URL */ + } while (l->flags & HIDDEN_LINE); + } + +#if 0 + /* This is broken if there are tabs (or other wide characters) around */ + p = l->buf + c - 1 + HScroll; /* ptr to character clicked on */ +#else + pos = 0; + p = l->buf; + while (pos < col) + { +#if 0 + if (*p == '\0') break; + pos += slrn_char_display_width (pos, *p++); +#else + int ch; + ch = *p++; + if (ch == '\0') { + break; + } + if ((ch == '\t') && (SLsmg_Tab_Width > 0)) { + pos += SLsmg_Tab_Width; + pos -= pos % SLsmg_Tab_Width; + } else { + pos++; + if (ch < ' ') { + pos++; + } + } +#endif + } + if (pos > col) p--; +#endif + + /* now repeat the same scan for URLs we used when colouring */ + str = l->buf; + for (;;) { + char *p_url; + unsigned int len; + p_url = find_url (str, &len); + if (NULL == p_url) break; + if (len) + { + if (p_url <= p && p < p_url + len) + { + /* found it */ + char temp; + int color; + slrn_push_suspension (0); + /* flash URL */ + color = URL_PRESS_COLOR; +#if 0 + /* This is broken if there are tabs (or other wide characters) around */ + col = p_url - l->buf - HScroll; +#else + /* !HACK! This is broken if there are 'wide' chars in the URL before the point clicked */ + col = c - 1 - (p - p_url); +#endif + while (1) + { + slrn_set_color (color); + SLsmg_gotorc (r - 1, col); + smg_write_nchars (p_url, len); + SLsmg_gotorc (old_row, old_col); + slrn_smg_refresh (); + if (color == URL_COLOR) break; + (void) SLang_input_pending (1); /* 1/10 sec */ + color = URL_COLOR; + } + slrn_set_color (0); + slrn_pop_suspension (); + temp = p_url[len]; + p_url[len] = '\0'; /* yuck */ + launch_url(p_url); + p_url[len] = temp; /* unyuck */ + return 1; /* URL found */ + } + } + str = p_url + len; + } + } + return 0; /* didn't find URL */ +} + +/*}}}*/ +#endif /*{{{ mouse commands */ /* actions for different regions: @@ -6385,6 +7903,9 @@ if (r - 2 > Header_Window_Nrows) { +#ifdef KANJI + if (Slrn_Click_On_Url && click_on_url (r, c)) return; +#endif if (NULL != normal_region) (*normal_region) (); return; } @@ -6532,6 +8053,9 @@ A_KEY("subject_search_forward", subject_search_forward), A_KEY("suspend", art_suspend_cmd), A_KEY("toggle_headers", toggle_headers), +#ifdef KANJI + A_KEY("toggle_mime", toggle_mime), +#endif A_KEY("toggle_quotes", toggle_quotes), A_KEY("undelete", undelete_header_cmd), A_KEY("up", header_up), @@ -6575,7 +8099,9 @@ Art_Mode_Cap.keymap = Slrn_Article_Keymap; Slrn_Article_Keymap->functions = Art_Functions; +#ifndef KANJI Art_Functions_Ptr = Art_Functions; +#endif numbuf[1] = 0; @@ -6590,6 +8116,9 @@ SLkm_define_key (numbuf, (FVOID_STAR) grouplens_rate_article, Slrn_Article_Keymap); #endif +#ifdef KANJI + SLkm_define_key ("\033m", (FVOID_STAR) toggle_mime, Slrn_Article_Keymap); +#endif SLkm_define_key ("\033l", (FVOID_STAR) locate_header_by_msgid, Slrn_Article_Keymap); SLkm_define_key ("\0331", (FVOID_STAR) slrn_digit_arg, Slrn_Article_Keymap); SLkm_define_key ("\0332", (FVOID_STAR) slrn_digit_arg, Slrn_Article_Keymap); @@ -6787,10 +8316,12 @@ static void init_graphic_chars (void) { +#ifndef KANJI #ifndef IBMPC_SYSTEM if (SLtt_Has_Alt_Charset == 0) Slrn_Simulate_Graphic_Chars = 1; #endif +#endif if (Slrn_Simulate_Graphic_Chars) { @@ -6823,7 +8354,11 @@ * that last 'all' UNREAD articles. * Otherwise, fetch ALL UNREAD headers from the server. */ +#ifndef KANJI int slrn_select_article_mode (Slrn_Group_Type *g, int all, int score) /*{{{*/ +#else +int slrn_select_article_mode (Slrn_Group_Type *g, int all, int score, int direc) +#endif { int min, max; int smin, smax; @@ -6855,6 +8390,11 @@ if (SLang_Error) return -1; #endif +#ifdef KANJI + if (Slrn_Mime_Display_Charset != NULL) { + Slrn_Default_Charset = slrn_find_charset(Slrn_Mime_Display_Charset); + } +#endif if (score && (1 == slrn_open_score (Slrn_Current_Group_Name))) Perform_Scoring = 1; @@ -6875,6 +8415,49 @@ if (status != -1) mark_ranges_read (r); } +#ifdef KANJI + else if (direc) { + int total = -all, unread; + + unread = total; + min = max = Slrn_Server_Min; + while (unread > 0 && max < Slrn_Server_Max) { + all = total; + if (min == Slrn_Server_Min + || (r != NULL && r->next != NULL && r->next->min <= min)) { + while(r != NULL) { + /* r->max + 1 >= min であるような r をさがす */ + if (r->max + 1 >= min) { + min = r->max + 1; + break; + } + r = r->next; + } + } + if (r == NULL || r->next == NULL) { + max = Slrn_Server_Max; + } else { + max = r->next->min - 1; + } + if (max - min + 1 >= unread) { + max = min + unread - 1; + } + if (min > max) { + break; + } + status = get_headers (min, max, &all); + + if (status == -1) + break; + + if (status == 0) { + Slrn_Groups_Dirty = 1; + } + unread -= status; + min = max + 1; + } + } +#endif else { if ((all < 0) && (r != NULL)) @@ -6984,9 +8567,19 @@ if ((status == -1) || SLKeyBoard_Quit) { if (SLang_Error == USER_BREAK) +#ifdef KANJI + slrn_error_now (0, Slrn_Japanese_Messages ? + "グループの転送を中止しました。" : + "Group transfer aborted."); + else + slrn_error_now (0, Slrn_Japanese_Messages ? + "サーバの読み出しに失敗しました。" : + "Server read failed."); +#else slrn_error_now (0, "Group transfer aborted."); else slrn_error_now (0, "Server read failed."); +#endif /* This means that we cannot update ranges for this group because * the user aborted and update_ranges assumes that all articles @@ -7003,9 +8596,19 @@ { slrn_close_score (); if (Number_Killed) +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages + ? "未読記事はありません。(%d 削除)" + : "No unread articles found. (%d killed)", Number_Killed); + else + slrn_error (Slrn_Japanese_Messages + ? "未読記事はありません。" + : "No unread articles found."); +#else slrn_error ("No unread articles found. (%d killed)", Number_Killed); else slrn_error ("No unread articles found."); +#endif free_kill_lists_and_update (); Slrn_Current_Group_Name = NULL; @@ -7020,7 +8623,9 @@ extract_real_names (); +#ifndef KANJI slrn_chmap_fix_headers (); +#endif slrn_push_mode (&Art_Mode_Cap); @@ -7069,7 +8674,13 @@ } else #endif +#ifdef KANJI + slrn_message (Slrn_Japanese_Messages + ? "削除数: %u, 高スコア: %u, 低スコア: %u" + : "Num Killed: %u, Num High: %u, Num Low: %u", +#else slrn_message ("Num Killed: %u, Num High: %u, Num Low: %u", +#endif Number_Score_Killed, Number_High_Scored, Number_Low_Scored); } @@ -7129,6 +8740,7 @@ /* Wrappers around SLsmg routines. */ +#ifndef KANJI static void smg_write_nchars (char *s, unsigned int n) { unsigned char *s1, *smax; @@ -7164,6 +8776,7 @@ { smg_write_nchars (&c, 1); } +#endif #if SLRN_HAS_EMPHASIZED_TEXT static void smg_write_emphasized_text (char *str, int color0) @@ -7379,7 +8992,7 @@ { unsigned char buf[2]; -#if !defined(IBMPC_SYSTEM) +#if defined(KANJI) || !defined(IBMPC_SYSTEM) if (Graphic_Chars_Mode == 0) { smg_write_string ((char *) h->tree); @@ -7414,7 +9027,7 @@ } smg_write_nchars ((char *) buf, 2); -#if !defined(IBMPC_SYSTEM) +#if defined(KANJI) || !defined(IBMPC_SYSTEM) if (Graphic_Chars_Mode == ALT_CHAR_SET_MODE) SLsmg_set_char_set (0); #endif } @@ -7468,9 +9081,19 @@ if ((Header_Window_Nrows == 0) && (next_parent != NULL) && (next_parent->subject != NULL)) +#ifdef KANJI + slrn_message (Slrn_Japanese_Messages + ? "スレッドの終わり。次: %s" + : "End of Thread. Next: %s", next_parent->subject); + else + slrn_message (Slrn_Japanese_Messages + ? "スレッドの終わり" + : "End of Thread."); +#else slrn_message ("End of Thread. Next: %s", next_parent->subject); else slrn_message ("End of Thread."); +#endif return 0; } @@ -7482,7 +9105,13 @@ * sisters except that one can have a fake parent. If this is the * case, we are at the end of a subthread. */ +#ifdef KANJI + slrn_message (Slrn_Japanese_Messages + ? "サブスレッドの終わり" + : "End of Sub-Thread"); +#else slrn_message ("End of Sub-Thread"); +#endif return 0; } @@ -7649,6 +9278,11 @@ if (fmt == NULL) fmt = "%F%-5S%G%-5l:[%12r]%t%s"; +#ifdef KANJI +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + Slang_Current_Charset = h->charset; +#endif +#endif while ((ch = *fmt) != 0) { char *s; @@ -7787,6 +9421,15 @@ else len = field_len; } +#ifdef KANJI + else if (row + 1 == SLtt_Screen_Rows) + { + field_len = SLtt_Screen_Cols - SLsmg_get_column() - 1; + if (len > field_len) { + len = field_len; + } + } +#endif if (right_justify) { while (spaces) @@ -7809,6 +9452,42 @@ return 0; } +#ifdef KANJI +static void art_write_string (char *str, int color, int use_emph_mask, Charset_Type charset) +{ + char *p_url; + unsigned int len; + +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + if (Slang_Use_ISO8859) { + Slang_Current_Charset = charset; + } +#endif + if (Slrn_Click_On_Url && (p_url = find_url (str, &len)) != NULL) { + do { + if (p_url != str) { + slrn_set_color (color); + smg_write_nchars (str, p_url - str); + } + if (len) { + slrn_set_color (URL_COLOR); + smg_write_nchars (p_url, len); + str = p_url + len; + } + } while ((p_url = find_url (str, &len)) != NULL); + use_emph_mask = 0; + } + +#if SLRN_HAS_EMPHASIZED_TEXT + if (use_emph_mask) { + smg_write_emphasized_text (str, color); + return; + } +#endif + slrn_set_color (color); + smg_write_string (str); +} +#endif static void display_article_line (Slrn_Article_Line_Type *l) { char *lbuf = l->buf; @@ -7819,7 +9498,12 @@ switch (l->flags & LINE_TYPE_MASK) { case HEADER_LINE: +#ifdef KANJI + /* オリジナルではwrapされた行は空白ではじまる仮定をしてるからまずい */ + if ((l->flags & WRAPPED_LINE) == 0) +#else if ((unsigned char)*lbuf > (unsigned char) ' ') +#endif { lbuf = slrn_strchr (lbuf, ':'); if (lbuf != NULL) @@ -7853,6 +9537,11 @@ break; #endif default: +#ifdef KANJI + if (l->flags & HEADER_LINE) { + color = HEADER_COLOR; + } else +#endif color = ARTICLE_COLOR; use_emph_mask = EMPHASIZE_ARTICLE; use_rot13 = 1; @@ -7876,6 +9565,9 @@ return; } +#ifdef KANJI + art_write_string (lbuf, color, use_emph_mask, l->charset); +#else if (use_emph_mask) { #if SLRN_HAS_EMPHASIZED_TEXT @@ -7884,6 +9576,7 @@ #endif } smg_write_string (lbuf); +#endif } @@ -7969,9 +9662,29 @@ SLsmg_gotorc (height, 0); slrn_set_color (STATUS_COLOR); +#ifdef KANJI + if (Article_Window_HScroll) c0 = '<'; +#ifdef SLRN_HAS_MIME + /* MIME が有効な時はモードラインに m を入れる */ + else if (Slrn_Use_Mime) c0 = 'm'; +#endif + else c0 = ' '; + /* mode line の subjectが漢字の途中で切られないように */ + sprintf((char *)Slrn_Tmp_Str, "%c %d : %s", + c0, Header_Showing->number, Header_Showing->subject); + c0 = strlen((char *)Slrn_Tmp_Str); + if (c0 > 60) { + c0 = 60; + } +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + Slang_Current_Charset = Header_Showing->charset; +#endif + smg_write_nchars((char *)Slrn_Tmp_Str, c0); +#else if (Article_Window_HScroll) smg_write_char ('<'); else smg_write_char (' '); SLsmg_printf (" %d : ", Header_Showing->number); SLsmg_write_string (Header_Showing->subject); +#endif slrn_print_percent (height, 60, &Slrn_Article_Window); slrn_set_color (0); diff -Nru slrn-0.9.6.2.orig/src/art.h slrn-0.9.6.2/src/art.h --- slrn-0.9.6.2.orig/src/art.h Fri Dec 24 02:24:42 1999 +++ slrn-0.9.6.2/src/art.h Wed Dec 29 10:54:10 1999 @@ -20,7 +20,12 @@ #ifndef _SLRN_ART_H #define _SLRN_ART_H #ifndef SLRNPULL_CODE +#ifdef KANJI +extern int slrn_insert_followup_format_string (char *, char *); +extern int slrn_select_article_mode (Slrn_Group_Type *, int, int, int); +#else extern int slrn_select_article_mode (Slrn_Group_Type *, int, int); +#endif extern void slrn_init_article_mode (void); extern int slrn_insert_followup_format (char *, FILE *); extern SLKeyMap_List_Type *Slrn_Article_Keymap; @@ -114,6 +119,9 @@ int score; int thread_score; #endif +#ifdef KANJI + Charset_Type charset; +#endif } Slrn_Header_Type; extern Slrn_Header_Type *Slrn_First_Header; @@ -145,6 +153,9 @@ #define MAX_QUOTE_LEVELS 8 #define QUOTE_LEVEL(flags) ((flags) >> QUOTE_LEVEL_SHIFT) +#ifdef KANJI + Charset_Type charset; +#endif char *buf; } Slrn_Article_Line_Type; @@ -218,6 +229,33 @@ extern int slrn_set_header_format (unsigned int, char *); +#ifdef KANJI +extern void slrn_convert_body(Slrn_Article_Line_Type *, Slrn_Article_Line_Type *, Charset_Type); +extern Slrn_Article_Line_Type *slrn_extract_header_line (Slrn_Article_Type *, char *, unsigned int); +extern unsigned int slrn_char_display_width (unsigned int, unsigned char); +#ifndef SLANG_JVERSION +extern int kanji_pos(unsigned char *, unsigned char *); +#endif +#ifdef SLRN_HAS_MIME +extern int slrn_mime_retrieve_partial_messages(char *); +#endif +typedef struct { + Slrn_Header_Type *header; + char *buf; + int len; +} Slrn_Article_Buf_Type; +extern Slrn_Article_Buf_Type Slrn_Article_Buf; + +extern int Slrn_Gmt2local; +extern int Slrn_Click_On_Url; +typedef struct { + char *std; + int offset; +} Slrn_tm; +extern Slrn_tm Slrn_Timezone; + +extern Charset_Type Slrn_Default_Charset; +#endif extern void slrn_art_sync_article (Slrn_Article_Type *); extern int _slrn_art_unhide_quotes (Slrn_Article_Type *a); extern int _slrn_art_hide_quotes (Slrn_Article_Type *a, int level); diff -Nru slrn-0.9.6.2.orig/src/artmisc.c slrn-0.9.6.2/src/artmisc.c --- slrn-0.9.6.2.orig/src/artmisc.c Fri Dec 24 02:24:41 1999 +++ slrn-0.9.6.2/src/artmisc.c Wed Dec 29 00:11:03 1999 @@ -55,6 +55,9 @@ #include "xover.h" #include "chmap.h" #include "print.h" +#ifdef KANJI +#include "mime.h" +#endif /*}}}*/ @@ -200,7 +203,11 @@ /*}}}*/ #endif +#ifndef KANJI static int try_supercite (Slrn_Article_Line_Type *l) /*{{{*/ +#else +static void try_supercite (Slrn_Article_Line_Type *l) +#endif { Slrn_Article_Line_Type *last, *lsave; static unsigned char compiled_pattern_buf[256]; @@ -209,7 +216,9 @@ int count; char name[32]; unsigned int len; +#ifndef KANJI int ret; +#endif re.pat = (unsigned char *) Super_Cite_Regexp; re.buf = compiled_pattern_buf; @@ -220,13 +229,19 @@ while ((l != NULL) && (*l->buf != 0)) l = l->next; if ((*compiled_pattern_buf == 0) && SLang_regexp_compile (&re)) +#ifdef KANJI + return; +#else return -1; +#endif /* look at the first 15 lines on first attempt. * After that, scan the whole buffer looking for more citations */ count = 15; lsave = l; +#ifndef KANJI ret = -1; +#endif while (1) { while (count && (l != NULL)) @@ -243,14 +258,22 @@ count--; } +#ifdef KANJI + if ((l == NULL) || (count == 0)) return; +#else if ((l == NULL) || (count == 0)) return ret; +#endif /* Now find out what is used for citing. */ b = (unsigned char *) l->buf + re.beg_matches[1]; len = re.end_matches[1]; +#ifdef KANJI + if (len > sizeof (name) - 2) return; +#else if (len > sizeof (name) - 2) return ret; ret = 0; +#endif strncpy (name, (char *) b, len); name[len] = 0; /* strcat (name, ">"); len++; */ @@ -322,10 +345,14 @@ if (a == NULL) return; +#ifdef KANJI + try_supercite(a->lines); +#else if (0 == try_supercite (a->lines)) { /* return; */ } +#endif if (Slrn_Ignore_Quote_Regexp[0] == NULL) return; @@ -415,8 +442,21 @@ do { b += strlen (b); +#ifdef KANJI + /* 2byte 文字の wrapping への対応。行頭が 2byte 文字で */ + /* '\' が 2 つで終わっていたら 2 つとも削除 */ + /* 前の行が space で終わっていたら、space のみ削除 */ + if (((unsigned char)l->buf[0] & 0x80) + && *(b - 2) == '\\' && *(b - 1) != ' ') { + b--; + } else if (*(b - 1) == '\t') { /* 行の端が tab の場合、'\' がない */ + b++; + } + strcpy (b - 1, l->buf); +#else strcpy (b, l->buf + 1); /* skip the space at beginning of * the wrapped line. */ +#endif next = l->next; slrn_free ((char *)l->buf); slrn_free ((char *)l); @@ -477,7 +517,9 @@ while (l != NULL) { +#ifndef KANJI unsigned char header_char_delimiter = 0; +#endif if (l->flags & HEADER_LINE) { @@ -487,12 +529,14 @@ continue; } +#ifndef KANJI if (0 == slrn_case_strncmp ((unsigned char *)"Path: ", (unsigned char *)l->buf, 6)) header_char_delimiter = '!'; else if (0 == slrn_case_strncmp ((unsigned char *) "Newsgroups: ", (unsigned char *)l->buf, 12)) header_char_delimiter = ','; +#endif } else if (l->flags & QUOTE_LINE) { @@ -513,6 +557,25 @@ len += SLsmg_Tab_Width; len -= len % SLsmg_Tab_Width; } +#ifdef KANJI + else { + len++; + if (ch < ' ') { + len++; + } + } + + /* 日本語では第1バイトで切れないよう、1文字早く対処 */ + if (len >= (unsigned int) SLtt_Screen_Cols) + { + Slrn_Article_Line_Type *new_l; + len = kanji_pos((unsigned char *)l->buf, buf); + if (len == 2) { /* 漢字第2byte */ + buf--; + } else if (ch == '\t') { + buf++; + } +#else else if (((ch >= ' ') && (ch < 127)) || (ch >= (unsigned char) SLsmg_Display_Eight_Bit)) len++; @@ -568,6 +631,7 @@ buf--; ch = *buf; *buf = ' '; +#endif new_l = (Slrn_Article_Line_Type *) slrn_malloc (sizeof (Slrn_Article_Line_Type), 1, 1); if (new_l == NULL) @@ -578,8 +642,25 @@ slrn_free ((char *) new_l); return -1; } +#ifdef KANJI + /* emacs style の wrapping (行末に '\' を入れる) */ + /* 滅多に無いが行端の文字が 2 バイト文字の 1 バイト目で */ + /* その手前の文字が '\' だったら、unwrap の時 '\' を */ + /* 削ってしまうので、その場合のみ行端に ' ' を入れる */ + /* また、画面の端がちょうど tab の時はおかしくなるので */ + /* '\' を入れない。*/ + if (len == 1 && *(buf - 1) == '\\') { + *buf++ = ' '; + } else if (ch != '\t') { + *buf++ = '\\'; + } + if (len == 2) { + *buf++ = '\\'; + } +#else *buf++ = ch; +#endif *buf = 0; new_l->next = l->next; @@ -588,6 +669,9 @@ if (new_l->next != NULL) new_l->next->prev = new_l; new_l->flags = l->flags | WRAPPED_LINE; +#ifdef KANJI + new_l->charset = l->charset; +#endif l = new_l; buf = (unsigned char *) new_l->buf; len = 0; @@ -693,6 +777,12 @@ char ch; char *buf; +#if defined(KANJI) && defined(SLRN_HAS_MIME) + /* treat a MIME multipart article as if it were a digest */ + if (Slrn_Use_Mime && (l->flags & HEADER_LINE) + && *l->buf == '[') { + } else { +#endif if ((l->flags & HIDDEN_LINE) || (l->flags & HEADER_LINE)) { l = l->next; @@ -718,6 +808,9 @@ continue; } } +#if defined(KANJI) && defined(SLRN_HAS_MIME) + } +#endif a->cline = l; a->needs_sync = 1; @@ -734,6 +827,29 @@ { Slrn_Article_Line_Type *l; +#ifdef KANJI + l = slrn_extract_header_line(a, hdr, len); + + if (l != NULL) { + char *result; + /* Return the data after the colon */ + result = slrn_strchr (l->buf, ':'); + if (result == NULL) + result = l->buf + len; + else result += 1; + + return slrn_skip_whitespace (result); + } + return NULL; +} + +/*}}}*/ + +Slrn_Article_Line_Type *slrn_extract_header_line (Slrn_Article_Type *a, char *hdr, unsigned int len) /*{{{*/ +{ + Slrn_Article_Line_Type *l; + +#endif if (a == NULL) return NULL; @@ -745,7 +861,9 @@ if (0 == slrn_case_strncmp ((unsigned char *) hdr, (unsigned char *) l->buf, len)) { +#ifndef KANJI char *result; +#endif if ((l->next != NULL) && (l->next->flags & WRAPPED_LINE)) { @@ -753,6 +871,9 @@ slrn_art_sync_article (a); } +#ifdef KANJI + return (l); +#else /* Return the data after the colon */ result = slrn_strchr (l->buf, ':'); if (result == NULL) @@ -760,6 +881,7 @@ else result += 1; return slrn_skip_whitespace (result); +#endif } l = l->next; } @@ -888,7 +1010,12 @@ l = l->next; } +#ifdef KANJI + while ((l != NULL) && ((*l->buf == ' ') || (*l->buf == '\t') + ||(l->flags & WRAPPED_LINE))); +#else while ((l != NULL) && ((*l->buf == ' ') || (*l->buf == '\t'))); +#endif } a->headers_hidden = 1; } @@ -906,6 +1033,32 @@ /*}}}*/ +#ifdef KANJI +static int illegal_folding(char *buf) /*{{{*/ +{ + /* RFC 違反の行の折り返しか、ヘッダかどうかの判定 */ + /* ':' の前に not ASCII or SPACE がある、 */ + /* または ':' がなければ RFC 違反の折り返し */ + int ch, i = 0; + while((ch = (unsigned char)buf[i]) != 0) { + if (ch == ':') { + if (i > 0) { + return (0); + } else { + break; + } + } else if (ch <= ' ' || (ch & 0x80)) { + break; + } + i++; + } + return (1); +} + + +/*}}}*/ + +#endif int _slrn_art_unfold_header_lines (Slrn_Article_Type *a) /*{{{*/ { Slrn_Article_Line_Type *l; @@ -921,7 +1074,13 @@ while ((l != NULL) && (l->flags & HEADER_LINE)) { ch = l->buf[0]; +#ifdef KANJI + /* RFC に反した header の folding に対する処置 */ + /* folding した行の初めにスペースが無い */ + if ((ch == ' ') || (ch == '\t') || illegal_folding(l->buf)) +#else if ((ch == ' ') || (ch == '\t')) +#endif { unsigned int len0, len1; Slrn_Article_Line_Type *prev; diff -Nru slrn-0.9.6.2.orig/src/charmaps.h slrn-0.9.6.2/src/charmaps.h --- slrn-0.9.6.2.orig/src/charmaps.h Fri Dec 24 02:24:37 1999 +++ slrn-0.9.6.2/src/charmaps.h Sat Jan 1 07:47:59 2000 @@ -21,6 +21,1697 @@ * maintainence of the various character sets. */ +#ifdef KANJI +/* + * X0201 kana conversion table (0x90 - 0xdf) + * upper = ((cv[ch - 0x90] & 0x80) >> 5) + 0x21 + * lower = (cv[ch - 0x90] & 0x7f) + 0x21 + */ +static unsigned char han2zen_cv[]= { + 0x00,0x02,0x35,0x36, 0x01,0x05,0xd1,0x80, + 0x82,0x84,0x86,0x88, 0xc2,0xc4,0xc6,0xa2, + 0x1b,0x81,0x83,0x85, 0x87,0x89,0x8a,0x8c, + 0x8e,0x90,0x92,0x94, 0x96,0x98,0x9a,0x9c, + 0x9e,0xa0,0xa3,0xa5, 0xa7,0xa9,0xaa,0xab, + 0xac,0xad,0xae,0xb1, 0xb4,0xb7,0xba,0xbd, + 0xbe,0xbf,0xc0,0xc1, 0xc3,0xc5,0xc7,0xc8, + 0xc9,0xca,0xcb,0xcc, 0xce,0xd2,0x0a,0x2c +}; + +/* UCS2 を JISX0201、JISX0208 に変換する */ +/* SLRN_UNICODE_KANJI_CONVERT を undef すると漢字の変換はできない */ +/* hi = (lo & 0x80) ? 0x22 : 0x21 */ +/* lo = lo & 0x7f */ +static unsigned char u3000[] = { /* 3000 - 3015 */ + 0x21, 0x22, 0x23, 0x37, 0x00, 0x39, 0x3A, 0x3B, + 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5A, 0x5B, 0xA9, 0xAE, 0x4C, 0x4D +}; + +static unsigned char u309b[] = { /* 309B - 309E */ + 0x2B, 0x2C, 0x35, 0x36 +}; + +static unsigned char u30fb[] = { /* 30FB - 30FE */ + 0x26, 0x3C, 0x33, 0x34 +}; + +static unsigned char uff01[] = { /* FF01 - FF0F */ + 0x2A, 0x00, 0x74, 0x70, 0x73, 0x75, 0x00, 0x4A, + 0x4B, 0x76, 0x5C, 0x24, 0x5D, 0x25, 0x3F +}; + +static unsigned char uff1a[] = { /* FF1A - FF20 */ + 0x27, 0x28, 0x63, 0x61, 0x64, 0x29, 0x77 +}; + +static unsigned char uff3b[] = { /* FF3B - FF40 */ + 0x4E, 0x40, 0x4F, 0x30, 0x32, 0x2E +}; + +static unsigned char uff5b[] = { /* FF5B - FF5D */ + 0x50, 0x43, 0x51 +}; + +static unsigned char u2000[] = { /* pair of Unicode and JISX0208 */ + 0x10, 0xBE, 0x15, 0xBD, 0x16, 0xC2, 0x18, 0xC6, + 0x19, 0xC7, 0x1c, 0xC8, 0x1d, 0xC9, 0x20, 0xF7, + 0x21, 0x78, 0x25, 0xC5, 0x26, 0xC4 +}; /* Unicode(0x20xx), JIS(0x22yy) set 8th bit if 0x21yy */ + +static unsigned char u2200[] = { /* pair of Unicode and JISX0208 */ + 0x00, 0x4f, 0x02, 0x5F, 0x03, 0x50, 0x07, 0x60, + 0x08, 0x3A, 0x0B, 0x3B, 0x12, 0xDD, 0x1A, 0x65, + 0x1D, 0x67, 0x1E, 0xE7, 0x20, 0x5C, 0x27, 0x4A, + 0x28, 0x4B, 0x29, 0x41, 0x2A, 0x40, 0x2B, 0x69, + 0x2C, 0x6A, 0x34, 0xE8, 0x35, 0x68, 0x3D, 0x66, + 0x52, 0x62, 0x60, 0xE2, 0x61, 0x61, 0x66, 0xE5, + 0x67, 0xE6, 0x6A, 0x63, 0x6B, 0x64, 0x82, 0x3E, + 0x83, 0x3F, 0x86, 0x3C, 0x87, 0x3D, 0xA5, 0x5D, +}; /* Unicode(0x22xx), JIS(0x22yy) set 8th bit if 0x21yy */ + +static unsigned char j2821[] = { /* JIS-X0208 0x2821 - 0x2840 */ + 0x00, 0x02, 0x0C, 0x10, 0x18, 0x14, 0x1C, 0x2C, + 0x24, 0x34, 0x3C, 0x01, 0x03, 0x0F, 0x13, 0x1B, + 0x17, 0x23, 0x33, 0x2B, 0x3B, 0x4B, 0x20, 0x2F, + 0x28, 0x37, 0x3F, 0x1D, 0x30, 0x25, 0x38, 0x42 +}; + +#if SLRN_UNICODE_KANJI_CONVERT +/* + * This is a table to convert JIS-X0208 Kanji to Unicode. + * if ch1 < 0x52 then uni = (ch1 << 8 | ch2) + 0x4e00 + * else if ch1 <= 0x80 then uni -= (ch1 - 0x51) + * else uni += ch1 & 0x7f + */ +static unsigned char jis2ucs[] = { /* JIS-X0208 0x3021 - 0x7426 */ + 0x00, 0x9C, 0x07, 0x16, 0x0C, 0x03, 0x48, 0x3F, + 0x06, 0xC0, 0x13, 0x1B, 0x15, 0x28, 0x0B, 0xF6, + 0x42, 0x22, 0x36, 0x75, 0x35, 0x1C, 0x2C, 0x50, + 0x12, 0xAA, 0x15, 0xE1, 0x20, 0x25, 0x17, 0xED, + 0x36, 0x66, 0x34, 0xA6, 0x4D, 0xF5, 0x1A, 0x93, + 0x09, 0x27, 0x17, 0xA1, 0x14, 0x71, 0x0D, 0x9B, + 0x0B, 0xD0, 0x38, 0x7B, 0x4A, 0xF4, 0x2F, 0x62, + 0xDC, 0x4D, 0x8E, 0x14, 0x16, 0x2E, 0x9F, + 0x3A, 0xB7, 0x0D, 0x89, 0x10, 0xB5, 0x15, 0x09, + 0x18, 0x97, 0x1A, 0x48, 0x47, 0xC7, 0x49, 0x8D, + 0x19, 0x4F, 0x00, 0xE5, 0xA5, 0xC3, + 0xD0, 0x02, 0x49, 0x08, 0xF2, 0x0B, 0x37, + 0x0B, 0xD4, 0xAD, 0x0E, 0x09, 0x12, 0xDF, + 0xB0, 0xE1, 0x18, 0x13, 0x1B, 0x05, + 0x22, 0xBA, 0x27, 0x4F, 0xA1, 0x2B, 0xFB, + 0x2F, 0xAD, 0xC2, 0x32, 0xC3, 0x36, 0x0E, + 0x3A, 0x63, 0x3D, 0x02, 0x42, 0x55, 0xA5, + 0x05, 0x3B, 0x00, 0x95, 0x90, 0x09, 0xDF, + 0x32, 0xB2, 0x42, 0xC1, 0x2A, 0xEF, 0x00, 0x00, + 0x0A, 0xF1, 0x20, 0xA2, 0x42, 0x38, 0x2C, 0x32, + 0x35, 0x28, 0x34, 0x8B, 0x4E, 0x2F, 0x03, 0x41, + 0x05, 0x70, 0x06, 0xBD, 0xA4, 0x08, 0xE0, + 0x0B, 0xFB, 0x11, 0x15, 0x4A, 0xF2, 0x1F, 0xEB, + 0x32, 0xE4, 0x37, 0x2D, 0x48, 0x62, 0x8E, + 0xB0, 0x49, 0xFB, 0x06, 0x0B, 0x69, + 0x0D, 0x87, 0x22, 0xCF, 0x31, 0xBD, 0x41, 0xC2, + 0x48, 0xE8, 0x05, 0x6F, 0x4F, 0x5C, 0x2C, 0xBA, + 0x00, 0x11, 0x2A, 0x93, 0x33, 0xFC, 0x20, 0x26, + 0x08, 0x18, 0x07, 0x04, 0x1D, 0x1D, 0x37, 0x1A, + 0x4E, 0x3B, 0x0B, 0xE5, 0x05, 0xA9, 0x1F, 0x66, + 0x26, 0xDC, 0x47, 0x8F, 0x08, 0x42, 0x00, 0x91, + 0x42, 0x4B, 0x48, 0xF2, 0x35, 0x4F, 0x4B, 0x0C, + 0x05, 0xE1, 0x07, 0xB6, 0x0D, 0x30, 0x11, 0x71, + 0x18, 0x20, 0x18, 0xF3, 0x1A, 0x04, 0x1E, 0x38, + 0x1E, 0xF3, 0xB6, 0x26, 0x5B, 0x28, 0xC8, + 0x2C, 0x4E, 0x4A, 0x34, 0x34, 0xF1, 0x3A, 0x5B, + 0x3C, 0x60, 0x44, 0xED, 0x1F, 0xB2, 0x27, 0xAB, + 0x28, 0xCA, 0x4B, 0xC5, 0x12, 0xA6, 0x3D, 0x01, + 0x3F, 0x8A, 0x47, 0xB2, 0x1B, 0x8E, 0x05, 0xAD, + 0x03, 0x86, 0x09, 0x12, 0x0A, 0x30, 0x0B, 0x44, + 0x0D, 0xB4, 0x10, 0xF6, 0x12, 0x28, 0x15, 0xA9, + 0xCB, 0x1E, 0xBF, 0x21, 0x14, 0x22, 0x8E, + 0x23, 0x14, 0xC5, 0xFC, 0x25, 0x3F, + 0x30, 0x01, 0x34, 0x76, 0xDB, 0x37, 0x97, + 0x42, 0x60, 0x44, 0x5B, 0x4F, 0x1B, 0x0A, 0x69, + 0x17, 0xBC, 0x1E, 0x5A, 0x27, 0x25, 0x03, 0xF9, + 0x0B, 0x2E, 0xB7, 0x11, 0x80, 0xDC, + 0x14, 0xBC, 0x17, 0xFA, 0x1C, 0x2A, 0x1D, 0x27, + 0x1D, 0xB4, 0x25, 0x8B, 0x31, 0xC1, 0x3B, 0x56, + 0x4F, 0x2C, 0x6F, 0x50, 0xC4, 0x0E, 0xA1, + 0x1E, 0x96, 0x35, 0x7B, 0x03, 0x04, 0x0E, 0x4B, + 0x13, 0xB6, 0x33, 0xC6, 0x1A, 0x76, 0x24, 0x61, + 0x00, 0x59, 0x01, 0xFA, 0x05, 0x78, 0x12, 0x69, + 0x20, 0x29, 0x2C, 0x4F, 0x49, 0xF3, 0x00, 0x0B, + 0x05, 0x16, 0x00, 0xEE, 0xE7, 0x69, + 0xE4, 0x7F, 0x04, 0xA0, 0x05, 0xEF, + 0x08, 0x09, 0x0B, 0x0F, 0x0C, 0xC1, 0x0D, 0xB6, + 0xAB, 0x2B, 0xD1, 0x18, 0x87, 0x19, 0x9C, + 0x9A, 0x1D, 0x4C, 0x1E, 0xB3, 0x22, 0x6B, + 0x25, 0xC2, 0x2B, 0x8D, 0xB1, 0xFE, + 0x2D, 0x87, 0x34, 0xB1, 0xAA, 0xA9, + 0xF3, 0xF8, 0x6D, 0x39, 0x66, + 0x3C, 0xB2, 0x08, 0x29, 0x3E, 0xA8, 0x41, 0xE6, + 0xE8, 0x49, 0x1E, 0x38, 0x8A, 0x01, 0xC4, + 0x0E, 0xE8, 0x14, 0x11, 0x24, 0x59, 0x27, 0x3B, + 0x33, 0xE5, 0x34, 0xBD, 0x38, 0xFE, 0x3E, 0xC0, + 0x48, 0xC5, 0x4B, 0x13, 0x4B, 0xD5, 0x00, 0xCB, + 0xCF, 0x3B, 0xE3, 0x08, 0xDE, 0x0A, 0x4A, + 0x0A, 0xCA, 0x10, 0xFB, 0x11, 0xEB, 0xBF, + 0xEA, 0x12, 0x62, 0x13, 0xD0, 0xC2, + 0x14, 0xD0, 0x17, 0x39, 0x4D, 0x41, 0x18, 0x66, + 0x1A, 0xB0, 0x1F, 0x77, 0x22, 0x70, 0x27, 0x4C, + 0x28, 0x86, 0x2F, 0x75, 0x34, 0xA5, 0x39, 0xF9, + 0x47, 0x8B, 0x48, 0x8E, 0x3E, 0x9D, 0x03, 0xF1, + 0x04, 0xBE, 0x0B, 0x16, 0x06, 0xB3, 0x0D, 0xB3, + 0x0F, 0x16, 0x13, 0x68, 0x1B, 0x82, 0x1F, 0xAF, + 0x2A, 0x8D, 0x36, 0xCB, 0x3A, 0x57, 0x3C, 0x72, + 0x45, 0xA7, 0x4C, 0xB8, 0x1F, 0x6C, 0x4B, 0xA8, + 0x38, 0xD9, 0x09, 0xA3, 0x19, 0xFF, 0x38, 0xCE, + 0x44, 0x0E, 0x04, 0x83, 0x08, 0x87, 0x06, 0x04, + 0x10, 0xD3, 0x14, 0xE1, 0x16, 0xB9, 0x1A, 0x3C, + 0x55, 0x1D, 0xBB, 0x25, 0x72, 0x2A, 0xBA, + 0x2C, 0x6B, 0x3B, 0x9A, 0xB8, 0x3F, 0x6B, + 0x41, 0x03, 0x42, 0xED, 0x47, 0xA3, 0x48, 0x94, + 0x49, 0x69, 0x0D, 0x66, 0x0E, 0xB3, 0x1B, 0x7D, + 0x4A, 0x4D, 0x81, 0x15, 0x9B, 0x2D, 0x20, + 0x1C, 0x2B, 0xD4, 0x1A, 0xB6, 0x4E, 0x0D, + 0x21, 0x5F, 0x04, 0x72, 0x07, 0x9D, 0x12, 0x70, + 0x14, 0xEC, 0x1F, 0x3B, 0x20, 0x07, 0x20, 0xD1, + 0x36, 0x5B, 0x3B, 0x10, 0x41, 0x44, 0x00, 0x14, + 0x4E, 0x39, 0x05, 0xF6, 0x1B, 0x1B, 0x1C, 0x3A, + 0x49, 0x84, 0x1A, 0x2A, 0x03, 0x5C, 0x2C, 0xC3, + 0x36, 0xB2, 0x43, 0xDC, 0x45, 0x8C, 0x08, 0x5B, + 0x4F, 0x28, 0x1A, 0x22, 0x35, 0x05, 0x36, 0x31, + 0x2E, 0xA5, 0x04, 0x08, 0x34, 0xC5, 0x26, 0xE6, + 0x00, 0x7E, 0x01, 0x83, 0x03, 0xA0, 0x0D, 0xD2, + 0x04, 0x0A, 0x04, 0xD8, 0x8F, 0x0F, 0xFB, + 0x07, 0x9A, 0x0A, 0x2A, 0x0B, 0xE6, 0x0D, 0x8C, + 0x8C, 0xC3, 0x10, 0x72, 0x87, + 0x12, 0xA3, 0xFC, 0xC4, 0xDB, + 0x15, 0xDB, 0x17, 0x62, 0x19, 0xD1, 0x1A, 0x53, + 0x1A, 0xFA, 0x1D, 0x3E, 0x95, 0x1E, 0x57, + 0x21, 0x22, 0xF5, 0x21, 0x45, 0x26, 0xB0, + 0xE8, 0x28, 0xE3, 0xA8, 0x2C, 0xFF, + 0x2D, 0xA1, 0x2E, 0x21, 0x2F, 0xE9, 0x31, 0x36, + 0x31, 0xF0, 0x32, 0x9D, 0x34, 0x66, 0x35, 0x9E, + 0x3B, 0xB3, 0x3C, 0xCC, 0x3E, 0xAB, 0x42, 0x84, + 0x46, 0x51, 0x47, 0x93, 0x53, 0x91, + 0x48, 0x65, 0x49, 0xD3, 0x4B, 0x28, 0x34, 0x18, + 0x00, 0x38, 0x06, 0x2B, 0x0E, 0xB8, 0x0F, 0xCC, + 0x25, 0xA9, 0x28, 0x4C, 0x29, 0x3C, 0x0E, 0xA9, + 0x31, 0xEB, 0x3F, 0x0B, 0x48, 0xC1, 0x4A, 0x11, + 0xC3, 0x84, 0x01, 0x01, 0x8D, + 0x05, 0x71, 0x07, 0x9C, 0x08, 0x68, 0x09, 0xFA, + 0x0B, 0x47, 0x0D, 0x09, 0x0D, 0xC4, 0x0E, 0x90, + 0x10, 0x0C, 0xF2, 0x11, 0xCC, 0x15, 0xEE, + 0x19, 0x3A, 0x17, 0xD7, 0x8B, 0x19, 0x1F, + 0x1A, 0xCB, 0x58, 0x1C, 0x5F, 0x10, 0x30, + 0x1D, 0xC5, 0xD2, 0xE6, 0x27, 0x7F, + 0x2B, 0x48, 0x0D, 0x63, 0x2C, 0x00, 0x2F, 0x00, + 0x11, 0xBD, 0x3B, 0x8F, 0x3C, 0x18, 0x3E, 0xB4, + 0x3F, 0x77, 0x40, 0xCC, 0xD1, 0x4A, 0xE2, + 0x4C, 0x0E, 0x4D, 0x3C, 0x00, 0x80, 0x02, 0x7D, + 0x03, 0x00, 0x0B, 0x93, 0x0D, 0x9C, 0x14, 0x2F, + 0xD1, 0x16, 0xEC, 0x1D, 0x3A, 0x24, 0xA0, + 0x27, 0x91, 0x2B, 0x47, 0x31, 0xA9, 0x39, 0xFB, + 0x3C, 0xBC, 0x3D, 0x70, 0x15, 0xAC, 0x35, 0xCA, + 0x49, 0xA0, 0x06, 0x09, 0x57, 0x07, 0xAB, + 0x1A, 0x54, 0x1C, 0x58, 0x3C, 0x70, 0x2A, 0x27, + 0x19, 0x75, 0x50, 0xCD, 0x05, 0x74, 0x0D, 0xA2, + 0x33, 0x1A, 0x38, 0x50, 0x42, 0x06, 0x00, 0x18, + 0xAD, 0x00, 0xC7, 0xCA, 0x05, 0xCA, + 0xEE, 0x0D, 0xAE, 0x11, 0x13, 0x12, 0x25, + 0x17, 0x51, 0x19, 0x3D, 0x1E, 0x42, 0xB0, + 0xF1, 0x22, 0x78, 0x26, 0x03, 0x2C, 0x76, + 0xB8, 0xDA, 0x2F, 0x1A, 0x6D, + 0xE8, 0x17, 0xE7, 0x24, 0x5B, 0x05, 0xBB, + 0x0E, 0x45, 0x0F, 0xE8, 0x14, 0xD2, 0x8E, + 0xB9, 0x20, 0x20, 0x38, 0x5A, 0x3C, 0x31, + 0x3F, 0xDD, 0x44, 0xF8, 0x21, 0x01, 0x2B, 0xA6, + 0x4D, 0x5A, 0x00, 0xA8, 0x83, 0x81, + 0x01, 0x9B, 0x85, 0x02, 0xD1, 0xF6, + 0x2C, 0xF6, 0x03, 0x71, 0x03, 0xF6, 0x05, 0x54, + 0x05, 0x21, 0xDE, 0xEC, 0x07, 0xAC, + 0x0A, 0x83, 0x0E, 0xE1, 0x11, 0x37, 0x93, + 0x12, 0x2F, 0xA1, 0x9D, 0x15, 0x1F, + 0x17, 0x59, 0x1C, 0x4B, 0x1E, 0xC1, 0x24, 0xC2, + 0xAB, 0x29, 0xEF, 0x32, 0xF8, 0x8D, + 0x34, 0x08, 0x37, 0x4E, 0x42, 0xF7, 0x45, 0xE1, + 0x49, 0xFF, 0x4B, 0x57, 0x4C, 0x5A, 0x00, 0xF0, + 0x03, 0xDD, 0x0E, 0x2D, 0x18, 0x81, 0x1B, 0x6D, + 0x0E, 0x40, 0x18, 0xF2, 0x1B, 0x75, 0x25, 0x89, + 0x1A, 0x50, 0x2E, 0x81, 0x02, 0xC5, 0x04, 0xE4, + 0x09, 0x47, 0x0F, 0xFE, 0x45, 0x26, 0x17, 0xA4, + 0x1D, 0x23, 0x9A, 0x26, 0x34, 0x2B, 0x81, + 0xBC, 0x2D, 0x4B, 0x2F, 0xCA, 0x34, 0xB9, + 0x35, 0xCC, 0x3A, 0x7F, 0x3B, 0x5F, 0x3D, 0x39, + 0x41, 0xD1, 0x43, 0xD1, 0x06, 0x1F, 0x44, 0x80, + 0x00, 0x5D, 0x02, 0x36, 0x05, 0xE5, 0x05, 0x3A, + 0x24, 0xD7, 0x25, 0x96, 0x29, 0xE9, 0x34, 0xE6, + 0x40, 0xAF, 0x4B, 0xC6, 0x82, 0x8A, + 0x03, 0x77, 0x13, 0x1A, 0x38, 0x5E, 0x07, 0xB0, + 0x2C, 0x7A, 0x02, 0x76, 0x0D, 0xD3, 0x42, 0x47, + 0x48, 0x85, 0x00, 0x32, 0x1C, 0xDB, 0x43, 0xE7, + 0x0E, 0x51, 0x5A, 0x15, 0x98, 0x2C, 0x9F, + 0x1E, 0x93, 0x49, 0x74, 0x41, 0x61, 0x2C, 0xAA, + 0x23, 0x8A, 0x48, 0x88, 0x2E, 0x82, 0x1A, 0x17, + 0x30, 0x70, 0x1A, 0x51, 0x45, 0x6C, 0x04, 0xF2, + 0x06, 0x1B, 0x37, 0xAB, 0x3C, 0x13, 0x31, 0xA4, + 0x40, 0xCD, 0x42, 0xE1, 0x05, 0x66, 0x3A, 0x88, + 0x2B, 0x41, 0x01, 0xC2, 0x02, 0xBE, 0x04, 0x11, + 0x03, 0x44, 0x07, 0x53, 0x09, 0x2D, 0x25, 0xEA, + 0x09, 0x8B, 0x0B, 0x51, 0x11, 0x62, 0xA2, + 0x12, 0x75, 0x13, 0x76, 0x60, 0xC2, + 0x15, 0xB2, 0x16, 0x3A, 0x17, 0x6C, 0x18, 0x6F, + 0x1A, 0x42, 0x20, 0x13, 0x27, 0x66, 0x2C, 0x3D, + 0x2E, 0xFB, 0xD1, 0xCD, 0x30, 0x4B, + 0x31, 0x6B, 0x35, 0x0E, 0xBC, 0x38, 0xCD, + 0x3C, 0x08, 0xDB, 0x3D, 0x66, 0x40, 0xFD, + 0x4A, 0x1A, 0x4F, 0x8F, 0x34, 0xB8, 0x41, 0xCE, + 0x4D, 0xE8, 0x04, 0x87, 0x14, 0x1F, 0x16, 0x83, + 0x21, 0xC0, 0x48, 0x99, 0x1A, 0x41, 0x02, 0x91, + 0x1D, 0x20, 0x1E, 0x7A, 0x21, 0x54, 0x2C, 0x74, + 0x2F, 0x50, 0x3A, 0x40, 0x3C, 0x23, 0x19, 0x08, + 0x00, 0xF6, 0x02, 0x39, 0x64, 0xBF, + 0x03, 0x7C, 0x04, 0x38, 0xAB, 0x07, 0xA7, + 0x09, 0x0F, 0x0A, 0x05, 0x0C, 0xCC, 0x10, 0xFA, + 0x13, 0xB2, 0xC6, 0x14, 0xF3, 0xFF, + 0x1B, 0x1C, 0x1C, 0x29, 0x24, 0x7D, 0xAF, + 0x25, 0x2E, 0x2A, 0x14, 0xDB, 0x2F, 0x79, + 0x29, 0x0C, 0x32, 0xA9, 0x3B, 0x8B, 0x3D, 0x19, + 0x3E, 0xE2, 0x40, 0xD2, 0x42, 0x63, 0x45, 0x75, + 0x48, 0x7A, 0x4A, 0x55, 0x4C, 0x13, 0x50, 0x78, + 0x03, 0x43, 0x05, 0x9F, 0x94, 0x10, 0x7B, + 0x11, 0x26, 0x20, 0x1B, 0xF5, 0x25, 0x84, + 0xFA, 0x2F, 0x43, 0x34, 0x37, 0x3C, 0x00, + 0x3C, 0xFA, 0x48, 0x50, 0x00, 0x4E, 0x02, 0x0B, + 0x05, 0xE4, 0x06, 0x7C, 0x08, 0xFA, 0x0B, 0xD1, + 0x0D, 0x64, 0x0F, 0xF1, 0x10, 0xAB, 0xFC, + 0x14, 0x38, 0x17, 0x45, 0x19, 0xAF, 0x20, 0x56, + 0x24, 0xD0, 0x2E, 0xCA, 0x3A, 0xB4, 0x32, 0xA1, + 0xC0, 0x35, 0xF0, 0x38, 0x4E, 0x3C, 0x87, + 0x3F, 0xE8, 0x44, 0x37, 0x48, 0xC7, 0x4A, 0x67, + 0x51, 0x13, 0x00, 0x94, 0x53, 0xFB, + 0x05, 0x48, 0x06, 0x49, 0x5C, 0x0C, 0x2F, + 0x11, 0x8C, 0x95, 0x12, 0x9F, 0x1A, 0xA7, + 0x1C, 0x8E, 0x26, 0x5A, 0x2A, 0x81, 0x3C, 0x9E, + 0x86, 0x3D, 0x77, 0x43, 0x90, 0x00, 0x5E, + 0x4D, 0xC9, 0x00, 0xA4, 0x01, 0x7C, 0xB3, + 0xEA, 0x54, 0x03, 0x49, 0xA3, + 0x04, 0x9F, 0x9A, 0xC5, 0x05, 0x9A, + 0xC9, 0xAE, 0x54, 0x07, 0x89, + 0x09, 0x51, 0xD1, 0x0B, 0x7D, 0x0D, 0x54, + 0x89, 0xB2, 0x0F, 0xE5, 0x82, + 0x90, 0x10, 0x78, 0x8B, 0x97, + 0x9D, 0xE1, 0x12, 0x52, 0x13, 0x4C, + 0x14, 0x97, 0xC1, 0x15, 0xA7, 0x17, 0x3B, + 0x18, 0x02, 0xC1, 0x18, 0xF4, 0xF9, + 0x1A, 0x21, 0xF6, 0x1B, 0xCB, 0x1E, 0x5F, + 0x1F, 0x2A, 0xBF, 0x20, 0x2F, 0xEE, + 0x27, 0x32, 0x28, 0x87, 0x2A, 0x6C, 0x2C, 0x3F, + 0x2E, 0xE0, 0xA5, 0x93, 0xC6, + 0xD3, 0x32, 0x15, 0x63, 0x32, 0xAF, + 0x82, 0x33, 0x54, 0xBB, 0x34, 0x2A, + 0x35, 0x52, 0x3A, 0x4C, 0x95, 0x3D, 0x1B, + 0x3E, 0xA2, 0xDA, 0x42, 0xCA, 0x43, 0x75, + 0x44, 0x71, 0x2A, 0x3F, 0x44, 0xFC, 0x47, 0xA4, + 0x48, 0x4D, 0x4A, 0x05, 0x4B, 0x99, 0x4C, 0xD8, + 0x4F, 0x3B, 0x04, 0x5B, 0xD0, 0x05, 0xF7, + 0x91, 0x0A, 0xD5, 0x14, 0xF7, 0x21, 0xE0, + 0x3E, 0x6A, 0x41, 0x5F, 0x50, 0xB9, 0x03, 0x4B, + 0x04, 0x3B, 0x06, 0x4A, 0x08, 0xFD, 0x2C, 0x40, + 0x43, 0x77, 0x4F, 0x60, 0x50, 0xD2, 0x25, 0x44, + 0x21, 0x09, 0x33, 0x70, 0x27, 0x11, 0x11, 0xFD, + 0x12, 0xDA, 0x4C, 0xA8, 0x24, 0xDB, 0x41, 0xBC, + 0x1D, 0x64, 0x4A, 0x03, 0x00, 0xCA, 0x08, 0xF0, + 0xF4, 0x0A, 0xBE, 0x0C, 0x5A, 0x12, 0x68, + 0x13, 0xC7, 0x18, 0x0F, 0x5A, 0x1A, 0x39, + 0xF8, 0x1F, 0xF7, 0x27, 0xD5, 0x2F, 0x3A, + 0x34, 0x6E, 0x4D, 0x42, 0x00, 0x9B, 0x01, 0x50, + 0x05, 0xC9, 0x07, 0x06, 0x0F, 0x6F, 0xF7, + 0x88, 0x19, 0xFB, 0x1E, 0x99, 0x26, 0x73, + 0x2A, 0x02, 0x3C, 0x50, 0x45, 0x96, 0x3A, 0xDF, + 0x09, 0x50, 0x10, 0xA7, 0x15, 0x2B, 0x02, 0xB5, + 0x5A, 0x03, 0x8D, 0x19, 0x00, 0x06, 0xC9, + 0x0A, 0x5E, 0x0B, 0xBB, 0x0D, 0xB0, 0x11, 0x69, + 0x14, 0x4D, 0x15, 0xA1, 0x1A, 0x3D, 0x1D, 0x73, + 0x20, 0x08, 0x22, 0x7D, 0x43, 0xC7, 0x24, 0x80, + 0x2A, 0x15, 0x91, 0x2B, 0x6D, 0x17, 0x8E, + 0x2F, 0x30, 0x35, 0xDC, 0x3A, 0xC1, 0x41, 0x09, + 0x48, 0x9B, 0x04, 0x64, 0x09, 0x28, 0x19, 0x50, + 0x31, 0x6A, 0x3E, 0xA1, 0x03, 0xB4, 0x09, 0x42, + 0x48, 0x2A, 0x0A, 0x3A, 0x1B, 0x8A, 0x32, 0xB4, + 0x06, 0xB2, 0x0F, 0x0E, 0x09, 0xFC, 0x2A, 0x95, + 0x4F, 0xFA, 0x01, 0x5C, 0x04, 0x4A, 0x06, 0x8B, + 0x16, 0x3E, 0x18, 0x28, 0x19, 0x14, 0x19, 0xF5, + 0x2C, 0x84, 0x2D, 0x56, 0x2F, 0x22, 0x45, 0x2F, + 0x1A, 0x5C, 0x4D, 0xAD, 0x2D, 0x39, 0x05, 0x19, + 0x03, 0x8A, 0x04, 0x37, 0x0D, 0xDF, 0x14, 0xF6, + 0x16, 0xAE, 0xB8, 0x19, 0x2D, 0x1D, 0xBA, + 0x37, 0xA9, 0x48, 0xD1, 0x28, 0x90, 0x4D, 0xD6, + 0x15, 0x4C, 0x45, 0x06, 0x4D, 0xAB, 0x28, 0xBF, + 0x18, 0x52, 0x00, 0x09, 0x02, 0x98, 0x05, 0xC2, + 0x0E, 0x71, 0x12, 0xE8, 0x16, 0x92, 0x17, 0x63, + 0x1A, 0x5F, 0x23, 0xE6, 0x25, 0xCA, 0x27, 0x23, + 0x2D, 0x97, 0x30, 0x82, 0x38, 0x95, 0x3D, 0x83, + 0x3E, 0xDB, 0x43, 0x78, 0x4B, 0x10, 0x17, 0xAC, + 0x18, 0xAB, 0x1D, 0x8B, 0x00, 0xD5, 0x52, + 0xE6, 0xC5, 0x04, 0x3A, 0x05, 0xF8, + 0x57, 0x07, 0xE3, 0x08, 0xDB, 0x0A, 0xEB, + 0x0B, 0xCB, 0x53, 0xB6, 0x0D, 0x50, + 0x0E, 0x4D, 0x10, 0x02, 0xA9, 0x11, 0xD7, + 0xC6, 0x15, 0x07, 0x17, 0x2F, 0x0D, 0x5C, + 0x17, 0xAF, 0x8E, 0xAB, 0x19, 0x9D, + 0x1D, 0x62, 0x99, 0x1E, 0x0F, 0x25, 0x45, + 0x2B, 0x49, 0xF8, 0x2E, 0xF8, 0xA1, + 0x92, 0x32, 0xA2, 0xE0, 0x33, 0xF3, + 0x3B, 0x96, 0x3C, 0x5E, 0x8B, 0x54, + 0xA6, 0xE2, 0x3E, 0xC7, 0x95, + 0x48, 0xCC, 0x4A, 0xFC, 0x1D, 0x6F, 0x00, 0x8B, + 0x01, 0x3C, 0xD1, 0x03, 0x50, 0x0D, 0x57, + 0x0D, 0xFA, 0x13, 0x48, 0x15, 0x01, 0x18, 0x42, + 0x1D, 0x21, 0x20, 0xCB, 0x1E, 0xBB, 0x24, 0x3E, + 0x26, 0xBD, 0x27, 0xD4, 0x2A, 0xC1, 0xF9, + 0x32, 0x0C, 0xA7, 0x33, 0xEA, 0x36, 0x94, + 0x41, 0x9E, 0x1E, 0x50, 0x50, 0x7F, 0x11, 0x0F, + 0x3D, 0x58, 0x4F, 0x2B, 0x2C, 0xFA, 0x40, 0xF8, + 0x0D, 0x8D, 0x48, 0xEB, 0x00, 0x03, 0x05, 0xF1, + 0x09, 0xF7, 0x0B, 0x31, 0x0C, 0xC9, 0x0D, 0xA4, + 0x12, 0x89, 0x20, 0x7F, 0x21, 0x06, 0x27, 0xBE, + 0x3E, 0xEA, 0x0D, 0x9F, 0x37, 0x00, 0x2D, 0xE0, + 0x02, 0x72, 0x19, 0xF4, 0x34, 0x9D, 0x0E, 0x61, + 0x37, 0x4A, 0x30, 0x1E, 0x34, 0x0E, 0x03, 0x99, + 0x0E, 0x04, 0x15, 0x68, 0x3F, 0x66, 0x17, 0x9C, + 0x23, 0x6E, 0x2B, 0x3E, 0x2F, 0x17, 0x32, 0x05, + 0x3D, 0x1D, 0x40, 0xCA, 0x42, 0x6E, 0x38, 0xC7, + 0x42, 0xAA, 0x02, 0x1F, 0x04, 0xFA, 0x0E, 0x3A, + 0x19, 0x53, 0x22, 0x7C, 0x24, 0x35, 0x43, 0x4C, + 0xFC, 0x45, 0x2B, 0x34, 0xE5, 0x0D, 0xC2, + 0x11, 0x31, 0x12, 0xF9, 0x00, 0x3B, 0x05, 0xD6, + 0x0D, 0x88, 0x14, 0x4B, 0x19, 0x31, 0x1D, 0x8A, + 0x24, 0xE9, 0x25, 0xE0, 0x2C, 0x2E, 0x33, 0x6B, + 0x3F, 0xA3, 0x43, 0x52, 0x4B, 0x96, 0x03, 0x12, + 0x05, 0xD7, 0x06, 0x6A, 0x0D, 0xFF, 0x15, 0x88, + 0x1C, 0x39, 0x2F, 0xAC, 0x49, 0x00, 0x08, 0xDA, + 0x05, 0xCE, 0x06, 0x68, 0x0D, 0x97, 0x0E, 0x31, + 0x0F, 0xDE, 0x01, 0xEE, 0x13, 0x01, 0x14, 0xFE, + 0x1F, 0x32, 0x2B, 0xC0, 0x8B, 0x2F, 0x42, + 0x30, 0x4D, 0x31, 0xD2, 0x33, 0xED, 0xB2, + 0x36, 0x90, 0x3A, 0x46, 0x3B, 0x72, 0x3D, 0x90, + 0x40, 0x74, 0x41, 0x2F, 0x42, 0x31, 0x43, 0x4B, + 0xA1, 0x48, 0xC6, 0x43, 0x9C, 0x00, 0xC0, + 0x01, 0x4F, 0x03, 0x45, 0x05, 0x41, 0x11, 0x93, + 0x14, 0x0E, 0x19, 0xD4, 0x1E, 0x41, 0x20, 0x0B, + 0x25, 0x63, 0x30, 0x26, 0x43, 0xCD, 0x44, 0x83, + 0x05, 0xD4, 0x0B, 0x19, 0x0D, 0xBF, 0x1F, 0xD1, + 0x2B, 0x5D, 0x30, 0x2E, 0x2E, 0x9B, 0x0A, 0x7E, + 0x23, 0x9F, 0x03, 0xFA, 0x3A, 0x53, 0x41, 0xF0, + 0x01, 0xCA, 0x0E, 0xFB, 0x18, 0x25, 0x29, 0xAC, + 0x2C, 0xE3, 0x34, 0x1C, 0x4B, 0xFF, 0x03, 0xC6, + 0x11, 0xAA, 0x17, 0xEC, 0x1B, 0x6F, 0x1D, 0x89, + 0x1F, 0xF3, 0x20, 0x96, 0x21, 0x64, 0x28, 0xFE, + 0x2F, 0x14, 0x0F, 0xE1, 0x42, 0x75, 0x43, 0x87, + 0x4A, 0x06, 0x03, 0xE6, 0xB7, 0x14, 0x40, + 0x18, 0x91, 0xC8, 0x20, 0x1A, 0x10, 0xB6, + 0x2F, 0xD2, 0x31, 0x72, 0x18, 0xF8, 0x37, 0xAF, + 0xC8, 0x3C, 0xF8, 0x04, 0xA9, 0x05, 0xD9, + 0x0B, 0x73, 0x10, 0x8F, 0x11, 0x90, 0x12, 0x55, + 0x44, 0xE4, 0x48, 0x64, 0x02, 0xB7, 0xE8, + 0x04, 0xDD, 0xC3, 0xA7, 0x05, 0xEC, + 0x06, 0xE8, 0xDE, 0x66, 0x08, 0x17, + 0x0B, 0x68, 0xD6, 0xFE, 0x0D, 0xB5, + 0xD1, 0x89, 0x82, 0x89, + 0x10, 0x84, 0x86, 0xD6, 0x11, 0x70, + 0x14, 0x7F, 0x85, 0xD7, 0x15, 0x8C, + 0x66, 0x18, 0x07, 0x85, 0xA1, + 0xC9, 0x19, 0x7E, 0x1A, 0xA2, 0x1C, 0x1F, + 0x96, 0x1E, 0xBC, 0x1F, 0x88, 0x20, 0x09, + 0xCF, 0x23, 0x3C, 0x67, 0xC1, + 0x27, 0xC7, 0x29, 0x01, 0x2A, 0x5D, 0x2B, 0x01, + 0xE4, 0x2B, 0xF0, 0x2C, 0xE0, 0xB1, + 0x2E, 0xA7, 0x2F, 0x39, 0x32, 0x96, 0x35, 0xD6, + 0x36, 0x8B, 0x37, 0x49, 0x3A, 0x5D, 0x3A, 0xF3, + 0x3C, 0x1F, 0x9D, 0x98, 0x9F, + 0x3E, 0x61, 0xFD, 0x43, 0xA4, 0x44, 0x66, + 0x45, 0x7E, 0x46, 0x18, 0x48, 0x9C, 0x49, 0x98, + 0x00, 0x0A, 0x53, 0x96, 0xB9, + 0x03, 0x97, 0x04, 0x70, 0x09, 0xCE, 0xE6, + 0x0A, 0xCC, 0x0D, 0x22, 0x10, 0x38, 0x12, 0xC5, + 0x16, 0xFE, 0x19, 0x61, 0x5C, 0x1F, 0x44, + 0x24, 0xB6, 0x27, 0x73, 0x2C, 0x63, 0x36, 0xB8, + 0x3D, 0x72, 0x43, 0xB8, 0x45, 0x20, 0x08, 0x31, + 0x09, 0xF4, 0x4A, 0xFE, 0x14, 0xED, 0x1B, 0x0D, + 0x1D, 0x96, 0x23, 0xED, 0x30, 0x54, 0x32, 0x77, + 0x34, 0x72, 0x3B, 0xE6, 0x4A, 0xDF, 0x39, 0x55, + 0x41, 0xB1, 0x0E, 0x3B, 0x01, 0x38, 0x01, 0xE1, + 0x7D, 0x07, 0x07, 0x0C, 0x20, 0x0D, 0xDD, + 0x8C, 0x11, 0xC3, 0x13, 0x4E, 0x15, 0x2F, + 0x17, 0xB0, 0x18, 0x4B, 0x1A, 0xEE, 0x1B, 0x9B, + 0x1F, 0x78, 0xF9, 0x27, 0x33, 0x27, 0xB9, + 0x29, 0x1F, 0x2B, 0x5E, 0x2B, 0xE6, 0x2F, 0x33, + 0x33, 0xE3, 0x34, 0xAF, 0x37, 0xAA, 0x3B, 0xAA, + 0x3C, 0x3A, 0x40, 0xAB, 0x41, 0x9B, 0x42, 0x32, + 0x43, 0xDD, 0x49, 0x07, 0x00, 0xBA, 0x87, + 0x04, 0x03, 0x0A, 0x75, 0xF7, 0x0E, 0x0B, + 0x27, 0x1A, 0x0E, 0x3D, 0x33, 0x4E, 0x3C, 0x0A, + 0x41, 0xC5, 0x48, 0x63, 0x49, 0x6D, 0x2D, 0x25, + 0x3C, 0xCF, 0x4A, 0x08, 0x43, 0x62, 0x08, 0xF3, + 0x05, 0xA8, 0x42, 0x17, 0x06, 0x39, 0x09, 0x82, + 0x10, 0x25, 0x15, 0xA8, 0x1E, 0x34, 0x22, 0x8A, + 0x29, 0x61, 0x2E, 0x8B, 0x31, 0xE0, 0x3A, 0x70, + 0x42, 0x42, 0x43, 0x54, 0x45, 0x10, 0x88, + 0x48, 0x8F, 0x26, 0x5E, 0x4C, 0xC4, 0x0F, 0x07, + 0xE2, 0x17, 0x70, 0x19, 0xA2, 0x3F, 0xA8, + 0x48, 0xDB, 0x15, 0x6E, 0x19, 0x49, 0x1B, 0x19, + 0x35, 0xC5, 0x4A, 0x17, 0x48, 0xC0, 0x3A, 0xFE, + 0x21, 0x84, 0x16, 0x7A, 0x0D, 0xF8, 0x00, 0x16, + 0x22, 0x2C, 0x27, 0x5D, 0x18, 0x2F, 0x03, 0xC4, + 0xF2, 0x04, 0xE2, 0x0B, 0xD3, 0x11, 0x81, + 0x12, 0x27, 0x14, 0x10, 0x17, 0x3F, 0xB5, + 0x18, 0x1F, 0xD5, 0x1A, 0xF2, 0x1A, 0x16, + 0x1D, 0x63, 0x20, 0x05, 0x24, 0x72, 0x27, 0x1F, + 0x28, 0xDB, 0x2E, 0xBE, 0x32, 0x56, 0x0A, 0xF0, + 0x3A, 0xFD, 0x3B, 0x7F, 0x3C, 0xA0, 0x5E, + 0xB8, 0x42, 0x1D, 0x43, 0x92, 0x49, 0x52, + 0x87, 0x17, 0x89, 0x2C, 0x0E, 0x33, 0x06, + 0x48, 0xBB, 0x10, 0x2D, 0x12, 0xDC, 0x14, 0x1A, + 0x17, 0xA5, 0xEF, 0x19, 0x90, 0x29, 0xF3, + 0x2C, 0x4D, 0x2E, 0x4D, 0x30, 0x3E, 0x33, 0x0A, + 0x3E, 0xAC, 0x3F, 0x64, 0xFD, 0xFE, + 0x2A, 0xA9, 0x04, 0x07, 0x14, 0xD9, 0x15, 0xA5, + 0x16, 0x42, 0x14, 0x98, 0x3C, 0x2D, 0x2C, 0x83, + 0x2D, 0xC0, 0x3C, 0xAC, 0x48, 0xEA, 0x2F, 0x76, + 0x34, 0x0C, 0x39, 0x49, 0x00, 0xD9, 0x03, 0x48, + 0x05, 0x43, 0x9D, 0x0D, 0xA3, 0xDF, + 0x94, 0x0F, 0xDD, 0x14, 0x26, 0xA1, + 0x16, 0xB0, 0x1A, 0x13, 0xA1, 0x1E, 0xC9, + 0xFC, 0x7F, 0x19, 0xD3, 0x21, 0x5C, + 0x23, 0x4E, 0xAF, 0x17, 0xCB, 0x2C, 0x7F, + 0x2D, 0xAD, 0x2F, 0xDA, 0xF0, 0x31, 0xA8, + 0x33, 0x7A, 0x34, 0x1B, 0x9E, 0x37, 0xA6, + 0x3C, 0x6E, 0x3E, 0xCE, 0x3F, 0xF5, 0x42, 0x78, + 0x52, 0x44, 0xAD, 0x6D, 0x47, 0x83, + 0x4D, 0xAE, 0x04, 0x4D, 0x07, 0x84, 0x21, 0x38, + 0x23, 0x36, 0x03, 0x68, 0x2B, 0x85, 0x30, 0x55, + 0x33, 0xB3, 0x2E, 0xCE, 0x08, 0x4C, 0x0A, 0x51, + 0x0E, 0xA8, 0x15, 0xAA, 0x18, 0xFE, 0x52, + 0x1B, 0x5A, 0x24, 0xD9, 0x27, 0x8F, 0x52, + 0x2B, 0x0E, 0xC8, 0x2B, 0xDF, 0x2E, 0x97, + 0x2F, 0x20, 0xA4, 0x38, 0x07, 0x3C, 0x34, + 0x48, 0x3B, 0x42, 0x61, 0x51, 0x20, 0x02, 0xE7, + 0x04, 0x75, 0x05, 0xCC, 0x96, 0x02, 0x09, + 0x07, 0xAA, 0x0A, 0xEE, 0xE1, 0x24, 0x3D, + 0x0D, 0x8B, 0x0E, 0x64, 0x05, 0x1D, 0x12, 0xE3, + 0x90, 0x15, 0x5C, 0xA7, 0x15, 0x3F, + 0xFC, 0x16, 0xCD, 0x17, 0xE9, 0x18, 0xF9, + 0x0F, 0xE3, 0x1B, 0xCD, 0xB0, 0x21, 0x15, + 0x23, 0xE5, 0x00, 0x89, 0x27, 0xE9, 0x28, 0xF8, + 0x2C, 0x93, 0x2E, 0xDF, 0x2F, 0xCF, 0x2F, 0x9C, + 0x32, 0x61, 0x35, 0x49, 0x8F, 0x36, 0x6C, + 0xD0, 0x37, 0xFB, 0x3A, 0xC5, 0x3F, 0x70, + 0x42, 0x01, 0xEC, 0x45, 0x97, 0x49, 0x1C, + 0x4C, 0x12, 0x02, 0xCF, 0x0A, 0x97, 0x13, 0x8E, + 0x33, 0xD3, 0x37, 0x35, 0x3F, 0x08, 0x42, 0x20, + 0x01, 0xC3, 0x02, 0x74, 0x04, 0x47, 0x05, 0x73, + 0x12, 0x6F, 0x15, 0x49, 0x19, 0x5F, 0x20, 0x2C, + 0x3F, 0xB3, 0x42, 0x1F, 0x01, 0xD7, 0x0E, 0x5E, + 0x3E, 0xCA, 0x17, 0xCF, 0x2F, 0x9A, 0x05, 0x52, + 0x3A, 0x96, 0x03, 0x76, 0x15, 0xC3, 0x0D, 0x58, + 0x93, 0x0E, 0x0A, 0x16, 0x0D, 0x19, 0x51, + 0x42, 0x5C, 0x00, 0xD6, 0x0B, 0x1A, 0x90, + 0x1E, 0x70, 0x3C, 0x51, 0x07, 0x3E, 0x0A, 0x15, + 0x0B, 0xA5, 0x12, 0xF0, 0x14, 0x53, 0x19, 0xC1, + 0x34, 0x35, 0x1B, 0x55, 0x48, 0x40, 0x4B, 0xC4, + 0xE4, 0x01, 0x53, 0x0A, 0x06, 0x0D, 0xFE, + 0x32, 0x10, 0x0E, 0xB1, 0x10, 0x2F, 0x11, 0x85, + 0x12, 0x20, 0x13, 0x4B, 0x14, 0x34, 0x18, 0xFF, + 0x1E, 0xF0, 0x20, 0xDE, 0x32, 0xCE, 0x33, 0x7F, + 0x34, 0xD4, 0x3A, 0x8B, 0x3E, 0xB8, 0x42, 0x00, + 0xAE, 0x48, 0x8A, 0x50, 0xDB, 0x4D, 0xDB, + 0x00, 0xE3, 0x05, 0xF0, 0x0B, 0x27, 0x2D, 0x2C, + 0x43, 0x8D, 0x4A, 0x4C, 0x4F, 0xF9, 0x20, 0xDD, + 0x22, 0x27, 0x05, 0x53, 0x07, 0x44, 0x0D, 0x85, + 0x14, 0x58, 0xC6, 0xB5, 0x1E, 0xA2, + 0x21, 0xEF, 0x26, 0x22, 0x3C, 0x17, 0x46, 0x38, + 0x21, 0xC1, 0x3C, 0xFE, 0x35, 0x38, 0x03, 0xE7, + 0x38, 0xF8, 0x05, 0xEA, 0x52, 0x01, 0x46, + 0x42, 0x54, 0x41, 0xB0, 0x0B, 0x6A, 0x33, 0x31, + 0x0F, 0xFD, 0x2C, 0xEA, 0x41, 0xBF, 0x1A, 0xDA, + 0x3E, 0x37, 0x24, 0xF8, 0x4E, 0x48, 0x1C, 0x3D, + 0x3C, 0xB0, 0x00, 0x39, 0x05, 0x58, 0x08, 0x06, + 0x09, 0x66, 0x14, 0xC5, 0x15, 0xA2, 0x17, 0xE6, + 0x1D, 0x4E, 0x1F, 0xE1, 0xFA, 0x22, 0xAD, + 0x29, 0xED, 0x2C, 0xEF, 0x2D, 0xAA, 0x2F, 0xBB, + 0x32, 0x3D, 0x32, 0xC6, 0x38, 0xCB, 0x3C, 0x95, + 0x45, 0x5B, 0x08, 0xE3, 0x0A, 0xC7, 0x11, 0x3E, + 0x17, 0xAD, 0x18, 0x96, 0x1C, 0x80, 0x1D, 0xB5, + 0x27, 0x37, 0x3C, 0xC7, 0x02, 0x24, 0x29, 0xE5, + 0x09, 0x30, 0x11, 0x1B, 0x12, 0x65, 0x18, 0x7A, + 0x1E, 0x60, 0x27, 0xF4, 0x2C, 0x1A, 0x31, 0x6E, + 0x33, 0xF4, 0x39, 0x18, 0x42, 0x45, 0x4B, 0xB3, + 0x2D, 0xC9, 0x27, 0x5C, 0x2C, 0xF9, 0xD8, + 0x36, 0xC4, 0x42, 0x10, 0x2B, 0xE9, 0x2C, 0x92, + 0x35, 0x36, 0x0C, 0xE1, 0x29, 0x40, 0x00, 0x2D, + 0x00, 0xF2, 0x0D, 0x99, 0x11, 0xE0, 0x14, 0xBD, + 0x18, 0x3C, 0x19, 0xF1, 0x1E, 0xE8, 0x38, 0x6B, + 0x3A, 0x77, 0x3C, 0x3B, 0x43, 0x4E, 0x44, 0xF3, + 0x4B, 0xD0, 0x1C, 0x17, 0x22, 0x26, 0x25, 0x2A, + 0x34, 0xE7, 0x36, 0x57, 0x3E, 0xAF, 0x00, 0x01, + 0x03, 0x46, 0x03, 0xCB, 0x07, 0x8B, 0x0D, 0xF5, + 0x10, 0x16, 0x9D, 0xCE, 0x11, 0x14, + 0xA1, 0xB6, 0xC9, 0x13, 0xF2, + 0x15, 0x11, 0x18, 0xA2, 0xFB, 0x21, 0x6E, + 0x24, 0x52, 0x27, 0x3A, 0x29, 0x3A, 0x32, 0x74, + 0x33, 0x39, 0xBF, 0x39, 0x76, 0x3C, 0xBF, + 0x9D, 0x3F, 0x85, 0xEE, 0x44, 0x9A, + 0x47, 0x77, 0x4A, 0x02, 0x4E, 0xE5, 0x04, 0xC5, + 0x15, 0x57, 0x28, 0xF4, 0x19, 0x15, 0x1E, 0x88, + 0x25, 0xCD, 0x3E, 0xC3, 0x45, 0xAE, 0x48, 0x73, + 0x1F, 0x25, 0x0A, 0x9C, 0x1B, 0x0E, 0x1B, 0xCC, + 0x41, 0xFD, 0x45, 0x9A, 0x27, 0xDB, 0x42, 0x1A, + 0x0A, 0x5A, 0x1A, 0x02, 0x15, 0xB4, 0x1B, 0xFB, + 0x01, 0x43, 0x21, 0x2C, 0x19, 0xD8, 0x41, 0xBB, + 0x37, 0x26, 0x2F, 0xB4, 0x45, 0x54, 0x1B, 0x3F, + 0x21, 0x70, 0x09, 0x6A, 0x0A, 0xF7, 0x0D, 0x2C, + 0x2F, 0x2C, 0x24, 0x2A, 0x06, 0x0A, 0x43, 0xE3, + 0x4F, 0xB4, 0x00, 0xAD, 0x01, 0x4E, 0x02, 0x5C, + 0x99, 0x04, 0x43, 0x3E, 0x9E, 0x06, 0x48, + 0x0A, 0x24, 0x0D, 0x9A, 0x10, 0x1D, 0xF8, + 0x98, 0xCA, 0xA8, 0x12, 0x8C, + 0x14, 0xB5, 0x15, 0x3A, 0x15, 0xD0, 0x1A, 0xAF, + 0x1E, 0x40, 0x2A, 0x87, 0x2B, 0x8E, 0xFD, + 0x2F, 0xE0, 0x34, 0x47, 0x3C, 0x02, 0x3C, 0xE6, + 0x40, 0x44, 0x42, 0x13, 0x42, 0xB8, 0xF5, + 0x43, 0xD8, 0x51, 0x0E, 0x1E, 0xE5, 0x16, 0x58, + 0x16, 0xE2, 0x17, 0x75, 0x20, 0xF4, 0x28, 0x84, + 0x2D, 0x1B, 0x42, 0x69, 0x45, 0xD1, 0x20, 0xBA, + 0x06, 0xF2, 0x11, 0xB9, 0x16, 0xA4, 0x41, 0x4D, + 0x41, 0xED, 0x44, 0x44, 0x03, 0x78, 0x0A, 0x6B, + 0x0B, 0x29, 0x0E, 0x55, 0x10, 0x97, 0x1F, 0xFB, + 0x30, 0x8F, 0x27, 0x1C, 0x3E, 0xBC, 0x40, 0xE2, + 0x4A, 0x5B, 0x22, 0xB9, 0x01, 0x1D, 0x1D, 0xBF, + 0x21, 0xB1, 0x27, 0x30, 0x48, 0xFB, 0x03, 0x4E, + 0x06, 0x10, 0x0A, 0x35, 0xA2, 0x0B, 0xAC, + 0x0E, 0x60, 0x11, 0x92, 0x17, 0x97, 0x19, 0x5C, + 0x20, 0x21, 0x28, 0x7B, 0x35, 0xDF, 0x3E, 0xED, + 0x42, 0x14, 0x42, 0xFD, 0x45, 0x4D, 0x2A, 0x25, + 0x95, 0x04, 0xAA, 0x10, 0xA6, 0x09, 0x1F, + 0x0B, 0x74, 0x12, 0x12, 0x02, 0x12, 0x03, 0x5A, + 0xD2, 0xA1, 0xB3, 0x07, 0x10, + 0x0A, 0x54, 0x84, 0x0B, 0x57, 0x0D, 0x95, + 0x0E, 0xF6, 0x0F, 0x8B, 0x12, 0xBC, 0x14, 0x95, + 0x16, 0x2D, 0x19, 0x71, 0x1A, 0x43, 0xF9, + 0xA3, 0x28, 0xD7, 0x1F, 0xD8, 0x20, 0x6F, + 0x1F, 0x9B, 0x22, 0x6F, 0x23, 0xC8, 0x11, 0x53, + 0x27, 0xD8, 0x2B, 0x77, 0x2D, 0x49, 0x8B, + 0x53, 0x2E, 0xD6, 0x2F, 0x71, 0x04, 0x30, + 0x36, 0x63, 0x37, 0x69, 0xFB, 0x3C, 0x0E, + 0x3D, 0x04, 0x3E, 0x46, 0x40, 0x0F, 0x42, 0x03, + 0x8C, 0x46, 0x19, 0x48, 0x76, 0x4A, 0x2D, + 0x4C, 0x30, 0x47, 0xD8, 0x02, 0xCD, 0x04, 0xD5, + 0x06, 0x0C, 0x0A, 0x02, 0x0E, 0x0E, 0x13, 0xA7, + 0x16, 0x9E, 0x1F, 0x1E, 0x29, 0xB3, 0x2C, 0xE5, + 0x32, 0xF4, 0x36, 0x04, 0x42, 0x53, 0x44, 0x85, + 0x0E, 0xE0, 0x4F, 0x07, 0x05, 0x3F, 0x11, 0x97, + 0x9C, 0x1F, 0x9C, 0x24, 0x79, 0x29, 0x63, + 0x2B, 0xBF, 0x2D, 0xE4, 0x1D, 0xD2, 0x24, 0xEC, + 0x3C, 0xAD, 0x1A, 0x03, 0x1C, 0x61, 0x03, 0xF8, + 0x2C, 0x81, 0x1B, 0x34, 0x0E, 0x4A, 0x4E, 0xF6, + 0x34, 0xEB, 0x0D, 0xC5, 0x43, 0x49, 0x22, 0x1E, + 0x08, 0x78, 0x0E, 0x6F, 0x12, 0xC7, 0x17, 0x66, + 0x1E, 0x8C, 0x3E, 0x5A, 0x42, 0x41, 0x4A, 0x13, + 0x06, 0x51, 0x18, 0xC7, 0x44, 0x0D, 0x0B, 0x48, + 0x42, 0xA3, 0x03, 0x85, 0x00, 0x4D, 0x03, 0xEA, + 0x37, 0x99, 0x3D, 0x0E, 0x22, 0x58, 0x15, 0x7A, + 0x45, 0x4B, 0x1B, 0x62, 0x4B, 0xB4, 0x30, 0x04, + 0x27, 0x77, 0x05, 0x57, 0x1B, 0x60, 0x40, 0xDF, + 0x48, 0xE3, 0x1E, 0x5D, 0x00, 0x8C, 0x0E, 0x3C, + 0x11, 0x10, 0x41, 0xE9, 0x05, 0x02, 0x3E, 0xD1, + 0x32, 0x89, 0x38, 0x79, 0x10, 0xFF, 0x17, 0xE5, + 0x00, 0x73, 0x03, 0x65, 0x0B, 0x82, 0x0E, 0x3F, + 0x49, 0xEE, 0x00, 0xFB, 0x0B, 0x8A, 0x11, 0xCD, + 0x3C, 0x8D, 0x21, 0xE1, 0x2B, 0xB0, 0x2B, 0x62, + 0x0D, 0xE7, 0x36, 0x71, 0x25, 0x2B, 0x23, 0xB1, + 0x10, 0x74, 0x11, 0xF5, 0x15, 0x7B, 0x16, 0x9A, + 0x23, 0xC3, 0x2E, 0x98, 0x00, 0x43, 0x10, 0xFC, + 0x00, 0x4B, 0x09, 0xDC, 0x08, 0xA2, 0x12, 0xA9, + 0x21, 0xC3, 0x2F, 0x0D, 0x32, 0xFD, 0xB6, + 0x33, 0xBF, 0x41, 0xB2, 0x3B, 0x97, 0x38, 0xA4, + 0x0F, 0xF4, 0x14, 0x8A, 0x16, 0xAD, 0x3B, 0x87, + 0x19, 0x77, 0x1E, 0xE2, 0xDC, 0x26, 0x36, + 0x2A, 0x34, 0x0C, 0x46, 0x31, 0x75, 0x34, 0xAD, + 0x4B, 0xAC, 0x01, 0xF3, 0x10, 0xC3, 0x14, 0xDD, + 0x15, 0x92, 0x17, 0x57, 0x19, 0x6F, 0x28, 0xC3, + 0x24, 0x4C, 0x32, 0xCC, 0x63, 0x41, 0x29, + 0x43, 0x4D, 0x02, 0x0D, 0x09, 0xF9, 0x0C, 0x92, + 0x1A, 0x85, 0x1B, 0x73, 0x23, 0x64, 0x24, 0xFD, + 0x3E, 0xB7, 0x0A, 0xF2, 0x3E, 0xE0, 0x48, 0x6A, + 0x42, 0x19, 0x39, 0x7F, 0x2B, 0xE4, 0x29, 0xE7, + 0x36, 0x29, 0x01, 0x2F, 0x04, 0x65, 0x05, 0x5A, + 0x14, 0xCD, 0x19, 0xCF, 0x1E, 0xCA, 0x28, 0x7D, + 0x2D, 0x94, 0x2E, 0x95, 0x34, 0x36, 0x37, 0x84, + 0x41, 0xEB, 0x18, 0xDD, 0x21, 0x20, 0x24, 0x06, + 0x30, 0x1B, 0x35, 0xAB, 0x4B, 0xC1, 0x50, 0xA6, + 0x03, 0xFD, 0x2D, 0xB1, 0x2A, 0x72, 0x2D, 0xB8, + 0x32, 0x87, 0x2D, 0x48, 0x1C, 0xE8, 0x10, 0x61, + 0x32, 0x8C, 0x27, 0x51, 0x8F, 0x03, 0x6B, + 0x44, 0x62, 0x20, 0x8C, 0x28, 0x7A, 0x43, 0x97, + 0x4C, 0xEA, 0x01, 0x10, 0x31, 0x70, 0x14, 0x9C, + 0x2D, 0x4F, 0x47, 0xA5, 0x4E, 0xE9, 0x08, 0x7A, + 0x0A, 0x59, 0x38, 0xE4, 0x48, 0xBC, 0x01, 0x34, + 0x04, 0x24, 0x05, 0x4A, 0x05, 0xCD, 0x8E, + 0x10, 0x06, 0x16, 0x2C, 0x17, 0x91, 0x19, 0x7F, + 0x1E, 0x3E, 0x90, 0x24, 0x48, 0xE7, + 0x25, 0xED, 0x27, 0x54, 0x30, 0x41, 0x34, 0x2C, + 0x37, 0xE9, 0x3E, 0xA9, 0x2D, 0xC4, 0x43, 0xC6, + 0x23, 0x69, 0x4A, 0x12, 0x4A, 0xEF, 0x15, 0x3D, + 0x18, 0x69, 0x27, 0x6A, 0x28, 0xE4, 0x2A, 0xD0, + 0x37, 0x43, 0x38, 0xEE, 0x05, 0x2A, 0xA7, + 0x06, 0x26, 0x0B, 0x83, 0x10, 0x87, 0x11, 0x7C, + 0x12, 0xB2, 0x14, 0x49, 0xB0, 0xB2, + 0x17, 0x90, 0x1D, 0xD4, 0x1E, 0xCC, 0x27, 0xB2, + 0x28, 0xAE, 0x2A, 0x91, 0x2B, 0xD8, 0x2F, 0xCB, + 0x31, 0x77, 0x32, 0xA5, 0x3A, 0xAB, 0x3C, 0xB9, + 0x3E, 0xBB, 0x42, 0x7F, 0x49, 0x5E, 0x4A, 0xDB, + 0x1C, 0x0B, 0x2E, 0x38, 0x02, 0x99, 0x0E, 0x3E, + 0x11, 0xAE, 0x19, 0x87, 0x1D, 0xD8, 0x26, 0x35, + 0x29, 0x09, 0x31, 0x8E, 0x51, 0x3B, 0x19, 0xCA, + 0x2C, 0x17, 0x05, 0x39, 0x27, 0x8B, 0x4C, 0xED, + 0x11, 0x66, 0x33, 0x9D, 0x35, 0xF1, 0x32, 0x98, + 0x11, 0x3C, 0x11, 0xC5, 0x27, 0x62, 0x2D, 0x46, + 0x42, 0x3C, 0x1A, 0x67, 0x0B, 0xEB, 0x0C, 0x9B, + 0x2F, 0x10, 0x28, 0x7E, 0x3D, 0x2C, 0x01, 0xF5, + 0x11, 0x6A, 0x1C, 0x19, 0x1E, 0x37, 0x21, 0x02, + 0x26, 0xE2, 0x2B, 0x68, 0x3A, 0x68, 0x3C, 0x55, + 0x3E, 0x79, 0x10, 0xDF, 0x15, 0xCF, 0x27, 0xC5, + 0x2B, 0xD2, 0x34, 0xD7, 0x45, 0x28, 0x44, 0xF2, + 0x36, 0x9C, 0x38, 0xED, 0x4E, 0x2D, 0x06, 0xC1, + 0x11, 0x6C, 0x17, 0x8C, 0x1F, 0x5C, 0x22, 0x15, + 0x3E, 0xA7, 0xAC, 0x4A, 0x3B, 0x17, 0x4F, + 0x26, 0xF6, 0x00, 0x0D, 0x00, 0xD8, 0x09, 0xE0, + 0x0B, 0x2B, 0x0C, 0x66, 0x0D, 0xCC, 0x03, 0xA8, + 0x10, 0x03, 0x10, 0x9C, 0x12, 0x16, 0x14, 0x76, + 0x17, 0x77, 0xB0, 0x18, 0x6E, 0x1F, 0x6E, + 0x24, 0x36, 0x2D, 0x26, 0x33, 0x50, 0xCA, + 0x34, 0x99, 0x3D, 0x5C, 0x3E, 0xA0, 0xC6, + 0x3F, 0x74, 0x48, 0x1C, 0xA8, 0x01, 0xAE, + 0x16, 0xAB, 0x1D, 0x66, 0x34, 0x1E, 0x36, 0x61, + 0x37, 0x6A, 0x42, 0xE8, 0x0E, 0x01, 0x1B, 0x53, + 0x4A, 0xA8, 0x36, 0x7A, 0x37, 0x57, 0x01, 0x0F, + 0x04, 0x6F, 0x11, 0xA9, 0x10, 0x45, 0x19, 0x0D, + 0x2B, 0x8F, 0x33, 0x79, 0x3B, 0x07, 0xFF, + 0x1F, 0xF5, 0x11, 0x17, 0x14, 0x55, 0x1E, 0xB8, + 0x00, 0xCF, 0x24, 0x69, 0x4D, 0x92, 0x04, 0x06, + 0x06, 0x3B, 0x08, 0x74, 0x0A, 0xB3, 0x13, 0xA4, + 0x14, 0x6E, 0x23, 0x1A, 0x0B, 0x6E, 0x2E, 0x89, + 0xD5, 0xBD, 0x48, 0xF0, 0x17, 0x87, + 0x32, 0x5E, 0x00, 0x19, 0x01, 0x75, 0x03, 0x75, + 0x0A, 0x40, 0x10, 0x63, 0x90, 0x11, 0x0A, + 0x19, 0xC4, 0x00, 0x26, 0x37, 0x3D, 0x47, 0x89, + 0x48, 0x5B, 0x2E, 0x73, 0x4A, 0x01, 0x02, 0xFB, + 0x0A, 0xC1, 0x28, 0x56, 0x2A, 0xA7, 0x04, 0x25, + 0x29, 0xA5, 0x37, 0x11, 0x2D, 0x86, 0x02, 0x4F, + 0x0B, 0x09, 0x24, 0x47, 0x2D, 0xC7, 0x2F, 0xE8, + 0x41, 0xBA, 0x9A, 0xF9, 0x01, 0xBF, + 0x04, 0xC9, 0x0C, 0x29, 0x11, 0x01, 0x49, 0xAD, + 0x01, 0xDD, 0x34, 0x17, 0x44, 0xEA, 0x09, 0x03, + 0x15, 0x55, 0x1D, 0x69, 0x27, 0x2B, 0x3A, 0xDC, + 0x41, 0x14, 0x2C, 0x42, 0x04, 0xDF, 0x0A, 0x93, + 0x13, 0x55, 0x14, 0x0A, 0x18, 0xAE, 0x1D, 0xCD, + 0x2E, 0x3F, 0x35, 0xE9, 0x02, 0x23, 0x7C, + 0x05, 0x05, 0x06, 0x46, 0x0A, 0x31, 0x0B, 0x49, + 0x0D, 0x9D, 0x0E, 0xF0, 0x52, 0xBA, + 0x10, 0x96, 0x14, 0xB1, 0x15, 0x67, 0x17, 0x3E, + 0xFB, 0x19, 0x0B, 0x1E, 0xD5, 0x8C, + 0x22, 0xF9, 0x2A, 0x32, 0x30, 0x2B, 0x32, 0xDE, + 0x34, 0xB3, 0x36, 0x0C, 0x36, 0xEC, 0x39, 0x02, + 0x3B, 0x12, 0x3C, 0x2A, 0x3E, 0x4A, 0x42, 0xA6, + 0x44, 0xD2, 0x4A, 0xFD, 0x4E, 0xF3, 0xF9, + 0x00, 0x4F, 0xD2, 0x02, 0x8D, 0x04, 0x56, + 0x09, 0x4A, 0x0B, 0xA8, 0x10, 0x3D, 0x11, 0xD8, + 0x81, 0x14, 0x3F, 0x18, 0xB4, 0xE7, + 0x19, 0xD0, 0x1A, 0xD2, 0x03, 0x92, 0x2F, 0x21, + 0x32, 0xAA, 0x33, 0xA8, 0x3D, 0x00, 0x3E, 0x8C, + 0xB3, 0x44, 0x7E, 0x48, 0x32, 0x06, 0x20, + 0x4A, 0x2C, 0x05, 0x17, 0x02, 0xD5, 0x05, 0x5C, + 0x0A, 0xA8, 0x16, 0xB2, 0x19, 0x34, 0x24, 0x67, + 0x29, 0x66, 0x2C, 0x46, 0x43, 0xE6, 0x04, 0xC3, + 0x1E, 0xA1, 0x1D, 0x86, 0x0A, 0x00, 0x10, 0x4C, + 0x0B, 0x54, 0x19, 0x2C, 0x31, 0xFB, 0x03, 0xE1, + 0x28, 0xC6, 0x16, 0x69, 0x2A, 0xE8, 0x4D, 0x54, + 0x50, 0xBB, 0x09, 0xCB, 0x0B, 0xB9, 0x18, 0x27, + 0x19, 0x9A, 0x1D, 0xCE, 0x06, 0xE9, 0x1B, 0xD9, + 0x10, 0x55, 0x33, 0x9C, 0x19, 0x95, 0x4D, 0xAA, + 0x19, 0xFE, 0x4E, 0x52, 0x1A, 0x5D, 0x00, 0xA6, + 0x01, 0xE3, 0x05, 0xC8, 0x14, 0xB9, 0x19, 0x2B, + 0x1E, 0xAB, 0x41, 0xC4, 0x01, 0xAD, 0x30, 0x6D, + 0x50, 0xBF, 0x00, 0x07, 0x13, 0x62, 0x20, 0x80, + 0x21, 0x2B, 0x37, 0x13, 0x06, 0x73, 0x19, 0x2A, + 0x4D, 0x45, 0x0F, 0xF3, 0x2D, 0x95, 0x0E, 0xAC, + 0x0D, 0xC6, 0x39, 0x1C, 0x20, 0x4A, 0x36, 0xD1, + 0x2C, 0x14, 0x33, 0x08, 0x0B, 0x99, 0x2E, 0x8D, + 0x1E, 0x11, 0x29, 0x20, 0x04, 0xD9, 0x0B, 0x22, + 0x23, 0x21, 0x24, 0x5F, 0x29, 0xDB, 0x49, 0x27, + 0x4F, 0x61, 0x1B, 0x0B, 0x0C, 0x7F, 0x0C, 0x18, + 0x03, 0xA5, 0x06, 0x0D, 0xF0, 0x18, 0x0E, + 0x28, 0xDF, 0x41, 0xF7, 0x44, 0x98, 0x4E, 0xF4, + 0x0B, 0xEA, 0x24, 0x5D, 0x20, 0xC5, 0x03, 0x4D, + 0x1A, 0xC9, 0x2F, 0xBF, 0xAD, 0x49, 0x62, + 0x50, 0xBA, 0x16, 0x78, 0x1C, 0x21, 0x35, 0x02, + 0x0B, 0x84, 0x0D, 0x5F, 0x1D, 0xDB, 0x25, 0x1B, + 0x28, 0xF2, 0x2F, 0xB2, 0x32, 0x17, 0x36, 0x99, + 0x03, 0x32, 0x19, 0x28, 0x50, 0xD9, 0x28, 0xEE, + 0x19, 0x62, 0x04, 0xFF, 0x4B, 0x05, 0x0E, 0x24, + 0x14, 0x3B, 0x2E, 0x7E, 0x3E, 0xB0, 0x07, 0x4F, + 0x12, 0xB6, 0x2F, 0x0B, 0x47, 0x80, 0x05, 0x01, + 0x00, 0x5F, 0x03, 0xB6, 0x0B, 0x1C, 0x24, 0x3A, + 0x32, 0x36, 0x43, 0xCE, 0x11, 0x25, 0x29, 0xE2, + 0x05, 0x84, 0x11, 0x79, 0x2F, 0x04, 0x37, 0xAC, + 0x3C, 0x33, 0x40, 0x8D, 0x49, 0x56, 0x19, 0xF3, + 0x37, 0xAE, 0x46, 0x53, 0x13, 0x09, 0x52, + 0x1E, 0xB9, 0x28, 0x52, 0x3C, 0xED, 0x41, 0x38, + 0x07, 0x2F, 0x01, 0x51, 0x03, 0x2A, 0x04, 0xC7, + 0x05, 0xCB, 0x0D, 0xA5, 0x10, 0x7D, 0x12, 0xA0, + 0x13, 0x82, 0x15, 0xD6, 0x19, 0x09, 0x19, 0xDA, + 0x20, 0x67, 0x1F, 0x8C, 0x25, 0x36, 0x81, + 0x27, 0x31, 0x2B, 0x50, 0x3A, 0xD5, 0x3C, 0x98, + 0x42, 0x4A, 0xC7, 0xE4, 0x48, 0xC4, + 0x39, 0x8D, 0x0B, 0x15, 0x00, 0x88, 0x01, 0x59, + 0x00, 0x0E, 0x3C, 0x89, 0x41, 0x3F, 0x4A, 0x10, + 0x02, 0xAD, 0x10, 0x7C, 0x0B, 0x96, 0x0D, 0xB9, + 0x10, 0xB8, 0x15, 0xDA, 0xA0, 0x16, 0xC1, + 0x18, 0xDC, 0x1B, 0x4A, 0x1B, 0xD8, 0x1F, 0x0B, + 0x20, 0xB6, 0x23, 0x94, 0x27, 0x28, 0x2C, 0xAF, + 0x31, 0x8A, 0xF6, 0x36, 0x49, 0x36, 0xC9, + 0x3B, 0x81, 0x3D, 0x21, 0x40, 0x0A, 0x42, 0x65, + 0x48, 0x7D, 0x4B, 0x0A, 0x13, 0x7E, 0x14, 0x91, + 0x1D, 0x32, 0x1E, 0x83, 0x1F, 0x74, 0x31, 0xCC, + 0xB0, 0x1F, 0xC0, 0x31, 0x85, 0x39, 0xBA, + 0x3A, 0xF8, 0x19, 0x65, 0x35, 0xB1, 0x4A, 0x3C, + 0x48, 0xF7, 0x1F, 0x1B, 0x2F, 0x61, 0x36, 0x3D, + 0x43, 0x6A, 0x00, 0x71, 0x05, 0x75, 0x0F, 0x50, + 0x1D, 0x04, 0x21, 0xEB, 0x37, 0xCD, 0xE0, + 0x3B, 0xA7, 0x04, 0x29, 0x06, 0x0F, 0x0E, 0x65, + 0x19, 0x4E, 0x1A, 0xA8, 0x26, 0x06, 0xFD, + 0x27, 0xE2, 0x3A, 0xCF, 0x92, 0x43, 0xCC, + 0x48, 0xE2, 0x48, 0x78, 0x11, 0x8B, 0x25, 0x87, + 0x2C, 0xCB, 0x36, 0x4E, 0x15, 0xA0, 0x27, 0x65, + 0x04, 0x89, 0x1F, 0x41, 0x20, 0x9C, 0x26, 0x09, + 0x27, 0x59, 0x2A, 0x6B, 0x2E, 0x92, 0x48, 0x86, + 0x2C, 0xDC, 0x51, 0x8D, 0x01, 0xB6, 0x13, 0x6E, + 0x17, 0xC5, 0x38, 0x5C, 0x00, 0x86, 0xA8, + 0x02, 0xDA, 0x00, 0x21, 0x03, 0xCC, 0x0D, 0xEE, + 0x17, 0x99, 0x1A, 0x81, 0x1F, 0xBC, 0x25, 0x1F, + 0x28, 0x42, 0x29, 0xAD, 0x2C, 0x1C, 0x2E, 0xE7, + 0x34, 0x6F, 0x3C, 0xD2, 0x42, 0x7C, 0x43, 0xCF, + 0x48, 0x75, 0x4A, 0x18, 0x04, 0x9B, 0x2F, 0xD1, + 0x02, 0x2B, 0x05, 0x98, 0x19, 0x97, 0x1F, 0xCB, + 0x23, 0xD0, 0x26, 0x33, 0x33, 0xE8, 0x41, 0x2A, + 0x48, 0xA3, 0x4E, 0x57, 0x50, 0x9F, 0x26, 0x60, + 0x0A, 0x41, 0x1F, 0x99, 0x2F, 0x2F, 0x4A, 0x5E, + 0x00, 0xE4, 0xD2, 0xD5, 0x03, 0xB7, + 0x04, 0xB1, 0x0F, 0xBA, 0x12, 0x1C, 0x25, 0xB2, + 0x2B, 0x3C, 0x34, 0xD3, 0x44, 0x34, 0x48, 0xB7, + 0xBF, 0x94, 0x50, 0x97, 0x51, 0x62, + 0x18, 0xA6, 0x1D, 0x74, 0x04, 0x17, 0x04, 0xA3, + 0x22, 0xC8, 0x3A, 0xC2, 0x10, 0xC9, 0x12, 0x4B, + 0x13, 0x90, 0x21, 0x23, 0x23, 0x49, 0x2E, 0x3E, + 0x2F, 0xF4, 0x32, 0x6F, 0x36, 0xEE, 0x42, 0x23, + 0x45, 0x2C, 0x06, 0x42, 0x4D, 0x6F, 0x1C, 0xD3, + 0x22, 0x89, 0x3E, 0xC2, 0x3F, 0xEF, 0x49, 0x32, + 0x04, 0xB4, 0x0C, 0x41, 0x10, 0xCA, 0xBA, + 0x19, 0x17, 0x1B, 0x7C, 0x98, 0x1F, 0x6A, + 0x21, 0x0F, 0x24, 0x62, 0x24, 0xFC, 0x2D, 0xED, + 0x32, 0x01, 0xFD, 0x39, 0x4B, 0x42, 0xCE, + 0x03, 0x6D, 0x50, 0x93, 0x2B, 0x84, 0x32, 0x8B, + 0x45, 0x32, 0x3C, 0xD6, 0x02, 0x2D, 0x06, 0x8C, + 0x3C, 0x71, 0x1D, 0x6A, 0x3E, 0xC4, 0x33, 0x07, + 0x12, 0xD1, 0x19, 0xA0, 0x4F, 0xF2, 0x00, 0x99, + 0x52, 0x4E, 0x10, 0x3C, 0x6B, 0x37, 0xC1, + 0x37, 0x68, 0x1B, 0x00, 0x20, 0x7E, 0x2A, 0x97, + 0x33, 0x55, 0x11, 0x0C, 0x00, 0x10, 0x85, + 0x95, 0x87, 0x85, 0x86, + 0x83, 0x83, 0x94, 0x82, + 0xAA, 0x83, 0x3E, 0x6B, 0x00, 0x8A, + 0x34, 0x12, 0x11, 0x0D, 0x00, 0x8E, 0x90, + 0x81, 0x81, 0x82, 0x8E, + 0x83, 0x83, 0x98, 0x52, + 0x5A, 0x82, 0x55, 0x95, + 0x87, 0x8F, 0x5F, 0x98, + 0x92, 0xD1, 0x7B, 0xAB, + 0x82, 0x57, 0x61, 0xAF, + 0x92, 0x87, 0x89, 0x6E, + 0x63, 0x87, 0xA1, 0x73, + 0x97, 0x90, 0x03, 0x18, 0x01, 0xD4, + 0x8B, 0x62, 0x8A, 0x83, + 0x5B, 0x89, 0x5B, 0x94, + 0x81, 0xB5, 0x8E, 0x65, + 0x96, 0x56, 0x71, 0x01, 0x1C, + 0x01, 0xF6, 0xAB, 0x88, 0x83, + 0x7F, 0x60, 0xA2, 0x5C, + 0xBD, 0x84, 0x19, 0x03, 0x02, 0x55, + 0x56, 0x59, 0x92, 0x55, + 0x96, 0x8C, 0x88, 0x9A, + 0x66, 0xAF, 0x53, 0x97, + 0x81, 0x68, 0x8F, 0x94, + 0x88, 0x87, 0x88, 0x5B, + 0x8B, 0x8B, 0x55, 0x94, + 0x59, 0x81, 0x94, 0x52, + 0x52, 0x86, 0x87, 0x99, + 0x54, 0x85, 0x52, 0x84, + 0x81, 0x92, 0x57, 0x88, + 0x8E, 0x2C, 0xF8, 0x03, 0x69, 0x81, + 0x84, 0x92, 0x82, 0x08, 0xD8, + 0x03, 0x8C, 0x54, 0x86, 0x82, + 0x82, 0x82, 0x81, 0x8E, + 0x82, 0x55, 0x87, 0x81, + 0x81, 0x88, 0x53, 0x81, + 0x53, 0x85, 0x88, 0x88, + 0x84, 0x92, 0x85, 0x38, 0x55, + 0x03, 0xE9, 0x84, 0x83, 0x85, + 0x89, 0x86, 0x87, 0x89, + 0x57, 0x99, 0x83, 0x84, + 0x85, 0x86, 0x96, 0x5C, + 0x87, 0x81, 0x92, 0x5B, + 0x96, 0x8A, 0x5C, 0x8A, + 0x8C, 0x53, 0x90, 0x87, + 0x53, 0x72, 0x97, 0x89, + 0x41, 0xA8, 0x52, 0x04, 0xAC, 0x81, + 0x8F, 0x58, 0x8C, 0x8C, + 0x8A, 0x87, 0x85, 0x83, + 0x4A, 0xED, 0x04, 0xE0, 0x93, 0x82, + 0x83, 0x81, 0x8D, 0x82, + 0x27, 0x38, 0x05, 0x0D, 0x83, 0x52, + 0x86, 0x85, 0x89, 0x8C, + 0x82, 0x82, 0x85, 0x88, + 0x86, 0x52, 0x00, 0x17, 0x05, 0x49, + 0x84, 0x03, 0xD6, 0x05, 0x5E, 0x8B, + 0x85, 0x0B, 0x18, 0x05, 0x7B, 0x55, + 0x8B, 0x94, 0x8A, 0x86, + 0x52, 0x89, 0x82, 0x86, + 0x8D, 0x2E, 0x12, 0x48, 0xD9, 0x05, 0xDF, + 0x18, 0xFC, 0x23, 0xEE, 0x05, 0xEE, 0x57, + 0x85, 0x8D, 0x87, 0xBC, + 0x83, 0x65, 0x81, 0x8F, + 0x5F, 0x88, 0x5E, 0x5D, + 0xB1, 0xC1, 0x6B, 0x99, + 0x80, 0x92, 0x86, 0x58, + 0xA2, 0x68, 0x85, 0x5B, + 0x8E, 0x8C, 0x5B, 0xC1, + 0x76, 0x96, 0x64, 0x87, + 0x98, 0x84, 0x71, 0x83, + 0x97, 0x6F, 0x9A, 0x53, + 0x9C, 0x8D, 0x81, 0xA9, + 0x85, 0x68, 0x60, 0x52, + 0x8D, 0x69, 0xD7, 0x87, + 0xA3, 0x68, 0x6F, 0xAE, + 0x68, 0x91, 0x81, 0x70, + 0x56, 0xAA, 0xBC, 0x6A, + 0x06, 0xAF, 0x07, 0x8A, 0x95, 0x75, + 0x83, 0x9A, 0x86, 0x90, + 0x07, 0x7C, 0x87, 0xA6, 0x73, + 0xA1, 0xB2, 0x66, 0x9A, + 0x6C, 0x98, 0x88, 0x61, + 0xC0, 0x6E, 0x9F, 0x69, + 0x52, 0x9E, 0x73, 0xD5, + 0x82, 0x23, 0xDF, 0x08, 0x34, 0x82, + 0x55, 0x86, 0xB3, 0x58, + 0x08, 0x2F, 0xBD, 0x53, 0x9C, + 0x57, 0x8A, 0x96, 0x5D, + 0x56, 0x96, 0x89, 0x88, + 0x53, 0x8E, 0x57, 0x85, + 0x82, 0x54, 0x88, 0x86, + 0x83, 0x82, 0x84, 0x97, + 0x8B, 0x87, 0x52, 0x85, + 0x85, 0x52, 0x83, 0x82, + 0x86, 0x85, 0x53, 0x07, 0xC7, + 0x09, 0x1C, 0x8A, 0x91, 0x81, + 0x96, 0x64, 0x85, 0x8F, + 0x9A, 0xD7, 0x09, 0x88, 0x78, + 0x9E, 0x8A, 0x8A, 0x8D, + 0x93, 0x60, 0x86, 0x86, + 0x93, 0x83, 0x8E, 0x53, + 0x81, 0xB7, 0x09, 0xD6, 0x8D, + 0xA8, 0x8E, 0x84, 0xD5, + 0x0A, 0x21, 0xC1, 0x68, 0xA5, + 0x1D, 0xC0, 0x0A, 0x52, 0x66, 0xBC, + 0x8C, 0xB4, 0x6B, 0x8C, + 0x8F, 0xA4, 0x74, 0x54, + 0x5B, 0x97, 0x8E, 0x53, + 0x86, 0x82, 0x52, 0x8D, + 0x5A, 0x88, 0x56, 0x90, + 0x8B, 0x52, 0x82, 0x81, + 0x81, 0x85, 0x88, 0x86, + 0x8B, 0x1A, 0xA6, 0x0B, 0x25, 0x87, + 0x81, 0x85, 0x86, 0x86, + 0x2C, 0xD2, 0x0B, 0x55, 0x56, 0x53, + 0x8C, 0x53, 0x8A, 0x53, + 0x87, 0x85, 0x54, 0x8F, + 0x89, 0x9C, 0x01, 0x5E, 0xCD, + 0x0B, 0xA3, 0x8F, 0x94, 0xA2, + 0x5D, 0x0B, 0x8D, 0xCC, 0x81, + 0xCB, 0x57, 0x5F, 0x8B, + 0x64, 0x91, 0xA6, 0xAC, + 0x74, 0x65, 0x81, 0xAC, + 0x88, 0xB0, 0xA2, 0x82, + 0x8D, 0x5A, 0x56, 0xA6, + 0x5D, 0x8F, 0x83, 0x64, + 0xA4, 0x81, 0x91, 0x52, + 0x8B, 0x9C, 0x0C, 0xD0, 0xDA, + 0x8C, 0x88, 0x85, 0x82, + 0x56, 0x91, 0x84, 0x85, + 0x81, 0x8A, 0x84, 0x87, + 0x83, 0x82, 0x83, 0x17, 0x88, + 0x0D, 0x7A, 0x86, 0x83, 0xA3, + 0x92, 0x8B, 0x84, 0x82, + 0x8B, 0x55, 0x94, 0x82, + 0x55, 0x55, 0x87, 0x86, + 0x85, 0x86, 0x54, 0x92, + 0x82, 0x81, 0x85, 0x86, + 0x8D, 0x82, 0x86, 0x90, + 0x81, 0x88, 0x85, 0x88, + 0x85, 0x54, 0x52, 0x0D, 0x71, + 0x0E, 0x6C, 0x82, 0x00, 0x62, 0x0E, 0x76, + 0x83, 0x93, 0x85, 0x83, + 0x0B, 0x9B, 0x0E, 0xAB, 0x90, 0x56, + 0x86, 0x56, 0x8E, 0x58, + 0x89, 0x92, 0x90, 0x94, + 0x54, 0x5E, 0x0F, 0x8C, 0x0E, 0xEA, + 0xA1, 0x8A, 0x82, 0xC5, + 0x0F, 0x1F, 0x55, 0x5B, 0x83, + 0x8E, 0x59, 0x52, 0x52, + 0xB4, 0x86, 0x55, 0x54, + 0xA1, 0x87, 0x83, 0x91, + 0x54, 0x53, 0xA0, 0x56, + 0x8F, 0x82, 0x8F, 0x7E, + 0xA7, 0x85, 0x8D, 0x84, + 0x86, 0x52, 0x84, 0x85, + 0x90, 0x87, 0x83, 0x96, + 0x8F, 0x52, 0x59, 0x8A, + 0x9B, 0x81, 0x8D, 0x52, + 0x54, 0x8E, 0x89, 0x54, + 0x8B, 0x83, 0x82, 0x6E, + 0xAE, 0x81, 0x84, 0x50, 0xBC, + 0x10, 0x7F, 0xA1, 0xA1, 0x81, + 0x86, 0x88, 0x52, 0x87, + 0x8D, 0x57, 0x54, 0x81, + 0x87, 0x52, 0x87, 0x81, + 0x83, 0x85, 0x82, 0x54, + 0x84, 0x84, 0x86, 0x85, + 0x86, 0xD4, 0x52, 0x11, 0x0B, + 0x86, 0x85, 0x93, 0x84, + 0x8B, 0x89, 0x87, 0x84, + 0x82, 0x70, 0xA2, 0x85, + 0x81, 0x82, 0x88, 0x8C, + 0x86, 0x84, 0x8C, 0x52, + 0x54, 0x8B, 0x53, 0x89, + 0x5B, 0x97, 0x56, 0x52, + 0x88, 0x88, 0x85, 0x8F, + 0x9A, 0xA5, 0x68, 0x94, + 0x58, 0x65, 0x12, 0xB3, 0x11, 0xFF, + 0xA2, 0xBF, 0x12, 0x19, 0x5A, + 0x99, 0x6C, 0xA3, 0x67, + 0x57, 0x96, 0x56, 0x68, + 0xAB, 0xA0, 0x6A, 0xA9, + 0x8D, 0x69, 0x66, 0x55, + 0x87, 0x96, 0x71, 0xA1, + 0x73, 0xAA, 0x52, 0x63, + 0xA8, 0x8C, 0xDA, 0x12, 0x83, + 0x97, 0x67, 0x97, 0x56, + 0x81, 0x56, 0x95, 0x6D, + 0xD6, 0x7A, 0xA8, 0x5E, + 0x70, 0x11, 0xF0, 0x12, 0xBD, 0x89, + 0x62, 0xA3, 0xF5, 0x13, 0x15, + 0x60, 0x61, 0x81, 0x89, + 0x5D, 0x86, 0x89, 0x9E, + 0x77, 0x5B, 0x9C, 0x81, + 0xB9, 0x5A, 0x67, 0x52, + 0xA3, 0x5C, 0x54, 0x61, + 0x88, 0x89, 0x85, 0x82, + 0xAF, 0x84, 0x70, 0x81, + 0x81, 0x91, 0x89, 0x56, + 0x5B, 0x8C, 0x63, 0x53, + 0x5B, 0xA2, 0xA4, 0x54, + 0x60, 0xA5, 0x69, 0x86, + 0x61, 0x87, 0x9A, 0x83, + 0x9E, 0x53, 0x52, 0xAE, + 0x80, 0x56, 0x83, 0x5D, + 0x91, 0x31, 0x79, 0x13, 0xCD, 0x99, + 0x54, 0x93, 0x84, 0x57, + 0x8B, 0x53, 0x52, 0x82, + 0x82, 0x88, 0x81, 0x84, + 0x52, 0x88, 0x87, 0x83, + 0x83, 0x89, 0x84, 0x82, + 0x82, 0x81, 0x8E, 0x8D, + 0x90, 0x85, 0x59, 0x85, + 0x88, 0x94, 0x86, 0x87, + 0x5C, 0x94, 0x81, 0x83, + 0xBE, 0x14, 0x83, 0x91, 0xC3, + 0x57, 0x67, 0x94, 0xB0, + 0x14, 0xC6, 0x16, 0xD4, 0x14, 0xC8, 0x94, + 0x61, 0x53, 0x59, 0x85, + 0x7D, 0xAE, 0xC3, 0x6F, + 0x83, 0xB6, 0x76, 0x86, + 0x6A, 0x86, 0xDB, 0x63, + 0x8F, 0x16, 0x1C, 0x15, 0x4F, 0xC7, + 0x59, 0x5F, 0xAB, 0x15, 0x76, + 0xAD, 0x65, 0x57, 0x96, + 0x96, 0x15, 0x6B, 0x53, 0xD5, + 0xAB, 0x7A, 0x86, 0x9D, + 0x6B, 0x89, 0xA4, 0x15, 0xC4, + 0xD2, 0x9E, 0x7F, 0x8D, + 0x93, 0x90, 0x17, 0x1D, 0x16, 0x17, + 0x91, 0x6A, 0xD8, 0x88, + 0x87, 0x79, 0x17, 0x2A, 0x16, 0x95, + 0x53, 0x92, 0x84, 0x72, + 0xB4, 0x9E, 0x59, 0x5E, + 0x82, 0x5D, 0x9D, 0x67, + 0xAF, 0x5B, 0x34, 0x09, 0x16, 0xE0, + 0x81, 0x14, 0xAC, 0x16, 0xE3, 0x8C, + 0xBD, 0x16, 0xF6, 0x53, 0x53, + 0x88, 0x86, 0x54, 0x9B, + 0x84, 0x68, 0x9F, 0x52, + 0x88, 0x89, 0x81, 0x82, + 0x52, 0x82, 0x27, 0x4B, 0x17, 0x48, + 0x8E, 0x52, 0x59, 0x8B, + 0x86, 0x52, 0x95, 0x86, + 0x8A, 0x81, 0x3D, 0x8A, 0x17, 0x9B, + 0x84, 0x8C, 0x8C, 0x8C, + 0x83, 0x56, 0x83, 0x88, + 0x86, 0x89, 0x53, 0x87, + 0x81, 0x90, 0x19, 0x72, 0x18, 0x0A, + 0x58, 0x59, 0x19, 0x73, 0x18, 0x35, + 0x81, 0x53, 0x69, 0xB3, + 0x5C, 0x85, 0x59, 0x9D, + 0x52, 0x87, 0x83, 0x81, + 0x5A, 0x83, 0x8E, 0x93, + 0x85, 0x86, 0x56, 0x56, + 0x94, 0x85, 0xA4, 0x59, + 0x90, 0x5C, 0x53, 0x88, + 0x5D, 0x9E, 0x84, 0x86, + 0x18, 0x3F, 0x18, 0xE6, 0x83, 0x87, + 0x85, 0x82, 0x98, 0x87, + 0x88, 0x88, 0x81, 0x49, 0x38, + 0x19, 0x2E, 0x91, 0x5A, 0x8B, + 0x5A, 0x52, 0x8F, 0x98, + 0x82, 0x58, 0x8A, 0x81, + 0xA5, 0x6A, 0xB9, 0x7E, + 0x63, 0xA2, 0x52, 0x9B, + 0x56, 0x6D, 0xB2, 0xB8, + 0x19, 0xB4, 0xB8, 0x19, 0xB3, 0xB6, + 0x19, 0xB8, 0xAC, 0x57, 0x52, + 0x85, 0x8C, 0x19, 0xB9, 0x95, + 0x59, 0xA1, 0x1C, 0x9C, 0x1A, 0x1E, + 0xA8, 0x6E, 0x97, 0x8D, + 0x6C, 0x9C, 0xE5, 0x1A, 0x2B, + 0xAE, 0x8A, 0x94, 0x88, + 0xA0, 0x61, 0x9E, 0x6A, + 0x89, 0x53, 0x69, 0x1C, 0xAE, + 0x1A, 0xB9, 0x1A, 0x74, 0xC1, 0x66, + 0x9A, 0xD5, 0x1A, 0x8D, 0x60, + 0x1B, 0x01, 0x1A, 0xCA, 0xBE, 0x1A, 0xD8, + 0xCA, 0x84, 0x1A, 0xE1, 0xAB, + 0x1A, 0xCD, 0x87, 0x93, 0x63, + 0xE1, 0x75, 0x5F, 0x7E, + 0x8C, 0xC2, 0x7D, 0x6A, + 0x8F, 0xB9, 0x82, 0x61, + 0x89, 0x53, 0x1A, 0xC6, 0x1B, 0x79, + 0x53, 0x6C, 0x9C, 0x5E, + 0x68, 0xAA, 0x61, 0x1B, 0x39, + 0xBB, 0x1B, 0x3D, 0x9C, 0x7A, + 0xB1, 0x54, 0x52, 0xA4, + 0x68, 0xC8, 0x55, 0xA2, + 0x62, 0x82, 0x92, 0x66, + 0x90, 0x0D, 0xE8, 0x1B, 0xCA, 0x93, + 0x73, 0x88, 0x6D, 0x1C, 0x2E, + 0x1B, 0x91, 0x8F, 0x55, 0x58, + 0x9F, 0xAA, 0x8A, 0x9A, + 0x99, 0x6D, 0x1D, 0x0A, 0x1B, 0xF9, + 0x58, 0x5C, 0x9E, 0x1B, 0xB1, + 0xED, 0x1B, 0xED, 0xA7, 0x7A, + 0x9F, 0x88, 0x1C, 0xC1, 0x1C, 0x23, + 0x61, 0xB1, 0x1C, 0x0C, 0xE6, + 0x1C, 0x36, 0xC2, 0x1C, 0x47, 0x9B, + 0x5A, 0x8D, 0x6F, 0x61, + 0x67, 0xEE, 0x54, 0x93, + 0x6D, 0x9E, 0x81, 0x5D, + 0x38, 0x17, 0x1C, 0xBB, 0x88, 0x52, + 0x5B, 0x56, 0x58, 0xB2, + 0x5E, 0x8E, 0x1C, 0xAA, 0xB0, + 0x90, 0x91, 0x8A, 0x38, 0x16, + 0x1C, 0xFA, 0x98, 0x84, 0x4D, 0x31, + 0x1D, 0x1F, 0x99, 0x52, 0x28, 0xDC, + 0x1D, 0x39, 0x4A, 0xEE, 0x1D, 0x47, 0x55, + 0x86, 0x87, 0x89, 0x56, + 0x87, 0x84, 0x82, 0x97, + 0x81, 0x86, 0x81, 0x84, + 0x52, 0x8A, 0x8B, 0x54, + 0x89, 0x86, 0x86, 0x81, + 0x84, 0x83, 0x52, 0x82, + 0x84, 0x85, 0x8A, 0x85, + 0x88, 0x8C, 0x8D, 0x52, + 0x88, 0x55, 0x50, 0xBE, 0x1E, 0x08, + 0x8B, 0x81, 0x87, 0x89, + 0x52, 0xBB, 0x5A, 0x8D, + 0x88, 0x98, 0x8B, 0x8D, + 0x6A, 0x9A, 0x6E, 0x67, + 0x8B, 0x9F, 0x53, 0xB4, + 0xAD, 0x6F, 0x67, 0x9A, + 0x63, 0x98, 0x80, 0x83, + 0x8D, 0x55, 0xA1, 0x94, + 0x67, 0x91, 0xB5, 0x3A, 0x4D, + 0x1F, 0x36, 0x5C, 0x92, 0x56, + 0x70, 0x9C, 0x53, 0x72, + 0x57, 0xD7, 0xB0, 0x80, + 0x5B, 0x9F, 0x71, 0xB5, + 0x87, 0x21, 0xE4, 0x1F, 0x85, 0xF4, + 0x9C, 0x5C, 0x1F, 0xB5, 0x92, + 0x9F, 0x7F, 0x8E, 0xA6, + 0x5F, 0x63, 0x9C, 0x67, + 0x5E, 0xB5, 0x72, 0x8B, + 0x60, 0x95, 0x84, 0xBF, + 0xC1, 0x20, 0x2E, 0x66, 0xD9, + 0x64, 0x72, 0x6C, 0xC8, + 0x20, 0x2B, 0xCB, 0x7A, 0x7F, + 0xA4, 0x5A, 0x94, 0x7B, + 0x20, 0xFF, 0x20, 0x1D, 0x9B, 0xCA, + 0xA8, 0x63, 0xB1, 0x63, + 0x9C, 0x67, 0x5F, 0x95, + 0x63, 0xA2, 0x81, 0x20, 0x8F, + 0x96, 0x9D, 0x74, 0x21, 0x41, + 0x21, 0x11, 0x22, 0x4C, 0x20, 0xEC, 0x8C, + 0x86, 0xC1, 0x20, 0xF2, 0xBF, + 0x20, 0xEF, 0xC3, 0x20, 0xCC, 0xF2, + 0x7C, 0x6D, 0x21, 0x86, 0x5D, + 0x53, 0x89, 0x52, 0x62, + 0x65, 0x21, 0xF3, 0x21, 0x6D, 0x95, + 0x57, 0x75, 0xB6, 0x83, + 0xB1, 0x21, 0x66, 0xCD, 0x61, + 0x53, 0x83, 0x95, 0x8D, + 0x6D, 0xB5, 0x5B, 0x97, + 0x69, 0x84, 0x99, 0x54, + 0x64, 0xAE, 0x82, 0x62, + 0x97, 0x61, 0x8E, 0x62, + 0x9D, 0x52, 0x21, 0x74, 0x22, 0x1D, + 0x56, 0x87, 0x91, 0x8E, + 0x5D, 0x9F, 0x92, 0xB6, + 0x58, 0x9D, 0xC2, 0x22, 0xAC, + 0x8C, 0x56, 0x56, 0xB1, + 0x65, 0x92, 0x55, 0xB0, + 0x5D, 0x9F, 0x54, 0xCC, + 0x61, 0xB3, 0x73, 0x55, + 0x67, 0x8A, 0x96, 0xA3, + 0xEC, 0x23, 0x84, 0x91, 0x93, + 0x84, 0xAB, 0x6F, 0x85, + 0x94, 0x5A, 0x8B, 0x57, + 0x92, 0x8C, 0x56, 0x8E, + 0x87, 0x54, 0x86, 0x8E, + 0x83, 0x8B, 0x8D, 0x85, + 0x52, 0x84, 0x82, 0x89, + 0x81, 0x83, 0x81, 0x86, + 0x85, 0x8D, 0x9C, 0x8A, + 0x84, 0x52, 0x86, 0x8B, + 0x84, 0x8C, 0x85, 0x92, + 0x58, 0x91, 0x83, 0x53, + 0x8A, 0x84, 0x90, 0x53, + 0x81, 0x98, 0x53, 0x02, 0x0F, + 0x25, 0x17, 0x5E, 0x92, 0x57, + 0x87, 0x97, 0x56, 0x57, + 0x55, 0x99, 0x90, 0x81, + 0x50, 0xD8, 0x25, 0x57, 0x93, 0x53, + 0x88, 0x88, 0x54, 0x86, + 0x52, 0xCE, 0x66, 0x9B, + 0x64, 0x85, 0xA5, 0x89, + 0x61, 0x26, 0xA2, 0x26, 0x05, 0xEA, + 0x26, 0x25, 0x7E, 0xBA, 0x88, + 0x9B, 0x67, 0xA0, 0x57, + 0x69, 0x9B, 0x8D, 0x87, + 0x5E, 0x87, 0x8C, 0x88, + 0x8D, 0x93, 0x89, 0xA3, + 0x85, 0x85, 0x25, 0xF1, 0x26, 0xE0, + 0x83, 0x84, 0x82, 0x85, + 0x84, 0x53, 0x81, 0x87, + 0x52, 0x8D, 0x52, 0x82, + 0x87, 0x82, 0x52, 0x88, + 0x53, 0x8B, 0x88, 0x86, + 0x90, 0x88, 0x89, 0x54, + 0x52, 0x92, 0x66, 0x94, + 0x8F, 0x56, 0x83, 0x84, + 0x82, 0x8B, 0x53, 0x90, + 0x81, 0x64, 0x96, 0x52, + 0x58, 0x92, 0x86, 0x83, + 0x88, 0x53, 0x9F, 0x60, + 0x90, 0x5F, 0x88, 0x56, + 0x84, 0x5C, 0x9C, 0x54, + 0x88, 0x87, 0x8A, 0x56, + 0xA0, 0x81, 0x54, 0x85, + 0x62, 0x8A, 0x59, 0x81, + 0x98, 0x82, 0x55, 0x96, + 0x88, 0x58, 0x81, 0x81, + 0x82, 0x90, 0x55, 0x8B, + 0x8C, 0x81, 0x53, 0x96, + 0x55, 0x89, 0x81, 0x86, + 0x81, 0x81, 0x54, 0x85, + 0x84, 0x82, 0x84, 0x82, + 0x84, 0x84, 0x83, 0x85, + 0x83, 0x83, 0x88, 0x54, + 0x86, 0x81, 0x96, 0x84, + 0x84, 0x81, 0x81, 0x88, + 0x8B, 0x89, 0x55, 0x8C, + 0x83, 0x84, 0x82, 0x83, + 0x38, 0x2F, 0x28, 0xFB, 0x8D, 0x52, + 0x54, 0xA5, 0x56, 0x57, + 0x87, 0x81, 0x5C, 0x9C, + 0x81, 0x8F, 0x93, 0x8E, + 0x83, 0x61, 0x8A, 0x9A, + 0x52, 0x56, 0x95, 0x54, + 0x86, 0x8F, 0x53, 0x92, + 0x86, 0x83, 0x86, 0x54, + 0x81, 0x53, 0x8C, 0x86, + 0x8A, 0x83, 0x82, 0x87, + 0x8B, 0x8E, 0x90, 0x86, + 0x2B, 0x26, 0x2A, 0x20, 0x2B, 0x2A, 0x2A, 0x45, + 0xC9, 0x6B, 0x92, 0x5B, + 0x9E, 0x5F, 0x97, 0x92, + 0x5C, 0x85, 0xA2, 0x5C, + 0x85, 0x89, 0x67, 0x53, + 0x89, 0x85, 0xA2, 0x56, + 0x5E, 0xA3, 0x5A, 0x93, + 0x8B, 0x52, 0x88, 0x93, + 0x52, 0x95, 0xA0, 0x5A, + 0x88, 0x56, 0x56, 0x53, + 0xA7, 0x85, 0x8B, 0x93, + 0x8A, 0x51, 0x4B, 0x2B, 0xAA, 0x84, + 0x85, 0x86, 0x81, 0x8F, + 0x8C, 0x92, 0x85, 0x5C, + 0x82, 0xA5, 0x85, 0x8B, + 0x81, 0x87, 0x52, 0x2B, 0x80, + 0x2C, 0x31, 0x8A, 0x83, 0x58, + 0x8C, 0x94, 0x5F, 0x98, + 0x81, 0x87, 0x51, 0x9D, 0x2C, 0x70, + 0x89, 0x84, 0x8B, 0x8F, + 0x53, 0x83, 0x53, 0x93, + 0x9F, 0x69, 0x86, 0x8F, + 0x52, 0x56, 0x42, 0x83, 0x2C, 0xC7, + 0x83, 0x83, 0x82, 0x86, + 0x53, 0x86, 0x81, 0x83, + 0x84, 0x81, 0x84, 0x87, + 0x83, 0x92, 0x8D, 0x56, + 0x55, 0xAD, 0x6C, 0x81, + 0x85, 0x97, 0x5E, 0x8E, + 0x9A, 0xAA, 0x2D, 0x04, 0xC9, + 0x2D, 0x0B, 0xC1, 0x58, 0xB0, + 0x61, 0x8F, 0x5E, 0x89, + 0x81, 0x56, 0x82, 0xAF, + 0x56, 0x87, 0x63, 0x8F, + 0x53, 0x60, 0x87, 0x54, + 0x2D, 0x5D, 0xBC, 0xB2, 0x5B, + 0x8B, 0x83, 0x6C, 0x92, + 0x97, 0x8C, 0xA8, 0x83, + 0x7F, 0x52, 0xFB, 0x2E, 0x00, + 0x87, 0x8C, 0x71, 0x84, + 0xA0, 0x5B, 0x68, 0xAD, + 0x84, 0x83, 0x5C, 0x98, + 0x5D, 0x92, 0x8F, 0x5A, + 0x91, 0x56, 0x60, 0x90, + 0x88, 0x87, 0x85, 0x5F, + 0x8F, 0x87, 0x89, 0x8E, + 0x8D, 0x94, 0x89, 0x5C, + 0x89, 0x5B, 0x87, 0x8B, + 0x52, 0x52, 0x54, 0x8B, + 0x84, 0x83, 0x85, 0x54, + 0x96, 0x57, 0x8A, 0x86, + 0x4D, 0x3B, 0x2E, 0xEF, 0x83, 0x82, + 0x82, 0x84, 0x8C, 0x55, + 0x9A, 0x58, 0x5C, 0xBB, + 0x86, 0x6E, 0x84, 0x8D, + 0x5B, 0x91, 0xAD, 0x6E, + 0x59, 0xA4, 0x5B, 0x86, + 0x70, 0x94, 0xB0, 0x5B, + 0x7F, 0xB4, 0x63, 0x9E, + 0x9F, 0x5D, 0x5C, 0x92, + 0x92, 0x5B, 0x63, 0x30, 0x3D, + 0x2F, 0xA2, 0x8D, 0xAD, 0x75, + 0x6A, 0x91, 0xA8, 0x85, + 0x87, 0x57, 0x9D, 0x5A, + 0x62, 0xA4, 0x85, 0x99, + 0x53, 0x60, 0x9F, 0x63, + 0x67, 0x82, 0x97, 0xA4, + 0xA0, 0x7C, 0x57, 0x84, + 0x8A, 0x5D, 0x56, 0x88, + 0xAD, 0x5B, 0x58, 0x88, + 0x56, 0x81, 0x9F, 0x60, + 0x52, 0x93, 0x52, 0x88, + 0x2F, 0xD5, 0x30, 0x7D, 0x41, 0xAE, 0x30, 0x7F, + 0x89, 0x81, 0x83, 0x86, + 0x53, 0x83, 0x81, 0x82, + 0x59, 0x8D, 0x81, 0x31, 0x38, + 0x82, 0x8B, 0x87, 0x81, + 0x81, 0x82, 0x81, 0x84, + 0x52, 0x84, 0x87, 0x81, + 0x88, 0x81, 0x53, 0x91, + 0x8A, 0x84, 0x54, 0x85, + 0x52, 0x85, 0x88, 0x8A, + 0x52, 0x54, 0x89, 0x8C, + 0x83, 0x87, 0x5C, 0x88, + 0x82, 0x3D, 0x71, 0x31, 0xC5, 0x81, + 0x84, 0x8B, 0x52, 0x8D, + 0x85, 0x83, 0x8A, 0x86, + 0x4A, 0xDC, 0x32, 0x06, 0x53, 0x87, + 0x87, 0x86, 0x81, 0x83, + 0x85, 0x87, 0x97, 0x55, + 0x8F, 0x55, 0x8C, 0x86, + 0x82, 0x85, 0x83, 0x86, + 0x8B, 0x52, 0x53, 0x86, + 0x83, 0x84, 0x82, 0x85, + 0x82, 0x52, 0x96, 0x59, + 0x87, 0x93, 0x03, 0x90, 0x32, 0xAC, + 0xAF, 0x8A, 0x5D, 0x84, + 0x6A, 0x96, 0x55, 0xB3, + 0x6B, 0x82, 0xAA, 0x8E, + 0x57, 0x8C, 0x9C, 0x48, 0x8B, + 0x33, 0x46, 0x59, 0x95, 0x53, + 0x32, 0xFC, 0xF5, 0x54, 0x5A, + 0x81, 0x8E, 0x8F, 0x85, + 0x82, 0x5B, 0x82, 0x9E, + 0x5C, 0x8F, 0x52, 0x33, 0x5F, + 0xB4, 0x96, 0x87, 0x85, + 0x89, 0x57, 0x85, 0x83, + 0x82, 0x59, 0x8F, 0x84, + 0x84, 0x88, 0x52, 0x61, + 0x92, 0x85, 0x81, 0x87, + 0x93, 0x81, 0x83, 0x83, + 0x81, 0x83, 0x82, 0x83, + 0x83, 0x83, 0x86, 0x93, + 0x82, 0x8D, 0x56, 0x8D, + 0x99, 0x52, 0x85, 0x54, + 0x85, 0x85, 0x53, 0x86, + 0x82, 0x81, 0x34, 0x2E, 0xC3, + 0x86, 0x81, 0x86, 0x8F, + 0x85, 0x99, 0x5D, 0x9C, + 0x60, 0xB5, 0x82, 0x55, + 0x5E, 0xA2, 0x52, 0x87, + 0x35, 0x93, 0x35, 0x03, 0x59, 0x53, + 0x6C, 0xA8, 0x7B, 0xAD, + 0x34, 0xD9, 0xDC, 0x52, 0x6F, + 0x9C, 0x52, 0x8F, 0x58, + 0x97, 0x5C, 0x67, 0x55, + 0x65, 0x81, 0xED, 0x95, + 0x90, 0x5C, 0x83, 0x5D, + 0x35, 0x23, 0xEB, 0x58, 0x83, + 0x5F, 0xB9, 0x35, 0x73, 0x82, + 0xAB, 0x68, 0x9F, 0xCC, + 0x9F, 0x79, 0x6E, 0xAF, + 0x86, 0x7C, 0xB3, 0x35, 0xC1, + 0xB6, 0x90, 0x78, 0x92, + 0x9B, 0x95, 0x53, 0x35, 0xBD, + 0xFB, 0x37, 0x06, 0x35, 0xFB, 0xF2, + 0x36, 0x2A, 0x92, 0x37, 0x5A, 0x36, 0x84, + 0x5E, 0x5D, 0xC2, 0x36, 0x6E, + 0x94, 0x6A, 0x74, 0x6B, + 0xC3, 0x8A, 0x36, 0x35, 0x36, 0xCA, + 0x36, 0x62, 0xD7, 0x86, 0x71, + 0xBA, 0x5D, 0x63, 0x9F, + 0x5B, 0x60, 0x85, 0x90, + 0x36, 0xA1, 0x37, 0x21, 0x73, 0x5C, + 0xA3, 0x81, 0x94, 0x5E, + 0x5B, 0x52, 0x69, 0xC4, + 0xA3, 0x5C, 0x61, 0x58, + 0x38, 0x02, 0x37, 0x4B, 0x8A, 0xAB, + 0xA4, 0x6D, 0x89, 0x58, + 0x9E, 0x37, 0x6D, 0xA7, 0x87, + 0xCF, 0x37, 0x87, 0x95, 0x76, + 0x87, 0x92, 0xB9, 0x60, + 0x95, 0x67, 0x97, 0x85, + 0x88, 0x88, 0x5A, 0x9D, + 0x91, 0x89, 0x59, 0x5E, + 0x55, 0x8C, 0x9C, 0x59, + 0x96, 0x8F, 0x8E, 0x00, 0x55, + 0x38, 0x54, 0x8B, 0x88, 0x8A, + 0xA2, 0x90, 0x86, 0x81, + 0x70, 0x81, 0xAA, 0x58, + 0x95, 0x82, 0x67, 0x99, + 0x3A, 0x23, 0x38, 0xAB, 0xA9, 0x8A, + 0x8B, 0x83, 0x5E, 0x55, + 0x94, 0xA3, 0x5D, 0x82, + 0x59, 0x83, 0x59, 0x96, + 0x59, 0x84, 0x65, 0x91, + 0xAA, 0x8B, 0x59, 0x84, + 0x67, 0x84, 0x60, 0xC6, + 0x52, 0x99, 0x7D, 0x82, + 0xA6, 0x6E, 0x91, 0x86, + 0x66, 0x57, 0x90, 0x87, + 0x3A, 0x05, 0x39, 0xA2, 0x54, 0x6E, + 0xAD, 0x9C, 0x5F, 0x83, + 0x90, 0x48, 0xD6, 0x39, 0xAB, 0x99, + 0x62, 0x94, 0x52, 0x5C, + 0xB4, 0x83, 0x63, 0xAF, + 0x53, 0x60, 0x59, 0x81, + 0x97, 0x39, 0xD2, 0xBF, 0x85, + 0x52, 0x8D, 0x52, 0x90, + 0x85, 0x83, 0x63, 0x94, + 0x89, 0x53, 0x90, 0x87, + 0x85, 0x84, 0x89, 0x96, + 0x54, 0xA0, 0x7A, 0x88, + 0xB8, 0x3A, 0x72, 0x90, 0x95, + 0x56, 0x9C, 0x66, 0x89, + 0x66, 0x97, 0x8C, 0x8F, + 0x5F, 0x92, 0x81, 0x90, + 0x84, 0x81, 0x84, 0x9C, + 0x89, 0x57, 0x59, 0x5D, + 0x8A, 0x92, 0x88, 0x53, + 0x89, 0xB0, 0x76, 0x87, + 0x85, 0x81, 0x96, 0x83, + 0x5A, 0x56, 0x82, 0x94, + 0x80, 0xC3, 0x53, 0x88, + 0x53, 0x89, 0x54, 0x85, + 0x85, 0x83, 0x87, 0x85, + 0x85, 0x82, 0x89, 0x85, + 0x89, 0x88, 0x54, 0x86, + 0x83, 0x83, 0x88, 0x83, + 0x82, 0x81, 0x9A, 0x82, + 0x81, 0x8A, 0x8D, 0x84, + 0x8B, 0x93, 0x57, 0x55, + 0x8F, 0x82, 0x88, 0x91, + 0x8B, 0x9A, 0x5A, 0x5D, + 0x82, 0xB4, 0x60, 0x52, + 0x5B, 0xA3, 0x54, 0x82, + 0xA4, 0x58, 0x61, 0x94, + 0x81, 0x5D, 0x89, 0xA1, + 0x89, 0x5C, 0x98, 0x91, + 0x88, 0x5D, 0x54, 0x8D, + 0xA3, 0x3C, 0xE0, 0x82, 0x95, + 0x6A, 0x54, 0xB1, 0x56, + 0x93, 0x3C, 0xE1, 0xB5, 0x57, + 0x87, 0x89, 0x93, 0x49, 0xAB, + 0x3D, 0x26, 0x85, 0x93, 0x67, + 0x99, 0x8B, 0x83, 0x52, + 0x56, 0x8D, 0x85, 0x52, + 0x91, 0x5D, 0x8D, 0x83, + 0x85, 0x89, 0x83, 0x8C, + 0x82, 0x84, 0x81, 0x83, + 0x83, 0x81, 0x3E, 0x3A, 0x87, + 0x53, 0x89, 0x84, 0x82, + 0x82, 0x85, 0x8D, 0x8A, + 0x8C, 0x82, 0x88, 0x87, + 0x55, 0x85, 0x83, 0x81, + 0x86, 0x69, 0x9C, 0x14, 0x1D, + 0x3E, 0xAD, 0x54, 0x93, 0x5C, + 0x81, 0x56, 0x88, 0x92, + 0x58, 0xA3, 0x52, 0x5A, + 0xA3, 0x54, 0x81, 0x89, + 0x81, 0x85, 0x54, 0x88, + 0x53, 0x83, 0x51, 0x4E, 0x3F, 0x13, + 0x3E, 0xCD, 0xC7, 0x82, 0xD1, + 0x86, 0x84, 0x82, 0x8E, + 0x98, 0xA9, 0x55, 0x55, + 0x95, 0x8B, 0x55, 0x5B, + 0x8F, 0x61, 0x9F, 0x81, + 0x5D, 0x84, 0x99, 0x8C, + 0x81, 0x5B, 0x9E, 0x81, + 0x5F, 0x8F, 0xA3, 0x5E, + 0x56, 0x84, 0x96, 0x54, + 0x82, 0x83, 0x84, 0x59, + 0x91, 0x8B, 0x55, 0x40, 0x2A, + 0xB9, 0x5F, 0xA1, 0x55, + 0x8A, 0x85, 0x86, 0x53, + 0x52, 0x87, 0x52, 0x89, + 0x53, 0x83, 0x85, 0x91, + 0x5A, 0x8B, 0x84, 0x96, + 0x66, 0x8D, 0x87, 0x83, + 0x83, 0x90, 0x88, 0x99, + 0x52, 0x61, 0x93, 0x8C, + 0x56, 0x90, 0x54, 0x87, + 0x57, 0x89, 0x83, 0x55, + 0x60, 0x9A, 0x8D, 0x88, + 0x53, 0x8C, 0x54, 0x55, + 0x8E, 0x54, 0x54, 0x88, + 0x89, 0x85, 0x86, 0x81, + 0x81, 0xB8, 0x83, 0x84, + 0x8A, 0x82, 0x88, 0xA3, + 0x8B, 0x54, 0x88, 0x85, + 0x42, 0x87, 0x41, 0xF4, 0x91, 0x5D, + 0x81, 0x97, 0x84, 0x8C, + 0x65, 0x91, 0x59, 0x5C, + 0x9C, 0x8F, 0x52, 0x84, + 0x41, 0xF8, 0xD7, 0x81, 0x81, + 0x81, 0x42, 0x0E, 0xBB, 0x5C, + 0x98, 0x82, 0x86, 0x8A, + 0x87, 0x87, 0x48, 0xA8, 0x42, 0x72, + 0x90, 0x56, 0x84, 0x52, + 0x8A, 0x52, 0x86, 0x99, + 0x87, 0x82, 0x84, 0xAD, + 0x82, 0x14, 0x48, 0x42, 0xDB, 0xA7, + 0x90, 0x87, 0x99, 0x53, + 0x9A, 0x8C, 0x82, 0x8B, + 0x82, 0x84, 0x8A, 0x52, + 0x99, 0x53, 0x58, 0xA0, + 0x89, 0x84, 0x56, 0x8B, + 0x52, 0x86, 0x86, 0x81, + 0x88, 0x82, 0x85, 0x86, + 0x89, 0x82, 0x57, 0xA1, + 0x58, 0x81, 0xA8, 0x70, + 0x95, 0x98, 0x68, 0x55, + 0xCD, 0x58, 0x63, 0x84, + 0x9B, 0x6D, 0xCD, 0x44, 0x3F, + 0x8C, 0x85, 0xCC, 0x57, + 0x54, 0x88, 0x44, 0x5A, 0xF5, + 0x67, 0x53, 0xB2, 0xA6, + 0x66, 0xCA, 0x67, 0x66, + 0x89, 0x59, 0x89, 0x97, + 0x56, 0x86, 0xA1, 0x84, + 0x9C, 0x5F, 0x69, 0xDA, + 0x55, 0x81, 0x6A, 0xA5, + 0x9D, 0x81, 0x91, 0x54, + 0x5E, 0x66, 0x9A, 0x5E, + 0x59, 0x9C, 0xB6, 0x57, + 0x52, 0x61, 0x84, 0x89, + 0xA6, 0x5C, 0x8A, 0x65, + 0x99, 0x87, 0x91, 0x5F, + 0x97, 0x85, 0x82, 0x55, + 0x8C, 0x44, 0x29, 0x46, 0x70, 0x85, + 0x82, 0x86, 0x74, 0xA2, + 0x82, 0x83, 0x53, 0x47, 0x82, + 0x85, 0x83, 0x8A, 0x82, + 0x82, 0x81, 0x87, 0x88, + 0x52, 0x86, 0x8F, 0x52, + 0x53, 0x85, 0x8C, 0x21, 0xF6, + 0x47, 0xC3, 0x8A, 0x52, 0x89, + 0x52, 0x82, 0x86, 0x85, + 0x84, 0x54, 0xBF, 0x87, + 0x86, 0x81, 0x93, 0x8A, + 0x83, 0x55, 0xAC, 0x6C, + 0x82, 0x52, 0x82, 0x87, + 0x8C, 0x57, 0xA1, 0x8B, + 0x54, 0x82, 0x93, 0x54, + 0x8A, 0x81, 0x53, 0x84, + 0x82, 0x82, 0x81, 0x95, + 0x54, 0x53, 0x84, 0x3B, 0x4D, + 0x48, 0xDC, 0xB1, 0x48, 0xD5, 0xA4, + 0x8B, 0x82, 0x82, 0x8B, + 0x56, 0x83, 0x53, 0x87, + 0x83, 0x8B, 0x86, 0x86, + 0x89, 0x84, 0x81, 0x86, + 0x82, 0x82, 0x57, 0x87, + 0x93, 0x84, 0x84, 0x82, + 0x82, 0x04, 0xD2, 0x49, 0x6B, 0x86, + 0x88, 0x8C, 0x5A, 0x85, + 0x58, 0x8C, 0x85, 0x84, + 0x81, 0x8C, 0x8C, 0x53, + 0x54, 0x90, 0x81, 0x8F, + 0x83, 0x82, 0x83, 0x91, + 0x91, 0x51, 0x4F, 0x49, 0xF2, 0x2C, 0xDF, + 0x49, 0xF6, 0x52, 0x9A, 0x54, + 0xAC, 0x65, 0x54, 0x96, + 0x86, 0x89, 0x89, 0x55, + 0xA0, 0x84, 0x81, 0x81, + 0x83, 0x52, 0xB7, 0x85, + 0x82, 0x85, 0x8E, 0x52, + 0x83, 0xA3, 0x82, 0x98, + 0x86, 0x89, 0x82, 0x84, + 0x89, 0x55, 0x81, 0x86, + 0x55, 0x8C, 0x82, 0x8F, + 0x81, 0x84, 0x87, 0x55, + 0x8B, 0x56, 0x86, 0x81, + 0x57, 0x89, 0xC2, 0x81, + 0x8D, 0x88, 0x81, 0x8E, + 0xA3, 0x55, 0x82, 0x56, + 0x58, 0x9C, 0x81, 0x83, + 0x81, 0x89, 0x54, 0x89, + 0x8E, 0x5B, 0x74, 0xB7, + 0x92, 0x8C, 0x8E, 0x54, + 0x53, 0x83, 0x56, 0x97, + 0x59, 0x8E, 0x55, 0x88, + 0x83, 0x83, 0x52, 0x85, + 0x82, 0x52, 0xC3, 0x83, + 0x8C, 0x84, 0x8F, 0x82, + 0x82, 0x81, 0x8A, 0x81, + 0x83, 0x81, 0x83, 0x89, + 0x55, 0x83, 0x86, 0x54, + 0x86, 0x84, 0x8B, 0x92, + 0x82, 0x85, 0x83, 0x81, + 0x82, 0x82, 0x81, 0x81, + 0x81, 0x84, 0x81, 0x83, + 0x92, 0x52, 0x8C, 0x53, + 0x81, 0x83, 0x87, 0x9C, + 0x9F, 0x61, 0x8E, 0x85, + 0x81, 0x88, 0x81, 0x88, + 0x8C, 0x8C, 0x8A, 0x62, + 0x8D, 0x89, 0x82, 0x81, + 0x91, 0x52, 0x82, 0x61, + 0x8D, 0xD9, 0x4D, 0xF2, 0x52, + 0x52, 0xA5, 0x52, 0x5C, + 0x8A, 0x58, 0x57, 0x82, + 0x8A, 0x59, 0x57, 0xAA, + 0x64, 0x8A, 0x52, 0x54, + 0x8F, 0x97, 0x66, 0x94, + 0x59, 0x9C, 0x86, 0x87, + 0x8F, 0x82, 0xEF, 0x85, + 0x84, 0x99, 0x52, 0x6E, + 0x98, 0x83, 0xA4, 0x55, + 0x4F, 0xAF, 0x4F, 0x23, 0x55, 0xA5, + 0x80, 0x54, 0xAF, 0x53, + 0x52, 0x88, 0x82, 0x95, + 0x81, 0x86, 0x64, 0x52, + 0x89, 0x99, 0x97, 0x53, + 0xA4, 0x4F, 0x6F, 0x8B, 0xA0, + 0x8A, 0x85, 0x89, 0x92, + 0x54, 0x57, 0x54, 0x82, + 0x8C, 0x89, 0x5E, 0x97, + 0x57, 0xA5, 0x63, 0x87, + 0x82, 0x8E, 0x9D, 0x81, + 0x83, 0xD7, 0x84, 0x84, + 0x84, 0x87, 0x83, 0x81, + 0x86, 0x83, 0x55, 0x8C, + 0x88, 0x84, 0x8F, 0x5F, + 0x83, 0x49, 0x61, 0x50, 0xCC, 0x82, + 0x81, 0x81, 0x84, 0x88, + 0x82, 0x52, 0x83, 0x85, + 0x83, 0x87, 0x85, 0x82, + 0x81, 0x82, 0x82, 0x81, + 0x81, 0x8A, 0x81, 0x28, 0xB7, + 0x51, 0x15, 0x8C, 0x8B, 0x92, + 0x8C, 0x88, 0x82, 0x8F, + 0x55, 0x81, 0x81, 0x85, + 0x81, 0x85, 0x53, 0x8D, + 0x56, 0x84, 0x9F, 0x87, + 0x84, 0x0A, 0x2F, 0x1B, 0xC7, 0x42, 0x59, + 0x26, 0x64, 0x03, 0xDC, 0x23, 0x99 +}; +#endif + +static unsigned char koi8_table[] = { + '?', '?', '?', 0xf1, '?', '?', '?', '?', + '?', '?', '?', '?', '?', '?', '?', '?', + '?', '?', '?', 0xa1, '?', '?', '?', '?', + '?', '?', '?', '?', '?', '?', '?', '?', + 0xee, 0xd0, 0xd1, 0xe6, 0xd4, 0xd5, 0xe4, 0xd3, + 0xe5, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, + 0xdf, 0xef, 0xe0, 0xe1, 0xe2, 0xe3, 0xd6, 0xd2, + 0xec, 0xeb, 0xd7, 0xe8, 0xed, 0xe9, 0xe7, 0xea, + 0xce, 0xb0, 0xb1, 0xc6, 0xb4, 0xb5, 0xc4, 0xb3, + 0xc5, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, + 0xbf, 0xcf, 0xc0, 0xc1, 0xc2, 0xc3, 0xb6, 0xb2, + 0xcc, 0xcb, 0xb7, 0xc8, 0xcd, 0xc9, 0xc7, 0xca +}; +#else #define HAVE_KOI8_CHARMAP 1 #define HAVE_NEXT_CHARMAP 1 #define HAVE_IBM850_CHARMAP 1 @@ -303,4 +1994,5 @@ NULL /* MUST be NULL terminated */ }; +#endif /* !KANJI */ diff -Nru slrn-0.9.6.2.orig/src/chmap.c slrn-0.9.6.2/src/chmap.c --- slrn-0.9.6.2.orig/src/chmap.c Fri Dec 24 02:24:37 1999 +++ slrn-0.9.6.2/src/chmap.c Sat Jan 1 07:48:17 2000 @@ -45,6 +45,1012 @@ #include "art.h" #include "chmap.h" +#ifdef KANJI +/* + * This code convert routine is originated by Makoto Kikutani, + * and exhanced by Uichi Katsuta. + */ +#include "mime.h" +/* This include file contains static globals */ +# include "charmaps.h" + +/* + * 他のモジュールで日本語コードを変換する時に一時的に使う領域 + * このモジュールでは使ってはいけない + */ +unsigned char Slrn_Tmp_Str[SLRN_TMP_STR_LEN + 1]; + +/* X0201 / X0208 conversion */ + +/* + * 文字列に含まれる半角カタカナ(1 or 2 文字)を濁点、半濁点も含めて + * 全角カタカナ(1 文字)に変換(EUC のみ対応) + */ +static void han2zen_int(unsigned char *s) +{ + int ch, d1, d2, diff = 0; + + while ((ch = *s) != '\0') { + if (ch == SS2) { + s++; + ch = *s - 0xa0; + if (ch < 0 || ch >= 0x40) { + continue; + } + ch = han2zen_cv[ch]; + d1 = ((ch & 0x80) >> 5) + 0x21; + d2 = (ch & 0x7f) + 0x21; + + if (d1 == 0x25 && + ((d2 >= 0x2b && d2 <= 0x48) || (d2 >= 0x4f && d2 <= 0x5b)) && + *(s + 1) == SS2) { + ch = *(s + 2) & 0x7f; + if (ch == 0x5e || (ch == 0x5f && d2 >= 0x4f)) { + d2++; /* 濁点 */ + diff += 2; + s += 2; + if (ch == 0x5f) { /* 半濁点 */ + d2++; + } + } + } + *(s - diff - 1) = d1 | 0x80; + *(s - diff) = d2 | 0x80; + } else if (diff > 0) { + *(s - diff) = ch; + } + s++; + } + if (diff > 0) { + *(s - diff) = '\0'; + } +} + +/* + * SJIS -> EUC + * 世の中にはSJISで投げてくる人もいるのでしかたがない + * return 0: success + * 1: 途中で切れた + * 2: SJIS ではない (未実装) + */ +static int sjis2euc(unsigned char *d, unsigned char *s, int dlen) +{ + int upper, lower, jisx0201 = 0; + + while((upper = *s++) != 0 && dlen > 0) { + if ((upper & 0x80) == 0) { /* ASCII */ + /* なぜか SJIS の中に JISX0201 へのシーケンスが存在することがある */ + if (upper != ESC) { + *d++ = upper; + dlen--; + continue; + } else if (*s == '(') { + s++; + if (*s == 'I') { + jisx0201 = 1; + } else { + jisx0201 = 0; + } + s++; + continue; + } + } + if (IS_SJISH(upper) || jisx0201) { /* いわゆる半角カナ */ + lower = upper | 0x80; + upper = SS2; + } else { /* 漢字 */ + lower = *s++; + if (!IS_SJIS2(lower) || upper >= 0xf0) { /* 途中で切れた! */ + if (lower == '\0') { /* たまに行の折り返し不正などで 2byte 文字の */ + break; /* 間の byte で切れている記事がある。*/ + } else { + return (1); + } + } + if (upper >= 0xe0) { + upper -= 0x70; + } else { + upper -= 0x30; + } + upper <<= 1; + if (lower >= 0x9f) { + lower += 2; + } else { + upper--; + if (lower & 0x80) { + lower += 0x60; + } else { + lower += 0x61; + } + } + } + dlen -= 2; + if (dlen < 0) break; + *d++ = upper; + *d++ = lower; + } + *d = '\0'; + + return 0; +} + +/* + * utf-8 かどうか調べる。1110 aaaa | 10bb bbcc | 10cc dddd のビットパターン + * が続いた場合、utf-8 と見なす。 + */ +static int detect_utf8(unsigned char *s) +{ + int count = 0, ch, ch2; + + while (*s != 0) { + ch = *s; + ch2 = *(s + 1); + if ((ch & 0x80) == 0) { + s++; + } else if ((ch & 0xe0) == 0xc0 && (ch2 & 0xc0) == 0x80) { + s += 2; + } else if ((ch & 0xf0) == 0xe0 && (ch2 & 0xc0) == 0x80 && + (*(s + 2) & 0xc0) == 0x80) { + s += 3; + count++; + if (count > 1) { + return 1; + } + } else { + break; + } + } + return 0; +} + +/* + * JIS(, EUC) -> EUC + * d: 変換後の文字列 + * s: 変換前の文字列 + * dlen: 変換後のバッファの長さ(最後の '\0' は含まない) + * + * return + * 0: ASCII + * 1: JIS + * 2: EUC + * 以下は変換結果不定 + * 3: SJIS かも知れない + * 4: 7bit で 2 バイト文字の途中で切れた、または JIS の終了シーケンスが無い + * 5: utf-8 かも知れない。 + * 6: 8bit で SJIS でも EUC でも utf-8 でもない + */ +typedef enum {ASC, JISX0208, JISX0201, OTHER1, OTHER2} Kanji_Type; + +static int jis2euc(unsigned char *d, unsigned char *s, int dlen) +{ + unsigned char *seq, *orig = s; + int c1, c2, ctrl = 0, euc = 0; + Kanji_Type kanji_mode = ASC; + + while((c1 = *s++) > '\0' && dlen > 0) { + switch(c1) { + case ESC: + c1 = *s++; + if (c1 == '$') { + c1 = *s++; + if (c1 == '(') c1 = *s++; + if (c1 == '@' || c1 == 'B') { + kanji_mode = JISX0208; + } else { /* その他の 2byte 文字集合。'□'に置き換える */ + kanji_mode = OTHER2; + } + } else if (c1 == '(') { + c1 = *s++; + if (c1 == 'B' || c1 == 'H' || c1 == 'J' ) { + kanji_mode = ASC; + } else if (c1 == 'I') { /* X0201 */ + kanji_mode = JISX0201; + } else { /* その他の 1byte 文字集合。'?'に置き換える */ + kanji_mode = OTHER1; + } + } else if (c1 == '.') { /* ISO-8859-X への指示。'?'に置き換える */ + kanji_mode = OTHER1; + s++; + } else if (c1 == 'N') { /* ISO-2022-JP-2 の Shift-In */ + kanji_mode = OTHER1; + } else { + s--; /* ただの ESC。無視する */ + } + c1 = 0; /* means control code */ + break; + case SO: + seq = s; /* SI がなければシングルシフトと見なす */ + while((c1 = *seq++) != '\0' && c1 != SI); + c2 = *s | 0x80; /* SJISH と EUC 半角カタカナは同じ範囲 */ + if (c1 == '\0' && IS_SJISH(c2)) { + s++; + dlen -= 2; + *d++ = SS2; + *d++ = c2; + } else { + kanji_mode = JISX0201; + } + c1 = 0; /* means control code */ + break; + case SI: + kanji_mode = ASC; + c1 = 0; /* means control code */ + break; + default: + if (c1 & 0x80) { /* 8bit code */ + /* irregular な文字列だが何とか変換を試みる */ + /* JIS-X0208 へのシーケンスが存在すれば 8bit 文字は SJIS + と見なす */ + seq = s; + while(*seq++ != '\0' && euc == 0 && ctrl == 0) { + if (*seq == ESC && *(seq + 1) == '$' + && (*(seq + 2) == '@' || *(seq + 2) == 'B')) ctrl++; + } + c2 = *s; + if (ctrl == 0) { + if (euc == 0 && detect_utf8(orig)) { + return 5; + } + if (c1 == 0x92 && IS_EUC1(c2) && IS_EUC2(*(s + 1))) { + /* Mule の内部コード */ + c1 = c2; + s++; + c2 = *s; + } + if ((IS_EUC1(c1) && IS_EUC2(c2)) || /* EUC らしい */ + (c1 == SS2 && IS_SJISH(c2))) { /* EUC 半角カタカナ */ + s++; + euc++; + } else if (IS_SJISH(c1) || (IS_SJIS1(c1) && IS_SJIS2(c2))) { + /* なんてこった、SJISらしい。取りあえず残りの文字を複写 */ + strcpy((char *)d, (char *)s); + return (3); + } else { /* 日本語ではない。同上 */ + strcpy((char *)d, (char *)s); + return 6; + } + } else { + unsigned char str[3]; /* SJIS とみなして変換する */ + + str[0] = c1; + if (IS_SJISH(c1)) { + c1 = 1; + } else if (IS_SJIS1(c1) && IS_SJIS1(c2)){ + str[1] = c2; + s++; + c1 = 2; + } else { + continue; /* 無視する。*/ + } + str[c1] = '\0'; + if (sjis2euc(d, str, dlen) == 0) { + while(*d != '\0') { + d++; + dlen--; + } + } + continue; + } /* end of if (ctrl == 0) */ + } else if (c1 <= ' ') { + *d++ = c1; + dlen--; + continue; + } else { + switch(kanji_mode) { + case JISX0201: + c2 = c1 | 0x80; + if (IS_SJISH(c2)) { + c1 = SS2; + } else { /* 半角カタカナでない。無視する。 */ + continue; + } + break; + case OTHER2: + c1 = c2 = 0xa2; /* 変換できないので '□'に置き換える */ + s++; + break; + case JISX0208: + c2 = *s; + if (c2 == '\0') { /* 半分で切れて終わった */ + break; + } else if (c2 == 0x01) { /* Mozilla 4.04 [en] (Win95; I) の */ + c1++; /* バグとおぼしき文字化けに対する補正 */ + c2 += 0x21; + } else if ((c2 & 0x7f) < ' ') { /* 半分切れた。無視する */ + continue; + } + s++; + c1 |= 0x80; + c2 |= 0x80; + break; + case OTHER1: + c1 = '?'; + /*FALLTHROUGH*/ + default: /* ASC */ + dlen--; + *d++ = c1; + continue; + } /* end of switch(kanji_mode) */ + } /* end of if (c1 & 0x80) */ + } /* end of switch(c1) */ + if (c1 == 0) { + ctrl++; + continue; + } + dlen -= 2; + if ((c2 & 0x80) == 0) { /* 途中で切れた */ + c2 = 0; + break; + } + if (dlen >= 0) { + *d++ = c1; + *d++ = c2; + } + } + *d = '\0'; + if ((kanji_mode != ASC && c2 == 0) || kanji_mode == JISX0208) { + return (4); + } else if (ctrl) { + return (1); + } else if (euc) { + return (2); + } + return (0); +} + +/* + * internal code(EUC) -> JIS + * + * return 0: success + * 1: 途中で切れた + */ +#define TO_ASCII(p) (*(p)++ = ESC, *(p)++ = '(', *(p)++ = 'B') +#define TO_JIS208(p) (*(p)++ = ESC, *(p)++ = '$', *(p)++ = 'B') + +static int int2jis(unsigned char *d, unsigned char *s, int dlen) +{ + Kanji_Type kanji_mode = ASC; + int ch; + + while(dlen > 0) { /* ASCII character or JIS encoding */ + ch = *s++; + if (ch & 0x80) { + if (kanji_mode == ASC) { + dlen -= 3; + if (dlen < 0) break; + TO_JIS208(d); + kanji_mode = JISX0208; + } + dlen--; + *d++ = ch & 0x7f; + ch = *s++; + if (dlen <= 0) break; + } else if (kanji_mode == JISX0208) { + dlen -= 3; + if (dlen < 0) break; + TO_ASCII(d); + kanji_mode = ASC; + } + if (ch == '\0') break; + dlen--; + *d++ = ch & 0x7f; + } + *d = '\0'; + if (dlen < 0) { + return 1; + } else { + return 0; + } +} + +/* + * internal code(EUC) -> SJIS + * エラーチェックはしていない + * return 0: success + */ +static int int2sjis(unsigned char *d, unsigned char *s, int dlen) +{ + int ch, ch2; + + while((ch = *s++) != 0 && dlen > 0) { + if ((ch & 0x80) == 0) { /* ASCII */ + *d++ = ch; + dlen--; + continue; + } + ch2 = *s++; + if (ch & 1) { + ch2 -= 0x60; + if ((ch2 & 0x80) == 0) { + ch2--; + } + } else { + ch2 -= 2; + } + ch++; + ch >>= 1; + ch += 0x30; + if (ch > 0x9f) { + ch += 0x40; + } + dlen -= 2; + *d++ = ch; + *d++ = ch2; + } + *d = '\0'; + return (0); +} + +/* + * 一文字の Unicode Character を EUC に変換して d が指す領域にストアする。 + * ストアした文字数を返す。 + */ +static int ucs2toeuc(unsigned char *d, int uni) +{ + int hi, lo, j; + unsigned char *tbl = NULL; + + lo = uni & 0xff; + + switch (uni & 0xff00) { + case 0x0000: + case 0x0100: + if (uni >= 0x0080) { + lo = '?'; + } /* 0:cannot convert 1:1 byte character 2:2 byte character */ + uni = 1; + break; + case 0x0300: + uni = 2; + hi = 0x26; + if ((lo >= 0x91 && lo <= 0xa9) || (lo >= 0xb1 && lo <= 0xc1)) { + lo -= 0x70; + } else if (lo >= 0xc3 && lo <= 0xc9) { + lo -= 0x71; + } else { + uni = 0; + } + break; + case 0x0400: /* russian character */ + uni = 2; + hi = 0x27; + if (lo >= 0x10 && lo <= 0x16) { + lo += 0x11; + } else if (lo >= 0x17 && lo <= 0x2f) { + lo += 0x12; + } else if (lo >= 0x30 && lo <= 0x35) { + lo += 0x21; + } else if (lo >= 0x36 && lo <= 0x4f) { + lo += 0x22; + } else { + uni = 0; + } + break; + case 0x2000: /* various characters */ + case 0x2200: /* various characters */ + if (uni < 0x2200) { + tbl = u2000; + hi = sizeof(u2000); + } else { + tbl = u2200; + hi = sizeof(u2200); + } + uni = 0; + do { + hi -= 2; + if (tbl[hi] == lo) { + lo = tbl[hi + 1]; + hi = 0x22 - ((lo & 0x80) >> 7); + uni = 2; + break; + } + } while (hi > 0 && (int)tbl[hi] > lo); + tbl = NULL; + break; + case 0x2500: /* keisen character */ + uni = 0; + for (hi = 0; hi < sizeof(j2821); hi++) { + if (j2821[hi] == lo) { + lo = hi + 0x21; + hi = 0x28; + uni = 2; + break; + } + } + break; + case 0x3000: + uni = 2; + if (lo <= 0x15) { + tbl = u3000; + } else if (lo >= 0x41 && lo <= 0x93) { /* hiragana */ + hi = 0x24; + lo -= 0x20; + } else if (lo >= 0x9b && lo <= 0x9e) { + tbl = u309b; + lo -= 0x9b; + } else if (lo >= 0xa1 && lo <= 0xf6) { /* katakana */ + hi = 0x25; + } else if (lo >= 0xfb && lo <= 0xfe) { + tbl = u30fb; + lo -= 0xfb; + } else { + uni = 0; + } + break; + case 0xff00: + uni = 2; + if (lo <= 0x0f) { + tbl = uff01; + lo -= 0x01; + } else if (lo <= 0x19) { /* full width digit */ + hi = 0x23; + lo += 0x21; + } else if (lo <= 0x20) { + tbl = uff1a; + lo -= 0x1a; + } else if ((lo <= 0x3a) || (lo >= 0x41 && lo <= 0x5a)) { + hi = 0x23; + lo += 0x20; + } else if (lo <= 0x40) { + tbl = uff3b; + lo -= 0x3b; + } else if (lo <= 0x5d) { + tbl = uff5b; + lo -= 0x5b; + } else if (lo >= 0x61 && lo <= 0x9f) { + hi = 0x8e; /* half width katakana */ + lo += 0x40; + } else { + uni = 0; + } + break; + default: +#if SLRN_UNICODE_KANJI_CONVERT + hi = uni - 0x4e00; + if (hi >= 0 && hi < 0x5200) { + j = 0; + tbl = jis2ucs; + while (tbl - jis2ucs < sizeof(jis2ucs)) { + lo = *tbl++; + if (lo < 0x52) { + uni = (lo << 8) | *tbl++; + } else if (lo & 0x80) { + uni += lo & 0x7f; + } else { + uni -= lo - 0x51; + } + if (uni == hi) { + hi = j / 0x5e + 0x30; + lo = j % 0x5e + 0x21; + uni = 2; + break; + } + j++; + } + tbl = NULL; + } +#endif + if (uni != 2) { + uni = 0; + } + } + + if (tbl != NULL) { + lo = tbl[lo]; + if (lo) { + hi = 0x21; + if (lo & 0x80) { + hi++; + lo &= 0x7f; + } + } else { + uni = 0; + } + } + if (uni == 1) { + *d = (unsigned char)lo; + return (1); + } + if (uni == 0) { + hi = lo = 0xa2; /* 変換できないので '□'に置き換える */ + } else { + hi |= 0x80; + lo |= 0x80; + } + *d = (unsigned char)hi; + *(d + 1) = (unsigned char)lo; + return (2); +} + +static void utf82int(unsigned char *s) +{ + unsigned char *d, *orig = s; + int ch, ch2; + + d = s; + while(*s) { + ch = *s++; + if (ch & 0x80) { + ch2 = *s++; + if (ch2 == '\0' || (ch2 & 0x80) == 0) { + break; + } + ch = (ch << 6) | (ch2 & 0x3f); + if (ch & 0x0800) { + ch2 = *s++; + if (ch2 == '\0' || (ch2 & 0x80) == 0) { + break; + } + if (ch & 0x0400) { + while (ch & 0x0400) { + s++; + ch <<= 1; + } + ch = 0x25a1; /* UCS-4 is not supported, so display '□' */ + } else { + ch = ((ch & 0x03ff) << 6) | (ch2 & 0x3f); + } + } else { + ch &= 0x07ff; + } + d += ucs2toeuc(d, ch); + } else { + *d++ = ch; + } + } + *d = '\0'; + + han2zen_int(orig); +} + +static void utf162int(unsigned char *s) +{ + static int big_endian = 0; + unsigned char *d, *orig = s; + int ch, ch2; + + d = s; + while(*s) { + ch = *s++; + ch2 = *s++; + if (ch == 0xff && ch2 == 0xfe) { + big_endian = 0; + } else if (ch == 0xfe && ch2 == 0xff) { + big_endian = 1; + } else { + if (big_endian) { + ch = (ch << 8) | ch2; + } else { + ch |= ch2 << 8; + } + d += ucs2toeuc(d, ch); + } + } + *d = '\0'; + + han2zen_int(orig); +} + +/* returns 0 if succeeded, 1 if contains control code, 2 if found 8bit char */ +static int utf72int(unsigned char *s) +{ + unsigned char *d, *orig = s; + int ch, ch2, uni; + int count = 0; /* current number of utf-7 encoded characters. */ + /* This is set to 1 at each 8 characters */ + /* zero means not encoded */ + + d = s; + while (*s) { + ch = *s++; + if (ch < ' ') { + return 1; + } + if (ch & 0x80) { + return 2; + } + if (count == 0) { + if (ch != '+') { + *d++ = ch; + } else if (*s == '-') { /* A sequence '+-' represents '+'. */ + *d++ = '+'; + s++; + } else { + count = 1; + uni = 0; + } + } else { + ch2 = slrn_base64(ch); + if (ch2 != -1) { + if (count == 4) { + uni = (((uni & 0x03) << 6) | ch2) << 8; + } else if (count == 7) { + uni = (((uni & 0x0f) << 6) | ch2) << 6; + } else { + uni |= (ch2 << ((52 - count * 6) % 16)) >> 4; + } + } else { + if (ch != '-') { + *d++ = ch; + } + count = 0; + continue; + } + if (count == 3 || count == 6 || count == 8) { + /* convert to EUC */ + d += ucs2toeuc(d, uni); + if (count == 8) { + uni = 0; + count = 0; + } else { /* make next unicode */ + uni = ch2; + } + } + count++; + } + } + *d = '\0'; + + han2zen_int(orig); + + return 0; +} + +/* + * JIS -> internal code(EUC) + * internal code とは EUC であるが、半角カタカナは含まない(全角に変換する)。 + * return (入力コードが) + * 0: ASCII + * 1: JIS + * 2: 不正な JIS + * 3: EUC (他の 8bit 系コードかも知れない) + * 4: SJIS + * 5: SJIS と思われるがそうでないかも知れない + * 6: 8bit で SJIS でも EUC でもない + */ +int slrn_jis2int(unsigned char *d, unsigned char *s, int dlen) +{ + unsigned char *p = s; + unsigned int ch, hibit = 0; + int ret; + + ret = jis2euc(d, s, dlen); /* まずは EUC に変換する */ + if (ret == 1 || ret == 2 || ret == 4) { + han2zen_int(d); /* 半角カタカナを全角に変換する */ + } + switch (ret) { + case 0: /* ASCII */ + return (0); + case 1: /* JIS */ + return (1); + case 4: /* JIS の途中で切れた。*/ + return (2); + case 2: /* EUC */ + return (3); + case 3: /* SJIS? */ + /* SJISくさかったらSJIS->EUCする */ + ret = sjis2euc(d, s, dlen); + if (ret != 0) return (6); + han2zen_int(d); /* 半角カタカナを全角に変換する */ + /* 8bit 文字に比べて ASCII が非常に多ければ日本語でないとみなす */ + /* 8bit 文字が 1 つおきに 3 つ連続していれば SJIS とみなす */ + /* 0x80 - 0x9f にあれば ISO-8859-X ではない(かといって SJIS であるとも + 言えないが SJIS でということにする) */ + /* もうちょっと正確に判定が出来るように、改良が必要!! */ + while((ch = *p++) != 0) { + if (ch & 0x80) { + hibit++; + if (ch < 0xa0 || (ch != *p && ch != *(p + 1) && + (*(p + 1) & 0x80) && + (*(p + 3) & 0x80))) return (4); + } + } + if (hibit * 9 > strlen((char *)s)) return (4); + return (5); + case 5: /* utf-8 */ + strcpy((char *)d, (char *)s); + utf82int(d); + return 1; + } + return (6); +} + +/* + * universal code covert routine + */ +static int convcode(unsigned char *d, unsigned char *s, int dlen, int code) +{ + static unsigned char jstr[SLRN_TMP_STR_LEN + 1]; + int ret; + + ret = slrn_jis2int(jstr, s, dlen); + if (ret == 6) { + strcpy((char *)d, (char *)s); + return 1; + } + switch(code) { + case JIS: + return (int2jis(d, jstr, dlen)); + case SJIS: + return (int2sjis(d, jstr, dlen)); + case EUC: + strcpy((char *)d, (char *)jstr); + } + return 0; +} + +/* 文字列を code で指定されたコードに変換する */ +void slrn_conv_string(char *line, int code) +{ + static unsigned char jstr[SLRN_TMP_STR_LEN]; + + (void)convcode(jstr, (unsigned char *)line, SLRN_TMP_STR_LEN, code); + (void)strcpy(line, (char *)jstr); +} + +/* ファイルを code で指定されたコードに変換する */ +int slrn_conv_file(char *file, int code) +{ + FILE *fin, *fout; + char line[4096], tmpfile[SLRN_MAX_PATH_LEN]; + char *mess = "Error on opening file: %s"; + int ret = 0; + unsigned int len; + + fin = fopen(file, "r"); + if (fin == NULL) { + slrn_error(mess, file); + return -1; + } + + fout = slrn_open_tmpfile (tmpfile, "w"); + if (fout == NULL) { + slrn_error(mess, tmpfile); + return -1; + } + + while (fgets (line, sizeof(line), fin) != NULL) { + len = strlen (line); + if (len == 0) continue; + len--; + + if (line[len] == '\n') line[len] = '\0'; + slrn_conv_string(line, code); + if (fputs(line, fout) == EOF) { + slrn_error ("Error on writing file: %s. Disk Full?", tmpfile); + ret = -1; + break; + } + putc('\n', fout); + } + + if (slrn_fclose (fout) == -1) { + ret = -1; + } + + slrn_fclose (fin); + + if (ret == -1) { + (void) slrn_delete_file (tmpfile); + return -1; + } + + return slrn_move_file(tmpfile, file); +} + +#define match_2byte(c1, c2) ((((c1) > '\040' && (c1) < '\050') \ + || ((c1) > '\057' && (c1) < '\165')) \ + && (c2) > '\040' && (c2) < '\177') + +#define match_kin(c1, c2) ((c1) == '$' \ + && ((c2) == '@' || (c2) == 'B')) + +#define match_kout(c1, c2) ((c1) == '(' \ + && ((c2) == 'J' || (c2) == 'B')) + +/* ESC の落ちた JIS encoding を EUC に変換する。変換した場合は */ +/* 1 を返す。*/ +int slrn_recover_jis(unsigned char *to, unsigned char *from, int max) +{ + static unsigned char jtmp[SLRN_TMP_STR_LEN]; + unsigned char *orig_ptr = from, *buf = jtmp, c1, c2; + int len, eflag = 0; + + while(*from != '\0' && from - orig_ptr < SLRN_TMP_STR_LEN) { + if (match_kin(*from, *(from + 1))){ + if (from > orig_ptr && *(from - 1) == '\033') { + eflag = 1; + } + len = 2; + while(*(from + len) != '\0' && from - orig_ptr < max - len) { + c1 = *(from + len); + c2 = *(from + len + 1); + if (match_2byte(c1, c2)) { /* 2byte charcter */ + len += 2; + } else if (c1 == '\040') { /* space */ + len++; + } else if (c1 == '\033') { + if (match_kin(c2, *(from + len + 2)) && eflag == 0) { + break; /* real kin sequence */ + } + len++; /* only a escape character */ + } else { /* not a mutibyte character sequence */ + if (match_kout(c1, c2) /* kout sequence */ + && (eflag == 0 || *(from + len - 1) == '\033')) { + if (eflag == 0) { + *buf++ = '\033'; + } + while(len > 0) { + *buf++ = *from++; + len--; + } + if (*(from - 1) != '\033') { + *buf++ = '\033'; + } + } + break; + } + } + eflag = 0; + } + *buf = *from; + from++; + buf++; + } + *buf = '\0'; + return (slrn_jis2int(to, jtmp, max)); +} + +/* koi8-r を ISO-8859-5 に変換する */ +void slrn_convert_koi8_r2iso8859_5(unsigned char *s) +{ + while(*s != '\0') { + if (*s >= 0xa0) { + *s = koi8_table[*s - 0xa0]; + } + s++; + } +} + +/* + * charset に応じて変換を行う。charset が USASCII ならば slrn_jis2int() を + * 呼び出す。 + */ +int slrn_all2int(unsigned char *d, unsigned char *s, int dlen, Charset_Type charset) +{ + int ret = 0; + + switch(charset) { + case UTF8: + utf82int(s); + break; + case UTF16: + utf162int(s); + break; + case UTF7: + if (utf72int(s) != 0) { + if (detect_utf8(s)) { + utf82int(s); + } else { + return slrn_jis2int(d, s, dlen); + } + } + break; + case SHIFTJIS: + ret = sjis2euc(d, s, dlen); + + if (ret == 0) { + han2zen_int(d); /* 半角カタカナを全角に変換する */ + } + ret = 4; + break; + default: + return slrn_jis2int(d, s, dlen); + } + return ret; +} + +#else /* KANJI */ #if SLRN_HAS_CHARACTER_MAP char *Slrn_Charset; @@ -245,3 +1251,4 @@ return -1; #endif } +#endif /* KANJI */ diff -Nru slrn-0.9.6.2.orig/src/chmap.h slrn-0.9.6.2/src/chmap.h --- slrn-0.9.6.2.orig/src/chmap.h Fri Dec 24 02:24:37 1999 +++ slrn-0.9.6.2/src/chmap.h Tue Dec 28 23:34:40 1999 @@ -19,6 +19,70 @@ */ #ifndef _SLRN_CHMAP_H #define _SLRN_CHMAP_H +#ifdef KANJI +/* + $@ JIS X0208-1978 + $B,$(B JIS X0208-1983 + (I JIS X0201 kana + (J JIS X0201 roman + $(D JIS X0212-1990 補助漢字 + (B ASCII + + $ 36 24 @ 64 40 ( 40 28 B 66 42 + I 73 49 D 68 44 +*/ + +#ifdef SLANG_JVERSION +#include "slkanji.h" +#define Slang_Display_Code (kSLdisplay_code) +#else +#define ESC 0x1b +#define SS2 0x8e + +#define JIS 0 +#define EUC 1 +#define SJIS 2 +#ifndef IBMPC_SYSTEM +extern int Slang_Display_Code; /* 0 = JIS, 1 = EUC, 2 = SJIS */ +#else +#define Slang_Display_Code SJIS +#endif +#endif /* SLANG_JVERSION */ +extern int Slrn_Editor_Code; + +#define SI 0x0f +#define SO 0x0e + +#define IS_SJIS1(c) (((c) >= 0x81 && (c) <= 0x9f) || ((c) >= 0xe0 && (c) <= 0xef)) /* 2byte 文字のみ */ +#define IS_SJIS2(c) ((c) >= 0x40 && (c) <= 0xfc && (c) != 0x7f) +#define IS_SJISH(c) ((c) >= 0xa0 && (c) <= 0xdf) /* SJIS hankaku katakana */ + +#define IS_EUC1(x) (((x) >= 0xa1 && (x) <= 0xa8) || (x) == 0xad || ((x) >= 0xb0 && (x) <= 0xf4)) + +#define IS_EUC2(x) ((x) >= 0xa1 && (x) <= 0xfe) + +extern int slrn_jis2int(unsigned char *, unsigned char *, int); +extern int slrn_all2int(unsigned char *, unsigned char *, int, Charset_Type); +extern int slrn_recover_jis(unsigned char *, unsigned char *, int); + +extern int slrn_conv_file(char *, int); +extern void slrn_conv_string(char *, int); + +extern void slrn_convert_koi8_r2iso8859_5(unsigned char *); + +#define SLRN_TMP_STR_LEN 4095 +extern unsigned char Slrn_Tmp_Str[]; + +extern int Slrn_Detect_SJIS; + +extern int Slrn_Japanese_Messages; +#ifndef IBMPC_SYSTEM +extern int Slang_Current_Charset; +#ifndef SLANG_JVERSION +extern int Slang_Use_ISO8859; +#endif +#endif +#else extern int slrn_set_charset (char *); extern int slrn_chmap_fix_file (char *); extern void slrn_chmap_fix_body (Slrn_Article_Type *); @@ -27,6 +91,7 @@ #if SLRN_HAS_CHARACTER_MAP extern char *Slrn_Charset; extern void slrn_chmap_show_supported (void); +#endif #endif #endif diff -Nru slrn-0.9.6.2.orig/src/clientlib.h slrn-0.9.6.2/src/clientlib.h --- slrn-0.9.6.2.orig/src/clientlib.h Fri Dec 24 02:24:39 1999 +++ slrn-0.9.6.2/src/clientlib.h Mon Dec 27 10:46:04 1999 @@ -1,6 +1,9 @@ #ifndef _SLTCP_H_LOADED_ #define _SLTCP_H_LOADED_ +#ifdef KANJI +#include +#endif typedef struct { int tcp_fd; diff -Nru slrn-0.9.6.2.orig/src/editscore.c slrn-0.9.6.2/src/editscore.c --- slrn-0.9.6.2.orig/src/editscore.c Fri Dec 24 02:24:44 1999 +++ slrn-0.9.6.2/src/editscore.c Mon Dec 27 10:46:04 1999 @@ -32,6 +32,9 @@ #include #include "jdmacros.h" +#ifdef KANJI +#include "chmap.h" +#endif #include "group.h" #include "art.h" #include "startup.h" @@ -64,7 +67,13 @@ if (Slrn_Prefix_Arg_Ptr == NULL) { +#ifdef KANJI + ch = slrn_get_response ("SsFfRrEeCc\007", Slrn_Japanese_Messages + ? "スコアの種類を選択: \001Subject, \001From, \001References, \001Edit, \001Cancel" + : "Pick Score type: \001Subject, \001From, \001References, \001Edit, \001Cancel"); +#else ch = slrn_get_response ("SsFfRrEeCc\007", "Pick Score type: \001Subject, \001From, \001References, \001Edit, \001Cancel"); +#endif if (ch == 7) return -1; ch |= 0x20; if (ch == 'c') return -1; @@ -74,13 +83,25 @@ return -1; if (score == 0) return -1; +#ifdef KANJI + if ('a' == (0x20 | slrn_get_response ("TtaA", Slrn_Japanese_Messages + ? "どのニュースグループ: \001This(このグループ), \001All(すべてのグループ)" + : "Which newsgroups: \001This group, \001All groups"))) +#else if ('a' == (0x20 | slrn_get_response ("TtaA", "Which newsgroups: \001This group, \001All groups"))) +#endif ng = "*"; while (1) { *qregexp = 0; +#ifdef KANJI + if (-1 == slrn_read_input (Slrn_Japanese_Messages + ? "期限 (MM/DD/YYYY か DD-MM-YYYY または空欄のまま)" + : "Expires (MM/DD/YYYY or DD-MM-YYYY or leave blank)", NULL, qregexp, 1, 0)) +#else if (-1 == slrn_read_input ("Expires (MM/DD/YYYY or DD-MM-YYYY or leave blank)", NULL, qregexp, 1, 0)) +#endif return -1; if (*qregexp) { @@ -159,6 +180,11 @@ if (-1 == slrn_fclose (fp)) return -1; +#ifdef KANJI + /* 書き出したスコアファイルを editor コードに変換する */ + if (Slrn_Editor_Code != EUC + && slrn_conv_file(file, Slrn_Editor_Code) == -1) return (-1); +#endif if (ch == 'e') { int status; diff -Nru slrn-0.9.6.2.orig/src/group.c slrn-0.9.6.2/src/group.c --- slrn-0.9.6.2.orig/src/group.c Fri Dec 24 02:24:39 1999 +++ slrn-0.9.6.2/src/group.c Mon Dec 27 10:46:04 1999 @@ -47,6 +47,9 @@ #include #include "jdmacros.h" +#ifdef KANJI +#include "chmap.h" +#endif #include "slrn.h" #include "group.h" #include "art.h" @@ -280,7 +283,13 @@ group = g->name; +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "%s を選択中 ... " + : "Selecting %s ...", group); +#else slrn_message_now ("Selecting %s ...", group); +#endif status = Slrn_Server_Obj->sv_select_group (group, minp, maxp); if (status == -1) @@ -289,7 +298,13 @@ if (status != OK_GROUP) { g->flags |= GROUP_UNSUBSCRIBED; +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages + ? "このグループは無効のようです。" + : "This group appears to be bogus."); +#else slrn_error ("This group appears to be bogus."); +#endif return -1; } @@ -308,7 +323,13 @@ group_mark_article_as_read (g, n); /* g->unread = 0; */ +#ifdef KANJI + slrn_message (Slrn_Japanese_Messages + ? "読む記事はありません。" + : "No articles to read."); +#else slrn_message ("No articles to read."); +#endif Slrn_Full_Screen_Update = 1; Slrn_Groups_Dirty = 1; return -1; @@ -463,7 +484,13 @@ if (status != -1) { Slrn_Groups_Dirty = 1; +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages + ? "グループ %s は無効のようです。" + : "Group %s may be bogus.", g->name); +#else slrn_error ("Group %s may be bogus.", g->name); +#endif } SLFREE (g); return NULL; @@ -517,7 +544,13 @@ if (len > MAX_GROUP_NAME_LEN) len = MAX_GROUP_NAME_LEN; strncpy (namebuf, name, len); namebuf[len] = 0; +#ifdef KANJI + slrn_message_now(Slrn_Japanese_Messages + ? "グループ %s は無効です。無視します。" + : "Group %s is bogus, Ignoring it.", namebuf); +#else fprintf (stderr, "Group %s is bogus, Ignoring it.\r\n", namebuf); +#endif return -1; } else g = create_group_entry (name, len, -1, -1, @@ -789,7 +822,11 @@ int min, max, n, max_available, last_n; int ret; Slrn_Range_Type *r; +#ifdef KANJI + int prefix, direc = 0; +#else int prefix; +#endif if (Slrn_Prefix_Arg_Ptr != NULL) { @@ -807,14 +844,20 @@ n = Slrn_Group_Current_Group->unread; +#ifndef KANJI #if 1 if ((prefix == 0) && (n == 0) && (n != last_n)) return -1; #endif +#endif max_available = Slrn_Group_Current_Group->range.max - Slrn_Group_Current_Group->range.min + 1; +#ifdef KANJI + if ((prefix & 1) || (n == 0 && last_n == 0)) +#else if ((prefix & 1) || (n == 0)) +#endif n = max_available; if ((prefix & 1) || @@ -822,15 +865,32 @@ && (Slrn_Query_Group_Cutoff > 0))) { char int_prompt_buf[256]; +#ifdef KANJI + sprintf (int_prompt_buf, Slrn_Japanese_Messages + ? "%s: いくつ読みますか?" + : "%s: Read how many?", Slrn_Group_Current_Group->name); +#else sprintf (int_prompt_buf, "%s: Read how many?", Slrn_Group_Current_Group->name); +#endif if ((-1 == slrn_read_integer (int_prompt_buf, &n, &n)) +#ifdef KANJI + /* 記事数にマイナスを付けた時、古い記事から読めるようにする */ + || (n == 0)) +#else || (n <= 0)) +#endif { slrn_clear_message (); Slrn_Full_Screen_Update = 1; return 0; } +#ifdef KANJI + if (n < 0) { + direc = 1; + } + else +#endif if ((0 == (prefix & 1)) && (Slrn_Group_Current_Group->unread != 0)) { @@ -851,7 +911,11 @@ n = 0; ret = slrn_select_article_mode (Slrn_Group_Current_Group, n, +#ifdef KANJI + ((prefix & 2) == 0), direc); +#else ((prefix & 2) == 0)); +#endif if (ret == -2) slrn_catchup_group (); @@ -902,7 +966,13 @@ { if (Slrn_User_Wants_Confirmation && (Slrn_Batch == 0) +#ifdef KANJI + && (slrn_get_yesno (1, Slrn_Japanese_Messages + ? "本当に抜けますか" + : "Do you really want to quit") <= 0)) return; +#else && (slrn_get_yesno (1, "Do you really want to quit") <= 0)) return; +#endif if ((Slrn_Groups_Dirty) && (-1 == slrn_write_newsrc ())) { @@ -992,12 +1062,24 @@ g = Slrn_Group_Current_Group; if (g == NULL) return; +#ifdef KANJI + if (slrn_read_input (Slrn_Japanese_Messages + ? "検索" + : "Search", search_str, NULL, 1, 0) <= 0) return; +#else if (slrn_read_input ("Search", search_str, NULL, 1, 0) <= 0) return; +#endif n = Group_Window.line_num; if (0 == slrn_group_search (search_str)) { +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages + ? "見つかりません。" + : "Not found."); +#else slrn_error ("Not found."); +#endif return; } @@ -1012,7 +1094,13 @@ char group[256]; *group = 0; +#ifdef KANJI + if (slrn_read_input (Slrn_Japanese_Messages + ? "グループの追加" + : "Add group", NULL, group, 1, 0) > 0) +#else if (slrn_read_input ("Add group", NULL, group, 1, 0) > 0) +#endif { if (!find_group (group) && (Slrn_List_Active_File == 0)) @@ -1086,7 +1174,13 @@ while (1) { +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "%s を移動中。終了時は RETURN を押す。" + : "Moving %s. Press RETURN when finished.", Slrn_Group_Current_Group->name); +#else slrn_message_now ("Moving %s. Press RETURN when finished.", Slrn_Group_Current_Group->name); +#endif key = SLang_do_key (Slrn_Group_Keymap, (int (*)(void)) SLang_getkey); @@ -1147,7 +1241,13 @@ Slrn_Prefix_Arg_Ptr = NULL; +#ifdef KANJI + if (NULL == (re = read_group_regexp (Slrn_Japanese_Messages + ? "購読するパターン" + : "Subscribe pattern", NULL))) +#else if (NULL == (re = read_group_regexp ("Subscribe pattern", NULL))) +#endif return; g = Groups; @@ -1175,11 +1275,23 @@ if ((Slrn_Group_Current_Group == NULL) || (Slrn_User_Wants_Confirmation && (Slrn_Batch == 0) +#ifdef KANJI + && slrn_get_yesno(1, Slrn_Japanese_Messages + ? "%s を既読にマークしますか" + : "Mark %s as read", Slrn_Group_Current_Group->name) <= 0)) +#else && slrn_get_yesno(1, "Mark %s as read", Slrn_Group_Current_Group->name) <= 0)) +#endif return; slrn_catchup_group (); +#ifdef KANJI + slrn_message (Slrn_Japanese_Messages + ? "グループを既読にマークしました。" + : "Group marked as read."); +#else slrn_message ("Group marked as read."); +#endif (void) slrn_group_down_n (1); } @@ -1190,11 +1302,23 @@ if ((Slrn_Group_Current_Group == NULL) || (Slrn_User_Wants_Confirmation && (Slrn_Batch == 0) +#ifdef KANJI + && slrn_get_yesno(1, Slrn_Japanese_Messages + ? "%s を未読にマークしますか" + : "Mark %s as un-read", Slrn_Group_Current_Group->name) <= 0)) +#else && slrn_get_yesno(1, "Mark %s as un-read", Slrn_Group_Current_Group->name) <= 0)) +#endif return; slrn_uncatchup_group (); +#ifdef KANJI + slrn_message (Slrn_Japanese_Messages + ? "グループを未読にマークしました。" + : "Group marked as un-read."); +#else slrn_message ("Group marked as un-read."); +#endif (void) slrn_group_down_n (1); } @@ -1217,7 +1341,13 @@ Slrn_Prefix_Arg_Ptr = NULL; +#ifdef KANJI + if (NULL == (re = read_group_regexp (Slrn_Japanese_Messages + ? "購読しないパターン" + : "Un-Subscribe pattern", NULL))) +#else if (NULL == (re = read_group_regexp ("Un-Subscribe pattern", NULL))) +#endif return; g = Groups; @@ -1408,7 +1538,13 @@ static void select_group_cmd (void) { if (-1 == slrn_group_select_group ()) +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages + ? "未読記事はありません。" + : "No unread articles."); +#else slrn_error ("No unread articles."); +#endif } void slrn_post_cmd (void) /*{{{*/ @@ -1419,7 +1555,13 @@ if (Slrn_Post_Obj->po_can_post == 0) { +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages + ? "投稿が許可されていません。" + : "Posting not allowed."); +#else slrn_error ("Posting not allowed."); +#endif return; } @@ -1429,8 +1571,15 @@ return; #endif +#ifdef KANJI + if (Slrn_User_Wants_Confirmation && (Slrn_Batch == 0) && + (slrn_get_yesno (1, Slrn_Japanese_Messages + ? "本当に投稿しますか" + : "Are you sure that you want to post") <= 0)) +#else if (Slrn_User_Wants_Confirmation && (Slrn_Batch == 0) && (slrn_get_yesno (1, "Are you sure that you want to post") <= 0)) +#endif return; if (Slrn_Group_Current_Group == NULL) name = ""; else name = Slrn_Group_Current_Group->name; @@ -1448,8 +1597,15 @@ if (-1 == slrn_check_batch ()) return; +#ifdef KANJI + switch (slrn_get_response ("FfSsNnCc\007", + Slrn_Japanese_Messages + ? "スコア付けのモード選択: \001Full(完全), \001Simple(簡易), \001None(なし), \001Cancel" + : "Select scoring mode: \001Full, \001Simple, \001None, \001Cancel")) +#else switch (slrn_get_response ("FfSsNnCc\007", "Select scoring mode: \001Full, \001Simple, \001None, \001Cancel")) +#endif { case 'F': case 'f': @@ -1485,7 +1641,13 @@ } else { +#ifdef KANJI + slrn_message (Slrn_Japanese_Messages + ? "セーブすべき変更はありません。" + : "No changes need to be saved."); +#else slrn_message ("No changes need to be saved."); +#endif } slrn_smg_refresh (); } @@ -2063,7 +2225,13 @@ if (num) { +#ifdef KANJI + slrn_message (Slrn_Japanese_Messages + ? "新しいニュースグループが %d ありました。" + : "%d new newsgroup(s) found.", num); +#else slrn_message ("%d new newsgroup(s) found.", num); +#endif } } else time (&tloc); @@ -2183,6 +2351,11 @@ slrn_exit_error ("Unable to create %s.", file); } +#ifdef KANJI + if (Slrn_Japanese_Messages) + slrn_message_now ("\n--次のステップは NNTP 接続が低速の場合しばらくかかります。--\n\n"); + else +#endif fputs ("\n--The next step may take a while if the NNTP connection is slow.--\n\n", stdout); fprintf (stdout, "Creating %s.", file); fflush (stdout); @@ -2235,6 +2408,15 @@ { add_group (line, len, 0, 1); } +#ifdef KANJI + if (((*line == 'f') + && (!strncmp (line, "fj.questions", 12) + || !strncmp (line, "fj.news.reader", 14))) || + (*line == 'j' && !strncmp(line, "japan.netnews.reader", 20))) + { + add_group (line, len, 0, 1); + } +#endif else if ((*line == 'a') && (!strncmp (line, "alt.test", 8))) { @@ -2377,7 +2559,13 @@ */ if (fp != NULL) slrn_fclose (fp); fp = NULL; +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "%s を書き込み中 ..." + : "Writing %s ...", Slrn_Newsrc_File); +#else slrn_message_now ("Writing %s ...", Slrn_Newsrc_File); +#endif slrn_make_home_filename (Slrn_Newsrc_File, file); @@ -2529,7 +2717,13 @@ Slrn_Groups_Dirty = 0; if (Slrn_TT_Initialized & SLRN_TTY_INIT) +#ifdef KANJI + slrn_message (Slrn_Japanese_Messages + ? "%s を書き込み中 ... 終了。" + : "Writing %s ... done.", Slrn_Newsrc_File); +#else slrn_message ("Writing %s ... done.", Slrn_Newsrc_File); +#endif slrn_init_hangup_signals (1); return 0; diff -Nru slrn-0.9.6.2.orig/src/help.c slrn-0.9.6.2/src/help.c --- slrn-0.9.6.2.orig/src/help.c Fri Dec 24 02:24:38 1999 +++ slrn-0.9.6.2/src/help.c Mon Dec 27 14:40:32 1999 @@ -33,6 +33,9 @@ #include "slrn.h" #include "misc.h" #include "util.h" +#ifdef KANJI +#include "chmap.h" +#endif static char *Global_Help [] = { @@ -44,6 +47,20 @@ NULL }; +#ifdef KANJI +/* このhelp.cはEUCでセーブすること。*/ + +static char *Global_Help_J [] = +{ + " slrnについての詳しい情報は、news.software.readers と alt.lang.s-lang ", + " というニュースグループを読んでください(日本ではfj.news.reader)。", + " バグレポート、提案やコメントはdavis@space.mit.eduまでどうぞ", + " (日本語版に関してはkikutani@galaxy.netまで)" + "", + NULL +}; +#endif + static char *Art_Help[] = { "Searching:", @@ -74,6 +91,9 @@ #if SLRN_HAS_GROUPLENS " 0 Assign article a GroupLens rating.", #endif +#if defined(KANJI) && defined(SLRN_HAS_MIME) + " ESC m Toggle on/off decoding MIME article.", +#endif "Posting, Replying, Printing, Piping, and Saving:", " y Send the article to the printer", " P Post a new article (NOT followup)", @@ -128,6 +148,96 @@ " U Search for URL and follow it", NULL }; +#ifdef KANJI +static char *Art_Help_J[] = +{ + "検索:", + " / 記事の前方検索。", + " a 著者の前方検索。", + " A 著者の後方検索。", + " s サブジェクトの前方検索。", + " S サブジェクトの後方検索。", + " = 指定したサブジェクトで次の記事にスキップ", + " ! 次のハイスコアの記事にスキップ", + " ESC-l メッセージIDで記事を検索。", + "記事に影響を与えるコマンド:", + " h 記事ウインドを隠す(ヘッダウインドを拡大)", + " SPACE 記事の選択、または次頁へスクロール", + " DEL, b 1頁バックスクロール", + " ESC-UP 記事を1行スクロールアップ", + " ESC-DOWN 記事を1行スクロールダウン", + " RIGHT 記事を右へパン", + " LEFT 記事を左へパン", + " W 記事を折りかえすかどうかのトグル", + " t 重要でないヘッダを表示するかどうかのトグル。", + " T 引用された行を表示するかどうかのトグル。", + " TAB 引用された行の下にスキップ。", + " ESC-r ROT 13 を復号するかどうかのトグル。", + " g 次の「ダイジェスト記事」にスキップ。", + " ESC Ctrl-C 記事のキャンセル(著者でないとだめ)。", + " ESC Ctrl-S 記事の supersede。もとのテキストを編集できる", +#if SLRN_HAS_GROUPLENS + " 0 記事にGroupLensのレートを付ける。", +#endif +#if defined(SLRN_HAS_MIME) && defined(KANJI) + " ESC m 記事の MIME のデコードのトグル", +#endif + "ポスト、リプライ、印刷、パイプ、セーブ:", + " y 記事をプリンタに送る", + " P 新しい記事の投稿(フォローではない)", + " ESC P あと回しにした記事の投稿または編集", + " f 現在の記事にフォロー。", + " 注: ESC 1 f ==> ヘッダもすべて挿入される。", + " ESC 2 f ==> 記事が引用符なしで挿入される。", + " F 記事のフォワード", + " r 記事をポストした人にリプライ", + " o 記事やスレッド、またはタグを付けた記事をファイルに追加する", + " : 記事、番号タグを付けた記事、あるいはスレッドをデコードする。", + " # 保存やデコードのために記事に番号タグを付ける。", + " ESC # 番号タグを消す。", + " | 記事を外部コマンドにパイプでわたす。", + "ヘッダウインドウに関するコマンド:", + " d 記事に読んだ印を付け、次の未読に移動。", + " ESC-d スレッドに読んだ印を付け、次の未読に移動。", + " u 記事を読まなかったことにする", + " p 前の未読記事に移動", + " n 次の未読記事に移動する、もし最後ならば次のグループに。", + " L 最後に読んだ記事に移動。", + " N 次のニュースグループにスキップ。", + " UP 前の記事に移動", + " DOWN 次の記事に移動", + " ; 現在の位置をマークを付ける", + " , まずマークを付けて、前にマークした位置に戻る", + " q グループモードに戻る", + " Ctrl-^ またはCtrl-6", + " ヘッダウィンドウを一行縮小", + " ^ ヘッダウィンドウを一行拡大", + " ESC t スレッドのツリー表示のトグル", + " 注: プレフィクス引数はすべてのスレッドに作用させるのに使う。", + " ESC > ヘッダリストの最後に移動", + " ESC < ヘッダリストの最初に移動", + " Ctrl-U ヘッダウィンドウでページアップ。", + " Ctrl-D ヘッダウィンドウでページダウン。", + " ESC-a ヘッダ表示形式を変更", + " ESC-s ソート方法の選択。", + " ESC-p 親記事のヘッダを探す。必要ならサーバから読む", + " ESC 1 ESC p スレッドを再構築する", + " ESC Ctrl-P 現在のヘッダの子記事をすべて探す(必要ならサーバから)", + " c キャッチアップ(すべての記事を読んだことにする)。", + " ESC-u すべての記事を読まなかったことにする", + " C 現在の位置の手前までの記事を読んだことにする", + " ESC-U 現在の位置の手前までの記事を読まなかったことにする", + " K 現在のヘッダを元にスコアエントリを作る。。", + " ESC 1 K スコアファイルを編集する。", + " * キャッチアップコマンドが影響しないマークをヘッダに付ける。", + " ESC 1 * '*'で付けたマークをすべて消す。", + " x 既読記事をすべてリストから消す。", + "その他のコマンド:", + " . (ピリオド)最後のキーシーケンスを繰り返す", + " U URLを探してそれを見に行く", + NULL +}; +#endif static char *Group_Help [] = { @@ -181,6 +291,64 @@ NULL }; +#ifdef KANJI +static char *Group_Help_J [] = +{ + " 注: キーは大文字/小文字を区別します! つまり「s」と「S」は別のものです。", + " いくつかのコマンドでは「プレフィクス引数」が使えます。これはESC", + " キーを押したのち、数字キーを押し、次に実行したいコマンドのキー", + " シーケンスを押すことです。", + "", + "ニュースグループの購読と購読中止について:", + " 1. 大文字の'L'を押し、表示させるグループ名を入力する: たとえば", + " *.music.* は 'music' の付くすべてのグループが表示される。", + " 2. 購読したいグループに移動し、's'を押す。", + " このステップをそれぞれのグループについて繰り返す。", + " 3. 購読中のグループのみを表示させるために再度、大文字の'L'を押す。", + "現在のグループに影響を与えるコマンド:", + " P 現在のニュースグループに記事を投稿", + " ESC P あと回しにした記事の投稿または編集", + " SPACE, RETURN 現在のニュースグループを選択する。", + " 次の三つの形式では、以前に読んだ記事を見ることができる:", + " ESC 1 SPACE グループを選択する時、読む記事数を入力する。", + " ESC 2 SPACE グループを選択する時、スコアを適用しない。", + " ESC 3 SPACE グループを選択する時、数を入れて、スコアを適用しない", + " s 現在のニュースグループを購読する", + " ESC 1 s パターンで購読する", + " u 現在のニュースグループの購読を中止する", + " ESC 1 u パターンで購読を中止する", + " c キャッチアップ---すべての記事を読んだことにする", + " ESC u キャッチアップの逆--すべての記事を読まなかったことにする", + "移動コマンド:", + " ESC < リストの最初に移動", + " ESC > リストの最後に移動", + " Ctrl-V, Ctrl-D 次ページにスクロール", + " ESC V, Ctrl-U 前ページにスクロール", + " DOWN 次のグループに移動", + " UP 前のグループに移動", + "その他のコマンド:", + " a 新しいグループを加える('L'のヘルプも参照のこと)", + " Ctrl-L, Ctrl-R 画面再描画", + " Ctrl-Z ニュースリーダをサスペンド", + " l 未読の記事がないグループの表示のトグル", + " L 購読していないグループの表示のトグル", + " ESC 1 L 購読していないグループを隠す", + " / グループをキーワードで検索。隠しているグループを", + " 検索するときは'l'を使う。", + " q ニュースリーダの終了", + " G 新しい記事の取得", + " K スコアモードのトグル", + " X newsrcファイルに強制的に書き出す。", + " ESC-a グループ記述表示をトグル。", + " Ctrl-X Ctrl-T グループの位置を交換する。", + " m グループを別の場所に移動する。", + " . (ピリオド) 最後のキーシーケンスを繰り返す", + NULL +}; + +int Slrn_Japanese_Messages = 0; +#endif + #define MAX_HELP_LINES 256 static char *User_Article_Help[MAX_HELP_LINES]; static char *User_Group_Help[MAX_HELP_LINES]; @@ -191,8 +359,15 @@ char **p, *sect = NULL; char quit; char **this_help; +#ifdef KANJI +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + int charset = Slang_Current_Charset; +#endif + this_help = p = Slrn_Japanese_Messages ? Global_Help_J : Global_Help; +#else this_help = p = Global_Help; +#endif slrn_enable_mouse (0); @@ -202,6 +377,11 @@ if (*p == NULL) break; slrn_push_suspension (0); +#ifdef KANJI +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + Slang_Current_Charset = ISO2022JP; +#endif +#endif SLsmg_cls (); @@ -211,7 +391,13 @@ SLsmg_gotorc (i, 0); SLsmg_write_string (sect); SLsmg_set_color (0); +#ifdef KANJI + SLsmg_write_string (Slrn_Japanese_Messages + ? " (続き...)" + : " (continued)"); +#else SLsmg_write_string (" (continued)"); +#endif i += 2; } @@ -249,7 +435,11 @@ SLsmg_set_color (1); if ((*p == NULL) +#ifdef KANJI + && (this_help == (Slrn_Japanese_Messages ? Global_Help_J : Global_Help))) +#else && (this_help == Global_Help)) +#endif { this_help = p = help; sect = NULL; @@ -257,15 +447,36 @@ if (*p == NULL) { +#ifdef KANJI + SLsmg_write_string (Slrn_Japanese_Messages + ? "\ +'?'を押すとヘルプの最初から。ほかのキーを押すとニュースリーダーに戻ります" + : "\ +Press '?' to start over, or any other key to return to news reader." +#else SLsmg_write_string ("\ Press '?' to start over, or any other key to return to news reader." +#endif ); } +#ifdef KANJI + else SLsmg_write_string (Slrn_Japanese_Messages + ? "\ +'q'を押すとヘルプから抜けます。また'?'を押すと最初から、他のキーで続きを" + : "\ +Press 'q' to quit help, '?' to start over, or any other key to continue." +#else else SLsmg_write_string ("\ Press 'q' to quit help, '?' to start over, or any other key to continue." +#endif ); slrn_smg_refresh (); +#ifdef KANJI +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + Slang_Current_Charset = charset; +#endif +#endif slrn_pop_suspension (); @@ -273,7 +484,11 @@ quit = SLang_getkey (); if (quit == '?') { +#ifdef KANJI + this_help = p = (Slrn_Japanese_Messages ? Global_Help_J : Global_Help); +#else this_help = p = Global_Help; +#endif sect = NULL; } else if ((*p == NULL) || ((quit | 0x20)== 'q')) @@ -359,7 +574,11 @@ { char **h; if (Slrn_Batch) return; +#ifdef KANJI + if (User_Article_Help[0] != NULL) h = User_Article_Help; else h = Slrn_Japanese_Messages ? Art_Help_J : Art_Help; +#else if (User_Article_Help[0] != NULL) h = User_Article_Help; else h = Art_Help; +#endif do_help (h); } @@ -367,6 +586,10 @@ { char **h; if (Slrn_Batch) return; +#ifdef KANJI + if (User_Group_Help[0] != NULL) h = User_Group_Help; else h = Slrn_Japanese_Messages ? Group_Help_J : Group_Help; +#else if (User_Group_Help[0] != NULL) h = User_Group_Help; else h = Group_Help; +#endif do_help (h); } diff -Nru slrn-0.9.6.2.orig/src/interp.c slrn-0.9.6.2/src/interp.c --- slrn-0.9.6.2.orig/src/interp.c Fri Dec 24 02:24:43 1999 +++ slrn-0.9.6.2/src/interp.c Mon Dec 27 10:46:04 1999 @@ -46,6 +46,9 @@ #include "interp.h" #include "util.h" #include "print.h" +#ifdef KANJI +#include "chmap.h" +#endif /*}}}*/ @@ -199,6 +202,9 @@ { if (Slrn_Batch == 0) { +#ifdef KANJI + slrn_conv_string(s, Slang_Display_Code); +#endif SLtt_write_string (s); SLtt_flush_output (); } @@ -643,12 +649,23 @@ Slrn_Article_Line_Type *next = l->next; buf = l->buf; +#ifndef KANJI if (l->flags & WRAPPED_LINE) buf++; /* skip space */ +#endif while (*buf != 0) *s1++ = *buf++; if ((next == NULL) || (0 == (next->flags & WRAPPED_LINE))) *s1++ = '\n'; +#ifdef KANJI + else { /* skip backslash */ + if (((unsigned char)next->buf[0] & 0x80) + && *(s1 - 2) == '\\' && *(s1 - 1) != ' ') { + s1--; + } + s1--; + } +#endif l = next; } *s1 = 0; diff -Nru slrn-0.9.6.2.orig/src/jdmacros.h slrn-0.9.6.2/src/jdmacros.h --- slrn-0.9.6.2.orig/src/jdmacros.h Fri Dec 24 02:24:36 1999 +++ slrn-0.9.6.2/src/jdmacros.h Mon Dec 27 10:46:04 1999 @@ -80,4 +80,26 @@ # define SLREALLOC realloc #endif +#ifdef KANJI +typedef enum { + USASCII, + ISO88591, + ISO88592, + ISO88593, + ISO88594, + ISO88595, + ISO88596, + ISO88597, + ISO88598, + ISO88599, + KOI8R, + ISO2022JP, + ISO2022JP2, + SHIFTJIS, + UTF7, + UTF8, + UTF16, + UNKNOWN_CHARSET +} Charset_Type; +#endif #endif /* _JD_MACROS_H_ */ diff -Nru slrn-0.9.6.2.orig/src/menu.c slrn-0.9.6.2/src/menu.c --- slrn-0.9.6.2.orig/src/menu.c Fri Dec 24 02:24:38 1999 +++ slrn-0.9.6.2/src/menu.c Mon Dec 27 10:46:04 1999 @@ -38,6 +38,9 @@ #include #include "jdmacros.h" +#ifdef KANJI +#include "chmap.h" +#endif #include "slrn.h" #include "menu.h" #include "misc.h" @@ -203,6 +206,24 @@ NULL }; +#ifdef KANJI +static char *Sort_Selections_J [] = /*{{{*/ +{ + "ソートしない", /* 000 */ + "ヘッダをスレッド化", /* 001 */ + "Subject でソート", /* 010 */ + "スレッド化の後、Subject でソートする。", /* 011 */ + "スコアでソートする。", /* 100 */ + "スレッド化の後、スコアでソートする。", /* 101 */ + "スコアと Subject でソートする。", /* 110 */ + "スレッド化の後、スコアと Subject でソートする。", /* 111 */ + "日付でソートする(最新が最初)", /* 1000 */ + "スレッド化の後、日付でソートする(最新が最初)", /* 1001 */ + "日付でソートする(最新が最後)", /* 1010 */ + "スレッド化の後、日付でソートする(最新が最後)", /* 1011 */ + NULL +}; +#endif /*}}}*/ static Slrn_Select_Box_Type Slrn_Sort_Select_Box = /*{{{*/ @@ -210,6 +231,12 @@ "Sorting Method", Sort_Selections }; +#ifdef KANJI +static Slrn_Select_Box_Type Slrn_Sort_Select_Box_J = /*{{{*/ +{ + "ソート方法", Sort_Selections_J +}; +#endif /*}}}*/ static void center_string_column (char *title, int row, int col, int num_columns) /*{{{*/ @@ -348,7 +375,13 @@ if ((rsp < 0) || (rsp >= num_selections)) { +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages + ? "取り消しました。" + : "Cancelled."); +#else slrn_error ("Cancelled."); +#endif while (SLang_input_pending (2)) (void) SLang_getkey (); @@ -363,6 +396,22 @@ int slrn_sbox_sorting_method (void) /*{{{*/ { +#ifdef KANJI +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + int i, charset = Slang_Current_Charset; + + if (Slrn_Japanese_Messages) { + Slang_Current_Charset = ISO2022JP; + i = slrn_select_box (&Slrn_Sort_Select_Box_J); + Slang_Current_Charset = charset; + return (i); + } else +#else + if (Slrn_Japanese_Messages) { + return slrn_select_box (&Slrn_Sort_Select_Box_J); + } else +#endif +#endif return slrn_select_box (&Slrn_Sort_Select_Box); } @@ -443,7 +492,13 @@ slrn_set_color (BOX_COLOR); } +#ifdef KANJI + slrn_message (Slrn_Japanese_Messages + ? "移動は UP/DOWN、選択は RETURN、取消は Ctrl-G を使用" + : "Use UP/DOWN to move, RETURN to select, Ctrl-G to cancel"); +#else slrn_message ("Use UP/DOWN to move, RETURN to select, Ctrl-G to cancel"); +#endif SLsmg_gotorc (row + Select_Window->window_row, column); slrn_pop_suspension (); } diff -Nru slrn-0.9.6.2.orig/src/mime.c slrn-0.9.6.2/src/mime.c --- slrn-0.9.6.2.orig/src/mime.c Fri Dec 24 02:24:39 1999 +++ slrn-0.9.6.2/src/mime.c Wed Dec 29 11:46:05 1999 @@ -37,7 +37,11 @@ #include "server.h" #include "slrn.h" #include "misc.h" +#ifdef KANJI +#include "chmap.h" +#else #include "slrn.h" +#endif #include "group.h" #include "art.h" #include "util.h" @@ -63,12 +67,77 @@ static char *Compatable_Charsets[] = { "US-ASCII", /* This MUST be zeroth element */ +#ifdef KANJI + "ISO-8859-1", + "ISO-8859-2", + "ISO-8859-3", + "ISO-8859-4", + "ISO-8859-5", + "ISO-8859-6", + "ISO-8859-7", + "ISO-8859-8", + "ISO-8859-9", + "KOI8-R", + "ISO-2022-JP", + "ISO-2022-JP-2", + "Shift_JIS", + "utf-7", + "utf-8", + "utf-16", +#else "ISO-8859-", "iso-latin1", /* knews adds his one */ "KOI8-R", +#endif NULL }; +#ifdef KANJI +typedef struct { + char *str; + int len; +} Mime_String; +typedef struct { + Slrn_Article_Line_Type *beg; + Slrn_Article_Line_Type *body; /* the top of body */ + Slrn_Article_Line_Type *end; +} Mime_Region; +static char *Mime_Content_Types[] = {"text", "message", "multipart", NULL}; +typedef enum { + CONTENT_TYPE_TEXT, + CONTENT_TYPE_MESSAGE, + CONTENT_TYPE_MULTIPART, + CONTENT_TYPE_UNSUPPORTED +} Mime_CT_Type; +static char *Mime_Content_Subtypes[] = { + "plain", "html", "rfc822", "partial", + "mixed", "alternative", "digest", "signed", NULL}; +typedef enum { + CONTENT_SUBTYPE_PLAIN, /* text */ + CONTENT_SUBTYPE_HTML, /* html */ + CONTENT_SUBTYPE_RFC822, /* message */ + CONTENT_SUBTYPE_PARTIAL, /* message */ + CONTENT_SUBTYPE_MIXED, /* multipart */ + CONTENT_SUBTYPE_ALTERNATIVE, /* multipart */ + CONTENT_SUBTYPE_DIGEST, /* multipart */ + CONTENT_SUBTYPE_SIGNED, /* multipart */ + CONTENT_SUBTYPE_UNKNOWN +} Mime_CS_Type; +struct Mime_Field_st { + Mime_CT_Type Content_Type; + Mime_String ctype; + Mime_CS_Type Content_Subtype; + Mime_String field; + Mime_String name; + Mime_String encoding; + Charset_Type charset; + int section; + struct Mime_Field_st *prev; +}; +typedef struct Mime_Field_st Mime_Field; + +static void mime_process_single_part (Slrn_Article_Line_Type *, Slrn_Article_Line_Type *, Mime_Field *); +#else static char *Char_Set; static int Content_Type; #define CONTENT_TYPE_TEXT 0x01 @@ -80,6 +149,7 @@ #define CONTENT_SUBTYPE_PLAIN 0x01 #define CONTENT_SUBTYPE_UNKNOWN 0x02 #define CONTENT_SUBTYPE_UNSUPPORTED 0x10 +#endif static int Encoding_Method; #define ENCODED_7BIT 1 @@ -96,17 +166,29 @@ || (((x) <= '9') && ((x) >= '0'))) #endif +#ifdef KANJI +static Slrn_Article_Line_Type *find_header_line (Mime_Region *mr, char *header) +#else static Slrn_Article_Line_Type *find_header_line (Slrn_Article_Type *a, char *header) +#endif { +#ifdef KANJI + Slrn_Article_Line_Type *line = mr->beg; +#else Slrn_Article_Line_Type *line; +#endif unsigned char ch = (unsigned char) UPPER_CASE(*header); unsigned int len = strlen (header); +#ifdef KANJI + while ((line != NULL) && (line != mr->end) && (line->flags & HEADER_LINE)) +#else if (a == NULL) return NULL; line = a->lines; while ((line != NULL) && (line->flags & HEADER_LINE)) +#endif { unsigned char ch1 = (unsigned char) *line->buf; if ((ch == UPPER_CASE(ch1)) @@ -120,6 +202,201 @@ } +#ifdef KANJI +static Charset_Type find_compatable_charset (char *cs, unsigned int len) +{ + char **compat_charset; + + compat_charset = Compatable_Charsets; + while (*compat_charset != NULL) + { + if ((0 == slrn_case_strncmp ((unsigned char *) cs, + (unsigned char *) *compat_charset, + len)) + && (len == strlen(*compat_charset))) + return (compat_charset - Compatable_Charsets); + compat_charset++; + } + return UNKNOWN_CHARSET; +} + +Charset_Type slrn_find_charset(char *s) +{ + Charset_Type cs; + + cs = find_compatable_charset(s, strlen(s)); + if (cs == UNKNOWN_CHARSET) { + cs = USASCII; + } + return cs; +} + +static int search_field(char *field, Slrn_Article_Line_Type *line, char *b, Mime_String *ms) +{ + int len = strlen(field), quote = 0; + + ms->str = NULL; + ms->len = 0; + + do { + while (b == line->buf || NULL != (b = slrn_strchr (b, ';'))) + { + b = slrn_skip_whitespace (b + 1); + + if (0 != slrn_case_strncmp ((unsigned char *)b, + (unsigned char *)field, + len)) + continue; + + b = slrn_skip_whitespace (b + len); + while (*b == 0) { + line = line->next; + if ((line == NULL) + || ((line->flags & HEADER_LINE) == 0) + || ((*(b = line->buf) != ' ') && (*b == '\t'))) + return 0; + b = slrn_skip_whitespace (b); + } + + if (*b != '=') continue; + b++; + if (*b == '"') { + quote = 1; + b++; + } + ms->str = b; + if (quote) { + while (*b && (*b != '"')) + b++; + } else { + while (*b && (*b != ';') + && (*b != ' ') && (*b != '\t') && (*b != '\n') + && (*b != '"')) + b++; + } + ms->len = b - ms->str; + return ms->len; + } + line = line->next; + } while ((line != NULL) + && (line->flags & HEADER_LINE) + && ((*(b = line->buf) == ' ') || (*b == '\t'))); + return 0; +} + +/* + * Find specified field in a header + * and if the header consists from more than one line, + * this funcion converts it into one line. + * If the field is NULL, all field is returned in name. + * Returns field length or 0 if not found. + */ +static int get_name_from_header (Mime_Region *mr, char *header, char *field, Mime_String *name) +{ + Slrn_Article_Line_Type *line; + + line = find_header_line (mr, header); + if (line == NULL) { + return 0; + } + + if (field != NULL) { + return search_field(field, line, line->buf, name); + } + + name->str = line->buf + strlen(header) + 1; + name->len = strlen(name->str); + + return name->len; +} + +static int parse_content_type_line (Mime_Region *mr, Mime_Field *mf) +{ + Slrn_Article_Line_Type *line; + char *b, *sep, **ct; + int len; + + /* Use default: text/plain; charset=us-ascii */ + mf->Content_Type = CONTENT_TYPE_TEXT; + mf->Content_Subtype = CONTENT_SUBTYPE_PLAIN; + mf->name.len = 0; + mf->ctype.str = "text/plain"; + mf->ctype.len = 10; + mf->charset = USASCII; + mf->field.str = Compatable_Charsets[mf->charset]; + mf->field.len = strlen(mf->field.str); + + if (NULL == (line = find_header_line (mr, "Content-Type:"))) + return 0; + + mf->Content_Type = CONTENT_TYPE_UNSUPPORTED; + mf->Content_Subtype = CONTENT_SUBTYPE_UNKNOWN; + b = slrn_skip_whitespace (line->buf + 13); + + /* get content type string */ + mf->ctype.str = b; + sep = slrn_strchr (b, ';'); + if (sep == NULL) { + mf->ctype.len = strlen(b); + } else { + mf->ctype.len = sep - b; + } + + /* find compatable content type string */ + ct = Mime_Content_Types; + while (*ct != NULL) { + len = strlen(*ct); + if (slrn_case_strncmp((unsigned char *)b, (unsigned char *)*ct, len) == 0 + && b[len] == '/') { + mf->Content_Type = ct - Mime_Content_Types; + b += len + 1; + ct = Mime_Content_Subtypes; + while(*ct != NULL) { + len = strlen(*ct); + if (slrn_case_strncmp((unsigned char *)b, (unsigned char *)*ct, len) == 0 + && (b[len] == ';' || b[len] == '\0')) { + mf->Content_Subtype = ct - Mime_Content_Subtypes; + b += len; + break; + } + ct++; + } + break; + } + ct++; + } + + if (mf->Content_Type == CONTENT_TYPE_MESSAGE && + mf->Content_Subtype == CONTENT_SUBTYPE_PARTIAL) { + if (search_field("id", line, b, &mf->field)) { + return 0; + } + return -1; + } + + if (get_name_from_header (mr, "Content-Description:", NULL, &mf->name) == 0 && + get_name_from_header (mr, "Subject:", NULL, &mf->name) == 0 && + get_name_from_header (mr, "Content-Type:", "name", &mf->name) == 0 && + get_name_from_header (mr, "Content-Disposition:", "filename", &mf->name) == 0) { + mf->name.len = 0; + } + + if (mf->Content_Type == CONTENT_TYPE_MULTIPART) { + if (search_field("boundary", line, b, &mf->field)) { + return 0; + } + return -1; + } + if (mf->Content_Type == CONTENT_TYPE_UNSUPPORTED) { + return -1; + } + + if (search_field("charset", line, b, &mf->field)) { + mf->charset = find_compatable_charset(mf->field.str, mf->field.len); + } + return 0; +} +#else static char *find_compatable_charset (char *cs, unsigned int len) { char **compat_charset; @@ -243,17 +520,30 @@ return 0; } +#endif +#ifdef KANJI +static int parse_content_transfer_encoding_line (Mime_Region *mr, Mime_String *encoding) +#else static int parse_content_transfer_encoding_line (Slrn_Article_Type *a) +#endif { Slrn_Article_Line_Type *line; unsigned char *buf; +#ifndef KANJI if (a == NULL) return -1; +#endif Encoding_Method = ENCODED_7BIT; +#ifdef KANJI + encoding->str = "7bit"; + encoding->len = 4; + line = find_header_line (mr, "Content-Transfer-Encoding:"); +#else line = find_header_line (a, "Content-Transfer-Encoding:"); +#endif if (line == NULL) return 0; buf = (unsigned char *) slrn_skip_whitespace (line->buf + 26); @@ -274,6 +564,13 @@ Encoding_Method = ENCODED_UNSUPPORTED; return -1; } +#ifdef KANJI + encoding->str = (char *)buf; + encoding->len = strlen((char *)buf); + if (buf[encoding->len - 1] == '"') { + encoding->len--; + } +#endif return 0; } @@ -345,7 +642,11 @@ return dest; } +#ifdef KANJI +Charset_Type slrn_rfc1522_decode_string (char *s) +#else int slrn_rfc1522_decode_string (char *s) +#endif { char *s1, *s2, ch; char *charset, method, *txt; @@ -353,6 +654,11 @@ char *after_whitespace; unsigned int count; unsigned int len; +#ifdef KANJI + Charset_Type cs = USASCII; + unsigned char *orig = (unsigned char *)s; + int orig_len = strlen(s); +#endif count = 0; after_whitespace = NULL; @@ -379,7 +685,14 @@ charset = s1 + 2; len = s - charset; +#ifdef KANJI + cs = find_compatable_charset (charset, len); + if (cs == UNKNOWN_CHARSET) { + charset = NULL; + } +#else charset = find_compatable_charset (charset, len); +#endif s++; /* skip ? */ method = *s++; /* skip B,Q */ method = UPPER_CASE(method); @@ -421,11 +734,30 @@ /* Note: these functions return a pointer to the END of the decoded * text. */ +#ifdef KANJI + s2 = s1; +#endif if (method == 'B') s1 = decode_base64 (s1, txt, s); else s1 = decode_quoted_printable (s1, txt, s, 1); /* Now move everything over */ +#ifdef KANJI + /* デコードして改行などが含まれている時は空白に置き換える */ + while(s2 < s1) { + ch = *s2; + if (ch == '\t' || ch == '\012' || ch == '\015') { + *s2 = ' '; + } + s2++; + } + s1 = s2; + + /* mime間の空白文字は無視 */ + s2 = slrn_skip_whitespace (s + 2); + /* 次の部分がmime encodeかどうかチェック */ + if (*s2 != '=' || *(s2 + 1) != '?') +#endif s2 = s + 2; /* skip final ?= */ s = s1; /* start from here next loop */ while ((ch = *s2++) != 0) *s1++ = ch; @@ -437,13 +769,105 @@ s = slrn_skip_whitespace (s); after_whitespace = s; } +#ifdef KANJI + /* convert all japanese codes to EUC so to be safe for structured field. */ + if (cs >= ISO2022JP && cs <= UNKNOWN_CHARSET) { + len = slrn_all2int(Slrn_Tmp_Str, orig, SLRN_TMP_STR_LEN, cs); + if (len && len < 5) { + strncpy((char *)orig, (char *)Slrn_Tmp_Str, orig_len); + } + } else if (cs == UNKNOWN_CHARSET) { + cs = USASCII; + } + return cs; +#else return count; +#endif } +#ifdef KANJI +static void rfc1522_decode_headers (Mime_Region *mr) +{ + Slrn_Article_Line_Type *line = mr->beg; + + while ((line != NULL) && (line != mr->end) && (line->flags & HEADER_LINE)) + { + line->charset = slrn_rfc1522_decode_string (line->buf); + if (line->charset > USASCII) { + Slrn_Mime_Was_Modified = 1; + } + line = line->next; + } +} + +static void decode_mime_base64 (Mime_Region *mr) +{ + Slrn_Article_Line_Type *line = mr->body, *l = NULL; + char *b; + int ch = 1; + + while (line != NULL && line != mr->end) { + if (l == NULL) { + b = line->buf; /* decode base64 */ + b = decode_base64 (b, b, b + strlen(b)); + if (b == NULL) { + return; + } + *b = '\0'; + } + if (ch == '\0') { + l = line; + line = line->prev; + b = line->buf; + b = slrn_realloc(b, strlen(b) + strlen(l->buf) + 1, 1); + if (b == NULL) { /* join with previous line */ + return; + } + strcat(b, l->buf); + line->buf = b; + line->next = l->next; + if (l->next != NULL) { + l->next->prev = line; + } + slrn_free(l->buf); + slrn_free((char *)l); + } + + l = NULL; + b = line->buf; + while((ch = *b) != '\012' && ch != '\015' && ch != '\0') { + b++; + } + if (ch != '\0') { /* 行末が、\012, \015, \015\012 のいずれかの時 */ + if (ch == '\015' && *(b + 1) == '\012') { + *b++ = '\0'; + } + *b++ = '\0'; + if (*b != '\0') { /* split line */ + l = (Slrn_Article_Line_Type *) slrn_malloc(sizeof (Slrn_Article_Line_Type), 0, 1); + b = slrn_safe_strmalloc(b); + if (l == NULL || b == NULL) { + return; + } + l->buf = b; + l->next = line->next; + if (l->next != NULL) { + l->next->prev = l; + } + line->next = l; + l->prev = line; + l->flags = line->flags; + } + } + line = line->next; + } + Slrn_Mime_Was_Modified = 1; +} +#else static void rfc1522_decode_headers (Slrn_Article_Type *a) { Slrn_Article_Line_Type *line; @@ -469,6 +893,7 @@ { Slrn_Mime_Needs_Metamail = 1; } +#endif /* This function checks if the last character on curr_line is an = and * if it is, then it merges curr_line and curr_line->next. See RFC1341, @@ -511,6 +936,93 @@ return 0; } +#ifdef KANJI +static void hide_pgp_signature(Slrn_Article_Line_Type *beg, Slrn_Article_Line_Type *end) +{ + Slrn_Article_Line_Type *line = beg, *new_end; + char *b; + + do { + if (line == NULL || line == end) { + return; + } + b = line->buf; + if (*b == '-' && + !(line->flags & HEADER_LINE) && + strncmp(b, "-----BEGIN PGP SIGNED MESSAGE-----", 34) == 0) { + break; + } + line = line->next; + } while (1); + + strcpy(b, "[ PGP SIGNED MESSAGE ]"); + line->flags |= HEADER_LINE; + do { + line = line->next; + if (line == NULL || line == end) { + return; + } + line->flags |= HIDDEN_LINE; + } while (*line->buf != '\0'); + + beg = line; + do { + if (line == NULL || line == end) { + return; + } + b = line->buf; + if (*b == '-') { + if (b[1] == ' ') { + strcpy(b, b + 2); + } else if (strncmp(b, "-----BEGIN PGP SIGNATURE-----", 29) == 0) { + break; + } + } + line = line->next; + } while (1); + + new_end = line; + strcpy(b, "[ PGP SIGNATURE ]"); + line->flags |= HEADER_LINE; + do { + line = line->next; + if (line == NULL || line == end) { + return; + } + line->flags |= HIDDEN_LINE; + } while (*line->buf != '-'); + + hide_pgp_signature(beg, new_end); /* recursive */ +} + +/* delete HIDDEN_LINE of body */ +static void delete_hidden_line(Slrn_Article_Line_Type *line) +{ + Slrn_Article_Line_Type *l; + + while (line != NULL && (line->flags & HEADER_LINE)) { + line = line->next; /* skip to body */ + } + while (line != NULL) { + if (line->flags & HIDDEN_LINE) { + l = line; + line = line->next; + l->prev->next = line; + if (line != NULL) { + line->prev = l->prev; + } + SLFREE(l->buf); + SLFREE(l); + } else { + line = line->next; + } + } +} + +static void decode_mime_quoted_printable (Mime_Region *mr) +{ + Slrn_Article_Line_Type *line = mr->body; +#else static void decode_mime_quoted_printable (Slrn_Article_Type *a) { Slrn_Article_Line_Type *line; @@ -524,8 +1036,13 @@ while ((line != NULL) && (line->flags & HEADER_LINE)) line = line->next; if (line == NULL) return; +#endif +#ifdef KANJI + while (line != NULL && line != mr->end) +#else while (line != NULL) +#endif { char *b; unsigned int len; @@ -544,7 +1061,9 @@ if (b < line->buf + len) { *b = 0; +#ifndef KANJI a->is_modified = 1; +#endif Slrn_Mime_Was_Modified = 1; } @@ -570,6 +1089,276 @@ Slrn_Mime_Was_Parsed = 1; /* or will be */ +#ifdef KANJI + mime_process_single_part(a->lines, NULL, NULL); + a = Slrn_Current_Article; + hide_pgp_signature(a->lines, NULL); + delete_hidden_line(a->lines); + if (Slrn_Mime_Was_Modified) { + a->is_modified = 1; + } +} + +static void mime_process_multipart (Mime_Region *mr, Mime_Field *mf) +{ + Slrn_Article_Line_Type *beg = mr->beg, *line; + char *b; + int body = 0, blen = mf->field.len, len; + + mf->section = 0; + line = beg; + + while((line != NULL) && (line != mr->end)) { + b = line->buf; + if (!body) { + if (*b == '\0') { /* end of header */ + body = 1; + } else { + line->flags |= HEADER_LINE; + } + if (mf->section == 0 && mf->prev != NULL && /* nested multipart */ + mf->prev->Content_Type == CONTENT_TYPE_MULTIPART) { + line->flags |= HIDDEN_LINE; + } + } else if (strncmp(b, "--", 2) == 0 && + strncmp(b + 2, mf->field.str, blen) == 0) { + len = strlen(b + 2); + if (mf->section > 0) { + mime_process_single_part(beg, line, mf); + } + mf->section++; + body = 0; + beg = line->next; + if (len == blen + 2 && strncmp(b + len, "--", 2) == 0) { + line->flags |= HIDDEN_LINE; /* hide last boundary line */ + return; /* found last boundary line */ + } + } else if (mf->section == 0) { + line->flags |= HIDDEN_LINE; /* hide comments "This is a multi...." */ + } + line = line->next; + } + mf->Content_Type = CONTENT_TYPE_TEXT; /* last boundary line not found */ +} + +static int concat_section(char *b, Mime_Field *mf) +{ + int len; + + if (mf->prev != NULL) { + len = concat_section(b, mf->prev); + } else { + len = 0; + } + sprintf(b + len, "%d.", mf->section); + return strlen(b); +} + +static void write_boundary(Slrn_Article_Line_Type *bound, Mime_Field *mf) +{ + char *b = (char *)Slrn_Tmp_Str; + int len, blen = strlen(bound->buf); + + *b = '['; + b++; + b += concat_section(b, mf->prev); + *(b - 1) = ' '; + len = mf->name.len; + if (len > 0) { + strncpy(b, mf->name.str, len); + b += len; + } + len = mf->ctype.len; + if (len > 0) { + strcpy(b, " <"); + b += 2; + strncpy(b, mf->ctype.str, len); + b += len; + len = mf->field.len; + if (mf->Content_Type == CONTENT_TYPE_TEXT && len != 0) { + strcpy(b, "; "); /* write charset */ + b += 2; + strncpy(b, mf->field.str, len); + b += len; + } + len = mf->encoding.len; + if (mf->Content_Type != CONTENT_TYPE_MULTIPART && len != 0) { + strcpy(b, " ("); /* write encoding type */ + b += 2; + strncpy(b, mf->encoding.str, len); + b += len; + *b++ = ')'; + } + *b++ = '>'; + } + *b++ = ']'; + *b = '\0'; + b = (char *)Slrn_Tmp_Str; + len = strlen(b); + if (len > blen) { + char *new_buf = slrn_realloc(bound->buf, len + 1, 1); + if (new_buf == NULL) { + return; + } + bound->buf = new_buf; + } + strcpy(bound->buf, b); + slrn_rfc1522_decode_string(bound->buf); + slrn_convert_body(bound, bound->next, mf->charset); + bound->flags |= HEADER_LINE; + bound->flags &= ~HIDDEN_LINE; +} + +static void hide_multipart_article(Mime_Region *mr, int hide_body) +{ + Slrn_Article_Line_Type *line = mr->beg->prev; + + while((line = line->next) != NULL && line != mr->end) { + if (hide_body || (line->flags & HEADER_LINE)) { + line->flags |= HIDDEN_LINE; + } else { + line->flags |= HIDDEN_LINE; /* hide separator */ + if (Encoding_Method != ENCODED_BASE64) { + line = mr->end->prev; + if (*line->buf == '\0') { + line->flags |= HIDDEN_LINE; /* hide last line */ + } + } + return; + } + } + if (line != NULL && *line->buf == '\0') { + line->flags &= ~HIDDEN_LINE; /* If last line is empty, not hide */ + } +} + +static void mime_process_rfc822 (Mime_Region *mr, Mime_Field *mf) +{ + Slrn_Article_Line_Type *line = mr->body; + + /* set HEADER_LINE flag so to be processed as MIME headers */ + while(line != NULL && line != mr->end && *line->buf != '\0') { + line->flags |= HEADER_LINE; + line = line->next; + } + if (line == NULL) return; + + mf->section = 1; + mime_process_single_part(mr->body, mr->end, mf); + + /* clear HEADER_LINE flag because this is not real article header */ + line = mr->body; + while(line != NULL && line != mr->end && + (line->flags & HEADER_LINE) && *line->buf != '\0') { + line->flags &= ~HEADER_LINE; + line = line->next; + } + /* convert header only */ + slrn_convert_body(mr->body, line, mf->charset); +} + +static Slrn_Article_Line_Type *unwrap_mime_header(Slrn_Article_Line_Type *line) +{ + Slrn_Article_Line_Type *l = line->next; + char *b = line->buf, *new; + int concat = (strncmp(line->buf, "Content-", 8) == 0 || + strncmp(line->buf, "Subject: ", 9) == 0); + + while (l != NULL) { + if (!(l->flags & HIDDEN_LINE)) { + new = l->buf; + if (*new != ' ' && *new != '\t') { /* not continued line */ + break; + } + if (concat) { /* concat continued line */ + b = slrn_realloc(b, strlen(b) + strlen(new) + 1, 1); + if (b == NULL) { + break; + } + strcat(b, new); + l->flags |= HIDDEN_LINE; + } + } + l = l->next; + } + line->buf = b; + return l; +} + +static void mime_process_single_part (Slrn_Article_Line_Type *beg, Slrn_Article_Line_Type *end, Mime_Field *prev_mf) +{ + Mime_Region mr; + Mime_Field mf; + Slrn_Article_Line_Type *line = beg; + + mr.beg = beg; + mr.end = end; + + while (line != NULL && line != end && *line->buf != '\0') { + if (prev_mf != NULL) { + line = unwrap_mime_header(line); + } else { + line = line->next; + } + } + mr.body = line->next; + + if (prev_mf == NULL || prev_mf->Content_Subtype == CONTENT_SUBTYPE_RFC822) { + rfc1522_decode_headers (&mr); + if (prev_mf != NULL && + find_header_line (&mr, "Mime-Version:") == NULL && + find_header_line (&mr, "Content-Type:") == NULL) { + prev_mf = NULL; + } + } + + mf.prev = prev_mf; + if ((-1 == parse_content_type_line (&mr, &mf) && (prev_mf == NULL)) + || (-1 == parse_content_transfer_encoding_line (&mr, &mf.encoding))) { + Slrn_Mime_Needs_Metamail = 1; + if (prev_mf == NULL) { + return; + } + } + + if (mf.Content_Type == CONTENT_TYPE_MULTIPART) { /* process multipart */ + mime_process_multipart(&mr, &mf); + } else if (mf.Content_Subtype == CONTENT_SUBTYPE_PARTIAL) { + /* partial message */ + char *id = slrn_strnmalloc(mf.field.str, mf.field.len, 1); + if (slrn_mime_retrieve_partial_messages(id) == 0) { + mime_process_single_part (Slrn_Current_Article->lines, NULL, NULL); + } else { + Slrn_Mime_Was_Modified = 0; /* not retrieved */ + } + slrn_free(id); + return; + } + if (prev_mf != NULL) { /* one part of multipart message*/ + /* hide body when a part of multipart/alternative message and it + * is not text/plain, or content type is neither text nor message. + */ + if (mf.Content_Type != CONTENT_TYPE_MULTIPART && + prev_mf->Content_Subtype != CONTENT_SUBTYPE_RFC822) { + int hide_body = + ((prev_mf->Content_Subtype == CONTENT_SUBTYPE_ALTERNATIVE || + prev_mf->Content_Subtype == CONTENT_SUBTYPE_SIGNED) && + mf.Content_Subtype != CONTENT_SUBTYPE_PLAIN) || + (/* mf.Content_Type != CONTENT_TYPE_TEXT && */ + mf.Content_Type != CONTENT_TYPE_MESSAGE && + Encoding_Method != ENCODED_7BIT && + mf.Content_Subtype != CONTENT_SUBTYPE_PLAIN); + hide_multipart_article(&mr, hide_body); + } + write_boundary(mr.beg->prev, &mf); + if (mf.Content_Subtype == CONTENT_SUBTYPE_RFC822) { + mime_process_rfc822(&mr, &mf); + } + } + if (mf.Content_Type != CONTENT_TYPE_TEXT) { + return; + } +#else rfc1522_decode_headers (a); if (NULL == find_header_line (a, "Mime-Version:")) return; @@ -579,6 +1368,7 @@ Slrn_Mime_Needs_Metamail = 1; return; } +#endif switch (Encoding_Method) { @@ -586,20 +1376,36 @@ case ENCODED_8BIT: case ENCODED_BINARY: /* Already done. */ +#ifdef KANJI + break; +#else return; +#endif case ENCODED_BASE64: +#ifdef KANJI + decode_mime_base64 (&mr); +#else decode_mime_base64 (); +#endif break; case ENCODED_QUOTED: +#ifdef KANJI + decode_mime_quoted_printable (&mr); +#else decode_mime_quoted_printable (a); +#endif break; default: Slrn_Mime_Needs_Metamail = 1; return; } +#ifdef KANJI + slrn_convert_body(mr.body, mr.end, mf.charset); + Slrn_Mime_Was_Modified = 1; +#endif } #ifndef MAXPATHLEN @@ -614,17 +1420,27 @@ int init = Slrn_TT_Initialized; char cmd [2 * SLRN_MAX_PATH_LEN]; char tempfile [SLRN_MAX_PATH_LEN]; +#ifndef KANJI Slrn_Article_Line_Type *ptr; +#endif FILE *fp; char *tmp, *mm; +#ifndef KANJI if (NULL == Slrn_Current_Article) return -1; ptr = Slrn_Current_Article->lines; +#endif if ((Slrn_Use_Meta_Mail == 0) || Slrn_Batch +#ifdef KANJI + || (slrn_get_yesno (1, Slrn_Japanese_Messages + ? "このMIME記事をmetamailで処理しますか" + : "Process this MIME article with metamail") <= 0)) +#else || (slrn_get_yesno (1, "Process this MIME article with metamail") <= 0)) +#endif return 0; # if defined(__os2__) || defined(__NT__) @@ -642,12 +1458,16 @@ return 0; } +#ifdef KANJI + fputs(Slrn_Article_Buf.buf, fp); +#else while (ptr) { fputs(ptr->buf, fp); putc('\n', fp); ptr = ptr->next; } +#endif slrn_fclose(fp); mm = Slrn_MetaMail_Cmd; @@ -735,8 +1555,14 @@ else Mime_Posting_Charset = Slrn_Mime_Display_Charset; } +#ifdef KANJI + else if (!cr && + UNKNOWN_CHARSET != find_compatable_charset (Slrn_Mime_Display_Charset, + strlen (Slrn_Mime_Display_Charset))) +#else else if (NULL != find_compatable_charset (Slrn_Mime_Display_Charset, strlen (Slrn_Mime_Display_Charset))) +#endif /* 7-bit data. Check to make sure that this display supports US-ASCII */ Mime_Posting_Charset = "us-ascii"; else @@ -761,6 +1587,278 @@ #define IS_RFC850_SPECIAL(c) \ (((c) == '(') || ((c) == ')') || ((c) == '<') || ((c) == '>') || ((c) == '"')) +#ifdef KANJI +/* + * For slrn_convert_utf72int() + * utf-7 で使用されている Modified MIME base64 変換の提供 + */ +int slrn_base64(int c) +{ + return BASE64(c); +} + +/* + * For uudecode.c + */ +char *slrn_decode_base64 (char *dest, char *src, char *srcmax) { + return decode_base64 (dest, src, srcmax); +} + +/* + * slrnのオリジナルのmime encoderは、Qエンコーディングしか + * サポートしていない。日本じゃbase64が普通なもんで追加。 + */ +static char basis_64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +/* src must less than srcmax */ +static unsigned char *encode_base64(unsigned char *dest, + unsigned char *src, unsigned char *srcmax) +{ + int c1, c2, pad = 0; + + while (src < srcmax) { + c1 = *src++; + *dest++ = basis_64[c1 >> 2]; + c1 <<= 4; + if (src < srcmax) { + c2 = *src++; + c1 |= c2 >> 4; + c2 <<= 2; + } else { + pad = 1; + } + *dest++ = basis_64[c1 & 0x3f]; + if (src < srcmax) { + c1 = *src++; + c2 |= c1 >> 6; + } else { + pad++; + } + if (pad < 2) { + *dest++ = basis_64[c2 & 0x3f]; + } else { + *dest++ = '='; + } + if (pad == 0) { + *dest++ = basis_64[c1 & 0x3f]; + } else { + *dest++ = '='; + } + } + return (dest); +} + +/* + * 上のoutput64chunkとto64は佐藤@電総研さんのmimekit1.1のコードを + * 参考にさせていただきましたが、下のエンコーダー本体は、スペースを + * 考慮していないきわめていいかげんなものです。 + * + * RFC2047 に厳密に対応するには、 + * 1. "あa" の場合、"あ" のみを encode すると decode した時 "あ a" となって + * しまう。-> "a" も含めてすべて encode するしかない。 + * + * 2. "あ い" の場合、"あ" と "い" を別々に encode すると、decode した時 + * "あい" となってしまう。-> space も含めて一緒に encode するか、"あ" + * か "い" のどちらかに space を含める。 + * + * 3. encoded word の前後は space でなければならない。つまり、日本語と + * くっついている半角文字もすべてひとつの encoded word にしなければな + * らない。ただ、これでは encode した文字列の可読性が落ちるので、日本 + * 語だけ encode する実装も存在するが、RFC2047 に厳密であるとは言えない。 + * + * 注: 2.で space も含めて一緒に encode すると単語の区切りがなくなって + * しまうので、RFC に厳密であるとは言えない。しかし、どうせ長くなると + * folding してしまうし、分けて encode すると全体が非常に長くなってし + * まうので、ここでは一緒に encode することにする。 + * + */ +/* アルゴリズム + * 1. まず、日本語の始まる ESC sequence を探す。 + 2. 空白まで元に戻る。 + 3. 日本語の終わる ESC sequence を探す。 + 4. 次が空白で、その次が日本語を含むならば、その日本語の終わる ESC sequence + を探す。 + 5. 4 を繰り返して、その次の文字列が日本語を含まない空白を探す。 + 6. 2 の位置から現在地まで base64 エンコードする。 + + さらに 75 文字以下に folding するのと、structured field に対応しなけ + ればならない。 + */ +/* only for ISO-2022-JP */ +int Slrn_Mime_Strict_Rfc = 0; /* RFC2047 に厳密な encode を行う(その代わり + ASCII 文字も encode してしまう)。 */ +#define IS_TO_KANJI(p) (*(p) == ESC && *((p) + 1) == '$' \ + && (*((p) + 2) == 'B' || *((p) + 2) == '@')) +#define IS_TO_ASCII(p) (*(p) == ESC && *((p) + 1) == '(' \ + && (*((p) + 2) == 'B' || *((p) + 2) == 'J')) +static int encode_base64_header(unsigned char *d, unsigned char *dmax, + unsigned char *s, char *charset, + unsigned int c_len, int ignore_specials) +{ + char *p, ch, *beg, *end, *to_ascii, *to_kanji, *beg_line; + int len = 0, count, beg_kanji, end_kanji; + + /* check if buffer 'd' has a enough length */ + if (dmax < d + strlen((char *)s) * 4 / 3) return (-1); + + p = slrn_strchr((char *)s, ':'); /* skip header name */ + if (p != NULL) { + while(*(++p) != ' '); /* skip next space */ + p--; + beg = (char *)s; + while(beg != p && d < dmax) { /* copy header */ + *d++ = *beg++; + } + } else { + p = (char *)s; + } + + while(*p != '\0' && d < dmax) { + beg_line = beg = p; + while (((ch = *p) != 0) && d < dmax && !IS_TO_KANJI(p) + && (len < 76 || beg != beg_line)) { + *d++ = ch; + p++; + len++; + if (ch == ' ' || (ignore_specials == 0 && IS_RFC850_SPECIAL(ch))) { + beg = p; /* remember the beginning of the current word */ + } + } + if (ch == 0) break; + if (d == dmax) return (-1); + + if (len > 75) { /* line break(in text) */ + p = beg; /* search previous word's end */ + while(*(beg - 1) == ' ') beg--; /* skip white space backward */ + d -= p - beg; + *d++ = '\n'; + *d++ = ' '; + len = 0; + continue; + } + + /* found to_kanji sequence and the beginning of encoding */ + to_kanji = p; + if (Slrn_Mime_Strict_Rfc) { + d -= p - beg; + len -= p - beg; + p = beg; + } else { + beg = p; + } + + /* search to_ascii sequence and the end of encoding */ + while((ch = *p) != 0) { + if (IS_TO_ASCII(p)) { /* skip to space or end of line */ + to_ascii = p; + p += 3; + if (!Slrn_Mime_Strict_Rfc) { + end = p; + break; + } + while((ch = *p) != 0 && ch != ' ' && ch != '\n' + && (ignore_specials || !IS_RFC850_SPECIAL(ch))) p++; + end = p; + if (ch == 0) break; + p = slrn_skip_whitespace(p); + while((ch = *p) != 0 && ch != ' ' && ch != '\n' && !IS_TO_KANJI(p) + && (ignore_specials || !IS_RFC850_SPECIAL(ch))) { + p++; + } + if (!IS_TO_KANJI(p)) break; + } + p++; + } + + /* encode between beg and end */ + p = beg; /* p must less than end */ + beg_kanji = 0; /* flag whether last string ended in kanji or ascii*/ + while (p < end && d < dmax) { + unsigned char *new_d; + + if (d + c_len >= dmax) return (-1); + + if (len + c_len + 14 > 75) { /* 14 = to_kanji(4) + one char(4) */ + *d++ = '\n'; /* + to_ascii(4) + "?="(2) */ + *d++ = ' '; + len = 0; + } else if (!Slrn_Mime_Strict_Rfc + && p != (char *)s && *(p - 1) != ' ' + && (ignore_specials || !IS_RFC850_SPECIAL(*(p - 1)))) { + *d++ = ' '; + len++; + } + strcpy((char *)d, charset); + d += c_len; + len += c_len + 2; /* 2 = "?=" */ + + /* count length of encoded word */ + count = beg_kanji * 4; /* 8 = one char(4) + to_ascii(4) */ + while(p < end && ((ch = *p) != 0) && len + count + 8 < 76) { + if (IS_TO_KANJI(p)) { + if (Slrn_Mime_Strict_Rfc && len + count > 70) { + len = 76; + break; + } else { /* flag whether current string ended in kanji or ascii*/ + end_kanji = 1; + } + p += 3; + } else if (IS_TO_ASCII(p)) { + end_kanji = 0; + p += 3; + } else if (*p > ' ' && end_kanji) { /* 2 byte character */ + p += 2; + } else { /* 1 byte character */ + p++; + } + count = (20 - (beg + 60 - p) / 3) * 4; + } + + if (len + count + 8 < 76) { + p = end; + } + if (beg_kanji) { + strncpy((char *)Slrn_Tmp_Str, to_kanji, 3); + count = 3; + } else { + count = 0; + } + + strncpy((char *)Slrn_Tmp_Str + count, beg, p - beg); + count += p - beg; + if (end_kanji) { + strncpy((char *)Slrn_Tmp_Str + count, to_ascii, 3); + count += 3; + } + /* add trailing space */ + if (!Slrn_Mime_Strict_Rfc && *p == ' ') { + Slrn_Tmp_Str[count] = ' '; + count++; + p++; + } + + new_d = encode_base64(d, Slrn_Tmp_Str, Slrn_Tmp_Str + count); + len += new_d - d; + d = new_d; + + beg_kanji = end_kanji; + beg = p; + + if (d + 1 >= dmax) return (-1); + d[0] = '?'; + d[1] = '='; + d += 2; + if (!Slrn_Mime_Strict_Rfc && *p != ' ') { + *d++ = ' '; + len++; + } + } + } + + *d = 0; + return (0); +} +#endif /* This routine returns -1 if d is not big enough to encode s. * Technically, this routine is incorrect. It should encode whitespace * separated words and not arbitrary sequences of text. @@ -778,6 +1876,9 @@ */ unsigned int hibit; /* How many 8-bit characters are left? */ +#ifdef KANJI + unsigned int esc = 0; +#endif unsigned char *p, ch, *dmax; char charset[256]; unsigned int charset_len; @@ -790,10 +1891,17 @@ while ((ch = *p) != 0) { if (ch & 0x80) hibit++; +#ifdef KANJI + else if (ch == ESC) esc++; +#endif p++; } +#ifdef KANJI + if (hibit == 0 && esc == 0) +#else if (hibit == 0) +#endif { if (s + len < p) return -1; @@ -804,8 +1912,17 @@ if (0 == slrn_case_strcmp ((unsigned char *)Slrn_Mime_Display_Charset, (unsigned char *)"us-ascii")) { +#ifdef KANJI + if (esc) + strcpy (charset, "=?ISO-2022-JP?B?"); + else +#endif strcpy (charset, "=?iso-8859-1?Q?"); } +#ifdef KANJI + else if (esc) + sprintf (charset, "=?%s?B?", Slrn_Mime_Display_Charset); +#endif else sprintf (charset, "=?%s?Q?", Slrn_Mime_Display_Charset); charset_len = strlen (charset); @@ -813,6 +1930,10 @@ dmax = d + len; /* leave room for the 0 character */ dmax--; +#ifdef KANJI + if (esc) return encode_base64_header(d, dmax, s, charset, charset_len, + ignore_specials); +#endif /* algorithm: * 1. copy up to first word that contains one or more eight bit chars. diff -Nru slrn-0.9.6.2.orig/src/mime.h slrn-0.9.6.2/src/mime.h --- slrn-0.9.6.2.orig/src/mime.h Fri Dec 24 02:24:39 1999 +++ slrn-0.9.6.2/src/mime.h Tue Dec 28 01:23:48 1999 @@ -1,4 +1,12 @@ +#ifdef KANJI +extern Charset_Type slrn_find_charset(char *); +extern char *slrn_decode_base64(char *, char *, char *); +extern int slrn_base64(int); +extern int Slrn_Mime_Strict_Rfc; +extern Charset_Type slrn_rfc1522_decode_string (char *); +#else extern int slrn_rfc1522_decode_string (char *); +#endif extern FILE *slrn_mime_encode (FILE *); extern void slrn_mime_header_encode (char *, unsigned int); diff -Nru slrn-0.9.6.2.orig/src/misc.c slrn-0.9.6.2/src/misc.c --- slrn-0.9.6.2.orig/src/misc.c Fri Dec 24 02:24:39 1999 +++ slrn-0.9.6.2/src/misc.c Mon Dec 27 10:46:05 1999 @@ -123,6 +123,9 @@ char *Slrn_Editor_Post; char *Slrn_Editor_Score; char *Slrn_Editor_Mail; +#ifdef KANJI +int Slrn_Editor_Code = -1; +#endif Slrn_User_Info_Type Slrn_User_Info; SLKeyMap_List_Type *Slrn_RLine_Keymap; @@ -214,6 +217,22 @@ if (Slrn_Full_Screen_Update == 0) return; SLsmg_gotorc (0, 0); slrn_set_color (MENU_COLOR); +#ifdef KANJI + if (Slrn_Japanese_Messages) { +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + int charset = Slang_Current_Charset; + + Slang_Current_Charset = ISO2022JP; +#endif + SLsmg_printf ("\ +slrn %s ** '?'を押すとヘルプ, 'q'で終了. ** サーバ: %s", + Slrn_Version, + Slrn_Server_Obj->sv_name); +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + Slang_Current_Charset = charset; +#endif + } else +#endif SLsmg_printf ("\ slrn %s ** Press '?' for help, 'q' to quit. ** Server: %s", Slrn_Version, @@ -232,6 +251,11 @@ static void redraw_message (void) { +#ifdef KANJI +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + int charset = Slang_Current_Charset; +#endif +#endif int color; char *m, *mmax; @@ -247,6 +271,13 @@ color = Message_Buffer [0]; m = Message_Buffer + 1; +#ifdef KANJI +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + if (Slrn_Japanese_Messages) { + Slang_Current_Charset = ISO2022JP; + } +#endif +#endif while (1) { mmax = slrn_strchr (m, 1); @@ -268,6 +299,11 @@ SLsmg_erase_eol (); slrn_set_color (0); +#ifdef KANJI +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + Slang_Current_Charset = charset; +#endif +#endif slrn_pop_suspension (); } @@ -743,19 +779,39 @@ { char rsp; +#ifdef KANJI + rsp = slrn_get_response ("yYnNeE", Slrn_Japanese_Messages + ? "メッセージを送りますか? \001Yes, \001No, \001Edit" + : "Mail the message? \001Yes, \001No, \001Edit"); +#else rsp = slrn_get_response ("yYnNeE", "Mail the message? \001Yes, \001No, \001Edit"); +#endif rsp |= 0x20; if (rsp == 'n') return -1; if (rsp == 'y') break; if (slrn_edit_file (Slrn_Editor_Mail, file, 1, 0) < 0) return -1; } } +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "送信中..." + : "Sending..."); +#else slrn_message_now ("Sending ..."); +#endif if (-1 == slrn_save_file_to_mail_file (file, Slrn_Save_Replies_File, NULL)) return -1; +#ifdef KANJI + /* editor が書き出したファイルのコードを JIS に変換する */ + if (Slrn_Editor_Code != JIS + && slrn_conv_file(file, JIS) == -1) { + return -1; + } +#else slrn_chmap_fix_file (file); +#endif #ifdef VMS sprintf(buf, "%s\"%s\"", MAIL_PROTOCOL, to); @@ -805,8 +861,24 @@ slrn_mime_add_headers (pp); fp = slrn_mime_encode (fp); } +#ifdef KANJI + if (Slrn_Use_Mime == 1) +#endif slrn_mime_header_encode (line, sizeof(line)); } +#if defined(KANJI) && !SLRN_GEN_FROM_EMAIL_HEADER + /* なぜか知らんが、SunOS4.1.3JLEのsendmailでは、body部に + From: と Subject: が出てくるとおかしくなる。で、 + newsでのヘッダの前に一個空白を入れることで逃げる + */ + /* 上記の対処のため、From の前に '>' を入れる */ + if ((*line == 'F') + && !strncmp ("From", line, 4) + && (line[4] == ' ' || line[4] == ':')) + { + putc ('>', pp); + } +#endif fputs (line, pp); putc('\n', pp); } @@ -829,7 +901,13 @@ slrn_posix_system (buf, 0); } #endif /* NOT VMS */ +#ifdef KANJI + slrn_message (Slrn_Japanese_Messages + ? "送信中...終了" + : "Sending...done"); +#else slrn_message ("Sending...done"); +#endif return 0; } @@ -1087,6 +1165,9 @@ #endif } +#ifdef KANJI + if (slrn_conv_file(file, Slrn_Editor_Code) == -1) return (-1); +#endif strcpy (editbuf, editor); if (0 == create_edit_command(editbuf, buf, file, line)) return -1; @@ -1106,7 +1187,13 @@ && (0 == stat (file, &st)) && (mtime == (unsigned long) st.st_mtime)) { +#ifdef KANJI + slrn_message (Slrn_Japanese_Messages + ? "ファイルが修正されていません" + : "File was not modified"); +#else slrn_message ("File was not modified"); +#endif ret = -2; } @@ -1255,6 +1342,11 @@ char prompt_buf[256]; unsigned int len; int save_slang_error; +#ifdef KANJI +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + int charset = Slang_Current_Charset; +#endif +#endif Slrn_Full_Screen_Update = 1; @@ -1338,7 +1430,15 @@ SLang_Error = 0; Reading_Input = 1; +#if defined(KANJI) && !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + if (Slrn_Japanese_Messages) { + Slang_Current_Charset = ISO2022JP; + } i = SLang_read_line (Slrn_Keymap_RLI); + Slang_Current_Charset = charset; +#else + i = SLang_read_line (Slrn_Keymap_RLI); +#endif Reading_Input = 0; slrn_enable_mouse (1); @@ -1486,7 +1586,13 @@ v++; } +#ifdef KANJI + slrn_error_now (0, Slrn_Japanese_Messages + ? "変な応答です!もう一度。" + : "Invalid response! Try again."); +#else slrn_error_now (0, "Invalid response! Try again."); +#endif if (Slrn_TT_Initialized & SLRN_TTY_INIT) { (void) SLang_input_pending (15); @@ -1654,6 +1760,11 @@ * to get more information. Why isn't there a simplified interface to * get the FQDN!!!! */ +#ifdef KANJI + if (slrn_is_fqdn(buf) != 0) { + return slrn_safe_strmalloc (buf); + } +#endif host_entry = gethostbyname (buf); #if defined(TRY_AGAIN) && !defined(MULTINET) @@ -1855,8 +1966,12 @@ Slrn_User_Info.signature = slrn_safe_strmalloc (SLRN_SIGNATURE_FILE); #if SLRN_HAS_MIME +#ifdef KANJI + Slrn_Mime_Display_Charset = slrn_safe_strmalloc (SLRN_DEFAULT_CHARSET); +#else Slrn_Mime_Display_Charset = slrn_safe_strmalloc ("iso-8859-1"); #endif +#endif #ifdef SLRN_SENDMAIL_COMMAND Slrn_SendMail_Command = slrn_safe_strmalloc (SLRN_SENDMAIL_COMMAND); @@ -1881,7 +1996,11 @@ return a; } +#ifdef KANJI +char *slrn_make_from_string (int code) +#else char *slrn_make_from_string (void) +#endif { char *username, *hostname, *realname; static char buf[256]; @@ -1896,6 +2015,9 @@ { _slrn_strcat (buf, username, sizeof (buf)); SLang_free_slstring (username); +#ifdef KANJI + slrn_conv_string(buf, code); +#endif return buf; } SLang_free_slstring (username); @@ -1920,6 +2042,9 @@ _slrn_strcat (buf, realname, sizeof(buf)); _slrn_strcat (buf, ")", sizeof(buf)); +#ifdef KANJI + slrn_conv_string(buf, code); +#endif return buf; } diff -Nru slrn-0.9.6.2.orig/src/nntplib.c slrn-0.9.6.2/src/nntplib.c --- slrn-0.9.6.2.orig/src/nntplib.c Fri Dec 24 02:24:44 1999 +++ slrn-0.9.6.2/src/nntplib.c Mon Dec 27 10:46:05 1999 @@ -33,6 +33,9 @@ #include #include "jdmacros.h" +#ifdef KANJI +#include "chmap.h" +#endif #include "sltcp.h" #include "nntpcodes.h" @@ -401,7 +404,13 @@ if (s->tcp != NULL) sltcp_close (s->tcp); +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "ホスト %s に接続中 ..." + : "Connecting to host %s ...", s->host); +#else slrn_message_now ("Connecting to host %s ...", s->host); +#endif if (NULL == (s->tcp = sltcp_open_connection (s->host, s->port))) return -1; @@ -428,6 +437,12 @@ || (-1 == _nntp_authorization (s))) goto failed; +#ifdef KANJI + if (Slrn_Japanese_Messages) + slrn_message_now ("ホストに接続しました。投稿%s可能です。", + (s->can_post ? "" : "不")); + else +#endif slrn_message_now ("Connected to host. Posting %sOk.", (s->can_post ? "" : "NOT ")); return 0; diff -Nru slrn-0.9.6.2.orig/src/post.c slrn-0.9.6.2/src/post.c --- slrn-0.9.6.2.orig/src/post.c Fri Dec 24 02:24:41 1999 +++ slrn-0.9.6.2/src/post.c Wed Dec 29 10:55:12 1999 @@ -160,6 +160,11 @@ while (NULL != fgets (buf, sizeof(buf), sfp)) { +#ifdef KANJI + /* signature のコードは何か分からないので、取りあえず + EUC に変換する */ + slrn_conv_string(buf, EUC); +#endif fputs (buf, fp); } slrn_fclose(sfp); @@ -267,8 +272,17 @@ linenum = 0; #if SLRN_GEN_FROM_EMAIL_HEADER +#ifdef KANJI + strncpy(line, slrn_make_from_string (JIS), sizeof(line)); +#if SLRN_HAS_MIME + if (Slrn_Use_Mime) + slrn_mime_header_encode(line, sizeof(line)); +#endif + fprintf (pp, "From: %s\n", line); +#else fprintf (pp, "From: %s\n", slrn_make_from_string ()); #endif +#endif if (msgid != NULL) fprintf (pp, "Message-Id: \n", @@ -279,6 +293,15 @@ { linenum++; if (linenum == cc_line) continue; +#ifdef KANJI +# if SLRN_HAS_MIME + if (Slrn_Use_Mime == 1) { + slrn_mime_header_encode (line, sizeof(line)); + fputs (line, pp); + continue; + } +#endif +#endif if (is_empty_header (line)) continue; if (0 == slrn_case_strncmp ((unsigned char *)line, (unsigned char *) "To: ", 4)) @@ -305,7 +328,14 @@ if ((NULL != Slrn_Courtesy_CC_Message) && (*Slrn_Courtesy_CC_Message)) { +#ifdef KANJI + slrn_insert_followup_format_string (line, Slrn_Courtesy_CC_Message); + /* Slrn_Courtesy_CC_Message は内部コード(EUC)なのでJISに直す */ + slrn_conv_string(line, JIS); + fputs (line, pp); +#else slrn_insert_followup_format (Slrn_Courtesy_CC_Message, pp); +#endif fputs ("\n", pp); } @@ -356,13 +386,25 @@ num = 0; while (NULL != fgets (line, sizeof (line), fp)) { +#ifdef KANJI + /* editor コードが JIS や SJIS の場合、EUC にする。*/ + if (Slrn_Editor_Code != EUC) { + slrn_conv_string(line, EUC); + } +#endif ch = *line; num++; if ((ch == ' ') || (ch == '\t') || (ch == '\n')) { if (num == 1) { +#ifdef KANJI + err = Slrn_Japanese_Messages + ? "最初の行はヘッダーで始まらなければならない。" + : "The first line must begin with a header."; +#else err = "The first line must begin with a header."; +#endif break; } if (ch == '\n') break; @@ -372,7 +414,13 @@ if (NULL == (colon = slrn_strchr (line, ':'))) { +#ifdef KANJI + err = Slrn_Japanese_Messages + ? "ヘッダーが要求されている。これはヘッダー行ではない。" + : "Expecting a header. This is not a header line."; +#else err = "Expecting a header. This is not a header line."; +#endif break; } @@ -380,7 +428,13 @@ { if (is_empty_header (line)) { +#ifdef KANJI + err = Slrn_Japanese_Messages + ? "Subject ヘッダーを空にすることはできない。" + : "The subject header is not allowed be to empty."; +#else err = "The subject header is not allowed be to empty."; +#endif break; } subject_found = 1; @@ -391,7 +445,13 @@ { if (is_empty_header (line)) { +#ifdef KANJI + err = Slrn_Japanese_Messages + ? "Newsgroups ヘッダーを空にすることはできない。" + : "The Newsgroups header is not allowed be to empty."; +#else err = "The Newsgroups header is not allowed be to empty."; +#endif break; } newsgroups_found = 1; @@ -403,13 +463,25 @@ if (*(colon + 1) != ' ') { +#ifdef KANJI + err = Slrn_Japanese_Messages + ? "ヘッダーは ':' の次はスペースでなければならない。" + : "A space must follow the ':' in a header"; +#else err = "A space must follow the ':' in a header"; +#endif break; } if (!slrn_case_strncmp ((unsigned char *) line, (unsigned char *) "From:", 5)) { +#ifdef KANJI + err = Slrn_Japanese_Messages + ? "このニュースリーダではユーザが作成した From 行は受け付けられない。" + : "This news reader will not accept user generated From lines."; +#else err = "This news reader will not accept user generated From lines."; +#endif break; } } @@ -418,12 +490,24 @@ { if (subject_found == 0) { +#ifdef KANJI + err = Slrn_Japanese_Messages + ? "Subject ヘッダーが必要である。" + : "Subject header is required."; +#else err = "Subject header is required."; +#endif num = 0; } else if (newsgroups_found == 0) { +#ifdef KANJI + err = Slrn_Japanese_Messages + ? "Newsgroups ヘッダーが必要である。" + : "Newsgroups header is required."; +#else err = "Newsgroups header is required."; +#endif num = 0; } } @@ -437,10 +521,23 @@ if (qs == NULL) qs = ">"; qlen = strlen (qs); +#ifdef KANJI + err = Slrn_Japanese_Messages + ? "引用された部分以外にメッセージが見当たらない。" + : "Your message does not appear to have any unquoted text."; +#else err = "Your message does not appear to have any unquoted text."; +#endif the_line = NULL; while (NULL != fgets (line, sizeof (line), fp)) { +#ifdef KANJI + /* editor コードが JIS の場合は一行が 80 文字より長くなっ + てしまうので EUC に直す。ついでに SJIS も EUC にする。*/ + if (Slrn_Editor_Code != EUC) { + slrn_conv_string(line, EUC); + } +#endif num++; if (!strncmp (line, qs, qlen)) continue; @@ -454,7 +551,13 @@ if (strlen (line) > 81) /* allow \n to slip */ { +#ifdef KANJI + err = Slrn_Japanese_Messages + ? "一行に 80 文字以上存在する。この行は折り返さなければならない。" + : "Line contains more than 80 characters. You need to wrap it."; +#else err = "Line contains more than 80 characters. You need to wrap it."; +#endif the_line = line; if (Slrn_Reject_Long_Lines == 2) only_warning = 1; @@ -481,6 +584,14 @@ SLsmg_cls (); SLsmg_gotorc (2,0); slrn_set_color (SUBJECT_COLOR); +#ifdef KANJI + if (Slrn_Japanese_Messages) { +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + Slang_Current_Charset = ISO2022JP; +#endif + SLsmg_write_string ("あなたのメッセージは以下の理由により受け付けられません:"); + } else +#endif SLsmg_write_string ("Your message is not acceptable for the following reason:"); slrn_set_color (ERROR_COLOR); SLsmg_gotorc (4,8); SLsmg_write_string (err); @@ -488,15 +599,33 @@ { SLsmg_gotorc (6,0); slrn_set_color (SUBJECT_COLOR); +#ifdef KANJI + SLsmg_printf (Slrn_Japanese_Messages + ? "このメッセージは %d 行目で出力されました。" + : "This message was generated while looking at line %d:", num); +#else SLsmg_printf ("This message was generated while looking at line %d:", num); +#endif SLsmg_gotorc (8,0); slrn_set_color (QUOTE_COLOR); SLsmg_write_string (the_line); SLsmg_gotorc (12, 0); slrn_set_color (ARTICLE_COLOR); +#ifdef KANJI + SLsmg_write_string (Slrn_Japanese_Messages + ? "もしかするとこのエラーは、ヘッダー部を空行で本文から分けていなかったために" + : "Perhaps this error was generated because you did not separate the header"); +#else SLsmg_write_string ("Perhaps this error was generated because you did not separate the header"); +#endif SLsmg_gotorc (13, 0); +#ifdef KANJI + SLsmg_write_string (Slrn_Japanese_Messages + ? "起きたのかも知れません。" + : "section from the body by a BLANK line."); +#else SLsmg_write_string ("section from the body by a BLANK line."); +#endif } if (only_warning) return 2; @@ -510,6 +639,9 @@ time_t now; char save_post_file[SLRN_MAX_PATH_LEN]; char line [MAX_LINE_BUFLEN]; +#ifdef KANJI + char *ch = save_file; +#endif if ((save_file == NULL) || (*save_file == 0)) return 0; @@ -520,8 +652,26 @@ return -1; } +#ifdef KANJI + /* save_files の先頭が '|' かどうかの解析を行う */ + while (*ch != '\0') { + if (*ch == ' ') { + ch++; + } else if (*ch == '|') { + outfp = slrn_popen(ch + 1, "w"); + break; + } else { + ch = NULL; + break; + } + } + if ((ch == NULL || *ch == '\0') + && NULL == (outfp = slrn_open_home_file (save_file, "a", + save_post_file, 1))) +#else if (NULL == (outfp = slrn_open_home_file (save_file, "a", save_post_file, 1))) +#endif { slrn_message_now ("***Warning: error saving to %s", save_post_file); SLang_input_pending (30); @@ -532,7 +682,11 @@ time (&now); fprintf (outfp, "From %s@%s %s", Slrn_User_Info.username, Slrn_User_Info.hostname, ctime(&now)); +#ifdef KANJI + fprintf (outfp, "From: %s\n", slrn_make_from_string (Slrn_Editor_Code)); +#else fprintf (outfp, "From: %s\n", slrn_make_from_string ()); +#endif if (msgid != NULL) fprintf (outfp, "Message-Id: \n", msgid, Slrn_User_Info.posting_host); while (NULL != fgets (line, sizeof(line) - 1, infp)) @@ -548,6 +702,11 @@ } fputs ("\n\n", outfp); /* separator */ slrn_fclose (infp); +#ifdef KANJI + if (ch != NULL && *ch != '\0') + return slrn_pclose(outfp); + else +#endif return slrn_fclose (outfp); } @@ -691,17 +850,41 @@ if (filter_hook != NULL) { if (is_postponed) +#ifdef KANJI + rsp = slrn_get_response ("yYnNeEsSDdFf", Slrn_Japanese_Messages + ? "記事を投稿しますか? \001Yes, \001No, \001Edit, po\001Stpone, \001Delete, \001Filter" + : "Post the message? \001Yes, \001No, \001Edit, po\001Stpone, \001Delete, \001Filter"); +#else rsp = slrn_get_response ("yYnNeEsSDdFf", "Post the message? \001Yes, \001No, \001Edit, po\001Stpone, \001Delete, \001Filter"); +#endif else +#ifdef KANJI + rsp = slrn_get_response ("yYnNeEsSFf", Slrn_Japanese_Messages + ? "記事を投稿しますか? \001Yes, \001No, \001Edit, po\001Stpone, \001Filter" + : "Post the message? \001Yes, \001No, \001Edit, po\001Stpone, \001Filter"); +#else rsp = slrn_get_response ("yYnNeEsSFf", "Post the message? \001Yes, \001No, \001Edit, po\001Stpone, \001Filter"); +#endif } else { #endif if (is_postponed) +#ifdef KANJI + rsp = slrn_get_response ("yYnNeEsSDd", Slrn_Japanese_Messages + ? "記事を投稿しますか? \001Yes, \001No, \001Edit, po\001Stpone, \001Delete" + : "Post the message? \001Yes, \001No, \001Edit, po\001Stpone, \001Delete"); +#else rsp = slrn_get_response ("yYnNeEsSDd", "Post the message? \001Yes, \001No, \001Edit, po\001Stpone, \001Delete"); +#endif else +#ifdef KANJI + rsp = slrn_get_response ("yYnNeEsS", Slrn_Japanese_Messages + ? "記事を投稿しますか? \001Yes, \001No, \001Edit, po\001Stpone" + : "Post the message? \001Yes, \001No, \001Edit, po\001Stpone"); +#else rsp = slrn_get_response ("yYnNeEsS", "Post the message? \001Yes, \001No, \001Edit, po\001Stpone"); +#endif #if SLRN_HAS_SLANG } #endif @@ -743,9 +926,21 @@ SLtt_beep (); if (rsp == 1) +#ifdef KANJI + rsp = slrn_get_response ("yYEenNcC\007", + Slrn_Japanese_Messages + ? "\001E(再編集)または\001C(キャンセル)" + : "re-\001Edit, or \001Cancel"); + else + rsp = slrn_get_response ("EeyYnNcC\007Ff", + Slrn_Japanese_Messages + ? "\001E(再編集), \001C(キャンセル)または\001F(強制投稿、推奨されない)" + : "re-\001Edit, \001Cancel, or \001Force the posting (not recommended)"); +#else rsp = slrn_get_response ("yYEenNcC\007", "re-\001Edit, or \001Cancel"); else rsp = slrn_get_response ("EeyYnNcC\007Ff", "re-\001Edit, \001Cancel, or \001Force the posting (not recommended)"); +#endif switch (rsp) { @@ -786,7 +981,13 @@ } } +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "投稿中..." + : "Posting ..."); +#else slrn_message_now ("Posting ..."); +#endif #if SLRN_HAS_GEN_MSGID msgid = slrn_create_message_id (); @@ -795,7 +996,15 @@ if (-1 == slrn_save_file_to_mail_file (file, Slrn_Save_Posts_File, msgid)) return -1; +#ifdef KANJI + /* editor のコードから JIS に変換する */ + if (Slrn_Editor_Code != JIS + && slrn_conv_file(file, JIS) == -1) { + return -1; + } +#else slrn_chmap_fix_file (file); +#endif if ((fp = fopen (file, "r")) == NULL) { @@ -824,7 +1033,13 @@ slrn_error ("File not found: %s--- message not posted.", file); return -1; } +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "投稿中..." + : "Posting ..."); +#else slrn_message_now ("Posting ..."); +#endif } #endif @@ -835,7 +1050,13 @@ fclose (fp); (void) saved_failed_post (file); if (status != -1) +#ifdef KANJI + slrn_error (Slrn_Japanese_Messages + ? "投稿が許可されていません。" + : "Posting not allowed."); +#else slrn_error ("Posting not allowed."); +#endif return -1; } @@ -843,7 +1064,11 @@ Slrn_Post_Obj->po_printf ("Path: %s\n", Slrn_User_Info.username); /* line is not used until now, so we can use it as a buffer */ +#ifdef KANJI + strncpy(line, slrn_make_from_string (JIS), sizeof(line)); +#else strncpy(line, slrn_make_from_string (), sizeof(line)); +#endif line[sizeof(line) - 1] = 0; #if SLRN_HAS_MIME @@ -933,7 +1158,12 @@ #endif linep[len - 1] = 0; #if SLRN_HAS_MIME +#ifdef KANJI + /* use_mime が 2 の時は From: 以外は MIME encode しない */ + if (Slrn_Use_Mime == 1) +#else if (Slrn_Use_Mime) +#endif slrn_mime_header_encode (linep, sizeof (line) - 1); #endif } @@ -961,7 +1191,13 @@ slrn_fclose (fp); if (0 == Slrn_Post_Obj->po_end ()) +#ifdef KANJI + slrn_message (Slrn_Japanese_Messages + ? "投稿中...終了。" + : "Posting...done."); +#else slrn_message ("Posting...done."); +#endif else { if (Slrn_Batch) @@ -974,7 +1210,13 @@ slrn_smg_refresh (); sleep (2); slrn_clear_message (); SLang_Error = 0; +#ifdef KANJI + rsp = slrn_get_response ("RrEeCc\007", Slrn_Japanese_Messages + ? "一つを選択: \001Repost(再投稿), \001Edit(編集), \001Cancel" + : "Select one: \001Repost, \001Edit, \001Cancel"); +#else rsp = slrn_get_response ("RrEeCc\007", "Select one: \001Repost, \001Edit, \001Cancel"); +#endif if ((rsp == 7) || (rsp == 'c') || (rsp == 'C') diff -Nru slrn-0.9.6.2.orig/src/print.c slrn-0.9.6.2/src/print.c --- slrn-0.9.6.2.orig/src/print.c Fri Dec 24 02:24:36 1999 +++ slrn-0.9.6.2/src/print.c Mon Dec 27 10:46:05 1999 @@ -86,7 +86,11 @@ # include # else #if 0 +#if defined(KANJI) && defined(__MINGW32__) && !defined(__CYGWIN32__) +extern WINBOOL WINAPI OpenPrinterA(LPTSTR, LPHANDLE, LPPRINTER_DEFAULTS); +#else extern WINBOOL WINAPI OpenPrinterA(LPTSTR, LPHANDLE, LPVOID); +#endif extern WINBOOL WINAPI ClosePrinter(HANDLE); extern WINBOOL WINAPI EndPagePrinter(HANDLE); #endif @@ -343,6 +347,9 @@ int slrn_write_to_printer (Slrn_Print_Type *p, char *buf, unsigned int len) { +#ifdef KANJI + return write_to_printer (p, buf, len); +#else char *b, *bmax; /* Map \n to \r\n */ @@ -382,6 +389,7 @@ return write_to_printer (p, buf, len); return 0; +#endif } int slrn_print_file (char *file) diff -Nru slrn-0.9.6.2.orig/src/score.c slrn-0.9.6.2/src/score.c --- slrn-0.9.6.2.orig/src/score.c Fri Dec 24 02:24:38 1999 +++ slrn-0.9.6.2/src/score.c Mon Dec 27 10:46:05 1999 @@ -43,6 +43,9 @@ # include "util.h" #endif +#ifdef KANJI +#include "chmap.h" +#endif #include "art.h" #include "xover.h" #include "score.h" @@ -862,6 +865,12 @@ unsigned char *lp; int not_flag; +#ifdef KANJI + /* editor コードが JIS や SJIS の場合、EUC にする。*/ + if (Slrn_Editor_Code != EUC) { + slrn_conv_string(line, EUC); + } +#endif linenum++; if (0 == SLprep_line_ok (line, &c->pt)) diff -Nru slrn-0.9.6.2.orig/src/server.c slrn-0.9.6.2/src/server.c --- slrn-0.9.6.2.orig/src/server.c Fri Dec 24 02:24:41 1999 +++ slrn-0.9.6.2/src/server.c Mon Dec 27 10:46:05 1999 @@ -79,7 +79,11 @@ * They stop the screen getting messed up, but the error messages aren't * very appropriate */ +#ifdef KANJI + if (NULL == (Fp_Inews = slrn_popen (Slrn_Inews_Pgm, "w"))) +#else if (NULL == (Fp_Inews = popen (Slrn_Inews_Pgm, "w"))) +#endif { slrn_error ("Couldn't open pipe to inews! -- Article not posted."); return -1; @@ -91,7 +95,11 @@ { int res = 0; +#ifdef KANJI + if (-1 == slrn_pclose (Fp_Inews)) +#else if (-1 == pclose (Fp_Inews)) +#endif { slrn_error ("pclose() failed -- check if article was posted"); /* !HACK! can we do better? */ res = -1; diff -Nru slrn-0.9.6.2.orig/src/slrn.c slrn-0.9.6.2/src/slrn.c --- slrn-0.9.6.2.orig/src/slrn.c Fri Dec 24 02:24:38 1999 +++ slrn-0.9.6.2/src/slrn.c Mon Dec 27 10:46:05 1999 @@ -162,8 +162,14 @@ copy of slrn, delete the file %s", pid, file); #else +#ifdef KANJI + slrn_exit_error (Slrn_Japanese_Messages + ? "slrn: PID %d が newsrc ファイルをロックしています。" + : "slrn: pid %d is locking the newsrc file.", pid); +#else slrn_exit_error ("slrn: pid %d is locking the newsrc file.", pid); #endif +#endif } } slrn_fclose (fp); @@ -776,6 +782,13 @@ char *msg3 = "Checking news via active file ..."; char *msg; +#ifdef KANJI + if (Slrn_Japanese_Messages) { + msg1 = "新しいグループをチェック中 ..."; + msg2 = "ニュースをチェック中 ..."; + msg3 = "active file からニュースをチェック中 ..."; + } +#endif if (Slrn_Server_Obj->sv_initialize () != 0) return (-1); if (create_flag == 0) @@ -1158,6 +1171,7 @@ * has a username and a usable hostname. Without those, we are not * starting up. */ +#if !defined(__os2__) || !defined(KANJI) if ((NULL == Slrn_User_Info.hostname) || (0 == slrn_is_fqdn (Slrn_User_Info.hostname))) { @@ -1166,6 +1180,7 @@ hostname in your %s file.\r\n", SLRN_USER_SLRNRC_FILENAME); } +#endif if ((NULL == Slrn_User_Info.username) || (0 == *Slrn_User_Info.username) || (NULL != slrn_strchr (Slrn_User_Info.username, '@'))) @@ -1190,7 +1205,13 @@ #else Slrn_Newsrc_File = ".jnewsrc"; #endif +#ifdef KANJI + slrn_message_now (Slrn_Japanese_Messages + ? "newsrc ファイル %s をサーバ %s に対して使用します。" + : "Using newsrc file %s for server %s.", +#else slrn_message_now ("Using newsrc file %s for server %s.", +#endif Slrn_Newsrc_File, Slrn_Server_Obj->sv_name); if (use_active) Slrn_List_Active_File = 1; diff -Nru slrn-0.9.6.2.orig/src/slrn.h slrn-0.9.6.2/src/slrn.h --- slrn-0.9.6.2.orig/src/slrn.h Fri Dec 24 02:24:41 1999 +++ slrn-0.9.6.2/src/slrn.h Mon Dec 27 10:52:25 1999 @@ -110,6 +110,10 @@ #define FRAME_COLOR 23 #define SELECT_COLOR 24 #define VERBATUM_COLOR 25 +#ifdef KANJI +#define URL_COLOR 28 +#define URL_PRESS_COLOR 29 +#endif #define BOLD_COLOR 30 #define UNDERLINE_COLOR 31 diff -Nru slrn-0.9.6.2.orig/src/slrnconf.h slrn-0.9.6.2/src/slrnconf.h --- slrn-0.9.6.2.orig/src/slrnconf.h Fri Dec 24 02:24:42 1999 +++ slrn-0.9.6.2/src/slrnconf.h Mon Dec 27 10:46:05 1999 @@ -128,6 +128,9 @@ #ifdef __WIN32__ /* # define USE_NOTEPAD_PRINT_CODE */ +#ifndef __MINGW32__ +# define USE_NOTEPAD_PRINT_CODE +#endif #endif /* diff -Nru slrn-0.9.6.2.orig/src/slrnfeat.h slrn-0.9.6.2/src/slrnfeat.h --- slrn-0.9.6.2.orig/src/slrnfeat.h Fri Dec 24 02:24:37 1999 +++ slrn-0.9.6.2/src/slrnfeat.h Sat Jan 1 07:49:44 2000 @@ -7,6 +7,33 @@ * the feature will be turned off. */ +/* These are essential macro definitions for Japanized version of slrn */ +#ifndef SLRNPULL_CODE +#define KANJI +#define SLANG_HAS_KANJI_SUPPORT 1 +#endif + +/* SLRN_TZ_TYPE is not necessary, but is recommended to be defined */ +/* according to such system types as below */ +/* CYGWIN32(not MINGW32) define none */ +/* EWS4800, MINGW32(included in CYGWIN-b20), HP-UX(R11.0) */ +/* SLRN_TZ_TZNAME */ +/* FreeBSD SLRN_TZ_TM_ZONE */ +/* Linux, IRIX, SUNOS, Solaris, .... not known */ +#define SLRN_TZ_TZNAME 1 /* tzname[] */ +#define SLRN_TZ_TM_ZONE 2 /* timezone set in tm_zone of struct tm */ +#define SLRN_TZ_TIMEZONE 3 /* timezone() */ + /* choose one from listed above */ +#define SLRN_TZ_TYPE SLRN_TZ_TZNAME +/* #define SLRN_TZ_TYPE SLRN_TZ_TM_ZONE */ + +#define SLRN_DEFAULT_TIMEZONE "JST" +#define SLRN_DEFAULT_CHARSET "ISO-2022-JP" + +/* If you need not read Unicode Kanji, you may undef this macro. */ +/* because this requires a big convert table. */ +#define SLRN_UNICODE_KANJI_CONVERT 1 + /* If you enable local SPOOL support, you must also enable NNTP support * or INEWS support. Also, see below for filenames regarding the location * of the local spool and inews. Currently only unix supports this. @@ -17,7 +44,7 @@ #define SLRN_HAS_PULL_SUPPORT 1 #define SLRN_HAS_NNTP_SUPPORT 1 #define SLRN_HAS_SPOOL_SUPPORT 1 -#define SLRN_HAS_INEWS_SUPPORT 1 +#define SLRN_HAS_INEWS_SUPPORT 0 /* Set this to 1 to force the user to use INEWS for posting. This also means * that slrn will use the hardcoded inews program pathname. */ @@ -65,12 +92,12 @@ #define SLRN_HAS_SLANG 1 /* Set this to 0 if you do not want slrn to generate message-id header. */ -#define SLRN_HAS_GEN_MSGID 1 +#define SLRN_HAS_GEN_MSGID 0 /* If you want mapping ISO Latin <--> native character set, set this to 1. * Supported character sets: isolatin, ibm850, and next */ -#define SLRN_HAS_CHARACTER_MAP 1 +#define SLRN_HAS_CHARACTER_MAP 0 /* If you want to use uudeview's uulib instead of slrn's builtin one * change this to 1. You will also need to edit the Makefile to point to @@ -110,7 +137,7 @@ #endif /* If non-zero, slrn will add From header to mail messages. */ -#if defined(IBMPC_SYSTEM) +#if defined(IBMPC_SYSTEM) && !defined(KANJI) # define SLRN_GEN_FROM_EMAIL_HEADER 1 #else # define SLRN_GEN_FROM_EMAIL_HEADER 0 diff -Nru slrn-0.9.6.2.orig/src/sltcp.c slrn-0.9.6.2/src/sltcp.c --- slrn-0.9.6.2.orig/src/sltcp.c Fri Dec 24 02:24:36 1999 +++ slrn-0.9.6.2/src/sltcp.c Mon Dec 27 10:46:06 1999 @@ -49,7 +49,7 @@ # include # define USE_WINSOCK_SLTCP 1 #else -# if defined(__MINGW32__) +# if defined(__MINGW32__) || defined(__CYGWIN32__) # define Win32_Winsock # include # define USE_WINSOCK_SLTCP 1 diff -Nru slrn-0.9.6.2.orig/src/spool.c slrn-0.9.6.2/src/spool.c --- slrn-0.9.6.2.orig/src/spool.c Fri Dec 24 02:24:41 1999 +++ slrn-0.9.6.2/src/spool.c Mon Dec 27 10:46:06 1999 @@ -214,6 +214,11 @@ { fp = ftell( Spool_fh_local ); if (1 != fscanf(Spool_fh_local,"%d", &i)) +#ifdef KANJI + if (getc (Spool_fh_local) == EOF) + break; + else +#endif return -1; while (((ch = getc (Spool_fh_local)) != '\n') @@ -1149,7 +1154,11 @@ return -1; if (-1 == (n = spool_find_artnum_from_msgid (msgid))) +#ifdef KANJI + return ERR_NOART; +#else return ERR_NOARTIG; +#endif } spool_fclose_local(); diff -Nru slrn-0.9.6.2.orig/src/startup.c slrn-0.9.6.2/src/startup.c --- slrn-0.9.6.2.orig/src/startup.c Fri Dec 24 02:24:42 1999 +++ slrn-0.9.6.2/src/startup.c Wed Dec 29 11:16:43 1999 @@ -29,6 +29,9 @@ #ifdef HAVE_STDLIB_H # include #endif +#ifdef KANJI +#include +#endif #include #include @@ -398,7 +401,11 @@ {"spoiler_char", &Slrn_Spoiler_Char}, {"spoiler_display_mode", &Slrn_Spoiler_Display_Mode}, #else +#ifdef KANJI /* correct bug */ + {"spoiler_display_mode", NULL}, +#else {"spoiler_start_new_page", NULL}, +#endif {"spoiler_char", NULL}, #endif #if SLRN_HAS_MIME @@ -434,6 +441,24 @@ #else {"spool_check_up_on_nov", NULL}, #endif +#ifdef KANJI + {"japanese_messages", &Slrn_Japanese_Messages}, + {"detect_SJIS", &Slrn_Detect_SJIS}, +#ifndef IBMPC_SYSTEM + {"display_code", &Slang_Display_Code}, +#else + {"display_code", NULL}, +#endif + {"editor_code", &Slrn_Editor_Code}, +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + {"use_iso8859", &Slang_Use_ISO8859}, +#else + {"use_iso8859", NULL}, +#endif + {"gmt_to_local", &Slrn_Gmt2local}, + {"mime_strict_rfc", &Slrn_Mime_Strict_Rfc}, + {"click_on_url", &Slrn_Click_On_Url}, +#endif {NULL, NULL} }; @@ -735,6 +760,10 @@ {"tilde", SLRN_TILDE_COLOR, "green", DEF_BG, SLTT_BOLD_MASK}, {"tree", TREE_COLOR, "red", DEF_BG, 0}, {"underlinetext", UNDERLINE_COLOR, "magenta", DEF_BG, SLTT_BOLD_MASK}, +#ifdef KANJI + {"url", URL_COLOR, "white", "blue", SLTT_BOLD_MASK}, + {"url_press", URL_PRESS_COLOR, "blue", DEF_BG, 0}, +#endif {"verbatum", VERBATUM_COLOR, "green", DEF_BG, 0}, {NULL, -1, NULL, NULL, 0} @@ -1178,6 +1207,46 @@ /*}}}*/ +#ifdef KANJI +Slrn_tm Slrn_Timezone; + +static char *get_zone_name(struct tm *lt) +{ +#if SLRN_TZ_TYPE == SLRN_TZ_TZNAME + char *env; + + env = getenv("TZ"); + if (env != NULL && *env != '\0') { + tzset(); + return (tzname[lt->tm_isdst]); + } +#elif SLRN_TZ_TYPE == SLRN_TZ_TM_ZONE + return (lt->tm_zone); +#elif SLRN_TZ_TYPE == SLRN_TZ_TIMEZONE + return (timezone(Slrn_Timezone.offset, lt->tm_isdst)); +#endif + return NULL; +} + +static void put_timezone(void) +{ + struct tm *lt; + time_t t; + char *zone; + + (void) time(&t); + lt = localtime(&t); + + /* difference from GMT in minutes */ + Slrn_Timezone.offset = (mktime(gmtime(&t)) - t) / 60; + zone = get_zone_name(lt); + if (zone != NULL) { + Slrn_Timezone.std = zone; + } else { + Slrn_Timezone.std = SLRN_DEFAULT_TIMEZONE; + } +} +#endif /* KANJI */ int slrn_read_startup_file (char *name) /*{{{*/ { @@ -1220,7 +1289,17 @@ { This_Line_Num++; if (SLprep_line_ok (line, &pt)) +#ifdef KANJI + { + int ret = slrn_jis2int(Slrn_Tmp_Str, (unsigned char *)line, SLRN_TMP_STR_LEN); + if (ret > 0 && ret < 5) { + strncpy(line, (char *)Slrn_Tmp_Str, sizeof(line)); + } +#endif (void) SLcmd_execute_string (line, &Slrn_Cmd_Table); +#ifdef KANJI + } +#endif if (SLang_Error) exit_unknown_object (); } @@ -1236,6 +1315,20 @@ && (-1 == (Slrn_Default_Post_Obj = slrn_map_name_to_object_id (1, Post_Object)))) slrn_exit_error ("Post object '%s' is not supported.", Post_Object); +#ifdef KANJI +#ifdef SLANG_JVERSION + kSLcode = EUC; +#endif + if (Slrn_Editor_Code < 0) { + Slrn_Editor_Code = Slang_Display_Code; + } + Slrn_Default_Charset = slrn_find_charset(Slrn_Mime_Display_Charset); +#if !defined(SLANG_JVERSION) && !defined(IBMPC_SYSTEM) + Slang_Current_Charset = Slrn_Default_Charset; +#endif + /* put timezone from TZ environment variable */ + put_timezone(); +#endif This_File = save_this_file; This_Line = save_this_line; This_Line_Num = save_this_line_num; diff -Nru slrn-0.9.6.2.orig/src/ttymsg.c slrn-0.9.6.2/src/ttymsg.c --- slrn-0.9.6.2.orig/src/ttymsg.c Fri Dec 24 02:24:44 1999 +++ slrn-0.9.6.2/src/ttymsg.c Mon Dec 27 10:46:06 1999 @@ -22,6 +22,12 @@ #include #include +#include "slrnfeat.h" +#ifdef KANJI +#include +#include "jdmacros.h" +#include "chmap.h" +#endif #include "ttymsg.h" void slrn_tty_vmessage (FILE *fp, char *fmt, va_list ap) @@ -29,6 +35,13 @@ static FILE *last_fp; if ((fp == stdout) || (last_fp == stdout)) fputc ('\n', fp); +#ifdef KANJI + if (Slang_Display_Code != EUC) { + (void) vsprintf((char *)Slrn_Tmp_Str, fmt, ap); + slrn_conv_string((char *)Slrn_Tmp_Str, Slang_Display_Code); + fputs((char *)Slrn_Tmp_Str, fp); + } else +#endif (void) vfprintf(fp, fmt, ap); if (fp == stderr) fputc ('\n', fp); fflush (fp); @@ -36,6 +49,7 @@ last_fp = fp; } +#ifndef KANJI void slrn_tty_message (char *fmt, ...) { va_list ap; @@ -53,4 +67,5 @@ slrn_tty_vmessage (stderr, fmt, ap); va_end (ap); } +#endif diff -Nru slrn-0.9.6.2.orig/src/util.h slrn-0.9.6.2/src/util.h --- slrn-0.9.6.2.orig/src/util.h Fri Dec 24 02:24:44 1999 +++ slrn-0.9.6.2/src/util.h Mon Dec 27 10:46:06 1999 @@ -62,6 +62,10 @@ * in util.c. */ extern void slrn_exit_error (char *, ...); +#ifdef KANJI +char *slrn_make_from_string (int); +#else char *slrn_make_from_string (void); +#endif #endif /* _SLRN_UTIL_H */ diff -Nru slrn-0.9.6.2.orig/src/uudecode.c slrn-0.9.6.2/src/uudecode.c --- slrn-0.9.6.2.orig/src/uudecode.c Fri Dec 24 02:24:37 1999 +++ slrn-0.9.6.2/src/uudecode.c Wed Dec 29 12:06:44 1999 @@ -83,6 +83,11 @@ # include "slrn.h" # include "misc.h" # include "uudecode.h" +#ifdef KANJI +# include "group.h" +# include "art.h" +# include "mime.h" +#endif # define SLRN_POPEN slrn_popen # define SLRN_PCLOSE slrn_pclose char *Slrn_Decode_Directory; @@ -172,6 +177,7 @@ /*}}}*/ +#ifndef KANJI static unsigned char Base64_Table [256]; static void initialize_base64 (void) /*{{{*/ @@ -263,6 +269,7 @@ } /*}}}*/ +#endif @@ -276,6 +283,51 @@ { int decoding = 0; unsigned int len; +#ifdef KANJI + int ch; + char *dest; + + while (NULL != fgets (line, buflen, fp)) { + ch = (unsigned char)*line; + if ((ch & 0x80) || slrn_base64(ch) == -1) { + if (decoding) return 0; + else return -1; + } + + len = strlen (line); + if (len) { + if (line [len - 1] == '\n') { + line[len - 1] = 0; + len--; + } + } + + if ((len % 4) != 0) { + if (decoding) return 0; + else return -1; + } + + dest = line; + while(*dest) { /* check base64 line */ + ch = *dest++; + if (((ch & 0x80) || slrn_base64(ch) == -1) && + (ch != '=' || (dest - line + 1) % 4 > 1)) { + if (decoding) { + return 0; + } + return -1; + } + } + dest = slrn_decode_base64 (line, line, line + len); + len = 0; + while(line + len != dest) { + fputc(line[len], fpout); + len++; + } + if (len % 3 != 0) { /* indicates last line */ + return 1; + } +#else int ret; while (NULL != fgets (line, buflen, fp)) @@ -308,6 +360,7 @@ if ((ret == -1) && decoding) ret = 0; return ret; } +#endif decoding = 1; } @@ -502,10 +555,29 @@ static int parse_content_type (char *p, Mime_Message_Partial_Type *mpt) /*{{{*/ { +#ifdef KANJI + char *q = p; + + if ((p = skip_header_string (p, "application")) != NULL + && (p = skip_header_string (p, "/")) != NULL + && (p = skip_header_string (p, "octet-stream")) != NULL + && (p = skip_header_string (p, ";")) != NULL) { + mpt->number = 1; + mpt->total = 1; + *mpt->id = '\0'; + } else { + p = q; + } +#endif #if 1 (void) parse_name_eqs_string (p, "name", Base64_Filename, sizeof (Base64_Filename)); #endif +#ifdef KANJI + if (p != q) { + return 0; + } +#endif if ((NULL == (p = skip_header_string (p, "message"))) || (NULL == (p = skip_header_string (p, "/"))) || (NULL == (p = skip_header_string (p, "partial"))) @@ -569,7 +641,9 @@ Mime_Message_Partial_Type *current_pmt, pmt_buf; int part = 1; +#ifndef KANJI initialize_base64 (); +#endif current_pmt = NULL; @@ -721,6 +795,9 @@ { FILE *outfp = NULL; char buf[MAX_ARTICLE_LINE_LEN]; +#ifdef KANJI + unsigned int checksum, may_be_lastline = 0; +#endif while (NULL != fgets (buf, sizeof (buf), fp)) { @@ -766,6 +843,11 @@ if (!strcmp (buf, "end\n")) { +#ifdef KANJI + if (may_be_lastline) { + write_len = fwrite ((char *) out, 1, len, outfp); + } +#endif uudecode_fclose (outfp, pipe_fp); outfp = NULL; break; @@ -776,6 +858,24 @@ len = *buf; no_slop = 0; +#ifdef KANJI + may_be_lastline = 0; + /* uuencode のチェックサムに対応 */ + buflen = strlen (buf); + if (buf[buflen - 1] == '\n') { + buflen--; + } + if ((buflen - 2) % 4) { + checksum = '\0'; + } else { /* checksum あり */ + buflen--; + checksum = buf[buflen]; + } + buflen--; + if (len <= ' ' || len > '`' + || buflen > 60 || buflen % 4 != 0) + { +#else if ((len <= ' ') || (len >= (60 + ' ')) || ((buflen = strlen (buf)) > 62) || (buflen < 2) @@ -785,6 +885,7 @@ #if 0 fprintf (stderr, "%s", buf); #endif +#endif if (strncmp (buf, "begin ", 6) || (-1 == parse_uuencode_begin_line ((unsigned char *)buf + 6, &file, &mode))) @@ -798,8 +899,12 @@ continue; } +#ifdef KANJI + len = (len - ' ') & 0x3f; +#else buflen -= 2; len -= ' '; +#endif /* In general, I cannot make the test: * @ if ((3 * buflen) != (len * 4)) continue; @@ -825,9 +930,13 @@ #endif continue; } +#ifdef KANJI + may_be_lastline = 1; +#else /* This may still be a bogus line, e.g., a header. */ if (NULL != slrn_strchr (buf, ' ')) continue; +#endif } @@ -836,12 +945,22 @@ while (b < bmax) { +#ifdef KANJI + if (*b < ' ' || *b > '`') break; +#endif *b = (*b - 32) & 0x3F; +#ifdef KANJI + b++; +#else *(b + 1) = (*(b + 1) - 32) & 0x3F; *(b + 2) = (*(b + 2) - 32) & 0x3F; *(b + 3) = (*(b + 3) - 32) & 0x3F; b += 4; +#endif } +#ifdef KANJI + if (b < bmax) continue; +#endif b = (unsigned char *) buf + 1; @@ -865,6 +984,9 @@ b += 4; } +#ifdef KANJI + if (may_be_lastline) continue; +#endif if (len != (write_len = fwrite ((char *) out, 1, len, outfp))) { slrn_error ("write to file failed (%u/%u bytes)\n", diff -Nru slrn-0.9.6.2.orig/src/version.c slrn-0.9.6.2/src/version.c --- slrn-0.9.6.2.orig/src/version.c Fri Dec 24 02:24:36 1999 +++ slrn-0.9.6.2/src/version.c Tue Dec 28 01:23:40 1999 @@ -34,13 +34,20 @@ #endif #include +#ifdef KANJI +#include "jdmacros.h" +#endif #include "version.h" #include "server.h" #include "group.h" #include "art.h" #include "chmap.h" +#ifdef KANJI +char *Slrn_Version = SLRN_VERSION"jp0"; +#else char *Slrn_Version = SLRN_VERSION; +#endif typedef struct { @@ -51,6 +58,9 @@ static Compile_Option_Type Compile_Options [] = { +#ifdef KANJI + {"KANJI", 1}, +#endif {"PULL_SUPPORT", SLRN_HAS_PULL_SUPPORT}, {"NNTP_SUPPORT", SLRN_HAS_NNTP_SUPPORT}, {"SPOOL_SUPPORT", SLRN_HAS_SPOOL_SUPPORT}, @@ -70,8 +80,10 @@ {"FAKE_REFS", SLRN_HAS_FAKE_REFS}, {"DECODE", SLRN_HAS_DECODE}, {"PIPING", SLRN_HAS_PIPING}, +#ifndef KANJI {"PIPING", SLRN_HAS_PIPING}, {"DECODE", SLRN_HAS_DECODE}, +#endif {"RNLOCK", SLRN_HAS_RNLOCK}, {"EMPHASIZED_TEXT", SLRN_HAS_EMPHASIZED_TEXT}, {"VERBATUM_MARKS", SLRN_HAS_VERBATUM_MARKS}, @@ -136,6 +148,9 @@ fprintf (stdout, "Slrn Version: %s\n", Slrn_Version); #endif fprintf (stdout, "S-Lang Library Version: %s\n", make_slang_version (SLang_Version)); +#if defined(SLANG_JVERSION) && SLANG_VERSION < 10308 + fprintf (stdout, " (JVersion: %s)\n", make_slang_version (SLang_JVersion)); +#endif if (SLANG_VERSION != SLang_Version) { fprintf (stdout, "\t** Note: This program was compiled against version %s.\n",