// 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);
}