4#include "Stroika/Frameworks/StroikaPreComp.h"
12#if qStroika_Foundation_Common_Platform_Windows
13#include "Stroika/Foundation/Characters/Platform/Windows/CodePage.h"
18#include "Stroika/Foundation/DataExchange/BadFormatException.h"
19#if qStroika_Foundation_Common_Platform_Windows
20#include "Stroika/Foundation/Execution/Platform/Windows/Exception.h"
23#include "Stroika/Frameworks/Led/Config.h"
25#include "Stroika/Frameworks/Led/Support.h"
27#include "StyledTextIO_RTF.h"
29#define qUseCompiledSetHack true
34using namespace Stroika::Frameworks;
35using namespace Stroika::Frameworks::Led;
36using namespace Stroika::Frameworks::Led::StyledTextIO;
38#if qStroika_Foundation_Common_Platform_Windows
43 inline int ConvertReadSingleHexDigit_ (
char digit)
45 if (isupper (digit)) {
46 digit =
static_cast<char> (tolower (digit));
48 if (isdigit (digit)) {
51 else if (islower (digit)) {
52 return 10 + (digit -
'a');
60 inline char ConvertWriteSingleHexDigit_ (
int numZeroToFifteen)
62 Require (numZeroToFifteen >= 0);
63 Require (numZeroToFifteen <= 15);
64 if (numZeroToFifteen < 10) {
65 return static_cast<char> (
'0' + numZeroToFifteen);
68 return static_cast<char> (
'a' + (numZeroToFifteen - 10));
73 inline static LineSpacing mkLineSpacing_From_RTFValues_ (CoordinateType sl,
bool multi)
84 if (sl < 0 or sl > 2000) {
87 result = LineSpacing (LineSpacing::eExactLinesSpacing, sl / 12);
91 result = LineSpacing (LineSpacing::eExactTWIPSSpacing, TWIPS (-sl));
94 result = LineSpacing (LineSpacing::eAtLeastTWIPSSpacing, TWIPS (sl));
100 inline static void mkRTFValues_From_LineSpacing (LineSpacing inLS, CoordinateType* sl,
bool* multi)
102 const int kOneLinesWorth = 240;
103 switch (inLS.fRule) {
104 case LineSpacing::eOnePointFiveSpace:
105 *sl =
static_cast<CoordinateType
> (kOneLinesWorth * 1.5);
108 case LineSpacing::eDoubleSpace:
109 *sl = kOneLinesWorth * 2;
112 case LineSpacing::eAtLeastTWIPSSpacing:
116 case LineSpacing::eExactTWIPSSpacing:
117 *sl = -
static_cast<CoordinateType
> (inLS.fArg);
120 case LineSpacing::eExactLinesSpacing:
121 *sl = inLS.fArg * 12;
126 case LineSpacing::eSingleSpace:
139RTFIO::FontTableEntry::FontTableEntry ()
143 , fCharSet (static_cast<uint8_t> (-1))
154using FontTableEntry = RTFIO::FontTableEntry;
155using FontTable = RTFIO::FontTable;
156FontTable::FontTable ()
161FontTable::FontTable (
const vector<FontTableEntry>& fontTable)
162 : fEntries{fontTable}
166IncrementalFontSpecification FontTable::GetFontSpec (
int fontNumber)
168 const FontTableEntry* ftep = LookupEntryByNumber (fontNumber);
169 if (ftep ==
nullptr) {
170 return IncrementalFontSpecification{};
172 IncrementalFontSpecification fontSpec;
173#if qStroika_Foundation_Common_Platform_Windows || qStroika_FeatureSupported_XWindows
174 fontSpec.SetFontNameSpecifier (ftep->fFontName.c_str ());
179const FontTableEntry* FontTable::LookupEntryByNumber (
int fontNumber)
181 for (
size_t i = 0; i < fEntries.size (); ++i) {
182 const FontTableEntry& fte = fEntries[i];
183 if (fte.fFNum == fontNumber) {
190const FontTableEntry* FontTable::LookupEntryByName (
const SDKString& name)
192 for (
size_t i = 0; i < fEntries.size (); ++i) {
193 const FontTableEntry& fte = fEntries[i];
194 if (fte.fFontName == name) {
201FontTableEntry FontTable::Add (
const FontTableEntry& newEntry)
203 int newFontNumber = FindSmallestUnusedFontNumber ();
204 FontTableEntry newerEntry = newEntry;
205 newerEntry.fFNum = newFontNumber;
206 fEntries.push_back (newerEntry);
210int FontTable::FindSmallestUnusedFontNumber ()
const
215 for (
size_t i = 0; i < fEntries.size (); ++i) {
216 const FontTableEntry& fte = fEntries[i];
217 if (fte.fFNum == tryThis) {
230RTFIO::ColorTable::ColorTable ()
235RTFIO::ColorTable::ColorTable (
const vector<Color>& colorTable)
236 : fEntries (colorTable)
240Color RTFIO::ColorTable::LookupColor (
size_t colorNumber)
const
242 if (colorNumber < 0 or colorNumber >= fEntries.size ()) {
245 return fEntries[colorNumber];
248size_t RTFIO::ColorTable::LookupColor (
const Color& color)
const
250 for (
size_t i = 0; i < fEntries.size (); ++i) {
251 const Color& c = fEntries[i];
260size_t RTFIO::ColorTable::EnterColor (
const Color& color)
262 for (
size_t i = 0; i < fEntries.size (); ++i) {
263 const Color& c = fEntries[i];
268 fEntries.push_back (color);
269 return fEntries.size () - 1;
278RTFIO::ListTableEntry::ListTableEntry ()
280 , fListTemplateID (0)
281 , fListStyle (eListStyle_None)
291RTFIO::ListOverrideTableEntry::ListOverrideTableEntry ()
301RTFIO::ListTables::ListTables ()
303 , fOverrideEntries ()
307RTFIO::ListTables::ListTables (
const vector<ListTableEntry>& listTableEntries,
const vector<ListOverrideTableEntry>& listOverrideTableEntries)
308 : fEntries (listTableEntries)
309 , fOverrideEntries (listOverrideTableEntries)
318#if qStroika_Frameworks_Led_SupportGDI
319const Led_PrivateEmbeddingTag RTFIO::kRTFBodyGroupFragmentEmbeddingTag =
"RTFBFrag";
320#if qStroika_Foundation_Common_Platform_Windows
321const Led_ClipFormat RTFIO::kRTFBodyGroupFragmentClipFormat =
static_cast<Led_ClipFormat
> (::RegisterClipboardFormat (_T(
"RTFF")));
323const Led_ClipFormat RTFIO::kRTFBodyGroupFragmentClipFormat =
static_cast<Led_ClipFormat
> (
'RTFF');
327inline RTFIO::ControlWordNameMap RTFIO::mkDefaultControlWordNameMap ()
329 RTFIO::ControlWordNameMap table;
330#if qUseMapForControlWordMap
331#define TAB_INS_METHOD(name) \
332 Assert (table.size () == RTFIO::eControlAtom_##name); \
333 table.insert (ControlWordNameMap::value_type (#name, RTFIO::eControlAtom_##name))
335#define TAB_INS_METHOD(name) \
336 Assert (table.size () == RTFIO::eControlAtom_##name); \
337 table.push_back (ControlWordNameMap::value_type (#name, RTFIO::eControlAtom_##name))
340 TAB_INS_METHOD (tab);
341 TAB_INS_METHOD (bullet);
342 TAB_INS_METHOD (endash);
343 TAB_INS_METHOD (emdash);
344 TAB_INS_METHOD (lquote);
345 TAB_INS_METHOD (rquote);
346 TAB_INS_METHOD (ldblquote);
347 TAB_INS_METHOD (rdblquote);
349 TAB_INS_METHOD (ansi);
350 TAB_INS_METHOD (author);
352 TAB_INS_METHOD (blue);
353 TAB_INS_METHOD (brdrs);
354 TAB_INS_METHOD (brdrth);
355 TAB_INS_METHOD (brdrsh);
356 TAB_INS_METHOD (brdrdb);
357 TAB_INS_METHOD (brdrdot);
358 TAB_INS_METHOD (brdrdash);
359 TAB_INS_METHOD (brdrhair);
360 TAB_INS_METHOD (brdrdashsm);
361 TAB_INS_METHOD (brdrdashd);
362 TAB_INS_METHOD (brdrdashdd);
363 TAB_INS_METHOD (brdrtriple);
364 TAB_INS_METHOD (brdrtnthsg);
365 TAB_INS_METHOD (brdrthtnsg);
366 TAB_INS_METHOD (brdrtnthtnsg);
367 TAB_INS_METHOD (brdrtnthmg);
368 TAB_INS_METHOD (brdrthtnmg);
369 TAB_INS_METHOD (brdrtnthtnmg);
370 TAB_INS_METHOD (brdrtnthlg);
371 TAB_INS_METHOD (brdrthtnlg);
372 TAB_INS_METHOD (brdrtnthtnlg);
373 TAB_INS_METHOD (brdrwavy);
374 TAB_INS_METHOD (brdrwavydb);
375 TAB_INS_METHOD (brdrdashdotstr);
376 TAB_INS_METHOD (brdremboss);
377 TAB_INS_METHOD (brdrengrave);
378 TAB_INS_METHOD (brdrw);
379 TAB_INS_METHOD (brdrcf);
380 TAB_INS_METHOD (cchs);
381 TAB_INS_METHOD (cell);
382 TAB_INS_METHOD (cellx);
384 TAB_INS_METHOD (clcbpat);
385 TAB_INS_METHOD (cpg);
386 TAB_INS_METHOD (colortbl);
387 TAB_INS_METHOD (deff);
388 TAB_INS_METHOD (deflang);
389 TAB_INS_METHOD (deftab);
390 TAB_INS_METHOD (deleted);
391 TAB_INS_METHOD (dibitmap);
393 TAB_INS_METHOD (emfblip);
395 TAB_INS_METHOD (fbidi);
396 TAB_INS_METHOD (fcharset);
397 TAB_INS_METHOD (fdecor);
399 TAB_INS_METHOD (fmodern);
400 TAB_INS_METHOD (footer);
401 TAB_INS_METHOD (fnil);
402 TAB_INS_METHOD (fonttbl);
403 TAB_INS_METHOD (fprq);
404 TAB_INS_METHOD (froman);
406 TAB_INS_METHOD (fswiss);
407 TAB_INS_METHOD (fscript);
408 TAB_INS_METHOD (ftech);
409 TAB_INS_METHOD (green);
410 TAB_INS_METHOD (header);
412 TAB_INS_METHOD (ilvl);
413 TAB_INS_METHOD (info);
414 TAB_INS_METHOD (intbl);
415 TAB_INS_METHOD (jpegblip);
417 TAB_INS_METHOD (line);
418 TAB_INS_METHOD (listtext);
419 TAB_INS_METHOD (ledprivateobjectembeddingformat);
421 TAB_INS_METHOD (mac);
422 TAB_INS_METHOD (macpict);
423 TAB_INS_METHOD (margb);
424 TAB_INS_METHOD (margl);
425 TAB_INS_METHOD (margr);
426 TAB_INS_METHOD (margt);
427 TAB_INS_METHOD (objdata);
428 TAB_INS_METHOD (
object);
429 TAB_INS_METHOD (objemb);
430 TAB_INS_METHOD (objh);
431 TAB_INS_METHOD (objscalex);
432 TAB_INS_METHOD (objscaley);
433 TAB_INS_METHOD (objw);
434 TAB_INS_METHOD (outl);
435 TAB_INS_METHOD (paperh);
436 TAB_INS_METHOD (paperw);
437 TAB_INS_METHOD (par);
438 TAB_INS_METHOD (pard);
440 TAB_INS_METHOD (pca);
441 TAB_INS_METHOD (pich);
442 TAB_INS_METHOD (pichgoal);
443 TAB_INS_METHOD (picscalex);
444 TAB_INS_METHOD (picscaley);
445 TAB_INS_METHOD (pict);
446 TAB_INS_METHOD (picw);
447 TAB_INS_METHOD (picwgoal);
448 TAB_INS_METHOD (plain);
449 TAB_INS_METHOD (pmmetafile);
451 TAB_INS_METHOD (pngblip);
452 TAB_INS_METHOD (pntext);
457 TAB_INS_METHOD (red);
458 TAB_INS_METHOD (result);
460 TAB_INS_METHOD (row);
461 TAB_INS_METHOD (rtf);
464 TAB_INS_METHOD (shad);
466 TAB_INS_METHOD (slmult);
467 TAB_INS_METHOD (sub);
468 TAB_INS_METHOD (super);
469 TAB_INS_METHOD (strike);
470 TAB_INS_METHOD (stylesheet);
471 TAB_INS_METHOD (trleft);
472 TAB_INS_METHOD (trgaph);
473 TAB_INS_METHOD (trowd);
474 TAB_INS_METHOD (trpaddb);
475 TAB_INS_METHOD (trpaddl);
476 TAB_INS_METHOD (trpaddr);
477 TAB_INS_METHOD (trpaddt);
478 TAB_INS_METHOD (trspdb);
479 TAB_INS_METHOD (trspdl);
480 TAB_INS_METHOD (trspdr);
481 TAB_INS_METHOD (trspdt);
486 TAB_INS_METHOD (ulnone);
489 TAB_INS_METHOD (wbitmap);
490 TAB_INS_METHOD (wmetafile);
492 Assert (table.size () == RTFIO::eControlAtomDynamicRangeStart);
493#if !qUseMapForControlWordMap
494 sort (table.begin (), table.end ());
498RTFIO::ControlWordNameMap RTFIO::sControlWordNameMap = RTFIO::mkDefaultControlWordNameMap ();
500string RTFIO::GetAtomName (ControlWordAtom atom)
502 using ITER = RTFIO::ControlWordNameMap::const_iterator;
503 ITER start = sControlWordNameMap.begin ();
504 ITER end = sControlWordNameMap.end ();
505 for (ITER it = start; it != end; ++it) {
506 if (it->second == atom) {
507 return string{it->first};
514#if !qUseMapForControlWordMap
515struct RTFIO::StringNControlWordAtom_Comparator : binary_function<RTFIO::StringNControlWordAtom, const char*, bool> {
516 bool operator() (
const RTFIO::StringNControlWordAtom& x,
const char* y)
const
522RTFIO::ControlWordAtom RTFIO::EnterControlWord (
523#
if qUseMapForControlWordMap
524 const ControlWordAtomName& controlWord
526 const char* controlWord
530#if !qUseMapForControlWordMap
534 using ITER = ControlWordNameMap::iterator;
535#if qUseMapForControlWordMap
536 ITER i = sControlWordNameMap.find (controlWord);
537 if (i == sControlWordNameMap.end ()) {
538 ControlWordAtom newVal = ControlWordAtom (eControlAtomDynamicRangeStart + sControlWordNameMap.size ());
539 i = sControlWordNameMap.insert (ControlWordNameMap::value_type (controlWord, newVal)).first;
543 ITER start = sControlWordNameMap.begin ();
544 ITER end = sControlWordNameMap.end ();
545 ITER i = lower_bound (start, end, controlWord, StringNControlWordAtom_Comparator ());
546 if (i != end and controlWord == (*i).first) {
549 ControlWordAtom newVal = ControlWordAtom (eControlAtomDynamicRangeStart + sControlWordNameMap.size ());
550 sControlWordNameMap.insert (i, ControlWordNameMap::value_type (controlWord, newVal));
555#if qStroika_Frameworks_Led_SupportGDI
561const Led_PrivateEmbeddingTag RTFIO::RTFOLEEmbedding::kEmbeddingTag =
"OLE2RTFEm";
569using ReaderContext = StyledTextIOReader_RTF::ReaderContext;
599using SinkStreamDestination = ReaderContext::SinkStreamDestination;
600StyledTextIOReader_RTF::ReaderContext::SinkStreamDestination::SinkStreamDestination (StyledTextIOReader_RTF& reader)
602 , fSinkStream (reader.GetSinkStream ())
603 , fRTFInfo (reader.GetRTFInfo ())
608SinkStreamDestination::~SinkStreamDestination ()
613 Require (fTCharsInSmallBuffer == 0);
616void SinkStreamDestination::AppendText (
const Led_tChar* text,
size_t nTChars)
619 AppendText_ (text, nTChars);
622#if qStroika_Frameworks_Led_SupportGDI
623void SinkStreamDestination::AppendEmbedding (SimpleEmbeddedObjectStyleMarker* embedding)
632 fSinkStream.AppendEmbedding (embedding);
636void SinkStreamDestination::AppendSoftLineBreak ()
640 fSinkStream.AppendSoftLineBreak ();
643void SinkStreamDestination::EndParagraph ()
646 fParaEndedFlag =
true;
649void SinkStreamDestination::UseFont (
const IncrementalFontSpecification& fontSpec)
652 if (fCurrentContext.fFontSpec != fontSpec) {
654 fCurrentContext.fFontSpec = fontSpec;
658void SinkStreamDestination::SetJustification (Justification justification)
661 if (fCurrentContext.fJustification != justification) {
663 fSinkStream.SetJustification (fCurrentContext.fJustification = justification);
667void SinkStreamDestination::SetTabStops (
const StandardTabStopList& tabStops)
670 if (fCurrentContext.fTabStops != tabStops) {
672 fSinkStream.SetStandardTabStopList (fCurrentContext.fTabStops = tabStops);
676void SinkStreamDestination::SetFirstIndent (TWIPS tx)
679 if (fCurrentContext.fFirstIndent != tx) {
681 fSinkStream.SetFirstIndent (fCurrentContext.fFirstIndent = tx);
685void SinkStreamDestination::SetLeftMargin (TWIPS lhs)
688 if (fCurrentContext.fLeftMargin != lhs) {
690 fSinkStream.SetLeftMargin (fCurrentContext.fLeftMargin = lhs);
694void SinkStreamDestination::SetRightMargin (TWIPS rhs)
699 TWIPS effectivePaperSize = fRTFInfo.GetEffectiveDrawingWidth ();
700 TWIPS realMargin = TWIPS (effectivePaperSize - rhs);
701 if (realMargin < 0) {
702 realMargin = TWIPS (1);
704 fSinkStream.SetRightMargin (fCurrentContext.fRightMargin = realMargin);
707void SinkStreamDestination::SetSpaceBefore (TWIPS tx)
710 if (fCurrentContext.fSpaceBefore != tx) {
712 fSinkStream.SetSpaceBefore (fCurrentContext.fSpaceBefore = tx);
716void SinkStreamDestination::SetSpaceAfter (TWIPS tx)
719 if (fCurrentContext.fSpaceAfter != tx) {
721 fSinkStream.SetSpaceAfter (fCurrentContext.fSpaceAfter = tx);
725void SinkStreamDestination::SetSpaceBetweenLines (CoordinateType sl)
728 if (fCurrentContext.fSpaceBetweenLines != sl) {
730 fSinkStream.SetLineSpacing (mkLineSpacing_From_RTFValues_ (fCurrentContext.fSpaceBetweenLines = sl, fCurrentContext.fSpaceBetweenLinesMult));
734void SinkStreamDestination::SetSpaceBetweenLinesMult (
bool multipleLineSpacing)
737 if (fCurrentContext.fSpaceBetweenLinesMult != multipleLineSpacing) {
739 fSinkStream.SetLineSpacing (mkLineSpacing_From_RTFValues_ (fCurrentContext.fSpaceBetweenLines,
740 fCurrentContext.fSpaceBetweenLinesMult = multipleLineSpacing));
744void SinkStreamDestination::SetTextHidden (
bool hidden)
747 if (fCurrentContext.fTextHidden != hidden) {
749 fSinkStream.SetTextHidden (fCurrentContext.fTextHidden = hidden);
753void SinkStreamDestination::SetInTable (
bool inTable)
756 if (fInTable != inTable) {
762void SinkStreamDestination::EndRow (
bool forceEmit)
764 if (forceEmit and not fTableInRow) {
774 fSinkStream.EndTableRow ();
777 Ensure (not fTableInRow);
778 Ensure (not fTableInCell);
782void SinkStreamDestination::EndCell (
bool forceEmit)
784 if (forceEmit and not fTableInCell) {
786 if (not fTableInRow) {
794 size_t thisCellNum = fTableNextCellNum - 1;
795 if (thisCellNum < fThisRow.fCellInfosForThisRow.size ()) {
796 fSinkStream.SetCellBackColor (fThisRow.fCellInfosForThisRow[thisCellNum].f_clcbpat);
798 fSinkStream.EndTableCell ();
799 fTableInCell =
false;
803void SinkStreamDestination::SetListStyle (ListStyle listStyle)
806 if (fCurrentContext.fListStyle != listStyle) {
808 fSinkStream.SetListStyle (fCurrentContext.fListStyle = listStyle);
812void SinkStreamDestination::SetListIndentLevel (
unsigned char indentLevel)
815 if (fCurrentContext.fListIndentLevel != indentLevel) {
817 fSinkStream.SetListIndentLevel (fCurrentContext.fListIndentLevel = indentLevel);
821void SinkStreamDestination::SetTableBorderColor (
Color c)
825 fSinkStream.SetTableBorderColor (c);
828void SinkStreamDestination::SetCellX (TWIPS cellx)
838 TWIPS sub = TWIPS{0};
839 for (
auto i = fThisRow.fCellInfosForThisRow.begin (); i != fThisRow.fCellInfosForThisRow.end (); ++i) {
842 fNextCellInfo.f_cellx = cellx - sub;
845 fThisRow.fCellInfosForThisRow.push_back (fNextCellInfo);
847 fNextCellInfo = CellInfo ();
850void SinkStreamDestination::SetCellBackColor (
const Color& c)
853 fNextCellInfo.f_clcbpat = c;
856void SinkStreamDestination::Call_trowd ()
858 fNextCellInfo = CellInfo ();
859 fThisRow = RowInfo ();
862void SinkStreamDestination::Set_trleft (TWIPS t)
864 fThisRow.f_trleft = t;
867void SinkStreamDestination::SetDefaultCellMarginsForRow_top (TWIPS t)
869 fThisRow.fDefaultCellMargins.top = t;
872void SinkStreamDestination::SetDefaultCellMarginsForRow_left (TWIPS t)
874 fThisRow.fDefaultCellMargins.left = t;
877void SinkStreamDestination::SetDefaultCellMarginsForRow_bottom (TWIPS t)
879 fThisRow.fDefaultCellMargins.bottom = t;
882void SinkStreamDestination::SetDefaultCellMarginsForRow_right (TWIPS t)
884 fThisRow.fDefaultCellMargins.right = t;
887void SinkStreamDestination::SetDefaultCellSpacingForRow_top (TWIPS t)
890 fThisRow.fDefaultCellSpacing.top = TWIPS (t * 2);
893void SinkStreamDestination::SetDefaultCellSpacingForRow_left (TWIPS t)
896 fThisRow.fDefaultCellSpacing.left = TWIPS (t * 2);
899void SinkStreamDestination::SetDefaultCellSpacingForRow_bottom (TWIPS t)
902 fThisRow.fDefaultCellSpacing.bottom = TWIPS (t * 2);
905void SinkStreamDestination::SetDefaultCellSpacingForRow_right (TWIPS t)
908 fThisRow.fDefaultCellSpacing.right = TWIPS (t * 2);
911void SinkStreamDestination::AssureTableOpen ()
913 if (not fTableInRow and fTableNextRowNum == 0) {
914 fSinkStream.StartTable ();
919void SinkStreamDestination::DoStartRow ()
921 fSinkStream.StartTableRow ();
923 vector<TWIPS> cellWidths;
924 for (
auto i = fThisRow.fCellInfosForThisRow.begin (); i != fThisRow.fCellInfosForThisRow.end (); ++i) {
925 const TWIPS kMinWidth = TWIPS{0};
926 TWIPS thisCellW = (*i).f_cellx;
927 if (i == fThisRow.fCellInfosForThisRow.begin ()) {
928 thisCellW -= fThisRow.f_trleft;
934 thisCellW -= TWIPS (3 * fThisRow.fDefaultCellSpacing.left / 2);
936 if (thisCellW < kMinWidth) {
937 thisCellW = kMinWidth;
939 cellWidths.push_back (thisCellW);
941 fSinkStream.SetCellWidths (cellWidths);
942 fSinkStream.SetDefaultCellMarginsForCurrentRow (fThisRow.fDefaultCellMargins.top, fThisRow.fDefaultCellMargins.left,
943 fThisRow.fDefaultCellMargins.bottom, fThisRow.fDefaultCellMargins.right);
944 fSinkStream.SetDefaultCellSpacingForCurrentRow (fThisRow.fDefaultCellSpacing.top, fThisRow.fDefaultCellSpacing.left,
945 fThisRow.fDefaultCellSpacing.bottom, fThisRow.fDefaultCellSpacing.right);
948 fTableNextCellNum = 0;
952void SinkStreamDestination::DoStartCell ()
954 fSinkStream.StartTableCell (fThisRow.fCellInfosForThisRow[fTableNextCellNum].fColSpan);
959void SinkStreamDestination::DoEndTable ()
965 fSinkStream.EndTable ();
967 fTableNextCellNum = 0;
968 fTableNextRowNum = 0;
970 Ensure (not fTableInRow);
971 Ensure (not fTableOpen);
974void SinkStreamDestination::Flush ()
977 if (fTCharsInSmallBuffer != 0) {
979 fsp.MergeIn (fCurrentContext.fFontSpec);
980 fSinkStream.AppendText (fSmallBuffer, fTCharsInSmallBuffer, &fsp);
981 fTCharsInSmallBuffer = 0;
985void SinkStreamDestination::Done ()
987 fParaEndedFlag =
false;
989 fSinkStream.EndOfBuffer ();
993SinkStreamDestination::Context SinkStreamDestination::GetContext ()
const
995 return fCurrentContext;
998void SinkStreamDestination::SetContext (
const Context& c)
1000 fParaEndBeforeNewContext = fParaEndedFlag;
1002 fNewContextPending =
true;
1005void SinkStreamDestination::ApplyContext (
const Context& c)
1010 UseFont (c.fFontSpec);
1011 SetTabStops (c.fTabStops);
1012 SetJustification (c.fJustification);
1013 SetSpaceBefore (c.fSpaceBefore);
1014 SetSpaceAfter (c.fSpaceAfter);
1015 SetSpaceBetweenLines (c.fSpaceBetweenLines);
1016 SetSpaceBetweenLinesMult (c.fSpaceBetweenLinesMult);
1017 SetListStyle (c.fListStyle);
1018 SetListIndentLevel (c.fListIndentLevel);
1019 SetFirstIndent (c.fFirstIndent);
1020 SetLeftMargin (c.fLeftMargin);
1021 SetRightMargin (c.fRightMargin);
1022 SetTextHidden (c.fTextHidden);
1025size_t SinkStreamDestination::current_offset ()
const
1028 return fSinkStream.current_offset () + fTCharsInSmallBuffer;
1031void SinkStreamDestination::InsertMarker (Marker* m,
size_t at,
size_t length,
MarkerOwner* markerOwner)
1033 Require (at <= current_offset ());
1037 if (at + length >= fSinkStream.current_offset ()) {
1040 fSinkStream.InsertMarker (m, at, length, markerOwner);
1043void SinkStreamDestination::AppendText_ (
const Led_tChar* text,
size_t nTChars)
1050 if (not fTableInRow and fTableNextRowNum == 0) {
1051 fSinkStream.StartTable ();
1055 if (not fTableInRow) {
1058 if (not fTableInCell) {
1067 if (fTCharsInSmallBuffer + nTChars < (Memory::NEltsOf (fSmallBuffer))) {
1068 (void)::memcpy (&fSmallBuffer[fTCharsInSmallBuffer], text, nTChars *
sizeof (Led_tChar));
1069 fTCharsInSmallBuffer += nTChars;
1073 Assert (fTCharsInSmallBuffer == 0);
1075 if (nTChars < (Memory::NEltsOf (fSmallBuffer))) {
1076 (void)::memcpy (&fSmallBuffer[0], text, nTChars *
sizeof (Led_tChar));
1077 fTCharsInSmallBuffer = nTChars;
1082 fsp.MergeIn (fCurrentContext.fFontSpec);
1083 fSinkStream.AppendText (text, nTChars, &fsp);
1088void SinkStreamDestination::AboutToChange ()
const
1093 FlushParaEndings ();
1094 FlushSetContextCalls ();
1097void SinkStreamDestination::FlushSetContextCalls ()
const
1102 if (fNewContextPending) {
1103 fNewContextPending =
false;
1104 const_cast<SinkStreamDestination*
> (
this)->ApplyContext (fNewContext);
1108void SinkStreamDestination::FlushParaEndings ()
const
1113 if (fParaEndedFlag) {
1114 fParaEndedFlag =
false;
1116 const_cast<SinkStreamDestination*
> (
this)->AppendText_ (&c, 1);
1125SinkStreamDestination::CellInfo::CellInfo ()
1127 , f_clcbpat{
Color::kWhite}
1137SinkStreamDestination::RowInfo::RowInfo ()
1139 , f_trleft{TWIPS{0}}
1140 , fDefaultCellMargins{TWIPS{0}, TWIPS{0}, TWIPS{0}, TWIPS{0}}
1141 , fDefaultCellSpacing{TWIPS{0}, TWIPS{0}, TWIPS{0}, TWIPS{0}}
1142 , fCellInfosForThisRow{}
1151StyledTextIOReader_RTF::ReaderContext::ReaderContext (StyledTextIOReader_RTF& reader)
1153 , fDocumentCharacterSet (Characters::WellKnownCodePages::kANSI)
1155 fCurrentInputCharSetEncoding_ (Characters::WellKnownCodePages::kANSI)
1156 , fMultiByteInputCharBuf ()
1158 memset (fMultiByteInputCharBuf, 0,
sizeof (fMultiByteInputCharBuf));
1159#if qCannotAssignRValueAutoPtrToExistingOneInOneStepBug || qTroubleOverloadingXofXRefCTORWithTemplatedMemberCTOR
1160 unique_ptr<Destination_> x = unique_ptr<Destination_> (
new SinkStreamDestination (reader));
1161 fDefaultDestination = x;
1163 fDefaultDestination = unique_ptr<Destination_> (
new SinkStreamDestination (reader));
1165 SetDestination (fDefaultDestination.get ());
1168StyledTextIOReader_RTF::ReaderContext::~ReaderContext ()
1170 Require (fCurrentGroup ==
nullptr);
1177void StyledTextIOReader_RTF::ReaderContext::UseInputCharSetEncoding (
CodePage codePage)
1179 fCurrentInputCharSetEncoding_ = codePage;
1182void StyledTextIOReader_RTF::ReaderContext::PutRawCharToDestination (
char c)
1186 if (fSkipNextNChars_UC > 0) {
1187 fSkipNextNChars_UC--;
1191 CodePage codePage = GetCurrentInputCharSetEncoding ();
1211 if ((GetCurrentGroupContext ()->fCCHSCodePage != 0) and fDocumentCharacterSet == codePage) {
1212 codePage = GetCurrentGroupContext ()->fCCHSCodePage;
1215 if (fMultiByteInputCharBuf[0] ==
'\0') {
1216 fMultiByteInputCharBuf[0] = c;
1217 fMultiByteInputCharBuf[1] =
'\0';
1224 fMultiByteInputCharBuf[1] = c;
1228 size_t nOutChars = 1;
1230 auto inBuf = span{
reinterpret_cast<const byte*
> (fMultiByteInputCharBuf), fMultiByteInputCharBuf[1] ==
'\0' ? 1u : 2u};
1232 Assert (nOutChars == 0 or nOutChars == 1);
1233 if (nOutChars == 1) {
1234 GetDestination ().AppendText (&outChar, 1);
1235 fMultiByteInputCharBuf[0] =
'\0';
1238 if (fMultiByteInputCharBuf[1] ==
'\0') {
1244 Led_tChar u = GetReader ().GetDefaultUnsupportedCharacterChar ();
1245 GetDestination ().AppendText (&u, 1);
1246 fMultiByteInputCharBuf[0] =
'\0';
1256StyledTextIOReader_RTF::ReaderContext::GroupContext::GroupContext (ReaderContext& readerContext)
1257 : fReaderContext (readerContext)
1258 , fParentGroup (readerContext.fCurrentGroup)
1259 , fCurrentGroupStartIdx (readerContext.GetReader ().GetSrcStream ().current_offset ())
1260 , fCurrentCodePage (WellKnownCodePages::kANSI)
1262 , fDestinationContext ()
1264 if (fParentGroup !=
nullptr) {
1265 fDestinationContext = fParentGroup->fDestinationContext;
1266 fCurrentCodePage = fParentGroup->fCurrentCodePage;
1267 fCCHSCodePage = fParentGroup->fCCHSCodePage;
1269 readerContext.fCurrentGroup =
this;
1272StyledTextIOReader_RTF::ReaderContext::GroupContext::~GroupContext ()
1274 Assert (fReaderContext.fCurrentGroup ==
this);
1276 fReaderContext.fCurrentGroup = fParentGroup;
1277 if (fReaderContext.fCurrentGroup !=
nullptr) {
1278 fReaderContext.UseInputCharSetEncoding (fReaderContext.fCurrentGroup->fCurrentCodePage);
1279 fReaderContext.GetDestination ().SetContext (fReaderContext.fCurrentGroup->fDestinationContext);
1283RTFIO::ControlWordAtomName::ControlWordAtomName (
const char* c)
1286 Characters::CString::Copy (fName, eMaxControlAtomNameLen, c);
1294const StyledTextIOReader_RTF::SpecialCharMappings StyledTextIOReader_RTF::kMappings[8] = {
1295 {RTFIO::eControlAtom_tab, 0x0009}, {RTFIO::eControlAtom_bullet, 0x2022}, {RTFIO::eControlAtom_endash, 0x2014},
1296 {RTFIO::eControlAtom_emdash, 0x2013}, {RTFIO::eControlAtom_lquote, 0x2018}, {RTFIO::eControlAtom_rquote, 0x2019},
1297 {RTFIO::eControlAtom_ldblquote, 0x201c}, {RTFIO::eControlAtom_rdblquote, 0x201d},
1300StyledTextIOReader_RTF::StyledTextIOReader_RTF (SrcStream* srcStream, SinkStream* sinkStream, RTFInfo* rtfInfo)
1301 : StyledTextIOReader (srcStream, sinkStream)
1303 , fDefaultUnsupportedCharacterChar (LED_TCHAR_OF (
'?'))
1304 , fRTFInfo (rtfInfo == nullptr ? new RTFInfo () : rtfInfo)
1305 , fOwnRTFInfo (rtfInfo == nullptr)
1306#if qStroika_Foundation_Common_Platform_Windows
1307 , fCachedFontSize (0)
1308 , fCachedFontSizeTMHeight (0)
1317 fPlainFont.SetPointSize (12);
1318#if qStroika_Foundation_Common_Platform_Windows
1319 fCachedFontSize = 12;
1320 fCachedFontSizeTMHeight = fPlainFont.PeekAtTMHeight ();
1324StyledTextIOReader_RTF::~StyledTextIOReader_RTF ()
1331void StyledTextIOReader_RTF::Read ()
1333 ReaderContext readerContext (*
this);
1335 ReadGroup (readerContext);
1337 catch (ReadEOFException& ) {
1343 readerContext.fDefaultDestination->Done ();
1346bool StyledTextIOReader_RTF::QuickLookAppearsToBeRightFormat ()
1348 SrcStreamSeekSaver savePos (GetSrcStream ());
1350 const char kStandardRTFOpenString[] =
"{\\rtf";
1351 char buf[
sizeof (kStandardRTFOpenString) - 1];
1352 size_t bytesRead = GetSrcStream ().read (buf,
sizeof (buf));
1353 return ((bytesRead ==
sizeof (kStandardRTFOpenString) - 1) and ::memcmp (kStandardRTFOpenString, buf,
sizeof (kStandardRTFOpenString) - 1) == 0);
1356void StyledTextIOReader_RTF::ReadGroup (ReaderContext& readerContext)
1358 ReaderContext::GroupContext thisGroupContext (readerContext);
1360 if (GetNextChar () != RTFIO::kRTFOpenGroupChar) {
1361 HandleBadlyFormattedInput (
true);
1365 char c = GetNextChar ();
1367 case RTFIO::kRTFOpenGroupChar: {
1370 ReadGroup (readerContext);
1373 case RTFIO::kRTFCloseGroupChar: {
1377 case RTFIO::kRTFStartTagChar: {
1379 char nextChar = PeekNextChar ();
1441 RTFIO::ControlWord cw = ReadControlWord ();
1442 if (HandleControlWord (readerContext, cw)) {
1449 const wchar_t kFormula = 0x0006;
1450 Led_tChar cc = kFormula;
1451 CheckIfAboutToStartBody (readerContext);
1452 readerContext.GetDestination ().AppendText (&cc, 1);
1457 Led_tChar cc = kNonBreakingSpace;
1458 CheckIfAboutToStartBody (readerContext);
1459 readerContext.GetDestination ().AppendText (&cc, 1);
1465 const wchar_t kOptionalHyphen = 0x00AD;
1467 Led_tChar cc = kOptionalHyphen;
1468 CheckIfAboutToStartBody (readerContext);
1469 readerContext.GetDestination ().AppendText (&cc, 1);
1474 const wchar_t kNonBreakingHyphen = 0x2011;
1475 Led_tChar cc = kNonBreakingHyphen;
1476 CheckIfAboutToStartBody (readerContext);
1477 readerContext.GetDestination ().AppendText (&cc, 1);
1485 ReadCommentGroup (readerContext);
1492 int number = ConvertReadSingleHexDigit_ (GetNextChar ());
1494 number += ConvertReadSingleHexDigit_ (GetNextChar ());
1495 c =
static_cast<char> (number);
1496 goto ReadNormalChar;
1504 goto ReadNormalChar;
1516 CheckIfAboutToStartBody (readerContext);
1518 readerContext.PutRawCharToDestination (c);
1524bool StyledTextIOReader_RTF::HandleControlWord (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
1526 switch (controlWord.fWord) {
1527 case RTFIO::eControlAtom_ansi:
1528 return (HandleControlWord_ansi (readerContext, controlWord));
1529 case RTFIO::eControlAtom_author:
1530 return (HandleControlWord_author (readerContext, controlWord));
1531 case RTFIO::eControlAtom_b:
1532 return (HandleControlWord_b (readerContext, controlWord));
1533 case RTFIO::eControlAtom_brdrs:
1534 case RTFIO::eControlAtom_brdrth:
1535 case RTFIO::eControlAtom_brdrsh:
1536 case RTFIO::eControlAtom_brdrdb:
1537 case RTFIO::eControlAtom_brdrdot:
1538 case RTFIO::eControlAtom_brdrdash:
1539 case RTFIO::eControlAtom_brdrhair:
1540 case RTFIO::eControlAtom_brdrdashsm:
1541 case RTFIO::eControlAtom_brdrdashd:
1542 case RTFIO::eControlAtom_brdrdashdd:
1543 case RTFIO::eControlAtom_brdrtriple:
1544 case RTFIO::eControlAtom_brdrtnthsg:
1545 case RTFIO::eControlAtom_brdrthtnsg:
1546 case RTFIO::eControlAtom_brdrtnthtnsg:
1547 case RTFIO::eControlAtom_brdrtnthmg:
1548 case RTFIO::eControlAtom_brdrthtnmg:
1549 case RTFIO::eControlAtom_brdrtnthtnmg:
1550 case RTFIO::eControlAtom_brdrtnthlg:
1551 case RTFIO::eControlAtom_brdrthtnlg:
1552 case RTFIO::eControlAtom_brdrtnthtnlg:
1553 case RTFIO::eControlAtom_brdrwavy:
1554 case RTFIO::eControlAtom_brdrwavydb:
1555 case RTFIO::eControlAtom_brdrdashdotstr:
1556 case RTFIO::eControlAtom_brdremboss:
1557 case RTFIO::eControlAtom_brdrengrave:
1558 case RTFIO::eControlAtom_brdrw:
1559 case RTFIO::eControlAtom_brdrcf:
1560 return (HandleControlWord_brdrXXX (readerContext, controlWord));
1561 case RTFIO::eControlAtom_cchs:
1562 return (HandleControlWord_cchs (readerContext, controlWord));
1563 case RTFIO::eControlAtom_cell:
1564 return (HandleControlWord_cell (readerContext, controlWord));
1565 case RTFIO::eControlAtom_cellx:
1566 return (HandleControlWord_cellx (readerContext, controlWord));
1567 case RTFIO::eControlAtom_cf:
1568 return (HandleControlWord_cf (readerContext, controlWord));
1569 case RTFIO::eControlAtom_clcbpat:
1570 return (HandleControlWord_clcbpat (readerContext, controlWord));
1571 case RTFIO::eControlAtom_cpg:
1572 return (HandleControlWord_cpg (readerContext, controlWord));
1573 case RTFIO::eControlAtom_colortbl:
1574 return (HandleControlWord_colortbl (readerContext, controlWord));
1575 case RTFIO::eControlAtom_deff:
1576 return (HandleControlWord_deff (readerContext, controlWord));
1577 case RTFIO::eControlAtom_deftab:
1578 return (HandleControlWord_deftab (readerContext, controlWord));
1579 case RTFIO::eControlAtom_deleted:
1580 return (HandleControlWord_deleted (readerContext, controlWord));
1581 case RTFIO::eControlAtom_dn:
1582 return (HandleControlWord_dn (readerContext, controlWord));
1583 case RTFIO::eControlAtom_f:
1584 return (HandleControlWord_f (readerContext, controlWord));
1585 case RTFIO::eControlAtom_fi:
1586 return (HandleControlWord_fi (readerContext, controlWord));
1587 case RTFIO::eControlAtom_footer:
1588 return (HandleControlWord_footer (readerContext, controlWord));
1589 case RTFIO::eControlAtom_fonttbl:
1590 return (HandleControlWord_fonttbl (readerContext, controlWord));
1591 case RTFIO::eControlAtom_fs:
1592 return (HandleControlWord_fs (readerContext, controlWord));
1593 case RTFIO::eControlAtom_header:
1594 return (HandleControlWord_header (readerContext, controlWord));
1595 case RTFIO::eControlAtom_i:
1596 return (HandleControlWord_i (readerContext, controlWord));
1597 case RTFIO::eControlAtom_ilvl:
1598 return (HandleControlWord_ilvl (readerContext, controlWord));
1599 case RTFIO::eControlAtom_info:
1600 return (HandleControlWord_info (readerContext, controlWord));
1601 case RTFIO::eControlAtom_intbl:
1602 return (HandleControlWord_intbl (readerContext, controlWord));
1603 case RTFIO::eControlAtom_li:
1604 return (HandleControlWord_li (readerContext, controlWord));
1605 case RTFIO::eControlAtom_line:
1606 return (HandleControlWord_line (readerContext, controlWord));
1607 case RTFIO::eControlAtom_listtext:
1608 return (HandleControlWord_listtext (readerContext, controlWord));
1609 case RTFIO::eControlAtom_ls:
1610 return (HandleControlWord_ls (readerContext, controlWord));
1611 case RTFIO::eControlAtom_mac:
1612 return (HandleControlWord_mac (readerContext, controlWord));
1613 case RTFIO::eControlAtom_margb:
1614 case RTFIO::eControlAtom_margl:
1615 case RTFIO::eControlAtom_margr:
1616 case RTFIO::eControlAtom_margt:
1617 return (HandleControlWord_margX (readerContext, controlWord));
1618 case RTFIO::eControlAtom_object:
1619 return (HandleControlWord_object (readerContext, controlWord));
1620 case RTFIO::eControlAtom_outl:
1621 return (HandleControlWord_outl (readerContext, controlWord));
1622 case RTFIO::eControlAtom_paperh:
1623 return (HandleControlWord_paperX (readerContext, controlWord));
1624 case RTFIO::eControlAtom_paperw:
1625 return (HandleControlWord_paperX (readerContext, controlWord));
1626 case RTFIO::eControlAtom_par:
1627 return (HandleControlWord_par (readerContext, controlWord));
1628 case RTFIO::eControlAtom_pard:
1629 return (HandleControlWord_pard (readerContext, controlWord));
1630 case RTFIO::eControlAtom_pc:
1631 return (HandleControlWord_pc (readerContext, controlWord));
1632 case RTFIO::eControlAtom_pca:
1633 return (HandleControlWord_pca (readerContext, controlWord));
1634 case RTFIO::eControlAtom_pict:
1635 return (HandleControlWord_pict (readerContext, controlWord));
1636 case RTFIO::eControlAtom_plain:
1637 return (HandleControlWord_plain (readerContext, controlWord));
1638 case RTFIO::eControlAtom_pntext:
1639 return (HandleControlWord_pntext (readerContext, controlWord));
1640 case RTFIO::eControlAtom_qc:
1641 return (HandleControlWord_qc (readerContext, controlWord));
1642 case RTFIO::eControlAtom_qj:
1643 return (HandleControlWord_qj (readerContext, controlWord));
1644 case RTFIO::eControlAtom_ql:
1645 return (HandleControlWord_ql (readerContext, controlWord));
1646 case RTFIO::eControlAtom_qr:
1647 return (HandleControlWord_qr (readerContext, controlWord));
1648 case RTFIO::eControlAtom_ri:
1649 return (HandleControlWord_ri (readerContext, controlWord));
1650 case RTFIO::eControlAtom_row:
1651 return (HandleControlWord_row (readerContext, controlWord));
1652 case RTFIO::eControlAtom_rtf:
1653 return (HandleControlWord_rtf (readerContext, controlWord));
1654 case RTFIO::eControlAtom_sa:
1655 return (HandleControlWord_sa (readerContext, controlWord));
1656 case RTFIO::eControlAtom_sb:
1657 return (HandleControlWord_sb (readerContext, controlWord));
1658 case RTFIO::eControlAtom_shad:
1659 return (HandleControlWord_shad (readerContext, controlWord));
1660 case RTFIO::eControlAtom_sl:
1661 return (HandleControlWord_sl (readerContext, controlWord));
1662 case RTFIO::eControlAtom_slmult:
1663 return (HandleControlWord_slmult (readerContext, controlWord));
1664 case RTFIO::eControlAtom_sub:
1665 return (HandleControlWord_sub (readerContext, controlWord));
1666 case RTFIO::eControlAtom_super:
1667 return (HandleControlWord_super (readerContext, controlWord));
1668 case RTFIO::eControlAtom_strike:
1669 return (HandleControlWord_strike (readerContext, controlWord));
1670 case RTFIO::eControlAtom_stylesheet:
1671 return (HandleControlWord_stylesheet (readerContext, controlWord));
1672 case RTFIO::eControlAtom_trgaph:
1673 return (HandleControlWord_trgaph (readerContext, controlWord));
1674 case RTFIO::eControlAtom_trleft:
1675 return (HandleControlWord_trleft (readerContext, controlWord));
1676 case RTFIO::eControlAtom_trowd:
1677 return (HandleControlWord_trowd (readerContext, controlWord));
1678 case RTFIO::eControlAtom_trpaddb:
1679 case RTFIO::eControlAtom_trpaddl:
1680 case RTFIO::eControlAtom_trpaddr:
1681 case RTFIO::eControlAtom_trpaddt:
1682 return (HandleControlWord_trpaddX (readerContext, controlWord));
1683 case RTFIO::eControlAtom_trspdb:
1684 case RTFIO::eControlAtom_trspdl:
1685 case RTFIO::eControlAtom_trspdr:
1686 case RTFIO::eControlAtom_trspdt:
1687 return (HandleControlWord_trspdX (readerContext, controlWord));
1688 case RTFIO::eControlAtom_tx:
1689 return (HandleControlWord_tx (readerContext, controlWord));
1690 case RTFIO::eControlAtom_u:
1691 return (HandleControlWord_u (readerContext, controlWord));
1692 case RTFIO::eControlAtom_uc:
1693 return (HandleControlWord_uc (readerContext, controlWord));
1694 case RTFIO::eControlAtom_ul:
1695 return (HandleControlWord_ul (readerContext, controlWord));
1696 case RTFIO::eControlAtom_ulnone:
1697 return (HandleControlWord_ulnone (readerContext, controlWord));
1698 case RTFIO::eControlAtom_up:
1699 return (HandleControlWord_up (readerContext, controlWord));
1700 case RTFIO::eControlAtom_v:
1701 return (HandleControlWord_v (readerContext, controlWord));
1704 return (HandleControlWord_UnknownControlWord (readerContext, controlWord));
1708bool StyledTextIOReader_RTF::HandleControlWord_ansi (ReaderContext& readerContext,
const RTFIO::ControlWord& )
1710 readerContext.fDocumentCharacterSet = WellKnownCodePages::kANSI;
1711 readerContext.UseInputCharSetEncoding (readerContext.fDocumentCharacterSet);
1715bool StyledTextIOReader_RTF::HandleControlWord_author (ReaderContext& ,
const RTFIO::ControlWord& )
1717 SkipToEndOfCurrentGroup ();
1721bool StyledTextIOReader_RTF::HandleControlWord_b (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
1723 ApplyFontSpec (readerContext, controlWord);
1727bool StyledTextIOReader_RTF::HandleControlWord_brdrXXX (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
1729 switch (controlWord.fWord) {
1730 case RTFIO::eControlAtom_brdrcf: {
1731 if (not controlWord.fHasArg) {
1732 HandleBadlyFormattedInput (
true);
1734 readerContext.GetDestination ().SetTableBorderColor (LookupColor (readerContext,
static_cast<size_t> (controlWord.fValue)));
1746bool StyledTextIOReader_RTF::HandleControlWord_cchs (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
1748 CheckIfAboutToStartBody (readerContext);
1749 if (readerContext.GetCurrentGroupContext () ==
nullptr) {
1750 HandleBadlyFormattedInput (
true);
1752 if (not controlWord.fHasArg) {
1753 HandleBadlyFormattedInput (
true);
1756 switch (controlWord.fValue) {
1758 readerContext.GetCurrentGroupContext ()->fCCHSCodePage = WellKnownCodePages::kANSI;
1761 readerContext.GetCurrentGroupContext ()->fCCHSCodePage = WellKnownCodePages::kPC;
1764 readerContext.GetCurrentGroupContext ()->fCCHSCodePage = WellKnownCodePages::kPCA;
1767 readerContext.GetCurrentGroupContext ()->fCCHSCodePage = WellKnownCodePages::kMAC;
1778bool StyledTextIOReader_RTF::HandleControlWord_cell (ReaderContext& readerContext,
const RTFIO::ControlWord& )
1780 CheckIfAboutToStartBody (readerContext);
1781 readerContext.GetDestination ().EndCell (
true);
1785bool StyledTextIOReader_RTF::HandleControlWord_cellx (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
1787 CheckIfAboutToStartBody (readerContext);
1788 if (not controlWord.fHasArg) {
1789 HandleBadlyFormattedInput (
true);
1791 readerContext.GetDestination ().SetCellX (TWIPS (controlWord.fValue));
1795bool StyledTextIOReader_RTF::HandleControlWord_cf (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
1797 ApplyFontSpec (readerContext, controlWord);
1801bool StyledTextIOReader_RTF::HandleControlWord_clcbpat (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
1803 CheckIfAboutToStartBody (readerContext);
1804 readerContext.GetDestination ().SetCellBackColor (LookupColor (readerContext,
static_cast<size_t> (controlWord.fValue)));
1808bool StyledTextIOReader_RTF::HandleControlWord_cpg (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
1810 CheckIfAboutToStartBody (readerContext);
1811 if (readerContext.GetCurrentGroupContext () ==
nullptr) {
1812 HandleBadlyFormattedInput (
true);
1814 if (not controlWord.fHasArg) {
1815 HandleBadlyFormattedInput (
true);
1817 readerContext.GetCurrentGroupContext ()->fCurrentCodePage = controlWord.fValue;
1818 readerContext.UseInputCharSetEncoding (readerContext.GetCurrentGroupContext ()->fCurrentCodePage);
1822bool StyledTextIOReader_RTF::HandleControlWord_colortbl (ReaderContext& readerContext,
const RTFIO::ControlWord& )
1824 if (readerContext.fColorTable !=
nullptr) {
1825 HandleBadlyFormattedInput ();
1834 if (readerContext.GetCurrentGroupContext () ==
nullptr) {
1835 HandleBadlyFormattedInput (
true);
1837 GetSrcStream ().seek_to (readerContext.GetCurrentGroupContext ()->fCurrentGroupStartIdx);
1838 if (GetNextChar () != RTFIO::kRTFOpenGroupChar) {
1839 HandleBadlyFormattedInput (
true);
1843 RTFIO::ControlWord cword = ReadControlWord ();
1844 if (cword.fWord != RTFIO::eControlAtom_colortbl or cword.fHasArg) {
1845 HandleBadlyFormattedInput (
true);
1849 vector<Color> colorTable;
1851 Color curColor = Color::kBlack;
1855 switch (PeekNextChar ()) {
1856 case RTFIO::kRTFCloseGroupChar: {
1858 goto ColorsComplete;
1864 case RTFIO::kRTFStartTagChar: {
1865 RTFIO::ControlWord cword = ReadControlWord ();
1866 if (cword.fWord == RTFIO::eControlAtom_red) {
1867 if (not cword.fHasArg) {
1868 HandleBadlyFormattedInput ();
1871 curColor =
Color (
static_cast<Color::ColorValue
> (
unsigned (cword.fValue) << 8), 0, 0);
1875 HandleBadlyFormattedInput ();
1885 HandleBadlyFormattedInput ();
1891 switch (PeekNextChar ()) {
1896 case RTFIO::kRTFStartTagChar: {
1897 RTFIO::ControlWord cword = ReadControlWord ();
1898 if (cword.fWord == RTFIO::eControlAtom_green) {
1899 if (not cword.fHasArg) {
1900 HandleBadlyFormattedInput ();
1903 curColor =
Color (curColor.GetRed (),
static_cast<Color::ColorValue
> (unsigned (cword.fValue) << 8), 0);
1907 HandleBadlyFormattedInput ();
1917 HandleBadlyFormattedInput ();
1923 switch (PeekNextChar ()) {
1928 case RTFIO::kRTFStartTagChar: {
1929 RTFIO::ControlWord cword = ReadControlWord ();
1930 if (cword.fWord == RTFIO::eControlAtom_blue) {
1931 if (not cword.fHasArg) {
1932 HandleBadlyFormattedInput ();
1935 curColor =
Color (curColor.GetRed (), curColor.GetGreen (),
static_cast<Color::ColorValue
> (unsigned (cword.fValue) << 8));
1939 HandleBadlyFormattedInput ();
1949 HandleBadlyFormattedInput ();
1955 switch (PeekNextChar ()) {
1965 HandleBadlyFormattedInput ();
1971 colorTable.push_back (curColor);
1975 Assert (readerContext.fColorTable ==
nullptr);
1976 readerContext.fColorTable =
new RTFIO::ColorTable (colorTable);
1981bool StyledTextIOReader_RTF::HandleControlWord_deff (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
1983 if (not controlWord.fHasArg) {
1984 HandleBadlyFormattedInput ();
1987 readerContext.fDefaultFontNumber = controlWord.fValue;
1992bool StyledTextIOReader_RTF::HandleControlWord_deftab (ReaderContext& ,
const RTFIO::ControlWord& controlWord)
1994 if (not controlWord.fHasArg) {
1995 HandleBadlyFormattedInput ();
1998 if (controlWord.fValue < 0) {
1999 HandleBadlyFormattedInput ();
2002 TWIPS tsl = TWIPS (controlWord.fValue);
2004 HandleBadlyFormattedInput ();
2007 if (fRTFInfo !=
nullptr) {
2008 fRTFInfo->fDefaultTabStop = tsl;
2013bool StyledTextIOReader_RTF::HandleControlWord_deleted (ReaderContext& ,
const RTFIO::ControlWord& )
2019 SkipToEndOfCurrentGroup ();
2023bool StyledTextIOReader_RTF::HandleControlWord_dn (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2028 if (controlWord.fHasArg and controlWord.fValue > 0) {
2029 RTFIO::ControlWord newCW;
2030 newCW.fHasArg =
false;
2031 newCW.fWord = RTFIO::eControlAtom_sub;
2032 return HandleControlWord_sub (readerContext, newCW);
2037bool StyledTextIOReader_RTF::HandleControlWord_f (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2039 ApplyFontSpec (readerContext, controlWord);
2043bool StyledTextIOReader_RTF::HandleControlWord_fi (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2045 if (not controlWord.fHasArg) {
2046 HandleBadlyFormattedInput ();
2049 readerContext.GetDestination ().SetFirstIndent (readerContext.GetCurrentGroupContext ()->fDestinationContext.fFirstIndent =
2050 TWIPS (controlWord.fValue));
2055bool StyledTextIOReader_RTF::HandleControlWord_footer (ReaderContext& ,
const RTFIO::ControlWord& )
2061 SkipToEndOfCurrentGroup ();
2065bool StyledTextIOReader_RTF::HandleControlWord_fonttbl (ReaderContext& readerContext,
const RTFIO::ControlWord& )
2067 if (readerContext.fFontTable !=
nullptr) {
2068 HandleBadlyFormattedInput ();
2077 if (readerContext.GetCurrentGroupContext () ==
nullptr) {
2078 HandleBadlyFormattedInput (
true);
2080 GetSrcStream ().seek_to (readerContext.GetCurrentGroupContext ()->fCurrentGroupStartIdx);
2081 if (GetNextChar () != RTFIO::kRTFOpenGroupChar) {
2082 HandleBadlyFormattedInput (
true);
2085 vector<FontTableEntry> fontTable;
2088 ScanForwardFor (
"{}");
2089 switch (PeekNextChar ()) {
2090 case RTFIO::kRTFOpenGroupChar: {
2091 fontTable.push_back (ReadInFontTablesEntry ());
2093 case RTFIO::kRTFCloseGroupChar: {
2095 if (readerContext.fFontTable ==
nullptr) {
2097 readerContext.fFontTable =
new FontTable (fontTable);
2109bool StyledTextIOReader_RTF::HandleControlWord_fs (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2111 ApplyFontSpec (readerContext, controlWord);
2115bool StyledTextIOReader_RTF::HandleControlWord_header (ReaderContext& ,
const RTFIO::ControlWord& )
2121 SkipToEndOfCurrentGroup ();
2125bool StyledTextIOReader_RTF::HandleControlWord_i (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2127 ApplyFontSpec (readerContext, controlWord);
2131bool StyledTextIOReader_RTF::HandleControlWord_ilvl (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2133 if (not controlWord.fHasArg) {
2134 HandleBadlyFormattedInput ();
2137 unsigned char listLevel =
static_cast<unsigned char> (controlWord.fValue);
2138 if (listLevel > 8) {
2141 readerContext.GetDestination ().SetListIndentLevel (readerContext.GetCurrentGroupContext ()->fDestinationContext.fListIndentLevel = listLevel);
2146bool StyledTextIOReader_RTF::HandleControlWord_info (ReaderContext& ,
const RTFIO::ControlWord& )
2148 SkipToEndOfCurrentGroup ();
2152bool StyledTextIOReader_RTF::HandleControlWord_intbl (ReaderContext& readerContext,
const RTFIO::ControlWord& )
2154 CheckIfAboutToStartBody (readerContext);
2155 if (readerContext.GetCurrentGroupContext () ==
nullptr) {
2156 HandleBadlyFormattedInput (
true);
2158 readerContext.GetDestination ().SetInTable (
true);
2162bool StyledTextIOReader_RTF::HandleControlWord_li (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2164 if (not controlWord.fHasArg) {
2165 HandleBadlyFormattedInput ();
2168 readerContext.GetDestination ().SetLeftMargin (readerContext.GetCurrentGroupContext ()->fDestinationContext.fLeftMargin =
2169 TWIPS (controlWord.fValue));
2174bool StyledTextIOReader_RTF::HandleControlWord_line (ReaderContext& readerContext,
const RTFIO::ControlWord& )
2176 readerContext.GetDestination ().AppendSoftLineBreak ();
2180bool StyledTextIOReader_RTF::HandleControlWord_listtext (ReaderContext& ,
const RTFIO::ControlWord& )
2182 SkipToEndOfCurrentGroup ();
2186bool StyledTextIOReader_RTF::HandleControlWord_ls (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2188 if (not controlWord.fHasArg) {
2189 HandleBadlyFormattedInput ();
2195 ListStyle listStyle = eListStyle_Bullet;
2196 readerContext.GetDestination ().SetListStyle (readerContext.GetCurrentGroupContext ()->fDestinationContext.fListStyle = listStyle);
2201bool StyledTextIOReader_RTF::HandleControlWord_mac (ReaderContext& readerContext,
const RTFIO::ControlWord& )
2203 readerContext.fDocumentCharacterSet = WellKnownCodePages::kMAC;
2204 readerContext.UseInputCharSetEncoding (readerContext.fDocumentCharacterSet);
2208bool StyledTextIOReader_RTF::HandleControlWord_margX (ReaderContext& ,
const RTFIO::ControlWord& controlWord)
2210 if (not controlWord.fHasArg) {
2211 HandleBadlyFormattedInput ();
2215 switch (controlWord.fWord) {
2216 case RTFIO::eControlAtom_margt: {
2217 fRTFInfo->fDefaultMarginTop = TWIPS (controlWord.fValue);
2219 case RTFIO::eControlAtom_margb: {
2220 fRTFInfo->fDefaultMarginBottom = TWIPS (controlWord.fValue);
2222 case RTFIO::eControlAtom_margl: {
2223 fRTFInfo->fDefaultMarginLeft = TWIPS (controlWord.fValue);
2225 case RTFIO::eControlAtom_margr: {
2226 fRTFInfo->fDefaultMarginRight = TWIPS (controlWord.fValue);
2235bool StyledTextIOReader_RTF::HandleControlWord_outl (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2237 ApplyFontSpec (readerContext, controlWord);
2241bool StyledTextIOReader_RTF::HandleControlWord_paperX (ReaderContext& ,
const RTFIO::ControlWord& controlWord)
2243 if (not controlWord.fHasArg) {
2244 HandleBadlyFormattedInput ();
2248 switch (controlWord.fWord) {
2249 case RTFIO::eControlAtom_paperh: {
2250 fRTFInfo->fDefaultPaperSize.v = TWIPS (controlWord.fValue);
2252 case RTFIO::eControlAtom_paperw: {
2253 fRTFInfo->fDefaultPaperSize.h = TWIPS (controlWord.fValue);
2262bool StyledTextIOReader_RTF::HandleControlWord_object (ReaderContext& readerContext,
const RTFIO::ControlWord& )
2264 CheckIfAboutToStartBody (readerContext);
2265#if qStroika_Frameworks_Led_SupportGDI
2266 using UnknownRTFEmbedding = RTFIO::UnknownRTFEmbedding;
2268 using ControlWord = RTFIO::ControlWord;
2282 bool isOLEEmbedding =
false;
2283 bool isPrivateLedEmbedding =
false;
2284 TWIPS_Point shownSize = TWIPS_Point (TWIPS{0}, TWIPS{0});
2285 vector<char> objData;
2286 float scaleX = 1.0f;
2287 float scaleY = 1.0f;
2288 size_t resultFoundAt = size_t (-1);
2292 if (PeekNextChar () != RTFIO::kRTFStartTagChar) {
2293 ScanForwardFor (
"{}");
2295 switch (PeekNextChar ()) {
2296 case RTFIO::kRTFStartTagChar: {
2297 ControlWord cw = ReadControlWord ();
2299 case RTFIO::eControlAtom_ledprivateobjectembeddingformat:
2300 isPrivateLedEmbedding =
true;
2302 case RTFIO::eControlAtom_objemb:
2303 isOLEEmbedding =
true;
2305 case RTFIO::eControlAtom_objh:
2306 if (not cw.fHasArg) {
2307 HandleBadlyFormattedInput ();
2310 shownSize.v = TWIPS (cw.fValue);
2312 case RTFIO::eControlAtom_objw:
2313 if (not cw.fHasArg) {
2314 HandleBadlyFormattedInput ();
2317 shownSize.h = TWIPS (cw.fValue);
2319 case RTFIO::eControlAtom_objscalex:
2320 if (not cw.fHasArg) {
2321 HandleBadlyFormattedInput ();
2324 scaleX = cw.fValue / 100.0f;
2326 case RTFIO::eControlAtom_objscaley:
2327 if (not cw.fHasArg) {
2328 HandleBadlyFormattedInput ();
2331 scaleY = cw.fValue / 100.0f;
2333 case RTFIO::eControlAtom_result:
2334 resultFoundAt = readerContext.GetReader ().GetSrcStream ().current_offset ();
2338 case RTFIO::kRTFOpenGroupChar: {
2339 ReadInObjectSubGroupEntry (readerContext, &objData, &resultFoundAt);
2341 case RTFIO::kRTFCloseGroupChar: {
2345 shownSize.h *= scaleX;
2346 shownSize.v *= scaleY;
2347#if qStroika_Frameworks_Led_SupportGDI
2348 if (shownSize.v > 20000 or shownSize.h > 20000 or shownSize.h < 100 or shownSize.v < 100) {
2349 shownSize = UnknownRTFEmbedding::CalcStaticDefaultShownSize ();
2355 if (isOLEEmbedding and isPrivateLedEmbedding) {
2356 HandleBadlyFormattedInput ();
2358 if (isOLEEmbedding) {
2360 ConstructOLEEmebddingFromRTFInfo (readerContext, shownSize, objData.size (), &objData.front ());
2363 isOLEEmbedding =
false;
2366 if (isPrivateLedEmbedding) {
2368 ConstructLedEmebddingFromRTFInfo (readerContext, objData.size (), &objData.front ());
2371 isPrivateLedEmbedding =
false;
2378 if (isOLEEmbedding or isPrivateLedEmbedding) {
2383 GetSrcStream ().seek_to (readerContext.GetCurrentGroupContext ()->fCurrentGroupStartIdx);
2384 string s = ReadInGroupAndSave ();
2386#if qStroika_Frameworks_Led_SupportGDI
2387 SimpleEmbeddedObjectStyleMarker* embedding =
nullptr;
2393 if (resultFoundAt !=
size_t (-1)) {
2394 size_t RETURN_TO = readerContext.GetReader ().GetSrcStream ().current_offset ();
2395 GetSrcStream ().seek_to (resultFoundAt);
2396 if (SearchForwardFor (
"\\pict", s.length ())) {
2397 ControlWord cw = ReadControlWord ();
2398 if (cw.fWord == RTFIO::eControlAtom_pict) {
2399 TWIPS_Point bmSize = TWIPS_Point (TWIPS{0}, TWIPS{0});
2400 vector<char> pictureData;
2401 ImageFormat imageFormat = eDefaultImageFormat;
2402 ReadTopLevelPictData (&shownSize, &imageFormat, &bmSize, &pictureData);
2410 unique_ptr<Led_DIB> dib = unique_ptr<Led_DIB> (
2411 ConstructDIBFromData (shownSize, imageFormat, bmSize, objData.size (), &pictureData.front ()));
2412 if (dib.get () !=
nullptr) {
2413 RTFIO::UnknownRTFEmbedding* e =
new RTFIO::UnknownRTFEmbedding (RTFIO::kRTFBodyGroupFragmentClipFormat,
2414 RTFIO::kRTFBodyGroupFragmentEmbeddingTag,
2415 s.c_str (), s.length (), dib.get ());
2416 e->SetShownSize (shownSize);
2421 GetSrcStream ().seek_to (RETURN_TO);
2424 if (embedding ==
nullptr) {
2425 RTFIO::UnknownRTFEmbedding* e =
new RTFIO::UnknownRTFEmbedding (
2426 RTFIO::kRTFBodyGroupFragmentClipFormat, RTFIO::kRTFBodyGroupFragmentEmbeddingTag, s.c_str (), s.length ());
2427 e->SetShownSize (shownSize);
2431 readerContext.GetDestination ().AppendEmbedding (embedding);
2449bool StyledTextIOReader_RTF::HandleControlWord_par (ReaderContext& readerContext,
const RTFIO::ControlWord& )
2456 CheckIfAboutToStartBody (readerContext);
2457 readerContext.GetDestination ().EndParagraph ();
2461bool StyledTextIOReader_RTF::HandleControlWord_pard (ReaderContext& readerContext,
const RTFIO::ControlWord& )
2465 readerContext.GetDestination ().SetTabStops (readerContext.GetCurrentGroupContext ()->fDestinationContext.fTabStops =
2466 StandardTabStopList (GetRTFInfo ().GetDefaultTabStop ()));
2467 readerContext.GetDestination ().SetJustification (readerContext.GetCurrentGroupContext ()->fDestinationContext.fJustification = eLeftJustify);
2468 readerContext.GetDestination ().SetFirstIndent (readerContext.GetCurrentGroupContext ()->fDestinationContext.fFirstIndent = TWIPS{0});
2469 readerContext.GetDestination ().SetLeftMargin (readerContext.GetCurrentGroupContext ()->fDestinationContext.fLeftMargin = TWIPS{0});
2470 readerContext.GetDestination ().SetRightMargin (readerContext.GetCurrentGroupContext ()->fDestinationContext.fRightMargin = TWIPS{0});
2471 readerContext.GetDestination ().SetSpaceBefore (readerContext.GetCurrentGroupContext ()->fDestinationContext.fSpaceBefore = TWIPS{0});
2472 readerContext.GetDestination ().SetSpaceAfter (readerContext.GetCurrentGroupContext ()->fDestinationContext.fSpaceAfter = TWIPS{0});
2473 readerContext.GetDestination ().SetSpaceBetweenLines (readerContext.GetCurrentGroupContext ()->fDestinationContext.fSpaceBetweenLines = 1000);
2474 readerContext.GetDestination ().SetSpaceBetweenLinesMult (readerContext.GetCurrentGroupContext ()->fDestinationContext.fSpaceBetweenLinesMult =
true);
2475 readerContext.GetDestination ().SetListStyle (readerContext.GetCurrentGroupContext ()->fDestinationContext.fListStyle = eListStyle_None);
2476 readerContext.GetDestination ().SetListIndentLevel (readerContext.GetCurrentGroupContext ()->fDestinationContext.fListIndentLevel = 0);
2480 readerContext.GetDestination ().SetInTable (
false);
2484bool StyledTextIOReader_RTF::HandleControlWord_pc (ReaderContext& readerContext,
const RTFIO::ControlWord& )
2486 readerContext.fDocumentCharacterSet = WellKnownCodePages::kPC;
2487 readerContext.UseInputCharSetEncoding (readerContext.fDocumentCharacterSet);
2491bool StyledTextIOReader_RTF::HandleControlWord_pca (ReaderContext& readerContext,
const RTFIO::ControlWord& )
2493 readerContext.fDocumentCharacterSet = WellKnownCodePages::kPCA;
2494 readerContext.UseInputCharSetEncoding (readerContext.fDocumentCharacterSet);
2498bool StyledTextIOReader_RTF::HandleControlWord_pict (ReaderContext& readerContext,
const RTFIO::ControlWord& )
2500 CheckIfAboutToStartBody (readerContext);
2502 TWIPS_Point shownSize = TWIPS_Point (TWIPS{0}, TWIPS{0});
2503 TWIPS_Point bmSize = TWIPS_Point (TWIPS{0}, TWIPS{0});
2504 vector<char> objData;
2505 ImageFormat imageFormat = eDefaultImageFormat;
2506 ReadTopLevelPictData (&shownSize, &imageFormat, &bmSize, &objData);
2515 unique_ptr<Led_DIB> dib = unique_ptr<Led_DIB> (ConstructDIBFromData (shownSize, imageFormat, bmSize, objData.size (), &objData.front ()));
2516#if qStroika_Frameworks_Led_SupportGDI
2517 bool createSucceeded = dib.get () !=
nullptr;
2518 SimpleEmbeddedObjectStyleMarker* embedding =
nullptr;
2519 if (createSucceeded) {
2520 embedding =
new StandardDIBStyleMarker (dib.get ());
2524 GetSrcStream ().seek_to (readerContext.GetCurrentGroupContext ()->fCurrentGroupStartIdx);
2525 string s = ReadInGroupAndSave ();
2526 embedding =
new RTFIO::UnknownRTFEmbedding (RTFIO::kRTFBodyGroupFragmentClipFormat, RTFIO::kRTFBodyGroupFragmentEmbeddingTag,
2527 s.c_str (), s.length ());
2530 if (embedding !=
nullptr) {
2532 readerContext.GetDestination ().AppendEmbedding (embedding);
2543bool StyledTextIOReader_RTF::HandleControlWord_plain (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2545 ApplyFontSpec (readerContext, controlWord);
2549bool StyledTextIOReader_RTF::HandleControlWord_pntext (ReaderContext& ,
const RTFIO::ControlWord& )
2551 SkipToEndOfCurrentGroup ();
2555bool StyledTextIOReader_RTF::HandleControlWord_qc (ReaderContext& readerContext,
const RTFIO::ControlWord& )
2557 readerContext.GetDestination ().SetJustification (readerContext.GetCurrentGroupContext ()->fDestinationContext.fJustification = eCenterJustify);
2561bool StyledTextIOReader_RTF::HandleControlWord_qj (ReaderContext& readerContext,
const RTFIO::ControlWord& )
2563 readerContext.GetDestination ().SetJustification (readerContext.GetCurrentGroupContext ()->fDestinationContext.fJustification = eFullyJustify);
2567bool StyledTextIOReader_RTF::HandleControlWord_ql (ReaderContext& readerContext,
const RTFIO::ControlWord& )
2569 readerContext.GetDestination ().SetJustification (readerContext.GetCurrentGroupContext ()->fDestinationContext.fJustification = eLeftJustify);
2573bool StyledTextIOReader_RTF::HandleControlWord_qr (ReaderContext& readerContext,
const RTFIO::ControlWord& )
2575 readerContext.GetDestination ().SetJustification (readerContext.GetCurrentGroupContext ()->fDestinationContext.fJustification = eRightJustify);
2579bool StyledTextIOReader_RTF::HandleControlWord_ri (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2581 if (not controlWord.fHasArg) {
2582 HandleBadlyFormattedInput ();
2585 readerContext.GetDestination ().SetRightMargin (readerContext.GetCurrentGroupContext ()->fDestinationContext.fRightMargin =
2586 TWIPS (controlWord.fValue));
2591bool StyledTextIOReader_RTF::HandleControlWord_row (ReaderContext& readerContext,
const RTFIO::ControlWord& )
2593 CheckIfAboutToStartBody (readerContext);
2594 readerContext.GetDestination ().EndRow (
true);
2598bool StyledTextIOReader_RTF::HandleControlWord_rtf (ReaderContext& ,
const RTFIO::ControlWord& )
2604bool StyledTextIOReader_RTF::HandleControlWord_sa (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2606 if (not controlWord.fHasArg) {
2607 HandleBadlyFormattedInput ();
2610 readerContext.GetDestination ().SetSpaceAfter (readerContext.GetCurrentGroupContext ()->fDestinationContext.fSpaceAfter =
2611 TWIPS (controlWord.fValue));
2616bool StyledTextIOReader_RTF::HandleControlWord_sb (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2618 if (not controlWord.fHasArg) {
2619 HandleBadlyFormattedInput ();
2622 readerContext.GetDestination ().SetSpaceBefore (readerContext.GetCurrentGroupContext ()->fDestinationContext.fSpaceBefore =
2623 TWIPS (controlWord.fValue));
2628bool StyledTextIOReader_RTF::HandleControlWord_shad (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2630 ApplyFontSpec (readerContext, controlWord);
2634bool StyledTextIOReader_RTF::HandleControlWord_sl (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2636 if (not controlWord.fHasArg) {
2637 HandleBadlyFormattedInput ();
2640 readerContext.GetDestination ().SetSpaceBetweenLines (readerContext.GetCurrentGroupContext ()->fDestinationContext.fSpaceBetweenLines =
2641 controlWord.fValue);
2646bool StyledTextIOReader_RTF::HandleControlWord_slmult (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2648 if (not controlWord.fHasArg) {
2649 HandleBadlyFormattedInput ();
2652 readerContext.GetDestination ().SetSpaceBetweenLinesMult (
2653 readerContext.GetCurrentGroupContext ()->fDestinationContext.fSpaceBetweenLinesMult =
static_cast<bool> (controlWord.fValue));
2658bool StyledTextIOReader_RTF::HandleControlWord_sub (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2660 ApplyFontSpec (readerContext, controlWord);
2664bool StyledTextIOReader_RTF::HandleControlWord_super (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2666 ApplyFontSpec (readerContext, controlWord);
2670bool StyledTextIOReader_RTF::HandleControlWord_strike (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2672 ApplyFontSpec (readerContext, controlWord);
2676bool StyledTextIOReader_RTF::HandleControlWord_stylesheet (ReaderContext& ,
const RTFIO::ControlWord& )
2678 SkipToEndOfCurrentGroup ();
2682bool StyledTextIOReader_RTF::HandleControlWord_trleft (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2684 CheckIfAboutToStartBody (readerContext);
2685 if (not controlWord.fHasArg) {
2686 HandleBadlyFormattedInput ();
2688 readerContext.GetDestination ().Set_trleft (TWIPS (controlWord.fValue));
2692bool StyledTextIOReader_RTF::HandleControlWord_trgaph (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2694 CheckIfAboutToStartBody (readerContext);
2695 if (not controlWord.fHasArg) {
2696 HandleBadlyFormattedInput ();
2698 TWIPS margins = TWIPS (controlWord.fValue);
2699 readerContext.GetDestination ().SetDefaultCellMarginsForRow_top (margins);
2700 readerContext.GetDestination ().SetDefaultCellMarginsForRow_left (margins);
2701 readerContext.GetDestination ().SetDefaultCellMarginsForRow_bottom (margins);
2702 readerContext.GetDestination ().SetDefaultCellMarginsForRow_right (margins);
2706bool StyledTextIOReader_RTF::HandleControlWord_trowd (ReaderContext& readerContext,
const RTFIO::ControlWord& )
2708 CheckIfAboutToStartBody (readerContext);
2709 readerContext.GetDestination ().Call_trowd ();
2713bool StyledTextIOReader_RTF::HandleControlWord_trpaddX (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2715 CheckIfAboutToStartBody (readerContext);
2716 if (not controlWord.fHasArg) {
2717 HandleBadlyFormattedInput ();
2719 TWIPS margin = TWIPS (controlWord.fValue);
2720 switch (controlWord.fWord) {
2721 case RTFIO::eControlAtom_trpaddb:
2722 readerContext.GetDestination ().SetDefaultCellMarginsForRow_bottom (margin);
2724 case RTFIO::eControlAtom_trpaddl:
2725 readerContext.GetDestination ().SetDefaultCellMarginsForRow_left (margin);
2727 case RTFIO::eControlAtom_trpaddr:
2728 readerContext.GetDestination ().SetDefaultCellMarginsForRow_right (margin);
2730 case RTFIO::eControlAtom_trpaddt:
2731 readerContext.GetDestination ().SetDefaultCellMarginsForRow_top (margin);
2739bool StyledTextIOReader_RTF::HandleControlWord_trspdX (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2741 CheckIfAboutToStartBody (readerContext);
2742 if (not controlWord.fHasArg) {
2743 HandleBadlyFormattedInput ();
2745 TWIPS margin = TWIPS (controlWord.fValue);
2746 switch (controlWord.fWord) {
2747 case RTFIO::eControlAtom_trspdb:
2748 readerContext.GetDestination ().SetDefaultCellSpacingForRow_bottom (margin);
2750 case RTFIO::eControlAtom_trspdl:
2751 readerContext.GetDestination ().SetDefaultCellSpacingForRow_left (margin);
2753 case RTFIO::eControlAtom_trspdr:
2754 readerContext.GetDestination ().SetDefaultCellSpacingForRow_right (margin);
2756 case RTFIO::eControlAtom_trspdt:
2757 readerContext.GetDestination ().SetDefaultCellSpacingForRow_top (margin);
2765bool StyledTextIOReader_RTF::HandleControlWord_tx (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2767 if (not controlWord.fHasArg) {
2768 HandleBadlyFormattedInput ();
2771 StandardTabStopList* curTabs = &readerContext.GetCurrentGroupContext ()->fDestinationContext.fTabStops;
2772 CoordinateType lastStop = 0;
2773 for (
auto i = curTabs->fTabStops.begin (); i != curTabs->fTabStops.end (); ++i) {
2776 TWIPS newStop = TWIPS (controlWord.fValue);
2777 if (newStop <= lastStop) {
2778 HandleBadlyFormattedInput ();
2781 Assert (newStop > lastStop);
2782 curTabs->fTabStops.push_back (TWIPS (newStop - lastStop));
2783 readerContext.GetDestination ().SetTabStops (*curTabs);
2788bool StyledTextIOReader_RTF::HandleControlWord_u ([[maybe_unused]] ReaderContext& readerContext, [[maybe_unused]]
const RTFIO::ControlWord& controlWord)
2793 if (controlWord.fHasArg) {
2794 readerContext.fSkipNextNChars_UC = readerContext.fUnicodeUCValue;
2795 wchar_t u =
static_cast<wchar_t> (controlWord.fValue);
2796 readerContext.GetDestination ().AppendText (&u, 1);
2799 HandleBadlyFormattedInput ();
2804bool StyledTextIOReader_RTF::HandleControlWord_uc ([[maybe_unused]] ReaderContext& readerContext, [[maybe_unused]]
const RTFIO::ControlWord& controlWord)
2806 if (not controlWord.fHasArg) {
2807 readerContext.fUnicodeUCValue = 1;
2810 readerContext.fUnicodeUCValue = max (0L, controlWord.fValue);
2815bool StyledTextIOReader_RTF::HandleControlWord_ul (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2817 ApplyFontSpec (readerContext, controlWord);
2821bool StyledTextIOReader_RTF::HandleControlWord_ulnone (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2823 ApplyFontSpec (readerContext, controlWord);
2827bool StyledTextIOReader_RTF::HandleControlWord_up (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2832 if (controlWord.fHasArg and controlWord.fValue > 0) {
2833 RTFIO::ControlWord newCW;
2834 newCW.fHasArg =
false;
2835 newCW.fWord = RTFIO::eControlAtom_super;
2836 return HandleControlWord_super (readerContext, newCW);
2841bool StyledTextIOReader_RTF::HandleControlWord_v (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2843 CheckIfAboutToStartBody (readerContext);
2844 if (readerContext.GetCurrentGroupContext () ==
nullptr) {
2845 HandleBadlyFormattedInput (
true);
2847 bool startHidden = controlWord.fHasArg ? controlWord.fValue :
true;
2848 readerContext.GetDestination ().SetTextHidden (readerContext.GetCurrentGroupContext ()->fDestinationContext.fTextHidden = startHidden);
2852bool StyledTextIOReader_RTF::HandleControlWord_UnknownControlWord (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2854 (void)HandlePossibleSpecialCharacterControlWord (readerContext, controlWord);
2858bool StyledTextIOReader_RTF::HandlePossibleSpecialCharacterControlWord (ReaderContext& readerContext,
const RTFIO::ControlWord& controlWord)
2861 for (
size_t i = 0; i < Memory::NEltsOf (kMappings); ++i) {
2862 if (controlWord.fWord == kMappings[i].fControlWordName) {
2863 CheckIfAboutToStartBody (readerContext);
2864 readerContext.GetDestination ().AppendText (&kMappings[i].fUNICODECharacter, 1);
2871void StyledTextIOReader_RTF::ReadCommentGroup (ReaderContext& readerContext)
2882 if (PeekNextChar () == RTFIO::kRTFStartTagChar) {
2883 RTFIO::ControlWord cword = ReadControlWord ();
2884 if (cword.fWord == RTFIO::eControlAtom_pn) {
2885 ReadIn_pn_Group (readerContext);
2890 SkipToEndOfCurrentGroup ();
2893void StyledTextIOReader_RTF::ReadIn_pn_Group (ReaderContext& readerContext)
2901 ListStyle listStyle = eListStyle_Bullet;
2902 if (readerContext.GetParentGroupContext () !=
nullptr) {
2903 readerContext.GetDestination ().SetListStyle (readerContext.GetParentGroupContext ()->fDestinationContext.fListStyle = listStyle);
2905 SkipToEndOfCurrentGroup ();
2908#define qTryQuickISXXX 1
2909inline bool quickIsAlpha (
char c)
2911 return (c >=
'a' and c <=
'z') or (c >=
'A' and c <=
'Z');
2913inline bool quickIsDigit (
char c)
2915 return (c >=
'0' and c <=
'9');
2918RTFIO::ControlWord StyledTextIOReader_RTF::ReadControlWord ()
2924 RTFIO::ControlWord controlWord;
2926 if (GetNextChar () != RTFIO::kRTFStartTagChar) {
2928 HandleBadlyFormattedInput (
true);
2937 char c = GetNextChar ();
2987 RTFIO::ControlWordAtomName controlWordBuf;
2988 size_t controlWordLen = 0;
2989 for (; quickIsAlpha (c); c = GetNextChar ()) {
2997 if (controlWordLen < RTFIO::eMaxControlAtomNameLen) {
2998 controlWordBuf[controlWordLen] = c;
3001#if qStroika_Foundation_Debug_AssertionsChecked
3007 controlWordBuf[controlWordLen] =
'\0';
3008 controlWord.fWord = RTFIO::EnterControlWord (controlWordBuf);
3017 else if (c ==
'-' or quickIsDigit (c)) {
3018 bool negative = bool (c ==
'-');
3022 unsigned long number = 0;
3023 for (; quickIsDigit (c); c = GetNextChar ()) {
3025 number += (
unsigned long)(c -
'0');
3027 controlWord.fHasArg =
true;
3030 controlWord.fValue = negative ? -long (number) : number;
3047void StyledTextIOReader_RTF::AboutToStartBody (ReaderContext& readerContext)
3049 Require (not readerContext.fStartedBodyYet);
3050 readerContext.fStartedBodyYet =
true;
3052 if (readerContext.fDefaultFontNumber != size_t (-1)) {
3055 IncrementalFontSpecification fontSpec = readerContext.GetCurrentGroupContext ()->fDestinationContext.fFontSpec;
3059 if (readerContext.fFontTable !=
nullptr) {
3060 IncrementalFontSpecification a = readerContext.fFontTable->GetFontSpec (readerContext.fDefaultFontNumber);
3061 if (a.GetFontNameSpecifier_Valid ()) {
3062 fontSpec.SetFontNameSpecifier (a.GetFontNameSpecifier ());
3065 newPlain.SetFontNameSpecifier (a.GetFontNameSpecifier ());
3066 SetPlainFont (newPlain);
3069 readerContext.GetDestination ().UseFont (readerContext.GetCurrentGroupContext ()->fDestinationContext.fFontSpec = fontSpec);
3073FontTableEntry StyledTextIOReader_RTF::ReadInFontTablesEntry ()
3079 FontTableEntry entry;
3081 if (GetNextChar () != RTFIO::kRTFOpenGroupChar) {
3086 while (PeekNextChar () == RTFIO::kRTFStartTagChar) {
3087 RTFIO::ControlWord cword = ReadControlWord ();
3088 switch (cword.fWord) {
3089 case RTFIO::eControlAtom_f: {
3090 if (not cword.fHasArg) {
3091 HandleBadlyFormattedInput ();
3094 entry.fFNum = cword.fValue;
3098 case RTFIO::eControlAtom_fnil:
3099 entry.fFamily = FontTableEntry::eNil;
3101 case RTFIO::eControlAtom_froman:
3102 entry.fFamily = FontTableEntry::eRoman;
3104 case RTFIO::eControlAtom_fswiss:
3105 entry.fFamily = FontTableEntry::eSwiss;
3107 case RTFIO::eControlAtom_fmodern:
3108 entry.fFamily = FontTableEntry::eModern;
3110 case RTFIO::eControlAtom_fscript:
3111 entry.fFamily = FontTableEntry::eScript;
3113 case RTFIO::eControlAtom_fdecor:
3114 entry.fFamily = FontTableEntry::eDecor;
3116 case RTFIO::eControlAtom_ftech:
3117 entry.fFamily = FontTableEntry::eTech;
3119 case RTFIO::eControlAtom_fbidi:
3120 entry.fFamily = FontTableEntry::eBidi;
3123 case RTFIO::eControlAtom_fcharset: {
3124 if (not cword.fHasArg) {
3125 HandleBadlyFormattedInput ();
3128 entry.fCharSet =
static_cast<uint8_t
> (cword.fValue);
3131 case RTFIO::eControlAtom_fprq: {
3132 if (not cword.fHasArg) {
3133 HandleBadlyFormattedInput ();
3136 entry.fPitch = cword.fValue;
3145 if (PeekNextChar () == RTFIO::kRTFOpenGroupChar) {
3147 SkipToEndOfCurrentGroup ();
3151 size_t startOfName = GetSrcStream ().current_offset ();
3152 ScanForwardFor (
"{;");
3153 entry.fFontName = String::FromNarrowSDKString (GrabString (startOfName)).AsSDKString ();
3156 if (PeekNextChar () == RTFIO::kRTFOpenGroupChar) {
3158 SkipToEndOfCurrentGroup ();
3161 ScanForwardFor (
"}");
3162 if (GetNextChar () != RTFIO::kRTFCloseGroupChar) {
3163 HandleBadlyFormattedInput (
true);
3170void StyledTextIOReader_RTF::ReadInObjectSubGroupEntry (ReaderContext& readerContext, vector<char>* data,
size_t* resultFoundAt)
3173 if (GetNextChar () != RTFIO::kRTFOpenGroupChar) {
3174 HandleBadlyFormattedInput (
true);
3177 if (PeekNextChar () == RTFIO::kRTFStartTagChar) {
3181 size_t xxxxxxx = readerContext.GetReader ().GetSrcStream ().current_offset ();
3182 RTFIO::ControlWord xxx = ReadControlWord ();
3183 if (xxx.fWord == RTFIO::eControlAtom_result) {
3184 *resultFoundAt = readerContext.GetReader ().GetSrcStream ().current_offset ();
3185 SkipToEndOfCurrentGroup ();
3189 GetSrcStream ().seek_to (xxxxxxx);
3196 if (PeekNextChar () ==
'*') {
3199 if (PeekNextChar () == RTFIO::kRTFStartTagChar) {
3200 RTFIO::ControlWord cword = ReadControlWord ();
3201 if (cword.fWord == RTFIO::eControlAtom_objdata) {
3208 SkipToEndOfCurrentGroup ();
3211void StyledTextIOReader_RTF::ReadObjData (vector<char>* data)
3216 for (
char c = PeekNextChar (); c != RTFIO::kRTFCloseGroupChar; c = PeekNextChar ()) {
3217 if (c ==
'\n' or c ==
'\r') {
3221 data->push_back (GetNextRTFHexByte ());
3223 Assert (PeekNextChar () == RTFIO::kRTFCloseGroupChar);
3227void StyledTextIOReader_RTF::ConstructOLEEmebddingFromRTFInfo ([[maybe_unused]] ReaderContext& readerContext, [[maybe_unused]] TWIPS_Point size,
3228 [[maybe_unused]]
size_t nBytes, [[maybe_unused]]
const void* data)
3230#if qStroika_Foundation_Common_Platform_Windows
3231 using RTFOLEEmbedding = RTFIO::RTFOLEEmbedding;
3233 const vector<EmbeddedObjectCreatorRegistry::Assoc>& types = EmbeddedObjectCreatorRegistry::Get ().GetAssocList ();
3234 for (
size_t i = 0; i < types.size (); ++i) {
3235 EmbeddedObjectCreatorRegistry::Assoc assoc = types[i];
3236 if (memcmp (assoc.fEmbeddingTag, RTFIO::RTFOLEEmbedding::kEmbeddingTag, sizeof (RTFIO::RTFOLEEmbedding::kEmbeddingTag)) == 0) {
3238 SimpleEmbeddedObjectStyleMarker* embedding = (assoc.fReadFromMemory) (RTFIO::RTFOLEEmbedding::kEmbeddingTag, data, nBytes);
3239 RTFOLEEmbedding* rtfe =
dynamic_cast<RTFOLEEmbedding*
> (embedding);
3240 if (rtfe !=
nullptr) {
3241 rtfe->PostCreateSpecifyExtraInfo (size);
3244 readerContext.GetDestination ().AppendEmbedding (embedding);
3257void StyledTextIOReader_RTF::ConstructLedEmebddingFromRTFInfo (ReaderContext& readerContext,
size_t nBytes,
const void* data)
3259#if qStroika_Frameworks_Led_SupportGDI
3262 if (nBytes <
sizeof (Led_PrivateEmbeddingTag)) {
3265 const char* tag = (
const char*)data;
3266 const char* theData = tag +
sizeof (Led_PrivateEmbeddingTag);
3267 size_t theDataNBytes = nBytes -
sizeof (Led_PrivateEmbeddingTag);
3268 const vector<EmbeddedObjectCreatorRegistry::Assoc>& types = EmbeddedObjectCreatorRegistry::Get ().GetAssocList ();
3269 for (
size_t i = 0; i < types.size (); ++i) {
3270 EmbeddedObjectCreatorRegistry::Assoc assoc = types[i];
3271 if (memcmp (assoc.fEmbeddingTag, tag, sizeof (assoc.fEmbeddingTag)) == 0) {
3273 SimpleEmbeddedObjectStyleMarker* embedding = (assoc.fReadFromMemory) (tag, theData, theDataNBytes);
3275 readerContext.GetDestination ().AppendEmbedding (embedding);
3288void StyledTextIOReader_RTF::ReadPictData (vector<char>* data)
3294 for (
char c = PeekNextChar (); c != RTFIO::kRTFCloseGroupChar and c != RTFIO::kRTFStartTagChar; c = PeekNextChar ()) {
3295 if (c ==
'\n' or c ==
'\r') {
3299 PUSH_BACK (*data, GetNextRTFHexByte ());
3301 Assert (PeekNextChar () == RTFIO::kRTFCloseGroupChar or PeekNextChar () == RTFIO::kRTFStartTagChar);
3308void StyledTextIOReader_RTF::ReadTopLevelPictData (TWIPS_Point* shownSize, ImageFormat* imageFormat, TWIPS_Point* bmSize, vector<char>* objData)
3310#if qStroika_Frameworks_Led_SupportGDI
3311 using UnknownRTFEmbedding = RTFIO::UnknownRTFEmbedding;
3313 using ControlWord = RTFIO::ControlWord;
3315 *imageFormat = eDefaultImageFormat;
3316 *shownSize = TWIPS_Point (TWIPS{0}, TWIPS{0});
3317 *bmSize = TWIPS_Point (TWIPS{0}, TWIPS{0});
3318 *objData = vector<char> ();
3319 float scaleX = 1.0f;
3320 float scaleY = 1.0f;
3323 switch (PeekNextChar ()) {
3324 case RTFIO::kRTFStartTagChar: {
3325 ControlWord cw = ReadControlWord ();
3327 case RTFIO::eControlAtom_emfblip:
3328 *imageFormat = eEMF;
3330 case RTFIO::eControlAtom_pngblip:
3331 *imageFormat = ePNG;
3333 case RTFIO::eControlAtom_jpegblip:
3334 *imageFormat = eJPEG;
3336 case RTFIO::eControlAtom_macpict:
3337 *imageFormat = eMacPICT;
3339 case RTFIO::eControlAtom_pmmetafile:
3340 *imageFormat = ePMMetaFile;
3342 case RTFIO::eControlAtom_wmetafile:
3343 *imageFormat = eWMF;
3345 case RTFIO::eControlAtom_dibitmap:
3346 *imageFormat = eDIB;
3348 case RTFIO::eControlAtom_wbitmap:
3349 *imageFormat = eBITMAP;
3351 case RTFIO::eControlAtom_picw:
3352 if (not cw.fHasArg) {
3353 HandleBadlyFormattedInput ();
3356 bmSize->h = TWIPS (cw.fValue);
3358 case RTFIO::eControlAtom_pich:
3359 if (not cw.fHasArg) {
3360 HandleBadlyFormattedInput ();
3363 bmSize->v = TWIPS (cw.fValue);
3365 case RTFIO::eControlAtom_picwgoal:
3366 if (not cw.fHasArg) {
3367 HandleBadlyFormattedInput ();
3370 shownSize->h = TWIPS (cw.fValue);
3372 case RTFIO::eControlAtom_pichgoal:
3373 if (not cw.fHasArg) {
3374 HandleBadlyFormattedInput ();
3377 shownSize->v = TWIPS (cw.fValue);
3379 case RTFIO::eControlAtom_picscalex:
3380 if (not cw.fHasArg) {
3381 HandleBadlyFormattedInput ();
3384 scaleX = cw.fValue / 100.0f;
3386 case RTFIO::eControlAtom_picscaley:
3387 if (not cw.fHasArg) {
3388 HandleBadlyFormattedInput ();
3391 scaleY = cw.fValue / 100.0f;
3396 case RTFIO::kRTFOpenGroupChar: {
3399 SkipToEndOfCurrentGroup ();
3402 case RTFIO::kRTFCloseGroupChar: {
3406 if (shownSize->h == 0) {
3407 shownSize->h = bmSize->h;
3409 if (shownSize->v == 0) {
3410 shownSize->v = bmSize->v;
3413 shownSize->h *= scaleX;
3414 shownSize->v *= scaleY;
3415#if qStroika_Frameworks_Led_SupportGDI
3416 if (shownSize->v > 20000 or shownSize->h > 20000 or shownSize->h < 10 or shownSize->v < 10) {
3417 *shownSize = UnknownRTFEmbedding::CalcStaticDefaultShownSize ();
3425 ReadPictData (objData);
3436Led_DIB* StyledTextIOReader_RTF::ConstructDIBFromData ([[maybe_unused]] TWIPS_Point shownSize, ImageFormat imageFormat,
3437 [[maybe_unused]] TWIPS_Point bmSize,
size_t nBytes,
const void* data)
3439 if (data ==
nullptr) {
3440 HandleBadlyFormattedInput ();
3443 switch (imageFormat) {
3445 const Led_DIB* dib =
reinterpret_cast<const Led_DIB*
> (data);
3446 if (Led_GetDIBImageByteCount (dib) != nBytes) {
3447 HandleBadlyFormattedInput ();
3450 return Led_CloneDIB (dib);
3452#if qStroika_Foundation_Common_Platform_Windows
3454 Led_DIB* result =
nullptr;
3455 HENHMETAFILE hMF = ::SetEnhMetaFileBits (
static_cast<UINT
> (nBytes),
reinterpret_cast<const unsigned char*
> (data));
3457 result = ConstructDIBFromEMFHelper (shownSize, bmSize, hMF);
3460 Verify (::DeleteEnhMetaFile (hMF));
3463 Verify (::DeleteEnhMetaFile (hMF));
3467 Led_DIB* result =
nullptr;
3468 HENHMETAFILE hMF = ::SetWinMetaFileBits (
static_cast<UINT
> (nBytes),
reinterpret_cast<const unsigned char*
> (data),
nullptr,
nullptr);
3470 result = ConstructDIBFromEMFHelper (shownSize, bmSize, hMF);
3473 Verify (::DeleteEnhMetaFile (hMF));
3476 Verify (::DeleteEnhMetaFile (hMF));
3484#if qStroika_Foundation_Common_Platform_Windows
3491Led_DIB* StyledTextIOReader_RTF::ConstructDIBFromEMFHelper (TWIPS_Point shownSize, [[maybe_unused]] TWIPS_Point bmSize,
const HENHMETAFILE hMF)
3495 ENHMETAHEADER header{};
3496 Verify (::GetEnhMetaFileHeader (hMF,
sizeof (header), &header) ==
sizeof (header));
3499 Tablet screenDC = (::GetWindowDC (
nullptr));
3501 DistanceType hSize = screenDC.CvtFromTWIPSH (shownSize.h);
3502 DistanceType vSize = screenDC.CvtFromTWIPSV (shownSize.v);
3503 Led_Rect imageRect = Led_Rect (0, 0, vSize, hSize);
3506 Bitmap memoryBitmap;
3511 HBITMAP oldBitmapInDC = memDC.SelectObject (memoryBitmap);
3515 Led_Rect eraser = imageRect;
3516 Color eraseColor = Led_GetTextBackgroundColor ();
3517 Brush backgroundBrush (eraseColor.GetOSRep ());
3518 GDI_Obj_Selector pen (&memDC, ::GetStockObject (NULL_PEN));
3519 GDI_Obj_Selector brush (&memDC, backgroundBrush);
3522 memDC.Rectangle (AsRECT (eraser));
3526 HPALETTE usePalette =
nullptr;
3528 UINT nPalEntries = ::GetEnhMetaFilePaletteEntries (hMF, 0,
nullptr);
3529 Assert (nPalEntries != GDI_ERROR);
3530 if (nPalEntries != 0) {
3531 LOGPALETTE* paletteData =
reinterpret_cast<LOGPALETTE*
> (
new char[
sizeof (LOGPALETTE) + nPalEntries *
sizeof (PALETTEENTRY)]);
3532 paletteData->palVersion = 0;
3533 paletteData->palNumEntries =
static_cast<WORD
> (nPalEntries);
3534 Verify (::GetEnhMetaFilePaletteEntries (hMF, nPalEntries, paletteData->palPalEntry) == nPalEntries);
3535 usePalette = ::CreatePalette (paletteData);
3536 delete[] (
char*)paletteData;
3539 HPALETTE oldPalette =
nullptr;
3540 if (usePalette !=
nullptr) {
3541 oldPalette = ::SelectPalette (memDC, usePalette,
true);
3542 ::RealizePalette (memDC);
3546 bool failed =
false;
3548 RECT rect = AsRECT (imageRect);
3549 if (PlayEnhMetaFile (memDC.m_hDC, hMF, &rect) == 0) {
3554 if (oldPalette !=
nullptr) {
3555 ::SelectPalette (memDC, oldPalette,
true);
3557 if (usePalette !=
nullptr) {
3558 ::DeleteObject (usePalette);
3560 if (oldBitmapInDC !=
nullptr) {
3561 (void)memDC.SelectObject (oldBitmapInDC);
3564 HandleBadlyFormattedInput ();
3569 return Led_DIBFromHBITMAP (memDC.m_hDC, memoryBitmap);
3573void StyledTextIOReader_RTF::ApplyFontSpec (ReaderContext& readerContext,
const RTFIO::ControlWord& cw)
3575 CheckIfAboutToStartBody (readerContext);
3576 if (readerContext.GetCurrentGroupContext () ==
nullptr) {
3577 HandleBadlyFormattedInput (
true);
3579 IncrementalFontSpecification fontSpec = readerContext.GetCurrentGroupContext ()->fDestinationContext.fFontSpec;
3582 case RTFIO::eControlAtom_plain: {
3583 fontSpec = GetPlainFont ();
3585 readerContext.GetDestination ().SetTextHidden (readerContext.GetCurrentGroupContext ()->fDestinationContext.fTextHidden =
false);
3588 case RTFIO::eControlAtom_cf: {
3589 if (not cw.fHasArg) {
3590 HandleBadlyFormattedInput ();
3593 fontSpec.SetTextColor (LookupColor (readerContext,
static_cast<size_t> (cw.fValue)));
3596 case RTFIO::eControlAtom_f: {
3597 if (readerContext.fFontTable ==
nullptr) {
3602 if (not cw.fHasArg) {
3603 HandleBadlyFormattedInput (
true);
3605 IncrementalFontSpecification a = readerContext.fFontTable->GetFontSpec (cw.fValue);
3606 if (a.GetFontNameSpecifier_Valid ()) {
3607 fontSpec.SetFontNameSpecifier (a.GetFontNameSpecifier ());
3611 const FontTableEntry* fte = readerContext.fFontTable->LookupEntryByNumber (cw.fValue);
3612 if (fte ==
nullptr) {
3619#if qStroika_Foundation_Common_Platform_Windows
3620 if (fte->fCharSet != -1) {
3622 CodePage cp = Platform::Windows::Win32CharSetToCodePage (fte->fCharSet);
3624 readerContext.GetCurrentGroupContext ()->fCurrentCodePage = cp;
3626 readerContext.UseInputCharSetEncoding (readerContext.GetCurrentGroupContext ()->fCurrentCodePage);
3631 case RTFIO::eControlAtom_fs: {
3632 if (not cw.fHasArg) {
3633 HandleBadlyFormattedInput (
true);
3635 int newSize = cw.fValue / 2;
3639 if (newSize > 128) {
3642#if qStroika_Foundation_Common_Platform_Windows
3643 if (newSize == fCachedFontSize) {
3644 fontSpec.PokeAtTMHeight (fCachedFontSizeTMHeight);
3648 fontSpec.SetPointSize (
static_cast<FontSpecification::FontSize
> (newSize));
3649#if qStroika_Foundation_Common_Platform_Windows
3650 fCachedFontSize =
static_cast<FontSpecification::FontSize
> (newSize);
3651 fCachedFontSizeTMHeight = fontSpec.PeekAtTMHeight ();
3655 case RTFIO::eControlAtom_b: {
3656 bool turnStyleOn =
true;
3658 turnStyleOn = cw.fValue;
3660 fontSpec.SetStyle_Bold (turnStyleOn);
3663 case RTFIO::eControlAtom_i: {
3664 bool turnStyleOn =
true;
3666 turnStyleOn = cw.fValue;
3668 fontSpec.SetStyle_Italic (turnStyleOn);
3671 case RTFIO::eControlAtom_sub: {
3672 fontSpec.SetStyle_SubOrSuperScript (FontSpecification::eSubscript);
3674 case RTFIO::eControlAtom_super: {
3675 fontSpec.SetStyle_SubOrSuperScript (FontSpecification::eSuperscript);
3677 case RTFIO::eControlAtom_strike: {
3678#if qStroika_Foundation_Common_Platform_Windows
3679 bool turnStyleOn =
true;
3681 turnStyleOn = cw.fValue;
3683 fontSpec.SetStyle_Strikeout (turnStyleOn);
3686 case RTFIO::eControlAtom_ul: {
3687 bool turnStyleOn =
true;
3689 turnStyleOn = cw.fValue;
3691 fontSpec.SetStyle_Underline (turnStyleOn);
3694 case RTFIO::eControlAtom_ulnone: {
3695 fontSpec.SetStyle_Underline (
false);
3698 readerContext.GetDestination ().UseFont (readerContext.GetCurrentGroupContext ()->fDestinationContext.fFontSpec = fontSpec);
3701unsigned char StyledTextIOReader_RTF::GetNextRTFHexByte ()
const
3703 char c = GetNextChar ();
3706 while (c ==
'\n' or c ==
'\r') {
3709 unsigned char value =
'\0';
3710 if (c >=
'0' and c <=
'9') {
3713 else if (c >=
'a' and c <=
'f') {
3714 value = c -
'a' + 10;
3716 else if (c >=
'A' and c <=
'F') {
3717 value = c -
'A' + 10;
3721 HandleBadlyFormattedInput (
true);
3726 while (c ==
'\n' or c ==
'\r') {
3729 unsigned char value2 =
'\0';
3730 if (c >=
'0' and c <=
'9') {
3733 else if (c >=
'a' and c <=
'f') {
3734 value2 = c -
'a' + 10;
3736 else if (c >=
'A' and c <=
'F') {
3737 value2 = c -
'A' + 10;
3741 HandleBadlyFormattedInput (
true);
3748string StyledTextIOReader_RTF::ReadInGroupAndSave ()
3750 size_t startOfGroup = GetSrcStream ().current_offset ();
3751 if (GetNextChar () != RTFIO::kRTFOpenGroupChar) {
3752 HandleBadlyFormattedInput (
true);
3754 SkipToEndOfCurrentGroup ();
3755 return GrabString (startOfGroup);
3758void StyledTextIOReader_RTF::SkipToEndOfCurrentGroup ()
3761 for (; depth > 0;) {
3762 ScanForwardFor (
"{}");
3763 switch (PeekNextChar ()) {
3764 case RTFIO::kRTFOpenGroupChar: {
3768 case RTFIO::kRTFCloseGroupChar: {
3779void StyledTextIOReader_RTF::ScanForwardFor (
const char* setOfChars)
3783#if qUseCompiledSetHack
3784 bitset<256> compiledSet;
3785 for (
auto p = setOfChars; *p !=
'\0'; ++p) {
3786 compiledSet[(
unsigned char)*p] =
true;
3791 for (
char c = GetNextChar ();; c = GetNextChar ()) {
3792 if (c == RTFIO::kRTFQuoteNextCharChar) {
3795#if qUseCompiledSetHack
3796 if (compiledSet[(
unsigned char)c]) {
3801 for (
const char* p = setOfChars; *p !=
'\0'; ++p) {
3810 catch (ReadEOFException&) {
3823bool StyledTextIOReader_RTF::SearchForwardFor (
const char* searchFor,
size_t maxCharsToExamine)
3826 SrcStream& srcStream = GetSrcStream ();
3827 size_t origOffset = srcStream.current_offset ();
3828 size_t matchStrLen = ::strlen (searchFor);
3829 Require (matchStrLen >= 1);
3833 for (; (c = GetNextChar ()) !=
'\0';) {
3834 if (c == *searchFor) {
3836 size_t foundAt = srcStream.current_offset () - 1;
3837 for (c = GetNextChar (); matchStrLen > (srcStream.current_offset () - foundAt); c = GetNextChar ()) {
3838 size_t idx = srcStream.current_offset () - foundAt - 1;
3839 if (searchFor[idx] == c) {
3844 srcStream.seek_to (foundAt + 1);
3845 goto RetryNextMatch;
3849 Assert (matchStrLen == srcStream.current_offset () - foundAt);
3850 srcStream.seek_to (foundAt);
3853 if (srcStream.current_offset () > origOffset + maxCharsToExamine) {
3854 srcStream.seek_to (origOffset);
3859 catch (ReadEOFException) {
3860 srcStream.seek_to (origOffset);
3864 srcStream.seek_to (origOffset);
3870RTFInfo& StyledTextIOReader_RTF::GetRTFInfo ()
const
3881size_t StyledTextIOWriter_RTF::WriterContext::GetCurSrcOffset ()
const
3883 return GetSrcStream ().current_offset ();
3886#if qStroika_Frameworks_Led_SupportGDI
3887SimpleEmbeddedObjectStyleMarker* StyledTextIOWriter_RTF::WriterContext::GetCurSimpleEmbeddedObjectStyleMarker ()
const
3889 size_t offset = GetCurSrcOffset ();
3890 vector<SimpleEmbeddedObjectStyleMarker*> embeddingsList = GetSrcStream ().CollectAllEmbeddingMarkersInRange (offset - 1, offset);
3891 Assert (embeddingsList.size () <= 1);
3894 if (embeddingsList.empty ()) {
3898 return embeddingsList[0];
3903StyledTextIOWriter_RTF::Table* StyledTextIOWriter_RTF::WriterContext::GetCurRTFTable ()
const
3905 return GetSrcStream ().GetTableAt (GetCurSrcOffset () - 1);
3913StyledTextIOWriter_RTF::StyledTextIOWriter_RTF (SrcStream* srcStream, SinkStream* sinkStream, RTFInfo* rtfInfo)
3914 : StyledTextIOWriter (srcStream, sinkStream)
3915 , fCurrentOutputCharSetEncoding{WellKnownCodePages::kANSI}
3917 , fDocumentCharacterSet{WellKnownCodePages::kANSI}
3918 , fSoftLineBreakChar (srcStream->GetSoftLineBreakCharacter ())
3919 , fHidableTextRuns (srcStream->GetHidableTextRuns ())
3921 static const pair<string, wchar_t> kCharsWrittenByName[] = {
3922 pair<string, wchar_t> (
"tab", L
'\x0009'), pair<string, wchar_t> (
"emdash", L
'\x2013'),
3923 pair<string, wchar_t> (
"endash", L
'\x2014'), pair<string, wchar_t> (
"lquote", L
'\x2018'),
3924 pair<string, wchar_t> (
"rquote", L
'\x2019'), pair<string, wchar_t> (
"ldblquote", L
'\x201c'),
3925 pair<string, wchar_t> (
"rdblquote", L
'\x201d'),
3927 SetCharactersSavedByName (vector<pair<string, wchar_t>> (&kCharsWrittenByName[0], &kCharsWrittenByName[Memory::NEltsOf (kCharsWrittenByName)]));
3930StyledTextIOWriter_RTF::~StyledTextIOWriter_RTF ()
3937void StyledTextIOWriter_RTF::UseOutputCharSetEncoding (
CodePage codePage)
3939 fCurrentOutputCharSetEncoding = codePage;
3942void StyledTextIOWriter_RTF::SetCharactersSavedByName (
const vector<pair<string, wchar_t>>& charactersSavedByName)
3944 fCharactersSavedByName = charactersSavedByName;
3945 for (vector<pair<string, wchar_t>>::const_iterator i = fCharactersSavedByName.begin (); i != fCharactersSavedByName.end (); ++i) {
3946 fCharactersSavedByName_Name2Char.insert (map<string, wchar_t>::value_type (i->first, i->second));
3947 fCharactersSavedByName_Char2Name.insert (map<wchar_t, string>::value_type (i->second, i->first));
3951void StyledTextIOWriter_RTF::Write ()
3953 WriterContext writerContext (*
this);
3955 write (RTFIO::kRTFOpenGroupChar);
3956 WriteHeader (writerContext);
3957 WriteBody (writerContext);
3958 write (RTFIO::kRTFCloseGroupChar);
3961void StyledTextIOWriter_RTF::WriteHeader (WriterContext& writerContext)
3965 WriteFontTable (writerContext);
3966 WriteColorTable (writerContext);
3968 if (fRTFInfo !=
nullptr) {
3969 WriteTagNValue (
"deftab", fRTFInfo->fDefaultTabStop);
3974void StyledTextIOWriter_RTF::WriteBody (WriterContext& writerContext)
3981 AssureStyleRunSummaryBuilt (writerContext);
3983 WriteStartParagraph (writerContext);
3984 writerContext.fLastEmittedISR = StyledInfoSummaryRecord (IncrementalFontSpecification (), 0);
3985 writerContext.fNextStyleChangeAt = 0;
3986 writerContext.fIthStyleRun = 0;
3987 if (not fHidableTextRuns.empty ()) {
3988 writerContext.fNextHidableTextChangeAt = fHidableTextRuns[0].fOffsetFromPrev;
3991 while (writerContext.GetSrcStream ().readNTChars (&c, 1) != 0) {
3992 WriteBodyCharacter (writerContext, c);
3994 if (writerContext.fHidableTextRegionOpen) {
3996 writerContext.fNextHidableTextChangeAt = size_t (-1);
4000void StyledTextIOWriter_RTF::WriteBodyCharacter (WriterContext& writerContext, Led_tChar c)
4008 if (writerContext.GetCurSrcOffset () - 1 == writerContext.fNextHidableTextChangeAt) {
4009 if (writerContext.fHidableTextRegionOpen) {
4011 ++writerContext.fIthHidableTextRun;
4012 if (writerContext.fIthHidableTextRun < fHidableTextRuns.size ()) {
4013 writerContext.fNextHidableTextChangeAt += fHidableTextRuns[writerContext.fIthHidableTextRun].fOffsetFromPrev;
4016 writerContext.fNextHidableTextChangeAt = size_t (-1);
4022 writerContext.fNextHidableTextChangeAt += fHidableTextRuns[writerContext.fIthHidableTextRun].fElementLength;
4024 writerContext.fHidableTextRegionOpen = not writerContext.fHidableTextRegionOpen;
4028 if (writerContext.GetCurSrcOffset () - 1 == writerContext.fNextStyleChangeAt) {
4029 const StyledInfoSummaryRecord& nextStyleRun = fStyleRunSummary[writerContext.fIthStyleRun];
4030 if (writerContext.GetCurSrcOffset () <= 1) {
4031 EmitBodyFontInfoChange (writerContext, nextStyleRun);
4034 EmitBodyFontInfoChange (writerContext, nextStyleRun, writerContext.fLastEmittedISR);
4036 writerContext.fLastEmittedISR = nextStyleRun;
4037 writerContext.fNextStyleChangeAt += writerContext.fLastEmittedISR.fLength;
4038 ++writerContext.fIthStyleRun;
4041 if (writerContext.fCharsToSkip > 0) {
4042 --writerContext.fCharsToSkip;
4049 WriteStartParagraph (writerContext);
4064#if qStroika_Frameworks_Led_SupportGDI
4065 case kEmbeddingSentinelChar: {
4066 unique_ptr<StyledTextIOWriter_RTF::Table> table (writerContext.GetCurRTFTable ());
4067 if (table.get () !=
nullptr) {
4068 Assert (writerContext.fCharsToSkip == 0);
4069 WriteTable (writerContext, table.get ());
4070 size_t x = table->GetOffsetEnd ();
4072 writerContext.fCharsToSkip = x - 1;
4076 SimpleEmbeddedObjectStyleMarker* embedding = writerContext.GetCurSimpleEmbeddedObjectStyleMarker ();
4077 if (embedding ==
nullptr) {
4078 WriteHexCharHelper (kEmbeddingSentinelChar);
4081 if (PossiblyWriteUnknownRTFEmbedding (writerContext, embedding)) {
4084 else if (PossiblyWriteOLERTFEmbedding (writerContext, embedding)) {
4087 else if (PossiblyWritePICTEmbedding (writerContext, embedding)) {
4090 WritePrivatLedEmbedding (writerContext, embedding);
4096 if (c == fSoftLineBreakChar) {
4100 map<wchar_t, string>::const_iterator i = fCharactersSavedByName_Char2Name.find (c);
4102 if (i == fCharactersSavedByName_Char2Name.end ()) {
4103 WritePlainUnicodeCharCharacterHelper (uc);
4106 WriteTag ((*i).second.c_str ());
4111 if ((writerContext.GetCurSrcOffset ()) % 80 == 0) {
4117void StyledTextIOWriter_RTF::WritePlainUnicodeCharCharacterHelper (
wchar_t c)
4120 size_t mbCharCount = 2;
4124 .Characters2Bytes (Memory::SpanBytesCast<span<char16_t>> (span{&c, 1}), Memory::SpanBytesCast<span<byte>> (span{mbCharBuf}))
4126 Assert (mbCharCount == 1 or mbCharCount == 2);
4128 bool needToWriteUNICODE = c >= 0x80;
4129 if (needToWriteUNICODE) {
4131 WriteTagNValue (
"uc",
static_cast<int> (mbCharCount));
4132 WriteTagNValue (
"u", c);
4135 unsigned char uc = mbCharBuf[0];
4140 WriteHexCharHelper (uc);
4142 if (mbCharCount == 2) {
4148 WriteHexCharHelper (uc);
4153void StyledTextIOWriter_RTF::WriteHexCharHelper (
unsigned char c)
4159 buf[2] = ConvertWriteSingleHexDigit_ (c / 16);
4160 buf[3] = ConvertWriteSingleHexDigit_ (c % 16);
4165void StyledTextIOWriter_RTF::WriteStartParagraph (WriterContext& writerContext)
4168 if (writerContext.fInTable) {
4171 switch (writerContext.GetSrcStream ().GetJustification ()) {
4172 case eCenterJustify:
4184 StandardTabStopList tabStops = writerContext.GetSrcStream ().GetStandardTabStopList ();
4187 TWIPS tabSoFar = TWIPS{0};
4188 for (
size_t i = 0; i < tabStops.fTabStops.size (); ++i) {
4189 tabSoFar += tabStops.fTabStops[i];
4190 WriteTagNValue (
"tx", tabSoFar);
4194 TWIPS fi = writerContext.GetSrcStream ().GetFirstIndent ();
4196 WriteTagNValue (
"fi", fi);
4201 TWIPS lhs = TWIPS{0};
4202 TWIPS rhs = TWIPS{0};
4203 writerContext.GetSrcStream ().GetMargins (&lhs, &rhs);
4205 WriteTagNValue (
"li", lhs);
4208 TWIPS effectiveDrawingWidth = fRTFInfo ==
nullptr ? RTFInfo ().GetEffectiveDrawingWidth () : fRTFInfo->GetEffectiveDrawingWidth ();
4209 TWIPS rhsRTFMarginInTWIPS = TWIPS (effectiveDrawingWidth - rhs);
4210 if (rhsRTFMarginInTWIPS != 0) {
4211 WriteTagNValue (
"ri", rhsRTFMarginInTWIPS);
4216 TWIPS sb = writerContext.GetSrcStream ().GetSpaceBefore ();
4218 WriteTagNValue (
"sb", sb);
4222 TWIPS sa = writerContext.GetSrcStream ().GetSpaceAfter ();
4224 WriteTagNValue (
"sa", sa);
4228 LineSpacing sl = writerContext.GetSrcStream ().GetLineSpacing ();
4229 if (sl.fRule != LineSpacing::eSingleSpace) {
4230 CoordinateType rtfsl = 1000;
4232 mkRTFValues_From_LineSpacing (sl, &rtfsl, &multi);
4233 if (rtfsl != 1000) {
4234 WriteTagNValue (
"sl", rtfsl);
4235 WriteTagNValue (
"slmult", multi);
4240 ListStyle listStyle = eListStyle_None;
4241 unsigned char indentLevel = 0;
4242 writerContext.GetSrcStream ().GetListStyleInfo (&listStyle, &indentLevel);
4243 if (listStyle != eListStyle_None) {
4247 WriteTag (
"listtext");
4254 int listTableID = 1;
4255 WriteTagNValue (
"ls", listTableID);
4256 if (indentLevel != 0) {
4257 WriteTagNValue (
"ilvl", indentLevel);
4263void StyledTextIOWriter_RTF::WriteTable (WriterContext& writerContext, Table* table)
4265 using CellInfo = StyledTextIOWriter_RTF::Table::CellInfo;
4269 size_t rows = table->GetRows ();
4270 for (
size_t r = 0; r < rows; ++r) {
4273 TWIPS_Rect cellMargins = table->GetDefaultCellMarginsForRow (r);
4274 TWIPS_Rect cellSpacing = table->GetDefaultCellSpacingForRow (r);
4276 WriteTagNValue (
"trgaph", (cellMargins.top + cellMargins.left + cellMargins.bottom + cellMargins.right) / 4);
4279 if (cellSpacing.top != 0) {
4280 WriteTagNValue (
"trspdt", cellSpacing.top / 2);
4281 WriteTagNValue (
"trspdft", 3);
4283 if (cellSpacing.left != 0) {
4284 WriteTagNValue (
"trspdl", cellSpacing.left / 2);
4285 WriteTagNValue (
"trspdfl", 3);
4287 if (cellSpacing.bottom != 0) {
4288 WriteTagNValue (
"trspdb", cellSpacing.bottom / 2);
4289 WriteTagNValue (
"trspdfb", 3);
4291 if (cellSpacing.right != 0) {
4292 WriteTagNValue (
"trspdr", cellSpacing.right / 2);
4293 WriteTagNValue (
"trspdfr", 3);
4298 if (cellMargins.top != 0) {
4299 WriteTagNValue (
"trpaddt", cellMargins.top);
4300 WriteTagNValue (
"trpaddft", 3);
4302 if (cellMargins.left != 0) {
4303 WriteTagNValue (
"trpaddl", cellMargins.left);
4304 WriteTagNValue (
"trpaddfl", 3);
4306 if (cellMargins.bottom != 0) {
4307 WriteTagNValue (
"trpaddb", cellMargins.bottom);
4308 WriteTagNValue (
"trpaddfb", 3);
4310 if (cellMargins.right != 0) {
4311 WriteTagNValue (
"trpaddr", cellMargins.right);
4312 WriteTagNValue (
"trpaddfr", 3);
4316 vector<CellInfo> cellInfos;
4317 table->GetRowInfo (r, &cellInfos);
4318 size_t columns = cellInfos.size ();
4321 TWIPS cellxSoFar = TWIPS{0};
4322 for (vector<CellInfo>::const_iterator i = cellInfos.begin (); i != cellInfos.end (); ++i) {
4323 WriteTagNValue (
"clcbpat",
static_cast<int> (fColorTable->LookupColor (i->f_clcbpat)));
4328 TWIPS cellWidthIncludingSpacing = (*i).f_cellx + TWIPS (3 * cellSpacing.left / 2);
4330 cellxSoFar += cellWidthIncludingSpacing;
4331 WriteTagNValue (
"cellx", cellxSoFar);
4335#if qStroika_Foundation_Debug_AssertionsChecked
4336 size_t nCellsWritten = 0;
4338 for (
size_t c = 0; c < columns; ++c) {
4339 unique_ptr<StyledTextIOWriter::SrcStream> srcStream = unique_ptr<StyledTextIOWriter::SrcStream>{table->MakeCellSubSrcStream (r, c)};
4340 if (srcStream.get () !=
nullptr) {
4341 WriterContext wc{writerContext, *srcStream.get ()};
4342 vector<StyledInfoSummaryRecord> x = fStyleRunSummary;
4343 fStyleRunSummary.clear ();
4344 AssureStyleRunSummaryBuilt (wc);
4346 fStyleRunSummary = x;
4348#if qStroika_Foundation_Debug_AssertionsChecked
4353#if qStroika_Foundation_Debug_AssertionsChecked
4354 Assert (nCellsWritten == cellInfos.size ());
4362 WriteStartParagraph (writerContext);
4366#if qStroika_Frameworks_Led_SupportGDI
4367bool StyledTextIOWriter_RTF::PossiblyWriteUnknownRTFEmbedding (WriterContext& , SimpleEmbeddedObjectStyleMarker* embedding)
4370 if (RTFIO::UnknownRTFEmbedding* ee =
dynamic_cast<RTFIO::UnknownRTFEmbedding*
> (embedding)) {
4377 if (memcmp (ee->GetTag (), RTFIO::kRTFBodyGroupFragmentEmbeddingTag, sizeof (RTFIO::kRTFBodyGroupFragmentEmbeddingTag)) == 0) {
4378 write (ee->GetData (), ee->GetDataLength ());
4385bool StyledTextIOWriter_RTF::PossiblyWriteOLERTFEmbedding (WriterContext& , SimpleEmbeddedObjectStyleMarker* embedding)
4388 if (RTFIO::RTFOLEEmbedding* anRTFOLEEmbedding =
dynamic_cast<RTFIO::RTFOLEEmbedding*
> (embedding)) {
4391 byte* theDataBytes =
nullptr;
4392 anRTFOLEEmbedding->DoWriteToOLE1Stream (&nBytes, &theDataBytes);
4396 WriteTag (
"object");
4397 WriteTag (
"objemb");
4398 Led_Size size = anRTFOLEEmbedding->GetSize ();
4399 WriteTagNValue (
"objh", Led_CvtScreenPixelsToTWIPSV (size.v));
4400 WriteTagNValue (
"objw", Led_CvtScreenPixelsToTWIPSH (size.h));
4406 string className = String::FromSDKString (anRTFOLEEmbedding->GetObjClassName ()).AsNarrowSDKString ();
4407 if (not className.empty ()) {
4408 write (
"{\\*\\objclass ");
4411 write (className.c_str ());
4417 write (
"\\*\\objdata ");
4418 WriteHexCharDataBlock (nBytes, theDataBytes);
4419 delete[] theDataBytes;
4437#define qWriteAsDIB 1
4438bool StyledTextIOWriter_RTF::PossiblyWritePICTEmbedding (WriterContext& , SimpleEmbeddedObjectStyleMarker* embedding)
4441 if (StandardDIBStyleMarker* aPictEmbedding =
dynamic_cast<StandardDIBStyleMarker*
> (embedding)) {
4445 const Led_DIB* dib = aPictEmbedding->GetDIBData ();
4446 Led_Size size = Led_GetDIBImageSize (dib);
4448 int vEnhSize = size.v * (1400 / 10) * 2.54;
4449 int hEnhSize = size.h * (1400 / 10) * 2.54;
4450 WriteTagNValue (
"pich", size.v * 20);
4451 WriteTagNValue (
"picw", size.h * 20);
4453 WriteTagNValue (
"pichgoal", Led_CvtScreenPixelsToTWIPSV (size.v));
4454 WriteTagNValue (
"picwgoal", Led_CvtScreenPixelsToTWIPSH (size.h));
4457 WriteTag (
"dibitmap");
4458 const void* theDataBytes = dib;
4459 size_t nBytes = Led_GetDIBImageByteCount (dib);
4462 WriteTagNValue (
"pich", Led_CvtScreenPixelsToTWIPSV (size.v));
4463 WriteTagNValue (
"picw", Led_CvtScreenPixelsToTWIPSH (size.h));
4464 WriteTagNValue (
"wbmbitspixel", dib->bmiHeader.biBitCount == 0 ? 24 : dib->bmiHeader.biBitCount);
4465 WriteTagNValue (
"wbmplanes", dib->bmiHeader.biPlanes == 0 ? 1 : dib->bmiHeader.biPlanes);
4466 WriteTagNValue (
"wbmwidthbytes",
static_cast<int> (Led_GetDIBImageRowByteCount (dib)));
4468 WriteTagNValue (
"wmetafile", 8);
4470 void* theDataBytes =
nullptr;
4472 unique_ptr<BYTE> theDataBytes_;
4474 Tablet screenDC = (::GetWindowDC (
nullptr));
4475 UINT mapMode = MM_TEXT;
4477 HENHMETAFILE hMF =
nullptr;
4479 RECT rect = AsRECT (Led_Rect (0, 0, vEnhSize, hEnhSize));
4480 HDC hMFDC = ::CreateEnhMetaFile (
nullptr,
nullptr, &rect,
nullptr);
4481 ::SetMapMode (hMFDC, mapMode);
4482 const char* lpBits =
reinterpret_cast<const char*
> (dib) + Led_GetDIBPalletByteCount (dib) +
sizeof (BITMAPINFOHEADER);
4483 Assert (mapMode == MM_TWIPS or mapMode == MM_TEXT);
4484 if (mapMode == MM_TWIPS) {
4485 ::StretchDIBits (hMFDC, 0, 0, Led_CvtScreenPixelsToTWIPSH (size.h), Led_CvtScreenPixelsToTWIPSV (size.v), 0, 0, size.h,
4486 size.v, lpBits, dib, DIB_RGB_COLORS, SRCCOPY);
4488 else if (mapMode == MM_TEXT) {
4489 ::StretchDIBits (hMFDC, 0, 0, size.h, size.v, 0, 0, size.h, size.v, lpBits, dib, DIB_RGB_COLORS, SRCCOPY);
4491 hMF = ::CloseEnhMetaFile (hMFDC);
4493 nBytes = ::GetWinMetaFileBits (hMF, 0,
nullptr, mapMode, screenDC);
4498 BYTE* bytes =
new BYTE[nBytes];
4499 Verify (::GetWinMetaFileBits (hMF, nBytes, bytes, mapMode, screenDC) == nBytes);
4501 theDataBytes = bytes;
4502 theDataBytes_ = unique_ptr<BYTE> (bytes);
4504 ::DeleteEnhMetaFile (hMF);
4510 WriteHexCharDataBlock (nBytes, theDataBytes);
4521#if qGCC_OptBugWithLocalClassesScopedInFunction
4522struct VectorSinkStream : SimpleEmbeddedObjectStyleMarker::SinkStream {
4524 virtual void write (
const void* buffer,
size_t bytes)
override
4526 using ci =
const char*;
4527 fData.insert (fData.end (), ci (buffer), ci (buffer) + bytes);
4532#if qStroika_Frameworks_Led_SupportGDI
4533void StyledTextIOWriter_RTF::WritePrivatLedEmbedding (WriterContext& , SimpleEmbeddedObjectStyleMarker* embedding)
4535#if qBorlandNameInLocalFunctDeclarationSpaceCompilerBug
4536 using namespace Led;
4538#if !qGCC_OptBugWithLocalClassesScopedInFunction
4539 struct VectorSinkStream : SimpleEmbeddedObjectStyleMarker::SinkStream {
4541 virtual void write (
const void* buffer,
size_t bytes)
override
4543 using ci =
const char*;
4544 fData.insert (fData.end (), ci (buffer), ci (buffer) + bytes);
4549 VectorSinkStream embeddingData;
4550 embedding->Write (embeddingData);
4554 WriteTag (
"object");
4555 WriteTag (
"ledprivateobjectembeddingformat");
4561 write (
"\\*\\objdata ");
4562 WriteHexCharDataBlock (
sizeof (Led_PrivateEmbeddingTag), embedding->GetTag ());
4563 WriteHexCharDataBlock (embeddingData.fData.size (), &embeddingData.fData.front ());
4573void StyledTextIOWriter_RTF::WriteTag (
const char* tagStr)
4576 Require (tagStr[0] !=
'\\');
4577 Require (::strchr (tagStr,
' ') == 0);
4583void StyledTextIOWriter_RTF::WriteTagNValue (
const char* tagStr,
int value)
4586 Require (tagStr[0] !=
'\\');
4587 Require (::strchr (tagStr,
' ') == 0);
4591 (void)snprintf (buf, Memory::NEltsOf (buf),
"%d", value);
4596void StyledTextIOWriter_RTF::WriteHexCharDataBlock (
size_t nBytes,
const void* resultData)
4598 const unsigned char* start = (
const unsigned char*)resultData;
4599 const unsigned char* end = start + nBytes;
4600 for (
const unsigned char* cur = start; cur != end; ++cur) {
4601 WriteRTFHexByte (*cur);
4602 if ((cur - start) % 50 == 0) {
4609void StyledTextIOWriter_RTF::WriteRTFHexByte (
unsigned char theByte)
4611 unsigned char hiNibble = (theByte) >> 4;
4612 unsigned char lowNibble = (theByte) & 0xf;
4613 Require (hiNibble <= 0xf);
4614 Require (lowNibble <= 0xf);
4615 write (ConvertWriteSingleHexDigit_ (hiNibble));
4616 write (ConvertWriteSingleHexDigit_ (lowNibble));
4619void StyledTextIOWriter_RTF::WriteDocCharset ()
4621 switch (fDocumentCharacterSet) {
4622 case WellKnownCodePages::kANSI:
4625 case WellKnownCodePages::kMAC:
4628 case WellKnownCodePages::kPC:
4631 case WellKnownCodePages::kPCA:
4640void StyledTextIOWriter_RTF::WriteFontTable (WriterContext& writerContext)
4643 WriteTag (
"fonttbl");
4645 AssureFontTableBuilt (writerContext);
4648 size_t entryCount = fFontTable->fEntries.size ();
4649 for (
size_t i = 0; i < entryCount; ++i) {
4650 WriteFontTablesEntry (fFontTable->fEntries[i]);
4656void StyledTextIOWriter_RTF::WriteFontTablesEntry (
const FontTableEntry& entry)
4660 WriteTagNValue (
"f", entry.fFNum);
4662 switch (entry.fFamily) {
4663 case FontTableEntry::eNil:
4666 case FontTableEntry::eRoman:
4667 WriteTag (
"froman");
4669 case FontTableEntry::eSwiss:
4670 WriteTag (
"fswiss");
4672 case FontTableEntry::eModern:
4673 WriteTag (
"fmodern");
4675 case FontTableEntry::eScript:
4676 WriteTag (
"fscript");
4678 case FontTableEntry::eDecor:
4679 WriteTag (
"fdecor");
4681 case FontTableEntry::eTech:
4684 case FontTableEntry::eBidi:
4689 if (entry.fCharSet !=
static_cast<uint8_t
> (-1)) {
4690 WriteTagNValue (
"fcharset", entry.fCharSet);
4693 if (entry.fPitch != 0) {
4694 WriteTagNValue (
"fprq", entry.fPitch);
4697 write (String::FromSDKString (entry.fFontName).AsNarrowSDKString ());
4704void StyledTextIOWriter_RTF::WriteColorTable (WriterContext& writerContext)
4706 AssureColorTableBuilt (writerContext);
4710 WriteTag (
"colortbl");
4712 size_t entryCount = fColorTable->fEntries.size ();
4713 for (
size_t i = 0; i < entryCount; ++i) {
4714 Color c = fColorTable->LookupColor (i);
4716 (void)snprintf (buf, Memory::NEltsOf (buf),
"\\red%d\\green%d\\blue%d;", c.GetRed () >> 8, c.GetGreen () >> 8, c.GetBlue () >> 8);
4723void StyledTextIOWriter_RTF::WriteListTable ()
4726 RTFIO::ListTableEntry lte;
4727 lte.fListID = rand ();
4728 lte.fListTemplateID = rand ();
4729 lte.fListStyle = eListStyle_Bullet;
4731 RTFIO::ListOverrideTableEntry lote;
4732 lote.fListID = lte.fListID;
4734 write (
"\r\n{\\*\\listtable");
4735 WriteListTablesEntry (lte);
4738 write (
"{\\*\\listoverridetable");
4739 WriteListOverrideTablesEntry (lote);
4743void StyledTextIOWriter_RTF::WriteListTablesEntry (
const RTFIO::ListTableEntry& entry)
4747 WriteTagNValue (
"listtemplateid", entry.fListTemplateID);
4749 WriteTag (
"listlevel");
4750 WriteTagNValue (
"levelnfc", entry.fListStyle);
4751 WriteTagNValue (
"leveljc", 0);
4752 WriteTagNValue (
"levelfollow", 0);
4753 WriteTagNValue (
"levelstartat", 1);
4754 WriteTagNValue (
"levelindent", 0);
4756 int levelTemplateID = rand ();
4757 WriteTag (
"leveltext");
4758 WriteTagNValue (
"levelnfc", entry.fListStyle);
4759 WriteTagNValue (
"leveltemplateid", levelTemplateID);
4767 WriteTagNValue (
"u", 0x2022);
4770 WriteTagNValue (
"f", entry.fFontID);
4771 WriteTagNValue (
"fi", -360);
4772 WriteTagNValue (
"li", 720);
4773 WriteTag (
"jclisttab");
4774 WriteTagNValue (
"tx", 720);
4776 WriteTagNValue (
"listid", entry.fListID);
4780void StyledTextIOWriter_RTF::WriteListOverrideTablesEntry (
const RTFIO::ListOverrideTableEntry& oEntry)
4783 WriteTag (
"listoverride");
4784 WriteTagNValue (
"listid", oEntry.fListID);
4785 WriteTagNValue (
"listoverridecount", 0);
4786 WriteTagNValue (
"ls", 1);
4790void StyledTextIOWriter_RTF::WriteGenerator ()
4793 WriteTag (
"generator");
4794 write (
"Sophist Solutions, Inc. Led RTF IO Engine - " qLed_ShortVersionString);
4799void StyledTextIOWriter_RTF::EmitBodyFontInfoChange (WriterContext& writerContext,
const FontSpecification& newOne)
4805 if (writerContext.fHidableTextRegionOpen) {
4811 const FontTableEntry* fe = fFontTable->LookupEntryByName (newOne.GetFontName ());
4814 WriteTagNValue (
"f", fe->fFNum);
4818 WriteTagNValue (
"fs", newOne.GetPointSize () * 2);
4821 if (newOne.GetStyle_Bold ()) {
4824 if (newOne.GetStyle_Italic ()) {
4827 if (newOne.GetStyle_Underline ()) {
4830 switch (newOne.GetStyle_SubOrSuperScript ()) {
4831 case FontSpecification::eSubscript:
4834 case FontSpecification::eSuperscript:
4838#if qStroika_Foundation_Common_Platform_Windows
4839 if (newOne.GetStyle_Strikeout ()) {
4840 WriteTag (
"strike");
4844 WriteTagNValue (
"cf",
static_cast<int> (fColorTable->LookupColor (newOne.GetTextColor ())));
4850 EmitBodyFontInfoChange (writerContext, newOne);
4853void StyledTextIOWriter_RTF::AssureColorTableBuilt (WriterContext& writerContext)
4855 if (fColorTable ==
nullptr) {
4856 fColorTable =
new RTFIO::ColorTable ();
4857 set<Color> colorsUsed;
4858 writerContext.GetSrcStream ().SummarizeFontAndColorTable (
nullptr, &colorsUsed);
4859 for (set<Color>::const_iterator i = colorsUsed.begin (); i != colorsUsed.end (); ++i) {
4860 (void)fColorTable->EnterColor (*i);
4865#if qStroika_Foundation_Common_Platform_Windows
4867 BOOL FAR PASCAL Save_Charset_EnumFontFamiliesProc (ENUMLOGFONTEX* pelf, NEWTEXTMETRICEX* ,
int , LPVOID pCharset)
4869 BYTE* charSet =
reinterpret_cast<BYTE*
> (pCharset);
4870 *charSet = pelf->elfLogFont.lfCharSet;
4876void StyledTextIOWriter_RTF::AssureFontTableBuilt (WriterContext& writerContext)
4878 if (fFontTable ==
nullptr) {
4879 fFontTable =
new FontTable ();
4881 set<SDKString> fontNames;
4882 writerContext.GetSrcStream ().SummarizeFontAndColorTable (&fontNames,
nullptr);
4883#if qStroika_Foundation_Common_Platform_Windows
4884 WindowDC screenDC (
nullptr);
4886 for (set<SDKString>::const_iterator i = fontNames.begin (); i != fontNames.end (); ++i) {
4888 if (fFontTable->LookupEntryByName (name) ==
nullptr) {
4890 fte.fFontName = name;
4904#if qStroika_Foundation_Common_Platform_MacOS
4905 if (name == Led_SDK_TCHAROF (
"New York")) {
4906 fte.fFamily = FontTableEntry::eSwiss;
4908 else if (name == Led_SDK_TCHAROF (
"Geneva")) {
4909 fte.fFamily = FontTableEntry::eRoman;
4911 else if (name == Led_SDK_TCHAROF (
"Monaco")) {
4912 fte.fFamily = FontTableEntry::eModern;
4914 else if (name == Led_SDK_TCHAROF (
"Helvetica")) {
4915 fte.fFamily = FontTableEntry::eSwiss;
4917 else if (name == Led_SDK_TCHAROF (
"Symbol")) {
4918 fte.fFamily = FontTableEntry::eTech;
4920 else if (name == Led_SDK_TCHAROF (
"Times")) {
4921 fte.fFamily = FontTableEntry::eRoman;
4923#elif qStroika_Foundation_Common_Platform_Windows
4925 (void)::memset (&lf, 0,
sizeof (lf));
4926 Characters::CString::Copy (lf.lfFaceName, Memory::NEltsOf (lf.lfFaceName), name.c_str ());
4927 lf.lfCharSet = DEFAULT_CHARSET;
4928 BYTE useCharset = DEFAULT_CHARSET;
4929 ::EnumFontFamiliesEx (screenDC.m_hDC, &lf, (FONTENUMPROC)Save_Charset_EnumFontFamiliesProc,
reinterpret_cast<LPARAM
> (&useCharset), 0);
4930 if (useCharset != DEFAULT_CHARSET) {
4931 fte.fCharSet = useCharset;
4935 fFontTable->Add (fte);
4941void StyledTextIOWriter_RTF::AssureStyleRunSummaryBuilt (WriterContext& writerContext)
4943 if (fStyleRunSummary.empty ()) {
4944 size_t totalTextLength = writerContext.GetSrcStream ().GetTotalTextLength ();
4945 if (totalTextLength != 0) {
4946 fStyleRunSummary = writerContext.GetSrcStream ().GetStyleInfo (0, totalTextLength);
4951void StyledTextIOWriter_RTF::AssureListTableBuilt (WriterContext& )
4953 if (fListTable ==
nullptr) {
4954 fListTable =
new RTFIO::ListTables ();
#define RequireNotNull(p)
CodeCvt unifies byte <-> unicode conversions, vaguely inspired by (and wraps) std::codecvt,...
nonvirtual size_t Bytes2Characters(span< const byte > from) const
convert span byte (external serialized format) parameters to characters (like std::codecvt<>::in () -...
basic_string< SDKChar > SDKString
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...