home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libi18n / euc2sjis.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  6.7 KB  |  194 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. /*    euc2sjis.c    */
  19.  
  20. #include "intlpriv.h"
  21.  
  22.  
  23. extern int MK_OUT_OF_MEMORY;
  24.  
  25.  
  26. /* net_euc2sjis(obj, eucbuf, eucbufsz)
  27.  * Args:
  28.  *    eucbuf:        Ptr to a buf of EUC chars
  29.  *    eucbufsz:    Size in bytes of eucbuf
  30.  *    uncvtbuf:    If entire buffer was converted, uncvtbuf[0] will be nul,
  31.  *        else this points to EUC chars that were NOT converted
  32.  *        and mz_euc2sjis() with additional EUC chars appended.
  33.  * Return:
  34.  *    Returns NULL on failure, otherwise it returns a pointer to a buffer of
  35.  *    converted characters.  Caller must XP_FREE() this memory.
  36.  *
  37.  * Description:
  38.  *
  39.  *    Allocate destination buffer.
  40.  *
  41.  *  All bytes < SS2 (0x8E) are either ASCII/Roman or invalid.  Treat them
  42.  *    as ASCII/Roman and just copy them unchanged.
  43.  *
  44.  *    If SS2, then the next byte should be a Half-width Katakana, just copy
  45.  *    it unchanged after disposing of the SS2 byte.
  46.  *
  47.  *    If SS3, then the next 2 bytes should be JIS x212.  If the bytes
  48.  *    are not in the valide range for JIS x212, then copy the SS3 and
  49.  *    continue.  Leave the 2 byte to be processed from the beginning.
  50.  *
  51.  *    If the next byte < 0xA0, this is not valid EUC, so treat it as
  52.  *    ASCII/Roman and just copy it unchanged.
  53.  *
  54.  *    If the next 2 bytes are both >= 0xA0, then this is a valid 2-byte
  55.  *    x208, so convert them to SJIS.  Otherwise, copy the 1st byte and
  56.  *    continue.
  57.  */
  58.  
  59.  
  60. MODULE_PRIVATE unsigned char *
  61. mz_euc2sjis(    CCCDataObject        obj,
  62.             const unsigned char    *eucbuf,    /* EUC buffer for conversion    */
  63.             int32                eucbufsz)    /* EUC buffer size in bytes        */
  64. {
  65.      char unsigned            *tobuf = NULL;
  66.      int32                    tobufsz;
  67.      register unsigned char    *tobufp, *eucp;        /* current byte in bufs    */
  68.      register unsigned char    *tobufep, *eucep;    /* end of buffers        */
  69.      int32                    uncvtlen;
  70.     unsigned char *uncvtbuf = INTL_GetCCCUncvtbuf(obj);
  71.  
  72.                                          /* Allocate a dest buffer:        */
  73.         /* Usually EUC will be the same length as SJIS.  SJIS will be shorter
  74.          * if Half-width Kana are used, but in the worst case, the converted
  75.          * SJIS will be the same size as the orignal EUC + 1 for nul byte.
  76.          */
  77.     uncvtlen = strlen((char *)uncvtbuf);
  78.     tobufsz = eucbufsz + uncvtlen + 1;
  79.     if ((tobuf = (unsigned char *)XP_ALLOC(tobufsz)) == (unsigned char *)NULL) {
  80.         INTL_SetCCCRetval(obj, MK_OUT_OF_MEMORY);
  81.         return(NULL);
  82.     }
  83.                                         /* Initialize pointers, etc.    */
  84.      eucp = (unsigned char *)eucbuf;
  85.      eucep = eucp + eucbufsz - 1;
  86.      
  87. #define uncvtp    tobufp    /* use tobufp as temp */                  
  88.                             /* If prev. unconverted chars, append unconverted
  89.                              * chars w/new chars and try to process.
  90.                              */
  91.      if (uncvtbuf[0] != '\0') {
  92.          uncvtp = uncvtbuf + uncvtlen;
  93.          while (uncvtp < (uncvtbuf + UNCVTBUF_SIZE) &&
  94.                                                         eucp <= eucep)
  95.              *uncvtp++ = *eucp++;
  96.          *uncvtp = '\0';                            /* nul terminate    */
  97.          eucp = uncvtbuf;                    /* process unconverted first */
  98.          eucep = uncvtp - 1;
  99.      }
  100. #undef uncvtp
  101.  
  102.      tobufp = tobuf;
  103.      tobufep = tobufp + tobufsz - 2;        /* save space for terminating null */
  104.  
  105. WHILELOOP:
  106.                                     /* While EUC data && space in dest. buf. */
  107.      while ((tobufp <= tobufep) && (eucp <= eucep)) {
  108.         if (*eucp < SS2) {                /* ASCII/JIS-Roman/invalid EUC    */
  109.              *tobufp++ = *eucp++;
  110.         } else if (*eucp == SS2) {        /* Half-width katakana        */
  111.              if (eucp+1 > eucep)            /* No 2nd byte in EUC buffer?    */
  112.                  break;
  113.             eucp++;                        /* Dispose of SS2            */
  114.              *tobufp++ = *eucp++;
  115.  
  116.         } else if (*eucp == SS3) {        /* JIS X 0212-1990                */
  117.              if (eucp+2 > eucep)            /* No 2nd & 3rd bytes in EUC buffer? */
  118.                  break;
  119.             if (*eucp < 0xA0 || *(eucp+1) < 0xA0) {    /* Invalid EUC212    */
  120.                 *tobufp++ = *eucp++;            /* process SS3 only        */
  121.              } else {
  122.                  *tobufp++ = *eucp++;        /* SS3                        */
  123.                  *tobufp++ = *eucp++;        /* 1st 212 byte unconverted    */
  124.                  *tobufp++ = *eucp++;        /* 2nd 212 byte unconverted    */
  125.             }
  126.         } else if (*eucp < 0xA0) {        /* Invalid EUC: treat as Roman    */
  127.              *tobufp++ = *eucp++;
  128.         } else {                        /* JIS X 0208                    */
  129.              if (eucp+1 > eucep)            /* No 2nd byte in EUC buffer?    */
  130.                  break;
  131.             if (*(eucp+1) < 0xA0) {        /* 1st byte OK, check if 2nd is valid */
  132.                 *tobufp++ = *eucp++;        /* process 1 byte as Roman    */
  133.  
  134.             } else {                /* Convert EUC-208 to SJIS:     Same as    */
  135.                                     /* jis2other.c's JIS208-to-SJIS algorithm */
  136.                                     /* except JIS 8th bit is set. */
  137.                 unsigned char b;
  138.                 b = ((*eucp) & 0x7F);        /* Convert 1st EUC byte to JIS    */
  139.                 if (b < 0x5F)                /* Convert it to SJIS byte    */
  140.                     *tobufp++ = ((b + 1) >> 1) + 0x70;
  141.                 else
  142.                     *tobufp++ = ((b + 1) >> 1) + 0xB0;
  143.                                             /* Convert 2nd SJIS byte    */
  144.                 if ((*eucp++) & 1) {        /* if 1st JIS byte is odd    */
  145.                     b = ((*eucp) & 0x7F);    /* convert 2nd EUC byte to JIS    */
  146.                     if (b > 0x5F)
  147.                         *tobufp = b + 0x20;
  148.                     else
  149.                         *tobufp = b + 0x1F;
  150.                 } else {
  151.                     *tobufp = (*eucp & 0x7F) + 0x7E;
  152.                 }
  153.                 tobufp++;
  154.                 eucp++;
  155.             }
  156.         }
  157.     }
  158.     
  159.      if (uncvtbuf[0] != '\0') {
  160.                                         /* Just processed unconverted chars:
  161.                                           * eucp pts to 1st unprocessed char in
  162.                                           * eucbuf.  Some may have been processed
  163.                                           * while processing unconverted chars,
  164.                                           * so set up ptrs not to process them
  165.                                           * twice.
  166.                                           */
  167.                                         /* If nothing was converted, this can
  168.                                          * only happen if there was not
  169.                                          * enough EUC data.  Stop and get
  170.                                          * more data.
  171.                                          */
  172.         if (eucp == uncvtbuf) {    /* Nothing converted */
  173.             *tobufp = '\0';
  174.             return(NULL);
  175.         }
  176.          eucp = (unsigned char *)eucbuf + (eucp - uncvtbuf - uncvtlen);
  177.          eucep = (unsigned char *)eucbuf + eucbufsz - 1;    /* save space for nul */
  178.          uncvtbuf[0] = '\0';         /* No more uncoverted chars.    */
  179.          goto WHILELOOP;                    /* Process new data                */
  180.      }
  181.  
  182.     *tobufp =  '\0';                        /* null terminate dest. data */
  183.     INTL_SetCCCLen(obj,  tobufp - tobuf);            /* length not counting null    */
  184.  
  185.      if (eucp <= eucep) {                /* uncoverted EUC?        */
  186.         tobufp = uncvtbuf;            /* reuse the tobufp as a TEMP */
  187.          while (eucp <= eucep)
  188.              *tobufp++ = *eucp++;
  189.          *tobufp = '\0';                    /* null terminate        */
  190.      }
  191.     return(tobuf);
  192. }
  193.                 
  194.