libraries/iosrv/client/pod_formatter.cpp
author Tom Sutcliffe <thomas.sutcliffe@accenture.com>
Sat, 31 Jul 2010 19:07:57 +0100
changeset 23 092bcc217d9d
parent 0 7f656887cf89
permissions -rw-r--r--
Tidied iocli exports, build macro tweaks. Removed 4 overloads of CCommandBase::RunCommand[L] that are no longer used at all, and changed one more to not be exported as it's only used internally to iocli.dll. fixed builds on platforms that don't support btrace or any form of tracing.

// pod_formatter.cpp
// 
// Copyright (c) 2009 - 2010 Accenture. All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the "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:
// Accenture - Initial contribution
//

#include "pod_formatter.h"

const TInt KGap = 2;

_LIT(KPartialCommandStart, "\r\n=");
_LIT(KCommandStart, "\r\n\r\n=");
_LIT(KBlankLine, "\r\n\r\n");
_LIT(KNewLine, "\r\n");

using namespace IoUtils;


TPodFormatter::TPodFormatter(CTextFormatter& aFormatter)
	: iFormatter(aFormatter)
	{
	}

void TPodFormatter::FormatL(const TDesC& aPod)
	{
	iPodLex = aPod;
	while (!iPodLex.Eos())
		{
		TPtrC command(NextCommand());
		if (command == _L("pod"))
			{
			SkipToNextBlankLine();
			}
		else if ((command == _L("head1")) || (command == _L("head2")))
			{
			iPodLex.SkipSpaceAndMark();
			SkipToLineEnd();
			iFormatter.SetAttributesL(ConsoleAttributes::EBold | ConsoleAttributes::EUnderscore);
			iFormatter.WrapL(0, iPodLex.MarkedToken());
			iFormatter.SetAttributesL(ConsoleAttributes::ENone);
			iFormatter.AppendL(KBlankLine);
			}
		else if (command == _L("cut"))
			{
			SkipToNextBlankLine();
			break;
			}
		else if (command == _L("begin"))
			{
			TPtrC nextCommand;
			do
				{
				nextCommand.Set(NextCommand());
				}
				while ((nextCommand.Length() > 0) && (nextCommand != _L("end")));

			SkipToNextBlankLine();
			}
		else if (command == _L("for"))
			{
			SkipToNextBlankLine();
			}
		else if (command == _L("over"))
			{
			iPodLex.SkipSpace();
			TUint indent;
			User::LeaveIfError(iPodLex.Val(indent));
			OverL(indent);
			}

		FormatToNextCommandL();
		}
	}

void TPodFormatter::OverL(TInt aIndent)
	{
	CTextBuffer* buffer = CTextBuffer::NewLC(0x100);

	while (!iPodLex.Eos())
		{
		FormatToNextCommandL(aIndent);

		TPtrC command(NextCommand());
		if (command == _L("item"))
			{
			iPodLex.SkipSpaceAndMark();
			SkipToLineEnd();
			buffer->AppendL(iPodLex.MarkedToken());
			iPodLex.SkipSpace();
			//buffer->AppendL('\t');
			//buffer->AppendL(TextToNextCommand());
			// Need to split the text up putting a tab in front of every paragraph of text, in case the item description is multi-paragraph.
			// If we don't, the next paragraph will end up in column one which will break the column formatter.
			// If there's a neater way of doing this, someone feel free! -TomS
			TPtrC text(TextToNextCommand());
			while(text.Length())
				{
				TInt nextNewLine = text.Find(KNewLine);
				if (nextNewLine == KErrNotFound) nextNewLine = text.Length();
				TPtrC line(text.Left(nextNewLine+KNewLine().Length()));
				buffer->AppendL('\t');
				buffer->AppendL(line);
				text.Set(text.Mid(line.Length()));
				}
			buffer->AppendL(KNewLine);
			}
		else if (command == _L("back"))
			{
			break;
			}
		else if (command == _L("over"))
			{
			if (buffer->Descriptor().Length() > 0)
				{
				iFormatter.TabulateL(aIndent, KGap, buffer->Descriptor(), EWrapLastColumn);
				iFormatter.AppendL(KNewLine);
				buffer->Zero();
				}
			iPodLex.SkipSpace();
			TUint indent;
			User::LeaveIfError(iPodLex.Val(indent));
			OverL(indent + aIndent);
			}
		}

	if (buffer->Descriptor().Length() > 0)
		{
		iFormatter.TabulateL(aIndent, KGap, buffer->Descriptor(), EWrapLastColumn);
		iFormatter.AppendL(KNewLine);
		}

	CleanupStack::PopAndDestroy(buffer);
	}

void TPodFormatter::FormatToNextCommandL(TInt aIndent)
	{
	FOREVER
		{
		TPtrC paragraph(NextParagraph());
		if (paragraph.Length() > 0)
			{
			if (TChar(paragraph[0]).IsSpace())
				{
				iFormatter.AppendL(paragraph);
				}
			else
				{
				iFormatter.WrapL(aIndent, paragraph);
				}
			iFormatter.AppendL(KNewLine);
			}
		else
			{
			break;
			}
		}
	}

TPtrC TPodFormatter::NextCommand()
	{
	TPtrC command;
	if (SkipToNextCommand() == KErrNone)
		{
		iPodLex.Mark();
		iPodLex.SkipCharacters();
		command.Set(iPodLex.MarkedToken());
		}
	return command;
	}

TPtrC TPodFormatter::NextParagraph()
	{
	// Consume leading new line characters.
	while (iPodLex.Remainder().Find(KNewLine) == 0)
		{
		if (AtCommandStart())
			{
			return TPtrC();
			}
		iPodLex.Inc(KNewLine().Length());
		}
	
	iPodLex.Mark();

	if (iPodLex.Peek().IsSpace())
		{
		// This line has leading white space - treat everything up to the next blank line as a single paragraph.
		if (SkipToNextBlankLine() != KErrNone)
			{
			SkipToLineEnd();
			}
		}
	else if (SkipToNextLine() != KErrNone)
		{
		SkipToLineEnd();
		}

	return iPodLex.MarkedToken();
	}

TPtrC TPodFormatter::TextToNextCommand()
	{
	TInt initialOffset = iPodLex.Offset();
	iPodLex.Mark();

	if (SkipToNextCommand() == KErrNone)
		{
		if (iPodLex.Offset() >= KCommandStart().Length())
			{
			iPodLex.Inc(-(KCommandStart().Length()));
			}
		else
			{
			iPodLex.Inc(-(iPodLex.Remainder().Length()));
			}
		}
	else
		{
		iPodLex.Inc(iPodLex.Remainder().Length());
		}

	if (initialOffset < iPodLex.Offset())
		{
		return iPodLex.MarkedToken();
		}
	else
		{
		return TPtrC(NULL, 0);
		}
	}

void TPodFormatter::SkipToLineEnd()
	{
	if (SkipTo(KNewLine) != KErrNone)
		{
		iPodLex.Inc(iPodLex.Remainder().Length());
		}
	}

TInt TPodFormatter::SkipToNextLine()
	{
	TInt ret = SkipTo(KNewLine);
	if (ret == KErrNone)
		{
		iPodLex.Inc(KNewLine().Length());
		}
	return ret;
	}

TInt TPodFormatter::SkipToNextCommand()
	{
	if (iPodLex.Remainder().Find(KPartialCommandStart) == 0)
		{
		if (iPodLex.Offset() == 0)
			{
			iPodLex.Inc(KPartialCommandStart().Length());
			return KErrNone;
			}
		else
			{
			iPodLex.Inc(-2);
			if (iPodLex.Remainder().Find(KCommandStart) == 0)
				{
				iPodLex.Inc(KCommandStart().Length());
				return KErrNone;
				}
			else
				{
				iPodLex.Inc(2);
				}
			}
		}

	TInt ret = SkipTo(KCommandStart);
	if (ret == KErrNone)
		{
		iPodLex.Inc(KCommandStart().Length());
		}
	return ret;
	}

TInt TPodFormatter::SkipToNextBlankLine()
	{
	TInt ret = SkipTo(KBlankLine);
	if (ret == KErrNone)
		{
		iPodLex.Inc(2);
		}
	return ret;
	}

TInt TPodFormatter::SkipTo(const TDesC& aDes)
	{
	TInt ret = iPodLex.Remainder().Find(aDes);
	if (ret >= 0)
		{
		iPodLex.Inc(ret);
		return KErrNone;
		}
	return KErrNotFound;
	}

TBool TPodFormatter::AtCommandStart()
	{
	return ((iPodLex.Remainder().Find(KCommandStart) == 0) || (iPodLex.Remainder().Find(KPartialCommandStart) == 0));
	}