4#include "Stroika/Frameworks/StroikaPreComp.h"
8#if qStroika_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_Platform_Windows
2047 memset (&cc, 0,
sizeof (cc));
2048 cc.lStructSize =
sizeof (cc);
2049 cc.Flags |= CC_ANYCOLOR;
2050 cc.rgbResult = color->GetOSRep ();
2051 cc.Flags |= CC_RGBINIT;
2052 cc.Flags |= CC_FULLOPEN;
2054 cc.Flags |= CC_ENABLEHOOK;
2055 cc.lpfnHook = ColorPickerINITPROC;
2057 static COLORREF sCustomColors[16];
2058 cc.lpCustColors = sCustomColors;
2060 cc.hwndOwner = ::GetActiveWindow ();
2062 if (::ChooseColor (&cc)) {
2063 *color =
Color (cc.rgbResult);
2070#if qStroika_Platform_Windows
2071UINT_PTR CALLBACK WordProcessor::DialogSupport::ColorPickerINITPROC (HWND hWnd, UINT message, [[maybe_unused]] WPARAM wParam, [[maybe_unused]] LPARAM lParam)
2073 if (hWnd !=
nullptr and message == WM_INITDIALOG) {
2074 Led_CenterWindowInParent (hWnd);
2080bool WordProcessor::DialogSupport::ChooseFont ([[maybe_unused]] IncrementalFontSpecification* font)
2084#if qStroika_Platform_Windows
2087 (void)::memset (&lf, 0,
sizeof (lf));
2088 if (font->GetFontNameSpecifier_Valid ()) {
2089 Characters::CString::Copy (lf.lfFaceName, std::size (lf.lfFaceName), font->GetFontNameSpecifier ().fName);
2090 Assert (::_tcslen (lf.lfFaceName) < std::size (lf.lfFaceName));
2092 lf.lfWeight = (font->GetStyle_Bold_Valid () and font->GetStyle_Bold ()) ? FW_BOLD : FW_NORMAL;
2093 lf.lfItalic = (font->GetStyle_Italic_Valid () and font->GetStyle_Italic ());
2094 lf.lfUnderline = (font->GetStyle_Underline_Valid () and font->GetStyle_Underline ());
2095 lf.lfStrikeOut = (font->GetStyle_Strikeout_Valid () and font->GetStyle_Strikeout ());
2097 if (font->GetPointSize_Valid ()) {
2098 lf.lfHeight = font->PeekAtTMHeight ();
2102 memset (&cc, 0,
sizeof (cc));
2103 cc.lStructSize =
sizeof (cc);
2104 cc.Flags |= CF_SCREENFONTS | CF_NOVERTFONTS | CF_EFFECTS | CF_SCALABLEONLY;
2106 cc.hwndOwner = ::GetActiveWindow ();
2109 cc.Flags |= CF_INITTOLOGFONTSTRUCT;
2111 if (font->GetTextColor_Valid ()) {
2112 cc.rgbColors = font->GetTextColor ().GetOSRep ();
2115 if (::ChooseFont (&cc)) {
2117 font->SetTextColor (
Color (cc.rgbColors));
2124void WordProcessor::DialogSupport::ShowSimpleEmbeddingInfoDialog (
const SDKString& )
2135bool WordProcessor::DialogSupport::ShowAddURLEmbeddingInfoDialog (
SDKString* ,
SDKString* )
2141bool WordProcessor::DialogSupport::AddNewTableDialog (
size_t* nRows,
size_t* nCols)
2151bool WordProcessor::DialogSupport::EditTablePropertiesDialog ([[maybe_unused]] TableSelectionPropertiesInfo* tableProperties)
2162WordProcessor::CommandNames WordProcessor::sCommandNames = WordProcessor::MakeDefaultCommandNames ();
2163WordProcessor::DialogSupport* WordProcessor::sDialogSupport =
nullptr;
2165template <
class T,
class EXTRACTOR>
2166bool CheckForCommonParaValue (EXTRACTOR ,
const shared_ptr<AbstractParagraphDatabaseRep>& paraDB,
2167 size_t from,
size_t to, T* commonValue)
2170 if (paraDB.get () ==
nullptr) {
2171 throw WordProcessor::NoParagraphDatabaseAvailable ();
2173 vector<pair<ParagraphInfo, size_t>> v = paraDB->GetParagraphInfo (from, to - from);
2174 Assert (v.size () != 0);
2175 if (v.size () >= 1) {
2176 T maybeCommonValue = EXTRACTOR () (v[0].first);
2177 for (
auto i = v.begin () + 1; i != v.end (); ++i) {
2178 if (EXTRACTOR () ((*i).first) != maybeCommonValue) {
2182 *commonValue = maybeCommonValue;
2189struct JustificationExtractor {
2192 return from.GetJustification ();
2195struct TabStopExtractor {
2198 return from.GetTabStopList ();
2201struct FirstIndentExtractor {
2204 return from.GetFirstIndent ();
2213 MarginsRec (TWIPS lhs, TWIPS rhs)
2222 inline bool operator!= (
const MarginsRec& rhs)
2224 return fLHS != rhs.fLHS or fRHS != rhs.fRHS;
2227struct MarginsRecExtractor {
2230 return MarginsRec (from.GetLeftMargin (), from.GetRightMargin ());
2233struct SpaceBeforeExtractor {
2236 return from.GetSpaceBefore ();
2239struct SpaceAfterExtractor {
2242 return from.GetSpaceAfter ();
2245struct LineSpacingExtractor {
2248 return from.GetLineSpacing ();
2251struct ListStyleExtractor {
2254 return from.GetListStyle ();
2257struct ListIndentLevelExtractor {
2260 return from.GetListIndentLevel ();
2264WordProcessor::WordProcessor ()
2266 , fSmartQuoteMode (true)
2267 , fParagraphDatabase (nullptr)
2268 , fICreatedParaDB (false)
2269 , fHidableTextDatabase (nullptr)
2270 , fICreatedHidableTextDB (false)
2272 , fCachedCurSelFontSpec ()
2273 , fCachedCurSelJustification (eLeftJustify)
2274 , fCachedCurSelJustificationUnique (false)
2275 , fCachedCurSelFontSpecValid (false)
2276 , fShowParagraphGlyphs (false)
2277 , fShowTabGlyphs (false)
2278 , fShowSpaceGlyphs (false)
2280 fWPIdler.fWP =
this;
2281 IdleManager::Get ().AddIdler (&fWPIdler);
2282 IdleManager::Get ().SetIdlerFrequncy (&fWPIdler, 0.25s);
2285WordProcessor::~WordProcessor ()
2287 IdleManager::Get ().RemoveIdler (&fWPIdler);
2290void WordProcessor::HookLosingTextStore ()
2292 HookLosingTextStore_ ();
2293 inherited::HookLosingTextStore ();
2296void WordProcessor::HookLosingTextStore_ ()
2299 MarkersOfATypeMarkerSink2Vector<WordProcessorTable> tables;
2300 GetTextStore ().CollectAllMarkersInRangeInto (GetTextStore ().GetStart (), GetTextStore ().GetEnd (),
this, tables);
2301 GetTextStore ().RemoveAndDeleteMarkers (
Containers::Start (tables.fResult), tables.fResult.size ());
2309 if (fICreatedParaDB) {
2310 fICreatedParaDB =
false;
2311 if (fParagraphDatabase.get () !=
nullptr) {
2312 fParagraphDatabase.reset ();
2313 HookParagraphDatabaseChanged ();
2316 if (fICreatedHidableTextDB) {
2317 SetHidableTextDatabase (
nullptr);
2318 fICreatedHidableTextDB =
false;
2321 if (fHidableTextDatabase.get () !=
nullptr) {
2322 fHidableTextDatabase->SetInternalizer (
nullptr);
2323 fHidableTextDatabase->SetExternalizer (
nullptr);
2327void WordProcessor::HookGainedNewTextStore ()
2333 if (fParagraphDatabase.get () !=
nullptr) {
2334 SetPartition (fParagraphDatabase->GetPartition ());
2336 inherited::HookGainedNewTextStore ();
2337 HookGainedNewTextStore_ ();
2340void WordProcessor::HookGainedNewTextStore_ ()
2342 if (fParagraphDatabase.get () ==
nullptr) {
2343 SetParagraphDatabase (
nullptr);
2345 if (fHidableTextDatabase.get () ==
nullptr) {
2346 SetHidableTextDatabase (MakeSharedPtr<UniformHidableTextMarkerOwner> (GetTextStore ()));
2347 fICreatedHidableTextDB =
true;
2351shared_ptr<Partition> WordProcessor::MakeDefaultPartition ()
const
2355 if (fParagraphDatabase.get () ==
nullptr) {
2356 return MakeSharedPtr<LineBasedPartition> (GetTextStore ());
2359 const MarkerOwner* mo = fParagraphDatabase.get ();
2360 return MakeSharedPtr<WPPartition> (GetTextStore (), *
const_cast<MarkerOwner*
> (mo));
2373void WordProcessor::SetParagraphDatabase (
const shared_ptr<AbstractParagraphDatabaseRep>& paragraphDatabase)
2375 fParagraphDatabase = paragraphDatabase;
2376 fICreatedParaDB =
false;
2377 if (fParagraphDatabase.get () ==
nullptr and PeekAtTextStore () !=
nullptr) {
2378 fParagraphDatabase = MakeSharedPtr<ParagraphDatabaseRep> (GetTextStore ());
2379 fICreatedParaDB =
true;
2382 HookParagraphDatabaseChanged ();
2392void WordProcessor::HookParagraphDatabaseChanged ()
2394 if (PeekAtTextStore () !=
nullptr) {
2395 HookParagraphDatabaseChanged_ ();
2403void WordProcessor::HookParagraphDatabaseChanged_ ()
2411 if (fParagraphDatabase.get () !=
nullptr) {
2412 SetPartition (fParagraphDatabase->GetPartition ());
2414 SetExternalizer (MakeDefaultExternalizer ());
2415 SetInternalizer (MakeDefaultInternalizer ());
2430void WordProcessor::SetHidableTextDatabase (
const shared_ptr<HidableTextMarkerOwner>& hidableTextDatabase)
2433 if (fHidableTextDatabase.get () !=
nullptr) {
2434 fHidableTextDatabase->SetInternalizer (shared_ptr<FlavorPackageInternalizer> ());
2435 fHidableTextDatabase->SetExternalizer (shared_ptr<FlavorPackageExternalizer> ());
2438 fHidableTextDatabase = hidableTextDatabase;
2439 fICreatedHidableTextDB =
false;
2440 HookHidableTextDatabaseChanged ();
2450void WordProcessor::HookHidableTextDatabaseChanged ()
2452 HookHidableTextDatabaseChanged_ ();
2461void WordProcessor::HookHidableTextDatabaseChanged_ ()
2463 if (PeekAtTextStore () !=
nullptr) {
2464 SetExternalizer (MakeDefaultExternalizer ());
2465 SetInternalizer (MakeDefaultInternalizer ());
2469shared_ptr<FlavorPackageInternalizer> WordProcessor::MakeDefaultInternalizer ()
2471 return MakeSharedPtr<WordProcessorFlavorPackageInternalizer> (GetTextStore (), GetStyleDatabase (), GetParagraphDatabase (),
2472 GetHidableTextDatabase ());
2475shared_ptr<FlavorPackageExternalizer> WordProcessor::MakeDefaultExternalizer ()
2477 return MakeSharedPtr<WordProcessorFlavorPackageExternalizer> (GetTextStore (), GetStyleDatabase (), GetParagraphDatabase (),
2478 GetHidableTextDatabase ());
2485void WordProcessor::HookInternalizerChanged ()
2487 inherited::HookInternalizerChanged ();
2488 if (fHidableTextDatabase.get () !=
nullptr) {
2489 fHidableTextDatabase->SetInternalizer (GetInternalizer ());
2497void WordProcessor::HookExternalizerChanged ()
2499 inherited::HookExternalizerChanged ();
2500 if (fHidableTextDatabase.get () !=
nullptr) {
2501 fHidableTextDatabase->SetExternalizer (GetExternalizer ());
2510void WordProcessor::InternalizeBestFlavor (
ReaderFlavorPackage& flavorPackage,
bool updateCursorPosition,
bool autoScroll, UpdateMode updateMode)
2512 WordProcessorTable* t = GetActiveTable ();
2514 WordProcessorFlavorPackageInternalizer* internalizerRep =
2515 dynamic_cast<WordProcessorFlavorPackageInternalizer*
> (
static_cast<FlavorPackageInternalizer*
> (GetInternalizer ().get ()));
2518 bool oldFlagVal = internalizerRep->GetOverwriteTableMode ();
2519 internalizerRep->SetOverwriteTableMode (
true);
2521 size_t selEnd = GetSelectionEnd ();
2522 Assert (selEnd - GetSelectionStart () == 1);
2526 bool good = GetInternalizer ()->InternalizeBestFlavor (flavorPackage, selEnd, selEnd);
2529 ScrollToSelection ();
2531 if (updateMode == eImmediateUpdate) {
2538 internalizerRep->SetOverwriteTableMode (oldFlagVal);
2541 internalizerRep->SetOverwriteTableMode (oldFlagVal);
2546 inherited::InternalizeBestFlavor (flavorPackage, updateCursorPosition, autoScroll, updateMode);
2557 WordProcessorFlavorPackageExternalizer* externalizerRep =
2558 dynamic_cast<WordProcessorFlavorPackageExternalizer*
> (
static_cast<FlavorPackageExternalizer*
> (GetExternalizer ().get ()));
2561 bool oldFlagVal = externalizerRep->GetUseTableSelection ();
2562 externalizerRep->SetUseTableSelection (
true);
2564 inherited::ExternalizeFlavors (flavorPackage);
2565 externalizerRep->SetUseTableSelection (oldFlagVal);
2568 externalizerRep->SetUseTableSelection (oldFlagVal);
2578void WordProcessor::InterectiveSetRegionHidable (
bool hidable)
2582 BreakInGroupedCommands ();
2584 UndoableContextHelper undoContext (*
this, hidable ? GetCommandNames ().fHideCommandName : GetCommandNames ().fUnHideCommandName, false);
2587 GetHidableTextDatabase ()->MakeRegionHidable (undoContext.GetUndoRegionStart (), undoContext.GetUndoRegionEnd ());
2590 GetHidableTextDatabase ()->MakeRegionUnHidable (undoContext.GetUndoRegionStart (), undoContext.GetUndoRegionEnd ());
2593 undoContext.CommandComplete ();
2601Justification WordProcessor::GetJustification (
size_t characterPos)
const
2603 if (fParagraphDatabase.get () ==
nullptr) {
2604 throw NoParagraphDatabaseAvailable ();
2606 return fParagraphDatabase->GetParagraphInfo (characterPos).GetJustification ();
2614bool WordProcessor::GetJustification (
size_t from,
size_t to, Justification* justification)
const
2617 return CheckForCommonParaValue (JustificationExtractor (), fParagraphDatabase, from, to, justification);
2625void WordProcessor::SetJustification (
size_t from,
size_t to, Justification justification)
2627 Require (from <= to);
2629 pi.SetJustification (justification);
2630 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2633StandardTabStopList WordProcessor::GetDefaultStandardTabStopList ()
2635 return StandardTabStopList{};
2643StandardTabStopList WordProcessor::GetStandardTabStopList (
size_t characterPos)
const
2645 return fParagraphDatabase->GetParagraphInfo (characterPos).GetTabStopList ();
2653bool WordProcessor::GetStandardTabStopList (
size_t from,
size_t to, StandardTabStopList* tabStops)
const
2656 return CheckForCommonParaValue (TabStopExtractor (), fParagraphDatabase, from, to, tabStops);
2664void WordProcessor::SetStandardTabStopList (
size_t from,
size_t to, StandardTabStopList tabStops)
2666 Require (from <= to);
2668 pi.SetTabStopList (tabStops);
2669 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2677void WordProcessor::GetMargins (
size_t characterPos, TWIPS* leftMargin, TWIPS* rightMargin)
const
2681 const ParagraphInfo& pi = fParagraphDatabase->GetParagraphInfo (characterPos);
2685 *leftMargin = pi.GetLeftMargin ();
2686 *rightMargin = pi.GetRightMargin ();
2689bool WordProcessor::GetMargins (
size_t from,
size_t to, TWIPS* leftMargin, TWIPS* rightMargin)
const
2693 MarginsRec mrResult;
2694 bool result = CheckForCommonParaValue (MarginsRecExtractor (), fParagraphDatabase, from, to, &mrResult);
2695 *leftMargin = mrResult.fLHS;
2696 *rightMargin = mrResult.fRHS;
2704void WordProcessor::SetMargins (
size_t from,
size_t to, TWIPS leftMargin, TWIPS rightMargin)
2706 Require (from <= to);
2708 pi.SetMargins (leftMargin, rightMargin);
2709 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2717TWIPS WordProcessor::GetFirstIndent (
size_t characterPos)
const
2719 return fParagraphDatabase->GetParagraphInfo (characterPos).GetFirstIndent ();
2727bool WordProcessor::GetFirstIndent (
size_t from,
size_t to, TWIPS* firstIndent)
const
2730 return CheckForCommonParaValue (FirstIndentExtractor (), fParagraphDatabase, from, to, firstIndent);
2737void WordProcessor::SetFirstIndent (
size_t from,
size_t to, TWIPS firstIndent)
2739 Require (from <= to);
2741 pi.SetFirstIndent (firstIndent);
2742 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2750TWIPS WordProcessor::GetSpaceBefore (
size_t characterPos)
const
2752 if (fParagraphDatabase.get () ==
nullptr) {
2753 throw NoParagraphDatabaseAvailable{};
2755 return fParagraphDatabase->GetParagraphInfo (characterPos).GetSpaceBefore ();
2763bool WordProcessor::GetSpaceBefore (
size_t from,
size_t to, TWIPS* sb)
const
2766 return CheckForCommonParaValue (SpaceBeforeExtractor{}, fParagraphDatabase, from, to, sb);
2774void WordProcessor::SetSpaceBefore (
size_t from,
size_t to, TWIPS sb)
2776 Require (from <= to);
2777 if (fParagraphDatabase.get () ==
nullptr) {
2778 throw NoParagraphDatabaseAvailable{};
2781 pi.SetSpaceBefore (sb);
2782 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2790TWIPS WordProcessor::GetSpaceAfter (
size_t characterPos)
const
2792 if (fParagraphDatabase.get () ==
nullptr) {
2793 throw NoParagraphDatabaseAvailable ();
2795 return fParagraphDatabase->GetParagraphInfo (characterPos).GetSpaceAfter ();
2803bool WordProcessor::GetSpaceAfter (
size_t from,
size_t to, TWIPS* sa)
const
2806 return CheckForCommonParaValue (SpaceAfterExtractor (), fParagraphDatabase, from, to, sa);
2814void WordProcessor::SetSpaceAfter (
size_t from,
size_t to, TWIPS sa)
2816 Require (from <= to);
2817 if (fParagraphDatabase.get () ==
nullptr) {
2818 throw NoParagraphDatabaseAvailable ();
2821 pi.SetSpaceAfter (sa);
2822 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2830LineSpacing WordProcessor::GetLineSpacing (
size_t characterPos)
const
2832 if (fParagraphDatabase.get () ==
nullptr) {
2833 throw NoParagraphDatabaseAvailable ();
2835 return fParagraphDatabase->GetParagraphInfo (characterPos).GetLineSpacing ();
2843bool WordProcessor::GetLineSpacing (
size_t from,
size_t to, LineSpacing* sl)
const
2846 return CheckForCommonParaValue (LineSpacingExtractor (), fParagraphDatabase, from, to, sl);
2854void WordProcessor::SetLineSpacing (
size_t from,
size_t to, LineSpacing sl)
2856 Require (from <= to);
2858 pi.SetLineSpacing (sl);
2859 if (fParagraphDatabase.get () ==
nullptr) {
2860 throw NoParagraphDatabaseAvailable ();
2862 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2870ListStyle WordProcessor::GetListStyle (
size_t characterPos)
const
2872 if (fParagraphDatabase.get () ==
nullptr) {
2873 throw NoParagraphDatabaseAvailable ();
2875 return fParagraphDatabase->GetParagraphInfo (characterPos).GetListStyle ();
2883bool WordProcessor::GetListStyle (
size_t from,
size_t to, ListStyle* listStyle)
const
2886 return CheckForCommonParaValue (ListStyleExtractor (), fParagraphDatabase, from, to, listStyle);
2894void WordProcessor::SetListStyle (
size_t from,
size_t to, ListStyle listStyle,
bool autoFormat)
2896 Require (from <= to);
2898 pi.SetListStyle (listStyle);
2899 if (fParagraphDatabase.get () ==
nullptr) {
2900 throw NoParagraphDatabaseAvailable ();
2902 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2905 AutoFormatIndentedText (from, to);
2914unsigned char WordProcessor::GetListIndentLevel (
size_t characterPos)
const
2916 if (fParagraphDatabase.get () ==
nullptr) {
2917 throw NoParagraphDatabaseAvailable ();
2919 return fParagraphDatabase->GetParagraphInfo (characterPos).GetListIndentLevel ();
2927bool WordProcessor::GetListIndentLevel (
size_t from,
size_t to,
unsigned char* indentLevel)
const
2930 return CheckForCommonParaValue (ListIndentLevelExtractor (), fParagraphDatabase, from, to, indentLevel);
2938void WordProcessor::SetListIndentLevel (
size_t from,
size_t to,
unsigned char indentLevel,
bool autoFormat)
2940 Require (from <= to);
2942 pi.SetListIndentLevel (indentLevel);
2943 if (fParagraphDatabase.get () ==
nullptr) {
2944 throw NoParagraphDatabaseAvailable ();
2946 fParagraphDatabase->SetParagraphInfo (from, to - from, pi);
2948 AutoFormatIndentedText (from, to);
2959void WordProcessor::AutoFormatIndentedText (
size_t from,
size_t to)
2961 for (PartitionMarker* pm = GetPartitionMarkerContainingPosition (from); pm !=
nullptr and pm->GetStart () <= to; pm = pm->GetNext ()) {
2963 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (pm->GetStart ());
2965 if (pi.GetListStyle () == eListStyle_None) {
2966 newPI.SetFirstIndent (TWIPS{0});
2967 newPI.SetMargins (TWIPS{0}, pi.GetRightMargin ());
2968 newPI.SetTabStopList (StandardTabStopList ());
2971 const int kTWIPSIncrement = 1440 / 4;
2972 TWIPS marginAt = TWIPS (kTWIPSIncrement * 2 * (pi.GetListIndentLevel () + 1));
2973 newPI.SetFirstIndent (TWIPS (-kTWIPSIncrement));
2974 newPI.SetMargins (marginAt, pi.GetRightMargin ());
2975 StandardTabStopList tabStops;
2976 tabStops.fTabStops.push_back (marginAt);
2977 newPI.SetTabStopList (tabStops);
2979 fParagraphDatabase->SetParagraphInfo (pm->GetStart (), pm->GetLength (), newPI);
2987void WordProcessor::SetSelection (
size_t start,
size_t end)
2989 size_t oldSelStart = 0;
2990 size_t oldSelEnd = 0;
2991 GetSelection (&oldSelStart, &oldSelEnd);
2992 inherited::SetSelection (start, end);
2997 if (oldSelStart != start or oldSelEnd != end) {
2998 vector<WordProcessorTable*> tables;
2999 size_t checkRangeStart1 = start;
3000 size_t checkRangeEnd1 = oldSelStart;
3001 if (checkRangeStart1 < checkRangeEnd1) {
3002 tables = GetTablesInRange (checkRangeStart1, checkRangeEnd1);
3005 size_t checkRangeStart2 = FindPreviousCharacter (oldSelEnd);
3006 size_t checkRangeEnd2 = end;
3007 if (checkRangeStart2 < checkRangeEnd2) {
3008 vector<WordProcessorTable*> tables2 = GetTablesInRange (checkRangeStart2, checkRangeEnd2);
3009 tables.insert (tables.end (), tables2.begin (), tables2.end ());
3011 for (
auto i = tables.begin (); i != tables.end (); ++i) {
3012 WordProcessorTable* t = *i;
3013 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*t, *
const_cast<WordProcessor*
> (
this));
3014 t->SetCellSelection (0, t->GetRowCount (), 0, t->GetColumnCount ());
3018 fCachedCurSelFontSpecValid =
false;
3025bool WordProcessor::GetCaretShownSituation ()
const
3027 if (inherited::GetCaretShownSituation ()) {
3031 WordProcessorTable* table = GetActiveTable ();
3032 if (table !=
nullptr) {
3033 return table->GetCaretShownSituation ();
3042Led_Rect WordProcessor::CalculateCaretRect ()
const
3044 WordProcessorTable* table = GetActiveTable ();
3045 if (table !=
nullptr) {
3046 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*table, *
const_cast<WordProcessor*
> (
this));
3047 return table->CalculateCaretRect ();
3049 return inherited::CalculateCaretRect ();
3057void WordProcessor::OnTypedNormalCharacter (Led_tChar theChar,
bool optionPressed,
bool shiftPressed,
bool commandPressed,
3058 bool controlPressed,
bool altKeyPressed)
3060 WordProcessorTable* table = GetActiveTable ();
3061 if (table !=
nullptr) {
3062 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*table, *
const_cast<WordProcessor*
> (
this));
3063 if (table->OnTypedNormalCharacter (theChar, optionPressed, shiftPressed, commandPressed, controlPressed, altKeyPressed)) {
3069 if (theChar ==
'\t' and not(optionPressed or commandPressed or controlPressed or altKeyPressed)) {
3070 ListStyle ls = eListStyle_None;
3071 if (GetListStyle (GetSelectionStart (), GetSelectionEnd (), &ls) and ls != eListStyle_None) {
3072 InteractiveDoIndentChange (not shiftPressed);
3076 if (theChar ==
'"' and GetSmartQuoteMode () and not(optionPressed or commandPressed or controlPressed or altKeyPressed)) {
3077 const wchar_t kSpecialOpenQuote = 8220;
3078 const wchar_t kSpecialCloseQuote = 8221;
3079 bool isAQuoteToClose =
false;
3080 size_t selStart = GetSelectionStart ();
3083 const size_t kScanBackSize = 1024;
3084 size_t scanBackTo =
static_cast<size_t> (max (0,
static_cast<int> (selStart) -
static_cast<int> (kScanBackSize)));
3086 size_t scanBackCount = selStart - scanBackTo;
3087 CopyOut (scanBackTo, scanBackCount, buf.data ());
3088 for (
size_t i = scanBackCount; i != 0; --i) {
3089 if (buf[i - 1] == kSpecialCloseQuote) {
3093 else if (buf[i - 1] == kSpecialOpenQuote) {
3094 isAQuoteToClose =
true;
3099 wchar_t quoteChar = isAQuoteToClose ? kSpecialCloseQuote : kSpecialOpenQuote;
3100 inherited::OnTypedNormalCharacter (quoteChar, optionPressed, shiftPressed, commandPressed, controlPressed, altKeyPressed);
3103 inherited::OnTypedNormalCharacter (theChar, optionPressed, shiftPressed, commandPressed, controlPressed, altKeyPressed);
3107bool WordProcessor::ProcessSimpleClick (Led_Point clickedAt,
unsigned clickCount,
bool extendSelection,
size_t* dragAnchor)
3110 size_t clickedOnChar = GetCharAtWindowLocation (clickedAt);
3111 Led_Rect charRect = GetCharWindowLocation (clickedOnChar);
3119 Led_Rect tstClickRect = charRect;
3120 const DistanceType kHMargin = 3;
3121 tstClickRect.left += kHMargin;
3122 tstClickRect.right -= kHMargin;
3123 if (tstClickRect.Contains (clickedAt)) {
3124 vector<WordProcessorTable*> tables = GetTablesInRange (clickedOnChar, clickedOnChar + 1);
3125 Assert (tables.size () == 0 or tables.size () == 1);
3126 if (tables.size () == 1) {
3127 WordProcessorTable* t = tables[0];
3128 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*t, *
const_cast<WordProcessor*
> (
this));
3129 if (clickCount == 1) {
3132 *dragAnchor = clickedOnChar;
3134 return t->ProcessSimpleClick (clickedAt - charRect.GetOrigin (), clickCount, extendSelection);
3137 return inherited::ProcessSimpleClick (clickedAt, clickCount, extendSelection, dragAnchor);
3144void WordProcessor::WhileSimpleMouseTracking (Led_Point newMousePos,
size_t dragAnchor)
3146 size_t clickedOnChar = GetCharAtWindowLocation (newMousePos);
3147 size_t oldSelStart = GetSelectionStart ();
3148 size_t oldSelEnd = GetSelectionEnd ();
3155 if ((clickedOnChar == dragAnchor or clickedOnChar + 1 == dragAnchor) and (oldSelEnd - oldSelStart == 1)) {
3156 vector<WordProcessorTable*> tables = GetTablesInRange (clickedOnChar, clickedOnChar + 1);
3157 if (tables.size () == 1) {
3158 WordProcessorTable* t = tables[0];
3159 Led_Rect charRect = GetCharWindowLocation (t->GetStart ());
3160 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*t, *
const_cast<WordProcessor*
> (
this));
3162 t->WhileSimpleMouseTracking (newMousePos - charRect.GetOrigin ());
3166 inherited::WhileSimpleMouseTracking (newMousePos, dragAnchor);
3168 DbgTrace (
"WordProcessor::WhileSimpleMouseTracking (tickCount=%f, newMousePos=(%d,%d), clickedOnChar=%d, dragAnchor=%d)\n",
3169 Time::GetTickCount (), newMousePos.v, newMousePos.h, clickedOnChar, dragAnchor
3179WordProcessorTable* WordProcessor::InsertTable (
size_t at)
3181 WordProcessorTable* t =
new WordProcessorTable (fParagraphDatabase.get (), at);
3182 t->SetDimensions (1, 1);
3193vector<WordProcessorTable*> WordProcessor::GetTablesInRange (
size_t from,
size_t to)
const
3195 if (to ==
static_cast<size_t> (-1)) {
3196 to = GetTextStore ().GetLength ();
3198 Require (from <= to);
3199 Require (to <= GetTextStore ().GetLength () + 1);
3200 MarkersOfATypeMarkerSink2Vector<WordProcessorTable> result;
3201 if (fParagraphDatabase.get () !=
nullptr) {
3202 GetTextStore ().CollectAllMarkersInRangeInto (from, to, fParagraphDatabase.get (), result);
3204 return result.fResult;
3211WordProcessorTable* WordProcessor::GetTableAt (
size_t from)
const
3213 size_t to = from + 1;
3214 Require (to <= GetTextStore ().GetLength () + 1);
3215 MarkerOfATypeMarkerSink<WordProcessorTable> result;
3216 if (fParagraphDatabase.get () !=
nullptr) {
3217 GetTextStore ().CollectAllMarkersInRangeInto (from, to, fParagraphDatabase.get (), result);
3219 return result.fResult;
3222WordProcessor::CommandNames WordProcessor::MakeDefaultCommandNames ()
3224 WordProcessor::CommandNames cmdNames;
3225 cmdNames.fJustificationCommandName = Led_SDK_TCHAROF (
"Justification Change");
3226 cmdNames.fStandardTabStopListCommandName = Led_SDK_TCHAROF (
"Set Tabs");
3227 cmdNames.fMarginsCommandName = Led_SDK_TCHAROF (
"Set Margins");
3228 cmdNames.fFirstIndentCommandName = Led_SDK_TCHAROF (
"Set First Indent");
3229 cmdNames.fMarginsAndFirstIndentCommandName = Led_SDK_TCHAROF (
"Set Margins and First Indent");
3230 cmdNames.fParagraphSpacingCommandName = Led_SDK_TCHAROF (
"Change Paragraph Spacing");
3231 cmdNames.fHideCommandName = Led_SDK_TCHAROF (
"Hide");
3232 cmdNames.fUnHideCommandName = Led_SDK_TCHAROF (
"UnHide");
3233 cmdNames.fSetListStyleCommandName = Led_SDK_TCHAROF (
"Change List Style");
3234 cmdNames.fIndentLevelChangeCommandName = Led_SDK_TCHAROF (
"Change Indent Level");
3235 cmdNames.fInsertTableCommandName = Led_SDK_TCHAROF (
"Insert Table");
3236 cmdNames.fInsertTableRowAboveCommandName = Led_SDK_TCHAROF (
"Insert Table Row Above");
3237 cmdNames.fInsertTableRowBelowCommandName = Led_SDK_TCHAROF (
"Insert Table Row Below");
3238 cmdNames.fInsertTableColBeforeCommandName = Led_SDK_TCHAROF (
"Insert Table Column Before");
3239 cmdNames.fInsertTableColAfterCommandName = Led_SDK_TCHAROF (
"Insert Table Column After");
3240 cmdNames.fInsertURLCommandName = Led_SDK_TCHAROF (
"Insert URL");
3241 cmdNames.fRemoveTableRowsCommandName = Led_SDK_TCHAROF (
"Remove Rows");
3242 cmdNames.fRemoveTableColumnsCommandName = Led_SDK_TCHAROF (
"Remove Columns");
3243 cmdNames.fEmbeddingTypeName_ImageDIB = Led_SDK_TCHAROF (
"image (DIB)");
3244 cmdNames.fEmbeddingTypeName_URL = Led_SDK_TCHAROF (
"URL");
3245 cmdNames.fEmbeddingTypeName_ImageMacPict = Led_SDK_TCHAROF (
"image (MacPICT)");
3246 cmdNames.fEmbeddingTypeName_Table = Led_SDK_TCHAROF (
"table");
3247 cmdNames.fEmbeddingTypeName_Unknown = Led_SDK_TCHAROF (
"unknown");
3248 cmdNames.fFontSizeChange_Other_NoArg = Led_SDK_TCHAROF (
"Other...");
3249 cmdNames.fFontSizeChange_Other_OneArg = Led_SDK_TCHAROF (
"Other (%d)...");
3250 cmdNames.fTablePropertiesCommandName = Led_SDK_TCHAROF (
"Table Properties...")
3251#if qStroika_Platform_Windows
3252 Led_SDK_TCHAROF (
"\tAlt+Enter")
3255 cmdNames.fGenericEmbeddingPropertiesCommandName = Led_SDK_TCHAROF (
"Properties")
3256#if qStroika_Platform_Windows
3257 Led_SDK_TCHAROF (
"\tAlt+Enter")
3260 cmdNames.fChangeTablePropertiesCommandName = Led_SDK_TCHAROF (
"Change table properties");
3270DistanceType WordProcessor::ComputeMaxHScrollPos ()
const
3272 DistanceType cachedLayoutWidth = 0;
3280 TextInteractor::Tablet_Acquirer tablet_ (
this);
3281 Tablet* tablet = tablet_;
3282 DistanceType width = tablet->CvtFromTWIPSH (CalculateFarthestRightMargin ());
3283 if (GetHScrollPos () != 0) {
3284 width = max (width, GetHScrollPos () + GetWindowRect ().GetWidth ());
3286 cachedLayoutWidth = max (width, DistanceType (1));
3288 DistanceType wWidth = GetWindowRect ().GetWidth ();
3289 if (cachedLayoutWidth > wWidth) {
3290 return (cachedLayoutWidth - wWidth);
3305TWIPS WordProcessor::CalculateFarthestRightMarginInDocument ()
const
3307 CoordinateType longestRowWidth = 0;
3308 RowReference curRow = RowReference{GetFirstPartitionMarker (), 0};
3310 CoordinateType rhsMargin = 0;
3311 GetLayoutMargins (curRow,
nullptr, &rhsMargin);
3312 longestRowWidth = max (longestRowWidth, rhsMargin);
3313 }
while (GetNextRowReference (&curRow));
3314 Tablet_Acquirer tablet_ (
this);
3315 Tablet* tablet = tablet_;
3316 return tablet->CvtToTWIPSH (longestRowWidth);
3324TWIPS WordProcessor::GetFarthestRightMarginInDocument ()
const
3326 AbstractParagraphDatabaseRep* pdbRep = GetParagraphDatabase ().get ();
3328 if (pdbRep->fCachedFarthestRightMarginInDocument == kBadCachedFarthestRightMarginInDocument) {
3329 pdbRep->fCachedFarthestRightMarginInDocument = CalculateFarthestRightMarginInDocument ();
3331 return pdbRep->fCachedFarthestRightMarginInDocument;
3342TWIPS WordProcessor::CalculateFarthestRightMarginInWindow ()
const
3344 CoordinateType longestRowWidth = 0;
3345 size_t rowsLeftInWindow = GetTotalRowsInWindow_ ();
3346 RowReference curRow = GetTopRowReferenceInWindow ();
3348 CoordinateType rhsMargin = 0;
3349 GetLayoutMargins (curRow,
nullptr, &rhsMargin);
3350 longestRowWidth = max (longestRowWidth, rhsMargin);
3351 }
while (rowsLeftInWindow-- > 0 and GetNextRowReference (&curRow));
3352 Tablet_Acquirer tablet_ (
this);
3353 Tablet* tablet = tablet_;
3354 return tablet->CvtToTWIPSH (longestRowWidth);
3363TWIPS WordProcessor::CalculateFarthestRightMargin ()
const
3365 return GetFarthestRightMarginInDocument ();
3368void WordProcessor::InvalidateAllCaches ()
3370 inherited::InvalidateAllCaches ();
3371 shared_ptr<AbstractParagraphDatabaseRep> pdb = GetParagraphDatabase ();
3372 if (pdb.get () !=
nullptr) {
3373 static_cast<AbstractParagraphDatabaseRep*
> (pdb.get ())->fCachedFarthestRightMarginInDocument = kBadCachedFarthestRightMarginInDocument;
3377void WordProcessor::TabletChangedMetrics ()
3379 inherited::TabletChangedMetrics ();
3380 shared_ptr<AbstractParagraphDatabaseRep> pdb = GetParagraphDatabase ();
3381 if (pdb.get () !=
nullptr) {
3382 static_cast<AbstractParagraphDatabaseRep*
> (pdb.get ())->fCachedFarthestRightMarginInDocument = kBadCachedFarthestRightMarginInDocument;
3386void WordProcessor::DidUpdateText (
const UpdateInfo& updateInfo)
noexcept
3388 inherited::DidUpdateText (updateInfo);
3389 fCachedCurSelFontSpecValid =
false;
3392void WordProcessor::AssureCurSelFontCacheValid ()
const
3394 if (not fCachedCurSelFontSpecValid) {
3395 Assert (GetSelectionEnd () >= GetSelectionStart ());
3396 size_t selectionLength = GetSelectionEnd () - GetSelectionStart ();
3397 WordProcessorTable* aT = GetActiveTable ();
3398 if (aT !=
nullptr) {
3399 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, *
const_cast<WordProcessor*
> (
this));
3400 aT->AssureCurSelFontCacheValid (&fCachedCurSelFontSpec);
3401 fCachedCurSelJustification = eLeftJustify;
3402 fCachedCurSelJustificationUnique =
false;
3405 fCachedCurSelFontSpec = GetContinuousStyleInfo (GetSelectionStart (), selectionLength);
3406 fCachedCurSelJustificationUnique = GetJustification (GetSelectionStart (), GetSelectionEnd (), &fCachedCurSelJustification);
3408 fCachedCurSelFontSpecValid =
true;
3412void WordProcessor::DoSingleCharCursorEdit (CursorMovementDirection direction, CursorMovementUnit movementUnit, CursorMovementAction action,
3413 UpdateMode updateMode,
bool scrollToSelection)
3415 WordProcessorTable* table = GetActiveTable ();
3416 if (table !=
nullptr) {
3417 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*table, *
const_cast<WordProcessor*
> (
this));
3418 if (table->DoSingleCharCursorEdit (direction, movementUnit, action, updateMode,
false)) {
3419 if (scrollToSelection) {
3420 ScrollToSelection ();
3425 inherited::DoSingleCharCursorEdit (direction, movementUnit, action, updateMode, scrollToSelection);
3428bool WordProcessor::OnUpdateCommand (CommandUpdater* enabler)
3432 WordProcessorTable* aT = GetActiveTable ();
3433 if (aT !=
nullptr) {
3434 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, *
const_cast<WordProcessor*
> (
this));
3435 if (aT->OnUpdateCommand (enabler)) {
3440 switch (enabler->GetCmdID ()) {
3441 case kFontStylePlain_CmdID: {
3442 OnUpdateFontStylePlainCommand (enabler);
3445 case kFontStyleBold_CmdID: {
3446 OnUpdateFontStyleBoldCommand (enabler);
3449 case kFontStyleItalic_CmdID: {
3450 OnUpdateFontStyleItalicCommand (enabler);
3453 case kFontStyleUnderline_CmdID: {
3454 OnUpdateFontStyleUnderlineCommand (enabler);
3457#if qStroika_Platform_Windows
3458 case kFontStyleStrikeout_CmdID: {
3459 OnUpdateFontStyleStrikeoutCommand (enabler);
3463 case kSubScriptCommand_CmdID: {
3464 OnUpdateFontStyleSubscriptCommand (enabler);
3467 case kSuperScriptCommand_CmdID: {
3468 OnUpdateFontStyleSuperscriptCommand (enabler);
3471 case kChooseFontCommand_CmdID: {
3472 OnUpdateChooseFontCommand (enabler);
3475 case kInsertTable_CmdID: {
3476 OnUpdateInsertTableCommand (enabler);
3479 case kInsertURL_CmdID: {
3480 OnUpdateInsertURLCommand (enabler);
3483 case kInsertSymbol_CmdID: {
3484 OnUpdateInsertSymbolCommand (enabler);
3487 case kHideSelection_CmdID: {
3488 OnUpdateHideSelectionCommands (enabler);
3491 case kUnHideSelection_CmdID: {
3492 OnUpdateHideSelectionCommands (enabler);
3495 case kParagraphSpacingCommand_CmdID: {
3496 OnUpdateParagraphSpacingChangeCommand (enabler);
3499 case kParagraphIndentsCommand_CmdID: {
3500 OnUpdateParagraphIndentsChangeCommand (enabler);
3503 case kIncreaseIndent_CmdID: {
3504 OnUpdateIndentCommand (enabler);
3507 case kDecreaseIndent_CmdID: {
3508 OnUpdateIndentCommand (enabler);
3513 if (kFontMenuFirst_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kFontMenuLast_CmdID) {
3514 OnUpdateFontNameChangeCommand (enabler);
3517 else if (kBaseFontSize_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastFontSize_CmdID) {
3518 OnUpdateFontSizeChangeCommand (enabler);
3521 else if (kBaseFontColor_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastFontColor_CmdID) {
3522 OnUpdateFontColorChangeCommand (enabler);
3525 else if (kFirstSelectedEmbedding_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastSelectedEmbedding_CmdID) {
3526 OnUpdateSelectedEmbeddingExtendedCommand (enabler);
3529 else if (kFirstJustification_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastJustification_CmdID) {
3530 OnUpdateParagraphJustificationCommand (enabler);
3533 else if (kFirstShowHideGlyph_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastShowHideGlyph_CmdID) {
3534 OnUpdateShowHideGlyphCommand (enabler);
3537 else if (kFirstListStyle_CmdID <= enabler->GetCmdID () and enabler->GetCmdID () <= kLastListStyle_CmdID) {
3538 OnUpdateListStyleChangeCommand (enabler);
3542 return inherited::OnUpdateCommand (enabler);
3545bool WordProcessor::OnPerformCommand (CommandNumber commandNumber)
3547 WordProcessorTable* aT = GetActiveTable ();
3548 if (aT !=
nullptr) {
3549 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, *
const_cast<WordProcessor*
> (
this));
3550 if (aT->OnPerformCommand (commandNumber)) {
3555 switch (commandNumber) {
3556 case kFontStylePlain_CmdID: {
3557 OnFontStylePlainCommand ();
3560 case kFontStyleBold_CmdID: {
3561 OnFontStyleBoldCommand ();
3564 case kFontStyleItalic_CmdID: {
3565 OnFontStyleItalicCommand ();
3568 case kFontStyleUnderline_CmdID: {
3569 OnFontStyleUnderlineCommand ();
3572#if qStroika_Platform_Windows
3573 case kFontStyleStrikeout_CmdID: {
3574 OnFontStyleStrikeoutCommand ();
3578 case kSubScriptCommand_CmdID: {
3579 OnFontStyleSubscriptCommand ();
3582 case kSuperScriptCommand_CmdID: {
3583 OnFontStyleSuperscriptCommand ();
3586 case kChooseFontCommand_CmdID: {
3587 OnChooseFontCommand ();
3590 case kInsertTable_CmdID: {
3591 OnInsertTableCommand ();
3594 case kInsertURL_CmdID: {
3595 OnInsertURLCommand ();
3598 case kInsertSymbol_CmdID: {
3599 OnInsertSymbolCommand ();
3602 case kHideSelection_CmdID: {
3606 case kUnHideSelection_CmdID: {
3607 OnUnHideSelection ();
3610 case kParagraphSpacingCommand_CmdID: {
3611 OnParagraphSpacingChangeCommand ();
3614 case kParagraphIndentsCommand_CmdID: {
3615 OnParagraphIndentsChangeCommand ();
3618 case kIncreaseIndent_CmdID: {
3619 OnIndentCommand (commandNumber);
3622 case kDecreaseIndent_CmdID: {
3623 OnIndentCommand (commandNumber);
3628 if (kFontMenuFirst_CmdID <= commandNumber and commandNumber <= kFontMenuLast_CmdID) {
3629 OnFontNameChangeCommand (commandNumber);
3632 else if (kBaseFontSize_CmdID <= commandNumber and commandNumber <= kLastFontSize_CmdID) {
3633 OnFontSizeChangeCommand (commandNumber);
3636 else if (kBaseFontColor_CmdID <= commandNumber and commandNumber <= kLastFontColor_CmdID) {
3637 OnFontColorChangeCommand (commandNumber);
3640 else if (kFirstSelectedEmbedding_CmdID <= commandNumber and commandNumber <= kLastSelectedEmbedding_CmdID) {
3641 return OnSelectedEmbeddingExtendedCommand (commandNumber);
3643 else if (kFirstJustification_CmdID <= commandNumber and commandNumber <= kLastJustification_CmdID) {
3644 OnParagraphJustificationCommand (commandNumber);
3647 else if (kFirstShowHideGlyph_CmdID <= commandNumber and commandNumber <= kLastShowHideGlyph_CmdID) {
3648 OnShowHideGlyphCommand (commandNumber);
3651 else if (kFirstListStyle_CmdID <= commandNumber and commandNumber <= kLastListStyle_CmdID) {
3652 OnListStyleChangeCommand (commandNumber);
3656 return inherited::OnPerformCommand (commandNumber);
3659bool WordProcessor::PassAlongCommandToIntraCellModeTableCell (CommandNumber commandNumber)
3661 switch (commandNumber) {
3672 case kSelectAll_CmdID: {
3678 WordProcessorTable* aT = GetActiveTable ();
3681 if (aT !=
nullptr and aT->GetIntraCellMode (&row, &col)) {
3682 size_t intraCellStart = 0;
3683 size_t intraCellEnd = 0;
3684 aT->GetIntraCellSelection (&intraCellStart, &intraCellEnd);
3685 if (intraCellStart != 0) {
3688 size_t cellEnd = aT->GetCell (row, col).GetTextStore ().GetEnd ();
3689 if (intraCellEnd != cellEnd) {
3696 case kParagraphSpacingCommand_CmdID:
3698 case kParagraphIndentsCommand_CmdID:
3700 case kIncreaseIndent_CmdID:
3702 case kDecreaseIndent_CmdID:
3704 case kChooseFontCommand_CmdID:
3706 case kInsertURL_CmdID:
3708 case kHideSelection_CmdID:
3710 case kUnHideSelection_CmdID:
3715 if (kBaseFontSize_CmdID <= commandNumber and commandNumber <= kLastFontSize_CmdID) {
3718 if (kBaseFontColor_CmdID <= commandNumber and commandNumber <= kLastFontColor_CmdID) {
3721 if (kFirstJustification_CmdID <= commandNumber and commandNumber <= kLastJustification_CmdID) {
3724 if (kFirstListStyle_CmdID <= commandNumber and commandNumber <= kLastListStyle_CmdID) {
3727 if (kFontMenuFirst_CmdID <= commandNumber and commandNumber <= kFontMenuLast_CmdID) {
3730 if (kFontStyleCommand_FirstCmdId <= commandNumber and commandNumber <= kFontStyleCommand_LastCmdId) {
3733 if (kFirstSelectedEmbedding_CmdID <= commandNumber and commandNumber <= kLastSelectedEmbedding_CmdID) {
3740bool WordProcessor::PassAlongCommandToEachSelectedTableCell (CommandNumber commandNumber)
3742 switch (commandNumber) {
3748 case kHideSelection_CmdID:
3750 case kUnHideSelection_CmdID:
3755 if (kBaseFontSize_CmdID <= commandNumber and commandNumber <= kLastFontSize_CmdID) {
3758 if (kBaseFontColor_CmdID <= commandNumber and commandNumber <= kLastFontColor_CmdID) {
3761 if (kFirstJustification_CmdID <= commandNumber and commandNumber <= kLastJustification_CmdID) {
3764 if (kFirstListStyle_CmdID <= commandNumber and commandNumber <= kLastListStyle_CmdID) {
3767 if (kFontMenuFirst_CmdID <= commandNumber and commandNumber <= kFontMenuLast_CmdID) {
3770 if (kFontStyleCommand_FirstCmdId <= commandNumber and commandNumber <= kFontStyleCommand_LastCmdId) {
3783void WordProcessor::OnSelectAllCommand ()
3785 inherited::OnSelectAllCommand ();
3786 if (GetLength () == 1) {
3787 (void)OnPerformCommand (kSelectTable_CmdID);
3791void WordProcessor::OnUpdateFontNameChangeCommand (CommandUpdater* enabler)
3794 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3797 enabler->SetChecked (fontSpec.GetFontNameSpecifier_Valid () and
3798 (GetDialogSupport ().CmdNumToFontName (enabler->GetCmdID ()) == fontSpec.GetFontNameSpecifier ()));
3799 enabler->SetEnabled (
true);
3802void WordProcessor::OnFontNameChangeCommand (CommandNumber cmdNum)
3804 IncrementalFontSpecification applyFontSpec;
3805 applyFontSpec.SetFontNameSpecifier (GetDialogSupport ().CmdNumToFontName (cmdNum));
3806 InteractiveSetFont (applyFontSpec);
3809void WordProcessor::OnUpdateFontStylePlainCommand (CommandUpdater* enabler)
3812 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3813 enabler->SetChecked (fontSpec.GetStyle_Plain_Valid () and fontSpec.GetStyle_Plain ());
3814 enabler->SetEnabled (
true);
3817void WordProcessor::OnFontStylePlainCommand ()
3819 IncrementalFontSpecification applyFontSpec;
3820 applyFontSpec.SetStyle_Plain ();
3821 InteractiveSetFont (applyFontSpec);
3824void WordProcessor::OnUpdateFontStyleBoldCommand (CommandUpdater* enabler)
3827 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3828 enabler->SetChecked (fontSpec.GetStyle_Bold_Valid () and fontSpec.GetStyle_Bold ());
3829 enabler->SetEnabled (
true);
3832void WordProcessor::OnFontStyleBoldCommand ()
3834 IncrementalFontSpecification applyFontSpec;
3835 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3836 applyFontSpec.SetStyle_Bold (not(fontSpec.GetStyle_Bold_Valid () and fontSpec.GetStyle_Bold ()));
3837 InteractiveSetFont (applyFontSpec);
3840void WordProcessor::OnUpdateFontStyleItalicCommand (CommandUpdater* enabler)
3843 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3844 enabler->SetChecked (fontSpec.GetStyle_Italic_Valid () and fontSpec.GetStyle_Italic ());
3845 enabler->SetEnabled (
true);
3848void WordProcessor::OnFontStyleItalicCommand ()
3850 IncrementalFontSpecification applyFontSpec;
3851 IncrementalFontSpecification fontSpec = GetCurSelFontSpec ();
3852 applyFontSpec.SetStyle_Italic (not(fontSpec.GetStyle_Italic_Valid () and fontSpec.GetStyle_Italic ()));
3853 InteractiveSetFont (applyFontSpec);
3856void WordProcessor::OnUpdateFontStyleUnderlineCommand (CommandUpdater* enabler)
3859 AssureCurSelFontCacheValid ();
3860 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_Underline_Valid () and fCachedCurSelFontSpec.GetStyle_Underline ());
3861 enabler->SetEnabled (
true);
3864void WordProcessor::OnFontStyleUnderlineCommand ()
3866 AssureCurSelFontCacheValid ();
3867 IncrementalFontSpecification applyFontSpec;
3868 applyFontSpec.SetStyle_Underline (not(fCachedCurSelFontSpec.GetStyle_Underline_Valid () and fCachedCurSelFontSpec.GetStyle_Underline ()));
3869 InteractiveSetFont (applyFontSpec);
3872#if qStroika_Platform_Windows
3874void WordProcessor::OnUpdateFontStyleStrikeoutCommand (CommandUpdater* enabler)
3877 AssureCurSelFontCacheValid ();
3878 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_Strikeout_Valid () and fCachedCurSelFontSpec.GetStyle_Strikeout ());
3879 enabler->SetEnabled (
true);
3882void WordProcessor::OnFontStyleStrikeoutCommand ()
3884 AssureCurSelFontCacheValid ();
3885 IncrementalFontSpecification applyFontSpec;
3886 applyFontSpec.SetStyle_Strikeout (not(fCachedCurSelFontSpec.GetStyle_Strikeout_Valid () and fCachedCurSelFontSpec.GetStyle_Strikeout ()));
3887 InteractiveSetFont (applyFontSpec);
3892void WordProcessor::OnUpdateFontStyleSubscriptCommand (CommandUpdater* enabler)
3895 AssureCurSelFontCacheValid ();
3896 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_SubOrSuperScript_Valid () and
3897 fCachedCurSelFontSpec.GetStyle_SubOrSuperScript () == FontSpecification::eSubscript);
3898 enabler->SetEnabled (
true);
3901void WordProcessor::OnFontStyleSubscriptCommand ()
3903 AssureCurSelFontCacheValid ();
3904 IncrementalFontSpecification applyFontSpec;
3905 applyFontSpec.SetStyle_SubOrSuperScript ((fCachedCurSelFontSpec.GetStyle_SubOrSuperScript_Valid () and
3906 fCachedCurSelFontSpec.GetStyle_SubOrSuperScript () == FontSpecification::eSubscript)
3907 ? FontSpecification::eNoSubOrSuperscript
3909 InteractiveSetFont (applyFontSpec);
3912void WordProcessor::OnUpdateFontStyleSuperscriptCommand (CommandUpdater* enabler)
3915 AssureCurSelFontCacheValid ();
3916 enabler->SetChecked (fCachedCurSelFontSpec.GetStyle_SubOrSuperScript_Valid () and
3917 fCachedCurSelFontSpec.GetStyle_SubOrSuperScript () == FontSpecification::eSuperscript);
3918 enabler->SetEnabled (
true);
3921void WordProcessor::OnFontStyleSuperscriptCommand ()
3923 AssureCurSelFontCacheValid ();
3924 IncrementalFontSpecification applyFontSpec;
3925 applyFontSpec.SetStyle_SubOrSuperScript ((fCachedCurSelFontSpec.GetStyle_SubOrSuperScript_Valid () and
3926 fCachedCurSelFontSpec.GetStyle_SubOrSuperScript () == FontSpecification::eSuperscript)
3927 ? FontSpecification::eNoSubOrSuperscript
3929 InteractiveSetFont (applyFontSpec);
3932void WordProcessor::OnUpdateChooseFontCommand (CommandUpdater* enabler)
3935 enabler->SetEnabled (
true);
3938void WordProcessor::OnChooseFontCommand ()
3940 IncrementalFontSpecification curSelFontSpec = GetCurSelFontSpec ();
3941 if (GetDialogSupport ().ChooseFont (&curSelFontSpec)) {
3942 InteractiveSetFont (curSelFontSpec);
3946void WordProcessor::OnUpdateFontSizeChangeCommand (CommandUpdater* enabler)
3949 DistanceType chosenFontSize = GetDialogSupport ().FontCmdToSize (enabler->GetCmdID ());
3951 AssureCurSelFontCacheValid ();
3952 if (chosenFontSize == 0) {
3953 switch (enabler->GetCmdID ()) {
3954 case kFontSizeSmaller_CmdID:
3955 case kFontSizeLarger_CmdID: {
3956 enabler->SetEnabled (
true);
3959 case kFontSizeOther_CmdID: {
3960 enabler->SetEnabled (
true);
3961 if (fCachedCurSelFontSpec.GetPointSize_Valid ()) {
3962 int pointSize = fCachedCurSelFontSpec.GetPointSize ();
3963 if (not GetDialogSupport ().IsPredefinedFontSize (pointSize)) {
3964 enabler->SetChecked (
true);
3965 enabler->SetText (Characters::CString::Format (GetCommandNames ().fFontSizeChange_Other_OneArg.c_str (), pointSize).c_str ());
3969 enabler->SetChecked (
false);
3970 enabler->SetText (GetCommandNames ().fFontSizeChange_Other_NoArg.c_str ());
3975 enabler->SetChecked (fCachedCurSelFontSpec.GetPointSize_Valid () and fCachedCurSelFontSpec.GetPointSize () == chosenFontSize);
3976 enabler->SetEnabled (
true);
3980void WordProcessor::OnFontSizeChangeCommand (CommandNumber cmdNum)
3982 DistanceType chosenFontSize = GetDialogSupport ().FontCmdToSize (cmdNum);
3983 if (chosenFontSize == 0) {
3985 case kFontSizeSmaller_CmdID: {
3986 IncrementalFontSpecification applyFontSpec;
3987 applyFontSpec.SetPointSizeIncrement (-1);
3988 InteractiveSetFont (applyFontSpec);
3991 case kFontSizeLarger_CmdID: {
3992 IncrementalFontSpecification applyFontSpec;
3993 applyFontSpec.SetPointSizeIncrement (1);
3994 InteractiveSetFont (applyFontSpec);
3997 case kFontSizeOther_CmdID: {
3998 DistanceType oldSize = fCachedCurSelFontSpec.GetPointSize_Valid () ? fCachedCurSelFontSpec.GetPointSize () : 0;
3999 chosenFontSize = GetDialogSupport ().PickOtherFontHeight (oldSize);
4003 if (chosenFontSize != 0) {
4004 IncrementalFontSpecification applyFontSpec;
4005 applyFontSpec.SetPointSize (
static_cast<unsigned short> (chosenFontSize));
4006 InteractiveSetFont (applyFontSpec);
4010void WordProcessor::OnUpdateFontColorChangeCommand (CommandUpdater* enabler)
4013 Require (enabler->GetCmdID () >= kBaseFontColor_CmdID and enabler->GetCmdID () <= kLastFontColor_CmdID);
4014 AssureCurSelFontCacheValid ();
4015 if (fCachedCurSelFontSpec.GetTextColor_Valid ()) {
4016 if (enabler->GetCmdID () == kFontColorOther_CmdID) {
4018 enabler->SetChecked (GetDialogSupport ().FontColorToCmd (fCachedCurSelFontSpec.GetTextColor ()) == kFontColorOther_CmdID);
4021 enabler->SetChecked (fCachedCurSelFontSpec.GetTextColor () == GetDialogSupport ().FontCmdToColor (enabler->GetCmdID ()));
4025 enabler->SetChecked (
false);
4027 enabler->SetEnabled (
true);
4030void WordProcessor::OnFontColorChangeCommand (CommandNumber cmdNum)
4032 Require (cmdNum >= kBaseFontColor_CmdID and cmdNum <= kLastFontColor_CmdID);
4034 AssureCurSelFontCacheValid ();
4035 IncrementalFontSpecification applyFontSpec;
4036 if (cmdNum == kFontColorOther_CmdID) {
4037 Color originalColor = GetDefaultFont ().GetTextColor ();
4038 if (fCachedCurSelFontSpec.GetTextColor_Valid ()) {
4039 originalColor = fCachedCurSelFontSpec.GetTextColor ();
4041 Color chosenColor = originalColor;
4042 if (GetDialogSupport ().PickOtherFontColor (&chosenColor)) {
4043 applyFontSpec.SetTextColor (chosenColor);
4050 Color chosenColor = GetDialogSupport ().FontCmdToColor (cmdNum);
4051 if (fCachedCurSelFontSpec.GetTextColor_Valid () and fCachedCurSelFontSpec.GetTextColor () == chosenColor) {
4052 applyFontSpec.SetTextColor (Color::kBlack);
4055 applyFontSpec.SetTextColor (chosenColor);
4058 InteractiveSetFont (applyFontSpec);
4061void WordProcessor::OnUpdateInsertTableCommand (CommandUpdater* enabler)
4066 enabler->SetEnabled (GetSelectionStart () == GetSelectionEnd ());
4069void WordProcessor::OnInsertTableCommand ()
4073 if (GetDialogSupport ().AddNewTableDialog (&rows, &cols)) {
4076 Assert (rows < 1000);
4077 Assert (cols < 100);
4079 InteractiveModeUpdater iuMode (*
this);
4082 TextStore::SimpleUpdater updater1 (GetTextStore (), GetSelectionStart (), GetSelectionEnd ());
4084 BreakInGroupedCommands ();
4085 UndoableContextHelper context (*
this, GetCommandNames ().fInsertTableCommandName,
false);
4088 WordProcessorTable* t = InsertTable (GetSelectionStart ());
4090 t->SetDimensions (rows, cols);
4092 for (
size_t r = 0; r < rows; ++r) {
4093 for (
size_t c = 0; c < cols; ++c) {
4094 TWIPS targetWidth = TWIPS{0};
4096 CoordinateType lhs = 0;
4097 CoordinateType rhs = 0;
4098 GetLayoutMargins (GetRowReferenceContainingPosition (t->GetStart ()), &lhs, &rhs);
4100 targetWidth = Led_CvtScreenPixelsToTWIPSH (rhs - lhs);
4101 targetWidth = TWIPS ((targetWidth / 5) * 4);
4103 t->SetColumnWidth (r, c, TWIPS (
static_cast<long> (targetWidth / cols)));
4105 TextStore* ts =
nullptr;
4106 t->GetCellWordProcessorDatabases (r, c, &ts);
4110 TextStore::SimpleUpdater updater (GetTextStore (), t->GetStart (), t->GetEnd ());
4111 SetSelection (t->GetEnd (), t->GetEnd ());
4113 context.CommandComplete ();
4114 BreakInGroupedCommands ();
4118void WordProcessor::OnUpdateInsertURLCommand (CommandUpdater* enabler)
4121 enabler->SetEnabled (GetSelectionStart () == GetSelectionEnd ());
4126void WordProcessor::OnInsertURLCommand ()
4128 InteractiveModeUpdater iuMode (*
this);
4129 BreakInGroupedCommands ();
4132 if (GetDialogSupport ().ShowAddURLEmbeddingInfoDialog (&title, &url)) {
4133 UndoableContextHelper context{*
this, GetCommandNames ().fInsertURLCommandName,
false};
4135 SimpleEmbeddedObjectStyleMarker* e =
new StandardURLStyleMarker{
4136 Led_URLD{String::FromSDKString (url).AsNarrowSDKString ().c_str (), String::FromSDKString (title).AsNarrowSDKString ().c_str ()}};
4137 AddEmbedding (e, GetTextStore (), GetSelectionStart (), GetStyleDatabase ().get ());
4138 SetSelection (e->GetEnd (), e->GetEnd ());
4140 context.CommandComplete ();
4142 BreakInGroupedCommands ();
4145void WordProcessor::OnUpdateInsertSymbolCommand ([[maybe_unused]] CommandUpdater* enabler)
4148#if qStroika_Platform_Windows
4149 enabler->SetEnabled (
true);
4155void WordProcessor::OnInsertSymbolCommand ()
4157#if qStroika_Platform_Windows
4158 (void)::ShellExecute (
nullptr, Led_SDK_TCHAROF (
"open"), Led_SDK_TCHAROF (
"CHARMAP.EXE"),
nullptr, Led_SDK_TCHAROF (
""), SW_SHOWNORMAL);
4164void WordProcessor::OnUpdateSelectedEmbeddingExtendedCommand (CommandUpdater* enabler)
4167 SimpleEmbeddedObjectStyleMarker* embedding = GetSoleSelectedEmbedding ();
4168 if (enabler->GetCmdID () == kSelectedEmbeddingProperties_CmdID) {
4169 enabler->SetEnabled (embedding !=
nullptr);
4170 WordProcessorTable* t = GetActiveTable ();
4171 enabler->SetText (t ==
nullptr ? GetCommandNames ().fGenericEmbeddingPropertiesCommandName.c_str ()
4172 : GetCommandNames ().fTablePropertiesCommandName.c_str ());
4175 using PrivateCmdNumber = SimpleEmbeddedObjectStyleMarker::PrivateCmdNumber;
4176 PrivateCmdNumber cmdNum =
4177 static_cast<PrivateCmdNumber
> (enabler->GetCmdID () - kFirstPrivateEmbedding_CmdID + SimpleEmbeddedObjectStyleMarker::eMinPrivateCmdNum);
4178 enabler->SetEnabled (embedding !=
nullptr and embedding->IsCmdEnabled (cmdNum));
4179 if (embedding !=
nullptr) {
4180 enabler->SetText (embedding->GetCmdText (cmdNum).c_str ());
4185bool WordProcessor::OnSelectedEmbeddingExtendedCommand (CommandNumber cmdNum)
4187 Require (cmdNum >= kFirstSelectedEmbedding_CmdID and cmdNum <= kLastSelectedEmbedding_CmdID);
4188 SimpleEmbeddedObjectStyleMarker* embedding = GetSoleSelectedEmbedding ();
4189 if (embedding ==
nullptr) {
4192 if (cmdNum == kSelectedEmbeddingProperties_CmdID) {
4193 if (
dynamic_cast<StandardURLStyleMarker*
> (embedding) !=
nullptr) {
4194 StandardURLStyleMarker* e =
dynamic_cast<StandardURLStyleMarker*
> (embedding);
4195 SDKString title = String::FromNarrowSDKString (e->GetURLData ().GetTitle ()).AsSDKString ();
4196 SDKString url = String::FromNarrowSDKString (e->GetURLData ().GetURL ()).AsSDKString ();
4197 if (GetDialogSupport ().ShowURLEmbeddingInfoDialog (GetPrettyTypeName (embedding), &title, &url)) {
4200 TextStore::SimpleUpdater updater (GetTextStore (), e->GetStart (), e->GetEnd ());
4201 e->SetURLData (Led_URLD{String::FromSDKString (url).AsNarrowSDKString ().c_str (),
4202 String::FromSDKString (title).AsNarrowSDKString ().c_str ()});
4206 else if (
dynamic_cast<WordProcessorTable*
> (embedding) !=
nullptr) {
4207 OnEditTablePropertiesDialog ();
4211 GetDialogSupport ().ShowSimpleEmbeddingInfoDialog (GetPrettyTypeName (embedding));
4215 using PrivateCmdNumber = SimpleEmbeddedObjectStyleMarker::PrivateCmdNumber;
4216 PrivateCmdNumber pCmdNum =
4217 static_cast<PrivateCmdNumber
> (cmdNum - kFirstPrivateEmbedding_CmdID + SimpleEmbeddedObjectStyleMarker::eMinPrivateCmdNum);
4218 embedding->DoCommand (pCmdNum);
4223void WordProcessor::OnEditTablePropertiesDialog ()
4225 WordProcessorTable* t = GetActiveTable ();
4232 DialogSupport::TableSelectionPropertiesInfo info;
4233 info.fTableBorderWidth = t->GetTableBorderWidth ();
4234 info.fTableBorderColor = t->GetTableBorderColor ();
4235 t->GetDefaultCellMargins (&info.fDefaultCellMargins.top, &info.fDefaultCellMargins.left, &info.fDefaultCellMargins.bottom,
4236 &info.fDefaultCellMargins.right);
4237 info.fCellSpacing = t->GetCellSpacing ();
4239 size_t rowSelStart = 0;
4240 size_t rowSelEnd = 0;
4241 size_t colSelStart = 0;
4242 size_t colSelEnd = 0;
4243 t->GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
4244 info.fCellWidth_Common =
false;
4245 info.fCellBackgroundColor_Common =
false;
4246 for (
size_t r = rowSelStart; r < rowSelEnd; ++r) {
4247 for (
size_t c = colSelStart; c < colSelEnd; ++c) {
4248 if (c < t->GetColumnCount (r)) {
4249 TWIPS cellWidth = t->GetColumnWidth (r, c);
4250 Color cellBkgrnd = t->GetCellColor (r, c);
4251 if (r == rowSelStart and c == colSelStart) {
4252 info.fCellWidth_Common =
true;
4253 info.fCellWidth = cellWidth;
4254 info.fCellBackgroundColor_Common =
true;
4255 info.fCellBackgroundColor = cellBkgrnd;
4258 if (info.fCellWidth_Common) {
4259 if (info.fCellWidth != cellWidth) {
4260 info.fCellWidth_Common =
false;
4263 if (info.fCellBackgroundColor_Common) {
4264 if (info.fCellBackgroundColor != cellBkgrnd) {
4265 info.fCellBackgroundColor_Common =
false;
4273 if (GetDialogSupport ().EditTablePropertiesDialog (&info)) {
4274 UndoableContextHelper context (*
this, GetCommandNames ().fChangeTablePropertiesCommandName,
false);
4276 t->SetTableBorderWidth (info.fTableBorderWidth);
4277 t->SetTableBorderColor (info.fTableBorderColor);
4278 t->SetDefaultCellMargins (info.fDefaultCellMargins.top, info.fDefaultCellMargins.left, info.fDefaultCellMargins.bottom,
4279 info.fDefaultCellMargins.right);
4280 t->SetCellSpacing (info.fCellSpacing);
4282 size_t rowSelStart = 0;
4283 size_t rowSelEnd = 0;
4284 size_t colSelStart = 0;
4285 size_t colSelEnd = 0;
4286 t->GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
4287 for (
size_t r = rowSelStart; r < rowSelEnd; ++r) {
4288 for (
size_t c = colSelStart; c < colSelEnd; ++c) {
4289 if (c < t->GetColumnCount (r)) {
4290 if (info.fCellWidth_Common) {
4291 t->SetColumnWidth (r, c, info.fCellWidth);
4293 if (info.fCellBackgroundColor_Common) {
4294 t->SetCellColor (r, c, info.fCellBackgroundColor);
4301 context.CommandComplete ();
4305void WordProcessor::OnUpdateHideSelectionCommands (CommandUpdater* enabler)
4308 bool enabled = GetSelectionStart () != GetSelectionEnd ();
4311 if (enabler->GetCmdID () == kHideSelection_CmdID) {
4312 enabled = not GetHidableTextDatabase ()->GetHidableRegionsContiguous (GetSelectionStart (), GetSelectionEnd (),
true);
4314 else if (enabler->GetCmdID () == kUnHideSelection_CmdID) {
4315 enabled = not GetHidableTextDatabase ()->GetHidableRegionsContiguous (GetSelectionStart (), GetSelectionEnd (),
false);
4318 enabler->SetEnabled (enabled);
4321void WordProcessor::OnHideSelection ()
4323 InterectiveSetRegionHidable (
true);
4326void WordProcessor::OnUnHideSelection ()
4328 InterectiveSetRegionHidable (
false);
4331void WordProcessor::OnUpdateParagraphJustificationCommand (CommandUpdater* enabler)
4335 AssureCurSelFontCacheValid ();
4337 switch (enabler->GetCmdID ()) {
4338 case kJustifyLeft_CmdID: {
4339 enabler->SetChecked (fCachedCurSelJustificationUnique and (fCachedCurSelJustification == eLeftJustify));
4341 case kJustifyCenter_CmdID: {
4342 enabler->SetChecked (fCachedCurSelJustificationUnique and (fCachedCurSelJustification == eCenterJustify));
4344 case kJustifyRight_CmdID: {
4345 enabler->SetChecked (fCachedCurSelJustificationUnique and (fCachedCurSelJustification == eRightJustify));
4347 case kJustifyFull_CmdID: {
4348 enabler->SetChecked (fCachedCurSelJustificationUnique and (fCachedCurSelJustification == eFullyJustify));
4351 enabler->SetEnabled (
true);
4354void WordProcessor::OnParagraphJustificationCommand (CommandNumber cmdNum)
4357 case kJustifyLeft_CmdID: {
4358 InteractiveSetJustification (eLeftJustify);
4360 case kJustifyCenter_CmdID: {
4361 InteractiveSetJustification (eCenterJustify);
4363 case kJustifyRight_CmdID: {
4364 InteractiveSetJustification (eRightJustify);
4366 case kJustifyFull_CmdID: {
4367 InteractiveSetJustification (eFullyJustify);
4375void WordProcessor::OnUpdateParagraphSpacingChangeCommand (CommandUpdater* enabler)
4378 enabler->SetEnabled (
true);
4381void WordProcessor::OnParagraphSpacingChangeCommand ()
4383 TWIPS spaceBefore = TWIPS{0};
4384 TWIPS spaceAfter = TWIPS{0};
4385 LineSpacing lineSpacing;
4387 bool spaceBeforeValid = GetSpaceBefore (GetSelectionStart (), GetSelectionEnd (), &spaceBefore);
4388 bool spaceAfterValid = GetSpaceAfter (GetSelectionStart (), GetSelectionEnd (), &spaceAfter);
4389 bool lineSpacingValid = GetLineSpacing (GetSelectionStart (), GetSelectionEnd (), &lineSpacing);
4391 if (GetDialogSupport ().PickNewParagraphLineSpacing (&spaceBefore, &spaceBeforeValid, &spaceAfter, &spaceAfterValid, &lineSpacing, &lineSpacingValid)) {
4392 if (spaceBeforeValid) {
4394 InteractiveSetParagraphSpacing (spaceBefore, spaceBeforeValid, spaceAfter, spaceAfterValid, lineSpacing, lineSpacingValid);
4398void WordProcessor::OnUpdateParagraphIndentsChangeCommand (CommandUpdater* enabler)
4401 enabler->SetEnabled (
true);
4404void WordProcessor::OnParagraphIndentsChangeCommand ()
4406 TWIPS leftMargin = TWIPS{0};
4407 TWIPS rightMargin = TWIPS{0};
4408 TWIPS firstIndent = TWIPS{0};
4411 bool leftMarginValid = GetMargins (GetSelectionStart (), GetSelectionEnd (), &leftMargin, &rightMargin);
4412 bool rightMarginValid = leftMarginValid;
4413 bool firstIndentValid = GetFirstIndent (GetSelectionStart (), GetSelectionEnd (), &firstIndent);
4415 if (GetDialogSupport ().PickNewParagraphMarginsAndFirstIndent (&leftMargin, &leftMarginValid, &rightMargin, &rightMarginValid,
4416 &firstIndent, &firstIndentValid)) {
4420 InteractiveSetMarginsAndFirstIndent (leftMargin, rightMargin, firstIndent);
4424void WordProcessor::OnUpdateListStyleChangeCommand (CommandUpdater* enabler)
4427 ListStyle listStyle = eListStyle_None;
4428 bool listStyleValid = GetListStyle (GetSelectionStart (), GetSelectionEnd (), &listStyle);
4429 if (enabler->GetCmdID () == kListStyle_None_CmdID) {
4430 enabler->SetChecked (listStyleValid and listStyle == eListStyle_None);
4432 else if (enabler->GetCmdID () == kListStyle_Bullet_CmdID) {
4433 enabler->SetChecked (listStyleValid and listStyle == eListStyle_Bullet);
4438 enabler->SetEnabled (
true);
4441void WordProcessor::OnListStyleChangeCommand (CommandNumber cmdNum)
4443 if (cmdNum == kListStyle_None_CmdID) {
4444 InteractiveSetListStyle (eListStyle_None);
4446 else if (cmdNum == kListStyle_Bullet_CmdID) {
4447 InteractiveSetListStyle (eListStyle_Bullet);
4454void WordProcessor::OnUpdateIndentCommand (CommandUpdater* enabler)
4457 ListStyle listStyle = eListStyle_None;
4458 bool listStyleValid = GetListStyle (GetSelectionStart (), GetSelectionEnd (), &listStyle);
4459 if (enabler->GetCmdID () == kIncreaseIndent_CmdID) {
4460 enabler->SetEnabled (listStyleValid and listStyle != eListStyle_None);
4462 else if (enabler->GetCmdID () == kDecreaseIndent_CmdID) {
4463 enabler->SetEnabled (listStyleValid and listStyle != eListStyle_None);
4470void WordProcessor::OnIndentCommand (CommandNumber cmdNum)
4472 if (cmdNum == kIncreaseIndent_CmdID) {
4473 InteractiveDoIndentChange (
true);
4475 else if (cmdNum == kDecreaseIndent_CmdID) {
4476 InteractiveDoIndentChange (
false);
4483void WordProcessor::OnUpdateShowHideGlyphCommand (CommandUpdater* enabler)
4486 Require (enabler->GetCmdID () >= kFirstShowHideGlyph_CmdID);
4487 Require (enabler->GetCmdID () <= kLastShowHideGlyph_CmdID);
4490 if (enabler->GetCmdID () == kShowHideParagraphGlyphs_CmdID) {
4491 enabler->SetChecked (GetShowParagraphGlyphs ());
4493 else if (enabler->GetCmdID () == kShowHideTabGlyphs_CmdID) {
4494 enabler->SetChecked (GetShowTabGlyphs ());
4496 else if (enabler->GetCmdID () == kShowHideSpaceGlyphs_CmdID) {
4497 enabler->SetChecked (GetShowSpaceGlyphs ());
4502 enabler->SetEnabled (
true);
4505void WordProcessor::OnShowHideGlyphCommand (CommandNumber cmdNum)
4507 Require (cmdNum >= kFirstShowHideGlyph_CmdID);
4508 Require (cmdNum <= kLastShowHideGlyph_CmdID);
4511 if (cmdNum == kShowHideParagraphGlyphs_CmdID) {
4512 SetShowParagraphGlyphs (not GetShowParagraphGlyphs ());
4514 else if (cmdNum == kShowHideTabGlyphs_CmdID) {
4515 SetShowTabGlyphs (not GetShowTabGlyphs ());
4517 else if (cmdNum == kShowHideSpaceGlyphs_CmdID) {
4518 SetShowSpaceGlyphs (not GetShowSpaceGlyphs ());
4525SDKString WordProcessor::GetPrettyTypeName (SimpleEmbeddedObjectStyleMarker* m)
4527 if (
dynamic_cast<StandardDIBStyleMarker*
> (m) !=
nullptr) {
4528 return GetCommandNames ().fEmbeddingTypeName_ImageDIB;
4530 else if (
dynamic_cast<StandardURLStyleMarker*
> (m) !=
nullptr) {
4531 return GetCommandNames ().fEmbeddingTypeName_URL;
4533#if qStroika_Platform_Windows
4534 else if (
dynamic_cast<StandardMacPictureStyleMarker*
> (m) !=
nullptr) {
4535 return GetCommandNames ().fEmbeddingTypeName_ImageMacPict;
4538 else if (
dynamic_cast<WordProcessorTable*
> (m) !=
nullptr) {
4539 return GetCommandNames ().fEmbeddingTypeName_Table;
4542 return GetCommandNames ().fEmbeddingTypeName_Unknown;
4546SimpleEmbeddedObjectStyleMarker* WordProcessor::GetSoleSelectedEmbedding ()
const
4548 size_t selStart = GetSelectionStart ();
4549 size_t selEnd = GetSelectionEnd ();
4550 Require (selStart <= selEnd);
4551 if (selEnd - selStart == 1) {
4552 vector<SimpleEmbeddedObjectStyleMarker*> embeddings = CollectAllEmbeddingMarkersInRange (selStart, selEnd);
4553 if (embeddings.size () == 1) {
4554 return (
dynamic_cast<SimpleEmbeddedObjectStyleMarker*
> (embeddings[0]));
4571Led_tString WordProcessor::GetListLeader (
size_t paragraphMarkerPos)
const
4573 if (fParagraphDatabase.get () ==
nullptr) {
4574 throw NoParagraphDatabaseAvailable ();
4576 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (paragraphMarkerPos);
4577 if (pi.GetListStyle () == eListStyle_None) {
4578 return Led_tString{};
4581 const Led_tChar kBulletChar = 0x2022;
4584 return Led_tString{&kBulletChar, 1} + LED_TCHAR_OF (
"\t");
4593DistanceType WordProcessor::GetListLeaderLength (
size_t paragraphMarkerPos)
const
4595 if (fParagraphDatabase.get () ==
nullptr) {
4596 throw NoParagraphDatabaseAvailable ();
4599 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (paragraphMarkerPos);
4600 TWIPS lhsTWIPS = pi.GetLeftMargin ();
4601 lhsTWIPS += pi.GetFirstIndent ();
4603 Tablet_Acquirer tablet_ (
this);
4604 Tablet* tablet = tablet_;
4605 CoordinateType lhs = tablet->CvtFromTWIPSH (lhsTWIPS);
4606 Led_tString leader = GetListLeader (paragraphMarkerPos);
4608 size_t len = leader.length ();
4616 useBulletFont.SetPointSize (max (
static_cast<unsigned short> (14), nextCharsFontStyle.GetPointSize ()));
4617 MeasureSegmentWidth_ (useBulletFont, paragraphMarkerPos, paragraphMarkerPos + len, leader.c_str (), distanceResults.data ());
4618 (void)ResetTabStopsWithMargin (lhs, paragraphMarkerPos, leader.c_str (), len, distanceResults.data (), 0);
4619 DistanceType result = distanceResults[len - 1];
4624InteractiveReplaceCommand::SavedTextRep* WordProcessor::InteractiveUndoHelperMakeTextRep (
size_t regionStart,
size_t regionEnd,
size_t selStart,
size_t selEnd)
4626 using SavedTextRep = InteractiveReplaceCommand::SavedTextRep;
4627 if (regionStart == regionEnd) {
4628 return new EmptySelectionParagraphSavedTextRep (
this, selStart, selEnd, regionStart);
4631 SavedTextRep* basicRep = inherited::InteractiveUndoHelperMakeTextRep (regionStart, regionEnd, selStart, selEnd);
4632 WordProcessorTable* aT = GetActiveTable ();
4633 if (aT !=
nullptr) {
4634 return new WordProcessorTable::SavedTextRepWSel (basicRep, *aT, WordProcessorTable::SavedTextRepWSel::eWPAbove);
4644void WordProcessor::InteractiveSetFont (
const IncrementalFontSpecification& defaultFont)
4646 WordProcessorTable* aT = GetActiveTable ();
4647 if (aT !=
nullptr) {
4648 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*aT, *
this);
4649 aT->InteractiveSetFont (defaultFont);
4652 inherited::InteractiveSetFont (defaultFont);
4659void WordProcessor::InteractiveSetJustification (Justification justification)
4661 Justification oldJustification;
4662 if (not GetJustification (GetSelectionStart (), GetSelectionEnd (), &oldJustification) or (oldJustification != justification)) {
4663 InteractiveWPHelper1<DoIt_SetJustification> (
this, justification);
4671void WordProcessor::InteractiveSetStandardTabStopList (StandardTabStopList tabStops)
4673 StandardTabStopList oldTabs;
4674 if (not GetStandardTabStopList (GetSelectionStart (), GetSelectionEnd (), &oldTabs) or (oldTabs != tabStops)) {
4675 InteractiveWPHelper1<DoIt_SetStandardTabStopList> (
this, tabStops);
4683void WordProcessor::InteractiveSetMargins (TWIPS leftMargin, TWIPS rightMargin)
4685 TWIPS oldLeftMargin = TWIPS{0};
4686 TWIPS oldRightMargin = TWIPS{0};
4687 if (not GetMargins (GetSelectionStart (), GetSelectionEnd (), &oldLeftMargin, &oldRightMargin) or
4688 ((oldLeftMargin != leftMargin) or (oldRightMargin != rightMargin))) {
4689 InteractiveWPHelper1<DoIt_SetMargins> (
this, DoIt_SetMargins::Margins (leftMargin, rightMargin));
4697void WordProcessor::InteractiveSetFirstIndent (TWIPS firstIndent)
4699 TWIPS oldFirstIndent = TWIPS{0};
4700 if (not GetFirstIndent (GetSelectionStart (), GetSelectionEnd (), &oldFirstIndent) or (oldFirstIndent != firstIndent)) {
4701 InteractiveWPHelper1<DoIt_SetFirstIndent> (
this, firstIndent);
4710void WordProcessor::InteractiveSetMarginsAndFirstIndent (TWIPS leftMargin, TWIPS rightMargin, TWIPS firstIndent)
4712 TWIPS oldLeftMargin = TWIPS{0};
4713 TWIPS oldRightMargin = TWIPS{0};
4714 TWIPS oldFirstIndent = TWIPS{0};
4715 if (not GetMargins (GetSelectionStart (), GetSelectionEnd (), &oldLeftMargin, &oldRightMargin) or
4716 ((oldLeftMargin != leftMargin) or (oldRightMargin != rightMargin)) or
4717 not GetFirstIndent (GetSelectionStart (), GetSelectionEnd (), &oldFirstIndent) or (oldFirstIndent != firstIndent)) {
4718 InteractiveWPHelper1<DoIt_SetMarginsAndFirstIndent> (
4719 this, DoIt_SetMarginsAndFirstIndent::MarginsAndFirstIndent (leftMargin, rightMargin, firstIndent));
4727void WordProcessor::InteractiveSetParagraphSpacing (TWIPS spaceBefore,
bool spaceBeforeValid, TWIPS spaceAfter,
bool spaceAfterValid,
4728 LineSpacing lineSpacing,
bool lineSpacingValid)
4733 TWIPS oldSpaceBefore = TWIPS{0};
4734 TWIPS oldSpaceAfter = TWIPS{0};
4735 LineSpacing oldLineSpacing;
4736 if (not GetSpaceBefore (GetSelectionStart (), GetSelectionEnd (), &oldSpaceBefore) or (oldSpaceBefore != spaceBefore) or
4737 not GetSpaceAfter (GetSelectionStart (), GetSelectionEnd (), &oldSpaceAfter) or (oldSpaceAfter != spaceAfter) or
4738 not GetLineSpacing (GetSelectionStart (), GetSelectionEnd (), &oldLineSpacing) or (oldLineSpacing != lineSpacing)) {
4739 InteractiveWPHelper1<DoIt_SetParagraphSpacing> (
4740 this, DoIt_SetParagraphSpacing::AllSpacingArgs (spaceBefore, spaceBeforeValid, spaceAfter, spaceAfterValid, lineSpacing, lineSpacingValid));
4748void WordProcessor::InteractiveSetListStyle (ListStyle listStyle)
4753 ListStyle oldListStyle = eListStyle_None;
4754 if (not GetListStyle (GetSelectionStart (), GetSelectionEnd (), &oldListStyle) or oldListStyle != listStyle) {
4755 InteractiveWPHelper1<DoIt_SetListStyle> (
this, listStyle);
4763void WordProcessor::InteractiveDoIndentChange (
bool increase)
4765 InteractiveWPHelper1<DoIt_IndentUnIndentList> (
this, increase);
4772const TabStopList& WordProcessor::GetTabStopList (
size_t containingPos)
const
4774 return fParagraphDatabase->GetParagraphInfo (containingPos).GetTabStopList ();
4777void WordProcessor::DrawBefore (
const Led_Rect& subsetToDraw,
bool printing)
4779 size_t winStart = GetMarkerPositionOfStartOfWindow ();
4780 size_t winEnd = GetMarkerPositionOfEndOfWindow ();
4784 vector<WordProcessorTable*> tables = GetTablesInRange (winStart, winEnd);
4785 for (
auto i = tables.begin (); i != tables.end (); ++i) {
4786 WordProcessorTable* t = *i;
4787 if (t->fNeedLayout != WordProcessorTable::eDone) {
4788 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*t, *
this);
4789 t->PerformLayout ();
4792 inherited::DrawBefore (subsetToDraw, printing);
4799void WordProcessor::DrawRowSegments (Tablet* tablet,
const Led_Rect& currentRowRect,
const Led_Rect& invalidRowRect,
4800 const TextLayoutBlock& text,
size_t rowStart,
size_t rowEnd)
4802 if (fParagraphDatabase.get () ==
nullptr) {
4803 throw NoParagraphDatabaseAvailable ();
4805 RowReference row = GetRowReferenceContainingPosition (rowStart);
4806 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (rowStart);
4808 Led_Rect adjustedDrawInto = currentRowRect;
4810 CoordinateType lhsMargin = 0;
4811 GetLayoutMargins (row, &lhsMargin,
nullptr);
4812 adjustedDrawInto += Led_Point (0, lhsMargin);
4816 if (row.GetSubRow () == 0) {
4817 ListStyle ls = pi.GetListStyle ();
4818 if (ls != eListStyle_None) {
4822 bool allowLists =
true;
4823 if (rowEnd - rowStart == 1) {
4824 vector<WordProcessorTable*> tables = GetTablesInRange (rowStart, rowEnd);
4825 if (tables.size () == 1) {
4831 Led_Rect xxx = adjustedDrawInto;
4832 Led_tString listLeader = GetListLeader (rowStart);
4833 xxx.SetLeft (xxx.GetLeft () - GetListLeaderLength (rowStart));
4836 useBulletFont.SetPointSize (max (
static_cast<unsigned short> (14), nextCharsFontStyle.GetPointSize ()));
4837 CoordinateType baseLine = xxx.GetTop () + MeasureSegmentBaseLine (rowStart, rowStart);
4838 DrawSegment_ (tablet, useBulletFont, rowStart, rowStart + listLeader.length (),
4839 TextLayoutBlock_Basic (listLeader.c_str (), listLeader.c_str () + listLeader.length ()), xxx, baseLine,
nullptr);
4845 switch (pi.GetJustification ()) {
4846 case eCenterJustify: {
4847 adjustedDrawInto.SetLeft (adjustedDrawInto.GetLeft () + CalcSpaceToEat (rowStart) / 2);
4849 case eRightJustify: {
4850 adjustedDrawInto.SetLeft (adjustedDrawInto.GetLeft () + CalcSpaceToEat (rowStart));
4853 if (not adjustedDrawInto.IsEmpty ()) {
4854 inherited::DrawRowSegments (tablet, adjustedDrawInto, invalidRowRect, text, rowStart, rowEnd);
4855 if (GetShowParagraphGlyphs ()) {
4857 PartitionElementCacheInfo pmCacheInfo = GetPartitionElementCacheInfo (GetPartitionMarkerContainingPosition (rowStart));
4858 if (row.GetSubRow () + 1 == pmCacheInfo.GetRowCount () and rowEnd < GetEnd ()) {
4859 const Led_tChar newline =
'\n';
4862 useFont.SetPointSize (max (
static_cast<unsigned short> (14), nextCharsFontStyle.GetPointSize ()));
4863 useFont.SetTextColor (Color::kGray);
4864 Led_Rect yyy = adjustedDrawInto;
4865 DistanceType segmentWidth = CalcSegmentSize (rowStart, rowEnd);
4866 yyy.left += segmentWidth;
4867 CoordinateType baseLine = yyy.GetTop () + MeasureSegmentBaseLine (rowStart, rowStart);
4868 DrawSegment_ (tablet, useFont, rowEnd, rowEnd + 1, TextLayoutBlock_Basic (&newline, &newline + 1), yyy, baseLine,
nullptr);
4878vector<Led_Rect> WordProcessor::GetRowHilightRects (
const TextLayoutBlock& text,
size_t rowStart,
size_t rowEnd,
size_t hilightStart,
size_t hilightEnd)
const
4880 size_t len = rowEnd - rowStart;
4881 if (len == 1 and text.PeekAtRealText ()[0] == kEmbeddingSentinelChar) {
4882 vector<WordProcessorTable*> tables = GetTablesInRange (rowStart, rowEnd);
4883 Assert (tables.size () <= 1);
4884 if (not tables.empty ()) {
4885 WordProcessorTable* table = tables[0];
4886 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*table, *
const_cast<WordProcessor*
> (
this));
4887 return table->GetRowHilightRects ();
4890 return inherited::GetRowHilightRects (text, rowStart, rowEnd, hilightStart, hilightEnd);
4893void WordProcessor::DrawSegment (Tablet* tablet,
size_t from,
size_t to,
const TextLayoutBlock& text,
const Led_Rect& drawInto,
4894 const Led_Rect& invalidRect, CoordinateType useBaseLine, DistanceType* pixelsDrawn)
4896 DistanceType pixelsDrawn_;
4897 if (GetShowTabGlyphs ()) {
4898 if (pixelsDrawn ==
nullptr) {
4900 pixelsDrawn = &pixelsDrawn_;
4904 inherited::DrawSegment (tablet, from, to, text, drawInto, invalidRect, useBaseLine, pixelsDrawn);
4907 if (GetShowTabGlyphs () and GetJustification (from) == eLeftJustify) {
4908 for (
size_t i = from; i < to; ++i) {
4909 if (text.PeekAtVirtualText ()[i - from] ==
'\t') {
4911 DistanceType beforeTabPos = drawInto.GetLeft () + CalcSegmentSize (from, i);
4913 DistanceType afterTabPos = drawInto.GetLeft () + CalcSegmentSize (from, i + 1);
4914 Assert (beforeTabPos < afterTabPos);
4915 Led_Rect tabRect = drawInto;
4916 tabRect.SetLeft (beforeTabPos);
4917 tabRect.SetRight (afterTabPos);
4918 Assert (tabRect.GetLeft () < tabRect.GetRight ());
4921 Color arrowColor = GetEffectiveDefaultTextColor (eDefaultTextColor);
4923 Led_Rect arrowBody = tabRect;
4924 arrowBody.left += 2;
4925 arrowBody.right -= 2;
4926 arrowBody.top += arrowBody.GetHeight () / 2;
4927 arrowBody.bottom = arrowBody.top + 1;
4928 arrowBody.bottom = min (arrowBody.bottom, drawInto.bottom);
4929 tablet->EraseBackground_SolidHelper (arrowBody, arrowColor);
4932 const CoordinateType kArrowHSize = 8;
4933 const CoordinateType kArrowVSize = 8;
4934 Led_Point tip = arrowBody.GetTopRight ();
4935 CoordinateType hTriangleBase = max (arrowBody.right - kArrowHSize, arrowBody.left);
4936 Led_Point topPt = Led_Point (max (arrowBody.GetTop () - kArrowVSize / 2, tabRect.top), hTriangleBase);
4937 Led_Point botPt = Led_Point (min (arrowBody.GetTop () + kArrowVSize / 2, tabRect.bottom), hTriangleBase);
4938#if qStroika_Platform_Windows
4939 Brush backgroundBrush (arrowColor.GetOSRep ());
4940 GDI_Obj_Selector pen (tablet, ::GetStockObject (NULL_PEN));
4941 GDI_Obj_Selector brush (tablet, backgroundBrush);
4943 pts[0] = AsPOINT (tip);
4944 pts[1] = AsPOINT (topPt);
4945 pts[2] = AsPOINT (botPt);
4946 Verify (::Polygon (*tablet, pts,
static_cast<int> (std::size (pts))));
4953 tablet->EraseBackground_SolidHelper (tabRect, Color::kRed);
4960DistanceType WordProcessor::MeasureSegmentHeight (
size_t from,
size_t to)
const
4962 Tablet_Acquirer tablet_ (
this);
4963 Tablet* tablet = tablet_;
4964 DistanceType d = inherited::MeasureSegmentHeight (from, to);
4967 shared_ptr<HidableTextMarkerOwner> hdb = GetHidableTextDatabase ();
4968 if (hdb.get () !=
nullptr) {
4969 DiscontiguousRun<bool> regions = hdb->GetHidableRegions (from, to);
4970 if (not regions.empty ()) {
4971 if (not regions[0].fData) {
4978 PartitionMarker* pm = GetPartitionMarkerContainingPosition (from);
4979 size_t pmStart = pm->GetStart ();
4980 size_t pmEnd = pm->GetEnd ();
4986 if (pmEnd - pmStart == 1) {
4987 vector<WordProcessorTable*> tables = GetTablesInRange (pmStart, pmEnd);
4988 if (tables.size () == 1) {
4990 WordProcessorTable* t = tables[0];
4991 Assert (t->GetStart () == pmStart);
4992 Assert (t->GetEnd () == pmEnd);
4998 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (from);
5000 LineSpacing sl = pi.GetLineSpacing ();
5002 case LineSpacing::eOnePointFiveSpace:
5006 case LineSpacing::eDoubleSpace:
5009 case LineSpacing::eAtLeastTWIPSSpacing:
5010 d = max (DistanceType (tablet->CvtFromTWIPSV (TWIPS (sl.fArg))), d);
5012 case LineSpacing::eExactTWIPSSpacing:
5013 d = tablet->CvtFromTWIPSV (TWIPS (sl.fArg));
5015 case LineSpacing::eExactLinesSpacing:
5021 case LineSpacing::eSingleSpace:
5026 bool isStartOfPara = pmStart == from;
5027 if (isStartOfPara) {
5028 d += tablet->CvtFromTWIPSV (pi.GetSpaceBefore ());
5032 bool isEndOfPara = pmEnd <= to + 1;
5034 d += tablet->CvtFromTWIPSV (pi.GetSpaceAfter ());
5040DistanceType WordProcessor::MeasureMinSegDescent (
size_t from,
size_t to)
const
5046 Require (from <= to);
5051 vector<StyleRunElement> outputSummary = SummarizeStyleMarkers (from, to);
5053 size_t outputSummaryLength = outputSummary.size ();
5054 Assert (outputSummaryLength != 0);
5055 DistanceType minHeightBelow = 0;
5056 size_t indexIntoText = 0;
5057 for (
size_t i = 0; i < outputSummaryLength; ++i) {
5058 const StyleRunElement& re = outputSummary[i];
5059 size_t reFrom = indexIntoText + from;
5060 size_t reLength = re.fLength;
5061 size_t reTo = reFrom + reLength;
5062 Assert (indexIntoText <= to - from);
5063 DistanceType itsBaseline;
5064 DistanceType itsHeight;
5065 if (re.fMarker ==
nullptr) {
5066 itsBaseline = MeasureSegmentBaseLine_ (GetDefaultFont (), reFrom, reTo);
5067 itsHeight = MeasureSegmentHeight_ (GetDefaultFont (), reFrom, reTo);
5070 itsBaseline = re.fMarker->MeasureSegmentBaseLine (
this, re, reFrom, reTo);
5071 itsHeight = re.fMarker->MeasureSegmentHeight (
this, re, reFrom, reTo);
5073 minHeightBelow = min (minHeightBelow, (itsHeight - itsBaseline));
5074 indexIntoText += reLength;
5076 return minHeightBelow;
5079void WordProcessor::AdjustBestRowLength (
size_t textStart,
const Led_tChar* text,
const Led_tChar* end,
size_t* rowLength)
5083 Require (text < end);
5085 Require (*rowLength > 0);
5086 inherited::AdjustBestRowLength (textStart, text, end, rowLength);
5087 for (
const Led_tChar* cur = &text[0]; cur < end; cur = Led_NextChar (cur)) {
5088 if (*cur == kEmbeddingSentinelChar) {
5090 vector<WordProcessorTable*> tables = GetTablesInRange (textStart + cur - text, textStart + cur - text + 1);
5091 if (not tables.empty ()) {
5092 Assert (cur == text);
5093 size_t newBestRowLength = (cur - text) + 1;
5094 Assert (newBestRowLength <= *rowLength + 1);
5099 Assert (newBestRowLength >= 1);
5100 *rowLength = newBestRowLength;
5109DistanceType WordProcessor::MeasureSegmentBaseLine (
size_t from,
size_t to)
const
5115 DistanceType d = inherited::MeasureSegmentBaseLine (from, to);
5118 shared_ptr<HidableTextMarkerOwner> hdb = GetHidableTextDatabase ();
5119 if (hdb.get () !=
nullptr) {
5120 DiscontiguousRun<bool> regions = hdb->GetHidableRegions (from, to);
5121 if (not regions.empty ()) {
5122 if (not regions[0].fData) {
5129 PartitionMarker* pm = GetPartitionMarkerContainingPosition (from);
5130 size_t pmStart = pm->GetStart ();
5131 size_t pmEnd = pm->GetEnd ();
5137 if (pmEnd - pmStart == 1) {
5138 vector<WordProcessorTable*> tables = GetTablesInRange (pmStart, pmEnd);
5139 if (tables.size () == 1) {
5141 WordProcessorTable* t = tables[0];
5142 Assert (t->GetStart () == pmStart);
5143 Assert (t->GetEnd () == pmEnd);
5158 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (from);
5160 LineSpacing sl = pi.GetLineSpacing ();
5162 case LineSpacing::eExactTWIPSSpacing: {
5163 Tablet_Acquirer tablet_ (
this);
5164 Tablet* tablet = tablet_;
5165 DistanceType revisedSegHeight = tablet->CvtFromTWIPSV (TWIPS (sl.fArg));
5166 DistanceType mhb = MeasureMinSegDescent (from, to);
5167 d = revisedSegHeight - mhb;
5169 case LineSpacing::eExactLinesSpacing: {
5171 Tablet_Acquirer tablet_ (
this);
5172 DistanceType normalSegHeight = inherited::MeasureSegmentHeight (from, to);
5173 DistanceType revisedSegHeight = normalSegHeight * sl.fArg / 20;
5174 DistanceType mhb = MeasureMinSegDescent (from, to);
5175 d = revisedSegHeight - mhb;
5184 bool isStartOfPara = pmStart == from;
5185 if (isStartOfPara) {
5186 TWIPS sb = pi.GetSpaceBefore ();
5188 Tablet_Acquirer tablet_ (
this);
5189 Tablet* tablet = tablet_;
5190 d += tablet->CvtFromTWIPSV (sb);
5203void WordProcessor::SetShowParagraphGlyphs (
bool showParagraphGlyphs)
5205 if (fShowParagraphGlyphs != showParagraphGlyphs) {
5206 fShowParagraphGlyphs = showParagraphGlyphs;
5207 InvalidateAllCaches ();
5219void WordProcessor::SetShowTabGlyphs (
bool showTabGlyphs)
5221 if (fShowTabGlyphs != showTabGlyphs) {
5222 fShowTabGlyphs = showTabGlyphs;
5234void WordProcessor::SetShowSpaceGlyphs (
bool showSpaceGlyphs)
5236 if (fShowSpaceGlyphs != showSpaceGlyphs) {
5237 fShowSpaceGlyphs = showSpaceGlyphs;
5238 InvalidateAllCaches ();
5243size_t WordProcessor::ComputeRelativePosition (
size_t fromPos, CursorMovementDirection direction, CursorMovementUnit movementUnit)
5245 size_t result = inherited::ComputeRelativePosition (fromPos, direction, movementUnit);
5252 shared_ptr<HidableTextMarkerOwner> hdb = GetHidableTextDatabase ();
5253 if (hdb.get () ==
nullptr) {
5255 if (direction == eCursorBack or direction == eCursorToStart) {
5256 DiscontiguousRun<bool> regions = hdb->GetHidableRegions (FindPreviousCharacter (result), result);
5257 if (not regions.empty ()) {
5260 if (not regions[0].fData) {
5261 result = FindPreviousCharacter (result);
5267 DiscontiguousRun<bool> regions = hdb->GetHidableRegions (result, FindNextCharacter (result));
5268 if (not regions.empty ()) {
5271 if (not regions[0].fData) {
5272 result = FindNextCharacter (result);
5286bool WordProcessor::ContainsMappedDisplayCharacters (
const Led_tChar* text,
size_t nTChars)
const
5288 if (fShowParagraphGlyphs and nTChars > 0 and text[nTChars - 1] ==
'\n') {
5291 if (fShowSpaceGlyphs and nTChars > 0 and ContainsMappedDisplayCharacters_HelperForChar (text, nTChars,
' ')) {
5294 return inherited::ContainsMappedDisplayCharacters (text, nTChars);
5301void WordProcessor::ReplaceMappedDisplayCharacters (
const Led_tChar* srcText, Led_tChar* copyText,
size_t nTChars)
const
5303 inherited::ReplaceMappedDisplayCharacters (srcText, copyText, nTChars);
5304 if (fShowParagraphGlyphs and nTChars > 0 and srcText[nTChars - 1] ==
'\n') {
5306 const Led_tChar kReplacementChar = 0x00b6;
5307 copyText[nTChars - 1] = kReplacementChar;
5309 if (fShowSpaceGlyphs) {
5311 const Led_tChar kReplacementChar = 0x00b7;
5312 ReplaceMappedDisplayCharacters_HelperForChar (copyText, nTChars,
' ', kReplacementChar);
5321Led_Rect WordProcessor::GetCharLocationRowRelative (
size_t afterPosition, RowReference topRow,
size_t maxRowsToCheck)
const
5323 Led_Rect r = inherited::GetCharLocationRowRelative (afterPosition, topRow, maxRowsToCheck);
5326 CoordinateType lhsMargin = 0;
5327 RowReference row = GetRowReferenceContainingPosition (afterPosition);
5328 GetLayoutMargins (row, &lhsMargin,
nullptr);
5329 r.left += lhsMargin;
5330 r.right += lhsMargin;
5333 Justification justification = GetJustification (afterPosition);
5334 if (justification == eCenterJustify or justification == eRightJustify) {
5335 switch (justification) {
5336 case eCenterJustify: {
5337 DistanceType d = CalcSpaceToEat (afterPosition) / 2;
5341 case eRightJustify: {
5342 DistanceType d = CalcSpaceToEat (afterPosition);
5356size_t WordProcessor::GetCharAtLocationRowRelative (
const Led_Point& where, RowReference topRow,
size_t maxRowsToCheck)
const
5359 size_t posInRow = inherited::GetCharAtLocationRowRelative (where, topRow, maxRowsToCheck);
5360 RowReference row = GetRowReferenceContainingPosition (posInRow);
5361 Led_Point adjustedWhere = where;
5363 CoordinateType lhsMargin = 0;
5364 GetLayoutMargins (row, &lhsMargin,
nullptr);
5365 adjustedWhere.h -= lhsMargin;
5367 Justification justification = GetJustification (posInRow);
5368 switch (justification) {
5369 case eCenterJustify: {
5370 adjustedWhere.h -= CalcSpaceToEat (posInRow) / 2;
5372 case eRightJustify: {
5373 adjustedWhere.h -= CalcSpaceToEat (posInRow);
5376 return inherited::GetCharAtLocationRowRelative (adjustedWhere, topRow, maxRowsToCheck);
5386size_t WordProcessor::ResetTabStops (
size_t from,
const Led_tChar* text,
size_t nTChars, DistanceType* charLocations,
size_t startSoFar)
const
5388 CoordinateType lhsMargin = 0;
5390 RowReference row = GetRowReferenceContainingPosition (from);
5391 GetLayoutMargins (row, &lhsMargin,
nullptr);
5393 return ResetTabStopsWithMargin (lhsMargin, from, text, nTChars, charLocations, startSoFar);
5396size_t WordProcessor::ResetTabStopsWithMargin (DistanceType lhsMargin,
size_t from,
const Led_tChar* text,
size_t nTChars,
5397 DistanceType* charLocations,
size_t startSoFar)
const
5400 size_t lastTabIndex = 0;
5401 CoordinateType tabAdjust = 0;
5402 DistanceType widthAtStart = (startSoFar == 0 ? 0 : charLocations[startSoFar - 1]);
5403 for (
size_t i = startSoFar; i < startSoFar + nTChars; ++i) {
5404 if (text[i] ==
'\t') {
5405 DistanceType widthSoFar = (i == 0 ? 0 : charLocations[i - 1]);
5406 tabAdjust = widthAtStart +
5407 GetTabStopList (from).ComputeTabStopAfterPosition (Tablet_Acquirer (
this), widthSoFar - widthAtStart + lhsMargin) -
5408 lhsMargin - charLocations[i];
5411 charLocations[i] += tabAdjust;
5413 return (lastTabIndex);
5421void WordProcessor::GetLayoutMargins (RowReference row, CoordinateType* lhs, CoordinateType* rhs)
const
5423 if (fParagraphDatabase.get () ==
nullptr) {
5424 throw NoParagraphDatabaseAvailable ();
5427 PartitionMarker* pm = row.GetPartitionMarker ();
5428 size_t pmStart = pm->GetStart ();
5430 Tablet_Acquirer tablet_ (
this);
5431 Tablet* tablet = tablet_;
5433 ParagraphInfo pi = fParagraphDatabase->GetParagraphInfo (pmStart);
5434 if (lhs !=
nullptr) {
5435 TWIPS lhsTWIPS = pi.GetLeftMargin ();
5436 if (row.GetSubRow () == 0) {
5437 lhsTWIPS += pi.GetFirstIndent ();
5439 *lhs = tablet->CvtFromTWIPSH (lhsTWIPS);
5440 if (row.GetSubRow () == 0) {
5441 ListStyle ls = pi.GetListStyle ();
5442 if (ls != eListStyle_None) {
5446 bool allowLists =
true;
5447 size_t pmEnd = pm->GetEnd ();
5448 if (pmEnd - pmStart == 1) {
5449 vector<WordProcessorTable*> tables = GetTablesInRange (pmStart, pmEnd);
5450 if (tables.size () == 1) {
5455 *lhs += GetListLeaderLength (pmStart);
5460 if (rhs !=
nullptr) {
5461 *rhs = tablet->CvtFromTWIPSH (pi.GetRightMargin ());
5465void WordProcessor::ExpandedFromAndToInPostReplace (
size_t from,
size_t newTo,
size_t stableTypingRegionStart,
size_t stableTypingRegionEnd,
5466 size_t startPositionOfRowWhereReplaceBegins,
size_t startPositionOfRowAfterReplaceEnds,
5467 size_t* expandedFrom,
size_t* expandedTo)
5469 Justification justification = GetJustification (from);
5470 if (justification != eLeftJustify) {
5471 from = GetStartOfRowContainingPosition (from);
5473 inherited::ExpandedFromAndToInPostReplace (from, newTo, stableTypingRegionStart, stableTypingRegionEnd, startPositionOfRowWhereReplaceBegins,
5474 startPositionOfRowAfterReplaceEnds, expandedFrom, expandedTo);
5477void WordProcessor::PostReplace (PreReplaceInfo& preReplaceInfo)
5479 inherited::PostReplace (preReplaceInfo);
5480 UpdateMode updateMode = preReplaceInfo.GetUpdateMode ();
5481 if (updateMode != eNoUpdate) {
5482 if (preReplaceInfo.GetTo () + 2 >= GetEnd ()) {
5489 ListStyle ls = eListStyle_None;
5490 if (not WordProcessor::GetListStyle (preReplaceInfo.GetFrom (), GetEnd (), &ls) or ls != eListStyle_None) {
5491 Refresh (updateMode);
5497DistanceType WordProcessor::CalcSpaceToEat (
size_t rowContainingCharPos)
const
5499 size_t rowStart = GetStartOfRowContainingPosition (rowContainingCharPos);
5500 size_t rowEnd = GetEndOfRowContainingPosition (rowStart);
5501 Assert (rowEnd == GetEndOfRowContainingPosition (rowContainingCharPos));
5504 size_t lenOfText = rowEnd - rowStart;
5506 CopyOut (rowStart, lenOfText, buf.data ());
5508 while (rowStart < rowEnd) {
5509 size_t i = rowEnd - rowStart - 1;
5519 DistanceType segmentWidth = CalcSegmentSize (rowStart, rowEnd);
5520 DistanceType layoutWidth;
5522 CoordinateType lhsMargin = 0;
5523 CoordinateType rhsMargin = 0;
5524 GetLayoutMargins (GetRowReferenceContainingPosition (rowStart), &lhsMargin, &rhsMargin);
5525 Assert (lhsMargin < rhsMargin);
5526 layoutWidth = rhsMargin - lhsMargin;
5530 if (layoutWidth < segmentWidth) {
5534 Assert (layoutWidth >= segmentWidth);
5535 DistanceType xtra = layoutWidth - segmentWidth;
5544using WordProcessorFlavorPackageInternalizer = WordProcessor::WordProcessorFlavorPackageInternalizer;
5546WordProcessorFlavorPackageInternalizer::WordProcessorFlavorPackageInternalizer (TextStore& ts,
const shared_ptr<AbstractStyleDatabaseRep>& styleDatabase,
5547 const shared_ptr<AbstractParagraphDatabaseRep>& paragraphDatabase,
5548 const shared_ptr<HidableTextMarkerOwner>& hidableTextDatabase)
5550 , inherited (ts, styleDatabase)
5551 , fOverwriteTableMode (false)
5553#if !qStroika_Frameworks_Led_NestedTablesSupported
5554 fNoTablesAllowed (false)
5557 fParagraphDatabase (paragraphDatabase)
5558 , fHidableTextDatabase (hidableTextDatabase)
5566 sinkStream->SetIgnoreLastParaAttributes (
true);
5567 sinkStream->SetOverwriteTableMode (GetOverwriteTableMode ());
5568#if !qStroika_Frameworks_Led_NestedTablesSupported
5569 sinkStream->SetNoTablesAllowed (GetNoTablesAllowed ());
5580WordProcessor::WPPartition::WPPartition (TextStore& textStore,
MarkerOwner& tableMarkerOwner)
5581 : inherited{textStore, eSpecialHackToDisableInit}
5582 , fTableMarkerOwner{tableMarkerOwner}
5588vector<WordProcessorTable*> WordProcessor::WPPartition::GetTablesInRange (
size_t from,
size_t to)
const
5590 if (to ==
static_cast<size_t> (-1)) {
5591 to = GetTextStore ().GetLength ();
5593 Require (from <= to);
5594 Require (to <= GetTextStore ().GetLength () + 1);
5595 MarkersOfATypeMarkerSink2Vector<WordProcessorTable> result;
5596 GetTextStore ().CollectAllMarkersInRangeInto (from, to, &fTableMarkerOwner, result);
5597 return result.fResult;
5600WordProcessorTable* WordProcessor::GetActiveTable ()
const
5602 size_t selStart = 0;
5604 GetSelection (&selStart, &selEnd);
5605 if (selEnd - selStart == 1) {
5606 vector<WordProcessorTable*> tables = GetTablesInRange (selStart, selEnd);
5607 Assert (tables.size () <= 1);
5608 if (tables.size () == 1) {
5616void WordProcessor::WPPartition::FinalConstruct ()
5619 inherited::FinalConstruct ();
5620 DoHandleUpdateForTableRangeCheck (0, GetTextStore ().GetLength ());
5623void WordProcessor::WPPartition::DidUpdateText (
const UpdateInfo& updateInfo)
noexcept
5628 DoHandleUpdateForTableRangeCheck (updateInfo.fReplaceFrom, updateInfo.GetResultingRHS ());
5631 inherited::DidUpdateText (updateInfo);
5634void WordProcessor::WPPartition::DoHandleUpdateForTableRangeCheck (
size_t from,
size_t to)
noexcept
5636 TextStore& ts = GetTextStore ();
5639 vector<WordProcessorTable*> tables = GetTablesInRange (ts.FindPreviousCharacter (from), ts.FindNextCharacter (to));
5640 for (
auto i = tables.begin (); i != tables.end (); ++i) {
5641 WordProcessorTable* t = *i;
5642 if (t->GetLength () != 0) {
5643 size_t tableEnd = t->GetEnd ();
5646 size_t tableStart = t->GetStart ();
5647 PartitionMarker* pm = GetPartitionMarkerContainingPosition (tableStart);
5652 if (tableEnd < pm->GetEnd () and tableEnd > pm->GetStart ()) {
5653 Split (pm, tableEnd);
5655 if (tableStart > pm->GetStart () and tableStart < pm->GetEnd ()) {
5656 Split (pm, tableStart);
5660 bool coalesce = NeedToCoalesce (pm);
5664 pm = pm->GetPrevious ();
5665 if (pm !=
nullptr) {
5666 coalesce = NeedToCoalesce (pm);
5670 pm = pm->GetPrevious ();
5671 if (pm !=
nullptr) {
5672 coalesce = NeedToCoalesce (pm);
5681 PartitionMarker* pm = GetPartitionMarkerContainingPosition (from);
5683 bool coalesce = NeedToCoalesce (pm);
5687 pm = pm->GetPrevious ();
5688 if (pm !=
nullptr) {
5689 coalesce = NeedToCoalesce (pm);
5693 pm = pm->GetPrevious ();
5694 if (pm !=
nullptr) {
5695 coalesce = NeedToCoalesce (pm);
5703bool WordProcessor::WPPartition::NeedToCoalesce (PartitionMarker* pm)
noexcept
5707 bool coalesce = inherited::NeedToCoalesce (pm);
5715 if (pm->GetLength () != 0) {
5716 size_t end = pm->GetEnd ();
5717 size_t trStart = end - 1;
5719 if (pm->GetNext () !=
nullptr) {
5723 vector<WordProcessorTable*> tables = GetTablesInRange (trStart, trEnd);
5724 if (not tables.empty ()) {
5725 if (tables.size () == 2) {
5729 else if (tables.size () == 1) {
5730 WordProcessorTable* table = tables[0];
5732 if (table->GetStart () == pm->GetEnd ()) {
5735 else if (table->GetEnd () == pm->GetEnd ()) {
5745#if qStroika_Foundation_Debug_AssertionsChecked
5746void WordProcessor::WPPartition::Invariant_ ()
const
5748 Partition::Invariant_ ();
5756 for (PartitionMarker* cur = GetFirstPartitionMarker (); cur !=
nullptr; cur = cur->GetNext ()) {
5758 size_t start = cur->GetStart ();
5759 size_t end = cur->GetEnd ();
5760 size_t len = end - start;
5762 if (end > GetEnd ()) {
5766 CopyOut (start, len, buf.data ());
5767 for (
size_t i = 1; i < len; ++i) {
5768 Assert (buf[i - 1] !=
'\n');
5769 vector<WordProcessorTable*> tables = GetTablesInRange (start + i - 1, start + i);
5770 if (not tables.empty ()) {
5771 Assert (tables.size () == 1);
5772 WordProcessorTable* t = tables[0];
5773 if (t->GetLength () != 0) {
5774 Assert (t->GetStart () == start);
5775 Assert (t->GetLength () == len);
5779 if (cur->GetNext () !=
nullptr) {
5780 Assert (buf[len - 1] ==
'\n' or (not GetTablesInRange (start + len - 1, start + len).empty ()) or
5781 (start + len + 1 <= GetEnd () and not GetTablesInRange (start + len, start + len + 1).empty ()));
5787 vector<WordProcessorTable*> tables = GetTablesInRange (0, GetTextStore ().GetLength ());
5788 for (
auto i = tables.begin (); i != tables.end (); ++i) {
5789 WordProcessorTable* t = *i;
5790 if (t->GetLength () != 0) {
5791 PartitionMarker* pm = GetPartitionMarkerContainingPosition (t->GetStart ());
5792 Assert (t->GetStart () == pm->GetStart ());
5793 Assert (t->GetEnd () == pm->GetEnd ());
5804using WordProcessorFlavorPackageExternalizer = WordProcessor::WordProcessorFlavorPackageExternalizer;
5806WordProcessorFlavorPackageExternalizer::WordProcessorFlavorPackageExternalizer (TextStore& ts,
const shared_ptr<AbstractStyleDatabaseRep>& styleDatabase,
5807 const shared_ptr<AbstractParagraphDatabaseRep>& paragraphDatabase,
5808 const shared_ptr<HidableTextMarkerOwner>& hidableTextDatabase)
5810 , inherited (ts, styleDatabase)
5811 , fParagraphDatabase (paragraphDatabase)
5812 , fHidableTextDatabase (hidableTextDatabase)
5816StandardStyledTextIOSrcStream* WordProcessorFlavorPackageExternalizer::mkStandardStyledTextIOSrcStream (
size_t selectionStart,
size_t selectionEnd)
5819 fHidableTextDatabase, selectionStart, selectionEnd);
5820 stream->SetUseTableSelection (GetUseTableSelection ());
5824void WordProcessorTable::DrawSegment (
const StyledTextImager* imager,
const StyleRunElement& , Tablet* tablet,
5825 [[maybe_unused]]
size_t from, [[maybe_unused]]
size_t to, [[maybe_unused]]
const TextLayoutBlock& text,
5826 const Led_Rect& drawInto,
const Led_Rect& invalidRect, CoordinateType , DistanceType* pixelsDrawn)
5828 RequireMember (
const_cast<StyledTextImager*
> (imager), WordProcessor);
5829 Assert (from + 1 == to);
5831 Require (text.PeekAtVirtualText ()[0] == kEmbeddingSentinelChar);
5833 using TemporarilyUseTablet = EmbeddedTableWordProcessor::TemporarilyUseTablet;
5835 WordProcessor& owningWP = *
dynamic_cast<WordProcessor*
> (
const_cast<StyledTextImager*
> (imager));
5837 WordProcessorTable::TemporarilySetOwningWP owningWPSetter (*
this, owningWP);
5839 DistanceType bwv = Led_CvtScreenPixelsFromTWIPSV (fBorderWidth);
5840 Led_Rect rowRect = drawInto;
5842 size_t nRows = fRows.size ();
5843 for (
size_t ri = 0; ri < nRows; ++ri) {
5846 size_t nCols = GetColumnCount (ri);
5847 rowRect.bottom = rowRect.top + fRows[ri].fHeight;
5848 for (
size_t ci = 0; ci < nCols; ++ci) {
5849 if (GetCellFlags (ri, ci) == ePlainCell) {
5850 Led_Rect scrolledCBWR = TableCoordinates2Window (GetCellBounds (ri, ci));
5851 if (Intersect (scrolledCBWR, invalidRect)) {
5852 Led_Rect scrolledEditorCBWR = TableCoordinates2Window (GetCellEditorBounds (ri, ci));
5856 if (scrolledCBWR != scrolledEditorCBWR) {
5857 tablet->EraseBackground_SolidHelper (scrolledCBWR, GetCellColor (ri, ci));
5860 TemporarilyAllocateCellWP wp (*
this, owningWP, ri, ci, scrolledEditorCBWR);
5861 TemporarilyUseTablet tmpUseTablet (*wp, tablet, TemporarilyUseTablet::eDontDoTextMetricsChangedCall);
5862 wp->Draw (scrolledEditorCBWR,
false);
5863 DrawCellBorders (tablet, ri, ci, scrolledCBWR);
5869 if (scrolledCBWR.bottom < invalidRect.top) {
5872 if (scrolledCBWR.top > invalidRect.bottom) {
5878 rowRect.top = rowRect.bottom + bwv;
5882 DrawTableBorders (owningWP, tablet, drawInto);
5884 if (pixelsDrawn !=
nullptr) {
5885 *pixelsDrawn = fTotalWidth;
5889void WordProcessorTable::MeasureSegmentWidth ([[maybe_unused]]
const StyledTextImager* imager,
const StyleRunElement& ,
5890 [[maybe_unused]]
size_t from, [[maybe_unused]]
size_t to,
5891 [[maybe_unused]]
const Led_tChar* text, DistanceType* distanceResults)
const
5893 RequireMember (
const_cast<StyledTextImager*
> (imager), WordProcessor);
5894 Assert (from + 1 == to);
5896 distanceResults[0] = fTotalWidth;
5899DistanceType WordProcessorTable::MeasureSegmentHeight ([[maybe_unused]]
const StyledTextImager* imager,
const StyleRunElement& ,
5900 [[maybe_unused]]
size_t from, [[maybe_unused]]
size_t to)
const
5902 RequireMember (
const_cast<StyledTextImager*
> (imager), WordProcessor);
5903 Assert (from + 1 == to);
5906 return fTotalHeight == 0 ? 1 : fTotalHeight;
5914vector<Led_Rect> WordProcessorTable::GetRowHilightRects ()
const
5916 Led_Require_CurrentOwningWP ();
5918 vector<Led_Rect> result;
5920 size_t rowStart = GetStart ();
5921 size_t rowEnd = GetEnd ();
5922 size_t hilightStart = fCurrentOwningWP->GetSelectionStart ();
5923 size_t hilightEnd = fCurrentOwningWP->GetSelectionEnd ();
5924 bool segmentHilighted = max (rowStart, hilightStart) < min (rowEnd, hilightEnd);
5926 if (segmentHilighted) {
5927 Led_Rect tableRect = fCurrentOwningWP->GetIntraRowTextWindowBoundingRect (rowStart, rowEnd);
5928 vector<Led_Rect> hilightRects = fCurrentOwningWP->TextImager::GetRowHilightRects (
5929 TextLayoutBlock_Basic{&kEmbeddingSentinelChar, &kEmbeddingSentinelChar + 1}, rowStart, rowEnd, hilightStart, hilightEnd);
5933 if (rowStart != hilightStart or rowEnd != hilightEnd) {
5934 return hilightRects;
5941 for (
auto i = hilightRects.begin (); i != hilightRects.end (); ++i) {
5942 if (tableRect != *i) {
5943 if (not(*i).IsEmpty ()) {
5944 result.push_back (*i);
5953 size_t rowSelStart = 0;
5954 size_t rowSelEnd = 0;
5955 size_t colSelStart = 0;
5956 size_t colSelEnd = 0;
5957 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
5960 if (rowSelStart == 0 and rowSelEnd == GetRowCount () and colSelStart == 0 and colSelEnd == GetColumnCount ()) {
5961 return hilightRects;
5964 if (rowSelEnd - rowSelStart == 1 and colSelEnd - colSelStart == 1 and GetIntraCellMode ()) {
5965 TemporarilyAllocateCellWithTablet wp (*
const_cast<WordProcessorTable*
> (
this), rowSelStart, colSelStart);
5966 vector<Led_Rect> cellHilightRegions = wp->GetSelectionWindowRects (wp->GetSelectionStart (), wp->GetSelectionEnd ());
5967 for (
auto i = cellHilightRegions.begin (); i != cellHilightRegions.end (); ++i) {
5968 result.push_back (*i);
5972 for (
size_t ri = rowSelStart; ri < rowSelEnd; ++ri) {
5973 size_t thisRowEnd = min (colSelEnd, GetColumnCount (ri));
5974 for (
size_t ci = colSelStart; ci < thisRowEnd; ++ci) {
5975 if (GetCellFlags (ri, ci) == ePlainCell) {
5977 Led_Rect wRelCellRect = TableCoordinates2Window (GetCellBounds (ri, ci));
5978 if (not wRelCellRect.IsEmpty ()) {
5979 result.push_back (wRelCellRect);
5990 for (
auto orit = result.begin (); orit != result.end (); ++orit) {
5991 Ensure ((*orit).GetWidth () > 0);
5992 Ensure ((*orit).GetHeight () > 0);
5993 for (
auto irit = orit + 1; irit != result.end (); ++irit) {
5994 Led_Rect hr = *irit;
5995 Ensure (hr.GetWidth () > 0);
5996 Ensure (hr.GetHeight () > 0);
5997 Ensure (not Intersect (hr, *orit));
6010void WordProcessorTable::DrawTableBorders (WordProcessor& owningWP, Tablet* tablet,
const Led_Rect& drawInto)
6020 DistanceType bwh = Led_CvtScreenPixelsFromTWIPSH (fBorderWidth);
6023 Led_Rect bounds = drawInto - Led_Point (0, owningWP.GetHScrollPos ());
6024 bounds.right = bounds.left + fTotalWidth;
6025 bounds.bottom = bounds.top + fTotalHeight;
6026 tablet->FrameRectangle (bounds, fBorderColor, bwh);
6036void WordProcessorTable::DrawCellBorders (Tablet* tablet,
size_t ,
size_t ,
const Led_Rect& cellBounds)
6038 CoordinateType bw = Led_CvtScreenPixelsFromTWIPSH (fBorderWidth);
6040 tablet->FrameRectangle (InsetRect (cellBounds, -bw, -bw), fBorderColor, bw);
6051Led_Rect WordProcessorTable::GetCellBounds (
size_t row,
size_t column)
const
6053 Require (GetCellFlags (row, column) == ePlainCell);
6054 return GetCell (row, column).GetCachedBoundsRect ();
6063Led_Rect WordProcessorTable::GetCellEditorBounds (
size_t row,
size_t column)
const
6065 Require (GetCellFlags (row, column) == ePlainCell);
6066 Led_Rect cellBounds = GetCellBounds (row, column);
6067 Led_Rect cellEditBounds = cellBounds;
6068 TWIPS_Rect defaultCellMarginTWIPS;
6069 GetDefaultCellMargins (&defaultCellMarginTWIPS.top, &defaultCellMarginTWIPS.left, &defaultCellMarginTWIPS.bottom,
6070 &defaultCellMarginTWIPS.right);
6071 cellEditBounds.top += Led_CvtScreenPixelsFromTWIPSV (defaultCellMarginTWIPS.top);
6072 cellEditBounds.left += Led_CvtScreenPixelsFromTWIPSH (defaultCellMarginTWIPS.left);
6073 cellEditBounds.bottom -= Led_CvtScreenPixelsFromTWIPSV (defaultCellMarginTWIPS.bottom);
6074 cellEditBounds.right -= Led_CvtScreenPixelsFromTWIPSH (defaultCellMarginTWIPS.right);
6076 cellEditBounds.bottom = max (cellEditBounds.bottom, cellEditBounds.top + 1);
6077 cellEditBounds.right = max (cellEditBounds.right, cellEditBounds.left + 1);
6078 return cellEditBounds;
6086void WordProcessorTable::GetClosestCell (
const Led_Point& p,
size_t* row,
size_t* col)
const
6091 Led_Size border = Led_Size (Led_CvtScreenPixelsFromTWIPSV (fBorderWidth), Led_CvtScreenPixelsFromTWIPSH (fBorderWidth));
6092 DistanceType spacing = Led_CvtScreenPixelsFromTWIPSV (GetCellSpacing ());
6095 size_t rowCount = GetRowCount ();
6096 Assert (rowCount > 0);
6097 CoordinateType top = spacing + border.v;
6099 for (; ri < rowCount; ++ri) {
6100 DistanceType h = fRows[ri].fHeight;
6101 CoordinateType bottom = top + h;
6107 top += spacing + border.v;
6109 if (ri >= rowCount) {
6115 size_t colCount = GetColumnCount (ri);
6116 Assert (colCount > 0);
6118 for (; ci < colCount; ++ci) {
6121 GetRealCell (&rri, &cci);
6122 Led_Rect bounds = GetCellBounds (rri, cci);
6124 if (p.h < bounds.GetRight ()) {
6128 if (ci >= colCount) {
6134Led_Point WordProcessorTable::TableCoordinates2Window (
const Led_Point& p)
const
6136 Led_Require_CurrentOwningWP ();
6137 Led_Point tableWROrigin = fCurrentOwningWP->GetCharWindowLocation (GetStart ()).GetTopLeft ();
6138 return p + tableWROrigin;
6141Led_Rect WordProcessorTable::TableCoordinates2Window (
const Led_Rect& r)
const
6143 return Led_Rect (TableCoordinates2Window (r.GetOrigin ()), r.GetSize ());
6146Led_Point WordProcessorTable::WindowCoordinates2Table (
const Led_Point& p)
const
6148 Led_Require_CurrentOwningWP ();
6149 Led_Point tableWROrigin = fCurrentOwningWP->GetCharWindowLocation (GetStart ()).GetTopLeft ();
6150 return p - tableWROrigin;
6153Led_Rect WordProcessorTable::WindowCoordinates2Table (
const Led_Rect& r)
const
6155 return Led_Rect (WindowCoordinates2Table (r.GetOrigin ()), r.GetSize ());
6158bool WordProcessorTable::GetCaretShownSituation ()
const
6160 if (GetIntraCellMode ()) {
6161 size_t selStart = 0;
6163 GetIntraCellSelection (&selStart, &selEnd);
6164 return selStart == selEnd;
6173Led_Rect WordProcessorTable::CalculateCaretRect ()
const
6175 Led_Require_CurrentOwningWP ();
6176 if (GetIntraCellMode ()) {
6177 size_t selStart = 0;
6179 GetIntraCellSelection (&selStart, &selEnd);
6180 if (selStart == selEnd) {
6183 (void)GetIntraCellMode (&row, &col);
6184 TemporarilyAllocateCellWithTablet wp (*
const_cast<WordProcessorTable*
> (
this), row, col);
6185 return wp->CalculateCaretRect ();
6188 return (Led_Rect (0, 0, 0, 0));
6191bool WordProcessorTable::OnTypedNormalCharacter (Led_tChar theChar,
bool optionPressed,
bool shiftPressed,
bool commandPressed,
6192 bool controlPressed,
bool altKeyPressed)
6194 using InteractiveModeUpdater = WordProcessor::InteractiveModeUpdater;
6195 using UndoableContextHelper = WordProcessor::UndoableContextHelper;
6196 Led_Require_CurrentOwningWP ();
6198 size_t rowSelStart = 0;
6199 size_t rowSelEnd = 0;
6200 size_t colSelStart = 0;
6201 size_t colSelEnd = 0;
6202 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6204 if (theChar ==
'\b') {
6206 if (rowSelStart == 0 and rowSelEnd == GetRowCount () and colSelStart == 0 and colSelEnd == GetColumnCount () and not fIntraCellMode) {
6211 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6212 AllowUpdateInfoPropagationContext AUIPC (*
this);
6213 if (not fIntraCellMode) {
6216 UndoableContextHelper undoContext (*fCurrentOwningWP, TextInteractor::GetCommandNames ().fTypingCommandName,
false);
6218 (void)OnPerformCommand_ApplyToEachSelectedCell (TextInteractor::kClear_CmdID,
false);
6220 undoContext.CommandComplete ();
6221 SetIntraCellMode (rowSelStart, colSelStart);
6224 Assert (fIntraCellMode);
6225 TemporarilyAllocateCellWithTablet wp (*
this, rowSelStart, colSelStart);
6226 wp->OnTypedNormalCharacter (theChar, optionPressed, shiftPressed, commandPressed, controlPressed, altKeyPressed);
6231bool WordProcessorTable::DoSingleCharCursorEdit (TextInteractor::CursorMovementDirection direction,
6232 TextInteractor::CursorMovementUnit movementUnit, TextInteractor::CursorMovementAction action,
6233 TextInteractor::UpdateMode updateMode,
bool scrollToSelection)
6237 if (GetIntraCellMode (&row, &col)) {
6239 AllowUpdateInfoPropagationContext AUIPC (*
this);
6240 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6241 wp->DoSingleCharCursorEdit (direction, movementUnit, action, updateMode, scrollToSelection);
6247bool WordProcessorTable::OnUpdateCommand (TextInteractor::CommandUpdater* enabler)
6249 Led_Require_CurrentOwningWP ();
6254 if (GetIntraCellMode (&row, &col)) {
6255 if (fCurrentOwningWP->PassAlongCommandToIntraCellModeTableCell (enabler->GetCmdID ())) {
6256 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6257 [[maybe_unused]]
bool result = wp->OnUpdateCommand (enabler);
6258 if (enabler->GetCmdID () == WordProcessor::kSelectedEmbeddingProperties_CmdID and not enabler->GetEnabled ()) {
6266 switch (enabler->GetCmdID ()) {
6267 case WordProcessor::kCut_CmdID: {
6268 OnUpdateCutCommand (enabler);
6271 case WordProcessor::kInsertTableRowAbove_CmdID: {
6272 OnUpdateInsertTableRowAboveCommand (enabler);
6275 case WordProcessor::kInsertTableRowBelow_CmdID: {
6276 OnUpdateInsertTableRowBelowCommand (enabler);
6279 case WordProcessor::kInsertTableColBefore_CmdID: {
6280 OnUpdateInsertTableColBeforeCommand (enabler);
6283 case WordProcessor::kInsertTableColAfter_CmdID: {
6284 OnUpdateInsertTableColAfterCommand (enabler);
6287 case WordProcessor::kRemoveTableColumns_CmdID: {
6288 OnUpdateRemoveTableColumnsCommand (enabler);
6291 case WordProcessor::kRemoveTableRows_CmdID: {
6292 OnUpdateRemoveTableRowsCommand (enabler);
6295 case WordProcessor::kSelectTableIntraCellAll_CmdID:
6296 case WordProcessor::kSelectTableCell_CmdID:
6297 case WordProcessor::kSelectTableRow_CmdID:
6298 case WordProcessor::kSelectTableColumn_CmdID:
6299 case WordProcessor::kSelectTable_CmdID: {
6300 OnUpdateSelectTablePartsCommand (enabler);
6305 if (fCurrentOwningWP->PassAlongCommandToEachSelectedTableCell (enabler->GetCmdID ())) {
6306 return OnUpdateCommand_ApplyToEachSelectedCell (enabler);
6312bool WordProcessorTable::OnPerformCommand (TextInteractor::CommandNumber commandNumber)
6314 Led_Require_CurrentOwningWP ();
6316 AllowUpdateInfoPropagationContext AUIPC (*
this);
6320 if (GetIntraCellMode (&row, &col)) {
6321 if (fCurrentOwningWP->PassAlongCommandToIntraCellModeTableCell (commandNumber)) {
6322 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6323 return wp->OnPerformCommand (commandNumber);
6327 switch (commandNumber) {
6328 case WordProcessor::kCut_CmdID: {
6332 case WordProcessor::kInsertTableRowAbove_CmdID: {
6333 OnInsertTableRowAboveCommand ();
6336 case WordProcessor::kInsertTableRowBelow_CmdID: {
6337 OnInsertTableRowBelowCommand ();
6340 case WordProcessor::kInsertTableColBefore_CmdID: {
6341 OnInsertTableColBeforeCommand ();
6344 case WordProcessor::kInsertTableColAfter_CmdID: {
6345 OnInsertTableColAfterCommand ();
6348 case WordProcessor::kRemoveTableColumns_CmdID: {
6349 OnRemoveTableColumnsCommand ();
6352 case WordProcessor::kRemoveTableRows_CmdID: {
6353 OnRemoveTableRowsCommand ();
6356 case WordProcessor::kSelectTableIntraCellAll_CmdID:
6357 case WordProcessor::kSelectTableCell_CmdID:
6358 case WordProcessor::kSelectTableRow_CmdID:
6359 case WordProcessor::kSelectTableColumn_CmdID:
6360 case WordProcessor::kSelectTable_CmdID: {
6361 OnPerformTablePartsCommand (commandNumber);
6366 if (fCurrentOwningWP->PassAlongCommandToEachSelectedTableCell (commandNumber)) {
6367 return OnPerformCommand_ApplyToEachSelectedCell (commandNumber);
6373void WordProcessorTable::BreakInGroupedCommands ()
6375 Led_Require_CurrentOwningWP ();
6376 fCurrentOwningWP->BreakInGroupedCommands ();
6379bool WordProcessorTable::OnUpdateCommand_ApplyToEachSelectedCell (TextInteractor::CommandUpdater* enabler)
6382 Led_Require_CurrentOwningWP ();
6384 bool result =
false;
6385 size_t rowSelStart = 0;
6386 size_t rowSelEnd = 0;
6387 size_t colSelStart = 0;
6388 size_t colSelEnd = 0;
6389 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6390 for (
size_t ri = rowSelStart; ri < rowSelEnd; ++ri) {
6391 size_t thisRowEnd = min (colSelEnd, GetColumnCount (ri));
6392 for (
size_t ci = colSelStart; ci < thisRowEnd; ++ci) {
6393 TemporarilyAllocateCellWithTablet wp (*
this, ri, ci);
6394 wp->SetSelection (0, wp->GetEnd (), TextInteractor::eNoUpdate);
6395 result = result or wp->OnUpdateCommand (enabler);
6401bool WordProcessorTable::OnPerformCommand_ApplyToEachSelectedCell (TextInteractor::CommandNumber commandNumber,
bool captureChangesForUndo)
6403 Led_Require_CurrentOwningWP ();
6404 if (captureChangesForUndo) {
6405 fCurrentOwningWP->BreakInGroupedCommands ();
6407 bool result =
false;
6408 size_t rowSelStart = 0;
6409 size_t rowSelEnd = 0;
6410 size_t colSelStart = 0;
6411 size_t colSelEnd = 0;
6412 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6413 for (
size_t ri = rowSelStart; ri < rowSelEnd; ++ri) {
6414 size_t thisRowEnd = min (colSelEnd, GetColumnCount (ri));
6415 for (
size_t ci = colSelStart; ci < thisRowEnd; ++ci) {
6416 TemporarilyAllocateCellWithTablet wp (*
this, ri, ci, captureChangesForUndo);
6417 wp->SetSelection (0, wp->GetEnd (), TextInteractor::eNoUpdate);
6418 TextInteractor::SuppressCommandBreaksContext SCBC (*wp);
6419 wp->OnPerformCommand (commandNumber);
6423 if (captureChangesForUndo) {
6424 fCurrentOwningWP->BreakInGroupedCommands ();
6429void WordProcessorTable::OnUpdateCutCommand (TextInteractor::CommandUpdater* enabler)
6432 Led_Require_CurrentOwningWP ();
6433 size_t rowSelStart = 0;
6434 size_t rowSelEnd = 0;
6435 size_t colSelStart = 0;
6436 size_t colSelEnd = 0;
6437 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6438 enabler->SetEnabled (rowSelStart != rowSelEnd and colSelStart != colSelEnd);
6441void WordProcessorTable::OnCutCommand ()
6443 Led_Require_CurrentOwningWP ();
6444 AllowUpdateInfoPropagationContext AUIPC (*
this);
6445 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6446 Assert (fCurrentOwningWP->GetSelectionEnd () - fCurrentOwningWP->GetSelectionStart () == 1);
6447 fCurrentOwningWP->OnCopyCommand ();
6448 UndoableContextHelper undoContext (*fCurrentOwningWP, TextInteractor::GetCommandNames ().fCutCommandName,
true);
6450 (void)OnPerformCommand_ApplyToEachSelectedCell (TextInteractor::kClear_CmdID,
false);
6452 undoContext.CommandComplete ();
6455void WordProcessorTable::OnUpdateInsertTableRowAboveCommand (TextInteractor::CommandUpdater* enabler)
6458 Led_Require_CurrentOwningWP ();
6459 enabler->SetEnabled (
true);
6462void WordProcessorTable::OnInsertTableRowAboveCommand ()
6464 Led_Require_CurrentOwningWP ();
6465 AllowUpdateInfoPropagationContext AUIPC (*
this);
6466 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6467 BreakInGroupedCommands ();
6468 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fInsertTableRowAboveCommandName,
false);
6472 GetCellSelection (&curRow,
nullptr,
nullptr,
nullptr);
6474 Assert (curRow <= GetRowCount ());
6477 context.CommandComplete ();
6478 BreakInGroupedCommands ();
6481void WordProcessorTable::OnUpdateInsertTableRowBelowCommand (TextInteractor::CommandUpdater* enabler)
6484 Led_Require_CurrentOwningWP ();
6485 enabler->SetEnabled (
true);
6488void WordProcessorTable::OnInsertTableRowBelowCommand ()
6490 Led_Require_CurrentOwningWP ();
6491 AllowUpdateInfoPropagationContext AUIPC (*
this);
6492 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6493 BreakInGroupedCommands ();
6494 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fInsertTableRowAboveCommandName,
false);
6498 GetCellSelection (
nullptr, &curRow,
nullptr,
nullptr);
6499 Assert (curRow <= GetRowCount ());
6502 context.CommandComplete ();
6503 BreakInGroupedCommands ();
6506void WordProcessorTable::OnUpdateInsertTableColBeforeCommand (TextInteractor::CommandUpdater* enabler)
6508 Led_Require_CurrentOwningWP ();
6510 enabler->SetEnabled (
true);
6513void WordProcessorTable::OnInsertTableColBeforeCommand ()
6515 Led_Require_CurrentOwningWP ();
6516 AllowUpdateInfoPropagationContext AUIPC (*
this);
6517 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6518 BreakInGroupedCommands ();
6519 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fInsertTableColBeforeCommandName,
false);
6522 GetCellSelection (
nullptr,
nullptr, &curCol,
nullptr);
6523 Assert (curCol <= GetColumnCount ());
6524 InsertColumn (curCol);
6526 context.CommandComplete ();
6527 BreakInGroupedCommands ();
6530void WordProcessorTable::OnUpdateInsertTableColAfterCommand (TextInteractor::CommandUpdater* enabler)
6532 Led_Require_CurrentOwningWP ();
6534 enabler->SetEnabled (
true);
6537void WordProcessorTable::OnInsertTableColAfterCommand ()
6539 Led_Require_CurrentOwningWP ();
6540 AllowUpdateInfoPropagationContext AUIPC (*
this);
6541 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6542 BreakInGroupedCommands ();
6543 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fInsertTableColAfterCommandName,
false);
6546 GetCellSelection (
nullptr,
nullptr,
nullptr, &curCol);
6547 Assert (curCol <= GetColumnCount ());
6548 InsertColumn (curCol);
6550 context.CommandComplete ();
6551 BreakInGroupedCommands ();
6554void WordProcessorTable::OnUpdateRemoveTableRowsCommand (TextInteractor::CommandUpdater* pCmdUI)
6556 Led_Require_CurrentOwningWP ();
6558 size_t rowSelStart = 0;
6559 size_t rowSelEnd = 0;
6560 size_t colSelStart = 0;
6561 size_t colSelEnd = 0;
6562 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6563 pCmdUI->SetEnabled (colSelStart == 0 and colSelEnd == GetColumnCount (rowSelStart, rowSelEnd));
6566void WordProcessorTable::OnRemoveTableRowsCommand ()
6568 Led_Require_CurrentOwningWP ();
6569 AllowUpdateInfoPropagationContext AUIPC (*
this);
6570 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6571 BreakInGroupedCommands ();
6572 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fRemoveTableRowsCommandName,
false);
6574 size_t rowSelStart = 0;
6575 size_t rowSelEnd = 0;
6576 size_t colSelStart = 0;
6577 size_t colSelEnd = 0;
6578 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6579 if (colSelStart == 0 and colSelEnd == GetColumnCount (rowSelStart, rowSelEnd)) {
6580 if (rowSelStart == 0 and rowSelEnd == GetRowCount ()) {
6581 fCurrentOwningWP->OnClearCommand ();
6584 size_t nRowsToDelete = rowSelEnd - rowSelStart;
6585 while (nRowsToDelete > 0) {
6586 DeleteRow (rowSelStart);
6591 fCurrentOwningWP->OnBadUserInput ();
6594 context.CommandComplete ();
6597void WordProcessorTable::OnUpdateRemoveTableColumnsCommand (TextInteractor::CommandUpdater* pCmdUI)
6599 Led_Require_CurrentOwningWP ();
6601 size_t rowSelStart = 0;
6602 size_t rowSelEnd = 0;
6603 size_t colSelStart = 0;
6604 size_t colSelEnd = 0;
6605 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6606 pCmdUI->SetEnabled (rowSelStart == 0 and rowSelEnd == GetRowCount ());
6609void WordProcessorTable::OnRemoveTableColumnsCommand ()
6611 Led_Require_CurrentOwningWP ();
6612 AllowUpdateInfoPropagationContext AUIPC (*
this);
6613 InteractiveModeUpdater iuMode (*fCurrentOwningWP);
6614 BreakInGroupedCommands ();
6615 UndoableContextHelper context (*fCurrentOwningWP, WordProcessor::GetCommandNames ().fRemoveTableColumnsCommandName,
false);
6617 size_t rowSelStart = 0;
6618 size_t rowSelEnd = 0;
6619 size_t colSelStart = 0;
6620 size_t colSelEnd = 0;
6621 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6622 if (rowSelStart == 0 and rowSelEnd == GetRowCount ()) {
6623 if (colSelStart == 0 and colSelEnd == GetColumnCount ()) {
6624 fCurrentOwningWP->OnClearCommand ();
6627 size_t nColsToDelete = colSelEnd - colSelStart;
6628 while (nColsToDelete > 0) {
6629 DeleteColumn (colSelStart);
6634 fCurrentOwningWP->OnBadUserInput ();
6637 context.CommandComplete ();
6638 BreakInGroupedCommands ();
6641void WordProcessorTable::OnUpdateSelectTablePartsCommand (TextInteractor::CommandUpdater* enabler)
6643 switch (enabler->GetCmdID ()) {
6644 case WordProcessor::kSelectTableIntraCellAll_CmdID: {
6645 enabler->SetEnabled (GetIntraCellMode ());
6647 case WordProcessor::kSelectTableCell_CmdID: {
6648 enabler->SetEnabled (GetIntraCellMode ());
6650 case WordProcessor::kSelectTableRow_CmdID: {
6651 size_t rowSelStart = 0;
6652 size_t rowSelEnd = 0;
6653 size_t colSelStart = 0;
6654 size_t colSelEnd = 0;
6655 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6656 size_t maxColSelEnd = GetColumnCount (rowSelStart, rowSelEnd);
6657 enabler->SetEnabled (colSelStart != 0 or colSelEnd != maxColSelEnd);
6659 case WordProcessor::kSelectTableColumn_CmdID: {
6660 size_t rowSelStart = 0;
6661 size_t rowSelEnd = 0;
6662 size_t colSelStart = 0;
6663 size_t colSelEnd = 0;
6664 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6665 enabler->SetEnabled (rowSelStart != 0 or rowSelEnd != GetRowCount ());
6667 case WordProcessor::kSelectTable_CmdID: {
6668 size_t rowSelStart = 0;
6669 size_t rowSelEnd = 0;
6670 size_t colSelStart = 0;
6671 size_t colSelEnd = 0;
6672 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6673 enabler->SetEnabled (rowSelStart != 0 or colSelStart != 0 or rowSelEnd != GetRowCount () or colSelEnd != GetColumnCount ());
6678void WordProcessorTable::OnPerformTablePartsCommand (TextInteractor::CommandNumber commandNumber)
6680 switch (commandNumber) {
6681 case WordProcessor::kSelectTableIntraCellAll_CmdID: {
6684 if (GetIntraCellMode (&row, &col)) {
6685 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6686 wp->OnPerformCommand (TextInteractor::kSelectAll_CmdID);
6692 case WordProcessor::kSelectTableCell_CmdID: {
6693 UnSetIntraCellMode ();
6695 case WordProcessor::kSelectTableRow_CmdID: {
6696 size_t rowSelStart = 0;
6697 size_t rowSelEnd = 0;
6698 size_t colSelStart = 0;
6699 size_t colSelEnd = 0;
6700 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6702 colSelEnd = GetColumnCount (rowSelStart, rowSelEnd);
6703 SetCellSelection (rowSelStart, rowSelEnd, colSelStart, colSelEnd);
6705 case WordProcessor::kSelectTableColumn_CmdID: {
6706 size_t rowSelStart = 0;
6707 size_t rowSelEnd = 0;
6708 size_t colSelStart = 0;
6709 size_t colSelEnd = 0;
6710 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6712 rowSelEnd = GetRowCount ();
6713 SetCellSelection (rowSelStart, rowSelEnd, colSelStart, colSelEnd);
6715 case WordProcessor::kSelectTable_CmdID: {
6716 SetCellSelection (0, GetRowCount (), 0, GetColumnCount ());
6721void WordProcessorTable::AssureCurSelFontCacheValid (IncrementalFontSpecification* curSelFontSpec)
6727 if (GetIntraCellMode (&row, &col)) {
6728 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6729 *curSelFontSpec = wp->GetCurSelFontSpec ();
6734 size_t rowSelStart = 0;
6735 size_t rowSelEnd = 0;
6736 size_t colSelStart = 0;
6737 size_t colSelEnd = 0;
6738 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6739 for (
size_t ri = rowSelStart; ri < rowSelEnd; ++ri) {
6740 size_t thisRowEnd = min (colSelEnd, GetColumnCount (ri));
6741 for (
size_t ci = colSelStart; ci < thisRowEnd; ++ci) {
6742 TemporarilyAllocateCellWithTablet wp (*
this, ri, ci);
6743 wp->SetSelection (0, wp->GetEnd (), TextInteractor::eNoUpdate);
6744 IncrementalFontSpecification iSpec = wp->GetCurSelFontSpec ();
6745 if (ri == rowSelStart and ci == colSelStart) {
6746 *curSelFontSpec = iSpec;
6749 *curSelFontSpec =
Intersection (*curSelFontSpec, iSpec);
6759void WordProcessorTable::InteractiveSetFont (
const IncrementalFontSpecification& defaultFont)
6761 Led_Require_CurrentOwningWP ();
6767 if (GetIntraCellMode (&row, &col)) {
6768 TemporarilyAllocateCellWithTablet wp (*
this, row, col);
6769 wp->InteractiveSetFont (defaultFont);
6774 AllowUpdateInfoPropagationContext AUIPC (*
this);
6776 fCurrentOwningWP->BreakInGroupedCommands ();
6777 UndoableContextHelper undoContext (*fCurrentOwningWP, StandardStyledTextInteractor::GetCommandNames ().fFontChangeCommandName,
false);
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 for (
size_t ri = rowSelStart; ri < rowSelEnd; ++ri) {
6785 size_t thisRowEnd = min (colSelEnd, GetColumnCount (ri));
6786 for (
size_t ci = colSelStart; ci < thisRowEnd; ++ci) {
6787 TemporarilyAllocateCellWithTablet wp (*
this, ri, ci);
6788 wp->SetStyleInfo (0, wp->GetEnd (), defaultFont);
6792 undoContext.CommandComplete ();
6795void WordProcessorTable::Write ([[maybe_unused]] SinkStream& sink)
6800void WordProcessorTable::ExternalizeFlavors ([[maybe_unused]]
WriterFlavorPackage& flavorPackage)
6808const char* WordProcessorTable::GetTag ()
const
6819bool WordProcessorTable::ProcessSimpleClick (Led_Point clickedAt,
unsigned clickCount,
bool extendSelection)
6822 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",
6823 this, clickedAt.v, clickedAt.h, clickCount, fRowSelStart, fRowSelEnd, fColSelStart, fColSelEnd, fIntraCellMode, fIntraSelStart, fIntraSelStart
6826 Led_Require_CurrentOwningWP ();
6828 size_t clickRow = 0;
6829 size_t clickCol = 0;
6830 GetClosestCell (clickedAt, &clickRow, &clickCol);
6832 fTrackingAnchor_Row = clickRow;
6833 fTrackingAnchor_Col = clickCol;
6835 bool forceSelectAllCells =
false;
6836 if (extendSelection) {
6837 size_t selStart = fCurrentOwningWP->GetSelectionStart ();
6838 size_t selEnd = fCurrentOwningWP->GetSelectionEnd ();
6839 selStart = min (selStart, GetStart ());
6840 selEnd = max (selEnd, GetEnd ());
6841 forceSelectAllCells = (selEnd - selStart != 1);
6842 fCurrentOwningWP->SetSelection (selStart, selEnd);
6845 fCurrentOwningWP->SetSelection (GetStart (), GetEnd ());
6848 if (forceSelectAllCells) {
6849 SetCellSelection (0, GetRowCount (), 0, GetColumnCount ());
6851 else if (extendSelection) {
6852 size_t rowSelStart = 0;
6853 size_t rowSelEnd = 0;
6854 size_t colSelStart = 0;
6855 size_t colSelEnd = 0;
6856 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6857 rowSelStart = min (rowSelStart, clickRow);
6858 rowSelEnd = max (rowSelEnd, clickRow + 1);
6859 colSelStart = min (colSelStart, clickCol);
6860 colSelEnd = max (colSelEnd, clickCol + 1);
6861 SetCellSelection (rowSelStart, rowSelEnd, colSelStart, colSelEnd);
6864 SetCellSelection (clickRow, clickRow + 1, clickCol, clickCol + 1);
6868 size_t rowSelStart = 0;
6869 size_t rowSelEnd = 0;
6870 size_t colSelStart = 0;
6871 size_t colSelEnd = 0;
6872 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6873 if (rowSelEnd - rowSelStart == 1 and colSelEnd - colSelStart == 1) {
6874 Led_Rect cellBounds = GetCellBounds (rowSelStart, colSelStart);
6875 Led_Rect cellEditorBounds = GetCellEditorBounds (rowSelStart, colSelStart);
6879 if (cellEditorBounds.Contains (clickedAt)) {
6880 SetIntraCellMode ();
6883 TemporarilyAllocateCellWithTablet wp (*
this, rowSelStart, colSelStart);
6884 wp->SetCurClickCount (fCurrentOwningWP->GetCurClickCount (), Time::GetTickCount ());
6885 Assert (fCurrentOwningWP->GetCurClickCount () == clickCount);
6886 wp->ProcessSimpleClick (TableCoordinates2Window (clickedAt), clickCount, extendSelection, &fIntraCellDragAnchor);
6889 UnSetIntraCellMode ();
6894 DbgTrace (
"EXITING WordProcessorTable::ProcessSimpleClick (this= 0x%x, rowSelStart=%d, rowSelEnd=%d, colSelStart=%d, colSelEnd=%d, intraCellMode=%d intraCellStart=%d, intraCellEnd=%d)\n",
6895 this, fRowSelStart, fRowSelEnd, fColSelStart, fColSelEnd, fIntraCellMode, fIntraSelStart, fIntraSelStart
6901void WordProcessorTable::WhileSimpleMouseTracking (Led_Point newMousePos)
6904 DbgTrace (
"ENTERING WordProcessorTable::WhileSimpleMouseTracking (this= 0x%x, rowSelStart=%d, rowSelEnd=%d, colSelStart=%d, colSelEnd=%d, intraCellMode=%d intraCellStart=%d, intraCellEnd=%d)\n",
6905 this, fRowSelStart, fRowSelEnd, fColSelStart, fColSelEnd, fIntraCellMode, fIntraSelStart, fIntraSelStart
6908 Led_Require_CurrentOwningWP ();
6910 if (fCurrentOwningWP->GetSelectionEnd () - fCurrentOwningWP->GetSelectionStart () == 1) {
6914 size_t clickRow = 0;
6915 size_t clickCol = 0;
6916 GetClosestCell (newMousePos, &clickRow, &clickCol);
6918 size_t rowSelStart = min (fTrackingAnchor_Row, clickRow);
6919 size_t rowSelEnd = max (fTrackingAnchor_Row + 1, clickRow + 1);
6920 size_t colSelStart = min (fTrackingAnchor_Col, clickCol);
6921 size_t colSelEnd = max (fTrackingAnchor_Col + 1, clickCol + 1);
6922 SetCellSelection (rowSelStart, rowSelEnd, colSelStart, colSelEnd);
6924 else if (fCurrentOwningWP->GetSelectionEnd () - fCurrentOwningWP->GetSelectionStart () > 1) {
6925 SetCellSelection (0, GetRowCount (), 0, GetColumnCount ());
6929 size_t rowSelStart = 0;
6930 size_t rowSelEnd = 0;
6931 size_t colSelStart = 0;
6932 size_t colSelEnd = 0;
6933 GetCellSelection (&rowSelStart, &rowSelEnd, &colSelStart, &colSelEnd);
6934 if (rowSelEnd - rowSelStart == 1 and colSelEnd - colSelStart == 1) {
6935 Led_Rect cellBounds = GetCellBounds (rowSelStart, colSelStart);
6936 Led_Rect cellEditorBounds = GetCellEditorBounds (rowSelStart, colSelStart);
6940 if (cellEditorBounds.Contains (newMousePos)) {
6941 if (fTrackingAnchor_Row == rowSelStart and rowSelStart + 1 == rowSelEnd and fTrackingAnchor_Col == colSelStart and
6942 colSelStart + 1 == colSelEnd) {
6946 SetIntraCellMode ();
6949 TemporarilyAllocateCellWithTablet wp (*
this, rowSelStart, colSelStart);
6950 wp->SetCurClickCount (fCurrentOwningWP->GetCurClickCount (), Time::GetTickCount ());
6951 wp->WhileSimpleMouseTracking (TableCoordinates2Window (newMousePos), fIntraCellDragAnchor);
6956 DbgTrace (
"EXITING WordProcessorTable::WhileSimpleMouseTracking (this= 0x%x, rowSelStart=%d, rowSelEnd=%d, colSelStart=%d, colSelEnd=%d, intraCellMode=%d intraCellStart=%d, intraCellEnd=%d)\n",
6957 this, fRowSelStart, fRowSelEnd, fColSelStart, fColSelEnd, fIntraCellMode, fIntraSelStart, fIntraSelStart
6967void WordProcessorTable::GetRealCell (
size_t* row,
size_t* column)
const
6974 CellMergeFlags flags = GetCell (r, c).GetCellMergeFlags ();
6975 if (flags == ePlainCell) {
6981#if qStroika_Foundation_Debug_AssertionsChecked
6982 bool changed =
false;
6984 if (flags & eMergeCellLeft) {
6987#if qStroika_Foundation_Debug_AssertionsChecked
6991 if (flags & eMergeCellUp) {
6994#if qStroika_Foundation_Debug_AssertionsChecked
6998#if qStroika_Foundation_Debug_AssertionsChecked
7005const WordProcessorTable::Cell& WordProcessorTable::GetRealCell (
size_t row,
size_t column)
const
7007 GetRealCell (&row, &column);
7008 return GetCell (row, column);
7011bool WordProcessorTable::CanMergeCells (
size_t fromRow,
size_t fromCol, [[maybe_unused]]
size_t toRow, [[maybe_unused]]
size_t toCol)
7013 Require (fromRow <= toRow);
7014 Require (fromCol <= toCol);
7015 Require (toRow <= GetRowCount ());
7016 Require (toCol <= GetColumnCount ());
7019 return GetCellFlags (fromRow, fromCol) == ePlainCell;
7036void WordProcessorTable::MergeCells (
size_t fromRow,
size_t fromCol,
size_t toRow,
size_t toCol)
7038 Require (fromRow <= toRow);
7039 Require (fromCol <= toCol);
7040 Require (toRow <= GetRowCount ());
7041 Require (toCol <= GetColumnCount ());
7042 Require (CanMergeCells (fromRow, fromCol, toRow, toCol));
7043 bool madeChange =
false;
7044 for (
size_t r = fromRow; r < toRow; ++r) {
7045 for (
size_t c = fromCol; c < toCol; ++c) {
7047 if (not(r == fromRow and c == fromCol)) {
7048 fRows[r].fCells[c] =
7049 Cell (*
this,
static_cast<CellMergeFlags
> (((r > fromRow) ? eMergeCellUp : 0) | ((c > fromCol) ? eMergeCellLeft : 0)));
7055 InvalidateLayout ();
7059void WordProcessorTable::UnMergeCells (
size_t fromRow,
size_t fromCol,
size_t toRow,
size_t toCol)
7061 Require (fromRow <= toRow);
7062 Require (fromCol <= toCol);
7063 Require (toRow < GetRowCount ());
7064 Require (toCol < GetColumnCount ());
7065 bool madeChange =
false;
7066 for (
size_t r = fromRow; r < toRow; ++r) {
7067 for (
size_t c = fromCol; c < toCol; ++c) {
7069 if (GetCellFlags (r, c) != ePlainCell) {
7070 fRows[r].fCells[c] = Cell (*
this, ePlainCell);
7076 InvalidateLayout ();
7084void WordProcessorTable::SetCellSelection (
size_t rowSelStart,
size_t rowSelEnd,
size_t colSelStart,
size_t colSelEnd)
7086 Ensure (rowSelStart <= rowSelEnd);
7087 Ensure (rowSelEnd <= GetRowCount ());
7088 Ensure (colSelStart <= colSelEnd);
7089 Ensure (colSelEnd <= GetColumnCount ());
7090 bool changed = (fRowSelStart != rowSelStart) or (fRowSelEnd != rowSelEnd) or (fColSelStart != colSelStart) or (fColSelEnd != colSelEnd);
7092 fRowSelStart = rowSelStart;
7093 fRowSelEnd = rowSelEnd;
7094 fColSelStart = colSelStart;
7095 fColSelEnd = colSelEnd;
7096 fIntraCellMode =
false;
7097 InvalidateIntraCellContextInfo ();
7098 if (fCurrentOwningWP !=
nullptr) {
7099 fCurrentOwningWP->fCachedCurSelFontSpecValid =
false;
7100 fCurrentOwningWP->Refresh (GetStart (), GetEnd ());
7104 DbgTrace (
"WordProcessorTable::SetCellSelection (table=0x%x, tickCount=%f, rs=%d, re=%d, cs=%d, ce=%d, changed=%d)\n",
7105 this, Time::GetTickCount (), rowSelStart, rowSelEnd, colSelStart, colSelEnd, changed
7110void WordProcessorTable::SetIntraCellMode ()
7112 Require (fRowSelEnd - fRowSelStart == 1);
7113 Require (fColSelEnd - fColSelStart == 1);
7114 if (not fIntraCellMode) {
7115 TextStore* ts =
nullptr;
7116 GetCellWordProcessorDatabases (fRowSelStart, fColSelStart, &ts);
7118 SetIntraCellSelection (0, ts->GetLength ());
7119 fIntraCellMode =
true;
7120 if (fCurrentOwningWP !=
nullptr) {
7121 fCurrentOwningWP->Refresh (GetStart (), GetEnd ());
7126void WordProcessorTable::SetIntraCellMode (
size_t row,
size_t col)
7128 if (not fIntraCellMode) {
7129 SetCellSelection (row, row + 1, col, col + 1);
7130 SetIntraCellMode ();
7134void WordProcessorTable::UnSetIntraCellMode ()
7136 if (fIntraCellMode) {
7137 fIntraCellMode =
false;
7138 if (fCurrentOwningWP !=
nullptr) {
7139 fCurrentOwningWP->Refresh (GetStart (), GetEnd ());
7144void WordProcessorTable::SetIntraCellSelection (
size_t selStart,
size_t selEnd)
7146 if (fIntraSelStart != selStart or fIntraSelEnd != selEnd) {
7148 DbgTrace (
"WordProcessorTable::SetIntraCellSelection (selStart = %d, selEnd = %d)- oldSel=(%d,%d), tickcount=%f\n", selStart, selEnd, fIntraSelStart, fIntraSelEnd, Time::GetTickCount ());
7150 if (fCurrentOwningWP !=
nullptr) {
7151 fCurrentOwningWP->fCachedCurSelFontSpecValid =
false;
7153 fIntraSelStart = selStart;
7154 fIntraSelEnd = selEnd;
7166WordProcessorTable::EmbeddedTableWordProcessor* WordProcessorTable::ConstructEmbeddedTableWordProcessor (WordProcessor& forWordProcessor,
7167 size_t forRow,
size_t forColumn,
7168 const Led_Rect& cellWindowRect,
7169 bool captureChangesForUndo)
7171 size_t cellModeRow = 0;
7172 size_t cellModeCol = 0;
7173 bool activeFocusedCell = GetIntraCellMode (&cellModeRow, &cellModeCol) and cellModeRow == forRow and cellModeCol == forColumn;
7174 EmbeddedTableWordProcessor* e =
new EmbeddedTableWordProcessor (forWordProcessor, *
this, forRow, forColumn, activeFocusedCell);
7176 TextStore* ts =
nullptr;
7177 shared_ptr<AbstractStyleDatabaseRep> styleDatabase;
7178 shared_ptr<AbstractParagraphDatabaseRep> paragraphDatabase;
7179 shared_ptr<HidableTextMarkerOwner> hidableTextDatabase;
7180 GetCellWordProcessorDatabases (forRow, forColumn, &ts, &styleDatabase, ¶graphDatabase, &hidableTextDatabase);
7181 e->SetStyleDatabase (styleDatabase);
7182 e->SetParagraphDatabase (paragraphDatabase);
7183 e->SetHidableTextDatabase (hidableTextDatabase);
7184 e->SpecifyTextStore (ts);
7185 e->SetWindowRect (cellWindowRect);
7186 e->SetDefaultTextColor (WordProcessor::eDefaultBackgroundColor, GetCellColor (forRow, forColumn));
7187 if (captureChangesForUndo) {
7188 e->SetCommandHandler (forWordProcessor.GetCommandHandler ());
7191 if (activeFocusedCell) {
7192 using TemporarilyUseTablet = EmbeddedTableWordProcessor::TemporarilyUseTablet;
7195 WordProcessor::Tablet_Acquirer tablet (fCurrentOwningWP);
7196 TemporarilyUseTablet tmpUseTablet (*e, tablet, TemporarilyUseTablet::eDontDoTextMetricsChangedCall);
7198 e->SetSelectionShown (
true, TextInteractor::eNoUpdate);
7199 e->RestoreMiscActiveFocusInfo ();
7203 e->SpecifyTextStore (
nullptr);
7217void WordProcessorTable::ReleaseEmbeddedTableWordProcessor (EmbeddedTableWordProcessor* e)
7220 e->SaveMiscActiveFocusInfo ();
7221 e->SetCommandHandler (
nullptr);
7222 e->SpecifyTextStore (
nullptr);
7231void WordProcessorTable::PerformLayout ()
7233 Require (fNeedLayout != eDone);
7235 if (fCurrentOwningWP !=
nullptr) {
7236 TextStore& ts = GetOwner ()->GetTextStore ();
7237 TextStore::SimpleUpdater updater (ts, GetStart (), GetEnd (),
false);
7239 Led_Size border = Led_Size (Led_CvtScreenPixelsFromTWIPSV (fBorderWidth), Led_CvtScreenPixelsFromTWIPSH (fBorderWidth));
7240 DistanceType spacing = Led_CvtScreenPixelsFromTWIPSV (GetCellSpacing ());
7241 Led_Rect defaultCellMargin;
7243 TWIPS_Rect defaultCellMarginTWIPS;
7244 GetDefaultCellMargins (&defaultCellMarginTWIPS.top, &defaultCellMarginTWIPS.left, &defaultCellMarginTWIPS.bottom,
7245 &defaultCellMarginTWIPS.right);
7246 defaultCellMargin.top = Led_CvtScreenPixelsFromTWIPSV (defaultCellMarginTWIPS.top);
7247 defaultCellMargin.left = Led_CvtScreenPixelsFromTWIPSH (defaultCellMarginTWIPS.left);
7248 defaultCellMargin.bottom = Led_CvtScreenPixelsFromTWIPSV (defaultCellMarginTWIPS.bottom);
7249 defaultCellMargin.right = Led_CvtScreenPixelsFromTWIPSH (defaultCellMarginTWIPS.right);
7255 size_t rows = GetRowCount ();
7257 Tablet_Acquirer tablet (fCurrentOwningWP);
7259 DistanceType maxTableWidth = 0;
7261 DistanceType runningHeight = 0;
7262 for (
size_t r = 0; r < rows; ++r) {
7266 size_t cols = GetColumnCount (r);
7268 DistanceType rowWidth = 0;
7270 size_t lastRealCellIdx = 0;
7271 for (
size_t c = 0; c < cols; ++c) {
7272 DistanceType thisColWidth = Led_CvtScreenPixelsFromTWIPSH (GetColumnWidth (r, c));
7273 if (GetCellFlags (r, c) == ePlainCell) {
7274 realCellWidths[c] = thisColWidth;
7275 lastRealCellIdx = c;
7276 rowWidth += thisColWidth;
7280 realCellWidths[lastRealCellIdx] += thisColWidth;
7288 DistanceType rowHeight = 0;
7289 for (
size_t c = 0; c < cols; ++c) {
7290 if (GetCellFlags (r, c) == ePlainCell) {
7291 using TemporarilyUseTablet = EmbeddedTableWordProcessor::TemporarilyUseTablet;
7293 DistanceType totalCellMargin = defaultCellMargin.left + defaultCellMargin.right;
7294 DistanceType wpWidth = (totalCellMargin < realCellWidths[c]) ? realCellWidths[c] - totalCellMargin : 1;
7295 TemporarilyAllocateCellWP wp (*
this, *fCurrentOwningWP, r, c, Led_Rect (0, 0, 1000, wpWidth));
7296 TemporarilyUseTablet tmpUseTablet (*wp, tablet, TemporarilyUseTablet::eDontDoTextMetricsChangedCall);
7297 rowHeight = max (rowHeight, wp->GetDesiredHeight ());
7304 rowHeight += defaultCellMargin.top + defaultCellMargin.bottom;
7305 rowHeight = max (rowHeight, DistanceType (5));
7306 fRows[r].fHeight = rowHeight;
7307 runningHeight += rowHeight;
7309 DistanceType rowWidthWithSpacingNBorders = rowWidth +
static_cast<DistanceType
> ((cols + 1) * (spacing + border.h));
7310 maxTableWidth = max (maxTableWidth, rowWidthWithSpacingNBorders);
7316 DistanceType runningWidth = 0;
7317 size_t lastRealCellIdx = 0;
7318 for (
size_t c = 0; c < cols; ++c) {
7319 if (GetCellFlags (r, c) == ePlainCell) {
7320 Cell cell = GetCell (r, c);
7321 Led_Rect cellRect = Led_Rect (runningHeight - rowHeight, runningWidth, rowHeight, realCellWidths[c]);
7324 Led_Point (
static_cast<CoordinateType
> ((r + 1) * border.v),
static_cast<CoordinateType
> ((c + 1) * border.h));
7327 cellRect += Led_Point (
static_cast<CoordinateType
> ((r + 1) * spacing),
static_cast<CoordinateType
> ((c + 1) * spacing));
7329 cell.SetCachedBoundsRect (cellRect);
7330 lastRealCellIdx = c;
7331 runningWidth += realCellWidths[c];
7338 DistanceType totalHeight = 0;
7339 for (
auto i = fRows.begin (); i != fRows.end (); ++i) {
7340 totalHeight += (*i).fHeight;
7342 fTotalHeight = totalHeight +
static_cast<DistanceType
> ((spacing + border.v) * (fRows.size () + 1));
7345 fTotalWidth = maxTableWidth;
7347 fNeedLayout = eDone;
7358void WordProcessorTable::GetDimensions (
size_t* rows,
size_t* columns)
const
7360 if (rows !=
nullptr) {
7361 *rows = fRows.size ();
7363 if (columns !=
nullptr) {
7365 for (
size_t ri = 0; ri < fRows.size (); ++ri) {
7366 maxCols = max (maxCols, fRows[ri].fCells.size ());
7379void WordProcessorTable::SetDimensions (
size_t rows,
size_t columns)
7382 size_t oldColumns = 0;
7383 GetDimensions (&oldRows, &oldColumns);
7386 while (oldRows > rows) {
7387 DeleteRow (oldRows - 1);
7390 while (oldColumns > columns) {
7391 DeleteColumn (oldColumns - 1);
7396 while (oldRows < rows) {
7397 InsertRow (oldRows);
7400 while (oldColumns < columns) {
7401 InsertColumn (oldColumns);
7405 GetDimensions (&oldRows, &oldColumns);
7406 Assert (oldRows == rows);
7407 Assert (oldColumns == columns);
7417void WordProcessorTable::SetDimensionsAtLeast (
size_t rows,
size_t columns)
7421 GetDimensions (&r, &c);
7423 c = max (columns, c);
7424 SetDimensions (r, c);
7434void WordProcessorTable::InsertRow (
size_t at,
size_t maxRowCopyCount)
7436 Require (at <= GetRowCount ());
7437 Require (maxRowCopyCount >= 1);
7438#if qStroika_Frameworks_Led_SupportGDI
7440 TextStore& ts = GetOwner ()->GetTextStore ();
7441 TextStore::SimpleUpdater updater (ts, GetStart (), GetEnd ());
7447 size_t rowToCopy = at > 0 ? at - 1 : at;
7448 size_t colCount = 0;
7449 if (rowToCopy < GetRowCount ()) {
7450 colCount = GetColumnCount (rowToCopy);
7452 colCount = min (colCount, maxRowCopyCount);
7454 for (
size_t c = 0; c < colCount; ++c) {
7455 Cell cell (*
this, ePlainCell);
7456 cell.SetCellXWidth (GetColumnWidth (rowToCopy, c));
7457 newRow.fCells.push_back (cell);
7460 fRows.insert (fRows.begin () + at, newRow);
7461#if qStroika_Frameworks_Led_SupportGDI
7463 InvalidateIntraCellContextInfo ();
7464 InvalidateLayout ();
7472void WordProcessorTable::DeleteRow (
size_t at)
7474 Require (at < GetRowCount ());
7475#if qStroika_Frameworks_Led_SupportGDI
7477 TextStore& ts = GetOwner ()->GetTextStore ();
7478 TextStore::SimpleUpdater updater (ts, GetStart (), GetEnd ());
7481 fRows.erase (fRows.begin () + at);
7482#if qStroika_Frameworks_Led_SupportGDI
7483 InvalidateIntraCellContextInfo ();
7484 InvalidateLayout ();
7485 ReValidateSelection ();
7494void WordProcessorTable::InsertColumn (
size_t at)
7496 Require (at <= GetColumnCount ());
7497#if qStroika_Frameworks_Led_SupportGDI
7498 TextStore& ts = GetOwner ()->GetTextStore ();
7499 TextStore::SimpleUpdater updater (ts, GetStart (), GetEnd ());
7500 TWIPS newColWidth = Led_CvtScreenPixelsToTWIPSH (100);
7502 TWIPS newColWidth = TWIPS (100);
7506 if (fRows.size () > 0) {
7507 size_t nColsInRow = GetColumnCount (0);
7509 if (at == nColsInRow and at > 0) {
7510 newColWidth = GetColumnWidth (0, at - 1);
7512 else if (at < nColsInRow) {
7513 newColWidth = GetColumnWidth (0, at);
7517 vector<Cell> newCol;
7518 for (
size_t r = 0; r < fRows.size (); ++r) {
7519 Cell cell (*
this, ePlainCell);
7520 cell.SetCellXWidth (newColWidth);
7521 newCol.push_back (cell);
7524 size_t rowCount = fRows.size ();
7525 for (
size_t ri = 0; ri < rowCount; ++ri) {
7526 vector<Cell>& rowCells = fRows[ri].fCells;
7527 rowCells.insert (rowCells.begin () + at, newCol[ri]);
7529#if qStroika_Frameworks_Led_SupportGDI
7531 InvalidateIntraCellContextInfo ();
7532 InvalidateLayout ();
7540void WordProcessorTable::DeleteColumn (
size_t at)
7542 Require (at < GetColumnCount ());
7545#if qStroika_Frameworks_Led_SupportGDI
7546 TextStore& ts = GetOwner ()->GetTextStore ();
7547 TextStore::SimpleUpdater updater (ts, GetStart (), GetEnd ());
7550 size_t rowCount = fRows.size ();
7551 for (
size_t ri = 0; ri < rowCount; ++ri) {
7552 vector<Cell>& rowCells = fRows[ri].fCells;
7553 if (at < rowCells.size ()) {
7554 rowCells.erase (rowCells.begin () + at);
7557#if qStroika_Frameworks_Led_SupportGDI
7558 InvalidateIntraCellContextInfo ();
7559 InvalidateLayout ();
7560 ReValidateSelection ();
7563#if qStroika_Frameworks_Led_SupportGDI
7571void WordProcessorTable::ReValidateSelection ()
7573 size_t rowCount = GetRowCount ();
7575 size_t rowSelStart = fRowSelStart;
7576 size_t rowSelEnd = fRowSelEnd;
7577 size_t colSelStart = fColSelStart;
7578 size_t colSelEnd = fColSelEnd;
7580 if (rowSelStart >= rowCount) {
7584 if (rowSelEnd > rowCount) {
7585 rowSelEnd = rowCount;
7587 size_t colCount = GetColumnCount (rowSelStart, rowSelEnd);
7588 if (colSelStart >= colCount) {
7592 if (colSelEnd >= colCount) {
7593 colSelEnd = colCount;
7595 SetCellSelection (rowSelStart, rowSelEnd, colSelStart, colSelEnd);
7608WordProcessorTable::EmbeddedTableWordProcessor::EmbeddedTableWordProcessor (WordProcessor& owningWordProcessor, WordProcessorTable& owningTable,
7609 size_t tRow,
size_t tCol,
bool activeEditCell)
7611 , fOwningWordProcessor (owningWordProcessor)
7612 , fOwningTable (owningTable)
7614 , fTableColumn (tCol)
7615 , fUpdateTablet (nullptr)
7616 , fDesiredHeight (0)
7617 , fDesiredHeightValid (false)
7618 , fActiveEditCell (activeEditCell)
7619 , fSuppressRefreshCalls (false)
7621 SetImageUsingOffscreenBitmaps (
false);
7624WordProcessorTable& WordProcessorTable::EmbeddedTableWordProcessor::GetOwningTable ()
const
7626 return fOwningTable;
7629WordProcessor& WordProcessorTable::EmbeddedTableWordProcessor::GetOwningWordProcessor ()
const
7631 return fOwningWordProcessor;
7634void WordProcessorTable::EmbeddedTableWordProcessor::SaveMiscActiveFocusInfo ()
7636 if (fActiveEditCell) {
7637 fOwningTable.SetIntraCellSelection (GetSelectionStart (), GetSelectionEnd ());
7638 fOwningTable.SaveIntraCellContextInfo (fLeftSideOfSelectionInteresting, GetEmptySelectionStyle ());
7642void WordProcessorTable::EmbeddedTableWordProcessor::RestoreMiscActiveFocusInfo ()
7644 if (fActiveEditCell) {
7645 DisableRefreshContext DFR (*
this);
7646 SuppressCellUpdatePropagationContext SCUP (fOwningTable);
7649 bool leftSideOfSelectionInteresting =
false;
7650 if (fOwningTable.RestoreIntraCellContextInfo (&leftSideOfSelectionInteresting, &emptySelFont)) {
7651 size_t intraCellSelStart = 0;
7652 size_t intraCellSelEnd = 0;
7653 fOwningTable.GetIntraCellSelection (&intraCellSelStart, &intraCellSelEnd);
7654 SetSelection (intraCellSelStart, intraCellSelEnd, TextInteractor::eNoUpdate);
7655 fLeftSideOfSelectionInteresting = leftSideOfSelectionInteresting;
7656 SetEmptySelectionStyle (emptySelFont);
7659 SetEmptySelectionStyle ();
7664#if !qStroika_Frameworks_Led_NestedTablesSupported
7665void WordProcessorTable::EmbeddedTableWordProcessor::HookInternalizerChanged ()
7667 inherited::HookInternalizerChanged ();
7668 WordProcessorFlavorPackageInternalizer* internalizerRep =
7669 dynamic_cast<WordProcessorFlavorPackageInternalizer*
> (
static_cast<FlavorPackageInternalizer*
> (GetInternalizer ().get ()));
7671 internalizerRep->SetNoTablesAllowed (
true);
7675bool WordProcessorTable::EmbeddedTableWordProcessor::OnCopyCommand_Before ()
7677 return fOwningWordProcessor.OnCopyCommand_Before ();
7680void WordProcessorTable::EmbeddedTableWordProcessor::OnCopyCommand_After ()
7682 fOwningWordProcessor.OnCopyCommand_After ();
7685bool WordProcessorTable::EmbeddedTableWordProcessor::OnPasteCommand_Before ()
7687 return fOwningWordProcessor.OnPasteCommand_Before ();
7690void WordProcessorTable::EmbeddedTableWordProcessor::OnPasteCommand_After ()
7692 fOwningWordProcessor.OnPasteCommand_After ();
7695void WordProcessorTable::EmbeddedTableWordProcessor::DrawRowHilight (Tablet* ,
const Led_Rect& ,
const Led_Rect& ,
7696 const TextLayoutBlock& ,
size_t ,
size_t
7702Tablet* WordProcessorTable::EmbeddedTableWordProcessor::AcquireTablet ()
const
7704 if (fUpdateTablet !=
nullptr) {
7705 return fUpdateTablet;
7709 return fOwningWordProcessor.AcquireTablet ();
7712void WordProcessorTable::EmbeddedTableWordProcessor::ReleaseTablet (Tablet* tablet)
const
7714 if (tablet == fUpdateTablet) {
7719 fOwningWordProcessor.ReleaseTablet (tablet);
7722void WordProcessorTable::EmbeddedTableWordProcessor::RefreshWindowRect_ (
const Led_Rect& windowRectArea, UpdateMode updateMode)
const
7724 if (not fSuppressRefreshCalls) {
7728 UpdateMode useUpdateMode = (updateMode == eImmediateUpdate) ? eDelayedUpdate : updateMode;
7729 fOwningWordProcessor.RefreshWindowRect_ (windowRectArea, useUpdateMode);
7733void WordProcessorTable::EmbeddedTableWordProcessor::UpdateWindowRect_ (
const Led_Rect& )
const
7735 throw CannotUpdateNow ();
7738bool WordProcessorTable::EmbeddedTableWordProcessor::QueryInputKeyStrokesPending ()
const
7745void WordProcessorTable::EmbeddedTableWordProcessor::SetDefaultUpdateMode (UpdateMode defaultUpdateMode)
7747 if (defaultUpdateMode == eImmediateUpdate) {
7748 defaultUpdateMode = eDelayedUpdate;
7750 inherited::SetDefaultUpdateMode (defaultUpdateMode);
7753void WordProcessorTable::EmbeddedTableWordProcessor::GetLayoutMargins (RowReference row, CoordinateType* lhs, CoordinateType* rhs)
const
7755 if (rhs !=
nullptr) {
7756 inherited::GetLayoutMargins (row, lhs,
nullptr);
7765 if (rhs !=
nullptr) {
7766 *rhs = (max (CoordinateType (GetWindowRect ().GetWidth ()), CoordinateType (1)));
7770void WordProcessorTable::EmbeddedTableWordProcessor::PostInteractiveUndoPostHelper (InteractiveReplaceCommand::SavedTextRep** beforeRep,
7771 InteractiveReplaceCommand::SavedTextRep** afterRep,
7772 size_t startOfInsert,
const SDKString& cmdName)
7776 CommandHandler* ch = GetCommandHandler ();
7779 if (*beforeRep !=
nullptr and *afterRep !=
nullptr) {
7782 InteractiveReplaceCommand* cmd =
7783 new TableCMD (fOwningTable.GetStart (), fTableRow, fTableColumn, *beforeRep, *afterRep, startOfInsert, cmdName);
7784 *beforeRep =
nullptr;
7785 *afterRep =
nullptr;
7791 *beforeRep =
nullptr;
7793 *afterRep =
nullptr;
7798InteractiveReplaceCommand::SavedTextRep*
7799WordProcessorTable::EmbeddedTableWordProcessor::InteractiveUndoHelperMakeTextRep (
size_t regionStart,
size_t regionEnd,
size_t selStart,
size_t selEnd)
7801 InteractiveReplaceCommand::SavedTextRep* tableStateRep = inherited::InteractiveUndoHelperMakeTextRep (regionStart, regionEnd, selStart, selEnd);
7802 return new SavedTextRepWSel (tableStateRep, fOwningTable, SavedTextRepWSel::eWPDirect);
7805DistanceType WordProcessorTable::EmbeddedTableWordProcessor::GetDesiredHeight ()
const
7807 if (not fDesiredHeightValid) {
7808 RowReference startingRow = GetRowReferenceContainingPosition (0);
7809 RowReference endingRow = GetRowReferenceContainingPosition (GetEnd ());
7814 fDesiredHeightValid =
true;
7815 fDesiredHeight = GetHeightOfRows (startingRow, CountRowDifference (startingRow, endingRow) + 1);
7817 return fDesiredHeight;
7825WordProcessorTable::SavedTextRepWSel::SavedTextRepWSel (SavedTextRep* delegateTo, WordProcessorTable& table, WPRelativeFlag wPRelativeFlag)
7826 : inherited (table.GetStart (), table.GetEnd ())
7827 , fWPRelativeFlag (wPRelativeFlag)
7828 , fRealRep (delegateTo)
7833 , fIntraCellMode (false)
7834 , fIntraCellSelStart (0)
7835 , fIntraCellSelEnd (0)
7838 table.GetCellSelection (&fRowSelStart, &fRowSelEnd, &fColSelStart, &fColSelEnd);
7839 fIntraCellMode = table.GetIntraCellMode ();
7840 if (fIntraCellMode) {
7841 table.GetIntraCellSelection (&fIntraCellSelStart, &fIntraCellSelEnd);
7845size_t WordProcessorTable::SavedTextRepWSel::GetLength ()
const
7847 return fRealRep->GetLength ();
7850void WordProcessorTable::SavedTextRepWSel::InsertSelf (TextInteractor* interactor,
size_t at,
size_t nBytesToOverwrite)
7852 fRealRep->InsertSelf (interactor, at, nBytesToOverwrite);
7855void WordProcessorTable::SavedTextRepWSel::ApplySelection (TextInteractor* interactor)
7857 fRealRep->ApplySelection (interactor);
7859 WordProcessorTable* aT =
nullptr;
7860 if (fWPRelativeFlag == eWPDirect) {
7861 EmbeddedTableWordProcessor* wp =
dynamic_cast<EmbeddedTableWordProcessor*
> (interactor);
7862 aT = &wp->GetOwningTable ();
7865 WordProcessor* wp =
dynamic_cast<WordProcessor*
> (interactor);
7867 aT = wp->GetActiveTable ();
7872 aT->SetCellSelection (fRowSelStart, fRowSelEnd, fColSelStart, fColSelEnd);
7873 if (fIntraCellMode) {
7874 aT->SetIntraCellMode ();
7875 aT->SetIntraCellSelection (fIntraCellSelStart, fIntraCellSelEnd);
7878 aT->UnSetIntraCellMode ();
7887using EmptySelectionParagraphSavedTextRep = WordProcessor::EmptySelectionParagraphSavedTextRep;
7889EmptySelectionParagraphSavedTextRep::EmptySelectionParagraphSavedTextRep (WordProcessor* interactor,
size_t selStart,
size_t selEnd,
size_t at)
7890 : inherited (interactor, selStart, selEnd)
7891 , fSavedStyleInfo (interactor->GetParagraphDatabase ()->GetParagraphInfo (at))
7895void EmptySelectionParagraphSavedTextRep::InsertSelf (TextInteractor* interactor,
size_t at,
size_t nBytesToOverwrite)
7897 inherited::InsertSelf (interactor, at, nBytesToOverwrite);
7898 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
Is this blank, and a place text may break (between words, tokens, lines ...)? The C standard white-sp...
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 ...