// EIKPROC.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <eikproc.h>
#include <eikdoc.h>
#include <s32file.h>
#include <basched.h>
#include <eikpanic.h>
#include <apacmdln.h>
#include <apparc.h>
#include <apffndr.h>
#include <apfdef.h>
#include <eikenv.h>

CEikProcess* CEikProcess::NewL(const RFs& aFs)
	{ // static
	CApaScanningAppFinder* appFinder=CApaScanningAppFinder::NewLC(aFs);
	CEikProcess* self=new(ELeave) CEikProcess(aFs,*appFinder);
	CleanupStack::Pop(); // appFinder
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(); // self
	return self;
	}

CEikProcess::CEikProcess(const RFs& aFs,CApaAppFinder& aAppFinder)
	: CApaProcess(aFs, aAppFinder)
	{}

EXPORT_C CEikProcess::~CEikProcess()
	{
	DestroyDocument(MainDocument()); // pre-empt this call at superclass level
	delete(iMainStore); // delete this only after document has been deleted
	}

EXPORT_C TFileName CEikProcess::MainDocFolder() const
	{
	TParse parse;
	parse.Set(MainDocFileName(),NULL,NULL);
	return(parse.DriveAndPath());
	}

EXPORT_C void CEikProcess::SetMainStore(CFileStore* aMainStore)
	{
	iMainStore=aMainStore;
	}

struct STemp
	{
	RFs* iFs;
	TParse iFile;
	};

LOCAL_C void DeleteTemp(TAny* aPtr)
	{
	STemp& temp=*(STemp*)aPtr;
	temp.iFs->Delete(temp.iFile.FullName());
	}

EXPORT_C void CEikProcess::SaveToDirectFileStoreL(CEikDocument* aDoc,const TFileName* aNewFileName)
// saves to a new file and then opens that file for reading.
// saves to iMainDocFileName if aNewFilename==NULL
// The old store should be passed in as aStore. This is deleted and then set to the new store.
// aApp should be the application used to create the main doc in the file being written
//
	{
	__ASSERT_ALWAYS( iMainStore ,Panic(EEikPanicProcessNoStore));
	__ASSERT_ALWAYS( iMainStore->Type()[0]==KDirectFileStoreLayoutUid ,Panic(EEikPanicProcessWrongStoreType));
	//
	RFs& fsSession=FsSession();
	STemp temp;					// for temporary file name and cleanup-deletion
	CDirectFileStore* store;
	if (aNewFileName)
		// save to the new filename supplied, and open this new file as iMainDoc
		store = CDirectFileStore::CreateLC(fsSession,*aNewFileName,EFileWrite);
	else
		{// overwrite iMainDocFileName, but save to a temporary first
		// make sure the temp directory is on the same drive as the file and that it exists
		TParsePtrC ptr(MainDocFileName());
		TPtrC drive=ptr.Drive();
		TFileName tempName(Apfile::TempPath());
		User::LeaveIfError(temp.iFile.Set(drive,&tempName,NULL) ); // abuse temp.iFile
		fsSession.MkDirAll(temp.iFile.DriveAndPath());
		// create temp file
		tempName.Zero();
		RFile file;
		User::LeaveIfError(file.Temp(fsSession,temp.iFile.DriveAndPath(),tempName,EFileWrite));
		temp.iFs=&fsSession;
		temp.iFile.Set(tempName,NULL,NULL);		// set for deletion if it goes wrong now
		CleanupStack::PushL(TCleanupItem(DeleteTemp,&temp));
		store = CDirectFileStore::NewLC(file);
		}
	store->SetTypeL(iMainStore->Type());
	// store main in temp
	CStreamDictionary* streamDic=CStreamDictionary::NewL();
	CleanupStack::PushL(streamDic);
	MainDocument()->StoreL(*store,*streamDic);
	// write root stream
	WriteRootStreamL(*store,*streamDic,*aDoc->Application());
	CleanupStack::PopAndDestroy(); // streamDic
	// close the new store
	store->CommitL();
	CleanupStack::PopAndDestroy(); // store
	if (aNewFileName==NULL)
		CleanupStack::Pop();		// temporary file deleter
	// close the old store
	delete iMainStore;
	iMainStore=NULL;
	TRAPD(err,OpenNewFileL(aNewFileName,temp.iFile));
	if (err!=KErrNone)
		{
		if (iMainStore!=NULL)
			User::Leave(err);
//		iEikonEnv->AlertWin();
		CBaActiveScheduler::Exit();
		}
	}

void CEikProcess::OpenNewFileL(const TFileName* aNewFileName,const TParse& aNewFilePath)
	{
	if (!aNewFileName)
		{
		RFs& fsSession=FsSession();
		const TInt err=fsSession.Replace(aNewFilePath.FullName(),MainDocFileName());
		iMainStore=CDirectFileStore::OpenL(fsSession,MainDocFileName(),EFileShareExclusive);
		User::LeaveIfError(err);
		}
	else
		{
		SetMainDocFileName(*aNewFileName);
		// open new file
		iMainStore=CDirectFileStore::OpenL(FsSession(),MainDocFileName(),EFileShareExclusive);
		}
	}

EXPORT_C void CEikProcess::AppFromDocL(TDes& aLibraryName,const TDesC& aDocumentName) const
	{
	CFileStore* docStore;
	CStreamDictionary* streamDic=CApaProcess::ReadRootStreamLC(FsSession(),docStore,aDocumentName,EFileRead);
	CleanupStack::PushL(docStore);
	GetLibraryNameL(aLibraryName,*docStore,*streamDic);
	CleanupStack::PopAndDestroy(2); // streamDic and docStore
	}

void CEikProcess::GetLibraryNameL(TDes& aLibraryName,const CFileStore& aDocStore,const CStreamDictionary& aStreamDic) const
	{
	TApaAppIdentifier appId=ReadAppIdentifierL(aDocStore,aStreamDic);
	aLibraryName=appId.iFullName;
	}

const TUid KUidEikLastOpenFile={0x100000fb};
const TUid KUidEikLastCreatedFile={0x100000fc};

EXPORT_C void CEikProcess::SetLastUsedFileL(TLastUsedFile aType,const TDesC& aFileName) const
	{
	CDictionaryStore* iniFile=OpenMainAppIniFileLC();
	if (iniFile==NULL)
		return;
	RDictionaryWriteStream writeStream;
	writeStream.AssignL(*iniFile,aType==ELastOpenFile? KUidEikLastOpenFile: KUidEikLastCreatedFile);
	writeStream << aFileName;
	writeStream.CommitL();
	writeStream.Close();
	iniFile->CommitL();
	CleanupStack::PopAndDestroy(); // inifile
	}

// implementation changed; function now never leaves.
EXPORT_C TFileName CEikProcess::LastUsedFileL(TLastUsedFile aType) const
	{
	TFileName ret;
	CDictionaryStore* iniFile=NULL;
	TRAPD(inierr, iniFile=OpenMainAppIniFileLC();
		if (iniFile)
			CleanupStack::Pop(););
	if (!inierr)
		{
		if (iniFile!=NULL)
			{
			CleanupStack::PushL(iniFile);
			RDictionaryReadStream readStream;
			TRAPD(err,readStream.OpenL(*iniFile,aType==ELastOpenFile? KUidEikLastOpenFile: KUidEikLastCreatedFile));
			if (!err)
				{
				TRAP(err,readStream >> ret);
				readStream.Close();
				}
			CleanupStack::PopAndDestroy(); // iniFile
			}
		}
	return(ret);
	}


CDictionaryStore* CEikProcess::OpenMainAppIniFileLC() const
	{
 	CDictionaryStore* iniFile=((CEikProcess*)this)->MainDocument()->Application()->OpenIniFileLC(FsSession());
	return(iniFile);
	}
