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