messagingfw/msgsrvnstore/server/src/MSVFTEXT.CPP
changeset 0 8e480a14352b
equal deleted inserted replaced
-1:000000000000 0:8e480a14352b
       
     1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <txtrich.h>
       
    17 #include "MSVFTEXT.H"
       
    18 #include "MSVPANIC.H"
       
    19 
       
    20 //**********************************
       
    21 // CMsvFindText
       
    22 //**********************************
       
    23 
       
    24 EXPORT_C CMsvFindText* CMsvFindText::NewLC(TInt aPriority)
       
    25 /** Creates a new find text utility object with the specified priority and puts 
       
    26 a pointer to the new object onto the cleanup stack.
       
    27 
       
    28 The function leaves if the object cannot be created.
       
    29 
       
    30 @param aPriority The priority of this active object. 
       
    31 @return Pointer to the new find text utility object */
       
    32 	{
       
    33 	CMsvFindText* self = new(ELeave)CMsvFindText(aPriority);
       
    34 	CleanupStack::PushL(self);
       
    35 	return self;
       
    36 	}
       
    37 
       
    38 EXPORT_C CMsvFindText* CMsvFindText::NewL(TInt aPriority)
       
    39 /** Creates a new find text utility object with the specified priority.
       
    40 
       
    41 The function leaves if the object cannot be created.
       
    42 
       
    43 @param aPriority The priority of this active object. 
       
    44 @return Pointer to the new find text utility object */
       
    45 	{
       
    46 	CMsvFindText* self = NewLC(aPriority);
       
    47 	CleanupStack::Pop(); // self
       
    48 	return self;
       
    49 	}
       
    50 
       
    51 CMsvFindText::CMsvFindText(TInt aPriority)
       
    52 : CMsgActive(aPriority), iPreChar(' '), iPostChar(' ')
       
    53 	{
       
    54 	CActiveScheduler::Add(this);
       
    55 	}
       
    56 
       
    57 /** Destructor.
       
    58 
       
    59 Any outstanding search is cancelled.
       
    60 */
       
    61 EXPORT_C CMsvFindText::~CMsvFindText()
       
    62 	{
       
    63 	Cancel();
       
    64 
       
    65 	delete iBuf;
       
    66 	delete iFind;
       
    67 	}
       
    68 
       
    69 void CMsvFindText::Check()
       
    70 	{
       
    71 	TPtrC findPtr(iFind->Des());
       
    72 
       
    73 	__ASSERT_ALWAYS(findPtr.Length() > 0, PanicServer(EMsvNoFindTextSpecified));
       
    74 	__ASSERT_ALWAYS(findPtr.Length() <= KMsvMaxFindTextLength, PanicServer(EMsvTooMuchFindTextSpecified));
       
    75 	__ASSERT_ALWAYS(!IsActive(), PanicServer(EMsvFindTextAlreadyActive));
       
    76 	}
       
    77 
       
    78 void CMsvFindText::DoRunL()
       
    79 	{
       
    80 	iFoundText = DoFindStepL();
       
    81 
       
    82 	// Continue searching?
       
    83 	if (!iFoundText && (iSourcePos < iSourceLen))
       
    84 		{
       
    85 		TRequestStatus* status = &iStatus;
       
    86 		User::RequestComplete(status, KErrNone);
       
    87 		SetActive();
       
    88 		}
       
    89 	}
       
    90 
       
    91 void CMsvFindText::InitialiseL(const TDesC& aFind, const TDesC* aPlainSource, const CRichText* aRichSource, TMsvPartList aFlags)
       
    92 	{
       
    93 	iPlainText = aPlainSource;
       
    94 	iRichText = aRichSource;
       
    95 
       
    96 	// Get length of data
       
    97 	iSourceLen = iPlainText ? iPlainText->Length() : iRichText->DocumentLength();
       
    98 
       
    99 	iSourcePos = 0;
       
   100 	iFoundText = EFalse;
       
   101 
       
   102 	// Copy text to find
       
   103 	delete iFind; iFind = NULL;
       
   104 	iFind = HBufC::NewL(aFind.Length());
       
   105 	*iFind = aFind;
       
   106 
       
   107 	// Initialise members
       
   108 	iMaxRead = KMsvMaxFindTextLength + aFind.Length() - 1;
       
   109 	iFlags = aFlags;
       
   110 
       
   111 	// Create buffer
       
   112 	delete iBuf; iBuf = NULL;
       
   113 	iBuf = HBufC::NewL(iMaxRead + 1);
       
   114 
       
   115 	Check();
       
   116 
       
   117 	// Convert text to find to lower case if not case sensitive
       
   118 	if (!(iFlags & KMsvFindCaseSensitive))
       
   119 		iFind->Des().LowerCase();
       
   120 	}
       
   121 
       
   122 EXPORT_C void CMsvFindText::FindTextL(const TDesC& aFind, const TDesC& aSource, TMsvPartList aFlags, TRequestStatus& aStatus)
       
   123 /** Performs an asynchronous search for a text string within another text string.
       
   124 
       
   125 @param aFind The text string to search for. 
       
   126 @param aSource The plain text to be searched.
       
   127 @param aFlags A set of flags which modify the way the search works: KMsvFindCaseSensitive 
       
   128 means the search is successful only if there is an exact case match for the 
       
   129 text. KMsvFindWholeWord means the search is successful only if the matching 
       
   130 text in aSource is not delimited by alphanumeric characters.
       
   131 @param aStatus The request status object, which is set when the search operation 
       
   132 is complete. Use FoundText() to return the result of the search. */
       
   133 	{
       
   134 	InitialiseL(aFind, &aSource, NULL, aFlags);
       
   135 	DoFindAsyncL(aStatus);
       
   136 	}
       
   137 
       
   138 EXPORT_C void CMsvFindText::FindRichTextL(const TDesC& aFind, const CRichText& aSource, TMsvPartList aFlags, TRequestStatus& aStatus)
       
   139 /** Searches for a specified text string within the given rich text asynchronously.
       
   140 
       
   141 @param aFind The text string to search for.
       
   142 @param aSource The rich text to be searched.
       
   143 @param aFlags A set of flags which modify the way the search works: KMsvFindCaseSensitive 
       
   144 means the search is successful only if there is an exact case match for the 
       
   145 text. KMsvFindWholeWord means the search is successful only if the matching 
       
   146 text in aSource is not delimited by alphanumeric characters.
       
   147 @param aStatus The request status object, which is set when the search operation 
       
   148 is complete. Use FoundText() to return the result of the search. */
       
   149 	{
       
   150 	InitialiseL(aFind, NULL, &aSource, aFlags);
       
   151 	DoFindAsyncL(aStatus);
       
   152 	}
       
   153 
       
   154 void CMsvFindText::DoFindAsyncL(TRequestStatus& aStatus)
       
   155 	{
       
   156 	Queue(aStatus);
       
   157 	TRequestStatus* status = &iStatus;
       
   158 	User::RequestComplete(status, KErrNone);
       
   159 	SetActive();
       
   160 	}
       
   161 
       
   162 EXPORT_C TBool CMsvFindText::FindTextL(const TDesC& aFind, const TDesC& aSource, TMsvPartList aFlags)
       
   163 /** Performs a synchronous search for a text string within another text string.
       
   164 
       
   165 @param aFind The text string to search for. 
       
   166 @param aSource The plain text to be searched.
       
   167 @param aFlags A set of flags which modify the way the search works: KMsvFindCaseSensitive 
       
   168 means the search is successful only if there is an exact case match for the 
       
   169 text. KMsvFindWholeWord means the search is successful only if the matching 
       
   170 text in aSource is not delimited by alphanumeric characters.
       
   171 @return ETrue if there is a match, otherwise EFalse. */
       
   172 	{
       
   173 	InitialiseL(aFind, &aSource, NULL, aFlags);
       
   174 	return DoFindSyncL();
       
   175 	}
       
   176 
       
   177 EXPORT_C TBool CMsvFindText::FindRichTextL(const TDesC& aFind, const CRichText& aSource, TMsvPartList aFlags)
       
   178 /** Searches for a specified text string within the given rich text synchronously.
       
   179 
       
   180 @param aFind The text string to search for. 
       
   181 @param aSource The rich text to be searched.
       
   182 @param aFlags A set of flags which modify the way the search works: KMsvFindCaseSensitive 
       
   183 means the search is successful only if there is an exact case match for the 
       
   184 text. KMsvFindWholeWord means the search is successful only if the matching 
       
   185 text in aSource is not delimited by alphanumeric characters. 
       
   186 @return ETrue if there is a match, otherwise EFalse. */
       
   187 	{
       
   188 	InitialiseL(aFind, NULL, &aSource, aFlags);
       
   189 	return DoFindSyncL();
       
   190 	}
       
   191 
       
   192 TBool CMsvFindText::DoFindSyncL()
       
   193 	{
       
   194 	// Spin through source text
       
   195 	while(!iFoundText && iSourcePos < iSourceLen)
       
   196 		iFoundText = DoFindStepL();
       
   197 
       
   198 	return iFoundText;
       
   199 	}
       
   200 
       
   201 TBool CMsvFindText::DoFindStepL()
       
   202 	{
       
   203 	// Get amount of data to fetch
       
   204 	TInt toRead = iMaxRead + 1;
       
   205 	if (iSourcePos + toRead > iSourceLen)
       
   206 		toRead = iSourceLen - iSourcePos;
       
   207 	
       
   208 	TPtrC findPtr(iFind->Des());
       
   209 	TPtr bufPtr(iBuf->Des());
       
   210 
       
   211 	// Is there enough data for a match?
       
   212 	if (iSourcePos + findPtr.Length() > iSourceLen)
       
   213 		{
       
   214 		iSourcePos += findPtr.Length();
       
   215 		return EFalse;
       
   216 		}
       
   217 
       
   218 	if (iFlags & KMsvFindWholeWord)
       
   219 		{
       
   220 		// Get character before the buffer
       
   221 		if (iSourcePos > 0)
       
   222 			iPreChar = TCharF(bufPtr[KMsvMaxFindTextLength - 1]);
       
   223 		else
       
   224 			iPreChar = TChar(' ');
       
   225 		}
       
   226 
       
   227 	if (iPlainText)
       
   228 		{
       
   229 		// Read data
       
   230 		bufPtr.Copy(iPlainText->Ptr() + iSourcePos, toRead);
       
   231 		}
       
   232 	else
       
   233 		{
       
   234 		// Assume data is rich text
       
   235 		// Text is always appended so clear the buffer
       
   236 		bufPtr.Zero();		
       
   237 		
       
   238 		// Read data, possibly across segment boundary
       
   239 		while (bufPtr.Length() < toRead)
       
   240 			bufPtr.Append(iRichText->Read(iSourcePos + bufPtr.Length(), toRead - bufPtr.Length()));
       
   241 		}
       
   242 
       
   243 	// Convert buffer to lower case if not case sensitive
       
   244 	if (!(iFlags & KMsvFindCaseSensitive))
       
   245 		bufPtr.LowerCase();
       
   246 
       
   247 	if (iFlags & KMsvFindWholeWord)
       
   248 		{
       
   249 		// Get character after the buffer
       
   250 		if (iSourcePos + toRead < iSourceLen)
       
   251 			{
       
   252 			iPostChar = TCharF(bufPtr[bufPtr.Length() - 1]);
       
   253 			bufPtr.SetLength(bufPtr.Length() - 1);
       
   254 			}
       
   255 		else
       
   256 			iPostChar = TChar(' ');
       
   257 		}
       
   258 
       
   259 	// Try and find text in this block of text
       
   260 	if (DoFindTextL())
       
   261 		return ETrue;
       
   262 
       
   263 	iSourcePos += KMsvMaxFindTextLength;
       
   264 	return EFalse;
       
   265 	}
       
   266 
       
   267 TBool CMsvFindText::DoFindTextL()
       
   268 	{
       
   269 	TPtrC findPtr(iFind->Des());
       
   270 	TPtrC bufPtr(iBuf->Des());
       
   271 	TInt pos = 0;
       
   272 
       
   273 	// Find the text
       
   274 	// If Wild card specified
       
   275 	if(iFlags & KMsvFindUsingWildCard)
       
   276 		{
       
   277 		pos = bufPtr.MatchC(findPtr);
       
   278 		}
       
   279 	else
       
   280 		{
       
   281 		pos = bufPtr.Find(findPtr);
       
   282 		}
       
   283 
       
   284 	// Did we find the text
       
   285 	if (pos < 0)
       
   286 		return EFalse;
       
   287 
       
   288 	if (iFlags & KMsvFindWholeWord)
       
   289 		{
       
   290 		// If we get here its because we've found the text but we need to check for whole word
       
   291 		// The following returns false (no match) if the matching text is preceded or followed by an alphanumeric digit
       
   292 		// The pre and post characters are the characters that come directly before and after the buffer we maintain
       
   293 
       
   294 		if ((pos == 0 && iPreChar.IsAlphaDigit()) ||
       
   295 			(pos > 0 && TCharF(bufPtr[pos - 1]).IsAlphaDigit()) ||
       
   296 			(pos + findPtr.Length() < bufPtr.Length() && TCharF(bufPtr[pos + findPtr.Length()]).IsAlphaDigit()) ||
       
   297 			(pos + findPtr.Length() == bufPtr.Length() && iPostChar.IsAlphaDigit()))
       
   298 			return EFalse;
       
   299 		}
       
   300 
       
   301 	// Found the text
       
   302 	return ETrue;
       
   303 	}
       
   304 
       
   305 void CMsvFindText::DoComplete(TInt&)
       
   306 	{
       
   307 	delete iBuf; iBuf = NULL;
       
   308 	delete iFind; iFind = NULL;
       
   309 	}