Branch libreoffice-5-0-4
[LibreOffice.git] / accessibility / source / extended / textwindowaccessibility.cxx
blob1a391ce13f04948deb4e355282ece2431fdb7e6e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <accessibility/extended/textwindowaccessibility.hxx>
21 #include <comphelper/accessibleeventnotifier.hxx>
22 #include <unotools/accessiblerelationsethelper.hxx>
23 #include <unotools/accessiblestatesethelper.hxx>
24 #include <vcl/window.hxx>
25 #include <toolkit/helper/convert.hxx>
27 #include <algorithm>
28 #include <vector>
30 namespace accessibility
32 void SfxListenerGuard::startListening(::SfxBroadcaster & rNotifier)
34 OSL_ENSURE(m_pNotifier == 0, "called more than once");
35 m_pNotifier = &rNotifier;
36 m_rListener.StartListening(*m_pNotifier, true);
39 void SfxListenerGuard::endListening()
41 if (m_pNotifier != 0)
43 m_rListener.EndListening(*m_pNotifier);
44 m_pNotifier = 0;
48 void WindowListenerGuard::startListening(vcl::Window & rNotifier)
50 OSL_ENSURE(m_pNotifier == nullptr, "called more than once");
51 m_pNotifier = &rNotifier;
52 m_pNotifier->AddEventListener(m_aListener);
55 void WindowListenerGuard::endListening()
57 if (m_pNotifier)
59 m_pNotifier->RemoveEventListener(m_aListener);
60 m_pNotifier = nullptr;
64 Paragraph::Paragraph(::rtl::Reference< Document > const & rDocument,
65 Paragraphs::size_type nNumber):
66 ParagraphBase(m_aMutex),
67 m_xDocument(rDocument),
68 m_nNumber(nNumber),
69 m_nClientId(0)
71 m_aParagraphText = m_xDocument->retrieveParagraphText(this);
74 void
75 Paragraph::numberChanged(bool bIncremented)
77 if (bIncremented)
78 ++m_nNumber;
79 else
80 --m_nNumber;
83 void Paragraph::textChanged()
85 OUString aParagraphText = implGetText();
86 css::uno::Any aOldValue, aNewValue;
87 if ( implInitTextChangedEvent( m_aParagraphText, aParagraphText, aOldValue, aNewValue ) )
89 m_aParagraphText = aParagraphText;
90 notifyEvent(css::accessibility::AccessibleEventId::
91 TEXT_CHANGED,
92 aOldValue, aNewValue);
96 void Paragraph::notifyEvent(::sal_Int16 nEventId,
97 css::uno::Any const & rOldValue,
98 css::uno::Any const & rNewValue)
100 if (m_nClientId)
101 comphelper::AccessibleEventNotifier::addEvent( m_nClientId, css::accessibility::AccessibleEventObject(
102 static_cast< ::cppu::OWeakObject * >(this),
103 nEventId, rNewValue, rOldValue) );
106 // virtual
107 css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL
108 Paragraph::getAccessibleContext() throw (css::uno::RuntimeException, std::exception)
110 checkDisposed();
111 return this;
114 // virtual
115 ::sal_Int32 SAL_CALL Paragraph::getAccessibleChildCount()
116 throw (css::uno::RuntimeException, std::exception)
118 checkDisposed();
119 return 0;
122 // virtual
123 css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
124 Paragraph::getAccessibleChild(::sal_Int32)
125 throw (css::lang::IndexOutOfBoundsException,
126 css::uno::RuntimeException, std::exception)
128 checkDisposed();
129 throw css::lang::IndexOutOfBoundsException(
130 "textwindowaccessibility.cxx:"
131 " Paragraph::getAccessibleChild",
132 static_cast< css::uno::XWeak * >(this));
135 // virtual
136 css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
137 Paragraph::getAccessibleParent()
138 throw (css::uno::RuntimeException, std::exception)
140 checkDisposed();
141 return m_xDocument->getAccessible();
144 // virtual
145 ::sal_Int32 SAL_CALL Paragraph::getAccessibleIndexInParent()
146 throw (css::uno::RuntimeException, std::exception)
148 checkDisposed();
149 return m_xDocument->retrieveParagraphIndex(this);
152 // virtual
153 ::sal_Int16 SAL_CALL Paragraph::getAccessibleRole()
154 throw (css::uno::RuntimeException, std::exception)
156 checkDisposed();
157 return css::accessibility::AccessibleRole::PARAGRAPH;
160 // virtual
161 OUString SAL_CALL Paragraph::getAccessibleDescription()
162 throw (css::uno::RuntimeException, std::exception)
164 checkDisposed();
165 return OUString();
168 // virtual
169 OUString SAL_CALL Paragraph::getAccessibleName()
170 throw (css::uno::RuntimeException, std::exception)
172 checkDisposed();
173 return OUString();
176 // virtual
177 css::uno::Reference< css::accessibility::XAccessibleRelationSet >
178 SAL_CALL Paragraph::getAccessibleRelationSet()
179 throw (css::uno::RuntimeException, std::exception)
181 checkDisposed();
182 return m_xDocument->retrieveParagraphRelationSet( this );
185 // virtual
186 css::uno::Reference< css::accessibility::XAccessibleStateSet >
187 SAL_CALL Paragraph::getAccessibleStateSet()
188 throw (css::uno::RuntimeException, std::exception)
190 checkDisposed();
192 // FIXME Notification of changes (STATE_CHANGED) missing when
193 // m_rView.IsReadOnly() changes:
194 return new ::utl::AccessibleStateSetHelper(
195 m_xDocument->retrieveParagraphState(this));
198 // virtual
199 css::lang::Locale SAL_CALL Paragraph::getLocale()
200 throw (css::accessibility::IllegalAccessibleComponentStateException,
201 css::uno::RuntimeException, std::exception)
203 checkDisposed();
204 return m_xDocument->retrieveLocale();
207 // virtual
208 sal_Bool SAL_CALL Paragraph::containsPoint(css::awt::Point const & rPoint)
209 throw (css::uno::RuntimeException, std::exception)
211 checkDisposed();
212 css::awt::Rectangle aRect(m_xDocument->retrieveParagraphBounds(this,
213 false));
214 return rPoint.X >= 0 && rPoint.X < aRect.Width
215 && rPoint.Y >= 0 && rPoint.Y < aRect.Height;
218 // virtual
219 css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
220 Paragraph::getAccessibleAtPoint(css::awt::Point const &)
221 throw (css::uno::RuntimeException, std::exception)
223 checkDisposed();
224 return 0;
227 // virtual
228 css::awt::Rectangle SAL_CALL Paragraph::getBounds()
229 throw (css::uno::RuntimeException, std::exception)
231 checkDisposed();
232 return m_xDocument->retrieveParagraphBounds(this, false);
235 // virtual
236 css::awt::Point SAL_CALL Paragraph::getLocation()
237 throw (css::uno::RuntimeException, std::exception)
239 checkDisposed();
240 css::awt::Rectangle aRect(m_xDocument->retrieveParagraphBounds(this,
241 false));
242 return css::awt::Point(aRect.X, aRect.Y);
245 // virtual
246 css::awt::Point SAL_CALL Paragraph::getLocationOnScreen()
247 throw (css::uno::RuntimeException, std::exception)
249 checkDisposed();
250 css::awt::Rectangle aRect(m_xDocument->retrieveParagraphBounds(this,
251 true));
252 return css::awt::Point(aRect.X, aRect.Y);
255 // virtual
256 css::awt::Size SAL_CALL Paragraph::getSize()
257 throw (css::uno::RuntimeException, std::exception)
259 checkDisposed();
260 css::awt::Rectangle aRect(m_xDocument->retrieveParagraphBounds(this,
261 false));
262 return css::awt::Size(aRect.Width, aRect.Height);
265 // virtual
266 void SAL_CALL Paragraph::grabFocus() throw (css::uno::RuntimeException, std::exception)
268 checkDisposed();
269 vcl::Window* pWindow = m_xDocument->GetWindow();
270 if ( pWindow )
272 pWindow->GrabFocus();
276 m_xDocument->changeParagraphSelection(this, 0, 0);
278 catch (const css::lang::IndexOutOfBoundsException & rEx)
280 OSL_TRACE(
281 "textwindowaccessibility.cxx: Paragraph::grabFocus:"
282 " caught unexpected %s\n",
283 OUStringToOString(rEx.Message, RTL_TEXTENCODING_UTF8).
284 getStr());
288 // virtual
289 css::util::Color SAL_CALL Paragraph::getForeground()
290 throw (css::uno::RuntimeException, std::exception)
292 return 0; // TODO
295 // virtual
296 css::util::Color SAL_CALL Paragraph::getBackground()
297 throw (css::uno::RuntimeException, std::exception)
299 return 0; // TODO
302 // virtual
303 ::sal_Int32 SAL_CALL Paragraph::getCaretPosition()
304 throw (css::uno::RuntimeException, std::exception)
306 checkDisposed();
307 return m_xDocument->retrieveParagraphCaretPosition(this);
310 // virtual
311 sal_Bool SAL_CALL Paragraph::setCaretPosition(::sal_Int32 nIndex)
312 throw (css::lang::IndexOutOfBoundsException,
313 css::uno::RuntimeException, std::exception)
315 checkDisposed();
316 m_xDocument->changeParagraphSelection(this, nIndex, nIndex);
317 return true;
320 // virtual
321 ::sal_Unicode SAL_CALL Paragraph::getCharacter(::sal_Int32 nIndex)
322 throw (css::lang::IndexOutOfBoundsException,
323 css::uno::RuntimeException, std::exception)
325 checkDisposed();
326 return OCommonAccessibleText::getCharacter(nIndex);
329 // virtual
330 css::uno::Sequence< css::beans::PropertyValue > SAL_CALL
331 Paragraph::getCharacterAttributes(::sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< OUString >& aRequestedAttributes)
332 throw (css::lang::IndexOutOfBoundsException,
333 css::uno::RuntimeException, std::exception)
335 checkDisposed();
336 return m_xDocument->retrieveCharacterAttributes( this, nIndex, aRequestedAttributes );
339 // virtual
340 css::awt::Rectangle SAL_CALL
341 Paragraph::getCharacterBounds(::sal_Int32 nIndex)
342 throw (css::lang::IndexOutOfBoundsException,
343 css::uno::RuntimeException, std::exception)
345 checkDisposed();
346 css::awt::Rectangle aBounds(m_xDocument->retrieveCharacterBounds(this, nIndex));
347 css::awt::Rectangle aParaBounds(m_xDocument->retrieveParagraphBounds(this, false));
348 aBounds.X -= aParaBounds.X;
349 aBounds.Y -= aParaBounds.Y;
350 return aBounds;
353 // virtual
354 ::sal_Int32 SAL_CALL Paragraph::getCharacterCount()
355 throw (css::uno::RuntimeException, std::exception)
357 checkDisposed();
358 return OCommonAccessibleText::getCharacterCount();
361 // virtual
362 ::sal_Int32 SAL_CALL
363 Paragraph::getIndexAtPoint(css::awt::Point const & rPoint)
364 throw (css::uno::RuntimeException, std::exception)
366 checkDisposed();
367 css::awt::Point aPoint(rPoint);
368 css::awt::Rectangle aParaBounds(m_xDocument->retrieveParagraphBounds(this, false));
369 aPoint.X += aParaBounds.X;
370 aPoint.Y += aParaBounds.Y;
371 return m_xDocument->retrieveCharacterIndex(this, aPoint);
374 // virtual
375 OUString SAL_CALL Paragraph::getSelectedText()
376 throw (css::uno::RuntimeException, std::exception)
378 checkDisposed();
380 return OCommonAccessibleText::getSelectedText();
383 // virtual
384 ::sal_Int32 SAL_CALL Paragraph::getSelectionStart()
385 throw (css::uno::RuntimeException, std::exception)
387 checkDisposed();
388 return OCommonAccessibleText::getSelectionStart();
391 // virtual
392 ::sal_Int32 SAL_CALL Paragraph::getSelectionEnd()
393 throw (css::uno::RuntimeException, std::exception)
395 checkDisposed();
396 return OCommonAccessibleText::getSelectionEnd();
399 // virtual
400 sal_Bool SAL_CALL Paragraph::setSelection(::sal_Int32 nStartIndex,
401 ::sal_Int32 nEndIndex)
402 throw (css::lang::IndexOutOfBoundsException,
403 css::uno::RuntimeException, std::exception)
405 checkDisposed();
406 m_xDocument->changeParagraphSelection(this, nStartIndex, nEndIndex);
407 return true;
410 // virtual
411 OUString SAL_CALL Paragraph::getText()
412 throw (css::uno::RuntimeException, std::exception)
414 checkDisposed();
415 return OCommonAccessibleText::getText();
418 // virtual
419 OUString SAL_CALL Paragraph::getTextRange(::sal_Int32 nStartIndex,
420 ::sal_Int32 nEndIndex)
421 throw (css::lang::IndexOutOfBoundsException,
422 css::uno::RuntimeException, std::exception)
424 checkDisposed();
425 return OCommonAccessibleText::getTextRange(nStartIndex, nEndIndex);
428 // virtual
429 ::com::sun::star::accessibility::TextSegment SAL_CALL Paragraph::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
431 checkDisposed();
432 return OCommonAccessibleText::getTextAtIndex(nIndex, aTextType);
435 // virtual
436 ::com::sun::star::accessibility::TextSegment SAL_CALL Paragraph::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
438 checkDisposed();
439 return OCommonAccessibleText::getTextBeforeIndex(nIndex, aTextType);
442 // virtual
443 ::com::sun::star::accessibility::TextSegment SAL_CALL Paragraph::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
445 checkDisposed();
446 return OCommonAccessibleText::getTextBehindIndex(nIndex, aTextType);
449 // virtual
450 sal_Bool SAL_CALL Paragraph::copyText(::sal_Int32 nStartIndex,
451 ::sal_Int32 nEndIndex)
452 throw (css::lang::IndexOutOfBoundsException,
453 css::uno::RuntimeException, std::exception)
455 checkDisposed();
456 m_xDocument->copyParagraphText(this, nStartIndex, nEndIndex);
457 return true;
460 // virtual
461 sal_Bool SAL_CALL Paragraph::cutText(::sal_Int32 nStartIndex,
462 ::sal_Int32 nEndIndex)
463 throw (css::lang::IndexOutOfBoundsException,
464 css::uno::RuntimeException, std::exception)
466 checkDisposed();
467 m_xDocument->changeParagraphText(this, nStartIndex, nEndIndex, true, false,
468 OUString());
469 return true;
472 // virtual
473 sal_Bool SAL_CALL Paragraph::pasteText(::sal_Int32 nIndex)
474 throw (css::lang::IndexOutOfBoundsException,
475 css::uno::RuntimeException, std::exception)
477 checkDisposed();
478 m_xDocument->changeParagraphText(this, nIndex, nIndex, false, true,
479 OUString());
480 return true;
483 // virtual
484 sal_Bool SAL_CALL Paragraph::deleteText(::sal_Int32 nStartIndex,
485 ::sal_Int32 nEndIndex)
486 throw (css::lang::IndexOutOfBoundsException,
487 css::uno::RuntimeException, std::exception)
489 checkDisposed();
490 m_xDocument->changeParagraphText(this, nStartIndex, nEndIndex, false, false,
491 OUString());
492 return true;
495 // virtual
496 sal_Bool SAL_CALL Paragraph::insertText(OUString const & rText,
497 ::sal_Int32 nIndex)
498 throw (css::lang::IndexOutOfBoundsException,
499 css::uno::RuntimeException, std::exception)
501 checkDisposed();
502 m_xDocument->changeParagraphText(this, nIndex, nIndex, false, false, rText);
503 return true;
506 // virtual
507 sal_Bool SAL_CALL
508 Paragraph::replaceText(::sal_Int32 nStartIndex, ::sal_Int32 nEndIndex,
509 OUString const & rReplacement)
510 throw (css::lang::IndexOutOfBoundsException,
511 css::uno::RuntimeException, std::exception)
513 checkDisposed();
514 m_xDocument->changeParagraphText(this, nStartIndex, nEndIndex, false, false,
515 rReplacement);
516 return true;
519 // virtual
520 sal_Bool SAL_CALL Paragraph::setAttributes(
521 ::sal_Int32 nStartIndex, ::sal_Int32 nEndIndex,
522 css::uno::Sequence< css::beans::PropertyValue > const & rAttributeSet)
523 throw (css::lang::IndexOutOfBoundsException,
524 css::uno::RuntimeException, std::exception)
526 checkDisposed();
527 m_xDocument->changeParagraphAttributes(this, nStartIndex, nEndIndex,
528 rAttributeSet);
529 return true;
532 // virtual
533 sal_Bool SAL_CALL Paragraph::setText(OUString const & rText)
534 throw (css::uno::RuntimeException, std::exception)
536 checkDisposed();
537 m_xDocument->changeParagraphText(this, rText);
538 return true;
541 // virtual
542 css::uno::Sequence< css::beans::PropertyValue > SAL_CALL
543 Paragraph::getDefaultAttributes(const css::uno::Sequence< OUString >& RequestedAttributes)
544 throw (css::uno::RuntimeException, std::exception)
546 checkDisposed();
547 return m_xDocument->retrieveDefaultAttributes( this, RequestedAttributes );
550 // virtual
551 css::uno::Sequence< css::beans::PropertyValue > SAL_CALL
552 Paragraph::getRunAttributes(::sal_Int32 Index, const css::uno::Sequence< OUString >& RequestedAttributes)
553 throw (css::lang::IndexOutOfBoundsException,
554 css::uno::RuntimeException, std::exception)
556 checkDisposed();
557 return m_xDocument->retrieveRunAttributes( this, Index, RequestedAttributes );
560 // virtual
561 ::sal_Int32 SAL_CALL Paragraph::getLineNumberAtIndex( ::sal_Int32 nIndex )
562 throw (css::lang::IndexOutOfBoundsException,
563 css::uno::RuntimeException, std::exception)
565 checkDisposed();
567 ::sal_Int32 nLineNo = -1;
568 m_xDocument->retrieveParagraphLineBoundary( this, nIndex, &nLineNo );
570 return nLineNo;
573 // virtual
574 css::accessibility::TextSegment SAL_CALL Paragraph::getTextAtLineNumber( ::sal_Int32 nLineNo )
575 throw (css::lang::IndexOutOfBoundsException,
576 css::uno::RuntimeException, std::exception)
578 checkDisposed();
580 css::i18n::Boundary aBoundary =
581 m_xDocument->retrieveParagraphBoundaryOfLine( this, nLineNo );
583 return css::accessibility::TextSegment( getTextRange(aBoundary.startPos, aBoundary.endPos),
584 aBoundary.startPos, aBoundary.endPos);
587 // virtual
588 css::accessibility::TextSegment SAL_CALL Paragraph::getTextAtLineWithCaret( )
589 throw (css::uno::RuntimeException, std::exception)
591 checkDisposed();
593 sal_Int32 nLineNo = getNumberOfLineWithCaret();
595 try {
596 return ( nLineNo >= 0 ) ?
597 getTextAtLineNumber( nLineNo ) :
598 css::accessibility::TextSegment();
599 } catch (const css::lang::IndexOutOfBoundsException&) {
600 throw css::uno::RuntimeException(
601 "textwindowaccessibility.cxx:"
602 " Paragraph::getTextAtLineWithCaret",
603 static_cast< css::uno::XWeak * >( this ) );
607 // virtual
608 ::sal_Int32 SAL_CALL Paragraph::getNumberOfLineWithCaret( )
609 throw (css::uno::RuntimeException, std::exception)
611 checkDisposed();
612 return m_xDocument->retrieveParagraphLineWithCursor(this);
616 // virtual
617 void SAL_CALL Paragraph::addAccessibleEventListener(
618 css::uno::Reference<
619 css::accessibility::XAccessibleEventListener > const & rListener)
620 throw (css::uno::RuntimeException, std::exception)
622 if (rListener.is())
624 ::osl::ClearableMutexGuard aGuard(rBHelper.rMutex);
625 if (rBHelper.bDisposed || rBHelper.bInDispose)
627 aGuard.clear();
628 rListener->disposing(css::lang::EventObject(
629 static_cast< ::cppu::OWeakObject * >(this)));
631 else
633 if (!m_nClientId)
634 m_nClientId = comphelper::AccessibleEventNotifier::registerClient( );
635 comphelper::AccessibleEventNotifier::addEventListener( m_nClientId, rListener );
640 // virtual
641 void SAL_CALL Paragraph::removeAccessibleEventListener(
642 css::uno::Reference<
643 css::accessibility::XAccessibleEventListener > const & rListener)
644 throw (css::uno::RuntimeException, std::exception)
646 comphelper::AccessibleEventNotifier::TClientId nId = 0;
648 ::osl::ClearableMutexGuard aGuard(rBHelper.rMutex);
649 if (rListener.is() && m_nClientId != 0
650 && comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId, rListener ) == 0)
652 nId = m_nClientId;
653 m_nClientId = 0;
656 if (nId != 0)
658 // no listeners anymore
659 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
660 // and at least to us not firing any events anymore, in case somebody calls
661 // NotifyAccessibleEvent, again
662 comphelper::AccessibleEventNotifier::revokeClient(nId);
666 // virtual
667 void SAL_CALL Paragraph::disposing()
669 comphelper::AccessibleEventNotifier::TClientId nId = 0;
671 ::osl::ClearableMutexGuard aGuard(rBHelper.rMutex);
672 nId = m_nClientId;
673 m_nClientId = 0;
675 if (nId != 0)
676 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing(nId, *this);
679 // virtual
680 OUString Paragraph::implGetText()
682 return m_xDocument->retrieveParagraphText(this);
685 // virtual
686 css::lang::Locale Paragraph::implGetLocale()
688 return m_xDocument->retrieveLocale();
691 // virtual
692 void Paragraph::implGetSelection(::sal_Int32 & rStartIndex,
693 ::sal_Int32 & rEndIndex)
695 m_xDocument->retrieveParagraphSelection(this, &rStartIndex, &rEndIndex);
698 // virtual
699 void Paragraph::implGetParagraphBoundary( css::i18n::Boundary& rBoundary,
700 ::sal_Int32 nIndex )
702 OUString sText( implGetText() );
703 ::sal_Int32 nLength = sText.getLength();
705 if ( implIsValidIndex( nIndex, nLength ) )
707 rBoundary.startPos = 0;
708 rBoundary.endPos = nLength;
710 else
712 rBoundary.startPos = nIndex;
713 rBoundary.endPos = nIndex;
717 // virtual
718 void Paragraph::implGetLineBoundary( css::i18n::Boundary& rBoundary,
719 ::sal_Int32 nIndex )
721 OUString sText( implGetText() );
722 ::sal_Int32 nLength = sText.getLength();
724 if ( implIsValidIndex( nIndex, nLength ) || nIndex == nLength )
726 css::i18n::Boundary aBoundary =
727 m_xDocument->retrieveParagraphLineBoundary( this, nIndex );
728 rBoundary.startPos = aBoundary.startPos;
729 rBoundary.endPos = aBoundary.endPos;
731 else
733 rBoundary.startPos = nIndex;
734 rBoundary.endPos = nIndex;
739 void Paragraph::checkDisposed()
741 ::osl::MutexGuard aGuard(rBHelper.rMutex);
742 if (!(rBHelper.bDisposed || rBHelper.bInDispose))
743 return;
744 throw css::lang::DisposedException(
745 OUString(), static_cast< css::uno::XWeak * >(this));
748 Document::Document(::VCLXWindow * pVclXWindow, ::TextEngine & rEngine,
749 ::TextView & rView):
750 VCLXAccessibleComponent(pVclXWindow),
751 m_xAccessible(pVclXWindow),
752 m_rEngine(rEngine),
753 m_rView(rView),
754 m_aEngineListener(*this),
755 m_aViewListener(LINK(this, Document, WindowEventHandler)),
756 m_nViewOffset(0),
757 m_nViewHeight(0),
758 m_nVisibleBeginOffset(0),
759 m_nSelectionFirstPara(-1),
760 m_nSelectionFirstPos(-1),
761 m_nSelectionLastPara(-1),
762 m_nSelectionLastPos(-1),
763 m_bSelectionChangedNotification(false)
766 css::lang::Locale Document::retrieveLocale()
768 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
769 return m_rEngine.GetLocale();
772 ::sal_Int32 Document::retrieveParagraphIndex(Paragraph const * pParagraph)
774 ::osl::MutexGuard aInternalGuard(GetMutex());
776 // If a client holds on to a Paragraph that is no longer visible, it can
777 // happen that this Paragraph lies outside the range from m_aVisibleBegin
778 // to m_aVisibleEnd. In that case, return -1 instead of a valid index:
779 Paragraphs::iterator aPara(m_xParagraphs->begin()
780 + pParagraph->getNumber());
781 return aPara < m_aVisibleBegin || aPara >= m_aVisibleEnd
782 ? -1 : static_cast< ::sal_Int32 >(aPara - m_aVisibleBegin);
783 // XXX numeric overflow
786 ::sal_Int64 Document::retrieveParagraphState(Paragraph const * pParagraph)
788 ::osl::MutexGuard aInternalGuard(GetMutex());
790 // If a client holds on to a Paragraph that is no longer visible, it can
791 // happen that this Paragraph lies outside the range from m_aVisibleBegin
792 // to m_aVisibleEnd. In that case, it is neither VISIBLE nor SHOWING:
793 ::sal_Int64 nState
794 = (static_cast< ::sal_Int64 >(1)
795 << css::accessibility::AccessibleStateType::ENABLED)
796 | (static_cast< ::sal_Int64 >(1)
797 << css::accessibility::AccessibleStateType::SENSITIVE)
798 | (static_cast< ::sal_Int64 >(1)
799 << css::accessibility::AccessibleStateType::FOCUSABLE)
800 | (static_cast< ::sal_Int64 >(1)
801 << css::accessibility::AccessibleStateType::MULTI_LINE);
802 if (!m_rView.IsReadOnly())
803 nState |= (static_cast< ::sal_Int64 >(1)
804 << css::accessibility::AccessibleStateType::EDITABLE);
805 Paragraphs::iterator aPara(m_xParagraphs->begin()
806 + pParagraph->getNumber());
807 if (aPara >= m_aVisibleBegin && aPara < m_aVisibleEnd)
809 nState
810 |= (static_cast< ::sal_Int64 >(1)
811 << css::accessibility::AccessibleStateType::VISIBLE)
812 | (static_cast< ::sal_Int64 >(1)
813 << css::accessibility::AccessibleStateType::SHOWING);
814 if (aPara == m_aFocused)
815 nState |= (static_cast< ::sal_Int64 >(1)
816 << css::accessibility::AccessibleStateType::FOCUSED);
818 return nState;
821 css::awt::Rectangle
822 Document::retrieveParagraphBounds(Paragraph const * pParagraph,
823 bool bAbsolute)
825 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
826 ::osl::MutexGuard aInternalGuard(GetMutex());
828 // If a client holds on to a Paragraph that is no longer visible (as it
829 // scrolled out the top of the view), it can happen that this Paragraph
830 // lies before m_aVisibleBegin. In that case, calculate the vertical
831 // position of the Paragraph starting at paragraph 0, otherwise optimize
832 // and start at m_aVisibleBegin:
833 Paragraphs::iterator aPara(m_xParagraphs->begin()
834 + pParagraph->getNumber());
835 ::sal_Int32 nPos;
836 Paragraphs::iterator aIt;
837 if (aPara < m_aVisibleBegin)
839 nPos = 0;
840 aIt = m_xParagraphs->begin();
842 else
844 nPos = m_nViewOffset - m_nVisibleBeginOffset;
845 aIt = m_aVisibleBegin;
847 for (; aIt != aPara; ++aIt)
848 nPos += aIt->getHeight();
850 Point aOrig(0, 0);
851 if (bAbsolute)
852 aOrig = m_rView.GetWindow()->OutputToAbsoluteScreenPixel(aOrig);
854 return css::awt::Rectangle(
855 static_cast< ::sal_Int32 >(aOrig.X()),
856 static_cast< ::sal_Int32 >(aOrig.Y()) + nPos - m_nViewOffset,
857 m_rView.GetWindow()->GetOutputSizePixel().Width(), aPara->getHeight());
858 // XXX numeric overflow (3x)
861 OUString
862 Document::retrieveParagraphText(Paragraph const * pParagraph)
864 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
865 ::osl::MutexGuard aInternalGuard(GetMutex());
866 return m_rEngine.GetText(static_cast< ::sal_uLong >(pParagraph->getNumber()));
867 // numeric overflow cannot happen here
870 void Document::retrieveParagraphSelection(Paragraph const * pParagraph,
871 ::sal_Int32 * pBegin,
872 ::sal_Int32 * pEnd)
874 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
875 ::osl::MutexGuard aInternalGuard(GetMutex());
876 ::TextSelection const & rSelection = m_rView.GetSelection();
877 Paragraphs::size_type nNumber = pParagraph->getNumber();
878 TextPaM aStartPaM( rSelection.GetStart() );
879 TextPaM aEndPaM( rSelection.GetEnd() );
880 TextPaM aMinPaM( ::std::min( aStartPaM, aEndPaM ) );
881 TextPaM aMaxPaM( ::std::max( aStartPaM, aEndPaM ) );
883 if ( nNumber >= aMinPaM.GetPara() && nNumber <= aMaxPaM.GetPara() )
885 *pBegin = nNumber > aMinPaM.GetPara()
887 : static_cast< ::sal_Int32 >( aMinPaM.GetIndex() );
888 // XXX numeric overflow
889 *pEnd = nNumber < aMaxPaM.GetPara()
890 ? static_cast< ::sal_Int32 >( m_rEngine.GetText(static_cast< ::sal_uLong >(nNumber)).getLength() )
891 : static_cast< ::sal_Int32 >( aMaxPaM.GetIndex() );
892 // XXX numeric overflow (3x)
894 if ( aStartPaM > aEndPaM )
895 ::std::swap( *pBegin, *pEnd );
897 else
899 *pBegin = 0;
900 *pEnd = 0;
904 ::sal_Int32 Document::retrieveParagraphCaretPosition(Paragraph const * pParagraph)
906 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
907 ::osl::MutexGuard aInternalGuard(GetMutex());
908 ::TextSelection const & rSelection = m_rView.GetSelection();
909 Paragraphs::size_type nNumber = pParagraph->getNumber();
910 TextPaM aEndPaM( rSelection.GetEnd() );
912 return aEndPaM.GetPara() == nNumber
913 ? static_cast< ::sal_Int32 >(aEndPaM.GetIndex()) : -1;
916 css::awt::Rectangle
917 Document::retrieveCharacterBounds(Paragraph const * pParagraph,
918 ::sal_Int32 nIndex)
920 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
921 ::osl::MutexGuard aInternalGuard(GetMutex());
922 ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
923 sal_Int32 nLength = m_rEngine.GetText(nNumber).getLength();
924 // XXX numeric overflow
925 if (nIndex < 0 || nIndex > nLength)
926 throw css::lang::IndexOutOfBoundsException(
927 "textwindowaccessibility.cxx:"
928 " Document::retrieveCharacterAttributes",
929 static_cast< css::uno::XWeak * >(this));
930 css::awt::Rectangle aBounds( 0, 0, 0, 0 );
931 if ( nIndex == nLength )
933 aBounds = AWTRectangle(
934 m_rEngine.PaMtoEditCursor(::TextPaM(nNumber,
935 static_cast< ::sal_uInt16 >(nIndex))));
937 else
939 ::Rectangle aLeft(
940 m_rEngine.PaMtoEditCursor(::TextPaM(nNumber,
941 static_cast< ::sal_uInt16 >(nIndex))));
942 // XXX numeric overflow
943 ::Rectangle aRight(
944 m_rEngine.PaMtoEditCursor(::TextPaM(nNumber,
945 static_cast< ::sal_uInt16 >(nIndex)
946 + 1)));
947 // XXX numeric overflow (2x)
948 // FIXME If the vertical extends of the two cursors do not match, assume
949 // nIndex is the last character on the line; the bounding box will then
950 // extend to m_rEnginge.GetMaxTextWidth():
951 ::sal_Int32 nWidth = (aLeft.Top() == aRight.Top()
952 && aLeft.Bottom() == aRight.Bottom())
953 ? static_cast< ::sal_Int32 >(aRight.Left() - aLeft.Left())
954 : static_cast< ::sal_Int32 >(m_rEngine.GetMaxTextWidth()
955 - aLeft.Left());
956 // XXX numeric overflow (4x)
957 aBounds = css::awt::Rectangle(static_cast< ::sal_Int32 >(aLeft.Left()),
958 static_cast< ::sal_Int32 >(aLeft.Top() - m_nViewOffset),
959 nWidth,
960 static_cast< ::sal_Int32 >(aLeft.Bottom()
961 - aLeft.Top()));
962 // XXX numeric overflow (4x)
964 return aBounds;
967 ::sal_Int32 Document::retrieveCharacterIndex(Paragraph const * pParagraph,
968 css::awt::Point const & rPoint)
970 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
971 ::osl::MutexGuard aInternalGuard(GetMutex());
972 ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
973 // XXX numeric overflow
974 ::TextPaM aPaM(m_rEngine.GetPaM(::Point(static_cast< long >(rPoint.X),
975 static_cast< long >(rPoint.Y))));
976 // XXX numeric overflow (2x)
977 return aPaM.GetPara() == nNumber
978 ? static_cast< ::sal_Int32 >(aPaM.GetIndex()) : -1;
979 // XXX numeric overflow
982 struct IndexCompare
984 const css::beans::PropertyValue* pValues;
985 explicit IndexCompare(const css::beans::PropertyValue* pVals)
986 : pValues(pVals)
989 bool operator() ( const sal_Int32& a, const sal_Int32& b ) const
991 return pValues[a].Name < pValues[b].Name;
995 css::uno::Sequence< css::beans::PropertyValue >
996 Document::retrieveCharacterAttributes(
997 Paragraph const * pParagraph, ::sal_Int32 nIndex,
998 const css::uno::Sequence< OUString >& aRequestedAttributes)
1000 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
1002 vcl::Font aFont = m_rEngine.GetFont();
1003 const sal_Int32 AttributeCount = 9;
1004 sal_Int32 i = 0;
1005 css::uno::Sequence< css::beans::PropertyValue > aAttribs( AttributeCount );
1007 //character background color
1008 aAttribs[i].Name = "CharBackColor";
1009 aAttribs[i].Handle = -1;
1010 aAttribs[i].Value = mapFontColor( aFont.GetFillColor() );
1011 aAttribs[i].State = css::beans::PropertyState_DIRECT_VALUE;
1012 i++;
1014 //character color
1015 aAttribs[i].Name = "CharColor";
1016 aAttribs[i].Handle = -1;
1017 //aAttribs[i].Value = mapFontColor( aFont.GetColor() );
1018 aAttribs[i].Value = mapFontColor( m_rEngine.GetTextColor() );
1019 aAttribs[i].State = css::beans::PropertyState_DIRECT_VALUE;
1020 i++;
1022 //character font name
1023 aAttribs[i].Name = "CharFontName";
1024 aAttribs[i].Handle = -1;
1025 aAttribs[i].Value = css::uno::makeAny( aFont.GetName() );
1026 aAttribs[i].State = css::beans::PropertyState_DIRECT_VALUE;
1027 i++;
1029 //character height
1030 aAttribs[i].Name = "CharHeight";
1031 aAttribs[i].Handle = -1;
1032 aAttribs[i].Value = css::uno::makeAny( (sal_Int16)aFont.GetHeight() );
1033 aAttribs[i].State = css::beans::PropertyState_DIRECT_VALUE;
1034 i++;
1036 //character posture
1037 aAttribs[i].Name = "CharPosture";
1038 aAttribs[i].Handle = -1;
1039 aAttribs[i].Value = css::uno::makeAny( (sal_Int16)aFont.GetItalic() );
1040 aAttribs[i].State = css::beans::PropertyState_DIRECT_VALUE;
1041 i++;
1043 //character relief
1045 aAttribs[i].Name = "CharRelief";
1046 aAttribs[i].Handle = -1;
1047 aAttribs[i].Value = css::uno::makeAny( (sal_Int16)aFont.GetRelief() );
1048 aAttribs[i].State = css::beans::PropertyState_DIRECT_VALUE;
1049 i++;
1052 //character strikeout
1053 aAttribs[i].Name = "CharStrikeout";
1054 aAttribs[i].Handle = -1;
1055 aAttribs[i].Value = css::uno::makeAny( (sal_Int16)aFont.GetStrikeout() );
1056 aAttribs[i].State = css::beans::PropertyState_DIRECT_VALUE;
1057 i++;
1059 //character underline
1060 aAttribs[i].Name = "CharUnderline";
1061 aAttribs[i].Handle = -1;
1062 aAttribs[i].Value = css::uno::makeAny( (sal_Int16)aFont.GetUnderline() );
1063 aAttribs[i].State = css::beans::PropertyState_DIRECT_VALUE;
1064 i++;
1066 //character weight
1067 aAttribs[i].Name = "CharWeight";
1068 aAttribs[i].Handle = -1;
1069 aAttribs[i].Value = css::uno::makeAny( (float)aFont.GetWeight() );
1070 aAttribs[i].State = css::beans::PropertyState_DIRECT_VALUE;
1071 i++;
1073 //character alignment
1074 aAttribs[i].Name = "ParaAdjust";
1075 aAttribs[i].Handle = -1;
1076 aAttribs[i].Value = css::uno::makeAny( (sal_Int16)m_rEngine.GetTextAlign() );
1077 aAttribs[i].State = css::beans::PropertyState_DIRECT_VALUE;
1078 i++;
1080 ::osl::MutexGuard aInternalGuard(GetMutex());
1081 ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
1082 // XXX numeric overflow
1083 // nIndex can be equal to getLength();
1084 if (nIndex < 0 || nIndex > m_rEngine.GetText(nNumber).getLength())
1085 throw css::lang::IndexOutOfBoundsException(
1086 "textwindowaccessibility.cxx:"
1087 " Document::retrieveCharacterAttributes",
1088 static_cast< css::uno::XWeak * >(this));
1090 // retrieve default attributes
1091 tPropValMap aCharAttrSeq;
1092 retrieveDefaultAttributesImpl( pParagraph, aRequestedAttributes, aCharAttrSeq );
1094 // retrieve run attributes
1095 tPropValMap aRunAttrSeq;
1096 retrieveRunAttributesImpl( pParagraph, nIndex, aRequestedAttributes, aRunAttrSeq );
1098 // merge default and run attributes
1099 for ( tPropValMap::const_iterator aRunIter = aRunAttrSeq.begin();
1100 aRunIter != aRunAttrSeq.end();
1101 ++aRunIter )
1103 aCharAttrSeq[ aRunIter->first ] = aRunIter->second;
1106 css::beans::PropertyValue* pValues = aAttribs.getArray();
1107 for (i = 0; i < AttributeCount; i++,pValues++)
1109 aCharAttrSeq[ pValues->Name ] = *pValues;
1112 css::uno::Sequence< css::beans::PropertyValue > aRes = convertHashMapToSequence( aCharAttrSeq );
1114 // sort the attributes
1115 sal_Int32 nLength = aRes.getLength();
1116 const css::beans::PropertyValue* pPairs = aRes.getConstArray();
1117 sal_Int32* pIndices = new sal_Int32[nLength];
1118 for( i = 0; i < nLength; i++ )
1119 pIndices[i] = i;
1120 std::sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) );
1121 // create sorted sequences according to index array
1122 css::uno::Sequence< css::beans::PropertyValue > aNewValues( nLength );
1123 css::beans::PropertyValue* pNewValues = aNewValues.getArray();
1124 for( i = 0; i < nLength; i++ )
1126 pNewValues[i] = pPairs[pIndices[i]];
1128 delete[] pIndices;
1130 return aNewValues;
1133 void Document::retrieveDefaultAttributesImpl(
1134 Paragraph const * pParagraph,
1135 const css::uno::Sequence< OUString >& RequestedAttributes,
1136 tPropValMap& rDefAttrSeq)
1138 // default attributes are not supported by text engine
1139 (void) pParagraph;
1140 (void) RequestedAttributes;
1141 (void) rDefAttrSeq;
1144 css::uno::Sequence< css::beans::PropertyValue >
1145 Document::retrieveDefaultAttributes(
1146 Paragraph const * pParagraph,
1147 const css::uno::Sequence< OUString >& RequestedAttributes)
1149 ::osl::Guard< ::comphelper::IMutex > aExternalGuard( getExternalLock() );
1150 ::osl::MutexGuard aInternalGuard( GetMutex() );
1152 tPropValMap aDefAttrSeq;
1153 retrieveDefaultAttributesImpl( pParagraph, RequestedAttributes, aDefAttrSeq );
1154 return convertHashMapToSequence( aDefAttrSeq );
1157 // static
1158 css::uno::Sequence< css::beans::PropertyValue >
1159 Document::convertHashMapToSequence(tPropValMap& rAttrSeq)
1161 css::uno::Sequence< css::beans::PropertyValue > aValues( rAttrSeq.size() );
1162 css::beans::PropertyValue* pValues = aValues.getArray();
1163 ::sal_Int32 i = 0;
1164 for ( tPropValMap::const_iterator aIter = rAttrSeq.begin();
1165 aIter != rAttrSeq.end();
1166 ++aIter )
1168 pValues[i] = aIter->second;
1169 ++i;
1171 return aValues;
1174 void Document::retrieveRunAttributesImpl(
1175 Paragraph const * pParagraph, ::sal_Int32 Index,
1176 const css::uno::Sequence< OUString >& RequestedAttributes,
1177 tPropValMap& rRunAttrSeq)
1179 ::sal_uLong nNumber = static_cast< ::sal_uLong >( pParagraph->getNumber() );
1180 ::TextPaM aPaM( nNumber, static_cast< ::sal_uInt16 >( Index ) );
1181 // XXX numeric overflow
1182 // FIXME TEXTATTR_HYPERLINK ignored:
1183 ::TextAttribFontColor const * pColor
1184 = static_cast< ::TextAttribFontColor const * >(
1185 m_rEngine.FindAttrib( aPaM, TEXTATTR_FONTCOLOR ) );
1186 ::TextAttribFontWeight const * pWeight
1187 = static_cast< ::TextAttribFontWeight const * >(
1188 m_rEngine.FindAttrib( aPaM, TEXTATTR_FONTWEIGHT ) );
1189 tPropValMap aRunAttrSeq;
1190 if ( pColor )
1192 css::beans::PropertyValue aPropVal;
1193 aPropVal.Name = "CharColor";
1194 aPropVal.Handle = -1;
1195 aPropVal.Value = mapFontColor( pColor->GetColor() );
1196 aPropVal.State = css::beans::PropertyState_DIRECT_VALUE;
1197 aRunAttrSeq[ aPropVal.Name ] = aPropVal;
1199 if ( pWeight )
1201 css::beans::PropertyValue aPropVal;
1202 aPropVal.Name = "CharWeight";
1203 aPropVal.Handle = -1;
1204 aPropVal.Value = mapFontWeight( pWeight->getFontWeight() );
1205 aPropVal.State = css::beans::PropertyState_DIRECT_VALUE;
1206 aRunAttrSeq[ aPropVal.Name ] = aPropVal;
1208 if ( RequestedAttributes.getLength() == 0 )
1210 rRunAttrSeq = aRunAttrSeq;
1212 else
1214 const OUString* pReqAttrs = RequestedAttributes.getConstArray();
1215 const ::sal_Int32 nLength = RequestedAttributes.getLength();
1216 for ( ::sal_Int32 i = 0; i < nLength; ++i )
1218 tPropValMap::iterator aIter = aRunAttrSeq.find( pReqAttrs[i] );
1219 if ( aIter != aRunAttrSeq.end() )
1221 rRunAttrSeq[ (*aIter).first ] = (*aIter).second;
1227 css::uno::Sequence< css::beans::PropertyValue >
1228 Document::retrieveRunAttributes(
1229 Paragraph const * pParagraph, ::sal_Int32 Index,
1230 const css::uno::Sequence< OUString >& RequestedAttributes)
1232 ::osl::Guard< ::comphelper::IMutex > aExternalGuard( getExternalLock() );
1233 ::osl::MutexGuard aInternalGuard( GetMutex() );
1234 ::sal_uLong nNumber = static_cast< ::sal_uLong >( pParagraph->getNumber() );
1235 // XXX numeric overflow
1236 if ( Index < 0 || Index >= m_rEngine.GetText(nNumber).getLength() )
1237 throw css::lang::IndexOutOfBoundsException(
1238 "textwindowaccessibility.cxx:"
1239 " Document::retrieveRunAttributes",
1240 static_cast< css::uno::XWeak * >( this ) );
1242 tPropValMap aRunAttrSeq;
1243 retrieveRunAttributesImpl( pParagraph, Index, RequestedAttributes, aRunAttrSeq );
1244 return convertHashMapToSequence( aRunAttrSeq );
1247 void Document::changeParagraphText(Paragraph * pParagraph,
1248 OUString const & rText)
1250 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
1252 ::osl::MutexGuard aInternalGuard(GetMutex());
1253 ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
1254 // XXX numeric overflow
1255 changeParagraphText(nNumber, 0, m_rEngine.GetTextLen(nNumber), false,
1256 false, rText);
1260 void Document::changeParagraphText(Paragraph * pParagraph,
1261 ::sal_Int32 nBegin, ::sal_Int32 nEnd,
1262 bool bCut, bool bPaste,
1263 OUString const & rText)
1265 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
1267 ::osl::MutexGuard aInternalGuard(GetMutex());
1268 ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
1269 // XXX numeric overflow
1270 if (nBegin < 0 || nBegin > nEnd
1271 || nEnd > m_rEngine.GetText(nNumber).getLength())
1272 throw css::lang::IndexOutOfBoundsException(
1273 "textwindowaccessibility.cxx:"
1274 " Document::changeParagraphText",
1275 static_cast< css::uno::XWeak * >(this));
1276 changeParagraphText(nNumber, static_cast< ::sal_uInt16 >(nBegin),
1277 static_cast< ::sal_uInt16 >(nEnd), bCut, bPaste, rText);
1278 // XXX numeric overflow (2x)
1282 void Document::copyParagraphText(Paragraph const * pParagraph,
1283 ::sal_Int32 nBegin, ::sal_Int32 nEnd)
1285 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
1287 ::osl::MutexGuard aInternalGuard(GetMutex());
1288 ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
1289 // XXX numeric overflow
1290 if (nBegin < 0 || nBegin > nEnd
1291 || nEnd > m_rEngine.GetText(nNumber).getLength())
1292 throw css::lang::IndexOutOfBoundsException(
1293 "textwindowaccessibility.cxx:"
1294 " Document::copyParagraphText",
1295 static_cast< css::uno::XWeak * >(this));
1296 m_rView.SetSelection(
1297 ::TextSelection(::TextPaM(nNumber, static_cast< ::sal_uInt16 >(nBegin)),
1298 ::TextPaM(nNumber, static_cast< ::sal_uInt16 >(nEnd))));
1299 // XXX numeric overflow (2x)
1300 m_rView.Copy();
1304 void Document::changeParagraphAttributes(
1305 Paragraph * pParagraph, ::sal_Int32 nBegin, ::sal_Int32 nEnd,
1306 css::uno::Sequence< css::beans::PropertyValue > const & rAttributeSet)
1308 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
1310 ::osl::MutexGuard aInternalGuard(GetMutex());
1311 ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
1312 // XXX numeric overflow
1313 if (nBegin < 0 || nBegin > nEnd
1314 || nEnd > m_rEngine.GetText(nNumber).getLength())
1315 throw css::lang::IndexOutOfBoundsException(
1316 "textwindowaccessibility.cxx:"
1317 " Document::changeParagraphAttributes",
1318 static_cast< css::uno::XWeak * >(this));
1320 // FIXME The new attributes are added to any attributes already set,
1321 // they do not replace the old attributes as required by
1322 // XAccessibleEditableText.setAttributes:
1323 for (::sal_Int32 i = 0; i < rAttributeSet.getLength(); ++i)
1324 if ( rAttributeSet[i].Name == "CharColor" )
1325 m_rEngine.SetAttrib(::TextAttribFontColor(
1326 mapFontColor(rAttributeSet[i].Value)),
1327 nNumber, static_cast< ::sal_uInt16 >(nBegin),
1328 static_cast< ::sal_uInt16 >(nEnd));
1329 // XXX numeric overflow (2x)
1330 else if ( rAttributeSet[i].Name == "CharWeight" )
1331 m_rEngine.SetAttrib(::TextAttribFontWeight(
1332 mapFontWeight(rAttributeSet[i].Value)),
1333 nNumber, static_cast< ::sal_uInt16 >(nBegin),
1334 static_cast< ::sal_uInt16 >(nEnd));
1335 // XXX numeric overflow (2x)
1339 void Document::changeParagraphSelection(Paragraph * pParagraph,
1340 ::sal_Int32 nBegin, ::sal_Int32 nEnd)
1342 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
1344 ::osl::MutexGuard aInternalGuard(GetMutex());
1345 ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
1346 // XXX numeric overflow
1347 if (nBegin < 0 || nBegin > nEnd
1348 || nEnd > m_rEngine.GetText(nNumber).getLength())
1349 throw css::lang::IndexOutOfBoundsException(
1350 "textwindowaccessibility.cxx:"
1351 " Document::changeParagraphSelection",
1352 static_cast< css::uno::XWeak * >(this));
1353 m_rView.SetSelection(
1354 ::TextSelection(::TextPaM(nNumber, static_cast< ::sal_uInt16 >(nBegin)),
1355 ::TextPaM(nNumber, static_cast< ::sal_uInt16 >(nEnd))));
1356 // XXX numeric overflow (2x)
1360 css::i18n::Boundary
1361 Document::retrieveParagraphLineBoundary( Paragraph const * pParagraph,
1362 ::sal_Int32 nIndex, ::sal_Int32 *pLineNo )
1364 css::i18n::Boundary aBoundary;
1365 aBoundary.startPos = nIndex;
1366 aBoundary.endPos = nIndex;
1368 ::osl::Guard< ::comphelper::IMutex > aExternalGuard( getExternalLock() );
1370 ::osl::MutexGuard aInternalGuard( GetMutex() );
1371 ::sal_uLong nNumber = static_cast< ::sal_uLong >( pParagraph->getNumber() );
1372 if ( nIndex < 0 || nIndex > m_rEngine.GetText( nNumber ).getLength() )
1373 throw css::lang::IndexOutOfBoundsException(
1374 "textwindowaccessibility.cxx:"
1375 " Document::retrieveParagraphLineBoundary",
1376 static_cast< css::uno::XWeak * >( this ) );
1377 ::sal_Int32 nLineStart = 0;
1378 ::sal_Int32 nLineEnd = 0;
1379 ::sal_uInt16 nLineCount = m_rEngine.GetLineCount( nNumber );
1380 for ( ::sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine )
1382 ::sal_Int32 nLineLength = static_cast< ::sal_Int32 >(
1383 m_rEngine.GetLineLen( nNumber, nLine ) );
1384 nLineStart = nLineEnd;
1385 nLineEnd += nLineLength;
1386 if ( nIndex >= nLineStart && ( ( nLine == nLineCount - 1 ) ? nIndex <= nLineEnd : nIndex < nLineEnd ) )
1388 aBoundary.startPos = nLineStart;
1389 aBoundary.endPos = nLineEnd;
1390 if( pLineNo )
1391 pLineNo[0] = nLine;
1392 break;
1397 return aBoundary;
1400 css::i18n::Boundary
1401 Document::retrieveParagraphBoundaryOfLine( Paragraph const * pParagraph,
1402 ::sal_Int32 nLineNo )
1404 css::i18n::Boundary aBoundary;
1405 aBoundary.startPos = 0;
1406 aBoundary.endPos = 0;
1408 ::osl::Guard< ::comphelper::IMutex > aExternalGuard( getExternalLock() );
1410 ::osl::MutexGuard aInternalGuard( GetMutex() );
1411 ::sal_uLong nNumber = static_cast< ::sal_uLong >( pParagraph->getNumber() );
1412 if ( nLineNo >= m_rEngine.GetLineCount( nNumber ) )
1413 throw css::lang::IndexOutOfBoundsException(
1414 "textwindowaccessibility.cxx:"
1415 " Document::retrieveParagraphBoundaryOfLine",
1416 static_cast< css::uno::XWeak * >( this ) );
1417 ::sal_Int32 nLineStart = 0;
1418 ::sal_Int32 nLineEnd = 0;
1419 for ( ::sal_uInt16 nLine = 0; nLine <= nLineNo; ++nLine )
1421 ::sal_Int32 nLineLength = static_cast< ::sal_Int32 >(
1422 m_rEngine.GetLineLen( nNumber, nLine ) );
1423 nLineStart = nLineEnd;
1424 nLineEnd += nLineLength;
1427 aBoundary.startPos = nLineStart;
1428 aBoundary.endPos = nLineEnd;
1431 return aBoundary;
1434 sal_Int32 Document::retrieveParagraphLineWithCursor( Paragraph const * pParagraph )
1436 ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
1437 ::osl::MutexGuard aInternalGuard(GetMutex());
1438 ::TextSelection const & rSelection = m_rView.GetSelection();
1439 Paragraphs::size_type nNumber = pParagraph->getNumber();
1440 TextPaM aEndPaM( rSelection.GetEnd() );
1442 return aEndPaM.GetPara() == nNumber
1443 ? m_rView.GetLineNumberOfCursorInSelection() : -1;
1447 css::uno::Reference< css::accessibility::XAccessibleRelationSet >
1448 Document::retrieveParagraphRelationSet( Paragraph const * pParagraph )
1450 ::osl::MutexGuard aInternalGuard( GetMutex() );
1452 ::utl::AccessibleRelationSetHelper* pRelationSetHelper = new ::utl::AccessibleRelationSetHelper();
1453 css::uno::Reference< css::accessibility::XAccessibleRelationSet > xSet = pRelationSetHelper;
1455 Paragraphs::iterator aPara( m_xParagraphs->begin() + pParagraph->getNumber() );
1457 if ( aPara > m_aVisibleBegin && aPara < m_aVisibleEnd )
1459 css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > aSequence(1);
1460 aSequence[0] = getAccessibleChild( aPara - 1 );
1461 css::accessibility::AccessibleRelation aRelation( css::accessibility::AccessibleRelationType::CONTENT_FLOWS_FROM, aSequence );
1462 pRelationSetHelper->AddRelation( aRelation );
1465 if ( aPara >= m_aVisibleBegin && aPara < m_aVisibleEnd -1 )
1467 css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > aSequence(1);
1468 aSequence[0] = getAccessibleChild( aPara + 1 );
1469 css::accessibility::AccessibleRelation aRelation( css::accessibility::AccessibleRelationType::CONTENT_FLOWS_TO, aSequence );
1470 pRelationSetHelper->AddRelation( aRelation );
1473 return xSet;
1476 // virtual
1477 ::sal_Int32 SAL_CALL Document::getAccessibleChildCount()
1478 throw (css::uno::RuntimeException, std::exception)
1480 ::comphelper::OExternalLockGuard aGuard(this);
1481 init();
1482 return m_aVisibleEnd - m_aVisibleBegin;
1485 // virtual
1486 css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
1487 Document::getAccessibleChild(::sal_Int32 i)
1488 throw (css::lang::IndexOutOfBoundsException,
1489 css::uno::RuntimeException, std::exception)
1491 ::comphelper::OExternalLockGuard aGuard(this);
1492 init();
1493 if (i < 0 || i >= m_aVisibleEnd - m_aVisibleBegin)
1494 throw css::lang::IndexOutOfBoundsException(
1495 "textwindowaccessibility.cxx:"
1496 " Document::getAccessibleChild",
1497 static_cast< css::uno::XWeak * >(this));
1498 return getAccessibleChild(m_aVisibleBegin
1499 + static_cast< Paragraphs::size_type >(i));
1502 // virtual
1503 ::sal_Int16 SAL_CALL Document::getAccessibleRole()
1504 throw (css::uno::RuntimeException, std::exception)
1506 return css::accessibility::AccessibleRole::TEXT_FRAME;
1509 // virtual
1510 css::uno::Reference< css::accessibility::XAccessible > SAL_CALL
1511 Document::getAccessibleAtPoint(css::awt::Point const & rPoint)
1512 throw (css::uno::RuntimeException, std::exception)
1514 ::comphelper::OExternalLockGuard aGuard(this);
1515 init();
1516 if (rPoint.X >= 0
1517 && rPoint.X < m_rView.GetWindow()->GetOutputSizePixel().Width()
1518 && rPoint.Y >= 0 && rPoint.Y < m_nViewHeight)
1520 ::sal_Int32 nOffset = m_nViewOffset + rPoint.Y; // XXX numeric overflow
1521 ::sal_Int32 nPos = m_nViewOffset - m_nVisibleBeginOffset;
1522 for (Paragraphs::iterator aIt(m_aVisibleBegin); aIt != m_aVisibleEnd;
1523 ++aIt)
1525 nPos += aIt->getHeight(); // XXX numeric overflow
1526 if (nOffset < nPos)
1527 return getAccessibleChild(aIt);
1530 return 0;
1532 void Document::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
1534 VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
1535 if (!m_rView.IsReadOnly())
1536 rStateSet.AddState( css::accessibility::AccessibleStateType::EDITABLE );
1539 void Document::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
1541 if( getAccessibleParent()->getAccessibleContext()->getAccessibleRole() == css::accessibility::AccessibleRole::SCROLL_PANE )
1543 css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > aSequence(1);
1544 aSequence[0] = getAccessibleParent();
1545 rRelationSet.AddRelation( css::accessibility::AccessibleRelation( css::accessibility::AccessibleRelationType::MEMBER_OF, aSequence ) );
1547 else
1549 VCLXAccessibleComponent::FillAccessibleRelationSet(rRelationSet);
1552 // virtual
1553 void SAL_CALL Document::disposing()
1555 m_aEngineListener.endListening();
1556 m_aViewListener.endListening();
1557 if (m_xParagraphs.get() != 0)
1558 disposeParagraphs();
1559 VCLXAccessibleComponent::disposing();
1562 // virtual
1563 void Document::Notify(::SfxBroadcaster &, ::SfxHint const & rHint)
1565 const TextHint* pTextHint = dynamic_cast<const TextHint*>(&rHint);
1566 if (pTextHint)
1568 ::TextHint const & rTextHint = *pTextHint;
1569 switch (rTextHint.GetId())
1571 case TEXT_HINT_PARAINSERTED:
1572 case TEXT_HINT_PARAREMOVED:
1573 // TEXT_HINT_PARAINSERTED and TEXT_HINT_PARAREMOVED are sent at
1574 // "unsafe" times (when the text engine has not yet re-formatted its
1575 // content), so that for example calling ::TextEngine::GetTextHeight
1576 // from within the code that handles TEXT_HINT_PARAINSERTED causes
1577 // trouble within the text engine. Therefore, these hints are just
1578 // buffered until a following ::TextEngine::FormatDoc causes a
1579 // TEXT_HINT_TEXTFORMATTED to come in:
1580 case TEXT_HINT_FORMATPARA:
1581 // ::TextEngine::FormatDoc sends a sequence of
1582 // TEXT_HINT_FORMATPARAs, followed by an optional
1583 // TEXT_HINT_TEXTHEIGHTCHANGED, followed in all cases by one
1584 // TEXT_HINT_TEXTFORMATTED. Only the TEXT_HINT_FORMATPARAs contain
1585 // the numbers of the affected paragraphs, but they are sent
1586 // before the changes are applied. Therefore, TEXT_HINT_FORMATPARAs
1587 // are just buffered until another hint comes in:
1589 ::osl::MutexGuard aInternalGuard(GetMutex());
1590 if (!isAlive())
1591 break;
1593 m_aParagraphNotifications.push(rTextHint);
1594 break;
1596 case TEXT_HINT_TEXTFORMATTED:
1597 case TEXT_HINT_TEXTHEIGHTCHANGED:
1598 case TEXT_HINT_MODIFIED:
1600 ::osl::MutexGuard aInternalGuard(GetMutex());
1601 if (!isAlive())
1602 break;
1603 handleParagraphNotifications();
1604 break;
1606 case TEXT_HINT_VIEWSCROLLED:
1608 ::osl::MutexGuard aInternalGuard(GetMutex());
1609 if (!isAlive())
1610 break;
1611 handleParagraphNotifications();
1613 ::sal_Int32 nOffset = static_cast< ::sal_Int32 >(
1614 m_rView.GetStartDocPos().Y());
1615 // XXX numeric overflow
1616 if (nOffset != m_nViewOffset)
1618 m_nViewOffset = nOffset;
1620 Paragraphs::iterator aOldVisibleBegin(
1621 m_aVisibleBegin);
1622 Paragraphs::iterator aOldVisibleEnd(m_aVisibleEnd);
1624 determineVisibleRange();
1626 notifyVisibleRangeChanges(aOldVisibleBegin,
1627 aOldVisibleEnd,
1628 m_xParagraphs->end());
1630 break;
1632 case TEXT_HINT_VIEWSELECTIONCHANGED:
1633 case TEXT_HINT_VIEWCARETCHANGED:
1635 ::osl::MutexGuard aInternalGuard(GetMutex());
1636 if (!isAlive())
1637 break;
1639 if (m_aParagraphNotifications.empty())
1641 handleSelectionChangeNotification();
1643 else
1645 // TEXT_HINT_VIEWSELECTIONCHANGED is sometimes sent at
1646 // "unsafe" times (when the text engine has not yet re-
1647 // formatted its content), so that for example calling
1648 // ::TextEngine::GetTextHeight from within the code that
1649 // handles a previous TEXT_HINT_PARAINSERTED causes
1650 // trouble within the text engine. Therefore, these
1651 // hints are just buffered (along with
1652 // TEXT_HINT_PARAINSERTED/REMOVED/FORMATPARA) until a
1653 // following ::TextEngine::FormatDoc causes a
1654 // TEXT_HINT_TEXTFORMATTED to come in:
1655 m_bSelectionChangedNotification = true;
1657 break;
1663 IMPL_LINK(Document, WindowEventHandler, ::VclSimpleEvent *, pEvent)
1665 switch (pEvent->GetId())
1667 case VCLEVENT_WINDOW_RESIZE:
1669 ::osl::MutexGuard aInternalGuard(GetMutex());
1670 if (!isAlive())
1671 break;
1673 ::sal_Int32 nHeight = static_cast< ::sal_Int32 >(
1674 m_rView.GetWindow()->GetOutputSizePixel().Height());
1675 // XXX numeric overflow
1676 if (nHeight != m_nViewHeight)
1678 m_nViewHeight = nHeight;
1680 Paragraphs::iterator aOldVisibleBegin(m_aVisibleBegin);
1681 Paragraphs::iterator aOldVisibleEnd(m_aVisibleEnd);
1683 determineVisibleRange();
1685 notifyVisibleRangeChanges(aOldVisibleBegin, aOldVisibleEnd,
1686 m_xParagraphs->end());
1688 break;
1690 case VCLEVENT_WINDOW_GETFOCUS:
1692 ::osl::MutexGuard aInternalGuard(GetMutex());
1693 if (!isAlive())
1694 break;
1695 //to enable the PARAGRAPH to get focus for multiline edit
1696 ::sal_Int32 count = getAccessibleChildCount();
1697 bool bEmpty = m_aFocused == m_aVisibleEnd && count == 1;
1698 if ((m_aFocused >= m_aVisibleBegin && m_aFocused < m_aVisibleEnd) || bEmpty)
1700 Paragraphs::iterator m_aTemp = bEmpty ? m_aVisibleBegin : m_aFocused;
1701 ::rtl::Reference< Paragraph > xParagraph(getParagraph(m_aTemp));
1702 if (xParagraph.is())
1704 xParagraph->notifyEvent(
1705 css::accessibility::AccessibleEventId::
1706 STATE_CHANGED,
1707 css::uno::Any(),
1708 css::uno::makeAny(
1709 css::accessibility::AccessibleStateType::
1710 FOCUSED));
1714 ::rtl::Reference< Paragraph > xParagraph(
1715 getParagraph(m_aFocused));
1716 if (xParagraph.is())
1717 xParagraph->notifyEvent(
1718 css::accessibility::AccessibleEventId::
1719 STATE_CHANGED,
1720 css::uno::Any(),
1721 css::uno::makeAny(
1722 css::accessibility::AccessibleStateType::
1723 FOCUSED));
1725 break;
1727 case VCLEVENT_WINDOW_LOSEFOCUS:
1729 ::osl::MutexGuard aInternalGuard(GetMutex());
1730 if (!isAlive())
1731 break;
1732 //to enable the PARAGRAPH to get focus for multiline edit
1733 ::sal_Int32 count = getAccessibleChildCount();
1734 bool bEmpty = m_aFocused == m_aVisibleEnd && count == 1;
1735 if ((m_aFocused >= m_aVisibleBegin && m_aFocused < m_aVisibleEnd) || bEmpty)
1737 Paragraphs::iterator m_aTemp = bEmpty ? m_aVisibleBegin : m_aFocused;
1738 ::rtl::Reference< Paragraph > xParagraph(getParagraph(m_aTemp));
1739 if (xParagraph.is())
1740 xParagraph->notifyEvent(
1741 css::accessibility::AccessibleEventId::
1742 STATE_CHANGED,
1743 css::uno::makeAny(
1744 css::accessibility::AccessibleStateType::
1745 FOCUSED),
1746 css::uno::Any());
1750 if (m_aFocused >= m_aVisibleBegin && m_aFocused < m_aVisibleEnd)
1752 ::rtl::Reference< Paragraph > xParagraph(
1753 getParagraph(m_aFocused));
1754 if (xParagraph.is())
1755 xParagraph->notifyEvent(
1756 css::accessibility::AccessibleEventId::
1757 STATE_CHANGED,
1758 css::uno::makeAny(
1759 css::accessibility::AccessibleStateType::
1760 FOCUSED),
1761 css::uno::Any());
1764 break;
1767 return 0;
1770 void Document::init()
1772 if (m_xParagraphs.get() == 0)
1774 ::sal_uLong nCount = m_rEngine.GetParagraphCount();
1775 m_xParagraphs.reset(new Paragraphs);
1776 m_xParagraphs->reserve(static_cast< Paragraphs::size_type >(nCount));
1777 // numeric overflow is harmless here
1778 for (::sal_uLong i = 0; i < nCount; ++i)
1779 m_xParagraphs->push_back(ParagraphInfo(static_cast< ::sal_Int32 >(
1780 m_rEngine.GetTextHeight(i))));
1781 // XXX numeric overflow
1782 m_nViewOffset = static_cast< ::sal_Int32 >(
1783 m_rView.GetStartDocPos().Y()); // XXX numeric overflow
1784 m_nViewHeight = static_cast< ::sal_Int32 >(
1785 m_rView.GetWindow()->GetOutputSizePixel().Height());
1786 // XXX numeric overflow
1787 determineVisibleRange();
1788 m_nSelectionFirstPara = -1;
1789 m_nSelectionFirstPos = -1;
1790 m_nSelectionLastPara = -1;
1791 m_nSelectionLastPos = -1;
1792 m_aFocused = m_xParagraphs->end();
1793 m_bSelectionChangedNotification = false;
1794 m_aEngineListener.startListening(m_rEngine);
1795 m_aViewListener.startListening(*m_rView.GetWindow());
1799 ::rtl::Reference< Paragraph >
1800 Document::getParagraph(Paragraphs::iterator const & rIt)
1802 return static_cast< Paragraph * >(
1803 css::uno::Reference< css::accessibility::XAccessible >(
1804 rIt->getParagraph()).get());
1807 css::uno::Reference< css::accessibility::XAccessible >
1808 Document::getAccessibleChild(Paragraphs::iterator const & rIt)
1810 css::uno::Reference< css::accessibility::XAccessible > xParagraph(
1811 rIt->getParagraph());
1812 if (!xParagraph.is())
1814 xParagraph = new Paragraph(this, rIt - m_xParagraphs->begin());
1815 rIt->setParagraph(xParagraph);
1817 return xParagraph;
1820 void Document::determineVisibleRange()
1822 Paragraphs::iterator const aEnd = m_xParagraphs->end();
1824 m_aVisibleBegin = aEnd;
1825 m_aVisibleEnd = aEnd;
1826 m_nVisibleBeginOffset = 0;
1828 ::sal_Int32 nPos = 0;
1829 for (Paragraphs::iterator aIt = m_xParagraphs->begin(); m_aVisibleEnd == aEnd && aIt != aEnd; ++aIt)
1831 ::sal_Int32 const nOldPos = nPos;
1832 nPos += aIt->getHeight(); // XXX numeric overflow
1833 if (m_aVisibleBegin == aEnd)
1835 if (nPos >= m_nViewOffset)
1837 m_aVisibleBegin = aIt;
1838 m_nVisibleBeginOffset = m_nViewOffset - nOldPos;
1841 else
1843 if (nPos >= m_nViewOffset + m_nViewHeight) // XXX numeric overflow
1845 m_aVisibleEnd = aIt;
1850 SAL_WARN_IF(
1851 !((m_aVisibleBegin == m_xParagraphs->end() && m_aVisibleEnd == m_xParagraphs->end() && m_nVisibleBeginOffset == 0)
1852 || (m_aVisibleBegin < m_aVisibleEnd && m_nVisibleBeginOffset >= 0)),
1853 "accessibility",
1854 "invalid visible range");
1857 void Document::notifyVisibleRangeChanges(
1858 Paragraphs::iterator const & rOldVisibleBegin,
1859 Paragraphs::iterator const & rOldVisibleEnd,
1860 Paragraphs::iterator const & rInserted)
1862 // XXX Replace this code that determines which paragraphs have changed from
1863 // invisible to visible or vice versa with a better algorithm.
1864 for (Paragraphs::iterator aIt(rOldVisibleBegin); aIt != rOldVisibleEnd;
1865 ++aIt)
1867 if (aIt != rInserted
1868 && (aIt < m_aVisibleBegin || aIt >= m_aVisibleEnd))
1869 NotifyAccessibleEvent(
1870 css::accessibility::AccessibleEventId::
1871 CHILD,
1872 css::uno::makeAny(getAccessibleChild(aIt)),
1873 css::uno::Any());
1875 for (Paragraphs::iterator aIt(m_aVisibleBegin); aIt != m_aVisibleEnd;
1876 ++aIt)
1878 if (aIt == rInserted
1879 || aIt < rOldVisibleBegin || aIt >= rOldVisibleEnd)
1880 NotifyAccessibleEvent(
1881 css::accessibility::AccessibleEventId::
1882 CHILD,
1883 css::uno::Any(),
1884 css::uno::makeAny(getAccessibleChild(aIt)));
1888 void
1889 Document::changeParagraphText(::sal_uLong nNumber, ::sal_uInt16 nBegin, ::sal_uInt16 nEnd,
1890 bool bCut, bool bPaste,
1891 OUString const & rText)
1893 m_rView.SetSelection(::TextSelection(::TextPaM(nNumber, nBegin),
1894 ::TextPaM(nNumber, nEnd)));
1895 if (bCut)
1896 m_rView.Cut();
1897 else if (nBegin != nEnd)
1898 m_rView.DeleteSelected();
1899 if (bPaste)
1900 m_rView.Paste();
1901 else if (!rText.isEmpty())
1902 m_rView.InsertText(rText);
1905 void Document::handleParagraphNotifications()
1907 while (!m_aParagraphNotifications.empty())
1909 ::TextHint aHint(m_aParagraphNotifications.front());
1910 m_aParagraphNotifications.pop();
1911 switch (aHint.GetId())
1913 case TEXT_HINT_PARAINSERTED:
1915 ::sal_uLong n = aHint.GetValue();
1916 OSL_ENSURE(n <= m_xParagraphs->size(),
1917 "bad TEXT_HINT_PARAINSERTED event");
1919 // Save the values of old iterators (the iterators themselves
1920 // will get invalidated), and adjust the old values so that they
1921 // reflect the insertion of the new paragraph:
1922 Paragraphs::size_type nOldVisibleBegin
1923 = m_aVisibleBegin - m_xParagraphs->begin();
1924 Paragraphs::size_type nOldVisibleEnd
1925 = m_aVisibleEnd - m_xParagraphs->begin();
1926 Paragraphs::size_type nOldFocused
1927 = m_aFocused - m_xParagraphs->begin();
1928 if (n <= nOldVisibleBegin)
1929 ++nOldVisibleBegin; // XXX numeric overflow
1930 if (n <= nOldVisibleEnd)
1931 ++nOldVisibleEnd; // XXX numeric overflow
1932 if (n <= nOldFocused)
1933 ++nOldFocused; // XXX numeric overflow
1934 if (sal::static_int_cast<sal_Int32>(n) <= m_nSelectionFirstPara)
1935 ++m_nSelectionFirstPara; // XXX numeric overflow
1936 if (sal::static_int_cast<sal_Int32>(n) <= m_nSelectionLastPara)
1937 ++m_nSelectionLastPara; // XXX numeric overflow
1939 Paragraphs::iterator aIns(
1940 m_xParagraphs->insert(
1941 m_xParagraphs->begin() + n,
1942 ParagraphInfo(static_cast< ::sal_Int32 >(
1943 m_rEngine.GetTextHeight(n)))));
1944 // XXX numeric overflow (2x)
1946 determineVisibleRange();
1947 m_aFocused = m_xParagraphs->begin() + nOldFocused;
1949 for (Paragraphs::iterator aIt(aIns);;)
1951 ++aIt;
1952 if (aIt == m_xParagraphs->end())
1953 break;
1954 ::rtl::Reference< Paragraph > xParagraph(
1955 getParagraph(aIt));
1956 if (xParagraph.is())
1957 xParagraph->numberChanged(true);
1960 notifyVisibleRangeChanges(
1961 m_xParagraphs->begin() + nOldVisibleBegin,
1962 m_xParagraphs->begin() + nOldVisibleEnd, aIns);
1963 break;
1965 case TEXT_HINT_PARAREMOVED:
1967 ::sal_uLong n = aHint.GetValue();
1968 if (n == TEXT_PARA_ALL)
1970 for (Paragraphs::iterator aIt(m_aVisibleBegin);
1971 aIt != m_aVisibleEnd; ++aIt)
1973 NotifyAccessibleEvent(
1974 css::accessibility::AccessibleEventId::
1975 CHILD,
1976 css::uno::makeAny(getAccessibleChild(aIt)),
1977 css::uno::Any());
1979 disposeParagraphs();
1980 m_xParagraphs->clear();
1981 determineVisibleRange();
1982 m_nSelectionFirstPara = -1;
1983 m_nSelectionFirstPos = -1;
1984 m_nSelectionLastPara = -1;
1985 m_nSelectionLastPos = -1;
1986 m_aFocused = m_xParagraphs->end();
1988 else
1990 OSL_ENSURE(n < m_xParagraphs->size(),
1991 "Bad TEXT_HINT_PARAREMOVED event");
1993 Paragraphs::iterator aIt(m_xParagraphs->begin() + n);
1994 // numeric overflow cannot occur
1996 // Save the values of old iterators (the iterators
1997 // themselves will get invalidated), and adjust the old
1998 // values so that they reflect the removal of the paragraph:
1999 Paragraphs::size_type nOldVisibleBegin
2000 = m_aVisibleBegin - m_xParagraphs->begin();
2001 Paragraphs::size_type nOldVisibleEnd
2002 = m_aVisibleEnd - m_xParagraphs->begin();
2003 bool bWasVisible
2004 = nOldVisibleBegin <= n && n < nOldVisibleEnd;
2005 Paragraphs::size_type nOldFocused
2006 = m_aFocused - m_xParagraphs->begin();
2007 bool bWasFocused = aIt == m_aFocused;
2008 if (n < nOldVisibleBegin)
2009 --nOldVisibleBegin;
2010 if (n < nOldVisibleEnd)
2011 --nOldVisibleEnd;
2012 if (n < nOldFocused)
2013 --nOldFocused;
2014 if (sal::static_int_cast<sal_Int32>(n) < m_nSelectionFirstPara)
2015 --m_nSelectionFirstPara;
2016 else if (sal::static_int_cast<sal_Int32>(n) == m_nSelectionFirstPara)
2018 if (m_nSelectionFirstPara == m_nSelectionLastPara)
2020 m_nSelectionFirstPara = -1;
2021 m_nSelectionFirstPos = -1;
2022 m_nSelectionLastPara = -1;
2023 m_nSelectionLastPos = -1;
2025 else
2027 ++m_nSelectionFirstPara;
2028 m_nSelectionFirstPos = 0;
2031 if (sal::static_int_cast<sal_Int32>(n) < m_nSelectionLastPara)
2032 --m_nSelectionLastPara;
2033 else if (sal::static_int_cast<sal_Int32>(n) == m_nSelectionLastPara)
2035 OSL_ENSURE(m_nSelectionFirstPara < m_nSelectionLastPara,
2036 "logic error");
2037 --m_nSelectionLastPara;
2038 m_nSelectionLastPos = 0x7FFFFFFF;
2041 css::uno::Reference< css::accessibility::XAccessible >
2042 xStrong;
2043 if (bWasVisible)
2044 xStrong = getAccessibleChild(aIt);
2045 css::uno::WeakReference<
2046 css::accessibility::XAccessible > xWeak(
2047 aIt->getParagraph());
2048 aIt = m_xParagraphs->erase(aIt);
2050 determineVisibleRange();
2051 m_aFocused = bWasFocused ? m_xParagraphs->end()
2052 : m_xParagraphs->begin() + nOldFocused;
2054 for (; aIt != m_xParagraphs->end(); ++aIt)
2056 ::rtl::Reference< Paragraph > xParagraph(
2057 getParagraph(aIt));
2058 if (xParagraph.is())
2059 xParagraph->numberChanged(false);
2062 if (bWasVisible)
2063 NotifyAccessibleEvent(
2064 css::accessibility::AccessibleEventId::
2065 CHILD,
2066 css::uno::makeAny(xStrong),
2067 css::uno::Any());
2069 css::uno::Reference< css::lang::XComponent > xComponent(
2070 xWeak.get(), css::uno::UNO_QUERY);
2071 if (xComponent.is())
2072 xComponent->dispose();
2074 notifyVisibleRangeChanges(
2075 m_xParagraphs->begin() + nOldVisibleBegin,
2076 m_xParagraphs->begin() + nOldVisibleEnd,
2077 m_xParagraphs->end());
2079 break;
2081 case TEXT_HINT_FORMATPARA:
2083 ::sal_uLong n = aHint.GetValue();
2084 OSL_ENSURE(n < m_xParagraphs->size(),
2085 "Bad TEXT_HINT_FORMATPARA event");
2087 (*m_xParagraphs)[static_cast< Paragraphs::size_type >(n)].
2088 changeHeight(static_cast< ::sal_Int32 >(
2089 m_rEngine.GetTextHeight(n)));
2090 // XXX numeric overflow
2091 Paragraphs::iterator aOldVisibleBegin(m_aVisibleBegin);
2092 Paragraphs::iterator aOldVisibleEnd(m_aVisibleEnd);
2093 determineVisibleRange();
2094 notifyVisibleRangeChanges(aOldVisibleBegin, aOldVisibleEnd,
2095 m_xParagraphs->end());
2097 if (n < m_xParagraphs->size())
2099 Paragraphs::iterator aIt(m_xParagraphs->begin() + n);
2100 ::rtl::Reference< Paragraph > xParagraph(getParagraph(aIt));
2101 if (xParagraph.is())
2102 xParagraph->textChanged();
2104 break;
2106 default:
2107 OSL_FAIL( "bad buffered hint");
2108 break;
2111 if (m_bSelectionChangedNotification)
2113 m_bSelectionChangedNotification = false;
2114 handleSelectionChangeNotification();
2118 ::sal_Int32 Document::getSelectionType(::sal_Int32 nNewFirstPara, ::sal_Int32 nNewFirstPos, ::sal_Int32 nNewLastPara, ::sal_Int32 nNewLastPos)
2120 if (m_nSelectionFirstPara == -1)
2121 return -1;
2122 ::sal_Int32 Osp = m_nSelectionFirstPara, Osl = m_nSelectionFirstPos, Oep = m_nSelectionLastPara, Oel = m_nSelectionLastPos;
2123 ::sal_Int32 Nsp = nNewFirstPara, Nsl = nNewFirstPos, Nep = nNewLastPara, Nel = nNewLastPos;
2124 TextPaM Ns(Nsp, sal_uInt16(Nsl));
2125 TextPaM Ne(Nep, sal_uInt16(Nel));
2126 TextPaM Os(Osp, sal_uInt16(Osl));
2127 TextPaM Oe(Oep, sal_uInt16(Oel));
2129 if (Os == Oe && Ns == Ne)
2131 //only caret moves.
2132 return 1;
2134 else if (Os == Oe && Ns != Ne)
2136 //old has no selection but new has selection
2137 return 2;
2139 else if (Os != Oe && Ns == Ne)
2141 //old has selection but new has no selection.
2142 return 3;
2144 else if (Os != Oe && Ns != Ne && Osp == Nsp && Osl == Nsl)
2146 //both old and new have selections.
2147 if (Oep == Nep )
2149 //Send text_selection_change event on Nep
2151 return 4;
2153 else if (Oep < Nep)
2155 //all the following examples like 1,2->1,3 means that old start select para is 1, old end select para is 2,
2156 // then press shift up, the new start select para is 1, new end select para is 3;
2157 //for example, 1, 2 -> 1, 3; 4,1 -> 4, 7; 4,1 -> 4, 2; 4,4->4,5
2158 if (Nep >= Nsp)
2160 // 1, 2 -> 1, 3; 4, 1 -> 4, 7; 4,4->4,5;
2161 if (Oep < Osp)
2163 // 4,1 -> 4,7;
2164 return 5;
2166 else if (Oep >= Osp)
2168 // 1, 2 -> 1, 3; 4,4->4,5;
2169 return 6;
2172 else
2174 // 4,1 -> 4,2,
2175 if (Oep < Osp)
2177 // 4,1 -> 4,2,
2178 return 7;
2180 else if (Oep >= Osp)
2182 // no such condition. Oep > Osp = Nsp > Nep
2186 else if (Oep > Nep)
2188 // 3,2 -> 3,1; 4,7 -> 4,1; 4, 7 -> 4,6; 4,4 -> 4,3
2189 if (Nep >= Nsp)
2191 // 4,7 -> 4,6
2192 if (Oep <= Osp)
2194 //no such condition, Oep<Osp=Nsp <= Nep
2196 else if (Oep > Osp)
2198 // 4,7 ->4,6
2199 return 8;
2202 else
2204 // 3,2 -> 3,1, 4,7 -> 4,1; 4,4->4,3
2205 if (Oep <= Osp)
2207 // 3,2 -> 3,1; 4,4->4,3
2208 return 9;
2210 else if (Oep > Osp)
2212 // 4,7 -> 4,1
2213 return 10;
2218 return -1;
2222 void Document::sendEvent(::sal_Int32 start, ::sal_Int32 end, ::sal_Int16 nEventId)
2224 size_t nAvailDistance = std::distance(m_xParagraphs->begin(), m_aVisibleEnd);
2226 Paragraphs::iterator aEnd(m_xParagraphs->begin());
2227 size_t nEndDistance = std::min<size_t>(end + 1, nAvailDistance);
2228 std::advance(aEnd, nEndDistance);
2230 Paragraphs::iterator aIt(m_xParagraphs->begin());
2231 size_t nStartDistance = std::min<size_t>(start, nAvailDistance);
2232 std::advance(aIt, nStartDistance);
2234 while (aIt < aEnd)
2236 ::rtl::Reference< Paragraph > xParagraph(getParagraph(aIt));
2237 if (xParagraph.is())
2238 xParagraph->notifyEvent(
2239 nEventId,
2240 css::uno::Any(), css::uno::Any());
2241 ++aIt;
2245 void Document::handleSelectionChangeNotification()
2247 ::TextSelection const & rSelection = m_rView.GetSelection();
2248 OSL_ENSURE(rSelection.GetStart().GetPara() < m_xParagraphs->size()
2249 && rSelection.GetEnd().GetPara() < m_xParagraphs->size(),
2250 "bad TEXT_HINT_VIEWSELECTIONCHANGED event");
2251 ::sal_Int32 nNewFirstPara
2252 = static_cast< ::sal_Int32 >(rSelection.GetStart().GetPara());
2253 ::sal_Int32 nNewFirstPos
2254 = static_cast< ::sal_Int32 >(rSelection.GetStart().GetIndex());
2255 // XXX numeric overflow
2256 ::sal_Int32 nNewLastPara
2257 = static_cast< ::sal_Int32 >(rSelection.GetEnd().GetPara());
2258 ::sal_Int32 nNewLastPos
2259 = static_cast< ::sal_Int32 >(rSelection.GetEnd().GetIndex());
2260 // XXX numeric overflow
2262 // Lose focus:
2263 Paragraphs::iterator aIt(m_xParagraphs->begin() + nNewLastPara);
2264 if (m_aFocused != m_xParagraphs->end() && m_aFocused != aIt
2265 && m_aFocused >= m_aVisibleBegin && m_aFocused < m_aVisibleEnd)
2267 ::rtl::Reference< Paragraph > xParagraph(getParagraph(m_aFocused));
2268 if (xParagraph.is())
2269 xParagraph->notifyEvent(
2270 css::accessibility::AccessibleEventId::
2271 STATE_CHANGED,
2272 css::uno::makeAny(
2273 css::accessibility::AccessibleStateType::FOCUSED),
2274 css::uno::Any());
2277 // Gain focus and update cursor position:
2278 if (aIt >= m_aVisibleBegin && aIt < m_aVisibleEnd
2279 && (aIt != m_aFocused
2280 || nNewLastPara != m_nSelectionLastPara
2281 || nNewLastPos != m_nSelectionLastPos))
2283 ::rtl::Reference< Paragraph > xParagraph(getParagraph(aIt));
2284 if (xParagraph.is())
2286 //disable the first event when user types in empty field.
2287 ::sal_Int32 count = getAccessibleChildCount();
2288 bool bEmpty = count > 1;
2289 //if (aIt != m_aFocused)
2290 if (aIt != m_aFocused && bEmpty)
2291 xParagraph->notifyEvent(
2292 css::accessibility::AccessibleEventId::
2293 STATE_CHANGED,
2294 css::uno::Any(),
2295 css::uno::makeAny(
2296 css::accessibility::AccessibleStateType::FOCUSED));
2297 if (nNewLastPara != m_nSelectionLastPara
2298 || nNewLastPos != m_nSelectionLastPos)
2299 xParagraph->notifyEvent(
2300 css::accessibility::AccessibleEventId::
2301 CARET_CHANGED,
2302 css::uno::makeAny< ::sal_Int32 >(
2303 nNewLastPara == m_nSelectionLastPara
2304 ? m_nSelectionLastPos : 0),
2305 css::uno::makeAny(nNewLastPos));
2308 m_aFocused = aIt;
2310 ::sal_Int32 nMin;
2311 ::sal_Int32 nMax;
2312 ::sal_Int32 ret = getSelectionType(nNewFirstPara, nNewFirstPos, nNewLastPara, nNewLastPos);
2313 switch (ret)
2315 case -1:
2317 //no event
2319 break;
2320 case 1:
2322 //only caret moved, already handled in above
2324 break;
2325 case 2:
2327 //old has no selection but new has selection
2328 nMin = ::std::min(nNewFirstPara, nNewLastPara);
2329 nMax = ::std::max(nNewFirstPara, nNewLastPara);
2330 sendEvent(nMin, nMax, css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2331 sendEvent(nMin, nMax, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2333 break;
2334 case 3:
2336 //old has selection but new has no selection.
2337 nMin = ::std::min(m_nSelectionFirstPara, m_nSelectionLastPara);
2338 nMax = ::std::max(m_nSelectionFirstPara, m_nSelectionLastPara);
2339 sendEvent(nMin, nMax, css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2340 sendEvent(nMin, nMax, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2342 break;
2343 case 4:
2345 //Send text_selection_change event on Nep
2346 sendEvent(nNewLastPara, nNewLastPara, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2348 break;
2349 case 5:
2351 // 4, 1 -> 4, 7
2352 sendEvent(m_nSelectionLastPara, m_nSelectionFirstPara-1, css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2353 sendEvent(nNewFirstPara+1, nNewLastPara, css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2355 sendEvent(m_nSelectionLastPara, nNewLastPara, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2357 break;
2358 case 6:
2360 // 1, 2 -> 1, 4; 4,4->4,5;
2361 sendEvent(m_nSelectionLastPara+1, nNewLastPara, css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2363 sendEvent(m_nSelectionLastPara, nNewLastPara, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2365 break;
2366 case 7:
2368 // 4,1 -> 4,3,
2369 sendEvent(m_nSelectionLastPara +1, nNewLastPara , css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2371 sendEvent(m_nSelectionLastPara, nNewLastPara, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2373 break;
2374 case 8:
2376 // 4,7 ->4,5;
2377 sendEvent(nNewLastPara + 1, m_nSelectionLastPara, css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2379 sendEvent(nNewLastPara, m_nSelectionLastPara, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2381 break;
2382 case 9:
2384 // 3,2 -> 3,1; 4,4->4,3
2385 sendEvent(nNewLastPara, m_nSelectionLastPara - 1, css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2387 sendEvent(nNewLastPara, m_nSelectionLastPara, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2389 break;
2390 case 10:
2392 // 4,7 -> 4,1
2393 sendEvent(m_nSelectionFirstPara + 1, m_nSelectionLastPara, css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2394 sendEvent(nNewLastPara, nNewFirstPara - 1, css::accessibility::AccessibleEventId::SELECTION_CHANGED);
2396 sendEvent(nNewLastPara, m_nSelectionLastPara, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED);
2398 break;
2399 default:
2400 break;
2404 // Update both old and new selection. (Regardless of how the two selections
2405 // look like, there will always be two ranges to the left and right of the
2406 // overlap---the overlap and/or the range to the right of it possibly being
2407 // empty. Only for these two ranges notifications have to be sent.)
2409 TextPaM aOldTextStart( static_cast< sal_uLong >( m_nSelectionFirstPara ), static_cast< sal_uInt16 >( m_nSelectionFirstPos ) );
2410 TextPaM aOldTextEnd( static_cast< sal_uLong >( m_nSelectionLastPara ), static_cast< sal_uInt16 >( m_nSelectionLastPos ) );
2411 TextPaM aNewTextStart( static_cast< sal_uLong >( nNewFirstPara ), static_cast< sal_uInt16 >( nNewFirstPos ) );
2412 TextPaM aNewTextEnd( static_cast< sal_uLong >( nNewLastPara ), static_cast< sal_uInt16 >( nNewLastPos ) );
2414 // justify selections
2415 justifySelection( aOldTextStart, aOldTextEnd );
2416 justifySelection( aNewTextStart, aNewTextEnd );
2418 sal_Int32 nFirst1;
2419 sal_Int32 nLast1;
2420 sal_Int32 nFirst2;
2421 sal_Int32 nLast2;
2423 if ( m_nSelectionFirstPara == -1 )
2425 // old selection not initialized yet => notify events only for new selection (if not empty)
2426 nFirst1 = aNewTextStart.GetPara();
2427 nLast1 = aNewTextEnd.GetPara() + ( aNewTextStart != aNewTextEnd ? 1 : 0 );
2428 nFirst2 = 0;
2429 nLast2 = 0;
2431 else if ( aOldTextStart == aOldTextEnd && aNewTextStart == aNewTextEnd )
2433 // old and new selection empty => no events
2434 nFirst1 = 0;
2435 nLast1 = 0;
2436 nFirst2 = 0;
2437 nLast2 = 0;
2439 else if ( aOldTextStart != aOldTextEnd && aNewTextStart == aNewTextEnd )
2441 // old selection not empty + new selection empty => notify events only for old selection
2442 nFirst1 = aOldTextStart.GetPara();
2443 nLast1 = aOldTextEnd.GetPara() + 1;
2444 nFirst2 = 0;
2445 nLast2 = 0;
2447 else if ( aOldTextStart == aOldTextEnd && aNewTextStart != aNewTextEnd )
2449 // old selection empty + new selection not empty => notify events only for new selection
2450 nFirst1 = aNewTextStart.GetPara();
2451 nLast1 = aNewTextEnd.GetPara() + 1;
2452 nFirst2 = 0;
2453 nLast2 = 0;
2455 else
2457 // old and new selection not empty => notify events for the two ranges left and right of the overlap
2458 ::std::vector< TextPaM > aTextPaMs(4);
2459 aTextPaMs[0] = aOldTextStart;
2460 aTextPaMs[1] = aOldTextEnd;
2461 aTextPaMs[2] = aNewTextStart;
2462 aTextPaMs[3] = aNewTextEnd;
2463 ::std::sort( aTextPaMs.begin(), aTextPaMs.end() );
2465 nFirst1 = aTextPaMs[0].GetPara();
2466 nLast1 = aTextPaMs[1].GetPara() + ( aTextPaMs[0] != aTextPaMs[1] ? 1 : 0 );
2468 nFirst2 = aTextPaMs[2].GetPara();
2469 nLast2 = aTextPaMs[3].GetPara() + ( aTextPaMs[2] != aTextPaMs[3] ? 1 : 0 );
2471 // adjust overlapping ranges
2472 if ( nLast1 > nFirst2 )
2473 nLast1 = nFirst2;
2476 // notify selection changes
2477 notifySelectionChange( nFirst1, nLast1 );
2478 notifySelectionChange( nFirst2, nLast2 );
2480 m_nSelectionFirstPara = nNewFirstPara;
2481 m_nSelectionFirstPos = nNewFirstPos;
2482 m_nSelectionLastPara = nNewLastPara;
2483 m_nSelectionLastPos = nNewLastPos;
2486 void Document::disposeParagraphs()
2488 for (Paragraphs::iterator aIt(m_xParagraphs->begin());
2489 aIt != m_xParagraphs->end(); ++aIt)
2491 css::uno::Reference< css::lang::XComponent > xComponent(
2492 aIt->getParagraph().get(), css::uno::UNO_QUERY);
2493 if (xComponent.is())
2494 xComponent->dispose();
2498 // static
2499 css::uno::Any Document::mapFontColor(::Color const & rColor)
2501 return css::uno::makeAny(
2502 static_cast< ::sal_Int32 >(COLORDATA_RGB(rColor.GetColor())));
2503 // FIXME keep transparency?
2506 // static
2507 ::Color Document::mapFontColor(css::uno::Any const & rColor)
2509 ::sal_Int32 nColor = 0;
2510 rColor >>= nColor;
2511 return ::Color(static_cast< ::ColorData >(nColor));
2514 // static
2515 css::uno::Any Document::mapFontWeight(::FontWeight nWeight)
2517 // Map from ::FontWeight to css::awt::FontWeight, depends on order of
2518 // elements in ::FontWeight (vcl/vclenum.hxx):
2519 static float const aWeight[]
2520 = { css::awt::FontWeight::DONTKNOW, // WEIGHT_DONTKNOW
2521 css::awt::FontWeight::THIN, // WEIGHT_THIN
2522 css::awt::FontWeight::ULTRALIGHT, // WEIGHT_ULTRALIGHT
2523 css::awt::FontWeight::LIGHT, // WEIGHT_LIGHT
2524 css::awt::FontWeight::SEMILIGHT, // WEIGHT_SEMILIGHT
2525 css::awt::FontWeight::NORMAL, // WEIGHT_NORMAL
2526 css::awt::FontWeight::NORMAL, // WEIGHT_MEDIUM
2527 css::awt::FontWeight::SEMIBOLD, // WEIGHT_SEMIBOLD
2528 css::awt::FontWeight::BOLD, // WEIGHT_BOLD
2529 css::awt::FontWeight::ULTRABOLD, // WEIGHT_ULTRABOLD
2530 css::awt::FontWeight::BLACK }; // WEIGHT_BLACK
2531 return css::uno::makeAny(aWeight[nWeight]);
2534 // static
2535 ::FontWeight Document::mapFontWeight(css::uno::Any const & rWeight)
2537 float nWeight = css::awt::FontWeight::NORMAL;
2538 rWeight >>= nWeight;
2539 return nWeight <= css::awt::FontWeight::DONTKNOW ? WEIGHT_DONTKNOW
2540 : nWeight <= css::awt::FontWeight::THIN ? WEIGHT_THIN
2541 : nWeight <= css::awt::FontWeight::ULTRALIGHT ? WEIGHT_ULTRALIGHT
2542 : nWeight <= css::awt::FontWeight::LIGHT ? WEIGHT_LIGHT
2543 : nWeight <= css::awt::FontWeight::SEMILIGHT ? WEIGHT_SEMILIGHT
2544 : nWeight <= css::awt::FontWeight::NORMAL ? WEIGHT_NORMAL
2545 : nWeight <= css::awt::FontWeight::SEMIBOLD ? WEIGHT_SEMIBOLD
2546 : nWeight <= css::awt::FontWeight::BOLD ? WEIGHT_BOLD
2547 : nWeight <= css::awt::FontWeight::ULTRABOLD ? WEIGHT_ULTRABOLD
2548 : WEIGHT_BLACK;
2553 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */