/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// Write freezepan data only when freeze pans are set if(nExFixPosX != 0 || nExFixPosY != 0 || nExHSplitPos != 0 || nExVSplitPos != 0)
{
pSettings[SC_HORIZONTAL_SPLIT_MODE].Name = SC_HORIZONTALSPLITMODE;
pSettings[SC_HORIZONTAL_SPLIT_MODE].Value <<= sal_Int16(eExHSplitMode);
pSettings[SC_VERTICAL_SPLIT_MODE].Name = SC_VERTICALSPLITMODE;
pSettings[SC_VERTICAL_SPLIT_MODE].Value <<= sal_Int16(eExVSplitMode);
pSettings[SC_HORIZONTAL_SPLIT_POSITION].Name = SC_HORIZONTALSPLITPOSITION; if (eExHSplitMode == SC_SPLIT_FIX)
pSettings[SC_HORIZONTAL_SPLIT_POSITION].Value <<= sal_Int32(nExFixPosX); else
pSettings[SC_HORIZONTAL_SPLIT_POSITION].Value <<= sal_Int32(nExHSplitPos);
pSettings[SC_VERTICAL_SPLIT_POSITION].Name = SC_VERTICALSPLITPOSITION; if (eExVSplitMode == SC_SPLIT_FIX)
pSettings[SC_VERTICAL_SPLIT_POSITION].Value <<= sal_Int32(nExFixPosY); else
pSettings[SC_VERTICAL_SPLIT_POSITION].Value <<= sal_Int32(nExVSplitPos);
}
// Prevent writing odd settings that would make crash versions that // don't apply SanitizeWhichActive() when reading the settings. // See tdf#117093 const ScSplitPos eActiveSplitRange = SanitizeWhichActive(); // And point out to give us a chance to inspect weird things (if anyone // remembers what s/he did).
assert(eWhichActive == eActiveSplitRange);
pSettings[SC_ACTIVE_SPLIT_RANGE].Name = SC_ACTIVESPLITRANGE;
pSettings[SC_ACTIVE_SPLIT_RANGE].Value <<= sal_Int16(eActiveSplitRange);
pSettings[SC_POSITION_LEFT].Name = SC_POSITIONLEFT;
pSettings[SC_POSITION_LEFT].Value <<= sal_Int32(nPosX[SC_SPLIT_LEFT]);
pSettings[SC_POSITION_RIGHT].Name = SC_POSITIONRIGHT;
pSettings[SC_POSITION_RIGHT].Value <<= sal_Int32(nPosX[SC_SPLIT_RIGHT]);
pSettings[SC_POSITION_TOP].Name = SC_POSITIONTOP;
pSettings[SC_POSITION_TOP].Value <<= sal_Int32(nPosY[SC_SPLIT_TOP]);
pSettings[SC_POSITION_BOTTOM].Name = SC_POSITIONBOTTOM;
pSettings[SC_POSITION_BOTTOM].Value <<= sal_Int32(nPosY[SC_SPLIT_BOTTOM]);
void ScViewData::CopyTab( SCTAB nSrcTab, SCTAB nDestTab )
{ if (nDestTab==SC_TAB_APPEND)
nDestTab = mrDoc.GetTableCount() - 1; // something had to have been copied
if (nDestTab > MAXTAB)
{
OSL_FAIL("too many sheets"); return;
}
if (nSrcTab >= static_cast<SCTAB>(maTabData.size()))
OSL_FAIL("pTabData out of bounds, FIX IT");
EnsureTabDataSize(nDestTab + 1);
if ( maTabData[nSrcTab] )
maTabData.emplace(maTabData.begin() + nDestTab, new ScViewDataTable( *maTabData[nSrcTab] )); else
maTabData.insert(maTabData.begin() + nDestTab, nullptr);
if ( rNewMark.IsMarked() || rNewMark.IsMultiMarked() )
{ if ( rNewMark.IsMultiMarked() )
rNewMark.MarkToSimple();
if ( rNewMark.IsMarked() && !rNewMark.IsMultiMarked() )
{
rRange = rNewMark.GetMarkArea(); if (ScViewUtil::HasFiltered(rRange, GetDocument()))
eMarkType = SC_MARK_SIMPLE_FILTERED; else
eMarkType = SC_MARK_SIMPLE;
} else
eMarkType = SC_MARK_MULTI;
} if (eMarkType != SC_MARK_SIMPLE && eMarkType != SC_MARK_SIMPLE_FILTERED)
{ if (eMarkType == SC_MARK_NONE)
eMarkType = SC_MARK_SIMPLE; const ScPatternAttr* pMarkPattern = mrDoc.GetPattern(GetCurX(), GetCurY(), GetTabNo()); const ScMergeAttr* pMergeItem = nullptr; if (pMarkPattern && pMarkPattern->GetItemSet().GetItemState(ATTR_MERGE, false, &pMergeItem) == SfxItemState::SET)
{
SCROW nRow = pMergeItem->GetRowMerge();
SCCOL nCol = pMergeItem->GetColMerge(); if ( nRow < 1 || nCol < 1 )
{ // This kind of cells do exist. Not sure if that is intended or a bug.
rRange = ScRange(GetCurX(), GetCurY(), GetTabNo());
} else
{
rRange = ScRange(GetCurX(), GetCurY(), GetTabNo(),
GetCurX() + nCol - 1, GetCurY() + nRow - 1, GetTabNo()); if ( ScViewUtil::HasFiltered(rRange, GetDocument()) )
eMarkType = SC_MARK_SIMPLE_FILTERED;
}
} else
rRange = ScRange(GetCurX(), GetCurY(), GetTabNo());
} return eMarkType;
}
ScMarkType ScViewData::GetSimpleArea( SCCOL& rStartCol, SCROW& rStartRow, SCTAB& rStartTab,
SCCOL& rEndCol, SCROW& rEndRow, SCTAB& rEndTab ) const
{ // parameter bMergeMark is no longer needed: The view's selection is never modified // (a local copy is used), and a multi selection that adds to a single range can always // be treated like a single selection (GetSimpleArea isn't used in selection // handling itself)
ScRange aRange;
ScMarkData aNewMark(maMarkData); // use a local copy for MarkToSimple
ScMarkType eMarkType = GetSimpleArea( aRange, aNewMark);
aRange.GetVars( rStartCol, rStartRow, rStartTab, rEndCol, rEndRow, rEndTab); return eMarkType;
}
ScMarkType ScViewData::GetSimpleArea( ScRange& rRange ) const
{ // parameter bMergeMark is no longer needed, see above
ScMarkData aNewMark(maMarkData); // use a local copy for MarkToSimple return GetSimpleArea( rRange, aNewMark);
}
void ScViewData::GetMultiArea( ScRangeListRef& rRange ) const
{ // parameter bMergeMark is no longer needed, see GetSimpleArea
ScMarkData aNewMark(maMarkData); // use a local copy for MarkToSimple
bool bMulti = aNewMark.IsMultiMarked(); if (bMulti)
{
aNewMark.MarkToSimple();
bMulti = aNewMark.IsMultiMarked();
} if (bMulti)
{
rRange = new ScRangeList;
aNewMark.FillRangeListWithMarks( rRange.get(), false );
} else
{
ScRange aSimple;
GetSimpleArea(aSimple);
rRange = new ScRangeList(aSimple);
}
}
bool ScViewData::IsMultiMarked() const
{ // Test for "real" multi selection, calling MarkToSimple on a local copy, // and taking filtered in simple area marks into account.
bool ScViewData::SelectionForbidsPaste( ScDocument* pClipDoc )
{ if (!pClipDoc)
{ // Same as checkDestRanges() in sc/source/ui/view/cellsh.cxx but // different return details.
vcl::Window* pWin = GetActiveWin(); if (!pWin) // No window doesn't mean paste would be forbidden. returnfalse;
const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(pWin)); if (!pOwnClip) // Foreign content does not get repeatedly replicated. returnfalse;
pClipDoc = pOwnClip->GetDocument(); if (!pClipDoc) // No clipdoc doesn't mean paste would be forbidden. returnfalse;
}
// static bool ScViewData::SelectionFillDOOM( const ScRange& rRange )
{ // Assume that more than 23 full columns (23M cells) will not be // successful... Even with only 10 bytes per cell that would already be // 230MB, formula cells would be 100 bytes and more per cell. // rows * columns > 23m => rows > 23m / columns // to not overflow in case number of available columns or rows would be // arbitrarily increased. // We could refine this and take some actual cell size into account, // evaluate available memory and what not, but... const sal_Int32 kMax = 23 * 1024 * 1024; // current MAXROWCOUNT1 is 1024*1024=1048576 return (rRange.aEnd.Row() - rRange.aStart.Row() + 1) > (kMax / (rRange.aEnd.Col() - rRange.aStart.Col() + 1));
}
bool bWasThere = false; if (pEditView[eWhich])
{ // if the view is already there don't call anything that changes the cursor position if (bEditActive[eWhich])
{
bWasThere = true;
} else
{
lcl_LOKRemoveWindow(GetViewShell(), eWhich);
pEditView[eWhich]->setEditEngine(rNewEngine);
}
if (pEditView[eWhich]->GetWindow() != pWin)
{
lcl_LOKRemoveWindow(GetViewShell(), eWhich);
pEditView[eWhich]->SetWindow(pWin);
OSL_FAIL("EditView Window has changed");
}
} else
{
pEditView[eWhich].reset(new EditView(rNewEngine, pWin));
if (bLOKActive)
{ // We can broadcast the view-cursor message in print-twips for all views.
pEditView[eWhich]->SetBroadcastLOKViewCursor(bLOKPrintTwips);
pEditView[eWhich]->RegisterViewShell(pView);
}
}
// add windows from other views if (!bWasThere && bLOKActive)
{
ScTabViewShell* pThisViewShell = GetViewShell();
SCTAB nThisTabNo = GetTabNo(); auto lAddWindows =
[pThisViewShell, nThisTabNo, eWhich] (ScTabViewShell* pOtherViewShell)
{
ScViewData& rOtherViewData = pOtherViewShell->GetViewData();
SCTAB nOtherTabNo = rOtherViewData.GetTabNo(); if (nThisTabNo == nOtherTabNo)
pOtherViewShell->AddWindowToForeignEditView(pThisViewShell, eWhich);
};
// when right-aligned, leave space for the cursor // in vertical mode, editing is always right-aligned if ( GetEditAdjust() == SvxAdjust::Right || bAsianVertical )
{
aPixRect.AdjustRight(1 ); if (bLOKPrintTwips)
aPTwipsRect.AdjustRight(o3tl::convert(1, o3tl::Length::px, o3tl::Length::twip));
}
if (bLOKPrintTwips)
{ if (!pEditView[eWhich]->HasLOKSpecialPositioning())
pEditView[eWhich]->InitLOKSpecialPositioning(MapUnit::MapTwip, aPTwipsRect, Point()); else
pEditView[eWhich]->SetLOKSpecialOutputArea(aPTwipsRect);
}
if (bLOKActive && pEditView[eWhich]->HasLOKSpecialPositioning())
pEditView[eWhich]->SetLOKSpecialFlags(bLOKLayoutRTL ? LOKSpecialFlags::LayoutRTL : LOKSpecialFlags::NONE);
if (bLOKPrintTwips)
notifyCellCursorAt(GetViewShell(), nNewX, nNewY, aPTwipsRect);
ScModule* pScMod = ScModule::get(); if ( bActive && eWhich == GetActivePart() )
{ // keep the part that has the active edit view available after // switching sheets or reference input on a different part
eEditActivePart = eWhich;
// modify members nEditCol etc. only if also extending for needed area
nEditCol = nNewX;
nEditRow = nNewY; const ScMergeAttr* pMergeAttr = &pPattern->GetItem(ATTR_MERGE);
nEditEndCol = nEditCol; if (pMergeAttr->GetColMerge() > 1)
nEditEndCol += pMergeAttr->GetColMerge() - 1;
nEditEndRow = nEditRow; if (pMergeAttr->GetRowMerge() > 1)
nEditEndRow += pMergeAttr->GetRowMerge() - 1;
nEditStartCol = nEditCol;
// For growing use only the alignment value from the attribute, numbers // (existing or started) with default alignment extend to the right. bool bGrowCentered = ( eJust == SvxCellHorJustify::Center ); bool bGrowToLeft = ( eJust == SvxCellHorJustify::Right ); // visual left bool bLOKRTLInvert = (bLOKActive && bLayoutRTL); if ( bAsianVertical )
bGrowCentered = bGrowToLeft = false; // keep old behavior for asian mode
if (bBreak && !bAsianVertical)
{
nSizeXPix = aPixRect.GetWidth(); // papersize -> no horizontal scrolling if (bLOKPrintTwips)
nSizeXPTwips = aPTwipsRect.GetWidth();
} else
{
OSL_ENSURE(pView,"no View for EditView");
if ( bGrowCentered )
{ // growing into both directions until one edge is reached //! should be limited to whole cells in both directions
tools::Long nLeft = aPixRect.Left();
tools::Long nRight = nGridWidthPx - aPixRect.Right();
nSizeXPix = aPixRect.GetWidth() + 2 * std::min( nLeft, nRight ); if (bLOKPrintTwips)
{
tools::Long nLeftPTwips = aPTwipsRect.Left();
tools::Long nRightPTwips = nGridWidthTwips - aPTwipsRect.Right();
nSizeXPTwips = aPTwipsRect.GetWidth() + 2 * std::min(nLeftPTwips, nRightPTwips);
}
} elseif ( (bGrowToLeft && !bLOKRTLInvert) || (!bGrowToLeft && bLOKRTLInvert) )
{
nSizeXPix = aPixRect.Right(); // space that's available in the window when growing to the left if (bLOKPrintTwips)
nSizeXPTwips = aPTwipsRect.Right();
} else
{
nSizeXPix = nGridWidthPx - aPixRect.Left(); if (bLOKPrintTwips)
nSizeXPTwips = nGridWidthTwips - aPTwipsRect.Left();
}
if ( nSizeXPix <= 0 )
{
nSizeXPix = aPixRect.GetWidth(); // editing outside to the right of the window -> keep cell width if (bLOKPrintTwips)
nSizeXPTwips = aPTwipsRect.GetWidth();
}
}
OSL_ENSURE(pView,"no View for EditView");
tools::Long nSizeYPix = nGridHeightPx - aPixRect.Top();
tools::Long nSizeYPTwips = bLOKPrintTwips ? (nGridHeightTwips - aPTwipsRect.Top()) : 0;
if ( nSizeYPix <= 0 )
{
nSizeYPix = aPixRect.GetHeight(); // editing outside below the window -> keep cell height if (bLOKPrintTwips)
nSizeYPTwips = aPTwipsRect.GetHeight();
}
Size aPaperSize = pView->GetActiveWin()->PixelToLogic( Size( nSizeXPix, nSizeYPix ), GetLogicMode() );
Size aPaperSizePTwips(nSizeXPTwips, nSizeYPTwips); // In the LOK case the following code can make the cell background and visible area larger // than needed which makes selecting the adjacent right cell impossible in some cases. if (bBreak && !bAsianVertical && pScMod->GetInputOptions().GetTextWysiwyg() && !bLOKActive)
{ // if text is formatted for printer, use the exact same paper width // (and same line breaks) as for output.
tools::Long nDiff = aVis.Right() - aVis.Left();
tools::Long nDiffPTwips = bLOKPrintTwips ? (aVisPTwips.Right() - aVisPTwips.Left()) : 0; if ( GetEditAdjust() == SvxAdjust::Right )
{
aVis.SetRight( aPaper.Width() - 1 ); if (bLOKPrintTwips)
aVisPTwips.SetRight( aPaperSizePTwips.Width() - 1 );
bMoveArea = !bLayoutRTL;
} elseif ( GetEditAdjust() == SvxAdjust::Center )
{
aVis.SetRight( ( aPaper.Width() - 1 + nDiff ) / 2 ); if (bLOKPrintTwips)
aVisPTwips.SetRight( ( aPaperSizePTwips.Width() - 1 + nDiffPTwips ) / 2 );
bMoveArea = true; // always
} else
{
aVis.SetRight( nDiff ); if (bLOKPrintTwips)
aVisPTwips.SetRight(nDiffPTwips);
bMoveArea = bLayoutRTL;
}
aVis.SetLeft( aVis.Right() - nDiff ); if (bLOKPrintTwips)
aVisPTwips.SetLeft(aVisPTwips.Right() - nDiffPTwips); // #i49561# Important note: // The set offset of the visible area of the EditView for centered and // right alignment in horizontal layout is consider by instances of // class <ScEditObjectViewForwarder> in its methods <LogicToPixel(..)> // and <PixelToLogic(..)>. This is needed for the correct visibility // of paragraphs in edit mode at the accessibility API.
pEditView[eWhich]->SetVisArea(aVis); if (bLOKPrintTwips)
pEditView[eWhich]->SetLOKSpecialVisArea(aVisPTwips); // UpdateMode has been disabled in ScInputHandler::StartTable // must be enabled before EditGrowY (GetTextHeight)
rNewEngine.SetUpdateLayout( true );
if (comphelper::LibreOfficeKit::isActive())
{ // now only needed when not CEOO (CellEditOnOverlay) // needed? // needed, if position changed
pEditView[eWhich]->Invalidate();
}
}
if (nStatus & EditStatusFlags::CURSOROUT)
{
ScSplitPos eWhich = GetActivePart(); if (pEditView[eWhich])
pEditView[eWhich]->ShowCursor(false);
}
}
}
void ScViewData::EditGrowX()
{ // It is insane to call EditGrowX while the output area is already growing. // That could occur because of the call to SetDefaultItem later. // We end up with wrong start/end edit columns and the changes // to the output area performed by the inner call to this method are // useless since they are discarded by the outer call. if (bGrowing) return;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.