xcfw/src/xcfwlocalizer.cpp
branchRCL_3
changeset 114 a5a39a295112
child 118 8baec10861af
equal deleted inserted replaced
113:0efa10d348c0 114:a5a39a295112
       
     1 /*
       
     2 * Copyright (c) 2002-2005 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementation for XCFWLocalizer
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include    "xcfwlocalizer.h"
       
    22 #include    <bautils.h>
       
    23 #include    <e32std.h>
       
    24 #include    <badesca.h>
       
    25 #include    <s32file.h>
       
    26 #include    <s32strm.h>
       
    27 #include    <utf.h>
       
    28 #include    <pathinfo.h>    
       
    29 // CONSTANTS
       
    30 _LIT8( KEntityStart, "!ENTITY " );
       
    31 _LIT( KDrivePathChars, ":\\" );
       
    32 const TInt KDefaultGranularity = 10;
       
    33 //Maximum entity declaration length is rather long because
       
    34 //in RND builds the DTD files contain a lot of comments 
       
    35 //and parsing the file requires long enough buffer.
       
    36 const TInt KMaxEntityDeclLen = 1024; 
       
    37 const TInt KPathStartLoc = 2;
       
    38 
       
    39 // ============================ MEMBER FUNCTIONS ===============================
       
    40 
       
    41 // -----------------------------------------------------------------------------
       
    42 // CXCFWLocalizer::CXCFWLocalizer
       
    43 // C++ default constructor can NOT contain any code, that
       
    44 // might leave.
       
    45 // -----------------------------------------------------------------------------
       
    46 //
       
    47 CXCFWLocalizer::CXCFWLocalizer()
       
    48     {
       
    49     }
       
    50 
       
    51 // -----------------------------------------------------------------------------
       
    52 // CXCFWLocalizer::ConstructL
       
    53 // Symbian 2nd phase constructor can leave.
       
    54 // -----------------------------------------------------------------------------
       
    55 //
       
    56 void CXCFWLocalizer::ConstructL()
       
    57     {
       
    58     iReferences = new ( ELeave ) CDesCArraySeg( KDefaultGranularity );
       
    59     iLocStrings = new ( ELeave ) CDesCArraySeg( KDefaultGranularity );
       
    60     }
       
    61 
       
    62 // -----------------------------------------------------------------------------
       
    63 // CXCFWLocalizer::NewL
       
    64 // Two-phased constructor with Node Data initializer.
       
    65 // -----------------------------------------------------------------------------
       
    66 //
       
    67 CXCFWLocalizer* CXCFWLocalizer::NewL()
       
    68     {
       
    69     CXCFWLocalizer* self = new( ELeave ) CXCFWLocalizer;
       
    70     
       
    71     CleanupStack::PushL( self );
       
    72     self->ConstructL();
       
    73     CleanupStack::Pop( self );
       
    74 
       
    75     return self;
       
    76     }
       
    77 
       
    78    
       
    79 // Destructor
       
    80 CXCFWLocalizer::~CXCFWLocalizer()
       
    81     {
       
    82     delete iReferences;
       
    83     delete iLocStrings;
       
    84     }
       
    85 
       
    86 // -----------------------------------------------------------------------------
       
    87 // CXCFWLocalizer::LoadDTDL
       
    88 // Load entity references from DTD file
       
    89 // Function searches the DTD file first from session path (which is where
       
    90 // the loaded XML file is located). If it is not found there, it is sought
       
    91 // from ROM drive at the same location. 
       
    92 // If function can't find loc file for current language, it will search the
       
    93 // possible replacement using language downgrade path.
       
    94 // -----------------------------------------------------------------------------
       
    95 //
       
    96 void CXCFWLocalizer::LoadDTDL(
       
    97     const TDesC& aDTD,
       
    98     RFs& aFileSystem,
       
    99     TRequestStatus* aStatus )
       
   100     {
       
   101     const TInt KMaxLangCodeLen = 5;
       
   102     const TInt KMinLangCodeLen = 2;
       
   103 
       
   104     TBuf<KMaxLangCodeLen> lcstring;
       
   105 
       
   106     delete iLocStrings;
       
   107     iLocStrings = NULL;
       
   108     delete iReferences;
       
   109     iLocStrings = NULL;
       
   110     iReferences = new ( ELeave ) CDesCArraySeg( KDefaultGranularity );
       
   111     iLocStrings = new ( ELeave ) CDesCArraySeg( KDefaultGranularity );
       
   112     
       
   113     iStatus = aStatus;
       
   114     
       
   115 
       
   116     //First get filepath without drive character
       
   117     TPtrC filepath;
       
   118     if ( aDTD.Find( KDrivePathChars ) != KErrNotFound )
       
   119         {
       
   120         filepath.Set( aDTD.Mid( KPathStartLoc ) );             
       
   121         }
       
   122     else
       
   123         {
       
   124         filepath.Set( aDTD );
       
   125         }
       
   126 
       
   127     // format filepath with current language data
       
   128     TLanguage langcode = User::Language(); //current language
       
   129     lcstring.Num( (TInt64)langcode ); //to get decimal langcode length in characters
       
   130     //use always at least 2 digits.
       
   131     TInt codelen = lcstring.Length() > 1 ? lcstring.Length() : KMinLangCodeLen; 
       
   132 
       
   133     HBufC* locfile = HBufC::NewL( aDTD.Length() + KMaxLangCodeLen );
       
   134     CleanupStack::PushL( locfile );
       
   135     locfile->Des().Format( filepath, codelen, langcode );
       
   136 
       
   137     //Check for file, if not found, check language downgrade path
       
   138     if( !BaflUtils::FileExists( aFileSystem, locfile->Des() ) )
       
   139         {
       
   140         RArray<TLanguage> langs;
       
   141         BaflUtils::GetDowngradePathL( aFileSystem, langcode, langs );
       
   142         //add current language to array for ROM fetching
       
   143         langs.Append( langcode );
       
   144         TInt current = langs.Count() - 1;
       
   145         do 
       
   146             {
       
   147             lcstring.Num( (TInt64)langs[current] );
       
   148             codelen = lcstring.Length()>1?lcstring.Length():KMinLangCodeLen;
       
   149             locfile->Des().Format( filepath, codelen, langs[current] );
       
   150             current--;
       
   151             } 
       
   152         while ( current >= 0 && 
       
   153                 !BaflUtils::FileExists( aFileSystem, locfile->Des() ) );
       
   154         
       
   155         //If still not found, check from ROM
       
   156         if ( !BaflUtils::FileExists( aFileSystem, locfile->Des() ) )
       
   157             {
       
   158             current = langs.Count() - 1;
       
   159             do {
       
   160                 lcstring.Num( (TInt64)langs[current] );
       
   161                 codelen = lcstring.Length()>1?lcstring.Length():KMinLangCodeLen;
       
   162                 locfile->Des().Format( filepath, codelen, langs[current] );
       
   163                 locfile->Des().Insert( 0, PathInfo::RomRootPath().Left( KPathStartLoc ) );
       
   164                 current--;
       
   165                 } while ( current >= 0 && 
       
   166                     !BaflUtils::FileExists( aFileSystem, locfile->Des() ) );
       
   167             }
       
   168         langs.Reset();
       
   169         langs.Close();
       
   170         }
       
   171 
       
   172 
       
   173     if ( BaflUtils::FileExists( aFileSystem, locfile->Des() ) )
       
   174         {
       
   175         RFile infile;
       
   176         User::LeaveIfError( infile.Open(aFileSystem, locfile->Des(), EFileRead) );
       
   177         CleanupClosePushL( infile );
       
   178         RFileReadStream readStream( infile,0 );
       
   179         CleanupClosePushL( readStream );
       
   180        
       
   181         ParseDTDL( readStream );
       
   182        
       
   183         CleanupStack::Pop( &readStream ); //readStream
       
   184         CleanupStack::Pop( &infile ); //infile
       
   185         }
       
   186     
       
   187 
       
   188     CleanupStack::PopAndDestroy( locfile );
       
   189 
       
   190     *aStatus = KRequestPending;
       
   191     User::RequestComplete( aStatus, KErrNone );
       
   192     
       
   193     }
       
   194 
       
   195 // -----------------------------------------------------------------------------
       
   196 // CXCFWLocalizer::LoadDTDL
       
   197 // Parse DTD file. Function assumes that the DTD contains ENTITY declarations
       
   198 // only.
       
   199 // -----------------------------------------------------------------------------
       
   200 //
       
   201 void CXCFWLocalizer::ParseDTDL( RFileReadStream& aStream )
       
   202     {
       
   203     
       
   204     TChar space = ' ';
       
   205     TChar quote = '"';
       
   206     TChar lessthan = '<';
       
   207     TChar morethan = '>';
       
   208 
       
   209     HBufC8* buf = HBufC8::NewLC( KMaxEntityDeclLen );
       
   210     TPtr8 p( buf->Des() );
       
   211 
       
   212     TInt streamError = KErrNone;
       
   213 
       
   214     do 
       
   215         {
       
   216         // Read until declaration start "<"
       
   217         TRAP( streamError, aStream.ReadL( p , lessthan)); 
       
   218         // This might be EOF, or other problem, we exit 
       
   219         if( streamError != KErrNone )   
       
   220             {
       
   221             aStream.Close();
       
   222             }
       
   223         else
       
   224             {
       
   225             aStream.ReadL( p , space); // Read until space " "
       
   226             
       
   227             // entity declaration handled, others are ignored
       
   228             if ( p.CompareC( KEntityStart ) == 0 ) 
       
   229                 {
       
   230                 p.Zero();
       
   231                 aStream.ReadL( p , space); // Read the reference name
       
   232                 p.TrimRight();  // Delete space from the end
       
   233                 
       
   234                 HBufC* ucsbuf = HBufC::NewLC( p.Length() );
       
   235                 TPtr ucsp( ucsbuf->Des() );
       
   236                 CnvUtfConverter::ConvertToUnicodeFromUtf8( ucsp, p );
       
   237                 iReferences->AppendL( ucsp );
       
   238                 CleanupStack::PopAndDestroy( ucsbuf );
       
   239                 
       
   240                 p.Zero();
       
   241                 aStream.ReadL( p , quote);
       
   242                 p.Zero();
       
   243                 aStream.ReadL( p , quote); 
       
   244                 p.SetLength(p.Length() - 1); // Delete quotation from the end
       
   245 
       
   246                 //Seek for percentage char symbol and do necessary conversion
       
   247                 const TInt KUCEntityLen = 8;
       
   248                 _LIT8( KUniCodeChar, "&#x0025;");
       
   249                 _LIT8( KPctage, "%" );
       
   250                 TInt pct = p.Find( KUniCodeChar );
       
   251                 while ( pct != KErrNotFound )
       
   252                     {
       
   253                     HBufC8* tmp = HBufC8::NewLC( KMaxEntityDeclLen );
       
   254                     tmp->Des().Copy ( p.Left( pct ) );
       
   255                     tmp->Des().Append( KPctage );
       
   256                     tmp->Des().Append( p.Mid( pct + KUCEntityLen ) );
       
   257                     p.Copy ( tmp->Des() );
       
   258                     CleanupStack::PopAndDestroy( tmp );
       
   259                     pct = p.Find( KUniCodeChar );
       
   260                     }
       
   261 
       
   262 
       
   263                 ucsbuf = HBufC::NewLC( p.Length() );
       
   264                 ucsp.Set ( ucsbuf->Des() );
       
   265                 CnvUtfConverter::ConvertToUnicodeFromUtf8( ucsp, p );
       
   266                 iLocStrings->AppendL( ucsp );
       
   267                 CleanupStack::PopAndDestroy( ucsbuf );
       
   268 
       
   269                 
       
   270                 p.Zero();
       
   271                 aStream.ReadL( p , morethan); // Read until declaration ends ">"           
       
   272                 }
       
   273             }
       
   274         
       
   275         } while ( streamError == KErrNone );
       
   276     
       
   277     CleanupStack::PopAndDestroy(buf);
       
   278     }
       
   279 
       
   280 // -----------------------------------------------------------------------------
       
   281 // CXCFWLocalizer::EntityRefToText
       
   282 // Gets localized text value for given entity reference
       
   283 // -----------------------------------------------------------------------------
       
   284 //
       
   285 TInt CXCFWLocalizer::EntityRefToText(
       
   286     TDesC& aRef, 
       
   287     TPtrC& aText)
       
   288     {
       
   289     TInt count = iReferences->Count();
       
   290     TInt ret = KErrNotFound;
       
   291     for ( TInt i = 0; i < count && ret == KErrNotFound; i++ )
       
   292         {
       
   293         if ( iReferences->MdcaPoint( i ).Compare( 
       
   294             aRef.Mid(1, aRef.Length()-2) ) == 0 )
       
   295             {
       
   296             ret = KErrNone;
       
   297             aText.Set( iLocStrings->MdcaPoint( i ) );
       
   298             }
       
   299         }
       
   300     return ret;
       
   301     }
       
   302 
       
   303 // -----------------------------------------------------------------------------
       
   304 // CXCFWLocalizer::TextToEntityRef
       
   305 // Gets entity reference for given text 
       
   306 // -----------------------------------------------------------------------------
       
   307 //
       
   308 TInt CXCFWLocalizer::TextToEntityRef(
       
   309     TDesC& aText, 
       
   310     TPtrC& aRef )
       
   311     {
       
   312     TInt count = iLocStrings->Count();
       
   313     TInt ret = KErrNotFound;
       
   314     for ( TInt i = 0; i < count && ret == KErrNotFound; i++ )
       
   315         {
       
   316         if ( iLocStrings->MdcaPoint( i ).Compare( aText ) == 0 )
       
   317             {
       
   318             ret = KErrNone;
       
   319             aRef.Set( iReferences->MdcaPoint( i ) );
       
   320             }
       
   321         }
       
   322     return ret;
       
   323     }
       
   324 
       
   325 // -----------------------------------------------------------------------------
       
   326 // CXCFWLocalizer::LastError
       
   327 // Returns error code from the parser.
       
   328 // -----------------------------------------------------------------------------
       
   329 //
       
   330 TInt CXCFWLocalizer::LastError()
       
   331     {
       
   332     TInt ret = KErrNone;
       
   333 
       
   334     if ( !iReferences || !iLocStrings )
       
   335         {
       
   336         ret = KErrNotReady;            
       
   337         }
       
   338     else
       
   339         {
       
   340         if ( iReferences->Count() != iLocStrings->Count() )
       
   341             {
       
   342             ret = KErrCorrupt;             
       
   343             }
       
   344         }
       
   345 
       
   346     return ret;        
       
   347 
       
   348     }
       
   349 
       
   350 
       
   351 
       
   352 //  End of File