Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <txtfrm.hxx>
31 : : #include <flyfrm.hxx>
32 : : #include <ndtxt.hxx>
33 : : #include <pam.hxx>
34 : : #include <unotextrange.hxx>
35 : : #include <unocrsrhelper.hxx>
36 : : #include <crstate.hxx>
37 : : #include <accmap.hxx>
38 : : #include <fesh.hxx>
39 : : #include <viewopt.hxx>
40 : : #include <osl/mutex.hxx>
41 : : #include <vcl/svapp.hxx>
42 : : #include <vcl/window.hxx>
43 : : #include <rtl/ustrbuf.hxx>
44 : : #include <com/sun/star/accessibility/AccessibleRole.hpp>
45 : : #include <com/sun/star/accessibility/AccessibleStateType.hpp>
46 : : #include <com/sun/star/accessibility/AccessibleTextType.hpp>
47 : : #include <com/sun/star/accessibility/AccessibleEventId.hpp>
48 : : #include <unotools/accessiblestatesethelper.hxx>
49 : : #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
50 : : #include <com/sun/star/i18n/WordType.hpp>
51 : : #include <com/sun/star/i18n/XBreakIterator.hpp>
52 : : #include <com/sun/star/beans/UnknownPropertyException.hpp>
53 : : #include <breakit.hxx>
54 : : #include <accpara.hxx>
55 : : #include <access.hrc>
56 : : #include <accportions.hxx>
57 : : #include <sfx2/viewsh.hxx> // for ExecuteAtViewShell(...)
58 : : #include <sfx2/viewfrm.hxx> // for ExecuteAtViewShell(...)
59 : : #include <sfx2/dispatch.hxx> // for ExecuteAtViewShell(...)
60 : : #include <unotools/charclass.hxx> // for GetWordBoundary
61 : : // for get/setCharacterAttribute(...)
62 : : #include <unocrsr.hxx>
63 : : #include <unoport.hxx>
64 : : #include <doc.hxx>
65 : : #include <crsskip.hxx>
66 : : #include <txtatr.hxx>
67 : : #include <acchyperlink.hxx>
68 : : #include <acchypertextdata.hxx>
69 : : #include <unotools/accessiblerelationsethelper.hxx>
70 : : #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
71 : : #include <comphelper/accessibletexthelper.hxx>
72 : : #include <unomap.hxx>
73 : : #include <unoprnms.hxx>
74 : : #include <com/sun/star/text/WritingMode2.hpp>
75 : : #include <editeng/brshitem.hxx>
76 : : #include <viewimp.hxx>
77 : : #include <boost/scoped_ptr.hpp>
78 : : #include <textmarkuphelper.hxx>
79 : : // #i10825#
80 : : #include <parachangetrackinginfo.hxx>
81 : : #include <com/sun/star/text/TextMarkupType.hpp>
82 : : #include <comphelper/stlunosequence.hxx> // #i92233#
83 : : #include <comphelper/servicehelper.hxx>
84 : :
85 : : #include <algorithm>
86 : :
87 : : using namespace ::com::sun::star;
88 : : using namespace ::com::sun::star::accessibility;
89 : :
90 : : using beans::PropertyValue;
91 : : using beans::XMultiPropertySet;
92 : : using beans::UnknownPropertyException;
93 : : using beans::PropertyState_DIRECT_VALUE;
94 : :
95 : : using std::max;
96 : : using std::min;
97 : : using std::sort;
98 : :
99 : : namespace com { namespace sun { namespace star {
100 : : namespace text {
101 : : class XText;
102 : : }
103 : : } } }
104 : :
105 : :
106 : : const sal_Char sServiceName[] = "com.sun.star.text.AccessibleParagraphView";
107 : : const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleParagraphView";
108 : : const xub_StrLen MAX_DESC_TEXT_LEN = 40;
109 : 218 : const SwTxtNode* SwAccessibleParagraph::GetTxtNode() const
110 : : {
111 : 218 : const SwFrm* pFrm = GetFrm();
112 : : OSL_ENSURE( pFrm->IsTxtFrm(), "The text frame has mutated!" );
113 : :
114 : 218 : const SwTxtNode* pNode = static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode();
115 : : OSL_ENSURE( pNode != NULL, "A text frame without a text node." );
116 : :
117 : 218 : return pNode;
118 : : }
119 : :
120 : 68 : ::rtl::OUString SwAccessibleParagraph::GetString()
121 : : {
122 : 68 : return GetPortionData().GetAccessibleString();
123 : : }
124 : :
125 : 26 : ::rtl::OUString SwAccessibleParagraph::GetDescription()
126 : : {
127 : 26 : return ::rtl::OUString(); // provide empty description for paragraphs
128 : : }
129 : :
130 : 137 : sal_Int32 SwAccessibleParagraph::GetCaretPos()
131 : : {
132 : 137 : sal_Int32 nRet = -1;
133 : :
134 : : // get the selection's point, and test whether it's in our node
135 : : // #i27301# - consider adjusted method signature
136 : 137 : SwPaM* pCaret = GetCursor( false ); // caret is first PaM in PaM-ring
137 : :
138 [ + + ]: 137 : if( pCaret != NULL )
139 : : {
140 : 135 : const SwTxtNode* pNode = GetTxtNode();
141 : :
142 : : // check whether the point points into 'our' node
143 : 135 : SwPosition* pPoint = pCaret->GetPoint();
144 [ + + ]: 135 : if( pNode->GetIndex() == pPoint->nNode.GetIndex() )
145 : : {
146 : : // same node? Then check whether it's also within 'our' part
147 : : // of the paragraph
148 : 119 : sal_uInt16 nIndex = pPoint->nContent.GetIndex();
149 [ + - ]: 119 : if( GetPortionData().IsValidCorePosition( nIndex ) )
150 : : {
151 : : // Yes, it's us!
152 : : // consider that cursor/caret is in front of the list label
153 [ - + ]: 119 : if ( pCaret->IsInFrontOfLabel() )
154 : : {
155 : 0 : nRet = 0;
156 : : }
157 : : else
158 : : {
159 : 119 : nRet = GetPortionData().GetAccessiblePosition( nIndex );
160 : : }
161 : :
162 : : OSL_ENSURE( nRet >= 0, "invalid cursor?" );
163 : : OSL_ENSURE( nRet <= GetPortionData().GetAccessibleString().
164 : : getLength(), "invalid cursor?" );
165 : : }
166 : : // else: in this paragraph, but in different frame
167 : : }
168 : : // else: not in this paragraph
169 : : }
170 : : // else: no cursor -> no caret
171 : :
172 : 137 : return nRet;
173 : : }
174 : :
175 : 0 : sal_Bool SwAccessibleParagraph::GetSelection(
176 : : sal_Int32& nStart, sal_Int32& nEnd)
177 : : {
178 : 0 : sal_Bool bRet = sal_False;
179 : 0 : nStart = -1;
180 : 0 : nEnd = -1;
181 : :
182 : : // get the selection, and test whether it affects our text node
183 : 0 : SwPaM* pCrsr = GetCursor( true ); // #i27301# - consider adjusted method signature
184 [ # # ]: 0 : if( pCrsr != NULL )
185 : : {
186 : : // get SwPosition for my node
187 : 0 : const SwTxtNode* pNode = GetTxtNode();
188 : 0 : sal_uLong nHere = pNode->GetIndex();
189 : :
190 : : // iterate over ring
191 : 0 : SwPaM* pRingStart = pCrsr;
192 [ # # ][ # # ]: 0 : do
[ # # ]
193 : : {
194 : : // ignore, if no mark
195 [ # # ]: 0 : if( pCrsr->HasMark() )
196 : : {
197 : : // check whether nHere is 'inside' pCrsr
198 : 0 : SwPosition* pStart = pCrsr->Start();
199 : 0 : sal_uLong nStartIndex = pStart->nNode.GetIndex();
200 : 0 : SwPosition* pEnd = pCrsr->End();
201 : 0 : sal_uLong nEndIndex = pEnd->nNode.GetIndex();
202 [ # # ][ # # ]: 0 : if( ( nHere >= nStartIndex ) &&
203 : : ( nHere <= nEndIndex ) )
204 : : {
205 : : // translate start and end positions
206 : :
207 : : // start position
208 : 0 : sal_Int32 nLocalStart = -1;
209 [ # # ]: 0 : if( nHere > nStartIndex )
210 : : {
211 : : // selection starts in previous node:
212 : : // then our local selection starts with the paragraph
213 : 0 : nLocalStart = 0;
214 : : }
215 : : else
216 : : {
217 : : OSL_ENSURE( nHere == nStartIndex,
218 : : "miscalculated index" );
219 : :
220 : : // selection starts in this node:
221 : : // then check whether it's before or inside our part of
222 : : // the paragraph, and if so, get the proper position
223 : 0 : sal_uInt16 nCoreStart = pStart->nContent.GetIndex();
224 [ # # ]: 0 : if( nCoreStart <
225 : 0 : GetPortionData().GetFirstValidCorePosition() )
226 : : {
227 : 0 : nLocalStart = 0;
228 : : }
229 [ # # ]: 0 : else if( nCoreStart <=
230 : 0 : GetPortionData().GetLastValidCorePosition() )
231 : : {
232 : : OSL_ENSURE(
233 : : GetPortionData().IsValidCorePosition(
234 : : nCoreStart ),
235 : : "problem determining valid core position" );
236 : :
237 : : nLocalStart =
238 : 0 : GetPortionData().GetAccessiblePosition(
239 : 0 : nCoreStart );
240 : : }
241 : : }
242 : :
243 : : // end position
244 : 0 : sal_Int32 nLocalEnd = -1;
245 [ # # ]: 0 : if( nHere < nEndIndex )
246 : : {
247 : : // selection ends in following node:
248 : : // then our local selection extends to the end
249 : 0 : nLocalEnd = GetPortionData().GetAccessibleString().
250 : 0 : getLength();
251 : : }
252 : : else
253 : : {
254 : : OSL_ENSURE( nHere == nEndIndex,
255 : : "miscalculated index" );
256 : :
257 : : // selection ends in this node: then select everything
258 : : // before our part of the node
259 : 0 : sal_uInt16 nCoreEnd = pEnd->nContent.GetIndex();
260 [ # # ]: 0 : if( nCoreEnd >
261 : 0 : GetPortionData().GetLastValidCorePosition() )
262 : : {
263 : : // selection extends beyond out part of this para
264 : 0 : nLocalEnd = GetPortionData().GetAccessibleString().
265 : 0 : getLength();
266 : : }
267 [ # # ]: 0 : else if( nCoreEnd >=
268 : 0 : GetPortionData().GetFirstValidCorePosition() )
269 : : {
270 : : // selection is inside our part of this para
271 : : OSL_ENSURE(
272 : : GetPortionData().IsValidCorePosition(
273 : : nCoreEnd ),
274 : : "problem determining valid core position" );
275 : :
276 : 0 : nLocalEnd = GetPortionData().GetAccessiblePosition(
277 : 0 : nCoreEnd );
278 : : }
279 : : }
280 : :
281 [ # # ][ # # ]: 0 : if( ( nLocalStart != -1 ) && ( nLocalEnd != -1 ) )
282 : : {
283 : 0 : nStart = nLocalStart;
284 : 0 : nEnd = nLocalEnd;
285 : 0 : bRet = sal_True;
286 : : }
287 : : }
288 : : // else: this PaM doesn't point to this paragraph
289 : : }
290 : : // else: this PaM is collapsed and doesn't select anything
291 : :
292 : : // next PaM in ring
293 : 0 : pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
294 : : }
295 : : while( !bRet && (pCrsr != pRingStart) );
296 : : }
297 : : // else: nocursor -> no selection
298 : :
299 : 0 : return bRet;
300 : : }
301 : :
302 : : // #i27301# - new parameter <_bForSelection>
303 : 161 : SwPaM* SwAccessibleParagraph::GetCursor( const bool _bForSelection )
304 : : {
305 : : // get the cursor shell; if we don't have any, we don't have a
306 : : // cursor/selection either
307 : 161 : SwPaM* pCrsr = NULL;
308 : 161 : SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell();
309 : : // #i27301# - if cursor is retrieved for selection, the cursors for
310 : : // a table selection has to be returned.
311 [ + - + + ]: 322 : if ( pCrsrShell != NULL &&
[ + + ][ + - ]
312 : 161 : ( _bForSelection || !pCrsrShell->IsTableMode() ) )
313 : : {
314 : 157 : SwFEShell *pFESh = pCrsrShell->ISA( SwFEShell )
315 [ + - ]: 157 : ? static_cast< SwFEShell * >( pCrsrShell ) : 0;
316 [ + - + - ]: 471 : if( !pFESh ||
[ + - ]
317 [ + - ]: 314 : !(pFESh->IsFrmSelected() || pFESh->IsObjSelected() > 0) )
318 : : {
319 : : // get the selection, and test whether it affects our text node
320 : 157 : pCrsr = pCrsrShell->GetCrsr( sal_False /* ??? */ );
321 : : }
322 : : }
323 : :
324 : 161 : return pCrsr;
325 : : }
326 : :
327 : 61 : sal_Bool SwAccessibleParagraph::IsHeading() const
328 : : {
329 : 61 : const SwTxtNode *pTxtNd = GetTxtNode();
330 : 61 : return pTxtNd->IsOutline();
331 : : }
332 : :
333 : 22 : void SwAccessibleParagraph::GetStates(
334 : : ::utl::AccessibleStateSetHelper& rStateSet )
335 : : {
336 : 22 : SwAccessibleContext::GetStates( rStateSet );
337 : :
338 : : // MULTILINE
339 : 22 : rStateSet.AddState( AccessibleStateType::MULTI_LINE );
340 : :
341 : : // MULTISELECTABLE
342 : 22 : SwCrsrShell *pCrsrSh = GetCrsrShell();
343 [ + - ]: 22 : if( pCrsrSh )
344 : 22 : rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
345 : :
346 : : // FOCUSABLE
347 [ + - ]: 22 : if( pCrsrSh )
348 : 22 : rStateSet.AddState( AccessibleStateType::FOCUSABLE );
349 : :
350 : : // FOCUSED (simulates node index of cursor)
351 : 22 : SwPaM* pCaret = GetCursor( false ); // #i27301# - consider adjusted method signature
352 : 22 : const SwTxtNode* pTxtNd = GetTxtNode();
353 [ + - + + ]: 42 : if( pCaret != 0 && pTxtNd != 0 &&
[ + - ][ + + ]
[ + + ]
354 : 20 : pTxtNd->GetIndex() == pCaret->GetPoint()->nNode.GetIndex() &&
355 : : nOldCaretPos != -1)
356 : : {
357 [ + - ]: 18 : Window *pWin = GetWindow();
358 [ + - ][ + - ]: 18 : if( pWin && pWin->HasFocus() )
[ + - ][ + - ]
359 [ + - ]: 18 : rStateSet.AddState( AccessibleStateType::FOCUSED );
360 : 18 : ::rtl::Reference < SwAccessibleContext > xThis( this );
361 [ + - ]: 18 : GetMap()->SetCursorContext( xThis );
362 : : }
363 : 22 : }
364 : :
365 : 28 : void SwAccessibleParagraph::_InvalidateContent( sal_Bool bVisibleDataFired )
366 : : {
367 [ + - ]: 28 : ::rtl::OUString sOldText( GetString() );
368 : :
369 [ + - ]: 28 : ClearPortionData();
370 : :
371 [ + - ]: 28 : const ::rtl::OUString& rText = GetString();
372 : :
373 [ - + ]: 28 : if( rText != sOldText )
374 : : {
375 : : // The text is changed
376 [ # # ]: 0 : AccessibleEventObject aEvent;
377 : 0 : aEvent.EventId = AccessibleEventId::TEXT_CHANGED;
378 : :
379 : : // determine exact changes between sOldText and rText
380 : : comphelper::OCommonAccessibleText::implInitTextChangedEvent(
381 : : sOldText, rText,
382 [ # # ]: 0 : aEvent.OldValue, aEvent.NewValue );
383 : :
384 [ # # ][ # # ]: 0 : FireAccessibleEvent( aEvent );
385 : : }
386 [ - + ]: 28 : else if( !bVisibleDataFired )
387 : : {
388 [ # # ]: 0 : FireVisibleDataEvent();
389 : : }
390 : :
391 [ + - ]: 28 : sal_Bool bNewIsHeading = IsHeading();
392 : : sal_Bool bOldIsHeading;
393 : : {
394 [ + - ]: 28 : osl::MutexGuard aGuard( aMutex );
395 : 28 : bOldIsHeading = bIsHeading;
396 [ - + ]: 28 : if( bIsHeading != bNewIsHeading )
397 [ + - ]: 28 : bIsHeading = bNewIsHeading;
398 : : }
399 : :
400 : :
401 [ + - ][ - + ]: 28 : if( bNewIsHeading != bOldIsHeading || rText != sOldText )
[ - + ]
402 : : {
403 : 0 : ::rtl::OUString sNewDesc( GetDescription() );
404 : 0 : ::rtl::OUString sOldDesc;
405 : : {
406 [ # # ]: 0 : osl::MutexGuard aGuard( aMutex );
407 : 0 : sOldDesc = sDesc;
408 [ # # ]: 0 : if( sDesc != sNewDesc )
409 [ # # ]: 0 : sDesc = sNewDesc;
410 : : }
411 : :
412 [ # # ]: 0 : if( sNewDesc != sOldDesc )
413 : : {
414 : : // The text is changed
415 [ # # ]: 0 : AccessibleEventObject aEvent;
416 : 0 : aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
417 [ # # ]: 0 : aEvent.OldValue <<= sOldDesc;
418 [ # # ]: 0 : aEvent.NewValue <<= sNewDesc;
419 : :
420 [ # # ][ # # ]: 0 : FireAccessibleEvent( aEvent );
421 : 0 : }
422 : 28 : }
423 : 28 : }
424 : :
425 : 104 : void SwAccessibleParagraph::_InvalidateCursorPos()
426 : : {
427 : : // The text is changed
428 [ + - ]: 104 : sal_Int32 nNew = GetCaretPos();
429 : : sal_Int32 nOld;
430 : : {
431 [ + - ]: 104 : osl::MutexGuard aGuard( aMutex );
432 : 104 : nOld = nOldCaretPos;
433 [ + - ]: 104 : nOldCaretPos = nNew;
434 : : }
435 [ + + ]: 104 : if( -1 != nNew )
436 : : {
437 : : // remember that object as the one that has the caret. This is
438 : : // neccessary to notify that object if the cursor leaves it.
439 : 102 : ::rtl::Reference < SwAccessibleContext > xThis( this );
440 [ + - ]: 102 : GetMap()->SetCursorContext( xThis );
441 : : }
442 : :
443 [ + - ]: 104 : Window *pWin = GetWindow();
444 [ + + ]: 104 : if( nOld != nNew )
445 : : {
446 : : // The cursor's node position is sumilated by the focus!
447 [ + - ][ + - ]: 6 : if( pWin && pWin->HasFocus() && -1 == nOld )
[ + - ][ + + ]
[ + + ]
448 [ + - ]: 4 : FireStateChangedEvent( AccessibleStateType::FOCUSED, sal_True );
449 : :
450 : :
451 [ + - ]: 6 : AccessibleEventObject aEvent;
452 : 6 : aEvent.EventId = AccessibleEventId::CARET_CHANGED;
453 [ + - ]: 6 : aEvent.OldValue <<= nOld;
454 [ + - ]: 6 : aEvent.NewValue <<= nNew;
455 : :
456 [ + - ]: 6 : FireAccessibleEvent( aEvent );
457 : :
458 [ + - ][ + - ]: 6 : if( pWin && pWin->HasFocus() && -1 == nNew )
[ + - ][ + + ]
[ + + ]
459 [ + - ][ + - ]: 6 : FireStateChangedEvent( AccessibleStateType::FOCUSED, sal_False );
460 : : }
461 : 104 : }
462 : :
463 : 18 : void SwAccessibleParagraph::_InvalidateFocus()
464 : : {
465 : 18 : Window *pWin = GetWindow();
466 [ + - ]: 18 : if( pWin )
467 : : {
468 : : sal_Int32 nPos;
469 : : {
470 [ + - ]: 18 : osl::MutexGuard aGuard( aMutex );
471 [ + - ]: 18 : nPos = nOldCaretPos;
472 : : }
473 : : OSL_ENSURE( nPos != -1, "focus object should be selected" );
474 : :
475 : : FireStateChangedEvent( AccessibleStateType::FOCUSED,
476 [ - + ][ # # ]: 18 : pWin->HasFocus() && nPos != -1 );
477 : : }
478 : 18 : }
479 : :
480 : 33 : SwAccessibleParagraph::SwAccessibleParagraph(
481 : : SwAccessibleMap& rInitMap,
482 : : const SwTxtFrm& rTxtFrm )
483 : 33 : : SwClient( const_cast<SwTxtNode*>(rTxtFrm.GetTxtNode()) ) // #i108125#
484 : : , SwAccessibleContext( &rInitMap, AccessibleRole::PARAGRAPH, &rTxtFrm )
485 : : , sDesc()
486 : : , pPortionData( NULL )
487 : : , pHyperTextData( NULL )
488 : : , nOldCaretPos( -1 )
489 : : , bIsHeading( sal_False )
490 : : , aSelectionHelper( *this )
491 [ + - ][ + - ]: 33 : , mpParaChangeTrackInfo( new SwParaChangeTrackingInfo( rTxtFrm ) ) // #i108125#
[ + - ][ + - ]
492 : : {
493 [ + - ]: 33 : SolarMutexGuard aGuard;
494 : :
495 [ + - ]: 33 : bIsHeading = IsHeading();
496 : 33 : SetName( ::rtl::OUString() ); // set an empty accessibility name for paragraphs
497 : :
498 : : // If this object has the focus, then it is remembered by the map itself.
499 [ + - ][ + - ]: 33 : nOldCaretPos = GetCaretPos();
500 : 33 : }
501 : :
502 [ + - ][ + - ]: 33 : SwAccessibleParagraph::~SwAccessibleParagraph()
503 : : {
504 [ + - ]: 33 : SolarMutexGuard aGuard;
505 : :
506 [ + + ][ + - ]: 33 : delete pPortionData;
507 [ - + ][ # # ]: 33 : delete pHyperTextData;
508 [ + - ][ + - ]: 33 : delete mpParaChangeTrackInfo; // #i108125#
[ + - ]
509 [ - + ]: 66 : }
510 : :
511 : 34 : sal_Bool SwAccessibleParagraph::HasCursor()
512 : : {
513 [ + - ]: 34 : osl::MutexGuard aGuard( aMutex );
514 [ + - ]: 34 : return nOldCaretPos != -1;
515 : : }
516 : :
517 : 55 : void SwAccessibleParagraph::UpdatePortionData()
518 : : throw( uno::RuntimeException )
519 : : {
520 : : // obtain the text frame
521 : : OSL_ENSURE( GetFrm() != NULL, "The text frame has vanished!" );
522 : : OSL_ENSURE( GetFrm()->IsTxtFrm(), "The text frame has mutated!" );
523 : 55 : const SwTxtFrm* pFrm = static_cast<const SwTxtFrm*>( GetFrm() );
524 : :
525 : : // build new portion data
526 [ - + ]: 55 : delete pPortionData;
527 : : pPortionData = new SwAccessiblePortionData(
528 [ + - ]: 55 : pFrm->GetTxtNode(), GetMap()->GetShell()->GetViewOptions() );
529 : 55 : pFrm->VisitPortions( *pPortionData );
530 : :
531 : : OSL_ENSURE( pPortionData != NULL, "UpdatePortionData() failed" );
532 : 55 : }
533 : :
534 : 28 : void SwAccessibleParagraph::ClearPortionData()
535 : : {
536 [ + - ]: 28 : delete pPortionData;
537 : 28 : pPortionData = NULL;
538 : :
539 [ - + ]: 28 : delete pHyperTextData;
540 : 28 : pHyperTextData = 0;
541 : 28 : }
542 : :
543 : :
544 : 0 : void SwAccessibleParagraph::ExecuteAtViewShell( sal_uInt16 nSlot )
545 : : {
546 : : OSL_ENSURE( GetMap() != NULL, "no map?" );
547 : 0 : ViewShell* pViewShell = GetMap()->GetShell();
548 : :
549 : : OSL_ENSURE( pViewShell != NULL, "View shell exptected!" );
550 : 0 : SfxViewShell* pSfxShell = pViewShell->GetSfxViewShell();
551 : :
552 : : OSL_ENSURE( pSfxShell != NULL, "SfxViewShell shell exptected!" );
553 [ # # ]: 0 : if( !pSfxShell )
554 : 0 : return;
555 : :
556 : 0 : SfxViewFrame *pFrame = pSfxShell->GetViewFrame();
557 : : OSL_ENSURE( pFrame != NULL, "View frame exptected!" );
558 [ # # ]: 0 : if( !pFrame )
559 : 0 : return;
560 : :
561 : 0 : SfxDispatcher *pDispatcher = pFrame->GetDispatcher();
562 : : OSL_ENSURE( pDispatcher != NULL, "Dispatcher exptected!" );
563 [ # # ]: 0 : if( !pDispatcher )
564 : 0 : return;
565 : :
566 : 0 : pDispatcher->Execute( nSlot );
567 : : }
568 : :
569 : 0 : SwXTextPortion* SwAccessibleParagraph::CreateUnoPortion(
570 : : sal_Int32 nStartIndex,
571 : : sal_Int32 nEndIndex )
572 : : {
573 : : OSL_ENSURE( (IsValidChar(nStartIndex, GetString().getLength()) &&
574 : : (nEndIndex == -1)) ||
575 : : IsValidRange(nStartIndex, nEndIndex, GetString().getLength()),
576 : : "please check parameters before calling this method" );
577 : :
578 [ # # ][ # # ]: 0 : sal_uInt16 nStart = GetPortionData().GetModelPosition( nStartIndex );
579 : : sal_uInt16 nEnd = (nEndIndex == -1) ? (nStart + 1) :
580 [ # # ][ # # ]: 0 : GetPortionData().GetModelPosition( nEndIndex );
[ # # ]
581 : :
582 : : // create UNO cursor
583 : 0 : SwTxtNode* pTxtNode = const_cast<SwTxtNode*>( GetTxtNode() );
584 [ # # ][ # # ]: 0 : SwIndex aIndex( pTxtNode, nStart );
585 [ # # ][ # # ]: 0 : SwPosition aStartPos( *pTxtNode, aIndex );
[ # # ]
586 [ # # ]: 0 : SwUnoCrsr* pUnoCursor = pTxtNode->GetDoc()->CreateUnoCrsr( aStartPos );
587 [ # # ]: 0 : pUnoCursor->SetMark();
588 [ # # ]: 0 : pUnoCursor->GetMark()->nContent = nEnd;
589 : :
590 : : // create a (dummy) text portion to be returned
591 : 0 : uno::Reference<text::XText> aEmpty;
592 : : SwXTextPortion* pPortion =
593 [ # # ]: 0 : new SwXTextPortion ( pUnoCursor, aEmpty, PORTION_TEXT);
594 [ # # ][ # # ]: 0 : delete pUnoCursor;
595 : :
596 [ # # ][ # # ]: 0 : return pPortion;
597 : : }
598 : :
599 : :
600 : : //
601 : : // range checking for parameter
602 : : //
603 : :
604 : 0 : sal_Bool SwAccessibleParagraph::IsValidChar(
605 : : sal_Int32 nPos, sal_Int32 nLength)
606 : : {
607 [ # # ][ # # ]: 0 : return (nPos >= 0) && (nPos < nLength);
608 : : }
609 : :
610 : 0 : sal_Bool SwAccessibleParagraph::IsValidPosition(
611 : : sal_Int32 nPos, sal_Int32 nLength)
612 : : {
613 [ # # ][ # # ]: 0 : return (nPos >= 0) && (nPos <= nLength);
614 : : }
615 : :
616 : 0 : sal_Bool SwAccessibleParagraph::IsValidRange(
617 : : sal_Int32 nBegin, sal_Int32 nEnd, sal_Int32 nLength)
618 : : {
619 [ # # ][ # # ]: 0 : return IsValidPosition(nBegin, nLength) && IsValidPosition(nEnd, nLength);
620 : : }
621 : :
622 : :
623 : : //
624 : : // text boundaries
625 : : //
626 : :
627 : :
628 : 0 : sal_Bool SwAccessibleParagraph::GetCharBoundary(
629 : : i18n::Boundary& rBound,
630 : : const ::rtl::OUString&,
631 : : sal_Int32 nPos )
632 : : {
633 : 0 : rBound.startPos = nPos;
634 : 0 : rBound.endPos = nPos+1;
635 : 0 : return sal_True;
636 : : }
637 : :
638 : 0 : sal_Bool SwAccessibleParagraph::GetWordBoundary(
639 : : i18n::Boundary& rBound,
640 : : const ::rtl::OUString& rText,
641 : : sal_Int32 nPos )
642 : : {
643 : 0 : sal_Bool bRet = sal_False;
644 : :
645 : : // now ask the Break-Iterator for the word
646 : : OSL_ENSURE( pBreakIt != NULL, "We always need a break." );
647 : : OSL_ENSURE( pBreakIt->GetBreakIter().is(), "No break-iterator." );
648 [ # # ]: 0 : if( pBreakIt->GetBreakIter().is() )
649 : : {
650 : : // get locale for this position
651 [ # # ][ # # ]: 0 : sal_uInt16 nModelPos = GetPortionData().GetModelPosition( nPos );
652 : : lang::Locale aLocale = pBreakIt->GetLocale(
653 [ # # ][ # # ]: 0 : GetTxtNode()->GetLang( nModelPos ) );
654 : :
655 : : // which type of word are we interested in?
656 : : // (DICTIONARY_WORD includes punctuation, ANY_WORD doesn't.)
657 : 0 : const sal_uInt16 nWordType = i18n::WordType::ANY_WORD;
658 : :
659 : : // get word boundary, as the Break-Iterator sees fit.
660 [ # # ][ # # ]: 0 : rBound = pBreakIt->GetBreakIter()->getWordBoundary(
661 [ # # ]: 0 : rText, nPos, aLocale, nWordType, sal_True );
662 : :
663 : : // It's a word if the first character is an alpha-numeric character.
664 [ # # ]: 0 : bRet = GetAppCharClass().isLetterNumeric(
665 [ # # ][ # # ]: 0 : rtl::OUString(rText[rBound.startPos]) );
[ # # ]
666 : : }
667 : : else
668 : : {
669 : : // no break Iterator -> no word
670 : 0 : rBound.startPos = nPos;
671 : 0 : rBound.endPos = nPos;
672 : : }
673 : :
674 : 0 : return bRet;
675 : : }
676 : :
677 : 0 : sal_Bool SwAccessibleParagraph::GetSentenceBoundary(
678 : : i18n::Boundary& rBound,
679 : : const ::rtl::OUString&,
680 : : sal_Int32 nPos )
681 : : {
682 : 0 : GetPortionData().GetSentenceBoundary( rBound, nPos );
683 : 0 : return sal_True;
684 : : }
685 : :
686 : 0 : sal_Bool SwAccessibleParagraph::GetLineBoundary(
687 : : i18n::Boundary& rBound,
688 : : const ::rtl::OUString& rText,
689 : : sal_Int32 nPos )
690 : : {
691 [ # # ]: 0 : if( rText.getLength() == nPos )
692 : 0 : GetPortionData().GetLastLineBoundary( rBound );
693 : : else
694 : 0 : GetPortionData().GetLineBoundary( rBound, nPos );
695 : 0 : return sal_True;
696 : : }
697 : :
698 : 0 : sal_Bool SwAccessibleParagraph::GetParagraphBoundary(
699 : : i18n::Boundary& rBound,
700 : : const ::rtl::OUString& rText,
701 : : sal_Int32 )
702 : : {
703 : 0 : rBound.startPos = 0;
704 : 0 : rBound.endPos = rText.getLength();
705 : 0 : return sal_True;
706 : : }
707 : :
708 : 0 : sal_Bool SwAccessibleParagraph::GetAttributeBoundary(
709 : : i18n::Boundary& rBound,
710 : : const ::rtl::OUString&,
711 : : sal_Int32 nPos )
712 : : {
713 : 0 : GetPortionData().GetAttributeBoundary( rBound, nPos );
714 : 0 : return sal_True;
715 : : }
716 : :
717 : 0 : sal_Bool SwAccessibleParagraph::GetGlyphBoundary(
718 : : i18n::Boundary& rBound,
719 : : const ::rtl::OUString& rText,
720 : : sal_Int32 nPos )
721 : : {
722 : 0 : sal_Bool bRet = sal_False;
723 : :
724 : : // ask the Break-Iterator for the glyph by moving one cell
725 : : // forward, and then one cell back
726 : : OSL_ENSURE( pBreakIt != NULL, "We always need a break." );
727 : : OSL_ENSURE( pBreakIt->GetBreakIter().is(), "No break-iterator." );
728 [ # # ]: 0 : if( pBreakIt->GetBreakIter().is() )
729 : : {
730 : : // get locale for this position
731 [ # # ][ # # ]: 0 : sal_uInt16 nModelPos = GetPortionData().GetModelPosition( nPos );
732 : : lang::Locale aLocale = pBreakIt->GetLocale(
733 [ # # ][ # # ]: 0 : GetTxtNode()->GetLang( nModelPos ) );
734 : :
735 : : // get word boundary, as the Break-Iterator sees fit.
736 : 0 : const sal_uInt16 nIterMode = i18n::CharacterIteratorMode::SKIPCELL;
737 : 0 : sal_Int32 nDone = 0;
738 [ # # ][ # # ]: 0 : rBound.endPos = pBreakIt->GetBreakIter()->nextCharacters(
739 [ # # ]: 0 : rText, nPos, aLocale, nIterMode, 1, nDone );
740 [ # # ][ # # ]: 0 : rBound.startPos = pBreakIt->GetBreakIter()->previousCharacters(
741 [ # # ]: 0 : rText, rBound.endPos, aLocale, nIterMode, 1, nDone );
742 : :
743 : : OSL_ENSURE( rBound.startPos <= nPos, "start pos too high" );
744 : 0 : OSL_ENSURE( rBound.endPos >= nPos, "end pos too low" );
745 : : }
746 : : else
747 : : {
748 : : // no break Iterator -> no glyph
749 : 0 : rBound.startPos = nPos;
750 : 0 : rBound.endPos = nPos;
751 : : }
752 : :
753 : 0 : return bRet;
754 : : }
755 : :
756 : :
757 : 0 : sal_Bool SwAccessibleParagraph::GetTextBoundary(
758 : : i18n::Boundary& rBound,
759 : : const ::rtl::OUString& rText,
760 : : sal_Int32 nPos,
761 : : sal_Int16 nTextType )
762 : : throw (
763 : : lang::IndexOutOfBoundsException,
764 : : lang::IllegalArgumentException,
765 : : uno::RuntimeException)
766 : : {
767 : : // error checking
768 [ # # ]: 0 : if( !( AccessibleTextType::LINE == nTextType
769 : 0 : ? IsValidPosition( nPos, rText.getLength() )
770 [ # # ]: 0 : : IsValidChar( nPos, rText.getLength() ) ) )
771 [ # # ]: 0 : throw lang::IndexOutOfBoundsException();
772 : :
773 : : sal_Bool bRet;
774 : :
775 [ # # # # : 0 : switch( nTextType )
# # # # ]
776 : : {
777 : : case AccessibleTextType::WORD:
778 : 0 : bRet = GetWordBoundary( rBound, rText, nPos );
779 : 0 : break;
780 : :
781 : : case AccessibleTextType::SENTENCE:
782 : 0 : bRet = GetSentenceBoundary( rBound, rText, nPos );
783 : 0 : break;
784 : :
785 : : case AccessibleTextType::PARAGRAPH:
786 : 0 : bRet = GetParagraphBoundary( rBound, rText, nPos );
787 : 0 : break;
788 : :
789 : : case AccessibleTextType::CHARACTER:
790 : 0 : bRet = GetCharBoundary( rBound, rText, nPos );
791 : 0 : break;
792 : :
793 : : case AccessibleTextType::LINE:
794 : 0 : bRet = GetLineBoundary( rBound, rText, nPos );
795 : 0 : break;
796 : :
797 : : case AccessibleTextType::ATTRIBUTE_RUN:
798 : 0 : bRet = GetAttributeBoundary( rBound, rText, nPos );
799 : 0 : break;
800 : :
801 : : case AccessibleTextType::GLYPH:
802 : 0 : bRet = GetGlyphBoundary( rBound, rText, nPos );
803 : 0 : break;
804 : :
805 : : default:
806 [ # # ]: 0 : throw lang::IllegalArgumentException( );
807 : : }
808 : :
809 : 0 : return bRet;
810 : : }
811 : :
812 : 26 : ::rtl::OUString SAL_CALL SwAccessibleParagraph::getAccessibleDescription (void)
813 : : throw (uno::RuntimeException)
814 : : {
815 [ + - ]: 26 : SolarMutexGuard aGuard;
816 : :
817 [ + - ][ - + ]: 26 : CHECK_FOR_DEFUNC( XAccessibleContext );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ]
818 : :
819 [ + - ]: 26 : osl::MutexGuard aGuard2( aMutex );
820 [ + - ]: 26 : if( sDesc.isEmpty() )
821 : 26 : sDesc = GetDescription();
822 : :
823 [ + - ][ + - ]: 26 : return sDesc;
824 : : }
825 : :
826 : 2 : lang::Locale SAL_CALL SwAccessibleParagraph::getLocale (void)
827 : : throw (IllegalAccessibleComponentStateException, uno::RuntimeException)
828 : : {
829 [ + - ]: 2 : SolarMutexGuard aGuard;
830 : :
831 [ + - ][ + - ]: 2 : SwTxtFrm *pTxtFrm = PTR_CAST( SwTxtFrm, GetFrm() );
[ + - ][ + - ]
832 [ - + ]: 2 : if( !pTxtFrm )
833 : : {
834 [ # # ][ # # ]: 0 : THROW_RUNTIME_EXCEPTION( XAccessibleContext, "internal error (no text frame)" );
[ # # ][ # # ]
835 : : }
836 : :
837 : 2 : const SwTxtNode *pTxtNd = pTxtFrm->GetTxtNode();
838 [ + - ][ + - ]: 2 : lang::Locale aLoc( pBreakIt->GetLocale( pTxtNd->GetLang( 0 ) ) );
839 : :
840 [ + - ]: 2 : return aLoc;
841 : : }
842 : :
843 : : /** #i27138# - paragraphs are in relation CONTENT_FLOWS_FROM and/or CONTENT_FLOWS_TO */
844 : 6 : uno::Reference<XAccessibleRelationSet> SAL_CALL SwAccessibleParagraph::getAccessibleRelationSet()
845 : : throw ( uno::RuntimeException )
846 : : {
847 [ + - ]: 6 : SolarMutexGuard aGuard;
848 [ + - ][ - + ]: 6 : CHECK_FOR_DEFUNC( XAccessibleContext );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ]
849 : :
850 [ + - ]: 6 : utl::AccessibleRelationSetHelper* pHelper = new utl::AccessibleRelationSetHelper();
851 : :
852 [ - + ]: 6 : const SwTxtFrm* pTxtFrm = dynamic_cast<const SwTxtFrm*>(GetFrm());
853 : : OSL_ENSURE( pTxtFrm,
854 : : "<SwAccessibleParagraph::getAccessibleRelationSet()> - missing text frame");
855 [ + - ]: 6 : if ( pTxtFrm )
856 : : {
857 [ + - ]: 6 : const SwCntntFrm* pPrevCntFrm( pTxtFrm->FindPrevCnt( true ) );
858 [ + + ]: 6 : if ( pPrevCntFrm )
859 : : {
860 [ + - ]: 2 : uno::Sequence< uno::Reference<XInterface> > aSequence(1);
861 [ + - ][ + - ]: 2 : aSequence[0] = GetMap()->GetContext( pPrevCntFrm );
[ + - ]
862 : : AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_FROM,
863 [ + - ]: 2 : aSequence );
864 [ + - ][ + - ]: 2 : pHelper->AddRelation( aAccRel );
[ + - ]
865 : : }
866 : :
867 [ + - ]: 6 : const SwCntntFrm* pNextCntFrm( pTxtFrm->FindNextCnt( true ) );
868 [ + + ]: 6 : if ( pNextCntFrm )
869 : : {
870 [ + - ]: 4 : uno::Sequence< uno::Reference<XInterface> > aSequence(1);
871 [ + - ][ + - ]: 4 : aSequence[0] = GetMap()->GetContext( pNextCntFrm );
[ + - ]
872 : : AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_TO,
873 [ + - ]: 4 : aSequence );
874 [ + - ][ + - ]: 4 : pHelper->AddRelation( aAccRel );
[ + - ]
875 : : }
876 : : }
877 : :
878 [ + - ][ + - ]: 6 : return pHelper;
[ + - ]
879 : : }
880 : :
881 : 2 : void SAL_CALL SwAccessibleParagraph::grabFocus()
882 : : throw (uno::RuntimeException)
883 : : {
884 [ + - ]: 2 : SolarMutexGuard aGuard;
885 : :
886 [ + - ][ - + ]: 2 : CHECK_FOR_DEFUNC( XAccessibleContext );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ]
887 : :
888 : : // get cursor shell
889 [ + - ]: 2 : SwCrsrShell *pCrsrSh = GetCrsrShell();
890 [ + - ]: 2 : SwPaM *pCrsr = GetCursor( false ); // #i27301# - consider new method signature
891 : 2 : const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
892 : 2 : const SwTxtNode* pTxtNd = pTxtFrm->GetTxtNode();
893 : :
894 [ + - ]: 6 : if( pCrsrSh != 0 && pTxtNd != 0 &&
[ + - + - ]
[ - + ][ - + ]
[ + - ]
895 : : ( pCrsr == 0 ||
896 : 2 : pCrsr->GetPoint()->nNode.GetIndex() != pTxtNd->GetIndex() ||
897 [ + - ]: 2 : !pTxtFrm->IsInside( pCrsr->GetPoint()->nContent.GetIndex()) ) )
898 : : {
899 : : // create pam for selection
900 : : SwIndex aIndex( const_cast< SwTxtNode * >( pTxtNd ),
901 [ # # ][ # # ]: 0 : pTxtFrm->GetOfst() );
902 [ # # ][ # # ]: 0 : SwPosition aStartPos( *pTxtNd, aIndex );
[ # # ]
903 [ # # ]: 0 : SwPaM aPaM( aStartPos );
904 : :
905 : : // set PaM at cursor shell
906 [ # # ][ # # ]: 0 : Select( aPaM );
[ # # ][ # # ]
907 : :
908 : :
909 : : }
910 : :
911 : : /* ->#i13955# */
912 [ + - ]: 2 : Window * pWindow = GetWindow();
913 : :
914 [ + - ]: 2 : if (pWindow != NULL)
915 [ + - ][ + - ]: 2 : pWindow->GrabFocus();
916 : : /* <-#i13955# */
917 : 2 : }
918 : :
919 : : // #i71385#
920 : 4 : bool lcl_GetBackgroundColor( Color & rColor,
921 : : const SwFrm* pFrm,
922 : : SwCrsrShell* pCrsrSh )
923 : : {
924 : 4 : const SvxBrushItem* pBackgrdBrush = 0;
925 : 4 : const Color* pSectionTOXColor = 0;
926 : 4 : SwRect aDummyRect;
927 [ - + ][ - + ]: 8 : if ( pFrm &&
[ + - ]
928 [ + - ]: 4 : pFrm->GetBackgroundBrush( pBackgrdBrush, pSectionTOXColor, aDummyRect, false ) )
929 : : {
930 [ # # ]: 0 : if ( pSectionTOXColor )
931 : : {
932 : 0 : rColor = *pSectionTOXColor;
933 : 0 : return true;
934 : : }
935 : : else
936 : : {
937 : 0 : rColor = pBackgrdBrush->GetColor();
938 : 0 : return true;
939 : : }
940 : : }
941 [ + - ]: 4 : else if ( pCrsrSh )
942 : : {
943 [ + - ]: 4 : rColor = pCrsrSh->Imp()->GetRetoucheColor();
944 : 4 : return true;
945 : : }
946 : :
947 : 4 : return false;
948 : : }
949 : :
950 : 2 : sal_Int32 SAL_CALL SwAccessibleParagraph::getForeground()
951 : : throw (uno::RuntimeException)
952 : : {
953 : 2 : Color aBackgroundCol;
954 : :
955 [ + - ][ + - ]: 2 : if ( lcl_GetBackgroundColor( aBackgroundCol, GetFrm(), GetCrsrShell() ) )
[ + - ]
956 : : {
957 [ + - ][ - + ]: 2 : if ( aBackgroundCol.IsDark() )
958 : : {
959 : 0 : return COL_WHITE;
960 : : }
961 : : else
962 : : {
963 : 2 : return COL_BLACK;
964 : : }
965 : : }
966 : :
967 [ # # ]: 2 : return SwAccessibleContext::getForeground();
968 : : }
969 : :
970 : 2 : sal_Int32 SAL_CALL SwAccessibleParagraph::getBackground()
971 : : throw (uno::RuntimeException)
972 : : {
973 : 2 : Color aBackgroundCol;
974 : :
975 [ + - ][ + - ]: 2 : if ( lcl_GetBackgroundColor( aBackgroundCol, GetFrm(), GetCrsrShell() ) )
[ + - ]
976 : : {
977 : 2 : return aBackgroundCol.GetColor();
978 : : }
979 : :
980 [ # # ]: 2 : return SwAccessibleContext::getBackground();
981 : : }
982 : :
983 : 6 : ::rtl::OUString SAL_CALL SwAccessibleParagraph::getImplementationName()
984 : : throw( uno::RuntimeException )
985 : : {
986 : 6 : return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
987 : : }
988 : :
989 : 0 : sal_Bool SAL_CALL SwAccessibleParagraph::supportsService(
990 : : const ::rtl::OUString& sTestServiceName)
991 : : throw (uno::RuntimeException)
992 : : {
993 : : return sTestServiceName.equalsAsciiL( sServiceName,
994 : 0 : sizeof(sServiceName)-1 ) ||
995 : : sTestServiceName.equalsAsciiL( sAccessibleServiceName,
996 [ # # ][ # # ]: 0 : sizeof(sAccessibleServiceName)-1 );
997 : : }
998 : :
999 : 0 : uno::Sequence< ::rtl::OUString > SAL_CALL SwAccessibleParagraph::getSupportedServiceNames()
1000 : : throw( uno::RuntimeException )
1001 : : {
1002 : 0 : uno::Sequence< ::rtl::OUString > aRet(2);
1003 [ # # ]: 0 : ::rtl::OUString* pArray = aRet.getArray();
1004 [ # # ]: 0 : pArray[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
1005 [ # # ]: 0 : pArray[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
1006 : 0 : return aRet;
1007 : : }
1008 : :
1009 : : //
1010 : : //===== XInterface =======================================================
1011 : : //
1012 : :
1013 : 895 : uno::Any SwAccessibleParagraph::queryInterface( const uno::Type& rType )
1014 : : throw (uno::RuntimeException)
1015 : : {
1016 : 895 : uno::Any aRet;
1017 [ + + ][ + - ]: 895 : if ( rType == ::getCppuType((uno::Reference<XAccessibleText> *)0) )
1018 : : {
1019 [ + - ]: 6 : uno::Reference<XAccessibleText> aAccText = (XAccessibleText *) *this; // resolve ambiguity
1020 [ + - ]: 6 : aRet <<= aAccText;
1021 : : }
1022 [ + - ][ - + ]: 889 : else if ( rType == ::getCppuType((uno::Reference<XAccessibleEditableText> *)0) )
1023 : : {
1024 [ # # ]: 0 : uno::Reference<XAccessibleEditableText> aAccEditText = this;
1025 [ # # ]: 0 : aRet <<= aAccEditText;
1026 : : }
1027 [ + - ][ + + ]: 889 : else if ( rType == ::getCppuType((uno::Reference<XAccessibleSelection> *)0) )
1028 : : {
1029 [ + - ]: 18 : uno::Reference<XAccessibleSelection> aAccSel = this;
1030 [ + - ]: 18 : aRet <<= aAccSel;
1031 : : }
1032 [ + - ][ - + ]: 871 : else if ( rType == ::getCppuType((uno::Reference<XAccessibleHypertext> *)0) )
1033 : : {
1034 [ # # ]: 0 : uno::Reference<XAccessibleHypertext> aAccHyp = this;
1035 [ # # ]: 0 : aRet <<= aAccHyp;
1036 : : }
1037 : : // #i63870#
1038 : : // add interface com::sun:star:accessibility::XAccessibleTextAttributes
1039 [ + - ][ - + ]: 871 : else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextAttributes> *)0) )
1040 : : {
1041 [ # # ]: 0 : uno::Reference<XAccessibleTextAttributes> aAccTextAttr = this;
1042 [ # # ]: 0 : aRet <<= aAccTextAttr;
1043 : : }
1044 : : // #i89175#
1045 : : // add interface com::sun:star:accessibility::XAccessibleTextMarkup
1046 [ + - ][ - + ]: 871 : else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextMarkup> *)0) )
1047 : : {
1048 [ # # ]: 0 : uno::Reference<XAccessibleTextMarkup> aAccTextMarkup = this;
1049 [ # # ]: 0 : aRet <<= aAccTextMarkup;
1050 : : }
1051 : : // add interface com::sun:star:accessibility::XAccessibleMultiLineText
1052 [ + - ][ - + ]: 871 : else if ( rType == ::getCppuType((uno::Reference<XAccessibleMultiLineText> *)0) )
1053 : : {
1054 [ # # ]: 0 : uno::Reference<XAccessibleMultiLineText> aAccMultiLineText = this;
1055 [ # # ]: 0 : aRet <<= aAccMultiLineText;
1056 : : }
1057 : : else
1058 : : {
1059 [ + - ]: 871 : aRet = SwAccessibleContext::queryInterface(rType);
1060 : : }
1061 : :
1062 : 895 : return aRet;
1063 : : }
1064 : :
1065 : : //====== XTypeProvider ====================================================
1066 : 0 : uno::Sequence< uno::Type > SAL_CALL SwAccessibleParagraph::getTypes() throw(uno::RuntimeException)
1067 : : {
1068 : 0 : uno::Sequence< uno::Type > aTypes( SwAccessibleContext::getTypes() );
1069 : :
1070 : 0 : sal_Int32 nIndex = aTypes.getLength();
1071 : : // #i63870# - add type accessibility::XAccessibleTextAttributes
1072 : : // #i89175# - add type accessibility::XAccessibleTextMarkup and
1073 : : // accessibility::XAccessibleMultiLineText
1074 [ # # ]: 0 : aTypes.realloc( nIndex + 6 );
1075 : :
1076 [ # # ]: 0 : uno::Type* pTypes = aTypes.getArray();
1077 [ # # ]: 0 : pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleEditableText > * >( 0 ) );
1078 [ # # ]: 0 : pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleTextAttributes > * >( 0 ) );
1079 [ # # ]: 0 : pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) );
1080 [ # # ]: 0 : pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleTextMarkup > * >( 0 ) );
1081 [ # # ]: 0 : pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleMultiLineText > * >( 0 ) );
1082 [ # # ]: 0 : pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleHypertext > * >( 0 ) );
1083 : :
1084 : 0 : return aTypes;
1085 : : }
1086 : :
1087 : : namespace
1088 : : {
1089 : : class theSwAccessibleParagraphImplementationId : public rtl::Static< UnoTunnelIdInit, theSwAccessibleParagraphImplementationId > {};
1090 : : }
1091 : :
1092 : 0 : uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleParagraph::getImplementationId()
1093 : : throw(uno::RuntimeException)
1094 : : {
1095 : 0 : return theSwAccessibleParagraphImplementationId::get().getSeq();
1096 : : }
1097 : :
1098 : :
1099 : : //
1100 : : //===== XAccesibleText ===================================================
1101 : : //
1102 : :
1103 : 0 : sal_Int32 SwAccessibleParagraph::getCaretPosition()
1104 : : throw (uno::RuntimeException)
1105 : : {
1106 [ # # ]: 0 : SolarMutexGuard aGuard;
1107 : :
1108 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1109 : :
1110 [ # # ]: 0 : sal_Int32 nRet = GetCaretPos();
1111 : : {
1112 [ # # ]: 0 : osl::MutexGuard aOldCaretPosGuard( aMutex );
1113 : : OSL_ENSURE( nRet == nOldCaretPos, "caret pos out of sync" );
1114 [ # # ]: 0 : nOldCaretPos = nRet;
1115 : : }
1116 [ # # ]: 0 : if( -1 != nRet )
1117 : : {
1118 : 0 : ::rtl::Reference < SwAccessibleContext > xThis( this );
1119 [ # # ]: 0 : GetMap()->SetCursorContext( xThis );
1120 : : }
1121 : :
1122 [ # # ]: 0 : return nRet;
1123 : : }
1124 : :
1125 : 0 : sal_Bool SAL_CALL SwAccessibleParagraph::setCaretPosition( sal_Int32 nIndex )
1126 : : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1127 : : {
1128 [ # # ]: 0 : SolarMutexGuard aGuard;
1129 : :
1130 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1131 : :
1132 : : // parameter checking
1133 [ # # ]: 0 : sal_Int32 nLength = GetString().getLength();
1134 [ # # ]: 0 : if ( ! IsValidPosition( nIndex, nLength ) )
1135 : : {
1136 [ # # ]: 0 : throw lang::IndexOutOfBoundsException();
1137 : : }
1138 : :
1139 : 0 : sal_Bool bRet = sal_False;
1140 : :
1141 : : // get cursor shell
1142 [ # # ]: 0 : SwCrsrShell* pCrsrShell = GetCrsrShell();
1143 [ # # ]: 0 : if( pCrsrShell != NULL )
1144 : : {
1145 : : // create pam for selection
1146 : 0 : SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
1147 [ # # ][ # # ]: 0 : SwIndex aIndex( pNode, GetPortionData().GetModelPosition(nIndex));
[ # # ][ # # ]
1148 [ # # ][ # # ]: 0 : SwPosition aStartPos( *pNode, aIndex );
[ # # ]
1149 [ # # ]: 0 : SwPaM aPaM( aStartPos );
1150 : :
1151 : : // set PaM at cursor shell
1152 [ # # ][ # # ]: 0 : bRet = Select( aPaM );
[ # # ][ # # ]
1153 : : }
1154 : :
1155 [ # # ]: 0 : return bRet;
1156 : : }
1157 : :
1158 : 0 : sal_Unicode SwAccessibleParagraph::getCharacter( sal_Int32 nIndex )
1159 : : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1160 : : {
1161 [ # # ]: 0 : SolarMutexGuard aGuard;
1162 : :
1163 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1164 : :
1165 [ # # ]: 0 : ::rtl::OUString sText( GetString() );
1166 : :
1167 : : // return character (if valid)
1168 [ # # ]: 0 : if( IsValidChar(nIndex, sText.getLength() ) )
1169 : : {
1170 : 0 : return sText.getStr()[nIndex];
1171 : : }
1172 : : else
1173 [ # # ][ # # ]: 0 : throw lang::IndexOutOfBoundsException();
1174 : : }
1175 : :
1176 : : // #i63870# - re-implement method on behalf of methods
1177 : : // <_getDefaultAttributesImpl(..)> and <_getRunAttributesImpl(..)>
1178 : 0 : uno::Sequence<PropertyValue> SwAccessibleParagraph::getCharacterAttributes(
1179 : : sal_Int32 nIndex,
1180 : : const uno::Sequence< ::rtl::OUString >& aRequestedAttributes )
1181 : : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1182 : : {
1183 : :
1184 [ # # ]: 0 : SolarMutexGuard aGuard;
1185 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1186 : :
1187 [ # # ]: 0 : const ::rtl::OUString& rText = GetString();
1188 : :
1189 [ # # ]: 0 : if( ! IsValidChar( nIndex, rText.getLength() ) )
1190 [ # # ]: 0 : throw lang::IndexOutOfBoundsException();
1191 : :
1192 : : // retrieve default character attributes
1193 [ # # ]: 0 : tAccParaPropValMap aDefAttrSeq;
1194 [ # # ]: 0 : _getDefaultAttributesImpl( aRequestedAttributes, aDefAttrSeq, true );
1195 : :
1196 : : // retrieved run character attributes
1197 [ # # ]: 0 : tAccParaPropValMap aRunAttrSeq;
1198 [ # # ]: 0 : _getRunAttributesImpl( nIndex, aRequestedAttributes, aRunAttrSeq );
1199 : :
1200 : : // merge default and run attributes
1201 [ # # ]: 0 : uno::Sequence< PropertyValue > aValues( aDefAttrSeq.size() );
1202 [ # # ]: 0 : PropertyValue* pValues = aValues.getArray();
1203 : 0 : sal_Int32 i = 0;
1204 [ # # ][ # # ]: 0 : for ( tAccParaPropValMap::const_iterator aDefIter = aDefAttrSeq.begin();
1205 [ # # ]: 0 : aDefIter != aDefAttrSeq.end();
1206 : : ++aDefIter )
1207 : : {
1208 : : tAccParaPropValMap::const_iterator aRunIter =
1209 [ # # ][ # # ]: 0 : aRunAttrSeq.find( aDefIter->first );
1210 [ # # ][ # # ]: 0 : if ( aRunIter != aRunAttrSeq.end() )
1211 : : {
1212 [ # # ]: 0 : pValues[i] = aRunIter->second;
1213 : : }
1214 : : else
1215 : : {
1216 [ # # ]: 0 : pValues[i] = aDefIter->second;
1217 : : }
1218 : 0 : ++i;
1219 : : }
1220 : :
1221 [ # # ][ # # ]: 0 : return aValues;
[ # # ]
1222 : : }
1223 : :
1224 : : // #i63870#
1225 : 0 : void SwAccessibleParagraph::_getDefaultAttributesImpl(
1226 : : const uno::Sequence< ::rtl::OUString >& aRequestedAttributes,
1227 : : tAccParaPropValMap& rDefAttrSeq,
1228 : : const bool bOnlyCharAttrs )
1229 : : {
1230 : : // retrieve default attributes
1231 : 0 : const SwTxtNode* pTxtNode( GetTxtNode() );
1232 : 0 : ::boost::scoped_ptr<SfxItemSet> pSet;
1233 [ # # ]: 0 : if ( !bOnlyCharAttrs )
1234 : : {
1235 : 0 : pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
1236 : : RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
1237 : : RES_PARATR_BEGIN, RES_PARATR_END - 1,
1238 : : RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
1239 [ # # ][ # # ]: 0 : 0 ) );
[ # # ]
1240 : : }
1241 : : else
1242 : : {
1243 : 0 : pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
1244 : : RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
1245 [ # # ][ # # ]: 0 : 0 ) );
[ # # ]
1246 : : }
1247 : : // #i82637# - From the perspective of the a11y API the default character
1248 : : // attributes are the character attributes, which are set at the paragraph style
1249 : : // of the paragraph. The character attributes set at the automatic paragraph
1250 : : // style of the paragraph are treated as run attributes.
1251 : : // pTxtNode->SwCntntNode::GetAttr( *pSet );
1252 : : // get default paragraph attributes, if needed, and merge these into <pSet>
1253 [ # # ]: 0 : if ( !bOnlyCharAttrs )
1254 : : {
1255 : 0 : SfxItemSet aParaSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
1256 : : RES_PARATR_BEGIN, RES_PARATR_END - 1,
1257 : : RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
1258 [ # # ]: 0 : 0 );
1259 [ # # ]: 0 : pTxtNode->SwCntntNode::GetAttr( aParaSet );
1260 [ # # ][ # # ]: 0 : pSet->Put( aParaSet );
1261 : : }
1262 : : // get default character attributes and merge these into <pSet>
1263 : : OSL_ENSURE( pTxtNode->GetTxtColl(),
1264 : : "<SwAccessibleParagraph::_getDefaultAttributesImpl(..)> - missing paragraph style. Serious defect, please inform OD!" );
1265 [ # # ]: 0 : if ( pTxtNode->GetTxtColl() )
1266 : : {
1267 : 0 : SfxItemSet aCharSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
1268 : : RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
1269 [ # # ]: 0 : 0 );
1270 [ # # ]: 0 : aCharSet.Put( pTxtNode->GetTxtColl()->GetAttrSet() );
1271 [ # # ][ # # ]: 0 : pSet->Put( aCharSet );
1272 : : }
1273 : :
1274 : : // build-up sequence containing the run attributes <rDefAttrSeq>
1275 [ # # ]: 0 : tAccParaPropValMap aDefAttrSeq;
1276 : : {
1277 : : const SfxItemPropertyMap& rPropMap =
1278 [ # # ]: 0 : aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR )->getPropertyMap();
1279 [ # # ]: 0 : PropertyEntryVector_t aPropertyEntries = rPropMap.getPropertyEntries();
1280 [ # # ]: 0 : PropertyEntryVector_t::const_iterator aPropIt = aPropertyEntries.begin();
1281 [ # # ][ # # ]: 0 : while ( aPropIt != aPropertyEntries.end() )
1282 : : {
1283 [ # # ]: 0 : const SfxPoolItem* pItem = pSet->GetItem( aPropIt->nWID );
1284 [ # # ]: 0 : if ( pItem )
1285 : : {
1286 : 0 : uno::Any aVal;
1287 [ # # ]: 0 : pItem->QueryValue( aVal, aPropIt->nMemberId );
1288 : :
1289 : 0 : PropertyValue rPropVal;
1290 : 0 : rPropVal.Name = aPropIt->sName;
1291 : 0 : rPropVal.Value = aVal;
1292 : 0 : rPropVal.Handle = -1;
1293 : 0 : rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
1294 : :
1295 [ # # ]: 0 : aDefAttrSeq[rPropVal.Name] = rPropVal;
1296 : : }
1297 : 0 : ++aPropIt;
1298 : : }
1299 : :
1300 : : // #i72800#
1301 : : // add property value entry for the paragraph style
1302 [ # # ][ # # ]: 0 : if ( !bOnlyCharAttrs && pTxtNode->GetTxtColl() )
[ # # ]
1303 : : {
1304 : : const ::rtl::OUString sParaStyleName =
1305 : : ::rtl::OUString::createFromAscii(
1306 [ # # ]: 0 : GetPropName( UNO_NAME_PARA_STYLE_NAME ).pName );
1307 [ # # ][ # # ]: 0 : if ( aDefAttrSeq.find( sParaStyleName ) == aDefAttrSeq.end() )
[ # # ]
1308 : : {
1309 : 0 : PropertyValue rPropVal;
1310 : 0 : rPropVal.Name = sParaStyleName;
1311 [ # # ][ # # ]: 0 : uno::Any aVal( uno::makeAny( ::rtl::OUString( pTxtNode->GetTxtColl()->GetName() ) ) );
1312 : 0 : rPropVal.Value = aVal;
1313 : 0 : rPropVal.Handle = -1;
1314 : 0 : rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
1315 : :
1316 [ # # ]: 0 : aDefAttrSeq[rPropVal.Name] = rPropVal;
1317 : 0 : }
1318 : : }
1319 : :
1320 : : // #i73371#
1321 : : // resolve value text::WritingMode2::PAGE of property value entry WritingMode
1322 [ # # ][ # # ]: 0 : if ( !bOnlyCharAttrs && GetFrm() )
[ # # ]
1323 : : {
1324 : : const ::rtl::OUString sWritingMode =
1325 : : ::rtl::OUString::createFromAscii(
1326 [ # # ]: 0 : GetPropName( UNO_NAME_WRITING_MODE ).pName );
1327 [ # # ]: 0 : tAccParaPropValMap::iterator aIter = aDefAttrSeq.find( sWritingMode );
1328 [ # # ][ # # ]: 0 : if ( aIter != aDefAttrSeq.end() )
1329 : : {
1330 [ # # ]: 0 : PropertyValue rPropVal( aIter->second );
1331 [ # # ]: 0 : sal_Int16 nVal = rPropVal.Value.get<sal_Int16>();
1332 [ # # ]: 0 : if ( nVal == text::WritingMode2::PAGE )
1333 : : {
1334 : 0 : const SwFrm* pUpperFrm( GetFrm()->GetUpper() );
1335 [ # # ]: 0 : while ( pUpperFrm )
1336 : : {
1337 [ # # ]: 0 : if ( pUpperFrm->GetType() &
1338 : : ( FRM_PAGE | FRM_FLY | FRM_SECTION | FRM_TAB | FRM_CELL ) )
1339 : : {
1340 [ # # ][ # # ]: 0 : if ( pUpperFrm->IsVertical() )
1341 : : {
1342 : 0 : nVal = text::WritingMode2::TB_RL;
1343 : : }
1344 [ # # ][ # # ]: 0 : else if ( pUpperFrm->IsRightToLeft() )
1345 : : {
1346 : 0 : nVal = text::WritingMode2::RL_TB;
1347 : : }
1348 : : else
1349 : : {
1350 : 0 : nVal = text::WritingMode2::LR_TB;
1351 : : }
1352 [ # # ]: 0 : rPropVal.Value <<= nVal;
1353 [ # # ]: 0 : aDefAttrSeq[rPropVal.Name] = rPropVal;
1354 : 0 : break;
1355 : : }
1356 : :
1357 [ # # ][ # # ]: 0 : if ( dynamic_cast<const SwFlyFrm*>(pUpperFrm) )
[ # # ]
1358 : : {
1359 [ # # ][ # # ]: 0 : pUpperFrm = dynamic_cast<const SwFlyFrm*>(pUpperFrm)->GetAnchorFrm();
1360 : : }
1361 : : else
1362 : : {
1363 : 0 : pUpperFrm = pUpperFrm->GetUpper();
1364 : : }
1365 : : }
1366 : 0 : }
1367 : 0 : }
1368 : 0 : }
1369 : : }
1370 : :
1371 [ # # ]: 0 : if ( aRequestedAttributes.getLength() == 0 )
1372 : : {
1373 [ # # ]: 0 : rDefAttrSeq = aDefAttrSeq;
1374 : : }
1375 : : else
1376 : : {
1377 : 0 : const ::rtl::OUString* pReqAttrs = aRequestedAttributes.getConstArray();
1378 : 0 : const sal_Int32 nLength = aRequestedAttributes.getLength();
1379 [ # # ]: 0 : for( sal_Int32 i = 0; i < nLength; ++i )
1380 : : {
1381 [ # # ]: 0 : tAccParaPropValMap::const_iterator const aIter = aDefAttrSeq.find( pReqAttrs[i] );
1382 [ # # ][ # # ]: 0 : if ( aIter != aDefAttrSeq.end() )
1383 : : {
1384 [ # # ][ # # ]: 0 : rDefAttrSeq[ aIter->first ] = aIter->second;
[ # # ]
1385 : : }
1386 : : }
1387 [ # # ][ # # ]: 0 : }
1388 : 0 : }
1389 : :
1390 : 0 : uno::Sequence< PropertyValue > SwAccessibleParagraph::getDefaultAttributes(
1391 : : const uno::Sequence< ::rtl::OUString >& aRequestedAttributes )
1392 : : throw ( uno::RuntimeException )
1393 : : {
1394 [ # # ]: 0 : SolarMutexGuard aGuard;
1395 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1396 : :
1397 [ # # ]: 0 : tAccParaPropValMap aDefAttrSeq;
1398 [ # # ]: 0 : _getDefaultAttributesImpl( aRequestedAttributes, aDefAttrSeq );
1399 : :
1400 : : // #i92233#
1401 [ # # ][ # # ]: 0 : static rtl::OUString sMMToPixelRatio(RTL_CONSTASCII_USTRINGPARAM("MMToPixelRatio"));
[ # # ][ # # ]
1402 : 0 : bool bProvideMMToPixelRatio( false );
1403 : : {
1404 [ # # ]: 0 : if ( aRequestedAttributes.getLength() == 0 )
1405 : : {
1406 : 0 : bProvideMMToPixelRatio = true;
1407 : : }
1408 : : else
1409 : : {
1410 : : const rtl::OUString* aRequestedAttrIter =
1411 : : ::std::find( ::comphelper::stl_begin( aRequestedAttributes ),
1412 : : ::comphelper::stl_end( aRequestedAttributes ),
1413 [ # # ]: 0 : sMMToPixelRatio );
1414 [ # # ]: 0 : if ( aRequestedAttrIter != ::comphelper::stl_end( aRequestedAttributes ) )
1415 : : {
1416 : 0 : bProvideMMToPixelRatio = true;
1417 : : }
1418 : : }
1419 : : }
1420 : :
1421 : 0 : uno::Sequence< PropertyValue > aValues( aDefAttrSeq.size() +
1422 [ # # ][ # # ]: 0 : ( bProvideMMToPixelRatio ? 1 : 0 ) );
1423 [ # # ]: 0 : PropertyValue* pValues = aValues.getArray();
1424 : 0 : sal_Int32 i = 0;
1425 [ # # ][ # # ]: 0 : for ( tAccParaPropValMap::const_iterator aIter = aDefAttrSeq.begin();
1426 [ # # ]: 0 : aIter != aDefAttrSeq.end();
1427 : : ++aIter )
1428 : : {
1429 [ # # ]: 0 : pValues[i] = aIter->second;
1430 : 0 : ++i;
1431 : : }
1432 : :
1433 : : // #i92233#
1434 [ # # ]: 0 : if ( bProvideMMToPixelRatio )
1435 : : {
1436 : 0 : PropertyValue rPropVal;
1437 : 0 : rPropVal.Name = sMMToPixelRatio;
1438 : 0 : const Size a100thMMSize( 1000, 1000 );
1439 [ # # ]: 0 : const Size aPixelSize = GetMap()->LogicToPixel( a100thMMSize );
1440 : 0 : const float fRatio = ((float)a100thMMSize.Width()/100)/aPixelSize.Width();
1441 [ # # ]: 0 : rPropVal.Value = uno::makeAny( fRatio );
1442 : 0 : rPropVal.Handle = -1;
1443 : 0 : rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
1444 : 0 : pValues[ aValues.getLength() - 1 ] = rPropVal;
1445 : : }
1446 : :
1447 [ # # ][ # # ]: 0 : return aValues;
1448 : : }
1449 : :
1450 : 0 : void SwAccessibleParagraph::_getRunAttributesImpl(
1451 : : const sal_Int32 nIndex,
1452 : : const uno::Sequence< ::rtl::OUString >& aRequestedAttributes,
1453 : : tAccParaPropValMap& rRunAttrSeq )
1454 : : {
1455 : : // create PaM for character at position <nIndex>
1456 : 0 : SwPaM* pPaM( 0 );
1457 : : {
1458 : 0 : const SwTxtNode* pTxtNode( GetTxtNode() );
1459 [ # # ][ # # ]: 0 : SwPosition* pStartPos = new SwPosition( *pTxtNode );
1460 [ # # ][ # # ]: 0 : pStartPos->nContent.Assign( const_cast<SwTxtNode*>(pTxtNode), static_cast<sal_uInt16>(nIndex) );
1461 [ # # ][ # # ]: 0 : SwPosition* pEndPos = new SwPosition( *pTxtNode );
1462 [ # # ][ # # ]: 0 : pEndPos->nContent.Assign( const_cast<SwTxtNode*>(pTxtNode), static_cast<sal_uInt16>(nIndex+1) );
1463 : :
1464 [ # # ][ # # ]: 0 : pPaM = new SwPaM( *pStartPos, *pEndPos );
1465 : :
1466 [ # # ][ # # ]: 0 : delete pStartPos;
1467 [ # # ][ # # ]: 0 : delete pEndPos;
1468 : : }
1469 : :
1470 : : // retrieve character attributes for the created PaM <pPaM>
1471 : 0 : SfxItemSet aSet( pPaM->GetDoc()->GetAttrPool(),
1472 : : RES_CHRATR_BEGIN, RES_CHRATR_END -1,
1473 [ # # ]: 0 : 0 );
1474 : : // #i82637#
1475 : : // From the perspective of the a11y API the character attributes, which
1476 : : // are set at the automatic paragraph style of the paragraph are treated
1477 : : // as run attributes.
1478 : : // SwXTextCursor::GetCrsrAttr( *pPaM, aSet, sal_True, sal_True );
1479 : : // get character attributes from automatic paragraph style and merge these into <aSet>
1480 : : {
1481 : 0 : const SwTxtNode* pTxtNode( GetTxtNode() );
1482 [ # # ][ # # ]: 0 : if ( pTxtNode->HasSwAttrSet() )
1483 : : {
1484 : 0 : SfxItemSet aAutomaticParaStyleCharAttrs( pPaM->GetDoc()->GetAttrPool(),
1485 : : RES_CHRATR_BEGIN, RES_CHRATR_END -1,
1486 [ # # ]: 0 : 0 );
1487 [ # # ][ # # ]: 0 : aAutomaticParaStyleCharAttrs.Put( *(pTxtNode->GetpSwAttrSet()), sal_False );
1488 [ # # ][ # # ]: 0 : aSet.Put( aAutomaticParaStyleCharAttrs );
1489 : : }
1490 : : }
1491 : : // get character attributes at <pPaM> and merge these into <aSet>
1492 : : {
1493 : 0 : SfxItemSet aCharAttrsAtPaM( pPaM->GetDoc()->GetAttrPool(),
1494 : : RES_CHRATR_BEGIN, RES_CHRATR_END -1,
1495 [ # # ]: 0 : 0 );
1496 [ # # ]: 0 : SwUnoCursorHelper::GetCrsrAttr(*pPaM, aCharAttrsAtPaM, sal_True, sal_True);
1497 [ # # ][ # # ]: 0 : aSet.Put( aCharAttrsAtPaM );
1498 : : }
1499 : :
1500 : : // build-up sequence containing the run attributes <rRunAttrSeq>
1501 : : {
1502 [ # # ]: 0 : tAccParaPropValMap aRunAttrSeq;
1503 : : {
1504 [ # # ]: 0 : tAccParaPropValMap aDefAttrSeq;
1505 [ # # ]: 0 : uno::Sequence< ::rtl::OUString > aDummy;
1506 [ # # ]: 0 : _getDefaultAttributesImpl( aDummy, aDefAttrSeq, true ); // #i82637#
1507 : :
1508 : : const SfxItemPropertyMap& rPropMap =
1509 [ # # ]: 0 : aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR )->getPropertyMap();
1510 [ # # ]: 0 : PropertyEntryVector_t aPropertyEntries = rPropMap.getPropertyEntries();
1511 [ # # ]: 0 : PropertyEntryVector_t::const_iterator aPropIt = aPropertyEntries.begin();
1512 [ # # ][ # # ]: 0 : while ( aPropIt != aPropertyEntries.end() )
1513 : : {
1514 : 0 : const SfxPoolItem* pItem( 0 );
1515 : : // #i82637# - Found character attributes, whose value equals the value of
1516 : : // the corresponding default character attributes, are excluded.
1517 [ # # ][ # # ]: 0 : if ( aSet.GetItemState( aPropIt->nWID, sal_True, &pItem ) == SFX_ITEM_SET )
1518 : : {
1519 : 0 : uno::Any aVal;
1520 [ # # ]: 0 : pItem->QueryValue( aVal, aPropIt->nMemberId );
1521 : :
1522 : 0 : PropertyValue rPropVal;
1523 : 0 : rPropVal.Name = aPropIt->sName;
1524 : 0 : rPropVal.Value = aVal;
1525 : 0 : rPropVal.Handle = -1;
1526 : 0 : rPropVal.State = PropertyState_DIRECT_VALUE;
1527 : :
1528 : : tAccParaPropValMap::const_iterator aDefIter =
1529 [ # # ]: 0 : aDefAttrSeq.find( rPropVal.Name );
1530 [ # # # # ]: 0 : if ( aDefIter == aDefAttrSeq.end() ||
[ # # ][ # # ]
[ # # # #
# # ][ # # ]
1531 [ # # ]: 0 : rPropVal.Value != aDefIter->second.Value )
1532 : : {
1533 [ # # ]: 0 : aRunAttrSeq[rPropVal.Name] = rPropVal;
1534 : 0 : }
1535 : : }
1536 : :
1537 : 0 : ++aPropIt;
1538 [ # # ][ # # ]: 0 : }
1539 : : }
1540 : :
1541 [ # # ]: 0 : if ( aRequestedAttributes.getLength() == 0 )
1542 : : {
1543 [ # # ]: 0 : rRunAttrSeq = aRunAttrSeq;
1544 : : }
1545 : : else
1546 : : {
1547 : 0 : const ::rtl::OUString* pReqAttrs = aRequestedAttributes.getConstArray();
1548 : 0 : const sal_Int32 nLength = aRequestedAttributes.getLength();
1549 [ # # ]: 0 : for( sal_Int32 i = 0; i < nLength; ++i )
1550 : : {
1551 [ # # ]: 0 : tAccParaPropValMap::iterator aIter = aRunAttrSeq.find( pReqAttrs[i] );
1552 [ # # ][ # # ]: 0 : if ( aIter != aRunAttrSeq.end() )
1553 : : {
1554 [ # # ][ # # ]: 0 : rRunAttrSeq[ (*aIter).first ] = (*aIter).second;
[ # # ]
1555 : : }
1556 : : }
1557 [ # # ]: 0 : }
1558 : : }
1559 : :
1560 [ # # ][ # # ]: 0 : delete pPaM;
[ # # ]
1561 : 0 : }
1562 : :
1563 : 0 : uno::Sequence< PropertyValue > SwAccessibleParagraph::getRunAttributes(
1564 : : sal_Int32 nIndex,
1565 : : const uno::Sequence< ::rtl::OUString >& aRequestedAttributes )
1566 : : throw ( lang::IndexOutOfBoundsException,
1567 : : uno::RuntimeException )
1568 : : {
1569 [ # # ]: 0 : SolarMutexGuard aGuard;
1570 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1571 : :
1572 : : {
1573 [ # # ]: 0 : const ::rtl::OUString& rText = GetString();
1574 [ # # ]: 0 : if ( !IsValidChar( nIndex, rText.getLength() ) )
1575 : : {
1576 [ # # ]: 0 : throw lang::IndexOutOfBoundsException();
1577 : 0 : }
1578 : : }
1579 : :
1580 [ # # ]: 0 : tAccParaPropValMap aRunAttrSeq;
1581 [ # # ]: 0 : _getRunAttributesImpl( nIndex, aRequestedAttributes, aRunAttrSeq );
1582 : :
1583 [ # # ]: 0 : uno::Sequence< PropertyValue > aValues( aRunAttrSeq.size() );
1584 [ # # ]: 0 : PropertyValue* pValues = aValues.getArray();
1585 : 0 : sal_Int32 i = 0;
1586 [ # # ][ # # ]: 0 : for ( tAccParaPropValMap::const_iterator aIter = aRunAttrSeq.begin();
1587 [ # # ]: 0 : aIter != aRunAttrSeq.end();
1588 : : ++aIter )
1589 : : {
1590 [ # # ]: 0 : pValues[i] = aIter->second;
1591 : 0 : ++i;
1592 : : }
1593 : :
1594 [ # # ][ # # ]: 0 : return aValues;
1595 : : }
1596 : :
1597 : 0 : awt::Rectangle SwAccessibleParagraph::getCharacterBounds(
1598 : : sal_Int32 nIndex )
1599 : : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1600 : : {
1601 [ # # ]: 0 : SolarMutexGuard aGuard;
1602 : :
1603 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1604 : :
1605 : :
1606 : : /* #i12332# The position after the string needs special treatment.
1607 : : IsValidChar -> IsValidPosition
1608 : : */
1609 [ # # ][ # # ]: 0 : if( ! (IsValidPosition( nIndex, GetString().getLength() ) ) )
1610 [ # # ]: 0 : throw lang::IndexOutOfBoundsException();
1611 : :
1612 : : /* #i12332# */
1613 : 0 : sal_Bool bBehindText = sal_False;
1614 [ # # ][ # # ]: 0 : if ( nIndex == GetString().getLength() )
1615 : 0 : bBehindText = sal_True;
1616 : :
1617 : : // get model position & prepare GetCharRect() arguments
1618 : 0 : SwCrsrMoveState aMoveState;
1619 : 0 : aMoveState.bRealHeight = sal_True;
1620 : 0 : aMoveState.bRealWidth = sal_True;
1621 : 0 : SwSpecialPos aSpecialPos;
1622 : 0 : SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
1623 : :
1624 : 0 : sal_uInt16 nPos = 0;
1625 : :
1626 : : /* #i12332# FillSpecialPos does not accept nIndex ==
1627 : : GetString().getLength(). In that case nPos is set to the
1628 : : length of the string in the core. This way GetCharRect
1629 : : returns the rectangle for a cursor at the end of the
1630 : : paragraph. */
1631 [ # # ]: 0 : if (bBehindText)
1632 : : {
1633 : 0 : nPos = pNode->GetTxt().Len();
1634 : : }
1635 : : else
1636 [ # # ]: 0 : nPos = GetPortionData().FillSpecialPos
1637 [ # # ]: 0 : (nIndex, aSpecialPos, aMoveState.pSpecialPos );
1638 : :
1639 : : // call GetCharRect
1640 : 0 : SwRect aCoreRect;
1641 [ # # ][ # # ]: 0 : SwIndex aIndex( pNode, nPos );
1642 [ # # ][ # # ]: 0 : SwPosition aPosition( *pNode, aIndex );
[ # # ]
1643 [ # # ]: 0 : GetFrm()->GetCharRect( aCoreRect, aPosition, &aMoveState );
1644 : :
1645 : : // translate core coordinates into accessibility coordinates
1646 [ # # ]: 0 : Window *pWin = GetWindow();
1647 [ # # ][ # # ]: 0 : CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
[ # # ][ # # ]
[ # # ]
1648 : :
1649 [ # # ][ # # ]: 0 : Rectangle aScreenRect( GetMap()->CoreToPixel( aCoreRect.SVRect() ));
1650 [ # # ]: 0 : SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root
1651 : :
1652 [ # # ][ # # ]: 0 : Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() );
1653 [ # # ]: 0 : aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() );
1654 : :
1655 : : // convert into AWT Rectangle
1656 : : return awt::Rectangle(
1657 : 0 : aScreenRect.Left(), aScreenRect.Top(),
1658 [ # # ]: 0 : aScreenRect.GetWidth(), aScreenRect.GetHeight() );
[ # # # # ]
[ # # ][ # # ]
1659 : : }
1660 : :
1661 : 0 : sal_Int32 SwAccessibleParagraph::getCharacterCount()
1662 : : throw (uno::RuntimeException)
1663 : : {
1664 [ # # ]: 0 : SolarMutexGuard aGuard;
1665 : :
1666 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1667 : :
1668 [ # # ][ # # ]: 0 : return GetString().getLength();
1669 : : }
1670 : :
1671 : 0 : sal_Int32 SwAccessibleParagraph::getIndexAtPoint( const awt::Point& rPoint )
1672 : : throw (uno::RuntimeException)
1673 : : {
1674 [ # # ]: 0 : SolarMutexGuard aGuard;
1675 : :
1676 : :
1677 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1678 : :
1679 : : // construct SwPosition (where GetCrsrOfst() will put the result into)
1680 : 0 : SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
1681 [ # # ][ # # ]: 0 : SwIndex aIndex( pNode, 0);
1682 [ # # ][ # # ]: 0 : SwPosition aPos( *pNode, aIndex );
[ # # ]
1683 : :
1684 : : // construct Point (translate into layout coordinates)
1685 [ # # ]: 0 : Window *pWin = GetWindow();
1686 [ # # ][ # # ]: 0 : CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
[ # # ][ # # ]
[ # # ]
1687 : 0 : Point aPoint( rPoint.X, rPoint.Y );
1688 [ # # ]: 0 : SwRect aLogBounds( GetBounds( *(GetMap()), GetFrm() ) ); // twip rel to doc root
1689 [ # # ][ # # ]: 0 : Point aPixPos( GetMap()->CoreToPixel( aLogBounds.SVRect() ).TopLeft() );
1690 : 0 : aPoint.X() += aPixPos.X();
1691 : 0 : aPoint.Y() += aPixPos.Y();
1692 [ # # ]: 0 : MapMode aMapMode = pWin->GetMapMode();
1693 [ # # ]: 0 : Point aCorePoint( GetMap()->PixelToCore( aPoint ) );
1694 [ # # ][ # # ]: 0 : if( !aLogBounds.IsInside( aCorePoint ) )
1695 : : {
1696 : : /* #i12332# rPoint is may also be in rectangle returned by
1697 : : getCharacterBounds(getCharacterCount() */
1698 : :
1699 : : awt::Rectangle aRectEndPos =
1700 [ # # ][ # # ]: 0 : getCharacterBounds(getCharacterCount());
1701 : :
1702 [ # # ][ # # ]: 0 : if (rPoint.X - aRectEndPos.X >= 0 &&
[ # # ][ # # ]
1703 : : rPoint.X - aRectEndPos.X < aRectEndPos.Width &&
1704 : : rPoint.Y - aRectEndPos.Y >= 0 &&
1705 : : rPoint.Y - aRectEndPos.Y < aRectEndPos.Height)
1706 [ # # ]: 0 : return getCharacterCount();
1707 : :
1708 : 0 : return -1;
1709 : : }
1710 : :
1711 : : // ask core for position
1712 : : OSL_ENSURE( GetFrm() != NULL, "The text frame has vanished!" );
1713 : : OSL_ENSURE( GetFrm()->IsTxtFrm(), "The text frame has mutated!" );
1714 : 0 : const SwTxtFrm* pFrm = static_cast<const SwTxtFrm*>( GetFrm() );
1715 : 0 : SwCrsrMoveState aMoveState;
1716 : 0 : aMoveState.bPosMatchesBounds = sal_True;
1717 [ # # ]: 0 : sal_Bool bSuccess = pFrm->GetCrsrOfst( &aPos, aCorePoint, &aMoveState );
1718 : :
1719 [ # # ]: 0 : SwIndex aCntntIdx = aPos.nContent;
1720 : 0 : const xub_StrLen nIndex = aCntntIdx.GetIndex();
1721 [ # # ]: 0 : if ( nIndex > 0 )
1722 : : {
1723 : 0 : SwRect aResultRect;
1724 [ # # ]: 0 : pFrm->GetCharRect( aResultRect, aPos );
1725 [ # # ]: 0 : bool bVert = pFrm->IsVertical();
1726 [ # # ]: 0 : bool bR2L = pFrm->IsRightToLeft();
1727 : :
1728 [ # # ][ # # ]: 0 : if ( (!bVert && aResultRect.Pos().X() > aCorePoint.X()) ||
[ # # # # ]
[ # # # # ]
[ # # ]
1729 : 0 : ( bVert && aResultRect.Pos().Y() > aCorePoint.Y()) ||
1730 : 0 : ( bR2L && aResultRect.Right() < aCorePoint.X()) )
1731 : : {
1732 [ # # ][ # # ]: 0 : SwIndex aIdxPrev( pNode, nIndex - 1);
1733 [ # # ][ # # ]: 0 : SwPosition aPosPrev( *pNode, aIdxPrev );
[ # # ]
1734 : 0 : SwRect aResultRectPrev;
1735 [ # # ]: 0 : pFrm->GetCharRect( aResultRectPrev, aPosPrev );
1736 [ # # ][ # # ]: 0 : if ( (!bVert && aResultRectPrev.Pos().X() < aCorePoint.X() && aResultRect.Pos().Y() == aResultRectPrev.Pos().Y()) ||
[ # # ][ # #
# # # # ]
[ # # # #
# # ][ # # ]
1737 : 0 : ( bVert && aResultRectPrev.Pos().Y() < aCorePoint.Y() && aResultRect.Pos().X() == aResultRectPrev.Pos().X()) ||
1738 : 0 : ( bR2L && aResultRectPrev.Right() > aCorePoint.X() && aResultRect.Pos().Y() == aResultRectPrev.Pos().Y()) )
1739 [ # # ][ # # ]: 0 : aPos = aPosPrev;
[ # # ]
1740 : : }
1741 : : }
1742 : :
1743 : : return bSuccess ?
1744 [ # # ]: 0 : GetPortionData().GetAccessiblePosition( aPos.nContent.GetIndex() )
1745 [ # # ][ # # ]: 0 : : -1L;
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1746 : : }
1747 : :
1748 : 0 : ::rtl::OUString SwAccessibleParagraph::getSelectedText()
1749 : : throw (uno::RuntimeException)
1750 : : {
1751 [ # # ]: 0 : SolarMutexGuard aGuard;
1752 : :
1753 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1754 : :
1755 : : sal_Int32 nStart, nEnd;
1756 [ # # ]: 0 : sal_Bool bSelected = GetSelection( nStart, nEnd );
1757 : : return bSelected
1758 : : ? GetString().copy( nStart, nEnd - nStart )
1759 [ # # ][ # # ]: 0 : : ::rtl::OUString();
[ # # ][ # # ]
[ # # ]
1760 : : }
1761 : :
1762 : 0 : sal_Int32 SwAccessibleParagraph::getSelectionStart()
1763 : : throw (uno::RuntimeException)
1764 : : {
1765 [ # # ]: 0 : SolarMutexGuard aGuard;
1766 : :
1767 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1768 : :
1769 : : sal_Int32 nStart, nEnd;
1770 [ # # ]: 0 : GetSelection( nStart, nEnd );
1771 [ # # ]: 0 : return nStart;
1772 : : }
1773 : :
1774 : 0 : sal_Int32 SwAccessibleParagraph::getSelectionEnd()
1775 : : throw (uno::RuntimeException)
1776 : : {
1777 [ # # ]: 0 : SolarMutexGuard aGuard;
1778 : :
1779 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1780 : :
1781 : : sal_Int32 nStart, nEnd;
1782 [ # # ]: 0 : GetSelection( nStart, nEnd );
1783 [ # # ]: 0 : return nEnd;
1784 : : }
1785 : :
1786 : 0 : sal_Bool SwAccessibleParagraph::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
1787 : : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1788 : : {
1789 [ # # ]: 0 : SolarMutexGuard aGuard;
1790 : :
1791 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1792 : :
1793 : : // parameter checking
1794 [ # # ]: 0 : sal_Int32 nLength = GetString().getLength();
1795 [ # # ]: 0 : if ( ! IsValidRange( nStartIndex, nEndIndex, nLength ) )
1796 : : {
1797 [ # # ]: 0 : throw lang::IndexOutOfBoundsException();
1798 : : }
1799 : :
1800 : 0 : sal_Bool bRet = sal_False;
1801 : :
1802 : : // get cursor shell
1803 [ # # ]: 0 : SwCrsrShell* pCrsrShell = GetCrsrShell();
1804 [ # # ]: 0 : if( pCrsrShell != NULL )
1805 : : {
1806 : : // create pam for selection
1807 : 0 : SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
1808 [ # # ][ # # ]: 0 : SwIndex aIndex( pNode, GetPortionData().GetModelPosition(nStartIndex));
[ # # ][ # # ]
1809 [ # # ][ # # ]: 0 : SwPosition aStartPos( *pNode, aIndex );
[ # # ]
1810 [ # # ]: 0 : SwPaM aPaM( aStartPos );
1811 [ # # ]: 0 : aPaM.SetMark();
1812 : 0 : aPaM.GetPoint()->nContent =
1813 [ # # ]: 0 : GetPortionData().GetModelPosition(nEndIndex);
[ # # # # ]
1814 : :
1815 : : // set PaM at cursor shell
1816 [ # # ][ # # ]: 0 : bRet = Select( aPaM );
[ # # ][ # # ]
1817 : : }
1818 : :
1819 [ # # ]: 0 : return bRet;
1820 : : }
1821 : :
1822 : 12 : ::rtl::OUString SwAccessibleParagraph::getText()
1823 : : throw (uno::RuntimeException)
1824 : : {
1825 [ + - ]: 12 : SolarMutexGuard aGuard;
1826 : :
1827 [ + - ][ - + ]: 12 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ]
1828 : :
1829 [ + - ][ + - ]: 12 : return GetString();
1830 : : }
1831 : :
1832 : 0 : ::rtl::OUString SwAccessibleParagraph::getTextRange(
1833 : : sal_Int32 nStartIndex, sal_Int32 nEndIndex )
1834 : : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1835 : : {
1836 [ # # ]: 0 : SolarMutexGuard aGuard;
1837 : :
1838 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1839 : :
1840 [ # # ]: 0 : ::rtl::OUString sText( GetString() );
1841 : :
1842 [ # # ]: 0 : if ( IsValidRange( nStartIndex, nEndIndex, sText.getLength() ) )
1843 : : {
1844 : 0 : OrderRange( nStartIndex, nEndIndex );
1845 : 0 : return sText.copy(nStartIndex, nEndIndex-nStartIndex );
1846 : : }
1847 : : else
1848 [ # # ][ # # ]: 0 : throw lang::IndexOutOfBoundsException();
1849 : : }
1850 : :
1851 : 0 : /*accessibility::*/TextSegment SwAccessibleParagraph::getTextAtIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException)
1852 : : {
1853 [ # # ]: 0 : SolarMutexGuard aGuard;
1854 : :
1855 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1856 : :
1857 : 0 : /*accessibility::*/TextSegment aResult;
1858 : 0 : aResult.SegmentStart = -1;
1859 : 0 : aResult.SegmentEnd = -1;
1860 : :
1861 [ # # ]: 0 : const ::rtl::OUString rText = GetString();
1862 : : // implement the silly specification that first position after
1863 : : // text must return an empty string, rather than throwing an
1864 : : // IndexOutOfBoundsException, except for LINE, where the last
1865 : : // line is returned
1866 [ # # ][ # # ]: 0 : if( nIndex == rText.getLength() && AccessibleTextType::LINE != nTextType )
[ # # ]
1867 : : return aResult;
1868 : :
1869 : : // with error checking
1870 : 0 : i18n::Boundary aBound;
1871 [ # # ]: 0 : sal_Bool bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
1872 : :
1873 : : OSL_ENSURE( aBound.startPos >= 0, "illegal boundary" );
1874 : : OSL_ENSURE( aBound.startPos <= aBound.endPos, "illegal boundary" );
1875 : :
1876 : : // return word (if present)
1877 [ # # ]: 0 : if ( bWord )
1878 : : {
1879 : 0 : aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
1880 : 0 : aResult.SegmentStart = aBound.startPos;
1881 : 0 : aResult.SegmentEnd = aBound.endPos;
1882 : : }
1883 : :
1884 [ # # ]: 0 : return aResult;
1885 : : }
1886 : :
1887 : 0 : /*accessibility::*/TextSegment SwAccessibleParagraph::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException)
1888 : : {
1889 [ # # ]: 0 : SolarMutexGuard aGuard;
1890 : :
1891 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1892 : :
1893 [ # # ]: 0 : const ::rtl::OUString rText = GetString();
1894 : :
1895 : 0 : /*accessibility::*/TextSegment aResult;
1896 : 0 : aResult.SegmentStart = -1;
1897 : 0 : aResult.SegmentEnd = -1;
1898 : :
1899 : : // get starting pos
1900 : 0 : i18n::Boundary aBound;
1901 [ # # ]: 0 : if (nIndex == rText.getLength())
1902 : 0 : aBound.startPos = aBound.endPos = nIndex;
1903 : : else
1904 : : {
1905 [ # # ]: 0 : sal_Bool bTmp = GetTextBoundary( aBound, rText, nIndex, nTextType );
1906 : :
1907 [ # # ]: 0 : if ( ! bTmp )
1908 : 0 : aBound.startPos = aBound.endPos = nIndex;
1909 : : }
1910 : :
1911 : : // now skip to previous word
1912 : 0 : sal_Bool bWord = sal_False;
1913 [ # # ]: 0 : while( !bWord )
1914 : : {
1915 [ # # ]: 0 : nIndex = min( nIndex, aBound.startPos ) - 1;
1916 [ # # ]: 0 : if( nIndex >= 0 )
1917 [ # # ]: 0 : bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
1918 : : else
1919 : 0 : break; // exit if beginning of string is reached
1920 : : }
1921 : :
1922 [ # # ]: 0 : if ( bWord )
1923 : : {
1924 : 0 : aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
1925 : 0 : aResult.SegmentStart = aBound.startPos;
1926 : 0 : aResult.SegmentEnd = aBound.endPos;
1927 : : };
1928 [ # # ]: 0 : return aResult;
1929 : : }
1930 : :
1931 : 0 : /*accessibility::*/TextSegment SwAccessibleParagraph::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException)
1932 : : {
1933 [ # # ]: 0 : SolarMutexGuard aGuard;
1934 : :
1935 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1936 : :
1937 : 0 : /*accessibility::*/TextSegment aResult;
1938 : 0 : aResult.SegmentStart = -1;
1939 : 0 : aResult.SegmentEnd = -1;
1940 [ # # ]: 0 : const ::rtl::OUString rText = GetString();
1941 : :
1942 : : // implement the silly specification that first position after
1943 : : // text must return an empty string, rather than throwing an
1944 : : // IndexOutOfBoundsException
1945 [ # # ]: 0 : if( nIndex == rText.getLength() )
1946 : : return aResult;
1947 : :
1948 : :
1949 : : // get first word, then skip to next word
1950 : 0 : i18n::Boundary aBound;
1951 [ # # ]: 0 : GetTextBoundary( aBound, rText, nIndex, nTextType );
1952 : 0 : sal_Bool bWord = sal_False;
1953 [ # # ]: 0 : while( !bWord )
1954 : : {
1955 [ # # ]: 0 : nIndex = max( sal_Int32(nIndex+1), aBound.endPos );
1956 [ # # ]: 0 : if( nIndex < rText.getLength() )
1957 [ # # ]: 0 : bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
1958 : : else
1959 : 0 : break; // exit if end of string is reached
1960 : : }
1961 : :
1962 [ # # ]: 0 : if ( bWord )
1963 : : {
1964 : 0 : aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
1965 : 0 : aResult.SegmentStart = aBound.startPos;
1966 : 0 : aResult.SegmentEnd = aBound.endPos;
1967 : : }
1968 [ # # ]: 0 : return aResult;
1969 : : }
1970 : :
1971 : 0 : sal_Bool SwAccessibleParagraph::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
1972 : : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1973 : : {
1974 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1975 [ # # ]: 0 : SolarMutexGuard aGuard;
1976 : :
1977 : : // select and copy (through dispatch mechanism)
1978 [ # # ]: 0 : setSelection( nStartIndex, nEndIndex );
1979 [ # # ]: 0 : ExecuteAtViewShell( SID_COPY );
1980 [ # # ]: 0 : return sal_True;
1981 : : }
1982 : :
1983 : :
1984 : : //
1985 : : //===== XAccesibleEditableText ==========================================
1986 : : //
1987 : :
1988 : 0 : sal_Bool SwAccessibleParagraph::cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
1989 : : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1990 : : {
1991 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC( XAccessibleEditableText );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1992 [ # # ]: 0 : SolarMutexGuard aGuard;
1993 : :
1994 [ # # ][ # # ]: 0 : if( !IsEditableState() )
1995 : 0 : return sal_False;
1996 : :
1997 : : // select and cut (through dispatch mechanism)
1998 [ # # ]: 0 : setSelection( nStartIndex, nEndIndex );
1999 [ # # ]: 0 : ExecuteAtViewShell( SID_CUT );
2000 [ # # ]: 0 : return sal_True;
2001 : : }
2002 : :
2003 : 0 : sal_Bool SwAccessibleParagraph::pasteText( sal_Int32 nIndex )
2004 : : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
2005 : : {
2006 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC( XAccessibleEditableText );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2007 [ # # ]: 0 : SolarMutexGuard aGuard;
2008 : :
2009 [ # # ][ # # ]: 0 : if( !IsEditableState() )
2010 : 0 : return sal_False;
2011 : :
2012 : : // select and paste (through dispatch mechanism)
2013 [ # # ]: 0 : setSelection( nIndex, nIndex );
2014 [ # # ]: 0 : ExecuteAtViewShell( SID_PASTE );
2015 [ # # ]: 0 : return sal_True;
2016 : : }
2017 : :
2018 : 0 : sal_Bool SwAccessibleParagraph::deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
2019 : : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
2020 : : {
2021 [ # # ]: 0 : return replaceText( nStartIndex, nEndIndex, ::rtl::OUString() );
2022 : : }
2023 : :
2024 : 0 : sal_Bool SwAccessibleParagraph::insertText( const ::rtl::OUString& sText, sal_Int32 nIndex )
2025 : : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
2026 : : {
2027 : 0 : return replaceText( nIndex, nIndex, sText );
2028 : : }
2029 : :
2030 : 0 : sal_Bool SwAccessibleParagraph::replaceText(
2031 : : sal_Int32 nStartIndex, sal_Int32 nEndIndex,
2032 : : const ::rtl::OUString& sReplacement )
2033 : : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
2034 : : {
2035 [ # # ]: 0 : SolarMutexGuard aGuard;
2036 : :
2037 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC( XAccessibleEditableText );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2038 : :
2039 [ # # ]: 0 : const ::rtl::OUString& rText = GetString();
2040 : :
2041 [ # # ]: 0 : if( IsValidRange( nStartIndex, nEndIndex, rText.getLength() ) )
2042 : : {
2043 [ # # ][ # # ]: 0 : if( !IsEditableState() )
2044 : 0 : return sal_False;
2045 : :
2046 : 0 : SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
2047 : :
2048 : : // translate positions
2049 : : sal_uInt16 nStart, nEnd;
2050 [ # # ]: 0 : sal_Bool bSuccess = GetPortionData().GetEditableRange(
2051 [ # # ]: 0 : nStartIndex, nEndIndex, nStart, nEnd );
2052 : :
2053 : : // edit only if the range is editable
2054 [ # # ]: 0 : if( bSuccess )
2055 : : {
2056 : : // create SwPosition for nStartIndex
2057 [ # # ][ # # ]: 0 : SwIndex aIndex( pNode, nStart );
2058 [ # # ][ # # ]: 0 : SwPosition aStartPos( *pNode, aIndex );
[ # # ]
2059 : :
2060 : : // create SwPosition for nEndIndex
2061 [ # # ]: 0 : SwPosition aEndPos( aStartPos );
2062 [ # # ]: 0 : aEndPos.nContent = nEnd;
2063 : :
2064 : : // now create XTextRange as helper and set string
2065 : : const uno::Reference<text::XTextRange> xRange(
2066 : : SwXTextRange::CreateXTextRange(
2067 [ # # ]: 0 : *pNode->GetDoc(), aStartPos, &aEndPos));
2068 [ # # ][ # # ]: 0 : xRange->setString(sReplacement);
2069 : :
2070 : : // delete portion data
2071 [ # # ][ # # ]: 0 : ClearPortionData();
[ # # ][ # # ]
2072 : : }
2073 : :
2074 : 0 : return bSuccess;
2075 : : }
2076 : : else
2077 [ # # ][ # # ]: 0 : throw lang::IndexOutOfBoundsException();
2078 : : }
2079 : :
2080 : : struct IndexCompare
2081 : : {
2082 : : const PropertyValue* pValues;
2083 : 0 : IndexCompare( const PropertyValue* pVals ) : pValues(pVals) {}
2084 : 0 : bool operator() ( const sal_Int32& a, const sal_Int32& b ) const
2085 : : {
2086 : 0 : return (pValues[a].Name < pValues[b].Name) ? true : false;
2087 : : }
2088 : : };
2089 : :
2090 : :
2091 : 0 : sal_Bool SwAccessibleParagraph::setAttributes(
2092 : : sal_Int32 nStartIndex,
2093 : : sal_Int32 nEndIndex,
2094 : : const uno::Sequence<PropertyValue>& rAttributeSet )
2095 : : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
2096 : : {
2097 [ # # ]: 0 : SolarMutexGuard aGuard;
2098 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC( XAccessibleEditableText );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2099 : :
2100 [ # # ]: 0 : const ::rtl::OUString& rText = GetString();
2101 : :
2102 [ # # ]: 0 : if( ! IsValidRange( nStartIndex, nEndIndex, rText.getLength() ) )
2103 [ # # ]: 0 : throw lang::IndexOutOfBoundsException();
2104 : :
2105 [ # # ][ # # ]: 0 : if( !IsEditableState() )
2106 : 0 : return sal_False;
2107 : :
2108 : :
2109 : : // create a (dummy) text portion for the sole purpose of calling
2110 : : // setPropertyValue on it
2111 : : uno::Reference<XMultiPropertySet> xPortion = CreateUnoPortion( nStartIndex,
2112 [ # # ][ # # ]: 0 : nEndIndex );
[ # # ]
2113 : :
2114 : : // build sorted index array
2115 : 0 : sal_Int32 nLength = rAttributeSet.getLength();
2116 : 0 : const PropertyValue* pPairs = rAttributeSet.getConstArray();
2117 [ # # ]: 0 : sal_Int32* pIndices = new sal_Int32[nLength];
2118 : : sal_Int32 i;
2119 [ # # ]: 0 : for( i = 0; i < nLength; i++ )
2120 : 0 : pIndices[i] = i;
2121 [ # # # # ]: 0 : sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) );
2122 : :
2123 : : // create sorted sequences accoring to index array
2124 [ # # ]: 0 : uno::Sequence< ::rtl::OUString > aNames( nLength );
2125 [ # # ]: 0 : ::rtl::OUString* pNames = aNames.getArray();
2126 [ # # ]: 0 : uno::Sequence< uno::Any > aValues( nLength );
2127 [ # # ]: 0 : uno::Any* pValues = aValues.getArray();
2128 [ # # ]: 0 : for( i = 0; i < nLength; i++ )
2129 : : {
2130 : 0 : const PropertyValue& rVal = pPairs[pIndices[i]];
2131 : 0 : pNames[i] = rVal.Name;
2132 : 0 : pValues[i] = rVal.Value;
2133 : : }
2134 [ # # ]: 0 : delete[] pIndices;
2135 : :
2136 : : // now set the values
2137 : 0 : sal_Bool bRet = sal_True;
2138 : : try
2139 : : {
2140 [ # # ][ # # ]: 0 : xPortion->setPropertyValues( aNames, aValues );
2141 : : }
2142 [ # # ]: 0 : catch (const UnknownPropertyException&)
2143 : : {
2144 : : // error handling through return code!
2145 : 0 : bRet = sal_False;
2146 : : }
2147 : :
2148 [ # # ][ # # ]: 0 : return bRet;
[ # # ]
2149 : : }
2150 : :
2151 : 0 : sal_Bool SwAccessibleParagraph::setText( const ::rtl::OUString& sText )
2152 : : throw (uno::RuntimeException)
2153 : : {
2154 [ # # ]: 0 : return replaceText(0, GetString().getLength(), sText);
2155 : : }
2156 : :
2157 : : //===== XAccessibleSelection ============================================
2158 : :
2159 : 4 : void SwAccessibleParagraph::selectAccessibleChild(
2160 : : sal_Int32 nChildIndex )
2161 : : throw ( lang::IndexOutOfBoundsException,
2162 : : uno::RuntimeException )
2163 : : {
2164 [ + - ][ - + ]: 4 : CHECK_FOR_DEFUNC( XAccessibleSelection );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ]
2165 : :
2166 : 4 : aSelectionHelper.selectAccessibleChild(nChildIndex);
2167 : 0 : }
2168 : :
2169 : 4 : sal_Bool SwAccessibleParagraph::isAccessibleChildSelected(
2170 : : sal_Int32 nChildIndex )
2171 : : throw ( lang::IndexOutOfBoundsException,
2172 : : uno::RuntimeException )
2173 : : {
2174 [ + - ][ - + ]: 4 : CHECK_FOR_DEFUNC( XAccessibleSelection );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ]
2175 : :
2176 : 4 : return aSelectionHelper.isAccessibleChildSelected(nChildIndex);
2177 : : }
2178 : :
2179 : 4 : void SwAccessibleParagraph::clearAccessibleSelection( )
2180 : : throw ( uno::RuntimeException )
2181 : : {
2182 [ + - ][ - + ]: 4 : CHECK_FOR_DEFUNC( XAccessibleSelection );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ]
2183 : :
2184 : 4 : aSelectionHelper.clearAccessibleSelection();
2185 : 4 : }
2186 : :
2187 : 6 : void SwAccessibleParagraph::selectAllAccessibleChildren( )
2188 : : throw ( uno::RuntimeException )
2189 : : {
2190 [ + - ][ - + ]: 6 : CHECK_FOR_DEFUNC( XAccessibleSelection );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ]
2191 : :
2192 : 6 : aSelectionHelper.selectAllAccessibleChildren();
2193 : 6 : }
2194 : :
2195 : 10 : sal_Int32 SwAccessibleParagraph::getSelectedAccessibleChildCount( )
2196 : : throw ( uno::RuntimeException )
2197 : : {
2198 [ + - ][ - + ]: 10 : CHECK_FOR_DEFUNC( XAccessibleSelection );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ]
2199 : :
2200 : 10 : return aSelectionHelper.getSelectedAccessibleChildCount();
2201 : : }
2202 : :
2203 : 4 : uno::Reference<XAccessible> SwAccessibleParagraph::getSelectedAccessibleChild(
2204 : : sal_Int32 nSelectedChildIndex )
2205 : : throw ( lang::IndexOutOfBoundsException,
2206 : : uno::RuntimeException)
2207 : : {
2208 [ + - ][ - + ]: 4 : CHECK_FOR_DEFUNC( XAccessibleSelection );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ]
2209 : :
2210 : 4 : return aSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex);
2211 : : }
2212 : :
2213 : : // index has to be treated as global child index.
2214 : 4 : void SwAccessibleParagraph::deselectAccessibleChild(
2215 : : sal_Int32 nChildIndex )
2216 : : throw ( lang::IndexOutOfBoundsException,
2217 : : uno::RuntimeException )
2218 : : {
2219 [ + - ][ - + ]: 4 : CHECK_FOR_DEFUNC( XAccessibleSelection );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ]
2220 : :
2221 : 4 : aSelectionHelper.deselectAccessibleChild( nChildIndex );
2222 : 0 : }
2223 : :
2224 : : //===== XAccessibleHypertext ============================================
2225 : :
2226 : : class SwHyperlinkIter_Impl
2227 : : {
2228 : : const SwpHints *pHints;
2229 : : xub_StrLen nStt;
2230 : : xub_StrLen nEnd;
2231 : : sal_uInt16 nPos;
2232 : :
2233 : : public:
2234 : : SwHyperlinkIter_Impl( const SwTxtFrm *pTxtFrm );
2235 : : const SwTxtAttr *next();
2236 : 0 : sal_uInt16 getCurrHintPos() const { return nPos-1; }
2237 : :
2238 : 0 : xub_StrLen startIdx() const { return nStt; }
2239 : 0 : xub_StrLen endIdx() const { return nEnd; }
2240 : : };
2241 : :
2242 : 0 : SwHyperlinkIter_Impl::SwHyperlinkIter_Impl( const SwTxtFrm *pTxtFrm ) :
2243 : 0 : pHints( pTxtFrm->GetTxtNode()->GetpSwpHints() ),
2244 : 0 : nStt( pTxtFrm->GetOfst() ),
2245 : 0 : nPos( 0 )
2246 : : {
2247 : 0 : const SwTxtFrm *pFollFrm = pTxtFrm->GetFollow();
2248 [ # # ]: 0 : nEnd = pFollFrm ? pFollFrm->GetOfst() : pTxtFrm->GetTxtNode()->Len();
2249 : 0 : }
2250 : :
2251 : 0 : const SwTxtAttr *SwHyperlinkIter_Impl::next()
2252 : : {
2253 : 0 : const SwTxtAttr *pAttr = 0;
2254 [ # # ]: 0 : if( pHints )
2255 : : {
2256 [ # # ][ # # ]: 0 : while( !pAttr && nPos < pHints->Count() )
[ # # ]
2257 : : {
2258 : 0 : const SwTxtAttr *pHt = (*pHints)[nPos];
2259 [ # # ]: 0 : if( RES_TXTATR_INETFMT == pHt->Which() )
2260 : : {
2261 : 0 : xub_StrLen nHtStt = *pHt->GetStart();
2262 : 0 : xub_StrLen nHtEnd = *pHt->GetAnyEnd();
2263 [ # # ][ # # ]: 0 : if( nHtEnd > nHtStt &&
[ # # ][ # # ]
[ # # ]
2264 : : ( (nHtStt >= nStt && nHtStt < nEnd) ||
2265 : : (nHtEnd > nStt && nHtEnd <= nEnd) ) )
2266 : : {
2267 : 0 : pAttr = pHt;
2268 : : }
2269 : : }
2270 : 0 : ++nPos;
2271 : : }
2272 : : }
2273 : :
2274 : 0 : return pAttr;
2275 : : };
2276 : :
2277 : 0 : sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkCount()
2278 : : throw (uno::RuntimeException)
2279 : : {
2280 [ # # ]: 0 : SolarMutexGuard aGuard;
2281 : :
2282 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC( XAccessibleHypertext );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2283 : :
2284 : 0 : sal_Int32 nCount = 0;
2285 : : // #i77108# - provide hyperlinks also in editable documents.
2286 : : // if( !IsEditableState() )
2287 : : {
2288 : 0 : const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
2289 [ # # ]: 0 : SwHyperlinkIter_Impl aIter( pTxtFrm );
2290 [ # # ][ # # ]: 0 : while( aIter.next() )
2291 : 0 : nCount++;
2292 : : }
2293 : :
2294 [ # # ]: 0 : return nCount;
2295 : : }
2296 : :
2297 : : uno::Reference< XAccessibleHyperlink > SAL_CALL
2298 : 0 : SwAccessibleParagraph::getHyperLink( sal_Int32 nLinkIndex )
2299 : : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
2300 : : {
2301 [ # # ]: 0 : SolarMutexGuard aGuard;
2302 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC( XAccessibleHypertext );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2303 : :
2304 : 0 : uno::Reference< XAccessibleHyperlink > xRet;
2305 : :
2306 : : // #i77108#
2307 : : {
2308 : 0 : const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
2309 [ # # ]: 0 : SwHyperlinkIter_Impl aHIter( pTxtFrm );
2310 [ # # ]: 0 : while( nLinkIndex-- )
2311 [ # # ]: 0 : aHIter.next();
2312 : :
2313 [ # # ]: 0 : const SwTxtAttr *pHt = aHIter.next();
2314 [ # # ]: 0 : if( pHt )
2315 : : {
2316 [ # # ]: 0 : if( !pHyperTextData )
2317 [ # # ][ # # ]: 0 : pHyperTextData = new SwAccessibleHyperTextData;
2318 : : SwAccessibleHyperTextData::iterator aIter =
2319 [ # # ]: 0 : pHyperTextData ->find( pHt );
2320 [ # # ]: 0 : if( aIter != pHyperTextData->end() )
2321 : : {
2322 [ # # ][ # # ]: 0 : xRet = (*aIter).second;
2323 : : }
2324 [ # # ]: 0 : if( !xRet.is() )
2325 : : {
2326 [ # # ]: 0 : sal_Int32 nHStt= GetPortionData().GetAccessiblePosition(
2327 [ # # ][ # # ]: 0 : max( aHIter.startIdx(), *pHt->GetStart() ) );
2328 [ # # ]: 0 : sal_Int32 nHEnd= GetPortionData().GetAccessiblePosition(
2329 [ # # ][ # # ]: 0 : min( aHIter.endIdx(), *pHt->GetAnyEnd() ) );
[ # # ]
2330 : 0 : xRet = new SwAccessibleHyperlink( aHIter.getCurrHintPos(),
2331 [ # # ][ # # ]: 0 : this, nHStt, nHEnd );
[ # # ]
2332 [ # # ]: 0 : if( aIter != pHyperTextData->end() )
2333 : : {
2334 [ # # ]: 0 : (*aIter).second = xRet;
2335 : : }
2336 : : else
2337 : : {
2338 [ # # ]: 0 : SwAccessibleHyperTextData::value_type aEntry( pHt, xRet );
2339 [ # # ][ # # ]: 0 : pHyperTextData->insert( aEntry );
2340 : : }
2341 : : }
2342 : : }
2343 : : }
2344 : :
2345 [ # # ]: 0 : if( !xRet.is() )
2346 [ # # ]: 0 : throw lang::IndexOutOfBoundsException();
2347 : :
2348 [ # # ]: 0 : return xRet;
2349 : : }
2350 : :
2351 : 0 : sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkIndex( sal_Int32 nCharIndex )
2352 : : throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
2353 : : {
2354 [ # # ]: 0 : SolarMutexGuard aGuard;
2355 [ # # ][ # # ]: 0 : CHECK_FOR_DEFUNC( XAccessibleHypertext );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2356 : :
2357 : : // parameter checking
2358 [ # # ]: 0 : sal_Int32 nLength = GetString().getLength();
2359 [ # # ]: 0 : if ( ! IsValidPosition( nCharIndex, nLength ) )
2360 : : {
2361 [ # # ]: 0 : throw lang::IndexOutOfBoundsException();
2362 : : }
2363 : :
2364 : 0 : sal_Int32 nRet = -1;
2365 : : // #i77108#
2366 : : {
2367 : 0 : const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
2368 [ # # ]: 0 : SwHyperlinkIter_Impl aHIter( pTxtFrm );
2369 : :
2370 [ # # ][ # # ]: 0 : xub_StrLen nIdx = GetPortionData().GetModelPosition( nCharIndex );
2371 : 0 : sal_Int32 nPos = 0;
2372 [ # # ]: 0 : const SwTxtAttr *pHt = aHIter.next();
2373 [ # # ][ # # ]: 0 : while( pHt && !(nIdx >= *pHt->GetStart() && nIdx < *pHt->GetAnyEnd()) )
[ # # ][ # # ]
[ # # ]
2374 : : {
2375 [ # # ]: 0 : pHt = aHIter.next();
2376 : 0 : nPos++;
2377 : : }
2378 : :
2379 [ # # ]: 0 : if( pHt )
2380 : 0 : nRet = nPos;
2381 : :
2382 : : }
2383 : :
2384 [ # # ]: 0 : return nRet;
2385 : : }
2386 : :
2387 : : // #i71360#, #i108125# - adjustments for change tracking text markup
2388 : 0 : sal_Int32 SAL_CALL SwAccessibleParagraph::getTextMarkupCount( sal_Int32 nTextMarkupType )
2389 : : throw (lang::IllegalArgumentException,
2390 : : uno::RuntimeException)
2391 : : {
2392 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
2393 : 0 : std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper;
2394 : : SAL_WNODEPRECATED_DECLARATIONS_POP
2395 [ # # ]: 0 : switch ( nTextMarkupType )
2396 : : {
2397 : : case text::TextMarkupType::TRACK_CHANGE_INSERTION:
2398 : : case text::TextMarkupType::TRACK_CHANGE_DELETION:
2399 : : case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
2400 : : {
2401 : : pTextMarkupHelper.reset( new SwTextMarkupHelper(
2402 : : GetPortionData(),
2403 [ # # ][ # # ]: 0 : *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
[ # # ][ # # ]
2404 : : }
2405 : 0 : break;
2406 : : default:
2407 : : {
2408 [ # # ][ # # ]: 0 : pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) );
[ # # ]
2409 : : }
2410 : : }
2411 : :
2412 [ # # ]: 0 : return pTextMarkupHelper->getTextMarkupCount( nTextMarkupType );
2413 : : }
2414 : :
2415 : : /*accessibility::*/TextSegment SAL_CALL
2416 : 0 : SwAccessibleParagraph::getTextMarkup( sal_Int32 nTextMarkupIndex,
2417 : : sal_Int32 nTextMarkupType )
2418 : : throw (lang::IndexOutOfBoundsException,
2419 : : lang::IllegalArgumentException,
2420 : : uno::RuntimeException)
2421 : : {
2422 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
2423 : 0 : std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper;
2424 : : SAL_WNODEPRECATED_DECLARATIONS_POP
2425 [ # # ]: 0 : switch ( nTextMarkupType )
2426 : : {
2427 : : case text::TextMarkupType::TRACK_CHANGE_INSERTION:
2428 : : case text::TextMarkupType::TRACK_CHANGE_DELETION:
2429 : : case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
2430 : : {
2431 : : pTextMarkupHelper.reset( new SwTextMarkupHelper(
2432 : : GetPortionData(),
2433 [ # # ][ # # ]: 0 : *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
[ # # ][ # # ]
2434 : : }
2435 : 0 : break;
2436 : : default:
2437 : : {
2438 [ # # ][ # # ]: 0 : pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) );
[ # # ]
2439 : : }
2440 : : }
2441 : :
2442 [ # # ]: 0 : return pTextMarkupHelper->getTextMarkup( nTextMarkupIndex, nTextMarkupType );
2443 : : }
2444 : :
2445 : : uno::Sequence< /*accessibility::*/TextSegment > SAL_CALL
2446 : 0 : SwAccessibleParagraph::getTextMarkupAtIndex( sal_Int32 nCharIndex,
2447 : : sal_Int32 nTextMarkupType )
2448 : : throw (lang::IndexOutOfBoundsException,
2449 : : lang::IllegalArgumentException,
2450 : : uno::RuntimeException)
2451 : : {
2452 : : // parameter checking
2453 [ # # ]: 0 : const sal_Int32 nLength = GetString().getLength();
2454 [ # # ]: 0 : if ( ! IsValidPosition( nCharIndex, nLength ) )
2455 : : {
2456 [ # # ]: 0 : throw lang::IndexOutOfBoundsException();
2457 : : }
2458 : :
2459 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
2460 : 0 : std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper;
2461 : : SAL_WNODEPRECATED_DECLARATIONS_POP
2462 [ # # ]: 0 : switch ( nTextMarkupType )
2463 : : {
2464 : : case text::TextMarkupType::TRACK_CHANGE_INSERTION:
2465 : : case text::TextMarkupType::TRACK_CHANGE_DELETION:
2466 : : case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
2467 : : {
2468 : : pTextMarkupHelper.reset( new SwTextMarkupHelper(
2469 : : GetPortionData(),
2470 [ # # ][ # # ]: 0 : *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
[ # # ][ # # ]
2471 : : }
2472 : 0 : break;
2473 : : default:
2474 : : {
2475 [ # # ][ # # ]: 0 : pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) );
[ # # ]
2476 : : }
2477 : : }
2478 : :
2479 [ # # ]: 0 : return pTextMarkupHelper->getTextMarkupAtIndex( nCharIndex, nTextMarkupType );
2480 : : }
2481 : :
2482 : : // #i89175#
2483 : 0 : sal_Int32 SAL_CALL SwAccessibleParagraph::getLineNumberAtIndex( sal_Int32 nIndex )
2484 : : throw (lang::IndexOutOfBoundsException,
2485 : : uno::RuntimeException)
2486 : : {
2487 : : // parameter checking
2488 : 0 : const sal_Int32 nLength = GetString().getLength();
2489 [ # # ]: 0 : if ( ! IsValidPosition( nIndex, nLength ) )
2490 : : {
2491 [ # # ]: 0 : throw lang::IndexOutOfBoundsException();
2492 : : }
2493 : :
2494 : 0 : const sal_Int32 nLineNo = GetPortionData().GetLineNo( nIndex );
2495 : 0 : return nLineNo;
2496 : : }
2497 : :
2498 : : /*accessibility::*/TextSegment SAL_CALL
2499 : 0 : SwAccessibleParagraph::getTextAtLineNumber( sal_Int32 nLineNo )
2500 : : throw (lang::IndexOutOfBoundsException,
2501 : : uno::RuntimeException)
2502 : : {
2503 : : // parameter checking
2504 [ # # ][ # # ]: 0 : if ( nLineNo < 0 ||
[ # # ]
2505 [ # # ][ # # ]: 0 : nLineNo >= GetPortionData().GetLineCount() )
2506 : : {
2507 [ # # ]: 0 : throw lang::IndexOutOfBoundsException();
2508 : : }
2509 : :
2510 : 0 : i18n::Boundary aLineBound;
2511 [ # # ][ # # ]: 0 : GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound );
2512 : :
2513 : 0 : /*accessibility::*/TextSegment aTextAtLine;
2514 [ # # ]: 0 : const ::rtl::OUString rText = GetString();
2515 : : aTextAtLine.SegmentText = rText.copy( aLineBound.startPos,
2516 : 0 : aLineBound.endPos - aLineBound.startPos );
2517 : 0 : aTextAtLine.SegmentStart = aLineBound.startPos;
2518 : 0 : aTextAtLine.SegmentEnd = aLineBound.endPos;
2519 : :
2520 : 0 : return aTextAtLine;
2521 : : }
2522 : :
2523 : 0 : /*accessibility::*/TextSegment SAL_CALL SwAccessibleParagraph::getTextAtLineWithCaret()
2524 : : throw (uno::RuntimeException)
2525 : : {
2526 : 0 : const sal_Int32 nLineNoOfCaret = getNumberOfLineWithCaret();
2527 : :
2528 [ # # ]: 0 : if ( nLineNoOfCaret >= 0 &&
[ # # # # ]
2529 : 0 : nLineNoOfCaret < GetPortionData().GetLineCount() )
2530 : : {
2531 : 0 : return getTextAtLineNumber( nLineNoOfCaret );
2532 : : }
2533 : :
2534 : 0 : return /*accessibility::*/TextSegment();
2535 : : }
2536 : :
2537 : 0 : sal_Int32 SAL_CALL SwAccessibleParagraph::getNumberOfLineWithCaret()
2538 : : throw (uno::RuntimeException)
2539 : : {
2540 : 0 : const sal_Int32 nCaretPos = getCaretPosition();
2541 : 0 : const sal_Int32 nLength = GetString().getLength();
2542 [ # # ]: 0 : if ( !IsValidPosition( nCaretPos, nLength ) )
2543 : : {
2544 : 0 : return -1;
2545 : : }
2546 : :
2547 : 0 : sal_Int32 nLineNo = GetPortionData().GetLineNo( nCaretPos );
2548 : :
2549 : : // special handling for cursor positioned at end of text line via End key
2550 [ # # ]: 0 : if ( nCaretPos != 0 )
2551 : : {
2552 : 0 : i18n::Boundary aLineBound;
2553 [ # # ][ # # ]: 0 : GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound );
2554 [ # # ]: 0 : if ( nCaretPos == aLineBound.startPos )
2555 : : {
2556 [ # # ]: 0 : SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell();
2557 [ # # ]: 0 : if ( pCrsrShell != 0 )
2558 : : {
2559 [ # # ]: 0 : const awt::Rectangle aCharRect = getCharacterBounds( nCaretPos );
2560 : :
2561 : 0 : const SwRect& aCursorCoreRect = pCrsrShell->GetCharRect();
2562 : : // translate core coordinates into accessibility coordinates
2563 [ # # ]: 0 : Window *pWin = GetWindow();
2564 [ # # ][ # # ]: 0 : CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
[ # # ][ # # ]
[ # # ]
2565 : :
2566 [ # # ][ # # ]: 0 : Rectangle aScreenRect( GetMap()->CoreToPixel( aCursorCoreRect.SVRect() ));
2567 : :
2568 [ # # ]: 0 : SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root
2569 [ # # ][ # # ]: 0 : Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() );
2570 [ # # ]: 0 : aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() );
2571 : :
2572 : : // convert into AWT Rectangle
2573 : 0 : const awt::Rectangle aCursorRect( aScreenRect.Left(),
2574 : 0 : aScreenRect.Top(),
2575 [ # # ]: 0 : aScreenRect.GetWidth(),
2576 [ # # ]: 0 : aScreenRect.GetHeight() );
2577 : :
2578 [ # # ][ # # ]: 0 : if ( aCharRect.X != aCursorRect.X ||
2579 : : aCharRect.Y != aCursorRect.Y )
2580 : : {
2581 : 0 : --nLineNo;
2582 : : }
2583 : : }
2584 : : }
2585 : : }
2586 : :
2587 : 0 : return nLineNo;
2588 : : }
2589 : :
2590 : : // #i108125#
2591 : 174 : void SwAccessibleParagraph::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
2592 : : {
2593 : 174 : mpParaChangeTrackInfo->reset();
2594 : :
2595 : 174 : CheckRegistration( pOld, pNew );
2596 : 174 : }
2597 : :
2598 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|