4#include "Stroika/Frameworks/StroikaPreComp.h"
8#include "LineBasedPartition.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_Foundation_Common_Platform_MacOS
502 RGBColor oldForeColor = GDI_GetForeColor ();
503 RGBColor oldBackColor = GDI_GetBackColor ();
504#elif qStroika_Foundation_Common_Platform_Windows
505 GDI_Obj_Selector pen (tablet, ::GetStockObject (NULL_PEN));
506 GDI_Obj_Selector brush (tablet, ::GetStockObject (NULL_BRUSH));
513 OffscreenTablet thisIsOurNewOST;
514 if (GetImageUsingOffscreenBitmaps () and not printing) {
515 thisIsOurNewOST.Setup (tablet_);
519 size_t totalRowsInWindow = GetTotalRowsInWindow_ ();
520 RowReference topRowInWindow = GetTopRowReferenceInWindow ();
521 size_t rowsLeftInWindow = totalRowsInWindow;
522 for (PartitionMarker* pm = topRowInWindow.GetPartitionMarker (); rowsLeftInWindow != 0; pm = pm->GetNext ()) {
524 size_t startSubRow = 0;
525 size_t maxSubRow = 0;
526 maxSubRow = rowsLeftInWindow - 1 + startSubRow;
527 size_t rowsDrawn = 0;
528 DrawPartitionElement (pm, startSubRow, maxSubRow, tablet, (GetImageUsingOffscreenBitmaps () and not printing) ? &thisIsOurNewOST : NULL,
529 printing, subsetToDraw, &rowsLeftToDrawRect, &rowsDrawn);
530 Assert (rowsLeftInWindow >= rowsDrawn);
531 rowsLeftInWindow -= rowsDrawn;
537 Assert (tablet == tablet_);
539 Led_Rect eraser = GetWindowRect ();
540 eraser.top = rowsLeftToDrawRect.top;
541 eraser.bottom = subsetToDraw.bottom;
543 if (eraser.top > eraser.bottom) {
544 eraser.bottom = eraser.top;
551 if (((eraser.top >= subsetToDraw.top and eraser.top <= subsetToDraw.bottom) or
552 (eraser.bottom >= subsetToDraw.top and eraser.bottom <= subsetToDraw.bottom)) and
553 (eraser.GetHeight () > 0 and eraser.GetWidth () > 0)) {
555 if (GetImageUsingOffscreenBitmaps () and not printing) {
556 tablet = thisIsOurNewOST.PrepareRect (eraser);
558 EraseBackground (tablet, eraser, printing);
562 size_t hilightStart = GetSelectionStart ();
563 size_t hilightEnd = GetSelectionEnd ();
564 size_t end = GetMarkerPositionOfEndOfWindow ();
565 bool segmentHilightedAtEnd = GetSelectionShown () and (hilightStart < end) and (end <= hilightEnd);
566 if (not printing and segmentHilightedAtEnd) {
567 HilightARectangle (tablet, eraser);
570 if (GetImageUsingOffscreenBitmaps () and not printing) {
574 thisIsOurNewOST.BlastBitmapToOrigTablet ();
581#if qStroika_Foundation_Common_Platform_MacOS
582 Assert (*tablet == Led_GetCurrentGDIPort ());
583 GDI_RGBForeColor (oldForeColor);
584 GDI_RGBBackColor (oldBackColor);
588#if qStroika_Foundation_Common_Platform_MacOS
589 Assert (*tablet == Led_GetCurrentGDIPort ());
590 GDI_RGBForeColor (oldForeColor);
591 GDI_RGBBackColor (oldBackColor);
599void SimpleTextImager::DrawPartitionElement (PartitionMarker* pm,
size_t startSubRow,
size_t , Tablet* tablet, OffscreenTablet* offscreenTablet,
600 bool printing,
const Led_Rect& subsetToDraw, Led_Rect* remainingDrawArea,
size_t* rowsDrawn)
606 size_t start = pm->GetStart ();
607 size_t end = pm->GetEnd ();
609 Assert (end <= GetLength () + 1);
610 if (end == GetLength () + 1) {
614 Tablet* savedTablet = tablet;
615 size_t endSubRow = 0;
618 for (
size_t subRow = startSubRow; subRow <= endSubRow; ++subRow) {
619 Led_Rect currentRowRect = *remainingDrawArea;
620 currentRowRect.bottom = currentRowRect.top + GetRowHeight ();
621 DistanceType interlineSpace = GetInterLineSpace ();
622 if ((currentRowRect.bottom + CoordinateType (interlineSpace) > subsetToDraw.top) and (currentRowRect.top < subsetToDraw.bottom)) {
627 size_t rowStart = start;
632 Assert (rowEnd < GetEnd () + 1);
633 size_t prevToEnd = FindPreviousCharacter (rowEnd);
634 if (prevToEnd >= rowStart and prevToEnd < GetEnd ()) {
636 CopyOut (prevToEnd, 1, &lastChar);
637 if (RemoveMappedDisplayCharacters (&lastChar, 1) == 0) {
643 TextLayoutBlock_Copy rowText = GetTextLayoutBlock (rowStart, rowEnd);
645 if (offscreenTablet != NULL) {
646 tablet = offscreenTablet->PrepareRect (currentRowRect, interlineSpace);
650 Led_Rect invalidRowRect = currentRowRect;
651 invalidRowRect.left = subsetToDraw.left;
652 invalidRowRect.right = subsetToDraw.right;
657 DrawRow (tablet, currentRowRect, invalidRowRect, rowText, rowStart, rowEnd, printing);
663 if (interlineSpace != 0) {
664 size_t hilightStart = GetSelectionStart ();
665 size_t hilightEnd = GetSelectionEnd ();
666 bool segmentHilightedAtEnd = GetSelectionShown () and (hilightStart < rowEnd) and (rowEnd <= hilightEnd);
667 if (pm->GetNext () == NULL) {
668 segmentHilightedAtEnd =
false;
670 DrawInterLineSpace (interlineSpace, tablet, currentRowRect.bottom, segmentHilightedAtEnd, printing);
673 if (offscreenTablet != NULL) {
677 offscreenTablet->BlastBitmapToOrigTablet ();
678 tablet = savedTablet;
682 remainingDrawArea->top = currentRowRect.bottom + interlineSpace;
687DistanceType SimpleTextImager::ComputeMaxHScrollPos ()
const
689 DistanceType maxHWidth = 0;
697 DistanceType width = CalculateLongestRowInWindowPixelWidth ();
698 if (GetHScrollPos () != 0) {
699 width = max (width, GetHScrollPos () + GetWindowRect ().GetWidth ());
701 maxHWidth = max<DistanceType> (width, 1);
703 DistanceType wWidth = GetWindowRect ().GetWidth ();
704 if (maxHWidth > wWidth) {
705 return maxHWidth - wWidth;
712Led_Rect SimpleTextImager::GetCharLocation (
size_t afterPosition)
const
714 return (GetCharLocationRowRelative (afterPosition, RowReference (GetFirstPartitionMarker ())));
717Led_Rect SimpleTextImager::GetCharWindowLocation (
size_t afterPosition)
const
719 Led_Point windowOrigin = GetWindowRect ().GetOrigin () - Led_Point (0, GetHScrollPos ());
720 return windowOrigin + GetCharLocationRowRelative (afterPosition, GetTopRowReferenceInWindow (), GetTotalRowsInWindow_ ());
723size_t SimpleTextImager::GetCharAtLocation (
const Led_Point& where)
const
725 return GetCharAtLocationRowRelative (where, RowReference (GetFirstPartitionMarker ()));
728size_t SimpleTextImager::GetCharAtWindowLocation (
const Led_Point& where)
const
730 Led_Point windowOrigin = GetWindowRect ().GetOrigin () - Led_Point (0, GetHScrollPos ());
731 return GetCharAtLocationRowRelative (where - windowOrigin, GetTopRowReferenceInWindow (), GetTotalRowsInWindow_ ());
734size_t SimpleTextImager::GetStartOfRow (
size_t rowNumber)
const
738 return (GetStartOfRow (GetIthRowReference (rowNumber)));
741size_t SimpleTextImager::GetStartOfRowContainingPosition (
size_t charPosition)
const
743 return GetStartOfRow (GetRowReferenceContainingPosition (charPosition));
746size_t SimpleTextImager::GetEndOfRow (
size_t rowNumber)
const
750 return GetEndOfRow (GetIthRowReference (rowNumber));
753size_t SimpleTextImager::GetEndOfRowContainingPosition (
size_t charPosition)
const
755 return GetEndOfRow (GetRowReferenceContainingPosition (charPosition));
758size_t SimpleTextImager::GetRealEndOfRow (
size_t rowNumber)
const
762 return GetRealEndOfRow (GetIthRowReference (rowNumber));
765size_t SimpleTextImager::GetRealEndOfRowContainingPosition (
size_t charPosition)
const
767 return GetRealEndOfRow (GetRowReferenceContainingPosition (charPosition));
770size_t SimpleTextImager::GetStartOfRow (RowReference row)
const
772 PartitionMarker* cur = row.GetPartitionMarker ();
774 return cur->GetStart ();
777size_t SimpleTextImager::GetEndOfRow (RowReference row)
const
779 size_t markerEnd = GetRealEndOfRow (row);
783 Assert (markerEnd <= GetLength () + 1);
784 if (markerEnd == GetLength () + 1) {
785 return (GetLength ());
787 size_t prevToEnd = FindPreviousCharacter (markerEnd);
788 if (prevToEnd >= GetStartOfRow (row)) {
790 CopyOut (prevToEnd, 1, &lastChar);
791 if (RemoveMappedDisplayCharacters (&lastChar, 1) == 0) {
798size_t SimpleTextImager::GetRealEndOfRow (RowReference row)
const
800 PartitionMarker* cur = row.GetPartitionMarker ();
802 Assert (cur->GetEnd () > 0);
803 size_t markerEnd = cur->GetEnd ();
804 Assert (markerEnd <= GetLength () + 1);
808SimpleTextImager::RowReference SimpleTextImager::GetRowReferenceContainingPosition (
size_t charPosition)
const
810 Require (charPosition >= 0);
811 Require (charPosition <= GetEnd ());
812 PartitionMarker* pm = GetPartitionMarkerContainingPosition (charPosition);
814 return (RowReference{pm});
817size_t SimpleTextImager::GetRowContainingPosition (
size_t charPosition)
const
819 return GetRowNumber (GetRowReferenceContainingPosition (charPosition));
822size_t SimpleTextImager::GetRowCount ()
const
826 for (PartitionMarker* cur = GetFirstPartitionMarker (); cur != NULL; cur = cur->GetNext ()) {
827 [[maybe_unused]] PartitionMarker* pm = cur;
835Led_Rect SimpleTextImager::GetCharLocationRowRelativeByPosition (
size_t afterPosition,
size_t positionOfTopRow,
size_t maxRowsToCheck)
const
837 return GetCharLocationRowRelative (afterPosition, GetRowReferenceContainingPosition (positionOfTopRow), maxRowsToCheck);
840DistanceType SimpleTextImager::GetRowHeight (
size_t )
const
842 return (GetRowHeight ());
849DistanceType SimpleTextImager::GetRowRelativeBaselineOfRowContainingPosition (
size_t charPosition)
const
851 RowReference thisRow = GetRowReferenceContainingPosition (charPosition);
852 size_t startOfRow = GetStartOfRow (thisRow);
853 size_t endOfRow = GetEndOfRow (thisRow);
854 return MeasureSegmentBaseLine (startOfRow, endOfRow);
857void SimpleTextImager::GetStableTypingRegionContaingMarkerRange (
size_t fromMarkerPos,
size_t toMarkerPos,
size_t* expandedFromMarkerPos,
858 size_t* expandedToMarkerPos)
const
862 Assert (fromMarkerPos >= 0);
863 Assert (fromMarkerPos <= toMarkerPos);
864 Assert (toMarkerPos <= GetEnd ());
866 size_t curTopRowRelativeRowNumber = 0;
868 RowReference curRow = GetTopRowReferenceInWindow ();
870 PartitionMarker* cur = curRow.GetPartitionMarker ();
872 size_t start = cur->GetStart ();
873 size_t end = cur->GetEnd ();
878 if (cur->GetNext () == NULL) {
885 if (curTopRowRelativeRowNumber == 0 and (fromMarkerPos < start)) {
889 ++curTopRowRelativeRowNumber;
891 if (Contains (*cur, fromMarkerPos) and Contains (*cur, toMarkerPos)) {
892 (*expandedFromMarkerPos) = start;
893 (*expandedToMarkerPos) = end;
894 Assert ((*expandedFromMarkerPos) >= 0);
895 Assert ((*expandedFromMarkerPos) <= (*expandedToMarkerPos));
896 Assert ((*expandedToMarkerPos) <= GetEnd ());
900 if (curTopRowRelativeRowNumber >= GetTotalRowsInWindow_ ()) {
906 }
while (GetNextRowReference (&curRow));
908 (*expandedFromMarkerPos) = 0;
909 (*expandedToMarkerPos) = GetEnd ();
912DistanceType SimpleTextImager::GetHeightOfRows (
size_t startingRow,
size_t rowCount)
const
914 return (GetHeightOfRows (GetIthRowReference (startingRow), rowCount));
917DistanceType SimpleTextImager::GetHeightOfRows (RowReference startingRow,
size_t rowCount)
const
919 DistanceType height = 0;
920 for (RowReference curRow = startingRow; rowCount > 0; --rowCount) {
921 PartitionMarker* curPM = curRow.GetPartitionMarker ();
922 height += GetRowHeight ();
923 height += GetInterLineSpace (curPM);
924 (void)GetNextRowReference (&curRow);
934void SimpleTextImager::SetInterLineSpace (DistanceType interlineSpace)
936 fInterlineSpace = interlineSpace;
947DistanceType SimpleTextImager::GetInterLineSpace (PartitionMarker* )
const
949 return GetInterLineSpace ();
959void SimpleTextImager::ChangedInterLineSpace (PartitionMarker* )
964void SimpleTextImager::SetDefaultFont (
const IncrementalFontSpecification& defaultFont)
967 inherited::SetDefaultFont (defaultFont);
969 TabletChangedMetrics ();
971 catch (NotFullyInitialized&) {
979void SimpleTextImager::DidUpdateText (
const UpdateInfo& updateInfo)
noexcept
981 InvalidateTotalRowsInWindow ();
982 inherited::DidUpdateText (updateInfo);
984 AssureWholeWindowUsedIfNeeded ();
985 InvalidateScrollBarParameters ();
988void SimpleTextImager::SetWindowRect (
const Led_Rect& windowRect)
990 bool heightChanged = GetWindowRect ().GetHeight () != windowRect.GetHeight ();
991 inherited::SetWindowRect (windowRect);
992 if (heightChanged and PeekAtTextStore () != NULL) {
993 InvalidateTotalRowsInWindow ();
994 AssureWholeWindowUsedIfNeeded ();
995 InvalidateScrollBarParameters ();
999void SimpleTextImager::InvalidateAllCaches ()
1001 inherited::InvalidateAllCaches ();
1002 InvalidateRowHeight ();
1003 if (GetPartition ().get () !=
nullptr) {
1006 InvalidateScrollBarParameters ();
1007 AssureWholeWindowUsedIfNeeded ();
1008 InvalidateTotalRowsInWindow ();
1012SimpleTextImager::RowReference SimpleTextImager::AdjustPotentialTopRowReferenceSoWholeWindowUsed (
const RowReference& potentialTopRow)
1019 if (potentialTopRow.GetPartitionMarker ()->GetPrevious () == NULL) {
1020 return potentialTopRow;
1023 CoordinateType windowHeight = GetWindowRect ().GetHeight ();
1024 CoordinateType heightUsed = 0;
1026 for (RowReference curRow = potentialTopRow;;) {
1027 PartitionMarker* curPM = curRow.GetPartitionMarker ();
1028 heightUsed += GetRowHeight ();
1029 heightUsed += GetInterLineSpace (curPM);
1030 if (heightUsed >= windowHeight) {
1031 return (potentialTopRow);
1033 if (not GetNextRowReference (&curRow)) {
1040 for (RowReference curRow = potentialTopRow;;) {
1041 if (not GetPreviousRowReference (&curRow)) {
1046 PartitionMarker* curPM = curRow.GetPartitionMarker ();
1047 heightUsed += GetRowHeight ();
1048 heightUsed += GetInterLineSpace (curPM);
1049 if (heightUsed > windowHeight) {
1051 [[maybe_unused]]
bool result = GetNextRowReference (&curRow);
1055 else if (heightUsed == windowHeight) {
1060 return (potentialTopRow);
1063bool SimpleTextImager::PositionWouldFitInWindowWithThisTopRow (
size_t markerPos,
const RowReference& newTopRow)
1065 if (markerPos < GetStartOfRow (newTopRow)) {
1069 size_t rowCount = ComputeRowsThatWouldFitInWindowWithTopRow (newTopRow);
1070 RowReference lastRow = GetIthRowReferenceFromHere (newTopRow, rowCount - 1);
1072 return (markerPos < GetRealEndOfRow (lastRow));
1075size_t SimpleTextImager::ComputeRowsThatWouldFitInWindowWithTopRow (
const RowReference& newTopRow)
const
1081 CoordinateType windowHeight = GetWindowRect ().GetHeight ();
1087 size_t rowCount = 0;
1088 CoordinateType heightUsed = 0;
1089 for (RowReference curRow = newTopRow;;) {
1091 PartitionMarker* curPM = curRow.GetPartitionMarker ();
1092 heightUsed += GetRowHeight ();
1093 heightUsed += GetInterLineSpace (curPM);
1094 if (heightUsed > windowHeight) {
1099 else if (heightUsed == windowHeight) {
1103 if (not GetNextRowReference (&curRow)) {
1107 if (rowCount == 0) {
1114Led_Rect SimpleTextImager::GetCharLocationRowRelative (
size_t afterPosition, RowReference topRow,
size_t maxRowsToCheck)
const
1117 const Led_Rect kMagicBeforeRect = Led_Rect (-10000, 0, 0, 0);
1118 const Led_Rect kMagicAfterRect = Led_Rect (10000, 0, 0, 0);
1120 Assert (afterPosition >= 0);
1121 Assert (afterPosition <= GetEnd ());
1123 if (afterPosition < GetStartOfRow (topRow)) {
1124 return (kMagicBeforeRect);
1127 RowReference curRow = topRow;
1128 size_t curTopRowRelativeRowNumber = 0;
1129 CoordinateType topVPos = 0;
1131 PartitionMarker* cur = curRow.GetPartitionMarker ();
1133 size_t start = cur->GetStart ();
1134 size_t end = cur->GetEnd ();
1136 Assert (end <= GetEnd () + 1);
1138 ++curTopRowRelativeRowNumber;
1140 if (afterPosition >= start and afterPosition < end) {
1141 Assert (start <= afterPosition);
1142 DistanceType hStart = 0;
1143 DistanceType hEnd = 0;
1144 GetRowRelativeCharLoc (afterPosition, &hStart, &hEnd);
1145 Assert (hStart <= hEnd);
1146 return (Led_Rect (topVPos, hStart, GetRowHeight (), hEnd - hStart));
1149 topVPos += GetRowHeight ();
1150 topVPos += GetInterLineSpace (cur);
1152 if (curTopRowRelativeRowNumber >= maxRowsToCheck) {
1155 }
while (GetNextRowReference (&curRow));
1157 return (kMagicAfterRect);
1160size_t SimpleTextImager::GetCharAtLocationRowRelative (
const Led_Point& where, RowReference topRow,
size_t maxRowsToCheck)
const
1172 RowReference curRow = topRow;
1173 size_t curTopRowRelativeRowNumber = 0;
1174 CoordinateType topVPos = 0;
1176 PartitionMarker* cur = curRow.GetPartitionMarker ();
1179 size_t start = cur->GetStart ();
1184 DistanceType interLineSpace = GetInterLineSpace (cur);
1186 ++curTopRowRelativeRowNumber;
1187 if (where.v >= topVPos and where.v < topVPos + CoordinateType (GetRowHeight () + interLineSpace)) {
1188 return GetRowRelativeCharAtLoc (where.h, start);
1191 if (curTopRowRelativeRowNumber >= maxRowsToCheck) {
1195 topVPos += GetRowHeight () + interLineSpace;
1196 }
while (GetNextRowReference (&curRow));
1206bool SimpleTextImager::ContainsMappedDisplayCharacters (
const Led_tChar* text,
size_t nTChars)
const
1208 return ContainsMappedDisplayCharacters_HelperForChar (text, nTChars,
'\n') or inherited::ContainsMappedDisplayCharacters (text, nTChars);
1215size_t SimpleTextImager::RemoveMappedDisplayCharacters (Led_tChar* copyText,
size_t nTChars)
const
1217 size_t newLen = inherited::RemoveMappedDisplayCharacters (copyText, nTChars);
1218 Assert (newLen <= nTChars);
1219 size_t newerLen = RemoveMappedDisplayCharacters_HelperForChar (copyText, newLen,
'\n');
1220 Assert (newerLen <= newLen);
1221 Assert (newerLen <= nTChars);
#define RequireNotNull(p)
#define AssertMember(p, c)