--- kf.c.orig	Sat Sep 29 13:43:18 2001
+++ kf.c	Sat Jan 19 13:41:50 2002
@@ -33,21 +33,19 @@
         -o ¤¬¤Ê¤±¤ì¤ÐÉ¸½à½ÐÎÏ¤Ë
 **********************************************************************
 EUC
-    G0 7¥Ó¥Ã¥ÈÊ¸»ú 00¡Á7F
-    G1 ´Á»ú        A1¡ÁFE A1¡ÁFE
+    G0 ASCII       00¡Á7F
+    G1 ´Á»ú1ÌÌ     A1¡ÁFE A1¡ÁFE
     G2 È¾³Ñ¥«¥Ê    8E A0¡ÁDF
-    G3 ³°»ú        8F A1¡ÁFE A1¡ÁFE
+    G3 ´Á»ú2ÌÌ     8F A1¡ÁFE A1¡ÁFE
 
 JIS
     ´Á»ú     21¡Á7E 21¡Á7E
     È¾³Ñ¥«¥Ê 20¡Á5F
 
-    Âè1¿å½à  2121¡Á4F53
-    Âè2¿å½à  5021¡Á7C6E
-
     78´Á»ú¤Ë   ESC $ @
     83´Á»ú¤Ë   ESC $ B ¢«ÊÑ´¹¤¹¤ë¾ì¹ç¤Ï¤³¤Á¤é¤ò»ÈÍÑ
-   (Êä½õ´Á»ú¤Ë ESC $ D)¢«Ì¤¥µ¥Ý¡¼¥È
+    X0213 1ÌÌ  ESC $ ( O
+    X0213 2ÌÌ  ESC $ ( P
 
     US ASCII¤Ë ESC ( B ¢«ÊÑ´¹¤¹¤ë¾ì¹ç¤Ï¤³¤Á¤é¤ò»ÈÍÑ
     ANK¤Ë      ESC ( J
@@ -56,19 +54,18 @@
     ËÜ¤ËÌá¤ë   0F or ESC ( B
 
 SJIS
-    ´Á»ú1¥Ð¥¤¥ÈÌÜ  81¡Á9F, E0¡ÁEF(¡ÁFC)
+    ´Á»ú1¥Ð¥¤¥ÈÌÜ  81¡Á9F, E0¡ÁFC
 
     ´Á»ú2¥Ð¥¤¥ÈÌÜ  40¡Á7E, 80¡ÁFC
     È¾³Ñ¥«¥Ê       A0¡ÁDF
 
-    Âè1¿å½à        8140¡Á9872
-    Âè2¿å½à        989F¡ÁFC4B
-
 Ãí: È¾³Ñ¥«¥Ê¤Î 20 (A0) ¤ÏÈ¾³Ñ¥¹¥Ú¡¼¥¹¤Ç¤¢¤ë¤¬ ' ' ¤È¤ÏÊÌ°·¤¤¤·¤¿
 
 MIME (RFC2045-2049)
     BASE64:           =?ISO-2022-JP?B?.....?=
+    BASE64:           =?ISO-2022-JP-3?B?.....?=
     Quoted-Printable: =?ISO-2022-JP?Q?.....?=
+   (Quoted-Printable: =?ISO-2022-JP-3?Q?.....?=)¢«Ì¤¥µ¥Ý¡¼¥È
     (=?iso-2022-jp?b?.....?= ¤Ê¤É¤Ç¤â¤¤¤¤)
     ..... ¤ÎÉôÊ¬¤Ï ? ¤È¥¹¥Ú¡¼¥¹°Ê³°¤Î7¥Ó¥Ã¥È¤Î°õºþ²ÄÇ½¤ÊASCIIÊ¸»ú
     ºÇ½é¤Î = ¤«¤éºÇ¸å¤Î = ¤Þ¤Ç¤Ç 75 ¥Ð¥¤¥È°ÊÆâ¤È¤µ¤ì¤Æ¤¤¤ë¤¬¼é¤é¤ì¤Æ
@@ -94,8 +91,10 @@
 #define isjis(c) (((c)>=0x21 && (c)<=0x7e))
 #define iseuc(c) (((c)>=0xa1 && (c)<=0xfe))
 
-/* ¥·¥Õ¥ÈJIS 1¥Ð¥¤¥ÈÌÜ */
+/* ¥·¥Õ¥ÈJIS 1¥Ð¥¤¥ÈÌÜ (1ÌÌ)*/
 #define issjis1(c) (((c)>=0x81 && (c)<=0x9f) || ((c)>=0xe0 && (c)<=0xef))
+/* ¥·¥Õ¥ÈJIS 1¥Ð¥¤¥ÈÌÜ (2ÌÌ)*/
+#define issjis1_2(c) ((c)>=0xf0 && (c)<=0xfc)
 
 /* ¥·¥Õ¥ÈJIS 2¥Ð¥¤¥ÈÌÜ */
 #define issjis2(c) ((c)>=0x40 && (c)<=0xfc && (c)!=0x7f)
@@ -103,10 +102,10 @@
 /* ¤¤¤ï¤æ¤ëÈ¾³Ñ¥«¥Ê */
 #define ishankana(c) ((c)>=0xa0 && (c)<=0xdf)
 
-enum { UNKNOWN, SJIS, EUC, JIS }
+enum { UNKNOWN, SJIS, EUC, JIS, JIS3 }
     icode, default_icode = UNKNOWN, ocode = DEFAULT_OCODE;
 
-char *codename[] = { "UNKNOWN", "SJIS", "EUC", "JIS" };
+char *codename[] = { "UNKNOWN", "SJIS", "EUC", "JIS", "ISO-2022-JP-3" };
 
 int verbose = 0;
 int overwrite = 0;
@@ -137,6 +136,13 @@
     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
 };
 
+/* 2ÌÌ¤ÎSJIS¤Î¤¦¤ÁÂè1¥Ð¥¤¥È¤¬f0¡Áf4¤Î¤â¤Î¤«¤éJISÂè1¥Ð¥¤¥È¤òµá¤á¤ëÉ½¡£
+   ¹Ô¤ÏÂè1¥Ð¥¤¥Èf0¡Áf4¡¢Îó¤ÏÂè2¥Ð¥¤¥È<9f, >=9f ¤ËÂÐ±þ¡£ */
+int plane2sjis[][2] = {
+  { 0x21, 0x28 }, { 0x23, 0x24 }, { 0x25, 0x20 + 12 },
+  { 0x20 + 13, 0x20 + 14 }, {0x20 + 15, 0x20 + 78 }
+};
+
 void error(char *format, ...)   /* ¥¨¥é¡¼¤òÊó¹ð¤·¡¤½ªÎ» */
 {
     va_list argptr;
@@ -148,7 +154,7 @@
     exit(1);
 }
 
-void sjis_to_jis(int *ph, int *pl)  /* ¥·¥Õ¥ÈJIS¤òJIS¤Ë */
+void sjis_to_jis(int *ph, int *pl)  /* ¥·¥Õ¥ÈJIS¤òJIS¤Ë (1ÌÌ) */
 {
     if (*ph <= 0x9f) {
         if (*pl < 0x9f)  *ph = (*ph << 1) - 0xe1;
@@ -162,7 +168,19 @@
     else                 *pl -= 0x7e;
 }
 
-void jis_to_sjis(int *ph, int *pl)  /* JIS¤ò¥·¥Õ¥ÈJIS¤Ë */
+void sjis2_to_jis(int *ph, int *pl)  /* ¥·¥Õ¥ÈJIS¤òJIS¤Ë (2ÌÌ) */
+{
+    if (*ph <= 0xf4) {
+        *ph = plane2sjis[*ph - 0xf0][(*pl <= 0x9e) ? 0 : 1];
+    } else {
+        *ph = 79 + (*ph - 0xf5) * 2 + ((*pl <= 0x9e) ? 0 : 1) + 0x20;
+    }
+    if      (*pl < 0x7f) *pl -= 0x1f;
+    else if (*pl < 0x9f) *pl -= 0x20;
+    else                 *pl -= 0x7e;
+}
+
+void jis_to_sjis(int *ph, int *pl)  /* JIS¤ò¥·¥Õ¥ÈJIS¤Ë (1ÌÌ) */
 {
     if (*ph & 1) {
         if (*pl < 0x60)  *pl += 0x1f;
@@ -172,6 +190,19 @@
     else                 *ph = (*ph + 0x161) >> 1;
 }
 
+void jis_to_sjis2(int *ph, int *pl)  /* JIS¤ò¥·¥Õ¥ÈJIS¤Ë (2ÌÌ) */
+{
+    int k = *ph - 0x20;
+    if (k == 1 || (3 <= k && k <= 5) || k == 8 || (12 <= k && k <= 15)) {
+        *ph = (k + 0x1df) / 2 - (k / 8) * 3;
+    } else if (k >= 78 && k <= 94) {
+        *ph = (k + 0x19b) / 2;
+    }
+    *pl = ((k & 1) ? 
+           ((*pl - 0x20 <= 63) ? (*pl - 0x20 + 0x3f) : (*pl - 0x20 + 0x40)) :
+           (*pl - 0x20 + 0x9e));
+}
+
 void guess(int imax, unsigned char buf[])
 {
     int i, bad_euc, bad_sjis;
@@ -220,21 +251,22 @@
 
 int decode_mime(unsigned char *buf)
 {
-    int k, p, q;
+    int k, p, q, len;
     unsigned long c;
 
     p = q = 0;
     mimetrue = 0;
     /* The following line is just an optimization. */
     if (buf[0] != '=') return strlen(buf);
-    if (strncasecmp(buf, "=?ISO-2022-JP?B?", 16) == 0) {
-        p = 16;
+    if ((len = 16, strncasecmp(buf, "=?ISO-2022-JP?B?", 16) == 0) ||
+        (len = 18, strncasecmp(buf, "=?ISO-2022-JP-3?B?", 18) == 0)) {
+        p = len;
         while (mimetbl[buf[p]] != 64) p++;
-        q = p % 4;
+        q = (p - (len - 16)) % 4;
         if ((q == 0 && strncmp(&buf[p],   "?=", 2) == 0) ||
             (q == 2 && strncmp(&buf[p], "==?=", 4) == 0) ||
             (q == 3 && strncmp(&buf[p],  "=?=", 3) == 0)) {
-            p = 16;
+            p = len;
             q = 0;
             c = 1;
             while ((k = mimetbl[buf[p]]) != 64) {
@@ -452,10 +484,38 @@
     }
 }
 
+int isDefinedInX0208(int high, int low)
+{
+    int ku = high - 0x20;
+    int ten = low - 0x20;
+
+    if ((ku == 1) ||
+        (ku == 2 && (ten <= 14 || (26 <= ten && ten <= 33) || 
+                     (42 <= ten && ten <= 48) || (60 <= ten && ten <= 74) ||
+                     (82 <= ten && ten <= 89) || (ten == 94))) ||
+        (ku == 3 && ((16 <= ten && ten <= 25) || (33 <= ten && ten <= 58) ||
+                     (65 <= ten && ten <= 90))) ||
+        (ku == 4 && ten <= 83) ||
+        (ku == 5 && ten <= 86) ||
+        (ku == 6 && ((ten <= 24) || (33 <= ten && ten <= 56))) ||
+        (ku == 7 && ((ten <= 33) || (49 <= ten && ten <= 81))) ||
+        (ku == 8 && ten <= 32)) {
+        /* Èó´Á»ú */
+        return 1;
+    } else if ((16 <= ku && ku <= 46) || (ku == 47 && ten <= 51)) {
+        /* ´Á»úÂè1¿å½à */
+        return 1;
+    } else if ((48 <= ku && ku <= 83) || (ku == 84 && ten <= 6)) {
+        /* ´Á»úÂè2¿å½à */
+        return 1;
+    }
+    return 0;
+}
+
 void tosjis(void)
 {
     int c, d, flag;
-    enum {NORMAL, KANJI, HANKANA} mode = NORMAL;
+    enum {NORMAL, KANJI1, KANJI2, HANKANA} mode = NORMAL;
 
     icode = default_icode;
     flag = 0;
@@ -464,7 +524,15 @@
         if (c == 0x1b) {
             if ((c = mygetc()) == '$') {
                 if ((c = mygetc()) == '@' || c == 'B') {
-                    mode = KANJI;
+                    mode = KANJI1;
+                } else if (c == '(') {
+                    if ((c = mygetc()) == 'O') {
+                        mode = KANJI1;
+                    } else if (c == 'P') {
+                        mode = KANJI2;
+                    } else if (! text) {
+                        myputc(0x1b);  myputc('$');  myputc('(');  myputc(c);
+                    }
                 } else if (! text) {
                     myputc(0x1b);  myputc('$');  myputc(c);
                 }
@@ -483,10 +551,14 @@
             mode = HANKANA;
         } else if (c == 0x0f) {
             mode = NORMAL;
-        } else if (mode == KANJI && isjis(c)) {
+        } else if ((mode == KANJI1 || mode == KANJI2) && isjis(c)) {
             d = mygetc();
             if (isjis(d)) {
-                jis_to_sjis(&c, &d);
+                if (mode == KANJI1) {
+                    jis_to_sjis(&c, &d);
+                } else if (mode == KANJI2) {
+                    jis_to_sjis2(&c, &d);
+                }
                 myputc(c);  myputc(d);
             } else {
                 c = d;  flag = 1;
@@ -515,6 +587,20 @@
                 } else {
                     flag = 1;
                 }
+            } else if (c == 0x8f) {  /* SS3, Â¨¤Á2ÌÌ¤Î¸Æ¤Ó½Ð¤· */
+                c = mygetc();
+                if (iseuc(c)) {
+                    d = mygetc();
+                    if (iseuc(d)) {
+                        c &= 0x7f;  d &= 0x7f;
+                        jis_to_sjis2(&c, &d);
+                        myputc(c);  myputc(d);
+                    } else {
+                        c = d;  flag = 1;
+                    }
+                } else {
+                    flag = 1;
+                }
             } else if (! text || c == '\t' || c == '\n' || c == '\r' ||
                        c == 12 || (c >= ' ' && c < 0x7f)) {
                 myputc(c);
@@ -537,7 +623,7 @@
 void tojis(void)
 {
     int c, d, flag;
-    enum {NORMAL, KANJI, HANKANA} mode = NORMAL;
+    enum {NORMAL, KANJIOLD, KANJI1, KANJI2, HANKANA} mode = NORMAL;
 
     icode = default_icode;
     flag = 0;
@@ -550,9 +636,26 @@
                 d = mygetc();
                 if (issjis2(d)) {
                     sjis_to_jis(&c, &d);
-                    if (mode != KANJI) {
-                        mode = KANJI;
-                        myputc(0x1b);  myputc('$');  myputc('B');
+                    if ((ocode != JIS3) && isDefinedInX0208(c, d)) {
+                        if (mode != KANJIOLD) {
+                            myputc(0x1b);  myputc('$');  myputc('B');
+                            mode = KANJIOLD;
+                        }
+                    } else if (mode != KANJI1) {
+                        myputc(0x1b);  myputc('$');  myputc('(');  myputc('O');
+                        mode = KANJI1;
+                    }
+                    myputc(c);  myputc(d);
+                } else {
+                    c = d;  flag = 1;
+                }
+            } else if (issjis1_2(c)) {
+                d = mygetc();
+                if (issjis2(d)) {
+                    sjis2_to_jis(&c, &d);
+                    if (mode != KANJI2) {
+                        myputc(0x1b);  myputc('$');  myputc('(');  myputc('P');
+                        mode = KANJI2;
                     }
                     myputc(c);  myputc(d);
                 } else {
@@ -578,14 +681,36 @@
             if (iseuc(c)) {
                 d = mygetc();
                 if (iseuc(d)) {
-                    if (mode != KANJI) {
-                        mode = KANJI;
-                        myputc(0x1b);  myputc('$');  myputc('B');
+                    c &= 0x7f;  d &= 0x7f;
+                    if ((ocode != JIS3) && isDefinedInX0208(c, d)) {
+                        if (mode != KANJIOLD) {
+                            myputc(0x1b);  myputc('$');  myputc('B');
+                            mode = KANJIOLD;
+                        }
+                    } else if (mode != KANJI1) {
+                        myputc(0x1b);  myputc('$');  myputc('(');  myputc('O');
+                        mode = KANJI1;
                     }
-                    myputc(c & 0x7f);  myputc(d & 0x7f);
+                    myputc(c);  myputc(d);
                 } else {
                     c = d;  flag = 1;
                 }
+            } else if (c == 0x8f) {
+                c = mygetc();
+                if (iseuc(c)) {
+                    d = mygetc();
+                    if (iseuc(d)) {
+                        if (mode != KANJI2) {
+                            mode = KANJI2;
+                            myputc(0x1b);  myputc('$');  myputc('(');  myputc('P');
+                        }
+                        myputc(c & 0x7f);  myputc(d & 0x7f);
+                    } else {
+                        c = d;  flag = 1;
+                    }
+                } else {
+                    flag = 1;
+                }
             } else if (c == 0x8e) {
                 c = mygetc();
                 if (ishankana(c)) {
@@ -615,7 +740,7 @@
 void toeuc(void)
 {
     int c, d, flag;
-    enum {NORMAL, KANJI, HANKANA} mode = NORMAL;
+    enum {NORMAL, KANJI1, KANJI2, HANKANA} mode = NORMAL;
 
     icode = default_icode;
     flag = 0;
@@ -624,7 +749,15 @@
         if (c == 0x1b) {
             if ((c = mygetc()) == '$') {
                 if ((c = mygetc()) == '@' || c == 'B') {
-                    mode = KANJI;
+                    mode = KANJI1;
+                } else if (c == '(') {
+                    if ((c = mygetc()) == 'O') {
+                        mode = KANJI1;
+                    } else if (c == 'P') {
+                        mode = KANJI2;
+                    } else if (! text) {
+                        myputc(0x1b);  myputc('$');  myputc('(');  myputc(c);
+                    }
                 } else if (! text) {
                     myputc(0x1b);  myputc('$');  myputc(c);
                 }
@@ -643,9 +776,12 @@
             mode = HANKANA;
         } else if (c == 0x0f) {
             mode = NORMAL;
-        } else if (mode == KANJI && isjis(c)) {
+        } else if ((mode == KANJI1 || mode == KANJI2) && isjis(c)) {
             d = mygetc();
             if (isjis(d)) {
+                  if (mode == KANJI2) {
+                    myputc(0x8f);
+                }
                 myputc(c | 0x80);  myputc(d | 0x80);
             } else {
                 c = d;  flag = 1;
@@ -661,6 +797,14 @@
                 } else {
                     c = d;  flag = 1;
                 }
+            } else if (issjis1_2(c)) {  /* 2ÌÌ¤Î¾ì¹ç */
+                d = mygetc();
+                if (issjis2(d)) {
+                    sjis2_to_jis(&c, &d);
+                    myputc(0x8f);  myputc(c | 0x80);  myputc(d | 0x80);
+                } else {
+                    c = d;  flag = 1;
+                }
             } else if (ishankana(c)) {
                 myputc(0x8e);  myputc(c);
             } else if (! text || c == '\t' || c == '\n' || c == '\r' ||
@@ -696,6 +840,7 @@
     if      (ocode == SJIS) tosjis();
     else if (ocode ==  EUC) toeuc();
     else if (ocode ==  JIS) tojis();
+    else if (ocode == JIS3) tojis();
 }
 
 void usage(void)
@@ -736,6 +881,7 @@
                 if      (c == 'e') ocode = EUC;
                 else if (c == 's') ocode = SJIS;
                 else if (c == 'j') ocode = JIS;
+                else if (c == '3') ocode = JIS3;
                 else if (c == 'S') default_icode = SJIS;
                 else if (c == 'E') default_icode = EUC;
                 else if (c == 'm') mime = 1;
