// Called by EText to scan an area of text
TBool CParserList::ParseThisText(CRichText& aTextObj,TInt aStartScan,TInt aScanLength,TInt& aStartOfTags,TInt& aLength)
	{
	TBool foundSomething = EFalse;
	TCharFormatX format;
	TCharFormatXMask varies;
	TPtrC ptr;
	TInt endRange;

	// Scan either side of the range in case part of some tagged text was deleted.
	if (aStartScan > 0)
		{
		aStartScan--;
		aScanLength++;
		}
	if (aStartScan + aScanLength < aTextObj.DocumentLength())
		aScanLength++;

	if (iNumberInList && aScanLength)
		{
		aStartOfTags = aStartScan + aScanLength;
		aLength = 0;
		for (TInt count = 0; count < iNumberInList; count++)
			{
			// For each parser in the list
			TUint tagIndex = iParserList[count]->TagIndex();
			TInt pos;
			MParser* parser = iParserList[count]->Parser();
			TInt localStartScan = aStartScan;
			TInt localScanLength = aScanLength;
			// Start by removing existing tags for this parser. This ensures
			// that old tags that have been invalidated by subsequent editing
			// are removed. Any that are still valid will be replaced.
			aTextObj.GetExtendedCharFormat(format, varies, localStartScan, aScanLength);

			if (format.iParserTag || varies.AttribIsSet(EAttParserTag))
				{
				// At least some of the object contains a non-zero tag - go through it
				// Are we starting part way through a tag?
				aTextObj.GetExtendedCharFormat(format, varies, localStartScan, 1);
				if (format.iParserTag == tagIndex)
					{
					// The first char of this range has the current parsers tag
					// so we need to check backwards for the start of that tag
					for (pos = localStartScan; pos > 0; pos--)
						{
						aTextObj.GetExtendedCharFormat(format, varies, pos - 1, 1);
						if (format.iParserTag != tagIndex)
							break;
						}
					// Since we are going to remove a tag starting from here
					// we need to allow this area to be rescanned
					localScanLength += localStartScan - pos;
					localStartScan = pos;
					}
				// What about off the end?
				aTextObj.GetExtendedCharFormat(format, varies, localStartScan + localScanLength - 1, 1);
				if (format.iParserTag == tagIndex)
					{
					// The last char of this range has the current parsers tag
					// so we need to check forwards for the end of that tag
					pos = localStartScan + localScanLength;
					TInt end = aTextObj.DocumentLength();
					while (pos < end)
						{
						aTextObj.GetTextAndExtendedFormat(ptr, format, pos);
						if (format.iParserTag != tagIndex)
							break;
						pos += ptr.Length();
						}
					// Adjust scan length
					localScanLength = pos - localStartScan;
					}
				pos = localStartScan;
				while (pos < localStartScan + localScanLength)
					{
					// Run along the scan range
					aTextObj.GetTextAndExtendedFormat(ptr, format, pos);
					if (format.iParserTag == tagIndex)
						{
						// Remove this tag
						format.iParserTag = 0;
						varies.ClearAll();
						varies.SetAttrib(EAttParserTag);
						TRAPD(leaveCode, aTextObj.ApplyExtendedCharFormatL(format, varies, pos, ptr.Length()));
						if (leaveCode==KErrNone)
							foundSomething = ETrue;	// We are removing a tag
						if (aLength)
							{
							if (pos < aStartOfTags)
								{
								aLength += aStartOfTags - pos;
								aStartOfTags = pos;
								}
							if (pos + ptr.Length() > aStartOfTags + aLength)
								aLength = pos + ptr.Length() - aStartOfTags;
							}
						else
							{
							aStartOfTags = pos;
							aLength = ptr.Length();
							}
						}
					pos += ptr.Length();
					}
				}
			endRange = localStartScan + localScanLength;

			// For this parser, run through text looking for changes
			TBool allowBack = ETrue;
			for (;;)	// Run forever
				{
				TInt localStartTag = aTextObj.DocumentLength();
				TInt localTagLength = 0;
				TInt result = parser->ParseThisText(aTextObj, allowBack, localStartScan, localScanLength, localStartTag, localTagLength);
				if (!result)
					break;
				if (!allowBack && (localStartTag < localStartScan))
				    {
				    OstTrace0( TRACE_DUMP, CPARSERLIST_PARSETHISTEXT, "EParserIgnoringAllowFlag" );
				    }
				__ASSERT_DEBUG(allowBack || (localStartTag >= localStartScan), Panic(EParserIgnoringAllowFlag));
				TInt startNewTag = localStartTag;
				TInt lengthNewTag = localTagLength;
				aTextObj.GetExtendedCharFormat(format, varies, localStartTag, localTagLength);
				if (format.iParserTag || varies.AttribIsSet(EAttParserTag))
					{
					// At least some of this area contains a non-zero tag - go through it
					pos = localStartTag;
					TBool higher = EFalse;
					while (pos < localStartTag + localTagLength)
						{
						aTextObj.GetTextAndExtendedFormat(ptr, format, pos);
						if (format.iParserTag && (MaskedTag(format.iParserTag) < MaskedTag(tagIndex)))
							{
							// A higher precedence tag is already here so we can't
							// insert our tag - let's see how far it goes
							TUint tag = format.iParserTag;	// Stash tag before overwriting it
							TInt len = aTextObj.DocumentLength();
							while (pos < len)
								{
								aTextObj.GetTextAndExtendedFormat(ptr, format, pos);
								if (format.iParserTag != tag)
									break;
								pos += ptr.Length();
								}
							result = EFalse;
							startNewTag = pos;
							lengthNewTag = 0;
							break;
							}
						// If there aren't any higher precedence tags in here then this
						// will save us having to go through again if there aren't any
						// lower precedence tags either
						if (MaskedTag(format.iParserTag) >= MaskedTag(tagIndex))
							higher = ETrue;
						pos += ptr.Length();
						}
					if (higher)
						{
						// There are lower or equal precedence tags in this range
						// Do they extend back off the start?
						aTextObj.GetExtendedCharFormat(format, varies, localStartTag, 1);
						if (format.iParserTag)
							{
							// need to check backwards
							TUint tag = format.iParserTag;	// Stash tag before overwriting it
							for (pos = localStartTag; pos > 0; pos--)
								{
								aTextObj.GetExtendedCharFormat(format, varies, pos - 1, 1);
								if (format.iParserTag != tag)
									break;
								}
							localTagLength += localStartTag - pos;
							localStartTag = pos;
							}
						// What about off the end?
						pos = localStartTag + localTagLength;
						aTextObj.GetExtendedCharFormat(format, varies, pos - 1, 1);
						if (format.iParserTag)
							{
							// need to check forwards
							TUint tag = format.iParserTag;	// Stash tag before overwriting it
							TInt len = aTextObj.DocumentLength();
							while (pos < len)
								{
								aTextObj.GetTextAndExtendedFormat(ptr, format, pos);
								if (format.iParserTag != tag)
									break;
								pos += ptr.Length();
								}
							localTagLength = pos - localStartTag;
							}

						// Remove all tags in this area - they all have lower precedence
						format.iParserTag = 0;
						varies.ClearAll();
						varies.SetAttrib(EAttCharLanguage);
						TRAPD(leaveCode, aTextObj.ApplyExtendedCharFormatL(format, varies, localStartTag, localTagLength));
						if (leaveCode==KErrNone)
							foundSomething = ETrue;	// We are removing a tag
						}
					}

				if (result)
					{
					// Format tag this area with tagIndex
					format.iParserTag = tagIndex;
					varies.ClearAll();
					varies.SetAttrib(EAttParserTag);
					// Use the original length, not the possibly expanded version
					TRAPD(leaveCode, aTextObj.ApplyExtendedCharFormatL(format, varies, startNewTag, lengthNewTag));
					if (leaveCode==KErrNone)
						foundSomething = ETrue;		// We are applying a tag
					if (aLength)
						{
						if (localStartTag < aStartOfTags)
							{
							aLength += aStartOfTags - localStartTag;
							aStartOfTags = localStartTag;
							}
						if (localStartTag + localTagLength > aStartOfTags + aLength)
							aLength = localStartTag + localTagLength - aStartOfTags;
						}
					else
						{
						aStartOfTags = localStartTag;
						aLength = localTagLength;
						}
					}
				// Jump over
				localScanLength -= startNewTag + lengthNewTag - localStartScan;
				localStartScan = startNewTag + lengthNewTag;	// Adjust start of next scan run
				if (localStartScan >= endRange)	// Have we reached the end of the range yet?
					break;
				allowBack = EFalse;
				}
			}
		}

	return foundSomething;
	}