commonuis/CommonUi/src/ItemFinder.cpp
changeset 0 2f259fa3e83a
child 5 aabf2c525e0f
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 /*
       
     2 * Copyright (c) 2002-2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Plugin utility used for automatic tags ( http, email, phone numbers, URI schemes )
       
    15 *                syntax highlighting in text viewers
       
    16 *
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 // INCLUDES
       
    22 #include <eikrted.h>
       
    23 #include <txtrich.h> // for CRichText
       
    24 #include "ItemFinder.h"
       
    25 #include <finditemengine.h>
       
    26 #include <commonphoneparser.h>
       
    27 #include <txtfrmat.h>
       
    28 #include <AknUtils.h> // for AknUtils
       
    29 #include <AknsUtils.h>
       
    30 
       
    31 // scheme recog
       
    32 #include <ecom/ecom.h>
       
    33 #include <ecom/implementationinformation.h>
       
    34 
       
    35 #include <centralrepository.h>
       
    36 #include <CommonUiInternalCRKeys.h>
       
    37 
       
    38 // CONSTANTS
       
    39 const TInt KMINTAGLENGTH(5);
       
    40 _LIT( KHTTPPREFIX, "http://");
       
    41 _LIT( RTSP, "rtsp");
       
    42 _LIT( KTELPREFIX, "tel:");
       
    43 
       
    44 const TInt KItemFinderMinDigitsToFind = 5;
       
    45 #define SCHEME_INTERFACE_DEF TUid( TUid::Uid(0x101f8534) ) // we don't want header dependency to browser utilities
       
    46 
       
    47 NONSHARABLE_CLASS(CSchemeResolver): public CBase
       
    48     {
       
    49 public:
       
    50     CSchemeResolver(){};
       
    51     static CSchemeResolver* NewL();
       
    52     inline CArrayPtrFlat<HBufC>& SupportedSchemes(){ return *iSupportedArray; };
       
    53     ~CSchemeResolver();
       
    54 private:
       
    55     void ConstructL();
       
    56     CArrayPtrFlat<HBufC>* iSupportedArray;
       
    57     RImplInfoPtrArray iEcomInfoArray;
       
    58     };
       
    59 
       
    60 CSchemeResolver* CSchemeResolver::NewL()
       
    61     {
       
    62     CSchemeResolver* me = new (ELeave) CSchemeResolver();
       
    63     CleanupStack::PushL( me );
       
    64     me->ConstructL();
       
    65     CleanupStack::Pop();
       
    66     return me;
       
    67     }
       
    68 
       
    69 void CSchemeResolver::ConstructL()
       
    70     {
       
    71     //perform plugin scan
       
    72     iSupportedArray = new (ELeave) CArrayPtrFlat<HBufC>( 5 );
       
    73     REComSession::ListImplementationsL( SCHEME_INTERFACE_DEF, iEcomInfoArray );
       
    74     for ( TInt i = 0; i < iEcomInfoArray.Count() ; i++ )
       
    75         {
       
    76         HBufC* data = HBufC::NewLC( iEcomInfoArray[ i ]->DataType().Length() );
       
    77         data->Des().Copy( iEcomInfoArray[ i ]->DataType() );
       
    78         iSupportedArray->AppendL( data );
       
    79         CleanupStack::Pop();
       
    80         }
       
    81     iEcomInfoArray.ResetAndDestroy(); // we don't need this anymore
       
    82     }
       
    83 
       
    84 CSchemeResolver::~CSchemeResolver()
       
    85     {
       
    86     iEcomInfoArray.ResetAndDestroy();
       
    87     if (iSupportedArray)
       
    88         {
       
    89         iSupportedArray->ResetAndDestroy();
       
    90         }
       
    91     delete iSupportedArray;
       
    92     }
       
    93 
       
    94 NONSHARABLE_CLASS(CItemFinderAsyncParser): public CActive
       
    95     {
       
    96 public:
       
    97     static CItemFinderAsyncParser* NewL( CEikRichTextEditor* aEditor, TInt* aFirstVisible, TInt aMinDigitsToFind );
       
    98     void SetCallbackObserver( CItemFinder* aObserver ){ iObserver = aObserver; };
       
    99     ~CItemFinderAsyncParser();
       
   100     void RunL();
       
   101     void DoCancel();
       
   102     CFindItemEngine* iFIE;
       
   103     CArrayPtrFlat<CItemFinder::CFindItemExt>* iMarkedItems;
       
   104 private:
       
   105     CItemFinderAsyncParser( CEikRichTextEditor* aEditor, TInt* aFirstVisible, TInt aMinDigitsToFind );
       
   106     CEikRichTextEditor* iEditor;
       
   107     TInt& iFirstVisible;
       
   108     CItemFinder* iObserver; // not owned
       
   109     TInt iMinDigitsToFind;
       
   110 };
       
   111 
       
   112 CItemFinderAsyncParser::CItemFinderAsyncParser( CEikRichTextEditor* aEditor, TInt* aFirstVisible, TInt aMinDigitsToFind )
       
   113     :CActive( CActive::EPriorityIdle ), iEditor( aEditor ), iFirstVisible( *aFirstVisible ), iMinDigitsToFind( aMinDigitsToFind )
       
   114     {
       
   115     CActiveScheduler::Add(this);
       
   116     iStatus = KRequestPending;
       
   117     SetActive();
       
   118     TRequestStatus* ptr = &iStatus;
       
   119     User::RequestComplete( ptr, KErrNone );// RunL will be called when everything with higher priority has completed
       
   120     }
       
   121 
       
   122 CItemFinderAsyncParser* CItemFinderAsyncParser::NewL( CEikRichTextEditor* aEditor, TInt* aFirstVisible, TInt aMinDigitsToFind )
       
   123     {
       
   124     return new (ELeave) CItemFinderAsyncParser( aEditor, aFirstVisible, aMinDigitsToFind );
       
   125     }
       
   126 
       
   127 CItemFinderAsyncParser::~CItemFinderAsyncParser()
       
   128     {
       
   129     Cancel(); // does nothing
       
   130     delete iFIE;
       
   131     if ( iMarkedItems )
       
   132         {
       
   133         iMarkedItems->ResetAndDestroy();
       
   134         }
       
   135     delete iMarkedItems;
       
   136     }
       
   137 
       
   138 void CItemFinderAsyncParser::RunL()
       
   139     {
       
   140     TInt fullLength = Min( iEditor->TextLength(), 0xffff );
       
   141     const TDesC& text = iEditor->Text()->Read( 0, fullLength );
       
   142     TInt searchAll = CFindItemEngine::EFindItemSearchURLBin
       
   143         |CFindItemEngine::EFindItemSearchMailAddressBin
       
   144         |CFindItemEngine::EFindItemSearchPhoneNumberBin
       
   145         |CFindItemEngine::EFindItemSearchScheme;
       
   146     if ( !iFIE )
       
   147         {
       
   148         iFIE = CFindItemEngine::NewL( text, (CFindItemEngine::TFindItemSearchCase)searchAll, iMinDigitsToFind );
       
   149         }
       
   150     else
       
   151         {
       
   152         iFIE->DoNewSearchL( text, (CFindItemEngine::TFindItemSearchCase)searchAll, iMinDigitsToFind );
       
   153         }
       
   154     delete iMarkedItems;
       
   155     iMarkedItems = 0;
       
   156     iMarkedItems = new ( ELeave ) CArrayPtrFlat<CItemFinder::CFindItemExt>( 10 );
       
   157     iEditor->RefreshParsersL();
       
   158     if ( iObserver && iObserver->CallbackToExtObserver() == EFalse )
       
   159         {
       
   160         iEditor->SetCursorPosL( 0, EFalse ); // need to rollback in order to make sure that line will remain same
       
   161         if ( iFirstVisible > 0 )
       
   162             {
       
   163             iEditor->SetCursorPosL( iFirstVisible, EFalse ); // Magic, parsing forces screen to first item (?)
       
   164             }
       
   165         iObserver->NextItemOrScrollL( iFirstVisible ? CItemFinder::EInit : CItemFinder::EInitDown );
       
   166         }
       
   167     }
       
   168 
       
   169 void CItemFinderAsyncParser::DoCancel()
       
   170     {
       
   171     }
       
   172 
       
   173 EXPORT_C CItemFinder::CFindItemExt::~CFindItemExt()
       
   174 		{
       
   175 		if ( iItemDescriptor ) 
       
   176 				delete iItemDescriptor;
       
   177 		}
       
   178 	
       
   179 CItemFinder::~CItemFinder()
       
   180     {
       
   181     CRichText::DeactivateParser(this);   
       
   182     if ( iCurrentItemExt )
       
   183         {
       
   184         delete iCurrentItemExt;
       
   185         }    
       
   186     if ( iExternalLinks )
       
   187         {
       
   188         iExternalLinks->ResetAndDestroy();
       
   189         delete iExternalLinks;
       
   190         }
       
   191     if ( iAsyncParser )
       
   192         {
       
   193         delete iAsyncParser;
       
   194         }    
       
   195     if ( iSchemeResolver )
       
   196         {
       
   197         delete iSchemeResolver;
       
   198         }    
       
   199     }
       
   200 
       
   201 CItemFinder::CItemFinder( TInt aFindFlags ): iFlags( aFindFlags )
       
   202     {}
       
   203 
       
   204 void CItemFinder::ConstructL()
       
   205     {
       
   206     iMinDigitsToFind = KItemFinderMinDigitsToFind; // default
       
   207     iCurrentItemExt = new (ELeave) CFindItemExt();
       
   208     CRichText::ActivateParserL(this);
       
   209     iSchemeResolver = CSchemeResolver::NewL();
       
   210     iMinDigitsToFind = GetMinDigitsToFindL(); // variated.
       
   211     }
       
   212 
       
   213 TInt CItemFinder::GetMinDigitsToFindL()
       
   214     {
       
   215     TInt err = KErrNone;
       
   216     CRepository* variation = CRepository::NewL( KCRUidCommonUi );
       
   217     TInt value;
       
   218     err = variation->Get( KCuiMinDigitsToFind, value );
       
   219     delete variation;
       
   220     if ( err != KErrNone )
       
   221         {
       
   222         value = KItemFinderMinDigitsToFind;
       
   223         }
       
   224     return value;
       
   225   }
       
   226 
       
   227 EXPORT_C CItemFinder* CItemFinder::NewL( TInt aFindFlags )
       
   228     {
       
   229     CItemFinder* me = new (ELeave) CItemFinder( aFindFlags );
       
   230     CleanupStack::PushL( me );
       
   231     me->ConstructL();
       
   232     CleanupStack::Pop();
       
   233     return me;
       
   234     }
       
   235 
       
   236 EXPORT_C TBool CItemFinder::NextItemOrScrollL( TFindDirection aDirection )
       
   237     {
       
   238     TBool allowScroll = ETrue;
       
   239     if ( !iEditor || !(*iEditor)  )
       
   240         {
       
   241         return EFalse;
       
   242         }
       
   243     if ( aDirection == EInit || aDirection == EInitUp || aDirection == EInitDown )
       
   244         {
       
   245         if ( aDirection == EInitUp )
       
   246             {
       
   247             iPreviousDirection = ENextUp;
       
   248             iCurrentStart = iCurrentEnd = (*iEditor)->TextLength() - 1;
       
   249             if ( iCurrentStart > 0 )
       
   250                 {
       
   251                 (*iEditor)->SetCursorPosL( iCurrentEnd, EFalse );
       
   252                 if ( iAsyncParser && iAsyncParser->iMarkedItems && iAsyncParser->iMarkedItems->Count() > 0 )
       
   253                     // Check manually if the last item ends to last character in editor
       
   254                     // as CRichText can't handle this correctly
       
   255                     {
       
   256                     if ( iCurrentStart <= iAsyncParser->iMarkedItems->At( iAsyncParser->iMarkedItems->Count() - 1 )->iEnd )
       
   257                         {
       
   258                         ResolveAndSetItemTypeL( iAsyncParser->iMarkedItems->At( iAsyncParser->iMarkedItems->Count() - 1 )->iStart );
       
   259                         }
       
   260                     }
       
   261                 }
       
   262             }
       
   263         else if ( aDirection == EInitDown )
       
   264             {
       
   265             iPreviousDirection = ENextDown;
       
   266             (*iEditor)->SetCursorPosL(0,EFalse);
       
   267             ResolveAndSetItemTypeL(0);
       
   268             }
       
   269         iFirstVisible = (*iEditor)->TextLayout()->FirstDocPosFullyInBand();
       
   270         (*iEditor)->TextView()->SetCursorVisibilityL( TCursor::EFCursorInvisible, TCursor::EFCursorInvisible );
       
   271         if ( iPreviousDirection == 0 )// just initialising
       
   272             {
       
   273             (*iEditor)->SetCursorPosL( iFirstVisible, EFalse );
       
   274             return EFalse;
       
   275             }
       
   276         // Search first tag on screen
       
   277         // and set the cursor but if none found, don't scroll
       
   278         allowScroll=EFalse;
       
   279         aDirection = iPreviousDirection;
       
   280         // check if we didn't scroll full display but only part of it
       
   281         TPoint dummy;
       
   282         if ( iCurrentStart != iCurrentEnd && (*iEditor)->TextLayout()->PosInBand( iCurrentStart, dummy ) )
       
   283             {
       
   284             (*iEditor)->SetCursorPosL( iCurrentStart, EFalse );
       
   285             if ( (*iEditor)->TextLayout()->PosInBand( iCurrentEnd, dummy ) )
       
   286                 {
       
   287                 // old selection should remain. basically this should be
       
   288                 // the case only when tag was partly visible in previous screen
       
   289                 (*iEditor)->SetSelectionL( iCurrentStart, iCurrentEnd );
       
   290                 return ETrue;
       
   291                 }
       
   292             }
       
   293         else if ( iPreviousDirection == ENextDown )
       
   294             { // to ensure correct scrolling of items
       
   295             (*iEditor)->SetCursorPosL( iFirstVisible, EFalse );
       
   296             }
       
   297         }
       
   298     TBool ret = EFalse;
       
   299     TInt nextItem = KErrNotFound;
       
   300     // Scroll cursor over tag or update page.
       
   301     iPreviousDirection = aDirection;
       
   302     TInt cursorPos = (*iEditor)->CursorPos();
       
   303     if ( aDirection == ENextDown )
       
   304         {
       
   305         if ( (*iEditor)->SelectionLength() )
       
   306             {
       
   307             cursorPos = iCurrentEnd;
       
   308             }
       
   309         if ( cursorPos == 0 )
       
   310             {
       
   311             ResolveAndSetItemTypeL( 0 );
       
   312             if ( iCurrentEnd != iCurrentStart )
       
   313                 {
       
   314                 TPoint pos;
       
   315                 if ( ((*iEditor)->TextLayout()->PosInBand( iCurrentEnd, pos ) ) ) // tag does not continue over screen
       
   316                     {
       
   317                     NextItemOrScrollL( EInit ); // will set the selection
       
   318                     return ETrue;
       
   319                     }
       
   320                 }
       
   321             }
       
   322         nextItem = (*iEditor)->RichText()->PositionOfNextTag( cursorPos, this );
       
   323         if ( nextItem != KErrNotFound )
       
   324             { // check whether the tag is on visible screen
       
   325             TPoint dummy;
       
   326             if ( !(*iEditor)->TextLayout()->PosInBand( nextItem, dummy ) )
       
   327                 {
       
   328                 nextItem = KErrNotFound;
       
   329                 }
       
   330             }
       
   331         if ( allowScroll && nextItem == KErrNotFound )
       
   332             {
       
   333             (*iEditor)->MoveDisplayL( TCursorPosition::EFPageDown );
       
   334             if ( (*iEditor)->TextLayout()->FirstDocPosFullyInBand() != iFirstVisible )
       
   335                 {// If keypress was effective.
       
   336                 ret = ETrue;
       
   337                 NextItemOrScrollL( EInit );
       
   338                 }
       
   339             }
       
   340         }
       
   341     else
       
   342         {
       
   343         if ( (*iEditor)->SelectionLength() )
       
   344             {
       
   345             cursorPos = iCurrentStart;
       
   346             }
       
   347         nextItem = (*iEditor)->RichText()->PositionOfPrevTag( cursorPos, this );
       
   348         /* if nextItem is KErrNotFound can mean cursorPos is in the middel of an valid item.
       
   349          * so if cursorPos is in the middle of an vaild item, make sure that we adjust it to 
       
   350          * end of the item so that PositionOfPrevTag works fine
       
   351          */
       
   352         if( nextItem == KErrNotFound )
       
   353             {
       
   354             if ( cursorPos > 0 )
       
   355                 {
       
   356                 cursorPos -= 1;
       
   357                 TInt temp = (*iEditor)->RichText()->PositionOfNextTag( cursorPos, this );
       
   358                 if( temp != KErrNotFound )
       
   359                     {
       
   360                     cursorPos = temp;
       
   361                     }
       
   362                 else
       
   363                     {
       
   364                     cursorPos = ( *iEditor )->TextLength();
       
   365                     }
       
   366                 }
       
   367             nextItem = ( *iEditor )->RichText()->PositionOfPrevTag( cursorPos, this );
       
   368             }
       
   369         if ( nextItem >=0 && nextItem < iFirstVisible )
       
   370             {
       
   371             nextItem = KErrNotFound;
       
   372             }
       
   373         if ( allowScroll && nextItem == KErrNotFound )
       
   374             {
       
   375             (*iEditor)->MoveDisplayL( TCursorPosition::EFPageUp );
       
   376             TInt currPos = (*iEditor)->TextLayout()->FirstDocPosFullyInBand();
       
   377             if ( currPos != iFirstVisible )
       
   378                 {// If keypress was effective.
       
   379                 ret = ETrue;
       
   380                 NextItemOrScrollL( EInit );
       
   381                 }
       
   382             }
       
   383         }
       
   384     if ( nextItem != KErrNotFound || !allowScroll )
       
   385         {
       
   386         // Check !allowScroll for the case display was scrolled but previous item is still visible
       
   387         // and no new tag found, just make the selection visible again
       
   388         ret = ETrue;
       
   389         if ( nextItem != KErrNotFound )
       
   390             {
       
   391             iCurrentStart = nextItem;
       
   392             ResolveAndSetItemTypeL();
       
   393             }
       
   394         if ( iCurrentItemExt->iItemType != ENoneSelected )
       
   395             {
       
   396             TPoint pos;
       
   397             if ( ( !(*iEditor)->TextLayout()->PosInBand( iCurrentEnd ,pos ) ) ) // tag continues over screen
       
   398                 {
       
   399                 // lets check if we can scroll to show whole tag
       
   400                 // if not, we'll just show what can be fitted to screen with hl
       
   401                 (*iEditor)->TextLayout()->DocPosToXyPosL( iFirstVisible, pos );
       
   402                 TRect lineRect;
       
   403                 TPoint tagStart;
       
   404                 (*iEditor)->TextLayout()->GetLineRect( pos.iY, lineRect );
       
   405                 (*iEditor)->TextLayout()->DocPosToXyPosL( iCurrentStart, tagStart );
       
   406                 if (!lineRect.Contains(tagStart) && allowScroll )
       
   407                     {
       
   408                     (*iEditor)->MoveDisplayL( TCursorPosition::EFPageDown );
       
   409                     while ( !(*iEditor)->TextLayout()->PosInBand( iCurrentStart, pos ) )
       
   410                         {
       
   411                         (*iEditor)->MoveDisplayL( TCursorPosition::EFLineUp );
       
   412                         }
       
   413                     NextItemOrScrollL(EInit);
       
   414                     }
       
   415                 else if ( !lineRect.Contains( tagStart ) )
       
   416                     {
       
   417                     // we are not allowed to scroll, dont show highligh
       
   418                     iCurrentStart = iCurrentEnd = iFirstVisible;
       
   419                     ResetCurrentItem();
       
   420                     return ret;
       
   421                     }
       
   422                 }
       
   423             else if ( nextItem == KErrNotFound )
       
   424                 {
       
   425                 // if the current end visible,and next item invisible, no select
       
   426                 iCurrentStart = iCurrentEnd = iFirstVisible;
       
   427                 ResetCurrentItem();
       
   428                 return ret;
       
   429                 }
       
   430             }
       
   431         if ( iCurrentStart < iCurrentEnd )
       
   432             {
       
   433             (*iEditor)->SetSelectionL( iCurrentStart, iCurrentEnd );
       
   434             }
       
   435         else
       
   436             {
       
   437             ResetCurrentItem(); // no item selected
       
   438             }
       
   439         }
       
   440     return ret;
       
   441     }
       
   442 
       
   443 EXPORT_C void CItemFinder::SetFindModeL( TInt aFindFlags )
       
   444     {
       
   445     if ( iFlags != aFindFlags )
       
   446         {
       
   447         iFlags = aFindFlags;
       
   448         if ( iEditor && *iEditor )
       
   449             {
       
   450             User::LeaveIfError ( RefreshEditor() );
       
   451             }
       
   452         }
       
   453     if ( !aFindFlags && iEditor && *iEditor )
       
   454         {
       
   455         if (!iExternalObserver) // do not align if no control to scrolling
       
   456             {
       
   457             iCurrentEnd = iCurrentStart;
       
   458             iFirstVisible = (*iEditor)->TextLayout()->FirstDocPosFullyInBand();
       
   459             (*iEditor)->SetCursorPosL( iFirstVisible, EFalse );
       
   460             }
       
   461         ResetCurrentItem();
       
   462         }
       
   463     }
       
   464 
       
   465 EXPORT_C void CItemFinder::SetEditor( CEikRichTextEditor** aEditor )
       
   466     {
       
   467     iEditor=aEditor;
       
   468     if ( aEditor && *aEditor && (*aEditor)->TextLength() )
       
   469         {
       
   470         TRAP_IGNORE( (*aEditor)->SetHighlightStyleL( EEikEdwinHighlightLink ) );
       
   471         if ( iAsyncParser )
       
   472             {
       
   473             // We are changing the editor used, strange.
       
   474             delete iAsyncParser;
       
   475             iAsyncParser = 0;
       
   476             }
       
   477         iMarkedArrayComplete = EFalse;
       
   478         TRAPD( err, iAsyncParser = CItemFinderAsyncParser::NewL( *iEditor, &iFirstVisible, iMinDigitsToFind ) ); // can't signal failure to client.
       
   479         if ( !err )
       
   480             {
       
   481             iAsyncParser->SetCallbackObserver( this );
       
   482             }
       
   483         }
       
   484     }
       
   485 
       
   486 // From MParser
       
   487 EXPORT_C TBool CItemFinder::ParseThisText(
       
   488     const CRichText& aTextObj,
       
   489     TBool /*aAllowBack*/,
       
   490     TInt aStartScan,
       
   491     TInt aScanLength,
       
   492     TInt& aStartTag,
       
   493     TInt& aTagLength )
       
   494     {
       
   495     TBool ret = EFalse;
       
   496     if ( iEditor && *iEditor && (*iEditor)->RichText() != &aTextObj )
       
   497         {
       
   498         return ret;
       
   499         }
       
   500     if ( !iAsyncParser || iAsyncParser->IsActive() || !iAsyncParser->iMarkedItems )
       
   501         {
       
   502         return ret; // Asynch parser not ready
       
   503         }
       
   504     TInt lastInRange = aStartScan + aScanLength;
       
   505     aStartTag = lastInRange;
       
   506     CFindItemEngine::SFoundItem item = { 0, 0 };
       
   507     HBufC* tag = 0;
       
   508     TInt engineFlags = EngineFlags();
       
   509     // Find (next) external item.
       
   510     CFindItemExt* externalItem = NULL;
       
   511     if ( iExternalLinks )
       
   512         {
       
   513         TInt externalIndex = 0;
       
   514         while ( externalIndex < iExternalLinks->Count() )
       
   515             {
       
   516             CFindItemExt* tmp = iExternalLinks->At( externalIndex );
       
   517             if ( tmp && ( tmp->iStart >= aStartScan ))
       
   518                 {
       
   519                 externalItem = tmp;
       
   520                 switch( externalItem->iItemType )
       
   521                     {
       
   522                     case EUrlAddress:
       
   523                         item.iItemType = CFindItemEngine::EFindItemSearchURLBin;
       
   524                         break;
       
   525                     case EUriScheme:
       
   526                         item.iItemType = CFindItemEngine::EFindItemSearchScheme;
       
   527                         break;
       
   528                     default: // only EUrlAddress and EUriScheme supported
       
   529                         item.iItemType = (CFindItemEngine::TFindItemSearchCase)0;
       
   530                         break;
       
   531                     }
       
   532                 if(item.iItemType&engineFlags)
       
   533                 	{
       
   534                 	tag = externalItem->iItemDescriptor->Des().Alloc(); // Null if failed.
       
   535                 	item.iStartPos = externalItem->iStart;
       
   536                     item.iLength = externalItem->iEnd - item.iStartPos + 1;
       
   537                 	break;
       
   538                 	}
       
   539                 }
       
   540             externalIndex++;
       
   541             }
       
   542         }
       
   543     // Find (next) internal item.
       
   544     iAsyncParser->iFIE->ResetPosition();
       
   545     CFindItemEngine::SFoundItem internalItem = { 0, 0 };
       
   546     if ( iAsyncParser->iFIE->Item( internalItem ) )
       
   547         {
       
   548         do
       
   549             {
       
   550             if ( ( internalItem.iStartPos >= aStartScan ) && ( internalItem.iItemType & engineFlags ) )
       
   551                 {
       
   552                 CFindItemEngine::SFoundItem scrollItem = { 0, 0 };
       
   553                 while ( iAsyncParser->iFIE->NextItem( scrollItem ) ) // Find longest overridden item.
       
   554                     {
       
   555                     if ( scrollItem.iStartPos == internalItem.iStartPos )
       
   556                         {
       
   557                         if ( internalItem.iLength == scrollItem.iLength )
       
   558                             {
       
   559                             if ( internalItem.iItemType & CFindItemEngine::EFindItemSearchScheme ) // Check if valid scheme.
       
   560                                 {
       
   561                                 if ( !SchemeSupported( (*iEditor)->Text()->Read( internalItem.iStartPos, internalItem.iLength ) ) )
       
   562                                     {
       
   563                                     internalItem = scrollItem;
       
   564                                     }
       
   565                                 }
       
   566                             }
       
   567                         else if ( ( scrollItem.iItemType & engineFlags ) && ( internalItem.iLength < scrollItem.iLength ) )
       
   568                             {
       
   569                             internalItem = scrollItem;
       
   570                             }
       
   571                         else if ( ( scrollItem.iItemType & CFindItemEngine::EFindItemSearchURLBin )
       
   572                                   && ( internalItem.iLength > scrollItem.iLength ) 
       
   573                                   && !SchemeSupported( (*iEditor)->Text()->Read( internalItem.iStartPos, internalItem.iLength ) ) )
       
   574                             {
       
   575                             // this is because URL is included in URI scheme
       
   576                             internalItem = scrollItem;
       
   577                             }
       
   578                         }
       
   579                     else
       
   580                         {
       
   581                         iAsyncParser->iFIE->PrevItem(scrollItem);
       
   582                         break;
       
   583                         }
       
   584                     }
       
   585                if ( internalItem.iItemType & CFindItemEngine::EFindItemSearchScheme ) // Check if valid scheme.
       
   586                     {
       
   587                     if ( SchemeSupported( (*iEditor)->Text()->Read( internalItem.iStartPos, internalItem.iLength ) ) )
       
   588                         {
       
   589                         break;
       
   590                         }
       
   591                     }
       
   592                 else if ( internalItem.iLength >= MinLengthForItemType( internalItem.iItemType ) ) // Check if valid length.
       
   593                     {
       
   594                     break;
       
   595                     }
       
   596                 }
       
   597             } while ( iAsyncParser->iFIE->NextItem( internalItem ) );
       
   598         }
       
   599    
       
   600     // Use internal item as item.
       
   601     TBool internalUsed( EFalse );
       
   602     if ( ( internalItem.iLength >0 ) && (internalItem.iStartPos>=aStartScan) &&( internalItem.iItemType&engineFlags )&& ( !externalItem || ( internalItem.iStartPos + internalItem.iLength - 1 ) < externalItem->iStart ) )
       
   603         {
       
   604         item = internalItem;
       
   605         delete tag; // Allocated for external link.
       
   606         tag = (*iEditor)->Text()->Read( item.iStartPos, item.iLength ).Alloc(); // Null if failed.
       
   607         internalUsed = ETrue;
       
   608         }
       
   609     // Add item as a marked item.
       
   610     if ( item.iStartPos >= aStartScan && ( item.iStartPos + item.iLength ) <= lastInRange &&
       
   611         item.iItemType & engineFlags &&
       
   612         ( ( internalUsed && item.iLength >= MinLengthForItemType( item.iItemType ) ) || !internalUsed ) &&
       
   613         tag )
       
   614         {
       
   615         TBool schemeNotSupported( EFalse );
       
   616         if ( item.iItemType & CFindItemEngine::EFindItemSearchScheme ) // Check if scheme valid.
       
   617             {
       
   618             if ( !SchemeSupported( tag->Des() ) )
       
   619                 {
       
   620                 schemeNotSupported = ETrue;
       
   621                 ret = EFalse;
       
   622                 }
       
   623             }
       
   624         if ( !schemeNotSupported ) // Add if valid item
       
   625             {
       
   626             aStartTag = item.iStartPos;
       
   627             aTagLength = item.iLength;
       
   628             TInt err = KErrNone;
       
   629             if ( !iMarkedArrayComplete )
       
   630                 {
       
   631                 // Resolve type and tag.
       
   632                 TItemType type = ENoneSelected;
       
   633                 switch( item.iItemType )
       
   634                     {
       
   635                     case CFindItemEngine::EFindItemSearchURLBin:
       
   636                         type = EUrlAddress;
       
   637                         break;
       
   638                     case CFindItemEngine::EFindItemSearchMailAddressBin:
       
   639                         type = EEmailAddress;
       
   640                         break;
       
   641                     case CFindItemEngine::EFindItemSearchPhoneNumberBin:
       
   642                         type = EPhoneNumber;
       
   643                         break;
       
   644                     case CFindItemEngine::EFindItemSearchScheme:
       
   645                         {
       
   646                         type = EUriScheme;
       
   647                         const TDesC& pref = tag->Des().Left( 4 );
       
   648                         if ( pref.CompareF( KHTTPPREFIX().Left( 4 ) ) == 0 || pref.CompareF( RTSP ) == 0 )
       
   649                             {
       
   650                             type = EUrlAddress;
       
   651                             }
       
   652                         }
       
   653                         break;
       
   654                     default:
       
   655                         break;
       
   656                     }
       
   657                 CFindItemExt* newItem = NULL;
       
   658                 TRAP( err, // Non-leaving method
       
   659                     {
       
   660                     newItem = new (ELeave) CFindItemExt();
       
   661                     newItem->iItemType = type;
       
   662                     newItem->iItemDescriptor = tag->Des().AllocL();
       
   663                     newItem->iStart = aStartTag;
       
   664                     newItem->iEnd = aStartTag + aTagLength - 1;
       
   665                     iAsyncParser->iMarkedItems->AppendL( newItem ); // Ownership changed.
       
   666                     newItem = NULL;
       
   667                     } );
       
   668                 delete newItem;
       
   669                 }
       
   670             if ( !err )
       
   671                 {
       
   672                 ret = ETrue;
       
   673                 }
       
   674             }
       
   675         }
       
   676     delete tag;
       
   677     if ( !ret || ( ( aStartTag + aTagLength ) == (*iEditor)->TextLength() ) ) // iMarkedList complete
       
   678         {
       
   679         iMarkedArrayComplete = ETrue;
       
   680         }
       
   681     return ret;
       
   682     }
       
   683 
       
   684 TInt CItemFinder::MinLengthForItemType( TInt aItemType )
       
   685     {
       
   686     TInt length = KMINTAGLENGTH; // by default
       
   687     if ( aItemType == CFindItemEngine::EFindItemSearchPhoneNumberBin )
       
   688         {
       
   689         length = iMinDigitsToFind; // For phone numbers
       
   690         }
       
   691     return length;
       
   692     }
       
   693 
       
   694 EXPORT_C const TDesC& CItemFinder::CreateDoItText(
       
   695     const CRichText& /*aTextObj*/,
       
   696     TInt /*aStartText*/,
       
   697     TInt /*aLength*/)
       
   698     {
       
   699     return KNullDesC();
       
   700     }
       
   701 
       
   702 EXPORT_C void CItemFinder::ActivateThisTextL(
       
   703     const CRichText& /*aTextObj*/,
       
   704     TInt /*aStartText*/,
       
   705     TInt /*aLength*/)
       
   706     {
       
   707     // We don't need this
       
   708     }
       
   709 
       
   710 EXPORT_C TBool CItemFinder::ReformatOnRecognise() const
       
   711     {
       
   712     return ETrue;
       
   713     }
       
   714 
       
   715 EXPORT_C TBool CItemFinder::ReformatOnRollover() const
       
   716     {
       
   717     return EFalse; // Rollover formating causes too much "unwanted" parsing.
       
   718     }
       
   719 
       
   720 EXPORT_C void CItemFinder::GetRecogniseFormat( TCharFormat& aFormat )
       
   721     {
       
   722     aFormat.iFontPresentation.iUnderline = EUnderlineOn;
       
   723     TRgb color( KRgbBlue );
       
   724     AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), color, KAknsIIDQsnHighlightColors,EAknsCIQsnHighlightColorsCG3 );
       
   725     aFormat.iFontPresentation.iTextColor = color;
       
   726     }
       
   727 
       
   728 EXPORT_C void CItemFinder::GetRolloverFormat( TCharFormat& /*aFormat*/ )
       
   729     {
       
   730     }
       
   731 
       
   732 EXPORT_C TBool CItemFinder::ConfirmCursorOverTag(
       
   733     const CRichText& /*aTextObj*/,
       
   734     TInt /*aTagStart*/,
       
   735     TInt /*aTagLen*/,
       
   736     TInt /*aCurPos*/)
       
   737     {
       
   738     return ETrue;
       
   739     }
       
   740 
       
   741 EXPORT_C void CItemFinder::Release()
       
   742     {
       
   743     iEditor = 0; // This makes parser to ignore practically all request from outside
       
   744     }
       
   745 
       
   746 EXPORT_C void CItemFinder::MParser_Reserved_2()
       
   747     {
       
   748     }
       
   749 
       
   750 EXPORT_C void CItemFinder::ResetCurrentItem()
       
   751     {
       
   752     if ( iCurrentItemExt )
       
   753         {
       
   754         iCurrentItemExt->iItemType = ENoneSelected;
       
   755         delete iCurrentItemExt->iItemDescriptor;
       
   756         iCurrentItemExt->iItemDescriptor = 0;
       
   757         iCurrentItemExt->iStart = 0;
       
   758         iCurrentItemExt->iEnd = 0;
       
   759         }
       
   760     }
       
   761 
       
   762 EXPORT_C TInt CItemFinder::PositionOfNextItem( TFindDirection aDirection )
       
   763     {
       
   764     if ( iAsyncParser && !iAsyncParser->IsActive() ) // exists only when editor is set
       
   765         {
       
   766         // Going down
       
   767         if ( aDirection != ENextUp )
       
   768             {
       
   769             if ( (*iEditor)->CursorPos() == 0 && // check if the first char starts the tag
       
   770                 iCurrentItemExt->iItemType == ENoneSelected &&
       
   771                 iAsyncParser->iMarkedItems &&
       
   772                 iAsyncParser->iMarkedItems->Count() > 0 &&
       
   773                 iAsyncParser->iMarkedItems->At(0)->iStart == 0 )
       
   774                 {
       
   775                 return 0;
       
   776                 }
       
   777             return (*iEditor)->RichText()->PositionOfNextTag( (*iEditor)->CursorPos(), this );
       
   778             }
       
   779         else
       
   780             {
       
   781             return (*iEditor)->RichText()->PositionOfPrevTag( (*iEditor)->CursorPos(), this );
       
   782             }
       
   783         }
       
   784     return KErrNotFound;
       
   785     }
       
   786 
       
   787 EXPORT_C void CItemFinder::ResolveAndSetItemTypeL( TInt aStart ) // defaults to KErrNotFound
       
   788     {
       
   789     if ( aStart != KErrNotFound )
       
   790         {
       
   791         iCurrentStart = aStart;
       
   792         }
       
   793     ResetCurrentItem(); // Reset item.
       
   794     if ( !iAsyncParser || iAsyncParser->IsActive() ) // Text not parsed
       
   795         {
       
   796         return;
       
   797         }
       
   798     iCurrentEnd = iCurrentStart;
       
   799     TInt count = iAsyncParser->iMarkedItems->Count();
       
   800     for ( TInt i = 0; i < count; i++ ) // Set item.
       
   801         {
       
   802         if ( iAsyncParser->iMarkedItems->At( i )->iStart == iCurrentStart )
       
   803             {
       
   804             iCurrentItemExt->iStart = iAsyncParser->iMarkedItems->At( i )->iStart;
       
   805             iCurrentStart = iCurrentItemExt->iStart;
       
   806             iCurrentItemExt->iEnd = iAsyncParser->iMarkedItems->At( i )->iEnd;
       
   807             iCurrentEnd = iCurrentItemExt->iEnd + 1;
       
   808             if ( iAsyncParser->iMarkedItems->At( i )->iItemDescriptor )
       
   809                 {
       
   810                 delete iCurrentItemExt->iItemDescriptor;
       
   811                 iCurrentItemExt->iItemDescriptor = 0;
       
   812                 iCurrentItemExt->iItemDescriptor = iAsyncParser->iMarkedItems->At( i )->iItemDescriptor->AllocL();
       
   813                 }
       
   814             DoResolveAndSetItemTypeL( iAsyncParser->iMarkedItems->At( i ) );
       
   815             break;
       
   816             }
       
   817         }
       
   818     }
       
   819 
       
   820 EXPORT_C void CItemFinder::AddObserver( MItemFinderObserver& aObserver )
       
   821     {
       
   822     iExternalObserver = &aObserver;
       
   823     }
       
   824 
       
   825 // Utilities
       
   826 TInt CItemFinder::EngineFlags()
       
   827     {
       
   828     TInt fieFlags( 0 );
       
   829     if ( iFlags & EUrlAddress )
       
   830         {
       
   831         fieFlags |= CFindItemEngine::EFindItemSearchURLBin;
       
   832         }
       
   833     if ( iFlags & EEmailAddress )
       
   834         {
       
   835         fieFlags |= CFindItemEngine::EFindItemSearchMailAddressBin;
       
   836         }
       
   837     if ( iFlags & EPhoneNumber )
       
   838         {
       
   839         fieFlags |= CFindItemEngine::EFindItemSearchPhoneNumberBin;
       
   840         }
       
   841     if ( iFlags & EUrlAddress || iFlags & EUriScheme )
       
   842         {
       
   843         fieFlags |= CFindItemEngine::EFindItemSearchScheme;
       
   844         }
       
   845     return fieFlags;
       
   846     }
       
   847 
       
   848 void CItemFinder::InsertPrefixToUrl()
       
   849     {
       
   850     if ( iCurrentItemExt && iCurrentItemExt->iItemType == EUrlAddress )
       
   851         {
       
   852         const TDesC& pref = iCurrentItemExt->iItemDescriptor->Des().Left( 4 );
       
   853         if ( pref.CompareF( KHTTPPREFIX().Left( 4 ) ) == 0 || pref.CompareF( RTSP ) == 0 )
       
   854             {
       
   855             return; // prefix already exists.
       
   856             }
       
   857         HBufC* tmp = iCurrentItemExt->iItemDescriptor->ReAlloc( iCurrentItemExt->iItemDescriptor->Length() + KHTTPPREFIX().Length() );
       
   858         if ( tmp )
       
   859             {
       
   860             iCurrentItemExt->iItemDescriptor = tmp;
       
   861             iCurrentItemExt->iItemDescriptor->Des().Insert( 0, KHTTPPREFIX );
       
   862             }
       
   863         }
       
   864     }
       
   865 
       
   866 TBool CItemFinder::SchemeSupported( const TDesC& aScheme )
       
   867     {
       
   868     if ( aScheme.Left( KTELPREFIX().Length() ).CompareF( KTELPREFIX ) == 0 )
       
   869         {
       
   870         if ( CommonPhoneParser::IsValidPhoneNumber( aScheme.Mid( 4 ), CommonPhoneParser::EPlainPhoneNumber) )
       
   871             {
       
   872             return EFalse; // will be handled as pure phone number later on.
       
   873             }
       
   874         }
       
   875     if ( iFlags & EUrlAddress || iFlags & EUriScheme )
       
   876         {
       
   877         TInt schLength = aScheme.Locate( ':' );
       
   878         if ( schLength > 0 )
       
   879             {
       
   880             TInt suppCount = iSchemeResolver->SupportedSchemes().Count();
       
   881             for ( TInt i = 0; i < suppCount; i++ )
       
   882                 {
       
   883                 if ( aScheme.Length() >= schLength && iSchemeResolver->SupportedSchemes().At(i)->Des().CompareF( aScheme.Left( schLength ) ) == 0)
       
   884                     {
       
   885                     return ETrue;
       
   886                     }
       
   887                 }
       
   888             }
       
   889         }
       
   890     return EFalse;
       
   891     }
       
   892 
       
   893 TBool CItemFinder::CallbackToExtObserver()
       
   894     {
       
   895     if ( iExternalObserver )
       
   896         {
       
   897         iExternalObserver->HandleParsingComplete();
       
   898         return ETrue;
       
   899         }
       
   900     return EFalse;
       
   901     }
       
   902 
       
   903 EXPORT_C TBool CItemFinder::ItemWasTappedL( const TPoint aTappedPoint )
       
   904     {
       
   905     if ( !iAsyncParser || iAsyncParser->IsActive() )
       
   906         {
       
   907         return EFalse;
       
   908         }
       
   909     TInt pos = 0;
       
   910     TInt len = (*iEditor)->TextLayout()->PosRangeInBand( pos );
       
   911     TRect rect;
       
   912     TInt i = 0;
       
   913     while ( i < iAsyncParser->iMarkedItems->Count() ) // Check visible items
       
   914         {
       
   915         TInt end = iAsyncParser->iMarkedItems->At( i )->iEnd;
       
   916         if ( end < pos )
       
   917             {
       
   918              i++;
       
   919             continue; // Item not visible.
       
   920             };
       
   921         TInt start = iAsyncParser->iMarkedItems->At( i )->iStart;
       
   922         if ( start >= ( pos + len ) )
       
   923             {
       
   924             break; // Item not visible.
       
   925             }
       
   926         TInt lastLine = (*iEditor)->TextLayout()->GetLineNumber( end );
       
   927         TInt nextLine = 0;
       
   928         TInt lastPos = start;
       
   929         do // Check all rects of one item.
       
   930             {
       
   931             rect = (*iEditor)->TextLayout()->GetLineRectL( start, end );
       
   932             if ( rect.Contains( aTappedPoint ) ) // Item rect tapped.
       
   933                 {
       
   934                 iFirstVisible = (*iEditor)->TextLayout()->FirstDocPosFullyInBand();
       
   935                 ResetCurrentItem();
       
   936                 iCurrentItemExt->iStart = iAsyncParser->iMarkedItems->At( i )->iStart;
       
   937                 iCurrentStart = iCurrentItemExt->iStart;
       
   938                 iCurrentItemExt->iEnd = iAsyncParser->iMarkedItems->At( i )->iEnd;
       
   939                 iCurrentEnd = iCurrentItemExt->iEnd + 1;
       
   940                 DoResolveAndSetItemTypeL( iAsyncParser->iMarkedItems->At( i ) );
       
   941                 (*iEditor)->SetSelectionL( iCurrentEnd, iCurrentStart );
       
   942                 return ETrue; // Hit
       
   943                 }
       
   944             TPoint midPoint( rect.iBr.iX, ( rect.iBr.iY + rect.iTl.iY ) / 2 );
       
   945             lastPos = (*iEditor)->TextLayout()->XyPosToDocPosL( midPoint );
       
   946             start = lastPos + 1;
       
   947             nextLine = (*iEditor)->TextLayout()->GetLineNumber( lastPos );
       
   948             } while ( nextLine != lastLine );
       
   949         i++;
       
   950         }
       
   951     return EFalse; // No hit
       
   952     }
       
   953 
       
   954 void CItemFinder::DoResolveAndSetItemTypeL( const CFindItemExt* aItem )
       
   955     {
       
   956     if ( aItem )
       
   957         {
       
   958         iCurrentItemExt->iItemType = aItem->iItemType;
       
   959         if ( aItem->iItemType != ENoneSelected && iCurrentEnd >= iCurrentStart )
       
   960             {
       
   961             if ( !iCurrentItemExt->iItemDescriptor )
       
   962                 {
       
   963                 iCurrentItemExt->iItemDescriptor = aItem->iItemDescriptor->AllocL();
       
   964                 }
       
   965             if ( iCurrentItemExt->iItemType == EUrlAddress )
       
   966                 {
       
   967                 InsertPrefixToUrl(); // old url types need prefix in order to work w/ schemehandler
       
   968                 }
       
   969             if ( iCurrentItemExt->iItemType == EUriScheme )
       
   970                 {
       
   971                 // some schemes (ie. "old ones") have special handling
       
   972                 const TDesC& pref = iCurrentItemExt->iItemDescriptor->Des().Left( 4 );
       
   973                 if ( pref.CompareF( KHTTPPREFIX().Left( 4 ) ) == 0 || pref.CompareF( RTSP ) == 0 )
       
   974                     {
       
   975                     iCurrentItemExt->iItemType = EUrlAddress;
       
   976                     }
       
   977                 }
       
   978             }
       
   979         }
       
   980     }
       
   981 
       
   982 EXPORT_C TInt CItemFinder::SetExternalLinks( CArrayPtrFlat<CFindItemExt>* aLinks )
       
   983     {
       
   984     TInt error = KErrNone;
       
   985     if ( iExternalLinks ) // Remove existing links.
       
   986         {
       
   987         iExternalLinks->ResetAndDestroy();
       
   988         delete iExternalLinks;
       
   989         iExternalLinks = 0;
       
   990         }
       
   991     // Add an external link validated by engine
       
   992     TInt linkCount = aLinks ? aLinks->Count() : 0;
       
   993     if ( linkCount > 0 )
       
   994         {
       
   995         iExternalLinks = new CArrayPtrFlat<CItemFinder::CFindItemExt>( linkCount );
       
   996         if ( !iExternalLinks ) // Error: no memory.
       
   997             {
       
   998             return EFalse;
       
   999             }
       
  1000         CFindItemEngine* fie = NULL; // For validation.
       
  1001         TInt linkIndex = 0;
       
  1002         do
       
  1003             {
       
  1004             CFindItemExt* link = aLinks->At( linkIndex++ );                   
       
  1005             TInt flag = 0;
       
  1006             switch ( link->iItemType )
       
  1007                 {
       
  1008                 case EUrlAddress:
       
  1009                     flag = CFindItemEngine::EFindItemSearchURLBin;
       
  1010                     break;
       
  1011                 case EUriScheme:                    
       
  1012                     if ( !SchemeSupported( link->iItemDescriptor->Des() ) )
       
  1013                         {
       
  1014                         continue;
       
  1015                         } 
       
  1016                     flag = CFindItemEngine::EFindItemSearchScheme;                        
       
  1017                     break;
       
  1018                 default: // Ignore unsupported types.
       
  1019                     continue;
       
  1020                 }                                                   
       
  1021             if ( !fie )
       
  1022                 {
       
  1023                 TRAP( error, fie = CFindItemEngine::NewL( link->iItemDescriptor->Des(), (CFindItemEngine::TFindItemSearchCase)flag ) );
       
  1024                 }
       
  1025             else
       
  1026                 {
       
  1027                 TRAP( error, fie->DoNewSearchL( link->iItemDescriptor->Des(), (CFindItemEngine::TFindItemSearchCase)flag ) );
       
  1028                 }
       
  1029             if ( error != KErrNone ) // Error: find engine fails.
       
  1030                 {
       
  1031                 iExternalLinks->ResetAndDestroy();
       
  1032                 delete iExternalLinks;
       
  1033                 iExternalLinks = 0;
       
  1034                 delete fie;
       
  1035                 return EFalse;                
       
  1036                 }                
       
  1037             if ( fie->ItemCount() ) // Link was found.
       
  1038                 {                
       
  1039                 CFindItemEngine::SFoundItem item = fie->ItemArray()->At( 0 );
       
  1040                 const TDesC& text = link->iItemDescriptor->Des().Mid( item.iStartPos, item.iLength );
       
  1041                 if ( link->iItemDescriptor->Des().CompareF( text ) == 0 )
       
  1042                     {                    
       
  1043                     CFindItemExt* newItem = 0;                    
       
  1044                     newItem = new CFindItemExt();
       
  1045                     error = KErrNoMemory;                                        
       
  1046                     if ( newItem )
       
  1047                         {                        
       
  1048                         newItem->iItemDescriptor = link->iItemDescriptor->Alloc();
       
  1049                         if ( newItem->iItemDescriptor )
       
  1050                             {                                                                                                                                                                 
       
  1051                             newItem->iItemType = link->iItemType;
       
  1052                             newItem->iStart = link->iStart;
       
  1053                             newItem->iEnd = link->iEnd;
       
  1054                             error = KErrNone;
       
  1055                             TRAP( error, iExternalLinks->AppendL( newItem ) );                                                        
       
  1056                             }
       
  1057                         }                                                                 
       
  1058                      if ( error != KErrNone ) // Error: cannot set ext. links.
       
  1059                         {
       
  1060                         iExternalLinks->ResetAndDestroy();
       
  1061                         delete iExternalLinks;
       
  1062                         iExternalLinks = 0;
       
  1063                         delete newItem->iItemDescriptor;
       
  1064                         delete newItem;
       
  1065                         delete fie;
       
  1066                         return EFalse;
       
  1067                         }                                                                     
       
  1068                     }
       
  1069                 }                       
       
  1070             }
       
  1071         while ( linkIndex < linkCount );                
       
  1072         delete fie; 
       
  1073         }
       
  1074     error = RefreshEditor(); // With ext. links.
       
  1075     if ( error != KErrNone )
       
  1076         {
       
  1077         iExternalLinks->ResetAndDestroy();
       
  1078         delete iExternalLinks;
       
  1079         iExternalLinks = 0;
       
  1080         (void)RefreshEditor();
       
  1081         }    
       
  1082     return error;
       
  1083     }
       
  1084 
       
  1085 EXPORT_C CItemFinder::CFindItemExt& CItemFinder::CurrentItemExt()
       
  1086     {
       
  1087     return *iCurrentItemExt;
       
  1088     }
       
  1089 
       
  1090 EXPORT_C TPtrC CItemFinder::CurrentSelection()
       
  1091     {
       
  1092     if ( iEditor && *iEditor ) // if editor used.
       
  1093         {
       
  1094         return (*iEditor)->Text()->Read( (*iEditor)->Selection().LowerPos(), (*iEditor)->Selection().Length() );      
       
  1095         }
       
  1096     else
       
  1097         {
       
  1098         HBufC* buffer = CurrentItemExt().iItemDescriptor;
       
  1099         if ( buffer )
       
  1100             {
       
  1101             return *buffer;
       
  1102             }
       
  1103         else
       
  1104             {
       
  1105             return KNullDesC();
       
  1106             }
       
  1107         }
       
  1108     }
       
  1109 
       
  1110 TInt CItemFinder::RefreshEditor()
       
  1111     {
       
  1112     TInt error = KErrNone;
       
  1113     TRAP( error, // Non-leaving method.
       
  1114         {
       
  1115         if ( iAsyncParser )
       
  1116             {
       
  1117             iFirstVisible = (*iEditor)->TextLayout()->FirstDocPosFullyInBand();
       
  1118             iMarkedArrayComplete = EFalse;
       
  1119             if ( iAsyncParser->iMarkedItems )
       
  1120                 {
       
  1121                 iAsyncParser->iMarkedItems->ResetAndDestroy();
       
  1122                 }
       
  1123             (*iEditor)->RefreshParsersL();
       
  1124             (*iEditor)->SetCursorPosL( 0, EFalse );
       
  1125             ResolveAndSetItemTypeL( iFirstVisible );
       
  1126             (*iEditor)->SetCursorPosL( iFirstVisible, EFalse );
       
  1127             iPreviousDirection = ENextDown;
       
  1128             NextItemOrScrollL( EInit );
       
  1129             }
       
  1130         else if ( (*iEditor)->TextLength() )
       
  1131             {
       
  1132             iMarkedArrayComplete = EFalse;
       
  1133             iAsyncParser = CItemFinderAsyncParser::NewL( *iEditor, &iFirstVisible, iMinDigitsToFind );
       
  1134             iAsyncParser->SetCallbackObserver( this );
       
  1135             }
       
  1136         } ); // TRAP
       
  1137     return error;
       
  1138     }
       
  1139 
       
  1140 // End of File