diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /vcl/source/edit/textdata.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vcl/source/edit/textdata.cxx')
-rw-r--r-- | vcl/source/edit/textdata.cxx | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/vcl/source/edit/textdata.cxx b/vcl/source/edit/textdata.cxx new file mode 100644 index 000000000..165dbfde9 --- /dev/null +++ b/vcl/source/edit/textdata.cxx @@ -0,0 +1,343 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <sal/log.hxx> +#include <osl/diagnose.h> + +#include <cstddef> + +#include <vcl/textdata.hxx> +#include "textdat2.hxx" + + +TextSelection::TextSelection() +{ +} + +TextSelection::TextSelection( const TextPaM& rPaM ) : + maStartPaM( rPaM ), maEndPaM( rPaM ) +{ +} + +TextSelection::TextSelection( const TextPaM& rStart, const TextPaM& rEnd ) : + maStartPaM( rStart ), maEndPaM( rEnd ) +{ +} + +void TextSelection::Justify() +{ + if ( maEndPaM < maStartPaM ) + { + TextPaM aTemp( maStartPaM ); + maStartPaM = maEndPaM; + maEndPaM = aTemp; + } +} + +TETextPortionList::TETextPortionList() +{ +} + +TETextPortionList::~TETextPortionList() +{ + Reset(); +} + +TETextPortion* TETextPortionList::operator[]( std::size_t nPos ) +{ + return maPortions[ nPos ].get(); +} + +std::vector<std::unique_ptr<TETextPortion>>::iterator TETextPortionList::begin() +{ + return maPortions.begin(); +} + +std::vector<std::unique_ptr<TETextPortion>>::const_iterator TETextPortionList::begin() const +{ + return maPortions.begin(); +} + +std::vector<std::unique_ptr<TETextPortion>>::iterator TETextPortionList::end() +{ + return maPortions.end(); +} + +std::vector<std::unique_ptr<TETextPortion>>::const_iterator TETextPortionList::end() const +{ + return maPortions.end(); +} + +bool TETextPortionList::empty() const +{ + return maPortions.empty(); +} + +std::size_t TETextPortionList::size() const +{ + return maPortions.size(); +} + +std::vector<std::unique_ptr<TETextPortion>>::iterator TETextPortionList::erase( const std::vector<std::unique_ptr<TETextPortion>>::iterator& aIter ) +{ + return maPortions.erase( aIter ); +} + +std::vector<std::unique_ptr<TETextPortion>>::iterator TETextPortionList::insert( const std::vector<std::unique_ptr<TETextPortion>>::iterator& aIter, + std::unique_ptr<TETextPortion> pTP ) +{ + return maPortions.insert( aIter, std::move(pTP) ); +} + +void TETextPortionList::push_back( std::unique_ptr<TETextPortion> pTP ) +{ + maPortions.push_back( std::move(pTP) ); +} + +void TETextPortionList::Reset() +{ + maPortions.clear(); +} + +void TETextPortionList::DeleteFromPortion( std::size_t nDelFrom ) +{ + SAL_WARN_IF( ( nDelFrom >= maPortions.size() ) && ( (nDelFrom != 0) || (!maPortions.empty()) ), "vcl", "DeleteFromPortion: Out of range" ); + maPortions.erase( maPortions.begin() + nDelFrom, maPortions.end() ); +} + +std::size_t TETextPortionList::FindPortion( sal_Int32 nCharPos, sal_Int32& nPortionStart, bool bPreferStartingPortion ) +{ + // find left portion at nCharPos at portion border + sal_Int32 nTmpPos = 0; + for ( std::size_t nPortion = 0; nPortion < maPortions.size(); nPortion++ ) + { + TETextPortion* pPortion = maPortions[ nPortion ].get(); + nTmpPos += pPortion->GetLen(); + if ( nTmpPos >= nCharPos ) + { + // take this one if we don't prefer the starting portion, or if it's the last one + if ( ( nTmpPos != nCharPos ) || !bPreferStartingPortion || ( nPortion == maPortions.size() - 1 ) ) + { + nPortionStart = nTmpPos - pPortion->GetLen(); + return nPortion; + } + } + } + OSL_FAIL( "FindPortion: Not found!" ); + return ( maPortions.size() - 1 ); +} + +TEParaPortion::TEParaPortion( TextNode* pN ) + : mpNode {pN} + , mnInvalidPosStart {0} + , mnInvalidDiff {0} + , mbInvalid {true} + , mbSimple {false} +{ +} + +TEParaPortion::~TEParaPortion() +{ +} + +void TEParaPortion::MarkInvalid( sal_Int32 nStart, sal_Int32 nDiff ) +{ + if ( !mbInvalid ) + { + mnInvalidPosStart = ( nDiff >= 0 ) ? nStart : ( nStart + nDiff ); + mnInvalidDiff = nDiff; + } + else + { + // simple consecutive typing + if ( ( nDiff > 0 ) && ( mnInvalidDiff > 0 ) && + ( ( mnInvalidPosStart+mnInvalidDiff ) == nStart ) ) + { + mnInvalidDiff = mnInvalidDiff + nDiff; + } + // simple consecutive deleting + else if ( ( nDiff < 0 ) && ( mnInvalidDiff < 0 ) && ( mnInvalidPosStart == nStart ) ) + { + mnInvalidPosStart = mnInvalidPosStart + nDiff; + mnInvalidDiff = mnInvalidDiff + nDiff; + } + else + { + SAL_WARN_IF( ( nDiff < 0 ) && ( (nStart+nDiff) < 0 ), "vcl", "MarkInvalid: Diff out of Range" ); + mnInvalidPosStart = std::min( mnInvalidPosStart, nDiff < 0 ? nStart+nDiff : nDiff ); + mnInvalidDiff = 0; + mbSimple = false; + } + } + + maWritingDirectionInfos.clear(); + + mbInvalid = true; +} + +void TEParaPortion::MarkSelectionInvalid( sal_Int32 nStart ) +{ + if ( !mbInvalid ) + { + mnInvalidPosStart = nStart; + } + else + { + mnInvalidPosStart = std::min( mnInvalidPosStart, nStart ); + } + + maWritingDirectionInfos.clear(); + + mnInvalidDiff = 0; + mbInvalid = true; + mbSimple = false; +} + +std::vector<TextLine>::size_type TEParaPortion::GetLineNumber( sal_Int32 nChar, bool bInclEnd ) +{ + for ( std::vector<TextLine>::size_type nLine = 0; nLine < maLines.size(); nLine++ ) + { + TextLine& rLine = maLines[ nLine ]; + if ( ( bInclEnd && ( rLine.GetEnd() >= nChar ) ) || + ( rLine.GetEnd() > nChar ) ) + { + return nLine; + } + } + + // Then it should be at the end of the last line + OSL_ENSURE(nChar == maLines.back().GetEnd(), "wrong Index"); + OSL_ENSURE(!bInclEnd, "Line not found: FindLine"); + return ( maLines.size() - 1 ); +} + +void TEParaPortion::CorrectValuesBehindLastFormattedLine( sal_uInt16 nLastFormattedLine ) +{ + sal_uInt16 nLines = maLines.size(); + SAL_WARN_IF( !nLines, "vcl", "CorrectPortionNumbersFromLine: Empty portion?" ); + if ( nLastFormattedLine < ( nLines - 1 ) ) + { + const TextLine& rLastFormatted = maLines[ nLastFormattedLine ]; + const TextLine& rUnformatted = maLines[ nLastFormattedLine+1 ]; + std::ptrdiff_t nPortionDiff = rUnformatted.GetStartPortion() - rLastFormatted.GetEndPortion(); + sal_Int32 nTextDiff = rUnformatted.GetStart() - rLastFormatted.GetEnd(); + nTextDiff++; // LastFormatted.GetEnd() was inclusive => subtracted one too much! + + // The first unformatted one has to start exactly one portion past the last + // formatted one. + // If a portion got split in the changed row, nLastEnd could be > nNextStart! + std::ptrdiff_t nPDiff = -( nPortionDiff-1 ); + const sal_Int32 nTDiff = -( nTextDiff-1 ); + if ( nPDiff || nTDiff ) + { + for ( sal_uInt16 nL = nLastFormattedLine+1; nL < nLines; nL++ ) + { + TextLine& rLine = maLines[ nL ]; + + rLine.SetStartPortion(rLine.GetStartPortion() + nPDiff); + rLine.SetEndPortion(rLine.GetEndPortion() + nPDiff); + + rLine.SetStart(rLine.GetStart() + nTDiff); + rLine.SetEnd(rLine.GetEnd() + nTDiff); + + rLine.SetValid(); + } + } + } +} + +TEParaPortions::~TEParaPortions() +{ +} + +IdleFormatter::IdleFormatter() + : mpView(nullptr) + , mnRestarts(0) +{ + SetPriority(TaskPriority::HIGH_IDLE); +} + +IdleFormatter::~IdleFormatter() +{ + mpView = nullptr; +} + +void IdleFormatter::DoIdleFormat( TextView* pV, sal_uInt16 nMaxRestarts ) +{ + mpView = pV; + + if ( IsActive() ) + mnRestarts++; + + if ( mnRestarts > nMaxRestarts ) + { + mnRestarts = 0; + Invoke(); + } + else + { + Start(); + } +} + +void IdleFormatter::ForceTimeout() +{ + if ( IsActive() ) + { + Stop(); + mnRestarts = 0; + Invoke(); + } +} + +TextHint::TextHint( SfxHintId Id ) : SfxHint( Id ), mnValue(0) +{ +} + +TextHint::TextHint( SfxHintId Id, sal_uLong nValue ) : SfxHint( Id ), mnValue(nValue) +{ +} + +TEIMEInfos::TEIMEInfos( const TextPaM& rPos, const OUString& rOldTextAfterStartPos ) + : aOldTextAfterStartPos(rOldTextAfterStartPos) + , aPos(rPos) + , nLen(0) + , bWasCursorOverwrite(false) +{ +} + +TEIMEInfos::~TEIMEInfos() +{ +} + +void TEIMEInfos::CopyAttribs(const ExtTextInputAttr* pA, sal_Int32 nL) +{ + nLen = nL; + pAttribs.reset( new ExtTextInputAttr[ nL ] ); + memcpy( pAttribs.get(), pA, nL*sizeof(ExtTextInputAttr) ); +} + +void TEIMEInfos::DestroyAttribs() +{ + pAttribs.reset(); + nLen = 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |