os/textandloc/textandlocutils/jplangutil/src/jplangutil.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/textandloc/textandlocutils/jplangutil/src/jplangutil.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,774 @@
     1.4 +/*
     1.5 +* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
     1.6 +* All rights reserved.
     1.7 +* This component and the accompanying materials are made available
     1.8 +* under the terms of the License "Eclipse Public License v1.0"
     1.9 +* which accompanies this distribution, and is available
    1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.11 +*
    1.12 +* Initial Contributors:
    1.13 +* Nokia Corporation - initial contribution.
    1.14 +*
    1.15 +* Contributors:
    1.16 +*
    1.17 +* Description: 
    1.18 +*     A utility for providing Japanese Language-specific (UNICODE) functions.
    1.19 +*
    1.20 +*
    1.21 +*/
    1.22 +
    1.23 +
    1.24 +// INCLUDES FILES
    1.25 +#include "jplangutil.h"
    1.26 +#include "jplangutil.tables.h"
    1.27 +
    1.28 +// LOCAL DEFINES
    1.29 +
    1.30 +// LOCAL CONSTANTS AND ENUMS
    1.31 +
    1.32 +#if defined(_DEBUG)
    1.33 +_LIT( KJPLangUtilPanic, "JPLangUtil" );
    1.34 +enum TJPLangUtilPanicCodes
    1.35 +    {
    1.36 +    EErrNotKatakana = 0x777,
    1.37 +    EErrNotVoicedKatakana
    1.38 +    };
    1.39 +#endif
    1.40 +
    1.41 +enum TConvDirection
    1.42 +    {
    1.43 +    EHalfToFullWidth,
    1.44 +    EFullToHalfWidth
    1.45 +    };
    1.46 +
    1.47 +const TInt KHalfWidthKatakanaRange = 59;
    1.48 +const TInt KHalfWidthIndex = 0;
    1.49 +const TInt KFullWidthIndex = 1;
    1.50 +const TInt KFullWidthVoicableKatakanaRange = 23;
    1.51 +const TInt KFullWidthSemiVoicableKatakanaRange = 5;
    1.52 +const TInt KHalfWidthSpecialCharRange = 21;
    1.53 +
    1.54 +const TText KHalfWidthKatakanaVoicedSoundMark     = 0xff9e;
    1.55 +const TText KHalfWidthKatakanaSemiVoicedSoundMark = 0xff9f;
    1.56 +
    1.57 +// The following Full-width (semi-)voiced markers are
    1.58 +// *also* considered Hiragana, per Unicode spec.
    1.59 +const TText KFullWidthKatakanaVoicedSoundMark     = 0x309b;
    1.60 +const TText KFullWidthKatakanaSemiVoicedSoundMark = 0x309c;
    1.61 +
    1.62 +const TText KHalfWidthKatakanaLowerBound = 0xff65;
    1.63 +const TText KHalfWidthKatakanaUpperBound = 0xff9f;
    1.64 +const TText KFullWidthKatakanaLowerBound = 0x30a0;
    1.65 +const TText KFullWidthKatakanaUpperBound = 0x30ff;
    1.66 +
    1.67 +const TText KCJKUnifiedIdiographLowerBound = 0x4e00;
    1.68 +const TText KCJKUnifiedIdiographUpperBound = 0x9fa5;
    1.69 +const TText KCJKUnifiedIdeographExtALowerBound = 0x3400;
    1.70 +const TText KCJKUnifiedIdeographExtAUpperBound = 0x4dbf;
    1.71 +
    1.72 +const TText KHalfToFullWidthASCIIOffset = 0xfee0;
    1.73 +const TText KHalfWidthASCIILowerBound = 0x0021; // Leaves out space (0x0020)
    1.74 +const TText KHalfWidthASCIIUpperBound = 0x007e;
    1.75 +const TText KFullWidthASCIILowerBound = 0xff01;
    1.76 +const TText KFullWidthASCIIUpperBound = 0xff5e;
    1.77 +
    1.78 +const TUint KFullWidthHiraganaSmallA = 0x3041;
    1.79 +const TUint KFullWidthHiraganaVU = 0x3094;
    1.80 +const TUint KFullWidthHiraganaU = 0x3046;
    1.81 +const TUint KFullWidthHiraganaVoicedSound = 0x309B;
    1.82 +const TUint KFullWidthKatakanaSmallA = 0x30a1;
    1.83 +const TUint KFullWidthKatakanaSmallVU = 0x30F4;
    1.84 +
    1.85 +
    1.86 +// ============================== LOCAL CLASSES ================================
    1.87 +
    1.88 +/**
    1.89 + *  This is an internal utility class used by the JPLangUtil class
    1.90 + *  and is intended for encapsulation only.
    1.91 + *
    1.92 + *  @lib JPLangUtil.lib
    1.93 + *  @since 2.6
    1.94 + */
    1.95 +class UnicodeTextUtil
    1.96 +    {
    1.97 +    public: // Query Functions
    1.98 +
    1.99 +        /**
   1.100 +        * Determines if aUnicodeChar is a base Katakana that is capable
   1.101 +        * of being converted into either a Vioced or Semi-voiced Full-width
   1.102 +        * Katakana character.
   1.103 +        * If aSemiVoiced is true, then the check is only performed
   1.104 +        * for Semi-voiced conversion capability.
   1.105 +        *
   1.106 +        * @param aUnicodeChar The character to be tested.
   1.107 +        * @param aSemiVoiced  Whether or not the character is to be tested
   1.108 +        *                     as convertable to a Semi-voiced Full-width
   1.109 +        *                     Katakana, rather than just voiced.
   1.110 +        *
   1.111 +        * @return ETrue is the character is in fact convertable to either
   1.112 +        *         a voiced or semi-voiced fullwidth katakana character,
   1.113 +        *         depending on the aSemiVoiced flag.
   1.114 +        */
   1.115 +        static TBool IsFullWidthVoicedConvertableHalfWidthBaseKatakana
   1.116 +                             ( TText aUnicodeChar, TBool aSemiVoiced = EFalse );
   1.117 +
   1.118 +        /**
   1.119 +        * Determines if aUnicodeChar is a  Vioced or Semi-voiced Full-width
   1.120 +        * Katakana character.
   1.121 +        * If aSemiVoiced is true, then the check is only performed
   1.122 +        * for Semi-voiced.
   1.123 +        *
   1.124 +        * @param aUnicodeChar The character to be tested.
   1.125 +        * @param aSemiVoiced  Whether or not the character is a Semi-voiced
   1.126 +        *                     Full-width Katakana, rather than just voiced.
   1.127 +        *
   1.128 +        * @return ETrue is the character is in fact a voiced or semi-voiced
   1.129 +        *         fullwidth katakana character, depending on the aSemiVoiced
   1.130 +        *         flag.
   1.131 +        */
   1.132 +        static TBool IsFullWidthVoicedKatakana( TText aUnicodeChar,
   1.133 +                                                TBool aSemiVoiced = EFalse);
   1.134 +
   1.135 +    public: // Conversion Functions
   1.136 +
   1.137 +        /**
   1.138 +        * Converts one Katakana character from either Half to Full-width
   1.139 +        * or vice versa, depending on the direction specified by aDirection
   1.140 +        *
   1.141 +        * @param aDirection Direction to convert.
   1.142 +        * @param aKatakanaChar The character to convert.
   1.143 +        *
   1.144 +        * @return The opposite width Katakana character.
   1.145 +        */
   1.146 +        static TChar ConvertKatakanaChar( TConvDirection aDirection,
   1.147 +                                          TText aKatakanaChar );
   1.148 +
   1.149 +        /**
   1.150 +        * Converts one voiced Katakana character from either Half to Full-width
   1.151 +        * or vice versa, depending on the direction specified by aDirection,
   1.152 +        * and appends the converted character to the descriptor aTarget.
   1.153 +        * In the case that it is from Full to Half-width, it is necessary to
   1.154 +        * convert it into a base-katakana + (semi-)voiced mark pair, thus
   1.155 +        * the necessity for passing in the TDes reference return type.
   1.156 +        * In the case of converting from Half to Full-width, it is only
   1.157 +        * necessary to pass in a base-katakana that has a (semi-)voiced
   1.158 +        * Full-width counterpart.
   1.159 +        *
   1.160 +        * @param aDirection Direction to convert.
   1.161 +        * @param aVoicedKatakana The character to convert.
   1.162 +        * @param aTarget The descriptor to append the converted character(s) to.
   1.163 +        * @param aSemiVoiced ETrue if performing a Semi-voiced conversion.
   1.164 +        *                    Default is EFalse.
   1.165 +        */
   1.166 +        static void ConvertVoicedKatakanaCharAndAppendToTarget(
   1.167 +                                                   TConvDirection aDirection,
   1.168 +                                                   TText aVoicedKatakana,
   1.169 +                                                   TDes& aTarget,
   1.170 +                                                   TBool aSemiVoiced = EFalse );
   1.171 +
   1.172 +        /**
   1.173 +        * Converts all special characters *in-place* from either Half to
   1.174 +        * Full-width or vice versa, depending on the direction specified
   1.175 +        * by aDirection
   1.176 +        *
   1.177 +        * @param aDirection Direction to convert.
   1.178 +        * @param aUnicodeText The character to convert.
   1.179 +        *
   1.180 +        * @return The number of converted special characters.
   1.181 +        */
   1.182 +        static TInt ConvertSpecialCharactersInPlace( TConvDirection aDirection,
   1.183 +                                                     TDes16& aUnicodeText );
   1.184 +
   1.185 +        /**
   1.186 +        * Converts all ASCII *in-place* from either Half to
   1.187 +        * Full-width or vice versa, depending on the direction specified
   1.188 +        * by aDirection
   1.189 +        *
   1.190 +        * @param aDirection Direction to convert.
   1.191 +        * @param aUnicodeText The character to convert.
   1.192 +        *
   1.193 +        * @return The number of converted ASCII-range characters.
   1.194 +        */
   1.195 +        static TInt ConvertASCIIInPlace( TConvDirection aDirection,
   1.196 +                                         TDes16& aUnicodeText );
   1.197 +    };
   1.198 +
   1.199 +// ============================= LOCAL FUNCTIONS ===============================
   1.200 +
   1.201 +// -----------------------------------------------------------------------------
   1.202 +// UnicodeTextUtil::IsFullWidthVoicedConvertableHalfWidthBaseKatakana
   1.203 +// Determines if aUnicodeChar is a base Katakana that is capable
   1.204 +// of being converted into either a Vioced or Semi-voiced
   1.205 +// Full-width character.
   1.206 +// If aSemiVoiced is true, then the check is only performed
   1.207 +// for Semi-voiced conversion capability.
   1.208 +// Returns: ETrue if it is convertable.
   1.209 +// -----------------------------------------------------------------------------
   1.210 +//
   1.211 +TBool UnicodeTextUtil::IsFullWidthVoicedConvertableHalfWidthBaseKatakana
   1.212 +                                       ( TText aUnicodeChar, TBool aSemiVoiced )
   1.213 +    {
   1.214 +    if( aSemiVoiced )
   1.215 +        {
   1.216 +        return ( aUnicodeChar >= 0xff8a && aUnicodeChar <= 0xff8e );
   1.217 +        }
   1.218 +    else
   1.219 +        {
   1.220 +        return ( ( aUnicodeChar == 0xff73 ) ||
   1.221 +                 ( aUnicodeChar >= 0xff76 && aUnicodeChar <= 0xff7f ) ||
   1.222 +                 ( aUnicodeChar >= 0xff80 && aUnicodeChar <= 0xff84 ) ||
   1.223 +                 ( aUnicodeChar >= 0xff8a && aUnicodeChar <= 0xff8e ) ||
   1.224 +                 ( aUnicodeChar == 0xff9c ) ||
   1.225 +                 ( aUnicodeChar == 0xff66 ) );
   1.226 +        }
   1.227 +    }
   1.228 +
   1.229 +// -----------------------------------------------------------------------------
   1.230 +// UnicodeTextUtil::IsFullWidthVoicedKatakana
   1.231 +// Determines if aUnicodeChar is Full-width Katakana.
   1.232 +// Returns: ETrue if it is Full-width Katakana.
   1.233 +// -----------------------------------------------------------------------------
   1.234 +//
   1.235 +TBool UnicodeTextUtil::IsFullWidthVoicedKatakana( TText aUnicodeChar,
   1.236 +                                                  TBool aSemiVoiced )
   1.237 +    {
   1.238 +    const TInt voicableRange( aSemiVoiced ?
   1.239 +                              KFullWidthSemiVoicableKatakanaRange :
   1.240 +                              KFullWidthVoicableKatakanaRange );
   1.241 +    const TText* const (*voicedTable) = aSemiVoiced ?
   1.242 +                              KHalfWidthBaseToFullWidthSemiVoicedKatakanaTable :
   1.243 +                              KHalfWidthBaseToFullWidthVoicedKatakanaTable;
   1.244 +    for( TInt i( 0 ); i < voicableRange; ++i )
   1.245 +        {
   1.246 +        if( aUnicodeChar == voicedTable[i][KFullWidthIndex] )
   1.247 +            {
   1.248 +            return ETrue;
   1.249 +            }
   1.250 +        }
   1.251 +    return EFalse;
   1.252 +    }
   1.253 +
   1.254 +// -----------------------------------------------------------------------------
   1.255 +// UnicodeTextUtil::ConvertKatakanaChar
   1.256 +// Converts one Katakana Char in the direction specified by aDirection.
   1.257 +// Assumes aKatakanaChar is within range.
   1.258 +// Returns: A TText containing either the varient character or the character
   1.259 +//          itself, in the case there is no conversion.
   1.260 +// -----------------------------------------------------------------------------
   1.261 +//
   1.262 +TChar UnicodeTextUtil::ConvertKatakanaChar( TConvDirection aDirection,
   1.263 +                                            TText aKatakanaChar )
   1.264 +    {
   1.265 +    __ASSERT_DEBUG(
   1.266 +        JPLangUtil::IsKatakana( aKatakanaChar ) &&
   1.267 +        !IsFullWidthVoicedKatakana( aKatakanaChar ),
   1.268 +        User::Panic( KJPLangUtilPanic, EErrNotKatakana )
   1.269 +    );
   1.270 +    TChar convChar( aKatakanaChar );
   1.271 +    const TInt directionIndex( ( aDirection == EHalfToFullWidth ) ?
   1.272 +                                   KHalfWidthIndex : KFullWidthIndex );
   1.273 +    for( TInt i( 0 ); i < KHalfWidthKatakanaRange; ++i )
   1.274 +        {
   1.275 +        if( aKatakanaChar ==
   1.276 +                KHalfToFullWidthKatakanaCharTable[i][directionIndex] )
   1.277 +            {
   1.278 +            convChar = KHalfToFullWidthKatakanaCharTable[i][!directionIndex];
   1.279 +            break;
   1.280 +            }
   1.281 +        }
   1.282 +    return convChar;
   1.283 +    }
   1.284 +
   1.285 +// -----------------------------------------------------------------------------
   1.286 +// UnicodeTextUtil::ConvertVoicedKatakanaChar
   1.287 +// Converts one Voiced Katakana Char in the direction specified by aDirection,
   1.288 +// and appends to the descriptor, aTarget.
   1.289 +// If aSemiVoiced is ETrue, then the code point is converted to the Semi-voiced
   1.290 +// variant.
   1.291 +// Assumes aVoicedKatakana is within range.
   1.292 +// -----------------------------------------------------------------------------
   1.293 +//
   1.294 +void UnicodeTextUtil::ConvertVoicedKatakanaCharAndAppendToTarget(
   1.295 +                                                      TConvDirection aDirection,
   1.296 +                                                      TText aVoicedKatakana,
   1.297 +                                                      TDes& aTarget,
   1.298 +                                                      TBool aSemiVoiced )
   1.299 +    {
   1.300 +    __ASSERT_DEBUG(
   1.301 +        IsFullWidthVoicedConvertableHalfWidthBaseKatakana( aVoicedKatakana ) ||
   1.302 +        IsFullWidthVoicedKatakana( aVoicedKatakana, aSemiVoiced ),
   1.303 +        User::Panic( KJPLangUtilPanic, EErrNotVoicedKatakana )
   1.304 +    );
   1.305 +
   1.306 +    const TInt  voicableRange( aSemiVoiced ?
   1.307 +                               KFullWidthSemiVoicableKatakanaRange :
   1.308 +                               KFullWidthVoicableKatakanaRange );
   1.309 +    const TText* const (*voicedTable) = aSemiVoiced ?
   1.310 +                              KHalfWidthBaseToFullWidthSemiVoicedKatakanaTable :
   1.311 +                              KHalfWidthBaseToFullWidthVoicedKatakanaTable;
   1.312 +    if( aDirection == EHalfToFullWidth )
   1.313 +        {
   1.314 +        // In the case of Half Width, only the base character is needed for
   1.315 +        // the conversion
   1.316 +        for( TInt i( 0 ); i < voicableRange; ++i )
   1.317 +            {
   1.318 +            if( aVoicedKatakana == voicedTable[i][KHalfWidthIndex] )
   1.319 +                {
   1.320 +                const TChar uniChar( voicedTable[i][KFullWidthIndex] );
   1.321 +                aTarget.Append( uniChar );
   1.322 +                break;
   1.323 +                }
   1.324 +            }
   1.325 +        }
   1.326 +    else
   1.327 +        {
   1.328 +        for( TInt i( 0 ); i < voicableRange; ++i )
   1.329 +            {
   1.330 +            if( aVoicedKatakana == voicedTable[i][KFullWidthIndex] )
   1.331 +                {
   1.332 +                const TChar uniChar( voicedTable[i][KHalfWidthIndex] );
   1.333 +                aTarget.Append( uniChar );
   1.334 +                break;
   1.335 +                }
   1.336 +            }
   1.337 +        const TChar voicedSoundMark( aSemiVoiced ?
   1.338 +                                     KHalfWidthKatakanaSemiVoicedSoundMark :
   1.339 +                                     KHalfWidthKatakanaVoicedSoundMark );
   1.340 +        aTarget.Append( voicedSoundMark );
   1.341 +        }
   1.342 +    }
   1.343 +
   1.344 +// -----------------------------------------------------------------------------
   1.345 +// UnicodeTextUtil::ConvertSpecialCharactersInPlace
   1.346 +// Converts all special characters in the aUnicodeText descriptor in-place
   1.347 +// that have both Full and Half-width variants.
   1.348 +// Conversion occurs in the direction specified by aDirection.
   1.349 +// Returns: The total number of characters converted.
   1.350 +// -----------------------------------------------------------------------------
   1.351 +//
   1.352 +TInt UnicodeTextUtil::ConvertSpecialCharactersInPlace
   1.353 +                             ( TConvDirection aDirection, TDes16& aUnicodeText )
   1.354 +    {
   1.355 +    TInt totalConverted( 0 );
   1.356 +    const TInt directionIndex( ( aDirection == EHalfToFullWidth ) ?
   1.357 +                                 KHalfWidthIndex : KFullWidthIndex );
   1.358 +    for( TInt i( 0 ); i < aUnicodeText.Length(); ++i )
   1.359 +        {
   1.360 +        const TText uniChar( aUnicodeText[i] );
   1.361 +        for( TInt j( 0 ); j < KHalfWidthSpecialCharRange; ++j )
   1.362 +            {
   1.363 +            if( uniChar == KHalfToFullWidthSpecialCharTable[j][directionIndex] )
   1.364 +                {
   1.365 +                aUnicodeText[i] =
   1.366 +                    KHalfToFullWidthSpecialCharTable[j][!directionIndex];
   1.367 +                totalConverted++;
   1.368 +                break;
   1.369 +                }
   1.370 +            }
   1.371 +        }
   1.372 +    return totalConverted;
   1.373 +    }
   1.374 +
   1.375 +// -----------------------------------------------------------------------------
   1.376 +// UnicodeTextUtil::ConvertASCIIInPlace
   1.377 +// Converts all ASCII *in-place* from either Half to Full-width or vice versa,
   1.378 +// depending on the direction specified by aDirection.
   1.379 +// Returns: The total number of characters converted.
   1.380 +// -----------------------------------------------------------------------------
   1.381 +//
   1.382 +TInt UnicodeTextUtil::ConvertASCIIInPlace( TConvDirection aDirection,
   1.383 +                                           TDes16& aUnicodeText )
   1.384 +    {
   1.385 +    TInt totalConverted( 0 );
   1.386 +    TText lowerBound( ( aDirection == EHalfToFullWidth ) ?
   1.387 +                        KHalfWidthASCIILowerBound :
   1.388 +                        KFullWidthASCIILowerBound );
   1.389 +    TText upperBound( ( aDirection == EHalfToFullWidth ) ?
   1.390 +                        KHalfWidthASCIIUpperBound :
   1.391 +                        KFullWidthASCIIUpperBound );
   1.392 +    TInt offset( ( aDirection == EHalfToFullWidth ) ?
   1.393 +                   KHalfToFullWidthASCIIOffset :
   1.394 +                   -KHalfToFullWidthASCIIOffset );
   1.395 +    for( TInt i( 0 ); i < aUnicodeText.Length(); ++i )
   1.396 +        {
   1.397 +        const TText uniChar( aUnicodeText[i] );
   1.398 +        if( uniChar >= lowerBound && uniChar <= upperBound )
   1.399 +            {
   1.400 +            TText convertedChar( static_cast<TText>( uniChar + offset ) );
   1.401 +            aUnicodeText[i] = convertedChar;
   1.402 +            totalConverted++;
   1.403 +            }
   1.404 +        }
   1.405 +    return totalConverted;
   1.406 +    }
   1.407 +
   1.408 +// EXPORTED FUNCTIONS
   1.409 +
   1.410 +// ============================ MEMBER FUNCTIONS ===============================
   1.411 +
   1.412 +// -----------------------------------------------------------------------------
   1.413 +// JPLangUtil::ConvertHalfToFullWidth
   1.414 +// Converts all Half-width conformant text (including ASCII, Special Characters
   1.415 +// and Katakana) found in aUnicodeSource to their Full-width counterparts and
   1.416 +// places the resulting text into aUnicodeTarget.
   1.417 +// (detailed information about the parameters and return values can be found
   1.418 +//  in the header file)
   1.419 +// -----------------------------------------------------------------------------
   1.420 +//
   1.421 +EXPORT_C TInt JPLangUtil::ConvertHalfToFullWidth( const TDesC16& aUnicodeSource,
   1.422 +                                                  TDes16& aUnicodeTarget )
   1.423 +    {
   1.424 +    TInt totalConverted( 0 );
   1.425 +    // Special Characters are handled in the Katakana conversion...
   1.426 +    totalConverted =  ConvertHalfToFullWidthKatakana( aUnicodeSource,
   1.427 +                                                      aUnicodeTarget );
   1.428 +    totalConverted += UnicodeTextUtil::ConvertASCIIInPlace( EHalfToFullWidth,
   1.429 +                                                            aUnicodeTarget );
   1.430 +    return totalConverted;
   1.431 +    }
   1.432 +
   1.433 +// -----------------------------------------------------------------------------
   1.434 +// JPLangUtil::ConvertFullToHalfWidth
   1.435 +// Converts all Full-width conformant text found in aUnicodeSource to their
   1.436 +// Full-width counterparts and places the resulting text into aUnicodeTarget.
   1.437 +// Only those characters with existing Half-width variants are converted. There
   1.438 +// will be a 2-for-1 conversion for each Full-width Voiced and Semi-voiced
   1.439 +// Katakana character.
   1.440 +// (detailed information about the parameters and return values can be found in
   1.441 +// the header file)
   1.442 +// -----------------------------------------------------------------------------
   1.443 +//
   1.444 +EXPORT_C TInt JPLangUtil::ConvertFullToHalfWidth( const TDesC16& aUnicodeSource,
   1.445 +                                                  TDes16& aUnicodeTarget )
   1.446 +    {
   1.447 +    TInt totalConverted( 0 );
   1.448 +    // Special Characters are handled in the Katakana conversion...
   1.449 +    totalConverted =  ConvertFullToHalfWidthKatakana( aUnicodeSource,
   1.450 +                                                      aUnicodeTarget );
   1.451 +    totalConverted += UnicodeTextUtil::ConvertASCIIInPlace( EFullToHalfWidth,
   1.452 +                                                            aUnicodeTarget );
   1.453 +    return totalConverted;
   1.454 +    }
   1.455 +
   1.456 +// -----------------------------------------------------------------------------
   1.457 +// JPLangUtil::ConvertHalfToFullWidthKatakana
   1.458 +// Converts Half-width Katakana and Special Character text found in
   1.459 +// aUnicodeSource to their Full-width counterparts and places the resulting text
   1.460 +// into aUnicodeTarget.
   1.461 +// (detailed information about the parameters and return values can be found in
   1.462 +// the header file)
   1.463 +// -----------------------------------------------------------------------------
   1.464 +//
   1.465 +EXPORT_C TInt JPLangUtil::ConvertHalfToFullWidthKatakana
   1.466 +                       ( const TDesC16& aUnicodeSource, TDes16& aUnicodeTarget )
   1.467 +    {
   1.468 +    TInt totalConverted( 0 );
   1.469 +    const TInt length( aUnicodeSource.Length() );
   1.470 +    if( length > aUnicodeTarget.MaxLength() )
   1.471 +        {
   1.472 +        return KErrTooBig;
   1.473 +        }
   1.474 +    aUnicodeTarget.Zero();
   1.475 +    for( TInt i( 0 ); i < length; ++i )
   1.476 +        {
   1.477 +        const TText uniChar( aUnicodeSource[i] );
   1.478 +        // Check if the next character is a Half Width Katakana (Semi-)Voiced
   1.479 +        // Sound Mark and if the current character + the voiced sound mark have
   1.480 +        // a Full Width counterpart
   1.481 +        if( i + 1 < length )
   1.482 +            {
   1.483 +            const TBool isVoiced(
   1.484 +            ( UnicodeTextUtil::IsFullWidthVoicedConvertableHalfWidthBaseKatakana
   1.485 +                  ( uniChar ) &&
   1.486 +              ( aUnicodeSource[i + 1] == KHalfWidthKatakanaVoicedSoundMark )
   1.487 +            ) );
   1.488 +
   1.489 +            const TBool isSemiVoiced(
   1.490 +            ( UnicodeTextUtil::IsFullWidthVoicedConvertableHalfWidthBaseKatakana
   1.491 +                  ( uniChar, ETrue ) &&
   1.492 +              ( aUnicodeSource[i + 1] == KHalfWidthKatakanaSemiVoicedSoundMark )
   1.493 +            ) );
   1.494 +
   1.495 +            if( isVoiced || isSemiVoiced )
   1.496 +                {
   1.497 +                UnicodeTextUtil::ConvertVoicedKatakanaCharAndAppendToTarget(
   1.498 +                    EHalfToFullWidth,
   1.499 +                    uniChar,
   1.500 +                    aUnicodeTarget,
   1.501 +                    isSemiVoiced
   1.502 +                );
   1.503 +                i++; // Skip the (semi-)voice marker
   1.504 +                totalConverted++;
   1.505 +                continue;
   1.506 +                }
   1.507 +            }
   1.508 +        // If not, then just convert directly if in range
   1.509 +        if( uniChar >= KHalfWidthKatakanaLowerBound &&
   1.510 +            uniChar <= KHalfWidthKatakanaUpperBound )
   1.511 +            {
   1.512 +            aUnicodeTarget.Append(
   1.513 +                UnicodeTextUtil::ConvertKatakanaChar( EHalfToFullWidth,
   1.514 +                                                      uniChar )
   1.515 +            );
   1.516 +            totalConverted++;
   1.517 +            }
   1.518 +        // Else this is not Half Width Katakana, so copy directly...
   1.519 +        else
   1.520 +            {
   1.521 +            const TChar uniCharacter( uniChar );
   1.522 +            aUnicodeTarget.Append( uniCharacter );
   1.523 +            }
   1.524 +        }
   1.525 +
   1.526 +    // Now handle special characters
   1.527 +    // This logic may be moved into this function to avoid another
   1.528 +    // loop over the text.
   1.529 +    totalConverted +=
   1.530 +        UnicodeTextUtil::ConvertSpecialCharactersInPlace( EHalfToFullWidth,
   1.531 +                                                          aUnicodeTarget );
   1.532 +
   1.533 +    return totalConverted;
   1.534 +    }
   1.535 +
   1.536 +// -----------------------------------------------------------------------------
   1.537 +// JPLangUtil::ConvertFullToHalfWidthKatakana
   1.538 +// Converts Full-width Katakana and Special Character text found in
   1.539 +// aUnicodeSource to their Half-width counterparts and places the resulting text
   1.540 +// into aUnicodeTarget. There will be a 2-for-1 conversion for each Full-width
   1.541 +// Voiced and Semi-voiced Katakana character.
   1.542 +// (detailed information about the parameters and return values can be found in
   1.543 +// the header file)
   1.544 +// -----------------------------------------------------------------------------
   1.545 +//
   1.546 +EXPORT_C TInt JPLangUtil::ConvertFullToHalfWidthKatakana
   1.547 +                       ( const TDesC16& aUnicodeSource, TDes16& aUnicodeTarget )
   1.548 +    {
   1.549 +    TInt totalConverted( 0 );
   1.550 +    const TInt length( aUnicodeSource.Length() );
   1.551 +    const TInt maxLength( aUnicodeTarget.MaxLength() );
   1.552 +    if( length > maxLength )
   1.553 +        {
   1.554 +        return KErrTooBig;
   1.555 +        }
   1.556 +    aUnicodeTarget.Zero();
   1.557 +    for( TInt i( 0 ); i < length; ++i )
   1.558 +        {
   1.559 +        const TText uniChar( aUnicodeSource[i] );
   1.560 +        // First check if this is this Full Width Katakana
   1.561 +        if( ( uniChar >= KFullWidthKatakanaLowerBound &&
   1.562 +              uniChar <= KFullWidthKatakanaUpperBound ) ||
   1.563 +            ( uniChar == KFullWidthKatakanaVoicedSoundMark ||
   1.564 +              uniChar == KFullWidthKatakanaSemiVoicedSoundMark ) )
   1.565 +            {
   1.566 +            // Then check if it is (Semi-)Voiced and convert it properly
   1.567 +            const TBool isVoiced(
   1.568 +                UnicodeTextUtil::IsFullWidthVoicedKatakana( uniChar )
   1.569 +            );
   1.570 +            const TBool isSemiVoiced(
   1.571 +                UnicodeTextUtil::IsFullWidthVoicedKatakana( uniChar, ETrue )
   1.572 +            );
   1.573 +            if( isVoiced || isSemiVoiced )
   1.574 +                {
   1.575 +                if( aUnicodeTarget.Length() + 2 > maxLength )
   1.576 +                    {
   1.577 +                    // This descriptor can't hold the new data
   1.578 +                    aUnicodeTarget.Zero();
   1.579 +                    return KErrTooBig;
   1.580 +                    }
   1.581 +                UnicodeTextUtil::ConvertVoicedKatakanaCharAndAppendToTarget(
   1.582 +                    EFullToHalfWidth,
   1.583 +                    uniChar,
   1.584 +                    aUnicodeTarget,
   1.585 +                    isSemiVoiced
   1.586 +                );
   1.587 +                totalConverted++;
   1.588 +                }
   1.589 +            else
   1.590 +                {
   1.591 +                if( aUnicodeTarget.Length() + 1 > maxLength )
   1.592 +                    {
   1.593 +                    // This descriptor can't hold the new data
   1.594 +                    aUnicodeTarget.Zero();
   1.595 +                    return KErrTooBig;
   1.596 +                    }
   1.597 +                aUnicodeTarget.Append(
   1.598 +                    UnicodeTextUtil::ConvertKatakanaChar(
   1.599 +                        EFullToHalfWidth,
   1.600 +                        uniChar
   1.601 +                    )
   1.602 +                );
   1.603 +                totalConverted++;
   1.604 +                }
   1.605 +            }
   1.606 +        // This is not Full Width Katakana, so copy directly...
   1.607 +        else
   1.608 +            {
   1.609 +            if( aUnicodeTarget.Length() + 1 > maxLength )
   1.610 +                {
   1.611 +                // This descriptor can't hold the new data
   1.612 +                aUnicodeTarget.Zero();
   1.613 +                return KErrTooBig;
   1.614 +                }
   1.615 +            const TChar uniCharacter( uniChar );
   1.616 +            aUnicodeTarget.Append( uniCharacter );
   1.617 +            }
   1.618 +        }
   1.619 +
   1.620 +    // Now handle special characters
   1.621 +    // This logic may be moved into this function to avoid another loop over
   1.622 +    // the text
   1.623 +    totalConverted +=
   1.624 +        UnicodeTextUtil::ConvertSpecialCharactersInPlace( EFullToHalfWidth,
   1.625 +                                                          aUnicodeTarget );
   1.626 +
   1.627 +    return totalConverted;
   1.628 +    }
   1.629 +
   1.630 +// -----------------------------------------------------------------------------
   1.631 +// JPLangUtil::ConvertFullHiragnaToFullKatakana
   1.632 +// Converts Full-width Hiragana and Special Character text found in
   1.633 +// aUnicodeSource to their Full-width counterparts and places the
   1.634 +// resulting text into aUnicodeTarget.
   1.635 +// -----------------------------------------------------------------------------
   1.636 +//
   1.637 +EXPORT_C TInt JPLangUtil::ConvertFullHiragnaToFullKatakana
   1.638 +                       ( const TDesC16& aUnicodeSource, TDes16& aUnicodeTarget )
   1.639 +    {
   1.640 +    TInt totalConverted( 0 );
   1.641 +    const TInt length( aUnicodeSource.Length() );
   1.642 +    const TInt maxLength( aUnicodeTarget.MaxLength() );
   1.643 +    if( length > maxLength )
   1.644 +        {
   1.645 +        return KErrTooBig;
   1.646 +        }
   1.647 +
   1.648 +    const TUint comp = KFullWidthKatakanaSmallA - KFullWidthHiraganaSmallA;
   1.649 +
   1.650 +    aUnicodeTarget.Zero();
   1.651 +    for( TInt i( 0 ); i < length; ++i )
   1.652 +        {
   1.653 +        const TText uniChar( aUnicodeSource[i] );
   1.654 +        TText uniChar2(0);
   1.655 +        if (i + 1 < length)
   1.656 +            {
   1.657 +            uniChar2 = aUnicodeSource[i+1];
   1.658 +            }
   1.659 +        // First check if this is this Full Width Katakana
   1.660 +        if (KFullWidthHiraganaSmallA <= uniChar && uniChar <= KFullWidthHiraganaVU)
   1.661 +            {
   1.662 +            if (uniChar == KFullWidthHiraganaU
   1.663 +             && uniChar2 == KFullWidthHiraganaVoicedSound)
   1.664 +                {
   1.665 +                aUnicodeTarget.Append(KFullWidthKatakanaSmallVU);
   1.666 +                totalConverted++;
   1.667 +                i++;
   1.668 +                }
   1.669 +            else
   1.670 +                {
   1.671 +                TUint katakana = uniChar + comp;
   1.672 +                if (IsKatakana(katakana))
   1.673 +                    {
   1.674 +                    aUnicodeTarget.Append(katakana);
   1.675 +                    totalConverted++;
   1.676 +                    }
   1.677 +                }
   1.678 +            }
   1.679 +        else
   1.680 +            {
   1.681 +            aUnicodeTarget.Append(uniChar);
   1.682 +            totalConverted++;
   1.683 +            }
   1.684 +        }
   1.685 +
   1.686 +    // Now handle special characters
   1.687 +    // This logic may be moved into this function to avoid another loop over
   1.688 +    // the text
   1.689 +    totalConverted +=
   1.690 +        UnicodeTextUtil::ConvertSpecialCharactersInPlace( EFullToHalfWidth,
   1.691 +                                                          aUnicodeTarget );
   1.692 +
   1.693 +    return totalConverted;
   1.694 +    }
   1.695 +
   1.696 +// -----------------------------------------------------------------------------
   1.697 +// JPLangUtil::IsKatakana
   1.698 +// Determines whether or not the character is Katakana
   1.699 +// (detailed information about the parameters and return values can be found in
   1.700 +// the header file)
   1.701 +// -----------------------------------------------------------------------------
   1.702 +//
   1.703 +EXPORT_C TBool JPLangUtil::IsKatakana( const TText aUnicodeChar )
   1.704 +    {
   1.705 +    return ( ( aUnicodeChar >= KFullWidthKatakanaLowerBound &&
   1.706 +               aUnicodeChar <= KFullWidthKatakanaUpperBound ) ||
   1.707 +             ( aUnicodeChar >= KHalfWidthKatakanaLowerBound &&
   1.708 +               aUnicodeChar <= KHalfWidthKatakanaUpperBound ) ||
   1.709 +             ( aUnicodeChar == KFullWidthKatakanaVoicedSoundMark ||
   1.710 +               aUnicodeChar == KFullWidthKatakanaSemiVoicedSoundMark ) );
   1.711 +    }
   1.712 +
   1.713 +// -----------------------------------------------------------------------------
   1.714 +// JPLangUtil::IsHiragana
   1.715 +// Determines whether or not the character is Hiragana
   1.716 +// (detailed information about the parameters and return values can be found in
   1.717 +// the header file)
   1.718 +// -----------------------------------------------------------------------------
   1.719 +//
   1.720 +EXPORT_C TBool JPLangUtil::IsHiragana( const TText aUnicodeChar )
   1.721 +    {
   1.722 +    return ( ( aUnicodeChar >= 0x3041 && aUnicodeChar <= 0x3096 ) ||
   1.723 +             ( aUnicodeChar >= 0x3099 && aUnicodeChar <= 0x309f ) );
   1.724 +    }
   1.725 +
   1.726 +// -----------------------------------------------------------------------------
   1.727 +// JPLangUtil::IsKanji
   1.728 +// Determines whether or not the character is a CJK Unified Ideograph (ExtA)
   1.729 +// (detailed information about the parameters and return values can be found in
   1.730 +// the header file)
   1.731 +// -----------------------------------------------------------------------------
   1.732 +//
   1.733 +EXPORT_C TBool JPLangUtil::IsKanji( const TText aUnicodeChar )
   1.734 +    {
   1.735 +    return( ( aUnicodeChar >= KCJKUnifiedIdiographLowerBound &&
   1.736 +              aUnicodeChar <= KCJKUnifiedIdiographUpperBound ) ||
   1.737 +            ( aUnicodeChar >= KCJKUnifiedIdeographExtALowerBound &&
   1.738 +              aUnicodeChar <= KCJKUnifiedIdeographExtAUpperBound ) );
   1.739 +    }
   1.740 +
   1.741 +// -----------------------------------------------------------------------------
   1.742 +// JPLangUtil::IsHalfWidth
   1.743 +// Determines whether or not the character is UNICODE defined Half-width.
   1.744 +// (detailed information about the parameters and return values can be found in
   1.745 +// the header file)
   1.746 +// -----------------------------------------------------------------------------
   1.747 +//
   1.748 +EXPORT_C TBool JPLangUtil::IsHalfWidth( const TText aUnicodeChar )
   1.749 +    {
   1.750 +    return // HW Katakana
   1.751 +           ( ( aUnicodeChar >= 0xff61 && aUnicodeChar <= 0xff9f ) ||
   1.752 +           // ASCII
   1.753 +             ( aUnicodeChar >= 0x0020 && aUnicodeChar <= 0x007e ) ||
   1.754 +           // Special Characters
   1.755 +             ( aUnicodeChar == 0x00a2 || aUnicodeChar == 0x00a3 ||
   1.756 +               aUnicodeChar == 0x00a5 || aUnicodeChar == 0x00a6 ||
   1.757 +               aUnicodeChar == 0x00a9 || aUnicodeChar == 0x00ac ||
   1.758 +               aUnicodeChar == 0x00af || aUnicodeChar == 0x2985 ||
   1.759 +               aUnicodeChar == 0x2986 ) ||
   1.760 +           // HW Symbol Variants
   1.761 +             ( aUnicodeChar >= 0xffe8 && aUnicodeChar <= 0xffee ) );
   1.762 +    }
   1.763 +
   1.764 +// -----------------------------------------------------------------------------
   1.765 +// JPLangUtil::IsFullWidth
   1.766 +// Determines whether or not the character is UNICODE defined Full-width.
   1.767 +// Essentially, all code values that are not Half-width.
   1.768 +// (detailed information about the parameters and return values can be found in
   1.769 +// the header file)
   1.770 +// -----------------------------------------------------------------------------
   1.771 +//
   1.772 +EXPORT_C TBool JPLangUtil::IsFullWidth( const TText aUnicodeChar )
   1.773 +    {
   1.774 +        return !IsHalfWidth( aUnicodeChar );
   1.775 +    }
   1.776 +
   1.777 +// End of File