4#include "Stroika/Frameworks/StroikaPreComp.h"
8#if qStroika_Foundation_Common_Platform_Windows
21#include "Stroika/Frameworks/Led/Config.h"
22#include "Stroika/Frameworks/Led/SimpleTextStore.h"
23#include "Stroika/Frameworks/Led/StyledTextEmbeddedObjects.h"
25#include "WordProcessor.h"
30using Memory::MakeSharedPtr;
32using namespace Stroika::Frameworks;
33using namespace Stroika::Frameworks::Led;
34using namespace Stroika::Frameworks::Led::StyledTextIO;
36#if qStroika_Frameworks_Led_SupportGDI
37using InteractiveModeUpdater = WordProcessor::InteractiveModeUpdater;
38using UndoableContextHelper = WordProcessor::UndoableContextHelper;
39using Tablet_Acquirer = WordProcessor::Tablet_Acquirer;
47ParagraphDatabaseRep::ParagraphDatabaseRep (TextStore& textStore)
48 : inheritedMC{textStore, GetStaticDefaultParagraphInfo ()}
50#if qStroika_Frameworks_Led_SupportGDI
53 SetPartition (MakeSharedPtr<WordProcessor::WPPartition> (GetTextStore (), *
this));
55 SetPartition (MakeSharedPtr<LineBasedPartition> (GetTextStore ()));
59void ParagraphDatabaseRep::SetPartition (
const shared_ptr<Partition>& partitionPtr)
61 if (fPartition != partitionPtr) {
62 fPartition = partitionPtr;
64 CheckMarkerBounaryConstraints (0, GetTextStore ().GetEnd ());
73ParagraphInfo ParagraphDatabaseRep::GetStaticDefaultParagraphInfo ()
76 const int kDefaultInches = 6;
77 defaultPi.SetMargins (TWIPS{0}, TWIPS (kDefaultInches * 1440));
78 defaultPi.SetJustification (eLeftJustify);
82const ParagraphInfo& ParagraphDatabaseRep::GetParagraphInfo (
size_t charAfterPos)
const
84 return GetInfo (charAfterPos);
87vector<pair<ParagraphInfo, size_t>> ParagraphDatabaseRep::GetParagraphInfo (
size_t charAfterPos,
size_t nTCharsFollowing)
const
89 return GetInfo (charAfterPos, nTCharsFollowing);
92void ParagraphDatabaseRep::SetParagraphInfo (
size_t charAfterPos,
size_t nTCharsFollowing,
const IncrementalParagraphInfo& infoForMarkers)
94 if (infoForMarkers.GetMargins_Valid ()) {
95 fCachedFarthestRightMarginInDocument = kBadCachedFarthestRightMarginInDocument;
97 SetInfo (charAfterPos, nTCharsFollowing, infoForMarkers);
100void ParagraphDatabaseRep::SetParagraphInfo (
size_t charAfterPos,
const vector<pair<IncrementalParagraphInfo, size_t>>& infoForMarkers)
102 for (
auto i = infoForMarkers.begin (); i != infoForMarkers.end (); ++i) {
103 if ((*i).first.GetMargins_Valid ()) {
104 fCachedFarthestRightMarginInDocument = kBadCachedFarthestRightMarginInDocument;
108 SetInfos (charAfterPos, infoForMarkers);
111void ParagraphDatabaseRep::SetParagraphInfo (
size_t charAfterPos,
const vector<pair<ParagraphInfo, size_t>>& infoForMarkers)
113 fCachedFarthestRightMarginInDocument = kBadCachedFarthestRightMarginInDocument;
114 SetInfos2 (charAfterPos, infoForMarkers);
122void ParagraphDatabaseRep::SetInfo (
size_t charAfterPos,
size_t nTCharsFollowing,
const IncrementalParagraphInfo& infoForMarkers)
124 Assert (fPartition.get () !=
nullptr);
125 inheritedMC::SetInfo (charAfterPos, nTCharsFollowing, infoForMarkers);
128void ParagraphDatabaseRep::SetInfos (
size_t charAfterPos,
const vector<pair<IncrementalParagraphInfo, size_t>>& infoForMarkers)
130 Assert (fPartition.get () !=
nullptr);
131 inheritedMC::SetInfos (charAfterPos, infoForMarkers);
141void ParagraphDatabaseRep::NoteCoverRangeDirtied (
size_t from,
size_t to,
const MarkerVector& rangeAndSurroundingsMarkers)
143 inheritedMC::NoteCoverRangeDirtied (from, to, rangeAndSurroundingsMarkers);
144 CheckMarkerBounaryConstraints (rangeAndSurroundingsMarkers);
147void ParagraphDatabaseRep::ConstrainSetInfoArgs (
size_t* charAfterPos,
size_t* nTCharsFollowing)
152 size_t from = *charAfterPos;
153 size_t to = from + *nTCharsFollowing;
154 PartitionMarker* startPara = fPartition->GetPartitionMarkerContainingPosition (from);
155 PartitionMarker* endPara = (to <= startPara->GetEnd ()) ? startPara : fPartition->GetPartitionMarkerContainingPosition (to);
158 if (startPara != endPara and endPara->GetStart () == to) {
159 endPara = endPara->GetPrevious ();
161 size_t bigFrom = startPara->GetStart ();
162 size_t bigEnd = min (endPara->GetEnd (), GetTextStore ().GetEnd () + 1);
164 *charAfterPos = bigFrom;
165 *nTCharsFollowing = bigEnd - bigFrom;
174void ParagraphDatabaseRep::CheckMarkerBounaryConstraints (
size_t from,
size_t to)
noexcept
176 if (fPartition.get () !=
nullptr) {
177 MarkerVector markers = CollectAllInRange_OrSurroundings (from, to);
178 sort (markers.begin (), markers.end (), LessThan<ParagraphInfoMarker> ());
179 CheckMarkerBounaryConstraints (markers);
183void ParagraphDatabaseRep::CheckMarkerBounaryConstraints (
const MarkerVector& rangeAndSurroundingsMarkers)
noexcept
189 if (fPartition.get () !=
nullptr) {
190 for (
auto i = rangeAndSurroundingsMarkers.begin (); i != rangeAndSurroundingsMarkers.end (); ++i) {
191 ParagraphInfoMarker* m = *i;
195 m->GetRange (&m_start, &m_end);
196 size_t m_length = m_end - m_start;
199 Assert (m->GetLength () == m_length);
201 Assert (m_start == m->GetStart ());
202 PartitionMarker* partitionElt = fPartition->GetPartitionMarkerContainingPosition (m_start);
203 Assert (partitionElt->GetStart () == m->GetStart ());
205 Assert (m->GetEnd () == m_end);
206 size_t partitionElt_end;
207 for (; (partitionElt_end = partitionElt->GetEnd ()) < m_end;) {
208 partitionElt = partitionElt->GetNext ();
211 Assert (partitionElt_end == partitionElt->GetEnd ());
236 Assert (m->GetEnd () == m_end);
237 if (partitionElt_end != m_end) {
238 MarkerVector markers = CollectAllNonEmptyInRange (m_end, m_end + 1);
239 Assert (markers.size () == 1);
240 ParagraphInfoMarker* followingMarker = markers[0];
241 Assert (m_end == followingMarker->GetStart ());
242 Assert (partitionElt_end == partitionElt->GetEnd ());
243 GetTextStore ().SetMarkerEnd (m, partitionElt_end);
244 Assert (followingMarker->GetEnd () >= partitionElt->GetEnd ());
245 Assert (partitionElt_end == partitionElt->GetEnd ());
246 GetTextStore ().SetMarkerStart (followingMarker, partitionElt_end);
248 if (followingMarker->GetLength () == 0) {
249 fMarkersToBeDeleted.AccumulateMarkerForDeletion (followingMarker);
250 Assert (partitionElt_end == m->GetEnd ());
251 CheckForMerges (partitionElt_end);
261 SetInfoInnerLoop (partitionElt->GetStart (), partitionElt->GetEnd (), followingInfo,
262 UpdateInfo (partitionElt->GetStart (), partitionElt->GetEnd (), LED_TCHAR_OF (
""), 0,
false,
false),
nullptr);
263 CullZerod (partitionElt->GetStart ());
264 CullZerod (partitionElt->GetEnd ());
271#if qStroika_Foundation_Debug_AssertionsChecked
272void ParagraphDatabaseRep::Invariant_ ()
const
274 inheritedMC::Invariant_ ();
277 if (fPartition.get () !=
nullptr) {
280 MarkerVector markers = CollectAllInRange_OrSurroundings (0, GetTextStore ().GetLength () + 1);
281 sort (markers.begin (), markers.end (), LessThan<ParagraphInfoMarker> ());
282 PartitionMarker* lastPartitionElt =
nullptr;
283 for (
auto i = markers.begin (); i != markers.end (); ++i) {
284 ParagraphInfoMarker* m = *i;
285 Assert (m->GetLength () != 0);
286 PartitionMarker* curPartitionElt = fPartition->GetPartitionMarkerContainingPosition (m->GetStart ());
287 Assert (curPartitionElt != lastPartitionElt);
288 Assert (curPartitionElt->GetStart () == m->GetStart ());
289 Assert (curPartitionElt->GetEnd () <= m->GetEnd ());
291 lastPartitionElt = curPartitionElt;
302#if qStroika_Frameworks_Led_SupportGDI
305 using inherited = InteractiveReplaceCommand;
308 TableCMD (
size_t tableAt,
size_t tRow,
size_t tCol, SavedTextRep* beforeRegion, SavedTextRep* afterRegion,
size_t at,
const SDKString& cmdName)
309 : inherited (beforeRegion, afterRegion, at, cmdName)
312 , fTableColumn (tCol)
317 virtual void Do (TextInteractor& interactor)
override
319 WordProcessor& owningWP =
dynamic_cast<WordProcessor&
> (interactor);
320 WordProcessorTable* aT = owningWP.GetTableAt (fTableAt);
322 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, owningWP);
323 WordProcessorTable::TemporarilyAllocateCellWithTablet wp (*aT, fTableRow, fTableColumn);
326 virtual void UnDo (TextInteractor& interactor)
override
328 WordProcessor& owningWP =
dynamic_cast<WordProcessor&
> (interactor);
329 WordProcessorTable* aT = owningWP.GetTableAt (fTableAt);
331 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, owningWP);
332 WordProcessorTable::TemporarilyAllocateCellWithTablet wp (*aT, fTableRow, fTableColumn);
333 inherited::UnDo (*wp);
335 virtual void ReDo (TextInteractor& interactor)
override
337 WordProcessor& owningWP =
dynamic_cast<WordProcessor&
> (interactor);
338 WordProcessorTable* aT = owningWP.GetTableAt (fTableAt);
340 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, owningWP);
341 WordProcessorTable::TemporarilyAllocateCellWithTablet wp (*aT, fTableRow, fTableColumn);
342 inherited::ReDo (*wp);
356#define Led_Require_CurrentOwningWP() RequireNotNull (fCurrentOwningWP)
363WordProcessorTable::WordProcessorTable (AbstractParagraphDatabaseRep* tableOwner,
size_t addAt)
365 FinalizeAddition (tableOwner, addAt);
368WordProcessorTable::~WordProcessorTable ()
370#if qStroika_Frameworks_Led_SupportGDI
371 if (fCellUpdatePropationUpdater !=
nullptr) {
374 fCellUpdatePropationUpdater->Cancel ();
375 delete fCellUpdatePropationUpdater;
377 Assert (fCurrentOwningWP ==
nullptr);
381void WordProcessorTable::FinalizeAddition (AbstractParagraphDatabaseRep* o,
size_t addAt)
384#if qStroika_Frameworks_Led_SupportGDI
385 TextStore& ts = o->GetTextStore ();
386 TextStore::SimpleUpdater updater (ts, addAt, addAt + 1);
387 ts.ReplaceWithoutUpdate (addAt, addAt, &kEmbeddingSentinelChar, 1);
388 ts.AddMarker (
this, addAt, 1, o);
392Color WordProcessorTable::GetTableBorderColor ()
const
397void WordProcessorTable::SetTableBorderColor (
Color c)
402TWIPS WordProcessorTable::GetTableBorderWidth ()
const
407void WordProcessorTable::SetTableBorderWidth (TWIPS w)
412TWIPS WordProcessorTable::GetColumnWidth (
size_t row,
size_t column)
const
414 if (GetCellFlags (row, column) != ePlainCell) {
418 return GetCell (row, column).GetCellXWidth ();
421void WordProcessorTable::SetColumnWidth (
size_t row,
size_t column, TWIPS colWidth)
423 GetCell (row, column).SetCellXWidth (colWidth);
424#if qStroika_Frameworks_Led_SupportGDI
429Color WordProcessorTable::GetCellColor (
size_t row,
size_t column)
const
431 return GetCell (row, column).GetBackColor ();
434void WordProcessorTable::SetCellColor (
size_t row,
size_t column,
const Color& c)
436 Cell cell = GetCell (row, column);
437 cell.SetBackColor (c);
440size_t WordProcessorTable::GetColumnCount (
size_t row)
const
442 Require (row < GetRowCount ());
443 return fRows[row].fCells.size ();
446size_t WordProcessorTable::GetColumnCount (
size_t rowStart,
size_t rowEnd)
const
448 Require (rowStart <= GetRowCount ());
449 Require (rowEnd <= GetRowCount ());
451 for (
size_t ri = rowStart; ri < rowEnd; ++ri) {
452 colCount = max (colCount, fRows[ri].fCells.size ());
457void WordProcessorTable::SetColumnCount (
size_t row,
size_t columns)
459 Require (row < GetRowCount ());
460 size_t curColCount = fRows[row].fCells.size ();
461 if (curColCount != columns) {
462 vector<Cell>& rowCells = fRows[row].fCells;
463 while (curColCount < columns) {
464 Cell cell (*
this, ePlainCell);
465 rowCells.push_back (cell);
468 while (curColCount > columns) {
470 rowCells.erase (rowCells.begin () + curColCount);
482void WordProcessorTable::GetCellWordProcessorDatabases (
size_t row,
size_t column, TextStore** ts, shared_ptr<AbstractStyleDatabaseRep>* styleDatabase,
483 shared_ptr<AbstractParagraphDatabaseRep>* paragraphDatabase,
484 shared_ptr<HidableTextMarkerOwner>* hidableTextDatabase)
486 Require (row < GetRowCount ());
487 Require (column < GetColumnCount (row));
488 const Cell& c = GetCell (row, column);
490 *ts = &c.GetTextStore ();
492 if (styleDatabase !=
nullptr) {
493 *styleDatabase = c.GetStyleDatabase ();
495 if (paragraphDatabase !=
nullptr) {
496 *paragraphDatabase = c.GetParagraphDatabase ();
498 if (hidableTextDatabase !=
nullptr) {
499 *hidableTextDatabase = c.GetHidableTextDatabase ();
508WordProcessorTable::Cell::Cell (WordProcessorTable& forTable, CellMergeFlags mergeFlags)
509 : fCellMergeFlags{mergeFlags}
510 , fCellRep{mergeFlags == ePlainCell ? (new CellRep (forTable)) : nullptr}
521void WordProcessorTable::Cell::GetCellWordProcessorDatabases (TextStore** ts, shared_ptr<AbstractStyleDatabaseRep>* styleDatabase,
522 shared_ptr<AbstractParagraphDatabaseRep>* paragraphDatabase,
523 shared_ptr<HidableTextMarkerOwner>* hidableTextDatabase)
525 Require (fCellMergeFlags == ePlainCell);
527 *ts = &GetTextStore ();
529 if (styleDatabase !=
nullptr) {
530 *styleDatabase = GetStyleDatabase ();
532 if (paragraphDatabase !=
nullptr) {
533 *paragraphDatabase = GetParagraphDatabase ();
535 if (hidableTextDatabase !=
nullptr) {
536 *hidableTextDatabase = GetHidableTextDatabase ();
540TextStore& WordProcessorTable::Cell::GetTextStore ()
const
542 Require (fCellMergeFlags == ePlainCell);
544 return *fCellRep->fTextStore;
547shared_ptr<AbstractStyleDatabaseRep> WordProcessorTable::Cell::GetStyleDatabase ()
const
549 Require (fCellMergeFlags == ePlainCell);
550 return fCellRep->fStyleDatabase;
553shared_ptr<AbstractParagraphDatabaseRep> WordProcessorTable::Cell::GetParagraphDatabase ()
const
555 Require (fCellMergeFlags == ePlainCell);
556 return fCellRep->fParagraphDatabase;
559shared_ptr<HidableTextMarkerOwner> WordProcessorTable::Cell::GetHidableTextDatabase ()
const
561 Require (fCellMergeFlags == ePlainCell);
562 return fCellRep->fHidableTextDatabase;
565Color WordProcessorTable::Cell::GetBackColor ()
const
567 Require (fCellMergeFlags == ePlainCell);
568 return fCellRep->fBackColor;
571void WordProcessorTable::Cell::SetBackColor (
Color c)
573 Require (fCellMergeFlags == ePlainCell);
574 fCellRep->fBackColor = c;
582WordProcessorTable::CellRep::CellRep (WordProcessorTable& forTable)
583 : fForTable (forTable)
584 , fTextStore (nullptr)
586 , fParagraphDatabase ()
587 , fHidableTextDatabase ()
588 , fBackColor (
Color::kWhite)
589 , fCachedBoundsRect (Led_Rect (0, 0, 0, 0))
590#if qStroika_Frameworks_Led_SupportGDI
591 , fCellXWidth (Led_CvtScreenPixelsToTWIPSH (75))
597 fTextStore =
new SimpleTextStore ();
598 fTextStore->AddMarkerOwner (
this);
599 fStyleDatabase = MakeSharedPtr<StyleDatabaseRep> (*fTextStore);
600 fParagraphDatabase = MakeSharedPtr<ParagraphDatabaseRep> (*fTextStore);
601 fHidableTextDatabase = MakeSharedPtr<UniformHidableTextMarkerOwner> (*fTextStore);
604WordProcessorTable::CellRep::~CellRep ()
606 Require (fStyleDatabase.use_count () == 1);
607 Require (fParagraphDatabase.use_count () == 1);
608 Require (fHidableTextDatabase.use_count () == 1);
609 fStyleDatabase.reset ();
610 fParagraphDatabase.reset ();
611 fHidableTextDatabase.reset ();
612 if (fTextStore !=
nullptr) {
613 fTextStore->RemoveMarkerOwner (
this);
618TextStore* WordProcessorTable::CellRep::PeekAtTextStore ()
const
623void WordProcessorTable::CellRep::AboutToUpdateText (
const UpdateInfo& updateInfo)
625 inherited::AboutToUpdateText (updateInfo);
626 if (fForTable.fAllowUpdateInfoPropagationContext and updateInfo.fRealContentUpdate) {
627 if (fForTable.fCellUpdatePropationUpdater !=
nullptr) {
630 fForTable.fCellUpdatePropationUpdater->Cancel ();
631 delete fForTable.fCellUpdatePropationUpdater;
632 fForTable.fCellUpdatePropationUpdater =
nullptr;
634 fForTable.fCellUpdatePropationUpdater =
635 new TextStore::SimpleUpdater (fForTable.GetOwner ()->GetTextStore (), fForTable.GetStart (), fForTable.GetEnd ());
639void WordProcessorTable::CellRep::DidUpdateText (
const UpdateInfo& updateInfo)
noexcept
641 inherited::DidUpdateText (updateInfo);
642 if (not fForTable.fSuppressCellUpdatePropagationContext) {
643 fForTable.InvalidateLayout ();
645 if (fForTable.fAllowUpdateInfoPropagationContext and updateInfo.fRealContentUpdate) {
647 delete fForTable.fCellUpdatePropationUpdater;
648 fForTable.fCellUpdatePropationUpdater =
nullptr;
658 inline TWIPS CalcDefaultRHSMargin_ ()
660 const int kRTF_SPEC_DefaultInches = 6;
661 int rhsTWIPS = kRTF_SPEC_DefaultInches * 1440;
662 return TWIPS{rhsTWIPS};
666WordProcessorTextIOSinkStream::WordProcessorTextIOSinkStream (TextStore* textStore,
const shared_ptr<AbstractStyleDatabaseRep>& textStyleDatabase,
667 const shared_ptr<AbstractParagraphDatabaseRep>& paragraphDatabase,
668 const shared_ptr<HidableTextMarkerOwner>& hidableTextDatabase,
size_t insertionStart)
669 : inherited{textStore, textStyleDatabase, insertionStart}
670 , fOverwriteTableMode{false}
672#if !qStroika_Frameworks_Led_NestedTablesSupported
673 fNoTablesAllowed{false}
677 , fParagraphDatabase{paragraphDatabase}
678 , fHidableTextDatabase{hidableTextDatabase}
680 , fNewParagraphInfo{}
683 , fEndOfBuffer{false}
684 , fIgnoreLastParaAttributes{false}
685 , fCurrentTable{nullptr}
686 , fCurrentTableCellWidths{}
687 , fCurrentTableCellColor{
Color::kWhite}
688 , fCurrentTableColSpanArray{}
692 , fCurrentTableCell{size_t (-1)}
695 , fTableRowOpen{false}
696 , fTableCellOpen{false}
702#if qStroika_Frameworks_Led_SupportGDI
703WordProcessorTextIOSinkStream::WordProcessorTextIOSinkStream (WordProcessor* wp,
size_t insertionStart)
704 : inherited{&wp->GetTextStore (), wp->GetStyleDatabase (), insertionStart}
705 , fOverwriteTableMode{false}
707#if !qStroika_Frameworks_Led_NestedTablesSupported
708 fNoTablesAllowed{false}
712 , fParagraphDatabase{wp->GetParagraphDatabase ()}
713 , fHidableTextDatabase{wp->GetHidableTextDatabase ()}
715 , fNewParagraphInfo{}
718 , fEndOfBuffer{false}
719 , fIgnoreLastParaAttributes{false}
720 , fCurrentTable{nullptr}
721 , fCurrentTableCellWidths{}
722 , fCurrentTableCellColor{
Color::kWhite}
723 , fCurrentTableColSpanArray{}
727 , fCurrentTableCell{size_t (-1)}
730 , fTableRowOpen{false}
731 , fTableCellOpen{false}
738WordProcessorTextIOSinkStream::~WordProcessorTextIOSinkStream ()
740#if qStroika_Foundation_Debug_AssertionsChecked
741 Assert (fTableOpenLevel == 0);
742 Assert (not fTableRowOpen);
743 Assert (not fTableCellOpen);
747 Ensure (GetCachedTextSize () == 0);
748 Ensure (fSavedParaInfo.size () == 0);
755void WordProcessorTextIOSinkStream::CTOR_COMMON ()
757 fNewParagraphInfo.SetJustification (eLeftJustify);
758 fNewParagraphInfo.SetTabStopList (StandardTabStopList{});
759 fNewParagraphInfo.SetFirstIndent (TWIPS{0});
760 fNewParagraphInfo.SetMargins (TWIPS{0}, CalcDefaultRHSMargin_ ());
761 fNewParagraphInfo.SetListStyle (eListStyle_None);
762 fNewParagraphInfo.SetSpaceBefore (TWIPS{0});
763 fNewParagraphInfo.SetSpaceAfter (TWIPS{0});
766void WordProcessorTextIOSinkStream::AppendText (
const Led_tChar* text,
size_t nTChars,
const FontSpecification* fontSpec)
769 inherited::AppendText (text, nTChars, fontSpec);
770 if (fSavedParaInfo.size () == 0) {
771 fSavedParaInfo.push_back (ParaInfoNSize (fNewParagraphInfo, nTChars));
773 else if (fSavedParaInfo.back ().first == fNewParagraphInfo) {
774 fSavedParaInfo.back ().second += nTChars;
777 fSavedParaInfo.push_back (ParaInfoNSize (fNewParagraphInfo, nTChars));
779 if (fHidableTextRuns.size () != 0 and fHidableTextRuns.back ().fData == fTextHidden) {
780 fHidableTextRuns.back ().fElementLength += nTChars;
783 fHidableTextRuns.push_back (DiscontiguousRunElement<bool> (0, nTChars, fTextHidden));
787#if qStroika_Frameworks_Led_SupportGDI
788void WordProcessorTextIOSinkStream::AppendEmbedding (SimpleEmbeddedObjectStyleMarker* embedding)
791 if (GetCachedTextSize () != 0) {
794 size_t whereToStartHiddenArea = GetInsertionStart ();
795 inherited::AppendEmbedding (embedding);
797 fHidableTextDatabase->MakeRegionHidable (whereToStartHiddenArea, whereToStartHiddenArea + 1);
802void WordProcessorTextIOSinkStream::AppendSoftLineBreak ()
804 AppendText (&kSoftLineBreakChar, 1,
nullptr);
807void WordProcessorTextIOSinkStream::SetJustification (Justification justification)
809 fNewParagraphInfo.SetJustification (justification);
812void WordProcessorTextIOSinkStream::SetStandardTabStopList (
const StandardTabStopList& tabStops)
814 fNewParagraphInfo.SetTabStopList (tabStops);
817void WordProcessorTextIOSinkStream::SetFirstIndent (TWIPS tx)
819 fNewParagraphInfo.SetFirstIndent (tx);
822void WordProcessorTextIOSinkStream::SetLeftMargin (TWIPS lhs)
824 fNewParagraphInfo.SetMargins (lhs, max (TWIPS (lhs + 1), fNewParagraphInfo.GetRightMargin ()));
827void WordProcessorTextIOSinkStream::SetRightMargin (TWIPS rhs)
829 fNewParagraphInfo.SetMargins (fNewParagraphInfo.GetLeftMargin (), max (TWIPS (fNewParagraphInfo.GetLeftMargin () + 1), rhs));
832void WordProcessorTextIOSinkStream::SetSpaceBefore (TWIPS sb)
834 fNewParagraphInfo.SetSpaceBefore (sb);
837void WordProcessorTextIOSinkStream::SetSpaceAfter (TWIPS sa)
839 fNewParagraphInfo.SetSpaceAfter (sa);
842void WordProcessorTextIOSinkStream::SetLineSpacing (LineSpacing sl)
844 fNewParagraphInfo.SetLineSpacing (sl);
847void WordProcessorTextIOSinkStream::SetTextHidden (
bool hidden)
849 fTextHidden = hidden;
852void WordProcessorTextIOSinkStream::StartTable ()
854#if qStroika_Foundation_Debug_AssertionsChecked
858 if (fTableOpenLevel == 0) {
860 Assert (fTableOpenLevel == 0);
861 Assert (not fTableRowOpen);
862 Assert (not fTableCellOpen);
866 Assert (fTableRowOpen);
867 Assert (fTableCellOpen);
870 fTableRowOpen =
false;
871 fTableCellOpen =
false;
874#if !qStroika_Frameworks_Led_NestedTablesSupported
875 if (GetNoTablesAllowed ()) {
880 if (GetCachedTextSize () != 0) {
886#if qStroika_Frameworks_Led_NestedTablesSupported
887 if (fCurrentTable !=
nullptr) {
889 fTableStack.push_back (fCurrentTable);
891 fCurrentTable =
nullptr;
894 if (GetOverwriteTableMode ()) {
895 TextStore& ts = GetTextStore ();
896 size_t realCoordStart = GetInsertionStart ();
897 MarkerOfATypeMarkerSink<WordProcessorTable> maybeTable;
898 Assert (realCoordStart <= ts.GetEnd ());
899 ts.CollectAllMarkersInRangeInto (ts.FindPreviousCharacter (realCoordStart), realCoordStart, fParagraphDatabase.get (), maybeTable);
900 if (maybeTable.fResult !=
nullptr) {
901 fCurrentTable = maybeTable.fResult;
902 size_t rowSelStart = 0;
903 size_t colSelStart = 0;
904 fCurrentTable->GetCellSelection (&rowSelStart,
nullptr, &colSelStart,
nullptr);
905 fNextTableRow = rowSelStart;
906 fNextTableCell = colSelStart;
907 fCurrentTableCell = size_t (-1);
911 if (fCurrentTable ==
nullptr) {
912 fCurrentTable =
new WordProcessorTable (fParagraphDatabase.get (), current_offset () + GetOriginalStart ());
913 SetInsertionStart (GetInsertionStart () + 1);
916 fCurrentTableCell = size_t (-1);
920void WordProcessorTextIOSinkStream::EndTable ()
922#if qStroika_Foundation_Debug_AssertionsChecked
923 Require (fTableOpenLevel >= 1);
924 Require (not fTableRowOpen);
925 Require (not fTableCellOpen);
929 if (fTableOpenLevel > 0) {
930 fTableRowOpen =
true;
931 fTableCellOpen =
true;
934 fTableRowOpen =
false;
935 fTableCellOpen =
false;
938#if !qStroika_Frameworks_Led_NestedTablesSupported
939 if (GetNoTablesAllowed ()) {
940 AppendText (LED_TCHAR_OF (
"\n"), 1,
nullptr);
944 if (fCurrentTable !=
nullptr) {
946 fCurrentTable =
nullptr;
947#if qStroika_Frameworks_Led_NestedTablesSupported
948 if (not fTableStack.empty ()) {
949 fCurrentTable = fTableStack.back ();
950 fTableStack.pop_back ();
956void WordProcessorTextIOSinkStream::StartTableRow ()
958#if qStroika_Foundation_Debug_AssertionsChecked
959 Require (fTableOpenLevel >= 1);
960 Require (not fTableRowOpen);
961 Require (not fTableCellOpen);
962 fTableRowOpen =
true;
964#if !qStroika_Frameworks_Led_NestedTablesSupported
965 if (GetNoTablesAllowed ()) {
967 AppendText (LED_TCHAR_OF (
"\n"), 1,
nullptr);
973 if (GetOverwriteTableMode ()) {
974 if (fNextTableRow > fCurrentTable->GetRowCount ()) {
975 fCurrentTable->InsertRow (fNextTableRow - 1, 1);
977 size_t colSelStart = 0;
978 fCurrentTable->GetCellSelection (
nullptr,
nullptr, &colSelStart,
nullptr);
979 fNextTableCell = min (fCurrentTable->GetColumnCount (fNextTableRow - 1) - 1, colSelStart);
983 fCurrentTable->InsertRow (fNextTableRow - 1, 1);
985 fCurrentTableColSpanArray.clear ();
988void WordProcessorTextIOSinkStream::EndTableRow ()
990#if qStroika_Foundation_Debug_AssertionsChecked
991 Require (fTableOpenLevel >= 1);
992 Require (fTableRowOpen);
993 Require (not fTableCellOpen);
994 fTableRowOpen =
false;
996#if !qStroika_Frameworks_Led_NestedTablesSupported
997 if (GetNoTablesAllowed ()) {
1002 size_t nCellsInThisRow = fCurrentTableCellWidths.size ();
1004 while (nCellsInThisRow > fCurrentTableColSpanArray.size ()) {
1006 fCurrentTableColSpanArray.push_back (1);
1009 if (nCellsInThisRow != fCurrentTableColSpanArray.size ()) {
1012 nCellsInThisRow = min (nCellsInThisRow, fCurrentTableColSpanArray.size ());
1014 fCurrentTable->SetColumnCount (fNextTableRow - 1, max (nCellsInThisRow, fCurrentTable->GetColumnCount (fNextTableRow - 1)));
1017 for (
size_t cellIdx = 0; cellIdx < nCellsInThisRow; ++cellIdx) {
1018 size_t nColsInThisCell = fCurrentTableColSpanArray[cellIdx];
1019 Assert (nColsInThisCell >= 1);
1020 Assert (col < fCurrentTable->GetColumnCount ());
1022 TWIPS thisCellWidth = fCurrentTableCellWidths[cellIdx];
1023 if (nColsInThisCell == 1) {
1024 Assert (fNextTableRow > 0);
1025 fCurrentTable->SetColumnWidth (fNextTableRow - 1, col, thisCellWidth);
1031 TWIPS prevColWidths = TWIPS{0};
1032 for (
size_t i = col; i < col + nColsInThisCell; ++i) {
1033 Assert (fNextTableRow > 0);
1034 prevColWidths += fCurrentTable->GetColumnWidth (fNextTableRow - 1, i);
1036 if (prevColWidths < thisCellWidth) {
1037 Assert (fNextTableRow > 0);
1038 fCurrentTable->SetColumnWidth (fNextTableRow - 1, col, thisCellWidth - prevColWidths);
1042 col += nColsInThisCell;
1046void WordProcessorTextIOSinkStream::StartTableCell (
size_t colSpan)
1048#if qStroika_Foundation_Debug_AssertionsChecked
1050 Require (fTableOpenLevel >= 1);
1051 Require (fTableRowOpen);
1052 Require (not fTableCellOpen);
1053 fTableCellOpen =
true;
1056#if !qStroika_Frameworks_Led_NestedTablesSupported
1057 if (GetNoTablesAllowed ()) {
1058 if (fNextTableCell >= 1) {
1059 AppendText (LED_TCHAR_OF (
"\t"), 1,
nullptr);
1065 Require (colSpan >= 1);
1067 fCurrentTableCell = fNextTableCell;
1068 fCurrentTableColSpanArray.push_back (colSpan);
1069 fNextTableCell += colSpan;
1072 fCurrentTable->SetColumnCount (fNextTableRow - 1, max (fNextTableCell, fCurrentTable->GetColumnCount (fNextTableRow - 1)));
1074 Assert (fNextTableRow > 0);
1075 Assert (fNextTableCell > 0);
1077 TextStore* ts =
nullptr;
1078 shared_ptr<AbstractStyleDatabaseRep> styleDatabase;
1079 shared_ptr<AbstractParagraphDatabaseRep> paragraphDatabase;
1080 shared_ptr<HidableTextMarkerOwner> hidableTextDatabase;
1081 fCurrentTable->GetCellWordProcessorDatabases (fNextTableRow - 1, fCurrentTableCell, &ts, &styleDatabase, ¶graphDatabase, &hidableTextDatabase);
1082 PushContext (ts, styleDatabase, paragraphDatabase, hidableTextDatabase, 0);
1083 if (GetOverwriteTableMode ()) {
1084 ts->Replace (0, ts->GetLength (),
nullptr, 0);
1088void WordProcessorTextIOSinkStream::EndTableCell ()
1090#if qStroika_Foundation_Debug_AssertionsChecked
1091 Require (fTableOpenLevel >= 1);
1092 Require (fTableRowOpen);
1093 Require (fTableCellOpen);
1094 fTableCellOpen =
false;
1096#if !qStroika_Frameworks_Led_NestedTablesSupported
1097 if (GetNoTablesAllowed ()) {
1102 fCurrentTable->SetCellColor (fNextTableRow - 1, fCurrentTableCell, fCurrentTableCellColor);
1106void WordProcessorTextIOSinkStream::SetListStyle (ListStyle listStyle)
1108 fNewParagraphInfo.SetListStyle (listStyle);
1111void WordProcessorTextIOSinkStream::SetListIndentLevel (
unsigned char indentLevel)
1113 fNewParagraphInfo.SetListIndentLevel (indentLevel);
1116void WordProcessorTextIOSinkStream::SetIgnoreLastParaAttributes (
bool ignoreLastParaAttributes)
1118 fIgnoreLastParaAttributes = ignoreLastParaAttributes;
1121void WordProcessorTextIOSinkStream::SetTableBorderColor (
Color c)
1123 if (fCurrentTable !=
nullptr) {
1124 fCurrentTable->SetTableBorderColor (c);
1128void WordProcessorTextIOSinkStream::SetTableBorderWidth (TWIPS bWidth)
1130 if (fCurrentTable !=
nullptr) {
1131 fCurrentTable->SetTableBorderWidth (bWidth);
1135void WordProcessorTextIOSinkStream::SetCellWidths (
const vector<TWIPS>& cellWidths)
1137 if (fCurrentTable !=
nullptr) {
1138 fCurrentTableCellWidths = cellWidths;
1142void WordProcessorTextIOSinkStream::SetCellBackColor (
const Color c)
1144 if (fCurrentTable !=
nullptr) {
1145 fCurrentTableCellColor = c;
1149void WordProcessorTextIOSinkStream::SetDefaultCellMarginsForCurrentRow (TWIPS top, TWIPS left, TWIPS bottom, TWIPS right)
1155 if (fCurrentTable !=
nullptr) {
1156 fCurrentTable->SetDefaultCellMargins (top, left, bottom, right);
1160void WordProcessorTextIOSinkStream::SetDefaultCellSpacingForCurrentRow (TWIPS top, TWIPS left, TWIPS bottom, TWIPS right)
1168 if (fCurrentTable !=
nullptr) {
1169 TWIPS aveSpacing = TWIPS ((top + left + bottom + right) / 4);
1170 fCurrentTable->SetCellSpacing (aveSpacing);
1174void WordProcessorTextIOSinkStream::PushContext (TextStore* ts,
const shared_ptr<AbstractStyleDatabaseRep>& textStyleDatabase,
1175 const shared_ptr<AbstractParagraphDatabaseRep>& paragraphDatabase,
1176 const shared_ptr<HidableTextMarkerOwner>& hidableTextDatabase,
size_t insertionStart)
1178 if (GetCachedTextSize () != 0) {
1181 inherited::PushContext (ts, textStyleDatabase, insertionStart);
1183 c.fHidableTextDatabase = fHidableTextDatabase;
1184 c.fParagraphDatabase = fParagraphDatabase;
1185 fSavedContexts.push_back (c);
1186 fHidableTextDatabase = hidableTextDatabase;
1187 fParagraphDatabase = paragraphDatabase;
1190void WordProcessorTextIOSinkStream::PopContext ()
1192 Require (GetCachedTextSize () == 0);
1193 Require (not fSavedContexts.empty ());
1194 inherited::PopContext ();
1195 fHidableTextDatabase = fSavedContexts.back ().fHidableTextDatabase;
1196 fParagraphDatabase = fSavedContexts.back ().fParagraphDatabase;
1197 fSavedContexts.pop_back ();
1200void WordProcessorTextIOSinkStream::EndOfBuffer ()
1202 fEndOfBuffer =
true;
1205void WordProcessorTextIOSinkStream::Flush ()
1207 size_t stripParaCharCount = 0;
1208 if (fEndOfBuffer and fIgnoreLastParaAttributes) {
1209 const vector<Led_tChar>& t = GetCachedText ();
1211 for (
auto i = t.rbegin (); i != t.rend (); ++i) {
1216 ++stripParaCharCount;
1222 size_t dataSize = GetCachedTextSize ();
1223 size_t whereToInsert = GetInsertionStart () - dataSize;
1224 inherited::Flush ();
1229 [[maybe_unused]]
size_t curInsert = whereToInsert;
1230 for (
auto i = fSavedParaInfo.begin (); i != fSavedParaInfo.end (); ++i) {
1231 curInsert += (*i).second;
1233 Assert (curInsert == GetInsertionStart ());
1235 if (stripParaCharCount != 0) {
1236 Assert (fSavedParaInfo.size () > 0);
1237 vector<ParaInfoNSize>::iterator i = fSavedParaInfo.end () - 1;
1238 if ((*i).second > stripParaCharCount) {
1239 (*i).second -= stripParaCharCount;
1242 fSavedParaInfo.resize (fSavedParaInfo.size () - 1);
1245 fParagraphDatabase->SetParagraphInfo (whereToInsert, fSavedParaInfo);
1246 fSavedParaInfo.clear ();
1260 if (fEndOfBuffer and not fIgnoreLastParaAttributes and whereToInsert == fParagraphDatabase->GetTextStore ().GetEnd ()) {
1261 fParagraphDatabase->SetParagraphInfo (whereToInsert, 1,
1263 fParagraphDatabase->GetTextStore ().FindPreviousCharacter (whereToInsert))));
1268 vector<pair<size_t, size_t>> hidePairs;
1269 size_t curInsert = whereToInsert;
1270 for (
auto i = fHidableTextRuns.begin (); i != fHidableTextRuns.end (); ++i) {
1272 hidePairs.push_back (pair<size_t, size_t> (curInsert, curInsert + (*i).fElementLength));
1274 curInsert += (*i).fElementLength;
1276 for (
auto i = hidePairs.rbegin (); i != hidePairs.rend (); ++i) {
1277 fHidableTextDatabase->MakeRegionHidable ((*i).first, (*i).second);
1279 fHidableTextRuns.clear ();
1288WordProcessorTextIOSrcStream::WordProcessorTextIOSrcStream (TextStore* textStore,
const shared_ptr<AbstractStyleDatabaseRep>& textStyleDatabase,
1289 const shared_ptr<AbstractParagraphDatabaseRep>& paragraphDatabase,
1290 const shared_ptr<HidableTextMarkerOwner>& hidableTextDatabase,
1291 size_t selectionStart,
size_t selectionEnd)
1292 : inherited{textStore, textStyleDatabase, selectionStart, selectionEnd}
1293 , fParagraphDatabase{paragraphDatabase}
1294 , fHidableTextRuns{}
1297 if (hidableTextDatabase.get () !=
nullptr) {
1298 fHidableTextRuns = hidableTextDatabase->GetHidableRegions (selectionStart, selectionEnd);
1302#if qStroika_Frameworks_Led_SupportGDI
1303WordProcessorTextIOSrcStream::WordProcessorTextIOSrcStream (WordProcessor* textImager,
size_t selectionStart,
size_t selectionEnd)
1304 : inherited (textImager, selectionStart, selectionEnd)
1305 , fParagraphDatabase (textImager->GetParagraphDatabase ())
1306 , fHidableTextRuns ()
1308 shared_ptr<HidableTextMarkerOwner> hidableTextDatabase = textImager->GetHidableTextDatabase ();
1309 if (hidableTextDatabase.get () !=
nullptr) {
1310 fHidableTextRuns = hidableTextDatabase->GetHidableRegions (selectionStart, selectionEnd);
1315Justification WordProcessorTextIOSrcStream::GetJustification ()
const
1317 if (fParagraphDatabase.get () ==
nullptr) {
1318 return inherited::GetJustification ();
1321 return fParagraphDatabase->GetParagraphInfo (GetCurOffset ()).GetJustification ();
1325StandardTabStopList WordProcessorTextIOSrcStream::GetStandardTabStopList ()
const
1327 if (fParagraphDatabase.get () ==
nullptr) {
1328 return inherited::GetStandardTabStopList ();
1331 return fParagraphDatabase->GetParagraphInfo (GetCurOffset ()).GetTabStopList ();
1335TWIPS WordProcessorTextIOSrcStream::GetFirstIndent ()
const
1337 if (fParagraphDatabase.get () ==
nullptr) {
1338 return inherited::GetFirstIndent ();
1341 return fParagraphDatabase->GetParagraphInfo (GetCurOffset ()).GetFirstIndent ();
1345void WordProcessorTextIOSrcStream::GetMargins (TWIPS* lhs, TWIPS* rhs)
const
1349 if (fParagraphDatabase.get () ==
nullptr) {
1350 inherited::GetMargins (lhs, rhs);
1353 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (GetCurOffset ());
1354 *lhs = pi.GetLeftMargin ();
1355 *rhs = pi.GetRightMargin ();
1363TWIPS WordProcessorTextIOSrcStream::GetSpaceBefore ()
const
1365 if (fParagraphDatabase.get () ==
nullptr) {
1366 return inherited::GetSpaceBefore ();
1369 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (GetCurOffset ());
1370 return pi.GetSpaceBefore ();
1378TWIPS WordProcessorTextIOSrcStream::GetSpaceAfter ()
const
1380 if (fParagraphDatabase.get () ==
nullptr) {
1381 return inherited::GetSpaceAfter ();
1384 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (GetCurOffset ());
1385 return pi.GetSpaceAfter ();
1393LineSpacing WordProcessorTextIOSrcStream::GetLineSpacing ()
const
1395 if (fParagraphDatabase.get () ==
nullptr) {
1396 return inherited::GetLineSpacing ();
1399 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (GetCurOffset ());
1400 return pi.GetLineSpacing ();
1408void WordProcessorTextIOSrcStream::GetListStyleInfo (ListStyle* listStyle,
unsigned char* indentLevel)
const
1412 if (fParagraphDatabase.get () ==
nullptr) {
1413 inherited::GetListStyleInfo (listStyle, indentLevel);
1416 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (GetCurOffset ());
1417 *listStyle = pi.GetListStyle ();
1418 *indentLevel = pi.GetListIndentLevel ();
1422Led_tChar WordProcessorTextIOSrcStream::GetSoftLineBreakCharacter ()
const
1424 return kSoftLineBreakChar;
1427DiscontiguousRun<bool> WordProcessorTextIOSrcStream::GetHidableTextRuns ()
const
1429 return fHidableTextRuns;
1432#if qStroika_Frameworks_Led_SupportTables
1433WordProcessorTextIOSrcStream::Table* WordProcessorTextIOSrcStream::GetTableAt (
size_t at)
const
1435 Require (fParagraphDatabase.get () !=
nullptr);
1436 TextStore& ts = fParagraphDatabase->GetTextStore ();
1437 size_t realCoordStart = GetEmbeddingMarkerPosOffset () + at;
1438 MarkerOfATypeMarkerSink<WordProcessorTable> maybeTable;
1439 ts.CollectAllMarkersInRangeInto (realCoordStart, realCoordStart + 1, fParagraphDatabase.get (), maybeTable);
1440 if (maybeTable.fResult ==
nullptr) {
1448 [[maybe_unused]]
size_t realCoordEnd = min (maybeTable.fResult->GetEnd (), GetSelEnd ());
1449 Assert (realCoordStart < realCoordEnd);
1450 if (fUseTableSelection) {
1451 size_t rowSelStart = 0;
1452 size_t rowSelEnd = 0;
1453 size_t colSelStart = 0;
1454 size_t colSelEnd = 0;
1455 maybeTable.fResult->GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
1456 return new TableIOMapper{*maybeTable.fResult, rowSelStart, rowSelEnd, colSelStart, colSelEnd};
1459 return new TableIOMapper{*maybeTable.fResult};
1465void WordProcessorTextIOSrcStream::SummarizeFontAndColorTable (set<SDKString>* fontNames, set<Color>* colorsUsed)
const
1467 inherited::SummarizeFontAndColorTable (fontNames, colorsUsed);
1470 TextStore& ts = fParagraphDatabase->GetTextStore ();
1471 MarkersOfATypeMarkerSink2Vector<WordProcessorTable> tables;
1472 ts.CollectAllMarkersInRangeInto (GetSelStart (), GetSelEnd (), fParagraphDatabase.get (), tables);
1473 for (
auto i = tables.fResult.begin (); i != tables.fResult.end (); ++i) {
1474 TableIOMapper tiom (**i);
1475 size_t rows = tiom.GetRows ();
1476 for (
size_t r = 0; r < rows; ++r) {
1477 size_t columns = tiom.GetColumns (r);
1478 for (
size_t c = 0; c < columns; ++c) {
1479 unique_ptr<StyledTextIOWriter::SrcStream> subSrcStream (tiom.MakeCellSubSrcStream (r, c));
1480 if (subSrcStream.get () !=
nullptr) {
1481 subSrcStream.get ()->SummarizeFontAndColorTable (fontNames, colorsUsed);
1484 if (colorsUsed !=
nullptr) {
1485 using CellInfo = StyledTextIOWriter::SrcStream::Table::CellInfo;
1486 vector<CellInfo> cellInfos;
1487 tiom.GetRowInfo (r, &cellInfos);
1488 for (
auto ci = cellInfos.begin (); ci != cellInfos.end (); ++ci) {
1489 colorsUsed->insert ((*ci).f_clcbpat);
1502WordProcessorTextIOSrcStream::TableIOMapper::TableIOMapper (WordProcessorTable& realTable,
size_t startRow,
size_t endRow,
size_t startCol,
size_t endCol)
1503 : fRealTable{realTable}
1504 , fStartRow{startRow}
1506 , fStartCol{startCol}
1509 if (fEndRow ==
static_cast<size_t> (-1)) {
1510 fEndRow = fRealTable.GetRowCount ();
1512 if (fEndCol ==
static_cast<size_t> (-1)) {
1513 fEndCol = fRealTable.GetColumnCount ();
1516 Ensure (fStartRow < fEndRow);
1517 Ensure (fStartCol < fEndCol);
1518 Ensure (fEndRow <= fRealTable.GetRowCount ());
1519 Ensure (fEndCol <= fRealTable.GetColumnCount ());
1522size_t WordProcessorTextIOSrcStream::TableIOMapper::GetRows ()
const
1524 return fEndRow - fStartRow;
1527size_t WordProcessorTextIOSrcStream::TableIOMapper::GetColumns (
size_t row)
const
1529 size_t vRow = row + fStartRow;
1530 size_t realColCount = fRealTable.GetColumnCount (vRow);
1531 size_t pinnedColEnd = min (realColCount, fEndCol);
1533 Assert (pinnedColEnd > fStartCol);
1535 return pinnedColEnd - fStartCol;
1538void WordProcessorTextIOSrcStream::TableIOMapper::GetRowInfo (
size_t row, vector<CellInfo>* cellInfos)
1540 Require (row < GetRows ());
1542 size_t vRow = row + fStartRow;
1545 size_t columns = GetColumns (row);
1546 cellInfos->clear ();
1547 for (
size_t c = 0; c < columns; ++c) {
1548 size_t vCol = c + fStartCol;
1549 if (fRealTable.GetCellFlags (vRow, vCol) == WordProcessorTable::ePlainCell) {
1551 cellInfo.f_clcbpat = fRealTable.GetCellColor (vRow, vCol);
1552 cellInfo.f_cellx = fRealTable.GetColumnWidth (vRow, vCol);
1553 cellInfos->push_back (cellInfo);
1557 if (not cellInfos->empty ()) {
1558 cellInfos->back ().f_cellx += fRealTable.GetColumnWidth (vRow, vCol);
1564StyledTextIOWriter::SrcStream* WordProcessorTextIOSrcStream::TableIOMapper::MakeCellSubSrcStream (
size_t row,
size_t column)
1566 Require (row < GetRows ());
1567 Require (column < GetColumns (row));
1569 size_t vRow = row + fStartRow;
1570 size_t vCol = column + fStartCol;
1572 if (fRealTable.GetCellFlags (vRow, vCol) == WordProcessorTable::ePlainCell) {
1573 TextStore* ts =
nullptr;
1574 shared_ptr<AbstractStyleDatabaseRep> styleDatabase;
1575 shared_ptr<AbstractParagraphDatabaseRep> paragraphDatabase;
1576 shared_ptr<HidableTextMarkerOwner> hidableTextDatabase;
1577 fRealTable.GetCellWordProcessorDatabases (vRow, vCol, &ts, &styleDatabase, ¶graphDatabase, &hidableTextDatabase);
1585size_t WordProcessorTextIOSrcStream::TableIOMapper::GetOffsetEnd ()
const
1592TWIPS_Rect WordProcessorTextIOSrcStream::TableIOMapper::GetDefaultCellMarginsForRow (
size_t )
const
1595 TWIPS_Rect cellMargins = TWIPS_Rect (TWIPS{0}, TWIPS{0}, TWIPS{0}, TWIPS{0});
1596 fRealTable.GetDefaultCellMargins (&cellMargins.top, &cellMargins.left, &cellMargins.bottom, &cellMargins.right);
1600TWIPS_Rect WordProcessorTextIOSrcStream::TableIOMapper::GetDefaultCellSpacingForRow (
size_t )
const
1603 TWIPS cellSpacing = fRealTable.GetCellSpacing ();
1604 return TWIPS_Rect (cellSpacing, cellSpacing, TWIPS{0}, TWIPS{0});
1607#if qStroika_Frameworks_Led_SupportGDI
1609class ParagraphInfoChangeTextRep :
public InteractiveReplaceCommand::SavedTextRep {
1611 using inherited = InteractiveReplaceCommand::SavedTextRep;
1614 using ParaInfoNSize = pair<ParagraphInfo, size_t>;
1617 ParagraphInfoChangeTextRep (WordProcessor* interactor,
size_t from,
size_t to)
1618 : inherited (from, to)
1621 fSavedInfo = interactor->GetParagraphDatabase ()->GetParagraphInfo (from, to - from);
1622 Assert (GetLength () == to - from);
1624 virtual size_t GetLength ()
const override
1627 for (
auto i = fSavedInfo.begin (); i != fSavedInfo.end (); ++i) {
1632 virtual void InsertSelf (TextInteractor* interactor,
size_t at, [[maybe_unused]]
size_t nBytesToOverwrite)
override
1635 WordProcessor* wp =
dynamic_cast<WordProcessor*
> (interactor);
1637 Assert (nBytesToOverwrite == GetLength ());
1638 shared_ptr<AbstractParagraphDatabaseRep> paraDBase = wp->GetParagraphDatabase ();
1639 paraDBase->SetParagraphInfo (at, fSavedInfo);
1643 vector<ParaInfoNSize> fSavedInfo;
1647template <
typename SPECIALIZER,
typename T1>
1648void InteractiveWPHelper1 (WordProcessor* wp, T1 arg1)
1650 TextInteractor::InteractiveModeUpdater iuMode (*wp);
1651 using SavedTextRep = InteractiveReplaceCommand::SavedTextRep;
1652 wp->BreakInGroupedCommands ();
1653 size_t selStart = wp->GetSelectionStart ();
1654 size_t selEnd = wp->GetSelectionEnd ();
1655 SavedTextRep* before =
nullptr;
1656 SavedTextRep* after =
nullptr;
1658 if (wp->GetCommandHandler () !=
nullptr) {
1659 before =
new ParagraphInfoChangeTextRep (wp, selStart, selEnd);
1661 SPECIALIZER::DoIt (wp, selStart, selEnd, arg1);
1662 if (wp->GetCommandHandler () !=
nullptr) {
1663 after =
new ParagraphInfoChangeTextRep (wp, selStart, selEnd);
1664 wp->PostInteractiveUndoPostHelper (&before, &after, selStart, SPECIALIZER::GetName (wp));
1672 wp->BreakInGroupedCommands ();
1674struct DoIt_SetJustification {
1675 static void DoIt (WordProcessor* wp,
size_t selStart,
size_t selEnd, Justification justification)
1677 wp->SetJustification (selStart, selEnd, justification);
1679 static SDKString GetName (WordProcessor* wp)
1681 return wp->GetCommandNames ().fJustificationCommandName;
1684struct DoIt_SetStandardTabStopList {
1685 static void DoIt (WordProcessor* wp,
size_t selStart,
size_t selEnd, StandardTabStopList tabStops)
1687 wp->SetStandardTabStopList (selStart, selEnd, tabStops);
1689 static SDKString GetName (WordProcessor* wp)
1691 return wp->GetCommandNames ().fStandardTabStopListCommandName;
1694struct DoIt_SetMargins {
1698 Margins (TWIPS l, TWIPS r)
1704 static void DoIt (WordProcessor* wp,
size_t selStart,
size_t selEnd, Margins margins)
1706 wp->SetMargins (selStart, selEnd, margins.fLHS, margins.fRHS);
1708 static SDKString GetName (WordProcessor* wp)
1710 return wp->GetCommandNames ().fMarginsCommandName;
1713struct DoIt_SetFirstIndent {
1714 static void DoIt (WordProcessor* wp,
size_t selStart,
size_t selEnd, TWIPS firstIndent)
1716 wp->SetFirstIndent (selStart, selEnd, firstIndent);
1718 static SDKString GetName (WordProcessor* wp)
1720 return wp->GetCommandNames ().fFirstIndentCommandName;
1723struct DoIt_SetMarginsAndFirstIndent {
1724 struct MarginsAndFirstIndent {
1728 MarginsAndFirstIndent (TWIPS l, TWIPS r, TWIPS firstIndent)
1731 , fFirstIndent (firstIndent)
1735 static void DoIt (WordProcessor* wp,
size_t selStart,
size_t selEnd, MarginsAndFirstIndent marginsEtc)
1737 wp->SetMargins (selStart, selEnd, marginsEtc.fLHS, marginsEtc.fRHS);
1738 wp->SetFirstIndent (selStart, selEnd, marginsEtc.fFirstIndent);
1740 static SDKString GetName (WordProcessor* wp)
1742 return wp->GetCommandNames ().fMarginsAndFirstIndentCommandName;
1745struct DoIt_SetParagraphSpacing {
1746 struct AllSpacingArgs {
1749 LineSpacing fLineSpacing;
1750 bool fSBValid, fSAValid, fSLValid;
1751 AllSpacingArgs (TWIPS sb,
bool sbValid, TWIPS sa,
bool saValid, LineSpacing sl,
bool slValid)
1753 , fSBValid (sbValid)
1755 , fSAValid (saValid)
1757 , fSLValid (slValid)
1761 static void DoIt (WordProcessor* wp,
size_t selStart,
size_t selEnd, AllSpacingArgs spacingArgs)
1763 if (spacingArgs.fSBValid) {
1764 wp->SetSpaceBefore (selStart, selEnd, spacingArgs.fSpaceBefore);
1766 if (spacingArgs.fSAValid) {
1767 wp->SetSpaceAfter (selStart, selEnd, spacingArgs.fSpaceAfter);
1769 if (spacingArgs.fSLValid) {
1770 wp->SetLineSpacing (selStart, selEnd, spacingArgs.fLineSpacing);
1773 static SDKString GetName (WordProcessor* wp)
1775 return wp->GetCommandNames ().fParagraphSpacingCommandName;
1778struct DoIt_SetListStyle {
1779 static void DoIt (WordProcessor* wp,
size_t selStart,
size_t selEnd, ListStyle listStyle)
1781 wp->SetListStyle (selStart, selEnd, listStyle,
true);
1783 static SDKString GetName (WordProcessor* wp)
1785 return wp->GetCommandNames ().fSetListStyleCommandName;
1788struct DoIt_IndentUnIndentList {
1789 static void DoIt (WordProcessor* wp,
size_t selStart,
size_t selEnd,
bool indent)
1791 unsigned char indentLevel = wp->GetListIndentLevel (selStart);
1793 if (indentLevel < 8) {
1801 if (indentLevel > 0) {
1808 wp->SetListIndentLevel (selStart, selEnd, indentLevel,
true);
1810 static SDKString GetName (WordProcessor* wp)
1812 return wp->GetCommandNames ().fIndentLevelChangeCommandName;
1821WordProcessor::WPIdler::WPIdler ()
1826void WordProcessor::WPIdler::SpendIdleTime ()
1832 AbstractParagraphDatabaseRep* pdbRep = fWP->GetParagraphDatabase ().get ();
1834 if (pdbRep->fSomeInvalidTables) {
1839 vector<WordProcessorTable*> tables = fWP->GetTablesInRange (0, fWP->GetEnd ());
1840 bool maybeMoreTables =
false;
1841 for (
auto i = tables.begin (); i != tables.end (); ++i) {
1842 WordProcessorTable* t = *i;
1843 if (t->fNeedLayout != WordProcessorTable::eDone) {
1844 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*t, *fWP);
1845 t->PerformLayout ();
1846 if (endTime < Time::GetTickCount ()) {
1847 maybeMoreTables =
true;
1852 pdbRep->fSomeInvalidTables = maybeMoreTables;
1861WordProcessor::DialogSupport::FontNameSpecifier WordProcessor::DialogSupport::CmdNumToFontName (CommandNumber )
1865 return FontNameSpecifier ();
1868bool WordProcessor::DialogSupport::IsPredefinedFontSize (DistanceType fontSize)
1894DistanceType WordProcessor::DialogSupport::FontCmdToSize (CommandNumber commandNum)
1896 switch (commandNum) {
1897 case kFontSize9_CmdID:
1899 case kFontSize10_CmdID:
1901 case kFontSize12_CmdID:
1903 case kFontSize14_CmdID:
1905 case kFontSize18_CmdID:
1907 case kFontSize24_CmdID:
1909 case kFontSize36_CmdID:
1911 case kFontSize48_CmdID:
1913 case kFontSize72_CmdID:
1919DistanceType WordProcessor::DialogSupport::PickOtherFontHeight (DistanceType )
1925bool WordProcessor::DialogSupport::PickNewParagraphLineSpacing (TWIPS* ,
bool* , TWIPS* ,
1926 bool* , LineSpacing* ,
bool* )
1932bool WordProcessor::DialogSupport::PickNewParagraphMarginsAndFirstIndent (TWIPS* ,
bool* , TWIPS* ,
1933 bool* , TWIPS* ,
bool* )
1939Color WordProcessor::DialogSupport::FontCmdToColor (CommandNumber cmd)
1942 case kFontColorBlack_CmdID:
1943 return Color::kBlack;
1944 case kFontColorMaroon_CmdID:
1945 return Color::kMaroon;
1946 case kFontColorGreen_CmdID:
1947 return Color::kGreen;
1948 case kFontColorOlive_CmdID:
1949 return Color::kOlive;
1950 case kFontColorNavy_CmdID:
1951 return Color::kNavyBlue;
1952 case kFontColorPurple_CmdID:
1953 return Color::kPurple;
1954 case kFontColorTeal_CmdID:
1955 return Color::kTeal;
1956 case kFontColorGray_CmdID:
1957 return Color::kGray;
1958 case kFontColorSilver_CmdID:
1959 return Color::kSilver;
1960 case kFontColorRed_CmdID:
1962 case kFontColorLime_CmdID:
1963 return Color::kLimeGreen;
1964 case kFontColorYellow_CmdID:
1965 return Color::kYellow;
1966 case kFontColorBlue_CmdID:
1967 return Color::kBlue;
1968 case kFontColorFuchsia_CmdID:
1969 return Color::kFuchsia;
1970 case kFontColorAqua_CmdID:
1971 return Color::kAqua;
1972 case kFontColorWhite_CmdID:
1973 return Color::kWhite;
1976 return Color::kBlack;
1979WordProcessor::DialogSupport::CommandNumber WordProcessor::DialogSupport::FontColorToCmd (
Color color)
1981 if (color == Color::kBlack) {
1982 return kFontColorBlack_CmdID;
1984 else if (color == Color::kMaroon) {
1985 return kFontColorMaroon_CmdID;
1987 else if (color == Color::kGreen) {
1988 return kFontColorGreen_CmdID;
1990 else if (color == Color::kOlive) {
1991 return kFontColorOlive_CmdID;
1993 else if (color == Color::kNavyBlue) {
1994 return kFontColorNavy_CmdID;
1996 else if (color == Color::kPurple) {
1997 return kFontColorPurple_CmdID;
1999 else if (color == Color::kTeal) {
2000 return kFontColorTeal_CmdID;
2002 else if (color == Color::kGray) {
2003 return kFontColorGray_CmdID;
2005 else if (color == Color::kSilver) {
2006 return kFontColorSilver_CmdID;
2008 else if (color == Color::kRed) {
2009 return kFontColorRed_CmdID;
2011 else if (color == Color::kGreen) {
2012 return kFontColorLime_CmdID;
2014 else if (color == Color::kYellow) {
2015 return kFontColorYellow_CmdID;
2017 else if (color == Color::kBlue) {
2018 return kFontColorBlue_CmdID;
2020 else if (color == Color::kFuchsia) {
2021 return kFontColorFuchsia_CmdID;
2023 else if (color == Color::kAqua) {
2024 return kFontColorAqua_CmdID;
2026 else if (color == Color::kWhite) {
2027 return kFontColorWhite_CmdID;
2032 for (CommandNumber i = kBaseFontColor_CmdID; i <= kLastNamedFontColor_CmdID; ++i) {
2033 if (FontCmdToColor (i) == color) {
2037 return kFontColorOther_CmdID;
2041bool WordProcessor::DialogSupport::PickOtherFontColor (
Color* color)
2045#if qStroika_Foundation_Common_Platform_MacOS
2046 RGBColor oldColor = color->GetOSRep ();
2047 RGBColor newColor = oldColor;
2048 Point where = {0, 0};
2049 if (::GetColor (where,
"\pPick new color", &oldColor, &newColor)) {
2050 *color =
Color (newColor);
2053#elif qStroika_Foundation_Common_Platform_Windows
2055 memset (&cc, 0,
sizeof (cc));
2056 cc.lStructSize =
sizeof (cc);
2057 cc.Flags |= CC_ANYCOLOR;
2058 cc.rgbResult = color->GetOSRep ();
2059 cc.Flags |= CC_RGBINIT;
2060 cc.Flags |= CC_FULLOPEN;
2062 cc.Flags |= CC_ENABLEHOOK;
2063 cc.lpfnHook = ColorPickerINITPROC;
2065 static COLORREF sCustomColors[16];
2066 cc.lpCustColors = sCustomColors;
2068 cc.hwndOwner = ::GetActiveWindow ();
2070 if (::ChooseColor (&cc)) {
2071 *color =
Color (cc.rgbResult);
2078#if qStroika_Foundation_Common_Platform_Windows
2079UINT_PTR CALLBACK WordProcessor::DialogSupport::ColorPickerINITPROC (HWND hWnd, UINT message, [[maybe_unused]] WPARAM wParam, [[maybe_unused]] LPARAM lParam)
2081 if (hWnd !=
nullptr and message == WM_INITDIALOG) {
2082 Led_CenterWindowInParent (hWnd);
2088bool WordProcessor::DialogSupport::ChooseFont ([[maybe_unused]] IncrementalFontSpecification* font)
2092#if qStroika_Foundation_Common_Platform_Windows
2095 (void)::memset (&lf, 0,
sizeof (lf));
2096 if (font->GetFontNameSpecifier_Valid ()) {
2097 Characters::CString::Copy (lf.lfFaceName, std::size (lf.lfFaceName), font->GetFontNameSpecifier ().fName);
2098 Assert (::_tcslen (lf.lfFaceName) < std::size (lf.lfFaceName));
2100 lf.lfWeight = (font->GetStyle_Bold_Valid () and font->GetStyle_Bold ()) ? FW_BOLD : FW_NORMAL;
2101 lf.lfItalic = (font->GetStyle_Italic_Valid () and font->GetStyle_Italic ());
2102 lf.lfUnderline = (font->GetStyle_Underline_Valid () and font->GetStyle_Underline ());
2103 lf.lfStrikeOut = (font->GetStyle_Strikeout_Valid () and font->GetStyle_Strikeout ());
2105 if (font->GetPointSize_Valid ()) {
2106 lf.lfHeight = font->PeekAtTMHeight ();
2110 memset (&cc, 0,
sizeof (cc));
2111 cc.lStructSize =
sizeof (cc);
2112 cc.Flags |= CF_SCREENFONTS | CF_NOVERTFONTS | CF_EFFECTS | CF_SCALABLEONLY;
2114 cc.hwndOwner = ::GetActiveWindow ();
2117 cc.Flags |= CF_INITTOLOGFONTSTRUCT;
2119 if (font->GetTextColor_Valid ()) {
2120 cc.rgbColors = font->GetTextColor ().GetOSRep ();
2123 if (::ChooseFont (&cc)) {
2125 font->SetTextColor (
Color (cc.rgbColors));
2132void WordProcessor::DialogSupport::ShowSimpleEmbeddingInfoDialog (
const SDKString& )
2143bool WordProcessor::DialogSupport::ShowAddURLEmbeddingInfoDialog (
SDKString* ,
SDKString* )
2149bool WordProcessor::DialogSupport::AddNewTableDialog (
size_t* nRows,
size_t* nCols)
2159bool WordProcessor::DialogSupport::EditTablePropertiesDialog ([[maybe_unused]] TableSelectionPropertiesInfo* tableProperties)
2170WordProcessor::CommandNames WordProcessor::sCommandNames = WordProcessor::MakeDefaultCommandNames ();
2171WordProcessor::DialogSupport* WordProcessor::sDialogSupport =
nullptr;
2173template <
class T,
class EXTRACTOR>
2174bool CheckForCommonParaValue (EXTRACTOR ,
const shared_ptr<AbstractParagraphDatabaseRep>& paraDB,
2175 size_t from,
size_t to, T* commonValue)
2178 if (paraDB.get () ==
nullptr) {
2179 throw WordProcessor::NoParagraphDatabaseAvailable ();
2181 vector<pair<ParagraphInfo, size_t>> v = paraDB->GetParagraphInfo (from, to - from);
2182 Assert (v.size () != 0);
2183 if (v.size () >= 1) {
2184 T maybeCommonValue = EXTRACTOR () (v[0].first);
2185 for (
auto i = v.begin () + 1; i != v.end (); ++i) {
2186 if (EXTRACTOR () ((*i).first) != maybeCommonValue) {
2190 *commonValue = maybeCommonValue;
2197struct JustificationExtractor {
2200 return from.GetJustification ();
2203struct TabStopExtractor {
2206 return from.GetTabStopList ();
2209struct FirstIndentExtractor {
2212 return from.GetFirstIndent ();
2221 MarginsRec (TWIPS lhs, TWIPS rhs)
2230 inline bool operator!= (
const MarginsRec& rhs)
2232 return fLHS != rhs.fLHS or fRHS != rhs.fRHS;
2235struct MarginsRecExtractor {
2238 return MarginsRec (from.GetLeftMargin (), from.GetRightMargin ());
2241struct SpaceBeforeExtractor {
2244 return from.GetSpaceBefore ();
2247struct SpaceAfterExtractor {
2250 return from.GetSpaceAfter ();
2253struct LineSpacingExtractor {
2256 return from.GetLineSpacing ();
2259struct ListStyleExtractor {
2262 return from.GetListStyle ();
2265struct ListIndentLevelExtractor {
2268 return from.GetListIndentLevel ();
2272WordProcessor::WordProcessor ()
2274 , fSmartQuoteMode (true)
2275 , fParagraphDatabase (nullptr)
2276 , fICreatedParaDB (false)
2277 , fHidableTextDatabase (nullptr)
2278 , fICreatedHidableTextDB (false)
2280 , fCachedCurSelFontSpec ()
2281 , fCachedCurSelJustification (eLeftJustify)
2282 , fCachedCurSelJustificationUnique (false)
2283 , fCachedCurSelFontSpecValid (false)
2284 , fShowParagraphGlyphs (false)
2285 , fShowTabGlyphs (false)
2286 , fShowSpaceGlyphs (false)
2288 fWPIdler.fWP =
this;
2289 IdleManager::Get ().AddIdler (&fWPIdler);
2290 IdleManager::Get ().SetIdlerFrequncy (&fWPIdler, 0.25s);
2293WordProcessor::~WordProcessor ()
2295 IdleManager::Get ().RemoveIdler (&fWPIdler);
2298void WordProcessor::HookLosingTextStore ()
2300 HookLosingTextStore_ ();
2301 inherited::HookLosingTextStore ();
2304void WordProcessor::HookLosingTextStore_ ()
2307 MarkersOfATypeMarkerSink2Vector<WordProcessorTable> tables;
2308 GetTextStore ().CollectAllMarkersInRangeInto (GetTextStore ().GetStart (), GetTextStore ().GetEnd (),
this, tables);
2309#if qConstNonConstPtrConversionsWithTemplatedMemberFunctionBug
2310 WordProcessorTable** t = Traversal::Iterator2Pointer (tables.fResultArray.begin ());
2311 WordProcessorTable*
const* tt = t;
2312 GetTextStore ().RemoveAndDeleteMarkers (tt, tables.fResult.size ());
2314 GetTextStore ().RemoveAndDeleteMarkers (
Containers::Start (tables.fResult), tables.fResult.size ());
2323 if (fICreatedParaDB) {
2324 fICreatedParaDB =
false;
2325 if (fParagraphDatabase.get () !=
nullptr) {
2326 fParagraphDatabase.reset ();
2327 HookParagraphDatabaseChanged ();
2330 if (fICreatedHidableTextDB) {
2331 SetHidableTextDatabase (
nullptr);
2332 fICreatedHidableTextDB =
false;
2335 if (fHidableTextDatabase.get () !=
nullptr) {
2336 fHidableTextDatabase->SetInternalizer (
nullptr);
2337 fHidableTextDatabase->SetExternalizer (
nullptr);
2341void WordProcessor::HookGainedNewTextStore ()
2347 if (fParagraphDatabase.get () !=
nullptr) {
2348 SetPartition (fParagraphDatabase->GetPartition ());
2350 inherited::HookGainedNewTextStore ();
2351 HookGainedNewTextStore_ ();
2354void WordProcessor::HookGainedNewTextStore_ ()
2356 if (fParagraphDatabase.get () ==
nullptr) {
2357 SetParagraphDatabase (
nullptr);
2359 if (fHidableTextDatabase.get () ==
nullptr) {
2360 SetHidableTextDatabase (MakeSharedPtr<UniformHidableTextMarkerOwner> (GetTextStore ()));
2361 fICreatedHidableTextDB =
true;
2365shared_ptr<Partition> WordProcessor::MakeDefaultPartition ()
const
2369 if (fParagraphDatabase.get () ==
nullptr) {
2370 return MakeSharedPtr<LineBasedPartition> (GetTextStore ());
2373 const MarkerOwner* mo = fParagraphDatabase.get ();
2374 return MakeSharedPtr<WPPartition> (GetTextStore (), *
const_cast<MarkerOwner*
> (mo));
2387void WordProcessor::SetParagraphDatabase (
const shared_ptr<AbstractParagraphDatabaseRep>& paragraphDatabase)
2389 fParagraphDatabase = paragraphDatabase;
2390 fICreatedParaDB =
false;
2391 if (fParagraphDatabase.get () ==
nullptr and PeekAtTextStore () !=
nullptr) {
2392 fParagraphDatabase = MakeSharedPtr<ParagraphDatabaseRep> (GetTextStore ());
2393 fICreatedParaDB =
true;
2396 HookParagraphDatabaseChanged ();
2406void WordProcessor::HookParagraphDatabaseChanged ()
2408 if (PeekAtTextStore () !=
nullptr) {
2409 HookParagraphDatabaseChanged_ ();
2417void WordProcessor::HookParagraphDatabaseChanged_ ()
2425 if (fParagraphDatabase.get () !=
nullptr) {
2426 SetPartition (fParagraphDatabase->GetPartition ());
2428 SetExternalizer (MakeDefaultExternalizer ());
2429 SetInternalizer (MakeDefaultInternalizer ());
2444void WordProcessor::SetHidableTextDatabase (
const shared_ptr<HidableTextMarkerOwner>& hidableTextDatabase)
2447 if (fHidableTextDatabase.get () !=
nullptr) {
2448 fHidableTextDatabase->SetInternalizer (shared_ptr<FlavorPackageInternalizer> ());
2449 fHidableTextDatabase->SetExternalizer (shared_ptr<FlavorPackageExternalizer> ());
2452 fHidableTextDatabase = hidableTextDatabase;
2453 fICreatedHidableTextDB =
false;
2454 HookHidableTextDatabaseChanged ();
2464void WordProcessor::HookHidableTextDatabaseChanged ()
2466 HookHidableTextDatabaseChanged_ ();
2475void WordProcessor::HookHidableTextDatabaseChanged_ ()
2477 if (PeekAtTextStore () !=
nullptr) {
2478 SetExternalizer (MakeDefaultExternalizer ());
2479 SetInternalizer (MakeDefaultInternalizer ());
2483shared_ptr<FlavorPackageInternalizer> WordProcessor::MakeDefaultInternalizer ()
2485 return MakeSharedPtr<WordProcessorFlavorPackageInternalizer> (GetTextStore (), GetStyleDatabase (), GetParagraphDatabase (),
2486 GetHidableTextDatabase ());
2489shared_ptr<FlavorPackageExternalizer> WordProcessor::MakeDefaultExternalizer ()
2491 return MakeSharedPtr<WordProcessorFlavorPackageExternalizer> (GetTextStore (), GetStyleDatabase (), GetParagraphDatabase (),
2492 GetHidableTextDatabase ());
2499void WordProcessor::HookInternalizerChanged ()
2501 inherited::HookInternalizerChanged ();
2502 if (fHidableTextDatabase.get () !=
nullptr) {
2503 fHidableTextDatabase->SetInternalizer (GetInternalizer ());
2511void WordProcessor::HookExternalizerChanged ()
2513 inherited::HookExternalizerChanged ();
2514 if (fHidableTextDatabase.get () !=
nullptr) {
2515 fHidableTextDatabase->SetExternalizer (GetExternalizer ());
2524void WordProcessor::InternalizeBestFlavor (
ReaderFlavorPackage& flavorPackage,
bool updateCursorPosition,
bool autoScroll, UpdateMode updateMode)
2526 WordProcessorTable* t = GetActiveTable ();
2528 WordProcessorFlavorPackageInternalizer* internalizerRep =
2529 dynamic_cast<WordProcessorFlavorPackageInternalizer*
> (
static_cast<FlavorPackageInternalizer*
> (GetInternalizer ().get ()));
2532 bool oldFlagVal = internalizerRep->GetOverwriteTableMode ();
2533 internalizerRep->SetOverwriteTableMode (
true);
2535 size_t selEnd = GetSelectionEnd ();
2536 Assert (selEnd - GetSelectionStart () == 1);
2540 bool good = GetInternalizer ()->InternalizeBestFlavor (flavorPackage, selEnd, selEnd);
2543 ScrollToSelection ();
2545 if (updateMode == eImmediateUpdate) {
2552 internalizerRep->SetOverwriteTableMode (oldFlagVal);
2555 internalizerRep->SetOverwriteTableMode (oldFlagVal);
2560 inherited::InternalizeBestFlavor (flavorPackage, updateCursorPosition, autoScroll, updateMode);
2571 WordProcessorFlavorPackageExternalizer* externalizerRep =
2572 dynamic_cast<WordProcessorFlavorPackageExternalizer*
> (
static_cast<FlavorPackageExternalizer*
> (GetExternalizer ().get ()));
2575 bool oldFlagVal = externalizerRep->GetUseTableSelection ();
2576 externalizerRep->SetUseTableSelection (
true);
2578 inherited::ExternalizeFlavors (flavorPackage);
2579 externalizerRep->SetUseTableSelection (oldFlagVal);
2582 externalizerRep->SetUseTableSelection (oldFlagVal);
2592void WordProcessor::InterectiveSetRegionHidable (
bool hidable)
2596 BreakInGroupedCommands ();
2598 UndoableContextHelper undoContext (*
this, hidable ? GetCommandNames ().fHideCommandName : GetCommandNames ().fUnHideCommandName, false);
2601 GetHidableTextDatabase ()->MakeRegionHidable (undoContext.GetUndoRegionStart (), undoContext.GetUndoRegionEnd ());
2604 GetHidableTextDatabase ()->MakeRegionUnHidable (undoContext.GetUndoRegionStart (), undoContext.GetUndoRegionEnd ());
2607 undoContext.CommandComplete ();
2615Justification WordProcessor::GetJustification (
size_t characterPos)
const
2617 if (fParagraphDatabase.get () ==
nullptr) {
2618 throw NoParagraphDatabaseAvailable ();
2620 return fParagraphDatabase->GetParagraphInfo (characterPos).GetJustification ();
2628bool WordProcessor::GetJustification (
size_t from,
size_t to, Justification* justification)
const
2631 return CheckForCommonParaValue (JustificationExtractor (), fParagraphDatabase, from, to, justification);
2639void WordProcessor::SetJustification (
size_t from,
size_t to, Justification justification)
2641 Require (from <= to);
2643 pi.SetJustification (justification);
2644 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2647StandardTabStopList WordProcessor::GetDefaultStandardTabStopList ()
2649 return StandardTabStopList{};
2657StandardTabStopList WordProcessor::GetStandardTabStopList (
size_t characterPos)
const
2659 return fParagraphDatabase->GetParagraphInfo (characterPos).GetTabStopList ();
2667bool WordProcessor::GetStandardTabStopList (
size_t from,
size_t to, StandardTabStopList* tabStops)
const
2670 return CheckForCommonParaValue (TabStopExtractor (), fParagraphDatabase, from, to, tabStops);
2678void WordProcessor::SetStandardTabStopList (
size_t from,
size_t to, StandardTabStopList tabStops)
2680 Require (from <= to);
2682 pi.SetTabStopList (tabStops);
2683 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2691void WordProcessor::GetMargins (
size_t characterPos, TWIPS* leftMargin, TWIPS* rightMargin)
const
2695 const ParagraphInfo& pi = fParagraphDatabase->GetParagraphInfo (characterPos);
2699 *leftMargin = pi.GetLeftMargin ();
2700 *rightMargin = pi.GetRightMargin ();
2703bool WordProcessor::GetMargins (
size_t from,
size_t to, TWIPS* leftMargin, TWIPS* rightMargin)
const
2707 MarginsRec mrResult;
2708 bool result = CheckForCommonParaValue (MarginsRecExtractor (), fParagraphDatabase, from, to, &mrResult);
2709 *leftMargin = mrResult.fLHS;
2710 *rightMargin = mrResult.fRHS;
2718void WordProcessor::SetMargins (
size_t from,
size_t to, TWIPS leftMargin, TWIPS rightMargin)
2720 Require (from <= to);
2722 pi.SetMargins (leftMargin, rightMargin);
2723 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2731TWIPS WordProcessor::GetFirstIndent (
size_t characterPos)
const
2733 return fParagraphDatabase->GetParagraphInfo (characterPos).GetFirstIndent ();
2741bool WordProcessor::GetFirstIndent (
size_t from,
size_t to, TWIPS* firstIndent)
const
2744 return CheckForCommonParaValue (FirstIndentExtractor (), fParagraphDatabase, from, to, firstIndent);
2751void WordProcessor::SetFirstIndent (
size_t from,
size_t to, TWIPS firstIndent)
2753 Require (from <= to);
2755 pi.SetFirstIndent (firstIndent);
2756 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2764TWIPS WordProcessor::GetSpaceBefore (
size_t characterPos)
const
2766 if (fParagraphDatabase.get () ==
nullptr) {
2767 throw NoParagraphDatabaseAvailable{};
2769 return fParagraphDatabase->GetParagraphInfo (characterPos).GetSpaceBefore ();
2777bool WordProcessor::GetSpaceBefore (
size_t from,
size_t to, TWIPS* sb)
const
2780 return CheckForCommonParaValue (SpaceBeforeExtractor{}, fParagraphDatabase, from, to, sb);
2788void WordProcessor::SetSpaceBefore (
size_t from,
size_t to, TWIPS sb)
2790 Require (from <= to);
2791 if (fParagraphDatabase.get () ==
nullptr) {
2792 throw NoParagraphDatabaseAvailable{};
2795 pi.SetSpaceBefore (sb);
2796 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2804TWIPS WordProcessor::GetSpaceAfter (
size_t characterPos)
const
2806 if (fParagraphDatabase.get () ==
nullptr) {
2807 throw NoParagraphDatabaseAvailable ();
2809 return fParagraphDatabase->GetParagraphInfo (characterPos).GetSpaceAfter ();
2817bool WordProcessor::GetSpaceAfter (
size_t from,
size_t to, TWIPS* sa)
const
2820 return CheckForCommonParaValue (SpaceAfterExtractor (), fParagraphDatabase, from, to, sa);
2828void WordProcessor::SetSpaceAfter (
size_t from,
size_t to, TWIPS sa)
2830 Require (from <= to);
2831 if (fParagraphDatabase.get () ==
nullptr) {
2832 throw NoParagraphDatabaseAvailable ();
2835 pi.SetSpaceAfter (sa);
2836 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2844LineSpacing WordProcessor::GetLineSpacing (
size_t characterPos)
const
2846 if (fParagraphDatabase.get () ==
nullptr) {
2847 throw NoParagraphDatabaseAvailable ();
2849 return fParagraphDatabase->GetParagraphInfo (characterPos).GetLineSpacing ();
2857bool WordProcessor::GetLineSpacing (
size_t from,
size_t to, LineSpacing* sl)
const
2860 return CheckForCommonParaValue (LineSpacingExtractor (), fParagraphDatabase, from, to, sl);
2868void WordProcessor::SetLineSpacing (
size_t from,
size_t to, LineSpacing sl)
2870 Require (from <= to);
2872 pi.SetLineSpacing (sl);
2873 if (fParagraphDatabase.get () ==
nullptr) {
2874 throw NoParagraphDatabaseAvailable ();
2876 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2884ListStyle WordProcessor::GetListStyle (
size_t characterPos)
const
2886 if (fParagraphDatabase.get () ==
nullptr) {
2887 throw NoParagraphDatabaseAvailable ();
2889 return fParagraphDatabase->GetParagraphInfo (characterPos).GetListStyle ();
2897bool WordProcessor::GetListStyle (
size_t from,
size_t to, ListStyle* listStyle)
const
2900 return CheckForCommonParaValue (ListStyleExtractor (), fParagraphDatabase, from, to, listStyle);
2908void WordProcessor::SetListStyle (
size_t from,
size_t to, ListStyle listStyle,
bool autoFormat)
2910 Require (from <= to);
2912 pi.SetListStyle (listStyle);
2913 if (fParagraphDatabase.get () ==
nullptr) {
2914 throw NoParagraphDatabaseAvailable ();
2916 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2919 AutoFormatIndentedText (from, to);
2928unsigned char WordProcessor::GetListIndentLevel (
size_t characterPos)
const
2930 if (fParagraphDatabase.get () ==
nullptr) {
2931 throw NoParagraphDatabaseAvailable ();
2933 return fParagraphDatabase->GetParagraphInfo (characterPos).GetListIndentLevel ();
2941bool WordProcessor::GetListIndentLevel (
size_t from,
size_t to,
unsigned char* indentLevel)
const
2944 return CheckForCommonParaValue (ListIndentLevelExtractor (), fParagraphDatabase, from, to, indentLevel);
2952void WordProcessor::SetListIndentLevel (
size_t from,
size_t to,
unsigned char indentLevel,
bool autoFormat)
2954 Require (from <= to);
2956 pi.SetListIndentLevel (indentLevel);
2957 if (fParagraphDatabase.get () ==
nullptr) {
2958 throw NoParagraphDatabaseAvailable ();
2960 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2962 AutoFormatIndentedText (from, to);
2973void WordProcessor::AutoFormatIndentedText (
size_t from,
size_t to)
2975 for (PartitionMarker* pm = GetPartitionMarkerContainingPosition (from); pm !=
nullptr and pm->GetStart () <= to; pm = pm->GetNext ()) {
2977 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (pm->GetStart ());
2979 if (pi.GetListStyle () == eListStyle_None) {
2980 newPI.SetFirstIndent (TWIPS{0});
2981 newPI.SetMargins (TWIPS{0}, pi.GetRightMargin ());
2982 newPI.SetTabStopList (StandardTabStopList ());
2985 const int kTWIPSIncrement = 1440 / 4;
2986 TWIPS marginAt = TWIPS (kTWIPSIncrement * 2 * (pi.GetListIndentLevel () + 1));
2987 newPI.SetFirstIndent (TWIPS (-kTWIPSIncrement));
2988 newPI.SetMargins (marginAt, pi.GetRightMargin ());
2989 StandardTabStopList tabStops;
2990 tabStops.fTabStops.push_back (marginAt);
2991 newPI.SetTabStopList (tabStops);
2993 fParagraphDatabase->SetParagraphInfo (pm->GetStart (), pm->GetLength (), newPI);
3001void WordProcessor::SetSelection (
size_t start,
size_t end)
3003 size_t oldSelStart = 0;
3004 size_t oldSelEnd = 0;
3005 GetSelection (&oldSelStart, &oldSelEnd);
3006 inherited::SetSelection (start, end);
3011 if (oldSelStart != start or oldSelEnd != end) {
3012 vector<WordProcessorTable*> tables;
3013 size_t checkRangeStart1 = start;
3014 size_t checkRangeEnd1 = oldSelStart;
3015 if (checkRangeStart1 < checkRangeEnd1) {
3016 tables = GetTablesInRange (checkRangeStart1, checkRangeEnd1);
3019 size_t checkRangeStart2 = FindPreviousCharacter (oldSelEnd);
3020 size_t checkRangeEnd2 = end;
3021 if (checkRangeStart2 < checkRangeEnd2) {
3022 vector<WordProcessorTable*> tables2 = GetTablesInRange (checkRangeStart2, checkRangeEnd2);
3023 tables.insert (tables.end (), tables2.begin (), tables2.end ());
3025 for (
auto i = tables.begin (); i != tables.end (); ++i) {
3026 WordProcessorTable* t = *i;
3027 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*t, *
const_cast<WordProcessor*
> (
this));
3028 t->SetCellSelection (0, t->GetRowCount (), 0, t->GetColumnCount ());
3032 fCachedCurSelFontSpecValid =
false;
3039bool WordProcessor::GetCaretShownSituation ()
const
3041 if (inherited::GetCaretShownSituation ()) {
3045 WordProcessorTable* table = GetActiveTable ();
3046 if (table !=
nullptr) {
3047 return table->GetCaretShownSituation ();
3056Led_Rect WordProcessor::CalculateCaretRect ()
const
3058 WordProcessorTable* table = GetActiveTable ();
3059 if (table !=
nullptr) {
3060 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*table, *
const_cast<WordProcessor*
> (
this));
3061 return table->CalculateCaretRect ();
3063 return inherited::CalculateCaretRect ();
3071void WordProcessor::OnTypedNormalCharacter (Led_tChar theChar,
bool optionPressed,
bool shiftPressed,
bool commandPressed,
3072 bool controlPressed,
bool altKeyPressed)
3074 WordProcessorTable* table = GetActiveTable ();
3075 if (table !=
nullptr) {
3076 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*table, *
const_cast<WordProcessor*
> (
this));
3077 if (table->OnTypedNormalCharacter (theChar, optionPressed, shiftPressed, commandPressed, controlPressed, altKeyPressed)) {
3083 if (theChar ==
'\t' and not(optionPressed or commandPressed or controlPressed or altKeyPressed)) {
3084 ListStyle ls = eListStyle_None;
3085 if (GetListStyle (GetSelectionStart (), GetSelectionEnd (), &ls) and ls != eListStyle_None) {
3086 InteractiveDoIndentChange (not shiftPressed);
3090 if (theChar ==
'"' and GetSmartQuoteMode () and not(optionPressed or commandPressed or controlPressed or altKeyPressed)) {
3091 const wchar_t kSpecialOpenQuote = 8220;
3092 const wchar_t kSpecialCloseQuote = 8221;
3093 bool isAQuoteToClose =
false;
3094 size_t selStart = GetSelectionStart ();
3097 const size_t kScanBackSize = 1024;
3098 size_t scanBackTo =
static_cast<size_t> (max (0,
static_cast<int> (selStart) -
static_cast<int> (kScanBackSize)));
3100 size_t scanBackCount = selStart - scanBackTo;
3101 CopyOut (scanBackTo, scanBackCount, buf.data ());
3102 for (
size_t i = scanBackCount; i != 0; --i) {
3103 if (buf[i - 1] == kSpecialCloseQuote) {
3107 else if (buf[i - 1] == kSpecialOpenQuote) {
3108 isAQuoteToClose =
true;
3113 wchar_t quoteChar = isAQuoteToClose ? kSpecialCloseQuote : kSpecialOpenQuote;
3114 inherited::OnTypedNormalCharacter (quoteChar, optionPressed, shiftPressed, commandPressed, controlPressed, altKeyPressed);
3117 inherited::OnTypedNormalCharacter (theChar, optionPressed, shiftPressed, commandPressed, controlPressed, altKeyPressed);
3121bool WordProcessor::ProcessSimpleClick (Led_Point clickedAt,
unsigned clickCount,
bool extendSelection,
size_t* dragAnchor)
3124 size_t clickedOnChar = GetCharAtWindowLocation (clickedAt);
3125 Led_Rect charRect = GetCharWindowLocation (clickedOnChar);
3133 Led_Rect tstClickRect = charRect;
3134 const DistanceType kHMargin = 3;
3135 tstClickRect.left += kHMargin;
3136 tstClickRect.right -= kHMargin;
3137 if (tstClickRect.Contains (clickedAt)) {
3138 vector<WordProcessorTable*> tables = GetTablesInRange (clickedOnChar, clickedOnChar + 1);
3139 Assert (tables.size () == 0 or tables.size () == 1);
3140 if (tables.size () == 1) {
3141 WordProcessorTable* t = tables[0];
3142 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*t, *
const_cast<WordProcessor*
> (
this));
3143 if (clickCount == 1) {
3146 *dragAnchor = clickedOnChar;
3148 return t->ProcessSimpleClick (clickedAt - charRect.GetOrigin (), clickCount, extendSelection);
3151 return inherited::ProcessSimpleClick (clickedAt, clickCount, extendSelection, dragAnchor);
3158void WordProcessor::WhileSimpleMouseTracking (Led_Point newMousePos,
size_t dragAnchor)
3160 size_t clickedOnChar = GetCharAtWindowLocation (newMousePos);
3161 size_t oldSelStart = GetSelectionStart ();
3162 size_t oldSelEnd = GetSelectionEnd ();
3169 if ((clickedOnChar == dragAnchor or clickedOnChar + 1 == dragAnchor) and (oldSelEnd - oldSelStart == 1)) {
3170 vector<WordProcessorTable*> tables = GetTablesInRange (clickedOnChar, clickedOnChar + 1);
3171 if (tables.size () == 1) {
3172 WordProcessorTable* t = tables[0];
3173 Led_Rect charRect = GetCharWindowLocation (t->GetStart ());
3174 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*t, *
const_cast<WordProcessor*
> (
this));
3176 t->WhileSimpleMouseTracking (newMousePos - charRect.GetOrigin ());
3180 inherited::WhileSimpleMouseTracking (newMousePos, dragAnchor);
3182 DbgTrace (
"WordProcessor::WhileSimpleMouseTracking (tickCount=%f, newMousePos=(%d,%d), clickedOnChar=%d, dragAnchor=%d)\n",
3183 Time::GetTickCount (), newMousePos.v, newMousePos.h, clickedOnChar, dragAnchor
3193WordProcessorTable* WordProcessor::InsertTable (
size_t at)
3195 WordProcessorTable* t =
new WordProcessorTable (fParagraphDatabase.get (), at);
3196 t->SetDimensions (1, 1);
3207vector<WordProcessorTable*> WordProcessor::GetTablesInRange (
size_t from,
size_t to)
const
3209 if (to ==
static_cast<size_t> (-1)) {
3210 to = GetTextStore ().GetLength ();
3212 Require (from <= to);
3213 Require (to <= GetTextStore ().GetLength () + 1);
3214 MarkersOfATypeMarkerSink2Vector<WordProcessorTable> result;
3215 if (fParagraphDatabase.get () !=
nullptr) {
3216 GetTextStore ().CollectAllMarkersInRangeInto (from, to, fParagraphDatabase.get (), result);
3218 return result.fResult;
3225WordProcessorTable* WordProcessor::GetTableAt (
size_t from)
const
3227 size_t to = from + 1;
3228 Require (to <= GetTextStore ().GetLength () + 1);
3229 MarkerOfATypeMarkerSink<WordProcessorTable> result;
3230 if (fParagraphDatabase.get () !=
nullptr) {
3231 GetTextStore ().CollectAllMarkersInRangeInto (from, to, fParagraphDatabase.get (), result);
3233 return result.fResult;
3236WordProcessor::CommandNames WordProcessor::MakeDefaultCommandNames ()
3238 WordProcessor::CommandNames cmdNames;
3239 cmdNames.fJustificationCommandName = Led_SDK_TCHAROF (
"Justification Change");
3240 cmdNames.fStandardTabStopListCommandName = Led_SDK_TCHAROF (
"Set Tabs");
3241 cmdNames.fMarginsCommandName = Led_SDK_TCHAROF (
"Set Margins");
3242 cmdNames.fFirstIndentCommandName = Led_SDK_TCHAROF (
"Set First Indent");
3243 cmdNames.fMarginsAndFirstIndentCommandName = Led_SDK_TCHAROF (
"Set Margins and First Indent");
3244 cmdNames.fParagraphSpacingCommandName = Led_SDK_TCHAROF (
"Change Paragraph Spacing");
3245 cmdNames.fHideCommandName = Led_SDK_TCHAROF (
"Hide");
3246 cmdNames.fUnHideCommandName = Led_SDK_TCHAROF (
"UnHide");
3247 cmdNames.fSetListStyleCommandName = Led_SDK_TCHAROF (
"Change List Style");
3248 cmdNames.fIndentLevelChangeCommandName = Led_SDK_TCHAROF (
"Change Indent Level");
3249 cmdNames.fInsertTableCommandName = Led_SDK_TCHAROF (
"Insert Table");
3250 cmdNames.fInsertTableRowAboveCommandName = Led_SDK_TCHAROF (
"Insert Table Row Above");
3251 cmdNames.fInsertTableRowBelowCommandName = Led_SDK_TCHAROF (
"Insert Table Row Below");
3252 cmdNames.fInsertTableColBeforeCommandName = Led_SDK_TCHAROF (
"Insert Table Column Before");
3253 cmdNames.fInsertTableColAfterCommandName = Led_SDK_TCHAROF (
"Insert Table Column After");
3254 cmdNames.fInsertURLCommandName = Led_SDK_TCHAROF (
"Insert URL");
3255 cmdNames.fRemoveTableRowsCommandName = Led_SDK_TCHAROF (
"Remove Rows");
3256 cmdNames.fRemoveTableColumnsCommandName = Led_SDK_TCHAROF (
"Remove Columns");
3257 cmdNames.fEmbeddingTypeName_ImageDIB = Led_SDK_TCHAROF (
"image (DIB)");
3258 cmdNames.fEmbeddingTypeName_URL = Led_SDK_TCHAROF (
"URL");
3259 cmdNames.fEmbeddingTypeName_ImageMacPict = Led_SDK_TCHAROF (
"image (MacPICT)");
3260 cmdNames.fEmbeddingTypeName_Table = Led_SDK_TCHAROF (
"table");
3261 cmdNames.fEmbeddingTypeName_Unknown = Led_SDK_TCHAROF (
"unknown");
3262 cmdNames.fFontSizeChange_Other_NoArg = Led_SDK_TCHAROF (
"Other...");
3263 cmdNames.fFontSizeChange_Other_OneArg = Led_SDK_TCHAROF (
"Other (%d)...");
3264 cmdNames.fTablePropertiesCommandName = Led_SDK_TCHAROF (
"Table Properties...")
3265#if qStroika_Foundation_Common_Platform_Windows
3266 Led_SDK_TCHAROF (
"\tAlt+Enter")
3269 cmdNames.fGenericEmbeddingPropertiesCommandName = Led_SDK_TCHAROF (
"Properties")
3270#if qStroika_Foundation_Common_Platform_Windows
3271 Led_SDK_TCHAROF (
"\tAlt+Enter")
3274 cmdNames.fChangeTablePropertiesCommandName = Led_SDK_TCHAROF (
"Change table properties");
3284DistanceType WordProcessor::ComputeMaxHScrollPos ()
const
3286 DistanceType cachedLayoutWidth = 0;
3294 TextInteractor::Tablet_Acquirer tablet_ (
this);
3295 Tablet* tablet = tablet_;
3296 DistanceType width = tablet->CvtFromTWIPSH (CalculateFarthestRightMargin ());
3297 if (GetHScrollPos () != 0) {
3298 width = max (width, GetHScrollPos () + GetWindowRect ().GetWidth ());
3300 cachedLayoutWidth = max (width, DistanceType (1));
3302 DistanceType wWidth = GetWindowRect ().GetWidth ();
3303 if (cachedLayoutWidth > wWidth) {
3304 return (cachedLayoutWidth - wWidth);
3319TWIPS WordProcessor::CalculateFarthestRightMarginInDocument ()
const
3321 CoordinateType longestRowWidth = 0;
3322 RowReference curRow = RowReference{GetFirstPartitionMarker (), 0};
3324 CoordinateType rhsMargin = 0;
3325 GetLayoutMargins (curRow,
nullptr, &rhsMargin);
3326 longestRowWidth = max (longestRowWidth, rhsMargin);
3327 }
while (GetNextRowReference (&curRow));
3328 Tablet_Acquirer tablet_ (
this);
3329 Tablet* tablet = tablet_;
3330 return tablet->CvtToTWIPSH (longestRowWidth);
3338TWIPS WordProcessor::GetFarthestRightMarginInDocument ()
const
3340 AbstractParagraphDatabaseRep* pdbRep = GetParagraphDatabase ().get ();
3342 if (pdbRep->fCachedFarthestRightMarginInDocument == kBadCachedFarthestRightMarginInDocument) {
3343 pdbRep->fCachedFarthestRightMarginInDocument = CalculateFarthestRightMarginInDocument ();
3345 return pdbRep->fCachedFarthestRightMarginInDocument;
3356TWIPS WordProcessor::CalculateFarthestRightMarginInWindow ()
const
3358 CoordinateType longestRowWidth = 0;
3359 size_t rowsLeftInWindow = GetTotalRowsInWindow_ ();
3360 RowReference curRow = GetTopRowReferenceInWindow ();
3362 CoordinateType rhsMargin = 0;
3363 GetLayoutMargins (curRow,
nullptr, &rhsMargin);
3364 longestRowWidth = max (longestRowWidth, rhsMargin);
3365 }
while (rowsLeftInWindow-- > 0 and GetNextRowReference (&curRow));
3366 Tablet_Acquirer tablet_ (
this);
3367 Tablet* tablet = tablet_;
3368 return tablet->CvtToTWIPSH (longestRowWidth);
3377TWIPS WordProcessor::CalculateFarthestRightMargin ()
const
3379 return GetFarthestRightMarginInDocument ();
3382void WordProcessor::InvalidateAllCaches ()
3384 inherited::InvalidateAllCaches ();
3385 shared_ptr<AbstractParagraphDatabaseRep> pdb = GetParagraphDatabase ();
3386 if (pdb.get () !=
nullptr) {
3387 static_cast<AbstractParagraphDatabaseRep*
> (pdb.get ())->fCachedFarthestRightMarginInDocument = kBadCachedFarthestRightMarginInDocument;
3391void WordProcessor::TabletChangedMetrics ()
3393 inherited::TabletChangedMetrics ();
3394 shared_ptr<AbstractParagraphDatabaseRep> pdb = GetParagraphDatabase ();
3395 if (pdb.get () !=
nullptr) {
3396 static_cast<AbstractParagraphDatabaseRep*
> (pdb.get ())->fCachedFarthestRightMarginInDocument = kBadCachedFarthestRightMarginInDocument;
3400void WordProcessor::DidUpdateText (
const UpdateInfo& updateInfo)
noexcept
3402 inherited::DidUpdateText (updateInfo);
3403 fCachedCurSelFontSpecValid =
false;
3406void WordProcessor::AssureCurSelFontCacheValid ()
const
3408 if (not fCachedCurSelFontSpecValid) {
3409 Assert (GetSelectionEnd () >= GetSelectionStart ());
3410 size_t selectionLength = GetSelectionEnd () - GetSelectionStart ();
3411 WordProcessorTable* aT = GetActiveTable ();
3412 if (aT !=
nullptr) {
3413 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, *
const_cast<WordProcessor*
> (
this));
3414 aT->AssureCurSelFontCacheValid (&fCachedCurSelFontSpec);
3415 fCachedCurSelJustification = eLeftJustify;
3416 fCachedCurSelJustificationUnique =
false;
3419 fCachedCurSelFontSpec = GetContinuousStyleInfo (GetSelectionStart (), selectionLength);
3420 fCachedCurSelJustificationUnique = GetJustification (GetSelectionStart (), GetSelectionEnd (), &fCachedCurSelJustification);
3422 fCachedCurSelFontSpecValid =
true;
3426void WordProcessor::DoSingleCharCursorEdit (CursorMovementDirection direction, CursorMovementUnit movementUnit, CursorMovementAction action,
3427 UpdateMode updateMode,
bool scrollToSelection)
3429 WordProcessorTable* table = GetActiveTable ();
3430 if (table !=
nullptr) {
3431 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*table, *
const_cast<WordProcessor*
> (
this));
3432 if (table->DoSingleCharCursorEdit (direction, movementUnit, action, updateMode,
false)) {
3433 if (scrollToSelection) {
3434 ScrollToSelection ();
3439 inherited::DoSingleCharCursorEdit (direction, movementUnit, action, updateMode, scrollToSelection);
3442bool WordProcessor::OnUpdateCommand (CommandUpdater* enabler)
3446 WordProcessorTable* aT = GetActiveTable ();
3447 if (aT !=
nullptr) {
3448 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, *
const_cast<WordProcessor*
> (
this));
3449 if (aT->OnUpdateCommand (enabler)) {
3454 switch (enabler->GetCmdID ()) {
3455 case kFontStylePlain_CmdID: {
3456 OnUpdateFontStylePlainCommand (enabler);
3459 case kFontStyleBold_CmdID: {
3460 OnUpdateFontStyleBoldCommand (enabler);
3463 case kFontStyleItalic_CmdID: {
3464 OnUpdateFontStyleItalicCommand (enabler);
3467 case kFontStyleUnderline_CmdID: {
3468 OnUpdateFontStyleUnderlineCommand (enabler);
3471#if qStroika_Foundation_Common_Platform_Windows
3472 case kFontStyleStrikeout_CmdID: {
3473 OnUpdateFontStyleStrikeoutCommand (enabler);
3477#if qStroika_Foundation_Common_Platform_MacOS
3478 case kFontStyleOutline_CmdID: {
3479 OnUpdateFontStyleOutlineCommand (enabler);
3482 case kFontStyleShadow_CmdID: {
3483 OnUpdateFontStyleShadowCommand (enabler);
3486 case kFontStyleCondensed_CmdID: {
3487 OnUpdateFontStyleCondensedCommand (enabler);
3490 case kFontStyleExtended_CmdID: {
3491 OnUpdateFontStyleExtendedCommand (enabler);
3495 case kSubScriptCommand_CmdID: {
3496 OnUpdateFontStyleSubscriptCommand (enabler);
3499 case kSuperScriptCommand_CmdID: {
3500 OnUpdateFontStyleSuperscriptCommand (enabler);
3503 case kChooseFontCommand_CmdID: {
3504 OnUpdateChooseFontCommand (enabler);
3507 case kInsertTable_CmdID: {
3508 OnUpdateInsertTableCommand (enabler);
3511 case kInsertURL_CmdID: {
3512 OnUpdateInsertURLCommand (enabler);
3515 case kInsertSymbol_CmdID: {
3516 OnUpdateInsertSymbolCommand (enabler);
3519 case kHideSelection_CmdID: {
3520 OnUpdateHideSelectionCommands (enabler);
3523 case kUnHideSelection_CmdID: {
3524 OnUpdateHideSelectionCommands (enabler);
3527 case kParagraphSpacingCommand_CmdID: {
3528 OnUpdateParagraphSpacingChangeCommand (enabler);
3531 case kParagraphIndentsCommand_CmdID: {
3532 OnUpdateParagraphIndentsChangeCommand (enabler);
3535 case kIncreaseIndent_CmdID: {
3536 OnUpdateIndentCommand (enabler);
3539 case kDecreaseIndent_CmdID: {
3540 OnUpdateIndentCommand (enabler);
3545 if (kFontMenuFirst_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kFontMenuLast_CmdID) {
3546 OnUpdateFontNameChangeCommand (enabler);
3549 else if (kBaseFontSize_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastFontSize_CmdID) {
3550 OnUpdateFontSizeChangeCommand (enabler);
3553 else if (kBaseFontColor_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastFontColor_CmdID) {
3554 OnUpdateFontColorChangeCommand (enabler);
3557 else if (kFirstSelectedEmbedding_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastSelectedEmbedding_CmdID) {
3558 OnUpdateSelectedEmbeddingExtendedCommand (enabler);
3561 else if (kFirstJustification_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastJustification_CmdID) {
3562 OnUpdateParagraphJustificationCommand (enabler);
3565 else if (kFirstShowHideGlyph_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastShowHideGlyph_CmdID) {
3566 OnUpdateShowHideGlyphCommand (enabler);
3569 else if (kFirstListStyle_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastListStyle_CmdID) {
3570 OnUpdateListStyleChangeCommand (enabler);
3574 return inherited::OnUpdateCommand (enabler);
3577bool WordProcessor::OnPerformCommand (CommandNumber commandNumber)
3579 WordProcessorTable* aT = GetActiveTable ();
3580 if (aT !=
nullptr) {
3581 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, *
const_cast<WordProcessor*
> (
this));
3582 if (aT->OnPerformCommand (commandNumber)) {
3587 switch (commandNumber) {
3588 case kFontStylePlain_CmdID: {
3589 OnFontStylePlainCommand ();
3592 case kFontStyleBold_CmdID: {
3593 OnFontStyleBoldCommand ();
3596 case kFontStyleItalic_CmdID: {
3597 OnFontStyleItalicCommand ();
3600 case kFontStyleUnderline_CmdID: {
3601 OnFontStyleUnderlineCommand ();
3604#if qStroika_Foundation_Common_Platform_Windows
3605 case kFontStyleStrikeout_CmdID: {
3606 OnFontStyleStrikeoutCommand ();
3610#if qStroika_Foundation_Common_Platform_MacOS
3611 case kFontStyleOutline_CmdID: {
3612 OnFontStyleOutlineCommand ();
3615 case kFontStyleShadow_CmdID: {
3616 OnFontStyleShadowCommand ();
3619 case kFontStyleCondensed_CmdID: {
3620 OnFontStyleCondensedCommand ();
3623 case kFontStyleExtended_CmdID: {
3624 OnFontStyleExtendedCommand ();
3628 case kSubScriptCommand_CmdID: {
3629 OnFontStyleSubscriptCommand ();
3632 case kSuperScriptCommand_CmdID: {
3633 OnFontStyleSuperscriptCommand ();
3636 case kChooseFontCommand_CmdID: {
3637 OnChooseFontCommand ();
3640 case kInsertTable_CmdID: {
3641 OnInsertTableCommand ();
3644 case kInsertURL_CmdID: {
3645 OnInsertURLCommand ();
3648 case kInsertSymbol_CmdID: {
3649 OnInsertSymbolCommand ();
3652 case kHideSelection_CmdID: {
3656 case kUnHideSelection_CmdID: {
3657 OnUnHideSelection ();
3660 case kParagraphSpacingCommand_CmdID: {
3661 OnParagraphSpacingChangeCommand ();
3664 case kParagraphIndentsCommand_CmdID: {
3665 OnParagraphIndentsChangeCommand ();
3668 case kIncreaseIndent_CmdID: {
3669 OnIndentCommand (commandNumber);
3672 case kDecreaseIndent_CmdID: {
3673 OnIndentCommand (commandNumber);
3678 if (kFontMenuFirst_CmdID <= commandNumber and commandNumber <= kFontMenuLast_CmdID) {
3679 OnFontNameChangeCommand (commandNumber);
3682 else if (kBaseFontSize_CmdID <= commandNumber and commandNumber <= kLastFontSize_CmdID) {
3683 OnFontSizeChangeCommand (commandNumber);
3686 else if (kBaseFontColor_CmdID <= commandNumber and commandNumber <= kLastFontColor_CmdID) {
3687 OnFontColorChangeCommand (commandNumber);
3690 else if (kFirstSelectedEmbedding_CmdID <= commandNumber and commandNumber <= kLastSelectedEmbedding_CmdID) {
3691 return OnSelectedEmbeddingExtendedCommand (commandNumber);
3693 else if (kFirstJustification_CmdID <= commandNumber and commandNumber <= kLastJustification_CmdID) {
3694 OnParagraphJustificationCommand (commandNumber);
3697 else if (kFirstShowHideGlyph_CmdID <= commandNumber and commandNumber <= kLastShowHideGlyph_CmdID) {
3698 OnShowHideGlyphCommand (commandNumber);
3701 else if (kFirstListStyle_CmdID <= commandNumber and commandNumber <= kLastListStyle_CmdID) {
3702 OnListStyleChangeCommand (commandNumber);
3706 return inherited::OnPerformCommand (commandNumber);
3709bool WordProcessor::PassAlongCommandToIntraCellModeTableCell (CommandNumber commandNumber)
3711 switch (commandNumber) {
3722 case kSelectAll_CmdID: {
3728 WordProcessorTable* aT = GetActiveTable ();
3731 if (aT !=
nullptr and aT->GetIntraCellMode (&row, &col)) {
3732 size_t intraCellStart = 0;
3733 size_t intraCellEnd = 0;
3734 aT->GetIntraCellSelection (&intraCellStart, &intraCellEnd);
3735 if (intraCellStart != 0) {
3738 size_t cellEnd = aT->GetCell (row, col).GetTextStore ().GetEnd ();
3739 if (intraCellEnd != cellEnd) {
3746 case kParagraphSpacingCommand_CmdID:
3748 case kParagraphIndentsCommand_CmdID:
3750 case kIncreaseIndent_CmdID:
3752 case kDecreaseIndent_CmdID:
3754 case kChooseFontCommand_CmdID:
3756 case kInsertURL_CmdID:
3758 case kHideSelection_CmdID:
3760 case kUnHideSelection_CmdID:
3765 if (kBaseFontSize_CmdID <= commandNumber and commandNumber <= kLastFontSize_CmdID) {
3768 if (kBaseFontColor_CmdID <= commandNumber and commandNumber <= kLastFontColor_CmdID) {
3771 if (kFirstJustification_CmdID <= commandNumber and commandNumber <= kLastJustification_CmdID) {
3774 if (kFirstListStyle_CmdID <= commandNumber and commandNumber <= kLastListStyle_CmdID) {
3777 if (kFontMenuFirst_CmdID <= commandNumber and commandNumber <= kFontMenuLast_CmdID) {
3780 if (kFontStyleCommand_FirstCmdId <= commandNumber and commandNumber <= kFontStyleCommand_LastCmdId) {
3783 if (kFirstSelectedEmbedding_CmdID <= commandNumber and commandNumber <= kLastSelectedEmbedding_CmdID) {
3790bool WordProcessor::PassAlongCommandToEachSelectedTableCell (CommandNumber commandNumber)
3792 switch (commandNumber) {
3798 case kHideSelection_CmdID:
3800 case kUnHideSelection_CmdID:
3805 if (kBaseFontSize_CmdID <= commandNumber and commandNumber <= kLastFontSize_CmdID) {
3808 if (kBaseFontColor_CmdID <= commandNumber and commandNumber <= kLastFontColor_CmdID) {
3811 if (kFirstJustification_CmdID <= commandNumber and commandNumber <= kLastJustification_CmdID) {
3814 if (kFirstListStyle_CmdID <= commandNumber and commandNumber <= kLastListStyle_CmdID) {
3817 if (kFontMenuFirst_CmdID <= commandNumber and commandNumber <= kFontMenuLast_CmdID) {
3820 if (kFontStyleCommand_FirstCmdId <= commandNumber and commandNumber <= kFontStyleCommand_LastCmdId) {
3833void WordProcessor::OnSelectAllCommand ()
3835 inherited::OnSelectAllCommand ();
3836 if (GetLength () == 1) {
3837 (void)OnPerformCommand (kSelectTable_CmdID);
3841void WordProcessor::OnUpdateFontNameChangeCommand (CommandUpdater* enabler)
3844 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3847 enabler->SetChecked (fontSpec.GetFontNameSpecifier_Valid () and
3848 (GetDialogSupport ().CmdNumToFontName (enabler->GetCmdID ()) == fontSpec.GetFontNameSpecifier ()));
3849 enabler->SetEnabled (
true);
3852void WordProcessor::OnFontNameChangeCommand (CommandNumber cmdNum)
3854 IncrementalFontSpecification applyFontSpec;
3855 applyFontSpec.SetFontNameSpecifier (GetDialogSupport ().CmdNumToFontName (cmdNum));
3856 InteractiveSetFont (applyFontSpec);
3859void WordProcessor::OnUpdateFontStylePlainCommand (CommandUpdater* enabler)
3862 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3863 enabler->SetChecked (fontSpec.GetStyle_Plain_Valid () and fontSpec.GetStyle_Plain ());
3864 enabler->SetEnabled (
true);
3867void WordProcessor::OnFontStylePlainCommand ()
3869 IncrementalFontSpecification applyFontSpec;
3870 applyFontSpec.SetStyle_Plain ();
3871 InteractiveSetFont (applyFontSpec);
3874void WordProcessor::OnUpdateFontStyleBoldCommand (CommandUpdater* enabler)
3877 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3878 enabler->SetChecked (fontSpec.GetStyle_Bold_Valid () and fontSpec.GetStyle_Bold ());
3879 enabler->SetEnabled (
true);
3882void WordProcessor::OnFontStyleBoldCommand ()
3884 IncrementalFontSpecification applyFontSpec;
3885 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3886 applyFontSpec.SetStyle_Bold (not(fontSpec.GetStyle_Bold_Valid () and fontSpec.GetStyle_Bold ()));
3887 InteractiveSetFont (applyFontSpec);
3890void WordProcessor::OnUpdateFontStyleItalicCommand (CommandUpdater* enabler)
3893 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3894 enabler->SetChecked (fontSpec.GetStyle_Italic_Valid () and fontSpec.GetStyle_Italic ());
3895 enabler->SetEnabled (
true);
3898void WordProcessor::OnFontStyleItalicCommand ()
3900 IncrementalFontSpecification applyFontSpec;
3901 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3902 applyFontSpec.SetStyle_Italic (not(fontSpec.GetStyle_Italic_Valid () and fontSpec.GetStyle_Italic ()));
3903 InteractiveSetFont (applyFontSpec);
3906void WordProcessor::OnUpdateFontStyleUnderlineCommand (CommandUpdater* enabler)
3909 AssureCurSelFontCacheValid ();
3910 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_Underline_Valid () and fCachedCurSelFontSpec.GetStyle_Underline ());
3911 enabler->SetEnabled (
true);
3914void WordProcessor::OnFontStyleUnderlineCommand ()
3916 AssureCurSelFontCacheValid ();
3917 IncrementalFontSpecification applyFontSpec;
3918 applyFontSpec.SetStyle_Underline (not(fCachedCurSelFontSpec.GetStyle_Underline_Valid () and fCachedCurSelFontSpec.GetStyle_Underline ()));
3919 InteractiveSetFont (applyFontSpec);
3922#if qStroika_Foundation_Common_Platform_MacOS
3923void WordProcessor::OnUpdateFontStyleOutlineCommand (CommandUpdater* enabler)
3926 AssureCurSelFontCacheValid ();
3927 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_Outline_Valid () and fCachedCurSelFontSpec.GetStyle_Outline ());
3928 enabler->SetEnabled (
true);
3931void WordProcessor::OnFontStyleOutlineCommand ()
3933 AssureCurSelFontCacheValid ();
3934 IncrementalFontSpecification applyFontSpec;
3935 applyFontSpec.SetStyle_Outline (not(fCachedCurSelFontSpec.GetStyle_Outline_Valid () and fCachedCurSelFontSpec.GetStyle_Outline ()));
3936 InteractiveSetFont (applyFontSpec);
3939void WordProcessor::OnUpdateFontStyleShadowCommand (CommandUpdater* enabler)
3942 AssureCurSelFontCacheValid ();
3943 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_Shadow_Valid () and fCachedCurSelFontSpec.GetStyle_Shadow ());
3944 enabler->SetEnabled (
true);
3947void WordProcessor::OnFontStyleShadowCommand ()
3949 AssureCurSelFontCacheValid ();
3950 IncrementalFontSpecification applyFontSpec;
3951 applyFontSpec.SetStyle_Shadow (not(fCachedCurSelFontSpec.GetStyle_Shadow_Valid () and fCachedCurSelFontSpec.GetStyle_Shadow ()));
3952 InteractiveSetFont (applyFontSpec);
3955void WordProcessor::OnUpdateFontStyleCondensedCommand (CommandUpdater* enabler)
3958 AssureCurSelFontCacheValid ();
3959 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_Condensed_Valid () and fCachedCurSelFontSpec.GetStyle_Condensed ());
3960 enabler->SetEnabled (
true);
3963void WordProcessor::OnFontStyleCondensedCommand ()
3965 AssureCurSelFontCacheValid ();
3966 IncrementalFontSpecification applyFontSpec;
3967 applyFontSpec.SetStyle_Condensed (not(fCachedCurSelFontSpec.GetStyle_Condensed_Valid () and fCachedCurSelFontSpec.GetStyle_Condensed ()));
3968 InteractiveSetFont (applyFontSpec);
3971void WordProcessor::OnUpdateFontStyleExtendedCommand (CommandUpdater* enabler)
3974 AssureCurSelFontCacheValid ();
3975 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_Extended_Valid () and fCachedCurSelFontSpec.GetStyle_Extended ());
3976 enabler->SetEnabled (
true);
3979void WordProcessor::OnFontStyleExtendedCommand ()
3981 AssureCurSelFontCacheValid ();
3982 IncrementalFontSpecification applyFontSpec;
3983 applyFontSpec.SetStyle_Extended (not(fCachedCurSelFontSpec.GetStyle_Extended_Valid () and fCachedCurSelFontSpec.GetStyle_Extended ()));
3984 InteractiveSetFont (applyFontSpec);
3987#elif qStroika_Foundation_Common_Platform_Windows
3989void WordProcessor::OnUpdateFontStyleStrikeoutCommand (CommandUpdater* enabler)
3992 AssureCurSelFontCacheValid ();
3993 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_Strikeout_Valid () and fCachedCurSelFontSpec.GetStyle_Strikeout ());
3994 enabler->SetEnabled (
true);
3997void WordProcessor::OnFontStyleStrikeoutCommand ()
3999 AssureCurSelFontCacheValid ();
4000 IncrementalFontSpecification applyFontSpec;
4001 applyFontSpec.SetStyle_Strikeout (not(fCachedCurSelFontSpec.GetStyle_Strikeout_Valid () and fCachedCurSelFontSpec.GetStyle_Strikeout ()));
4002 InteractiveSetFont (applyFontSpec);
4007void WordProcessor::OnUpdateFontStyleSubscriptCommand (CommandUpdater* enabler)
4010 AssureCurSelFontCacheValid ();
4011 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_SubOrSuperScript_Valid () and
4012 fCachedCurSelFontSpec.GetStyle_SubOrSuperScript () == FontSpecification::eSubscript);
4013 enabler->SetEnabled (
true);
4016void WordProcessor::OnFontStyleSubscriptCommand ()
4018 AssureCurSelFontCacheValid ();
4019 IncrementalFontSpecification applyFontSpec;
4020 applyFontSpec.SetStyle_SubOrSuperScript ((fCachedCurSelFontSpec.GetStyle_SubOrSuperScript_Valid () and
4021 fCachedCurSelFontSpec.GetStyle_SubOrSuperScript () == FontSpecification::eSubscript)
4022 ? FontSpecification::eNoSubOrSuperscript
4024 InteractiveSetFont (applyFontSpec);
4027void WordProcessor::OnUpdateFontStyleSuperscriptCommand (CommandUpdater* enabler)
4030 AssureCurSelFontCacheValid ();
4031 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_SubOrSuperScript_Valid () and
4032 fCachedCurSelFontSpec.GetStyle_SubOrSuperScript () == FontSpecification::eSuperscript);
4033 enabler->SetEnabled (
true);
4036void WordProcessor::OnFontStyleSuperscriptCommand ()
4038 AssureCurSelFontCacheValid ();
4039 IncrementalFontSpecification applyFontSpec;
4040 applyFontSpec.SetStyle_SubOrSuperScript ((fCachedCurSelFontSpec.GetStyle_SubOrSuperScript_Valid () and
4041 fCachedCurSelFontSpec.GetStyle_SubOrSuperScript () == FontSpecification::eSuperscript)
4042 ? FontSpecification::eNoSubOrSuperscript
4044 InteractiveSetFont (applyFontSpec);
4047void WordProcessor::OnUpdateChooseFontCommand (CommandUpdater* enabler)
4050 enabler->SetEnabled (
true);
4053void WordProcessor::OnChooseFontCommand ()
4055 IncrementalFontSpecification curSelFontSpec = GetCurSelFontSpec ();
4056 if (GetDialogSupport ().ChooseFont (&curSelFontSpec)) {
4057 InteractiveSetFont (curSelFontSpec);
4061void WordProcessor::OnUpdateFontSizeChangeCommand (CommandUpdater* enabler)
4064 DistanceType chosenFontSize = GetDialogSupport ().FontCmdToSize (enabler->GetCmdID ());
4066 AssureCurSelFontCacheValid ();
4067 if (chosenFontSize == 0) {
4068 switch (enabler->GetCmdID ()) {
4069 case kFontSizeSmaller_CmdID:
4070 case kFontSizeLarger_CmdID: {
4071 enabler->SetEnabled (
true);
4074 case kFontSizeOther_CmdID: {
4075 enabler->SetEnabled (
true);
4076 if (fCachedCurSelFontSpec.GetPointSize_Valid ()) {
4077 int pointSize = fCachedCurSelFontSpec.GetPointSize ();
4078 if (not GetDialogSupport ().IsPredefinedFontSize (pointSize)) {
4079 enabler->SetChecked (
true);
4080 enabler->SetText (Characters::CString::Format (GetCommandNames ().fFontSizeChange_Other_OneArg.c_str (), pointSize).c_str ());
4084 enabler->SetChecked (
false);
4085 enabler->SetText (GetCommandNames ().fFontSizeChange_Other_NoArg.c_str ());
4090 enabler->SetChecked (fCachedCurSelFontSpec.GetPointSize_Valid () and fCachedCurSelFontSpec.GetPointSize () == chosenFontSize);
4091 enabler->SetEnabled (
true);
4095void WordProcessor::OnFontSizeChangeCommand (CommandNumber cmdNum)
4097 DistanceType chosenFontSize = GetDialogSupport ().FontCmdToSize (cmdNum);
4098 if (chosenFontSize == 0) {
4100 case kFontSizeSmaller_CmdID: {
4101 IncrementalFontSpecification applyFontSpec;
4102 applyFontSpec.SetPointSizeIncrement (-1);
4103 InteractiveSetFont (applyFontSpec);
4106 case kFontSizeLarger_CmdID: {
4107 IncrementalFontSpecification applyFontSpec;
4108 applyFontSpec.SetPointSizeIncrement (1);
4109 InteractiveSetFont (applyFontSpec);
4112 case kFontSizeOther_CmdID: {
4113 DistanceType oldSize = fCachedCurSelFontSpec.GetPointSize_Valid () ? fCachedCurSelFontSpec.GetPointSize () : 0;
4114 chosenFontSize = GetDialogSupport ().PickOtherFontHeight (oldSize);
4118 if (chosenFontSize != 0) {
4119 IncrementalFontSpecification applyFontSpec;
4120 applyFontSpec.SetPointSize (
static_cast<unsigned short> (chosenFontSize));
4121 InteractiveSetFont (applyFontSpec);
4125void WordProcessor::OnUpdateFontColorChangeCommand (CommandUpdater* enabler)
4128 Require (enabler->GetCmdID () >= kBaseFontColor_CmdID and enabler->GetCmdID () <= kLastFontColor_CmdID);
4129 AssureCurSelFontCacheValid ();
4130 if (fCachedCurSelFontSpec.GetTextColor_Valid ()) {
4131 if (enabler->GetCmdID () == kFontColorOther_CmdID) {
4133 enabler->SetChecked (GetDialogSupport ().FontColorToCmd (fCachedCurSelFontSpec.GetTextColor ()) == kFontColorOther_CmdID);
4136 enabler->SetChecked (fCachedCurSelFontSpec.GetTextColor () == GetDialogSupport ().FontCmdToColor (enabler->GetCmdID ()));
4140 enabler->SetChecked (
false);
4142 enabler->SetEnabled (
true);
4145void WordProcessor::OnFontColorChangeCommand (CommandNumber cmdNum)
4147 Require (cmdNum >= kBaseFontColor_CmdID and cmdNum <= kLastFontColor_CmdID);
4149 AssureCurSelFontCacheValid ();
4150 IncrementalFontSpecification applyFontSpec;
4151 if (cmdNum == kFontColorOther_CmdID) {
4152 Color originalColor = GetDefaultFont ().GetTextColor ();
4153 if (fCachedCurSelFontSpec.GetTextColor_Valid ()) {
4154 originalColor = fCachedCurSelFontSpec.GetTextColor ();
4156 Color chosenColor = originalColor;
4157 if (GetDialogSupport ().PickOtherFontColor (&chosenColor)) {
4158 applyFontSpec.SetTextColor (chosenColor);
4165 Color chosenColor = GetDialogSupport ().FontCmdToColor (cmdNum);
4166 if (fCachedCurSelFontSpec.GetTextColor_Valid () and fCachedCurSelFontSpec.GetTextColor () == chosenColor) {
4167 applyFontSpec.SetTextColor (Color::kBlack);
4170 applyFontSpec.SetTextColor (chosenColor);
4173 InteractiveSetFont (applyFontSpec);
4176void WordProcessor::OnUpdateInsertTableCommand (CommandUpdater* enabler)
4181 enabler->SetEnabled (GetSelectionStart () == GetSelectionEnd ());
4184void WordProcessor::OnInsertTableCommand ()
4188 if (GetDialogSupport ().AddNewTableDialog (&rows, &cols)) {
4191 Assert (rows < 1000);
4192 Assert (cols < 100);
4194 InteractiveModeUpdater iuMode (*
this);
4197 TextStore::SimpleUpdater updater1 (GetTextStore (), GetSelectionStart (), GetSelectionEnd ());
4199 BreakInGroupedCommands ();
4200 UndoableContextHelper context (*
this, GetCommandNames ().fInsertTableCommandName,
false);
4203 WordProcessorTable* t = InsertTable (GetSelectionStart ());
4205 t->SetDimensions (rows, cols);
4207 for (
size_t r = 0; r < rows; ++r) {
4208 for (
size_t c = 0; c < cols; ++c) {
4209 TWIPS targetWidth = TWIPS{0};
4211 CoordinateType lhs = 0;
4212 CoordinateType rhs = 0;
4213 GetLayoutMargins (GetRowReferenceContainingPosition (t->GetStart ()), &lhs, &rhs);
4215 targetWidth = Led_CvtScreenPixelsToTWIPSH (rhs - lhs);
4216 targetWidth = TWIPS ((targetWidth / 5) * 4);
4218 t->SetColumnWidth (r, c, TWIPS (
static_cast<long> (targetWidth / cols)));
4220 TextStore* ts =
nullptr;
4221 t->GetCellWordProcessorDatabases (r, c, &ts);
4225 TextStore::SimpleUpdater updater (GetTextStore (), t->GetStart (), t->GetEnd ());
4226 SetSelection (t->GetEnd (), t->GetEnd ());
4228 context.CommandComplete ();
4229 BreakInGroupedCommands ();
4233void WordProcessor::OnUpdateInsertURLCommand (CommandUpdater* enabler)
4236 enabler->SetEnabled (GetSelectionStart () == GetSelectionEnd ());
4241void WordProcessor::OnInsertURLCommand ()
4243 InteractiveModeUpdater iuMode (*
this);
4244 BreakInGroupedCommands ();
4247 if (GetDialogSupport ().ShowAddURLEmbeddingInfoDialog (&title, &url)) {
4248 UndoableContextHelper context{*
this, GetCommandNames ().fInsertURLCommandName,
false};
4250 SimpleEmbeddedObjectStyleMarker* e =
new StandardURLStyleMarker{
4251 Led_URLD{String::FromSDKString (url).AsNarrowSDKString ().c_str (), String::FromSDKString (title).AsNarrowSDKString ().c_str ()}};
4252 AddEmbedding (e, GetTextStore (), GetSelectionStart (), GetStyleDatabase ().get ());
4253 SetSelection (e->GetEnd (), e->GetEnd ());
4255 context.CommandComplete ();
4257 BreakInGroupedCommands ();
4260void WordProcessor::OnUpdateInsertSymbolCommand ([[maybe_unused]] CommandUpdater* enabler)
4263#if qStroika_Foundation_Common_Platform_Windows
4264 enabler->SetEnabled (
true);
4270void WordProcessor::OnInsertSymbolCommand ()
4272#if qStroika_Foundation_Common_Platform_Windows
4273 (void)::ShellExecute (
nullptr, Led_SDK_TCHAROF (
"open"), Led_SDK_TCHAROF (
"CHARMAP.EXE"),
nullptr, Led_SDK_TCHAROF (
""), SW_SHOWNORMAL);
4279void WordProcessor::OnUpdateSelectedEmbeddingExtendedCommand (CommandUpdater* enabler)
4282 SimpleEmbeddedObjectStyleMarker* embedding = GetSoleSelectedEmbedding ();
4283 if (enabler->GetCmdID () == kSelectedEmbeddingProperties_CmdID) {
4284 enabler->SetEnabled (embedding !=
nullptr);
4285 WordProcessorTable* t = GetActiveTable ();
4286 enabler->SetText (t ==
nullptr ? GetCommandNames ().fGenericEmbeddingPropertiesCommandName.c_str ()
4287 : GetCommandNames ().fTablePropertiesCommandName.c_str ());
4290 using PrivateCmdNumber = SimpleEmbeddedObjectStyleMarker::PrivateCmdNumber;
4291 PrivateCmdNumber cmdNum =
4292 static_cast<PrivateCmdNumber
> (enabler->GetCmdID () - kFirstPrivateEmbedding_CmdID + SimpleEmbeddedObjectStyleMarker::eMinPrivateCmdNum);
4293 enabler->SetEnabled (embedding !=
nullptr and embedding->IsCmdEnabled (cmdNum));
4294 if (embedding !=
nullptr) {
4295 enabler->SetText (embedding->GetCmdText (cmdNum).c_str ());
4300bool WordProcessor::OnSelectedEmbeddingExtendedCommand (CommandNumber cmdNum)
4302 Require (cmdNum >= kFirstSelectedEmbedding_CmdID and cmdNum <= kLastSelectedEmbedding_CmdID);
4303 SimpleEmbeddedObjectStyleMarker* embedding = GetSoleSelectedEmbedding ();
4304 if (embedding ==
nullptr) {
4307 if (cmdNum == kSelectedEmbeddingProperties_CmdID) {
4308 if (
dynamic_cast<StandardURLStyleMarker*
> (embedding) !=
nullptr) {
4309 StandardURLStyleMarker* e =
dynamic_cast<StandardURLStyleMarker*
> (embedding);
4310 SDKString title = String::FromNarrowSDKString (e->GetURLData ().GetTitle ()).AsSDKString ();
4311 SDKString url = String::FromNarrowSDKString (e->GetURLData ().GetURL ()).AsSDKString ();
4312 if (GetDialogSupport ().ShowURLEmbeddingInfoDialog (GetPrettyTypeName (embedding), &title, &url)) {
4315 TextStore::SimpleUpdater updater (GetTextStore (), e->GetStart (), e->GetEnd ());
4316 e->SetURLData (Led_URLD{String::FromSDKString (url).AsNarrowSDKString ().c_str (),
4317 String::FromSDKString (title).AsNarrowSDKString ().c_str ()});
4321 else if (
dynamic_cast<WordProcessorTable*
> (embedding) !=
nullptr) {
4322 OnEditTablePropertiesDialog ();
4326 GetDialogSupport ().ShowSimpleEmbeddingInfoDialog (GetPrettyTypeName (embedding));
4330 using PrivateCmdNumber = SimpleEmbeddedObjectStyleMarker::PrivateCmdNumber;
4331 PrivateCmdNumber pCmdNum =
4332 static_cast<PrivateCmdNumber
> (cmdNum - kFirstPrivateEmbedding_CmdID + SimpleEmbeddedObjectStyleMarker::eMinPrivateCmdNum);
4333 embedding->DoCommand (pCmdNum);
4338void WordProcessor::OnEditTablePropertiesDialog ()
4340 WordProcessorTable* t = GetActiveTable ();
4347 DialogSupport::TableSelectionPropertiesInfo info;
4348 info.fTableBorderWidth = t->GetTableBorderWidth ();
4349 info.fTableBorderColor = t->GetTableBorderColor ();
4350 t->GetDefaultCellMargins (&info.fDefaultCellMargins.top, &info.fDefaultCellMargins.left, &info.fDefaultCellMargins.bottom,
4351 &info.fDefaultCellMargins.right);
4352 info.fCellSpacing = t->GetCellSpacing ();
4354 size_t rowSelStart = 0;
4355 size_t rowSelEnd = 0;
4356 size_t colSelStart = 0;
4357 size_t colSelEnd = 0;
4358 t->GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
4359 info.fCellWidth_Common =
false;
4360 info.fCellBackgroundColor_Common =
false;
4361 for (
size_t r = rowSelStart; r < rowSelEnd; ++r) {
4362 for (
size_t c = colSelStart; c < colSelEnd; ++c) {
4363 if (c < t->GetColumnCount (r)) {
4364 TWIPS cellWidth = t->GetColumnWidth (r, c);
4365 Color cellBkgrnd = t->GetCellColor (r, c);
4366 if (r == rowSelStart and c == colSelStart) {
4367 info.fCellWidth_Common =
true;
4368 info.fCellWidth = cellWidth;
4369 info.fCellBackgroundColor_Common =
true;
4370 info.fCellBackgroundColor = cellBkgrnd;
4373 if (info.fCellWidth_Common) {
4374 if (info.fCellWidth != cellWidth) {
4375 info.fCellWidth_Common =
false;
4378 if (info.fCellBackgroundColor_Common) {
4379 if (info.fCellBackgroundColor != cellBkgrnd) {
4380 info.fCellBackgroundColor_Common =
false;
4388 if (GetDialogSupport ().EditTablePropertiesDialog (&info)) {
4389 UndoableContextHelper context (*
this, GetCommandNames ().fChangeTablePropertiesCommandName,
false);
4391 t->SetTableBorderWidth (info.fTableBorderWidth);
4392 t->SetTableBorderColor (info.fTableBorderColor);
4393 t->SetDefaultCellMargins (info.fDefaultCellMargins.top, info.fDefaultCellMargins.left, info.fDefaultCellMargins.bottom,
4394 info.fDefaultCellMargins.right);
4395 t->SetCellSpacing (info.fCellSpacing);
4397 size_t rowSelStart = 0;
4398 size_t rowSelEnd = 0;
4399 size_t colSelStart = 0;
4400 size_t colSelEnd = 0;
4401 t->GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
4402 for (
size_t r = rowSelStart; r < rowSelEnd; ++r) {
4403 for (
size_t c = colSelStart; c < colSelEnd; ++c) {
4404 if (c < t->GetColumnCount (r)) {
4405 if (info.fCellWidth_Common) {
4406 t->SetColumnWidth (r, c, info.fCellWidth);
4408 if (info.fCellBackgroundColor_Common) {
4409 t->SetCellColor (r, c, info.fCellBackgroundColor);
4416 context.CommandComplete ();
4420void WordProcessor::OnUpdateHideSelectionCommands (CommandUpdater* enabler)
4423 bool enabled = GetSelectionStart () != GetSelectionEnd ();
4426 if (enabler->GetCmdID () == kHideSelection_CmdID) {
4427 enabled = not GetHidableTextDatabase ()->GetHidableRegionsContiguous (GetSelectionStart (), GetSelectionEnd (),
true);
4429 else if (enabler->GetCmdID () == kUnHideSelection_CmdID) {
4430 enabled = not GetHidableTextDatabase ()->GetHidableRegionsContiguous (GetSelectionStart (), GetSelectionEnd (),
false);
4433 enabler->SetEnabled (enabled);
4436void WordProcessor::OnHideSelection ()
4438 InterectiveSetRegionHidable (
true);
4441void WordProcessor::OnUnHideSelection ()
4443 InterectiveSetRegionHidable (
false);
4446void WordProcessor::OnUpdateParagraphJustificationCommand (CommandUpdater* enabler)
4450 AssureCurSelFontCacheValid ();
4452 switch (enabler->GetCmdID ()) {
4453 case kJustifyLeft_CmdID: {
4454 enabler->SetChecked (fCachedCurSelJustificationUnique and (fCachedCurSelJustification == eLeftJustify));
4456 case kJustifyCenter_CmdID: {
4457 enabler->SetChecked (fCachedCurSelJustificationUnique and (fCachedCurSelJustification == eCenterJustify));
4459 case kJustifyRight_CmdID: {
4460 enabler->SetChecked (fCachedCurSelJustificationUnique and (fCachedCurSelJustification == eRightJustify));
4462 case kJustifyFull_CmdID: {
4463 enabler->SetChecked (fCachedCurSelJustificationUnique and (fCachedCurSelJustification == eFullyJustify));
4466 enabler->SetEnabled (
true);
4469void WordProcessor::OnParagraphJustificationCommand (CommandNumber cmdNum)
4472 case kJustifyLeft_CmdID: {
4473 InteractiveSetJustification (eLeftJustify);
4475 case kJustifyCenter_CmdID: {
4476 InteractiveSetJustification (eCenterJustify);
4478 case kJustifyRight_CmdID: {
4479 InteractiveSetJustification (eRightJustify);
4481 case kJustifyFull_CmdID: {
4482 InteractiveSetJustification (eFullyJustify);
4490void WordProcessor::OnUpdateParagraphSpacingChangeCommand (CommandUpdater* enabler)
4493 enabler->SetEnabled (
true);
4496void WordProcessor::OnParagraphSpacingChangeCommand ()
4498 TWIPS spaceBefore = TWIPS{0};
4499 TWIPS spaceAfter = TWIPS{0};
4500 LineSpacing lineSpacing;
4502 bool spaceBeforeValid = GetSpaceBefore (GetSelectionStart (), GetSelectionEnd (), &spaceBefore);
4503 bool spaceAfterValid = GetSpaceAfter (GetSelectionStart (), GetSelectionEnd (), &spaceAfter);
4504 bool lineSpacingValid = GetLineSpacing (GetSelectionStart (), GetSelectionEnd (), &lineSpacing);
4506 if (GetDialogSupport ().PickNewParagraphLineSpacing (&spaceBefore, &spaceBeforeValid, &spaceAfter, &spaceAfterValid, &lineSpacing, &lineSpacingValid)) {
4507 if (spaceBeforeValid) {
4509 InteractiveSetParagraphSpacing (spaceBefore, spaceBeforeValid, spaceAfter, spaceAfterValid, lineSpacing, lineSpacingValid);
4513void WordProcessor::OnUpdateParagraphIndentsChangeCommand (CommandUpdater* enabler)
4516 enabler->SetEnabled (
true);
4519void WordProcessor::OnParagraphIndentsChangeCommand ()
4521 TWIPS leftMargin = TWIPS{0};
4522 TWIPS rightMargin = TWIPS{0};
4523 TWIPS firstIndent = TWIPS{0};
4526 bool leftMarginValid = GetMargins (GetSelectionStart (), GetSelectionEnd (), &leftMargin, &rightMargin);
4527 bool rightMarginValid = leftMarginValid;
4528 bool firstIndentValid = GetFirstIndent (GetSelectionStart (), GetSelectionEnd (), &firstIndent);
4530 if (GetDialogSupport ().PickNewParagraphMarginsAndFirstIndent (&leftMargin, &leftMarginValid, &rightMargin, &rightMarginValid,
4531 &firstIndent, &firstIndentValid)) {
4535 InteractiveSetMarginsAndFirstIndent (leftMargin, rightMargin, firstIndent);
4539void WordProcessor::OnUpdateListStyleChangeCommand (CommandUpdater* enabler)
4542 ListStyle listStyle = eListStyle_None;
4543 bool listStyleValid = GetListStyle (GetSelectionStart (), GetSelectionEnd (), &listStyle);
4544 if (enabler->GetCmdID () == kListStyle_None_CmdID) {
4545 enabler->SetChecked (listStyleValid and listStyle == eListStyle_None);
4547 else if (enabler->GetCmdID () == kListStyle_Bullet_CmdID) {
4548 enabler->SetChecked (listStyleValid and listStyle == eListStyle_Bullet);
4553 enabler->SetEnabled (
true);
4556void WordProcessor::OnListStyleChangeCommand (CommandNumber cmdNum)
4558 if (cmdNum == kListStyle_None_CmdID) {
4559 InteractiveSetListStyle (eListStyle_None);
4561 else if (cmdNum == kListStyle_Bullet_CmdID) {
4562 InteractiveSetListStyle (eListStyle_Bullet);
4569void WordProcessor::OnUpdateIndentCommand (CommandUpdater* enabler)
4572 ListStyle listStyle = eListStyle_None;
4573 bool listStyleValid = GetListStyle (GetSelectionStart (), GetSelectionEnd (), &listStyle);
4574 if (enabler->GetCmdID () == kIncreaseIndent_CmdID) {
4575 enabler->SetEnabled (listStyleValid and listStyle != eListStyle_None);
4577 else if (enabler->GetCmdID () == kDecreaseIndent_CmdID) {
4578 enabler->SetEnabled (listStyleValid and listStyle != eListStyle_None);
4585void WordProcessor::OnIndentCommand (CommandNumber cmdNum)
4587 if (cmdNum == kIncreaseIndent_CmdID) {
4588 InteractiveDoIndentChange (
true);
4590 else if (cmdNum == kDecreaseIndent_CmdID) {
4591 InteractiveDoIndentChange (
false);
4598void WordProcessor::OnUpdateShowHideGlyphCommand (CommandUpdater* enabler)
4601 Require (enabler->GetCmdID () >= kFirstShowHideGlyph_CmdID);
4602 Require (enabler->GetCmdID () <= kLastShowHideGlyph_CmdID);
4605 if (enabler->GetCmdID () == kShowHideParagraphGlyphs_CmdID) {
4606 enabler->SetChecked (GetShowParagraphGlyphs ());
4608 else if (enabler->GetCmdID () == kShowHideTabGlyphs_CmdID) {
4609 enabler->SetChecked (GetShowTabGlyphs ());
4611 else if (enabler->GetCmdID () == kShowHideSpaceGlyphs_CmdID) {
4612 enabler->SetChecked (GetShowSpaceGlyphs ());
4617 enabler->SetEnabled (
true);
4620void WordProcessor::OnShowHideGlyphCommand (CommandNumber cmdNum)
4622 Require (cmdNum >= kFirstShowHideGlyph_CmdID);
4623 Require (cmdNum <= kLastShowHideGlyph_CmdID);
4626 if (cmdNum == kShowHideParagraphGlyphs_CmdID) {
4627 SetShowParagraphGlyphs (not GetShowParagraphGlyphs ());
4629 else if (cmdNum == kShowHideTabGlyphs_CmdID) {
4630 SetShowTabGlyphs (not GetShowTabGlyphs ());
4632 else if (cmdNum == kShowHideSpaceGlyphs_CmdID) {
4633 SetShowSpaceGlyphs (not GetShowSpaceGlyphs ());
4640SDKString WordProcessor::GetPrettyTypeName (SimpleEmbeddedObjectStyleMarker* m)
4642 if (
dynamic_cast<StandardDIBStyleMarker*
> (m) !=
nullptr) {
4643 return GetCommandNames ().fEmbeddingTypeName_ImageDIB;
4645 else if (
dynamic_cast<StandardURLStyleMarker*
> (m) !=
nullptr) {
4646 return GetCommandNames ().fEmbeddingTypeName_URL;
4648#if qStroika_Foundation_Common_Platform_MacOS || qStroika_Foundation_Common_Platform_Windows
4649 else if (
dynamic_cast<StandardMacPictureStyleMarker*
> (m) !=
nullptr) {
4650 return GetCommandNames ().fEmbeddingTypeName_ImageMacPict;
4653 else if (
dynamic_cast<WordProcessorTable*
> (m) !=
nullptr) {
4654 return GetCommandNames ().fEmbeddingTypeName_Table;
4657 return GetCommandNames ().fEmbeddingTypeName_Unknown;
4661SimpleEmbeddedObjectStyleMarker* WordProcessor::GetSoleSelectedEmbedding ()
const
4663 size_t selStart = GetSelectionStart ();
4664 size_t selEnd = GetSelectionEnd ();
4665 Require (selStart <= selEnd);
4666 if (selEnd - selStart == 1) {
4667 vector<SimpleEmbeddedObjectStyleMarker*> embeddings = CollectAllEmbeddingMarkersInRange (selStart, selEnd);
4668 if (embeddings.size () == 1) {
4669 return (
dynamic_cast<SimpleEmbeddedObjectStyleMarker*
> (embeddings[0]));
4686Led_tString WordProcessor::GetListLeader (
size_t paragraphMarkerPos)
const
4688 if (fParagraphDatabase.get () ==
nullptr) {
4689 throw NoParagraphDatabaseAvailable ();
4691 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (paragraphMarkerPos);
4692 if (pi.GetListStyle () == eListStyle_None) {
4693 return Led_tString{};
4696 const Led_tChar kBulletChar = 0x2022;
4699 return Led_tString{&kBulletChar, 1} + LED_TCHAR_OF (
"\t");
4708DistanceType WordProcessor::GetListLeaderLength (
size_t paragraphMarkerPos)
const
4710 if (fParagraphDatabase.get () ==
nullptr) {
4711 throw NoParagraphDatabaseAvailable ();
4714 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (paragraphMarkerPos);
4715 TWIPS lhsTWIPS = pi.GetLeftMargin ();
4716 lhsTWIPS += pi.GetFirstIndent ();
4718 Tablet_Acquirer tablet_ (
this);
4719 Tablet* tablet = tablet_;
4720 CoordinateType lhs = tablet->CvtFromTWIPSH (lhsTWIPS);
4721 Led_tString leader = GetListLeader (paragraphMarkerPos);
4723 size_t len = leader.length ();
4731 useBulletFont.SetPointSize (max (
static_cast<unsigned short> (14), nextCharsFontStyle.GetPointSize ()));
4732 MeasureSegmentWidth_ (useBulletFont, paragraphMarkerPos, paragraphMarkerPos + len, leader.c_str (), distanceResults.data ());
4733 (void)ResetTabStopsWithMargin (lhs, paragraphMarkerPos, leader.c_str (), len, distanceResults.data (), 0);
4734 DistanceType result = distanceResults[len - 1];
4739InteractiveReplaceCommand::SavedTextRep* WordProcessor::InteractiveUndoHelperMakeTextRep (
size_t regionStart,
size_t regionEnd,
size_t selStart,
size_t selEnd)
4741 using SavedTextRep = InteractiveReplaceCommand::SavedTextRep;
4742 if (regionStart == regionEnd) {
4743 return new EmptySelectionParagraphSavedTextRep (
this, selStart, selEnd, regionStart);
4746 SavedTextRep* basicRep = inherited::InteractiveUndoHelperMakeTextRep (regionStart, regionEnd, selStart, selEnd);
4747 WordProcessorTable* aT = GetActiveTable ();
4748 if (aT !=
nullptr) {
4749 return new WordProcessorTable::SavedTextRepWSel (basicRep, *aT, WordProcessorTable::SavedTextRepWSel::eWPAbove);
4759void WordProcessor::InteractiveSetFont (
const IncrementalFontSpecification& defaultFont)
4761 WordProcessorTable* aT = GetActiveTable ();
4762 if (aT !=
nullptr) {
4763 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, *
this);
4764 aT->InteractiveSetFont (defaultFont);
4767 inherited::InteractiveSetFont (defaultFont);
4774void WordProcessor::InteractiveSetJustification (Justification justification)
4776 Justification oldJustification;
4777 if (not GetJustification (GetSelectionStart (), GetSelectionEnd (), &oldJustification) or (oldJustification != justification)) {
4778 InteractiveWPHelper1<DoIt_SetJustification> (
this, justification);
4786void WordProcessor::InteractiveSetStandardTabStopList (StandardTabStopList tabStops)
4788 StandardTabStopList oldTabs;
4789 if (not GetStandardTabStopList (GetSelectionStart (), GetSelectionEnd (), &oldTabs) or (oldTabs != tabStops)) {
4790 InteractiveWPHelper1<DoIt_SetStandardTabStopList> (
this, tabStops);
4798void WordProcessor::InteractiveSetMargins (TWIPS leftMargin, TWIPS rightMargin)
4800 TWIPS oldLeftMargin = TWIPS{0};
4801 TWIPS oldRightMargin = TWIPS{0};
4802 if (not GetMargins (GetSelectionStart (), GetSelectionEnd (), &oldLeftMargin, &oldRightMargin) or
4803 ((oldLeftMargin != leftMargin) or (oldRightMargin != rightMargin))) {
4804 InteractiveWPHelper1<DoIt_SetMargins> (
this, DoIt_SetMargins::Margins (leftMargin, rightMargin));
4812void WordProcessor::InteractiveSetFirstIndent (TWIPS firstIndent)
4814 TWIPS oldFirstIndent = TWIPS{0};
4815 if (not GetFirstIndent (GetSelectionStart (), GetSelectionEnd (), &oldFirstIndent) or (oldFirstIndent != firstIndent)) {
4816 InteractiveWPHelper1<DoIt_SetFirstIndent> (
this, firstIndent);
4825void WordProcessor::InteractiveSetMarginsAndFirstIndent (TWIPS leftMargin, TWIPS rightMargin, TWIPS firstIndent)
4827 TWIPS oldLeftMargin = TWIPS{0};
4828 TWIPS oldRightMargin = TWIPS{0};
4829 TWIPS oldFirstIndent = TWIPS{0};
4830 if (not GetMargins (GetSelectionStart (), GetSelectionEnd (), &oldLeftMargin, &oldRightMargin) or
4831 ((oldLeftMargin != leftMargin) or (oldRightMargin != rightMargin)) or
4832 not GetFirstIndent (GetSelectionStart (), GetSelectionEnd (), &oldFirstIndent) or (oldFirstIndent != firstIndent)) {
4833 InteractiveWPHelper1<DoIt_SetMarginsAndFirstIndent> (
4834 this, DoIt_SetMarginsAndFirstIndent::MarginsAndFirstIndent (leftMargin, rightMargin, firstIndent));
4842void WordProcessor::InteractiveSetParagraphSpacing (TWIPS spaceBefore,
bool spaceBeforeValid, TWIPS spaceAfter,
bool spaceAfterValid,
4843 LineSpacing lineSpacing,
bool lineSpacingValid)
4848 TWIPS oldSpaceBefore = TWIPS{0};
4849 TWIPS oldSpaceAfter = TWIPS{0};
4850 LineSpacing oldLineSpacing;
4851 if (not GetSpaceBefore (GetSelectionStart (), GetSelectionEnd (), &oldSpaceBefore) or (oldSpaceBefore != spaceBefore) or
4852 not GetSpaceAfter (GetSelectionStart (), GetSelectionEnd (), &oldSpaceAfter) or (oldSpaceAfter != spaceAfter) or
4853 not GetLineSpacing (GetSelectionStart (), GetSelectionEnd (), &oldLineSpacing) or (oldLineSpacing != lineSpacing)) {
4854 InteractiveWPHelper1<DoIt_SetParagraphSpacing> (
4855 this, DoIt_SetParagraphSpacing::AllSpacingArgs (spaceBefore, spaceBeforeValid, spaceAfter, spaceAfterValid, lineSpacing, lineSpacingValid));
4863void WordProcessor::InteractiveSetListStyle (ListStyle listStyle)
4868 ListStyle oldListStyle = eListStyle_None;
4869 if (not GetListStyle (GetSelectionStart (), GetSelectionEnd (), &oldListStyle) or oldListStyle != listStyle) {
4870 InteractiveWPHelper1<DoIt_SetListStyle> (
this, listStyle);
4878void WordProcessor::InteractiveDoIndentChange (
bool increase)
4880 InteractiveWPHelper1<DoIt_IndentUnIndentList> (
this, increase);
4887const TabStopList& WordProcessor::GetTabStopList (
size_t containingPos)
const
4889 return fParagraphDatabase->GetParagraphInfo (containingPos).GetTabStopList ();
4892void WordProcessor::DrawBefore (
const Led_Rect& subsetToDraw,
bool printing)
4894 size_t winStart = GetMarkerPositionOfStartOfWindow ();
4895 size_t winEnd = GetMarkerPositionOfEndOfWindow ();
4899 vector<WordProcessorTable*> tables = GetTablesInRange (winStart, winEnd);
4900 for (
auto i = tables.begin (); i != tables.end (); ++i) {
4901 WordProcessorTable* t = *i;
4902 if (t->fNeedLayout != WordProcessorTable::eDone) {
4903 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*t, *
this);
4904 t->PerformLayout ();
4907 inherited::DrawBefore (subsetToDraw, printing);
4914void WordProcessor::DrawRowSegments (Tablet* tablet,
const Led_Rect& currentRowRect,
const Led_Rect& invalidRowRect,
4915 const TextLayoutBlock& text,
size_t rowStart,
size_t rowEnd)
4917 if (fParagraphDatabase.get () ==
nullptr) {
4918 throw NoParagraphDatabaseAvailable ();
4920 RowReference row = GetRowReferenceContainingPosition (rowStart);
4921 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (rowStart);
4923 Led_Rect adjustedDrawInto = currentRowRect;
4925 CoordinateType lhsMargin = 0;
4926 GetLayoutMargins (row, &lhsMargin,
nullptr);
4927 adjustedDrawInto += Led_Point (0, lhsMargin);
4931 if (row.GetSubRow () == 0) {
4932 ListStyle ls = pi.GetListStyle ();
4933 if (ls != eListStyle_None) {
4937 bool allowLists =
true;
4938 if (rowEnd - rowStart == 1) {
4939 vector<WordProcessorTable*> tables = GetTablesInRange (rowStart, rowEnd);
4940 if (tables.size () == 1) {
4946 Led_Rect xxx = adjustedDrawInto;
4947 Led_tString listLeader = GetListLeader (rowStart);
4948 xxx.SetLeft (xxx.GetLeft () - GetListLeaderLength (rowStart));
4951 useBulletFont.SetPointSize (max (
static_cast<unsigned short> (14), nextCharsFontStyle.GetPointSize ()));
4952 CoordinateType baseLine = xxx.GetTop () + MeasureSegmentBaseLine (rowStart, rowStart);
4953 DrawSegment_ (tablet, useBulletFont, rowStart, rowStart + listLeader.length (),
4954 TextLayoutBlock_Basic (listLeader.c_str (), listLeader.c_str () + listLeader.length ()), xxx, baseLine,
nullptr);
4960 switch (pi.GetJustification ()) {
4961 case eCenterJustify: {
4962 adjustedDrawInto.SetLeft (adjustedDrawInto.GetLeft () + CalcSpaceToEat (rowStart) / 2);
4964 case eRightJustify: {
4965 adjustedDrawInto.SetLeft (adjustedDrawInto.GetLeft () + CalcSpaceToEat (rowStart));
4968 if (not adjustedDrawInto.IsEmpty ()) {
4969 inherited::DrawRowSegments (tablet, adjustedDrawInto, invalidRowRect, text, rowStart, rowEnd);
4970 if (GetShowParagraphGlyphs ()) {
4972 PartitionElementCacheInfo pmCacheInfo = GetPartitionElementCacheInfo (GetPartitionMarkerContainingPosition (rowStart));
4973 if (row.GetSubRow () + 1 == pmCacheInfo.GetRowCount () and rowEnd < GetEnd ()) {
4974 const Led_tChar newline =
'\n';
4977 useFont.SetPointSize (max (
static_cast<unsigned short> (14), nextCharsFontStyle.GetPointSize ()));
4978 useFont.SetTextColor (Color::kGray);
4979 Led_Rect yyy = adjustedDrawInto;
4980 DistanceType segmentWidth = CalcSegmentSize (rowStart, rowEnd);
4981 yyy.left += segmentWidth;
4982 CoordinateType baseLine = yyy.GetTop () + MeasureSegmentBaseLine (rowStart, rowStart);
4983 DrawSegment_ (tablet, useFont, rowEnd, rowEnd + 1, TextLayoutBlock_Basic (&newline, &newline + 1), yyy, baseLine,
nullptr);
4993vector<Led_Rect> WordProcessor::GetRowHilightRects (
const TextLayoutBlock& text,
size_t rowStart,
size_t rowEnd,
size_t hilightStart,
size_t hilightEnd)
const
4995 size_t len = rowEnd - rowStart;
4996 if (len == 1 and text.PeekAtRealText ()[0] == kEmbeddingSentinelChar) {
4997 vector<WordProcessorTable*> tables = GetTablesInRange (rowStart, rowEnd);
4998 Assert (tables.size () <= 1);
4999 if (not tables.empty ()) {
5000 WordProcessorTable* table = tables[0];
5001 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*table, *
const_cast<WordProcessor*
> (
this));
5002 return table->GetRowHilightRects ();
5005 return inherited::GetRowHilightRects (text, rowStart, rowEnd, hilightStart, hilightEnd);
5008void WordProcessor::DrawSegment (Tablet* tablet,
size_t from,
size_t to,
const TextLayoutBlock& text,
const Led_Rect& drawInto,
5009 const Led_Rect& invalidRect, CoordinateType useBaseLine, DistanceType* pixelsDrawn)
5011 DistanceType pixelsDrawn_;
5012 if (GetShowTabGlyphs ()) {
5013 if (pixelsDrawn ==
nullptr) {
5015 pixelsDrawn = &pixelsDrawn_;
5019 inherited::DrawSegment (tablet, from, to, text, drawInto, invalidRect, useBaseLine, pixelsDrawn);
5022 if (GetShowTabGlyphs () and GetJustification (from) == eLeftJustify) {
5023 for (
size_t i = from; i < to; ++i) {
5024 if (text.PeekAtVirtualText ()[i - from] ==
'\t') {
5026 DistanceType beforeTabPos = drawInto.GetLeft () + CalcSegmentSize (from, i);
5028 DistanceType afterTabPos = drawInto.GetLeft () + CalcSegmentSize (from, i + 1);
5029 Assert (beforeTabPos < afterTabPos);
5030 Led_Rect tabRect = drawInto;
5031 tabRect.SetLeft (beforeTabPos);
5032 tabRect.SetRight (afterTabPos);
5033 Assert (tabRect.GetLeft () < tabRect.GetRight ());
5036 Color arrowColor = GetEffectiveDefaultTextColor (eDefaultTextColor);
5038 Led_Rect arrowBody = tabRect;
5039 arrowBody.left += 2;
5040 arrowBody.right -= 2;
5041 arrowBody.top += arrowBody.GetHeight () / 2;
5042 arrowBody.bottom = arrowBody.top + 1;
5043 arrowBody.bottom = min (arrowBody.bottom, drawInto.bottom);
5044 tablet->EraseBackground_SolidHelper (arrowBody, arrowColor);
5047 const CoordinateType kArrowHSize = 8;
5048 const CoordinateType kArrowVSize = 8;
5049 Led_Point tip = arrowBody.GetTopRight ();
5050 CoordinateType hTriangleBase = max (arrowBody.right - kArrowHSize, arrowBody.left);
5051 Led_Point topPt = Led_Point (max (arrowBody.GetTop () - kArrowVSize / 2, tabRect.top), hTriangleBase);
5052 Led_Point botPt = Led_Point (min (arrowBody.GetTop () + kArrowVSize / 2, tabRect.bottom), hTriangleBase);
5053#if qStroika_Foundation_Common_Platform_Windows
5054 Brush backgroundBrush (arrowColor.GetOSRep ());
5055 GDI_Obj_Selector pen (tablet, ::GetStockObject (NULL_PEN));
5056 GDI_Obj_Selector brush (tablet, backgroundBrush);
5058 pts[0] = AsPOINT (tip);
5059 pts[1] = AsPOINT (topPt);
5060 pts[2] = AsPOINT (botPt);
5061 Verify (::Polygon (*tablet, pts,
static_cast<int> (std::size (pts))));
5062#elif qStroika_Foundation_Common_Platform_MacOS
5063 PolyHandle ph = ::OpenPoly ();
5064 ::MoveTo (tip.h, tip.v);
5065 ::LineTo (topPt.h, topPt.v);
5066 ::LineTo (botPt.h, botPt.v);
5067 ::LineTo (tip.h, tip.v);
5069 if (ph !=
nullptr) {
5070 Assert (*tablet == Led_GetCurrentGDIPort ());
5071 GDI_RGBForeColor (arrowColor.GetOSRep ());
5072 ::FillPoly (ph, &Pen::kBlackPattern);
5081 tablet->EraseBackground_SolidHelper (tabRect, Color::kRed);
5088DistanceType WordProcessor::MeasureSegmentHeight (
size_t from,
size_t to)
const
5090 Tablet_Acquirer tablet_ (
this);
5091 Tablet* tablet = tablet_;
5092 DistanceType d = inherited::MeasureSegmentHeight (from, to);
5095 shared_ptr<HidableTextMarkerOwner> hdb = GetHidableTextDatabase ();
5096 if (hdb.get () !=
nullptr) {
5097 DiscontiguousRun<bool> regions = hdb->GetHidableRegions (from, to);
5098 if (not regions.empty ()) {
5099 if (not regions[0].fData) {
5106 PartitionMarker* pm = GetPartitionMarkerContainingPosition (from);
5107 size_t pmStart = pm->GetStart ();
5108 size_t pmEnd = pm->GetEnd ();
5114 if (pmEnd - pmStart == 1) {
5115 vector<WordProcessorTable*> tables = GetTablesInRange (pmStart, pmEnd);
5116 if (tables.size () == 1) {
5118 WordProcessorTable* t = tables[0];
5119 Assert (t->GetStart () == pmStart);
5120 Assert (t->GetEnd () == pmEnd);
5126 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (from);
5128 LineSpacing sl = pi.GetLineSpacing ();
5130 case LineSpacing::eOnePointFiveSpace:
5134 case LineSpacing::eDoubleSpace:
5137 case LineSpacing::eAtLeastTWIPSSpacing:
5138 d = max (DistanceType (tablet->CvtFromTWIPSV (TWIPS (sl.fArg))), d);
5140 case LineSpacing::eExactTWIPSSpacing:
5141 d = tablet->CvtFromTWIPSV (TWIPS (sl.fArg));
5143 case LineSpacing::eExactLinesSpacing:
5149 case LineSpacing::eSingleSpace:
5154 bool isStartOfPara = pmStart == from;
5155 if (isStartOfPara) {
5156 d += tablet->CvtFromTWIPSV (pi.GetSpaceBefore ());
5160 bool isEndOfPara = pmEnd <= to + 1;
5162 d += tablet->CvtFromTWIPSV (pi.GetSpaceAfter ());
5168DistanceType WordProcessor::MeasureMinSegDescent (
size_t from,
size_t to)
const
5174 Require (from <= to);
5179 vector<StyleRunElement> outputSummary = SummarizeStyleMarkers (from, to);
5181 size_t outputSummaryLength = outputSummary.size ();
5182 Assert (outputSummaryLength != 0);
5183 DistanceType minHeightBelow = 0;
5184 size_t indexIntoText = 0;
5185 for (
size_t i = 0; i < outputSummaryLength; ++i) {
5186 const StyleRunElement& re = outputSummary[i];
5187 size_t reFrom = indexIntoText + from;
5188 size_t reLength = re.fLength;
5189 size_t reTo = reFrom + reLength;
5190 Assert (indexIntoText <= to - from);
5191 DistanceType itsBaseline;
5192 DistanceType itsHeight;
5193 if (re.fMarker ==
nullptr) {
5194 itsBaseline = MeasureSegmentBaseLine_ (GetDefaultFont (), reFrom, reTo);
5195 itsHeight = MeasureSegmentHeight_ (GetDefaultFont (), reFrom, reTo);
5198 itsBaseline = re.fMarker->MeasureSegmentBaseLine (
this, re, reFrom, reTo);
5199 itsHeight = re.fMarker->MeasureSegmentHeight (
this, re, reFrom, reTo);
5201 minHeightBelow = min (minHeightBelow, (itsHeight - itsBaseline));
5202 indexIntoText += reLength;
5204 return minHeightBelow;
5207void WordProcessor::AdjustBestRowLength (
size_t textStart,
const Led_tChar* text,
const Led_tChar* end,
size_t* rowLength)
5211 Require (text < end);
5213 Require (*rowLength > 0);
5214 inherited::AdjustBestRowLength (textStart, text, end, rowLength);
5215 for (
const Led_tChar* cur = &text[0]; cur < end; cur = Led_NextChar (cur)) {
5216 if (*cur == kEmbeddingSentinelChar) {
5218 vector<WordProcessorTable*> tables = GetTablesInRange (textStart + cur - text, textStart + cur - text + 1);
5219 if (not tables.empty ()) {
5220 Assert (cur == text);
5221 size_t newBestRowLength = (cur - text) + 1;
5222 Assert (newBestRowLength <= *rowLength + 1);
5227 Assert (newBestRowLength >= 1);
5228 *rowLength = newBestRowLength;
5237DistanceType WordProcessor::MeasureSegmentBaseLine (
size_t from,
size_t to)
const
5243 DistanceType d = inherited::MeasureSegmentBaseLine (from, to);
5246 shared_ptr<HidableTextMarkerOwner> hdb = GetHidableTextDatabase ();
5247 if (hdb.get () !=
nullptr) {
5248 DiscontiguousRun<bool> regions = hdb->GetHidableRegions (from, to);
5249 if (not regions.empty ()) {
5250 if (not regions[0].fData) {
5257 PartitionMarker* pm = GetPartitionMarkerContainingPosition (from);
5258 size_t pmStart = pm->GetStart ();
5259 size_t pmEnd = pm->GetEnd ();
5265 if (pmEnd - pmStart == 1) {
5266 vector<WordProcessorTable*> tables = GetTablesInRange (pmStart, pmEnd);
5267 if (tables.size () == 1) {
5269 WordProcessorTable* t = tables[0];
5270 Assert (t->GetStart () == pmStart);
5271 Assert (t->GetEnd () == pmEnd);
5286 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (from);
5288 LineSpacing sl = pi.GetLineSpacing ();
5290 case LineSpacing::eExactTWIPSSpacing: {
5291 Tablet_Acquirer tablet_ (
this);
5292 Tablet* tablet = tablet_;
5293 DistanceType revisedSegHeight = tablet->CvtFromTWIPSV (TWIPS (sl.fArg));
5294 DistanceType mhb = MeasureMinSegDescent (from, to);
5295 d = revisedSegHeight - mhb;
5297 case LineSpacing::eExactLinesSpacing: {
5299 Tablet_Acquirer tablet_ (
this);
5300 DistanceType normalSegHeight = inherited::MeasureSegmentHeight (from, to);
5301 DistanceType revisedSegHeight = normalSegHeight * sl.fArg / 20;
5302 DistanceType mhb = MeasureMinSegDescent (from, to);
5303 d = revisedSegHeight - mhb;
5312 bool isStartOfPara = pmStart == from;
5313 if (isStartOfPara) {
5314 TWIPS sb = pi.GetSpaceBefore ();
5316 Tablet_Acquirer tablet_ (
this);
5317 Tablet* tablet = tablet_;
5318 d += tablet->CvtFromTWIPSV (sb);
5331void WordProcessor::SetShowParagraphGlyphs (
bool showParagraphGlyphs)
5333 if (fShowParagraphGlyphs != showParagraphGlyphs) {
5334 fShowParagraphGlyphs = showParagraphGlyphs;
5335 InvalidateAllCaches ();
5347void WordProcessor::SetShowTabGlyphs (
bool showTabGlyphs)
5349 if (fShowTabGlyphs != showTabGlyphs) {
5350 fShowTabGlyphs = showTabGlyphs;
5362void WordProcessor::SetShowSpaceGlyphs (
bool showSpaceGlyphs)
5364 if (fShowSpaceGlyphs != showSpaceGlyphs) {
5365 fShowSpaceGlyphs = showSpaceGlyphs;
5366 InvalidateAllCaches ();
5371size_t WordProcessor::ComputeRelativePosition (
size_t fromPos, CursorMovementDirection direction, CursorMovementUnit movementUnit)
5373 size_t result = inherited::ComputeRelativePosition (fromPos, direction, movementUnit);
5380 shared_ptr<HidableTextMarkerOwner> hdb = GetHidableTextDatabase ();
5381 if (hdb.get () ==
nullptr) {
5383 if (direction == eCursorBack or direction == eCursorToStart) {
5384 DiscontiguousRun<bool> regions = hdb->GetHidableRegions (FindPreviousCharacter (result), result);
5385 if (not regions.empty ()) {
5388 if (not regions[0].fData) {
5389 result = FindPreviousCharacter (result);
5395 DiscontiguousRun<bool> regions = hdb->GetHidableRegions (result, FindNextCharacter (result));
5396 if (not regions.empty ()) {
5399 if (not regions[0].fData) {
5400 result = FindNextCharacter (result);
5414bool WordProcessor::ContainsMappedDisplayCharacters (
const Led_tChar* text,
size_t nTChars)
const
5416 if (fShowParagraphGlyphs and nTChars > 0 and text[nTChars - 1] ==
'\n') {
5419 if (fShowSpaceGlyphs and nTChars > 0 and ContainsMappedDisplayCharacters_HelperForChar (text, nTChars,
' ')) {
5422 return inherited::ContainsMappedDisplayCharacters (text, nTChars);
5429void WordProcessor::ReplaceMappedDisplayCharacters (
const Led_tChar* srcText, Led_tChar* copyText,
size_t nTChars)
const
5431 inherited::ReplaceMappedDisplayCharacters (srcText, copyText, nTChars);
5432 if (fShowParagraphGlyphs and nTChars > 0 and srcText[nTChars - 1] ==
'\n') {
5434 const Led_tChar kReplacementChar = 0x00b6;
5435 copyText[nTChars - 1] = kReplacementChar;
5437 if (fShowSpaceGlyphs) {
5439 const Led_tChar kReplacementChar = 0x00b7;
5440 ReplaceMappedDisplayCharacters_HelperForChar (copyText, nTChars,
' ', kReplacementChar);
5449Led_Rect WordProcessor::GetCharLocationRowRelative (
size_t afterPosition, RowReference topRow,
size_t maxRowsToCheck)
const
5451 Led_Rect r = inherited::GetCharLocationRowRelative (afterPosition, topRow, maxRowsToCheck);
5454 CoordinateType lhsMargin = 0;
5455 RowReference row = GetRowReferenceContainingPosition (afterPosition);
5456 GetLayoutMargins (row, &lhsMargin,
nullptr);
5457 r.left += lhsMargin;
5458 r.right += lhsMargin;
5461 Justification justification = GetJustification (afterPosition);
5462 if (justification == eCenterJustify or justification == eRightJustify) {
5463 switch (justification) {
5464 case eCenterJustify: {
5465 DistanceType d = CalcSpaceToEat (afterPosition) / 2;
5469 case eRightJustify: {
5470 DistanceType d = CalcSpaceToEat (afterPosition);
5484size_t WordProcessor::GetCharAtLocationRowRelative (
const Led_Point& where, RowReference topRow,
size_t maxRowsToCheck)
const
5487 size_t posInRow = inherited::GetCharAtLocationRowRelative (where, topRow, maxRowsToCheck);
5488 RowReference row = GetRowReferenceContainingPosition (posInRow);
5489 Led_Point adjustedWhere = where;
5491 CoordinateType lhsMargin = 0;
5492 GetLayoutMargins (row, &lhsMargin,
nullptr);
5493 adjustedWhere.h -= lhsMargin;
5495 Justification justification = GetJustification (posInRow);
5496 switch (justification) {
5497 case eCenterJustify: {
5498 adjustedWhere.h -= CalcSpaceToEat (posInRow) / 2;
5500 case eRightJustify: {
5501 adjustedWhere.h -= CalcSpaceToEat (posInRow);
5504 return inherited::GetCharAtLocationRowRelative (adjustedWhere, topRow, maxRowsToCheck);
5514size_t WordProcessor::ResetTabStops (
size_t from,
const Led_tChar* text,
size_t nTChars, DistanceType* charLocations,
size_t startSoFar)
const
5516 CoordinateType lhsMargin = 0;
5518 RowReference row = GetRowReferenceContainingPosition (from);
5519 GetLayoutMargins (row, &lhsMargin,
nullptr);
5521 return ResetTabStopsWithMargin (lhsMargin, from, text, nTChars, charLocations, startSoFar);
5524size_t WordProcessor::ResetTabStopsWithMargin (DistanceType lhsMargin,
size_t from,
const Led_tChar* text,
size_t nTChars,
5525 DistanceType* charLocations,
size_t startSoFar)
const
5528 size_t lastTabIndex = 0;
5529 CoordinateType tabAdjust = 0;
5530 DistanceType widthAtStart = (startSoFar == 0 ? 0 : charLocations[startSoFar - 1]);
5531 for (
size_t i = startSoFar; i < startSoFar + nTChars; ++i) {
5532 if (text[i] ==
'\t') {
5533 DistanceType widthSoFar = (i == 0 ? 0 : charLocations[i - 1]);
5534 tabAdjust = widthAtStart +
5535 GetTabStopList (from).ComputeTabStopAfterPosition (Tablet_Acquirer (
this), widthSoFar - widthAtStart + lhsMargin) -
5536 lhsMargin - charLocations[i];
5539 charLocations[i] += tabAdjust;
5541 return (lastTabIndex);
5549void WordProcessor::GetLayoutMargins (RowReference row, CoordinateType* lhs, CoordinateType* rhs)
const
5551 if (fParagraphDatabase.get () ==
nullptr) {
5552 throw NoParagraphDatabaseAvailable ();
5555 PartitionMarker* pm = row.GetPartitionMarker ();
5556 size_t pmStart = pm->GetStart ();
5558 Tablet_Acquirer tablet_ (
this);
5559 Tablet* tablet = tablet_;
5561 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (pmStart);
5562 if (lhs !=
nullptr) {
5563 TWIPS lhsTWIPS = pi.GetLeftMargin ();
5564 if (row.GetSubRow () == 0) {
5565 lhsTWIPS += pi.GetFirstIndent ();
5567 *lhs = tablet->CvtFromTWIPSH (lhsTWIPS);
5568 if (row.GetSubRow () == 0) {
5569 ListStyle ls = pi.GetListStyle ();
5570 if (ls != eListStyle_None) {
5574 bool allowLists =
true;
5575 size_t pmEnd = pm->GetEnd ();
5576 if (pmEnd - pmStart == 1) {
5577 vector<WordProcessorTable*> tables = GetTablesInRange (pmStart, pmEnd);
5578 if (tables.size () == 1) {
5583 *lhs += GetListLeaderLength (pmStart);
5588 if (rhs !=
nullptr) {
5589 *rhs = tablet->CvtFromTWIPSH (pi.GetRightMargin ());
5593void WordProcessor::ExpandedFromAndToInPostReplace (
size_t from,
size_t newTo,
size_t stableTypingRegionStart,
size_t stableTypingRegionEnd,
5594 size_t startPositionOfRowWhereReplaceBegins,
size_t startPositionOfRowAfterReplaceEnds,
5595 size_t* expandedFrom,
size_t* expandedTo)
5597 Justification justification = GetJustification (from);
5598 if (justification != eLeftJustify) {
5599 from = GetStartOfRowContainingPosition (from);
5601 inherited::ExpandedFromAndToInPostReplace (from, newTo, stableTypingRegionStart, stableTypingRegionEnd, startPositionOfRowWhereReplaceBegins,
5602 startPositionOfRowAfterReplaceEnds, expandedFrom, expandedTo);
5605void WordProcessor::PostReplace (PreReplaceInfo& preReplaceInfo)
5607 inherited::PostReplace (preReplaceInfo);
5608 UpdateMode updateMode = preReplaceInfo.GetUpdateMode ();
5609 if (updateMode != eNoUpdate) {
5610 if (preReplaceInfo.GetTo () + 2 >= GetEnd ()) {
5617 ListStyle ls = eListStyle_None;
5618 if (not WordProcessor::GetListStyle (preReplaceInfo.GetFrom (), GetEnd (), &ls) or ls != eListStyle_None) {
5619 Refresh (updateMode);
5625DistanceType WordProcessor::CalcSpaceToEat (
size_t rowContainingCharPos)
const
5627 size_t rowStart = GetStartOfRowContainingPosition (rowContainingCharPos);
5628 size_t rowEnd = GetEndOfRowContainingPosition (rowStart);
5629 Assert (rowEnd == GetEndOfRowContainingPosition (rowContainingCharPos));
5632 size_t lenOfText = rowEnd - rowStart;
5634 CopyOut (rowStart, lenOfText, buf.data ());
5636 while (rowStart < rowEnd) {
5637 size_t i = rowEnd - rowStart - 1;
5647 DistanceType segmentWidth = CalcSegmentSize (rowStart, rowEnd);
5648 DistanceType layoutWidth;
5650 CoordinateType lhsMargin = 0;
5651 CoordinateType rhsMargin = 0;
5652 GetLayoutMargins (GetRowReferenceContainingPosition (rowStart), &lhsMargin, &rhsMargin);
5653 Assert (lhsMargin < rhsMargin);
5654 layoutWidth = rhsMargin - lhsMargin;
5658 if (layoutWidth < segmentWidth) {
5662 Assert (layoutWidth >= segmentWidth);
5663 DistanceType xtra = layoutWidth - segmentWidth;
5672using WordProcessorFlavorPackageInternalizer = WordProcessor::WordProcessorFlavorPackageInternalizer;
5674WordProcessorFlavorPackageInternalizer::WordProcessorFlavorPackageInternalizer (TextStore& ts,
const shared_ptr<AbstractStyleDatabaseRep>& styleDatabase,
5675 const shared_ptr<AbstractParagraphDatabaseRep>& paragraphDatabase,
5676 const shared_ptr<HidableTextMarkerOwner>& hidableTextDatabase)
5678 , inherited (ts, styleDatabase)
5679 , fOverwriteTableMode (false)
5681#if !qStroika_Frameworks_Led_NestedTablesSupported
5682 fNoTablesAllowed (false)
5685 fParagraphDatabase (paragraphDatabase)
5686 , fHidableTextDatabase (hidableTextDatabase)
5694 sinkStream->SetIgnoreLastParaAttributes (
true);
5695 sinkStream->SetOverwriteTableMode (GetOverwriteTableMode ());
5696#if !qStroika_Frameworks_Led_NestedTablesSupported
5697 sinkStream->SetNoTablesAllowed (GetNoTablesAllowed ());
5708WordProcessor::WPPartition::WPPartition (TextStore& textStore,
MarkerOwner& tableMarkerOwner)
5709 : inherited{textStore, eSpecialHackToDisableInit}
5710 , fTableMarkerOwner{tableMarkerOwner}
5716vector<WordProcessorTable*> WordProcessor::WPPartition::GetTablesInRange (
size_t from,
size_t to)
const
5718 if (to ==
static_cast<size_t> (-1)) {
5719 to = GetTextStore ().GetLength ();
5721 Require (from <= to);
5722 Require (to <= GetTextStore ().GetLength () + 1);
5723 MarkersOfATypeMarkerSink2Vector<WordProcessorTable> result;
5724 GetTextStore ().CollectAllMarkersInRangeInto (from, to, &fTableMarkerOwner, result);
5725 return result.fResult;
5728WordProcessorTable* WordProcessor::GetActiveTable ()
const
5730 size_t selStart = 0;
5732 GetSelection (&selStart, &selEnd);
5733 if (selEnd - selStart == 1) {
5734 vector<WordProcessorTable*> tables = GetTablesInRange (selStart, selEnd);
5735 Assert (tables.size () <= 1);
5736 if (tables.size () == 1) {
5744void WordProcessor::WPPartition::FinalConstruct ()
5747 inherited::FinalConstruct ();
5748 DoHandleUpdateForTableRangeCheck (0, GetTextStore ().GetLength ());
5751void WordProcessor::WPPartition::DidUpdateText (
const UpdateInfo& updateInfo)
noexcept
5756 DoHandleUpdateForTableRangeCheck (updateInfo.fReplaceFrom, updateInfo.GetResultingRHS ());
5759 inherited::DidUpdateText (updateInfo);
5762void WordProcessor::WPPartition::DoHandleUpdateForTableRangeCheck (
size_t from,
size_t to)
noexcept
5764 TextStore& ts = GetTextStore ();
5767 vector<WordProcessorTable*> tables = GetTablesInRange (ts.FindPreviousCharacter (from), ts.FindNextCharacter (to));
5768 for (
auto i = tables.begin (); i != tables.end (); ++i) {
5769 WordProcessorTable* t = *i;
5770 if (t->GetLength () != 0) {
5771 size_t tableEnd = t->GetEnd ();
5774 size_t tableStart = t->GetStart ();
5775 PartitionMarker* pm = GetPartitionMarkerContainingPosition (tableStart);
5780 if (tableEnd < pm->GetEnd () and tableEnd > pm->GetStart ()) {
5781 Split (pm, tableEnd);
5783 if (tableStart > pm->GetStart () and tableStart < pm->GetEnd ()) {
5784 Split (pm, tableStart);
5788 bool coalesce = NeedToCoalesce (pm);
5792 pm = pm->GetPrevious ();
5793 if (pm !=
nullptr) {
5794 coalesce = NeedToCoalesce (pm);
5798 pm = pm->GetPrevious ();
5799 if (pm !=
nullptr) {
5800 coalesce = NeedToCoalesce (pm);
5809 PartitionMarker* pm = GetPartitionMarkerContainingPosition (from);
5811 bool coalesce = NeedToCoalesce (pm);
5815 pm = pm->GetPrevious ();
5816 if (pm !=
nullptr) {
5817 coalesce = NeedToCoalesce (pm);
5821 pm = pm->GetPrevious ();
5822 if (pm !=
nullptr) {
5823 coalesce = NeedToCoalesce (pm);
5831bool WordProcessor::WPPartition::NeedToCoalesce (PartitionMarker* pm)
noexcept
5835 bool coalesce = inherited::NeedToCoalesce (pm);
5843 if (pm->GetLength () != 0) {
5844 size_t end = pm->GetEnd ();
5845 size_t trStart = end - 1;
5847 if (pm->GetNext () !=
nullptr) {
5851 vector<WordProcessorTable*> tables = GetTablesInRange (trStart, trEnd);
5852 if (not tables.empty ()) {
5853 if (tables.size () == 2) {
5857 else if (tables.size () == 1) {
5858 WordProcessorTable* table = tables[0];
5860 if (table->GetStart () == pm->GetEnd ()) {
5863 else if (table->GetEnd () == pm->GetEnd ()) {
5873#if qStroika_Foundation_Debug_AssertionsChecked
5874void WordProcessor::WPPartition::Invariant_ ()
const
5876 Partition::Invariant_ ();
5884 for (PartitionMarker* cur = GetFirstPartitionMarker (); cur !=
nullptr; cur = cur->GetNext ()) {
5886 size_t start = cur->GetStart ();
5887 size_t end = cur->GetEnd ();
5888 size_t len = end - start;
5890 if (end > GetEnd ()) {
5894 CopyOut (start, len, buf.data ());
5895 for (
size_t i = 1; i < len; ++i) {
5896 Assert (buf[i - 1] !=
'\n');
5897 vector<WordProcessorTable*> tables = GetTablesInRange (start + i - 1, start + i);
5898 if (not tables.empty ()) {
5899 Assert (tables.size () == 1);
5900 WordProcessorTable* t = tables[0];
5901 if (t->GetLength () != 0) {
5902 Assert (t->GetStart () == start);
5903 Assert (t->GetLength () == len);
5907 if (cur->GetNext () !=
nullptr) {
5908 Assert (buf[len - 1] ==
'\n' or (not GetTablesInRange (start + len - 1, start + len).empty ()) or
5909 (start + len + 1 <= GetEnd () and not GetTablesInRange (start + len, start + len + 1).empty ()));
5915 vector<WordProcessorTable*> tables = GetTablesInRange (0, GetTextStore ().GetLength ());
5916 for (
auto i = tables.begin (); i != tables.end (); ++i) {
5917 WordProcessorTable* t = *i;
5918 if (t->GetLength () != 0) {
5919 PartitionMarker* pm = GetPartitionMarkerContainingPosition (t->GetStart ());
5920 Assert (t->GetStart () == pm->GetStart ());
5921 Assert (t->GetEnd () == pm->GetEnd ());
5932using WordProcessorFlavorPackageExternalizer = WordProcessor::WordProcessorFlavorPackageExternalizer;
5934WordProcessorFlavorPackageExternalizer::WordProcessorFlavorPackageExternalizer (TextStore& ts,
const shared_ptr<AbstractStyleDatabaseRep>& styleDatabase,
5935 const shared_ptr<AbstractParagraphDatabaseRep>& paragraphDatabase,
5936 const shared_ptr<HidableTextMarkerOwner>& hidableTextDatabase)
5938 , inherited (ts, styleDatabase)
5939 , fParagraphDatabase (paragraphDatabase)
5940 , fHidableTextDatabase (hidableTextDatabase)
5944StandardStyledTextIOSrcStream* WordProcessorFlavorPackageExternalizer::mkStandardStyledTextIOSrcStream (
size_t selectionStart,
size_t selectionEnd)
5947 fHidableTextDatabase, selectionStart, selectionEnd);
5948 stream->SetUseTableSelection (GetUseTableSelection ());
5952void WordProcessorTable::DrawSegment (
const StyledTextImager* imager,
const StyleRunElement& , Tablet* tablet,
5953 [[maybe_unused]]
size_t from, [[maybe_unused]]
size_t to, [[maybe_unused]]
const TextLayoutBlock& text,
5954 const Led_Rect& drawInto,
const Led_Rect& invalidRect, CoordinateType , DistanceType* pixelsDrawn)
5956 RequireMember (
const_cast<StyledTextImager*
> (imager), WordProcessor);
5957 Assert (from + 1 == to);
5959 Require (text.PeekAtVirtualText ()[0] == kEmbeddingSentinelChar);
5961 using TemporarilyUseTablet = EmbeddedTableWordProcessor::TemporarilyUseTablet;
5963 WordProcessor& owningWP = *
dynamic_cast<WordProcessor*
> (
const_cast<StyledTextImager*
> (imager));
5965 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*
this, owningWP);
5967 DistanceType bwv = Led_CvtScreenPixelsFromTWIPSV (fBorderWidth);
5968 Led_Rect rowRect = drawInto;
5970 size_t nRows = fRows.size ();
5971 for (
size_t ri = 0; ri < nRows; ++ri) {
5974 size_t nCols = GetColumnCount (ri);
5975 rowRect.bottom = rowRect.top + fRows[ri].fHeight;
5976 for (
size_t ci = 0; ci < nCols; ++ci) {
5977 if (GetCellFlags (ri, ci) == ePlainCell) {
5978 Led_Rect scrolledCBWR = TableCoordinates2Window (GetCellBounds (ri, ci));
5979 if (Intersect (scrolledCBWR, invalidRect)) {
5980 Led_Rect scrolledEditorCBWR = TableCoordinates2Window (GetCellEditorBounds (ri, ci));
5984 if (scrolledCBWR != scrolledEditorCBWR) {
5985 tablet->EraseBackground_SolidHelper (scrolledCBWR, GetCellColor (ri, ci));
5988 TemporarilyAllocateCellWP wp (*
this, owningWP, ri, ci, scrolledEditorCBWR);
5989 TemporarilyUseTablet tmpUseTablet (*wp, tablet, TemporarilyUseTablet::eDontDoTextMetricsChangedCall);
5990 wp->Draw (scrolledEditorCBWR,
false);
5991 DrawCellBorders (tablet, ri, ci, scrolledCBWR);
5997 if (scrolledCBWR.bottom < invalidRect.top) {
6000 if (scrolledCBWR.top > invalidRect.bottom) {
6006 rowRect.top = rowRect.bottom + bwv;
6010 DrawTableBorders (owningWP, tablet, drawInto);
6012 if (pixelsDrawn !=
nullptr) {
6013 *pixelsDrawn = fTotalWidth;
6017void WordProcessorTable::MeasureSegmentWidth ([[maybe_unused]]
const StyledTextImager* imager,
const StyleRunElement& ,
6018 [[maybe_unused]]
size_t from, [[maybe_unused]]
size_t to,
6019 [[maybe_unused]]
const Led_tChar* text, DistanceType* distanceResults)
const
6021 RequireMember (
const_cast<StyledTextImager*
> (imager), WordProcessor);
6022 Assert (from + 1 == to);
6024 distanceResults[0] = fTotalWidth;
6027DistanceType WordProcessorTable::MeasureSegmentHeight ([[maybe_unused]]
const StyledTextImager* imager,
const StyleRunElement& ,
6028 [[maybe_unused]]
size_t from, [[maybe_unused]]
size_t to)
const
6030 RequireMember (
const_cast<StyledTextImager*
> (imager), WordProcessor);
6031 Assert (from + 1 == to);
6034 return fTotalHeight == 0 ? 1 : fTotalHeight;
6042vector<Led_Rect> WordProcessorTable::GetRowHilightRects ()
const
6044 Led_Require_CurrentOwningWP ();
6046 vector<Led_Rect> result;
6048 size_t rowStart = GetStart ();
6049 size_t rowEnd = GetEnd ();
6050 size_t hilightStart = fCurrentOwningWP->GetSelectionStart ();
6051 size_t hilightEnd = fCurrentOwningWP->GetSelectionEnd ();
6052 bool segmentHilighted = max (rowStart, hilightStart) < min (rowEnd, hilightEnd);
6054 if (segmentHilighted) {
6055 Led_Rect tableRect = fCurrentOwningWP->GetIntraRowTextWindowBoundingRect (rowStart, rowEnd);
6056 vector<Led_Rect> hilightRects = fCurrentOwningWP->TextImager::GetRowHilightRects (
6057 TextLayoutBlock_Basic{&kEmbeddingSentinelChar, &kEmbeddingSentinelChar + 1}, rowStart, rowEnd, hilightStart, hilightEnd);
6061 if (rowStart != hilightStart or rowEnd != hilightEnd) {
6062 return hilightRects;
6069 for (
auto i = hilightRects.begin (); i != hilightRects.end (); ++i) {
6070 if (tableRect != *i) {
6071 if (not(*i).IsEmpty ()) {
6072 result.push_back (*i);
6081 size_t rowSelStart = 0;
6082 size_t rowSelEnd = 0;
6083 size_t colSelStart = 0;
6084 size_t colSelEnd = 0;
6085 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6088 if (rowSelStart == 0 and rowSelEnd == GetRowCount () and colSelStart == 0 and colSelEnd == GetColumnCount ()) {
6089 return hilightRects;
6092 if (rowSelEnd - rowSelStart == 1 and colSelEnd - colSelStart == 1 and GetIntraCellMode ()) {
6093 TemporarilyAllocateCellWithTablet wp (*
const_cast<WordProcessorTable*
> (
this), rowSelStart, colSelStart);
6094 vector<Led_Rect> cellHilightRegions = wp->GetSelectionWindowRects (wp->GetSelectionStart (), wp->GetSelectionEnd ());
6095 for (
auto i = cellHilightRegions.begin (); i != cellHilightRegions.end (); ++i) {
6096 result.push_back (*i);
6100 for (
size_t ri = rowSelStart; ri < rowSelEnd; ++ri) {
6101 size_t thisRowEnd = min (colSelEnd, GetColumnCount (ri));
6102 for (
size_t ci = colSelStart; ci < thisRowEnd; ++ci) {
6103 if (GetCellFlags (ri, ci) == ePlainCell) {
6105 Led_Rect wRelCellRect = TableCoordinates2Window (GetCellBounds (ri, ci));
6106 if (not wRelCellRect.IsEmpty ()) {
6107 result.push_back (wRelCellRect);
6118 for (
auto orit = result.begin (); orit != result.end (); ++orit) {
6119 Ensure ((*orit).GetWidth () > 0);
6120 Ensure ((*orit).GetHeight () > 0);
6121 for (
auto irit = orit + 1; irit != result.end (); ++irit) {
6122 Led_Rect hr = *irit;
6123 Ensure (hr.GetWidth () > 0);
6124 Ensure (hr.GetHeight () > 0);
6125 Ensure (not Intersect (hr, *orit));
6138void WordProcessorTable::DrawTableBorders (WordProcessor& owningWP, Tablet* tablet,
const Led_Rect& drawInto)
6148 DistanceType bwh = Led_CvtScreenPixelsFromTWIPSH (fBorderWidth);
6151 Led_Rect bounds = drawInto - Led_Point (0, owningWP.GetHScrollPos ());
6152 bounds.right = bounds.left + fTotalWidth;
6153 bounds.bottom = bounds.top + fTotalHeight;
6154 tablet->FrameRectangle (bounds, fBorderColor, bwh);
6164void WordProcessorTable::DrawCellBorders (Tablet* tablet,
size_t ,
size_t ,
const Led_Rect& cellBounds)
6166 CoordinateType bw = Led_CvtScreenPixelsFromTWIPSH (fBorderWidth);
6168 tablet->FrameRectangle (InsetRect (cellBounds, -bw, -bw), fBorderColor, bw);
6179Led_Rect WordProcessorTable::GetCellBounds (
size_t row,
size_t column)
const
6181 Require (GetCellFlags (row, column) == ePlainCell);
6182 return GetCell (row, column).GetCachedBoundsRect ();
6191Led_Rect WordProcessorTable::GetCellEditorBounds (
size_t row,
size_t column)
const
6193 Require (GetCellFlags (row, column) == ePlainCell);
6194 Led_Rect cellBounds = GetCellBounds (row, column);
6195 Led_Rect cellEditBounds = cellBounds;
6196 TWIPS_Rect defaultCellMarginTWIPS;
6197 GetDefaultCellMargins (&defaultCellMarginTWIPS.top, &defaultCellMarginTWIPS.left, &defaultCellMarginTWIPS.bottom,
6198 &defaultCellMarginTWIPS.right);
6199 cellEditBounds.top += Led_CvtScreenPixelsFromTWIPSV (defaultCellMarginTWIPS.top);
6200 cellEditBounds.left += Led_CvtScreenPixelsFromTWIPSH (defaultCellMarginTWIPS.left);
6201 cellEditBounds.bottom -= Led_CvtScreenPixelsFromTWIPSV (defaultCellMarginTWIPS.bottom);
6202 cellEditBounds.right -= Led_CvtScreenPixelsFromTWIPSH (defaultCellMarginTWIPS.right);
6204 cellEditBounds.bottom = max (cellEditBounds.bottom, cellEditBounds.top + 1);
6205 cellEditBounds.right = max (cellEditBounds.right, cellEditBounds.left + 1);
6206 return cellEditBounds;
6214void WordProcessorTable::GetClosestCell (
const Led_Point& p,
size_t* row,
size_t* col)
const
6219 Led_Size border = Led_Size (Led_CvtScreenPixelsFromTWIPSV (fBorderWidth), Led_CvtScreenPixelsFromTWIPSH (fBorderWidth));
6220 DistanceType spacing = Led_CvtScreenPixelsFromTWIPSV (GetCellSpacing ());
6223 size_t rowCount = GetRowCount ();
6224 Assert (rowCount > 0);
6225 CoordinateType top = spacing + border.v;
6227 for (; ri < rowCount; ++ri) {
6228 DistanceType h = fRows[ri].fHeight;
6229 CoordinateType bottom = top + h;
6235 top += spacing + border.v;
6237 if (ri >= rowCount) {
6243 size_t colCount = GetColumnCount (ri);
6244 Assert (colCount > 0);
6246 for (; ci < colCount; ++ci) {
6249 GetRealCell (&rri, &cci);
6250 Led_Rect bounds = GetCellBounds (rri, cci);
6252 if (p.h < bounds.GetRight ()) {
6256 if (ci >= colCount) {
6262Led_Point WordProcessorTable::TableCoordinates2Window (
const Led_Point& p)
const
6264 Led_Require_CurrentOwningWP ();
6265 Led_Point tableWROrigin = fCurrentOwningWP->GetCharWindowLocation (GetStart ()).GetTopLeft ();
6266 return p + tableWROrigin;
6269Led_Rect WordProcessorTable::TableCoordinates2Window (
const Led_Rect& r)
const
6271 return Led_Rect (TableCoordinates2Window (r.GetOrigin ()), r.GetSize ());
6274Led_Point WordProcessorTable::WindowCoordinates2Table (
const Led_Point& p)
const
6276 Led_Require_CurrentOwningWP ();
6277 Led_Point tableWROrigin = fCurrentOwningWP->GetCharWindowLocation (GetStart ()).GetTopLeft ();
6278 return p - tableWROrigin;
6281Led_Rect WordProcessorTable::WindowCoordinates2Table (
const Led_Rect& r)
const
6283 return Led_Rect (WindowCoordinates2Table (r.GetOrigin ()), r.GetSize ());
6286bool WordProcessorTable::GetCaretShownSituation ()
const
6288 if (GetIntraCellMode ()) {
6289 size_t selStart = 0;
6291 GetIntraCellSelection (&selStart, &selEnd);
6292 return selStart == selEnd;
6301Led_Rect WordProcessorTable::CalculateCaretRect ()
const
6303 Led_Require_CurrentOwningWP ();
6304 if (GetIntraCellMode ()) {
6305 size_t selStart = 0;
6307 GetIntraCellSelection (&selStart, &selEnd);
6308 if (selStart == selEnd) {
6311 (void)GetIntraCellMode (&row, &col);
6312 TemporarilyAllocateCellWithTablet wp (*
const_cast<WordProcessorTable*
> (
this), row, col);
6313 return wp->CalculateCaretRect ();
6316 return (Led_Rect (0, 0, 0, 0));
6319bool WordProcessorTable::OnTypedNormalCharacter (Led_tChar theChar,
bool optionPressed,
bool shiftPressed,
bool commandPressed,
6320 bool controlPressed,
bool altKeyPressed)
6322 using InteractiveModeUpdater = WordProcessor::InteractiveModeUpdater;
6323 using UndoableContextHelper = WordProcessor::UndoableContextHelper;
6324 Led_Require_CurrentOwningWP ();
6326 size_t rowSelStart = 0;
6327 size_t rowSelEnd = 0;
6328 size_t colSelStart = 0;
6329 size_t colSelEnd = 0;
6330 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6332 if (theChar ==
'\b') {
6334 if (rowSelStart == 0 and rowSelEnd == GetRowCount () and colSelStart == 0 and colSelEnd == GetColumnCount () and not fIntraCellMode) {
6339 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6340 AllowUpdateInfoPropagationContext AUIPC (*
this);
6341 if (not fIntraCellMode) {
6344 UndoableContextHelper undoContext (*fCurrentOwningWP, TextInteractor::GetCommandNames ().fTypingCommandName,
false);
6346 (void)OnPerformCommand_ApplyToEachSelectedCell (TextInteractor::kClear_CmdID,
false);
6348 undoContext.CommandComplete ();
6349 SetIntraCellMode (rowSelStart, colSelStart);
6352 Assert (fIntraCellMode);
6353 TemporarilyAllocateCellWithTablet wp (*
this, rowSelStart, colSelStart);
6354 wp->OnTypedNormalCharacter (theChar, optionPressed, shiftPressed, commandPressed, controlPressed, altKeyPressed);
6359bool WordProcessorTable::DoSingleCharCursorEdit (TextInteractor::CursorMovementDirection direction,
6360 TextInteractor::CursorMovementUnit movementUnit, TextInteractor::CursorMovementAction action,
6361 TextInteractor::UpdateMode updateMode,
bool scrollToSelection)
6365 if (GetIntraCellMode (&row, &col)) {
6367 AllowUpdateInfoPropagationContext AUIPC (*
this);
6368 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6369 wp->DoSingleCharCursorEdit (direction, movementUnit, action, updateMode, scrollToSelection);
6375bool WordProcessorTable::OnUpdateCommand (TextInteractor::CommandUpdater* enabler)
6377 Led_Require_CurrentOwningWP ();
6382 if (GetIntraCellMode (&row, &col)) {
6383 if (fCurrentOwningWP->PassAlongCommandToIntraCellModeTableCell (enabler->GetCmdID ())) {
6384 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6385 [[maybe_unused]]
bool result = wp->OnUpdateCommand (enabler);
6386 if (enabler->GetCmdID () == WordProcessor::kSelectedEmbeddingProperties_CmdID and not enabler->GetEnabled ()) {
6394 switch (enabler->GetCmdID ()) {
6395 case WordProcessor::kCut_CmdID: {
6396 OnUpdateCutCommand (enabler);
6399 case WordProcessor::kInsertTableRowAbove_CmdID: {
6400 OnUpdateInsertTableRowAboveCommand (enabler);
6403 case WordProcessor::kInsertTableRowBelow_CmdID: {
6404 OnUpdateInsertTableRowBelowCommand (enabler);
6407 case WordProcessor::kInsertTableColBefore_CmdID: {
6408 OnUpdateInsertTableColBeforeCommand (enabler);
6411 case WordProcessor::kInsertTableColAfter_CmdID: {
6412 OnUpdateInsertTableColAfterCommand (enabler);
6415 case WordProcessor::kRemoveTableColumns_CmdID: {
6416 OnUpdateRemoveTableColumnsCommand (enabler);
6419 case WordProcessor::kRemoveTableRows_CmdID: {
6420 OnUpdateRemoveTableRowsCommand (enabler);
6423 case WordProcessor::kSelectTableIntraCellAll_CmdID:
6424 case WordProcessor::kSelectTableCell_CmdID:
6425 case WordProcessor::kSelectTableRow_CmdID:
6426 case WordProcessor::kSelectTableColumn_CmdID:
6427 case WordProcessor::kSelectTable_CmdID: {
6428 OnUpdateSelectTablePartsCommand (enabler);
6433 if (fCurrentOwningWP->PassAlongCommandToEachSelectedTableCell (enabler->GetCmdID ())) {
6434 return OnUpdateCommand_ApplyToEachSelectedCell (enabler);
6440bool WordProcessorTable::OnPerformCommand (TextInteractor::CommandNumber commandNumber)
6442 Led_Require_CurrentOwningWP ();
6444 AllowUpdateInfoPropagationContext AUIPC (*
this);
6448 if (GetIntraCellMode (&row, &col)) {
6449 if (fCurrentOwningWP->PassAlongCommandToIntraCellModeTableCell (commandNumber)) {
6450 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6451 return wp->OnPerformCommand (commandNumber);
6455 switch (commandNumber) {
6456 case WordProcessor::kCut_CmdID: {
6460 case WordProcessor::kInsertTableRowAbove_CmdID: {
6461 OnInsertTableRowAboveCommand ();
6464 case WordProcessor::kInsertTableRowBelow_CmdID: {
6465 OnInsertTableRowBelowCommand ();
6468 case WordProcessor::kInsertTableColBefore_CmdID: {
6469 OnInsertTableColBeforeCommand ();
6472 case WordProcessor::kInsertTableColAfter_CmdID: {
6473 OnInsertTableColAfterCommand ();
6476 case WordProcessor::kRemoveTableColumns_CmdID: {
6477 OnRemoveTableColumnsCommand ();
6480 case WordProcessor::kRemoveTableRows_CmdID: {
6481 OnRemoveTableRowsCommand ();
6484 case WordProcessor::kSelectTableIntraCellAll_CmdID:
6485 case WordProcessor::kSelectTableCell_CmdID:
6486 case WordProcessor::kSelectTableRow_CmdID:
6487 case WordProcessor::kSelectTableColumn_CmdID:
6488 case WordProcessor::kSelectTable_CmdID: {
6489 OnPerformTablePartsCommand (commandNumber);
6494 if (fCurrentOwningWP->PassAlongCommandToEachSelectedTableCell (commandNumber)) {
6495 return OnPerformCommand_ApplyToEachSelectedCell (commandNumber);
6501void WordProcessorTable::BreakInGroupedCommands ()
6503 Led_Require_CurrentOwningWP ();
6504 fCurrentOwningWP->BreakInGroupedCommands ();
6507bool WordProcessorTable::OnUpdateCommand_ApplyToEachSelectedCell (TextInteractor::CommandUpdater* enabler)
6510 Led_Require_CurrentOwningWP ();
6512 bool result =
false;
6513 size_t rowSelStart = 0;
6514 size_t rowSelEnd = 0;
6515 size_t colSelStart = 0;
6516 size_t colSelEnd = 0;
6517 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6518 for (
size_t ri = rowSelStart; ri < rowSelEnd; ++ri) {
6519 size_t thisRowEnd = min (colSelEnd, GetColumnCount (ri));
6520 for (
size_t ci = colSelStart; ci < thisRowEnd; ++ci) {
6521 TemporarilyAllocateCellWithTablet wp (*
this, ri, ci);
6522 wp->SetSelection (0, wp->GetEnd (), TextInteractor::eNoUpdate);
6523 result = result or wp->OnUpdateCommand (enabler);
6529bool WordProcessorTable::OnPerformCommand_ApplyToEachSelectedCell (TextInteractor::CommandNumber commandNumber,
bool captureChangesForUndo)
6531 Led_Require_CurrentOwningWP ();
6532 if (captureChangesForUndo) {
6533 fCurrentOwningWP->BreakInGroupedCommands ();
6535 bool result =
false;
6536 size_t rowSelStart = 0;
6537 size_t rowSelEnd = 0;
6538 size_t colSelStart = 0;
6539 size_t colSelEnd = 0;
6540 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6541 for (
size_t ri = rowSelStart; ri < rowSelEnd; ++ri) {
6542 size_t thisRowEnd = min (colSelEnd, GetColumnCount (ri));
6543 for (
size_t ci = colSelStart; ci < thisRowEnd; ++ci) {
6544 TemporarilyAllocateCellWithTablet wp (*
this, ri, ci, captureChangesForUndo);
6545 wp->SetSelection (0, wp->GetEnd (), TextInteractor::eNoUpdate);
6546 TextInteractor::SuppressCommandBreaksContext SCBC (*wp);
6547 wp->OnPerformCommand (commandNumber);
6551 if (captureChangesForUndo) {
6552 fCurrentOwningWP->BreakInGroupedCommands ();
6557void WordProcessorTable::OnUpdateCutCommand (TextInteractor::CommandUpdater* enabler)
6560 Led_Require_CurrentOwningWP ();
6561 size_t rowSelStart = 0;
6562 size_t rowSelEnd = 0;
6563 size_t colSelStart = 0;
6564 size_t colSelEnd = 0;
6565 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6566 enabler->SetEnabled (rowSelStart != rowSelEnd and colSelStart != colSelEnd);
6569void WordProcessorTable::OnCutCommand ()
6571 Led_Require_CurrentOwningWP ();
6572 AllowUpdateInfoPropagationContext AUIPC (*
this);
6573 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6574 Assert (fCurrentOwningWP->GetSelectionEnd () - fCurrentOwningWP->GetSelectionStart () == 1);
6575 fCurrentOwningWP->OnCopyCommand ();
6576 UndoableContextHelper undoContext (*fCurrentOwningWP, TextInteractor::GetCommandNames ().fCutCommandName,
true);
6578 (void)OnPerformCommand_ApplyToEachSelectedCell (TextInteractor::kClear_CmdID,
false);
6580 undoContext.CommandComplete ();
6583void WordProcessorTable::OnUpdateInsertTableRowAboveCommand (TextInteractor::CommandUpdater* enabler)
6586 Led_Require_CurrentOwningWP ();
6587 enabler->SetEnabled (
true);
6590void WordProcessorTable::OnInsertTableRowAboveCommand ()
6592 Led_Require_CurrentOwningWP ();
6593 AllowUpdateInfoPropagationContext AUIPC (*
this);
6594 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6595 BreakInGroupedCommands ();
6596 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fInsertTableRowAboveCommandName,
false);
6600 GetCellSelection (&curRow,
nullptr,
nullptr,
nullptr);
6602 Assert (curRow <= GetRowCount ());
6605 context.CommandComplete ();
6606 BreakInGroupedCommands ();
6609void WordProcessorTable::OnUpdateInsertTableRowBelowCommand (TextInteractor::CommandUpdater* enabler)
6612 Led_Require_CurrentOwningWP ();
6613 enabler->SetEnabled (
true);
6616void WordProcessorTable::OnInsertTableRowBelowCommand ()
6618 Led_Require_CurrentOwningWP ();
6619 AllowUpdateInfoPropagationContext AUIPC (*
this);
6620 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6621 BreakInGroupedCommands ();
6622 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fInsertTableRowAboveCommandName,
false);
6626 GetCellSelection (
nullptr, &curRow,
nullptr,
nullptr);
6627 Assert (curRow <= GetRowCount ());
6630 context.CommandComplete ();
6631 BreakInGroupedCommands ();
6634void WordProcessorTable::OnUpdateInsertTableColBeforeCommand (TextInteractor::CommandUpdater* enabler)
6636 Led_Require_CurrentOwningWP ();
6638 enabler->SetEnabled (
true);
6641void WordProcessorTable::OnInsertTableColBeforeCommand ()
6643 Led_Require_CurrentOwningWP ();
6644 AllowUpdateInfoPropagationContext AUIPC (*
this);
6645 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6646 BreakInGroupedCommands ();
6647 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fInsertTableColBeforeCommandName,
false);
6650 GetCellSelection (
nullptr,
nullptr, &curCol,
nullptr);
6651 Assert (curCol <= GetColumnCount ());
6652 InsertColumn (curCol);
6654 context.CommandComplete ();
6655 BreakInGroupedCommands ();
6658void WordProcessorTable::OnUpdateInsertTableColAfterCommand (TextInteractor::CommandUpdater* enabler)
6660 Led_Require_CurrentOwningWP ();
6662 enabler->SetEnabled (
true);
6665void WordProcessorTable::OnInsertTableColAfterCommand ()
6667 Led_Require_CurrentOwningWP ();
6668 AllowUpdateInfoPropagationContext AUIPC (*
this);
6669 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6670 BreakInGroupedCommands ();
6671 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fInsertTableColAfterCommandName,
false);
6674 GetCellSelection (
nullptr,
nullptr,
nullptr, &curCol);
6675 Assert (curCol <= GetColumnCount ());
6676 InsertColumn (curCol);
6678 context.CommandComplete ();
6679 BreakInGroupedCommands ();
6682void WordProcessorTable::OnUpdateRemoveTableRowsCommand (TextInteractor::CommandUpdater* pCmdUI)
6684 Led_Require_CurrentOwningWP ();
6686 size_t rowSelStart = 0;
6687 size_t rowSelEnd = 0;
6688 size_t colSelStart = 0;
6689 size_t colSelEnd = 0;
6690 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6691 pCmdUI->SetEnabled (colSelStart == 0 and colSelEnd == GetColumnCount (rowSelStart, rowSelEnd));
6694void WordProcessorTable::OnRemoveTableRowsCommand ()
6696 Led_Require_CurrentOwningWP ();
6697 AllowUpdateInfoPropagationContext AUIPC (*
this);
6698 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6699 BreakInGroupedCommands ();
6700 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fRemoveTableRowsCommandName,
false);
6702 size_t rowSelStart = 0;
6703 size_t rowSelEnd = 0;
6704 size_t colSelStart = 0;
6705 size_t colSelEnd = 0;
6706 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6707 if (colSelStart == 0 and colSelEnd == GetColumnCount (rowSelStart, rowSelEnd)) {
6708 if (rowSelStart == 0 and rowSelEnd == GetRowCount ()) {
6709 fCurrentOwningWP->OnClearCommand ();
6712 size_t nRowsToDelete = rowSelEnd - rowSelStart;
6713 while (nRowsToDelete > 0) {
6714 DeleteRow (rowSelStart);
6719 fCurrentOwningWP->OnBadUserInput ();
6722 context.CommandComplete ();
6725void WordProcessorTable::OnUpdateRemoveTableColumnsCommand (TextInteractor::CommandUpdater* pCmdUI)
6727 Led_Require_CurrentOwningWP ();
6729 size_t rowSelStart = 0;
6730 size_t rowSelEnd = 0;
6731 size_t colSelStart = 0;
6732 size_t colSelEnd = 0;
6733 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6734 pCmdUI->SetEnabled (rowSelStart == 0 and rowSelEnd == GetRowCount ());
6737void WordProcessorTable::OnRemoveTableColumnsCommand ()
6739 Led_Require_CurrentOwningWP ();
6740 AllowUpdateInfoPropagationContext AUIPC (*
this);
6741 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6742 BreakInGroupedCommands ();
6743 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fRemoveTableColumnsCommandName,
false);
6745 size_t rowSelStart = 0;
6746 size_t rowSelEnd = 0;
6747 size_t colSelStart = 0;
6748 size_t colSelEnd = 0;
6749 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6750 if (rowSelStart == 0 and rowSelEnd == GetRowCount ()) {
6751 if (colSelStart == 0 and colSelEnd == GetColumnCount ()) {
6752 fCurrentOwningWP->OnClearCommand ();
6755 size_t nColsToDelete = colSelEnd - colSelStart;
6756 while (nColsToDelete > 0) {
6757 DeleteColumn (colSelStart);
6762 fCurrentOwningWP->OnBadUserInput ();
6765 context.CommandComplete ();
6766 BreakInGroupedCommands ();
6769void WordProcessorTable::OnUpdateSelectTablePartsCommand (TextInteractor::CommandUpdater* enabler)
6771 switch (enabler->GetCmdID ()) {
6772 case WordProcessor::kSelectTableIntraCellAll_CmdID: {
6773 enabler->SetEnabled (GetIntraCellMode ());
6775 case WordProcessor::kSelectTableCell_CmdID: {
6776 enabler->SetEnabled (GetIntraCellMode ());
6778 case WordProcessor::kSelectTableRow_CmdID: {
6779 size_t rowSelStart = 0;
6780 size_t rowSelEnd = 0;
6781 size_t colSelStart = 0;
6782 size_t colSelEnd = 0;
6783 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6784 size_t maxColSelEnd = GetColumnCount (rowSelStart, rowSelEnd);
6785 enabler->SetEnabled (colSelStart != 0 or colSelEnd != maxColSelEnd);
6787 case WordProcessor::kSelectTableColumn_CmdID: {
6788 size_t rowSelStart = 0;
6789 size_t rowSelEnd = 0;
6790 size_t colSelStart = 0;
6791 size_t colSelEnd = 0;
6792 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6793 enabler->SetEnabled (rowSelStart != 0 or rowSelEnd != GetRowCount ());
6795 case WordProcessor::kSelectTable_CmdID: {
6796 size_t rowSelStart = 0;
6797 size_t rowSelEnd = 0;
6798 size_t colSelStart = 0;
6799 size_t colSelEnd = 0;
6800 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6801 enabler->SetEnabled (rowSelStart != 0 or colSelStart != 0 or rowSelEnd != GetRowCount () or colSelEnd != GetColumnCount ());
6806void WordProcessorTable::OnPerformTablePartsCommand (TextInteractor::CommandNumber commandNumber)
6808 switch (commandNumber) {
6809 case WordProcessor::kSelectTableIntraCellAll_CmdID: {
6812 if (GetIntraCellMode (&row, &col)) {
6813 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6814 wp->OnPerformCommand (TextInteractor::kSelectAll_CmdID);
6820 case WordProcessor::kSelectTableCell_CmdID: {
6821 UnSetIntraCellMode ();
6823 case WordProcessor::kSelectTableRow_CmdID: {
6824 size_t rowSelStart = 0;
6825 size_t rowSelEnd = 0;
6826 size_t colSelStart = 0;
6827 size_t colSelEnd = 0;
6828 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6830 colSelEnd = GetColumnCount (rowSelStart, rowSelEnd);
6831 SetCellSelection (rowSelStart, rowSelEnd, colSelStart, colSelEnd);
6833 case WordProcessor::kSelectTableColumn_CmdID: {
6834 size_t rowSelStart = 0;
6835 size_t rowSelEnd = 0;
6836 size_t colSelStart = 0;
6837 size_t colSelEnd = 0;
6838 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6840 rowSelEnd = GetRowCount ();
6841 SetCellSelection (rowSelStart, rowSelEnd, colSelStart, colSelEnd);
6843 case WordProcessor::kSelectTable_CmdID: {
6844 SetCellSelection (0, GetRowCount (), 0, GetColumnCount ());
6849void WordProcessorTable::AssureCurSelFontCacheValid (IncrementalFontSpecification* curSelFontSpec)
6855 if (GetIntraCellMode (&row, &col)) {
6856 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6857 *curSelFontSpec = wp->GetCurSelFontSpec ();
6862 size_t rowSelStart = 0;
6863 size_t rowSelEnd = 0;
6864 size_t colSelStart = 0;
6865 size_t colSelEnd = 0;
6866 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6867 for (
size_t ri = rowSelStart; ri < rowSelEnd; ++ri) {
6868 size_t thisRowEnd = min (colSelEnd, GetColumnCount (ri));
6869 for (
size_t ci = colSelStart; ci < thisRowEnd; ++ci) {
6870 TemporarilyAllocateCellWithTablet wp (*
this, ri, ci);
6871 wp->SetSelection (0, wp->GetEnd (), TextInteractor::eNoUpdate);
6872 IncrementalFontSpecification iSpec = wp->GetCurSelFontSpec ();
6873 if (ri == rowSelStart and ci == colSelStart) {
6874 *curSelFontSpec = iSpec;
6877 *curSelFontSpec =
Intersection (*curSelFontSpec, iSpec);
6887void WordProcessorTable::InteractiveSetFont (
const IncrementalFontSpecification& defaultFont)
6889 Led_Require_CurrentOwningWP ();
6895 if (GetIntraCellMode (&row, &col)) {
6896 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6897 wp->InteractiveSetFont (defaultFont);
6902 AllowUpdateInfoPropagationContext AUIPC (*
this);
6904 fCurrentOwningWP->BreakInGroupedCommands ();
6905 UndoableContextHelper undoContext (*fCurrentOwningWP, StandardStyledTextInteractor::GetCommandNames ().fFontChangeCommandName,
false);
6907 size_t rowSelStart = 0;
6908 size_t rowSelEnd = 0;
6909 size_t colSelStart = 0;
6910 size_t colSelEnd = 0;
6911 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6912 for (
size_t ri = rowSelStart; ri < rowSelEnd; ++ri) {
6913 size_t thisRowEnd = min (colSelEnd, GetColumnCount (ri));
6914 for (
size_t ci = colSelStart; ci < thisRowEnd; ++ci) {
6915 TemporarilyAllocateCellWithTablet wp (*
this, ri, ci);
6916 wp->SetStyleInfo (0, wp->GetEnd (), defaultFont);
6920 undoContext.CommandComplete ();
6923void WordProcessorTable::Write ([[maybe_unused]] SinkStream& sink)
6928void WordProcessorTable::ExternalizeFlavors ([[maybe_unused]]
WriterFlavorPackage& flavorPackage)
6936const char* WordProcessorTable::GetTag ()
const
6947bool WordProcessorTable::ProcessSimpleClick (Led_Point clickedAt,
unsigned clickCount,
bool extendSelection)
6950 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",
6951 this, clickedAt.v, clickedAt.h, clickCount, fRowSelStart, fRowSelEnd, fColSelStart, fColSelEnd, fIntraCellMode, fIntraSelStart, fIntraSelStart
6954 Led_Require_CurrentOwningWP ();
6956 size_t clickRow = 0;
6957 size_t clickCol = 0;
6958 GetClosestCell (clickedAt, &clickRow, &clickCol);
6960 fTrackingAnchor_Row = clickRow;
6961 fTrackingAnchor_Col = clickCol;
6963 bool forceSelectAllCells =
false;
6964 if (extendSelection) {
6965 size_t selStart = fCurrentOwningWP->GetSelectionStart ();
6966 size_t selEnd = fCurrentOwningWP->GetSelectionEnd ();
6967 selStart = min (selStart, GetStart ());
6968 selEnd = max (selEnd, GetEnd ());
6969 forceSelectAllCells = (selEnd - selStart != 1);
6970 fCurrentOwningWP->SetSelection (selStart, selEnd);
6973 fCurrentOwningWP->SetSelection (GetStart (), GetEnd ());
6976 if (forceSelectAllCells) {
6977 SetCellSelection (0, GetRowCount (), 0, GetColumnCount ());
6979 else if (extendSelection) {
6980 size_t rowSelStart = 0;
6981 size_t rowSelEnd = 0;
6982 size_t colSelStart = 0;
6983 size_t colSelEnd = 0;
6984 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6985 rowSelStart = min (rowSelStart, clickRow);
6986 rowSelEnd = max (rowSelEnd, clickRow + 1);
6987 colSelStart = min (colSelStart, clickCol);
6988 colSelEnd = max (colSelEnd, clickCol + 1);
6989 SetCellSelection (rowSelStart, rowSelEnd, colSelStart, colSelEnd);
6992 SetCellSelection (clickRow, clickRow + 1, clickCol, clickCol + 1);
6996 size_t rowSelStart = 0;
6997 size_t rowSelEnd = 0;
6998 size_t colSelStart = 0;
6999 size_t colSelEnd = 0;
7000 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
7001 if (rowSelEnd - rowSelStart == 1 and colSelEnd - colSelStart == 1) {
7002 Led_Rect cellBounds = GetCellBounds (rowSelStart, colSelStart);
7003 Led_Rect cellEditorBounds = GetCellEditorBounds (rowSelStart, colSelStart);
7007 if (cellEditorBounds.Contains (clickedAt)) {
7008 SetIntraCellMode ();
7011 TemporarilyAllocateCellWithTablet wp (*
this, rowSelStart, colSelStart);
7012 wp->SetCurClickCount (fCurrentOwningWP->GetCurClickCount (), Time::GetTickCount ());
7013 Assert (fCurrentOwningWP->GetCurClickCount () == clickCount);
7014 wp->ProcessSimpleClick (TableCoordinates2Window (clickedAt), clickCount, extendSelection, &fIntraCellDragAnchor);
7017 UnSetIntraCellMode ();
7022 DbgTrace (
"EXITING WordProcessorTable::ProcessSimpleClick (this= 0x%x, rowSelStart=%d, rowSelEnd=%d, colSelStart=%d, colSelEnd=%d, intraCellMode=%d intraCellStart=%d, intraCellEnd=%d)\n",
7023 this, fRowSelStart, fRowSelEnd, fColSelStart, fColSelEnd, fIntraCellMode, fIntraSelStart, fIntraSelStart
7029void WordProcessorTable::WhileSimpleMouseTracking (Led_Point newMousePos)
7032 DbgTrace (
"ENTERING WordProcessorTable::WhileSimpleMouseTracking (this= 0x%x, rowSelStart=%d, rowSelEnd=%d, colSelStart=%d, colSelEnd=%d, intraCellMode=%d intraCellStart=%d, intraCellEnd=%d)\n",
7033 this, fRowSelStart, fRowSelEnd, fColSelStart, fColSelEnd, fIntraCellMode, fIntraSelStart, fIntraSelStart
7036 Led_Require_CurrentOwningWP ();
7038 if (fCurrentOwningWP->GetSelectionEnd () - fCurrentOwningWP->GetSelectionStart () == 1) {
7042 size_t clickRow = 0;
7043 size_t clickCol = 0;
7044 GetClosestCell (newMousePos, &clickRow, &clickCol);
7046 size_t rowSelStart = min (fTrackingAnchor_Row, clickRow);
7047 size_t rowSelEnd = max (fTrackingAnchor_Row + 1, clickRow + 1);
7048 size_t colSelStart = min (fTrackingAnchor_Col, clickCol);
7049 size_t colSelEnd = max (fTrackingAnchor_Col + 1, clickCol + 1);
7050 SetCellSelection (rowSelStart, rowSelEnd, colSelStart, colSelEnd);
7052 else if (fCurrentOwningWP->GetSelectionEnd () - fCurrentOwningWP->GetSelectionStart () > 1) {
7053 SetCellSelection (0, GetRowCount (), 0, GetColumnCount ());
7057 size_t rowSelStart = 0;
7058 size_t rowSelEnd = 0;
7059 size_t colSelStart = 0;
7060 size_t colSelEnd = 0;
7061 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
7062 if (rowSelEnd - rowSelStart == 1 and colSelEnd - colSelStart == 1) {
7063 Led_Rect cellBounds = GetCellBounds (rowSelStart, colSelStart);
7064 Led_Rect cellEditorBounds = GetCellEditorBounds (rowSelStart, colSelStart);
7068 if (cellEditorBounds.Contains (newMousePos)) {
7069 if (fTrackingAnchor_Row == rowSelStart and rowSelStart + 1 == rowSelEnd and fTrackingAnchor_Col == colSelStart and
7070 colSelStart + 1 == colSelEnd) {
7074 SetIntraCellMode ();
7077 TemporarilyAllocateCellWithTablet wp (*
this, rowSelStart, colSelStart);
7078 wp->SetCurClickCount (fCurrentOwningWP->GetCurClickCount (), Time::GetTickCount ());
7079 wp->WhileSimpleMouseTracking (TableCoordinates2Window (newMousePos), fIntraCellDragAnchor);
7084 DbgTrace (
"EXITING WordProcessorTable::WhileSimpleMouseTracking (this= 0x%x, rowSelStart=%d, rowSelEnd=%d, colSelStart=%d, colSelEnd=%d, intraCellMode=%d intraCellStart=%d, intraCellEnd=%d)\n",
7085 this, fRowSelStart, fRowSelEnd, fColSelStart, fColSelEnd, fIntraCellMode, fIntraSelStart, fIntraSelStart
7095void WordProcessorTable::GetRealCell (
size_t* row,
size_t* column)
const
7102 CellMergeFlags flags = GetCell (r, c).GetCellMergeFlags ();
7103 if (flags == ePlainCell) {
7109#if qStroika_Foundation_Debug_AssertionsChecked
7110 bool changed =
false;
7112 if (flags & eMergeCellLeft) {
7115#if qStroika_Foundation_Debug_AssertionsChecked
7119 if (flags & eMergeCellUp) {
7122#if qStroika_Foundation_Debug_AssertionsChecked
7126#if qStroika_Foundation_Debug_AssertionsChecked
7133const WordProcessorTable::Cell& WordProcessorTable::GetRealCell (
size_t row,
size_t column)
const
7135 GetRealCell (&row, &column);
7136 return GetCell (row, column);
7139bool WordProcessorTable::CanMergeCells (
size_t fromRow,
size_t fromCol, [[maybe_unused]]
size_t toRow, [[maybe_unused]]
size_t toCol)
7141 Require (fromRow <= toRow);
7142 Require (fromCol <= toCol);
7143 Require (toRow <= GetRowCount ());
7144 Require (toCol <= GetColumnCount ());
7147 return GetCellFlags (fromRow, fromCol) == ePlainCell;
7164void WordProcessorTable::MergeCells (
size_t fromRow,
size_t fromCol,
size_t toRow,
size_t toCol)
7166 Require (fromRow <= toRow);
7167 Require (fromCol <= toCol);
7168 Require (toRow <= GetRowCount ());
7169 Require (toCol <= GetColumnCount ());
7170 Require (CanMergeCells (fromRow, fromCol, toRow, toCol));
7171 bool madeChange =
false;
7172 for (
size_t r = fromRow; r < toRow; ++r) {
7173 for (
size_t c = fromCol; c < toCol; ++c) {
7175 if (not(r == fromRow and c == fromCol)) {
7176 fRows[r].fCells[c] =
7177 Cell (*
this,
static_cast<CellMergeFlags
> (((r > fromRow) ? eMergeCellUp : 0) | ((c > fromCol) ? eMergeCellLeft : 0)));
7183 InvalidateLayout ();
7187void WordProcessorTable::UnMergeCells (
size_t fromRow,
size_t fromCol,
size_t toRow,
size_t toCol)
7189 Require (fromRow <= toRow);
7190 Require (fromCol <= toCol);
7191 Require (toRow < GetRowCount ());
7192 Require (toCol < GetColumnCount ());
7193 bool madeChange =
false;
7194 for (
size_t r = fromRow; r < toRow; ++r) {
7195 for (
size_t c = fromCol; c < toCol; ++c) {
7197 if (GetCellFlags (r, c) != ePlainCell) {
7198 fRows[r].fCells[c] = Cell (*
this, ePlainCell);
7204 InvalidateLayout ();
7212void WordProcessorTable::SetCellSelection (
size_t rowSelStart,
size_t rowSelEnd,
size_t colSelStart,
size_t colSelEnd)
7214 Ensure (rowSelStart <= rowSelEnd);
7215 Ensure (rowSelEnd <= GetRowCount ());
7216 Ensure (colSelStart <= colSelEnd);
7217 Ensure (colSelEnd <= GetColumnCount ());
7218 bool changed = (fRowSelStart != rowSelStart) or (fRowSelEnd != rowSelEnd) or (fColSelStart != colSelStart) or (fColSelEnd != colSelEnd);
7220 fRowSelStart = rowSelStart;
7221 fRowSelEnd = rowSelEnd;
7222 fColSelStart = colSelStart;
7223 fColSelEnd = colSelEnd;
7224 fIntraCellMode =
false;
7225 InvalidateIntraCellContextInfo ();
7226 if (fCurrentOwningWP !=
nullptr) {
7227 fCurrentOwningWP->fCachedCurSelFontSpecValid =
false;
7228 fCurrentOwningWP->Refresh (GetStart (), GetEnd ());
7232 DbgTrace (
"WordProcessorTable::SetCellSelection (table=0x%x, tickCount=%f, rs=%d, re=%d, cs=%d, ce=%d, changed=%d)\n",
7233 this, Time::GetTickCount (), rowSelStart, rowSelEnd, colSelStart, colSelEnd, changed
7238void WordProcessorTable::SetIntraCellMode ()
7240 Require (fRowSelEnd - fRowSelStart == 1);
7241 Require (fColSelEnd - fColSelStart == 1);
7242 if (not fIntraCellMode) {
7243 TextStore* ts =
nullptr;
7244 GetCellWordProcessorDatabases (fRowSelStart, fColSelStart, &ts);
7246 SetIntraCellSelection (0, ts->GetLength ());
7247 fIntraCellMode =
true;
7248 if (fCurrentOwningWP !=
nullptr) {
7249 fCurrentOwningWP->Refresh (GetStart (), GetEnd ());
7254void WordProcessorTable::SetIntraCellMode (
size_t row,
size_t col)
7256 if (not fIntraCellMode) {
7257 SetCellSelection (row, row + 1, col, col + 1);
7258 SetIntraCellMode ();
7262void WordProcessorTable::UnSetIntraCellMode ()
7264 if (fIntraCellMode) {
7265 fIntraCellMode =
false;
7266 if (fCurrentOwningWP !=
nullptr) {
7267 fCurrentOwningWP->Refresh (GetStart (), GetEnd ());
7272void WordProcessorTable::SetIntraCellSelection (
size_t selStart,
size_t selEnd)
7274 if (fIntraSelStart != selStart or fIntraSelEnd != selEnd) {
7276 DbgTrace (
"WordProcessorTable::SetIntraCellSelection (selStart = %d, selEnd = %d)- oldSel=(%d,%d), tickcount=%f\n", selStart, selEnd, fIntraSelStart, fIntraSelEnd, Time::GetTickCount ());
7278 if (fCurrentOwningWP !=
nullptr) {
7279 fCurrentOwningWP->fCachedCurSelFontSpecValid =
false;
7281 fIntraSelStart = selStart;
7282 fIntraSelEnd = selEnd;
7294WordProcessorTable::EmbeddedTableWordProcessor* WordProcessorTable::ConstructEmbeddedTableWordProcessor (WordProcessor& forWordProcessor,
7295 size_t forRow,
size_t forColumn,
7296 const Led_Rect& cellWindowRect,
7297 bool captureChangesForUndo)
7299 size_t cellModeRow = 0;
7300 size_t cellModeCol = 0;
7301 bool activeFocusedCell = GetIntraCellMode (&cellModeRow, &cellModeCol) and cellModeRow == forRow and cellModeCol == forColumn;
7302 EmbeddedTableWordProcessor* e =
new EmbeddedTableWordProcessor (forWordProcessor, *
this, forRow, forColumn, activeFocusedCell);
7304 TextStore* ts =
nullptr;
7305 shared_ptr<AbstractStyleDatabaseRep> styleDatabase;
7306 shared_ptr<AbstractParagraphDatabaseRep> paragraphDatabase;
7307 shared_ptr<HidableTextMarkerOwner> hidableTextDatabase;
7308 GetCellWordProcessorDatabases (forRow, forColumn, &ts, &styleDatabase, ¶graphDatabase, &hidableTextDatabase);
7309 e->SetStyleDatabase (styleDatabase);
7310 e->SetParagraphDatabase (paragraphDatabase);
7311 e->SetHidableTextDatabase (hidableTextDatabase);
7312 e->SpecifyTextStore (ts);
7313 e->SetWindowRect (cellWindowRect);
7314 e->SetDefaultTextColor (WordProcessor::eDefaultBackgroundColor, GetCellColor (forRow, forColumn));
7315 if (captureChangesForUndo) {
7316 e->SetCommandHandler (forWordProcessor.GetCommandHandler ());
7319 if (activeFocusedCell) {
7320 using TemporarilyUseTablet = EmbeddedTableWordProcessor::TemporarilyUseTablet;
7323 WordProcessor::Tablet_Acquirer tablet (fCurrentOwningWP);
7324 TemporarilyUseTablet tmpUseTablet (*e, tablet, TemporarilyUseTablet::eDontDoTextMetricsChangedCall);
7326 e->SetSelectionShown (
true, TextInteractor::eNoUpdate);
7327 e->RestoreMiscActiveFocusInfo ();
7331 e->SpecifyTextStore (
nullptr);
7345void WordProcessorTable::ReleaseEmbeddedTableWordProcessor (EmbeddedTableWordProcessor* e)
7348 e->SaveMiscActiveFocusInfo ();
7349 e->SetCommandHandler (
nullptr);
7350 e->SpecifyTextStore (
nullptr);
7359void WordProcessorTable::PerformLayout ()
7361 Require (fNeedLayout != eDone);
7363 if (fCurrentOwningWP !=
nullptr) {
7364 TextStore& ts = GetOwner ()->GetTextStore ();
7365 TextStore::SimpleUpdater updater (ts, GetStart (), GetEnd (),
false);
7367 Led_Size border = Led_Size (Led_CvtScreenPixelsFromTWIPSV (fBorderWidth), Led_CvtScreenPixelsFromTWIPSH (fBorderWidth));
7368 DistanceType spacing = Led_CvtScreenPixelsFromTWIPSV (GetCellSpacing ());
7369 Led_Rect defaultCellMargin;
7371 TWIPS_Rect defaultCellMarginTWIPS;
7372 GetDefaultCellMargins (&defaultCellMarginTWIPS.top, &defaultCellMarginTWIPS.left, &defaultCellMarginTWIPS.bottom,
7373 &defaultCellMarginTWIPS.right);
7374 defaultCellMargin.top = Led_CvtScreenPixelsFromTWIPSV (defaultCellMarginTWIPS.top);
7375 defaultCellMargin.left = Led_CvtScreenPixelsFromTWIPSH (defaultCellMarginTWIPS.left);
7376 defaultCellMargin.bottom = Led_CvtScreenPixelsFromTWIPSV (defaultCellMarginTWIPS.bottom);
7377 defaultCellMargin.right = Led_CvtScreenPixelsFromTWIPSH (defaultCellMarginTWIPS.right);
7383 size_t rows = GetRowCount ();
7385 Tablet_Acquirer tablet (fCurrentOwningWP);
7387 DistanceType maxTableWidth = 0;
7389 DistanceType runningHeight = 0;
7390 for (
size_t r = 0; r < rows; ++r) {
7394 size_t cols = GetColumnCount (r);
7396 DistanceType rowWidth = 0;
7398 size_t lastRealCellIdx = 0;
7399 for (
size_t c = 0; c < cols; ++c) {
7400 DistanceType thisColWidth = Led_CvtScreenPixelsFromTWIPSH (GetColumnWidth (r, c));
7401 if (GetCellFlags (r, c) == ePlainCell) {
7402 realCellWidths[c] = thisColWidth;
7403 lastRealCellIdx = c;
7404 rowWidth += thisColWidth;
7408 realCellWidths[lastRealCellIdx] += thisColWidth;
7416 DistanceType rowHeight = 0;
7417 for (
size_t c = 0; c < cols; ++c) {
7418 if (GetCellFlags (r, c) == ePlainCell) {
7419 using TemporarilyUseTablet = EmbeddedTableWordProcessor::TemporarilyUseTablet;
7421 DistanceType totalCellMargin = defaultCellMargin.left + defaultCellMargin.right;
7422 DistanceType wpWidth = (totalCellMargin < realCellWidths[c]) ? realCellWidths[c] - totalCellMargin : 1;
7423 TemporarilyAllocateCellWP wp (*
this, *fCurrentOwningWP, r, c, Led_Rect (0, 0, 1000, wpWidth));
7424 TemporarilyUseTablet tmpUseTablet (*wp, tablet, TemporarilyUseTablet::eDontDoTextMetricsChangedCall);
7425 rowHeight = max (rowHeight, wp->GetDesiredHeight ());
7432 rowHeight += defaultCellMargin.top + defaultCellMargin.bottom;
7433 rowHeight = max (rowHeight, DistanceType (5));
7434 fRows[r].fHeight = rowHeight;
7435 runningHeight += rowHeight;
7437 DistanceType rowWidthWithSpacingNBorders = rowWidth +
static_cast<DistanceType
> ((cols + 1) * (spacing + border.h));
7438 maxTableWidth = max (maxTableWidth, rowWidthWithSpacingNBorders);
7444 DistanceType runningWidth = 0;
7445 size_t lastRealCellIdx = 0;
7446 for (
size_t c = 0; c < cols; ++c) {
7447 if (GetCellFlags (r, c) == ePlainCell) {
7448 Cell cell = GetCell (r, c);
7449 Led_Rect cellRect = Led_Rect (runningHeight - rowHeight, runningWidth, rowHeight, realCellWidths[c]);
7452 Led_Point (
static_cast<CoordinateType
> ((r + 1) * border.v),
static_cast<CoordinateType
> ((c + 1) * border.h));
7455 cellRect += Led_Point (
static_cast<CoordinateType
> ((r + 1) * spacing),
static_cast<CoordinateType
> ((c + 1) * spacing));
7457 cell.SetCachedBoundsRect (cellRect);
7458 lastRealCellIdx = c;
7459 runningWidth += realCellWidths[c];
7466 DistanceType totalHeight = 0;
7467 for (
auto i = fRows.begin (); i != fRows.end (); ++i) {
7468 totalHeight += (*i).fHeight;
7470 fTotalHeight = totalHeight +
static_cast<DistanceType
> ((spacing + border.v) * (fRows.size () + 1));
7473 fTotalWidth = maxTableWidth;
7475 fNeedLayout = eDone;
7486void WordProcessorTable::GetDimensions (
size_t* rows,
size_t* columns)
const
7488 if (rows !=
nullptr) {
7489 *rows = fRows.size ();
7491 if (columns !=
nullptr) {
7493 for (
size_t ri = 0; ri < fRows.size (); ++ri) {
7494 maxCols = max (maxCols, fRows[ri].fCells.size ());
7507void WordProcessorTable::SetDimensions (
size_t rows,
size_t columns)
7510 size_t oldColumns = 0;
7511 GetDimensions (&oldRows, &oldColumns);
7514 while (oldRows > rows) {
7515 DeleteRow (oldRows - 1);
7518 while (oldColumns > columns) {
7519 DeleteColumn (oldColumns - 1);
7524 while (oldRows < rows) {
7525 InsertRow (oldRows);
7528 while (oldColumns < columns) {
7529 InsertColumn (oldColumns);
7533 GetDimensions (&oldRows, &oldColumns);
7534 Assert (oldRows == rows);
7535 Assert (oldColumns == columns);
7545void WordProcessorTable::SetDimensionsAtLeast (
size_t rows,
size_t columns)
7549 GetDimensions (&r, &c);
7551 c = max (columns, c);
7552 SetDimensions (r, c);
7562void WordProcessorTable::InsertRow (
size_t at,
size_t maxRowCopyCount)
7564 Require (at <= GetRowCount ());
7565 Require (maxRowCopyCount >= 1);
7566#if qStroika_Frameworks_Led_SupportGDI
7568 TextStore& ts = GetOwner ()->GetTextStore ();
7569 TextStore::SimpleUpdater updater (ts, GetStart (), GetEnd ());
7575 size_t rowToCopy = at > 0 ? at - 1 : at;
7576 size_t colCount = 0;
7577 if (rowToCopy < GetRowCount ()) {
7578 colCount = GetColumnCount (rowToCopy);
7580 colCount = min (colCount, maxRowCopyCount);
7582 for (
size_t c = 0; c < colCount; ++c) {
7583 Cell cell (*
this, ePlainCell);
7584 cell.SetCellXWidth (GetColumnWidth (rowToCopy, c));
7585 newRow.fCells.push_back (cell);
7588 fRows.insert (fRows.begin () + at, newRow);
7589#if qStroika_Frameworks_Led_SupportGDI
7591 InvalidateIntraCellContextInfo ();
7592 InvalidateLayout ();
7600void WordProcessorTable::DeleteRow (
size_t at)
7602 Require (at < GetRowCount ());
7603#if qStroika_Frameworks_Led_SupportGDI
7605 TextStore& ts = GetOwner ()->GetTextStore ();
7606 TextStore::SimpleUpdater updater (ts, GetStart (), GetEnd ());
7609 fRows.erase (fRows.begin () + at);
7610#if qStroika_Frameworks_Led_SupportGDI
7611 InvalidateIntraCellContextInfo ();
7612 InvalidateLayout ();
7613 ReValidateSelection ();
7622void WordProcessorTable::InsertColumn (
size_t at)
7624 Require (at <= GetColumnCount ());
7625#if qStroika_Frameworks_Led_SupportGDI
7626 TextStore& ts = GetOwner ()->GetTextStore ();
7627 TextStore::SimpleUpdater updater (ts, GetStart (), GetEnd ());
7628 TWIPS newColWidth = Led_CvtScreenPixelsToTWIPSH (100);
7630 TWIPS newColWidth = TWIPS (100);
7634 if (fRows.size () > 0) {
7635 size_t nColsInRow = GetColumnCount (0);
7637 if (at == nColsInRow and at > 0) {
7638 newColWidth = GetColumnWidth (0, at - 1);
7640 else if (at < nColsInRow) {
7641 newColWidth = GetColumnWidth (0, at);
7645 vector<Cell> newCol;
7646 for (
size_t r = 0; r < fRows.size (); ++r) {
7647 Cell cell (*
this, ePlainCell);
7648 cell.SetCellXWidth (newColWidth);
7649 newCol.push_back (cell);
7652 size_t rowCount = fRows.size ();
7653 for (
size_t ri = 0; ri < rowCount; ++ri) {
7654 vector<Cell>& rowCells = fRows[ri].fCells;
7655 rowCells.insert (rowCells.begin () + at, newCol[ri]);
7657#if qStroika_Frameworks_Led_SupportGDI
7659 InvalidateIntraCellContextInfo ();
7660 InvalidateLayout ();
7668void WordProcessorTable::DeleteColumn (
size_t at)
7670 Require (at < GetColumnCount ());
7673#if qStroika_Frameworks_Led_SupportGDI
7674 TextStore& ts = GetOwner ()->GetTextStore ();
7675 TextStore::SimpleUpdater updater (ts, GetStart (), GetEnd ());
7678 size_t rowCount = fRows.size ();
7679 for (
size_t ri = 0; ri < rowCount; ++ri) {
7680 vector<Cell>& rowCells = fRows[ri].fCells;
7681 if (at < rowCells.size ()) {
7682 rowCells.erase (rowCells.begin () + at);
7685#if qStroika_Frameworks_Led_SupportGDI
7686 InvalidateIntraCellContextInfo ();
7687 InvalidateLayout ();
7688 ReValidateSelection ();
7691#if qStroika_Frameworks_Led_SupportGDI
7699void WordProcessorTable::ReValidateSelection ()
7701 size_t rowCount = GetRowCount ();
7703 size_t rowSelStart = fRowSelStart;
7704 size_t rowSelEnd = fRowSelEnd;
7705 size_t colSelStart = fColSelStart;
7706 size_t colSelEnd = fColSelEnd;
7708 if (rowSelStart >= rowCount) {
7712 if (rowSelEnd > rowCount) {
7713 rowSelEnd = rowCount;
7715 size_t colCount = GetColumnCount (rowSelStart, rowSelEnd);
7716 if (colSelStart >= colCount) {
7720 if (colSelEnd >= colCount) {
7721 colSelEnd = colCount;
7723 SetCellSelection (rowSelStart, rowSelEnd, colSelStart, colSelEnd);
7736WordProcessorTable::EmbeddedTableWordProcessor::EmbeddedTableWordProcessor (WordProcessor& owningWordProcessor, WordProcessorTable& owningTable,
7737 size_t tRow,
size_t tCol,
bool activeEditCell)
7739 , fOwningWordProcessor (owningWordProcessor)
7740 , fOwningTable (owningTable)
7742 , fTableColumn (tCol)
7743 , fUpdateTablet (nullptr)
7744 , fDesiredHeight (0)
7745 , fDesiredHeightValid (false)
7746 , fActiveEditCell (activeEditCell)
7747 , fSuppressRefreshCalls (false)
7749 SetImageUsingOffscreenBitmaps (
false);
7752WordProcessorTable& WordProcessorTable::EmbeddedTableWordProcessor::GetOwningTable ()
const
7754 return fOwningTable;
7757WordProcessor& WordProcessorTable::EmbeddedTableWordProcessor::GetOwningWordProcessor ()
const
7759 return fOwningWordProcessor;
7762void WordProcessorTable::EmbeddedTableWordProcessor::SaveMiscActiveFocusInfo ()
7764 if (fActiveEditCell) {
7765 fOwningTable.SetIntraCellSelection (GetSelectionStart (), GetSelectionEnd ());
7766 fOwningTable.SaveIntraCellContextInfo (fLeftSideOfSelectionInteresting, GetEmptySelectionStyle ());
7770void WordProcessorTable::EmbeddedTableWordProcessor::RestoreMiscActiveFocusInfo ()
7772 if (fActiveEditCell) {
7773 DisableRefreshContext DFR (*
this);
7774 SuppressCellUpdatePropagationContext SCUP (fOwningTable);
7777 bool leftSideOfSelectionInteresting =
false;
7778 if (fOwningTable.RestoreIntraCellContextInfo (&leftSideOfSelectionInteresting, &emptySelFont)) {
7779 size_t intraCellSelStart = 0;
7780 size_t intraCellSelEnd = 0;
7781 fOwningTable.GetIntraCellSelection (&intraCellSelStart, &intraCellSelEnd);
7782 SetSelection (intraCellSelStart, intraCellSelEnd, TextInteractor::eNoUpdate);
7783 fLeftSideOfSelectionInteresting = leftSideOfSelectionInteresting;
7784 SetEmptySelectionStyle (emptySelFont);
7787 SetEmptySelectionStyle ();
7792#if !qStroika_Frameworks_Led_NestedTablesSupported
7793void WordProcessorTable::EmbeddedTableWordProcessor::HookInternalizerChanged ()
7795 inherited::HookInternalizerChanged ();
7796 WordProcessorFlavorPackageInternalizer* internalizerRep =
7797 dynamic_cast<WordProcessorFlavorPackageInternalizer*
> (
static_cast<FlavorPackageInternalizer*
> (GetInternalizer ().get ()));
7799 internalizerRep->SetNoTablesAllowed (
true);
7803bool WordProcessorTable::EmbeddedTableWordProcessor::OnCopyCommand_Before ()
7805 return fOwningWordProcessor.OnCopyCommand_Before ();
7808void WordProcessorTable::EmbeddedTableWordProcessor::OnCopyCommand_After ()
7810 fOwningWordProcessor.OnCopyCommand_After ();
7813bool WordProcessorTable::EmbeddedTableWordProcessor::OnPasteCommand_Before ()
7815 return fOwningWordProcessor.OnPasteCommand_Before ();
7818void WordProcessorTable::EmbeddedTableWordProcessor::OnPasteCommand_After ()
7820 fOwningWordProcessor.OnPasteCommand_After ();
7823void WordProcessorTable::EmbeddedTableWordProcessor::DrawRowHilight (Tablet* ,
const Led_Rect& ,
const Led_Rect& ,
7824 const TextLayoutBlock& ,
size_t ,
size_t
7830Tablet* WordProcessorTable::EmbeddedTableWordProcessor::AcquireTablet ()
const
7832 if (fUpdateTablet !=
nullptr) {
7833 return fUpdateTablet;
7837 return fOwningWordProcessor.AcquireTablet ();
7840void WordProcessorTable::EmbeddedTableWordProcessor::ReleaseTablet (Tablet* tablet)
const
7842 if (tablet == fUpdateTablet) {
7847 fOwningWordProcessor.ReleaseTablet (tablet);
7850void WordProcessorTable::EmbeddedTableWordProcessor::RefreshWindowRect_ (
const Led_Rect& windowRectArea, UpdateMode updateMode)
const
7852 if (not fSuppressRefreshCalls) {
7856 UpdateMode useUpdateMode = (updateMode == eImmediateUpdate) ? eDelayedUpdate : updateMode;
7857 fOwningWordProcessor.RefreshWindowRect_ (windowRectArea, useUpdateMode);
7861void WordProcessorTable::EmbeddedTableWordProcessor::UpdateWindowRect_ (
const Led_Rect& )
const
7863 throw CannotUpdateNow ();
7866bool WordProcessorTable::EmbeddedTableWordProcessor::QueryInputKeyStrokesPending ()
const
7873void WordProcessorTable::EmbeddedTableWordProcessor::SetDefaultUpdateMode (UpdateMode defaultUpdateMode)
7875 if (defaultUpdateMode == eImmediateUpdate) {
7876 defaultUpdateMode = eDelayedUpdate;
7878 inherited::SetDefaultUpdateMode (defaultUpdateMode);
7881void WordProcessorTable::EmbeddedTableWordProcessor::GetLayoutMargins (RowReference row, CoordinateType* lhs, CoordinateType* rhs)
const
7883 if (rhs !=
nullptr) {
7884 inherited::GetLayoutMargins (row, lhs,
nullptr);
7893 if (rhs !=
nullptr) {
7894 *rhs = (max (CoordinateType (GetWindowRect ().GetWidth ()), CoordinateType (1)));
7898void WordProcessorTable::EmbeddedTableWordProcessor::PostInteractiveUndoPostHelper (InteractiveReplaceCommand::SavedTextRep** beforeRep,
7899 InteractiveReplaceCommand::SavedTextRep** afterRep,
7900 size_t startOfInsert,
const SDKString& cmdName)
7904 CommandHandler* ch = GetCommandHandler ();
7907 if (*beforeRep !=
nullptr and *afterRep !=
nullptr) {
7910 InteractiveReplaceCommand* cmd =
7911 new TableCMD (fOwningTable.GetStart (), fTableRow, fTableColumn, *beforeRep, *afterRep, startOfInsert, cmdName);
7912 *beforeRep =
nullptr;
7913 *afterRep =
nullptr;
7919 *beforeRep =
nullptr;
7921 *afterRep =
nullptr;
7926InteractiveReplaceCommand::SavedTextRep*
7927WordProcessorTable::EmbeddedTableWordProcessor::InteractiveUndoHelperMakeTextRep (
size_t regionStart,
size_t regionEnd,
size_t selStart,
size_t selEnd)
7929 InteractiveReplaceCommand::SavedTextRep* tableStateRep = inherited::InteractiveUndoHelperMakeTextRep (regionStart, regionEnd, selStart, selEnd);
7930 return new SavedTextRepWSel (tableStateRep, fOwningTable, SavedTextRepWSel::eWPDirect);
7933DistanceType WordProcessorTable::EmbeddedTableWordProcessor::GetDesiredHeight ()
const
7935 if (not fDesiredHeightValid) {
7936 RowReference startingRow = GetRowReferenceContainingPosition (0);
7937 RowReference endingRow = GetRowReferenceContainingPosition (GetEnd ());
7942 fDesiredHeightValid =
true;
7943 fDesiredHeight = GetHeightOfRows (startingRow, CountRowDifference (startingRow, endingRow) + 1);
7945 return fDesiredHeight;
7953WordProcessorTable::SavedTextRepWSel::SavedTextRepWSel (SavedTextRep* delegateTo, WordProcessorTable& table, WPRelativeFlag wPRelativeFlag)
7954 : inherited (table.GetStart (), table.GetEnd ())
7955 , fWPRelativeFlag (wPRelativeFlag)
7956 , fRealRep (delegateTo)
7961 , fIntraCellMode (false)
7962 , fIntraCellSelStart (0)
7963 , fIntraCellSelEnd (0)
7966 table.GetCellSelection (&fRowSelStart, &fRowSelEnd, &fColSelStart, &fColSelEnd);
7967 fIntraCellMode = table.GetIntraCellMode ();
7968 if (fIntraCellMode) {
7969 table.GetIntraCellSelection (&fIntraCellSelStart, &fIntraCellSelEnd);
7973size_t WordProcessorTable::SavedTextRepWSel::GetLength ()
const
7975 return fRealRep->GetLength ();
7978void WordProcessorTable::SavedTextRepWSel::InsertSelf (TextInteractor* interactor,
size_t at,
size_t nBytesToOverwrite)
7980 fRealRep->InsertSelf (interactor, at, nBytesToOverwrite);
7983void WordProcessorTable::SavedTextRepWSel::ApplySelection (TextInteractor* interactor)
7985 fRealRep->ApplySelection (interactor);
7987 WordProcessorTable* aT =
nullptr;
7988 if (fWPRelativeFlag == eWPDirect) {
7989 EmbeddedTableWordProcessor* wp =
dynamic_cast<EmbeddedTableWordProcessor*
> (interactor);
7990 aT = &wp->GetOwningTable ();
7993 WordProcessor* wp =
dynamic_cast<WordProcessor*
> (interactor);
7995 aT = wp->GetActiveTable ();
8000 aT->SetCellSelection (fRowSelStart, fRowSelEnd, fColSelStart, fColSelEnd);
8001 if (fIntraCellMode) {
8002 aT->SetIntraCellMode ();
8003 aT->SetIntraCellSelection (fIntraCellSelStart, fIntraCellSelEnd);
8006 aT->UnSetIntraCellMode ();
8015using EmptySelectionParagraphSavedTextRep = WordProcessor::EmptySelectionParagraphSavedTextRep;
8017EmptySelectionParagraphSavedTextRep::EmptySelectionParagraphSavedTextRep (WordProcessor* interactor,
size_t selStart,
size_t selEnd,
size_t at)
8018 : inherited (interactor, selStart, selEnd)
8019 , fSavedStyleInfo (interactor->GetParagraphDatabase ()->GetParagraphInfo (at))
8023void EmptySelectionParagraphSavedTextRep::InsertSelf (TextInteractor* interactor,
size_t at,
size_t nBytesToOverwrite)
8025 inherited::InsertSelf (interactor, at, nBytesToOverwrite);
8026 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 ...