|
1 // Copyright (c) 2002-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 // |
|
15 |
|
16 |
|
17 |
|
18 // INCLUDE FILES |
|
19 #include <e32svr.h> |
|
20 #include <tuladdressstringtokenizer.h> |
|
21 #include <tulpanics.h> |
|
22 #include "languagespecificnumberconverter.h" |
|
23 |
|
24 // DEFINE |
|
25 |
|
26 const TInt KFindItemMaxNumbers = 20; |
|
27 const TInt KFindItemMinNumbers = 3; |
|
28 const TInt KDotsInIpAddress = 3; |
|
29 const TInt KNumbersInIpAddress = 3; |
|
30 |
|
31 const TInt KCharLinefeed = 0x000A; |
|
32 const TInt KCharFormfeed = 0x000C; |
|
33 const TInt KCharCarriageReturn = 0x000D; |
|
34 const TInt KCharLineSeparator = 0x2028; |
|
35 const TInt KCharParagraphSeparator = 0x2029; |
|
36 |
|
37 // Valid characters for different search cases |
|
38 _LIT( KPhoneNumberChars, "1234567890*#-./"); |
|
39 _LIT( KEmailChars, "!#$?%&*+-/"); |
|
40 _LIT( KEmailHostChars, "abcdefghijklmnopqrstuvwxyz1234567890._-"); |
|
41 _LIT( KUrlChars, "%/-~?=:&,#+|"); |
|
42 |
|
43 // generic URI scheme checking |
|
44 _LIT( KURISchemeStartCharacters, "abcdefghijklmnopqrstuvwxyz" ); |
|
45 _LIT( KURISchemeBodyCharacters, "abcdefghijklmnopqrstuvwxyz1234567890+-."); |
|
46 _LIT( KURISchemeTerminator, ":"); |
|
47 _LIT( KURICharacters, "abcdefghijklmnopqrstuvwxyz1234567890?/;:@&=+$,%-_.!~*'()#|"); |
|
48 |
|
49 // Url Address beginnings (to support deprecated search cases) |
|
50 _LIT( KHttpUrlAddress, "http://"); |
|
51 _LIT( KRtspUrlAddress, "rtsp://"); |
|
52 _LIT( KHttpsUrlAddress, "https://"); |
|
53 |
|
54 // Non-schematic URL address beginnings |
|
55 _LIT( KWwwUrlAddress, "www."); |
|
56 _LIT( KWapUrlAddress, "wap."); |
|
57 |
|
58 // IP address pattern to match |
|
59 _LIT( KIPAddress, "*.*.*.*"); |
|
60 |
|
61 // Panic |
|
62 _LIT( KFindItemPanic, "ETUL-Panic"); |
|
63 |
|
64 GLDEF_C void Panic(TTulPanic aPanic) |
|
65 { |
|
66 User::Panic(KFindItemPanic, aPanic); |
|
67 } |
|
68 |
|
69 |
|
70 // ================= MEMBER FUNCTIONS ======================= |
|
71 |
|
72 /** |
|
73 C++ default constructor. |
|
74 */ |
|
75 CTulAddressStringTokenizer::CTulAddressStringTokenizer() |
|
76 { |
|
77 // C++ default constructor must NOT contain any code, that might leave. |
|
78 } |
|
79 |
|
80 /** |
|
81 Symbian OS constructor |
|
82 @param aText Text that will be parsed |
|
83 @param aSearchCases Identifies what items are we looking for: |
|
84 EFindItemSearchPhoneNumberBin |
|
85 EFindItemSearchMailAddressBin |
|
86 EFindItemSearchURLBin |
|
87 EFindItemSearchScheme |
|
88 Any combination of these flags can be given |
|
89 as a bit mask. |
|
90 @param aMinNumbers Minimum count of numbers in a string when |
|
91 the string is considered as a phone number. |
|
92 */ |
|
93 void CTulAddressStringTokenizer::ConstructL(const TDesC& aText, TInt aSearchCases, TInt aMinNumbers) |
|
94 { |
|
95 iMinNumbers = aMinNumbers; |
|
96 HBufC* buf = NULL; |
|
97 TLanguage language = User::Language(); |
|
98 |
|
99 if (language == ELangArabic || language == ELangHebrew || language == ELangUrdu || |
|
100 language == ELangFarsi || language == ELangHindi) |
|
101 { |
|
102 buf = aText.AllocLC(); |
|
103 TPtr ptr = buf->Des(); |
|
104 LanguageSpecificNumberConverter::ConvertToWesternNumbers( ptr ); |
|
105 PerformSearchL( *buf, aSearchCases ); |
|
106 } |
|
107 else |
|
108 PerformSearchL( aText, aSearchCases ); |
|
109 |
|
110 if(buf) |
|
111 CleanupStack::PopAndDestroy(buf); |
|
112 } |
|
113 |
|
114 /** |
|
115 Performs the search. Uses search algorithms SearchGenericUriL(), SearchMailAddressL(), |
|
116 SearchUrlL() and SearchPhoneNumberL(). |
|
117 */ |
|
118 void CTulAddressStringTokenizer::PerformSearchL(const TDesC& aText , TInt aSearchCases) |
|
119 { |
|
120 ASSERT(!iFoundItems); |
|
121 iFoundItems = new (ELeave) CArrayFixFlat<SFoundItem>(2); |
|
122 |
|
123 TBool somethingSearched = EFalse; |
|
124 |
|
125 // first detect binary mask cases |
|
126 if ( (aSearchCases & EFindItemSearchScheme) == EFindItemSearchScheme) |
|
127 { |
|
128 SearchGenericUriL( aText ); |
|
129 somethingSearched = ETrue; |
|
130 } |
|
131 |
|
132 // Prioritize mail address found before URL search. Address name@123.123.123.123 |
|
133 // would otherwise be detected as IP number. |
|
134 if ( (aSearchCases & EFindItemSearchMailAddressBin) == EFindItemSearchMailAddressBin) |
|
135 { |
|
136 SearchMailAddressL( aText ); |
|
137 somethingSearched = ETrue; |
|
138 } |
|
139 |
|
140 if ( (aSearchCases & EFindItemSearchURLBin) == EFindItemSearchURLBin) |
|
141 { |
|
142 SearchUrlL( aText, ETrue ); |
|
143 somethingSearched = ETrue; |
|
144 } |
|
145 |
|
146 // Search phone numbers last as all others can contain number sequences |
|
147 if ( (aSearchCases & EFindItemSearchPhoneNumberBin) == EFindItemSearchPhoneNumberBin) |
|
148 { |
|
149 SearchPhoneNumberL( aText ); |
|
150 somethingSearched = ETrue; |
|
151 } |
|
152 |
|
153 // if no binary cases found |
|
154 if ( !somethingSearched ) |
|
155 { |
|
156 __ASSERT_DEBUG( 1, Panic(ETulPanicInvalidTokenizerSearchCase) ); |
|
157 } |
|
158 } |
|
159 |
|
160 /** |
|
161 Two-phase constructor method that is used to create a new instance |
|
162 of the CTulAddressStringTokenizer class. This instance can then be queried for |
|
163 the items defined by the second parameter. The actual search is |
|
164 executed during construction. |
|
165 |
|
166 @param aText will be parsed. |
|
167 @param aSearchCases identifies what items we are looking for: |
|
168 EFindItemSearchPhoneNumberBin |
|
169 EFindItemSearchMailAddressBin |
|
170 EFindItemSearchURLBin |
|
171 EFindItemSearchScheme |
|
172 Any combination of these flags can be given as a bit mask. |
|
173 @return a pointer to a new instance of CTulAddressStringTokenizer class. |
|
174 |
|
175 @panic ETulPanicInvalidTokenizerSearchCase in debug build if there is no valid search case. |
|
176 @panic ETulPanicDescriptorLength in debug build if item's position |
|
177 and/or length is out of the document's range. |
|
178 @leave KErrNone, if successful; otherwise one of the other system-wide error codes. |
|
179 */ |
|
180 EXPORT_C CTulAddressStringTokenizer* CTulAddressStringTokenizer::NewL(const TDesC& aText, TInt aSearchCases) |
|
181 { |
|
182 CTulAddressStringTokenizer* self = new (ELeave) CTulAddressStringTokenizer; |
|
183 CleanupStack::PushL(self); |
|
184 self->ConstructL(aText, aSearchCases, KFindItemMinNumbers); |
|
185 CleanupStack::Pop(); |
|
186 return self; |
|
187 } |
|
188 |
|
189 /** |
|
190 Two-phase constructor method that is used to create a new instance |
|
191 of the CTulAddressStringTokenizer class. This instance can then be queried for |
|
192 the items defined by the second parameter. The actual search is |
|
193 executed during construction. |
|
194 |
|
195 @param aText will be parsed. |
|
196 @param aSearchCases identifies what items we are looking for: |
|
197 EFindItemSearchPhoneNumberBin |
|
198 EFindItemSearchMailAddressBin |
|
199 EFindItemSearchURLBin |
|
200 EFindItemSearchScheme |
|
201 Any combination of these flags can be given as a bit mask. |
|
202 @param aMinNumbers defines a minimum count of numbers in a phone |
|
203 number string, during a phone number |
|
204 search. |
|
205 @return a pointer to an new instance of CTulAddressStringTokenizer class. |
|
206 |
|
207 @panic ETulPanicInvalidTokenizerSearchCase in debug build if there is no valid search case. |
|
208 @panic ETulPanicDescriptorLength in debug build if item's position |
|
209 and/or length is out of the document's range. |
|
210 @leave KErrNone, if successful; otherwise one of the other system-wide error codes. |
|
211 */ |
|
212 EXPORT_C CTulAddressStringTokenizer* CTulAddressStringTokenizer::NewL(const TDesC& aText, TInt aSearchCases, |
|
213 TInt aMinNumbers ) |
|
214 { |
|
215 CTulAddressStringTokenizer* self = new (ELeave) CTulAddressStringTokenizer; |
|
216 CleanupStack::PushL( self ); |
|
217 self->ConstructL( aText, aSearchCases, aMinNumbers ); |
|
218 CleanupStack::Pop( ); |
|
219 return self; |
|
220 } |
|
221 |
|
222 |
|
223 /** |
|
224 Destructor. |
|
225 */ |
|
226 EXPORT_C CTulAddressStringTokenizer::~CTulAddressStringTokenizer() |
|
227 { |
|
228 delete iFoundItems; |
|
229 } |
|
230 |
|
231 // API methods for using engine separately from FindItemUI |
|
232 |
|
233 /** |
|
234 Executes a new search with the already created CTulAddressStringTokenizer |
|
235 instance. The position in the found items array is reset to the |
|
236 beginning of the array. |
|
237 |
|
238 @param aText will be parsed. |
|
239 @param aSearchCases identifies what items are we looking for: |
|
240 EFindItemSearchPhoneNumberBin |
|
241 EFindItemSearchMailAddressBin |
|
242 EFindItemSearchURLBin |
|
243 EFindItemSearchScheme |
|
244 Any combination of these flags can be given as a bit mask. |
|
245 @return number of found items. |
|
246 |
|
247 @panic ETulPanicInvalidTokenizerSearchCase in debug build if there is no valid search case. |
|
248 @panic ETulPanicDescriptorLength in debug build if item's position |
|
249 and/or length is out of the document's range. |
|
250 @leave one of the Symbian error codes. |
|
251 */ |
|
252 EXPORT_C TInt CTulAddressStringTokenizer::DoNewSearchL(const TDesC& aText, TInt aSearchCases) |
|
253 { |
|
254 return DoNewSearchL( aText, aSearchCases, KFindItemMinNumbers ); |
|
255 } |
|
256 |
|
257 // API methods for using engine separately from FindItemUI |
|
258 |
|
259 /** |
|
260 Executes a new search with the already created CTulAddressStringTokenizer |
|
261 instance. The position in the found items array is reset to the |
|
262 beginning of the array. |
|
263 |
|
264 @param aText will be parsed. |
|
265 @param aSearchCases identifies what items are we looking for: |
|
266 EFindItemSearchPhoneNumberBin |
|
267 EFindItemSearchMailAddressBin |
|
268 EFindItemSearchURLBin |
|
269 EFindItemSearchScheme |
|
270 Any combination of these flags can be given as a bit mask. |
|
271 @param aMinNumbers defines a minimum count of numbers in a phone |
|
272 number string, during a phone number |
|
273 search. |
|
274 @return number of found items. |
|
275 |
|
276 @panic ETulPanicInvalidTokenizerSearchCase in debug build if there is no valid search case. |
|
277 @panic ETulPanicDescriptorLength in debug build if item's position |
|
278 and/or length is out of the document's range. |
|
279 @leave KErrNone, if successful; otherwise one of the other system-wide error codes. |
|
280 */ |
|
281 EXPORT_C TInt CTulAddressStringTokenizer::DoNewSearchL(const TDesC& aText, TInt aSearchCases, TInt aMinNumbers) |
|
282 { |
|
283 delete iFoundItems; |
|
284 iFoundItems = NULL; |
|
285 iPosition = 0; |
|
286 ConstructL(aText, aSearchCases, aMinNumbers); |
|
287 return ItemCount(); |
|
288 } |
|
289 |
|
290 // --------------------------------------------------------- |
|
291 // Search Algorithms and helpers |
|
292 // --------------------------------------------------------- |
|
293 /** |
|
294 Character information methods |
|
295 |
|
296 @param charac a Character to be investigated |
|
297 @return ETrue if the parameter for phone number was valid, else returns EFalse |
|
298 */ |
|
299 TBool CTulAddressStringTokenizer::IsValidPhoneNumberChar(const TChar& aCharac) |
|
300 { |
|
301 // Returns ETrue if the parameter is a valid character in a phonenumber |
|
302 const TDesC& array = KPhoneNumberChars; |
|
303 return (array.Locate(aCharac) != KErrNotFound); |
|
304 } |
|
305 |
|
306 /** |
|
307 Character information methods |
|
308 |
|
309 @param charac a Character to be investigated |
|
310 @return ETrue if the parameter for login part of the e-mail address is valid, else returns EFalse |
|
311 */ |
|
312 TBool CTulAddressStringTokenizer::IsValidEmailChar(const TChar& aCharac) |
|
313 { |
|
314 // Returns ETrue if the parameter is a valid character for username part of e-mail address |
|
315 // ASCII 33 - 47 (without '"', ',', ''', '(' and ')' because they can be used to separate address |
|
316 // from rest of the text ) |
|
317 const TDesC& array = KEmailChars; |
|
318 return (array.Locate(aCharac) != KErrNotFound || IsValidEmailHostChar(aCharac)); |
|
319 } |
|
320 |
|
321 /** |
|
322 Character information methods |
|
323 |
|
324 @param charac a Character to be investigated |
|
325 @return ETrue if the parameter for host part of the e-mail address is valid, else returns EFalse |
|
326 */ |
|
327 TBool CTulAddressStringTokenizer::IsValidEmailHostChar(const TChar& aCharac) |
|
328 { |
|
329 // Returns ETrue if the parameter is a valid character for a host part of e-mail address |
|
330 const TDesC& array = KEmailHostChars; |
|
331 return (array.Locate( aCharac.GetLowerCase() ) != KErrNotFound); |
|
332 } |
|
333 |
|
334 /** |
|
335 Character information methods |
|
336 |
|
337 @param charac a Character to be investigated |
|
338 @return ETrue if the parameter for URL is valid, else returns EFalse |
|
339 */ |
|
340 TBool CTulAddressStringTokenizer::IsValidUrlChar(const TChar& aCharac) |
|
341 { |
|
342 // Returns ETrue if the parameter is a valid character for url |
|
343 if (IsValidEmailHostChar(aCharac)) |
|
344 return ETrue; |
|
345 |
|
346 const TDesC& array = KUrlChars; |
|
347 return (array.Locate(aCharac) != KErrNotFound); |
|
348 } |
|
349 |
|
350 /** |
|
351 Search algorithm for searching e-mail addresses |
|
352 |
|
353 @param aText Text that will be parsed |
|
354 @return ETrue if any EMail items were found else returns EFalse |
|
355 @leave KErrNone, if successful; otherwise one of the other system-wide error codes. |
|
356 @panic ETulPanicDescriptorLength in debug build if item's position |
|
357 and/or length is out of the document's range. |
|
358 */ |
|
359 TBool CTulAddressStringTokenizer::SearchMailAddressL( const TDesC& aText ) |
|
360 { |
|
361 TInt searchStart = 0; |
|
362 TInt searchResult = 0; |
|
363 const TInt end = aText.Length(); // end of document |
|
364 |
|
365 do |
|
366 { |
|
367 TPtrC segment = aText.Right( end - searchStart ); |
|
368 searchResult = segment.LocateF('@'); |
|
369 |
|
370 if (searchResult != KErrNotFound) |
|
371 { // @ found |
|
372 // There should be valid characters (not a period) before and after the @ character |
|
373 if ( searchResult == 0 // first char |
|
374 || (searchResult >= segment.Length() - 1) // last char |
|
375 || !(IsValidEmailChar(segment[searchResult - 1])) |
|
376 || !(IsValidEmailHostChar(segment[searchResult + 1])) |
|
377 || segment[searchResult - 1] == '.' |
|
378 || segment[searchResult + 1] == '.' |
|
379 ) |
|
380 { |
|
381 searchStart += searchResult + 1; |
|
382 continue; |
|
383 } |
|
384 |
|
385 TBool wasPeriod = EFalse; // To prevent sequential periods |
|
386 // Get TLex from the pointer to get a better API for parsing |
|
387 TLexMark startPos; |
|
388 TLexMark endPos; |
|
389 TLex token = segment; |
|
390 |
|
391 // Go to searchResult and un-get until the beginning of e-mail address is reached |
|
392 token.Inc( searchResult ); |
|
393 token.Mark(); |
|
394 do |
|
395 { |
|
396 token.UnGet(); |
|
397 if ( token.Peek() == '.' ) |
|
398 { // If it was a period |
|
399 if (wasPeriod) // and if the former was also -> break |
|
400 break; |
|
401 else // else mark that this one was a period |
|
402 wasPeriod = ETrue; |
|
403 } |
|
404 else |
|
405 wasPeriod = EFalse; |
|
406 } |
|
407 while (token.Offset() > 0 && IsValidEmailChar(token.Peek())); |
|
408 |
|
409 if (token.Offset() != 0 || !IsValidEmailChar(token.Peek())) |
|
410 token.Inc(); |
|
411 |
|
412 // Get rid of periods from the start of address |
|
413 // Does it have to start with a number or char(abc...). |
|
414 // If it does, the loop should check that it gets rid of all special chars also. |
|
415 while (token.Peek() == '.') |
|
416 token.Inc(); |
|
417 |
|
418 token.Mark( startPos ); // Mark the beginning of address |
|
419 token.UnGetToMark(); |
|
420 wasPeriod = EFalse; |
|
421 |
|
422 do // Go forward until a nonvalid character |
|
423 { |
|
424 token.Inc(); |
|
425 if ( token.Peek() == '.' ) |
|
426 { // If it was a period |
|
427 if ( wasPeriod ) // and if the former was also -> break |
|
428 break; |
|
429 else // else mark that this one was a period |
|
430 wasPeriod = ETrue; |
|
431 } |
|
432 else |
|
433 wasPeriod = EFalse; |
|
434 } |
|
435 while ( !token.Eos() && IsValidEmailHostChar( token.Peek() ) ); |
|
436 |
|
437 // If address ends with a period take it away |
|
438 token.UnGet(); |
|
439 if (token.Peek() != '.') |
|
440 token.Inc(); |
|
441 |
|
442 token.Mark( endPos ); // Mark the beginning of address |
|
443 |
|
444 // Append the found string to the array |
|
445 __ASSERT_DEBUG( searchStart + token.MarkedOffset( startPos ) |
|
446 + token.MarkedOffset( endPos ) |
|
447 - token.MarkedOffset( startPos ) <= aText.Length(), |
|
448 Panic(ETulPanicDescriptorLength) ); |
|
449 AddItemL( searchStart + token.MarkedOffset( startPos ), |
|
450 token.MarkedOffset( endPos ) - token.MarkedOffset( startPos ), |
|
451 EFindItemSearchMailAddressBin); |
|
452 searchStart += token.MarkedOffset( endPos ) + 1; |
|
453 } |
|
454 } |
|
455 while ( searchResult != KErrNotFound && searchStart < end ); |
|
456 |
|
457 return (iFoundItems->Count() > 0); |
|
458 } |
|
459 |
|
460 /** |
|
461 Search algorithm for searching phone numbers |
|
462 |
|
463 @param aText Text that will be parsed |
|
464 @return ETrue if any Phone Number items were found else returns EFalse |
|
465 @leave KErrNone, if successful; otherwise one of the other system-wide error codes. |
|
466 @panic ETulPanicDescriptorLength in debug build if item's position |
|
467 and/or length is out of the document's range. |
|
468 */ |
|
469 TBool CTulAddressStringTokenizer::SearchPhoneNumberL( const TDesC& aText ) |
|
470 { |
|
471 TLexMark startMark; // Points to the start of the found phone number |
|
472 TLexMark endMark; // Points to the end of the found phone number |
|
473 TLexMark mark; |
|
474 const TInt end = aText.Length(); |
|
475 |
|
476 TLex number = aText; |
|
477 |
|
478 while ( !(number.Eos()) ) |
|
479 { |
|
480 TInt numberCount = 0; // How many real numbers (1234567890) |
|
481 TInt bracketsOpen = 0; // How many brackets are currently open |
|
482 TInt brackets = 0; // How many brackets overall |
|
483 |
|
484 TChar charac = number.Peek(); |
|
485 |
|
486 while( (!(IsValidPhoneNumberChar( charac ) || charac == '+' |
|
487 || charac == '(' ) || charac == '-' || charac == '.' || charac == '/') |
|
488 && !(number.Eos()) && number.Offset() < end ) |
|
489 { |
|
490 number.Inc(); |
|
491 charac = number.Peek(); |
|
492 } |
|
493 |
|
494 if ( number.Offset() >= end ) |
|
495 break; |
|
496 |
|
497 if ( number.Peek() == '#' ) |
|
498 { |
|
499 number.Inc(); |
|
500 if (number.Peek() == '.' ) |
|
501 continue; |
|
502 |
|
503 number.UnGet(); |
|
504 } |
|
505 |
|
506 if ( number.Peek() == '+' ) |
|
507 { // '+' has to be followed by a number (not # or * ...) |
|
508 number.Inc(); |
|
509 if ( !(number.Peek().IsDigit()) ) |
|
510 continue; |
|
511 |
|
512 number.UnGet(); |
|
513 } |
|
514 |
|
515 if ( number.Peek() == '(' ) |
|
516 { // '(' has to be followed by valid phone number |
|
517 // character (whitespaces are allowed before) or '+' is a next character |
|
518 number.Inc(); |
|
519 if ( !(number.Peek() == '+') ) |
|
520 { |
|
521 number.Mark(mark); |
|
522 number.SkipSpace(); |
|
523 charac = number.Peek(); |
|
524 if ( !( IsValidPhoneNumberChar(charac) || charac == '+' |
|
525 || charac == '(' ) || charac == '-' || charac == '.' || charac == '/') |
|
526 { |
|
527 number.Inc(); |
|
528 continue; |
|
529 } |
|
530 else |
|
531 { |
|
532 number.UnGetToMark(mark); |
|
533 number.UnGet(); |
|
534 number.Mark(startMark); |
|
535 } |
|
536 } |
|
537 else |
|
538 { |
|
539 number.UnGet(); |
|
540 number.Mark(startMark); |
|
541 number.Inc(); |
|
542 } |
|
543 |
|
544 bracketsOpen++; |
|
545 brackets++; |
|
546 } |
|
547 else |
|
548 number.Mark(startMark); |
|
549 |
|
550 if ( number.Peek().IsDigit() ) // If the character was a number |
|
551 numberCount++; |
|
552 else if ( bracketsOpen > 0 ) |
|
553 { |
|
554 number.Inc(); |
|
555 TChar next = number.Peek(); |
|
556 TInt bracketsOpen2 = bracketsOpen; |
|
557 while( (IsValidPhoneNumberChar( next ) || next.IsSpace() |
|
558 || next == '(' || next == ')' || next == 'p' || next == '+' |
|
559 || next == 'w' ) && !(number.Eos()) && number.Offset() < end) |
|
560 { |
|
561 if ( next == '(' ) |
|
562 bracketsOpen2++; |
|
563 else if ( next == ')' ) |
|
564 bracketsOpen2--; |
|
565 |
|
566 if ( bracketsOpen2 == 0 ) |
|
567 break; |
|
568 |
|
569 number.Inc(); |
|
570 next = number.Peek(); |
|
571 } |
|
572 |
|
573 number.UnGetToMark(startMark); |
|
574 if ( bracketsOpen2 != 0 ) |
|
575 { |
|
576 number.Inc(); |
|
577 continue; |
|
578 } |
|
579 } |
|
580 |
|
581 number.Inc(); |
|
582 while ( number.Peek() == '(' && !(number.Eos()) && bracketsOpen > 0 ) |
|
583 { |
|
584 number.Inc(); |
|
585 bracketsOpen++; |
|
586 } |
|
587 |
|
588 if ( number.Peek() == '+' && bracketsOpen > 0 ) |
|
589 number.Inc(); |
|
590 |
|
591 // a Valid first character has been found. Let's go forward as long as valid characters are found. |
|
592 charac = number.Peek(); |
|
593 |
|
594 while( (IsValidPhoneNumberChar( charac ) || charac.IsSpace() |
|
595 || charac == '(' || charac == ')' || charac == 'p' |
|
596 || charac == 'w' ) && !(number.Eos()) && number.Offset() < end |
|
597 && charac != KCharLinefeed && charac != KCharFormfeed |
|
598 && charac != KCharCarriageReturn |
|
599 && charac != KCharLineSeparator |
|
600 && charac != KCharParagraphSeparator ) |
|
601 { |
|
602 if ( number.Peek() == '(' ) |
|
603 { // '(' can't be the last character in phone number |
|
604 number.Mark(mark); |
|
605 number.Inc(); |
|
606 |
|
607 TChar spaceJump = number.Peek(); |
|
608 while ( !number.Eos() && spaceJump.IsSpace() && spaceJump != KCharLinefeed |
|
609 && spaceJump != KCharFormfeed && spaceJump != KCharCarriageReturn |
|
610 && charac != KCharLineSeparator && spaceJump != KCharParagraphSeparator) |
|
611 { |
|
612 number.Inc(); |
|
613 spaceJump = number.Peek(); |
|
614 } |
|
615 |
|
616 if ( !(IsValidPhoneNumberChar(number.Peek())) && number.Peek() != ')' |
|
617 && number.Peek() != '(' ) |
|
618 { |
|
619 number.UnGetToMark(mark); |
|
620 break; |
|
621 } |
|
622 |
|
623 TChar next = number.Peek(); |
|
624 TInt bracketsOpen2 = bracketsOpen + 1; |
|
625 while( (IsValidPhoneNumberChar( next ) || next.IsSpace() |
|
626 || next == '(' || next == ')' || next == 'p' |
|
627 || next == 'w' ) && !(number.Eos()) && number.Offset() < end) |
|
628 { |
|
629 if ( next == '(' ) |
|
630 bracketsOpen2++; |
|
631 else if ( next == ')' ) |
|
632 bracketsOpen2--; |
|
633 |
|
634 if ( bracketsOpen2 == 0 ) |
|
635 break; |
|
636 |
|
637 number.Inc(); |
|
638 next = number.Peek(); |
|
639 } |
|
640 |
|
641 number.UnGetToMark(mark); |
|
642 |
|
643 if ( bracketsOpen2 != 0 ) |
|
644 break; |
|
645 |
|
646 bracketsOpen++; |
|
647 brackets++; |
|
648 } |
|
649 else if ( number.Peek() == ')' ) |
|
650 { |
|
651 if ( bracketsOpen <= 0 ) // there has to be equal number of brackets |
|
652 break; |
|
653 |
|
654 bracketsOpen--; |
|
655 number.Mark(mark); |
|
656 number.Inc(); |
|
657 if ( number.Peek() == '.' ) // '.' is not allowed after ')' |
|
658 break; |
|
659 |
|
660 number.UnGetToMark(mark); |
|
661 } |
|
662 else if ( number.Peek() == '-' || number.Peek() == 'w' |
|
663 || number.Peek() == 'p' || number.Peek() == '.' || number.Peek() == '/') |
|
664 { // Hyphen mark and 'p' & 'w' chars must be followed by a number |
|
665 TChar last = number.Peek(); |
|
666 number.Mark(mark); |
|
667 number.Inc(); |
|
668 |
|
669 TChar spaceJump = number.Peek(); |
|
670 while ( !number.Eos() && spaceJump.IsSpace() && spaceJump != KCharLinefeed |
|
671 && spaceJump != KCharFormfeed && spaceJump != KCharCarriageReturn |
|
672 && charac != KCharLineSeparator && spaceJump != KCharParagraphSeparator ) |
|
673 { |
|
674 number.Inc(); |
|
675 spaceJump = number.Peek(); |
|
676 } |
|
677 |
|
678 if ( !(number.Peek().IsDigit()) ) |
|
679 { |
|
680 if (last == '.' && number.Peek() == ')' && bracketsOpen > 0 ) |
|
681 continue; |
|
682 else |
|
683 { |
|
684 number.UnGetToMark(mark); |
|
685 break; |
|
686 } |
|
687 } |
|
688 |
|
689 number.UnGetToMark(mark); |
|
690 } |
|
691 else if ( number.Peek().IsDigit() ) |
|
692 numberCount++; |
|
693 |
|
694 number.Inc(); |
|
695 charac = number.Peek(); |
|
696 } |
|
697 |
|
698 // Get rid of whitespaces from the end |
|
699 number.UnGet(); |
|
700 while( number.Peek().IsSpace() && !(number.Eos())) |
|
701 number.UnGet(); |
|
702 |
|
703 number.Inc(); |
|
704 // ------------------------------------ |
|
705 number.Mark(endMark); |
|
706 |
|
707 // If they exist, remove brackets from the beginning and the end |
|
708 number.Mark(mark); // Let's mark where to continue the search |
|
709 TBool endBrackets = ETrue; |
|
710 do |
|
711 { |
|
712 number.UnGet(); |
|
713 |
|
714 if ( number.Peek() == ')' ) |
|
715 { |
|
716 number.UnGetToMark(startMark); |
|
717 if ( number.Peek() == '(' ) |
|
718 { |
|
719 // If there's more than one pair of brackets -> don't strip them. |
|
720 if ( brackets > 1 ) |
|
721 break; |
|
722 |
|
723 number.Inc(); |
|
724 number.Mark(startMark); |
|
725 number.UnGetToMark(endMark); |
|
726 number.UnGet(); |
|
727 number.Mark(endMark); |
|
728 // Get rid of whitespaces and periods from the end and from the beginning |
|
729 number.UnGet(); |
|
730 while ( (number.Peek().IsSpace() || number.Peek() == '.') |
|
731 && number.Offset() > number.MarkedOffset(startMark) ) |
|
732 { // from the end |
|
733 number.UnGet(); |
|
734 } |
|
735 number.Inc(); |
|
736 number.Mark(endMark); |
|
737 number.UnGetToMark(startMark); |
|
738 while ( (number.Peek().IsSpace() || number.Peek() == '.') |
|
739 && number.Offset() < number.MarkedOffset(endMark) ) |
|
740 { // from the beginning |
|
741 number.Inc(); |
|
742 } |
|
743 number.Mark(startMark); |
|
744 number.UnGetToMark(endMark); |
|
745 // ---- |
|
746 } |
|
747 else |
|
748 endBrackets = EFalse; |
|
749 } |
|
750 else |
|
751 endBrackets = EFalse; |
|
752 } |
|
753 while ( endBrackets ); |
|
754 |
|
755 number.UnGetToMark(mark); |
|
756 // ---------------- |
|
757 |
|
758 if ( numberCount <= KFindItemMaxNumbers && numberCount >= iMinNumbers ) |
|
759 { |
|
760 TPtrC tokenPtr = number.MarkedToken(startMark); |
|
761 TInt tokensEnd = tokenPtr.Length(); |
|
762 TInt numbers = 0; |
|
763 TInt partialNumber = 0; |
|
764 TBool wasValidPhoneNumber = ETrue; |
|
765 TInt i = 0; |
|
766 |
|
767 for ( ; i < tokensEnd; i++ ) |
|
768 { |
|
769 if ( tokenPtr[i] == '.' ) |
|
770 partialNumber = 0; |
|
771 else if ( ((TChar)tokenPtr[i]).IsDigit() ) |
|
772 { |
|
773 numbers++; |
|
774 partialNumber++; |
|
775 } |
|
776 |
|
777 if ( ( partialNumber == 1 || partialNumber == 2 ) && i + 1 < tokensEnd ) |
|
778 { |
|
779 if ( tokenPtr[i + 1] == '.' ) |
|
780 wasValidPhoneNumber = EFalse; |
|
781 } |
|
782 } |
|
783 |
|
784 if (!wasValidPhoneNumber && numbers > 6) |
|
785 wasValidPhoneNumber = ETrue; |
|
786 |
|
787 if (wasValidPhoneNumber) |
|
788 { |
|
789 __ASSERT_DEBUG( number.MarkedOffset(startMark) + number.MarkedOffset(endMark) |
|
790 - number.MarkedOffset(startMark) <= aText.Length(), |
|
791 Panic(ETulPanicDescriptorLength) ); |
|
792 |
|
793 AddItemL( number.MarkedOffset(startMark), |
|
794 number.MarkedOffset(endMark) - number.MarkedOffset(startMark), |
|
795 EFindItemSearchPhoneNumberBin ); |
|
796 } |
|
797 } |
|
798 |
|
799 } |
|
800 |
|
801 return (iFoundItems->Count() > 0); |
|
802 } |
|
803 |
|
804 |
|
805 /** |
|
806 Parses URL from a token. Is used by SearchUrlL method and if a URL |
|
807 was found it's appended to item array. Note that parsing for generic URIs |
|
808 is done with SearchGenericUriL -method. |
|
809 |
|
810 @param aType a Type of URL to seach, i.e. |
|
811 www. |
|
812 wap. |
|
813 IP e.g.127.0.0.1 |
|
814 @param aTokenPtr Pointer to token that will be parsed |
|
815 @param aTextOffset Offset of the token (start position in the whole text) |
|
816 @leave KErrNone, if successful; otherwise one of the other system-wide error codes. |
|
817 @return ETrue if the parameter for phone number is valid, else returns EFalse |
|
818 */ |
|
819 TBool CTulAddressStringTokenizer::ParseUrlL(const TDesC& aType, const TPtrC& aTokenPtr, TInt aTextOffset) |
|
820 { |
|
821 TBool wasValidUrl = EFalse; |
|
822 TLex url; |
|
823 |
|
824 TInt position = aTokenPtr.FindF( aType ); |
|
825 if ( position != KErrNotFound ) |
|
826 { // address start found |
|
827 url = aTokenPtr.Right( aTokenPtr.Length() - position ); |
|
828 url.Inc( aType.Length() ); |
|
829 |
|
830 while( IsValidUrlChar( url.Peek() ) && !(url.Eos()) ) |
|
831 { |
|
832 if( url.Peek() == ':' ) |
|
833 { |
|
834 url.Inc(); |
|
835 if ( !url.Peek().IsDigit() ) |
|
836 { |
|
837 url.UnGet(); |
|
838 break; |
|
839 } |
|
840 } |
|
841 else |
|
842 url.Inc(); |
|
843 } |
|
844 |
|
845 // If a period or question mark was followed by a whitespace remove it |
|
846 if ( url.Eos() ) // Can't be followed by white space if it's |
|
847 { // the last character at token |
|
848 url.UnGet(); |
|
849 if ( url.Peek() != '.' && url.Peek() != '?' && url.Peek() != ',' ) // If it wasn't a period or question mark |
|
850 url.Inc(); |
|
851 } |
|
852 |
|
853 url.Mark(); |
|
854 wasValidUrl = ETrue; |
|
855 } |
|
856 |
|
857 if ( wasValidUrl && ( url.MarkedOffset() > aType.Length() ) ) |
|
858 { |
|
859 AddItemL( aTextOffset - aTokenPtr.Length() + position, url.MarkedOffset(), EFindItemSearchURLBin ); |
|
860 return ETrue; |
|
861 } |
|
862 |
|
863 return EFalse; |
|
864 } |
|
865 |
|
866 /** |
|
867 Search fixed start URLs, i.e. URLs without schema (www., wap.). |
|
868 Also finds IPv4 addresses (*.*.*.*). |
|
869 As a special case, supports deprecated hardcoded schematic addresses finding |
|
870 (http://, https://, rtsp://) to make sure deprecated search cases work |
|
871 as they did previously. |
|
872 |
|
873 @param aText Text that will be parsed |
|
874 @param aFindFixedSchemas If true, will find old fixed schematic URLs also |
|
875 @return ETrue if any URL are found else returns EFalse |
|
876 @leave KErrNone, if successful; otherwise one of the other system-wide error codes. |
|
877 @panic ETulPanicDescriptorLength in debug build if item's position and/or length is out of the document's range. |
|
878 */ |
|
879 TBool CTulAddressStringTokenizer::SearchUrlL( const TDesC& aText, const TBool aFindFixedSchemas ) |
|
880 { |
|
881 TLex text = aText; |
|
882 while ( !text.Eos() ) |
|
883 { |
|
884 while( !(text.Eos()) && !IsValidUrlChar( text.Peek() ) ) |
|
885 text.Inc(); |
|
886 |
|
887 text.Mark(); |
|
888 while( !(text.Eos()) && IsValidUrlChar( text.Peek() ) ) |
|
889 text.Inc(); |
|
890 |
|
891 TPtrC tokenPtr = text.MarkedToken(); |
|
892 TBool wasValidUrl = EFalse; |
|
893 |
|
894 if ( aFindFixedSchemas ) // Search for http:// |
|
895 wasValidUrl = ParseUrlL( KHttpUrlAddress, tokenPtr, text.Offset() ); |
|
896 |
|
897 if (aFindFixedSchemas && !wasValidUrl) // Search for https:// |
|
898 wasValidUrl = ParseUrlL( KHttpsUrlAddress, tokenPtr, text.Offset() ); |
|
899 |
|
900 if (aFindFixedSchemas && !wasValidUrl) // Search for rtsp:// |
|
901 wasValidUrl = ParseUrlL( KRtspUrlAddress, tokenPtr, text.Offset() ); |
|
902 |
|
903 if ( !wasValidUrl ) // Search for www. |
|
904 wasValidUrl = ParseUrlL( KWwwUrlAddress, tokenPtr, text.Offset() ); |
|
905 |
|
906 if ( !wasValidUrl ) // Search for wap. |
|
907 wasValidUrl = ParseUrlL( KWapUrlAddress, tokenPtr, text.Offset() ); |
|
908 |
|
909 if ( !wasValidUrl ) // Search for IP-address (xxx.xxx.xxx.xxx) |
|
910 { |
|
911 if ( tokenPtr.Match( KIPAddress ) != KErrNotFound ) |
|
912 { |
|
913 TInt periods = 0; |
|
914 wasValidUrl = ETrue; |
|
915 TBool endWithPunctuation = EFalse; |
|
916 TBool betweenBrackets = EFalse; |
|
917 |
|
918 // First see if token ends with ",",".","!","?",";" or ":" |
|
919 TChar charac = tokenPtr[tokenPtr.Length() - 1]; |
|
920 TChar charac0 = tokenPtr[0]; |
|
921 if ( charac == ',' || charac == '.' || |
|
922 charac == '!' || charac == '?' || |
|
923 charac == ';' || charac == ':' ) |
|
924 { |
|
925 endWithPunctuation = ETrue; |
|
926 } |
|
927 // Or if it starts and ends with brackets or quotation marks |
|
928 else if ( ( charac0 == '(' && charac == ')' ) |
|
929 || ( charac0 == '"' && charac == '"' ) |
|
930 || ( charac0 == '[' && charac == ']' ) |
|
931 || ( charac0 == '<' && charac == '>' ) ) |
|
932 { |
|
933 betweenBrackets = ETrue; |
|
934 } |
|
935 |
|
936 TInt i = 0; |
|
937 TInt tokensEnd = tokenPtr.Length(); |
|
938 if ( endWithPunctuation ) |
|
939 tokensEnd--; |
|
940 else if ( betweenBrackets ) |
|
941 { |
|
942 i = 1; |
|
943 tokensEnd--; |
|
944 } |
|
945 |
|
946 // Take a closer look to see if a valid IP-address |
|
947 TBuf<3> ipPart; |
|
948 TInt numbers = 0; |
|
949 for ( ; i < tokensEnd; i++ ) |
|
950 { |
|
951 if ( !( ((TChar)tokenPtr[i]).IsDigit() || tokenPtr[i] == '.' ) ) |
|
952 { |
|
953 wasValidUrl = EFalse; |
|
954 break; |
|
955 } |
|
956 |
|
957 if ( tokenPtr[i] == '.' ) |
|
958 periods++; |
|
959 else |
|
960 numbers++; |
|
961 |
|
962 if ( numbers > KNumbersInIpAddress || periods > KDotsInIpAddress ) |
|
963 { |
|
964 wasValidUrl = EFalse; |
|
965 break; |
|
966 } |
|
967 |
|
968 if ( ((TChar)tokenPtr[i]).IsDigit() ) |
|
969 { |
|
970 ipPart.Append( tokenPtr[i] ); |
|
971 TBool checkInt = EFalse; |
|
972 if ( i + 1 < tokensEnd ) |
|
973 { |
|
974 if ( tokenPtr[i+1] == '.' ) |
|
975 checkInt = ETrue; |
|
976 } |
|
977 |
|
978 if ( i == tokensEnd - 1 || checkInt ) |
|
979 { |
|
980 TLex val = ipPart; |
|
981 TInt numberInt; |
|
982 TInt error = val.Val( numberInt ); |
|
983 if ( error != KErrNone || numberInt > 255 ) |
|
984 { |
|
985 wasValidUrl = EFalse; |
|
986 break; |
|
987 } |
|
988 |
|
989 numbers = 0; |
|
990 ipPart.Delete( 0, ipPart.Length() ); |
|
991 } |
|
992 } |
|
993 } |
|
994 |
|
995 if ( wasValidUrl && periods == KDotsInIpAddress ) |
|
996 { |
|
997 TInt startPos = text.Offset() - tokenPtr.Length(); |
|
998 TInt length = tokenPtr.Length(); |
|
999 // If there was a punctuation at the end or brackets, let's take it/them away |
|
1000 if ( endWithPunctuation || betweenBrackets) |
|
1001 { |
|
1002 length--; |
|
1003 if ( betweenBrackets ) |
|
1004 { |
|
1005 startPos++; |
|
1006 length--; |
|
1007 } |
|
1008 } |
|
1009 |
|
1010 __ASSERT_DEBUG( startPos + length <= aText.Length(), Panic(ETulPanicDescriptorLength) ); |
|
1011 AddItemL( startPos, length, EFindItemSearchURLBin ); |
|
1012 } |
|
1013 } |
|
1014 } |
|
1015 } |
|
1016 |
|
1017 return (iFoundItems->Count() > 0); |
|
1018 } |
|
1019 |
|
1020 /** |
|
1021 Search algorithm for searching generic URIs |
|
1022 |
|
1023 @param aText Text that will be parsed |
|
1024 @return ETrue if any generic URI is found else returns EFalse |
|
1025 @leave KErrNone, if successful; otherwise one of the other system-wide error codes. |
|
1026 */ |
|
1027 TBool CTulAddressStringTokenizer::SearchGenericUriL( const TDesC& aText ) |
|
1028 { |
|
1029 // Detect generic URI within the token |
|
1030 const TDesC& schemeStartArray = KURISchemeStartCharacters; |
|
1031 const TDesC& schemeBodyArray = KURISchemeBodyCharacters; |
|
1032 const TDesC& schemeTerminatorArray = KURISchemeTerminator; |
|
1033 const TDesC& URIArray = KURICharacters; |
|
1034 |
|
1035 TBool wasValidUri = EFalse; |
|
1036 TLex text = aText; |
|
1037 |
|
1038 while ( !text.Eos() ) |
|
1039 { |
|
1040 // Discard characters until URI scheme terminator is found |
|
1041 while( !(text.Eos()) && schemeTerminatorArray.Locate(text.Peek()) == KErrNotFound ) |
|
1042 text.Inc(); |
|
1043 |
|
1044 // if at end of the text, no legit URI found |
|
1045 if ( !text.Eos() ) |
|
1046 { |
|
1047 // Store the schema end offset (+1 to skip ':') |
|
1048 TInt schemeEndOffset = text.Offset() + 1; |
|
1049 |
|
1050 // Scheme must be at least 1 character long at the beginning of the text to be valid |
|
1051 if ( text.Offset() > 0 ) |
|
1052 { |
|
1053 // Un-get last scheme character to begin examination |
|
1054 text.UnGet(); |
|
1055 |
|
1056 // Rewind until beginning of the URI |
|
1057 while ( text.Offset() > 0 && schemeBodyArray.Locate(text.Peek().GetLowerCase()) != KErrNotFound ) |
|
1058 text.UnGet(); |
|
1059 |
|
1060 // Now text pointer is at first character of the URI |
|
1061 // Do go back through the scheme until a legal beginning character for URI |
|
1062 // is found or back to the (schemeEndOffset - 1) i.e. URI scheme terminator |
|
1063 while ( schemeStartArray.Locate(text.Peek().GetLowerCase()) == KErrNotFound && (text.Offset() + 1) < schemeEndOffset ) |
|
1064 text.Inc(); |
|
1065 |
|
1066 // check if terminated because a valid start character was found when |
|
1067 // scheme terminator was reached. |
|
1068 if ( schemeStartArray.Locate(text.Peek().GetLowerCase()) != KErrNotFound ) |
|
1069 { |
|
1070 // First character is a valid URI char, so the scheme is valid -> |
|
1071 // marks the beginning of the array |
|
1072 text.Mark(); |
|
1073 |
|
1074 // fast forward to the end of the scheme |
|
1075 while( text.Offset() < schemeEndOffset ) |
|
1076 text.Inc(); |
|
1077 |
|
1078 // Get characters until end of schema |
|
1079 while( !(text.Eos()) && URIArray.Locate( text.Peek().GetLowerCase() ) != KErrNotFound ) |
|
1080 text.Inc(); |
|
1081 |
|
1082 // remove certain punctuation from end of the URI, as it is likely |
|
1083 // to be part of the surrounding text. |
|
1084 text.UnGet(); |
|
1085 |
|
1086 //special processing for bracket |
|
1087 //only remove the end bracket if there is no open bracket in the uri |
|
1088 //not counting bracket pairs for efficiency |
|
1089 if (text.Peek()!=')' || text.MarkedToken().Locate(TChar('('))!=-1) |
|
1090 text.Inc(); |
|
1091 |
|
1092 text.UnGet(); |
|
1093 if ( text.Peek() != '.' && text.Peek() != '?' && text.Peek() != ',') |
|
1094 text.Inc(); |
|
1095 |
|
1096 // URI cannot contain only scheme, so check that pointer was increased |
|
1097 // by at least one character |
|
1098 if ( schemeEndOffset != text.Offset() ) |
|
1099 { |
|
1100 // Append found text to item array (it is now known to be |
|
1101 // syntactically valid URI as it contains characters after the scheme) |
|
1102 AddItemL( text.MarkedOffset(), text.Offset() - text.MarkedOffset(), EFindItemSearchScheme ); |
|
1103 wasValidUri = ETrue; |
|
1104 } |
|
1105 } |
|
1106 else // First character of scheme is not legit, fast forward to end of the |
|
1107 // scheme anyway to continue search |
|
1108 { |
|
1109 while( text.Offset() < schemeEndOffset ) |
|
1110 text.Inc(); |
|
1111 } |
|
1112 } |
|
1113 else |
|
1114 text.Inc(); |
|
1115 } |
|
1116 } |
|
1117 |
|
1118 return wasValidUri; |
|
1119 } |
|
1120 |
|
1121 // --------------------------------------------------------- |
|
1122 // Position and count methods |
|
1123 // --------------------------------------------------------- |
|
1124 |
|
1125 /** |
|
1126 Gets the number of items in the found items array. |
|
1127 |
|
1128 @return the number of items in the found items array. |
|
1129 */ |
|
1130 EXPORT_C TInt CTulAddressStringTokenizer::ItemCount() const |
|
1131 { |
|
1132 return (iFoundItems ? iFoundItems->Count() : 0); |
|
1133 } |
|
1134 |
|
1135 /** |
|
1136 Gets the current position (or the position of the currently selected item) |
|
1137 in the found items array. |
|
1138 |
|
1139 @return the current position in the found items array of the |
|
1140 CTulAddressStringTokenizer instance. If no items are in the array, zero is returned. |
|
1141 */ |
|
1142 EXPORT_C TInt CTulAddressStringTokenizer::Position() const |
|
1143 { |
|
1144 return iPosition; |
|
1145 } |
|
1146 |
|
1147 /** |
|
1148 Resets the position in item array to zero (beginning of the array). |
|
1149 */ |
|
1150 EXPORT_C void CTulAddressStringTokenizer::ResetPosition() |
|
1151 { |
|
1152 iPosition = 0; |
|
1153 } |
|
1154 |
|
1155 // --------------------------------------------------------- |
|
1156 // GetItem methods |
|
1157 // --------------------------------------------------------- |
|
1158 |
|
1159 /** |
|
1160 Gets the array of found items. Returns a constant pointer to the |
|
1161 found items array of the CTulAddressStringTokenizer instance. The items cannot |
|
1162 be modified through this pointer, only accessed. The ownership of |
|
1163 the array stays with CTulAddressStringTokenizer. |
|
1164 |
|
1165 @return a constant pointer to the array of found items. Ownership |
|
1166 stays with CTulAddressStringTokenizer. |
|
1167 */ |
|
1168 EXPORT_C const CArrayFixFlat<CTulAddressStringTokenizer::SFoundItem>* CTulAddressStringTokenizer::ItemArray() const |
|
1169 { |
|
1170 return iFoundItems; |
|
1171 } |
|
1172 |
|
1173 /** |
|
1174 Gets the currently 'selected' item in the array of found items. |
|
1175 |
|
1176 @param aItem contains the currently selected item after returning. |
|
1177 @return ETrue if the item was found. EFalse if the item wasn't found. |
|
1178 */ |
|
1179 EXPORT_C TBool CTulAddressStringTokenizer::Item( SFoundItem& aItem ) const |
|
1180 { // Return EFalse if no items were found |
|
1181 if ( iFoundItems->Count() <= 0 ) |
|
1182 { |
|
1183 aItem.iStartPos = 0; |
|
1184 aItem.iLength = 0; |
|
1185 aItem.iItemType = EFindItemSearchPhoneNumberBin; |
|
1186 return EFalse; |
|
1187 } |
|
1188 |
|
1189 aItem = iFoundItems->At( iPosition ); |
|
1190 return ETrue; |
|
1191 } |
|
1192 |
|
1193 /** |
|
1194 Gets the next found item relative to the currently selected item. |
|
1195 Moves the selection to point to the next item in the array of |
|
1196 found items. |
|
1197 |
|
1198 @param aItem contains the next item after returning. |
|
1199 @return ETrue if the item was found. EFalse if there's no next item. |
|
1200 */ |
|
1201 EXPORT_C TBool CTulAddressStringTokenizer::NextItem( SFoundItem& aItem ) |
|
1202 { |
|
1203 if (iFoundItems->Count() <= (iPosition + 1)) |
|
1204 return EFalse; |
|
1205 |
|
1206 iPosition++; |
|
1207 aItem = iFoundItems->At( iPosition ); |
|
1208 return ETrue; |
|
1209 } |
|
1210 |
|
1211 /** |
|
1212 Gets the previous found item relative to the currently selected |
|
1213 item. Moves the selection to point to the previous item in the |
|
1214 array of found items.. |
|
1215 |
|
1216 @param aItem contains the previous item after returning. |
|
1217 @return ETrue if the item was found. EFalse if there's no previous item. |
|
1218 */ |
|
1219 EXPORT_C TBool CTulAddressStringTokenizer::PrevItem( SFoundItem& aItem ) |
|
1220 { |
|
1221 if ( iPosition <= 0 ) |
|
1222 return EFalse; |
|
1223 |
|
1224 iPosition--; |
|
1225 aItem = iFoundItems->At( iPosition ); |
|
1226 return ETrue; |
|
1227 } |
|
1228 |
|
1229 /** |
|
1230 Adds item to search arrays. Adding is done so that arrays are always sorted. |
|
1231 If added element would overlap a previously found element, it is not added. |
|
1232 |
|
1233 @param aStartPos Start position of the found item |
|
1234 @param aLength Length of found item |
|
1235 @param aType Type of the found item |
|
1236 @leave KErrNone, if successful; otherwise one of the other system-wide error codes. |
|
1237 */ |
|
1238 void CTulAddressStringTokenizer::AddItemL(TInt aStartPos, TInt aLength, TTokenizerSearchCase aType ) |
|
1239 { |
|
1240 // Create item element |
|
1241 SFoundItem foundItem; |
|
1242 foundItem.iStartPos = aStartPos; |
|
1243 foundItem.iLength = aLength; |
|
1244 foundItem.iItemType = aType; |
|
1245 |
|
1246 // Add item data to arrays |
|
1247 TKeyArrayFix insertKey(0, ECmpTInt); |
|
1248 iFoundItems->InsertIsqAllowDuplicatesL(foundItem, insertKey); |
|
1249 } |
|
1250 |
|
1251 // End of File |