Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/vcl/source/edit/vclmedit.cxx
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <memory>
21
#include <i18nlangtag/languagetag.hxx>
22
#include <vcl/commandevent.hxx>
23
#include <vcl/builder.hxx>
24
#include <vcl/decoview.hxx>
25
#include <vcl/event.hxx>
26
#include <vcl/menu.hxx>
27
#include <vcl/specialchars.hxx>
28
#include <vcl/timer.hxx>
29
#include <vcl/vclevent.hxx>
30
#include <vcl/xtextedt.hxx>
31
#include <vcl/textview.hxx>
32
#include <vcl/ptrstyle.hxx>
33
34
#include <svl/undo.hxx>
35
#include <svl/lstner.hxx>
36
#include <vcl/uitest/uiobject.hxx>
37
38
#include <vcl/settings.hxx>
39
#include <vcl/toolkit/scrbar.hxx>
40
#include <vcl/toolkit/vclmedit.hxx>
41
#include <vcl/weld.hxx>
42
#include <osl/diagnose.h>
43
#include <tools/json_writer.hxx>
44
#include <strings.hrc>
45
#include <svdata.hxx>
46
47
class ImpVclMEdit : public SfxListener
48
{
49
private:
50
    VclPtr<VclMultiLineEdit>   pVclMultiLineEdit;
51
52
    VclPtr<TextWindow>         mpTextWindow;
53
    VclPtr<ScrollBar>          mpHScrollBar;
54
    VclPtr<ScrollBar>          mpVScrollBar;
55
    VclPtr<ScrollBarBox>       mpScrollBox;
56
57
    tools::Long                mnTextWidth;
58
    mutable Selection   maSelection;
59
60
protected:
61
    virtual void        Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
62
    void                ImpUpdateScrollBarVis( WinBits nWinStyle );
63
    void                ImpInitScrollBars();
64
    void                ImpSetScrollBarRanges();
65
    void                ImpSetHScrollBarThumbPos();
66
    DECL_LINK(    ScrollHdl, ScrollBar*, void );
67
68
public:
69
                ImpVclMEdit( VclMultiLineEdit* pVclMultiLineEdit, WinBits nWinStyle );
70
                virtual ~ImpVclMEdit() override;
71
72
    void        SetModified( bool bMod );
73
74
    void        SetReadOnly( bool bRdOnly );
75
    bool        IsReadOnly() const;
76
77
    void        SetMaxTextLen(sal_Int32 nLen);
78
    sal_Int32   GetMaxTextLen() const;
79
80
    void        SetMaxTextWidth(tools::Long nMaxWidth);
81
82
    void        InsertText( const OUString& rStr );
83
    OUString    GetSelected() const;
84
    OUString    GetSelected( LineEnd aSeparator ) const;
85
86
    void        SetSelection( const Selection& rSelection );
87
    const Selection& GetSelection() const;
88
89
    void        Cut();
90
    void        Copy();
91
    void        Paste();
92
93
    void        SetText( const OUString& rStr );
94
    OUString    GetText() const;
95
    OUString    GetText( LineEnd aSeparator ) const;
96
    OUString    GetTextLines( LineEnd aSeparator ) const;
97
98
    void        Resize();
99
    void        GetFocus();
100
101
    bool        HandleCommand( const CommandEvent& rCEvt );
102
103
    void        Enable( bool bEnable );
104
105
    Size        CalcMinimumSize() const;
106
    Size        CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const;
107
    void        GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const;
108
109
    void        SetAlign( WinBits nWinStyle );
110
111
    void        InitFromStyle( WinBits nWinStyle );
112
113
0
    TextWindow* GetTextWindow() { return mpTextWindow; }
114
0
    ScrollBar&  GetHScrollBar() { return *mpHScrollBar; }
115
0
    ScrollBar&  GetVScrollBar() { return *mpVScrollBar; }
116
};
117
118
ImpVclMEdit::ImpVclMEdit( VclMultiLineEdit* pEdt, WinBits nWinStyle )
119
0
    : pVclMultiLineEdit(pEdt)
120
0
    , mpTextWindow(VclPtr<TextWindow>::Create(pEdt))
121
0
    , mpHScrollBar(VclPtr<ScrollBar>::Create(pVclMultiLineEdit, WB_HSCROLL|WB_DRAG))
122
0
    , mpVScrollBar(VclPtr<ScrollBar>::Create(pVclMultiLineEdit, WB_VSCROLL|WB_DRAG))
123
0
    , mpScrollBox(VclPtr<ScrollBarBox>::Create(pVclMultiLineEdit, WB_SIZEABLE))
124
0
    , mnTextWidth(0)
125
0
{
126
0
    mpVScrollBar->SetScrollHdl( LINK( this, ImpVclMEdit, ScrollHdl ) );
127
0
    mpHScrollBar->SetScrollHdl( LINK( this, ImpVclMEdit, ScrollHdl ) );
128
0
    mpTextWindow->Show();
129
0
    InitFromStyle( nWinStyle );
130
0
    StartListening( *mpTextWindow->GetTextEngine() );
131
0
}
132
133
void ImpVclMEdit::ImpUpdateScrollBarVis( WinBits nWinStyle )
134
0
{
135
0
    const bool bHaveVScroll = mpVScrollBar->IsVisible();
136
0
    const bool bHaveHScroll = mpHScrollBar->IsVisible();
137
0
    const bool bHaveScrollBox = mpScrollBox->IsVisible();
138
139
0
    bool bNeedVScroll = ( nWinStyle & WB_VSCROLL ) == WB_VSCROLL;
140
0
    const bool bNeedHScroll = ( nWinStyle & WB_HSCROLL ) == WB_HSCROLL;
141
142
0
    const bool bAutoVScroll = ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL;
143
0
    if ( !bNeedVScroll && bAutoVScroll )
144
0
    {
145
0
        TextEngine& rEngine( *mpTextWindow->GetTextEngine() );
146
0
        tools::Long nOverallTextHeight(0);
147
0
        for ( sal_uInt32 i=0; i<rEngine.GetParagraphCount(); ++i )
148
0
            nOverallTextHeight += rEngine.GetTextHeight( i );
149
0
        if ( nOverallTextHeight > mpTextWindow->GetOutputSizePixel().Height() )
150
0
            bNeedVScroll = true;
151
0
    }
152
153
0
    const bool bNeedScrollBox = bNeedVScroll && bNeedHScroll;
154
155
0
    bool bScrollbarsChanged = false;
156
0
    if ( bHaveVScroll != bNeedVScroll )
157
0
    {
158
0
        mpVScrollBar->Show(bNeedVScroll);
159
0
        bScrollbarsChanged = true;
160
0
    }
161
162
0
    if ( bHaveHScroll != bNeedHScroll )
163
0
    {
164
0
        mpHScrollBar->Show(bNeedHScroll);
165
0
        bScrollbarsChanged = true;
166
0
    }
167
168
0
    if ( bHaveScrollBox != bNeedScrollBox )
169
0
    {
170
0
        mpScrollBox->Show(bNeedScrollBox);
171
0
    }
172
173
0
    if ( bScrollbarsChanged )
174
0
    {
175
0
        ImpInitScrollBars();
176
0
        Resize();
177
0
    }
178
0
}
179
180
void ImpVclMEdit::InitFromStyle( WinBits nWinStyle )
181
0
{
182
0
    ImpUpdateScrollBarVis( nWinStyle );
183
0
    SetAlign( nWinStyle );
184
185
0
    if ( nWinStyle & WB_NOHIDESELECTION )
186
0
        mpTextWindow->SetAutoFocusHide( false );
187
0
    else
188
0
        mpTextWindow->SetAutoFocusHide( true );
189
190
0
    if ( nWinStyle & WB_READONLY )
191
0
        mpTextWindow->GetTextView()->SetReadOnly( true );
192
0
    else
193
0
        mpTextWindow->GetTextView()->SetReadOnly( false );
194
195
0
    if ( nWinStyle & WB_IGNORETAB )
196
0
    {
197
0
        mpTextWindow->SetIgnoreTab( true );
198
0
    }
199
0
    else
200
0
    {
201
0
        mpTextWindow->SetIgnoreTab( false );
202
        // #103667# VclMultiLineEdit has the flag, but focusable window also needs this flag
203
0
        WinBits nStyle = mpTextWindow->GetStyle();
204
0
        nStyle |= WB_NODIALOGCONTROL;
205
0
        mpTextWindow->SetStyle( nStyle );
206
0
    }
207
0
}
208
209
ImpVclMEdit::~ImpVclMEdit()
210
0
{
211
0
    EndListening( *mpTextWindow->GetTextEngine() );
212
0
    mpTextWindow.disposeAndClear();
213
0
    mpHScrollBar.disposeAndClear();
214
0
    mpVScrollBar.disposeAndClear();
215
0
    mpScrollBox.disposeAndClear();
216
0
    pVclMultiLineEdit.disposeAndClear();
217
0
}
218
219
void ImpVclMEdit::ImpSetScrollBarRanges()
220
0
{
221
0
    const tools::Long nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight();
222
0
    mpVScrollBar->SetRange( Range( 0, nTextHeight-1 ) );
223
224
0
    mpHScrollBar->SetRange( Range( 0, mnTextWidth-1 ) );
225
0
}
226
227
void ImpVclMEdit::ImpInitScrollBars()
228
0
{
229
0
    static const sal_Unicode sampleChar = { 'x' };
230
231
0
    ImpSetScrollBarRanges();
232
233
0
    Size aCharBox;
234
0
    aCharBox.setWidth( mpTextWindow->GetTextWidth( OUString(sampleChar) ) );
235
0
    aCharBox.setHeight( mpTextWindow->GetTextHeight() );
236
0
    Size aOutSz = mpTextWindow->GetOutputSizePixel();
237
238
0
    mpHScrollBar->SetVisibleSize( aOutSz.Width() );
239
0
    mpHScrollBar->SetPageSize( aOutSz.Width() * 8 / 10 );
240
0
    mpHScrollBar->SetLineSize( aCharBox.Width()*10 );
241
0
    ImpSetHScrollBarThumbPos();
242
243
0
    mpVScrollBar->SetVisibleSize( aOutSz.Height() );
244
0
    mpVScrollBar->SetPageSize( aOutSz.Height() * 8 / 10 );
245
0
    mpVScrollBar->SetLineSize( aCharBox.Height() );
246
0
    mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() );
247
0
}
248
249
void ImpVclMEdit::ImpSetHScrollBarThumbPos()
250
0
{
251
0
    tools::Long nX = mpTextWindow->GetTextView()->GetStartDocPos().X();
252
0
    if ( !mpTextWindow->GetTextEngine()->IsRightToLeft() )
253
0
        mpHScrollBar->SetThumbPos( nX );
254
0
    else
255
0
        mpHScrollBar->SetThumbPos( mnTextWidth - mpHScrollBar->GetVisibleSize() - nX );
256
257
0
}
258
259
IMPL_LINK( ImpVclMEdit, ScrollHdl, ScrollBar*, pCurScrollBar, void )
260
0
{
261
0
    tools::Long nDiffX = 0, nDiffY = 0;
262
263
0
    if ( pCurScrollBar == mpVScrollBar )
264
0
        nDiffY = mpTextWindow->GetTextView()->GetStartDocPos().Y() - pCurScrollBar->GetThumbPos();
265
0
    else if ( pCurScrollBar == mpHScrollBar )
266
0
        nDiffX = mpTextWindow->GetTextView()->GetStartDocPos().X() - pCurScrollBar->GetThumbPos();
267
268
0
    mpTextWindow->GetTextView()->Scroll( nDiffX, nDiffY );
269
    // mpTextWindow->GetTextView()->ShowCursor( false, true );
270
0
}
271
272
void ImpVclMEdit::SetAlign( WinBits nWinStyle )
273
0
{
274
0
    bool bRTL = AllSettings::GetLayoutRTL();
275
0
    mpTextWindow->GetTextEngine()->SetRightToLeft( bRTL );
276
277
0
    if ( nWinStyle & WB_CENTER )
278
0
        mpTextWindow->GetTextEngine()->SetTextAlign( TxtAlign::Center );
279
0
    else if ( nWinStyle & WB_RIGHT )
280
0
        mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TxtAlign::Right : TxtAlign::Left );
281
0
    else if ( nWinStyle & WB_LEFT )
282
0
        mpTextWindow->GetTextEngine()->SetTextAlign( !bRTL ? TxtAlign::Left : TxtAlign::Right );
283
0
}
284
285
void ImpVclMEdit::SetModified( bool bMod )
286
0
{
287
0
    mpTextWindow->GetTextEngine()->SetModified( bMod );
288
0
}
289
290
void ImpVclMEdit::SetReadOnly( bool bRdOnly )
291
0
{
292
0
    mpTextWindow->GetTextView()->SetReadOnly( bRdOnly );
293
    // TODO: Adjust color?
294
0
}
295
296
bool ImpVclMEdit::IsReadOnly() const
297
0
{
298
0
    return mpTextWindow->GetTextView()->IsReadOnly();
299
0
}
300
301
void ImpVclMEdit::SetMaxTextLen(sal_Int32 nLen)
302
0
{
303
0
    mpTextWindow->GetTextEngine()->SetMaxTextLen(nLen);
304
0
}
305
306
sal_Int32 ImpVclMEdit::GetMaxTextLen() const
307
0
{
308
0
    return mpTextWindow->GetTextEngine()->GetMaxTextLen();
309
0
}
310
311
void ImpVclMEdit::InsertText( const OUString& rStr )
312
0
{
313
0
    mpTextWindow->GetTextView()->InsertText( rStr );
314
0
}
315
316
OUString ImpVclMEdit::GetSelected() const
317
0
{
318
0
    return mpTextWindow->GetTextView()->GetSelected();
319
0
}
320
321
OUString ImpVclMEdit::GetSelected( LineEnd aSeparator ) const
322
0
{
323
0
    return mpTextWindow->GetTextView()->GetSelected( aSeparator );
324
0
}
325
326
void ImpVclMEdit::SetMaxTextWidth(tools::Long nMaxWidth)
327
0
{
328
0
    mpTextWindow->GetTextEngine()->SetMaxTextWidth(nMaxWidth);
329
0
}
330
331
void ImpVclMEdit::Resize()
332
0
{
333
0
    int nIteration = 1;
334
0
    do
335
0
    {
336
0
        WinBits nWinStyle( pVclMultiLineEdit->GetStyle() );
337
0
        if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL )
338
0
            ImpUpdateScrollBarVis( nWinStyle );
339
340
0
        Size aSz = pVclMultiLineEdit->GetOutputSizePixel();
341
0
        Size aEditSize = aSz;
342
0
        tools::Long nSBWidth = pVclMultiLineEdit->GetSettings().GetStyleSettings().GetScrollBarSize();
343
0
        nSBWidth = pVclMultiLineEdit->CalcZoom( nSBWidth );
344
345
0
        if (mpHScrollBar->IsVisible())
346
0
            aSz.AdjustHeight( -(nSBWidth+1) );
347
0
        if (mpVScrollBar->IsVisible())
348
0
            aSz.AdjustWidth( -(nSBWidth+1) );
349
350
0
        if (!mpHScrollBar->IsVisible())
351
0
            mpTextWindow->GetTextEngine()->SetMaxTextWidth( aSz.Width() );
352
0
        else
353
0
            mpHScrollBar->setPosSizePixel( 0, aEditSize.Height()-nSBWidth, aSz.Width(), nSBWidth );
354
355
0
        Point aTextWindowPos;
356
0
        if (mpVScrollBar->IsVisible())
357
0
        {
358
0
            if( AllSettings::GetLayoutRTL() )
359
0
            {
360
0
                mpVScrollBar->setPosSizePixel( 0, 0, nSBWidth, aSz.Height() );
361
0
                aTextWindowPos.AdjustX(nSBWidth );
362
0
            }
363
0
            else
364
0
                mpVScrollBar->setPosSizePixel( aEditSize.Width()-nSBWidth, 0, nSBWidth, aSz.Height() );
365
0
        }
366
367
0
        if (mpScrollBox->IsVisible())
368
0
            mpScrollBox->setPosSizePixel( aSz.Width(), aSz.Height(), nSBWidth, nSBWidth );
369
370
0
        Size aTextWindowSize( aSz );
371
0
        if ( aTextWindowSize.Width() < 0 )
372
0
            aTextWindowSize.setWidth( 0 );
373
0
        if ( aTextWindowSize.Height() < 0 )
374
0
            aTextWindowSize.setHeight( 0 );
375
376
0
        Size aOldTextWindowSize( mpTextWindow->GetSizePixel() );
377
0
        mpTextWindow->SetPosSizePixel( aTextWindowPos, aTextWindowSize );
378
0
        if ( aOldTextWindowSize == aTextWindowSize )
379
0
            break;
380
381
        // Changing the text window size might effectively have changed the need for
382
        // scrollbars, so do another iteration.
383
0
        ++nIteration;
384
0
        OSL_ENSURE( nIteration < 3, "ImpVclMEdit::Resize: isn't this expected to terminate with the second iteration?" );
385
386
0
    } while ( nIteration <= 3 );    // artificial break after four iterations
387
388
0
    ImpInitScrollBars();
389
0
}
390
391
void ImpVclMEdit::GetFocus()
392
0
{
393
0
    mpTextWindow->GrabFocus();
394
0
}
395
396
void ImpVclMEdit::Cut()
397
0
{
398
0
    if ( !mpTextWindow->GetTextView()->IsReadOnly() )
399
0
        mpTextWindow->GetTextView()->Cut();
400
0
}
401
402
void ImpVclMEdit::Copy()
403
0
{
404
0
    mpTextWindow->GetTextView()->Copy();
405
0
}
406
407
void ImpVclMEdit::Paste()
408
0
{
409
0
    if ( !mpTextWindow->GetTextView()->IsReadOnly() )
410
0
        mpTextWindow->GetTextView()->Paste();
411
0
}
412
413
void ImpVclMEdit::SetText( const OUString& rStr )
414
0
{
415
0
    bool bWasModified = mpTextWindow->GetTextEngine()->IsModified();
416
0
    mpTextWindow->GetTextEngine()->SetText( rStr );
417
0
    if ( !bWasModified )
418
0
        mpTextWindow->GetTextEngine()->SetModified( false );
419
420
0
    mpTextWindow->GetTextView()->SetSelection( TextSelection() );
421
422
0
    WinBits nWinStyle( pVclMultiLineEdit->GetStyle() );
423
0
    if ( ( nWinStyle & WB_AUTOVSCROLL ) == WB_AUTOVSCROLL )
424
0
        ImpUpdateScrollBarVis( nWinStyle );
425
0
}
426
427
OUString ImpVclMEdit::GetText() const
428
0
{
429
0
    return mpTextWindow->GetTextEngine()->GetText();
430
0
}
431
432
OUString ImpVclMEdit::GetText( LineEnd aSeparator ) const
433
0
{
434
0
    return mpTextWindow->GetTextEngine()->GetText( aSeparator );
435
0
}
436
437
OUString ImpVclMEdit::GetTextLines( LineEnd aSeparator ) const
438
0
{
439
0
    return mpTextWindow->GetTextEngine()->GetTextLines( aSeparator );
440
0
}
441
442
void ImpVclMEdit::Notify( SfxBroadcaster&, const SfxHint& rHint )
443
0
{
444
0
    switch (rHint.GetId())
445
0
    {
446
0
        case SfxHintId::TextViewScrolled:
447
0
            if (mpHScrollBar->IsVisible())
448
0
                ImpSetHScrollBarThumbPos();
449
0
            if (mpVScrollBar->IsVisible())
450
0
                mpVScrollBar->SetThumbPos( mpTextWindow->GetTextView()->GetStartDocPos().Y() );
451
0
            break;
452
453
0
        case SfxHintId::TextHeightChanged:
454
0
            if ( mpTextWindow->GetTextView()->GetStartDocPos().Y() )
455
0
            {
456
0
                tools::Long nOutHeight = mpTextWindow->GetOutputSizePixel().Height();
457
0
                tools::Long nTextHeight = mpTextWindow->GetTextEngine()->GetTextHeight();
458
0
                if ( nTextHeight < nOutHeight )
459
0
                    mpTextWindow->GetTextView()->Scroll( 0, mpTextWindow->GetTextView()->GetStartDocPos().Y() );
460
0
            }
461
0
            ImpSetScrollBarRanges();
462
0
            break;
463
464
0
        case SfxHintId::TextFormatted:
465
0
            if (mpHScrollBar->IsVisible())
466
0
            {
467
0
                const tools::Long nWidth = mpTextWindow->GetTextEngine()->CalcTextWidth();
468
0
                if ( nWidth != mnTextWidth )
469
0
                {
470
0
                    mnTextWidth = nWidth;
471
0
                    mpHScrollBar->SetRange( Range( 0, mnTextWidth-1 ) );
472
0
                    ImpSetHScrollBarThumbPos();
473
0
                }
474
0
            }
475
0
            break;
476
477
0
        case SfxHintId::TextModified:
478
0
            ImpUpdateScrollBarVis(pVclMultiLineEdit->GetStyle());
479
0
            pVclMultiLineEdit->Modify();
480
0
            break;
481
482
0
        case SfxHintId::TextViewSelectionChanged:
483
0
            pVclMultiLineEdit->SelectionChanged();
484
0
            break;
485
486
0
        case SfxHintId::TextViewCaretChanged:
487
0
            pVclMultiLineEdit->CaretChanged();
488
0
            break;
489
490
0
        default: break;
491
0
    }
492
0
}
493
494
void ImpVclMEdit::SetSelection( const Selection& rSelection )
495
0
{
496
0
    OUString aText = mpTextWindow->GetTextEngine()->GetText();
497
498
0
    Selection aNewSelection( rSelection );
499
0
    if ( aNewSelection.Min() < 0 )
500
0
        aNewSelection.Min() = 0;
501
0
    else if ( aNewSelection.Min() > aText.getLength() )
502
0
        aNewSelection.Min() = aText.getLength();
503
0
    if ( aNewSelection.Max() < 0 )
504
0
        aNewSelection.Max() = 0;
505
0
    else if ( aNewSelection.Max() > aText.getLength() )
506
0
        aNewSelection.Max() = aText.getLength();
507
508
0
    tools::Long nEnd = std::max( aNewSelection.Min(), aNewSelection.Max() );
509
0
    TextSelection aTextSel;
510
0
    sal_uInt32 nPara = 0;
511
0
    sal_Int32 nChar = 0;
512
0
    tools::Long x = 0;
513
0
    while ( x <= nEnd )
514
0
    {
515
0
        if ( x == aNewSelection.Min() )
516
0
            aTextSel.GetStart() = TextPaM( nPara, nChar );
517
0
        if ( x == aNewSelection.Max() )
518
0
            aTextSel.GetEnd() = TextPaM( nPara, nChar );
519
520
0
        if ( ( x < aText.getLength() ) && ( aText[ x ] == '\n' ) )
521
0
        {
522
0
            nPara++;
523
0
            nChar = 0;
524
0
        }
525
0
        else
526
0
            nChar++;
527
0
        x++;
528
0
    }
529
0
    mpTextWindow->GetTextView()->SetSelection( aTextSel );
530
0
}
531
532
const Selection& ImpVclMEdit::GetSelection() const
533
0
{
534
0
    maSelection = Selection();
535
0
    TextSelection aTextSel( mpTextWindow->GetTextView()->GetSelection() );
536
0
    aTextSel.Justify();
537
    // flatten selection => every line-break a character
538
539
0
    ExtTextEngine* pExtTextEngine = mpTextWindow->GetTextEngine();
540
    // paragraphs before
541
0
    for ( sal_uInt32 n = 0; n < aTextSel.GetStart().GetPara(); ++n )
542
0
    {
543
0
        maSelection.Min() += pExtTextEngine->GetTextLen( n );
544
0
        maSelection.Min()++;
545
0
    }
546
547
    // first paragraph with selection
548
0
    maSelection.Max() = maSelection.Min();
549
0
    maSelection.Min() += aTextSel.GetStart().GetIndex();
550
551
0
    for ( sal_uInt32 n = aTextSel.GetStart().GetPara(); n < aTextSel.GetEnd().GetPara(); ++n )
552
0
    {
553
0
        maSelection.Max() += pExtTextEngine->GetTextLen( n );
554
0
        maSelection.Max()++;
555
0
    }
556
557
0
    maSelection.Max() += aTextSel.GetEnd().GetIndex();
558
559
0
    return maSelection;
560
0
}
561
562
Size ImpVclMEdit::CalcMinimumSize() const
563
0
{
564
0
    Size aSz(   mpTextWindow->GetTextEngine()->CalcTextWidth(),
565
0
                mpTextWindow->GetTextEngine()->GetTextHeight() );
566
567
0
    if (mpHScrollBar->IsVisible())
568
0
        aSz.AdjustHeight(mpHScrollBar->GetSizePixel().Height() );
569
0
    if (mpVScrollBar->IsVisible())
570
0
        aSz.AdjustWidth(mpVScrollBar->GetSizePixel().Width() );
571
572
0
    return aSz;
573
0
}
574
575
Size ImpVclMEdit::CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
576
0
{
577
0
    static const sal_Unicode sampleChar = 'X';
578
579
0
    Size aSz;
580
0
    Size aCharSz;
581
0
    aCharSz.setWidth( mpTextWindow->GetTextWidth( OUString(sampleChar) ) );
582
0
    aCharSz.setHeight( mpTextWindow->GetTextHeight() );
583
584
0
    if ( nLines )
585
0
        aSz.setHeight( nLines*aCharSz.Height() );
586
0
    else
587
0
        aSz.setHeight( mpTextWindow->GetTextEngine()->GetTextHeight() );
588
589
0
    if ( nColumns )
590
0
        aSz.setWidth( nColumns*aCharSz.Width() );
591
0
    else
592
0
        aSz.setWidth( mpTextWindow->GetTextEngine()->CalcTextWidth() );
593
594
0
    if (mpHScrollBar->IsVisible())
595
0
        aSz.AdjustHeight(mpHScrollBar->GetSizePixel().Height() );
596
0
    if (mpVScrollBar->IsVisible())
597
0
        aSz.AdjustWidth(mpVScrollBar->GetSizePixel().Width() );
598
599
0
    return aSz;
600
0
}
601
602
void ImpVclMEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
603
0
{
604
0
    static const sal_Unicode sampleChar = { 'x' };
605
0
    Size aOutSz = mpTextWindow->GetOutputSizePixel();
606
0
    Size aCharSz( mpTextWindow->GetTextWidth( OUString(sampleChar) ), mpTextWindow->GetTextHeight() );
607
0
    rnCols = static_cast<sal_uInt16>(aOutSz.Width()/aCharSz.Width());
608
0
    rnLines = static_cast<sal_uInt16>(aOutSz.Height()/aCharSz.Height());
609
0
}
610
611
void ImpVclMEdit::Enable( bool bEnable )
612
0
{
613
0
    mpTextWindow->Enable( bEnable );
614
0
    if (mpHScrollBar->IsVisible())
615
0
        mpHScrollBar->Enable( bEnable );
616
0
    if (mpVScrollBar->IsVisible())
617
0
        mpVScrollBar->Enable( bEnable );
618
0
}
619
620
bool ImpVclMEdit::HandleCommand( const CommandEvent& rCEvt )
621
0
{
622
0
    bool bDone = false;
623
0
    CommandEventId nCommand = rCEvt.GetCommand();
624
0
    if (nCommand == CommandEventId::Wheel ||
625
0
        nCommand == CommandEventId::StartAutoScroll ||
626
0
        nCommand == CommandEventId::AutoScroll ||
627
0
        nCommand == CommandEventId::GesturePan)
628
0
    {
629
0
        ScrollBar* pHScrollBar = mpHScrollBar->IsVisible() ? mpHScrollBar.get() : nullptr;
630
0
        ScrollBar* pVScrollBar = mpVScrollBar->IsVisible() ? mpVScrollBar.get() : nullptr;
631
0
        mpTextWindow->HandleScrollCommand(rCEvt, pHScrollBar, pVScrollBar);
632
0
        bDone = true;
633
0
    }
634
0
    return bDone;
635
0
}
636
637
TextWindow::TextWindow(Edit* pParent)
638
0
    : Window(pParent)
639
0
    , mxParent(pParent)
640
0
{
641
0
    mbInMBDown = false;
642
0
    mbFocusSelectionHide = false;
643
0
    mbIgnoreTab = false;
644
0
    mbActivePopup = false;
645
0
    mbSelectOnTab = true;
646
647
0
    SetPointer( PointerStyle::Text );
648
649
0
    mpExtTextEngine.reset(new ExtTextEngine);
650
0
    mpExtTextEngine->SetMaxTextLen(EDIT_NOLIMIT);
651
0
    if( pParent->GetStyle() & WB_BORDER )
652
0
        mpExtTextEngine->SetLeftMargin( 2 );
653
0
    mpExtTextEngine->SetLocale( GetSettings().GetLanguageTag().getLocale() );
654
0
    mpExtTextView.reset(new TextView( mpExtTextEngine.get(), this ));
655
0
    mpExtTextEngine->InsertView( mpExtTextView.get() );
656
0
    mpExtTextEngine->EnableUndo( true );
657
0
    mpExtTextView->ShowCursor();
658
659
0
    Color aBackgroundColor = GetSettings().GetStyleSettings().GetWorkspaceColor();
660
0
    SetBackground( aBackgroundColor );
661
0
    pParent->SetBackground( aBackgroundColor );
662
0
}
Unexecuted instantiation: TextWindow::TextWindow(Edit*)
Unexecuted instantiation: TextWindow::TextWindow(Edit*)
663
664
TextWindow::~TextWindow()
665
0
{
666
0
    disposeOnce();
667
0
}
668
669
void TextWindow::dispose()
670
0
{
671
0
    mxParent.reset();
672
0
    mpExtTextView.reset();
673
0
    mpExtTextEngine.reset();
674
0
    Window::dispose();
675
0
}
676
677
void TextWindow::MouseMove( const MouseEvent& rMEvt )
678
0
{
679
0
    mpExtTextView->MouseMove( rMEvt );
680
0
    Window::MouseMove( rMEvt );
681
0
}
682
683
void TextWindow::MouseButtonDown( const MouseEvent& rMEvt )
684
0
{
685
0
    mbInMBDown = true;  // so that GetFocus does not select everything
686
0
    mpExtTextView->MouseButtonDown( rMEvt );
687
0
    GrabFocus();
688
0
    mbInMBDown = false;
689
0
}
690
691
void TextWindow::MouseButtonUp( const MouseEvent& rMEvt )
692
0
{
693
0
    mpExtTextView->MouseButtonUp( rMEvt );
694
0
}
695
696
void TextWindow::KeyInput( const KeyEvent& rKEvent )
697
0
{
698
0
    bool bDone = false;
699
0
    sal_uInt16 nCode = rKEvent.GetKeyCode().GetCode();
700
0
    if ( nCode == css::awt::Key::SELECT_ALL ||
701
0
         ( (nCode == KEY_A) && rKEvent.GetKeyCode().IsMod1() && !rKEvent.GetKeyCode().IsMod2() )
702
0
       )
703
0
    {
704
0
        mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
705
0
        bDone = true;
706
0
    }
707
0
    else if ( (nCode == KEY_S) && rKEvent.GetKeyCode().IsShift() && rKEvent.GetKeyCode().IsMod1() )
708
0
    {
709
0
        if ( vcl::GetGetSpecialCharsFunction() )
710
0
        {
711
            // to maintain the selection
712
0
            mbActivePopup = true;
713
0
            OUString aChars = vcl::GetGetSpecialCharsFunction()(GetFrameWeld(), GetFont());
714
0
            if (!aChars.isEmpty())
715
0
            {
716
0
                mpExtTextView->InsertText( aChars );
717
0
                mpExtTextView->GetTextEngine()->SetModified( true );
718
0
            }
719
0
            mbActivePopup = false;
720
0
            bDone = true;
721
0
        }
722
0
    }
723
0
    else if ( nCode == KEY_TAB )
724
0
    {
725
0
        if (!mbIgnoreTab)
726
0
        {
727
0
            if (!rKEvent.GetKeyCode().IsMod1())
728
0
                bDone = mpExtTextView->KeyInput(rKEvent);
729
0
            else
730
0
            {
731
                // tdf#107625 make ctrl+tab act like tab when MultiLine Edit normally accepts tab as an input char
732
0
                vcl::KeyCode aKeyCode(rKEvent.GetKeyCode().GetCode(), rKEvent.GetKeyCode().GetModifier() & ~KEY_MOD1);
733
0
                KeyEvent aKEventWithoutMod1(rKEvent.GetCharCode(), aKeyCode, rKEvent.GetRepeat());
734
0
                Window::KeyInput(aKEventWithoutMod1);
735
0
                bDone = true;
736
0
            }
737
0
        }
738
0
    }
739
0
    else
740
0
    {
741
0
        bDone = mpExtTextView->KeyInput( rKEvent  );
742
0
    }
743
744
0
    if ( !bDone )
745
0
        Window::KeyInput( rKEvent );
746
0
}
747
748
void TextWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
749
0
{
750
0
    mpExtTextView->Paint(rRenderContext, rRect);
751
0
}
752
753
void TextWindow::Resize()
754
0
{
755
0
}
756
757
void TextWindow::Command( const CommandEvent& rCEvt )
758
0
{
759
0
    if ( rCEvt.GetCommand() == CommandEventId::ContextMenu )
760
0
    {
761
0
        VclPtr<PopupMenu> pPopup = mxParent->CreatePopupMenu();
762
0
        bool bEnableCut = true;
763
0
        bool bEnableCopy = true;
764
0
        bool bEnableDelete = true;
765
0
        bool bEnablePaste = true;
766
0
        bool bEnableSpecialChar = true;
767
0
        bool bEnableUndo = true;
768
769
0
        if ( !mpExtTextView->HasSelection() )
770
0
        {
771
0
            bEnableCut = false;
772
0
            bEnableCopy = false;
773
0
            bEnableDelete = false;
774
0
        }
775
0
        if ( mpExtTextView->IsReadOnly() )
776
0
        {
777
0
            bEnableCut = false;
778
0
            bEnablePaste = false;
779
0
            bEnableDelete = false;
780
0
            bEnableSpecialChar = false;
781
0
        }
782
0
        if ( !mpExtTextView->GetTextEngine()->HasUndoManager() || !mpExtTextView->GetTextEngine()->GetUndoManager().GetUndoActionCount() )
783
0
        {
784
0
            bEnableUndo = false;
785
0
        }
786
0
        pPopup->EnableItem(pPopup->GetItemId(u"cut"), bEnableCut);
787
0
        pPopup->EnableItem(pPopup->GetItemId(u"copy"), bEnableCopy);
788
0
        pPopup->EnableItem(pPopup->GetItemId(u"delete"), bEnableDelete);
789
0
        pPopup->EnableItem(pPopup->GetItemId(u"paste"), bEnablePaste);
790
0
        pPopup->SetItemText(pPopup->GetItemId(u"specialchar"),
791
0
            BuilderUtils::convertMnemonicMarkup(VclResId(STR_SPECIAL_CHARACTER_MENU_ENTRY)));
792
0
        pPopup->EnableItem(pPopup->GetItemId(u"specialchar"), bEnableSpecialChar);
793
0
        pPopup->EnableItem(pPopup->GetItemId(u"undo"), bEnableUndo);
794
0
        pPopup->ShowItem(pPopup->GetItemId(u"specialchar"), !vcl::GetGetSpecialCharsFunction());
795
796
0
        mbActivePopup = true;
797
0
        Point aPos = rCEvt.GetMousePosPixel();
798
0
        if ( !rCEvt.IsMouseEvent() )
799
0
        {
800
            // Sometime do show Menu centered in the selection !!!
801
0
            Size aSize = GetOutputSizePixel();
802
0
            aPos = Point( aSize.Width()/2, aSize.Height()/2 );
803
0
        }
804
0
        sal_uInt16 n = pPopup->Execute( this, aPos );
805
0
        OUString sCommand = pPopup->GetItemIdent(n);
806
0
        if (sCommand == "undo")
807
0
        {
808
0
            mpExtTextView->Undo();
809
0
            mpExtTextEngine->SetModified( true );
810
0
            mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
811
0
        }
812
0
        else if (sCommand == "cut")
813
0
        {
814
0
            mpExtTextView->Cut();
815
0
            mpExtTextEngine->SetModified( true );
816
0
            mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
817
0
        }
818
0
        else if (sCommand == "copy")
819
0
        {
820
0
            mpExtTextView->Copy();
821
0
        }
822
0
        else if (sCommand == "paste")
823
0
        {
824
0
            mpExtTextView->Paste();
825
0
            mpExtTextEngine->SetModified( true );
826
0
            mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
827
0
        }
828
0
        else if (sCommand == "delete")
829
0
        {
830
0
            mpExtTextView->DeleteSelected();
831
0
            mpExtTextEngine->SetModified( true );
832
0
            mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
833
0
        }
834
0
        else if (sCommand == "selectall")
835
0
        {
836
0
            mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
837
0
        }
838
0
        else if (sCommand == "specialchar")
839
0
        {
840
0
            OUString aChars = vcl::GetGetSpecialCharsFunction()(GetFrameWeld(), GetFont());
841
0
            if (!aChars.isEmpty())
842
0
            {
843
0
                mpExtTextView->InsertText( aChars );
844
0
                mpExtTextEngine->SetModified( true );
845
0
                mpExtTextEngine->Broadcast( TextHint( SfxHintId::TextModified ) );
846
0
            }
847
0
        }
848
0
        pPopup.reset();
849
0
        mbActivePopup = false;
850
0
    }
851
0
    else
852
0
    {
853
0
        mpExtTextView->Command( rCEvt );
854
0
    }
855
0
    Window::Command( rCEvt );
856
0
}
857
858
void TextWindow::GetFocus()
859
0
{
860
0
    Window::GetFocus();
861
0
    if ( mbActivePopup )
862
0
        return;
863
864
0
    bool bGotoCursor = !mpExtTextView->IsReadOnly();
865
0
    if ( mbFocusSelectionHide && IsReallyVisible() && mbSelectOnTab && !mbInMBDown )
866
0
    {
867
        // select everything, but do not scroll
868
0
        bool bAutoScroll = mpExtTextView->IsAutoScroll();
869
0
        mpExtTextView->SetAutoScroll( false );
870
0
        mpExtTextView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
871
0
        mpExtTextView->SetAutoScroll( bAutoScroll );
872
0
        bGotoCursor = false;
873
0
    }
874
0
    mpExtTextView->SetPaintSelection( true );
875
0
    mpExtTextView->ShowCursor( bGotoCursor );
876
0
}
877
878
void TextWindow::LoseFocus()
879
0
{
880
0
    Window::LoseFocus();
881
882
0
    if ( mbFocusSelectionHide && !mbActivePopup && mpExtTextView )
883
0
        mpExtTextView->SetPaintSelection( false );
884
0
}
885
886
VclMultiLineEdit::VclMultiLineEdit( vcl::Window* pParent, WinBits nWinStyle )
887
0
    : Edit( pParent, nWinStyle )
888
0
{
889
0
    SetType( WindowType::MULTILINEEDIT );
890
0
    pImpVclMEdit.reset(new ImpVclMEdit( this, nWinStyle ));
891
0
    ImplInitSettings( true );
892
893
0
    SetCompoundControl( true );
894
0
    SetStyle( ImplInitStyle( nWinStyle ) );
895
0
}
Unexecuted instantiation: VclMultiLineEdit::VclMultiLineEdit(vcl::Window*, long)
Unexecuted instantiation: VclMultiLineEdit::VclMultiLineEdit(vcl::Window*, long)
896
897
VclMultiLineEdit::~VclMultiLineEdit()
898
0
{
899
0
    disposeOnce();
900
0
}
901
902
void VclMultiLineEdit::dispose()
903
0
{
904
0
    pImpVclMEdit.reset();
905
0
    Edit::dispose();
906
0
}
907
908
WinBits VclMultiLineEdit::ImplInitStyle( WinBits nStyle )
909
0
{
910
0
    if ( !(nStyle & WB_NOTABSTOP) )
911
0
        nStyle |= WB_TABSTOP;
912
913
0
    if ( !(nStyle & WB_NOGROUP) )
914
0
        nStyle |= WB_GROUP;
915
916
0
    if ( !(nStyle & WB_IGNORETAB ))
917
0
        nStyle |= WB_NODIALOGCONTROL;
918
919
0
    return nStyle;
920
0
}
921
922
void VclMultiLineEdit::ApplySettings(vcl::RenderContext& rRenderContext)
923
0
{
924
0
    const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
925
926
    // The Font has to be adjusted, as the TextEngine does not take care of
927
    // TextColor/Background
928
929
0
    Color aTextColor = rStyleSettings.GetFieldTextColor();
930
0
    if (IsControlForeground())
931
0
        aTextColor = GetControlForeground();
932
933
0
    if (!IsEnabled())
934
0
        aTextColor = rStyleSettings.GetDisableColor();
935
936
0
    vcl::Font aFont = rStyleSettings.GetFieldFont();
937
0
    aFont.SetTransparent(IsPaintTransparent());
938
0
    ApplyControlFont(rRenderContext, aFont);
939
940
0
    vcl::Font theFont = rRenderContext.GetFont();
941
0
    theFont.SetColor(aTextColor);
942
0
    if (IsPaintTransparent())
943
0
        theFont.SetFillColor(COL_TRANSPARENT);
944
0
    else
945
0
        theFont.SetFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor());
946
947
0
    pImpVclMEdit->GetTextWindow()->SetFont(theFont);
948
    // FIXME: next call causes infinite invalidation loop, rethink how to properly fix this situation
949
    // pImpVclMEdit->GetTextWindow()->GetTextEngine()->SetFont(theFont);
950
0
    pImpVclMEdit->GetTextWindow()->SetTextColor(aTextColor);
951
952
0
    if (IsPaintTransparent())
953
0
    {
954
0
        pImpVclMEdit->GetTextWindow()->SetPaintTransparent(true);
955
0
        pImpVclMEdit->GetTextWindow()->SetBackground();
956
0
        pImpVclMEdit->GetTextWindow()->SetControlBackground();
957
0
        rRenderContext.SetBackground();
958
0
        SetControlBackground();
959
0
    }
960
0
    else
961
0
    {
962
0
        if (IsControlBackground())
963
0
            pImpVclMEdit->GetTextWindow()->SetBackground(GetControlBackground());
964
0
        else
965
0
            pImpVclMEdit->GetTextWindow()->SetBackground(rStyleSettings.GetFieldColor());
966
        // also adjust for VclMultiLineEdit as the TextComponent might hide Scrollbars
967
0
        rRenderContext.SetBackground(pImpVclMEdit->GetTextWindow()->GetBackground());
968
0
    }
969
0
}
970
971
void VclMultiLineEdit::ImplInitSettings(bool bBackground)
972
0
{
973
0
    const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
974
975
    // The Font has to be adjusted, as the TextEngine does not take care of
976
    // TextColor/Background
977
978
0
    Color aTextColor = rStyleSettings.GetFieldTextColor();
979
0
    if (IsControlForeground())
980
0
        aTextColor = GetControlForeground();
981
0
    if (!IsEnabled())
982
0
        aTextColor = rStyleSettings.GetDisableColor();
983
984
0
    vcl::Font aFont = rStyleSettings.GetFieldFont();
985
0
    aFont.SetTransparent(IsPaintTransparent());
986
0
    ApplyControlFont(*GetOutDev(), aFont);
987
988
0
    vcl::Font TheFont = GetFont();
989
0
    TheFont.SetColor(aTextColor);
990
0
    if (IsPaintTransparent())
991
0
        TheFont.SetFillColor(COL_TRANSPARENT);
992
0
    else
993
0
        TheFont.SetFillColor(IsControlBackground() ? GetControlBackground() : rStyleSettings.GetFieldColor());
994
0
    pImpVclMEdit->GetTextWindow()->SetFont(TheFont);
995
0
    pImpVclMEdit->GetTextWindow()->GetTextEngine()->SetFont(TheFont);
996
0
    pImpVclMEdit->GetTextWindow()->SetTextColor(aTextColor);
997
998
0
    if (!bBackground)
999
0
        return;
1000
1001
0
    if (IsPaintTransparent())
1002
0
    {
1003
0
        pImpVclMEdit->GetTextWindow()->SetPaintTransparent(true);
1004
0
        pImpVclMEdit->GetTextWindow()->SetBackground();
1005
0
        pImpVclMEdit->GetTextWindow()->SetControlBackground();
1006
0
        SetBackground();
1007
0
        SetControlBackground();
1008
0
    }
1009
0
    else
1010
0
    {
1011
0
        if (IsControlBackground())
1012
0
            pImpVclMEdit->GetTextWindow()->SetBackground(GetControlBackground());
1013
0
        else
1014
0
            pImpVclMEdit->GetTextWindow()->SetBackground(rStyleSettings.GetFieldColor());
1015
        // also adjust for VclMultiLineEdit as the TextComponent might hide Scrollbars
1016
0
        SetBackground(pImpVclMEdit->GetTextWindow()->GetBackground());
1017
0
    }
1018
0
}
1019
1020
void VclMultiLineEdit::Modify()
1021
0
{
1022
0
    aModifyHdlLink.Call( *this );
1023
1024
0
    CallEventListeners( VclEventId::EditModify );
1025
0
}
1026
1027
void VclMultiLineEdit::SelectionChanged()
1028
0
{
1029
0
    CallEventListeners(VclEventId::EditSelectionChanged);
1030
0
}
1031
1032
void VclMultiLineEdit::CaretChanged()
1033
0
{
1034
0
    CallEventListeners(VclEventId::EditCaretChanged);
1035
0
}
1036
1037
void VclMultiLineEdit::SetModifyFlag()
1038
0
{
1039
0
    pImpVclMEdit->SetModified( true );
1040
0
}
1041
1042
void VclMultiLineEdit::SetReadOnly( bool bReadOnly )
1043
0
{
1044
0
    pImpVclMEdit->SetReadOnly( bReadOnly );
1045
0
    Edit::SetReadOnly( bReadOnly );
1046
1047
    // #94921# ReadOnly can be overwritten in InitFromStyle() when WB not set.
1048
0
    WinBits nStyle = GetStyle();
1049
0
    if ( bReadOnly )
1050
0
        nStyle |= WB_READONLY;
1051
0
    else
1052
0
        nStyle &= ~WB_READONLY;
1053
0
    SetStyle( nStyle );
1054
0
}
1055
1056
bool VclMultiLineEdit::IsReadOnly() const
1057
0
{
1058
0
    if (!pImpVclMEdit)  // might be called from within the dtor, when pImpVclMEdit == NULL is a valid state
1059
0
        return true;
1060
1061
0
    return pImpVclMEdit->IsReadOnly();
1062
0
}
1063
1064
void VclMultiLineEdit::SetMaxTextLen(sal_Int32 nMaxLen)
1065
0
{
1066
0
    pImpVclMEdit->SetMaxTextLen(nMaxLen);
1067
0
}
1068
1069
void VclMultiLineEdit::SetMaxTextWidth(tools::Long nMaxWidth)
1070
0
{
1071
0
    pImpVclMEdit->SetMaxTextWidth(nMaxWidth );
1072
0
}
1073
1074
sal_Int32 VclMultiLineEdit::GetMaxTextLen() const
1075
0
{
1076
0
    return pImpVclMEdit->GetMaxTextLen();
1077
0
}
1078
1079
void VclMultiLineEdit::ReplaceSelected( const OUString& rStr )
1080
0
{
1081
0
    pImpVclMEdit->InsertText( rStr );
1082
0
}
1083
1084
void VclMultiLineEdit::DeleteSelected()
1085
0
{
1086
0
    pImpVclMEdit->InsertText( OUString() );
1087
0
}
1088
1089
OUString VclMultiLineEdit::GetSelected() const
1090
0
{
1091
0
    return pImpVclMEdit->GetSelected();
1092
0
}
1093
1094
OUString VclMultiLineEdit::GetSelected( LineEnd aSeparator ) const
1095
0
{
1096
0
    return pImpVclMEdit->GetSelected( aSeparator );
1097
0
}
1098
1099
void VclMultiLineEdit::Cut()
1100
0
{
1101
0
    pImpVclMEdit->Cut();
1102
0
}
1103
1104
void VclMultiLineEdit::Copy()
1105
0
{
1106
0
    pImpVclMEdit->Copy();
1107
0
}
1108
1109
void VclMultiLineEdit::Paste()
1110
0
{
1111
0
    pImpVclMEdit->Paste();
1112
0
}
1113
1114
void VclMultiLineEdit::SetText( const OUString& rStr )
1115
0
{
1116
0
    pImpVclMEdit->SetText( rStr );
1117
0
}
1118
1119
OUString VclMultiLineEdit::GetText() const
1120
0
{
1121
0
    return pImpVclMEdit ? pImpVclMEdit->GetText() : OUString();
1122
0
}
1123
1124
OUString VclMultiLineEdit::GetText( LineEnd aSeparator ) const
1125
0
{
1126
0
    return pImpVclMEdit ? pImpVclMEdit->GetText( aSeparator ) : OUString();
1127
0
}
1128
1129
OUString VclMultiLineEdit::GetTextLines( LineEnd aSeparator ) const
1130
0
{
1131
0
    return pImpVclMEdit ? pImpVclMEdit->GetTextLines( aSeparator ) : OUString();
1132
0
}
1133
1134
void VclMultiLineEdit::Resize()
1135
0
{
1136
0
    pImpVclMEdit->Resize();
1137
0
}
1138
1139
void VclMultiLineEdit::GetFocus()
1140
0
{
1141
0
    if ( !pImpVclMEdit )  // might be called from within the dtor, when pImpVclMEdit == NULL is a valid state
1142
0
        return;
1143
1144
0
    pImpVclMEdit->GetFocus();
1145
0
}
1146
1147
void VclMultiLineEdit::SetSelection( const Selection& rSelection )
1148
0
{
1149
0
    pImpVclMEdit->SetSelection( rSelection );
1150
0
}
1151
1152
const Selection& VclMultiLineEdit::GetSelection() const
1153
0
{
1154
0
    return pImpVclMEdit->GetSelection();
1155
0
}
1156
1157
Size VclMultiLineEdit::CalcMinimumSize() const
1158
0
{
1159
0
    Size aSz = pImpVclMEdit->CalcMinimumSize();
1160
1161
0
    sal_Int32 nLeft, nTop, nRight, nBottom;
1162
0
    GetBorder(nLeft, nTop, nRight, nBottom);
1163
0
    aSz.AdjustWidth(nLeft+nRight );
1164
0
    aSz.AdjustHeight(nTop+nBottom );
1165
1166
0
    return aSz;
1167
0
}
1168
1169
Size VclMultiLineEdit::CalcAdjustedSize( const Size& rPrefSize ) const
1170
0
{
1171
0
    Size aSz = rPrefSize;
1172
0
    sal_Int32 nLeft, nTop, nRight, nBottom;
1173
0
    GetBorder(nLeft, nTop, nRight, nBottom);
1174
1175
    // center vertically for whole lines
1176
1177
0
    tools::Long nHeight = aSz.Height() - nTop - nBottom;
1178
0
    tools::Long nLineHeight = pImpVclMEdit->CalcBlockSize( 1, 1 ).Height();
1179
0
    tools::Long nLines = nHeight / nLineHeight;
1180
0
    if ( nLines < 1 )
1181
0
        nLines = 1;
1182
1183
0
    aSz.setHeight( nLines * nLineHeight );
1184
0
    aSz.AdjustHeight(nTop+nBottom );
1185
1186
0
    return aSz;
1187
0
}
1188
1189
Size VclMultiLineEdit::CalcBlockSize( sal_uInt16 nColumns, sal_uInt16 nLines ) const
1190
0
{
1191
0
    Size aSz = pImpVclMEdit->CalcBlockSize( nColumns, nLines );
1192
1193
0
    sal_Int32 nLeft, nTop, nRight, nBottom;
1194
0
    GetBorder(nLeft, nTop, nRight, nBottom);
1195
0
    aSz.AdjustWidth(nLeft+nRight );
1196
0
    aSz.AdjustHeight(nTop+nBottom );
1197
0
    return aSz;
1198
0
}
1199
1200
void VclMultiLineEdit::GetMaxVisColumnsAndLines( sal_uInt16& rnCols, sal_uInt16& rnLines ) const
1201
0
{
1202
0
    pImpVclMEdit->GetMaxVisColumnsAndLines( rnCols, rnLines );
1203
0
}
1204
1205
void VclMultiLineEdit::StateChanged( StateChangedType nType )
1206
0
{
1207
0
    if( nType == StateChangedType::Enable )
1208
0
    {
1209
0
        pImpVclMEdit->Enable( IsEnabled() );
1210
0
        ImplInitSettings( false );
1211
0
    }
1212
0
    else if( nType == StateChangedType::ReadOnly )
1213
0
    {
1214
0
        pImpVclMEdit->SetReadOnly( IsReadOnly() );
1215
0
    }
1216
0
    else if ( nType == StateChangedType::Zoom )
1217
0
    {
1218
0
        pImpVclMEdit->GetTextWindow()->SetZoom( GetZoom() );
1219
0
        ImplInitSettings( false );
1220
0
        Resize();
1221
0
    }
1222
0
    else if ( nType == StateChangedType::ControlFont )
1223
0
    {
1224
0
        ImplInitSettings( false );
1225
0
        Resize();
1226
0
        Invalidate();
1227
0
    }
1228
0
    else if ( nType == StateChangedType::ControlForeground )
1229
0
    {
1230
0
        ImplInitSettings( false );
1231
0
        Invalidate();
1232
0
    }
1233
0
    else if ( nType == StateChangedType::ControlBackground )
1234
0
    {
1235
0
        ImplInitSettings( true );
1236
0
        Invalidate();
1237
0
    }
1238
0
    else if ( nType == StateChangedType::Style )
1239
0
    {
1240
0
        pImpVclMEdit->InitFromStyle( GetStyle() );
1241
0
        SetStyle( ImplInitStyle( GetStyle() ) );
1242
0
    }
1243
0
    else if ( nType == StateChangedType::InitShow )
1244
0
    {
1245
0
        if( IsPaintTransparent() )
1246
0
        {
1247
0
            pImpVclMEdit->GetTextWindow()->SetPaintTransparent( true );
1248
0
            pImpVclMEdit->GetTextWindow()->SetBackground();
1249
0
            pImpVclMEdit->GetTextWindow()->SetControlBackground();
1250
0
            SetBackground();
1251
0
            SetControlBackground();
1252
0
        }
1253
0
    }
1254
1255
0
    Control::StateChanged( nType );
1256
0
}
1257
1258
void VclMultiLineEdit::DataChanged( const DataChangedEvent& rDCEvt )
1259
0
{
1260
0
    if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
1261
0
         (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
1262
0
    {
1263
0
        ImplInitSettings( true );
1264
0
        Resize();
1265
0
        Invalidate();
1266
0
    }
1267
0
    else
1268
0
        Control::DataChanged( rDCEvt );
1269
0
}
1270
1271
void VclMultiLineEdit::Draw( OutputDevice* pDev, const Point& rPos, SystemTextColorFlags nFlags )
1272
0
{
1273
0
    ImplInitSettings(true);
1274
1275
0
    Point aPos = pDev->LogicToPixel( rPos );
1276
0
    Size aSize = GetSizePixel();
1277
1278
0
    vcl::Font aFont = pImpVclMEdit->GetTextWindow()->GetDrawPixelFont(pDev);
1279
0
    aFont.SetTransparent( true );
1280
1281
0
    pDev->Push();
1282
0
    pDev->SetMapMode();
1283
0
    pDev->SetFont( aFont );
1284
0
    pDev->SetTextFillColor();
1285
1286
    // Border/Background
1287
0
    pDev->SetLineColor();
1288
0
    pDev->SetFillColor();
1289
0
    bool bBorder = (GetStyle() & WB_BORDER);
1290
0
    bool bBackground = IsControlBackground();
1291
0
    if ( bBorder || bBackground )
1292
0
    {
1293
0
        tools::Rectangle aRect( aPos, aSize );
1294
0
        if ( bBorder )
1295
0
        {
1296
0
            DecorationView aDecoView( pDev );
1297
0
            aRect = aDecoView.DrawFrame( aRect, DrawFrameStyle::DoubleIn );
1298
0
        }
1299
0
        if ( bBackground )
1300
0
        {
1301
0
            pDev->SetFillColor( GetControlBackground() );
1302
0
            pDev->DrawRect( aRect );
1303
0
        }
1304
0
    }
1305
1306
0
    pDev->SetSystemTextColor(nFlags, IsEnabled());
1307
1308
0
    OUString aText = GetText();
1309
0
    Size aTextSz( pDev->GetTextWidth( aText ), pDev->GetTextHeight() );
1310
0
    sal_uLong nLines = static_cast<sal_uLong>(aSize.Height() / aTextSz.Height());
1311
0
    if ( !nLines )
1312
0
        nLines = 1;
1313
0
    aTextSz.setHeight( nLines*aTextSz.Height() );
1314
0
    tools::Long nOnePixel = GetDrawPixel( pDev, 1 );
1315
0
    tools::Long nOffX = 3*nOnePixel;
1316
0
    tools::Long nOffY = 2*nOnePixel;
1317
1318
    // Clipping?
1319
0
    if ( ( nOffY < 0  ) || ( (nOffY+aTextSz.Height()) > aSize.Height() ) || ( (nOffX+aTextSz.Width()) > aSize.Width() ) )
1320
0
    {
1321
0
        tools::Rectangle aClip( aPos, aSize );
1322
0
        if ( aTextSz.Height() > aSize.Height() )
1323
0
            aClip.AdjustBottom(aTextSz.Height() - aSize.Height() + 1 );  // so that HP-printer does not 'optimize-away'
1324
0
        pDev->IntersectClipRegion( aClip );
1325
0
    }
1326
1327
0
    ExtTextEngine aTE;
1328
0
    aTE.SetText( GetText() );
1329
0
    aTE.SetMaxTextWidth( aSize.Width() );
1330
0
    aTE.SetFont( aFont );
1331
0
    aTE.SetTextAlign( pImpVclMEdit->GetTextWindow()->GetTextEngine()->GetTextAlign() );
1332
0
    aTE.Draw( pDev, Point( aPos.X() + nOffX, aPos.Y() + nOffY ) );
1333
1334
0
    pDev->Pop();
1335
0
}
1336
1337
bool VclMultiLineEdit::EventNotify( NotifyEvent& rNEvt )
1338
0
{
1339
0
    bool bDone = false;
1340
0
    if( rNEvt.GetType() == NotifyEventType::COMMAND )
1341
0
    {
1342
0
        bDone = pImpVclMEdit->HandleCommand( *rNEvt.GetCommandEvent() );
1343
0
    }
1344
0
    return bDone || Edit::EventNotify( rNEvt );
1345
0
}
1346
1347
bool VclMultiLineEdit::PreNotify( NotifyEvent& rNEvt )
1348
0
{
1349
0
    bool bDone = false;
1350
1351
0
    if( ( rNEvt.GetType() == NotifyEventType::KEYINPUT ) && ( !GetTextView()->IsCursorEnabled() ) )
1352
0
    {
1353
0
        const KeyEvent& rKEvent = *rNEvt.GetKeyEvent();
1354
0
        if ( !rKEvent.GetKeyCode().IsShift() && ( rKEvent.GetKeyCode().GetGroup() == KEYGROUP_CURSOR ) )
1355
0
        {
1356
0
            bDone = true;
1357
0
            TextSelection aSel = pImpVclMEdit->GetTextWindow()->GetTextView()->GetSelection();
1358
0
            if ( aSel.HasRange() )
1359
0
            {
1360
0
                aSel.GetStart() = aSel.GetEnd();
1361
0
                pImpVclMEdit->GetTextWindow()->GetTextView()->SetSelection( aSel );
1362
0
            }
1363
0
            else
1364
0
            {
1365
0
                switch ( rKEvent.GetKeyCode().GetCode() )
1366
0
                {
1367
0
                    case KEY_UP:
1368
0
                    {
1369
0
                        if ( pImpVclMEdit->GetVScrollBar().IsVisible() )
1370
0
                            pImpVclMEdit->GetVScrollBar().DoScrollAction( ScrollType::LineUp );
1371
0
                    }
1372
0
                    break;
1373
0
                    case KEY_DOWN:
1374
0
                    {
1375
0
                        if ( pImpVclMEdit->GetVScrollBar().IsVisible() )
1376
0
                            pImpVclMEdit->GetVScrollBar().DoScrollAction( ScrollType::LineDown );
1377
0
                    }
1378
0
                    break;
1379
0
                    case KEY_PAGEUP :
1380
0
                    {
1381
0
                        if ( pImpVclMEdit->GetVScrollBar().IsVisible() )
1382
0
                            pImpVclMEdit->GetVScrollBar().DoScrollAction( ScrollType::PageUp );
1383
0
                    }
1384
0
                    break;
1385
0
                    case KEY_PAGEDOWN:
1386
0
                    {
1387
0
                        if ( pImpVclMEdit->GetVScrollBar().IsVisible() )
1388
0
                            pImpVclMEdit->GetVScrollBar().DoScrollAction( ScrollType::PageDown );
1389
0
                    }
1390
0
                    break;
1391
0
                    case KEY_LEFT:
1392
0
                    {
1393
0
                        if ( pImpVclMEdit->GetHScrollBar().IsVisible() )
1394
0
                            pImpVclMEdit->GetHScrollBar().DoScrollAction( ScrollType::LineUp );
1395
0
                    }
1396
0
                    break;
1397
0
                    case KEY_RIGHT:
1398
0
                    {
1399
0
                        if ( pImpVclMEdit->GetHScrollBar().IsVisible() )
1400
0
                            pImpVclMEdit->GetHScrollBar().DoScrollAction( ScrollType::LineDown );
1401
0
                    }
1402
0
                    break;
1403
0
                    case KEY_HOME:
1404
0
                    {
1405
0
                        if ( rKEvent.GetKeyCode().IsMod1() )
1406
0
                            pImpVclMEdit->GetTextWindow()->GetTextView()->
1407
0
                                SetSelection( TextSelection( TextPaM( 0, 0 ) ) );
1408
0
                    }
1409
0
                    break;
1410
0
                    case KEY_END:
1411
0
                    {
1412
0
                        if ( rKEvent.GetKeyCode().IsMod1() )
1413
0
                            pImpVclMEdit->GetTextWindow()->GetTextView()->
1414
0
                                SetSelection( TextSelection( TextPaM( TEXT_PARA_ALL, TEXT_INDEX_ALL ) ) );
1415
0
                    }
1416
0
                    break;
1417
0
                    default:
1418
0
                    {
1419
0
                        bDone = false;
1420
0
                    }
1421
0
                }
1422
0
            }
1423
0
        }
1424
0
    }
1425
1426
0
    return bDone || Edit::PreNotify( rNEvt );
1427
0
}
1428
1429
// Internals for derived classes, e.g. TextComponent
1430
1431
ExtTextEngine* VclMultiLineEdit::GetTextEngine() const
1432
0
{
1433
0
    return pImpVclMEdit->GetTextWindow()->GetTextEngine();
1434
0
}
1435
1436
TextView* VclMultiLineEdit::GetTextView() const
1437
0
{
1438
0
    return pImpVclMEdit->GetTextWindow()->GetTextView();
1439
0
}
1440
1441
ScrollBar& VclMultiLineEdit::GetVScrollBar() const
1442
0
{
1443
0
    return pImpVclMEdit->GetVScrollBar();
1444
0
}
1445
1446
void VclMultiLineEdit::EnableFocusSelectionHide( bool bHide )
1447
0
{
1448
0
    pImpVclMEdit->GetTextWindow()->SetAutoFocusHide( bHide );
1449
0
}
1450
1451
void VclMultiLineEdit::DisableSelectionOnFocus()
1452
0
{
1453
0
    pImpVclMEdit->GetTextWindow()->DisableSelectionOnFocus();
1454
0
}
1455
1456
void VclMultiLineEdit::EnableCursor( bool bEnable )
1457
0
{
1458
0
    GetTextView()->EnableCursor( bEnable );
1459
0
}
1460
1461
bool VclMultiLineEdit::CanUp() const
1462
0
{
1463
0
    TextView* pTextView = GetTextView();
1464
0
    const TextSelection& rTextSelection = pTextView->GetSelection();
1465
0
    TextPaM aPaM(rTextSelection.GetEnd());
1466
0
    return aPaM != pTextView->CursorUp(aPaM);
1467
0
}
1468
1469
bool VclMultiLineEdit::CanDown() const
1470
0
{
1471
0
    TextView* pTextView = GetTextView();
1472
0
    const TextSelection& rTextSelection = pTextView->GetSelection();
1473
0
    TextPaM aPaM(rTextSelection.GetEnd());
1474
0
    return aPaM != pTextView->CursorDown(aPaM);
1475
0
}
1476
1477
TextWindow* VclMultiLineEdit::GetTextWindow()
1478
0
{
1479
0
    return pImpVclMEdit->GetTextWindow();
1480
0
}
1481
1482
FactoryFunction VclMultiLineEdit::GetUITestFactory() const
1483
0
{
1484
0
    return MultiLineEditUIObject::create;
1485
0
}
1486
1487
bool VclMultiLineEdit::set_property(const OUString &rKey, const OUString &rValue)
1488
0
{
1489
0
    if (rKey == "cursor-visible")
1490
0
        EnableCursor(toBool(rValue));
1491
0
    else if (rKey == "accepts-tab")
1492
0
        pImpVclMEdit->GetTextWindow()->SetIgnoreTab(!toBool(rValue));
1493
0
    else
1494
0
        return Edit::set_property(rKey, rValue);
1495
0
    return true;
1496
0
}
1497
1498
void VclMultiLineEdit::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
1499
0
{
1500
0
    Edit::DumpAsPropertyTree(rJsonWriter);
1501
1502
0
    rJsonWriter.put("cursor", pImpVclMEdit->GetTextWindow()->GetTextView()->IsCursorEnabled());
1503
0
}
1504
1505
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */