lafagnosticuifoundation/uigraphicsutils/tulsrc/tuladdressstringtokenizer.cpp
changeset 0 2f259fa3e83a
child 4 8ca85d2f0db7
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     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