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