home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libi18n / jis2oth.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  9.3 KB  |  294 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. /*    jis2oth.c    */
  19. /*    other: SJIS or EUC */
  20.  
  21. #include "intlpriv.h"
  22.  
  23.  
  24. extern int MK_OUT_OF_MEMORY;
  25.  
  26.  
  27. /* net_jis2other(obj, jisbuf, jisbufsz, uncvtbuf)
  28.  * Args:
  29.  *    jisbuf:        Ptr to a buf of JIS chars
  30.  *    jisbufsz:    Size in bytes of jisbuf
  31.  *    jismode:    Ptr to encoding mode, use as arg for next call to
  32.  *        jis2other() for rest of current SJIS data.  First call should
  33.  *        initialize mode to ASCII (0).                    
  34.  *    uncvtbuf:    If entire buffer was converted, uncvtbuf[0] will be nul,
  35.  *        else this points to SJIS chars that were NOT converted
  36.  *        and jis2other() with additional SJIS chars appended.
  37.  *    obj->cvtflag:    Specifies converting to either EUC or SJIS.
  38.  * Return:
  39.  *    Returns NULL on failure, otherwise it returns a pointer to a buffer of
  40.  *    converted JIS characters.  Caller must XP_FREE() this memory.
  41.  *
  42.  * Description:
  43.  *
  44.  *    Allocate destination buffer (for SJIS or EUC).
  45.  *
  46.  *    Set JIS mode state based upon ESC sequences.  Also if NL or CR,
  47.  *    mode is reset to JIS-Roman.
  48.  *
  49.  *  If JIS mode is JIS x208 and converting to EUC, set 8th bits of next 2 bytes.
  50.  *
  51.  *  If JIS mode is JIS x208-1983 and converting to SJIS, use the
  52.  *    JIS to SJIS algorithm.
  53.  *
  54.  *  If JIS mode is JIS x212 and converting to EUC, output SS3 and set 8th
  55.  *    bits of next 2 bytes.  (This mode only set when converting to EUC.)
  56.  *
  57.  *    If JIS Half-width Katakana and converting to EUC, output SS2 followed
  58.  *    by the 2 bytes w/8th bits set.
  59.  *
  60.  *    If JIS Half-width Katakana and converting to SJIS, output the 2 bytes
  61.  *    w/8th bits set.
  62.  *
  63.  *    If any other JIS mode, then assume Latin1 and just copy the next byte.
  64.  *
  65.  *    If either SJIS buffer does not contain complete JIS char or JIS buffer
  66.  *    is full, then return unconverted SJIS to caller.  Caller should
  67.  *    append more data and recall jis2other.
  68.  */
  69.  
  70.  
  71. MODULE_PRIVATE unsigned char *
  72. jis2other(    CCCDataObject        obj,
  73.             const unsigned char    *jisbuf,    /* JIS buffer for conversion*/
  74.             int32                jisbufsz)    /* JIS buffer size in bytes    */
  75. {
  76.      unsigned char            *tobuf = NULL;
  77.      int32                    tobufsz;
  78.      unsigned char    *tobufp, *jisp;        /* current byte in bufs    */
  79.      unsigned char    *tobufep, *jisep;    /* end of buffers        */
  80.      int32                    uncvtlen;
  81.     unsigned char *uncvtbuf = INTL_GetCCCUncvtbuf(obj);
  82.  
  83. #define sjisbuf        tobuf
  84. #define sjisbufsz    tobufsz
  85. #define sjisp        tobufp
  86. #define sjisep        tobufep
  87.  
  88. #define eucbufsz    tobufsz
  89. #define eucbuf        tobuf
  90. #define eucp        tobufp
  91. #define eucep        tobufep
  92.                                          /* Allocate a dest buffer:        */
  93.         /* JIS is usually longer than SJIS or EUC because of ESC seq.
  94.          *
  95.          * In the worst case (all Roman), converted SJIS will be the same
  96.          * length as the original JIS + 1 for nul byte
  97.          *
  98.          * In the worst case ( <ESC> ( I <rest Half-width Kana>... ),
  99.          * converted EUC will be 2X - 2 the size of the original JIS + 1 for nul
  100.          * byte.
  101.          */
  102.     uncvtlen = strlen((char *)uncvtbuf);
  103.     if (!INTL_GetCCCCvtflag(obj))
  104.         tobufsz = jisbufsz + uncvtlen + 1;
  105.     else
  106.         tobufsz = (jisbufsz + uncvtlen) << 1;
  107.  
  108.     if (!tobufsz) {
  109.         return NULL;
  110.     }
  111.  
  112.     if ((tobuf = (unsigned char *)XP_ALLOC(tobufsz)) == (unsigned char *)NULL) {
  113.         INTL_SetCCCRetval(obj, MK_OUT_OF_MEMORY);
  114.         return(NULL);
  115.     }
  116.                                         /* Initialize pointers, etc.    */
  117.      jisp = (unsigned char *)jisbuf;
  118.      jisep = jisp + jisbufsz - 1;
  119.  
  120. #define uncvtp    tobufp    /* use tobufp as temp */                  
  121.                             /* If prev. unconverted chars, append unconverted
  122.                              * chars w/new chars and try to process.
  123.                              */
  124.      if (uncvtbuf[0] != '\0') {
  125.          uncvtp = uncvtbuf + uncvtlen;
  126.          while (uncvtp < (uncvtbuf + UNCVTBUF_SIZE) &&
  127.                                                         jisp <= jisep)
  128.              *uncvtp++ = *jisp++;
  129.          *uncvtp = '\0';                        /* nul terminate    */
  130.          jisp = uncvtbuf;                /* process unconverted first */
  131.          jisep = uncvtp - 1;
  132.      }
  133. #undef uncvtp
  134.      
  135.      tobufp = tobuf;
  136.      tobufep = tobufp + tobufsz - 2;        /* save space for terminating null */
  137.      
  138. WHILELOOP:     
  139.                                     /* While JIS data && space in SJIS buf. */
  140.      while ((tobufp <= tobufep) && (jisp <= jisep)) {
  141.         if (*jisp == ESC) {
  142.              if ((jisep - jisp) < 2)    /* Incomplete ESC seq in JIS buf?        */
  143.                  break;
  144.             switch (jisp[1]) {
  145.                 case '(':
  146.                     switch (jisp[2]) {
  147.                         case 'J':                /* JIS X 0201-Roman            */
  148.                         case 'B':                /* ASCII    */
  149.                             INTL_SetCCCJismode(obj, JIS_Roman);
  150.                             jisp += 3;            /* remove ESC seq.    */
  151.                             break;
  152.                         case 'I':                /* Half-width katakana    */
  153.                             INTL_SetCCCJismode(obj, JIS_HalfKana);
  154.                             jisp += 3;            /* remove ESC seq.    */
  155.                             break;
  156.                         default:                /* pass thru invalid ESC seq. */
  157.                             *tobufp++ = *jisp++;
  158.                             *tobufp++ = *jisp++;
  159.                     }
  160.                     break;
  161.                 case DOLLAR:
  162.                     switch (jisp[2]) {
  163.                            case 'B':                /* JIS X 0208-1983    */
  164.                         case '@':                /* JIS X 0208-1978 (old-JIS) */
  165.                             INTL_SetCCCJismode(obj, JIS_208_83);
  166.                             jisp += 3;            /* remove rest of ESC seq.    */
  167.                             break;
  168.                         case '(':
  169.                              if ((jisep - jisp) < 3)    /* Full ESC seq in buf? */
  170.                                  goto abortwhile;
  171.                             switch (jisp[3]) {
  172.                                 case 'D':            /* JIS X 0212-1990    */
  173.                                     if (!INTL_GetCCCCvtflag(obj))    /* No JIS212 in SJIS */
  174.                                         INTL_SetCCCJismode(obj, JIS_208_83);
  175.                                     else
  176.                                         INTL_SetCCCJismode(obj, JIS_212_90);
  177.                                     jisp += 4;    /* remove rest of ESC seq.    */
  178.                                     break;
  179.                                 default:        /* pass thru invalid ESC seq. */
  180.                                     *tobufp++ = *jisp++;
  181.                                     *tobufp++ = *jisp++;
  182.                                     break;
  183.                             }
  184.                             break;
  185.                         default:                /* pass thru invalid ESC seq. */
  186.                             *tobufp++ = *jisp++;
  187.                             *tobufp++ = *jisp++;
  188.                     }
  189.                     break;
  190.                 case '-':
  191.                     switch (jisp[2]) {
  192.                         case 'A':                /* ISO8859-1            */
  193.                             INTL_SetCCCJismode(obj, JIS_Roman);
  194.                             jisp += 3;            /* remove rest of ESC seq.    */
  195.                             break;
  196.                         default:                /* pass thru invalid ESC seq. */
  197.                             *tobufp++ = *jisp++;
  198.                             *tobufp++ = *jisp++;
  199.                     }
  200.                     break;
  201.                 default:                        /* pass thru invalid ESC seq. */
  202.                     *tobufp++ = *jisp++;
  203.             }
  204.         } else if (*jisp == NL || *jisp == CR) {
  205.             INTL_SetCCCJismode(obj, JIS_Roman);
  206.             *tobufp++ = *jisp++;
  207.         } else if (INTL_GetCCCJismode(obj) == JIS_208_83) {
  208.              if ((jisp+1) > jisep)        /* Incomplete 2Byte char in JIS buf? */
  209.                  break;
  210.  
  211.             if (INTL_GetCCCCvtflag(obj)) {                /* Convert JIS 208 to EUC        */
  212.                 *eucp++ = *jisp | 0x80;
  213.                 jisp++;
  214.                 *eucp++ = *jisp | 0x80;
  215.                 jisp++;
  216.  
  217.             } else {                /* Convert JIS-208 to SJIS:     Same as    */
  218.                                     /* euc2sjis.c's EUC208-to-SJIS algorithm */
  219.                                     /* except JIS 8th bit is clear. */
  220.                 if (*jisp < 0x5F)            /* Convert 1st SJIS byte    */
  221.                     *sjisp++ = ((*jisp + 1) >> 1) + 0x70;
  222.                 else
  223.                     *sjisp++ = ((*jisp + 1) >> 1) + 0xB0;
  224.                                             /* Convert 2nd SJIS byte    */
  225.  
  226.                 if ((*jisp++) & 1) {        /* if 1st JIS byte is odd    */
  227.                     if (*jisp > 0x5F)
  228.                         *sjisp = *jisp + 0x20;
  229.                     else
  230.                         *sjisp = *jisp + 0x1F;
  231.                 } else {
  232.                     *sjisp = *jisp + 0x7E;
  233.                 }
  234.                 sjisp++;
  235.                 jisp++;
  236.             }
  237.         } else if (INTL_GetCCCJismode(obj) == JIS_212_90) {
  238.                                         /* only "to EUC" supports 212    */
  239.              if ((jisp+1) > jisep)        /* Incomplete 2Byte char in JIS buf? */
  240.                  break;
  241.             *eucp++ = SS3;
  242.             *eucp++ = *jisp | 0x80;
  243.             jisp++;
  244.             *eucp++ = *jisp | 0x80;
  245.             jisp++;
  246.         } else if (INTL_GetCCCJismode(obj) == JIS_HalfKana) {
  247.                 if (INTL_GetCCCCvtflag(obj)) {
  248.                     *eucp++ = SS2;
  249.                 }
  250.                 *tobufp++ = *jisp | 0x80;        /* Set 8th bit for EUC & SJIS */
  251.                 jisp++;
  252.         } else {
  253.                                             /* Unknown type: no conversion    */
  254.             *tobufp++ = *jisp++;
  255.         }
  256.     }
  257. abortwhile:
  258.     
  259.      if (uncvtbuf[0] != '\0') {
  260.                                         /* Just processed unconverted chars:
  261.                                          * jisp pts to 1st unprocessed char in
  262.                                           * jisbuf.  Some may have been processed
  263.                                           * while processing unconverted chars,
  264.                                           * so set up ptrs not to process them
  265.                                           * twice.
  266.                                           */
  267.                                         /* If nothing was converted, this can
  268.                                          * only happen if there was not
  269.                                          * enough JIS data.  Stop and get
  270.                                          * more data.
  271.                                          */
  272.         if (jisp == uncvtbuf) {    /* Nothing converted */
  273.             *tobufp = '\0';
  274.             return(NULL);
  275.         }
  276.          jisep = (unsigned char *)jisbuf + jisbufsz - 1 ;
  277.          jisp = (unsigned char *)jisbuf + (jisp - uncvtbuf - uncvtlen);
  278.          uncvtbuf[0] = '\0';            /* No more uncoverted chars.    */
  279.          goto WHILELOOP;                    /* Process new data                */
  280.      }
  281.  
  282.     *tobufp = '\0';                        /* null terminate dest. data */
  283.     INTL_SetCCCLen(obj,  tobufp - tobuf);            /* length not counting null    */
  284.  
  285.      if (jisp <= jisep) {                /* uncoverted JIS?        */
  286.         tobufp = uncvtbuf;                /* reuse the tobufp as a TEMP */
  287.          while (jisp <= jisep)
  288.              *tobufp++ = *jisp++;
  289.          *tobufp = '\0';                    /* null terminate        */
  290.      }
  291.     return(tobuf);
  292. }
  293.                 
  294.