Coverage Report

Created: 2026-04-09 11:41

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