textrendering/texthandling/spml/T_PMLPAR.CPP
changeset 0 1fb32624e06b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/textrendering/texthandling/spml/T_PMLPAR.CPP	Tue Feb 02 02:02:46 2010 +0200
@@ -0,0 +1,1933 @@
+/*
+* Copyright (c) 1997-2009 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: 
+*
+*/
+
+
+#include "../incp/T_PMLPAR.H"
+
+#define UNUSED_VAR(a) a = a
+
+#define UNUSED_VAR(a) a = a
+
+////////////////////////////////////////////
+// CParser
+////////////////////////////////////////////
+
+CParser* CParser::NewL()
+	{
+	CParser* self=new(ELeave) CParser;
+	CleanupStack::PushL(self);
+	self->ConstructApplicationL();
+	CleanupStack::Pop();
+	return self;
+	}
+
+
+CParser::CParser()
+	{
+	// init variables
+	iErrorLevel = ENoError;			
+	iParagraphIsOpen = EFalse;	
+	iLineNo = 1;
+	iReadPos = 0;
+	iDocInsertPos = 0;
+	iDocParaLength = 0;
+	iDocPhraseLength = 0;
+	iBorderUsed = EFalse;
+	iBulletUsed = EFalse;
+	}
+	 
+
+void CParser::ConstructApplicationL()
+	{ 
+	// Construct Rich Text Doc
+	// Make the global format layers and associated formats and masks
+	iGlobalParaFormatLayer=CParaFormatLayer::NewL();
+	iGlobalCharFormatLayer=CCharFormatLayer::NewL();
+	iGlobalParaFormat=CParaFormat::NewL();	   	// initialised with factory settings
+	iGlobalParaFormatMask.SetAll();
+	iGlobalCharFormatMask.SetAll();
+	
+	// Set the global layers
+	iGlobalParaFormatLayer->SetL(iGlobalParaFormat,iGlobalParaFormatMask);
+	iGlobalCharFormatLayer->SetL(iGlobalCharFormat, iGlobalCharFormatMask);
+
+	// Create the rich text document
+	iRichTextDoc=CRichText::NewL(iGlobalParaFormatLayer,iGlobalCharFormatLayer);
+
+	// Initialise the paragraph and character layers
+	iParaFormatLayer = CParaFormatLayer::NewL();
+	iCharFormatLayer = CCharFormatLayer::NewL();
+	iParaFormat = CParaFormat::NewL();
+
+	// Create temp alias' for compound attributes
+	iBorder = new TParaBorder;
+	User::LeaveIfNull(iBorder);
+	iBullet = new (ELeave) TBullet;
+	}
+
+
+CParser::~CParser()
+	{
+	// destroy Rich Text Document
+// 	delete iRichTextDoc;
+//	delete iGlobalParaFormatLayer;
+//	delete iGlobalCharFormatLayer;
+	delete iGlobalParaFormat;
+	delete iParaFormatLayer;
+	delete iCharFormatLayer;
+	delete iParaFormat;
+	if (!iBorderUsed)
+		delete(iBorder);
+	if (!iBulletUsed)
+		delete(iBullet);
+	}
+
+
+CRichText* CParser::ParseL(CConsoleBase* aConsole)
+// version for parsing with console output and interactive file dialog
+// primarily for debugging purposes (you can see what's going on!)
+	{
+	// set console
+	iConsoleExists = ETrue;
+	iConsole = aConsole;
+
+	// Construct a CFileApp & load a file
+	CFileApp* myFileApp=NULL;
+	TRAPD(ret, myFileApp = CFileApp::NewL());
+    UNUSED_VAR(ret);
+	iTextBuf = myFileApp->LoadFileL(iConsole);
+	iFileName = myFileApp->ReturnFileName();
+
+	ParseTextBufL();	   			// parse the buffer
+	delete myFileApp;	// destroy file app
+
+	// Pause before returning
+	WriteNewLine();
+	WriteNewLine();
+	OutputToScreen(_L("Press Space to continue\n"));
+	TKeyCode keystroke = EKeyNull;
+	while (keystroke != EKeySpace)
+		keystroke = iConsole->Getch();
+	return iRichTextDoc;
+	}
+
+CRichText* CParser::ParseL(const TFileName &aFileName)
+// silent version of the parser
+	{
+	iConsoleExists = EFalse;
+	// Construct a CFileApp & load a file
+	CFileApp* myFileApp=NULL;
+	TRAPD(ret, myFileApp = CFileApp::NewL());
+    UNUSED_VAR(ret);
+	iTextBuf = myFileApp->LoadFileL(aFileName);
+	iFileName = myFileApp->ReturnFileName();
+
+	ParseTextBufL();	   			// parse the buffer
+	delete myFileApp;	// destroy file app
+
+	return iRichTextDoc;
+	}
+
+
+void CParser::EmitErrorMessage()
+	{
+	TBuf<80> errorMessage;
+	switch (iErrorLevel)
+		{
+		case EUnknownTagType:
+			errorMessage.Format(_L("    Unknown tag type: Line %d"),iLineNo);
+			break;
+		case EUnparagraphedText:
+			errorMessage.Format(_L("    Text not contained by paragraph: Line %d"),iLineNo);
+			break;
+		case EUnknownAttrib:
+			errorMessage.Format(_L("    Unknown tag attribute: Line %d"),iLineNo);
+			break;
+		case ENoAttribValue:
+			errorMessage.Format(_L("    Unknown attribute or no attribute value supplied: Line %d"),iLineNo);
+			break;
+		case EIllegalAttribValue:
+			errorMessage.Format(_L("    Illegal attribute value: Line %d"),iLineNo);
+			break;
+		default:
+			errorMessage.Format(_L("    Error: Line %d"),iLineNo);
+			break;
+		}
+	OutputToScreen(_L(""));
+	OutputToScreen(_L("*** Error!!\n"));
+	OutputToScreen(errorMessage);
+	}
+
+
+void CParser::OutputToScreen(const TDesC& aMessageBuffer)
+	{
+	if (iConsoleExists)
+		iConsole->Write(aMessageBuffer);  // output line to screen
+	}
+
+
+TBool CParser::Validate()
+// Check that document starts with <G> tag - serves as file validation
+//  - Read in characters sequentially
+//  - if the first alphanumeric characters encountered are not "<G" then error
+	{
+	TBool fileFormatError = EFalse;
+	TBool fileValidated = EFalse;
+	TChar charToTest;
+	while ((!fileFormatError)&&(!fileValidated))
+		{					
+		charToTest = ReadChar();
+		if (charToTest == '<')
+			{
+			iReadPos+=KCharLength;
+			charToTest = ReadTagChar();
+			if (charToTest != 'G')			 // Not a style tag - error
+				fileFormatError = ETrue;
+			else
+				fileValidated = ETrue;
+			}
+		else
+			{
+			if (charToTest.IsAlphaDigit())	 // Char is alphanumeric - error
+				fileFormatError = ETrue;	 // (File must start with style tag)
+			else
+				iReadPos+=KCharLength;
+			}
+		}
+	if (fileFormatError)
+		{
+		OutputToScreen(_L("File format error\n"));
+		}
+	iReadPos = 0;		// reset after validation
+	iLineNo = 1;		// ...
+	return fileValidated;
+	}
+
+
+void CParser::ParseTextBufL()
+// Parses contents of iTextBuf
+// Reads in chars sequentially.
+// - If a char is a tag open ("<") process the following tag
+// - otherwise add the char to the text of the rich text document
+// Tidy up at the end of the document 
+	{ 
+	TChar charToTest;
+	TUint textBufSize = iTextBuf->Size();
+	if (Validate())
+		{
+		while ((iReadPos < textBufSize)&&(iErrorLevel == ENoError))
+			{
+			charToTest = ReadChar();
+			if (charToTest == '<')
+				ProcessTagL();
+			else
+				ProcessTextL(charToTest);
+			iReadPos+=KCharLength;						
+			}
+		if ((iReadPos == textBufSize)&&(iReadPos>0)&&(iErrorLevel == ENoError))
+			{
+			// at end of document apply any outstanding formatting (if there is text to apply it to)
+			if (iDocParaLength > 0)
+				{
+				iParaFormatLayer->SetL(iParaFormat, iParaFormatMask);
+				iRichTextDoc->ApplyParaFormatL( iParaFormat,iParaFormatMask,iDocInsertPos-iDocParaLength,iDocParaLength);
+				}
+			if (iDocPhraseLength > 0)
+				{
+				iCharFormatLayer->SetL(iCharFormat, iCharFormatMask);
+				iRichTextDoc->ApplyCharFormatL(iCharFormat,iCharFormatMask,iDocInsertPos-iDocPhraseLength,iDocPhraseLength);
+				}
+			}
+		if (iErrorLevel != ENoError)
+			EmitErrorMessage();
+		}
+	}
+
+
+TChar CParser::ReadChar()
+// Reads the next character from the text buffer
+	{
+// 	TChar charToTest;
+	TText charToTest;
+	iTextBuf->Read(iReadPos,&charToTest,KCharLength);
+	if (charToTest == (TText)KLineFeed)
+		iLineNo++;				   	// Info used only by error messages
+	return charToTest;
+	}
+
+
+void CParser::ProcessTextL(TChar aChar)
+// 1) Check text is in a paragraph
+// 2) Check for escape characters
+// 3) Check for tabs
+// 4) Add to paragraph
+	{
+	if (!iParagraphIsOpen)
+		{
+		if (!(aChar.IsControl()))
+			iErrorLevel = EUnparagraphedText;	// Text not contained by a paragraph - error!!
+		}
+	else
+		{
+		if (aChar == '/')	// Escape character for <
+			{
+			TChar tempChar;
+			iTextBuf->Read(iReadPos+KCharLength,&tempChar,1);	// doesn't increment line counter
+			if (tempChar == '<')
+				{
+				AddCharToParaL(tempChar);
+				iReadPos+=2*KCharLength;				  	// Skip escape character
+				}
+			else
+				AddCharToParaL(aChar);
+			}
+		else if (aChar == KTabChar)
+			AddCharToParaL(aChar);
+		else if (!(aChar.IsControl()))		// if it's not a control char add it 
+			AddCharToParaL(aChar);			//		(this includes spaces)
+		}
+	}
+
+
+void CParser::AddCharToParaL(TChar aChar)
+	{ 
+	// Add char to RichText doc...
+	iRichTextDoc->InsertL(iDocInsertPos, aChar);
+	iDocInsertPos++;
+	iDocParaLength++;
+	if (iPhraseOpen)
+		iDocPhraseLength++;
+	// and also write it to screen
+	TBuf<4> screenBuf;				// Buffer for text to be written to console
+	screenBuf.Append(aChar);		
+	OutputToScreen(screenBuf);
+	}
+
+
+void CParser::ProcessTagL()
+	{
+	TChar tagChar;
+	iReadPos+=KCharLength;
+	tagChar = ReadTagChar();	  	// Read in tag type
+	ClassifyTagL(tagChar);		  	
+	if (iTagType == EError)
+		iErrorLevel = EUnknownTagType;
+	else
+		{
+		ClassifyArgumentsL();
+		}
+	}
+
+
+TChar CParser::ReadTagChar()
+	{ // Returns tag character capitalised - therefore case-insensitive
+ 	TChar charToTest;
+	charToTest = ReadChar();
+	charToTest.UpperCase();
+	return charToTest;
+	}
+
+
+void CParser::ClassifyArgumentsL()
+// reads tag one argument at a time, dealing with each arg as it is read
+// If and argument is followed by a value (ie a=4) it is processed in two passes.
+	{
+	TChar tagChar(0);
+	iArgStored = EFalse;
+	iArgValueExpected = EFalse;		// Initialise
+	iCancelArg = EFalse;
+	while ((tagChar != '>')&&(iErrorLevel == ENoError))	// ">" is end of tag
+		{
+		iReadPos+=KCharLength;
+		tagChar = ReadTagChar();	// Read in next bit of tag
+		if (iTagType != EComment)	// text of comments is ignored
+			{
+			if (tagChar.IsSpace())	// spaces separate args
+				ProcessArgBufL();
+			if (tagChar == '=')
+				{
+				iArgValueExpected = ETrue;
+				ProcessArgBufL();
+				}
+			if (tagChar == '!')
+				{
+				iCancelArg = ETrue;
+				OutputToScreen(_L("!"));
+				}
+			if (tagChar == ',')
+				AppendToArgBuf(tagChar);
+			if (tagChar.IsAlphaDigit())
+				{
+				AppendToArgBuf(tagChar);
+				}
+			}
+		}
+	if (tagChar == '>')				// Is it end of tag?
+		{
+		if (iTagType != EComment)
+			{
+			ProcessArgBufL();
+			if ((iTagType == EControl)||(iTagType == EGlobal))	// Control & global style formatting is applied "on the spot"
+				SetFormatLayerL();								// While char & paragraph are applied retrospectively
+			}
+		}
+	}
+
+
+void CParser::AppendToArgBuf(TChar aTagChar)
+	{
+	iArgType.Append(aTagChar);	   	// assume it'll fit
+	}
+
+
+void CParser::ProcessArgBufL()
+	{
+	if (iArgValueExpected)
+		{
+		if (iArgStored)
+			{
+			TBuf<32> tempArgBuf;				// Swap the buffers	back as an arg and its value have been stored
+			tempArgBuf = iArgType;
+			EmptyBuffer(iArgType);
+			iArgType = iArgValue;
+			EmptyBuffer(iArgValue);
+			iArgValue = tempArgBuf;
+			TranslateTagArgL();				// Translate the tag argument
+			iArgStored = EFalse;			// Reset the flags and buffers
+			iArgValueExpected = EFalse;
+			EmptyBuffer(iArgType);
+			EmptyBuffer(iArgValue);
+			}
+		else
+			{
+			iArgValue = iArgType;		 	// Swap the buffers ready to store the value of the arg
+			EmptyBuffer(iArgType);			// Empty buffer
+			iArgStored = ETrue;
+			}
+		}
+	else
+		{
+		TranslateTagArgL();			// match to list
+		EmptyBuffer(iArgType);
+		EmptyBuffer(iArgValue);
+		}
+	}
+
+
+void CParser::EmptyBuffer(TDes &aBuf)
+	{
+	aBuf.SetLength(0);
+	}
+
+	 
+void CParser::ClassifyTagL(TChar aTagChar)
+	{
+	switch (aTagChar)
+		{
+		case 'G':
+			iTagType = EGlobal;
+			break;
+		case 'P':
+			{
+			iTagType = EParagraph;
+			if (iParagraphIsOpen)
+				{
+				iRichTextDoc->InsertL(iDocInsertPos,CEditableText::EParagraphDelimiter);  // insert para delimiter
+				WriteNewLine();				// Write new line to console
+				iDocInsertPos++;			// Paragraph delimiters occupy 1 character space
+				iDocParaLength++;
+				if (iPhraseOpen)
+					iDocPhraseLength++;
+				SetFormatLayerL();			// apply formatting to old para before starting to fill new one
+				}
+			else
+				iParagraphIsOpen = ETrue;
+			break;
+			}
+		case 'C':
+			{
+			iTagType = ECharacter;
+			if (iPhraseOpen)                                                      
+				SetFormatLayerL();	// apply formatting to old phrase retrospectively 			    
+			else 
+				iPhraseOpen = ETrue;		
+			break;
+			}
+		case 'X':
+			iTagType = EControl;
+			break;
+		case '!':
+			iTagType = EComment;
+			break;
+		default:
+			iTagType = EError;
+			break;
+		}
+	}
+
+
+void CParser::SetFormatLayerL()
+// Apply format & mask that have been set in the tag to a Layer
+// Apply the layer to the RichText doc
+	{
+	if (iTagType == EGlobal)
+		{
+		iGlobalParaFormatLayer->SetL(iGlobalParaFormat, iGlobalParaFormatMask);
+		iGlobalCharFormatLayer->SetL(iGlobalCharFormat, iGlobalCharFormatMask);
+		iRichTextDoc->SetGlobalParaFormat(iGlobalParaFormatLayer);
+		iRichTextDoc->SetGlobalCharFormat(iGlobalCharFormatLayer);
+		WriteNewLine();
+		}
+	if (iTagType == EParagraph)
+		{
+		iParaFormatLayer->SetL(iParaFormat, iParaFormatMask);
+		iRichTextDoc->ApplyParaFormatL(iParaFormat,iParaFormatMask,iDocInsertPos-iDocParaLength,iDocParaLength);
+		iCharFormatLayer->SetL(iCharFormat, iCharFormatMask);
+		if (iDocPhraseLength > 0)
+			iRichTextDoc->ApplyCharFormatL(iCharFormat,iCharFormatMask,iDocInsertPos-iDocPhraseLength,iDocPhraseLength);
+		iDocParaLength = 0;			// reset ready for new paragraph
+		iDocPhraseLength = 0;
+		}
+	if (iTagType == ECharacter)
+		{
+		iCharFormatLayer->SetL(iCharFormat, iCharFormatMask);
+		if (iDocPhraseLength > 0)
+			iRichTextDoc->ApplyCharFormatL(iCharFormat,iCharFormatMask,iDocInsertPos-iDocPhraseLength,iDocPhraseLength);
+		iDocPhraseLength = 0;
+		}
+	}
+
+
+TInt CParser::GetArgValue()
+// converts numerals in iArgValue to a TInt, 
+// first checking that the buffer is totally numeric in content
+ 	{
+	TInt value = 0;
+	if (BufIsNumeric(iArgValue))
+		{
+		TLex tmpLex(iArgValue);
+		tmpLex.Val(value);
+		}
+	else iErrorLevel = EIllegalAttribValue;
+	return value;
+	}
+
+
+TInt CParser::GetArgValue(const TDes &aBuf)
+// converts numerals in aBuf to a TInt as above
+	{ 
+	TInt value = 0;
+	if (BufIsNumeric(aBuf))
+		{
+		TLex tmpLex(aBuf);
+		tmpLex.Val(value);
+		}
+	else iErrorLevel = EIllegalAttribValue;
+	return value;
+	}
+
+
+TBool CParser::BufIsNumeric(const TDes &aBuffer)
+// checks that aBuffer is totally numeric in content.
+// checks all characters sequentially
+	{
+	TBool isNumeric = ETrue;
+	TChar testChar;
+	TUint bufLength = aBuffer.Length();
+	for (TUint pos=0; ((pos<bufLength)&&(isNumeric)); pos++)
+		{
+		testChar = (aBuffer[pos]);
+		if (!(testChar.IsDigit()&&isNumeric))
+			isNumeric = EFalse;
+		}
+	return isNumeric;
+	}
+
+/* All the TransXxx.. functions translate arguments and their values and apply these 
+	to RichText Formats and Masks */
+
+
+void CParser::TranslateTagArgL()
+	{
+	switch (iTagType)
+		{
+		case EGlobal:
+			TransGlobalArgL();
+			break;
+		case EParagraph:
+			TransParagraphArgL(); 
+			break;
+		case ECharacter:
+			TransCharArg();
+			break;
+		case EControl:
+			TransControlArgL();
+			break;
+		case EError:
+			break;
+		}
+	iCancelArg = EFalse;  // reset
+	}
+
+
+void CParser::TransControlArgL()
+	{
+	if (iArgType != _L(""))
+		{
+		if (iArgType == _L("TAB"))
+			AddCharToParaL(KTabChar);	// TransTab();
+		else
+			iErrorLevel = EUnknownAttrib;
+		}
+	}
+
+
+void CParser::TransGlobalArgL()
+// Test for each possible arg in turn
+// (a switch statement cannot be used)
+	{
+	if (iArgType != _L("")) 				// Is there an argument?
+		{
+		if (iArgType == _L("KEEPTOGETHER"))	
+				TransParaKeepTogether();
+		else if (iArgType == _L("KEEPWITHNEXT"))
+				TransParaKeepWithNext();
+		else if (iArgType == _L("STARTNEWPAGE"))	
+				TransParaStartNewPage();
+		else if (iArgType == _L("WIDOWORPHAN"))	 	
+				TransParaWidowOrphan();
+
+		if (iArgType == _L("ITALIC"))	
+				TransCharPosture();
+		else if (iArgType == _L("BOLD"))	
+				TransCharStrokeWeight();
+		else if (iArgType == _L("UNDERLINE"))	
+				TransCharUnderline();
+		else if (iArgType == _L("STRIKETHROUGH"))
+				TransCharStrikethrough();
+
+		else if (!iArgValueExpected)			// No argument value supplied when one is required for the
+				iErrorLevel = ENoAttribValue;	// remaining options or an unknown argument supplied
+
+		else if (iArgType == _L("PARALANGUAGE")) 
+				OutputToScreen(_L("PARA LANGUAGE "));
+		else if (iArgType == _L("LEFTMARGIN")) 	 	   
+				TransParaArgLeftMargin();
+		else if (iArgType == _L("RIGHTMARGIN"))  	
+				TransParaArgRightMargin();
+		else if (iArgType == _L("INDENT"))		 
+				TransParaArgIndent();
+		else if (iArgType == _L("ALIGNMENT"))	 
+				TransParaArgAlignment();
+		else if (iArgType == _L("LINESPACING"))	 
+				TransParaLineSpacing();
+		else if (iArgType == _L("LINESPACINGCONTROL"))   
+				TransParaArgLineSpacingControl();
+		else if (iArgType == _L("SPACEBEFORE"))	 	
+				TransParaSpaceBefore();
+		else if (iArgType == _L("SPACEAFTER"))	 
+				TransParaSpaceAfter();
+		else if (iArgType == _L("BORDERMARGIN"))	
+				TransParaBorderMargin();
+		else if (iArgType == _L("TOPBORDER"))	 	
+				TransParaBorderL();
+		else if (iArgType == _L("BOTTOMBORDER"))	
+				TransParaBorderL();
+		else if (iArgType == _L("LEFT BORDER"))	 
+				TransParaBorderL();
+		else if (iArgType == _L("RIGHTBORDER"))	 
+				TransParaBorderL();
+		else if (iArgType == _L("BULLET"))		 
+				TransParaBullet();
+		else if (iArgType == _L("DEFAULTTABWIDTH"))
+				TransParaTabWidth();
+		else if (iArgType == _L("TABSTOP"))
+				TransParaTabStopL();
+
+		else if (iArgType == _L("FONTHEIGHT"))	
+				TransCharFontHeight();
+		else if (iArgType == _L("PRINTPOS"))	
+				TransCharPrintPos();
+		else if (iArgType == _L("TYPEFACENAME"))
+				TransCharTypefaceName();
+		else if (iArgType == _L("TYPEFACEFLAGS"))	
+				TransCharTypefaceFlags();
+		else if (iArgType == _L("COLOR"))	 	 
+				TransCharColor();
+		else if (iArgType == _L("LANGUAGE"))	
+				TransCharLanguage();
+		else 
+				iErrorLevel = EUnknownAttrib;
+		}
+	}
+
+
+void CParser::TransParagraphArgL()
+// Test for each possible arg in turn
+// (a switch statement cannot be used)
+	{
+	if (iArgType != _L("")) 				// Is there an argument?
+		{
+		if (iArgType == _L("DEFAULT"))		
+				TransParaDefault();
+		else if (iArgType == _L("KEEPTOGETHER"))
+				TransParaKeepTogether();
+		else if (iArgType == _L("KEEPWITHNEXT"))
+				TransParaKeepWithNext();
+		else if (iArgType == _L("STARTNEWPAGE"))
+				TransParaStartNewPage();
+		else if (iArgType == _L("WIDOWORPHAN"))	 
+				TransParaWidowOrphan();
+		else if (!iArgValueExpected)			// No argument value supplied when one is required for the
+				iErrorLevel = ENoAttribValue;	// remaining options or an unknown argument supplied
+		else if (iArgType == _L("PARALANGUAGE")) 
+				OutputToScreen(_L("PARA LANGUAGE "));
+		else if (iArgType == _L("LEFTMARGIN")) 				   
+				TransParaArgLeftMargin();
+		else if (iArgType == _L("RIGHTMARGIN"))  
+				TransParaArgRightMargin();
+		else if (iArgType == _L("INDENT"))		 
+				TransParaArgIndent();
+		else if (iArgType == _L("ALIGNMENT"))	 
+				TransParaArgAlignment();
+		else if (iArgType == _L("LINESPACING"))	 
+				TransParaLineSpacing();
+		else if (iArgType == _L("LINESPACINGCONTROL"))  
+				TransParaArgLineSpacingControl();
+		else if (iArgType == _L("SPACEBEFORE"))	 
+				TransParaSpaceBefore();
+		else if (iArgType == _L("SPACEAFTER"))	 
+				TransParaSpaceAfter();
+		else if (iArgType == _L("BORDERMARGIN"))	
+				TransParaBorderMargin();
+		else if (iArgType == _L("TOPBORDER"))	 
+				TransParaBorderL();
+		else if (iArgType == _L("BOTTOMBORDER"))
+				TransParaBorderL();
+		else if (iArgType == _L("LEFT BORDER"))	 
+				TransParaBorderL();
+		else if (iArgType == _L("RIGHTBORDER"))	 
+				TransParaBorderL();
+		else if (iArgType == _L("BULLET"))		 
+				TransParaBullet();
+		else if (iArgType == _L("DEFAULTTABWIDTH")) 
+				TransParaTabWidth();
+		else if (iArgType == _L("TABSTOP"))
+				TransParaTabStopL();
+		else 
+				iErrorLevel = EUnknownAttrib;
+		}
+	}
+
+
+void CParser::TransParaDefault()
+// turns off all applied para formatting - reverts to global
+	{
+	iParaFormatMask.ClearAll();
+	OutputToScreen(_L("<PARA-DEFAULT>"));
+	}
+
+
+void CParser::TransParaArgLeftMargin()
+	{
+	TInt32 margin = GetArgValue();
+	switch (iTagType)
+		{
+		case EParagraph:		 
+			iParaFormat->iLeftMarginInTwips = margin;
+			iParaFormatMask.SetAttrib(EAttLeftMargin);
+			break;
+		case EGlobal:
+			iGlobalParaFormat->iLeftMarginInTwips = margin;
+			iGlobalParaFormatMask.SetAttrib(EAttLeftMargin);
+			break;
+		}
+	// screen output
+	TBuf<80> outputBuf;
+	outputBuf.Format(_L("<LEFT MARGIN = %d>"),margin);
+	OutputToScreen(outputBuf);
+	}
+
+void CParser::TransParaArgRightMargin()
+	{
+	TInt32 margin = GetArgValue();		
+	switch (iTagType)
+		{
+		case EParagraph:		 
+			iParaFormat->iRightMarginInTwips = margin;
+			iParaFormatMask.SetAttrib(EAttRightMargin);
+			break;
+		case EGlobal:
+			iGlobalParaFormat->iRightMarginInTwips = margin;
+			iGlobalParaFormatMask.SetAttrib(EAttRightMargin);
+			break;
+		}
+	// screen output
+	TBuf<80> outputBuf;
+	outputBuf.Format(_L("<RIGHT MARGIN = %d>"),margin);
+	OutputToScreen(outputBuf);
+	}
+
+void CParser::TransParaArgIndent()
+	{
+	TInt32 indent = GetArgValue();
+	switch (iTagType)
+		{
+		case EParagraph:		 
+			iParaFormat->iIndentInTwips = indent;
+			iParaFormatMask.SetAttrib(EAttIndent);
+			break;
+		case EGlobal:
+			iGlobalParaFormat->iIndentInTwips = indent;
+			iGlobalParaFormatMask.SetAttrib(EAttIndent);
+			break;
+		}
+	// screen output
+	TBuf<80> outputBuf;
+	outputBuf.Format(_L("<INDENT = %d>"),indent);
+	OutputToScreen(outputBuf);
+	}
+
+void CParser::TransParaLineSpacing()
+	{
+	TInt32 lineSpacing = GetArgValue();		  
+	switch (iTagType)
+		{
+		case EParagraph:		 
+			iParaFormat->iLineSpacingInTwips = lineSpacing;
+			iParaFormatMask.SetAttrib(EAttLineSpacing);
+			break;
+		case EGlobal:
+			iGlobalParaFormat->iLineSpacingInTwips = lineSpacing;
+			iGlobalParaFormatMask.SetAttrib(EAttLineSpacing);
+			break;
+		}
+	// screen output
+	TBuf<80> outputBuf;
+	outputBuf.Format(_L("<LINESPACING = %d>"),lineSpacing);
+	OutputToScreen(outputBuf);
+	}
+
+void CParser::TransParaArgLineSpacingControl()
+	{
+	if (iArgValue == _L("ATLEAST"))
+		{
+		switch (iTagType)
+			{
+			case EParagraph:		 
+				iParaFormat->iLineSpacingControl = CParaFormat::ELineSpacingAtLeastInTwips;
+				iParaFormatMask.SetAttrib(EAttLineSpacingControl);
+				break;
+			case EGlobal:
+				iGlobalParaFormat->iLineSpacingControl = CParaFormat::ELineSpacingAtLeastInTwips;
+				iGlobalParaFormatMask.SetAttrib(EAttLineSpacingControl);
+				break;
+			}
+		OutputToScreen(_L("<Line spacing control Atleast>"));
+		}
+	else if (iArgValue == _L("EXACTLY"))
+		{
+		switch (iTagType)
+			{
+			case EParagraph:		 
+				iParaFormat->iLineSpacingControl = CParaFormat::ELineSpacingExactlyInTwips;
+				iParaFormatMask.SetAttrib(EAttLineSpacingControl);
+				break;
+			case EGlobal:
+				iGlobalParaFormat->iLineSpacingControl = CParaFormat::ELineSpacingExactlyInTwips;
+				iGlobalParaFormatMask.SetAttrib(EAttLineSpacingControl);
+				break;
+			}
+		OutputToScreen(_L("<Line spacing control Exactly>"));
+		}
+	else
+		iErrorLevel = EIllegalAttribValue;
+	}
+
+void CParser::TransParaSpaceBefore()
+	{
+	TInt32 spaceBefore = GetArgValue();		  
+	switch (iTagType)
+		{
+		case EParagraph:		 
+			iParaFormat->iSpaceBeforeInTwips = spaceBefore;
+			iParaFormatMask.SetAttrib(EAttSpaceBefore);
+			break;
+		case EGlobal:
+			iGlobalParaFormat->iSpaceBeforeInTwips = spaceBefore;
+			iGlobalParaFormatMask.SetAttrib(EAttSpaceBefore);
+			break;
+		}
+	// screen output
+	TBuf<80> outputBuf;
+	outputBuf.Format(_L("<SPACE BEFORE = %d>"),spaceBefore);
+	OutputToScreen(outputBuf);
+	}
+
+void CParser::TransParaSpaceAfter()
+	{
+	TInt32 spaceAfter = GetArgValue();		  
+	switch (iTagType)
+		{
+		case EParagraph:		 
+			iParaFormat->iSpaceAfterInTwips = spaceAfter;
+			iParaFormatMask.SetAttrib(EAttSpaceAfter);
+			break;
+		case EGlobal:
+			iGlobalParaFormat->iSpaceAfterInTwips = spaceAfter;
+			iGlobalParaFormatMask.SetAttrib(EAttSpaceAfter);
+			break;
+		}
+	// screen output
+	TBuf<80> outputBuf;
+	outputBuf.Format(_L("<SPACE AFTER = %d>"),spaceAfter);
+	OutputToScreen(outputBuf);
+	}
+
+void CParser::TransParaBorderMargin()
+	{
+	TInt32 borderMargin = GetArgValue();		  
+	switch (iTagType)
+		{
+		case EParagraph:		 
+			iParaFormat->iBorderMarginInTwips = borderMargin;
+			iParaFormatMask.SetAttrib(EAttBorderMargin);
+			break;
+		case EGlobal:
+			iGlobalParaFormat->iBorderMarginInTwips = borderMargin;
+			iGlobalParaFormatMask.SetAttrib(EAttBorderMargin);
+			break;
+		}
+	// screen output
+	TBuf<80> outputBuf;
+	outputBuf.Format(_L("<BORDER MARGIN = %d>"),borderMargin);
+	OutputToScreen(outputBuf);
+	}
+
+void CParser::TransParaKeepTogether()
+	{
+	switch (iTagType)
+		{
+		case EParagraph:		 
+			if (iCancelArg)
+				iParaFormat->iKeepTogether = EFalse;
+			else
+				iParaFormat->iKeepTogether = ETrue;
+			iParaFormatMask.SetAttrib(EAttKeepTogether);
+			break;
+		case EGlobal:
+			if (iCancelArg)
+				iGlobalParaFormat->iKeepTogether = EFalse;
+			else
+				iGlobalParaFormat->iKeepTogether = ETrue;
+			iGlobalParaFormatMask.SetAttrib(EAttKeepTogether);
+			break;
+		}
+	// screen output
+	OutputToScreen(_L("<KEEP TOGETHER>"));
+	}
+
+void CParser::TransParaKeepWithNext()
+	{
+	switch (iTagType)
+		{
+		case EParagraph:		 
+			if (iCancelArg)
+				iParaFormat->iKeepWithNext = EFalse;
+			else
+				iParaFormat->iKeepWithNext = ETrue;
+			iParaFormatMask.SetAttrib(EAttKeepWithNext);
+			break;
+		case EGlobal:
+			if (iCancelArg)
+				iGlobalParaFormat->iKeepWithNext = EFalse;
+			else
+				iGlobalParaFormat->iKeepWithNext = ETrue;
+			iGlobalParaFormatMask.SetAttrib(EAttKeepWithNext);
+			break;
+		}
+	// screen output
+	OutputToScreen(_L("<KEEP WITH NEXT>"));
+	}
+
+void CParser::TransParaStartNewPage()
+	{
+	switch (iTagType)
+		{
+		case EParagraph:		 
+			if (iCancelArg)
+				iParaFormat->iStartNewPage = EFalse;
+			else
+				iParaFormat->iStartNewPage = ETrue;
+			iParaFormatMask.SetAttrib(EAttStartNewPage);
+			break;
+		case EGlobal:
+			if (iCancelArg)
+				iGlobalParaFormat->iStartNewPage = EFalse;
+			else
+				iGlobalParaFormat->iStartNewPage = ETrue;
+			iGlobalParaFormatMask.SetAttrib(EAttStartNewPage);
+			break;
+		}
+	// screen output
+	OutputToScreen(_L("<START NEW PAGE>"));
+	}
+
+void CParser::TransParaWidowOrphan()
+	{
+	switch (iTagType)
+		{
+		case EParagraph:		 
+			if (iCancelArg)
+				iParaFormat->iWidowOrphan = EFalse;
+			else
+				iParaFormat->iWidowOrphan = ETrue;
+			iParaFormatMask.SetAttrib(EAttWidowOrphan);
+			break;
+		case EGlobal:
+			if (iCancelArg)
+				iGlobalParaFormat->iWidowOrphan = EFalse;
+			else
+				iGlobalParaFormat->iWidowOrphan = ETrue;
+			iGlobalParaFormatMask.SetAttrib(EAttWidowOrphan);
+			break;
+		}
+	// screen output
+	OutputToScreen(_L("<WIDOWS & ORPHANS>"));
+	}
+
+void CParser::TransParaArgAlignment()
+	{
+	// parse argValue
+	if (iArgValue == _L("LEFT"))
+		{
+		switch (iTagType)
+			{
+			case EParagraph:		 
+				iParaFormat->iHorizontalAlignment = CParaFormat::ELeftAlign;
+				iParaFormatMask.SetAttrib(EAttAlignment);
+				break;
+			case EGlobal:
+				iGlobalParaFormat->iHorizontalAlignment = CParaFormat::ELeftAlign;
+				iGlobalParaFormatMask.SetAttrib(EAttAlignment);
+				break;
+			}
+		OutputToScreen(_L("<ALIGNMENT LEFT>"));
+		}
+	else if (iArgValue == _L("RIGHT"))
+		{
+		switch (iTagType)
+			{
+			case EParagraph:		 
+				iParaFormat->iHorizontalAlignment = CParaFormat::ERightAlign;
+				iParaFormatMask.SetAttrib(EAttAlignment);
+				break;
+			case EGlobal:
+				iGlobalParaFormat->iHorizontalAlignment = CParaFormat::ERightAlign;
+				iGlobalParaFormatMask.SetAttrib(EAttAlignment);
+				break;
+			}
+		OutputToScreen(_L("<ALIGNMENT RIGHT>"));
+		}
+	else if (iArgValue == _L("CENTER"))
+		{
+		switch (iTagType)
+			{
+			case EParagraph:		 
+				iParaFormat->iHorizontalAlignment = CParaFormat::ECenterAlign;
+				iParaFormatMask.SetAttrib(EAttAlignment);
+				break;
+			case EGlobal:
+				iGlobalParaFormat->iHorizontalAlignment = CParaFormat::ECenterAlign;
+				iGlobalParaFormatMask.SetAttrib(EAttAlignment);
+				break;
+			}
+		OutputToScreen(_L("<ALIGNMENT CENTER>"));
+		}
+	else if (iArgValue == _L("JUSTIFIED"))
+		{
+		switch (iTagType)
+			{
+			case EParagraph:		 
+				iParaFormat->iHorizontalAlignment = CParaFormat::EJustifiedAlign;
+				iParaFormatMask.SetAttrib(EAttAlignment);
+				break;
+			case EGlobal:
+				iGlobalParaFormat->iHorizontalAlignment = CParaFormat::EJustifiedAlign;
+				iGlobalParaFormatMask.SetAttrib(EAttAlignment);
+				break;
+			}
+		OutputToScreen(_L("<ALIGNMENT JUSTIFIED>"));
+		}
+	else
+		iErrorLevel = EIllegalAttribValue;
+	}
+
+
+void CParser::TransParaBullet()
+	{
+	TInt characterCode = 0x2022;
+	TUint32 heightInTwips=0;
+	TUint32 flags=0;
+	TBuf<KMaxTypefaceNameLength> name;
+	TBuf<128> component;
+
+	// set first component (character code)
+	TInt commaPos = iArgValue.Locate(KComma);	 // find pos of first comma
+	component = iArgValue.Left(commaPos);
+	if (component != _L(""))					// only third arg remains
+		{
+		if (BufIsNumeric(component))
+			{
+			TLex tmpLex(component);
+			// TUint value;
+			tmpLex.Val(characterCode);
+			}
+		else 
+			iErrorLevel = EIllegalAttribValue;
+		}
+	else
+		iErrorLevel = EIllegalAttribValue;
+
+	// set second component (bullet height)
+	iArgValue.Delete(0,commaPos+1);				// delete previous component & trailing comma 
+	commaPos = iArgValue.Locate(KComma);	// find pos of first comma
+	component = iArgValue.Left(commaPos);
+	if (component != _L(""))					// only third arg remains
+		{
+		if (BufIsNumeric(component))
+			{
+			TLex tmpLex(component);
+			TUint value;
+			tmpLex.Val(value);
+			heightInTwips = value;
+			}
+		else 
+			iErrorLevel = EIllegalAttribValue;
+		}
+	else
+		iErrorLevel = EIllegalAttribValue;
+
+	// set third component (typeface flags)
+	iArgValue.Delete(0,commaPos+1);				// delete previous component & trailing comma 
+	commaPos = iArgValue.Locate(KComma);		// find pos of first comma
+	component = iArgValue.Left(commaPos);
+	if (component != _L(""))					// only third arg remains
+		{
+		flags = GetArgValue(component);
+		if (flags>2)
+			iErrorLevel=EIllegalAttribValue;	// only values 0,1,2 valid for flag
+		}
+	else
+		iErrorLevel = EIllegalAttribValue;
+
+	// set fourth component (typeface name)
+	iArgValue.Delete(0,commaPos+1);				// delete previous component & trailing comma 
+	if (iArgValue != _L(""))					// only third arg remains
+		{
+		name.Copy(iArgValue);		
+//		name = SquashBuf(iArgValue);
+		}
+	else
+		iErrorLevel = EIllegalAttribValue;
+
+	// apply
+	if (iErrorLevel == ENoError)
+		{
+		iBulletUsed = ETrue;
+		iBullet->iCharacterCode = (TText)characterCode;
+		iBullet->iHeightInTwips = heightInTwips;
+		if (flags>=1)
+			iBullet->iTypeface.SetIsProportional(ETrue);
+		if (flags>=3)
+			iBullet->iTypeface.SetIsSerif(ETrue);
+		iBullet->iTypeface.iName = name;
+		switch (iTagType)
+			{
+			case EParagraph:
+				iParaFormat->iBullet = iBullet;  
+				iParaFormatMask.SetAttrib(EAttBullet);
+				break;
+			case EGlobal:
+				iGlobalParaFormat->iBullet = iBullet;
+				iGlobalParaFormatMask.SetAttrib(EAttBullet);
+				break;
+			}
+		OutputToScreen(_L("<BULLET>"));
+		}
+	}
+
+TBuf8<512> CParser::SquashBuf(TDes aBuffer)
+	//
+	// Input 8/16 bit buffer to be returned as an 8-bit version
+	// Used for unicode compatability
+	//
+	{
+	TText16 textPointer;
+
+	TBuf8<512> returnBuf;
+
+	for ( TInt pos=0 ; pos<aBuffer.Length() ; pos++ )
+		{
+		textPointer = aBuffer[pos];
+#pragma warning ( disable : 4244 )
+		returnBuf[pos] = textPointer; // conversion from unsigned short to unsigned char (16 bit to 8 bit) in unicode
+#pragma warning ( default : 4244 )
+		}
+	return returnBuf;
+	}
+
+
+
+void CParser::TransParaBorderL()
+	{
+	TParaBorder::TLineStyle lineStyle=TParaBorder::ENullLineStyle;
+	TBool autoColor=EFalse;
+	TRgb color;
+	TBuf<128> component;
+
+	// set first component
+	TInt commaPos = iArgValue.Locate(KComma);	 // find pos of first comma
+	component = iArgValue.Left(commaPos);
+	if (component != _L(""))
+		{
+		if (component == _L("NULL"))
+			lineStyle = TParaBorder::ENullLineStyle;
+		else if (component == _L("SOLID"))
+			lineStyle = TParaBorder::ESolid;
+		else if (component == _L("DOUBLE"))
+			lineStyle = TParaBorder::EDouble;
+		else if (component == _L("DOTTED"))
+			lineStyle = TParaBorder::EDotted;
+		else if (component == _L("DASHED"))
+			lineStyle = TParaBorder::EDashed;
+		else if (component == _L("DOTDASH"))
+			lineStyle = TParaBorder::EDotDash;
+		else if (component == _L("DOTDOTDASH"))
+			lineStyle = TParaBorder::EDotDotDash;
+		else
+			iErrorLevel = EIllegalAttribValue; 
+		}
+	else
+		iErrorLevel = EIllegalAttribValue;
+	
+	// set second component
+	iArgValue.Delete(0,commaPos+1);				// delete first component & trailing comma 
+	commaPos = iArgValue.Locate(KComma);	 	// find pos of first comma
+	component = iArgValue.Left(commaPos);
+	if (component != _L(""))
+		{
+		if (component == _L("ON"))
+			autoColor = ETrue;
+		else if (component == _L("OFF"))
+			autoColor = EFalse;
+		else
+			iErrorLevel = EIllegalAttribValue; 
+		}
+	else
+		iErrorLevel = EIllegalAttribValue;
+
+	// set third component
+	iArgValue.Delete(0,commaPos+1);				// delete second component & trailing comma 
+	if (component != _L(""))					// only third arg remains
+		{
+		if (BufIsNumeric(iArgValue))
+			{
+			TLex tmpLex(iArgValue);
+			TUint value;
+			tmpLex.Val(value);
+			color=TRgb((TUint32)value);
+			}
+		else 
+			iErrorLevel = EIllegalAttribValue;
+		}
+
+	// apply
+	if (iErrorLevel == ENoError)
+		{
+		iBorderUsed = ETrue;
+		iBorder->iLineStyle = lineStyle;
+		iBorder->iAutoColor = autoColor;
+		iBorder->iColor = color;
+		if (iArgType == _L("TOPBORDER"))
+			{
+			switch (iTagType)
+				{
+				case EParagraph:
+					iParaFormat->SetParaBorderL(CParaFormat::EParaBorderTop,*iBorder);
+					iParaFormatMask.SetAttrib(EAttTopBorder);
+					break;
+				case EGlobal:
+					iGlobalParaFormat->SetParaBorderL(CParaFormat::EParaBorderTop,*iBorder);
+					iGlobalParaFormatMask.SetAttrib(EAttTopBorder);
+					break;
+				}
+			}
+		if (iArgType == _L("BOTTOMBORDER"))
+			{
+			switch (iTagType)
+				{
+				case EParagraph:
+					iParaFormat->SetParaBorderL(CParaFormat::EParaBorderBottom,*iBorder);
+					iParaFormatMask.SetAttrib(EAttBottomBorder);
+					break;
+				case EGlobal:
+					iGlobalParaFormat->SetParaBorderL(CParaFormat::EParaBorderBottom,*iBorder);
+					iGlobalParaFormatMask.SetAttrib(EAttBottomBorder);
+					break;
+				}
+			}
+		if (iArgType == _L("LEFTBORDER"))
+			{
+			switch (iTagType)
+				{
+				case EParagraph:
+					iParaFormat->SetParaBorderL(CParaFormat::EParaBorderLeft,*iBorder);
+					iParaFormatMask.SetAttrib(EAttLeftBorder);
+					break;
+				case EGlobal:
+					iGlobalParaFormat->SetParaBorderL(CParaFormat::EParaBorderLeft,*iBorder);
+					iGlobalParaFormatMask.SetAttrib(EAttLeftBorder);
+					break;
+				}
+			}
+		if (iArgType == _L("RIGHTBORDER"))
+			{
+			switch (iTagType)
+				{
+				case EParagraph:
+					iParaFormat->SetParaBorderL(CParaFormat::EParaBorderRight,*iBorder);
+					iParaFormatMask.SetAttrib(EAttRightBorder);
+					break;
+				case EGlobal:
+					iGlobalParaFormat->SetParaBorderL(CParaFormat::EParaBorderRight,*iBorder);
+					iGlobalParaFormatMask.SetAttrib(EAttRightBorder);
+					break;
+				}
+			}
+		OutputToScreen(_L("<PARA BORDER>"));
+		}
+	}
+
+void CParser::TransParaTabWidth()
+	{
+	TInt32 tabWidth = GetArgValue();
+	switch (iTagType)
+		{
+		case EParagraph:		 
+			iParaFormat->iDefaultTabWidthInTwips = tabWidth;
+			iParaFormatMask.SetAttrib(EAttDefaultTabWidth);
+			break;
+		case EGlobal:
+			iGlobalParaFormat->iDefaultTabWidthInTwips = tabWidth;
+			iGlobalParaFormatMask.SetAttrib(EAttDefaultTabWidth);
+			break;
+		}
+	// screen output
+	TBuf<80> outputBuf;
+	outputBuf.Format(_L("<DEFAULT TAB WIDTH = %d>"),tabWidth);
+	OutputToScreen(outputBuf);
+	}
+
+
+void CParser::TransParaTabStopL()
+// This arg has a compound value of the form Tabstop=value,type
+// It also accepts !Tabstop=value to delete an existing tabstop
+	{
+	TTabStop tabStop;
+	TBuf<128> component;
+	TBuf<6> outputBuf;
+
+	// get first component (tab type)
+	TInt commaPos = iArgValue.Locate(KComma);	 // find pos of first comma (returns -1 if no comma)
+	if (commaPos > 0)	// comma & first component exist
+		{
+		component = iArgValue.Left(commaPos);	// take part to the left of the comma
+		if (component != _L(""))				
+			tabStop.iTwipsPosition = GetArgValue(component);
+		else
+			iErrorLevel = EIllegalAttribValue;
+		}
+	else if ((iCancelArg)&&(commaPos == -1))	// no comma but only one component required (position)
+		{
+		if (iArgValue != _L(""))				
+			tabStop.iTwipsPosition = GetArgValue(iArgValue);
+		else
+			iErrorLevel = EIllegalAttribValue;
+		}
+
+	if (iErrorLevel == ENoError)
+		{
+		if (iCancelArg)
+			// insert a null tab
+			{
+			if ((iParaFormat->LocateTab(tabStop.iTwipsPosition) != KTabNotFound)
+				||(iGlobalParaFormat->LocateTab(tabStop.iTwipsPosition) != KTabNotFound))
+					{
+					tabStop.iType = TTabStop::ENullTab;	// null tab "deletes" existing tab
+					outputBuf = _L("<!TAB>");
+					}
+			else
+				iErrorLevel = EIllegalAttribValue;
+			}
+		else
+			{
+			// set second component (tab position in twips)
+			iArgValue.Delete(0,commaPos+1);				// delete previous component & trailing comma 
+			if (iArgValue != _L(""))				
+				{
+				outputBuf = _L("<TAB>");
+				if (iArgValue == _L("NULL"))
+					tabStop.iType = TTabStop::ENullTab;
+				else if (iArgValue == _L("LEFT"))
+					tabStop.iType = TTabStop::ELeftTab;
+				else if (iArgValue == _L("CENTERED"))
+					tabStop.iType = TTabStop::ECenteredTab;
+				else if (iArgValue == _L("RIGHT"))
+					tabStop.iType = TTabStop::ERightTab;
+				else 
+					iErrorLevel = EIllegalAttribValue;
+				}
+			else
+				iErrorLevel = EIllegalAttribValue;
+			}
+		}
+
+ 	// Insert the tab
+	if (iErrorLevel == ENoError)
+		{
+		switch (iTagType)
+			{
+			case EParagraph:
+				iParaFormat->StoreTabL(tabStop);
+				iParaFormatMask.SetAttrib(EAttTabStop);
+				break;
+			case EGlobal:
+				iGlobalParaFormat->StoreTabL(tabStop);
+				iGlobalParaFormatMask.SetAttrib(EAttTabStop);
+				break;
+			}
+		// output to screen
+		OutputToScreen(outputBuf);
+		}
+	}
+
+ 
+void CParser::TransCharArg()
+	{
+	if (iArgType != _L("")) 				// Is there an argument?
+		{
+		if (iArgType == _L("DEFAULT"))
+				TransCharDefault();
+		else if (iArgType == _L("ITALIC"))	
+				TransCharPosture();
+		else if (iArgType == _L("BOLD"))	
+				TransCharStrokeWeight();
+		else if (iArgType == _L("UNDERLINE"))	
+				TransCharUnderline();
+		else if (iArgType == _L("STRIKETHROUGH"))
+				TransCharStrikethrough();
+		else if (!iArgValueExpected)			// No argument value supplied when one is required for the
+				iErrorLevel = ENoAttribValue;	// remaining options or an unknown argument supplied
+		else if (iArgType == _L("FONTHEIGHT"))	
+				TransCharFontHeight();
+		else if (iArgType == _L("PRINTPOS"))	
+				TransCharPrintPos();
+		else if (iArgType == _L("TYPEFACENAME"))
+				TransCharTypefaceName();
+		else if (iArgType == _L("TYPEFACEFLAGS"))	
+				TransCharTypefaceFlags();
+		else if (iArgType == _L("COLOR"))	 	 
+				TransCharColor();
+		else if (iArgType == _L("LANGUAGE"))	
+				TransCharLanguage();
+		else 
+				iErrorLevel = EUnknownAttrib;
+		}
+	}
+
+
+void CParser::TransCharDefault()
+// turns off all applied Char formatting - reverts to global
+	{
+	iCharFormatMask.ClearAll();
+	OutputToScreen(_L("<CHAR-DEFAULT>"));
+	}
+
+
+void CParser::TransCharPosture()
+	{
+	switch (iTagType)
+		{
+		case ECharacter:		 
+			if (iCancelArg)
+				iCharFormat.iFontSpec.iFontStyle.SetPosture(EPostureUpright);
+			else
+				iCharFormat.iFontSpec.iFontStyle.SetPosture(EPostureItalic);
+			iCharFormatMask.SetAttrib(EAttFontPosture);
+			break;
+		case EGlobal:
+			if (iCancelArg)
+				iGlobalCharFormat.iFontSpec.iFontStyle.SetPosture(EPostureUpright);
+			else
+				iGlobalCharFormat.iFontSpec.iFontStyle.SetPosture(EPostureItalic);
+			iGlobalCharFormatMask.SetAttrib(EAttFontPosture);
+			break;
+		}
+	// screen output
+	OutputToScreen(_L("<ITALIC>"));
+	}
+
+
+void CParser::TransCharStrokeWeight()
+	{
+	switch (iTagType)
+		{
+		case ECharacter:		 
+			if (iCancelArg)
+				iCharFormat.iFontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightNormal);
+			else
+				iCharFormat.iFontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
+			iCharFormatMask.SetAttrib(EAttFontStrokeWeight);
+			break;
+		case EGlobal:
+			if (iCancelArg)
+				iGlobalCharFormat.iFontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightNormal);
+			else
+				iGlobalCharFormat.iFontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
+			iGlobalCharFormatMask.SetAttrib(EAttFontStrokeWeight);
+			break;
+		}
+	// screen output
+	OutputToScreen(_L("<BOLD>"));
+	}
+
+
+void CParser::TransCharUnderline()
+	{
+	switch (iTagType)
+		{
+		case ECharacter:		 
+			if (iCancelArg)
+				iCharFormat.iFontPresentation.iUnderline = EUnderlineOff;
+			else
+				iCharFormat.iFontPresentation.iUnderline = EUnderlineOn;
+			iCharFormatMask.SetAttrib(EAttFontUnderline);
+			break;
+		case EGlobal:
+			if (iCancelArg)
+				iGlobalCharFormat.iFontPresentation.iUnderline = EUnderlineOff;
+			else
+				iGlobalCharFormat.iFontPresentation.iUnderline = EUnderlineOn;
+			iGlobalCharFormatMask.SetAttrib(EAttFontUnderline);
+			break;
+		}
+	// screen output
+	OutputToScreen(_L("<UNDERLINE>"));
+	}
+
+
+void CParser::TransCharStrikethrough()
+	{
+	switch (iTagType)
+		{
+		case ECharacter:		 
+			if (iCancelArg)
+				iCharFormat.iFontPresentation.iStrikethrough = EStrikethroughOff;
+			else
+				iCharFormat.iFontPresentation.iStrikethrough = EStrikethroughOn;
+			iCharFormatMask.SetAttrib(EAttFontStrikethrough);
+			break;
+		case EGlobal:
+			if (iCancelArg)
+				iGlobalCharFormat.iFontPresentation.iStrikethrough = EStrikethroughOff;
+			else
+				iGlobalCharFormat.iFontPresentation.iStrikethrough = EStrikethroughOn;
+			iGlobalCharFormatMask.SetAttrib(EAttFontStrikethrough);
+			break;
+		}
+	// screen output
+	OutputToScreen(_L("<STRIKETHROUGH>"));
+	}
+
+
+void CParser::TransCharFontHeight()
+	{
+	TInt32 fontHeight = GetArgValue();		  
+	switch (iTagType)
+		{
+		case ECharacter:		 
+			iCharFormat.iFontSpec.iHeight = fontHeight;
+			iCharFormatMask.SetAttrib(EAttFontHeight);
+			break;
+		case EGlobal:
+			iGlobalCharFormat.iFontSpec.iHeight = fontHeight;
+			iGlobalCharFormatMask.SetAttrib(EAttFontHeight);
+			break;
+		}
+	// screen output
+	TBuf<80> outputBuf;
+	outputBuf.Format(_L("<FONTHEIGHT = %d>"),fontHeight);
+	OutputToScreen(outputBuf);
+	}
+
+void CParser::TransCharPrintPos()
+	{
+	if (iArgValue == _L("NORMAL"))
+		{
+		switch (iTagType)
+			{
+			case ECharacter:		 
+				iCharFormat.iFontSpec.iFontStyle.SetPrintPosition(EPrintPosNormal);
+				iCharFormatMask.SetAttrib(EAttFontPrintPos);
+				break;
+			case EGlobal:
+				iGlobalCharFormat.iFontSpec.iFontStyle.SetPrintPosition(EPrintPosNormal);
+				iGlobalCharFormatMask.SetAttrib(EAttFontPrintPos);
+				break;
+			}
+		OutputToScreen(_L("<PRINT POSITION NORMAL>"));
+		}
+	else if (iArgValue == _L("SUPERSCRIPT"))
+		{
+		switch (iTagType)
+			{
+			case ECharacter:		 
+				iCharFormat.iFontSpec.iFontStyle.SetPrintPosition(EPrintPosSuperscript);
+				iCharFormatMask.SetAttrib(EAttFontPrintPos);
+				break;
+			case EGlobal:
+				iGlobalCharFormat.iFontSpec.iFontStyle.SetPrintPosition(EPrintPosSuperscript);
+				iGlobalCharFormatMask.SetAttrib(EAttFontPrintPos);
+				break;
+			}
+		OutputToScreen(_L("<SUPERSCRIPT>"));
+		}
+	else if (iArgValue == _L("SUBSCRIPT"))
+		{
+		switch (iTagType)
+			{
+			case ECharacter:		 
+				iCharFormat.iFontSpec.iFontStyle.SetPrintPosition(EPrintPosSubscript);
+				iCharFormatMask.SetAttrib(EAttFontPrintPos);
+				break;
+			case EGlobal:
+				iGlobalCharFormat.iFontSpec.iFontStyle.SetPrintPosition(EPrintPosSubscript);
+				iGlobalCharFormatMask.SetAttrib(EAttFontPrintPos);
+				break;
+			}
+		OutputToScreen(_L("<SUBSCRIPT>"));
+		}
+	else
+		iErrorLevel = EIllegalAttribValue;
+	}
+
+
+void CParser::TransCharTypefaceFlags()
+	{
+	TUint flags = GetArgValue();
+	if (flags>2)
+		iErrorLevel=EIllegalAttribValue;	// only values 0,1,2 valid for flag
+	if (iErrorLevel==ENoError)
+		{
+		switch (iTagType)
+			{
+			case ECharacter:		 
+				if (flags>=1)
+					iCharFormat.iFontSpec.iTypeface.SetIsProportional(ETrue);
+				if (flags>=3)
+					iCharFormat.iFontSpec.iTypeface.SetIsSerif(ETrue);
+				iCharFormatMask.SetAttrib(EAttFontTypeface);
+				break;
+			case EGlobal:
+				if (flags>=1)
+					iGlobalCharFormat.iFontSpec.iTypeface.SetIsProportional(ETrue);
+				if (flags>=3)
+					iGlobalCharFormat.iFontSpec.iTypeface.SetIsSerif(ETrue);
+				iGlobalCharFormatMask.SetAttrib(EAttFontTypeface);
+				break;
+			}
+		// screen output
+		TBuf<80> outputBuf;
+		outputBuf.Format(_L("<TYPEFACE FLAGS = %d>"),flags);
+		OutputToScreen(outputBuf);
+		}
+	}
+
+
+void CParser::TransCharTypefaceName()
+	{
+	switch (iTagType)
+		{
+		case ECharacter:
+			iCharFormat.iFontSpec.iTypeface.iName=iArgValue;
+			iCharFormatMask.SetAttrib(EAttFontTypeface);
+			break;
+		case EGlobal:
+			iGlobalCharFormat.iFontSpec.iTypeface.iName=iArgValue;
+			iGlobalCharFormatMask.SetAttrib(EAttFontTypeface);
+			break;
+		}
+	// screen output
+	TBuf<80> outputBuf;
+	outputBuf.Format(_L("<TYPEFACE NAME = %S>"),&iArgValue);
+	OutputToScreen(outputBuf);
+	}
+
+
+void CParser::TransCharColor()
+	{
+	TUint value = GetArgValue();
+	if (iErrorLevel==ENoError)
+		{
+		TRgb color;
+		color=TRgb((TUint32)value);
+		switch (iTagType)
+			{
+			case ECharacter:		 
+				iCharFormat.iFontPresentation.iTextColor = color;
+				iCharFormatMask.SetAttrib(EAttColor);
+				break;
+			case EGlobal:
+				iGlobalCharFormat.iFontPresentation.iTextColor = color;
+				iGlobalCharFormatMask.SetAttrib(EAttColor);
+				break;
+			}
+		// screen output
+		TBuf<80> outputBuf;
+		outputBuf.Format(_L("<COLOR = %d>"),value);
+		OutputToScreen(outputBuf);
+		}
+	}
+
+
+void CParser::TransCharLanguage()
+// Assumes languages are integer coded - will have to change in time
+	{
+	TUint value = GetArgValue();
+	if (iErrorLevel==ENoError)
+		{
+		switch (iTagType)
+			{
+			case ECharacter:		 
+				iCharFormat.iLanguage = value;
+				iCharFormatMask.SetAttrib(EAttCharLanguage);
+				break;
+			case EGlobal:
+				iGlobalCharFormat.iLanguage = value;
+				iGlobalCharFormatMask.SetAttrib(EAttCharLanguage);
+				break;
+			}
+		// screen output
+		TBuf<80> outputBuf;
+		outputBuf.Format(_L("<LANGUAGE = %d>"),value);
+		OutputToScreen(outputBuf);
+		}
+	}
+
+
+
+////////////////////////////////
+// CFileApp
+////////////////////////////////
+
+
+CFileApp* CFileApp::NewL()
+	{
+	CFileApp* self=new(ELeave) CFileApp;
+	CleanupStack::PushL(self);
+	self->ConstructApplicationL();
+	CleanupStack::Pop();
+	return self;
+	}
+
+
+CFileApp::CFileApp()
+	{
+	// init variables
+	iConsoleExists = EFalse;
+	iFilePos = 0;
+	}
+	 
+
+void CFileApp::ConstructApplicationL()
+	{
+	iTextBuf = CBufSeg::NewL(64);  // Granularity of 64 bytes
+	}
+
+
+CFileApp::~CFileApp()
+	{
+	delete iTextBuf;
+	}
+
+
+CBufSeg* CFileApp::LoadFileL(CConsoleBase* aConsoleWin)
+// Asks for file name, then loads file into text buffer.
+	{ 
+	iConsoleExists = ETrue;
+	iConsole = aConsoleWin;			// grab console handle
+	GetFileName();
+	FileHandlingL();					// load file & store it
+	return iTextBuf;
+	}
+
+CBufSeg* CFileApp::LoadFileL(const TFileName &aFileName)
+// uses supplied FileName to load file into CBufSeg
+	{ 
+	iFileName = aFileName;
+	FileHandlingL();					// load file & store it
+	return iTextBuf;
+	}
+
+
+void CFileApp::OutputToScreen(const TDesC& aMessageBuffer)
+	{
+	if (iConsoleExists)
+		iConsole->Write(aMessageBuffer);  // output line to screen
+	}
+
+
+TInt CFileApp::SaveFile(CBufSeg* aTextBuf, TFileName aFileName)
+// saves supplied buffer to disc, making the new filename a varient of the PML source filename supplied
+	{
+	// set filename to be saved as
+	TInt length = aFileName.Length();
+	aFileName.Delete(length-1,1);
+	aFileName.Append(_L("G")); // generated filenames end in G
+
+	// create fileserver client and save.
+	RFs fsClient;
+	RFile theFile;
+	TInt err = fsClient.Connect();
+	if (err == 0)
+		err = theFile.Replace(fsClient, aFileName, EFileStream|EFileRead|EFileWrite);
+	if (err == 0)
+		{
+		TInt readWritePos = 0;
+		TBuf8<80> insertBuf;
+		TInt readLength=0;
+		FOREVER
+			{
+			// read from TextBuf into insertBuf
+			readLength=Min(aTextBuf->Size()-readWritePos,insertBuf.MaxLength());
+			insertBuf.SetLength(0); 				// empty buffer
+			aTextBuf->Read(readWritePos,insertBuf,readLength);
+			// insert buf into file
+			theFile.Write(readWritePos, insertBuf);
+			readWritePos += insertBuf.Length();
+			if (readWritePos >= aTextBuf->Size())
+				break;
+			}
+	  	theFile.Close();
+		}
+	return err;
+	}
+
+void CFileApp::GetFileName()
+// read FileName synchronously from console
+	{ 
+	TKeyCode keystroke = EKeyNull;
+	iFileName.SetLength(0);
+
+	//Debuging cheat to hardwire filename
+	//iFileName=_L("d:\\etext\\incp\\dunk.pml");
+	//return;
+
+	OutputToScreen(_L("Enter file to be parsed: "));
+	keystroke = iConsole->Getch();
+	while (keystroke != EKeyEnter)
+		{
+		TBuf<1> uniBuf; // used to ease unicode build
+		uniBuf.Append(keystroke);
+
+		iConsole->Write(uniBuf);
+		iFileName.Append(uniBuf);
+		keystroke = iConsole->Getch();
+		}
+	WriteNewLine();
+	}
+
+void CFileApp::FileHandlingL()
+// Open a file, read contents into buffer, then close file again
+	{
+	// open file
+    RFile textFile;
+	RFs fsClient;
+	TInt err = 1;
+	while (err)
+		{
+		err = fsClient.Connect();
+		if (!err)
+    		err = textFile.Open(fsClient,iFileName,EFileStream|EFileRead|EFileShareReadersOnly);
+    	if (err)
+			return;
+/******GA
+			{
+    		OutputToScreen(_L("Error in file open\n\n"));
+    		GetFileName();
+    		}
+******/
+    	}   	
+    
+	OutputToScreen(_L("Parsing "));
+	OutputToScreen(iFileName);
+	WriteNewLine();
+	WriteNewLine();
+
+	// Read file into segmented buffer
+	TUint insertPos = 0;
+
+	TInt max = sizeof(TText) * KFileBufSize;
+
+	FOREVER
+		{
+		iFileBuf.SetLength(0);
+		ReadChunkOfFileContents(textFile);
+		iTextBuf->/*Do*/InsertL(insertPos,iFileBuf.Ptr(),iFileBuf.Size());
+		insertPos += iFileBuf.Size();			// in bytes
+		if (iFileBuf.Size() < max)
+			break;
+		}
+
+	// finish up
+ 	textFile.Close();
+	iFilePos = 0; // reset
+	}
+
+void CFileApp::ReadChunkOfFileContents(RFile &aFile)
+    {
+	TBuf8<KFileBufSize> readBuf;
+	aFile.Read(iFilePos,readBuf);
+	// read into iFileBuf (8/16 bit); 
+	TText textPointer;
+	for ( TInt pos=0 ; pos<readBuf.Length() ; pos++ )
+		{
+		textPointer = readBuf[pos];
+		iFileBuf.Append(textPointer);
+		}
+    //TInt ret=aFile.Read(iFilePos,iFileBuf);
+	iFilePos += KFileBufSize;
+    }
+
+void CFileApp::WriteNewLine()
+//
+	{
+	TBuf<1> buf(_L("\n"));
+	OutputToScreen(buf);
+	}
+