--- a/emailservices/emailstore/base_plugin/src/basepluginresourceloader.cpp Mon Mar 15 12:39:10 2010 +0200
+++ b/emailservices/emailstore/base_plugin/src/basepluginresourceloader.cpp Wed Mar 31 21:08:33 2010 +0300
@@ -17,10 +17,45 @@
*/
+
#include <barsread.h>
#include <bautils.h>
+#include <biditext.h>
+#include <tulpanics.h>
+
#include "basepluginresourceloader.h"
+// panic category constant
+#ifdef _DEBUG
+_LIT( KPanicCategory, "CResourceLoader" );
+#endif
+
+// CP1252 ellipsis character value.
+#define KEllipsis 0x2026 // cp1252=133
+
+// Key characters to format key strings.
+const TText KKeyPrefix('%');
+const TText KSubStringSeparator(0x0001); // pipe ('|') character
+const TText KDirNotFound( 0x0002 );
+
+const TInt KExtraSpaceForMainStringDirMarker = 1;
+const TInt KExtraSpaceForSubStringDirMarkers = 2;
+const TText KLRMarker = 0x200E;
+const TText KRLMarker = 0x200F;
+
+// KIntSize and KKeySize define maximum number of characters
+// in input TInts and in keystring. KNumOfParams is maximum number of
+// parameters in the resource string.
+const TInt KIntSize(11); //Max 11 digits.
+const TInt KNumOfParams(20); //Max 20 parameters
+
+// Key strings for number and unicode data.
+_LIT(KNumKeyBuf, "%N"); //Number data
+_LIT(KStringKeyBuf, "%U"); //Unicode data
+
+// KUnknownCount is used as default value for param count in FormatStringL
+const TInt KUnknownCount(-99);
+
EXPORT_C CResourceLoader* CResourceLoader::NewL( const TDesC& aName )
{
CResourceLoader* temp = new( ELeave ) CResourceLoader();
@@ -54,7 +89,7 @@
return iFs;
}
-EXPORT_C HBufC* CResourceLoader::LoadLC(TInt aResourceId)
+EXPORT_C HBufC* CResourceLoader::LoadLC( TInt aResourceId )
{
TResourceReader reader;
HBufC8* readBuffer = CreateResourceReaderLC( reader, aResourceId );
@@ -62,11 +97,136 @@
HBufC16* textBuffer = HBufC16::NewL( textdata.Length() );
*textBuffer = textdata;
- CleanupStack::PopAndDestroy(readBuffer);
+ CleanupStack::PopAndDestroy( readBuffer );
CleanupStack::PushL( textBuffer );
return textBuffer;
}
+EXPORT_C HBufC* CResourceLoader::Load2L( TInt aResourceId )
+ {
+ HBufC8* readBuffer = iResFile.AllocReadLC( aResourceId );
+ const TPtrC16 ptrReadBuffer( ( TText16* ) readBuffer->Ptr(), ( readBuffer->Length()+1 )>>1 );
+ HBufC16* textBuffer=HBufC16::NewL( ptrReadBuffer.Length() );
+ *textBuffer=ptrReadBuffer;
+ CleanupStack::PopAndDestroy( readBuffer );
+ return textBuffer;
+ }
+
+EXPORT_C HBufC* CResourceLoader::Load2LC( TInt aResourceId )
+ {
+ HBufC* retbuf = Load2L( aResourceId );
+ CleanupStack::PushL( retbuf );
+ return retbuf;
+ }
+
+EXPORT_C HBufC* CResourceLoader::Load2L( TInt aResourceId, const TDesC& aString )
+ {
+ HBufC* resbuf = Load2LC( aResourceId );
+ TPtr retptr(resbuf->Des());
+
+ // Get number of sub strings
+ TInt count = GetSubStringCount( retptr );
+ TBool marker(EFalse);
+
+ if (count >= 1)
+ {
+ HBufC* buffer = ResolveSubStringDirsL( retptr, count, &marker );
+ CleanupStack::PushL(buffer);
+
+ TBool found(EFalse);
+ TBidiText::TDirectionality mainDir = DirectionalityL(*buffer , &found);
+
+ //Formating the return string with FormatStringL.
+ HBufC* retbuf = FormatStringL(*buffer, KStringKeyBuf, aString, mainDir);
+
+ CleanupStack::PopAndDestroy(buffer);
+ CleanupStack::PopAndDestroy(resbuf);
+
+ if (marker && retbuf->Length())
+ {
+ TPtr ptr = retbuf->Des();
+ RemoveNoDirMarkers(ptr);
+ }
+
+ __ASSERT_DEBUG(retbuf->Length(),
+ User::Panic(KPanicCategory, EKeyStringNotFound));
+ return retbuf;
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy(resbuf);
+ HBufC* retbuf = HBufC::NewL(0); // return empty buffer
+ __ASSERT_DEBUG(retbuf->Length(),
+ User::Panic(KPanicCategory, EKeyStringNotFound));
+ return retbuf;
+ }
+ }
+
+EXPORT_C HBufC* CResourceLoader::Load2LC( TInt aResourceId, const TDesC& aString )
+ {
+ HBufC* retbuf = Load2L( aResourceId, aString );
+ CleanupStack::PushL( retbuf );
+ return retbuf;
+ }
+
+EXPORT_C HBufC* CResourceLoader::Load2L(TInt aResourceId, TInt aInt )
+ {
+ HBufC* resbuf = Load2LC( aResourceId );
+ TPtr retptr = resbuf->Des();
+ //
+ //Converting input TInt to a descriptor. This way the size
+ //of the return string can be controlled.
+ //
+ TBuf<KIntSize> intbuf;
+ intbuf.Num(aInt);
+
+ if (LanguageSpecificNumberConverter::IsConversionNeeded())
+ LanguageSpecificNumberConverter::Convert(intbuf);
+ //
+ // Get number of sub strings
+ TInt count = GetSubStringCount(retptr);
+ TBool marker(EFalse);
+
+ if (count >= 1)
+ {
+ HBufC* buffer = ResolveSubStringDirsL(retptr, count, &marker);
+ CleanupStack::PushL(buffer);
+
+ TBool found(EFalse);
+ TBidiText::TDirectionality mainDir = DirectionalityL(*buffer , &found);
+
+ //Adding int
+ HBufC* retbuf = FormatStringL(*buffer, KNumKeyBuf, intbuf, mainDir);
+
+ CleanupStack::PopAndDestroy(buffer);
+ CleanupStack::PopAndDestroy(resbuf);
+
+ if (marker && retbuf->Length())
+ {
+ TPtr ptr = retbuf->Des();
+ RemoveNoDirMarkers(ptr);
+ }
+ __ASSERT_DEBUG(retbuf->Length(),
+ User::Panic(KPanicCategory, EKeyStringNotFound));
+ return retbuf;
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy(resbuf);
+ HBufC* retbuf = HBufC::NewL(0); // return empty buffer
+ __ASSERT_DEBUG(retbuf->Length(),
+ User::Panic(KPanicCategory, EKeyStringNotFound));
+ return retbuf;
+ }
+ }
+
+EXPORT_C HBufC* CResourceLoader::Load2LC( TInt aResourceId, TInt aInt )
+ {
+ HBufC* retbuf = Load2L( aResourceId, aInt );
+ CleanupStack::PushL( retbuf );
+ return retbuf;
+ }
+
EXPORT_C HBufC8* CResourceLoader::CreateResourceReaderLC(TResourceReader& aReader,TInt aResourceId) const
{
HBufC8* readBuffer = iResFile.AllocReadLC( aResourceId );
@@ -74,3 +234,657 @@
return readBuffer;
}
+/**
+Counts the number of substrings (separated by KSubStringSeparators) in the text.
+Needed for correct memory allocations.
+*/
+TInt CResourceLoader::GetSubStringCount(const TDesC& aText)
+ {
+ TInt subCount = 0;
+ TInt i = 0;
+
+ while (i < aText.Length())
+ {
+ TPtrC remainder = aText.Right(aText.Length() - i);
+ TInt nextKey = remainder.Locate(KSubStringSeparator);
+ i += nextKey;
+
+ // Always increase subcount, as a string without any separators counts as one substring.
+ // However, if string length is zero, then there are no substrings.
+ subCount++;
+
+ if (nextKey != KErrNotFound && i < aText.Length() - 1)
+ {
+ i++; // skip separator
+ }
+ else
+ break;
+ }
+
+ return subCount;
+ }
+
+HBufC* CResourceLoader::ResolveSubStringDirsL(TDes& aText, TInt aCount, TBool* aMarker)
+ {
+ // Allocating heap buffer for return string.
+ TInt destlength(aText.Length());
+ destlength = destlength + (KExtraSpaceForMainStringDirMarker) * aCount;
+ HBufC* retbuf = HBufC::NewLC(destlength);
+ TPtr retptr(retbuf->Des());
+ TInt freeSpace(destlength);
+ TInt i(0);
+ TInt j(0);
+ TBuf<1> subsMarker;
+ subsMarker.Append(KSubStringSeparator);
+ TInt count(aCount - 1);
+
+ while (i < aCount)
+ {
+ // Resolve sub string
+ HBufC* buffer = ResolveSubStringL(aText, aMarker);
+ TPtr ptr = buffer->Des();
+ CleanupStack::PushL(buffer);
+
+ // Restore sub string separators
+ if (freeSpace >= ptr.Length())
+ {
+ retptr.Insert(j, ptr);
+ freeSpace -= ptr.Length();
+ j += ptr.Length();
+ if (freeSpace > KExtraSpaceForMainStringDirMarker && i < count)
+ {
+ retptr.Append(subsMarker);
+ j ++;
+ }
+ }
+ CleanupStack::PopAndDestroy(buffer);
+ i++;
+ }
+
+ retbuf = retbuf->ReAllocL(retptr.Length());
+ CleanupStack::Pop(); //retbuf
+ return retbuf;
+ }
+
+TBidiText::TDirectionality CResourceLoader::DirectionalityL(const TDesC& aText, TBool* aFound)
+ {
+ // Resolve directionality of sub string
+ HBufC* dirbuf = aText.AllocL();
+ TPtr dirptr = dirbuf->Des();
+ TBidiText::TDirectionality dir = ResolveDirectionality(dirptr, aFound);
+ delete dirbuf;
+ return dir;
+ }
+
+/**
+Resolves directionality of the given source text.
+Place-holder strings are removed so that they don't affect the result.
+*/
+TBidiText::TDirectionality CResourceLoader::ResolveDirectionality(TDes& aText, TBool* aFound)
+ {
+ TInt i = 0;
+
+ // Remove place-holders from string so they don't affect directionality
+ // length parameters e.g. "[29]" do not contain strongly directional
+ // characters so can ignore them.
+ while (i < aText.Length())
+ {
+ TPtrC remainder = aText.Right(aText.Length() - i);
+ TInt nextKey = remainder.Locate(KKeyPrefix);
+ i += nextKey;
+
+ if (nextKey != KErrNotFound && i < aText.Length() - 1)
+ {
+ TInt lastCharInKey = i + 1;
+
+ // skip possible key index
+ TText t = aText[lastCharInKey];
+ if (t >= '0' && t <= '9')
+ {
+ lastCharInKey++;
+
+ if (lastCharInKey < aText.Length())
+ {
+ t = aText[lastCharInKey];
+ if (t >= '0' && t <= '9')
+ {
+ lastCharInKey++;
+ }
+ }
+ }
+
+ // lastCharInKey is now the index of 'N' or 'U' in the key
+
+ if (lastCharInKey < aText.Length())
+ {
+ TText t = aText[lastCharInKey];
+ if (t == 'U' || t == 'N')
+ {
+ // found key, delete it and continue loop to
+ // search for the next key
+ aText.Delete(i, lastCharInKey - i + 1);
+ }
+ // This was not a proper key - check the remaining string
+ else
+ {
+ i = lastCharInKey + 1;
+ }
+ }
+ // end of string encountered - stop
+ else
+ {
+ break;
+ }
+ }
+ // no key found - stop
+ else
+ {
+ break;
+ }
+ }
+
+ return TBidiText::TextDirectionality(aText, aFound);
+ }
+
+/**
+Finds the keystring from the source string and replaces it with the
+replacement string.
+*/
+HBufC* CResourceLoader::FormatStringL(const TDesC& aSource, const TDesC& aKey, const TDesC& aSubs,TBidiText::TDirectionality aDir)
+ {
+ TInt paramCount(KUnknownCount); // variable needed as it may be updated
+ return FormatStringL(aSource, aKey, aSubs, aDir, paramCount, KUnknownCount);
+ }
+
+/**
+Finds the keystring from the source string and replaces it with the
+replacement string.
+*/
+HBufC* CResourceLoader::FormatStringL(const TDesC& aSource, const TDesC& aKey, const TDesC& aSubs, TBidiText::TDirectionality aDirectionality,
+ TInt& aParamCount, TInt aSubCount)
+ {
+ if (aParamCount == KUnknownCount)
+ aParamCount = GetParamCount(aSource);
+
+ if (aSubCount == KUnknownCount)
+ aSubCount = GetSubStringCount(aSource);
+
+ // determine lenght of needed buffer
+ TInt sourcelength(aSource.Length());
+ TInt keylength(aKey.Length());
+ TInt subslength(aSubs.Length());
+ TInt destlength = 0;
+ if (subslength >= keylength)
+ {
+ destlength = sourcelength + ((subslength - keylength) * aParamCount);
+ }
+ else
+ {
+ destlength = sourcelength;
+ }
+
+ destlength += KExtraSpaceForMainStringDirMarker * aSubCount;
+ destlength += KExtraSpaceForSubStringDirMarkers * aParamCount;
+ //
+ // Allocating heap buffer for return string.
+ //
+
+ HBufC* retbuf = HBufC::NewL(destlength);
+ TPtr retptr(retbuf->Des());
+
+ // Formating the resource string. Don't bother with format,
+ // if parameter count is not above zero
+ if (aParamCount > 0)
+ {
+ aParamCount -= Formater(retptr, aSource, aKey, aSubs, aDirectionality);
+ __ASSERT_DEBUG(aParamCount >= 0, User::Invariant());
+ }
+
+ //
+ // If the key string wasn't found, retbuf is empty.
+ //
+ return retbuf;
+ }
+
+/**
+Finds the keystring from the source string and replaces it with the
+replacement string. The formated string is stored in the destination
+descriptor.
+*/
+TInt CResourceLoader::Formater(TDes& aDest, const TDesC& aSource, const TDesC& aKey, const TDesC& aSubs, TBidiText::TDirectionality aDirectionality)
+ {
+ // substitute string must not contain KSubStringSeparator,
+ // or results will be unpredictable
+ __ASSERT_DEBUG(aSubs.Locate(KSubStringSeparator) == KErrNotFound,
+ User::Panic(KPanicCategory, EInvalidSubstitute));
+
+ TInt keylength(aKey.Length());
+
+ //aDest must be empty.
+ aDest.Zero();
+
+ // offset indicates end of last handled key in source
+ TInt offset(0);
+
+ // offset in destination string
+ TInt desOffset(0);
+
+ // Substring directionalities are adjusted after all changes are done.
+ TBool checkSubstringDirectionalities(EFalse);
+
+ // count is the position in the source from which the substring starts
+ TInt count(0);
+
+ // Replaced parameters count
+ TInt replaceCount(0);
+
+ while (count != KErrNotFound)
+ {
+ // desCount is the position of the substring starts in destination.
+ TInt desCount(0);
+
+ TPtrC remainder = aSource.Right(aSource.Length() - offset);
+ count = remainder.Find(aKey);
+
+ TInt maxSubLength = -1;
+ if (count != KErrNotFound)
+ {
+ replaceCount++;
+ desOffset += count;
+ offset += count;
+ count = offset;
+ desCount = desOffset;
+
+ // copy source to destination if first time
+ if (aDest.Length() == 0)
+ aDest.Append(aSource);
+
+ // delete found key from destination
+ aDest.Delete(desCount, keylength);
+
+ offset += keylength; // increase offset by key length
+
+ if (count + keylength < (aSource.Length()-1)) // aKey is not at the end of string
+ {
+ if (aSource[count+keylength] == '[') // Key includes max datalength
+ {
+ maxSubLength = 10*(aSource[count+keylength+1]-'0')
+ + (aSource[count+keylength+2]-'0');
+ aDest.Delete(desCount,4); // Length information stored->delete from descriptor
+ offset += 4; // increase offset by max sub length indicator
+ }
+ }
+
+ aDest.Insert(desCount, aSubs);
+
+ desOffset = desCount + aSubs.Length();
+
+ if (maxSubLength > 0 && aSubs.Length() > maxSubLength)
+ {
+ aDest.Delete(desCount+maxSubLength-1, aSubs.Length()+1-maxSubLength);
+ TText ellipsis(KEllipsis);
+ aDest.Insert(desCount+maxSubLength-1, TPtrC(&ellipsis,1));
+ desOffset = desCount + maxSubLength;
+ }
+
+ TBidiText::TDirectionality subsDir =
+ TBidiText::TextDirectionality(aDest.Mid(desCount, desOffset - desCount));
+
+ // If inserted string has different directionality,
+ // insert directionality markers so that bidi algorithm works in a desired way.
+ if (aDirectionality != subsDir)
+ {
+ checkSubstringDirectionalities = ETrue;
+
+ TInt freeSpace = aDest.MaxLength() - aDest.Length();
+
+ // Protect the directionality of the inserted string.
+ if (freeSpace >= KExtraSpaceForSubStringDirMarkers)
+ {
+ TBuf<1> subsMarker;
+ subsMarker.Append(subsDir == TBidiText::ELeftToRight ?
+ KLRMarker : KRLMarker);
+
+ aDest.Insert(desOffset, subsMarker);
+ aDest.Insert(desCount, subsMarker);
+ desOffset += KExtraSpaceForSubStringDirMarkers;
+ }
+ }
+ }
+ }
+
+ // Adjust substring directionality markers if necessary
+ // and if there is enough room in destination string
+ if (checkSubstringDirectionalities)
+ {
+ TText mainMarker = (aDirectionality == TBidiText::ELeftToRight ?
+ KLRMarker : KRLMarker);
+
+ TInt freeSpace = aDest.MaxLength() - aDest.Length();
+
+ // If not already done, protect the directionality of the original string
+ // and all of the KSubStringSeparator separated substrings.
+ if (freeSpace > 0
+ && aDest.Length()
+ && aDest[0] != mainMarker
+ && aDest[0] != KSubStringSeparator
+ && aDest[0] != KDirNotFound)
+ {
+ aDest.Insert(0, TPtrC(&mainMarker, 1));
+ freeSpace--;
+ }
+
+ // Find and protect KSubStringSeparator separated substrings.
+ // Go through string backwards so that any changes will not affect indexes
+ // that are not yet checked.
+ TInt j(aDest.Length()-1);
+ while (freeSpace > 0 && j >= 0)
+ {
+ if (aDest[j] == KSubStringSeparator && j < (aDest.Length() - 1)
+ && aDest[j+1] != mainMarker && aDest[j+1] != KDirNotFound)
+ {
+ aDest.Insert(j+1, TPtrC(&mainMarker, 1));
+ freeSpace--;
+ }
+ j--;
+ }
+ }
+
+ return replaceCount;
+ }
+
+/**
+Counts the number of parameters in the text.
+Needed for correct memory allocations.
+*/
+TInt CResourceLoader::GetParamCount(const TDesC& aText, TInt aIndex)
+ {
+ TInt paramCount(0);
+ TInt i(0);
+ TBool singleIndex((aIndex < 0) || (aIndex > KNumOfParams) ? EFalse : ETrue);
+
+ while (i < aText.Length())
+ {
+ TPtrC remainder = aText.Right(aText.Length() - i);
+ TInt nextKey = remainder.Locate(KKeyPrefix);
+ i += nextKey;
+
+ if (nextKey != KErrNotFound && i < aText.Length() - 1)
+ {
+ TInt lastCharInKey = i + 1;
+
+ // skip possible key index
+ TText t = aText[lastCharInKey];
+ TInt foundIndex(-1);
+
+ if (t >= '0' && t <= '9')
+ {
+ lastCharInKey++;
+ foundIndex = t - '0';
+
+ if (lastCharInKey < aText.Length())
+ {
+ t = aText[lastCharInKey];
+ if (t >= '0' && t <= '9')
+ {
+ foundIndex *= 10;
+ foundIndex += t - '0';
+ lastCharInKey++;
+ }
+ }
+ }
+
+ // lastCharInKey is now the index of 'N' or 'U' in the key
+
+ if (lastCharInKey < aText.Length())
+ {
+ // Only count parameter, if index matches
+ if (!singleIndex || (foundIndex == aIndex))
+ {
+ TText t = aText[lastCharInKey];
+ if (t == 'U' || t == 'N')
+ {
+ // found legit key, count it
+ paramCount++;
+ // continue search after index
+ i = lastCharInKey + 1;
+ }
+ else if (t == '%')
+ i = lastCharInKey;
+ else // continue search after index
+ i = lastCharInKey + 1;
+ }
+ else // continue search after index
+ i = lastCharInKey + 1;
+ }
+ else // end of string encountered - stop
+ break;
+ }
+ else // no key found - stop
+ break;
+ }
+
+ return paramCount;
+ }
+
+/**
+Resolves sub string and directionality of the sub string.
+Adds no dir marker if directionality of the string not found.
+*/
+HBufC* CResourceLoader::ResolveSubStringL(TDes& aText, TBool* aMarker)
+ {
+ // Allocating heap buffer for return string.
+ TInt destlength(aText.Length());
+ HBufC* retbuf = HBufC::NewLC(destlength + 1); // no dir marker
+ TPtr retptr(retbuf->Des());
+
+ TBuf<1> marker;
+ marker.Append(KDirNotFound);
+
+ TPtrC remainder = aText.Right(aText.Length());
+ TInt nextKey = remainder.Locate(KSubStringSeparator);
+
+ if (nextKey == 0)
+ {
+ remainder.Set(remainder.Mid(1));
+ nextKey = remainder.Locate(KSubStringSeparator);
+ if (nextKey != KErrNotFound)
+ {
+ retptr.Insert(0, aText.Mid(1, nextKey));
+ // Remove string from aText
+ aText.Delete(0, nextKey + 1);
+ }
+ else
+ {
+ TInt length = aText.Length();
+ retptr.Insert(0, aText.Mid(1, length - 1));
+ // Remove string from aText
+ aText.Delete(0, length);
+ }
+ }
+ else if (nextKey == KErrNotFound)
+ {
+ retptr.Insert(0, aText);
+ // Remove string from aText
+ aText.Delete(0, aText.Length());
+ }
+ else
+ {
+ retptr.Insert(0, aText.Mid(0, nextKey));
+ // Remove string from aText
+ aText.Delete(0, nextKey);
+ }
+
+ // Resolve directionality of sub string
+ HBufC* dirbuf = retbuf->AllocL();
+ TPtr dirptr = dirbuf->Des();
+ TBool found(EFalse);
+ TBidiText::TDirectionality mainDir = ResolveDirectionality(dirptr, &found);
+ delete dirbuf;
+
+ if (!found)
+ {
+ retptr.Insert(0, marker);
+ *aMarker = ETrue;
+ }
+ else
+ {
+ *aMarker = EFalse;
+ }
+
+ retbuf = retbuf->ReAllocL(retptr.Length());
+ CleanupStack::Pop(); //retbuf
+ // If the key string wasn't found, retbuf is empty.
+ return retbuf;
+ }
+
+/**
+Removes no dir markers from source text.
+*/
+void CResourceLoader::RemoveNoDirMarkers(TDes& aText)
+ {
+ TInt nextkey(0);
+ while (nextkey < aText.Length())
+ {
+ nextkey = aText.Locate(KDirNotFound);
+ if (nextkey != KErrNotFound)
+ {
+ aText.Delete(nextkey, 1);
+ nextkey++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+static TChar NumberToBase(const TChar& aCharacter )
+ {
+ const TDigitType d[] = { EDigitTypeWestern,
+ EDigitTypeArabicIndic,
+ EDigitTypeEasternArabicIndic,
+ EDigitTypeDevanagari,
+ EDigitTypeThai };
+
+ const TInt num = sizeof( d ) / sizeof( d[0] );
+
+ TInt i = 0;
+ while( i < num )
+ {
+ if (aCharacter > TChar( d[i] ) && aCharacter < TChar( d[i]+10 ))
+ return d[i];
+
+ i++;
+ }
+
+ return aCharacter;
+ }
+
+/**
+This routine is used to convert between European digits and
+Arabic-Indic, Eastern Arabic-Indic, Devanagari or Thai digits
+based on existing digit type setting.
+
+@param aDes Parameter to change
+*/
+void CResourceLoader::LanguageSpecificNumberConverter::Convert( TDes &aDes )
+ {
+ TLocale locale;
+ locale.Refresh();
+ const TDigitType digitType = locale.DigitType();
+ TChar toArea = 0x030;
+ switch( digitType )
+ {
+ case EDigitTypeWestern:
+ case EDigitTypeArabicIndic:
+ case EDigitTypeEasternArabicIndic:
+ case EDigitTypeDevanagari:
+ case EDigitTypeThai:
+ toArea = digitType;
+ break;
+ case EDigitTypeUnknown:
+ case EDigitTypeAllTypes:
+ return;
+ }
+
+ const TInt length = aDes.Length();
+ for( TInt i = 0; i < length; i++ )
+ {
+ TChar character = aDes[i];
+ TChar fromArea = NumberToBase( character );
+ TChar::TBdCategory cat = character.GetBdCategory();
+ switch( cat )
+ {
+ case TChar::EArabicNumber:
+ case TChar::EEuropeanNumber:
+ character += toArea;
+ character -= fromArea;
+ aDes[i] = TUint16( character );
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+/**
+This routine is used to convert Arabic-Indic, Eastern Arabic-Indic
+or Devanagari digits to European digits.
+
+@param aDes Parameter to change
+*/
+void CResourceLoader::LanguageSpecificNumberConverter::ConvertToWesternNumbers( TDes &aDes )
+ {
+ const TChar toArea = 0x030;
+ const TInt KLastDevanagariDigit = 0x96F;
+ const TInt KFirstDevanagariDigit = 0x966;
+ const TInt length = aDes.Length();
+
+ for( TInt i=0; i<length; i++ )
+ {
+ TChar character = aDes[i];
+ TChar fromArea = NumberToBase( character );
+ TChar::TBdCategory cat = character.GetBdCategory();
+
+ if ( cat == TChar::EArabicNumber || cat == TChar::EEuropeanNumber ||
+ ( KFirstDevanagariDigit <= character && character <= KLastDevanagariDigit ) )
+ {
+ character += toArea;
+ character -= fromArea;
+ aDes[i] = TUint16( character );
+ }
+ }
+ }
+
+/**
+This routine is used to check if conversion of digits is needed.
+Conversion is needed if user language is
+- Arabic, Urdu or Farsi and if digit type is Arabic-Indic
+- Urdu or Farsi and digit type is Eastern Arabic_indic
+- Hindi and digit type is Devanagari.
+
+@return ETrue if conversion is needed, EFalse if not
+*/
+TBool CResourceLoader::LanguageSpecificNumberConverter::IsConversionNeeded()
+ {
+ TLocale locale;
+ locale.Refresh();
+ const TLanguage language = User::Language();
+ const TDigitType digitType = locale.DigitType();
+
+ if ( ( ( language == ELangArabic || language == ELangUrdu || language == ELangFarsi ) &&
+ digitType == EDigitTypeArabicIndic )
+ || ( ( language == ELangUrdu || language == ELangFarsi ) &&
+ digitType == EDigitTypeEasternArabicIndic )
+ || ( language == ELangHindi && digitType == EDigitTypeDevanagari )
+ )
+ {
+ return ETrue;
+ }
+
+ return EFalse;
+ }
+