diff -r 000000000000 -r e4d67989cc36 lowlevellibsandfws/apputils/src/BAUTILS.CPP --- /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 +#include +#include +#include +#include +#include +#include + +/** +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 +#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(aLanguage))<=KDialectMask)) + return EFalse; + else + return ETrue; + } + + +LOCAL_C TLanguage BaseLanguage(const TLanguage aLanguage) + { + if (IsLanguageExtended(aLanguage)) + return static_cast(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(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(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(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('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(bestLanguageMatch); + AppendLanguageCode(static_cast(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(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; iSet(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 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 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& 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(RFs::GetSystemDrive())); + TBuf 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(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;iFind(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* 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;iAt(i); + for (TInt j=sortedInsertionPoint;jiType[2]) + { + TRAPD(insertErr, ::InsertL(iArray, j, sortedInsertionPoint++, MinEntrySize(*pEntry))); + if(insertErr!=KErrNone) + { + return insertErr; + } + iArray->Delete(j+1); + } + } + } + iArray->Compress(); + return KErrNone; + }