home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libi18n / euc2jis.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  8.1 KB  |  239 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /*    euc2jis.c    */
  19.  
  20. #include "intlpriv.h"
  21. #ifdef XP_MAC
  22. #include "katakana.h"
  23. #endif
  24.  
  25.  
  26. extern int MK_OUT_OF_MEMORY;
  27.  
  28.  
  29. /* net_euc2jis(obj, eucbuf, eucbufsz)
  30.  * Args:
  31.  *    eucbuf:        Ptr to a buf of EUC chars
  32.  *    eucbufsz:    Size in bytes of eucbuf
  33.  *    obj->eucmode:    Ptr to encoding mode, use as arg for next call to
  34.  *        mz_euc2jis() for rest of current EUC data.  First call should
  35.  *        initialize mode to ASCII (0).                    
  36.  *    uncvtbuf:    If entire buffer was converted, uncvtbuf[0] will be nul,
  37.  *        else this points to EUC chars that were NOT converted
  38.  *        and mz_euc2jis() with additional EUC chars appended.
  39.  * Return:
  40.  *    Returns NULL on failure, otherwise it returns a pointer to a buffer of
  41.  *    converted characters.  Caller must XP_FREE() this memory.
  42.  *
  43.  * Description:
  44.  *
  45.  *    Allocate destination buffer.
  46.  *
  47.  *    Ouput JIS ESC sequences based upon which EUC code set.
  48.  *
  49.  *  No conversion is needed for ASCII/JIS Roman characters.
  50.  *
  51.  *    Clear 8th bit of 1-byte Half-width Katakana.  Half-width Katakana
  52.  *  is not widely used and its ESC sequence may not be recognized
  53.  *  by some software.  It's use on the internet is discouraged...
  54.  *
  55.  *    Clear 8th bits of 2-byte JIS X 212-1990 chars.  JIS-212
  56.  *  is not widely used and its ESC sequence may not be recognized
  57.  *  by some software.  These chars do not have corresponding chars
  58.  *    in JIS-208 or SJIS.
  59.  *
  60.  *    Clear 8th bits of 2-byte JIS X 208-1993 chars.  These are the commonly
  61.  *    used chars (along with JIS-Roman).
  62.  *
  63.  *    Bytes which do not fall in the EUC valid character codes are treated
  64.  *    like JIS-Roman.
  65.  *
  66.  *    If either EUC buffer does not contain a complete EUC char or dest buffer
  67.  *    is full, then return unconverted EUC to caller.  Caller should
  68.  *    append more data and recall mz_euc2jis.
  69.  */
  70.  
  71.  
  72. MODULE_PRIVATE unsigned char *
  73. mz_euc2jis(    CCCDataObject        obj,
  74.             const unsigned char    *eucbuf,    /* EUC buffer for conversion    */
  75.             int32                eucbufsz)    /* EUC buffer size in bytes        */
  76. {
  77.      unsigned char            *tobuf = NULL;
  78.      int32                    tobufsz;
  79.      register unsigned char    *tobufp, *eucp;        /* current byte in bufs    */
  80.      register unsigned char    *tobufep, *eucep;    /* end of buffers        */
  81.      int32                    uncvtlen;
  82.     unsigned char *uncvtbuf = INTL_GetCCCUncvtbuf(obj);
  83. #ifdef FEATURE_KATAKANA
  84.      unsigned char outbuf[2];                /* for 1 byte katakana */
  85.      uint32 byteused;                        /* for 1 byte katakana */
  86. #endif
  87.  
  88.                                          /* Allocate a dest buffer:        */
  89.         /* JIS is longer than EUC because of ESC seq.  In the worst case
  90.          * ( <SS2> <Half-width Kana> <Roman> ... ), the converted JIS will
  91.          * be 2-2/3 times the size of the original EUC + 1 for nul byte.
  92.          * Worst case: single half-width kana:
  93.          *    ESC ( I KANA ESC ( J
  94.          */
  95.     uncvtlen = strlen((const char *)uncvtbuf);
  96.                                         /* 3 times length of EUC    */
  97.     tobufsz = eucbufsz + uncvtlen + ((eucbufsz + uncvtlen)<<2) + 8;
  98.     if ((tobuf = (unsigned char *)XP_ALLOC(tobufsz)) == (unsigned char *)NULL) {
  99.         INTL_SetCCCRetval(obj, MK_OUT_OF_MEMORY);
  100.         return(NULL);
  101.     }
  102.                                         /* Initialize pointers, etc.    */
  103.      eucp = (unsigned char *)eucbuf;
  104.      eucep = eucp + eucbufsz - 1;
  105.  
  106. #define uncvtp    tobufp    /* use tobufp as temp */                  
  107.                             /* If prev. unconverted chars, append unconverted
  108.                              * chars w/new chars and try to process.
  109.                              */
  110.      if (uncvtbuf[0] != '\0') {
  111.          uncvtp = (unsigned char *)uncvtbuf + uncvtlen;
  112.          while (uncvtp < ((unsigned char *)uncvtbuf + UNCVTBUF_SIZE) &&
  113.                                                         eucp <= eucep)
  114.              *uncvtp++ = *eucp++;
  115.          *uncvtp = '\0';                        /* nul terminate    */
  116.          eucp = (unsigned char *)uncvtbuf; /* process unconverted first */
  117.          eucep = uncvtp - 1;
  118.      }
  119. #undef uncvtp
  120.      
  121.      tobufp = tobuf;
  122.      tobufep = tobufp + tobufsz - 2;        /* save space for terminating null */
  123.      
  124. WHILELOOP:     
  125.                                     /* While EUC data && space in dest. buf. */
  126.      while ((tobufp <= tobufep) && (eucp <= eucep)) {
  127.         if (*eucp < SS2) {                /* ASCII/JIS-Roman or invalid EUC    */
  128.              if (INTL_GetCCCJismode(obj) != JIS_Roman) {
  129.                  InsASCII_ESC(tobufp, obj);
  130.              }
  131.              *tobufp++ = *eucp++;
  132.         } else if (*eucp == SS2) {        /* Half-width Katakana            */
  133. #ifdef FEATURE_KATAKANA
  134.              if (eucp+1 > eucep)            /* No 2nd byte in EUC buffer?    */
  135.                  break;
  136.              if (INTL_GetCCCJismode(obj) != JIS_208_83) {
  137.                  Ins208_83_ESC(tobufp, obj);
  138.              }
  139.             eucp++;                            /* skip SS2    */
  140.             INTL_EucHalf2FullKana(eucp, (uint32)eucep - (uint32)eucp + 1, outbuf, &byteused);
  141.             *tobufp++ = outbuf[0] & 0x7F;
  142.             *tobufp++ = outbuf[1] & 0x7F;
  143.             eucp += byteused;
  144. #else
  145.              if (eucp+1 > eucep)            /* No 2nd byte in EUC buffer?    */
  146.                  break;
  147.              if (INTL_GetCCCJismode(obj) != JIS_HalfKana) {
  148.                  InsHalfKana_ESC(tobufp, obj);
  149.              }
  150.             eucp++;                            /* skip SS2    */
  151.              *tobufp++ = *eucp & 0x7F;
  152.             eucp++;
  153. #endif
  154.  
  155.         } else if (*eucp == SS3) {        /* JIS X 0212-1990                */
  156.              if (eucp+2 > eucep)            /* No 2nd & 3rd bytes in EUC buffer? */
  157.                  break;
  158.             if (*(eucp+1) <= 0xA0 || *(eucp+2) <= 0xA0) { /* Invalid EUC212    */
  159.                  if (INTL_GetCCCJismode(obj) != JIS_Roman) {
  160.                      InsASCII_ESC(tobufp, obj);
  161.                 }
  162.                 *tobufp++ = *eucp++;            /* process 1 byte as Roman */
  163.              } else {
  164.                  if (INTL_GetCCCJismode(obj) != JIS_212_90) {
  165.                     Ins212_90_ESC(tobufp, obj);
  166.                  }
  167.                 eucp++;                            /* skip SS3    */
  168.                  *tobufp++ = *eucp & 0x7F;
  169.                 eucp++;
  170.                  *tobufp++ = *eucp & 0x7F;
  171.                 eucp++;
  172.             }
  173.         } else if (*eucp < 0xA0) {        /* Invalid EUC: treat as Roman    */
  174.              if (INTL_GetCCCJismode(obj) != JIS_Roman) {
  175.                  InsASCII_ESC(tobufp, obj);
  176.              }
  177.              *tobufp++ = *eucp++;
  178.         } else {                        /* JIS X 0208-1990                */
  179.              if (eucp+1 > eucep)            /* No 2nd byte in EUC buffer?    */
  180.                  break;
  181.             if (*(eucp+1) < 0xA0) {        /* 1st byte OK, check if 2nd is valid */
  182.                  if (INTL_GetCCCJismode(obj) != JIS_Roman) {
  183.                      InsASCII_ESC(tobufp, obj);
  184.                 }
  185.                 *tobufp++ = *eucp++;            /* process 1 byte as Roman    */
  186.              } else {
  187.                  if (INTL_GetCCCJismode(obj) != JIS_208_83) {
  188.                      Ins208_83_ESC(tobufp, obj);
  189.                  }
  190.                  *tobufp++ = *eucp & 0x7F;
  191.                 eucp++;
  192.                  *tobufp++ = *eucp & 0x7F;
  193.                 eucp++;
  194.             }
  195.         }
  196.     }
  197.     
  198.      if (uncvtbuf[0] != '\0') {
  199.                                         /* Just processed unconverted chars:
  200.                                          * eucp pts to 1st unprocessed char in
  201.                                           * eucbuf.  Some may have been processed
  202.                                           * while processing unconverted chars,
  203.                                           * so set up ptrs not to process them
  204.                                           * twice.
  205.                                           */
  206.                                         /* If nothing was converted, this can
  207.                                          * only happen if there was not
  208.                                          * enough EUC data.  Stop and get
  209.                                          * more data.
  210.                                          */
  211.         if (eucp == (unsigned char *)uncvtbuf) {    /* Nothing converted */
  212.             *tobufp = '\0';
  213.             return(NULL);
  214.         }
  215.          eucp = (unsigned char *)eucbuf +
  216.                              (eucp - (unsigned char *)uncvtbuf - uncvtlen);
  217.          eucep = (unsigned char *)eucbuf + eucbufsz - 1;    /* save space for nul */
  218.          uncvtbuf[0] = '\0';        /* No more uncoverted chars.    */
  219.          goto WHILELOOP;                    /* Process new data                */
  220.      }
  221.      
  222.      if (INTL_GetCCCJismode(obj) != JIS_Roman) {
  223.          INTL_SetCCCJismode(obj, JIS_Roman);
  224.          InsASCII_ESC(tobufp, obj);
  225.     }
  226.  
  227.     *tobufp = '\0';                        /* null terminate dest. data */
  228.     INTL_SetCCCLen(obj,  tobufp - tobuf);            /* length not counting null    */
  229.  
  230.      if (eucp <= eucep) {                /* uncoverted EUC?            */
  231.         tobufp = (unsigned char *)uncvtbuf;/* reuse the tobufp as a TEMP */
  232.          while (eucp <= eucep)
  233.              *tobufp++ = *eucp++;
  234.          *tobufp = '\0';                    /* null terminate            */
  235.      }
  236.     return(tobuf);
  237. }
  238.                 
  239.