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