os/textandloc/charconvfw/charconvplugins/src/shared/SHIFTJIS_SHARED_2.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description:       
sl@0
    15
*
sl@0
    16
*/
sl@0
    17
sl@0
    18
sl@0
    19
#include "PictographObserver.h"
sl@0
    20
#include "featmgr/featmgr.h"  
sl@0
    21
sl@0
    22
#include <e32std.h>
sl@0
    23
#include <charconv.h>
sl@0
    24
#include <convutils.h>
sl@0
    25
#include "jisx0201.h"
sl@0
    26
#include "jisx0208.h"
sl@0
    27
#include "SHIFTJIS_2.H"
sl@0
    28
#include <convdata.h>
sl@0
    29
sl@0
    30
//const TUint KSingleByteRangeFirstBlockStart=0x00;
sl@0
    31
const TUint KSingleByteRangeFirstBlockEnd=0x7f;
sl@0
    32
const TUint KSingleByteRangeSecondBlockStart=0xa1;
sl@0
    33
const TUint KSingleByteRangeSecondBlockEnd=0xdf;
sl@0
    34
const TUint KFirstByteRangeFirstBlockStart=0x81;
sl@0
    35
const TUint KFirstByteRangeFirstBlockEnd=0x9f;
sl@0
    36
const TUint KFirstByteRangeFirstBlockLength=(KFirstByteRangeFirstBlockEnd+1)-KFirstByteRangeFirstBlockStart;
sl@0
    37
const TUint KFirstByteRangeSecondBlockStart=0xe0;
sl@0
    38
// Ken Lunde's book "CJKV Information Processing" (page 176) says this
sl@0
    39
// constant should be 0xef, but no Shift-JIS characters in
sl@0
    40
// \charconv\data\JISX0208.TXT have a first byte greater than 0xea, and
sl@0
    41
// some extensions of Shift-JIS may use the 0xeb-0xef range for the first
sl@0
    42
// byte of their characters (e.g. "MOPERA"), and in order for users of this
sl@0
    43
// DLL to be able to implement these extensions using the
sl@0
    44
// aArrayOfAdditionalXxxxx parameters, this constant therefore needs to
sl@0
    45
// be set as low as possible, i.e. to 0xea
sl@0
    46
const TUint KFirstByteRangeSecondBlockEnd=0xea;
sl@0
    47
const TUint KFirstByteRangeOtherBlockEnd = 0xfc;
sl@0
    48
sl@0
    49
const TUint KPictoFirstByteStart = 0xF0;
sl@0
    50
const TUint KPictoFirstByteEnd = 0xF9;
sl@0
    51
sl@0
    52
const TUint KSecondByteRangeFirstBlockStart=0x40;
sl@0
    53
const TUint KSecondByteRangeFirstBlockEnd=0x7e;
sl@0
    54
const TUint KSecondByteRangeFirstBlockLength=(KSecondByteRangeFirstBlockEnd+1)-KSecondByteRangeFirstBlockStart;
sl@0
    55
const TUint KSecondByteRangeSecondBlockStart=0x80;
sl@0
    56
const TUint KSecondByteRangeSecondBlockEnd=0xfc;
sl@0
    57
sl@0
    58
// SecureID for Brower app
sl@0
    59
const TUint32 KBrowserSecureId = 0x10008D39;
sl@0
    60
// Define for converting from YenSign to BackSlash
sl@0
    61
const TUint KCharacterCodeForYenSign = 0x00A5;
sl@0
    62
const TUint KCharacterCodeForBackSlash = 0x005C;
sl@0
    63
sl@0
    64
TInt BytesInOtherDoubleByteAreas(const TDesC8& aShiftJis);
sl@0
    65
TInt OneIfNotValid(const TDesC8& aShiftJis);
sl@0
    66
sl@0
    67
TBool IsJisX0208LeadByte(TUint a)
sl@0
    68
    {
sl@0
    69
    return (KFirstByteRangeFirstBlockStart <= a
sl@0
    70
        && a <= KFirstByteRangeFirstBlockEnd)
sl@0
    71
        || (KFirstByteRangeSecondBlockStart <= a
sl@0
    72
        && a <= KFirstByteRangeSecondBlockEnd);
sl@0
    73
    }
sl@0
    74
sl@0
    75
TBool IsValidTrailByte(TUint a)
sl@0
    76
    {
sl@0
    77
    return KSecondByteRangeFirstBlockStart <= a
sl@0
    78
        && a <= KSecondByteRangeSecondBlockEnd
sl@0
    79
        && a != KSecondByteRangeFirstBlockEnd + 1;
sl@0
    80
    }
sl@0
    81
sl@0
    82
TBool IsOtherLeadByte(TUint a)
sl@0
    83
    {
sl@0
    84
    if ( FeatureManager::FeatureSupported(KFeatureIdJapanesePicto) )
sl@0
    85
        {        
sl@0
    86
        return ((KFirstByteRangeSecondBlockEnd < a && a <= KFirstByteRangeOtherBlockEnd)
sl@0
    87
                && (a < KPictoFirstByteStart || a > KPictoFirstByteEnd));
sl@0
    88
        }
sl@0
    89
    else
sl@0
    90
        {        
sl@0
    91
        return KFirstByteRangeSecondBlockEnd < a
sl@0
    92
                && a <= KFirstByteRangeOtherBlockEnd;
sl@0
    93
        }
sl@0
    94
    }
sl@0
    95
sl@0
    96
_LIT8(KLit8ShiftJisReplacementForUnconvertibleUnicodeCharacters, "\x81\x48"); // fullwidth question mark
sl@0
    97
sl@0
    98
#if defined(_DEBUG)
sl@0
    99
sl@0
   100
_LIT(KLitPanicText, "SHIFTJIS_SHARED");
sl@0
   101
sl@0
   102
enum TPanic
sl@0
   103
    {
sl@0
   104
    EPanicIndexOverflow1=1,
sl@0
   105
    EPanicIndexOverflow2,
sl@0
   106
    EPanicNothingToConvert1,
sl@0
   107
    EPanicNothingToConvert2,
sl@0
   108
    EPanicOddNumberOfBytes1,
sl@0
   109
    EPanicOddNumberOfBytes2,
sl@0
   110
    EPanicBadPointers1,
sl@0
   111
    EPanicBadPointers2,
sl@0
   112
    EPanicBadPointers3,
sl@0
   113
    EPanicBadPointers4,
sl@0
   114
    EPanicBadPointers5,
sl@0
   115
    EPanicBadPointers6,
sl@0
   116
    EPanicBadPointers7,
sl@0
   117
    EPanicBadPointers8,
sl@0
   118
    EPanicBadPointers9
sl@0
   119
    };
sl@0
   120
sl@0
   121
LOCAL_C void Panic(TPanic aPanic)
sl@0
   122
    {
sl@0
   123
    User::Panic(KLitPanicText, aPanic);
sl@0
   124
    }
sl@0
   125
sl@0
   126
#endif
sl@0
   127
sl@0
   128
// TCombinedArrayOfCharacterSets
sl@0
   129
sl@0
   130
class TCombinedArrayOfCharacterSets
sl@0
   131
    {
sl@0
   132
public:
sl@0
   133
    TCombinedArrayOfCharacterSets(const TArray<CnvUtilities::SCharacterSet>* aArrayOfAdditionalCharacterSets);
sl@0
   134
    ~TCombinedArrayOfCharacterSets();
sl@0
   135
    TArray<CnvUtilities::SCharacterSet> Array() const;
sl@0
   136
private:
sl@0
   137
    static TInt CombinedCount(const CBase* aThis);
sl@0
   138
    static const TAny* CombinedAccessor(const CBase* aThis, TInt aIndex);
sl@0
   139
private:
sl@0
   140
    RArray<CnvUtilities::SCharacterSet> iArrayOfCoreCharacterSets;
sl@0
   141
    const TArray<CnvUtilities::SCharacterSet>* iArrayOfAdditionalCharacterSets;
sl@0
   142
    };
sl@0
   143
sl@0
   144
TCombinedArrayOfCharacterSets::TCombinedArrayOfCharacterSets(const TArray<CnvUtilities::SCharacterSet>* aArrayOfAdditionalCharacterSets)
sl@0
   145
    :iArrayOfAdditionalCharacterSets(aArrayOfAdditionalCharacterSets)
sl@0
   146
    {
sl@0
   147
    if ( FeatureManager::FeatureSupported(KFeatureIdJapanesePicto) )
sl@0
   148
        {      
sl@0
   149
        CnvUtilities::SCharacterSet characterSet;
sl@0
   150
        characterSet.iConversionData=&CnvJisX0201::ConversionData();
sl@0
   151
        characterSet.iConvertFromIntermediateBufferInPlace=CnvShiftJis::DummyConvertFromIntermediateBufferInPlace;
sl@0
   152
        characterSet.iEscapeSequence=&KNullDesC8;
sl@0
   153
        iArrayOfCoreCharacterSets.Append(characterSet);
sl@0
   154
        characterSet.iConversionData=&CnvJisX0208::ConversionData();
sl@0
   155
        characterSet.iConvertFromIntermediateBufferInPlace=CnvShiftJis::ConvertFromJisX0208ToShiftJisInPlace;
sl@0
   156
        characterSet.iEscapeSequence=&KNullDesC8;
sl@0
   157
        iArrayOfCoreCharacterSets.Append(characterSet);
sl@0
   158
sl@0
   159
        SetCharacterSetsForPictograph(iArrayOfCoreCharacterSets, ECharsetShiftJis);
sl@0
   160
        }
sl@0
   161
    else
sl@0
   162
        {            
sl@0
   163
        CnvUtilities::SCharacterSet characterSet;
sl@0
   164
        characterSet.iConversionData=&CnvJisX0201::ConversionData();
sl@0
   165
        characterSet.iConvertFromIntermediateBufferInPlace=CnvShiftJis::DummyConvertFromIntermediateBufferInPlace;
sl@0
   166
        characterSet.iEscapeSequence=&KNullDesC8;
sl@0
   167
        iArrayOfCoreCharacterSets.Append(characterSet);
sl@0
   168
        characterSet.iConversionData=&CnvJisX0208::ConversionData();
sl@0
   169
        characterSet.iConvertFromIntermediateBufferInPlace=CnvShiftJis::ConvertFromJisX0208ToShiftJisInPlace;
sl@0
   170
        characterSet.iEscapeSequence=&KNullDesC8;
sl@0
   171
        iArrayOfCoreCharacterSets.Append(characterSet);
sl@0
   172
        }
sl@0
   173
    }
sl@0
   174
sl@0
   175
TCombinedArrayOfCharacterSets::~TCombinedArrayOfCharacterSets()
sl@0
   176
    {
sl@0
   177
    iArrayOfCoreCharacterSets.Close();
sl@0
   178
    }
sl@0
   179
sl@0
   180
sl@0
   181
TArray<CnvUtilities::SCharacterSet> TCombinedArrayOfCharacterSets::Array() const
sl@0
   182
    {
sl@0
   183
    return TArray<CnvUtilities::SCharacterSet>(CombinedCount, CombinedAccessor, REINTERPRET_CAST(const CBase*, this));
sl@0
   184
    }
sl@0
   185
sl@0
   186
TInt TCombinedArrayOfCharacterSets::CombinedCount(const CBase* aThis)
sl@0
   187
    {
sl@0
   188
    const TCombinedArrayOfCharacterSets& thisReference=*REINTERPRET_CAST(const TCombinedArrayOfCharacterSets*, aThis);
sl@0
   189
    const TInt numberOfCoreCharacterSets=thisReference.iArrayOfCoreCharacterSets.Count();
sl@0
   190
    if (thisReference.iArrayOfAdditionalCharacterSets!=NULL)
sl@0
   191
        {
sl@0
   192
        return numberOfCoreCharacterSets+thisReference.iArrayOfAdditionalCharacterSets->Count();
sl@0
   193
        }
sl@0
   194
    return numberOfCoreCharacterSets;
sl@0
   195
    }
sl@0
   196
sl@0
   197
const TAny* TCombinedArrayOfCharacterSets::CombinedAccessor(const CBase* aThis, TInt aIndex)
sl@0
   198
    {
sl@0
   199
    const TCombinedArrayOfCharacterSets& thisReference=*REINTERPRET_CAST(const TCombinedArrayOfCharacterSets*, aThis);
sl@0
   200
    const TInt numberOfCoreCharacterSets=thisReference.iArrayOfCoreCharacterSets.Count();
sl@0
   201
    if (aIndex>=numberOfCoreCharacterSets)
sl@0
   202
        {
sl@0
   203
        __ASSERT_DEBUG(thisReference.iArrayOfAdditionalCharacterSets!=NULL, Panic(EPanicIndexOverflow1));
sl@0
   204
        return &(*thisReference.iArrayOfAdditionalCharacterSets)[aIndex-numberOfCoreCharacterSets];
sl@0
   205
        }
sl@0
   206
    return &thisReference.iArrayOfCoreCharacterSets[aIndex];
sl@0
   207
    }
sl@0
   208
sl@0
   209
// TCombinedArrayOfMethods
sl@0
   210
sl@0
   211
class TCombinedArrayOfMethods
sl@0
   212
    {
sl@0
   213
public:
sl@0
   214
    TCombinedArrayOfMethods(const TArray<CnvUtilities::SMethod>* aArrayOfAdditionalMethods);
sl@0
   215
    ~TCombinedArrayOfMethods();
sl@0
   216
    TArray<CnvUtilities::SMethod> Array() const;
sl@0
   217
private:
sl@0
   218
    static TInt CombinedCount(const CBase* aThis);
sl@0
   219
    static const TAny* CombinedAccessor(const CBase* aThis, TInt aIndex);
sl@0
   220
private:
sl@0
   221
    RArray<CnvUtilities::SMethod> iArrayOfCoreMethods;
sl@0
   222
    const TArray<CnvUtilities::SMethod>* iArrayOfAdditionalMethods;
sl@0
   223
    };
sl@0
   224
sl@0
   225
TCombinedArrayOfMethods::TCombinedArrayOfMethods(const TArray<CnvUtilities::SMethod>* aArrayOfAdditionalMethods)
sl@0
   226
    :iArrayOfAdditionalMethods(aArrayOfAdditionalMethods)
sl@0
   227
    {
sl@0
   228
    if ( FeatureManager::FeatureSupported(KFeatureIdJapanesePicto) )
sl@0
   229
        {      
sl@0
   230
        SetMethodsForPictograph(iArrayOfCoreMethods, ECharsetShiftJis);
sl@0
   231
        CnvUtilities::SMethod method;
sl@0
   232
        method.iNumberOfBytesAbleToConvert=CnvShiftJis::NumberOfBytesAbleToConvertToJisX0201;
sl@0
   233
        method.iConvertToIntermediateBufferInPlace=CnvShiftJis::DummyConvertToIntermediateBufferInPlace;
sl@0
   234
        method.iConversionData=&CnvJisX0201::ConversionData();
sl@0
   235
        method.iNumberOfBytesPerCharacter=1;
sl@0
   236
        method.iNumberOfCoreBytesPerCharacter=1;
sl@0
   237
        iArrayOfCoreMethods.Append(method);
sl@0
   238
        method.iNumberOfBytesAbleToConvert=CnvShiftJis::NumberOfBytesAbleToConvertToJisX0208;
sl@0
   239
        method.iConvertToIntermediateBufferInPlace=CnvShiftJis::ConvertToJisX0208FromShiftJisInPlace;
sl@0
   240
        method.iConversionData=&CnvJisX0208::ConversionData();
sl@0
   241
        method.iNumberOfBytesPerCharacter=2;
sl@0
   242
        method.iNumberOfCoreBytesPerCharacter=2;
sl@0
   243
        iArrayOfCoreMethods.Append(method);
sl@0
   244
        }
sl@0
   245
    else
sl@0
   246
        {        
sl@0
   247
        CnvUtilities::SMethod method;
sl@0
   248
        method.iNumberOfBytesAbleToConvert=CnvShiftJis::NumberOfBytesAbleToConvertToJisX0201;
sl@0
   249
        method.iConvertToIntermediateBufferInPlace=CnvShiftJis::DummyConvertToIntermediateBufferInPlace;
sl@0
   250
        method.iConversionData=&CnvJisX0201::ConversionData();
sl@0
   251
        method.iNumberOfBytesPerCharacter=1;
sl@0
   252
        method.iNumberOfCoreBytesPerCharacter=1;
sl@0
   253
        iArrayOfCoreMethods.Append(method);
sl@0
   254
        method.iNumberOfBytesAbleToConvert=CnvShiftJis::NumberOfBytesAbleToConvertToJisX0208;
sl@0
   255
        method.iConvertToIntermediateBufferInPlace=CnvShiftJis::ConvertToJisX0208FromShiftJisInPlace;
sl@0
   256
        method.iConversionData=&CnvJisX0208::ConversionData();
sl@0
   257
        method.iNumberOfBytesPerCharacter=2;
sl@0
   258
        method.iNumberOfCoreBytesPerCharacter=2;
sl@0
   259
        iArrayOfCoreMethods.Append(method);    
sl@0
   260
        }
sl@0
   261
    }
sl@0
   262
sl@0
   263
TCombinedArrayOfMethods::~TCombinedArrayOfMethods()
sl@0
   264
    {
sl@0
   265
    iArrayOfCoreMethods.Close();
sl@0
   266
    }
sl@0
   267
sl@0
   268
sl@0
   269
TArray<CnvUtilities::SMethod> TCombinedArrayOfMethods::Array() const
sl@0
   270
    {
sl@0
   271
    return TArray<CnvUtilities::SMethod>(CombinedCount, CombinedAccessor, REINTERPRET_CAST(const CBase*, this));
sl@0
   272
    }
sl@0
   273
sl@0
   274
TInt TCombinedArrayOfMethods::CombinedCount(const CBase* aThis)
sl@0
   275
    {
sl@0
   276
    const TCombinedArrayOfMethods& thisReference=*REINTERPRET_CAST(const TCombinedArrayOfMethods*, aThis);
sl@0
   277
    const TInt numberOfCoreMethods=thisReference.iArrayOfCoreMethods.Count();
sl@0
   278
    if (thisReference.iArrayOfAdditionalMethods!=NULL)
sl@0
   279
        {
sl@0
   280
        return numberOfCoreMethods+thisReference.iArrayOfAdditionalMethods->Count();
sl@0
   281
        }
sl@0
   282
    return numberOfCoreMethods;
sl@0
   283
    }
sl@0
   284
sl@0
   285
const TAny* TCombinedArrayOfMethods::CombinedAccessor(const CBase* aThis, TInt aIndex)
sl@0
   286
    {
sl@0
   287
    const TCombinedArrayOfMethods& thisReference=*REINTERPRET_CAST(const TCombinedArrayOfMethods*, aThis);
sl@0
   288
    const TInt numberOfCoreMethods=thisReference.iArrayOfCoreMethods.Count();
sl@0
   289
    if (aIndex>=numberOfCoreMethods)
sl@0
   290
        {
sl@0
   291
        __ASSERT_DEBUG(thisReference.iArrayOfAdditionalMethods!=NULL, Panic(EPanicIndexOverflow2));
sl@0
   292
        return &(*thisReference.iArrayOfAdditionalMethods)[aIndex-numberOfCoreMethods];
sl@0
   293
        }
sl@0
   294
    return &thisReference.iArrayOfCoreMethods[aIndex];
sl@0
   295
    }
sl@0
   296
sl@0
   297
// CnvShiftJis
sl@0
   298
sl@0
   299
EXPORT_C const TDesC8& CnvShiftJis::ReplacementForUnconvertibleUnicodeCharacters()
sl@0
   300
    {
sl@0
   301
    return KLit8ShiftJisReplacementForUnconvertibleUnicodeCharacters;
sl@0
   302
    }
sl@0
   303
sl@0
   304
EXPORT_C TInt CnvShiftJis::ConvertFromUnicode(CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, const TDesC8& aReplacementForUnconvertibleUnicodeCharacters, TDes8& aForeign, const TDesC16& aUnicode, CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters)
sl@0
   305
    {
sl@0
   306
    return DoConvertFromUnicode(aDefaultEndiannessOfForeignCharacters, aReplacementForUnconvertibleUnicodeCharacters, aForeign, aUnicode, aIndicesOfUnconvertibleCharacters, NULL);
sl@0
   307
    }
sl@0
   308
sl@0
   309
/**
sl@0
   310
 * Converts text from Unicode to Shift-JIS (aArrayOfAdditionalCharacterSets provides support
sl@0
   311
 * for Shift-JIS extensions)
sl@0
   312
 *
sl@0
   313
 * @since Internationalization_6.2
sl@0
   314
 */
sl@0
   315
EXPORT_C TInt CnvShiftJis::ConvertFromUnicode(CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, const TDesC8& aReplacementForUnconvertibleUnicodeCharacters, TDes8& aForeign, const TDesC16& aUnicode, CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters, const TArray<CnvUtilities::SCharacterSet>& aArrayOfAdditionalCharacterSets)
sl@0
   316
    {
sl@0
   317
    return DoConvertFromUnicode(aDefaultEndiannessOfForeignCharacters, aReplacementForUnconvertibleUnicodeCharacters, aForeign, aUnicode, aIndicesOfUnconvertibleCharacters, &aArrayOfAdditionalCharacterSets);
sl@0
   318
    }
sl@0
   319
sl@0
   320
EXPORT_C TInt CnvShiftJis::ConvertToUnicode(
sl@0
   321
    CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
sl@0
   322
    TDes16& aUnicode, const TDesC8& aForeign,
sl@0
   323
    TInt& aNumberOfUnconvertibleCharacters,
sl@0
   324
    TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter)
sl@0
   325
    {
sl@0
   326
    // DummyData converts any pair of bytes into FFFD
sl@0
   327
    static const SCnvConversionData::SVariableByteData::SRange
sl@0
   328
        DummyByteLengths = {0, 255, 1, 0};
sl@0
   329
    static const SCnvConversionData::SOneDirectionData::SRange DummyConv =
sl@0
   330
        { 0xFFFD, 0xFFFD,
sl@0
   331
        SCnvConversionData::SOneDirectionData::SRange::EDirect, 2, 0 };
sl@0
   332
    static const SCnvConversionData DummyData =
sl@0
   333
        {
sl@0
   334
        SCnvConversionData::EFixedBigEndian,
sl@0
   335
        {1, &DummyByteLengths},
sl@0
   336
        {1, &DummyConv},
sl@0
   337
        {1, &DummyConv}
sl@0
   338
        };
sl@0
   339
    TFixedArray<CnvUtilities::SMethod, 2> nullExtension;
sl@0
   340
    // First extension converts unrecognised double byte characters to FFFD
sl@0
   341
    nullExtension[0].iNumberOfBytesAbleToConvert
sl@0
   342
        = BytesInOtherDoubleByteAreas;
sl@0
   343
    nullExtension[0].iConvertToIntermediateBufferInPlace
sl@0
   344
        = CnvShiftJis::DummyConvertToIntermediateBufferInPlace;
sl@0
   345
    // This conversion data won't do anything for us: it will just get us
sl@0
   346
    // a load of FFFD, which is what we want.
sl@0
   347
    nullExtension[0].iConversionData = &DummyData;
sl@0
   348
    nullExtension[0].iNumberOfBytesPerCharacter = 2;
sl@0
   349
    nullExtension[0].iNumberOfCoreBytesPerCharacter = 2;
sl@0
   350
    // Second extension converts any other single byte to FFFD,
sl@0
   351
    // but only ever one!
sl@0
   352
    nullExtension[1].iNumberOfBytesAbleToConvert
sl@0
   353
        = OneIfNotValid;
sl@0
   354
    nullExtension[1].iConvertToIntermediateBufferInPlace
sl@0
   355
        = CnvShiftJis::DummyConvertToIntermediateBufferInPlace;
sl@0
   356
    // This conversion data won't do anything for us: it will just get us
sl@0
   357
    // a load of FFFD, which is what we want.
sl@0
   358
    nullExtension[1].iConversionData = &CnvJisX0201::ConversionData();
sl@0
   359
    nullExtension[1].iNumberOfBytesPerCharacter = 1;
sl@0
   360
    nullExtension[1].iNumberOfCoreBytesPerCharacter = 1;
sl@0
   361
    const TArray<CnvUtilities::SMethod> nullExtensionArray = nullExtension.Array();
sl@0
   362
    return DoConvertToUnicode(aDefaultEndiannessOfForeignCharacters,
sl@0
   363
        aUnicode, aForeign, aNumberOfUnconvertibleCharacters,
sl@0
   364
        aIndexOfFirstByteOfFirstUnconvertibleCharacter,
sl@0
   365
        &nullExtensionArray);
sl@0
   366
    }
sl@0
   367
sl@0
   368
/**
sl@0
   369
 * Converts text from Shift-JIS to Unicode (aArrayOfAdditionalMethods provides support
sl@0
   370
 * for Shift-JIS extensions)
sl@0
   371
 *
sl@0
   372
 * @since Internationalization_6.2
sl@0
   373
 */
sl@0
   374
EXPORT_C TInt CnvShiftJis::ConvertToUnicode(CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters, TDes16& aUnicode, const TDesC8& aForeign, TInt& aNumberOfUnconvertibleCharacters, TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter, const TArray<CnvUtilities::SMethod>& aArrayOfAdditionalMethods)
sl@0
   375
    {
sl@0
   376
    return DoConvertToUnicode(aDefaultEndiannessOfForeignCharacters, aUnicode, aForeign, aNumberOfUnconvertibleCharacters, aIndexOfFirstByteOfFirstUnconvertibleCharacter, &aArrayOfAdditionalMethods);
sl@0
   377
    }
sl@0
   378
sl@0
   379
TInt CnvShiftJis::DoConvertFromUnicode(
sl@0
   380
    CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
sl@0
   381
    const TDesC8& aReplacementForUnconvertibleUnicodeCharacters,
sl@0
   382
    TDes8& aForeign, const TDesC16& aUnicode,
sl@0
   383
    CCnvCharacterSetConverter::TArrayOfAscendingIndices& aIndicesOfUnconvertibleCharacters,
sl@0
   384
    const TArray<CnvUtilities::SCharacterSet>* aArrayOfAdditionalCharacterSets)
sl@0
   385
    {
sl@0
   386
    TCombinedArrayOfCharacterSets combinedArrayOfCharacterSets(aArrayOfAdditionalCharacterSets);
sl@0
   387
    return CnvUtilities::ConvertFromUnicode(aDefaultEndiannessOfForeignCharacters, aReplacementForUnconvertibleUnicodeCharacters, aForeign, aUnicode, aIndicesOfUnconvertibleCharacters, combinedArrayOfCharacterSets.Array());
sl@0
   388
    }
sl@0
   389
sl@0
   390
TInt CnvShiftJis::DoConvertToUnicode(
sl@0
   391
    CCnvCharacterSetConverter::TEndianness aDefaultEndiannessOfForeignCharacters,
sl@0
   392
    TDes16& aUnicode, const TDesC8& aForeign,
sl@0
   393
    TInt& aNumberOfUnconvertibleCharacters,
sl@0
   394
    TInt& aIndexOfFirstByteOfFirstUnconvertibleCharacter,
sl@0
   395
    const TArray<CnvUtilities::SMethod>* aArrayOfAdditionalMethods)
sl@0
   396
    {
sl@0
   397
    TCombinedArrayOfMethods combinedArrayOfMethods(aArrayOfAdditionalMethods);
sl@0
   398
    TInt unconvert = CnvUtilities::ConvertToUnicodeFromHeterogeneousForeign(
sl@0
   399
        aDefaultEndiannessOfForeignCharacters, aUnicode, aForeign,
sl@0
   400
        aNumberOfUnconvertibleCharacters,
sl@0
   401
        aIndexOfFirstByteOfFirstUnconvertibleCharacter,
sl@0
   402
        combinedArrayOfMethods.Array());
sl@0
   403
sl@0
   404
    // The following is specific impelementation for brower.
sl@0
   405
    // If brower app calls this API, the yen sign code(0xA5)
sl@0
   406
    // must be converted to backslash code(0x5C).
sl@0
   407
    // Becasue Javascript supports backslash code ony.
sl@0
   408
    TBool browserProcess = (RProcess().SecureId().iId == KBrowserSecureId);
sl@0
   409
    if (browserProcess && aUnicode.Length() > 0)
sl@0
   410
        {
sl@0
   411
        const TUint16* pB = aUnicode.Ptr();
sl@0
   412
        const TUint16* pbase = pB;
sl@0
   413
        const TUint16* pE = pB + aUnicode.Length() -1;
sl@0
   414
        while (pE>=pbase)
sl@0
   415
            {
sl@0
   416
            if (*pbase == KCharacterCodeForYenSign)
sl@0
   417
                {
sl@0
   418
                aUnicode[pbase - pB] = KCharacterCodeForBackSlash;
sl@0
   419
                }
sl@0
   420
            pbase++;
sl@0
   421
            }
sl@0
   422
        }
sl@0
   423
sl@0
   424
    return unconvert;
sl@0
   425
    }
sl@0
   426
sl@0
   427
void CnvShiftJis::DummyConvertFromIntermediateBufferInPlace(TInt, TDes8&, TInt& aNumberOfCharactersThatDroppedOut)
sl@0
   428
    {
sl@0
   429
    aNumberOfCharactersThatDroppedOut=0;
sl@0
   430
    }
sl@0
   431
sl@0
   432
void CnvShiftJis::ConvertFromJisX0208ToShiftJisInPlace(TInt aStartPositionInDescriptor, TDes8& aDescriptor, TInt& aNumberOfCharactersThatDroppedOut)
sl@0
   433
    {
sl@0
   434
    aNumberOfCharactersThatDroppedOut=0;
sl@0
   435
    const TInt descriptorLength=aDescriptor.Length();
sl@0
   436
    __ASSERT_DEBUG(descriptorLength>aStartPositionInDescriptor, Panic(EPanicNothingToConvert1));
sl@0
   437
    __ASSERT_DEBUG((descriptorLength-aStartPositionInDescriptor)%2==0, Panic(EPanicOddNumberOfBytes1));
sl@0
   438
    TUint8* pointerToCurrentByte=CONST_CAST(TUint8*, aDescriptor.Ptr());
sl@0
   439
    const TUint8* const pointerToLastByte=pointerToCurrentByte+(descriptorLength-1);
sl@0
   440
    pointerToCurrentByte+=aStartPositionInDescriptor;
sl@0
   441
    FOREVER
sl@0
   442
        {
sl@0
   443
        TUint firstByte=*pointerToCurrentByte-0x21;
sl@0
   444
        TUint secondByte=*(pointerToCurrentByte+1)-0x21;
sl@0
   445
        if (firstByte%2!=0)
sl@0
   446
            {
sl@0
   447
            secondByte+=94;
sl@0
   448
            }
sl@0
   449
        firstByte/=2;
sl@0
   450
        if (firstByte<KFirstByteRangeFirstBlockLength)
sl@0
   451
            {
sl@0
   452
            firstByte+=KFirstByteRangeFirstBlockStart;
sl@0
   453
            }
sl@0
   454
        else
sl@0
   455
            {
sl@0
   456
            firstByte+=KFirstByteRangeSecondBlockStart-KFirstByteRangeFirstBlockLength;
sl@0
   457
            }
sl@0
   458
        if (secondByte<KSecondByteRangeFirstBlockLength)
sl@0
   459
            {
sl@0
   460
            secondByte+=KSecondByteRangeFirstBlockStart;
sl@0
   461
            }
sl@0
   462
        else
sl@0
   463
            {
sl@0
   464
            secondByte+=KSecondByteRangeSecondBlockStart-KSecondByteRangeFirstBlockLength;
sl@0
   465
            }
sl@0
   466
        *pointerToCurrentByte=STATIC_CAST(TUint8, firstByte);
sl@0
   467
        ++pointerToCurrentByte;
sl@0
   468
        *pointerToCurrentByte=STATIC_CAST(TUint8, secondByte);
sl@0
   469
        __ASSERT_DEBUG(pointerToCurrentByte<=pointerToLastByte, Panic(EPanicBadPointers1));
sl@0
   470
        if (pointerToCurrentByte>=pointerToLastByte)
sl@0
   471
            {
sl@0
   472
            break;
sl@0
   473
            }
sl@0
   474
        ++pointerToCurrentByte;
sl@0
   475
        }
sl@0
   476
    }
sl@0
   477
sl@0
   478
TInt CnvShiftJis::NumberOfBytesAbleToConvertToJisX0201(const TDesC8& aDescriptor)
sl@0
   479
    {
sl@0
   480
    const TUint8* pointerToPreviousByte=aDescriptor.Ptr()-1;
sl@0
   481
    const TUint8* const pointerToLastByte=pointerToPreviousByte+aDescriptor.Length();
sl@0
   482
    if (pointerToPreviousByte==pointerToLastByte)
sl@0
   483
        {
sl@0
   484
        return 0;
sl@0
   485
        }
sl@0
   486
    FOREVER
sl@0
   487
        {
sl@0
   488
        __ASSERT_DEBUG(pointerToPreviousByte<pointerToLastByte, Panic(EPanicBadPointers2));
sl@0
   489
        const TUint currentByte=*(pointerToPreviousByte+1);
sl@0
   490
        if (((currentByte>KSingleByteRangeFirstBlockEnd) && (currentByte<KSingleByteRangeSecondBlockStart)) ||
sl@0
   491
            (currentByte>KSingleByteRangeSecondBlockEnd))
sl@0
   492
            {
sl@0
   493
            break;
sl@0
   494
            }
sl@0
   495
        __ASSERT_DEBUG(pointerToPreviousByte<pointerToLastByte, Panic(EPanicBadPointers3));
sl@0
   496
        ++pointerToPreviousByte;
sl@0
   497
        __ASSERT_DEBUG(pointerToPreviousByte<=pointerToLastByte, Panic(EPanicBadPointers4));
sl@0
   498
        if (pointerToPreviousByte>=pointerToLastByte)
sl@0
   499
            {
sl@0
   500
            break;
sl@0
   501
            }
sl@0
   502
        }
sl@0
   503
    return (pointerToPreviousByte+1)-aDescriptor.Ptr();
sl@0
   504
    }
sl@0
   505
sl@0
   506
TInt CnvShiftJis::NumberOfBytesAbleToConvertToJisX0208(const TDesC8& aDescriptor)
sl@0
   507
    {
sl@0
   508
    const TUint8* pointerToPreviousByte=aDescriptor.Ptr()-1;
sl@0
   509
    const TUint8* const pointerToLastByte=pointerToPreviousByte+aDescriptor.Length();
sl@0
   510
    if (pointerToPreviousByte==pointerToLastByte)
sl@0
   511
        {
sl@0
   512
        return 0;
sl@0
   513
        }
sl@0
   514
    FOREVER
sl@0
   515
        {
sl@0
   516
        __ASSERT_DEBUG(pointerToPreviousByte<pointerToLastByte, Panic(EPanicBadPointers5));
sl@0
   517
        TUint currentByte=*(pointerToPreviousByte+1);
sl@0
   518
        if (!IsJisX0208LeadByte(currentByte))
sl@0
   519
            {
sl@0
   520
            if (!IsOtherLeadByte(currentByte))
sl@0
   521
                {
sl@0
   522
                break;
sl@0
   523
                }
sl@0
   524
            }
sl@0
   525
        __ASSERT_DEBUG(pointerToPreviousByte<pointerToLastByte, Panic(EPanicBadPointers6));
sl@0
   526
        if (pointerToPreviousByte+1>=pointerToLastByte)
sl@0
   527
            {
sl@0
   528
            break;
sl@0
   529
            }
sl@0
   530
        __ASSERT_DEBUG(pointerToPreviousByte+2<=pointerToLastByte, Panic(EPanicBadPointers7));
sl@0
   531
        currentByte=*(pointerToPreviousByte+2);
sl@0
   532
        if (!IsValidTrailByte(currentByte))
sl@0
   533
            {
sl@0
   534
            break;
sl@0
   535
            }
sl@0
   536
        pointerToPreviousByte+=2;
sl@0
   537
        __ASSERT_DEBUG(pointerToPreviousByte<=pointerToLastByte, Panic(EPanicBadPointers8));
sl@0
   538
        if (pointerToPreviousByte>=pointerToLastByte)
sl@0
   539
            {
sl@0
   540
            break;
sl@0
   541
            }
sl@0
   542
        }
sl@0
   543
    return (pointerToPreviousByte+1)-aDescriptor.Ptr();
sl@0
   544
    }
sl@0
   545
sl@0
   546
void CnvShiftJis::DummyConvertToIntermediateBufferInPlace(TDes8&)
sl@0
   547
    {
sl@0
   548
    }
sl@0
   549
sl@0
   550
void CnvShiftJis::ConvertToJisX0208FromShiftJisInPlace(TDes8& aDescriptor)
sl@0
   551
    {
sl@0
   552
    const TInt descriptorLength=aDescriptor.Length();
sl@0
   553
    __ASSERT_DEBUG(descriptorLength>0, Panic(EPanicNothingToConvert2));
sl@0
   554
    __ASSERT_DEBUG(descriptorLength%2==0, Panic(EPanicOddNumberOfBytes2));
sl@0
   555
    TUint8* pointerToCurrentByte=CONST_CAST(TUint8*, aDescriptor.Ptr());
sl@0
   556
    const TUint8* const pointerToLastByte=pointerToCurrentByte+(descriptorLength-1);
sl@0
   557
    FOREVER
sl@0
   558
        {
sl@0
   559
        TUint firstByte=*pointerToCurrentByte;
sl@0
   560
        TUint secondByte=*(pointerToCurrentByte+1);
sl@0
   561
        if (firstByte<KFirstByteRangeSecondBlockStart)
sl@0
   562
            {
sl@0
   563
            firstByte-=KFirstByteRangeFirstBlockStart;
sl@0
   564
            }
sl@0
   565
        else
sl@0
   566
            {
sl@0
   567
            firstByte-=KFirstByteRangeSecondBlockStart-KFirstByteRangeFirstBlockLength;
sl@0
   568
            }
sl@0
   569
        if (secondByte<KSecondByteRangeSecondBlockStart)
sl@0
   570
            {
sl@0
   571
            secondByte-=KSecondByteRangeFirstBlockStart;
sl@0
   572
            }
sl@0
   573
        else
sl@0
   574
            {
sl@0
   575
            secondByte-=KSecondByteRangeSecondBlockStart-KSecondByteRangeFirstBlockLength;
sl@0
   576
            }
sl@0
   577
        firstByte*=2;
sl@0
   578
        if (secondByte>=94)
sl@0
   579
            {
sl@0
   580
            ++firstByte;
sl@0
   581
            secondByte-=94;
sl@0
   582
            }
sl@0
   583
        firstByte+=0x21;
sl@0
   584
        secondByte+=0x21;
sl@0
   585
        *pointerToCurrentByte=STATIC_CAST(TUint8, firstByte);
sl@0
   586
        ++pointerToCurrentByte;
sl@0
   587
        *pointerToCurrentByte=STATIC_CAST(TUint8, secondByte);
sl@0
   588
        __ASSERT_DEBUG(pointerToCurrentByte<=pointerToLastByte, Panic(EPanicBadPointers9));
sl@0
   589
        if (pointerToCurrentByte>=pointerToLastByte)
sl@0
   590
            {
sl@0
   591
            break;
sl@0
   592
            }
sl@0
   593
        ++pointerToCurrentByte;
sl@0
   594
        }
sl@0
   595
    }
sl@0
   596
sl@0
   597
TInt BytesInOtherDoubleByteAreas(const TDesC8& aShiftJis)
sl@0
   598
    {
sl@0
   599
    const TText8* start = aShiftJis.Ptr();
sl@0
   600
    const TText8* end = start + aShiftJis.Length() - 1;
sl@0
   601
    const TText8* p = start;
sl@0
   602
    while (p < end && IsOtherLeadByte(p[0]) && IsValidTrailByte(p[1]))
sl@0
   603
        p += 2;
sl@0
   604
    return p - start;
sl@0
   605
    }
sl@0
   606
sl@0
   607
TInt OneIfNotValid(const TDesC8& aShiftJis)
sl@0
   608
    {
sl@0
   609
    TInt length = aShiftJis.Length();
sl@0
   610
    if (length == 0)
sl@0
   611
        return 0;
sl@0
   612
    TInt c = aShiftJis[0];
sl@0
   613
    // If the next byte is not a lead byte, we can swallow it. The
sl@0
   614
    // double-byte methods obviously can't be waiting for more
sl@0
   615
    // information.
sl@0
   616
    if (!IsOtherLeadByte(c) && !IsJisX0208LeadByte(c))
sl@0
   617
        return 1;
sl@0
   618
    // Otherwise we have a lead byte. If it is on its own we cannot
sl@0
   619
    // swallow it as the double-byte converters will be waiting for
sl@0
   620
    // more information. If they have the information (i.e. if length > 1)
sl@0
   621
    // then they have passed on it and we can swallow it.
sl@0
   622
    return length == 1? 0 : 1;
sl@0
   623
    }