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