Coverage Report

Created: 2026-07-10 11:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sw/source/uibase/ribbar/inputwin.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 <sal/config.h>
21
#include <sal/log.hxx>
22
23
#include <osl/diagnose.h>
24
#include <comphelper/string.hxx>
25
#include <o3tl/safeint.hxx>
26
#include <officecfg/Office/Common.hxx>
27
#include <tools/gen.hxx>
28
#include <sfx2/chalign.hxx>
29
#include <sfx2/objface.hxx>
30
#include <sfx2/viewfrm.hxx>
31
#include <sfx2/dispatch.hxx>
32
#include <svx/ruler.hxx>
33
#include <svl/stritem.hxx>
34
#include <vcl/event.hxx>
35
#include <vcl/image.hxx>
36
#include <vcl/svapp.hxx>
37
#include <vcl/weld/Menu.hxx>
38
#include <vcl/weld/Window.hxx>
39
#include <vcl/weld/weldutils.hxx>
40
41
#include <swtypes.hxx>
42
#include <cmdid.h>
43
#include <swmodule.hxx>
44
#include <wrtsh.hxx>
45
#include <view.hxx>
46
#include <inputwin.hxx>
47
#include <fldbas.hxx>
48
#include <fldmgr.hxx>
49
#include <frmfmt.hxx>
50
#include <cellatr.hxx>
51
#include <edtwin.hxx>
52
#include <helpids.h>
53
#include <strings.hrc>
54
#include <bitmaps.hlst>
55
56
// Only for the UpdateRange: Delete the box in which the stacked cursor is positioned.
57
#include <pam.hxx>
58
59
#include <swundo.hxx>
60
61
#include <IDocumentContentOperations.hxx>
62
63
constexpr ToolBoxItemId ED_POS(2);
64
constexpr ToolBoxItemId ED_FORMULA(3);
65
constexpr ToolBoxItemId FN_FORMULA_CALC(FN_FORMAT + 156);  /* select formula */
66
constexpr ToolBoxItemId FN_FORMULA_CANCEL(FN_FORMAT + 157);  /* don't apply formula */
67
constexpr ToolBoxItemId FN_FORMULA_APPLY(FN_FORMAT + 158); /* apply formula */
68
69
SFX_IMPL_POS_CHILDWINDOW_WITHID( SwInputChild, FN_EDIT_FORMULA, SFX_OBJECTBAR_OBJECT )
70
71
IMPL_LINK(PosEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool)
72
0
{
73
0
    return ChildKeyInput(rKEvt);
74
0
}
75
76
SwInputWindow::SwInputWindow(vcl::Window* pParent, SfxDispatcher const * pDispatcher)
77
0
    : ToolBox(pParent, WB_3DLOOK|WB_BORDER)
78
0
    , mxPos(VclPtr<PosEdit>::Create(this))
79
0
    , mxEdit(VclPtr<InputEdit>::Create(this))
80
0
    , m_pWrtShell(nullptr)
81
0
    , m_pView(nullptr)
82
0
    , m_bDoesUndo(true)
83
0
    , m_bResetUndo(false)
84
0
    , m_bCallUndo(false)
85
0
{
86
0
    m_bFirst = true;
87
0
    m_bIsTable = m_bDelSel = false;
88
89
0
    InsertItem(FN_FORMULA_CALC, Image(StockImage::Yes, RID_BMP_FORMULA_CALC),
90
0
               SwResId(STR_FORMULA_CALC));
91
0
    InsertItem(FN_FORMULA_CANCEL, Image(StockImage::Yes, RID_BMP_FORMULA_CANCEL),
92
0
               SwResId(STR_FORMULA_CANCEL));
93
0
    InsertItem(FN_FORMULA_APPLY, Image(StockImage::Yes, RID_BMP_FORMULA_APPLY),
94
0
               SwResId(STR_FORMULA_APPLY));
95
96
0
    SetHelpId(FN_FORMULA_CALC, HID_TBX_FORMULA_CALC);
97
0
    SetHelpId(FN_FORMULA_CANCEL, HID_TBX_FORMULA_CANCEL);
98
0
    SetHelpId(FN_FORMULA_APPLY, HID_TBX_FORMULA_APPLY);
99
100
0
    SwView *pDispatcherView = dynamic_cast<SwView*>(pDispatcher ? pDispatcher->GetFrame()->GetViewShell() : nullptr);
101
0
    SwView* pActiveView = ::GetActiveView();
102
0
    if (pDispatcherView == pActiveView)
103
0
        m_pView = pActiveView;
104
0
    m_pWrtShell = m_pView ? m_pView->GetWrtShellPtr() : nullptr;
105
106
0
    InsertWindow(ED_POS, mxPos.get(), ToolBoxItemBits::NONE, 0);
107
0
    SetItemText(ED_POS, SwResId(STR_ACCESS_FORMULA_TYPE));
108
0
    mxPos->set_accessible_name(SwResId(STR_ACCESS_FORMULA_TYPE));
109
0
    SetAccessibleName(SwResId(STR_ACCESS_FORMULA_TOOLBAR));
110
0
    InsertSeparator ( 1 );
111
0
    InsertSeparator ();
112
0
    InsertWindow(ED_FORMULA, mxEdit.get());
113
0
    SetItemText(ED_FORMULA, SwResId(STR_ACCESS_FORMULA_TEXT));
114
0
    mxEdit->set_accessible_name(SwResId(STR_ACCESS_FORMULA_TEXT));
115
0
    SetHelpId(ED_FORMULA, HID_EDIT_FORMULA);
116
117
0
    SetItemBits( FN_FORMULA_CALC, GetItemBits( FN_FORMULA_CALC ) | ToolBoxItemBits::DROPDOWNONLY );
118
0
    SetDropdownClickHdl( LINK( this, SwInputWindow, DropdownClickHdl ));
119
120
0
    Size    aSizeTbx = CalcWindowSizePixel();
121
0
    Size    aEditSize = mxEdit->GetSizePixel();
122
0
    tools::Rectangle aItemRect( GetItemRect(FN_FORMULA_CALC) );
123
0
    tools::Long nMaxHeight = std::max(aEditSize.Height(), aItemRect.GetHeight());
124
0
    if( nMaxHeight+2 > aSizeTbx.Height() )
125
0
        aSizeTbx.setHeight( nMaxHeight+2 );
126
0
    Size aSize = GetSizePixel();
127
0
    aSize.setHeight( aSizeTbx.Height() );
128
0
    SetSizePixel( aSize );
129
130
    // align edit and item vcentered
131
0
    Size    aPosSize = mxPos->GetSizePixel();
132
0
    aPosSize.setHeight( nMaxHeight );
133
0
    aEditSize.setHeight( nMaxHeight );
134
0
    Point aPosPos  = mxPos->GetPosPixel();
135
0
    Point aEditPos = mxEdit->GetPosPixel();
136
0
    aPosPos.setY( (aSize.Height() - nMaxHeight)/2 + 1 );
137
0
    aEditPos.setY( (aSize.Height() - nMaxHeight)/2 + 1 );
138
0
    mxPos->SetPosSizePixel( aPosPos, aPosSize );
139
0
    mxEdit->SetPosSizePixel( aEditPos, aEditSize );
140
0
}
Unexecuted instantiation: SwInputWindow::SwInputWindow(vcl::Window*, SfxDispatcher const*)
Unexecuted instantiation: SwInputWindow::SwInputWindow(vcl::Window*, SfxDispatcher const*)
141
142
SwInputWindow::~SwInputWindow()
143
0
{
144
0
    disposeOnce();
145
0
}
146
147
void SwInputWindow::dispose()
148
0
{
149
    // wake rulers
150
0
    if(m_pView)
151
0
    {
152
0
        m_pView->GetHRuler().SetActive();
153
0
        m_pView->GetVRuler().SetActive();
154
0
    }
155
0
    m_pMgr.reset();
156
0
    if(m_pWrtShell)
157
0
        m_pWrtShell->EndSelTableCells();
158
159
0
    CleanupUglyHackWithUndo();
160
161
0
    mxPos.disposeAndClear();
162
0
    mxEdit.disposeAndClear();
163
0
    ToolBox::dispose();
164
0
}
165
166
void SwInputWindow::CleanupUglyHackWithUndo()
167
0
{
168
0
    if (!m_bResetUndo)
169
0
        return;
170
171
0
    if (m_pWrtShell)
172
0
    {
173
0
        DelBoxContent();
174
0
        m_pWrtShell->DoUndo(m_bDoesUndo);
175
0
        if (m_bCallUndo)
176
0
        {
177
0
            m_pWrtShell->Undo();
178
0
        }
179
0
    }
180
0
    m_bResetUndo = false; // #i117122# once is enough :)
181
0
}
182
183
void SwInputWindow::Resize()
184
0
{
185
0
    ToolBox::Resize();
186
187
0
    tools::Long    nWidth      = GetSizePixel().Width();
188
0
    tools::Long    nLeft       = mxEdit->GetPosPixel().X();
189
0
    Size    aEditSize   = mxEdit->GetSizePixel();
190
191
0
    aEditSize.setWidth( std::max( static_cast<tools::Long>(nWidth - nLeft - 5), tools::Long(0) ) );
192
0
    mxEdit->SetSizePixel( aEditSize );
193
0
}
194
195
void SwInputWindow::ShowWin()
196
0
{
197
0
    m_bIsTable = false;
198
    // stop rulers
199
0
    if (m_pView && m_pWrtShell)
200
0
    {
201
0
        m_pView->GetHRuler().SetActive( false );
202
0
        m_pView->GetVRuler().SetActive( false );
203
204
        // Cursor in table
205
0
        m_bIsTable = m_pWrtShell->IsCursorInTable();
206
207
0
        if( m_bFirst )
208
0
            m_pWrtShell->SelTableCells( LINK( this, SwInputWindow,
209
0
                                                SelTableCellsNotify) );
210
0
        if( m_bIsTable )
211
0
        {
212
0
            const OUString aPos = m_pWrtShell->GetBoxNms();
213
0
            sal_Int32 nPos = 0;
214
0
            short nSrch = -1;
215
0
            while( (nPos = aPos.indexOf( ':',nPos + 1 ) ) != -1 )
216
0
                nSrch = static_cast<short>(nPos);
217
0
            mxPos->set_text( aPos.copy( ++nSrch ) );
218
0
            m_aCurrentTableName = m_pWrtShell->GetTableFormat()->GetName();
219
0
        }
220
0
        else
221
0
            mxPos->set_text(SwResId(STR_TBL_FORMULA));
222
223
        // Edit current field
224
0
        OSL_ENSURE(m_pMgr == nullptr, "FieldManager not deleted");
225
0
        m_pMgr.reset(new SwFieldMgr);
226
227
        // Form should always begin with "=" , so set here
228
0
        OUString sEdit('=');
229
0
        if( m_pMgr->GetCurField() && SwFieldTypesEnum::Formel == m_pMgr->GetCurTypeId() )
230
0
        {
231
0
            sEdit += m_pMgr->GetCurFieldPar2();
232
0
        }
233
0
        else if( m_bFirst && m_bIsTable )
234
0
        {
235
0
            m_bResetUndo = true;
236
0
            SAL_WARN_IF(
237
0
                officecfg::Office::Common::Undo::Steps::get() <= 0,
238
0
                "sw", "/org.openoffice.Office.Common/Undo/Steps <= 0");
239
240
0
            m_bDoesUndo = m_pWrtShell->DoesUndo();
241
0
            if( !m_bDoesUndo )
242
0
            {
243
0
                m_pWrtShell->DoUndo();
244
0
            }
245
246
0
            if( !m_pWrtShell->SwCursorShell::HasSelection() )
247
0
            {
248
0
                m_pWrtShell->MoveSection( GoCurrSection, fnSectionStart );
249
0
                m_pWrtShell->SetMark();
250
0
                m_pWrtShell->MoveSection( GoCurrSection, fnSectionEnd );
251
0
            }
252
0
            if( m_pWrtShell->SwCursorShell::HasSelection() )
253
0
            {
254
0
                m_pWrtShell->StartUndo( SwUndoId::DELETE );
255
0
                m_pWrtShell->Delete(false);
256
0
                if( SwUndoId::EMPTY != m_pWrtShell->EndUndo( SwUndoId::DELETE ))
257
0
                {
258
0
                    m_bCallUndo = true;
259
0
                }
260
0
            }
261
0
            m_pWrtShell->DoUndo(false);
262
263
0
            SfxItemSet aSet(SfxItemSet::makeFixedSfxItemSet<RES_BOXATR_FORMULA, RES_BOXATR_FORMULA>( m_pWrtShell->GetAttrPool() ));
264
0
            if( m_pWrtShell->GetTableBoxFormulaAttrs( aSet ))
265
0
            {
266
0
                SwTableBoxFormula& rFormula
267
0
                    = const_cast<SwTableBoxFormula&>(aSet.Get(RES_BOXATR_FORMULA));
268
                // rFormula could be ANY of the table's formulas.
269
                // GetFormula returns the "current" formula - which is basically undefined,
270
                // so do something that encourages the current position's formula to become current.
271
0
                if (m_pWrtShell->GetCursor())
272
0
                {
273
0
                    const SwNode* pNd = m_pWrtShell->GetCursor()->GetPointNode().FindTableNode();
274
0
                    if (pNd)
275
0
                    {
276
0
                        const SwTable& rTable = static_cast<const SwTableNode*>(pNd)->GetTable();
277
                        // get cell's external formula (for UI) by waving the magic wand.
278
0
                        rFormula.PtrToBoxNm(&rTable);
279
0
                    }
280
0
                }
281
282
0
                sEdit += rFormula.GetFormula();
283
0
            }
284
0
        }
285
286
0
        if( m_bFirst )
287
0
        {
288
            // Set WrtShell flags correctly
289
0
            m_pWrtShell->SttSelect();
290
0
            m_pWrtShell->EndSelect();
291
0
        }
292
293
0
        m_bFirst = false;
294
295
0
        mxEdit->connect_changed( LINK( this, SwInputWindow, ModifyHdl ));
296
297
0
        mxEdit->set_text( sEdit );
298
0
        m_sOldFormula = sEdit;
299
300
        // For input cut the UserInterface
301
302
0
        m_pView->GetEditWin().LockKeyInput(true);
303
0
        m_pView->GetViewFrame().GetDispatcher()->Lock(true);
304
0
        m_pWrtShell->Push();
305
0
    }
306
307
0
    ToolBox::Show();
308
309
    // grab focus after ToolBox is shown so focus isn't potentially lost elsewhere
310
0
    if (m_pView)
311
0
    {
312
0
        int nPos = mxEdit->get_text().getLength();
313
0
        mxEdit->select_region(nPos, nPos);
314
0
        mxEdit->GrabFocus();
315
0
    }
316
0
}
317
318
void SwInputWindow::MenuHdl(std::u16string_view command)
319
0
{
320
0
    if (!command.empty())
321
0
        mxEdit->replace_selection(OUString::Concat(command) + " ");
322
0
}
323
324
IMPL_LINK_NOARG(SwInputWindow, DropdownClickHdl, ToolBox *, void)
325
0
{
326
0
    ToolBoxItemId nCurID = GetCurItemId();
327
0
    EndSelection(); // reset back CurItemId !
328
0
    if (nCurID == FN_FORMULA_CALC)
329
0
    {
330
0
        std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(nullptr, u"modules/swriter/ui/inputwinmenu.ui"_ustr));
331
0
        std::unique_ptr<weld::Menu> xPopMenu(xBuilder->weld_menu(u"menu"_ustr));
332
0
        tools::Rectangle aRect(GetItemRect(FN_FORMULA_CALC));
333
0
        weld::Window* pParent = weld::GetPopupParent(*this, aRect);
334
0
        MenuHdl(xPopMenu->popup_at_rect(pParent, aRect));
335
0
    }
336
0
}
337
338
void SwInputWindow::Click( )
339
0
{
340
0
    ToolBoxItemId nCurID = GetCurItemId();
341
0
    EndSelection(); // reset back CurItemId !
342
0
    if ( nCurID == FN_FORMULA_CANCEL )
343
0
    {
344
0
        CancelFormula();
345
0
    }
346
0
    else if (nCurID == FN_FORMULA_APPLY)
347
0
    {
348
0
        ApplyFormula();
349
0
    }
350
0
}
351
352
void  SwInputWindow::ApplyFormula()
353
0
{
354
    // in case it was created while loading the document, the active view
355
    // wasn't initialised at that time, so ShowWin() didn't initialise anything
356
    // either - nothing to do
357
0
    if (!m_pView || !m_pWrtShell)
358
0
    {
359
        // presumably there must be an active view now since the event arrived
360
0
        if (SwView* pView = GetActiveView())
361
0
        {
362
            // this just makes the input window go away, so that the next time it works
363
0
            pView->GetViewFrame().GetDispatcher()->Execute(FN_EDIT_FORMULA, SfxCallMode::ASYNCHRON);
364
0
        }
365
0
        return;
366
0
    }
367
368
0
    m_pView->GetViewFrame().GetDispatcher()->Lock(false);
369
0
    m_pView->GetEditWin().LockKeyInput(false);
370
0
    CleanupUglyHackWithUndo();
371
0
    m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
372
373
    // Form should always begin with "=", so remove it here again
374
0
    OUString sEdit(comphelper::string::strip(mxEdit->get_text(), ' '));
375
0
    if( !sEdit.isEmpty() && '=' == sEdit[0] )
376
0
        sEdit = sEdit.copy( 1 );
377
0
    SfxStringItem aParam(FN_EDIT_FORMULA, sEdit);
378
379
0
    m_pWrtShell->EndSelTableCells();
380
0
    m_pView->GetEditWin().GrabFocus();
381
0
    const SfxPoolItem* aArgs[2];
382
0
    aArgs[0] = &aParam;
383
0
    aArgs[1] = nullptr;
384
0
    m_pView->GetViewFrame().GetBindings().Execute( FN_EDIT_FORMULA, aArgs, SfxCallMode::ASYNCHRON );
385
0
}
386
387
void  SwInputWindow::CancelFormula()
388
0
{
389
    // in case it was created while loading the document, the active view
390
    // wasn't initialised at that time, so ShowWin() didn't initialise anything
391
    // either - nothing to do
392
0
    if (!m_pView || !m_pWrtShell)
393
0
    {
394
        // presumably there must be an active view now since the event arrived
395
0
        if (SwView* pView = GetActiveView())
396
0
        {
397
            // this just makes the input window go away, so that the next time it works
398
0
            pView->GetViewFrame().GetDispatcher()->Execute(FN_EDIT_FORMULA, SfxCallMode::ASYNCHRON);
399
0
        }
400
0
        return;
401
0
    }
402
403
0
    m_pView->GetViewFrame().GetDispatcher()->Lock( false );
404
0
    m_pView->GetEditWin().LockKeyInput(false);
405
0
    CleanupUglyHackWithUndo();
406
0
    m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
407
408
0
    if( m_bDelSel )
409
0
        m_pWrtShell->EnterStdMode();
410
411
0
    m_pWrtShell->EndSelTableCells();
412
413
0
    m_pView->GetEditWin().GrabFocus();
414
415
0
    m_pView->GetViewFrame().GetDispatcher()->Execute( FN_EDIT_FORMULA, SfxCallMode::ASYNCHRON);
416
0
}
417
418
const sal_Unicode CH_LRE = 0x202a;
419
const sal_Unicode CH_PDF = 0x202c;
420
421
IMPL_LINK( SwInputWindow, SelTableCellsNotify, SwWrtShell&, rCaller, void )
422
0
{
423
0
    if(m_pWrtShell && m_bIsTable)
424
0
    {
425
0
        SwFrameFormat* pTableFormat = rCaller.GetTableFormat();
426
0
        OUString sBoxNms( rCaller.GetBoxNms() );
427
0
        UIName sTableNm;
428
0
        if( pTableFormat && m_aCurrentTableName != pTableFormat->GetName() )
429
0
            sTableNm = pTableFormat->GetName();
430
431
0
        mxEdit->UpdateRange( sBoxNms, sTableNm );
432
433
0
        OUString sNew = OUStringChar(CH_LRE) + mxEdit->get_text()
434
0
            + OUStringChar(CH_PDF);
435
436
0
        if( sNew != m_sOldFormula )
437
0
        {
438
            // The WrtShell is in the table selection,
439
            // then cancel the table selection otherwise, the cursor is
440
            // positioned "in the forest" and the live update does not work!
441
0
            m_pWrtShell->StartAllAction();
442
443
0
            SwPaM aPam( *m_pWrtShell->GetStackCursor()->GetPoint() );
444
0
            aPam.Move( fnMoveBackward, GoInSection );
445
0
            aPam.SetMark();
446
0
            aPam.Move( fnMoveForward, GoInSection );
447
448
0
            IDocumentContentOperations& rIDCO = m_pWrtShell->getIDocumentContentOperations();
449
0
            rIDCO.DeleteRange( aPam );
450
0
            rIDCO.InsertString( aPam, sNew );
451
0
            m_pWrtShell->EndAllAction();
452
0
            m_sOldFormula = sNew;
453
0
        }
454
0
    }
455
0
    else
456
0
        mxEdit->GrabFocus();
457
0
}
458
459
void SwInputWindow::SetFormula( const OUString& rFormula )
460
0
{
461
0
    OUString sEdit('=');
462
0
    if( !rFormula.isEmpty() )
463
0
    {
464
0
        if( '=' == rFormula[0] )
465
0
            sEdit = rFormula;
466
0
        else
467
0
            sEdit += rFormula;
468
0
    }
469
0
    mxEdit->set_text( sEdit );
470
0
    mxEdit->select_region(sEdit.getLength(), sEdit.getLength());
471
0
    m_bDelSel = true;
472
0
}
473
474
IMPL_LINK_NOARG(SwInputWindow, ModifyHdl, weld::Entry&, void)
475
0
{
476
0
    if (m_pWrtShell && m_bIsTable && m_bResetUndo)
477
0
    {
478
0
        m_pWrtShell->StartAllAction();
479
0
        DelBoxContent();
480
0
        OUString sNew = OUStringChar(CH_LRE) + mxEdit->get_text()
481
0
            + OUStringChar(CH_PDF);
482
0
        m_pWrtShell->SwEditShell::Insert2( sNew );
483
0
        m_pWrtShell->EndAllAction();
484
0
        m_sOldFormula = sNew;
485
0
    }
486
0
}
487
488
void SwInputWindow::DelBoxContent()
489
0
{
490
0
    if( m_pWrtShell && m_bIsTable )
491
0
    {
492
0
        m_pWrtShell->StartAllAction();
493
0
        m_pWrtShell->ClearMark();
494
0
        m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
495
0
        m_pWrtShell->Push();
496
0
        m_pWrtShell->MoveSection( GoCurrSection, fnSectionStart );
497
0
        m_pWrtShell->SetMark();
498
0
        m_pWrtShell->MoveSection( GoCurrSection, fnSectionEnd );
499
0
        m_pWrtShell->SwEditShell::Delete(false);
500
0
        m_pWrtShell->EndAllAction();
501
0
    }
502
0
}
503
504
IMPL_LINK(InputEdit, KeyInputHdl, const KeyEvent&, rEvent, bool)
505
0
{
506
0
    bool bHandled = false;
507
0
    const vcl::KeyCode aCode = rEvent.GetKeyCode();
508
0
    if (aCode == KEY_RETURN || aCode == KEY_F2)
509
0
    {
510
0
        bHandled = ActivateHdl(*m_xWidget);
511
0
    }
512
0
    else if(aCode == KEY_ESCAPE )
513
0
    {
514
0
        static_cast<SwInputWindow*>(GetParent())->CancelFormula();
515
0
        bHandled = true;
516
0
    }
517
0
    return bHandled || ChildKeyInput(rEvent);
518
0
}
519
520
IMPL_LINK_NOARG(InputEdit, ActivateHdl, weld::Entry&, bool)
521
0
{
522
0
    static_cast<SwInputWindow*>(GetParent())->ApplyFormula();
523
0
    return true;
524
0
}
525
526
void InputEdit::UpdateRange(std::u16string_view rBoxes,
527
                                    const UIName& rName )
528
0
{
529
0
    if( rBoxes.empty() )
530
0
    {
531
0
        GrabFocus();
532
0
        return;
533
0
    }
534
0
    const sal_Unicode   cOpen = '<', cClose = '>',
535
0
                cOpenBracket = '(';
536
0
    OUString aPrefix = rName.toString();
537
0
    if(!rName.isEmpty())
538
0
        aPrefix += ".";
539
0
    OUString aBoxes = aPrefix + rBoxes;
540
541
0
    int nSelStartPos, nSelEndPos;
542
0
    m_xWidget->get_selection_bounds(nSelStartPos, nSelEndPos);
543
544
0
    Selection aSelection(nSelStartPos, nSelEndPos);
545
0
    sal_uInt16 nSel = o3tl::narrowing<sal_uInt16>(aSelection.Len());
546
    // OS: The following expression ensures that in the overwrite mode,
547
    // the selected closing parenthesis will be not deleted.
548
0
    if( nSel && ( nSel > 1 ||
549
0
                  m_xWidget->get_text()[ o3tl::narrowing<sal_uInt16>(aSelection.Min()) ] != cClose ))
550
0
        m_xWidget->cut_clipboard();
551
0
    else
552
0
        aSelection.Max() = aSelection.Min();
553
0
    OUString aActText(m_xWidget->get_text());
554
0
    const sal_uInt16 nLen = aActText.getLength();
555
0
    if( !nLen )
556
0
    {
557
0
        OUString aStr = OUStringChar(cOpen) + aBoxes + OUStringChar(cClose);
558
0
        m_xWidget->set_text(aStr);
559
0
        sal_Int32 nPos = aStr.indexOf( cClose );
560
0
        OSL_ENSURE(nPos != -1, "delimiter not found");
561
0
        ++nPos;
562
0
        m_xWidget->select_region(nPos, nPos);
563
0
    }
564
0
    else
565
0
    {
566
0
        bool bFound = false;
567
0
        sal_Unicode cCh;
568
0
        sal_uInt16 nPos, nEndPos = 0, nStartPos = o3tl::narrowing<sal_uInt16>(aSelection.Min());
569
0
        if( nStartPos-- )
570
0
        {
571
0
            do {
572
0
                if( cOpen  == (cCh = aActText[ nStartPos ] ) ||
573
0
                    cOpenBracket == cCh )
574
0
                {
575
0
                    bFound = cCh == cOpen;
576
0
                    break;
577
0
                }
578
0
            } while( nStartPos-- > 0 );
579
0
        }
580
0
        if( bFound )
581
0
        {
582
0
            bFound = false;
583
0
            nEndPos = nStartPos;
584
0
            while( nEndPos < nLen )
585
0
            {
586
0
                if( cClose == aActText[ nEndPos ] )
587
0
                {
588
0
                    bFound = true;
589
0
                    break;
590
0
                }
591
0
                ++nEndPos;
592
0
            }
593
            // Only if the current position lies in the range or right behind.
594
0
            if( bFound && ( nStartPos >= o3tl::make_unsigned(aSelection.Max()) ||
595
0
                             o3tl::narrowing<sal_uInt16>(aSelection.Max()) > nEndPos + 1 ))
596
0
                bFound = false;
597
0
        }
598
0
        if( bFound )
599
0
        {
600
0
            nPos = ++nStartPos + 1; // We want behind
601
0
            aActText = aActText.replaceAt( nStartPos, nEndPos - nStartPos, aBoxes );
602
0
            nPos = nPos + aBoxes.getLength();
603
0
        }
604
0
        else
605
0
        {
606
0
            OUString aTmp = OUStringChar(cOpen) + aBoxes + OUStringChar(cClose);
607
0
            nPos = o3tl::narrowing<sal_uInt16>(aSelection.Min());
608
0
            aActText = aActText.replaceAt( nPos, 0, aTmp );
609
0
            nPos = nPos + aTmp.getLength();
610
0
        }
611
0
        if( m_xWidget->get_text() != aActText )
612
0
        {
613
0
            m_xWidget->set_text(aActText);
614
0
            m_xWidget->select_region(nPos, nPos);
615
0
        }
616
0
    }
617
0
    GrabFocus();
618
619
0
}
620
621
SwInputChild::SwInputChild(vcl::Window* _pParent,
622
                                sal_uInt16 nId,
623
                                SfxBindings const * pBindings,
624
                                SfxChildWinInfo* ) :
625
0
                                SfxChildWindow( _pParent, nId )
626
0
{
627
0
    m_pDispatch = pBindings->GetDispatcher();
628
0
    SetWindow(VclPtr<SwInputWindow>::Create(_pParent, m_pDispatch));
629
0
    static_cast<SwInputWindow*>(GetWindow())->ShowWin();
630
0
    SetAlignment(SfxChildAlignment::LOWESTTOP);
631
0
}
632
633
SwInputChild::~SwInputChild()
634
0
{
635
0
    if(m_pDispatch)
636
0
        m_pDispatch->Lock(false);
637
0
}
638
639
SfxChildWinInfo SwInputChild::GetInfo() const
640
0
{
641
0
    SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
642
0
    return aInfo;
643
0
}
644
645
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */