textrendering/word/SRC/WPDOC.CPP
changeset 0 1fb32624e06b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/textrendering/word/SRC/WPDOC.CPP	Tue Feb 02 02:02:46 2010 +0200
@@ -0,0 +1,555 @@
+/*
+* 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 <s32std.h>
+#include <s32stor.h>
+#include <s32file.h>
+
+#include <f32file.h>
+
+#include <gdi.h>
+
+#include <txtrich.h>
+#include "txtmrtsr.h"
+
+#include <frmprint.h>
+
+#include <prnsetup.h>
+
+#include <basched.h>
+
+#include <coemain.h>
+
+#include <apparc.h>
+#include <apgdoor.h>
+
+#include <eikproc.h>
+#include <techview/eikpword.h>
+#include <techview/eikon.rsg>
+#include <eikfutil.h>
+#include <techview/eikdialg.h>
+#include <eikenv.h>
+
+#include "WNGMODEL.H"
+
+#include "WPDOC.H"
+#include "WPAPPUI.H"
+#include "WPMAIN.H"
+#include "WPPANIC.H"
+#include "wpresources.h"
+#include <word.rsg>
+#include "WORD.HRH"
+
+//#define ALLOC_TESTING
+
+//
+// CWordDocument
+//
+
+const TUid KUidWordAppUiStream={268436035};
+
+CWordDocument* CWordDocument::NewL(CEikApplication& aApp)
+// Return a handle to a new instance of this class.
+//
+	{
+#if defined(ALLOC_TESTING)
+	// reserve some space on the cleanup stack
+	{for (TInt ii=0;ii<1000;++ii)
+		CleanupStack::PushL(&ii);}
+	CleanupStack::Pop(1000);
+	//
+	__UHEAP_MARK;
+	{
+	CWordDocument* self=NULL;
+	for (TInt ii=2;;++ii)
+		{
+		__UHEAP_SETFAIL(RHeap::EDeterministic,ii);
+		__UHEAP_MARK;
+		TInt err=KErrNone;
+		self=new(ELeave) CWordDocument(aApp);
+		if (self)
+			{
+			TRAP(err,self->ConstructL());
+			delete self;
+			self=NULL;
+			}
+		__UHEAP_MARKEND;
+		User::Heap().Check();
+		if (err==KErrNone)
+			break;
+		}
+	__UHEAP_MARKEND;
+	__UHEAP_RESET;
+	User::Heap().Check();
+	}
+#endif
+	CWordDocument* self=new(ELeave) CWordDocument(aApp);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop();
+	return self;
+	}
+
+
+void CWordDocument::ConstructL()
+// Complete initialisation
+//
+	{
+	CreateModelL();
+	ConstructPrintL();
+	iUiData=new(ELeave) TWordUiData;
+	}
+
+
+CWordDocument::~CWordDocument()
+	{
+	delete iModel;
+	delete iPrint;
+	delete iUiData;
+	}
+
+
+void CWordDocument::CreateModelL()
+	{iModel=CWordModel::NewL(this,this);}
+
+
+void CWordDocument::ConstructPrintL()
+// Print initialisation
+//
+	{
+	CCoeEnv* coeEnv=CCoeEnv::Static();
+	CWordModel& model=*Model();
+	CPrintSetup& printSetup=*model.PrintSetup();
+	printSetup.CreatePrinterDeviceL(KUidPrinterDevice,coeEnv->FsSession());
+	iPrint=CTextPageRegionPrinter::NewL(model.Text(),printSetup.PrinterDevice());
+	//
+	TPageMargins margins;									 
+	margins.iMargins.iLeft=1440;
+	margins.iMargins.iRight=1440;			
+	margins.iMargins.iTop=1440;		   
+	margins.iMargins.iBottom=1440;
+	margins.iHeaderOffset=720;
+	margins.iFooterOffset=720;
+	TPageSpec pageSpec;
+	pageSpec.iPortraitPageSize=TSize(11906,16838);	   // A4 !!	
+	printSetup.iPageMarginsInTwips=margins;
+  	printSetup.PrinterDevice()->SelectPageSpecInTwips(pageSpec);	   // A4 !!
+	}
+
+
+void CWordDocument::NewDocumentL()
+// Builds a new main (container) document, creating content from a standard file.
+// If a leave occurs whilst loading the standard document, current document
+// content will not be lost.
+//
+	{ 
+	TFileName templateFileName;
+	TWordFilePath::GetNormalTemplateFolderName(templateFileName);
+	TFindFile* ff = new(ELeave) TFindFile(Process()->FsSession());
+	CleanupStack::PushL(ff);
+	TFileName* tempFileName = new(ELeave) TFileName();
+	CleanupStack::PushL(tempFileName);
+	CCoeEnv* coeEnv = CCoeEnv::Static();
+	coeEnv->ReadResource(*tempFileName, R_WORD_NORMAL_TEMPLATE_FILE_NAME);
+	templateFileName.Append(*tempFileName);
+	// look for a normal template
+	templateFileName[0] = 'Y';
+	TParsePtrC tParse(templateFileName);
+	TInt error = ff->FindByDir(templateFileName,tParse.DriveAndPath());
+	if(error)
+		{
+		// no normal template, search ROM for blank
+		TWordFilePath::GetNormalTemplateFolderName(templateFileName);
+		coeEnv->ReadResource(*tempFileName, R_WORD_BLANK_TEMPLATE_FILE_NAME);
+		templateFileName.Append(*tempFileName);
+		templateFileName[0] = 'Z';
+		TParsePtr blankParse(templateFileName);
+		error = ff->FindByDir(blankParse.NameAndExt(),blankParse.DriveAndPath());
+		}
+	CleanupStack::PopAndDestroy(); // tempFileName
+	if(error!=KErrNone)
+		Panic(EDefaultTemplateNotPresent);
+	templateFileName = ff->File();
+	CleanupStack::PopAndDestroy(); // ff
+	DoNewDocumentL(templateFileName);
+	if (iAppUi)
+		WordAppUi().NotifyNewTextL();  // edwin must know of new text for focus loss etc...
+	}
+
+
+CFileStore* CWordDocument::DoNewDocumentL(const TDesC& aStandardDocument,TKeepStoreOpen aKeepStoreOpen/*=EKeepFalse*/)
+// Open and restore the specified valid document.
+// The store that is opened over the file for restoration may be kept open, or destroyed, depending on
+// the value of aKeepStoreOpen.
+//
+	{
+	CFileStore* store=NULL;
+	CStreamDictionary* dictionary=CApaProcess::ReadRootStreamLC(Process()->FsSession(),store,aStandardDocument,EFileShareExclusive|EFileRead);  // takes ownership of store
+	CleanupStack::PushL(store);
+	iNewDocument = ETrue;
+	RestoreL(*store,*dictionary);
+	iNewDocument = EFalse;
+	iModel->Text()->DetachFromStoreL(CPicture::EDetachFull);
+	if (aKeepStoreOpen==EKeepTrue)
+		CleanupStack::Pop();  // store
+	else
+		CleanupStack::PopAndDestroy();  // store
+	CleanupStack::PopAndDestroy();  // dictionary
+	return (aKeepStoreOpen==EKeepTrue)
+		? store
+		: NULL;
+	}
+
+
+void CWordDocument::LocateTemplateL(const TDes& aFullFileName) const
+// Verify that the template file selected by the user is still present
+//
+	{
+	TFindFile ff(Process()->FsSession());
+	TParsePtrC tParse(aFullFileName);
+	User::LeaveIfError(ff.FindByDir(aFullFileName,tParse.DriveAndPath()));
+	VerifyDocumentTypeL(aFullFileName);
+	}
+
+void CWordDocument::VerifyDocumentTypeL(const TFileName& aFileName)const
+// Verify the document of the specified name is indeed of the
+// same type as this document object.
+//
+	{
+	TEntry entry;
+	User::LeaveIfError(Process()->FsSession().Entry(aFileName,entry));
+	if (entry.MostDerivedUid()!=Application()->AppDllUid())
+		User::Leave(KErrCorrupt);
+	}
+
+
+const CStreamStore& CWordDocument::StreamStoreL(TInt /*aPos*/)const
+// In this case the store does not vary with document position.
+//
+	{return *iEditStore;}
+
+
+void CWordDocument::DetachFromStoreL(CPicture::TDetach aDegree)
+// Propogate the detachFromStore to all picture container components.
+//
+	{
+	iModel->Text()->DetachFromStoreL(aDegree);
+	CRichText* text=iModel->PrintSetup()->Header()->Text();
+	if (text)
+		text->DetachFromStoreL(aDegree);
+	text=iModel->PrintSetup()->Footer()->Text();
+	if (text)
+		text->DetachFromStoreL(aDegree);
+	iEditStore=NULL;
+	}
+
+void CWordDocument::StoreUiDataL(CStreamStore& aStore,CStreamDictionary& aStreamDic)const
+// Write any Ui data
+//
+	{
+	if (iAppUi)
+		WordAppUi().GetUiData(*iUiData);
+
+	RStoreWriteStream stream;
+	TStreamId id=stream.CreateLC(aStore);
+	stream <<*iUiData;
+	stream.CommitL();
+	CleanupStack::PopAndDestroy();  // stream
+
+	aStreamDic.AssignL(KUidWordAppUiStream,id);
+	}
+
+
+void CWordDocument::StoreL(CStreamStore& aStore,CStreamDictionary& aStreamDic)const
+// Write this object network.
+//
+	{
+	if (iAppUi)
+		CEikonEnv::Static()->BusyMsgL(R_EIK_TBUF_SAVING_FILE,KFileBusyInitialDelayInMicroSeconds);
+	StoreUiDataL(aStore,aStreamDic);
+	iModel->StoreL(aStore, aStreamDic, 0);
+	if (iAppUi)
+		CEikonEnv::Static()->BusyMsgCancel();
+	}
+
+
+void CWordDocument::RestoreUiDataL(const CStreamStore& aStore,const CStreamDictionary& aStreamDic)
+// Restore any ui data for future use
+//
+	{
+	TStreamId id=aStreamDic.At(KUidWordAppUiStream);
+	if (id==KNullStreamId)
+		iUiData->Reset();
+	else
+		{
+		RStoreReadStream stream;
+		stream.OpenLC(aStore,id);
+		stream>> *iUiData;
+		CleanupStack::PopAndDestroy();  // stream
+		}
+	}
+
+
+void CWordDocument::RestoreL(const CStreamStore& aStore,const CStreamDictionary& aStreamDic)
+// Restore this document.
+// All model restoration is done here, to save having a temporary model member data,
+// implementing a rollback robust model restore.
+//
+	{
+	CEikonEnv* eikonEnv=CEikonEnv::Static();
+	if (iAppUi && !iNewDocument)
+		eikonEnv->BusyMsgL(R_EIK_TBUF_OPENING_FILE,KFileBusyInitialDelayInMicroSeconds);
+	else if (iAppUi && iNewDocument)
+		eikonEnv->BusyMsgL(R_WORD_FILE_CREATE_FILE,KFileBusyInitialDelayInMicroSeconds);
+	//
+	CWordModel* tempModel=CWordModel::NewL(this,this);
+	CleanupStack::PushL(tempModel);
+	//
+	CStreamStore* oldStore=iEditStore;
+	iEditStore=CONST_CAST(CStreamStore*,&aStore);
+	//
+	tempModel->Text()->SetPictureFactory(&iPictureFactory,this);  // rich text callbacks
+	TRAPD(ret,
+		tempModel->RestoreL(aStore,aStreamDic,0,this,this,eikonEnv->PictureFactory()));  // print setup field callbacks
+	if (ret!=KErrNone)
+		{
+		iEditStore=oldStore;
+		User::Leave(ret);
+		}
+	delete iModel;
+	iModel=tempModel;  // document takes over ownership
+	CleanupStack::Pop();  // tempModel
+
+	SetChanged(EFalse);  // this is a brand new document - it cannot yet have been changed.
+
+	TRAP(ret,
+	RestoreUiDataL(aStore,aStreamDic));
+		if (ret!=KErrNone)
+			iUiData->Reset();  // do not propogate.  We can handle this.
+	//
+	if (iAppUi)
+		{
+		WordAppUi().SetUiData();
+//		CEikonEnv::Static()->BusyMsgCancel();
+		}
+	}
+
+
+TInt CWordDocument::UpdateFieldFileName(TPtr& aValueText)const
+// Set aValueText with the current document filename only.
+// (No path or extension).
+//
+	{
+	TParsePtrC parser(Process()->MainDocFileName());
+	TPtrC pp=parser.NameAndExt();
+	if (pp.Length()>aValueText.MaxLength())
+		return pp.Length();
+	aValueText=pp;
+	return 0;
+	}
+
+
+TInt CWordDocument::UpdateFieldNumPages()const
+// Return the number of pages currently in this document.
+// Precondition: pagination of the document has already occured.
+//
+	{return iModel->PageTable()->Count();}
+
+
+void CWordDocument::DoFileNewL(const TFileName& aNewFilename, const TFileName& aTemplateFileName)
+// Create an initialised document instance with the specified name,
+// and initialise a new file store to store the document in.
+// (A new document is not created, *this* instance is re-used).
+//
+	{
+	//
+	// Create the file store for the new document
+	LocateTemplateL(aTemplateFileName);
+	User::LeaveIfError(EikFileUtils::CopyFile(aTemplateFileName,aNewFilename));
+	CCoeEnv* coeEnv=CCoeEnv::Static();
+	User::LeaveIfError(coeEnv->FsSession().SetAtt(aNewFilename,KEntryAttNormal,KEntryAttReadOnly));
+	// turn read-only file attribute if set, just to be safe.
+	//
+	CFileStore* store=DoNewDocumentL(aNewFilename,EKeepTrue);
+	__ASSERT_DEBUG(store,Panic(ENewFileNullStore));
+	//
+	SetMainStoreAndMainDocFileName(store,aNewFilename);
+	SetChanged(ETrue);
+	TUint appFileMode=AppFileMode();
+	appFileMode|=EFileWrite;
+	SetAppFileMode(appFileMode);
+	WordAppUi().SetReadOnly((TBool)!(appFileMode&EFileWrite));
+	}
+
+
+void CWordDocument::SetMainStoreAndMainDocFileName(CFileStore* aMainStore,const TDesC& aMainDocFileName)
+	{
+	CEikProcess& process=REINTERPRET_CAST(CEikProcess&,*Process());
+	delete process.MainStore();  // remove the [original] store
+	process.SetMainStore(aMainStore);  // set the new file store as the main one.
+	process.SetMainDocFileName(aMainDocFileName);
+	}
+
+
+void CWordDocument::DoFileOpenL(const TFileName& aFileName,TUint aFileMode)
+// Open the Word document specified by aFileName.
+//
+	{
+	VerifyDocumentTypeL(aFileName);
+	RFs session=Process()->FsSession();
+	GetFileOpenModeL(aFileMode,aFileName,session);
+//
+	CFileStore* store=NULL;
+	CStreamDictionary* dic=CApaProcess::ReadRootStreamLC(session,store,aFileName,EFileShareExclusive|aFileMode);
+	CleanupStack::PushL(store);
+	RestoreL(*store,*dic);
+	CleanupStack::Pop();  // store
+	CleanupStack::PopAndDestroy();  // dictionary
+	//
+	SetMainStoreAndMainDocFileName(store,aFileName);
+	SetAppFileMode(aFileMode);
+	WordAppUi().SetReadOnly((TBool)!(aFileMode&EFileWrite));
+	}
+
+
+void CWordDocument::GetFileOpenModeL(TUint& aFileMode,const TDesC& aFilename,RFs& aSession)
+// Attempt to open the specified file in the specified mode.
+// If this fails because write access was requested on a read-only file,
+// the file is opened read-only.
+// Any other error (leave) is propogated.
+// aFileMode is set to the mode that the file was successfully opened in.
+//
+	{
+	CFileStore* store=NULL;
+	TRAPD(ret,
+	store=CFileStore::OpenL(aSession,aFilename,aFileMode));
+	if (ret==KErrAccessDenied && aFileMode&EFileWrite)
+		{
+		ret=KErrNone;
+		aFileMode&=~EFileWrite;
+		store=CFileStore::OpenL(aSession,aFilename,aFileMode);
+		}
+	//
+	User::LeaveIfError(ret);
+	__ASSERT_DEBUG(ret==KErrNone && store,Panic(EFileOpenIntegrityError));
+	delete store;
+	}
+
+
+void CWordDocument::DoFileSaveToCurrentL()
+	{
+	SaveL();	  
+	}
+
+
+void CWordDocument::DoFileSaveToNewL(const TFileName& aNewFileName)
+	{
+	((CEikProcess*)Process())->SaveToDirectFileStoreL(this,&aNewFileName); // writes root stream
+	SetAppFileMode(EFileWrite);
+	}
+
+void CWordDocument::DoFileSaveToNewNoSwitchL(const TFileName& aNewFileName)
+// Save the current file to a new file, but don't open the new file
+	{
+	// From CEikProcess::SaveToDirectFileStoreL but without the close iMainDoc at the end
+	//
+	CApaProcess* proc = Process();
+	RFs& fsSession=proc->FsSession();
+	CDirectFileStore* store;
+	store = CDirectFileStore::CreateLC(fsSession,aNewFileName,EFileWrite);
+	store->SetTypeL(REINTERPRET_CAST(CEikProcess*,proc)->MainStore()->Type());
+	CStreamDictionary* streamDic=CStreamDictionary::NewL();
+	CleanupStack::PushL(streamDic);
+	proc->MainDocument()->StoreL(*store,*streamDic);
+	// write root stream
+	proc->WriteRootStreamL(*store,*streamDic,*(this->Application()));
+	CleanupStack::PopAndDestroy(); // streamDic
+	// close the new store
+	store->CommitL();
+	CleanupStack::PopAndDestroy(); // store
+	}
+
+void CWordDocument::DoFileRevertL()
+	{
+	CStreamDictionary* streamDic=CStreamDictionary::NewL();
+	CleanupStack::PushL(streamDic);
+	CFileStore* mainStore=REINTERPRET_CAST(CEikProcess*,Process())->MainStore();
+	RStoreReadStream root;
+	root.OpenLC(*mainStore,mainStore->Root());
+	root>> *streamDic;
+	root.Close();
+	CleanupStack::PopAndDestroy(); // root
+	RestoreL(*mainStore,*streamDic);
+	CleanupStack::PopAndDestroy(); // streamDic
+	}
+
+//
+// CWordApplication
+//
+
+TUid CWordApplication::AppDllUid() const
+	{
+	return KUidWordAppValue;
+	}
+
+CApaDocument* CWordApplication::CreateDocumentL()
+	{return CWordDocument::NewL(*this);}
+
+
+CEikAppUi* CWordDocument::CreateAppUiL()
+	{
+#if defined(ALLOC_TESTING)
+	// reserve some space on the cleanup stack
+	{for (TInt ii=0;ii<1000;++ii)
+		CleanupStack::PushL(&ii);}
+	CleanupStack::Pop(1000);
+	// construct the appUi before the setfail loop so that cached resources
+	// do not cause alloc failure
+	CWordAppUi* appUi=NULL;
+	appUi=new(ELeave) CWordAppUi;
+	appUi->SetDocument(this);
+	appUi->ConstructL();
+	delete appUi;
+	appUi=NULL;
+	__UHEAP_MARK;
+	{
+	for (TInt ii=2;;++ii)
+		{
+		__UHEAP_SETFAIL(RHeap::EDeterministic,ii);
+		__UHEAP_MARK;
+		appUi=new(ELeave) CWordAppUi;
+		appUi->SetDocument(this);
+		TInt err=KErrNone;
+		if (appUi)
+			{
+			TRAP(err,appUi->ConstructL());
+			delete appUi;
+			appUi=NULL;
+			}
+		__UHEAP_MARKEND;
+		User::Heap().Check();
+		if (err==KErrNone)
+			break;
+		}
+	__UHEAP_MARKEND;
+	__UHEAP_RESET;
+	User::Heap().Check();
+	}
+#endif
+    return(new(ELeave) CWordAppUi);
+	}