xref: /trunk/main/sw/source/core/access/accportions.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
1efeef26fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3efeef26fSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4efeef26fSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5efeef26fSAndrew Rist  * distributed with this work for additional information
6efeef26fSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7efeef26fSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8efeef26fSAndrew Rist  * "License"); you may not use this file except in compliance
9efeef26fSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11efeef26fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13efeef26fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14efeef26fSAndrew Rist  * software distributed under the License is distributed on an
15efeef26fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16efeef26fSAndrew Rist  * KIND, either express or implied.  See the License for the
17efeef26fSAndrew Rist  * specific language governing permissions and limitations
18efeef26fSAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20efeef26fSAndrew Rist  *************************************************************/
21efeef26fSAndrew Rist 
22efeef26fSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sw.hxx"
26cdf0e10cSrcweir #include "accportions.hxx"
27cdf0e10cSrcweir #include <tools/debug.hxx>
28cdf0e10cSrcweir #include <rtl/ustring.hxx>
29cdf0e10cSrcweir #include <com/sun/star/i18n/Boundary.hpp>
30cdf0e10cSrcweir #include <txttypes.hxx>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir // for portion replacement in Special()
33cdf0e10cSrcweir #ifndef _ACCESS_HRC
34cdf0e10cSrcweir #include "access.hrc"
35cdf0e10cSrcweir #endif
36cdf0e10cSrcweir #include <tools/resid.hxx>
37cdf0e10cSrcweir #include "viewopt.hxx"
38cdf0e10cSrcweir 
39cdf0e10cSrcweir // for GetWordBoundary(...), GetSentenceBoundary(...):
40cdf0e10cSrcweir #include <breakit.hxx>
41cdf0e10cSrcweir #include <com/sun/star/i18n/WordType.hpp>
42cdf0e10cSrcweir #include <com/sun/star/i18n/XBreakIterator.hpp>
43cdf0e10cSrcweir #include <ndtxt.hxx>
44cdf0e10cSrcweir 
45cdf0e10cSrcweir // for FillSpecialPos(...)
46cdf0e10cSrcweir #include "crstate.hxx"
47cdf0e10cSrcweir 
48cdf0e10cSrcweir // for SwAccessibleContext::GetResource()
49cdf0e10cSrcweir #include "acccontext.hxx"
50cdf0e10cSrcweir 
51cdf0e10cSrcweir // for Post-It replacement text:
52cdf0e10cSrcweir #include "txatbase.hxx"
53cdf0e10cSrcweir #include "fmtfld.hxx"
54cdf0e10cSrcweir #include "fldbas.hxx"
55cdf0e10cSrcweir #include "docufld.hxx"
56cdf0e10cSrcweir 
57cdf0e10cSrcweir // for in-line graphics replacement:
58cdf0e10cSrcweir #include "ndindex.hxx"
59cdf0e10cSrcweir #include "ndnotxt.hxx"
60cdf0e10cSrcweir #include "fmtflcnt.hxx"
61cdf0e10cSrcweir #include "frmfmt.hxx"
62cdf0e10cSrcweir #include "fmtcntnt.hxx"
63cdf0e10cSrcweir 
64cdf0e10cSrcweir 
65cdf0e10cSrcweir using namespace ::com::sun::star;
66cdf0e10cSrcweir 
67ca62e2c2SSteve Yin //#include "accnote.hxx"
68ca62e2c2SSteve Yin 
69cdf0e10cSrcweir using rtl::OUString;
70cdf0e10cSrcweir using rtl::OUStringBuffer;
71cdf0e10cSrcweir using i18n::Boundary;
72cdf0e10cSrcweir 
73cdf0e10cSrcweir 
74cdf0e10cSrcweir // 'portion type' for terminating portions
75cdf0e10cSrcweir #define POR_TERMINATE 0
76cdf0e10cSrcweir 
77cdf0e10cSrcweir 
78cdf0e10cSrcweir // portion attributes
79cdf0e10cSrcweir #define PORATTR_SPECIAL     1
80cdf0e10cSrcweir #define PORATTR_READONLY    2
81cdf0e10cSrcweir #define PORATTR_GRAY        4
82cdf0e10cSrcweir #define PORATTR_TERM        128
83cdf0e10cSrcweir 
SwAccessiblePortionData(const SwTxtNode * pTxtNd,const SwViewOption * pViewOpt)84cdf0e10cSrcweir SwAccessiblePortionData::SwAccessiblePortionData(
85cdf0e10cSrcweir     const SwTxtNode* pTxtNd,
86cdf0e10cSrcweir     const SwViewOption* pViewOpt ) :
87cdf0e10cSrcweir     SwPortionHandler(),
88cdf0e10cSrcweir     pTxtNode( pTxtNd ),
89cdf0e10cSrcweir     aBuffer(),
90cdf0e10cSrcweir     nModelPosition( 0 ),
91cdf0e10cSrcweir     bFinished( sal_False ),
92cdf0e10cSrcweir     pViewOptions( pViewOpt ),
93cdf0e10cSrcweir     sAccessibleString(),
94cdf0e10cSrcweir     aLineBreaks(),
95cdf0e10cSrcweir     aModelPositions(),
96cdf0e10cSrcweir     aAccessiblePositions(),
97cdf0e10cSrcweir     pSentences( 0 ),
98cdf0e10cSrcweir     nBeforePortions( 0 ),
99cdf0e10cSrcweir     bLastIsSpecial( sal_False )
100cdf0e10cSrcweir {
101cdf0e10cSrcweir     DBG_ASSERT( pTxtNode != NULL, "Text node is needed!" );
102cdf0e10cSrcweir 
103cdf0e10cSrcweir     // reserve some space to reduce memory allocations
104cdf0e10cSrcweir     aLineBreaks.reserve( 5 );
105cdf0e10cSrcweir     aModelPositions.reserve( 10 );
106cdf0e10cSrcweir     aAccessiblePositions.reserve( 10 );
107cdf0e10cSrcweir 
108cdf0e10cSrcweir     // always include 'first' line-break position
109cdf0e10cSrcweir     aLineBreaks.push_back( 0 );
110cdf0e10cSrcweir }
111cdf0e10cSrcweir 
~SwAccessiblePortionData()112cdf0e10cSrcweir SwAccessiblePortionData::~SwAccessiblePortionData()
113cdf0e10cSrcweir {
114cdf0e10cSrcweir     delete pSentences;
115cdf0e10cSrcweir }
116cdf0e10cSrcweir 
Text(sal_uInt16 nLength,sal_uInt16 nType)117cdf0e10cSrcweir void SwAccessiblePortionData::Text(sal_uInt16 nLength, sal_uInt16 nType)
118cdf0e10cSrcweir {
119cdf0e10cSrcweir     DBG_ASSERT( (nModelPosition + nLength) <= pTxtNode->GetTxt().Len(),
120cdf0e10cSrcweir                 "portion exceeds model string!" );
121cdf0e10cSrcweir 
122cdf0e10cSrcweir     DBG_ASSERT( !bFinished, "We are already done!" );
123cdf0e10cSrcweir 
124cdf0e10cSrcweir     // ignore zero-length portions
125cdf0e10cSrcweir     if( nLength == 0 )
126cdf0e10cSrcweir         return;
127cdf0e10cSrcweir 
128cdf0e10cSrcweir     // store 'old' positions
129cdf0e10cSrcweir     aModelPositions.push_back( nModelPosition );
130cdf0e10cSrcweir     aAccessiblePositions.push_back( aBuffer.getLength() );
131cdf0e10cSrcweir 
132cdf0e10cSrcweir     // store portion attributes
133cdf0e10cSrcweir     sal_uInt8 nAttr = IsGrayPortionType(nType) ? PORATTR_GRAY : 0;
134cdf0e10cSrcweir     aPortionAttrs.push_back( nAttr );
135cdf0e10cSrcweir 
136cdf0e10cSrcweir     // update buffer + nModelPosition
137cdf0e10cSrcweir     aBuffer.append( OUString(
138cdf0e10cSrcweir         pTxtNode->GetTxt().Copy(
139cdf0e10cSrcweir             static_cast<sal_uInt16>( nModelPosition ),
140cdf0e10cSrcweir             nLength ) ) );
141cdf0e10cSrcweir     nModelPosition += nLength;
142cdf0e10cSrcweir 
143cdf0e10cSrcweir     bLastIsSpecial = sal_False;
144cdf0e10cSrcweir }
SetAttrFieldType(sal_uInt16 nAttrFldType)145ca62e2c2SSteve Yin void SwAccessiblePortionData::SetAttrFieldType( sal_uInt16 nAttrFldType )
146ca62e2c2SSteve Yin {
147ca62e2c2SSteve Yin     aAttrFieldType.push_back(nAttrFldType);
148ca62e2c2SSteve Yin     return;
149ca62e2c2SSteve Yin }
150cdf0e10cSrcweir 
Special(sal_uInt16 nLength,const String & rText,sal_uInt16 nType)151cdf0e10cSrcweir void SwAccessiblePortionData::Special(
152cdf0e10cSrcweir     sal_uInt16 nLength, const String& rText, sal_uInt16 nType)
153cdf0e10cSrcweir {
154cdf0e10cSrcweir     DBG_ASSERT( nModelPosition >= 0, "illegal position" );
155cdf0e10cSrcweir     DBG_ASSERT( (nModelPosition + nLength) <= pTxtNode->GetTxt().Len(),
156cdf0e10cSrcweir                 "portion exceeds model string!" );
157cdf0e10cSrcweir 
158cdf0e10cSrcweir     DBG_ASSERT( !bFinished, "We are already done!" );
159cdf0e10cSrcweir 
160cdf0e10cSrcweir     // construct string with representation; either directly from
161cdf0e10cSrcweir     // rText, or use resources for special case portions
162cdf0e10cSrcweir     String sDisplay;
163cdf0e10cSrcweir     switch( nType )
164cdf0e10cSrcweir     {
165cdf0e10cSrcweir         case POR_POSTITS:
166cdf0e10cSrcweir             sDisplay = String(sal_Unicode(0xfffc));
167cdf0e10cSrcweir 
168cdf0e10cSrcweir             break;
169ca62e2c2SSteve Yin         case POR_FLYCNT:
170ca62e2c2SSteve Yin             sDisplay = String(sal_Unicode(0xfffc));
171ca62e2c2SSteve Yin             break;
172ca62e2c2SSteve Yin         case POR_GRFNUM:
173ca62e2c2SSteve Yin                 break;
174ca62e2c2SSteve Yin         case POR_FLD:
175ca62e2c2SSteve Yin         //Added by yanjun for 6854
176ca62e2c2SSteve Yin         case POR_HIDDEN:
177ca62e2c2SSteve Yin         case POR_COMBINED:
178ca62e2c2SSteve Yin         case POR_ISOREF:
179ca62e2c2SSteve Yin         //End
180ca62e2c2SSteve Yin             {
181ca62e2c2SSteve Yin                 //When the filed content is empty, input a special character.
182ca62e2c2SSteve Yin                 if (rText.Len() == 0)
183ca62e2c2SSteve Yin                     sDisplay = String(sal_Unicode(0xfffc));
184ca62e2c2SSteve Yin                 else
185ca62e2c2SSteve Yin                     sDisplay = rText;
186ca62e2c2SSteve Yin                 aFieldPosition.push_back(aBuffer.getLength());
187ca62e2c2SSteve Yin                 aFieldPosition.push_back(aBuffer.getLength() + rText.Len());
188ca62e2c2SSteve Yin                 break;
189ca62e2c2SSteve Yin             }
190ca62e2c2SSteve Yin         case POR_FTNNUM:
191ca62e2c2SSteve Yin             {
192ca62e2c2SSteve Yin                 break;
193ca62e2c2SSteve Yin             }
194ca62e2c2SSteve Yin         case POR_FTN:
195ca62e2c2SSteve Yin             {
196ca62e2c2SSteve Yin                 sDisplay = rText;
197ca62e2c2SSteve Yin                 sal_Int32 nStart=aBuffer.getLength();
198ca62e2c2SSteve Yin                 sal_Int32 nEnd=nStart + rText.Len();
199ca62e2c2SSteve Yin                 m_vecPairPos.push_back(std::make_pair(nStart,nEnd));
200ca62e2c2SSteve Yin                 break;
201ca62e2c2SSteve Yin             }
202ca62e2c2SSteve Yin             break;
203cdf0e10cSrcweir         case POR_NUMBER:
204739ed914SDamjan Jovanovic         case POR_BULLET:
205cdf0e10cSrcweir         {
206cdf0e10cSrcweir             OUStringBuffer aTmpBuffer( rText.Len() + 1 );
207cdf0e10cSrcweir             aTmpBuffer.append( rText );
208cdf0e10cSrcweir             aTmpBuffer.append( sal_Unicode(' ') );
209cdf0e10cSrcweir             sDisplay = aTmpBuffer.makeStringAndClear();
210cdf0e10cSrcweir             break;
211cdf0e10cSrcweir         }
212cdf0e10cSrcweir         // --> OD 2010-06-04 #i111768# - apply patch from kstribley:
213cdf0e10cSrcweir         // Include the control characters.
214cdf0e10cSrcweir         case POR_CONTROLCHAR:
215cdf0e10cSrcweir         {
216cdf0e10cSrcweir             OUStringBuffer aTmpBuffer( rText.Len() + 1 );
217cdf0e10cSrcweir             aTmpBuffer.append( rText );
218cdf0e10cSrcweir             aTmpBuffer.append( pTxtNode->GetTxt().GetChar(nModelPosition) );
219cdf0e10cSrcweir             sDisplay = aTmpBuffer.makeStringAndClear();
220cdf0e10cSrcweir             break;
221cdf0e10cSrcweir         }
222cdf0e10cSrcweir         // <--
223cdf0e10cSrcweir         default:
224cdf0e10cSrcweir             sDisplay = rText;
225cdf0e10cSrcweir             break;
226cdf0e10cSrcweir     }
227cdf0e10cSrcweir 
228cdf0e10cSrcweir     // ignore zero/zero portions (except for terminators)
229cdf0e10cSrcweir     if( (nLength == 0) && (sDisplay.Len() == 0) && (nType != POR_TERMINATE) )
230cdf0e10cSrcweir         return;
231cdf0e10cSrcweir 
232cdf0e10cSrcweir     // special treatment for zero length portion at the beginning:
233cdf0e10cSrcweir     // count as 'before' portion
234cdf0e10cSrcweir     if( ( nLength == 0 ) && ( nModelPosition == 0 ) )
235cdf0e10cSrcweir         nBeforePortions++;
236cdf0e10cSrcweir 
237cdf0e10cSrcweir     // store the 'old' positions
238cdf0e10cSrcweir     aModelPositions.push_back( nModelPosition );
239cdf0e10cSrcweir     aAccessiblePositions.push_back( aBuffer.getLength() );
240cdf0e10cSrcweir 
241cdf0e10cSrcweir     // store portion attributes
242cdf0e10cSrcweir     sal_uInt8 nAttr = PORATTR_SPECIAL;
243cdf0e10cSrcweir     if( IsGrayPortionType(nType) )      nAttr |= PORATTR_GRAY;
244cdf0e10cSrcweir     if( nLength == 0 )                  nAttr |= PORATTR_READONLY;
245cdf0e10cSrcweir     if( nType == POR_TERMINATE )        nAttr |= PORATTR_TERM;
246cdf0e10cSrcweir     aPortionAttrs.push_back( nAttr );
247cdf0e10cSrcweir 
248cdf0e10cSrcweir     // update buffer + nModelPosition
249cdf0e10cSrcweir     aBuffer.append( OUString(sDisplay) );
250cdf0e10cSrcweir     nModelPosition += nLength;
251cdf0e10cSrcweir 
252cdf0e10cSrcweir     // remember 'last' special portion (unless it's our own 'closing'
253cdf0e10cSrcweir     // portions from 'Finish()'
254cdf0e10cSrcweir     if( nType != POR_TERMINATE )
255cdf0e10cSrcweir         bLastIsSpecial = sal_True;
256cdf0e10cSrcweir }
257cdf0e10cSrcweir 
LineBreak()258cdf0e10cSrcweir void SwAccessiblePortionData::LineBreak()
259cdf0e10cSrcweir {
260cdf0e10cSrcweir     DBG_ASSERT( !bFinished, "We are already done!" );
261cdf0e10cSrcweir 
262cdf0e10cSrcweir     aLineBreaks.push_back( aBuffer.getLength() );
263cdf0e10cSrcweir }
264cdf0e10cSrcweir 
Skip(sal_uInt16 nLength)265cdf0e10cSrcweir void SwAccessiblePortionData::Skip(sal_uInt16 nLength)
266cdf0e10cSrcweir {
267cdf0e10cSrcweir     DBG_ASSERT( !bFinished, "We are already done!" );
268cdf0e10cSrcweir     DBG_ASSERT( aModelPositions.size() == 0, "Never Skip() after portions" );
269cdf0e10cSrcweir     DBG_ASSERT( nLength <= pTxtNode->GetTxt().Len(), "skip exceeds model string!" );
270cdf0e10cSrcweir 
271cdf0e10cSrcweir     nModelPosition += nLength;
272cdf0e10cSrcweir }
273cdf0e10cSrcweir 
Finish()274cdf0e10cSrcweir void SwAccessiblePortionData::Finish()
275cdf0e10cSrcweir {
276cdf0e10cSrcweir     DBG_ASSERT( !bFinished, "We are already done!" );
277cdf0e10cSrcweir 
278cdf0e10cSrcweir     // include terminator values: always include two 'last character'
279cdf0e10cSrcweir     // markers in the position arrays to make sure we always find one
280cdf0e10cSrcweir     // position before the end
281cdf0e10cSrcweir     Special( 0, String(), POR_TERMINATE );
282cdf0e10cSrcweir     Special( 0, String(), POR_TERMINATE );
283cdf0e10cSrcweir     LineBreak();
284cdf0e10cSrcweir     LineBreak();
285cdf0e10cSrcweir 
286cdf0e10cSrcweir     sAccessibleString = aBuffer.makeStringAndClear();
287cdf0e10cSrcweir     bFinished = sal_True;
288cdf0e10cSrcweir }
289cdf0e10cSrcweir 
290cdf0e10cSrcweir 
IsPortionAttrSet(size_t nPortionNo,sal_uInt8 nAttr) const291cdf0e10cSrcweir sal_Bool SwAccessiblePortionData::IsPortionAttrSet(
292cdf0e10cSrcweir     size_t nPortionNo, sal_uInt8 nAttr ) const
293cdf0e10cSrcweir {
294cdf0e10cSrcweir     DBG_ASSERT( nPortionNo < aPortionAttrs.size(),
295cdf0e10cSrcweir                 "Illegal portion number" );
296cdf0e10cSrcweir     return (aPortionAttrs[nPortionNo] & nAttr) != 0;
297cdf0e10cSrcweir }
298cdf0e10cSrcweir 
IsSpecialPortion(size_t nPortionNo) const299cdf0e10cSrcweir sal_Bool SwAccessiblePortionData::IsSpecialPortion( size_t nPortionNo ) const
300cdf0e10cSrcweir {
301cdf0e10cSrcweir     return IsPortionAttrSet(nPortionNo, PORATTR_SPECIAL);
302cdf0e10cSrcweir }
303cdf0e10cSrcweir 
IsReadOnlyPortion(size_t nPortionNo) const304cdf0e10cSrcweir sal_Bool SwAccessiblePortionData::IsReadOnlyPortion( size_t nPortionNo ) const
305cdf0e10cSrcweir {
306cdf0e10cSrcweir     return IsPortionAttrSet(nPortionNo, PORATTR_READONLY);
307cdf0e10cSrcweir }
308cdf0e10cSrcweir 
IsGrayPortionType(sal_uInt16 nType) const309cdf0e10cSrcweir sal_Bool SwAccessiblePortionData::IsGrayPortionType( sal_uInt16 nType ) const
310cdf0e10cSrcweir {
311cdf0e10cSrcweir     // gray portions?
312cdf0e10cSrcweir     // Compare with: inftxt.cxx, SwTxtPaintInfo::DrawViewOpt(...)
313cdf0e10cSrcweir     sal_Bool bGray = sal_False;
314cdf0e10cSrcweir     switch( nType )
315cdf0e10cSrcweir     {
316cdf0e10cSrcweir         case POR_FTN:
317cdf0e10cSrcweir         case POR_ISOREF:
318cdf0e10cSrcweir         case POR_REF:
319cdf0e10cSrcweir         case POR_QUOVADIS:
320cdf0e10cSrcweir         case POR_NUMBER:
321cdf0e10cSrcweir         case POR_FLD:
322cdf0e10cSrcweir         case POR_URL:
32369a74367SOliver-Rainer Wittmann         case POR_INPUTFLD:
324cdf0e10cSrcweir         case POR_ISOTOX:
325cdf0e10cSrcweir         case POR_TOX:
326cdf0e10cSrcweir         case POR_HIDDEN:
327cdf0e10cSrcweir             bGray = !pViewOptions->IsPagePreview() &&
328cdf0e10cSrcweir                 !pViewOptions->IsReadonly() && SwViewOption::IsFieldShadings();
329cdf0e10cSrcweir         break;
330cdf0e10cSrcweir         case POR_TAB:       bGray = pViewOptions->IsTab();          break;
331cdf0e10cSrcweir         case POR_SOFTHYPH:  bGray = pViewOptions->IsSoftHyph();     break;
332cdf0e10cSrcweir         case POR_BLANK:     bGray = pViewOptions->IsHardBlank();    break;
333cdf0e10cSrcweir         default:
334cdf0e10cSrcweir             break; // bGray is false
335cdf0e10cSrcweir     }
336cdf0e10cSrcweir     return bGray;
337cdf0e10cSrcweir }
338cdf0e10cSrcweir 
339cdf0e10cSrcweir 
GetAccessibleString() const340cdf0e10cSrcweir const OUString& SwAccessiblePortionData::GetAccessibleString() const
341cdf0e10cSrcweir {
342cdf0e10cSrcweir     DBG_ASSERT( bFinished, "Shouldn't call this before we are done!" );
343cdf0e10cSrcweir 
344cdf0e10cSrcweir     return sAccessibleString;
345cdf0e10cSrcweir }
346cdf0e10cSrcweir 
347cdf0e10cSrcweir 
GetLineBoundary(Boundary & rBound,sal_Int32 nPos) const348cdf0e10cSrcweir void SwAccessiblePortionData::GetLineBoundary(
349cdf0e10cSrcweir     Boundary& rBound,
350cdf0e10cSrcweir     sal_Int32 nPos ) const
351cdf0e10cSrcweir {
352cdf0e10cSrcweir     FillBoundary( rBound, aLineBreaks,
353cdf0e10cSrcweir                   FindBreak( aLineBreaks, nPos ) );
354cdf0e10cSrcweir }
355cdf0e10cSrcweir 
356cdf0e10cSrcweir // --> OD 2008-05-30 #i89175#
GetLineCount() const357cdf0e10cSrcweir sal_Int32 SwAccessiblePortionData::GetLineCount() const
358cdf0e10cSrcweir {
359cdf0e10cSrcweir     size_t nBreaks = aLineBreaks.size();
360cdf0e10cSrcweir     // A non-empty paragraph has at least 4 breaks: one for each line3 and
361cdf0e10cSrcweir     // 3 additional ones.
362cdf0e10cSrcweir     // An empty paragraph has 3 breaks.
363cdf0e10cSrcweir     // Less than 3 breaks is an error case.
364cdf0e10cSrcweir     sal_Int32 nLineCount = ( nBreaks > 3 )
365cdf0e10cSrcweir                            ? nBreaks - 3
366cdf0e10cSrcweir                            : ( ( nBreaks == 3 ) ? 1 : 0 );
367cdf0e10cSrcweir     return nLineCount;
368cdf0e10cSrcweir }
369cdf0e10cSrcweir 
GetLineNo(const sal_Int32 nPos) const370cdf0e10cSrcweir sal_Int32 SwAccessiblePortionData::GetLineNo( const sal_Int32 nPos ) const
371cdf0e10cSrcweir {
372cdf0e10cSrcweir     sal_Int32 nLineNo = FindBreak( aLineBreaks, nPos );
373cdf0e10cSrcweir 
374cdf0e10cSrcweir     // handling of position after last character
375cdf0e10cSrcweir     const sal_Int32 nLineCount( GetLineCount() );
376cdf0e10cSrcweir     if ( nLineNo >= nLineCount )
377cdf0e10cSrcweir     {
378cdf0e10cSrcweir         nLineNo = nLineCount - 1;
379cdf0e10cSrcweir     }
380cdf0e10cSrcweir 
381cdf0e10cSrcweir     return nLineNo;
382cdf0e10cSrcweir }
383cdf0e10cSrcweir 
GetBoundaryOfLine(const sal_Int32 nLineNo,i18n::Boundary & rLineBound)384cdf0e10cSrcweir void SwAccessiblePortionData::GetBoundaryOfLine( const sal_Int32 nLineNo,
385cdf0e10cSrcweir                                                  i18n::Boundary& rLineBound )
386cdf0e10cSrcweir {
387cdf0e10cSrcweir     FillBoundary( rLineBound, aLineBreaks, nLineNo );
388cdf0e10cSrcweir }
389cdf0e10cSrcweir // <--
390cdf0e10cSrcweir 
GetLastLineBoundary(Boundary & rBound) const391cdf0e10cSrcweir void SwAccessiblePortionData::GetLastLineBoundary(
392cdf0e10cSrcweir     Boundary& rBound ) const
393cdf0e10cSrcweir {
394cdf0e10cSrcweir     DBG_ASSERT( aLineBreaks.size() >= 2, "need min + max value" );
395cdf0e10cSrcweir 
396*0cb2ec91SJohn Bampton     // The last two positions except the two delimiters are the ones
397cdf0e10cSrcweir     // we are looking for, except for empty paragraphs (nBreaks==3)
398cdf0e10cSrcweir     size_t nBreaks = aLineBreaks.size();
399cdf0e10cSrcweir     FillBoundary( rBound, aLineBreaks, nBreaks <= 3 ? 0 : nBreaks-4 );
400cdf0e10cSrcweir }
401cdf0e10cSrcweir 
GetModelPosition(sal_Int32 nPos) const402cdf0e10cSrcweir sal_uInt16 SwAccessiblePortionData::GetModelPosition( sal_Int32 nPos ) const
403cdf0e10cSrcweir {
404cdf0e10cSrcweir     DBG_ASSERT( nPos >= 0, "illegal position" );
405cdf0e10cSrcweir     DBG_ASSERT( nPos <= sAccessibleString.getLength(), "illegal position" );
406cdf0e10cSrcweir 
407cdf0e10cSrcweir     // find the portion number
408cdf0e10cSrcweir     size_t nPortionNo = FindBreak( aAccessiblePositions, nPos );
409cdf0e10cSrcweir 
410cdf0e10cSrcweir     // get model portion size
411cdf0e10cSrcweir     sal_Int32 nStartPos = aModelPositions[nPortionNo];
412cdf0e10cSrcweir 
413cdf0e10cSrcweir     // if it's a non-special portion, move into the portion, else
414cdf0e10cSrcweir     // return the portion start
415cdf0e10cSrcweir     if( ! IsSpecialPortion( nPortionNo ) )
416cdf0e10cSrcweir     {
417cdf0e10cSrcweir         // 'wide' portions have to be of the same width
418cdf0e10cSrcweir         DBG_ASSERT( ( aModelPositions[nPortionNo+1] - nStartPos ) ==
419cdf0e10cSrcweir                     ( aAccessiblePositions[nPortionNo+1] -
420cdf0e10cSrcweir                       aAccessiblePositions[nPortionNo] ),
421*0cb2ec91SJohn Bampton                     "accessibility portion disagrees with text model" );
422cdf0e10cSrcweir 
423cdf0e10cSrcweir         sal_Int32 nWithinPortion = nPos - aAccessiblePositions[nPortionNo];
424cdf0e10cSrcweir         nStartPos += nWithinPortion;
425cdf0e10cSrcweir     }
426cdf0e10cSrcweir     // else: return nStartPos unmodified
427cdf0e10cSrcweir 
428cdf0e10cSrcweir     DBG_ASSERT( (nStartPos >= 0) && (nStartPos < USHRT_MAX),
429cdf0e10cSrcweir                 "How can the SwTxtNode have so many characters?" );
430cdf0e10cSrcweir     return static_cast<sal_uInt16>(nStartPos);
431cdf0e10cSrcweir }
432cdf0e10cSrcweir 
FillBoundary(Boundary & rBound,const Positions_t & rPositions,size_t nPos) const433cdf0e10cSrcweir void SwAccessiblePortionData::FillBoundary(
434cdf0e10cSrcweir     Boundary& rBound,
435cdf0e10cSrcweir     const Positions_t& rPositions,
436cdf0e10cSrcweir     size_t nPos ) const
437cdf0e10cSrcweir {
438cdf0e10cSrcweir     rBound.startPos = rPositions[nPos];
439cdf0e10cSrcweir     rBound.endPos = rPositions[nPos+1];
440cdf0e10cSrcweir }
441cdf0e10cSrcweir 
442cdf0e10cSrcweir 
FindBreak(const Positions_t & rPositions,sal_Int32 nValue) const443cdf0e10cSrcweir size_t SwAccessiblePortionData::FindBreak(
444cdf0e10cSrcweir     const Positions_t& rPositions,
445cdf0e10cSrcweir     sal_Int32 nValue ) const
446cdf0e10cSrcweir {
447cdf0e10cSrcweir     DBG_ASSERT( rPositions.size() >= 2, "need min + max value" );
448cdf0e10cSrcweir     DBG_ASSERT( rPositions[0] <= nValue, "need min value" );
449cdf0e10cSrcweir     DBG_ASSERT( rPositions[rPositions.size()-1] >= nValue,
450cdf0e10cSrcweir                 "need first terminator value" );
451cdf0e10cSrcweir     DBG_ASSERT( rPositions[rPositions.size()-2] >= nValue,
452cdf0e10cSrcweir                 "need second terminator value" );
453cdf0e10cSrcweir 
454cdf0e10cSrcweir     size_t nMin = 0;
455cdf0e10cSrcweir     size_t nMax = rPositions.size()-2;
456cdf0e10cSrcweir 
457cdf0e10cSrcweir     // loop until no more than two candidates are left
458cdf0e10cSrcweir     while( nMin+1 < nMax )
459cdf0e10cSrcweir     {
460cdf0e10cSrcweir         // check loop invariants
461cdf0e10cSrcweir         DBG_ASSERT( ( (nMin == 0) && (rPositions[nMin] <= nValue) ) ||
462cdf0e10cSrcweir                     ( (nMin != 0) && (rPositions[nMin] < nValue) ),
463cdf0e10cSrcweir                     "minvalue not minimal" );
464cdf0e10cSrcweir         DBG_ASSERT( nValue <= rPositions[nMax], "max value not maximal" );
465cdf0e10cSrcweir 
466cdf0e10cSrcweir         // get middle (and ensure progress)
467cdf0e10cSrcweir         size_t nMiddle = (nMin + nMax)/2;
468cdf0e10cSrcweir         DBG_ASSERT( nMin < nMiddle, "progress?" );
469cdf0e10cSrcweir         DBG_ASSERT( nMiddle < nMax, "progress?" );
470cdf0e10cSrcweir 
471cdf0e10cSrcweir         // check array
472cdf0e10cSrcweir         DBG_ASSERT( rPositions[nMin] <= rPositions[nMiddle],
473cdf0e10cSrcweir                     "garbled positions array" );
474cdf0e10cSrcweir         DBG_ASSERT( rPositions[nMiddle] <= rPositions[nMax],
475cdf0e10cSrcweir                     "garbled positions array" );
476cdf0e10cSrcweir 
477cdf0e10cSrcweir         if( nValue > rPositions[nMiddle] )
478cdf0e10cSrcweir             nMin = nMiddle;
479cdf0e10cSrcweir         else
480cdf0e10cSrcweir             nMax = nMiddle;
481cdf0e10cSrcweir     }
482cdf0e10cSrcweir 
483cdf0e10cSrcweir     // only two are left; we only need to check which one is the winner
484cdf0e10cSrcweir     DBG_ASSERT( (nMax == nMin) || (nMax == nMin+1), "only two left" );
485cdf0e10cSrcweir     if( (rPositions[nMin] < nValue) && (rPositions[nMin+1] <= nValue) )
486cdf0e10cSrcweir         nMin = nMin+1;
487cdf0e10cSrcweir 
488cdf0e10cSrcweir     // finally, check to see whether the returned value is the 'right' position
489cdf0e10cSrcweir     DBG_ASSERT( rPositions[nMin] <= nValue, "not smaller or equal" );
490cdf0e10cSrcweir     DBG_ASSERT( nValue <= rPositions[nMin+1], "not equal or larger" );
491cdf0e10cSrcweir     DBG_ASSERT( (nMin == 0) || (rPositions[nMin-1] <= nValue),
492cdf0e10cSrcweir                 "earlier value should have been returned" );
493cdf0e10cSrcweir 
494cdf0e10cSrcweir     DBG_ASSERT( nMin < rPositions.size()-1,
495*0cb2ec91SJohn Bampton                 "shouldn't return last position (due to terminator values)" );
496cdf0e10cSrcweir 
497cdf0e10cSrcweir     return nMin;
498cdf0e10cSrcweir }
499cdf0e10cSrcweir 
FindLastBreak(const Positions_t & rPositions,sal_Int32 nValue) const500cdf0e10cSrcweir size_t SwAccessiblePortionData::FindLastBreak(
501cdf0e10cSrcweir     const Positions_t& rPositions,
502cdf0e10cSrcweir     sal_Int32 nValue ) const
503cdf0e10cSrcweir {
504cdf0e10cSrcweir     size_t nResult = FindBreak( rPositions, nValue );
505cdf0e10cSrcweir 
506cdf0e10cSrcweir     // skip 'zero-length' portions
507cdf0e10cSrcweir     // --> OD 2006-10-19 #i70538#
508cdf0e10cSrcweir     // consider size of <rPosition> and ignore last entry
509cdf0e10cSrcweir //    while( rPositions[nResult+1] <= nValue )
510cdf0e10cSrcweir     while ( nResult < rPositions.size() - 2 &&
511cdf0e10cSrcweir             rPositions[nResult+1] <= nValue )
512cdf0e10cSrcweir     {
513cdf0e10cSrcweir         nResult++;
514cdf0e10cSrcweir     }
515cdf0e10cSrcweir     // <--
516cdf0e10cSrcweir 
517cdf0e10cSrcweir     return nResult;
518cdf0e10cSrcweir }
519cdf0e10cSrcweir 
520cdf0e10cSrcweir 
GetSentenceBoundary(Boundary & rBound,sal_Int32 nPos)521cdf0e10cSrcweir void SwAccessiblePortionData::GetSentenceBoundary(
522cdf0e10cSrcweir     Boundary& rBound,
523cdf0e10cSrcweir     sal_Int32 nPos )
524cdf0e10cSrcweir {
525cdf0e10cSrcweir     DBG_ASSERT( nPos >= 0, "illegal position; check before" );
526cdf0e10cSrcweir     DBG_ASSERT( nPos < sAccessibleString.getLength(), "illegal position" );
527cdf0e10cSrcweir 
528cdf0e10cSrcweir     if( pSentences == NULL )
529cdf0e10cSrcweir     {
530cdf0e10cSrcweir          DBG_ASSERT( pBreakIt != NULL, "We always need a break." );
531cdf0e10cSrcweir          DBG_ASSERT( pBreakIt->GetBreakIter().is(), "No break-iterator." );
532cdf0e10cSrcweir          if( pBreakIt->GetBreakIter().is() )
533cdf0e10cSrcweir          {
534cdf0e10cSrcweir              pSentences = new Positions_t();
535cdf0e10cSrcweir              pSentences->reserve(10);
536cdf0e10cSrcweir 
537cdf0e10cSrcweir              // use xBreak->endOfSentence to iterate over all words; store
538cdf0e10cSrcweir              // positions in pSentences
539cdf0e10cSrcweir              sal_Int32 nCurrent = 0;
540cdf0e10cSrcweir              sal_Int32 nLength = sAccessibleString.getLength();
541cdf0e10cSrcweir              do
542cdf0e10cSrcweir              {
543cdf0e10cSrcweir                  pSentences->push_back( nCurrent );
544cdf0e10cSrcweir 
545cdf0e10cSrcweir                  sal_uInt16 nModelPos = GetModelPosition( nCurrent );
546cdf0e10cSrcweir 
547cdf0e10cSrcweir                  sal_Int32 nNew = pBreakIt->GetBreakIter()->endOfSentence(
548cdf0e10cSrcweir                      sAccessibleString, nCurrent,
549cdf0e10cSrcweir                      pBreakIt->GetLocale(pTxtNode->GetLang(nModelPos)) ) + 1;
550cdf0e10cSrcweir 
551cdf0e10cSrcweir                  if( (nNew < 0) && (nNew > nLength) )
552cdf0e10cSrcweir                      nNew = nLength;
553cdf0e10cSrcweir                  else if (nNew <= nCurrent)
554cdf0e10cSrcweir                      nNew = nCurrent + 1;   // ensure forward progress
555cdf0e10cSrcweir 
556cdf0e10cSrcweir                  nCurrent = nNew;
557cdf0e10cSrcweir              }
558cdf0e10cSrcweir              while (nCurrent < nLength);
559cdf0e10cSrcweir 
560cdf0e10cSrcweir              // finish with two terminators
561cdf0e10cSrcweir              pSentences->push_back( nLength );
562cdf0e10cSrcweir              pSentences->push_back( nLength );
563cdf0e10cSrcweir          }
564cdf0e10cSrcweir          else
565cdf0e10cSrcweir          {
566cdf0e10cSrcweir              // no break iterator -> empty word
567cdf0e10cSrcweir              rBound.startPos = 0;
568cdf0e10cSrcweir              rBound.endPos = 0;
569cdf0e10cSrcweir              return;
570cdf0e10cSrcweir          }
571cdf0e10cSrcweir     }
572cdf0e10cSrcweir 
573cdf0e10cSrcweir     FillBoundary( rBound, *pSentences, FindBreak( *pSentences, nPos ) );
574cdf0e10cSrcweir }
575cdf0e10cSrcweir 
GetAttributeBoundary(Boundary & rBound,sal_Int32 nPos) const576cdf0e10cSrcweir void SwAccessiblePortionData::GetAttributeBoundary(
577cdf0e10cSrcweir     Boundary& rBound,
578cdf0e10cSrcweir     sal_Int32 nPos) const
579cdf0e10cSrcweir {
580cdf0e10cSrcweir     DBG_ASSERT( pTxtNode != NULL, "Need SwTxtNode!" );
581cdf0e10cSrcweir 
582cdf0e10cSrcweir     // attribute boundaries can only occur on portion boundaries
583cdf0e10cSrcweir     FillBoundary( rBound, aAccessiblePositions,
584cdf0e10cSrcweir                   FindBreak( aAccessiblePositions, nPos ) );
585cdf0e10cSrcweir }
586cdf0e10cSrcweir 
587cdf0e10cSrcweir 
GetAccessiblePosition(sal_uInt16 nPos) const588cdf0e10cSrcweir sal_Int32 SwAccessiblePortionData::GetAccessiblePosition( sal_uInt16 nPos ) const
589cdf0e10cSrcweir {
590cdf0e10cSrcweir     DBG_ASSERT( nPos <= pTxtNode->GetTxt().Len(), "illegal position" );
591cdf0e10cSrcweir 
592cdf0e10cSrcweir     // find the portion number
593cdf0e10cSrcweir     // --> OD 2006-10-19 #i70538#
594cdf0e10cSrcweir     // consider "empty" model portions - e.g. number portion
595cdf0e10cSrcweir     size_t nPortionNo = FindLastBreak( aModelPositions,
596cdf0e10cSrcweir                                        static_cast<sal_Int32>(nPos) );
597cdf0e10cSrcweir     // <--
598cdf0e10cSrcweir 
599cdf0e10cSrcweir     sal_Int32 nRet = aAccessiblePositions[nPortionNo];
600cdf0e10cSrcweir 
601cdf0e10cSrcweir     // if the model portion has more than one position, go into it;
602cdf0e10cSrcweir     // else return that position
603cdf0e10cSrcweir     sal_Int32 nStartPos = aModelPositions[nPortionNo];
604cdf0e10cSrcweir     sal_Int32 nEndPos = aModelPositions[nPortionNo+1];
605cdf0e10cSrcweir     if( (nEndPos - nStartPos) > 1 )
606cdf0e10cSrcweir     {
607cdf0e10cSrcweir         // 'wide' portions have to be of the same width
608cdf0e10cSrcweir         DBG_ASSERT( ( nEndPos - nStartPos ) ==
609cdf0e10cSrcweir                     ( aAccessiblePositions[nPortionNo+1] -
610cdf0e10cSrcweir                       aAccessiblePositions[nPortionNo] ),
611*0cb2ec91SJohn Bampton                     "accessibility portion disagrees with text model" );
612cdf0e10cSrcweir 
613cdf0e10cSrcweir         sal_Int32 nWithinPortion = nPos - aModelPositions[nPortionNo];
614cdf0e10cSrcweir         nRet += nWithinPortion;
615cdf0e10cSrcweir     }
616cdf0e10cSrcweir     // else: return nRet unmodified
617cdf0e10cSrcweir 
618cdf0e10cSrcweir     DBG_ASSERT( (nRet >= 0) && (nRet <= sAccessibleString.getLength()),
619cdf0e10cSrcweir                 "too long!" );
620cdf0e10cSrcweir     return nRet;
621cdf0e10cSrcweir }
622cdf0e10cSrcweir 
FillSpecialPos(sal_Int32 nPos,SwSpecialPos & rPos,SwSpecialPos * & rpPos) const623cdf0e10cSrcweir sal_uInt16 SwAccessiblePortionData::FillSpecialPos(
624cdf0e10cSrcweir     sal_Int32 nPos,
625cdf0e10cSrcweir     SwSpecialPos& rPos,
626cdf0e10cSrcweir     SwSpecialPos*& rpPos ) const
627cdf0e10cSrcweir {
628cdf0e10cSrcweir     size_t nPortionNo = FindLastBreak( aAccessiblePositions, nPos );
629cdf0e10cSrcweir 
630cdf0e10cSrcweir     sal_uInt8 nExtend(SP_EXTEND_RANGE_NONE);
631cdf0e10cSrcweir     sal_Int32 nRefPos(0);
632cdf0e10cSrcweir     sal_Int32 nModelPos(0);
633cdf0e10cSrcweir 
634cdf0e10cSrcweir     if( nPortionNo < nBeforePortions )
635cdf0e10cSrcweir     {
636cdf0e10cSrcweir         nExtend = SP_EXTEND_RANGE_BEFORE;
637cdf0e10cSrcweir         rpPos = &rPos;
638cdf0e10cSrcweir     }
639cdf0e10cSrcweir     else
640cdf0e10cSrcweir     {
641cdf0e10cSrcweir         sal_Int32 nModelEndPos = aModelPositions[nPortionNo+1];
642cdf0e10cSrcweir         nModelPos = aModelPositions[nPortionNo];
643cdf0e10cSrcweir 
644cdf0e10cSrcweir         // skip backwards over zero-length portions, since GetCharRect()
645cdf0e10cSrcweir         // counts all model-zero-length portions as belonging to the
646*0cb2ec91SJohn Bampton         // previous portion
647cdf0e10cSrcweir         size_t nCorePortionNo = nPortionNo;
648cdf0e10cSrcweir         while( nModelPos == nModelEndPos )
649cdf0e10cSrcweir         {
650cdf0e10cSrcweir             nCorePortionNo--;
651cdf0e10cSrcweir             nModelEndPos = nModelPos;
652cdf0e10cSrcweir             nModelPos = aModelPositions[nCorePortionNo];
653cdf0e10cSrcweir 
654cdf0e10cSrcweir             DBG_ASSERT( nModelPos >= 0, "Can't happen." );
655cdf0e10cSrcweir             DBG_ASSERT( nCorePortionNo >= nBeforePortions, "Can't happen." );
656cdf0e10cSrcweir         }
657cdf0e10cSrcweir         DBG_ASSERT( nModelPos != nModelEndPos,
658cdf0e10cSrcweir                     "portion with core-representation expected" );
659cdf0e10cSrcweir 
660cdf0e10cSrcweir         // if we have anything except plain text, compute nExtend + nRefPos
661cdf0e10cSrcweir         if( (nModelEndPos - nModelPos == 1) &&
662cdf0e10cSrcweir             (pTxtNode->GetTxt().GetChar(static_cast<sal_uInt16>(nModelPos)) !=
663cdf0e10cSrcweir              sAccessibleString.getStr()[nPos]) )
664cdf0e10cSrcweir         {
665cdf0e10cSrcweir             // case 1: a one-character, non-text portion
666ceb51a8eSJohn Bampton             // reference position is the first accessibility for our
667cdf0e10cSrcweir             // core portion
668cdf0e10cSrcweir             nRefPos = aAccessiblePositions[ nCorePortionNo ];
669cdf0e10cSrcweir             nExtend = SP_EXTEND_RANGE_NONE;
670cdf0e10cSrcweir             rpPos = &rPos;
671cdf0e10cSrcweir         }
672cdf0e10cSrcweir         else if(nPortionNo != nCorePortionNo)
673cdf0e10cSrcweir         {
674cdf0e10cSrcweir             // case 2: a multi-character (text!) portion, followed by
675cdf0e10cSrcweir             // zero-length portions
676cdf0e10cSrcweir             // reference position is the first character of the next
677cdf0e10cSrcweir             // portion, and we are 'behind'
678cdf0e10cSrcweir             nRefPos = aAccessiblePositions[ nCorePortionNo+1 ];
679cdf0e10cSrcweir             nExtend = SP_EXTEND_RANGE_BEHIND;
680cdf0e10cSrcweir             rpPos = &rPos;
681cdf0e10cSrcweir         }
682cdf0e10cSrcweir         else
683cdf0e10cSrcweir         {
684cdf0e10cSrcweir             // case 3: regular text portion
685cdf0e10cSrcweir             DBG_ASSERT( ( nModelEndPos - nModelPos ) ==
686cdf0e10cSrcweir                         ( aAccessiblePositions[nPortionNo+1] -
687cdf0e10cSrcweir                           aAccessiblePositions[nPortionNo] ),
688cdf0e10cSrcweir                         "text portion expected" );
689cdf0e10cSrcweir 
690cdf0e10cSrcweir             nModelPos += nPos - aAccessiblePositions[ nPortionNo ];
691cdf0e10cSrcweir             rpPos = NULL;
692cdf0e10cSrcweir         }
693cdf0e10cSrcweir     }
694cdf0e10cSrcweir     if( rpPos != NULL )
695cdf0e10cSrcweir     {
696cdf0e10cSrcweir         DBG_ASSERT( rpPos == &rPos, "Yes!" );
697cdf0e10cSrcweir         DBG_ASSERT( nRefPos <= nPos, "wrong reference" );
698cdf0e10cSrcweir         DBG_ASSERT( (nExtend == SP_EXTEND_RANGE_NONE) ||
699cdf0e10cSrcweir                     (nExtend == SP_EXTEND_RANGE_BEFORE) ||
700cdf0e10cSrcweir                     (nExtend == SP_EXTEND_RANGE_BEHIND), "need extend" );
701cdf0e10cSrcweir 
702cdf0e10cSrcweir         // get the line number, and adjust nRefPos for the line
703cdf0e10cSrcweir         // (if necessary)
704cdf0e10cSrcweir         size_t nRefLine = FindBreak( aLineBreaks, nRefPos );
705cdf0e10cSrcweir         size_t nMyLine  = FindBreak( aLineBreaks, nPos );
706cdf0e10cSrcweir         sal_uInt16 nLineOffset = static_cast<sal_uInt16>( nMyLine - nRefLine );
707cdf0e10cSrcweir         if( nLineOffset != 0 )
708cdf0e10cSrcweir             nRefPos = aLineBreaks[ nMyLine ];
709cdf0e10cSrcweir 
710cdf0e10cSrcweir         // fill char offset and 'special position'
711cdf0e10cSrcweir         rPos.nCharOfst = static_cast<sal_uInt16>( nPos - nRefPos );
712cdf0e10cSrcweir         rPos.nExtendRange = nExtend;
713cdf0e10cSrcweir         rPos.nLineOfst = nLineOffset;
714cdf0e10cSrcweir     }
715cdf0e10cSrcweir 
716cdf0e10cSrcweir     return static_cast<sal_uInt16>( nModelPos );
717cdf0e10cSrcweir }
718cdf0e10cSrcweir 
GetAttrFldType(sal_Int32 nPos)719ca62e2c2SSteve Yin sal_uInt16 SwAccessiblePortionData::GetAttrFldType( sal_Int32 nPos )
720ca62e2c2SSteve Yin {
721ca62e2c2SSteve Yin     if( aFieldPosition.size() < 2 ) return sal_False;
722ca62e2c2SSteve Yin     sal_Int32 nFieldIndex = 0;
723ca62e2c2SSteve Yin     for( size_t i = 0; i < aFieldPosition.size() - 1; i += 2 )
724ca62e2c2SSteve Yin     {
725ca62e2c2SSteve Yin         if( nPos < aFieldPosition[ i + 1 ]  &&  nPos >= aFieldPosition[ i ] )
726ca62e2c2SSteve Yin         {
727ca62e2c2SSteve Yin             return aAttrFieldType[nFieldIndex];
728ca62e2c2SSteve Yin         }
729ca62e2c2SSteve Yin         nFieldIndex++ ;
730ca62e2c2SSteve Yin     }
731ca62e2c2SSteve Yin     return 0;
732ca62e2c2SSteve Yin }
733ca62e2c2SSteve Yin 
FillBoundaryIFDateField(com::sun::star::i18n::Boundary & rBound,const sal_Int32 nPos)734ca62e2c2SSteve Yin sal_Bool SwAccessiblePortionData::FillBoundaryIFDateField( com::sun::star::i18n::Boundary& rBound, const sal_Int32 nPos )
735ca62e2c2SSteve Yin {
736ca62e2c2SSteve Yin     if( aFieldPosition.size() < 2 ) return sal_False;
737ca62e2c2SSteve Yin     for( size_t i = 0; i < aFieldPosition.size() - 1; i += 2 )
738ca62e2c2SSteve Yin     {
739ca62e2c2SSteve Yin         if( nPos < aFieldPosition[ i + 1 ]  &&  nPos >= aFieldPosition[ i ] )
740ca62e2c2SSteve Yin         {
741ca62e2c2SSteve Yin             rBound.startPos = aFieldPosition[i];
742ca62e2c2SSteve Yin             rBound.endPos =  aFieldPosition[i + 1];
743ca62e2c2SSteve Yin             return sal_True;
744ca62e2c2SSteve Yin         }
745ca62e2c2SSteve Yin     }
746ca62e2c2SSteve Yin     return sal_False;
747ca62e2c2SSteve Yin }
AdjustAndCheck(sal_Int32 nPos,size_t & nPortionNo,sal_uInt16 & nCorePos,sal_Bool & bEdit) const748cdf0e10cSrcweir void SwAccessiblePortionData::AdjustAndCheck(
749cdf0e10cSrcweir     sal_Int32 nPos,
750cdf0e10cSrcweir     size_t& nPortionNo,
751cdf0e10cSrcweir     sal_uInt16& nCorePos,
752cdf0e10cSrcweir     sal_Bool& bEdit) const
753cdf0e10cSrcweir {
754cdf0e10cSrcweir     // find portion and get mode position
755cdf0e10cSrcweir     nPortionNo = FindBreak( aAccessiblePositions, nPos );
756cdf0e10cSrcweir     nCorePos = static_cast<sal_uInt16>( aModelPositions[ nPortionNo ] );
757cdf0e10cSrcweir 
758cdf0e10cSrcweir     // for special portions, make sure we're on a portion boundary
759cdf0e10cSrcweir     // for text portions, add the in-portion offset
760cdf0e10cSrcweir     if( IsSpecialPortion( nPortionNo ) )
761cdf0e10cSrcweir         bEdit &= nPos == aAccessiblePositions[nPortionNo];
762cdf0e10cSrcweir     else
763cdf0e10cSrcweir         nCorePos = static_cast<sal_uInt16>( nCorePos +
764cdf0e10cSrcweir             nPos - aAccessiblePositions[nPortionNo] );
765cdf0e10cSrcweir }
766cdf0e10cSrcweir 
GetEditableRange(sal_Int32 nStart,sal_Int32 nEnd,sal_uInt16 & nCoreStart,sal_uInt16 & nCoreEnd) const767cdf0e10cSrcweir sal_Bool SwAccessiblePortionData::GetEditableRange(
768cdf0e10cSrcweir     sal_Int32 nStart, sal_Int32 nEnd,
769cdf0e10cSrcweir     sal_uInt16& nCoreStart, sal_uInt16& nCoreEnd ) const
770cdf0e10cSrcweir {
771cdf0e10cSrcweir     sal_Bool bIsEditable = sal_True;
772cdf0e10cSrcweir 
773cdf0e10cSrcweir     // get start and end portions
774cdf0e10cSrcweir     size_t nStartPortion, nEndPortion;
775cdf0e10cSrcweir     AdjustAndCheck( nStart, nStartPortion, nCoreStart, bIsEditable );
776cdf0e10cSrcweir     AdjustAndCheck( nEnd,   nEndPortion,   nCoreEnd,   bIsEditable );
777cdf0e10cSrcweir 
778cdf0e10cSrcweir     // iterate over portions, and make sure there is no read-only portion
779cdf0e10cSrcweir     // in-between
780cdf0e10cSrcweir     size_t nLastPortion = nEndPortion;
781cdf0e10cSrcweir 
782cdf0e10cSrcweir     // don't count last portion if we're in front of a special portion
783cdf0e10cSrcweir     if( IsSpecialPortion(nLastPortion) )
784cdf0e10cSrcweir     {
785cdf0e10cSrcweir         if (nLastPortion > 0)
786cdf0e10cSrcweir             nLastPortion--;
787cdf0e10cSrcweir         else
788cdf0e10cSrcweir             // special case: because size_t is usually unsigned, we can't just
789cdf0e10cSrcweir             // decrease nLastPortion to -1 (which would normally do the job, so
790cdf0e10cSrcweir             // this whole if wouldn't be needed). Instead, we'll do this
791*0cb2ec91SJohn Bampton             // special case and just increase the start portion beyond the last
792cdf0e10cSrcweir             // portion to make sure the loop below will have zero iteration.
793cdf0e10cSrcweir             nStartPortion = nLastPortion + 1;
794cdf0e10cSrcweir     }
795cdf0e10cSrcweir 
796cdf0e10cSrcweir     for( size_t nPor = nStartPortion; nPor <= nLastPortion; nPor ++ )
797cdf0e10cSrcweir     {
798cdf0e10cSrcweir         bIsEditable &= ! IsReadOnlyPortion( nPor );
799cdf0e10cSrcweir     }
800cdf0e10cSrcweir 
801cdf0e10cSrcweir     return bIsEditable;
802cdf0e10cSrcweir }
803cdf0e10cSrcweir 
IsValidCorePosition(sal_uInt16 nPos) const804cdf0e10cSrcweir sal_Bool SwAccessiblePortionData::IsValidCorePosition( sal_uInt16 nPos ) const
805cdf0e10cSrcweir {
806cdf0e10cSrcweir     // a position is valid its within the model positions that we know
807cdf0e10cSrcweir     return ( aModelPositions[0] <= nPos ) &&
808cdf0e10cSrcweir            ( nPos <= aModelPositions[ aModelPositions.size()-1 ] );
809cdf0e10cSrcweir }
810cdf0e10cSrcweir 
IsZeroCorePositionData()811ca62e2c2SSteve Yin sal_Bool SwAccessiblePortionData::IsZeroCorePositionData()
812ca62e2c2SSteve Yin {
813ca62e2c2SSteve Yin     if( aModelPositions.size() < 1  ) return sal_True;
814ca62e2c2SSteve Yin     return aModelPositions[0] == 0 &&  aModelPositions[aModelPositions.size()-1] == 0;
815ca62e2c2SSteve Yin }
816ca62e2c2SSteve Yin 
IsIndexInFootnode(sal_Int32 nIndex)817ca62e2c2SSteve Yin sal_Bool SwAccessiblePortionData::IsIndexInFootnode(sal_Int32 nIndex)
818ca62e2c2SSteve Yin {
819ca62e2c2SSteve Yin     VEC_PAIR_POS::iterator vi =m_vecPairPos.begin();
820ca62e2c2SSteve Yin     for (;vi != m_vecPairPos.end() ; ++vi)
821ca62e2c2SSteve Yin     {
822ca62e2c2SSteve Yin         const PAIR_POS &pairPos = *vi;
823ca62e2c2SSteve Yin         if(nIndex >= pairPos.first && nIndex < pairPos.second )
824ca62e2c2SSteve Yin         {
825ca62e2c2SSteve Yin             return sal_True;
826ca62e2c2SSteve Yin         }
827ca62e2c2SSteve Yin     }
828ca62e2c2SSteve Yin     return sal_False;
829ca62e2c2SSteve Yin }
830ca62e2c2SSteve Yin 
IsInGrayPortion(sal_Int32 nPos)831ca62e2c2SSteve Yin sal_Bool SwAccessiblePortionData::IsInGrayPortion( sal_Int32 nPos )
832ca62e2c2SSteve Yin {
833ca62e2c2SSteve Yin //    return IsGrayPortion( FindBreak( aAccessiblePositions, nPos ) );
834ca62e2c2SSteve Yin     return IsPortionAttrSet( FindBreak( aAccessiblePositions, nPos ),
835ca62e2c2SSteve Yin                              PORATTR_GRAY );
836ca62e2c2SSteve Yin }
837ca62e2c2SSteve Yin 
GetFieldIndex(sal_Int32 nPos)838ca62e2c2SSteve Yin sal_Int32 SwAccessiblePortionData::GetFieldIndex(sal_Int32 nPos)
839ca62e2c2SSteve Yin {
840ca62e2c2SSteve Yin     sal_Int32 nIndex = -1;
841ca62e2c2SSteve Yin     if( aFieldPosition.size() >= 2 )
842ca62e2c2SSteve Yin     {
843588ea58aSPavel Janík         for( sal_uInt32 i = 0; i < aFieldPosition.size() - 1; i += 2 )
844ca62e2c2SSteve Yin         {
845ca62e2c2SSteve Yin             if( nPos <= aFieldPosition[ i + 1 ]  &&  nPos >= aFieldPosition[ i ] )
846ca62e2c2SSteve Yin             {
847ca62e2c2SSteve Yin                 nIndex = i/2;
848ca62e2c2SSteve Yin                 break;
849ca62e2c2SSteve Yin             }
850ca62e2c2SSteve Yin         }
851ca62e2c2SSteve Yin     }
852ca62e2c2SSteve Yin     return nIndex;
853ca62e2c2SSteve Yin }
GetFirstValidCorePosition() const854cdf0e10cSrcweir sal_uInt16 SwAccessiblePortionData::GetFirstValidCorePosition() const
855cdf0e10cSrcweir {
856cdf0e10cSrcweir     return static_cast<sal_uInt16>( aModelPositions[0] );
857cdf0e10cSrcweir }
858cdf0e10cSrcweir 
GetLastValidCorePosition() const859cdf0e10cSrcweir sal_uInt16 SwAccessiblePortionData::GetLastValidCorePosition() const
860cdf0e10cSrcweir {
861cdf0e10cSrcweir     return static_cast<sal_uInt16>( aModelPositions[ aModelPositions.size()-1 ] );
862cdf0e10cSrcweir }
863