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