|
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 |