lowlevellibsandfws/apputils/src/BACLIPB.CPP
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Started by DS, October 1996
       
    15 // Clipboard
       
    16 // 
       
    17 //
       
    18 
       
    19 #include <baclipb.h>
       
    20 #include <s32file.h>
       
    21 #include <basched.h>
       
    22 #include <bautils.h>
       
    23 #include <s32stor.h>
       
    24 #include <hal.h>
       
    25 #include <hal_data.h>
       
    26 #include <baflpan.h>
       
    27 
       
    28 
       
    29 #ifdef _UNICODE
       
    30 const TUid KClipboardFileUid16={0x10003A10};
       
    31 #define KClipboardFileUid KClipboardFileUid16
       
    32 #else
       
    33 const TUid KClipboardFileUid8={268435515};
       
    34 #define KClipboardFileUid KClipboardFileUid8
       
    35 #endif
       
    36 
       
    37 _LIT(KClipboardFileName,"\\System\\Data\\Clpboard.cbd");
       
    38 
       
    39 
       
    40 inline CClipboard::CClipboard(RFs& aFs)
       
    41 	: iFs(aFs)
       
    42 	{__DECLARE_NAME(_S("CClipboard"));}
       
    43 
       
    44 CClipboard* CClipboard::NewLC(RFs& aFs)
       
    45 	{
       
    46 	CClipboard* self=new(ELeave) CClipboard(aFs);
       
    47     CleanupStack::PushL(self);
       
    48 	return self;
       
    49 	}
       
    50 
       
    51 void CClipboard::ConstructReadL()
       
    52 	{
       
    53 	__ASSERT_DEBUG(iStore==NULL&&iStreamDictionary==NULL,User::Invariant());
       
    54 
       
    55 //	
       
    56 	TDriveName clipboardDrive = ClipboardFileDrive();
       
    57 	TFileName clipboardFile(KClipboardFileName);
       
    58 	clipboardFile.Insert(0,clipboardDrive);
       
    59 
       
    60 	CFileStore* store=CDirectFileStore::OpenLC(iFs,clipboardFile,EFileRead|EFileShareReadersOnly);
       
    61 	if (store->Type()!=TUidType(KDirectFileStoreLayoutUid,KClipboardFileUid))
       
    62 		User::Leave(KErrCorrupt);
       
    63 	CStreamDictionary* dict=CStreamDictionary::NewLC();
       
    64 	RStoreReadStream root;
       
    65 	root.OpenLC(*store,store->Root());
       
    66 	root >> *dict;
       
    67 	CleanupStack::PopAndDestroy(); // root stream
       
    68 //
       
    69 	CleanupStack::Pop(2);	// store and dictionary
       
    70 	iStore=store;
       
    71 	iStreamDictionary=dict;
       
    72 	}
       
    73 
       
    74 
       
    75 EXPORT_C TDriveName CClipboard::ClipboardFileDrive()
       
    76 /**
       
    77  Returns the clipboad file drive information stored in the TLS
       
    78  
       
    79  @return A drive letter and a colon (A:, B:... etc,.)
       
    80  @panic BAFL 23 If drive is either not in range 0-24 or is not defined in HAL file(s).
       
    81  If this panic occurs, check the value of EClipboardDrive defined in HAL file(s)
       
    82  i,e <values.hda> & <config.hcf>. This value should be in range EDriveA-EDriveY.
       
    83  */
       
    84     {
       
    85 	TInt drive;
       
    86 	TInt retVal;
       
    87 	TBool badDrive = ETrue;
       
    88 
       
    89 	retVal = HAL::Get(HAL::EClipboardDrive,drive);	
       
    90 	
       
    91 	if(retVal == KErrNone)
       
    92 		{
       
    93 		//EDriveZ can not be a valid clipboard drive as it is non-writable
       
    94 		// Check if drive is between range 0-24,
       
    95 		if(EDriveA <= drive && EDriveY >= drive)
       
    96 			{
       
    97 			badDrive = EFalse; // Drive is valid				
       
    98 			}
       
    99 		}
       
   100 			
       
   101 	__ASSERT_ALWAYS((badDrive == EFalse), ::Panic(EBafPanicBadDrive));
       
   102 
       
   103 	TDriveUnit driveUnit(drive);
       
   104 	return driveUnit.Name();
       
   105 	}
       
   106 
       
   107 EXPORT_C CClipboard* CClipboard::NewForReadingLC(RFs& aFs)
       
   108 /** Constructs a clipboard object and prepares the clipboard's store for reading, 
       
   109 placing a pointer to the object on the cleanup stack. This allows the object 
       
   110 and allocated resources to be cleaned up if a subsequent leave occurs.
       
   111 
       
   112 @param aFs A handle to a file server session. 
       
   113 @return A pointer to the newly constructed clipboard object. This pointer is 
       
   114 put onto the cleanup stack. */
       
   115     {
       
   116 	CClipboard* self=NewLC(aFs);
       
   117 	TRAPD(error,self->ConstructReadL());
       
   118 	switch (error)
       
   119 		{
       
   120 	default:
       
   121 		User::LeaveIfError(error);
       
   122 		__ASSERT_DEBUG(self->iStore!=NULL&&self->iStreamDictionary!=NULL,User::Invariant());
       
   123 		break;
       
   124 	case KErrPathNotFound:	// clipboard does not exist
       
   125 	case KErrNotFound:		// no root stream
       
   126 	case KErrInUse:			// someone is writing to the clipboard
       
   127 	case KErrCorrupt:		// type is invalid, or cardinality failure
       
   128 	case KErrEof:			// wrong structure
       
   129 	case KErrNotSupported:	// not a file store
       
   130 		// return an empty clipboard: will need an empty dictionary
       
   131 		__ASSERT_DEBUG(self->iStore==NULL&&self->iStreamDictionary==NULL,User::Invariant());
       
   132 		self->iStreamDictionary=CStreamDictionary::NewL();
       
   133 		break;
       
   134 		}
       
   135 	return(self);
       
   136 	}
       
   137 
       
   138 EXPORT_C CClipboard* CClipboard::NewForReadingL(RFs& aFs)
       
   139 /** Constructs a clipboard object and prepares the clipboard's store for reading.
       
   140 
       
   141 @param aFs A handle to a file server session. 
       
   142 @return A pointer to the newly constructed clipboard object. */
       
   143 	{
       
   144 	CClipboard* self=CClipboard::NewForReadingLC(aFs);
       
   145 	CleanupStack::Pop();
       
   146 	return self;
       
   147 	}
       
   148 
       
   149 EXPORT_C CClipboard* CClipboard::NewForWritingLC(RFs& aFs)
       
   150 /** Constructs a clipboard object and prepares the clipboard's store for writing.
       
   151 
       
   152 If the file associated with the clipboard's store does not exist, it is created; 
       
   153 if it already exists, any existing content is discarded.
       
   154 
       
   155 @param aFs A handle to a file server session. 
       
   156 @return A pointer to the newly constructed clipboard object. This pointer is 
       
   157 put onto the cleanup stack. */
       
   158     {
       
   159 	CClipboard* self=NewLC(aFs);
       
   160 	self->iStreamDictionary=CStreamDictionary::NewL();
       
   161 //
       
   162 	TDriveName clipboardDrive = ClipboardFileDrive();
       
   163 	TFileName clipboardFile(KClipboardFileName);
       
   164 	clipboardFile.Insert(0,clipboardDrive);
       
   165 
       
   166 	RFile file;
       
   167 	TInt r=file.Open(aFs,clipboardFile,EFileRead|EFileWrite);
       
   168 
       
   169 	/**
       
   170 	 * The following branching is desired at this stage:
       
   171 	 * -> if the path is not present, we need to create it and then create the file. 
       
   172 	 * -> if the path is present, we only need to create the file 
       
   173 	 * -> if both path and file exists, we don't need to do anything 
       
   174 	 * 
       
   175 	 * Instead of the switch case block we can achieve this by atleast 2 other means.
       
   176  	 * Option 1:
       
   177 	 * RFile file; 
       
   178 	 * TInt r=file.Open(aFs,clipboardFile,EFileRead|EFileWrite); 
       
   179 	 * if(r == KErrPathNotFound) { 
       
   180 	 *       BaflUtils::EnsurePathExistsL(aFs,clipboardFile); 
       
   181 	 *       r=file.Replace(aFs,clipboardFile,EFileRead|EFileWrite); 
       
   182 	 * } else if(r == KErrNotFound) { 
       
   183 	 *       r=file.Replace(aFs,clipboardFile,EFileRead|EFileWrite); 
       
   184 	 * }
       
   185 	 * User::LeaveIfError(r);
       
   186 	 *
       
   187 	 * => the above code has extra check to be made when the error is KErrNotFound 
       
   188 	 *    and has increased code size owing to repeated file.Replace().
       
   189 	 *
       
   190 	 * Option 2:
       
   191 	 * BaflUtils::EnsurePathExistsL(aFs,clipboardFile); 
       
   192 	 * RFile file; 
       
   193 	 * TInt r=file.Open(aFs,clipboardFile,EFileRead|EFileWrite); 
       
   194 	 * if(r == KErrNotFound) { 
       
   195 	 *        r=file.Replace(aFs,clipboardFile,EFileRead|EFileWrite); 
       
   196 	 * } 
       
   197 	 * User::LeaveIfError(r);
       
   198 	 * => Call to BaflUtils::EnsurePathExistsL unconditionally which in turn 
       
   199 	 * invokes Rfs::MkDirAll() can be expensive and errorneous.
       
   200 	 * (Check documnentation for RFs::MkDirAll()
       
   201 	 */
       
   202  
       
   203 
       
   204 	//Maintain the order of the switch case and DO NOT add break between the
       
   205 	//switch cases. They have been written such that only the required set of 
       
   206 	//functionality is executed based on the Error code.
       
   207 	switch (r)
       
   208 		{
       
   209 	case KErrPathNotFound:		// path has not been created yet
       
   210 		BaflUtils::EnsurePathExistsL(aFs,clipboardFile);
       
   211 		// coverity [fallthrough]
       
   212 		// Missing break intentional. Read comment before switch case.
       
   213 	case KErrNotFound:			// it does not exist yet
       
   214 		r=file.Replace(aFs,clipboardFile,EFileRead|EFileWrite);
       
   215 		// coverity [fallthrough]
       
   216 		// Missing break intentional. Read comment before switch case.
       
   217 	default:
       
   218 		User::LeaveIfError(r);
       
   219 		}
       
   220 //
       
   221 	CFileStore* store=CDirectFileStore::NewL(file);
       
   222 	self->iStore=store;
       
   223 	store->SetTypeL(TUidType(KDirectFileStoreLayoutUid,KClipboardFileUid));
       
   224 	return self;
       
   225 	}
       
   226 
       
   227 EXPORT_C TInt CClipboard::Clear(RFs& aFs)
       
   228 /** Empties the clipboard.
       
   229 
       
   230 Note that if the file associated with the clipboard's store does not exist, 
       
   231 this is not regarded as an error and the function completes successfully.
       
   232 
       
   233 @param aFs A handle to a file server session. 
       
   234 @return KErrNone if successful, otherwise another of the system-wide error 
       
   235 codes. */
       
   236 	{
       
   237 	TDriveName clipboardDrive = ClipboardFileDrive();
       
   238 	TFileName clipboardFile(KClipboardFileName);
       
   239 	clipboardFile.Insert(0,clipboardDrive);
       
   240 
       
   241 	RFile file;
       
   242 	TInt r=file.Open(aFs,clipboardFile,EFileWrite);
       
   243 	switch (r)
       
   244 		{
       
   245 	case KErrNone:			// clear without notification
       
   246 		r=file.SetSize(0);
       
   247 		file.Close();
       
   248 		break;
       
   249 	case KErrPathNotFound:	// no clipboard to clear
       
   250 	case KErrNotFound:
       
   251 		r=KErrNone;
       
   252 		break;
       
   253 	default:
       
   254 		r=aFs.Delete(clipboardFile);	// just delete the fella
       
   255 		break;
       
   256 		}
       
   257 	return r;
       
   258 	}
       
   259 
       
   260 EXPORT_C CClipboard::~CClipboard()
       
   261 /** Destructor. Frees all resources owned by the object, prior to its destruction. 
       
   262 In particular, the file associated with the clipboard's store is closed.
       
   263 
       
   264 Note that if the clipboard file store has no root stream, i.e. the CommitL() 
       
   265 member function of CClipboard has not been called prior to deleting the CClipboard 
       
   266 object, then the file associated with the clipboard file store is deleted. */
       
   267     {
       
   268 	delete iStreamDictionary;
       
   269 	CFileStore* store=iStore;
       
   270 	if (store!=NULL)
       
   271 		{
       
   272 		TBool rollback=(store->Root()==KNullStreamId);
       
   273    		delete store;
       
   274 		if (rollback)	// useless clipboard, no root stream
       
   275 			{
       
   276 			TDriveName clipboardDrive = ClipboardFileDrive();
       
   277 			TFileName clipboardFile(KClipboardFileName);
       
   278 			clipboardFile.Insert(0,clipboardDrive);
       
   279 			
       
   280 			iFs.Delete(clipboardFile);
       
   281 			}
       
   282 		}
       
   283     }
       
   284 
       
   285 EXPORT_C void CClipboard::CommitL()
       
   286 /** Commits changes to the clipboard's store.
       
   287 
       
   288 It externalises the stream dictionary to the clipboard store as the root stream 
       
   289 and then commits all changes to the store. This function must be called after 
       
   290 application data has been externalised; failure to do so results in the deletion 
       
   291 of the file associated with the clipboard store and the loss of data. */
       
   292 	{
       
   293 	__ASSERT_DEBUG(iStore!=NULL&&iStreamDictionary!=NULL,User::Invariant());
       
   294 //
       
   295 	CFileStore& store=*iStore;
       
   296 	RStoreWriteStream stream;
       
   297 	TStreamId root=stream.CreateLC(store);
       
   298 	stream<< *iStreamDictionary;
       
   299 	stream.CommitL();
       
   300 	CleanupStack::PopAndDestroy(); // dictionary stream
       
   301 	store.SetRootL(root);
       
   302 	store.CommitL();
       
   303 	}
       
   304 
       
   305 
       
   306 // Copy and paste member functions for low level data types
       
   307 
       
   308 
       
   309 const TUid KClipboardRealTypeUid = { 268435705 };
       
   310 
       
   311 
       
   312 EXPORT_C void  CClipboard::CopyToL(TReal aReal) __SOFTFP
       
   313 /** Copies a double-precision floating point value to the clipboard.
       
   314 
       
   315 Note that the function does not automatically commit changes to the clipboard's 
       
   316 store. This must be done explicitly.
       
   317 
       
   318 @param aReal The double-precision floating point value to be copied to the 
       
   319 clipboard.
       
   320 @see CommitL() */
       
   321     {
       
   322 	__ASSERT_DEBUG(iStore!=NULL&&iStreamDictionary!=NULL,User::Invariant());
       
   323 //
       
   324     RStoreWriteStream stream;
       
   325     TStreamId id = stream.CreateLC ( Store() );
       
   326     stream << aReal;
       
   327 	stream.CommitL();
       
   328     CleanupStack::PopAndDestroy();
       
   329     StreamDictionary().AssignL ( KClipboardRealTypeUid, id );
       
   330     }
       
   331 
       
   332 EXPORT_C TBool CClipboard::PasteFromL  ( TReal& aReal )
       
   333 /** Pastes a double-precision floating point value from the clipboard.
       
   334 
       
   335 If a double-precision floating point value exists on the clipboard, then the 
       
   336 function restores it to the referenced argument and returns a true value.
       
   337 
       
   338 If there is no double-precision floating point value on the clipboard, then 
       
   339 the function returns a false value. The referenced argument is not changed.
       
   340 
       
   341 @param aReal On return, contains the double-precision floating point value 
       
   342 found on the clipboard.
       
   343 @return ETrue, if a double-precision floating point value exists on the 
       
   344 clipboard and has been pasted to the referenced argument; EFalse otherwise. */
       
   345     {
       
   346 	__ASSERT_DEBUG(iStreamDictionary!=NULL,User::Invariant());
       
   347     TStreamId id = StreamDictionary().At(KClipboardRealTypeUid);
       
   348     if (id == KNullStreamId)
       
   349 		return (EFalse); // nothing here
       
   350     __ASSERT_DEBUG(iStore!=NULL,User::Invariant());
       
   351 	RStoreReadStream stream;
       
   352     stream.OpenLC (Store(), id);
       
   353     stream >> aReal;
       
   354     CleanupStack::PopAndDestroy();
       
   355     return (ETrue);
       
   356     }
       
   357 
       
   358 
       
   359 
       
   360 // end of BACLIPB.CPP