michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsUnicodeToISO2022JP.h" michael@0: #include "nsUCVJADll.h" michael@0: #include "nsUnicodeEncodeHelper.h" michael@0: michael@0: //---------------------------------------------------------------------- michael@0: // Global functions and data [declaration] michael@0: michael@0: // Basic mapping from Hankaku to Zenkaku michael@0: // Nigori and Maru are taken care of outside this basic mapping michael@0: static const char16_t gBasicMapping[0x40] = michael@0: { michael@0: // 0xff60 michael@0: 0xff60,0x3002,0x300c,0x300d,0x3001,0x30fb,0x30f2,0x30a1, michael@0: // 0xff68 michael@0: 0x30a3,0x30a5,0x30a7,0x30a9,0x30e3,0x30e5,0x30e7,0x30c3, michael@0: // 0xff70 michael@0: 0x30fc,0x30a2,0x30a4,0x30a6,0x30a8,0x30aa,0x30ab,0x30ad, michael@0: // 0xff78 michael@0: 0x30af,0x30b1,0x30b3,0x30b5,0x30b7,0x30b9,0x30bb,0x30bd, michael@0: // 0xff80 michael@0: 0x30bf,0x30c1,0x30c4,0x30c6,0x30c8,0x30ca,0x30cb,0x30cc, michael@0: // 0xff88 michael@0: 0x30cd,0x30ce,0x30cf,0x30d2,0x30d5,0x30d8,0x30db,0x30de, michael@0: // 0xff90 michael@0: 0x30df,0x30e0,0x30e1,0x30e2,0x30e4,0x30e6,0x30e8,0x30e9, michael@0: // 0xff98 michael@0: 0x30ea,0x30eb,0x30ec,0x30ed,0x30ef,0x30f3,0x309b,0x309c michael@0: }; michael@0: michael@0: // Do we need to check for Nigori for the next unicode ? michael@0: #define NEED_TO_CHECK_NIGORI(u) (((0xff76<=(u))&&((u)<=0xff84))||((0xff8a<=(u))&&((u)<=0xff8e))) michael@0: michael@0: // Do we need to check for Maru for the next unicode ? michael@0: #define NEED_TO_CHECK_MARU(u) ((0xff8a<=(u))&&((u)<=0xff8e)) michael@0: michael@0: // The unicode is in Katakana Hankaku block michael@0: #define IS_HANKAKU(u) ((0xff61 <= (u)) && ((u) <= 0xff9f)) michael@0: #define IS_NIGORI(u) (0xff9e == (u)) michael@0: #define IS_MARU(u) (0xff9f == (u)) michael@0: #define NIGORI_MODIFIER 1 michael@0: #define MARU_MODIFIER 2 michael@0: michael@0: static const uint16_t g_ufAsciiMapping [] = { michael@0: 0x0001, 0x0004, 0x0005, 0x0008, 0x0000, 0x0000, 0x007F, 0x0000 michael@0: }; michael@0: michael@0: #define SIZE_OF_ISO2022JP_TABLES 5 michael@0: static const uint16_t * g_ufMappingTables[SIZE_OF_ISO2022JP_TABLES] = { michael@0: g_ufAsciiMapping, // ASCII ISOREG 6 michael@0: g_uf0201GLMapping, // JIS X 0201-1976 ISOREG 14 michael@0: g_uf0208Mapping, // JIS X 0208-1983 ISOREG 87 michael@0: g_uf0208extMapping, // JIS X 0208 - cp932 ext michael@0: g_uf0208Mapping, // JIS X 0208-1978 ISOREG 42 michael@0: }; michael@0: michael@0: static const uScanClassID g_ufScanClassIDs[SIZE_OF_ISO2022JP_TABLES] = { michael@0: u1ByteCharset, // ASCII ISOREG 6 michael@0: u1ByteCharset, // JIS X 0201-1976 ISOREG 14 michael@0: u2BytesCharset, // JIS X 0208-1983 ISOREG 87 michael@0: u2BytesCharset, // JIS X 0208- cp932 ext michael@0: u2BytesCharset, // JIS X 0208-1978 ISOREG 42 michael@0: }; michael@0: #define JIS_X_208_INDEX 2 michael@0: michael@0: //---------------------------------------------------------------------- michael@0: // Class nsUnicodeToISO2022JP [implementation] michael@0: michael@0: // worst case max length: michael@0: // 1 2 3 4 5 6 7 8 michael@0: // ESC $ B XX XX ESC ( B michael@0: nsUnicodeToISO2022JP::nsUnicodeToISO2022JP() michael@0: : nsEncoderSupport(8) michael@0: { michael@0: Reset(); michael@0: } michael@0: michael@0: nsUnicodeToISO2022JP::~nsUnicodeToISO2022JP() michael@0: { michael@0: } michael@0: michael@0: nsresult nsUnicodeToISO2022JP::ChangeCharset(int32_t aCharset, michael@0: char * aDest, michael@0: int32_t * aDestLength) michael@0: { michael@0: // both 2 and 3 generate the same escape sequence. 2 is for michael@0: // the standard JISx0208 table, and 3 is for theCP932 extensions michael@0: // therefore, we treat them as the same one. michael@0: if(((2 == aCharset) && ( 3 == mCharset)) || michael@0: ((3 == aCharset) && ( 2 == mCharset)) ) michael@0: { michael@0: mCharset = aCharset; michael@0: } michael@0: michael@0: if(aCharset == mCharset) michael@0: { michael@0: *aDestLength = 0; michael@0: return NS_OK; michael@0: } michael@0: michael@0: if (*aDestLength < 3) { michael@0: *aDestLength = 0; michael@0: return NS_OK_UENC_MOREOUTPUT; michael@0: } michael@0: michael@0: switch (aCharset) { michael@0: case 0: // ASCII ISOREG 6 michael@0: aDest[0] = 0x1b; michael@0: aDest[1] = '('; michael@0: aDest[2] = 'B'; michael@0: break; michael@0: case 1: // JIS X 0201-1976 ("Roman" set) ISOREG 14 michael@0: aDest[0] = 0x1b; michael@0: aDest[1] = '('; michael@0: aDest[2] = 'J'; michael@0: break; michael@0: case 2: // JIS X 0208-1983 ISOREG 87 michael@0: case 3: // JIS X 0208-1983 michael@0: // we currently use this for CP932 ext michael@0: aDest[0] = 0x1b; michael@0: aDest[1] = '$'; michael@0: aDest[2] = 'B'; michael@0: break; michael@0: case 4: // JIS X 0201-1978 ISOREG 87- michael@0: // we currently do not have a diff mapping for it. michael@0: aDest[0] = 0x1b; michael@0: aDest[1] = '$'; michael@0: aDest[2] = '@'; michael@0: break; michael@0: } michael@0: michael@0: mCharset = aCharset; michael@0: *aDestLength = 3; michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult nsUnicodeToISO2022JP::ConvertHankaku(const char16_t * aSrc, michael@0: int32_t * aSrcLength, michael@0: char * aDest, michael@0: int32_t * aDestLength) michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: const char16_t * src = aSrc; michael@0: const char16_t * srcEnd = aSrc + *aSrcLength; michael@0: char * dest = aDest; michael@0: char * destEnd = aDest + *aDestLength; michael@0: char16_t srcChar, tempChar; michael@0: int32_t bcr, bcw; michael@0: michael@0: bcw = destEnd - dest; michael@0: res = ChangeCharset(JIS_X_208_INDEX, dest, &bcw); michael@0: dest += bcw; michael@0: if (res != NS_OK) { michael@0: return res; michael@0: } michael@0: michael@0: while (src < srcEnd) { michael@0: srcChar = *src; michael@0: if (!IS_HANKAKU(srcChar)) { michael@0: break; michael@0: } michael@0: ++src; michael@0: tempChar = gBasicMapping[(srcChar) - 0xff60]; michael@0: michael@0: if (src < srcEnd) { michael@0: // if the character could take a modifier, and the next char michael@0: // is a modifier, modify it and eat one char16_t michael@0: if (NEED_TO_CHECK_NIGORI(srcChar) && IS_NIGORI(*src)) { michael@0: tempChar += NIGORI_MODIFIER; michael@0: ++src; michael@0: } else if (NEED_TO_CHECK_MARU(srcChar) && IS_MARU(*src)) { michael@0: tempChar += MARU_MODIFIER; michael@0: ++src; michael@0: } michael@0: } michael@0: bcr = 1; michael@0: bcw = destEnd - dest; michael@0: res = nsUnicodeEncodeHelper::ConvertByTable( michael@0: &tempChar, &bcr, dest, &bcw, g_ufScanClassIDs[JIS_X_208_INDEX], michael@0: nullptr, (uMappingTable *) g_ufMappingTables[JIS_X_208_INDEX]); michael@0: dest += bcw; michael@0: if (res != NS_OK) michael@0: break; michael@0: } michael@0: *aDestLength = dest - aDest; michael@0: *aSrcLength = src - aSrc; michael@0: return res; michael@0: } michael@0: michael@0: //---------------------------------------------------------------------- michael@0: // Subclassing of nsTableEncoderSupport class [implementation] michael@0: michael@0: NS_IMETHODIMP nsUnicodeToISO2022JP::ConvertNoBuffNoErr( michael@0: const char16_t * aSrc, michael@0: int32_t * aSrcLength, michael@0: char * aDest, michael@0: int32_t * aDestLength) michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: const char16_t * src = aSrc; michael@0: const char16_t * srcEnd = aSrc + *aSrcLength; michael@0: char * dest = aDest; michael@0: char * destEnd = aDest + *aDestLength; michael@0: int32_t bcr, bcw; michael@0: int32_t i; michael@0: michael@0: while (src < srcEnd) { michael@0: for (i=0; i< SIZE_OF_ISO2022JP_TABLES ; i++) { michael@0: bcr = 1; michael@0: bcw = destEnd - dest; michael@0: res = nsUnicodeEncodeHelper::ConvertByTable(src, &bcr, dest, &bcw, michael@0: g_ufScanClassIDs[i], nullptr, michael@0: (uMappingTable *) g_ufMappingTables[i]); michael@0: if (res != NS_ERROR_UENC_NOMAPPING) break; michael@0: } michael@0: michael@0: if ( i>= SIZE_OF_ISO2022JP_TABLES) { michael@0: if (IS_HANKAKU(*src)) { michael@0: bcr = srcEnd - src; michael@0: bcw = destEnd - dest; michael@0: res = ConvertHankaku(src, &bcr, dest, &bcw); michael@0: dest += bcw; michael@0: src += bcr; michael@0: if (res == NS_OK) continue; michael@0: } else { michael@0: res = NS_ERROR_UENC_NOMAPPING; michael@0: src++; michael@0: } michael@0: } michael@0: if (res != NS_OK) break; michael@0: michael@0: bcw = destEnd - dest; michael@0: res = ChangeCharset(i, dest, &bcw); michael@0: dest += bcw; michael@0: if (res != NS_OK) break; michael@0: michael@0: bcr = srcEnd - src; michael@0: bcw = destEnd - dest; michael@0: res = nsUnicodeEncodeHelper::ConvertByTable(src, &bcr, dest, &bcw, michael@0: g_ufScanClassIDs[i], nullptr, michael@0: (uMappingTable *) g_ufMappingTables[i]); michael@0: src += bcr; michael@0: dest += bcw; michael@0: michael@0: if ((res != NS_OK) && (res != NS_ERROR_UENC_NOMAPPING)) break; michael@0: if (res == NS_ERROR_UENC_NOMAPPING) src--; michael@0: } michael@0: michael@0: *aSrcLength = src - aSrc; michael@0: *aDestLength = dest - aDest; michael@0: return res; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsUnicodeToISO2022JP::FinishNoBuff(char * aDest, michael@0: int32_t * aDestLength) michael@0: { michael@0: ChangeCharset(0, aDest, aDestLength); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsUnicodeToISO2022JP::Reset() michael@0: { michael@0: mCharset = 0; michael@0: return nsEncoderSupport::Reset(); michael@0: }