Drop ScGlobal::GetEmptyOUString() and EMPTY_OUSTRING
[LibreOffice.git] / sc / source / ui / view / viewfun4.cxx
blobd3679b13c0d2c39bf69d720d19348c137ecfc116
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_features.h>
22 #include <memory>
23 #include <editeng/eeitem.hxx>
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>
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>
49 #include <comphelper/propertyvalue.hxx>
50 #include <comphelper/storagehelper.hxx>
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>
76 using namespace com::sun::star;
78 void ScViewFunc::PasteRTF( SCCOL nStartCol, SCROW nStartRow,
79 const css::uno::Reference< css::datatransfer::XTransferable >& rxTransferable )
81 TransferableDataHelper aDataHelper( rxTransferable );
82 if ( aDataHelper.HasFormat( SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT ) )
84 HideAllCursors();
86 ScDocShell* pDocSh = GetViewData().GetDocShell();
87 ScDocument& rDoc = pDocSh->GetDocument();
88 SCTAB nTab = GetViewData().GetTabNo();
89 const bool bRecord (rDoc.IsUndoEnabled());
91 const ScPatternAttr* pPattern = rDoc.GetPattern( nStartCol, nStartRow, nTab );
92 std::optional<ScTabEditEngine> pEngine(std::in_place, *pPattern, rDoc.GetEnginePool(), &rDoc );
93 pEngine->EnableUndo( false );
95 vcl::Window* pActWin = GetActiveWin();
96 if (pActWin)
98 pEngine->SetPaperSize(Size(100000,100000));
99 ScopedVclPtrInstance< vcl::Window > aWin( pActWin );
100 EditView aEditView( &*pEngine, aWin.get() );
101 aEditView.SetOutputArea(tools::Rectangle(0,0,100000,100000));
103 // same method now for clipboard or drag&drop
104 // mba: clipboard always must contain absolute URLs (could be from alien source)
105 aEditView.InsertText( rxTransferable, OUString(), true );
108 sal_Int32 nParCnt = pEngine->GetParagraphCount();
109 if (nParCnt)
111 SCROW nEndRow = nStartRow + static_cast<SCROW>(nParCnt) - 1;
112 if (nEndRow > rDoc.MaxRow())
113 nEndRow = rDoc.MaxRow();
115 ScDocumentUniquePtr pUndoDoc;
116 if (bRecord)
118 pUndoDoc.reset(new ScDocument( SCDOCMODE_UNDO ));
119 pUndoDoc->InitUndo( rDoc, nTab, nTab );
120 rDoc.CopyToDocument( nStartCol,nStartRow,nTab, nStartCol,nEndRow,nTab, InsertDeleteFlags::ALL, false, *pUndoDoc );
123 SCROW nRow = nStartRow;
125 // Temporarily turn off undo generation for this lot
126 bool bUndoEnabled = rDoc.IsUndoEnabled();
127 rDoc.EnableUndo( false );
128 for( sal_Int32 n = 0; n < nParCnt; n++ )
130 std::unique_ptr<EditTextObject> pObject(pEngine->CreateTextObject(n));
131 EnterData(nStartCol, nRow, nTab, *pObject, true);
132 if( ++nRow > rDoc.MaxRow() )
133 break;
135 rDoc.EnableUndo(bUndoEnabled);
137 if (bRecord)
139 ScDocumentUniquePtr pRedoDoc(new ScDocument( SCDOCMODE_UNDO ));
140 pRedoDoc->InitUndo( rDoc, nTab, nTab );
141 rDoc.CopyToDocument( nStartCol,nStartRow,nTab, nStartCol,nEndRow,nTab, InsertDeleteFlags::ALL|InsertDeleteFlags::NOCAPTIONS, false, *pRedoDoc );
143 ScRange aMarkRange(nStartCol, nStartRow, nTab, nStartCol, nEndRow, nTab);
144 ScMarkData aDestMark(rDoc.GetSheetLimits());
145 aDestMark.SetMarkArea( aMarkRange );
146 pDocSh->GetUndoManager()->AddUndoAction(
147 std::make_unique<ScUndoPaste>( pDocSh, aMarkRange, aDestMark,
148 std::move(pUndoDoc), std::move(pRedoDoc), InsertDeleteFlags::ALL, nullptr));
152 pEngine.reset();
154 ShowAllCursors();
156 else
158 HideAllCursors();
159 ScDocShell* pDocSh = GetViewData().GetDocShell();
160 ScImportExport aImpEx( pDocSh->GetDocument(),
161 ScAddress( nStartCol, nStartRow, GetViewData().GetTabNo() ) );
163 OUString aStr;
164 tools::SvRef<SotTempStream> xStream;
165 if ( aDataHelper.GetSotStorageStream( SotClipboardFormatId::RTF, xStream ) && xStream.is() )
166 // mba: clipboard always must contain absolute URLs (could be from alien source)
167 aImpEx.ImportStream( *xStream, OUString(), SotClipboardFormatId::RTF );
168 else if ( aDataHelper.GetString( SotClipboardFormatId::RTF, aStr ) )
169 aImpEx.ImportString( aStr, SotClipboardFormatId::RTF );
170 else if ( aDataHelper.GetSotStorageStream( SotClipboardFormatId::RICHTEXT, xStream ) && xStream.is() )
171 aImpEx.ImportStream( *xStream, OUString(), SotClipboardFormatId::RICHTEXT );
172 else if ( aDataHelper.GetString( SotClipboardFormatId::RICHTEXT, aStr ) )
173 aImpEx.ImportString( aStr, SotClipboardFormatId::RICHTEXT );
175 AdjustRowHeight( nStartRow, aImpEx.GetRange().aEnd.Row(), true );
176 pDocSh->UpdateOle(GetViewData());
177 ShowAllCursors();
180 void ScViewFunc::DoRefConversion()
182 ScDocument& rDoc = GetViewData().GetDocument();
183 ScMarkData& rMark = GetViewData().GetMarkData();
184 SCTAB nTabCount = rDoc.GetTableCount();
185 bool bRecord = true;
186 if (!rDoc.IsUndoEnabled())
187 bRecord = false;
189 ScRange aMarkRange;
190 rMark.MarkToSimple();
191 bool bMulti = rMark.IsMultiMarked();
192 if (bMulti)
193 rMark.GetMultiMarkArea( aMarkRange );
194 else if (rMark.IsMarked())
195 rMark.GetMarkArea( aMarkRange );
196 else
198 aMarkRange = ScRange( GetViewData().GetCurX(),
199 GetViewData().GetCurY(), GetViewData().GetTabNo() );
201 ScEditableTester aTester( rDoc, aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
202 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),rMark );
203 if (!aTester.IsEditable())
205 ErrorMessage(aTester.GetMessageId());
206 return;
209 ScDocShell* pDocSh = GetViewData().GetDocShell();
210 bool bOk = false;
212 ScDocumentUniquePtr pUndoDoc;
213 if (bRecord)
215 pUndoDoc.reset( new ScDocument( SCDOCMODE_UNDO ) );
216 SCTAB nTab = aMarkRange.aStart.Tab();
217 pUndoDoc->InitUndo( rDoc, nTab, nTab );
219 if ( rMark.GetSelectCount() > 1 )
221 for (const auto& rTab : rMark)
222 if ( rTab != nTab )
223 pUndoDoc->AddUndoTab( rTab, rTab );
225 ScRange aCopyRange = aMarkRange;
226 aCopyRange.aStart.SetTab(0);
227 aCopyRange.aEnd.SetTab(nTabCount-1);
228 rDoc.CopyToDocument( aCopyRange, InsertDeleteFlags::ALL, bMulti, *pUndoDoc, &rMark );
231 ScRangeListRef xRanges;
232 GetViewData().GetMultiArea( xRanges );
233 size_t nCount = xRanges->size();
235 for (const SCTAB& i : rMark)
237 for (size_t j = 0; j < nCount; ++j)
239 ScRange aRange = (*xRanges)[j];
240 aRange.aStart.SetTab(i);
241 aRange.aEnd.SetTab(i);
242 ScCellIterator aIter( rDoc, aRange );
243 for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
245 if (aIter.getType() != CELLTYPE_FORMULA)
246 continue;
248 ScFormulaCell* pCell = aIter.getFormulaCell();
249 ScMatrixMode eMatrixMode = pCell->GetMatrixFlag();
250 if (eMatrixMode == ScMatrixMode::Reference)
251 continue;
253 OUString aOld = pCell->GetFormula();
254 sal_Int32 nLen = aOld.getLength();
255 if (eMatrixMode == ScMatrixMode::Formula)
257 assert(nLen >= 2 && aOld[0] == '{' && aOld[nLen-1] == '}');
258 nLen -= 2;
259 aOld = aOld.copy( 1, nLen);
261 ScRefFinder aFinder( aOld, aIter.GetPos(), rDoc, rDoc.GetAddressConvention() );
262 aFinder.ToggleRel( 0, nLen );
263 if (aFinder.GetFound())
265 ScAddress aPos = pCell->aPos;
266 const OUString& aNew = aFinder.GetText();
267 ScCompiler aComp( rDoc, aPos, rDoc.GetGrammar());
268 std::unique_ptr<ScTokenArray> pArr(aComp.CompileString(aNew));
269 ScFormulaCell* pNewCell =
270 new ScFormulaCell(
271 rDoc, aPos, *pArr, formula::FormulaGrammar::GRAM_DEFAULT, eMatrixMode);
273 rDoc.SetFormulaCell(aPos, pNewCell);
274 bOk = true;
279 if (bRecord)
281 ScDocumentUniquePtr pRedoDoc(new ScDocument( SCDOCMODE_UNDO ));
282 SCTAB nTab = aMarkRange.aStart.Tab();
283 pRedoDoc->InitUndo( rDoc, nTab, nTab );
285 if ( rMark.GetSelectCount() > 1 )
287 for (const auto& rTab : rMark)
288 if ( rTab != nTab )
289 pRedoDoc->AddUndoTab( rTab, rTab );
291 ScRange aCopyRange = aMarkRange;
292 aCopyRange.aStart.SetTab(0);
293 aCopyRange.aEnd.SetTab(nTabCount-1);
294 rDoc.CopyToDocument( aCopyRange, InsertDeleteFlags::ALL, bMulti, *pRedoDoc, &rMark );
296 pDocSh->GetUndoManager()->AddUndoAction(
297 std::make_unique<ScUndoRefConversion>( pDocSh,
298 aMarkRange, rMark, std::move(pUndoDoc), std::move(pRedoDoc), bMulti) );
301 pDocSh->PostPaint( aMarkRange, PaintPartFlags::Grid );
302 pDocSh->UpdateOle(GetViewData());
303 pDocSh->SetDocumentModified();
304 CellContentChanged();
306 if (!bOk)
307 ErrorMessage(STR_ERR_NOREF);
310 // Thesaurus - Undo ok
311 void ScViewFunc::DoThesaurus()
313 SCCOL nCol;
314 SCROW nRow;
315 SCTAB nTab;
316 ScDocShell* pDocSh = GetViewData().GetDocShell();
317 ScDocument& rDoc = pDocSh->GetDocument();
318 ScMarkData& rMark = GetViewData().GetMarkData();
319 ScSplitPos eWhich = GetViewData().GetActivePart();
320 EESpellState eState;
321 EditView* pEditView = nullptr;
322 std::unique_ptr<ESelection> pEditSel;
323 std::unique_ptr<ScEditEngineDefaulter> pThesaurusEngine;
324 bool bIsEditMode = GetViewData().HasEditView(eWhich);
325 bool bRecord = true;
326 if (!rDoc.IsUndoEnabled())
327 bRecord = false;
328 if (bIsEditMode) // edit mode active
330 GetViewData().GetEditView(eWhich, pEditView, nCol, nRow);
331 pEditSel.reset(new ESelection(pEditView->GetSelection()));
332 SC_MOD()->InputEnterHandler();
333 GetViewData().GetBindings().Update(); // otherwise the Sfx becomes mixed-up...
335 else
337 nCol = GetViewData().GetCurX();
338 nRow = GetViewData().GetCurY();
340 nTab = GetViewData().GetTabNo();
342 ScAddress aPos(nCol, nRow, nTab);
343 ScEditableTester aTester( rDoc, nCol, nRow, nCol, nRow, rMark );
344 if (!aTester.IsEditable())
346 ErrorMessage(aTester.GetMessageId());
347 return;
350 ScCellValue aOldText;
351 aOldText.assign(rDoc, aPos);
352 if (aOldText.meType != CELLTYPE_STRING && aOldText.meType != CELLTYPE_EDIT)
354 ErrorMessage(STR_THESAURUS_NO_STRING);
355 return;
358 uno::Reference<linguistic2::XSpellChecker1> xSpeller = LinguMgr::GetSpellChecker();
360 pThesaurusEngine.reset(new ScEditEngineDefaulter(rDoc.GetEnginePool()));
361 pThesaurusEngine->SetEditTextObjectPool( rDoc.GetEditPool() );
362 pThesaurusEngine->SetRefDevice(GetViewData().GetActiveWin()->GetOutDev());
363 pThesaurusEngine->SetSpeller(xSpeller);
364 MakeEditView(pThesaurusEngine.get(), nCol, nRow );
365 SfxItemSet aEditDefaults(pThesaurusEngine->GetEmptyItemSet());
366 const ScPatternAttr* pPattern = rDoc.GetPattern(nCol, nRow, nTab);
367 if (pPattern)
369 pPattern->FillEditItemSet( &aEditDefaults );
370 pThesaurusEngine->SetDefaults( aEditDefaults );
373 if (aOldText.meType == CELLTYPE_EDIT)
374 pThesaurusEngine->SetTextCurrentDefaults(*aOldText.mpEditText);
375 else
376 pThesaurusEngine->SetTextCurrentDefaults(aOldText.getString(rDoc));
378 pEditView = GetViewData().GetEditView(GetViewData().GetActivePart());
379 if (pEditSel)
380 pEditView->SetSelection(*pEditSel);
381 else
382 pEditView->SetSelection(ESelection(0,0,0,0));
384 pThesaurusEngine->ClearModifyFlag();
386 // language is now in EditEngine attributes -> no longer passed to StartThesaurus
388 eState = pEditView->StartThesaurus(GetViewData().GetDialogParent());
389 OSL_ENSURE(eState != EESpellState::NoSpeller, "No SpellChecker");
391 if (eState == EESpellState::ErrorFound) // should happen later through Wrapper!
393 LanguageType eLnge = ScViewUtil::GetEffLanguage( rDoc, ScAddress( nCol, nRow, nTab ) );
394 OUString aErr = SvtLanguageTable::GetLanguageString(eLnge) + ScResId( STR_SPELLING_NO_LANG );
396 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetViewData().GetDialogParent(),
397 VclMessageType::Info, VclButtonsType::Ok,
398 aErr));
399 xInfoBox->run();
401 if (pThesaurusEngine->IsModified())
403 ScCellValue aNewText;
405 if (aOldText.meType == CELLTYPE_EDIT)
407 // The cell will own the text object instance.
408 std::unique_ptr<EditTextObject> pText = pThesaurusEngine->CreateTextObject();
409 auto tmp = pText.get();
410 if (rDoc.SetEditText(ScAddress(nCol,nRow,nTab), std::move(pText)))
411 aNewText.set(*tmp);
413 else
415 OUString aStr = pThesaurusEngine->GetText();
416 aNewText.set(rDoc.GetSharedStringPool().intern(aStr));
417 rDoc.SetString(nCol, nRow, nTab, aStr);
420 pDocSh->SetDocumentModified();
421 if (bRecord)
423 GetViewData().GetDocShell()->GetUndoManager()->AddUndoAction(
424 std::make_unique<ScUndoThesaurus>(
425 GetViewData().GetDocShell(), nCol, nRow, nTab, aOldText, aNewText));
429 KillEditView(true);
430 pDocSh->PostPaintGridAll();
433 void ScViewFunc::DoHangulHanjaConversion()
435 ScConversionParam aConvParam( SC_CONVERSION_HANGULHANJA, LANGUAGE_KOREAN, 0, true );
436 DoSheetConversion( aConvParam );
439 void ScViewFunc::DoSheetConversion( const ScConversionParam& rConvParam )
441 SCCOL nCol;
442 SCROW nRow;
443 SCTAB nTab;
444 ScViewData& rViewData = GetViewData();
445 ScDocShell* pDocSh = rViewData.GetDocShell();
446 ScDocument& rDoc = pDocSh->GetDocument();
447 ScMarkData& rMark = rViewData.GetMarkData();
448 ScSplitPos eWhich = rViewData.GetActivePart();
449 EditView* pEditView = nullptr;
450 bool bIsEditMode = rViewData.HasEditView(eWhich);
451 bool bRecord = true;
452 if (!rDoc.IsUndoEnabled())
453 bRecord = false;
454 if (bIsEditMode) // edit mode active
456 rViewData.GetEditView(eWhich, pEditView, nCol, nRow);
457 SC_MOD()->InputEnterHandler();
459 else
461 nCol = rViewData.GetCurX();
462 nRow = rViewData.GetCurY();
464 AlignToCursor( nCol, nRow, SC_FOLLOW_JUMP);
466 nTab = rViewData.GetTabNo();
468 rMark.MarkToMulti();
469 bool bMarked = rMark.IsMultiMarked();
470 if (bMarked)
472 ScEditableTester aTester( rDoc, rMark );
473 if (!aTester.IsEditable())
475 ErrorMessage(aTester.GetMessageId());
476 return;
480 ScDocumentUniquePtr pUndoDoc;
481 ScDocumentUniquePtr pRedoDoc;
482 if (bRecord)
484 pUndoDoc.reset( new ScDocument( SCDOCMODE_UNDO ) );
485 pUndoDoc->InitUndo( rDoc, nTab, nTab );
486 pRedoDoc.reset( new ScDocument( SCDOCMODE_UNDO ) );
487 pRedoDoc->InitUndo( rDoc, nTab, nTab );
489 if ( rMark.GetSelectCount() > 1 )
491 for (const auto& rTab : rMark)
492 if ( rTab != nTab )
494 pUndoDoc->AddUndoTab( rTab, rTab );
495 pRedoDoc->AddUndoTab( rTab, rTab );
500 // from here no return
502 bool bOldEnabled = rDoc.IsIdleEnabled();
503 rDoc.EnableIdle(false); // stop online spelling
505 // *** create and init the edit engine *** --------------------------------
507 std::unique_ptr<ScConversionEngineBase> pEngine;
508 switch( rConvParam.GetType() )
510 case SC_CONVERSION_SPELLCHECK:
511 pEngine.reset(new ScSpellingEngine(
512 rDoc.GetEnginePool(), rViewData, pUndoDoc.get(), pRedoDoc.get(), LinguMgr::GetSpellChecker() ));
513 break;
514 case SC_CONVERSION_HANGULHANJA:
515 case SC_CONVERSION_CHINESE_TRANSL:
516 pEngine.reset(new ScTextConversionEngine(
517 rDoc.GetEnginePool(), rViewData, rConvParam, pUndoDoc.get(), pRedoDoc.get() ));
518 break;
519 default:
520 OSL_FAIL( "ScViewFunc::DoSheetConversion - unknown conversion type" );
523 MakeEditView( pEngine.get(), nCol, nRow );
524 pEngine->SetRefDevice( rViewData.GetActiveWin()->GetOutDev() );
525 // simulate dummy cell:
526 pEditView = rViewData.GetEditView( rViewData.GetActivePart() );
527 rViewData.SetSpellingView( pEditView );
528 tools::Rectangle aRect( Point( 0, 0 ), Point( 0, 0 ) );
529 pEditView->SetOutputArea( aRect );
530 pEngine->SetControlWord( EEControlBits::USECHARATTRIBS );
531 pEngine->EnableUndo( false );
532 pEngine->SetPaperSize( aRect.GetSize() );
533 pEngine->SetTextCurrentDefaults( OUString() );
535 // *** do the conversion *** ----------------------------------------------
537 pEngine->ClearModifyFlag();
538 pEngine->ConvertAll(GetViewData().GetDialogParent(), *pEditView);
540 // *** undo/redo *** ------------------------------------------------------
542 if( pEngine->IsAnyModified() )
544 if (bRecord)
546 SCCOL nNewCol = rViewData.GetCurX();
547 SCROW nNewRow = rViewData.GetCurY();
548 rViewData.GetDocShell()->GetUndoManager()->AddUndoAction(
549 std::make_unique<ScUndoConversion>(
550 pDocSh, rMark,
551 nCol, nRow, nTab, std::move(pUndoDoc),
552 nNewCol, nNewRow, nTab, std::move(pRedoDoc), rConvParam ) );
555 sc::SetFormulaDirtyContext aCxt;
556 rDoc.SetAllFormulasDirty(aCxt);
558 pDocSh->SetDocumentModified();
560 else
562 pUndoDoc.reset();
563 pRedoDoc.reset();
566 // *** final cleanup *** --------------------------------------------------
568 rViewData.SetSpellingView( nullptr );
569 KillEditView(true);
570 pEngine.reset();
571 pDocSh->PostPaintGridAll();
572 rViewData.GetViewShell()->UpdateInputHandler();
573 rDoc.EnableIdle(bOldEnabled);
576 // past from SotClipboardFormatId::FILE items
577 // is not called directly from Drop, but asynchronously -> dialogs are allowed
579 bool ScViewFunc::PasteFile( const Point& rPos, const OUString& rFile, bool bLink )
581 INetURLObject aURL;
582 aURL.SetSmartURL( rFile );
583 OUString aStrURL = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
585 // is it a media URL?
586 #if HAVE_FEATURE_AVMEDIA
587 if( ::avmedia::MediaWindow::isMediaURL( aStrURL, ""/*TODO?*/ ) )
589 const SfxStringItem aMediaURLItem( SID_INSERT_AVMEDIA, aStrURL );
590 return ( nullptr != GetViewData().GetDispatcher().ExecuteList(
591 SID_INSERT_AVMEDIA, SfxCallMode::SYNCHRON,
592 { &aMediaURLItem }) );
594 #endif
596 if (!bLink) // for bLink only graphics or URL
598 // 1. can I open the file?
599 std::shared_ptr<const SfxFilter> pFlt;
601 // search only for its own filters, without selection box (as in ScDocumentLoader)
602 SfxFilterMatcher aMatcher( ScDocShell::Factory().GetFilterContainer()->GetName() );
603 SfxMedium aSfxMedium( aStrURL, (StreamMode::READ | StreamMode::SHARE_DENYNONE) );
604 // #i73992# GuessFilter no longer calls UseInteractionHandler.
605 // This is UI, so it can be called here.
606 aSfxMedium.UseInteractionHandler(true);
607 ErrCode nErr = aMatcher.GuessFilter( aSfxMedium, pFlt );
609 if ( pFlt && !nErr )
611 // code stolen from the SFX!
612 SfxDispatcher &rDispatcher = GetViewData().GetDispatcher();
613 SfxStringItem aFileNameItem( SID_FILE_NAME, aStrURL );
614 SfxStringItem aFilterItem( SID_FILTER_NAME, pFlt->GetName() );
615 // #i69524# add target, as in SfxApplication when the Open dialog is used
616 SfxStringItem aTargetItem( SID_TARGETNAME, "_default" );
618 // Open Asynchronously, because it can also happen from D&D
619 // and that is not so good for the MAC...
620 return (nullptr != rDispatcher.ExecuteList(SID_OPENDOC,
621 SfxCallMode::ASYNCHRON,
622 { &aFileNameItem, &aFilterItem, &aTargetItem}));
626 // 2. can the file be inserted using the graphics filter?
627 // (as a link, since the Gallery provides it in this way)
629 Graphic aGraphic;
630 GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
632 if (!rGraphicFilter.ImportGraphic(aGraphic, aURL,
633 GRFILTER_FORMAT_DONTKNOW ))
635 if ( bLink )
637 return PasteGraphic( rPos, aGraphic, aStrURL );
639 else
641 // #i76709# if bLink isn't set, pass empty URL/filter, so a non-linked image is inserted
642 return PasteGraphic( rPos, aGraphic, OUString() );
646 if (bLink) // for bLink everything, which is not graphics, as URL
648 tools::Rectangle aRect( rPos, Size(0,0) );
649 ScRange aRange = GetViewData().GetDocument().
650 GetRange( GetViewData().GetTabNo(), aRect );
651 SCCOL nPosX = aRange.aStart.Col();
652 SCROW nPosY = aRange.aStart.Row();
654 InsertBookmark( aStrURL, aStrURL, nPosX, nPosY );
655 return true;
657 else
659 // 3. can the file be inserted as OLE?
660 // also non-storages, for instance sounds (#38282#)
661 uno::Reference < embed::XStorage > xStorage = comphelper::OStorageHelper::GetTemporaryStorage();
663 //TODO/LATER: what about "bLink"?
665 uno::Sequence < beans::PropertyValue > aMedium{ comphelper::makePropertyValue("URL",
666 aStrURL) };
668 comphelper::EmbeddedObjectContainer aCnt( xStorage );
669 OUString aName;
670 uno::Reference < embed::XEmbeddedObject > xObj = aCnt.InsertEmbeddedObject( aMedium, aName );
671 if( xObj.is() )
672 return PasteObject( rPos, xObj, nullptr );
674 // If an OLE object can't be created, insert a URL button
676 GetViewData().GetViewShell()->InsertURLButton( aStrURL, aStrURL, OUString(), &rPos );
677 return true;
681 bool ScViewFunc::PasteBookmark( SotClipboardFormatId nFormatId,
682 const css::uno::Reference< css::datatransfer::XTransferable >& rxTransferable,
683 SCCOL nPosX, SCROW nPosY )
685 INetBookmark aBookmark;
686 TransferableDataHelper aDataHelper( rxTransferable );
687 if ( !aDataHelper.GetINetBookmark( nFormatId, aBookmark ) )
688 return false;
690 InsertBookmark( aBookmark.GetDescription(), aBookmark.GetURL(), nPosX, nPosY );
691 return true;
694 void ScViewFunc::InsertBookmark( const OUString& rDescription, const OUString& rURL,
695 SCCOL nPosX, SCROW nPosY, const OUString* pTarget,
696 bool bTryReplace )
698 ScViewData& rViewData = GetViewData();
699 if ( rViewData.HasEditView( rViewData.GetActivePart() ) &&
700 nPosX >= rViewData.GetEditStartCol() && nPosX <= rViewData.GetEditEndCol() &&
701 nPosY >= rViewData.GetEditStartRow() && nPosY <= rViewData.GetEditEndRow() )
703 // insert into the cell which just got edited
705 OUString aTargetFrame;
706 if (pTarget)
707 aTargetFrame = *pTarget;
708 rViewData.GetViewShell()->InsertURLField( rDescription, rURL, aTargetFrame );
709 return;
712 // insert into not edited cell
714 ScDocument& rDoc = GetViewData().GetDocument();
715 SCTAB nTab = GetViewData().GetTabNo();
716 ScAddress aCellPos( nPosX, nPosY, nTab );
717 EditEngine aEngine( rDoc.GetEnginePool() );
719 const EditTextObject* pOld = rDoc.GetEditText(aCellPos);
720 if (pOld)
721 aEngine.SetText(*pOld);
722 else
724 OUString aOld = rDoc.GetInputString(nPosX, nPosY, nTab);
725 if (!aOld.isEmpty())
726 aEngine.SetText(aOld);
729 sal_Int32 nPara = aEngine.GetParagraphCount();
730 if (nPara)
731 --nPara;
732 sal_Int32 nTxtLen = aEngine.GetTextLen(nPara);
733 ESelection aInsSel( nPara, nTxtLen, nPara, nTxtLen );
735 if ( bTryReplace && HasBookmarkAtCursor( nullptr ) )
737 // if called from hyperlink slot and cell contains only a URL,
738 // replace old URL with new one
740 aInsSel = ESelection( 0, 0, 0, 1 ); // replace first character (field)
743 SvxURLField aField( rURL, rDescription, SvxURLFormat::AppDefault );
744 if (pTarget)
745 aField.SetTargetFrame(*pTarget);
746 aEngine.QuickInsertField( SvxFieldItem( aField, EE_FEATURE_FIELD ), aInsSel );
748 std::unique_ptr<EditTextObject> pData(aEngine.CreateTextObject());
749 EnterData(nPosX, nPosY, nTab, *pData);
752 bool ScViewFunc::HasBookmarkAtCursor( SvxHyperlinkItem* pContent )
754 ScAddress aPos( GetViewData().GetCurX(), GetViewData().GetCurY(), GetViewData().GetTabNo() );
755 ScDocument& rDoc = GetViewData().GetDocShell()->GetDocument();
757 const EditTextObject* pData = rDoc.GetEditText(aPos);
758 if (!pData)
759 return false;
761 if (!pData->IsFieldObject())
762 // not a field object.
763 return false;
765 const SvxFieldItem* pFieldItem = pData->GetField();
766 if (!pFieldItem)
767 // doesn't have a field item.
768 return false;
770 const SvxFieldData* pField = pFieldItem->GetField();
771 if (!pField)
772 // doesn't have a field item data.
773 return false;
775 if (pField->GetClassId() != css::text::textfield::Type::URL)
776 // not a URL field.
777 return false;
779 if (pContent)
781 const SvxURLField* pURLField = static_cast<const SvxURLField*>(pField);
782 pContent->SetName( pURLField->GetRepresentation() );
783 pContent->SetURL( pURLField->GetURL() );
784 pContent->SetTargetFrame( pURLField->GetTargetFrame() );
786 return true;
789 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */