/* -*- 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 .
*/
/// returns the index of the first position whose value is smaller /// or equal, and whose following value is equal or larger template<typename T> static size_t FindBreak(const std::vector<T>& rPositions, T nValue);
/// like FindBreak, but finds the last equal or larger position template<typename T> static size_t FindLastBreak(const std::vector<T>& rPositions, T nValue);
OSL_ENSURE( !m_bFinished, "We are already done!" );
// construct string with representation; either directly from // rText, or use resources for special case portions
OUString sDisplay; switch( nType )
{ case PortionType::PostIts: case PortionType::FlyCnt:
sDisplay = OUString(u'\xfffc'); break; case PortionType::Field: case PortionType::Hidden: case PortionType::Combined: case PortionType::IsoRef: // When the field content is empty, input a special character. if (rText.isEmpty())
sDisplay = OUString(u'\xfffc'); else
sDisplay = rText;
m_aFieldPosition.push_back(m_aBuffer.getLength());
m_aFieldPosition.push_back(m_aBuffer.getLength() + rText.getLength()); break; case PortionType::FootnoteNum: break; case PortionType::Footnote:
{
sDisplay = rText;
sal_Int32 nStart=m_aBuffer.getLength();
sal_Int32 nEnd=nStart + rText.getLength();
m_vecPairPos.emplace_back(nStart,nEnd); break;
} break; case PortionType::Number: case PortionType::Bullet:
sDisplay = rText + " "; break; // There should probably be some special treatment to graphical bullets case PortionType::GrfNum: break; // #i111768# - apply patch from kstribley: // Include the control characters. case PortionType::ControlChar:
sDisplay = rText + OUStringChar(m_rTextFrame.GetText()[sal_Int32(m_nViewPosition)]); break; case PortionType::Bookmark: if ( m_pViewOptions->IsShowBookmarks() )
sDisplay = rText + " "; break; default:
sDisplay = rText; break;
}
// ignore zero/zero portions (except for terminators) if ((nLength == TextFrameIndex(0)) && (sDisplay.getLength() == 0) && (nType != POR_TERMINATE)) return;
// special treatment for zero length portion at the beginning: // count as 'before' portion if ((nLength == TextFrameIndex(0)) && (m_nViewPosition == TextFrameIndex(0)))
m_nBeforePortions++;
// store the 'old' positions
m_ViewPositions.push_back( m_nViewPosition );
m_aAccessiblePositions.push_back( m_aBuffer.getLength() );
void SwAccessiblePortionData::Skip(TextFrameIndex const nLength)
{
OSL_ENSURE( !m_bFinished, "We are already done!" );
OSL_ENSURE( m_ViewPositions.empty(), "Never Skip() after portions" );
OSL_ENSURE(nLength <= TextFrameIndex(m_rTextFrame.GetText().getLength()), "skip exceeds model string!" );
m_nViewPosition += nLength;
}
void SwAccessiblePortionData::Finish()
{
OSL_ENSURE( !m_bFinished, "We are already done!" );
// include terminator values: always include two 'last character' // markers in the position arrays to make sure we always find one // position before the end
Special( TextFrameIndex(0), OUString(), POR_TERMINATE );
Special( TextFrameIndex(0), OUString(), POR_TERMINATE );
LineBreak();
LineBreak();
void SwAccessiblePortionData::GetLastLineBoundary(
Boundary& rBound ) const
{
OSL_ENSURE( m_aLineBreaks.size() >= 2, "need min + max value" );
// The last two positions except the two delimiters are the ones // we are looking for, except for empty paragraphs (nBreaks==3)
size_t nBreaks = m_aLineBreaks.size();
FillBoundary( rBound, m_aLineBreaks, nBreaks <= 3 ? 0 : nBreaks-4 );
}
// find the portion number
size_t nPortionNo = FindBreak( m_aAccessiblePositions, nPos );
// get core view portion size
TextFrameIndex nStartPos = m_ViewPositions[nPortionNo];
// if it's a non-special portion, move into the portion, else // return the portion start if( ! IsSpecialPortion( nPortionNo ) )
{ // text portions have to be of the same width
OSL_ENSURE( sal_Int32(m_ViewPositions[nPortionNo+1] - nStartPos) ==
( m_aAccessiblePositions[nPortionNo+1] -
m_aAccessiblePositions[nPortionNo] ), "accessibility portion disagrees with text model" );
// only two are left; we only need to check which one is the winner
OSL_ENSURE( (nMax == nMin) || (nMax == nMin+1), "only two left" ); if( (rPositions[nMin] < nValue) && (rPositions[nMin+1] <= nValue) )
nMin = nMin+1;
// finally, check to see whether the returned value is the 'right' position
OSL_ENSURE( rPositions[nMin] <= nValue, "not smaller or equal" );
OSL_ENSURE( nValue <= rPositions[nMin+1], "not equal or larger" );
OSL_ENSURE( (nMin == 0) || (rPositions[nMin-1] <= nValue), "earlier value should have been returned" );
OSL_ENSURE( nMin < rPositions.size()-1, "shouldn't return last position (due to terminator values)" );
// use xBreak->endOfSentence to iterate over all words; store // positions in pSentences
sal_Int32 nCurrent = 0;
sal_Int32 nLength = m_sAccessibleString.getLength(); do
{
m_aSentences.push_back( nCurrent );
// find the portion number // #i70538# - consider "empty" model portions - e.g. number portion
size_t nPortionNo = FindLastBreak( m_ViewPositions, nPos );
// if the view portion has more than one position, go into it; // else return that position
TextFrameIndex nStartPos = m_ViewPositions[nPortionNo];
TextFrameIndex nEndPos = m_ViewPositions[nPortionNo+1]; if (!IsSpecialPortion(nPortionNo))
{ // text portions have to be of the same width
OSL_ENSURE( sal_Int32(nEndPos - nStartPos) ==
( m_aAccessiblePositions[nPortionNo+1] -
m_aAccessiblePositions[nPortionNo] ), "accessibility portion disagrees with text model" );
// if we have anything except plain text, compute nExtend + nRefPos if (IsSpecialPortion(nCorePortionNo))
{ // case 1: a non-text portion // reference position is the first accessibility for our // core portion
nRefPos = m_aAccessiblePositions[ nCorePortionNo ];
nExtend = SwSPExtendRange::NONE;
rpPos = &rPos;
} elseif(nPortionNo != nCorePortionNo)
{ // case 2: a multi-character (text!) portion, followed by // zero-length portions // reference position is the first character of the next // portion, and we are 'behind'
nRefPos = m_aAccessiblePositions[ nCorePortionNo+1 ];
nExtend = SwSPExtendRange::BEHIND;
rpPos = &rPos;
} else
{ // case 3: regular text portion
OSL_ENSURE( sal_Int32(nCoreEndPos - nCorePos) ==
( m_aAccessiblePositions[nPortionNo+1] -
m_aAccessiblePositions[nPortionNo] ), "text portion expected" );
void SwAccessiblePortionData::AdjustAndCheck(
sal_Int32 nPos,
size_t& nPortionNo,
TextFrameIndex& rCorePos, bool& bEdit) const
{ // find portion and get mode position
nPortionNo = FindBreak( m_aAccessiblePositions, nPos );
rCorePos = m_ViewPositions[ nPortionNo ];
// for special portions, make sure we're on a portion boundary // for text portions, add the in-portion offset if( IsSpecialPortion( nPortionNo ) )
bEdit &= nPos == m_aAccessiblePositions[nPortionNo]; else
rCorePos += TextFrameIndex(nPos - m_aAccessiblePositions[nPortionNo]);
}
// get start and end portions
size_t nStartPortion, nEndPortion;
AdjustAndCheck( nStart, nStartPortion, rCoreStart, bIsEditable );
AdjustAndCheck( nEnd, nEndPortion, rCoreEnd, bIsEditable );
// iterate over portions, and make sure there is no read-only portion // in-between
size_t nLastPortion = nEndPortion;
// don't count last portion if we're in front of a special portion if( IsSpecialPortion(nLastPortion) )
{ if (nLastPortion > 0)
nLastPortion--; else // special case: because size_t is usually unsigned, we can't just // decrease nLastPortion to -1 (which would normally do the job, so // this whole if wouldn't be needed). Instead, we'll do this // special case and just increase the start portion beyond the last // portion to make sure the loop below will have zero iteration.
nStartPortion = nLastPortion + 1;
}
bool SwAccessiblePortionData::IsValidCorePosition(TextFrameIndex const nPos) const
{ // a position is valid if it's within the core view positions that we know return (m_ViewPositions[0] <= nPos) && (nPos <= m_ViewPositions.back());
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.