--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/webengine/wmlengine/src/css/src/CSSVariableStyleSheet.cpp Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,1074 @@
+/*
+* Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Contains all CSS styles
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <e32def.h> // First to avoid NULL redefine warning (no #ifndef NULL).
+#include <f32file.h>
+#include "nw_css_defaultstylesheet.h"
+#include <nwx_assert.h>
+#include "nwx_settings.h"
+#include "nwx_ctx.h"
+#include "nwx_logger.h"
+#include "CSSReader.h"
+#include "CSSPropVal.h"
+#include "CSSDeclListHandle.h"
+#include "CSSVariableStyleSheet.h"
+#include "nw_xhtml_xhtml_1_0_tokens.h"
+
+#include <bldvariant.hrh>
+#include <data_caging_path_literals.hrh>
+
+// ================================= CONSTANTS ====================================
+
+#define ASCII_LEFT_BRACE '{'
+#define ASCII_RIGHT_BRACE '}'
+#define ASCII_NULL '\0'
+
+static const NW_Ucs2 CSS_CURLY_BRACES[] = {ASCII_LEFT_BRACE, ASCII_RIGHT_BRACE, ASCII_NULL};
+
+/* User Supplied Style Sheet
+ * The user can provide a style sheet that will override the operator
+ * provided one.
+ * The user provided sheet is stored in the emulator at:
+ * K:\epoc32\wins\c\System\data
+ * The operator provided sheet is stored in the emulator at:
+ * K:\epoc32\release\wins\udeb\z\system\data
+ *
+ * Note that since 3.0, these location will change as defined in
+ * data_caging_path_literals.hrh
+ */
+void CCSSVariableStyleSheet::ConstructCSSFileName()
+{
+ // Literals for files ( drive, directory, filename(s) )
+ _LIT(KZDrive,"z:");
+ _LIT(KCDrive,"c:");
+
+ // _LIT(KDC_APP_RESOURCE_DIR,"\\resource\\apps\\uiresourcefiles\\"); // Application resource (.rsc)
+ // _LIT(KDC_RESOURCE_FILES_DIR,"\\resource\\"); // Other resource files
+
+ _LIT(KFileName,"oem.css");
+
+ CSS_USER_SUPPLIED_FILE.Zero();
+ CSS_USER_SUPPLIED_FILE += KCDrive;
+ CSS_USER_SUPPLIED_FILE += KDC_RESOURCE_FILES_DIR;
+ CSS_USER_SUPPLIED_FILE += KFileName;
+ CSS_USER_SUPPLIED_FILE.ZeroTerminate();
+
+ CSS_OPERATOR_SUPPLIED_FILE.Zero();
+ CSS_OPERATOR_SUPPLIED_FILE += KZDrive;
+ CSS_OPERATOR_SUPPLIED_FILE += KDC_RESOURCE_FILES_DIR;
+ CSS_OPERATOR_SUPPLIED_FILE += KFileName;
+ CSS_OPERATOR_SUPPLIED_FILE.ZeroTerminate();
+}
+
+#ifdef _DEBUG
+static const NW_Ucs2 CSS_INVALID_TOKEN[] = {'*','E','R','R','O','R','*','\0'};
+static const NW_Ucs2 CSS_VARIABLE[] = {'v','a','r','\0'};
+static const NW_Ucs2 CSS_DEFAULT[] = {'d','e','f','\0'};
+static const NW_Ucs2 CSS_HEX_FORMAT[] = {'0','x','%','6','.','6','X','\0'};
+static const NW_Ucs2 CSS_FLOAT_FORMAT[] = {'%','1','0','f','\0'};
+
+#define NW_XHTML_1_0_INDEX 1
+#endif /* _DEBUG */
+
+// ============================ CONSTRUCTOR/DESTRUCTOR ===============================
+
+void CCSSVariableStyleSheet::operator=(const CCSSVariableStyleSheet& aObj){
+NW_REQUIRED_PARAM( &aObj );
+}
+
+// -----------------------------------------------------------------------------
+// Symbian two phase constructor.
+// -----------------------------------------------------------------------------
+
+void CCSSVariableStyleSheet::ConstructL()
+{
+ HBufC8* buffer = NULL;
+
+ //Initially nothing is loaded.
+ iStaticCSSLoaded = EFalse;
+ iVariableCSSLoaded = EFalse;
+
+ //Create the lists. Pick a course granularity, they will be compressed
+ //after completion. Minimize churning as we add components.
+ iPropList = new (ELeave) CCSSPropEntryList(10);
+ iStringList = new (ELeave) CCSSStringEntryList(5);
+ ConstructCSSFileName();
+
+ buffer = ReadVariableCSSFile();
+ AddDefaultStyleStrings();
+ AddVariableStyles(buffer);
+ AddDefaultStyleProperties();
+ delete buffer;
+#ifdef _DEBUG
+ DumpVariableStyleSheet();
+#endif /* _DEBUG */
+}
+
+CCSSVariableStyleSheet* CCSSVariableStyleSheet::NewL()
+ {
+ CCSSVariableStyleSheet* self = new( ELeave ) CCSSVariableStyleSheet();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+
+// -----------------------------------------------------------------------------
+// Destructor.
+// Close and delete the lists. The destructors of each of the objects
+// will be called implicitly as a result.
+// -----------------------------------------------------------------------------
+
+CCSSVariableStyleSheet::~CCSSVariableStyleSheet()
+{
+ TInt count;
+ TInt index;
+
+ //Walk through the RArray. For each entry, if it references a dynamic
+ //entry (e.g. variable) delete the referenced object. Otherwise don't
+ //do anything with the entry itself. Then close and delete the array.
+ if (iPropList != NULL){
+ count = iPropList->Count();
+ for(index=0; index<count; index++){
+ TCSSPropEntry& propEntry = iPropList->operator[](index);
+ if (propEntry.variableEntry == TRUE){
+ delete propEntry.entry->pattern;
+ delete propEntry.entry;
+ }
+ }
+ iPropList->Close();
+ delete iPropList;
+ }
+
+ if (iStringList != NULL){
+ count = iStringList->Count();
+ for(index=0; index<count; index++){
+ TCSSStringEntry& stringEntry = iStringList->operator[](index);
+ if (stringEntry.variableEntry == TRUE){
+ delete stringEntry.entry;
+ }
+ }
+ iStringList->Close();
+ delete iStringList;
+ }
+}
+
+
+// ============================ PUBLIC METHODS ===============================
+
+// -----------------------------------------------------------------------------
+// CCSSVariableStyleSheet::CreateSingleton
+//
+// Creates the CCSSVariableStyleSheet singleton.
+// -----------------------------------------------------------------------------
+
+CCSSVariableStyleSheet* CCSSVariableStyleSheet::CreateSingleton()
+{
+ CCSSVariableStyleSheet* thisObj = CCSSVariableStyleSheet::GetSingleton();
+ if (thisObj == NULL){
+ TRAPD(ret, thisObj = CCSSVariableStyleSheet::NewL());
+ if (ret != KErrNone)
+ return NULL;
+ TRAP(ret, NW_Ctx_Set(NW_CTX_VARIABLE_CSS, 0, (void*)thisObj));
+ if (ret != KErrNone)
+ return NULL;
+ }
+ return thisObj;
+}
+
+
+// -----------------------------------------------------------------------------
+// CCSSVariableStyleSheet::DeleteSingleton
+//
+// Deletes the CCSSVariableStyleSheet singleton.
+// -----------------------------------------------------------------------------
+
+void CCSSVariableStyleSheet::DeleteSingleton()
+{
+ CCSSVariableStyleSheet* thisObj = CCSSVariableStyleSheet::GetSingleton();
+ if (thisObj != NULL){
+ delete thisObj;
+ NW_Ctx_Set(NW_CTX_VARIABLE_CSS, 0, NULL);
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// CCSSVariableStyleSheet::GetSingleton
+//
+// Get the CCSSVariableStyleSheet singleton. If it doesn't already exist then returns null.
+// -----------------------------------------------------------------------------
+
+CCSSVariableStyleSheet* CCSSVariableStyleSheet::GetSingleton()
+{
+ CCSSVariableStyleSheet* thisObj = (CCSSVariableStyleSheet*) NW_Ctx_Get(NW_CTX_VARIABLE_CSS, 0);
+ return thisObj;
+}
+
+
+// -----------------------------------------------------------------------------
+// CCSSVariableStyleSheet::ApplyStyles
+//
+// Applies the combined default and variable styles.
+// -----------------------------------------------------------------------------
+
+TBrowserStatusCode
+ CCSSVariableStyleSheet::ApplyStyles(NW_DOM_ElementNode_t* aElementNode,
+ NW_LMgr_Box_t* aBox,
+ NW_WBXML_Dictionary_t* aDictionary,
+ const NW_Evt_Event_t* aEvent,
+ NW_HED_DocumentNode_t* aDocNode,
+ NW_HED_DomHelper_t* aDomHelper)
+{
+ const NW_CSS_DefaultStyleSheet_PropEntry_t* propertyVal;
+ TInt index, numPropertyVals;
+ NW_Uint16 tagToken;
+ const TCSSPropertyTablePropEntry* propEntry;
+ TBrowserStatusCode status = KBrsrSuccess;
+ NW_LMgr_Property_t prop;
+ CCSSNodeData nodeData;
+ TCSSPropEntry startEntry;
+
+ tagToken = NW_DOM_ElementNode_getTagToken(aElementNode);
+ numPropertyVals = iPropList->Count();
+
+ //The entries are in order based on a key comprised of the element token
+ //and the element name. The old algorithm searched through the array
+ //until it found the first element token that matched. This algorithm lets
+ //the binary search algorithm of the array do the work of finding the first
+ //element that matches, or at least where to start looking. The looking stops
+ //when a key is found that is greater than the token OR the end of the array
+ //is reached.
+
+ //Create a dummy entry with a search key that starts with the first
+ //entry (if it exists) for this token and a default name of 0. If no
+ //entry exists we will start at the place it WOULD exist. The search
+ //will fail quickly in that case.
+
+ startEntry.key = (tagToken << 16) | 0;
+ iPropList->FindInUnsignedKeyOrder(startEntry, index);
+
+ for(; index < numPropertyVals; index++){
+ NW_Byte *pattern;
+ propertyVal = iPropList->operator[](index).entry;
+
+ if (propertyVal->elementToken < tagToken)
+ continue;
+
+ if (propertyVal->elementToken > tagToken)
+ return KBrsrSuccess;
+
+ /* match pattern - if pattern matches apply style */
+ pattern = propertyVal->pattern;
+ if (pattern != NULL){
+ NW_Uint32 numBytes;
+ CCSSPatternMatcher patternMatcher(aDictionary, aDocNode, aDomHelper);
+ TBool matched = EFalse;
+
+ (void) NW_String_charBuffGetLength(pattern, HTTP_us_ascii, &numBytes);
+ TCSSParser parser(pattern, numBytes, HTTP_us_ascii);
+
+ TRAPD(ret, matched = patternMatcher.MatchPatternLazyL(aElementNode, &parser, pattern, aEvent, &nodeData));
+ if (ret == KErrNoMemory)
+ return KBrsrOutOfMemory;
+
+ if (!matched)
+ continue;
+ }
+
+ propEntry = TCSSPropertyTable::GetPropEntryByToken(propertyVal->name);
+ if (propEntry == NULL)
+ continue;
+
+ status = InitProperty(propEntry, &prop, aBox, propertyVal->val, propertyVal->valType);
+ if (status == KBrsrOutOfMemory)
+ return status;
+ if (status != KBrsrSuccess)
+ continue;
+
+ /*
+ Rules are arranged by decreasing specificity. If a property is
+ already present, it can be replaced only if the other property is
+ marked important. All defaults are NOT important.
+ */
+ TInt ret;
+ TRAP(ret, TCSSDeclListHandle::ApplyPropertyL(propEntry->tokenName, &prop, 1,
+ EFalse, NULL, aBox, ETrue));
+
+ if ((prop.type == NW_CSS_ValueType_Text) ||(prop.type == NW_CSS_ValueType_Image)){
+ NW_Object_Delete(prop.value.object);
+ }
+ }
+ return status;
+}
+
+
+// ============================ PRIVATE METHODS ===============================
+
+
+// -----------------------------------------------------------------------------
+// CCSSVariableStyleSheet::ReadVariableCSSFile
+//
+// Loads the file into a buffer.
+// -----------------------------------------------------------------------------
+
+HBufC8*
+CCSSVariableStyleSheet::ReadVariableCSSFile()
+{
+ HBufC8* buffer = NULL;
+
+ if ((buffer = ReadFile(CSS_USER_SUPPLIED_FILE)) == NULL)
+ {
+ buffer = ReadFile(CSS_OPERATOR_SUPPLIED_FILE);
+ }
+
+ return buffer;
+}
+
+
+//Returns a HBufC8 with the contents of aFile
+HBufC8*
+CCSSVariableStyleSheet::ReadFile(const TDesC& aFile)
+{
+ RFs fs;
+ RFile file;
+ TInt size = 0;
+ HBufC8* contents = NULL;
+
+ if (fs.Connect() != KErrNone )
+ return contents;
+
+ if (file.Open(fs, aFile, EFileShareAny | EFileRead) != KErrNone )
+ {
+ fs.Close();
+ return contents;
+ }
+
+ //The file exists, allocate enough space for the NULL termination later.
+ file.Size(size);
+ if ((size != 0) && ((contents = HBufC8::New(size + 4)) != NULL))
+ {
+ //We have opened the file and it has a non-zero size and we have allocated memory
+ TPtr8 contentsPtr(contents->Des());
+ if (file.Read(contentsPtr, size)!= KErrNone)
+ {
+ delete contents;
+ contents = NULL;
+ }
+ }
+
+ file.Close();
+ fs.Close();
+ return contents;
+}
+
+
+// -----------------------------------------------------------------------------
+// CCSSVariableStyleSheet::AddVariableStyles
+//
+// Adds the variable styles to the default list.
+// -----------------------------------------------------------------------------
+
+TBool CCSSVariableStyleSheet::AddVariableStyles(HBufC8* aBuffer)
+{
+ iVariableCSSLoaded = EFalse;
+ if (aBuffer != NULL)
+ {
+ iVariableCSSLoaded = ProcessBuffer(aBuffer->Ptr(), aBuffer->Length());
+ }
+ else
+ {
+ iVariableCSSLoaded = EFalse;
+ }
+ return iVariableCSSLoaded;
+}
+
+
+// -----------------------------------------------------------------------------
+// CCSSVariableStyleSheet::ProcessBuffer
+//
+// Adds the variable styles to the default list.
+// -----------------------------------------------------------------------------
+TBool CCSSVariableStyleSheet::ProcessBuffer(const TUint8* aBuffer, TUint32 aLength)
+{
+ TInt index = 0;
+ TInt size = 0;
+ TUint32 charset = HTTP_us_ascii;
+ CCSSRuleList* ruleList = NULL;
+ CCSSRuleListElementEntry* entry = NULL;
+
+ TCSSParser parser((TUint8*)aBuffer, aLength, charset) ;
+
+ TRAPD(ret, ruleList = CCSSRuleList::NewL(NULL));
+ if (ret != KErrNone)
+ return EFalse;
+
+ ruleList->SetDictionary((NW_WBXML_Dictionary_t *) &NW_XHTML_WBXMLDictionary);
+
+ ruleList->ProcessBuffer((TText8*)aBuffer, aLength, charset, ETrue); // delete buffer with ruleList
+ size = ruleList->GetSize();
+
+ for (index = 0; index < size; index++)
+ {
+ entry = ruleList->GetElementRulesByIndex(index);
+ if (entry != NULL)
+ {
+ UpdateList(&parser, entry->iRules, entry->iElementToken);
+ }
+ }
+ delete ruleList;
+ return ETrue;
+}
+
+// -----------------------------------------------------------------------------
+// CCSSVariableStyleSheet::AddDefaultStyleStrings
+//
+// Adds the default style string to the default list.
+// -----------------------------------------------------------------------------
+
+void CCSSVariableStyleSheet::AddDefaultStyleStrings()
+{
+ NW_Uint32 numVals;
+ NW_Ucs2** stringVals;
+ const NW_CSS_DefaultStyleSheet_t* defaultCSS;
+ NW_Uint32 index;
+ TCSSStringEntry stringEntry;
+ NW_Ucs2* stringVal;
+
+ defaultCSS = &NW_CSS_DefaultStyleSheet;
+ numVals = NW_CSS_DefaultStyleSheet_GetClassPart(defaultCSS).numStringVals;
+ stringVals = (NW_Ucs2**)(NW_CSS_DefaultStyleSheet_GetClassPart(defaultCSS).stringVals);
+
+ for(index = 0; index < numVals; index++)
+ {
+ // Decode all the data in this structure and add to the array. No
+ // duplicates are allowed. The variable stuff was already added so
+ // this is a lower priority.
+ stringEntry.variableEntry = EFalse;
+ stringVal = stringVals[index];
+ stringEntry.entry = stringVal;
+ iStringList->Append(stringEntry);
+ }
+
+ iStaticCSSLoaded = ETrue;
+}
+
+
+// -----------------------------------------------------------------------------
+// CCSSVariableStyleSheet::AddDefaultStyleProps
+//
+// Adds the default style properties to the default list.
+// -----------------------------------------------------------------------------
+
+void CCSSVariableStyleSheet::AddDefaultStyleProperties()
+{
+ NW_Uint32 numVals;
+ NW_CSS_DefaultStyleSheet_PropEntry_s* propertyVals;
+ const NW_CSS_DefaultStyleSheet_t* defaultCSS;
+ NW_Uint32 index;
+ TCSSPropEntry propEntry;
+
+ defaultCSS = &NW_CSS_DefaultStyleSheet;
+ numVals = NW_CSS_DefaultStyleSheet_GetClassPart(defaultCSS).numPropertyVals;
+ propertyVals = (NW_CSS_DefaultStyleSheet_PropEntry_s*)(NW_CSS_DefaultStyleSheet_GetClassPart(defaultCSS).propertyVals);
+
+ for(index = 0; index < numVals; index++)
+ {
+ // Decode all the data in this structure and add to the array. No
+ // duplicates are allowed. The variable stuff was already added so
+ // this is a lower priority.
+
+ propEntry.key = (propertyVals[index].elementToken <<16) | (propertyVals[index].name);
+ propEntry.variableEntry = EFalse;
+ propEntry.entry = &(propertyVals[index]);
+
+ //Insert the property. If this was a duplicate we ignore it. Ignore return value
+ InsertProperty(propEntry);
+ }
+ iStaticCSSLoaded = ETrue;
+}
+
+
+// -----------------------------------------------------------------------------
+// CCSSVariableStyleSheet::InsertProperty
+//
+// Applies the styles to the property.
+// -----------------------------------------------------------------------------
+TInt CCSSVariableStyleSheet::InsertProperty(TCSSPropEntry aPropEntry)
+{
+ TCSSPropEntry compareEntry;
+ TInt searchIndex;
+ if (iPropList->FindInUnsignedKeyOrder(aPropEntry, searchIndex) == KErrNone){
+ //A duplicate primary key was found. Check secondary key
+ //(e.g. pattern) to see if this is really a duplicate. Only insert
+ //if the pattern specified matches none of the existing ones.
+
+ //Multiple entries with the same key exist. Walk back until we find
+ //the first one. The binary search that returned this index doesn't
+ //always return the first entry in the list of duplicate keys.
+ while (searchIndex >= 0){
+ compareEntry = iPropList->operator[](searchIndex);
+ if (compareEntry.key != aPropEntry.key){
+ searchIndex++;
+ break;
+ }
+ if (searchIndex == 0){
+ break;
+ }
+ searchIndex--;
+ }
+
+ //Search until primary keys no longer match.
+ while (searchIndex < iPropList->Count()){
+ compareEntry = iPropList->operator[](searchIndex);
+ if (compareEntry.key != aPropEntry.key){
+ //duplicate not found in primary key so no more duplicates.
+ //Add to list.
+ break;
+ }
+
+ //We have matching primary keys. Check secondary. Watch out for nulls.
+ //This messy because NW_Asc_strcmp doesn't handle nulls.
+ if ((compareEntry.entry->pattern == NULL)&&(aPropEntry.entry->pattern == NULL) ||
+ (compareEntry.entry->pattern != NULL)&&(aPropEntry.entry->pattern != NULL) ){
+ //Either both or neither null
+ if ((compareEntry.entry->pattern == aPropEntry.entry->pattern) ||
+ !NW_Asc_strcmp((char*)(compareEntry.entry->pattern), (char*)(aPropEntry.entry->pattern))){
+ //Secondary match found. Either both pointers are null or the
+ //strings are the same. This is really a duplicate.
+ //Don't add to list.
+ searchIndex = -1;
+ break;
+ }
+ }
+ //If you got here than primary keys matched but pattern didn't match.
+ //Keep checking.
+ searchIndex++;
+ }
+ //If you got here then you hit the end of the list while primary
+ //keys matched but pattern didn't. Add it at the end which is
+ //where the index should be pointing.
+ }
+
+ //Insert at the calculated index if a valid index. This is not a duplicate.
+ if (searchIndex != -1){
+ iPropList->Insert(aPropEntry, searchIndex);
+ }
+ return searchIndex;
+}
+
+
+// -----------------------------------------------------------------------------
+// CCSSVariableStyleSheet::InitProperty
+//
+// Applies the styles to the property.
+// -----------------------------------------------------------------------------
+
+TBrowserStatusCode
+CCSSVariableStyleSheet::InitProperty(const TCSSPropertyTablePropEntry* aPropEntry,
+ NW_LMgr_Property_t* aProp,
+ NW_LMgr_Box_t* aBox,
+ NW_Float32 aVal,
+ NW_Uint8 aValType)
+{
+ aProp->type = aValType;
+
+ switch(aValType)
+ {
+ case NW_CSS_ValueType_Integer:
+ case NW_CSS_ValueType_Px:
+ case NW_CSS_ValueType_Color:
+ aProp->value.integer = (NW_Int32)aVal;
+ break;
+ case NW_CSS_ValueType_Number:
+ case NW_CSS_ValueType_In:
+ case NW_CSS_ValueType_Cm:
+ case NW_CSS_ValueType_Mm:
+ case NW_CSS_ValueType_Pt:
+ case NW_CSS_ValueType_Pc:
+ case NW_CSS_ValueType_Em:
+ case NW_CSS_ValueType_Ex:
+ case NW_CSS_ValueType_Percentage:
+ aProp->value.decimal = aVal;
+ break;
+ case NW_CSS_ValueType_Token:
+ {
+ TBool set = TCSSPropVal::SetTokenVal( aPropEntry->tokenName, aProp, (NW_Uint32) (NW_Int32) aVal, aBox);
+ return set? KBrsrSuccess:KBrsrFailure;
+ }
+ case NW_CSS_ValueType_Text:
+ {
+ const NW_Ucs2* ucs2Str;
+ NW_Text_Length_t length;
+
+ if (aVal >= iStringList->Count())
+ return KBrsrFailure;
+
+ ucs2Str = iStringList->operator[]((NW_Int32)aVal).entry;
+ length = (NW_Text_Length_t)(NW_Str_Strlen(ucs2Str));
+
+ aProp->value.object = NW_Text_UCS2_New ((NW_Ucs2*) ucs2Str, length, 0);
+ if (aProp->value.object == NULL)
+ return KBrsrOutOfMemory;
+
+ break;
+ }
+ default:
+ return KBrsrFailure;
+ }
+
+ return KBrsrSuccess;
+}
+
+
+// -----------------------------------------------------------------------------
+// CCSSVariableStyleSheet::UpdateList
+//
+//
+// -----------------------------------------------------------------------------
+TBrowserStatusCode
+CCSSVariableStyleSheet::UpdateList(TCSSParser* aParser,
+ CCSSRules* aRuleList,
+ TUint16 aElementToken)
+{
+ TInt index;
+ TInt size;
+ TBrowserStatusCode status;
+
+ size = aRuleList->Count();
+ for (index = 0; index < size; index++)
+ {
+ CCSSSelector* entry;
+ TUint32 specificity;
+ TText16* patternStr;
+ char* asciiPatternStr;
+ TText8* selectorEndPosition;
+ TCSSSimpleSelector simpleSelector;
+ TCSSReaderUnit unit;
+ TText8* declarationList;
+
+ entry = aRuleList->At(index);
+ aParser->SetPosition(entry->iSelector);
+ specificity = 0;
+ patternStr = NULL;
+ asciiPatternStr = NULL;
+ simpleSelector.specificity = 0;
+
+ do{
+ specificity += simpleSelector.specificity;
+ status = aParser->SimpleSelectorListIterate(&simpleSelector);
+ }while (status == KBrsrIterateMore);
+
+ if (status != KBrsrIterateDone)
+ continue;
+
+ selectorEndPosition = aParser->GetPosition();
+ if (specificity > 1)
+ {
+ unit.Init(entry->iSelector, selectorEndPosition - entry->iSelector, 0);
+ patternStr = unit.GetUnicode(aParser->GetEncoding());
+
+ if (patternStr != NULL)
+ {
+ //Add the curly braces back into the pattern. These are
+ //required for parsing later on. Revove whitespace before adding curly
+ //braces. If you decide to remove leading whitespace then save the
+ //pointer so you can delete it later.
+ NW_Str_TrimInPlace(patternStr, NW_Str_End);
+ TText16* tempStr = NW_Str_Newcat(patternStr, CSS_CURLY_BRACES);
+ if (tempStr != NULL)
+ {
+ asciiPatternStr = NW_Str_CvtToAscii(tempStr);
+ delete tempStr;
+ }
+ delete patternStr;
+ }
+ }
+
+ (aParser->GetReader())->GoToToken(LEFT_BRACE, &declarationList);
+ NW_ASSERT(declarationList);
+ UpdateEntry(aParser, aElementToken, asciiPatternStr);
+ }
+ return KBrsrSuccess;
+}
+
+// -----------------------------------------------------------------------------
+// CCSSVariableStyleSheet::UpdateEntry
+//
+//
+// -----------------------------------------------------------------------------
+TBrowserStatusCode
+CCSSVariableStyleSheet::UpdateEntry(TCSSParser* aParser,
+ TUint16 aElementToken,
+ char* aAsciiPatternStr)
+{
+ TBool important;
+ TCSSReaderUnit propertyName;
+ TCSSPropertyVal propertyVal;
+ TUint8 numVals;
+ TCSSPropEntry entryWrapper;
+ TCSSStringEntry stringWrapper;
+ NW_CSS_DefaultStyleSheet_PropEntry_s* entry;
+ const TCSSPropertyTablePropEntry* propEntry;
+ NW_LMgr_PropertyValue_t val;
+ NW_LMgr_PropertyValueType_t valType;
+ TText16* ucs2Str = NULL;
+ TText16* valStorage = NULL;
+ TUint32 encoding;
+
+ while (aParser->DeclarationListIterate(&propertyName, &propertyVal, &numVals, 1, &important)
+ == KBrsrIterateMore)
+ {
+ if (propertyName.iLength == 0)
+ continue;
+
+ encoding = aParser->GetEncoding();
+ ucs2Str = propertyName.GetUnicode(encoding);
+ if ((ucs2Str == NULL) || (propertyVal.type == -1))
+ continue;
+
+ propEntry = TCSSPropertyTable::GetPropertyEntry(ucs2Str);
+ delete(ucs2Str);
+ if (propEntry == NULL)
+ continue;
+
+ valStorage = propertyVal.val.GetUnicode(encoding);
+ if (valStorage == NULL)
+ continue;
+
+ valType = SetPropertyVal(aParser, propEntry, &val, &propertyVal, valStorage);
+ if (valType == 0)
+ continue;
+
+ /* create a new entry to and initialize it */
+ entry = new NW_CSS_DefaultStyleSheet_PropEntry_s;
+ entryWrapper.variableEntry = ETrue;
+ entryWrapper.entry = entry;
+ entryWrapper.key = (aElementToken <<16) | propEntry->tokenName;
+
+ entry->elementToken = aElementToken;
+ entry->pattern = (unsigned char *)aAsciiPatternStr;
+ entry->name = propEntry->tokenName;
+ entry->valType = valType;
+ switch (valType)
+ {
+ case NW_CSS_ValueType_Percentage:
+ case NW_CSS_ValueType_Em:
+ case NW_CSS_ValueType_In:
+ case NW_CSS_ValueType_Cm:
+ case NW_CSS_ValueType_Mm:
+ case NW_CSS_ValueType_Pt:
+ case NW_CSS_ValueType_Pc:
+ entry->val = (NW_Float32)val.decimal;
+ break;
+ case NW_CSS_ValueType_Token:
+ entry->val = (NW_Float32)val.token;
+ break;
+ case NW_CSS_ValueType_Px:
+ case NW_CSS_ValueType_Integer:
+ case NW_CSS_ValueType_Ex:
+ case NW_CSS_ValueType_Color:
+ entry->val = (NW_Float32)val.integer;
+ break;
+ case NW_CSS_ValueType_Text:
+ {
+ stringWrapper.variableEntry = ETrue;
+ stringWrapper.entry = valStorage;
+ valStorage = NULL;
+ iStringList->Append(stringWrapper);
+ //Index of this entry is count - 1
+ entry->val = (NW_Float32)(iStringList->Count() - 1);
+ break;
+ }
+ default:
+ entry->val = (NW_Float32)val.integer;
+ break;
+ }
+ delete valStorage;
+
+ if (InsertProperty(entryWrapper) == -1)
+ {
+ //This was a duplicate. It wasn't added to list. Free memory.
+ delete entry->pattern;
+ delete entry;
+ }
+ }
+
+
+ return KBrsrSuccess;
+}
+
+// -----------------------------------------------------------------------------
+// CCSSVariableStyleSheet::SetPropertyVal
+//
+
+NW_LMgr_PropertyValueType_t
+CCSSVariableStyleSheet::SetPropertyVal(TCSSParser* aParser,
+ const TCSSPropertyTablePropEntry* aPropEntry,
+ NW_LMgr_PropertyValue_t* aVal,
+ TCSSPropertyVal* aPropertyVal,
+ TText16* aValStorage)
+{
+ NW_LMgr_PropertyValueToken_t token;
+ TBool result = EFalse;
+ NW_Float32 v;
+ TText16* endPtr = NULL;
+
+
+ if ((aPropertyVal->type == RGB) || (aPropertyVal->type == HASH)){
+ //COLOR
+ NW_LMgr_Property_t tmpVal;
+ tmpVal.value.integer = 0; //remove warning
+ tmpVal.type = 0;
+
+ TRAPD( err, result = TCSSPropVal::SetColorL( aParser, &tmpVal, aPropertyVal, aValStorage));
+ if ((err != KErrNone) || !result)
+ return 0;
+
+ aVal->integer = tmpVal.value.integer;
+ return NW_CSS_ValueType_Color;
+ }
+
+ if (aPropertyVal->type == IDENTIFIER){
+ //TOKEN
+ if(aPropEntry->tokenName != NW_CSS_Prop_fontFamily) {
+ if (TCSSPropertyTable::GetPropertyValToken(aValStorage, &token)){
+ aVal->token = token;
+ return NW_CSS_ValueType_Token;
+ }
+ }
+ }
+
+ if ((aPropertyVal->type == IDENTIFIER) || (aPropertyVal->type == STRING)){
+ //TEXT
+ /* If the identifier is not recognized as a token OR it is a real
+ string interpret is as a string */
+ return NW_CSS_ValueType_Text;
+ }
+
+ //NUMBER - If not one of the above it must be a number.
+
+ if ( NW_Str_CvtToFloat32(aValStorage, &endPtr, &v) != KBrsrSuccess)
+ return 0;
+
+ switch (aPropertyVal->type)
+ {
+ case NUMBER:
+ /* This code is the point that default units of measure are
+ applied. This is a convenience. According to the spec. only the
+ value zero can omit the units. However, defaults are usually
+ inserted. */
+ switch (aPropEntry->tokenName)
+ {
+ // PIXEL Defaults
+ case NW_CSS_Prop_borderWidth:
+ case NW_CSS_Prop_topBorderWidth:
+ case NW_CSS_Prop_bottomBorderWidth:
+ case NW_CSS_Prop_leftBorderWidth:
+ case NW_CSS_Prop_rightBorderWidth:
+
+ case NW_CSS_Prop_padding:
+ case NW_CSS_Prop_topPadding:
+ case NW_CSS_Prop_bottomPadding:
+ case NW_CSS_Prop_leftPadding:
+ case NW_CSS_Prop_rightPadding:
+
+ case NW_CSS_Prop_margin:
+ case NW_CSS_Prop_topMargin:
+ case NW_CSS_Prop_bottomMargin:
+ case NW_CSS_Prop_leftMargin:
+ case NW_CSS_Prop_rightMargin:
+ aVal->integer = (TInt32)v;
+ return NW_CSS_ValueType_Px;
+
+ //INTEGER defaults
+ case NW_CSS_Prop_font:
+ case NW_CSS_Prop_fontSize:
+ case NW_CSS_Prop_fontWeight:
+ case NW_CSS_Prop_marqueeSpeed:
+ case NW_CSS_Prop_marqueeLoop:
+ default:
+ aVal->integer = (TInt32)v;
+ return NW_CSS_ValueType_Integer;
+ }
+
+ case PERCENTAGE:
+ aVal->decimal = v;
+ return NW_CSS_ValueType_Percentage;
+
+ case EMS:
+ aVal->decimal = v;
+ return NW_CSS_ValueType_Em;
+
+ case EXS:
+ aVal->decimal = v;
+ return NW_CSS_ValueType_Ex;
+
+ case PXS:
+ aVal->integer =(TInt32)v;
+ return NW_CSS_ValueType_Px;
+
+ case INS:
+ aVal->decimal = v;
+ return NW_CSS_ValueType_In;
+
+ case CMS:
+ aVal->decimal = v;
+ return NW_CSS_ValueType_Cm;
+
+ case MMS:
+ aVal->decimal = v;
+ return NW_CSS_ValueType_Mm;
+
+ case PCS:
+ aVal->decimal = v;
+ return NW_CSS_ValueType_Pc;
+
+ case PTS:
+ aVal->decimal = v;
+ return NW_CSS_ValueType_Pt;
+
+ //default:
+ //return 0;
+ }
+ return 0;
+}
+
+
+// -----------------------------------------------------------------------------
+// CCSSVariableStyleSheet::DumpVariableStyleSheet
+//
+// -----------------------------------------------------------------------------
+#ifdef _DEBUG
+
+TBrowserStatusCode
+CCSSVariableStyleSheet::DumpVariableStyleSheet()
+{
+ TInt count;
+ TInt index;
+
+ NW_LOG0(NW_LOG_LEVEL3, "*** Printing Variable Style Sheet ****");
+ //Walk through the RArray. For each entry, if it references a dynamic
+ //entry (e.g. variable) delete the referenced object. Otherwise don't
+ //do anything with the entry itself. Then close and delete the array.
+
+ if (iPropList != NULL){
+ NW_Ucs2 tmpString[40];
+ NW_Ucs2* valString;
+ NW_Ucs2* elementString;
+ NW_Ucs2* patternString;
+ NW_Int32 tmpInt;
+
+ count = iPropList->Count();
+ NW_LOG1(NW_LOG_LEVEL3, "CSS Property List - %d entries", count);
+ for(index=0; index<count; index++){
+ TCSSPropEntry& propEntry = iPropList->operator[](index);
+
+ const TCSSPropertyTablePropEntry* propTableEntry =
+ TCSSPropertyTable::GetPropEntryByToken(propEntry.entry->name);
+
+ switch(propEntry.entry->valType){
+ case NW_CSS_ValueType_Color:
+ tmpInt = (NW_Int32)(propEntry.entry->val);
+ NW_Str_Sprintf(tmpString, CSS_HEX_FORMAT, tmpInt);
+ valString = tmpString;
+ break;
+ case NW_CSS_ValueType_Token:
+ {
+ tmpInt = (NW_Int32)(propEntry.entry->val);
+ const TCSSPropertyTablePropValEntry* valTableEntry =
+ TCSSPropertyTable::GetPropValEntryByToken ((NW_LMgr_PropertyValueToken_t)tmpInt);
+ valString = valTableEntry == NULL ? (NW_Ucs2*)CSS_INVALID_TOKEN : (NW_Ucs2*)valTableEntry->strVal;
+ }
+ break;
+ case NW_CSS_ValueType_Text:
+ if (propEntry.entry->val < iStringList->Count()){
+ tmpInt = (NW_Int32)(propEntry.entry->val);
+ TCSSStringEntry& stringEntry = iStringList->operator[](tmpInt);
+ valString = stringEntry.entry;
+ }else{
+ valString = (NW_Ucs2*)CSS_INVALID_TOKEN;
+ }
+ break;
+
+ case NW_CSS_ValueType_Number:
+ case NW_CSS_ValueType_Percentage:
+ case NW_CSS_ValueType_Em:
+ case NW_CSS_ValueType_Ex:
+ case NW_CSS_ValueType_In:
+ case NW_CSS_ValueType_Cm:
+ case NW_CSS_ValueType_Mm:
+ case NW_CSS_ValueType_Pc:
+ case NW_CSS_ValueType_Pt:
+ NW_Str_Sprintf(tmpString, CSS_FLOAT_FORMAT, propEntry.entry->val);
+ valString = tmpString;
+ break;
+ case NW_CSS_ValueType_Integer:
+ case NW_CSS_ValueType_Px:
+ default:
+ tmpInt = (NW_Int32)(propEntry.entry->val);
+ NW_Str_Itoa(tmpInt, tmpString);
+ valString = tmpString;
+ }
+
+ // Pattern string contains the element name. It it exists show it. Otherwise show element name
+ elementString = (NW_Ucs2*)NW_WBXML_Dictionary_getTagByFqToken((NW_XHTML_1_0_INDEX << 16) | propEntry.entry->elementToken);
+ if (elementString == NULL) {
+ elementString = (NW_Ucs2*)CSS_INVALID_TOKEN;
+ }
+
+ if (propEntry.entry->pattern == NULL){
+ patternString = NULL;
+ }else {
+ patternString = NW_Str_CvtFromAscii((const char*)(propEntry.entry->pattern));
+ NW_Str_Strcharreplace(patternString, ASCII_LEFT_BRACE, ASCII_NULL);
+ }
+
+ NW_LOG7(NW_LOG_LEVEL3,
+ "%3d %s key: 0x%06X %s{ %s: %s%s }",
+ //Wrapper
+ index,
+ propEntry.variableEntry == TRUE ? (NW_Ucs2*)CSS_VARIABLE:(NW_Ucs2*)CSS_DEFAULT,
+ propEntry.key,
+ //Entry
+ patternString == NULL ? elementString : patternString,
+ propTableEntry->strName,
+ valString,
+ TCSSPropertyTable::GetPropValType(propEntry.entry->valType));
+
+ delete patternString;
+ }
+ }
+
+ if (iStringList != NULL){
+ count = iStringList->Count();
+ NW_LOG1(NW_LOG_LEVEL3, "CSS String List - %d entries", count);
+ for(index=0; index<count; index++){
+ TCSSStringEntry& stringEntry = iStringList->operator[](index);
+ NW_LOG3(NW_LOG_LEVEL3, "%2d %s %s",
+ index,
+ stringEntry.variableEntry == TRUE ? (NW_Ucs2*)CSS_VARIABLE : (NW_Ucs2*)CSS_DEFAULT,
+ stringEntry.entry);
+ }
+ }
+ return KErrNone;
+}
+#endif /* _DEBUG */