filehandling/fileconverterfw/SRC/TXCONV.CPP
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 19 Feb 2010 22:58:54 +0200
branchRCL_3
changeset 4 0fdb7f6b0309
parent 0 2e3d3ce01487
permissions -rw-r--r--
Revision: 201002 Kit: 201007

// 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 <conarc.h>
#include <s32file.h>
#include <e32std.h>
#include <e32uid.h>

#include "TXCONV.H"

//
// class CEtToTxtCnv
// 

CEtToTxtCnv::~CEtToTxtCnv()
	{
	delete iTextTranFromEra;
	}

void CEtToTxtCnv::ConvertObjectAL(RReadStream& aReadStream, RWriteStream& aWriteStream,MConverterUiObserver* /*aObserver*/)
	{
	iReadStream = &aReadStream;
	iPos=0;
	iLength=aReadStream.Source()->SizeL();
	delete iTextTranFromEra;
	iTextTranFromEra=NULL;
	iTextTranFromEra=TTextTranFromEra::NewL(CPlainText::EOrganiseByParagraph, aWriteStream,0);
	}

const TInt KBufSize=256;

TBool CEtToTxtCnv::DoConvertL()
	{
	__ASSERT_DEBUG(iTextTranFromEra, User::Invariant());
	TBuf<KBufSize> buf;
	TInt read = Min(iLength - iPos, KBufSize);
#if defined _UNICODE
	TBuf8<KBufSize> buf8;
	iReadStream->ReadL(buf8, read);
	for(TInt i = 0; i < (buf8.Size() - 1); i += 2)
		{
		buf.Append(buf8[i] | (buf8[i + 1] << 8));
		}
#else
	iReadStream->ReadL(buf,read);
#endif
	iPos += read;
	iTextTranFromEra->Initialise(buf);
	return iTextTranFromEra->DoTranslateL();
	}


TUid CEtToTxtCnv::Uid()
	{
	return KUidEtextToText;
	}

TInt CEtToTxtCnv::Capabilities()
	{
	return EConvertsObjects;
	}

CEtToTxtCnv::CEtToTxtCnv()
	{}

//
// class CTxtToEtCnv
// 

CTxtToEtCnv::~CTxtToEtCnv()
	{
	delete iTextTranToEra;
	}

void CTxtToEtCnv::ConvertObjectAL(RReadStream& aReadStream, RWriteStream& aWriteStream, MConverterUiObserver* /*aObserver*/)
	{
	iReadStream = &aReadStream;
	iWriteStream = &aWriteStream;
	iLength=iReadStream->Source()->SizeL();
	iPos=0;
	delete iTextTranToEra;
	iTextTranToEra=NULL;
	iTextTranToEra=new(ELeave) TTextTranToEra(CPlainText::EOrganiseByParagraph, iNoTrim);
	}

TBool CTxtToEtCnv::DoConvertL()
	{
	__ASSERT_DEBUG(iTextTranToEra, User::Invariant());
	TBuf<KBufSize> buf;
	TInt read = Min(iLength - iPos, KBufSize);
#if defined _UNICODE
	TBuf8<KBufSize> buf8;
	iReadStream->ReadL(buf8, read);
	TInt i = 0;
	for(; i < (buf8.Size() - 1); i += 2)
		{
		buf.Append(buf8[i] | (buf8[i + 1] << 8));
		}
#else
	iReadStream->ReadL(buf, read);
#endif
	iPos += read;
	iTextTranToEra->Translate(buf);
#if defined _UNICODE
	buf8.Zero();
	for (i = 0; i < buf.Length(); i++)
		{
		buf8.Append(buf[i] & 0x00FF);
		buf8.Append((buf[i] >> 8) & 0x00FF);
		}
	iWriteStream->WriteL(buf8);	
#else
	iWriteStream->WriteL(buf);
#endif
	if (iPos < iLength)
		return ETrue; // more to do
	return EFalse;
	}

TUid CTxtToEtCnv::Uid()
	{
	return KUidTextToEtext;
	}

TInt CTxtToEtCnv::Capabilities()
	{
	return EConvertsObjects;
	}

CTxtToEtCnv::CTxtToEtCnv()
	{}
CTxtToEtCnv::CTxtToEtCnv(TBool aNoTrim) : iNoTrim(aNoTrim)
	{}

TTextTran::TTextTran(CPlainText::TTextOrganisation aTextOrganisation)
// C'tor
//
	: iTransMode(aTextOrganisation)
	{}


void TTextTran::SetTranslationMode(CPlainText::TTextOrganisation aTextOrganisation)
//
	{iTransMode=aTextOrganisation;}


CPlainText::TTextOrganisation TTextTran::TranslationMode()const
//
	{return iTransMode;}
	

TTextTranToEra::TTextTranToEra(CPlainText::TTextOrganisation aTextOrganisation, TBool aNoTrim)
// C'tor
//
	: TTextTran(aTextOrganisation)
	{
	iNoTrim=aNoTrim;
	}


void TTextTranToEra::Translate(TDes& aBuf)
// Scans the passed buffer, replacing line delimiters with paragraph delimiters
// based on the translation mode that has been set. (Paragraph or line).
// Control characters in the source, that have meaning to ERA text are translated
// into 'blobs'.
// The descriptor aBuf will never be enlarged, only made smaller!
//
// Unicode specifies discontinuous control code regions.!!!
	{

	iReadPtr=CONST_CAST(TText*,aBuf.Ptr());
	iWritePtr=CONST_CAST(TText*,iReadPtr);
	const TText* basePtr=iReadPtr;
	const TInt length=aBuf.Length();
	while (iReadPtr<basePtr+length)
		{
//		__ASSERT_DEBUG(iReadPtr>=iWritePtr,Panic(EDebug));
		if (*iReadPtr<0x20)
			MapControlCode();  // This is a control character
		else
			{
			*iWritePtr=*iReadPtr;
			iWritePtr++;
			}
		iReadPtr++;
		}
	aBuf.SetLength(iWritePtr-basePtr);
	}


void TTextTranToEra::MapControlCode()
// Translate any control codes encountered into something more reasonable.
// CR's are ignored completely, only LF's influence where paragraph delimiters occur.
//
	{
	switch (*iReadPtr)
		{
		case 0x0c:  // FF
			*iWritePtr=CEditableText::EPageBreak;
			break;
		case 0x09:  // CEditableText::ETabCharacter
			*iWritePtr=*iReadPtr;
			break;  // No translation required
		case 0x0d:  // CR - ignore this character.
			iWritePtr--;  // cos its incremented again outside the switch.
			break;
		case 0x0a:  // LF
			{
			if (iTransMode==CPlainText::EOrganiseByParagraph)
				{
				if(!iNoTrim)
					{
					Trim();  // trims trailng white space preceeding this line delimter.
					}
				*iWritePtr=CEditableText::EParagraphDelimiter;  // all line delimiters become paragraph delimiters
				}
			else
				{// only consecutive line delimiters become paragraph delimiters
				if (*(iReadPtr+1)==0x0a || (*(iReadPtr+1)==0x0d && *(iReadPtr+2)==0x0a))
					{
					Trim();  // trims trailng white space preceeding this line delimter.
					*iWritePtr=CEditableText::EParagraphDelimiter;  // Insert paragraph
					iReadPtr+=(*(iReadPtr+1)==0x0a) ? 1 : 2; // consume this delimiter set.
					}
				else
					*iWritePtr=0x20;  // replace with white space.
				}
			break;
			}
		default:
			// CEditableText::EParagraphDelimiter
			// CEditableText::ELineBreak
			// CEditableText::EPageBreak
			// CEditableText::ENonBreakingTab
			// CEditableText::ENonBreakingHyphen
			// CEditableText::EPotentialHyphen
			// CEditableText::ENonBreakingSpace
			// CEditableText::EPictureCharacter
			*iWritePtr=*iReadPtr;
			break;
		}
	iWritePtr++;
	}


void TTextTranToEra::Trim()
// Removes white space that has already been written before the line delimiter was encountered.
//
	{
	while (*(iWritePtr-1)==0x20)
		iWritePtr--;
	}


TTextTranFromEra* TTextTranFromEra::NewL(CPlainText::TTextOrganisation aTextOrganisation,RWriteStream& aOutStream,TInt aLineWrap)
// Create & initialise a new instance of this class.
//
	{
	TTextTranFromEra* self=new(ELeave) TTextTranFromEra(aTextOrganisation,aOutStream,aLineWrap);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop();
	return self;
	}


TTextTranFromEra::TTextTranFromEra(CPlainText::TTextOrganisation aTextOrganisation,RWriteStream& aOutStream,TInt aLineWrap)
// C'tor
//
	: TTextTran(aTextOrganisation),iOutStream(aOutStream),iLineWrap(aLineWrap)

	{
	ResetExportBuffer();
	if (aTextOrganisation==CPlainText::EOrganiseByParagraph)
		iLineWrap=KMaxTInt;
	}


void TTextTranFromEra::ConstructL()
// Initialise this object.
//
	{}


TInt TTextTranFromEra::DoTranslateL()
// Scans the passed buffer, replacing paragraph delimiters with line delimiters (CR/LF)
// based on the translation mode that has been set. (Paragraph or line).
// Special characters in the source, that have meaning to ERA text are translated.
//
	{
	if(iReadPtr<iSBase+iSLen)
		{
		while (iReadPtr<(iSBase+iSLen))
			{
			DoTranslateSourceBufferL();  // returns when export buffer is full or aBuf is empty
			CommitExportBufferToFileL();  // export buffer full
			}
		return ETrue;
		}
	CommitExportBufferToFileL();
	return EFalse;
	}


void TTextTranFromEra::NotifyEndOfSourceL()
// Flush the export buffer.
//
	{CommitExportBufferToFileL();}
	

void TTextTranFromEra::Initialise(const TDesC& aBuf)
//
	{
	iReadPtr=CONST_CAST(TText*,aBuf.Ptr());
	iSBase=iReadPtr;
	iSLen=aBuf.Length();
	}


void TTextTranFromEra::ResetExportBuffer()
//
	{
	iWritePtr=CONST_CAST(TText*,iExportBuffer.Ptr());
	iTBase=iWritePtr;
	}

void TTextTranFromEra::CommitExportBufferToFileL()
//
	{
	iExportBuffer.SetLength(iWritePtr - iTBase);
#if !defined(_UNICODE)
	iOutStream.WriteL(iExportBuffer);
#else // Write wide descriptor to file as byte stream
	TBuf8<KMaxExportBuffer> narrowBuffer;
	TInt i = 0;
	for (; i < (iExportBuffer.Length() / 2); i++)
		{
		narrowBuffer.Append(iExportBuffer[i] & 0x00FF);
		narrowBuffer.Append((iExportBuffer[i] >> 8) & 0x00FF);
		}
	iOutStream.WriteL(narrowBuffer);
	narrowBuffer.Zero();
	for (i = (iExportBuffer.Length() / 2); i < iExportBuffer.Length(); i++)
		{
		narrowBuffer.Append(iExportBuffer[i] & 0x00FF);
		narrowBuffer.Append((iExportBuffer[i] >> 8) & 0x00FF);
		}
	iOutStream.WriteL(narrowBuffer);
#endif
	iExportBuffer.SetLength(0);
	iWritePtr = iTBase;  // Reset the write pointer - fundamental !!!!
	}


void TTextTranFromEra::DoTranslateSourceBufferL()
// Translate the source buffer, writing to the export buffer.
// Returns when either the source has been consumed or the export buffer is full
//
	{
	while (iReadPtr<iSBase+iSLen && iWritePtr<iTBase+KMaxExportBuffer-2*KLineDelimiterLength)
		{
		if ((*iReadPtr<0x20) || (*iReadPtr==CEditableText::EParagraphDelimiter))
			MapEraCodeL();  // May fill export buffer
		else
			{
			*iWritePtr=*iReadPtr;
			iWritePtr++;
			}
		if (iLineWrap!=KMaxTInt && iWritePtr>=iTBase+iLineWrap)
			{
			TText* ptr=iWritePtr;
			TText* end=iWritePtr;
			TText chr(0);
			while ((*(--ptr))!=' ' && ptr>iTBase)		//Allow for more general breaking character
				{}
			if (*ptr!=' ')
				{
				WriteCRLF(KLineDelimiterLength);
				ptr=end;		//So the while below is not executed
				}
			else
				{
				*ptr++=KCharacterCR;
				chr=*ptr;
				*ptr++=KCharacterLF;
				iWritePtr=ptr;
				}
			CommitExportBufferToFileL();
			if (ptr<=end)
				{
				*(iWritePtr++)=chr;
				while (ptr<end)
					{
					*(iWritePtr++)=*(ptr++);
					}
				}
			}
		iReadPtr++;
		}
	}
	

void TTextTranFromEra::MapEraCodeL()
//
	{
	switch (*iReadPtr)
		{
		case CEditableText::EPictureCharacter:
		case CEditableText::ELineBreak:
		case CEditableText::EPageBreak:
		case CEditableText::EPotentialHyphen:
			return;  // These characters are not emitted.
		case CEditableText::ETabCharacter:
			*iWritePtr=KCharacterTab;
			break;
		case CEditableText::ENonBreakingHyphen:
			*iWritePtr=KCharacterHyphen;
			break;
		case CEditableText::ENonBreakingSpace:
			*iWritePtr=KCharacterSpace;
			break;
		case CEditableText::EParagraphDelimiter:
			{
			TInt charsToWrite=KLineDelimiterLength;
			if (iTransMode==CPlainText::EOrganiseByLine)
				charsToWrite=2*KLineDelimiterLength;
			WriteCRLF(charsToWrite);
			if (iTransMode==CPlainText::EOrganiseByLine)
				CommitExportBufferToFileL();  // export buffer
			return;
			}
		default:
			*iWritePtr=*iReadPtr;
			break;
		}
	iWritePtr++;
	}


void TTextTranFromEra::WriteCRLF(TInt aNumCharacters)
//
	{
	while (aNumCharacters>0)
		{
		if (aNumCharacters%2==1)
			*iWritePtr=KCharacterLF;
		else
			*iWritePtr=KCharacterCR;
		aNumCharacters--;
		iWritePtr++;
		}
	}