OSDN Git Service

UTF-16 入力の変換の一部バグ修正
[nkf/nkf.git] / nkf.c
diff --git a/nkf.c b/nkf.c
index 23e6a99..57534e2 100644 (file)
--- a/nkf.c
+++ b/nkf.c
@@ -95,8 +95,11 @@ static char *Patchlevel =
 **
 **/
 
-#if (defined(__TURBOC__) || defined(LSI_C)) && !defined(MSDOS)
+#if (defined(__TURBOC__) || defined(_MSC_VER) || defined(LSI_C)) && !defined(MSDOS)
 #define MSDOS
+#if (defined(__Win32__) || defined(_WIN32)) && !defined(__WIN32__)
+#define __WIN32__
+#endif
 #endif
 
 #ifdef PERL_XS
@@ -125,7 +128,7 @@ static char *Patchlevel =
 #define setbinmode(fp)
 #endif
 
-#ifdef _IOFBF /* SysV and MSDOS */
+#ifdef _IOFBF /* SysV and MSDOS, Windows */
 #define       setvbuffer(fp, buf, size)       setvbuf(fp, buf, _IOFBF, size)
 #else /* BSD */
 #define       setvbuffer(fp, buf, size)       setbuffer(fp, buf, size)
@@ -134,15 +137,25 @@ static char *Patchlevel =
 /*Borland C++ 4.5 EasyWin*/
 #if defined(__TURBOC__) && defined(_Windows) && !defined(__WIN32__) /*Easy Win */
 #define         EASYWIN
+#ifndef __WIN16__
+#define __WIN16__
+#endif
 #include <windows.h>
 #endif
 
 #ifdef OVERWRITE
 /* added by satoru@isoternet.org */
 #include <sys/stat.h>
-#ifndef MSDOS
+#ifndef MSDOS /* UNIX, OS/2 */
 #include <unistd.h>
 #include <utime.h>
+#else
+#if defined(_MSC_VER) /* VC++ */
+#include <sys/utime.h>
+#elif defined(__TURBOC__) /* BCC */
+#include <utime.h>
+#elif defined(LSI_C) /* LSI C */
+#endif
 #endif
 #endif 
 
@@ -253,6 +266,7 @@ struct input_code{
     int buf[3];
     void (*status_func)PROTO((struct input_code *, int));
     int (*iconv_func)PROTO((int c2, int c1, int c0));
+    int _file_stat;
 };
 
 STATIC  int     noconvert PROTO((FILE *f));
@@ -357,6 +371,7 @@ static int             x0201_f = NO_X0201;     /* Assume NO JISX0201 */
 static int             iso2022jp_f = FALSE;    /* convert ISO-2022-JP */
 #ifdef UTF8_OUTPUT_ENABLE
 static int             w_oconv16_begin_f= 0;   /* utf-16 header */
+static int             w_oconv16_LE = 0;   /* utf-16 little endian */
 #endif
 
 
@@ -399,13 +414,15 @@ STATIC void s_status PROTO((struct input_code *, int));
 
 #ifdef UTF8_INPUT_ENABLE
 STATIC void w_status PROTO((struct input_code *, int));
+STATIC void w16_status PROTO((struct input_code *, int));
 static int             utf16_mode = UTF16_INPUT;
 #endif
 
 struct input_code input_code_list[] = {
-    {"EUC-JP",    0, 0, 0, {0, 0, 0}, e_status, e_iconv},
-    {"Shift_JIS", 0, 0, 0, {0, 0, 0}, s_status, s_iconv},
-    {"UTF-8",     0, 0, 0, {0, 0, 0}, w_status, w_iconv},
+    {"EUC-JP",    0, 0, 0, {0, 0, 0}, e_status, e_iconv, 0},
+    {"Shift_JIS", 0, 0, 0, {0, 0, 0}, s_status, s_iconv, 0},
+    {"UTF-8",     0, 0, 0, {0, 0, 0}, w_status, w_iconv, 0},
+    {"UTF-16",     0, 0, 0, {0, 0, 0}, w16_status, w_iconv16, 0},
     {0}
 };
 
@@ -966,7 +983,16 @@ options(cp)
                output_conv = w_oconv16; cp+=2;
                if (cp[0]=='L') {
                    w_oconv16_begin_f=2; cp++;
-               }
+                   w_oconv16_LE = 1;
+                    if (cp[0] == '0'){
+                        w_oconv16_begin_f=1; cp++;
+                    }
+               } else if (cp[0] == 'B') {
+                   w_oconv16_begin_f=2; cp++;
+                    if (cp[0] == '0'){
+                        w_oconv16_begin_f=1; cp++;
+                    }
+                }
            } else
                 output_conv = w_oconv;
             continue;
@@ -1219,6 +1245,13 @@ void status_reset(ptr)
     ptr->index = 0;
 }
 
+void status_reinit(ptr)
+     struct input_code *ptr;
+{
+    status_reset(ptr);
+    ptr->_file_stat = 0;
+}
+
 void status_check(ptr, c)
      struct input_code *ptr;
      int c;
@@ -1314,6 +1347,54 @@ void e_status(ptr, c)
 }
 
 #ifdef UTF8_INPUT_ENABLE
+void w16_status(ptr, c)
+     struct input_code *ptr;
+     int c;
+{
+    switch (ptr->stat){
+      case -1:
+          break;
+      case 0:
+          if (ptr->_file_stat == 0){
+              if (c == 0xfe || c == 0xff){
+                  ptr->stat = c;
+                  status_push_ch(ptr, c);
+                  ptr->_file_stat = 1;
+              }else{
+                  status_disable(ptr);
+                  ptr->_file_stat = -1;
+              }
+          }else if (ptr->_file_stat > 0){
+              ptr->stat = 1;
+              status_push_ch(ptr, c);
+          }else if (ptr->_file_stat < 0){
+              status_disable(ptr);
+          }
+          break;
+
+      case 1:
+          if (c == EOF){
+              status_disable(ptr);
+              ptr->_file_stat = -1;
+          }else{
+              status_push_ch(ptr, c);
+              status_reset(ptr);
+          }
+          break;
+
+      case 0xfe:
+      case 0xff:
+          if (ptr->stat != c && (c == 0xfe || c == 0xff)){
+              status_push_ch(ptr, c);
+              status_reset(ptr);
+          }else{
+              status_disable(ptr);
+              ptr->_file_stat = -1;
+          }
+          break;
+    }
+}
+
 void w_status(ptr, c)
      struct input_code *ptr;
      int c;
@@ -1375,7 +1456,7 @@ code_status(c)
     }
 
     if (action_flag){
-        if (result){
+        if (result && !estab_f){
             set_iconv(TRUE, result->iconv_func);
         }else if (c <= DEL){
             struct input_code *ptr = input_code_list;
@@ -1524,7 +1605,7 @@ module_connection()
     {
         struct input_code *p = input_code_list;
         while (p->name){
-            status_reset(p++);
+            status_reinit(p++);
         }
     }
 }
@@ -2041,11 +2122,12 @@ w16e_conv(val, p2, p1)
         if (c0){
             pp = utf8_to_euc_3bytes[c2 - 0x80];
             psize = sizeof_utf8_to_euc_C2;
+            return w_iconv_common(c1, c0, pp, psize, p2, p1);
         }else{
             pp = utf8_to_euc_2bytes;
             psize = sizeof_utf8_to_euc_2bytes;
+            return w_iconv_common(c2, c1, pp, psize, p2, p1);
         }
-        return w_iconv_common(c1, c0, pp, psize, p2, p1);
     }
     return val;
 }
@@ -2067,7 +2149,7 @@ w_iconv16(c2, c1, c0)
        int tmp;
        tmp=c1; c1=c2; c2=tmp;
     }
-    if (c2==0 || c2==EOF) {
+    if ((c2==0 && c1 < 0x80) || c2==EOF) {
        (*oconv)(c2, c1);
        return 0;
     }
@@ -2172,25 +2254,36 @@ w_oconv16(c2, c1)
     int    c2,
                     c1;
 {
-    
-    if (w_oconv16_begin_f==2) {
-       (*o_putc)('\376');
-       (*o_putc)('\377');
-       w_oconv16_begin_f=1;
-    }
     if (c2 == EOF) {
         (*o_putc)(EOF);
         return;
-    } else if (c2 == 0) { 
-        (*o_putc)(0);
-        (*o_putc)(c1);
-    } else if (c2 == ISO8859_1) {
-        (*o_putc)(0);
-        (*o_putc)(c1 | 0x080);
-    } else {
+    }    
+
+    if (w_oconv16_begin_f==2) {
+        if (w_oconv16_LE){
+            (*o_putc)((unsigned char)'\377');
+            (*o_putc)('\376');
+        }else{
+            (*o_putc)('\376');
+            (*o_putc)((unsigned char)'\377');
+        }
+       w_oconv16_begin_f=1;
+    }
+
+    if (c2 == ISO8859_1) {
+        c2 = 0;
+        c1 |= 0x80;
+    } else if (c2) {
         unsigned short val = (unsigned short)e2w_conv(c2, c1);
-        (*o_putc)((val&0xff00)>>8);
-        (*o_putc)(val&0xff);
+        c2 = (val >> 8) & 0xff;
+        c1 = val & 0xff;
+    }
+    if (w_oconv16_LE){
+        (*o_putc)(c1);
+        (*o_putc)(c2);
+    }else{
+        (*o_putc)(c2);
+        (*o_putc)(c1);
     }
 }
 
@@ -3537,7 +3630,7 @@ reinit()
     {
         struct input_code *p = input_code_list;
         while (p->name){
-            status_reset(p++);
+            status_reinit(p++);
         }
     }
 #ifdef UTF8_OUTPUT_ENABLE
@@ -3624,13 +3717,13 @@ void
 version()
 {
     fprintf(stderr,"Network Kanji Filter Version %s (%s) "
-#if defined(MSDOS) && !defined(_Windows)
+#if defined(MSDOS) && !defined(__WIN32__) && !defined(__WIN16__)
                   "for DOS"
 #endif
-#if !defined(__WIN32__) && defined(_Windows)
+#if defined(MSDOS) && defined(__WIN16__)
                   "for Win16"
 #endif
-#if defined(__WIN32__) && defined(_Windows)
+#if defined(MSDOS) && defined(__WIN32__)
                   "for Win32"
 #endif
 #ifdef __OS2__