1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/textandloc/textrendering/texthandling/stext/Txtparse.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,382 @@
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 "TXTRICH.H"
1.23 +#include "TXTSTD.H"
1.24 +#include "ParseLst.h"
1.25 +#include "OstTraceDefinitions.h"
1.26 +#ifdef OST_TRACE_COMPILER_IN_USE
1.27 +#include "TxtparseTraces.h"
1.28 +#endif
1.29 +
1.30 +
1.31 +
1.32 +// Install and activate a particular parser, app provides instance
1.33 +EXPORT_C void CRichText::ActivateParserL(MParser* aParser)
1.34 + {
1.35 + CParserList* activeParserList = (CParserList*)Dll::Tls();
1.36 + if (!activeParserList)
1.37 + {
1.38 + CreateParserETextTLSL();
1.39 + activeParserList = (CParserList*)Dll::Tls();
1.40 + }
1.41 + activeParserList->ActivateParserL(aParser);
1.42 + }
1.43 +
1.44 +
1.45 +// Deactivate and deinstall a particular parser, identified by ptr to instance
1.46 +EXPORT_C void CRichText::DeactivateParser(MParser* aParser)
1.47 + {
1.48 + CParserList* activeParserList = (CParserList*)Dll::Tls();
1.49 + if (!activeParserList)
1.50 + {
1.51 + OstTrace0( TRACE_DUMP, CRICHTEXT_DEACTIVATEPARSER, "EParserListNotInitialized" );
1.52 + }
1.53 + __ASSERT_DEBUG(activeParserList, Panic(EParserListNotInitialized));
1.54 + activeParserList->DeactivateParser(aParser);
1.55 + if ((activeParserList->iRefCount == 0) && (activeParserList->iNumberInList == 0))
1.56 + {
1.57 + Dll::FreeTls();
1.58 + delete activeParserList;
1.59 + }
1.60 + }
1.61 +
1.62 +
1.63 +// Install and activate a parser in the default set
1.64 +EXPORT_C void CRichText::ActivateDefaultParserL(MParser* aParser)
1.65 + {
1.66 + CParserList* activeParserList = (CParserList*)Dll::Tls();
1.67 + if (!activeParserList)
1.68 + {
1.69 + CreateParserETextTLSL();
1.70 + activeParserList = (CParserList*)Dll::Tls();
1.71 + }
1.72 + activeParserList->ActivateDefaultParserL(aParser);
1.73 + }
1.74 +
1.75 +
1.76 +// Deactivate and deinstall the standard set of default parsers
1.77 +EXPORT_C void CRichText::DeactivateParserDefaults()
1.78 + {
1.79 + CParserList* activeParserList = (CParserList*)Dll::Tls();
1.80 + if (activeParserList)
1.81 + {
1.82 + activeParserList->DeactivateParserDefaults();
1.83 + if ((activeParserList->iRefCount == 0) && (activeParserList->iNumberInList == 0))
1.84 + {
1.85 + Dll::FreeTls();
1.86 + delete activeParserList;
1.87 + }
1.88 + }
1.89 + }
1.90 +
1.91 +
1.92 +// Create ParserLst instance and retain ownership of it but pass address to EText TLS
1.93 +void CRichText::CreateParserETextTLSL()
1.94 + {
1.95 + if (Dll::Tls() != NULL)
1.96 + {
1.97 + OstTrace0( TRACE_DUMP, CRICHTEXT_CREATEPARSERETEXTTLSL, "EParserListAlreadyExists" );
1.98 + }
1.99 + __ASSERT_DEBUG(Dll::Tls() == NULL, Panic(EParserListAlreadyExists));
1.100 + CParserList* activeParserList = new (ELeave) CParserList;
1.101 + CleanupStack::PushL(activeParserList);
1.102 + TInt err = Dll::SetTls(activeParserList);
1.103 + User::LeaveIfError(err);
1.104 + CleanupStack::Pop(activeParserList);
1.105 + }
1.106 +
1.107 +
1.108 +// Set observer callback to tell whenever the object has been edited.
1.109 +// If set set then the parser system is active for this instance, otherwise not.
1.110 +
1.111 +
1.112 +
1.113 +EXPORT_C void CRichText::SetEditObserver(MEditObserver* aEditObserver)
1.114 +/** Sets the rich text object's edit observer. The observer's EditObserver() function
1.115 +is called by the rich text object each time the object's text content is edited
1.116 +(e.g. after a paste, insert, delete, reset etc.).
1.117 +
1.118 +@param aEditObserver Pointer to the edit observer. */
1.119 + {
1.120 + iParserData->iEditObserver = aEditObserver;
1.121 + }
1.122 +
1.123 +
1.124 +EXPORT_C TBool CRichText::ParseText(TInt& aStartOfTags, TInt& aLength, TBool aForceScanAllText)
1.125 + {
1.126 + if (!iIndex.IsPtr())
1.127 + {
1.128 + OstTrace0( TRACE_DUMP, CRICHTEXT_PARSETEXT, "EParserListTextIndexNotInitialized" );
1.129 + }
1.130 + __ASSERT_ALWAYS(iIndex.IsPtr(),Panic(EParserListTextIndexNotInitialized));
1.131 + TBool foundSomething = EFalse;
1.132 + if (iParserData->iActiveParserList && iParserData->iEditObserver)
1.133 + {
1.134 + if (aForceScanAllText)
1.135 + foundSomething = iParserData->iActiveParserList->ParseThisText(*this,0,DocumentLength(),
1.136 + aStartOfTags,aLength);
1.137 + else if (iParserData->HaveRange())
1.138 + foundSomething = iParserData->iActiveParserList->ParseThisText(*this,iParserData->StartParse(),
1.139 + iParserData->EndParse() - iParserData->StartParse(),
1.140 + aStartOfTags,aLength);
1.141 + // All parsers have scanned the area
1.142 + iParserData->KillRange();
1.143 + }
1.144 + return foundSomething;
1.145 + }
1.146 +
1.147 +
1.148 +// Given a cursor position, is there a tag under it and, if so, give me details
1.149 +TBool CRichText::DoCursorOverTag(TInt aPos, MParser*& aParser, TInt& aTagStart, TInt& aLength) const
1.150 + {
1.151 + TCharFormatX format;
1.152 + TCharFormatXMask varies;
1.153 + TBool success = EFalse;
1.154 + TBuf<1> buf;
1.155 +
1.156 + if (!iParserData->iActiveParserList)
1.157 + {
1.158 + OstTrace0( TRACE_DUMP, CRICHTEXT_DOCURSOROVERTAG, "EParserListNotInitialized" );
1.159 + }
1.160 + __ASSERT_DEBUG(iParserData->iActiveParserList, Panic(EParserListNotInitialized));
1.161 + if (!iParserData->iEditObserver)
1.162 + {
1.163 + OstTrace0( TRACE_DUMP, DUP1_CRICHTEXT_DOCURSOROVERTAG, "EParserListNotActive" );
1.164 + }
1.165 + __ASSERT_DEBUG(iParserData->iEditObserver, Panic(EParserListNotActive));
1.166 + GetExtendedCharFormat(format, varies, aPos, 1);
1.167 + Extract(buf, aPos, 1);
1.168 + if ((format.iParserTag) && (buf[0] != 0x2029))
1.169 + {
1.170 + aParser = iParserData->iActiveParserList->ParserWithThisTag(format.iParserTag);
1.171 + if (aParser == NULL)
1.172 + { // Parser has been deactivated
1.173 + return EFalse;
1.174 + }
1.175 + // Get extent of tag (or set of contiguous tags for same parser)
1.176 + TInt pos = aPos;
1.177 + TInt startScan;
1.178 + TInt scanLength;
1.179 + // need to check backwards
1.180 + TUint tag = format.iParserTag; // Stash tag before overwriting it
1.181 + for (; pos > 0; pos--)
1.182 + {
1.183 + GetExtendedCharFormat(format, varies, pos - 1, 1);
1.184 + Extract(buf, aPos, 1);
1.185 + if ((format.iParserTag != tag) || (buf[0] == 0x2029))
1.186 + break;
1.187 + }
1.188 + startScan = pos;
1.189 + // Now forwards
1.190 + TInt len = DocumentLength();
1.191 + while (pos < len)
1.192 + {
1.193 + TPtrC ptr;
1.194 + GetTextAndExtendedFormat(ptr, format, pos);
1.195 + if (format.iParserTag != tag)
1.196 + break;
1.197 + pos += ptr.Length();
1.198 + }
1.199 + if (pos > len)
1.200 + pos = len;
1.201 + scanLength = pos - startScan;
1.202 + // Now use the parser that found it originally to isolate the exact range
1.203 + // of the tag from the range that could contain several
1.204 + for (;;)
1.205 + {
1.206 + TInt result = aParser->ParseThisText(*this, EFalse, startScan, scanLength, aTagStart, aLength);
1.207 + // Check we haven't gone past it (failed to find it this time)
1.208 + if (!result || (aTagStart > aPos))
1.209 + break;
1.210 + if ((aPos >= aTagStart) && (aPos < aTagStart + aLength))
1.211 + {
1.212 + // We've found it
1.213 + success = ETrue;
1.214 + break;
1.215 + }
1.216 + // Not yet, skip over that one
1.217 + startScan += aLength;
1.218 + scanLength -= aLength;
1.219 + if (scanLength < 0)
1.220 + break;
1.221 + }
1.222 +
1.223 + }
1.224 + return success;
1.225 + }
1.226 +
1.227 +
1.228 +EXPORT_C TBool CRichText::CursorOverTag(TInt aPos, MParser*& aParser, TInt& aTagStart, TInt& aLength) const
1.229 + {
1.230 + TBool over = EFalse;
1.231 +
1.232 + if (iParserData->iActiveParserList && iParserData->iEditObserver)
1.233 + {
1.234 + iParserData->iLastKnownCursor = aPos;
1.235 + if (DoCursorOverTag(aPos, aParser, aTagStart, aLength))
1.236 + {
1.237 + over = ETrue;
1.238 + }
1.239 + if (aPos && DoCursorOverTag(aPos - 1, aParser, aTagStart, aLength))
1.240 + {
1.241 + over = ETrue;
1.242 + }
1.243 + }
1.244 + return over &&
1.245 + aParser->ConfirmCursorOverTag(*this, aTagStart, aLength, aPos);
1.246 + }
1.247 +
1.248 +
1.249 +EXPORT_C TInt CRichText::PositionOfNextTag(TInt aPos, const MParser * aParser) const
1.250 + {
1.251 + if (iParserData->iActiveParserList && iParserData->iEditObserver)
1.252 + {
1.253 + MParser* parser;
1.254 + TInt tagStart;
1.255 + TInt length;
1.256 + TInt newPos = aPos;
1.257 + TUint tag = 0;
1.258 + if (aParser)
1.259 + tag = iParserData->iActiveParserList->TagForThisParser(aParser);
1.260 + if (DoCursorOverTag(newPos, parser, tagStart, length))
1.261 + newPos = tagStart + length; // To get past the current tag
1.262 + TPtrC ptr;
1.263 + TCharFormatX format;
1.264 + while (newPos < DocumentLength())
1.265 + {
1.266 + GetTextAndExtendedFormat(ptr, format, newPos);
1.267 + if (format.iParserTag &&(!aParser || format.iParserTag == tag))
1.268 + return newPos;
1.269 + newPos += ptr.Length();
1.270 + }
1.271 + }
1.272 +
1.273 + return KErrNotFound;
1.274 + }
1.275 +
1.276 +
1.277 +EXPORT_C TInt CRichText::PositionOfNextTag(TInt aPos) const
1.278 + {
1.279 + return PositionOfNextTag(aPos, NULL);
1.280 + }
1.281 +
1.282 +
1.283 +EXPORT_C TInt CRichText::PositionOfPrevTag(TInt aPos, const MParser * aParser) const
1.284 + {
1.285 + if (iParserData->iActiveParserList && iParserData->iEditObserver)
1.286 + {
1.287 + MParser* parser;
1.288 + TInt tagStart;
1.289 + TInt length;
1.290 + TInt newPos = aPos;
1.291 + TUint tag = 0;
1.292 + if (aParser)
1.293 + tag = iParserData->iActiveParserList->TagForThisParser(aParser);
1.294 + if (DoCursorOverTag(newPos, parser, tagStart, length))
1.295 + newPos = tagStart; // To get past the current tag
1.296 + TCharFormatX format;
1.297 + TCharFormatXMask varies;
1.298 +
1.299 + for (; newPos > 0; newPos--)
1.300 + {
1.301 + GetExtendedCharFormat(format, varies, newPos - 1, 1);
1.302 + if (format.iParserTag &&(!aParser || format.iParserTag == tag))
1.303 + {
1.304 + if (DoCursorOverTag(newPos - 1, parser, tagStart, length))
1.305 + return tagStart;
1.306 + }
1.307 + }
1.308 + }
1.309 +
1.310 + return KErrNotFound;
1.311 + }
1.312 +
1.313 +
1.314 +EXPORT_C TInt CRichText::PositionOfPrevTag(TInt aPos) const
1.315 + {
1.316 + return PositionOfPrevTag(aPos, NULL);
1.317 + }
1.318 +
1.319 +
1.320 +void CRichText::OverrideFormatForParsersIfApplicable(TPtrC& aText, TCharFormatX& aFormat, TInt aStartPos) const
1.321 + {
1.322 + if (aFormat.iParserTag && iParserData->iActiveParserList && iParserData->iEditObserver)
1.323 + {
1.324 + // Replace format
1.325 + TInt start = -1;
1.326 + TInt length = 0;
1.327 + TInt curPos = iParserData->iLastKnownCursor;
1.328 + if (curPos > DocumentLength())
1.329 + curPos = DocumentLength(); // This shouldn't be neccesary but it makes it more
1.330 + // bulletproof if the calls from outside are made in
1.331 + // the wrong order
1.332 + if (curPos != -1)
1.333 + {
1.334 + TCharFormatX format;
1.335 + TCharFormatXMask varies;
1.336 + MParser* parser;
1.337 +
1.338 + GetExtendedCharFormat(format, varies, curPos, 1);
1.339 + // If char at curpos has a tag then cursor is over that tag, get extents of tag
1.340 + if (CParserList::ReformatOnRollover(format.iParserTag))
1.341 + DoCursorOverTag(curPos, parser, start, length);
1.342 + else if (curPos)
1.343 + {
1.344 + GetExtendedCharFormat(format, varies, curPos - 1, 1);
1.345 + // Try the char "before" curpos
1.346 + if (CParserList::ReformatOnRollover(format.iParserTag))
1.347 + DoCursorOverTag(curPos - 1, parser, start, length);
1.348 + }
1.349 + }
1.350 +
1.351 + MParser* parser = iParserData->iActiveParserList->ParserWithThisTag(aFormat.iParserTag);
1.352 +
1.353 + if (length && (aStartPos >= start) && (aStartPos < start + length))
1.354 + {
1.355 + if (start + length < aStartPos + aText.Length())
1.356 + aText.Set(aText.Left(start + length - aStartPos));
1.357 + if (parser != NULL)
1.358 + {
1.359 + // Only accept the rollover format if the parser agrees
1.360 + // with the framework match of a tag
1.361 + if (parser->ConfirmCursorOverTag(*this, start, length, curPos))
1.362 + parser->GetRolloverFormat(aFormat.iCharFormat);
1.363 + else
1.364 + // Reset format to recognised format if parser disagrees
1.365 + // with the framework match as the tag is still in view
1.366 + // and must be formatted as in the else clause below.
1.367 + parser->GetRecogniseFormat(aFormat.iCharFormat);
1.368 + }
1.369 + }
1.370 + else
1.371 + {
1.372 + if (length && (start > aStartPos))
1.373 + aText.Set(aText.Left(start - aStartPos));
1.374 + if (parser != NULL)
1.375 + parser->GetRecogniseFormat(aFormat.iCharFormat);
1.376 + }
1.377 + }
1.378 + }
1.379 +
1.380 +
1.381 +void CRichText::CallEditObserver(TInt aStart, TInt aExtent) const
1.382 + {
1.383 + if (iParserData->iEditObserver)
1.384 + iParserData->iEditObserver->EditObserver(aStart, aExtent);
1.385 + }