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