1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include "accportions.hxx"
23 #include <osl/diagnose.h>
24 #include <rtl/ustring.hxx>
25 #include <com/sun/star/i18n/Boundary.hpp>
26 #include <com/sun/star/i18n/XBreakIterator.hpp>
27 #include <txttypes.hxx>
29 // for portion replacement in Special()
30 #include <viewopt.hxx>
32 // for GetWordBoundary(...), GetSentenceBoundary(...):
33 #include <breakit.hxx>
36 // for FillSpecialPos(...)
37 #include <crstate.hxx>
39 using namespace ::com::sun::star
;
43 // 'portion type' for terminating portions
44 #define POR_TERMINATE PortionType::NONE
47 #define PORATTR_SPECIAL 1
48 #define PORATTR_READONLY 2
49 #define PORATTR_GRAY 4
50 #define PORATTR_TERM 128
52 /// returns the index of the first position whose value is smaller
53 /// or equal, and whose following value is equal or larger
55 static size_t FindBreak(const std::vector
<T
>& rPositions
, T nValue
);
57 /// like FindBreak, but finds the last equal or larger position
59 static size_t FindLastBreak(const std::vector
<T
>& rPositions
, T nValue
);
62 SwAccessiblePortionData::SwAccessiblePortionData(
63 const SwTextFrame
*const pTextFrame
,
64 const SwViewOption
* pViewOpt
) :
65 m_pTextFrame(pTextFrame
),
67 m_pViewOptions( pViewOpt
),
68 m_nBeforePortions( 0 ),
71 OSL_ENSURE( m_pTextFrame
!= nullptr, "Need SwTextFrame!" );
73 // reserve some space to reduce memory allocations
74 m_aLineBreaks
.reserve( 5 );
75 m_ViewPositions
.reserve( 10 );
76 m_aAccessiblePositions
.reserve( 10 );
78 // always include 'first' line-break position
79 m_aLineBreaks
.push_back( 0 );
82 SwAccessiblePortionData::~SwAccessiblePortionData()
86 void SwAccessiblePortionData::Text(TextFrameIndex
const nLength
,
89 OSL_ENSURE((m_nViewPosition
+ nLength
) <= TextFrameIndex(m_pTextFrame
->GetText().getLength()),
90 "portion exceeds model string!" );
92 OSL_ENSURE( !m_bFinished
, "We are already done!" );
94 // ignore zero-length portions
95 if (nLength
== TextFrameIndex(0))
98 // store 'old' positions
99 m_ViewPositions
.push_back( m_nViewPosition
);
100 m_aAccessiblePositions
.push_back( m_aBuffer
.getLength() );
102 // store portion attributes
103 sal_uInt8 nAttr
= IsGrayPortionType(nType
) ? PORATTR_GRAY
: 0;
104 m_aPortionAttrs
.push_back( nAttr
);
106 // update buffer + nViewPosition
107 m_aBuffer
.append(m_pTextFrame
->GetText().subView(sal_Int32(m_nViewPosition
), sal_Int32(nLength
)));
108 m_nViewPosition
+= nLength
;
111 void SwAccessiblePortionData::Special(
112 TextFrameIndex
const nLength
, const OUString
& rText
, PortionType nType
)
114 OSL_ENSURE(m_nViewPosition
>= TextFrameIndex(0), "illegal position");
115 OSL_ENSURE((m_nViewPosition
+ nLength
) <= TextFrameIndex(m_pTextFrame
->GetText().getLength()),
116 "portion exceeds model string!" );
118 OSL_ENSURE( !m_bFinished
, "We are already done!" );
120 // construct string with representation; either directly from
121 // rText, or use resources for special case portions
125 case PortionType::PostIts
:
126 case PortionType::FlyCnt
:
127 sDisplay
= OUString(u
'\xfffc');
129 case PortionType::Field
:
130 case PortionType::Hidden
:
131 case PortionType::Combined
:
132 case PortionType::IsoRef
:
133 // When the field content is empty, input a special character.
135 sDisplay
= OUString(u
'\xfffc');
138 m_aFieldPosition
.push_back(m_aBuffer
.getLength());
139 m_aFieldPosition
.push_back(m_aBuffer
.getLength() + rText
.getLength());
141 case PortionType::FootnoteNum
:
143 case PortionType::Footnote
:
146 sal_Int32 nStart
=m_aBuffer
.getLength();
147 sal_Int32 nEnd
=nStart
+ rText
.getLength();
148 m_vecPairPos
.emplace_back(nStart
,nEnd
);
152 case PortionType::Number
:
153 case PortionType::Bullet
:
154 sDisplay
= rText
+ " ";
156 // There should probably be some special treatment to graphical bullets
157 case PortionType::GrfNum
:
159 // #i111768# - apply patch from kstribley:
160 // Include the control characters.
161 case PortionType::ControlChar
:
162 sDisplay
= rText
+ OUStringChar(m_pTextFrame
->GetText()[sal_Int32(m_nViewPosition
)]);
164 case PortionType::Bookmark
:
165 if ( m_pViewOptions
->IsShowBookmarks() )
166 sDisplay
= rText
+ " ";
173 // ignore zero/zero portions (except for terminators)
174 if ((nLength
== TextFrameIndex(0)) && (sDisplay
.getLength() == 0) && (nType
!= POR_TERMINATE
))
177 // special treatment for zero length portion at the beginning:
178 // count as 'before' portion
179 if ((nLength
== TextFrameIndex(0)) && (m_nViewPosition
== TextFrameIndex(0)))
182 // store the 'old' positions
183 m_ViewPositions
.push_back( m_nViewPosition
);
184 m_aAccessiblePositions
.push_back( m_aBuffer
.getLength() );
186 // store portion attributes
187 sal_uInt8 nAttr
= PORATTR_SPECIAL
;
188 if( IsGrayPortionType(nType
) ) nAttr
|= PORATTR_GRAY
;
189 if (nLength
== TextFrameIndex(0)) nAttr
|= PORATTR_READONLY
;
190 if( nType
== POR_TERMINATE
) nAttr
|= PORATTR_TERM
;
191 m_aPortionAttrs
.push_back( nAttr
);
193 // update buffer + nViewPosition
194 m_aBuffer
.append( sDisplay
);
195 m_nViewPosition
+= nLength
;
198 void SwAccessiblePortionData::LineBreak()
200 OSL_ENSURE( !m_bFinished
, "We are already done!" );
202 m_aLineBreaks
.push_back( m_aBuffer
.getLength() );
205 void SwAccessiblePortionData::Skip(TextFrameIndex
const nLength
)
207 OSL_ENSURE( !m_bFinished
, "We are already done!" );
208 OSL_ENSURE( m_ViewPositions
.empty(), "Never Skip() after portions" );
209 OSL_ENSURE(nLength
<= TextFrameIndex(m_pTextFrame
->GetText().getLength()),
210 "skip exceeds model string!" );
212 m_nViewPosition
+= nLength
;
215 void SwAccessiblePortionData::Finish()
217 OSL_ENSURE( !m_bFinished
, "We are already done!" );
219 // include terminator values: always include two 'last character'
220 // markers in the position arrays to make sure we always find one
221 // position before the end
222 Special( TextFrameIndex(0), OUString(), POR_TERMINATE
);
223 Special( TextFrameIndex(0), OUString(), POR_TERMINATE
);
227 m_sAccessibleString
= m_aBuffer
.makeStringAndClear();
231 bool SwAccessiblePortionData::IsPortionAttrSet(
232 size_t nPortionNo
, sal_uInt8 nAttr
) const
234 OSL_ENSURE( nPortionNo
< m_aPortionAttrs
.size(),
235 "Illegal portion number" );
236 return (m_aPortionAttrs
[nPortionNo
] & nAttr
) != 0;
239 bool SwAccessiblePortionData::IsSpecialPortion( size_t nPortionNo
) const
241 return IsPortionAttrSet(nPortionNo
, PORATTR_SPECIAL
);
244 bool SwAccessiblePortionData::IsGrayPortionType( PortionType nType
) const
247 // Compare with: inftxt.cxx, SwTextPaintInfo::DrawViewOpt(...)
251 case PortionType::Footnote
:
252 case PortionType::IsoRef
:
253 case PortionType::Ref
:
254 case PortionType::QuoVadis
:
255 case PortionType::Number
:
256 case PortionType::Field
:
257 case PortionType::InputField
:
258 case PortionType::IsoTox
:
259 case PortionType::Tox
:
260 case PortionType::Hidden
:
261 bGray
= !m_pViewOptions
->IsPagePreview() &&
262 !m_pViewOptions
->IsReadonly() && m_pViewOptions
->IsFieldShadings();
264 case PortionType::Tab
: bGray
= m_pViewOptions
->IsTab(); break;
265 case PortionType::SoftHyphen
: bGray
= m_pViewOptions
->IsSoftHyph(); break;
266 case PortionType::Blank
: bGray
= m_pViewOptions
->IsHardBlank(); break;
268 break; // bGray is false
273 const OUString
& SwAccessiblePortionData::GetAccessibleString() const
275 OSL_ENSURE( m_bFinished
, "Shouldn't call this before we are done!" );
277 return m_sAccessibleString
;
280 void SwAccessiblePortionData::GetLineBoundary(
282 sal_Int32 nPos
) const
284 FillBoundary( rBound
, m_aLineBreaks
,
285 FindBreak( m_aLineBreaks
, nPos
) );
289 sal_Int32
SwAccessiblePortionData::GetLineCount() const
291 size_t nBreaks
= m_aLineBreaks
.size();
292 // A non-empty paragraph has at least 4 breaks: one for each line3 and
293 // 3 additional ones.
294 // An empty paragraph has 3 breaks.
295 // Less than 3 breaks is an error case.
296 sal_Int32 nLineCount
= ( nBreaks
> 3 )
298 : ( ( nBreaks
== 3 ) ? 1 : 0 );
302 sal_Int32
SwAccessiblePortionData::GetLineNo( const sal_Int32 nPos
) const
304 sal_Int32 nLineNo
= FindBreak( m_aLineBreaks
, nPos
);
306 // handling of position after last character
307 const sal_Int32
nLineCount( GetLineCount() );
308 if ( nLineNo
>= nLineCount
)
310 nLineNo
= nLineCount
- 1;
316 void SwAccessiblePortionData::GetBoundaryOfLine( const sal_Int32 nLineNo
,
317 i18n::Boundary
& rLineBound
)
319 FillBoundary( rLineBound
, m_aLineBreaks
, nLineNo
);
322 void SwAccessiblePortionData::GetLastLineBoundary(
323 Boundary
& rBound
) const
325 OSL_ENSURE( m_aLineBreaks
.size() >= 2, "need min + max value" );
327 // The last two positions except the two delimiters are the ones
328 // we are looking for, except for empty paragraphs (nBreaks==3)
329 size_t nBreaks
= m_aLineBreaks
.size();
330 FillBoundary( rBound
, m_aLineBreaks
, nBreaks
<= 3 ? 0 : nBreaks
-4 );
333 TextFrameIndex
SwAccessiblePortionData::GetCoreViewPosition(sal_Int32
const nPos
) const
335 OSL_ENSURE( nPos
>= 0, "illegal position" );
336 OSL_ENSURE( nPos
<= m_sAccessibleString
.getLength(), "illegal position" );
338 // find the portion number
339 size_t nPortionNo
= FindBreak( m_aAccessiblePositions
, nPos
);
341 // get core view portion size
342 TextFrameIndex nStartPos
= m_ViewPositions
[nPortionNo
];
344 // if it's a non-special portion, move into the portion, else
345 // return the portion start
346 if( ! IsSpecialPortion( nPortionNo
) )
348 // text portions have to be of the same width
349 OSL_ENSURE( sal_Int32(m_ViewPositions
[nPortionNo
+1] - nStartPos
) ==
350 ( m_aAccessiblePositions
[nPortionNo
+1] -
351 m_aAccessiblePositions
[nPortionNo
] ),
352 "accessibility portion disagrees with text model" );
354 nStartPos
+= TextFrameIndex(nPos
- m_aAccessiblePositions
[nPortionNo
]);
356 // else: return nStartPos unmodified
358 OSL_ENSURE(nStartPos
>= TextFrameIndex(0), "There's something weird in number of characters of SwTextFrame");
362 void SwAccessiblePortionData::FillBoundary(
364 const AccessiblePositions
& rPositions
,
367 rBound
.startPos
= rPositions
[nPos
];
368 rBound
.endPos
= rPositions
[nPos
+1];
372 static size_t FindBreak(const std::vector
<T
>& rPositions
, T
const nValue
)
374 OSL_ENSURE( rPositions
.size() >= 2, "need min + max value" );
375 OSL_ENSURE( rPositions
[0] <= nValue
, "need min value" );
376 OSL_ENSURE( rPositions
[rPositions
.size()-1] >= nValue
,
377 "need first terminator value" );
378 OSL_ENSURE( rPositions
[rPositions
.size()-2] >= nValue
,
379 "need second terminator value" );
382 size_t nMax
= rPositions
.size()-2;
384 // loop until no more than two candidates are left
385 while( nMin
+1 < nMax
)
387 // check loop invariants
388 OSL_ENSURE( ( (nMin
== 0) && (rPositions
[nMin
] <= nValue
) ) ||
389 ( (nMin
!= 0) && (rPositions
[nMin
] < nValue
) ),
390 "minvalue not minimal" );
391 OSL_ENSURE( nValue
<= rPositions
[nMax
], "max value not maximal" );
393 // get middle (and ensure progress)
394 size_t nMiddle
= (nMin
+ nMax
)/2;
395 OSL_ENSURE( nMin
< nMiddle
, "progress?" );
396 OSL_ENSURE( nMiddle
< nMax
, "progress?" );
399 OSL_ENSURE( rPositions
[nMin
] <= rPositions
[nMiddle
],
400 "garbled positions array" );
401 OSL_ENSURE( rPositions
[nMiddle
] <= rPositions
[nMax
],
402 "garbled positions array" );
404 if( nValue
> rPositions
[nMiddle
] )
410 // only two are left; we only need to check which one is the winner
411 OSL_ENSURE( (nMax
== nMin
) || (nMax
== nMin
+1), "only two left" );
412 if( (rPositions
[nMin
] < nValue
) && (rPositions
[nMin
+1] <= nValue
) )
415 // finally, check to see whether the returned value is the 'right' position
416 OSL_ENSURE( rPositions
[nMin
] <= nValue
, "not smaller or equal" );
417 OSL_ENSURE( nValue
<= rPositions
[nMin
+1], "not equal or larger" );
418 OSL_ENSURE( (nMin
== 0) || (rPositions
[nMin
-1] <= nValue
),
419 "earlier value should have been returned" );
421 OSL_ENSURE( nMin
< rPositions
.size()-1,
422 "shouldn't return last position (due to terminator values)" );
428 static size_t FindLastBreak(const std::vector
<T
>& rPositions
, T
const nValue
)
430 size_t nResult
= FindBreak( rPositions
, nValue
);
432 // skip 'zero-length' portions
433 // #i70538# consider size of <rPosition> and ignore last entry
434 while ( nResult
< rPositions
.size() - 2 &&
435 rPositions
[nResult
+1] <= nValue
)
443 void SwAccessiblePortionData::GetSentenceBoundary(
447 OSL_ENSURE( nPos
>= 0, "illegal position; check before" );
448 OSL_ENSURE( nPos
< m_sAccessibleString
.getLength(), "illegal position" );
450 if( m_pSentences
== nullptr )
452 assert(g_pBreakIt
&& g_pBreakIt
->GetBreakIter().is());
454 m_pSentences
.reset(new AccessiblePositions
);
455 m_pSentences
->reserve(10);
457 // use xBreak->endOfSentence to iterate over all words; store
458 // positions in pSentences
459 sal_Int32 nCurrent
= 0;
460 sal_Int32 nLength
= m_sAccessibleString
.getLength();
463 m_pSentences
->push_back( nCurrent
);
465 const TextFrameIndex nFramePos
= GetCoreViewPosition(nCurrent
);
467 sal_Int32 nNew
= g_pBreakIt
->GetBreakIter()->endOfSentence(
468 m_sAccessibleString
, nCurrent
,
469 g_pBreakIt
->GetLocale(m_pTextFrame
->GetLangOfChar(nFramePos
, 0, true))) + 1;
471 if( (nNew
< 0) && (nNew
> nLength
) )
473 else if (nNew
<= nCurrent
)
474 nNew
= nCurrent
+ 1; // ensure forward progress
478 while (nCurrent
< nLength
);
480 // finish with two terminators
481 m_pSentences
->push_back( nLength
);
482 m_pSentences
->push_back( nLength
);
485 FillBoundary( rBound
, *m_pSentences
, FindBreak( *m_pSentences
, nPos
) );
488 void SwAccessiblePortionData::GetAttributeBoundary(
490 sal_Int32 nPos
) const
492 OSL_ENSURE( m_pTextFrame
!= nullptr, "Need SwTextNode!" );
494 // attribute boundaries can only occur on portion boundaries
495 FillBoundary( rBound
, m_aAccessiblePositions
,
496 FindBreak( m_aAccessiblePositions
, nPos
) );
499 sal_Int32
SwAccessiblePortionData::GetAccessiblePosition(TextFrameIndex
const nPos
) const
501 OSL_ENSURE(nPos
<= TextFrameIndex(m_pTextFrame
->GetText().getLength()), "illegal position");
503 // find the portion number
504 // #i70538# - consider "empty" model portions - e.g. number portion
505 size_t nPortionNo
= FindLastBreak( m_ViewPositions
, nPos
);
507 sal_Int32 nRet
= m_aAccessiblePositions
[nPortionNo
];
509 // if the view portion has more than one position, go into it;
510 // else return that position
511 TextFrameIndex nStartPos
= m_ViewPositions
[nPortionNo
];
512 TextFrameIndex nEndPos
= m_ViewPositions
[nPortionNo
+1];
513 if (!IsSpecialPortion(nPortionNo
))
515 // text portions have to be of the same width
516 OSL_ENSURE( sal_Int32(nEndPos
- nStartPos
) ==
517 ( m_aAccessiblePositions
[nPortionNo
+1] -
518 m_aAccessiblePositions
[nPortionNo
] ),
519 "accessibility portion disagrees with text model" );
521 TextFrameIndex nWithinPortion
= nPos
- m_ViewPositions
[nPortionNo
];
522 nRet
+= sal_Int32(nWithinPortion
);
524 // else: return nRet unmodified
526 OSL_ENSURE( (nRet
>= 0) && (nRet
<= m_sAccessibleString
.getLength()),
531 TextFrameIndex
SwAccessiblePortionData::FillSpecialPos(
534 SwSpecialPos
*& rpPos
) const
536 size_t nPortionNo
= FindLastBreak( m_aAccessiblePositions
, nPos
);
538 SwSPExtendRange
nExtend(SwSPExtendRange::NONE
);
539 sal_Int32
nRefPos(0);
540 TextFrameIndex
nCorePos(0);
542 if( nPortionNo
< m_nBeforePortions
)
544 nExtend
= SwSPExtendRange::BEFORE
;
549 TextFrameIndex nCoreEndPos
= m_ViewPositions
[nPortionNo
+1];
550 nCorePos
= m_ViewPositions
[nPortionNo
];
552 // skip backwards over zero-length portions, since GetCharRect()
553 // counts all model-zero-length portions as belonging to the
555 size_t nCorePortionNo
= nPortionNo
;
556 while (nCorePos
== nCoreEndPos
)
559 nCoreEndPos
= nCorePos
;
560 nCorePos
= m_ViewPositions
[nCorePortionNo
];
562 OSL_ENSURE( nCorePos
>= TextFrameIndex(0), "Can't happen." );
563 OSL_ENSURE( nCorePortionNo
>= m_nBeforePortions
, "Can't happen." );
565 OSL_ENSURE( nCorePos
!= nCoreEndPos
,
566 "portion with core-representation expected" );
568 // if we have anything except plain text, compute nExtend + nRefPos
569 if (IsSpecialPortion(nCorePortionNo
))
571 // case 1: a non-text portion
572 // reference position is the first accessibility for our
574 nRefPos
= m_aAccessiblePositions
[ nCorePortionNo
];
575 nExtend
= SwSPExtendRange::NONE
;
578 else if(nPortionNo
!= nCorePortionNo
)
580 // case 2: a multi-character (text!) portion, followed by
581 // zero-length portions
582 // reference position is the first character of the next
583 // portion, and we are 'behind'
584 nRefPos
= m_aAccessiblePositions
[ nCorePortionNo
+1 ];
585 nExtend
= SwSPExtendRange::BEHIND
;
590 // case 3: regular text portion
591 OSL_ENSURE( sal_Int32(nCoreEndPos
- nCorePos
) ==
592 ( m_aAccessiblePositions
[nPortionNo
+1] -
593 m_aAccessiblePositions
[nPortionNo
] ),
594 "text portion expected" );
596 nCorePos
+= TextFrameIndex(nPos
- m_aAccessiblePositions
[nPortionNo
]);
600 if( rpPos
!= nullptr )
602 OSL_ENSURE( rpPos
== &rPos
, "Yes!" );
603 OSL_ENSURE( nRefPos
<= nPos
, "wrong reference" );
605 // get the line number, and adjust nRefPos for the line
607 size_t nRefLine
= FindBreak( m_aLineBreaks
, nRefPos
);
608 size_t nMyLine
= FindBreak( m_aLineBreaks
, nPos
);
609 sal_Int32 nLineOffset
= o3tl::narrowing
<sal_Int32
>( nMyLine
- nRefLine
);
610 if( nLineOffset
!= 0 )
611 nRefPos
= m_aLineBreaks
[ nMyLine
];
613 // fill char offset and 'special position'
614 rPos
.nCharOfst
= nPos
- nRefPos
;
615 rPos
.nExtendRange
= nExtend
;
616 rPos
.nLineOfst
= nLineOffset
;
622 bool SwAccessiblePortionData::FillBoundaryIFDateField( css::i18n::Boundary
& rBound
, const sal_Int32 nPos
)
624 if( m_aFieldPosition
.size() < 2 )
626 for( size_t i
= 0; i
< m_aFieldPosition
.size() - 1; i
+= 2 )
628 if( nPos
< m_aFieldPosition
[ i
+ 1 ] && nPos
>= m_aFieldPosition
[ i
] )
630 rBound
.startPos
= m_aFieldPosition
[i
];
631 rBound
.endPos
= m_aFieldPosition
[i
+ 1];
638 void SwAccessiblePortionData::AdjustAndCheck(
641 TextFrameIndex
& rCorePos
,
644 // find portion and get mode position
645 nPortionNo
= FindBreak( m_aAccessiblePositions
, nPos
);
646 rCorePos
= m_ViewPositions
[ nPortionNo
];
648 // for special portions, make sure we're on a portion boundary
649 // for text portions, add the in-portion offset
650 if( IsSpecialPortion( nPortionNo
) )
651 bEdit
&= nPos
== m_aAccessiblePositions
[nPortionNo
];
653 rCorePos
+= TextFrameIndex(nPos
- m_aAccessiblePositions
[nPortionNo
]);
656 bool SwAccessiblePortionData::GetEditableRange(
657 sal_Int32 nStart
, sal_Int32 nEnd
,
658 TextFrameIndex
& rCoreStart
, TextFrameIndex
& rCoreEnd
) const
660 bool bIsEditable
= true;
662 // get start and end portions
663 size_t nStartPortion
, nEndPortion
;
664 AdjustAndCheck( nStart
, nStartPortion
, rCoreStart
, bIsEditable
);
665 AdjustAndCheck( nEnd
, nEndPortion
, rCoreEnd
, bIsEditable
);
667 // iterate over portions, and make sure there is no read-only portion
669 size_t nLastPortion
= nEndPortion
;
671 // don't count last portion if we're in front of a special portion
672 if( IsSpecialPortion(nLastPortion
) )
674 if (nLastPortion
> 0)
677 // special case: because size_t is usually unsigned, we can't just
678 // decrease nLastPortion to -1 (which would normally do the job, so
679 // this whole if wouldn't be needed). Instead, we'll do this
680 // special case and just increase the start portion beyond the last
681 // portion to make sure the loop below will have zero iteration.
682 nStartPortion
= nLastPortion
+ 1;
685 for( size_t nPor
= nStartPortion
; nPor
<= nLastPortion
; nPor
++ )
687 bIsEditable
&= ! IsPortionAttrSet(nPor
, PORATTR_READONLY
);
693 bool SwAccessiblePortionData::IsValidCorePosition(TextFrameIndex
const nPos
) const
695 // a position is valid if it's within the core view positions that we know
696 return (m_ViewPositions
[0] <= nPos
) && (nPos
<= m_ViewPositions
.back());
699 bool SwAccessiblePortionData::IsZeroCorePositionData()
701 if (m_ViewPositions
.empty()) return true;
702 return m_ViewPositions
[0] == TextFrameIndex(0)
703 && m_ViewPositions
.back() == TextFrameIndex(0);
706 bool SwAccessiblePortionData::IsIndexInFootnode(sal_Int32 nIndex
)
708 for (const auto & pairPos
: m_vecPairPos
)
710 if(nIndex
>= pairPos
.first
&& nIndex
< pairPos
.second
)
718 bool SwAccessiblePortionData::IsInGrayPortion( sal_Int32 nPos
)
720 // return IsGrayPortion( FindBreak( aAccessiblePositions, nPos ) );
721 return IsPortionAttrSet( FindBreak( m_aAccessiblePositions
, nPos
),
725 sal_Int32
SwAccessiblePortionData::GetFieldIndex(sal_Int32 nPos
) const
727 sal_Int32 nIndex
= -1;
728 if( m_aFieldPosition
.size() >= 2 )
730 for( size_t i
= 0; i
< m_aFieldPosition
.size() - 1; i
+= 2 )
732 if( nPos
<= m_aFieldPosition
[ i
+ 1 ] && nPos
>= m_aFieldPosition
[ i
] )
742 TextFrameIndex
SwAccessiblePortionData::GetFirstValidCorePosition() const
744 return m_ViewPositions
[0];
747 TextFrameIndex
SwAccessiblePortionData::GetLastValidCorePosition() const
749 return m_ViewPositions
.back();
752 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */