Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/editeng/source/accessibility/AccessibleEditableTextPara.cxx
Line
Count
Source
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
21
// Global header
22
23
24
#include <algorithm>
25
#include <utility>
26
#include <vcl/svapp.hxx>
27
#include <tools/debug.hxx>
28
#include <comphelper/diagnose_ex.hxx>
29
#include <sal/log.hxx>
30
#include <editeng/flditem.hxx>
31
#include <com/sun/star/uno/Any.hxx>
32
#include <com/sun/star/uno/Reference.hxx>
33
#include <com/sun/star/awt/Point.hpp>
34
#include <com/sun/star/awt/Rectangle.hpp>
35
#include <com/sun/star/container/XNameContainer.hpp>
36
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
37
#include <com/sun/star/i18n/Boundary.hpp>
38
#include <com/sun/star/accessibility/AccessibleRole.hpp>
39
#include <com/sun/star/accessibility/AccessibleTextType.hpp>
40
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
41
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
42
#include <comphelper/sequenceashashmap.hxx>
43
#include <unotools/accessiblerelationsethelper.hxx>
44
#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
45
#include <vcl/settings.hxx>
46
#include <i18nlangtag/languagetag.hxx>
47
48
#include <editeng/AccessibleParaManager.hxx>
49
#include <editeng/editeng.hxx>
50
#include <editeng/unoprnms.hxx>
51
#include <editeng/unoipset.hxx>
52
#include <editeng/outliner.hxx>
53
#include <editeng/unoedprx.hxx>
54
#include <editeng/unoedsrc.hxx>
55
#include <svl/eitem.hxx>
56
57
58
// Project-local header
59
60
61
#include <com/sun/star/beans/PropertyState.hpp>
62
63
#include <unopracc.hxx>
64
#include <editeng/AccessibleEditableTextPara.hxx>
65
#include "AccessibleHyperlink.hxx"
66
#include "AccessibleImageBullet.hxx"
67
68
#include <svtools/colorcfg.hxx>
69
#include <editeng/numitem.hxx>
70
#include <memory>
71
72
using namespace ::com::sun::star;
73
using namespace ::com::sun::star::beans;
74
using namespace ::com::sun::star::accessibility;
75
76
77
// AccessibleEditableTextPara implementation
78
79
80
namespace accessibility
81
{
82
83
static const SvxItemPropertySet* ImplGetSvxCharAndParaPropertiesSet()
84
0
{
85
    // PropertyMap for character and paragraph properties
86
0
    static const SfxItemPropertyMapEntry aPropMap[] =
87
0
    {
88
0
        SVX_UNOEDIT_OUTLINER_PROPERTIES,
89
0
        SVX_UNOEDIT_CHAR_PROPERTIES,
90
0
        SVX_UNOEDIT_PARA_PROPERTIES,
91
0
        SVX_UNOEDIT_NUMBERING_PROPERTY,
92
0
        { u"TextUserDefinedAttributes"_ustr,     EE_CHAR_XMLATTRIBS,     cppu::UnoType<css::container::XNameContainer>::get(),        0,     0},
93
0
        { u"ParaUserDefinedAttributes"_ustr,     EE_PARA_XMLATTRIBS,     cppu::UnoType<css::container::XNameContainer>::get(),        0,     0},
94
0
    };
95
0
    static SvxItemPropertySet aPropSet( aPropMap, EditEngine::GetGlobalItemPool() );
96
0
    return &aPropSet;
97
0
}
98
99
// #i27138# - add parameter <_pParaManager>
100
AccessibleEditableTextPara::AccessibleEditableTextPara(
101
    const rtl::Reference<comphelper::OAccessible>& rpParent,
102
    const AccessibleParaManager* _pParaManager)
103
0
    : mnParagraphIndex( 0 ),
104
0
      mnIndexInParent( 0 ),
105
0
      mpEditSource( nullptr ),
106
0
      maEEOffset( 0, 0 ),
107
0
      mpParent(rpParent),
108
0
      mpParaManager( _pParaManager )
109
0
{
110
111
    // Create the state set.
112
0
    mnStateSet  = 0;
113
114
    // these are always on
115
0
    mnStateSet |= AccessibleStateType::MULTI_LINE;
116
0
    mnStateSet |= AccessibleStateType::FOCUSABLE;
117
0
    mnStateSet |= AccessibleStateType::VISIBLE;
118
0
    mnStateSet |= AccessibleStateType::SHOWING;
119
0
    mnStateSet |= AccessibleStateType::ENABLED;
120
0
    mnStateSet |= AccessibleStateType::SENSITIVE;
121
0
}
122
123
OUString AccessibleEditableTextPara::implGetText()
124
0
{
125
0
    return GetTextRange( 0, GetTextLen() );
126
0
}
127
128
css::lang::Locale AccessibleEditableTextPara::implGetLocale()
129
0
{
130
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
131
0
               "AccessibleEditableTextPara::getLocale: paragraph index value overflow");
132
133
    // return locale of first character in the paragraph
134
0
    return LanguageTag(GetTextForwarder().GetLanguage( GetParagraphIndex(), 0 )).getLocale();
135
0
}
136
137
void AccessibleEditableTextPara::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
138
0
{
139
0
    sal_Int32 nStart, nEnd;
140
141
0
    if( GetSelection( nStart, nEnd ) )
142
0
    {
143
0
        nStartIndex = nStart;
144
0
        nEndIndex = nEnd;
145
0
    }
146
0
    else
147
0
    {
148
        // #102234# No exception, just set to 'invalid'
149
0
        nStartIndex = -1;
150
0
        nEndIndex = -1;
151
0
    }
152
0
}
153
154
void AccessibleEditableTextPara::implGetParagraphBoundary( const OUString& rText, css::i18n::Boundary& rBoundary, sal_Int32 /*nIndex*/ )
155
0
{
156
0
    SAL_INFO( "editeng", "AccessibleEditableTextPara::implGetParagraphBoundary: only a base implementation, ignoring the index" );
157
158
0
    rBoundary.startPos = 0;
159
0
    rBoundary.endPos = rText.getLength();
160
0
}
161
162
void AccessibleEditableTextPara::implGetLineBoundary( const OUString&, css::i18n::Boundary& rBoundary, sal_Int32 nIndex )
163
0
{
164
0
    SvxTextForwarder&   rCacheTF = GetTextForwarder();
165
0
    const sal_Int32     nParaIndex = GetParagraphIndex();
166
167
0
    DBG_ASSERT(nParaIndex >= 0,
168
0
               "AccessibleEditableTextPara::implGetLineBoundary: paragraph index value overflow");
169
170
0
    const sal_Int32 nTextLen = rCacheTF.GetTextLen( nParaIndex );
171
172
0
    CheckPosition(nIndex);
173
174
0
    rBoundary.startPos = rBoundary.endPos = -1;
175
176
0
    const sal_Int32 nLineCount=rCacheTF.GetLineCount( nParaIndex );
177
178
0
    if( nIndex == nTextLen )
179
0
    {
180
        // #i17014# Special-casing one-behind-the-end character
181
0
        if( nLineCount <= 1 )
182
0
            rBoundary.startPos = 0;
183
0
        else
184
0
            rBoundary.startPos = nTextLen - rCacheTF.GetLineLen( nParaIndex,
185
0
                                                                 nLineCount-1 );
186
187
0
        rBoundary.endPos = nTextLen;
188
0
    }
189
0
    else
190
0
    {
191
        // normal line search
192
0
        sal_Int32 nLine;
193
0
        sal_Int32 nCurIndex;
194
0
        for( nLine=0, nCurIndex=0; nLine<nLineCount; ++nLine )
195
0
        {
196
0
            nCurIndex += rCacheTF.GetLineLen( nParaIndex, nLine);
197
198
0
            if( nCurIndex > nIndex )
199
0
            {
200
0
                rBoundary.startPos = nCurIndex - rCacheTF.GetLineLen( nParaIndex, nLine);
201
0
                rBoundary.endPos = nCurIndex;
202
0
                break;
203
0
            }
204
0
        }
205
0
    }
206
0
}
207
208
209
void AccessibleEditableTextPara::SetIndexInParent( sal_Int32 nIndex )
210
0
{
211
0
    mnIndexInParent = nIndex;
212
0
}
213
214
215
void AccessibleEditableTextPara::SetParagraphIndex( sal_Int32 nIndex )
216
0
{
217
0
    sal_Int32 nOldIndex = mnParagraphIndex;
218
219
0
    mnParagraphIndex = nIndex;
220
221
0
    auto aChild( maImageBullet.get() );
222
0
    if( aChild.is() )
223
0
        aChild->SetParagraphIndex(mnParagraphIndex);
224
225
0
    try
226
0
    {
227
0
        if( nOldIndex != nIndex )
228
0
        {
229
0
            uno::Any aOldDesc;
230
0
            uno::Any aOldName;
231
232
0
            try
233
0
            {
234
0
                aOldDesc <<= getAccessibleDescription();
235
0
                aOldName <<= getAccessibleName();
236
0
            }
237
0
            catch (const uno::Exception&) // optional behaviour
238
0
            {
239
0
            }
240
            // index and therefore description changed
241
0
            FireEvent( AccessibleEventId::DESCRIPTION_CHANGED, uno::Any( getAccessibleDescription() ), aOldDesc );
242
0
            FireEvent( AccessibleEventId::NAME_CHANGED, uno::Any( getAccessibleName() ), aOldName );
243
0
        }
244
0
    }
245
0
    catch (const uno::Exception&) // optional behaviour
246
0
    {
247
0
    }
248
0
}
249
250
251
void SAL_CALL AccessibleEditableTextPara::dispose()
252
0
{
253
0
    rtl::Reference<AccessibleImageBullet> xBullet = maImageBullet.get();
254
0
    if (xBullet.is())
255
0
        xBullet->dispose();
256
0
    maImageBullet.clear();
257
258
0
    mpParent = nullptr;
259
0
    mpEditSource = nullptr;
260
261
0
    comphelper::OAccessible::dispose();
262
0
}
263
264
void AccessibleEditableTextPara::SetEditSource( SvxEditSourceAdapter* pEditSource )
265
0
{
266
0
    auto aChild( maImageBullet.get() );
267
0
    if( aChild.is() )
268
0
        aChild->SetEditSource(pEditSource);
269
270
0
    if( !pEditSource )
271
0
    {
272
        // going defunc
273
0
        UnSetState( AccessibleStateType::SHOWING );
274
0
        UnSetState( AccessibleStateType::VISIBLE );
275
0
        SetState( AccessibleStateType::INVALID );
276
0
        SetState( AccessibleStateType::DEFUNC );
277
0
    }
278
0
    mpEditSource = pEditSource;
279
    // #108900# Init last text content
280
0
    try
281
0
    {
282
0
        TextChanged();
283
0
    }
284
0
    catch (const uno::RuntimeException&)
285
0
    {
286
0
    }
287
0
}
288
289
ESelection AccessibleEditableTextPara::MakeSelection( sal_Int32 nStartEEIndex, sal_Int32 nEndEEIndex )
290
0
{
291
    // check overflow
292
0
    DBG_ASSERT(nStartEEIndex >= 0 &&
293
0
               nEndEEIndex >= 0 &&
294
0
               GetParagraphIndex() >= 0,
295
0
               "AccessibleEditableTextPara::MakeSelection: index value overflow");
296
297
0
    sal_Int32 nParaIndex = GetParagraphIndex();
298
0
    return ESelection(nParaIndex, nStartEEIndex, nParaIndex, nEndEEIndex);
299
0
}
300
301
ESelection AccessibleEditableTextPara::MakeSelection( sal_Int32 nEEIndex )
302
0
{
303
0
    return MakeSelection( nEEIndex, nEEIndex+1 );
304
0
}
305
306
ESelection AccessibleEditableTextPara::MakeCursor( sal_Int32 nEEIndex )
307
0
{
308
0
    return MakeSelection( nEEIndex, nEEIndex );
309
0
}
310
311
void AccessibleEditableTextPara::CheckIndex( sal_Int32 nIndex )
312
0
{
313
0
    if( nIndex < 0 || nIndex >= getCharacterCount() )
314
0
        throw lang::IndexOutOfBoundsException(u"AccessibleEditableTextPara: character index out of bounds"_ustr,
315
0
                                              getXWeak() );
316
0
}
317
318
void AccessibleEditableTextPara::CheckPosition( sal_Int32 nIndex )
319
0
{
320
0
    if( nIndex < 0 || nIndex > getCharacterCount() )
321
0
        throw lang::IndexOutOfBoundsException(u"AccessibleEditableTextPara: character position out of bounds"_ustr,
322
0
                                              getXWeak() );
323
0
}
324
325
void AccessibleEditableTextPara::CheckRange( sal_Int32 nStart, sal_Int32 nEnd )
326
0
{
327
0
    CheckPosition( nStart );
328
0
    CheckPosition( nEnd );
329
0
}
330
331
bool AccessibleEditableTextPara::GetSelection(sal_Int32 &nStartPos, sal_Int32 &nEndPos)
332
0
{
333
0
    ESelection aSelection;
334
0
    sal_Int32 nPara = GetParagraphIndex();
335
0
    if( !GetEditViewForwarder().GetSelection( aSelection ) )
336
0
        return false;
337
338
0
    aSelection.Adjust();
339
340
0
    if (aSelection.start.nPara > nPara || aSelection.end.nPara < nPara)
341
0
        return false;
342
343
0
    if (nPara == aSelection.start.nPara)
344
0
        nStartPos = aSelection.start.nIndex;
345
0
    else
346
0
        nStartPos = 0;
347
348
0
    if (nPara == aSelection.end.nPara)
349
0
        nEndPos = aSelection.end.nIndex;
350
0
    else
351
0
        nEndPos = GetTextLen();
352
353
0
    return true;
354
0
}
355
356
OUString AccessibleEditableTextPara::GetTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
357
0
{
358
0
    return GetTextForwarder().GetText( MakeSelection(nStartIndex, nEndIndex) );
359
0
}
360
361
sal_Int32 AccessibleEditableTextPara::GetTextLen() const
362
0
{
363
0
    return GetTextForwarder().GetTextLen(GetParagraphIndex());
364
0
}
365
366
SvxEditSourceAdapter& AccessibleEditableTextPara::GetEditSource() const
367
0
{
368
0
    if( !mpEditSource )
369
0
        throw uno::RuntimeException(u"No edit source, object is defunct"_ustr,
370
0
                                     const_cast< AccessibleEditableTextPara* > (this)->getXWeak() );
371
0
    return *mpEditSource;
372
0
}
373
374
SvxAccessibleTextAdapter& AccessibleEditableTextPara::GetTextForwarder() const
375
0
{
376
0
    SvxEditSourceAdapter& rEditSource = GetEditSource();
377
0
    SvxAccessibleTextAdapter* pTextForwarder = rEditSource.GetTextForwarderAdapter();
378
379
0
    if( !pTextForwarder )
380
0
        throw uno::RuntimeException(u"Unable to fetch text forwarder, object is defunct"_ustr,
381
0
                                    const_cast< AccessibleEditableTextPara* > (this)->getXWeak() );
382
383
0
    if( !pTextForwarder->IsValid() )
384
0
        throw uno::RuntimeException(u"Text forwarder is invalid, object is defunct"_ustr,
385
0
                                    const_cast< AccessibleEditableTextPara* > (this)->getXWeak() );
386
0
    return *pTextForwarder;
387
0
}
388
389
SvxViewForwarder& AccessibleEditableTextPara::GetViewForwarder() const
390
0
{
391
0
    SvxEditSource& rEditSource = GetEditSource();
392
0
    SvxViewForwarder* pViewForwarder = rEditSource.GetViewForwarder();
393
394
0
    if( !pViewForwarder )
395
0
    {
396
0
        throw uno::RuntimeException(u"Unable to fetch view forwarder, object is defunct"_ustr,
397
0
                                    const_cast< AccessibleEditableTextPara* > (this)->getXWeak() );
398
0
    }
399
400
0
    if( !pViewForwarder->IsValid() )
401
0
        throw uno::RuntimeException(u"View forwarder is invalid, object is defunct"_ustr,
402
0
                                    const_cast< AccessibleEditableTextPara* > (this)->getXWeak() );
403
0
    return *pViewForwarder;
404
0
}
405
406
SvxAccessibleTextEditViewAdapter& AccessibleEditableTextPara::GetEditViewForwarder( bool bCreate ) const
407
0
{
408
0
    SvxEditSourceAdapter& rEditSource = GetEditSource();
409
0
    SvxAccessibleTextEditViewAdapter* pTextEditViewForwarder = rEditSource.GetEditViewForwarderAdapter( bCreate );
410
411
0
    if( !pTextEditViewForwarder )
412
0
    {
413
0
        if( bCreate )
414
0
            throw uno::RuntimeException(u"Unable to fetch view forwarder, object is defunct"_ustr,
415
0
                                        const_cast< AccessibleEditableTextPara* > (this)->getXWeak() );
416
0
        else
417
0
            throw uno::RuntimeException(u"No view forwarder, object not in edit mode"_ustr,
418
0
                                        const_cast< AccessibleEditableTextPara* > (this)->getXWeak() );
419
0
    }
420
421
0
    if( pTextEditViewForwarder->IsValid() )
422
0
        return *pTextEditViewForwarder;
423
0
    else
424
0
    {
425
0
        if( bCreate )
426
0
            throw uno::RuntimeException(u"View forwarder is invalid, object is defunct"_ustr,
427
0
                                        const_cast< AccessibleEditableTextPara* > (this)->getXWeak() );
428
0
        else
429
0
            throw uno::RuntimeException(u"View forwarder is invalid, object not in edit mode"_ustr,
430
0
                                        const_cast< AccessibleEditableTextPara* > (this)->getXWeak() );
431
0
    }
432
0
}
433
434
bool AccessibleEditableTextPara::HaveEditView() const
435
0
{
436
0
    SvxEditSource& rEditSource = GetEditSource();
437
0
    SvxEditViewForwarder* pViewForwarder = rEditSource.GetEditViewForwarder();
438
439
0
    if( !pViewForwarder )
440
0
        return false;
441
442
0
    if( !pViewForwarder->IsValid() )
443
0
        return false;
444
445
0
    return true;
446
0
}
447
448
bool AccessibleEditableTextPara::HaveChildren()
449
0
{
450
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
451
0
               "AccessibleEditableTextPara::HaveChildren: paragraph index value overflow");
452
453
0
    return GetTextForwarder().HaveImageBullet( GetParagraphIndex() );
454
0
}
455
456
sal_Int32 AccessibleEditableTextPara::GetBulletTextLength() const
457
0
{
458
0
    sal_Int32 nBulletLen = 0;
459
0
    EBulletInfo aBulletInfo = GetTextForwarder().GetBulletInfo(GetParagraphIndex());
460
0
    if (aBulletInfo.nParagraph != EE_PARA_MAX && aBulletInfo.bVisible)
461
0
        nBulletLen = aBulletInfo.aText.getLength();
462
0
    return nBulletLen;
463
0
}
464
465
tools::Rectangle AccessibleEditableTextPara::LogicToPixel( const tools::Rectangle& rRect, const MapMode& rMapMode, SvxViewForwarder const & rForwarder )
466
0
{
467
    // convert to screen coordinates
468
0
    return tools::Rectangle( rForwarder.LogicToPixel( rRect.TopLeft(), rMapMode ),
469
0
                      rForwarder.LogicToPixel( rRect.BottomRight(), rMapMode ) );
470
0
}
471
472
473
void AccessibleEditableTextPara::SetEEOffset( const Point& rOffset )
474
0
{
475
0
    auto aChild( maImageBullet.get() );
476
0
    if( aChild.is() )
477
0
        aChild->SetEEOffset(rOffset);
478
479
0
    maEEOffset = rOffset;
480
0
}
481
482
void AccessibleEditableTextPara::FireEvent(const sal_Int16 nEventId, const uno::Any& rNewValue, const uno::Any& rOldValue)
483
0
{
484
0
    NotifyAccessibleEvent(nEventId, rOldValue, rNewValue);
485
0
}
486
487
void AccessibleEditableTextPara::SetState( const sal_Int64 nStateId )
488
0
{
489
0
    if( !(mnStateSet & nStateId) )
490
0
    {
491
0
        mnStateSet |= nStateId;
492
0
        FireEvent( AccessibleEventId::STATE_CHANGED, uno::Any( nStateId ) );
493
0
    }
494
0
}
495
496
void AccessibleEditableTextPara::UnSetState( const sal_Int64 nStateId )
497
0
{
498
0
    if( mnStateSet & nStateId )
499
0
    {
500
0
        mnStateSet &= ~nStateId;
501
0
        FireEvent( AccessibleEventId::STATE_CHANGED, uno::Any(), uno::Any( nStateId ) );
502
0
    }
503
0
}
504
505
void AccessibleEditableTextPara::TextChanged()
506
0
{
507
0
    OUString aCurrentString( implGetText() );
508
0
    uno::Any aDeleted;
509
0
    uno::Any aInserted;
510
0
    if( OCommonAccessibleText::implInitTextChangedEvent( maLastTextString, aCurrentString,
511
0
                                                         aDeleted, aInserted) )
512
0
    {
513
0
        FireEvent( AccessibleEventId::TEXT_CHANGED, aInserted, aDeleted );
514
0
        maLastTextString = aCurrentString;
515
0
    }
516
0
}
517
518
bool AccessibleEditableTextPara::GetAttributeRun( sal_Int32& nStartIndex, sal_Int32& nEndIndex, sal_Int32 nIndex )
519
0
{
520
0
    DBG_ASSERT(nIndex >= 0,
521
0
               "AccessibleEditableTextPara::GetAttributeRun: index value overflow");
522
523
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
524
0
               "AccessibleEditableTextPara::getLocale: paragraph index value overflow");
525
526
0
    return GetTextForwarder().GetAttributeRun( nStartIndex,
527
0
                                               nEndIndex,
528
0
                                               GetParagraphIndex(),
529
0
                                               nIndex );
530
0
}
531
532
// XAccessibleContext
533
sal_Int64 SAL_CALL AccessibleEditableTextPara::getAccessibleChildCount()
534
0
{
535
0
    SolarMutexGuard aGuard;
536
537
0
    return HaveChildren() ? 1 : 0;
538
0
}
539
540
uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleChild( sal_Int64 i )
541
0
{
542
0
    SolarMutexGuard aGuard;
543
544
0
    if( !HaveChildren() )
545
0
        throw lang::IndexOutOfBoundsException(u"No children available"_ustr,
546
0
                                              getXWeak() );
547
548
0
    if( i != 0 )
549
0
        throw lang::IndexOutOfBoundsException(u"Invalid child index"_ustr,
550
0
                                              getXWeak() );
551
552
0
    auto aChild( maImageBullet.get() );
553
554
0
    if( !aChild.is() )
555
0
    {
556
        // there is no hard reference available, create object then
557
0
        aChild = new AccessibleImageBullet(this, i);
558
559
0
        aChild->SetEditSource( &GetEditSource() );
560
0
        aChild->SetParagraphIndex( GetParagraphIndex() );
561
562
0
        maImageBullet = aChild.get();
563
0
    }
564
565
0
    return aChild;
566
0
}
567
568
uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleParent()
569
0
{
570
0
    SAL_WARN_IF(!mpParent.is(), "editeng", "AccessibleEditableTextPara::getAccessibleParent: no frontend set, did somebody forgot to call AccessibleTextHelper::SetEventSource()?");
571
572
0
    return mpParent;
573
0
}
574
575
sal_Int64 SAL_CALL AccessibleEditableTextPara::getAccessibleIndexInParent()
576
0
{
577
0
    return mnIndexInParent;
578
0
}
579
580
sal_Int16 SAL_CALL AccessibleEditableTextPara::getAccessibleRole()
581
0
{
582
0
    return AccessibleRole::PARAGRAPH;
583
0
}
584
585
OUString SAL_CALL AccessibleEditableTextPara::getAccessibleDescription()
586
0
{
587
0
    return OUString();
588
0
}
589
590
OUString SAL_CALL AccessibleEditableTextPara::getAccessibleName()
591
0
{
592
    //See tdf#101003 before implementing a body
593
0
    return OUString();
594
0
}
595
596
uno::Reference< XAccessibleRelationSet > SAL_CALL AccessibleEditableTextPara::getAccessibleRelationSet()
597
0
{
598
    // #i27138# - provide relations CONTENT_FLOWS_FROM
599
    // and CONTENT_FLOWS_TO
600
0
    if ( mpParaManager )
601
0
    {
602
0
        rtl::Reference<utl::AccessibleRelationSetHelper> pAccRelSetHelper =
603
0
                                    new utl::AccessibleRelationSetHelper();
604
0
        sal_Int32 nMyParaIndex( GetParagraphIndex() );
605
        // relation CONTENT_FLOWS_FROM
606
0
        if ( nMyParaIndex > 0 &&
607
0
             mpParaManager->IsReferencable( nMyParaIndex - 1 ) )
608
0
        {
609
0
            uno::Sequence<uno::Reference<XAccessible>> aSequence
610
0
                { mpParaManager->GetChild( nMyParaIndex - 1 ).first.get() };
611
0
            AccessibleRelation aAccRel(AccessibleRelationType_CONTENT_FLOWS_FROM,
612
0
                                       aSequence );
613
0
            pAccRelSetHelper->AddRelation( aAccRel );
614
0
        }
615
616
        // relation CONTENT_FLOWS_TO
617
0
        if ( (nMyParaIndex + 1) < mpParaManager->GetNum() &&
618
0
             mpParaManager->IsReferencable( nMyParaIndex + 1 ) )
619
0
        {
620
0
            uno::Sequence<uno::Reference<XAccessible>> aSequence
621
0
                { mpParaManager->GetChild( nMyParaIndex + 1 ).first.get() };
622
0
            AccessibleRelation aAccRel(AccessibleRelationType_CONTENT_FLOWS_TO,
623
0
                                       aSequence );
624
0
            pAccRelSetHelper->AddRelation( aAccRel );
625
0
        }
626
627
0
        return pAccRelSetHelper;
628
0
    }
629
0
    else
630
0
    {
631
        // no relations, therefore empty
632
0
        return uno::Reference< XAccessibleRelationSet >();
633
0
    }
634
0
}
635
636
static uno::Sequence< OUString > const & getAttributeNames()
637
0
{
638
0
    static const uno::Sequence<OUString> aNames{
639
0
        u"CharColor"_ustr,
640
0
        u"CharContoured"_ustr,
641
0
        u"CharEmphasis"_ustr,
642
0
        u"CharEscapement"_ustr,
643
0
        u"CharFontName"_ustr,
644
0
        u"CharHeight"_ustr,
645
0
        u"CharPosture"_ustr,
646
0
        u"CharShadowed"_ustr,
647
0
        u"CharStrikeout"_ustr,
648
0
        u"CharCaseMap"_ustr,
649
0
        u"CharUnderline"_ustr,
650
0
        u"CharUnderlineColor"_ustr,
651
0
        u"CharWeight"_ustr,
652
0
        u"NumberingLevel"_ustr,
653
0
        u"NumberingRules"_ustr,
654
0
        u"ParaAdjust"_ustr,
655
0
        u"ParaBottomMargin"_ustr,
656
0
        u"ParaFirstLineIndent"_ustr,
657
0
        u"ParaLeftMargin"_ustr,
658
0
        u"ParaLineSpacing"_ustr,
659
0
        u"ParaRightMargin"_ustr,
660
0
        u"ParaTabStops"_ustr};
661
662
0
    return aNames;
663
0
}
664
665
namespace {
666
667
struct IndexCompare
668
{
669
    const uno::Sequence<beans::PropertyValue>& m_rValues;
670
    explicit IndexCompare(const uno::Sequence<beans::PropertyValue>& rValues)
671
0
        : m_rValues(rValues)
672
0
    {
673
0
    }
674
    bool operator() ( sal_Int32 a, sal_Int32 b ) const
675
0
    {
676
0
        return m_rValues[a].Name < m_rValues[b].Name;
677
0
    }
678
};
679
680
}
681
}
682
683
namespace
684
{
685
OUString GetFieldTypeNameFromField(EFieldInfo const &ree)
686
0
{
687
0
    OUString strFldType;
688
0
    sal_Int32 nFieldType = -1;
689
0
    if (ree.pFieldItem)
690
0
    {
691
        // So we get a field, check its type now.
692
0
        nFieldType = ree.pFieldItem->GetField()->GetClassId() ;
693
0
    }
694
0
    switch (nFieldType)
695
0
    {
696
0
        case text::textfield::Type::DATE:
697
0
        {
698
0
            const SvxDateField* pDateField = static_cast< const SvxDateField* >(ree.pFieldItem->GetField());
699
0
            if (pDateField)
700
0
            {
701
0
                if (pDateField->GetType() == SvxDateType::Fix)
702
0
                    strFldType = "date (fixed)";
703
0
                else if (pDateField->GetType() == SvxDateType::Var)
704
0
                    strFldType = "date (variable)";
705
0
            }
706
0
            break;
707
0
        }
708
0
        case text::textfield::Type::PAGE:
709
0
            strFldType = "page-number";
710
0
            break;
711
        //support the sheet name & pages fields
712
0
        case text::textfield::Type::PAGES:
713
0
            strFldType = "page-count";
714
0
            break;
715
0
        case text::textfield::Type::TABLE:
716
0
            strFldType = "sheet-name";
717
0
            break;
718
        //End
719
0
        case text::textfield::Type::TIME:
720
0
            strFldType = "time";
721
0
            break;
722
0
        case text::textfield::Type::EXTENDED_TIME:
723
0
        {
724
0
            const SvxExtTimeField* pTimeField = static_cast< const SvxExtTimeField* >(ree.pFieldItem->GetField());
725
0
            if (pTimeField)
726
0
            {
727
0
                if (pTimeField->GetType() == SvxTimeType::Fix)
728
0
                    strFldType = "time (fixed)";
729
0
                else if (pTimeField->GetType() == SvxTimeType::Var)
730
0
                    strFldType = "time (variable)";
731
0
            }
732
0
            break;
733
0
        }
734
0
        case text::textfield::Type::AUTHOR:
735
0
            strFldType = "author";
736
0
            break;
737
0
        case text::textfield::Type::EXTENDED_FILE:
738
0
        case text::textfield::Type::DOCINFO_TITLE:
739
0
            strFldType = "file name";
740
0
            break;
741
0
        case text::textfield::Type::DOCINFO_CUSTOM:
742
0
            strFldType = "custom document property";
743
0
            break;
744
0
        default:
745
0
            break;
746
0
    }
747
0
    return strFldType;
748
0
}
749
}
750
751
namespace accessibility
752
{
753
OUString AccessibleEditableTextPara::GetFieldTypeNameAtIndex(sal_Int32 nIndex)
754
0
{
755
0
    SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder();
756
    //For field object info
757
0
    sal_Int32 nParaIndex = GetParagraphIndex();
758
0
    sal_Int32 nAllFieldLen = 0;
759
0
    std::vector<EFieldInfo> aFieldInfos = rCacheTF.GetFieldInfo(nParaIndex);
760
0
    for (const EFieldInfo& ree : aFieldInfos)
761
0
    {
762
0
        sal_Int32 reeBegin = ree.aPosition.nIndex + nAllFieldLen;
763
0
        sal_Int32 reeEnd = reeBegin + ree.aCurrentText.getLength();
764
0
        nAllFieldLen += (ree.aCurrentText.getLength() - 1);
765
0
        if (nIndex < reeBegin)
766
0
            break;
767
0
        if (nIndex < reeEnd)
768
0
            return GetFieldTypeNameFromField(ree);
769
0
    }
770
0
    return OUString();
771
0
}
772
773
sal_Int64 SAL_CALL AccessibleEditableTextPara::getAccessibleStateSet()
774
0
{
775
0
    SolarMutexGuard aGuard;
776
777
    // Create a copy of the state set and return it.
778
779
0
    sal_Int64 nParentStates = 0;
780
0
    if (getAccessibleParent().is())
781
0
    {
782
0
        uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
783
0
        nParentStates = xParentContext->getAccessibleStateSet();
784
0
    }
785
0
    if (nParentStates & AccessibleStateType::EDITABLE)
786
0
    {
787
0
        mnStateSet |= AccessibleStateType::EDITABLE;
788
0
    }
789
0
    return mnStateSet;
790
0
}
791
792
lang::Locale SAL_CALL AccessibleEditableTextPara::getLocale()
793
0
{
794
0
    SolarMutexGuard aGuard;
795
796
0
    return implGetLocale();
797
0
}
798
799
// XAccessibleComponent
800
801
uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleAtPoint( const awt::Point& _aPoint )
802
0
{
803
0
    SolarMutexGuard aGuard;
804
805
0
    if( HaveChildren() )
806
0
    {
807
        // #103862# No longer need to make given position relative
808
0
        Point aPoint( _aPoint.X, _aPoint.Y );
809
810
        // respect EditEngine offset to surrounding shape/cell
811
0
        aPoint -= GetEEOffset();
812
813
        // convert to EditEngine coordinate system
814
0
        SvxTextForwarder& rCacheTF = GetTextForwarder();
815
0
        Point aLogPoint( GetViewForwarder().PixelToLogic( aPoint, rCacheTF.GetMapMode() ) );
816
817
0
        EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(GetParagraphIndex());
818
819
0
        if( aBulletInfo.nParagraph != EE_PARA_MAX &&
820
0
            aBulletInfo.bVisible &&
821
0
            aBulletInfo.nType == SVX_NUM_BITMAP )
822
0
        {
823
0
            tools::Rectangle aRect = aBulletInfo.aBounds;
824
825
0
            if( aRect.Contains( aLogPoint ) )
826
0
                return getAccessibleChild(0);
827
0
        }
828
0
    }
829
830
    // no children at all, or none at given position
831
0
    return uno::Reference< XAccessible >();
832
0
}
833
834
awt::Rectangle AccessibleEditableTextPara::implGetBounds()
835
0
{
836
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
837
0
               "AccessibleEditableTextPara::implGetBounds: index value overflow");
838
839
0
    SvxTextForwarder& rCacheTF = GetTextForwarder();
840
0
    tools::Rectangle aRect = rCacheTF.GetParaBounds( GetParagraphIndex() );
841
842
    // convert to screen coordinates
843
0
    tools::Rectangle aScreenRect = AccessibleEditableTextPara::LogicToPixel( aRect,
844
0
                                                                      rCacheTF.GetMapMode(),
845
0
                                                                      GetViewForwarder() );
846
847
    // offset from shape/cell
848
0
    Point aOffset = GetEEOffset();
849
850
0
    return awt::Rectangle( aScreenRect.Left() + aOffset.X(),
851
0
                           aScreenRect.Top() + aOffset.Y(),
852
0
                           aScreenRect.GetSize().Width(),
853
0
                           aScreenRect.GetSize().Height() );
854
0
}
855
856
void SAL_CALL AccessibleEditableTextPara::grabFocus(  )
857
0
{
858
    // set cursor to this paragraph
859
0
    setSelection(0,0);
860
0
}
861
862
sal_Int32 SAL_CALL AccessibleEditableTextPara::getForeground(  )
863
0
{
864
    // #104444# Added to XAccessibleComponent interface
865
0
    svtools::ColorConfig aColorConfig;
866
0
    Color nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor;
867
0
    return static_cast<sal_Int32>(nColor);
868
0
}
869
870
sal_Int32 SAL_CALL AccessibleEditableTextPara::getBackground(  )
871
0
{
872
    // #104444# Added to XAccessibleComponent interface
873
0
    Color aColor( Application::GetSettings().GetStyleSettings().GetWindowColor() );
874
875
    // the background is transparent
876
0
    aColor.SetAlpha(0);
877
878
0
    return static_cast<sal_Int32>( aColor );
879
0
}
880
881
// XAccessibleText
882
sal_Int32 SAL_CALL AccessibleEditableTextPara::getCaretPosition()
883
0
{
884
0
    SolarMutexGuard aGuard;
885
886
0
    if( !HaveEditView() )
887
0
        return -1;
888
889
0
    ESelection aSelection;
890
0
    if( GetEditViewForwarder().GetSelection( aSelection ) &&
891
0
        GetParagraphIndex() == aSelection.end.nPara )
892
0
    {
893
        // caret is always nEndPara,nEndPos
894
0
        EBulletInfo aBulletInfo = GetTextForwarder().GetBulletInfo(GetParagraphIndex());
895
0
        if( aBulletInfo.nParagraph != EE_PARA_MAX &&
896
0
            aBulletInfo.bVisible &&
897
0
            aBulletInfo.nType != SVX_NUM_BITMAP )
898
0
        {
899
0
            sal_Int32 nBulletLen = aBulletInfo.aText.getLength();
900
0
            if( aSelection.end.nIndex - nBulletLen >= 0 )
901
0
                return aSelection.end.nIndex - nBulletLen;
902
0
        }
903
0
        return aSelection.end.nIndex;
904
0
    }
905
906
    // not within this paragraph
907
0
    return -1;
908
0
}
909
910
sal_Bool SAL_CALL AccessibleEditableTextPara::setCaretPosition( sal_Int32 nIndex )
911
0
{
912
0
    return setSelection(nIndex, nIndex);
913
0
}
914
915
sal_Unicode SAL_CALL AccessibleEditableTextPara::getCharacter( sal_Int32 nIndex )
916
0
{
917
0
    SolarMutexGuard aGuard;
918
919
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
920
0
               "AccessibleEditableTextPara::getCharacter: index value overflow");
921
922
0
    return OCommonAccessibleText::implGetCharacter( implGetText(), nIndex );
923
0
}
924
925
uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getCharacterAttributes( sal_Int32 nIndex, const css::uno::Sequence< OUString >& rRequestedAttributes )
926
0
{
927
0
    SolarMutexGuard aGuard;
928
929
    //Skip the bullet range to ignore the bullet text
930
0
    SvxTextForwarder& rCacheTF = GetTextForwarder();
931
0
    EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(GetParagraphIndex());
932
0
    if (aBulletInfo.bVisible)
933
0
        nIndex += aBulletInfo.aText.getLength();
934
0
    CheckIndex(nIndex); // may throw IndexOutOfBoundsException
935
936
0
    bool bSupplementalMode = false;
937
0
    uno::Sequence< OUString > aPropertyNames = rRequestedAttributes;
938
0
    if (!aPropertyNames.hasElements())
939
0
    {
940
0
        bSupplementalMode = true;
941
0
        aPropertyNames = getAttributeNames();
942
0
    }
943
944
    // get default attributes...
945
0
    ::comphelper::SequenceAsHashMap aPropHashMap( getDefaultAttributes( aPropertyNames ) );
946
947
    // ... and override them with the direct attributes from the specific position
948
0
    const uno::Sequence< beans::PropertyValue > aRunAttribs( getRunAttributes( nIndex, aPropertyNames ) );
949
0
    for (auto const& rRunAttrib : aRunAttribs)
950
0
    {
951
0
        aPropHashMap[ rRunAttrib.Name ] = rRunAttrib.Value; //!! should not only be the value !!
952
0
    }
953
954
    // get resulting sequence
955
0
    uno::Sequence< beans::PropertyValue > aRes;
956
0
    aPropHashMap >> aRes;
957
958
    // since SequenceAsHashMap ignores property handles and property state
959
    // we have to restore the property state here (property handles are
960
    // of no use to the accessibility API).
961
0
    for (beans::PropertyValue & rRes : asNonConstRange(aRes))
962
0
    {
963
0
        bool bIsDirectVal = false;
964
0
        for (auto const& rRunAttrib : aRunAttribs)
965
0
        {
966
0
            bIsDirectVal = rRes.Name == rRunAttrib.Name;
967
0
            if (bIsDirectVal)
968
0
                break;
969
0
        }
970
0
        rRes.Handle = -1;
971
0
        rRes.State  = bIsDirectVal ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
972
0
    }
973
0
    if( bSupplementalMode )
974
0
    {
975
0
        _correctValues( aRes );
976
        // NumberingPrefix
977
0
        sal_Int32 nRes = aRes.getLength();
978
0
        aRes.realloc( nRes + 1 );
979
0
        beans::PropertyValue &rRes = aRes.getArray()[nRes];
980
0
        rRes.Name = "NumberingPrefix";
981
0
        OUString numStr;
982
0
        if (aBulletInfo.nType != SVX_NUM_CHAR_SPECIAL && aBulletInfo.nType != SVX_NUM_BITMAP)
983
0
            numStr = aBulletInfo.aText;
984
0
        rRes.Value <<= numStr;
985
0
        rRes.Handle = -1;
986
0
        rRes.State = PropertyState_DIRECT_VALUE;
987
        //For field object.
988
0
        OUString strFieldType = GetFieldTypeNameAtIndex(nIndex);
989
0
        if (!strFieldType.isEmpty())
990
0
        {
991
0
            nRes = aRes.getLength();
992
0
            aRes.realloc( nRes + 1 );
993
0
            beans::PropertyValue &rResField = aRes.getArray()[nRes];
994
0
            rResField.Name = "FieldType";
995
0
            rResField.Value <<= strFieldType.toAsciiLowerCase();
996
0
            rResField.Handle = -1;
997
0
            rResField.State = PropertyState_DIRECT_VALUE;
998
0
        }
999
        //sort property values
1000
        // build sorted index array
1001
0
        sal_Int32 nLength = aRes.getLength();
1002
0
        std::vector<sal_Int32> indices(nLength);
1003
0
        std::iota(indices.begin(), indices.end(), 0);
1004
0
        std::sort(indices.begin(), indices.end(), IndexCompare(aRes));
1005
        // create sorted sequences according to index array
1006
0
        uno::Sequence<beans::PropertyValue> aNewValues( nLength );
1007
0
        std::transform(indices.begin(), indices.end(), aNewValues.getArray(),
1008
0
                       [&aRes](sal_Int32 index) -> const beans::PropertyValue& { return aRes[index]; });
1009
1010
0
        return aNewValues;
1011
0
    }
1012
0
    return aRes;
1013
0
}
1014
1015
awt::Rectangle SAL_CALL AccessibleEditableTextPara::getCharacterBounds( sal_Int32 nIndex )
1016
0
{
1017
0
    SolarMutexGuard aGuard;
1018
1019
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
1020
0
               "AccessibleEditableTextPara::getCharacterBounds: index value overflow");
1021
1022
    // #108900# Have position semantics now for nIndex, as
1023
    // one-past-the-end values are legal, too.
1024
0
    CheckPosition( nIndex );
1025
1026
0
    SvxTextForwarder& rCacheTF = GetTextForwarder();
1027
0
    tools::Rectangle aRect = rCacheTF.GetCharBounds(GetParagraphIndex(), nIndex);
1028
1029
    // convert to screen
1030
0
    tools::Rectangle aScreenRect = AccessibleEditableTextPara::LogicToPixel( aRect,
1031
0
                                                                      rCacheTF.GetMapMode(),
1032
0
                                                                      GetViewForwarder() );
1033
    // #109864# offset from parent (paragraph), but in screen
1034
    // coordinates. This makes sure the internal text offset in
1035
    // the outline view forwarder gets cancelled out here
1036
0
    awt::Rectangle aParaRect( getBounds() );
1037
0
    aScreenRect.Move( -aParaRect.X, -aParaRect.Y );
1038
1039
    // offset from shape/cell
1040
0
    Point aOffset = GetEEOffset();
1041
1042
0
    return awt::Rectangle( aScreenRect.Left() + aOffset.X(),
1043
0
                           aScreenRect.Top() + aOffset.Y(),
1044
0
                           aScreenRect.GetSize().Width(),
1045
0
                           aScreenRect.GetSize().Height() );
1046
0
}
1047
1048
sal_Int32 SAL_CALL AccessibleEditableTextPara::getCharacterCount()
1049
0
{
1050
0
    SolarMutexGuard aGuard;
1051
1052
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
1053
0
               "AccessibleEditableTextPara::getCharacterCount: index value overflow");
1054
1055
0
    return implGetText().getLength();
1056
0
}
1057
1058
sal_Int32 SAL_CALL AccessibleEditableTextPara::getIndexAtPoint( const awt::Point& rPoint )
1059
0
{
1060
0
    SolarMutexGuard aGuard;
1061
1062
0
    sal_Int32 nPara;
1063
0
    sal_Int32 nIndex;
1064
1065
    // offset from surrounding cell/shape
1066
0
    Point aOffset( GetEEOffset() );
1067
0
    Point aPoint( rPoint.X - aOffset.X(), rPoint.Y - aOffset.Y() );
1068
1069
    // convert to logical coordinates
1070
0
    SvxTextForwarder& rCacheTF = GetTextForwarder();
1071
0
    Point aLogPoint( GetViewForwarder().PixelToLogic( aPoint, rCacheTF.GetMapMode() ) );
1072
1073
    // re-offset to parent (paragraph)
1074
0
    tools::Rectangle aParaRect = rCacheTF.GetParaBounds( GetParagraphIndex() );
1075
0
    aLogPoint.Move( aParaRect.Left(), aParaRect.Top() );
1076
1077
0
    if( rCacheTF.GetIndexAtPoint( aLogPoint, nPara, nIndex ) &&
1078
0
        GetParagraphIndex() == nPara )
1079
0
    {
1080
        // #102259# Double-check if we're _really_ on the given character
1081
0
        try
1082
0
        {
1083
0
            awt::Rectangle aRect1( getCharacterBounds(nIndex) );
1084
0
            tools::Rectangle aRect2( aRect1.X, aRect1.Y,
1085
0
                              aRect1.Width + aRect1.X, aRect1.Height + aRect1.Y );
1086
0
            if( aRect2.Contains( Point( rPoint.X, rPoint.Y ) ) )
1087
0
                return nIndex;
1088
0
            else
1089
0
                return -1;
1090
0
        }
1091
0
        catch (const lang::IndexOutOfBoundsException&)
1092
0
        {
1093
            // #103927# Don't throw for invalid nIndex values
1094
0
            return -1;
1095
0
        }
1096
0
    }
1097
0
    else
1098
0
    {
1099
        // not within our paragraph
1100
0
        return -1;
1101
0
    }
1102
0
}
1103
1104
OUString SAL_CALL AccessibleEditableTextPara::getSelectedText()
1105
0
{
1106
0
    SolarMutexGuard aGuard;
1107
1108
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
1109
0
               "AccessibleEditableTextPara::getSelectedText: index value overflow");
1110
1111
0
    if( !HaveEditView() )
1112
0
        return OUString();
1113
1114
0
    return OCommonAccessibleText::getSelectedText();
1115
0
}
1116
1117
sal_Int32 SAL_CALL AccessibleEditableTextPara::getSelectionStart()
1118
0
{
1119
0
    SolarMutexGuard aGuard;
1120
1121
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
1122
0
               "AccessibleEditableTextPara::getSelectionStart: index value overflow");
1123
1124
0
    if( !HaveEditView() )
1125
0
        return -1;
1126
1127
0
    return OCommonAccessibleText::getSelectionStart();
1128
0
}
1129
1130
sal_Int32 SAL_CALL AccessibleEditableTextPara::getSelectionEnd()
1131
0
{
1132
0
    SolarMutexGuard aGuard;
1133
1134
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
1135
0
               "AccessibleEditableTextPara::getSelectionEnd: index value overflow");
1136
1137
0
    if( !HaveEditView() )
1138
0
        return -1;
1139
1140
0
    return OCommonAccessibleText::getSelectionEnd();
1141
0
}
1142
1143
sal_Bool SAL_CALL AccessibleEditableTextPara::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
1144
0
{
1145
0
    SolarMutexGuard aGuard;
1146
1147
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
1148
0
               "AccessibleEditableTextPara::setSelection: paragraph index value overflow");
1149
1150
0
    CheckRange(nStartIndex, nEndIndex);
1151
1152
0
    try
1153
0
    {
1154
0
        SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( true );
1155
0
        return rCacheVF.SetSelection( MakeSelection(nStartIndex, nEndIndex) );
1156
0
    }
1157
0
    catch (const uno::RuntimeException&)
1158
0
    {
1159
0
        return false;
1160
0
    }
1161
0
}
1162
1163
OUString SAL_CALL AccessibleEditableTextPara::getText()
1164
0
{
1165
0
    SolarMutexGuard aGuard;
1166
1167
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
1168
0
               "AccessibleEditableTextPara::getText: paragraph index value overflow");
1169
1170
0
    return implGetText();
1171
0
}
1172
1173
OUString SAL_CALL AccessibleEditableTextPara::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
1174
0
{
1175
0
    SolarMutexGuard aGuard;
1176
1177
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
1178
0
               "AccessibleEditableTextPara::getTextRange: paragraph index value overflow");
1179
1180
0
    return OCommonAccessibleText::implGetTextRange(implGetText(), nStartIndex, nEndIndex);
1181
0
}
1182
1183
void AccessibleEditableTextPara::_correctValues( uno::Sequence< PropertyValue >& rValues)
1184
0
{
1185
0
    SvxTextForwarder& rCacheTF = GetTextForwarder();
1186
0
    sal_Int32 nRes = rValues.getLength();
1187
0
    beans::PropertyValue *pRes = rValues.getArray();
1188
0
    for (sal_Int32 i = 0;  i < nRes;  ++i)
1189
0
    {
1190
0
        beans::PropertyValue &rRes = pRes[i];
1191
        // Char color
1192
0
        if (rRes.Name == "CharColor")
1193
0
        {
1194
0
            uno::Any &anyChar = rRes.Value;
1195
0
            Color crChar;
1196
0
            anyChar >>= crChar;
1197
0
            if (COL_AUTO == crChar )
1198
0
            {
1199
0
                if (mpParent->getAccessibleRole() == AccessibleRole::SHAPE
1200
0
                    || mpParent->getAccessibleRole() == AccessibleRole::TABLE_CELL)
1201
0
                {
1202
0
                    anyChar <<= COL_BLACK;
1203
0
                }
1204
0
                else
1205
0
                {
1206
0
                    Color cr(ColorTransparency, mpParent->getBackground());
1207
0
                    crChar = cr.IsDark() ? COL_WHITE : COL_BLACK;
1208
0
                    anyChar <<= crChar;
1209
0
                }
1210
0
            }
1211
0
            continue;
1212
0
        }
1213
        // Underline
1214
0
        if (rRes.Name == "CharUnderline")
1215
0
        {
1216
0
            continue;
1217
0
        }
1218
        // Underline color && Mis-spell
1219
0
        if (rRes.Name == "CharUnderlineColor")
1220
0
        {
1221
0
            uno::Any &anyCharUnderLine = rRes.Value;
1222
0
            Color crCharUnderLine;
1223
0
            anyCharUnderLine >>= crCharUnderLine;
1224
0
            if (COL_AUTO == crCharUnderLine )
1225
0
            {
1226
0
                if (mpParent->getAccessibleRole() == AccessibleRole::SHAPE
1227
0
                    || mpParent->getAccessibleRole() == AccessibleRole::TABLE_CELL)
1228
0
                {
1229
0
                    anyCharUnderLine <<= COL_BLACK;
1230
0
                }
1231
0
                else
1232
0
                {
1233
0
                    Color cr(ColorTransparency, mpParent->getBackground());
1234
0
                    crCharUnderLine = cr.IsDark() ? COL_WHITE : COL_BLACK;
1235
0
                    anyCharUnderLine <<= crCharUnderLine;
1236
0
                }
1237
0
            }
1238
0
            continue;
1239
0
        }
1240
        // NumberingLevel
1241
0
        if (rRes.Name == "NumberingLevel")
1242
0
        {
1243
0
            if(rCacheTF.GetParaAttribs(GetParagraphIndex()).Get(EE_PARA_NUMBULLET).GetNumRule().GetLevelCount()==0)
1244
0
            {
1245
0
                rRes.Value <<= sal_Int16(-1);
1246
0
                rRes.Handle = -1;
1247
0
                rRes.State = PropertyState_DIRECT_VALUE;
1248
0
            }
1249
0
            else
1250
0
            {
1251
//                  SvxAccessibleTextPropertySet aPropSet( &GetEditSource(),
1252
//                      ImplGetSvxCharAndParaPropertiesMap() );
1253
                // MT IA2 TODO: Check if this is the correct replacement for ImplGetSvxCharAndParaPropertiesMap
1254
0
                rtl::Reference< SvxAccessibleTextPropertySet > xPropSet( new SvxAccessibleTextPropertySet( &GetEditSource(), ImplGetSvxTextPortionSvxPropertySet() ) );
1255
1256
0
                xPropSet->SetSelection( MakeSelection( 0, GetTextLen() ) );
1257
0
                rRes.Value = xPropSet->_getPropertyValue( rRes.Name, mnParagraphIndex );
1258
0
                rRes.State = xPropSet->_getPropertyState( rRes.Name, mnParagraphIndex );
1259
0
                rRes.Handle = -1;
1260
0
            }
1261
0
            continue;
1262
0
        }
1263
        // NumberingRules
1264
0
        if (rRes.Name == "NumberingRules")
1265
0
        {
1266
0
            SfxItemSet aAttribs = rCacheTF.GetParaAttribs(GetParagraphIndex());
1267
0
            bool bVis = aAttribs.Get( EE_PARA_BULLETSTATE ).GetValue();
1268
0
            if(bVis)
1269
0
            {
1270
0
                rRes.Value <<= sal_Int16(-1);
1271
0
                rRes.Handle = -1;
1272
0
                rRes.State = PropertyState_DIRECT_VALUE;
1273
0
            }
1274
0
            else
1275
0
            {
1276
                // MT IA2 TODO: Check if this is the correct replacement for ImplGetSvxCharAndParaPropertiesMap
1277
0
                rtl::Reference< SvxAccessibleTextPropertySet > xPropSet( new SvxAccessibleTextPropertySet( &GetEditSource(), ImplGetSvxTextPortionSvxPropertySet() ) );
1278
0
                xPropSet->SetSelection( MakeSelection( 0, GetTextLen() ) );
1279
0
                rRes.Value = xPropSet->_getPropertyValue( rRes.Name, mnParagraphIndex );
1280
0
                rRes.State = xPropSet->_getPropertyState( rRes.Name, mnParagraphIndex );
1281
0
                rRes.Handle = -1;
1282
0
            }
1283
0
            continue;
1284
0
        }
1285
0
    }
1286
0
}
1287
sal_Int32 AccessibleEditableTextPara::SkipField(sal_Int32 nIndex, bool bForward)
1288
0
{
1289
0
    sal_Int32 nParaIndex = GetParagraphIndex();
1290
0
    SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder();
1291
0
    sal_Int32 nAllFieldLen = 0;
1292
0
    sal_Int32 nFoundFieldIndex = -1;
1293
0
    std::vector<EFieldInfo> aFieldInfos = rCacheTF.GetFieldInfo(nParaIndex);
1294
0
    sal_Int32  reeBegin=0, reeEnd=0;
1295
0
    sal_Int32 j = 0;
1296
0
    for (const EFieldInfo& ree : aFieldInfos)
1297
0
    {
1298
0
        reeBegin = ree.aPosition.nIndex + nAllFieldLen;
1299
0
        reeEnd = reeBegin + ree.aCurrentText.getLength();
1300
0
        nAllFieldLen += (ree.aCurrentText.getLength() - 1);
1301
0
        if (nIndex < reeBegin)
1302
0
            break;
1303
0
        if (!ree.pFieldItem)
1304
0
            continue;
1305
0
        if (nIndex < reeEnd)
1306
0
        {
1307
0
            if (ree.pFieldItem->GetField()->GetClassId() != text::textfield::Type::URL)
1308
0
            {
1309
0
                nFoundFieldIndex = j;
1310
0
                break;
1311
0
            }
1312
0
        }
1313
0
        j++;
1314
0
    }
1315
0
    if( nFoundFieldIndex >= 0  )
1316
0
    {
1317
0
        if( bForward )
1318
0
            return reeEnd - 1;
1319
0
        else
1320
0
            return reeBegin;
1321
0
    }
1322
0
    return nIndex;
1323
0
}
1324
void AccessibleEditableTextPara::ExtendByField( css::accessibility::TextSegment& Segment )
1325
0
{
1326
0
    sal_Int32 nParaIndex = GetParagraphIndex();
1327
0
    SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder();
1328
0
    std::vector<EFieldInfo> aFieldInfos = rCacheTF.GetFieldInfo(nParaIndex);
1329
0
    sal_Int32 nAllFieldLen = 0;
1330
0
    sal_Int32 nField = aFieldInfos.size(), nFoundFieldIndex = -1;
1331
0
    sal_Int32  reeBegin=0, reeEnd=0;
1332
0
    for (sal_Int32 j = 0; j < nField; ++j)
1333
0
    {
1334
0
        const EFieldInfo& ree = aFieldInfos[j];
1335
0
        reeBegin  = ree.aPosition.nIndex + nAllFieldLen;
1336
0
        reeEnd = reeBegin + ree.aCurrentText.getLength();
1337
0
        nAllFieldLen += (ree.aCurrentText.getLength() - 1);
1338
0
        if( reeBegin > Segment.SegmentEnd )
1339
0
        {
1340
0
            break;
1341
0
        }
1342
0
        if (!ree.pFieldItem)
1343
0
            continue;
1344
0
        if(  (Segment.SegmentEnd > reeBegin && Segment.SegmentEnd <= reeEnd) ||
1345
0
              (Segment.SegmentStart >= reeBegin && Segment.SegmentStart < reeEnd)  )
1346
0
        {
1347
0
            if(ree.pFieldItem->GetField()->GetClassId() != text::textfield::Type::URL)
1348
0
            {
1349
0
                nFoundFieldIndex = j;
1350
0
                break;
1351
0
            }
1352
0
        }
1353
0
    }
1354
0
    if( nFoundFieldIndex < 0 )
1355
0
        return;
1356
1357
0
    bool bExtend = false;
1358
0
    if( Segment.SegmentEnd < reeEnd )
1359
0
    {
1360
0
        Segment.SegmentEnd  = reeEnd;
1361
0
        bExtend = true;
1362
0
    }
1363
0
    if( Segment.SegmentStart > reeBegin )
1364
0
    {
1365
0
        Segment.SegmentStart = reeBegin;
1366
0
        bExtend = true;
1367
0
    }
1368
0
    if( !bExtend )
1369
0
        return;
1370
1371
    //If there is a bullet before the field, should add the bullet length into the segment.
1372
0
    EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(nParaIndex);
1373
0
    sal_Int32 nBulletLen = aBulletInfo.aText.getLength();
1374
0
    if (nBulletLen > 0)
1375
0
    {
1376
0
        Segment.SegmentEnd += nBulletLen;
1377
0
        if (nFoundFieldIndex > 0)
1378
0
            Segment.SegmentStart += nBulletLen;
1379
0
        Segment.SegmentText = GetTextRange(Segment.SegmentStart, Segment.SegmentEnd);
1380
        //After get the correct field name, should restore the offset value which don't contain the bullet.
1381
0
        Segment.SegmentEnd -= nBulletLen;
1382
0
        if (nFoundFieldIndex > 0)
1383
0
            Segment.SegmentStart -= nBulletLen;
1384
0
    }
1385
0
    else
1386
0
        Segment.SegmentText = GetTextRange(Segment.SegmentStart, Segment.SegmentEnd);
1387
0
}
1388
1389
css::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
1390
0
{
1391
0
    SolarMutexGuard aGuard;
1392
1393
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
1394
0
               "AccessibleEditableTextPara::getTextAtIndex: paragraph index value overflow");
1395
1396
0
    css::accessibility::TextSegment aResult;
1397
0
    aResult.SegmentStart = -1;
1398
0
    aResult.SegmentEnd = -1;
1399
1400
0
    switch( aTextType )
1401
0
    {
1402
0
        case AccessibleTextType::CHARACTER:
1403
0
        case AccessibleTextType::WORD:
1404
0
        {
1405
0
            aResult = OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
1406
0
            ExtendByField( aResult );
1407
0
            break;
1408
0
        }
1409
        // Not yet handled by OCommonAccessibleText. Missing
1410
        // implGetAttributeRunBoundary() method there
1411
0
        case AccessibleTextType::ATTRIBUTE_RUN:
1412
0
        {
1413
0
            const sal_Int32 nTextLen = GetTextForwarder().GetTextLen( GetParagraphIndex() );
1414
1415
0
            if( nIndex == nTextLen )
1416
0
            {
1417
                // #i17014# Special-casing one-behind-the-end character
1418
0
                aResult.SegmentStart = aResult.SegmentEnd = nTextLen;
1419
0
            }
1420
0
            else
1421
0
            {
1422
0
                sal_Int32 nStartIndex, nEndIndex;
1423
                //For the bullet paragraph, the bullet string is ignored for IAText::attributes() function.
1424
0
                SvxTextForwarder&   rCacheTF = GetTextForwarder();
1425
                // MT IA2: Not used? sal_Int32 nBulletLen = 0;
1426
0
                EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(GetParagraphIndex());
1427
0
                if (aBulletInfo.bVisible)
1428
0
                    nIndex += aBulletInfo.aText.getLength();
1429
0
                if (nIndex != 0  && nIndex >= getCharacterCount())
1430
0
                    nIndex = getCharacterCount()-1;
1431
0
                CheckPosition(nIndex);
1432
0
                if( GetAttributeRun(nStartIndex, nEndIndex, nIndex) )
1433
0
                {
1434
0
                    aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex);
1435
0
                    if (aBulletInfo.bVisible)
1436
0
                    {
1437
0
                        nStartIndex -= aBulletInfo.aText.getLength();
1438
0
                        nEndIndex -= aBulletInfo.aText.getLength();
1439
0
                    }
1440
0
                    aResult.SegmentStart = nStartIndex;
1441
0
                    aResult.SegmentEnd = nEndIndex;
1442
0
                }
1443
0
            }
1444
0
            break;
1445
0
        }
1446
0
        case AccessibleTextType::LINE:
1447
0
        {
1448
0
            SvxTextForwarder&   rCacheTF = GetTextForwarder();
1449
0
            sal_Int32           nParaIndex = GetParagraphIndex();
1450
0
            CheckPosition(nIndex);
1451
0
            if (nIndex != 0  && nIndex == getCharacterCount())
1452
0
                --nIndex;
1453
0
            sal_Int32 nLine, nLineCount=rCacheTF.GetLineCount( nParaIndex );
1454
0
            sal_Int32 nCurIndex;
1455
            //the problem is that rCacheTF.GetLineLen() will include the bullet length. But for the bullet line,
1456
            //the text value doesn't contain the bullet characters. all of the bullet and numbering info are exposed
1457
            //by the IAText::attributes(). So here must do special support for bullet line.
1458
0
            sal_Int32 nBulletLen = 0;
1459
0
            for( nLine=0, nCurIndex=0; nLine<nLineCount; ++nLine )
1460
0
            {
1461
0
                if (nLine == 0)
1462
0
                {
1463
0
                    EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo( nParaIndex );
1464
0
                    if (aBulletInfo.bVisible)
1465
0
                    {
1466
                        //in bullet or numbering;
1467
0
                        nBulletLen = aBulletInfo.aText.getLength();
1468
0
                    }
1469
0
                }
1470
0
                sal_Int32 nLineLen = rCacheTF.GetLineLen(nParaIndex, nLine);
1471
0
                if (nLine == 0)
1472
0
                    nCurIndex += nLineLen - nBulletLen;
1473
0
                else
1474
0
                    nCurIndex += nLineLen;
1475
0
                if( nCurIndex > nIndex )
1476
0
                {
1477
0
                    if (nLine ==0)
1478
0
                    {
1479
0
                        aResult.SegmentStart = 0;
1480
0
                        aResult.SegmentEnd = nCurIndex;
1481
0
                        aResult.SegmentText = GetTextRange( aResult.SegmentStart, aResult.SegmentEnd + nBulletLen);
1482
0
                        break;
1483
0
                    }
1484
0
                    else
1485
0
                    {
1486
0
                        aResult.SegmentStart = nCurIndex - nLineLen;
1487
0
                        aResult.SegmentEnd = nCurIndex;
1488
                        //aResult.SegmentText = GetTextRange( aResult.SegmentStart, aResult.SegmentEnd );
1489
0
                        aResult.SegmentText = GetTextRange( aResult.SegmentStart + nBulletLen, aResult.SegmentEnd + nBulletLen);
1490
0
                        break;
1491
0
                    }
1492
0
                }
1493
0
            }
1494
0
            break;
1495
0
        }
1496
0
        default:
1497
0
            aResult = OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
1498
0
            break;
1499
0
    } /* end of switch( aTextType ) */
1500
1501
0
    return aResult;
1502
0
}
1503
1504
css::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
1505
0
{
1506
0
    SolarMutexGuard aGuard;
1507
1508
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
1509
0
               "AccessibleEditableTextPara::getTextBeforeIndex: paragraph index value overflow");
1510
1511
0
    css::accessibility::TextSegment aResult;
1512
0
    aResult.SegmentStart = -1;
1513
0
    aResult.SegmentEnd = -1;
1514
0
    i18n::Boundary aBoundary;
1515
0
    switch( aTextType )
1516
0
    {
1517
        // Not yet handled by OCommonAccessibleText. Missing
1518
        // implGetAttributeRunBoundary() method there
1519
0
        case AccessibleTextType::ATTRIBUTE_RUN:
1520
0
        {
1521
0
            const sal_Int32 nTextLen = GetTextForwarder().GetTextLen( GetParagraphIndex() );
1522
0
            sal_Int32 nStartIndex, nEndIndex;
1523
1524
0
            if( nIndex == nTextLen )
1525
0
            {
1526
                // #i17014# Special-casing one-behind-the-end character
1527
0
                if( nIndex > 0 &&
1528
0
                    GetAttributeRun(nStartIndex, nEndIndex, nIndex-1) )
1529
0
                {
1530
0
                    aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex);
1531
0
                    aResult.SegmentStart = nStartIndex;
1532
0
                    aResult.SegmentEnd = nEndIndex;
1533
0
                }
1534
0
            }
1535
0
            else
1536
0
            {
1537
0
                if( GetAttributeRun(nStartIndex, nEndIndex, nIndex) )
1538
0
                {
1539
                    // already at the left border? If not, query
1540
                    // one index further left
1541
0
                    if( nStartIndex > 0 &&
1542
0
                        GetAttributeRun(nStartIndex, nEndIndex, nStartIndex-1) )
1543
0
                    {
1544
0
                        aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex);
1545
0
                        aResult.SegmentStart = nStartIndex;
1546
0
                        aResult.SegmentEnd = nEndIndex;
1547
0
                    }
1548
0
                }
1549
0
            }
1550
0
            break;
1551
0
        }
1552
0
        case AccessibleTextType::LINE:
1553
0
        {
1554
0
            SvxTextForwarder&   rCacheTF = GetTextForwarder();
1555
0
            sal_Int32           nParaIndex = GetParagraphIndex();
1556
1557
0
            CheckPosition(nIndex);
1558
1559
0
            sal_Int32 nLine, nLineCount=rCacheTF.GetLineCount( nParaIndex );
1560
            //the problem is that rCacheTF.GetLineLen() will include the bullet length. But for the bullet line,
1561
            //the text value doesn't contain the bullet characters. all of the bullet and numbering info are exposed
1562
            //by the IAText::attributes(). So here must do special support for bullet line.
1563
0
            sal_Int32 nCurIndex=0, nLastIndex=0, nCurLineLen=0;
1564
0
            sal_Int32 nLastLineLen = 0, nBulletLen = 0;
1565
            // get the line before the line the index points into
1566
0
            for( nLine=0, nCurIndex=0; nLine<nLineCount; ++nLine )
1567
0
            {
1568
0
                nLastIndex = nCurIndex;
1569
0
                if (nLine == 0)
1570
0
                {
1571
0
                    EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(nParaIndex);
1572
0
                    if (aBulletInfo.bVisible)
1573
0
                    {
1574
                        //in bullet or numbering;
1575
0
                        nBulletLen = aBulletInfo.aText.getLength();
1576
0
                    }
1577
0
                }
1578
0
                if (nLine == 1)
1579
0
                    nLastLineLen = nCurLineLen - nBulletLen;
1580
0
                else
1581
0
                    nLastLineLen = nCurLineLen;
1582
0
                nCurLineLen = rCacheTF.GetLineLen( nParaIndex, nLine);
1583
                //nCurIndex += nCurLineLen;
1584
0
                if (nLine == 0)
1585
0
                    nCurIndex += nCurLineLen - nBulletLen;
1586
0
                else
1587
0
                    nCurIndex += nCurLineLen;
1588
1589
                //if( nCurIndex > nIndex &&
1590
                //nLastIndex > nCurLineLen )
1591
0
                if (nCurIndex > nIndex)
1592
0
                {
1593
0
                    if (nLine == 0)
1594
0
                    {
1595
0
                        break;
1596
0
                    }
1597
0
                    else if (nLine == 1)
1598
0
                    {
1599
0
                        aResult.SegmentStart = 0;
1600
0
                        aResult.SegmentEnd = nLastIndex;
1601
0
                        aResult.SegmentText = GetTextRange( aResult.SegmentStart, aResult.SegmentEnd + nBulletLen);
1602
0
                        break;
1603
0
                    }
1604
0
                    else
1605
0
                    {
1606
                        //aResult.SegmentStart = nLastIndex - nCurLineLen;
1607
0
                        aResult.SegmentStart = nLastIndex - nLastLineLen;
1608
0
                        aResult.SegmentEnd = nLastIndex;
1609
0
                        aResult.SegmentText = GetTextRange( aResult.SegmentStart + nBulletLen, aResult.SegmentEnd + nBulletLen);
1610
0
                        break;
1611
0
                    }
1612
0
                }
1613
0
            }
1614
1615
0
            break;
1616
0
        }
1617
0
        case AccessibleTextType::WORD:
1618
0
        {
1619
0
            nIndex = SkipField( nIndex, false);
1620
0
            OUString sText( implGetText() );
1621
0
            sal_Int32 nLength = sText.getLength();
1622
1623
            // get word at index
1624
0
            implGetWordBoundary( sText, aBoundary, nIndex );
1625
1626
1627
            //sal_Int32 curWordStart = aBoundary.startPos;
1628
            //sal_Int32 preWordStart = curWordStart;
1629
0
            sal_Int32 curWordStart , preWordStart;
1630
0
            if( aBoundary.startPos == -1 || aBoundary.startPos > nIndex)
1631
0
                curWordStart = preWordStart = nIndex;
1632
0
            else
1633
0
                curWordStart = preWordStart = aBoundary.startPos;
1634
1635
            // get previous word
1636
1637
0
            bool bWord = false;
1638
1639
            //while ( preWordStart > 0 && aBoundary.startPos == curWordStart)
1640
0
            while ( (preWordStart >= 0 && !bWord ) || ( aBoundary.endPos > curWordStart ) )
1641
0
            {
1642
0
                preWordStart--;
1643
0
                bWord = implGetWordBoundary( sText, aBoundary, preWordStart );
1644
0
            }
1645
0
            if ( bWord && implIsValidBoundary( aBoundary, nLength ) )
1646
0
            {
1647
0
                aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
1648
0
                aResult.SegmentStart = aBoundary.startPos;
1649
0
                aResult.SegmentEnd = aBoundary.endPos;
1650
0
                ExtendByField( aResult );
1651
0
            }
1652
0
        }
1653
0
        break;
1654
0
        case AccessibleTextType::CHARACTER:
1655
0
        {
1656
0
            nIndex = SkipField( nIndex, false);
1657
0
            aResult = OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
1658
0
            ExtendByField( aResult );
1659
0
            break;
1660
0
        }
1661
0
        default:
1662
0
            aResult = OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
1663
0
            break;
1664
0
    } /* end of switch( aTextType ) */
1665
1666
0
    return aResult;
1667
0
}
1668
1669
css::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
1670
0
{
1671
0
    SolarMutexGuard aGuard;
1672
1673
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
1674
0
               "AccessibleEditableTextPara::getTextBehindIndex: paragraph index value overflow");
1675
1676
0
    css::accessibility::TextSegment aResult;
1677
0
    aResult.SegmentStart = -1;
1678
0
    aResult.SegmentEnd = -1;
1679
0
    i18n::Boundary aBoundary;
1680
0
    switch( aTextType )
1681
0
    {
1682
0
        case AccessibleTextType::ATTRIBUTE_RUN:
1683
0
        {
1684
0
            sal_Int32 nStartIndex, nEndIndex;
1685
1686
0
            if( GetAttributeRun(nStartIndex, nEndIndex, nIndex) )
1687
0
            {
1688
                // already at the right border?
1689
0
                if( nEndIndex < GetTextLen() )
1690
0
                {
1691
0
                    if( GetAttributeRun(nStartIndex, nEndIndex, nEndIndex) )
1692
0
                    {
1693
0
                        aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex);
1694
0
                        aResult.SegmentStart = nStartIndex;
1695
0
                        aResult.SegmentEnd = nEndIndex;
1696
0
                    }
1697
0
                }
1698
0
            }
1699
0
            break;
1700
0
        }
1701
1702
0
        case AccessibleTextType::LINE:
1703
0
        {
1704
0
            SvxTextForwarder&   rCacheTF = GetTextForwarder();
1705
0
            sal_Int32           nParaIndex = GetParagraphIndex();
1706
1707
0
            CheckPosition(nIndex);
1708
1709
0
            sal_Int32 nLine, nLineCount = rCacheTF.GetLineCount( nParaIndex );
1710
0
            sal_Int32 nCurIndex;
1711
            //the problem is that rCacheTF.GetLineLen() will include the bullet length. But for the bullet line,
1712
            //the text value doesn't contain the bullet characters. all of the bullet and numbering info are exposed
1713
            //by the IAText::attributes(). So here must do special support for bullet line.
1714
0
            sal_Int32 nBulletLen = 0;
1715
            // get the line after the line the index points into
1716
0
            for( nLine=0, nCurIndex=0; nLine<nLineCount; ++nLine )
1717
0
            {
1718
0
                if (nLine == 0)
1719
0
                {
1720
0
                    EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(nParaIndex);
1721
0
                    if (aBulletInfo.bVisible)
1722
0
                    {
1723
                        //in bullet or numbering;
1724
0
                        nBulletLen = aBulletInfo.aText.getLength();
1725
0
                    }
1726
0
                }
1727
0
                sal_Int32 nLineLen = rCacheTF.GetLineLen( nParaIndex, nLine);
1728
1729
0
                if (nLine == 0)
1730
0
                    nCurIndex += nLineLen - nBulletLen;
1731
0
                else
1732
0
                    nCurIndex += nLineLen;
1733
1734
0
                if( nCurIndex > nIndex &&
1735
0
                    nLine < nLineCount-1 )
1736
0
                {
1737
0
                    aResult.SegmentStart = nCurIndex;
1738
0
                    aResult.SegmentEnd = nCurIndex + rCacheTF.GetLineLen( nParaIndex, nLine+1);
1739
0
                    aResult.SegmentText = GetTextRange( aResult.SegmentStart + nBulletLen, aResult.SegmentEnd + nBulletLen);
1740
0
                    break;
1741
0
                }
1742
0
            }
1743
1744
0
            break;
1745
0
        }
1746
0
        case AccessibleTextType::WORD:
1747
0
        {
1748
0
            nIndex = SkipField( nIndex, true);
1749
0
            OUString sText( implGetText() );
1750
0
            sal_Int32 nLength = sText.getLength();
1751
1752
            // get word at index
1753
0
            bool bWord = implGetWordBoundary( sText, aBoundary, nIndex );
1754
1755
            // real current world
1756
0
            sal_Int32 nextWord = nIndex;
1757
            //if( nIndex >= aBoundary.startPos && nIndex <= aBoundary.endPos )
1758
0
            if( nIndex <= aBoundary.endPos )
1759
0
            {
1760
0
                nextWord =  aBoundary.endPos;
1761
0
                if (nextWord < sText.getLength() && sText[nextWord] == u' ') nextWord++;
1762
0
                bWord = implGetWordBoundary( sText, aBoundary, nextWord );
1763
0
            }
1764
1765
0
            if ( bWord && implIsValidBoundary( aBoundary, nLength ) )
1766
0
            {
1767
0
                aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
1768
0
                aResult.SegmentStart = aBoundary.startPos;
1769
0
                aResult.SegmentEnd = aBoundary.endPos;
1770
1771
                // If the end position of aBoundary is inside a field, extend the result to the end of the field
1772
1773
0
                ExtendByField( aResult );
1774
0
            }
1775
0
        }
1776
0
        break;
1777
1778
0
        case AccessibleTextType::CHARACTER:
1779
0
        {
1780
0
            nIndex = SkipField( nIndex, true);
1781
0
            aResult = OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
1782
0
            ExtendByField( aResult );
1783
0
            break;
1784
0
        }
1785
0
        default:
1786
0
            aResult = OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
1787
0
            break;
1788
0
    } /* end of switch( aTextType ) */
1789
1790
0
    return aResult;
1791
0
}
1792
1793
sal_Bool SAL_CALL AccessibleEditableTextPara::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
1794
0
{
1795
0
    SolarMutexGuard aGuard;
1796
1797
0
    try
1798
0
    {
1799
0
        SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( true );
1800
0
        GetTextForwarder();                                         // MUST be after GetEditViewForwarder(), see method docs
1801
1802
0
        bool aRetVal;
1803
1804
0
        DBG_ASSERT(GetParagraphIndex() >= 0,
1805
0
                   "AccessibleEditableTextPara::copyText: index value overflow");
1806
1807
0
        CheckRange(nStartIndex, nEndIndex);
1808
1809
        //Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet
1810
0
        const sal_Int32 nBulletLen = GetBulletTextLength();
1811
        // save current selection
1812
0
        ESelection aOldSelection;
1813
1814
0
        rCacheVF.GetSelection( aOldSelection );
1815
        //rCacheVF.SetSelection( MakeSelection(nStartIndex, nEndIndex) );
1816
0
        rCacheVF.SetSelection( MakeSelection(nStartIndex + nBulletLen, nEndIndex + nBulletLen) );
1817
0
        aRetVal = rCacheVF.Copy();
1818
0
        rCacheVF.SetSelection( aOldSelection ); // restore
1819
1820
0
        return aRetVal;
1821
0
    }
1822
0
    catch (const uno::RuntimeException&)
1823
0
    {
1824
0
        return false;
1825
0
    }
1826
0
}
1827
1828
sal_Bool SAL_CALL AccessibleEditableTextPara::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
1829
0
{
1830
0
    return false;
1831
0
}
1832
1833
// XAccessibleEditableText
1834
sal_Bool SAL_CALL AccessibleEditableTextPara::cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
1835
0
{
1836
1837
0
    SolarMutexGuard aGuard;
1838
1839
0
    try
1840
0
    {
1841
0
        SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( true );
1842
0
        SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder();    // MUST be after GetEditViewForwarder(), see method docs
1843
1844
0
        DBG_ASSERT(GetParagraphIndex() >= 0,
1845
0
                   "AccessibleEditableTextPara::cutText: index value overflow");
1846
1847
0
        CheckRange(nStartIndex, nEndIndex);
1848
1849
        // Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet
1850
0
        const sal_Int32 nBulletLen = GetBulletTextLength();
1851
0
        ESelection aSelection = MakeSelection (nStartIndex + nBulletLen, nEndIndex + nBulletLen);
1852
        //if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) )
1853
0
        if( !rCacheTF.IsEditable( aSelection ) )
1854
0
            return false; // non-editable area selected
1855
1856
        // don't save selection, might become invalid after cut!
1857
        //rCacheVF.SetSelection( MakeSelection(nStartIndex, nEndIndex) );
1858
0
        rCacheVF.SetSelection( aSelection );
1859
1860
0
        return rCacheVF.Cut();
1861
0
    }
1862
0
    catch (const uno::RuntimeException&)
1863
0
    {
1864
0
        return false;
1865
0
    }
1866
0
}
1867
1868
sal_Bool SAL_CALL AccessibleEditableTextPara::pasteText( sal_Int32 nIndex )
1869
0
{
1870
1871
0
    SolarMutexGuard aGuard;
1872
1873
0
    try
1874
0
    {
1875
0
        SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( true );
1876
0
        SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder();    // MUST be after GetEditViewForwarder(), see method docs
1877
1878
0
        DBG_ASSERT(GetParagraphIndex() >= 0,
1879
0
                   "AccessibleEditableTextPara::pasteText: index value overflow");
1880
1881
0
        CheckPosition(nIndex);
1882
1883
        // Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet
1884
0
        const sal_Int32 nBulletLen = GetBulletTextLength();
1885
0
        if( !rCacheTF.IsEditable( MakeSelection(nIndex + nBulletLen) ) )
1886
0
            return false; // non-editable area selected
1887
1888
        // #104400# set empty selection (=> cursor) to given index
1889
        //rCacheVF.SetSelection( MakeCursor(nIndex) );
1890
0
        rCacheVF.SetSelection( MakeCursor(nIndex + nBulletLen) );
1891
1892
0
        return rCacheVF.Paste();
1893
0
    }
1894
0
    catch (const uno::RuntimeException&)
1895
0
    {
1896
0
        return false;
1897
0
    }
1898
0
}
1899
1900
sal_Bool SAL_CALL AccessibleEditableTextPara::deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
1901
0
{
1902
1903
0
    SolarMutexGuard aGuard;
1904
1905
0
    try
1906
0
    {
1907
        // #102710# Request edit view when doing changes
1908
        // AccessibleEmptyEditSource relies on this behaviour
1909
0
        GetEditViewForwarder( true );
1910
0
        SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder();    // MUST be after GetEditViewForwarder(), see method docs
1911
1912
0
        DBG_ASSERT(GetParagraphIndex() >= 0,
1913
0
                   "AccessibleEditableTextPara::deleteText: index value overflow");
1914
1915
0
        CheckRange(nStartIndex, nEndIndex);
1916
1917
        // Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet
1918
0
        const sal_Int32 nBulletLen = GetBulletTextLength();
1919
0
        ESelection aSelection = MakeSelection (nStartIndex + nBulletLen, nEndIndex + nBulletLen);
1920
1921
        //if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) )
1922
0
        if( !rCacheTF.IsEditable( aSelection ) )
1923
0
            return false; // non-editable area selected
1924
1925
        //sal_Bool bRet = rCacheTF.Delete( MakeSelection(nStartIndex, nEndIndex) );
1926
0
        bool bRet = rCacheTF.Delete( aSelection );
1927
1928
0
        GetEditSource().UpdateData();
1929
1930
0
        return bRet;
1931
0
    }
1932
0
    catch (const uno::RuntimeException&)
1933
0
    {
1934
0
        return false;
1935
0
    }
1936
0
}
1937
1938
sal_Bool SAL_CALL AccessibleEditableTextPara::insertText( const OUString& sText, sal_Int32 nIndex )
1939
0
{
1940
1941
0
    SolarMutexGuard aGuard;
1942
1943
0
    try
1944
0
    {
1945
        // #102710# Request edit view when doing changes
1946
        // AccessibleEmptyEditSource relies on this behaviour
1947
0
        GetEditViewForwarder( true );
1948
0
        SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder();    // MUST be after GetEditViewForwarder(), see method docs
1949
1950
0
        DBG_ASSERT(GetParagraphIndex() >= 0,
1951
0
                   "AccessibleEditableTextPara::insertText: index value overflow");
1952
1953
0
        CheckPosition(nIndex);
1954
1955
        // Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet
1956
0
        const sal_Int32 nBulletLen = GetBulletTextLength();
1957
0
        if( !rCacheTF.IsEditable( MakeSelection(nIndex + nBulletLen) ) )
1958
0
            return false; // non-editable area selected
1959
1960
        // #104400# insert given text at empty selection (=> cursor)
1961
0
        bool bRet = rCacheTF.InsertText( sText, MakeCursor(nIndex + nBulletLen) );
1962
1963
0
        rCacheTF.QuickFormatDoc();
1964
0
        GetEditSource().UpdateData();
1965
1966
0
        return bRet;
1967
0
    }
1968
0
    catch (const uno::RuntimeException&)
1969
0
    {
1970
0
        return false;
1971
0
    }
1972
0
}
1973
1974
sal_Bool SAL_CALL AccessibleEditableTextPara::replaceText( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const OUString& sReplacement )
1975
0
{
1976
1977
0
    SolarMutexGuard aGuard;
1978
1979
0
    try
1980
0
    {
1981
        // #102710# Request edit view when doing changes
1982
        // AccessibleEmptyEditSource relies on this behaviour
1983
0
        GetEditViewForwarder( true );
1984
0
        SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder();    // MUST be after GetEditViewForwarder(), see method docs
1985
1986
0
        DBG_ASSERT(GetParagraphIndex() >= 0,
1987
0
                   "AccessibleEditableTextPara::replaceText: index value overflow");
1988
1989
0
        CheckRange(nStartIndex, nEndIndex);
1990
1991
        // Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet
1992
0
        const sal_Int32 nBulletLen = GetBulletTextLength();
1993
0
        ESelection aSelection = MakeSelection (nStartIndex + nBulletLen, nEndIndex + nBulletLen);
1994
1995
        //if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) )
1996
0
        if( !rCacheTF.IsEditable( aSelection ) )
1997
0
            return false; // non-editable area selected
1998
1999
        // insert given text into given range => replace
2000
        //sal_Bool bRet = rCacheTF.InsertText( sReplacement, MakeSelection(nStartIndex, nEndIndex) );
2001
0
        bool bRet = rCacheTF.InsertText( sReplacement, aSelection );
2002
2003
0
        rCacheTF.QuickFormatDoc();
2004
0
        GetEditSource().UpdateData();
2005
2006
0
        return bRet;
2007
0
    }
2008
0
    catch (const uno::RuntimeException&)
2009
0
    {
2010
0
        return false;
2011
0
    }
2012
0
}
2013
2014
sal_Bool SAL_CALL AccessibleEditableTextPara::setAttributes( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const uno::Sequence< beans::PropertyValue >& aAttributeSet )
2015
0
{
2016
2017
0
    SolarMutexGuard aGuard;
2018
2019
0
    try
2020
0
    {
2021
        // #102710# Request edit view when doing changes
2022
        // AccessibleEmptyEditSource relies on this behaviour
2023
0
        GetEditViewForwarder( true );
2024
0
        SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder();    // MUST be after GetEditViewForwarder(), see method docs
2025
0
        sal_Int32 nPara = GetParagraphIndex();
2026
2027
0
        DBG_ASSERT(GetParagraphIndex() >= 0,
2028
0
                   "AccessibleEditableTextPara::setAttributes: index value overflow");
2029
2030
0
        CheckRange(nStartIndex, nEndIndex);
2031
2032
0
        if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) )
2033
0
            return false; // non-editable area selected
2034
2035
        // do the indices span the whole paragraph? Then use the outliner map
2036
        // TODO: hold it as a member?
2037
0
        rtl::Reference< SvxAccessibleTextPropertySet > xPropSet( new SvxAccessibleTextPropertySet( &GetEditSource(),
2038
0
                                               0 == nStartIndex &&
2039
0
                                               rCacheTF.GetTextLen(nPara) == nEndIndex ?
2040
0
                                               ImplGetSvxUnoOutlinerTextCursorSvxPropertySet() :
2041
0
                                               ImplGetSvxTextPortionSvxPropertySet() ) );
2042
2043
0
        xPropSet->SetSelection( MakeSelection(nStartIndex, nEndIndex) );
2044
2045
        // convert from PropertyValue to Any
2046
0
        for(const beans::PropertyValue& rProp : aAttributeSet)
2047
0
        {
2048
0
            try
2049
0
            {
2050
0
                xPropSet->setPropertyValue(rProp.Name, rProp.Value);
2051
0
            }
2052
0
            catch (const uno::Exception&)
2053
0
            {
2054
0
                TOOLS_WARN_EXCEPTION( "dbaccess", "AccessibleEditableTextPara::setAttributes exception in setPropertyValue");
2055
0
            }
2056
0
        }
2057
2058
0
        rCacheTF.QuickFormatDoc();
2059
0
        GetEditSource().UpdateData();
2060
2061
0
        return true;
2062
0
    }
2063
0
    catch (const uno::RuntimeException&)
2064
0
    {
2065
0
        return false;
2066
0
    }
2067
0
}
2068
2069
sal_Bool SAL_CALL AccessibleEditableTextPara::setText( const OUString& sText )
2070
0
{
2071
2072
0
    SolarMutexGuard aGuard;
2073
2074
0
    return replaceText(0, getCharacterCount(), sText);
2075
0
}
2076
2077
// XAccessibleTextAttributes
2078
uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getDefaultAttributes(
2079
        const uno::Sequence< OUString >& rRequestedAttributes )
2080
0
{
2081
0
    SolarMutexGuard aGuard;
2082
2083
0
    GetTextForwarder();
2084
2085
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
2086
0
               "AccessibleEditableTextPara::getCharacterAttributes: index value overflow");
2087
2088
    // get XPropertySetInfo for paragraph attributes and
2089
    // character attributes that span all the paragraphs text.
2090
0
    rtl::Reference< SvxAccessibleTextPropertySet > xPropSet( new SvxAccessibleTextPropertySet( &GetEditSource(),
2091
0
            ImplGetSvxCharAndParaPropertiesSet() ) );
2092
0
    xPropSet->SetSelection( MakeSelection( 0, GetTextLen() ) );
2093
0
    uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
2094
0
    if (!xPropSetInfo.is())
2095
0
        throw uno::RuntimeException(u"Cannot query XPropertySetInfo"_ustr, getXWeak());
2096
2097
    // build sequence of available properties to check
2098
0
    uno::Sequence< beans::Property > aProperties;
2099
0
    if (const sal_Int32 nLenReqAttr = rRequestedAttributes.getLength())
2100
0
    {
2101
0
        aProperties.realloc( nLenReqAttr );
2102
0
        beans::Property *pProperties = aProperties.getArray();
2103
0
        sal_Int32 nCurLen = 0;
2104
0
        for (const OUString& rRequestedAttribute : rRequestedAttributes)
2105
0
        {
2106
0
            beans::Property aProp;
2107
0
            try
2108
0
            {
2109
0
                aProp = xPropSetInfo->getPropertyByName( rRequestedAttribute );
2110
0
            }
2111
0
            catch (const beans::UnknownPropertyException&)
2112
0
            {
2113
0
                continue;
2114
0
            }
2115
0
            pProperties[nCurLen++] = std::move(aProp);
2116
0
        }
2117
0
        aProperties.realloc( nCurLen );
2118
0
    }
2119
0
    else
2120
0
        aProperties = xPropSetInfo->getProperties();
2121
2122
    // build resulting sequence
2123
0
    uno::Sequence< beans::PropertyValue > aOutSequence( aProperties.getLength() );
2124
0
    beans::PropertyValue* pOutSequence = aOutSequence.getArray();
2125
0
    sal_Int32 nOutLen = 0;
2126
0
    for (const beans::Property& rProperty : aProperties)
2127
0
    {
2128
        // calling implementation functions:
2129
        // _getPropertyState and _getPropertyValue (see below) to provide
2130
        // the proper paragraph number when retrieving paragraph attributes
2131
0
        PropertyState eState = xPropSet->_getPropertyState( rProperty.Name, mnParagraphIndex );
2132
0
        if ( eState == PropertyState_AMBIGUOUS_VALUE )
2133
0
        {
2134
0
            OSL_FAIL( "ambiguous property value encountered" );
2135
0
        }
2136
2137
        //if (eState == PropertyState_DIRECT_VALUE)
2138
        // per definition all paragraph properties and all character
2139
        // properties spanning the whole paragraph should be returned
2140
        // and declared as default value
2141
0
        {
2142
0
            pOutSequence->Name      = rProperty.Name;
2143
0
            pOutSequence->Handle    = rProperty.Handle;
2144
0
            pOutSequence->Value     = xPropSet->_getPropertyValue( rProperty.Name, mnParagraphIndex );
2145
0
            pOutSequence->State     = PropertyState_DEFAULT_VALUE;
2146
2147
0
            ++pOutSequence;
2148
0
            ++nOutLen;
2149
0
        }
2150
0
    }
2151
0
    aOutSequence.realloc( nOutLen );
2152
2153
0
    return aOutSequence;
2154
0
}
2155
2156
2157
uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getRunAttributes(
2158
        sal_Int32 nIndex,
2159
        const uno::Sequence< OUString >& rRequestedAttributes )
2160
0
{
2161
2162
0
    SolarMutexGuard aGuard;
2163
2164
0
    GetTextForwarder();
2165
2166
0
    DBG_ASSERT(GetParagraphIndex() >= 0,
2167
0
               "AccessibleEditableTextPara::getCharacterAttributes: index value overflow");
2168
2169
0
    if( getCharacterCount() > 0 )
2170
0
        CheckIndex(nIndex);
2171
0
    else
2172
0
        CheckPosition(nIndex);
2173
2174
0
    rtl::Reference< SvxAccessibleTextPropertySet > xPropSet( new SvxAccessibleTextPropertySet( &GetEditSource(),
2175
0
                                           ImplGetSvxCharAndParaPropertiesSet() ) );
2176
0
    xPropSet->SetSelection( MakeSelection( nIndex ) );
2177
0
    uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
2178
0
    if (!xPropSetInfo.is())
2179
0
        throw uno::RuntimeException(u"Cannot query XPropertySetInfo"_ustr, getXWeak());
2180
2181
    // build sequence of available properties to check
2182
0
    uno::Sequence< beans::Property > aProperties;
2183
0
    if (const sal_Int32 nLenReqAttr = rRequestedAttributes.getLength())
2184
0
    {
2185
0
        aProperties.realloc( nLenReqAttr );
2186
0
        beans::Property *pProperties = aProperties.getArray();
2187
0
        sal_Int32 nCurLen = 0;
2188
0
        for (const OUString& rRequestedAttribute : rRequestedAttributes)
2189
0
        {
2190
0
            beans::Property aProp;
2191
0
            try
2192
0
            {
2193
0
                aProp = xPropSetInfo->getPropertyByName( rRequestedAttribute );
2194
0
            }
2195
0
            catch (const beans::UnknownPropertyException&)
2196
0
            {
2197
0
                continue;
2198
0
            }
2199
0
            pProperties[ nCurLen++ ] = std::move(aProp);
2200
0
        }
2201
0
        aProperties.realloc( nCurLen );
2202
0
    }
2203
0
    else
2204
0
        aProperties = xPropSetInfo->getProperties();
2205
2206
    // build resulting sequence
2207
0
    uno::Sequence< beans::PropertyValue > aOutSequence( aProperties.getLength() );
2208
0
    beans::PropertyValue* pOutSequence = aOutSequence.getArray();
2209
0
    sal_Int32 nOutLen = 0;
2210
0
    for (const beans::Property& rProperty : aProperties)
2211
0
    {
2212
        // calling 'regular' functions that will operate on the selection
2213
0
        PropertyState eState = xPropSet->getPropertyState( rProperty.Name );
2214
0
        if (eState == PropertyState_DIRECT_VALUE)
2215
0
        {
2216
0
            pOutSequence->Name      = rProperty.Name;
2217
0
            pOutSequence->Handle    = rProperty.Handle;
2218
0
            pOutSequence->Value     = xPropSet->getPropertyValue( rProperty.Name );
2219
0
            pOutSequence->State     = eState;
2220
2221
0
            ++pOutSequence;
2222
0
            ++nOutLen;
2223
0
        }
2224
0
    }
2225
0
    aOutSequence.realloc( nOutLen );
2226
2227
0
    return aOutSequence;
2228
0
}
2229
2230
// XAccessibleHypertext
2231
::sal_Int32 SAL_CALL AccessibleEditableTextPara::getHyperLinkCount(  )
2232
0
{
2233
0
    SvxAccessibleTextAdapter& rT = GetTextForwarder();
2234
0
    const sal_Int32 nPara = GetParagraphIndex();
2235
2236
0
    std::vector<EFieldInfo> aFieldInfos = rT.GetFieldInfo( nPara );
2237
0
    sal_Int32 nHyperLinks = 0;
2238
0
    sal_Int32 nFields = aFieldInfos.size();
2239
0
    for (sal_Int32 n = 0; n < nFields; ++n)
2240
0
    {
2241
0
        if ( dynamic_cast<const SvxURLField* >(aFieldInfos[n].pFieldItem->GetField() ) != nullptr)
2242
0
            nHyperLinks++;
2243
0
    }
2244
0
    return nHyperLinks;
2245
0
}
2246
2247
css::uno::Reference< css::accessibility::XAccessibleHyperlink > SAL_CALL AccessibleEditableTextPara::getHyperLink( ::sal_Int32 nLinkIndex )
2248
0
{
2249
0
    rtl::Reference< AccessibleHyperlink > xRef;
2250
2251
0
    SvxAccessibleTextAdapter& rT = GetTextForwarder();
2252
0
    const sal_Int32 nPara = GetParagraphIndex();
2253
2254
0
    sal_Int32 nHyperLink = 0;
2255
0
    for (const EFieldInfo& rField : rT.GetFieldInfo( nPara ))
2256
0
    {
2257
0
        if ( dynamic_cast<const SvxURLField* >(rField.pFieldItem->GetField()) != nullptr )
2258
0
        {
2259
0
            if ( nHyperLink == nLinkIndex )
2260
0
            {
2261
0
                sal_Int32 nEEStart = rField.aPosition.nIndex;
2262
2263
                // Translate EE Index to accessible index
2264
0
                sal_Int32 nStart = rT.CalcEditEngineIndex( nPara, nEEStart );
2265
0
                sal_Int32 nEnd = nStart + rField.aCurrentText.getLength();
2266
0
                xRef = new AccessibleHyperlink( rT, new SvxFieldItem( *rField.pFieldItem ), nStart, nEnd, rField.aCurrentText );
2267
0
                break;
2268
0
            }
2269
0
            nHyperLink++;
2270
0
        }
2271
0
    }
2272
2273
0
    return xRef;
2274
0
}
2275
2276
::sal_Int32 SAL_CALL AccessibleEditableTextPara::getHyperLinkIndex( ::sal_Int32 nCharIndex )
2277
0
{
2278
0
    const sal_Int32 nPara = GetParagraphIndex();
2279
0
    SvxAccessibleTextAdapter& rT = GetTextForwarder();
2280
2281
0
    const sal_Int32 nEEIndex = rT.CalcEditEngineIndex( nPara, nCharIndex );
2282
0
    sal_Int32 nHLIndex = -1; //i123620
2283
0
    sal_Int32 nHyperLink = 0;
2284
0
    for (const EFieldInfo & rField : rT.GetFieldInfo( nPara ))
2285
0
    {
2286
0
        if ( dynamic_cast<const SvxURLField* >( rField.pFieldItem->GetField() ) != nullptr)
2287
0
        {
2288
0
            if ( rField.aPosition.nIndex == nEEIndex )
2289
0
            {
2290
0
                nHLIndex = nHyperLink;
2291
0
                break;
2292
0
            }
2293
0
            nHyperLink++;
2294
0
        }
2295
0
    }
2296
2297
0
    return nHLIndex;
2298
0
}
2299
2300
// XAccessibleMultiLineText
2301
sal_Int32 SAL_CALL AccessibleEditableTextPara::getLineNumberAtIndex( sal_Int32 nIndex )
2302
0
{
2303
2304
0
    sal_Int32 nRes = -1;
2305
0
    sal_Int32 nPara = GetParagraphIndex();
2306
2307
0
    SvxTextForwarder &rCacheTF = GetTextForwarder();
2308
0
    const bool bValidPara = 0 <= nPara && nPara < rCacheTF.GetParagraphCount();
2309
0
    DBG_ASSERT( bValidPara, "getLineNumberAtIndex: current paragraph index out of range" );
2310
0
    if (bValidPara)
2311
0
    {
2312
        // we explicitly allow for the index to point at the character right behind the text
2313
0
        if (0 > nIndex || nIndex > rCacheTF.GetTextLen( nPara ))
2314
0
            throw lang::IndexOutOfBoundsException();
2315
0
        nRes = rCacheTF.GetLineNumberAtIndex( nPara, nIndex );
2316
0
    }
2317
0
    return nRes;
2318
0
}
2319
2320
// XAccessibleMultiLineText
2321
css::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextAtLineNumber( sal_Int32 nLineNo )
2322
0
{
2323
2324
0
    css::accessibility::TextSegment aResult;
2325
0
    sal_Int32 nPara = GetParagraphIndex();
2326
0
    SvxTextForwarder &rCacheTF = GetTextForwarder();
2327
0
    const bool bValidPara = 0 <= nPara && nPara < rCacheTF.GetParagraphCount();
2328
0
    DBG_ASSERT( bValidPara, "getTextAtLineNumber: current paragraph index out of range" );
2329
0
    if (bValidPara)
2330
0
    {
2331
0
        if (0 > nLineNo || nLineNo >= rCacheTF.GetLineCount( nPara ))
2332
0
            throw lang::IndexOutOfBoundsException();
2333
0
        sal_Int32 nStart = 0, nEnd = 0;
2334
0
        rCacheTF.GetLineBoundaries( nStart, nEnd, nPara, nLineNo );
2335
0
        if (nStart >= 0 && nEnd >=  0)
2336
0
        {
2337
0
            try
2338
0
            {
2339
0
                aResult.SegmentText     = getTextRange( nStart, nEnd );
2340
0
                aResult.SegmentStart    = nStart;
2341
0
                aResult.SegmentEnd      = nEnd;
2342
0
            }
2343
0
            catch (const lang::IndexOutOfBoundsException&)
2344
0
            {
2345
                // this is not the exception that should be raised in this function ...
2346
0
                DBG_UNHANDLED_EXCEPTION("editeng");
2347
0
            }
2348
0
        }
2349
0
    }
2350
0
    return aResult;
2351
0
}
2352
2353
// XAccessibleMultiLineText
2354
css::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextAtLineWithCaret(  )
2355
0
{
2356
2357
0
    css::accessibility::TextSegment aResult;
2358
0
    try
2359
0
    {
2360
0
        aResult = getTextAtLineNumber( getNumberOfLineWithCaret() );
2361
0
    }
2362
0
    catch (const lang::IndexOutOfBoundsException&)
2363
0
    {
2364
        // this one needs to be caught since this interface does not allow for it.
2365
0
    }
2366
0
    return aResult;
2367
0
}
2368
2369
// XAccessibleMultiLineText
2370
sal_Int32 SAL_CALL AccessibleEditableTextPara::getNumberOfLineWithCaret(  )
2371
0
{
2372
2373
0
    sal_Int32 nRes = -1;
2374
0
    try
2375
0
    {
2376
0
        nRes = getLineNumberAtIndex( getCaretPosition() );
2377
0
    }
2378
0
    catch (const lang::IndexOutOfBoundsException&)
2379
0
    {
2380
        // this one needs to be caught since this interface does not allow for it.
2381
0
    }
2382
0
    return nRes;
2383
0
}
2384
2385
}  // end of namespace accessibility
2386
2387
2388
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */