diff options
Diffstat (limited to 'sc/source/ui')
36 files changed, 483 insertions, 179 deletions
diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx index 8b4d8bde90b3..e69b06b9abca 100644 --- a/sc/source/ui/app/inputhdl.cxx +++ b/sc/source/ui/app/inputhdl.cxx @@ -830,6 +830,7 @@ ScInputHandler::ScInputHandler() bLastIsSymbol( false ), mbDocumentDisposing(false), mbPartialPrefix(false), + mbEditingExistingContent(false), nValidation( 0 ), eAttrAdjust( SvxCellHorJustify::Standard ), aScaleX( 1,1 ), @@ -1079,14 +1080,14 @@ void ScInputHandler::GetFormulaData() IMPL_LINK( ScInputHandler, ShowHideTipVisibleParentListener, VclWindowEvent&, rEvent, void ) { if (rEvent.GetId() == VclEventId::ObjectDying || rEvent.GetId() == VclEventId::WindowHide - || rEvent.GetId() == VclEventId::WindowLoseFocus) + || rEvent.GetId() == VclEventId::WindowLoseFocus || rEvent.GetId() == VclEventId::ControlLoseFocus) HideTip(); } IMPL_LINK( ScInputHandler, ShowHideTipVisibleSecParentListener, VclWindowEvent&, rEvent, void ) { if (rEvent.GetId() == VclEventId::ObjectDying || rEvent.GetId() == VclEventId::WindowHide - || rEvent.GetId() == VclEventId::WindowLoseFocus) + || rEvent.GetId() == VclEventId::WindowLoseFocus || rEvent.GetId() == VclEventId::ControlLoseFocus) HideTipBelow(); } @@ -1287,6 +1288,7 @@ void ScInputHandler::ShowTipCursor() HideTipBelow(); EditView* pActiveView = pTopView ? pTopView : pTableView; + /* TODO: MLFORMULA: this should work also with multi-line formulas. */ if ( !(bFormulaMode && pActiveView && pFormulaDataPara && mpEditEngine->GetParagraphCount() == 1) ) return; @@ -1534,7 +1536,7 @@ void ScInputHandler::UseFormulaData() { EditView* pActiveView = pTopView ? pTopView : pTableView; - // Formulas may only have 1 paragraph + /* TODO: MLFORMULA: this should work also with multi-line formulas. */ if ( !(pActiveView && pFormulaData && mpEditEngine->GetParagraphCount() == 1) ) return; @@ -1767,6 +1769,9 @@ void ScInputHandler::LOKPasteFunctionData(const OUString& rFunctionName) if (pEditEngine) { aFormula = pEditEngine->GetText(0); + /* TODO: LOK: are you sure you want '+' and '-' let start formulas with + * function names? That was meant for "data typist" numeric keyboard + * input. */ bEdit = aFormula.getLength() > 1 && (aFormula[0] == '=' || aFormula[0] == '+' || aFormula[0] == '-'); } @@ -2166,10 +2171,11 @@ void ScInputHandler::UpdateParenthesis() { // Examine character left to the cursor sal_Int32 nPos = aSel.nStartPos - 1; - OUString aFormula = mpEditEngine->GetText(0); + OUString aFormula = mpEditEngine->GetText(aSel.nStartPara); sal_Unicode c = aFormula[nPos]; if ( c == '(' || c == ')' ) { + // Note this matches only within one paragraph. sal_Int32 nOther = lcl_MatchParenthesis( aFormula, nPos ); if ( nOther != -1 ) { @@ -2185,9 +2191,9 @@ void ScInputHandler::UpdateParenthesis() mpEditEngine->RemoveCharAttribs( i, EE_CHAR_WEIGHT ); } - ESelection aSelThis( 0,nPos, 0,nPos+1 ); + ESelection aSelThis( aSel.nStartPara, nPos, aSel.nStartPara, nPos+1); mpEditEngine->QuickSetAttribs( aSet, aSelThis ); - ESelection aSelOther( 0,nOther, 0,nOther+1 ); + ESelection aSelOther( aSel.nStartPara, nOther, aSel.nStartPara, nOther+1); mpEditEngine->QuickSetAttribs( aSet, aSelOther ); // Dummy InsertText for Update and Paint (selection is empty) @@ -2556,6 +2562,9 @@ bool ScInputHandler::StartTable( sal_Unicode cTyped, bool bFromCommand, bool bIn else aStr = GetEditText(mpEditEngine.get()); + // cTyped!=0 is overtyping, not editing. + mbEditingExistingContent = !cTyped && !aStr.isEmpty(); + if (aStr.startsWith("{=") && aStr.endsWith("}") ) // Matrix formula? { aStr = aStr.copy(1, aStr.getLength() -2); @@ -2569,8 +2578,7 @@ bool ScInputHandler::StartTable( sal_Unicode cTyped, bool bFromCommand, bool bIn if ( bAutoComplete ) GetColData(); - if ( !aStr.isEmpty() && ( aStr[0] == '=' || aStr[0] == '+' || aStr[0] == '-' ) && - !cTyped && !bCreatingFuncView ) + if (!cTyped && !bCreatingFuncView && StartsLikeFormula(aStr)) InitRangeFinder(aStr); // Formula is being edited -> RangeFinder bNewTable = true; // -> PostEditView Call @@ -2761,16 +2769,22 @@ void ScInputHandler::DataChanged( bool bFromTopNotify, bool bSetModified ) bInOwnChange = false; } +bool ScInputHandler::StartsLikeFormula( std::u16string_view rStr ) const +{ + // For new input '+' and '-' may start the dreaded "lazy data typist" + // formula input, editing existing formula content can only start with '='. + return !rStr.empty() && (rStr[0] == '=' || (!mbEditingExistingContent && (rStr[0] == '+' || rStr[0] == '-'))); +} + void ScInputHandler::UpdateFormulaMode() { SfxApplication* pSfxApp = SfxGetpApp(); - bool bIsFormula = !bProtected && mpEditEngine->GetParagraphCount() == 1; + bool bIsFormula = !bProtected; if (bIsFormula) { const OUString& rText = mpEditEngine->GetText(0); - bIsFormula = !rText.isEmpty() && - (rText[0] == '=' || rText[0] == '+' || rText[0] == '-'); + bIsFormula = StartsLikeFormula(rText); } if ( bIsFormula ) @@ -3001,7 +3015,7 @@ static void lcl_SelectionToEnd( EditView* pView ) } } -void ScInputHandler::EnterHandler( ScEnterMode nBlockMode ) +void ScInputHandler::EnterHandler( ScEnterMode nBlockMode, bool bBeforeSavingInLOK ) { if (!mbDocumentDisposing && comphelper::LibreOfficeKit::isActive() && pActiveViewSh != SfxViewShell::Current()) @@ -3081,6 +3095,16 @@ void ScInputHandler::EnterHandler( ScEnterMode nBlockMode ) pSelEngine->ReleaseMouse(); } + if (bBeforeSavingInLOK) + { + // Invalid entry but not applied to the document model. + // Exit to complete the "save", leaving the edit view as it is + // for the user to continue after save. + bInOwnChange = false; + bInEnterHandler = false; + return; + } + if (pData->DoError(pActiveViewSh->GetFrameWeld(), aString, aCursorPos)) bForget = true; // Do not take over input } @@ -3366,6 +3390,7 @@ void ScInputHandler::EnterHandler( ScEnterMode nBlockMode ) nFormSelStart = nFormSelEnd = 0; aFormText.clear(); + mbEditingExistingContent = false; bInOwnChange = false; bInEnterHandler = false; } @@ -3378,6 +3403,7 @@ void ScInputHandler::CancelHandler() bModified = false; mbPartialPrefix = false; + mbEditingExistingContent = false; // Don't rely on ShowRefFrame switching the active view synchronously // execute the function directly on the correct view's bindings instead diff --git a/sc/source/ui/app/inputwin.cxx b/sc/source/ui/app/inputwin.cxx index b601fc4d5c34..d44ee9769bf9 100644 --- a/sc/source/ui/app/inputwin.cxx +++ b/sc/source/ui/app/inputwin.cxx @@ -1798,7 +1798,8 @@ bool ScTextWnd::Command( const CommandEvent& rCEvt ) bool ScTextWnd::StartDrag() { - if (m_xEditView) + // tdf#145248 don't start a drag if actively selecting + if (m_xEditView && !m_xEditEngine->IsInSelectionMode()) { OUString sSelection = m_xEditView->GetSelected(); m_xHelper->SetData(sSelection); @@ -2362,8 +2363,7 @@ void ScPosWnd::Notify( SfxBroadcaster&, const SfxHint& rHint ) else { const SfxHintId nHintId = rHint.GetId(); - if (nHintId == SfxHintId::ScAreasChanged || nHintId == SfxHintId::ScNavigatorUpdateAll - || nHintId == SfxHintId::ScTablesRenamed) + if (nHintId == SfxHintId::ScAreasChanged || nHintId == SfxHintId::ScNavigatorUpdateAll) FillRangeNames(); } } diff --git a/sc/source/ui/app/scmod.cxx b/sc/source/ui/app/scmod.cxx index dee33b48a509..3534ecdb69e3 100644 --- a/sc/source/ui/app/scmod.cxx +++ b/sc/source/ui/app/scmod.cxx @@ -1356,13 +1356,13 @@ bool ScModule::InputKeyEvent( const KeyEvent& rKEvt, bool bStartEdit ) return pHdl && pHdl->KeyInput( rKEvt, bStartEdit ); } -void ScModule::InputEnterHandler( ScEnterMode nBlockMode ) +void ScModule::InputEnterHandler( ScEnterMode nBlockMode, bool bBeforeSavingInLOK ) { if ( !SfxGetpApp()->IsDowning() ) // Not when quitting the program { ScInputHandler* pHdl = GetInputHdl(); if (pHdl) - pHdl->EnterHandler( nBlockMode ); + pHdl->EnterHandler( nBlockMode, bBeforeSavingInLOK ); } } diff --git a/sc/source/ui/cctrl/checklistmenu.cxx b/sc/source/ui/cctrl/checklistmenu.cxx index f62b2369da27..88366b2ff0ac 100644 --- a/sc/source/ui/cctrl/checklistmenu.cxx +++ b/sc/source/ui/cctrl/checklistmenu.cxx @@ -283,6 +283,8 @@ void ScCheckListMenuControl::queueCloseSubMenu() maCloseTimer.mpSubMenu = maOpenTimer.mpSubMenu; maCloseTimer.mnMenuPos = maOpenTimer.mnMenuPos; + maOpenTimer.mpSubMenu = nullptr; + maOpenTimer.mnMenuPos = MENU_NOT_SELECTED; maCloseTimer.maTimer.Start(); } @@ -570,11 +572,8 @@ void ScCheckListMenuControl::GrabFocus() } } -ScCheckListMenuControl::~ScCheckListMenuControl() +void ScCheckListMenuControl::DropPendingEvents() { - EndPopupMode(); - for (auto& rMenuItem : maMenuItems) - rMenuItem.mxSubMenuWin.reset(); if (mnAsyncPostPopdownId) { Application::RemoveUserEvent(mnAsyncPostPopdownId); @@ -587,6 +586,14 @@ ScCheckListMenuControl::~ScCheckListMenuControl() } } +ScCheckListMenuControl::~ScCheckListMenuControl() +{ + EndPopupMode(); + for (auto& rMenuItem : maMenuItems) + rMenuItem.mxSubMenuWin.reset(); + DropPendingEvents(); +} + void ScCheckListMenuControl::prepWindow() { mxMenu->set_size_request(-1, mxMenu->get_preferred_size().Height() + 2); @@ -1427,6 +1434,8 @@ IMPL_LINK_NOARG(ScCheckListMenuControl, PopupModeEndHdl, weld::Popover&, void) if (mxPopupEndAction) mxPopupEndAction->execute(); + DropPendingEvents(); + if (comphelper::LibreOfficeKit::isActive()) NotifyCloseLOK(); } diff --git a/sc/source/ui/dbgui/PivotLayoutDialog.cxx b/sc/source/ui/dbgui/PivotLayoutDialog.cxx index 05a9428eda5e..3ea7e0121eb0 100644 --- a/sc/source/ui/dbgui/PivotLayoutDialog.cxx +++ b/sc/source/ui/dbgui/PivotLayoutDialog.cxx @@ -627,7 +627,8 @@ void ScPivotLayoutDialog::PushDataFieldNames(std::vector<ScDPName>& rDataFieldNa void ScPivotLayoutDialog::Close() { - DoClose( ScPivotLayoutWrapper::GetChildWindowId() ); + DoClose(ScPivotLayoutWrapper::GetChildWindowId()); + SfxDialogController::Close(); } IMPL_LINK_NOARG( ScPivotLayoutDialog, OKClicked, weld::Button&, void ) diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx index a126b0b9330b..2e1a62070511 100644 --- a/sc/source/ui/docshell/docfunc.cxx +++ b/sc/source/ui/docshell/docfunc.cxx @@ -3400,6 +3400,7 @@ bool ScDocFunc::DeleteTable( SCTAB nTab, bool bRecord ) SfxApplication* pSfxApp = SfxGetpApp(); // Navigator pSfxApp->Broadcast( SfxHint( SfxHintId::ScTablesChanged ) ); + pSfxApp->Broadcast( SfxHint( SfxHintId::ScAreasChanged ) ); pSfxApp->Broadcast( SfxHint( SfxHintId::ScDbAreasChanged ) ); pSfxApp->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) ); @@ -3516,7 +3517,7 @@ bool ScDocFunc::RenameTable( SCTAB nTab, const OUString& rName, bool bRecord, bo rDocShell.PostPaintExtras(); aModificator.SetDocumentModified(); SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged ) ); - SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesRenamed ) ); + SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreasChanged ) ); bSuccess = true; } diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx index 4a13484c82cf..19992e3641d5 100644 --- a/sc/source/ui/docshell/docsh.cxx +++ b/sc/source/ui/docshell/docsh.cxx @@ -136,6 +136,9 @@ #include <memory> #include <vector> +#include <svtools/sfxecode.hxx> +#include <unotools/pathoptions.hxx> + using namespace com::sun::star; using ::com::sun::star::uno::Reference; using ::com::sun::star::lang::XMultiServiceFactory; @@ -1789,6 +1792,17 @@ bool ScDocShell::SaveAs( SfxMedium& rMedium ) bNeedsRehash = ScPassHashHelper::needsPassHashRegen(m_aDocument, PASSHASH_SHA256); } + // skip saving recovery file instead of showing re-type password dialog window + if ( bNeedsRehash && rMedium.GetFilter()->GetFilterName() == "calc8" && + // it seems, utl::MediaDescriptor::PROP_AUTOSAVEEVENT is true at Save As, too, + // so check the backup path + rMedium.GetName().startsWith( SvtPathOptions().GetBackupPath() ) ) + { + SAL_WARN("sc.filter", "Should re-type password for own format, won't export recovery file"); + rMedium.SetError(ERRCODE_SFX_WRONGPASSWORD); + return false; + } + if (pViewShell && bNeedsRehash) { if (!pViewShell->ExecuteRetypePassDlg(PASSHASH_SHA1)) diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx index 472872db7359..2e3df2f54a23 100644 --- a/sc/source/ui/docshell/externalrefmgr.cxx +++ b/sc/source/ui/docshell/externalrefmgr.cxx @@ -3080,6 +3080,14 @@ void ScExternalRefManager::setFilterData(sal_uInt16 nFileId, const OUString& rFi void ScExternalRefManager::clear() { + for (auto& rEntry : maLinkListeners) + { + for (auto& it : rEntry.second) + { + it->notify(0, OH_NO_WE_ARE_GOING_TO_DIE); + } + } + for (auto& rEntry : maDocShells) rEntry.second.maShell->DoClose(); diff --git a/sc/source/ui/docshell/impex.cxx b/sc/source/ui/docshell/impex.cxx index 5d8e755c18f6..5bd8052e0bec 100644 --- a/sc/source/ui/docshell/impex.cxx +++ b/sc/source/ui/docshell/impex.cxx @@ -1616,40 +1616,55 @@ bool ScImportExport::ExtText2Doc( SvStream& rStrm ) bool bMultiLine = false; if ( bFixed ) // Fixed line length { - sal_Int32 nStartIdx = 0; - // Yes, the check is nCol<=rDoc.MaxCol()+1, +1 because it is only an - // overflow if there is really data following to be put behind - // the last column, which doesn't happen if info is - // SC_COL_SKIP. - for ( i=0; i<nInfoCount && nCol <= rDoc.MaxCol()+1; i++ ) + if (bDetermineRange) { - sal_uInt8 nFmt = pColFormat[i]; - if (nFmt != SC_COL_SKIP) // otherwise don't increment nCol either + // Yes, the check is nCol<=rDoc.MaxCol()+1, +1 because it + // is only an overflow if there is really data following to + // be put behind the last column, which doesn't happen if + // info is SC_COL_SKIP. + for (i=0; i < nInfoCount && nCol <= rDoc.MaxCol()+1; ++i) { - if (nCol > rDoc.MaxCol()) - bOverflowCol = true; // display warning on import - else if (!bDetermineRange) + const sal_uInt8 nFmt = pColFormat[i]; + if (nFmt != SC_COL_SKIP) // otherwise don't increment nCol either { - sal_Int32 nNextIdx = nStartIdx; - if ( i + 1 < nInfoCount ) - CountVisualWidth( aLine, nNextIdx, pColStart[i+1] - pColStart[i] ); + if (nCol > rDoc.MaxCol()) + bOverflowCol = true; // display warning on import + ++nCol; + } + } + } + else + { + sal_Int32 nStartIdx = 0; + // Same maxcol+1 check reason as above. + for (i=0; i < nInfoCount && nCol <= rDoc.MaxCol()+1; ++i) + { + sal_Int32 nNextIdx = nStartIdx; + if (i + 1 < nInfoCount) + CountVisualWidth( aLine, nNextIdx, pColStart[i+1] - pColStart[i] ); + else + nNextIdx = nLineLen; + sal_uInt8 nFmt = pColFormat[i]; + if (nFmt != SC_COL_SKIP) // otherwise don't increment nCol either + { + if (nCol > rDoc.MaxCol()) + bOverflowCol = true; // display warning on import else - nNextIdx = nLineLen; - - bool bIsQuoted = false; - aCell = lcl_GetFixed( aLine, nStartIdx, nNextIdx, bIsQuoted, bOverflowCell ); - if (bIsQuoted && bQuotedAsText) - nFmt = SC_COL_TEXT; - - bMultiLine |= lcl_PutString( - aDocImport, !mbOverwriting, nCol, nRow, nTab, aCell, nFmt, - &aNumFormatter, bDetectNumFormat, bEvaluateFormulas, bSkipEmptyCells, - aTransliteration, aCalendar, - pEnglishTransliteration.get(), pEnglishCalendar.get()); - - nStartIdx = nNextIdx; + { + bool bIsQuoted = false; + aCell = lcl_GetFixed( aLine, nStartIdx, nNextIdx, bIsQuoted, bOverflowCell ); + if (bIsQuoted && bQuotedAsText) + nFmt = SC_COL_TEXT; + + bMultiLine |= lcl_PutString( + aDocImport, !mbOverwriting, nCol, nRow, nTab, aCell, nFmt, + &aNumFormatter, bDetectNumFormat, bEvaluateFormulas, bSkipEmptyCells, + aTransliteration, aCalendar, + pEnglishTransliteration.get(), pEnglishCalendar.get()); + } + ++nCol; } - ++nCol; + nStartIdx = nNextIdx; } } } @@ -1766,10 +1781,41 @@ void ScImportExport::EmbeddedNullTreatment( OUString & rStr ) // The normal case is no embedded NULL, check first before de-/allocating // ustring stuff. - sal_Unicode cNull = 0; - if (rStr.indexOf( cNull) >= 0) + const sal_Unicode cNull = 0; + sal_Int32 i; + if ((i = rStr.indexOf( cNull)) >= 0) { - rStr = rStr.replaceAll( std::u16string_view( &cNull, 1), ""); + // Do not use OUString::replaceAll(...,""), in case of repeated null + // bytes that reallocates for each and for massive amounts takes + // ~endless. See tdf#147421 with 3577016 trailing null-bytes. + const sal_Int32 nLen = rStr.getLength(); + OUStringBuffer aBuf( nLen); + sal_Int32 s = 0; + sal_Unicode const * const p = rStr.getStr(); + do + { + // Append good substring. + aBuf.append( p + s, i - s); + // Skip all cNull. + while (++i < nLen && *(p+i) == cNull) + ; + // Find next cNull after good if characters left, else end. + if (i < nLen) + { + s = i; + i = rStr.indexOf( cNull, i); + } + else + { + s = nLen; + } + } + while (0 <= i && i < nLen); + // Append good trailing substring, if any. + if (s < nLen) + aBuf.append( p + s, nLen - s); + + rStr = aBuf.makeStringAndClear(); } } @@ -2294,7 +2340,7 @@ bool ScImportExport::Sylk2Doc( SvStream& rStrm ) aFormats.push_back( nKey ); } } - else if( cTag == 'I' && *p == 'D' ) + else if (cTag == 'I' && *p == 'D' && aLine.getLength() > 4) { aLine = aLine.copy(4); if (aLine == "CALCOOO32") diff --git a/sc/source/ui/inc/checklistmenu.hxx b/sc/source/ui/inc/checklistmenu.hxx index 961fddceac58..8d135870d871 100644 --- a/sc/source/ui/inc/checklistmenu.hxx +++ b/sc/source/ui/inc/checklistmenu.hxx @@ -254,6 +254,8 @@ private: DECL_LINK(SetDropdownPosHdl, void*, void); + void DropPendingEvents(); + private: std::unique_ptr<weld::Builder> mxBuilder; std::unique_ptr<weld::Popover> mxPopover; diff --git a/sc/source/ui/inc/inputhdl.hxx b/sc/source/ui/inc/inputhdl.hxx index fb3880e97a69..88ec1dd81adc 100644 --- a/sc/source/ui/inc/inputhdl.hxx +++ b/sc/source/ui/inc/inputhdl.hxx @@ -105,6 +105,7 @@ private: bool mbDocumentDisposing:1; /// To indicate if there is a partial prefix completion. bool mbPartialPrefix:1; + bool mbEditingExistingContent:1; sal_uLong nValidation; SvxCellHorJustify eAttrAdjust; @@ -146,6 +147,7 @@ private: bool StartTable( sal_Unicode cTyped, bool bFromCommand, bool bInputActivated, ScEditEngineDefaulter* pTopEngine ); void RemoveSelection(); + bool StartsLikeFormula( std::u16string_view rStr ) const; void UpdateFormulaMode(); static void InvalidateAttribs(); void ImplCreateEditEngine(); @@ -198,7 +200,7 @@ public: void MergeLanguageAttributes( ScEditEngineDefaulter& rDestEngine ) const; bool KeyInput( const KeyEvent& rKEvt, bool bStartEdit ); - void EnterHandler( ScEnterMode nBlockMode = ScEnterMode::NORMAL ); + void EnterHandler( ScEnterMode nBlockMode = ScEnterMode::NORMAL, bool bBeforeSavingInLOK = false ); void CancelHandler(); void SetReference( const ScRange& rRef, const ScDocument& rDoc ); void AddRefEntry(); diff --git a/sc/source/ui/inc/undoblk.hxx b/sc/source/ui/inc/undoblk.hxx index 39dba0afa20d..a0de06cb698d 100644 --- a/sc/source/ui/inc/undoblk.hxx +++ b/sc/source/ui/inc/undoblk.hxx @@ -163,14 +163,14 @@ private: struct ScUndoPasteOptions { ScPasteFunc nFunction; - bool bSkipEmpty; + bool bSkipEmptyCells; bool bTranspose; bool bAsLink; InsCellCmd eMoveMode; ScUndoPasteOptions() : nFunction( ScPasteFunc::NONE ), - bSkipEmpty( false ), + bSkipEmptyCells( false ), bTranspose( false ), bAsLink( false ), eMoveMode( INS_NONE ) diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx index ec037cc18e71..80b9b090bcad 100644 --- a/sc/source/ui/inc/viewfunc.hxx +++ b/sc/source/ui/inc/viewfunc.hxx @@ -116,12 +116,14 @@ public: bool CopyToClipMultiRange( const ScDocument* pClipDoc, const ScRangeList& rRanges, bool bCut, bool bApi, bool bIncludeObjects ); rtl::Reference<ScTransferObj> CopyToTransferable(); - SC_DLLPUBLIC bool PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, - ScPasteFunc nFunction = ScPasteFunc::NONE, bool bSkipEmpty = false, - bool bTranspose = false, bool bAsLink = false, - InsCellCmd eMoveMode = INS_NONE, - InsertDeleteFlags nUndoExtraFlags = InsertDeleteFlags::NONE, - bool bAllowDialogs = false ); + + SC_DLLPUBLIC bool PasteFromClip( + InsertDeleteFlags nFlags, ScDocument* pClipDoc, + ScPasteFunc nFunction = ScPasteFunc::NONE, bool bSkipEmptyCells = false, + bool bTranspose = false, bool bAsLink = false, + InsCellCmd eMoveMode = INS_NONE, + InsertDeleteFlags nUndoExtraFlags = InsertDeleteFlags::NONE, + bool bAllowDialogs = false ); void FillTab( InsertDeleteFlags nFlags, ScPasteFunc nFunction, bool bSkipEmpty, bool bAsLink ); @@ -352,14 +354,16 @@ private: void PasteRTF( SCCOL nCol, SCROW nStartRow, const css::uno::Reference< css::datatransfer::XTransferable >& rxTransferable ); - bool PasteMultiRangesFromClip(InsertDeleteFlags nFlags, ScDocument* pClipDoc, - ScPasteFunc nFunction, bool bSkipEmpty, bool bIncludeFiltered, - bool bTranspose, bool bAsLink, bool bAllowDialogs, - InsCellCmd eMoveMode, InsertDeleteFlags nUndoFlags); + bool PasteMultiRangesFromClip( + InsertDeleteFlags nFlags, ScDocument* pClipDoc, + ScPasteFunc nFunction, bool bSkipEmptyCells, bool bIncludeFiltered, + bool bTranspose, bool bAsLink, bool bAllowDialogs, + InsCellCmd eMoveMode, InsertDeleteFlags nUndoFlags ); - bool PasteFromClipToMultiRanges( InsertDeleteFlags nFlags, ScDocument* pClipDoc, ScPasteFunc nFunction, - bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs, - InsCellCmd eMoveMode, InsertDeleteFlags nUndoFlags ); + bool PasteFromClipToMultiRanges( + InsertDeleteFlags nFlags, ScDocument* pClipDoc, ScPasteFunc nFunction, + bool bSkipEmptyCells, bool bTranspose, bool bAsLink, bool bAllowDialogs, + InsCellCmd eMoveMode, InsertDeleteFlags nUndoFlags ); void PostPasteFromClip(const ScRangeList& rPasteRanges, const ScMarkData& rMark); diff --git a/sc/source/ui/miscdlgs/sharedocdlg.cxx b/sc/source/ui/miscdlgs/sharedocdlg.cxx index ec019fb70655..294a69e93c2b 100644 --- a/sc/source/ui/miscdlgs/sharedocdlg.cxx +++ b/sc/source/ui/miscdlgs/sharedocdlg.cxx @@ -39,7 +39,7 @@ using namespace ::com::sun::star; IMPL_LINK(ScShareDocumentDlg, SizeAllocated, const Size&, rSize, void) { - OUString sWidestAccessString = getWidestTime(ScGlobal::getLocaleData()); + OUString sWidestAccessString = getWidestDateTime(ScGlobal::getLocaleData(), false); const int nAccessWidth = m_xLbUsers->get_pixel_size(sWidestAccessString).Width() * 2; std::vector<int> aWidths { @@ -151,7 +151,7 @@ void ScShareDocumentDlg::UpdateView() tools::Time aTime( nHours, nMinutes ); DateTime aDateTime( aDate, aTime ); - OUString aString = formatTime(aDateTime, ScGlobal::getLocaleData()); + OUString aString = formatDateTime(aDateTime, ScGlobal::getLocaleData(), false); m_xLbUsers->append_text(aUser); m_xLbUsers->set_text(m_xLbUsers->n_children() - 1, aString, 1); @@ -201,7 +201,7 @@ void ScShareDocumentDlg::UpdateView() util::DateTime uDT(xDocProps->getModificationDate()); DateTime aDateTime(uDT); - OUString aString = formatTime(aDateTime, ScGlobal::getLocaleData()) + " " + + OUString aString = formatDateTime(aDateTime, ScGlobal::getLocaleData(), false) + " " + ScGlobal::getLocaleData().getTime( aDateTime, false ); m_xLbUsers->append_text(aUser); diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx index 26841c009eb2..be93e37bd35f 100644 --- a/sc/source/ui/undo/undoblk.cxx +++ b/sc/source/ui/undo/undoblk.cxx @@ -1177,7 +1177,7 @@ void ScUndoPaste::Repeat(SfxRepeatTarget& rTarget) if (pOwnClip) { pViewSh->PasteFromClip( nFlags, pOwnClip->GetDocument(), - aPasteOptions.nFunction, aPasteOptions.bSkipEmpty, aPasteOptions.bTranspose, + aPasteOptions.nFunction, aPasteOptions.bSkipEmptyCells, aPasteOptions.bTranspose, aPasteOptions.bAsLink, aPasteOptions.eMoveMode, InsertDeleteFlags::NONE, true ); // allow warning dialog } diff --git a/sc/source/ui/undo/undotab.cxx b/sc/source/ui/undo/undotab.cxx index 467e93cb7145..a4000a12863a 100644 --- a/sc/source/ui/undo/undotab.cxx +++ b/sc/source/ui/undo/undotab.cxx @@ -363,6 +363,7 @@ void ScUndoDeleteTab::Undo() } SfxApplication* pSfxApp = SfxGetpApp(); // Navigator pSfxApp->Broadcast( SfxHint( SfxHintId::ScTablesChanged ) ); + pSfxApp->Broadcast( SfxHint( SfxHintId::ScAreasChanged ) ); pSfxApp->Broadcast( SfxHint( SfxHintId::ScDbAreasChanged ) ); pSfxApp->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) ); @@ -433,7 +434,7 @@ void ScUndoRenameTab::DoChange( SCTAB nTabP, const OUString& rName ) const rDoc.RenameTab( nTabP, rName ); SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged ) ); // Navigator - SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesRenamed ) ); // Name Box + SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreasChanged ) ); // Also Name Box pDocShell->PostPaintGridAll(); pDocShell->PostPaintExtras(); @@ -597,7 +598,9 @@ void ScUndoCopyTab::DoChange() const if (pViewShell) pViewShell->SetTabNo((*mpOldTabs)[0],true); - SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScTablesChanged ) ); // Navigator + SfxApplication* pSfxApp = SfxGetpApp(); // Navigator + pSfxApp->Broadcast( SfxHint( SfxHintId::ScTablesChanged ) ); + pSfxApp->Broadcast( SfxHint( SfxHintId::ScAreasChanged ) ); pDocShell->PostPaintGridAll(); pDocShell->PostPaintExtras(); diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx index 622307974a75..566a989ecafc 100644 --- a/sc/source/ui/unoobj/cellsuno.cxx +++ b/sc/source/ui/unoobj/cellsuno.cxx @@ -6721,7 +6721,9 @@ uno::Reference<sheet::XSheetCellCursor> SAL_CALL ScTableSheetObj::createCursorBy if (pRangesImp) { const ScRangeList& rRanges = pRangesImp->GetRangeList(); - OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" ); + SAL_WARN_IF( rRanges.size() != 1, "sc", "ScTableSheetObj::createCursorByRange: Range? Ranges?"); + if (rRanges.empty()) + return nullptr; return new ScCellCursorObj( pDocSh, rRanges[ 0 ] ); } } diff --git a/sc/source/ui/unoobj/chart2uno.cxx b/sc/source/ui/unoobj/chart2uno.cxx index 40e72bbfc8d9..f15ceb2722a2 100644 --- a/sc/source/ui/unoobj/chart2uno.cxx +++ b/sc/source/ui/unoobj/chart2uno.cxx @@ -2915,6 +2915,9 @@ void ScChart2DataSequence::ExternalRefListener::notify(sal_uInt16 nFileId, ScExt case ScExternalRefManager::LINK_BROKEN: maFileIds.erase(nFileId); break; + case ScExternalRefManager::OH_NO_WE_ARE_GOING_TO_DIE: + mpDoc = nullptr; + break; } } diff --git a/sc/source/ui/unoobj/listenercalls.cxx b/sc/source/ui/unoobj/listenercalls.cxx index 2d9a23083ca8..7ff7c7df0956 100644 --- a/sc/source/ui/unoobj/listenercalls.cxx +++ b/sc/source/ui/unoobj/listenercalls.cxx @@ -44,7 +44,7 @@ void ScUnoListenerCalls::ExecuteAndClear() // During each modified() call, Add may be called again. // These new calls are executed here, too. - std::vector<ScUnoListenerEntry>::iterator aItr(aEntries.begin()); + std::list<ScUnoListenerEntry>::iterator aItr(aEntries.begin()); while (aItr != aEntries.end()) { ScUnoListenerEntry aEntry = *aItr; diff --git a/sc/source/ui/vba/excelvbahelper.cxx b/sc/source/ui/vba/excelvbahelper.cxx index d337a0f6836e..37d3a5fcf1de 100644 --- a/sc/source/ui/vba/excelvbahelper.cxx +++ b/sc/source/ui/vba/excelvbahelper.cxx @@ -210,25 +210,28 @@ void implnPasteSpecial( const uno::Reference< frame::XModel>& xModel, InsertDele { PasteCellsWarningReseter resetWarningBox; - ScTabViewShell* pTabViewShell = getBestViewShell( xModel ); - ScDocShell* pDocShell = getDocShell( xModel ); - if ( !(pTabViewShell && pDocShell) ) + ScTabViewShell* pTabViewShell = getBestViewShell(xModel); + if (!pTabViewShell) + return; + + ScDocShell* pDocShell = getDocShell(xModel); + if (!pDocShell) return; ScViewData& rView = pTabViewShell->GetViewData(); vcl::Window* pWin = rView.GetActiveWin(); - if (pWin) + if (!pWin) + return; + + const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(pWin)); + if (pOwnClip) { - const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(pDocShell->GetClipData()); - ScDocument* pDoc = nullptr; - if ( pOwnClip ) - pDoc = pOwnClip->GetDocument(); - pTabViewShell->PasteFromClip( nFlags, pDoc, + pTabViewShell->PasteFromClip(nFlags, pOwnClip->GetDocument(), nFunction, bSkipEmpty, bTranspose, false, - INS_NONE, InsertDeleteFlags::NONE, true ); + INS_NONE, InsertDeleteFlags::NONE, true); + pTabViewShell->CellContentChanged(); } - } ScDocShell* diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx index 1cb307133cf7..351cbdc60a75 100644 --- a/sc/source/ui/vba/vbarange.cxx +++ b/sc/source/ui/vba/vbarange.cxx @@ -871,15 +871,18 @@ protected: ScCellRangesBase* pUnoRangesBase = dynamic_cast< ScCellRangesBase* >( xIf.get() ); if ( pUnoRangesBase ) { - ScRangeList aCellRanges = pUnoRangesBase->GetRangeList(); - ScCompiler aCompiler( m_rDoc, aCellRanges.front().aStart, m_eGrammar ); - // compile the string in the format passed in - std::unique_ptr<ScTokenArray> pArray(aCompiler.CompileString(sFormula)); - // convert to API grammar - aCompiler.SetGrammar( formula::FormulaGrammar::GRAM_API ); - OUString sConverted; - aCompiler.CreateStringFromTokenArray(sConverted); - sFormula = EQUALS + sConverted; + const ScRangeList& rCellRanges = pUnoRangesBase->GetRangeList(); + if (!rCellRanges.empty()) + { + ScCompiler aCompiler( m_rDoc, rCellRanges.front().aStart, m_eGrammar ); + // compile the string in the format passed in + std::unique_ptr<ScTokenArray> pArray(aCompiler.CompileString(sFormula)); + // convert to API grammar + aCompiler.SetGrammar( formula::FormulaGrammar::GRAM_API ); + OUString sConverted; + aCompiler.CreateStringFromTokenArray(sConverted); + sFormula = EQUALS + sConverted; + } } } @@ -917,16 +920,19 @@ public: { OUString sVal; aValue >>= sVal; - ScRangeList aCellRanges = pUnoRangesBase->GetRangeList(); - // Compile string from API grammar. - ScCompiler aCompiler( m_rDoc, aCellRanges.front().aStart, formula::FormulaGrammar::GRAM_API ); - std::unique_ptr<ScTokenArray> pArray(aCompiler.CompileString(sVal)); - // Convert to desired grammar. - aCompiler.SetGrammar( m_eGrammar ); - OUString sConverted; - aCompiler.CreateStringFromTokenArray(sConverted); - sVal = EQUALS + sConverted; - aValue <<= sVal; + const ScRangeList& rCellRanges = pUnoRangesBase->GetRangeList(); + if (!rCellRanges.empty()) + { + // Compile string from API grammar. + ScCompiler aCompiler( m_rDoc, rCellRanges.front().aStart, formula::FormulaGrammar::GRAM_API ); + std::unique_ptr<ScTokenArray> pArray(aCompiler.CompileString(sVal)); + // Convert to desired grammar. + aCompiler.SetGrammar( m_eGrammar ); + OUString sConverted; + aCompiler.CreateStringFromTokenArray(sConverted); + sVal = EQUALS + sConverted; + aValue <<= sVal; + } } } @@ -1279,9 +1285,12 @@ uno::Reference< sheet::XSheetCellRange > lclExpandToMerged( const uno::Reference { aOldAddress = aNewAddress; uno::Reference< sheet::XSheetCellCursor > xCursor( xSheet->createCursorByRange( xNewCellRange ), uno::UNO_SET_THROW ); - xCursor->collapseToMergedArea(); - xNewCellRange.set( xCursor, uno::UNO_QUERY_THROW ); - aNewAddress = lclGetRangeAddress( xNewCellRange ); + if (xCursor.is()) + { + xCursor->collapseToMergedArea(); + xNewCellRange.set( xCursor, uno::UNO_QUERY_THROW ); + aNewAddress = lclGetRangeAddress( xNewCellRange ); + } } while( bRecursive && (aOldAddress != aNewAddress) ); return xNewCellRange; @@ -1913,7 +1922,8 @@ ScVbaRange::Offset( const ::uno::Any &nRowOff, const uno::Any &nColOff ) return new ScVbaRange( mxParent, mxContext, xRanges ); } // normal range - uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pUnoRangesBase->GetDocShell(), aCellRanges.front() ) ); + const ScRange aRange( obtainRangeEvenIfRangeListIsEmpty( aCellRanges)); + uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pUnoRangesBase->GetDocShell(), aRange)); return new ScVbaRange( mxParent, mxContext, xRange ); } @@ -2364,17 +2374,28 @@ ScVbaRange::Activate() } +ScRange ScVbaRange::obtainRangeEvenIfRangeListIsEmpty( const ScRangeList& rCellRanges ) const +{ + // XXX It may be that using the current range list was never correct, but + // always the initial sheet range would be instead, history is unclear. + + if (!rCellRanges.empty()) + return rCellRanges.front(); + + table::CellRangeAddress aRA( lclGetRangeAddress( mxRange )); + return ScRange( aRA.StartColumn, aRA.StartRow, aRA.Sheet, aRA.EndColumn, aRA.EndRow, aRA.Sheet); +} + uno::Reference< excel::XRange > ScVbaRange::Rows(const uno::Any& aIndex ) { if ( aIndex.hasValue() ) { - sal_Int32 nValue = 0; ScCellRangesBase* pUnoRangesBase = getCellRangesBase(); - ScRangeList aCellRanges = pUnoRangesBase->GetRangeList(); - OUString sAddress; + ScRange aRange( obtainRangeEvenIfRangeListIsEmpty( pUnoRangesBase->GetRangeList())); - ScRange aRange = aCellRanges.front(); + sal_Int32 nValue = 0; + OUString sAddress; if( aIndex >>= nValue ) { aRange.aStart.SetRow( aRange.aStart.Row() + --nValue ); @@ -2410,9 +2431,8 @@ uno::Reference< excel::XRange > ScVbaRange::Columns(const uno::Any& aIndex ) { ScCellRangesBase* pUnoRangesBase = getCellRangesBase(); - ScRangeList aCellRanges = pUnoRangesBase->GetRangeList(); + ScRange aRange( obtainRangeEvenIfRangeListIsEmpty( pUnoRangesBase->GetRangeList())); - ScRange aRange = aCellRanges.front(); if ( aIndex.hasValue() ) { OUString sAddress; @@ -2534,7 +2554,9 @@ ScVbaRange::Copy(const ::uno::Any& Destination) } else { - excel::implnCopy( getUnoModel() ); + uno::Reference<frame::XModel> xModel = getModelFromRange(mxRange); + Select(); + excel::implnCopy(getUnoModel()); } } @@ -2892,7 +2914,8 @@ ScVbaRange::PasteSpecial( const uno::Any& Paste, const uno::Any& Operation, cons InsertDeleteFlags nFlags = getPasteFlags(nPaste); ScPasteFunc nFormulaBits = getPasteFormulaBits(nOperation); - excel::implnPasteSpecial(pShell->GetModel(), nFlags,nFormulaBits,bSkipBlanks,bTranspose); + + excel::implnPasteSpecial(xModel, nFlags, nFormulaBits, bSkipBlanks, bTranspose); } uno::Reference< excel::XRange > @@ -2923,7 +2946,8 @@ ScVbaRange::getEntireColumnOrRow( bool bColumn ) return new ScVbaRange( mxParent, mxContext, xRanges, !bColumn, bColumn ); } - uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pUnoRangesBase->GetDocShell(), aCellRanges.front() ) ); + const ScRange aRange( obtainRangeEvenIfRangeListIsEmpty( aCellRanges)); + uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( pUnoRangesBase->GetDocShell(), aRange)); return new ScVbaRange( mxParent, mxContext, xRange, !bColumn, bColumn ); } @@ -3409,9 +3433,9 @@ ScVbaRange::Sort( const uno::Any& Key1, const uno::Any& Order1, const uno::Any& // set up defaults - sal_Int16 nOrder1 = aSortParam.maKeyState[1].bAscending ? excel::XlSortOrder::xlAscending : excel::XlSortOrder::xlDescending; - sal_Int16 nOrder2 = aSortParam.maKeyState[2].bAscending ? excel::XlSortOrder::xlAscending : excel::XlSortOrder::xlDescending; - sal_Int16 nOrder3 = aSortParam.maKeyState[3].bAscending ? excel::XlSortOrder::xlAscending : excel::XlSortOrder::xlDescending; + sal_Int16 nOrder1 = aSortParam.maKeyState[0].bAscending ? excel::XlSortOrder::xlAscending : excel::XlSortOrder::xlDescending; + sal_Int16 nOrder2 = aSortParam.maKeyState[1].bAscending ? excel::XlSortOrder::xlAscending : excel::XlSortOrder::xlDescending; + sal_Int16 nOrder3 = aSortParam.maKeyState[2].bAscending ? excel::XlSortOrder::xlAscending : excel::XlSortOrder::xlDescending; sal_Int16 nCustom = aSortParam.nUserIndex; sal_Int16 nSortMethod = excel::XlSortMethod::xlPinYin; diff --git a/sc/source/ui/vba/vbarange.hxx b/sc/source/ui/vba/vbarange.hxx index 2e9b71746879..cdeab983fa6d 100644 --- a/sc/source/ui/vba/vbarange.hxx +++ b/sc/source/ui/vba/vbarange.hxx @@ -119,6 +119,9 @@ class ScVbaRange : public ScVbaRange_BASE /** Fires a Worksheet_Change event for this range or range list. */ void fireChangeEvent(); + /// @throws css::uno::RuntimeException + ScRange obtainRangeEvenIfRangeListIsEmpty( const ScRangeList& rCellRanges ) const; + protected: virtual ScCellRangesBase* getCellRangesBase() override; /// @throws css::uno::RuntimeException diff --git a/sc/source/ui/vba/vbaworkbooks.cxx b/sc/source/ui/vba/vbaworkbooks.cxx index bd52292cfa5a..e3b608b33942 100644 --- a/sc/source/ui/vba/vbaworkbooks.cxx +++ b/sc/source/ui/vba/vbaworkbooks.cxx @@ -144,9 +144,14 @@ ScVbaWorkbooks::Add( const uno::Any& Template ) // need to set up the document modules ( and vba mode ) here excel::setUpDocumentModules( xSpreadDoc ); - if( xSpreadDoc.is() ) - return getWorkbook( mxContext, xSpreadDoc, mxParent ); - return uno::Any(); + if (!xSpreadDoc.is()) + return uno::Any(); + + uno::Any aRet = getWorkbook( mxContext, xSpreadDoc, mxParent ); + uno::Reference< excel::XWorkbook > xWBook( aRet, uno::UNO_QUERY ); + if (xWBook.is()) + xWBook->Activate(); + return aRet; } void SAL_CALL diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx index 0bed3b16141f..8ff829326597 100644 --- a/sc/source/ui/view/cellsh2.cxx +++ b/sc/source/ui/view/cellsh2.cxx @@ -526,6 +526,55 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq ) // subtotal when needed new pTabViewShell->UISort( rOutParam ); + + SfxViewFrame* pViewFrm = pTabViewShell->GetViewFrame(); + if (pViewFrm) + { + SfxRequest aRequest(pViewFrm, SID_SORT); + + if ( rOutParam.bInplace ) + { + aRequest.AppendItem( SfxBoolItem( SID_SORT_BYROW, + rOutParam.bByRow ) ); + aRequest.AppendItem( SfxBoolItem( SID_SORT_HASHEADER, + rOutParam.bHasHeader ) ); + aRequest.AppendItem( SfxBoolItem( SID_SORT_CASESENS, + rOutParam.bCaseSens ) ); + aRequest.AppendItem( SfxBoolItem( SID_SORT_NATURALSORT, + rOutParam.bNaturalSort ) ); + aRequest.AppendItem( SfxBoolItem( SID_SORT_INCCOMMENTS, + rOutParam.aDataAreaExtras.mbCellNotes ) ); + aRequest.AppendItem( SfxBoolItem( SID_SORT_INCIMAGES, + rOutParam.aDataAreaExtras.mbCellDrawObjects ) ); + aRequest.AppendItem( SfxBoolItem( SID_SORT_ATTRIBS, + rOutParam.aDataAreaExtras.mbCellFormats ) ); + sal_uInt16 nUser = rOutParam.bUserDef ? ( rOutParam.nUserIndex + 1 ) : 0; + aRequest.AppendItem( SfxUInt16Item( SID_SORT_USERDEF, nUser ) ); + if ( rOutParam.maKeyState[0].bDoSort ) + { + aRequest.AppendItem( SfxInt32Item( FN_PARAM_1, + rOutParam.maKeyState[0].nField + 1 ) ); + aRequest.AppendItem( SfxBoolItem( FN_PARAM_2, + rOutParam.maKeyState[0].bAscending ) ); + } + if ( rOutParam.maKeyState[1].bDoSort ) + { + aRequest.AppendItem( SfxInt32Item( FN_PARAM_3, + rOutParam.maKeyState[1].nField + 1 ) ); + aRequest.AppendItem( SfxBoolItem( FN_PARAM_4, + rOutParam.maKeyState[1].bAscending ) ); + } + if ( rOutParam.maKeyState[2].bDoSort ) + { + aRequest.AppendItem( SfxInt32Item( FN_PARAM_5, + rOutParam.maKeyState[2].nField + 1 ) ); + aRequest.AppendItem( SfxBoolItem( FN_PARAM_6, + rOutParam.maKeyState[2].bAscending ) ); + } + } + + aRequest.Done(); + } } else { diff --git a/sc/source/ui/view/editsh.cxx b/sc/source/ui/view/editsh.cxx index c7e7dabd1ee5..ba0abdc433c4 100644 --- a/sc/source/ui/view/editsh.cxx +++ b/sc/source/ui/view/editsh.cxx @@ -526,6 +526,7 @@ void ScEditShell::Execute( SfxRequest& rReq ) case SID_TOGGLE_REL: { + /* TODO: MLFORMULA: this should work also with multi-line formulas. */ if (pEngine->GetParagraphCount() == 1) { OUString aText = pEngine->GetText(); diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index 42b02d4b9743..f41d7b580a01 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -475,6 +475,7 @@ IMPL_LINK_NOARG(ScGridWindow, PopupModeEndHdl, weld::Popover&, void) mpFilterBox->SetCancelled(); // cancel select // restore the mouse capture state of the GridWindow to // what it was at initial popup time + SAL_WARN_IF(bMouseWasCaptured, "sc.ui", "Is there a scenario where the mouse was captured before mouse down?"); if (bMouseWasCaptured) CaptureMouse(); } @@ -524,6 +525,7 @@ public: virtual bool execute() override { mpWindow->RefreshAutoFilterButton(maPos); + mpWindow->GrabFocus(); return false; // this is called after the popup has been closed } }; @@ -1796,6 +1798,9 @@ void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt, MouseEventSta if (pScMod->IsModalMode(mrViewData.GetSfxDocShell())) return; + const bool bWasMouseCaptured = IsMouseCaptured(); + SAL_WARN_IF(bWasMouseCaptured, "sc.ui", "Is there a scenario where the mouse is captured before mouse down?"); + pScActiveViewShell = mrViewData.GetViewShell(); // if left is clicked nScClickMouseModifier = rMEvt.GetModifier(); // to always catch a control click @@ -2052,9 +2057,11 @@ void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt, MouseEventSta tools::Rectangle aButtonRect = GetListValButtonRect( aListValPos ); if ( aButtonRect.Contains( aPos ) ) { - // tdf#125917 typically we have the mouse captured already, except if are editing the cell. - // Ensure its captured before the menu is launched even in the cell editing case - CaptureMouse(); + // tdf#149609 if we captured the mouse in the course of this function + // release it before showing the data select menu to undo any unhelpful + // seleng capture + if (!bWasMouseCaptured && IsMouseCaptured()) + ReleaseMouse(); LaunchDataSelectMenu( aListValPos.Col(), aListValPos.Row() ); @@ -2070,7 +2077,11 @@ void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt, MouseEventSta ScRange aScenRange; if ( rMEvt.IsLeft() && HasScenarioButton( aPos, aScenRange ) ) { - CaptureMouse(); + // tdf#149609 if we captured the mouse in the course of this function + // release it before showing the data scenario menu to undo any unhelpful + // seleng capture + if (!bWasMouseCaptured && IsMouseCaptured()) + ReleaseMouse(); DoScenarioMenu( aScenRange ); diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx index 5da4a54508d2..d1aa33f4c847 100644 --- a/sc/source/ui/view/gridwin4.cxx +++ b/sc/source/ui/view/gridwin4.cxx @@ -1355,7 +1355,9 @@ namespace if (!pPageView) return; - SdrPageWindow* pSdrPageWindow = pPageView->GetPageWindow(0); + SdrPageWindow* pSdrPageWindow = nullptr; + if (pPageView->PageWindowCount() > 0) + pSdrPageWindow = pPageView->GetPageWindow(0); if (!pSdrPageWindow) return; diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx index ba4a1b13a795..56e428d557a2 100644 --- a/sc/source/ui/view/output2.cxx +++ b/sc/source/ui/view/output2.cxx @@ -74,6 +74,7 @@ #include <scopetools.hxx> #include <com/sun/star/i18n/DirectionProperty.hpp> +#include <comphelper/scopeguard.hxx> #include <comphelper/string.hxx> #include <memory> @@ -1518,6 +1519,12 @@ void ScOutputData::DrawStrings( bool bPixelToLogic ) tools::Rectangle ScOutputData::LayoutStrings(bool bPixelToLogic, bool bPaint, const ScAddress &rAddress) { + bool bOrigIsInLayoutStrings = mpDoc->IsInLayoutStrings(); + mpDoc->SetLayoutStrings(true); + comphelper::ScopeGuard g([this, bOrigIsInLayoutStrings] { + mpDoc->SetLayoutStrings(bOrigIsInLayoutStrings); + }); + OSL_ENSURE( mpDev == mpRefDevice || mpDev->GetMapMode().GetMapUnit() == mpRefDevice->GetMapMode().GetMapUnit(), "LayoutStrings: different MapUnits ?!?!" ); @@ -1552,6 +1559,11 @@ tools::Rectangle ScOutputData::LayoutStrings(bool bPixelToLogic, bool bPaint, co const SfxItemSet* pOldCondSet = nullptr; SvtScriptType nOldScript = SvtScriptType::NONE; + // Try to limit interpreting to only visible cells. Calling e.g. IsValue() + // on a formula cell that needs interpreting would call Interpret() + // for the entire formula group, which could be large. + mpDoc->InterpretCellsIfNeeded( ScRange( nX1, nY1, nTab, nX2, nY2, nTab )); + // alternative pattern instances in case we need to modify the pattern // before processing the cell value. std::vector<std::unique_ptr<ScPatternAttr> > aAltPatterns; diff --git a/sc/source/ui/view/printfun.cxx b/sc/source/ui/view/printfun.cxx index ccd015552074..b5d2da8b96c6 100644 --- a/sc/source/ui/view/printfun.cxx +++ b/sc/source/ui/view/printfun.cxx @@ -3091,6 +3091,10 @@ void PrintPageRanges::calculate(ScDocument& rDoc, rDoc.SetPageSize(nPrintTab, rDocSize); + // Clear the map to prevent any outdated values to "survive" when + // we have to recalculate the new values anyway + m_xPageRows->clear(); + // #i123672# use dynamic mem to react on size changes if (m_xPageEndX->size() < static_cast<size_t>(rDoc.MaxCol()) + 1) { diff --git a/sc/source/ui/view/spellcheckcontext.cxx b/sc/source/ui/view/spellcheckcontext.cxx index 224af6859f59..a1358dcd647a 100644 --- a/sc/source/ui/view/spellcheckcontext.cxx +++ b/sc/source/ui/view/spellcheckcontext.cxx @@ -327,12 +327,14 @@ void SpellCheckContext::ensureResults(SCCOL nCol, SCROW nRow) } // Cache miss, the cell needs spell-check.. - mpEngine->SetDefaultItem(SvxLanguageItem(eCellLang, EE_CHAR_LANGUAGE)); if (eType == CELLTYPE_STRING) mpEngine->SetText(aCell.mpString->getString()); else mpEngine->SetText(*aCell.mpEditText); + // it has to happen after we set text + mpEngine->SetDefaultItem(SvxLanguageItem(eCellLang, EE_CHAR_LANGUAGE)); + mpStatus->mbModified = false; mpEngine->CompleteOnlineSpelling(); std::unique_ptr<MisspellType> pRanges; diff --git a/sc/source/ui/view/tabvwsh2.cxx b/sc/source/ui/view/tabvwsh2.cxx index a096a766ea7d..9060fa98e65c 100644 --- a/sc/source/ui/view/tabvwsh2.cxx +++ b/sc/source/ui/view/tabvwsh2.cxx @@ -265,6 +265,7 @@ void ScTabViewShell::ExecDraw(SfxRequest& rReq) case SID_DRAW_TEXT_MARQUEE: case SID_DRAW_NOTEEDIT: pTabView->SetDrawFuncPtr(new FuText(*this, pWin, pView, pDoc, aNewReq)); + bCreateDirectly = comphelper::LibreOfficeKit::isActive(); break; case SID_FM_CREATE_CONTROL: @@ -335,7 +336,6 @@ void ScTabViewShell::ExecDraw(SfxRequest& rReq) } else { - GetViewFrame()->GetDispatcher()->Execute(SID_OBJECT_SELECT, SfxCallMode::ASYNCHRON); ScViewData& rViewData = GetViewData(); aInsertPos = rViewData.getLOKVisibleArea().Center(); if (comphelper::LibreOfficeKit::isCompatFlagSet( @@ -370,13 +370,20 @@ void ScTabViewShell::ExecDraw(SfxRequest& rReq) // insert into page pView->InsertObjectAtView(pObj.release(), *pPageView); - if ( nNewId == SID_DRAW_CAPTION || nNewId == SID_DRAW_CAPTION_VERTICAL ) + switch ( nNewId ) { + case SID_DRAW_CAPTION: + case SID_DRAW_CAPTION_VERTICAL: + case SID_DRAW_TEXT: + case SID_DRAW_TEXT_VERTICAL: // use KeyInput to start edit mode (FuText is created). // For FuText objects, edit mode is handled within CreateDefaultObject. // KEY_F2 is handled in FuDraw::KeyInput. pFuActual->KeyInput( KeyEvent( 0, vcl::KeyCode( KEY_F2 ) ) ); + break; + default: + break; } } diff --git a/sc/source/ui/view/tabvwsha.cxx b/sc/source/ui/view/tabvwsha.cxx index 414a293d854d..39910e32cc39 100644 --- a/sc/source/ui/view/tabvwsha.cxx +++ b/sc/source/ui/view/tabvwsha.cxx @@ -29,6 +29,7 @@ #include <sfx2/viewfrm.hxx> #include <svl/ilstitem.hxx> #include <svl/numformat.hxx> +#include <svl/zformat.hxx> #include <svl/int64item.hxx> #include <svl/srchitem.hxx> #include <svl/srchdefs.hxx> @@ -127,6 +128,17 @@ bool ScTabViewShell::GetFunction( OUString& rFuncStr, FormulaError nErrCode ) { // number format from attributes or formula nNumFmt = rDoc.GetNumberFormat( nPosX, nPosY, nTab ); + // If the number format is time (without date) and the + // result is not within 24 hours, use a duration + // format. Summing date+time doesn't make much sense + // otherwise but we also don't want to display duration + // for a single date+time value. + if (nVal < 0.0 || nVal >= 1.0) + { + const SvNumberformat* pFormat = pFormatter->GetEntry(nNumFmt); + if (pFormat && (pFormat->GetType() == SvNumFormatType::TIME)) + nNumFmt = pFormatter->GetTimeFormat( nVal, pFormat->GetLanguage(), true); + } } OUString aValStr; @@ -757,9 +769,16 @@ void ScTabViewShell::ExecuteSave( SfxRequest& rReq ) // Finish entering unless 'DontTerminateEdit' is specified, even if a formula is being processed if (bCommitChanges) { - SC_MOD()->InputEnterHandler(); + bool bLOKActive = comphelper::LibreOfficeKit::isActive(); + + // Disable error dialog box when about to save in lok mode as + // this ultimately invokes SvpSalInstance::DoYield() when we want + // to save immediately without committing any erroneous input in possibly + // a cell with validation rules. After save is complete the user + // can continue editing. + SC_MOD()->InputEnterHandler(ScEnterMode::NORMAL, bLOKActive /* bBeforeSavingInLOK */); - if (comphelper::LibreOfficeKit::isActive()) + if (bLOKActive) { // Normally this isn't needed, but in Calc when editing a cell formula // and manually saving (without changing cells or hitting enter), while diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx index 6ac95430a84e..f712d23ae0e6 100644 --- a/sc/source/ui/view/viewdata.cxx +++ b/sc/source/ui/view/viewdata.cxx @@ -1153,7 +1153,7 @@ ScMarkType ScViewData::GetSimpleArea( ScRange & rRange, ScMarkData & rNewMark ) if (eMarkType == SC_MARK_NONE) eMarkType = SC_MARK_SIMPLE; const ScPatternAttr* pMarkPattern = mrDoc.GetPattern(GetCurX(), GetCurY(), GetTabNo()); - if (pMarkPattern->GetItemSet().GetItemState(ATTR_MERGE, false) == SfxItemState::SET) + if (pMarkPattern && pMarkPattern->GetItemSet().GetItemState(ATTR_MERGE, false) == SfxItemState::SET) { SCROW nRow = pMarkPattern->GetItem(ATTR_MERGE).GetRowMerge(); SCCOL nCol = pMarkPattern->GetItem(ATTR_MERGE).GetColMerge(); @@ -2416,7 +2416,7 @@ Point ScViewData::GetScrPos( SCCOL nWhereX, SCROW nWhereY, ScSplitPos eWhich, const_cast<ScViewData*>(this)->aScrSize.setHeight( pView->GetGridHeight(eWhichY) ); } - sal_uLong nTSize; + sal_uInt16 nTSize; bool bIsTiledRendering = comphelper::LibreOfficeKit::isActive(); @@ -2484,20 +2484,27 @@ Point ScViewData::GetScrPos( SCCOL nWhereX, SCROW nWhereY, ScSplitPos eWhich, if (nWhereY >= nStartPosY) { - if (bAllowNeg || bIsTiledRendering || nScrPosY <= aScrSize.Height()) + for (SCROW nY = nStartPosY; nY < nWhereY && (bAllowNeg || bIsTiledRendering || nScrPosY <= aScrSize.Height()); nY++) { - if (nWhereY - 1 > mrDoc.MaxRow()) + if ( nY > mrDoc.MaxRow() ) nScrPosY = 0x7FFFFFFF; - else if (bAllowNeg || bIsTiledRendering) - { - sal_uLong nSizeYPix = mrDoc.GetScaledRowHeight(nStartPosY, nWhereY - 1, nForTab, nPPTY); - nScrPosY += nSizeYPix; - } else { - sal_uLong nMaxHeight = aScrSize.getHeight() - nScrPosY; - sal_uLong nSizeYPix = mrDoc.GetScaledRowHeight(nStartPosY, nWhereY - 1, nForTab, nPPTY, &nMaxHeight); - nScrPosY += nSizeYPix; + nTSize = mrDoc.GetRowHeight( nY, nTabNo ); + if (nTSize) + { + tools::Long nSizeYPix = ToPixel( nTSize, nPPTY ); + nScrPosY += nSizeYPix; + } + else if ( nY < mrDoc.MaxRow() ) + { + // skip multiple hidden rows (forward only for now) + SCROW nNext = mrDoc.FirstVisibleRow(nY + 1, mrDoc.MaxRow(), nTabNo); + if ( nNext > mrDoc.MaxRow() ) + nY = mrDoc.MaxRow(); + else + nY = nNext - 1; // +=nDir advances to next visible row + } } } } diff --git a/sc/source/ui/view/viewfun2.cxx b/sc/source/ui/view/viewfun2.cxx index f5c79f583efb..fe8536918164 100644 --- a/sc/source/ui/view/viewfun2.cxx +++ b/sc/source/ui/view/viewfun2.cxx @@ -2591,6 +2591,7 @@ bool ScViewFunc::DeleteTables(const vector<SCTAB> &TheTabs, bool bRecord ) SfxApplication* pSfxApp = SfxGetpApp(); // Navigator pSfxApp->Broadcast( SfxHint( SfxHintId::ScTablesChanged ) ); + pSfxApp->Broadcast( SfxHint( SfxHintId::ScAreasChanged ) ); pSfxApp->Broadcast( SfxHint( SfxHintId::ScDbAreasChanged ) ); pSfxApp->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) ); } diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx index 5397d2dec352..679557d020b4 100644 --- a/sc/source/ui/view/viewfun3.cxx +++ b/sc/source/ui/view/viewfun3.cxx @@ -869,7 +869,7 @@ bool checkDestRangeForOverwrite(const ScRangeList& rDestRanges, const ScDocument } bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, - ScPasteFunc nFunction, bool bSkipEmpty, + ScPasteFunc nFunction, bool bSkipEmptyCells, bool bTranspose, bool bAsLink, InsCellCmd eMoveMode, InsertDeleteFlags nUndoExtraFlags, bool bAllowDialogs ) @@ -900,7 +900,7 @@ bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, if (rClipParam.isMultiRange()) { // Source data is multi-range. - return PasteMultiRangesFromClip(nFlags, pClipDoc, nFunction, bSkipEmpty, false, bTranspose, + return PasteMultiRangesFromClip(nFlags, pClipDoc, nFunction, bSkipEmptyCells, false, bTranspose, bAsLink, bAllowDialogs, eMoveMode, nUndoFlags); } @@ -909,7 +909,7 @@ bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, { // Source data is single-range but destination is multi-range. return PasteFromClipToMultiRanges( - nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs, + nFlags, pClipDoc, nFunction, bSkipEmptyCells, bTranspose, bAsLink, bAllowDialogs, eMoveMode, nUndoFlags); } @@ -1281,7 +1281,7 @@ bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, ScDocumentUniquePtr pMixDoc; if (nFunction != ScPasteFunc::NONE) { - bSkipEmpty = false; + bSkipEmptyCells = false; if ( nFlags & InsertDeleteFlags::CONTENTS ) { pMixDoc.reset(new ScDocument( SCDOCMODE_UNDO )); @@ -1306,7 +1306,7 @@ bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, // copy normally (original range) rDoc.CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, pRefUndoDoc.get(), pClipDoc, true, false, bIncludeFiltered, - bSkipEmpty, (bMarkIsFiltered ? &aRangeList : nullptr) ); + bSkipEmptyCells, (bMarkIsFiltered ? &aRangeList : nullptr) ); // adapt refs manually in case of transpose if ( bTranspose && bCutMode && (nFlags & InsertDeleteFlags::CONTENTS) ) @@ -1316,7 +1316,7 @@ bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, { // copy with bAsLink=TRUE rDoc.CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, pRefUndoDoc.get(), pClipDoc, - true, true, bIncludeFiltered, bSkipEmpty ); + true, true, bIncludeFiltered, bSkipEmptyCells ); } else { @@ -1333,7 +1333,7 @@ bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, if ( pMixDoc ) // calculate with original data? { - rDoc.MixDocument( aUserRange, nFunction, bSkipEmpty, *pMixDoc ); + rDoc.MixDocument( aUserRange, nFunction, bSkipEmptyCells, *pMixDoc ); } pMixDoc.reset(); @@ -1405,7 +1405,7 @@ bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, ScUndoPasteOptions aOptions; // store options for repeat aOptions.nFunction = nFunction; - aOptions.bSkipEmpty = bSkipEmpty; + aOptions.bSkipEmptyCells = bSkipEmptyCells; aOptions.bTranspose = bTranspose; aOptions.bAsLink = bAsLink; aOptions.eMoveMode = eMoveMode; @@ -1464,7 +1464,7 @@ bool ScViewFunc::PasteFromClip( InsertDeleteFlags nFlags, ScDocument* pClipDoc, } bool ScViewFunc::PasteMultiRangesFromClip(InsertDeleteFlags nFlags, ScDocument* pClipDoc, - ScPasteFunc nFunction, bool bSkipEmpty, + ScPasteFunc nFunction, bool bSkipEmptyCells, bool bIncludeFiltered, bool bTranspose, bool bAsLink, bool bAllowDialogs, InsCellCmd eMoveMode, InsertDeleteFlags nUndoFlags) @@ -1554,7 +1554,7 @@ bool ScViewFunc::PasteMultiRangesFromClip(InsertDeleteFlags nFlags, ScDocument* } ScDocumentUniquePtr pMixDoc; - if ( bSkipEmpty || nFunction != ScPasteFunc::NONE) + if ( bSkipEmptyCells || nFunction != ScPasteFunc::NONE) { if ( nFlags & InsertDeleteFlags::CONTENTS ) { @@ -1578,10 +1578,10 @@ bool ScViewFunc::PasteMultiRangesFromClip(InsertDeleteFlags nFlags, ScDocument* if (bAsLink && bTranspose) nCopyFlags |= InsertDeleteFlags::FORMULA; rDoc.CopyMultiRangeFromClip(rCurPos, aMark, nCopyFlags, pClipDoc, true, bAsLink && !bTranspose, - bIncludeFiltered, bSkipEmpty); + bIncludeFiltered, bSkipEmptyCells); if (pMixDoc) - rDoc.MixDocument(aMarkedRange, nFunction, bSkipEmpty, *pMixDoc); + rDoc.MixDocument(aMarkedRange, nFunction, bSkipEmptyCells, *pMixDoc); AdjustBlockHeight(); // update row heights before pasting objects @@ -1611,7 +1611,7 @@ bool ScViewFunc::PasteMultiRangesFromClip(InsertDeleteFlags nFlags, ScDocument* ScUndoPasteOptions aOptions; // store options for repeat aOptions.nFunction = nFunction; - aOptions.bSkipEmpty = bSkipEmpty; + aOptions.bSkipEmptyCells = bSkipEmptyCells; aOptions.bTranspose = bTranspose; aOptions.bAsLink = bAsLink; aOptions.eMoveMode = eMoveMode; @@ -1634,7 +1634,7 @@ bool ScViewFunc::PasteMultiRangesFromClip(InsertDeleteFlags nFlags, ScDocument* bool ScViewFunc::PasteFromClipToMultiRanges( InsertDeleteFlags nFlags, ScDocument* pClipDoc, ScPasteFunc nFunction, - bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs, + bool bSkipEmptyCells, bool bTranspose, bool bAsLink, bool bAllowDialogs, InsCellCmd eMoveMode, InsertDeleteFlags nUndoFlags ) { if (bTranspose) @@ -1714,7 +1714,7 @@ bool ScViewFunc::PasteFromClipToMultiRanges( } ScDocumentUniquePtr pMixDoc; - if (bSkipEmpty || nFunction != ScPasteFunc::NONE) + if (bSkipEmptyCells || nFunction != ScPasteFunc::NONE) { if (nFlags & InsertDeleteFlags::CONTENTS) { @@ -1738,13 +1738,13 @@ bool ScViewFunc::PasteFromClipToMultiRanges( { rDoc.CopyFromClip( aRanges[i], aMark, (nFlags & ~InsertDeleteFlags::OBJECTS), nullptr, pClipDoc, - false, false, true, bSkipEmpty); + false, false, true, bSkipEmptyCells); } if (pMixDoc) { for (size_t i = 0, n = aRanges.size(); i < n; ++i) - rDoc.MixDocument(aRanges[i], nFunction, bSkipEmpty, *pMixDoc); + rDoc.MixDocument(aRanges[i], nFunction, bSkipEmptyCells, *pMixDoc); } AdjustBlockHeight(); // update row heights before pasting objects @@ -1756,7 +1756,7 @@ bool ScViewFunc::PasteFromClipToMultiRanges( { rDoc.CopyFromClip( aRanges[i], aMark, InsertDeleteFlags::OBJECTS, nullptr, pClipDoc, - false, false, true, bSkipEmpty); + false, false, true, bSkipEmptyCells); } } @@ -1777,7 +1777,7 @@ bool ScViewFunc::PasteFromClipToMultiRanges( ScUndoPasteOptions aOptions; // store options for repeat aOptions.nFunction = nFunction; - aOptions.bSkipEmpty = bSkipEmpty; + aOptions.bSkipEmptyCells = bSkipEmptyCells; aOptions.bTranspose = bTranspose; aOptions.bAsLink = bAsLink; aOptions.eMoveMode = eMoveMode; diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx index af151534c018..95020795aceb 100644 --- a/sc/source/ui/view/viewfunc.cxx +++ b/sc/source/ui/view/viewfunc.cxx @@ -77,6 +77,7 @@ #include <comphelper/lok.hxx> #include <conditio.hxx> #include <columnspanset.hxx> +#include <stringutil.hxx> #include <memory> @@ -337,6 +338,29 @@ namespace HelperNotifyChanges } } +namespace +{ + class AutoCorrectQuery : public weld::MessageDialogController + { + private: + std::unique_ptr<weld::TextView> m_xError; + public: + AutoCorrectQuery(weld::Window* pParent, const OUString& rFormula) + : weld::MessageDialogController(pParent, "modules/scalc/ui/warnautocorrect.ui", "WarnAutoCorrect", "grid") + , m_xError(m_xBuilder->weld_text_view("error")) + { + m_xDialog->set_primary_text(ScResId(SCSTR_FORMULA_AUTOCORRECTION).trim()); + m_xDialog->set_default_response(RET_YES); + + const int nMaxWidth = m_xError->get_approximate_digit_width() * 65; + const int nMaxHeight = m_xError->get_height_rows(6); + m_xError->set_size_request(nMaxWidth, nMaxHeight); + + m_xError->set_text(rFormula); + } + }; +} + // actual functions // input - undo OK @@ -447,13 +471,8 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, nResult = RET_NO; // empty formula, just '=' else { - OUString aMessage = ScResId( SCSTR_FORMULA_AUTOCORRECTION ) + aCorrectedFormula; - - std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetViewData().GetDialogParent(), - VclMessageType::Question, VclButtonsType::YesNo, - aMessage)); - xQueryBox->set_default_response(RET_YES); - nResult = xQueryBox->run(); + AutoCorrectQuery aQueryBox(GetViewData().GetDialogParent(), aCorrectedFormula); + nResult = aQueryBox.run(); } if ( nResult == RET_YES ) { @@ -560,10 +579,24 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, } else { + ScFieldEditEngine& rEngine = rDoc.GetEditEngine(); for (const auto& rTab : rMark) { bool bNumFmtSet = false; - rFunc.SetNormalString( bNumFmtSet, ScAddress( nCol, nRow, rTab ), rString, false ); + const ScAddress aScAddress(nCol, nRow, rTab); + + // tdf#104902 - handle embedded newline + if (ScStringUtil::isMultiline(rString)) + { + rEngine.SetTextCurrentDefaults(rString); + rDoc.SetEditText(aScAddress, rEngine.CreateTextObject()); + pDocSh->AdjustRowHeight(nRow, nRow, rTab); + } + else + { + rFunc.SetNormalString(bNumFmtSet, aScAddress, rString, false); + } + if (bNumFmtSet) { /* FIXME: if set on any sheet results in changed only on @@ -661,7 +694,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, // formulas have to be recognized even if they're formatted // (but common attributes are still collected) - if ( !bSimple && aEngine.GetParagraphCount() == 1 ) + if (!bSimple) { OUString aParStr(aEngine.GetText( 0 )); if ( aParStr[0] == '=' ) |