csxhelp/HelpEngine/src/CSXHHTMLContentParser.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 19 Feb 2010 22:42:03 +0200
branchRCL_3
changeset 5 d06b1526f62c
parent 1 27f5851bd5a5
child 11 91bbff48ea9c
permissions -rw-r--r--
Revision: 201003 Kit: 201007

/*
* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "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:  CCSXHHTMLContentParser class definition
*
*/

#include "CSXHHTMLContentParser.h"
#include "CSXHXMLParseHandler.h"
#include "CSXHHtmlTOC1.h"
#include "CSXHKywdTOC1.h"
#include "CSXHHtmlTOC2.h"
#include "CSXHHelpDataBase.h"
#include "csxhconstants.h"
#include "CSXHRuntimeIndexing.h"
#include "csxhviewids.h"

#include <eikenv.h> 
#include <utf.h>
#include <data_caging_path_literals.hrh>
#include <zipfile.h>
#include <bautils.h>
#include <SenXmlReader.h> 
#include <f32file.h>
#include <pathinfo.h> 

//Input Language variation changes
#include <PtiEngine.h>

const TInt KOffset = 2;
        
CCSXHHTMLContentParser* CCSXHHTMLContentParser::NewL(CCoeEnv* aCoeEnv)
    {
    CCSXHHTMLContentParser* self = CCSXHHTMLContentParser::NewLC(aCoeEnv);
    CleanupStack::Pop(self);
    return self;
    }
    
CCSXHHTMLContentParser* CCSXHHTMLContentParser::NewLC(CCoeEnv* aCoeEnv)
    {
    CCSXHHTMLContentParser* self = new (ELeave) CCSXHHTMLContentParser(aCoeEnv);
    CleanupStack::PushL(self);
    self->ConstructL();
    return self;
    }
    
void CCSXHHTMLContentParser::ConstructL()
    {
    //RUNTIME
    GetSupportedFeatureListL();
    }
    
CCSXHHTMLContentParser::CCSXHHTMLContentParser(CCoeEnv* aCoeEnv) : iCoeEnv(aCoeEnv)
    {
    }
    
CCSXHHTMLContentParser::~CCSXHHTMLContentParser()
    {
    delete iXmlReader;
    
    //No need to delete the entries here, it will be done by the database
    iHtmlTOC1List.Close();
    
    //Delete all contents from the array.
    TInt count =    iDuplicateHelpTopicList.Count();
    CCSXHHtmlTOC1* toc1;
    for(TInt i=0;i<count;++i )
        {
        toc1 = iDuplicateHelpTopicList[i];
        delete toc1;
        }
    iDuplicateHelpTopicList.Reset();    
	iDuplicateHelpTopicList.Close();
	
    // Closes the array and frees all memory allocated to the array.
   // iSupportedFeatures.Close();
    
    delete iSupportedInputLanguages;
    delete iFeatureManager_FeatureIds;
    delete iIndexing;
    }
    
void CCSXHHTMLContentParser::GenerateTOC1ListL(CCSXHHelpDataBase* aDataBase)
    {       
    RFs& FileSession = iCoeEnv->FsSession();

    TDriveList DirList; 
    if(FileSession.DriveList(DirList) != KErrNone)
        return; 
    CCSXHXMLParseHandler_MetaFile* XMLParser = CCSXHXMLParseHandler_MetaFile::NewL(iCoeEnv); 
    CleanupStack::PushL(XMLParser);   
    InitializeReaderL(XMLParser);
    
      
    TBuf<KMaxFileName>* rootDir = new(ELeave) TBuf<KMaxFileName>;
    CleanupStack::PushL(rootDir);//5

    // begin runtime index XML generating
    //   
    iIndexing = CCSXHRuntimeIndexing::NewL();
    TInt driveListSize = DirList.Length();
    TBool dirExists = iIndexing->IndexFileExistsL();
    CDirScan* scanner=CDirScan::NewLC(FileSession);
#ifdef _DEBUG
    RDebug::Print(_L("runtime indexing object successfully build"));
#endif
    for(TInt dir(0); dir < driveListSize; dir++)
        {
        TInt error;
        TDriveInfo info;
        TChar driveLetter = '?';
        error = FileSession.Drive(info, dir);
            
        if  ( ( error == KErrNone ) && 
                (DirList[dir] && info.iType != EMediaNotPresent))
            {
            RFs::DriveToChar( dir, driveLetter );
            TInt dirChanged = iIndexing->CheckDirChangeL( driveLetter );
            rootDir->Delete( 0, rootDir->Length() );//Clear the previous contents                  
            rootDir->Append( driveLetter );

            if  ( dirExists 
                    && ( dirChanged == KNoChange
                        || dirChanged == KNoDirExist) )
                {
                // xml exist and no install/uninstall happened
                // while Z needs special process once its index file exists
#ifdef _DEBUG
                RDebug::Print(_L("Used to launch, scan drive number:  %d"), dir);
#endif
                if ( dirChanged == KNoChange )
                    {
                    // no modify helps, so just parse index.xml
                    //
                    HandleMasterMetaFileL( aDataBase, driveLetter, XMLParser );
                    }
                else // KNoDirExist
                    {
                    // help content folder removed due to some reason (uninstall/crash?)
                    // delete index file in case it exist
#ifdef _DEBUG
                    RDebug::Print( _L("no resource folder, delete index.xml if exists") );
#endif
                    iIndexing->DeleteIndexFileL( driveLetter );
                    }
                }
            else
                {
                // xml not exist or install/uninstall not happend
                //
                if( GetHTMLContentPathForDriveL( rootDir,iCoeEnv ) )
                    {
#ifdef _DEBUG
                    RDebug::Print( _L("No index, scan folder for parsing, drive letter: %d"), dir );
#endif
                    iIndexing->BeginIndexFileL( driveLetter );
                    scanner->SetScanDataL(*rootDir
                                    ,KEntryAttDir|KEntryAttMatchExclusive,
                                    ESortByName|EAscending, CDirScan::EScanDownTree);
                    ScanAndParseXMLfileToCreateTOC1ObjectL(FileSession,scanner,aDataBase,
                                                        dir,XMLParser);  
                                                        
                    iIndexing->FinishAndCloseIndexFileL();
                    
                    }
                
                }

            }
        }
    CleanupStack::PopAndDestroy( scanner );
    CleanupStack::PopAndDestroy(rootDir);
    CleanupStack::PopAndDestroy(XMLParser);
    
    ClearReader();
    }

TBool CCSXHHTMLContentParser::GetHTMLContentPathForDriveL(TBuf<KMaxFileName>* aContentDrive,CCoeEnv *aCoeEnv)
	{
    // get the path to language level
    // Input: aContentDrive == C or E or Z
    // Output: aContentDrive == C:\\resource\\xhtml\\01\\ (or Z:\\resource\\xhtml\\31\\)
    //
	aContentDrive->Append(KXhtmlFolder);
	TInt len = aContentDrive->Length();
	RFs& FileSession = aCoeEnv->FsSession();
	RArray<TLanguage> langs;
   	BaflUtils::GetDowngradePathL(FileSession,User::Language(),langs);
    		
    for(int i = 0; i < langs.Count(); ++i)
    	{
    	TLanguage lang = langs[i];
    	//TSW Error: UKAL-6YL72P
    	//Tool chain uses full symbian language id in 
    	//the directory name, which is not detected by help application.
    	//
    	if(lang < 10)
            {
            aContentDrive->AppendNumFixedWidth(lang,EDecimal,2);
            }
        else
            {
            aContentDrive->AppendNum(lang);
            }
    	
    	aContentDrive->Append(KFwdSlash);
    	if(BaflUtils::PathExists(FileSession,*aContentDrive))
    		{
    		langs.Reset();
    		return ETrue;
    		}
    	else
    		{
    		aContentDrive->Delete((len-1),aContentDrive->Length()-len);
    		}	
    	}
    	langs.Reset();
    	return EFalse;
	}
    
TBool CCSXHHTMLContentParser::HandleMasterMetaFileL(CCSXHHelpDataBase* aDataBase, 
                        TChar& aDrive, MSenContentHandlerClient *aPrevHandler)											   
    {
    RFs& FileSession = iCoeEnv->FsSession();
    TBuf<KMaxFileName> masterFile;

    iIndexing->GetPrivatePath( masterFile );
    masterFile.Append( aDrive );
    masterFile.Append( KFwdSlash );
    iIndexing->AppendLocaleL( masterFile );
    masterFile.Append( KMasterMetaFile );
    if(BaflUtils::FileExists( FileSession,masterFile ) )
        {
#ifdef _DEBUG
        RDebug::Print(_L("index exist begin to parse!    %c"), TUint( aDrive ) );
#endif
        CCSXHXMLParseHandler_MasterMetaFile* masterMetaHandler = 
        CCSXHXMLParseHandler_MasterMetaFile::NewL(iCoeEnv);
        masterMetaHandler->SetDataBasePtr(aDataBase);
        masterMetaHandler->SetHtmlContentParserPtr(this);
        CleanupStack::PushL(masterMetaHandler);      
    
        iXmlReader->SetContentHandler(*masterMetaHandler);
        // ParseL is not in async
        iXmlReader->ParseL(FileSession,masterFile);
        iXmlReader->SetContentHandler(*aPrevHandler);
        CleanupStack::PopAndDestroy(masterMetaHandler);
        }

    return ETrue;
    }

TBool CCSXHHTMLContentParser::IsRedirectedL(CCSXHHelpDataBase *aDataBase, 
		                      const TDesC &aPath, TUid &aUid, TCoeContextName &aContextName)											   
    {
    RFs& FileSession = iCoeEnv->FsSession();
    TBuf<KMaxFileName> redirectFile( aPath );
    redirectFile.Append( KRedirectFile );
    TBool result = EFalse;
    
    if ( BaflUtils::FileExists( FileSession, redirectFile ) )
        {
        CCSXHXMLParseHandler_RedirectFile* XMLParser = 
                     CCSXHXMLParseHandler_RedirectFile::NewL(iCoeEnv, aUid, aContextName);
        XMLParser->SetDataBasePtr( aDataBase );
     
        CleanupStack::PushL( XMLParser );      
        InitializeReaderL( XMLParser );
        // ParseL is not in async
        iXmlReader->ParseL( FileSession, redirectFile );
        if ( XMLParser->IsTargetPathFound() )
        	{
            TBuf<KMaxFileName>& targetContextName = XMLParser->TargetContextName();
            if ( targetContextName.Length() <= aContextName.MaxLength() )
            	{
        	    aUid = XMLParser->TargetUid();
        	    aContextName = targetContextName;
        	    result = ETrue;
                }
        	}
        CleanupStack::PopAndDestroy( XMLParser );
        ClearReader();
        }

    return result;
    }
    
void CCSXHHTMLContentParser::GenerateTOC2ListL(CCSXHGenericTOC1& 
aGenericTOC1Object, RPointerArray<CCSXHHelpContentBase>* GenericTOC2List)
    {
    CCSXHXMLParseHandler_IndexFile* XMLParser = CCSXHXMLParseHandler_IndexFile::NewL(iCoeEnv);
    CleanupStack::PushL(XMLParser);      
    InitializeReaderL(XMLParser);
        
    XMLParser->SetArray(GenericTOC2List);
    XMLParser->SetGenericTOC1Object(aGenericTOC1Object);
    XMLParser->SetHtmlContentParserPtr(this);
    RFs& FileSession = iCoeEnv->FsSession();
    CCSXHHtmlTOC1* toc1 = STATIC_CAST(CCSXHHtmlTOC1*,&aGenericTOC1Object);
    TBuf<KMaxFileName> lookupindexfile;
    toc1->GetHelpFileL(lookupindexfile);
    XMLParser->SetPath(lookupindexfile);
    lookupindexfile.Append(KIndexFile);              
 
    if(BaflUtils::FileExists(FileSession,lookupindexfile))
        iXmlReader->ParseL (FileSession,lookupindexfile);
	
	TBuf<KMaxFileName>HelpContentName(toc1->GetName());
	int toc1Count = iDuplicateHelpTopicList.Count();
	
 	for(int i=0;i < toc1Count;i++)
	    {    
	    CCSXHHtmlTOC1* temptoc1 = iDuplicateHelpTopicList[i];
	        
	    if(temptoc1->GetName().CompareF(HelpContentName) == 0)
		    {    
		    TBuf<KMaxFileName> lookup;
		    temptoc1->GetHelpFileL(lookup);
		    XMLParser->SetPath(lookup);
		    lookup.Append(KIndexFile);              
		 
		    if(BaflUtils::FileExists(FileSession,lookup))
		        iXmlReader->ParseL (FileSession,lookup);
		    }
	    }
    
    CleanupStack::PopAndDestroy(XMLParser);
    ClearReader();
    }       
        
TAny* CCSXHHTMLContentParser::GetTopicContentL(CCSXHGenericTOC2* aTopic)
    {
    CCSXHHtmlTOC2* topic = STATIC_CAST(CCSXHHtmlTOC2*,aTopic);
    TBuf<KMaxFileName> htmlFile;
	topic->GetHtmlFileName(htmlFile);
    return GetContentsFromFileL(htmlFile,iCoeEnv,iFeatureControl);
    }
    

void CCSXHHTMLContentParser::ScanAndParseXMLfileToCreateTOC1ObjectL(RFs& FileSession,
                                                                 CDirScan* scanner,
                                                                 CCSXHHelpDataBase* aDataBase,
                                                                 const TInt& aDrive,
                                                                 CCSXHXMLParseHandler_MetaFile* XMLParser
                                                                  )
    {
     CDir* entryList = NULL;
    scanner->NextL(entryList);
    if(!entryList)
        return;
 
    CleanupStack::PushL(entryList);
    TInt entryCount = entryList->Count();           
         
    TInt ROMDrive;
    RFs::CharToDrive( PathInfo::RomRootPath()[0], ROMDrive );
    
    TBuf<KMaxFileName> lookup;
    

    while(entryCount--)
        {
        TEntry entry=(*entryList)[entryCount];
        
        //Clear the previous values
        lookup.Delete(0,lookup.Length());
        
        lookup.Append(scanner->FullPath());
        lookup.Append(entry.iName); 
        lookup.Append(KFwdSlash);
        lookup.Append(KMetaFile);
        
        //Check whether a file exists        
        if(!BaflUtils::FileExists(FileSession,lookup))
            continue;
        
        TRAPD(parserResult,iXmlReader->ParseL (FileSession,lookup ));
        if(parserResult == KErrNone)
            {
			if(CheckFeatureIDL(XMLParser->GetFeatureIds()))
            	{            
            	if(!IsAppUIdPresentAlready(entry.iName))
					{
					CCSXHHtmlTOC1* CategoryObj = NULL;
		            TBool duplicateToc = EFalse;
		            
		            TInt32 priority = XMLParser->Priority();
		            // Now we take a walk if it's application helps (priority == 0)
		           
		            if ( (priority != 0) 
		            	&& ( ( aDrive == ROMDrive ) || IsRomBasedContentL( FileSession, entry.iName ) ) )
		                {
		                if ( priority < KHighestPriority )
		                	{
		                    priority = KHighestPriority;
		                	}
		                else if ( priority > KLowestPriority )
		                	{
		                    priority = KLowestPriority;
		                	}
		                
		                CategoryObj = CCSXHHtmlTOC1::NewL(
		                		           XMLParser->GetApplicationName(),entry.iName,aDrive, 
		                		           KCSXHToc2ViewID, priority);
		                if(CategoryObj && aDataBase->GetMainTopics()->InsertChildWithPriority(CategoryObj,EFalse))
		            	    iHtmlTOC1List.Append(CategoryObj);//Keep a local copy 
		                else
		                    duplicateToc = ETrue;
		                }
		            else 
		           		{
		           		CategoryObj = CCSXHHtmlTOC1::NewL(
		           		                    XMLParser->GetApplicationName(),entry.iName, aDrive, 
		           		                    KCSXHToc2AppHelpsViewID, 0);
		           		               
		           		if(CategoryObj && aDataBase->GetAppHelpsTopics()->InsertChild(CategoryObj,EFalse))
		                                    iHtmlTOC1List.Append(CategoryObj);//Keep a local copy 
		           		else
		           		    duplicateToc = ETrue;
		           		}
		            if ( CategoryObj )
		            	{
		                iIndexing->RuntimeGenerateIndexL( *CategoryObj, XMLParser->GetFeatureIds() );

                        if( duplicateToc )
                        	{
                            iDuplicateHelpTopicList.Append(CategoryObj);
                        	}
		            	}
		            }
            	}         
            }
        }       

    CleanupStack::PopAndDestroy(entryList);
    }
TBool CCSXHHTMLContentParser::IsRomBasedContentL( RFs& FileSession, const TDesC &aUid )
    {
#ifdef __WINSCW__
    return ETrue;
#endif
    
	TBool result = EFalse;
	CDirScan* scanner=CDirScan::NewLC(FileSession);
	TBuf<KMaxFileName> rootDir;
	rootDir.Append( 'z' );
	        	
	if( GetHTMLContentPathForDriveL( &rootDir,iCoeEnv ) )
		{
	    scanner->SetScanDataL(rootDir,KEntryAttDir|KEntryAttMatchExclusive,
	                                    ESortByName|EAscending, CDirScan::EScanDownTree);
        CDir* entryList = NULL;
        scanner->NextL(entryList);
    
        if ( !entryList )
        	{
            CleanupStack::PopAndDestroy( scanner );
            return EFalse;
        	}
 
        TInt entryCount = entryList->Count();           
    
        while ( entryCount-- )
            {
            TEntry entry=(*entryList)[entryCount]; 
            if ( ( entry.iName ).CompareC(aUid) == 0 )
        	    {
                result = ETrue;
            	break;
        	    }
            }
        delete entryList;
		}
    
    CleanupStack::PopAndDestroy( scanner );
 
    return result;
    }
    
void CCSXHHTMLContentParser::InsertHTMLToc1L(
            const TDesC &appUidName,const TDesC &appName, 
            const TInt& aDrive , CCSXHHelpDataBase* aDataBase, 
            const TDesC &FeatureIds, TInt32 aPriority )
    {
	if(CheckFeatureIDL(FeatureIds))
	    {
	    if(!IsAppUIdPresentAlready(appUidName)) 
            {    
            CCSXHHtmlTOC1* CategoryObj = NULL;
            TBool duplicateToc = EFalse;
            // Now we take a walk if it's application helps (priority == 0)
            if ( aPriority == 0 )
                {
                CategoryObj = CCSXHHtmlTOC1::NewL(appName,appUidName,aDrive,
                		                          KCSXHToc2AppHelpsViewID,aPriority);
                // Hardcode EDriveZ as ROM drive, need to be runtime check?
                if(CategoryObj && aDataBase->GetAppHelpsTopics()->InsertChild(CategoryObj,EFalse))
                    iHtmlTOC1List.Append(CategoryObj);//Keep a local copy 
                else
                    duplicateToc = ETrue;
                }
            else
                {
                CategoryObj = CCSXHHtmlTOC1::NewL(appName,appUidName,aDrive,
                		                          KCSXHToc2ViewID,aPriority);
                if(CategoryObj && aDataBase->GetMainTopics()->InsertChildWithPriority(CategoryObj,EFalse))
                    iHtmlTOC1List.Append(CategoryObj);//Keep a local copy*/ 
                else
                    duplicateToc = ETrue;
                }

            if( CategoryObj && duplicateToc )  
                iDuplicateHelpTopicList.Append(CategoryObj);			    	
		    }
	    }	
    }
    
HBufC8* CCSXHHTMLContentParser::GetContentsFromFileL(const TDesC& htmlFile,CCoeEnv* aCoeEnv,
			RFeatureControl& aFeatureControl) 
    {
    RFs& fileSession = aCoeEnv->FsSession();        
    TInt SlashPosition = htmlFile.LocateReverse('\\');    
    TBuf<KMaxFileName>* CompressedFile = new (ELeave) TBuf<KMaxFileName>; 
    CleanupStack::PushL(CompressedFile); //1
    CompressedFile->Copy(htmlFile.Mid(0,SlashPosition+1));
    CompressedFile->Append(KContentZipFile);    
    
    HBufC8* CssContent = CreateBufferForCSSContentL(aFeatureControl);
       
    if(!BaflUtils::FileExists(fileSession,*CompressedFile))
        {
        CleanupStack::PopAndDestroy(CompressedFile);
        
        HBufC8* buffer = GetContentsFromHTMLFileL(htmlFile,aCoeEnv);
        
        return MergeCssAndHTMLContentL(buffer,CssContent);
        }
        
    // Create an instance of CZipFile.
    CZipFile* zipFile = CZipFile::NewL(fileSession, *CompressedFile);    
    CleanupStack::PushL(zipFile); //2
        
    // Iterate and get the file name
    CZipFileMemberIterator* members = zipFile->GetMembersL();
    CleanupStack::PushL(members);//3
    CZipFileMember* member = members->NextL(); // Get the first file in zip
    
    TInt nCount=0;    
    const TBuf<KMaxFileName>*Fname;
    TBuf<KMaxFileName> *HtmlFileName = new (ELeave) TBuf<KMaxFileName>;
    CleanupStack::PushL(HtmlFileName); //4
    HtmlFileName->Copy(htmlFile.Mid(SlashPosition+1));
    for(nCount=0;member!=NULL;nCount++)
    	{    	 
    	 Fname = member->Name();    
	     if(Fname->Compare(*HtmlFileName)==0 )
	    	{
	    	break;
	    	}	    
	    delete member;	
    	member = members->NextL();    	
    	}

	if(NULL == member)
		{
		CleanupStack::PopAndDestroy(HtmlFileName);
		CleanupStack::PopAndDestroy(members);
	    CleanupStack::PopAndDestroy(zipFile);
	    CleanupStack::PopAndDestroy(CompressedFile);
	    
	    HBufC8* buffer = GetContentsFromHTMLFileL(htmlFile,aCoeEnv);
	    return MergeCssAndHTMLContentL(buffer,CssContent);
	    }
		
    CleanupStack::PushL(member);//5
    RZipFileMemberReaderStream* stream;
    zipFile->GetInputStreamL(member, stream);
    CleanupStack::PushL(stream);//6
        
    // Extracts aFileName to a buffer.
    // If the file is quite huge, then read the file in streaming mode.
    // For example, use 4KB buffer and read it in an active object.
    HBufC8* buffer = HBufC8::NewLC(member->UncompressedSize());//5
    TPtr8 bufferPtr(buffer->Des());
    User::LeaveIfError(stream->Read(bufferPtr, member->UncompressedSize()));

    // Release all the resources.   
    CleanupStack::Pop(buffer);
    CleanupStack::PopAndDestroy(stream); 
    CleanupStack::PopAndDestroy(member);
    CleanupStack::PopAndDestroy(HtmlFileName);
    CleanupStack::PopAndDestroy(members);
    CleanupStack::PopAndDestroy(zipFile);
    CleanupStack::PopAndDestroy(CompressedFile);
    
    return MergeCssAndHTMLContentL(buffer,CssContent);
    }

TBool CCSXHHTMLContentParser::HandleMasterKeywordFileL(CCSXHHelpDataBase* aDataBase)
    {
    RFs& FileSession = iCoeEnv->FsSession();
    CCSXHXMLParseHandler_MasterKywd* XMLParser_MasterKywd = CCSXHXMLParseHandler_MasterKywd::NewL(iCoeEnv);  
    CleanupStack::PushL(XMLParser_MasterKywd);  
    InitializeReaderL(XMLParser_MasterKywd);
    XMLParser_MasterKywd->SetHtmlContentParserPtr(this);
    XMLParser_MasterKywd->SetDataBasePtr(aDataBase);
    TBool bMasterKeywordFilePresent = EFalse;
    
    //Check for the availability of Master Keyword file
    TBuf<KMaxFileName>* Master_kywdPath = new(ELeave) TBuf<KMaxFileName>;
    CleanupStack::PushL(Master_kywdPath);//5
    Master_kywdPath->Append(PathInfo::RomRootPath().Left(1));
    GetHTMLContentPathForDriveL(Master_kywdPath,iCoeEnv);
    Master_kywdPath->Append(KMasterKywdFile);
    
    if(BaflUtils::FileExists(FileSession,*Master_kywdPath))
    	{    	
        TRAP_IGNORE(iXmlReader->ParseL(FileSession,*Master_kywdPath ));
        bMasterKeywordFilePresent = ETrue;
    	}    
    
    //KMasterKywdFile;
    CleanupStack::PopAndDestroy(Master_kywdPath);
    CleanupStack::PopAndDestroy(XMLParser_MasterKywd);
    ClearReader();	
    
    return bMasterKeywordFilePresent;
    }
    
void CCSXHHTMLContentParser::GenerateKywdTOC1ListL(CCSXHHelpDataBase* aDataBase)
    {
    if(!iHtmlTOC1List.Count())
        return;
    TBool bMasterKeywordFilePresent = HandleMasterKeywordFileL(aDataBase);
    
    CCSXHXMLParseHandler_Kywd* XMLParser = CCSXHXMLParseHandler_Kywd::NewL(iCoeEnv);  
    CleanupStack::PushL(XMLParser);  
    InitializeReaderL(XMLParser);
    
    XMLParser->SetDataBasePtr(aDataBase);
    XMLParser->SetIsTOC2(EFalse);
    XMLParser->SetHtmlContentParserPtr(this);
    
    //Parse keyword.xml file from Main Array list
    ParseKeywdFileAndCreatekywdTOC1ObjectsL(iHtmlTOC1List,XMLParser,bMasterKeywordFilePresent);
    
    //Parse keyword.xml file from duplicate Array list
    ParseKeywdFileAndCreatekywdTOC1ObjectsL(iDuplicateHelpTopicList,XMLParser,bMasterKeywordFilePresent);
    
    CleanupStack::PopAndDestroy(XMLParser);
    ClearReader();
    }
    
void CCSXHHTMLContentParser::GenerateTOC2ListForKeywordSearchL
(CCSXHHelpDataBase* aDataBase,CCSXHKywdTOC1* aKywdTOC1Object)
    {
    RPointerArray<CCSXHHtmlTOC1>* TOC1HtmlList = aKywdTOC1Object->GetHtmlTOC1List();
    if(!TOC1HtmlList)
        return;
    
    CCSXHXMLParseHandler_Kywd* XMLParser = CCSXHXMLParseHandler_Kywd::NewL(iCoeEnv);
    CleanupStack::PushL(XMLParser);      
    InitializeReaderL(XMLParser);
	
    int toc1Count = TOC1HtmlList->Count();
    CCSXHHtmlTOC1* toc1;

    RFs& FileSession = iCoeEnv->FsSession();
    
    XMLParser->SetDataBasePtr(aDataBase);
    XMLParser->SetIsTOC2(ETrue);
    XMLParser->SetHtmlContentParserPtr(this);
    
    TBuf<KMaxFileName>* lookup = new(ELeave)TBuf<KMaxFileName>;
    CleanupStack::PushL(lookup);//3
    XMLParser->SetTOC1Title(aKywdTOC1Object->GetName());
    for(int i = 0; i < toc1Count ; ++i )
        {
        toc1 = (*TOC1HtmlList)[i];
        //Get Corresponding toc1 from Main array and set toc1 object
        XMLParser->SetCurrentHtmlToc1(GetCorrespondingTOC1FromMainArray(toc1->GetName()));
        //Clear the previous values
        lookup->Delete(0,lookup->Length());
        toc1->GetHelpFileL(*lookup);
        XMLParser->SetPath(*lookup);
        lookup->Append(KKeywordsFile);
        TRAP_IGNORE(iXmlReader->ParseL (FileSession,*lookup ));
        aDataBase->IncrementKeywordSearchCount();
        }   
    CleanupStack::PopAndDestroy(lookup);
    CleanupStack::PopAndDestroy(XMLParser);  
    ClearReader();
    }
    
CCSXHHelpContentBase* CCSXHHTMLContentParser::GetContextTopicL( 
		CCSXHHelpDataBase *aDataBase, 
		TUid &aUid, 
		TCoeContextName &aContextName
		)
    {
    TBuf<KMaxFileName> path;
    TInt32 toc1Count = iHtmlTOC1List.Count();
    TInt32 dupToc1Count = iDuplicateHelpTopicList.Count();
    CCSXHHtmlTOC1 *toc1 = NULL;
    CCSXHHtmlTOC1 *temptoc1 = NULL;
    TBool redirected = EFalse;
    
    for ( TInt32 i = 0; i < toc1Count; ++i )
        {
        toc1 = iHtmlTOC1List[i];
        if ( aUid == toc1->GetAppUid() )
            {
            toc1->GetHelpFileL( path );
            if ( IsRedirectedL( aDataBase, path, aUid, aContextName ) )
            	{
                redirected = ETrue;
            	}
            else
            	{
                return toc1->GetContextTopic( aContextName );
            	}
            break;
            }
        }
    
    if ( !redirected )
        {
        for ( TInt32 i = 0; i < dupToc1Count; ++i )
            {
    	    toc1 = iDuplicateHelpTopicList[i];
    	    if ( aUid == toc1->GetAppUid() )
    	        {
    	        toc1->GetHelpFileL( path );
    	        if ( IsRedirectedL( aDataBase, path, aUid, aContextName ) )
    	            {
    	            redirected = ETrue;
    	            }
    	        else
    	            {
    	            temptoc1 = GetCorrespondingTOC1FromMainArray(toc1->GetName());        		
    	            return temptoc1->GetContextTopic( aContextName );
    	            }
    	        }
            }
        }
    	
    if ( redirected )
    	{
    	for ( TInt32 i = 0; i < toc1Count; ++i )
    	    {
    	    toc1 = iHtmlTOC1List[i];
    	    if ( aUid == toc1->GetAppUid() )
    	        {    
    	        return toc1->GetContextTopic( aContextName );
    	        }
    	    }
    	
    	for ( TInt32 i = 0; i < dupToc1Count; ++i )
    	    {
    	    toc1 = iDuplicateHelpTopicList[i];
    	    if ( aUid == toc1->GetAppUid() )
    	        {
    	    	temptoc1 = GetCorrespondingTOC1FromMainArray( toc1->GetName() );        		
    	    	return temptoc1->GetContextTopic( aContextName );
    	    	}
    	    }
    	}
        
    return NULL;
    }
    
CCSXHHelpContentBase* CCSXHHTMLContentParser::GetHtmlTopicForUrlL(const TDesC& aUrl)
    {
    CCSXHHelpContentBase* tocobj = GetObjectBasedonUrlL(iHtmlTOC1List,aUrl,ETrue);
    
    if(NULL == tocobj)
    	tocobj = GetObjectBasedonUrlL(iDuplicateHelpTopicList,aUrl,EFalse);
    
	return tocobj;    	
    }

CCSXHHelpContentBase* CCSXHHTMLContentParser::GetObjectBasedonUrlL(RPointerArray<CCSXHHtmlTOC1>& aTOC1ObjectsArray,
		const TDesC& aUrl, TBool aMainArrayList)    
    {
        /*For URLs of form 
        file:://<Drive Name>:/system/xhtml/<Lang ID>/<App UID>/Html name
      We can have help topics for other cases, help topic objects not possible   
    */
    TBuf<KMaxFileName> aFileUrl;
    
    int toc1Count = aTOC1ObjectsArray.Count();
    CCSXHHtmlTOC1* toc1,*temptoc1;
    for(int j = 0; j < toc1Count; ++j)
        {
        toc1 = aTOC1ObjectsArray[j];
        TBuf<KMaxFileName> htmlFile;
        toc1->GetHelpFileL(htmlFile);
        
        //Convert fwd slashes to back slashes
        TInt i = htmlFile.Find(KFwdSlash) ;
        while (KErrNotFound != i)
            {
            htmlFile.Replace(i,1,KBackSlash);
            i = htmlFile.Find(KFwdSlash) ;
            }
        
        i = aUrl.FindC(htmlFile);
        if(i != KErrNotFound)
            {
            TFileName fileName;
            i = aUrl.LocateReverseF('/');
            fileName = aUrl.Mid(i + 1);
            if(aMainArrayList)
            	temptoc1 = toc1;
            else
            	temptoc1 = GetCorrespondingTOC1FromMainArray(toc1->GetName());	
            
            return temptoc1->GetHtmlTopicForFile(fileName);
            }
        }
    return NULL;	
    }

void CCSXHHTMLContentParser::GetHtmlFileL(CCoeEnv* coeEnv,const short& aDir,
                                            const TAppUid& aUid,TBuf<KMaxFileName>& aFileName)
    {
    aFileName.Copy(KEmptyString);
    
    RFs& FileSession = coeEnv->FsSession();
    TDriveList DirList; 
    if( (FileSession.DriveList(DirList)<KErrNone) ||
        (aDir >= DirList.Length()))
        return; 
    
    TChar driveLetter = '?';
    TDriveInfo info;
    TInt error = FileSession.Drive(info, aDir);
    if  ((error == KErrNone) && 
        (DirList[aDir] && info.iType != EMediaNotPresent))
        {
        RFs::DriveToChar(aDir, driveLetter);

        aFileName.Append(driveLetter);
        GetHTMLContentPathForDriveL(&aFileName,coeEnv);
        aUid.AppendUid(aFileName);
        aFileName.Append(KFwdSlash);
        }
    }

void CCSXHHTMLContentParser::InitializeReaderL(CCSXHXMLParseHandler* aXMLParser)
    {
    if(iXmlReader == NULL )
        {       
        iXmlReader = CSenXmlReader::NewL();
        iXmlReader->SetContentHandler(*aXMLParser);
        }
    }
void CCSXHHTMLContentParser::ClearReader()
    {
    delete iXmlReader;
    iXmlReader = NULL;
    }
    
TBool CCSXHHTMLContentParser::IsUidCategoryPresent(const TUid& aUid)
    {
    int toc1Count = iHtmlTOC1List.Count();
    CCSXHHtmlTOC1* toc1;    
    for(int i = 0; i < toc1Count; ++i)
        {
        toc1 = iHtmlTOC1List[i];
        if(aUid == toc1->GetAppUid())
            return ETrue;
        }
    
    toc1Count = iDuplicateHelpTopicList.Count();
    for(int i = 0; i < toc1Count; ++i)
        {
        toc1 = iDuplicateHelpTopicList[i];
        if(aUid == toc1->GetAppUid())
            return ETrue;
        }    
    return EFalse;  
    }

TBool CCSXHHTMLContentParser::GetHTMLToc1(const TDesC& aUid,CCSXHXMLParseHandler* aParser)
	{
	TUint AppId;
	
	if(!aUid.Length())
		return EFalse;

    TLex FolderUid(aUid.Mid(KOffset));
    FolderUid.Val(AppId,EHex);
    TUid ApplicationUid = TUid::Uid((TInt)AppId);
	
	int toc1Count = iHtmlTOC1List.Count();
	
    CCSXHHtmlTOC1* toc1;    
    for(int i = 0; i < toc1Count; ++i)
        {
        toc1 = iHtmlTOC1List[i];
        if(ApplicationUid == toc1->GetAppUid())
        	{
        	STATIC_CAST(CCSXHXMLParseHandler_MasterKywd*,aParser)->SetCurrentHtmlToc1(toc1); 
        	return ETrue;
        	}            
        }
	
	toc1Count = iDuplicateHelpTopicList.Count();	        
	for(int i = 0; i < toc1Count; ++i)
        {
        toc1 = iDuplicateHelpTopicList[i];
        if(ApplicationUid == toc1->GetAppUid())
        	{
        	STATIC_CAST(CCSXHXMLParseHandler_MasterKywd*,aParser)->SetCurrentHtmlToc1(toc1); 
        	return ETrue;
        	}            
        }
                
    return EFalse;  
	}

//To get Corresponding toc1 from main array.
CCSXHHtmlTOC1* CCSXHHTMLContentParser::GetCorrespondingTOC1FromMainArray(const TDesC& aApplicationName)
	{
	TInt toc1Count = iHtmlTOC1List.Count();
	CCSXHHtmlTOC1* toc1;
	for(int i=0;i<toc1Count;++i)
		{
		toc1 = iHtmlTOC1List[i];
		if(toc1->GetName().CompareF(aApplicationName) == 0)
			return toc1;
		}
	
    return NULL;
	}

//Check UId is already present in the list.	
TBool CCSXHHTMLContentParser::IsAppUIdPresentAlready(const TDesC& aUid)
	{
	TBool result = EFalse;
	TInt toc1Count = iHtmlTOC1List.Count();
	CCSXHHtmlTOC1* toc1;
	
	TUint AppId;
    TLex FolderUid(aUid.Mid(KOffset));
    FolderUid.Val(AppId,EHex);
    TUid ApplicationUid = TUid::Uid((TInt)AppId);
	
	for(int i=0;i<toc1Count;++i)
		{
		toc1 = iHtmlTOC1List[i];
		if(ApplicationUid == toc1->GetAppUid())
			{
			result = ETrue;
			break;
			}			
		}
		
	toc1Count =    iDuplicateHelpTopicList.Count();	
	for(int i=0;i<toc1Count;++i)
		{
		toc1 = iDuplicateHelpTopicList[i];
		if(ApplicationUid == toc1->GetAppUid())
			{
			result = ETrue;
			break;
			}
		}		
		
	return result;	

	}
	
void CCSXHHTMLContentParser::ParseKeywdFileAndCreatekywdTOC1ObjectsL(
		RPointerArray<CCSXHHtmlTOC1>& aTOC1ObjectsArray,
		CCSXHXMLParseHandler_Kywd* XMLParser, TBool bMasterKeywordFilePresent)
	{
	int toc1Count = aTOC1ObjectsArray.Count();
    CCSXHHtmlTOC1* toc1;
     
    TBuf<KMaxFileName>* lookup = new(ELeave)TBuf<KMaxFileName>;
    CleanupStack::PushL(lookup);//1
    
    RFs& FileSession = iCoeEnv->FsSession();
	
	    for(int i = 0; i < toc1Count; ++i)
        {
        toc1 = aTOC1ObjectsArray[i];
        
        if(bMasterKeywordFilePresent && toc1->IsROMDrive())
        	continue;
        
        //Clear the previous values
        lookup->Delete(0,lookup->Length());
        
        toc1->GetHelpFileL(*lookup);
        lookup->Append(KKeywordsFile);
        
          //Check whether a file exists        
        if(!BaflUtils::FileExists(FileSession,*lookup))
            continue;
        
        XMLParser->SetCurrentHtmlToc1(toc1);
        TRAP_IGNORE(iXmlReader->ParseL(FileSession,*lookup ));
        }

    CleanupStack::PopAndDestroy(lookup);  
	}

//RUNTIME
void CCSXHHTMLContentParser::GetSupportedFeatureListL()
	{
	RFeatureUidArray SupportedFeatures;	
	TInt err = iFeatureControl.Connect();
	if ( err == KErrNone )
		{
         // ListSupportedFeatures() returns one of the Symbian error codes.
         err = iFeatureControl.ListSupportedFeatures( SupportedFeatures );
		 	
         // Remember to call CloseL after using RFeatureControl.
         // It disconnects the Feature Manager server.
         iFeatureControl.Close();  
		}
	//As per new req. add true, flase to id and create an array.
	
	iFeatureManager_FeatureIds = new (ELeave) CDesCArrayFlat(2); 
	
	TBuf<25>CurrFId;
	
	for(TInt i=0;i<SupportedFeatures.Count();i++)
		{
		CurrFId.Copy(KEmptyString);	
		CurrFId.AppendNum(SupportedFeatures[i].iUid);
		iFeatureManager_FeatureIds->AppendL(CurrFId);
		
		CurrFId.Copy(KTrue_StringtoAppend);	
		CurrFId.AppendNum(SupportedFeatures[i].iUid);
		iFeatureManager_FeatureIds->AppendL(CurrFId);
		
		CurrFId.Copy(KFalse_StringtoAppend);	
		CurrFId.AppendNum(SupportedFeatures[i].iUid);
		iFeatureManager_FeatureIds->AppendL(CurrFId);		
		}
		
	//Input Language variation changes
	//-----------------------------------------
	//Create an array with supported input language		
	CPtiEngine* ptiEngine = CPtiEngine::NewL();
    CleanupStack::PushL( ptiEngine );
    
    CArrayFix<TInt>* languageCodeArray = new(ELeave)CArrayFixFlat<TInt>(2);
    
    ptiEngine->GetAvailableLanguagesL( languageCodeArray );
	
	TInt nCount = languageCodeArray->Count();
	
	iSupportedInputLanguages = new (ELeave) CDesCArrayFlat(2); 
	
	//Codescanner gives error, if member variables are pushed.
	//CleanupStack::PushL( iSupportedInputLanguages );
    
    for(TInt i=0; i<nCount;i++)
    	{
    	TInt languageCode = languageCodeArray->At(i);
    	TBuf<25>Currlang(_L("LANGUAGE_"));
		if(languageCode < 10)
			Currlang.AppendNumFixedWidth(languageCode,EDecimal,2);
		else
			Currlang.AppendNum(languageCode);
		
		iSupportedInputLanguages->AppendL(Currlang);
    	}
    
    //CleanupStack::Pop(iSupportedInputLanguages);	
    CleanupStack::PopAndDestroy( ptiEngine );
    
    delete languageCodeArray;	
    //-----------------------------------------
    
    SupportedFeatures.Close();
	}
	
//RUNTIME
TBool CCSXHHTMLContentParser::CheckFeatureIDL(const TDesC& aFeatureIds)
	{
	if(/*KHexPrefixLength == aFeatureIds.Length() &&*/ 
		KErrNotFound != aFeatureIds.Find(KDefaultFeatureIdStringTemp))
		{
		return ETrue;
		}
			
	HBufC* Ids = HBufC::NewLC(aFeatureIds.Length());	
	TPtr CurrentFeatureIds = Ids->Des();	
	CurrentFeatureIds.Copy(aFeatureIds);
	CleanupStack::Pop(Ids);
		
	CDesCArray* FeatureIdList = new (ELeave) CDesCArrayFlat(2); ;
	TInt EndPos = CurrentFeatureIds.Locate(' ');
	
	CleanupStack::PushL(FeatureIdList);
				
    while (KErrNotFound != EndPos)
        {
				FeatureIdList->AppendL(CurrentFeatureIds.Mid(0,EndPos));// FId_Val);	        
        CurrentFeatureIds = CurrentFeatureIds.Mid(EndPos+1);
        EndPos = CurrentFeatureIds.Locate(' ') ;
        }

	if(KErrNotFound == EndPos && 0!= CurrentFeatureIds.Length())
		{
		FeatureIdList->AppendL(CurrentFeatureIds);
		}    
	
	CleanupStack::Pop(FeatureIdList); 
	 
	TInt position;		
	if(KErrNone == FeatureIdList->Find(KDefaultFeatureIdString,position) || 
	   KErrNone == FeatureIdList->Find(KDefaultFeatureIdStringTemp,position) )
		{
		delete FeatureIdList;
		delete Ids;
		return ETrue;
		}
		
	TInt nCount = FeatureIdList->MdcaCount();
	
	
	//FeatureManager list contains all enabled featureIds, appended with true, and false.
	//New Req. text associated with true_featureId, should be displayed, if Id is enabled.
	//else, if featureId is disabled, text associated with false_featureId should be displayed. 
	// 1. if featureId string contains "false" and it is not in the list, return ETrue.
	// 2. if featureId string does not contain "false" and it is present in the list, return ETrue.
	// 3. if featureId is part of input language, return ETrue.
	for(TInt j=0;j < nCount;j++)
		{
		if(
			(KErrNotFound != FeatureIdList->MdcaPoint(j).Find(KFalseString) &&
			KErrNone != iFeatureManager_FeatureIds->Find(FeatureIdList->MdcaPoint(j),position))||
		
			(KErrNotFound == FeatureIdList->MdcaPoint(j).Find(KFalseString) &&
			KErrNone == iFeatureManager_FeatureIds->Find(FeatureIdList->MdcaPoint(j),position)) ||
		
			KErrNone == iSupportedInputLanguages->Find(FeatureIdList->MdcaPoint(j),position)
		)						
			{
			delete FeatureIdList;
			delete Ids;
			return ETrue;
			}		
		}
				
	delete Ids;		
	delete FeatureIdList;	
	return EFalse;		
	}	
	
HBufC8* CCSXHHTMLContentParser::CreateBufferForCSSContentL(RFeatureControl& aFeatureControl)
	{	
	RFeatureUidArray SupportedFeatures;
	TInt err = aFeatureControl.Connect();
	if ( err == KErrNone )
		{
         // ListSupportedFeatures() returns one of the Symbian error codes.
         err = aFeatureControl.ListSupportedFeatures( SupportedFeatures );
		 	
         // Remember to call CloseL after using RFeatureControl.
         // It disconnects the Feature Manager server.
         aFeatureControl.Close();                    
		}
	
		//Input Language variation changes
	//-----------------------------------------

	CPtiEngine* ptiEngine = CPtiEngine::NewL();
    CleanupStack::PushL( ptiEngine );

    CArrayFix<TInt>* languageCodeArray = new(ELeave)CArrayFixFlat<TInt>(2);

    ptiEngine->GetAvailableLanguagesL( languageCodeArray );
    
	TInt nInputLangCount = languageCodeArray->Count();
	TInt nCount = SupportedFeatures.Count();	

	HBufC8* CssContent = HBufC8::NewLC(nCount * KMaxUnits * 6 + nInputLangCount * 3 + 400);
	TPtr8 bufferPtr(CssContent->Des());
	
	AppendStyleSheetContent_listitem(bufferPtr,nCount,SupportedFeatures,*languageCodeArray);
	AppendStyleSheetContent_paragraph(bufferPtr,nCount,SupportedFeatures,*languageCodeArray);
	AppendStyleSheetContent_ahref(bufferPtr,nCount,SupportedFeatures,*languageCodeArray);
	AppendStyleSheetContent_none(bufferPtr,nCount,SupportedFeatures);	
		
	SupportedFeatures.Close();				
	
	CleanupStack::Pop(CssContent);	
	
	//Input Language variation changes
	//-----------------------------------------
	CleanupStack::PopAndDestroy( ptiEngine );	

	delete languageCodeArray;
	//-----------------------------------------

	return CssContent;
	}
	
HBufC8* CCSXHHTMLContentParser::GetContentsFromHTMLFileL(const TDesC& htmlFile,CCoeEnv* aCoeEnv)
	{
	RFs& fsSession = aCoeEnv->FsSession();             
	RFile file; 
        
	TInt err = file.Open(fsSession,htmlFile,EFileRead|EFileShareReadersOrWriters);
    if(KErrNone == err)
	    {
	    TInt FileSize;
	    HBufC8* htmlFileContent = NULL;
	    if(KErrNone == file.Size(FileSize))
		    {
		    htmlFileContent = HBufC8::NewLC(FileSize);
			TPtr8 PtrContent = htmlFileContent->Des();
	        
		    file.Read(PtrContent);	
		    CleanupStack::Pop(htmlFileContent);			    
		    }		
	    file.Close();
		return htmlFileContent;
		}
	else
		{		
		return NULL;
		}
	}
	
HBufC8* CCSXHHTMLContentParser::MergeCssAndHTMLContentL(HBufC8* aHTMLBuffer, HBufC8* aCssContent)
	{
    TInt BufferLength=0;
    if(aHTMLBuffer)
    	BufferLength = aHTMLBuffer->Size();
    
    if(aCssContent)
    	BufferLength += aCssContent->Size();
    
    HBufC8* Htmlbuffer = HBufC8::NewLC(BufferLength);
    
    TPtr8 HtmlbufferPtr(Htmlbuffer->Des());
    
    if(aCssContent)
    	{
    	HtmlbufferPtr.Copy(aCssContent->Des());
    	delete aCssContent;
    	}
    	
    if(aHTMLBuffer)
	    {
	    HtmlbufferPtr.Append(aHTMLBuffer->Des());
	    delete aHTMLBuffer;	
	    }
    
    if(Htmlbuffer)
    	CleanupStack::Pop(Htmlbuffer);
    
    return Htmlbuffer;	
	}

void CCSXHHTMLContentParser::AppendStyleSheetContent_listitem(TPtr8& abufferptr,TInt aFeatureIdCount,
													RFeatureUidArray& aSupportedFeatures,
													CArrayFix<TInt>& alanguageCodeArray)
	{
	//List Items
	//---------------------------------------------------------
	abufferptr.Copy(KCsstext_First);
	
	for(TInt i=0;i<aFeatureIdCount;++i)
		{
		TBuf<KMaxFileName> FeatureId;
		FeatureId.Format(KtextFormat_true_l,aSupportedFeatures[i].iUid);
		//FeatureId.Append(KComma);
		abufferptr.Append(FeatureId);		
		}
		
	for(TInt i=0;i<alanguageCodeArray.Count();++i)
		{
		TBuf<KMaxFileName> FeatureId;
		if(alanguageCodeArray[i] < 10)
			FeatureId.Format(KtextFormat_lang_0l,alanguageCodeArray[i]);
		else
			FeatureId.Format(KtextFormat_lang_l,alanguageCodeArray[i]);
		
		abufferptr.Append(FeatureId);		
		}
		
	abufferptr.Append(KDefaultFeatureId);		
	abufferptr.Append(KCsstext_displayp_li);		
	abufferptr.Append(KCsstext_Last);
	//---------------------------------------------------------
	}

void CCSXHHTMLContentParser::AppendStyleSheetContent_paragraph(TPtr8& abufferptr,TInt aFeatureIdCount,
													RFeatureUidArray& aSupportedFeatures,
													CArrayFix<TInt>& alanguageCodeArray)
	{
	//Paragraph
	//---------------------------------------------------------
	abufferptr.Append(KCsstext_First);
	for(TInt i=0;i<aFeatureIdCount;++i)
		{
		TBuf<KMaxFileName> FeatureId;
		FeatureId.Format(KtextFormat_true_b,aSupportedFeatures[i].iUid);
		//FeatureId.Append(KComma);
		
		abufferptr.Append(FeatureId);		
		}
		
	for(TInt i=0;i<alanguageCodeArray.Count();++i)
		{
		TBuf<KMaxFileName> FeatureId;
		if(alanguageCodeArray[i] < 10)
			FeatureId.Format(KtextFormat_lang_0b,alanguageCodeArray[i]);
		else
			FeatureId.Format(KtextFormat_lang_b,alanguageCodeArray[i]);
		
		abufferptr.Append(FeatureId);		
		}
		
	abufferptr.Append(KDefaultFeatureId);
	abufferptr.Append(KCsstext_displayp_p);		
	abufferptr.Append(KCsstext_Last);
	
	//---------------------------------------------------------
	}

void CCSXHHTMLContentParser::AppendStyleSheetContent_ahref(TPtr8& abufferptr,TInt aFeatureIdCount,
												RFeatureUidArray& aSupportedFeatures,
												CArrayFix<TInt>& alanguageCodeArray)
	{
	//A href
	//---------------------------------------------------------
	abufferptr.Append(KCsstext_First);
	for(TInt i=0;i<aFeatureIdCount;++i)
		{
		TBuf<KMaxFileName> FeatureId;
		FeatureId.Format(KtextFormat_true_a,aSupportedFeatures[i].iUid);		
		abufferptr.Append(FeatureId);		
		}
	
	for(TInt i=0;i<alanguageCodeArray.Count();++i)
		{
		TBuf<KMaxFileName> FeatureId;
		if(alanguageCodeArray[i] < 10)
			FeatureId.Format(KtextFormat_lang_0a,alanguageCodeArray[i]);
		else
			FeatureId.Format(KtextFormat_lang_a,alanguageCodeArray[i]);
		abufferptr.Append(FeatureId);		
		}
		
	abufferptr.Append(KDefaultFeatureId);
	abufferptr.Append(KCsstext_displayp_a);		
	abufferptr.Append(KCsstext_Last);
	
	//---------------------------------------------------------
	}

void CCSXHHTMLContentParser::AppendStyleSheetContent_none(TPtr8& abufferptr,TInt aFeatureIdCount,
													RFeatureUidArray& aSupportedFeatures
													)
	{
	//False
	//---------------------------------------------------------
	abufferptr.Append(KCsstext_First);
	for(TInt i=0;i<aFeatureIdCount;++i)
		{
		TBuf<KMaxFileName> FeatureId;
		FeatureId.Format(KtextFormat_false,aSupportedFeatures[i].iUid,aSupportedFeatures[i].iUid,aSupportedFeatures[i].iUid);
		abufferptr.Append(FeatureId);		
		}
		
	abufferptr.Append(KDefaultFeatureId);
	abufferptr.Append(KCsstext_displayp_n);		
	abufferptr.Append(KCsstext_Last);
	
	//---------------------------------------------------------
	}