home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libi18n / sjis2jis.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  7.6 KB  |  230 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. /*    sjis2jis.c    */
  19.  
  20. #include "intlpriv.h"
  21. #ifdef XP_MAC
  22. #include "katakana.h"
  23. #endif
  24.  
  25. extern int MK_OUT_OF_MEMORY;
  26.  
  27.  
  28.                                     /* SJIS to JIS Algorithm.        */
  29. #define TwoByteSJIS2JIS(sjisp, jisp, offset) {                    \
  30.      *jisp = (*sjisp++ - offset) << 1; /* assign 1st byte */        \
  31.      if (*sjisp < 0x9F) {            /* check 2nd SJIS byte */    \
  32.          *jisp++ -= 1;                /* adjust 1st JIS byte */    \
  33.          if (*sjisp > 0x7F)                                        \
  34.              *jisp++ = *sjisp++ - 0x20;                            \
  35.          else                                                    \
  36.              *jisp++ = *sjisp++ - 0x1F;                            \
  37.      } else {                                                    \
  38.          jisp++;                                                    \
  39.          *jisp++ = *sjisp++ - 0x7E;                                \
  40.      }                                                            \
  41. }
  42.                 
  43. /* net_sjis2jis(obj, sjisbuf, sjisbufsz)
  44.  * Args:
  45.  *    sjisbuf:    Ptr to a buf of SJIS chars
  46.  *    sjisbufsz:    Size in bytes of sjisbuf
  47.  *    jismode:    Ptr to encoding mode, use as arg for next call to
  48.  *        mz_sjis2jis() for rest of current SJIS data.  First call should
  49.  *        initialize mode to ASCII (0).                    
  50.  *    uncvtbuf:    If entire buffer was converted, uncvtbuf[0] will be null,
  51.  *        else this points to SJIS chars that were NOT converted
  52.  *        and mz_sjis2jis() with additional SJIS chars appended.
  53.  * Return:
  54.  *    Returns NULL on failure, otherwise it returns a pointer to a buffer of
  55.  *    converted SJIS characters.  Caller must XP_FREE() this memory.
  56.  *
  57.  * Description:
  58.  *     Allocate destination JIS buffer.
  59.  *
  60.  *     If the SJIS to JIS conversion changes JIS encoding, output proper ESC
  61.  *     sequence.
  62.  *
  63.  *     If byte in ASCII range, just copy it to JIS buffer.
  64.  *     If Half-width SJIS katakana (1 byte), convert to Half-width JIS katakana.
  65.  *    --- Now Half-width SJIS katakana is converted to 2-byte JIS katakana. ---
  66.  *     If 2-byte SJIS, convert to 2-byte JIS.
  67.  *     Otherwise assume user-defined SJIS, just copy 2 bytes.
  68.  *
  69.  *    If either SJIS buffer does not contain complete SJIS char or JIS buffer
  70.  *    is full, then return unconverted SJIS to caller.  Caller should
  71.  *    append more data and recall mz_sjis2jis.
  72.  */
  73.  
  74. MODULE_PRIVATE unsigned char *
  75. mz_sjis2jis(    CCCDataObject        obj,
  76.             const unsigned char    *sjisbuf,    /* SJIS buf for conversion    */
  77.             int32                sjisbufsz)    /* SJIS buf size in bytes    */
  78. {
  79.      unsigned char            *tobuf = NULL;
  80.      int32                    tobufsz;
  81.      register unsigned char    *sjisp, *tobufp;    /* current byte in bufs    */
  82.      register unsigned char    *sjisep, *toep;        /* end of buffers        */
  83.      int32                    uncvtlen;
  84.     unsigned char *uncvtbuf = INTL_GetCCCUncvtbuf(obj);
  85. #ifdef FEATURE_KATAKANA
  86.      unsigned char outbuf[2];                    /* for half-width kana */
  87.      uint32    byteused;                            /* for half-width kana */
  88. #endif
  89.     
  90.                                          /* Allocate a JIS buffer:            */
  91.         /* JIS is longer than SJIS because of ESC seq.  In the worst case
  92.          * ( alternating Half-width Kana and Roman chars ), converted
  93.          * JIS will be 4X the size of the original SJIS + 1 for nul byte.
  94.          * Worst case: single half-width kana:
  95.          *    ESC ( I KANA ESC ( J
  96.          */
  97.     uncvtlen = strlen((char *)uncvtbuf);
  98.     tobufsz = ((sjisbufsz + uncvtlen) << 2) + 8;
  99.     if ((tobuf = (unsigned char *)XP_ALLOC(tobufsz)) == (unsigned char *)NULL) {
  100.         INTL_SetCCCRetval(obj, MK_OUT_OF_MEMORY);
  101.         return(NULL);
  102.     }
  103.                                         /* Initialize pointers, etc.    */
  104.      sjisp = (unsigned char *)sjisbuf;
  105.      sjisep = sjisp + sjisbufsz - 1;
  106.  
  107. #define uncvtp    tobufp    /* use tobufp as temp */     
  108.                             /* If prev. unconverted chars, append unconverted
  109.                              * chars w/new chars and try to process.
  110.                              */
  111.      if (uncvtbuf[0] != '\0') {
  112.          uncvtp = uncvtbuf + uncvtlen;
  113.          while (uncvtp < (uncvtbuf + UNCVTBUF_SIZE) &&
  114.                                                     sjisp <= sjisep)
  115.              *uncvtp++ = *sjisp++;
  116.          *uncvtp = '\0';                        /* nul terminate    */
  117.          sjisp = uncvtbuf;                /* process unconverted first */
  118.          sjisep = uncvtp - 1;
  119.      }
  120. #undef uncvtp
  121.      
  122.      tobufp = tobuf;
  123.      toep = tobufp + tobufsz - 2;        /* save space for terminating null */
  124.      
  125. WHILELOOP:     
  126.                                     /* While SJIS data && space in JIS buf. */
  127.      while ((sjisp <= sjisep) && (tobufp <= toep)) {
  128.         if (*sjisp < 0x80) {
  129.                                          /* ASCII/JIS-Roman                 */
  130.              if (INTL_GetCCCJismode(obj) != JIS_Roman) {
  131.                  InsASCII_ESC(tobufp, obj);
  132.              }
  133.              *tobufp++ = *sjisp++;
  134.  
  135.          } else if (*sjisp < 0xA0) {
  136.                                          /* 1st byte of 2-byte low SJIS. */
  137.              if (sjisp+1 > sjisep)        /* No 2nd byte in SJIS buffer?    */
  138.                  break;
  139.  
  140.              if (INTL_GetCCCJismode(obj) != JIS_208_83) {
  141.                  Ins208_83_ESC(tobufp, obj);
  142.              }
  143.  
  144.              TwoByteSJIS2JIS(sjisp, tobufp, 0x70);
  145.  
  146.          } else if (*sjisp==0xA0) {
  147.                                         /* SJIS half-width space.    */
  148.                                         /* Just treat like Roman??    */
  149.              if (INTL_GetCCCJismode(obj) != JIS_Roman) {
  150.                  InsASCII_ESC(tobufp, obj);
  151.              }
  152.              *tobufp++ = *sjisp++;
  153.  
  154.          } else if (*sjisp < 0xE0) {
  155.                                         /* SJIS half-width katakana        */
  156. #ifdef FEATURE_KATAKANA
  157.              if (INTL_GetCCCJismode(obj) != JIS_208_83) {
  158.                  Ins208_83_ESC(tobufp, obj);
  159.              }
  160.             INTL_SjisHalf2FullKana(sjisp, (uint32)sjisep - (uint32)sjisp + 1, outbuf, &byteused);
  161.                                                         /* SJIS Katakana is 0x8340-0x8396 */
  162.              *tobufp++ = ((outbuf[0] - 0x70) << 1) - 1;    /* assign 1st byte */
  163.             if (outbuf[1] > 0x7F)                                        
  164.                 *tobufp++ = outbuf[1] - 0x20;
  165.             else                            
  166.                 *tobufp++ = outbuf[1] - 0x1F;
  167.             sjisp += byteused;
  168. #else
  169.              if (INTL_GetCCCJismode(obj) != JIS_HalfKana) {
  170.                  InsHalfKana_ESC(tobufp, obj);
  171.              }
  172.              *tobufp++ = *sjisp & 0x7F;
  173.             sjisp++;
  174. #endif
  175.          } else if (*sjisp < 0xF0) {
  176.                                         /* 1st byte of 2-byte high SJIS */
  177.              if (sjisp+1 > sjisep)        /* No 2nd byte in SJIS buffer? */
  178.                  break;
  179.  
  180.              if (INTL_GetCCCJismode(obj) != JIS_208_83) {
  181.                  Ins208_83_ESC(tobufp, obj);
  182.              }
  183.  
  184.              TwoByteSJIS2JIS(sjisp, tobufp, 0xB0);
  185.          } else {
  186.                                         /* User Defined SJIS: copy bytes */
  187.              if (sjisp+1 > sjisep)        /* No 2nd byte in SJIS buf?    */
  188.                  break;
  189.  
  190.              if (INTL_GetCCCJismode(obj) != JIS_208_83) {
  191.                  Ins208_83_ESC(tobufp, obj);
  192.              }
  193.  
  194.              *tobufp++ = *sjisp++;            /* Just copy 2 bytes.    */
  195.              *tobufp++ = *sjisp++;
  196.          }
  197.      }
  198.      
  199.      if (uncvtbuf[0] != '\0') {
  200.                                          /* tobufp pts to 1st unprocessed char in
  201.                                           * tobuf.  Some may have been processed
  202.                                           * while processing unconverted chars,
  203.                                           * so set up ptrs not to process them
  204.                                           * twice.
  205.                                           */
  206.          sjisp = (unsigned char *)sjisbuf + (sjisp - uncvtbuf - uncvtlen);
  207.                                             /* save space for term. null */
  208.          sjisep = (unsigned char *)sjisbuf + sjisbufsz - 1;
  209.          uncvtbuf[0] = '\0';        /* No more uncoverted chars.    */
  210.          goto WHILELOOP;                    /* Process new data                */
  211.      }
  212.  
  213.      if (INTL_GetCCCJismode(obj) != JIS_Roman) {
  214.          INTL_SetCCCJismode(obj, JIS_Roman);
  215.          InsASCII_ESC(tobufp, obj);
  216.     }
  217.  
  218.     *tobufp = '\0';                        /* null terminate JIS data */
  219.     INTL_SetCCCLen(obj,  tobufp - tobuf);            /* length not counting null    */
  220.  
  221.      if (sjisp <= sjisep) {                /* uncoverted SJIS?        */
  222.         tobufp = uncvtbuf;            /* reuse the tobufp as a TEMP */
  223.          while (sjisp <= sjisep)
  224.              *tobufp++ = *sjisp++;
  225.          *tobufp = '\0';                    /* null terminate        */
  226.      }
  227.     return(tobuf);
  228. }
  229.  
  230.