diff -r 000000000000 -r 1fb32624e06b textrendering/word/SRC/WPDOC.CPP --- /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 +#include +#include + +#include + +#include + +#include +#include "txtmrtsr.h" + +#include + +#include + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "WNGMODEL.H" + +#include "WPDOC.H" +#include "WPAPPUI.H" +#include "WPMAIN.H" +#include "WPPANIC.H" +#include "wpresources.h" +#include +#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); + }