1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/textandloc/textrendering/texthandling/stext/ParseLst.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,512 @@
1.4 +/*
1.5 +* Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +#include "TXTSTD.H"
1.23 +#include "ParseLst.h"
1.24 +#include "OstTraceDefinitions.h"
1.25 +#ifdef OST_TRACE_COMPILER_IN_USE
1.26 +#include "ParseLstTraces.h"
1.27 +#endif
1.28 +
1.29 +
1.30 +
1.31 +//++ sort out definitive hash includes
1.32 +
1.33 +
1.34 +CParserList::CParserItem::CParserItem(MParser* aParser, const TUint aTagIndex)
1.35 +: iParser(aParser),
1.36 + iTagIndex(aTagIndex)
1.37 + {
1.38 + }
1.39 +
1.40 +
1.41 +// Panic the process with UikParse as the category.
1.42 +void CParserList::Panic(TParserListPanic aPanic) const
1.43 + {
1.44 + OstTraceExt2( TRACE_FATAL, DUP1_CPARSERLIST_PANIC, "CParserList::Panic;this=%x;aPanic=%x", (unsigned int)this, ( TUint )&( aPanic ) );
1.45 + _LIT(panicStr, "ParseLst");
1.46 + User::Panic(panicStr, aPanic);
1.47 + }
1.48 +
1.49 +
1.50 +CParserList::CParserList()
1.51 +: iParserList(4)
1.52 + {
1.53 + iHighestIndex = 0;
1.54 + iNumberInList = 0;
1.55 + }
1.56 +
1.57 +
1.58 +CParserList::~CParserList()
1.59 + {
1.60 + iParserList.ResetAndDestroy(); // Reset the list and destroy the CParserItems
1.61 + iParserList.Close(); // but leave the parsers and free the resources
1.62 + }
1.63 +
1.64 +
1.65 +// Add parser to appropriate list
1.66 +void CParserList::ActivateAParserL(MParser* aParser, const TBool aDefaultParser)
1.67 + {
1.68 + // Check the index isn't rolling over
1.69 + // N.B. This is somewhat unlikely. Since index is effectively a 29-bit
1.70 + // uint (I'm using the top 3 bits as flags) this allows 268435456 parsers
1.71 + // to be installed. (Assuming we deinstall almost as many, as we went
1.72 + // along, to avoid OOM.) At 50 per sec that's 20 years continuous action!
1.73 + if (iHighestIndex >= EMaxParserIndex)
1.74 + {
1.75 + OstTrace0( TRACE_DUMP, CPARSERLIST_ACTIVATEAPARSERL, "EParserIndexRollover" );
1.76 + }
1.77 + __ASSERT_DEBUG((iHighestIndex < EMaxParserIndex), Panic(EParserIndexRollover));
1.78 + if (!aParser)
1.79 + {
1.80 + OstTrace0( TRACE_DUMP, DUP1_CPARSERLIST_ACTIVATEAPARSERL, "EParserNullPtr" );
1.81 + }
1.82 + __ASSERT_DEBUG(aParser, Panic(EParserNullPtr));
1.83 + TUint parserIndex = iHighestIndex + 1;
1.84 + // Adjust flags to describe parser
1.85 + if (aParser->ReformatOnRecognise())
1.86 + parserIndex |= static_cast<TUint>( EReformatOnRecogniseFlag );
1.87 + if (aParser->ReformatOnRollover())
1.88 + parserIndex |= EReformatOnRolloverFlag;
1.89 + if (aDefaultParser)
1.90 + parserIndex |= EDefaultParserFlag;
1.91 + // Create a parser item
1.92 + TInt result;
1.93 + CParserItem* parserItem = new (ELeave) CParserItem(aParser, parserIndex);
1.94 + ++iHighestIndex;
1.95 + if (aDefaultParser)
1.96 + {
1.97 + CleanupStack::PushL(parserItem);
1.98 + result = iParserList.Append(parserItem);
1.99 + if (result) // We couldn't get it in the main list
1.100 + User::Leave(result);
1.101 + CleanupStack::Pop();
1.102 + }
1.103 + else
1.104 + {
1.105 + // Look for the end of the specific parsers and the start of the default set
1.106 + TInt count;
1.107 + for (count = 0; count < iNumberInList; count++)
1.108 + {
1.109 + if (DefaultParser(iParserList[count]->TagIndex()))
1.110 + break;
1.111 + }
1.112 + CleanupStack::PushL(parserItem);
1.113 + result = iParserList.Insert(parserItem, count);
1.114 + if (result) // We couldn't get it in the main list
1.115 + User::Leave(result);
1.116 + CleanupStack::Pop();
1.117 + }
1.118 + iNumberInList++;
1.119 + }
1.120 +
1.121 +
1.122 +// Activate an individual parser
1.123 +void CParserList::ActivateParserL(MParser* aParser)
1.124 + {
1.125 + ActivateAParserL(aParser, EFalse);
1.126 + }
1.127 +
1.128 +
1.129 +// N.B. We can't just delete CParserList and zero TLS when we get back
1.130 +// to a list with no specific or default parsers because there could be
1.131 +// an EText left with a local ptr to it.
1.132 +void CParserList::DeactivateParser(MParser* aParser)
1.133 + {
1.134 + if (!iNumberInList)
1.135 + {
1.136 + OstTrace0( TRACE_DUMP, CPARSERLIST_DEACTIVATEPARSER, "EParserNoneActive" );
1.137 + }
1.138 + __ASSERT_DEBUG(iNumberInList, Panic(EParserNoneActive));
1.139 + if (!aParser)
1.140 + {
1.141 + OstTrace0( TRACE_DUMP, DUP1_CPARSERLIST_DEACTIVATEPARSER, "EParserNullPtr" );
1.142 + }
1.143 + __ASSERT_DEBUG(aParser, Panic(EParserNullPtr));
1.144 + // Run thru list till find entry we need
1.145 + TInt count;
1.146 + for (count = 0; count < iNumberInList; count++)
1.147 + {
1.148 + if (iParserList[count]->Parser() == aParser)
1.149 + {
1.150 + delete iParserList[count];
1.151 + iParserList.Remove(count);
1.152 + break;
1.153 + }
1.154 + }
1.155 + if (count >= iNumberInList)
1.156 + {
1.157 + OstTrace0( TRACE_DUMP, DUP2_CPARSERLIST_DEACTIVATEPARSER, "EParserInstanceNotActive" );
1.158 + }
1.159 + __ASSERT_DEBUG((count < iNumberInList), Panic(EParserInstanceNotActive));
1.160 + iNumberInList--;
1.161 + }
1.162 +
1.163 +
1.164 +// Activate a parser as one of the default set
1.165 +void CParserList::ActivateDefaultParserL(MParser* aParser)
1.166 + {
1.167 + ActivateAParserL(aParser, ETrue);
1.168 + }
1.169 +
1.170 +
1.171 +//++ Put comment here
1.172 +void CParserList::DeactivateParserDefaults()
1.173 + {
1.174 + if (iNumberInList)
1.175 + {
1.176 + // Take them out of the list
1.177 + while (iNumberInList && DefaultParser(iParserList[iNumberInList - 1]->TagIndex()))
1.178 + {
1.179 + // Tell the parser to free itself
1.180 + iParserList[iNumberInList - 1]->Parser()->Release();
1.181 + // Delete the item that refers to it
1.182 + delete iParserList[iNumberInList - 1];
1.183 + // Remove the entry from the list
1.184 + iParserList.Remove(iNumberInList - 1);
1.185 + iNumberInList--;
1.186 + }
1.187 + }
1.188 + }
1.189 +
1.190 +
1.191 +// Called by EText to scan an area of text
1.192 +TBool CParserList::ParseThisText(CRichText& aTextObj,TInt aStartScan,TInt aScanLength,TInt& aStartOfTags,TInt& aLength)
1.193 + {
1.194 + TBool foundSomething = EFalse;
1.195 + TCharFormatX format;
1.196 + TCharFormatXMask varies;
1.197 + TPtrC ptr;
1.198 + TInt endRange;
1.199 +
1.200 + // Scan either side of the range in case part of some tagged text was deleted.
1.201 + if (aStartScan > 0)
1.202 + {
1.203 + aStartScan--;
1.204 + aScanLength++;
1.205 + }
1.206 + if (aStartScan + aScanLength < aTextObj.DocumentLength())
1.207 + aScanLength++;
1.208 +
1.209 + if (iNumberInList && aScanLength)
1.210 + {
1.211 + aStartOfTags = aStartScan + aScanLength;
1.212 + aLength = 0;
1.213 + for (TInt count = 0; count < iNumberInList; count++)
1.214 + {
1.215 + // For each parser in the list
1.216 + TUint tagIndex = iParserList[count]->TagIndex();
1.217 + TInt pos;
1.218 + MParser* parser = iParserList[count]->Parser();
1.219 + TInt localStartScan = aStartScan;
1.220 + TInt localScanLength = aScanLength;
1.221 + // Start by removing existing tags for this parser. This ensures
1.222 + // that old tags that have been invalidated by subsequent editing
1.223 + // are removed. Any that are still valid will be replaced.
1.224 + aTextObj.GetExtendedCharFormat(format, varies, localStartScan, aScanLength);
1.225 +
1.226 + if (format.iParserTag || varies.AttribIsSet(EAttParserTag))
1.227 + {
1.228 + // At least some of the object contains a non-zero tag - go through it
1.229 + // Are we starting part way through a tag?
1.230 + aTextObj.GetExtendedCharFormat(format, varies, localStartScan, 1);
1.231 + if (format.iParserTag == tagIndex)
1.232 + {
1.233 + // The first char of this range has the current parsers tag
1.234 + // so we need to check backwards for the start of that tag
1.235 + for (pos = localStartScan; pos > 0; pos--)
1.236 + {
1.237 + aTextObj.GetExtendedCharFormat(format, varies, pos - 1, 1);
1.238 + if (format.iParserTag != tagIndex)
1.239 + break;
1.240 + }
1.241 + // Since we are going to remove a tag starting from here
1.242 + // we need to allow this area to be rescanned
1.243 + localScanLength += localStartScan - pos;
1.244 + localStartScan = pos;
1.245 + }
1.246 + // What about off the end?
1.247 + aTextObj.GetExtendedCharFormat(format, varies, localStartScan + localScanLength - 1, 1);
1.248 + if (format.iParserTag == tagIndex)
1.249 + {
1.250 + // The last char of this range has the current parsers tag
1.251 + // so we need to check forwards for the end of that tag
1.252 + pos = localStartScan + localScanLength;
1.253 + TInt end = aTextObj.DocumentLength();
1.254 + while (pos < end)
1.255 + {
1.256 + aTextObj.GetTextAndExtendedFormat(ptr, format, pos);
1.257 + if (format.iParserTag != tagIndex)
1.258 + break;
1.259 + pos += ptr.Length();
1.260 + }
1.261 + // Adjust scan length
1.262 + localScanLength = pos - localStartScan;
1.263 + }
1.264 + pos = localStartScan;
1.265 + while (pos < localStartScan + localScanLength)
1.266 + {
1.267 + // Run along the scan range
1.268 + aTextObj.GetTextAndExtendedFormat(ptr, format, pos);
1.269 + if (format.iParserTag == tagIndex)
1.270 + {
1.271 + // Remove this tag
1.272 + format.iParserTag = 0;
1.273 + varies.ClearAll();
1.274 + varies.SetAttrib(EAttParserTag);
1.275 + TRAPD(leaveCode, aTextObj.ApplyExtendedCharFormatL(format, varies, pos, ptr.Length()));
1.276 + if (leaveCode==KErrNone)
1.277 + foundSomething = ETrue; // We are removing a tag
1.278 + if (aLength)
1.279 + {
1.280 + if (pos < aStartOfTags)
1.281 + {
1.282 + aLength += aStartOfTags - pos;
1.283 + aStartOfTags = pos;
1.284 + }
1.285 + if (pos + ptr.Length() > aStartOfTags + aLength)
1.286 + aLength = pos + ptr.Length() - aStartOfTags;
1.287 + }
1.288 + else
1.289 + {
1.290 + aStartOfTags = pos;
1.291 + aLength = ptr.Length();
1.292 + }
1.293 + }
1.294 + pos += ptr.Length();
1.295 + }
1.296 + }
1.297 + endRange = localStartScan + localScanLength;
1.298 +
1.299 + // For this parser, run through text looking for changes
1.300 + TBool allowBack = ETrue;
1.301 + for (;;) // Run forever
1.302 + {
1.303 + TInt localStartTag = aTextObj.DocumentLength();
1.304 + TInt localTagLength = 0;
1.305 + TInt result = parser->ParseThisText(aTextObj, allowBack, localStartScan, localScanLength, localStartTag, localTagLength);
1.306 + if (!result)
1.307 + break;
1.308 + if (!allowBack && (localStartTag < localStartScan))
1.309 + {
1.310 + OstTrace0( TRACE_DUMP, CPARSERLIST_PARSETHISTEXT, "EParserIgnoringAllowFlag" );
1.311 + }
1.312 + __ASSERT_DEBUG(allowBack || (localStartTag >= localStartScan), Panic(EParserIgnoringAllowFlag));
1.313 + TInt startNewTag = localStartTag;
1.314 + TInt lengthNewTag = localTagLength;
1.315 + aTextObj.GetExtendedCharFormat(format, varies, localStartTag, localTagLength);
1.316 + if (format.iParserTag || varies.AttribIsSet(EAttParserTag))
1.317 + {
1.318 + // At least some of this area contains a non-zero tag - go through it
1.319 + pos = localStartTag;
1.320 + TBool higher = EFalse;
1.321 + while (pos < localStartTag + localTagLength)
1.322 + {
1.323 + aTextObj.GetTextAndExtendedFormat(ptr, format, pos);
1.324 + if (format.iParserTag && (MaskedTag(format.iParserTag) < MaskedTag(tagIndex)))
1.325 + {
1.326 + // A higher precedence tag is already here so we can't
1.327 + // insert our tag - let's see how far it goes
1.328 + TUint tag = format.iParserTag; // Stash tag before overwriting it
1.329 + TInt len = aTextObj.DocumentLength();
1.330 + while (pos < len)
1.331 + {
1.332 + aTextObj.GetTextAndExtendedFormat(ptr, format, pos);
1.333 + if (format.iParserTag != tag)
1.334 + break;
1.335 + pos += ptr.Length();
1.336 + }
1.337 + result = EFalse;
1.338 + startNewTag = pos;
1.339 + lengthNewTag = 0;
1.340 + break;
1.341 + }
1.342 + // If there aren't any higher precedence tags in here then this
1.343 + // will save us having to go through again if there aren't any
1.344 + // lower precedence tags either
1.345 + if (MaskedTag(format.iParserTag) >= MaskedTag(tagIndex))
1.346 + higher = ETrue;
1.347 + pos += ptr.Length();
1.348 + }
1.349 + if (higher)
1.350 + {
1.351 + // There are lower or equal precedence tags in this range
1.352 + // Do they extend back off the start?
1.353 + aTextObj.GetExtendedCharFormat(format, varies, localStartTag, 1);
1.354 + if (format.iParserTag)
1.355 + {
1.356 + // need to check backwards
1.357 + TUint tag = format.iParserTag; // Stash tag before overwriting it
1.358 + for (pos = localStartTag; pos > 0; pos--)
1.359 + {
1.360 + aTextObj.GetExtendedCharFormat(format, varies, pos - 1, 1);
1.361 + if (format.iParserTag != tag)
1.362 + break;
1.363 + }
1.364 + localTagLength += localStartTag - pos;
1.365 + localStartTag = pos;
1.366 + }
1.367 + // What about off the end?
1.368 + pos = localStartTag + localTagLength;
1.369 + aTextObj.GetExtendedCharFormat(format, varies, pos - 1, 1);
1.370 + if (format.iParserTag)
1.371 + {
1.372 + // need to check forwards
1.373 + TUint tag = format.iParserTag; // Stash tag before overwriting it
1.374 + TInt len = aTextObj.DocumentLength();
1.375 + while (pos < len)
1.376 + {
1.377 + aTextObj.GetTextAndExtendedFormat(ptr, format, pos);
1.378 + if (format.iParserTag != tag)
1.379 + break;
1.380 + pos += ptr.Length();
1.381 + }
1.382 + localTagLength = pos - localStartTag;
1.383 + }
1.384 +
1.385 + // Remove all tags in this area - they all have lower precedence
1.386 + format.iParserTag = 0;
1.387 + varies.ClearAll();
1.388 + varies.SetAttrib(EAttCharLanguage);
1.389 + TRAPD(leaveCode, aTextObj.ApplyExtendedCharFormatL(format, varies, localStartTag, localTagLength));
1.390 + if (leaveCode==KErrNone)
1.391 + foundSomething = ETrue; // We are removing a tag
1.392 + }
1.393 + }
1.394 +
1.395 + if (result)
1.396 + {
1.397 + // Format tag this area with tagIndex
1.398 + format.iParserTag = tagIndex;
1.399 + varies.ClearAll();
1.400 + varies.SetAttrib(EAttParserTag);
1.401 + // Use the original length, not the possibly expanded version
1.402 + TRAPD(leaveCode, aTextObj.ApplyExtendedCharFormatL(format, varies, startNewTag, lengthNewTag));
1.403 + if (leaveCode==KErrNone)
1.404 + foundSomething = ETrue; // We are applying a tag
1.405 + if (aLength)
1.406 + {
1.407 + if (localStartTag < aStartOfTags)
1.408 + {
1.409 + aLength += aStartOfTags - localStartTag;
1.410 + aStartOfTags = localStartTag;
1.411 + }
1.412 + if (localStartTag + localTagLength > aStartOfTags + aLength)
1.413 + aLength = localStartTag + localTagLength - aStartOfTags;
1.414 + }
1.415 + else
1.416 + {
1.417 + aStartOfTags = localStartTag;
1.418 + aLength = localTagLength;
1.419 + }
1.420 + }
1.421 + // Jump over
1.422 + localScanLength -= startNewTag + lengthNewTag - localStartScan;
1.423 + localStartScan = startNewTag + lengthNewTag; // Adjust start of next scan run
1.424 + if (localStartScan >= endRange) // Have we reached the end of the range yet?
1.425 + break;
1.426 + allowBack = EFalse;
1.427 + }
1.428 + }
1.429 + }
1.430 +
1.431 + return foundSomething;
1.432 + }
1.433 +
1.434 +
1.435 +// given a tag, fetch a ptr to the parser - or null
1.436 +MParser* CParserList::ParserWithThisTag(const TUint aTagIndex) const
1.437 + {
1.438 + MParser* parser = NULL;
1.439 + for (TInt count = 0; count < iNumberInList; count++)
1.440 + {
1.441 + if (aTagIndex == iParserList[count]->TagIndex())
1.442 + {
1.443 + parser = iParserList[count]->Parser();
1.444 + break;
1.445 + }
1.446 + }
1.447 + return parser;
1.448 + }
1.449 +
1.450 +// given a ptr to a parser, fetch a tag - or zero
1.451 +TUint CParserList::TagForThisParser(const MParser *const aParser) const
1.452 + {
1.453 + TUint tagIndex = 0;
1.454 + for (TInt count = 0; count < iNumberInList; count++)
1.455 + {
1.456 + if (aParser == iParserList[count]->Parser())
1.457 + {
1.458 + tagIndex = iParserList[count]->TagIndex();
1.459 + break;
1.460 + }
1.461 + }
1.462 + if (!tagIndex)
1.463 + {
1.464 + OstTrace0( TRACE_DUMP, CPARSERLIST_TAGFORTHISPARSER, "EParserNoSuchTag" );
1.465 + }
1.466 + __ASSERT_DEBUG(tagIndex, Panic(EParserNoSuchTag));
1.467 + return tagIndex;
1.468 + }
1.469 +
1.470 +
1.471 +CParserData::CParserData(TInt aEndParse):
1.472 + iStartParse(0),
1.473 + iEndParse(aEndParse)
1.474 + {
1.475 + // Get parser data
1.476 + iActiveParserList = (CParserList*)Dll::Tls();
1.477 + iLastKnownCursor = -1;
1.478 + if (iActiveParserList)
1.479 + iActiveParserList->iRefCount++;
1.480 + }
1.481 +
1.482 +
1.483 +CParserData::~CParserData()
1.484 + {
1.485 + if (iActiveParserList)
1.486 + {
1.487 + iActiveParserList->iRefCount--;
1.488 + if ((iActiveParserList->iRefCount == 0) && (iActiveParserList->iNumberInList == 0))
1.489 + {
1.490 + Dll::FreeTls();
1.491 + delete iActiveParserList;
1.492 + }
1.493 + }
1.494 + }
1.495 +
1.496 +
1.497 +// Merge the specified range, which may have changed length, into the current range.
1.498 +// aOldLength is the # of chars deleted and to be removed from the range
1.499 +// aNewLength is the # of chars inserted and to be added to the range
1.500 +void CParserData::MergeRange(TInt aStart,TInt aOldLength,TInt aNewLength)
1.501 + {
1.502 + if (iStartParse == -1) // no current range
1.503 + {
1.504 + iStartParse = aStart;
1.505 + iEndParse = aStart + aNewLength;
1.506 + }
1.507 + else
1.508 + {
1.509 + if (aStart < iStartParse)
1.510 + iStartParse = aStart;
1.511 + if (aStart + aOldLength > iEndParse)
1.512 + iEndParse = aStart + aOldLength;
1.513 + iEndParse += aNewLength - aOldLength;
1.514 + }
1.515 + }