Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <txtfrm.hxx>
21 : #include <flyfrm.hxx>
22 : #include <ndtxt.hxx>
23 : #include <pam.hxx>
24 : #include <unotextrange.hxx>
25 : #include <unocrsrhelper.hxx>
26 : #include <crstate.hxx>
27 : #include <accmap.hxx>
28 : #include <fesh.hxx>
29 : #include <viewopt.hxx>
30 : #include <osl/mutex.hxx>
31 : #include <vcl/svapp.hxx>
32 : #include <vcl/window.hxx>
33 : #include <rtl/ustrbuf.hxx>
34 : #include <com/sun/star/accessibility/AccessibleRole.hpp>
35 : #include <com/sun/star/accessibility/AccessibleStateType.hpp>
36 : #include <com/sun/star/accessibility/AccessibleTextType.hpp>
37 : #include <com/sun/star/accessibility/AccessibleEventId.hpp>
38 : #include <unotools/accessiblestatesethelper.hxx>
39 : #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
40 : #include <com/sun/star/i18n/WordType.hpp>
41 : #include <com/sun/star/i18n/XBreakIterator.hpp>
42 : #include <com/sun/star/beans/UnknownPropertyException.hpp>
43 : #include <breakit.hxx>
44 : #include <accpara.hxx>
45 : #include <access.hrc>
46 : #include <accportions.hxx>
47 : #include <sfx2/viewsh.hxx>
48 : #include <sfx2/viewfrm.hxx>
49 : #include <sfx2/dispatch.hxx>
50 : #include <unotools/charclass.hxx>
51 : #include <unocrsr.hxx>
52 : #include <unoport.hxx>
53 : #include <doc.hxx>
54 : #include <IDocumentRedlineAccess.hxx>
55 : #include <crsskip.hxx>
56 : #include <txtatr.hxx>
57 : #include <acchyperlink.hxx>
58 : #include <acchypertextdata.hxx>
59 : #include <unotools/accessiblerelationsethelper.hxx>
60 : #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
61 : #include <section.hxx>
62 : #include <doctxm.hxx>
63 : #include <comphelper/accessibletexthelper.hxx>
64 : #include <algorithm>
65 : #include <docufld.hxx>
66 : #include <txtfld.hxx>
67 : #include <fmtfld.hxx>
68 : #include <modcfg.hxx>
69 : #include <com/sun/star/beans/XPropertySet.hpp>
70 : #include "swmodule.hxx"
71 : #include "redline.hxx"
72 : #include <com/sun/star/awt/FontWeight.hpp>
73 : #include <com/sun/star/awt/FontStrikeout.hpp>
74 : #include <com/sun/star/awt/FontSlant.hpp>
75 : #include <wrong.hxx>
76 : #include <editeng/brushitem.hxx>
77 : #include <swatrset.hxx>
78 : #include <frmatr.hxx>
79 : #include <unosett.hxx>
80 : #include <paratr.hxx>
81 : #include <com/sun/star/container/XIndexReplace.hpp>
82 : #include <unomap.hxx>
83 : #include <unoprnms.hxx>
84 : #include <com/sun/star/text/WritingMode2.hpp>
85 : #include <viewimp.hxx>
86 : #include <boost/scoped_ptr.hpp>
87 : #include <textmarkuphelper.hxx>
88 : #include <parachangetrackinginfo.hxx>
89 : #include <com/sun/star/text/TextMarkupType.hpp>
90 : #include <comphelper/servicehelper.hxx>
91 : #include <cppuhelper/supportsservice.hxx>
92 :
93 : #include <reffld.hxx>
94 : #include <expfld.hxx>
95 : #include <flddat.hxx>
96 : #include <fldui.hrc>
97 : #include "../../uibase/inc/fldmgr.hxx"
98 : #include "fldbas.hxx" // SwField
99 :
100 : using namespace ::com::sun::star;
101 : using namespace ::com::sun::star::accessibility;
102 : using namespace ::com::sun::star::container;
103 :
104 : using beans::PropertyValue;
105 : using beans::XMultiPropertySet;
106 : using beans::UnknownPropertyException;
107 : using beans::PropertyState_DIRECT_VALUE;
108 :
109 : using std::max;
110 : using std::min;
111 : using std::sort;
112 :
113 : namespace com { namespace sun { namespace star {
114 : namespace text {
115 : class XText;
116 : }
117 : } } }
118 :
119 : const sal_Char sServiceName[] = "com.sun.star.text.AccessibleParagraphView";
120 : const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleParagraphView";
121 :
122 282 : const SwTextNode* SwAccessibleParagraph::GetTextNode() const
123 : {
124 282 : const SwFrm* pFrm = GetFrm();
125 : OSL_ENSURE( pFrm->IsTextFrm(), "The text frame has mutated!" );
126 :
127 282 : const SwTextNode* pNode = static_cast<const SwTextFrm*>(pFrm)->GetTextNode();
128 : OSL_ENSURE( pNode != NULL, "A text frame without a text node." );
129 :
130 282 : return pNode;
131 : }
132 :
133 34 : OUString SwAccessibleParagraph::GetString()
134 : {
135 34 : return GetPortionData().GetAccessibleString();
136 : }
137 :
138 13 : OUString SwAccessibleParagraph::GetDescription()
139 : {
140 13 : return OUString(); // provide empty description for paragraphs
141 : }
142 :
143 123 : sal_Int32 SwAccessibleParagraph::GetCaretPos()
144 : {
145 123 : sal_Int32 nRet = -1;
146 :
147 : // get the selection's point, and test whether it's in our node
148 : // #i27301# - consider adjusted method signature
149 123 : SwPaM* pCaret = GetCursor( false ); // caret is first PaM in PaM-ring
150 :
151 123 : if( pCaret != NULL )
152 : {
153 99 : const SwTextNode* pNode = GetTextNode();
154 :
155 : // check whether the point points into 'our' node
156 99 : SwPosition* pPoint = pCaret->GetPoint();
157 99 : if( pNode->GetIndex() == pPoint->nNode.GetIndex() )
158 : {
159 : // same node? Then check whether it's also within 'our' part
160 : // of the paragraph
161 79 : const sal_Int32 nIndex = pPoint->nContent.GetIndex();
162 211 : if(!GetPortionData().IsValidCorePosition( nIndex ) ||
163 132 : ( GetPortionData().IsZeroCorePositionData() && nIndex== 0) )
164 : {
165 53 : const SwTextFrm *pTextFrm = PTR_CAST( SwTextFrm, GetFrm() );
166 53 : bool bFormat = (pTextFrm && pTextFrm->HasPara());
167 53 : if(bFormat)
168 : {
169 31 : ClearPortionData();
170 31 : UpdatePortionData();
171 : }
172 : }
173 79 : if( GetPortionData().IsValidCorePosition( nIndex ) )
174 : {
175 : // Yes, it's us!
176 : // consider that cursor/caret is in front of the list label
177 79 : if ( pCaret->IsInFrontOfLabel() )
178 : {
179 0 : nRet = 0;
180 : }
181 : else
182 : {
183 79 : nRet = GetPortionData().GetAccessiblePosition( nIndex );
184 : }
185 :
186 : OSL_ENSURE( nRet >= 0, "invalid cursor?" );
187 : OSL_ENSURE( nRet <= GetPortionData().GetAccessibleString().
188 : getLength(), "invalid cursor?" );
189 : }
190 : // else: in this paragraph, but in different frame
191 : }
192 : // else: not in this paragraph
193 : }
194 : // else: no cursor -> no caret
195 :
196 123 : return nRet;
197 : }
198 :
199 3 : bool SwAccessibleParagraph::GetSelection(
200 : sal_Int32& nStart, sal_Int32& nEnd)
201 : {
202 3 : bool bRet = false;
203 3 : nStart = -1;
204 3 : nEnd = -1;
205 :
206 : // get the selection, and test whether it affects our text node
207 3 : SwPaM* pCrsr = GetCursor( true ); // #i27301# - consider adjusted method signature
208 3 : if( pCrsr != NULL )
209 : {
210 : // get SwPosition for my node
211 3 : const SwTextNode* pNode = GetTextNode();
212 3 : sal_uLong nHere = pNode->GetIndex();
213 :
214 : // iterate over ring
215 6 : for(SwPaM& rTmpCrsr : pCrsr->GetRingContainer())
216 : {
217 : // ignore, if no mark
218 3 : if( rTmpCrsr.HasMark() )
219 : {
220 : // check whether nHere is 'inside' pCrsr
221 0 : SwPosition* pStart = rTmpCrsr.Start();
222 0 : sal_uLong nStartIndex = pStart->nNode.GetIndex();
223 0 : SwPosition* pEnd = rTmpCrsr.End();
224 0 : sal_uLong nEndIndex = pEnd->nNode.GetIndex();
225 0 : if( ( nHere >= nStartIndex ) &&
226 : ( nHere <= nEndIndex ) )
227 : {
228 : // translate start and end positions
229 :
230 : // start position
231 0 : sal_Int32 nLocalStart = -1;
232 0 : if( nHere > nStartIndex )
233 : {
234 : // selection starts in previous node:
235 : // then our local selection starts with the paragraph
236 0 : nLocalStart = 0;
237 : }
238 : else
239 : {
240 : OSL_ENSURE( nHere == nStartIndex,
241 : "miscalculated index" );
242 :
243 : // selection starts in this node:
244 : // then check whether it's before or inside our part of
245 : // the paragraph, and if so, get the proper position
246 0 : const sal_Int32 nCoreStart = pStart->nContent.GetIndex();
247 0 : if( nCoreStart <
248 0 : GetPortionData().GetFirstValidCorePosition() )
249 : {
250 0 : nLocalStart = 0;
251 : }
252 0 : else if( nCoreStart <=
253 0 : GetPortionData().GetLastValidCorePosition() )
254 : {
255 : OSL_ENSURE(
256 : GetPortionData().IsValidCorePosition(
257 : nCoreStart ),
258 : "problem determining valid core position" );
259 :
260 : nLocalStart =
261 0 : GetPortionData().GetAccessiblePosition(
262 0 : nCoreStart );
263 : }
264 : }
265 :
266 : // end position
267 0 : sal_Int32 nLocalEnd = -1;
268 0 : if( nHere < nEndIndex )
269 : {
270 : // selection ends in following node:
271 : // then our local selection extends to the end
272 0 : nLocalEnd = GetPortionData().GetAccessibleString().
273 0 : getLength();
274 : }
275 : else
276 : {
277 : OSL_ENSURE( nHere == nEndIndex,
278 : "miscalculated index" );
279 :
280 : // selection ends in this node: then select everything
281 : // before our part of the node
282 0 : const sal_Int32 nCoreEnd = pEnd->nContent.GetIndex();
283 0 : if( nCoreEnd >
284 0 : GetPortionData().GetLastValidCorePosition() )
285 : {
286 : // selection extends beyond out part of this para
287 0 : nLocalEnd = GetPortionData().GetAccessibleString().
288 0 : getLength();
289 : }
290 0 : else if( nCoreEnd >=
291 0 : GetPortionData().GetFirstValidCorePosition() )
292 : {
293 : // selection is inside our part of this para
294 : OSL_ENSURE(
295 : GetPortionData().IsValidCorePosition(
296 : nCoreEnd ),
297 : "problem determining valid core position" );
298 :
299 0 : nLocalEnd = GetPortionData().GetAccessiblePosition(
300 0 : nCoreEnd );
301 : }
302 : }
303 :
304 0 : if( ( nLocalStart != -1 ) && ( nLocalEnd != -1 ) )
305 : {
306 0 : nStart = nLocalStart;
307 0 : nEnd = nLocalEnd;
308 0 : bRet = true;
309 : }
310 : }
311 : // else: this PaM doesn't point to this paragraph
312 : }
313 : // else: this PaM is collapsed and doesn't select anything
314 3 : if(bRet)
315 0 : break;
316 : }
317 : // else: nocursor -> no selection
318 : }
319 3 : return bRet;
320 : }
321 :
322 : // #i27301# - new parameter <_bForSelection>
323 149 : SwPaM* SwAccessibleParagraph::GetCursor( const bool _bForSelection )
324 : {
325 : // get the cursor shell; if we don't have any, we don't have a
326 : // cursor/selection either
327 149 : SwPaM* pCrsr = NULL;
328 149 : SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell();
329 : // #i27301# - if cursor is retrieved for selection, the cursors for
330 : // a table selection has to be returned.
331 273 : if ( pCrsrShell != NULL &&
332 146 : ( _bForSelection || !pCrsrShell->IsTableMode() ) )
333 : {
334 124 : SwFEShell *pFESh = pCrsrShell->ISA( SwFEShell )
335 124 : ? static_cast< SwFEShell * >( pCrsrShell ) : 0;
336 372 : if( !pFESh ||
337 248 : !(pFESh->IsFrmSelected() || pFESh->IsObjSelected() > 0) )
338 : {
339 : // get the selection, and test whether it affects our text node
340 124 : pCrsr = pCrsrShell->GetCrsr( false /* ??? */ );
341 : }
342 : }
343 :
344 149 : return pCrsr;
345 : }
346 :
347 79 : bool SwAccessibleParagraph::IsHeading() const
348 : {
349 79 : const SwTextNode *pTextNd = GetTextNode();
350 79 : return pTextNd->IsOutline();
351 : }
352 :
353 22 : void SwAccessibleParagraph::GetStates(
354 : ::utl::AccessibleStateSetHelper& rStateSet )
355 : {
356 22 : SwAccessibleContext::GetStates( rStateSet );
357 :
358 : // MULTILINE
359 22 : rStateSet.AddState( AccessibleStateType::MULTI_LINE );
360 :
361 : // MULTISELECTABLE
362 22 : SwCrsrShell *pCrsrSh = GetCrsrShell();
363 22 : if( pCrsrSh )
364 22 : rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
365 :
366 : // FOCUSABLE
367 22 : if( pCrsrSh )
368 22 : rStateSet.AddState( AccessibleStateType::FOCUSABLE );
369 :
370 : // FOCUSED (simulates node index of cursor)
371 22 : SwPaM* pCaret = GetCursor( false ); // #i27301# - consider adjusted method signature
372 22 : const SwTextNode* pTextNd = GetTextNode();
373 64 : if( pCaret != 0 && pTextNd != 0 &&
374 63 : pTextNd->GetIndex() == pCaret->GetPoint()->nNode.GetIndex() &&
375 20 : nOldCaretPos != -1)
376 : {
377 20 : vcl::Window *pWin = GetWindow();
378 20 : if( pWin && pWin->HasFocus() )
379 16 : rStateSet.AddState( AccessibleStateType::FOCUSED );
380 20 : ::rtl::Reference < SwAccessibleContext > xThis( this );
381 20 : GetMap()->SetCursorContext( xThis );
382 : }
383 22 : }
384 :
385 14 : void SwAccessibleParagraph::_InvalidateContent( bool bVisibleDataFired )
386 : {
387 14 : OUString sOldText( GetString() );
388 :
389 14 : ClearPortionData();
390 :
391 28 : const OUString& rText = GetString();
392 :
393 14 : if( rText != sOldText )
394 : {
395 : // The text is changed
396 0 : AccessibleEventObject aEvent;
397 0 : aEvent.EventId = AccessibleEventId::TEXT_CHANGED;
398 :
399 : // determine exact changes between sOldText and rText
400 : comphelper::OCommonAccessibleText::implInitTextChangedEvent(
401 : sOldText, rText,
402 0 : aEvent.OldValue, aEvent.NewValue );
403 :
404 0 : FireAccessibleEvent( aEvent );
405 0 : uno::Reference< XAccessible > xparent = getAccessibleParent();
406 0 : uno::Reference< XAccessibleContext > xAccContext(xparent,uno::UNO_QUERY);
407 0 : if (xAccContext.is() && xAccContext->getAccessibleRole() == AccessibleRole::TABLE_CELL)
408 : {
409 0 : SwAccessibleContext* pPara = static_cast< SwAccessibleContext* >(xparent.get());
410 0 : if(pPara)
411 : {
412 0 : AccessibleEventObject aParaEvent;
413 0 : aParaEvent.EventId = AccessibleEventId::VALUE_CHANGED;
414 0 : pPara->FireAccessibleEvent(aParaEvent);
415 : }
416 0 : }
417 : }
418 14 : else if( !bVisibleDataFired )
419 : {
420 0 : FireVisibleDataEvent();
421 : }
422 :
423 14 : bool bNewIsHeading = IsHeading();
424 : //Get the real heading level, Heading1 ~ Heading10
425 14 : nHeadingLevel = GetRealHeadingLevel();
426 : bool bOldIsHeading;
427 : {
428 14 : osl::MutexGuard aGuard( m_Mutex );
429 14 : bOldIsHeading = bIsHeading;
430 14 : if( bIsHeading != bNewIsHeading )
431 0 : bIsHeading = bNewIsHeading;
432 : }
433 :
434 14 : if( bNewIsHeading != bOldIsHeading )
435 : {
436 : // The role has changed
437 0 : AccessibleEventObject aEvent;
438 0 : aEvent.EventId = AccessibleEventId::ROLE_CHANGED;
439 :
440 0 : FireAccessibleEvent( aEvent );
441 : }
442 :
443 14 : if( rText != sOldText )
444 : {
445 0 : OUString sNewDesc( GetDescription() );
446 0 : OUString sOldDesc;
447 : {
448 0 : osl::MutexGuard aGuard( m_Mutex );
449 0 : sOldDesc = sDesc;
450 0 : if( sDesc != sNewDesc )
451 0 : sDesc = sNewDesc;
452 : }
453 :
454 0 : if( sNewDesc != sOldDesc )
455 : {
456 : // The text is changed
457 0 : AccessibleEventObject aEvent;
458 0 : aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
459 0 : aEvent.OldValue <<= sOldDesc;
460 0 : aEvent.NewValue <<= sNewDesc;
461 :
462 0 : FireAccessibleEvent( aEvent );
463 0 : }
464 14 : }
465 14 : }
466 :
467 58 : void SwAccessibleParagraph::_InvalidateCursorPos()
468 : {
469 : // The text is changed
470 58 : sal_Int32 nNew = GetCaretPos();
471 : sal_Int32 nOld;
472 : {
473 58 : osl::MutexGuard aGuard( m_Mutex );
474 58 : nOld = nOldCaretPos;
475 58 : nOldCaretPos = nNew;
476 : }
477 58 : if( -1 != nNew )
478 : {
479 : // remember that object as the one that has the caret. This is
480 : // necessary to notify that object if the cursor leaves it.
481 57 : ::rtl::Reference < SwAccessibleContext > xThis( this );
482 57 : GetMap()->SetCursorContext( xThis );
483 : }
484 :
485 58 : vcl::Window *pWin = GetWindow();
486 58 : if( nOld != nNew )
487 : {
488 : // The cursor's node position is simulated by the focus!
489 3 : if( pWin && pWin->HasFocus() && -1 == nOld )
490 1 : FireStateChangedEvent( AccessibleStateType::FOCUSED, true );
491 :
492 3 : AccessibleEventObject aEvent;
493 3 : aEvent.EventId = AccessibleEventId::CARET_CHANGED;
494 3 : aEvent.OldValue <<= nOld;
495 3 : aEvent.NewValue <<= nNew;
496 :
497 3 : FireAccessibleEvent( aEvent );
498 :
499 3 : if( pWin && pWin->HasFocus() && -1 == nNew )
500 0 : FireStateChangedEvent( AccessibleStateType::FOCUSED, false );
501 : //To send TEXT_SELECTION_CHANGED event
502 3 : sal_Int32 nStart=0;
503 3 : sal_Int32 nEnd =0;
504 3 : bool bCurSelection=GetSelection(nStart,nEnd);
505 3 : if(m_bLastHasSelection || bCurSelection )
506 : {
507 0 : aEvent.EventId = AccessibleEventId::TEXT_SELECTION_CHANGED;
508 0 : aEvent.OldValue <<= uno::Any();
509 0 : aEvent.NewValue <<= uno::Any();
510 0 : FireAccessibleEvent(aEvent);
511 : }
512 3 : m_bLastHasSelection =bCurSelection;
513 : }
514 58 : }
515 :
516 5 : void SwAccessibleParagraph::_InvalidateFocus()
517 : {
518 5 : vcl::Window *pWin = GetWindow();
519 5 : if( pWin )
520 : {
521 : sal_Int32 nPos;
522 : {
523 5 : osl::MutexGuard aGuard( m_Mutex );
524 5 : nPos = nOldCaretPos;
525 : }
526 : OSL_ENSURE( nPos != -1, "focus object should be selected" );
527 :
528 : FireStateChangedEvent( AccessibleStateType::FOCUSED,
529 5 : pWin->HasFocus() && nPos != -1 );
530 : }
531 5 : }
532 :
533 65 : SwAccessibleParagraph::SwAccessibleParagraph(
534 : SwAccessibleMap& rInitMap,
535 : const SwTextFrm& rTextFrm )
536 65 : : SwClient( const_cast<SwTextNode*>(rTextFrm.GetTextNode()) ) // #i108125#
537 : , SwAccessibleContext( &rInitMap, AccessibleRole::PARAGRAPH, &rTextFrm )
538 : , sDesc()
539 : , pPortionData( NULL )
540 : , pHyperTextData( NULL )
541 : , nOldCaretPos( -1 )
542 : , bIsHeading( false )
543 : //Get the real heading level, Heading1 ~ Heading10
544 : , nHeadingLevel (-1)
545 : , aSelectionHelper( *this )
546 65 : , mpParaChangeTrackInfo( new SwParaChangeTrackingInfo( rTextFrm ) ) // #i108125#
547 130 : , m_bLastHasSelection(false) //To add TEXT_SELECTION_CHANGED event
548 : {
549 65 : SolarMutexGuard aGuard;
550 :
551 65 : bIsHeading = IsHeading();
552 : //Get the real heading level, Heading1 ~ Heading10
553 65 : nHeadingLevel = GetRealHeadingLevel();
554 65 : SetName( OUString() ); // set an empty accessibility name for paragraphs
555 :
556 : // If this object has the focus, then it is remembered by the map itself.
557 65 : nOldCaretPos = GetCaretPos();
558 65 : }
559 :
560 195 : SwAccessibleParagraph::~SwAccessibleParagraph()
561 : {
562 65 : SolarMutexGuard aGuard;
563 :
564 65 : delete pPortionData;
565 65 : delete pHyperTextData;
566 65 : delete mpParaChangeTrackInfo; // #i108125#
567 130 : }
568 :
569 79 : bool SwAccessibleParagraph::HasCursor()
570 : {
571 79 : osl::MutexGuard aGuard( m_Mutex );
572 79 : return nOldCaretPos != -1;
573 : }
574 :
575 110 : void SwAccessibleParagraph::UpdatePortionData()
576 : throw( uno::RuntimeException )
577 : {
578 : // obtain the text frame
579 : OSL_ENSURE( GetFrm() != NULL, "The text frame has vanished!" );
580 : OSL_ENSURE( GetFrm()->IsTextFrm(), "The text frame has mutated!" );
581 110 : const SwTextFrm* pFrm = static_cast<const SwTextFrm*>( GetFrm() );
582 :
583 : // build new portion data
584 110 : delete pPortionData;
585 : pPortionData = new SwAccessiblePortionData(
586 110 : pFrm->GetTextNode(), GetMap()->GetShell()->GetViewOptions() );
587 110 : pFrm->VisitPortions( *pPortionData );
588 :
589 : OSL_ENSURE( pPortionData != NULL, "UpdatePortionData() failed" );
590 110 : }
591 :
592 45 : void SwAccessibleParagraph::ClearPortionData()
593 : {
594 45 : delete pPortionData;
595 45 : pPortionData = NULL;
596 :
597 45 : delete pHyperTextData;
598 45 : pHyperTextData = 0;
599 45 : }
600 :
601 0 : void SwAccessibleParagraph::ExecuteAtViewShell( sal_uInt16 nSlot )
602 : {
603 : OSL_ENSURE( GetMap() != NULL, "no map?" );
604 0 : SwViewShell* pViewShell = GetMap()->GetShell();
605 :
606 : OSL_ENSURE( pViewShell != NULL, "View shell expected!" );
607 0 : SfxViewShell* pSfxShell = pViewShell->GetSfxViewShell();
608 :
609 : OSL_ENSURE( pSfxShell != NULL, "SfxViewShell shell expected!" );
610 0 : if( !pSfxShell )
611 0 : return;
612 :
613 0 : SfxViewFrame *pFrame = pSfxShell->GetViewFrame();
614 : OSL_ENSURE( pFrame != NULL, "View frame expected!" );
615 0 : if( !pFrame )
616 0 : return;
617 :
618 0 : SfxDispatcher *pDispatcher = pFrame->GetDispatcher();
619 : OSL_ENSURE( pDispatcher != NULL, "Dispatcher expected!" );
620 0 : if( !pDispatcher )
621 0 : return;
622 :
623 0 : pDispatcher->Execute( nSlot );
624 : }
625 :
626 79 : SwXTextPortion* SwAccessibleParagraph::CreateUnoPortion(
627 : sal_Int32 nStartIndex,
628 : sal_Int32 nEndIndex )
629 : {
630 : OSL_ENSURE( (IsValidChar(nStartIndex, GetString().getLength()) &&
631 : (nEndIndex == -1)) ||
632 : IsValidRange(nStartIndex, nEndIndex, GetString().getLength()),
633 : "please check parameters before calling this method" );
634 :
635 79 : const sal_Int32 nStart = GetPortionData().GetModelPosition( nStartIndex );
636 : const sal_Int32 nEnd = (nEndIndex == -1) ? (nStart + 1) :
637 79 : GetPortionData().GetModelPosition( nEndIndex );
638 :
639 : // create UNO cursor
640 79 : SwTextNode* pTextNode = const_cast<SwTextNode*>( GetTextNode() );
641 79 : SwIndex aIndex( pTextNode, nStart );
642 158 : SwPosition aStartPos( *pTextNode, aIndex );
643 158 : auto pUnoCursor(pTextNode->GetDoc()->CreateUnoCrsr( aStartPos ));
644 79 : pUnoCursor->SetMark();
645 79 : pUnoCursor->GetMark()->nContent = nEnd;
646 :
647 : // create a (dummy) text portion to be returned
648 158 : uno::Reference<text::XText> aEmpty;
649 : SwXTextPortion* pPortion =
650 79 : new SwXTextPortion ( pUnoCursor.get(), aEmpty, PORTION_TEXT);
651 :
652 158 : return pPortion;
653 : }
654 :
655 : // range checking for parameter
656 :
657 0 : bool SwAccessibleParagraph::IsValidChar(
658 : sal_Int32 nPos, sal_Int32 nLength)
659 : {
660 0 : return (nPos >= 0) && (nPos < nLength);
661 : }
662 :
663 0 : bool SwAccessibleParagraph::IsValidPosition(
664 : sal_Int32 nPos, sal_Int32 nLength)
665 : {
666 0 : return (nPos >= 0) && (nPos <= nLength);
667 : }
668 :
669 0 : bool SwAccessibleParagraph::IsValidRange(
670 : sal_Int32 nBegin, sal_Int32 nEnd, sal_Int32 nLength)
671 : {
672 0 : return IsValidPosition(nBegin, nLength) && IsValidPosition(nEnd, nLength);
673 : }
674 :
675 0 : SwTOXSortTabBase* SwAccessibleParagraph::GetTOXSortTabBase()
676 : {
677 0 : const SwTextNode* pTextNd = GetTextNode();
678 0 : if( pTextNd )
679 : {
680 0 : const SwSectionNode * pSectNd = pTextNd->FindSectionNode();
681 0 : if( pSectNd )
682 : {
683 0 : const SwSection * pSect = &pSectNd->GetSection();
684 0 : const SwTOXBaseSection *pTOXBaseSect = static_cast<const SwTOXBaseSection *>(pSect);
685 0 : if( pSect->GetType() == TOX_CONTENT_SECTION )
686 : {
687 0 : SwTOXSortTabBase* pSortBase = 0;
688 0 : size_t nSize = pTOXBaseSect->GetTOXSortTabBases().size();
689 :
690 0 : for(size_t nIndex = 0; nIndex<nSize; nIndex++ )
691 : {
692 0 : pSortBase = pTOXBaseSect->GetTOXSortTabBases()[nIndex];
693 0 : if( pSortBase->pTOXNd == pTextNd )
694 0 : break;
695 : }
696 :
697 0 : if (pSortBase)
698 : {
699 0 : return pSortBase;
700 : }
701 : }
702 : }
703 : }
704 0 : return NULL;
705 : }
706 :
707 : //the function is to check whether the position is in a redline range.
708 0 : const SwRangeRedline* SwAccessibleParagraph::GetRedlineAtIndex( sal_Int32 )
709 : {
710 0 : const SwRangeRedline* pRedline = NULL;
711 0 : SwPaM* pCrSr = GetCursor( true );
712 0 : if ( pCrSr )
713 : {
714 0 : SwPosition* pStart = pCrSr->Start();
715 0 : const SwTextNode* pNode = GetTextNode();
716 0 : if ( pNode )
717 : {
718 0 : const SwDoc* pDoc = pNode->GetDoc();
719 0 : if ( pDoc )
720 : {
721 0 : pRedline = pDoc->getIDocumentRedlineAccess().GetRedline( *pStart, NULL );
722 : }
723 : }
724 : }
725 :
726 0 : return pRedline;
727 : }
728 :
729 : // text boundaries
730 :
731 0 : bool SwAccessibleParagraph::GetCharBoundary(
732 : i18n::Boundary& rBound,
733 : const OUString&,
734 : sal_Int32 nPos )
735 : {
736 0 : if( GetPortionData().FillBoundaryIFDateField( rBound, nPos) )
737 0 : return true;
738 :
739 0 : rBound.startPos = nPos;
740 0 : rBound.endPos = nPos+1;
741 0 : return true;
742 : }
743 :
744 0 : bool SwAccessibleParagraph::GetWordBoundary(
745 : i18n::Boundary& rBound,
746 : const OUString& rText,
747 : sal_Int32 nPos )
748 : {
749 0 : bool bRet = false;
750 :
751 : // now ask the Break-Iterator for the word
752 : OSL_ENSURE( g_pBreakIt != NULL, "We always need a break." );
753 : OSL_ENSURE( g_pBreakIt->GetBreakIter().is(), "No break-iterator." );
754 0 : if( g_pBreakIt->GetBreakIter().is() )
755 : {
756 : // get locale for this position
757 0 : const sal_Int32 nModelPos = GetPortionData().GetModelPosition( nPos );
758 : lang::Locale aLocale = g_pBreakIt->GetLocale(
759 0 : GetTextNode()->GetLang( nModelPos ) );
760 :
761 : // which type of word are we interested in?
762 : // (DICTIONARY_WORD includes punctuation, ANY_WORD doesn't.)
763 0 : const sal_Int16 nWordType = i18n::WordType::ANY_WORD;
764 :
765 : // get word boundary, as the Break-Iterator sees fit.
766 0 : rBound = g_pBreakIt->GetBreakIter()->getWordBoundary(
767 0 : rText, nPos, aLocale, nWordType, sal_True );
768 :
769 : // It's a word if the first character is an alpha-numeric character.
770 0 : bRet = GetAppCharClass().isLetterNumeric(
771 0 : OUString(rText[rBound.startPos]) );
772 : }
773 : else
774 : {
775 : // no break Iterator -> no word
776 0 : rBound.startPos = nPos;
777 0 : rBound.endPos = nPos;
778 : }
779 :
780 0 : return bRet;
781 : }
782 :
783 0 : bool SwAccessibleParagraph::GetSentenceBoundary(
784 : i18n::Boundary& rBound,
785 : const OUString& rText,
786 : sal_Int32 nPos )
787 : {
788 0 : const sal_Unicode* pStr = rText.getStr();
789 0 : if (pStr)
790 : {
791 0 : while( pStr[nPos] == sal_Unicode(' ') && nPos < rText.getLength())
792 0 : nPos++;
793 : }
794 :
795 0 : GetPortionData().GetSentenceBoundary( rBound, nPos );
796 0 : return true;
797 : }
798 :
799 0 : bool SwAccessibleParagraph::GetLineBoundary(
800 : i18n::Boundary& rBound,
801 : const OUString& rText,
802 : sal_Int32 nPos )
803 : {
804 0 : if( rText.getLength() == nPos )
805 0 : GetPortionData().GetLastLineBoundary( rBound );
806 : else
807 0 : GetPortionData().GetLineBoundary( rBound, nPos );
808 0 : return true;
809 : }
810 :
811 0 : bool SwAccessibleParagraph::GetParagraphBoundary(
812 : i18n::Boundary& rBound,
813 : const OUString& rText,
814 : sal_Int32 )
815 : {
816 0 : rBound.startPos = 0;
817 0 : rBound.endPos = rText.getLength();
818 0 : return true;
819 : }
820 :
821 0 : bool SwAccessibleParagraph::GetAttributeBoundary(
822 : i18n::Boundary& rBound,
823 : const OUString&,
824 : sal_Int32 nPos )
825 : {
826 0 : GetPortionData().GetAttributeBoundary( rBound, nPos );
827 0 : return true;
828 : }
829 :
830 0 : bool SwAccessibleParagraph::GetGlyphBoundary(
831 : i18n::Boundary& rBound,
832 : const OUString& rText,
833 : sal_Int32 nPos )
834 : {
835 0 : bool bRet = false;
836 :
837 : // ask the Break-Iterator for the glyph by moving one cell
838 : // forward, and then one cell back
839 : OSL_ENSURE( g_pBreakIt != NULL, "We always need a break." );
840 : OSL_ENSURE( g_pBreakIt->GetBreakIter().is(), "No break-iterator." );
841 0 : if( g_pBreakIt->GetBreakIter().is() )
842 : {
843 : // get locale for this position
844 0 : const sal_Int32 nModelPos = GetPortionData().GetModelPosition( nPos );
845 : lang::Locale aLocale = g_pBreakIt->GetLocale(
846 0 : GetTextNode()->GetLang( nModelPos ) );
847 :
848 : // get word boundary, as the Break-Iterator sees fit.
849 0 : const sal_Int16 nIterMode = i18n::CharacterIteratorMode::SKIPCELL;
850 0 : sal_Int32 nDone = 0;
851 0 : rBound.endPos = g_pBreakIt->GetBreakIter()->nextCharacters(
852 0 : rText, nPos, aLocale, nIterMode, 1, nDone );
853 0 : rBound.startPos = g_pBreakIt->GetBreakIter()->previousCharacters(
854 0 : rText, rBound.endPos, aLocale, nIterMode, 1, nDone );
855 0 : bRet = ((rBound.startPos <= nPos) && (nPos <= rBound.endPos));
856 : OSL_ENSURE( rBound.startPos <= nPos, "start pos too high" );
857 0 : OSL_ENSURE( rBound.endPos >= nPos, "end pos too low" );
858 : }
859 : else
860 : {
861 : // no break Iterator -> no glyph
862 0 : rBound.startPos = nPos;
863 0 : rBound.endPos = nPos;
864 : }
865 :
866 0 : return bRet;
867 : }
868 :
869 0 : bool SwAccessibleParagraph::GetTextBoundary(
870 : i18n::Boundary& rBound,
871 : const OUString& rText,
872 : sal_Int32 nPos,
873 : sal_Int16 nTextType )
874 : throw (
875 : lang::IndexOutOfBoundsException,
876 : lang::IllegalArgumentException,
877 : uno::RuntimeException)
878 : {
879 : // error checking
880 0 : if( !( AccessibleTextType::LINE == nTextType
881 0 : ? IsValidPosition( nPos, rText.getLength() )
882 0 : : IsValidChar( nPos, rText.getLength() ) ) )
883 0 : throw lang::IndexOutOfBoundsException();
884 :
885 : bool bRet;
886 :
887 0 : switch( nTextType )
888 : {
889 : case AccessibleTextType::WORD:
890 0 : bRet = GetWordBoundary( rBound, rText, nPos );
891 0 : break;
892 :
893 : case AccessibleTextType::SENTENCE:
894 0 : bRet = GetSentenceBoundary( rBound, rText, nPos );
895 0 : break;
896 :
897 : case AccessibleTextType::PARAGRAPH:
898 0 : bRet = GetParagraphBoundary( rBound, rText, nPos );
899 0 : break;
900 :
901 : case AccessibleTextType::CHARACTER:
902 0 : bRet = GetCharBoundary( rBound, rText, nPos );
903 0 : break;
904 :
905 : case AccessibleTextType::LINE:
906 : //Solve the problem of returning wrong LINE and PARAGRAPH
907 0 : if((nPos == rText.getLength()) && nPos > 0)
908 0 : bRet = GetLineBoundary( rBound, rText, nPos - 1);
909 : else
910 0 : bRet = GetLineBoundary( rBound, rText, nPos );
911 0 : break;
912 :
913 : case AccessibleTextType::ATTRIBUTE_RUN:
914 0 : bRet = GetAttributeBoundary( rBound, rText, nPos );
915 0 : break;
916 :
917 : case AccessibleTextType::GLYPH:
918 0 : bRet = GetGlyphBoundary( rBound, rText, nPos );
919 0 : break;
920 :
921 : default:
922 0 : throw lang::IllegalArgumentException( );
923 : }
924 :
925 0 : return bRet;
926 : }
927 :
928 13 : OUString SAL_CALL SwAccessibleParagraph::getAccessibleDescription()
929 : throw (uno::RuntimeException, std::exception)
930 : {
931 13 : SolarMutexGuard aGuard;
932 :
933 13 : CHECK_FOR_DEFUNC( XAccessibleContext );
934 :
935 26 : osl::MutexGuard aGuard2( m_Mutex );
936 13 : if( sDesc.isEmpty() )
937 13 : sDesc = GetDescription();
938 :
939 26 : return sDesc;
940 : }
941 :
942 1 : lang::Locale SAL_CALL SwAccessibleParagraph::getLocale()
943 : throw (IllegalAccessibleComponentStateException, uno::RuntimeException, std::exception)
944 : {
945 1 : SolarMutexGuard aGuard;
946 :
947 1 : const SwTextFrm *pTextFrm = PTR_CAST( SwTextFrm, GetFrm() );
948 1 : if( !pTextFrm )
949 : {
950 0 : THROW_RUNTIME_EXCEPTION( XAccessibleContext, "internal error (no text frame)" );
951 : }
952 :
953 1 : const SwTextNode *pTextNd = pTextFrm->GetTextNode();
954 1 : lang::Locale aLoc( g_pBreakIt->GetLocale( pTextNd->GetLang( 0 ) ) );
955 :
956 1 : return aLoc;
957 : }
958 :
959 : // #i27138# - paragraphs are in relation CONTENT_FLOWS_FROM and/or CONTENT_FLOWS_TO
960 3 : uno::Reference<XAccessibleRelationSet> SAL_CALL SwAccessibleParagraph::getAccessibleRelationSet()
961 : throw ( uno::RuntimeException, std::exception )
962 : {
963 3 : SolarMutexGuard aGuard;
964 3 : CHECK_FOR_DEFUNC( XAccessibleContext );
965 :
966 3 : utl::AccessibleRelationSetHelper* pHelper = new utl::AccessibleRelationSetHelper();
967 :
968 3 : const SwTextFrm* pTextFrm = dynamic_cast<const SwTextFrm*>(GetFrm());
969 : OSL_ENSURE( pTextFrm,
970 : "<SwAccessibleParagraph::getAccessibleRelationSet()> - missing text frame");
971 3 : if ( pTextFrm )
972 : {
973 3 : const SwContentFrm* pPrevCntFrm( pTextFrm->FindPrevCnt( true ) );
974 3 : if ( pPrevCntFrm )
975 : {
976 1 : uno::Sequence< uno::Reference<XInterface> > aSequence(1);
977 1 : aSequence[0] = GetMap()->GetContext( pPrevCntFrm );
978 : AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_FROM,
979 2 : aSequence );
980 2 : pHelper->AddRelation( aAccRel );
981 : }
982 :
983 3 : const SwContentFrm* pNextCntFrm( pTextFrm->FindNextCnt( true ) );
984 3 : if ( pNextCntFrm )
985 : {
986 2 : uno::Sequence< uno::Reference<XInterface> > aSequence(1);
987 2 : aSequence[0] = GetMap()->GetContext( pNextCntFrm );
988 : AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_TO,
989 4 : aSequence );
990 4 : pHelper->AddRelation( aAccRel );
991 : }
992 : }
993 :
994 3 : return pHelper;
995 : }
996 :
997 1 : void SAL_CALL SwAccessibleParagraph::grabFocus()
998 : throw (uno::RuntimeException, std::exception)
999 : {
1000 1 : SolarMutexGuard aGuard;
1001 :
1002 1 : CHECK_FOR_DEFUNC( XAccessibleContext );
1003 :
1004 : // get cursor shell
1005 1 : SwCrsrShell *pCrsrSh = GetCrsrShell();
1006 1 : SwPaM *pCrsr = GetCursor( false ); // #i27301# - consider new method signature
1007 1 : const SwTextFrm *pTextFrm = static_cast<const SwTextFrm*>( GetFrm() );
1008 1 : const SwTextNode* pTextNd = pTextFrm->GetTextNode();
1009 :
1010 1 : if( pCrsrSh != 0 && pTextNd != 0 &&
1011 1 : ( pCrsr == 0 ||
1012 2 : pCrsr->GetPoint()->nNode.GetIndex() != pTextNd->GetIndex() ||
1013 1 : !pTextFrm->IsInside( pCrsr->GetPoint()->nContent.GetIndex()) ) )
1014 : {
1015 : // create pam for selection
1016 : SwIndex aIndex( const_cast< SwTextNode * >( pTextNd ),
1017 0 : pTextFrm->GetOfst() );
1018 0 : SwPosition aStartPos( *pTextNd, aIndex );
1019 0 : SwPaM aPaM( aStartPos );
1020 :
1021 : // set PaM at cursor shell
1022 0 : Select( aPaM );
1023 :
1024 : }
1025 :
1026 : // ->#i13955#
1027 1 : vcl::Window * pWindow = GetWindow();
1028 :
1029 1 : if (pWindow != NULL)
1030 1 : pWindow->GrabFocus();
1031 : // <-#i13955#
1032 1 : }
1033 :
1034 : // #i71385#
1035 2 : static bool lcl_GetBackgroundColor( Color & rColor,
1036 : const SwFrm* pFrm,
1037 : SwCrsrShell* pCrsrSh )
1038 : {
1039 2 : const SvxBrushItem* pBackgrdBrush = 0;
1040 2 : const Color* pSectionTOXColor = 0;
1041 2 : SwRect aDummyRect;
1042 :
1043 : //UUUU
1044 2 : drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes;
1045 :
1046 4 : if ( pFrm &&
1047 2 : pFrm->GetBackgroundBrush( aFillAttributes, pBackgrdBrush, pSectionTOXColor, aDummyRect, false ) )
1048 : {
1049 0 : if ( pSectionTOXColor )
1050 : {
1051 0 : rColor = *pSectionTOXColor;
1052 0 : return true;
1053 : }
1054 : else
1055 : {
1056 0 : rColor = pBackgrdBrush->GetColor();
1057 0 : return true;
1058 : }
1059 : }
1060 2 : else if ( pCrsrSh )
1061 : {
1062 2 : rColor = pCrsrSh->Imp()->GetRetoucheColor();
1063 2 : return true;
1064 : }
1065 :
1066 0 : return false;
1067 : }
1068 :
1069 1 : sal_Int32 SAL_CALL SwAccessibleParagraph::getForeground()
1070 : throw (uno::RuntimeException, std::exception)
1071 : {
1072 1 : Color aBackgroundCol;
1073 :
1074 1 : if ( lcl_GetBackgroundColor( aBackgroundCol, GetFrm(), GetCrsrShell() ) )
1075 : {
1076 1 : if ( aBackgroundCol.IsDark() )
1077 : {
1078 0 : return COL_WHITE;
1079 : }
1080 : else
1081 : {
1082 1 : return COL_BLACK;
1083 : }
1084 : }
1085 :
1086 0 : return SwAccessibleContext::getForeground();
1087 : }
1088 :
1089 1 : sal_Int32 SAL_CALL SwAccessibleParagraph::getBackground()
1090 : throw (uno::RuntimeException, std::exception)
1091 : {
1092 1 : Color aBackgroundCol;
1093 :
1094 1 : if ( lcl_GetBackgroundColor( aBackgroundCol, GetFrm(), GetCrsrShell() ) )
1095 : {
1096 1 : return aBackgroundCol.GetColor();
1097 : }
1098 :
1099 0 : return SwAccessibleContext::getBackground();
1100 : }
1101 :
1102 3 : OUString SAL_CALL SwAccessibleParagraph::getImplementationName()
1103 : throw( uno::RuntimeException, std::exception )
1104 : {
1105 3 : return OUString(sImplementationName);
1106 : }
1107 :
1108 0 : sal_Bool SAL_CALL SwAccessibleParagraph::supportsService(
1109 : const OUString& sTestServiceName)
1110 : throw (uno::RuntimeException, std::exception)
1111 : {
1112 0 : return cppu::supportsService(this, sTestServiceName);
1113 : }
1114 :
1115 0 : uno::Sequence< OUString > SAL_CALL SwAccessibleParagraph::getSupportedServiceNames()
1116 : throw( uno::RuntimeException, std::exception )
1117 : {
1118 0 : uno::Sequence< OUString > aRet(2);
1119 0 : OUString* pArray = aRet.getArray();
1120 0 : pArray[0] = sServiceName;
1121 0 : pArray[1] = sAccessibleServiceName;
1122 0 : return aRet;
1123 : }
1124 :
1125 0 : uno::Sequence< OUString > getAttributeNames()
1126 : {
1127 : static uno::Sequence< OUString >* pNames = NULL;
1128 :
1129 0 : if( pNames == NULL )
1130 : {
1131 : // Add the font name to attribute list
1132 0 : uno::Sequence< OUString >* pSeq = new uno::Sequence< OUString >( 13 );
1133 :
1134 0 : OUString* pStrings = pSeq->getArray();
1135 :
1136 : // sorted list of strings
1137 0 : sal_Int32 i = 0;
1138 :
1139 0 : pStrings[i++] = UNO_NAME_CHAR_BACK_COLOR;
1140 0 : pStrings[i++] = UNO_NAME_CHAR_COLOR;
1141 0 : pStrings[i++] = UNO_NAME_CHAR_CONTOURED;
1142 0 : pStrings[i++] = UNO_NAME_CHAR_EMPHASIS;
1143 0 : pStrings[i++] = UNO_NAME_CHAR_ESCAPEMENT;
1144 0 : pStrings[i++] = UNO_NAME_CHAR_FONT_NAME;
1145 0 : pStrings[i++] = UNO_NAME_CHAR_HEIGHT;
1146 0 : pStrings[i++] = UNO_NAME_CHAR_POSTURE;
1147 0 : pStrings[i++] = UNO_NAME_CHAR_SHADOWED;
1148 0 : pStrings[i++] = UNO_NAME_CHAR_STRIKEOUT;
1149 0 : pStrings[i++] = UNO_NAME_CHAR_UNDERLINE;
1150 0 : pStrings[i++] = UNO_NAME_CHAR_UNDERLINE_COLOR;
1151 0 : pStrings[i++] = UNO_NAME_CHAR_WEIGHT;
1152 : assert(i == pSeq->getLength());
1153 0 : pNames = pSeq;
1154 : }
1155 0 : return *pNames;
1156 : }
1157 :
1158 0 : uno::Sequence< OUString > getSupplementalAttributeNames()
1159 : {
1160 : static uno::Sequence< OUString >* pNames = NULL;
1161 :
1162 0 : if( pNames == NULL )
1163 : {
1164 0 : uno::Sequence< OUString >* pSeq = new uno::Sequence< OUString >( 9 );
1165 :
1166 0 : OUString* pStrings = pSeq->getArray();
1167 :
1168 : // sorted list of strings
1169 0 : sal_Int32 i = 0;
1170 :
1171 0 : pStrings[i++] = UNO_NAME_NUMBERING_LEVEL;
1172 0 : pStrings[i++] = UNO_NAME_NUMBERING_RULES;
1173 0 : pStrings[i++] = UNO_NAME_PARA_ADJUST;
1174 0 : pStrings[i++] = UNO_NAME_PARA_BOTTOM_MARGIN;
1175 0 : pStrings[i++] = UNO_NAME_PARA_FIRST_LINE_INDENT;
1176 0 : pStrings[i++] = UNO_NAME_PARA_LEFT_MARGIN;
1177 0 : pStrings[i++] = UNO_NAME_PARA_LINE_SPACING;
1178 0 : pStrings[i++] = UNO_NAME_PARA_RIGHT_MARGIN;
1179 0 : pStrings[i++] = UNO_NAME_TABSTOPS;
1180 : assert(i == pSeq->getLength());
1181 0 : pNames = pSeq;
1182 : }
1183 0 : return *pNames;
1184 : }
1185 :
1186 : // XInterface
1187 :
1188 652 : uno::Any SwAccessibleParagraph::queryInterface( const uno::Type& rType )
1189 : throw (uno::RuntimeException, std::exception)
1190 : {
1191 652 : uno::Any aRet;
1192 652 : if ( rType == cppu::UnoType<XAccessibleText>::get())
1193 : {
1194 3 : uno::Reference<XAccessibleText> aAccText = static_cast<XAccessibleText *>(*this); // resolve ambiguity
1195 3 : aRet <<= aAccText;
1196 : }
1197 649 : else if ( rType == cppu::UnoType<XAccessibleEditableText>::get())
1198 : {
1199 0 : uno::Reference<XAccessibleEditableText> aAccEditText = this;
1200 0 : aRet <<= aAccEditText;
1201 : }
1202 649 : else if ( rType == cppu::UnoType<XAccessibleSelection>::get())
1203 : {
1204 9 : uno::Reference<XAccessibleSelection> aAccSel = this;
1205 9 : aRet <<= aAccSel;
1206 : }
1207 640 : else if ( rType == cppu::UnoType<XAccessibleHypertext>::get())
1208 : {
1209 0 : uno::Reference<XAccessibleHypertext> aAccHyp = this;
1210 0 : aRet <<= aAccHyp;
1211 : }
1212 : // #i63870#
1213 : // add interface com::sun:star:accessibility::XAccessibleTextAttributes
1214 640 : else if ( rType == cppu::UnoType<XAccessibleTextAttributes>::get())
1215 : {
1216 0 : uno::Reference<XAccessibleTextAttributes> aAccTextAttr = this;
1217 0 : aRet <<= aAccTextAttr;
1218 : }
1219 : // #i89175#
1220 : // add interface com::sun:star:accessibility::XAccessibleTextMarkup
1221 640 : else if ( rType == cppu::UnoType<XAccessibleTextMarkup>::get())
1222 : {
1223 0 : uno::Reference<XAccessibleTextMarkup> aAccTextMarkup = this;
1224 0 : aRet <<= aAccTextMarkup;
1225 : }
1226 : // add interface com::sun:star:accessibility::XAccessibleMultiLineText
1227 640 : else if ( rType == cppu::UnoType<XAccessibleMultiLineText>::get())
1228 : {
1229 0 : uno::Reference<XAccessibleMultiLineText> aAccMultiLineText = this;
1230 0 : aRet <<= aAccMultiLineText;
1231 : }
1232 640 : else if ( rType == cppu::UnoType<XAccessibleTextSelection>::get())
1233 : {
1234 0 : uno::Reference< com::sun::star::accessibility::XAccessibleTextSelection > aTextExtension = this;
1235 0 : aRet <<= aTextExtension;
1236 : }
1237 640 : else if ( rType == cppu::UnoType<XAccessibleExtendedAttributes>::get())
1238 : {
1239 0 : uno::Reference<XAccessibleExtendedAttributes> xAttr = this;
1240 0 : aRet <<= xAttr;
1241 : }
1242 : else
1243 : {
1244 640 : aRet = SwAccessibleContext::queryInterface(rType);
1245 : }
1246 :
1247 652 : return aRet;
1248 : }
1249 :
1250 : // XTypeProvider
1251 0 : uno::Sequence< uno::Type > SAL_CALL SwAccessibleParagraph::getTypes() throw(uno::RuntimeException, std::exception)
1252 : {
1253 0 : uno::Sequence< uno::Type > aTypes( SwAccessibleContext::getTypes() );
1254 :
1255 0 : sal_Int32 nIndex = aTypes.getLength();
1256 : // #i63870# - add type accessibility::XAccessibleTextAttributes
1257 : // #i89175# - add type accessibility::XAccessibleTextMarkup and
1258 : // accessibility::XAccessibleMultiLineText
1259 0 : aTypes.realloc( nIndex + 6 );
1260 :
1261 0 : uno::Type* pTypes = aTypes.getArray();
1262 0 : pTypes[nIndex++] = cppu::UnoType<XAccessibleEditableText>::get();
1263 0 : pTypes[nIndex++] = cppu::UnoType<XAccessibleTextAttributes>::get();
1264 0 : pTypes[nIndex++] = ::cppu::UnoType<XAccessibleSelection>::get();
1265 0 : pTypes[nIndex++] = cppu::UnoType<XAccessibleTextMarkup>::get();
1266 0 : pTypes[nIndex++] = cppu::UnoType<XAccessibleMultiLineText>::get();
1267 0 : pTypes[nIndex] = cppu::UnoType<XAccessibleHypertext>::get();
1268 :
1269 0 : return aTypes;
1270 : }
1271 :
1272 0 : uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleParagraph::getImplementationId()
1273 : throw(uno::RuntimeException, std::exception)
1274 : {
1275 0 : return css::uno::Sequence<sal_Int8>();
1276 : }
1277 :
1278 : // XAccesibleText
1279 :
1280 0 : sal_Int32 SwAccessibleParagraph::getCaretPosition()
1281 : throw (uno::RuntimeException, std::exception)
1282 : {
1283 0 : SolarMutexGuard aGuard;
1284 :
1285 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
1286 :
1287 0 : sal_Int32 nRet = GetCaretPos();
1288 : {
1289 0 : osl::MutexGuard aOldCaretPosGuard( m_Mutex );
1290 : OSL_ENSURE( nRet == nOldCaretPos, "caret pos out of sync" );
1291 0 : nOldCaretPos = nRet;
1292 : }
1293 0 : if( -1 != nRet )
1294 : {
1295 0 : ::rtl::Reference < SwAccessibleContext > xThis( this );
1296 0 : GetMap()->SetCursorContext( xThis );
1297 : }
1298 :
1299 0 : return nRet;
1300 : }
1301 :
1302 0 : sal_Bool SAL_CALL SwAccessibleParagraph::setCaretPosition( sal_Int32 nIndex )
1303 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
1304 : {
1305 0 : SolarMutexGuard aGuard;
1306 :
1307 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
1308 :
1309 : // parameter checking
1310 0 : sal_Int32 nLength = GetString().getLength();
1311 0 : if ( ! IsValidPosition( nIndex, nLength ) )
1312 : {
1313 0 : throw lang::IndexOutOfBoundsException();
1314 : }
1315 :
1316 0 : bool bRet = false;
1317 :
1318 : // get cursor shell
1319 0 : SwCrsrShell* pCrsrShell = GetCrsrShell();
1320 0 : if( pCrsrShell != NULL )
1321 : {
1322 : // create pam for selection
1323 0 : SwTextNode* pNode = const_cast<SwTextNode*>( GetTextNode() );
1324 0 : SwIndex aIndex( pNode, GetPortionData().GetModelPosition(nIndex));
1325 0 : SwPosition aStartPos( *pNode, aIndex );
1326 0 : SwPaM aPaM( aStartPos );
1327 :
1328 : // set PaM at cursor shell
1329 0 : bRet = Select( aPaM );
1330 : }
1331 :
1332 0 : return bRet;
1333 : }
1334 :
1335 0 : sal_Unicode SwAccessibleParagraph::getCharacter( sal_Int32 nIndex )
1336 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
1337 : {
1338 0 : SolarMutexGuard aGuard;
1339 :
1340 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
1341 :
1342 0 : OUString sText( GetString() );
1343 :
1344 : // return character (if valid)
1345 0 : if( IsValidChar(nIndex, sText.getLength() ) )
1346 : {
1347 0 : return sText[nIndex];
1348 : }
1349 : else
1350 0 : throw lang::IndexOutOfBoundsException();
1351 : }
1352 :
1353 0 : com::sun::star::uno::Sequence< ::com::sun::star::style::TabStop > SwAccessibleParagraph::GetCurrentTabStop( sal_Int32 nIndex )
1354 : {
1355 0 : SolarMutexGuard aGuard;
1356 :
1357 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
1358 :
1359 : /* #i12332# The position after the string needs special treatment.
1360 : IsValidChar -> IsValidPosition
1361 : */
1362 0 : if( ! (IsValidPosition( nIndex, GetString().getLength() ) ) )
1363 0 : throw lang::IndexOutOfBoundsException();
1364 :
1365 : /* #i12332# */
1366 0 : bool bBehindText = false;
1367 0 : if ( nIndex == GetString().getLength() )
1368 0 : bBehindText = true;
1369 :
1370 : // get model position & prepare GetCharRect() arguments
1371 0 : SwCrsrMoveState aMoveState;
1372 0 : aMoveState.bRealHeight = true;
1373 0 : aMoveState.bRealWidth = true;
1374 0 : SwSpecialPos aSpecialPos;
1375 0 : SwTextNode* pNode = const_cast<SwTextNode*>( GetTextNode() );
1376 :
1377 : /* #i12332# FillSpecialPos does not accept nIndex ==
1378 : GetString().getLength(). In that case nPos is set to the
1379 : length of the string in the core. This way GetCharRect
1380 : returns the rectangle for a cursor at the end of the
1381 : paragraph. */
1382 : const sal_Int32 nPos = bBehindText
1383 0 : ? pNode->GetText().getLength()
1384 0 : : GetPortionData().FillSpecialPos(nIndex, aSpecialPos, aMoveState.pSpecialPos );
1385 :
1386 : // call GetCharRect
1387 0 : SwRect aCoreRect;
1388 0 : SwIndex aIndex( pNode, nPos );
1389 0 : SwPosition aPosition( *pNode, aIndex );
1390 0 : GetFrm()->GetCharRect( aCoreRect, aPosition, &aMoveState );
1391 :
1392 : // already get the caret position
1393 0 : com::sun::star::uno::Sequence< ::com::sun::star::style::TabStop > tabs;
1394 0 : const sal_Int32 nStrLen = GetTextNode()->GetText().getLength();
1395 0 : if( nStrLen > 0 )
1396 : {
1397 0 : SwFrm* pTFrm = const_cast<SwFrm*>(GetFrm());
1398 0 : tabs = pTFrm->GetTabStopInfo(aCoreRect.Left());
1399 : }
1400 :
1401 0 : if( tabs.hasElements() )
1402 : {
1403 : // translate core coordinates into accessibility coordinates
1404 0 : vcl::Window *pWin = GetWindow();
1405 0 : CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
1406 :
1407 0 : SwRect aTmpRect(0, 0, tabs[0].Position, 0);
1408 :
1409 0 : Rectangle aScreenRect( GetMap()->CoreToPixel( aTmpRect.SVRect() ));
1410 0 : SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root
1411 :
1412 0 : Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() );
1413 0 : aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() );
1414 :
1415 0 : tabs[0].Position = aScreenRect.GetWidth();
1416 : }
1417 :
1418 0 : return tabs;
1419 : }
1420 :
1421 : struct IndexCompare
1422 : {
1423 : const PropertyValue* pValues;
1424 0 : explicit IndexCompare( const PropertyValue* pVals ) : pValues(pVals) {}
1425 0 : bool operator() ( const sal_Int32& a, const sal_Int32& b ) const
1426 : {
1427 0 : return (pValues[a].Name < pValues[b].Name);
1428 : }
1429 : };
1430 :
1431 0 : OUString SwAccessibleParagraph::GetFieldTypeNameAtIndex(sal_Int32 nIndex)
1432 : {
1433 0 : OUString strTypeName;
1434 0 : SwFieldMgr aMgr;
1435 0 : SwTextField* pTextField = NULL;
1436 0 : SwTextNode* pTextNd = const_cast<SwTextNode*>( GetTextNode() );
1437 0 : SwIndex fldIndex( pTextNd, nIndex );
1438 0 : sal_Int32 nFieldIndex = GetPortionData().GetFieldIndex(nIndex);
1439 0 : if (nFieldIndex >= 0)
1440 : {
1441 0 : const SwpHints* pSwpHints = GetTextNode()->GetpSwpHints();
1442 0 : if (pSwpHints)
1443 : {
1444 0 : const size_t nSize = pSwpHints->Count();
1445 0 : for( size_t i = 0; i < nSize; ++i )
1446 : {
1447 0 : const SwTextAttr* pHt = (*pSwpHints)[i];
1448 0 : if ( ( pHt->Which() == RES_TXTATR_FIELD
1449 0 : || pHt->Which() == RES_TXTATR_ANNOTATION
1450 0 : || pHt->Which() == RES_TXTATR_INPUTFIELD )
1451 0 : && (nFieldIndex-- == 0))
1452 : {
1453 : pTextField = const_cast<SwTextField*>(
1454 0 : static_txtattr_cast<SwTextField const*>(pHt));
1455 0 : break;
1456 : }
1457 0 : else if (pHt->Which() == RES_TXTATR_REFMARK
1458 0 : && (nFieldIndex-- == 0))
1459 0 : strTypeName = "set reference";
1460 : }
1461 : }
1462 : }
1463 0 : if (pTextField)
1464 : {
1465 0 : const SwField* pField = (pTextField->GetFormatField()).GetField();
1466 0 : if (pField)
1467 : {
1468 0 : strTypeName = SwFieldType::GetTypeStr(pField->GetTypeId());
1469 0 : const sal_uInt16 nWhich = pField->GetTyp()->Which();
1470 0 : OUString sEntry;
1471 0 : sal_Int32 subType = 0;
1472 0 : switch (nWhich)
1473 : {
1474 : case RES_DOCSTATFLD:
1475 0 : subType = static_cast<const SwDocStatField*>(pField)->GetSubType();
1476 0 : break;
1477 : case RES_GETREFFLD:
1478 : {
1479 0 : switch( pField->GetSubType() )
1480 : {
1481 : case REF_BOOKMARK:
1482 : {
1483 0 : const SwGetRefField* pRefField = dynamic_cast<const SwGetRefField*>(pField);
1484 0 : if ( pRefField && pRefField->IsRefToHeadingCrossRefBookmark() )
1485 0 : sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Headings"));
1486 0 : else if ( pRefField && pRefField->IsRefToNumItemCrossRefBookmark() )
1487 0 : sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Numbered Paragraphs"));
1488 : else
1489 0 : sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Bookmarks"));
1490 : }
1491 0 : break;
1492 : case REF_FOOTNOTE:
1493 0 : sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Footnotes"));
1494 0 : break;
1495 : case REF_ENDNOTE:
1496 0 : sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Endnotes"));
1497 0 : break;
1498 : case REF_SETREFATTR:
1499 0 : sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Insert Reference"));
1500 0 : break;
1501 : case REF_SEQUENCEFLD:
1502 0 : sEntry = static_cast<const SwGetRefField*>(pField)->GetSetRefName();
1503 0 : break;
1504 : }
1505 : //Get format string
1506 0 : strTypeName = sEntry;
1507 : // <pField->GetFormat() >= 0> is always true as <pField->GetFormat()> is unsigned
1508 : // if (pField->GetFormat() >= 0)
1509 : {
1510 0 : sEntry = aMgr.GetFormatStr( pField->GetTypeId(), pField->GetFormat() );
1511 0 : if (sEntry.getLength() > 0)
1512 : {
1513 0 : strTypeName += "-";
1514 0 : strTypeName += sEntry;
1515 : }
1516 : }
1517 : }
1518 0 : break;
1519 : case RES_DATETIMEFLD:
1520 0 : subType = static_cast<const SwDateTimeField*>(pField)->GetSubType();
1521 0 : break;
1522 : case RES_JUMPEDITFLD:
1523 : {
1524 0 : const sal_uInt16 nFormat= pField->GetFormat();
1525 0 : const sal_uInt16 nSize = aMgr.GetFormatCount(pField->GetTypeId(), false);
1526 0 : if (nFormat < nSize)
1527 : {
1528 0 : sEntry = aMgr.GetFormatStr(pField->GetTypeId(), nFormat);
1529 0 : if (sEntry.getLength() > 0)
1530 : {
1531 0 : strTypeName += "-";
1532 0 : strTypeName += sEntry;
1533 : }
1534 : }
1535 : }
1536 0 : break;
1537 : case RES_EXTUSERFLD:
1538 0 : subType = static_cast<const SwExtUserField*>(pField)->GetSubType();
1539 0 : break;
1540 : case RES_HIDDENTXTFLD:
1541 : case RES_SETEXPFLD:
1542 : {
1543 0 : sEntry = pField->GetTyp()->GetName();
1544 0 : if (sEntry.getLength() > 0)
1545 : {
1546 0 : strTypeName += "-";
1547 0 : strTypeName += sEntry;
1548 : }
1549 : }
1550 0 : break;
1551 : case RES_DOCINFOFLD:
1552 0 : subType = pField->GetSubType();
1553 0 : subType &= 0x00ff;
1554 0 : break;
1555 : case RES_REFPAGESETFLD:
1556 : {
1557 0 : const SwRefPageSetField* pRPld = static_cast<const SwRefPageSetField*>(pField);
1558 0 : bool bOn = pRPld->IsOn();
1559 0 : strTypeName += "-";
1560 0 : if (bOn)
1561 0 : strTypeName += "on";
1562 : else
1563 0 : strTypeName += "off";
1564 : }
1565 0 : break;
1566 : case RES_AUTHORFLD:
1567 : {
1568 0 : strTypeName += "-";
1569 0 : strTypeName += aMgr.GetFormatStr(pField->GetTypeId(), pField->GetFormat() & 0xff);
1570 : }
1571 0 : break;
1572 : }
1573 0 : if (subType > 0 || (subType == 0 && (nWhich == RES_DOCINFOFLD || nWhich == RES_EXTUSERFLD || nWhich == RES_DOCSTATFLD)))
1574 : {
1575 0 : std::vector<OUString> aLst;
1576 0 : aMgr.GetSubTypes(pField->GetTypeId(), aLst);
1577 0 : if (static_cast<size_t>(subType) < aLst.size())
1578 0 : sEntry = aLst[subType];
1579 0 : if (sEntry.getLength() > 0)
1580 : {
1581 0 : if (nWhich == RES_DOCINFOFLD)
1582 : {
1583 0 : strTypeName = sEntry;
1584 0 : sal_uInt32 nSize = aMgr.GetFormatCount(pField->GetTypeId(), false);
1585 0 : const sal_uInt16 nExSub = pField->GetSubType() & 0xff00;
1586 0 : if (nSize > 0 && nExSub > 0)
1587 : {
1588 : //Get extra subtype string
1589 0 : strTypeName += "-";
1590 0 : sEntry = aMgr.GetFormatStr(pField->GetTypeId(), nExSub/0x0100-1);
1591 0 : strTypeName += sEntry;
1592 : }
1593 : }
1594 : else
1595 : {
1596 0 : strTypeName += "-";
1597 0 : strTypeName += sEntry;
1598 : }
1599 0 : }
1600 0 : }
1601 : }
1602 : }
1603 0 : return strTypeName;
1604 : }
1605 :
1606 : // #i63870# - re-implement method on behalf of methods
1607 : // <_getDefaultAttributesImpl(..)> and <_getRunAttributesImpl(..)>
1608 0 : uno::Sequence<PropertyValue> SwAccessibleParagraph::getCharacterAttributes(
1609 : sal_Int32 nIndex,
1610 : const uno::Sequence< OUString >& aRequestedAttributes )
1611 : throw (lang::IndexOutOfBoundsException,
1612 : uno::RuntimeException,
1613 : std::exception)
1614 : {
1615 :
1616 0 : SolarMutexGuard aGuard;
1617 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
1618 :
1619 0 : const OUString& rText = GetString();
1620 :
1621 0 : if( ! IsValidChar( nIndex, rText.getLength()+1 ) )
1622 0 : throw lang::IndexOutOfBoundsException();
1623 :
1624 0 : bool bSupplementalMode = false;
1625 0 : uno::Sequence< OUString > aNames = aRequestedAttributes;
1626 0 : if (aNames.getLength() == 0)
1627 : {
1628 0 : bSupplementalMode = true;
1629 0 : aNames = getAttributeNames();
1630 : }
1631 : // retrieve default character attributes
1632 0 : tAccParaPropValMap aDefAttrSeq;
1633 0 : _getDefaultAttributesImpl( aNames, aDefAttrSeq, true );
1634 :
1635 : // retrieved run character attributes
1636 0 : tAccParaPropValMap aRunAttrSeq;
1637 0 : _getRunAttributesImpl( nIndex, aNames, aRunAttrSeq );
1638 :
1639 : // merge default and run attributes
1640 0 : uno::Sequence< PropertyValue > aValues( aDefAttrSeq.size() );
1641 0 : PropertyValue* pValues = aValues.getArray();
1642 0 : sal_Int32 i = 0;
1643 0 : for ( tAccParaPropValMap::const_iterator aDefIter = aDefAttrSeq.begin();
1644 0 : aDefIter != aDefAttrSeq.end();
1645 : ++aDefIter )
1646 : {
1647 : tAccParaPropValMap::const_iterator aRunIter =
1648 0 : aRunAttrSeq.find( aDefIter->first );
1649 0 : if ( aRunIter != aRunAttrSeq.end() )
1650 : {
1651 0 : pValues[i] = aRunIter->second;
1652 : }
1653 : else
1654 : {
1655 0 : pValues[i] = aDefIter->second;
1656 : }
1657 0 : ++i;
1658 : }
1659 0 : if( bSupplementalMode )
1660 : {
1661 0 : uno::Sequence< OUString > aSupplementalNames = aRequestedAttributes;
1662 0 : if (aSupplementalNames.getLength() == 0)
1663 0 : aSupplementalNames = getSupplementalAttributeNames();
1664 :
1665 0 : tAccParaPropValMap aSupplementalAttrSeq;
1666 0 : _getSupplementalAttributesImpl( nIndex, aSupplementalNames, aSupplementalAttrSeq );
1667 :
1668 0 : aValues.realloc( aValues.getLength() + aSupplementalAttrSeq.size() );
1669 0 : pValues = aValues.getArray();
1670 :
1671 0 : for ( tAccParaPropValMap::const_iterator aSupplementalIter = aSupplementalAttrSeq.begin();
1672 0 : aSupplementalIter != aSupplementalAttrSeq.end();
1673 : ++aSupplementalIter )
1674 : {
1675 0 : pValues[i] = aSupplementalIter->second;
1676 0 : ++i;
1677 : }
1678 :
1679 0 : _correctValues( nIndex, aValues );
1680 :
1681 0 : aValues.realloc( aValues.getLength() + 1 );
1682 :
1683 0 : pValues = aValues.getArray();
1684 :
1685 0 : const SwTextNode* pTextNode( GetTextNode() );
1686 0 : PropertyValue& rValue = pValues[aValues.getLength() - 1 ];
1687 0 : rValue.Name = "NumberingPrefix";
1688 0 : OUString sNumBullet = pTextNode->GetNumString();
1689 0 : rValue.Value <<= sNumBullet;
1690 0 : rValue.Handle = -1;
1691 0 : rValue.State = PropertyState_DIRECT_VALUE;
1692 :
1693 0 : OUString strTypeName = GetFieldTypeNameAtIndex(nIndex);
1694 0 : if (!strTypeName.isEmpty())
1695 : {
1696 0 : aValues.realloc( aValues.getLength() + 1 );
1697 0 : pValues = aValues.getArray();
1698 0 : PropertyValue& rValueFT = pValues[aValues.getLength() - 1];
1699 0 : rValueFT.Name = "FieldType";
1700 0 : rValueFT.Value <<= strTypeName.toAsciiLowerCase();
1701 0 : rValueFT.Handle = -1;
1702 0 : rValueFT.State = PropertyState_DIRECT_VALUE;
1703 : }
1704 :
1705 : //sort property values
1706 : // build sorted index array
1707 0 : sal_Int32 nLength = aValues.getLength();
1708 0 : const PropertyValue* pPairs = aValues.getConstArray();
1709 0 : sal_Int32* pIndices = new sal_Int32[nLength];
1710 0 : for( i = 0; i < nLength; i++ )
1711 0 : pIndices[i] = i;
1712 0 : sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) );
1713 : // create sorted sequences according to index array
1714 0 : uno::Sequence<PropertyValue> aNewValues( nLength );
1715 0 : PropertyValue* pNewValues = aNewValues.getArray();
1716 0 : for( i = 0; i < nLength; i++ )
1717 : {
1718 0 : pNewValues[i] = pPairs[pIndices[i]];
1719 : }
1720 0 : delete[] pIndices;
1721 0 : return aNewValues;
1722 : }
1723 :
1724 0 : return aValues;
1725 : }
1726 :
1727 0 : static void SetPutRecursive(SfxItemSet &targetSet, const SfxItemSet &sourceSet)
1728 : {
1729 0 : const SfxItemSet *const pParentSet = sourceSet.GetParent();
1730 0 : if (pParentSet)
1731 0 : SetPutRecursive(targetSet, *pParentSet);
1732 0 : targetSet.Put(sourceSet);
1733 0 : }
1734 :
1735 : // #i63870#
1736 0 : void SwAccessibleParagraph::_getDefaultAttributesImpl(
1737 : const uno::Sequence< OUString >& aRequestedAttributes,
1738 : tAccParaPropValMap& rDefAttrSeq,
1739 : const bool bOnlyCharAttrs )
1740 : {
1741 : // retrieve default attributes
1742 0 : const SwTextNode* pTextNode( GetTextNode() );
1743 0 : ::boost::scoped_ptr<SfxItemSet> pSet;
1744 0 : if ( !bOnlyCharAttrs )
1745 : {
1746 0 : pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTextNode->GetDoc()->GetAttrPool()),
1747 : RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
1748 : RES_PARATR_BEGIN, RES_PARATR_END - 1,
1749 : RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
1750 0 : 0 ) );
1751 : }
1752 : else
1753 : {
1754 0 : pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTextNode->GetDoc()->GetAttrPool()),
1755 : RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
1756 0 : 0 ) );
1757 : }
1758 : // #i82637# - From the perspective of the a11y API the default character
1759 : // attributes are the character attributes, which are set at the paragraph style
1760 : // of the paragraph. The character attributes set at the automatic paragraph
1761 : // style of the paragraph are treated as run attributes.
1762 : // pTextNode->SwContentNode::GetAttr( *pSet );
1763 : // get default paragraph attributes, if needed, and merge these into <pSet>
1764 0 : if ( !bOnlyCharAttrs )
1765 : {
1766 0 : SfxItemSet aParaSet( const_cast<SwAttrPool&>(pTextNode->GetDoc()->GetAttrPool()),
1767 : RES_PARATR_BEGIN, RES_PARATR_END - 1,
1768 : RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
1769 0 : 0 );
1770 0 : pTextNode->SwContentNode::GetAttr( aParaSet );
1771 0 : pSet->Put( aParaSet );
1772 : }
1773 : // get default character attributes and merge these into <pSet>
1774 : OSL_ENSURE( pTextNode->GetTextColl(),
1775 : "<SwAccessibleParagraph::_getDefaultAttributesImpl(..)> - missing paragraph style. Serious defect, please inform OD!" );
1776 0 : if ( pTextNode->GetTextColl() )
1777 : {
1778 0 : SfxItemSet aCharSet( const_cast<SwAttrPool&>(pTextNode->GetDoc()->GetAttrPool()),
1779 : RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
1780 0 : 0 );
1781 0 : SetPutRecursive( aCharSet, pTextNode->GetTextColl()->GetAttrSet() );
1782 0 : pSet->Put( aCharSet );
1783 : }
1784 :
1785 : // build-up sequence containing the run attributes <rDefAttrSeq>
1786 0 : tAccParaPropValMap aDefAttrSeq;
1787 : {
1788 : const SfxItemPropertyMap& rPropMap =
1789 0 : aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR )->getPropertyMap();
1790 0 : PropertyEntryVector_t aPropertyEntries = rPropMap.getPropertyEntries();
1791 0 : PropertyEntryVector_t::const_iterator aPropIt = aPropertyEntries.begin();
1792 0 : while ( aPropIt != aPropertyEntries.end() )
1793 : {
1794 0 : const SfxPoolItem* pItem = pSet->GetItem( aPropIt->nWID );
1795 0 : if ( pItem )
1796 : {
1797 0 : uno::Any aVal;
1798 0 : pItem->QueryValue( aVal, aPropIt->nMemberId );
1799 :
1800 0 : PropertyValue rPropVal;
1801 0 : rPropVal.Name = aPropIt->sName;
1802 0 : rPropVal.Value = aVal;
1803 0 : rPropVal.Handle = -1;
1804 0 : rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
1805 :
1806 0 : aDefAttrSeq[rPropVal.Name] = rPropVal;
1807 : }
1808 0 : ++aPropIt;
1809 : }
1810 :
1811 : // #i72800#
1812 : // add property value entry for the paragraph style
1813 0 : if ( !bOnlyCharAttrs && pTextNode->GetTextColl() )
1814 : {
1815 0 : if ( aDefAttrSeq.find( UNO_NAME_PARA_STYLE_NAME ) == aDefAttrSeq.end() )
1816 : {
1817 0 : PropertyValue rPropVal;
1818 0 : rPropVal.Name = UNO_NAME_PARA_STYLE_NAME;
1819 0 : uno::Any aVal( uno::makeAny( pTextNode->GetTextColl()->GetName() ) );
1820 0 : rPropVal.Value = aVal;
1821 0 : rPropVal.Handle = -1;
1822 0 : rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
1823 :
1824 0 : aDefAttrSeq[rPropVal.Name] = rPropVal;
1825 : }
1826 : }
1827 :
1828 : // #i73371#
1829 : // resolve value text::WritingMode2::PAGE of property value entry WritingMode
1830 0 : if ( !bOnlyCharAttrs && GetFrm() )
1831 : {
1832 0 : tAccParaPropValMap::iterator aIter = aDefAttrSeq.find( UNO_NAME_WRITING_MODE );
1833 0 : if ( aIter != aDefAttrSeq.end() )
1834 : {
1835 0 : PropertyValue rPropVal( aIter->second );
1836 0 : sal_Int16 nVal = rPropVal.Value.get<sal_Int16>();
1837 0 : if ( nVal == text::WritingMode2::PAGE )
1838 : {
1839 0 : const SwFrm* pUpperFrm( GetFrm()->GetUpper() );
1840 0 : while ( pUpperFrm )
1841 : {
1842 0 : if ( pUpperFrm->GetType() &
1843 : ( FRM_PAGE | FRM_FLY | FRM_SECTION | FRM_TAB | FRM_CELL ) )
1844 : {
1845 0 : if ( pUpperFrm->IsVertical() )
1846 : {
1847 0 : nVal = text::WritingMode2::TB_RL;
1848 : }
1849 0 : else if ( pUpperFrm->IsRightToLeft() )
1850 : {
1851 0 : nVal = text::WritingMode2::RL_TB;
1852 : }
1853 : else
1854 : {
1855 0 : nVal = text::WritingMode2::LR_TB;
1856 : }
1857 0 : rPropVal.Value <<= nVal;
1858 0 : aDefAttrSeq[rPropVal.Name] = rPropVal;
1859 0 : break;
1860 : }
1861 :
1862 0 : if ( const SwFlyFrm* pFlyFrm = dynamic_cast<const SwFlyFrm*>(pUpperFrm) )
1863 : {
1864 0 : pUpperFrm = pFlyFrm->GetAnchorFrm();
1865 : }
1866 : else
1867 : {
1868 0 : pUpperFrm = pUpperFrm->GetUpper();
1869 : }
1870 : }
1871 0 : }
1872 : }
1873 0 : }
1874 : }
1875 :
1876 0 : if ( aRequestedAttributes.getLength() == 0 )
1877 : {
1878 0 : rDefAttrSeq = aDefAttrSeq;
1879 : }
1880 : else
1881 : {
1882 0 : const OUString* pReqAttrs = aRequestedAttributes.getConstArray();
1883 0 : const sal_Int32 nLength = aRequestedAttributes.getLength();
1884 0 : for( sal_Int32 i = 0; i < nLength; ++i )
1885 : {
1886 0 : tAccParaPropValMap::const_iterator const aIter = aDefAttrSeq.find( pReqAttrs[i] );
1887 0 : if ( aIter != aDefAttrSeq.end() )
1888 : {
1889 0 : rDefAttrSeq[ aIter->first ] = aIter->second;
1890 : }
1891 : }
1892 0 : }
1893 0 : }
1894 :
1895 0 : uno::Sequence< PropertyValue > SwAccessibleParagraph::getDefaultAttributes(
1896 : const uno::Sequence< OUString >& aRequestedAttributes )
1897 : throw ( uno::RuntimeException, std::exception )
1898 : {
1899 0 : SolarMutexGuard aGuard;
1900 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
1901 :
1902 0 : tAccParaPropValMap aDefAttrSeq;
1903 0 : _getDefaultAttributesImpl( aRequestedAttributes, aDefAttrSeq );
1904 :
1905 : // #i92233#
1906 : static const char sMMToPixelRatio[] = "MMToPixelRatio";
1907 0 : bool bProvideMMToPixelRatio( false );
1908 : {
1909 0 : if ( aRequestedAttributes.getLength() == 0 )
1910 : {
1911 0 : bProvideMMToPixelRatio = true;
1912 : }
1913 : else
1914 : {
1915 : const OUString* aRequestedAttrIter =
1916 0 : ::std::find( aRequestedAttributes.begin(), aRequestedAttributes.end(), sMMToPixelRatio );
1917 0 : if ( aRequestedAttrIter != aRequestedAttributes.end() )
1918 0 : bProvideMMToPixelRatio = true;
1919 : }
1920 : }
1921 :
1922 0 : uno::Sequence< PropertyValue > aValues( aDefAttrSeq.size() +
1923 0 : ( bProvideMMToPixelRatio ? 1 : 0 ) );
1924 0 : PropertyValue* pValues = aValues.getArray();
1925 0 : sal_Int32 i = 0;
1926 0 : for ( tAccParaPropValMap::const_iterator aIter = aDefAttrSeq.begin();
1927 0 : aIter != aDefAttrSeq.end();
1928 : ++aIter )
1929 : {
1930 0 : pValues[i] = aIter->second;
1931 0 : ++i;
1932 : }
1933 :
1934 : // #i92233#
1935 0 : if ( bProvideMMToPixelRatio )
1936 : {
1937 0 : PropertyValue rPropVal;
1938 0 : rPropVal.Name = sMMToPixelRatio;
1939 0 : const Size a100thMMSize( 1000, 1000 );
1940 0 : const Size aPixelSize = GetMap()->LogicToPixel( a100thMMSize );
1941 0 : const float fRatio = ((float)a100thMMSize.Width()/100)/aPixelSize.Width();
1942 0 : rPropVal.Value = uno::makeAny( fRatio );
1943 0 : rPropVal.Handle = -1;
1944 0 : rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
1945 0 : pValues[ aValues.getLength() - 1 ] = rPropVal;
1946 : }
1947 :
1948 0 : return aValues;
1949 : }
1950 :
1951 0 : void SwAccessibleParagraph::_getRunAttributesImpl(
1952 : const sal_Int32 nIndex,
1953 : const uno::Sequence< OUString >& aRequestedAttributes,
1954 : tAccParaPropValMap& rRunAttrSeq )
1955 : {
1956 : // create PaM for character at position <nIndex>
1957 0 : SwPaM* pPaM( 0 );
1958 : {
1959 0 : const SwTextNode* pTextNode( GetTextNode() );
1960 0 : SwPosition* pStartPos = new SwPosition( *pTextNode );
1961 0 : pStartPos->nContent.Assign( const_cast<SwTextNode*>(pTextNode), nIndex );
1962 0 : SwPosition* pEndPos = new SwPosition( *pTextNode );
1963 0 : pEndPos->nContent.Assign( const_cast<SwTextNode*>(pTextNode), nIndex+1 );
1964 :
1965 0 : pPaM = new SwPaM( *pStartPos, *pEndPos );
1966 :
1967 0 : delete pStartPos;
1968 0 : delete pEndPos;
1969 : }
1970 :
1971 : // retrieve character attributes for the created PaM <pPaM>
1972 0 : SfxItemSet aSet( pPaM->GetDoc()->GetAttrPool(),
1973 : RES_CHRATR_BEGIN, RES_CHRATR_END -1,
1974 0 : 0 );
1975 : // #i82637#
1976 : // From the perspective of the a11y API the character attributes, which
1977 : // are set at the automatic paragraph style of the paragraph, are treated
1978 : // as run attributes.
1979 : // SwXTextCursor::GetCrsrAttr( *pPaM, aSet, sal_True, sal_True );
1980 : // get character attributes from automatic paragraph style and merge these into <aSet>
1981 : {
1982 0 : const SwTextNode* pTextNode( GetTextNode() );
1983 0 : if ( pTextNode->HasSwAttrSet() )
1984 : {
1985 0 : SfxItemSet aAutomaticParaStyleCharAttrs( pPaM->GetDoc()->GetAttrPool(),
1986 : RES_CHRATR_BEGIN, RES_CHRATR_END -1,
1987 0 : 0 );
1988 0 : aAutomaticParaStyleCharAttrs.Put( *(pTextNode->GetpSwAttrSet()), false );
1989 0 : aSet.Put( aAutomaticParaStyleCharAttrs );
1990 : }
1991 : }
1992 : // get character attributes at <pPaM> and merge these into <aSet>
1993 : {
1994 0 : SfxItemSet aCharAttrsAtPaM( pPaM->GetDoc()->GetAttrPool(),
1995 : RES_CHRATR_BEGIN, RES_CHRATR_END -1,
1996 0 : 0 );
1997 0 : SwUnoCursorHelper::GetCrsrAttr(*pPaM, aCharAttrsAtPaM, true, true);
1998 0 : aSet.Put( aCharAttrsAtPaM );
1999 : }
2000 :
2001 : // build-up sequence containing the run attributes <rRunAttrSeq>
2002 : {
2003 0 : tAccParaPropValMap aRunAttrSeq;
2004 : {
2005 0 : tAccParaPropValMap aDefAttrSeq;
2006 0 : uno::Sequence< OUString > aDummy;
2007 0 : _getDefaultAttributesImpl( aDummy, aDefAttrSeq, true ); // #i82637#
2008 :
2009 : const SfxItemPropertyMap& rPropMap =
2010 0 : aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR )->getPropertyMap();
2011 0 : PropertyEntryVector_t aPropertyEntries = rPropMap.getPropertyEntries();
2012 0 : PropertyEntryVector_t::const_iterator aPropIt = aPropertyEntries.begin();
2013 0 : while ( aPropIt != aPropertyEntries.end() )
2014 : {
2015 0 : const SfxPoolItem* pItem( 0 );
2016 : // #i82637# - Found character attributes, whose value equals the value of
2017 : // the corresponding default character attributes, are excluded.
2018 0 : if ( aSet.GetItemState( aPropIt->nWID, true, &pItem ) == SfxItemState::SET )
2019 : {
2020 0 : uno::Any aVal;
2021 0 : pItem->QueryValue( aVal, aPropIt->nMemberId );
2022 :
2023 0 : PropertyValue rPropVal;
2024 0 : rPropVal.Name = aPropIt->sName;
2025 0 : rPropVal.Value = aVal;
2026 0 : rPropVal.Handle = -1;
2027 0 : rPropVal.State = PropertyState_DIRECT_VALUE;
2028 :
2029 : tAccParaPropValMap::const_iterator aDefIter =
2030 0 : aDefAttrSeq.find( rPropVal.Name );
2031 0 : if ( aDefIter == aDefAttrSeq.end() ||
2032 0 : rPropVal.Value != aDefIter->second.Value )
2033 : {
2034 0 : aRunAttrSeq[rPropVal.Name] = rPropVal;
2035 0 : }
2036 : }
2037 :
2038 0 : ++aPropIt;
2039 0 : }
2040 : }
2041 :
2042 0 : if ( aRequestedAttributes.getLength() == 0 )
2043 : {
2044 0 : rRunAttrSeq = aRunAttrSeq;
2045 : }
2046 : else
2047 : {
2048 0 : const OUString* pReqAttrs = aRequestedAttributes.getConstArray();
2049 0 : const sal_Int32 nLength = aRequestedAttributes.getLength();
2050 0 : for( sal_Int32 i = 0; i < nLength; ++i )
2051 : {
2052 0 : tAccParaPropValMap::iterator aIter = aRunAttrSeq.find( pReqAttrs[i] );
2053 0 : if ( aIter != aRunAttrSeq.end() )
2054 : {
2055 0 : rRunAttrSeq[ (*aIter).first ] = (*aIter).second;
2056 : }
2057 : }
2058 0 : }
2059 : }
2060 :
2061 0 : delete pPaM;
2062 0 : }
2063 :
2064 0 : uno::Sequence< PropertyValue > SwAccessibleParagraph::getRunAttributes(
2065 : sal_Int32 nIndex,
2066 : const uno::Sequence< OUString >& aRequestedAttributes )
2067 : throw ( lang::IndexOutOfBoundsException,
2068 : uno::RuntimeException, std::exception )
2069 : {
2070 0 : SolarMutexGuard aGuard;
2071 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2072 :
2073 : {
2074 0 : const OUString& rText = GetString();
2075 0 : if ( !IsValidChar( nIndex, rText.getLength() ) )
2076 : {
2077 0 : throw lang::IndexOutOfBoundsException();
2078 0 : }
2079 : }
2080 :
2081 0 : tAccParaPropValMap aRunAttrSeq;
2082 0 : _getRunAttributesImpl( nIndex, aRequestedAttributes, aRunAttrSeq );
2083 :
2084 0 : uno::Sequence< PropertyValue > aValues( aRunAttrSeq.size() );
2085 0 : PropertyValue* pValues = aValues.getArray();
2086 0 : sal_Int32 i = 0;
2087 0 : for ( tAccParaPropValMap::const_iterator aIter = aRunAttrSeq.begin();
2088 0 : aIter != aRunAttrSeq.end();
2089 : ++aIter )
2090 : {
2091 0 : pValues[i] = aIter->second;
2092 0 : ++i;
2093 : }
2094 :
2095 0 : return aValues;
2096 : }
2097 :
2098 0 : void SwAccessibleParagraph::_getSupplementalAttributesImpl(
2099 : const sal_Int32,
2100 : const uno::Sequence< OUString >& aRequestedAttributes,
2101 : tAccParaPropValMap& rSupplementalAttrSeq )
2102 : {
2103 0 : const SwTextNode* pTextNode( GetTextNode() );
2104 0 : ::boost::scoped_ptr<SfxItemSet> pSet;
2105 0 : pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTextNode->GetDoc()->GetAttrPool()),
2106 : RES_PARATR_ADJUST, RES_PARATR_ADJUST,
2107 : RES_PARATR_TABSTOP, RES_PARATR_TABSTOP,
2108 : RES_PARATR_LINESPACING, RES_PARATR_LINESPACING,
2109 : RES_UL_SPACE, RES_UL_SPACE,
2110 : RES_LR_SPACE, RES_LR_SPACE,
2111 : RES_PARATR_NUMRULE, RES_PARATR_NUMRULE,
2112 : RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
2113 0 : 0 ) );
2114 :
2115 0 : if ( pTextNode->HasBullet() || pTextNode->HasNumber() )
2116 : {
2117 0 : pSet->Put( pTextNode->GetAttr(RES_PARATR_LIST_LEVEL, true) );
2118 : }
2119 0 : pSet->Put( pTextNode->SwContentNode::GetAttr(RES_UL_SPACE) );
2120 0 : pSet->Put( pTextNode->SwContentNode::GetAttr(RES_LR_SPACE) );
2121 0 : pSet->Put( pTextNode->SwContentNode::GetAttr(RES_PARATR_ADJUST) );
2122 :
2123 0 : tAccParaPropValMap aSupplementalAttrSeq;
2124 : {
2125 : const SfxItemPropertyMapEntry* pPropMap(
2126 0 : aSwMapProvider.GetPropertyMapEntries( PROPERTY_MAP_ACCESSIBILITY_TEXT_ATTRIBUTE ) );
2127 0 : while ( !pPropMap->aName.isEmpty() )
2128 : {
2129 0 : const SfxPoolItem* pItem = pSet->GetItem( pPropMap->nWID );
2130 0 : if ( pItem )
2131 : {
2132 0 : uno::Any aVal;
2133 0 : pItem->QueryValue( aVal, pPropMap->nMemberId );
2134 :
2135 0 : PropertyValue rPropVal;
2136 0 : rPropVal.Name = pPropMap->aName;
2137 0 : rPropVal.Value = aVal;
2138 0 : rPropVal.Handle = -1;
2139 0 : rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
2140 :
2141 0 : aSupplementalAttrSeq[rPropVal.Name] = rPropVal;
2142 : }
2143 :
2144 0 : ++pPropMap;
2145 : }
2146 : }
2147 :
2148 0 : const OUString* pSupplementalAttrs = aRequestedAttributes.getConstArray();
2149 0 : const sal_Int32 nSupplementalLength = aRequestedAttributes.getLength();
2150 :
2151 0 : for( sal_Int32 index = 0; index < nSupplementalLength; ++index )
2152 : {
2153 0 : tAccParaPropValMap::const_iterator const aIter = aSupplementalAttrSeq.find( pSupplementalAttrs[index] );
2154 0 : if ( aIter != aSupplementalAttrSeq.end() )
2155 : {
2156 0 : rSupplementalAttrSeq[ aIter->first ] = aIter->second;
2157 : }
2158 0 : }
2159 0 : }
2160 :
2161 0 : void SwAccessibleParagraph::_correctValues( const sal_Int32 nIndex,
2162 : uno::Sequence< PropertyValue >& rValues)
2163 : {
2164 0 : PropertyValue ChangeAttr, ChangeAttrColor;
2165 :
2166 0 : const SwRangeRedline* pRedline = GetRedlineAtIndex( nIndex );
2167 0 : if ( pRedline )
2168 : {
2169 :
2170 0 : const SwModuleOptions *pOpt = SW_MOD()->GetModuleConfig();
2171 0 : AuthorCharAttr aChangeAttr;
2172 0 : if ( pOpt )
2173 : {
2174 0 : switch( pRedline->GetType())
2175 : {
2176 : case nsRedlineType_t::REDLINE_INSERT:
2177 0 : aChangeAttr = pOpt->GetInsertAuthorAttr();
2178 0 : break;
2179 : case nsRedlineType_t::REDLINE_DELETE:
2180 0 : aChangeAttr = pOpt->GetDeletedAuthorAttr();
2181 0 : break;
2182 : case nsRedlineType_t::REDLINE_FORMAT:
2183 0 : aChangeAttr = pOpt->GetFormatAuthorAttr();
2184 0 : break;
2185 : }
2186 : }
2187 0 : switch( aChangeAttr.nItemId )
2188 : {
2189 : case SID_ATTR_CHAR_WEIGHT:
2190 0 : ChangeAttr.Name = UNO_NAME_CHAR_WEIGHT;
2191 0 : ChangeAttr.Value <<= awt::FontWeight::BOLD;
2192 0 : break;
2193 : case SID_ATTR_CHAR_POSTURE:
2194 0 : ChangeAttr.Name = UNO_NAME_CHAR_POSTURE;
2195 0 : ChangeAttr.Value <<= awt::FontSlant_ITALIC; //char posture
2196 0 : break;
2197 : case SID_ATTR_CHAR_STRIKEOUT:
2198 0 : ChangeAttr.Name = UNO_NAME_CHAR_STRIKEOUT;
2199 0 : ChangeAttr.Value <<= awt::FontStrikeout::SINGLE; //char strikeout
2200 0 : break;
2201 : case SID_ATTR_CHAR_UNDERLINE:
2202 0 : ChangeAttr.Name = UNO_NAME_CHAR_UNDERLINE;
2203 0 : ChangeAttr.Value <<= aChangeAttr.nAttr; //underline line
2204 0 : break;
2205 : }
2206 0 : if( aChangeAttr.nColor != COL_NONE_COLOR )
2207 : {
2208 0 : if( aChangeAttr.nItemId == SID_ATTR_BRUSH )
2209 : {
2210 0 : ChangeAttrColor.Name = UNO_NAME_CHAR_BACK_COLOR;
2211 0 : if( aChangeAttr.nColor == COL_TRANSPARENT )//char backcolor
2212 0 : ChangeAttrColor.Value <<= COL_BLUE;
2213 : else
2214 0 : ChangeAttrColor.Value <<= aChangeAttr.nColor;
2215 : }
2216 : else
2217 : {
2218 0 : ChangeAttrColor.Name = UNO_NAME_CHAR_COLOR;
2219 0 : if( aChangeAttr.nColor == COL_TRANSPARENT )//char color
2220 0 : ChangeAttrColor.Value <<= COL_BLUE;
2221 : else
2222 0 : ChangeAttrColor.Value <<= aChangeAttr.nColor;
2223 : }
2224 : }
2225 : }
2226 :
2227 0 : PropertyValue* pValues = rValues.getArray();
2228 :
2229 0 : const SwTextNode* pTextNode( GetTextNode() );
2230 :
2231 0 : sal_Int32 nValues = rValues.getLength();
2232 0 : for (sal_Int32 i = 0; i < nValues; ++i)
2233 : {
2234 0 : PropertyValue& rValue = pValues[i];
2235 :
2236 0 : if (rValue.Name == ChangeAttr.Name )
2237 : {
2238 0 : rValue.Value = ChangeAttr.Value;
2239 0 : continue;
2240 : }
2241 :
2242 0 : if (rValue.Name == ChangeAttrColor.Name )
2243 : {
2244 0 : rValue.Value = ChangeAttrColor.Value;
2245 0 : continue;
2246 : }
2247 :
2248 : //back color
2249 0 : if (rValue.Name == UNO_NAME_CHAR_BACK_COLOR)
2250 : {
2251 0 : uno::Any &anyChar = rValue.Value;
2252 0 : sal_uInt32 crBack = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>(anyChar.pReserved));
2253 0 : if (COL_AUTO == crBack)
2254 : {
2255 0 : uno::Reference<XAccessibleComponent> xComponent(this);
2256 0 : if (xComponent.is())
2257 : {
2258 0 : crBack = (sal_uInt32)xComponent->getBackground();
2259 : }
2260 0 : rValue.Value <<= crBack;
2261 : }
2262 0 : continue;
2263 : }
2264 :
2265 : //char color
2266 0 : if (rValue.Name == UNO_NAME_CHAR_COLOR)
2267 : {
2268 0 : if( GetPortionData().IsInGrayPortion( nIndex ) )
2269 0 : rValue.Value <<= SwViewOption::GetFieldShadingsColor().GetColor();
2270 0 : uno::Any &anyChar = rValue.Value;
2271 0 : sal_uInt32 crChar = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>(anyChar.pReserved));
2272 :
2273 0 : if( COL_AUTO == crChar )
2274 : {
2275 0 : uno::Reference<XAccessibleComponent> xComponent(this);
2276 0 : if (xComponent.is())
2277 : {
2278 0 : Color cr(xComponent->getBackground());
2279 0 : crChar = cr.IsDark() ? COL_WHITE : COL_BLACK;
2280 0 : rValue.Value <<= crChar;
2281 0 : }
2282 : }
2283 0 : continue;
2284 : }
2285 :
2286 : // UnderLine
2287 0 : if (rValue.Name == UNO_NAME_CHAR_UNDERLINE)
2288 : {
2289 : //misspelled word
2290 0 : SwCrsrShell* pCrsrShell = GetCrsrShell();
2291 0 : if( pCrsrShell != NULL && pCrsrShell->GetViewOptions() && pCrsrShell->GetViewOptions()->IsOnlineSpell())
2292 : {
2293 0 : const SwWrongList* pWrongList = pTextNode->GetWrong();
2294 0 : if( NULL != pWrongList )
2295 : {
2296 0 : sal_Int32 nBegin = nIndex;
2297 0 : sal_Int32 nLen = 1;
2298 0 : if( pWrongList->InWrongWord(nBegin,nLen) && !pTextNode->IsSymbol(nBegin) )
2299 : {
2300 0 : rValue.Value <<= (sal_uInt16)UNDERLINE_WAVE;
2301 : }
2302 : }
2303 : }
2304 0 : continue;
2305 : }
2306 :
2307 : // UnderLineColor
2308 0 : if (rValue.Name == UNO_NAME_CHAR_UNDERLINE_COLOR)
2309 : {
2310 : //misspelled word
2311 0 : SwCrsrShell* pCrsrShell = GetCrsrShell();
2312 0 : if( pCrsrShell != NULL && pCrsrShell->GetViewOptions() && pCrsrShell->GetViewOptions()->IsOnlineSpell())
2313 : {
2314 0 : const SwWrongList* pWrongList = pTextNode->GetWrong();
2315 0 : if( NULL != pWrongList )
2316 : {
2317 0 : sal_Int32 nBegin = nIndex;
2318 0 : sal_Int32 nLen = 1;
2319 0 : if( pWrongList->InWrongWord(nBegin,nLen) && !pTextNode->IsSymbol(nBegin) )
2320 : {
2321 0 : rValue.Value <<= (sal_Int32)0x00ff0000;
2322 0 : continue;
2323 : }
2324 : }
2325 : }
2326 :
2327 0 : uno::Any &anyChar = rValue.Value;
2328 0 : sal_uInt32 crUnderline = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>(anyChar.pReserved));
2329 0 : if ( COL_AUTO == crUnderline )
2330 : {
2331 0 : uno::Reference<XAccessibleComponent> xComponent(this);
2332 0 : if (xComponent.is())
2333 : {
2334 0 : Color cr(xComponent->getBackground());
2335 0 : crUnderline = cr.IsDark() ? COL_WHITE : COL_BLACK;
2336 0 : rValue.Value <<= crUnderline;
2337 0 : }
2338 : }
2339 :
2340 0 : continue;
2341 : }
2342 :
2343 : //tab stop
2344 0 : if (rValue.Name == UNO_NAME_TABSTOPS)
2345 : {
2346 0 : com::sun::star::uno::Sequence< ::com::sun::star::style::TabStop > tabs = GetCurrentTabStop( nIndex );
2347 0 : if( !tabs.hasElements() )
2348 : {
2349 0 : tabs.realloc(1);
2350 0 : ::com::sun::star::style::TabStop ts;
2351 0 : com::sun::star::awt::Rectangle rc0 = getCharacterBounds(0);
2352 0 : com::sun::star::awt::Rectangle rc1 = getCharacterBounds(nIndex);
2353 0 : if( rc1.X - rc0.X >= 48 )
2354 0 : ts.Position = (rc1.X - rc0.X) - (rc1.X - rc0.X - 48)% 47 + 47;
2355 : else
2356 0 : ts.Position = 48;
2357 0 : ts.DecimalChar = ' ';
2358 0 : ts.FillChar = ' ';
2359 0 : ts.Alignment = ::com::sun::star::style::TabAlign_LEFT;
2360 0 : tabs[0] = ts;
2361 : }
2362 0 : rValue.Value <<= tabs;
2363 0 : continue;
2364 : }
2365 :
2366 : //number bullet
2367 0 : if (rValue.Name == UNO_NAME_NUMBERING_RULES)
2368 : {
2369 0 : if ( pTextNode->HasBullet() || pTextNode->HasNumber() )
2370 : {
2371 0 : uno::Any aVal;
2372 0 : SwNumRule* pNumRule = pTextNode->GetNumRule();
2373 0 : if (pNumRule)
2374 : {
2375 0 : uno::Reference< container::XIndexReplace > xNum = new SwXNumberingRules(*pNumRule);
2376 0 : aVal.setValue(&xNum, cppu::UnoType<container::XIndexReplace>::get());
2377 : }
2378 0 : rValue.Value <<= aVal;
2379 : }
2380 0 : continue;
2381 : }
2382 :
2383 : //footnote & endnote
2384 0 : if (rValue.Name == UNO_NAME_CHAR_ESCAPEMENT)
2385 : {
2386 0 : if ( GetPortionData().IsIndexInFootnode(nIndex) )
2387 : {
2388 0 : rValue.Value <<= (sal_Int32)101;
2389 : }
2390 0 : continue;
2391 : }
2392 0 : }
2393 0 : }
2394 :
2395 0 : awt::Rectangle SwAccessibleParagraph::getCharacterBounds(
2396 : sal_Int32 nIndex )
2397 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2398 : {
2399 0 : SolarMutexGuard aGuard;
2400 :
2401 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2402 :
2403 : // #i12332# The position after the string needs special treatment.
2404 : // IsValidChar -> IsValidPosition
2405 0 : if( ! (IsValidPosition( nIndex, GetString().getLength() ) ) )
2406 0 : throw lang::IndexOutOfBoundsException();
2407 :
2408 : // #i12332#
2409 0 : bool bBehindText = false;
2410 0 : if ( nIndex == GetString().getLength() )
2411 0 : bBehindText = true;
2412 :
2413 : // get model position & prepare GetCharRect() arguments
2414 0 : SwCrsrMoveState aMoveState;
2415 0 : aMoveState.bRealHeight = true;
2416 0 : aMoveState.bRealWidth = true;
2417 0 : SwSpecialPos aSpecialPos;
2418 0 : SwTextNode* pNode = const_cast<SwTextNode*>( GetTextNode() );
2419 :
2420 : /** #i12332# FillSpecialPos does not accept nIndex ==
2421 : GetString().getLength(). In that case nPos is set to the
2422 : length of the string in the core. This way GetCharRect
2423 : returns the rectangle for a cursor at the end of the
2424 : paragraph. */
2425 : const sal_Int32 nPos = bBehindText
2426 0 : ? pNode->GetText().getLength()
2427 0 : : GetPortionData().FillSpecialPos(nIndex, aSpecialPos, aMoveState.pSpecialPos );
2428 :
2429 : // call GetCharRect
2430 0 : SwRect aCoreRect;
2431 0 : SwIndex aIndex( pNode, nPos );
2432 0 : SwPosition aPosition( *pNode, aIndex );
2433 0 : GetFrm()->GetCharRect( aCoreRect, aPosition, &aMoveState );
2434 :
2435 : // translate core coordinates into accessibility coordinates
2436 0 : vcl::Window *pWin = GetWindow();
2437 0 : CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
2438 :
2439 0 : Rectangle aScreenRect( GetMap()->CoreToPixel( aCoreRect.SVRect() ));
2440 0 : SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root
2441 :
2442 0 : Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() );
2443 0 : aScreenRect.Move( -aFrmPixPos.getX(), -aFrmPixPos.getY() );
2444 :
2445 : // convert into AWT Rectangle
2446 : return awt::Rectangle(
2447 0 : aScreenRect.Left(), aScreenRect.Top(),
2448 0 : aScreenRect.GetWidth(), aScreenRect.GetHeight() );
2449 : }
2450 :
2451 0 : sal_Int32 SwAccessibleParagraph::getCharacterCount()
2452 : throw (uno::RuntimeException, std::exception)
2453 : {
2454 0 : SolarMutexGuard aGuard;
2455 :
2456 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2457 :
2458 0 : return GetString().getLength();
2459 : }
2460 :
2461 0 : sal_Int32 SwAccessibleParagraph::getIndexAtPoint( const awt::Point& rPoint )
2462 : throw (uno::RuntimeException, std::exception)
2463 : {
2464 0 : SolarMutexGuard aGuard;
2465 :
2466 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2467 :
2468 : // construct SwPosition (where GetCrsrOfst() will put the result into)
2469 0 : SwTextNode* pNode = const_cast<SwTextNode*>( GetTextNode() );
2470 0 : SwIndex aIndex( pNode, 0);
2471 0 : SwPosition aPos( *pNode, aIndex );
2472 :
2473 : // construct Point (translate into layout coordinates)
2474 0 : vcl::Window *pWin = GetWindow();
2475 0 : CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
2476 0 : Point aPoint( rPoint.X, rPoint.Y );
2477 0 : SwRect aLogBounds( GetBounds( *(GetMap()), GetFrm() ) ); // twip rel to doc root
2478 0 : Point aPixPos( GetMap()->CoreToPixel( aLogBounds.SVRect() ).TopLeft() );
2479 0 : aPoint.setX(aPoint.getX() + aPixPos.getX());
2480 0 : aPoint.setY(aPoint.getY() + aPixPos.getY());
2481 0 : MapMode aMapMode = pWin->GetMapMode();
2482 0 : Point aCorePoint( GetMap()->PixelToCore( aPoint ) );
2483 0 : if( !aLogBounds.IsInside( aCorePoint ) )
2484 : {
2485 : // #i12332# rPoint is may also be in rectangle returned by
2486 : // getCharacterBounds(getCharacterCount()
2487 :
2488 : awt::Rectangle aRectEndPos =
2489 0 : getCharacterBounds(getCharacterCount());
2490 :
2491 0 : if (rPoint.X - aRectEndPos.X >= 0 &&
2492 0 : rPoint.X - aRectEndPos.X < aRectEndPos.Width &&
2493 0 : rPoint.Y - aRectEndPos.Y >= 0 &&
2494 0 : rPoint.Y - aRectEndPos.Y < aRectEndPos.Height)
2495 0 : return getCharacterCount();
2496 :
2497 0 : return -1;
2498 : }
2499 :
2500 : // ask core for position
2501 : OSL_ENSURE( GetFrm() != NULL, "The text frame has vanished!" );
2502 : OSL_ENSURE( GetFrm()->IsTextFrm(), "The text frame has mutated!" );
2503 0 : const SwTextFrm* pFrm = static_cast<const SwTextFrm*>( GetFrm() );
2504 0 : SwCrsrMoveState aMoveState;
2505 0 : aMoveState.bPosMatchesBounds = true;
2506 0 : const bool bSuccess = pFrm->GetCrsrOfst( &aPos, aCorePoint, &aMoveState );
2507 :
2508 0 : SwIndex aContentIdx = aPos.nContent;
2509 0 : const sal_Int32 nIndex = aContentIdx.GetIndex();
2510 0 : if ( nIndex > 0 )
2511 : {
2512 0 : SwRect aResultRect;
2513 0 : pFrm->GetCharRect( aResultRect, aPos );
2514 0 : bool bVert = pFrm->IsVertical();
2515 0 : bool bR2L = pFrm->IsRightToLeft();
2516 :
2517 0 : if ( (!bVert && aResultRect.Pos().getX() > aCorePoint.getX()) ||
2518 0 : ( bVert && aResultRect.Pos().getY() > aCorePoint.getY()) ||
2519 0 : ( bR2L && aResultRect.Right() < aCorePoint.getX()) )
2520 : {
2521 0 : SwIndex aIdxPrev( pNode, nIndex - 1);
2522 0 : SwPosition aPosPrev( *pNode, aIdxPrev );
2523 0 : SwRect aResultRectPrev;
2524 0 : pFrm->GetCharRect( aResultRectPrev, aPosPrev );
2525 0 : if ( (!bVert && aResultRectPrev.Pos().getX() < aCorePoint.getX() && aResultRect.Pos().getY() == aResultRectPrev.Pos().getY()) ||
2526 0 : ( bVert && aResultRectPrev.Pos().getY() < aCorePoint.getY() && aResultRect.Pos().getX() == aResultRectPrev.Pos().getX()) ||
2527 0 : ( bR2L && aResultRectPrev.Right() > aCorePoint.getX() && aResultRect.Pos().getY() == aResultRectPrev.Pos().getY()) )
2528 0 : aPos = aPosPrev;
2529 : }
2530 : }
2531 :
2532 : return bSuccess ?
2533 0 : GetPortionData().GetAccessiblePosition( aPos.nContent.GetIndex() )
2534 0 : : -1L;
2535 : }
2536 :
2537 0 : OUString SwAccessibleParagraph::getSelectedText()
2538 : throw (uno::RuntimeException, std::exception)
2539 : {
2540 0 : SolarMutexGuard aGuard;
2541 :
2542 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2543 :
2544 : sal_Int32 nStart, nEnd;
2545 0 : bool bSelected = GetSelection( nStart, nEnd );
2546 : return bSelected
2547 : ? GetString().copy( nStart, nEnd - nStart )
2548 0 : : OUString();
2549 : }
2550 :
2551 0 : sal_Int32 SwAccessibleParagraph::getSelectionStart()
2552 : throw (uno::RuntimeException, std::exception)
2553 : {
2554 0 : SolarMutexGuard aGuard;
2555 :
2556 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2557 :
2558 : sal_Int32 nStart, nEnd;
2559 0 : GetSelection( nStart, nEnd );
2560 0 : return nStart;
2561 : }
2562 :
2563 0 : sal_Int32 SwAccessibleParagraph::getSelectionEnd()
2564 : throw (uno::RuntimeException, std::exception)
2565 : {
2566 0 : SolarMutexGuard aGuard;
2567 :
2568 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2569 :
2570 : sal_Int32 nStart, nEnd;
2571 0 : GetSelection( nStart, nEnd );
2572 0 : return nEnd;
2573 : }
2574 :
2575 0 : sal_Bool SwAccessibleParagraph::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
2576 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2577 : {
2578 0 : SolarMutexGuard aGuard;
2579 :
2580 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2581 :
2582 : // parameter checking
2583 0 : sal_Int32 nLength = GetString().getLength();
2584 0 : if ( ! IsValidRange( nStartIndex, nEndIndex, nLength ) )
2585 : {
2586 0 : throw lang::IndexOutOfBoundsException();
2587 : }
2588 :
2589 0 : bool bRet = false;
2590 :
2591 : // get cursor shell
2592 0 : SwCrsrShell* pCrsrShell = GetCrsrShell();
2593 0 : if( pCrsrShell != NULL )
2594 : {
2595 : // create pam for selection
2596 0 : SwTextNode* pNode = const_cast<SwTextNode*>( GetTextNode() );
2597 0 : SwIndex aIndex( pNode, GetPortionData().GetModelPosition(nStartIndex));
2598 0 : SwPosition aStartPos( *pNode, aIndex );
2599 0 : SwPaM aPaM( aStartPos );
2600 0 : aPaM.SetMark();
2601 0 : aPaM.GetPoint()->nContent =
2602 0 : GetPortionData().GetModelPosition(nEndIndex);
2603 :
2604 : // set PaM at cursor shell
2605 0 : bRet = Select( aPaM );
2606 : }
2607 :
2608 0 : return bRet;
2609 : }
2610 :
2611 6 : OUString SwAccessibleParagraph::getText()
2612 : throw (uno::RuntimeException, std::exception)
2613 : {
2614 6 : SolarMutexGuard aGuard;
2615 :
2616 6 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2617 :
2618 6 : return GetString();
2619 : }
2620 :
2621 0 : OUString SwAccessibleParagraph::getTextRange(
2622 : sal_Int32 nStartIndex, sal_Int32 nEndIndex )
2623 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2624 : {
2625 0 : SolarMutexGuard aGuard;
2626 :
2627 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2628 :
2629 0 : OUString sText( GetString() );
2630 :
2631 0 : if ( IsValidRange( nStartIndex, nEndIndex, sText.getLength() ) )
2632 : {
2633 0 : OrderRange( nStartIndex, nEndIndex );
2634 0 : return sText.copy(nStartIndex, nEndIndex-nStartIndex );
2635 : }
2636 : else
2637 0 : throw lang::IndexOutOfBoundsException();
2638 : }
2639 :
2640 0 : /*accessibility::*/TextSegment SwAccessibleParagraph::getTextAtIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException, std::exception)
2641 : {
2642 0 : SolarMutexGuard aGuard;
2643 :
2644 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2645 :
2646 0 : /*accessibility::*/TextSegment aResult;
2647 0 : aResult.SegmentStart = -1;
2648 0 : aResult.SegmentEnd = -1;
2649 :
2650 0 : const OUString rText = GetString();
2651 : // implement the silly specification that first position after
2652 : // text must return an empty string, rather than throwing an
2653 : // IndexOutOfBoundsException, except for LINE, where the last
2654 : // line is returned
2655 0 : if( nIndex == rText.getLength() && AccessibleTextType::LINE != nTextType )
2656 0 : return aResult;
2657 :
2658 : // with error checking
2659 0 : i18n::Boundary aBound;
2660 0 : bool bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
2661 :
2662 : OSL_ENSURE( aBound.startPos >= 0, "illegal boundary" );
2663 : OSL_ENSURE( aBound.startPos <= aBound.endPos, "illegal boundary" );
2664 :
2665 : // return word (if present)
2666 0 : if ( bWord )
2667 : {
2668 0 : aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
2669 0 : aResult.SegmentStart = aBound.startPos;
2670 0 : aResult.SegmentEnd = aBound.endPos;
2671 : }
2672 :
2673 0 : return aResult;
2674 : }
2675 :
2676 0 : /*accessibility::*/TextSegment SwAccessibleParagraph::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException, std::exception)
2677 : {
2678 0 : SolarMutexGuard aGuard;
2679 :
2680 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2681 :
2682 0 : const OUString rText = GetString();
2683 :
2684 0 : /*accessibility::*/TextSegment aResult;
2685 0 : aResult.SegmentStart = -1;
2686 0 : aResult.SegmentEnd = -1;
2687 : //If nIndex = 0, then nobefore text so return -1 directly.
2688 0 : if( nIndex == 0 )
2689 0 : return aResult;
2690 : //Tab will be return when call WORDTYPE
2691 :
2692 : // get starting pos
2693 0 : i18n::Boundary aBound;
2694 0 : if (nIndex == rText.getLength())
2695 0 : aBound.startPos = aBound.endPos = nIndex;
2696 : else
2697 : {
2698 0 : bool bTmp = GetTextBoundary( aBound, rText, nIndex, nTextType );
2699 :
2700 0 : if ( ! bTmp )
2701 0 : aBound.startPos = aBound.endPos = nIndex;
2702 : }
2703 :
2704 : // now skip to previous word
2705 0 : if (nTextType==2 || nTextType == 3)
2706 : {
2707 0 : i18n::Boundary preBound = aBound;
2708 0 : while(preBound.startPos==aBound.startPos && nIndex > 0)
2709 : {
2710 0 : nIndex = min( nIndex, preBound.startPos ) - 1;
2711 0 : if( nIndex < 0 ) break;
2712 0 : GetTextBoundary( preBound, rText, nIndex, nTextType );
2713 : }
2714 : //if (nIndex>0)
2715 0 : if (nIndex>=0)
2716 : //Tab will be return when call WORDTYPE
2717 : {
2718 0 : aResult.SegmentText = rText.copy( preBound.startPos, preBound.endPos - preBound.startPos );
2719 0 : aResult.SegmentStart = preBound.startPos;
2720 0 : aResult.SegmentEnd = preBound.endPos;
2721 0 : }
2722 : }
2723 : else
2724 : {
2725 0 : bool bWord = false;
2726 0 : while( !bWord )
2727 : {
2728 0 : nIndex = min( nIndex, aBound.startPos ) - 1;
2729 0 : if( nIndex >= 0 )
2730 : {
2731 0 : bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
2732 : }
2733 : else
2734 0 : break; // exit if beginning of string is reached
2735 : }
2736 :
2737 0 : if (bWord && nIndex<rText.getLength())
2738 : {
2739 0 : aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
2740 0 : aResult.SegmentStart = aBound.startPos;
2741 0 : aResult.SegmentEnd = aBound.endPos;
2742 : }
2743 : }
2744 0 : return aResult;
2745 : }
2746 :
2747 0 : /*accessibility::*/TextSegment SwAccessibleParagraph::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException, std::exception)
2748 : {
2749 0 : SolarMutexGuard aGuard;
2750 :
2751 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2752 :
2753 0 : /*accessibility::*/TextSegment aResult;
2754 0 : aResult.SegmentStart = -1;
2755 0 : aResult.SegmentEnd = -1;
2756 0 : const OUString rText = GetString();
2757 :
2758 : // implement the silly specification that first position after
2759 : // text must return an empty string, rather than throwing an
2760 : // IndexOutOfBoundsException
2761 0 : if( nIndex == rText.getLength() )
2762 0 : return aResult;
2763 :
2764 : // get first word, then skip to next word
2765 0 : i18n::Boundary aBound;
2766 0 : GetTextBoundary( aBound, rText, nIndex, nTextType );
2767 0 : bool bWord = false;
2768 0 : while( !bWord )
2769 : {
2770 0 : nIndex = max( sal_Int32(nIndex+1), aBound.endPos );
2771 0 : if( nIndex < rText.getLength() )
2772 0 : bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
2773 : else
2774 0 : break; // exit if end of string is reached
2775 : }
2776 :
2777 0 : if ( bWord )
2778 : {
2779 0 : aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
2780 0 : aResult.SegmentStart = aBound.startPos;
2781 0 : aResult.SegmentEnd = aBound.endPos;
2782 : }
2783 :
2784 : /*
2785 : sal_Bool bWord = sal_False;
2786 : bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
2787 :
2788 : if (nTextType==2)
2789 : {
2790 : Boundary nexBound=aBound;
2791 :
2792 : // real current word
2793 : if( nIndex <= aBound.endPos && nIndex >= aBound.startPos )
2794 : {
2795 : while(nexBound.endPos==aBound.endPos&&nIndex<rText.getLength())
2796 : {
2797 : // nIndex = max( (sal_Int32)(nIndex), nexBound.endPos) + 1;
2798 : nIndex = max( (sal_Int32)(nIndex), nexBound.endPos) ;
2799 : const sal_Unicode* pStr = rText.getStr();
2800 : if (pStr)
2801 : {
2802 : if( pStr[nIndex] == sal_Unicode(' ') )
2803 : nIndex++;
2804 : }
2805 : if( nIndex < rText.getLength() )
2806 : {
2807 : bWord = GetTextBoundary( nexBound, rText, nIndex, nTextType );
2808 : }
2809 : }
2810 : }
2811 :
2812 : if (bWord && nIndex<rText.getLength())
2813 : {
2814 : aResult.SegmentText = rText.copy( nexBound.startPos, nexBound.endPos - nexBound.startPos );
2815 : aResult.SegmentStart = nexBound.startPos;
2816 : aResult.SegmentEnd = nexBound.endPos;
2817 : }
2818 :
2819 : }
2820 : else
2821 : {
2822 : bWord = sal_False;
2823 : while( !bWord )
2824 : {
2825 : nIndex = max( (sal_Int32)(nIndex+1), aBound.endPos );
2826 : if( nIndex < rText.getLength() )
2827 : {
2828 : bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
2829 : }
2830 : else
2831 : break; // exit if end of string is reached
2832 : }
2833 : if (bWord && nIndex<rText.getLength())
2834 : {
2835 : aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
2836 : aResult.SegmentStart = aBound.startPos;
2837 : aResult.SegmentEnd = aBound.endPos;
2838 : }
2839 : }
2840 : */
2841 0 : return aResult;
2842 : }
2843 :
2844 0 : sal_Bool SwAccessibleParagraph::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
2845 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2846 : {
2847 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2848 0 : SolarMutexGuard aGuard;
2849 :
2850 : // select and copy (through dispatch mechanism)
2851 0 : setSelection( nStartIndex, nEndIndex );
2852 0 : ExecuteAtViewShell( SID_COPY );
2853 0 : return sal_True;
2854 : }
2855 :
2856 : // XAccesibleEditableText
2857 :
2858 0 : sal_Bool SwAccessibleParagraph::cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
2859 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2860 : {
2861 0 : CHECK_FOR_DEFUNC( XAccessibleEditableText );
2862 0 : SolarMutexGuard aGuard;
2863 :
2864 0 : if( !IsEditableState() )
2865 0 : return sal_False;
2866 :
2867 : // select and cut (through dispatch mechanism)
2868 0 : setSelection( nStartIndex, nEndIndex );
2869 0 : ExecuteAtViewShell( SID_CUT );
2870 0 : return sal_True;
2871 : }
2872 :
2873 0 : sal_Bool SwAccessibleParagraph::pasteText( sal_Int32 nIndex )
2874 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2875 : {
2876 0 : CHECK_FOR_DEFUNC( XAccessibleEditableText );
2877 0 : SolarMutexGuard aGuard;
2878 :
2879 0 : if( !IsEditableState() )
2880 0 : return sal_False;
2881 :
2882 : // select and paste (through dispatch mechanism)
2883 0 : setSelection( nIndex, nIndex );
2884 0 : ExecuteAtViewShell( SID_PASTE );
2885 0 : return sal_True;
2886 : }
2887 :
2888 0 : sal_Bool SwAccessibleParagraph::deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
2889 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2890 : {
2891 0 : return replaceText( nStartIndex, nEndIndex, OUString() );
2892 : }
2893 :
2894 0 : sal_Bool SwAccessibleParagraph::insertText( const OUString& sText, sal_Int32 nIndex )
2895 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2896 : {
2897 0 : return replaceText( nIndex, nIndex, sText );
2898 : }
2899 :
2900 0 : sal_Bool SwAccessibleParagraph::replaceText(
2901 : sal_Int32 nStartIndex, sal_Int32 nEndIndex,
2902 : const OUString& sReplacement )
2903 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2904 : {
2905 0 : SolarMutexGuard aGuard;
2906 :
2907 0 : CHECK_FOR_DEFUNC( XAccessibleEditableText );
2908 :
2909 0 : const OUString& rText = GetString();
2910 :
2911 0 : if( IsValidRange( nStartIndex, nEndIndex, rText.getLength() ) )
2912 : {
2913 0 : if( !IsEditableState() )
2914 0 : return sal_False;
2915 :
2916 0 : SwTextNode* pNode = const_cast<SwTextNode*>( GetTextNode() );
2917 :
2918 : // translate positions
2919 : sal_Int32 nStart;
2920 : sal_Int32 nEnd;
2921 0 : bool bSuccess = GetPortionData().GetEditableRange(
2922 0 : nStartIndex, nEndIndex, nStart, nEnd );
2923 :
2924 : // edit only if the range is editable
2925 0 : if( bSuccess )
2926 : {
2927 : // create SwPosition for nStartIndex
2928 0 : SwIndex aIndex( pNode, nStart );
2929 0 : SwPosition aStartPos( *pNode, aIndex );
2930 :
2931 : // create SwPosition for nEndIndex
2932 0 : SwPosition aEndPos( aStartPos );
2933 0 : aEndPos.nContent = nEnd;
2934 :
2935 : // now create XTextRange as helper and set string
2936 : const uno::Reference<text::XTextRange> xRange(
2937 : SwXTextRange::CreateXTextRange(
2938 0 : *pNode->GetDoc(), aStartPos, &aEndPos));
2939 0 : xRange->setString(sReplacement);
2940 :
2941 : // delete portion data
2942 0 : ClearPortionData();
2943 : }
2944 :
2945 0 : return bSuccess;
2946 : }
2947 : else
2948 0 : throw lang::IndexOutOfBoundsException();
2949 : }
2950 :
2951 0 : sal_Bool SwAccessibleParagraph::setAttributes(
2952 : sal_Int32 nStartIndex,
2953 : sal_Int32 nEndIndex,
2954 : const uno::Sequence<PropertyValue>& rAttributeSet )
2955 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2956 : {
2957 0 : SolarMutexGuard aGuard;
2958 0 : CHECK_FOR_DEFUNC( XAccessibleEditableText );
2959 :
2960 0 : const OUString& rText = GetString();
2961 :
2962 0 : if( ! IsValidRange( nStartIndex, nEndIndex, rText.getLength() ) )
2963 0 : throw lang::IndexOutOfBoundsException();
2964 :
2965 0 : if( !IsEditableState() )
2966 0 : return sal_False;
2967 :
2968 : // create a (dummy) text portion for the sole purpose of calling
2969 : // setPropertyValue on it
2970 : uno::Reference<XMultiPropertySet> xPortion = CreateUnoPortion( nStartIndex,
2971 0 : nEndIndex );
2972 :
2973 : // build sorted index array
2974 0 : sal_Int32 nLength = rAttributeSet.getLength();
2975 0 : const PropertyValue* pPairs = rAttributeSet.getConstArray();
2976 0 : sal_Int32* pIndices = new sal_Int32[nLength];
2977 : sal_Int32 i;
2978 0 : for( i = 0; i < nLength; i++ )
2979 0 : pIndices[i] = i;
2980 0 : sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) );
2981 :
2982 : // create sorted sequences according to index array
2983 0 : uno::Sequence< OUString > aNames( nLength );
2984 0 : OUString* pNames = aNames.getArray();
2985 0 : uno::Sequence< uno::Any > aValues( nLength );
2986 0 : uno::Any* pValues = aValues.getArray();
2987 0 : for( i = 0; i < nLength; i++ )
2988 : {
2989 0 : const PropertyValue& rVal = pPairs[pIndices[i]];
2990 0 : pNames[i] = rVal.Name;
2991 0 : pValues[i] = rVal.Value;
2992 : }
2993 0 : delete[] pIndices;
2994 :
2995 : // now set the values
2996 0 : bool bRet = true;
2997 : try
2998 : {
2999 0 : xPortion->setPropertyValues( aNames, aValues );
3000 : }
3001 0 : catch (const UnknownPropertyException&)
3002 : {
3003 : // error handling through return code!
3004 0 : bRet = false;
3005 : }
3006 :
3007 0 : return bRet;
3008 : }
3009 :
3010 0 : sal_Bool SwAccessibleParagraph::setText( const OUString& sText )
3011 : throw (uno::RuntimeException, std::exception)
3012 : {
3013 0 : return replaceText(0, GetString().getLength(), sText);
3014 : }
3015 :
3016 : // XAccessibleSelection
3017 :
3018 2 : void SwAccessibleParagraph::selectAccessibleChild(
3019 : sal_Int32 nChildIndex )
3020 : throw ( lang::IndexOutOfBoundsException,
3021 : uno::RuntimeException, std::exception )
3022 : {
3023 2 : CHECK_FOR_DEFUNC( XAccessibleSelection );
3024 :
3025 2 : aSelectionHelper.selectAccessibleChild(nChildIndex);
3026 0 : }
3027 :
3028 2 : sal_Bool SwAccessibleParagraph::isAccessibleChildSelected(
3029 : sal_Int32 nChildIndex )
3030 : throw ( lang::IndexOutOfBoundsException,
3031 : uno::RuntimeException, std::exception )
3032 : {
3033 2 : CHECK_FOR_DEFUNC( XAccessibleSelection );
3034 :
3035 2 : return aSelectionHelper.isAccessibleChildSelected(nChildIndex);
3036 : }
3037 :
3038 2 : void SwAccessibleParagraph::clearAccessibleSelection( )
3039 : throw ( uno::RuntimeException, std::exception )
3040 : {
3041 2 : CHECK_FOR_DEFUNC( XAccessibleSelection );
3042 2 : }
3043 :
3044 3 : void SwAccessibleParagraph::selectAllAccessibleChildren( )
3045 : throw ( uno::RuntimeException, std::exception )
3046 : {
3047 3 : CHECK_FOR_DEFUNC( XAccessibleSelection );
3048 :
3049 3 : aSelectionHelper.selectAllAccessibleChildren();
3050 3 : }
3051 :
3052 5 : sal_Int32 SwAccessibleParagraph::getSelectedAccessibleChildCount( )
3053 : throw ( uno::RuntimeException, std::exception )
3054 : {
3055 5 : CHECK_FOR_DEFUNC( XAccessibleSelection );
3056 :
3057 5 : return aSelectionHelper.getSelectedAccessibleChildCount();
3058 : }
3059 :
3060 2 : uno::Reference<XAccessible> SwAccessibleParagraph::getSelectedAccessibleChild(
3061 : sal_Int32 nSelectedChildIndex )
3062 : throw ( lang::IndexOutOfBoundsException,
3063 : uno::RuntimeException, std::exception)
3064 : {
3065 2 : CHECK_FOR_DEFUNC( XAccessibleSelection );
3066 :
3067 2 : return aSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex);
3068 : }
3069 :
3070 : // index has to be treated as global child index.
3071 2 : void SwAccessibleParagraph::deselectAccessibleChild(
3072 : sal_Int32 nChildIndex )
3073 : throw ( lang::IndexOutOfBoundsException,
3074 : uno::RuntimeException, std::exception )
3075 : {
3076 2 : CHECK_FOR_DEFUNC( XAccessibleSelection );
3077 :
3078 2 : aSelectionHelper.deselectAccessibleChild( nChildIndex );
3079 0 : }
3080 :
3081 : // XAccessibleHypertext
3082 :
3083 : class SwHyperlinkIter_Impl
3084 : {
3085 : const SwpHints *pHints;
3086 : sal_Int32 nStt;
3087 : sal_Int32 nEnd;
3088 : size_t nPos;
3089 :
3090 : public:
3091 : explicit SwHyperlinkIter_Impl( const SwTextFrm *pTextFrm );
3092 : const SwTextAttr *next();
3093 0 : size_t getCurrHintPos() const { return nPos-1; }
3094 :
3095 0 : sal_Int32 startIdx() const { return nStt; }
3096 0 : sal_Int32 endIdx() const { return nEnd; }
3097 : };
3098 :
3099 0 : SwHyperlinkIter_Impl::SwHyperlinkIter_Impl( const SwTextFrm *pTextFrm ) :
3100 0 : pHints( pTextFrm->GetTextNode()->GetpSwpHints() ),
3101 0 : nStt( pTextFrm->GetOfst() ),
3102 0 : nPos( 0 )
3103 : {
3104 0 : const SwTextFrm *pFollFrm = pTextFrm->GetFollow();
3105 0 : nEnd = pFollFrm ? pFollFrm->GetOfst() : pTextFrm->GetTextNode()->Len();
3106 0 : }
3107 :
3108 0 : const SwTextAttr *SwHyperlinkIter_Impl::next()
3109 : {
3110 0 : const SwTextAttr *pAttr = 0;
3111 0 : if( pHints )
3112 : {
3113 0 : while( !pAttr && nPos < pHints->Count() )
3114 : {
3115 0 : const SwTextAttr *pHt = (*pHints)[nPos];
3116 0 : if( RES_TXTATR_INETFMT == pHt->Which() )
3117 : {
3118 0 : const sal_Int32 nHtStt = pHt->GetStart();
3119 0 : const sal_Int32 nHtEnd = *pHt->GetAnyEnd();
3120 0 : if( nHtEnd > nHtStt &&
3121 0 : ( (nHtStt >= nStt && nHtStt < nEnd) ||
3122 0 : (nHtEnd > nStt && nHtEnd <= nEnd) ) )
3123 : {
3124 0 : pAttr = pHt;
3125 : }
3126 : }
3127 0 : ++nPos;
3128 : }
3129 : }
3130 :
3131 0 : return pAttr;
3132 : };
3133 :
3134 0 : sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkCount()
3135 : throw (uno::RuntimeException, std::exception)
3136 : {
3137 0 : SolarMutexGuard aGuard;
3138 :
3139 0 : CHECK_FOR_DEFUNC( XAccessibleHypertext );
3140 :
3141 0 : sal_Int32 nCount = 0;
3142 : // #i77108# - provide hyperlinks also in editable documents.
3143 :
3144 0 : const SwTextFrm *pTextFrm = static_cast<const SwTextFrm*>( GetFrm() );
3145 0 : SwHyperlinkIter_Impl aIter( pTextFrm );
3146 0 : while( aIter.next() )
3147 0 : nCount++;
3148 :
3149 0 : return nCount;
3150 : }
3151 :
3152 : uno::Reference< XAccessibleHyperlink > SAL_CALL
3153 0 : SwAccessibleParagraph::getHyperLink( sal_Int32 nLinkIndex )
3154 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
3155 : {
3156 0 : SolarMutexGuard aGuard;
3157 0 : CHECK_FOR_DEFUNC( XAccessibleHypertext );
3158 :
3159 0 : uno::Reference< XAccessibleHyperlink > xRet;
3160 :
3161 0 : const SwTextFrm *pTextFrm = static_cast<const SwTextFrm*>( GetFrm() );
3162 0 : SwHyperlinkIter_Impl aHIter( pTextFrm );
3163 0 : sal_Int32 nTIndex = -1;
3164 0 : SwTOXSortTabBase* pTBase = GetTOXSortTabBase();
3165 0 : SwTextAttr* pHt = const_cast<SwTextAttr*>(aHIter.next());
3166 0 : while( (nLinkIndex < getHyperLinkCount()) && nTIndex < nLinkIndex)
3167 : {
3168 0 : sal_Int32 nHStt = -1;
3169 0 : bool bH = false;
3170 :
3171 0 : if( pHt )
3172 0 : nHStt = pHt->GetStart();
3173 0 : bool bTOC = false;
3174 : // Inside TOC & get the first link
3175 0 : if( pTBase && nTIndex == -1 )
3176 : {
3177 0 : nTIndex++;
3178 0 : bTOC = true;
3179 : }
3180 0 : else if( nHStt >= 0 )
3181 : {
3182 : // only hyperlink available
3183 0 : nTIndex++;
3184 0 : bH = true;
3185 : }
3186 :
3187 0 : if( nTIndex == nLinkIndex )
3188 : { // found
3189 0 : if( bH )
3190 : { // it's a hyperlink
3191 0 : if( pHt )
3192 : {
3193 0 : if( !pHyperTextData )
3194 0 : pHyperTextData = new SwAccessibleHyperTextData;
3195 : SwAccessibleHyperTextData::iterator aIter =
3196 0 : pHyperTextData ->find( pHt );
3197 0 : if( aIter != pHyperTextData->end() )
3198 : {
3199 0 : xRet = (*aIter).second;
3200 : }
3201 0 : if( !xRet.is() )
3202 : {
3203 : {
3204 0 : const sal_Int32 nTmpHStt= GetPortionData().GetAccessiblePosition(
3205 0 : max( aHIter.startIdx(), pHt->GetStart() ) );
3206 0 : const sal_Int32 nTmpHEnd= GetPortionData().GetAccessiblePosition(
3207 0 : min( aHIter.endIdx(), *pHt->GetAnyEnd() ) );
3208 0 : xRet = new SwAccessibleHyperlink( aHIter.getCurrHintPos(),
3209 0 : this, nTmpHStt, nTmpHEnd );
3210 : }
3211 0 : if( aIter != pHyperTextData->end() )
3212 : {
3213 0 : (*aIter).second = xRet;
3214 : }
3215 : else
3216 : {
3217 0 : SwAccessibleHyperTextData::value_type aEntry( pHt, xRet );
3218 0 : pHyperTextData->insert( aEntry );
3219 : }
3220 : }
3221 : }
3222 : }
3223 0 : break;
3224 : }
3225 :
3226 : // iterate next
3227 0 : if( bH )
3228 : // iterate next hyperlink
3229 0 : pHt = const_cast<SwTextAttr*>(aHIter.next());
3230 0 : else if(bTOC)
3231 0 : continue;
3232 : else
3233 : // no candidate, exit
3234 0 : break;
3235 : }
3236 0 : if( !xRet.is() )
3237 0 : throw lang::IndexOutOfBoundsException();
3238 :
3239 0 : return xRet;
3240 : }
3241 :
3242 0 : sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkIndex( sal_Int32 nCharIndex )
3243 : throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
3244 : {
3245 0 : SolarMutexGuard aGuard;
3246 0 : CHECK_FOR_DEFUNC( XAccessibleHypertext );
3247 :
3248 : // parameter checking
3249 0 : sal_Int32 nLength = GetString().getLength();
3250 0 : if ( ! IsValidPosition( nCharIndex, nLength ) )
3251 : {
3252 0 : throw lang::IndexOutOfBoundsException();
3253 : }
3254 :
3255 0 : sal_Int32 nRet = -1;
3256 : // #i77108#
3257 : {
3258 0 : const SwTextFrm *pTextFrm = static_cast<const SwTextFrm*>( GetFrm() );
3259 0 : SwHyperlinkIter_Impl aHIter( pTextFrm );
3260 :
3261 0 : const sal_Int32 nIdx = GetPortionData().GetModelPosition( nCharIndex );
3262 0 : sal_Int32 nPos = 0;
3263 0 : const SwTextAttr *pHt = aHIter.next();
3264 0 : while( pHt && !(nIdx >= pHt->GetStart() && nIdx < *pHt->GetAnyEnd()) )
3265 : {
3266 0 : pHt = aHIter.next();
3267 0 : nPos++;
3268 : }
3269 :
3270 0 : if( pHt )
3271 0 : nRet = nPos;
3272 : }
3273 :
3274 0 : if (nRet == -1)
3275 0 : throw lang::IndexOutOfBoundsException();
3276 : else
3277 0 : return nRet;
3278 : //return nRet;
3279 : }
3280 :
3281 : // #i71360#, #i108125# - adjustments for change tracking text markup
3282 0 : sal_Int32 SAL_CALL SwAccessibleParagraph::getTextMarkupCount( sal_Int32 nTextMarkupType )
3283 : throw (lang::IllegalArgumentException,
3284 : uno::RuntimeException, std::exception)
3285 : {
3286 0 : boost::scoped_ptr<SwTextMarkupHelper> pTextMarkupHelper;
3287 0 : switch ( nTextMarkupType )
3288 : {
3289 : case text::TextMarkupType::TRACK_CHANGE_INSERTION:
3290 : case text::TextMarkupType::TRACK_CHANGE_DELETION:
3291 : case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
3292 : {
3293 : pTextMarkupHelper.reset( new SwTextMarkupHelper(
3294 : GetPortionData(),
3295 0 : *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
3296 : }
3297 0 : break;
3298 : default:
3299 : {
3300 0 : pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTextNode() ) );
3301 : }
3302 : }
3303 :
3304 0 : return pTextMarkupHelper->getTextMarkupCount( nTextMarkupType );
3305 : }
3306 :
3307 : //MSAA Extension Implementation in app module
3308 0 : sal_Bool SAL_CALL SwAccessibleParagraph::scrollToPosition( const ::com::sun::star::awt::Point&, sal_Bool )
3309 : throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
3310 : {
3311 0 : return sal_False;
3312 : }
3313 :
3314 0 : sal_Int32 SAL_CALL SwAccessibleParagraph::getSelectedPortionCount( )
3315 : throw (::com::sun::star::uno::RuntimeException,
3316 : std::exception)
3317 : {
3318 0 : SolarMutexGuard g;
3319 :
3320 0 : sal_Int32 nSeleted = 0;
3321 0 : SwPaM* pCrsr = GetCursor( true );
3322 0 : if( pCrsr != NULL )
3323 : {
3324 : // get SwPosition for my node
3325 0 : const SwTextNode* pNode = GetTextNode();
3326 0 : sal_uLong nHere = pNode->GetIndex();
3327 :
3328 : // iterate over ring
3329 0 : for(SwPaM& rTmpCrsr : pCrsr->GetRingContainer())
3330 : {
3331 : // ignore, if no mark
3332 0 : if( rTmpCrsr.HasMark() )
3333 : {
3334 : // check whether nHere is 'inside' pCrsr
3335 0 : SwPosition* pStart = rTmpCrsr.Start();
3336 0 : sal_uLong nStartIndex = pStart->nNode.GetIndex();
3337 0 : SwPosition* pEnd = rTmpCrsr.End();
3338 0 : sal_uLong nEndIndex = pEnd->nNode.GetIndex();
3339 0 : if( ( nHere >= nStartIndex ) &&
3340 : ( nHere <= nEndIndex ) )
3341 : {
3342 0 : nSeleted++;
3343 : }
3344 : // else: this PaM doesn't point to this paragraph
3345 : }
3346 : // else: this PaM is collapsed and doesn't select anything
3347 : }
3348 : }
3349 0 : return nSeleted;
3350 :
3351 : }
3352 :
3353 0 : sal_Int32 SAL_CALL SwAccessibleParagraph::getSeletedPositionStart( sal_Int32 nSelectedPortionIndex )
3354 : throw (::com::sun::star::lang::IndexOutOfBoundsException,
3355 : ::com::sun::star::uno::RuntimeException,
3356 : std::exception)
3357 : {
3358 0 : SolarMutexGuard aGuard;
3359 :
3360 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
3361 :
3362 : sal_Int32 nStart, nEnd;
3363 0 : /*sal_Bool bSelected = */GetSelectionAtIndex(nSelectedPortionIndex, nStart, nEnd );
3364 0 : return nStart;
3365 : }
3366 :
3367 0 : sal_Int32 SAL_CALL SwAccessibleParagraph::getSeletedPositionEnd( sal_Int32 nSelectedPortionIndex )
3368 : throw (::com::sun::star::lang::IndexOutOfBoundsException,
3369 : ::com::sun::star::uno::RuntimeException,
3370 : std::exception)
3371 : {
3372 0 : SolarMutexGuard aGuard;
3373 :
3374 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
3375 :
3376 : sal_Int32 nStart, nEnd;
3377 0 : /*sal_Bool bSelected = */GetSelectionAtIndex(nSelectedPortionIndex, nStart, nEnd );
3378 0 : return nEnd;
3379 : }
3380 :
3381 0 : sal_Bool SAL_CALL SwAccessibleParagraph::removeSelection( sal_Int32 selectionIndex )
3382 : throw (::com::sun::star::lang::IndexOutOfBoundsException,
3383 : ::com::sun::star::uno::RuntimeException,
3384 : std::exception)
3385 : {
3386 0 : SolarMutexGuard g;
3387 :
3388 0 : if(selectionIndex < 0) return sal_False;
3389 :
3390 0 : sal_Int32 nSelected = selectionIndex;
3391 :
3392 : // get the selection, and test whether it affects our text node
3393 0 : SwPaM* pCrsr = GetCursor( true );
3394 :
3395 0 : if( pCrsr != NULL )
3396 : {
3397 0 : bool bRet = false;
3398 :
3399 : // get SwPosition for my node
3400 0 : const SwTextNode* pNode = GetTextNode();
3401 0 : sal_uLong nHere = pNode->GetIndex();
3402 :
3403 : // iterate over ring
3404 0 : SwPaM* pRingStart = pCrsr;
3405 0 : do
3406 : {
3407 : // ignore, if no mark
3408 0 : if( pCrsr->HasMark() )
3409 : {
3410 : // check whether nHere is 'inside' pCrsr
3411 0 : SwPosition* pStart = pCrsr->Start();
3412 0 : sal_uLong nStartIndex = pStart->nNode.GetIndex();
3413 0 : SwPosition* pEnd = pCrsr->End();
3414 0 : sal_uLong nEndIndex = pEnd->nNode.GetIndex();
3415 0 : if( ( nHere >= nStartIndex ) &&
3416 : ( nHere <= nEndIndex ) )
3417 : {
3418 0 : if( nSelected == 0 )
3419 : {
3420 0 : pCrsr->MoveTo(nullptr);
3421 0 : delete pCrsr;
3422 0 : bRet = true;
3423 : }
3424 : else
3425 : {
3426 0 : nSelected--;
3427 : }
3428 : }
3429 : }
3430 : // else: this PaM is collapsed and doesn't select anything
3431 0 : if(!bRet)
3432 0 : pCrsr = pCrsr->GetNext();
3433 : }
3434 0 : while( !bRet && (pCrsr != pRingStart) );
3435 : }
3436 0 : return sal_True;
3437 : }
3438 :
3439 0 : sal_Int32 SAL_CALL SwAccessibleParagraph::addSelection( sal_Int32, sal_Int32 startOffset, sal_Int32 endOffset)
3440 : throw (::com::sun::star::lang::IndexOutOfBoundsException,
3441 : ::com::sun::star::uno::RuntimeException,
3442 : std::exception)
3443 : {
3444 0 : SolarMutexGuard aGuard;
3445 :
3446 0 : CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
3447 :
3448 : // parameter checking
3449 0 : sal_Int32 nLength = GetString().getLength();
3450 0 : if ( ! IsValidRange( startOffset, endOffset, nLength ) )
3451 : {
3452 0 : throw lang::IndexOutOfBoundsException();
3453 : }
3454 :
3455 0 : sal_Int32 nSelectedCount = getSelectedPortionCount();
3456 0 : for ( sal_Int32 i = nSelectedCount ; i >= 0 ; i--)
3457 : {
3458 : sal_Int32 nStart, nEnd;
3459 0 : bool bSelected = GetSelectionAtIndex(i, nStart, nEnd );
3460 0 : if(bSelected)
3461 : {
3462 0 : if(nStart <= nEnd )
3463 : {
3464 0 : if (( startOffset>=nStart && startOffset <=nEnd ) || //startOffset in a selection
3465 0 : ( endOffset>=nStart && endOffset <=nEnd ) || //endOffset in a selection
3466 0 : ( startOffset <= nStart && endOffset >=nEnd) || //start and end include the old selection
3467 0 : ( startOffset >= nStart && endOffset <=nEnd) )
3468 : {
3469 0 : removeSelection(i);
3470 : }
3471 :
3472 : }
3473 : else
3474 : {
3475 0 : if (( startOffset>=nEnd && startOffset <=nStart ) || //startOffset in a selection
3476 0 : ( endOffset>=nEnd && endOffset <=nStart ) || //endOffset in a selection
3477 0 : ( startOffset <= nStart && endOffset >=nEnd) || //start and end include the old selection
3478 0 : ( startOffset >= nStart && endOffset <=nEnd) )
3479 :
3480 : {
3481 0 : removeSelection(i);
3482 : }
3483 : }
3484 : }
3485 :
3486 : }
3487 :
3488 : // get cursor shell
3489 0 : SwCrsrShell* pCrsrShell = GetCrsrShell();
3490 0 : if( pCrsrShell != NULL )
3491 : {
3492 : // create pam for selection
3493 0 : pCrsrShell->StartAction();
3494 0 : SwPaM* aPaM = pCrsrShell->CreateCrsr();
3495 0 : aPaM->SetMark();
3496 0 : aPaM->GetPoint()->nContent = GetPortionData().GetModelPosition(startOffset);
3497 0 : aPaM->GetMark()->nContent = GetPortionData().GetModelPosition(endOffset);
3498 0 : pCrsrShell->EndAction();
3499 : }
3500 :
3501 0 : return 0;
3502 : }
3503 :
3504 : /*accessibility::*/TextSegment SAL_CALL
3505 0 : SwAccessibleParagraph::getTextMarkup( sal_Int32 nTextMarkupIndex,
3506 : sal_Int32 nTextMarkupType )
3507 : throw (lang::IndexOutOfBoundsException,
3508 : lang::IllegalArgumentException,
3509 : uno::RuntimeException, std::exception)
3510 : {
3511 0 : boost::scoped_ptr<SwTextMarkupHelper> pTextMarkupHelper;
3512 0 : switch ( nTextMarkupType )
3513 : {
3514 : case text::TextMarkupType::TRACK_CHANGE_INSERTION:
3515 : case text::TextMarkupType::TRACK_CHANGE_DELETION:
3516 : case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
3517 : {
3518 : pTextMarkupHelper.reset( new SwTextMarkupHelper(
3519 : GetPortionData(),
3520 0 : *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
3521 : }
3522 0 : break;
3523 : default:
3524 : {
3525 0 : pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTextNode() ) );
3526 : }
3527 : }
3528 :
3529 0 : return pTextMarkupHelper->getTextMarkup( nTextMarkupIndex, nTextMarkupType );
3530 : }
3531 :
3532 : uno::Sequence< /*accessibility::*/TextSegment > SAL_CALL
3533 0 : SwAccessibleParagraph::getTextMarkupAtIndex( sal_Int32 nCharIndex,
3534 : sal_Int32 nTextMarkupType )
3535 : throw (lang::IndexOutOfBoundsException,
3536 : lang::IllegalArgumentException,
3537 : uno::RuntimeException, std::exception)
3538 : {
3539 : // parameter checking
3540 0 : const sal_Int32 nLength = GetString().getLength();
3541 0 : if ( ! IsValidPosition( nCharIndex, nLength ) )
3542 : {
3543 0 : throw lang::IndexOutOfBoundsException();
3544 : }
3545 :
3546 0 : boost::scoped_ptr<SwTextMarkupHelper> pTextMarkupHelper;
3547 0 : switch ( nTextMarkupType )
3548 : {
3549 : case text::TextMarkupType::TRACK_CHANGE_INSERTION:
3550 : case text::TextMarkupType::TRACK_CHANGE_DELETION:
3551 : case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
3552 : {
3553 : pTextMarkupHelper.reset( new SwTextMarkupHelper(
3554 : GetPortionData(),
3555 0 : *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
3556 : }
3557 0 : break;
3558 : default:
3559 : {
3560 0 : pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTextNode() ) );
3561 : }
3562 : }
3563 :
3564 0 : return pTextMarkupHelper->getTextMarkupAtIndex( nCharIndex, nTextMarkupType );
3565 : }
3566 :
3567 : // #i89175#
3568 0 : sal_Int32 SAL_CALL SwAccessibleParagraph::getLineNumberAtIndex( sal_Int32 nIndex )
3569 : throw (lang::IndexOutOfBoundsException,
3570 : uno::RuntimeException, std::exception)
3571 : {
3572 : // parameter checking
3573 0 : const sal_Int32 nLength = GetString().getLength();
3574 0 : if ( ! IsValidPosition( nIndex, nLength ) )
3575 : {
3576 0 : throw lang::IndexOutOfBoundsException();
3577 : }
3578 :
3579 0 : const sal_Int32 nLineNo = GetPortionData().GetLineNo( nIndex );
3580 0 : return nLineNo;
3581 : }
3582 :
3583 : /*accessibility::*/TextSegment SAL_CALL
3584 0 : SwAccessibleParagraph::getTextAtLineNumber( sal_Int32 nLineNo )
3585 : throw (lang::IndexOutOfBoundsException,
3586 : uno::RuntimeException, std::exception)
3587 : {
3588 : // parameter checking
3589 0 : if ( nLineNo < 0 ||
3590 0 : nLineNo >= GetPortionData().GetLineCount() )
3591 : {
3592 0 : throw lang::IndexOutOfBoundsException();
3593 : }
3594 :
3595 0 : i18n::Boundary aLineBound;
3596 0 : GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound );
3597 :
3598 0 : /*accessibility::*/TextSegment aTextAtLine;
3599 0 : const OUString rText = GetString();
3600 0 : aTextAtLine.SegmentText = rText.copy( aLineBound.startPos,
3601 0 : aLineBound.endPos - aLineBound.startPos );
3602 0 : aTextAtLine.SegmentStart = aLineBound.startPos;
3603 0 : aTextAtLine.SegmentEnd = aLineBound.endPos;
3604 :
3605 0 : return aTextAtLine;
3606 : }
3607 :
3608 0 : /*accessibility::*/TextSegment SAL_CALL SwAccessibleParagraph::getTextAtLineWithCaret()
3609 : throw (uno::RuntimeException, std::exception)
3610 : {
3611 0 : const sal_Int32 nLineNoOfCaret = getNumberOfLineWithCaret();
3612 :
3613 0 : if ( nLineNoOfCaret >= 0 &&
3614 0 : nLineNoOfCaret < GetPortionData().GetLineCount() )
3615 : {
3616 0 : return getTextAtLineNumber( nLineNoOfCaret );
3617 : }
3618 :
3619 0 : return /*accessibility::*/TextSegment();
3620 : }
3621 :
3622 0 : sal_Int32 SAL_CALL SwAccessibleParagraph::getNumberOfLineWithCaret()
3623 : throw (uno::RuntimeException, std::exception)
3624 : {
3625 0 : const sal_Int32 nCaretPos = getCaretPosition();
3626 0 : const sal_Int32 nLength = GetString().getLength();
3627 0 : if ( !IsValidPosition( nCaretPos, nLength ) )
3628 : {
3629 0 : return -1;
3630 : }
3631 :
3632 0 : sal_Int32 nLineNo = GetPortionData().GetLineNo( nCaretPos );
3633 :
3634 : // special handling for cursor positioned at end of text line via End key
3635 0 : if ( nCaretPos != 0 )
3636 : {
3637 0 : i18n::Boundary aLineBound;
3638 0 : GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound );
3639 0 : if ( nCaretPos == aLineBound.startPos )
3640 : {
3641 0 : SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell();
3642 0 : if ( pCrsrShell != 0 )
3643 : {
3644 0 : const awt::Rectangle aCharRect = getCharacterBounds( nCaretPos );
3645 :
3646 0 : const SwRect& aCursorCoreRect = pCrsrShell->GetCharRect();
3647 : // translate core coordinates into accessibility coordinates
3648 0 : vcl::Window *pWin = GetWindow();
3649 0 : CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
3650 :
3651 0 : Rectangle aScreenRect( GetMap()->CoreToPixel( aCursorCoreRect.SVRect() ));
3652 :
3653 0 : SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root
3654 0 : Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() );
3655 0 : aScreenRect.Move( -aFrmPixPos.getX(), -aFrmPixPos.getY() );
3656 :
3657 : // convert into AWT Rectangle
3658 0 : const awt::Rectangle aCursorRect( aScreenRect.Left(),
3659 0 : aScreenRect.Top(),
3660 0 : aScreenRect.GetWidth(),
3661 0 : aScreenRect.GetHeight() );
3662 :
3663 0 : if ( aCharRect.X != aCursorRect.X ||
3664 0 : aCharRect.Y != aCursorRect.Y )
3665 : {
3666 0 : --nLineNo;
3667 : }
3668 : }
3669 : }
3670 : }
3671 :
3672 0 : return nLineNo;
3673 : }
3674 :
3675 : // #i108125#
3676 72 : void SwAccessibleParagraph::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
3677 : {
3678 72 : mpParaChangeTrackInfo->reset();
3679 :
3680 72 : CheckRegistration( pOld, pNew );
3681 72 : }
3682 :
3683 0 : bool SwAccessibleParagraph::GetSelectionAtIndex(
3684 : sal_Int32& nIndex, sal_Int32& nStart, sal_Int32& nEnd)
3685 : {
3686 0 : if(nIndex < 0) return false;
3687 :
3688 0 : bool bRet = false;
3689 0 : nStart = -1;
3690 0 : nEnd = -1;
3691 0 : sal_Int32 nSelected = nIndex;
3692 :
3693 : // get the selection, and test whether it affects our text node
3694 0 : SwPaM* pCrsr = GetCursor( true );
3695 0 : if( pCrsr != NULL )
3696 : {
3697 : // get SwPosition for my node
3698 0 : const SwTextNode* pNode = GetTextNode();
3699 0 : sal_uLong nHere = pNode->GetIndex();
3700 :
3701 : // iterate over ring
3702 0 : for(SwPaM& rTmpCrsr : pCrsr->GetRingContainer())
3703 : {
3704 : // ignore, if no mark
3705 0 : if( rTmpCrsr.HasMark() )
3706 : {
3707 : // check whether nHere is 'inside' pCrsr
3708 0 : SwPosition* pStart = rTmpCrsr.Start();
3709 0 : sal_uLong nStartIndex = pStart->nNode.GetIndex();
3710 0 : SwPosition* pEnd = rTmpCrsr.End();
3711 0 : sal_uLong nEndIndex = pEnd->nNode.GetIndex();
3712 0 : if( ( nHere >= nStartIndex ) &&
3713 : ( nHere <= nEndIndex ) )
3714 : {
3715 0 : if( nSelected == 0 )
3716 : {
3717 : // translate start and end positions
3718 :
3719 : // start position
3720 0 : sal_Int32 nLocalStart = -1;
3721 0 : if( nHere > nStartIndex )
3722 : {
3723 : // selection starts in previous node:
3724 : // then our local selection starts with the paragraph
3725 0 : nLocalStart = 0;
3726 : }
3727 : else
3728 : {
3729 : assert(nHere == nStartIndex);
3730 :
3731 : // selection starts in this node:
3732 : // then check whether it's before or inside our part of
3733 : // the paragraph, and if so, get the proper position
3734 0 : const sal_Int32 nCoreStart = pStart->nContent.GetIndex();
3735 0 : if( nCoreStart <
3736 0 : GetPortionData().GetFirstValidCorePosition() )
3737 : {
3738 0 : nLocalStart = 0;
3739 : }
3740 0 : else if( nCoreStart <=
3741 0 : GetPortionData().GetLastValidCorePosition() )
3742 : {
3743 : SAL_WARN_IF(
3744 : GetPortionData().IsValidCorePosition(
3745 : nCoreStart),
3746 : "sw.core",
3747 : "problem determining valid core position");
3748 :
3749 : nLocalStart =
3750 0 : GetPortionData().GetAccessiblePosition(
3751 0 : nCoreStart );
3752 : }
3753 : }
3754 :
3755 : // end position
3756 0 : sal_Int32 nLocalEnd = -1;
3757 0 : if( nHere < nEndIndex )
3758 : {
3759 : // selection ends in following node:
3760 : // then our local selection extends to the end
3761 0 : nLocalEnd = GetPortionData().GetAccessibleString().
3762 0 : getLength();
3763 : }
3764 : else
3765 : {
3766 : assert(nHere == nEndIndex);
3767 :
3768 : // selection ends in this node: then select everything
3769 : // before our part of the node
3770 0 : const sal_Int32 nCoreEnd = pEnd->nContent.GetIndex();
3771 0 : if( nCoreEnd >
3772 0 : GetPortionData().GetLastValidCorePosition() )
3773 : {
3774 : // selection extends beyond out part of this para
3775 0 : nLocalEnd = GetPortionData().GetAccessibleString().
3776 0 : getLength();
3777 : }
3778 0 : else if( nCoreEnd >=
3779 0 : GetPortionData().GetFirstValidCorePosition() )
3780 : {
3781 : // selection is inside our part of this para
3782 : SAL_WARN_IF(
3783 : GetPortionData().IsValidCorePosition(
3784 : nCoreEnd),
3785 : "sw.core",
3786 : "problem determining valid core position");
3787 :
3788 0 : nLocalEnd = GetPortionData().GetAccessiblePosition(
3789 0 : nCoreEnd );
3790 : }
3791 : }
3792 :
3793 0 : if( ( nLocalStart != -1 ) && ( nLocalEnd != -1 ) )
3794 : {
3795 0 : nStart = nLocalStart;
3796 0 : nEnd = nLocalEnd;
3797 0 : bRet = true;
3798 : }
3799 : } // if hit the index
3800 : else
3801 : {
3802 0 : nSelected--;
3803 : }
3804 : }
3805 : // else: this PaM doesn't point to this paragraph
3806 : }
3807 : // else: this PaM is collapsed and doesn't select anything
3808 0 : if(bRet)
3809 0 : break;
3810 : }
3811 : }
3812 : // else: nocursor -> no selection
3813 :
3814 0 : if( bRet )
3815 : {
3816 0 : sal_Int32 nCaretPos = GetCaretPos();
3817 0 : if( nStart == nCaretPos )
3818 : {
3819 0 : sal_Int32 tmp = nStart;
3820 0 : nStart = nEnd;
3821 0 : nEnd = tmp;
3822 : }
3823 : }
3824 0 : return bRet;
3825 : }
3826 :
3827 21 : sal_Int16 SAL_CALL SwAccessibleParagraph::getAccessibleRole() throw (::com::sun::star::uno::RuntimeException, std::exception)
3828 : {
3829 21 : SolarMutexGuard g;
3830 :
3831 : //Get the real heading level, Heading1 ~ Heading10
3832 21 : if (nHeadingLevel > 0)
3833 : {
3834 0 : return AccessibleRole::HEADING;
3835 : }
3836 : else
3837 : {
3838 21 : return AccessibleRole::PARAGRAPH;
3839 21 : }
3840 : }
3841 :
3842 : //Get the real heading level, Heading1 ~ Heading10
3843 79 : sal_Int32 SwAccessibleParagraph::GetRealHeadingLevel()
3844 : {
3845 79 : uno::Reference< ::com::sun::star::beans::XPropertySet > xPortion = CreateUnoPortion( 0, 0 );
3846 158 : OUString pString = "ParaStyleName";
3847 158 : uno::Any styleAny = xPortion->getPropertyValue( pString );
3848 158 : OUString sValue;
3849 79 : if (styleAny >>= sValue)
3850 : {
3851 79 : sal_Int32 length = sValue.getLength();
3852 79 : if (length == 9 || length == 10)
3853 : {
3854 0 : OUString headStr = sValue.copy(0, 7);
3855 0 : if (headStr == "Heading")
3856 : {
3857 0 : OUString intStr = sValue.copy(8);
3858 0 : sal_Int32 headingLevel = intStr.toInt32(10);
3859 0 : return headingLevel;
3860 0 : }
3861 : }
3862 : }
3863 158 : return -1;
3864 : }
3865 :
3866 0 : uno::Any SAL_CALL SwAccessibleParagraph::getExtendedAttributes()
3867 : throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException, std::exception)
3868 : {
3869 0 : SolarMutexGuard g;
3870 :
3871 0 : uno::Any Ret;
3872 0 : OUString strHeading("heading-level:");
3873 0 : if( nHeadingLevel >= 0 )
3874 0 : strHeading += OUString::number(nHeadingLevel, 10);
3875 0 : strHeading += ";";
3876 :
3877 0 : strHeading += strHeading.copy(8); // tdf#84102: expose the same attribute with the name "level"
3878 :
3879 0 : Ret <<= strHeading;
3880 :
3881 0 : return Ret;
3882 177 : }
3883 :
3884 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|