--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lowlevellibsandfws/apputils/src/BAUTILS.CPP Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,2127 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Started by DWW, November 1995
+// BAFL utilities static class
+//
+//
+
+#include "BaUtilsImp.h"
+#include <e32hal.h>
+#include <bautils.h>
+#include <baflpan.h>
+#include <baliba.h>
+#include <hal.h>
+#include <hal_data.h>
+#include <utf.h>
+
+/**
+Mimimum length of a filename and mimimum length of a suffix.
+Note these two values are tied together.
+*/
+const TInt KInvNameAndMinSuffixLength = 2;
+
+#define ISDIGIT(c) (c-'0' >= 0 && c-'0' <= 9)
+
+_LIT(KAllDrives, "YXWVUTSRQPONMLKJIHGFEDCBAZ");
+const TInt KDriveAndPathLength = 3;
+
+// screen calibration stuff
+_LIT(KScreenCalibrationFolder,"\\System\\Data\\");
+_LIT(KScreenCalibrationFileName, "Screen.DAT");
+const TInt KScreenCalibrationPathLength = 23; // folder + filename
+
+
+// #define DO_PROFILING
+
+#if defined(DO_PROFILING)
+#pragma message ("------------ N.B. profiling of \"BaflUtils::NearestLanguageFile\" is enabled")
+#include <e32svr.h>
+#define FIRST_PROFILE_INDEX 50
+#define PROFILE_INDEX_1 (FIRST_PROFILE_INDEX+0)
+#define PROFILE_COUNT 1
+#endif
+
+// BaflUtils
+
+class BaflDir : public CDir
+ {
+public:
+ void RemoveSystem();
+ TInt SortByTable(CBaflFileSortTable* aTable);
+private:
+ TInt MinEntrySize(const TEntry & aEntry);
+ };
+
+
+LOCAL_C const TLanguage dp0[] = { ELangCanadianEnglish, ELangAmerican,ELangEnglish, ELangEnglish_Apac,ELangEnglish_Taiwan,ELangEnglish_HongKong,ELangEnglish_Prc,ELangEnglish_Japan,ELangEnglish_Thailand,ELangEnglish_India,ELangAustralian,ELangNewZealand,ELangInternationalEnglish,ELangSouthAfricanEnglish,ELangNone };
+LOCAL_C const TLanguage dp1[] = { ELangAmerican, ELangEnglish,ELangCanadianEnglish, ELangEnglish_Apac,ELangEnglish_Taiwan,ELangEnglish_HongKong,ELangEnglish_Prc,ELangEnglish_Japan,ELangEnglish_Thailand,ELangEnglish_India,ELangAustralian,ELangNewZealand,ELangInternationalEnglish,ELangSouthAfricanEnglish, ELangNone };
+LOCAL_C const TLanguage dp2[] = { ELangAustralian, ELangEnglish, ELangAmerican, ELangEnglish_Apac,ELangEnglish_Taiwan,ELangEnglish_HongKong,ELangEnglish_Prc,ELangEnglish_Japan,ELangEnglish_Thailand,ELangEnglish_India,ELangNewZealand,ELangInternationalEnglish,ELangSouthAfricanEnglish, ELangCanadianEnglish,ELangNone };
+LOCAL_C const TLanguage dp3[] = { ELangSouthAfricanEnglish, ELangEnglish, ELangAustralian, ELangAmerican, ELangEnglish_Apac,ELangEnglish_Taiwan,ELangEnglish_HongKong,ELangEnglish_Prc,ELangEnglish_Japan,ELangEnglish_Thailand,ELangEnglish_India,ELangNewZealand,ELangInternationalEnglish,ELangCanadianEnglish,ELangNone };
+LOCAL_C const TLanguage dp4[] = { ELangInternationalEnglish, ELangEnglish, ELangAustralian, ELangAmerican, ELangEnglish_Apac,ELangEnglish_Taiwan,ELangEnglish_HongKong,ELangEnglish_Prc,ELangEnglish_Japan,ELangEnglish_Thailand,ELangEnglish_India,ELangNewZealand,ELangSouthAfricanEnglish,ELangCanadianEnglish,ELangNone };
+LOCAL_C const TLanguage dp5[] = { ELangEnglish_Apac, ELangEnglish, ELangAustralian, ELangAmerican,ELangInternationalEnglish,ELangEnglish_Taiwan,ELangEnglish_HongKong,ELangEnglish_Prc,ELangEnglish_Japan,ELangEnglish_Thailand,ELangEnglish_India,ELangNewZealand,ELangSouthAfricanEnglish,ELangCanadianEnglish,ELangNone };
+LOCAL_C const TLanguage dp6[] = { ELangEnglish_Taiwan, ELangEnglish, ELangAustralian, ELangAmerican, ELangEnglish_Apac,ELangInternationalEnglish,ELangEnglish_HongKong,ELangEnglish_Prc,ELangEnglish_Japan,ELangEnglish_Thailand,ELangEnglish_India,ELangNewZealand,ELangSouthAfricanEnglish,ELangCanadianEnglish,ELangNone };
+LOCAL_C const TLanguage dp7[] = { ELangEnglish_HongKong, ELangEnglish, ELangAustralian, ELangAmerican, ELangEnglish_Apac,ELangEnglish_Taiwan,ELangInternationalEnglish,ELangEnglish_Prc,ELangEnglish_Japan,ELangEnglish_Thailand,ELangEnglish_India,ELangNewZealand,ELangSouthAfricanEnglish,ELangCanadianEnglish,ELangNone };
+LOCAL_C const TLanguage dp8[] = { ELangEnglish_Prc, ELangEnglish, ELangAustralian, ELangAmerican, ELangEnglish_Apac,ELangEnglish_Taiwan,ELangEnglish_HongKong,ELangInternationalEnglish,ELangEnglish_Japan,ELangEnglish_Thailand,ELangEnglish_India,ELangNewZealand,ELangSouthAfricanEnglish,ELangCanadianEnglish,ELangNone };
+LOCAL_C const TLanguage dp9[] = { ELangEnglish_Japan, ELangEnglish, ELangAustralian, ELangAmerican, ELangEnglish_Apac,ELangEnglish_Taiwan,ELangEnglish_HongKong,ELangEnglish_Prc,ELangInternationalEnglish,ELangEnglish_Thailand,ELangEnglish_India,ELangNewZealand,ELangSouthAfricanEnglish,ELangCanadianEnglish,ELangNone };
+LOCAL_C const TLanguage dp10[] = { ELangEnglish_Thailand, ELangEnglish, ELangAustralian, ELangAmerican, ELangEnglish_Apac,ELangEnglish_Taiwan,ELangEnglish_HongKong,ELangEnglish_Prc,ELangEnglish_Japan,ELangInternationalEnglish,ELangEnglish_India,ELangNewZealand,ELangSouthAfricanEnglish,ELangCanadianEnglish,ELangNone };
+LOCAL_C const TLanguage dp11[] = { ELangEnglish_India, ELangEnglish, ELangAustralian, ELangAmerican, ELangEnglish_Apac,ELangEnglish_Taiwan,ELangEnglish_HongKong,ELangEnglish_Prc,ELangEnglish_Japan,ELangEnglish_Thailand,ELangInternationalEnglish,ELangNewZealand,ELangSouthAfricanEnglish,ELangCanadianEnglish,ELangNone };
+LOCAL_C const TLanguage dp12[] = { ELangNewZealand, ELangEnglish, ELangAmerican, ELangEnglish_Apac,ELangEnglish_Taiwan,ELangEnglish_HongKong,ELangEnglish_Prc,ELangEnglish_Japan,ELangEnglish_Thailand,ELangEnglish_India,ELangAustralian,ELangInternationalEnglish,ELangSouthAfricanEnglish, ELangCanadianEnglish,ELangNone };
+LOCAL_C const TLanguage dp13[] = { ELangInternationalFrench,ELangFrench,ELangSwissFrench,ELangBelgianFrench,ELangCanadianFrench,ELangNone };
+LOCAL_C const TLanguage dp14[] = { ELangBelgianFrench, ELangFrench,ELangInternationalFrench,ELangSwissFrench,ELangCanadianFrench,ELangNone };
+LOCAL_C const TLanguage dp15[] = { ELangCanadianFrench, ELangFrench,ELangInternationalFrench,ELangSwissFrench,ELangBelgianFrench,ELangNone };
+LOCAL_C const TLanguage dp16[] = { ELangFrench,ELangInternationalFrench,ELangSwissFrench,ELangBelgianFrench,ELangCanadianFrench,ELangNone };
+LOCAL_C const TLanguage dp17[] = { ELangSwissFrench,ELangFrench,ELangInternationalFrench,ELangBelgianFrench,ELangCanadianFrench,ELangNone };
+LOCAL_C const TLanguage dp18[] = { ELangSwissGerman,ELangGerman,ELangAustrian,ELangNone };
+LOCAL_C const TLanguage dp19[] = { ELangAustrian,ELangGerman,ELangSwissGerman,ELangNone };
+LOCAL_C const TLanguage dp20[] = { ELangGerman,ELangSwissGerman,ELangAustrian,ELangNone };
+LOCAL_C const TLanguage dp21[] = { ELangSerbian,ELangCroatian,ELangNone };
+LOCAL_C const TLanguage dp22[] = { ELangCroatian,ELangSerbian,ELangNone };
+LOCAL_C const TLanguage dp23[] = { ELangRomanian,ELangMoldavian,ELangNone };
+LOCAL_C const TLanguage dp24[] = { ELangMoldavian,ELangRomanian,ELangNone };
+LOCAL_C const TLanguage dp25[] = { ELangBelgianFlemish,ELangDutch,ELangNone };
+LOCAL_C const TLanguage dp26[] = { ELangDutch,ELangBelgianFlemish,ELangNone };
+LOCAL_C const TLanguage dp27[] = { ELangAfrikaans,ELangDutch,ELangNone };
+LOCAL_C const TLanguage dp28[] = { ELangMalay_Apac,ELangMalay,ELangNone };
+LOCAL_C const TLanguage dp29[] = { ELangIndonesian_Apac,ELangIndonesian,ELangNone };
+LOCAL_C const TLanguage dp30[] = { ELangSpanish,ELangInternationalSpanish,ELangLatinAmericanSpanish,ELangNone };
+LOCAL_C const TLanguage dp31[] = { ELangLatinAmericanSpanish,ELangSpanish,ELangInternationalSpanish,ELangNone };
+LOCAL_C const TLanguage dp32[] = { ELangInternationalSpanish,ELangSpanish,ELangLatinAmericanSpanish,ELangNone };
+LOCAL_C const TLanguage dp33[] = { ELangCyprusGreek,ELangGreek,ELangNone };
+LOCAL_C const TLanguage dp34[] = { ELangGreek,ELangCyprusGreek,ELangNone };
+LOCAL_C const TLanguage dp35[] = { ELangSwissItalian,ELangItalian,ELangNone };
+LOCAL_C const TLanguage dp36[] = { ELangItalian,ELangSwissItalian,ELangNone };
+LOCAL_C const TLanguage dp37[] = { ELangBrazilianPortuguese,ELangPortuguese,ELangNone };
+LOCAL_C const TLanguage dp38[] = { ELangPortuguese,ELangBrazilianPortuguese,ELangNone };
+LOCAL_C const TLanguage dp39[] = { ELangFinlandSwedish,ELangSwedish,ELangNone };
+LOCAL_C const TLanguage dp40[] = { ELangSwedish,ELangFinlandSwedish,ELangNone };
+LOCAL_C const TLanguage dp41[] = { ELangCyprusTurkish,ELangTurkish,ELangNone };
+LOCAL_C const TLanguage dp42[] = { ELangTurkish,ELangCyprusTurkish,ELangNone };
+LOCAL_C const TLanguage dp43[] = { ELangHongKongChinese, ELangTaiwanChinese, ELangPrcChinese,ELangNone };
+LOCAL_C const TLanguage dp44[] = { ELangTaiwanChinese, ELangHongKongChinese,ELangPrcChinese,ELangNone };
+LOCAL_C const TLanguage dp45[] = { ELangPrcChinese, ELangHongKongChinese, ELangTaiwanChinese,ELangNone };
+LOCAL_C const TLanguage * const KEquivalentLists[] = { dp0, dp1, dp2, dp3, dp4, dp5, dp6,
+ dp7, dp8, dp9, dp10, dp11, dp12, dp13, dp14, dp15, dp16, dp17,
+ dp18, dp19, dp20, dp21, dp22, dp23, dp24, dp25, dp26, dp27,
+ dp28, dp29, dp30, dp31, dp32, dp33, dp34, dp35, dp36, dp37,
+ dp38, dp39, dp40, dp41, dp42, dp43, dp44, dp45};
+
+/**
+This function gets the list of languages that are 'equivalent' to the
+given language. We say language L1 is equivalent to language L2 if
+speakers of L2 can readily understand L1 without intentional study
+or extraordinary effort.
+
+The equivalence relationship is defined in a static table. Please refer
+to the definition of 'KEquivalentLists' for details.
+Each row in the table is formatted like this:
+@code
+L1, L2, L3, ..., Ln, ELangNone
+@codeend
+In which L2, ..., Ln are equivalents of L1, and ELangNone marks the end of an
+entry. The list is ordered. Compared with L3, L2 is nearer to L1. When choosing
+an equivalent of L1, L2 shall be preferred over L3, L3 shall be preferred
+over L4, and so on.
+L1 is always returned as the ‘nearest equivalent’ of L1 itself.
+
+BaflUtils::NearestLanguageFileV2 searches language specific resource files
+according to the 'equivalent' relationship returned by this function.
+
+@param aLang The language whose equivalents needs to be found out.
+@param aEquivalents On return, this array contains the ordered list of
+ languages that are equivalent to the given language. If there is no
+ entry for the given language in the table, this array will contain
+ two elements on return: the first is the given language itself
+ and the 2nd one is ELangNone. For any language that has equivalents
+ defined, content of he corresponding entry is returned.
+
+@see BaflUtils::NearestLanguageFileV2
+*/
+EXPORT_C void
+BaflUtils::GetEquivalentLanguageList(TLanguage aLang, TLanguagePath& aEquivalents)
+ {
+ aEquivalents[0] = aLang;
+ aEquivalents[1] = ELangNone;
+ const TInt len = sizeof(KEquivalentLists) / sizeof(KEquivalentLists[0]);
+ for (TInt i = 0; i < len; ++i)
+ {
+ const TLanguage *ptr = KEquivalentLists[i];
+ if (ptr[0] == aLang)
+ {
+ TInt index = 1;
+ while (ELangNone != *ptr)
+ {
+ aEquivalents[index++] = (TLanguage)*(++ptr);
+ }
+ aEquivalents[index] = ELangNone;
+ break;
+ } // end if ptr[0]
+ } // end for i
+ }
+
+/**
+NearestLanguageFileV2 is very similar to the existing 'NearestLanguageFile'
+function. The only difference between NearestLanguageFile and
+NearestLanguageFileV2 is the order in which language specific
+resource files are searched for.
+NearestLanguageFile searches language specific resource files in the
+order defined by the 'downgrade path' of the given language. Content of the
+downgrade path is dependent on the current active locale, and parts of
+it is runtime configurable.
+NearestLanguageFileV2 searches for language specific resource files
+in the order defined by the 'language equivalence table', which is a
+static data table fixed at build time. There is one entry in the table for
+each language that has one or more equivalents.
+
+@param aFs An active file server session.
+@param aName Name of the language-neutral resource file name which consist of
+an optional drive specification, followed by an optional path name,
+followed by basename for filename, followed by a period and extension.
+On return, in case of a match, this is replaced by the language-specific version
+which consists of the last two characters of the extension plus any preceding
+numeric characters being replaced by the language code. Remains unchanged when there's no match
+@param aLanguage On return, in case of a match, this is replaced by the corresponding language.
+ In case of no match, it is set to ELangNone.
+
+@see TLanguage
+@see BaflUtils::GetEquivalentLanguageList
+ */
+EXPORT_C void
+BaflUtils::NearestLanguageFileV2(const RFs& aFs,TFileName& aName, TLanguage& aLanguage)
+ {
+ TNearestLanguageFileFinder finder(aFs);
+ TBool goodSuffix=finder.SetFileName(aName);
+
+ // Continue only if the suffix is good.
+ if(goodSuffix)
+ {
+ // add preset customised resource drive to drive list
+ // Note that errors returned from AddCustomResourceDrive are ignored. This is because if
+ // a custom resource drive has not been found we still want to continue on with searching
+ // other drives according to our algorithm
+ finder.AddCustomResourceDrive();
+
+ GetEquivalentLanguageList(User::Language(), finder.iPath);
+ if (!finder.FindLanguageAndDrive()
+ && KErrNone != finder.FindFirstLanguageFileAndDrive())
+ finder.RepairFileName();
+ aLanguage = finder.Language();
+ }
+ else
+ {
+ aLanguage = ELangNone;
+ }
+ }
+
+// TLibAssocBase
+
+EXPORT_C TLibAssocBase::TLibAssocBase(const RLibrary& aLib,TAny* aPtr)
+ : iLibrary(aLib),iPtr(aPtr)
+/**
+Constructs the object taking the specified DLL and a class instance.
+
+@param aLib A reference to a DLL that has already been opened.
+@param aPtr An untyped pointer to an object to be associated with the DLL.
+ Typically, this object will have been created using
+ the ordinal 1 function from that DLL. */
+ {}
+
+
+
+
+EXPORT_C void TLibAssocBase::Set(const RLibrary& aLib,TAny* aPtr)
+/**
+Implements TLibAssoc::Set().
+
+@param aLib A reference to a DLL that has already been opened.
+@param aClass A pointer to an object to be associated with the DLL.
+ Typically, this object will have been created using
+ the ordinal 1 function from that DLL.
+
+@see TLibAssoc::Set */
+ {
+ __ASSERT_ALWAYS(iLibrary.Handle()==KNullHandle&&iPtr==NULL,Panic(EBafPanicLibAssocAlreadySet));
+ iLibrary=aLib;
+ iPtr=aPtr;
+ }
+
+
+
+
+EXPORT_C void TLibAssocBase::DoUnload(TAny* aThis)
+/**
+Calls Close() on the associated DLL.
+
+@param aThis An untyped pointer to a TLibAssoc type.
+*/
+ {
+ TLibAssocBase& l=*(TLibAssocBase*)aThis;
+ l.iPtr=NULL;
+ l.iLibrary.Close();
+ }
+
+//
+// class BaflUtils
+//
+EXPORT_C void BaflUtils::CopyWithTruncation(TDes& aDest,const TDesC& aSrc,TChar aTruncationSymbol)
+/** Copies a descriptor, abbreviating it to fit the destination descriptor.
+
+If aSrc is less than the maximum length of aDest, then the string is simply
+copied to aDest.
+
+If this is not so, then the left-most characters of aSrc are copied to aDest,
+up to aDest's maximum length-1. aDest's final character is set to be aTruncationSymbol.
+
+@param aDest On return, the truncated string
+@param aSrc The string to truncate
+@param aTruncationSymbol The truncation character to add */
+ { // static
+ TInt maxLength=aDest.MaxLength();
+ if (aSrc.Length()<=maxLength)
+ aDest.Copy(aSrc);
+ else
+ {
+ aDest.Copy(aSrc.Left(maxLength-1));
+ aDest.Append(aTruncationSymbol);
+ }
+ }
+
+EXPORT_C TBool BaflUtils::FileExists(const RFs& aFileSession,const TDesC& aFileName)
+/** Checks if the specified file exists.
+
+@param aFs File server session
+@param aFileName File to check
+@return ETrue if the file exists, otherwise EFalse */
+ { // static
+ TEntry entry;
+ return(aFileSession.Entry(aFileName,entry)==KErrNone);
+ }
+
+EXPORT_C TBool BaflUtils::PathExists(RFs& aFs,const TDesC& aPath)
+/** Tests whether a path exists.
+
+The path should contain a drive letter and a directory, or EFalse is returned.
+EFalse is also returned if it contains a filename or filename extension.
+
+If the path is badly formed, for instance if it contains illegal characters,
+or any directory name consists of a single or double dot, or any directory
+name includes wildcard characters, the function returns EFalse.
+
+@param aFs A connected session with the file server.
+@param aPath The path to test for. It should end in a backslash.
+@return ETrue if the path exists, EFalse if not. EFalse is also returned if the
+specified path is badly formed. */
+ { // static
+ TParse parse;
+ TInt retcode;
+ retcode = parse.Set(aPath, NULL, NULL);
+ if (retcode != KErrNone)
+ return EFalse;
+ if ((! parse.DrivePresent()) || (parse.NameOrExtPresent()))
+ return EFalse;
+ if (parse.Path().Length() == 0)
+ return EFalse;
+ TFileName dirName = parse.DriveAndPath();
+ if (dirName.Length() > KMaxFileName)
+ return(EFalse);
+ RDir dir;
+ retcode = dir.Open(aFs,dirName,0);
+ if (retcode == KErrNone)
+ dir.Close();
+ return (retcode == KErrNone);
+ }
+
+EXPORT_C void BaflUtils::EnsurePathExistsL(RFs& aFileSession,const TDesC& aFileName)
+/** Makes one or more directories, if they do not already exist.
+
+Any valid path component in the specified path that does not already exist
+is created as a directory. If the specified path already exists, the function
+returns normally.
+
+@param aFs File server session
+@param aFileName Path to ensure exists
+@see RFs::MkDirAll() */
+ { // static
+ TInt error=aFileSession.MkDirAll(aFileName);
+ if (error!=KErrAlreadyExists)
+ User::LeaveIfError(error);
+ }
+
+EXPORT_C TPtrC BaflUtils::ExtractAppNameFromFullName(const TFullName &aName)
+/** Gets the application name from a full thread name.
+
+@param aName Thread name
+@return Application name
+@see RThread */
+ {
+ // static - return the app name (after first :: before next ::, if any) from a full thread name
+ TChar delimiter=':';
+ TInt start=aName.Locate(delimiter);
+ if (start<0)
+ start=0; // should never happen
+ else if (aName.Length()>start+2)
+ start+=2;
+ TPtrC rest=aName.Mid(start);
+ TInt end=rest.Locate(delimiter);
+ return end<0 ? rest : rest.Left(end);
+ }
+
+LOCAL_C TBool IsLanguageExtended(const TLanguage aLanguage)
+ {
+ // For compatibility reasons, ELangNone is 0xFFFF. However, it's not an extended language.
+ if ((aLanguage==ELangNone) || ((static_cast<TUint>(aLanguage))<=KDialectMask))
+ return EFalse;
+ else
+ return ETrue;
+ }
+
+
+LOCAL_C TLanguage BaseLanguage(const TLanguage aLanguage)
+ {
+ if (IsLanguageExtended(aLanguage))
+ return static_cast<TLanguage>(aLanguage & KDialectMask);
+ else
+ return aLanguage;
+ }
+
+LOCAL_C TLanguage NextLanguage(TLanguage aLanguage)
+/** Returns the next best language to use after aLanguage,
+based on Symbian's base table of language near-equivalence.
+@internalAll */
+ {
+ switch (aLanguage)
+ {
+ case ELangAustralian:
+ case ELangNewZealand:
+ case ELangSouthAfricanEnglish:
+ case ELangInternationalEnglish:
+ case ELangAmerican:
+ case ELangEnglish_Apac:
+ case ELangEnglish_Taiwan:
+ case ELangEnglish_HongKong:
+ case ELangEnglish_Prc:
+ case ELangEnglish_Japan:
+ case ELangEnglish_Thailand:
+ return ELangEnglish;
+ case ELangCanadianEnglish:
+ return ELangAmerican; // 2-stage downgrade
+ case ELangSwissFrench:
+ case ELangBelgianFrench:
+ case ELangInternationalFrench:
+ case ELangCanadianFrench:
+ return ELangFrench;
+ case ELangSwissGerman:
+ case ELangAustrian:
+ return ELangGerman;
+ case ELangInternationalSpanish:
+ case ELangLatinAmericanSpanish:
+ return ELangSpanish;
+ case ELangSwissItalian:
+ return ELangItalian;
+ case ELangFinlandSwedish:
+ return ELangSwedish;
+ case ELangCyprusTurkish:
+ return ELangTurkish;
+ case ELangBelgianFlemish:
+ return ELangDutch;
+ case ELangHongKongChinese:
+ return ELangTaiwanChinese;
+ case ELangCyprusGreek:
+ return ELangGreek;
+ case ELangMalay_Apac:
+ return ELangMalay;
+ case ELangBrazilianPortuguese:
+ return ELangPortuguese;
+ default:
+ return ELangNone;
+ }
+ }
+
+
+void AddLanguage(TLanguagePath& aPath, TLanguage aNewLanguage)
+/** Add language to the language path if there is space.
+The first empty slot must have "ELangNone" in it. This will also be true
+on exit. */
+ {
+ TLanguage *p = aPath;
+ const TLanguage *end = &(aPath[KMaxDowngradeLanguages]);
+ while (p != end)
+ {
+ if (*p == aNewLanguage)
+ // language already in list
+ break;
+ if (*p == ELangNone)
+ {
+ // found the end of the list
+ p[0] = aNewLanguage;
+ p[1] = ELangNone;
+ break;
+ }
+ ++p;
+ }
+ return;
+ }
+
+void MakeLanguageDowngradePath(TLanguagePath& aPath,
+ TLanguage aCurrent, TLanguage aIdeal, const TLocale& aLocale)
+ {
+ TInt j = 0;
+ if( aIdeal != ELangNone)
+ {
+ aPath[j++]=aIdeal;
+ }
+ aPath[j++] = aCurrent;
+ aPath[j++] = ELangNone;
+
+ if (aCurrent & ~KDialectMask)
+ AddLanguage(aPath, static_cast<TLanguage>(aCurrent & KDialectMask));
+
+ for (TInt i=0;i<=2;i++)
+ {
+ AddLanguage(aPath, aLocale.LanguageDowngrade(i));
+ AddLanguage(aPath, BaseLanguage(aLocale.LanguageDowngrade(i)));
+ }
+
+ while (ELangNone != (aCurrent = NextLanguage(BaseLanguage(aCurrent))))
+ AddLanguage(aPath, aCurrent);
+ }
+
+TInt RRealDirectoryScanner::Open(RFs& aFs, const TDesC& aMatchPattern)
+ {
+ return iDir.Open(aFs, aMatchPattern,
+ KEntryAttReadOnly | KEntryAttHidden | KEntryAttSystem | KEntryAttArchive);
+ }
+
+TInt RRealDirectoryScanner::Next(TEntry& aOut)
+ {
+ return iDir.Read(aOut);
+ }
+
+void RRealDirectoryScanner::Close()
+ {
+ iDir.Close();
+ }
+
+/**
+Simply counts the number of numerical characters at the end of the name passed.
+
+@internalComponent
+@param aFilename The filename to parse
+
+@return Count of the numeric digits at the end of the name passed,
+ e.g. x.r491 gives 3.
+*/
+TInt TNearestLanguageFileFinder::CountDigitsFromEnd(const TDesC& aFilename)
+ {
+ TInt digitCount = 0;
+
+ for (TInt idx = aFilename.Length()-1; idx>=0 && ISDIGIT (aFilename [idx]); --idx)
+ {
+ ++digitCount;
+ }
+
+ return digitCount;
+ }
+
+
+/**
+Counts the number of digits at the end of a filename.
+
+@internalComponent
+@param aFilename The filename to parse
+
+@return Count of the numeric digits at the end of the suffix,
+ e.g. x.r491 gives 3.
+ 0 if no numeric end of suffix,
+ KErrBadName for an invalid filename,
+ KErrNotSupported if the filename (minus path) is less
+ than or equal to KInvNameAndMinSuffixLength in length
+*/
+TInt TNearestLanguageFileFinder::CountDigitsFromEndInSuffix (const TDesC& aFilename)
+ {
+ TInt digitCount = 0;
+ TInt slashIdx = 0;
+ TInt len = aFilename.Length ();
+
+ // NOTE: We didn't use TChar here as they are too slow.
+ // We also didn't use TParse as they are too large.
+
+ // don't work on the path
+ for (slashIdx=len-1; slashIdx >= 0 && aFilename[slashIdx] != '\\'; --slashIdx)
+ {/*do nothing*/};
+
+ // Get new length
+ if (slashIdx>=0) {len = len-slashIdx-1;}
+
+ // Initial test to see if filename legal size.
+ if (len > KInvNameAndMinSuffixLength)
+ {
+ digitCount = CountDigitsFromEnd(aFilename);
+
+ // Can't store something bigger or we'll panic!
+ if (digitCount > KMaxSuffixLength)
+ {
+ digitCount = KErrBadName;
+ }
+ else
+ // numeric filename, e.g. "1234".
+ // No preceeding alpha character
+ if (!(len-digitCount))
+ {
+ digitCount = KErrBadName;
+ }
+ }
+ else
+ {
+ digitCount = KErrNotSupported;
+ }
+
+ return digitCount;
+ }
+
+RDirectoryScanner& TNearestLanguageFileFinder::DirectoryScanner()
+ {
+ return iDirScanner;
+ }
+
+TBool TNearestLanguageFileFinder::FileExists(const TDesC& aFileName) const
+ {
+ return BaflUtils::FileExists(iFs, aFileName);
+ }
+
+TBool TNearestLanguageFileFinder::FindDrive()
+ {
+ ASSERT(iFileName);
+ TBool found=EFalse;
+ TInt driveLength=iDrives.Length();
+ for (TInt drive = 0; drive!=driveLength; ++drive)
+ {
+ (*iFileName)[0] = iDrives[drive];
+ if (FileExists(*iFileName))
+ {
+ found=ETrue;
+ break;
+ }
+ }
+ return found;
+ }
+
+TBool TNearestLanguageFileFinder::AppendLanguageCode(TLanguage aLanguage)
+ {
+ TInt rest = static_cast<TInt>(aLanguage);
+#ifdef _DEBUG
+ _LIT(KErrorMessage, "Bafl");
+#endif
+ __ASSERT_DEBUG(0 <= rest, User::Panic(KErrorMessage,KErrArgument));
+ iFileName->SetLength(iBaseLength);
+ const TInt remaining = iFileName->MaxLength() - iBaseLength;
+ TInt soFar = 0;
+ TBuf<1> num;
+ num.Append('0');
+ TBool appendLangSuccess = ETrue;
+ TInt digitCount = 0;
+ TInt digit = 0;
+ while (rest)
+ {
+ if (remaining == soFar)
+ {
+ // no more room in descriptor- return rather than panic,
+ // file cannot exist.
+ iFileName->SetLength(iBaseLength);
+ appendLangSuccess= EFalse;
+ break;
+ }
+ // Convert the number to ASCII by consistantly getting the base 10 remainder to convert.
+ // The number is updated minus the remainder for the next iteration.
+ // eg (rest = 123) -> (12, r3) -> (1, r2) -> (0, r1)
+ // Then insert the ASCII representation of the remainder into the filename end
+ // so it appears the correct way round.
+ // eg (filename.r) -> (filename.r3) -> (filename.r23) -> (filename.r123)
+ digit = rest % 10;
+ digitCount++;
+ rest /= 10;
+ num[0] = static_cast<TText16>(digit + '0');
+ iFileName->Insert(iBaseLength, num);
+
+ // Minimum suffix length is KInvNameAndMinSuffixLength
+ // so we have to insert zeros to make this up.
+ while (!rest && digitCount < KInvNameAndMinSuffixLength)
+ {
+ num[0] = static_cast<TText16>('0');
+ iFileName->Insert(iBaseLength, num);
+ ++digitCount;
+ }
+
+ ++soFar;
+ }
+
+ return appendLangSuccess;
+ }
+
+
+TBool TNearestLanguageFileFinder::FindLanguageAndDrive()
+/** Search for files across all drives in all languages in the path plus the
+language-neutral file. */
+ {
+ ASSERT(iFileName);
+ // No point appending if the suffix is bad
+ for (const TLanguage* currentLang = iPath; *currentLang != ELangNone; ++currentLang)
+ {
+ if (AppendLanguageCode(*currentLang) && FindDrive())
+ {
+ iLanguage = *currentLang;
+ return ETrue;
+ }
+ }
+ // search for language-neutral file
+ iFileName->SetLength(iBaseLength);
+ iFileName->Append(iSuffix);
+ return FindDrive();
+ }
+
+TInt TNearestLanguageFileFinder::LanguageNumberFromFile(const TDesC& aFileName, const TDesC& aStem)
+ {
+ TInt lang = 0;
+ TInt multiplier = 1;
+ TInt leadingZeroCount = 0;
+ TInt languageNumber = KErrNotFound;
+ const TText* firstChar = aFileName.Ptr();
+ const TText* lastChar = firstChar + aFileName.Length() - 1;
+ const TText* currentChar = lastChar;
+ // string cannot contain only numbers, because it must have a ':' in it
+ while ('0' <= *currentChar && *currentChar <= '9')
+ {
+ if (*currentChar == '0')
+ leadingZeroCount++;
+ else
+ {
+ leadingZeroCount = 0;
+ lang += multiplier * (*currentChar - '0');
+ }
+ multiplier *= 10;
+ --currentChar;
+ }
+ TInt along=lastChar - currentChar;
+ if (2 <= along)
+ {
+ // We have at least 2 digits at the end.
+ // trim of bad leading zeros
+ TInt maxTrim = along - 2;
+ if (maxTrim < leadingZeroCount)
+ {
+ leadingZeroCount = maxTrim;
+ }
+ currentChar += leadingZeroCount;
+ // we have at least 2 digits at the end but does the rest of it match the stem?
+ TPtrC foundStem(firstChar, currentChar - firstChar + 1);
+ //foundStem.CompareF(aStem.Right(foundStem.Length()))
+ if (0 == foundStem.CompareF(aStem))
+ {
+ languageNumber=lang;
+ }
+ }
+ return languageNumber;
+ }
+
+TInt TNearestLanguageFileFinder::FindFirstLanguageFile(RFs& aFs)
+ {
+ ASSERT(iFileName);
+ iFileName->SetLength(iBaseLength);
+ TPtrC name(*iFileName);
+ TParsePtrC nameToParse(name);
+ TPtrC nameStem(nameToParse.NameAndExt());
+ iFileName->Append('*');
+ TInt bestLanguageMatch = KMaxTInt;
+ RDirectoryScanner& scanner = DirectoryScanner();
+ TInt err = scanner.Open(aFs, *iFileName);
+ if (err != KErrNone)
+ {
+ return err;
+ }
+ TEntry entry;
+ while (KErrNone == scanner.Next(entry))
+ {
+ TInt lang = LanguageNumberFromFile(entry.iName, nameStem);
+ if (0 < lang && lang < bestLanguageMatch)
+ {
+ bestLanguageMatch = lang;
+ }
+ }
+ scanner.Close();
+ if (bestLanguageMatch != KMaxTInt)
+ {
+ iLanguage = static_cast<TLanguage>(bestLanguageMatch);
+ AppendLanguageCode(static_cast<TLanguage>(bestLanguageMatch));
+ return KErrNone;
+ }
+ return KErrNotFound;
+ }
+
+// Try each drive for any language files
+// iFileName must have a directory specifier
+TInt TNearestLanguageFileFinder::FindFirstLanguageFileAndDrive()
+ {
+ ASSERT(iFileName);
+ TInt findFirstResult=KErrNotFound;
+ TInt driveLength=iDrives.Length();
+ for (TInt drive = 0; drive != driveLength; ++drive)
+ {
+ (*iFileName)[0] = iDrives[drive];
+ TInt err = FindFirstLanguageFile(CONST_CAST(RFs&,iFs));
+ if (err == KErrNone || err == KErrNoMemory)
+ {
+ findFirstResult=err;
+ break;
+ }
+ }
+ return findFirstResult;
+ }
+
+/**
+Invalid filenames are any filename whose length (minus path) must be greater
+than KInvNameAndMinSuffixLength, and whose form is purely numerical, i.e. '1234'
+*/
+TBool TNearestLanguageFileFinder::SetFileName(TFileName& aFileName)
+ {
+ iDrives.Zero();
+ iFileName = &aFileName;
+ iOriginalBaseLength = iFileName->Length();
+
+ TInt suffixLength = CountDigitsFromEndInSuffix (aFileName);
+
+ // No point trying for filenames thats are badly formed
+ // or that are too large.
+ if (suffixLength >= 0 &&
+ KInvNameAndMinSuffixLength < iOriginalBaseLength)
+ {
+ if (suffixLength > 0)
+ {
+ // all of suffix to be replaced
+ iSuffix = iFileName->Right(suffixLength);
+ iOriginalBaseLength -= suffixLength;
+ iFileName->SetLength(iOriginalBaseLength);
+ }
+ else
+ {
+ // No numerical part to suffix
+ TInt periodIdx = 0;
+
+ // Search for the period within range KInvNameAndMinSuffixLength
+ // from the end. As this must work for all values of
+ // KInvNameAndMinSuffixLength
+ for (TInt i = iOriginalBaseLength-1;
+ !periodIdx && i >= (iOriginalBaseLength-KInvNameAndMinSuffixLength-1);
+ --i)
+ {
+ if ((*iFileName) [i] == '.')
+ {
+ periodIdx = i;
+ }
+ }
+
+ // Don't handle files ending in a period.
+ // This is because the behaviour is different between Windows
+ // and Symbian Fs. In Windows it strips the period off.
+ //
+ // However, and this shouldn't happen as it is not shown
+ // (in the documentation) to be valid.
+ // Just try our best.
+ if (periodIdx == iOriginalBaseLength-1)
+ {
+ iSuffix.Zero();
+ return EFalse;
+ }
+ else
+ if (periodIdx)
+ {
+ // If there are KInvNameAndMinSuffixLength chars after the period
+ // simply replace them.
+ TInt right = iOriginalBaseLength-periodIdx-1;
+ iSuffix = iFileName->Right(right);
+ iOriginalBaseLength -= right;
+ iFileName->SetLength(iOriginalBaseLength);
+ }
+ else
+ {
+ // Make the suffix start from KInvNameAndMinSuffixLength
+ // from the right
+ TInt right = KInvNameAndMinSuffixLength;
+ iSuffix = iFileName->Right(right);
+ iOriginalBaseLength -= right;
+ iFileName->SetLength(iOriginalBaseLength);
+ }
+ }
+ }
+ else
+ {
+ // bad or no suffix - treat the same
+ iSuffix.Zero();
+ return EFalse;
+ }
+
+ // For filenames with no drive letter prefix and also for filenames
+ // shorter than the drive letter length, i.e. with no drive
+ // information, insert it.
+ // Handles if the user simply enters the drive, e.g. "c:".
+ if (iOriginalBaseLength < KMaxDriveName || (*iFileName)[1] != ':')
+ {
+ // Set up the default if none supplied and make room in the filename
+ // array to contain a drive specification. Set initial drive letter to -1
+ // so the iFileName is repaired before exited
+ iInitialDriveLetter = -1;
+ iFileName->Insert(0, _L("_:"));
+ iDrives.Append('Z');
+ }
+ else
+ {
+ // Use the drive supplied inthe aName to NearestLanguageFile()
+ iInitialDriveLetter = (*iFileName)[0];
+ iDrives.Append(iInitialDriveLetter);
+ }
+
+ iBaseLength = iFileName->Length();
+
+ return ETrue;
+ }
+
+
+TLanguage TNearestLanguageFileFinder::Language()
+ {
+ return iLanguage;
+ }
+
+TNearestLanguageFileFinder::TNearestLanguageFileFinder(
+ const RFs& aFs)
+ : iFs(aFs), iFileName(0), iLanguage(ELangNone)
+ {
+ }
+
+void TNearestLanguageFileFinder::RepairFileName()
+ {
+ ASSERT(iFileName);
+ iFileName->SetLength(iBaseLength);
+ if (iInitialDriveLetter == -1)
+ iFileName->Delete(0, 2);
+ else
+ (*iFileName)[0] = static_cast<TText>(iInitialDriveLetter);
+ iFileName->SetLength(iOriginalBaseLength);
+ iFileName->Append(iSuffix);
+ }
+
+
+/**
+Add the custom resource drive to the start of the iDrives string.
+
+The custom resource drive is a preset writeable drive on which customised
+resource files may be present. This drive takes priority over the other
+drives when searching for language files.
+
+@return KErrNone if iDrives string was successfully modified; KErrAlreadyExists
+if the drive is already present in the string; otherwise one of
+the other system-wide error codes (iDrives will be unmodified).
+*/
+TInt TNearestLanguageFileFinder::AddCustomResourceDrive()
+ {
+ TInt drive = GetCustomResourceDriveNumber();
+ if (drive<0)
+ return drive;
+
+ // if drive not already in drive list
+ if (iDrives.LocateF('A' + drive) < 0)
+ {
+ // add it
+ _LIT(KDrivePlaceholder, "_");
+ iDrives.Insert(0, KDrivePlaceholder);
+ iDrives[0] = 'A' + drive;
+ return KErrNone;
+ }
+ else
+ return KErrAlreadyExists;
+ }
+
+
+void TNearestLanguageFileFinder::AddAllDrives()
+ {
+ ASSERT(iDrives.Length() < 2);
+ if (iDrives.Length() == 0)
+ {
+ iDrives = KAllDrives;
+ return;
+ }
+ TInt pos = KAllDrives().LocateF(iDrives[0]);
+ if (pos < 0)
+ {
+ iDrives = KAllDrives;
+ return;
+ }
+ iDrives.Append(KAllDrives().Left(pos));
+ iDrives.Append(KAllDrives().Mid(pos + 1));
+ }
+
+
+/**
+Get the value of the custom resource drive.
+
+The custom resource drive is a preset writeable drive on which customised language resource
+files can reside. The drive number is accessed via the HAL attribute ECustomResourceDrive.
+It is then returned if it has been defined as a valid drive no.
+Otherwise for backward compatibility reasons an attempt is then made to access the system
+drive HAL attribute instead. This drive number is returned if it has been defined as a valid
+drive number.
+Otherwise if neither a valid ECustomResourceDrive or ESystemDrive exists then KErrNotFound
+is returned.
+
+Note that the ESystemDrive HAL attribute has been deprecated. It is accessed here to cater
+for existing implementations which still expect it to be used.
+
+@return The drive number (corresponding to a TDriveNumber value) if successful;
+KErrNotFound if neither a valid ECustomResourceDrive or a valid ESystemDrive HAL attribute
+is defined;
+
+@see HAL::ECustomResourceDrive
+@see HAL::ESystemDrive
+*/
+TInt TNearestLanguageFileFinder::GetCustomResourceDriveNumber() const
+ {
+ TInt drive = KErrNotFound;
+
+ // access custom resource drive attribute
+ if (HAL::Get(HAL::ECustomResourceDrive, drive) == KErrNone)
+ {
+ // check that drive is valid
+ if (drive>=EDriveA && drive<=EDriveZ)
+ return drive;
+ }
+
+ // access system drive attribute
+ // (Note that ESystemDrive is deprecated. It is checked here
+ // solely for backward compatibility reasons.)
+ if (HAL::Get(HAL::ESystemDrive, drive) == KErrNone)
+ {
+ // check that drive is valid
+ if (drive>=EDriveA && drive<=EDriveZ)
+ return drive;
+ }
+
+ return KErrNotFound;
+ }
+
+
+
+/** Get the value of the system drive.
+
+The system drive can be set to one of the built-in read/write drives. Which
+drive is used is hardware-dependent. On some hardware, there may not be a
+system drive. The system drive is used as the drive on which localisable files
+are searched for. This enables a phone to be localised dynamically, using
+files not in the ROM.
+
+@param aDriveNumber On return, contains the drive number of the system drive.
+@return KErrNone is always returned.
+
+@deprecated This method has been replaced by (and now internally calls)
+RFs:GetSystemDrive, which always returns a valid drive number.
+
+@see BaflUtils::NearestLanguageFile
+@see RFs::GetSystemDrive
+*/
+EXPORT_C TInt BaflUtils::GetSystemDrive(TDriveNumber& aDriveNumber)
+ {
+ aDriveNumber = RFs::GetSystemDrive();
+ return KErrNone;
+ }
+
+
+/** Set most appropriate extension language code for filename and set corresponding language.
+
+Symbian uses numeric values to identify natural languages as specified by the TLanguage enumeration
+defined in e32const.h. These values are used at the end of filename extensions to identify the
+languages pertaining to files which have language specific variants such as resource files.
+For instance filename.r01 and filename.r02 would be the English and French versions of the
+resource file filename.rsc. Language codes can be between 2 to 5 digits in length.
+
+Starting from Symbian OS v7.0 this function constructs and uses a language downgrade path which
+consists of up to sixteen TLanguage values the first of which is the ideal language followed by
+the language of the current locale. Up to the next three can be customised using
+TLocale::SetLanguageDowngrade(). The rest of the language downgrade path is based on a
+table of language near equivalence which is internal to Symbian.
+
+This function searches the custom resource drive (if set, retrieved from HAL)
+and then searches the optional drive specified in aName or 'Z:' if none is
+specified in aName. The custom resource drive is retrieved from the HAL
+attribute ECustomResourceDrive if set, if not set it will retrieve the legacy
+value set in the legacy HAL attribute ESystemDrive. No custom resource drive
+is searched if neither are set.
+Note - setting the custom resource drive will reduce the performance of this
+routine which will adversely affect device performance e.g. at boot up.
+On NAND Flash based devices use of a composite Z: drive file system made up of multiple
+ROM images is the preferred mechanism for customising language resources on devices in
+Symbian OS 9.2 onwards, see Developer Library » Base Porting Guide » Porting: background
+information » NAND flash » NAND Flash image format. Thus use of the custom resource drive
+HAL attribute is effectively obsolete.
+
+The last two characters of aName are removed along with any digits which appear before them.
+Then language codes specified in the constructed language downgrade path are appended in turn to
+aName as a match is searched for in the file system. In case no match is found using the
+constructed language downgradepath then files in the specified directory are searched for a
+suitable extension with preference given to the one specified if present. In cases where a
+match takes place the aName and aLanguage arguments are updated otherwise aName is left
+unchanged and aLanguage is set to ELangNone.
+
+Here are some examples of correct and incorrect function usage with different aName inputs,
+file system state and downgrade paths as follows:
+
+@code
+Following files exist:
+C:\\abc.rsc - Language Neutral resource file.
+C:\\abc.r01 - Resource file for the English language.
+C:\\abc.r10 - Resource file for the American-English language.
+C:\\abc.r160 - Resource file for the English as appropriate in Japan.
+
+Constructed Downgrade Language Path cases:
+- Case 1. (ELangAmerican -> ELangEnglish -> ELangNone).
+- Case 2. (ELangEnglish_Japan -> ELangEnglish -> ELangNone).
+- Case 3. Same as case 1, However "C:\\abc.r10" is deleted prior to the function call.
+- Case 4. Same as case 1, However both "C:\\abc.r01" and "C:\\abc.r10" are deleted prior to the function call.
+@endcode
+
+@code
+Input aName . . . . Output aName. . . aLanguage . . . . . Description
+--------------------------------------------------------------------------------------------------------------------
+"C:\\abc.rsc" . . . "C:\\abc.r10" . . ELangAmerican . . . Match on first language (Case 1)
+"C:\\abc.r10" . . . "C:\\abc.r10" . . ELangAmerican . . . Match, However it's not the intended use of
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . the function (Case 1)
+"C:\\abc.r" . . . . "C:\\abc.r" . . . ELangNone . . . . . The no. of characters in the suffix is less than
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . KInvNameAndMinSuffixLength(2)(Case 1)
+"C:\\abc.". . . . . "C:\\abc.". . . . ELangNone . . . . . Invalid Suffix: The filename ends with a period(Case 1)
+"C:\\abc.r123456" . "C:\\abc.r123456" ELangNone . . . . . Invalid Suffix: The no. of digits in the suffix is greater
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . than KMaxSuffixLength(5) (Case 1)
+"C:\\abc.10". . . . "C:\\abc.10 . . . ELangNone . . . . . Invalid Suffix: There's no proceeding alphabetical
+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . characters in the suffix (Case 1)
+"\\abc.rsc" . . . . "\\abc.rsc" . . . ELangNone . . . . . No drive so Z: search, no match (Case 1)
+"C:\\abc.rsc" . . . "C:\\abc.r160". . ELangEnglish_Japan. Match for language file 3 digits long (Case 2)
+"C:\\abc.rsc" . . . "C:\\abc.r01" . . ELangEnglish. . . . Match on second language (Case 3)
+"C:\\abc.rsc" . . . "C:\\abc.rsc" . . ELangNone . . . . . No corresponding langauge file match found (Case 4)
+---------------------------------------------------------------------------------------------------------------------
+@endcode
+
+@param aFs File server session.
+@param aName Optional drive specification, followed by optional path name,
+followed by basename for filename, followed by period and extension.
+On return, in case of a match, this is replaced by the language-specific version
+which consists of the last two characters of the extension plus any preceding
+numeric characters being replaced by the language code. Remains unchanged when there's no match
+@param aLanguage On return, in case of a match, this is replaced by the corresponding language.
+In case of no match it's set to ELangNone.
+@see TLanguage
+@see BaflUtils::GetDowngradePathL
+@see TLocale::SetLanguageDowngrade
+*/
+EXPORT_C void BaflUtils::NearestLanguageFile(const RFs& aFs,TFileName& aName, TLanguage& aLanguage)
+ {
+#if defined(DO_PROFILING)
+ RDebug::ProfileReset(FIRST_PROFILE_INDEX, PROFILE_COUNT);
+ RDebug::ProfileStart(PROFILE_INDEX_1);
+#endif
+ TNearestLanguageFileFinder finder(aFs);
+ TBool goodSuffix=finder.SetFileName(aName);
+
+ // Only continue if the suffix is good.
+ if(goodSuffix)
+ {
+ // add preset customised resource drive to drive list
+ // Note that errors returned from AddCustomResourceDrive are ignored. This is because if
+ // a custom resource drive has not been found we still want to continue on with searching
+ // other drives according to our algorithm
+ finder.AddCustomResourceDrive();
+
+ TLocale locale;
+ TLanguage idealLanguage;
+ idealLanguage = IdealLanguage();
+ MakeLanguageDowngradePath(finder.iPath, User::Language(), idealLanguage, locale);
+ if (!finder.FindLanguageAndDrive()
+ && KErrNone != finder.FindFirstLanguageFileAndDrive())
+ finder.RepairFileName();
+ aLanguage = finder.Language();
+ }
+
+#if defined(DO_PROFILING)
+ RDebug::ProfileEnd(PROFILE_INDEX_1);
+ TProfile profile[PROFILE_COUNT];
+ RDebug::ProfileResult(&profile[0], FIRST_PROFILE_INDEX, PROFILE_COUNT);
+ if(goodSuffix)
+ {
+ RDebug::Print(_L("BaflUtils::NearestLanguageFile profile info: %d.%03ds"), profile[PROFILE_INDEX_1-FIRST_PROFILE_INDEX].iTime/1000000, profile[PROFILE_INDEX_1-FIRST_PROFILE_INDEX].iTime%1000000);
+ }
+ else
+ {
+ RDebug::Print(_L("BaflUtils::NearestLanguageFile (bad suffix ) profile info: %d.%03ds"), profile[PROFILE_INDEX_1-FIRST_PROFILE_INDEX].iTime/1000000, profile[PROFILE_INDEX_1-FIRST_PROFILE_INDEX].iTime%1000000);
+ }
+#endif
+ }
+
+/** Searches for the file with the correct language extension for the language
+of the current locale, or failing this, the best matching file.
+
+@param aFs File server session.
+@param aName File name as it would be without a language-specific extension.
+On return, this is changed to the language-specific version. If no such file
+is found, the name is unchanged.
+@see BaflUtils::NearestLanguageFile(const RFs& aFs,TFileName& aName, TLanguage& aLanguage) */
+EXPORT_C void BaflUtils::NearestLanguageFile(const RFs& aFs,TFileName& aName)
+ {
+ TLanguage language;
+
+ NearestLanguageFile( aFs, aName, language);
+
+ (void)language;
+ }
+
+/** Set the ideal language for the thread.
+This interface is intended for the use of UIKON only.
+
+@param aLanguage Ideal language.
+@return KErrNone, if successful; KErrNoMemory if there is not enough memory @see TLanguage
+@see BaflUtils::NearestLanguageFile()
+@internalAll */
+EXPORT_C TInt BaflUtils::SetIdealLanguage(TLanguage aLanguage)
+ {
+ TLanguage* langPtr=(TLanguage*)Dll::Tls();
+ if( langPtr==NULL)
+ {
+ langPtr=(TLanguage*)User::Alloc(sizeof(TLanguage));
+
+ if(!langPtr)
+ return(KErrNoMemory);
+
+ TInt ret=Dll::SetTls(langPtr);
+
+ if(ret!=KErrNone)
+ return(ret);
+ }
+ *langPtr=aLanguage;
+ return(KErrNone);
+ }
+
+/** Get the ideal language of the thread.
+This interface is intended for the use of UIKON only.
+
+@return Ideal language if set, ELangNone if not set
+@see BaflUtils::NearestLanguageFile()
+@internalAll */
+EXPORT_C TLanguage BaflUtils::IdealLanguage()
+ {
+ TLanguage* langPtr=(TLanguage*)Dll::Tls();
+
+ if( langPtr==NULL)
+ {
+ return(ELangNone);
+ }
+
+ return(*langPtr);
+ }
+
+EXPORT_C void BaflUtils::ReleaseIdealLanguage()
+/** Releases the ideal language store if it has been allocated.
+This interface is intended for the use of UIKON only.
+
+@internalAll */
+ {
+ TLanguage* aLanguage=(TLanguage*)Dll::Tls();
+ if( aLanguage==NULL)
+ return;
+
+ delete aLanguage;
+ Dll::FreeTls();
+ }
+
+EXPORT_C TInt BaflUtils::IsFolder(const RFs& aFs, const TDesC& aFullName, TBool& aIsFolder)
+/** Checks if the specified item is a folder.
+
+@param aFs File server session
+@param aFullName Name to check
+@param aIsFolder ETrue if aFullName is a folder, otherwise EFalse
+@return KErrNone if successful, otherwise another of the system-wide error
+codes */
+ {
+ TParsePtrC parse(aFullName);
+ if ((parse.DriveAndPath().Length() == KDriveAndPathLength) && (aFullName.Length() == KDriveAndPathLength))
+ {
+ aIsFolder = ETrue;
+ return(KErrNone);
+ }
+ TEntry entry;
+ TInt retcode = aFs.Entry(aFullName, entry);
+ if (retcode == KErrNone)
+ aIsFolder = ((entry.iAtt & KEntryAttDir)==KEntryAttDir);
+
+ return(retcode);
+ }
+
+
+EXPORT_C TBool BaflUtils::FolderExists(RFs& aFs, const TDesC& aFolderName)
+/** Tests whether a folder exists.
+
+The folder is specified in a path. The path can omit the drive letter, in
+which case the drive letter is taken from the session path.
+
+If the path is badly formed, for instance if it contains illegal characters,
+or any directory name consists of a single or double dot, or any directory
+name includes wildcard characters, the function returns EFalse.
+
+If a filename is included in the path, it is ignored (the existence
+of the file will not be checked). However if included, it must not
+be badly formed - this will cause the function to return EFalse.
+If no filename is specified, the path should end in a backslash.
+
+Examples of valid paths (returning ETrue):
+C:\; \; C:\Readme.txt; C:\system\data\; \system\data\Anyfile.dat
+
+Examples of invalid paths (returning EFalse):
+C:\FolderDoesntExist\; ..\system\; C:\Wild*card\; C:\system\data\Bad>File.txt
+
+@param aFs A connected session with the file server.
+@param aFolderName A path specifying the folder to test for.
+@return ETrue if the folder specified in aFolderName exists, EFalse if not.
+EFalse is also returned if the specified path is badly formed. */
+ {
+ if (aFolderName.Length()==0)
+ {return EFalse;}
+
+ TParse parse;
+
+ TInt retcode = parse.SetNoWild(aFolderName, NULL, NULL);
+
+ if (retcode != KErrNone)
+ {return EFalse;}
+
+ if (parse.NameOrExtPresent())
+ if (!aFs.IsValidName(aFolderName))
+ {return EFalse;}
+
+ TPtrC dirName = parse.DriveAndPath();
+ RDir dir;
+ retcode = dir.Open(aFs,dirName,0);
+ if (retcode == KErrNone)
+ {dir.Close();}
+ return (retcode == KErrNone);
+ }
+
+
+EXPORT_C TFileName BaflUtils::FolderNameFromFullName(const TDesC& aFullName)
+/** Gets the folder name from a path.
+
+A valid full name should have a drive associated with it
+e.g ("a:\\" - "z:\\")("a:" - "z:")("c:\\system\data\file.txt")
+Invalid entry will have no drive and cause a panic EBafPanicBadOpenArg
+For example, if the path is "c:\documents\word\mydoc1", then "word" is returned.
+ "c:" then "c:" is returned
+ "c:\\" then "c:\" is returned
+ "c:\\mydoc1.txt then "c:\" is returned
+
+@param aFullName A path.
+@return The folder name. */
+ {
+ TParsePtrC parse(aFullName);
+
+ __ASSERT_ALWAYS(parse.DrivePresent(),Panic(EBafPanicBadOpenArg));
+
+ TFileName folderName = parse.Path();
+ //If the path name has no associated path(e.g "c:") or path='\'(e.g "c:\\", "c:\\file.txt")
+ //then the folder name is just equal to drivename
+
+ TBuf<1> pathSeparator;
+ pathSeparator.Append(KPathDelimiter);
+
+ if (folderName.Length()==0 || folderName==pathSeparator)
+ return (parse.DriveAndPath());
+ //else just get the foldername
+ TInt len = folderName.Length();
+ TInt pos = --len;
+ while (--pos)
+ if (folderName.Mid(pos, 1)==pathSeparator)
+ break;
+ folderName.Delete(len, 1);
+ folderName.Delete(0, pos+1);
+ return(folderName);
+ }
+
+
+EXPORT_C TFileName BaflUtils::DriveAndPathFromFullName(const TDesC& aFullName)
+/** Gets the drive letter and path from a file name.
+
+This is in the form: drive-letter:\\path\\. The drive letter is folded using
+class TCharF.
+
+@param aFullName File name
+@return The drive and path */
+ {
+ TParsePtrC parse(aFullName);
+ return (parse.DriveAndPath());
+ }
+
+
+EXPORT_C TFileName BaflUtils::RootFolderPath(const TBuf<1> aDriveLetter)
+/** Gets the root folder for the specified drive.
+
+If aDriveLetter is an alphabet(lowercase or uppercase) then it will return
+the TFileName which is simply the drive letter plus ":\"
+If this is not the case, the function will panic with panic code EBafPanicBadOpenArg
+
+@param aDriveLetter Drive letter
+@return Root folder */
+ {
+ TChar driveLetter(aDriveLetter[0]);
+ driveLetter.LowerCase();
+ TInt aDriveNumber=driveLetter-TChar('a');
+ __ASSERT_ALWAYS(aDriveNumber>= EDriveA && aDriveNumber <= EDriveZ,Panic(EBafPanicBadOpenArg));
+
+ TFileName rootFolderPath = aDriveLetter;
+ rootFolderPath.Append(_L(":\\"));
+ return rootFolderPath;
+ }
+
+
+EXPORT_C void BaflUtils::AbbreviateFileName(const TFileName& aOriginalFileName, TDes& aAbbreviatedFileName)
+/** Abbreviates a file name.
+
+If aOriginalFileName is less than the maximum length of aAbbreviatedFileName,
+then the name is simply copied to aAbbreviatedFileName.
+
+If this is not so, then the left-most characters of aOriginalFileName are
+copied to aAbbreviatedFileName, up to aAbbreviatedFileName's maximum length-1.
+aAbbreviatedFileName's first character is set to be an ellipsis.
+
+@param aOriginalFileName Original file name
+@param aAbbreviatedFileName On return, abbreviated file name */
+ {
+ TInt maxWidthInChars = aAbbreviatedFileName.MaxLength();
+ if (aOriginalFileName.Length() <= maxWidthInChars)
+ {
+ aAbbreviatedFileName = aOriginalFileName;
+ return;
+ }
+ TChar ellipsis(0x2026);
+ --maxWidthInChars; // since the ellipsis will be the first char in aAbbreviatedFileName
+ aAbbreviatedFileName.Zero();
+ aAbbreviatedFileName.Append(ellipsis);
+ aAbbreviatedFileName.Append(aOriginalFileName.Mid((aOriginalFileName.Length() - 1) - maxWidthInChars + 1, maxWidthInChars));
+ }
+
+
+EXPORT_C TBool BaflUtils::UidTypeMatches(const TUidType& aFileUid, const TUidType& aMatchUid)
+/** Tests whether two UID types match.
+
+A match is made if each UID in aMatchUid is either identical to the corresponding
+one in aFileUid, or is KNullUid.
+
+@param aFileUid The UID type to match
+@param aMatchUid The UID type to match against
+@return ETrue if the UIDs match, otherwise EFalse */
+ {
+ for (TInt i=0; i<KMaxCheckedUid; i++)
+ {
+ if (aMatchUid[i] == KNullUid)
+ continue;
+ if (aMatchUid[i] != aFileUid[i])
+ return(EFalse);
+ }
+ return(ETrue);
+ }
+
+
+EXPORT_C TInt BaflUtils::Parse(const TDesC& aName)
+/** Checks if a specified file name can be parsed.
+
+@param aName Name to parse
+@return KErrNone if successful, otherwise another of the system-wide error
+codes */
+ { // keeps a TParse on the stack for the minimum time possible
+ TParse parse;
+ return parse.Set(aName,NULL,NULL);
+ }
+
+
+EXPORT_C TInt BaflUtils::ValidateFolderNameTypedByUserL(const RFs& aFs, const TDesC& aFolderNameTypedByUser, const TDesC& aCurrentPath, TFileName& aNewFolderFullName)
+/** Checks if a folder name (without drive or path) is valid and returns the full
+name of the folder.
+
+@param aFs File server session
+@param aFolderNameTypedByUser Folder name to check
+@param aCurrentPath Path to which to add the folder
+@param aNewFolderFullName aFolderNameTypedByUser appended to aCurrentPath
+@return KErrNone if successful, otherwise another of the system-wide error
+codes */
+ {
+ if (aFolderNameTypedByUser.Length() == 0)
+ return KErrArgument; // R_EIK_TBUF_NO_FOLDERNAME_SPECIFIED;
+
+ TParse* targetParse = new(ELeave) TParse;
+ CleanupStack::PushL(targetParse);
+
+ TInt retcode = targetParse->Set(aFolderNameTypedByUser, NULL, NULL);
+ User::LeaveIfError(retcode);
+ if (targetParse->DrivePresent() || targetParse->PathPresent())
+ {
+ CleanupStack::PopAndDestroy();
+ return KErrBadName; // R_EIK_TBUF_INVALID_FOLDER_NAME;
+ }
+
+ if (!(aFs.IsValidName(aFolderNameTypedByUser)))
+ {
+ CleanupStack::PopAndDestroy();
+ return KErrBadName; // R_EIK_TBUF_INVALID_FOLDER_NAME;
+ }
+
+
+ if ((aCurrentPath.Length() + aFolderNameTypedByUser.Length() + 1) > KMaxFileName)
+ {
+ CleanupStack::PopAndDestroy();
+ return KErrTooBig; //R_EIK_TBUF_FOLDERNAME_TOO_LONG;
+ }
+
+
+ //TFileName newFolderFullName = aCurrentPath;
+ aNewFolderFullName = aCurrentPath;
+ if ((aNewFolderFullName.Length() + aFolderNameTypedByUser.Length() + 1) <= KMaxFileName)
+ {
+ aNewFolderFullName.Append(aFolderNameTypedByUser);
+ aNewFolderFullName.Append(KPathDelimiter);
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy();
+ return KErrOverflow;
+ }
+
+ retcode = targetParse->Set(aNewFolderFullName, NULL, NULL);
+ if (retcode != KErrNone)
+ {
+ CleanupStack::PopAndDestroy();
+ return KErrBadName; // R_EIK_TBUF_INVALID_FOLDER_NAME;
+ }
+
+ CleanupStack::PopAndDestroy();
+
+ return(KErrNone);
+ }
+
+void BaflUtils::DoCopyFileL(RFs& aFs, const TDesC& aSourceFullName, const TDesC& aTargetFullName, TUint aSwitch)
+ {
+ CFileMan* fileMan=CFileMan::NewL(aFs);
+ CleanupStack::PushL(fileMan);
+ User::LeaveIfError(fileMan->Copy(aSourceFullName,aTargetFullName,aSwitch));
+ CleanupStack::PopAndDestroy(); // fileMan
+ }
+
+
+EXPORT_C TInt BaflUtils::CopyFile(RFs& aFs, const TDesC& aSourceFullName, const TDesC& aTargetFullName, TUint aSwitch)
+/** Copies one or more files.
+
+For more details,
+@see CFileMan::Copy()
+@since 5.1
+@param aFs File server session
+@param aSourceFullName Path indicating the file(s) to be copied. Any path
+components that are not specified here will be taken from the session path.
+@param aTargetFullName Path indicating the directory into which the file(s)
+are to be copied
+@param aSwitch=CFileMan::EOverWrite Set this to zero for no overwriting and
+no recursion; CFileMan::EOverWrite to overwrite files with the same name; or
+CFileMan::ERecurse for recursion.
+@return KErrNone if successful, otherwise another of the system-wide error
+codes.*/
+ {
+ TRAPD(err,DoCopyFileL(aFs,aSourceFullName,aTargetFullName,aSwitch));
+ return err;
+ }
+
+void BaflUtils::DoDeleteFileL(RFs& aFs, const TDesC& aSourceFullName, TUint aSwitch)
+ {
+ CFileMan* fileMan=CFileMan::NewL(aFs);
+ CleanupStack::PushL(fileMan);
+ User::LeaveIfError(fileMan->Delete(aSourceFullName,aSwitch));
+ CleanupStack::PopAndDestroy(); // fileMan
+ }
+
+
+EXPORT_C TInt BaflUtils::DeleteFile(RFs& aFs, const TDesC& aSourceFullName, TUint aSwitch)
+/** Deletes one or more files.
+
+For more details,
+@see CFileMan::Delete().
+@since 5.1
+@param aFs File server session
+@param aSourceFullName Path indicating the file(s) to be deleted. May either
+be a full path, or relative to the session path. Use wildcards to specify
+more than one file.
+@param aSwitch=0 Specify CFileMan::ERecurse for recursion,
+zero for no recursion.
+@return KErrNone if successful, otherwise another of the system-wide error
+codes. */
+ {
+ TRAPD(err,DoDeleteFileL(aFs,aSourceFullName,aSwitch));
+ return err;
+ }
+
+void BaflUtils::DoRenameFileL(RFs& aFs, const TDesC& aOldFullName, const TDesC& aNewFullName, TUint aSwitch)
+ {
+ CFileMan* fileMan=CFileMan::NewL(aFs);
+ CleanupStack::PushL(fileMan);
+ User::LeaveIfError(fileMan->Rename(aOldFullName,aNewFullName,aSwitch));
+ CleanupStack::PopAndDestroy(); // fileMan
+ }
+
+
+EXPORT_C TInt BaflUtils::RenameFile(RFs& aFs, const TDesC& aOldFullName, const TDesC& aNewFullName, TUint aSwitch)
+/** Renames or moves one or more files or directories.
+
+It can be used to move one or more files by specifying different
+destination and source directories.
+For more details,
+@see CFileMan::Rename().
+@since 5.1
+@param aFs File server session
+@param aOldFullName Path specifying the file(s) to be renamed.
+@param aNewFullName Path specifying the new name for the files and/or the
+new directory. Any directories specified in this path that do not exist will
+be created.
+@param aSwitch=CFileMan::EOverWrite Specify zero for no overwriting, or
+CFileMan::EOverWrite to overwrite files with the same name. This
+function cannot operate recursively.
+@return KErrNone if successful, otherwise another of the system-wide error
+codes. */
+ {
+ TRAPD(err,DoRenameFileL(aFs,aOldFullName,aNewFullName,aSwitch));
+ return err;
+ }
+
+
+EXPORT_C TInt BaflUtils::CheckWhetherFullNameRefersToFolder(const TDesC& aFullName, TBool& aIsFolder)
+/** Checks if a string is a valid folder name.
+
+@param aFullName String to check
+@param aIsFolder ETrue if aFullName is a valid folder name, otherwise EFalse
+@return KErrNone if successful, otherwise another of the system-wide error
+codes (probably because aFullName cannot be parsed). */
+ {
+ aIsFolder = EFalse;
+ TInt retcode = BaflUtils::Parse(aFullName);
+ if (retcode != KErrNone)
+ return(retcode);
+ TParsePtrC parse(aFullName);
+ if (! parse.NameOrExtPresent())
+ aIsFolder = ETrue;
+ return(KErrNone);
+ }
+
+EXPORT_C TInt BaflUtils::MostSignificantPartOfFullName(const TDesC& aFullName, TFileName& aMostSignificantPart)
+/** Gets the folder name if the specified item is a valid folder name, otherwise
+gets the file name.
+
+@param aFullName Item to parse
+@param aMostSignificantPart Folder or file name
+@return KErrNone if successful, otherwise another of the system-wide error
+codes */
+ {
+ TBool entryIsAFolder;
+ TInt retcode = CheckWhetherFullNameRefersToFolder(aFullName, entryIsAFolder);
+ if (retcode != KErrNone)
+ return(retcode);
+ if (entryIsAFolder)
+ {
+ aMostSignificantPart = FolderNameFromFullName(aFullName);
+ return (KErrNone);
+ }
+ // assume aFullName refers to a file
+ TParsePtrC parse(aFullName);
+ aMostSignificantPart = parse.NameAndExt();
+ return(KErrNone);
+ }
+
+EXPORT_C TInt BaflUtils::CheckFolder(RFs& aFs, const TDesC& aFolderName)
+/** Checks that the specified folder can be opened.
+
+@param aFs File server session
+@param aFolderName Folder to check
+@return KErrNone if successful, otherwise another of the system-wide error
+codes */
+ {
+ RDir dir;
+ TInt retcode = dir.Open(aFs, aFolderName, 0);
+ if (retcode == KErrNone)
+ dir.Close();
+ return (retcode);
+ }
+
+/**
+Checks if the specified drive is read-only.
+Checks that the KMediaAttWriteProtected and EMediaRom flags are both set.
+
+@param aFs File server session
+@param aFullName File name, including drive
+@param aIsReadOnly On return, ETrue if the drive is read-only, otherwise EFalse
+@return KErrNone if successful, otherwise another of the system-wide error codes
+@see BaflUtils::DriveIsReadOnlyInternal
+*/
+EXPORT_C TInt BaflUtils::DiskIsReadOnly(RFs& aFs, const TDesC& aFullName, TBool& aIsReadOnly)
+ {
+ TInt retcode=BaflUtils::Parse(aFullName);
+ if (retcode!=KErrNone)
+ return retcode;
+ TParsePtrC parse(aFullName);
+ if (!parse.DrivePresent())
+ return KErrBadName;
+ TBuf<1> drive=parse.Drive().Left(1);
+ TChar driveLetter=drive[0];
+ TInt driveId=0;
+ retcode=RFs::CharToDrive(driveLetter,driveId);
+ if (retcode!=KErrNone)
+ return retcode;
+ TVolumeInfo volInfo;
+ retcode=aFs.Volume(volInfo,driveId);
+ if (retcode!=KErrNone)
+ return retcode;
+ aIsReadOnly=(volInfo.iDrive.iMediaAtt&KMediaAttWriteProtected || volInfo.iDrive.iType==EMediaRom);
+ return KErrNone;
+ }
+
+/**
+Checks if the specified drive is read-only and is an internal drive i.e. non-removable.
+Checks that the KMediaAttWriteProtected and KDriveAttInternal flags are both set.
+
+@param aFs File server session
+@param aFullName File name, including drive
+@param aIsReadOnlyInternal On return, ETrue if the drive is read-only and internal, otherwise EFalse
+@return KErrNone if successful, otherwise another of the system-wide errors codes
+*/
+EXPORT_C TInt BaflUtils::DriveIsReadOnlyInternal(RFs& aFs, const TDesC& aFullName, TBool& aIsReadOnlyInternal)
+ {
+ TInt retcode=BaflUtils::Parse(aFullName);
+ if (retcode!=KErrNone)
+ return retcode;
+ TParsePtrC parse(aFullName);
+ if (!parse.DrivePresent())
+ return KErrBadName;
+ TBuf<1> drive=parse.Drive().Left(1);
+ TChar driveLetter=drive[0];
+ TInt driveId=0;
+ retcode=RFs::CharToDrive(driveLetter,driveId);
+ if (retcode!=KErrNone)
+ return retcode;
+ TVolumeInfo volInfo;
+ retcode=aFs.Volume(volInfo,driveId);
+ if (retcode!=KErrNone)
+ return retcode;
+ aIsReadOnlyInternal=((volInfo.iDrive.iMediaAtt&KMediaAttWriteProtected)&&(volInfo.iDrive.iDriveAtt&KDriveAttInternal));
+ return KErrNone;
+ }
+
+EXPORT_C void BaflUtils::GetDiskListL(const RFs& aFs,CDesCArray& aArray)
+/** Retrieves a list of all drives on the system.
+
+The file server is interrogated for a list of the drive letters for all available
+drives.
+
+On emulator:
+The removable media is represented by drive X: .
+
+On hardware:
+The removable media is represented by drives D: E: F: and G: .
+
+@param aFs A connected session with the file server.
+@param aArray On return, contains the drive letters that correspond to the
+available drives. The drive letters are uppercase and are in alphabetical
+order. */
+ { // static
+ aArray.Reset();
+ TDriveList driveList;
+ User::LeaveIfError(aFs.DriveList(driveList));
+ for (TInt ii=0;ii<KMaxDrives;ii++)
+ {
+ if (driveList[ii])
+ {
+ TChar drive;
+ User::LeaveIfError(aFs.DriveToChar(ii,drive));
+ drive.UpperCase();
+ TBuf<1> buf;
+ buf.Append(drive);
+ aArray.AppendL(buf);
+ }
+ }
+ }
+
+EXPORT_C void BaflUtils::UpdateDiskListL(const RFs& aFs,CDesCArray& aArray,TBool aIncludeRom,TDriveNumber aDriveNumber)
+/** Retrieves a list of all drives present on the system.
+
+The file server is interrogated for a list of the drive letters for all available
+drives. The drive letter that corresponds to aDriveNumber is added to the
+list regardless of whether it is present, or is corrupt. Also, the C: drive
+is forced onto the list, even if corrupt or not present.
+
+On emulator:
+The removable media is represented by drive X: and is forced onto the list
+unless removed (F5,F4).
+
+On hardware:
+The removable media is represented by drives D: E: F: and G: and is forced
+onto the list regardless of whether it is present, or is corrupt.
+
+@param aFs A connected session with the file server.
+@param aArray On return, contains the drive letters that correspond to the
+available drives. The drive letters are uppercase and are in alphabetical
+order.
+@param aIncludeRom Specify ETrue if the ROM drive should be included in the
+list, EFalse if not.
+@param aDriveNumber The drive to force into the list, e.g. the drive in the
+default path. */
+ { // static
+ aArray.Reset();
+ TDriveList driveList;
+ User::LeaveIfError(aFs.DriveList(driveList));
+ for (TInt ii=0;ii<KMaxDrives;ii++)
+ {
+ if (driveList[ii] || ii==aDriveNumber)
+ {
+ TVolumeInfo vInfo;
+ const TInt err=aFs.Volume(vInfo,TDriveUnit(ii));
+ if (err==KErrNone || err==KErrCorrupt || ii==aDriveNumber || BaflUtils::IsFirstDriveForSocket(TDriveUnit(ii)))
+ {
+ if (ii==EDriveZ && vInfo.iDrive.iDriveAtt&KDriveAttRom && !aIncludeRom)
+ continue;
+ TChar drive;
+ User::LeaveIfError(aFs.DriveToChar(ii,drive));
+ drive.UpperCase();
+ TBuf<1> buf;
+ buf.Append(drive);
+ aArray.AppendL(buf);
+ }
+ }
+ }
+ }
+
+EXPORT_C TBool BaflUtils::IsFirstDriveForSocket(TDriveUnit aDriveUnit)
+/** Tests whether the specified drive corresponds to the primary partition in a
+removable media slot.
+
+The function assumes that the D: drive corresponds to the primary partition
+on socket 0, and that the E: drive corresponds to the primary partition on
+socket 1 (a socket is a slot for removable media). This mapping may not always
+be the case because it is set up in the variant layer of the Symbian OS.
+
+This function assumes that the drive mappings are contiguous, starting
+from drive D: .
+
+On emulator:
+The removable media is represented by drive X: only.
+
+@param aDriveUnit The drive to check.
+@return ETrue if the drive is the primary partition in a removable media slot.
+ETrue is also returned if the drive is A, B or C:. EFalse is returned otherwise. */
+ { // static
+ TDriveInfoV1Buf buf;
+ UserHal::DriveInfo(buf);
+
+#ifdef __EPOC32__
+ return ((aDriveUnit-EDriveC)<=buf().iTotalSockets);
+#else // emulator
+ return (aDriveUnit==EDriveX || (aDriveUnit-EDriveC)<=buf().iTotalSockets);
+#endif
+ }
+
+EXPORT_C void BaflUtils::RemoveSystemDirectory(CDir& aDir)
+/** Removes "System" from a list of directory entries.
+
+@param aDir Array of directory entries. */
+ { // static
+ STATIC_CAST(BaflDir&,aDir).RemoveSystem();
+ }
+
+EXPORT_C TInt BaflUtils::SortByTable(CDir& aDir,CBaflFileSortTable* aTable)
+/** Sorts files by UID.
+
+The caller supplies a table which specifies the order in which files are to
+be sorted. The files whose UID3 is the first UID in the table appear first.
+The files whose UID3 is the UID specified second appear next, and so on. Files
+whose UID3 is not specified in the table, and directories, appear at the end
+of the list, with directories preceding the files, and with files sorted in
+ascending order of UID3.
+
+This function is used for customising how lists of application files are sorted.
+
+@param aDir The array of files and directories to sort.
+@param aTable A sort order table containing the UIDs to use in the sort.
+@return KErrNone if successful, otherwise one of the standard error codes. */
+ { // static
+ return STATIC_CAST(BaflDir&,aDir).SortByTable(aTable);
+ }
+
+EXPORT_C void BaflUtils::GetDowngradePathL(const RFs& aFs, const TLanguage aCurrentLanguage, RArray<TLanguage>& aLanguageArray)
+/** Gets the full language downgrade path for a particular locale.
+
+@param aFs A connected session with the file server.
+@param aCurrentLanguage The language of the locale for which the language downgrade
+path is required. This language will always be returned as the first language
+in aLanguageArray. To get the downgrade path for the language of the current
+locale, specify the language returned by User::Language().
+@param aLanguageArray On return, contains the language downgrade path.
+@see BaflUtils::NearestLanguageFile() */
+ {
+ TLocale currentLocale;
+ TNearestLanguageFileFinder languageDowngradePath(aFs);
+ TLanguage idealLanguage=IdealLanguage();
+ MakeLanguageDowngradePath(languageDowngradePath.iPath,aCurrentLanguage,idealLanguage, currentLocale);
+ aLanguageArray.Reset();
+ const TLanguage* p=languageDowngradePath.iPath;
+ while (*p != ELangNone)
+ {
+ User::LeaveIfError(aLanguageArray.Append(*p));
+ ++p;
+ }
+ }
+
+EXPORT_C void BaflUtils::PersistLocale()
+/** Saves the locale settings in TLocale and the currency symbol to file.
+@deprecated 9.1
+Persistence and initialisation of system locale data will be performed
+transparently by a separate executable (InilialiseLocale.exe) wich should
+be loaded as part of the system start procedure.
+*/
+ {
+// Replaced by new repository based locale initialisation mechanism.
+ }
+
+
+
+EXPORT_C TInt BaflUtils::PersistHAL()
+/** Saves the HAL settings to file.
+This will start a new executable and saves HAL attributes to a file,
+little delay because of the creation of new process
+@return KErrNone if suceessful, otheriwse system wide error code.
+*/
+ {
+ RProcess process;
+ _LIT(KHALSettings, "HALSettings.exe");
+ _LIT(KCommandLine, "PERSIST");
+ TInt result = process.Create(KHALSettings, KCommandLine);
+ if(result != KErrNone )
+ return result;
+ TRequestStatus status;
+ process.Logon(status);
+ if ( status != KRequestPending)
+ {
+ process.Kill(0); // abort
+ }
+ else
+ {
+ process.Resume(); // logon OK
+ }
+ User::WaitForRequest(status);
+
+ // we can't use the 'exit reason' if the exe panicked as this
+ // is the panic 'reason' and may be '0' which cannot be distinguished
+ // from KErrNone
+ result = process.ExitType() == EExitPanic ? KErrGeneral : status.Int();
+ process.Close();
+ return result;
+ }
+
+EXPORT_C void BaflUtils::PersistScreenCalibration(const TDigitizerCalibration& aScreenCalibration)
+ {
+
+ RFs fs;
+ TInt err = fs.Connect();
+ if (err == KErrNone)
+ {
+ // Setting up drive to store Screen data
+ TDriveUnit systemDrive(static_cast<TInt>(RFs::GetSystemDrive()));
+ TBuf<KMaxDriveName+KScreenCalibrationPathLength> ScreenFileNameWithDriveAndPath(systemDrive.Name());
+ ScreenFileNameWithDriveAndPath.Append(KScreenCalibrationFolder);
+
+ // Ensure directory \System\Data exists in target drive
+ TRAP(err, EnsurePathExistsL(fs, ScreenFileNameWithDriveAndPath));
+ if(err == KErrNone)
+ {
+ ScreenFileNameWithDriveAndPath.Append(KScreenCalibrationFileName);
+
+ RFile file;
+ err = file.Replace(fs,ScreenFileNameWithDriveAndPath,EFileWrite|EFileShareExclusive);
+ if (err == KErrNone)
+ {
+ // Write aScreenCalibration to file.
+ TPtrC8 calptr((const TUint8*)&aScreenCalibration, sizeof(TDigitizerCalibration));
+ err = file.Write(calptr);
+ }
+ file.Close();
+ }
+ }
+ fs.Close();
+ }
+
+EXPORT_C void BaflUtils::InitialiseScreenCalibration(RFs& aFs)
+ {
+ TFindFile ff(aFs);
+ if (ff.FindByDir(KScreenCalibrationFileName, KScreenCalibrationFolder)==KErrNone)
+ {
+ RFile file;
+ if (file.Open(aFs,ff.File(),EFileRead) == KErrNone )
+ {
+ TDigitizerCalibration calibrationSetting;
+ TPtr8 scrcal((TUint8*)&calibrationSetting, sizeof(TDigitizerCalibration));
+ if( file.Read(scrcal, sizeof( TDigitizerCalibration )) == KErrNone )
+ UserHal::SetXYInputCalibration(calibrationSetting);
+
+ }
+ file.Close();
+ }
+ }
+
+EXPORT_C void BaflUtils::InitialiseHAL(RFs&)
+/** Initialise the HAL settings from.
+@deprecated 9.1
+This function is empty
+*/
+ {
+ }
+
+EXPORT_C void BaflUtils::InitialiseLocale(RFs& /* aFs */)
+ {
+// Replaced by new repository based locale initialisation mechanism.
+ }
+
+
+//
+// class CEikFileSortTable
+//
+
+/**
+*/
+EXPORT_C CBaflFileSortTable::CBaflFileSortTable()
+ : CArrayFixFlat<TUid>(EArrayGranularity)
+ {}
+
+/**
+ * Loads the CBaflFileSortTable using the UIDs read from the TResourceReader supplied in aReader.
+ * @param aReader TResourceReader from which UIDS are read.
+ * @leave KErrNoMemory if there is insufficient memory available or one of the system wide error codes.
+ */
+EXPORT_C void CBaflFileSortTable::ConstructFromResourceL(TResourceReader& aReader)
+ {
+ const TInt count=aReader.ReadInt16();
+ for (TInt i=0;i<count;i++)
+ AppendL(TUid::Uid(aReader.ReadInt32()));
+ }
+
+//
+// class BaflDir
+//
+
+#define KSystemDirName _L("System") // Name for System directory
+
+
+void BaflDir::RemoveSystem()
+/* Remove "System" if in list and it's a directory. */
+{
+ TInt index;
+ TEntry entry;
+ entry.iName=KSystemDirName;
+ TKeyArrayPak key(_FOFF(TEntry,iName),ECmpFolded);
+ if (iArray->Find(entry,key,index)==KErrNone)
+ {
+ entry=(*iArray)[index];
+ if (entry.IsDir())
+ iArray->Delete(index);
+ }
+ };
+
+/*
+This function gets the element at position "aPos" of aEntries array and inserts
+it to poition "aNewPos". The element size is "aSize". After the operation the array size
+grows by 1, the element at "aPos" position moves one position forward.
+This function must be called only from BaflDir::SortByTable() and the insert position
+is always less or equal than the position of the element to be inserted.
+*/
+static void InsertL(CArrayPakFlat<TEntry>* aEntries, TInt aPos, TInt aNewPos, TInt aSize)
+ {
+ __ASSERT_DEBUG(aPos >= aNewPos, User::Invariant());
+ //Expand the array adding one empty entry at "aNewPos" position.
+ aEntries->ExpandL(aNewPos, aSize);
+ //After successfull "ExpandL" call "aPos" must be incremented by 1.
+ //Copy the entry from "aPos + 1" position to "aNewPos" position
+ (*aEntries)[aNewPos] = (*aEntries)[++aPos];
+ }
+
+/**
+Copied from f32file.inl (now moved to f32file_private.h)
+Returns the minimum uncompressed size of the TEntry object, including the valid
+portion of the name string. The returned value is aligned to 4-byte boundary and
+length includes private members.
+
+@internalTechnology
+@return minimum uncompressed size of TEntry object
+*/
+
+TInt BaflDir::MinEntrySize(const TEntry & aEntry)
+ {
+ return(sizeof(TUint)+sizeof(TInt)+sizeof(TTime)+sizeof(TInt)+sizeof(TUidType)+
+ Align4(aEntry.iName.Size()) + 2*sizeof(TInt));
+ }
+
+TInt BaflDir::SortByTable(CBaflFileSortTable* aTable)
+/**
+Sort into order from given table.
+Any file with uid[2] matching an entry in the table will be sorted relative to
+others in the table and before any files with no matching uid.
+For Example: Assume UID table is filled with below 2 UID's
+table[0] =0x10003a64 and table[1] =0x10003a5c. Then file with UID[2]=0x10003a64
+will be sorted first in the list followed by file with UID[2]=0x10003a5c. Rest
+files will be sorted in the ascending order of UID[2] with directories preceding
+the files.
+
+@param aTable A sort order table containing the UIDs to use in the sort.
+@return KErrNone if suceessful, otheriwse another system-wide error code.
+*/
+ {
+ TInt r=this->Sort(EDirsFirst|ESortByUid);
+ if(r != KErrNone)
+ {
+ return r;
+ }
+ const TInt tableCount=aTable->Count();
+ const TInt count=iArray->Count();
+ TInt sortedInsertionPoint = 0;
+ for (TInt i=0;i<tableCount;i++)
+ {
+ TUid tableUid;
+ // get each UID in the table
+ tableUid = aTable->At(i);
+ for (TInt j=sortedInsertionPoint;j<count;j++)
+ {
+ //parse files in the array list
+ TEntry* pEntry=&(*iArray)[j];
+ // check table UID for match with UID[2] of the file in the list
+ // if found, move the file at the top in the list, followed by next matching UID
+ if (tableUid == pEntry->iType[2])
+ {
+ TRAPD(insertErr, ::InsertL(iArray, j, sortedInsertionPoint++, MinEntrySize(*pEntry)));
+ if(insertErr!=KErrNone)
+ {
+ return insertErr;
+ }
+ iArray->Delete(j+1);
+ }
+ }
+ }
+ iArray->Compress();
+ return KErrNone;
+ }