1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_accessibility.hxx"
26
27 #ifndef _TOOLKIT_AWT_VCLXACCESSIBLECOMPONENT_HXX_
28 #include <accessibility/extended/textwindowaccessibility.hxx>
29 #endif
30 #include "comphelper/accessibleeventnotifier.hxx"
31 #include "unotools/accessiblerelationsethelper.hxx"
32 #include <unotools/accessiblestatesethelper.hxx>
33 #include <vcl/window.hxx>
34 #include <toolkit/helper/convert.hxx>
35
36 #include <algorithm>
37 #include <vector>
38 #include <hash_map>
39
40 namespace css = ::com::sun::star;
41
42 namespace accessibility
43 {
44 ::sal_Int32 getSelectionType(::sal_Int32 nNewFirstPara, ::sal_Int32 nNewFirstPos, ::sal_Int32 nNewLastPara, ::sal_Int32 nNewLastPos);
45 void sendEvent(::sal_Int32 start, ::sal_Int32 end, ::sal_Int16 nEventId);
46
47 // Both ::osl::Mutex and ParagraphBase implement acquire and release, and thus
48 // ::rtl::Reference< Paragraph > does not work. So ParagraphImpl was factored
49 // out and ::rtl::Reference< ParagraphImpl > is used instead.
50 class Paragraph: private ::osl::Mutex, public ParagraphImpl
51 {
52 public:
Paragraph(::rtl::Reference<Document> const & rDocument,Paragraphs::size_type nNumber)53 inline Paragraph(::rtl::Reference< Document > const & rDocument,
54 Paragraphs::size_type nNumber):
55 ParagraphImpl(rDocument, nNumber, *this) {}
56 };
57
startListening(::SfxBroadcaster & rNotifier)58 void SfxListenerGuard::startListening(::SfxBroadcaster & rNotifier)
59 {
60 OSL_ENSURE(m_pNotifier == 0, "called more than once");
61 m_pNotifier = &rNotifier;
62 m_rListener.StartListening(*m_pNotifier, true);
63 }
64
endListening()65 void SfxListenerGuard::endListening()
66 {
67 if (m_pNotifier != 0)
68 {
69 m_rListener.EndListening(*m_pNotifier);
70 m_pNotifier = 0;
71 }
72 }
73
startListening(::Window & rNotifier)74 void WindowListenerGuard::startListening(::Window & rNotifier)
75 {
76 OSL_ENSURE(m_pNotifier == 0, "called more than once");
77 m_pNotifier = &rNotifier;
78 m_pNotifier->AddEventListener(m_aListener);
79 }
80
endListening()81 void WindowListenerGuard::endListening()
82 {
83 if (m_pNotifier != 0)
84 {
85 m_pNotifier->RemoveEventListener(m_aListener);
86 m_pNotifier = 0;
87 }
88 }
89
ParagraphImpl(::rtl::Reference<Document> const & rDocument,Paragraphs::size_type nNumber,::osl::Mutex & rMutex)90 ParagraphImpl::ParagraphImpl(::rtl::Reference< Document > const & rDocument,
91 Paragraphs::size_type nNumber,
92 ::osl::Mutex & rMutex):
93 ParagraphBase(rMutex),
94 m_xDocument(rDocument),
95 m_nNumber(nNumber),
96 m_nClientId(0)
97 {
98 m_aParagraphText = m_xDocument->retrieveParagraphText(this);
99 }
100
101 void
numberChanged(bool bIncremented)102 ParagraphImpl::numberChanged(bool bIncremented)
103 {
104 if (bIncremented)
105 ++m_nNumber;
106 else
107 --m_nNumber;
108 }
109
textChanged()110 void ParagraphImpl::textChanged()
111 {
112 ::rtl::OUString aParagraphText = implGetText();
113 ::css::uno::Any aOldValue, aNewValue;
114 if ( implInitTextChangedEvent( m_aParagraphText, aParagraphText, aOldValue, aNewValue ) )
115 {
116 m_aParagraphText = aParagraphText;
117 notifyEvent(::css::accessibility::AccessibleEventId::
118 TEXT_CHANGED,
119 aOldValue, aNewValue);
120 }
121 }
122
notifyEvent(::sal_Int16 nEventId,::css::uno::Any const & rOldValue,::css::uno::Any const & rNewValue)123 void ParagraphImpl::notifyEvent(::sal_Int16 nEventId,
124 ::css::uno::Any const & rOldValue,
125 ::css::uno::Any const & rNewValue)
126 {
127 if (m_nClientId)
128 comphelper::AccessibleEventNotifier::addEvent( m_nClientId, ::css::accessibility::AccessibleEventObject(
129 static_cast< ::cppu::OWeakObject * >(this),
130 nEventId, rNewValue, rOldValue) );
131 }
132
133 // virtual
134 ::css::uno::Reference< ::css::accessibility::XAccessibleContext > SAL_CALL
getAccessibleContext()135 ParagraphImpl::getAccessibleContext() throw (::css::uno::RuntimeException)
136 {
137 checkDisposed();
138 return this;
139 }
140
141 // virtual
getAccessibleChildCount()142 ::sal_Int32 SAL_CALL ParagraphImpl::getAccessibleChildCount()
143 throw (::css::uno::RuntimeException)
144 {
145 checkDisposed();
146 return 0;
147 }
148
149 // virtual
150 ::css::uno::Reference< ::css::accessibility::XAccessible > SAL_CALL
getAccessibleChild(::sal_Int32)151 ParagraphImpl::getAccessibleChild(::sal_Int32)
152 throw (::css::lang::IndexOutOfBoundsException,
153 ::css::uno::RuntimeException)
154 {
155 checkDisposed();
156 throw ::css::lang::IndexOutOfBoundsException(
157 ::rtl::OUString(
158 RTL_CONSTASCII_USTRINGPARAM(
159 "textwindowaccessibility.cxx:"
160 " ParagraphImpl::getAccessibleChild")),
161 static_cast< ::css::uno::XWeak * >(this));
162 }
163
164 // virtual
165 ::css::uno::Reference< ::css::accessibility::XAccessible > SAL_CALL
getAccessibleParent()166 ParagraphImpl::getAccessibleParent()
167 throw (::css::uno::RuntimeException)
168 {
169 checkDisposed();
170 return m_xDocument->getAccessible();
171 }
172
173 // virtual
getAccessibleIndexInParent()174 ::sal_Int32 SAL_CALL ParagraphImpl::getAccessibleIndexInParent()
175 throw (::css::uno::RuntimeException)
176 {
177 checkDisposed();
178 return m_xDocument->retrieveParagraphIndex(this);
179 }
180
181 // virtual
getAccessibleRole()182 ::sal_Int16 SAL_CALL ParagraphImpl::getAccessibleRole()
183 throw (::css::uno::RuntimeException)
184 {
185 checkDisposed();
186 return ::css::accessibility::AccessibleRole::PARAGRAPH;
187 }
188
189 // virtual
getAccessibleDescription()190 ::rtl::OUString SAL_CALL ParagraphImpl::getAccessibleDescription()
191 throw (::css::uno::RuntimeException)
192 {
193 checkDisposed();
194 return ::rtl::OUString();
195 }
196
197 // virtual
getAccessibleName()198 ::rtl::OUString SAL_CALL ParagraphImpl::getAccessibleName()
199 throw (::css::uno::RuntimeException)
200 {
201 checkDisposed();
202 return ::rtl::OUString();
203 }
204
205 // virtual
206 ::css::uno::Reference< ::css::accessibility::XAccessibleRelationSet >
getAccessibleRelationSet()207 SAL_CALL ParagraphImpl::getAccessibleRelationSet()
208 throw (::css::uno::RuntimeException)
209 {
210 checkDisposed();
211 return m_xDocument->retrieveParagraphRelationSet( this );
212 }
213
214 // virtual
215 ::css::uno::Reference< ::css::accessibility::XAccessibleStateSet >
getAccessibleStateSet()216 SAL_CALL ParagraphImpl::getAccessibleStateSet()
217 throw (::css::uno::RuntimeException)
218 {
219 checkDisposed();
220
221 // FIXME Notification of changes (STATE_CHANGED) missing when
222 // m_rView.IsReadOnly() changes:
223 return new ::utl::AccessibleStateSetHelper(
224 m_xDocument->retrieveParagraphState(this));
225 }
226
227 // virtual
getLocale()228 ::css::lang::Locale SAL_CALL ParagraphImpl::getLocale()
229 throw (::css::accessibility::IllegalAccessibleComponentStateException,
230 ::css::uno::RuntimeException)
231 {
232 checkDisposed();
233 return m_xDocument->retrieveLocale();
234 }
235
236 // virtual
containsPoint(::css::awt::Point const & rPoint)237 ::sal_Bool SAL_CALL ParagraphImpl::containsPoint(::css::awt::Point const & rPoint)
238 throw (::css::uno::RuntimeException)
239 {
240 checkDisposed();
241 ::css::awt::Rectangle aRect(m_xDocument->retrieveParagraphBounds(this,
242 false));
243 return rPoint.X >= 0 && rPoint.X < aRect.Width
244 && rPoint.Y >= 0 && rPoint.Y < aRect.Height;
245 }
246
247 // virtual
248 ::css::uno::Reference< ::css::accessibility::XAccessible > SAL_CALL
getAccessibleAtPoint(::css::awt::Point const &)249 ParagraphImpl::getAccessibleAtPoint(::css::awt::Point const &)
250 throw (::css::uno::RuntimeException)
251 {
252 checkDisposed();
253 return 0;
254 }
255
256 // virtual
getBounds()257 ::css::awt::Rectangle SAL_CALL ParagraphImpl::getBounds()
258 throw (::css::uno::RuntimeException)
259 {
260 checkDisposed();
261 return m_xDocument->retrieveParagraphBounds(this, false);
262 }
263
264 // virtual
getLocation()265 ::css::awt::Point SAL_CALL ParagraphImpl::getLocation()
266 throw (::css::uno::RuntimeException)
267 {
268 checkDisposed();
269 ::css::awt::Rectangle aRect(m_xDocument->retrieveParagraphBounds(this,
270 false));
271 return ::css::awt::Point(aRect.X, aRect.Y);
272 }
273
274 // virtual
getLocationOnScreen()275 ::css::awt::Point SAL_CALL ParagraphImpl::getLocationOnScreen()
276 throw (::css::uno::RuntimeException)
277 {
278 checkDisposed();
279 ::css::awt::Rectangle aRect(m_xDocument->retrieveParagraphBounds(this,
280 true));
281 return ::css::awt::Point(aRect.X, aRect.Y);
282 }
283
284 // virtual
getSize()285 ::css::awt::Size SAL_CALL ParagraphImpl::getSize()
286 throw (::css::uno::RuntimeException)
287 {
288 checkDisposed();
289 ::css::awt::Rectangle aRect(m_xDocument->retrieveParagraphBounds(this,
290 false));
291 return ::css::awt::Size(aRect.Width, aRect.Height);
292 }
293
294 // virtual
grabFocus()295 void SAL_CALL ParagraphImpl::grabFocus() throw (::css::uno::RuntimeException)
296 {
297 checkDisposed();
298 Window* pWindow = m_xDocument->GetWindow();
299 if ( pWindow )
300 {
301 pWindow->GrabFocus();
302 }
303 try
304 {
305 m_xDocument->changeParagraphSelection(this, 0, 0);
306 }
307 catch (::css::lang::IndexOutOfBoundsException & rEx)
308 {
309 OSL_TRACE(
310 "textwindowaccessibility.cxx: ParagraphImpl::grabFocus:"
311 " caught unexpected %s\n",
312 ::rtl::OUStringToOString(rEx.Message, RTL_TEXTENCODING_UTF8).
313 getStr());
314 }
315 }
316
317 // virtual
getAccessibleKeyBinding()318 ::css::uno::Any SAL_CALL ParagraphImpl::getAccessibleKeyBinding()
319 throw (::css::uno::RuntimeException)
320 {
321 checkDisposed();
322 return ::css::uno::Any();
323 }
324
325 // virtual
getForeground()326 ::css::util::Color SAL_CALL ParagraphImpl::getForeground()
327 throw (::css::uno::RuntimeException)
328 {
329 return 0; // TODO
330 }
331
332 // virtual
getBackground()333 ::css::util::Color SAL_CALL ParagraphImpl::getBackground()
334 throw (::css::uno::RuntimeException)
335 {
336 return 0; // TODO
337 }
338
339 // virtual
getCaretPosition()340 ::sal_Int32 SAL_CALL ParagraphImpl::getCaretPosition()
341 throw (::css::uno::RuntimeException)
342 {
343 checkDisposed();
344 return m_xDocument->retrieveParagraphCaretPosition(this);
345 }
346
347 // virtual
setCaretPosition(::sal_Int32 nIndex)348 ::sal_Bool SAL_CALL ParagraphImpl::setCaretPosition(::sal_Int32 nIndex)
349 throw (::css::lang::IndexOutOfBoundsException,
350 ::css::uno::RuntimeException)
351 {
352 checkDisposed();
353 m_xDocument->changeParagraphSelection(this, nIndex, nIndex);
354 return true;
355 }
356
357 // virtual
getCharacter(::sal_Int32 nIndex)358 ::sal_Unicode SAL_CALL ParagraphImpl::getCharacter(::sal_Int32 nIndex)
359 throw (::css::lang::IndexOutOfBoundsException,
360 ::css::uno::RuntimeException)
361 {
362 checkDisposed();
363 return OCommonAccessibleText::getCharacter(nIndex);
364 }
365
366 // virtual
367 ::css::uno::Sequence< ::css::beans::PropertyValue > SAL_CALL
getCharacterAttributes(::sal_Int32 nIndex,const::com::sun::star::uno::Sequence<::rtl::OUString> & aRequestedAttributes)368 ParagraphImpl::getCharacterAttributes(::sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes)
369 throw (::css::lang::IndexOutOfBoundsException,
370 ::css::uno::RuntimeException)
371 {
372 checkDisposed();
373 return m_xDocument->retrieveCharacterAttributes( this, nIndex, aRequestedAttributes );
374 }
375
376 // virtual
377 ::css::awt::Rectangle SAL_CALL
getCharacterBounds(::sal_Int32 nIndex)378 ParagraphImpl::getCharacterBounds(::sal_Int32 nIndex)
379 throw (::css::lang::IndexOutOfBoundsException,
380 ::css::uno::RuntimeException)
381 {
382 checkDisposed();
383 ::css::awt::Rectangle aBounds(m_xDocument->retrieveCharacterBounds(this, nIndex));
384 ::css::awt::Rectangle aParaBounds(m_xDocument->retrieveParagraphBounds(this, false));
385 aBounds.X -= aParaBounds.X;
386 aBounds.Y -= aParaBounds.Y;
387 return aBounds;
388 }
389
390 // virtual
getCharacterCount()391 ::sal_Int32 SAL_CALL ParagraphImpl::getCharacterCount()
392 throw (::css::uno::RuntimeException)
393 {
394 checkDisposed();
395 return OCommonAccessibleText::getCharacterCount();
396 }
397
398 // virtual
399 ::sal_Int32 SAL_CALL
getIndexAtPoint(::css::awt::Point const & rPoint)400 ParagraphImpl::getIndexAtPoint(::css::awt::Point const & rPoint)
401 throw (::css::uno::RuntimeException)
402 {
403 checkDisposed();
404 ::css::awt::Point aPoint(rPoint);
405 ::css::awt::Rectangle aParaBounds(m_xDocument->retrieveParagraphBounds(this, false));
406 aPoint.X += aParaBounds.X;
407 aPoint.Y += aParaBounds.Y;
408 return m_xDocument->retrieveCharacterIndex(this, aPoint);
409 }
410
411 // virtual
getSelectedText()412 ::rtl::OUString SAL_CALL ParagraphImpl::getSelectedText()
413 throw (::css::uno::RuntimeException)
414 {
415 checkDisposed();
416
417 return OCommonAccessibleText::getSelectedText();
418 }
419
420 // virtual
getSelectionStart()421 ::sal_Int32 SAL_CALL ParagraphImpl::getSelectionStart()
422 throw (::css::uno::RuntimeException)
423 {
424 checkDisposed();
425 return OCommonAccessibleText::getSelectionStart();
426 }
427
428 // virtual
getSelectionEnd()429 ::sal_Int32 SAL_CALL ParagraphImpl::getSelectionEnd()
430 throw (::css::uno::RuntimeException)
431 {
432 checkDisposed();
433 return OCommonAccessibleText::getSelectionEnd();
434 }
435
436 // virtual
setSelection(::sal_Int32 nStartIndex,::sal_Int32 nEndIndex)437 ::sal_Bool SAL_CALL ParagraphImpl::setSelection(::sal_Int32 nStartIndex,
438 ::sal_Int32 nEndIndex)
439 throw (::css::lang::IndexOutOfBoundsException,
440 ::css::uno::RuntimeException)
441 {
442 checkDisposed();
443 m_xDocument->changeParagraphSelection(this, nStartIndex, nEndIndex);
444 return true;
445 }
446
447 // virtual
getText()448 ::rtl::OUString SAL_CALL ParagraphImpl::getText()
449 throw (::css::uno::RuntimeException)
450 {
451 checkDisposed();
452 return OCommonAccessibleText::getText();
453 }
454
455 // virtual
getTextRange(::sal_Int32 nStartIndex,::sal_Int32 nEndIndex)456 ::rtl::OUString SAL_CALL ParagraphImpl::getTextRange(::sal_Int32 nStartIndex,
457 ::sal_Int32 nEndIndex)
458 throw (::css::lang::IndexOutOfBoundsException,
459 ::css::uno::RuntimeException)
460 {
461 checkDisposed();
462 return OCommonAccessibleText::getTextRange(nStartIndex, nEndIndex);
463 }
464
465 // virtual
getTextAtIndex(sal_Int32 nIndex,sal_Int16 aTextType)466 ::com::sun::star::accessibility::TextSegment SAL_CALL ParagraphImpl::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
467 {
468 checkDisposed();
469 return OCommonAccessibleText::getTextAtIndex(nIndex, aTextType);
470 }
471
472 // virtual
getTextBeforeIndex(sal_Int32 nIndex,sal_Int16 aTextType)473 ::com::sun::star::accessibility::TextSegment SAL_CALL ParagraphImpl::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
474 {
475 checkDisposed();
476 return OCommonAccessibleText::getTextBeforeIndex(nIndex, aTextType);
477 }
478
479 // virtual
getTextBehindIndex(sal_Int32 nIndex,sal_Int16 aTextType)480 ::com::sun::star::accessibility::TextSegment SAL_CALL ParagraphImpl::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
481 {
482 checkDisposed();
483 return OCommonAccessibleText::getTextBehindIndex(nIndex, aTextType);
484 }
485
486 // virtual
copyText(::sal_Int32 nStartIndex,::sal_Int32 nEndIndex)487 ::sal_Bool SAL_CALL ParagraphImpl::copyText(::sal_Int32 nStartIndex,
488 ::sal_Int32 nEndIndex)
489 throw (::css::lang::IndexOutOfBoundsException,
490 ::css::uno::RuntimeException)
491 {
492 checkDisposed();
493 m_xDocument->copyParagraphText(this, nStartIndex, nEndIndex);
494 return true;
495 }
496
497 // virtual
cutText(::sal_Int32 nStartIndex,::sal_Int32 nEndIndex)498 ::sal_Bool SAL_CALL ParagraphImpl::cutText(::sal_Int32 nStartIndex,
499 ::sal_Int32 nEndIndex)
500 throw (::css::lang::IndexOutOfBoundsException,
501 ::css::uno::RuntimeException)
502 {
503 checkDisposed();
504 m_xDocument->changeParagraphText(this, nStartIndex, nEndIndex, true, false,
505 ::rtl::OUString());
506 return true;
507 }
508
509 // virtual
pasteText(::sal_Int32 nIndex)510 ::sal_Bool SAL_CALL ParagraphImpl::pasteText(::sal_Int32 nIndex)
511 throw (::css::lang::IndexOutOfBoundsException,
512 ::css::uno::RuntimeException)
513 {
514 checkDisposed();
515 m_xDocument->changeParagraphText(this, nIndex, nIndex, false, true,
516 ::rtl::OUString());
517 return true;
518 }
519
520 // virtual
deleteText(::sal_Int32 nStartIndex,::sal_Int32 nEndIndex)521 ::sal_Bool SAL_CALL ParagraphImpl::deleteText(::sal_Int32 nStartIndex,
522 ::sal_Int32 nEndIndex)
523 throw (::css::lang::IndexOutOfBoundsException,
524 ::css::uno::RuntimeException)
525 {
526 checkDisposed();
527 m_xDocument->changeParagraphText(this, nStartIndex, nEndIndex, false, false,
528 ::rtl::OUString());
529 return true;
530 }
531
532 // virtual
insertText(::rtl::OUString const & rText,::sal_Int32 nIndex)533 ::sal_Bool SAL_CALL ParagraphImpl::insertText(::rtl::OUString const & rText,
534 ::sal_Int32 nIndex)
535 throw (::css::lang::IndexOutOfBoundsException,
536 ::css::uno::RuntimeException)
537 {
538 checkDisposed();
539 m_xDocument->changeParagraphText(this, nIndex, nIndex, false, false, rText);
540 return true;
541 }
542
543 // virtual
544 ::sal_Bool SAL_CALL
replaceText(::sal_Int32 nStartIndex,::sal_Int32 nEndIndex,::rtl::OUString const & rReplacement)545 ParagraphImpl::replaceText(::sal_Int32 nStartIndex, ::sal_Int32 nEndIndex,
546 ::rtl::OUString const & rReplacement)
547 throw (::css::lang::IndexOutOfBoundsException,
548 ::css::uno::RuntimeException)
549 {
550 checkDisposed();
551 m_xDocument->changeParagraphText(this, nStartIndex, nEndIndex, false, false,
552 rReplacement);
553 return true;
554 }
555
556 // virtual
setAttributes(::sal_Int32 nStartIndex,::sal_Int32 nEndIndex,::css::uno::Sequence<::css::beans::PropertyValue> const & rAttributeSet)557 ::sal_Bool SAL_CALL ParagraphImpl::setAttributes(
558 ::sal_Int32 nStartIndex, ::sal_Int32 nEndIndex,
559 ::css::uno::Sequence< ::css::beans::PropertyValue > const & rAttributeSet)
560 throw (::css::lang::IndexOutOfBoundsException,
561 ::css::uno::RuntimeException)
562 {
563 checkDisposed();
564 m_xDocument->changeParagraphAttributes(this, nStartIndex, nEndIndex,
565 rAttributeSet);
566 return true;
567 }
568
569 // virtual
setText(::rtl::OUString const & rText)570 ::sal_Bool SAL_CALL ParagraphImpl::setText(::rtl::OUString const & rText)
571 throw (::css::uno::RuntimeException)
572 {
573 checkDisposed();
574 m_xDocument->changeParagraphText(this, rText);
575 return true;
576 }
577
578 // virtual
579 ::css::uno::Sequence< ::css::beans::PropertyValue > SAL_CALL
getDefaultAttributes(const::css::uno::Sequence<::rtl::OUString> & RequestedAttributes)580 ParagraphImpl::getDefaultAttributes(const ::css::uno::Sequence< ::rtl::OUString >& RequestedAttributes)
581 throw (::css::uno::RuntimeException)
582 {
583 checkDisposed();
584 return m_xDocument->retrieveDefaultAttributes( this, RequestedAttributes );
585 }
586
587 // virtual
588 ::css::uno::Sequence< ::css::beans::PropertyValue > SAL_CALL
getRunAttributes(::sal_Int32 Index,const::css::uno::Sequence<::rtl::OUString> & RequestedAttributes)589 ParagraphImpl::getRunAttributes(::sal_Int32 Index, const ::css::uno::Sequence< ::rtl::OUString >& RequestedAttributes)
590 throw (::css::lang::IndexOutOfBoundsException,
591 ::css::uno::RuntimeException)
592 {
593 checkDisposed();
594 return m_xDocument->retrieveRunAttributes( this, Index, RequestedAttributes );
595 }
596
597 // virtual
getLineNumberAtIndex(::sal_Int32 nIndex)598 ::sal_Int32 SAL_CALL ParagraphImpl::getLineNumberAtIndex( ::sal_Int32 nIndex )
599 throw (::css::lang::IndexOutOfBoundsException,
600 ::css::uno::RuntimeException)
601 {
602 checkDisposed();
603
604 ::sal_Int32 nLineNo = -1;
605 ::css::i18n::Boundary aBoundary =
606 m_xDocument->retrieveParagraphLineBoundary( this, nIndex, &nLineNo );
607
608 return nLineNo;
609 }
610
611 // virtual
getTextAtLineNumber(::sal_Int32 nLineNo)612 ::css::accessibility::TextSegment SAL_CALL ParagraphImpl::getTextAtLineNumber( ::sal_Int32 nLineNo )
613 throw (::css::lang::IndexOutOfBoundsException,
614 ::css::uno::RuntimeException)
615 {
616 checkDisposed();
617
618 ::css::i18n::Boundary aBoundary =
619 m_xDocument->retrieveParagraphBoundaryOfLine( this, nLineNo );
620
621 return ::css::accessibility::TextSegment( getTextRange(aBoundary.startPos, aBoundary.endPos),
622 aBoundary.startPos, aBoundary.endPos);
623 }
624
625 // virtual
getTextAtLineWithCaret()626 ::css::accessibility::TextSegment SAL_CALL ParagraphImpl::getTextAtLineWithCaret( )
627 throw (::css::uno::RuntimeException)
628 {
629 checkDisposed();
630
631 sal_Int32 nLineNo = getNumberOfLineWithCaret();
632
633 try {
634 return ( nLineNo >= 0 ) ?
635 getTextAtLineNumber( nLineNo ) :
636 ::css::accessibility::TextSegment();
637 } catch (const ::css::lang::IndexOutOfBoundsException&) {
638 throw ::css::uno::RuntimeException(
639 ::rtl::OUString(
640 RTL_CONSTASCII_USTRINGPARAM(
641 "textwindowaccessibility.cxx:"
642 " ParagraphImpl::getTextAtLineWithCaret") ),
643 static_cast< ::css::uno::XWeak * >( this ) );
644 }
645 }
646
647 // virtual
getNumberOfLineWithCaret()648 ::sal_Int32 SAL_CALL ParagraphImpl::getNumberOfLineWithCaret( )
649 throw (::css::uno::RuntimeException)
650 {
651 checkDisposed();
652 return m_xDocument->retrieveParagraphLineWithCursor(this);
653 }
654
655
656 // virtual
addEventListener(::css::uno::Reference<::css::accessibility::XAccessibleEventListener> const & rListener)657 void SAL_CALL ParagraphImpl::addEventListener(
658 ::css::uno::Reference<
659 ::css::accessibility::XAccessibleEventListener > const & rListener)
660 throw (::css::uno::RuntimeException)
661 {
662 if (rListener.is())
663 {
664 ::osl::ClearableMutexGuard aGuard(rBHelper.rMutex);
665 if (rBHelper.bDisposed || rBHelper.bInDispose)
666 {
667 aGuard.clear();
668 rListener->disposing(::css::lang::EventObject(
669 static_cast< ::cppu::OWeakObject * >(this)));
670 }
671 else
672 {
673 if (!m_nClientId)
674 m_nClientId = comphelper::AccessibleEventNotifier::registerClient( );
675 comphelper::AccessibleEventNotifier::addEventListener( m_nClientId, rListener );
676 }
677 }
678 }
679
680 // virtual
removeEventListener(::css::uno::Reference<::css::accessibility::XAccessibleEventListener> const & rListener)681 void SAL_CALL ParagraphImpl::removeEventListener(
682 ::css::uno::Reference<
683 ::css::accessibility::XAccessibleEventListener > const & rListener)
684 throw (::css::uno::RuntimeException)
685 {
686 comphelper::AccessibleEventNotifier::TClientId nId = 0;
687 {
688 ::osl::ClearableMutexGuard aGuard(rBHelper.rMutex);
689 if (rListener.is() && m_nClientId != 0
690 && comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId, rListener ) == 0)
691 {
692 nId = m_nClientId;
693 m_nClientId = 0;
694 }
695 }
696 if (nId != 0)
697 {
698 // no listeners anymore
699 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
700 // and at least to us not firing any events anymore, in case somebody calls
701 // NotifyAccessibleEvent, again
702 comphelper::AccessibleEventNotifier::revokeClient(nId);
703 }
704 }
705
706 // virtual
disposing()707 void SAL_CALL ParagraphImpl::disposing()
708 {
709 comphelper::AccessibleEventNotifier::TClientId nId = 0;
710 {
711 ::osl::ClearableMutexGuard aGuard(rBHelper.rMutex);
712 nId = m_nClientId;
713 m_nClientId = 0;
714 }
715 if (nId != 0)
716 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing(nId, *this);
717 }
718
719 // virtual
implGetText()720 ::rtl::OUString ParagraphImpl::implGetText()
721 {
722 return m_xDocument->retrieveParagraphText(this);
723 }
724
725 // virtual
implGetLocale()726 ::css::lang::Locale ParagraphImpl::implGetLocale()
727 {
728 return m_xDocument->retrieveLocale();
729 }
730
731 // virtual
implGetSelection(::sal_Int32 & rStartIndex,::sal_Int32 & rEndIndex)732 void ParagraphImpl::implGetSelection(::sal_Int32 & rStartIndex,
733 ::sal_Int32 & rEndIndex)
734 {
735 m_xDocument->retrieveParagraphSelection(this, &rStartIndex, &rEndIndex);
736 }
737
738 // virtual
implGetParagraphBoundary(::css::i18n::Boundary & rBoundary,::sal_Int32 nIndex)739 void ParagraphImpl::implGetParagraphBoundary( ::css::i18n::Boundary& rBoundary,
740 ::sal_Int32 nIndex )
741 {
742 ::rtl::OUString sText( implGetText() );
743 ::sal_Int32 nLength = sText.getLength();
744
745 if ( implIsValidIndex( nIndex, nLength ) )
746 {
747 rBoundary.startPos = 0;
748 rBoundary.endPos = nLength;
749 }
750 else
751 {
752 rBoundary.startPos = nIndex;
753 rBoundary.endPos = nIndex;
754 }
755 }
756
757 // virtual
implGetLineBoundary(::css::i18n::Boundary & rBoundary,::sal_Int32 nIndex)758 void ParagraphImpl::implGetLineBoundary( ::css::i18n::Boundary& rBoundary,
759 ::sal_Int32 nIndex )
760 {
761 ::rtl::OUString sText( implGetText() );
762 ::sal_Int32 nLength = sText.getLength();
763
764 if ( implIsValidIndex( nIndex, nLength ) || nIndex == nLength )
765 {
766 ::css::i18n::Boundary aBoundary =
767 m_xDocument->retrieveParagraphLineBoundary( this, nIndex );
768 rBoundary.startPos = aBoundary.startPos;
769 rBoundary.endPos = aBoundary.endPos;
770 }
771 else
772 {
773 rBoundary.startPos = nIndex;
774 rBoundary.endPos = nIndex;
775 }
776 }
777
778
checkDisposed()779 void ParagraphImpl::checkDisposed()
780 {
781 ::osl::MutexGuard aGuard(rBHelper.rMutex);
782 if (!(rBHelper.bDisposed || rBHelper.bInDispose))
783 return;
784 throw ::css::lang::DisposedException(
785 ::rtl::OUString(), static_cast< ::css::uno::XWeak * >(this));
786 }
787
Document(::VCLXWindow * pVclXWindow,::TextEngine & rEngine,::TextView & rView,bool bCompoundControlChild)788 Document::Document(::VCLXWindow * pVclXWindow, ::TextEngine & rEngine,
789 ::TextView & rView, bool bCompoundControlChild):
790 VCLXAccessibleComponent(pVclXWindow),
791 m_xAccessible(pVclXWindow),
792 m_rEngine(rEngine),
793 m_rView(rView),
794 m_aEngineListener(*this),
795 m_aViewListener(LINK(this, Document, WindowEventHandler)),
796 m_bCompoundControlChild(bCompoundControlChild)
797 {}
798
retrieveLocale()799 ::css::lang::Locale Document::retrieveLocale()
800 {
801 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
802 return m_rEngine.GetLocale();
803 }
804
retrieveParagraphIndex(ParagraphImpl const * pParagraph)805 ::sal_Int32 Document::retrieveParagraphIndex(ParagraphImpl const * pParagraph)
806 {
807 ::osl::MutexGuard aInternalGuard(GetMutex());
808
809 // If a client holds on to a Paragraph that is no longer visible, it can
810 // happen that this Paragraph lies outside the range from m_aVisibleBegin
811 // to m_aVisibleEnd. In that case, return -1 instead of a valid index:
812 Paragraphs::iterator aPara(m_xParagraphs->begin()
813 + pParagraph->getNumber());
814 return aPara < m_aVisibleBegin || aPara >= m_aVisibleEnd
815 ? -1 : static_cast< ::sal_Int32 >(aPara - m_aVisibleBegin);
816 // XXX numeric overflow
817 }
818
retrieveParagraphState(ParagraphImpl const * pParagraph)819 ::sal_Int64 Document::retrieveParagraphState(ParagraphImpl const * pParagraph)
820 {
821 ::osl::MutexGuard aInternalGuard(GetMutex());
822
823 // If a client holds on to a Paragraph that is no longer visible, it can
824 // happen that this Paragraph lies outside the range from m_aVisibleBegin
825 // to m_aVisibleEnd. In that case, it is neither VISIBLE nor SHOWING:
826 ::sal_Int64 nState
827 = (static_cast< ::sal_Int64 >(1)
828 << ::css::accessibility::AccessibleStateType::ENABLED)
829 | (static_cast< ::sal_Int64 >(1)
830 << ::css::accessibility::AccessibleStateType::SENSITIVE)
831 | (static_cast< ::sal_Int64 >(1)
832 << ::css::accessibility::AccessibleStateType::FOCUSABLE)
833 | (static_cast< ::sal_Int64 >(1)
834 << ::css::accessibility::AccessibleStateType::MULTI_LINE);
835 if (!m_rView.IsReadOnly())
836 nState |= (static_cast< ::sal_Int64 >(1)
837 << ::css::accessibility::AccessibleStateType::EDITABLE);
838 Paragraphs::iterator aPara(m_xParagraphs->begin()
839 + pParagraph->getNumber());
840 if (aPara >= m_aVisibleBegin && aPara < m_aVisibleEnd)
841 {
842 nState
843 |= (static_cast< ::sal_Int64 >(1)
844 << ::css::accessibility::AccessibleStateType::VISIBLE)
845 | (static_cast< ::sal_Int64 >(1)
846 << ::css::accessibility::AccessibleStateType::SHOWING);
847 if (aPara == m_aFocused)
848 nState |= (static_cast< ::sal_Int64 >(1)
849 << ::css::accessibility::AccessibleStateType::FOCUSED);
850 }
851 return nState;
852 };
853
854 ::css::awt::Rectangle
retrieveParagraphBounds(ParagraphImpl const * pParagraph,bool bAbsolute)855 Document::retrieveParagraphBounds(ParagraphImpl const * pParagraph,
856 bool bAbsolute)
857 {
858 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
859 ::osl::MutexGuard aInternalGuard(GetMutex());
860
861 // If a client holds on to a Paragraph that is no longer visible (as it
862 // scrolled out the top of the view), it can happen that this Paragraph
863 // lies before m_aVisibleBegin. In that case, calculate the vertical
864 // position of the Paragraph starting at paragraph 0, otherwise optimize
865 // and start at m_aVisibleBegin:
866 Paragraphs::iterator aPara(m_xParagraphs->begin()
867 + pParagraph->getNumber());
868 ::sal_Int32 nPos;
869 Paragraphs::iterator aIt;
870 if (aPara < m_aVisibleBegin)
871 {
872 nPos = 0;
873 aIt = m_xParagraphs->begin();
874 }
875 else
876 {
877 nPos = m_nViewOffset - m_nVisibleBeginOffset;
878 aIt = m_aVisibleBegin;
879 }
880 for (; aIt != aPara; ++aIt)
881 nPos += aIt->getHeight();
882
883 Point aOrig(0, 0);
884 if (bAbsolute)
885 aOrig = m_rView.GetWindow()->OutputToAbsoluteScreenPixel(aOrig);
886
887 return ::css::awt::Rectangle(
888 static_cast< ::sal_Int32 >(aOrig.X()),
889 static_cast< ::sal_Int32 >(aOrig.Y()) + nPos - m_nViewOffset,
890 m_rView.GetWindow()->GetOutputSizePixel().Width(), aPara->getHeight());
891 // XXX numeric overflow (3x)
892 }
893
894 ::rtl::OUString
retrieveParagraphText(ParagraphImpl const * pParagraph)895 Document::retrieveParagraphText(ParagraphImpl const * pParagraph)
896 {
897 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
898 ::osl::MutexGuard aInternalGuard(GetMutex());
899 return m_rEngine.GetText(static_cast< ::sal_uLong >(pParagraph->getNumber()));
900 // numeric overflow cannot happen here
901 }
902
retrieveParagraphSelection(ParagraphImpl const * pParagraph,::sal_Int32 * pBegin,::sal_Int32 * pEnd)903 void Document::retrieveParagraphSelection(ParagraphImpl const * pParagraph,
904 ::sal_Int32 * pBegin,
905 ::sal_Int32 * pEnd)
906 {
907 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
908 ::osl::MutexGuard aInternalGuard(GetMutex());
909 ::TextSelection const & rSelection = m_rView.GetSelection();
910 Paragraphs::size_type nNumber = pParagraph->getNumber();
911 TextPaM aStartPaM( rSelection.GetStart() );
912 TextPaM aEndPaM( rSelection.GetEnd() );
913 TextPaM aMinPaM( ::std::min( aStartPaM, aEndPaM ) );
914 TextPaM aMaxPaM( ::std::max( aStartPaM, aEndPaM ) );
915
916 if ( nNumber >= aMinPaM.GetPara() && nNumber <= aMaxPaM.GetPara() )
917 {
918 *pBegin = nNumber > aMinPaM.GetPara()
919 ? 0
920 : static_cast< ::sal_Int32 >( aMinPaM.GetIndex() );
921 // XXX numeric overflow
922 *pEnd = nNumber < aMaxPaM.GetPara()
923 ? static_cast< ::sal_Int32 >( m_rEngine.GetText(static_cast< ::sal_uLong >(nNumber)).Len() )
924 : static_cast< ::sal_Int32 >( aMaxPaM.GetIndex() );
925 // XXX numeric overflow (3x)
926
927 if ( aStartPaM > aEndPaM )
928 ::std::swap( *pBegin, *pEnd );
929 }
930 else
931 {
932 *pBegin = 0;
933 *pEnd = 0;
934 }
935 }
936
retrieveParagraphCaretPosition(ParagraphImpl const * pParagraph)937 ::sal_Int32 Document::retrieveParagraphCaretPosition(ParagraphImpl const * pParagraph)
938 {
939 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
940 ::osl::MutexGuard aInternalGuard(GetMutex());
941 ::TextSelection const & rSelection = m_rView.GetSelection();
942 Paragraphs::size_type nNumber = pParagraph->getNumber();
943 TextPaM aEndPaM( rSelection.GetEnd() );
944
945 return aEndPaM.GetPara() == nNumber
946 ? static_cast< ::sal_Int32 >(aEndPaM.GetIndex()) : -1;
947 }
948
949 ::css::awt::Rectangle
retrieveCharacterBounds(ParagraphImpl const * pParagraph,::sal_Int32 nIndex)950 Document::retrieveCharacterBounds(ParagraphImpl const * pParagraph,
951 ::sal_Int32 nIndex)
952 {
953 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
954 ::osl::MutexGuard aInternalGuard(GetMutex());
955 ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
956 sal_Int32 nLength = m_rEngine.GetText(nNumber).Len();
957 // XXX numeric overflow
958 if (nIndex < 0 || nIndex > nLength)
959 throw ::css::lang::IndexOutOfBoundsException(
960 ::rtl::OUString(
961 RTL_CONSTASCII_USTRINGPARAM(
962 "textwindowaccessibility.cxx:"
963 " Document::retrieveCharacterAttributes")),
964 static_cast< ::css::uno::XWeak * >(this));
965 ::css::awt::Rectangle aBounds( 0, 0, 0, 0 );
966 if ( nIndex == nLength )
967 {
968 aBounds = AWTRectangle(
969 m_rEngine.PaMtoEditCursor(::TextPaM(nNumber,
970 static_cast< ::sal_uInt16 >(nIndex))));
971 }
972 else
973 {
974 ::Rectangle aLeft(
975 m_rEngine.PaMtoEditCursor(::TextPaM(nNumber,
976 static_cast< ::sal_uInt16 >(nIndex))));
977 // XXX numeric overflow
978 ::Rectangle aRight(
979 m_rEngine.PaMtoEditCursor(::TextPaM(nNumber,
980 static_cast< ::sal_uInt16 >(nIndex)
981 + 1)));
982 // XXX numeric overflow (2x)
983 // FIXME If the vertical extends of the two cursors do not match, assume
984 // nIndex is the last character on the line; the bounding box will then
985 // extend to m_rEnginge.GetMaxTextWidth():
986 ::sal_Int32 nWidth = (aLeft.Top() == aRight.Top()
987 && aLeft.Bottom() == aRight.Bottom())
988 ? static_cast< ::sal_Int32 >(aRight.Left() - aLeft.Left())
989 : static_cast< ::sal_Int32 >(m_rEngine.GetMaxTextWidth()
990 - aLeft.Left());
991 // XXX numeric overflow (4x)
992 aBounds = ::css::awt::Rectangle(static_cast< ::sal_Int32 >(aLeft.Left()),
993 static_cast< ::sal_Int32 >(aLeft.Top() - m_nViewOffset),
994 nWidth,
995 static_cast< ::sal_Int32 >(aLeft.Bottom()
996 - aLeft.Top()));
997 // XXX numeric overflow (4x)
998 }
999 return aBounds;
1000 }
1001
retrieveCharacterIndex(ParagraphImpl const * pParagraph,::css::awt::Point const & rPoint)1002 ::sal_Int32 Document::retrieveCharacterIndex(ParagraphImpl const * pParagraph,
1003 ::css::awt::Point const & rPoint)
1004 {
1005 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
1006 ::osl::MutexGuard aInternalGuard(GetMutex());
1007 ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
1008 // XXX numeric overflow
1009 ::TextPaM aPaM(m_rEngine.GetPaM(::Point(static_cast< long >(rPoint.X),
1010 static_cast< long >(rPoint.Y))));
1011 // XXX numeric overflow (2x)
1012 return aPaM.GetPara() == nNumber
1013 ? static_cast< ::sal_Int32 >(aPaM.GetIndex()) : -1;
1014 // XXX numeric overflow
1015 }
1016
1017 struct IndexCompare
1018 {
1019 const ::css::beans::PropertyValue* pValues;
IndexCompareaccessibility::IndexCompare1020 IndexCompare( const ::css::beans::PropertyValue* pVals ) : pValues(pVals) {}
operator ()accessibility::IndexCompare1021 bool operator() ( const sal_Int32& a, const sal_Int32& b ) const
1022 {
1023 return (pValues[a].Name < pValues[b].Name) ? true : false;
1024 }
1025 };
1026
1027 ::css::uno::Sequence< ::css::beans::PropertyValue >
retrieveCharacterAttributes(ParagraphImpl const * pParagraph,::sal_Int32 nIndex,const::css::uno::Sequence<::rtl::OUString> & aRequestedAttributes)1028 Document::retrieveCharacterAttributes(
1029 ParagraphImpl const * pParagraph, ::sal_Int32 nIndex,
1030 const ::css::uno::Sequence< ::rtl::OUString >& aRequestedAttributes)
1031 {
1032 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
1033
1034 Font aFont = m_rEngine.GetFont();
1035 const sal_Int32 AttributeCount = 9;
1036 sal_Int32 i = 0;
1037 ::css::uno::Sequence< ::css::beans::PropertyValue > aAttribs( AttributeCount );
1038 //character background color
1039 {
1040 aAttribs[i].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharBackColor"));
1041 aAttribs[i].Handle = -1;
1042 aAttribs[i].Value = mapFontColor( aFont.GetFillColor() );
1043 aAttribs[i].State = ::css::beans::PropertyState_DIRECT_VALUE;
1044 i++;
1045 }
1046 //character color
1047 {
1048 aAttribs[i].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharColor"));
1049 aAttribs[i].Handle = -1;
1050 //aAttribs[i].Value = mapFontColor( aFont.GetColor() );
1051 aAttribs[i].Value = mapFontColor( m_rEngine.GetTextColor() );
1052 aAttribs[i].State = ::css::beans::PropertyState_DIRECT_VALUE;
1053 i++;
1054 }
1055 //character font name
1056 {
1057 aAttribs[i].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharFontName"));
1058 aAttribs[i].Handle = -1;
1059 aAttribs[i].Value = ::css::uno::makeAny( (::rtl::OUString)aFont.GetName() );
1060 aAttribs[i].State = ::css::beans::PropertyState_DIRECT_VALUE;
1061 i++;
1062 }
1063 //character height
1064 {
1065 aAttribs[i].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharHeight"));
1066 aAttribs[i].Handle = -1;
1067 aAttribs[i].Value = ::css::uno::makeAny( (sal_Int16)aFont.GetHeight() );
1068 aAttribs[i].State = ::css::beans::PropertyState_DIRECT_VALUE;
1069 i++;
1070 }
1071 //character posture
1072 {
1073 aAttribs[i].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharPosture"));
1074 aAttribs[i].Handle = -1;
1075 aAttribs[i].Value = ::css::uno::makeAny( (sal_Int16)aFont.GetItalic() );
1076 aAttribs[i].State = ::css::beans::PropertyState_DIRECT_VALUE;
1077 i++;
1078 }
1079 //character relief
1080 /*{
1081 aAttribs[i].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharRelief"));
1082 aAttribs[i].Handle = -1;
1083 aAttribs[i].Value = ::css::uno::makeAny( (sal_Int16)aFont.GetRelief() );
1084 aAttribs[i].State = ::css::beans::PropertyState_DIRECT_VALUE;
1085 i++;
1086 }*/
1087 //character strikeout
1088 {
1089 aAttribs[i].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharStrikeout"));
1090 aAttribs[i].Handle = -1;
1091 aAttribs[i].Value = ::css::uno::makeAny( (sal_Int16)aFont.GetStrikeout() );
1092 aAttribs[i].State = ::css::beans::PropertyState_DIRECT_VALUE;
1093 i++;
1094 }
1095 //character underline
1096 {
1097 aAttribs[i].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharUnderline"));
1098 aAttribs[i].Handle = -1;
1099 aAttribs[i].Value = ::css::uno::makeAny( (sal_Int16)aFont.GetUnderline() );
1100 aAttribs[i].State = ::css::beans::PropertyState_DIRECT_VALUE;
1101 i++;
1102 }
1103 //character weight
1104 {
1105 aAttribs[i].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CharWeight"));
1106 aAttribs[i].Handle = -1;
1107 aAttribs[i].Value = ::css::uno::makeAny( (float)aFont.GetWeight() );
1108 aAttribs[i].State = ::css::beans::PropertyState_DIRECT_VALUE;
1109 i++;
1110 }
1111 //character alignment
1112 {
1113 aAttribs[i].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParaAdjust"));
1114 aAttribs[i].Handle = -1;
1115 aAttribs[i].Value = ::css::uno::makeAny( (sal_Int16)m_rEngine.GetTextAlign() );
1116 aAttribs[i].State = ::css::beans::PropertyState_DIRECT_VALUE;
1117 i++;
1118 }
1119 ::osl::MutexGuard aInternalGuard(GetMutex());
1120 ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
1121 // XXX numeric overflow
1122 // nIndex can be equal to Len();
1123 //if (nIndex < 0 || nIndex >= m_rEngine.GetText(nNumber).Len())
1124 if (nIndex < 0 || nIndex > m_rEngine.GetText(nNumber).Len())
1125 throw ::css::lang::IndexOutOfBoundsException(
1126 ::rtl::OUString(
1127 RTL_CONSTASCII_USTRINGPARAM(
1128 "textwindowaccessibility.cxx:"
1129 " Document::retrieveCharacterAttributes")),
1130 static_cast< ::css::uno::XWeak * >(this));
1131
1132 // retrieve default attributes
1133 tPropValMap aCharAttrSeq;
1134 retrieveDefaultAttributesImpl( pParagraph, aRequestedAttributes, aCharAttrSeq );
1135
1136 // retrieve run attributes
1137 tPropValMap aRunAttrSeq;
1138 retrieveRunAttributesImpl( pParagraph, nIndex, aRequestedAttributes, aRunAttrSeq );
1139
1140 // merge default and run attributes
1141 for ( tPropValMap::const_iterator aRunIter = aRunAttrSeq.begin();
1142 aRunIter != aRunAttrSeq.end();
1143 ++aRunIter )
1144 {
1145 aCharAttrSeq[ aRunIter->first ] = aRunIter->second;
1146 }
1147
1148 ::css::beans::PropertyValue* pValues = aAttribs.getArray();
1149 for (i = 0; i < AttributeCount; i++,pValues++)
1150 {
1151 aCharAttrSeq[ pValues->Name ] = *pValues;
1152 }
1153
1154 ::css::uno::Sequence< ::css::beans::PropertyValue > aRes = convertHashMapToSequence( aCharAttrSeq );
1155
1156 // sort the attributes
1157 sal_Int32 nLength = aRes.getLength();
1158 const ::css::beans::PropertyValue* pPairs = aRes.getConstArray();
1159 sal_Int32* pIndices = new sal_Int32[nLength];
1160 for( i = 0; i < nLength; i++ )
1161 pIndices[i] = i;
1162 std::sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) );
1163 // create sorted sequences according to index array
1164 ::css::uno::Sequence< ::css::beans::PropertyValue > aNewValues( nLength );
1165 ::css::beans::PropertyValue* pNewValues = aNewValues.getArray();
1166 for( i = 0; i < nLength; i++ )
1167 {
1168 pNewValues[i] = pPairs[pIndices[i]];
1169 }
1170 delete[] pIndices;
1171
1172 return aNewValues;
1173 }
1174
retrieveDefaultAttributesImpl(ParagraphImpl const * pParagraph,const::css::uno::Sequence<::rtl::OUString> & RequestedAttributes,tPropValMap & rDefAttrSeq)1175 void Document::retrieveDefaultAttributesImpl(
1176 ParagraphImpl const * pParagraph,
1177 const ::css::uno::Sequence< ::rtl::OUString >& RequestedAttributes,
1178 tPropValMap& rDefAttrSeq)
1179 {
1180 // default attributes are not supported by text engine
1181 (void) pParagraph;
1182 (void) RequestedAttributes;
1183 (void) rDefAttrSeq;
1184 }
1185
1186 ::css::uno::Sequence< ::css::beans::PropertyValue >
retrieveDefaultAttributes(ParagraphImpl const * pParagraph,const::css::uno::Sequence<::rtl::OUString> & RequestedAttributes)1187 Document::retrieveDefaultAttributes(
1188 ParagraphImpl const * pParagraph,
1189 const ::css::uno::Sequence< ::rtl::OUString >& RequestedAttributes)
1190 {
1191 ::osl::Guard< ::comphelper::IMutex > aExternalGuard( getExternalLock() );
1192 ::osl::MutexGuard aInternalGuard( GetMutex() );
1193
1194 tPropValMap aDefAttrSeq;
1195 retrieveDefaultAttributesImpl( pParagraph, RequestedAttributes, aDefAttrSeq );
1196 return convertHashMapToSequence( aDefAttrSeq );
1197 }
1198
1199 // static
1200 ::css::uno::Sequence< ::css::beans::PropertyValue >
convertHashMapToSequence(tPropValMap & rAttrSeq)1201 Document::convertHashMapToSequence(tPropValMap& rAttrSeq)
1202 {
1203 ::css::uno::Sequence< ::css::beans::PropertyValue > aValues( rAttrSeq.size() );
1204 ::css::beans::PropertyValue* pValues = aValues.getArray();
1205 ::sal_Int32 i = 0;
1206 for ( tPropValMap::const_iterator aIter = rAttrSeq.begin();
1207 aIter != rAttrSeq.end();
1208 ++aIter )
1209 {
1210 pValues[i] = aIter->second;
1211 ++i;
1212 }
1213 return aValues;
1214 }
1215
retrieveRunAttributesImpl(ParagraphImpl const * pParagraph,::sal_Int32 Index,const::css::uno::Sequence<::rtl::OUString> & RequestedAttributes,tPropValMap & rRunAttrSeq)1216 void Document::retrieveRunAttributesImpl(
1217 ParagraphImpl const * pParagraph, ::sal_Int32 Index,
1218 const ::css::uno::Sequence< ::rtl::OUString >& RequestedAttributes,
1219 tPropValMap& rRunAttrSeq)
1220 {
1221 ::sal_uLong nNumber = static_cast< ::sal_uLong >( pParagraph->getNumber() );
1222 ::TextPaM aPaM( nNumber, static_cast< ::sal_uInt16 >( Index ) );
1223 // XXX numeric overflow
1224 // FIXME TEXTATTR_HYPERLINK ignored:
1225 ::TextAttribFontColor const * pColor
1226 = static_cast< ::TextAttribFontColor const * >(
1227 m_rEngine.FindAttrib( aPaM, TEXTATTR_FONTCOLOR ) );
1228 ::TextAttribFontWeight const * pWeight
1229 = static_cast< ::TextAttribFontWeight const * >(
1230 m_rEngine.FindAttrib( aPaM, TEXTATTR_FONTWEIGHT ) );
1231 tPropValMap aRunAttrSeq;
1232 if ( pColor )
1233 {
1234 ::css::beans::PropertyValue aPropVal;
1235 aPropVal.Name =
1236 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CharColor" ) );
1237 aPropVal.Handle = -1;
1238 aPropVal.Value = mapFontColor( pColor->GetColor() );
1239 aPropVal.State = ::css::beans::PropertyState_DIRECT_VALUE;
1240 aRunAttrSeq[ aPropVal.Name ] = aPropVal;
1241 }
1242 if ( pWeight )
1243 {
1244 ::css::beans::PropertyValue aPropVal;
1245 aPropVal.Name =
1246 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CharWeight" ) );
1247 aPropVal.Handle = -1;
1248 aPropVal.Value = mapFontWeight( pWeight->getFontWeight() );
1249 aPropVal.State = ::css::beans::PropertyState_DIRECT_VALUE;
1250 aRunAttrSeq[ aPropVal.Name ] = aPropVal;
1251 }
1252 if ( RequestedAttributes.getLength() == 0 )
1253 {
1254 rRunAttrSeq = aRunAttrSeq;
1255 }
1256 else
1257 {
1258 const ::rtl::OUString* pReqAttrs = RequestedAttributes.getConstArray();
1259 const ::sal_Int32 nLength = RequestedAttributes.getLength();
1260 for ( ::sal_Int32 i = 0; i < nLength; ++i )
1261 {
1262 tPropValMap::iterator aIter = aRunAttrSeq.find( pReqAttrs[i] );
1263 if ( aIter != aRunAttrSeq.end() )
1264 {
1265 rRunAttrSeq[ (*aIter).first ] = (*aIter).second;
1266 }
1267 }
1268 }
1269 }
1270
1271 ::css::uno::Sequence< ::css::beans::PropertyValue >
retrieveRunAttributes(ParagraphImpl const * pParagraph,::sal_Int32 Index,const::css::uno::Sequence<::rtl::OUString> & RequestedAttributes)1272 Document::retrieveRunAttributes(
1273 ParagraphImpl const * pParagraph, ::sal_Int32 Index,
1274 const ::css::uno::Sequence< ::rtl::OUString >& RequestedAttributes)
1275 {
1276 ::osl::Guard< ::comphelper::IMutex > aExternalGuard( getExternalLock() );
1277 ::osl::MutexGuard aInternalGuard( GetMutex() );
1278 ::sal_uLong nNumber = static_cast< ::sal_uLong >( pParagraph->getNumber() );
1279 // XXX numeric overflow
1280 if ( Index < 0 || Index >= m_rEngine.GetText(nNumber).Len() )
1281 throw ::css::lang::IndexOutOfBoundsException(
1282 ::rtl::OUString(
1283 RTL_CONSTASCII_USTRINGPARAM(
1284 "textwindowaccessibility.cxx:"
1285 " Document::retrieveRunAttributes") ),
1286 static_cast< ::css::uno::XWeak * >( this ) );
1287
1288 tPropValMap aRunAttrSeq;
1289 retrieveRunAttributesImpl( pParagraph, Index, RequestedAttributes, aRunAttrSeq );
1290 return convertHashMapToSequence( aRunAttrSeq );
1291 }
1292
changeParagraphText(ParagraphImpl * pParagraph,::rtl::OUString const & rText)1293 void Document::changeParagraphText(ParagraphImpl * pParagraph,
1294 ::rtl::OUString const & rText)
1295 {
1296 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
1297 {
1298 ::osl::MutexGuard aInternalGuard(GetMutex());
1299 ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
1300 // XXX numeric overflow
1301 changeParagraphText(nNumber, 0, m_rEngine.GetTextLen(nNumber), false,
1302 false, rText);
1303 }
1304 }
1305
changeParagraphText(ParagraphImpl * pParagraph,::sal_Int32 nBegin,::sal_Int32 nEnd,bool bCut,bool bPaste,::rtl::OUString const & rText)1306 void Document::changeParagraphText(ParagraphImpl * pParagraph,
1307 ::sal_Int32 nBegin, ::sal_Int32 nEnd,
1308 bool bCut, bool bPaste,
1309 ::rtl::OUString const & rText)
1310 {
1311 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
1312 {
1313 ::osl::MutexGuard aInternalGuard(GetMutex());
1314 ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
1315 // XXX numeric overflow
1316 if (nBegin < 0 || nBegin > nEnd
1317 || nEnd > m_rEngine.GetText(nNumber).Len())
1318 throw ::css::lang::IndexOutOfBoundsException(
1319 ::rtl::OUString(
1320 RTL_CONSTASCII_USTRINGPARAM(
1321 "textwindowaccessibility.cxx:"
1322 " Document::changeParagraphText")),
1323 static_cast< ::css::uno::XWeak * >(this));
1324 changeParagraphText(nNumber, static_cast< ::sal_uInt16 >(nBegin),
1325 static_cast< ::sal_uInt16 >(nEnd), bCut, bPaste, rText);
1326 // XXX numeric overflow (2x)
1327 }
1328 }
1329
copyParagraphText(ParagraphImpl const * pParagraph,::sal_Int32 nBegin,::sal_Int32 nEnd)1330 void Document::copyParagraphText(ParagraphImpl const * pParagraph,
1331 ::sal_Int32 nBegin, ::sal_Int32 nEnd)
1332 {
1333 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
1334 {
1335 ::osl::MutexGuard aInternalGuard(GetMutex());
1336 ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
1337 // XXX numeric overflow
1338 if (nBegin < 0 || nBegin > nEnd
1339 || nEnd > m_rEngine.GetText(nNumber).Len())
1340 throw ::css::lang::IndexOutOfBoundsException(
1341 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1342 "textwindowaccessibility.cxx:"
1343 " Document::copyParagraphText")),
1344 static_cast< ::css::uno::XWeak * >(this));
1345 m_rView.SetSelection(
1346 ::TextSelection(::TextPaM(nNumber, static_cast< ::sal_uInt16 >(nBegin)),
1347 ::TextPaM(nNumber, static_cast< ::sal_uInt16 >(nEnd))));
1348 // XXX numeric overflow (2x)
1349 m_rView.Copy();
1350 }
1351 }
1352
changeParagraphAttributes(ParagraphImpl * pParagraph,::sal_Int32 nBegin,::sal_Int32 nEnd,::css::uno::Sequence<::css::beans::PropertyValue> const & rAttributeSet)1353 void Document::changeParagraphAttributes(
1354 ParagraphImpl * pParagraph, ::sal_Int32 nBegin, ::sal_Int32 nEnd,
1355 ::css::uno::Sequence< ::css::beans::PropertyValue > const & rAttributeSet)
1356 {
1357 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
1358 {
1359 ::osl::MutexGuard aInternalGuard(GetMutex());
1360 ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
1361 // XXX numeric overflow
1362 if (nBegin < 0 || nBegin > nEnd
1363 || nEnd > m_rEngine.GetText(nNumber).Len())
1364 throw ::css::lang::IndexOutOfBoundsException(
1365 ::rtl::OUString(
1366 RTL_CONSTASCII_USTRINGPARAM(
1367 "textwindowaccessibility.cxx:"
1368 " Document::changeParagraphAttributes")),
1369 static_cast< ::css::uno::XWeak * >(this));
1370
1371 // FIXME The new attributes are added to any attributes already set,
1372 // they do not replace the old attributes as required by
1373 // XAccessibleEditableText.setAttributes:
1374 for (::sal_Int32 i = 0; i < rAttributeSet.getLength(); ++i)
1375 if (rAttributeSet[i].Name.equalsAsciiL(
1376 RTL_CONSTASCII_STRINGPARAM("CharColor")))
1377 m_rEngine.SetAttrib(::TextAttribFontColor(
1378 mapFontColor(rAttributeSet[i].Value)),
1379 nNumber, static_cast< ::sal_uInt16 >(nBegin),
1380 static_cast< ::sal_uInt16 >(nEnd));
1381 // XXX numeric overflow (2x)
1382 else if (rAttributeSet[i].Name.equalsAsciiL(
1383 RTL_CONSTASCII_STRINGPARAM("CharWeight")))
1384 m_rEngine.SetAttrib(::TextAttribFontWeight(
1385 mapFontWeight(rAttributeSet[i].Value)),
1386 nNumber, static_cast< ::sal_uInt16 >(nBegin),
1387 static_cast< ::sal_uInt16 >(nEnd));
1388 // XXX numeric overflow (2x)
1389 }
1390 }
1391
changeParagraphSelection(ParagraphImpl * pParagraph,::sal_Int32 nBegin,::sal_Int32 nEnd)1392 void Document::changeParagraphSelection(ParagraphImpl * pParagraph,
1393 ::sal_Int32 nBegin, ::sal_Int32 nEnd)
1394 {
1395 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
1396 {
1397 ::osl::MutexGuard aInternalGuard(GetMutex());
1398 ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
1399 // XXX numeric overflow
1400 if (nBegin < 0 || nBegin > nEnd
1401 || nEnd > m_rEngine.GetText(nNumber).Len())
1402 throw ::css::lang::IndexOutOfBoundsException(
1403 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1404 "textwindowaccessibility.cxx:"
1405 " Document::changeParagraphSelection")),
1406 static_cast< ::css::uno::XWeak * >(this));
1407 m_rView.SetSelection(
1408 ::TextSelection(::TextPaM(nNumber, static_cast< ::sal_uInt16 >(nBegin)),
1409 ::TextPaM(nNumber, static_cast< ::sal_uInt16 >(nEnd))));
1410 // XXX numeric overflow (2x)
1411 }
1412 }
1413
1414 ::css::i18n::Boundary
retrieveParagraphLineBoundary(ParagraphImpl const * pParagraph,::sal_Int32 nIndex,::sal_Int32 * pLineNo)1415 Document::retrieveParagraphLineBoundary( ParagraphImpl const * pParagraph,
1416 ::sal_Int32 nIndex, ::sal_Int32 *pLineNo )
1417 {
1418 ::css::i18n::Boundary aBoundary;
1419 aBoundary.startPos = nIndex;
1420 aBoundary.endPos = nIndex;
1421
1422 ::osl::Guard< ::comphelper::IMutex > aExternalGuard( getExternalLock() );
1423 {
1424 ::osl::MutexGuard aInternalGuard( GetMutex() );
1425 ::sal_uLong nNumber = static_cast< ::sal_uLong >( pParagraph->getNumber() );
1426 if ( nIndex < 0 || nIndex > m_rEngine.GetText( nNumber ).Len() )
1427 throw ::css::lang::IndexOutOfBoundsException(
1428 ::rtl::OUString(
1429 RTL_CONSTASCII_USTRINGPARAM(
1430 "textwindowaccessibility.cxx:"
1431 " Document::retrieveParagraphLineBoundary" ) ),
1432 static_cast< ::css::uno::XWeak * >( this ) );
1433 ::sal_Int32 nLineStart = 0;
1434 ::sal_Int32 nLineEnd = 0;
1435 ::sal_uInt16 nLineCount = m_rEngine.GetLineCount( nNumber );
1436 for ( ::sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine )
1437 {
1438 ::sal_Int32 nLineLength = static_cast< ::sal_Int32 >(
1439 m_rEngine.GetLineLen( nNumber, nLine ) );
1440 nLineStart = nLineEnd;
1441 nLineEnd += nLineLength;
1442 if ( nIndex >= nLineStart && ( ( nLine == nLineCount - 1 ) ? nIndex <= nLineEnd : nIndex < nLineEnd ) )
1443 {
1444 aBoundary.startPos = nLineStart;
1445 aBoundary.endPos = nLineEnd;
1446 if( pLineNo )
1447 pLineNo[0] = nLine;
1448 break;
1449 }
1450 }
1451 }
1452
1453 return aBoundary;
1454 }
1455
1456 ::css::i18n::Boundary
retrieveParagraphBoundaryOfLine(ParagraphImpl const * pParagraph,::sal_Int32 nLineNo)1457 Document::retrieveParagraphBoundaryOfLine( ParagraphImpl const * pParagraph,
1458 ::sal_Int32 nLineNo )
1459 {
1460 ::css::i18n::Boundary aBoundary;
1461 aBoundary.startPos = 0;
1462 aBoundary.endPos = 0;
1463
1464 ::osl::Guard< ::comphelper::IMutex > aExternalGuard( getExternalLock() );
1465 {
1466 ::osl::MutexGuard aInternalGuard( GetMutex() );
1467 ::sal_uLong nNumber = static_cast< ::sal_uLong >( pParagraph->getNumber() );
1468 if ( nLineNo >= m_rEngine.GetLineCount( nNumber ) )
1469 throw ::css::lang::IndexOutOfBoundsException(
1470 ::rtl::OUString(
1471 RTL_CONSTASCII_USTRINGPARAM(
1472 "textwindowaccessibility.cxx:"
1473 " Document::retrieveParagraphBoundaryOfLine" ) ),
1474 static_cast< ::css::uno::XWeak * >( this ) );
1475 ::sal_Int32 nLineStart = 0;
1476 ::sal_Int32 nLineEnd = 0;
1477 for ( ::sal_uInt16 nLine = 0; nLine <= nLineNo; ++nLine )
1478 {
1479 ::sal_Int32 nLineLength = static_cast< ::sal_Int32 >(
1480 m_rEngine.GetLineLen( nNumber, nLine ) );
1481 nLineStart = nLineEnd;
1482 nLineEnd += nLineLength;
1483 }
1484
1485 aBoundary.startPos = nLineStart;
1486 aBoundary.endPos = nLineEnd;
1487 }
1488
1489 return aBoundary;
1490 }
1491
retrieveParagraphLineWithCursor(ParagraphImpl const * pParagraph)1492 sal_Int32 Document::retrieveParagraphLineWithCursor( ParagraphImpl const * pParagraph )
1493 {
1494 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
1495 ::osl::MutexGuard aInternalGuard(GetMutex());
1496 ::TextSelection const & rSelection = m_rView.GetSelection();
1497 Paragraphs::size_type nNumber = pParagraph->getNumber();
1498 TextPaM aEndPaM( rSelection.GetEnd() );
1499
1500 return aEndPaM.GetPara() == nNumber
1501 ? m_rView.GetLineNumberOfCursorInSelection() : -1;
1502 }
1503
1504
1505 ::css::uno::Reference< ::css::accessibility::XAccessibleRelationSet >
retrieveParagraphRelationSet(ParagraphImpl const * pParagraph)1506 Document::retrieveParagraphRelationSet( ParagraphImpl const * pParagraph )
1507 {
1508 ::osl::MutexGuard aInternalGuard( GetMutex() );
1509
1510 ::utl::AccessibleRelationSetHelper* pRelationSetHelper = new ::utl::AccessibleRelationSetHelper();
1511 ::css::uno::Reference< ::css::accessibility::XAccessibleRelationSet > xSet = pRelationSetHelper;
1512
1513 Paragraphs::iterator aPara( m_xParagraphs->begin() + pParagraph->getNumber() );
1514
1515 if ( aPara > m_aVisibleBegin && aPara < m_aVisibleEnd )
1516 {
1517 ::css::uno::Sequence< ::css::uno::Reference< ::css::uno::XInterface > > aSequence(1);
1518 aSequence[0] = getAccessibleChild( aPara - 1 );
1519 ::css::accessibility::AccessibleRelation aRelation( ::css::accessibility::AccessibleRelationType::CONTENT_FLOWS_FROM, aSequence );
1520 pRelationSetHelper->AddRelation( aRelation );
1521 }
1522
1523 if ( aPara >= m_aVisibleBegin && aPara < m_aVisibleEnd -1 )
1524 {
1525 ::css::uno::Sequence< ::css::uno::Reference< ::css::uno::XInterface > > aSequence(1);
1526 aSequence[0] = getAccessibleChild( aPara + 1 );
1527 ::css::accessibility::AccessibleRelation aRelation( ::css::accessibility::AccessibleRelationType::CONTENT_FLOWS_TO, aSequence );
1528 pRelationSetHelper->AddRelation( aRelation );
1529 }
1530
1531 return xSet;
1532 }
1533
ProcessWindowEvent(const VclWindowEvent & rVclWindowEvent)1534 void Document::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
1535 {
1536 VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
1537 }
1538
1539 // virtual
getAccessibleChildCount()1540 ::sal_Int32 SAL_CALL Document::getAccessibleChildCount()
1541 throw (::css::uno::RuntimeException)
1542 {
1543 ::comphelper::OExternalLockGuard aGuard(this);
1544 init();
1545 return m_aVisibleEnd - m_aVisibleBegin;
1546 }
1547
1548 // virtual
1549 ::css::uno::Reference< ::css::accessibility::XAccessible > SAL_CALL
getAccessibleChild(::sal_Int32 i)1550 Document::getAccessibleChild(::sal_Int32 i)
1551 throw (::css::lang::IndexOutOfBoundsException,
1552 ::css::uno::RuntimeException)
1553 {
1554 ::comphelper::OExternalLockGuard aGuard(this);
1555 init();
1556 if (i < 0 || i >= m_aVisibleEnd - m_aVisibleBegin)
1557 throw ::css::lang::IndexOutOfBoundsException(
1558 ::rtl::OUString(
1559 RTL_CONSTASCII_USTRINGPARAM(
1560 "textwindowaccessibility.cxx:"
1561 " Document::getAccessibleChild")),
1562 static_cast< ::css::uno::XWeak * >(this));
1563 return getAccessibleChild(m_aVisibleBegin
1564 + static_cast< Paragraphs::size_type >(i));
1565 }
1566
1567 // virtual
getAccessibleRole()1568 ::sal_Int16 SAL_CALL Document::getAccessibleRole()
1569 throw (::css::uno::RuntimeException)
1570 {
1571 return ::css::accessibility::AccessibleRole::TEXT_FRAME;
1572 }
1573
1574 // virtual
1575 ::css::uno::Reference< ::css::accessibility::XAccessible > SAL_CALL
getAccessibleAtPoint(::css::awt::Point const & rPoint)1576 Document::getAccessibleAtPoint(::css::awt::Point const & rPoint)
1577 throw (::css::uno::RuntimeException)
1578 {
1579 ::comphelper::OExternalLockGuard aGuard(this);
1580 init();
1581 if (rPoint.X >= 0
1582 && rPoint.X < m_rView.GetWindow()->GetOutputSizePixel().Width()
1583 && rPoint.Y >= 0 && rPoint.Y < m_nViewHeight)
1584 {
1585 ::sal_Int32 nOffset = m_nViewOffset + rPoint.Y; // XXX numeric overflow
1586 ::sal_Int32 nPos = m_nViewOffset - m_nVisibleBeginOffset;
1587 for (Paragraphs::iterator aIt(m_aVisibleBegin); aIt != m_aVisibleEnd;
1588 ++aIt)
1589 {
1590 nPos += aIt->getHeight(); // XXX numeric overflow
1591 if (nOffset < nPos)
1592 return getAccessibleChild(aIt);
1593 }
1594 }
1595 return 0;
1596 }
FillAccessibleStateSet(utl::AccessibleStateSetHelper & rStateSet)1597 void Document::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
1598 {
1599 VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
1600 if (!m_rView.IsReadOnly())
1601 rStateSet.AddState( ::css::accessibility::AccessibleStateType::EDITABLE );
1602 }
1603
FillAccessibleRelationSet(utl::AccessibleRelationSetHelper & rRelationSet)1604 void Document::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
1605 {
1606 if( getAccessibleParent()->getAccessibleContext()->getAccessibleRole() == ::css::accessibility::AccessibleRole::SCROLL_PANE )
1607 {
1608 ::css::uno::Sequence< ::css::uno::Reference< ::css::uno::XInterface > > aSequence(1);
1609 aSequence[0] = getAccessibleParent();
1610 rRelationSet.AddRelation( ::css::accessibility::AccessibleRelation( ::css::accessibility::AccessibleRelationType::MEMBER_OF, aSequence ) );
1611 }
1612 else
1613 {
1614 VCLXAccessibleComponent::FillAccessibleRelationSet(rRelationSet);
1615 }
1616 }
1617 // virtual
disposing()1618 void SAL_CALL Document::disposing()
1619 {
1620 m_aEngineListener.endListening();
1621 m_aViewListener.endListening();
1622 if (m_xParagraphs.get() != 0)
1623 disposeParagraphs();
1624 VCLXAccessibleComponent::disposing();
1625 }
1626
1627 // virtual
Notify(::SfxBroadcaster &,::SfxHint const & rHint)1628 void Document::Notify(::SfxBroadcaster &, ::SfxHint const & rHint)
1629 {
1630 if (rHint.ISA(::TextHint))
1631 {
1632 ::TextHint const & rTextHint
1633 = static_cast< ::TextHint const & >(rHint);
1634 switch (rTextHint.GetId())
1635 {
1636 case TEXT_HINT_PARAINSERTED:
1637 case TEXT_HINT_PARAREMOVED:
1638 // TEXT_HINT_PARAINSERTED and TEXT_HINT_PARAREMOVED are sent at
1639 // "unsafe" times (when the text engine has not yet re-formatted its
1640 // content), so that for example calling ::TextEngine::GetTextHeight
1641 // from within the code that handles TEXT_HINT_PARAINSERTED causes
1642 // trouble within the text engine. Therefore, these hints are just
1643 // buffered until a following ::TextEngine::FormatDoc causes a
1644 // TEXT_HINT_TEXTFORMATTED to come in:
1645 case TEXT_HINT_FORMATPARA:
1646 // ::TextEngine::FormatDoc sends a sequence of
1647 // TEXT_HINT_FORMATPARAs, followed by an optional
1648 // TEXT_HINT_TEXTHEIGHTCHANGED, followed in all cases by one
1649 // TEXT_HINT_TEXTFORMATTED. Only the TEXT_HINT_FORMATPARAs contain
1650 // the numbers of the affected paragraphs, but they are sent
1651 // before the changes are applied. Therefore, TEXT_HINT_FORMATPARAs
1652 // are just buffered until another hint comes in:
1653 {
1654 ::osl::MutexGuard aInternalGuard(GetMutex());
1655 if (!isAlive())
1656 break;
1657
1658 m_aParagraphNotifications.push(rTextHint);
1659 break;
1660 }
1661 case TEXT_HINT_TEXTFORMATTED:
1662 case TEXT_HINT_TEXTHEIGHTCHANGED:
1663 case TEXT_HINT_MODIFIED:
1664 {
1665 ::osl::MutexGuard aInternalGuard(GetMutex());
1666 if (!isAlive())
1667 break;
1668 handleParagraphNotifications();
1669 break;
1670 }
1671 case TEXT_HINT_VIEWSCROLLED:
1672 {
1673 ::osl::MutexGuard aInternalGuard(GetMutex());
1674 if (!isAlive())
1675 break;
1676 handleParagraphNotifications();
1677
1678 ::sal_Int32 nOffset = static_cast< ::sal_Int32 >(
1679 m_rView.GetStartDocPos().Y());
1680 // XXX numeric overflow
1681 if (nOffset != m_nViewOffset)
1682 {
1683 m_nViewOffset = nOffset;
1684
1685 Paragraphs::iterator aOldVisibleBegin(
1686 m_aVisibleBegin);
1687 Paragraphs::iterator aOldVisibleEnd(m_aVisibleEnd);
1688
1689 determineVisibleRange();
1690
1691 notifyVisibleRangeChanges(aOldVisibleBegin,
1692 aOldVisibleEnd,
1693 m_xParagraphs->end());
1694 }
1695 break;
1696 }
1697 case TEXT_HINT_VIEWSELECTIONCHANGED:
1698 {
1699 ::osl::MutexGuard aInternalGuard(GetMutex());
1700 if (!isAlive())
1701 break;
1702
1703 if (m_aParagraphNotifications.empty())
1704 {
1705 handleSelectionChangeNotification();
1706 }
1707 else
1708 {
1709 // TEXT_HINT_VIEWSELECTIONCHANGED is sometimes sent at
1710 // "unsafe" times (when the text engine has not yet re-
1711 // formatted its content), so that for example calling
1712 // ::TextEngine::GetTextHeight from within the code that
1713 // handles a previous TEXT_HINT_PARAINSERTED causes
1714 // trouble within the text engine. Therefore, these
1715 // hints are just buffered (along with
1716 // TEXT_HINT_PARAINSERTED/REMOVED/FORMATPARA) until a
1717 // following ::TextEngine::FormatDoc causes a
1718 // TEXT_HINT_TEXTFORMATTED to come in:
1719 m_bSelectionChangedNotification = true;
1720 }
1721 break;
1722 }
1723 }
1724 }
1725 }
1726
IMPL_LINK(Document,WindowEventHandler,::VclSimpleEvent *,pEvent)1727 IMPL_LINK(Document, WindowEventHandler, ::VclSimpleEvent *, pEvent)
1728 {
1729 switch (pEvent->GetId())
1730 {
1731 case VCLEVENT_WINDOW_RESIZE:
1732 {
1733 ::osl::MutexGuard aInternalGuard(GetMutex());
1734 if (!isAlive())
1735 break;
1736
1737 ::sal_Int32 nHeight = static_cast< ::sal_Int32 >(
1738 m_rView.GetWindow()->GetOutputSizePixel().Height());
1739 // XXX numeric overflow
1740 if (nHeight != m_nViewHeight)
1741 {
1742 m_nViewHeight = nHeight;
1743
1744 Paragraphs::iterator aOldVisibleBegin(m_aVisibleBegin);
1745 Paragraphs::iterator aOldVisibleEnd(m_aVisibleEnd);
1746
1747 determineVisibleRange();
1748
1749 notifyVisibleRangeChanges(aOldVisibleBegin, aOldVisibleEnd,
1750 m_xParagraphs->end());
1751 }
1752 break;
1753 }
1754 case VCLEVENT_WINDOW_GETFOCUS:
1755 {
1756 ::osl::MutexGuard aInternalGuard(GetMutex());
1757 if (!isAlive())
1758 break;
1759 //to enable the PARAGRAPH to get focus for multiline edit
1760 ::sal_Int32 count = getAccessibleChildCount();
1761 ::sal_Bool bEmpty = m_aFocused == m_aVisibleEnd && count == 1;
1762 if ((m_aFocused >= m_aVisibleBegin && m_aFocused < m_aVisibleEnd) || bEmpty)
1763 {
1764 Paragraphs::iterator m_aTemp = bEmpty ? m_aVisibleBegin : m_aFocused;
1765 ::rtl::Reference< ParagraphImpl > xParagraph(getParagraph(m_aTemp));
1766 if (xParagraph.is())
1767 {
1768 xParagraph->notifyEvent(
1769 ::css::accessibility::AccessibleEventId::
1770 STATE_CHANGED,
1771 ::css::uno::Any(),
1772 ::css::uno::makeAny(
1773 ::css::accessibility::AccessibleStateType::
1774 FOCUSED));
1775 }
1776 }
1777 /*
1778 ::rtl::Reference< ParagraphImpl > xParagraph(
1779 getParagraph(m_aFocused));
1780 if (xParagraph.is())
1781 xParagraph->notifyEvent(
1782 ::css::accessibility::AccessibleEventId::
1783 STATE_CHANGED,
1784 ::css::uno::Any(),
1785 ::css::uno::makeAny(
1786 ::css::accessibility::AccessibleStateType::
1787 FOCUSED));
1788 */
1789 break;
1790 }
1791 case VCLEVENT_WINDOW_LOSEFOCUS:
1792 {
1793 ::osl::MutexGuard aInternalGuard(GetMutex());
1794 if (!isAlive())
1795 break;
1796 //to enable the PARAGRAPH to get focus for multiline edit
1797 ::sal_Int32 count = getAccessibleChildCount();
1798 ::sal_Bool bEmpty = m_aFocused == m_aVisibleEnd && count == 1;
1799 if ((m_aFocused >= m_aVisibleBegin && m_aFocused < m_aVisibleEnd) || bEmpty)
1800 {
1801 Paragraphs::iterator m_aTemp = bEmpty ? m_aVisibleBegin : m_aFocused;
1802 ::rtl::Reference< ParagraphImpl > xParagraph(getParagraph(m_aTemp));
1803 if (xParagraph.is())
1804 xParagraph->notifyEvent(
1805 ::css::accessibility::AccessibleEventId::
1806 STATE_CHANGED,
1807 ::css::uno::makeAny(
1808 ::css::accessibility::AccessibleStateType::
1809 FOCUSED),
1810 ::css::uno::Any());
1811 }
1812
1813 /*
1814 if (m_aFocused >= m_aVisibleBegin && m_aFocused < m_aVisibleEnd)
1815 {
1816 ::rtl::Reference< ParagraphImpl > xParagraph(
1817 getParagraph(m_aFocused));
1818 if (xParagraph.is())
1819 xParagraph->notifyEvent(
1820 ::css::accessibility::AccessibleEventId::
1821 STATE_CHANGED,
1822 ::css::uno::makeAny(
1823 ::css::accessibility::AccessibleStateType::
1824 FOCUSED),
1825 ::css::uno::Any());
1826 }
1827 */
1828 break;
1829 }
1830 }
1831 return 0;
1832 }
1833
init()1834 void Document::init()
1835 {
1836 if (m_xParagraphs.get() == 0)
1837 {
1838 ::sal_uLong nCount = m_rEngine.GetParagraphCount();
1839 ::std::auto_ptr< Paragraphs > p(new Paragraphs);
1840 p->reserve(static_cast< Paragraphs::size_type >(nCount));
1841 // numeric overflow is harmless here
1842 for (::sal_uLong i = 0; i < nCount; ++i)
1843 p->push_back(ParagraphInfo(static_cast< ::sal_Int32 >(
1844 m_rEngine.GetTextHeight(i))));
1845 // XXX numeric overflow
1846 m_nViewOffset = static_cast< ::sal_Int32 >(
1847 m_rView.GetStartDocPos().Y()); // XXX numeric overflow
1848 m_nViewHeight = static_cast< ::sal_Int32 >(
1849 m_rView.GetWindow()->GetOutputSizePixel().Height());
1850 // XXX numeric overflow
1851 m_xParagraphs = p;
1852 determineVisibleRange();
1853 m_nSelectionFirstPara = -1;
1854 m_nSelectionFirstPos = -1;
1855 m_nSelectionLastPara = -1;
1856 m_nSelectionLastPos = -1;
1857 m_aFocused = m_xParagraphs->end();
1858 m_bSelectionChangedNotification = false;
1859 m_aEngineListener.startListening(m_rEngine);
1860 m_aViewListener.startListening(*m_rView.GetWindow());
1861 }
1862 }
1863
1864 ::rtl::Reference< ParagraphImpl >
getParagraph(Paragraphs::iterator const & rIt)1865 Document::getParagraph(Paragraphs::iterator const & rIt)
1866 {
1867 return static_cast< ParagraphImpl * >(
1868 ::css::uno::Reference< ::css::accessibility::XAccessible >(
1869 rIt->getParagraph()).get());
1870 }
1871
1872 ::css::uno::Reference< ::css::accessibility::XAccessible >
getAccessibleChild(Paragraphs::iterator const & rIt)1873 Document::getAccessibleChild(Paragraphs::iterator const & rIt)
1874 {
1875 ::css::uno::Reference< ::css::accessibility::XAccessible > xParagraph(
1876 rIt->getParagraph());
1877 if (!xParagraph.is())
1878 {
1879 xParagraph = new Paragraph(this, rIt - m_xParagraphs->begin());
1880 rIt->setParagraph(xParagraph);
1881 }
1882 return xParagraph;
1883 }
1884
determineVisibleRange()1885 void Document::determineVisibleRange()
1886 {
1887 m_aVisibleBegin = m_xParagraphs->end();
1888 m_aVisibleEnd = m_aVisibleBegin;
1889 ::sal_Int32 nPos = 0;
1890 for (Paragraphs::iterator aIt = m_xParagraphs->begin();;)
1891 {
1892 if (aIt == m_xParagraphs->end())
1893 {
1894 m_nVisibleBeginOffset = 0;
1895 break;
1896 }
1897 ::sal_Int32 nOldPos = nPos;
1898 nPos += aIt->getHeight(); // XXX numeric overflow
1899 if (m_aVisibleBegin == m_xParagraphs->end() && nPos >= m_nViewOffset)
1900 {
1901 m_aVisibleBegin = aIt;
1902 m_nVisibleBeginOffset = m_nViewOffset - nOldPos;
1903 }
1904 ++aIt;
1905 if (m_aVisibleBegin != m_xParagraphs->end()
1906 && (aIt == m_xParagraphs->end()
1907 || nPos >= m_nViewOffset + m_nViewHeight))
1908 // XXX numeric overflow
1909 {
1910 m_aVisibleEnd = aIt;
1911 break;
1912 }
1913 }
1914 }
1915
notifyVisibleRangeChanges(Paragraphs::iterator const & rOldVisibleBegin,Paragraphs::iterator const & rOldVisibleEnd,Paragraphs::iterator const & rInserted)1916 void Document::notifyVisibleRangeChanges(
1917 Paragraphs::iterator const & rOldVisibleBegin,
1918 Paragraphs::iterator const & rOldVisibleEnd,
1919 Paragraphs::iterator const & rInserted)
1920 {
1921 // XXX Replace this code that determines which paragraphs have changed from
1922 // invisible to visible or vice versa with a better algorithm.
1923 {for (Paragraphs::iterator aIt(rOldVisibleBegin); aIt != rOldVisibleEnd;
1924 ++aIt)
1925 if (aIt != rInserted
1926 && (aIt < m_aVisibleBegin || aIt >= m_aVisibleEnd))
1927 NotifyAccessibleEvent(
1928 ::css::accessibility::AccessibleEventId::
1929 CHILD,
1930 ::css::uno::makeAny(getAccessibleChild(aIt)),
1931 ::css::uno::Any());
1932 }
1933 {for (Paragraphs::iterator aIt(m_aVisibleBegin); aIt != m_aVisibleEnd;
1934 ++aIt)
1935 if (aIt == rInserted
1936 || aIt < rOldVisibleBegin || aIt >= rOldVisibleEnd)
1937 NotifyAccessibleEvent(
1938 ::css::accessibility::AccessibleEventId::
1939 CHILD,
1940 ::css::uno::Any(),
1941 ::css::uno::makeAny(getAccessibleChild(aIt)));
1942 }
1943 }
1944
1945 void
changeParagraphText(::sal_uLong nNumber,::sal_uInt16 nBegin,::sal_uInt16 nEnd,bool bCut,bool bPaste,::rtl::OUString const & rText)1946 Document::changeParagraphText(::sal_uLong nNumber, ::sal_uInt16 nBegin, ::sal_uInt16 nEnd,
1947 bool bCut, bool bPaste,
1948 ::rtl::OUString const & rText)
1949 {
1950 m_rView.SetSelection(::TextSelection(::TextPaM(nNumber, nBegin),
1951 ::TextPaM(nNumber, nEnd)));
1952 if (bCut)
1953 m_rView.Cut();
1954 else if (nBegin != nEnd)
1955 m_rView.DeleteSelected();
1956 if (bPaste)
1957 m_rView.Paste();
1958 else if ( !rText.isEmpty() )
1959 m_rView.InsertText(rText);
1960 }
1961
handleParagraphNotifications()1962 void Document::handleParagraphNotifications()
1963 {
1964 while (!m_aParagraphNotifications.empty())
1965 {
1966 ::TextHint aHint(m_aParagraphNotifications.front());
1967 m_aParagraphNotifications.pop();
1968 switch (aHint.GetId())
1969 {
1970 case TEXT_HINT_PARAINSERTED:
1971 {
1972 ::sal_uLong n = aHint.GetValue();
1973 OSL_ENSURE(n <= m_xParagraphs->size(),
1974 "bad TEXT_HINT_PARAINSERTED event");
1975
1976 // Save the values of old iterators (the iterators themselves
1977 // will get invalidated), and adjust the old values so that they
1978 // reflect the insertion of the new paragraph:
1979 Paragraphs::size_type nOldVisibleBegin
1980 = m_aVisibleBegin - m_xParagraphs->begin();
1981 Paragraphs::size_type nOldVisibleEnd
1982 = m_aVisibleEnd - m_xParagraphs->begin();
1983 Paragraphs::size_type nOldFocused
1984 = m_aFocused - m_xParagraphs->begin();
1985 if (n <= nOldVisibleBegin)
1986 ++nOldVisibleBegin; // XXX numeric overflow
1987 if (n <= nOldVisibleEnd)
1988 ++nOldVisibleEnd; // XXX numeric overflow
1989 if (n <= nOldFocused)
1990 ++nOldFocused; // XXX numeric overflow
1991 if (sal::static_int_cast<sal_Int32>(n) <= m_nSelectionFirstPara)
1992 ++m_nSelectionFirstPara; // XXX numeric overflow
1993 if (sal::static_int_cast<sal_Int32>(n) <= m_nSelectionLastPara)
1994 ++m_nSelectionLastPara; // XXX numeric overflow
1995
1996 Paragraphs::iterator aIns(
1997 m_xParagraphs->insert(
1998 m_xParagraphs->begin() + n,
1999 ParagraphInfo(static_cast< ::sal_Int32 >(
2000 m_rEngine.GetTextHeight(n)))));
2001 // XXX numeric overflow (2x)
2002
2003 determineVisibleRange();
2004 m_aFocused = m_xParagraphs->begin() + nOldFocused;
2005
2006 for (Paragraphs::iterator aIt(aIns);;)
2007 {
2008 ++aIt;
2009 if (aIt == m_xParagraphs->end())
2010 break;
2011 ::rtl::Reference< ParagraphImpl > xParagraph(
2012 getParagraph(aIt));
2013 if (xParagraph.is())
2014 xParagraph->numberChanged(true);
2015 }
2016
2017 notifyVisibleRangeChanges(
2018 m_xParagraphs->begin() + nOldVisibleBegin,
2019 m_xParagraphs->begin() + nOldVisibleEnd, aIns);
2020 break;
2021 }
2022 case TEXT_HINT_PARAREMOVED:
2023 {
2024 ::sal_uLong n = aHint.GetValue();
2025 if (n == TEXT_PARA_ALL)
2026 {
2027 {for (Paragraphs::iterator aIt(m_aVisibleBegin);
2028 aIt != m_aVisibleEnd; ++aIt)
2029 NotifyAccessibleEvent(
2030 ::css::accessibility::AccessibleEventId::
2031 CHILD,
2032 ::css::uno::makeAny(getAccessibleChild(aIt)),
2033 ::css::uno::Any());
2034 }
2035 disposeParagraphs();
2036 m_xParagraphs->clear();
2037 determineVisibleRange();
2038 m_nSelectionFirstPara = -1;
2039 m_nSelectionFirstPos = -1;
2040 m_nSelectionLastPara = -1;
2041 m_nSelectionLastPos = -1;
2042 m_aFocused = m_xParagraphs->end();
2043 }
2044 else
2045 {
2046 OSL_ENSURE(n < m_xParagraphs->size(),
2047 "Bad TEXT_HINT_PARAREMOVED event");
2048
2049 Paragraphs::iterator aIt(m_xParagraphs->begin() + n);
2050 // numeric overflow cannot occur
2051
2052 // Save the values of old iterators (the iterators
2053 // themselves will get invalidated), and adjust the old
2054 // values so that they reflect the removal of the paragraph:
2055 Paragraphs::size_type nOldVisibleBegin
2056 = m_aVisibleBegin - m_xParagraphs->begin();
2057 Paragraphs::size_type nOldVisibleEnd
2058 = m_aVisibleEnd - m_xParagraphs->begin();
2059 bool bWasVisible
2060 = nOldVisibleBegin <= n && n < nOldVisibleEnd;
2061 Paragraphs::size_type nOldFocused
2062 = m_aFocused - m_xParagraphs->begin();
2063 bool bWasFocused = aIt == m_aFocused;
2064 if (n < nOldVisibleBegin)
2065 --nOldVisibleBegin;
2066 if (n < nOldVisibleEnd)
2067 --nOldVisibleEnd;
2068 if (n < nOldFocused)
2069 --nOldFocused;
2070 if (sal::static_int_cast<sal_Int32>(n) < m_nSelectionFirstPara)
2071 --m_nSelectionFirstPara;
2072 else if (sal::static_int_cast<sal_Int32>(n) == m_nSelectionFirstPara)
2073 {
2074 if (m_nSelectionFirstPara == m_nSelectionLastPara)
2075 {
2076 m_nSelectionFirstPara = -1;
2077 m_nSelectionFirstPos = -1;
2078 m_nSelectionLastPara = -1;
2079 m_nSelectionLastPos = -1;
2080 }
2081 else
2082 {
2083 ++m_nSelectionFirstPara;
2084 m_nSelectionFirstPos = 0;
2085 }
2086 }
2087 if (sal::static_int_cast<sal_Int32>(n) < m_nSelectionLastPara)
2088 --m_nSelectionLastPara;
2089 else if (sal::static_int_cast<sal_Int32>(n) == m_nSelectionLastPara)
2090 {
2091 OSL_ENSURE(m_nSelectionFirstPara < m_nSelectionLastPara,
2092 "logic error");
2093 --m_nSelectionLastPara;
2094 m_nSelectionLastPos = 0x7FFFFFFF;
2095 }
2096
2097 ::css::uno::Reference< ::css::accessibility::XAccessible >
2098 xStrong;
2099 if (bWasVisible)
2100 xStrong = getAccessibleChild(aIt);
2101 ::css::uno::WeakReference<
2102 ::css::accessibility::XAccessible > xWeak(
2103 aIt->getParagraph());
2104 aIt = m_xParagraphs->erase(aIt);
2105
2106 determineVisibleRange();
2107 m_aFocused = bWasFocused ? m_xParagraphs->end()
2108 : m_xParagraphs->begin() + nOldFocused;
2109
2110 for (; aIt != m_xParagraphs->end(); ++aIt)
2111 {
2112 ::rtl::Reference< ParagraphImpl > xParagraph(
2113 getParagraph(aIt));
2114 if (xParagraph.is())
2115 xParagraph->numberChanged(false);
2116 }
2117
2118 if (bWasVisible)
2119 NotifyAccessibleEvent(
2120 ::css::accessibility::AccessibleEventId::
2121 CHILD,
2122 ::css::uno::makeAny(getAccessibleChild(aIt)),
2123 ::css::uno::Any());
2124
2125 ::css::uno::Reference< ::css::lang::XComponent > xComponent(
2126 xWeak.get(), ::css::uno::UNO_QUERY);
2127 if (xComponent.is())
2128 xComponent->dispose();
2129
2130 notifyVisibleRangeChanges(
2131 m_xParagraphs->begin() + nOldVisibleBegin,
2132 m_xParagraphs->begin() + nOldVisibleEnd,
2133 m_xParagraphs->end());
2134 }
2135 break;
2136 }
2137 case TEXT_HINT_FORMATPARA:
2138 {
2139 ::sal_uLong n = aHint.GetValue();
2140 OSL_ENSURE(n < m_xParagraphs->size(),
2141 "Bad TEXT_HINT_FORMATPARA event");
2142
2143 (*m_xParagraphs)[static_cast< Paragraphs::size_type >(n)].
2144 changeHeight(static_cast< ::sal_Int32 >(
2145 m_rEngine.GetTextHeight(n)));
2146 // XXX numeric overflow
2147 Paragraphs::iterator aOldVisibleBegin(m_aVisibleBegin);
2148 Paragraphs::iterator aOldVisibleEnd(m_aVisibleEnd);
2149 determineVisibleRange();
2150 notifyVisibleRangeChanges(aOldVisibleBegin, aOldVisibleEnd,
2151 m_xParagraphs->end());
2152
2153 if (n < m_xParagraphs->size())
2154 {
2155 Paragraphs::iterator aIt(m_xParagraphs->begin() + n);
2156 ::rtl::Reference< ParagraphImpl > xParagraph(getParagraph(aIt));
2157 if (xParagraph.is())
2158 xParagraph->textChanged();
2159 }
2160 break;
2161 }
2162 default:
2163 OSL_ENSURE(false, "bad buffered hint");
2164 break;
2165 }
2166 }
2167 if (m_bSelectionChangedNotification)
2168 {
2169 m_bSelectionChangedNotification = false;
2170 handleSelectionChangeNotification();
2171 }
2172 }
2173
getSelectionType(::sal_Int32 nNewFirstPara,::sal_Int32 nNewFirstPos,::sal_Int32 nNewLastPara,::sal_Int32 nNewLastPos)2174 ::sal_Int32 Document::getSelectionType(::sal_Int32 nNewFirstPara, ::sal_Int32 nNewFirstPos, ::sal_Int32 nNewLastPara, ::sal_Int32 nNewLastPos)
2175 {
2176 if (m_nSelectionFirstPara == -1)
2177 return -1;
2178 ::sal_Int32 Osp = m_nSelectionFirstPara, Osl = m_nSelectionFirstPos, Oep = m_nSelectionLastPara, Oel = m_nSelectionLastPos;
2179 ::sal_Int32 Nsp = nNewFirstPara, Nsl = nNewFirstPos, Nep = nNewLastPara, Nel = nNewLastPos;
2180 TextPaM Ns(Nsp, sal_uInt16(Nsl));
2181 TextPaM Ne(Nep, sal_uInt16(Nel));
2182 TextPaM Os(Osp, sal_uInt16(Osl));
2183 TextPaM Oe(Oep, sal_uInt16(Oel));
2184
2185 if (Os == Oe && Ns == Ne)
2186 {
2187 //only caret moves.
2188 return 1;
2189 }
2190 else if (Os == Oe && Ns != Ne)
2191 {
2192 //old has no selection but new has selection
2193 return 2;
2194 }
2195 else if (Os != Oe && Ns == Ne)
2196 {
2197 //old has selection but new has no selection.
2198 return 3;
2199 }
2200 else if (Os != Oe && Ns != Ne && Osp == Nsp && Osl == Nsl)
2201 {
2202 //both old and new have selections.
2203 if (Oep == Nep )
2204 {
2205 //Send text_selection_change event on Nep
2206
2207 return 4;
2208 }
2209 else if (Oep < Nep)
2210 {
2211 //all the following examples like 1,2->1,3 means that old start select para is 1, old end select para is 2,
2212 // then press shift up, the new start select para is 1, new end select para is 3;
2213 //for example, 1, 2 -> 1, 3; 4,1 -> 4, 7; 4,1 -> 4, 2; 4,4->4,5
2214 if (Nep >= Nsp)
2215 {
2216 // 1, 2 -> 1, 3; 4, 1 -> 4, 7; 4,4->4,5;
2217 if (Oep < Osp)
2218 {
2219 // 4,1 -> 4,7;
2220 return 5;
2221 }
2222 else if (Oep >= Osp)
2223 {
2224 // 1, 2 -> 1, 3; 4,4->4,5;
2225 return 6;
2226 }
2227 }
2228 else
2229 {
2230 // 4,1 -> 4,2,
2231 if (Oep < Osp)
2232 {
2233 // 4,1 -> 4,2,
2234 return 7;
2235 }
2236 else if (Oep >= Osp)
2237 {
2238 // no such condition. Oep > Osp = Nsp > Nep
2239 }
2240 }
2241 }
2242 else if (Oep > Nep)
2243 {
2244 // 3,2 -> 3,1; 4,7 -> 4,1; 4, 7 -> 4,6; 4,4 -> 4,3
2245 if (Nep >= Nsp)
2246 {
2247 // 4,7 -> 4,6
2248 if (Oep <= Osp)
2249 {
2250 //no such condition, Oep<Osp=Nsp <= Nep
2251 }
2252 else if (Oep > Osp)
2253 {
2254 // 4,7 ->4,6
2255 return 8;
2256 }
2257 }
2258 else
2259 {
2260 // 3,2 -> 3,1, 4,7 -> 4,1; 4,4->4,3
2261 if (Oep <= Osp)
2262 {
2263 // 3,2 -> 3,1; 4,4->4,3
2264 return 9;
2265 }
2266 else if (Oep > Osp)
2267 {
2268 // 4,7 -> 4,1
2269 return 10;
2270 }
2271 }
2272 }
2273 }
2274 return -1;
2275 }
2276
2277
sendEvent(::sal_Int32 start,::sal_Int32 end,::sal_Int16 nEventId)2278 void Document::sendEvent(::sal_Int32 start, ::sal_Int32 end, ::sal_Int16 nEventId)
2279 {
2280 Paragraphs::iterator aEnd = ::std::min(m_xParagraphs->begin() + end + 1, m_aVisibleEnd);
2281 for (Paragraphs::iterator aIt = ::std::max(m_xParagraphs->begin() + start, m_aVisibleBegin);
2282 aIt < aEnd; ++aIt)
2283 {
2284 ::rtl::Reference< ParagraphImpl > xParagraph(getParagraph(aIt));
2285 if (xParagraph.is())
2286 xParagraph->notifyEvent(
2287 nEventId,
2288 ::css::uno::Any(), ::css::uno::Any());
2289 }
2290 }
2291
handleSelectionChangeNotification()2292 void Document::handleSelectionChangeNotification()
2293 {
2294 ::TextSelection const & rSelection = m_rView.GetSelection();
2295 OSL_ENSURE(rSelection.GetStart().GetPara() < m_xParagraphs->size()
2296 && rSelection.GetEnd().GetPara() < m_xParagraphs->size(),
2297 "bad TEXT_HINT_VIEWSELECTIONCHANGED event");
2298 ::sal_Int32 nNewFirstPara
2299 = static_cast< ::sal_Int32 >(rSelection.GetStart().GetPara());
2300 ::sal_Int32 nNewFirstPos
2301 = static_cast< ::sal_Int32 >(rSelection.GetStart().GetIndex());
2302 // XXX numeric overflow
2303 ::sal_Int32 nNewLastPara
2304 = static_cast< ::sal_Int32 >(rSelection.GetEnd().GetPara());
2305 ::sal_Int32 nNewLastPos
2306 = static_cast< ::sal_Int32 >(rSelection.GetEnd().GetIndex());
2307 // XXX numeric overflow
2308
2309 // Lose focus:
2310 Paragraphs::iterator aIt(m_xParagraphs->begin() + nNewLastPara);
2311 if (m_aFocused != m_xParagraphs->end() && m_aFocused != aIt
2312 && m_aFocused >= m_aVisibleBegin && m_aFocused < m_aVisibleEnd)
2313 {
2314 ::rtl::Reference< ParagraphImpl > xParagraph(getParagraph(m_aFocused));
2315 if (xParagraph.is())
2316 xParagraph->notifyEvent(
2317 ::css::accessibility::AccessibleEventId::
2318 STATE_CHANGED,
2319 ::css::uno::makeAny(
2320 ::css::accessibility::AccessibleStateType::FOCUSED),
2321 ::css::uno::Any());
2322 }
2323
2324 // Gain focus and update cursor position:
2325 if (aIt >= m_aVisibleBegin && aIt < m_aVisibleEnd
2326 && (aIt != m_aFocused
2327 || nNewLastPara != m_nSelectionLastPara
2328 || nNewLastPos != m_nSelectionLastPos))
2329 {
2330 ::rtl::Reference< ParagraphImpl > xParagraph(getParagraph(aIt));
2331 if (xParagraph.is())
2332 {
2333 //disable the first event when user types in empty field.
2334 ::sal_Int32 count = getAccessibleChildCount();
2335 ::sal_Bool bEmpty = count > 1;
2336 //if (aIt != m_aFocused)
2337 if (aIt != m_aFocused && bEmpty)
2338 xParagraph->notifyEvent(
2339 ::css::accessibility::AccessibleEventId::
2340 STATE_CHANGED,
2341 ::css::uno::Any(),
2342 ::css::uno::makeAny(
2343 ::css::accessibility::AccessibleStateType::FOCUSED));
2344 if (nNewLastPara != m_nSelectionLastPara
2345 || nNewLastPos != m_nSelectionLastPos)
2346 xParagraph->notifyEvent(
2347 ::css::accessibility::AccessibleEventId::
2348 CARET_CHANGED,
2349 ::css::uno::makeAny< ::sal_Int32 >(
2350 nNewLastPara == m_nSelectionLastPara
2351 ? m_nSelectionLastPos : 0),
2352 ::css::uno::makeAny(nNewLastPos));
2353 }
2354 }
2355 m_aFocused = aIt;
2356
2357 ::sal_Int32 nMin;
2358 ::sal_Int32 nMax;
2359 ::sal_Int32 ret = getSelectionType(nNewFirstPara, nNewFirstPos, nNewLastPara, nNewLastPos);
2360 switch (ret)
2361 {
2362 case -1:
2363 {
2364 //no event
2365 }
2366 break;
2367 case 1:
2368 {
2369 //only caret moved, already handled in above
2370 }
2371 break;
2372 case 2:
2373 {
2374 //old has no selection but new has selection
2375 nMin = ::std::min(nNewFirstPara, nNewLastPara);
2376 nMax = ::std::max(nNewFirstPara, nNewLastPara);
2377 sendEvent(nMin, nMax, ::css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2378 sendEvent(nMin, nMax, ::css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2379 }
2380 break;
2381 case 3:
2382 {
2383 //old has selection but new has no selection.
2384 nMin = ::std::min(m_nSelectionFirstPara, m_nSelectionLastPara);
2385 nMax = ::std::max(m_nSelectionFirstPara, m_nSelectionLastPara);
2386 sendEvent(nMin, nMax, ::css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2387 sendEvent(nMin, nMax, ::css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2388 }
2389 break;
2390 case 4:
2391 {
2392 //Send text_selection_change event on Nep
2393 sendEvent(nNewLastPara, nNewLastPara, ::css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2394 }
2395 break;
2396 case 5:
2397 {
2398 // 4, 1 -> 4, 7
2399 sendEvent(m_nSelectionLastPara, m_nSelectionFirstPara-1, ::css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2400 sendEvent(nNewFirstPara+1, nNewLastPara, ::css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2401
2402 sendEvent(m_nSelectionLastPara, nNewLastPara, ::css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2403 }
2404 break;
2405 case 6:
2406 {
2407 // 1, 2 -> 1, 4; 4,4->4,5;
2408 sendEvent(m_nSelectionLastPara+1, nNewLastPara, ::css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2409
2410 sendEvent(m_nSelectionLastPara, nNewLastPara, ::css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2411 }
2412 break;
2413 case 7:
2414 {
2415 // 4,1 -> 4,3,
2416 sendEvent(m_nSelectionLastPara +1, nNewLastPara , ::css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2417
2418 sendEvent(m_nSelectionLastPara, nNewLastPara, ::css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2419 }
2420 break;
2421 case 8:
2422 {
2423 // 4,7 ->4,5;
2424 sendEvent(nNewLastPara + 1, m_nSelectionLastPara, ::css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2425
2426 sendEvent(nNewLastPara, m_nSelectionLastPara, ::css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2427 }
2428 break;
2429 case 9:
2430 {
2431 // 3,2 -> 3,1; 4,4->4,3
2432 sendEvent(nNewLastPara, m_nSelectionLastPara - 1, ::css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2433
2434 sendEvent(nNewLastPara, m_nSelectionLastPara, ::css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2435 }
2436 break;
2437 case 10:
2438 {
2439 // 4,7 -> 4,1
2440 sendEvent(m_nSelectionFirstPara + 1, m_nSelectionLastPara, ::css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2441 sendEvent(nNewLastPara, nNewFirstPara - 1, ::css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2442
2443 sendEvent(nNewLastPara, m_nSelectionLastPara, ::css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2444 }
2445 break;
2446 default:
2447 break;
2448 }
2449
2450 /*
2451 // Update both old and new selection. (Regardless of how the two selections
2452 // look like, there will always be two ranges to the left and right of the
2453 // overlap---the overlap and/or the range to the right of it possibly being
2454 // empty. Only for these two ranges notifications have to be sent.)
2455
2456 TextPaM aOldTextStart( static_cast< sal_uLong >( m_nSelectionFirstPara ), static_cast< sal_uInt16 >( m_nSelectionFirstPos ) );
2457 TextPaM aOldTextEnd( static_cast< sal_uLong >( m_nSelectionLastPara ), static_cast< sal_uInt16 >( m_nSelectionLastPos ) );
2458 TextPaM aNewTextStart( static_cast< sal_uLong >( nNewFirstPara ), static_cast< sal_uInt16 >( nNewFirstPos ) );
2459 TextPaM aNewTextEnd( static_cast< sal_uLong >( nNewLastPara ), static_cast< sal_uInt16 >( nNewLastPos ) );
2460
2461 // justify selections
2462 justifySelection( aOldTextStart, aOldTextEnd );
2463 justifySelection( aNewTextStart, aNewTextEnd );
2464
2465 sal_Int32 nFirst1;
2466 sal_Int32 nLast1;
2467 sal_Int32 nFirst2;
2468 sal_Int32 nLast2;
2469
2470 if ( m_nSelectionFirstPara == -1 )
2471 {
2472 // old selection not initialized yet => notify events only for new selection (if not empty)
2473 nFirst1 = aNewTextStart.GetPara();
2474 nLast1 = aNewTextEnd.GetPara() + ( aNewTextStart != aNewTextEnd ? 1 : 0 );
2475 nFirst2 = 0;
2476 nLast2 = 0;
2477 }
2478 else if ( aOldTextStart == aOldTextEnd && aNewTextStart == aNewTextEnd )
2479 {
2480 // old an new selection empty => no events
2481 nFirst1 = 0;
2482 nLast1 = 0;
2483 nFirst2 = 0;
2484 nLast2 = 0;
2485 }
2486 else if ( aOldTextStart != aOldTextEnd && aNewTextStart == aNewTextEnd )
2487 {
2488 // old selection not empty + new selection empty => notify events only for old selection
2489 nFirst1 = aOldTextStart.GetPara();
2490 nLast1 = aOldTextEnd.GetPara() + 1;
2491 nFirst2 = 0;
2492 nLast2 = 0;
2493 }
2494 else if ( aOldTextStart == aOldTextEnd && aNewTextStart != aNewTextEnd )
2495 {
2496 // old selection empty + new selection not empty => notify events only for new selection
2497 nFirst1 = aNewTextStart.GetPara();
2498 nLast1 = aNewTextEnd.GetPara() + 1;
2499 nFirst2 = 0;
2500 nLast2 = 0;
2501 }
2502 else
2503 {
2504 // old and new selection not empty => notify events for the two ranges left and right of the overlap
2505 ::std::vector< TextPaM > aTextPaMs(4);
2506 aTextPaMs[0] = aOldTextStart;
2507 aTextPaMs[1] = aOldTextEnd;
2508 aTextPaMs[2] = aNewTextStart;
2509 aTextPaMs[3] = aNewTextEnd;
2510 ::std::sort( aTextPaMs.begin(), aTextPaMs.end() );
2511
2512 nFirst1 = aTextPaMs[0].GetPara();
2513 nLast1 = aTextPaMs[1].GetPara() + ( aTextPaMs[0] != aTextPaMs[1] ? 1 : 0 );
2514
2515 nFirst2 = aTextPaMs[2].GetPara();
2516 nLast2 = aTextPaMs[3].GetPara() + ( aTextPaMs[2] != aTextPaMs[3] ? 1 : 0 );
2517
2518 // adjust overlapping ranges
2519 if ( nLast1 > nFirst2 )
2520 nLast1 = nFirst2;
2521 }
2522
2523 // notify selection changes
2524 notifySelectionChange( nFirst1, nLast1 );
2525 notifySelectionChange( nFirst2, nLast2 );
2526 */
2527 m_nSelectionFirstPara = nNewFirstPara;
2528 m_nSelectionFirstPos = nNewFirstPos;
2529 m_nSelectionLastPara = nNewLastPara;
2530 m_nSelectionLastPos = nNewLastPos;
2531 }
2532
notifySelectionChange(sal_Int32 nFirst,sal_Int32 nLast)2533 void Document::notifySelectionChange( sal_Int32 nFirst, sal_Int32 nLast )
2534 {
2535 if ( nFirst < nLast )
2536 {
2537 Paragraphs::iterator aEnd( ::std::min( m_xParagraphs->begin() + nLast, m_aVisibleEnd ) );
2538 for ( Paragraphs::iterator aIt = ::std::max( m_xParagraphs->begin() + nFirst, m_aVisibleBegin ); aIt < aEnd; ++aIt )
2539 {
2540 ::rtl::Reference< ParagraphImpl > xParagraph( getParagraph( aIt ) );
2541 if ( xParagraph.is() )
2542 {
2543 xParagraph->notifyEvent(
2544 ::css::accessibility::AccessibleEventId::SELECTION_CHANGED,
2545 ::css::uno::Any(), ::css::uno::Any() );
2546 xParagraph->notifyEvent(
2547 ::css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED,
2548 ::css::uno::Any(), ::css::uno::Any() );
2549 }
2550 }
2551 }
2552 }
2553
justifySelection(TextPaM & rTextStart,TextPaM & rTextEnd)2554 void Document::justifySelection( TextPaM& rTextStart, TextPaM& rTextEnd )
2555 {
2556 if ( rTextStart > rTextEnd )
2557 {
2558 TextPaM aTextPaM( rTextStart );
2559 rTextStart = rTextEnd;
2560 rTextEnd = aTextPaM;
2561 }
2562 }
2563
disposeParagraphs()2564 void Document::disposeParagraphs()
2565 {
2566 for (Paragraphs::iterator aIt(m_xParagraphs->begin());
2567 aIt != m_xParagraphs->end(); ++aIt)
2568 {
2569 ::css::uno::Reference< ::css::lang::XComponent > xComponent(
2570 aIt->getParagraph().get(), ::css::uno::UNO_QUERY);
2571 if (xComponent.is())
2572 xComponent->dispose();
2573 }
2574 }
2575
2576 // static
mapFontColor(::Color const & rColor)2577 ::css::uno::Any Document::mapFontColor(::Color const & rColor)
2578 {
2579 return ::css::uno::makeAny(
2580 static_cast< ::sal_Int32 >(COLORDATA_RGB(rColor.GetColor())));
2581 // FIXME keep transparency?
2582 }
2583
2584 // static
mapFontColor(::css::uno::Any const & rColor)2585 ::Color Document::mapFontColor(::css::uno::Any const & rColor)
2586 {
2587 ::sal_Int32 nColor = 0;
2588 rColor >>= nColor;
2589 return ::Color(static_cast< ::ColorData >(nColor));
2590 }
2591
2592 // static
mapFontWeight(::FontWeight nWeight)2593 ::css::uno::Any Document::mapFontWeight(::FontWeight nWeight)
2594 {
2595 // Map from ::FontWeight to ::css:awt::FontWeight, depends on order of
2596 // elements in ::FontWeight (vcl/vclenum.hxx):
2597 static float const aWeight[]
2598 = { ::css::awt::FontWeight::DONTKNOW, // WEIGHT_DONTKNOW
2599 ::css::awt::FontWeight::THIN, // WEIGHT_THIN
2600 ::css::awt::FontWeight::ULTRALIGHT, // WEIGHT_ULTRALIGHT
2601 ::css::awt::FontWeight::LIGHT, // WEIGHT_LIGHT
2602 ::css::awt::FontWeight::SEMILIGHT, // WEIGHT_SEMILIGHT
2603 ::css::awt::FontWeight::NORMAL, // WEIGHT_NORMAL
2604 ::css::awt::FontWeight::NORMAL, // WEIGHT_MEDIUM
2605 ::css::awt::FontWeight::SEMIBOLD, // WEIGHT_SEMIBOLD
2606 ::css::awt::FontWeight::BOLD, // WEIGHT_BOLD
2607 ::css::awt::FontWeight::ULTRABOLD, // WEIGHT_ULTRABOLD
2608 ::css::awt::FontWeight::BLACK }; // WEIGHT_BLACK
2609 return ::css::uno::makeAny(aWeight[nWeight]);
2610 }
2611
2612 // static
mapFontWeight(::css::uno::Any const & rWeight)2613 ::FontWeight Document::mapFontWeight(::css::uno::Any const & rWeight)
2614 {
2615 float nWeight = ::css::awt::FontWeight::NORMAL;
2616 rWeight >>= nWeight;
2617 return nWeight <= ::css::awt::FontWeight::DONTKNOW ? WEIGHT_DONTKNOW
2618 : nWeight <= ::css::awt::FontWeight::THIN ? WEIGHT_THIN
2619 : nWeight <= ::css::awt::FontWeight::ULTRALIGHT ? WEIGHT_ULTRALIGHT
2620 : nWeight <= ::css::awt::FontWeight::LIGHT ? WEIGHT_LIGHT
2621 : nWeight <= ::css::awt::FontWeight::SEMILIGHT ? WEIGHT_SEMILIGHT
2622 : nWeight <= ::css::awt::FontWeight::NORMAL ? WEIGHT_NORMAL
2623 : nWeight <= ::css::awt::FontWeight::SEMIBOLD ? WEIGHT_SEMIBOLD
2624 : nWeight <= ::css::awt::FontWeight::BOLD ? WEIGHT_BOLD
2625 : nWeight <= ::css::awt::FontWeight::ULTRABOLD ? WEIGHT_ULTRABOLD
2626 : WEIGHT_BLACK;
2627 }
2628
2629 }
2630
2631