4#include "Stroika/Frameworks/StroikaPreComp.h"
8#include "Stroika/Frameworks/Led/LineBasedPartition.h"
9#include "Stroika/Frameworks/Led/Support.h"
11#include "SimpleTextImager.h"
14using namespace Stroika::Frameworks;
15using namespace Stroika::Frameworks::Led;
17using PartitionMarker = Partition::PartitionMarker;
18#if qStroika_Frameworks_Led_SupportGDI
19using PartitionPtr = PartitioningTextImager::PartitionPtr;
26void SimpleTextImager::MyPartitionWatcher::Init (PartitionPtr partition, SimpleTextImager* imager)
29 if (partition.get () !=
nullptr) {
30 partition->AddPartitionWatcher (
this);
34void SimpleTextImager::MyPartitionWatcher::UnInit (PartitionPtr partition)
37 if (partition.get () !=
nullptr) {
38 partition->RemovePartitionWatcher (
this);
42void SimpleTextImager::MyPartitionWatcher::AboutToSplit (PartitionMarker* ,
size_t ,
void** )
const noexcept
47void SimpleTextImager::MyPartitionWatcher::DidSplit (
void* )
const noexcept
50 fImager->InvalidateTotalRowsInWindow ();
53void SimpleTextImager::MyPartitionWatcher::AboutToCoalece (PartitionMarker* pm,
void** infoRecord)
const noexcept
61 PartitionMarker* newTopLine = NULL;
62 if (pm == fImager->fTopLinePartitionMarkerInWindow) {
63 if (pm->GetNext () == NULL) {
64 newTopLine = fImager->fTopLinePartitionMarkerInWindow->GetPrevious ();
67 newTopLine = fImager->fTopLinePartitionMarkerInWindow->GetNext ();
72 *infoRecord = newTopLine;
75void SimpleTextImager::MyPartitionWatcher::DidCoalece (
void* infoRecord)
const noexcept
79 PartitionMarker* newTopLine =
reinterpret_cast<PartitionMarker*
> (infoRecord);
82 if (newTopLine != NULL) {
83 fImager->SetTopRowInWindow_ (RowReference (newTopLine));
86 AssertMember (fImager->fTopLinePartitionMarkerInWindow, PartitionMarker);
87 fImager->InvalidateTotalRowsInWindow ();
95SimpleTextImager::SimpleTextImager ()
96 : fICreatedPartition{false}
97 , fMyPartitionWatcher{}
98 , fRowHeight{DistanceType (-1)}
100 , fTopLinePartitionMarkerInWindow{NULL}
101 , fTotalRowsInWindow{0}
105SimpleTextImager::~SimpleTextImager ()
107 Assert (fTopLinePartitionMarkerInWindow == NULL);
110void SimpleTextImager::HookLosingTextStore ()
112 inherited::HookLosingTextStore ();
113 HookLosingTextStore_ ();
116void SimpleTextImager::HookLosingTextStore_ ()
118 InvalidateTotalRowsInWindow ();
119 fTopLinePartitionMarkerInWindow = NULL;
121 if (fICreatedPartition) {
122 fMyPartitionWatcher.UnInit (GetPartition ());
123 fICreatedPartition =
false;
124 inherited::SetPartition (NULL);
128void SimpleTextImager::HookGainedNewTextStore ()
130 inherited::HookGainedNewTextStore ();
131 HookGainedNewTextStore_ ();
134void SimpleTextImager::HookGainedNewTextStore_ ()
136 Require (fTopLinePartitionMarkerInWindow == NULL);
137 if (GetPartition ().get () ==
nullptr) {
140 Assert (fTopLinePartitionMarkerInWindow == NULL);
141 fTopLinePartitionMarkerInWindow = GetFirstPartitionMarker ();
142 AssureWholeWindowUsedIfNeeded ();
143 InvalidateScrollBarParameters ();
151void SimpleTextImager::SetPartition (
const PartitionPtr& partitionPtr)
153 fMyPartitionWatcher.UnInit (GetPartition ());
154 inherited::SetPartition (partitionPtr);
155 fICreatedPartition =
false;
156 if (GetPartition ().get () ==
nullptr and PeekAtTextStore () != NULL) {
158 fICreatedPartition =
true;
160 fMyPartitionWatcher.Init (GetPartition (),
this);
163PartitioningTextImager::PartitionPtr SimpleTextImager::MakeDefaultPartition ()
const
175DistanceType SimpleTextImager::ReCalcRowHeight ()
const
177 return MeasureSegmentHeight_ (GetDefaultFont (), 0, 0);
180DistanceType SimpleTextImager::MeasureSegmentHeight (
size_t ,
size_t )
const
183 return GetRowHeight ();
186DistanceType SimpleTextImager::MeasureSegmentBaseLine (
size_t ,
size_t )
const
190 DistanceType rh = GetRowHeight ();
191 DistanceType sbrh = MeasureSegmentHeight_ (GetDefaultFont (), 0, 0);
192 DistanceType bl = MeasureSegmentBaseLine_ (GetDefaultFont (), 0, 0);
199bool SimpleTextImager::GetIthRowReferenceFromHere (RowReference* adjustMeInPlace, ptrdiff_t ith)
const
201 for (; ith > 0; --ith) {
202 if (not GetNextRowReference (adjustMeInPlace)) {
206 for (; ith < 0; ++ith) {
207 if (not GetPreviousRowReference (adjustMeInPlace)) {
214size_t SimpleTextImager::GetRowNumber (RowReference rowRef)
const
219 size_t rowNumber = 0;
221 for (PartitionMarker* cur = rowRef.GetPartitionMarker ()->GetPrevious (); cur != NULL; cur = cur->GetPrevious ()) {
227size_t SimpleTextImager::CountRowDifference (RowReference lhs, RowReference rhs)
const
236 PartitionMarker* lhsPM = lhs.GetPartitionMarker ();
237 PartitionMarker* rhsPM = rhs.GetPartitionMarker ();
238 size_t lhsMarkerStart = lhsPM->GetStart ();
239 size_t rhsMarkerStart = rhsPM->GetStart ();
240 bool leftSmaller = ((lhsMarkerStart < rhsMarkerStart) or ((lhsMarkerStart == rhsMarkerStart)));
241 RowReference firstRowRef = leftSmaller ? lhs : rhs;
242 RowReference lastRowRef = leftSmaller ? rhs : lhs;
244 size_t rowsGoneBy = 0;
245 for (RowReference cur = firstRowRef; cur != lastRowRef; ++rowsGoneBy) {
246 [[maybe_unused]]
bool result = GetIthRowReferenceFromHere (&cur, 1);
252size_t SimpleTextImager::GetTopRowInWindow ()
const
255 return (GetRowNumber (GetTopRowReferenceInWindow ()));
258size_t SimpleTextImager::GetTotalRowsInWindow ()
const
260 return GetTotalRowsInWindow_ ();
263size_t SimpleTextImager::GetLastRowInWindow ()
const
266 return GetRowNumber (GetLastRowReferenceInWindow ());
269void SimpleTextImager::SetTopRowInWindow (
size_t newTopRow)
272 Assert (newTopRow >= 0);
274 SetTopRowInWindow (GetIthRowReference (newTopRow));
276 Assert (GetTopRowInWindow () == newTopRow);
281void SimpleTextImager::AssureWholeWindowUsedIfNeeded ()
283 SetTopRowInWindow (GetTopRowReferenceInWindow ());
286size_t SimpleTextImager::GetMarkerPositionOfStartOfWindow ()
const
288 return (GetStartOfRow (GetTopRowReferenceInWindow ()));
291size_t SimpleTextImager::GetMarkerPositionOfEndOfWindow ()
const
293 return GetEndOfRow (GetLastRowReferenceInWindow ());
296size_t SimpleTextImager::GetMarkerPositionOfStartOfLastRowOfWindow ()
const
298 return GetStartOfRow (GetLastRowReferenceInWindow ());
301ptrdiff_t SimpleTextImager::CalculateRowDeltaFromCharDeltaFromTopOfWindow (
long deltaChars)
const
303 Assert (
long (GetMarkerPositionOfStartOfWindow ()) >= 0 - deltaChars);
304 size_t pos = long (GetMarkerPositionOfStartOfWindow ()) + deltaChars;
305 RowReference targetRow = GetRowReferenceContainingPosition (pos);
306 size_t rowDiff = CountRowDifference (targetRow, GetTopRowReferenceInWindow ());
307 return (deltaChars >= 0) ? rowDiff : -long (rowDiff);
310ptrdiff_t SimpleTextImager::CalculateCharDeltaFromRowDeltaFromTopOfWindow (ptrdiff_t deltaRows)
const
312 RowReference row = GetIthRowReferenceFromHere (GetTopRowReferenceInWindow (), deltaRows);
313 return long (GetStartOfRow (row)) - long (GetMarkerPositionOfStartOfWindow ());
316void SimpleTextImager::ScrollByIfRoom (ptrdiff_t downByRows)
318 RowReference newTopRow = GetTopRowReferenceInWindow ();
319 (void)GetIthRowReferenceFromHere (&newTopRow, downByRows);
320 SetTopRowInWindow (newTopRow);
327void SimpleTextImager::ScrollSoShowing (
size_t markerPos,
size_t andTryToShowMarkerPos)
329 Assert (markerPos >= 0);
330 Assert (markerPos <= GetLength ());
331 Assert (fTotalRowsInWindow == 0 or fTotalRowsInWindow == ComputeRowsThatWouldFitInWindowWithTopRow (GetTopRowReferenceInWindow ()));
333 if (andTryToShowMarkerPos == 0) {
334 andTryToShowMarkerPos = markerPos;
336 Assert (andTryToShowMarkerPos >= 0);
337 Assert (andTryToShowMarkerPos <= GetLength ());
345 size_t startOfWindow = GetMarkerPositionOfStartOfWindow ();
346 size_t endOfWindow = GetMarkerPositionOfEndOfWindow ();
347 if (markerPos >= startOfWindow and markerPos < endOfWindow and andTryToShowMarkerPos >= startOfWindow and andTryToShowMarkerPos < endOfWindow) {
348 ScrollSoShowingHHelper (markerPos, andTryToShowMarkerPos);
352 RowReference originalTop = GetTopRowReferenceInWindow ();
369 RowReference newTop = originalTop;
375 if (markerPos < newTop.GetPartitionMarker ()->GetStart () / 2) {
376 newTop = GetRowReferenceContainingPosition (0);
378 else if (markerPos > (GetEnd () + newTop.GetPartitionMarker ()->GetEnd ()) / 2) {
379 newTop = GetRowReferenceContainingPosition (GetEnd ());
383 while (markerPos < newTop.GetPartitionMarker ()->GetStart ()) {
384 newTop = RowReference (newTop.GetPartitionMarker ()->GetPrevious ());
388 if (not PositionWouldFitInWindowWithThisTopRow (markerPos, newTop)) {
389 while (markerPos > newTop.GetPartitionMarker ()->GetEnd ()) {
390 if (newTop.GetPartitionMarker ()->GetNext () == NULL) {
394 newTop = RowReference (newTop.GetPartitionMarker ()->GetNext ());
396 Assert (Contains (markerPos, markerPos, *newTop.GetPartitionMarker ()));
403 while (markerPos < GetStartOfRow (newTop) and GetPreviousRowReference (&newTop))
405 while (not PositionWouldFitInWindowWithThisTopRow (markerPos, newTop) and GetNextRowReference (&newTop))
409 Assert (markerPos >= GetStartOfRow (newTop));
410 Assert (PositionWouldFitInWindowWithThisTopRow (markerPos, newTop));
416 while (not PositionWouldFitInWindowWithThisTopRow (andTryToShowMarkerPos, newTop)) {
417 RowReference trailNewTop = newTop;
418 if (andTryToShowMarkerPos < GetStartOfRow (trailNewTop)) {
419 if (not GetPreviousRowReference (&trailNewTop)) {
424 if (not GetNextRowReference (&trailNewTop)) {
428 if (PositionWouldFitInWindowWithThisTopRow (markerPos, trailNewTop)) {
429 newTop = trailNewTop;
440 const unsigned kRowMoveThreshold = 1;
441 if (CountRowDifference (originalTop, newTop) > kRowMoveThreshold) {
442 bool mustPreserveSecondPos = PositionWouldFitInWindowWithThisTopRow (andTryToShowMarkerPos, newTop);
446 size_t topMarkerPos = min (markerPos, andTryToShowMarkerPos);
447 size_t botMarkerPos = max (markerPos, andTryToShowMarkerPos);
448 size_t numRowsAbove = CountRowDifference (newTop, GetRowReferenceContainingPosition (topMarkerPos));
449 size_t rowsInWindow = ComputeRowsThatWouldFitInWindowWithTopRow (newTop);
450 RowReference lastRowInWindow = GetIthRowReferenceFromHere (newTop, rowsInWindow - 1);
451 size_t numRowsBelow = CountRowDifference (lastRowInWindow, GetRowReferenceContainingPosition (botMarkerPos));
453 size_t numRowsToSpare = numRowsAbove + numRowsBelow;
456 RowReference trailNewTop = newTop;
457 GetIthRowReferenceFromHere (&trailNewTop,
int (numRowsAbove) -
int (numRowsToSpare / 2));
458 if (PositionWouldFitInWindowWithThisTopRow (markerPos, trailNewTop) and
459 (not mustPreserveSecondPos or PositionWouldFitInWindowWithThisTopRow (andTryToShowMarkerPos, trailNewTop))) {
460 newTop = trailNewTop;
464 SetTopRowInWindow (newTop);
466 Assert (GetMarkerPositionOfStartOfWindow () <= markerPos and markerPos <= GetMarkerPositionOfEndOfWindow ());
471 ScrollSoShowingHHelper (markerPos, andTryToShowMarkerPos);
474void SimpleTextImager::SetTopRowInWindow (RowReference row)
476 if (GetForceAllRowsShowing ()) {
477 row = AdjustPotentialTopRowReferenceSoWholeWindowUsed (row);
479 if (row != GetTopRowReferenceInWindow ()) {
480 SetTopRowInWindow_ (row);
481 InvalidateScrollBarParameters ();
485void SimpleTextImager::Draw (
const Led_Rect& subsetToDraw,
bool printing)
489 Led_Rect rowsLeftToDrawRect = GetWindowRect ();
491 Tablet_Acquirer tablet_ (
this);
492 Tablet* tablet = tablet_;
500#if qStroika_Platform_Windows
501 GDI_Obj_Selector pen (tablet, ::GetStockObject (NULL_PEN));
502 GDI_Obj_Selector brush (tablet, ::GetStockObject (NULL_BRUSH));
509 OffscreenTablet thisIsOurNewOST;
510 if (GetImageUsingOffscreenBitmaps () and not printing) {
511 thisIsOurNewOST.Setup (tablet_);
515 size_t totalRowsInWindow = GetTotalRowsInWindow_ ();
516 RowReference topRowInWindow = GetTopRowReferenceInWindow ();
517 size_t rowsLeftInWindow = totalRowsInWindow;
518 for (PartitionMarker* pm = topRowInWindow.GetPartitionMarker (); rowsLeftInWindow != 0; pm = pm->GetNext ()) {
520 size_t startSubRow = 0;
521 size_t maxSubRow = 0;
522 maxSubRow = rowsLeftInWindow - 1 + startSubRow;
523 size_t rowsDrawn = 0;
524 DrawPartitionElement (pm, startSubRow, maxSubRow, tablet, (GetImageUsingOffscreenBitmaps () and not printing) ? &thisIsOurNewOST : NULL,
525 printing, subsetToDraw, &rowsLeftToDrawRect, &rowsDrawn);
526 Assert (rowsLeftInWindow >= rowsDrawn);
527 rowsLeftInWindow -= rowsDrawn;
533 Assert (tablet == tablet_);
535 Led_Rect eraser = GetWindowRect ();
536 eraser.top = rowsLeftToDrawRect.top;
537 eraser.bottom = subsetToDraw.bottom;
539 if (eraser.top > eraser.bottom) {
540 eraser.bottom = eraser.top;
547 if (((eraser.top >= subsetToDraw.top and eraser.top <= subsetToDraw.bottom) or
548 (eraser.bottom >= subsetToDraw.top and eraser.bottom <= subsetToDraw.bottom)) and
549 (eraser.GetHeight () > 0 and eraser.GetWidth () > 0)) {
551 if (GetImageUsingOffscreenBitmaps () and not printing) {
552 tablet = thisIsOurNewOST.PrepareRect (eraser);
554 EraseBackground (tablet, eraser, printing);
558 size_t hilightStart = GetSelectionStart ();
559 size_t hilightEnd = GetSelectionEnd ();
560 size_t end = GetMarkerPositionOfEndOfWindow ();
561 bool segmentHilightedAtEnd = GetSelectionShown () and (hilightStart < end) and (end <= hilightEnd);
562 if (not printing and segmentHilightedAtEnd) {
563 HilightARectangle (tablet, eraser);
566 if (GetImageUsingOffscreenBitmaps () and not printing) {
570 thisIsOurNewOST.BlastBitmapToOrigTablet ();
585void SimpleTextImager::DrawPartitionElement (PartitionMarker* pm,
size_t startSubRow,
size_t , Tablet* tablet, OffscreenTablet* offscreenTablet,
586 bool printing,
const Led_Rect& subsetToDraw, Led_Rect* remainingDrawArea,
size_t* rowsDrawn)
592 size_t start = pm->GetStart ();
593 size_t end = pm->GetEnd ();
595 Assert (end <= GetLength () + 1);
596 if (end == GetLength () + 1) {
600 Tablet* savedTablet = tablet;
601 size_t endSubRow = 0;
604 for (
size_t subRow = startSubRow; subRow <= endSubRow; ++subRow) {
605 Led_Rect currentRowRect = *remainingDrawArea;
606 currentRowRect.bottom = currentRowRect.top + GetRowHeight ();
607 DistanceType interlineSpace = GetInterLineSpace ();
608 if ((currentRowRect.bottom + CoordinateType (interlineSpace) > subsetToDraw.top) and (currentRowRect.top < subsetToDraw.bottom)) {
613 size_t rowStart = start;
618 Assert (rowEnd < GetEnd () + 1);
619 size_t prevToEnd = FindPreviousCharacter (rowEnd);
620 if (prevToEnd >= rowStart and prevToEnd < GetEnd ()) {
622 CopyOut (prevToEnd, 1, &lastChar);
623 if (RemoveMappedDisplayCharacters (&lastChar, 1) == 0) {
629 TextLayoutBlock_Copy rowText = GetTextLayoutBlock (rowStart, rowEnd);
631 if (offscreenTablet != NULL) {
632 tablet = offscreenTablet->PrepareRect (currentRowRect, interlineSpace);
636 Led_Rect invalidRowRect = currentRowRect;
637 invalidRowRect.left = subsetToDraw.left;
638 invalidRowRect.right = subsetToDraw.right;
643 DrawRow (tablet, currentRowRect, invalidRowRect, rowText, rowStart, rowEnd, printing);
649 if (interlineSpace != 0) {
650 size_t hilightStart = GetSelectionStart ();
651 size_t hilightEnd = GetSelectionEnd ();
652 bool segmentHilightedAtEnd = GetSelectionShown () and (hilightStart < rowEnd) and (rowEnd <= hilightEnd);
653 if (pm->GetNext () == NULL) {
654 segmentHilightedAtEnd =
false;
656 DrawInterLineSpace (interlineSpace, tablet, currentRowRect.bottom, segmentHilightedAtEnd, printing);
659 if (offscreenTablet != NULL) {
663 offscreenTablet->BlastBitmapToOrigTablet ();
664 tablet = savedTablet;
668 remainingDrawArea->top = currentRowRect.bottom + interlineSpace;
673DistanceType SimpleTextImager::ComputeMaxHScrollPos ()
const
675 DistanceType maxHWidth = 0;
683 DistanceType width = CalculateLongestRowInWindowPixelWidth ();
684 if (GetHScrollPos () != 0) {
685 width = max (width, GetHScrollPos () + GetWindowRect ().GetWidth ());
687 maxHWidth = max<DistanceType> (width, 1);
689 DistanceType wWidth = GetWindowRect ().GetWidth ();
690 if (maxHWidth > wWidth) {
691 return maxHWidth - wWidth;
698Led_Rect SimpleTextImager::GetCharLocation (
size_t afterPosition)
const
700 return (GetCharLocationRowRelative (afterPosition, RowReference (GetFirstPartitionMarker ())));
703Led_Rect SimpleTextImager::GetCharWindowLocation (
size_t afterPosition)
const
705 Led_Point windowOrigin = GetWindowRect ().GetOrigin () - Led_Point (0, GetHScrollPos ());
706 return windowOrigin + GetCharLocationRowRelative (afterPosition, GetTopRowReferenceInWindow (), GetTotalRowsInWindow_ ());
709size_t SimpleTextImager::GetCharAtLocation (
const Led_Point& where)
const
711 return GetCharAtLocationRowRelative (where, RowReference (GetFirstPartitionMarker ()));
714size_t SimpleTextImager::GetCharAtWindowLocation (
const Led_Point& where)
const
716 Led_Point windowOrigin = GetWindowRect ().GetOrigin () - Led_Point (0, GetHScrollPos ());
717 return GetCharAtLocationRowRelative (where - windowOrigin, GetTopRowReferenceInWindow (), GetTotalRowsInWindow_ ());
720size_t SimpleTextImager::GetStartOfRow (
size_t rowNumber)
const
724 return (GetStartOfRow (GetIthRowReference (rowNumber)));
727size_t SimpleTextImager::GetStartOfRowContainingPosition (
size_t charPosition)
const
729 return GetStartOfRow (GetRowReferenceContainingPosition (charPosition));
732size_t SimpleTextImager::GetEndOfRow (
size_t rowNumber)
const
736 return GetEndOfRow (GetIthRowReference (rowNumber));
739size_t SimpleTextImager::GetEndOfRowContainingPosition (
size_t charPosition)
const
741 return GetEndOfRow (GetRowReferenceContainingPosition (charPosition));
744size_t SimpleTextImager::GetRealEndOfRow (
size_t rowNumber)
const
748 return GetRealEndOfRow (GetIthRowReference (rowNumber));
751size_t SimpleTextImager::GetRealEndOfRowContainingPosition (
size_t charPosition)
const
753 return GetRealEndOfRow (GetRowReferenceContainingPosition (charPosition));
756size_t SimpleTextImager::GetStartOfRow (RowReference row)
const
758 PartitionMarker* cur = row.GetPartitionMarker ();
760 return cur->GetStart ();
763size_t SimpleTextImager::GetEndOfRow (RowReference row)
const
765 size_t markerEnd = GetRealEndOfRow (row);
769 Assert (markerEnd <= GetLength () + 1);
770 if (markerEnd == GetLength () + 1) {
771 return (GetLength ());
773 size_t prevToEnd = FindPreviousCharacter (markerEnd);
774 if (prevToEnd >= GetStartOfRow (row)) {
776 CopyOut (prevToEnd, 1, &lastChar);
777 if (RemoveMappedDisplayCharacters (&lastChar, 1) == 0) {
784size_t SimpleTextImager::GetRealEndOfRow (RowReference row)
const
786 PartitionMarker* cur = row.GetPartitionMarker ();
788 Assert (cur->GetEnd () > 0);
789 size_t markerEnd = cur->GetEnd ();
790 Assert (markerEnd <= GetLength () + 1);
794SimpleTextImager::RowReference SimpleTextImager::GetRowReferenceContainingPosition (
size_t charPosition)
const
796 Require (charPosition >= 0);
797 Require (charPosition <= GetEnd ());
798 PartitionMarker* pm = GetPartitionMarkerContainingPosition (charPosition);
800 return (RowReference{pm});
803size_t SimpleTextImager::GetRowContainingPosition (
size_t charPosition)
const
805 return GetRowNumber (GetRowReferenceContainingPosition (charPosition));
808size_t SimpleTextImager::GetRowCount ()
const
812 for (PartitionMarker* cur = GetFirstPartitionMarker (); cur != NULL; cur = cur->GetNext ()) {
813 [[maybe_unused]] PartitionMarker* pm = cur;
821Led_Rect SimpleTextImager::GetCharLocationRowRelativeByPosition (
size_t afterPosition,
size_t positionOfTopRow,
size_t maxRowsToCheck)
const
823 return GetCharLocationRowRelative (afterPosition, GetRowReferenceContainingPosition (positionOfTopRow), maxRowsToCheck);
826DistanceType SimpleTextImager::GetRowHeight (
size_t )
const
828 return (GetRowHeight ());
835DistanceType SimpleTextImager::GetRowRelativeBaselineOfRowContainingPosition (
size_t charPosition)
const
837 RowReference thisRow = GetRowReferenceContainingPosition (charPosition);
838 size_t startOfRow = GetStartOfRow (thisRow);
839 size_t endOfRow = GetEndOfRow (thisRow);
840 return MeasureSegmentBaseLine (startOfRow, endOfRow);
843void SimpleTextImager::GetStableTypingRegionContaingMarkerRange (
size_t fromMarkerPos,
size_t toMarkerPos,
size_t* expandedFromMarkerPos,
844 size_t* expandedToMarkerPos)
const
848 Assert (fromMarkerPos >= 0);
849 Assert (fromMarkerPos <= toMarkerPos);
850 Assert (toMarkerPos <= GetEnd ());
852 size_t curTopRowRelativeRowNumber = 0;
854 RowReference curRow = GetTopRowReferenceInWindow ();
856 PartitionMarker* cur = curRow.GetPartitionMarker ();
858 size_t start = cur->GetStart ();
859 size_t end = cur->GetEnd ();
864 if (cur->GetNext () == NULL) {
871 if (curTopRowRelativeRowNumber == 0 and (fromMarkerPos < start)) {
875 ++curTopRowRelativeRowNumber;
877 if (Contains (*cur, fromMarkerPos) and Contains (*cur, toMarkerPos)) {
878 (*expandedFromMarkerPos) = start;
879 (*expandedToMarkerPos) = end;
880 Assert ((*expandedFromMarkerPos) >= 0);
881 Assert ((*expandedFromMarkerPos) <= (*expandedToMarkerPos));
882 Assert ((*expandedToMarkerPos) <= GetEnd ());
886 if (curTopRowRelativeRowNumber >= GetTotalRowsInWindow_ ()) {
892 }
while (GetNextRowReference (&curRow));
894 (*expandedFromMarkerPos) = 0;
895 (*expandedToMarkerPos) = GetEnd ();
898DistanceType SimpleTextImager::GetHeightOfRows (
size_t startingRow,
size_t rowCount)
const
900 return (GetHeightOfRows (GetIthRowReference (startingRow), rowCount));
903DistanceType SimpleTextImager::GetHeightOfRows (RowReference startingRow,
size_t rowCount)
const
905 DistanceType height = 0;
906 for (RowReference curRow = startingRow; rowCount > 0; --rowCount) {
907 PartitionMarker* curPM = curRow.GetPartitionMarker ();
908 height += GetRowHeight ();
909 height += GetInterLineSpace (curPM);
910 (void)GetNextRowReference (&curRow);
920void SimpleTextImager::SetInterLineSpace (DistanceType interlineSpace)
922 fInterlineSpace = interlineSpace;
933DistanceType SimpleTextImager::GetInterLineSpace (PartitionMarker* )
const
935 return GetInterLineSpace ();
945void SimpleTextImager::ChangedInterLineSpace (PartitionMarker* )
950void SimpleTextImager::SetDefaultFont (
const IncrementalFontSpecification& defaultFont)
953 inherited::SetDefaultFont (defaultFont);
955 TabletChangedMetrics ();
957 catch (NotFullyInitialized&) {
965void SimpleTextImager::DidUpdateText (
const UpdateInfo& updateInfo)
noexcept
967 InvalidateTotalRowsInWindow ();
968 inherited::DidUpdateText (updateInfo);
970 AssureWholeWindowUsedIfNeeded ();
971 InvalidateScrollBarParameters ();
974void SimpleTextImager::SetWindowRect (
const Led_Rect& windowRect)
976 bool heightChanged = GetWindowRect ().GetHeight () != windowRect.GetHeight ();
977 inherited::SetWindowRect (windowRect);
978 if (heightChanged and PeekAtTextStore () != NULL) {
979 InvalidateTotalRowsInWindow ();
980 AssureWholeWindowUsedIfNeeded ();
981 InvalidateScrollBarParameters ();
985void SimpleTextImager::InvalidateAllCaches ()
987 inherited::InvalidateAllCaches ();
988 InvalidateRowHeight ();
989 if (GetPartition ().get () !=
nullptr) {
992 InvalidateScrollBarParameters ();
993 AssureWholeWindowUsedIfNeeded ();
994 InvalidateTotalRowsInWindow ();
998SimpleTextImager::RowReference SimpleTextImager::AdjustPotentialTopRowReferenceSoWholeWindowUsed (
const RowReference& potentialTopRow)
1005 if (potentialTopRow.GetPartitionMarker ()->GetPrevious () == NULL) {
1006 return potentialTopRow;
1009 CoordinateType windowHeight = GetWindowRect ().GetHeight ();
1010 CoordinateType heightUsed = 0;
1012 for (RowReference curRow = potentialTopRow;;) {
1013 PartitionMarker* curPM = curRow.GetPartitionMarker ();
1014 heightUsed += GetRowHeight ();
1015 heightUsed += GetInterLineSpace (curPM);
1016 if (heightUsed >= windowHeight) {
1017 return (potentialTopRow);
1019 if (not GetNextRowReference (&curRow)) {
1026 for (RowReference curRow = potentialTopRow;;) {
1027 if (not GetPreviousRowReference (&curRow)) {
1032 PartitionMarker* curPM = curRow.GetPartitionMarker ();
1033 heightUsed += GetRowHeight ();
1034 heightUsed += GetInterLineSpace (curPM);
1035 if (heightUsed > windowHeight) {
1037 [[maybe_unused]]
bool result = GetNextRowReference (&curRow);
1041 else if (heightUsed == windowHeight) {
1046 return (potentialTopRow);
1049bool SimpleTextImager::PositionWouldFitInWindowWithThisTopRow (
size_t markerPos,
const RowReference& newTopRow)
1051 if (markerPos < GetStartOfRow (newTopRow)) {
1055 size_t rowCount = ComputeRowsThatWouldFitInWindowWithTopRow (newTopRow);
1056 RowReference lastRow = GetIthRowReferenceFromHere (newTopRow, rowCount - 1);
1058 return (markerPos < GetRealEndOfRow (lastRow));
1061size_t SimpleTextImager::ComputeRowsThatWouldFitInWindowWithTopRow (
const RowReference& newTopRow)
const
1067 CoordinateType windowHeight = GetWindowRect ().GetHeight ();
1073 size_t rowCount = 0;
1074 CoordinateType heightUsed = 0;
1075 for (RowReference curRow = newTopRow;;) {
1077 PartitionMarker* curPM = curRow.GetPartitionMarker ();
1078 heightUsed += GetRowHeight ();
1079 heightUsed += GetInterLineSpace (curPM);
1080 if (heightUsed > windowHeight) {
1085 else if (heightUsed == windowHeight) {
1089 if (not GetNextRowReference (&curRow)) {
1093 if (rowCount == 0) {
1100Led_Rect SimpleTextImager::GetCharLocationRowRelative (
size_t afterPosition, RowReference topRow,
size_t maxRowsToCheck)
const
1103 const Led_Rect kMagicBeforeRect = Led_Rect (-10000, 0, 0, 0);
1104 const Led_Rect kMagicAfterRect = Led_Rect (10000, 0, 0, 0);
1106 Assert (afterPosition >= 0);
1107 Assert (afterPosition <= GetEnd ());
1109 if (afterPosition < GetStartOfRow (topRow)) {
1110 return (kMagicBeforeRect);
1113 RowReference curRow = topRow;
1114 size_t curTopRowRelativeRowNumber = 0;
1115 CoordinateType topVPos = 0;
1117 PartitionMarker* cur = curRow.GetPartitionMarker ();
1119 size_t start = cur->GetStart ();
1120 size_t end = cur->GetEnd ();
1122 Assert (end <= GetEnd () + 1);
1124 ++curTopRowRelativeRowNumber;
1126 if (afterPosition >= start and afterPosition < end) {
1127 Assert (start <= afterPosition);
1128 DistanceType hStart = 0;
1129 DistanceType hEnd = 0;
1130 GetRowRelativeCharLoc (afterPosition, &hStart, &hEnd);
1131 Assert (hStart <= hEnd);
1132 return (Led_Rect (topVPos, hStart, GetRowHeight (), hEnd - hStart));
1135 topVPos += GetRowHeight ();
1136 topVPos += GetInterLineSpace (cur);
1138 if (curTopRowRelativeRowNumber >= maxRowsToCheck) {
1141 }
while (GetNextRowReference (&curRow));
1143 return (kMagicAfterRect);
1146size_t SimpleTextImager::GetCharAtLocationRowRelative (
const Led_Point& where, RowReference topRow,
size_t maxRowsToCheck)
const
1158 RowReference curRow = topRow;
1159 size_t curTopRowRelativeRowNumber = 0;
1160 CoordinateType topVPos = 0;
1162 PartitionMarker* cur = curRow.GetPartitionMarker ();
1165 size_t start = cur->GetStart ();
1170 DistanceType interLineSpace = GetInterLineSpace (cur);
1172 ++curTopRowRelativeRowNumber;
1173 if (where.v >= topVPos and where.v < topVPos + CoordinateType (GetRowHeight () + interLineSpace)) {
1174 return GetRowRelativeCharAtLoc (where.h, start);
1177 if (curTopRowRelativeRowNumber >= maxRowsToCheck) {
1181 topVPos += GetRowHeight () + interLineSpace;
1182 }
while (GetNextRowReference (&curRow));
1192bool SimpleTextImager::ContainsMappedDisplayCharacters (
const Led_tChar* text,
size_t nTChars)
const
1194 return ContainsMappedDisplayCharacters_HelperForChar (text, nTChars,
'\n') or inherited::ContainsMappedDisplayCharacters (text, nTChars);
1201size_t SimpleTextImager::RemoveMappedDisplayCharacters (Led_tChar* copyText,
size_t nTChars)
const
1203 size_t newLen = inherited::RemoveMappedDisplayCharacters (copyText, nTChars);
1204 Assert (newLen <= nTChars);
1205 size_t newerLen = RemoveMappedDisplayCharacters_HelperForChar (copyText, newLen,
'\n');
1206 Assert (newerLen <= newLen);
1207 Assert (newerLen <= nTChars);
#define RequireNotNull(p)
#define AssertMember(p, c)