|
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Started by DWW, November 1995 |
|
15 // BAFL utilities static class |
|
16 // |
|
17 // |
|
18 |
|
19 #include "BaUtilsImp.h" |
|
20 #include <e32hal.h> |
|
21 #include <bautils.h> |
|
22 #include <baflpan.h> |
|
23 #include <baliba.h> |
|
24 #include <hal.h> |
|
25 #include <hal_data.h> |
|
26 #include <utf.h> |
|
27 |
|
28 /** |
|
29 Mimimum length of a filename and mimimum length of a suffix. |
|
30 Note these two values are tied together. |
|
31 */ |
|
32 const TInt KInvNameAndMinSuffixLength = 2; |
|
33 |
|
34 #define ISDIGIT(c) (c-'0' >= 0 && c-'0' <= 9) |
|
35 |
|
36 _LIT(KAllDrives, "YXWVUTSRQPONMLKJIHGFEDCBAZ"); |
|
37 const TInt KDriveAndPathLength = 3; |
|
38 |
|
39 // screen calibration stuff |
|
40 _LIT(KScreenCalibrationFolder,"\\System\\Data\\"); |
|
41 _LIT(KScreenCalibrationFileName, "Screen.DAT"); |
|
42 const TInt KScreenCalibrationPathLength = 23; // folder + filename |
|
43 |
|
44 |
|
45 // #define DO_PROFILING |
|
46 |
|
47 #if defined(DO_PROFILING) |
|
48 #pragma message ("------------ N.B. profiling of \"BaflUtils::NearestLanguageFile\" is enabled") |
|
49 #include <e32svr.h> |
|
50 #define FIRST_PROFILE_INDEX 50 |
|
51 #define PROFILE_INDEX_1 (FIRST_PROFILE_INDEX+0) |
|
52 #define PROFILE_COUNT 1 |
|
53 #endif |
|
54 |
|
55 // BaflUtils |
|
56 |
|
57 class BaflDir : public CDir |
|
58 { |
|
59 public: |
|
60 void RemoveSystem(); |
|
61 TInt SortByTable(CBaflFileSortTable* aTable); |
|
62 private: |
|
63 TInt MinEntrySize(const TEntry & aEntry); |
|
64 }; |
|
65 |
|
66 |
|
67 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 }; |
|
68 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 }; |
|
69 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 }; |
|
70 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 }; |
|
71 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 }; |
|
72 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 }; |
|
73 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 }; |
|
74 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 }; |
|
75 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 }; |
|
76 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 }; |
|
77 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 }; |
|
78 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 }; |
|
79 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 }; |
|
80 LOCAL_C const TLanguage dp13[] = { ELangInternationalFrench,ELangFrench,ELangSwissFrench,ELangBelgianFrench,ELangCanadianFrench,ELangNone }; |
|
81 LOCAL_C const TLanguage dp14[] = { ELangBelgianFrench, ELangFrench,ELangInternationalFrench,ELangSwissFrench,ELangCanadianFrench,ELangNone }; |
|
82 LOCAL_C const TLanguage dp15[] = { ELangCanadianFrench, ELangFrench,ELangInternationalFrench,ELangSwissFrench,ELangBelgianFrench,ELangNone }; |
|
83 LOCAL_C const TLanguage dp16[] = { ELangFrench,ELangInternationalFrench,ELangSwissFrench,ELangBelgianFrench,ELangCanadianFrench,ELangNone }; |
|
84 LOCAL_C const TLanguage dp17[] = { ELangSwissFrench,ELangFrench,ELangInternationalFrench,ELangBelgianFrench,ELangCanadianFrench,ELangNone }; |
|
85 LOCAL_C const TLanguage dp18[] = { ELangSwissGerman,ELangGerman,ELangAustrian,ELangNone }; |
|
86 LOCAL_C const TLanguage dp19[] = { ELangAustrian,ELangGerman,ELangSwissGerman,ELangNone }; |
|
87 LOCAL_C const TLanguage dp20[] = { ELangGerman,ELangSwissGerman,ELangAustrian,ELangNone }; |
|
88 LOCAL_C const TLanguage dp21[] = { ELangSerbian,ELangCroatian,ELangNone }; |
|
89 LOCAL_C const TLanguage dp22[] = { ELangCroatian,ELangSerbian,ELangNone }; |
|
90 LOCAL_C const TLanguage dp23[] = { ELangRomanian,ELangMoldavian,ELangNone }; |
|
91 LOCAL_C const TLanguage dp24[] = { ELangMoldavian,ELangRomanian,ELangNone }; |
|
92 LOCAL_C const TLanguage dp25[] = { ELangBelgianFlemish,ELangDutch,ELangNone }; |
|
93 LOCAL_C const TLanguage dp26[] = { ELangDutch,ELangBelgianFlemish,ELangNone }; |
|
94 LOCAL_C const TLanguage dp27[] = { ELangAfrikaans,ELangDutch,ELangNone }; |
|
95 LOCAL_C const TLanguage dp28[] = { ELangMalay_Apac,ELangMalay,ELangNone }; |
|
96 LOCAL_C const TLanguage dp29[] = { ELangIndonesian_Apac,ELangIndonesian,ELangNone }; |
|
97 LOCAL_C const TLanguage dp30[] = { ELangSpanish,ELangInternationalSpanish,ELangLatinAmericanSpanish,ELangNone }; |
|
98 LOCAL_C const TLanguage dp31[] = { ELangLatinAmericanSpanish,ELangSpanish,ELangInternationalSpanish,ELangNone }; |
|
99 LOCAL_C const TLanguage dp32[] = { ELangInternationalSpanish,ELangSpanish,ELangLatinAmericanSpanish,ELangNone }; |
|
100 LOCAL_C const TLanguage dp33[] = { ELangCyprusGreek,ELangGreek,ELangNone }; |
|
101 LOCAL_C const TLanguage dp34[] = { ELangGreek,ELangCyprusGreek,ELangNone }; |
|
102 LOCAL_C const TLanguage dp35[] = { ELangSwissItalian,ELangItalian,ELangNone }; |
|
103 LOCAL_C const TLanguage dp36[] = { ELangItalian,ELangSwissItalian,ELangNone }; |
|
104 LOCAL_C const TLanguage dp37[] = { ELangBrazilianPortuguese,ELangPortuguese,ELangNone }; |
|
105 LOCAL_C const TLanguage dp38[] = { ELangPortuguese,ELangBrazilianPortuguese,ELangNone }; |
|
106 LOCAL_C const TLanguage dp39[] = { ELangFinlandSwedish,ELangSwedish,ELangNone }; |
|
107 LOCAL_C const TLanguage dp40[] = { ELangSwedish,ELangFinlandSwedish,ELangNone }; |
|
108 LOCAL_C const TLanguage dp41[] = { ELangCyprusTurkish,ELangTurkish,ELangNone }; |
|
109 LOCAL_C const TLanguage dp42[] = { ELangTurkish,ELangCyprusTurkish,ELangNone }; |
|
110 LOCAL_C const TLanguage dp43[] = { ELangHongKongChinese, ELangTaiwanChinese, ELangPrcChinese,ELangNone }; |
|
111 LOCAL_C const TLanguage dp44[] = { ELangTaiwanChinese, ELangHongKongChinese,ELangPrcChinese,ELangNone }; |
|
112 LOCAL_C const TLanguage dp45[] = { ELangPrcChinese, ELangHongKongChinese, ELangTaiwanChinese,ELangNone }; |
|
113 LOCAL_C const TLanguage * const KEquivalentLists[] = { dp0, dp1, dp2, dp3, dp4, dp5, dp6, |
|
114 dp7, dp8, dp9, dp10, dp11, dp12, dp13, dp14, dp15, dp16, dp17, |
|
115 dp18, dp19, dp20, dp21, dp22, dp23, dp24, dp25, dp26, dp27, |
|
116 dp28, dp29, dp30, dp31, dp32, dp33, dp34, dp35, dp36, dp37, |
|
117 dp38, dp39, dp40, dp41, dp42, dp43, dp44, dp45}; |
|
118 |
|
119 /** |
|
120 This function gets the list of languages that are 'equivalent' to the |
|
121 given language. We say language L1 is equivalent to language L2 if |
|
122 speakers of L2 can readily understand L1 without intentional study |
|
123 or extraordinary effort. |
|
124 |
|
125 The equivalence relationship is defined in a static table. Please refer |
|
126 to the definition of 'KEquivalentLists' for details. |
|
127 Each row in the table is formatted like this: |
|
128 @code |
|
129 L1, L2, L3, ..., Ln, ELangNone |
|
130 @codeend |
|
131 In which L2, ..., Ln are equivalents of L1, and ELangNone marks the end of an |
|
132 entry. The list is ordered. Compared with L3, L2 is nearer to L1. When choosing |
|
133 an equivalent of L1, L2 shall be preferred over L3, L3 shall be preferred |
|
134 over L4, and so on. |
|
135 L1 is always returned as the ‘nearest equivalent’ of L1 itself. |
|
136 |
|
137 BaflUtils::NearestLanguageFileV2 searches language specific resource files |
|
138 according to the 'equivalent' relationship returned by this function. |
|
139 |
|
140 @param aLang The language whose equivalents needs to be found out. |
|
141 @param aEquivalents On return, this array contains the ordered list of |
|
142 languages that are equivalent to the given language. If there is no |
|
143 entry for the given language in the table, this array will contain |
|
144 two elements on return: the first is the given language itself |
|
145 and the 2nd one is ELangNone. For any language that has equivalents |
|
146 defined, content of he corresponding entry is returned. |
|
147 |
|
148 @see BaflUtils::NearestLanguageFileV2 |
|
149 */ |
|
150 EXPORT_C void |
|
151 BaflUtils::GetEquivalentLanguageList(TLanguage aLang, TLanguagePath& aEquivalents) |
|
152 { |
|
153 aEquivalents[0] = aLang; |
|
154 aEquivalents[1] = ELangNone; |
|
155 const TInt len = sizeof(KEquivalentLists) / sizeof(KEquivalentLists[0]); |
|
156 for (TInt i = 0; i < len; ++i) |
|
157 { |
|
158 const TLanguage *ptr = KEquivalentLists[i]; |
|
159 if (ptr[0] == aLang) |
|
160 { |
|
161 TInt index = 1; |
|
162 while (ELangNone != *ptr) |
|
163 { |
|
164 aEquivalents[index++] = (TLanguage)*(++ptr); |
|
165 } |
|
166 aEquivalents[index] = ELangNone; |
|
167 break; |
|
168 } // end if ptr[0] |
|
169 } // end for i |
|
170 } |
|
171 |
|
172 /** |
|
173 NearestLanguageFileV2 is very similar to the existing 'NearestLanguageFile' |
|
174 function. The only difference between NearestLanguageFile and |
|
175 NearestLanguageFileV2 is the order in which language specific |
|
176 resource files are searched for. |
|
177 NearestLanguageFile searches language specific resource files in the |
|
178 order defined by the 'downgrade path' of the given language. Content of the |
|
179 downgrade path is dependent on the current active locale, and parts of |
|
180 it is runtime configurable. |
|
181 NearestLanguageFileV2 searches for language specific resource files |
|
182 in the order defined by the 'language equivalence table', which is a |
|
183 static data table fixed at build time. There is one entry in the table for |
|
184 each language that has one or more equivalents. |
|
185 |
|
186 @param aFs An active file server session. |
|
187 @param aName Name of the language-neutral resource file name which consist of |
|
188 an optional drive specification, followed by an optional path name, |
|
189 followed by basename for filename, followed by a period and extension. |
|
190 On return, in case of a match, this is replaced by the language-specific version |
|
191 which consists of the last two characters of the extension plus any preceding |
|
192 numeric characters being replaced by the language code. Remains unchanged when there's no match |
|
193 @param aLanguage On return, in case of a match, this is replaced by the corresponding language. |
|
194 In case of no match, it is set to ELangNone. |
|
195 |
|
196 @see TLanguage |
|
197 @see BaflUtils::GetEquivalentLanguageList |
|
198 */ |
|
199 EXPORT_C void |
|
200 BaflUtils::NearestLanguageFileV2(const RFs& aFs,TFileName& aName, TLanguage& aLanguage) |
|
201 { |
|
202 TNearestLanguageFileFinder finder(aFs); |
|
203 TBool goodSuffix=finder.SetFileName(aName); |
|
204 |
|
205 // Continue only if the suffix is good. |
|
206 if(goodSuffix) |
|
207 { |
|
208 // add preset customised resource drive to drive list |
|
209 // Note that errors returned from AddCustomResourceDrive are ignored. This is because if |
|
210 // a custom resource drive has not been found we still want to continue on with searching |
|
211 // other drives according to our algorithm |
|
212 finder.AddCustomResourceDrive(); |
|
213 |
|
214 GetEquivalentLanguageList(User::Language(), finder.iPath); |
|
215 if (!finder.FindLanguageAndDrive() |
|
216 && KErrNone != finder.FindFirstLanguageFileAndDrive()) |
|
217 finder.RepairFileName(); |
|
218 aLanguage = finder.Language(); |
|
219 } |
|
220 else |
|
221 { |
|
222 aLanguage = ELangNone; |
|
223 } |
|
224 } |
|
225 |
|
226 // TLibAssocBase |
|
227 |
|
228 EXPORT_C TLibAssocBase::TLibAssocBase(const RLibrary& aLib,TAny* aPtr) |
|
229 : iLibrary(aLib),iPtr(aPtr) |
|
230 /** |
|
231 Constructs the object taking the specified DLL and a class instance. |
|
232 |
|
233 @param aLib A reference to a DLL that has already been opened. |
|
234 @param aPtr An untyped pointer to an object to be associated with the DLL. |
|
235 Typically, this object will have been created using |
|
236 the ordinal 1 function from that DLL. */ |
|
237 {} |
|
238 |
|
239 |
|
240 |
|
241 |
|
242 EXPORT_C void TLibAssocBase::Set(const RLibrary& aLib,TAny* aPtr) |
|
243 /** |
|
244 Implements TLibAssoc::Set(). |
|
245 |
|
246 @param aLib A reference to a DLL that has already been opened. |
|
247 @param aClass A pointer to an object to be associated with the DLL. |
|
248 Typically, this object will have been created using |
|
249 the ordinal 1 function from that DLL. |
|
250 |
|
251 @see TLibAssoc::Set */ |
|
252 { |
|
253 __ASSERT_ALWAYS(iLibrary.Handle()==KNullHandle&&iPtr==NULL,Panic(EBafPanicLibAssocAlreadySet)); |
|
254 iLibrary=aLib; |
|
255 iPtr=aPtr; |
|
256 } |
|
257 |
|
258 |
|
259 |
|
260 |
|
261 EXPORT_C void TLibAssocBase::DoUnload(TAny* aThis) |
|
262 /** |
|
263 Calls Close() on the associated DLL. |
|
264 |
|
265 @param aThis An untyped pointer to a TLibAssoc type. |
|
266 */ |
|
267 { |
|
268 TLibAssocBase& l=*(TLibAssocBase*)aThis; |
|
269 l.iPtr=NULL; |
|
270 l.iLibrary.Close(); |
|
271 } |
|
272 |
|
273 // |
|
274 // class BaflUtils |
|
275 // |
|
276 EXPORT_C void BaflUtils::CopyWithTruncation(TDes& aDest,const TDesC& aSrc,TChar aTruncationSymbol) |
|
277 /** Copies a descriptor, abbreviating it to fit the destination descriptor. |
|
278 |
|
279 If aSrc is less than the maximum length of aDest, then the string is simply |
|
280 copied to aDest. |
|
281 |
|
282 If this is not so, then the left-most characters of aSrc are copied to aDest, |
|
283 up to aDest's maximum length-1. aDest's final character is set to be aTruncationSymbol. |
|
284 |
|
285 @param aDest On return, the truncated string |
|
286 @param aSrc The string to truncate |
|
287 @param aTruncationSymbol The truncation character to add */ |
|
288 { // static |
|
289 TInt maxLength=aDest.MaxLength(); |
|
290 if (aSrc.Length()<=maxLength) |
|
291 aDest.Copy(aSrc); |
|
292 else |
|
293 { |
|
294 aDest.Copy(aSrc.Left(maxLength-1)); |
|
295 aDest.Append(aTruncationSymbol); |
|
296 } |
|
297 } |
|
298 |
|
299 EXPORT_C TBool BaflUtils::FileExists(const RFs& aFileSession,const TDesC& aFileName) |
|
300 /** Checks if the specified file exists. |
|
301 |
|
302 @param aFs File server session |
|
303 @param aFileName File to check |
|
304 @return ETrue if the file exists, otherwise EFalse */ |
|
305 { // static |
|
306 TEntry entry; |
|
307 return(aFileSession.Entry(aFileName,entry)==KErrNone); |
|
308 } |
|
309 |
|
310 EXPORT_C TBool BaflUtils::PathExists(RFs& aFs,const TDesC& aPath) |
|
311 /** Tests whether a path exists. |
|
312 |
|
313 The path should contain a drive letter and a directory, or EFalse is returned. |
|
314 EFalse is also returned if it contains a filename or filename extension. |
|
315 |
|
316 If the path is badly formed, for instance if it contains illegal characters, |
|
317 or any directory name consists of a single or double dot, or any directory |
|
318 name includes wildcard characters, the function returns EFalse. |
|
319 |
|
320 @param aFs A connected session with the file server. |
|
321 @param aPath The path to test for. It should end in a backslash. |
|
322 @return ETrue if the path exists, EFalse if not. EFalse is also returned if the |
|
323 specified path is badly formed. */ |
|
324 { // static |
|
325 TParse parse; |
|
326 TInt retcode; |
|
327 retcode = parse.Set(aPath, NULL, NULL); |
|
328 if (retcode != KErrNone) |
|
329 return EFalse; |
|
330 if ((! parse.DrivePresent()) || (parse.NameOrExtPresent())) |
|
331 return EFalse; |
|
332 if (parse.Path().Length() == 0) |
|
333 return EFalse; |
|
334 TFileName dirName = parse.DriveAndPath(); |
|
335 if (dirName.Length() > KMaxFileName) |
|
336 return(EFalse); |
|
337 RDir dir; |
|
338 retcode = dir.Open(aFs,dirName,0); |
|
339 if (retcode == KErrNone) |
|
340 dir.Close(); |
|
341 return (retcode == KErrNone); |
|
342 } |
|
343 |
|
344 EXPORT_C void BaflUtils::EnsurePathExistsL(RFs& aFileSession,const TDesC& aFileName) |
|
345 /** Makes one or more directories, if they do not already exist. |
|
346 |
|
347 Any valid path component in the specified path that does not already exist |
|
348 is created as a directory. If the specified path already exists, the function |
|
349 returns normally. |
|
350 |
|
351 @param aFs File server session |
|
352 @param aFileName Path to ensure exists |
|
353 @see RFs::MkDirAll() */ |
|
354 { // static |
|
355 TInt error=aFileSession.MkDirAll(aFileName); |
|
356 if (error!=KErrAlreadyExists) |
|
357 User::LeaveIfError(error); |
|
358 } |
|
359 |
|
360 EXPORT_C TPtrC BaflUtils::ExtractAppNameFromFullName(const TFullName &aName) |
|
361 /** Gets the application name from a full thread name. |
|
362 |
|
363 @param aName Thread name |
|
364 @return Application name |
|
365 @see RThread */ |
|
366 { |
|
367 // static - return the app name (after first :: before next ::, if any) from a full thread name |
|
368 TChar delimiter=':'; |
|
369 TInt start=aName.Locate(delimiter); |
|
370 if (start<0) |
|
371 start=0; // should never happen |
|
372 else if (aName.Length()>start+2) |
|
373 start+=2; |
|
374 TPtrC rest=aName.Mid(start); |
|
375 TInt end=rest.Locate(delimiter); |
|
376 return end<0 ? rest : rest.Left(end); |
|
377 } |
|
378 |
|
379 LOCAL_C TBool IsLanguageExtended(const TLanguage aLanguage) |
|
380 { |
|
381 // For compatibility reasons, ELangNone is 0xFFFF. However, it's not an extended language. |
|
382 if ((aLanguage==ELangNone) || ((static_cast<TUint>(aLanguage))<=KDialectMask)) |
|
383 return EFalse; |
|
384 else |
|
385 return ETrue; |
|
386 } |
|
387 |
|
388 |
|
389 LOCAL_C TLanguage BaseLanguage(const TLanguage aLanguage) |
|
390 { |
|
391 if (IsLanguageExtended(aLanguage)) |
|
392 return static_cast<TLanguage>(aLanguage & KDialectMask); |
|
393 else |
|
394 return aLanguage; |
|
395 } |
|
396 |
|
397 LOCAL_C TLanguage NextLanguage(TLanguage aLanguage) |
|
398 /** Returns the next best language to use after aLanguage, |
|
399 based on Symbian's base table of language near-equivalence. |
|
400 @internalAll */ |
|
401 { |
|
402 switch (aLanguage) |
|
403 { |
|
404 case ELangAustralian: |
|
405 case ELangNewZealand: |
|
406 case ELangSouthAfricanEnglish: |
|
407 case ELangInternationalEnglish: |
|
408 case ELangAmerican: |
|
409 case ELangEnglish_Apac: |
|
410 case ELangEnglish_Taiwan: |
|
411 case ELangEnglish_HongKong: |
|
412 case ELangEnglish_Prc: |
|
413 case ELangEnglish_Japan: |
|
414 case ELangEnglish_Thailand: |
|
415 return ELangEnglish; |
|
416 case ELangCanadianEnglish: |
|
417 return ELangAmerican; // 2-stage downgrade |
|
418 case ELangSwissFrench: |
|
419 case ELangBelgianFrench: |
|
420 case ELangInternationalFrench: |
|
421 case ELangCanadianFrench: |
|
422 return ELangFrench; |
|
423 case ELangSwissGerman: |
|
424 case ELangAustrian: |
|
425 return ELangGerman; |
|
426 case ELangInternationalSpanish: |
|
427 case ELangLatinAmericanSpanish: |
|
428 return ELangSpanish; |
|
429 case ELangSwissItalian: |
|
430 return ELangItalian; |
|
431 case ELangFinlandSwedish: |
|
432 return ELangSwedish; |
|
433 case ELangCyprusTurkish: |
|
434 return ELangTurkish; |
|
435 case ELangBelgianFlemish: |
|
436 return ELangDutch; |
|
437 case ELangHongKongChinese: |
|
438 return ELangTaiwanChinese; |
|
439 case ELangCyprusGreek: |
|
440 return ELangGreek; |
|
441 case ELangMalay_Apac: |
|
442 return ELangMalay; |
|
443 case ELangBrazilianPortuguese: |
|
444 return ELangPortuguese; |
|
445 default: |
|
446 return ELangNone; |
|
447 } |
|
448 } |
|
449 |
|
450 |
|
451 void AddLanguage(TLanguagePath& aPath, TLanguage aNewLanguage) |
|
452 /** Add language to the language path if there is space. |
|
453 The first empty slot must have "ELangNone" in it. This will also be true |
|
454 on exit. */ |
|
455 { |
|
456 TLanguage *p = aPath; |
|
457 const TLanguage *end = &(aPath[KMaxDowngradeLanguages]); |
|
458 while (p != end) |
|
459 { |
|
460 if (*p == aNewLanguage) |
|
461 // language already in list |
|
462 break; |
|
463 if (*p == ELangNone) |
|
464 { |
|
465 // found the end of the list |
|
466 p[0] = aNewLanguage; |
|
467 p[1] = ELangNone; |
|
468 break; |
|
469 } |
|
470 ++p; |
|
471 } |
|
472 return; |
|
473 } |
|
474 |
|
475 void MakeLanguageDowngradePath(TLanguagePath& aPath, |
|
476 TLanguage aCurrent, TLanguage aIdeal, const TLocale& aLocale) |
|
477 { |
|
478 TInt j = 0; |
|
479 if( aIdeal != ELangNone) |
|
480 { |
|
481 aPath[j++]=aIdeal; |
|
482 } |
|
483 aPath[j++] = aCurrent; |
|
484 aPath[j++] = ELangNone; |
|
485 |
|
486 if (aCurrent & ~KDialectMask) |
|
487 AddLanguage(aPath, static_cast<TLanguage>(aCurrent & KDialectMask)); |
|
488 |
|
489 for (TInt i=0;i<=2;i++) |
|
490 { |
|
491 AddLanguage(aPath, aLocale.LanguageDowngrade(i)); |
|
492 AddLanguage(aPath, BaseLanguage(aLocale.LanguageDowngrade(i))); |
|
493 } |
|
494 |
|
495 while (ELangNone != (aCurrent = NextLanguage(BaseLanguage(aCurrent)))) |
|
496 AddLanguage(aPath, aCurrent); |
|
497 } |
|
498 |
|
499 TInt RRealDirectoryScanner::Open(RFs& aFs, const TDesC& aMatchPattern) |
|
500 { |
|
501 return iDir.Open(aFs, aMatchPattern, |
|
502 KEntryAttReadOnly | KEntryAttHidden | KEntryAttSystem | KEntryAttArchive); |
|
503 } |
|
504 |
|
505 TInt RRealDirectoryScanner::Next(TEntry& aOut) |
|
506 { |
|
507 return iDir.Read(aOut); |
|
508 } |
|
509 |
|
510 void RRealDirectoryScanner::Close() |
|
511 { |
|
512 iDir.Close(); |
|
513 } |
|
514 |
|
515 /** |
|
516 Simply counts the number of numerical characters at the end of the name passed. |
|
517 |
|
518 @internalComponent |
|
519 @param aFilename The filename to parse |
|
520 |
|
521 @return Count of the numeric digits at the end of the name passed, |
|
522 e.g. x.r491 gives 3. |
|
523 */ |
|
524 TInt TNearestLanguageFileFinder::CountDigitsFromEnd(const TDesC& aFilename) |
|
525 { |
|
526 TInt digitCount = 0; |
|
527 |
|
528 for (TInt idx = aFilename.Length()-1; idx>=0 && ISDIGIT (aFilename [idx]); --idx) |
|
529 { |
|
530 ++digitCount; |
|
531 } |
|
532 |
|
533 return digitCount; |
|
534 } |
|
535 |
|
536 |
|
537 /** |
|
538 Counts the number of digits at the end of a filename. |
|
539 |
|
540 @internalComponent |
|
541 @param aFilename The filename to parse |
|
542 |
|
543 @return Count of the numeric digits at the end of the suffix, |
|
544 e.g. x.r491 gives 3. |
|
545 0 if no numeric end of suffix, |
|
546 KErrBadName for an invalid filename, |
|
547 KErrNotSupported if the filename (minus path) is less |
|
548 than or equal to KInvNameAndMinSuffixLength in length |
|
549 */ |
|
550 TInt TNearestLanguageFileFinder::CountDigitsFromEndInSuffix (const TDesC& aFilename) |
|
551 { |
|
552 TInt digitCount = 0; |
|
553 TInt slashIdx = 0; |
|
554 TInt len = aFilename.Length (); |
|
555 |
|
556 // NOTE: We didn't use TChar here as they are too slow. |
|
557 // We also didn't use TParse as they are too large. |
|
558 |
|
559 // don't work on the path |
|
560 for (slashIdx=len-1; slashIdx >= 0 && aFilename[slashIdx] != '\\'; --slashIdx) |
|
561 {/*do nothing*/}; |
|
562 |
|
563 // Get new length |
|
564 if (slashIdx>=0) {len = len-slashIdx-1;} |
|
565 |
|
566 // Initial test to see if filename legal size. |
|
567 if (len > KInvNameAndMinSuffixLength) |
|
568 { |
|
569 digitCount = CountDigitsFromEnd(aFilename); |
|
570 |
|
571 // Can't store something bigger or we'll panic! |
|
572 if (digitCount > KMaxSuffixLength) |
|
573 { |
|
574 digitCount = KErrBadName; |
|
575 } |
|
576 else |
|
577 // numeric filename, e.g. "1234". |
|
578 // No preceeding alpha character |
|
579 if (!(len-digitCount)) |
|
580 { |
|
581 digitCount = KErrBadName; |
|
582 } |
|
583 } |
|
584 else |
|
585 { |
|
586 digitCount = KErrNotSupported; |
|
587 } |
|
588 |
|
589 return digitCount; |
|
590 } |
|
591 |
|
592 RDirectoryScanner& TNearestLanguageFileFinder::DirectoryScanner() |
|
593 { |
|
594 return iDirScanner; |
|
595 } |
|
596 |
|
597 TBool TNearestLanguageFileFinder::FileExists(const TDesC& aFileName) const |
|
598 { |
|
599 return BaflUtils::FileExists(iFs, aFileName); |
|
600 } |
|
601 |
|
602 TBool TNearestLanguageFileFinder::FindDrive() |
|
603 { |
|
604 ASSERT(iFileName); |
|
605 TBool found=EFalse; |
|
606 TInt driveLength=iDrives.Length(); |
|
607 for (TInt drive = 0; drive!=driveLength; ++drive) |
|
608 { |
|
609 (*iFileName)[0] = iDrives[drive]; |
|
610 if (FileExists(*iFileName)) |
|
611 { |
|
612 found=ETrue; |
|
613 break; |
|
614 } |
|
615 } |
|
616 return found; |
|
617 } |
|
618 |
|
619 TBool TNearestLanguageFileFinder::AppendLanguageCode(TLanguage aLanguage) |
|
620 { |
|
621 TInt rest = static_cast<TInt>(aLanguage); |
|
622 #ifdef _DEBUG |
|
623 _LIT(KErrorMessage, "Bafl"); |
|
624 #endif |
|
625 __ASSERT_DEBUG(0 <= rest, User::Panic(KErrorMessage,KErrArgument)); |
|
626 iFileName->SetLength(iBaseLength); |
|
627 const TInt remaining = iFileName->MaxLength() - iBaseLength; |
|
628 TInt soFar = 0; |
|
629 TBuf<1> num; |
|
630 num.Append('0'); |
|
631 TBool appendLangSuccess = ETrue; |
|
632 TInt digitCount = 0; |
|
633 TInt digit = 0; |
|
634 while (rest) |
|
635 { |
|
636 if (remaining == soFar) |
|
637 { |
|
638 // no more room in descriptor- return rather than panic, |
|
639 // file cannot exist. |
|
640 iFileName->SetLength(iBaseLength); |
|
641 appendLangSuccess= EFalse; |
|
642 break; |
|
643 } |
|
644 // Convert the number to ASCII by consistantly getting the base 10 remainder to convert. |
|
645 // The number is updated minus the remainder for the next iteration. |
|
646 // eg (rest = 123) -> (12, r3) -> (1, r2) -> (0, r1) |
|
647 // Then insert the ASCII representation of the remainder into the filename end |
|
648 // so it appears the correct way round. |
|
649 // eg (filename.r) -> (filename.r3) -> (filename.r23) -> (filename.r123) |
|
650 digit = rest % 10; |
|
651 digitCount++; |
|
652 rest /= 10; |
|
653 num[0] = static_cast<TText16>(digit + '0'); |
|
654 iFileName->Insert(iBaseLength, num); |
|
655 |
|
656 // Minimum suffix length is KInvNameAndMinSuffixLength |
|
657 // so we have to insert zeros to make this up. |
|
658 while (!rest && digitCount < KInvNameAndMinSuffixLength) |
|
659 { |
|
660 num[0] = static_cast<TText16>('0'); |
|
661 iFileName->Insert(iBaseLength, num); |
|
662 ++digitCount; |
|
663 } |
|
664 |
|
665 ++soFar; |
|
666 } |
|
667 |
|
668 return appendLangSuccess; |
|
669 } |
|
670 |
|
671 |
|
672 TBool TNearestLanguageFileFinder::FindLanguageAndDrive() |
|
673 /** Search for files across all drives in all languages in the path plus the |
|
674 language-neutral file. */ |
|
675 { |
|
676 ASSERT(iFileName); |
|
677 // No point appending if the suffix is bad |
|
678 for (const TLanguage* currentLang = iPath; *currentLang != ELangNone; ++currentLang) |
|
679 { |
|
680 if (AppendLanguageCode(*currentLang) && FindDrive()) |
|
681 { |
|
682 iLanguage = *currentLang; |
|
683 return ETrue; |
|
684 } |
|
685 } |
|
686 // search for language-neutral file |
|
687 iFileName->SetLength(iBaseLength); |
|
688 iFileName->Append(iSuffix); |
|
689 return FindDrive(); |
|
690 } |
|
691 |
|
692 TInt TNearestLanguageFileFinder::LanguageNumberFromFile(const TDesC& aFileName, const TDesC& aStem) |
|
693 { |
|
694 TInt lang = 0; |
|
695 TInt multiplier = 1; |
|
696 TInt leadingZeroCount = 0; |
|
697 TInt languageNumber = KErrNotFound; |
|
698 const TText* firstChar = aFileName.Ptr(); |
|
699 const TText* lastChar = firstChar + aFileName.Length() - 1; |
|
700 const TText* currentChar = lastChar; |
|
701 // string cannot contain only numbers, because it must have a ':' in it |
|
702 while ('0' <= *currentChar && *currentChar <= '9') |
|
703 { |
|
704 if (*currentChar == '0') |
|
705 leadingZeroCount++; |
|
706 else |
|
707 { |
|
708 leadingZeroCount = 0; |
|
709 lang += multiplier * (*currentChar - '0'); |
|
710 } |
|
711 multiplier *= 10; |
|
712 --currentChar; |
|
713 } |
|
714 TInt along=lastChar - currentChar; |
|
715 if (2 <= along) |
|
716 { |
|
717 // We have at least 2 digits at the end. |
|
718 // trim of bad leading zeros |
|
719 TInt maxTrim = along - 2; |
|
720 if (maxTrim < leadingZeroCount) |
|
721 { |
|
722 leadingZeroCount = maxTrim; |
|
723 } |
|
724 currentChar += leadingZeroCount; |
|
725 // we have at least 2 digits at the end but does the rest of it match the stem? |
|
726 TPtrC foundStem(firstChar, currentChar - firstChar + 1); |
|
727 //foundStem.CompareF(aStem.Right(foundStem.Length())) |
|
728 if (0 == foundStem.CompareF(aStem)) |
|
729 { |
|
730 languageNumber=lang; |
|
731 } |
|
732 } |
|
733 return languageNumber; |
|
734 } |
|
735 |
|
736 TInt TNearestLanguageFileFinder::FindFirstLanguageFile(RFs& aFs) |
|
737 { |
|
738 ASSERT(iFileName); |
|
739 iFileName->SetLength(iBaseLength); |
|
740 TPtrC name(*iFileName); |
|
741 TParsePtrC nameToParse(name); |
|
742 TPtrC nameStem(nameToParse.NameAndExt()); |
|
743 iFileName->Append('*'); |
|
744 TInt bestLanguageMatch = KMaxTInt; |
|
745 RDirectoryScanner& scanner = DirectoryScanner(); |
|
746 TInt err = scanner.Open(aFs, *iFileName); |
|
747 if (err != KErrNone) |
|
748 { |
|
749 return err; |
|
750 } |
|
751 TEntry entry; |
|
752 while (KErrNone == scanner.Next(entry)) |
|
753 { |
|
754 TInt lang = LanguageNumberFromFile(entry.iName, nameStem); |
|
755 if (0 < lang && lang < bestLanguageMatch) |
|
756 { |
|
757 bestLanguageMatch = lang; |
|
758 } |
|
759 } |
|
760 scanner.Close(); |
|
761 if (bestLanguageMatch != KMaxTInt) |
|
762 { |
|
763 iLanguage = static_cast<TLanguage>(bestLanguageMatch); |
|
764 AppendLanguageCode(static_cast<TLanguage>(bestLanguageMatch)); |
|
765 return KErrNone; |
|
766 } |
|
767 return KErrNotFound; |
|
768 } |
|
769 |
|
770 // Try each drive for any language files |
|
771 // iFileName must have a directory specifier |
|
772 TInt TNearestLanguageFileFinder::FindFirstLanguageFileAndDrive() |
|
773 { |
|
774 ASSERT(iFileName); |
|
775 TInt findFirstResult=KErrNotFound; |
|
776 TInt driveLength=iDrives.Length(); |
|
777 for (TInt drive = 0; drive != driveLength; ++drive) |
|
778 { |
|
779 (*iFileName)[0] = iDrives[drive]; |
|
780 TInt err = FindFirstLanguageFile(CONST_CAST(RFs&,iFs)); |
|
781 if (err == KErrNone || err == KErrNoMemory) |
|
782 { |
|
783 findFirstResult=err; |
|
784 break; |
|
785 } |
|
786 } |
|
787 return findFirstResult; |
|
788 } |
|
789 |
|
790 /** |
|
791 Invalid filenames are any filename whose length (minus path) must be greater |
|
792 than KInvNameAndMinSuffixLength, and whose form is purely numerical, i.e. '1234' |
|
793 */ |
|
794 TBool TNearestLanguageFileFinder::SetFileName(TFileName& aFileName) |
|
795 { |
|
796 iDrives.Zero(); |
|
797 iFileName = &aFileName; |
|
798 iOriginalBaseLength = iFileName->Length(); |
|
799 |
|
800 TInt suffixLength = CountDigitsFromEndInSuffix (aFileName); |
|
801 |
|
802 // No point trying for filenames thats are badly formed |
|
803 // or that are too large. |
|
804 if (suffixLength >= 0 && |
|
805 KInvNameAndMinSuffixLength < iOriginalBaseLength) |
|
806 { |
|
807 if (suffixLength > 0) |
|
808 { |
|
809 // all of suffix to be replaced |
|
810 iSuffix = iFileName->Right(suffixLength); |
|
811 iOriginalBaseLength -= suffixLength; |
|
812 iFileName->SetLength(iOriginalBaseLength); |
|
813 } |
|
814 else |
|
815 { |
|
816 // No numerical part to suffix |
|
817 TInt periodIdx = 0; |
|
818 |
|
819 // Search for the period within range KInvNameAndMinSuffixLength |
|
820 // from the end. As this must work for all values of |
|
821 // KInvNameAndMinSuffixLength |
|
822 for (TInt i = iOriginalBaseLength-1; |
|
823 !periodIdx && i >= (iOriginalBaseLength-KInvNameAndMinSuffixLength-1); |
|
824 --i) |
|
825 { |
|
826 if ((*iFileName) [i] == '.') |
|
827 { |
|
828 periodIdx = i; |
|
829 } |
|
830 } |
|
831 |
|
832 // Don't handle files ending in a period. |
|
833 // This is because the behaviour is different between Windows |
|
834 // and Symbian Fs. In Windows it strips the period off. |
|
835 // |
|
836 // However, and this shouldn't happen as it is not shown |
|
837 // (in the documentation) to be valid. |
|
838 // Just try our best. |
|
839 if (periodIdx == iOriginalBaseLength-1) |
|
840 { |
|
841 iSuffix.Zero(); |
|
842 return EFalse; |
|
843 } |
|
844 else |
|
845 if (periodIdx) |
|
846 { |
|
847 // If there are KInvNameAndMinSuffixLength chars after the period |
|
848 // simply replace them. |
|
849 TInt right = iOriginalBaseLength-periodIdx-1; |
|
850 iSuffix = iFileName->Right(right); |
|
851 iOriginalBaseLength -= right; |
|
852 iFileName->SetLength(iOriginalBaseLength); |
|
853 } |
|
854 else |
|
855 { |
|
856 // Make the suffix start from KInvNameAndMinSuffixLength |
|
857 // from the right |
|
858 TInt right = KInvNameAndMinSuffixLength; |
|
859 iSuffix = iFileName->Right(right); |
|
860 iOriginalBaseLength -= right; |
|
861 iFileName->SetLength(iOriginalBaseLength); |
|
862 } |
|
863 } |
|
864 } |
|
865 else |
|
866 { |
|
867 // bad or no suffix - treat the same |
|
868 iSuffix.Zero(); |
|
869 return EFalse; |
|
870 } |
|
871 |
|
872 // For filenames with no drive letter prefix and also for filenames |
|
873 // shorter than the drive letter length, i.e. with no drive |
|
874 // information, insert it. |
|
875 // Handles if the user simply enters the drive, e.g. "c:". |
|
876 if (iOriginalBaseLength < KMaxDriveName || (*iFileName)[1] != ':') |
|
877 { |
|
878 // Set up the default if none supplied and make room in the filename |
|
879 // array to contain a drive specification. Set initial drive letter to -1 |
|
880 // so the iFileName is repaired before exited |
|
881 iInitialDriveLetter = -1; |
|
882 iFileName->Insert(0, _L("_:")); |
|
883 iDrives.Append('Z'); |
|
884 } |
|
885 else |
|
886 { |
|
887 // Use the drive supplied inthe aName to NearestLanguageFile() |
|
888 iInitialDriveLetter = (*iFileName)[0]; |
|
889 iDrives.Append(iInitialDriveLetter); |
|
890 } |
|
891 |
|
892 iBaseLength = iFileName->Length(); |
|
893 |
|
894 return ETrue; |
|
895 } |
|
896 |
|
897 |
|
898 TLanguage TNearestLanguageFileFinder::Language() |
|
899 { |
|
900 return iLanguage; |
|
901 } |
|
902 |
|
903 TNearestLanguageFileFinder::TNearestLanguageFileFinder( |
|
904 const RFs& aFs) |
|
905 : iFs(aFs), iFileName(0), iLanguage(ELangNone) |
|
906 { |
|
907 } |
|
908 |
|
909 void TNearestLanguageFileFinder::RepairFileName() |
|
910 { |
|
911 ASSERT(iFileName); |
|
912 iFileName->SetLength(iBaseLength); |
|
913 if (iInitialDriveLetter == -1) |
|
914 iFileName->Delete(0, 2); |
|
915 else |
|
916 (*iFileName)[0] = static_cast<TText>(iInitialDriveLetter); |
|
917 iFileName->SetLength(iOriginalBaseLength); |
|
918 iFileName->Append(iSuffix); |
|
919 } |
|
920 |
|
921 |
|
922 /** |
|
923 Add the custom resource drive to the start of the iDrives string. |
|
924 |
|
925 The custom resource drive is a preset writeable drive on which customised |
|
926 resource files may be present. This drive takes priority over the other |
|
927 drives when searching for language files. |
|
928 |
|
929 @return KErrNone if iDrives string was successfully modified; KErrAlreadyExists |
|
930 if the drive is already present in the string; otherwise one of |
|
931 the other system-wide error codes (iDrives will be unmodified). |
|
932 */ |
|
933 TInt TNearestLanguageFileFinder::AddCustomResourceDrive() |
|
934 { |
|
935 TInt drive = GetCustomResourceDriveNumber(); |
|
936 if (drive<0) |
|
937 return drive; |
|
938 |
|
939 // if drive not already in drive list |
|
940 if (iDrives.LocateF('A' + drive) < 0) |
|
941 { |
|
942 // add it |
|
943 _LIT(KDrivePlaceholder, "_"); |
|
944 iDrives.Insert(0, KDrivePlaceholder); |
|
945 iDrives[0] = 'A' + drive; |
|
946 return KErrNone; |
|
947 } |
|
948 else |
|
949 return KErrAlreadyExists; |
|
950 } |
|
951 |
|
952 |
|
953 void TNearestLanguageFileFinder::AddAllDrives() |
|
954 { |
|
955 ASSERT(iDrives.Length() < 2); |
|
956 if (iDrives.Length() == 0) |
|
957 { |
|
958 iDrives = KAllDrives; |
|
959 return; |
|
960 } |
|
961 TInt pos = KAllDrives().LocateF(iDrives[0]); |
|
962 if (pos < 0) |
|
963 { |
|
964 iDrives = KAllDrives; |
|
965 return; |
|
966 } |
|
967 iDrives.Append(KAllDrives().Left(pos)); |
|
968 iDrives.Append(KAllDrives().Mid(pos + 1)); |
|
969 } |
|
970 |
|
971 |
|
972 /** |
|
973 Get the value of the custom resource drive. |
|
974 |
|
975 The custom resource drive is a preset writeable drive on which customised language resource |
|
976 files can reside. The drive number is accessed via the HAL attribute ECustomResourceDrive. |
|
977 It is then returned if it has been defined as a valid drive no. |
|
978 Otherwise for backward compatibility reasons an attempt is then made to access the system |
|
979 drive HAL attribute instead. This drive number is returned if it has been defined as a valid |
|
980 drive number. |
|
981 Otherwise if neither a valid ECustomResourceDrive or ESystemDrive exists then KErrNotFound |
|
982 is returned. |
|
983 |
|
984 Note that the ESystemDrive HAL attribute has been deprecated. It is accessed here to cater |
|
985 for existing implementations which still expect it to be used. |
|
986 |
|
987 @return The drive number (corresponding to a TDriveNumber value) if successful; |
|
988 KErrNotFound if neither a valid ECustomResourceDrive or a valid ESystemDrive HAL attribute |
|
989 is defined; |
|
990 |
|
991 @see HAL::ECustomResourceDrive |
|
992 @see HAL::ESystemDrive |
|
993 */ |
|
994 TInt TNearestLanguageFileFinder::GetCustomResourceDriveNumber() const |
|
995 { |
|
996 TInt drive = KErrNotFound; |
|
997 |
|
998 // access custom resource drive attribute |
|
999 if (HAL::Get(HAL::ECustomResourceDrive, drive) == KErrNone) |
|
1000 { |
|
1001 // check that drive is valid |
|
1002 if (drive>=EDriveA && drive<=EDriveZ) |
|
1003 return drive; |
|
1004 } |
|
1005 |
|
1006 // access system drive attribute |
|
1007 // (Note that ESystemDrive is deprecated. It is checked here |
|
1008 // solely for backward compatibility reasons.) |
|
1009 if (HAL::Get(HAL::ESystemDrive, drive) == KErrNone) |
|
1010 { |
|
1011 // check that drive is valid |
|
1012 if (drive>=EDriveA && drive<=EDriveZ) |
|
1013 return drive; |
|
1014 } |
|
1015 |
|
1016 return KErrNotFound; |
|
1017 } |
|
1018 |
|
1019 |
|
1020 |
|
1021 /** Get the value of the system drive. |
|
1022 |
|
1023 The system drive can be set to one of the built-in read/write drives. Which |
|
1024 drive is used is hardware-dependent. On some hardware, there may not be a |
|
1025 system drive. The system drive is used as the drive on which localisable files |
|
1026 are searched for. This enables a phone to be localised dynamically, using |
|
1027 files not in the ROM. |
|
1028 |
|
1029 @param aDriveNumber On return, contains the drive number of the system drive. |
|
1030 @return KErrNone is always returned. |
|
1031 |
|
1032 @deprecated This method has been replaced by (and now internally calls) |
|
1033 RFs:GetSystemDrive, which always returns a valid drive number. |
|
1034 |
|
1035 @see BaflUtils::NearestLanguageFile |
|
1036 @see RFs::GetSystemDrive |
|
1037 */ |
|
1038 EXPORT_C TInt BaflUtils::GetSystemDrive(TDriveNumber& aDriveNumber) |
|
1039 { |
|
1040 aDriveNumber = RFs::GetSystemDrive(); |
|
1041 return KErrNone; |
|
1042 } |
|
1043 |
|
1044 |
|
1045 /** Set most appropriate extension language code for filename and set corresponding language. |
|
1046 |
|
1047 Symbian uses numeric values to identify natural languages as specified by the TLanguage enumeration |
|
1048 defined in e32const.h. These values are used at the end of filename extensions to identify the |
|
1049 languages pertaining to files which have language specific variants such as resource files. |
|
1050 For instance filename.r01 and filename.r02 would be the English and French versions of the |
|
1051 resource file filename.rsc. Language codes can be between 2 to 5 digits in length. |
|
1052 |
|
1053 Starting from Symbian OS v7.0 this function constructs and uses a language downgrade path which |
|
1054 consists of up to sixteen TLanguage values the first of which is the ideal language followed by |
|
1055 the language of the current locale. Up to the next three can be customised using |
|
1056 TLocale::SetLanguageDowngrade(). The rest of the language downgrade path is based on a |
|
1057 table of language near equivalence which is internal to Symbian. |
|
1058 |
|
1059 This function searches the custom resource drive (if set, retrieved from HAL) |
|
1060 and then searches the optional drive specified in aName or 'Z:' if none is |
|
1061 specified in aName. The custom resource drive is retrieved from the HAL |
|
1062 attribute ECustomResourceDrive if set, if not set it will retrieve the legacy |
|
1063 value set in the legacy HAL attribute ESystemDrive. No custom resource drive |
|
1064 is searched if neither are set. |
|
1065 Note - setting the custom resource drive will reduce the performance of this |
|
1066 routine which will adversely affect device performance e.g. at boot up. |
|
1067 On NAND Flash based devices use of a composite Z: drive file system made up of multiple |
|
1068 ROM images is the preferred mechanism for customising language resources on devices in |
|
1069 Symbian OS 9.2 onwards, see Developer Library » Base Porting Guide » Porting: background |
|
1070 information » NAND flash » NAND Flash image format. Thus use of the custom resource drive |
|
1071 HAL attribute is effectively obsolete. |
|
1072 |
|
1073 The last two characters of aName are removed along with any digits which appear before them. |
|
1074 Then language codes specified in the constructed language downgrade path are appended in turn to |
|
1075 aName as a match is searched for in the file system. In case no match is found using the |
|
1076 constructed language downgradepath then files in the specified directory are searched for a |
|
1077 suitable extension with preference given to the one specified if present. In cases where a |
|
1078 match takes place the aName and aLanguage arguments are updated otherwise aName is left |
|
1079 unchanged and aLanguage is set to ELangNone. |
|
1080 |
|
1081 Here are some examples of correct and incorrect function usage with different aName inputs, |
|
1082 file system state and downgrade paths as follows: |
|
1083 |
|
1084 @code |
|
1085 Following files exist: |
|
1086 C:\\abc.rsc - Language Neutral resource file. |
|
1087 C:\\abc.r01 - Resource file for the English language. |
|
1088 C:\\abc.r10 - Resource file for the American-English language. |
|
1089 C:\\abc.r160 - Resource file for the English as appropriate in Japan. |
|
1090 |
|
1091 Constructed Downgrade Language Path cases: |
|
1092 - Case 1. (ELangAmerican -> ELangEnglish -> ELangNone). |
|
1093 - Case 2. (ELangEnglish_Japan -> ELangEnglish -> ELangNone). |
|
1094 - Case 3. Same as case 1, However "C:\\abc.r10" is deleted prior to the function call. |
|
1095 - Case 4. Same as case 1, However both "C:\\abc.r01" and "C:\\abc.r10" are deleted prior to the function call. |
|
1096 @endcode |
|
1097 |
|
1098 @code |
|
1099 Input aName . . . . Output aName. . . aLanguage . . . . . Description |
|
1100 -------------------------------------------------------------------------------------------------------------------- |
|
1101 "C:\\abc.rsc" . . . "C:\\abc.r10" . . ELangAmerican . . . Match on first language (Case 1) |
|
1102 "C:\\abc.r10" . . . "C:\\abc.r10" . . ELangAmerican . . . Match, However it's not the intended use of |
|
1103 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . the function (Case 1) |
|
1104 "C:\\abc.r" . . . . "C:\\abc.r" . . . ELangNone . . . . . The no. of characters in the suffix is less than |
|
1105 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . KInvNameAndMinSuffixLength(2)(Case 1) |
|
1106 "C:\\abc.". . . . . "C:\\abc.". . . . ELangNone . . . . . Invalid Suffix: The filename ends with a period(Case 1) |
|
1107 "C:\\abc.r123456" . "C:\\abc.r123456" ELangNone . . . . . Invalid Suffix: The no. of digits in the suffix is greater |
|
1108 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . than KMaxSuffixLength(5) (Case 1) |
|
1109 "C:\\abc.10". . . . "C:\\abc.10 . . . ELangNone . . . . . Invalid Suffix: There's no proceeding alphabetical |
|
1110 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . characters in the suffix (Case 1) |
|
1111 "\\abc.rsc" . . . . "\\abc.rsc" . . . ELangNone . . . . . No drive so Z: search, no match (Case 1) |
|
1112 "C:\\abc.rsc" . . . "C:\\abc.r160". . ELangEnglish_Japan. Match for language file 3 digits long (Case 2) |
|
1113 "C:\\abc.rsc" . . . "C:\\abc.r01" . . ELangEnglish. . . . Match on second language (Case 3) |
|
1114 "C:\\abc.rsc" . . . "C:\\abc.rsc" . . ELangNone . . . . . No corresponding langauge file match found (Case 4) |
|
1115 --------------------------------------------------------------------------------------------------------------------- |
|
1116 @endcode |
|
1117 |
|
1118 @param aFs File server session. |
|
1119 @param aName Optional drive specification, followed by optional path name, |
|
1120 followed by basename for filename, followed by period and extension. |
|
1121 On return, in case of a match, this is replaced by the language-specific version |
|
1122 which consists of the last two characters of the extension plus any preceding |
|
1123 numeric characters being replaced by the language code. Remains unchanged when there's no match |
|
1124 @param aLanguage On return, in case of a match, this is replaced by the corresponding language. |
|
1125 In case of no match it's set to ELangNone. |
|
1126 @see TLanguage |
|
1127 @see BaflUtils::GetDowngradePathL |
|
1128 @see TLocale::SetLanguageDowngrade |
|
1129 */ |
|
1130 EXPORT_C void BaflUtils::NearestLanguageFile(const RFs& aFs,TFileName& aName, TLanguage& aLanguage) |
|
1131 { |
|
1132 #if defined(DO_PROFILING) |
|
1133 RDebug::ProfileReset(FIRST_PROFILE_INDEX, PROFILE_COUNT); |
|
1134 RDebug::ProfileStart(PROFILE_INDEX_1); |
|
1135 #endif |
|
1136 TNearestLanguageFileFinder finder(aFs); |
|
1137 TBool goodSuffix=finder.SetFileName(aName); |
|
1138 |
|
1139 // Only continue if the suffix is good. |
|
1140 if(goodSuffix) |
|
1141 { |
|
1142 // add preset customised resource drive to drive list |
|
1143 // Note that errors returned from AddCustomResourceDrive are ignored. This is because if |
|
1144 // a custom resource drive has not been found we still want to continue on with searching |
|
1145 // other drives according to our algorithm |
|
1146 finder.AddCustomResourceDrive(); |
|
1147 |
|
1148 TLocale locale; |
|
1149 TLanguage idealLanguage; |
|
1150 idealLanguage = IdealLanguage(); |
|
1151 MakeLanguageDowngradePath(finder.iPath, User::Language(), idealLanguage, locale); |
|
1152 if (!finder.FindLanguageAndDrive() |
|
1153 && KErrNone != finder.FindFirstLanguageFileAndDrive()) |
|
1154 finder.RepairFileName(); |
|
1155 aLanguage = finder.Language(); |
|
1156 } |
|
1157 |
|
1158 #if defined(DO_PROFILING) |
|
1159 RDebug::ProfileEnd(PROFILE_INDEX_1); |
|
1160 TProfile profile[PROFILE_COUNT]; |
|
1161 RDebug::ProfileResult(&profile[0], FIRST_PROFILE_INDEX, PROFILE_COUNT); |
|
1162 if(goodSuffix) |
|
1163 { |
|
1164 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); |
|
1165 } |
|
1166 else |
|
1167 { |
|
1168 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); |
|
1169 } |
|
1170 #endif |
|
1171 } |
|
1172 |
|
1173 /** Searches for the file with the correct language extension for the language |
|
1174 of the current locale, or failing this, the best matching file. |
|
1175 |
|
1176 @param aFs File server session. |
|
1177 @param aName File name as it would be without a language-specific extension. |
|
1178 On return, this is changed to the language-specific version. If no such file |
|
1179 is found, the name is unchanged. |
|
1180 @see BaflUtils::NearestLanguageFile(const RFs& aFs,TFileName& aName, TLanguage& aLanguage) */ |
|
1181 EXPORT_C void BaflUtils::NearestLanguageFile(const RFs& aFs,TFileName& aName) |
|
1182 { |
|
1183 TLanguage language; |
|
1184 |
|
1185 NearestLanguageFile( aFs, aName, language); |
|
1186 |
|
1187 (void)language; |
|
1188 } |
|
1189 |
|
1190 /** Set the ideal language for the thread. |
|
1191 This interface is intended for the use of UIKON only. |
|
1192 |
|
1193 @param aLanguage Ideal language. |
|
1194 @return KErrNone, if successful; KErrNoMemory if there is not enough memory @see TLanguage |
|
1195 @see BaflUtils::NearestLanguageFile() |
|
1196 @internalAll */ |
|
1197 EXPORT_C TInt BaflUtils::SetIdealLanguage(TLanguage aLanguage) |
|
1198 { |
|
1199 TLanguage* langPtr=(TLanguage*)Dll::Tls(); |
|
1200 if( langPtr==NULL) |
|
1201 { |
|
1202 langPtr=(TLanguage*)User::Alloc(sizeof(TLanguage)); |
|
1203 |
|
1204 if(!langPtr) |
|
1205 return(KErrNoMemory); |
|
1206 |
|
1207 TInt ret=Dll::SetTls(langPtr); |
|
1208 |
|
1209 if(ret!=KErrNone) |
|
1210 return(ret); |
|
1211 } |
|
1212 *langPtr=aLanguage; |
|
1213 return(KErrNone); |
|
1214 } |
|
1215 |
|
1216 /** Get the ideal language of the thread. |
|
1217 This interface is intended for the use of UIKON only. |
|
1218 |
|
1219 @return Ideal language if set, ELangNone if not set |
|
1220 @see BaflUtils::NearestLanguageFile() |
|
1221 @internalAll */ |
|
1222 EXPORT_C TLanguage BaflUtils::IdealLanguage() |
|
1223 { |
|
1224 TLanguage* langPtr=(TLanguage*)Dll::Tls(); |
|
1225 |
|
1226 if( langPtr==NULL) |
|
1227 { |
|
1228 return(ELangNone); |
|
1229 } |
|
1230 |
|
1231 return(*langPtr); |
|
1232 } |
|
1233 |
|
1234 EXPORT_C void BaflUtils::ReleaseIdealLanguage() |
|
1235 /** Releases the ideal language store if it has been allocated. |
|
1236 This interface is intended for the use of UIKON only. |
|
1237 |
|
1238 @internalAll */ |
|
1239 { |
|
1240 TLanguage* aLanguage=(TLanguage*)Dll::Tls(); |
|
1241 if( aLanguage==NULL) |
|
1242 return; |
|
1243 |
|
1244 delete aLanguage; |
|
1245 Dll::FreeTls(); |
|
1246 } |
|
1247 |
|
1248 EXPORT_C TInt BaflUtils::IsFolder(const RFs& aFs, const TDesC& aFullName, TBool& aIsFolder) |
|
1249 /** Checks if the specified item is a folder. |
|
1250 |
|
1251 @param aFs File server session |
|
1252 @param aFullName Name to check |
|
1253 @param aIsFolder ETrue if aFullName is a folder, otherwise EFalse |
|
1254 @return KErrNone if successful, otherwise another of the system-wide error |
|
1255 codes */ |
|
1256 { |
|
1257 TParsePtrC parse(aFullName); |
|
1258 if ((parse.DriveAndPath().Length() == KDriveAndPathLength) && (aFullName.Length() == KDriveAndPathLength)) |
|
1259 { |
|
1260 aIsFolder = ETrue; |
|
1261 return(KErrNone); |
|
1262 } |
|
1263 TEntry entry; |
|
1264 TInt retcode = aFs.Entry(aFullName, entry); |
|
1265 if (retcode == KErrNone) |
|
1266 aIsFolder = ((entry.iAtt & KEntryAttDir)==KEntryAttDir); |
|
1267 |
|
1268 return(retcode); |
|
1269 } |
|
1270 |
|
1271 |
|
1272 EXPORT_C TBool BaflUtils::FolderExists(RFs& aFs, const TDesC& aFolderName) |
|
1273 /** Tests whether a folder exists. |
|
1274 |
|
1275 The folder is specified in a path. The path can omit the drive letter, in |
|
1276 which case the drive letter is taken from the session path. |
|
1277 |
|
1278 If the path is badly formed, for instance if it contains illegal characters, |
|
1279 or any directory name consists of a single or double dot, or any directory |
|
1280 name includes wildcard characters, the function returns EFalse. |
|
1281 |
|
1282 If a filename is included in the path, it is ignored (the existence |
|
1283 of the file will not be checked). However if included, it must not |
|
1284 be badly formed - this will cause the function to return EFalse. |
|
1285 If no filename is specified, the path should end in a backslash. |
|
1286 |
|
1287 Examples of valid paths (returning ETrue): |
|
1288 C:\; \; C:\Readme.txt; C:\system\data\; \system\data\Anyfile.dat |
|
1289 |
|
1290 Examples of invalid paths (returning EFalse): |
|
1291 C:\FolderDoesntExist\; ..\system\; C:\Wild*card\; C:\system\data\Bad>File.txt |
|
1292 |
|
1293 @param aFs A connected session with the file server. |
|
1294 @param aFolderName A path specifying the folder to test for. |
|
1295 @return ETrue if the folder specified in aFolderName exists, EFalse if not. |
|
1296 EFalse is also returned if the specified path is badly formed. */ |
|
1297 { |
|
1298 if (aFolderName.Length()==0) |
|
1299 {return EFalse;} |
|
1300 |
|
1301 TParse parse; |
|
1302 |
|
1303 TInt retcode = parse.SetNoWild(aFolderName, NULL, NULL); |
|
1304 |
|
1305 if (retcode != KErrNone) |
|
1306 {return EFalse;} |
|
1307 |
|
1308 if (parse.NameOrExtPresent()) |
|
1309 if (!aFs.IsValidName(aFolderName)) |
|
1310 {return EFalse;} |
|
1311 |
|
1312 TPtrC dirName = parse.DriveAndPath(); |
|
1313 RDir dir; |
|
1314 retcode = dir.Open(aFs,dirName,0); |
|
1315 if (retcode == KErrNone) |
|
1316 {dir.Close();} |
|
1317 return (retcode == KErrNone); |
|
1318 } |
|
1319 |
|
1320 |
|
1321 EXPORT_C TFileName BaflUtils::FolderNameFromFullName(const TDesC& aFullName) |
|
1322 /** Gets the folder name from a path. |
|
1323 |
|
1324 A valid full name should have a drive associated with it |
|
1325 e.g ("a:\\" - "z:\\")("a:" - "z:")("c:\\system\data\file.txt") |
|
1326 Invalid entry will have no drive and cause a panic EBafPanicBadOpenArg |
|
1327 For example, if the path is "c:\documents\word\mydoc1", then "word" is returned. |
|
1328 "c:" then "c:" is returned |
|
1329 "c:\\" then "c:\" is returned |
|
1330 "c:\\mydoc1.txt then "c:\" is returned |
|
1331 |
|
1332 @param aFullName A path. |
|
1333 @return The folder name. */ |
|
1334 { |
|
1335 TParsePtrC parse(aFullName); |
|
1336 |
|
1337 __ASSERT_ALWAYS(parse.DrivePresent(),Panic(EBafPanicBadOpenArg)); |
|
1338 |
|
1339 TFileName folderName = parse.Path(); |
|
1340 //If the path name has no associated path(e.g "c:") or path='\'(e.g "c:\\", "c:\\file.txt") |
|
1341 //then the folder name is just equal to drivename |
|
1342 |
|
1343 TBuf<1> pathSeparator; |
|
1344 pathSeparator.Append(KPathDelimiter); |
|
1345 |
|
1346 if (folderName.Length()==0 || folderName==pathSeparator) |
|
1347 return (parse.DriveAndPath()); |
|
1348 //else just get the foldername |
|
1349 TInt len = folderName.Length(); |
|
1350 TInt pos = --len; |
|
1351 while (--pos) |
|
1352 if (folderName.Mid(pos, 1)==pathSeparator) |
|
1353 break; |
|
1354 folderName.Delete(len, 1); |
|
1355 folderName.Delete(0, pos+1); |
|
1356 return(folderName); |
|
1357 } |
|
1358 |
|
1359 |
|
1360 EXPORT_C TFileName BaflUtils::DriveAndPathFromFullName(const TDesC& aFullName) |
|
1361 /** Gets the drive letter and path from a file name. |
|
1362 |
|
1363 This is in the form: drive-letter:\\path\\. The drive letter is folded using |
|
1364 class TCharF. |
|
1365 |
|
1366 @param aFullName File name |
|
1367 @return The drive and path */ |
|
1368 { |
|
1369 TParsePtrC parse(aFullName); |
|
1370 return (parse.DriveAndPath()); |
|
1371 } |
|
1372 |
|
1373 |
|
1374 EXPORT_C TFileName BaflUtils::RootFolderPath(const TBuf<1> aDriveLetter) |
|
1375 /** Gets the root folder for the specified drive. |
|
1376 |
|
1377 If aDriveLetter is an alphabet(lowercase or uppercase) then it will return |
|
1378 the TFileName which is simply the drive letter plus ":\" |
|
1379 If this is not the case, the function will panic with panic code EBafPanicBadOpenArg |
|
1380 |
|
1381 @param aDriveLetter Drive letter |
|
1382 @return Root folder */ |
|
1383 { |
|
1384 TChar driveLetter(aDriveLetter[0]); |
|
1385 driveLetter.LowerCase(); |
|
1386 TInt aDriveNumber=driveLetter-TChar('a'); |
|
1387 __ASSERT_ALWAYS(aDriveNumber>= EDriveA && aDriveNumber <= EDriveZ,Panic(EBafPanicBadOpenArg)); |
|
1388 |
|
1389 TFileName rootFolderPath = aDriveLetter; |
|
1390 rootFolderPath.Append(_L(":\\")); |
|
1391 return rootFolderPath; |
|
1392 } |
|
1393 |
|
1394 |
|
1395 EXPORT_C void BaflUtils::AbbreviateFileName(const TFileName& aOriginalFileName, TDes& aAbbreviatedFileName) |
|
1396 /** Abbreviates a file name. |
|
1397 |
|
1398 If aOriginalFileName is less than the maximum length of aAbbreviatedFileName, |
|
1399 then the name is simply copied to aAbbreviatedFileName. |
|
1400 |
|
1401 If this is not so, then the left-most characters of aOriginalFileName are |
|
1402 copied to aAbbreviatedFileName, up to aAbbreviatedFileName's maximum length-1. |
|
1403 aAbbreviatedFileName's first character is set to be an ellipsis. |
|
1404 |
|
1405 @param aOriginalFileName Original file name |
|
1406 @param aAbbreviatedFileName On return, abbreviated file name */ |
|
1407 { |
|
1408 TInt maxWidthInChars = aAbbreviatedFileName.MaxLength(); |
|
1409 if (aOriginalFileName.Length() <= maxWidthInChars) |
|
1410 { |
|
1411 aAbbreviatedFileName = aOriginalFileName; |
|
1412 return; |
|
1413 } |
|
1414 TChar ellipsis(0x2026); |
|
1415 --maxWidthInChars; // since the ellipsis will be the first char in aAbbreviatedFileName |
|
1416 aAbbreviatedFileName.Zero(); |
|
1417 aAbbreviatedFileName.Append(ellipsis); |
|
1418 aAbbreviatedFileName.Append(aOriginalFileName.Mid((aOriginalFileName.Length() - 1) - maxWidthInChars + 1, maxWidthInChars)); |
|
1419 } |
|
1420 |
|
1421 |
|
1422 EXPORT_C TBool BaflUtils::UidTypeMatches(const TUidType& aFileUid, const TUidType& aMatchUid) |
|
1423 /** Tests whether two UID types match. |
|
1424 |
|
1425 A match is made if each UID in aMatchUid is either identical to the corresponding |
|
1426 one in aFileUid, or is KNullUid. |
|
1427 |
|
1428 @param aFileUid The UID type to match |
|
1429 @param aMatchUid The UID type to match against |
|
1430 @return ETrue if the UIDs match, otherwise EFalse */ |
|
1431 { |
|
1432 for (TInt i=0; i<KMaxCheckedUid; i++) |
|
1433 { |
|
1434 if (aMatchUid[i] == KNullUid) |
|
1435 continue; |
|
1436 if (aMatchUid[i] != aFileUid[i]) |
|
1437 return(EFalse); |
|
1438 } |
|
1439 return(ETrue); |
|
1440 } |
|
1441 |
|
1442 |
|
1443 EXPORT_C TInt BaflUtils::Parse(const TDesC& aName) |
|
1444 /** Checks if a specified file name can be parsed. |
|
1445 |
|
1446 @param aName Name to parse |
|
1447 @return KErrNone if successful, otherwise another of the system-wide error |
|
1448 codes */ |
|
1449 { // keeps a TParse on the stack for the minimum time possible |
|
1450 TParse parse; |
|
1451 return parse.Set(aName,NULL,NULL); |
|
1452 } |
|
1453 |
|
1454 |
|
1455 EXPORT_C TInt BaflUtils::ValidateFolderNameTypedByUserL(const RFs& aFs, const TDesC& aFolderNameTypedByUser, const TDesC& aCurrentPath, TFileName& aNewFolderFullName) |
|
1456 /** Checks if a folder name (without drive or path) is valid and returns the full |
|
1457 name of the folder. |
|
1458 |
|
1459 @param aFs File server session |
|
1460 @param aFolderNameTypedByUser Folder name to check |
|
1461 @param aCurrentPath Path to which to add the folder |
|
1462 @param aNewFolderFullName aFolderNameTypedByUser appended to aCurrentPath |
|
1463 @return KErrNone if successful, otherwise another of the system-wide error |
|
1464 codes */ |
|
1465 { |
|
1466 if (aFolderNameTypedByUser.Length() == 0) |
|
1467 return KErrArgument; // R_EIK_TBUF_NO_FOLDERNAME_SPECIFIED; |
|
1468 |
|
1469 TParse* targetParse = new(ELeave) TParse; |
|
1470 CleanupStack::PushL(targetParse); |
|
1471 |
|
1472 TInt retcode = targetParse->Set(aFolderNameTypedByUser, NULL, NULL); |
|
1473 User::LeaveIfError(retcode); |
|
1474 if (targetParse->DrivePresent() || targetParse->PathPresent()) |
|
1475 { |
|
1476 CleanupStack::PopAndDestroy(); |
|
1477 return KErrBadName; // R_EIK_TBUF_INVALID_FOLDER_NAME; |
|
1478 } |
|
1479 |
|
1480 if (!(aFs.IsValidName(aFolderNameTypedByUser))) |
|
1481 { |
|
1482 CleanupStack::PopAndDestroy(); |
|
1483 return KErrBadName; // R_EIK_TBUF_INVALID_FOLDER_NAME; |
|
1484 } |
|
1485 |
|
1486 |
|
1487 if ((aCurrentPath.Length() + aFolderNameTypedByUser.Length() + 1) > KMaxFileName) |
|
1488 { |
|
1489 CleanupStack::PopAndDestroy(); |
|
1490 return KErrTooBig; //R_EIK_TBUF_FOLDERNAME_TOO_LONG; |
|
1491 } |
|
1492 |
|
1493 |
|
1494 //TFileName newFolderFullName = aCurrentPath; |
|
1495 aNewFolderFullName = aCurrentPath; |
|
1496 if ((aNewFolderFullName.Length() + aFolderNameTypedByUser.Length() + 1) <= KMaxFileName) |
|
1497 { |
|
1498 aNewFolderFullName.Append(aFolderNameTypedByUser); |
|
1499 aNewFolderFullName.Append(KPathDelimiter); |
|
1500 } |
|
1501 else |
|
1502 { |
|
1503 CleanupStack::PopAndDestroy(); |
|
1504 return KErrOverflow; |
|
1505 } |
|
1506 |
|
1507 retcode = targetParse->Set(aNewFolderFullName, NULL, NULL); |
|
1508 if (retcode != KErrNone) |
|
1509 { |
|
1510 CleanupStack::PopAndDestroy(); |
|
1511 return KErrBadName; // R_EIK_TBUF_INVALID_FOLDER_NAME; |
|
1512 } |
|
1513 |
|
1514 CleanupStack::PopAndDestroy(); |
|
1515 |
|
1516 return(KErrNone); |
|
1517 } |
|
1518 |
|
1519 void BaflUtils::DoCopyFileL(RFs& aFs, const TDesC& aSourceFullName, const TDesC& aTargetFullName, TUint aSwitch) |
|
1520 { |
|
1521 CFileMan* fileMan=CFileMan::NewL(aFs); |
|
1522 CleanupStack::PushL(fileMan); |
|
1523 User::LeaveIfError(fileMan->Copy(aSourceFullName,aTargetFullName,aSwitch)); |
|
1524 CleanupStack::PopAndDestroy(); // fileMan |
|
1525 } |
|
1526 |
|
1527 |
|
1528 EXPORT_C TInt BaflUtils::CopyFile(RFs& aFs, const TDesC& aSourceFullName, const TDesC& aTargetFullName, TUint aSwitch) |
|
1529 /** Copies one or more files. |
|
1530 |
|
1531 For more details, |
|
1532 @see CFileMan::Copy() |
|
1533 @since 5.1 |
|
1534 @param aFs File server session |
|
1535 @param aSourceFullName Path indicating the file(s) to be copied. Any path |
|
1536 components that are not specified here will be taken from the session path. |
|
1537 @param aTargetFullName Path indicating the directory into which the file(s) |
|
1538 are to be copied |
|
1539 @param aSwitch=CFileMan::EOverWrite Set this to zero for no overwriting and |
|
1540 no recursion; CFileMan::EOverWrite to overwrite files with the same name; or |
|
1541 CFileMan::ERecurse for recursion. |
|
1542 @return KErrNone if successful, otherwise another of the system-wide error |
|
1543 codes.*/ |
|
1544 { |
|
1545 TRAPD(err,DoCopyFileL(aFs,aSourceFullName,aTargetFullName,aSwitch)); |
|
1546 return err; |
|
1547 } |
|
1548 |
|
1549 void BaflUtils::DoDeleteFileL(RFs& aFs, const TDesC& aSourceFullName, TUint aSwitch) |
|
1550 { |
|
1551 CFileMan* fileMan=CFileMan::NewL(aFs); |
|
1552 CleanupStack::PushL(fileMan); |
|
1553 User::LeaveIfError(fileMan->Delete(aSourceFullName,aSwitch)); |
|
1554 CleanupStack::PopAndDestroy(); // fileMan |
|
1555 } |
|
1556 |
|
1557 |
|
1558 EXPORT_C TInt BaflUtils::DeleteFile(RFs& aFs, const TDesC& aSourceFullName, TUint aSwitch) |
|
1559 /** Deletes one or more files. |
|
1560 |
|
1561 For more details, |
|
1562 @see CFileMan::Delete(). |
|
1563 @since 5.1 |
|
1564 @param aFs File server session |
|
1565 @param aSourceFullName Path indicating the file(s) to be deleted. May either |
|
1566 be a full path, or relative to the session path. Use wildcards to specify |
|
1567 more than one file. |
|
1568 @param aSwitch=0 Specify CFileMan::ERecurse for recursion, |
|
1569 zero for no recursion. |
|
1570 @return KErrNone if successful, otherwise another of the system-wide error |
|
1571 codes. */ |
|
1572 { |
|
1573 TRAPD(err,DoDeleteFileL(aFs,aSourceFullName,aSwitch)); |
|
1574 return err; |
|
1575 } |
|
1576 |
|
1577 void BaflUtils::DoRenameFileL(RFs& aFs, const TDesC& aOldFullName, const TDesC& aNewFullName, TUint aSwitch) |
|
1578 { |
|
1579 CFileMan* fileMan=CFileMan::NewL(aFs); |
|
1580 CleanupStack::PushL(fileMan); |
|
1581 User::LeaveIfError(fileMan->Rename(aOldFullName,aNewFullName,aSwitch)); |
|
1582 CleanupStack::PopAndDestroy(); // fileMan |
|
1583 } |
|
1584 |
|
1585 |
|
1586 EXPORT_C TInt BaflUtils::RenameFile(RFs& aFs, const TDesC& aOldFullName, const TDesC& aNewFullName, TUint aSwitch) |
|
1587 /** Renames or moves one or more files or directories. |
|
1588 |
|
1589 It can be used to move one or more files by specifying different |
|
1590 destination and source directories. |
|
1591 For more details, |
|
1592 @see CFileMan::Rename(). |
|
1593 @since 5.1 |
|
1594 @param aFs File server session |
|
1595 @param aOldFullName Path specifying the file(s) to be renamed. |
|
1596 @param aNewFullName Path specifying the new name for the files and/or the |
|
1597 new directory. Any directories specified in this path that do not exist will |
|
1598 be created. |
|
1599 @param aSwitch=CFileMan::EOverWrite Specify zero for no overwriting, or |
|
1600 CFileMan::EOverWrite to overwrite files with the same name. This |
|
1601 function cannot operate recursively. |
|
1602 @return KErrNone if successful, otherwise another of the system-wide error |
|
1603 codes. */ |
|
1604 { |
|
1605 TRAPD(err,DoRenameFileL(aFs,aOldFullName,aNewFullName,aSwitch)); |
|
1606 return err; |
|
1607 } |
|
1608 |
|
1609 |
|
1610 EXPORT_C TInt BaflUtils::CheckWhetherFullNameRefersToFolder(const TDesC& aFullName, TBool& aIsFolder) |
|
1611 /** Checks if a string is a valid folder name. |
|
1612 |
|
1613 @param aFullName String to check |
|
1614 @param aIsFolder ETrue if aFullName is a valid folder name, otherwise EFalse |
|
1615 @return KErrNone if successful, otherwise another of the system-wide error |
|
1616 codes (probably because aFullName cannot be parsed). */ |
|
1617 { |
|
1618 aIsFolder = EFalse; |
|
1619 TInt retcode = BaflUtils::Parse(aFullName); |
|
1620 if (retcode != KErrNone) |
|
1621 return(retcode); |
|
1622 TParsePtrC parse(aFullName); |
|
1623 if (! parse.NameOrExtPresent()) |
|
1624 aIsFolder = ETrue; |
|
1625 return(KErrNone); |
|
1626 } |
|
1627 |
|
1628 EXPORT_C TInt BaflUtils::MostSignificantPartOfFullName(const TDesC& aFullName, TFileName& aMostSignificantPart) |
|
1629 /** Gets the folder name if the specified item is a valid folder name, otherwise |
|
1630 gets the file name. |
|
1631 |
|
1632 @param aFullName Item to parse |
|
1633 @param aMostSignificantPart Folder or file name |
|
1634 @return KErrNone if successful, otherwise another of the system-wide error |
|
1635 codes */ |
|
1636 { |
|
1637 TBool entryIsAFolder; |
|
1638 TInt retcode = CheckWhetherFullNameRefersToFolder(aFullName, entryIsAFolder); |
|
1639 if (retcode != KErrNone) |
|
1640 return(retcode); |
|
1641 if (entryIsAFolder) |
|
1642 { |
|
1643 aMostSignificantPart = FolderNameFromFullName(aFullName); |
|
1644 return (KErrNone); |
|
1645 } |
|
1646 // assume aFullName refers to a file |
|
1647 TParsePtrC parse(aFullName); |
|
1648 aMostSignificantPart = parse.NameAndExt(); |
|
1649 return(KErrNone); |
|
1650 } |
|
1651 |
|
1652 EXPORT_C TInt BaflUtils::CheckFolder(RFs& aFs, const TDesC& aFolderName) |
|
1653 /** Checks that the specified folder can be opened. |
|
1654 |
|
1655 @param aFs File server session |
|
1656 @param aFolderName Folder to check |
|
1657 @return KErrNone if successful, otherwise another of the system-wide error |
|
1658 codes */ |
|
1659 { |
|
1660 RDir dir; |
|
1661 TInt retcode = dir.Open(aFs, aFolderName, 0); |
|
1662 if (retcode == KErrNone) |
|
1663 dir.Close(); |
|
1664 return (retcode); |
|
1665 } |
|
1666 |
|
1667 /** |
|
1668 Checks if the specified drive is read-only. |
|
1669 Checks that the KMediaAttWriteProtected and EMediaRom flags are both set. |
|
1670 |
|
1671 @param aFs File server session |
|
1672 @param aFullName File name, including drive |
|
1673 @param aIsReadOnly On return, ETrue if the drive is read-only, otherwise EFalse |
|
1674 @return KErrNone if successful, otherwise another of the system-wide error codes |
|
1675 @see BaflUtils::DriveIsReadOnlyInternal |
|
1676 */ |
|
1677 EXPORT_C TInt BaflUtils::DiskIsReadOnly(RFs& aFs, const TDesC& aFullName, TBool& aIsReadOnly) |
|
1678 { |
|
1679 TInt retcode=BaflUtils::Parse(aFullName); |
|
1680 if (retcode!=KErrNone) |
|
1681 return retcode; |
|
1682 TParsePtrC parse(aFullName); |
|
1683 if (!parse.DrivePresent()) |
|
1684 return KErrBadName; |
|
1685 TBuf<1> drive=parse.Drive().Left(1); |
|
1686 TChar driveLetter=drive[0]; |
|
1687 TInt driveId=0; |
|
1688 retcode=RFs::CharToDrive(driveLetter,driveId); |
|
1689 if (retcode!=KErrNone) |
|
1690 return retcode; |
|
1691 TVolumeInfo volInfo; |
|
1692 retcode=aFs.Volume(volInfo,driveId); |
|
1693 if (retcode!=KErrNone) |
|
1694 return retcode; |
|
1695 aIsReadOnly=(volInfo.iDrive.iMediaAtt&KMediaAttWriteProtected || volInfo.iDrive.iType==EMediaRom); |
|
1696 return KErrNone; |
|
1697 } |
|
1698 |
|
1699 /** |
|
1700 Checks if the specified drive is read-only and is an internal drive i.e. non-removable. |
|
1701 Checks that the KMediaAttWriteProtected and KDriveAttInternal flags are both set. |
|
1702 |
|
1703 @param aFs File server session |
|
1704 @param aFullName File name, including drive |
|
1705 @param aIsReadOnlyInternal On return, ETrue if the drive is read-only and internal, otherwise EFalse |
|
1706 @return KErrNone if successful, otherwise another of the system-wide errors codes |
|
1707 */ |
|
1708 EXPORT_C TInt BaflUtils::DriveIsReadOnlyInternal(RFs& aFs, const TDesC& aFullName, TBool& aIsReadOnlyInternal) |
|
1709 { |
|
1710 TInt retcode=BaflUtils::Parse(aFullName); |
|
1711 if (retcode!=KErrNone) |
|
1712 return retcode; |
|
1713 TParsePtrC parse(aFullName); |
|
1714 if (!parse.DrivePresent()) |
|
1715 return KErrBadName; |
|
1716 TBuf<1> drive=parse.Drive().Left(1); |
|
1717 TChar driveLetter=drive[0]; |
|
1718 TInt driveId=0; |
|
1719 retcode=RFs::CharToDrive(driveLetter,driveId); |
|
1720 if (retcode!=KErrNone) |
|
1721 return retcode; |
|
1722 TVolumeInfo volInfo; |
|
1723 retcode=aFs.Volume(volInfo,driveId); |
|
1724 if (retcode!=KErrNone) |
|
1725 return retcode; |
|
1726 aIsReadOnlyInternal=((volInfo.iDrive.iMediaAtt&KMediaAttWriteProtected)&&(volInfo.iDrive.iDriveAtt&KDriveAttInternal)); |
|
1727 return KErrNone; |
|
1728 } |
|
1729 |
|
1730 EXPORT_C void BaflUtils::GetDiskListL(const RFs& aFs,CDesCArray& aArray) |
|
1731 /** Retrieves a list of all drives on the system. |
|
1732 |
|
1733 The file server is interrogated for a list of the drive letters for all available |
|
1734 drives. |
|
1735 |
|
1736 On emulator: |
|
1737 The removable media is represented by drive X: . |
|
1738 |
|
1739 On hardware: |
|
1740 The removable media is represented by drives D: E: F: and G: . |
|
1741 |
|
1742 @param aFs A connected session with the file server. |
|
1743 @param aArray On return, contains the drive letters that correspond to the |
|
1744 available drives. The drive letters are uppercase and are in alphabetical |
|
1745 order. */ |
|
1746 { // static |
|
1747 aArray.Reset(); |
|
1748 TDriveList driveList; |
|
1749 User::LeaveIfError(aFs.DriveList(driveList)); |
|
1750 for (TInt ii=0;ii<KMaxDrives;ii++) |
|
1751 { |
|
1752 if (driveList[ii]) |
|
1753 { |
|
1754 TChar drive; |
|
1755 User::LeaveIfError(aFs.DriveToChar(ii,drive)); |
|
1756 drive.UpperCase(); |
|
1757 TBuf<1> buf; |
|
1758 buf.Append(drive); |
|
1759 aArray.AppendL(buf); |
|
1760 } |
|
1761 } |
|
1762 } |
|
1763 |
|
1764 EXPORT_C void BaflUtils::UpdateDiskListL(const RFs& aFs,CDesCArray& aArray,TBool aIncludeRom,TDriveNumber aDriveNumber) |
|
1765 /** Retrieves a list of all drives present on the system. |
|
1766 |
|
1767 The file server is interrogated for a list of the drive letters for all available |
|
1768 drives. The drive letter that corresponds to aDriveNumber is added to the |
|
1769 list regardless of whether it is present, or is corrupt. Also, the C: drive |
|
1770 is forced onto the list, even if corrupt or not present. |
|
1771 |
|
1772 On emulator: |
|
1773 The removable media is represented by drive X: and is forced onto the list |
|
1774 unless removed (F5,F4). |
|
1775 |
|
1776 On hardware: |
|
1777 The removable media is represented by drives D: E: F: and G: and is forced |
|
1778 onto the list regardless of whether it is present, or is corrupt. |
|
1779 |
|
1780 @param aFs A connected session with the file server. |
|
1781 @param aArray On return, contains the drive letters that correspond to the |
|
1782 available drives. The drive letters are uppercase and are in alphabetical |
|
1783 order. |
|
1784 @param aIncludeRom Specify ETrue if the ROM drive should be included in the |
|
1785 list, EFalse if not. |
|
1786 @param aDriveNumber The drive to force into the list, e.g. the drive in the |
|
1787 default path. */ |
|
1788 { // static |
|
1789 aArray.Reset(); |
|
1790 TDriveList driveList; |
|
1791 User::LeaveIfError(aFs.DriveList(driveList)); |
|
1792 for (TInt ii=0;ii<KMaxDrives;ii++) |
|
1793 { |
|
1794 if (driveList[ii] || ii==aDriveNumber) |
|
1795 { |
|
1796 TVolumeInfo vInfo; |
|
1797 const TInt err=aFs.Volume(vInfo,TDriveUnit(ii)); |
|
1798 if (err==KErrNone || err==KErrCorrupt || ii==aDriveNumber || BaflUtils::IsFirstDriveForSocket(TDriveUnit(ii))) |
|
1799 { |
|
1800 if (ii==EDriveZ && vInfo.iDrive.iDriveAtt&KDriveAttRom && !aIncludeRom) |
|
1801 continue; |
|
1802 TChar drive; |
|
1803 User::LeaveIfError(aFs.DriveToChar(ii,drive)); |
|
1804 drive.UpperCase(); |
|
1805 TBuf<1> buf; |
|
1806 buf.Append(drive); |
|
1807 aArray.AppendL(buf); |
|
1808 } |
|
1809 } |
|
1810 } |
|
1811 } |
|
1812 |
|
1813 EXPORT_C TBool BaflUtils::IsFirstDriveForSocket(TDriveUnit aDriveUnit) |
|
1814 /** Tests whether the specified drive corresponds to the primary partition in a |
|
1815 removable media slot. |
|
1816 |
|
1817 The function assumes that the D: drive corresponds to the primary partition |
|
1818 on socket 0, and that the E: drive corresponds to the primary partition on |
|
1819 socket 1 (a socket is a slot for removable media). This mapping may not always |
|
1820 be the case because it is set up in the variant layer of the Symbian OS. |
|
1821 |
|
1822 This function assumes that the drive mappings are contiguous, starting |
|
1823 from drive D: . |
|
1824 |
|
1825 On emulator: |
|
1826 The removable media is represented by drive X: only. |
|
1827 |
|
1828 @param aDriveUnit The drive to check. |
|
1829 @return ETrue if the drive is the primary partition in a removable media slot. |
|
1830 ETrue is also returned if the drive is A, B or C:. EFalse is returned otherwise. */ |
|
1831 { // static |
|
1832 TDriveInfoV1Buf buf; |
|
1833 UserHal::DriveInfo(buf); |
|
1834 |
|
1835 #ifdef __EPOC32__ |
|
1836 return ((aDriveUnit-EDriveC)<=buf().iTotalSockets); |
|
1837 #else // emulator |
|
1838 return (aDriveUnit==EDriveX || (aDriveUnit-EDriveC)<=buf().iTotalSockets); |
|
1839 #endif |
|
1840 } |
|
1841 |
|
1842 EXPORT_C void BaflUtils::RemoveSystemDirectory(CDir& aDir) |
|
1843 /** Removes "System" from a list of directory entries. |
|
1844 |
|
1845 @param aDir Array of directory entries. */ |
|
1846 { // static |
|
1847 STATIC_CAST(BaflDir&,aDir).RemoveSystem(); |
|
1848 } |
|
1849 |
|
1850 EXPORT_C TInt BaflUtils::SortByTable(CDir& aDir,CBaflFileSortTable* aTable) |
|
1851 /** Sorts files by UID. |
|
1852 |
|
1853 The caller supplies a table which specifies the order in which files are to |
|
1854 be sorted. The files whose UID3 is the first UID in the table appear first. |
|
1855 The files whose UID3 is the UID specified second appear next, and so on. Files |
|
1856 whose UID3 is not specified in the table, and directories, appear at the end |
|
1857 of the list, with directories preceding the files, and with files sorted in |
|
1858 ascending order of UID3. |
|
1859 |
|
1860 This function is used for customising how lists of application files are sorted. |
|
1861 |
|
1862 @param aDir The array of files and directories to sort. |
|
1863 @param aTable A sort order table containing the UIDs to use in the sort. |
|
1864 @return KErrNone if successful, otherwise one of the standard error codes. */ |
|
1865 { // static |
|
1866 return STATIC_CAST(BaflDir&,aDir).SortByTable(aTable); |
|
1867 } |
|
1868 |
|
1869 EXPORT_C void BaflUtils::GetDowngradePathL(const RFs& aFs, const TLanguage aCurrentLanguage, RArray<TLanguage>& aLanguageArray) |
|
1870 /** Gets the full language downgrade path for a particular locale. |
|
1871 |
|
1872 @param aFs A connected session with the file server. |
|
1873 @param aCurrentLanguage The language of the locale for which the language downgrade |
|
1874 path is required. This language will always be returned as the first language |
|
1875 in aLanguageArray. To get the downgrade path for the language of the current |
|
1876 locale, specify the language returned by User::Language(). |
|
1877 @param aLanguageArray On return, contains the language downgrade path. |
|
1878 @see BaflUtils::NearestLanguageFile() */ |
|
1879 { |
|
1880 TLocale currentLocale; |
|
1881 TNearestLanguageFileFinder languageDowngradePath(aFs); |
|
1882 TLanguage idealLanguage=IdealLanguage(); |
|
1883 MakeLanguageDowngradePath(languageDowngradePath.iPath,aCurrentLanguage,idealLanguage, currentLocale); |
|
1884 aLanguageArray.Reset(); |
|
1885 const TLanguage* p=languageDowngradePath.iPath; |
|
1886 while (*p != ELangNone) |
|
1887 { |
|
1888 User::LeaveIfError(aLanguageArray.Append(*p)); |
|
1889 ++p; |
|
1890 } |
|
1891 } |
|
1892 |
|
1893 EXPORT_C void BaflUtils::PersistLocale() |
|
1894 /** Saves the locale settings in TLocale and the currency symbol to file. |
|
1895 @deprecated 9.1 |
|
1896 Persistence and initialisation of system locale data will be performed |
|
1897 transparently by a separate executable (InilialiseLocale.exe) wich should |
|
1898 be loaded as part of the system start procedure. |
|
1899 */ |
|
1900 { |
|
1901 // Replaced by new repository based locale initialisation mechanism. |
|
1902 } |
|
1903 |
|
1904 |
|
1905 |
|
1906 EXPORT_C TInt BaflUtils::PersistHAL() |
|
1907 /** Saves the HAL settings to file. |
|
1908 This will start a new executable and saves HAL attributes to a file, |
|
1909 little delay because of the creation of new process |
|
1910 @return KErrNone if suceessful, otheriwse system wide error code. |
|
1911 */ |
|
1912 { |
|
1913 RProcess process; |
|
1914 _LIT(KHALSettings, "HALSettings.exe"); |
|
1915 _LIT(KCommandLine, "PERSIST"); |
|
1916 TInt result = process.Create(KHALSettings, KCommandLine); |
|
1917 if(result != KErrNone ) |
|
1918 return result; |
|
1919 TRequestStatus status; |
|
1920 process.Logon(status); |
|
1921 if ( status != KRequestPending) |
|
1922 { |
|
1923 process.Kill(0); // abort |
|
1924 } |
|
1925 else |
|
1926 { |
|
1927 process.Resume(); // logon OK |
|
1928 } |
|
1929 User::WaitForRequest(status); |
|
1930 |
|
1931 // we can't use the 'exit reason' if the exe panicked as this |
|
1932 // is the panic 'reason' and may be '0' which cannot be distinguished |
|
1933 // from KErrNone |
|
1934 result = process.ExitType() == EExitPanic ? KErrGeneral : status.Int(); |
|
1935 process.Close(); |
|
1936 return result; |
|
1937 } |
|
1938 |
|
1939 EXPORT_C void BaflUtils::PersistScreenCalibration(const TDigitizerCalibration& aScreenCalibration) |
|
1940 { |
|
1941 |
|
1942 RFs fs; |
|
1943 TInt err = fs.Connect(); |
|
1944 if (err == KErrNone) |
|
1945 { |
|
1946 // Setting up drive to store Screen data |
|
1947 TDriveUnit systemDrive(static_cast<TInt>(RFs::GetSystemDrive())); |
|
1948 TBuf<KMaxDriveName+KScreenCalibrationPathLength> ScreenFileNameWithDriveAndPath(systemDrive.Name()); |
|
1949 ScreenFileNameWithDriveAndPath.Append(KScreenCalibrationFolder); |
|
1950 |
|
1951 // Ensure directory \System\Data exists in target drive |
|
1952 TRAP(err, EnsurePathExistsL(fs, ScreenFileNameWithDriveAndPath)); |
|
1953 if(err == KErrNone) |
|
1954 { |
|
1955 ScreenFileNameWithDriveAndPath.Append(KScreenCalibrationFileName); |
|
1956 |
|
1957 RFile file; |
|
1958 err = file.Replace(fs,ScreenFileNameWithDriveAndPath,EFileWrite|EFileShareExclusive); |
|
1959 if (err == KErrNone) |
|
1960 { |
|
1961 // Write aScreenCalibration to file. |
|
1962 TPtrC8 calptr((const TUint8*)&aScreenCalibration, sizeof(TDigitizerCalibration)); |
|
1963 err = file.Write(calptr); |
|
1964 } |
|
1965 file.Close(); |
|
1966 } |
|
1967 } |
|
1968 fs.Close(); |
|
1969 } |
|
1970 |
|
1971 EXPORT_C void BaflUtils::InitialiseScreenCalibration(RFs& aFs) |
|
1972 { |
|
1973 TFindFile ff(aFs); |
|
1974 if (ff.FindByDir(KScreenCalibrationFileName, KScreenCalibrationFolder)==KErrNone) |
|
1975 { |
|
1976 RFile file; |
|
1977 if (file.Open(aFs,ff.File(),EFileRead) == KErrNone ) |
|
1978 { |
|
1979 TDigitizerCalibration calibrationSetting; |
|
1980 TPtr8 scrcal((TUint8*)&calibrationSetting, sizeof(TDigitizerCalibration)); |
|
1981 if( file.Read(scrcal, sizeof( TDigitizerCalibration )) == KErrNone ) |
|
1982 UserHal::SetXYInputCalibration(calibrationSetting); |
|
1983 |
|
1984 } |
|
1985 file.Close(); |
|
1986 } |
|
1987 } |
|
1988 |
|
1989 EXPORT_C void BaflUtils::InitialiseHAL(RFs&) |
|
1990 /** Initialise the HAL settings from. |
|
1991 @deprecated 9.1 |
|
1992 This function is empty |
|
1993 */ |
|
1994 { |
|
1995 } |
|
1996 |
|
1997 EXPORT_C void BaflUtils::InitialiseLocale(RFs& /* aFs */) |
|
1998 { |
|
1999 // Replaced by new repository based locale initialisation mechanism. |
|
2000 } |
|
2001 |
|
2002 |
|
2003 // |
|
2004 // class CEikFileSortTable |
|
2005 // |
|
2006 |
|
2007 /** |
|
2008 */ |
|
2009 EXPORT_C CBaflFileSortTable::CBaflFileSortTable() |
|
2010 : CArrayFixFlat<TUid>(EArrayGranularity) |
|
2011 {} |
|
2012 |
|
2013 /** |
|
2014 * Loads the CBaflFileSortTable using the UIDs read from the TResourceReader supplied in aReader. |
|
2015 * @param aReader TResourceReader from which UIDS are read. |
|
2016 * @leave KErrNoMemory if there is insufficient memory available or one of the system wide error codes. |
|
2017 */ |
|
2018 EXPORT_C void CBaflFileSortTable::ConstructFromResourceL(TResourceReader& aReader) |
|
2019 { |
|
2020 const TInt count=aReader.ReadInt16(); |
|
2021 for (TInt i=0;i<count;i++) |
|
2022 AppendL(TUid::Uid(aReader.ReadInt32())); |
|
2023 } |
|
2024 |
|
2025 // |
|
2026 // class BaflDir |
|
2027 // |
|
2028 |
|
2029 #define KSystemDirName _L("System") // Name for System directory |
|
2030 |
|
2031 |
|
2032 void BaflDir::RemoveSystem() |
|
2033 /* Remove "System" if in list and it's a directory. */ |
|
2034 { |
|
2035 TInt index; |
|
2036 TEntry entry; |
|
2037 entry.iName=KSystemDirName; |
|
2038 TKeyArrayPak key(_FOFF(TEntry,iName),ECmpFolded); |
|
2039 if (iArray->Find(entry,key,index)==KErrNone) |
|
2040 { |
|
2041 entry=(*iArray)[index]; |
|
2042 if (entry.IsDir()) |
|
2043 iArray->Delete(index); |
|
2044 } |
|
2045 }; |
|
2046 |
|
2047 /* |
|
2048 This function gets the element at position "aPos" of aEntries array and inserts |
|
2049 it to poition "aNewPos". The element size is "aSize". After the operation the array size |
|
2050 grows by 1, the element at "aPos" position moves one position forward. |
|
2051 This function must be called only from BaflDir::SortByTable() and the insert position |
|
2052 is always less or equal than the position of the element to be inserted. |
|
2053 */ |
|
2054 static void InsertL(CArrayPakFlat<TEntry>* aEntries, TInt aPos, TInt aNewPos, TInt aSize) |
|
2055 { |
|
2056 __ASSERT_DEBUG(aPos >= aNewPos, User::Invariant()); |
|
2057 //Expand the array adding one empty entry at "aNewPos" position. |
|
2058 aEntries->ExpandL(aNewPos, aSize); |
|
2059 //After successfull "ExpandL" call "aPos" must be incremented by 1. |
|
2060 //Copy the entry from "aPos + 1" position to "aNewPos" position |
|
2061 (*aEntries)[aNewPos] = (*aEntries)[++aPos]; |
|
2062 } |
|
2063 |
|
2064 /** |
|
2065 Copied from f32file.inl (now moved to f32file_private.h) |
|
2066 Returns the minimum uncompressed size of the TEntry object, including the valid |
|
2067 portion of the name string. The returned value is aligned to 4-byte boundary and |
|
2068 length includes private members. |
|
2069 |
|
2070 @internalTechnology |
|
2071 @return minimum uncompressed size of TEntry object |
|
2072 */ |
|
2073 |
|
2074 TInt BaflDir::MinEntrySize(const TEntry & aEntry) |
|
2075 { |
|
2076 return(sizeof(TUint)+sizeof(TInt)+sizeof(TTime)+sizeof(TInt)+sizeof(TUidType)+ |
|
2077 Align4(aEntry.iName.Size()) + 2*sizeof(TInt)); |
|
2078 } |
|
2079 |
|
2080 TInt BaflDir::SortByTable(CBaflFileSortTable* aTable) |
|
2081 /** |
|
2082 Sort into order from given table. |
|
2083 Any file with uid[2] matching an entry in the table will be sorted relative to |
|
2084 others in the table and before any files with no matching uid. |
|
2085 For Example: Assume UID table is filled with below 2 UID's |
|
2086 table[0] =0x10003a64 and table[1] =0x10003a5c. Then file with UID[2]=0x10003a64 |
|
2087 will be sorted first in the list followed by file with UID[2]=0x10003a5c. Rest |
|
2088 files will be sorted in the ascending order of UID[2] with directories preceding |
|
2089 the files. |
|
2090 |
|
2091 @param aTable A sort order table containing the UIDs to use in the sort. |
|
2092 @return KErrNone if suceessful, otheriwse another system-wide error code. |
|
2093 */ |
|
2094 { |
|
2095 TInt r=this->Sort(EDirsFirst|ESortByUid); |
|
2096 if(r != KErrNone) |
|
2097 { |
|
2098 return r; |
|
2099 } |
|
2100 const TInt tableCount=aTable->Count(); |
|
2101 const TInt count=iArray->Count(); |
|
2102 TInt sortedInsertionPoint = 0; |
|
2103 for (TInt i=0;i<tableCount;i++) |
|
2104 { |
|
2105 TUid tableUid; |
|
2106 // get each UID in the table |
|
2107 tableUid = aTable->At(i); |
|
2108 for (TInt j=sortedInsertionPoint;j<count;j++) |
|
2109 { |
|
2110 //parse files in the array list |
|
2111 TEntry* pEntry=&(*iArray)[j]; |
|
2112 // check table UID for match with UID[2] of the file in the list |
|
2113 // if found, move the file at the top in the list, followed by next matching UID |
|
2114 if (tableUid == pEntry->iType[2]) |
|
2115 { |
|
2116 TRAPD(insertErr, ::InsertL(iArray, j, sortedInsertionPoint++, MinEntrySize(*pEntry))); |
|
2117 if(insertErr!=KErrNone) |
|
2118 { |
|
2119 return insertErr; |
|
2120 } |
|
2121 iArray->Delete(j+1); |
|
2122 } |
|
2123 } |
|
2124 } |
|
2125 iArray->Compress(); |
|
2126 return KErrNone; |
|
2127 } |