4#include "Stroika/Frameworks/StroikaPreComp.h"
8#include "Stroika/Foundation/Characters/LineEndings.h"
14#if qStroika_Foundation_Common_Platform_Windows
18#elif qStroika_FeatureSupported_XWindows
28#include "FlavorPackage.h"
35using namespace Stroika::Frameworks;
36using namespace Stroika::Frameworks::Led;
44TextStore* FlavorPackageExternalizer::PeekAtTextStore ()
const
55void FlavorPackageExternalizer::ExternalizeFlavors (
WriterFlavorPackage& flavorPackage,
size_t from,
size_t to)
57 ExternalizeFlavor_TEXT (flavorPackage, from, to);
66void FlavorPackageExternalizer::ExternalizeBestFlavor (
WriterFlavorPackage& flavorPackage,
size_t from,
size_t to)
68 ExternalizeFlavor_TEXT (flavorPackage, from, to);
79void FlavorPackageExternalizer::ExternalizeFlavor_TEXT (
WriterFlavorPackage& flavorPackage,
size_t from,
size_t to)
84 Require (end <= GetTextStore ().GetEnd ());
85 Require (start <= end);
86 size_t length = end - start;
87#if qStroika_Foundation_Common_Platform_Windows
94 GetTextStore ().CopyOut (start, length, buf2.data ());
95#if qStroika_FeatureSupported_XWindows
96 length = Characters::NLToNative<Led_tChar> (buf2, length, buf, length);
97#elif qStroika_Foundation_Common_Platform_Windows
98 length = Characters::NLToNative<Led_tChar> (buf2.data (), length, buf.data (), 2 * length + 1);
106 length = Led_SkrunchOutSpecialChars (buf.data (), length,
'\0');
108#if qStroika_Foundation_Common_Platform_Windows
112 flavorPackage.AddFlavorData (kTEXTClipFormat, length *
sizeof (Led_tChar), buf.data ());
120TextStore* FlavorPackageInternalizer::PeekAtTextStore ()
const
125bool FlavorPackageInternalizer::InternalizeBestFlavor (
ReaderFlavorPackage& flavorPackage,
size_t from,
size_t to)
127 if (InternalizeFlavor_FILE (flavorPackage, from, to)) {
130 else if (InternalizeFlavor_TEXT (flavorPackage, from, to)) {
136bool FlavorPackageInternalizer::InternalizeFlavor_TEXT (
ReaderFlavorPackage& flavorPackage,
size_t from,
size_t to)
138 if (flavorPackage.GetFlavorAvailable_TEXT ()) {
139 size_t length = flavorPackage.
GetFlavorSize (kTEXTClipFormat);
140 Led_ClipFormat textFormat = kTEXTClipFormat;
145 length = flavorPackage.ReadFlavorData (textFormat, length, buf.data ());
147 Led_tChar* buffp =
reinterpret_cast<Led_tChar*
> (
static_cast<char*
> (buf));
148 size_t nTChars = length /
sizeof (Led_tChar);
149#if qStroika_Foundation_Common_Platform_Windows
154 nTChars = min (nTChars, Led_tStrlen (buffp));
160 Require (start <= end);
162 nTChars = Characters::NormalizeTextToNL<Led_tChar> (buffp, nTChars, buffp, nTChars);
163 GetTextStore ().Replace (start, end, buffp, nTChars);
171bool FlavorPackageInternalizer::InternalizeFlavor_FILE (
ReaderFlavorPackage& flavorPackage,
size_t from,
size_t to)
174 if (flavorPackage.GetFlavorAvailable (kFILEClipFormat)) {
175 size_t fileSpecBufferLength = flavorPackage.
GetFlavorSize (kFILEClipFormat);
177 fileSpecBufferLength = flavorPackage.ReadFlavorData (kFILEClipFormat, fileSpecBufferLength, fileSpecBuffer.data ());
180#if qStroika_Foundation_Common_Platform_Windows
181 TCHAR realFileName[_MAX_PATH + 1];
183 HDROP hdrop = (HDROP)::GlobalAlloc (GMEM_FIXED, fileSpecBufferLength);
185 (void)::memcpy (hdrop, fileSpecBuffer.data (), fileSpecBufferLength);
186 size_t nChars = ::DragQueryFile (hdrop, 0,
nullptr, 0);
187 Verify (::DragQueryFile (hdrop, 0, realFileName,
static_cast<UINT
> (nChars + 1)) == nChars);
188 ::GlobalFree (hdrop);
190 Led_ClipFormat suggestedClipFormat = kBadClipFormat;
192 char realFileName[1000];
193 realFileName[0] =
'\0';
194 Led_ClipFormat suggestedClipFormat = kBadClipFormat;
197 return InternalizeFlavor_FILEData (realFileName, &suggestedClipFormat, nullopt, from, to);
204bool FlavorPackageInternalizer::InternalizeFlavor_FILEData (filesystem::path fileName, Led_ClipFormat* suggestedClipFormat,
205 optional<CodePage> suggestedCodePage,
size_t from,
size_t to)
207 Memory::BLOB b = IO::FileSystem::FileInputStream::New (filesystem::path (fileName)).ReadAll ();
208 const byte* fileBuf = b.
begin ();
209 size_t fileLen = b.
size ();
211 InternalizeFlavor_FILEGuessFormatsFromName (fileName, suggestedClipFormat, suggestedCodePage);
215 InternalizeFlavor_FILEGuessFormatsFromStartOfData (suggestedClipFormat, suggestedCodePage, fileBuf, fileBuf + fileLen);
220 return InternalizeFlavor_FILEDataRawBytes (suggestedClipFormat, suggestedCodePage, from, to, fileBuf, fileLen);
223void FlavorPackageInternalizer::InternalizeFlavor_FILEGuessFormatsFromName (filesystem::path fileName, Led_ClipFormat* suggestedClipFormat,
224 [[maybe_unused]] optional<CodePage> suggestedCodePage)
226#if qStroika_Foundation_Common_Platform_Windows
227 if (suggestedClipFormat !=
nullptr and *suggestedClipFormat == kBadClipFormat) {
228 TCHAR drive[_MAX_DRIVE];
230 TCHAR fname[_MAX_FNAME];
232 ::_tsplitpath_s (fileName.native ().c_str (), drive, dir, fname, ext);
233 if (::_tcsicmp (ext, Led_SDK_TCHAROF (
".txt")) == 0) {
234 *suggestedClipFormat = kTEXTClipFormat;
240void FlavorPackageInternalizer::InternalizeFlavor_FILEGuessFormatsFromStartOfData (Led_ClipFormat* suggestedClipFormat,
241 [[maybe_unused]] optional<CodePage> suggestedCodePage,
242 const byte* ,
const byte*
245 if (suggestedClipFormat !=
nullptr) {
246 if (*suggestedClipFormat == kBadClipFormat) {
254bool FlavorPackageInternalizer::InternalizeFlavor_FILEDataRawBytes (Led_ClipFormat* suggestedClipFormat, optional<CodePage> suggestedCodePage,
255 size_t from,
size_t to,
const void* rawBytes,
size_t nRawBytes)
264 Led_ClipFormat cf = (suggestedClipFormat ==
nullptr or *suggestedClipFormat == kBadClipFormat) ? kTEXTClipFormat : *suggestedClipFormat;
265 if (cf != kTEXTClipFormat) {
267 package.AddFlavorData (cf, nRawBytes, rawBytes);
268 if (InternalizeBestFlavor (package, from, to)) {
280 span<const byte> rawByteSpan{
reinterpret_cast<const byte*
> (rawBytes), nRawBytes};
281#if qStroika_Foundation_Common_Platform_Windows
286 size_t outCharCnt = converter.ComputeTargetCharacterBufferSize (rawByteSpan);
288 auto charsRead = converter.Bytes2Characters (&rawByteSpan, span{fileData2}).size ();
289 charsRead = Characters::NormalizeTextToNL<Led_tChar> (fileData2.data (), charsRead, fileData2.data (), charsRead);
290 GetTextStore ().Replace (from, to, fileData2.data (), charsRead);
294#if qStroika_Frameworks_Led_SupportClipboard
300#if qStroika_FeatureSupported_XWindows
301map<Led_ClipFormat, vector<char>> ReaderClipboardFlavorPackage::sPrivateClipData;
304bool ReaderClipboardFlavorPackage::GetFlavorAvailable (Led_ClipFormat clipFormat)
const
306#if qStroika_FeatureSupported_XWindows
307 map<Led_ClipFormat, vector<char>>::const_iterator i = sPrivateClipData.find (clipFormat);
308 return (i != sPrivateClipData.end ());
310 return Led_ClipboardObjectAcquire::FormatAvailable (clipFormat);
314size_t ReaderClipboardFlavorPackage::GetFlavorSize (Led_ClipFormat clipFormat)
const
316#if qStroika_FeatureSupported_XWindows
317 map<Led_ClipFormat, vector<char>>::const_iterator i = sPrivateClipData.find (clipFormat);
318 if (i == sPrivateClipData.end ()) {
322 return i->second.size ();
325 Led_ClipboardObjectAcquire clip (clipFormat);
326 if (clip.GoodClip ()) {
327 return clip.GetDataLength ();
335size_t ReaderClipboardFlavorPackage::ReadFlavorData (Led_ClipFormat clipFormat,
size_t bufSize,
void* buf)
const
337#if qStroika_FeatureSupported_XWindows
338 map<Led_ClipFormat, vector<char>>::const_iterator i = sPrivateClipData.find (clipFormat);
339 if (i == sPrivateClipData.end ()) {
343 size_t copyNBytes = min (bufSize, i->second.size ());
344 (void)::memcpy (buf, Traversal::Iterator2Pointer (i->second.begin ()), copyNBytes);
345 Ensure (copyNBytes <= bufSize);
349 Led_ClipboardObjectAcquire clip{clipFormat};
350 if (clip.GoodClip ()) {
351 size_t copyNBytes = min (bufSize, clip.GetDataLength ());
352 (void)::memcpy (buf, clip.GetData (), copyNBytes);
353 Ensure (copyNBytes <= bufSize);
363#if qStroika_Frameworks_Led_SupportClipboard
369void WriterClipboardFlavorPackage::AddFlavorData (Led_ClipFormat clipFormat,
size_t bufSize,
const void* buf)
371#if qStroika_Foundation_Common_Platform_Windows
374 HANDLE h = ::GlobalAlloc (GHND | GMEM_MOVEABLE, bufSize);
377 char* clipBuf = (
char*)::GlobalLock (h);
378 if (clipBuf ==
nullptr) {
382 memcpy (clipBuf, buf, bufSize);
385 if (::SetClipboardData (clipFormat, h) ==
nullptr) {
386 DWORD err = ::GetLastError ();
389#elif qStroika_FeatureSupported_XWindows
390 ReaderClipboardFlavorPackage::sPrivateClipData.insert (map<Led_ClipFormat, vector<char>>::value_type (
391 clipFormat, vector<char> (
reinterpret_cast<const char*
> (buf),
reinterpret_cast<const char*
> (buf) + bufSize)));
401ReadWriteMemBufferPackage::ReadWriteMemBufferPackage ()
414 fPackages.reserve (1);
417ReadWriteMemBufferPackage::~ReadWriteMemBufferPackage ()
421bool ReadWriteMemBufferPackage::GetFlavorAvailable (Led_ClipFormat clipFormat)
const
423 for (
size_t i = 0; i < fPackages.size (); i++) {
424 if (fPackages[i].fFormat == clipFormat) {
433 for (
size_t i = 0; i < fPackages.size (); i++) {
434 if (fPackages[i].fFormat == clipFormat) {
435 return fPackages[i].fData.size ();
442size_t ReadWriteMemBufferPackage::ReadFlavorData (Led_ClipFormat clipFormat,
size_t bufSize,
void* buf)
const
444 for (
size_t i = 0; i < fPackages.size (); i++) {
445 if (fPackages[i].fFormat == clipFormat) {
446 size_t copyNBytes = min (bufSize, fPackages[i].fData.size ());
447 memcpy (buf, Traversal::Iterator2Pointer (fPackages[i].fData.begin ()), copyNBytes);
448 Ensure (copyNBytes <= bufSize);
456void ReadWriteMemBufferPackage::AddFlavorData (Led_ClipFormat clipFormat,
size_t bufSize,
const void* buf)
459 pr.fFormat = clipFormat;
460 const char* cb =
reinterpret_cast<const char*
> (buf);
461 pr.fData = vector<char> (cb, cb + bufSize);
462 fPackages.push_back (pr);
CodeCvt unifies byte <-> unicode conversions, vaguely inspired by (and wraps) std::codecvt,...
nonvirtual const byte * begin() const
nonvirtual size_t size() const
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
virtual size_t GetFlavorSize(Led_ClipFormat clipFormat) const override
virtual size_t GetFlavorSize(Led_ClipFormat clipFormat) const =0
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
void ThrowIfNull(const Private_::ConstVoidStar &p, const HRESULT &hr)
Template specialization for ThrowIfNull (), for thing being thrown HRESULT - really throw HRESULTErro...