webengine/wmlengine/src/css/src/CSSVariableStyleSheet.cpp
changeset 0 dd21522fd290
child 37 cb62a4f66ebe
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Contains all CSS styles
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include <e32def.h>  // First to avoid NULL redefine warning (no #ifndef NULL).
       
    22 #include <f32file.h>
       
    23 #include "nw_css_defaultstylesheet.h"
       
    24 #include <nwx_assert.h>
       
    25 #include "nwx_settings.h"
       
    26 #include "nwx_ctx.h"
       
    27 #include "nwx_logger.h"
       
    28 #include "CSSReader.h"
       
    29 #include "CSSPropVal.h"
       
    30 #include "CSSDeclListHandle.h"
       
    31 #include "CSSVariableStyleSheet.h"
       
    32 #include "nw_xhtml_xhtml_1_0_tokens.h"
       
    33 
       
    34 #include <bldvariant.hrh>
       
    35 #include <data_caging_path_literals.hrh>
       
    36 
       
    37 // ================================= CONSTANTS ====================================
       
    38 
       
    39 #define ASCII_LEFT_BRACE          '{'
       
    40 #define ASCII_RIGHT_BRACE         '}'
       
    41 #define ASCII_NULL                '\0'
       
    42 
       
    43 static const NW_Ucs2 CSS_CURLY_BRACES[] = {ASCII_LEFT_BRACE, ASCII_RIGHT_BRACE, ASCII_NULL};
       
    44 
       
    45 /* User Supplied Style Sheet
       
    46  * The user can provide a style sheet that will override the operator
       
    47  * provided one.
       
    48  * The user provided sheet is stored in the emulator at:
       
    49  *      K:\epoc32\wins\c\System\data
       
    50  * The operator provided sheet is stored in the emulator at:
       
    51  *      K:\epoc32\release\wins\udeb\z\system\data
       
    52  *
       
    53  * Note that since 3.0, these location will change as defined in
       
    54  * data_caging_path_literals.hrh
       
    55  */
       
    56 void CCSSVariableStyleSheet::ConstructCSSFileName()
       
    57 {
       
    58    // Literals for files ( drive, directory, filename(s) )
       
    59 	_LIT(KZDrive,"z:");
       
    60 	_LIT(KCDrive,"c:");
       
    61 
       
    62 	// _LIT(KDC_APP_RESOURCE_DIR,"\\resource\\apps\\uiresourcefiles\\");	//	Application resource (.rsc)
       
    63 	// _LIT(KDC_RESOURCE_FILES_DIR,"\\resource\\");				// 	Other resource files
       
    64 
       
    65 	_LIT(KFileName,"oem.css");
       
    66 
       
    67 	CSS_USER_SUPPLIED_FILE.Zero();
       
    68     CSS_USER_SUPPLIED_FILE += KCDrive;
       
    69     CSS_USER_SUPPLIED_FILE += KDC_RESOURCE_FILES_DIR;
       
    70     CSS_USER_SUPPLIED_FILE += KFileName;
       
    71     CSS_USER_SUPPLIED_FILE.ZeroTerminate();
       
    72 
       
    73 	CSS_OPERATOR_SUPPLIED_FILE.Zero();
       
    74     CSS_OPERATOR_SUPPLIED_FILE += KZDrive;
       
    75     CSS_OPERATOR_SUPPLIED_FILE += KDC_RESOURCE_FILES_DIR;
       
    76     CSS_OPERATOR_SUPPLIED_FILE += KFileName;
       
    77     CSS_OPERATOR_SUPPLIED_FILE.ZeroTerminate();
       
    78 }
       
    79 
       
    80 #ifdef _DEBUG
       
    81 static const NW_Ucs2 CSS_INVALID_TOKEN[] = {'*','E','R','R','O','R','*','\0'};
       
    82 static const NW_Ucs2 CSS_VARIABLE[] = {'v','a','r','\0'};
       
    83 static const NW_Ucs2 CSS_DEFAULT[] = {'d','e','f','\0'};
       
    84 static const NW_Ucs2 CSS_HEX_FORMAT[] = {'0','x','%','6','.','6','X','\0'};
       
    85 static const NW_Ucs2 CSS_FLOAT_FORMAT[] = {'%','1','0','f','\0'};
       
    86 
       
    87 #define NW_XHTML_1_0_INDEX 1
       
    88 #endif /* _DEBUG */
       
    89 
       
    90 // ============================ CONSTRUCTOR/DESTRUCTOR ===============================
       
    91 
       
    92 void CCSSVariableStyleSheet::operator=(const CCSSVariableStyleSheet& aObj){
       
    93 NW_REQUIRED_PARAM( &aObj );
       
    94 }
       
    95 
       
    96 // -----------------------------------------------------------------------------
       
    97 // Symbian two phase constructor.
       
    98 // -----------------------------------------------------------------------------
       
    99 
       
   100 void CCSSVariableStyleSheet::ConstructL()
       
   101 {
       
   102   HBufC8* buffer = NULL;
       
   103 
       
   104   //Initially nothing is loaded.
       
   105   iStaticCSSLoaded = EFalse;
       
   106   iVariableCSSLoaded = EFalse;
       
   107 
       
   108   //Create the lists. Pick a course granularity, they will be compressed
       
   109   //after completion. Minimize churning as we add components.
       
   110   iPropList = new (ELeave) CCSSPropEntryList(10);
       
   111   iStringList = new (ELeave) CCSSStringEntryList(5);
       
   112   ConstructCSSFileName();
       
   113 
       
   114   buffer = ReadVariableCSSFile();
       
   115   AddDefaultStyleStrings();
       
   116   AddVariableStyles(buffer);
       
   117   AddDefaultStyleProperties();
       
   118   delete buffer;
       
   119 #ifdef _DEBUG
       
   120   DumpVariableStyleSheet();
       
   121 #endif /* _DEBUG */
       
   122 }
       
   123 
       
   124 CCSSVariableStyleSheet* CCSSVariableStyleSheet::NewL()
       
   125   {
       
   126   CCSSVariableStyleSheet* self = new( ELeave ) CCSSVariableStyleSheet();
       
   127   CleanupStack::PushL( self );
       
   128   self->ConstructL();
       
   129   CleanupStack::Pop();
       
   130   return self;
       
   131   }
       
   132 
       
   133 
       
   134 // -----------------------------------------------------------------------------
       
   135 // Destructor.
       
   136 // Close and delete the lists. The destructors of each of the objects
       
   137 // will be called implicitly as a result.
       
   138 // -----------------------------------------------------------------------------
       
   139 
       
   140 CCSSVariableStyleSheet::~CCSSVariableStyleSheet()
       
   141 {
       
   142   TInt count;
       
   143   TInt index;
       
   144 
       
   145   //Walk through the RArray. For each entry, if it references a dynamic
       
   146   //entry (e.g. variable) delete the referenced object. Otherwise don't
       
   147   //do anything with the entry itself. Then close and delete the array.
       
   148   if (iPropList != NULL){
       
   149     count = iPropList->Count();
       
   150     for(index=0; index<count; index++){
       
   151       TCSSPropEntry& propEntry = iPropList->operator[](index);
       
   152       if (propEntry.variableEntry == TRUE){
       
   153         delete propEntry.entry->pattern;
       
   154         delete propEntry.entry;
       
   155       }
       
   156     }
       
   157     iPropList->Close();
       
   158     delete iPropList;
       
   159   }
       
   160 
       
   161   if (iStringList != NULL){
       
   162     count = iStringList->Count();
       
   163     for(index=0; index<count; index++){
       
   164       TCSSStringEntry& stringEntry = iStringList->operator[](index);
       
   165       if (stringEntry.variableEntry == TRUE){
       
   166         delete stringEntry.entry;
       
   167       }
       
   168     }
       
   169     iStringList->Close();
       
   170     delete iStringList;
       
   171   }
       
   172 }
       
   173 
       
   174 
       
   175 // ============================ PUBLIC METHODS ===============================
       
   176 
       
   177 // -----------------------------------------------------------------------------
       
   178 // CCSSVariableStyleSheet::CreateSingleton
       
   179 //
       
   180 // Creates the CCSSVariableStyleSheet singleton.
       
   181 // -----------------------------------------------------------------------------
       
   182 
       
   183 CCSSVariableStyleSheet* CCSSVariableStyleSheet::CreateSingleton()
       
   184 {
       
   185   CCSSVariableStyleSheet* thisObj = CCSSVariableStyleSheet::GetSingleton();
       
   186   if (thisObj == NULL){
       
   187     TRAPD(ret, thisObj = CCSSVariableStyleSheet::NewL());
       
   188     if (ret != KErrNone)
       
   189       return NULL;
       
   190     TRAP(ret, NW_Ctx_Set(NW_CTX_VARIABLE_CSS, 0, (void*)thisObj));
       
   191     if (ret != KErrNone)
       
   192       return NULL;
       
   193   }
       
   194   return thisObj;
       
   195 }
       
   196 
       
   197 
       
   198 // -----------------------------------------------------------------------------
       
   199 // CCSSVariableStyleSheet::DeleteSingleton
       
   200 //
       
   201 // Deletes the CCSSVariableStyleSheet singleton.
       
   202 // -----------------------------------------------------------------------------
       
   203 
       
   204 void CCSSVariableStyleSheet::DeleteSingleton()
       
   205 {
       
   206   CCSSVariableStyleSheet* thisObj = CCSSVariableStyleSheet::GetSingleton();
       
   207   if (thisObj != NULL){
       
   208     delete thisObj;
       
   209     NW_Ctx_Set(NW_CTX_VARIABLE_CSS, 0, NULL);
       
   210   }
       
   211 }
       
   212 
       
   213 
       
   214 // -----------------------------------------------------------------------------
       
   215 // CCSSVariableStyleSheet::GetSingleton
       
   216 //
       
   217 // Get the CCSSVariableStyleSheet singleton. If it doesn't already exist then returns null.
       
   218 // -----------------------------------------------------------------------------
       
   219 
       
   220 CCSSVariableStyleSheet* CCSSVariableStyleSheet::GetSingleton()
       
   221 {
       
   222   CCSSVariableStyleSheet* thisObj = (CCSSVariableStyleSheet*) NW_Ctx_Get(NW_CTX_VARIABLE_CSS, 0);
       
   223   return thisObj;
       
   224 }
       
   225 
       
   226 
       
   227 // -----------------------------------------------------------------------------
       
   228 // CCSSVariableStyleSheet::ApplyStyles
       
   229 //
       
   230 // Applies the combined default and variable styles.
       
   231 // -----------------------------------------------------------------------------
       
   232 
       
   233 TBrowserStatusCode
       
   234   CCSSVariableStyleSheet::ApplyStyles(NW_DOM_ElementNode_t* aElementNode,
       
   235                                      NW_LMgr_Box_t* aBox,
       
   236                                      NW_WBXML_Dictionary_t* aDictionary,
       
   237                                      const NW_Evt_Event_t* aEvent,
       
   238                                      NW_HED_DocumentNode_t* aDocNode,
       
   239                                      NW_HED_DomHelper_t* aDomHelper)
       
   240 {
       
   241   const NW_CSS_DefaultStyleSheet_PropEntry_t* propertyVal;
       
   242   TInt index, numPropertyVals;
       
   243   NW_Uint16 tagToken;
       
   244   const TCSSPropertyTablePropEntry* propEntry;
       
   245   TBrowserStatusCode status = KBrsrSuccess;
       
   246   NW_LMgr_Property_t prop;
       
   247   CCSSNodeData nodeData;
       
   248   TCSSPropEntry startEntry;
       
   249 
       
   250   tagToken = NW_DOM_ElementNode_getTagToken(aElementNode);
       
   251   numPropertyVals = iPropList->Count();
       
   252 
       
   253   //The entries are in order based on a key comprised of the element token
       
   254   //and the element name. The old algorithm searched through the array
       
   255   //until it found the first element token that matched. This algorithm lets
       
   256   //the binary search algorithm of the array do the work of finding the first
       
   257   //element that matches, or at least where to start looking. The looking stops
       
   258   //when a key is found that is greater than the token OR the end of the array
       
   259   //is reached.
       
   260 
       
   261   //Create a dummy entry with a search key that starts with the first
       
   262   //entry (if it exists) for this token and a default name of 0. If no
       
   263   //entry exists we will start at the place it WOULD exist. The search
       
   264   //will fail quickly in that case.
       
   265 
       
   266   startEntry.key = (tagToken << 16) | 0;
       
   267   iPropList->FindInUnsignedKeyOrder(startEntry, index);
       
   268 
       
   269   for(; index < numPropertyVals; index++){
       
   270     NW_Byte *pattern;
       
   271     propertyVal = iPropList->operator[](index).entry;
       
   272 
       
   273     if (propertyVal->elementToken < tagToken)
       
   274       continue;
       
   275 
       
   276     if (propertyVal->elementToken > tagToken)
       
   277       return KBrsrSuccess;
       
   278 
       
   279     /* match pattern - if pattern matches apply style */
       
   280     pattern = propertyVal->pattern;
       
   281     if (pattern != NULL){
       
   282       NW_Uint32 numBytes;
       
   283       CCSSPatternMatcher patternMatcher(aDictionary, aDocNode, aDomHelper);
       
   284       TBool matched = EFalse;
       
   285 
       
   286       (void) NW_String_charBuffGetLength(pattern, HTTP_us_ascii, &numBytes);
       
   287       TCSSParser parser(pattern, numBytes, HTTP_us_ascii);
       
   288 
       
   289       TRAPD(ret, matched = patternMatcher.MatchPatternLazyL(aElementNode, &parser, pattern, aEvent, &nodeData));
       
   290       if (ret == KErrNoMemory)
       
   291         return KBrsrOutOfMemory;
       
   292 
       
   293       if (!matched)
       
   294         continue;
       
   295     }
       
   296 
       
   297     propEntry = TCSSPropertyTable::GetPropEntryByToken(propertyVal->name);
       
   298     if (propEntry == NULL)
       
   299       continue;
       
   300 
       
   301     status = InitProperty(propEntry, &prop, aBox, propertyVal->val, propertyVal->valType);
       
   302     if (status == KBrsrOutOfMemory)
       
   303       return status;
       
   304     if (status != KBrsrSuccess)
       
   305       continue;
       
   306 
       
   307     /*
       
   308      Rules are arranged by decreasing specificity. If a property is
       
   309      already present, it can be replaced only if the other property is
       
   310      marked important. All defaults are NOT important.
       
   311     */
       
   312 	TInt ret;
       
   313     TRAP(ret, TCSSDeclListHandle::ApplyPropertyL(propEntry->tokenName, &prop, 1,
       
   314                                                   EFalse, NULL, aBox, ETrue));
       
   315 
       
   316     if ((prop.type == NW_CSS_ValueType_Text) ||(prop.type == NW_CSS_ValueType_Image)){
       
   317       NW_Object_Delete(prop.value.object);
       
   318     }
       
   319   }
       
   320   return status;
       
   321 }
       
   322 
       
   323 
       
   324 // ============================ PRIVATE METHODS ===============================
       
   325 
       
   326 
       
   327 // -----------------------------------------------------------------------------
       
   328 // CCSSVariableStyleSheet::ReadVariableCSSFile
       
   329 //
       
   330 // Loads the file into a buffer.
       
   331 // -----------------------------------------------------------------------------
       
   332 
       
   333 HBufC8*
       
   334 CCSSVariableStyleSheet::ReadVariableCSSFile()
       
   335 {
       
   336   HBufC8* buffer = NULL;
       
   337 
       
   338   if ((buffer = ReadFile(CSS_USER_SUPPLIED_FILE)) == NULL)
       
   339     {
       
   340       buffer = ReadFile(CSS_OPERATOR_SUPPLIED_FILE);
       
   341     }
       
   342 
       
   343   return buffer;
       
   344 }
       
   345 
       
   346 
       
   347 //Returns a HBufC8 with the contents of aFile
       
   348 HBufC8*
       
   349 CCSSVariableStyleSheet::ReadFile(const TDesC& aFile)
       
   350 {
       
   351   RFs fs;
       
   352   RFile file;
       
   353   TInt size = 0;
       
   354   HBufC8* contents = NULL;
       
   355 
       
   356   if (fs.Connect() != KErrNone )
       
   357     return contents;
       
   358 
       
   359   if (file.Open(fs, aFile, EFileShareAny | EFileRead) != KErrNone )
       
   360     {
       
   361       fs.Close();
       
   362       return contents;
       
   363     }
       
   364 
       
   365   //The file exists, allocate enough space for the NULL termination later.
       
   366   file.Size(size);
       
   367   if ((size != 0) && ((contents = HBufC8::New(size + 4)) != NULL))
       
   368     {
       
   369       //We have opened the file and it has a non-zero size and we have allocated memory
       
   370       TPtr8 contentsPtr(contents->Des());
       
   371       if (file.Read(contentsPtr, size)!= KErrNone)
       
   372         {
       
   373           delete contents;
       
   374           contents = NULL;
       
   375         }
       
   376     }
       
   377 
       
   378   file.Close();
       
   379   fs.Close();
       
   380   return contents;
       
   381 }
       
   382 
       
   383 
       
   384 // -----------------------------------------------------------------------------
       
   385 // CCSSVariableStyleSheet::AddVariableStyles
       
   386 //
       
   387 // Adds the variable styles to the default list.
       
   388 // -----------------------------------------------------------------------------
       
   389 
       
   390 TBool CCSSVariableStyleSheet::AddVariableStyles(HBufC8* aBuffer)
       
   391 {
       
   392   iVariableCSSLoaded = EFalse;
       
   393   if (aBuffer != NULL)
       
   394     {
       
   395       iVariableCSSLoaded = ProcessBuffer(aBuffer->Ptr(), aBuffer->Length());
       
   396     }
       
   397   else
       
   398     {
       
   399       iVariableCSSLoaded = EFalse;
       
   400     }
       
   401   return iVariableCSSLoaded;
       
   402 }
       
   403 
       
   404 
       
   405 // -----------------------------------------------------------------------------
       
   406 // CCSSVariableStyleSheet::ProcessBuffer
       
   407 //
       
   408 // Adds the variable styles to the default list.
       
   409 // -----------------------------------------------------------------------------
       
   410 TBool CCSSVariableStyleSheet::ProcessBuffer(const TUint8* aBuffer, TUint32 aLength)
       
   411 {
       
   412   TInt index = 0;
       
   413   TInt size = 0;
       
   414   TUint32 charset = HTTP_us_ascii;
       
   415   CCSSRuleList* ruleList = NULL;
       
   416   CCSSRuleListElementEntry* entry = NULL;
       
   417 
       
   418   TCSSParser parser((TUint8*)aBuffer, aLength, charset) ;
       
   419 
       
   420   TRAPD(ret, ruleList = CCSSRuleList::NewL(NULL));
       
   421   if (ret != KErrNone)
       
   422     return EFalse;
       
   423 
       
   424   ruleList->SetDictionary((NW_WBXML_Dictionary_t *) &NW_XHTML_WBXMLDictionary);
       
   425 
       
   426   ruleList->ProcessBuffer((TText8*)aBuffer, aLength, charset, ETrue); // delete buffer with ruleList
       
   427   size = ruleList->GetSize();
       
   428 
       
   429   for (index = 0; index < size; index++)
       
   430     {
       
   431       entry = ruleList->GetElementRulesByIndex(index);
       
   432       if (entry != NULL)
       
   433         {
       
   434           UpdateList(&parser, entry->iRules, entry->iElementToken);
       
   435         }
       
   436     }
       
   437   delete ruleList;
       
   438   return ETrue;
       
   439 }
       
   440 
       
   441 // -----------------------------------------------------------------------------
       
   442 // CCSSVariableStyleSheet::AddDefaultStyleStrings
       
   443 //
       
   444 // Adds the default style string to the default list.
       
   445 // -----------------------------------------------------------------------------
       
   446 
       
   447 void CCSSVariableStyleSheet::AddDefaultStyleStrings()
       
   448 {
       
   449   NW_Uint32 numVals;
       
   450   NW_Ucs2** stringVals;
       
   451   const NW_CSS_DefaultStyleSheet_t* defaultCSS;
       
   452   NW_Uint32 index;
       
   453   TCSSStringEntry stringEntry;
       
   454   NW_Ucs2* stringVal;
       
   455 
       
   456   defaultCSS = &NW_CSS_DefaultStyleSheet;
       
   457   numVals = NW_CSS_DefaultStyleSheet_GetClassPart(defaultCSS).numStringVals;
       
   458   stringVals = (NW_Ucs2**)(NW_CSS_DefaultStyleSheet_GetClassPart(defaultCSS).stringVals);
       
   459 
       
   460   for(index = 0; index < numVals; index++)
       
   461     {
       
   462       // Decode all the data in this structure and add to the array.  No
       
   463       // duplicates are allowed. The variable stuff was already added so
       
   464       // this is a lower priority.
       
   465       stringEntry.variableEntry = EFalse;
       
   466       stringVal = stringVals[index];
       
   467       stringEntry.entry = stringVal;
       
   468       iStringList->Append(stringEntry);
       
   469     }
       
   470 
       
   471   iStaticCSSLoaded = ETrue;
       
   472 }
       
   473 
       
   474 
       
   475 // -----------------------------------------------------------------------------
       
   476 // CCSSVariableStyleSheet::AddDefaultStyleProps
       
   477 //
       
   478 // Adds the default style properties to the default list.
       
   479 // -----------------------------------------------------------------------------
       
   480 
       
   481 void CCSSVariableStyleSheet::AddDefaultStyleProperties()
       
   482 {
       
   483   NW_Uint32 numVals;
       
   484   NW_CSS_DefaultStyleSheet_PropEntry_s* propertyVals;
       
   485   const NW_CSS_DefaultStyleSheet_t* defaultCSS;
       
   486   NW_Uint32 index;
       
   487   TCSSPropEntry propEntry;
       
   488 
       
   489   defaultCSS = &NW_CSS_DefaultStyleSheet;
       
   490   numVals = NW_CSS_DefaultStyleSheet_GetClassPart(defaultCSS).numPropertyVals;
       
   491   propertyVals = (NW_CSS_DefaultStyleSheet_PropEntry_s*)(NW_CSS_DefaultStyleSheet_GetClassPart(defaultCSS).propertyVals);
       
   492 
       
   493   for(index = 0; index < numVals; index++)
       
   494     {
       
   495       // Decode all the data in this structure and add to the array.  No
       
   496       // duplicates are allowed. The variable stuff was already added so
       
   497       // this is a lower priority.
       
   498 
       
   499       propEntry.key = (propertyVals[index].elementToken <<16) | (propertyVals[index].name);
       
   500       propEntry.variableEntry = EFalse;
       
   501       propEntry.entry = &(propertyVals[index]);
       
   502 
       
   503       //Insert the property. If this was a duplicate we ignore it. Ignore return value
       
   504       InsertProperty(propEntry);
       
   505     }
       
   506   iStaticCSSLoaded = ETrue;
       
   507 }
       
   508 
       
   509 
       
   510 // -----------------------------------------------------------------------------
       
   511 // CCSSVariableStyleSheet::InsertProperty
       
   512 //
       
   513 // Applies the styles to the property.
       
   514 // -----------------------------------------------------------------------------
       
   515 TInt CCSSVariableStyleSheet::InsertProperty(TCSSPropEntry aPropEntry)
       
   516 {
       
   517   TCSSPropEntry compareEntry;
       
   518   TInt searchIndex;
       
   519   if (iPropList->FindInUnsignedKeyOrder(aPropEntry, searchIndex) == KErrNone){
       
   520     //A duplicate primary key was found. Check secondary key
       
   521     //(e.g. pattern) to see if this is really a duplicate. Only insert
       
   522     //if the pattern specified matches none of the existing ones.
       
   523 
       
   524     //Multiple entries with the same key exist. Walk back until we find
       
   525     //the first one. The binary search that returned this index doesn't
       
   526     //always return the first entry in the list of duplicate keys.
       
   527     while (searchIndex >= 0){
       
   528       compareEntry = iPropList->operator[](searchIndex);
       
   529       if (compareEntry.key != aPropEntry.key){
       
   530         searchIndex++;
       
   531         break;
       
   532       }
       
   533       if (searchIndex == 0){
       
   534         break;
       
   535       }
       
   536       searchIndex--;
       
   537     }
       
   538 
       
   539     //Search until primary keys no longer match.
       
   540     while (searchIndex < iPropList->Count()){
       
   541       compareEntry = iPropList->operator[](searchIndex);
       
   542       if (compareEntry.key != aPropEntry.key){
       
   543         //duplicate not found in primary key so no more duplicates.
       
   544         //Add to list.
       
   545         break;
       
   546       }
       
   547 
       
   548       //We have matching primary keys. Check secondary. Watch out for nulls.
       
   549       //This messy because NW_Asc_strcmp doesn't handle nulls.
       
   550       if ((compareEntry.entry->pattern == NULL)&&(aPropEntry.entry->pattern == NULL) ||
       
   551           (compareEntry.entry->pattern != NULL)&&(aPropEntry.entry->pattern != NULL) ){
       
   552         //Either both or neither null
       
   553         if ((compareEntry.entry->pattern == aPropEntry.entry->pattern) ||
       
   554             !NW_Asc_strcmp((char*)(compareEntry.entry->pattern), (char*)(aPropEntry.entry->pattern))){
       
   555           //Secondary match found. Either both pointers are null or the
       
   556           //strings are the same. This is really a duplicate.
       
   557           //Don't add to list.
       
   558           searchIndex = -1;
       
   559           break;
       
   560         }
       
   561       }
       
   562       //If you got here than primary keys matched but pattern didn't match.
       
   563       //Keep checking.
       
   564       searchIndex++;
       
   565     }
       
   566     //If you got here then you hit the end of the list while primary
       
   567     //keys matched but pattern didn't. Add it at the end which is
       
   568     //where the index should be pointing.
       
   569   }
       
   570 
       
   571   //Insert at the calculated index if a valid index. This is not a duplicate.
       
   572   if (searchIndex != -1){
       
   573     iPropList->Insert(aPropEntry, searchIndex);
       
   574   }
       
   575   return searchIndex;
       
   576 }
       
   577 
       
   578 
       
   579 // -----------------------------------------------------------------------------
       
   580 // CCSSVariableStyleSheet::InitProperty
       
   581 //
       
   582 // Applies the styles to the property.
       
   583 // -----------------------------------------------------------------------------
       
   584 
       
   585 TBrowserStatusCode
       
   586 CCSSVariableStyleSheet::InitProperty(const TCSSPropertyTablePropEntry* aPropEntry,
       
   587                                      NW_LMgr_Property_t* aProp,
       
   588                                      NW_LMgr_Box_t* aBox,
       
   589                                      NW_Float32 aVal,
       
   590                                      NW_Uint8 aValType)
       
   591 {
       
   592   aProp->type = aValType;
       
   593 
       
   594  switch(aValType)
       
   595    {
       
   596    case NW_CSS_ValueType_Integer:
       
   597    case NW_CSS_ValueType_Px:
       
   598    case NW_CSS_ValueType_Color:
       
   599      aProp->value.integer = (NW_Int32)aVal;
       
   600      break;
       
   601    case NW_CSS_ValueType_Number:
       
   602    case NW_CSS_ValueType_In:
       
   603    case NW_CSS_ValueType_Cm:
       
   604    case NW_CSS_ValueType_Mm:
       
   605    case NW_CSS_ValueType_Pt:
       
   606    case NW_CSS_ValueType_Pc:
       
   607    case NW_CSS_ValueType_Em:
       
   608    case NW_CSS_ValueType_Ex:
       
   609    case NW_CSS_ValueType_Percentage:
       
   610      aProp->value.decimal = aVal;
       
   611      break;
       
   612    case NW_CSS_ValueType_Token:
       
   613      {
       
   614      TBool set = TCSSPropVal::SetTokenVal( aPropEntry->tokenName, aProp, (NW_Uint32) (NW_Int32) aVal, aBox);
       
   615      return set? KBrsrSuccess:KBrsrFailure;
       
   616      }
       
   617    case NW_CSS_ValueType_Text:
       
   618      {
       
   619      const NW_Ucs2* ucs2Str;
       
   620      NW_Text_Length_t length;
       
   621 
       
   622      if (aVal >= iStringList->Count())
       
   623        return KBrsrFailure;
       
   624 
       
   625      ucs2Str = iStringList->operator[]((NW_Int32)aVal).entry;
       
   626      length = (NW_Text_Length_t)(NW_Str_Strlen(ucs2Str));
       
   627 
       
   628      aProp->value.object = NW_Text_UCS2_New ((NW_Ucs2*) ucs2Str, length, 0);
       
   629      if (aProp->value.object == NULL)
       
   630        return KBrsrOutOfMemory;
       
   631 
       
   632      break;
       
   633      }
       
   634    default:
       
   635      return KBrsrFailure;
       
   636  }
       
   637 
       
   638  return KBrsrSuccess;
       
   639 }
       
   640 
       
   641 
       
   642 // -----------------------------------------------------------------------------
       
   643 // CCSSVariableStyleSheet::UpdateList
       
   644 //
       
   645 //
       
   646 // -----------------------------------------------------------------------------
       
   647 TBrowserStatusCode
       
   648 CCSSVariableStyleSheet::UpdateList(TCSSParser* aParser,
       
   649                                    CCSSRules* aRuleList,
       
   650                                    TUint16 aElementToken)
       
   651 {
       
   652   TInt index;
       
   653   TInt size;
       
   654   TBrowserStatusCode status;
       
   655 
       
   656   size = aRuleList->Count();
       
   657   for (index = 0; index < size; index++)
       
   658     {
       
   659       CCSSSelector* entry;
       
   660       TUint32 specificity;
       
   661       TText16* patternStr;
       
   662       char* asciiPatternStr;
       
   663       TText8* selectorEndPosition;
       
   664       TCSSSimpleSelector simpleSelector;
       
   665       TCSSReaderUnit unit;
       
   666       TText8* declarationList;
       
   667 
       
   668       entry = aRuleList->At(index);
       
   669       aParser->SetPosition(entry->iSelector);
       
   670       specificity = 0;
       
   671       patternStr = NULL;
       
   672       asciiPatternStr = NULL;
       
   673       simpleSelector.specificity = 0;
       
   674 
       
   675       do{
       
   676         specificity += simpleSelector.specificity;
       
   677         status = aParser->SimpleSelectorListIterate(&simpleSelector);
       
   678       }while (status == KBrsrIterateMore);
       
   679 
       
   680       if (status != KBrsrIterateDone)
       
   681         continue;
       
   682 
       
   683       selectorEndPosition = aParser->GetPosition();
       
   684       if (specificity > 1)
       
   685         {
       
   686           unit.Init(entry->iSelector, selectorEndPosition - entry->iSelector, 0);
       
   687           patternStr = unit.GetUnicode(aParser->GetEncoding());
       
   688 
       
   689           if (patternStr != NULL)
       
   690             {
       
   691               //Add the curly braces back into the pattern. These are
       
   692               //required for parsing later on. Revove whitespace before adding curly
       
   693               //braces. If you decide to remove leading whitespace then save the
       
   694               //pointer so you can delete it later.
       
   695               NW_Str_TrimInPlace(patternStr, NW_Str_End);
       
   696               TText16* tempStr = NW_Str_Newcat(patternStr, CSS_CURLY_BRACES);
       
   697               if (tempStr != NULL)
       
   698                 {
       
   699                   asciiPatternStr = NW_Str_CvtToAscii(tempStr);
       
   700                   delete tempStr;
       
   701                 }
       
   702               delete patternStr;
       
   703             }
       
   704         }
       
   705 
       
   706       (aParser->GetReader())->GoToToken(LEFT_BRACE, &declarationList);
       
   707       NW_ASSERT(declarationList);
       
   708       UpdateEntry(aParser, aElementToken, asciiPatternStr);
       
   709     }
       
   710   return KBrsrSuccess;
       
   711 }
       
   712 
       
   713 // -----------------------------------------------------------------------------
       
   714 // CCSSVariableStyleSheet::UpdateEntry
       
   715 //
       
   716 //
       
   717 // -----------------------------------------------------------------------------
       
   718 TBrowserStatusCode
       
   719 CCSSVariableStyleSheet::UpdateEntry(TCSSParser* aParser,
       
   720                                    TUint16 aElementToken,
       
   721                                    char* aAsciiPatternStr)
       
   722 {
       
   723   TBool important;
       
   724   TCSSReaderUnit propertyName;
       
   725   TCSSPropertyVal propertyVal;
       
   726   TUint8 numVals;
       
   727   TCSSPropEntry entryWrapper;
       
   728   TCSSStringEntry stringWrapper;
       
   729   NW_CSS_DefaultStyleSheet_PropEntry_s* entry;
       
   730   const TCSSPropertyTablePropEntry* propEntry;
       
   731   NW_LMgr_PropertyValue_t val;
       
   732   NW_LMgr_PropertyValueType_t valType;
       
   733   TText16* ucs2Str = NULL;
       
   734   TText16* valStorage = NULL;
       
   735   TUint32 encoding;
       
   736 
       
   737   while (aParser->DeclarationListIterate(&propertyName, &propertyVal, &numVals, 1, &important)
       
   738          == KBrsrIterateMore)
       
   739     {
       
   740       if (propertyName.iLength == 0)
       
   741         continue;
       
   742 
       
   743       encoding = aParser->GetEncoding();
       
   744       ucs2Str = propertyName.GetUnicode(encoding);
       
   745       if ((ucs2Str == NULL) || (propertyVal.type == -1))
       
   746         continue;
       
   747 
       
   748       propEntry = TCSSPropertyTable::GetPropertyEntry(ucs2Str);
       
   749       delete(ucs2Str);
       
   750       if (propEntry == NULL)
       
   751         continue;
       
   752 
       
   753       valStorage = propertyVal.val.GetUnicode(encoding);
       
   754       if (valStorage == NULL)
       
   755         continue;
       
   756 
       
   757       valType = SetPropertyVal(aParser, propEntry, &val, &propertyVal, valStorage);
       
   758       if (valType == 0)
       
   759         continue;
       
   760 
       
   761       /* create a new entry to and initialize it */
       
   762       entry = new NW_CSS_DefaultStyleSheet_PropEntry_s;
       
   763       entryWrapper.variableEntry = ETrue;
       
   764       entryWrapper.entry = entry;
       
   765       entryWrapper.key = (aElementToken <<16) | propEntry->tokenName;
       
   766 
       
   767       entry->elementToken = aElementToken;
       
   768       entry->pattern = (unsigned char *)aAsciiPatternStr;
       
   769       entry->name = propEntry->tokenName;
       
   770       entry->valType = valType;
       
   771       switch (valType)
       
   772         {
       
   773         case NW_CSS_ValueType_Percentage:
       
   774         case NW_CSS_ValueType_Em:
       
   775         case NW_CSS_ValueType_In:
       
   776         case NW_CSS_ValueType_Cm:
       
   777         case NW_CSS_ValueType_Mm:
       
   778         case NW_CSS_ValueType_Pt:
       
   779         case NW_CSS_ValueType_Pc:
       
   780           entry->val = (NW_Float32)val.decimal;
       
   781           break;
       
   782         case NW_CSS_ValueType_Token:
       
   783           entry->val = (NW_Float32)val.token;
       
   784           break;
       
   785         case NW_CSS_ValueType_Px:
       
   786         case NW_CSS_ValueType_Integer:
       
   787         case NW_CSS_ValueType_Ex:
       
   788         case NW_CSS_ValueType_Color:
       
   789           entry->val = (NW_Float32)val.integer;
       
   790           break;
       
   791         case NW_CSS_ValueType_Text:
       
   792           {
       
   793             stringWrapper.variableEntry = ETrue;
       
   794             stringWrapper.entry = valStorage;
       
   795             valStorage = NULL;
       
   796             iStringList->Append(stringWrapper);
       
   797             //Index of this entry is count - 1
       
   798             entry->val = (NW_Float32)(iStringList->Count() - 1);
       
   799             break;
       
   800           }
       
   801         default:
       
   802           entry->val = (NW_Float32)val.integer;
       
   803           break;
       
   804         }
       
   805       delete valStorage;
       
   806 
       
   807       if (InsertProperty(entryWrapper) == -1)
       
   808         {
       
   809           //This was a duplicate. It wasn't added to list. Free memory.
       
   810           delete entry->pattern;
       
   811           delete entry;
       
   812         }
       
   813     }
       
   814 
       
   815 
       
   816   return KBrsrSuccess;
       
   817 }
       
   818 
       
   819 // -----------------------------------------------------------------------------
       
   820 // CCSSVariableStyleSheet::SetPropertyVal
       
   821 //
       
   822 
       
   823 NW_LMgr_PropertyValueType_t
       
   824 CCSSVariableStyleSheet::SetPropertyVal(TCSSParser* aParser,
       
   825                                        const TCSSPropertyTablePropEntry* aPropEntry,
       
   826                                        NW_LMgr_PropertyValue_t* aVal,
       
   827                                        TCSSPropertyVal* aPropertyVal,
       
   828                                        TText16* aValStorage)
       
   829 {
       
   830   NW_LMgr_PropertyValueToken_t token;
       
   831   TBool result = EFalse;
       
   832   NW_Float32 v;
       
   833   TText16* endPtr = NULL;
       
   834 
       
   835 
       
   836   if ((aPropertyVal->type == RGB) || (aPropertyVal->type == HASH)){
       
   837     //COLOR
       
   838      NW_LMgr_Property_t tmpVal;
       
   839      tmpVal.value.integer = 0; //remove warning
       
   840      tmpVal.type = 0;
       
   841 
       
   842      TRAPD( err, result = TCSSPropVal::SetColorL( aParser, &tmpVal, aPropertyVal, aValStorage));
       
   843      if ((err != KErrNone) || !result)
       
   844        return 0;
       
   845 
       
   846      aVal->integer = tmpVal.value.integer;
       
   847      return NW_CSS_ValueType_Color;
       
   848   }
       
   849 
       
   850   if (aPropertyVal->type == IDENTIFIER){
       
   851      //TOKEN
       
   852      if(aPropEntry->tokenName != NW_CSS_Prop_fontFamily) {
       
   853        if (TCSSPropertyTable::GetPropertyValToken(aValStorage, &token)){
       
   854          aVal->token = token;
       
   855          return NW_CSS_ValueType_Token;
       
   856        }
       
   857      }
       
   858   }
       
   859 
       
   860   if ((aPropertyVal->type == IDENTIFIER) || (aPropertyVal->type == STRING)){
       
   861     //TEXT
       
   862     /* If the identifier is not recognized as a token OR it is a real
       
   863        string interpret is as a string */
       
   864     return NW_CSS_ValueType_Text;
       
   865   }
       
   866 
       
   867   //NUMBER - If not one of the above it must be a number.
       
   868 
       
   869   if ( NW_Str_CvtToFloat32(aValStorage, &endPtr, &v) != KBrsrSuccess)
       
   870     return 0;
       
   871 
       
   872   switch (aPropertyVal->type)
       
   873     {
       
   874     case NUMBER:
       
   875       /* This code is the point that default units of measure are
       
   876          applied. This is a convenience. According to the spec. only the
       
   877          value zero can omit the units. However, defaults are usually
       
   878          inserted. */
       
   879       switch (aPropEntry->tokenName)
       
   880         {
       
   881           // PIXEL Defaults
       
   882 		case NW_CSS_Prop_borderWidth:
       
   883         case NW_CSS_Prop_topBorderWidth:
       
   884         case NW_CSS_Prop_bottomBorderWidth:
       
   885         case NW_CSS_Prop_leftBorderWidth:
       
   886         case NW_CSS_Prop_rightBorderWidth:
       
   887 
       
   888         case NW_CSS_Prop_padding:
       
   889         case NW_CSS_Prop_topPadding:
       
   890         case NW_CSS_Prop_bottomPadding:
       
   891         case NW_CSS_Prop_leftPadding:
       
   892         case NW_CSS_Prop_rightPadding:
       
   893 
       
   894 		case NW_CSS_Prop_margin:
       
   895 		case NW_CSS_Prop_topMargin:
       
   896         case NW_CSS_Prop_bottomMargin:
       
   897         case NW_CSS_Prop_leftMargin:
       
   898         case NW_CSS_Prop_rightMargin:
       
   899           aVal->integer = (TInt32)v;
       
   900           return NW_CSS_ValueType_Px;
       
   901 
       
   902           //INTEGER defaults
       
   903         case NW_CSS_Prop_font:
       
   904         case NW_CSS_Prop_fontSize:
       
   905         case NW_CSS_Prop_fontWeight:
       
   906         case NW_CSS_Prop_marqueeSpeed:
       
   907         case NW_CSS_Prop_marqueeLoop:
       
   908         default:
       
   909           aVal->integer = (TInt32)v;
       
   910           return NW_CSS_ValueType_Integer;
       
   911         }
       
   912 
       
   913     case PERCENTAGE:
       
   914       aVal->decimal = v;
       
   915       return NW_CSS_ValueType_Percentage;
       
   916 
       
   917     case EMS:
       
   918       aVal->decimal = v;
       
   919       return NW_CSS_ValueType_Em;
       
   920 
       
   921     case EXS:
       
   922       aVal->decimal = v;
       
   923       return NW_CSS_ValueType_Ex;
       
   924 
       
   925     case PXS:
       
   926       aVal->integer =(TInt32)v;
       
   927       return NW_CSS_ValueType_Px;
       
   928 
       
   929     case INS:
       
   930       aVal->decimal = v;
       
   931       return NW_CSS_ValueType_In;
       
   932 
       
   933     case CMS:
       
   934       aVal->decimal = v;
       
   935       return NW_CSS_ValueType_Cm;
       
   936 
       
   937     case MMS:
       
   938       aVal->decimal = v;
       
   939       return NW_CSS_ValueType_Mm;
       
   940 
       
   941     case PCS:
       
   942       aVal->decimal = v;
       
   943       return NW_CSS_ValueType_Pc;
       
   944 
       
   945     case PTS:
       
   946       aVal->decimal = v;
       
   947       return NW_CSS_ValueType_Pt;
       
   948 
       
   949       //default:
       
   950       //return 0;
       
   951     }
       
   952   return 0;
       
   953 }
       
   954 
       
   955 
       
   956 // -----------------------------------------------------------------------------
       
   957 // CCSSVariableStyleSheet::DumpVariableStyleSheet
       
   958 //
       
   959 // -----------------------------------------------------------------------------
       
   960 #ifdef _DEBUG
       
   961 
       
   962 TBrowserStatusCode
       
   963 CCSSVariableStyleSheet::DumpVariableStyleSheet()
       
   964 {
       
   965   TInt count;
       
   966   TInt index;
       
   967 
       
   968   NW_LOG0(NW_LOG_LEVEL3, "*** Printing Variable Style Sheet ****");
       
   969   //Walk through the RArray. For each entry, if it references a dynamic
       
   970   //entry (e.g. variable) delete the referenced object. Otherwise don't
       
   971   //do anything with the entry itself. Then close and delete the array.
       
   972 
       
   973   if (iPropList != NULL){
       
   974     NW_Ucs2 tmpString[40];
       
   975     NW_Ucs2* valString;
       
   976     NW_Ucs2* elementString;
       
   977     NW_Ucs2* patternString;
       
   978     NW_Int32 tmpInt;
       
   979 
       
   980     count = iPropList->Count();
       
   981     NW_LOG1(NW_LOG_LEVEL3, "CSS Property List -  %d entries", count);
       
   982     for(index=0; index<count; index++){
       
   983       TCSSPropEntry& propEntry = iPropList->operator[](index);
       
   984 
       
   985       const TCSSPropertyTablePropEntry* propTableEntry =
       
   986         TCSSPropertyTable::GetPropEntryByToken(propEntry.entry->name);
       
   987 
       
   988       switch(propEntry.entry->valType){
       
   989       case NW_CSS_ValueType_Color:
       
   990         tmpInt = (NW_Int32)(propEntry.entry->val);
       
   991         NW_Str_Sprintf(tmpString, CSS_HEX_FORMAT, tmpInt);
       
   992         valString = tmpString;
       
   993         break;
       
   994       case NW_CSS_ValueType_Token:
       
   995         {
       
   996           tmpInt = (NW_Int32)(propEntry.entry->val);
       
   997           const TCSSPropertyTablePropValEntry* valTableEntry =
       
   998             TCSSPropertyTable::GetPropValEntryByToken ((NW_LMgr_PropertyValueToken_t)tmpInt);
       
   999           valString = valTableEntry == NULL ? (NW_Ucs2*)CSS_INVALID_TOKEN : (NW_Ucs2*)valTableEntry->strVal;
       
  1000         }
       
  1001         break;
       
  1002       case NW_CSS_ValueType_Text:
       
  1003         if (propEntry.entry->val < iStringList->Count()){
       
  1004           tmpInt = (NW_Int32)(propEntry.entry->val);
       
  1005           TCSSStringEntry& stringEntry = iStringList->operator[](tmpInt);
       
  1006           valString = stringEntry.entry;
       
  1007         }else{
       
  1008           valString = (NW_Ucs2*)CSS_INVALID_TOKEN;
       
  1009         }
       
  1010         break;
       
  1011 
       
  1012       case NW_CSS_ValueType_Number:
       
  1013       case NW_CSS_ValueType_Percentage:
       
  1014       case NW_CSS_ValueType_Em:
       
  1015       case NW_CSS_ValueType_Ex:
       
  1016       case NW_CSS_ValueType_In:
       
  1017       case NW_CSS_ValueType_Cm:
       
  1018       case NW_CSS_ValueType_Mm:
       
  1019       case NW_CSS_ValueType_Pc:
       
  1020       case NW_CSS_ValueType_Pt:
       
  1021         NW_Str_Sprintf(tmpString, CSS_FLOAT_FORMAT, propEntry.entry->val);
       
  1022         valString = tmpString;
       
  1023         break;
       
  1024       case NW_CSS_ValueType_Integer:
       
  1025       case NW_CSS_ValueType_Px:
       
  1026       default:
       
  1027         tmpInt = (NW_Int32)(propEntry.entry->val);
       
  1028         NW_Str_Itoa(tmpInt, tmpString);
       
  1029         valString = tmpString;
       
  1030       }
       
  1031 
       
  1032       // Pattern string contains the element name. It it exists show it. Otherwise show element name
       
  1033       elementString = (NW_Ucs2*)NW_WBXML_Dictionary_getTagByFqToken((NW_XHTML_1_0_INDEX << 16) | propEntry.entry->elementToken);
       
  1034       if (elementString == NULL) {
       
  1035         elementString = (NW_Ucs2*)CSS_INVALID_TOKEN;
       
  1036       }
       
  1037 
       
  1038       if (propEntry.entry->pattern == NULL){
       
  1039 		  patternString = NULL;
       
  1040 	  }else {
       
  1041 		  patternString = NW_Str_CvtFromAscii((const char*)(propEntry.entry->pattern));
       
  1042 		  NW_Str_Strcharreplace(patternString, ASCII_LEFT_BRACE, ASCII_NULL);
       
  1043 	  }
       
  1044 
       
  1045       NW_LOG7(NW_LOG_LEVEL3,
       
  1046               "%3d %s  key: 0x%06X  %s{ %s: %s%s }",
       
  1047               //Wrapper
       
  1048               index,
       
  1049               propEntry.variableEntry == TRUE ? (NW_Ucs2*)CSS_VARIABLE:(NW_Ucs2*)CSS_DEFAULT,
       
  1050               propEntry.key,
       
  1051               //Entry
       
  1052               patternString == NULL ? elementString : patternString,
       
  1053               propTableEntry->strName,
       
  1054               valString,
       
  1055               TCSSPropertyTable::GetPropValType(propEntry.entry->valType));
       
  1056 
       
  1057       delete patternString;
       
  1058     }
       
  1059   }
       
  1060 
       
  1061   if (iStringList != NULL){
       
  1062     count = iStringList->Count();
       
  1063     NW_LOG1(NW_LOG_LEVEL3, "CSS String List - %d entries", count);
       
  1064     for(index=0; index<count; index++){
       
  1065       TCSSStringEntry& stringEntry = iStringList->operator[](index);
       
  1066       NW_LOG3(NW_LOG_LEVEL3, "%2d  %s  %s",
       
  1067               index,
       
  1068               stringEntry.variableEntry == TRUE ? (NW_Ucs2*)CSS_VARIABLE : (NW_Ucs2*)CSS_DEFAULT,
       
  1069               stringEntry.entry);
       
  1070     }
       
  1071   }
       
  1072   return KErrNone;
       
  1073 }
       
  1074 #endif /* _DEBUG */