4#include "Stroika/Frameworks/StroikaPreComp.h"
8#if qStroika_Foundation_Common_Platform_Windows
19#include "Stroika/Frameworks/Led/Config.h"
20#include "Stroika/Frameworks/Led/SimpleTextStore.h"
21#include "Stroika/Frameworks/Led/StyledTextEmbeddedObjects.h"
23#include "WordProcessor.h"
28using namespace Stroika::Frameworks;
29using namespace Stroika::Frameworks::Led;
30using namespace Stroika::Frameworks::Led::StyledTextIO;
32#if qStroika_Frameworks_Led_SupportGDI
33using InteractiveModeUpdater = WordProcessor::InteractiveModeUpdater;
34using UndoableContextHelper = WordProcessor::UndoableContextHelper;
35using Tablet_Acquirer = WordProcessor::Tablet_Acquirer;
43ParagraphDatabaseRep::ParagraphDatabaseRep (TextStore& textStore)
44 : inheritedMC{textStore, GetStaticDefaultParagraphInfo ()}
46#if qStroika_Frameworks_Led_SupportGDI
49 SetPartition (make_shared<WordProcessor::WPPartition> (GetTextStore (), *
this));
51 SetPartition (make_shared<LineBasedPartition> (GetTextStore ()));
55void ParagraphDatabaseRep::SetPartition (
const shared_ptr<Partition>& partitionPtr)
57 if (fPartition != partitionPtr) {
58 fPartition = partitionPtr;
60 CheckMarkerBounaryConstraints (0, GetTextStore ().GetEnd ());
69ParagraphInfo ParagraphDatabaseRep::GetStaticDefaultParagraphInfo ()
72 const int kDefaultInches = 6;
73 defaultPi.SetMargins (TWIPS{0}, TWIPS (kDefaultInches * 1440));
74 defaultPi.SetJustification (eLeftJustify);
78const ParagraphInfo& ParagraphDatabaseRep::GetParagraphInfo (
size_t charAfterPos)
const
80 return GetInfo (charAfterPos);
83vector<pair<ParagraphInfo, size_t>> ParagraphDatabaseRep::GetParagraphInfo (
size_t charAfterPos,
size_t nTCharsFollowing)
const
85 return GetInfo (charAfterPos, nTCharsFollowing);
88void ParagraphDatabaseRep::SetParagraphInfo (
size_t charAfterPos,
size_t nTCharsFollowing,
const IncrementalParagraphInfo& infoForMarkers)
90 if (infoForMarkers.GetMargins_Valid ()) {
91 fCachedFarthestRightMarginInDocument = kBadCachedFarthestRightMarginInDocument;
93 SetInfo (charAfterPos, nTCharsFollowing, infoForMarkers);
96void ParagraphDatabaseRep::SetParagraphInfo (
size_t charAfterPos,
const vector<pair<IncrementalParagraphInfo, size_t>>& infoForMarkers)
98 for (
auto i = infoForMarkers.begin (); i != infoForMarkers.end (); ++i) {
99 if ((*i).first.GetMargins_Valid ()) {
100 fCachedFarthestRightMarginInDocument = kBadCachedFarthestRightMarginInDocument;
104 SetInfos (charAfterPos, infoForMarkers);
107void ParagraphDatabaseRep::SetParagraphInfo (
size_t charAfterPos,
const vector<pair<ParagraphInfo, size_t>>& infoForMarkers)
109 fCachedFarthestRightMarginInDocument = kBadCachedFarthestRightMarginInDocument;
110 SetInfos2 (charAfterPos, infoForMarkers);
118void ParagraphDatabaseRep::SetInfo (
size_t charAfterPos,
size_t nTCharsFollowing,
const IncrementalParagraphInfo& infoForMarkers)
120 Assert (fPartition.get () !=
nullptr);
121 inheritedMC::SetInfo (charAfterPos, nTCharsFollowing, infoForMarkers);
124void ParagraphDatabaseRep::SetInfos (
size_t charAfterPos,
const vector<pair<IncrementalParagraphInfo, size_t>>& infoForMarkers)
126 Assert (fPartition.get () !=
nullptr);
127 inheritedMC::SetInfos (charAfterPos, infoForMarkers);
137void ParagraphDatabaseRep::NoteCoverRangeDirtied (
size_t from,
size_t to,
const MarkerVector& rangeAndSurroundingsMarkers)
139 inheritedMC::NoteCoverRangeDirtied (from, to, rangeAndSurroundingsMarkers);
140 CheckMarkerBounaryConstraints (rangeAndSurroundingsMarkers);
143void ParagraphDatabaseRep::ConstrainSetInfoArgs (
size_t* charAfterPos,
size_t* nTCharsFollowing)
148 size_t from = *charAfterPos;
149 size_t to = from + *nTCharsFollowing;
150 PartitionMarker* startPara = fPartition->GetPartitionMarkerContainingPosition (from);
151 PartitionMarker* endPara = (to <= startPara->GetEnd ()) ? startPara : fPartition->GetPartitionMarkerContainingPosition (to);
154 if (startPara != endPara and endPara->GetStart () == to) {
155 endPara = endPara->GetPrevious ();
157 size_t bigFrom = startPara->GetStart ();
158 size_t bigEnd = min (endPara->GetEnd (), GetTextStore ().GetEnd () + 1);
160 *charAfterPos = bigFrom;
161 *nTCharsFollowing = bigEnd - bigFrom;
170void ParagraphDatabaseRep::CheckMarkerBounaryConstraints (
size_t from,
size_t to)
noexcept
172 if (fPartition.get () !=
nullptr) {
173 MarkerVector markers = CollectAllInRange_OrSurroundings (from, to);
174 sort (markers.begin (), markers.end (), LessThan<ParagraphInfoMarker> ());
175 CheckMarkerBounaryConstraints (markers);
179void ParagraphDatabaseRep::CheckMarkerBounaryConstraints (
const MarkerVector& rangeAndSurroundingsMarkers)
noexcept
185 if (fPartition.get () !=
nullptr) {
186 for (
auto i = rangeAndSurroundingsMarkers.begin (); i != rangeAndSurroundingsMarkers.end (); ++i) {
187 ParagraphInfoMarker* m = *i;
191 m->GetRange (&m_start, &m_end);
192 size_t m_length = m_end - m_start;
195 Assert (m->GetLength () == m_length);
197 Assert (m_start == m->GetStart ());
198 PartitionMarker* partitionElt = fPartition->GetPartitionMarkerContainingPosition (m_start);
199 Assert (partitionElt->GetStart () == m->GetStart ());
201 Assert (m->GetEnd () == m_end);
202 size_t partitionElt_end;
203 for (; (partitionElt_end = partitionElt->GetEnd ()) < m_end;) {
204 partitionElt = partitionElt->GetNext ();
207 Assert (partitionElt_end == partitionElt->GetEnd ());
232 Assert (m->GetEnd () == m_end);
233 if (partitionElt_end != m_end) {
234 MarkerVector markers = CollectAllNonEmptyInRange (m_end, m_end + 1);
235 Assert (markers.size () == 1);
236 ParagraphInfoMarker* followingMarker = markers[0];
237 Assert (m_end == followingMarker->GetStart ());
238 Assert (partitionElt_end == partitionElt->GetEnd ());
239 GetTextStore ().SetMarkerEnd (m, partitionElt_end);
240 Assert (followingMarker->GetEnd () >= partitionElt->GetEnd ());
241 Assert (partitionElt_end == partitionElt->GetEnd ());
242 GetTextStore ().SetMarkerStart (followingMarker, partitionElt_end);
244 if (followingMarker->GetLength () == 0) {
245 fMarkersToBeDeleted.AccumulateMarkerForDeletion (followingMarker);
246 Assert (partitionElt_end == m->GetEnd ());
247 CheckForMerges (partitionElt_end);
257 SetInfoInnerLoop (partitionElt->GetStart (), partitionElt->GetEnd (), followingInfo,
258 UpdateInfo (partitionElt->GetStart (), partitionElt->GetEnd (), LED_TCHAR_OF (
""), 0,
false,
false),
nullptr);
259 CullZerod (partitionElt->GetStart ());
260 CullZerod (partitionElt->GetEnd ());
267#if qStroika_Foundation_Debug_AssertionsChecked
268void ParagraphDatabaseRep::Invariant_ ()
const
270 inheritedMC::Invariant_ ();
273 if (fPartition.get () !=
nullptr) {
276 MarkerVector markers = CollectAllInRange_OrSurroundings (0, GetTextStore ().GetLength () + 1);
277 sort (markers.begin (), markers.end (), LessThan<ParagraphInfoMarker> ());
278 PartitionMarker* lastPartitionElt =
nullptr;
279 for (
auto i = markers.begin (); i != markers.end (); ++i) {
280 ParagraphInfoMarker* m = *i;
281 Assert (m->GetLength () != 0);
282 PartitionMarker* curPartitionElt = fPartition->GetPartitionMarkerContainingPosition (m->GetStart ());
283 Assert (curPartitionElt != lastPartitionElt);
284 Assert (curPartitionElt->GetStart () == m->GetStart ());
285 Assert (curPartitionElt->GetEnd () <= m->GetEnd ());
287 lastPartitionElt = curPartitionElt;
298#if qStroika_Frameworks_Led_SupportGDI
301 using inherited = InteractiveReplaceCommand;
304 TableCMD (
size_t tableAt,
size_t tRow,
size_t tCol, SavedTextRep* beforeRegion, SavedTextRep* afterRegion,
size_t at,
const SDKString& cmdName)
305 : inherited (beforeRegion, afterRegion, at, cmdName)
308 , fTableColumn (tCol)
313 virtual void Do (TextInteractor& interactor)
override
315 WordProcessor& owningWP =
dynamic_cast<WordProcessor&
> (interactor);
316 WordProcessorTable* aT = owningWP.GetTableAt (fTableAt);
318 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, owningWP);
319 WordProcessorTable::TemporarilyAllocateCellWithTablet wp (*aT, fTableRow, fTableColumn);
322 virtual void UnDo (TextInteractor& interactor)
override
324 WordProcessor& owningWP =
dynamic_cast<WordProcessor&
> (interactor);
325 WordProcessorTable* aT = owningWP.GetTableAt (fTableAt);
327 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, owningWP);
328 WordProcessorTable::TemporarilyAllocateCellWithTablet wp (*aT, fTableRow, fTableColumn);
329 inherited::UnDo (*wp);
331 virtual void ReDo (TextInteractor& interactor)
override
333 WordProcessor& owningWP =
dynamic_cast<WordProcessor&
> (interactor);
334 WordProcessorTable* aT = owningWP.GetTableAt (fTableAt);
336 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, owningWP);
337 WordProcessorTable::TemporarilyAllocateCellWithTablet wp (*aT, fTableRow, fTableColumn);
338 inherited::ReDo (*wp);
352#define Led_Require_CurrentOwningWP() RequireNotNull (fCurrentOwningWP)
359WordProcessorTable::WordProcessorTable (AbstractParagraphDatabaseRep* tableOwner,
size_t addAt)
361 FinalizeAddition (tableOwner, addAt);
364WordProcessorTable::~WordProcessorTable ()
366#if qStroika_Frameworks_Led_SupportGDI
367 if (fCellUpdatePropationUpdater !=
nullptr) {
370 fCellUpdatePropationUpdater->Cancel ();
371 delete fCellUpdatePropationUpdater;
373 Assert (fCurrentOwningWP ==
nullptr);
377void WordProcessorTable::FinalizeAddition (AbstractParagraphDatabaseRep* o,
size_t addAt)
380#if qStroika_Frameworks_Led_SupportGDI
381 TextStore& ts = o->GetTextStore ();
382 TextStore::SimpleUpdater updater (ts, addAt, addAt + 1);
383 ts.ReplaceWithoutUpdate (addAt, addAt, &kEmbeddingSentinelChar, 1);
384 ts.AddMarker (
this, addAt, 1, o);
388Color WordProcessorTable::GetTableBorderColor ()
const
393void WordProcessorTable::SetTableBorderColor (
Color c)
398TWIPS WordProcessorTable::GetTableBorderWidth ()
const
403void WordProcessorTable::SetTableBorderWidth (TWIPS w)
408TWIPS WordProcessorTable::GetColumnWidth (
size_t row,
size_t column)
const
410 if (GetCellFlags (row, column) != ePlainCell) {
414 return GetCell (row, column).GetCellXWidth ();
417void WordProcessorTable::SetColumnWidth (
size_t row,
size_t column, TWIPS colWidth)
419 GetCell (row, column).SetCellXWidth (colWidth);
420#if qStroika_Frameworks_Led_SupportGDI
425Color WordProcessorTable::GetCellColor (
size_t row,
size_t column)
const
427 return GetCell (row, column).GetBackColor ();
430void WordProcessorTable::SetCellColor (
size_t row,
size_t column,
const Color& c)
432 Cell cell = GetCell (row, column);
433 cell.SetBackColor (c);
436size_t WordProcessorTable::GetColumnCount (
size_t row)
const
438 Require (row < GetRowCount ());
439 return fRows[row].fCells.size ();
442size_t WordProcessorTable::GetColumnCount (
size_t rowStart,
size_t rowEnd)
const
444 Require (rowStart <= GetRowCount ());
445 Require (rowEnd <= GetRowCount ());
447 for (
size_t ri = rowStart; ri < rowEnd; ++ri) {
448 colCount = max (colCount, fRows[ri].fCells.size ());
453void WordProcessorTable::SetColumnCount (
size_t row,
size_t columns)
455 Require (row < GetRowCount ());
456 size_t curColCount = fRows[row].fCells.size ();
457 if (curColCount != columns) {
458 vector<Cell>& rowCells = fRows[row].fCells;
459 while (curColCount < columns) {
460 Cell cell (*
this, ePlainCell);
461 rowCells.push_back (cell);
464 while (curColCount > columns) {
466 rowCells.erase (rowCells.begin () + curColCount);
478void WordProcessorTable::GetCellWordProcessorDatabases (
size_t row,
size_t column, TextStore** ts, shared_ptr<AbstractStyleDatabaseRep>* styleDatabase,
479 shared_ptr<AbstractParagraphDatabaseRep>* paragraphDatabase,
480 shared_ptr<HidableTextMarkerOwner>* hidableTextDatabase)
482 Require (row < GetRowCount ());
483 Require (column < GetColumnCount (row));
484 const Cell& c = GetCell (row, column);
486 *ts = &c.GetTextStore ();
488 if (styleDatabase !=
nullptr) {
489 *styleDatabase = c.GetStyleDatabase ();
491 if (paragraphDatabase !=
nullptr) {
492 *paragraphDatabase = c.GetParagraphDatabase ();
494 if (hidableTextDatabase !=
nullptr) {
495 *hidableTextDatabase = c.GetHidableTextDatabase ();
504WordProcessorTable::Cell::Cell (WordProcessorTable& forTable, CellMergeFlags mergeFlags)
505 : fCellMergeFlags{mergeFlags}
506 , fCellRep{mergeFlags == ePlainCell ? (new CellRep (forTable)) : nullptr}
517void WordProcessorTable::Cell::GetCellWordProcessorDatabases (TextStore** ts, shared_ptr<AbstractStyleDatabaseRep>* styleDatabase,
518 shared_ptr<AbstractParagraphDatabaseRep>* paragraphDatabase,
519 shared_ptr<HidableTextMarkerOwner>* hidableTextDatabase)
521 Require (fCellMergeFlags == ePlainCell);
523 *ts = &GetTextStore ();
525 if (styleDatabase !=
nullptr) {
526 *styleDatabase = GetStyleDatabase ();
528 if (paragraphDatabase !=
nullptr) {
529 *paragraphDatabase = GetParagraphDatabase ();
531 if (hidableTextDatabase !=
nullptr) {
532 *hidableTextDatabase = GetHidableTextDatabase ();
536TextStore& WordProcessorTable::Cell::GetTextStore ()
const
538 Require (fCellMergeFlags == ePlainCell);
540 return *fCellRep->fTextStore;
543shared_ptr<AbstractStyleDatabaseRep> WordProcessorTable::Cell::GetStyleDatabase ()
const
545 Require (fCellMergeFlags == ePlainCell);
546 return fCellRep->fStyleDatabase;
549shared_ptr<AbstractParagraphDatabaseRep> WordProcessorTable::Cell::GetParagraphDatabase ()
const
551 Require (fCellMergeFlags == ePlainCell);
552 return fCellRep->fParagraphDatabase;
555shared_ptr<HidableTextMarkerOwner> WordProcessorTable::Cell::GetHidableTextDatabase ()
const
557 Require (fCellMergeFlags == ePlainCell);
558 return fCellRep->fHidableTextDatabase;
561Color WordProcessorTable::Cell::GetBackColor ()
const
563 Require (fCellMergeFlags == ePlainCell);
564 return fCellRep->fBackColor;
567void WordProcessorTable::Cell::SetBackColor (
Color c)
569 Require (fCellMergeFlags == ePlainCell);
570 fCellRep->fBackColor = c;
578WordProcessorTable::CellRep::CellRep (WordProcessorTable& forTable)
579 : fForTable (forTable)
580 , fTextStore (nullptr)
582 , fParagraphDatabase ()
583 , fHidableTextDatabase ()
584 , fBackColor (
Color::kWhite)
585 , fCachedBoundsRect (Led_Rect (0, 0, 0, 0))
586#if qStroika_Frameworks_Led_SupportGDI
587 , fCellXWidth (Led_CvtScreenPixelsToTWIPSH (75))
593 fTextStore =
new SimpleTextStore ();
594 fTextStore->AddMarkerOwner (
this);
595 fStyleDatabase = make_shared<StyleDatabaseRep> (*fTextStore);
596 fParagraphDatabase = make_shared<ParagraphDatabaseRep> (*fTextStore);
597 fHidableTextDatabase = make_shared<UniformHidableTextMarkerOwner> (*fTextStore);
600WordProcessorTable::CellRep::~CellRep ()
602 Require (fStyleDatabase.use_count () == 1);
603 Require (fParagraphDatabase.use_count () == 1);
604 Require (fHidableTextDatabase.use_count () == 1);
605 fStyleDatabase.reset ();
606 fParagraphDatabase.reset ();
607 fHidableTextDatabase.reset ();
608 if (fTextStore !=
nullptr) {
609 fTextStore->RemoveMarkerOwner (
this);
614TextStore* WordProcessorTable::CellRep::PeekAtTextStore ()
const
619void WordProcessorTable::CellRep::AboutToUpdateText (
const UpdateInfo& updateInfo)
621 inherited::AboutToUpdateText (updateInfo);
622 if (fForTable.fAllowUpdateInfoPropagationContext and updateInfo.fRealContentUpdate) {
623 if (fForTable.fCellUpdatePropationUpdater !=
nullptr) {
626 fForTable.fCellUpdatePropationUpdater->Cancel ();
627 delete fForTable.fCellUpdatePropationUpdater;
628 fForTable.fCellUpdatePropationUpdater =
nullptr;
630 fForTable.fCellUpdatePropationUpdater =
631 new TextStore::SimpleUpdater (fForTable.GetOwner ()->GetTextStore (), fForTable.GetStart (), fForTable.GetEnd ());
635void WordProcessorTable::CellRep::DidUpdateText (
const UpdateInfo& updateInfo)
noexcept
637 inherited::DidUpdateText (updateInfo);
638 if (not fForTable.fSuppressCellUpdatePropagationContext) {
639 fForTable.InvalidateLayout ();
641 if (fForTable.fAllowUpdateInfoPropagationContext and updateInfo.fRealContentUpdate) {
643 delete fForTable.fCellUpdatePropationUpdater;
644 fForTable.fCellUpdatePropationUpdater =
nullptr;
654 inline TWIPS CalcDefaultRHSMargin_ ()
656 const int kRTF_SPEC_DefaultInches = 6;
657 int rhsTWIPS = kRTF_SPEC_DefaultInches * 1440;
658 return TWIPS{rhsTWIPS};
662WordProcessorTextIOSinkStream::WordProcessorTextIOSinkStream (TextStore* textStore,
const shared_ptr<AbstractStyleDatabaseRep>& textStyleDatabase,
663 const shared_ptr<AbstractParagraphDatabaseRep>& paragraphDatabase,
664 const shared_ptr<HidableTextMarkerOwner>& hidableTextDatabase,
size_t insertionStart)
665 : inherited{textStore, textStyleDatabase, insertionStart}
666 , fOverwriteTableMode{false}
668#if !qStroika_Frameworks_Led_NestedTablesSupported
669 fNoTablesAllowed{false}
673 , fParagraphDatabase{paragraphDatabase}
674 , fHidableTextDatabase{hidableTextDatabase}
676 , fNewParagraphInfo{}
679 , fEndOfBuffer{false}
680 , fIgnoreLastParaAttributes{false}
681 , fCurrentTable{nullptr}
682 , fCurrentTableCellWidths{}
683 , fCurrentTableCellColor{
Color::kWhite}
684 , fCurrentTableColSpanArray{}
688 , fCurrentTableCell{size_t (-1)}
691 , fTableRowOpen{false}
692 , fTableCellOpen{false}
698#if qStroika_Frameworks_Led_SupportGDI
699WordProcessorTextIOSinkStream::WordProcessorTextIOSinkStream (WordProcessor* wp,
size_t insertionStart)
700 : inherited{&wp->GetTextStore (), wp->GetStyleDatabase (), insertionStart}
701 , fOverwriteTableMode{false}
703#if !qStroika_Frameworks_Led_NestedTablesSupported
704 fNoTablesAllowed{false}
708 , fParagraphDatabase{wp->GetParagraphDatabase ()}
709 , fHidableTextDatabase{wp->GetHidableTextDatabase ()}
711 , fNewParagraphInfo{}
714 , fEndOfBuffer{false}
715 , fIgnoreLastParaAttributes{false}
716 , fCurrentTable{nullptr}
717 , fCurrentTableCellWidths{}
718 , fCurrentTableCellColor{
Color::kWhite}
719 , fCurrentTableColSpanArray{}
723 , fCurrentTableCell{size_t (-1)}
726 , fTableRowOpen{false}
727 , fTableCellOpen{false}
734WordProcessorTextIOSinkStream::~WordProcessorTextIOSinkStream ()
736#if qStroika_Foundation_Debug_AssertionsChecked
737 Assert (fTableOpenLevel == 0);
738 Assert (not fTableRowOpen);
739 Assert (not fTableCellOpen);
743 Ensure (GetCachedTextSize () == 0);
744 Ensure (fSavedParaInfo.size () == 0);
751void WordProcessorTextIOSinkStream::CTOR_COMMON ()
753 fNewParagraphInfo.SetJustification (eLeftJustify);
754 fNewParagraphInfo.SetTabStopList (StandardTabStopList{});
755 fNewParagraphInfo.SetFirstIndent (TWIPS{0});
756 fNewParagraphInfo.SetMargins (TWIPS{0}, CalcDefaultRHSMargin_ ());
757 fNewParagraphInfo.SetListStyle (eListStyle_None);
758 fNewParagraphInfo.SetSpaceBefore (TWIPS{0});
759 fNewParagraphInfo.SetSpaceAfter (TWIPS{0});
762void WordProcessorTextIOSinkStream::AppendText (
const Led_tChar* text,
size_t nTChars,
const FontSpecification* fontSpec)
765 inherited::AppendText (text, nTChars, fontSpec);
766 if (fSavedParaInfo.size () == 0) {
767 fSavedParaInfo.push_back (ParaInfoNSize (fNewParagraphInfo, nTChars));
769 else if (fSavedParaInfo.back ().first == fNewParagraphInfo) {
770 fSavedParaInfo.back ().second += nTChars;
773 fSavedParaInfo.push_back (ParaInfoNSize (fNewParagraphInfo, nTChars));
775 if (fHidableTextRuns.size () != 0 and fHidableTextRuns.back ().fData == fTextHidden) {
776 fHidableTextRuns.back ().fElementLength += nTChars;
779 fHidableTextRuns.push_back (DiscontiguousRunElement<bool> (0, nTChars, fTextHidden));
783#if qStroika_Frameworks_Led_SupportGDI
784void WordProcessorTextIOSinkStream::AppendEmbedding (SimpleEmbeddedObjectStyleMarker* embedding)
787 if (GetCachedTextSize () != 0) {
790 size_t whereToStartHiddenArea = GetInsertionStart ();
791 inherited::AppendEmbedding (embedding);
793 fHidableTextDatabase->MakeRegionHidable (whereToStartHiddenArea, whereToStartHiddenArea + 1);
798void WordProcessorTextIOSinkStream::AppendSoftLineBreak ()
800 AppendText (&kSoftLineBreakChar, 1,
nullptr);
803void WordProcessorTextIOSinkStream::SetJustification (Justification justification)
805 fNewParagraphInfo.SetJustification (justification);
808void WordProcessorTextIOSinkStream::SetStandardTabStopList (
const StandardTabStopList& tabStops)
810 fNewParagraphInfo.SetTabStopList (tabStops);
813void WordProcessorTextIOSinkStream::SetFirstIndent (TWIPS tx)
815 fNewParagraphInfo.SetFirstIndent (tx);
818void WordProcessorTextIOSinkStream::SetLeftMargin (TWIPS lhs)
820 fNewParagraphInfo.SetMargins (lhs, max (TWIPS (lhs + 1), fNewParagraphInfo.GetRightMargin ()));
823void WordProcessorTextIOSinkStream::SetRightMargin (TWIPS rhs)
825 fNewParagraphInfo.SetMargins (fNewParagraphInfo.GetLeftMargin (), max (TWIPS (fNewParagraphInfo.GetLeftMargin () + 1), rhs));
828void WordProcessorTextIOSinkStream::SetSpaceBefore (TWIPS sb)
830 fNewParagraphInfo.SetSpaceBefore (sb);
833void WordProcessorTextIOSinkStream::SetSpaceAfter (TWIPS sa)
835 fNewParagraphInfo.SetSpaceAfter (sa);
838void WordProcessorTextIOSinkStream::SetLineSpacing (LineSpacing sl)
840 fNewParagraphInfo.SetLineSpacing (sl);
843void WordProcessorTextIOSinkStream::SetTextHidden (
bool hidden)
845 fTextHidden = hidden;
848void WordProcessorTextIOSinkStream::StartTable ()
850#if qStroika_Foundation_Debug_AssertionsChecked
854 if (fTableOpenLevel == 0) {
856 Assert (fTableOpenLevel == 0);
857 Assert (not fTableRowOpen);
858 Assert (not fTableCellOpen);
862 Assert (fTableRowOpen);
863 Assert (fTableCellOpen);
866 fTableRowOpen =
false;
867 fTableCellOpen =
false;
870#if !qStroika_Frameworks_Led_NestedTablesSupported
871 if (GetNoTablesAllowed ()) {
876 if (GetCachedTextSize () != 0) {
882#if qStroika_Frameworks_Led_NestedTablesSupported
883 if (fCurrentTable !=
nullptr) {
885 fTableStack.push_back (fCurrentTable);
887 fCurrentTable =
nullptr;
890 if (GetOverwriteTableMode ()) {
891 TextStore& ts = GetTextStore ();
892 size_t realCoordStart = GetInsertionStart ();
893 MarkerOfATypeMarkerSink<WordProcessorTable> maybeTable;
894 Assert (realCoordStart <= ts.GetEnd ());
895 ts.CollectAllMarkersInRangeInto (ts.FindPreviousCharacter (realCoordStart), realCoordStart, fParagraphDatabase.get (), maybeTable);
896 if (maybeTable.fResult !=
nullptr) {
897 fCurrentTable = maybeTable.fResult;
898 size_t rowSelStart = 0;
899 size_t colSelStart = 0;
900 fCurrentTable->GetCellSelection (&rowSelStart,
nullptr, &colSelStart,
nullptr);
901 fNextTableRow = rowSelStart;
902 fNextTableCell = colSelStart;
903 fCurrentTableCell = size_t (-1);
907 if (fCurrentTable ==
nullptr) {
908 fCurrentTable =
new WordProcessorTable (fParagraphDatabase.get (), current_offset () + GetOriginalStart ());
909 SetInsertionStart (GetInsertionStart () + 1);
912 fCurrentTableCell = size_t (-1);
916void WordProcessorTextIOSinkStream::EndTable ()
918#if qStroika_Foundation_Debug_AssertionsChecked
919 Require (fTableOpenLevel >= 1);
920 Require (not fTableRowOpen);
921 Require (not fTableCellOpen);
925 if (fTableOpenLevel > 0) {
926 fTableRowOpen =
true;
927 fTableCellOpen =
true;
930 fTableRowOpen =
false;
931 fTableCellOpen =
false;
934#if !qStroika_Frameworks_Led_NestedTablesSupported
935 if (GetNoTablesAllowed ()) {
936 AppendText (LED_TCHAR_OF (
"\n"), 1,
nullptr);
940 if (fCurrentTable !=
nullptr) {
942 fCurrentTable =
nullptr;
943#if qStroika_Frameworks_Led_NestedTablesSupported
944 if (not fTableStack.empty ()) {
945 fCurrentTable = fTableStack.back ();
946 fTableStack.pop_back ();
952void WordProcessorTextIOSinkStream::StartTableRow ()
954#if qStroika_Foundation_Debug_AssertionsChecked
955 Require (fTableOpenLevel >= 1);
956 Require (not fTableRowOpen);
957 Require (not fTableCellOpen);
958 fTableRowOpen =
true;
960#if !qStroika_Frameworks_Led_NestedTablesSupported
961 if (GetNoTablesAllowed ()) {
963 AppendText (LED_TCHAR_OF (
"\n"), 1,
nullptr);
969 if (GetOverwriteTableMode ()) {
970 if (fNextTableRow > fCurrentTable->GetRowCount ()) {
971 fCurrentTable->InsertRow (fNextTableRow - 1, 1);
973 size_t colSelStart = 0;
974 fCurrentTable->GetCellSelection (
nullptr,
nullptr, &colSelStart,
nullptr);
975 fNextTableCell = min (fCurrentTable->GetColumnCount (fNextTableRow - 1) - 1, colSelStart);
979 fCurrentTable->InsertRow (fNextTableRow - 1, 1);
981 fCurrentTableColSpanArray.clear ();
984void WordProcessorTextIOSinkStream::EndTableRow ()
986#if qStroika_Foundation_Debug_AssertionsChecked
987 Require (fTableOpenLevel >= 1);
988 Require (fTableRowOpen);
989 Require (not fTableCellOpen);
990 fTableRowOpen =
false;
992#if !qStroika_Frameworks_Led_NestedTablesSupported
993 if (GetNoTablesAllowed ()) {
998 size_t nCellsInThisRow = fCurrentTableCellWidths.size ();
1000 while (nCellsInThisRow > fCurrentTableColSpanArray.size ()) {
1002 fCurrentTableColSpanArray.push_back (1);
1005 if (nCellsInThisRow != fCurrentTableColSpanArray.size ()) {
1008 nCellsInThisRow = min (nCellsInThisRow, fCurrentTableColSpanArray.size ());
1010 fCurrentTable->SetColumnCount (fNextTableRow - 1, max (nCellsInThisRow, fCurrentTable->GetColumnCount (fNextTableRow - 1)));
1013 for (
size_t cellIdx = 0; cellIdx < nCellsInThisRow; ++cellIdx) {
1014 size_t nColsInThisCell = fCurrentTableColSpanArray[cellIdx];
1015 Assert (nColsInThisCell >= 1);
1016 Assert (col < fCurrentTable->GetColumnCount ());
1018 TWIPS thisCellWidth = fCurrentTableCellWidths[cellIdx];
1019 if (nColsInThisCell == 1) {
1020 Assert (fNextTableRow > 0);
1021 fCurrentTable->SetColumnWidth (fNextTableRow - 1, col, thisCellWidth);
1027 TWIPS prevColWidths = TWIPS{0};
1028 for (
size_t i = col; i < col + nColsInThisCell; ++i) {
1029 Assert (fNextTableRow > 0);
1030 prevColWidths += fCurrentTable->GetColumnWidth (fNextTableRow - 1, i);
1032 if (prevColWidths < thisCellWidth) {
1033 Assert (fNextTableRow > 0);
1034 fCurrentTable->SetColumnWidth (fNextTableRow - 1, col, thisCellWidth - prevColWidths);
1038 col += nColsInThisCell;
1042void WordProcessorTextIOSinkStream::StartTableCell (
size_t colSpan)
1044#if qStroika_Foundation_Debug_AssertionsChecked
1046 Require (fTableOpenLevel >= 1);
1047 Require (fTableRowOpen);
1048 Require (not fTableCellOpen);
1049 fTableCellOpen =
true;
1052#if !qStroika_Frameworks_Led_NestedTablesSupported
1053 if (GetNoTablesAllowed ()) {
1054 if (fNextTableCell >= 1) {
1055 AppendText (LED_TCHAR_OF (
"\t"), 1,
nullptr);
1061 Require (colSpan >= 1);
1063 fCurrentTableCell = fNextTableCell;
1064 fCurrentTableColSpanArray.push_back (colSpan);
1065 fNextTableCell += colSpan;
1068 fCurrentTable->SetColumnCount (fNextTableRow - 1, max (fNextTableCell, fCurrentTable->GetColumnCount (fNextTableRow - 1)));
1070 Assert (fNextTableRow > 0);
1071 Assert (fNextTableCell > 0);
1073 TextStore* ts =
nullptr;
1074 shared_ptr<AbstractStyleDatabaseRep> styleDatabase;
1075 shared_ptr<AbstractParagraphDatabaseRep> paragraphDatabase;
1076 shared_ptr<HidableTextMarkerOwner> hidableTextDatabase;
1077 fCurrentTable->GetCellWordProcessorDatabases (fNextTableRow - 1, fCurrentTableCell, &ts, &styleDatabase, ¶graphDatabase, &hidableTextDatabase);
1078 PushContext (ts, styleDatabase, paragraphDatabase, hidableTextDatabase, 0);
1079 if (GetOverwriteTableMode ()) {
1080 ts->Replace (0, ts->GetLength (),
nullptr, 0);
1084void WordProcessorTextIOSinkStream::EndTableCell ()
1086#if qStroika_Foundation_Debug_AssertionsChecked
1087 Require (fTableOpenLevel >= 1);
1088 Require (fTableRowOpen);
1089 Require (fTableCellOpen);
1090 fTableCellOpen =
false;
1092#if !qStroika_Frameworks_Led_NestedTablesSupported
1093 if (GetNoTablesAllowed ()) {
1098 fCurrentTable->SetCellColor (fNextTableRow - 1, fCurrentTableCell, fCurrentTableCellColor);
1102void WordProcessorTextIOSinkStream::SetListStyle (ListStyle listStyle)
1104 fNewParagraphInfo.SetListStyle (listStyle);
1107void WordProcessorTextIOSinkStream::SetListIndentLevel (
unsigned char indentLevel)
1109 fNewParagraphInfo.SetListIndentLevel (indentLevel);
1112void WordProcessorTextIOSinkStream::SetIgnoreLastParaAttributes (
bool ignoreLastParaAttributes)
1114 fIgnoreLastParaAttributes = ignoreLastParaAttributes;
1117void WordProcessorTextIOSinkStream::SetTableBorderColor (
Color c)
1119 if (fCurrentTable !=
nullptr) {
1120 fCurrentTable->SetTableBorderColor (c);
1124void WordProcessorTextIOSinkStream::SetTableBorderWidth (TWIPS bWidth)
1126 if (fCurrentTable !=
nullptr) {
1127 fCurrentTable->SetTableBorderWidth (bWidth);
1131void WordProcessorTextIOSinkStream::SetCellWidths (
const vector<TWIPS>& cellWidths)
1133 if (fCurrentTable !=
nullptr) {
1134 fCurrentTableCellWidths = cellWidths;
1138void WordProcessorTextIOSinkStream::SetCellBackColor (
const Color c)
1140 if (fCurrentTable !=
nullptr) {
1141 fCurrentTableCellColor = c;
1145void WordProcessorTextIOSinkStream::SetDefaultCellMarginsForCurrentRow (TWIPS top, TWIPS left, TWIPS bottom, TWIPS right)
1151 if (fCurrentTable !=
nullptr) {
1152 fCurrentTable->SetDefaultCellMargins (top, left, bottom, right);
1156void WordProcessorTextIOSinkStream::SetDefaultCellSpacingForCurrentRow (TWIPS top, TWIPS left, TWIPS bottom, TWIPS right)
1164 if (fCurrentTable !=
nullptr) {
1165 TWIPS aveSpacing = TWIPS ((top + left + bottom + right) / 4);
1166 fCurrentTable->SetCellSpacing (aveSpacing);
1170void WordProcessorTextIOSinkStream::PushContext (TextStore* ts,
const shared_ptr<AbstractStyleDatabaseRep>& textStyleDatabase,
1171 const shared_ptr<AbstractParagraphDatabaseRep>& paragraphDatabase,
1172 const shared_ptr<HidableTextMarkerOwner>& hidableTextDatabase,
size_t insertionStart)
1174 if (GetCachedTextSize () != 0) {
1177 inherited::PushContext (ts, textStyleDatabase, insertionStart);
1179 c.fHidableTextDatabase = fHidableTextDatabase;
1180 c.fParagraphDatabase = fParagraphDatabase;
1181 fSavedContexts.push_back (c);
1182 fHidableTextDatabase = hidableTextDatabase;
1183 fParagraphDatabase = paragraphDatabase;
1186void WordProcessorTextIOSinkStream::PopContext ()
1188 Require (GetCachedTextSize () == 0);
1189 Require (not fSavedContexts.empty ());
1190 inherited::PopContext ();
1191 fHidableTextDatabase = fSavedContexts.back ().fHidableTextDatabase;
1192 fParagraphDatabase = fSavedContexts.back ().fParagraphDatabase;
1193 fSavedContexts.pop_back ();
1196void WordProcessorTextIOSinkStream::EndOfBuffer ()
1198 fEndOfBuffer =
true;
1201void WordProcessorTextIOSinkStream::Flush ()
1203 size_t stripParaCharCount = 0;
1204 if (fEndOfBuffer and fIgnoreLastParaAttributes) {
1205 const vector<Led_tChar>& t = GetCachedText ();
1207 for (
auto i = t.rbegin (); i != t.rend (); ++i) {
1212 ++stripParaCharCount;
1218 size_t dataSize = GetCachedTextSize ();
1219 size_t whereToInsert = GetInsertionStart () - dataSize;
1220 inherited::Flush ();
1225 [[maybe_unused]]
size_t curInsert = whereToInsert;
1226 for (
auto i = fSavedParaInfo.begin (); i != fSavedParaInfo.end (); ++i) {
1227 curInsert += (*i).second;
1229 Assert (curInsert == GetInsertionStart ());
1231 if (stripParaCharCount != 0) {
1232 Assert (fSavedParaInfo.size () > 0);
1233 vector<ParaInfoNSize>::iterator i = fSavedParaInfo.end () - 1;
1234 if ((*i).second > stripParaCharCount) {
1235 (*i).second -= stripParaCharCount;
1238 fSavedParaInfo.resize (fSavedParaInfo.size () - 1);
1241 fParagraphDatabase->SetParagraphInfo (whereToInsert, fSavedParaInfo);
1242 fSavedParaInfo.clear ();
1256 if (fEndOfBuffer and not fIgnoreLastParaAttributes and whereToInsert == fParagraphDatabase->GetTextStore ().GetEnd ()) {
1257 fParagraphDatabase->SetParagraphInfo (whereToInsert, 1,
1259 fParagraphDatabase->GetTextStore ().FindPreviousCharacter (whereToInsert))));
1264 vector<pair<size_t, size_t>> hidePairs;
1265 size_t curInsert = whereToInsert;
1266 for (
auto i = fHidableTextRuns.begin (); i != fHidableTextRuns.end (); ++i) {
1268 hidePairs.push_back (pair<size_t, size_t> (curInsert, curInsert + (*i).fElementLength));
1270 curInsert += (*i).fElementLength;
1272 for (
auto i = hidePairs.rbegin (); i != hidePairs.rend (); ++i) {
1273 fHidableTextDatabase->MakeRegionHidable ((*i).first, (*i).second);
1275 fHidableTextRuns.clear ();
1284WordProcessorTextIOSrcStream::WordProcessorTextIOSrcStream (TextStore* textStore,
const shared_ptr<AbstractStyleDatabaseRep>& textStyleDatabase,
1285 const shared_ptr<AbstractParagraphDatabaseRep>& paragraphDatabase,
1286 const shared_ptr<HidableTextMarkerOwner>& hidableTextDatabase,
1287 size_t selectionStart,
size_t selectionEnd)
1288 : inherited{textStore, textStyleDatabase, selectionStart, selectionEnd}
1289 , fParagraphDatabase{paragraphDatabase}
1290 , fHidableTextRuns{}
1293 if (hidableTextDatabase.get () !=
nullptr) {
1294 fHidableTextRuns = hidableTextDatabase->GetHidableRegions (selectionStart, selectionEnd);
1298#if qStroika_Frameworks_Led_SupportGDI
1299WordProcessorTextIOSrcStream::WordProcessorTextIOSrcStream (WordProcessor* textImager,
size_t selectionStart,
size_t selectionEnd)
1300 : inherited (textImager, selectionStart, selectionEnd)
1301 , fParagraphDatabase (textImager->GetParagraphDatabase ())
1302 , fHidableTextRuns ()
1304 shared_ptr<HidableTextMarkerOwner> hidableTextDatabase = textImager->GetHidableTextDatabase ();
1305 if (hidableTextDatabase.get () !=
nullptr) {
1306 fHidableTextRuns = hidableTextDatabase->GetHidableRegions (selectionStart, selectionEnd);
1311Justification WordProcessorTextIOSrcStream::GetJustification ()
const
1313 if (fParagraphDatabase.get () ==
nullptr) {
1314 return inherited::GetJustification ();
1317 return fParagraphDatabase->GetParagraphInfo (GetCurOffset ()).GetJustification ();
1321StandardTabStopList WordProcessorTextIOSrcStream::GetStandardTabStopList ()
const
1323 if (fParagraphDatabase.get () ==
nullptr) {
1324 return inherited::GetStandardTabStopList ();
1327 return fParagraphDatabase->GetParagraphInfo (GetCurOffset ()).GetTabStopList ();
1331TWIPS WordProcessorTextIOSrcStream::GetFirstIndent ()
const
1333 if (fParagraphDatabase.get () ==
nullptr) {
1334 return inherited::GetFirstIndent ();
1337 return fParagraphDatabase->GetParagraphInfo (GetCurOffset ()).GetFirstIndent ();
1341void WordProcessorTextIOSrcStream::GetMargins (TWIPS* lhs, TWIPS* rhs)
const
1345 if (fParagraphDatabase.get () ==
nullptr) {
1346 inherited::GetMargins (lhs, rhs);
1349 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (GetCurOffset ());
1350 *lhs = pi.GetLeftMargin ();
1351 *rhs = pi.GetRightMargin ();
1359TWIPS WordProcessorTextIOSrcStream::GetSpaceBefore ()
const
1361 if (fParagraphDatabase.get () ==
nullptr) {
1362 return inherited::GetSpaceBefore ();
1365 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (GetCurOffset ());
1366 return pi.GetSpaceBefore ();
1374TWIPS WordProcessorTextIOSrcStream::GetSpaceAfter ()
const
1376 if (fParagraphDatabase.get () ==
nullptr) {
1377 return inherited::GetSpaceAfter ();
1380 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (GetCurOffset ());
1381 return pi.GetSpaceAfter ();
1389LineSpacing WordProcessorTextIOSrcStream::GetLineSpacing ()
const
1391 if (fParagraphDatabase.get () ==
nullptr) {
1392 return inherited::GetLineSpacing ();
1395 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (GetCurOffset ());
1396 return pi.GetLineSpacing ();
1404void WordProcessorTextIOSrcStream::GetListStyleInfo (ListStyle* listStyle,
unsigned char* indentLevel)
const
1408 if (fParagraphDatabase.get () ==
nullptr) {
1409 inherited::GetListStyleInfo (listStyle, indentLevel);
1412 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (GetCurOffset ());
1413 *listStyle = pi.GetListStyle ();
1414 *indentLevel = pi.GetListIndentLevel ();
1418Led_tChar WordProcessorTextIOSrcStream::GetSoftLineBreakCharacter ()
const
1420 return kSoftLineBreakChar;
1423DiscontiguousRun<bool> WordProcessorTextIOSrcStream::GetHidableTextRuns ()
const
1425 return fHidableTextRuns;
1428#if qStroika_Frameworks_Led_SupportTables
1429WordProcessorTextIOSrcStream::Table* WordProcessorTextIOSrcStream::GetTableAt (
size_t at)
const
1431 Require (fParagraphDatabase.get () !=
nullptr);
1432 TextStore& ts = fParagraphDatabase->GetTextStore ();
1433 size_t realCoordStart = GetEmbeddingMarkerPosOffset () + at;
1434 MarkerOfATypeMarkerSink<WordProcessorTable> maybeTable;
1435 ts.CollectAllMarkersInRangeInto (realCoordStart, realCoordStart + 1, fParagraphDatabase.get (), maybeTable);
1436 if (maybeTable.fResult ==
nullptr) {
1444 [[maybe_unused]]
size_t realCoordEnd = min (maybeTable.fResult->GetEnd (), GetSelEnd ());
1445 Assert (realCoordStart < realCoordEnd);
1446 if (fUseTableSelection) {
1447 size_t rowSelStart = 0;
1448 size_t rowSelEnd = 0;
1449 size_t colSelStart = 0;
1450 size_t colSelEnd = 0;
1451 maybeTable.fResult->GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
1452 return new TableIOMapper{*maybeTable.fResult, rowSelStart, rowSelEnd, colSelStart, colSelEnd};
1455 return new TableIOMapper{*maybeTable.fResult};
1461void WordProcessorTextIOSrcStream::SummarizeFontAndColorTable (set<SDKString>* fontNames, set<Color>* colorsUsed)
const
1463 inherited::SummarizeFontAndColorTable (fontNames, colorsUsed);
1466 TextStore& ts = fParagraphDatabase->GetTextStore ();
1467 MarkersOfATypeMarkerSink2Vector<WordProcessorTable> tables;
1468 ts.CollectAllMarkersInRangeInto (GetSelStart (), GetSelEnd (), fParagraphDatabase.get (), tables);
1469 for (
auto i = tables.fResult.begin (); i != tables.fResult.end (); ++i) {
1470 TableIOMapper tiom (**i);
1471 size_t rows = tiom.GetRows ();
1472 for (
size_t r = 0; r < rows; ++r) {
1473 size_t columns = tiom.GetColumns (r);
1474 for (
size_t c = 0; c < columns; ++c) {
1475 unique_ptr<StyledTextIOWriter::SrcStream> subSrcStream (tiom.MakeCellSubSrcStream (r, c));
1476 if (subSrcStream.get () !=
nullptr) {
1477 subSrcStream.get ()->SummarizeFontAndColorTable (fontNames, colorsUsed);
1480 if (colorsUsed !=
nullptr) {
1481 using CellInfo = StyledTextIOWriter::SrcStream::Table::CellInfo;
1482 vector<CellInfo> cellInfos;
1483 tiom.GetRowInfo (r, &cellInfos);
1484 for (
auto ci = cellInfos.begin (); ci != cellInfos.end (); ++ci) {
1485 colorsUsed->insert ((*ci).f_clcbpat);
1498WordProcessorTextIOSrcStream::TableIOMapper::TableIOMapper (WordProcessorTable& realTable,
size_t startRow,
size_t endRow,
size_t startCol,
size_t endCol)
1499 : fRealTable{realTable}
1500 , fStartRow{startRow}
1502 , fStartCol{startCol}
1505 if (fEndRow ==
static_cast<size_t> (-1)) {
1506 fEndRow = fRealTable.GetRowCount ();
1508 if (fEndCol ==
static_cast<size_t> (-1)) {
1509 fEndCol = fRealTable.GetColumnCount ();
1512 Ensure (fStartRow < fEndRow);
1513 Ensure (fStartCol < fEndCol);
1514 Ensure (fEndRow <= fRealTable.GetRowCount ());
1515 Ensure (fEndCol <= fRealTable.GetColumnCount ());
1518size_t WordProcessorTextIOSrcStream::TableIOMapper::GetRows ()
const
1520 return fEndRow - fStartRow;
1523size_t WordProcessorTextIOSrcStream::TableIOMapper::GetColumns (
size_t row)
const
1525 size_t vRow = row + fStartRow;
1526 size_t realColCount = fRealTable.GetColumnCount (vRow);
1527 size_t pinnedColEnd = min (realColCount, fEndCol);
1529 Assert (pinnedColEnd > fStartCol);
1531 return pinnedColEnd - fStartCol;
1534void WordProcessorTextIOSrcStream::TableIOMapper::GetRowInfo (
size_t row, vector<CellInfo>* cellInfos)
1536 Require (row < GetRows ());
1538 size_t vRow = row + fStartRow;
1541 size_t columns = GetColumns (row);
1542 cellInfos->clear ();
1543 for (
size_t c = 0; c < columns; ++c) {
1544 size_t vCol = c + fStartCol;
1545 if (fRealTable.GetCellFlags (vRow, vCol) == WordProcessorTable::ePlainCell) {
1547 cellInfo.f_clcbpat = fRealTable.GetCellColor (vRow, vCol);
1548 cellInfo.f_cellx = fRealTable.GetColumnWidth (vRow, vCol);
1549 cellInfos->push_back (cellInfo);
1553 if (not cellInfos->empty ()) {
1554 cellInfos->back ().f_cellx += fRealTable.GetColumnWidth (vRow, vCol);
1560StyledTextIOWriter::SrcStream* WordProcessorTextIOSrcStream::TableIOMapper::MakeCellSubSrcStream (
size_t row,
size_t column)
1562 Require (row < GetRows ());
1563 Require (column < GetColumns (row));
1565 size_t vRow = row + fStartRow;
1566 size_t vCol = column + fStartCol;
1568 if (fRealTable.GetCellFlags (vRow, vCol) == WordProcessorTable::ePlainCell) {
1569 TextStore* ts =
nullptr;
1570 shared_ptr<AbstractStyleDatabaseRep> styleDatabase;
1571 shared_ptr<AbstractParagraphDatabaseRep> paragraphDatabase;
1572 shared_ptr<HidableTextMarkerOwner> hidableTextDatabase;
1573 fRealTable.GetCellWordProcessorDatabases (vRow, vCol, &ts, &styleDatabase, ¶graphDatabase, &hidableTextDatabase);
1581size_t WordProcessorTextIOSrcStream::TableIOMapper::GetOffsetEnd ()
const
1588TWIPS_Rect WordProcessorTextIOSrcStream::TableIOMapper::GetDefaultCellMarginsForRow (
size_t )
const
1591 TWIPS_Rect cellMargins = TWIPS_Rect (TWIPS{0}, TWIPS{0}, TWIPS{0}, TWIPS{0});
1592 fRealTable.GetDefaultCellMargins (&cellMargins.top, &cellMargins.left, &cellMargins.bottom, &cellMargins.right);
1596TWIPS_Rect WordProcessorTextIOSrcStream::TableIOMapper::GetDefaultCellSpacingForRow (
size_t )
const
1599 TWIPS cellSpacing = fRealTable.GetCellSpacing ();
1600 return TWIPS_Rect (cellSpacing, cellSpacing, TWIPS{0}, TWIPS{0});
1603#if qStroika_Frameworks_Led_SupportGDI
1605class ParagraphInfoChangeTextRep :
public InteractiveReplaceCommand::SavedTextRep {
1607 using inherited = InteractiveReplaceCommand::SavedTextRep;
1610 using ParaInfoNSize = pair<ParagraphInfo, size_t>;
1613 ParagraphInfoChangeTextRep (WordProcessor* interactor,
size_t from,
size_t to)
1614 : inherited (from, to)
1617 fSavedInfo = interactor->GetParagraphDatabase ()->GetParagraphInfo (from, to - from);
1618 Assert (GetLength () == to - from);
1620 virtual size_t GetLength ()
const override
1623 for (
auto i = fSavedInfo.begin (); i != fSavedInfo.end (); ++i) {
1628 virtual void InsertSelf (TextInteractor* interactor,
size_t at, [[maybe_unused]]
size_t nBytesToOverwrite)
override
1631 WordProcessor* wp =
dynamic_cast<WordProcessor*
> (interactor);
1633 Assert (nBytesToOverwrite == GetLength ());
1634 shared_ptr<AbstractParagraphDatabaseRep> paraDBase = wp->GetParagraphDatabase ();
1635 paraDBase->SetParagraphInfo (at, fSavedInfo);
1639 vector<ParaInfoNSize> fSavedInfo;
1643template <
typename SPECIALIZER,
typename T1>
1644void InteractiveWPHelper1 (WordProcessor* wp, T1 arg1)
1646 TextInteractor::InteractiveModeUpdater iuMode (*wp);
1647 using SavedTextRep = InteractiveReplaceCommand::SavedTextRep;
1648 wp->BreakInGroupedCommands ();
1649 size_t selStart = wp->GetSelectionStart ();
1650 size_t selEnd = wp->GetSelectionEnd ();
1651 SavedTextRep* before =
nullptr;
1652 SavedTextRep* after =
nullptr;
1654 if (wp->GetCommandHandler () !=
nullptr) {
1655 before =
new ParagraphInfoChangeTextRep (wp, selStart, selEnd);
1657 SPECIALIZER::DoIt (wp, selStart, selEnd, arg1);
1658 if (wp->GetCommandHandler () !=
nullptr) {
1659 after =
new ParagraphInfoChangeTextRep (wp, selStart, selEnd);
1660 wp->PostInteractiveUndoPostHelper (&before, &after, selStart, SPECIALIZER::GetName (wp));
1668 wp->BreakInGroupedCommands ();
1670struct DoIt_SetJustification {
1671 static void DoIt (WordProcessor* wp,
size_t selStart,
size_t selEnd, Justification justification)
1673 wp->SetJustification (selStart, selEnd, justification);
1675 static SDKString GetName (WordProcessor* wp)
1677 return wp->GetCommandNames ().fJustificationCommandName;
1680struct DoIt_SetStandardTabStopList {
1681 static void DoIt (WordProcessor* wp,
size_t selStart,
size_t selEnd, StandardTabStopList tabStops)
1683 wp->SetStandardTabStopList (selStart, selEnd, tabStops);
1685 static SDKString GetName (WordProcessor* wp)
1687 return wp->GetCommandNames ().fStandardTabStopListCommandName;
1690struct DoIt_SetMargins {
1694 Margins (TWIPS l, TWIPS r)
1700 static void DoIt (WordProcessor* wp,
size_t selStart,
size_t selEnd, Margins margins)
1702 wp->SetMargins (selStart, selEnd, margins.fLHS, margins.fRHS);
1704 static SDKString GetName (WordProcessor* wp)
1706 return wp->GetCommandNames ().fMarginsCommandName;
1709struct DoIt_SetFirstIndent {
1710 static void DoIt (WordProcessor* wp,
size_t selStart,
size_t selEnd, TWIPS firstIndent)
1712 wp->SetFirstIndent (selStart, selEnd, firstIndent);
1714 static SDKString GetName (WordProcessor* wp)
1716 return wp->GetCommandNames ().fFirstIndentCommandName;
1719struct DoIt_SetMarginsAndFirstIndent {
1720 struct MarginsAndFirstIndent {
1724 MarginsAndFirstIndent (TWIPS l, TWIPS r, TWIPS firstIndent)
1727 , fFirstIndent (firstIndent)
1731 static void DoIt (WordProcessor* wp,
size_t selStart,
size_t selEnd, MarginsAndFirstIndent marginsEtc)
1733 wp->SetMargins (selStart, selEnd, marginsEtc.fLHS, marginsEtc.fRHS);
1734 wp->SetFirstIndent (selStart, selEnd, marginsEtc.fFirstIndent);
1736 static SDKString GetName (WordProcessor* wp)
1738 return wp->GetCommandNames ().fMarginsAndFirstIndentCommandName;
1741struct DoIt_SetParagraphSpacing {
1742 struct AllSpacingArgs {
1745 LineSpacing fLineSpacing;
1746 bool fSBValid, fSAValid, fSLValid;
1747 AllSpacingArgs (TWIPS sb,
bool sbValid, TWIPS sa,
bool saValid, LineSpacing sl,
bool slValid)
1749 , fSBValid (sbValid)
1751 , fSAValid (saValid)
1753 , fSLValid (slValid)
1757 static void DoIt (WordProcessor* wp,
size_t selStart,
size_t selEnd, AllSpacingArgs spacingArgs)
1759 if (spacingArgs.fSBValid) {
1760 wp->SetSpaceBefore (selStart, selEnd, spacingArgs.fSpaceBefore);
1762 if (spacingArgs.fSAValid) {
1763 wp->SetSpaceAfter (selStart, selEnd, spacingArgs.fSpaceAfter);
1765 if (spacingArgs.fSLValid) {
1766 wp->SetLineSpacing (selStart, selEnd, spacingArgs.fLineSpacing);
1769 static SDKString GetName (WordProcessor* wp)
1771 return wp->GetCommandNames ().fParagraphSpacingCommandName;
1774struct DoIt_SetListStyle {
1775 static void DoIt (WordProcessor* wp,
size_t selStart,
size_t selEnd, ListStyle listStyle)
1777 wp->SetListStyle (selStart, selEnd, listStyle,
true);
1779 static SDKString GetName (WordProcessor* wp)
1781 return wp->GetCommandNames ().fSetListStyleCommandName;
1784struct DoIt_IndentUnIndentList {
1785 static void DoIt (WordProcessor* wp,
size_t selStart,
size_t selEnd,
bool indent)
1787 unsigned char indentLevel = wp->GetListIndentLevel (selStart);
1789 if (indentLevel < 8) {
1797 if (indentLevel > 0) {
1804 wp->SetListIndentLevel (selStart, selEnd, indentLevel,
true);
1806 static SDKString GetName (WordProcessor* wp)
1808 return wp->GetCommandNames ().fIndentLevelChangeCommandName;
1817WordProcessor::WPIdler::WPIdler ()
1822void WordProcessor::WPIdler::SpendIdleTime ()
1828 AbstractParagraphDatabaseRep* pdbRep = fWP->GetParagraphDatabase ().get ();
1830 if (pdbRep->fSomeInvalidTables) {
1835 vector<WordProcessorTable*> tables = fWP->GetTablesInRange (0, fWP->GetEnd ());
1836 bool maybeMoreTables =
false;
1837 for (
auto i = tables.begin (); i != tables.end (); ++i) {
1838 WordProcessorTable* t = *i;
1839 if (t->fNeedLayout != WordProcessorTable::eDone) {
1840 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*t, *fWP);
1841 t->PerformLayout ();
1842 if (endTime < Time::GetTickCount ()) {
1843 maybeMoreTables =
true;
1848 pdbRep->fSomeInvalidTables = maybeMoreTables;
1857WordProcessor::DialogSupport::FontNameSpecifier WordProcessor::DialogSupport::CmdNumToFontName (CommandNumber )
1861 return FontNameSpecifier ();
1864bool WordProcessor::DialogSupport::IsPredefinedFontSize (DistanceType fontSize)
1890DistanceType WordProcessor::DialogSupport::FontCmdToSize (CommandNumber commandNum)
1892 switch (commandNum) {
1893 case kFontSize9_CmdID:
1895 case kFontSize10_CmdID:
1897 case kFontSize12_CmdID:
1899 case kFontSize14_CmdID:
1901 case kFontSize18_CmdID:
1903 case kFontSize24_CmdID:
1905 case kFontSize36_CmdID:
1907 case kFontSize48_CmdID:
1909 case kFontSize72_CmdID:
1915DistanceType WordProcessor::DialogSupport::PickOtherFontHeight (DistanceType )
1921bool WordProcessor::DialogSupport::PickNewParagraphLineSpacing (TWIPS* ,
bool* , TWIPS* ,
1922 bool* , LineSpacing* ,
bool* )
1928bool WordProcessor::DialogSupport::PickNewParagraphMarginsAndFirstIndent (TWIPS* ,
bool* , TWIPS* ,
1929 bool* , TWIPS* ,
bool* )
1935Color WordProcessor::DialogSupport::FontCmdToColor (CommandNumber cmd)
1938 case kFontColorBlack_CmdID:
1939 return Color::kBlack;
1940 case kFontColorMaroon_CmdID:
1941 return Color::kMaroon;
1942 case kFontColorGreen_CmdID:
1943 return Color::kGreen;
1944 case kFontColorOlive_CmdID:
1945 return Color::kOlive;
1946 case kFontColorNavy_CmdID:
1947 return Color::kNavyBlue;
1948 case kFontColorPurple_CmdID:
1949 return Color::kPurple;
1950 case kFontColorTeal_CmdID:
1951 return Color::kTeal;
1952 case kFontColorGray_CmdID:
1953 return Color::kGray;
1954 case kFontColorSilver_CmdID:
1955 return Color::kSilver;
1956 case kFontColorRed_CmdID:
1958 case kFontColorLime_CmdID:
1959 return Color::kLimeGreen;
1960 case kFontColorYellow_CmdID:
1961 return Color::kYellow;
1962 case kFontColorBlue_CmdID:
1963 return Color::kBlue;
1964 case kFontColorFuchsia_CmdID:
1965 return Color::kFuchsia;
1966 case kFontColorAqua_CmdID:
1967 return Color::kAqua;
1968 case kFontColorWhite_CmdID:
1969 return Color::kWhite;
1972 return Color::kBlack;
1975WordProcessor::DialogSupport::CommandNumber WordProcessor::DialogSupport::FontColorToCmd (
Color color)
1977 if (color == Color::kBlack) {
1978 return kFontColorBlack_CmdID;
1980 else if (color == Color::kMaroon) {
1981 return kFontColorMaroon_CmdID;
1983 else if (color == Color::kGreen) {
1984 return kFontColorGreen_CmdID;
1986 else if (color == Color::kOlive) {
1987 return kFontColorOlive_CmdID;
1989 else if (color == Color::kNavyBlue) {
1990 return kFontColorNavy_CmdID;
1992 else if (color == Color::kPurple) {
1993 return kFontColorPurple_CmdID;
1995 else if (color == Color::kTeal) {
1996 return kFontColorTeal_CmdID;
1998 else if (color == Color::kGray) {
1999 return kFontColorGray_CmdID;
2001 else if (color == Color::kSilver) {
2002 return kFontColorSilver_CmdID;
2004 else if (color == Color::kRed) {
2005 return kFontColorRed_CmdID;
2007 else if (color == Color::kGreen) {
2008 return kFontColorLime_CmdID;
2010 else if (color == Color::kYellow) {
2011 return kFontColorYellow_CmdID;
2013 else if (color == Color::kBlue) {
2014 return kFontColorBlue_CmdID;
2016 else if (color == Color::kFuchsia) {
2017 return kFontColorFuchsia_CmdID;
2019 else if (color == Color::kAqua) {
2020 return kFontColorAqua_CmdID;
2022 else if (color == Color::kWhite) {
2023 return kFontColorWhite_CmdID;
2028 for (CommandNumber i = kBaseFontColor_CmdID; i <= kLastNamedFontColor_CmdID; ++i) {
2029 if (FontCmdToColor (i) == color) {
2033 return kFontColorOther_CmdID;
2037bool WordProcessor::DialogSupport::PickOtherFontColor (
Color* color)
2041#if qStroika_Foundation_Common_Platform_MacOS
2042 RGBColor oldColor = color->GetOSRep ();
2043 RGBColor newColor = oldColor;
2044 Point where = {0, 0};
2045 if (::GetColor (where,
"\pPick new color", &oldColor, &newColor)) {
2046 *color =
Color (newColor);
2049#elif qStroika_Foundation_Common_Platform_Windows
2051 memset (&cc, 0,
sizeof (cc));
2052 cc.lStructSize =
sizeof (cc);
2053 cc.Flags |= CC_ANYCOLOR;
2054 cc.rgbResult = color->GetOSRep ();
2055 cc.Flags |= CC_RGBINIT;
2056 cc.Flags |= CC_FULLOPEN;
2058 cc.Flags |= CC_ENABLEHOOK;
2059 cc.lpfnHook = ColorPickerINITPROC;
2061 static COLORREF sCustomColors[16];
2062 cc.lpCustColors = sCustomColors;
2064 cc.hwndOwner = ::GetActiveWindow ();
2066 if (::ChooseColor (&cc)) {
2067 *color =
Color (cc.rgbResult);
2074#if qStroika_Foundation_Common_Platform_Windows
2075UINT_PTR CALLBACK WordProcessor::DialogSupport::ColorPickerINITPROC (HWND hWnd, UINT message, [[maybe_unused]] WPARAM wParam, [[maybe_unused]] LPARAM lParam)
2077 if (hWnd !=
nullptr and message == WM_INITDIALOG) {
2078 Led_CenterWindowInParent (hWnd);
2084bool WordProcessor::DialogSupport::ChooseFont ([[maybe_unused]] IncrementalFontSpecification* font)
2088#if qStroika_Foundation_Common_Platform_Windows
2091 (void)::memset (&lf, 0,
sizeof (lf));
2092 if (font->GetFontNameSpecifier_Valid ()) {
2093 Characters::CString::Copy (lf.lfFaceName, Memory::NEltsOf (lf.lfFaceName), font->GetFontNameSpecifier ().fName);
2094 Assert (::_tcslen (lf.lfFaceName) < Memory::NEltsOf (lf.lfFaceName));
2096 lf.lfWeight = (font->GetStyle_Bold_Valid () and font->GetStyle_Bold ()) ? FW_BOLD : FW_NORMAL;
2097 lf.lfItalic = (font->GetStyle_Italic_Valid () and font->GetStyle_Italic ());
2098 lf.lfUnderline = (font->GetStyle_Underline_Valid () and font->GetStyle_Underline ());
2099 lf.lfStrikeOut = (font->GetStyle_Strikeout_Valid () and font->GetStyle_Strikeout ());
2101 if (font->GetPointSize_Valid ()) {
2102 lf.lfHeight = font->PeekAtTMHeight ();
2106 memset (&cc, 0,
sizeof (cc));
2107 cc.lStructSize =
sizeof (cc);
2108 cc.Flags |= CF_SCREENFONTS | CF_NOVERTFONTS | CF_EFFECTS | CF_SCALABLEONLY;
2110 cc.hwndOwner = ::GetActiveWindow ();
2113 cc.Flags |= CF_INITTOLOGFONTSTRUCT;
2115 if (font->GetTextColor_Valid ()) {
2116 cc.rgbColors = font->GetTextColor ().GetOSRep ();
2119 if (::ChooseFont (&cc)) {
2121 font->SetTextColor (
Color (cc.rgbColors));
2128void WordProcessor::DialogSupport::ShowSimpleEmbeddingInfoDialog (
const SDKString& )
2139bool WordProcessor::DialogSupport::ShowAddURLEmbeddingInfoDialog (
SDKString* ,
SDKString* )
2145bool WordProcessor::DialogSupport::AddNewTableDialog (
size_t* nRows,
size_t* nCols)
2155bool WordProcessor::DialogSupport::EditTablePropertiesDialog ([[maybe_unused]] TableSelectionPropertiesInfo* tableProperties)
2166WordProcessor::CommandNames WordProcessor::sCommandNames = WordProcessor::MakeDefaultCommandNames ();
2167WordProcessor::DialogSupport* WordProcessor::sDialogSupport =
nullptr;
2169template <
class T,
class EXTRACTOR>
2170bool CheckForCommonParaValue (EXTRACTOR ,
const shared_ptr<AbstractParagraphDatabaseRep>& paraDB,
2171 size_t from,
size_t to, T* commonValue)
2174 if (paraDB.get () ==
nullptr) {
2175 throw WordProcessor::NoParagraphDatabaseAvailable ();
2177 vector<pair<ParagraphInfo, size_t>> v = paraDB->GetParagraphInfo (from, to - from);
2178 Assert (v.size () != 0);
2179 if (v.size () >= 1) {
2180 T maybeCommonValue = EXTRACTOR () (v[0].first);
2181 for (
auto i = v.begin () + 1; i != v.end (); ++i) {
2182 if (EXTRACTOR () ((*i).first) != maybeCommonValue) {
2186 *commonValue = maybeCommonValue;
2193struct JustificationExtractor {
2196 return from.GetJustification ();
2199struct TabStopExtractor {
2202 return from.GetTabStopList ();
2205struct FirstIndentExtractor {
2208 return from.GetFirstIndent ();
2217 MarginsRec (TWIPS lhs, TWIPS rhs)
2226 inline bool operator!= (
const MarginsRec& rhs)
2228 return fLHS != rhs.fLHS or fRHS != rhs.fRHS;
2231struct MarginsRecExtractor {
2234 return MarginsRec (from.GetLeftMargin (), from.GetRightMargin ());
2237struct SpaceBeforeExtractor {
2240 return from.GetSpaceBefore ();
2243struct SpaceAfterExtractor {
2246 return from.GetSpaceAfter ();
2249struct LineSpacingExtractor {
2252 return from.GetLineSpacing ();
2255struct ListStyleExtractor {
2258 return from.GetListStyle ();
2261struct ListIndentLevelExtractor {
2264 return from.GetListIndentLevel ();
2268WordProcessor::WordProcessor ()
2270 , fSmartQuoteMode (true)
2271 , fParagraphDatabase (nullptr)
2272 , fICreatedParaDB (false)
2273 , fHidableTextDatabase (nullptr)
2274 , fICreatedHidableTextDB (false)
2276 , fCachedCurSelFontSpec ()
2277 , fCachedCurSelJustification (eLeftJustify)
2278 , fCachedCurSelJustificationUnique (false)
2279 , fCachedCurSelFontSpecValid (false)
2280 , fShowParagraphGlyphs (false)
2281 , fShowTabGlyphs (false)
2282 , fShowSpaceGlyphs (false)
2284 fWPIdler.fWP =
this;
2285 IdleManager::Get ().AddIdler (&fWPIdler);
2286 IdleManager::Get ().SetIdlerFrequncy (&fWPIdler, 0.25s);
2289WordProcessor::~WordProcessor ()
2291 IdleManager::Get ().RemoveIdler (&fWPIdler);
2294void WordProcessor::HookLosingTextStore ()
2296 HookLosingTextStore_ ();
2297 inherited::HookLosingTextStore ();
2300void WordProcessor::HookLosingTextStore_ ()
2303 MarkersOfATypeMarkerSink2Vector<WordProcessorTable> tables;
2304 GetTextStore ().CollectAllMarkersInRangeInto (GetTextStore ().GetStart (), GetTextStore ().GetEnd (),
this, tables);
2305#if qConstNonConstPtrConversionsWithTemplatedMemberFunctionBug
2306 WordProcessorTable** t = Traversal::Iterator2Pointer (tables.fResultArray.begin ());
2307 WordProcessorTable*
const* tt = t;
2308 GetTextStore ().RemoveAndDeleteMarkers (tt, tables.fResult.size ());
2310 GetTextStore ().RemoveAndDeleteMarkers (
Containers::Start (tables.fResult), tables.fResult.size ());
2319 if (fICreatedParaDB) {
2320 fICreatedParaDB =
false;
2321 if (fParagraphDatabase.get () !=
nullptr) {
2322 fParagraphDatabase.reset ();
2323 HookParagraphDatabaseChanged ();
2326 if (fICreatedHidableTextDB) {
2327 SetHidableTextDatabase (
nullptr);
2328 fICreatedHidableTextDB =
false;
2331 if (fHidableTextDatabase.get () !=
nullptr) {
2332 fHidableTextDatabase->SetInternalizer (
nullptr);
2333 fHidableTextDatabase->SetExternalizer (
nullptr);
2337void WordProcessor::HookGainedNewTextStore ()
2343 if (fParagraphDatabase.get () !=
nullptr) {
2344 SetPartition (fParagraphDatabase->GetPartition ());
2346 inherited::HookGainedNewTextStore ();
2347 HookGainedNewTextStore_ ();
2350void WordProcessor::HookGainedNewTextStore_ ()
2352 if (fParagraphDatabase.get () ==
nullptr) {
2353 SetParagraphDatabase (
nullptr);
2355 if (fHidableTextDatabase.get () ==
nullptr) {
2356 SetHidableTextDatabase (make_shared<UniformHidableTextMarkerOwner> (GetTextStore ()));
2357 fICreatedHidableTextDB =
true;
2361shared_ptr<Partition> WordProcessor::MakeDefaultPartition ()
const
2365 if (fParagraphDatabase.get () ==
nullptr) {
2366 return make_shared<LineBasedPartition> (GetTextStore ());
2369 const MarkerOwner* mo = fParagraphDatabase.get ();
2370 return make_shared<WPPartition> (GetTextStore (), *
const_cast<MarkerOwner*
> (mo));
2383void WordProcessor::SetParagraphDatabase (
const shared_ptr<AbstractParagraphDatabaseRep>& paragraphDatabase)
2385 fParagraphDatabase = paragraphDatabase;
2386 fICreatedParaDB =
false;
2387 if (fParagraphDatabase.get () ==
nullptr and PeekAtTextStore () !=
nullptr) {
2388 fParagraphDatabase = make_shared<ParagraphDatabaseRep> (GetTextStore ());
2389 fICreatedParaDB =
true;
2392 HookParagraphDatabaseChanged ();
2402void WordProcessor::HookParagraphDatabaseChanged ()
2404 if (PeekAtTextStore () !=
nullptr) {
2405 HookParagraphDatabaseChanged_ ();
2413void WordProcessor::HookParagraphDatabaseChanged_ ()
2421 if (fParagraphDatabase.get () !=
nullptr) {
2422 SetPartition (fParagraphDatabase->GetPartition ());
2424 SetExternalizer (MakeDefaultExternalizer ());
2425 SetInternalizer (MakeDefaultInternalizer ());
2440void WordProcessor::SetHidableTextDatabase (
const shared_ptr<HidableTextMarkerOwner>& hidableTextDatabase)
2443 if (fHidableTextDatabase.get () !=
nullptr) {
2444 fHidableTextDatabase->SetInternalizer (shared_ptr<FlavorPackageInternalizer> ());
2445 fHidableTextDatabase->SetExternalizer (shared_ptr<FlavorPackageExternalizer> ());
2448 fHidableTextDatabase = hidableTextDatabase;
2449 fICreatedHidableTextDB =
false;
2450 HookHidableTextDatabaseChanged ();
2460void WordProcessor::HookHidableTextDatabaseChanged ()
2462 HookHidableTextDatabaseChanged_ ();
2471void WordProcessor::HookHidableTextDatabaseChanged_ ()
2473 if (PeekAtTextStore () !=
nullptr) {
2474 SetExternalizer (MakeDefaultExternalizer ());
2475 SetInternalizer (MakeDefaultInternalizer ());
2479shared_ptr<FlavorPackageInternalizer> WordProcessor::MakeDefaultInternalizer ()
2481 return make_shared<WordProcessorFlavorPackageInternalizer> (GetTextStore (), GetStyleDatabase (), GetParagraphDatabase (),
2482 GetHidableTextDatabase ());
2485shared_ptr<FlavorPackageExternalizer> WordProcessor::MakeDefaultExternalizer ()
2487 return make_shared<WordProcessorFlavorPackageExternalizer> (GetTextStore (), GetStyleDatabase (), GetParagraphDatabase (),
2488 GetHidableTextDatabase ());
2495void WordProcessor::HookInternalizerChanged ()
2497 inherited::HookInternalizerChanged ();
2498 if (fHidableTextDatabase.get () !=
nullptr) {
2499 fHidableTextDatabase->SetInternalizer (GetInternalizer ());
2507void WordProcessor::HookExternalizerChanged ()
2509 inherited::HookExternalizerChanged ();
2510 if (fHidableTextDatabase.get () !=
nullptr) {
2511 fHidableTextDatabase->SetExternalizer (GetExternalizer ());
2520void WordProcessor::InternalizeBestFlavor (
ReaderFlavorPackage& flavorPackage,
bool updateCursorPosition,
bool autoScroll, UpdateMode updateMode)
2522 WordProcessorTable* t = GetActiveTable ();
2524 WordProcessorFlavorPackageInternalizer* internalizerRep =
2525 dynamic_cast<WordProcessorFlavorPackageInternalizer*
> (
static_cast<FlavorPackageInternalizer*
> (GetInternalizer ().get ()));
2528 bool oldFlagVal = internalizerRep->GetOverwriteTableMode ();
2529 internalizerRep->SetOverwriteTableMode (
true);
2531 size_t selEnd = GetSelectionEnd ();
2532 Assert (selEnd - GetSelectionStart () == 1);
2536 bool good = GetInternalizer ()->InternalizeBestFlavor (flavorPackage, selEnd, selEnd);
2539 ScrollToSelection ();
2541 if (updateMode == eImmediateUpdate) {
2548 internalizerRep->SetOverwriteTableMode (oldFlagVal);
2551 internalizerRep->SetOverwriteTableMode (oldFlagVal);
2556 inherited::InternalizeBestFlavor (flavorPackage, updateCursorPosition, autoScroll, updateMode);
2567 WordProcessorFlavorPackageExternalizer* externalizerRep =
2568 dynamic_cast<WordProcessorFlavorPackageExternalizer*
> (
static_cast<FlavorPackageExternalizer*
> (GetExternalizer ().get ()));
2571 bool oldFlagVal = externalizerRep->GetUseTableSelection ();
2572 externalizerRep->SetUseTableSelection (
true);
2574 inherited::ExternalizeFlavors (flavorPackage);
2575 externalizerRep->SetUseTableSelection (oldFlagVal);
2578 externalizerRep->SetUseTableSelection (oldFlagVal);
2588void WordProcessor::InterectiveSetRegionHidable (
bool hidable)
2592 BreakInGroupedCommands ();
2594 UndoableContextHelper undoContext (*
this, hidable ? GetCommandNames ().fHideCommandName : GetCommandNames ().fUnHideCommandName, false);
2597 GetHidableTextDatabase ()->MakeRegionHidable (undoContext.GetUndoRegionStart (), undoContext.GetUndoRegionEnd ());
2600 GetHidableTextDatabase ()->MakeRegionUnHidable (undoContext.GetUndoRegionStart (), undoContext.GetUndoRegionEnd ());
2603 undoContext.CommandComplete ();
2611Justification WordProcessor::GetJustification (
size_t characterPos)
const
2613 if (fParagraphDatabase.get () ==
nullptr) {
2614 throw NoParagraphDatabaseAvailable ();
2616 return fParagraphDatabase->GetParagraphInfo (characterPos).GetJustification ();
2624bool WordProcessor::GetJustification (
size_t from,
size_t to, Justification* justification)
const
2627 return CheckForCommonParaValue (JustificationExtractor (), fParagraphDatabase, from, to, justification);
2635void WordProcessor::SetJustification (
size_t from,
size_t to, Justification justification)
2637 Require (from <= to);
2639 pi.SetJustification (justification);
2640 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2643StandardTabStopList WordProcessor::GetDefaultStandardTabStopList ()
2645 return StandardTabStopList{};
2653StandardTabStopList WordProcessor::GetStandardTabStopList (
size_t characterPos)
const
2655 return fParagraphDatabase->GetParagraphInfo (characterPos).GetTabStopList ();
2663bool WordProcessor::GetStandardTabStopList (
size_t from,
size_t to, StandardTabStopList* tabStops)
const
2666 return CheckForCommonParaValue (TabStopExtractor (), fParagraphDatabase, from, to, tabStops);
2674void WordProcessor::SetStandardTabStopList (
size_t from,
size_t to, StandardTabStopList tabStops)
2676 Require (from <= to);
2678 pi.SetTabStopList (tabStops);
2679 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2687void WordProcessor::GetMargins (
size_t characterPos, TWIPS* leftMargin, TWIPS* rightMargin)
const
2691 const ParagraphInfo& pi = fParagraphDatabase->GetParagraphInfo (characterPos);
2695 *leftMargin = pi.GetLeftMargin ();
2696 *rightMargin = pi.GetRightMargin ();
2699bool WordProcessor::GetMargins (
size_t from,
size_t to, TWIPS* leftMargin, TWIPS* rightMargin)
const
2703 MarginsRec mrResult;
2704 bool result = CheckForCommonParaValue (MarginsRecExtractor (), fParagraphDatabase, from, to, &mrResult);
2705 *leftMargin = mrResult.fLHS;
2706 *rightMargin = mrResult.fRHS;
2714void WordProcessor::SetMargins (
size_t from,
size_t to, TWIPS leftMargin, TWIPS rightMargin)
2716 Require (from <= to);
2718 pi.SetMargins (leftMargin, rightMargin);
2719 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2727TWIPS WordProcessor::GetFirstIndent (
size_t characterPos)
const
2729 return fParagraphDatabase->GetParagraphInfo (characterPos).GetFirstIndent ();
2737bool WordProcessor::GetFirstIndent (
size_t from,
size_t to, TWIPS* firstIndent)
const
2740 return CheckForCommonParaValue (FirstIndentExtractor (), fParagraphDatabase, from, to, firstIndent);
2747void WordProcessor::SetFirstIndent (
size_t from,
size_t to, TWIPS firstIndent)
2749 Require (from <= to);
2751 pi.SetFirstIndent (firstIndent);
2752 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2760TWIPS WordProcessor::GetSpaceBefore (
size_t characterPos)
const
2762 if (fParagraphDatabase.get () ==
nullptr) {
2763 throw NoParagraphDatabaseAvailable{};
2765 return fParagraphDatabase->GetParagraphInfo (characterPos).GetSpaceBefore ();
2773bool WordProcessor::GetSpaceBefore (
size_t from,
size_t to, TWIPS* sb)
const
2776 return CheckForCommonParaValue (SpaceBeforeExtractor{}, fParagraphDatabase, from, to, sb);
2784void WordProcessor::SetSpaceBefore (
size_t from,
size_t to, TWIPS sb)
2786 Require (from <= to);
2787 if (fParagraphDatabase.get () ==
nullptr) {
2788 throw NoParagraphDatabaseAvailable{};
2791 pi.SetSpaceBefore (sb);
2792 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2800TWIPS WordProcessor::GetSpaceAfter (
size_t characterPos)
const
2802 if (fParagraphDatabase.get () ==
nullptr) {
2803 throw NoParagraphDatabaseAvailable ();
2805 return fParagraphDatabase->GetParagraphInfo (characterPos).GetSpaceAfter ();
2813bool WordProcessor::GetSpaceAfter (
size_t from,
size_t to, TWIPS* sa)
const
2816 return CheckForCommonParaValue (SpaceAfterExtractor (), fParagraphDatabase, from, to, sa);
2824void WordProcessor::SetSpaceAfter (
size_t from,
size_t to, TWIPS sa)
2826 Require (from <= to);
2827 if (fParagraphDatabase.get () ==
nullptr) {
2828 throw NoParagraphDatabaseAvailable ();
2831 pi.SetSpaceAfter (sa);
2832 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2840LineSpacing WordProcessor::GetLineSpacing (
size_t characterPos)
const
2842 if (fParagraphDatabase.get () ==
nullptr) {
2843 throw NoParagraphDatabaseAvailable ();
2845 return fParagraphDatabase->GetParagraphInfo (characterPos).GetLineSpacing ();
2853bool WordProcessor::GetLineSpacing (
size_t from,
size_t to, LineSpacing* sl)
const
2856 return CheckForCommonParaValue (LineSpacingExtractor (), fParagraphDatabase, from, to, sl);
2864void WordProcessor::SetLineSpacing (
size_t from,
size_t to, LineSpacing sl)
2866 Require (from <= to);
2868 pi.SetLineSpacing (sl);
2869 if (fParagraphDatabase.get () ==
nullptr) {
2870 throw NoParagraphDatabaseAvailable ();
2872 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2880ListStyle WordProcessor::GetListStyle (
size_t characterPos)
const
2882 if (fParagraphDatabase.get () ==
nullptr) {
2883 throw NoParagraphDatabaseAvailable ();
2885 return fParagraphDatabase->GetParagraphInfo (characterPos).GetListStyle ();
2893bool WordProcessor::GetListStyle (
size_t from,
size_t to, ListStyle* listStyle)
const
2896 return CheckForCommonParaValue (ListStyleExtractor (), fParagraphDatabase, from, to, listStyle);
2904void WordProcessor::SetListStyle (
size_t from,
size_t to, ListStyle listStyle,
bool autoFormat)
2906 Require (from <= to);
2908 pi.SetListStyle (listStyle);
2909 if (fParagraphDatabase.get () ==
nullptr) {
2910 throw NoParagraphDatabaseAvailable ();
2912 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2915 AutoFormatIndentedText (from, to);
2924unsigned char WordProcessor::GetListIndentLevel (
size_t characterPos)
const
2926 if (fParagraphDatabase.get () ==
nullptr) {
2927 throw NoParagraphDatabaseAvailable ();
2929 return fParagraphDatabase->GetParagraphInfo (characterPos).GetListIndentLevel ();
2937bool WordProcessor::GetListIndentLevel (
size_t from,
size_t to,
unsigned char* indentLevel)
const
2940 return CheckForCommonParaValue (ListIndentLevelExtractor (), fParagraphDatabase, from, to, indentLevel);
2948void WordProcessor::SetListIndentLevel (
size_t from,
size_t to,
unsigned char indentLevel,
bool autoFormat)
2950 Require (from <= to);
2952 pi.SetListIndentLevel (indentLevel);
2953 if (fParagraphDatabase.get () ==
nullptr) {
2954 throw NoParagraphDatabaseAvailable ();
2956 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2958 AutoFormatIndentedText (from, to);
2969void WordProcessor::AutoFormatIndentedText (
size_t from,
size_t to)
2971 for (PartitionMarker* pm = GetPartitionMarkerContainingPosition (from); pm !=
nullptr and pm->GetStart () <= to; pm = pm->GetNext ()) {
2973 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (pm->GetStart ());
2975 if (pi.GetListStyle () == eListStyle_None) {
2976 newPI.SetFirstIndent (TWIPS{0});
2977 newPI.SetMargins (TWIPS{0}, pi.GetRightMargin ());
2978 newPI.SetTabStopList (StandardTabStopList ());
2981 const int kTWIPSIncrement = 1440 / 4;
2982 TWIPS marginAt = TWIPS (kTWIPSIncrement * 2 * (pi.GetListIndentLevel () + 1));
2983 newPI.SetFirstIndent (TWIPS (-kTWIPSIncrement));
2984 newPI.SetMargins (marginAt, pi.GetRightMargin ());
2985 StandardTabStopList tabStops;
2986 tabStops.fTabStops.push_back (marginAt);
2987 newPI.SetTabStopList (tabStops);
2989 fParagraphDatabase->SetParagraphInfo (pm->GetStart (), pm->GetLength (), newPI);
2997void WordProcessor::SetSelection (
size_t start,
size_t end)
2999 size_t oldSelStart = 0;
3000 size_t oldSelEnd = 0;
3001 GetSelection (&oldSelStart, &oldSelEnd);
3002 inherited::SetSelection (start, end);
3007 if (oldSelStart != start or oldSelEnd != end) {
3008 vector<WordProcessorTable*> tables;
3009 size_t checkRangeStart1 = start;
3010 size_t checkRangeEnd1 = oldSelStart;
3011 if (checkRangeStart1 < checkRangeEnd1) {
3012 tables = GetTablesInRange (checkRangeStart1, checkRangeEnd1);
3015 size_t checkRangeStart2 = FindPreviousCharacter (oldSelEnd);
3016 size_t checkRangeEnd2 = end;
3017 if (checkRangeStart2 < checkRangeEnd2) {
3018 vector<WordProcessorTable*> tables2 = GetTablesInRange (checkRangeStart2, checkRangeEnd2);
3019 tables.insert (tables.end (), tables2.begin (), tables2.end ());
3021 for (
auto i = tables.begin (); i != tables.end (); ++i) {
3022 WordProcessorTable* t = *i;
3023 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*t, *
const_cast<WordProcessor*
> (
this));
3024 t->SetCellSelection (0, t->GetRowCount (), 0, t->GetColumnCount ());
3028 fCachedCurSelFontSpecValid =
false;
3035bool WordProcessor::GetCaretShownSituation ()
const
3037 if (inherited::GetCaretShownSituation ()) {
3041 WordProcessorTable* table = GetActiveTable ();
3042 if (table !=
nullptr) {
3043 return table->GetCaretShownSituation ();
3052Led_Rect WordProcessor::CalculateCaretRect ()
const
3054 WordProcessorTable* table = GetActiveTable ();
3055 if (table !=
nullptr) {
3056 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*table, *
const_cast<WordProcessor*
> (
this));
3057 return table->CalculateCaretRect ();
3059 return inherited::CalculateCaretRect ();
3067void WordProcessor::OnTypedNormalCharacter (Led_tChar theChar,
bool optionPressed,
bool shiftPressed,
bool commandPressed,
3068 bool controlPressed,
bool altKeyPressed)
3070 WordProcessorTable* table = GetActiveTable ();
3071 if (table !=
nullptr) {
3072 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*table, *
const_cast<WordProcessor*
> (
this));
3073 if (table->OnTypedNormalCharacter (theChar, optionPressed, shiftPressed, commandPressed, controlPressed, altKeyPressed)) {
3079 if (theChar ==
'\t' and not(optionPressed or commandPressed or controlPressed or altKeyPressed)) {
3080 ListStyle ls = eListStyle_None;
3081 if (GetListStyle (GetSelectionStart (), GetSelectionEnd (), &ls) and ls != eListStyle_None) {
3082 InteractiveDoIndentChange (not shiftPressed);
3086 if (theChar ==
'"' and GetSmartQuoteMode () and not(optionPressed or commandPressed or controlPressed or altKeyPressed)) {
3087 const wchar_t kSpecialOpenQuote = 8220;
3088 const wchar_t kSpecialCloseQuote = 8221;
3089 bool isAQuoteToClose =
false;
3090 size_t selStart = GetSelectionStart ();
3093 const size_t kScanBackSize = 1024;
3094 size_t scanBackTo =
static_cast<size_t> (max (0,
static_cast<int> (selStart) -
static_cast<int> (kScanBackSize)));
3096 size_t scanBackCount = selStart - scanBackTo;
3097 CopyOut (scanBackTo, scanBackCount, buf.data ());
3098 for (
size_t i = scanBackCount; i != 0; --i) {
3099 if (buf[i - 1] == kSpecialCloseQuote) {
3103 else if (buf[i - 1] == kSpecialOpenQuote) {
3104 isAQuoteToClose =
true;
3109 wchar_t quoteChar = isAQuoteToClose ? kSpecialCloseQuote : kSpecialOpenQuote;
3110 inherited::OnTypedNormalCharacter (quoteChar, optionPressed, shiftPressed, commandPressed, controlPressed, altKeyPressed);
3113 inherited::OnTypedNormalCharacter (theChar, optionPressed, shiftPressed, commandPressed, controlPressed, altKeyPressed);
3117bool WordProcessor::ProcessSimpleClick (Led_Point clickedAt,
unsigned clickCount,
bool extendSelection,
size_t* dragAnchor)
3120 size_t clickedOnChar = GetCharAtWindowLocation (clickedAt);
3121 Led_Rect charRect = GetCharWindowLocation (clickedOnChar);
3129 Led_Rect tstClickRect = charRect;
3130 const DistanceType kHMargin = 3;
3131 tstClickRect.left += kHMargin;
3132 tstClickRect.right -= kHMargin;
3133 if (tstClickRect.Contains (clickedAt)) {
3134 vector<WordProcessorTable*> tables = GetTablesInRange (clickedOnChar, clickedOnChar + 1);
3135 Assert (tables.size () == 0 or tables.size () == 1);
3136 if (tables.size () == 1) {
3137 WordProcessorTable* t = tables[0];
3138 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*t, *
const_cast<WordProcessor*
> (
this));
3139 if (clickCount == 1) {
3142 *dragAnchor = clickedOnChar;
3144 return t->ProcessSimpleClick (clickedAt - charRect.GetOrigin (), clickCount, extendSelection);
3147 return inherited::ProcessSimpleClick (clickedAt, clickCount, extendSelection, dragAnchor);
3154void WordProcessor::WhileSimpleMouseTracking (Led_Point newMousePos,
size_t dragAnchor)
3156 size_t clickedOnChar = GetCharAtWindowLocation (newMousePos);
3157 size_t oldSelStart = GetSelectionStart ();
3158 size_t oldSelEnd = GetSelectionEnd ();
3165 if ((clickedOnChar == dragAnchor or clickedOnChar + 1 == dragAnchor) and (oldSelEnd - oldSelStart == 1)) {
3166 vector<WordProcessorTable*> tables = GetTablesInRange (clickedOnChar, clickedOnChar + 1);
3167 if (tables.size () == 1) {
3168 WordProcessorTable* t = tables[0];
3169 Led_Rect charRect = GetCharWindowLocation (t->GetStart ());
3170 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*t, *
const_cast<WordProcessor*
> (
this));
3172 t->WhileSimpleMouseTracking (newMousePos - charRect.GetOrigin ());
3176 inherited::WhileSimpleMouseTracking (newMousePos, dragAnchor);
3178 DbgTrace (
"WordProcessor::WhileSimpleMouseTracking (tickCount=%f, newMousePos=(%d,%d), clickedOnChar=%d, dragAnchor=%d)\n",
3179 Time::GetTickCount (), newMousePos.v, newMousePos.h, clickedOnChar, dragAnchor
3189WordProcessorTable* WordProcessor::InsertTable (
size_t at)
3191 WordProcessorTable* t =
new WordProcessorTable (fParagraphDatabase.get (), at);
3192 t->SetDimensions (1, 1);
3203vector<WordProcessorTable*> WordProcessor::GetTablesInRange (
size_t from,
size_t to)
const
3205 if (to ==
static_cast<size_t> (-1)) {
3206 to = GetTextStore ().GetLength ();
3208 Require (from <= to);
3209 Require (to <= GetTextStore ().GetLength () + 1);
3210 MarkersOfATypeMarkerSink2Vector<WordProcessorTable> result;
3211 if (fParagraphDatabase.get () !=
nullptr) {
3212 GetTextStore ().CollectAllMarkersInRangeInto (from, to, fParagraphDatabase.get (), result);
3214 return result.fResult;
3221WordProcessorTable* WordProcessor::GetTableAt (
size_t from)
const
3223 size_t to = from + 1;
3224 Require (to <= GetTextStore ().GetLength () + 1);
3225 MarkerOfATypeMarkerSink<WordProcessorTable> result;
3226 if (fParagraphDatabase.get () !=
nullptr) {
3227 GetTextStore ().CollectAllMarkersInRangeInto (from, to, fParagraphDatabase.get (), result);
3229 return result.fResult;
3232WordProcessor::CommandNames WordProcessor::MakeDefaultCommandNames ()
3234 WordProcessor::CommandNames cmdNames;
3235 cmdNames.fJustificationCommandName = Led_SDK_TCHAROF (
"Justification Change");
3236 cmdNames.fStandardTabStopListCommandName = Led_SDK_TCHAROF (
"Set Tabs");
3237 cmdNames.fMarginsCommandName = Led_SDK_TCHAROF (
"Set Margins");
3238 cmdNames.fFirstIndentCommandName = Led_SDK_TCHAROF (
"Set First Indent");
3239 cmdNames.fMarginsAndFirstIndentCommandName = Led_SDK_TCHAROF (
"Set Margins and First Indent");
3240 cmdNames.fParagraphSpacingCommandName = Led_SDK_TCHAROF (
"Change Paragraph Spacing");
3241 cmdNames.fHideCommandName = Led_SDK_TCHAROF (
"Hide");
3242 cmdNames.fUnHideCommandName = Led_SDK_TCHAROF (
"UnHide");
3243 cmdNames.fSetListStyleCommandName = Led_SDK_TCHAROF (
"Change List Style");
3244 cmdNames.fIndentLevelChangeCommandName = Led_SDK_TCHAROF (
"Change Indent Level");
3245 cmdNames.fInsertTableCommandName = Led_SDK_TCHAROF (
"Insert Table");
3246 cmdNames.fInsertTableRowAboveCommandName = Led_SDK_TCHAROF (
"Insert Table Row Above");
3247 cmdNames.fInsertTableRowBelowCommandName = Led_SDK_TCHAROF (
"Insert Table Row Below");
3248 cmdNames.fInsertTableColBeforeCommandName = Led_SDK_TCHAROF (
"Insert Table Column Before");
3249 cmdNames.fInsertTableColAfterCommandName = Led_SDK_TCHAROF (
"Insert Table Column After");
3250 cmdNames.fInsertURLCommandName = Led_SDK_TCHAROF (
"Insert URL");
3251 cmdNames.fRemoveTableRowsCommandName = Led_SDK_TCHAROF (
"Remove Rows");
3252 cmdNames.fRemoveTableColumnsCommandName = Led_SDK_TCHAROF (
"Remove Columns");
3253 cmdNames.fEmbeddingTypeName_ImageDIB = Led_SDK_TCHAROF (
"image (DIB)");
3254 cmdNames.fEmbeddingTypeName_URL = Led_SDK_TCHAROF (
"URL");
3255 cmdNames.fEmbeddingTypeName_ImageMacPict = Led_SDK_TCHAROF (
"image (MacPICT)");
3256 cmdNames.fEmbeddingTypeName_Table = Led_SDK_TCHAROF (
"table");
3257 cmdNames.fEmbeddingTypeName_Unknown = Led_SDK_TCHAROF (
"unknown");
3258 cmdNames.fFontSizeChange_Other_NoArg = Led_SDK_TCHAROF (
"Other...");
3259 cmdNames.fFontSizeChange_Other_OneArg = Led_SDK_TCHAROF (
"Other (%d)...");
3260 cmdNames.fTablePropertiesCommandName = Led_SDK_TCHAROF (
"Table Properties...")
3261#if qStroika_Foundation_Common_Platform_Windows
3262 Led_SDK_TCHAROF (
"\tAlt+Enter")
3265 cmdNames.fGenericEmbeddingPropertiesCommandName = Led_SDK_TCHAROF (
"Properties")
3266#if qStroika_Foundation_Common_Platform_Windows
3267 Led_SDK_TCHAROF (
"\tAlt+Enter")
3270 cmdNames.fChangeTablePropertiesCommandName = Led_SDK_TCHAROF (
"Change table properties");
3280DistanceType WordProcessor::ComputeMaxHScrollPos ()
const
3282 DistanceType cachedLayoutWidth = 0;
3290 TextInteractor::Tablet_Acquirer tablet_ (
this);
3291 Tablet* tablet = tablet_;
3292 DistanceType width = tablet->CvtFromTWIPSH (CalculateFarthestRightMargin ());
3293 if (GetHScrollPos () != 0) {
3294 width = max (width, GetHScrollPos () + GetWindowRect ().GetWidth ());
3296 cachedLayoutWidth = max (width, DistanceType (1));
3298 DistanceType wWidth = GetWindowRect ().GetWidth ();
3299 if (cachedLayoutWidth > wWidth) {
3300 return (cachedLayoutWidth - wWidth);
3315TWIPS WordProcessor::CalculateFarthestRightMarginInDocument ()
const
3317 CoordinateType longestRowWidth = 0;
3318 RowReference curRow = RowReference{GetFirstPartitionMarker (), 0};
3320 CoordinateType rhsMargin = 0;
3321 GetLayoutMargins (curRow,
nullptr, &rhsMargin);
3322 longestRowWidth = max (longestRowWidth, rhsMargin);
3323 }
while (GetNextRowReference (&curRow));
3324 Tablet_Acquirer tablet_ (
this);
3325 Tablet* tablet = tablet_;
3326 return tablet->CvtToTWIPSH (longestRowWidth);
3334TWIPS WordProcessor::GetFarthestRightMarginInDocument ()
const
3336 AbstractParagraphDatabaseRep* pdbRep = GetParagraphDatabase ().get ();
3338 if (pdbRep->fCachedFarthestRightMarginInDocument == kBadCachedFarthestRightMarginInDocument) {
3339 pdbRep->fCachedFarthestRightMarginInDocument = CalculateFarthestRightMarginInDocument ();
3341 return pdbRep->fCachedFarthestRightMarginInDocument;
3352TWIPS WordProcessor::CalculateFarthestRightMarginInWindow ()
const
3354 CoordinateType longestRowWidth = 0;
3355 size_t rowsLeftInWindow = GetTotalRowsInWindow_ ();
3356 RowReference curRow = GetTopRowReferenceInWindow ();
3358 CoordinateType rhsMargin = 0;
3359 GetLayoutMargins (curRow,
nullptr, &rhsMargin);
3360 longestRowWidth = max (longestRowWidth, rhsMargin);
3361 }
while (rowsLeftInWindow-- > 0 and GetNextRowReference (&curRow));
3362 Tablet_Acquirer tablet_ (
this);
3363 Tablet* tablet = tablet_;
3364 return tablet->CvtToTWIPSH (longestRowWidth);
3373TWIPS WordProcessor::CalculateFarthestRightMargin ()
const
3375 return GetFarthestRightMarginInDocument ();
3378void WordProcessor::InvalidateAllCaches ()
3380 inherited::InvalidateAllCaches ();
3381 shared_ptr<AbstractParagraphDatabaseRep> pdb = GetParagraphDatabase ();
3382 if (pdb.get () !=
nullptr) {
3383 static_cast<AbstractParagraphDatabaseRep*
> (pdb.get ())->fCachedFarthestRightMarginInDocument = kBadCachedFarthestRightMarginInDocument;
3387void WordProcessor::TabletChangedMetrics ()
3389 inherited::TabletChangedMetrics ();
3390 shared_ptr<AbstractParagraphDatabaseRep> pdb = GetParagraphDatabase ();
3391 if (pdb.get () !=
nullptr) {
3392 static_cast<AbstractParagraphDatabaseRep*
> (pdb.get ())->fCachedFarthestRightMarginInDocument = kBadCachedFarthestRightMarginInDocument;
3396void WordProcessor::DidUpdateText (
const UpdateInfo& updateInfo)
noexcept
3398 inherited::DidUpdateText (updateInfo);
3399 fCachedCurSelFontSpecValid =
false;
3402void WordProcessor::AssureCurSelFontCacheValid ()
const
3404 if (not fCachedCurSelFontSpecValid) {
3405 Assert (GetSelectionEnd () >= GetSelectionStart ());
3406 size_t selectionLength = GetSelectionEnd () - GetSelectionStart ();
3407 WordProcessorTable* aT = GetActiveTable ();
3408 if (aT !=
nullptr) {
3409 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, *
const_cast<WordProcessor*
> (
this));
3410 aT->AssureCurSelFontCacheValid (&fCachedCurSelFontSpec);
3411 fCachedCurSelJustification = eLeftJustify;
3412 fCachedCurSelJustificationUnique =
false;
3415 fCachedCurSelFontSpec = GetContinuousStyleInfo (GetSelectionStart (), selectionLength);
3416 fCachedCurSelJustificationUnique = GetJustification (GetSelectionStart (), GetSelectionEnd (), &fCachedCurSelJustification);
3418 fCachedCurSelFontSpecValid =
true;
3422void WordProcessor::DoSingleCharCursorEdit (CursorMovementDirection direction, CursorMovementUnit movementUnit, CursorMovementAction action,
3423 UpdateMode updateMode,
bool scrollToSelection)
3425 WordProcessorTable* table = GetActiveTable ();
3426 if (table !=
nullptr) {
3427 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*table, *
const_cast<WordProcessor*
> (
this));
3428 if (table->DoSingleCharCursorEdit (direction, movementUnit, action, updateMode,
false)) {
3429 if (scrollToSelection) {
3430 ScrollToSelection ();
3435 inherited::DoSingleCharCursorEdit (direction, movementUnit, action, updateMode, scrollToSelection);
3438bool WordProcessor::OnUpdateCommand (CommandUpdater* enabler)
3442 WordProcessorTable* aT = GetActiveTable ();
3443 if (aT !=
nullptr) {
3444 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, *
const_cast<WordProcessor*
> (
this));
3445 if (aT->OnUpdateCommand (enabler)) {
3450 switch (enabler->GetCmdID ()) {
3451 case kFontStylePlain_CmdID: {
3452 OnUpdateFontStylePlainCommand (enabler);
3455 case kFontStyleBold_CmdID: {
3456 OnUpdateFontStyleBoldCommand (enabler);
3459 case kFontStyleItalic_CmdID: {
3460 OnUpdateFontStyleItalicCommand (enabler);
3463 case kFontStyleUnderline_CmdID: {
3464 OnUpdateFontStyleUnderlineCommand (enabler);
3467#if qStroika_Foundation_Common_Platform_Windows
3468 case kFontStyleStrikeout_CmdID: {
3469 OnUpdateFontStyleStrikeoutCommand (enabler);
3473#if qStroika_Foundation_Common_Platform_MacOS
3474 case kFontStyleOutline_CmdID: {
3475 OnUpdateFontStyleOutlineCommand (enabler);
3478 case kFontStyleShadow_CmdID: {
3479 OnUpdateFontStyleShadowCommand (enabler);
3482 case kFontStyleCondensed_CmdID: {
3483 OnUpdateFontStyleCondensedCommand (enabler);
3486 case kFontStyleExtended_CmdID: {
3487 OnUpdateFontStyleExtendedCommand (enabler);
3491 case kSubScriptCommand_CmdID: {
3492 OnUpdateFontStyleSubscriptCommand (enabler);
3495 case kSuperScriptCommand_CmdID: {
3496 OnUpdateFontStyleSuperscriptCommand (enabler);
3499 case kChooseFontCommand_CmdID: {
3500 OnUpdateChooseFontCommand (enabler);
3503 case kInsertTable_CmdID: {
3504 OnUpdateInsertTableCommand (enabler);
3507 case kInsertURL_CmdID: {
3508 OnUpdateInsertURLCommand (enabler);
3511 case kInsertSymbol_CmdID: {
3512 OnUpdateInsertSymbolCommand (enabler);
3515 case kHideSelection_CmdID: {
3516 OnUpdateHideSelectionCommands (enabler);
3519 case kUnHideSelection_CmdID: {
3520 OnUpdateHideSelectionCommands (enabler);
3523 case kParagraphSpacingCommand_CmdID: {
3524 OnUpdateParagraphSpacingChangeCommand (enabler);
3527 case kParagraphIndentsCommand_CmdID: {
3528 OnUpdateParagraphIndentsChangeCommand (enabler);
3531 case kIncreaseIndent_CmdID: {
3532 OnUpdateIndentCommand (enabler);
3535 case kDecreaseIndent_CmdID: {
3536 OnUpdateIndentCommand (enabler);
3541 if (kFontMenuFirst_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kFontMenuLast_CmdID) {
3542 OnUpdateFontNameChangeCommand (enabler);
3545 else if (kBaseFontSize_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastFontSize_CmdID) {
3546 OnUpdateFontSizeChangeCommand (enabler);
3549 else if (kBaseFontColor_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastFontColor_CmdID) {
3550 OnUpdateFontColorChangeCommand (enabler);
3553 else if (kFirstSelectedEmbedding_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastSelectedEmbedding_CmdID) {
3554 OnUpdateSelectedEmbeddingExtendedCommand (enabler);
3557 else if (kFirstJustification_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastJustification_CmdID) {
3558 OnUpdateParagraphJustificationCommand (enabler);
3561 else if (kFirstShowHideGlyph_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastShowHideGlyph_CmdID) {
3562 OnUpdateShowHideGlyphCommand (enabler);
3565 else if (kFirstListStyle_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastListStyle_CmdID) {
3566 OnUpdateListStyleChangeCommand (enabler);
3570 return inherited::OnUpdateCommand (enabler);
3573bool WordProcessor::OnPerformCommand (CommandNumber commandNumber)
3575 WordProcessorTable* aT = GetActiveTable ();
3576 if (aT !=
nullptr) {
3577 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, *
const_cast<WordProcessor*
> (
this));
3578 if (aT->OnPerformCommand (commandNumber)) {
3583 switch (commandNumber) {
3584 case kFontStylePlain_CmdID: {
3585 OnFontStylePlainCommand ();
3588 case kFontStyleBold_CmdID: {
3589 OnFontStyleBoldCommand ();
3592 case kFontStyleItalic_CmdID: {
3593 OnFontStyleItalicCommand ();
3596 case kFontStyleUnderline_CmdID: {
3597 OnFontStyleUnderlineCommand ();
3600#if qStroika_Foundation_Common_Platform_Windows
3601 case kFontStyleStrikeout_CmdID: {
3602 OnFontStyleStrikeoutCommand ();
3606#if qStroika_Foundation_Common_Platform_MacOS
3607 case kFontStyleOutline_CmdID: {
3608 OnFontStyleOutlineCommand ();
3611 case kFontStyleShadow_CmdID: {
3612 OnFontStyleShadowCommand ();
3615 case kFontStyleCondensed_CmdID: {
3616 OnFontStyleCondensedCommand ();
3619 case kFontStyleExtended_CmdID: {
3620 OnFontStyleExtendedCommand ();
3624 case kSubScriptCommand_CmdID: {
3625 OnFontStyleSubscriptCommand ();
3628 case kSuperScriptCommand_CmdID: {
3629 OnFontStyleSuperscriptCommand ();
3632 case kChooseFontCommand_CmdID: {
3633 OnChooseFontCommand ();
3636 case kInsertTable_CmdID: {
3637 OnInsertTableCommand ();
3640 case kInsertURL_CmdID: {
3641 OnInsertURLCommand ();
3644 case kInsertSymbol_CmdID: {
3645 OnInsertSymbolCommand ();
3648 case kHideSelection_CmdID: {
3652 case kUnHideSelection_CmdID: {
3653 OnUnHideSelection ();
3656 case kParagraphSpacingCommand_CmdID: {
3657 OnParagraphSpacingChangeCommand ();
3660 case kParagraphIndentsCommand_CmdID: {
3661 OnParagraphIndentsChangeCommand ();
3664 case kIncreaseIndent_CmdID: {
3665 OnIndentCommand (commandNumber);
3668 case kDecreaseIndent_CmdID: {
3669 OnIndentCommand (commandNumber);
3674 if (kFontMenuFirst_CmdID <= commandNumber and commandNumber <= kFontMenuLast_CmdID) {
3675 OnFontNameChangeCommand (commandNumber);
3678 else if (kBaseFontSize_CmdID <= commandNumber and commandNumber <= kLastFontSize_CmdID) {
3679 OnFontSizeChangeCommand (commandNumber);
3682 else if (kBaseFontColor_CmdID <= commandNumber and commandNumber <= kLastFontColor_CmdID) {
3683 OnFontColorChangeCommand (commandNumber);
3686 else if (kFirstSelectedEmbedding_CmdID <= commandNumber and commandNumber <= kLastSelectedEmbedding_CmdID) {
3687 return OnSelectedEmbeddingExtendedCommand (commandNumber);
3689 else if (kFirstJustification_CmdID <= commandNumber and commandNumber <= kLastJustification_CmdID) {
3690 OnParagraphJustificationCommand (commandNumber);
3693 else if (kFirstShowHideGlyph_CmdID <= commandNumber and commandNumber <= kLastShowHideGlyph_CmdID) {
3694 OnShowHideGlyphCommand (commandNumber);
3697 else if (kFirstListStyle_CmdID <= commandNumber and commandNumber <= kLastListStyle_CmdID) {
3698 OnListStyleChangeCommand (commandNumber);
3702 return inherited::OnPerformCommand (commandNumber);
3705bool WordProcessor::PassAlongCommandToIntraCellModeTableCell (CommandNumber commandNumber)
3707 switch (commandNumber) {
3718 case kSelectAll_CmdID: {
3724 WordProcessorTable* aT = GetActiveTable ();
3727 if (aT !=
nullptr and aT->GetIntraCellMode (&row, &col)) {
3728 size_t intraCellStart = 0;
3729 size_t intraCellEnd = 0;
3730 aT->GetIntraCellSelection (&intraCellStart, &intraCellEnd);
3731 if (intraCellStart != 0) {
3734 size_t cellEnd = aT->GetCell (row, col).GetTextStore ().GetEnd ();
3735 if (intraCellEnd != cellEnd) {
3742 case kParagraphSpacingCommand_CmdID:
3744 case kParagraphIndentsCommand_CmdID:
3746 case kIncreaseIndent_CmdID:
3748 case kDecreaseIndent_CmdID:
3750 case kChooseFontCommand_CmdID:
3752 case kInsertURL_CmdID:
3754 case kHideSelection_CmdID:
3756 case kUnHideSelection_CmdID:
3761 if (kBaseFontSize_CmdID <= commandNumber and commandNumber <= kLastFontSize_CmdID) {
3764 if (kBaseFontColor_CmdID <= commandNumber and commandNumber <= kLastFontColor_CmdID) {
3767 if (kFirstJustification_CmdID <= commandNumber and commandNumber <= kLastJustification_CmdID) {
3770 if (kFirstListStyle_CmdID <= commandNumber and commandNumber <= kLastListStyle_CmdID) {
3773 if (kFontMenuFirst_CmdID <= commandNumber and commandNumber <= kFontMenuLast_CmdID) {
3776 if (kFontStyleCommand_FirstCmdId <= commandNumber and commandNumber <= kFontStyleCommand_LastCmdId) {
3779 if (kFirstSelectedEmbedding_CmdID <= commandNumber and commandNumber <= kLastSelectedEmbedding_CmdID) {
3786bool WordProcessor::PassAlongCommandToEachSelectedTableCell (CommandNumber commandNumber)
3788 switch (commandNumber) {
3794 case kHideSelection_CmdID:
3796 case kUnHideSelection_CmdID:
3801 if (kBaseFontSize_CmdID <= commandNumber and commandNumber <= kLastFontSize_CmdID) {
3804 if (kBaseFontColor_CmdID <= commandNumber and commandNumber <= kLastFontColor_CmdID) {
3807 if (kFirstJustification_CmdID <= commandNumber and commandNumber <= kLastJustification_CmdID) {
3810 if (kFirstListStyle_CmdID <= commandNumber and commandNumber <= kLastListStyle_CmdID) {
3813 if (kFontMenuFirst_CmdID <= commandNumber and commandNumber <= kFontMenuLast_CmdID) {
3816 if (kFontStyleCommand_FirstCmdId <= commandNumber and commandNumber <= kFontStyleCommand_LastCmdId) {
3829void WordProcessor::OnSelectAllCommand ()
3831 inherited::OnSelectAllCommand ();
3832 if (GetLength () == 1) {
3833 (void)OnPerformCommand (kSelectTable_CmdID);
3837void WordProcessor::OnUpdateFontNameChangeCommand (CommandUpdater* enabler)
3840 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3843 enabler->SetChecked (fontSpec.GetFontNameSpecifier_Valid () and
3844 (GetDialogSupport ().CmdNumToFontName (enabler->GetCmdID ()) == fontSpec.GetFontNameSpecifier ()));
3845 enabler->SetEnabled (
true);
3848void WordProcessor::OnFontNameChangeCommand (CommandNumber cmdNum)
3850 IncrementalFontSpecification applyFontSpec;
3851 applyFontSpec.SetFontNameSpecifier (GetDialogSupport ().CmdNumToFontName (cmdNum));
3852 InteractiveSetFont (applyFontSpec);
3855void WordProcessor::OnUpdateFontStylePlainCommand (CommandUpdater* enabler)
3858 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3859 enabler->SetChecked (fontSpec.GetStyle_Plain_Valid () and fontSpec.GetStyle_Plain ());
3860 enabler->SetEnabled (
true);
3863void WordProcessor::OnFontStylePlainCommand ()
3865 IncrementalFontSpecification applyFontSpec;
3866 applyFontSpec.SetStyle_Plain ();
3867 InteractiveSetFont (applyFontSpec);
3870void WordProcessor::OnUpdateFontStyleBoldCommand (CommandUpdater* enabler)
3873 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3874 enabler->SetChecked (fontSpec.GetStyle_Bold_Valid () and fontSpec.GetStyle_Bold ());
3875 enabler->SetEnabled (
true);
3878void WordProcessor::OnFontStyleBoldCommand ()
3880 IncrementalFontSpecification applyFontSpec;
3881 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3882 applyFontSpec.SetStyle_Bold (not(fontSpec.GetStyle_Bold_Valid () and fontSpec.GetStyle_Bold ()));
3883 InteractiveSetFont (applyFontSpec);
3886void WordProcessor::OnUpdateFontStyleItalicCommand (CommandUpdater* enabler)
3889 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3890 enabler->SetChecked (fontSpec.GetStyle_Italic_Valid () and fontSpec.GetStyle_Italic ());
3891 enabler->SetEnabled (
true);
3894void WordProcessor::OnFontStyleItalicCommand ()
3896 IncrementalFontSpecification applyFontSpec;
3897 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3898 applyFontSpec.SetStyle_Italic (not(fontSpec.GetStyle_Italic_Valid () and fontSpec.GetStyle_Italic ()));
3899 InteractiveSetFont (applyFontSpec);
3902void WordProcessor::OnUpdateFontStyleUnderlineCommand (CommandUpdater* enabler)
3905 AssureCurSelFontCacheValid ();
3906 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_Underline_Valid () and fCachedCurSelFontSpec.GetStyle_Underline ());
3907 enabler->SetEnabled (
true);
3910void WordProcessor::OnFontStyleUnderlineCommand ()
3912 AssureCurSelFontCacheValid ();
3913 IncrementalFontSpecification applyFontSpec;
3914 applyFontSpec.SetStyle_Underline (not(fCachedCurSelFontSpec.GetStyle_Underline_Valid () and fCachedCurSelFontSpec.GetStyle_Underline ()));
3915 InteractiveSetFont (applyFontSpec);
3918#if qStroika_Foundation_Common_Platform_MacOS
3919void WordProcessor::OnUpdateFontStyleOutlineCommand (CommandUpdater* enabler)
3922 AssureCurSelFontCacheValid ();
3923 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_Outline_Valid () and fCachedCurSelFontSpec.GetStyle_Outline ());
3924 enabler->SetEnabled (
true);
3927void WordProcessor::OnFontStyleOutlineCommand ()
3929 AssureCurSelFontCacheValid ();
3930 IncrementalFontSpecification applyFontSpec;
3931 applyFontSpec.SetStyle_Outline (not(fCachedCurSelFontSpec.GetStyle_Outline_Valid () and fCachedCurSelFontSpec.GetStyle_Outline ()));
3932 InteractiveSetFont (applyFontSpec);
3935void WordProcessor::OnUpdateFontStyleShadowCommand (CommandUpdater* enabler)
3938 AssureCurSelFontCacheValid ();
3939 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_Shadow_Valid () and fCachedCurSelFontSpec.GetStyle_Shadow ());
3940 enabler->SetEnabled (
true);
3943void WordProcessor::OnFontStyleShadowCommand ()
3945 AssureCurSelFontCacheValid ();
3946 IncrementalFontSpecification applyFontSpec;
3947 applyFontSpec.SetStyle_Shadow (not(fCachedCurSelFontSpec.GetStyle_Shadow_Valid () and fCachedCurSelFontSpec.GetStyle_Shadow ()));
3948 InteractiveSetFont (applyFontSpec);
3951void WordProcessor::OnUpdateFontStyleCondensedCommand (CommandUpdater* enabler)
3954 AssureCurSelFontCacheValid ();
3955 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_Condensed_Valid () and fCachedCurSelFontSpec.GetStyle_Condensed ());
3956 enabler->SetEnabled (
true);
3959void WordProcessor::OnFontStyleCondensedCommand ()
3961 AssureCurSelFontCacheValid ();
3962 IncrementalFontSpecification applyFontSpec;
3963 applyFontSpec.SetStyle_Condensed (not(fCachedCurSelFontSpec.GetStyle_Condensed_Valid () and fCachedCurSelFontSpec.GetStyle_Condensed ()));
3964 InteractiveSetFont (applyFontSpec);
3967void WordProcessor::OnUpdateFontStyleExtendedCommand (CommandUpdater* enabler)
3970 AssureCurSelFontCacheValid ();
3971 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_Extended_Valid () and fCachedCurSelFontSpec.GetStyle_Extended ());
3972 enabler->SetEnabled (
true);
3975void WordProcessor::OnFontStyleExtendedCommand ()
3977 AssureCurSelFontCacheValid ();
3978 IncrementalFontSpecification applyFontSpec;
3979 applyFontSpec.SetStyle_Extended (not(fCachedCurSelFontSpec.GetStyle_Extended_Valid () and fCachedCurSelFontSpec.GetStyle_Extended ()));
3980 InteractiveSetFont (applyFontSpec);
3983#elif qStroika_Foundation_Common_Platform_Windows
3985void WordProcessor::OnUpdateFontStyleStrikeoutCommand (CommandUpdater* enabler)
3988 AssureCurSelFontCacheValid ();
3989 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_Strikeout_Valid () and fCachedCurSelFontSpec.GetStyle_Strikeout ());
3990 enabler->SetEnabled (
true);
3993void WordProcessor::OnFontStyleStrikeoutCommand ()
3995 AssureCurSelFontCacheValid ();
3996 IncrementalFontSpecification applyFontSpec;
3997 applyFontSpec.SetStyle_Strikeout (not(fCachedCurSelFontSpec.GetStyle_Strikeout_Valid () and fCachedCurSelFontSpec.GetStyle_Strikeout ()));
3998 InteractiveSetFont (applyFontSpec);
4003void WordProcessor::OnUpdateFontStyleSubscriptCommand (CommandUpdater* enabler)
4006 AssureCurSelFontCacheValid ();
4007 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_SubOrSuperScript_Valid () and
4008 fCachedCurSelFontSpec.GetStyle_SubOrSuperScript () == FontSpecification::eSubscript);
4009 enabler->SetEnabled (
true);
4012void WordProcessor::OnFontStyleSubscriptCommand ()
4014 AssureCurSelFontCacheValid ();
4015 IncrementalFontSpecification applyFontSpec;
4016 applyFontSpec.SetStyle_SubOrSuperScript ((fCachedCurSelFontSpec.GetStyle_SubOrSuperScript_Valid () and
4017 fCachedCurSelFontSpec.GetStyle_SubOrSuperScript () == FontSpecification::eSubscript)
4018 ? FontSpecification::eNoSubOrSuperscript
4020 InteractiveSetFont (applyFontSpec);
4023void WordProcessor::OnUpdateFontStyleSuperscriptCommand (CommandUpdater* enabler)
4026 AssureCurSelFontCacheValid ();
4027 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_SubOrSuperScript_Valid () and
4028 fCachedCurSelFontSpec.GetStyle_SubOrSuperScript () == FontSpecification::eSuperscript);
4029 enabler->SetEnabled (
true);
4032void WordProcessor::OnFontStyleSuperscriptCommand ()
4034 AssureCurSelFontCacheValid ();
4035 IncrementalFontSpecification applyFontSpec;
4036 applyFontSpec.SetStyle_SubOrSuperScript ((fCachedCurSelFontSpec.GetStyle_SubOrSuperScript_Valid () and
4037 fCachedCurSelFontSpec.GetStyle_SubOrSuperScript () == FontSpecification::eSuperscript)
4038 ? FontSpecification::eNoSubOrSuperscript
4040 InteractiveSetFont (applyFontSpec);
4043void WordProcessor::OnUpdateChooseFontCommand (CommandUpdater* enabler)
4046 enabler->SetEnabled (
true);
4049void WordProcessor::OnChooseFontCommand ()
4051 IncrementalFontSpecification curSelFontSpec = GetCurSelFontSpec ();
4052 if (GetDialogSupport ().ChooseFont (&curSelFontSpec)) {
4053 InteractiveSetFont (curSelFontSpec);
4057void WordProcessor::OnUpdateFontSizeChangeCommand (CommandUpdater* enabler)
4060 DistanceType chosenFontSize = GetDialogSupport ().FontCmdToSize (enabler->GetCmdID ());
4062 AssureCurSelFontCacheValid ();
4063 if (chosenFontSize == 0) {
4064 switch (enabler->GetCmdID ()) {
4065 case kFontSizeSmaller_CmdID:
4066 case kFontSizeLarger_CmdID: {
4067 enabler->SetEnabled (
true);
4070 case kFontSizeOther_CmdID: {
4071 enabler->SetEnabled (
true);
4072 if (fCachedCurSelFontSpec.GetPointSize_Valid ()) {
4073 int pointSize = fCachedCurSelFontSpec.GetPointSize ();
4074 if (not GetDialogSupport ().IsPredefinedFontSize (pointSize)) {
4075 enabler->SetChecked (
true);
4076 enabler->SetText (Characters::CString::Format (GetCommandNames ().fFontSizeChange_Other_OneArg.c_str (), pointSize).c_str ());
4080 enabler->SetChecked (
false);
4081 enabler->SetText (GetCommandNames ().fFontSizeChange_Other_NoArg.c_str ());
4086 enabler->SetChecked (fCachedCurSelFontSpec.GetPointSize_Valid () and fCachedCurSelFontSpec.GetPointSize () == chosenFontSize);
4087 enabler->SetEnabled (
true);
4091void WordProcessor::OnFontSizeChangeCommand (CommandNumber cmdNum)
4093 DistanceType chosenFontSize = GetDialogSupport ().FontCmdToSize (cmdNum);
4094 if (chosenFontSize == 0) {
4096 case kFontSizeSmaller_CmdID: {
4097 IncrementalFontSpecification applyFontSpec;
4098 applyFontSpec.SetPointSizeIncrement (-1);
4099 InteractiveSetFont (applyFontSpec);
4102 case kFontSizeLarger_CmdID: {
4103 IncrementalFontSpecification applyFontSpec;
4104 applyFontSpec.SetPointSizeIncrement (1);
4105 InteractiveSetFont (applyFontSpec);
4108 case kFontSizeOther_CmdID: {
4109 DistanceType oldSize = fCachedCurSelFontSpec.GetPointSize_Valid () ? fCachedCurSelFontSpec.GetPointSize () : 0;
4110 chosenFontSize = GetDialogSupport ().PickOtherFontHeight (oldSize);
4114 if (chosenFontSize != 0) {
4115 IncrementalFontSpecification applyFontSpec;
4116 applyFontSpec.SetPointSize (
static_cast<unsigned short> (chosenFontSize));
4117 InteractiveSetFont (applyFontSpec);
4121void WordProcessor::OnUpdateFontColorChangeCommand (CommandUpdater* enabler)
4124 Require (enabler->GetCmdID () >= kBaseFontColor_CmdID and enabler->GetCmdID () <= kLastFontColor_CmdID);
4125 AssureCurSelFontCacheValid ();
4126 if (fCachedCurSelFontSpec.GetTextColor_Valid ()) {
4127 if (enabler->GetCmdID () == kFontColorOther_CmdID) {
4129 enabler->SetChecked (GetDialogSupport ().FontColorToCmd (fCachedCurSelFontSpec.GetTextColor ()) == kFontColorOther_CmdID);
4132 enabler->SetChecked (fCachedCurSelFontSpec.GetTextColor () == GetDialogSupport ().FontCmdToColor (enabler->GetCmdID ()));
4136 enabler->SetChecked (
false);
4138 enabler->SetEnabled (
true);
4141void WordProcessor::OnFontColorChangeCommand (CommandNumber cmdNum)
4143 Require (cmdNum >= kBaseFontColor_CmdID and cmdNum <= kLastFontColor_CmdID);
4145 AssureCurSelFontCacheValid ();
4146 IncrementalFontSpecification applyFontSpec;
4147 if (cmdNum == kFontColorOther_CmdID) {
4148 Color originalColor = GetDefaultFont ().GetTextColor ();
4149 if (fCachedCurSelFontSpec.GetTextColor_Valid ()) {
4150 originalColor = fCachedCurSelFontSpec.GetTextColor ();
4152 Color chosenColor = originalColor;
4153 if (GetDialogSupport ().PickOtherFontColor (&chosenColor)) {
4154 applyFontSpec.SetTextColor (chosenColor);
4161 Color chosenColor = GetDialogSupport ().FontCmdToColor (cmdNum);
4162 if (fCachedCurSelFontSpec.GetTextColor_Valid () and fCachedCurSelFontSpec.GetTextColor () == chosenColor) {
4163 applyFontSpec.SetTextColor (Color::kBlack);
4166 applyFontSpec.SetTextColor (chosenColor);
4169 InteractiveSetFont (applyFontSpec);
4172void WordProcessor::OnUpdateInsertTableCommand (CommandUpdater* enabler)
4177 enabler->SetEnabled (GetSelectionStart () == GetSelectionEnd ());
4180void WordProcessor::OnInsertTableCommand ()
4184 if (GetDialogSupport ().AddNewTableDialog (&rows, &cols)) {
4187 Assert (rows < 1000);
4188 Assert (cols < 100);
4190 InteractiveModeUpdater iuMode (*
this);
4193 TextStore::SimpleUpdater updater1 (GetTextStore (), GetSelectionStart (), GetSelectionEnd ());
4195 BreakInGroupedCommands ();
4196 UndoableContextHelper context (*
this, GetCommandNames ().fInsertTableCommandName,
false);
4199 WordProcessorTable* t = InsertTable (GetSelectionStart ());
4201 t->SetDimensions (rows, cols);
4203 for (
size_t r = 0; r < rows; ++r) {
4204 for (
size_t c = 0; c < cols; ++c) {
4205 TWIPS targetWidth = TWIPS{0};
4207 CoordinateType lhs = 0;
4208 CoordinateType rhs = 0;
4209 GetLayoutMargins (GetRowReferenceContainingPosition (t->GetStart ()), &lhs, &rhs);
4211 targetWidth = Led_CvtScreenPixelsToTWIPSH (rhs - lhs);
4212 targetWidth = TWIPS ((targetWidth / 5) * 4);
4214 t->SetColumnWidth (r, c, TWIPS (
static_cast<long> (targetWidth / cols)));
4216 TextStore* ts =
nullptr;
4217 t->GetCellWordProcessorDatabases (r, c, &ts);
4221 TextStore::SimpleUpdater updater (GetTextStore (), t->GetStart (), t->GetEnd ());
4222 SetSelection (t->GetEnd (), t->GetEnd ());
4224 context.CommandComplete ();
4225 BreakInGroupedCommands ();
4229void WordProcessor::OnUpdateInsertURLCommand (CommandUpdater* enabler)
4232 enabler->SetEnabled (GetSelectionStart () == GetSelectionEnd ());
4237void WordProcessor::OnInsertURLCommand ()
4239 InteractiveModeUpdater iuMode (*
this);
4240 BreakInGroupedCommands ();
4243 if (GetDialogSupport ().ShowAddURLEmbeddingInfoDialog (&title, &url)) {
4244 UndoableContextHelper context (*
this, GetCommandNames ().fInsertURLCommandName,
false);
4246 SimpleEmbeddedObjectStyleMarker* e =
new StandardURLStyleMarker (Led_URLD (
4247 String::FromSDKString (url).AsNarrowSDKString ().c_str (), String::FromSDKString (title).AsNarrowSDKString ().c_str ()));
4248 AddEmbedding (e, GetTextStore (), GetSelectionStart (), GetStyleDatabase ().get ());
4249 SetSelection (e->GetEnd (), e->GetEnd ());
4251 context.CommandComplete ();
4253 BreakInGroupedCommands ();
4256void WordProcessor::OnUpdateInsertSymbolCommand ([[maybe_unused]] CommandUpdater* enabler)
4259#if qStroika_Foundation_Common_Platform_Windows
4260 enabler->SetEnabled (
true);
4266void WordProcessor::OnInsertSymbolCommand ()
4268#if qStroika_Foundation_Common_Platform_Windows
4269 (void)::ShellExecute (
nullptr, Led_SDK_TCHAROF (
"open"), Led_SDK_TCHAROF (
"CHARMAP.EXE"),
nullptr, Led_SDK_TCHAROF (
""), SW_SHOWNORMAL);
4275void WordProcessor::OnUpdateSelectedEmbeddingExtendedCommand (CommandUpdater* enabler)
4278 SimpleEmbeddedObjectStyleMarker* embedding = GetSoleSelectedEmbedding ();
4279 if (enabler->GetCmdID () == kSelectedEmbeddingProperties_CmdID) {
4280 enabler->SetEnabled (embedding !=
nullptr);
4281 WordProcessorTable* t = GetActiveTable ();
4282 enabler->SetText (t ==
nullptr ? GetCommandNames ().fGenericEmbeddingPropertiesCommandName.c_str ()
4283 : GetCommandNames ().fTablePropertiesCommandName.c_str ());
4286 using PrivateCmdNumber = SimpleEmbeddedObjectStyleMarker::PrivateCmdNumber;
4287 PrivateCmdNumber cmdNum =
4288 static_cast<PrivateCmdNumber
> (enabler->GetCmdID () - kFirstPrivateEmbedding_CmdID + SimpleEmbeddedObjectStyleMarker::eMinPrivateCmdNum);
4289 enabler->SetEnabled (embedding !=
nullptr and embedding->IsCmdEnabled (cmdNum));
4290 if (embedding !=
nullptr) {
4291 enabler->SetText (embedding->GetCmdText (cmdNum).c_str ());
4296bool WordProcessor::OnSelectedEmbeddingExtendedCommand (CommandNumber cmdNum)
4298 Require (cmdNum >= kFirstSelectedEmbedding_CmdID and cmdNum <= kLastSelectedEmbedding_CmdID);
4299 SimpleEmbeddedObjectStyleMarker* embedding = GetSoleSelectedEmbedding ();
4300 if (embedding ==
nullptr) {
4303 if (cmdNum == kSelectedEmbeddingProperties_CmdID) {
4304 if (
dynamic_cast<StandardURLStyleMarker*
> (embedding) !=
nullptr) {
4305 StandardURLStyleMarker* e =
dynamic_cast<StandardURLStyleMarker*
> (embedding);
4306 SDKString title = String::FromNarrowSDKString (e->GetURLData ().GetTitle ()).AsSDKString ();
4307 SDKString url = String::FromNarrowSDKString (e->GetURLData ().GetURL ()).AsSDKString ();
4308 if (GetDialogSupport ().ShowURLEmbeddingInfoDialog (GetPrettyTypeName (embedding), &title, &url)) {
4311 TextStore::SimpleUpdater updater (GetTextStore (), e->GetStart (), e->GetEnd ());
4312 e->SetURLData (Led_URLD{String::FromSDKString (url).AsNarrowSDKString ().c_str (),
4313 String::FromSDKString (title).AsNarrowSDKString ().c_str ()});
4317 else if (
dynamic_cast<WordProcessorTable*
> (embedding) !=
nullptr) {
4318 OnEditTablePropertiesDialog ();
4322 GetDialogSupport ().ShowSimpleEmbeddingInfoDialog (GetPrettyTypeName (embedding));
4326 using PrivateCmdNumber = SimpleEmbeddedObjectStyleMarker::PrivateCmdNumber;
4327 PrivateCmdNumber pCmdNum =
4328 static_cast<PrivateCmdNumber
> (cmdNum - kFirstPrivateEmbedding_CmdID + SimpleEmbeddedObjectStyleMarker::eMinPrivateCmdNum);
4329 embedding->DoCommand (pCmdNum);
4334void WordProcessor::OnEditTablePropertiesDialog ()
4336 WordProcessorTable* t = GetActiveTable ();
4343 DialogSupport::TableSelectionPropertiesInfo info;
4344 info.fTableBorderWidth = t->GetTableBorderWidth ();
4345 info.fTableBorderColor = t->GetTableBorderColor ();
4346 t->GetDefaultCellMargins (&info.fDefaultCellMargins.top, &info.fDefaultCellMargins.left, &info.fDefaultCellMargins.bottom,
4347 &info.fDefaultCellMargins.right);
4348 info.fCellSpacing = t->GetCellSpacing ();
4350 size_t rowSelStart = 0;
4351 size_t rowSelEnd = 0;
4352 size_t colSelStart = 0;
4353 size_t colSelEnd = 0;
4354 t->GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
4355 info.fCellWidth_Common =
false;
4356 info.fCellBackgroundColor_Common =
false;
4357 for (
size_t r = rowSelStart; r < rowSelEnd; ++r) {
4358 for (
size_t c = colSelStart; c < colSelEnd; ++c) {
4359 if (c < t->GetColumnCount (r)) {
4360 TWIPS cellWidth = t->GetColumnWidth (r, c);
4361 Color cellBkgrnd = t->GetCellColor (r, c);
4362 if (r == rowSelStart and c == colSelStart) {
4363 info.fCellWidth_Common =
true;
4364 info.fCellWidth = cellWidth;
4365 info.fCellBackgroundColor_Common =
true;
4366 info.fCellBackgroundColor = cellBkgrnd;
4369 if (info.fCellWidth_Common) {
4370 if (info.fCellWidth != cellWidth) {
4371 info.fCellWidth_Common =
false;
4374 if (info.fCellBackgroundColor_Common) {
4375 if (info.fCellBackgroundColor != cellBkgrnd) {
4376 info.fCellBackgroundColor_Common =
false;
4384 if (GetDialogSupport ().EditTablePropertiesDialog (&info)) {
4385 UndoableContextHelper context (*
this, GetCommandNames ().fChangeTablePropertiesCommandName,
false);
4387 t->SetTableBorderWidth (info.fTableBorderWidth);
4388 t->SetTableBorderColor (info.fTableBorderColor);
4389 t->SetDefaultCellMargins (info.fDefaultCellMargins.top, info.fDefaultCellMargins.left, info.fDefaultCellMargins.bottom,
4390 info.fDefaultCellMargins.right);
4391 t->SetCellSpacing (info.fCellSpacing);
4393 size_t rowSelStart = 0;
4394 size_t rowSelEnd = 0;
4395 size_t colSelStart = 0;
4396 size_t colSelEnd = 0;
4397 t->GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
4398 for (
size_t r = rowSelStart; r < rowSelEnd; ++r) {
4399 for (
size_t c = colSelStart; c < colSelEnd; ++c) {
4400 if (c < t->GetColumnCount (r)) {
4401 if (info.fCellWidth_Common) {
4402 t->SetColumnWidth (r, c, info.fCellWidth);
4404 if (info.fCellBackgroundColor_Common) {
4405 t->SetCellColor (r, c, info.fCellBackgroundColor);
4412 context.CommandComplete ();
4416void WordProcessor::OnUpdateHideSelectionCommands (CommandUpdater* enabler)
4419 bool enabled = GetSelectionStart () != GetSelectionEnd ();
4422 if (enabler->GetCmdID () == kHideSelection_CmdID) {
4423 enabled = not GetHidableTextDatabase ()->GetHidableRegionsContiguous (GetSelectionStart (), GetSelectionEnd (),
true);
4425 else if (enabler->GetCmdID () == kUnHideSelection_CmdID) {
4426 enabled = not GetHidableTextDatabase ()->GetHidableRegionsContiguous (GetSelectionStart (), GetSelectionEnd (),
false);
4429 enabler->SetEnabled (enabled);
4432void WordProcessor::OnHideSelection ()
4434 InterectiveSetRegionHidable (
true);
4437void WordProcessor::OnUnHideSelection ()
4439 InterectiveSetRegionHidable (
false);
4442void WordProcessor::OnUpdateParagraphJustificationCommand (CommandUpdater* enabler)
4446 AssureCurSelFontCacheValid ();
4448 switch (enabler->GetCmdID ()) {
4449 case kJustifyLeft_CmdID: {
4450 enabler->SetChecked (fCachedCurSelJustificationUnique and (fCachedCurSelJustification == eLeftJustify));
4452 case kJustifyCenter_CmdID: {
4453 enabler->SetChecked (fCachedCurSelJustificationUnique and (fCachedCurSelJustification == eCenterJustify));
4455 case kJustifyRight_CmdID: {
4456 enabler->SetChecked (fCachedCurSelJustificationUnique and (fCachedCurSelJustification == eRightJustify));
4458 case kJustifyFull_CmdID: {
4459 enabler->SetChecked (fCachedCurSelJustificationUnique and (fCachedCurSelJustification == eFullyJustify));
4462 enabler->SetEnabled (
true);
4465void WordProcessor::OnParagraphJustificationCommand (CommandNumber cmdNum)
4468 case kJustifyLeft_CmdID: {
4469 InteractiveSetJustification (eLeftJustify);
4471 case kJustifyCenter_CmdID: {
4472 InteractiveSetJustification (eCenterJustify);
4474 case kJustifyRight_CmdID: {
4475 InteractiveSetJustification (eRightJustify);
4477 case kJustifyFull_CmdID: {
4478 InteractiveSetJustification (eFullyJustify);
4486void WordProcessor::OnUpdateParagraphSpacingChangeCommand (CommandUpdater* enabler)
4489 enabler->SetEnabled (
true);
4492void WordProcessor::OnParagraphSpacingChangeCommand ()
4494 TWIPS spaceBefore = TWIPS{0};
4495 TWIPS spaceAfter = TWIPS{0};
4496 LineSpacing lineSpacing;
4498 bool spaceBeforeValid = GetSpaceBefore (GetSelectionStart (), GetSelectionEnd (), &spaceBefore);
4499 bool spaceAfterValid = GetSpaceAfter (GetSelectionStart (), GetSelectionEnd (), &spaceAfter);
4500 bool lineSpacingValid = GetLineSpacing (GetSelectionStart (), GetSelectionEnd (), &lineSpacing);
4502 if (GetDialogSupport ().PickNewParagraphLineSpacing (&spaceBefore, &spaceBeforeValid, &spaceAfter, &spaceAfterValid, &lineSpacing, &lineSpacingValid)) {
4503 if (spaceBeforeValid) {
4505 InteractiveSetParagraphSpacing (spaceBefore, spaceBeforeValid, spaceAfter, spaceAfterValid, lineSpacing, lineSpacingValid);
4509void WordProcessor::OnUpdateParagraphIndentsChangeCommand (CommandUpdater* enabler)
4512 enabler->SetEnabled (
true);
4515void WordProcessor::OnParagraphIndentsChangeCommand ()
4517 TWIPS leftMargin = TWIPS{0};
4518 TWIPS rightMargin = TWIPS{0};
4519 TWIPS firstIndent = TWIPS{0};
4522 bool leftMarginValid = GetMargins (GetSelectionStart (), GetSelectionEnd (), &leftMargin, &rightMargin);
4523 bool rightMarginValid = leftMarginValid;
4524 bool firstIndentValid = GetFirstIndent (GetSelectionStart (), GetSelectionEnd (), &firstIndent);
4526 if (GetDialogSupport ().PickNewParagraphMarginsAndFirstIndent (&leftMargin, &leftMarginValid, &rightMargin, &rightMarginValid,
4527 &firstIndent, &firstIndentValid)) {
4531 InteractiveSetMarginsAndFirstIndent (leftMargin, rightMargin, firstIndent);
4535void WordProcessor::OnUpdateListStyleChangeCommand (CommandUpdater* enabler)
4538 ListStyle listStyle = eListStyle_None;
4539 bool listStyleValid = GetListStyle (GetSelectionStart (), GetSelectionEnd (), &listStyle);
4540 if (enabler->GetCmdID () == kListStyle_None_CmdID) {
4541 enabler->SetChecked (listStyleValid and listStyle == eListStyle_None);
4543 else if (enabler->GetCmdID () == kListStyle_Bullet_CmdID) {
4544 enabler->SetChecked (listStyleValid and listStyle == eListStyle_Bullet);
4549 enabler->SetEnabled (
true);
4552void WordProcessor::OnListStyleChangeCommand (CommandNumber cmdNum)
4554 if (cmdNum == kListStyle_None_CmdID) {
4555 InteractiveSetListStyle (eListStyle_None);
4557 else if (cmdNum == kListStyle_Bullet_CmdID) {
4558 InteractiveSetListStyle (eListStyle_Bullet);
4565void WordProcessor::OnUpdateIndentCommand (CommandUpdater* enabler)
4568 ListStyle listStyle = eListStyle_None;
4569 bool listStyleValid = GetListStyle (GetSelectionStart (), GetSelectionEnd (), &listStyle);
4570 if (enabler->GetCmdID () == kIncreaseIndent_CmdID) {
4571 enabler->SetEnabled (listStyleValid and listStyle != eListStyle_None);
4573 else if (enabler->GetCmdID () == kDecreaseIndent_CmdID) {
4574 enabler->SetEnabled (listStyleValid and listStyle != eListStyle_None);
4581void WordProcessor::OnIndentCommand (CommandNumber cmdNum)
4583 if (cmdNum == kIncreaseIndent_CmdID) {
4584 InteractiveDoIndentChange (
true);
4586 else if (cmdNum == kDecreaseIndent_CmdID) {
4587 InteractiveDoIndentChange (
false);
4594void WordProcessor::OnUpdateShowHideGlyphCommand (CommandUpdater* enabler)
4597 Require (enabler->GetCmdID () >= kFirstShowHideGlyph_CmdID);
4598 Require (enabler->GetCmdID () <= kLastShowHideGlyph_CmdID);
4601 if (enabler->GetCmdID () == kShowHideParagraphGlyphs_CmdID) {
4602 enabler->SetChecked (GetShowParagraphGlyphs ());
4604 else if (enabler->GetCmdID () == kShowHideTabGlyphs_CmdID) {
4605 enabler->SetChecked (GetShowTabGlyphs ());
4607 else if (enabler->GetCmdID () == kShowHideSpaceGlyphs_CmdID) {
4608 enabler->SetChecked (GetShowSpaceGlyphs ());
4613 enabler->SetEnabled (
true);
4616void WordProcessor::OnShowHideGlyphCommand (CommandNumber cmdNum)
4618 Require (cmdNum >= kFirstShowHideGlyph_CmdID);
4619 Require (cmdNum <= kLastShowHideGlyph_CmdID);
4622 if (cmdNum == kShowHideParagraphGlyphs_CmdID) {
4623 SetShowParagraphGlyphs (not GetShowParagraphGlyphs ());
4625 else if (cmdNum == kShowHideTabGlyphs_CmdID) {
4626 SetShowTabGlyphs (not GetShowTabGlyphs ());
4628 else if (cmdNum == kShowHideSpaceGlyphs_CmdID) {
4629 SetShowSpaceGlyphs (not GetShowSpaceGlyphs ());
4636SDKString WordProcessor::GetPrettyTypeName (SimpleEmbeddedObjectStyleMarker* m)
4638 if (
dynamic_cast<StandardDIBStyleMarker*
> (m) !=
nullptr) {
4639 return GetCommandNames ().fEmbeddingTypeName_ImageDIB;
4641 else if (
dynamic_cast<StandardURLStyleMarker*
> (m) !=
nullptr) {
4642 return GetCommandNames ().fEmbeddingTypeName_URL;
4644#if qStroika_Foundation_Common_Platform_MacOS || qStroika_Foundation_Common_Platform_Windows
4645 else if (
dynamic_cast<StandardMacPictureStyleMarker*
> (m) !=
nullptr) {
4646 return GetCommandNames ().fEmbeddingTypeName_ImageMacPict;
4649 else if (
dynamic_cast<WordProcessorTable*
> (m) !=
nullptr) {
4650 return GetCommandNames ().fEmbeddingTypeName_Table;
4653 return GetCommandNames ().fEmbeddingTypeName_Unknown;
4657SimpleEmbeddedObjectStyleMarker* WordProcessor::GetSoleSelectedEmbedding ()
const
4659 size_t selStart = GetSelectionStart ();
4660 size_t selEnd = GetSelectionEnd ();
4661 Require (selStart <= selEnd);
4662 if (selEnd - selStart == 1) {
4663 vector<SimpleEmbeddedObjectStyleMarker*> embeddings = CollectAllEmbeddingMarkersInRange (selStart, selEnd);
4664 if (embeddings.size () == 1) {
4665 return (
dynamic_cast<SimpleEmbeddedObjectStyleMarker*
> (embeddings[0]));
4682Led_tString WordProcessor::GetListLeader (
size_t paragraphMarkerPos)
const
4684 if (fParagraphDatabase.get () ==
nullptr) {
4685 throw NoParagraphDatabaseAvailable ();
4687 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (paragraphMarkerPos);
4688 if (pi.GetListStyle () == eListStyle_None) {
4689 return Led_tString{};
4692 const Led_tChar kBulletChar = 0x2022;
4695 return Led_tString{&kBulletChar, 1} + LED_TCHAR_OF (
"\t");
4704DistanceType WordProcessor::GetListLeaderLength (
size_t paragraphMarkerPos)
const
4706 if (fParagraphDatabase.get () ==
nullptr) {
4707 throw NoParagraphDatabaseAvailable ();
4710 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (paragraphMarkerPos);
4711 TWIPS lhsTWIPS = pi.GetLeftMargin ();
4712 lhsTWIPS += pi.GetFirstIndent ();
4714 Tablet_Acquirer tablet_ (
this);
4715 Tablet* tablet = tablet_;
4716 CoordinateType lhs = tablet->CvtFromTWIPSH (lhsTWIPS);
4717 Led_tString leader = GetListLeader (paragraphMarkerPos);
4719 size_t len = leader.length ();
4727 useBulletFont.SetPointSize (max (
static_cast<unsigned short> (14), nextCharsFontStyle.GetPointSize ()));
4728 MeasureSegmentWidth_ (useBulletFont, paragraphMarkerPos, paragraphMarkerPos + len, leader.c_str (), distanceResults.data ());
4729 (void)ResetTabStopsWithMargin (lhs, paragraphMarkerPos, leader.c_str (), len, distanceResults.data (), 0);
4730 DistanceType result = distanceResults[len - 1];
4735InteractiveReplaceCommand::SavedTextRep* WordProcessor::InteractiveUndoHelperMakeTextRep (
size_t regionStart,
size_t regionEnd,
size_t selStart,
size_t selEnd)
4737 using SavedTextRep = InteractiveReplaceCommand::SavedTextRep;
4738 if (regionStart == regionEnd) {
4739 return new EmptySelectionParagraphSavedTextRep (
this, selStart, selEnd, regionStart);
4742 SavedTextRep* basicRep = inherited::InteractiveUndoHelperMakeTextRep (regionStart, regionEnd, selStart, selEnd);
4743 WordProcessorTable* aT = GetActiveTable ();
4744 if (aT !=
nullptr) {
4745 return new WordProcessorTable::SavedTextRepWSel (basicRep, *aT, WordProcessorTable::SavedTextRepWSel::eWPAbove);
4755void WordProcessor::InteractiveSetFont (
const IncrementalFontSpecification& defaultFont)
4757 WordProcessorTable* aT = GetActiveTable ();
4758 if (aT !=
nullptr) {
4759 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, *
this);
4760 aT->InteractiveSetFont (defaultFont);
4763 inherited::InteractiveSetFont (defaultFont);
4770void WordProcessor::InteractiveSetJustification (Justification justification)
4772 Justification oldJustification;
4773 if (not GetJustification (GetSelectionStart (), GetSelectionEnd (), &oldJustification) or (oldJustification != justification)) {
4774 InteractiveWPHelper1<DoIt_SetJustification> (
this, justification);
4782void WordProcessor::InteractiveSetStandardTabStopList (StandardTabStopList tabStops)
4784 StandardTabStopList oldTabs;
4785 if (not GetStandardTabStopList (GetSelectionStart (), GetSelectionEnd (), &oldTabs) or (oldTabs != tabStops)) {
4786 InteractiveWPHelper1<DoIt_SetStandardTabStopList> (
this, tabStops);
4794void WordProcessor::InteractiveSetMargins (TWIPS leftMargin, TWIPS rightMargin)
4796 TWIPS oldLeftMargin = TWIPS{0};
4797 TWIPS oldRightMargin = TWIPS{0};
4798 if (not GetMargins (GetSelectionStart (), GetSelectionEnd (), &oldLeftMargin, &oldRightMargin) or
4799 ((oldLeftMargin != leftMargin) or (oldRightMargin != rightMargin))) {
4800 InteractiveWPHelper1<DoIt_SetMargins> (
this, DoIt_SetMargins::Margins (leftMargin, rightMargin));
4808void WordProcessor::InteractiveSetFirstIndent (TWIPS firstIndent)
4810 TWIPS oldFirstIndent = TWIPS{0};
4811 if (not GetFirstIndent (GetSelectionStart (), GetSelectionEnd (), &oldFirstIndent) or (oldFirstIndent != firstIndent)) {
4812 InteractiveWPHelper1<DoIt_SetFirstIndent> (
this, firstIndent);
4821void WordProcessor::InteractiveSetMarginsAndFirstIndent (TWIPS leftMargin, TWIPS rightMargin, TWIPS firstIndent)
4823 TWIPS oldLeftMargin = TWIPS{0};
4824 TWIPS oldRightMargin = TWIPS{0};
4825 TWIPS oldFirstIndent = TWIPS{0};
4826 if (not GetMargins (GetSelectionStart (), GetSelectionEnd (), &oldLeftMargin, &oldRightMargin) or
4827 ((oldLeftMargin != leftMargin) or (oldRightMargin != rightMargin)) or
4828 not GetFirstIndent (GetSelectionStart (), GetSelectionEnd (), &oldFirstIndent) or (oldFirstIndent != firstIndent)) {
4829 InteractiveWPHelper1<DoIt_SetMarginsAndFirstIndent> (
4830 this, DoIt_SetMarginsAndFirstIndent::MarginsAndFirstIndent (leftMargin, rightMargin, firstIndent));
4838void WordProcessor::InteractiveSetParagraphSpacing (TWIPS spaceBefore,
bool spaceBeforeValid, TWIPS spaceAfter,
bool spaceAfterValid,
4839 LineSpacing lineSpacing,
bool lineSpacingValid)
4844 TWIPS oldSpaceBefore = TWIPS{0};
4845 TWIPS oldSpaceAfter = TWIPS{0};
4846 LineSpacing oldLineSpacing;
4847 if (not GetSpaceBefore (GetSelectionStart (), GetSelectionEnd (), &oldSpaceBefore) or (oldSpaceBefore != spaceBefore) or
4848 not GetSpaceAfter (GetSelectionStart (), GetSelectionEnd (), &oldSpaceAfter) or (oldSpaceAfter != spaceAfter) or
4849 not GetLineSpacing (GetSelectionStart (), GetSelectionEnd (), &oldLineSpacing) or (oldLineSpacing != lineSpacing)) {
4850 InteractiveWPHelper1<DoIt_SetParagraphSpacing> (
4851 this, DoIt_SetParagraphSpacing::AllSpacingArgs (spaceBefore, spaceBeforeValid, spaceAfter, spaceAfterValid, lineSpacing, lineSpacingValid));
4859void WordProcessor::InteractiveSetListStyle (ListStyle listStyle)
4864 ListStyle oldListStyle = eListStyle_None;
4865 if (not GetListStyle (GetSelectionStart (), GetSelectionEnd (), &oldListStyle) or oldListStyle != listStyle) {
4866 InteractiveWPHelper1<DoIt_SetListStyle> (
this, listStyle);
4874void WordProcessor::InteractiveDoIndentChange (
bool increase)
4876 InteractiveWPHelper1<DoIt_IndentUnIndentList> (
this, increase);
4883const TabStopList& WordProcessor::GetTabStopList (
size_t containingPos)
const
4885 return fParagraphDatabase->GetParagraphInfo (containingPos).GetTabStopList ();
4888void WordProcessor::DrawBefore (
const Led_Rect& subsetToDraw,
bool printing)
4890 size_t winStart = GetMarkerPositionOfStartOfWindow ();
4891 size_t winEnd = GetMarkerPositionOfEndOfWindow ();
4895 vector<WordProcessorTable*> tables = GetTablesInRange (winStart, winEnd);
4896 for (
auto i = tables.begin (); i != tables.end (); ++i) {
4897 WordProcessorTable* t = *i;
4898 if (t->fNeedLayout != WordProcessorTable::eDone) {
4899 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*t, *
this);
4900 t->PerformLayout ();
4903 inherited::DrawBefore (subsetToDraw, printing);
4910void WordProcessor::DrawRowSegments (Tablet* tablet,
const Led_Rect& currentRowRect,
const Led_Rect& invalidRowRect,
4911 const TextLayoutBlock& text,
size_t rowStart,
size_t rowEnd)
4913 if (fParagraphDatabase.get () ==
nullptr) {
4914 throw NoParagraphDatabaseAvailable ();
4916 RowReference row = GetRowReferenceContainingPosition (rowStart);
4917 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (rowStart);
4919 Led_Rect adjustedDrawInto = currentRowRect;
4921 CoordinateType lhsMargin = 0;
4922 GetLayoutMargins (row, &lhsMargin,
nullptr);
4923 adjustedDrawInto += Led_Point (0, lhsMargin);
4927 if (row.GetSubRow () == 0) {
4928 ListStyle ls = pi.GetListStyle ();
4929 if (ls != eListStyle_None) {
4933 bool allowLists =
true;
4934 if (rowEnd - rowStart == 1) {
4935 vector<WordProcessorTable*> tables = GetTablesInRange (rowStart, rowEnd);
4936 if (tables.size () == 1) {
4942 Led_Rect xxx = adjustedDrawInto;
4943 Led_tString listLeader = GetListLeader (rowStart);
4944 xxx.SetLeft (xxx.GetLeft () - GetListLeaderLength (rowStart));
4947 useBulletFont.SetPointSize (max (
static_cast<unsigned short> (14), nextCharsFontStyle.GetPointSize ()));
4948 CoordinateType baseLine = xxx.GetTop () + MeasureSegmentBaseLine (rowStart, rowStart);
4949 DrawSegment_ (tablet, useBulletFont, rowStart, rowStart + listLeader.length (),
4950 TextLayoutBlock_Basic (listLeader.c_str (), listLeader.c_str () + listLeader.length ()), xxx, baseLine,
nullptr);
4956 switch (pi.GetJustification ()) {
4957 case eCenterJustify: {
4958 adjustedDrawInto.SetLeft (adjustedDrawInto.GetLeft () + CalcSpaceToEat (rowStart) / 2);
4960 case eRightJustify: {
4961 adjustedDrawInto.SetLeft (adjustedDrawInto.GetLeft () + CalcSpaceToEat (rowStart));
4964 if (not adjustedDrawInto.IsEmpty ()) {
4965 inherited::DrawRowSegments (tablet, adjustedDrawInto, invalidRowRect, text, rowStart, rowEnd);
4966 if (GetShowParagraphGlyphs ()) {
4968 PartitionElementCacheInfo pmCacheInfo = GetPartitionElementCacheInfo (GetPartitionMarkerContainingPosition (rowStart));
4969 if (row.GetSubRow () + 1 == pmCacheInfo.GetRowCount () and rowEnd < GetEnd ()) {
4970 const Led_tChar newline =
'\n';
4973 useFont.SetPointSize (max (
static_cast<unsigned short> (14), nextCharsFontStyle.GetPointSize ()));
4974 useFont.SetTextColor (Color::kGray);
4975 Led_Rect yyy = adjustedDrawInto;
4976 DistanceType segmentWidth = CalcSegmentSize (rowStart, rowEnd);
4977 yyy.left += segmentWidth;
4978 CoordinateType baseLine = yyy.GetTop () + MeasureSegmentBaseLine (rowStart, rowStart);
4979 DrawSegment_ (tablet, useFont, rowEnd, rowEnd + 1, TextLayoutBlock_Basic (&newline, &newline + 1), yyy, baseLine,
nullptr);
4989vector<Led_Rect> WordProcessor::GetRowHilightRects (
const TextLayoutBlock& text,
size_t rowStart,
size_t rowEnd,
size_t hilightStart,
size_t hilightEnd)
const
4991 size_t len = rowEnd - rowStart;
4992 if (len == 1 and text.PeekAtRealText ()[0] == kEmbeddingSentinelChar) {
4993 vector<WordProcessorTable*> tables = GetTablesInRange (rowStart, rowEnd);
4994 Assert (tables.size () <= 1);
4995 if (not tables.empty ()) {
4996 WordProcessorTable* table = tables[0];
4997 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*table, *
const_cast<WordProcessor*
> (
this));
4998 return table->GetRowHilightRects ();
5001 return inherited::GetRowHilightRects (text, rowStart, rowEnd, hilightStart, hilightEnd);
5004void WordProcessor::DrawSegment (Tablet* tablet,
size_t from,
size_t to,
const TextLayoutBlock& text,
const Led_Rect& drawInto,
5005 const Led_Rect& invalidRect, CoordinateType useBaseLine, DistanceType* pixelsDrawn)
5007 DistanceType pixelsDrawn_;
5008 if (GetShowTabGlyphs ()) {
5009 if (pixelsDrawn ==
nullptr) {
5011 pixelsDrawn = &pixelsDrawn_;
5015 inherited::DrawSegment (tablet, from, to, text, drawInto, invalidRect, useBaseLine, pixelsDrawn);
5018 if (GetShowTabGlyphs () and GetJustification (from) == eLeftJustify) {
5019 for (
size_t i = from; i < to; ++i) {
5020 if (text.PeekAtVirtualText ()[i - from] ==
'\t') {
5022 DistanceType beforeTabPos = drawInto.GetLeft () + CalcSegmentSize (from, i);
5024 DistanceType afterTabPos = drawInto.GetLeft () + CalcSegmentSize (from, i + 1);
5025 Assert (beforeTabPos < afterTabPos);
5026 Led_Rect tabRect = drawInto;
5027 tabRect.SetLeft (beforeTabPos);
5028 tabRect.SetRight (afterTabPos);
5029 Assert (tabRect.GetLeft () < tabRect.GetRight ());
5032 Color arrowColor = GetEffectiveDefaultTextColor (eDefaultTextColor);
5034 Led_Rect arrowBody = tabRect;
5035 arrowBody.left += 2;
5036 arrowBody.right -= 2;
5037 arrowBody.top += arrowBody.GetHeight () / 2;
5038 arrowBody.bottom = arrowBody.top + 1;
5039 arrowBody.bottom = min (arrowBody.bottom, drawInto.bottom);
5040 tablet->EraseBackground_SolidHelper (arrowBody, arrowColor);
5043 const CoordinateType kArrowHSize = 8;
5044 const CoordinateType kArrowVSize = 8;
5045 Led_Point tip = arrowBody.GetTopRight ();
5046 CoordinateType hTriangleBase = max (arrowBody.right - kArrowHSize, arrowBody.left);
5047 Led_Point topPt = Led_Point (max (arrowBody.GetTop () - kArrowVSize / 2, tabRect.top), hTriangleBase);
5048 Led_Point botPt = Led_Point (min (arrowBody.GetTop () + kArrowVSize / 2, tabRect.bottom), hTriangleBase);
5049#if qStroika_Foundation_Common_Platform_Windows
5050 Brush backgroundBrush (arrowColor.GetOSRep ());
5051 GDI_Obj_Selector pen (tablet, ::GetStockObject (NULL_PEN));
5052 GDI_Obj_Selector brush (tablet, backgroundBrush);
5054 pts[0] = AsPOINT (tip);
5055 pts[1] = AsPOINT (topPt);
5056 pts[2] = AsPOINT (botPt);
5057 Verify (::Polygon (*tablet, pts,
static_cast<int> (Memory::NEltsOf (pts))));
5058#elif qStroika_Foundation_Common_Platform_MacOS
5059 PolyHandle ph = ::OpenPoly ();
5060 ::MoveTo (tip.h, tip.v);
5061 ::LineTo (topPt.h, topPt.v);
5062 ::LineTo (botPt.h, botPt.v);
5063 ::LineTo (tip.h, tip.v);
5065 if (ph !=
nullptr) {
5066 Assert (*tablet == Led_GetCurrentGDIPort ());
5067 GDI_RGBForeColor (arrowColor.GetOSRep ());
5068 ::FillPoly (ph, &Pen::kBlackPattern);
5077 tablet->EraseBackground_SolidHelper (tabRect, Color::kRed);
5084DistanceType WordProcessor::MeasureSegmentHeight (
size_t from,
size_t to)
const
5086 Tablet_Acquirer tablet_ (
this);
5087 Tablet* tablet = tablet_;
5088 DistanceType d = inherited::MeasureSegmentHeight (from, to);
5091 shared_ptr<HidableTextMarkerOwner> hdb = GetHidableTextDatabase ();
5092 if (hdb.get () !=
nullptr) {
5093 DiscontiguousRun<bool> regions = hdb->GetHidableRegions (from, to);
5094 if (not regions.empty ()) {
5095 if (not regions[0].fData) {
5102 PartitionMarker* pm = GetPartitionMarkerContainingPosition (from);
5103 size_t pmStart = pm->GetStart ();
5104 size_t pmEnd = pm->GetEnd ();
5110 if (pmEnd - pmStart == 1) {
5111 vector<WordProcessorTable*> tables = GetTablesInRange (pmStart, pmEnd);
5112 if (tables.size () == 1) {
5114 WordProcessorTable* t = tables[0];
5115 Assert (t->GetStart () == pmStart);
5116 Assert (t->GetEnd () == pmEnd);
5122 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (from);
5124 LineSpacing sl = pi.GetLineSpacing ();
5126 case LineSpacing::eOnePointFiveSpace:
5130 case LineSpacing::eDoubleSpace:
5133 case LineSpacing::eAtLeastTWIPSSpacing:
5134 d = max (DistanceType (tablet->CvtFromTWIPSV (TWIPS (sl.fArg))), d);
5136 case LineSpacing::eExactTWIPSSpacing:
5137 d = tablet->CvtFromTWIPSV (TWIPS (sl.fArg));
5139 case LineSpacing::eExactLinesSpacing:
5145 case LineSpacing::eSingleSpace:
5150 bool isStartOfPara = pmStart == from;
5151 if (isStartOfPara) {
5152 d += tablet->CvtFromTWIPSV (pi.GetSpaceBefore ());
5156 bool isEndOfPara = pmEnd <= to + 1;
5158 d += tablet->CvtFromTWIPSV (pi.GetSpaceAfter ());
5164DistanceType WordProcessor::MeasureMinSegDescent (
size_t from,
size_t to)
const
5170 Require (from <= to);
5175 vector<StyleRunElement> outputSummary = SummarizeStyleMarkers (from, to);
5177 size_t outputSummaryLength = outputSummary.size ();
5178 Assert (outputSummaryLength != 0);
5179 DistanceType minHeightBelow = 0;
5180 size_t indexIntoText = 0;
5181 for (
size_t i = 0; i < outputSummaryLength; ++i) {
5182 const StyleRunElement& re = outputSummary[i];
5183 size_t reFrom = indexIntoText + from;
5184 size_t reLength = re.fLength;
5185 size_t reTo = reFrom + reLength;
5186 Assert (indexIntoText <= to - from);
5187 DistanceType itsBaseline;
5188 DistanceType itsHeight;
5189 if (re.fMarker ==
nullptr) {
5190 itsBaseline = MeasureSegmentBaseLine_ (GetDefaultFont (), reFrom, reTo);
5191 itsHeight = MeasureSegmentHeight_ (GetDefaultFont (), reFrom, reTo);
5194 itsBaseline = re.fMarker->MeasureSegmentBaseLine (
this, re, reFrom, reTo);
5195 itsHeight = re.fMarker->MeasureSegmentHeight (
this, re, reFrom, reTo);
5197 minHeightBelow = min (minHeightBelow, (itsHeight - itsBaseline));
5198 indexIntoText += reLength;
5200 return minHeightBelow;
5203void WordProcessor::AdjustBestRowLength (
size_t textStart,
const Led_tChar* text,
const Led_tChar* end,
size_t* rowLength)
5207 Require (text < end);
5209 Require (*rowLength > 0);
5210 inherited::AdjustBestRowLength (textStart, text, end, rowLength);
5211 for (
const Led_tChar* cur = &text[0]; cur < end; cur = Led_NextChar (cur)) {
5212 if (*cur == kEmbeddingSentinelChar) {
5214 vector<WordProcessorTable*> tables = GetTablesInRange (textStart + cur - text, textStart + cur - text + 1);
5215 if (not tables.empty ()) {
5216 Assert (cur == text);
5217 size_t newBestRowLength = (cur - text) + 1;
5218 Assert (newBestRowLength <= *rowLength + 1);
5223 Assert (newBestRowLength >= 1);
5224 *rowLength = newBestRowLength;
5233DistanceType WordProcessor::MeasureSegmentBaseLine (
size_t from,
size_t to)
const
5239 DistanceType d = inherited::MeasureSegmentBaseLine (from, to);
5242 shared_ptr<HidableTextMarkerOwner> hdb = GetHidableTextDatabase ();
5243 if (hdb.get () !=
nullptr) {
5244 DiscontiguousRun<bool> regions = hdb->GetHidableRegions (from, to);
5245 if (not regions.empty ()) {
5246 if (not regions[0].fData) {
5253 PartitionMarker* pm = GetPartitionMarkerContainingPosition (from);
5254 size_t pmStart = pm->GetStart ();
5255 size_t pmEnd = pm->GetEnd ();
5261 if (pmEnd - pmStart == 1) {
5262 vector<WordProcessorTable*> tables = GetTablesInRange (pmStart, pmEnd);
5263 if (tables.size () == 1) {
5265 WordProcessorTable* t = tables[0];
5266 Assert (t->GetStart () == pmStart);
5267 Assert (t->GetEnd () == pmEnd);
5282 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (from);
5284 LineSpacing sl = pi.GetLineSpacing ();
5286 case LineSpacing::eExactTWIPSSpacing: {
5287 Tablet_Acquirer tablet_ (
this);
5288 Tablet* tablet = tablet_;
5289 DistanceType revisedSegHeight = tablet->CvtFromTWIPSV (TWIPS (sl.fArg));
5290 DistanceType mhb = MeasureMinSegDescent (from, to);
5291 d = revisedSegHeight - mhb;
5293 case LineSpacing::eExactLinesSpacing: {
5295 Tablet_Acquirer tablet_ (
this);
5296 DistanceType normalSegHeight = inherited::MeasureSegmentHeight (from, to);
5297 DistanceType revisedSegHeight = normalSegHeight * sl.fArg / 20;
5298 DistanceType mhb = MeasureMinSegDescent (from, to);
5299 d = revisedSegHeight - mhb;
5308 bool isStartOfPara = pmStart == from;
5309 if (isStartOfPara) {
5310 TWIPS sb = pi.GetSpaceBefore ();
5312 Tablet_Acquirer tablet_ (
this);
5313 Tablet* tablet = tablet_;
5314 d += tablet->CvtFromTWIPSV (sb);
5327void WordProcessor::SetShowParagraphGlyphs (
bool showParagraphGlyphs)
5329 if (fShowParagraphGlyphs != showParagraphGlyphs) {
5330 fShowParagraphGlyphs = showParagraphGlyphs;
5331 InvalidateAllCaches ();
5343void WordProcessor::SetShowTabGlyphs (
bool showTabGlyphs)
5345 if (fShowTabGlyphs != showTabGlyphs) {
5346 fShowTabGlyphs = showTabGlyphs;
5358void WordProcessor::SetShowSpaceGlyphs (
bool showSpaceGlyphs)
5360 if (fShowSpaceGlyphs != showSpaceGlyphs) {
5361 fShowSpaceGlyphs = showSpaceGlyphs;
5362 InvalidateAllCaches ();
5367size_t WordProcessor::ComputeRelativePosition (
size_t fromPos, CursorMovementDirection direction, CursorMovementUnit movementUnit)
5369 size_t result = inherited::ComputeRelativePosition (fromPos, direction, movementUnit);
5376 shared_ptr<HidableTextMarkerOwner> hdb = GetHidableTextDatabase ();
5377 if (hdb.get () ==
nullptr) {
5379 if (direction == eCursorBack or direction == eCursorToStart) {
5380 DiscontiguousRun<bool> regions = hdb->GetHidableRegions (FindPreviousCharacter (result), result);
5381 if (not regions.empty ()) {
5384 if (not regions[0].fData) {
5385 result = FindPreviousCharacter (result);
5391 DiscontiguousRun<bool> regions = hdb->GetHidableRegions (result, FindNextCharacter (result));
5392 if (not regions.empty ()) {
5395 if (not regions[0].fData) {
5396 result = FindNextCharacter (result);
5410bool WordProcessor::ContainsMappedDisplayCharacters (
const Led_tChar* text,
size_t nTChars)
const
5412 if (fShowParagraphGlyphs and nTChars > 0 and text[nTChars - 1] ==
'\n') {
5415 if (fShowSpaceGlyphs and nTChars > 0 and ContainsMappedDisplayCharacters_HelperForChar (text, nTChars,
' ')) {
5418 return inherited::ContainsMappedDisplayCharacters (text, nTChars);
5425void WordProcessor::ReplaceMappedDisplayCharacters (
const Led_tChar* srcText, Led_tChar* copyText,
size_t nTChars)
const
5427 inherited::ReplaceMappedDisplayCharacters (srcText, copyText, nTChars);
5428 if (fShowParagraphGlyphs and nTChars > 0 and srcText[nTChars - 1] ==
'\n') {
5430 const Led_tChar kReplacementChar = 0x00b6;
5431 copyText[nTChars - 1] = kReplacementChar;
5433 if (fShowSpaceGlyphs) {
5435 const Led_tChar kReplacementChar = 0x00b7;
5436 ReplaceMappedDisplayCharacters_HelperForChar (copyText, nTChars,
' ', kReplacementChar);
5445Led_Rect WordProcessor::GetCharLocationRowRelative (
size_t afterPosition, RowReference topRow,
size_t maxRowsToCheck)
const
5447 Led_Rect r = inherited::GetCharLocationRowRelative (afterPosition, topRow, maxRowsToCheck);
5450 CoordinateType lhsMargin = 0;
5451 RowReference row = GetRowReferenceContainingPosition (afterPosition);
5452 GetLayoutMargins (row, &lhsMargin,
nullptr);
5453 r.left += lhsMargin;
5454 r.right += lhsMargin;
5457 Justification justification = GetJustification (afterPosition);
5458 if (justification == eCenterJustify or justification == eRightJustify) {
5459 switch (justification) {
5460 case eCenterJustify: {
5461 DistanceType d = CalcSpaceToEat (afterPosition) / 2;
5465 case eRightJustify: {
5466 DistanceType d = CalcSpaceToEat (afterPosition);
5480size_t WordProcessor::GetCharAtLocationRowRelative (
const Led_Point& where, RowReference topRow,
size_t maxRowsToCheck)
const
5483 size_t posInRow = inherited::GetCharAtLocationRowRelative (where, topRow, maxRowsToCheck);
5484 RowReference row = GetRowReferenceContainingPosition (posInRow);
5485 Led_Point adjustedWhere = where;
5487 CoordinateType lhsMargin = 0;
5488 GetLayoutMargins (row, &lhsMargin,
nullptr);
5489 adjustedWhere.h -= lhsMargin;
5491 Justification justification = GetJustification (posInRow);
5492 switch (justification) {
5493 case eCenterJustify: {
5494 adjustedWhere.h -= CalcSpaceToEat (posInRow) / 2;
5496 case eRightJustify: {
5497 adjustedWhere.h -= CalcSpaceToEat (posInRow);
5500 return inherited::GetCharAtLocationRowRelative (adjustedWhere, topRow, maxRowsToCheck);
5510size_t WordProcessor::ResetTabStops (
size_t from,
const Led_tChar* text,
size_t nTChars, DistanceType* charLocations,
size_t startSoFar)
const
5512 CoordinateType lhsMargin = 0;
5514 RowReference row = GetRowReferenceContainingPosition (from);
5515 GetLayoutMargins (row, &lhsMargin,
nullptr);
5517 return ResetTabStopsWithMargin (lhsMargin, from, text, nTChars, charLocations, startSoFar);
5520size_t WordProcessor::ResetTabStopsWithMargin (DistanceType lhsMargin,
size_t from,
const Led_tChar* text,
size_t nTChars,
5521 DistanceType* charLocations,
size_t startSoFar)
const
5524 size_t lastTabIndex = 0;
5525 CoordinateType tabAdjust = 0;
5526 DistanceType widthAtStart = (startSoFar == 0 ? 0 : charLocations[startSoFar - 1]);
5527 for (
size_t i = startSoFar; i < startSoFar + nTChars; ++i) {
5528 if (text[i] ==
'\t') {
5529 DistanceType widthSoFar = (i == 0 ? 0 : charLocations[i - 1]);
5530 tabAdjust = widthAtStart +
5531 GetTabStopList (from).ComputeTabStopAfterPosition (Tablet_Acquirer (
this), widthSoFar - widthAtStart + lhsMargin) -
5532 lhsMargin - charLocations[i];
5535 charLocations[i] += tabAdjust;
5537 return (lastTabIndex);
5545void WordProcessor::GetLayoutMargins (RowReference row, CoordinateType* lhs, CoordinateType* rhs)
const
5547 if (fParagraphDatabase.get () ==
nullptr) {
5548 throw NoParagraphDatabaseAvailable ();
5551 PartitionMarker* pm = row.GetPartitionMarker ();
5552 size_t pmStart = pm->GetStart ();
5554 Tablet_Acquirer tablet_ (
this);
5555 Tablet* tablet = tablet_;
5557 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (pmStart);
5558 if (lhs !=
nullptr) {
5559 TWIPS lhsTWIPS = pi.GetLeftMargin ();
5560 if (row.GetSubRow () == 0) {
5561 lhsTWIPS += pi.GetFirstIndent ();
5563 *lhs = tablet->CvtFromTWIPSH (lhsTWIPS);
5564 if (row.GetSubRow () == 0) {
5565 ListStyle ls = pi.GetListStyle ();
5566 if (ls != eListStyle_None) {
5570 bool allowLists =
true;
5571 size_t pmEnd = pm->GetEnd ();
5572 if (pmEnd - pmStart == 1) {
5573 vector<WordProcessorTable*> tables = GetTablesInRange (pmStart, pmEnd);
5574 if (tables.size () == 1) {
5579 *lhs += GetListLeaderLength (pmStart);
5584 if (rhs !=
nullptr) {
5585 *rhs = tablet->CvtFromTWIPSH (pi.GetRightMargin ());
5589void WordProcessor::ExpandedFromAndToInPostReplace (
size_t from,
size_t newTo,
size_t stableTypingRegionStart,
size_t stableTypingRegionEnd,
5590 size_t startPositionOfRowWhereReplaceBegins,
size_t startPositionOfRowAfterReplaceEnds,
5591 size_t* expandedFrom,
size_t* expandedTo)
5593 Justification justification = GetJustification (from);
5594 if (justification != eLeftJustify) {
5595 from = GetStartOfRowContainingPosition (from);
5597 inherited::ExpandedFromAndToInPostReplace (from, newTo, stableTypingRegionStart, stableTypingRegionEnd, startPositionOfRowWhereReplaceBegins,
5598 startPositionOfRowAfterReplaceEnds, expandedFrom, expandedTo);
5601void WordProcessor::PostReplace (PreReplaceInfo& preReplaceInfo)
5603 inherited::PostReplace (preReplaceInfo);
5604 UpdateMode updateMode = preReplaceInfo.GetUpdateMode ();
5605 if (updateMode != eNoUpdate) {
5606 if (preReplaceInfo.GetTo () + 2 >= GetEnd ()) {
5613 ListStyle ls = eListStyle_None;
5614 if (not WordProcessor::GetListStyle (preReplaceInfo.GetFrom (), GetEnd (), &ls) or ls != eListStyle_None) {
5615 Refresh (updateMode);
5621DistanceType WordProcessor::CalcSpaceToEat (
size_t rowContainingCharPos)
const
5623 size_t rowStart = GetStartOfRowContainingPosition (rowContainingCharPos);
5624 size_t rowEnd = GetEndOfRowContainingPosition (rowStart);
5625 Assert (rowEnd == GetEndOfRowContainingPosition (rowContainingCharPos));
5628 size_t lenOfText = rowEnd - rowStart;
5630 CopyOut (rowStart, lenOfText, buf.data ());
5632 while (rowStart < rowEnd) {
5633 size_t i = rowEnd - rowStart - 1;
5643 DistanceType segmentWidth = CalcSegmentSize (rowStart, rowEnd);
5644 DistanceType layoutWidth;
5646 CoordinateType lhsMargin = 0;
5647 CoordinateType rhsMargin = 0;
5648 GetLayoutMargins (GetRowReferenceContainingPosition (rowStart), &lhsMargin, &rhsMargin);
5649 Assert (lhsMargin < rhsMargin);
5650 layoutWidth = rhsMargin - lhsMargin;
5654 if (layoutWidth < segmentWidth) {
5658 Assert (layoutWidth >= segmentWidth);
5659 DistanceType xtra = layoutWidth - segmentWidth;
5668using WordProcessorFlavorPackageInternalizer = WordProcessor::WordProcessorFlavorPackageInternalizer;
5670WordProcessorFlavorPackageInternalizer::WordProcessorFlavorPackageInternalizer (TextStore& ts,
const shared_ptr<AbstractStyleDatabaseRep>& styleDatabase,
5671 const shared_ptr<AbstractParagraphDatabaseRep>& paragraphDatabase,
5672 const shared_ptr<HidableTextMarkerOwner>& hidableTextDatabase)
5674 , inherited (ts, styleDatabase)
5675 , fOverwriteTableMode (false)
5677#if !qStroika_Frameworks_Led_NestedTablesSupported
5678 fNoTablesAllowed (false)
5681 fParagraphDatabase (paragraphDatabase)
5682 , fHidableTextDatabase (hidableTextDatabase)
5690 sinkStream->SetIgnoreLastParaAttributes (
true);
5691 sinkStream->SetOverwriteTableMode (GetOverwriteTableMode ());
5692#if !qStroika_Frameworks_Led_NestedTablesSupported
5693 sinkStream->SetNoTablesAllowed (GetNoTablesAllowed ());
5704WordProcessor::WPPartition::WPPartition (TextStore& textStore,
MarkerOwner& tableMarkerOwner)
5705 : inherited{textStore, eSpecialHackToDisableInit}
5706 , fTableMarkerOwner{tableMarkerOwner}
5712vector<WordProcessorTable*> WordProcessor::WPPartition::GetTablesInRange (
size_t from,
size_t to)
const
5714 if (to ==
static_cast<size_t> (-1)) {
5715 to = GetTextStore ().GetLength ();
5717 Require (from <= to);
5718 Require (to <= GetTextStore ().GetLength () + 1);
5719 MarkersOfATypeMarkerSink2Vector<WordProcessorTable> result;
5720 GetTextStore ().CollectAllMarkersInRangeInto (from, to, &fTableMarkerOwner, result);
5721 return result.fResult;
5724WordProcessorTable* WordProcessor::GetActiveTable ()
const
5726 size_t selStart = 0;
5728 GetSelection (&selStart, &selEnd);
5729 if (selEnd - selStart == 1) {
5730 vector<WordProcessorTable*> tables = GetTablesInRange (selStart, selEnd);
5731 Assert (tables.size () <= 1);
5732 if (tables.size () == 1) {
5740void WordProcessor::WPPartition::FinalConstruct ()
5743 inherited::FinalConstruct ();
5744 DoHandleUpdateForTableRangeCheck (0, GetTextStore ().GetLength ());
5747void WordProcessor::WPPartition::DidUpdateText (
const UpdateInfo& updateInfo)
noexcept
5752 DoHandleUpdateForTableRangeCheck (updateInfo.fReplaceFrom, updateInfo.GetResultingRHS ());
5755 inherited::DidUpdateText (updateInfo);
5758void WordProcessor::WPPartition::DoHandleUpdateForTableRangeCheck (
size_t from,
size_t to)
noexcept
5760 TextStore& ts = GetTextStore ();
5763 vector<WordProcessorTable*> tables = GetTablesInRange (ts.FindPreviousCharacter (from), ts.FindNextCharacter (to));
5764 for (
auto i = tables.begin (); i != tables.end (); ++i) {
5765 WordProcessorTable* t = *i;
5766 if (t->GetLength () != 0) {
5767 size_t tableEnd = t->GetEnd ();
5770 size_t tableStart = t->GetStart ();
5771 PartitionMarker* pm = GetPartitionMarkerContainingPosition (tableStart);
5776 if (tableEnd < pm->GetEnd () and tableEnd > pm->GetStart ()) {
5777 Split (pm, tableEnd);
5779 if (tableStart > pm->GetStart () and tableStart < pm->GetEnd ()) {
5780 Split (pm, tableStart);
5784 bool coalesce = NeedToCoalesce (pm);
5788 pm = pm->GetPrevious ();
5789 if (pm !=
nullptr) {
5790 coalesce = NeedToCoalesce (pm);
5794 pm = pm->GetPrevious ();
5795 if (pm !=
nullptr) {
5796 coalesce = NeedToCoalesce (pm);
5805 PartitionMarker* pm = GetPartitionMarkerContainingPosition (from);
5807 bool coalesce = NeedToCoalesce (pm);
5811 pm = pm->GetPrevious ();
5812 if (pm !=
nullptr) {
5813 coalesce = NeedToCoalesce (pm);
5817 pm = pm->GetPrevious ();
5818 if (pm !=
nullptr) {
5819 coalesce = NeedToCoalesce (pm);
5827bool WordProcessor::WPPartition::NeedToCoalesce (PartitionMarker* pm)
noexcept
5831 bool coalesce = inherited::NeedToCoalesce (pm);
5839 if (pm->GetLength () != 0) {
5840 size_t end = pm->GetEnd ();
5841 size_t trStart = end - 1;
5843 if (pm->GetNext () !=
nullptr) {
5847 vector<WordProcessorTable*> tables = GetTablesInRange (trStart, trEnd);
5848 if (not tables.empty ()) {
5849 if (tables.size () == 2) {
5853 else if (tables.size () == 1) {
5854 WordProcessorTable* table = tables[0];
5856 if (table->GetStart () == pm->GetEnd ()) {
5859 else if (table->GetEnd () == pm->GetEnd ()) {
5869#if qStroika_Foundation_Debug_AssertionsChecked
5870void WordProcessor::WPPartition::Invariant_ ()
const
5872 Partition::Invariant_ ();
5880 for (PartitionMarker* cur = GetFirstPartitionMarker (); cur !=
nullptr; cur = cur->GetNext ()) {
5882 size_t start = cur->GetStart ();
5883 size_t end = cur->GetEnd ();
5884 size_t len = end - start;
5886 if (end > GetEnd ()) {
5890 CopyOut (start, len, buf.data ());
5891 for (
size_t i = 1; i < len; ++i) {
5892 Assert (buf[i - 1] !=
'\n');
5893 vector<WordProcessorTable*> tables = GetTablesInRange (start + i - 1, start + i);
5894 if (not tables.empty ()) {
5895 Assert (tables.size () == 1);
5896 WordProcessorTable* t = tables[0];
5897 if (t->GetLength () != 0) {
5898 Assert (t->GetStart () == start);
5899 Assert (t->GetLength () == len);
5903 if (cur->GetNext () !=
nullptr) {
5904 Assert (buf[len - 1] ==
'\n' or (not GetTablesInRange (start + len - 1, start + len).empty ()) or
5905 (start + len + 1 <= GetEnd () and not GetTablesInRange (start + len, start + len + 1).empty ()));
5911 vector<WordProcessorTable*> tables = GetTablesInRange (0, GetTextStore ().GetLength ());
5912 for (
auto i = tables.begin (); i != tables.end (); ++i) {
5913 WordProcessorTable* t = *i;
5914 if (t->GetLength () != 0) {
5915 PartitionMarker* pm = GetPartitionMarkerContainingPosition (t->GetStart ());
5916 Assert (t->GetStart () == pm->GetStart ());
5917 Assert (t->GetEnd () == pm->GetEnd ());
5928using WordProcessorFlavorPackageExternalizer = WordProcessor::WordProcessorFlavorPackageExternalizer;
5930WordProcessorFlavorPackageExternalizer::WordProcessorFlavorPackageExternalizer (TextStore& ts,
const shared_ptr<AbstractStyleDatabaseRep>& styleDatabase,
5931 const shared_ptr<AbstractParagraphDatabaseRep>& paragraphDatabase,
5932 const shared_ptr<HidableTextMarkerOwner>& hidableTextDatabase)
5934 , inherited (ts, styleDatabase)
5935 , fParagraphDatabase (paragraphDatabase)
5936 , fHidableTextDatabase (hidableTextDatabase)
5940StandardStyledTextIOSrcStream* WordProcessorFlavorPackageExternalizer::mkStandardStyledTextIOSrcStream (
size_t selectionStart,
size_t selectionEnd)
5943 fHidableTextDatabase, selectionStart, selectionEnd);
5944 stream->SetUseTableSelection (GetUseTableSelection ());
5948void WordProcessorTable::DrawSegment (
const StyledTextImager* imager,
const StyleRunElement& , Tablet* tablet,
5949 [[maybe_unused]]
size_t from, [[maybe_unused]]
size_t to, [[maybe_unused]]
const TextLayoutBlock& text,
5950 const Led_Rect& drawInto,
const Led_Rect& invalidRect, CoordinateType , DistanceType* pixelsDrawn)
5952 RequireMember (
const_cast<StyledTextImager*
> (imager), WordProcessor);
5953 Assert (from + 1 == to);
5955 Require (text.PeekAtVirtualText ()[0] == kEmbeddingSentinelChar);
5957 using TemporarilyUseTablet = EmbeddedTableWordProcessor::TemporarilyUseTablet;
5959 WordProcessor& owningWP = *
dynamic_cast<WordProcessor*
> (
const_cast<StyledTextImager*
> (imager));
5961 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*
this, owningWP);
5963 DistanceType bwv = Led_CvtScreenPixelsFromTWIPSV (fBorderWidth);
5964 Led_Rect rowRect = drawInto;
5966 size_t nRows = fRows.size ();
5967 for (
size_t ri = 0; ri < nRows; ++ri) {
5970 size_t nCols = GetColumnCount (ri);
5971 rowRect.bottom = rowRect.top + fRows[ri].fHeight;
5972 for (
size_t ci = 0; ci < nCols; ++ci) {
5973 if (GetCellFlags (ri, ci) == ePlainCell) {
5974 Led_Rect scrolledCBWR = TableCoordinates2Window (GetCellBounds (ri, ci));
5975 if (Intersect (scrolledCBWR, invalidRect)) {
5976 Led_Rect scrolledEditorCBWR = TableCoordinates2Window (GetCellEditorBounds (ri, ci));
5980 if (scrolledCBWR != scrolledEditorCBWR) {
5981 tablet->EraseBackground_SolidHelper (scrolledCBWR, GetCellColor (ri, ci));
5984 TemporarilyAllocateCellWP wp (*
this, owningWP, ri, ci, scrolledEditorCBWR);
5985 TemporarilyUseTablet tmpUseTablet (*wp, tablet, TemporarilyUseTablet::eDontDoTextMetricsChangedCall);
5986 wp->Draw (scrolledEditorCBWR,
false);
5987 DrawCellBorders (tablet, ri, ci, scrolledCBWR);
5993 if (scrolledCBWR.bottom < invalidRect.top) {
5996 if (scrolledCBWR.top > invalidRect.bottom) {
6002 rowRect.top = rowRect.bottom + bwv;
6006 DrawTableBorders (owningWP, tablet, drawInto);
6008 if (pixelsDrawn !=
nullptr) {
6009 *pixelsDrawn = fTotalWidth;
6013void WordProcessorTable::MeasureSegmentWidth ([[maybe_unused]]
const StyledTextImager* imager,
const StyleRunElement& ,
6014 [[maybe_unused]]
size_t from, [[maybe_unused]]
size_t to,
6015 [[maybe_unused]]
const Led_tChar* text, DistanceType* distanceResults)
const
6017 RequireMember (
const_cast<StyledTextImager*
> (imager), WordProcessor);
6018 Assert (from + 1 == to);
6020 distanceResults[0] = fTotalWidth;
6023DistanceType WordProcessorTable::MeasureSegmentHeight ([[maybe_unused]]
const StyledTextImager* imager,
const StyleRunElement& ,
6024 [[maybe_unused]]
size_t from, [[maybe_unused]]
size_t to)
const
6026 RequireMember (
const_cast<StyledTextImager*
> (imager), WordProcessor);
6027 Assert (from + 1 == to);
6030 return fTotalHeight == 0 ? 1 : fTotalHeight;
6038vector<Led_Rect> WordProcessorTable::GetRowHilightRects ()
const
6040 Led_Require_CurrentOwningWP ();
6042 vector<Led_Rect> result;
6044 size_t rowStart = GetStart ();
6045 size_t rowEnd = GetEnd ();
6046 size_t hilightStart = fCurrentOwningWP->GetSelectionStart ();
6047 size_t hilightEnd = fCurrentOwningWP->GetSelectionEnd ();
6048 bool segmentHilighted = max (rowStart, hilightStart) < min (rowEnd, hilightEnd);
6050 if (segmentHilighted) {
6051 Led_Rect tableRect = fCurrentOwningWP->GetIntraRowTextWindowBoundingRect (rowStart, rowEnd);
6052 vector<Led_Rect> hilightRects = fCurrentOwningWP->TextImager::GetRowHilightRects (
6053 TextLayoutBlock_Basic{&kEmbeddingSentinelChar, &kEmbeddingSentinelChar + 1}, rowStart, rowEnd, hilightStart, hilightEnd);
6057 if (rowStart != hilightStart or rowEnd != hilightEnd) {
6058 return hilightRects;
6065 for (
auto i = hilightRects.begin (); i != hilightRects.end (); ++i) {
6066 if (tableRect != *i) {
6067 if (not(*i).IsEmpty ()) {
6068 result.push_back (*i);
6077 size_t rowSelStart = 0;
6078 size_t rowSelEnd = 0;
6079 size_t colSelStart = 0;
6080 size_t colSelEnd = 0;
6081 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6084 if (rowSelStart == 0 and rowSelEnd == GetRowCount () and colSelStart == 0 and colSelEnd == GetColumnCount ()) {
6085 return hilightRects;
6088 if (rowSelEnd - rowSelStart == 1 and colSelEnd - colSelStart == 1 and GetIntraCellMode ()) {
6089 TemporarilyAllocateCellWithTablet wp (*
const_cast<WordProcessorTable*
> (
this), rowSelStart, colSelStart);
6090 vector<Led_Rect> cellHilightRegions = wp->GetSelectionWindowRects (wp->GetSelectionStart (), wp->GetSelectionEnd ());
6091 for (
auto i = cellHilightRegions.begin (); i != cellHilightRegions.end (); ++i) {
6092 result.push_back (*i);
6096 for (
size_t ri = rowSelStart; ri < rowSelEnd; ++ri) {
6097 size_t thisRowEnd = min (colSelEnd, GetColumnCount (ri));
6098 for (
size_t ci = colSelStart; ci < thisRowEnd; ++ci) {
6099 if (GetCellFlags (ri, ci) == ePlainCell) {
6101 Led_Rect wRelCellRect = TableCoordinates2Window (GetCellBounds (ri, ci));
6102 if (not wRelCellRect.IsEmpty ()) {
6103 result.push_back (wRelCellRect);
6114 for (
auto orit = result.begin (); orit != result.end (); ++orit) {
6115 Ensure ((*orit).GetWidth () > 0);
6116 Ensure ((*orit).GetHeight () > 0);
6117 for (
auto irit = orit + 1; irit != result.end (); ++irit) {
6118 Led_Rect hr = *irit;
6119 Ensure (hr.GetWidth () > 0);
6120 Ensure (hr.GetHeight () > 0);
6121 Ensure (not Intersect (hr, *orit));
6134void WordProcessorTable::DrawTableBorders (WordProcessor& owningWP, Tablet* tablet,
const Led_Rect& drawInto)
6144 DistanceType bwh = Led_CvtScreenPixelsFromTWIPSH (fBorderWidth);
6147 Led_Rect bounds = drawInto - Led_Point (0, owningWP.GetHScrollPos ());
6148 bounds.right = bounds.left + fTotalWidth;
6149 bounds.bottom = bounds.top + fTotalHeight;
6150 tablet->FrameRectangle (bounds, fBorderColor, bwh);
6160void WordProcessorTable::DrawCellBorders (Tablet* tablet,
size_t ,
size_t ,
const Led_Rect& cellBounds)
6162 CoordinateType bw = Led_CvtScreenPixelsFromTWIPSH (fBorderWidth);
6164 tablet->FrameRectangle (InsetRect (cellBounds, -bw, -bw), fBorderColor, bw);
6175Led_Rect WordProcessorTable::GetCellBounds (
size_t row,
size_t column)
const
6177 Require (GetCellFlags (row, column) == ePlainCell);
6178 return GetCell (row, column).GetCachedBoundsRect ();
6187Led_Rect WordProcessorTable::GetCellEditorBounds (
size_t row,
size_t column)
const
6189 Require (GetCellFlags (row, column) == ePlainCell);
6190 Led_Rect cellBounds = GetCellBounds (row, column);
6191 Led_Rect cellEditBounds = cellBounds;
6192 TWIPS_Rect defaultCellMarginTWIPS;
6193 GetDefaultCellMargins (&defaultCellMarginTWIPS.top, &defaultCellMarginTWIPS.left, &defaultCellMarginTWIPS.bottom,
6194 &defaultCellMarginTWIPS.right);
6195 cellEditBounds.top += Led_CvtScreenPixelsFromTWIPSV (defaultCellMarginTWIPS.top);
6196 cellEditBounds.left += Led_CvtScreenPixelsFromTWIPSH (defaultCellMarginTWIPS.left);
6197 cellEditBounds.bottom -= Led_CvtScreenPixelsFromTWIPSV (defaultCellMarginTWIPS.bottom);
6198 cellEditBounds.right -= Led_CvtScreenPixelsFromTWIPSH (defaultCellMarginTWIPS.right);
6200 cellEditBounds.bottom = max (cellEditBounds.bottom, cellEditBounds.top + 1);
6201 cellEditBounds.right = max (cellEditBounds.right, cellEditBounds.left + 1);
6202 return cellEditBounds;
6210void WordProcessorTable::GetClosestCell (
const Led_Point& p,
size_t* row,
size_t* col)
const
6215 Led_Size border = Led_Size (Led_CvtScreenPixelsFromTWIPSV (fBorderWidth), Led_CvtScreenPixelsFromTWIPSH (fBorderWidth));
6216 DistanceType spacing = Led_CvtScreenPixelsFromTWIPSV (GetCellSpacing ());
6219 size_t rowCount = GetRowCount ();
6220 Assert (rowCount > 0);
6221 CoordinateType top = spacing + border.v;
6223 for (; ri < rowCount; ++ri) {
6224 DistanceType h = fRows[ri].fHeight;
6225 CoordinateType bottom = top + h;
6231 top += spacing + border.v;
6233 if (ri >= rowCount) {
6239 size_t colCount = GetColumnCount (ri);
6240 Assert (colCount > 0);
6242 for (; ci < colCount; ++ci) {
6245 GetRealCell (&rri, &cci);
6246 Led_Rect bounds = GetCellBounds (rri, cci);
6248 if (p.h < bounds.GetRight ()) {
6252 if (ci >= colCount) {
6258Led_Point WordProcessorTable::TableCoordinates2Window (
const Led_Point& p)
const
6260 Led_Require_CurrentOwningWP ();
6261 Led_Point tableWROrigin = fCurrentOwningWP->GetCharWindowLocation (GetStart ()).GetTopLeft ();
6262 return p + tableWROrigin;
6265Led_Rect WordProcessorTable::TableCoordinates2Window (
const Led_Rect& r)
const
6267 return Led_Rect (TableCoordinates2Window (r.GetOrigin ()), r.GetSize ());
6270Led_Point WordProcessorTable::WindowCoordinates2Table (
const Led_Point& p)
const
6272 Led_Require_CurrentOwningWP ();
6273 Led_Point tableWROrigin = fCurrentOwningWP->GetCharWindowLocation (GetStart ()).GetTopLeft ();
6274 return p - tableWROrigin;
6277Led_Rect WordProcessorTable::WindowCoordinates2Table (
const Led_Rect& r)
const
6279 return Led_Rect (WindowCoordinates2Table (r.GetOrigin ()), r.GetSize ());
6282bool WordProcessorTable::GetCaretShownSituation ()
const
6284 if (GetIntraCellMode ()) {
6285 size_t selStart = 0;
6287 GetIntraCellSelection (&selStart, &selEnd);
6288 return selStart == selEnd;
6297Led_Rect WordProcessorTable::CalculateCaretRect ()
const
6299 Led_Require_CurrentOwningWP ();
6300 if (GetIntraCellMode ()) {
6301 size_t selStart = 0;
6303 GetIntraCellSelection (&selStart, &selEnd);
6304 if (selStart == selEnd) {
6307 (void)GetIntraCellMode (&row, &col);
6308 TemporarilyAllocateCellWithTablet wp (*
const_cast<WordProcessorTable*
> (
this), row, col);
6309 return wp->CalculateCaretRect ();
6312 return (Led_Rect (0, 0, 0, 0));
6315bool WordProcessorTable::OnTypedNormalCharacter (Led_tChar theChar,
bool optionPressed,
bool shiftPressed,
bool commandPressed,
6316 bool controlPressed,
bool altKeyPressed)
6318 using InteractiveModeUpdater = WordProcessor::InteractiveModeUpdater;
6319 using UndoableContextHelper = WordProcessor::UndoableContextHelper;
6320 Led_Require_CurrentOwningWP ();
6322 size_t rowSelStart = 0;
6323 size_t rowSelEnd = 0;
6324 size_t colSelStart = 0;
6325 size_t colSelEnd = 0;
6326 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6328 if (theChar ==
'\b') {
6330 if (rowSelStart == 0 and rowSelEnd == GetRowCount () and colSelStart == 0 and colSelEnd == GetColumnCount () and not fIntraCellMode) {
6335 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6336 AllowUpdateInfoPropagationContext AUIPC (*
this);
6337 if (not fIntraCellMode) {
6340 UndoableContextHelper undoContext (*fCurrentOwningWP, TextInteractor::GetCommandNames ().fTypingCommandName,
false);
6342 (void)OnPerformCommand_ApplyToEachSelectedCell (TextInteractor::kClear_CmdID,
false);
6344 undoContext.CommandComplete ();
6345 SetIntraCellMode (rowSelStart, colSelStart);
6348 Assert (fIntraCellMode);
6349 TemporarilyAllocateCellWithTablet wp (*
this, rowSelStart, colSelStart);
6350 wp->OnTypedNormalCharacter (theChar, optionPressed, shiftPressed, commandPressed, controlPressed, altKeyPressed);
6355bool WordProcessorTable::DoSingleCharCursorEdit (TextInteractor::CursorMovementDirection direction,
6356 TextInteractor::CursorMovementUnit movementUnit, TextInteractor::CursorMovementAction action,
6357 TextInteractor::UpdateMode updateMode,
bool scrollToSelection)
6361 if (GetIntraCellMode (&row, &col)) {
6363 AllowUpdateInfoPropagationContext AUIPC (*
this);
6364 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6365 wp->DoSingleCharCursorEdit (direction, movementUnit, action, updateMode, scrollToSelection);
6371bool WordProcessorTable::OnUpdateCommand (TextInteractor::CommandUpdater* enabler)
6373 Led_Require_CurrentOwningWP ();
6378 if (GetIntraCellMode (&row, &col)) {
6379 if (fCurrentOwningWP->PassAlongCommandToIntraCellModeTableCell (enabler->GetCmdID ())) {
6380 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6381 [[maybe_unused]]
bool result = wp->OnUpdateCommand (enabler);
6382 if (enabler->GetCmdID () == WordProcessor::kSelectedEmbeddingProperties_CmdID and not enabler->GetEnabled ()) {
6390 switch (enabler->GetCmdID ()) {
6391 case WordProcessor::kCut_CmdID: {
6392 OnUpdateCutCommand (enabler);
6395 case WordProcessor::kInsertTableRowAbove_CmdID: {
6396 OnUpdateInsertTableRowAboveCommand (enabler);
6399 case WordProcessor::kInsertTableRowBelow_CmdID: {
6400 OnUpdateInsertTableRowBelowCommand (enabler);
6403 case WordProcessor::kInsertTableColBefore_CmdID: {
6404 OnUpdateInsertTableColBeforeCommand (enabler);
6407 case WordProcessor::kInsertTableColAfter_CmdID: {
6408 OnUpdateInsertTableColAfterCommand (enabler);
6411 case WordProcessor::kRemoveTableColumns_CmdID: {
6412 OnUpdateRemoveTableColumnsCommand (enabler);
6415 case WordProcessor::kRemoveTableRows_CmdID: {
6416 OnUpdateRemoveTableRowsCommand (enabler);
6419 case WordProcessor::kSelectTableIntraCellAll_CmdID:
6420 case WordProcessor::kSelectTableCell_CmdID:
6421 case WordProcessor::kSelectTableRow_CmdID:
6422 case WordProcessor::kSelectTableColumn_CmdID:
6423 case WordProcessor::kSelectTable_CmdID: {
6424 OnUpdateSelectTablePartsCommand (enabler);
6429 if (fCurrentOwningWP->PassAlongCommandToEachSelectedTableCell (enabler->GetCmdID ())) {
6430 return OnUpdateCommand_ApplyToEachSelectedCell (enabler);
6436bool WordProcessorTable::OnPerformCommand (TextInteractor::CommandNumber commandNumber)
6438 Led_Require_CurrentOwningWP ();
6440 AllowUpdateInfoPropagationContext AUIPC (*
this);
6444 if (GetIntraCellMode (&row, &col)) {
6445 if (fCurrentOwningWP->PassAlongCommandToIntraCellModeTableCell (commandNumber)) {
6446 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6447 return wp->OnPerformCommand (commandNumber);
6451 switch (commandNumber) {
6452 case WordProcessor::kCut_CmdID: {
6456 case WordProcessor::kInsertTableRowAbove_CmdID: {
6457 OnInsertTableRowAboveCommand ();
6460 case WordProcessor::kInsertTableRowBelow_CmdID: {
6461 OnInsertTableRowBelowCommand ();
6464 case WordProcessor::kInsertTableColBefore_CmdID: {
6465 OnInsertTableColBeforeCommand ();
6468 case WordProcessor::kInsertTableColAfter_CmdID: {
6469 OnInsertTableColAfterCommand ();
6472 case WordProcessor::kRemoveTableColumns_CmdID: {
6473 OnRemoveTableColumnsCommand ();
6476 case WordProcessor::kRemoveTableRows_CmdID: {
6477 OnRemoveTableRowsCommand ();
6480 case WordProcessor::kSelectTableIntraCellAll_CmdID:
6481 case WordProcessor::kSelectTableCell_CmdID:
6482 case WordProcessor::kSelectTableRow_CmdID:
6483 case WordProcessor::kSelectTableColumn_CmdID:
6484 case WordProcessor::kSelectTable_CmdID: {
6485 OnPerformTablePartsCommand (commandNumber);
6490 if (fCurrentOwningWP->PassAlongCommandToEachSelectedTableCell (commandNumber)) {
6491 return OnPerformCommand_ApplyToEachSelectedCell (commandNumber);
6497void WordProcessorTable::BreakInGroupedCommands ()
6499 Led_Require_CurrentOwningWP ();
6500 fCurrentOwningWP->BreakInGroupedCommands ();
6503bool WordProcessorTable::OnUpdateCommand_ApplyToEachSelectedCell (TextInteractor::CommandUpdater* enabler)
6506 Led_Require_CurrentOwningWP ();
6508 bool result =
false;
6509 size_t rowSelStart = 0;
6510 size_t rowSelEnd = 0;
6511 size_t colSelStart = 0;
6512 size_t colSelEnd = 0;
6513 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6514 for (
size_t ri = rowSelStart; ri < rowSelEnd; ++ri) {
6515 size_t thisRowEnd = min (colSelEnd, GetColumnCount (ri));
6516 for (
size_t ci = colSelStart; ci < thisRowEnd; ++ci) {
6517 TemporarilyAllocateCellWithTablet wp (*
this, ri, ci);
6518 wp->SetSelection (0, wp->GetEnd (), TextInteractor::eNoUpdate);
6519 result = result or wp->OnUpdateCommand (enabler);
6525bool WordProcessorTable::OnPerformCommand_ApplyToEachSelectedCell (TextInteractor::CommandNumber commandNumber,
bool captureChangesForUndo)
6527 Led_Require_CurrentOwningWP ();
6528 if (captureChangesForUndo) {
6529 fCurrentOwningWP->BreakInGroupedCommands ();
6531 bool result =
false;
6532 size_t rowSelStart = 0;
6533 size_t rowSelEnd = 0;
6534 size_t colSelStart = 0;
6535 size_t colSelEnd = 0;
6536 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6537 for (
size_t ri = rowSelStart; ri < rowSelEnd; ++ri) {
6538 size_t thisRowEnd = min (colSelEnd, GetColumnCount (ri));
6539 for (
size_t ci = colSelStart; ci < thisRowEnd; ++ci) {
6540 TemporarilyAllocateCellWithTablet wp (*
this, ri, ci, captureChangesForUndo);
6541 wp->SetSelection (0, wp->GetEnd (), TextInteractor::eNoUpdate);
6542 TextInteractor::SuppressCommandBreaksContext SCBC (*wp);
6543 wp->OnPerformCommand (commandNumber);
6547 if (captureChangesForUndo) {
6548 fCurrentOwningWP->BreakInGroupedCommands ();
6553void WordProcessorTable::OnUpdateCutCommand (TextInteractor::CommandUpdater* enabler)
6556 Led_Require_CurrentOwningWP ();
6557 size_t rowSelStart = 0;
6558 size_t rowSelEnd = 0;
6559 size_t colSelStart = 0;
6560 size_t colSelEnd = 0;
6561 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6562 enabler->SetEnabled (rowSelStart != rowSelEnd and colSelStart != colSelEnd);
6565void WordProcessorTable::OnCutCommand ()
6567 Led_Require_CurrentOwningWP ();
6568 AllowUpdateInfoPropagationContext AUIPC (*
this);
6569 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6570 Assert (fCurrentOwningWP->GetSelectionEnd () - fCurrentOwningWP->GetSelectionStart () == 1);
6571 fCurrentOwningWP->OnCopyCommand ();
6572 UndoableContextHelper undoContext (*fCurrentOwningWP, TextInteractor::GetCommandNames ().fCutCommandName,
true);
6574 (void)OnPerformCommand_ApplyToEachSelectedCell (TextInteractor::kClear_CmdID,
false);
6576 undoContext.CommandComplete ();
6579void WordProcessorTable::OnUpdateInsertTableRowAboveCommand (TextInteractor::CommandUpdater* enabler)
6582 Led_Require_CurrentOwningWP ();
6583 enabler->SetEnabled (
true);
6586void WordProcessorTable::OnInsertTableRowAboveCommand ()
6588 Led_Require_CurrentOwningWP ();
6589 AllowUpdateInfoPropagationContext AUIPC (*
this);
6590 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6591 BreakInGroupedCommands ();
6592 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fInsertTableRowAboveCommandName,
false);
6596 GetCellSelection (&curRow,
nullptr,
nullptr,
nullptr);
6598 Assert (curRow <= GetRowCount ());
6601 context.CommandComplete ();
6602 BreakInGroupedCommands ();
6605void WordProcessorTable::OnUpdateInsertTableRowBelowCommand (TextInteractor::CommandUpdater* enabler)
6608 Led_Require_CurrentOwningWP ();
6609 enabler->SetEnabled (
true);
6612void WordProcessorTable::OnInsertTableRowBelowCommand ()
6614 Led_Require_CurrentOwningWP ();
6615 AllowUpdateInfoPropagationContext AUIPC (*
this);
6616 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6617 BreakInGroupedCommands ();
6618 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fInsertTableRowAboveCommandName,
false);
6622 GetCellSelection (
nullptr, &curRow,
nullptr,
nullptr);
6623 Assert (curRow <= GetRowCount ());
6626 context.CommandComplete ();
6627 BreakInGroupedCommands ();
6630void WordProcessorTable::OnUpdateInsertTableColBeforeCommand (TextInteractor::CommandUpdater* enabler)
6632 Led_Require_CurrentOwningWP ();
6634 enabler->SetEnabled (
true);
6637void WordProcessorTable::OnInsertTableColBeforeCommand ()
6639 Led_Require_CurrentOwningWP ();
6640 AllowUpdateInfoPropagationContext AUIPC (*
this);
6641 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6642 BreakInGroupedCommands ();
6643 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fInsertTableColBeforeCommandName,
false);
6646 GetCellSelection (
nullptr,
nullptr, &curCol,
nullptr);
6647 Assert (curCol <= GetColumnCount ());
6648 InsertColumn (curCol);
6650 context.CommandComplete ();
6651 BreakInGroupedCommands ();
6654void WordProcessorTable::OnUpdateInsertTableColAfterCommand (TextInteractor::CommandUpdater* enabler)
6656 Led_Require_CurrentOwningWP ();
6658 enabler->SetEnabled (
true);
6661void WordProcessorTable::OnInsertTableColAfterCommand ()
6663 Led_Require_CurrentOwningWP ();
6664 AllowUpdateInfoPropagationContext AUIPC (*
this);
6665 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6666 BreakInGroupedCommands ();
6667 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fInsertTableColAfterCommandName,
false);
6670 GetCellSelection (
nullptr,
nullptr,
nullptr, &curCol);
6671 Assert (curCol <= GetColumnCount ());
6672 InsertColumn (curCol);
6674 context.CommandComplete ();
6675 BreakInGroupedCommands ();
6678void WordProcessorTable::OnUpdateRemoveTableRowsCommand (TextInteractor::CommandUpdater* pCmdUI)
6680 Led_Require_CurrentOwningWP ();
6682 size_t rowSelStart = 0;
6683 size_t rowSelEnd = 0;
6684 size_t colSelStart = 0;
6685 size_t colSelEnd = 0;
6686 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6687 pCmdUI->SetEnabled (colSelStart == 0 and colSelEnd == GetColumnCount (rowSelStart, rowSelEnd));
6690void WordProcessorTable::OnRemoveTableRowsCommand ()
6692 Led_Require_CurrentOwningWP ();
6693 AllowUpdateInfoPropagationContext AUIPC (*
this);
6694 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6695 BreakInGroupedCommands ();
6696 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fRemoveTableRowsCommandName,
false);
6698 size_t rowSelStart = 0;
6699 size_t rowSelEnd = 0;
6700 size_t colSelStart = 0;
6701 size_t colSelEnd = 0;
6702 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6703 if (colSelStart == 0 and colSelEnd == GetColumnCount (rowSelStart, rowSelEnd)) {
6704 if (rowSelStart == 0 and rowSelEnd == GetRowCount ()) {
6705 fCurrentOwningWP->OnClearCommand ();
6708 size_t nRowsToDelete = rowSelEnd - rowSelStart;
6709 while (nRowsToDelete > 0) {
6710 DeleteRow (rowSelStart);
6715 fCurrentOwningWP->OnBadUserInput ();
6718 context.CommandComplete ();
6721void WordProcessorTable::OnUpdateRemoveTableColumnsCommand (TextInteractor::CommandUpdater* pCmdUI)
6723 Led_Require_CurrentOwningWP ();
6725 size_t rowSelStart = 0;
6726 size_t rowSelEnd = 0;
6727 size_t colSelStart = 0;
6728 size_t colSelEnd = 0;
6729 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6730 pCmdUI->SetEnabled (rowSelStart == 0 and rowSelEnd == GetRowCount ());
6733void WordProcessorTable::OnRemoveTableColumnsCommand ()
6735 Led_Require_CurrentOwningWP ();
6736 AllowUpdateInfoPropagationContext AUIPC (*
this);
6737 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6738 BreakInGroupedCommands ();
6739 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fRemoveTableColumnsCommandName,
false);
6741 size_t rowSelStart = 0;
6742 size_t rowSelEnd = 0;
6743 size_t colSelStart = 0;
6744 size_t colSelEnd = 0;
6745 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6746 if (rowSelStart == 0 and rowSelEnd == GetRowCount ()) {
6747 if (colSelStart == 0 and colSelEnd == GetColumnCount ()) {
6748 fCurrentOwningWP->OnClearCommand ();
6751 size_t nColsToDelete = colSelEnd - colSelStart;
6752 while (nColsToDelete > 0) {
6753 DeleteColumn (colSelStart);
6758 fCurrentOwningWP->OnBadUserInput ();
6761 context.CommandComplete ();
6762 BreakInGroupedCommands ();
6765void WordProcessorTable::OnUpdateSelectTablePartsCommand (TextInteractor::CommandUpdater* enabler)
6767 switch (enabler->GetCmdID ()) {
6768 case WordProcessor::kSelectTableIntraCellAll_CmdID: {
6769 enabler->SetEnabled (GetIntraCellMode ());
6771 case WordProcessor::kSelectTableCell_CmdID: {
6772 enabler->SetEnabled (GetIntraCellMode ());
6774 case WordProcessor::kSelectTableRow_CmdID: {
6775 size_t rowSelStart = 0;
6776 size_t rowSelEnd = 0;
6777 size_t colSelStart = 0;
6778 size_t colSelEnd = 0;
6779 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6780 size_t maxColSelEnd = GetColumnCount (rowSelStart, rowSelEnd);
6781 enabler->SetEnabled (colSelStart != 0 or colSelEnd != maxColSelEnd);
6783 case WordProcessor::kSelectTableColumn_CmdID: {
6784 size_t rowSelStart = 0;
6785 size_t rowSelEnd = 0;
6786 size_t colSelStart = 0;
6787 size_t colSelEnd = 0;
6788 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6789 enabler->SetEnabled (rowSelStart != 0 or rowSelEnd != GetRowCount ());
6791 case WordProcessor::kSelectTable_CmdID: {
6792 size_t rowSelStart = 0;
6793 size_t rowSelEnd = 0;
6794 size_t colSelStart = 0;
6795 size_t colSelEnd = 0;
6796 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6797 enabler->SetEnabled (rowSelStart != 0 or colSelStart != 0 or rowSelEnd != GetRowCount () or colSelEnd != GetColumnCount ());
6802void WordProcessorTable::OnPerformTablePartsCommand (TextInteractor::CommandNumber commandNumber)
6804 switch (commandNumber) {
6805 case WordProcessor::kSelectTableIntraCellAll_CmdID: {
6808 if (GetIntraCellMode (&row, &col)) {
6809 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6810 wp->OnPerformCommand (TextInteractor::kSelectAll_CmdID);
6816 case WordProcessor::kSelectTableCell_CmdID: {
6817 UnSetIntraCellMode ();
6819 case WordProcessor::kSelectTableRow_CmdID: {
6820 size_t rowSelStart = 0;
6821 size_t rowSelEnd = 0;
6822 size_t colSelStart = 0;
6823 size_t colSelEnd = 0;
6824 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6826 colSelEnd = GetColumnCount (rowSelStart, rowSelEnd);
6827 SetCellSelection (rowSelStart, rowSelEnd, colSelStart, colSelEnd);
6829 case WordProcessor::kSelectTableColumn_CmdID: {
6830 size_t rowSelStart = 0;
6831 size_t rowSelEnd = 0;
6832 size_t colSelStart = 0;
6833 size_t colSelEnd = 0;
6834 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6836 rowSelEnd = GetRowCount ();
6837 SetCellSelection (rowSelStart, rowSelEnd, colSelStart, colSelEnd);
6839 case WordProcessor::kSelectTable_CmdID: {
6840 SetCellSelection (0, GetRowCount (), 0, GetColumnCount ());
6845void WordProcessorTable::AssureCurSelFontCacheValid (IncrementalFontSpecification* curSelFontSpec)
6851 if (GetIntraCellMode (&row, &col)) {
6852 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6853 *curSelFontSpec = wp->GetCurSelFontSpec ();
6858 size_t rowSelStart = 0;
6859 size_t rowSelEnd = 0;
6860 size_t colSelStart = 0;
6861 size_t colSelEnd = 0;
6862 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6863 for (
size_t ri = rowSelStart; ri < rowSelEnd; ++ri) {
6864 size_t thisRowEnd = min (colSelEnd, GetColumnCount (ri));
6865 for (
size_t ci = colSelStart; ci < thisRowEnd; ++ci) {
6866 TemporarilyAllocateCellWithTablet wp (*
this, ri, ci);
6867 wp->SetSelection (0, wp->GetEnd (), TextInteractor::eNoUpdate);
6868 IncrementalFontSpecification iSpec = wp->GetCurSelFontSpec ();
6869 if (ri == rowSelStart and ci == colSelStart) {
6870 *curSelFontSpec = iSpec;
6873 *curSelFontSpec =
Intersection (*curSelFontSpec, iSpec);
6883void WordProcessorTable::InteractiveSetFont (
const IncrementalFontSpecification& defaultFont)
6885 Led_Require_CurrentOwningWP ();
6891 if (GetIntraCellMode (&row, &col)) {
6892 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6893 wp->InteractiveSetFont (defaultFont);
6898 AllowUpdateInfoPropagationContext AUIPC (*
this);
6900 fCurrentOwningWP->BreakInGroupedCommands ();
6901 UndoableContextHelper undoContext (*fCurrentOwningWP, StandardStyledTextInteractor::GetCommandNames ().fFontChangeCommandName,
false);
6903 size_t rowSelStart = 0;
6904 size_t rowSelEnd = 0;
6905 size_t colSelStart = 0;
6906 size_t colSelEnd = 0;
6907 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6908 for (
size_t ri = rowSelStart; ri < rowSelEnd; ++ri) {
6909 size_t thisRowEnd = min (colSelEnd, GetColumnCount (ri));
6910 for (
size_t ci = colSelStart; ci < thisRowEnd; ++ci) {
6911 TemporarilyAllocateCellWithTablet wp (*
this, ri, ci);
6912 wp->SetStyleInfo (0, wp->GetEnd (), defaultFont);
6916 undoContext.CommandComplete ();
6919void WordProcessorTable::Write ([[maybe_unused]] SinkStream& sink)
6924void WordProcessorTable::ExternalizeFlavors ([[maybe_unused]]
WriterFlavorPackage& flavorPackage)
6932const char* WordProcessorTable::GetTag ()
const
6943bool WordProcessorTable::ProcessSimpleClick (Led_Point clickedAt,
unsigned clickCount,
bool extendSelection)
6946 DbgTrace (
"ENTERING WordProcessorTable::ProcessSimpleClick (this= 0x%x, clickedAt=(%d,%d), clickCount=%d, rowSelStart=%d, rowSelEnd=%d, colSelStart=%d, colSelEnd=%d, intraCellMode=%d intraCellStart=%d, intraCellEnd=%d)\n",
6947 this, clickedAt.v, clickedAt.h, clickCount, fRowSelStart, fRowSelEnd, fColSelStart, fColSelEnd, fIntraCellMode, fIntraSelStart, fIntraSelStart
6950 Led_Require_CurrentOwningWP ();
6952 size_t clickRow = 0;
6953 size_t clickCol = 0;
6954 GetClosestCell (clickedAt, &clickRow, &clickCol);
6956 fTrackingAnchor_Row = clickRow;
6957 fTrackingAnchor_Col = clickCol;
6959 bool forceSelectAllCells =
false;
6960 if (extendSelection) {
6961 size_t selStart = fCurrentOwningWP->GetSelectionStart ();
6962 size_t selEnd = fCurrentOwningWP->GetSelectionEnd ();
6963 selStart = min (selStart, GetStart ());
6964 selEnd = max (selEnd, GetEnd ());
6965 forceSelectAllCells = (selEnd - selStart != 1);
6966 fCurrentOwningWP->SetSelection (selStart, selEnd);
6969 fCurrentOwningWP->SetSelection (GetStart (), GetEnd ());
6972 if (forceSelectAllCells) {
6973 SetCellSelection (0, GetRowCount (), 0, GetColumnCount ());
6975 else if (extendSelection) {
6976 size_t rowSelStart = 0;
6977 size_t rowSelEnd = 0;
6978 size_t colSelStart = 0;
6979 size_t colSelEnd = 0;
6980 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6981 rowSelStart = min (rowSelStart, clickRow);
6982 rowSelEnd = max (rowSelEnd, clickRow + 1);
6983 colSelStart = min (colSelStart, clickCol);
6984 colSelEnd = max (colSelEnd, clickCol + 1);
6985 SetCellSelection (rowSelStart, rowSelEnd, colSelStart, colSelEnd);
6988 SetCellSelection (clickRow, clickRow + 1, clickCol, clickCol + 1);
6992 size_t rowSelStart = 0;
6993 size_t rowSelEnd = 0;
6994 size_t colSelStart = 0;
6995 size_t colSelEnd = 0;
6996 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6997 if (rowSelEnd - rowSelStart == 1 and colSelEnd - colSelStart == 1) {
6998 Led_Rect cellBounds = GetCellBounds (rowSelStart, colSelStart);
6999 Led_Rect cellEditorBounds = GetCellEditorBounds (rowSelStart, colSelStart);
7003 if (cellEditorBounds.Contains (clickedAt)) {
7004 SetIntraCellMode ();
7007 TemporarilyAllocateCellWithTablet wp (*
this, rowSelStart, colSelStart);
7008 wp->SetCurClickCount (fCurrentOwningWP->GetCurClickCount (), Time::GetTickCount ());
7009 Assert (fCurrentOwningWP->GetCurClickCount () == clickCount);
7010 wp->ProcessSimpleClick (TableCoordinates2Window (clickedAt), clickCount, extendSelection, &fIntraCellDragAnchor);
7013 UnSetIntraCellMode ();
7018 DbgTrace (
"EXITING WordProcessorTable::ProcessSimpleClick (this= 0x%x, rowSelStart=%d, rowSelEnd=%d, colSelStart=%d, colSelEnd=%d, intraCellMode=%d intraCellStart=%d, intraCellEnd=%d)\n",
7019 this, fRowSelStart, fRowSelEnd, fColSelStart, fColSelEnd, fIntraCellMode, fIntraSelStart, fIntraSelStart
7025void WordProcessorTable::WhileSimpleMouseTracking (Led_Point newMousePos)
7028 DbgTrace (
"ENTERING WordProcessorTable::WhileSimpleMouseTracking (this= 0x%x, rowSelStart=%d, rowSelEnd=%d, colSelStart=%d, colSelEnd=%d, intraCellMode=%d intraCellStart=%d, intraCellEnd=%d)\n",
7029 this, fRowSelStart, fRowSelEnd, fColSelStart, fColSelEnd, fIntraCellMode, fIntraSelStart, fIntraSelStart
7032 Led_Require_CurrentOwningWP ();
7034 if (fCurrentOwningWP->GetSelectionEnd () - fCurrentOwningWP->GetSelectionStart () == 1) {
7038 size_t clickRow = 0;
7039 size_t clickCol = 0;
7040 GetClosestCell (newMousePos, &clickRow, &clickCol);
7042 size_t rowSelStart = min (fTrackingAnchor_Row, clickRow);
7043 size_t rowSelEnd = max (fTrackingAnchor_Row + 1, clickRow + 1);
7044 size_t colSelStart = min (fTrackingAnchor_Col, clickCol);
7045 size_t colSelEnd = max (fTrackingAnchor_Col + 1, clickCol + 1);
7046 SetCellSelection (rowSelStart, rowSelEnd, colSelStart, colSelEnd);
7048 else if (fCurrentOwningWP->GetSelectionEnd () - fCurrentOwningWP->GetSelectionStart () > 1) {
7049 SetCellSelection (0, GetRowCount (), 0, GetColumnCount ());
7053 size_t rowSelStart = 0;
7054 size_t rowSelEnd = 0;
7055 size_t colSelStart = 0;
7056 size_t colSelEnd = 0;
7057 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
7058 if (rowSelEnd - rowSelStart == 1 and colSelEnd - colSelStart == 1) {
7059 Led_Rect cellBounds = GetCellBounds (rowSelStart, colSelStart);
7060 Led_Rect cellEditorBounds = GetCellEditorBounds (rowSelStart, colSelStart);
7064 if (cellEditorBounds.Contains (newMousePos)) {
7065 if (fTrackingAnchor_Row == rowSelStart and rowSelStart + 1 == rowSelEnd and fTrackingAnchor_Col == colSelStart and
7066 colSelStart + 1 == colSelEnd) {
7070 SetIntraCellMode ();
7073 TemporarilyAllocateCellWithTablet wp (*
this, rowSelStart, colSelStart);
7074 wp->SetCurClickCount (fCurrentOwningWP->GetCurClickCount (), Time::GetTickCount ());
7075 wp->WhileSimpleMouseTracking (TableCoordinates2Window (newMousePos), fIntraCellDragAnchor);
7080 DbgTrace (
"EXITING WordProcessorTable::WhileSimpleMouseTracking (this= 0x%x, rowSelStart=%d, rowSelEnd=%d, colSelStart=%d, colSelEnd=%d, intraCellMode=%d intraCellStart=%d, intraCellEnd=%d)\n",
7081 this, fRowSelStart, fRowSelEnd, fColSelStart, fColSelEnd, fIntraCellMode, fIntraSelStart, fIntraSelStart
7091void WordProcessorTable::GetRealCell (
size_t* row,
size_t* column)
const
7098 CellMergeFlags flags = GetCell (r, c).GetCellMergeFlags ();
7099 if (flags == ePlainCell) {
7105#if qStroika_Foundation_Debug_AssertionsChecked
7106 bool changed =
false;
7108 if (flags & eMergeCellLeft) {
7111#if qStroika_Foundation_Debug_AssertionsChecked
7115 if (flags & eMergeCellUp) {
7118#if qStroika_Foundation_Debug_AssertionsChecked
7122#if qStroika_Foundation_Debug_AssertionsChecked
7129const WordProcessorTable::Cell& WordProcessorTable::GetRealCell (
size_t row,
size_t column)
const
7131 GetRealCell (&row, &column);
7132 return GetCell (row, column);
7135bool WordProcessorTable::CanMergeCells (
size_t fromRow,
size_t fromCol, [[maybe_unused]]
size_t toRow, [[maybe_unused]]
size_t toCol)
7137 Require (fromRow <= toRow);
7138 Require (fromCol <= toCol);
7139 Require (toRow <= GetRowCount ());
7140 Require (toCol <= GetColumnCount ());
7143 return GetCellFlags (fromRow, fromCol) == ePlainCell;
7160void WordProcessorTable::MergeCells (
size_t fromRow,
size_t fromCol,
size_t toRow,
size_t toCol)
7162 Require (fromRow <= toRow);
7163 Require (fromCol <= toCol);
7164 Require (toRow <= GetRowCount ());
7165 Require (toCol <= GetColumnCount ());
7166 Require (CanMergeCells (fromRow, fromCol, toRow, toCol));
7167 bool madeChange =
false;
7168 for (
size_t r = fromRow; r < toRow; ++r) {
7169 for (
size_t c = fromCol; c < toCol; ++c) {
7171 if (not(r == fromRow and c == fromCol)) {
7172 fRows[r].fCells[c] =
7173 Cell (*
this,
static_cast<CellMergeFlags
> (((r > fromRow) ? eMergeCellUp : 0) | ((c > fromCol) ? eMergeCellLeft : 0)));
7179 InvalidateLayout ();
7183void WordProcessorTable::UnMergeCells (
size_t fromRow,
size_t fromCol,
size_t toRow,
size_t toCol)
7185 Require (fromRow <= toRow);
7186 Require (fromCol <= toCol);
7187 Require (toRow < GetRowCount ());
7188 Require (toCol < GetColumnCount ());
7189 bool madeChange =
false;
7190 for (
size_t r = fromRow; r < toRow; ++r) {
7191 for (
size_t c = fromCol; c < toCol; ++c) {
7193 if (GetCellFlags (r, c) != ePlainCell) {
7194 fRows[r].fCells[c] = Cell (*
this, ePlainCell);
7200 InvalidateLayout ();
7208void WordProcessorTable::SetCellSelection (
size_t rowSelStart,
size_t rowSelEnd,
size_t colSelStart,
size_t colSelEnd)
7210 Ensure (rowSelStart <= rowSelEnd);
7211 Ensure (rowSelEnd <= GetRowCount ());
7212 Ensure (colSelStart <= colSelEnd);
7213 Ensure (colSelEnd <= GetColumnCount ());
7214 bool changed = (fRowSelStart != rowSelStart) or (fRowSelEnd != rowSelEnd) or (fColSelStart != colSelStart) or (fColSelEnd != colSelEnd);
7216 fRowSelStart = rowSelStart;
7217 fRowSelEnd = rowSelEnd;
7218 fColSelStart = colSelStart;
7219 fColSelEnd = colSelEnd;
7220 fIntraCellMode =
false;
7221 InvalidateIntraCellContextInfo ();
7222 if (fCurrentOwningWP !=
nullptr) {
7223 fCurrentOwningWP->fCachedCurSelFontSpecValid =
false;
7224 fCurrentOwningWP->Refresh (GetStart (), GetEnd ());
7228 DbgTrace (
"WordProcessorTable::SetCellSelection (table=0x%x, tickCount=%f, rs=%d, re=%d, cs=%d, ce=%d, changed=%d)\n",
7229 this, Time::GetTickCount (), rowSelStart, rowSelEnd, colSelStart, colSelEnd, changed
7234void WordProcessorTable::SetIntraCellMode ()
7236 Require (fRowSelEnd - fRowSelStart == 1);
7237 Require (fColSelEnd - fColSelStart == 1);
7238 if (not fIntraCellMode) {
7239 TextStore* ts =
nullptr;
7240 GetCellWordProcessorDatabases (fRowSelStart, fColSelStart, &ts);
7242 SetIntraCellSelection (0, ts->GetLength ());
7243 fIntraCellMode =
true;
7244 if (fCurrentOwningWP !=
nullptr) {
7245 fCurrentOwningWP->Refresh (GetStart (), GetEnd ());
7250void WordProcessorTable::SetIntraCellMode (
size_t row,
size_t col)
7252 if (not fIntraCellMode) {
7253 SetCellSelection (row, row + 1, col, col + 1);
7254 SetIntraCellMode ();
7258void WordProcessorTable::UnSetIntraCellMode ()
7260 if (fIntraCellMode) {
7261 fIntraCellMode =
false;
7262 if (fCurrentOwningWP !=
nullptr) {
7263 fCurrentOwningWP->Refresh (GetStart (), GetEnd ());
7268void WordProcessorTable::SetIntraCellSelection (
size_t selStart,
size_t selEnd)
7270 if (fIntraSelStart != selStart or fIntraSelEnd != selEnd) {
7272 DbgTrace (
"WordProcessorTable::SetIntraCellSelection (selStart = %d, selEnd = %d)- oldSel=(%d,%d), tickcount=%f\n", selStart, selEnd, fIntraSelStart, fIntraSelEnd, Time::GetTickCount ());
7274 if (fCurrentOwningWP !=
nullptr) {
7275 fCurrentOwningWP->fCachedCurSelFontSpecValid =
false;
7277 fIntraSelStart = selStart;
7278 fIntraSelEnd = selEnd;
7290WordProcessorTable::EmbeddedTableWordProcessor* WordProcessorTable::ConstructEmbeddedTableWordProcessor (WordProcessor& forWordProcessor,
7291 size_t forRow,
size_t forColumn,
7292 const Led_Rect& cellWindowRect,
7293 bool captureChangesForUndo)
7295 size_t cellModeRow = 0;
7296 size_t cellModeCol = 0;
7297 bool activeFocusedCell = GetIntraCellMode (&cellModeRow, &cellModeCol) and cellModeRow == forRow and cellModeCol == forColumn;
7298 EmbeddedTableWordProcessor* e =
new EmbeddedTableWordProcessor (forWordProcessor, *
this, forRow, forColumn, activeFocusedCell);
7300 TextStore* ts =
nullptr;
7301 shared_ptr<AbstractStyleDatabaseRep> styleDatabase;
7302 shared_ptr<AbstractParagraphDatabaseRep> paragraphDatabase;
7303 shared_ptr<HidableTextMarkerOwner> hidableTextDatabase;
7304 GetCellWordProcessorDatabases (forRow, forColumn, &ts, &styleDatabase, ¶graphDatabase, &hidableTextDatabase);
7305 e->SetStyleDatabase (styleDatabase);
7306 e->SetParagraphDatabase (paragraphDatabase);
7307 e->SetHidableTextDatabase (hidableTextDatabase);
7308 e->SpecifyTextStore (ts);
7309 e->SetWindowRect (cellWindowRect);
7310 e->SetDefaultTextColor (WordProcessor::eDefaultBackgroundColor, GetCellColor (forRow, forColumn));
7311 if (captureChangesForUndo) {
7312 e->SetCommandHandler (forWordProcessor.GetCommandHandler ());
7315 if (activeFocusedCell) {
7316 using TemporarilyUseTablet = EmbeddedTableWordProcessor::TemporarilyUseTablet;
7319 WordProcessor::Tablet_Acquirer tablet (fCurrentOwningWP);
7320 TemporarilyUseTablet tmpUseTablet (*e, tablet, TemporarilyUseTablet::eDontDoTextMetricsChangedCall);
7322 e->SetSelectionShown (
true, TextInteractor::eNoUpdate);
7323 e->RestoreMiscActiveFocusInfo ();
7327 e->SpecifyTextStore (
nullptr);
7341void WordProcessorTable::ReleaseEmbeddedTableWordProcessor (EmbeddedTableWordProcessor* e)
7344 e->SaveMiscActiveFocusInfo ();
7345 e->SetCommandHandler (
nullptr);
7346 e->SpecifyTextStore (
nullptr);
7355void WordProcessorTable::PerformLayout ()
7357 Require (fNeedLayout != eDone);
7359 if (fCurrentOwningWP !=
nullptr) {
7360 TextStore& ts = GetOwner ()->GetTextStore ();
7361 TextStore::SimpleUpdater updater (ts, GetStart (), GetEnd (),
false);
7363 Led_Size border = Led_Size (Led_CvtScreenPixelsFromTWIPSV (fBorderWidth), Led_CvtScreenPixelsFromTWIPSH (fBorderWidth));
7364 DistanceType spacing = Led_CvtScreenPixelsFromTWIPSV (GetCellSpacing ());
7365 Led_Rect defaultCellMargin;
7367 TWIPS_Rect defaultCellMarginTWIPS;
7368 GetDefaultCellMargins (&defaultCellMarginTWIPS.top, &defaultCellMarginTWIPS.left, &defaultCellMarginTWIPS.bottom,
7369 &defaultCellMarginTWIPS.right);
7370 defaultCellMargin.top = Led_CvtScreenPixelsFromTWIPSV (defaultCellMarginTWIPS.top);
7371 defaultCellMargin.left = Led_CvtScreenPixelsFromTWIPSH (defaultCellMarginTWIPS.left);
7372 defaultCellMargin.bottom = Led_CvtScreenPixelsFromTWIPSV (defaultCellMarginTWIPS.bottom);
7373 defaultCellMargin.right = Led_CvtScreenPixelsFromTWIPSH (defaultCellMarginTWIPS.right);
7379 size_t rows = GetRowCount ();
7381 Tablet_Acquirer tablet (fCurrentOwningWP);
7383 DistanceType maxTableWidth = 0;
7385 DistanceType runningHeight = 0;
7386 for (
size_t r = 0; r < rows; ++r) {
7390 size_t cols = GetColumnCount (r);
7392 DistanceType rowWidth = 0;
7394 size_t lastRealCellIdx = 0;
7395 for (
size_t c = 0; c < cols; ++c) {
7396 DistanceType thisColWidth = Led_CvtScreenPixelsFromTWIPSH (GetColumnWidth (r, c));
7397 if (GetCellFlags (r, c) == ePlainCell) {
7398 realCellWidths[c] = thisColWidth;
7399 lastRealCellIdx = c;
7400 rowWidth += thisColWidth;
7404 realCellWidths[lastRealCellIdx] += thisColWidth;
7412 DistanceType rowHeight = 0;
7413 for (
size_t c = 0; c < cols; ++c) {
7414 if (GetCellFlags (r, c) == ePlainCell) {
7415 using TemporarilyUseTablet = EmbeddedTableWordProcessor::TemporarilyUseTablet;
7417 DistanceType totalCellMargin = defaultCellMargin.left + defaultCellMargin.right;
7418 DistanceType wpWidth = (totalCellMargin < realCellWidths[c]) ? realCellWidths[c] - totalCellMargin : 1;
7419 TemporarilyAllocateCellWP wp (*
this, *fCurrentOwningWP, r, c, Led_Rect (0, 0, 1000, wpWidth));
7420 TemporarilyUseTablet tmpUseTablet (*wp, tablet, TemporarilyUseTablet::eDontDoTextMetricsChangedCall);
7421 rowHeight = max (rowHeight, wp->GetDesiredHeight ());
7428 rowHeight += defaultCellMargin.top + defaultCellMargin.bottom;
7429 rowHeight = max (rowHeight, DistanceType (5));
7430 fRows[r].fHeight = rowHeight;
7431 runningHeight += rowHeight;
7433 DistanceType rowWidthWithSpacingNBorders = rowWidth +
static_cast<DistanceType
> ((cols + 1) * (spacing + border.h));
7434 maxTableWidth = max (maxTableWidth, rowWidthWithSpacingNBorders);
7440 DistanceType runningWidth = 0;
7441 size_t lastRealCellIdx = 0;
7442 for (
size_t c = 0; c < cols; ++c) {
7443 if (GetCellFlags (r, c) == ePlainCell) {
7444 Cell cell = GetCell (r, c);
7445 Led_Rect cellRect = Led_Rect (runningHeight - rowHeight, runningWidth, rowHeight, realCellWidths[c]);
7448 Led_Point (
static_cast<CoordinateType
> ((r + 1) * border.v),
static_cast<CoordinateType
> ((c + 1) * border.h));
7451 cellRect += Led_Point (
static_cast<CoordinateType
> ((r + 1) * spacing),
static_cast<CoordinateType
> ((c + 1) * spacing));
7453 cell.SetCachedBoundsRect (cellRect);
7454 lastRealCellIdx = c;
7455 runningWidth += realCellWidths[c];
7462 DistanceType totalHeight = 0;
7463 for (
auto i = fRows.begin (); i != fRows.end (); ++i) {
7464 totalHeight += (*i).fHeight;
7466 fTotalHeight = totalHeight +
static_cast<DistanceType
> ((spacing + border.v) * (fRows.size () + 1));
7469 fTotalWidth = maxTableWidth;
7471 fNeedLayout = eDone;
7482void WordProcessorTable::GetDimensions (
size_t* rows,
size_t* columns)
const
7484 if (rows !=
nullptr) {
7485 *rows = fRows.size ();
7487 if (columns !=
nullptr) {
7489 for (
size_t ri = 0; ri < fRows.size (); ++ri) {
7490 maxCols = max (maxCols, fRows[ri].fCells.size ());
7503void WordProcessorTable::SetDimensions (
size_t rows,
size_t columns)
7506 size_t oldColumns = 0;
7507 GetDimensions (&oldRows, &oldColumns);
7510 while (oldRows > rows) {
7511 DeleteRow (oldRows - 1);
7514 while (oldColumns > columns) {
7515 DeleteColumn (oldColumns - 1);
7520 while (oldRows < rows) {
7521 InsertRow (oldRows);
7524 while (oldColumns < columns) {
7525 InsertColumn (oldColumns);
7529 GetDimensions (&oldRows, &oldColumns);
7530 Assert (oldRows == rows);
7531 Assert (oldColumns == columns);
7541void WordProcessorTable::SetDimensionsAtLeast (
size_t rows,
size_t columns)
7545 GetDimensions (&r, &c);
7547 c = max (columns, c);
7548 SetDimensions (r, c);
7558void WordProcessorTable::InsertRow (
size_t at,
size_t maxRowCopyCount)
7560 Require (at <= GetRowCount ());
7561 Require (maxRowCopyCount >= 1);
7562#if qStroika_Frameworks_Led_SupportGDI
7564 TextStore& ts = GetOwner ()->GetTextStore ();
7565 TextStore::SimpleUpdater updater (ts, GetStart (), GetEnd ());
7571 size_t rowToCopy = at > 0 ? at - 1 : at;
7572 size_t colCount = 0;
7573 if (rowToCopy < GetRowCount ()) {
7574 colCount = GetColumnCount (rowToCopy);
7576 colCount = min (colCount, maxRowCopyCount);
7578 for (
size_t c = 0; c < colCount; ++c) {
7579 Cell cell (*
this, ePlainCell);
7580 cell.SetCellXWidth (GetColumnWidth (rowToCopy, c));
7581 newRow.fCells.push_back (cell);
7584 fRows.insert (fRows.begin () + at, newRow);
7585#if qStroika_Frameworks_Led_SupportGDI
7587 InvalidateIntraCellContextInfo ();
7588 InvalidateLayout ();
7596void WordProcessorTable::DeleteRow (
size_t at)
7598 Require (at < GetRowCount ());
7599#if qStroika_Frameworks_Led_SupportGDI
7601 TextStore& ts = GetOwner ()->GetTextStore ();
7602 TextStore::SimpleUpdater updater (ts, GetStart (), GetEnd ());
7605 fRows.erase (fRows.begin () + at);
7606#if qStroika_Frameworks_Led_SupportGDI
7607 InvalidateIntraCellContextInfo ();
7608 InvalidateLayout ();
7609 ReValidateSelection ();
7618void WordProcessorTable::InsertColumn (
size_t at)
7620 Require (at <= GetColumnCount ());
7621#if qStroika_Frameworks_Led_SupportGDI
7622 TextStore& ts = GetOwner ()->GetTextStore ();
7623 TextStore::SimpleUpdater updater (ts, GetStart (), GetEnd ());
7624 TWIPS newColWidth = Led_CvtScreenPixelsToTWIPSH (100);
7626 TWIPS newColWidth = TWIPS (100);
7630 if (fRows.size () > 0) {
7631 size_t nColsInRow = GetColumnCount (0);
7633 if (at == nColsInRow and at > 0) {
7634 newColWidth = GetColumnWidth (0, at - 1);
7636 else if (at < nColsInRow) {
7637 newColWidth = GetColumnWidth (0, at);
7641 vector<Cell> newCol;
7642 for (
size_t r = 0; r < fRows.size (); ++r) {
7643 Cell cell (*
this, ePlainCell);
7644 cell.SetCellXWidth (newColWidth);
7645 newCol.push_back (cell);
7648 size_t rowCount = fRows.size ();
7649 for (
size_t ri = 0; ri < rowCount; ++ri) {
7650 vector<Cell>& rowCells = fRows[ri].fCells;
7651 rowCells.insert (rowCells.begin () + at, newCol[ri]);
7653#if qStroika_Frameworks_Led_SupportGDI
7655 InvalidateIntraCellContextInfo ();
7656 InvalidateLayout ();
7664void WordProcessorTable::DeleteColumn (
size_t at)
7666 Require (at < GetColumnCount ());
7669#if qStroika_Frameworks_Led_SupportGDI
7670 TextStore& ts = GetOwner ()->GetTextStore ();
7671 TextStore::SimpleUpdater updater (ts, GetStart (), GetEnd ());
7674 size_t rowCount = fRows.size ();
7675 for (
size_t ri = 0; ri < rowCount; ++ri) {
7676 vector<Cell>& rowCells = fRows[ri].fCells;
7677 if (at < rowCells.size ()) {
7678 rowCells.erase (rowCells.begin () + at);
7681#if qStroika_Frameworks_Led_SupportGDI
7682 InvalidateIntraCellContextInfo ();
7683 InvalidateLayout ();
7684 ReValidateSelection ();
7687#if qStroika_Frameworks_Led_SupportGDI
7695void WordProcessorTable::ReValidateSelection ()
7697 size_t rowCount = GetRowCount ();
7699 size_t rowSelStart = fRowSelStart;
7700 size_t rowSelEnd = fRowSelEnd;
7701 size_t colSelStart = fColSelStart;
7702 size_t colSelEnd = fColSelEnd;
7704 if (rowSelStart >= rowCount) {
7708 if (rowSelEnd > rowCount) {
7709 rowSelEnd = rowCount;
7711 size_t colCount = GetColumnCount (rowSelStart, rowSelEnd);
7712 if (colSelStart >= colCount) {
7716 if (colSelEnd >= colCount) {
7717 colSelEnd = colCount;
7719 SetCellSelection (rowSelStart, rowSelEnd, colSelStart, colSelEnd);
7732WordProcessorTable::EmbeddedTableWordProcessor::EmbeddedTableWordProcessor (WordProcessor& owningWordProcessor, WordProcessorTable& owningTable,
7733 size_t tRow,
size_t tCol,
bool activeEditCell)
7735 , fOwningWordProcessor (owningWordProcessor)
7736 , fOwningTable (owningTable)
7738 , fTableColumn (tCol)
7739 , fUpdateTablet (nullptr)
7740 , fDesiredHeight (0)
7741 , fDesiredHeightValid (false)
7742 , fActiveEditCell (activeEditCell)
7743 , fSuppressRefreshCalls (false)
7745 SetImageUsingOffscreenBitmaps (
false);
7748WordProcessorTable& WordProcessorTable::EmbeddedTableWordProcessor::GetOwningTable ()
const
7750 return fOwningTable;
7753WordProcessor& WordProcessorTable::EmbeddedTableWordProcessor::GetOwningWordProcessor ()
const
7755 return fOwningWordProcessor;
7758void WordProcessorTable::EmbeddedTableWordProcessor::SaveMiscActiveFocusInfo ()
7760 if (fActiveEditCell) {
7761 fOwningTable.SetIntraCellSelection (GetSelectionStart (), GetSelectionEnd ());
7762 fOwningTable.SaveIntraCellContextInfo (fLeftSideOfSelectionInteresting, GetEmptySelectionStyle ());
7766void WordProcessorTable::EmbeddedTableWordProcessor::RestoreMiscActiveFocusInfo ()
7768 if (fActiveEditCell) {
7769 DisableRefreshContext DFR (*
this);
7770 SuppressCellUpdatePropagationContext SCUP (fOwningTable);
7773 bool leftSideOfSelectionInteresting =
false;
7774 if (fOwningTable.RestoreIntraCellContextInfo (&leftSideOfSelectionInteresting, &emptySelFont)) {
7775 size_t intraCellSelStart = 0;
7776 size_t intraCellSelEnd = 0;
7777 fOwningTable.GetIntraCellSelection (&intraCellSelStart, &intraCellSelEnd);
7778 SetSelection (intraCellSelStart, intraCellSelEnd, TextInteractor::eNoUpdate);
7779 fLeftSideOfSelectionInteresting = leftSideOfSelectionInteresting;
7780 SetEmptySelectionStyle (emptySelFont);
7783 SetEmptySelectionStyle ();
7788#if !qStroika_Frameworks_Led_NestedTablesSupported
7789void WordProcessorTable::EmbeddedTableWordProcessor::HookInternalizerChanged ()
7791 inherited::HookInternalizerChanged ();
7792 WordProcessorFlavorPackageInternalizer* internalizerRep =
7793 dynamic_cast<WordProcessorFlavorPackageInternalizer*
> (
static_cast<FlavorPackageInternalizer*
> (GetInternalizer ().get ()));
7795 internalizerRep->SetNoTablesAllowed (
true);
7799bool WordProcessorTable::EmbeddedTableWordProcessor::OnCopyCommand_Before ()
7801 return fOwningWordProcessor.OnCopyCommand_Before ();
7804void WordProcessorTable::EmbeddedTableWordProcessor::OnCopyCommand_After ()
7806 fOwningWordProcessor.OnCopyCommand_After ();
7809bool WordProcessorTable::EmbeddedTableWordProcessor::OnPasteCommand_Before ()
7811 return fOwningWordProcessor.OnPasteCommand_Before ();
7814void WordProcessorTable::EmbeddedTableWordProcessor::OnPasteCommand_After ()
7816 fOwningWordProcessor.OnPasteCommand_After ();
7819void WordProcessorTable::EmbeddedTableWordProcessor::DrawRowHilight (Tablet* ,
const Led_Rect& ,
const Led_Rect& ,
7820 const TextLayoutBlock& ,
size_t ,
size_t
7826Tablet* WordProcessorTable::EmbeddedTableWordProcessor::AcquireTablet ()
const
7828 if (fUpdateTablet !=
nullptr) {
7829 return fUpdateTablet;
7833 return fOwningWordProcessor.AcquireTablet ();
7836void WordProcessorTable::EmbeddedTableWordProcessor::ReleaseTablet (Tablet* tablet)
const
7838 if (tablet == fUpdateTablet) {
7843 fOwningWordProcessor.ReleaseTablet (tablet);
7846void WordProcessorTable::EmbeddedTableWordProcessor::RefreshWindowRect_ (
const Led_Rect& windowRectArea, UpdateMode updateMode)
const
7848 if (not fSuppressRefreshCalls) {
7852 UpdateMode useUpdateMode = (updateMode == eImmediateUpdate) ? eDelayedUpdate : updateMode;
7853 fOwningWordProcessor.RefreshWindowRect_ (windowRectArea, useUpdateMode);
7857void WordProcessorTable::EmbeddedTableWordProcessor::UpdateWindowRect_ (
const Led_Rect& )
const
7859 throw CannotUpdateNow ();
7862bool WordProcessorTable::EmbeddedTableWordProcessor::QueryInputKeyStrokesPending ()
const
7869void WordProcessorTable::EmbeddedTableWordProcessor::SetDefaultUpdateMode (UpdateMode defaultUpdateMode)
7871 if (defaultUpdateMode == eImmediateUpdate) {
7872 defaultUpdateMode = eDelayedUpdate;
7874 inherited::SetDefaultUpdateMode (defaultUpdateMode);
7877void WordProcessorTable::EmbeddedTableWordProcessor::GetLayoutMargins (RowReference row, CoordinateType* lhs, CoordinateType* rhs)
const
7879 if (rhs !=
nullptr) {
7880 inherited::GetLayoutMargins (row, lhs,
nullptr);
7889 if (rhs !=
nullptr) {
7890 *rhs = (max (CoordinateType (GetWindowRect ().GetWidth ()), CoordinateType (1)));
7894void WordProcessorTable::EmbeddedTableWordProcessor::PostInteractiveUndoPostHelper (InteractiveReplaceCommand::SavedTextRep** beforeRep,
7895 InteractiveReplaceCommand::SavedTextRep** afterRep,
7896 size_t startOfInsert,
const SDKString& cmdName)
7900 CommandHandler* ch = GetCommandHandler ();
7903 if (*beforeRep !=
nullptr and *afterRep !=
nullptr) {
7906 InteractiveReplaceCommand* cmd =
7907 new TableCMD (fOwningTable.GetStart (), fTableRow, fTableColumn, *beforeRep, *afterRep, startOfInsert, cmdName);
7908 *beforeRep =
nullptr;
7909 *afterRep =
nullptr;
7915 *beforeRep =
nullptr;
7917 *afterRep =
nullptr;
7922InteractiveReplaceCommand::SavedTextRep*
7923WordProcessorTable::EmbeddedTableWordProcessor::InteractiveUndoHelperMakeTextRep (
size_t regionStart,
size_t regionEnd,
size_t selStart,
size_t selEnd)
7925 InteractiveReplaceCommand::SavedTextRep* tableStateRep = inherited::InteractiveUndoHelperMakeTextRep (regionStart, regionEnd, selStart, selEnd);
7926 return new SavedTextRepWSel (tableStateRep, fOwningTable, SavedTextRepWSel::eWPDirect);
7929DistanceType WordProcessorTable::EmbeddedTableWordProcessor::GetDesiredHeight ()
const
7931 if (not fDesiredHeightValid) {
7932 RowReference startingRow = GetRowReferenceContainingPosition (0);
7933 RowReference endingRow = GetRowReferenceContainingPosition (GetEnd ());
7938 fDesiredHeightValid =
true;
7939 fDesiredHeight = GetHeightOfRows (startingRow, CountRowDifference (startingRow, endingRow) + 1);
7941 return fDesiredHeight;
7949WordProcessorTable::SavedTextRepWSel::SavedTextRepWSel (SavedTextRep* delegateTo, WordProcessorTable& table, WPRelativeFlag wPRelativeFlag)
7950 : inherited (table.GetStart (), table.GetEnd ())
7951 , fWPRelativeFlag (wPRelativeFlag)
7952 , fRealRep (delegateTo)
7957 , fIntraCellMode (false)
7958 , fIntraCellSelStart (0)
7959 , fIntraCellSelEnd (0)
7962 table.GetCellSelection (&fRowSelStart, &fRowSelEnd, &fColSelStart, &fColSelEnd);
7963 fIntraCellMode = table.GetIntraCellMode ();
7964 if (fIntraCellMode) {
7965 table.GetIntraCellSelection (&fIntraCellSelStart, &fIntraCellSelEnd);
7969size_t WordProcessorTable::SavedTextRepWSel::GetLength ()
const
7971 return fRealRep->GetLength ();
7974void WordProcessorTable::SavedTextRepWSel::InsertSelf (TextInteractor* interactor,
size_t at,
size_t nBytesToOverwrite)
7976 fRealRep->InsertSelf (interactor, at, nBytesToOverwrite);
7979void WordProcessorTable::SavedTextRepWSel::ApplySelection (TextInteractor* interactor)
7981 fRealRep->ApplySelection (interactor);
7983 WordProcessorTable* aT =
nullptr;
7984 if (fWPRelativeFlag == eWPDirect) {
7985 EmbeddedTableWordProcessor* wp =
dynamic_cast<EmbeddedTableWordProcessor*
> (interactor);
7986 aT = &wp->GetOwningTable ();
7989 WordProcessor* wp =
dynamic_cast<WordProcessor*
> (interactor);
7991 aT = wp->GetActiveTable ();
7996 aT->SetCellSelection (fRowSelStart, fRowSelEnd, fColSelStart, fColSelEnd);
7997 if (fIntraCellMode) {
7998 aT->SetIntraCellMode ();
7999 aT->SetIntraCellSelection (fIntraCellSelStart, fIntraCellSelEnd);
8002 aT->UnSetIntraCellMode ();
8011using EmptySelectionParagraphSavedTextRep = WordProcessor::EmptySelectionParagraphSavedTextRep;
8013EmptySelectionParagraphSavedTextRep::EmptySelectionParagraphSavedTextRep (WordProcessor* interactor,
size_t selStart,
size_t selEnd,
size_t at)
8014 : inherited (interactor, selStart, selEnd)
8015 , fSavedStyleInfo (interactor->GetParagraphDatabase ()->GetParagraphInfo (at))
8019void EmptySelectionParagraphSavedTextRep::InsertSelf (TextInteractor* interactor,
size_t at,
size_t nBytesToOverwrite)
8021 inherited::InsertSelf (interactor, at, nBytesToOverwrite);
8022 WordProcessor* wp =
dynamic_cast<WordProcessor*
> (interactor);
#define RequireMember(p, c)
#define qStroika_Foundation_Debug_AssertionsChecked
The qStroika_Foundation_Debug_AssertionsChecked flag determines if assertions are checked and validat...
#define RequireNotNull(p)
conditional_t< qStroika_Foundation_Memory_PreferBlockAllocation and andTrueCheck, BlockAllocationUseHelper< T >, Common::Empty > UseBlockAllocationIfAppropriate
Use this to enable block allocation for a particular class. Beware of subclassing.
set< T > Intersection(const set< T > &s1, const set< T > &s2)
time_point< RealtimeClock, DurationSeconds > TimePointSeconds
TimePointSeconds is a simpler approach to chrono::time_point, which doesn't require using templates e...
chrono::duration< double > DurationSeconds
chrono::duration<double> - a time span (length of time) measured in seconds, but high precision.
constexpr bool IsWhitespace() const noexcept
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
basic_string< SDKChar > SDKString
CONTAINER::value_type * Start(CONTAINER &c)
For a contiguous container (such as a vector or basic_string) - find the pointer to the start of the ...