libraries/ltkutils/src/clipboard.cpp
changeset 0 7f656887cf89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libraries/ltkutils/src/clipboard.cpp	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,158 @@
+// clipboard.cpp
+// 
+// Copyright (c) 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "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:
+// Accenture - Initial contribution
+//
+#include <fshell/ltkutils.h>
+#include <baclipb.h>
+#include <S32MEM.H>
+#include <S32UCMP.H>
+const TUid KClipboardUidTypePlainText = {268450333}; // from TXTETEXT.h
+
+// This could probably be optimised away, but I don't feel that confident
+NONSHARABLE_CLASS(TFieldMapExternalizer) : public MExternalizer<TStreamRef>
+	{
+public:
+	TFieldMapExternalizer(const CStoreMap& aMap);
+	void ExternalizeL(const TStreamRef& anObject,RWriteStream& aStream) const;
+private:
+	const CStoreMap* iMap;
+	};
+
+RFs OpenFsIfNeededLC(RFs* aFsPtr)
+	{
+	if (!aFsPtr)
+		{
+		RFs stackFs;
+		CleanupClosePushL(stackFs);
+		User::LeaveIfError(stackFs.Connect());
+		return stackFs;
+		}
+	else
+		{
+		CleanupStack::PushL((CBase*)NULL); // Just so the cleanup stack is the same depth in both cases - this is ok to destroy
+		return *aFsPtr;
+		}
+	}
+
+
+EXPORT_C void LtkUtils::CopyToClipboardL(const TDesC& aText, RFs* aFs)
+	{
+	/*
+	The simple way of implementing this is as follows. However this gives you a dependancy on etext.dll so is not desirable
+
+	CClipboard* cb = CClipboard::NewForWritingLC(FsL());
+	CPlainText* text = CPlainText::NewL();
+	CleanupStack::PushL(text);
+	text->InsertL(0, aText);
+	text->CopyToStoreL(cb->Store(), cb->StreamDictionary(), 0, text->DocumentLength());
+	cb->CommitL();
+	CleanupStack::PopAndDestroy(2, cb); // text, cb
+	*/
+
+	RFs fs = OpenFsIfNeededLC(aFs);
+	CClipboard* cb = CClipboard::NewForWritingLC(fs);
+	CStreamStore& store = cb->Store();
+	CStreamDictionary& dictionary = cb->StreamDictionary();
+	// Following adapted from CPlainText::DoCopyToStoreL
+	if (aText.Length())
+		{
+		CStoreMap* map=CStoreMap::NewLC(store);
+		//CopyComponentsL(aStore,*map,aPos,aLength);
+
+		// create custom externalizer over the map
+		TFieldMapExternalizer fMap(*map);
+		RStoreWriteStream stream(fMap);
+		TStreamId id=stream.CreateLC(store);
+		//CopyToStreamL(stream,aPos,aLength);
+		stream.WriteInt32L(aText.Length());
+		CBufFlat* textBuf = CBufFlat::NewL(256);
+		CleanupStack::PushL(textBuf);
+		textBuf->InsertL(0, TPtrC8((const TText8*)aText.Ptr(), aText.Size()));
+		RBufReadStream input_stream(*textBuf, 0);
+		TMemoryStreamUnicodeSource source(input_stream);
+		TUnicodeCompressor c;
+		c.CompressL(stream,source,KMaxTInt,aText.Length());
+		input_stream.Close();
+		stream.WriteUint8L(EFalse); // Indicating !fieldSetPresent
+		CleanupStack::PopAndDestroy(textBuf);
+		stream.CommitL();
+
+		dictionary.AssignL(KClipboardUidTypePlainText,id);
+		map->Reset();
+		CleanupStack::PopAndDestroy(2);
+		}
+	cb->CommitL();
+	CleanupStack::PopAndDestroy(cb);
+	CleanupStack::PopAndDestroy(); // stackfs
+	}
+
+EXPORT_C HBufC* LtkUtils::GetFromClipboardL(RFs* aFs)
+	{
+	/*
+	The simple way of implementing this is as follows. However this gives you a dependancy on etext.dll so is not desirable
+
+	CClipboard* cb = CClipboard::NewForReadingLC(FsL());
+	CPlainText* text = CPlainText::NewL();
+	CleanupStack::PushL(text);
+	text->PasteFromStoreL(cb->Store(), cb->StreamDictionary(), 0);
+	HBufC* res = HBufC::NewL(text->DocumentLength());
+	TPtr ptr(res->Des());
+	text->Extract(ptr, 0);
+	CleanupStack::PopAndDestroy(2, cb); // text, cb
+	return res;
+	*/
+
+	RFs fs = OpenFsIfNeededLC(aFs);
+	HBufC* result = NULL;
+	CClipboard* cb = CClipboard::NewForReadingLC(fs);
+	CStreamStore& store = cb->Store();
+	CStreamDictionary& dictionary = cb->StreamDictionary();
+
+	// Adapted from CPlainText::PasteFromStoreL, 
+	TStreamId id=dictionary.At(KClipboardUidTypePlainText);
+	if (id != KNullStreamId)
+		{
+		RStoreReadStream stream;
+		stream.OpenLC(store, id);
+		CBufSeg* buffer = CBufSeg::NewL(512);
+		CleanupStack::PushL(buffer);
+		TInt length = stream.ReadInt32L();
+		RBufWriteStream output_stream(*buffer);
+		TMemoryStreamUnicodeSink sink(output_stream);
+		TUnicodeExpander e;
+		e.ExpandL(sink,stream,length);
+		output_stream.CommitL();
+		output_stream.Close();
+
+		result = HBufC::NewMaxL(buffer->Size()/sizeof(TText));
+		TPtr8 ptr = TPtr8((TText8*)result->Ptr(), 0, buffer->Size());
+		buffer->Read(0, ptr);
+		
+		CleanupStack::PopAndDestroy(2, &stream); // buffer, stream
+		}
+
+	CleanupStack::PopAndDestroy(cb);
+	CleanupStack::PopAndDestroy(); // OpenFsIfNeededLC
+	if (!result) result = KNullDesC().AllocL();
+	return result;
+	}
+
+
+TFieldMapExternalizer::TFieldMapExternalizer(const CStoreMap& aMap)
+	: iMap(&aMap)
+	{}
+
+void TFieldMapExternalizer::ExternalizeL(const TStreamRef& aRef,RWriteStream& aStream) const
+// Write the stream id bound to aRef to aStream. If not bound, write KNullStreamId
+//
+	{
+	TSwizzleC<TAny> swizzle=aRef;
+	aStream<<iMap->At(swizzle);
+	}