Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/view/viewfun4.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 <config_features.h>
21
22
#include <memory>
23
#include <editeng/eeitem.hxx>
24
25
#include <editeng/editobj.hxx>
26
#include <editeng/editstat.hxx>
27
#include <editeng/editview.hxx>
28
#include <editeng/flditem.hxx>
29
#include <sot/storage.hxx>
30
#include <svx/hlnkitem.hxx>
31
#include <editeng/unolingu.hxx>
32
33
#include <sfx2/bindings.hxx>
34
#include <sfx2/dispatch.hxx>
35
#include <sfx2/docfile.hxx>
36
#include <sfx2/docfilt.hxx>
37
#include <sfx2/fcontnr.hxx>
38
#include <svtools/langtab.hxx>
39
#include <vcl/graphicfilter.hxx>
40
#include <svl/stritem.hxx>
41
#include <vcl/transfer.hxx>
42
#include <svl/urlbmk.hxx>
43
#include <svl/sharedstringpool.hxx>
44
#include <vcl/svapp.hxx>
45
#include <vcl/weld.hxx>
46
#include <avmedia/mediawindow.hxx>
47
#include <osl/diagnose.h>
48
49
#include <comphelper/propertyvalue.hxx>
50
#include <comphelper/storagehelper.hxx>
51
52
#include <viewfunc.hxx>
53
#include <docsh.hxx>
54
#include <document.hxx>
55
#include <globstr.hrc>
56
#include <global.hxx>
57
#include <scresid.hxx>
58
#include <undoblk.hxx>
59
#include <undocell.hxx>
60
#include <formulacell.hxx>
61
#include <scmod.hxx>
62
#include <spelleng.hxx>
63
#include <patattr.hxx>
64
#include <tabvwsh.hxx>
65
#include <impex.hxx>
66
#include <editutil.hxx>
67
#include <editable.hxx>
68
#include <dociter.hxx>
69
#include <reffind.hxx>
70
#include <compiler.hxx>
71
#include <tokenarray.hxx>
72
#include <refupdatecontext.hxx>
73
#include <gridwin.hxx>
74
#include <refundo.hxx>
75
76
using namespace com::sun::star;
77
78
void ScViewFunc::PasteRTF( SCCOL nStartCol, SCROW nStartRow,
79
                                const css::uno::Reference< css::datatransfer::XTransferable >& rxTransferable )
80
0
{
81
0
    TransferableDataHelper aDataHelper( rxTransferable );
82
0
    if ( aDataHelper.HasFormat( SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT ) )
83
0
    {
84
0
        HideAllCursors();
85
86
0
        ScDocShell* pDocSh = GetViewData().GetDocShell();
87
0
        ScDocument& rDoc = pDocSh->GetDocument();
88
0
        SCTAB nTab = GetViewData().CurrentTabForData();
89
0
        const bool bRecord (rDoc.IsUndoEnabled());
90
91
0
        const ScPatternAttr* pPattern = rDoc.GetPattern( nStartCol, nStartRow, nTab );
92
0
        std::optional<ScTabEditEngine> pEngine(std::in_place, *pPattern, rDoc.GetEditEnginePool(), rDoc );
93
0
        pEngine->EnableUndo( false );
94
95
0
        vcl::Window* pActWin = GetActiveWin();
96
0
        if (pActWin)
97
0
        {
98
0
            pEngine->SetPaperSize(Size(100000,100000));
99
0
            ScopedVclPtrInstance< vcl::Window > aWin( pActWin );
100
0
            EditView aEditView(*pEngine, aWin.get());
101
0
            aEditView.SetOutputArea(tools::Rectangle(0,0,100000,100000));
102
103
            // same method now for clipboard or drag&drop
104
            // mba: clipboard always must contain absolute URLs (could be from alien source)
105
0
            aEditView.InsertText( rxTransferable, OUString(), true );
106
0
        }
107
108
0
        sal_Int32 nParCnt = pEngine->GetParagraphCount();
109
0
        if (nParCnt)
110
0
        {
111
0
            SCROW nEndRow = nStartRow + static_cast<SCROW>(nParCnt) - 1;
112
0
            if (nEndRow > rDoc.MaxRow())
113
0
                nEndRow = rDoc.MaxRow();
114
115
0
            ScDocumentUniquePtr pUndoDoc;
116
0
            if (bRecord)
117
0
            {
118
0
                pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
119
0
                pUndoDoc->InitUndo( rDoc, nTab, nTab );
120
0
                rDoc.CopyToDocument( nStartCol,nStartRow,nTab, nStartCol,nEndRow,nTab, InsertDeleteFlags::ALL, false, *pUndoDoc );
121
0
            }
122
123
0
            SCROW nRow = nStartRow;
124
125
            // Temporarily turn off undo generation for this lot
126
0
            bool bUndoEnabled = rDoc.IsUndoEnabled();
127
0
            rDoc.EnableUndo( false );
128
0
            for( sal_Int32 n = 0; n < nParCnt; n++ )
129
0
            {
130
0
                std::unique_ptr<EditTextObject> pObject(pEngine->CreateTextObject(n));
131
0
                EnterData(nStartCol, nRow, nTab, *pObject, true);
132
0
                if( ++nRow > rDoc.MaxRow() )
133
0
                    break;
134
0
            }
135
0
            rDoc.EnableUndo(bUndoEnabled);
136
137
0
            if (bRecord)
138
0
            {
139
0
                ScDocumentUniquePtr pRedoDoc(new ScDocument( SCDOCMODE_UNDO ));
140
0
                pRedoDoc->InitUndo( rDoc, nTab, nTab );
141
0
                rDoc.CopyToDocument( nStartCol,nStartRow,nTab, nStartCol,nEndRow,nTab, InsertDeleteFlags::ALL|InsertDeleteFlags::NOCAPTIONS, false, *pRedoDoc );
142
143
0
                ScRange aMarkRange(nStartCol, nStartRow, nTab, nStartCol, nEndRow, nTab);
144
0
                ScMarkData aDestMark(rDoc.GetSheetLimits());
145
0
                aDestMark.SetMarkArea( aMarkRange );
146
0
                pDocSh->GetUndoManager()->AddUndoAction(
147
0
                    std::make_unique<ScUndoPaste>( *pDocSh, aMarkRange, aDestMark,
148
0
                                     std::move(pUndoDoc), std::move(pRedoDoc), InsertDeleteFlags::ALL, nullptr));
149
0
            }
150
0
        }
151
152
0
        pEngine.reset();
153
154
0
        ShowAllCursors();
155
0
    }
156
0
    else
157
0
    {
158
0
        HideAllCursors();
159
0
        ScDocShell* pDocSh = GetViewData().GetDocShell();
160
0
        ScImportExport aImpEx( pDocSh->GetDocument(),
161
0
            ScAddress( nStartCol, nStartRow, GetViewData().CurrentTabForData() ) );
162
163
0
        OUString aStr;
164
0
        std::unique_ptr<SvStream> xStream;
165
0
        if ( (xStream = aDataHelper.GetSotStorageStream( SotClipboardFormatId::RTF )) )
166
            // mba: clipboard always must contain absolute URLs (could be from alien source)
167
0
            aImpEx.ImportStream( *xStream, OUString(), SotClipboardFormatId::RTF );
168
0
        else if ( aDataHelper.GetString( SotClipboardFormatId::RTF, aStr ) )
169
0
            aImpEx.ImportString( aStr, SotClipboardFormatId::RTF );
170
0
        else if ( (xStream = aDataHelper.GetSotStorageStream( SotClipboardFormatId::RICHTEXT)) )
171
0
            aImpEx.ImportStream( *xStream, OUString(), SotClipboardFormatId::RICHTEXT );
172
0
        else if ( aDataHelper.GetString( SotClipboardFormatId::RICHTEXT, aStr ) )
173
0
            aImpEx.ImportString( aStr, SotClipboardFormatId::RICHTEXT );
174
175
0
        AdjustRowHeight( nStartRow, aImpEx.GetRange().aEnd.Row(), true );
176
0
        pDocSh->UpdateOle(GetViewData());
177
0
        ShowAllCursors();
178
0
    }
179
0
}
180
void ScViewFunc::DoRefConversion()
181
0
{
182
0
    ScDocument& rDoc = GetViewData().GetDocument();
183
0
    ScMarkData& rMark = GetViewData().GetMarkData();
184
0
    SCTAB nTabCount = rDoc.GetTableCount();
185
0
    bool bRecord = true;
186
0
    if (!rDoc.IsUndoEnabled())
187
0
        bRecord = false;
188
189
0
    ScRange aMarkRange;
190
0
    rMark.MarkToSimple();
191
0
    bool bMulti = rMark.IsMultiMarked();
192
0
    if (bMulti)
193
0
        aMarkRange = rMark.GetMultiMarkArea();
194
0
    else if (rMark.IsMarked())
195
0
        aMarkRange = rMark.GetMarkArea();
196
0
    else
197
0
    {
198
0
        aMarkRange = ScRange( GetViewData().GetCurX(),
199
0
            GetViewData().GetCurY(), GetViewData().CurrentTabForData() );
200
0
    }
201
0
    ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock(
202
0
                                rDoc, aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
203
0
                                aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), rMark);
204
0
    if (!aTester.IsEditable())
205
0
    {
206
0
        ErrorMessage(aTester.GetMessageId());
207
0
        return;
208
0
    }
209
210
0
    ScDocShell* pDocSh = GetViewData().GetDocShell();
211
0
    bool bOk = false;
212
213
0
    ScDocumentUniquePtr pUndoDoc;
214
0
    if (bRecord)
215
0
    {
216
0
        pUndoDoc.reset( new ScDocument( SCDOCMODE_UNDO ) );
217
0
        SCTAB nTab = aMarkRange.aStart.Tab();
218
0
        pUndoDoc->InitUndo( rDoc, nTab, nTab );
219
220
0
        if ( rMark.GetSelectCount() > 1 )
221
0
        {
222
0
            for (const auto& rTab : rMark)
223
0
                if ( rTab != nTab )
224
0
                    pUndoDoc->AddUndoTab( rTab, rTab );
225
0
        }
226
0
        ScRange aCopyRange = aMarkRange;
227
0
        aCopyRange.aStart.SetTab(0);
228
0
        aCopyRange.aEnd.SetTab(nTabCount-1);
229
0
        rDoc.CopyToDocument( aCopyRange, InsertDeleteFlags::ALL, bMulti, *pUndoDoc, &rMark );
230
0
    }
231
232
0
    ScRangeListRef xRanges;
233
0
    GetViewData().GetMultiArea( xRanges );
234
0
    size_t nCount = xRanges->size();
235
236
0
    for (const SCTAB& i : rMark)
237
0
    {
238
0
        for (size_t j = 0; j < nCount; ++j)
239
0
        {
240
0
            ScRange aRange = (*xRanges)[j];
241
0
            aRange.aStart.SetTab(i);
242
0
            aRange.aEnd.SetTab(i);
243
0
            ScCellIterator aIter( rDoc, aRange );
244
0
            for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
245
0
            {
246
0
                if (aIter.getType() != CELLTYPE_FORMULA)
247
0
                    continue;
248
249
0
                ScFormulaCell* pCell = aIter.getFormulaCell();
250
0
                ScMatrixMode eMatrixMode = pCell->GetMatrixFlag();
251
0
                if (eMatrixMode == ScMatrixMode::Reference)
252
0
                    continue;
253
254
0
                OUString aOld = pCell->GetFormula();
255
0
                sal_Int32 nLen = aOld.getLength();
256
0
                if (eMatrixMode == ScMatrixMode::Formula)
257
0
                {
258
0
                    assert(nLen >= 2 && aOld[0] == '{' && aOld[nLen-1] == '}');
259
0
                    nLen -= 2;
260
0
                    aOld = aOld.copy( 1, nLen);
261
0
                }
262
0
                ScRefFinder aFinder( aOld, aIter.GetPos(), rDoc, rDoc.GetAddressConvention() );
263
0
                aFinder.ToggleRel( 0, nLen );
264
0
                if (aFinder.GetFound())
265
0
                {
266
0
                    ScAddress aPos = pCell->aPos;
267
0
                    const OUString& aNew = aFinder.GetText();
268
0
                    ScCompiler aComp( rDoc, aPos, rDoc.GetGrammar());
269
0
                    std::unique_ptr<ScTokenArray> pArr(aComp.CompileString(aNew));
270
0
                    ScFormulaCell* pNewCell =
271
0
                        new ScFormulaCell(
272
0
                            rDoc, aPos, *pArr, formula::FormulaGrammar::GRAM_DEFAULT, eMatrixMode);
273
274
0
                    rDoc.SetFormulaCell(aPos, pNewCell);
275
0
                    bOk = true;
276
0
                }
277
0
            }
278
0
        }
279
0
    }
280
0
    if (bRecord)
281
0
    {
282
0
        ScDocumentUniquePtr pRedoDoc(new ScDocument( SCDOCMODE_UNDO ));
283
0
        SCTAB nTab = aMarkRange.aStart.Tab();
284
0
        pRedoDoc->InitUndo( rDoc, nTab, nTab );
285
286
0
        if ( rMark.GetSelectCount() > 1 )
287
0
        {
288
0
            for (const auto& rTab : rMark)
289
0
                if ( rTab != nTab )
290
0
                    pRedoDoc->AddUndoTab( rTab, rTab );
291
0
        }
292
0
        ScRange aCopyRange = aMarkRange;
293
0
        aCopyRange.aStart.SetTab(0);
294
0
        aCopyRange.aEnd.SetTab(nTabCount-1);
295
0
        rDoc.CopyToDocument( aCopyRange, InsertDeleteFlags::ALL, bMulti, *pRedoDoc, &rMark );
296
297
0
        pDocSh->GetUndoManager()->AddUndoAction(
298
0
            std::make_unique<ScUndoRefConversion>( *pDocSh,
299
0
                                    aMarkRange, rMark, std::move(pUndoDoc), std::move(pRedoDoc), bMulti) );
300
0
    }
301
302
0
    pDocSh->PostPaint( aMarkRange, PaintPartFlags::Grid );
303
0
    pDocSh->UpdateOle(GetViewData());
304
0
    pDocSh->SetDocumentModified();
305
0
    CellContentChanged();
306
307
0
    if (!bOk)
308
0
        ErrorMessage(STR_ERR_NOREF);
309
0
}
310
311
//  Thesaurus - Undo ok
312
void ScViewFunc::DoThesaurus()
313
0
{
314
0
    SCCOL nCol;
315
0
    SCROW nRow;
316
0
    SCTAB nTab;
317
0
    ScDocShell* pDocSh = GetViewData().GetDocShell();
318
0
    ScDocument& rDoc = pDocSh->GetDocument();
319
0
    ScMarkData& rMark = GetViewData().GetMarkData();
320
0
    ScSplitPos eWhich = GetViewData().GetActivePart();
321
0
    EESpellState eState;
322
0
    EditView* pEditView = nullptr;
323
0
    std::unique_ptr<ESelection> pEditSel;
324
0
    std::unique_ptr<ScEditEngineDefaulter> pThesaurusEngine;
325
0
    bool bIsEditMode = GetViewData().HasEditView(eWhich);
326
0
    bool bRecord = true;
327
0
    if (!rDoc.IsUndoEnabled())
328
0
        bRecord = false;
329
0
    if (bIsEditMode)                                            // edit mode active
330
0
    {
331
0
        GetViewData().GetEditView(eWhich, pEditView, nCol, nRow);
332
0
        pEditSel.reset(new ESelection(pEditView->GetSelection()));
333
0
        ScModule::get()->InputEnterHandler();
334
0
        GetViewData().GetBindings().Update();          // otherwise the Sfx becomes mixed-up...
335
0
    }
336
0
    else
337
0
    {
338
0
        nCol = GetViewData().GetCurX();
339
0
        nRow = GetViewData().GetCurY();
340
0
    }
341
0
    nTab = GetViewData().CurrentTabForData();
342
343
0
    ScAddress aPos(nCol, nRow, nTab);
344
0
    ScEditableTester aTester = ScEditableTester::CreateAndTestSelectedBlock(rDoc, nCol, nRow, nCol, nRow, rMark);
345
0
    if (!aTester.IsEditable())
346
0
    {
347
0
        ErrorMessage(aTester.GetMessageId());
348
0
        return;
349
0
    }
350
351
0
    ScCellValue aOldText;
352
0
    aOldText.assign(rDoc, aPos);
353
0
    if (aOldText.getType() != CELLTYPE_STRING && aOldText.getType() != CELLTYPE_EDIT)
354
0
    {
355
0
        ErrorMessage(STR_THESAURUS_NO_STRING);
356
0
        return;
357
0
    }
358
359
0
    uno::Reference<linguistic2::XSpellChecker1> xSpeller = LinguMgr::GetSpellChecker();
360
361
0
    pThesaurusEngine.reset(new ScEditEngineDefaulter(rDoc.GetEditEnginePool()));
362
0
    pThesaurusEngine->SetRefDevice(GetViewData().GetActiveWin()->GetOutDev());
363
0
    pThesaurusEngine->SetSpeller(xSpeller);
364
0
    MakeEditView(*pThesaurusEngine, nCol, nRow);
365
0
    const ScPatternAttr* pPattern = rDoc.GetPattern(nCol, nRow, nTab);
366
0
    if (pPattern)
367
0
    {
368
0
        SfxItemSet aEditDefaults(pThesaurusEngine->GetEmptyItemSet());
369
0
        pPattern->FillEditItemSet(&aEditDefaults);
370
0
        pThesaurusEngine->SetDefaults(std::move(aEditDefaults));
371
0
    }
372
373
0
    if (aOldText.getType() == CELLTYPE_EDIT)
374
0
        pThesaurusEngine->SetTextCurrentDefaults(*aOldText.getEditText());
375
0
    else
376
0
        pThesaurusEngine->SetTextCurrentDefaults(aOldText.getString(rDoc));
377
378
0
    pEditView = GetViewData().GetEditView(GetViewData().GetActivePart());
379
0
    if (pEditSel)
380
0
        pEditView->SetSelection(*pEditSel);
381
0
    else
382
0
        pEditView->SetSelection(ESelection());
383
384
0
    pThesaurusEngine->ClearModifyFlag();
385
386
    //  language is now in EditEngine attributes -> no longer passed to StartThesaurus
387
388
0
    eState = pEditView->StartThesaurus(GetViewData().GetDialogParent());
389
0
    OSL_ENSURE(eState != EESpellState::NoSpeller, "No SpellChecker");
390
391
0
    if (eState == EESpellState::ErrorFound)              // should happen later through Wrapper!
392
0
    {
393
0
        LanguageType eLnge = ScViewUtil::GetEffLanguage( rDoc, ScAddress( nCol, nRow, nTab ) );
394
0
        OUString aErr = SvtLanguageTable::GetLanguageString(eLnge) + ScResId( STR_SPELLING_NO_LANG );
395
396
0
        std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetViewData().GetDialogParent(),
397
0
                                                      VclMessageType::Info, VclButtonsType::Ok,
398
0
                                                      aErr));
399
0
        xInfoBox->run();
400
0
    }
401
0
    if (pThesaurusEngine->IsModified())
402
0
    {
403
0
        ScCellValue aNewText;
404
405
0
        if (aOldText.getType() == CELLTYPE_EDIT)
406
0
        {
407
            // The cell will own the text object instance.
408
0
            std::unique_ptr<EditTextObject> pText = pThesaurusEngine->CreateTextObject();
409
0
            auto tmp = pText.get();
410
0
            if (rDoc.SetEditText(ScAddress(nCol,nRow,nTab), std::move(pText)))
411
0
                aNewText.set(*tmp);
412
0
        }
413
0
        else
414
0
        {
415
0
            OUString aStr = pThesaurusEngine->GetText();
416
0
            aNewText.set(rDoc.GetSharedStringPool().intern(aStr));
417
0
            rDoc.SetString(nCol, nRow, nTab, aStr);
418
0
        }
419
420
0
        pDocSh->SetDocumentModified();
421
0
        if (bRecord)
422
0
        {
423
0
            GetViewData().GetDocShell()->GetUndoManager()->AddUndoAction(
424
0
                std::make_unique<ScUndoThesaurus>(
425
0
                    *GetViewData().GetDocShell(), nCol, nRow, nTab, aOldText, aNewText));
426
0
        }
427
0
    }
428
429
0
    KillEditView(true);
430
0
    pDocSh->PostPaintGridAll();
431
0
}
432
433
void ScViewFunc::DoHangulHanjaConversion()
434
0
{
435
0
    ScConversionParam aConvParam( SC_CONVERSION_HANGULHANJA, LANGUAGE_KOREAN, 0, true );
436
0
    DoSheetConversion( aConvParam );
437
0
}
438
439
void ScViewFunc::DoSheetConversion( const ScConversionParam& rConvParam )
440
0
{
441
0
    SCCOL nCol;
442
0
    SCROW nRow;
443
0
    SCTAB nTab;
444
0
    ScViewData& rViewData = GetViewData();
445
0
    ScDocShell* pDocSh = rViewData.GetDocShell();
446
0
    ScDocument& rDoc = pDocSh->GetDocument();
447
0
    ScMarkData& rMark = rViewData.GetMarkData();
448
0
    ScSplitPos eWhich = rViewData.GetActivePart();
449
0
    EditView* pEditView = nullptr;
450
0
    bool bIsEditMode = rViewData.HasEditView(eWhich);
451
0
    bool bRecord = true;
452
0
    if (!rDoc.IsUndoEnabled())
453
0
        bRecord = false;
454
0
    if (bIsEditMode)                                            // edit mode active
455
0
    {
456
0
        rViewData.GetEditView(eWhich, pEditView, nCol, nRow);
457
0
        ScModule::get()->InputEnterHandler();
458
0
    }
459
0
    else
460
0
    {
461
0
        nCol = rViewData.GetCurX();
462
0
        nRow = rViewData.GetCurY();
463
464
0
        AlignToCursor( nCol, nRow, SC_FOLLOW_JUMP);
465
0
    }
466
0
    nTab = rViewData.CurrentTabForData();
467
468
0
    rMark.MarkToMulti();
469
0
    bool bMarked = rMark.IsMultiMarked();
470
0
    if (bMarked)
471
0
    {
472
0
        ScEditableTester aTester = ScEditableTester::CreateAndTestSelection(rDoc, rMark);
473
0
        if (!aTester.IsEditable())
474
0
        {
475
0
            ErrorMessage(aTester.GetMessageId());
476
0
            return;
477
0
        }
478
0
    }
479
480
0
    ScDocumentUniquePtr pUndoDoc;
481
0
    ScDocumentUniquePtr pRedoDoc;
482
0
    if (bRecord)
483
0
    {
484
0
        pUndoDoc.reset( new ScDocument( SCDOCMODE_UNDO ) );
485
0
        pUndoDoc->InitUndo( rDoc, nTab, nTab );
486
0
        pRedoDoc.reset( new ScDocument( SCDOCMODE_UNDO ) );
487
0
        pRedoDoc->InitUndo( rDoc, nTab, nTab );
488
489
0
        if ( rMark.GetSelectCount() > 1 )
490
0
        {
491
0
            for (const auto& rTab : rMark)
492
0
                if ( rTab != nTab )
493
0
                {
494
0
                    pUndoDoc->AddUndoTab( rTab, rTab );
495
0
                    pRedoDoc->AddUndoTab( rTab, rTab );
496
0
                }
497
0
        }
498
0
    }
499
500
    // from here no return
501
502
0
    bool bOldEnabled = rDoc.IsIdleEnabled();
503
0
    rDoc.EnableIdle(false);   // stop online spelling
504
505
    // *** create and init the edit engine *** --------------------------------
506
507
0
    std::unique_ptr<ScConversionEngineBase> pEngine;
508
0
    switch( rConvParam.GetType() )
509
0
    {
510
0
        case SC_CONVERSION_SPELLCHECK:
511
0
            pEngine.reset(new ScSpellingEngine(
512
0
                rDoc.GetEditEnginePool(), rViewData, pUndoDoc.get(), pRedoDoc.get(), LinguMgr::GetSpellChecker() ));
513
0
        break;
514
0
        case SC_CONVERSION_HANGULHANJA:
515
0
        case SC_CONVERSION_CHINESE_TRANSL:
516
0
            pEngine.reset(new ScTextConversionEngine(
517
0
                rDoc.GetEditEnginePool(), rViewData, rConvParam, pUndoDoc.get(), pRedoDoc.get() ));
518
0
        break;
519
0
    }
520
521
0
    assert(pEngine && "all cases result in pEngine set");
522
523
0
    MakeEditView(*pEngine, nCol, nRow);
524
0
    pEngine->SetRefDevice( rViewData.GetActiveWin()->GetOutDev() );
525
                                        // simulate dummy cell:
526
0
    pEditView = rViewData.GetEditView( rViewData.GetActivePart() );
527
0
    rViewData.SetSpellingView( pEditView );
528
0
    tools::Rectangle aRect( Point( 0, 0 ), Point( 0, 0 ) );
529
0
    pEditView->SetOutputArea( aRect );
530
0
    pEngine->SetControlWord( EEControlBits::USECHARATTRIBS );
531
0
    pEngine->EnableUndo( false );
532
0
    pEngine->SetPaperSize( aRect.GetSize() );
533
0
    pEngine->SetTextCurrentDefaults( OUString() );
534
535
    // *** do the conversion *** ----------------------------------------------
536
537
0
    pEngine->ClearModifyFlag();
538
0
    pEngine->ConvertAll(GetViewData().GetDialogParent(), *pEditView);
539
540
    // *** undo/redo *** ------------------------------------------------------
541
542
0
    if( pEngine->IsAnyModified() )
543
0
    {
544
0
        if (bRecord)
545
0
        {
546
0
            SCCOL nNewCol = rViewData.GetCurX();
547
0
            SCROW nNewRow = rViewData.GetCurY();
548
0
            rViewData.GetDocShell()->GetUndoManager()->AddUndoAction(
549
0
                std::make_unique<ScUndoConversion>(
550
0
                        *pDocSh, rMark,
551
0
                        nCol, nRow, nTab, std::move(pUndoDoc),
552
0
                        nNewCol, nNewRow, nTab, std::move(pRedoDoc), rConvParam ) );
553
0
        }
554
555
0
        sc::SetFormulaDirtyContext aCxt;
556
0
        rDoc.SetAllFormulasDirty(aCxt);
557
558
0
        pDocSh->SetDocumentModified();
559
0
    }
560
0
    else
561
0
    {
562
0
        pUndoDoc.reset();
563
0
        pRedoDoc.reset();
564
0
    }
565
566
    // *** final cleanup *** --------------------------------------------------
567
568
0
    rViewData.SetSpellingView( nullptr );
569
0
    KillEditView(true);
570
0
    pEngine.reset();
571
0
    pDocSh->PostPaintGridAll();
572
0
    rViewData.GetViewShell()->UpdateInputHandler();
573
0
    rDoc.EnableIdle(bOldEnabled);
574
0
}
575
576
// past from SotClipboardFormatId::FILE items
577
// is not called directly from Drop, but asynchronously -> dialogs are allowed
578
579
bool ScViewFunc::PasteFile( const Point& rPos, const OUString& rFile, bool bLink )
580
0
{
581
0
    INetURLObject aURL;
582
0
    aURL.SetSmartURL( rFile );
583
0
    OUString aStrURL = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
584
585
    // is it a media URL?
586
0
#if HAVE_FEATURE_AVMEDIA
587
0
    if( ::avmedia::MediaWindow::isMediaURL( aStrURL, u""_ustr/*TODO?*/ ) )
588
0
    {
589
0
        const SfxStringItem aMediaURLItem( SID_INSERT_AVMEDIA, aStrURL );
590
0
        const SfxPoolItemHolder aResult(GetViewData().GetDispatcher().ExecuteList(
591
0
            SID_INSERT_AVMEDIA, SfxCallMode::SYNCHRON,
592
0
            { &aMediaURLItem }));
593
0
        return aResult.is();
594
0
    }
595
0
#endif
596
597
0
    if (!bLink)     // for bLink only graphics or URL
598
0
    {
599
        // 1. can I open the file?
600
0
        std::shared_ptr<const SfxFilter> pFlt;
601
602
        // search only for its own filters, without selection box (as in ScDocumentLoader)
603
0
        SfxFilterMatcher aMatcher( ScDocShell::Factory().GetFilterContainer()->GetName() );
604
0
        SfxMedium aSfxMedium( aStrURL, (StreamMode::READ | StreamMode::SHARE_DENYNONE) );
605
        // #i73992# GuessFilter no longer calls UseInteractionHandler.
606
        // This is UI, so it can be called here.
607
0
        aSfxMedium.UseInteractionHandler(true);
608
0
        ErrCode nErr = aMatcher.GuessFilter( aSfxMedium, pFlt );
609
610
0
        if ( pFlt && !nErr )
611
0
        {
612
            // code stolen from the SFX!
613
0
            SfxDispatcher &rDispatcher = GetViewData().GetDispatcher();
614
0
            SfxStringItem aFileNameItem( SID_FILE_NAME, aStrURL );
615
0
            SfxStringItem aFilterItem( SID_FILTER_NAME, pFlt->GetName() );
616
            // #i69524# add target, as in SfxApplication when the Open dialog is used
617
0
            SfxStringItem aTargetItem( SID_TARGETNAME, u"_default"_ustr );
618
619
            // Open Asynchronously, because it can also happen from D&D
620
            // and that is not so good for the MAC...
621
0
            const SfxPoolItemHolder aResult(rDispatcher.ExecuteList(SID_OPENDOC,
622
0
                SfxCallMode::ASYNCHRON,
623
0
                { &aFileNameItem, &aFilterItem, &aTargetItem}));
624
0
            return aResult.is();
625
0
        }
626
0
    }
627
628
    // 2. can the file be inserted using the graphics filter?
629
    // (as a link, since the Gallery provides it in this way)
630
631
0
    Graphic aGraphic;
632
0
    GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
633
634
0
    if (!rGraphicFilter.ImportGraphic(aGraphic, aURL,
635
0
            GRFILTER_FORMAT_DONTKNOW ))
636
0
    {
637
0
        if ( bLink )
638
0
        {
639
0
            return PasteGraphic( rPos, aGraphic, aStrURL );
640
0
        }
641
0
        else
642
0
        {
643
            // #i76709# if bLink isn't set, pass empty URL/filter, so a non-linked image is inserted
644
0
            return PasteGraphic( rPos, aGraphic, OUString() );
645
0
        }
646
0
    }
647
648
0
    if (bLink)                      // for bLink everything, which is not graphics, as URL
649
0
    {
650
0
        tools::Rectangle aRect( rPos, Size(0,0) );
651
0
        ScRange aRange = GetViewData().GetDocument().
652
0
                            GetRange( GetViewData().CurrentTabForData(), aRect );
653
0
        SCCOL nPosX = aRange.aStart.Col();
654
0
        SCROW nPosY = aRange.aStart.Row();
655
656
0
        InsertBookmark( aStrURL, aStrURL, nPosX, nPosY );
657
0
        return true;
658
0
    }
659
0
    else
660
0
    {
661
        // 3. can the file be inserted as OLE?
662
        // also non-storages, for instance sounds (#38282#)
663
0
        uno::Reference < embed::XStorage > xStorage = comphelper::OStorageHelper::GetTemporaryStorage();
664
665
        //TODO/LATER: what about "bLink"?
666
667
0
        uno::Sequence < beans::PropertyValue > aMedium{ comphelper::makePropertyValue(u"URL"_ustr,
668
0
                                                                                      aStrURL) };
669
670
0
        comphelper::EmbeddedObjectContainer aCnt( xStorage );
671
0
        OUString aName;
672
0
        uno::Reference < embed::XEmbeddedObject > xObj = aCnt.InsertEmbeddedObject( aMedium, aName );
673
0
        if( xObj.is() )
674
0
            return PasteObject( rPos, xObj, nullptr );
675
676
        // If an OLE object can't be created, insert a URL button
677
678
0
        GetViewData().GetViewShell()->InsertURLButton( aStrURL, aStrURL, OUString(), &rPos );
679
0
        return true;
680
0
    }
681
0
}
682
683
bool ScViewFunc::PasteBookmark( SotClipboardFormatId nFormatId,
684
                                const css::uno::Reference< css::datatransfer::XTransferable >& rxTransferable,
685
                                SCCOL nPosX, SCROW nPosY )
686
0
{
687
0
    INetBookmark aBookmark;
688
0
    TransferableDataHelper aDataHelper( rxTransferable );
689
0
    if ( !aDataHelper.GetINetBookmark( nFormatId, aBookmark ) )
690
0
        return false;
691
692
0
    InsertBookmark( aBookmark.GetDescription(), aBookmark.GetURL(), nPosX, nPosY );
693
0
    return true;
694
0
}
695
696
void ScViewFunc::InsertBookmark( const OUString& rDescription, const OUString& rURL,
697
                                    SCCOL nPosX, SCROW nPosY, const OUString* pTarget,
698
                                    bool bTryReplace )
699
0
{
700
0
    ScViewData& rViewData = GetViewData();
701
0
    if ( rViewData.HasEditView( rViewData.GetActivePart() ) &&
702
0
            nPosX >= rViewData.GetEditStartCol() && nPosX <= rViewData.GetEditEndCol() &&
703
0
            nPosY >= rViewData.GetEditStartRow() && nPosY <= rViewData.GetEditEndRow() )
704
0
    {
705
        // insert into the cell which just got edited
706
707
0
        OUString aTargetFrame;
708
0
        if (pTarget)
709
0
            aTargetFrame = *pTarget;
710
0
        rViewData.GetViewShell()->InsertURLField( rDescription, rURL, aTargetFrame );
711
0
        return;
712
0
    }
713
714
    // insert into not edited cell
715
716
0
    ScDocument& rDoc = GetViewData().GetDocument();
717
0
    SCTAB nTab = GetViewData().CurrentTabForData();
718
0
    ScAddress aCellPos( nPosX, nPosY, nTab );
719
0
    EditEngine aEngine( rDoc.GetEditEnginePool() );
720
721
0
    const EditTextObject* pOld = rDoc.GetEditText(aCellPos);
722
0
    if (pOld)
723
0
        aEngine.SetText(*pOld);
724
0
    else
725
0
    {
726
0
        OUString aOld = rDoc.GetInputString(nPosX, nPosY, nTab);
727
0
        if (!aOld.isEmpty())
728
0
            aEngine.SetText(aOld);
729
0
    }
730
731
0
    ESelection aInsSel(ESelection::AtEnd());
732
733
0
    if ( bTryReplace && HasBookmarkAtCursor( nullptr ) )
734
0
    {
735
        //  if called from hyperlink slot and cell contains only a URL,
736
        //  replace old URL with new one
737
738
0
        aInsSel = ESelection( 0, 0, 0, 1 );     // replace first character (field)
739
0
    }
740
741
0
    SvxURLField aField( rURL, rDescription, SvxURLFormat::AppDefault );
742
0
    if (pTarget)
743
0
        aField.SetTargetFrame(*pTarget);
744
0
    aEngine.QuickInsertField( SvxFieldItem( aField, EE_FEATURE_FIELD ), aInsSel );
745
746
0
    std::unique_ptr<EditTextObject> pData(aEngine.CreateTextObject());
747
0
    EnterData(nPosX, nPosY, nTab, *pData);
748
0
}
749
750
bool ScViewFunc::HasBookmarkAtCursor( SvxHyperlinkItem* pContent )
751
0
{
752
0
    ScAddress aPos( GetViewData().GetCurX(), GetViewData().GetCurY(), GetViewData().CurrentTabForData() );
753
0
    ScDocument& rDoc = GetViewData().GetDocShell()->GetDocument();
754
755
0
    const EditTextObject* pData = rDoc.GetEditText(aPos);
756
0
    if (!pData)
757
0
        return false;
758
759
0
    if (!pData->IsFieldObject())
760
        // not a field object.
761
0
        return false;
762
763
0
    const SvxFieldItem* pFieldItem = pData->GetField();
764
0
    if (!pFieldItem)
765
        // doesn't have a field item.
766
0
        return false;
767
768
0
    const SvxFieldData* pField = pFieldItem->GetField();
769
0
    if (!pField)
770
        // doesn't have a field item data.
771
0
        return false;
772
773
0
    if (pField->GetClassId() != css::text::textfield::Type::URL)
774
        // not a URL field.
775
0
        return false;
776
777
0
    if (pContent)
778
0
    {
779
0
        const SvxURLField* pURLField = static_cast<const SvxURLField*>(pField);
780
0
        pContent->SetName( pURLField->GetRepresentation() );
781
0
        pContent->SetURL( pURLField->GetURL() );
782
0
        pContent->SetTargetFrame( pURLField->GetTargetFrame() );
783
0
    }
784
0
    return true;
785
0
}
786
787
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */