diff -r 000000000000 -r e4d67989cc36 lowlevellibsandfws/apputils/src/BACLIPB.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lowlevellibsandfws/apputils/src/BACLIPB.CPP Tue Feb 02 02:01:42 2010 +0200 @@ -0,0 +1,360 @@ +// 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: +// Started by DS, October 1996 +// Clipboard +// +// + +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef _UNICODE +const TUid KClipboardFileUid16={0x10003A10}; +#define KClipboardFileUid KClipboardFileUid16 +#else +const TUid KClipboardFileUid8={268435515}; +#define KClipboardFileUid KClipboardFileUid8 +#endif + +_LIT(KClipboardFileName,"\\System\\Data\\Clpboard.cbd"); + + +inline CClipboard::CClipboard(RFs& aFs) + : iFs(aFs) + {__DECLARE_NAME(_S("CClipboard"));} + +CClipboard* CClipboard::NewLC(RFs& aFs) + { + CClipboard* self=new(ELeave) CClipboard(aFs); + CleanupStack::PushL(self); + return self; + } + +void CClipboard::ConstructReadL() + { + __ASSERT_DEBUG(iStore==NULL&&iStreamDictionary==NULL,User::Invariant()); + +// + TDriveName clipboardDrive = ClipboardFileDrive(); + TFileName clipboardFile(KClipboardFileName); + clipboardFile.Insert(0,clipboardDrive); + + CFileStore* store=CDirectFileStore::OpenLC(iFs,clipboardFile,EFileRead|EFileShareReadersOnly); + if (store->Type()!=TUidType(KDirectFileStoreLayoutUid,KClipboardFileUid)) + User::Leave(KErrCorrupt); + CStreamDictionary* dict=CStreamDictionary::NewLC(); + RStoreReadStream root; + root.OpenLC(*store,store->Root()); + root >> *dict; + CleanupStack::PopAndDestroy(); // root stream +// + CleanupStack::Pop(2); // store and dictionary + iStore=store; + iStreamDictionary=dict; + } + + +EXPORT_C TDriveName CClipboard::ClipboardFileDrive() +/** + Returns the clipboad file drive information stored in the TLS + + @return A drive letter and a colon (A:, B:... etc,.) + @panic BAFL 23 If drive is either not in range 0-24 or is not defined in HAL file(s). + If this panic occurs, check the value of EClipboardDrive defined in HAL file(s) + i,e & . This value should be in range EDriveA-EDriveY. + */ + { + TInt drive; + TInt retVal; + TBool badDrive = ETrue; + + retVal = HAL::Get(HAL::EClipboardDrive,drive); + + if(retVal == KErrNone) + { + //EDriveZ can not be a valid clipboard drive as it is non-writable + // Check if drive is between range 0-24, + if(EDriveA <= drive && EDriveY >= drive) + { + badDrive = EFalse; // Drive is valid + } + } + + __ASSERT_ALWAYS((badDrive == EFalse), ::Panic(EBafPanicBadDrive)); + + TDriveUnit driveUnit(drive); + return driveUnit.Name(); + } + +EXPORT_C CClipboard* CClipboard::NewForReadingLC(RFs& aFs) +/** Constructs a clipboard object and prepares the clipboard's store for reading, +placing a pointer to the object on the cleanup stack. This allows the object +and allocated resources to be cleaned up if a subsequent leave occurs. + +@param aFs A handle to a file server session. +@return A pointer to the newly constructed clipboard object. This pointer is +put onto the cleanup stack. */ + { + CClipboard* self=NewLC(aFs); + TRAPD(error,self->ConstructReadL()); + switch (error) + { + default: + User::LeaveIfError(error); + __ASSERT_DEBUG(self->iStore!=NULL&&self->iStreamDictionary!=NULL,User::Invariant()); + break; + case KErrPathNotFound: // clipboard does not exist + case KErrNotFound: // no root stream + case KErrInUse: // someone is writing to the clipboard + case KErrCorrupt: // type is invalid, or cardinality failure + case KErrEof: // wrong structure + case KErrNotSupported: // not a file store + // return an empty clipboard: will need an empty dictionary + __ASSERT_DEBUG(self->iStore==NULL&&self->iStreamDictionary==NULL,User::Invariant()); + self->iStreamDictionary=CStreamDictionary::NewL(); + break; + } + return(self); + } + +EXPORT_C CClipboard* CClipboard::NewForReadingL(RFs& aFs) +/** Constructs a clipboard object and prepares the clipboard's store for reading. + +@param aFs A handle to a file server session. +@return A pointer to the newly constructed clipboard object. */ + { + CClipboard* self=CClipboard::NewForReadingLC(aFs); + CleanupStack::Pop(); + return self; + } + +EXPORT_C CClipboard* CClipboard::NewForWritingLC(RFs& aFs) +/** Constructs a clipboard object and prepares the clipboard's store for writing. + +If the file associated with the clipboard's store does not exist, it is created; +if it already exists, any existing content is discarded. + +@param aFs A handle to a file server session. +@return A pointer to the newly constructed clipboard object. This pointer is +put onto the cleanup stack. */ + { + CClipboard* self=NewLC(aFs); + self->iStreamDictionary=CStreamDictionary::NewL(); +// + TDriveName clipboardDrive = ClipboardFileDrive(); + TFileName clipboardFile(KClipboardFileName); + clipboardFile.Insert(0,clipboardDrive); + + RFile file; + TInt r=file.Open(aFs,clipboardFile,EFileRead|EFileWrite); + + /** + * The following branching is desired at this stage: + * -> if the path is not present, we need to create it and then create the file. + * -> if the path is present, we only need to create the file + * -> if both path and file exists, we don't need to do anything + * + * Instead of the switch case block we can achieve this by atleast 2 other means. + * Option 1: + * RFile file; + * TInt r=file.Open(aFs,clipboardFile,EFileRead|EFileWrite); + * if(r == KErrPathNotFound) { + * BaflUtils::EnsurePathExistsL(aFs,clipboardFile); + * r=file.Replace(aFs,clipboardFile,EFileRead|EFileWrite); + * } else if(r == KErrNotFound) { + * r=file.Replace(aFs,clipboardFile,EFileRead|EFileWrite); + * } + * User::LeaveIfError(r); + * + * => the above code has extra check to be made when the error is KErrNotFound + * and has increased code size owing to repeated file.Replace(). + * + * Option 2: + * BaflUtils::EnsurePathExistsL(aFs,clipboardFile); + * RFile file; + * TInt r=file.Open(aFs,clipboardFile,EFileRead|EFileWrite); + * if(r == KErrNotFound) { + * r=file.Replace(aFs,clipboardFile,EFileRead|EFileWrite); + * } + * User::LeaveIfError(r); + * => Call to BaflUtils::EnsurePathExistsL unconditionally which in turn + * invokes Rfs::MkDirAll() can be expensive and errorneous. + * (Check documnentation for RFs::MkDirAll() + */ + + + //Maintain the order of the switch case and DO NOT add break between the + //switch cases. They have been written such that only the required set of + //functionality is executed based on the Error code. + switch (r) + { + case KErrPathNotFound: // path has not been created yet + BaflUtils::EnsurePathExistsL(aFs,clipboardFile); + // coverity [fallthrough] + // Missing break intentional. Read comment before switch case. + case KErrNotFound: // it does not exist yet + r=file.Replace(aFs,clipboardFile,EFileRead|EFileWrite); + // coverity [fallthrough] + // Missing break intentional. Read comment before switch case. + default: + User::LeaveIfError(r); + } +// + CFileStore* store=CDirectFileStore::NewL(file); + self->iStore=store; + store->SetTypeL(TUidType(KDirectFileStoreLayoutUid,KClipboardFileUid)); + return self; + } + +EXPORT_C TInt CClipboard::Clear(RFs& aFs) +/** Empties the clipboard. + +Note that if the file associated with the clipboard's store does not exist, +this is not regarded as an error and the function completes successfully. + +@param aFs A handle to a file server session. +@return KErrNone if successful, otherwise another of the system-wide error +codes. */ + { + TDriveName clipboardDrive = ClipboardFileDrive(); + TFileName clipboardFile(KClipboardFileName); + clipboardFile.Insert(0,clipboardDrive); + + RFile file; + TInt r=file.Open(aFs,clipboardFile,EFileWrite); + switch (r) + { + case KErrNone: // clear without notification + r=file.SetSize(0); + file.Close(); + break; + case KErrPathNotFound: // no clipboard to clear + case KErrNotFound: + r=KErrNone; + break; + default: + r=aFs.Delete(clipboardFile); // just delete the fella + break; + } + return r; + } + +EXPORT_C CClipboard::~CClipboard() +/** Destructor. Frees all resources owned by the object, prior to its destruction. +In particular, the file associated with the clipboard's store is closed. + +Note that if the clipboard file store has no root stream, i.e. the CommitL() +member function of CClipboard has not been called prior to deleting the CClipboard +object, then the file associated with the clipboard file store is deleted. */ + { + delete iStreamDictionary; + CFileStore* store=iStore; + if (store!=NULL) + { + TBool rollback=(store->Root()==KNullStreamId); + delete store; + if (rollback) // useless clipboard, no root stream + { + TDriveName clipboardDrive = ClipboardFileDrive(); + TFileName clipboardFile(KClipboardFileName); + clipboardFile.Insert(0,clipboardDrive); + + iFs.Delete(clipboardFile); + } + } + } + +EXPORT_C void CClipboard::CommitL() +/** Commits changes to the clipboard's store. + +It externalises the stream dictionary to the clipboard store as the root stream +and then commits all changes to the store. This function must be called after +application data has been externalised; failure to do so results in the deletion +of the file associated with the clipboard store and the loss of data. */ + { + __ASSERT_DEBUG(iStore!=NULL&&iStreamDictionary!=NULL,User::Invariant()); +// + CFileStore& store=*iStore; + RStoreWriteStream stream; + TStreamId root=stream.CreateLC(store); + stream<< *iStreamDictionary; + stream.CommitL(); + CleanupStack::PopAndDestroy(); // dictionary stream + store.SetRootL(root); + store.CommitL(); + } + + +// Copy and paste member functions for low level data types + + +const TUid KClipboardRealTypeUid = { 268435705 }; + + +EXPORT_C void CClipboard::CopyToL(TReal aReal) __SOFTFP +/** Copies a double-precision floating point value to the clipboard. + +Note that the function does not automatically commit changes to the clipboard's +store. This must be done explicitly. + +@param aReal The double-precision floating point value to be copied to the +clipboard. +@see CommitL() */ + { + __ASSERT_DEBUG(iStore!=NULL&&iStreamDictionary!=NULL,User::Invariant()); +// + RStoreWriteStream stream; + TStreamId id = stream.CreateLC ( Store() ); + stream << aReal; + stream.CommitL(); + CleanupStack::PopAndDestroy(); + StreamDictionary().AssignL ( KClipboardRealTypeUid, id ); + } + +EXPORT_C TBool CClipboard::PasteFromL ( TReal& aReal ) +/** Pastes a double-precision floating point value from the clipboard. + +If a double-precision floating point value exists on the clipboard, then the +function restores it to the referenced argument and returns a true value. + +If there is no double-precision floating point value on the clipboard, then +the function returns a false value. The referenced argument is not changed. + +@param aReal On return, contains the double-precision floating point value +found on the clipboard. +@return ETrue, if a double-precision floating point value exists on the +clipboard and has been pasted to the referenced argument; EFalse otherwise. */ + { + __ASSERT_DEBUG(iStreamDictionary!=NULL,User::Invariant()); + TStreamId id = StreamDictionary().At(KClipboardRealTypeUid); + if (id == KNullStreamId) + return (EFalse); // nothing here + __ASSERT_DEBUG(iStore!=NULL,User::Invariant()); + RStoreReadStream stream; + stream.OpenLC (Store(), id); + stream >> aReal; + CleanupStack::PopAndDestroy(); + return (ETrue); + } + + + +// end of BACLIPB.CPP