charconvfw/JPLangUtil/src/jplangutil.cpp
branchRCL_3
changeset 55 336bee5c2d35
equal deleted inserted replaced
54:748ec5531811 55:336bee5c2d35
       
     1 /*
       
     2 * Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *     A utility for providing Japanese Language-specific (UNICODE) functions.
       
    16 *
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 // INCLUDES FILES
       
    22 #include "jplangutil.h"
       
    23 #include "jplangutil.tables.h"
       
    24 
       
    25 // LOCAL DEFINES
       
    26 
       
    27 // LOCAL CONSTANTS AND ENUMS
       
    28 
       
    29 #if defined(_DEBUG)
       
    30 _LIT( KJPLangUtilPanic, "JPLangUtil" );
       
    31 enum TJPLangUtilPanicCodes
       
    32     {
       
    33     EErrNotKatakana = 0x777,
       
    34     EErrNotVoicedKatakana
       
    35     };
       
    36 #endif
       
    37 
       
    38 enum TConvDirection
       
    39     {
       
    40     EHalfToFullWidth,
       
    41     EFullToHalfWidth
       
    42     };
       
    43 
       
    44 const TInt KHalfWidthKatakanaRange = 59;
       
    45 const TInt KHalfWidthIndex = 0;
       
    46 const TInt KFullWidthIndex = 1;
       
    47 const TInt KFullWidthVoicableKatakanaRange = 23;
       
    48 const TInt KFullWidthSemiVoicableKatakanaRange = 5;
       
    49 const TInt KHalfWidthSpecialCharRange = 21;
       
    50 
       
    51 const TText KHalfWidthKatakanaVoicedSoundMark     = 0xff9e;
       
    52 const TText KHalfWidthKatakanaSemiVoicedSoundMark = 0xff9f;
       
    53 
       
    54 // The following Full-width (semi-)voiced markers are
       
    55 // *also* considered Hiragana, per Unicode spec.
       
    56 const TText KFullWidthKatakanaVoicedSoundMark     = 0x309b;
       
    57 const TText KFullWidthKatakanaSemiVoicedSoundMark = 0x309c;
       
    58 
       
    59 const TText KHalfWidthKatakanaLowerBound = 0xff65;
       
    60 const TText KHalfWidthKatakanaUpperBound = 0xff9f;
       
    61 const TText KFullWidthKatakanaLowerBound = 0x30a0;
       
    62 const TText KFullWidthKatakanaUpperBound = 0x30ff;
       
    63 
       
    64 const TText KCJKUnifiedIdiographLowerBound = 0x4e00;
       
    65 const TText KCJKUnifiedIdiographUpperBound = 0x9fa5;
       
    66 const TText KCJKUnifiedIdeographExtALowerBound = 0x3400;
       
    67 const TText KCJKUnifiedIdeographExtAUpperBound = 0x4dbf;
       
    68 
       
    69 const TText KHalfToFullWidthASCIIOffset = 0xfee0;
       
    70 const TText KHalfWidthASCIILowerBound = 0x0021; // Leaves out space (0x0020)
       
    71 const TText KHalfWidthASCIIUpperBound = 0x007e;
       
    72 const TText KFullWidthASCIILowerBound = 0xff01;
       
    73 const TText KFullWidthASCIIUpperBound = 0xff5e;
       
    74 
       
    75 const TUint KFullWidthHiraganaSmallA = 0x3041;
       
    76 const TUint KFullWidthHiraganaVU = 0x3094;
       
    77 const TUint KFullWidthHiraganaU = 0x3046;
       
    78 const TUint KFullWidthHiraganaVoicedSound = 0x309B;
       
    79 const TUint KFullWidthKatakanaSmallA = 0x30a1;
       
    80 const TUint KFullWidthKatakanaSmallVU = 0x30F4;
       
    81 
       
    82 
       
    83 // ============================== LOCAL CLASSES ================================
       
    84 
       
    85 /**
       
    86  *  This is an internal utility class used by the JPLangUtil class
       
    87  *  and is intended for encapsulation only.
       
    88  *
       
    89  *  @lib JPLangUtil.lib
       
    90  *  @since 2.6
       
    91  */
       
    92 class UnicodeTextUtil
       
    93     {
       
    94     public: // Query Functions
       
    95 
       
    96         /**
       
    97         * Determines if aUnicodeChar is a base Katakana that is capable
       
    98         * of being converted into either a Vioced or Semi-voiced Full-width
       
    99         * Katakana character.
       
   100         * If aSemiVoiced is true, then the check is only performed
       
   101         * for Semi-voiced conversion capability.
       
   102         *
       
   103         * @param aUnicodeChar The character to be tested.
       
   104         * @param aSemiVoiced  Whether or not the character is to be tested
       
   105         *                     as convertable to a Semi-voiced Full-width
       
   106         *                     Katakana, rather than just voiced.
       
   107         *
       
   108         * @return ETrue is the character is in fact convertable to either
       
   109         *         a voiced or semi-voiced fullwidth katakana character,
       
   110         *         depending on the aSemiVoiced flag.
       
   111         */
       
   112         static TBool IsFullWidthVoicedConvertableHalfWidthBaseKatakana
       
   113                              ( TText aUnicodeChar, TBool aSemiVoiced = EFalse );
       
   114 
       
   115         /**
       
   116         * Determines if aUnicodeChar is a  Vioced or Semi-voiced Full-width
       
   117         * Katakana character.
       
   118         * If aSemiVoiced is true, then the check is only performed
       
   119         * for Semi-voiced.
       
   120         *
       
   121         * @param aUnicodeChar The character to be tested.
       
   122         * @param aSemiVoiced  Whether or not the character is a Semi-voiced
       
   123         *                     Full-width Katakana, rather than just voiced.
       
   124         *
       
   125         * @return ETrue is the character is in fact a voiced or semi-voiced
       
   126         *         fullwidth katakana character, depending on the aSemiVoiced
       
   127         *         flag.
       
   128         */
       
   129         static TBool IsFullWidthVoicedKatakana( TText aUnicodeChar,
       
   130                                                 TBool aSemiVoiced = EFalse);
       
   131 
       
   132     public: // Conversion Functions
       
   133 
       
   134         /**
       
   135         * Converts one Katakana character from either Half to Full-width
       
   136         * or vice versa, depending on the direction specified by aDirection
       
   137         *
       
   138         * @param aDirection Direction to convert.
       
   139         * @param aKatakanaChar The character to convert.
       
   140         *
       
   141         * @return The opposite width Katakana character.
       
   142         */
       
   143         static TChar ConvertKatakanaChar( TConvDirection aDirection,
       
   144                                           TText aKatakanaChar );
       
   145 
       
   146         /**
       
   147         * Converts one voiced Katakana character from either Half to Full-width
       
   148         * or vice versa, depending on the direction specified by aDirection,
       
   149         * and appends the converted character to the descriptor aTarget.
       
   150         * In the case that it is from Full to Half-width, it is necessary to
       
   151         * convert it into a base-katakana + (semi-)voiced mark pair, thus
       
   152         * the necessity for passing in the TDes reference return type.
       
   153         * In the case of converting from Half to Full-width, it is only
       
   154         * necessary to pass in a base-katakana that has a (semi-)voiced
       
   155         * Full-width counterpart.
       
   156         *
       
   157         * @param aDirection Direction to convert.
       
   158         * @param aVoicedKatakana The character to convert.
       
   159         * @param aTarget The descriptor to append the converted character(s) to.
       
   160         * @param aSemiVoiced ETrue if performing a Semi-voiced conversion.
       
   161         *                    Default is EFalse.
       
   162         */
       
   163         static void ConvertVoicedKatakanaCharAndAppendToTarget(
       
   164                                                    TConvDirection aDirection,
       
   165                                                    TText aVoicedKatakana,
       
   166                                                    TDes& aTarget,
       
   167                                                    TBool aSemiVoiced = EFalse );
       
   168 
       
   169         /**
       
   170         * Converts all special characters *in-place* from either Half to
       
   171         * Full-width or vice versa, depending on the direction specified
       
   172         * by aDirection
       
   173         *
       
   174         * @param aDirection Direction to convert.
       
   175         * @param aUnicodeText The character to convert.
       
   176         *
       
   177         * @return The number of converted special characters.
       
   178         */
       
   179         static TInt ConvertSpecialCharactersInPlace( TConvDirection aDirection,
       
   180                                                      TDes16& aUnicodeText );
       
   181 
       
   182         /**
       
   183         * Converts all ASCII *in-place* from either Half to
       
   184         * Full-width or vice versa, depending on the direction specified
       
   185         * by aDirection
       
   186         *
       
   187         * @param aDirection Direction to convert.
       
   188         * @param aUnicodeText The character to convert.
       
   189         *
       
   190         * @return The number of converted ASCII-range characters.
       
   191         */
       
   192         static TInt ConvertASCIIInPlace( TConvDirection aDirection,
       
   193                                          TDes16& aUnicodeText );
       
   194     };
       
   195 
       
   196 // ============================= LOCAL FUNCTIONS ===============================
       
   197 
       
   198 // -----------------------------------------------------------------------------
       
   199 // UnicodeTextUtil::IsFullWidthVoicedConvertableHalfWidthBaseKatakana
       
   200 // Determines if aUnicodeChar is a base Katakana that is capable
       
   201 // of being converted into either a Vioced or Semi-voiced
       
   202 // Full-width character.
       
   203 // If aSemiVoiced is true, then the check is only performed
       
   204 // for Semi-voiced conversion capability.
       
   205 // Returns: ETrue if it is convertable.
       
   206 // -----------------------------------------------------------------------------
       
   207 //
       
   208 TBool UnicodeTextUtil::IsFullWidthVoicedConvertableHalfWidthBaseKatakana
       
   209                                        ( TText aUnicodeChar, TBool aSemiVoiced )
       
   210     {
       
   211     if( aSemiVoiced )
       
   212         {
       
   213         return ( aUnicodeChar >= 0xff8a && aUnicodeChar <= 0xff8e );
       
   214         }
       
   215     else
       
   216         {
       
   217         return ( ( aUnicodeChar == 0xff73 ) ||
       
   218                  ( aUnicodeChar >= 0xff76 && aUnicodeChar <= 0xff7f ) ||
       
   219                  ( aUnicodeChar >= 0xff80 && aUnicodeChar <= 0xff84 ) ||
       
   220                  ( aUnicodeChar >= 0xff8a && aUnicodeChar <= 0xff8e ) ||
       
   221                  ( aUnicodeChar == 0xff9c ) ||
       
   222                  ( aUnicodeChar == 0xff66 ) );
       
   223         }
       
   224     }
       
   225 
       
   226 // -----------------------------------------------------------------------------
       
   227 // UnicodeTextUtil::IsFullWidthVoicedKatakana
       
   228 // Determines if aUnicodeChar is Full-width Katakana.
       
   229 // Returns: ETrue if it is Full-width Katakana.
       
   230 // -----------------------------------------------------------------------------
       
   231 //
       
   232 TBool UnicodeTextUtil::IsFullWidthVoicedKatakana( TText aUnicodeChar,
       
   233                                                   TBool aSemiVoiced )
       
   234     {
       
   235     const TInt voicableRange( aSemiVoiced ?
       
   236                               KFullWidthSemiVoicableKatakanaRange :
       
   237                               KFullWidthVoicableKatakanaRange );
       
   238     const TText* const (*voicedTable) = aSemiVoiced ?
       
   239                               KHalfWidthBaseToFullWidthSemiVoicedKatakanaTable :
       
   240                               KHalfWidthBaseToFullWidthVoicedKatakanaTable;
       
   241     for( TInt i( 0 ); i < voicableRange; ++i )
       
   242         {
       
   243         if( aUnicodeChar == voicedTable[i][KFullWidthIndex] )
       
   244             {
       
   245             return ETrue;
       
   246             }
       
   247         }
       
   248     return EFalse;
       
   249     }
       
   250 
       
   251 // -----------------------------------------------------------------------------
       
   252 // UnicodeTextUtil::ConvertKatakanaChar
       
   253 // Converts one Katakana Char in the direction specified by aDirection.
       
   254 // Assumes aKatakanaChar is within range.
       
   255 // Returns: A TText containing either the varient character or the character
       
   256 //          itself, in the case there is no conversion.
       
   257 // -----------------------------------------------------------------------------
       
   258 //
       
   259 TChar UnicodeTextUtil::ConvertKatakanaChar( TConvDirection aDirection,
       
   260                                             TText aKatakanaChar )
       
   261     {
       
   262     __ASSERT_DEBUG(
       
   263         JPLangUtil::IsKatakana( aKatakanaChar ) &&
       
   264         !IsFullWidthVoicedKatakana( aKatakanaChar ),
       
   265         User::Panic( KJPLangUtilPanic, EErrNotKatakana )
       
   266     );
       
   267     TChar convChar( aKatakanaChar );
       
   268     const TInt directionIndex( ( aDirection == EHalfToFullWidth ) ?
       
   269                                    KHalfWidthIndex : KFullWidthIndex );
       
   270     for( TInt i( 0 ); i < KHalfWidthKatakanaRange; ++i )
       
   271         {
       
   272         if( aKatakanaChar ==
       
   273                 KHalfToFullWidthKatakanaCharTable[i][directionIndex] )
       
   274             {
       
   275             convChar = KHalfToFullWidthKatakanaCharTable[i][!directionIndex];
       
   276             break;
       
   277             }
       
   278         }
       
   279     return convChar;
       
   280     }
       
   281 
       
   282 // -----------------------------------------------------------------------------
       
   283 // UnicodeTextUtil::ConvertVoicedKatakanaChar
       
   284 // Converts one Voiced Katakana Char in the direction specified by aDirection,
       
   285 // and appends to the descriptor, aTarget.
       
   286 // If aSemiVoiced is ETrue, then the code point is converted to the Semi-voiced
       
   287 // variant.
       
   288 // Assumes aVoicedKatakana is within range.
       
   289 // -----------------------------------------------------------------------------
       
   290 //
       
   291 void UnicodeTextUtil::ConvertVoicedKatakanaCharAndAppendToTarget(
       
   292                                                       TConvDirection aDirection,
       
   293                                                       TText aVoicedKatakana,
       
   294                                                       TDes& aTarget,
       
   295                                                       TBool aSemiVoiced )
       
   296     {
       
   297     __ASSERT_DEBUG(
       
   298         IsFullWidthVoicedConvertableHalfWidthBaseKatakana( aVoicedKatakana ) ||
       
   299         IsFullWidthVoicedKatakana( aVoicedKatakana, aSemiVoiced ),
       
   300         User::Panic( KJPLangUtilPanic, EErrNotVoicedKatakana )
       
   301     );
       
   302 
       
   303     const TInt  voicableRange( aSemiVoiced ?
       
   304                                KFullWidthSemiVoicableKatakanaRange :
       
   305                                KFullWidthVoicableKatakanaRange );
       
   306     const TText* const (*voicedTable) = aSemiVoiced ?
       
   307                               KHalfWidthBaseToFullWidthSemiVoicedKatakanaTable :
       
   308                               KHalfWidthBaseToFullWidthVoicedKatakanaTable;
       
   309     if( aDirection == EHalfToFullWidth )
       
   310         {
       
   311         // In the case of Half Width, only the base character is needed for
       
   312         // the conversion
       
   313         for( TInt i( 0 ); i < voicableRange; ++i )
       
   314             {
       
   315             if( aVoicedKatakana == voicedTable[i][KHalfWidthIndex] )
       
   316                 {
       
   317                 const TChar uniChar( voicedTable[i][KFullWidthIndex] );
       
   318                 aTarget.Append( uniChar );
       
   319                 break;
       
   320                 }
       
   321             }
       
   322         }
       
   323     else
       
   324         {
       
   325         for( TInt i( 0 ); i < voicableRange; ++i )
       
   326             {
       
   327             if( aVoicedKatakana == voicedTable[i][KFullWidthIndex] )
       
   328                 {
       
   329                 const TChar uniChar( voicedTable[i][KHalfWidthIndex] );
       
   330                 aTarget.Append( uniChar );
       
   331                 break;
       
   332                 }
       
   333             }
       
   334         const TChar voicedSoundMark( aSemiVoiced ?
       
   335                                      KHalfWidthKatakanaSemiVoicedSoundMark :
       
   336                                      KHalfWidthKatakanaVoicedSoundMark );
       
   337         aTarget.Append( voicedSoundMark );
       
   338         }
       
   339     }
       
   340 
       
   341 // -----------------------------------------------------------------------------
       
   342 // UnicodeTextUtil::ConvertSpecialCharactersInPlace
       
   343 // Converts all special characters in the aUnicodeText descriptor in-place
       
   344 // that have both Full and Half-width variants.
       
   345 // Conversion occurs in the direction specified by aDirection.
       
   346 // Returns: The total number of characters converted.
       
   347 // -----------------------------------------------------------------------------
       
   348 //
       
   349 TInt UnicodeTextUtil::ConvertSpecialCharactersInPlace
       
   350                              ( TConvDirection aDirection, TDes16& aUnicodeText )
       
   351     {
       
   352     TInt totalConverted( 0 );
       
   353     const TInt directionIndex( ( aDirection == EHalfToFullWidth ) ?
       
   354                                  KHalfWidthIndex : KFullWidthIndex );
       
   355     for( TInt i( 0 ); i < aUnicodeText.Length(); ++i )
       
   356         {
       
   357         const TText uniChar( aUnicodeText[i] );
       
   358         for( TInt j( 0 ); j < KHalfWidthSpecialCharRange; ++j )
       
   359             {
       
   360             if( uniChar == KHalfToFullWidthSpecialCharTable[j][directionIndex] )
       
   361                 {
       
   362                 aUnicodeText[i] =
       
   363                     KHalfToFullWidthSpecialCharTable[j][!directionIndex];
       
   364                 totalConverted++;
       
   365                 break;
       
   366                 }
       
   367             }
       
   368         }
       
   369     return totalConverted;
       
   370     }
       
   371 
       
   372 // -----------------------------------------------------------------------------
       
   373 // UnicodeTextUtil::ConvertASCIIInPlace
       
   374 // Converts all ASCII *in-place* from either Half to Full-width or vice versa,
       
   375 // depending on the direction specified by aDirection.
       
   376 // Returns: The total number of characters converted.
       
   377 // -----------------------------------------------------------------------------
       
   378 //
       
   379 TInt UnicodeTextUtil::ConvertASCIIInPlace( TConvDirection aDirection,
       
   380                                            TDes16& aUnicodeText )
       
   381     {
       
   382     TInt totalConverted( 0 );
       
   383     TText lowerBound( ( aDirection == EHalfToFullWidth ) ?
       
   384                         KHalfWidthASCIILowerBound :
       
   385                         KFullWidthASCIILowerBound );
       
   386     TText upperBound( ( aDirection == EHalfToFullWidth ) ?
       
   387                         KHalfWidthASCIIUpperBound :
       
   388                         KFullWidthASCIIUpperBound );
       
   389     TInt offset( ( aDirection == EHalfToFullWidth ) ?
       
   390                    KHalfToFullWidthASCIIOffset :
       
   391                    -KHalfToFullWidthASCIIOffset );
       
   392     for( TInt i( 0 ); i < aUnicodeText.Length(); ++i )
       
   393         {
       
   394         const TText uniChar( aUnicodeText[i] );
       
   395         if( uniChar >= lowerBound && uniChar <= upperBound )
       
   396             {
       
   397             TText convertedChar( static_cast<TText>( uniChar + offset ) );
       
   398             aUnicodeText[i] = convertedChar;
       
   399             totalConverted++;
       
   400             }
       
   401         }
       
   402     return totalConverted;
       
   403     }
       
   404 
       
   405 // EXPORTED FUNCTIONS
       
   406 
       
   407 // ============================ MEMBER FUNCTIONS ===============================
       
   408 
       
   409 // -----------------------------------------------------------------------------
       
   410 // JPLangUtil::ConvertHalfToFullWidth
       
   411 // Converts all Half-width conformant text (including ASCII, Special Characters
       
   412 // and Katakana) found in aUnicodeSource to their Full-width counterparts and
       
   413 // places the resulting text into aUnicodeTarget.
       
   414 // (detailed information about the parameters and return values can be found
       
   415 //  in the header file)
       
   416 // -----------------------------------------------------------------------------
       
   417 //
       
   418 EXPORT_C TInt JPLangUtil::ConvertHalfToFullWidth( const TDesC16& aUnicodeSource,
       
   419                                                   TDes16& aUnicodeTarget )
       
   420     {
       
   421     TInt totalConverted( 0 );
       
   422     // Special Characters are handled in the Katakana conversion...
       
   423     totalConverted =  ConvertHalfToFullWidthKatakana( aUnicodeSource,
       
   424                                                       aUnicodeTarget );
       
   425     totalConverted += UnicodeTextUtil::ConvertASCIIInPlace( EHalfToFullWidth,
       
   426                                                             aUnicodeTarget );
       
   427     return totalConverted;
       
   428     }
       
   429 
       
   430 // -----------------------------------------------------------------------------
       
   431 // JPLangUtil::ConvertFullToHalfWidth
       
   432 // Converts all Full-width conformant text found in aUnicodeSource to their
       
   433 // Full-width counterparts and places the resulting text into aUnicodeTarget.
       
   434 // Only those characters with existing Half-width variants are converted. There
       
   435 // will be a 2-for-1 conversion for each Full-width Voiced and Semi-voiced
       
   436 // Katakana character.
       
   437 // (detailed information about the parameters and return values can be found in
       
   438 // the header file)
       
   439 // -----------------------------------------------------------------------------
       
   440 //
       
   441 EXPORT_C TInt JPLangUtil::ConvertFullToHalfWidth( const TDesC16& aUnicodeSource,
       
   442                                                   TDes16& aUnicodeTarget )
       
   443     {
       
   444     TInt totalConverted( 0 );
       
   445     // Special Characters are handled in the Katakana conversion...
       
   446     totalConverted =  ConvertFullToHalfWidthKatakana( aUnicodeSource,
       
   447                                                       aUnicodeTarget );
       
   448     totalConverted += UnicodeTextUtil::ConvertASCIIInPlace( EFullToHalfWidth,
       
   449                                                             aUnicodeTarget );
       
   450     return totalConverted;
       
   451     }
       
   452 
       
   453 // -----------------------------------------------------------------------------
       
   454 // JPLangUtil::ConvertHalfToFullWidthKatakana
       
   455 // Converts Half-width Katakana and Special Character text found in
       
   456 // aUnicodeSource to their Full-width counterparts and places the resulting text
       
   457 // into aUnicodeTarget.
       
   458 // (detailed information about the parameters and return values can be found in
       
   459 // the header file)
       
   460 // -----------------------------------------------------------------------------
       
   461 //
       
   462 EXPORT_C TInt JPLangUtil::ConvertHalfToFullWidthKatakana
       
   463                        ( const TDesC16& aUnicodeSource, TDes16& aUnicodeTarget )
       
   464     {
       
   465     TInt totalConverted( 0 );
       
   466     const TInt length( aUnicodeSource.Length() );
       
   467     if( length > aUnicodeTarget.MaxLength() )
       
   468         {
       
   469         return KErrTooBig;
       
   470         }
       
   471     aUnicodeTarget.Zero();
       
   472     for( TInt i( 0 ); i < length; ++i )
       
   473         {
       
   474         const TText uniChar( aUnicodeSource[i] );
       
   475         // Check if the next character is a Half Width Katakana (Semi-)Voiced
       
   476         // Sound Mark and if the current character + the voiced sound mark have
       
   477         // a Full Width counterpart
       
   478         if( i + 1 < length )
       
   479             {
       
   480             const TBool isVoiced(
       
   481             ( UnicodeTextUtil::IsFullWidthVoicedConvertableHalfWidthBaseKatakana
       
   482                   ( uniChar ) &&
       
   483               ( aUnicodeSource[i + 1] == KHalfWidthKatakanaVoicedSoundMark )
       
   484             ) );
       
   485 
       
   486             const TBool isSemiVoiced(
       
   487             ( UnicodeTextUtil::IsFullWidthVoicedConvertableHalfWidthBaseKatakana
       
   488                   ( uniChar, ETrue ) &&
       
   489               ( aUnicodeSource[i + 1] == KHalfWidthKatakanaSemiVoicedSoundMark )
       
   490             ) );
       
   491 
       
   492             if( isVoiced || isSemiVoiced )
       
   493                 {
       
   494                 UnicodeTextUtil::ConvertVoicedKatakanaCharAndAppendToTarget(
       
   495                     EHalfToFullWidth,
       
   496                     uniChar,
       
   497                     aUnicodeTarget,
       
   498                     isSemiVoiced
       
   499                 );
       
   500                 i++; // Skip the (semi-)voice marker
       
   501                 totalConverted++;
       
   502                 continue;
       
   503                 }
       
   504             }
       
   505         // If not, then just convert directly if in range
       
   506         if( uniChar >= KHalfWidthKatakanaLowerBound &&
       
   507             uniChar <= KHalfWidthKatakanaUpperBound )
       
   508             {
       
   509             aUnicodeTarget.Append(
       
   510                 UnicodeTextUtil::ConvertKatakanaChar( EHalfToFullWidth,
       
   511                                                       uniChar )
       
   512             );
       
   513             totalConverted++;
       
   514             }
       
   515         // Else this is not Half Width Katakana, so copy directly...
       
   516         else
       
   517             {
       
   518             const TChar uniCharacter( uniChar );
       
   519             aUnicodeTarget.Append( uniCharacter );
       
   520             }
       
   521         }
       
   522 
       
   523     // Now handle special characters
       
   524     // This logic may be moved into this function to avoid another
       
   525     // loop over the text.
       
   526     totalConverted +=
       
   527         UnicodeTextUtil::ConvertSpecialCharactersInPlace( EHalfToFullWidth,
       
   528                                                           aUnicodeTarget );
       
   529 
       
   530     return totalConverted;
       
   531     }
       
   532 
       
   533 // -----------------------------------------------------------------------------
       
   534 // JPLangUtil::ConvertFullToHalfWidthKatakana
       
   535 // Converts Full-width Katakana and Special Character text found in
       
   536 // aUnicodeSource to their Half-width counterparts and places the resulting text
       
   537 // into aUnicodeTarget. There will be a 2-for-1 conversion for each Full-width
       
   538 // Voiced and Semi-voiced Katakana character.
       
   539 // (detailed information about the parameters and return values can be found in
       
   540 // the header file)
       
   541 // -----------------------------------------------------------------------------
       
   542 //
       
   543 EXPORT_C TInt JPLangUtil::ConvertFullToHalfWidthKatakana
       
   544                        ( const TDesC16& aUnicodeSource, TDes16& aUnicodeTarget )
       
   545     {
       
   546     TInt totalConverted( 0 );
       
   547     const TInt length( aUnicodeSource.Length() );
       
   548     const TInt maxLength( aUnicodeTarget.MaxLength() );
       
   549     if( length > maxLength )
       
   550         {
       
   551         return KErrTooBig;
       
   552         }
       
   553     aUnicodeTarget.Zero();
       
   554     for( TInt i( 0 ); i < length; ++i )
       
   555         {
       
   556         const TText uniChar( aUnicodeSource[i] );
       
   557         // First check if this is this Full Width Katakana
       
   558         if( ( uniChar >= KFullWidthKatakanaLowerBound &&
       
   559               uniChar <= KFullWidthKatakanaUpperBound ) ||
       
   560             ( uniChar == KFullWidthKatakanaVoicedSoundMark ||
       
   561               uniChar == KFullWidthKatakanaSemiVoicedSoundMark ) )
       
   562             {
       
   563             // Then check if it is (Semi-)Voiced and convert it properly
       
   564             const TBool isVoiced(
       
   565                 UnicodeTextUtil::IsFullWidthVoicedKatakana( uniChar )
       
   566             );
       
   567             const TBool isSemiVoiced(
       
   568                 UnicodeTextUtil::IsFullWidthVoicedKatakana( uniChar, ETrue )
       
   569             );
       
   570             if( isVoiced || isSemiVoiced )
       
   571                 {
       
   572                 if( aUnicodeTarget.Length() + 2 > maxLength )
       
   573                     {
       
   574                     // This descriptor can't hold the new data
       
   575                     aUnicodeTarget.Zero();
       
   576                     return KErrTooBig;
       
   577                     }
       
   578                 UnicodeTextUtil::ConvertVoicedKatakanaCharAndAppendToTarget(
       
   579                     EFullToHalfWidth,
       
   580                     uniChar,
       
   581                     aUnicodeTarget,
       
   582                     isSemiVoiced
       
   583                 );
       
   584                 totalConverted++;
       
   585                 }
       
   586             else
       
   587                 {
       
   588                 if( aUnicodeTarget.Length() + 1 > maxLength )
       
   589                     {
       
   590                     // This descriptor can't hold the new data
       
   591                     aUnicodeTarget.Zero();
       
   592                     return KErrTooBig;
       
   593                     }
       
   594                 aUnicodeTarget.Append(
       
   595                     UnicodeTextUtil::ConvertKatakanaChar(
       
   596                         EFullToHalfWidth,
       
   597                         uniChar
       
   598                     )
       
   599                 );
       
   600                 totalConverted++;
       
   601                 }
       
   602             }
       
   603         // This is not Full Width Katakana, so copy directly...
       
   604         else
       
   605             {
       
   606             if( aUnicodeTarget.Length() + 1 > maxLength )
       
   607                 {
       
   608                 // This descriptor can't hold the new data
       
   609                 aUnicodeTarget.Zero();
       
   610                 return KErrTooBig;
       
   611                 }
       
   612             const TChar uniCharacter( uniChar );
       
   613             aUnicodeTarget.Append( uniCharacter );
       
   614             }
       
   615         }
       
   616 
       
   617     // Now handle special characters
       
   618     // This logic may be moved into this function to avoid another loop over
       
   619     // the text
       
   620     totalConverted +=
       
   621         UnicodeTextUtil::ConvertSpecialCharactersInPlace( EFullToHalfWidth,
       
   622                                                           aUnicodeTarget );
       
   623 
       
   624     return totalConverted;
       
   625     }
       
   626 
       
   627 // -----------------------------------------------------------------------------
       
   628 // JPLangUtil::ConvertFullHiragnaToFullKatakana
       
   629 // Converts Full-width Hiragana and Special Character text found in
       
   630 // aUnicodeSource to their Full-width counterparts and places the
       
   631 // resulting text into aUnicodeTarget.
       
   632 // -----------------------------------------------------------------------------
       
   633 //
       
   634 EXPORT_C TInt JPLangUtil::ConvertFullHiragnaToFullKatakana
       
   635                        ( const TDesC16& aUnicodeSource, TDes16& aUnicodeTarget )
       
   636     {
       
   637     TInt totalConverted( 0 );
       
   638     const TInt length( aUnicodeSource.Length() );
       
   639     const TInt maxLength( aUnicodeTarget.MaxLength() );
       
   640     if( length > maxLength )
       
   641         {
       
   642         return KErrTooBig;
       
   643         }
       
   644 
       
   645     const TUint comp = KFullWidthKatakanaSmallA - KFullWidthHiraganaSmallA;
       
   646 
       
   647     aUnicodeTarget.Zero();
       
   648     for( TInt i( 0 ); i < length; ++i )
       
   649         {
       
   650         const TText uniChar( aUnicodeSource[i] );
       
   651         TText uniChar2(0);
       
   652         if (i + 1 < length)
       
   653             {
       
   654             uniChar2 = aUnicodeSource[i+1];
       
   655             }
       
   656         // First check if this is this Full Width Katakana
       
   657         if (KFullWidthHiraganaSmallA <= uniChar && uniChar <= KFullWidthHiraganaVU)
       
   658             {
       
   659             if (uniChar == KFullWidthHiraganaU
       
   660              && uniChar2 == KFullWidthHiraganaVoicedSound)
       
   661                 {
       
   662                 aUnicodeTarget.Append(KFullWidthKatakanaSmallVU);
       
   663                 totalConverted++;
       
   664                 i++;
       
   665                 }
       
   666             else
       
   667                 {
       
   668                 TUint katakana = uniChar + comp;
       
   669                 if (IsKatakana(katakana))
       
   670                     {
       
   671                     aUnicodeTarget.Append(katakana);
       
   672                     totalConverted++;
       
   673                     }
       
   674                 }
       
   675             }
       
   676         else
       
   677             {
       
   678             aUnicodeTarget.Append(uniChar);
       
   679             totalConverted++;
       
   680             }
       
   681         }
       
   682 
       
   683     // Now handle special characters
       
   684     // This logic may be moved into this function to avoid another loop over
       
   685     // the text
       
   686     totalConverted +=
       
   687         UnicodeTextUtil::ConvertSpecialCharactersInPlace( EFullToHalfWidth,
       
   688                                                           aUnicodeTarget );
       
   689 
       
   690     return totalConverted;
       
   691     }
       
   692 
       
   693 // -----------------------------------------------------------------------------
       
   694 // JPLangUtil::IsKatakana
       
   695 // Determines whether or not the character is Katakana
       
   696 // (detailed information about the parameters and return values can be found in
       
   697 // the header file)
       
   698 // -----------------------------------------------------------------------------
       
   699 //
       
   700 EXPORT_C TBool JPLangUtil::IsKatakana( const TText aUnicodeChar )
       
   701     {
       
   702     return ( ( aUnicodeChar >= KFullWidthKatakanaLowerBound &&
       
   703                aUnicodeChar <= KFullWidthKatakanaUpperBound ) ||
       
   704              ( aUnicodeChar >= KHalfWidthKatakanaLowerBound &&
       
   705                aUnicodeChar <= KHalfWidthKatakanaUpperBound ) ||
       
   706              ( aUnicodeChar == KFullWidthKatakanaVoicedSoundMark ||
       
   707                aUnicodeChar == KFullWidthKatakanaSemiVoicedSoundMark ) );
       
   708     }
       
   709 
       
   710 // -----------------------------------------------------------------------------
       
   711 // JPLangUtil::IsHiragana
       
   712 // Determines whether or not the character is Hiragana
       
   713 // (detailed information about the parameters and return values can be found in
       
   714 // the header file)
       
   715 // -----------------------------------------------------------------------------
       
   716 //
       
   717 EXPORT_C TBool JPLangUtil::IsHiragana( const TText aUnicodeChar )
       
   718     {
       
   719     return ( ( aUnicodeChar >= 0x3041 && aUnicodeChar <= 0x3096 ) ||
       
   720              ( aUnicodeChar >= 0x3099 && aUnicodeChar <= 0x309f ) );
       
   721     }
       
   722 
       
   723 // -----------------------------------------------------------------------------
       
   724 // JPLangUtil::IsKanji
       
   725 // Determines whether or not the character is a CJK Unified Ideograph (ExtA)
       
   726 // (detailed information about the parameters and return values can be found in
       
   727 // the header file)
       
   728 // -----------------------------------------------------------------------------
       
   729 //
       
   730 EXPORT_C TBool JPLangUtil::IsKanji( const TText aUnicodeChar )
       
   731     {
       
   732     return( ( aUnicodeChar >= KCJKUnifiedIdiographLowerBound &&
       
   733               aUnicodeChar <= KCJKUnifiedIdiographUpperBound ) ||
       
   734             ( aUnicodeChar >= KCJKUnifiedIdeographExtALowerBound &&
       
   735               aUnicodeChar <= KCJKUnifiedIdeographExtAUpperBound ) );
       
   736     }
       
   737 
       
   738 // -----------------------------------------------------------------------------
       
   739 // JPLangUtil::IsHalfWidth
       
   740 // Determines whether or not the character is UNICODE defined Half-width.
       
   741 // (detailed information about the parameters and return values can be found in
       
   742 // the header file)
       
   743 // -----------------------------------------------------------------------------
       
   744 //
       
   745 EXPORT_C TBool JPLangUtil::IsHalfWidth( const TText aUnicodeChar )
       
   746     {
       
   747     return // HW Katakana
       
   748            ( ( aUnicodeChar >= 0xff61 && aUnicodeChar <= 0xff9f ) ||
       
   749            // ASCII
       
   750              ( aUnicodeChar >= 0x0020 && aUnicodeChar <= 0x007e ) ||
       
   751            // Special Characters
       
   752              ( aUnicodeChar == 0x00a2 || aUnicodeChar == 0x00a3 ||
       
   753                aUnicodeChar == 0x00a5 || aUnicodeChar == 0x00a6 ||
       
   754                aUnicodeChar == 0x00a9 || aUnicodeChar == 0x00ac ||
       
   755                aUnicodeChar == 0x00af || aUnicodeChar == 0x2985 ||
       
   756                aUnicodeChar == 0x2986 ) ||
       
   757            // HW Symbol Variants
       
   758              ( aUnicodeChar >= 0xffe8 && aUnicodeChar <= 0xffee ) );
       
   759     }
       
   760 
       
   761 // -----------------------------------------------------------------------------
       
   762 // JPLangUtil::IsFullWidth
       
   763 // Determines whether or not the character is UNICODE defined Full-width.
       
   764 // Essentially, all code values that are not Half-width.
       
   765 // (detailed information about the parameters and return values can be found in
       
   766 // the header file)
       
   767 // -----------------------------------------------------------------------------
       
   768 //
       
   769 EXPORT_C TBool JPLangUtil::IsFullWidth( const TText aUnicodeChar )
       
   770     {
       
   771         return !IsHalfWidth( aUnicodeChar );
       
   772     }
       
   773 
       
   774 // End of File