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