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