diff options
Diffstat (limited to 'sc/source/ui/view/viewfun2.cxx')
-rw-r--r-- | sc/source/ui/view/viewfun2.cxx | 3093 |
1 files changed, 3093 insertions, 0 deletions
diff --git a/sc/source/ui/view/viewfun2.cxx b/sc/source/ui/view/viewfun2.cxx new file mode 100644 index 000000000000..17bf069f274d --- /dev/null +++ b/sc/source/ui/view/viewfun2.cxx @@ -0,0 +1,3093 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// INCLUDE --------------------------------------------------------------- + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> + +#include <sfx2/app.hxx> +#define _SVSTDARR_STRINGS +#include <editeng/boxitem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/scripttypeitem.hxx> +#include <svl/srchitem.hxx> +#include <sfx2/linkmgr.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/objitem.hxx> +#include <sfx2/viewfrm.hxx> +#include <svl/stritem.hxx> +#include <svl/zforlist.hxx> +#include <svl/svstdarr.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/sound.hxx> +#include <vcl/waitobj.hxx> + +#include <basic/sbstar.hxx> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/script/XLibraryContainer.hpp> + +#include "viewfunc.hxx" + +#include "sc.hrc" +#include "globstr.hrc" + +#include "attrib.hxx" +#include "autoform.hxx" +#include "cell.hxx" // EnterAutoSum +#include "cellmergeoption.hxx" +#include "compiler.hxx" +#include "docfunc.hxx" +#include "docpool.hxx" +#include "docsh.hxx" +#include "global.hxx" +#include "patattr.hxx" +#include "printfun.hxx" +#include "rangenam.hxx" +#include "rangeutl.hxx" +#include "refundo.hxx" +#include "tablink.hxx" +#include "tabvwsh.hxx" +#include "uiitems.hxx" +#include "undoblk.hxx" +#include "undocell.hxx" +#include "undotab.hxx" +#include "sizedev.hxx" +#include "editable.hxx" +#include "scmod.hxx" +#include "inputhdl.hxx" +#include "inputwin.hxx" +#include "funcdesc.hxx" +#include "docuno.hxx" +#include "charthelper.hxx" +#include "tabbgcolor.hxx" + +#include <basic/sbstar.hxx> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/script/XLibraryContainer.hpp> + +#include <boost/scoped_ptr.hpp> +#include <vector> +#include <memory> + +using namespace com::sun::star; +using ::rtl::OUStringBuffer; +using ::rtl::OUString; +using ::editeng::SvxBorderLine; + +using ::std::vector; +using ::std::auto_ptr; + +// helper func defined in docfunc.cxx +void VBA_DeleteModule( ScDocShell& rDocSh, String& sModuleName ); + +// STATIC DATA --------------------------------------------------------------- + + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::AdjustBlockHeight( sal_Bool bPaint, ScMarkData* pMarkData ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + if (!pMarkData) + pMarkData = &GetViewData()->GetMarkData(); + + ScDocument* pDoc = pDocSh->GetDocument(); + SCCOLROW* pRanges = new SCCOLROW[MAXCOLROWCOUNT]; + SCCOLROW nRangeCnt = pMarkData->GetMarkRowRanges( pRanges ); + if (nRangeCnt == 0) + { + pRanges[0] = pRanges[1] = GetViewData()->GetCurY(); + nRangeCnt = 1; + } + + double nPPTX = GetViewData()->GetPPTX(); + double nPPTY = GetViewData()->GetPPTY(); + Fraction aZoomX = GetViewData()->GetZoomX(); + Fraction aZoomY = GetViewData()->GetZoomY(); + + ScSizeDeviceProvider aProv(pDocSh); + if (aProv.IsPrinter()) + { + nPPTX = aProv.GetPPTX(); + nPPTY = aProv.GetPPTY(); + aZoomX = aZoomY = Fraction( 1, 1 ); + } + + sal_Bool bAnyChanged = false; + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + { + if (pMarkData->GetTableSelect(nTab)) + { + SCCOLROW* pOneRange = pRanges; + sal_Bool bChanged = false; + SCROW nPaintY = 0; + for (SCROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++) + { + SCROW nStartNo = *(pOneRange++); + SCROW nEndNo = *(pOneRange++); + if (pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, 0, aProv.GetDevice(), + nPPTX, nPPTY, aZoomX, aZoomY, false )) + { + if (!bChanged) + nPaintY = nStartNo; + bAnyChanged = bChanged = sal_True; + } + } + if ( bPaint && bChanged ) + pDocSh->PostPaint( 0, nPaintY, nTab, MAXCOL, MAXROW, nTab, + PAINT_GRID | PAINT_LEFT ); + } + } + delete[] pRanges; + + if ( bPaint && bAnyChanged ) + pDocSh->UpdateOle(GetViewData()); + + return bAnyChanged; +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::AdjustRowHeight( SCROW nStartRow, SCROW nEndRow, sal_Bool bPaint ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetViewData()->GetTabNo(); + double nPPTX = GetViewData()->GetPPTX(); + double nPPTY = GetViewData()->GetPPTY(); + Fraction aZoomX = GetViewData()->GetZoomX(); + Fraction aZoomY = GetViewData()->GetZoomY(); + sal_uInt16 nOldPixel = 0; + if (nStartRow == nEndRow) + nOldPixel = (sal_uInt16) (pDoc->GetRowHeight(nStartRow,nTab) * nPPTY); + + ScSizeDeviceProvider aProv(pDocSh); + if (aProv.IsPrinter()) + { + nPPTX = aProv.GetPPTX(); + nPPTY = aProv.GetPPTY(); + aZoomX = aZoomY = Fraction( 1, 1 ); + } + sal_Bool bChanged = pDoc->SetOptimalHeight( nStartRow, nEndRow, nTab, 0, aProv.GetDevice(), + nPPTX, nPPTY, aZoomX, aZoomY, false ); + + if (bChanged && ( nStartRow == nEndRow )) + { + sal_uInt16 nNewPixel = (sal_uInt16) (pDoc->GetRowHeight(nStartRow,nTab) * nPPTY); + if ( nNewPixel == nOldPixel ) + bChanged = false; + } + + if ( bPaint && bChanged ) + pDocSh->PostPaint( 0, nStartRow, nTab, MAXCOL, MAXROW, nTab, + PAINT_GRID | PAINT_LEFT ); + + return bChanged; +} + + +//---------------------------------------------------------------------------- + +enum ScAutoSum +{ + ScAutoSumNone = 0, + ScAutoSumData, + ScAutoSumSum +}; + + +ScAutoSum lcl_IsAutoSumData( ScDocument* pDoc, SCCOL nCol, SCROW nRow, + SCTAB nTab, ScDirection eDir, SCCOLROW& nExtend ) +{ + ScBaseCell* pCell; + pDoc->GetCell( nCol, nRow, nTab, pCell ); + if ( pCell && pCell->HasValueData() ) + { + if ( pCell->GetCellType() == CELLTYPE_FORMULA ) + { + ScTokenArray* pCode = ((ScFormulaCell*)pCell)->GetCode(); + if ( pCode && pCode->GetOuterFuncOpCode() == ocSum ) + { + if ( pCode->GetAdjacentExtendOfOuterFuncRefs( nExtend, + ScAddress( nCol, nRow, nTab ), eDir ) ) + return ScAutoSumSum; + } + } + return ScAutoSumData; + } + return ScAutoSumNone; +} + + +//---------------------------------------------------------------------------- + +#define SC_AUTOSUM_MAXCOUNT 20 + +ScAutoSum lcl_SeekAutoSumData( ScDocument* pDoc, SCCOL& nCol, SCROW& nRow, + SCTAB nTab, ScDirection eDir, SCCOLROW& nExtend ) +{ + sal_uInt16 nCount = 0; + while (nCount < SC_AUTOSUM_MAXCOUNT) + { + if ( eDir == DIR_TOP ) + { + if (nRow > 0) + --nRow; + else + return ScAutoSumNone; + } + else + { + if (nCol > 0) + --nCol; + else + return ScAutoSumNone; + } + ScAutoSum eSum; + if ( (eSum = lcl_IsAutoSumData( + pDoc, nCol, nRow, nTab, eDir, nExtend )) != ScAutoSumNone ) + return eSum; + ++nCount; + } + return ScAutoSumNone; +} + +#undef SC_AUTOSUM_MAXCOUNT + +//---------------------------------------------------------------------------- + +bool lcl_FindNextSumEntryInColumn( ScDocument* pDoc, SCCOL nCol, SCROW& nRow, + SCTAB nTab, SCCOLROW& nExtend, SCROW nMinRow ) +{ + const SCROW nTmp = nRow; + ScAutoSum eSkip = ScAutoSumNone; + while ( ( eSkip = lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_TOP, nExtend ) ) == ScAutoSumData && + nRow > nMinRow ) + { + --nRow; + } + if ( eSkip == ScAutoSumSum && nRow < nTmp ) + { + return true; + } + return false; +} + +//---------------------------------------------------------------------------- + +bool lcl_FindNextSumEntryInRow( ScDocument* pDoc, SCCOL& nCol, SCROW nRow, + SCTAB nTab, SCCOLROW& nExtend, SCROW nMinCol ) +{ + const SCCOL nTmp = nCol; + ScAutoSum eSkip = ScAutoSumNone; + while ( ( eSkip = lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_LEFT, nExtend ) ) == ScAutoSumData && + nCol > nMinCol ) + { + --nCol; + } + if ( eSkip == ScAutoSumSum && nCol < nTmp ) + { + return true; + } + return false; +} + +//---------------------------------------------------------------------------- + +bool lcl_GetAutoSumForColumnRange( ScDocument* pDoc, ScRangeList& rRangeList, const ScRange& rRange ) +{ + const ScAddress aStart = rRange.aStart; + const ScAddress aEnd = rRange.aEnd; + if ( aStart.Col() != aEnd.Col() ) + { + return false; + } + + const SCTAB nTab = aEnd.Tab(); + const SCCOL nCol = aEnd.Col(); + SCROW nEndRow = aEnd.Row(); + SCROW nStartRow = nEndRow; + SCCOLROW nExtend = 0; + const ScAutoSum eSum = lcl_IsAutoSumData( pDoc, nCol, nEndRow, nTab, DIR_TOP, nExtend /*out*/ ); + + if ( eSum == ScAutoSumSum ) + { + bool bContinue = false; + do + { + rRangeList.Append( ScRange( nCol, nStartRow, nTab, nCol, nEndRow, nTab ) ); + nEndRow = static_cast< SCROW >( nExtend ); + if ( ( bContinue = lcl_FindNextSumEntryInColumn( pDoc, nCol, nEndRow /*inout*/, nTab, nExtend /*out*/, aStart.Row() ) ) == true ) + { + nStartRow = nEndRow; + } + } while ( bContinue ); + } + else + { + while ( nStartRow > aStart.Row() && + lcl_IsAutoSumData( pDoc, nCol, nStartRow-1, nTab, DIR_TOP, nExtend /*out*/ ) != ScAutoSumSum ) + { + --nStartRow; + } + rRangeList.Append( ScRange( nCol, nStartRow, nTab, nCol, nEndRow, nTab ) ); + } + + return true; +} + +//---------------------------------------------------------------------------- + +bool lcl_GetAutoSumForRowRange( ScDocument* pDoc, ScRangeList& rRangeList, const ScRange& rRange ) +{ + const ScAddress aStart = rRange.aStart; + const ScAddress aEnd = rRange.aEnd; + if ( aStart.Row() != aEnd.Row() ) + { + return false; + } + + const SCTAB nTab = aEnd.Tab(); + const SCROW nRow = aEnd.Row(); + SCCOL nEndCol = aEnd.Col(); + SCCOL nStartCol = nEndCol; + SCCOLROW nExtend = 0; + const ScAutoSum eSum = lcl_IsAutoSumData( pDoc, nEndCol, nRow, nTab, DIR_LEFT, nExtend /*out*/ ); + + if ( eSum == ScAutoSumSum ) + { + bool bContinue = false; + do + { + rRangeList.Append( ScRange( nStartCol, nRow, nTab, nEndCol, nRow, nTab ) ); + nEndCol = static_cast< SCCOL >( nExtend ); + if ( ( bContinue = lcl_FindNextSumEntryInRow( pDoc, nEndCol /*inout*/, nRow, nTab, nExtend /*out*/, aStart.Col() ) ) == true ) + { + nStartCol = nEndCol; + } + } while ( bContinue ); + } + else + { + while ( nStartCol > aStart.Col() && + lcl_IsAutoSumData( pDoc, nStartCol-1, nRow, nTab, DIR_LEFT, nExtend /*out*/ ) != ScAutoSumSum ) + { + --nStartCol; + } + rRangeList.Append( ScRange( nStartCol, nRow, nTab, nEndCol, nRow, nTab ) ); + } + + return true; +} + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::GetAutoSumArea( ScRangeList& rRangeList ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + SCTAB nTab = GetViewData()->GetTabNo(); + + SCCOL nCol = GetViewData()->GetCurX(); + SCROW nRow = GetViewData()->GetCurY(); + + SCCOL nStartCol = nCol; + SCROW nStartRow = nRow; + SCCOL nEndCol = nCol; + SCROW nEndRow = nRow; + SCCOL nSeekCol = nCol; + SCROW nSeekRow = nRow; + SCCOLROW nExtend; // will become valid via reference for ScAutoSumSum + + sal_Bool bCol = false; + sal_Bool bRow = false; + + ScAutoSum eSum; + if ( nRow != 0 + && ((eSum = lcl_IsAutoSumData( pDoc, nCol, nRow-1, nTab, + DIR_TOP, nExtend /*out*/ )) == ScAutoSumData ) + && ((eSum = lcl_IsAutoSumData( pDoc, nCol, nRow-1, nTab, + DIR_LEFT, nExtend /*out*/ )) == ScAutoSumData ) + ) + { + bRow = sal_True; + nSeekRow = nRow - 1; + } + else if ( nCol != 0 && (eSum = lcl_IsAutoSumData( pDoc, nCol-1, nRow, nTab, + DIR_LEFT, nExtend /*out*/ )) == ScAutoSumData ) + { + bCol = sal_True; + nSeekCol = nCol - 1; + } + else if ( (eSum = lcl_SeekAutoSumData( pDoc, nCol, nSeekRow, nTab, DIR_TOP, nExtend /*out*/ )) != ScAutoSumNone ) + bRow = sal_True; + else if (( eSum = lcl_SeekAutoSumData( pDoc, nSeekCol, nRow, nTab, DIR_LEFT, nExtend /*out*/ )) != ScAutoSumNone ) + bCol = sal_True; + + if ( bCol || bRow ) + { + if ( bRow ) + { + nStartRow = nSeekRow; // nSeekRow might be adjusted via reference + if ( eSum == ScAutoSumSum ) + nEndRow = nStartRow; // only sum sums + else + nEndRow = nRow - 1; // maybe extend data area at bottom + } + else + { + nStartCol = nSeekCol; // nSeekCol might be adjusted vie reference + if ( eSum == ScAutoSumSum ) + nEndCol = nStartCol; // only sum sums + else + nEndCol = nCol - 1; // maybe extend data area to the right + } + sal_Bool bContinue = false; + do + { + if ( eSum == ScAutoSumData ) + { + if ( bRow ) + { + while ( nStartRow != 0 && lcl_IsAutoSumData( pDoc, nCol, + nStartRow-1, nTab, DIR_TOP, nExtend /*out*/ ) == eSum ) + --nStartRow; + } + else + { + while ( nStartCol != 0 && lcl_IsAutoSumData( pDoc, nStartCol-1, + nRow, nTab, DIR_LEFT, nExtend /*out*/ ) == eSum ) + --nStartCol; + } + } + rRangeList.Append( + ScRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ) ); + if ( eSum == ScAutoSumSum ) + { + if ( bRow ) + { + nEndRow = static_cast< SCROW >( nExtend ); + if ( ( bContinue = lcl_FindNextSumEntryInColumn( pDoc, nCol, nEndRow /*inout*/, nTab, nExtend /*out*/, 0 ) ) == true ) + { + nStartRow = nEndRow; + } + } + else + { + nEndCol = static_cast< SCCOL >( nExtend ); + if ( ( bContinue = lcl_FindNextSumEntryInRow( pDoc, nEndCol /*inout*/, nRow, nTab, nExtend /*out*/, 0 ) ) == true ) + { + nStartCol = nEndCol; + } + } + } + } while ( bContinue ); + return sal_True; + } + return false; +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::EnterAutoSum(const ScRangeList& rRangeList, bool bSubTotal, const ScAddress& rAddr) +{ + String aFormula = GetAutoSumFormula( rRangeList, bSubTotal, rAddr ); + EnterBlock( aFormula, NULL ); +} + +//---------------------------------------------------------------------------- + +bool ScViewFunc::AutoSum( const ScRange& rRange, bool bSubTotal, bool bSetCursor, bool bContinue ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + const SCTAB nTab = rRange.aStart.Tab(); + SCCOL nStartCol = rRange.aStart.Col(); + SCROW nStartRow = rRange.aStart.Row(); + const SCCOL nEndCol = rRange.aEnd.Col(); + const SCROW nEndRow = rRange.aEnd.Row(); + SCCOLROW nExtend = 0; // out parameter for lcl_IsAutoSumData + + // ignore rows at the top of the given range which don't contain autosum data + bool bRowData = false; + for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow ) + { + for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol ) + { + if ( lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_TOP, nExtend ) != ScAutoSumNone ) + { + bRowData = true; + break; + } + } + if ( bRowData ) + { + nStartRow = nRow; + break; + } + } + if ( !bRowData ) + { + return false; + } + + // ignore columns at the left of the given range which don't contain autosum data + bool bColData = false; + for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol ) + { + for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow ) + { + if ( lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_LEFT, nExtend ) != ScAutoSumNone ) + { + bColData = true; + break; + } + } + if ( bColData ) + { + nStartCol = nCol; + break; + } + } + if ( !bColData ) + { + return false; + } + + const bool bEndRowEmpty = pDoc->IsBlockEmpty( nTab, nStartCol, nEndRow, nEndCol, nEndRow ); + const bool bEndColEmpty = pDoc->IsBlockEmpty( nTab, nEndCol, nStartRow, nEndCol, nEndRow ); + bool bRow = ( ( nStartRow != nEndRow ) && ( bEndRowEmpty || ( !bEndRowEmpty && !bEndColEmpty ) ) ); + bool bCol = ( ( nStartCol != nEndCol ) && ( bEndColEmpty || nStartRow == nEndRow ) ); + + // find an empty row for entering the result + SCROW nInsRow = nEndRow; + if ( bRow && !bEndRowEmpty ) + { + if ( nInsRow < MAXROW ) + { + ++nInsRow; + while ( !pDoc->IsBlockEmpty( nTab, nStartCol, nInsRow, nEndCol, nInsRow ) ) + { + if ( nInsRow < MAXROW ) + { + ++nInsRow; + } + else + { + bRow = false; + break; + } + } + } + else + { + bRow = false; + } + } + + // find an empty column for entering the result + SCCOL nInsCol = nEndCol; + if ( bCol && !bEndColEmpty ) + { + if ( nInsCol < MAXCOL ) + { + ++nInsCol; + while ( !pDoc->IsBlockEmpty( nTab, nInsCol, nStartRow, nInsCol, nEndRow ) ) + { + if ( nInsCol < MAXCOL ) + { + ++nInsCol; + } + else + { + bCol = false; + break; + } + } + } + else + { + bCol = false; + } + } + + if ( !bRow && !bCol ) + { + return false; + } + + SCCOL nMarkEndCol = nEndCol; + SCROW nMarkEndRow = nEndRow; + + if ( bRow ) + { + // calculate the row sums for all columns of the given range + + SCROW nSumEndRow = nEndRow; + + if ( bEndRowEmpty ) + { + // the last row of the given range is empty; + // don't take into account for calculating the autosum + --nSumEndRow; + } + else + { + // increase mark range + ++nMarkEndRow; + } + + for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol ) + { + if ( !pDoc->IsBlockEmpty( nTab, nCol, nStartRow, nCol, nSumEndRow ) ) + { + ScRangeList aRangeList; + const ScRange aRange( nCol, nStartRow, nTab, nCol, nSumEndRow, nTab ); + if ( lcl_GetAutoSumForColumnRange( pDoc, aRangeList, aRange ) ) + { + const String aFormula = GetAutoSumFormula( + aRangeList, bSubTotal, ScAddress(nCol, nInsRow, nTab)); + EnterData( nCol, nInsRow, nTab, aFormula ); + } + } + } + } + + if ( bCol ) + { + // calculate the column sums for all rows of the given range + + SCCOL nSumEndCol = nEndCol; + + if ( bEndColEmpty ) + { + // the last column of the given range is empty; + // don't take into account for calculating the autosum + --nSumEndCol; + } + else + { + // increase mark range + ++nMarkEndCol; + } + + for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow ) + { + if ( !pDoc->IsBlockEmpty( nTab, nStartCol, nRow, nSumEndCol, nRow ) ) + { + ScRangeList aRangeList; + const ScRange aRange( nStartCol, nRow, nTab, nSumEndCol, nRow, nTab ); + if ( lcl_GetAutoSumForRowRange( pDoc, aRangeList, aRange ) ) + { + const String aFormula = GetAutoSumFormula( aRangeList, bSubTotal, ScAddress(nInsCol, nRow, nTab) ); + EnterData( nInsCol, nRow, nTab, aFormula ); + } + } + } + } + + // set new mark range and cursor position + const ScRange aMarkRange( nStartCol, nStartRow, nTab, nMarkEndCol, nMarkEndRow, nTab ); + MarkRange( aMarkRange, false, bContinue ); + if ( bSetCursor ) + { + SetCursor( nMarkEndCol, nMarkEndRow ); + } + + return true; +} + +//---------------------------------------------------------------------------- + +String ScViewFunc::GetAutoSumFormula( const ScRangeList& rRangeList, bool bSubTotal, const ScAddress& rAddr ) +{ + ScViewData* pViewData = GetViewData(); + ScDocument* pDoc = pViewData->GetDocument(); + ::boost::scoped_ptr<ScTokenArray> pArray(new ScTokenArray); + + pArray->AddOpCode(bSubTotal ? ocSubTotal : ocSum); + pArray->AddOpCode(ocOpen); + + if (bSubTotal) + { + pArray->AddDouble(9); + pArray->AddOpCode(ocSep); + } + + if(!rRangeList.empty()) + { + ScRangeList aRangeList = rRangeList; + const ScRange* pFirst = aRangeList.front(); + size_t ListSize = aRangeList.size(); + for ( size_t i = 0; i < ListSize; ++i ) + { + const ScRange* p = aRangeList[i]; + if (p != pFirst) + pArray->AddOpCode(ocSep); + ScComplexRefData aRef; + aRef.InitRangeRel(*p, rAddr); + pArray->AddDoubleReference(aRef); + } + } + + pArray->AddOpCode(ocClose); + + ScCompiler aComp(pDoc, rAddr, *pArray); + aComp.SetGrammar(pDoc->GetGrammar()); + OUStringBuffer aBuf; + aComp.CreateStringFromTokenArray(aBuf); + OUString aFormula = aBuf.makeStringAndClear(); + aBuf.append(sal_Unicode('=')); + aBuf.append(aFormula); + return aBuf.makeStringAndClear(); +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::EnterBlock( const String& rString, const EditTextObject* pData ) +{ + // test for multi selection + + SCCOL nCol = GetViewData()->GetCurX(); + SCROW nRow = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + if ( rMark.IsMultiMarked() ) + { + rMark.MarkToSimple(); + if ( rMark.IsMultiMarked() ) + { // "Insert into multi selection not possible" + ErrorMessage(STR_MSSG_PASTEFROMCLIP_0); + + // insert into single cell + if ( pData ) + EnterData( nCol, nRow, nTab, pData ); + else + EnterData( nCol, nRow, nTab, rString ); + return; + } + } + + ScDocument* pDoc = GetViewData()->GetDocument(); + String aNewStr = rString; + if ( pData ) + { + const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab ); + ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() ); + aEngine.SetText(*pData); + + ScEditAttrTester aTester( &aEngine ); + if (!aTester.NeedsObject()) + { + aNewStr = aEngine.GetText(); + pData = NULL; + } + } + + // Insert via PasteFromClip + + WaitObject aWait( GetFrameWin() ); + + ScAddress aPos( nCol, nRow, nTab ); + + ScDocument* pInsDoc = new ScDocument( SCDOCMODE_CLIP ); + pInsDoc->ResetClip( pDoc, nTab ); + + if (aNewStr.GetChar(0) == '=') // Formula ? + { + // SetString not possible, because in Clipboard-Documents nothing will be compiled! + ScFormulaCell* pFCell = new ScFormulaCell( pDoc, aPos, aNewStr ); + pInsDoc->PutCell( nCol, nRow, nTab, pFCell ); + } + else if ( pData ) + pInsDoc->PutCell( nCol, nRow, nTab, new ScEditCell( pData, pDoc, NULL ) ); + else + pInsDoc->SetString( nCol, nRow, nTab, aNewStr ); + + pInsDoc->SetClipArea( ScRange(aPos) ); + // insert Block, with Undo etc. + if ( PasteFromClip( IDF_CONTENTS, pInsDoc, PASTE_NOFUNC, false, false, + false, INS_NONE, IDF_ATTRIB ) ) + { + const SfxUInt32Item* pItem = (SfxUInt32Item*) pInsDoc->GetAttr( + nCol, nRow, nTab, ATTR_VALUE_FORMAT ); + if ( pItem ) + { // set number format if incompatible + // MarkData was already MarkToSimple'ed in PasteFromClip + ScRange aRange; + rMark.GetMarkArea( aRange ); + ScPatternAttr* pPattern = new ScPatternAttr( pDoc->GetPool() ); + pPattern->GetItemSet().Put( *pItem ); + short nNewType = pDoc->GetFormatTable()->GetType( pItem->GetValue() ); + pDoc->ApplyPatternIfNumberformatIncompatible( aRange, rMark, + *pPattern, nNewType ); + delete pPattern; + } + } + + delete pInsDoc; +} + + +//---------------------------------------------------------------------------- +// manual page break + +void ScViewFunc::InsertPageBreak( sal_Bool bColumn, sal_Bool bRecord, const ScAddress* pPos, + sal_Bool bSetModified ) +{ + SCTAB nTab = GetViewData()->GetTabNo(); + ScAddress aCursor; + if (pPos) + aCursor = *pPos; + else + aCursor = ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(), nTab ); + + sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc(). + InsertPageBreak( bColumn, aCursor, bRecord, bSetModified, false ); + + if ( bSuccess && bSetModified ) + UpdatePageBreakData( true ); // for PageBreak-Mode +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::DeletePageBreak( sal_Bool bColumn, sal_Bool bRecord, const ScAddress* pPos, + sal_Bool bSetModified ) +{ + SCTAB nTab = GetViewData()->GetTabNo(); + ScAddress aCursor; + if (pPos) + aCursor = *pPos; + else + aCursor = ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(), nTab ); + + sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc(). + RemovePageBreak( bColumn, aCursor, bRecord, bSetModified, false ); + + if ( bSuccess && bSetModified ) + UpdatePageBreakData( true ); // for PageBreak-Mode +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::RemoveManualBreaks() +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetViewData()->GetTabNo(); + sal_Bool bUndo(pDoc->IsUndoEnabled()); + + if (bUndo) + { + ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True ); + pDoc->CopyToDocument( 0,0,nTab, MAXCOL,MAXROW,nTab, IDF_NONE, false, pUndoDoc ); + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoRemoveBreaks( pDocSh, nTab, pUndoDoc ) ); + } + + pDoc->RemoveManualBreaks(nTab); + pDoc->UpdatePageBreaks(nTab); + + UpdatePageBreakData( sal_True ); + pDocSh->SetDocumentModified(); + pDocSh->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID ); +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::SetPrintZoom(sal_uInt16 nScale, sal_uInt16 nPages) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + SCTAB nTab = GetViewData()->GetTabNo(); + pDocSh->SetPrintZoom( nTab, nScale, nPages ); +} + +void ScViewFunc::AdjustPrintZoom() +{ + ScRange aRange; + if ( GetViewData()->GetSimpleArea( aRange ) != SC_MARK_SIMPLE ) + GetViewData()->GetMarkData().GetMultiMarkArea( aRange ); + GetViewData()->GetDocShell()->AdjustPrintZoom( aRange ); +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::SetPrintRanges( sal_Bool bEntireSheet, const String* pPrint, + const String* pRepCol, const String* pRepRow, + sal_Bool bAddPrint ) +{ + // on all selected tables + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTab; + sal_Bool bUndo (pDoc->IsUndoEnabled()); + + ScPrintRangeSaver* pOldRanges = pDoc->CreatePrintRangeSaver(); + + ScAddress::Details aDetails(pDoc->GetAddressConvention(), 0, 0); + + for (nTab=0; nTab<nTabCount; nTab++) + if (rMark.GetTableSelect(nTab)) + { + ScRange aRange( 0,0,nTab ); + + // print ranges + + if( !bAddPrint ) + pDoc->ClearPrintRanges( nTab ); + + if( bEntireSheet ) + { + pDoc->SetPrintEntireSheet( nTab ); + } + else if ( pPrint ) + { + if ( pPrint->Len() ) + { + const sal_Unicode sep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0); + sal_uInt16 nTCount = pPrint->GetTokenCount(sep); + for (sal_uInt16 i=0; i<nTCount; i++) + { + String aToken = pPrint->GetToken(i, sep); + if ( aRange.ParseAny( aToken, pDoc, aDetails ) & SCA_VALID ) + pDoc->AddPrintRange( nTab, aRange ); + } + } + } + else // NULL = use selection (print range is always set), use empty string to delete all ranges + { + if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE ) + { + pDoc->AddPrintRange( nTab, aRange ); + } + else if ( rMark.IsMultiMarked() ) + { + rMark.MarkToMulti(); + ScRangeListRef pList( new ScRangeList ); + rMark.FillRangeListWithMarks( pList, false ); + for (size_t i = 0, n = pList->size(); i < n; ++i) + { + ScRange* pR = (*pList)[i]; + pDoc->AddPrintRange(nTab, *pR); + } + } + } + + // repeat columns + + if ( pRepCol ) + { + if ( !pRepCol->Len() ) + pDoc->SetRepeatColRange( nTab, NULL ); + else + if ( aRange.ParseAny( *pRepCol, pDoc, aDetails ) & SCA_VALID ) + pDoc->SetRepeatColRange( nTab, &aRange ); + } + + // repeat rows + + if ( pRepRow ) + { + if ( !pRepRow->Len() ) + pDoc->SetRepeatRowRange( nTab, NULL ); + else + if ( aRange.ParseAny( *pRepRow, pDoc, aDetails ) & SCA_VALID ) + pDoc->SetRepeatRowRange( nTab, &aRange ); + } + } + + // undo (for all tables) + if (bUndo) + { + SCTAB nCurTab = GetViewData()->GetTabNo(); + ScPrintRangeSaver* pNewRanges = pDoc->CreatePrintRangeSaver(); + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoPrintRange( pDocSh, nCurTab, pOldRanges, pNewRanges ) ); + } + + // update page breaks + + for (nTab=0; nTab<nTabCount; nTab++) + if (rMark.GetTableSelect(nTab)) + ScPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab ).UpdatePages(); + + SfxBindings& rBindings = GetViewData()->GetBindings(); + rBindings.Invalidate( SID_DELETE_PRINTAREA ); + + pDocSh->SetDocumentModified(); +} + +//---------------------------------------------------------------------------- +// Merge cells + +sal_Bool ScViewFunc::TestMergeCells() // pre-test (for menu) +{ + // simple test: sal_True if there's a selection but no multi selection and not filtered + + const ScMarkData& rMark = GetViewData()->GetMarkData(); + if ( rMark.IsMarked() || rMark.IsMultiMarked() ) + { + ScRange aDummy; + return GetViewData()->GetSimpleArea( aDummy) == SC_MARK_SIMPLE; + } + else + return false; +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::MergeCells( sal_Bool bApi, sal_Bool& rDoContents, sal_Bool bRecord, sal_Bool bCenter ) +{ + // Editable- and Being-Nested- test must be at the beginning (in DocFunc too), + // so that the Contents-QueryBox won't appear + ScEditableTester aTester( this ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + return false; + } + + ScMarkData& rMark = GetViewData()->GetMarkData(); + rMark.MarkToSimple(); + if (!rMark.IsMarked()) + { + ErrorMessage(STR_NOMULTISELECT); + return false; + } + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + + ScRange aMarkRange; + rMark.GetMarkArea( aMarkRange ); + SCCOL nStartCol = aMarkRange.aStart.Col(); + SCROW nStartRow = aMarkRange.aStart.Row(); + SCTAB nStartTab = aMarkRange.aStart.Tab(); + SCCOL nEndCol = aMarkRange.aEnd.Col(); + SCROW nEndRow = aMarkRange.aEnd.Row(); + SCTAB nEndTab = aMarkRange.aEnd.Tab(); + if ( nStartCol == nEndCol && nStartRow == nEndRow ) + { + // nothing to do + return true; + } + + if ( pDoc->HasAttrib( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab, + HASATTR_MERGED | HASATTR_OVERLAPPED ) ) + { // "Don't nest merging !" + ErrorMessage(STR_MSSG_MERGECELLS_0); + return false; + } + + // Check for the contents of all selected tables. + bool bAskDialog = false; + SCTAB nTabCount = pDoc->GetTableCount(); + ScCellMergeOption aMergeOption(nStartCol, nStartRow, nEndCol, nEndRow, bCenter); + for (SCTAB i = 0; i < nTabCount; ++i) + { + if (!rMark.GetTableSelect(i)) + // this table is not selected. + continue; + + aMergeOption.maTabs.insert(i); + + if (!pDoc->IsBlockEmpty(i, nStartCol, nStartRow+1, nStartCol, nEndRow) || + !pDoc->IsBlockEmpty(i, nStartCol+1, nStartRow, nEndCol, nEndRow)) + bAskDialog = true; + } + + sal_Bool bOk = true; + + if (bAskDialog) + { + if (!bApi) + { + MessBox aBox( GetViewData()->GetDialogParent(), + WinBits(WB_YES_NO_CANCEL | WB_DEF_NO), + ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ), + ScGlobal::GetRscString( STR_MERGE_NOTEMPTY ) ); + sal_uInt16 nRetVal = aBox.Execute(); + + if ( nRetVal == RET_YES ) + rDoContents = sal_True; + else if ( nRetVal == RET_CANCEL ) + bOk = false; + } + } + + if (bOk) + { + HideCursor(); + bOk = pDocSh->GetDocFunc().MergeCells( aMergeOption, rDoContents, bRecord, bApi ); + ShowCursor(); + + if (bOk) + { + SetCursor( nStartCol, nStartRow ); + //DoneBlockMode( sal_False); + Unmark(); + + pDocSh->UpdateOle(GetViewData()); + UpdateInputLine(); + } + } + + return bOk; +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::TestRemoveMerge() +{ + sal_Bool bMerged = false; + ScRange aRange; + if (GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE) + { + ScDocument* pDoc = GetViewData()->GetDocument(); + if ( pDoc->HasAttrib( aRange, HASATTR_MERGED ) ) + bMerged = sal_True; + } + return bMerged; +} + + +//---------------------------------------------------------------------------- + +static bool lcl_extendMergeRange(ScCellMergeOption& rOption, const ScRange& rRange) +{ + bool bExtended = false; + if (rOption.mnStartCol > rRange.aStart.Col()) + { + rOption.mnStartCol = rRange.aStart.Col(); + bExtended = true; + } + if (rOption.mnStartRow > rRange.aStart.Row()) + { + rOption.mnStartRow = rRange.aStart.Row(); + bExtended = true; + } + if (rOption.mnEndCol < rRange.aEnd.Col()) + { + rOption.mnEndCol = rRange.aEnd.Col(); + bExtended = true; + } + if (rOption.mnEndRow < rRange.aEnd.Row()) + { + rOption.mnEndRow = rRange.aEnd.Row(); + bExtended = true; + } + return bExtended; +} + +sal_Bool ScViewFunc::RemoveMerge( sal_Bool bRecord ) +{ + ScRange aRange; + ScEditableTester aTester( this ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + return false; + } + else if (GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE) + { + ScDocument* pDoc = GetViewData()->GetDocument(); + ScRange aExtended( aRange ); + pDoc->ExtendMerge( aExtended ); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + const ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTabCount = pDoc->GetTableCount(); + ScCellMergeOption aOption(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row()); + bool bExtended = false; + do + { + bExtended = false; + for (SCTAB i = 0; i < nTabCount; ++i) + { + if (!rMark.GetTableSelect(i)) + // This table is not selected. + continue; + + aOption.maTabs.insert(i); + aExtended.aStart.SetTab(i); + aExtended.aEnd.SetTab(i); + pDoc->ExtendMerge(aExtended); + pDoc->ExtendOverlapped(aExtended); + + // Expand the current range to be inclusive of all merged + // areas on all sheets. + bExtended = lcl_extendMergeRange(aOption, aExtended); + } + } + while (bExtended); + + HideCursor(); + sal_Bool bOk = pDocSh->GetDocFunc().UnmergeCells(aOption, bRecord, false ); + aExtended = aOption.getFirstSingleRange(); + MarkRange( aExtended ); + ShowCursor(); + + if (bOk) + pDocSh->UpdateOle(GetViewData()); + } + return sal_True; //! bOk ?? +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::FillSimple( FillDir eDir, sal_Bool bRecord ) +{ + ScRange aRange; + if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + const ScMarkData& rMark = GetViewData()->GetMarkData(); + sal_Bool bSuccess = pDocSh->GetDocFunc().FillSimple( aRange, &rMark, eDir, bRecord, false ); + if (bSuccess) + { + pDocSh->UpdateOle(GetViewData()); + UpdateScrollBars(); + } + } + else + ErrorMessage(STR_NOMULTISELECT); +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::FillSeries( FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd, + double fStart, double fStep, double fMax, sal_Bool bRecord ) +{ + ScRange aRange; + if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + const ScMarkData& rMark = GetViewData()->GetMarkData(); + sal_Bool bSuccess = pDocSh->GetDocFunc(). + FillSeries( aRange, &rMark, eDir, eCmd, eDateCmd, + fStart, fStep, fMax, bRecord, false ); + if (bSuccess) + { + pDocSh->UpdateOle(GetViewData()); + UpdateScrollBars(); + + // #i97876# Spreadsheet data changes are not notified + ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); + if ( pModelObj && pModelObj->HasChangesListeners() ) + { + ScRangeList aChangeRanges; + aChangeRanges.Append( aRange ); + pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); + } + } + } + else + ErrorMessage(STR_NOMULTISELECT); +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::FillAuto( FillDir eDir, SCCOL nStartCol, SCROW nStartRow, + SCCOL nEndCol, SCROW nEndRow, sal_uLong nCount, sal_Bool bRecord ) +{ + SCTAB nTab = GetViewData()->GetTabNo(); + ScRange aRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab ); + ScRange aSourceRange( aRange ); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + const ScMarkData& rMark = GetViewData()->GetMarkData(); + sal_Bool bSuccess = pDocSh->GetDocFunc(). + FillAuto( aRange, &rMark, eDir, nCount, bRecord, false ); + if (bSuccess) + { + MarkRange( aRange, false ); // aRange was modified in FillAuto + pDocSh->UpdateOle(GetViewData()); + UpdateScrollBars(); + + // #i97876# Spreadsheet data changes are not notified + ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() ); + if ( pModelObj && pModelObj->HasChangesListeners() ) + { + ScRangeList aChangeRanges; + ScRange aChangeRange( aRange ); + switch ( eDir ) + { + case FILL_TO_BOTTOM: + { + aChangeRange.aStart.SetRow( aSourceRange.aEnd.Row() + 1 ); + } + break; + case FILL_TO_TOP: + { + aChangeRange.aEnd.SetRow( aSourceRange.aStart.Row() - 1 ); + } + break; + case FILL_TO_RIGHT: + { + aChangeRange.aStart.SetCol( aSourceRange.aEnd.Col() + 1 ); + } + break; + case FILL_TO_LEFT: + { + aChangeRange.aEnd.SetCol( aSourceRange.aStart.Col() - 1 ); + } + break; + default: + { + + } + break; + } + aChangeRanges.Append( aChangeRange ); + pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges ); + } + } +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::FillTab( sal_uInt16 nFlags, sal_uInt16 nFunction, sal_Bool bSkipEmpty, sal_Bool bAsLink ) +{ + //! allow source sheet to be protected + ScEditableTester aTester( this ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + return; + } + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTab = GetViewData()->GetTabNo(); + sal_Bool bUndo(pDoc->IsUndoEnabled()); + + ScRange aMarkRange; + rMark.MarkToSimple(); + sal_Bool bMulti = rMark.IsMultiMarked(); + if (bMulti) + rMark.GetMultiMarkArea( aMarkRange ); + else if (rMark.IsMarked()) + rMark.GetMarkArea( aMarkRange ); + else + aMarkRange = ScRange( GetViewData()->GetCurX(), GetViewData()->GetCurY(), nTab ); + + ScDocument* pUndoDoc = NULL; + + if (bUndo) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nTab, nTab ); + + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nTabCount; i++) + if (i != nTab && rMark.GetTableSelect(i)) + { + pUndoDoc->AddUndoTab( i, i ); + aMarkRange.aStart.SetTab( i ); + aMarkRange.aEnd.SetTab( i ); + pDoc->CopyToDocument( aMarkRange, IDF_ALL, bMulti, pUndoDoc ); + } + } + + if (bMulti) + pDoc->FillTabMarked( nTab, rMark, nFlags, nFunction, bSkipEmpty, bAsLink ); + else + { + aMarkRange.aStart.SetTab( nTab ); + aMarkRange.aEnd.SetTab( nTab ); + pDoc->FillTab( aMarkRange, rMark, nFlags, nFunction, bSkipEmpty, bAsLink ); + } + + if (bUndo) + { //! for ChangeTrack not until the end + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoFillTable( pDocSh, rMark, + aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nTab, + aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), nTab, + pUndoDoc, bMulti, nTab, nFlags, nFunction, bSkipEmpty, bAsLink ) ); + } + + pDocSh->PostPaintGridAll(); + pDocSh->PostDataChanged(); +} + +//---------------------------------------------------------------------------- + +/** Downward fill of selected cell(s) by double-clicking cross-hair cursor + + Extends a current selection down to the last non-empty cell of an adjacent + column when the lower-right corner of the selection is double-clicked. It + uses a left-adjoining non-empty column as a guide if such is available, + otherwise a right-adjoining non-empty column is used. + + @author Kohei Yoshida (kohei@openoffice.org) + + @return No return value + + @see #i12313# +*/ +void ScViewFunc::FillCrossDblClick() +{ + ScRange aRange; + GetViewData()->GetSimpleArea( aRange ); + aRange.Justify(); + + SCTAB nTab = GetViewData()->GetCurPos().Tab(); + SCCOL nStartX = aRange.aStart.Col(); + SCROW nStartY = aRange.aStart.Row(); + SCCOL nEndX = aRange.aEnd.Col(); + SCROW nEndY = aRange.aEnd.Row(); + + ScDocument* pDoc = GetViewData()->GetDocument(); + + // Make sure the selection is not empty + if ( pDoc->IsBlockEmpty( nTab, nStartX, nStartY, nEndX, nEndY ) ) + return; + + if ( nEndY < MAXROW ) + { + if ( nStartX > 0 ) + { + SCCOL nMovX = nStartX - 1; + SCROW nMovY = nStartY; + + if ( pDoc->HasData( nMovX, nStartY, nTab ) && + pDoc->HasData( nMovX, nStartY + 1, nTab ) ) + { + pDoc->FindAreaPos( nMovX, nMovY, nTab, 0, 1 ); + + if ( nMovY > nEndY ) + { + FillAuto( FILL_TO_BOTTOM, nStartX, nStartY, nEndX, nEndY, + nMovY - nEndY ); + return; + } + } + } + + if ( nEndX < MAXCOL ) + { + SCCOL nMovX = nEndX + 1; + SCROW nMovY = nStartY; + + if ( pDoc->HasData( nMovX, nStartY, nTab ) && + pDoc->HasData( nMovX, nStartY + 1, nTab ) ) + { + pDoc->FindAreaPos( nMovX, nMovY, nTab, 0, 1 ); + + if ( nMovY > nEndY ) + { + FillAuto( FILL_TO_BOTTOM, nStartX, nStartY, nEndX, nEndY, + nMovY - nEndY ); + return; + } + } + } + } +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::TransliterateText( sal_Int32 nType ) +{ + ScMarkData aFuncMark = GetViewData()->GetMarkData(); + if ( !aFuncMark.IsMarked() && !aFuncMark.IsMultiMarked() ) + { + // no selection -> use cursor position + + ScAddress aCursor( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + aFuncMark.SetMarkArea( ScRange( aCursor ) ); + } + + sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc(). + TransliterateText( aFuncMark, nType, sal_True, false ); + if (bSuccess) + { + GetViewData()->GetViewShell()->UpdateInputHandler(); + } +} + +//---------------------------------------------------------------------------- +// AutoFormat + +ScAutoFormatData* ScViewFunc::CreateAutoFormatData() +{ + ScAutoFormatData* pData = NULL; + SCCOL nStartCol; + SCROW nStartRow; + SCTAB nStartTab; + SCCOL nEndCol; + SCROW nEndRow; + SCTAB nEndTab; + if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE) + { + if ( nEndCol-nStartCol >= 3 && nEndRow-nStartRow >= 3 ) + { + ScDocument* pDoc = GetViewData()->GetDocument(); + pData = new ScAutoFormatData; + pDoc->GetAutoFormatData( nStartTab, nStartCol,nStartRow,nEndCol,nEndRow, *pData ); + } + } + return pData; +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::AutoFormat( sal_uInt16 nFormatNo, sal_Bool bRecord ) +{ + ScRange aRange; + if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + + sal_Bool bSuccess = pDocSh->GetDocFunc().AutoFormat( aRange, &rMark, nFormatNo, bRecord, false ); + if (bSuccess) + pDocSh->UpdateOle(GetViewData()); + } + else + ErrorMessage(STR_NOMULTISELECT); +} + + +//---------------------------------------------------------------------------- +// Suchen & Ersetzen + +void ScViewFunc::SearchAndReplace( const SvxSearchItem* pSearchItem, + sal_Bool bAddUndo, sal_Bool bIsApi ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + if (bAddUndo && !pDoc->IsUndoEnabled()) + bAddUndo = false; + + SCCOL nCol = GetViewData()->GetCurX(); + SCROW nRow = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + sal_uInt16 nCommand = pSearchItem->GetCommand(); + sal_Bool bAllTables = pSearchItem->IsAllTables(); + sal_Bool* pOldSelectedTables = NULL; + sal_uInt16 nOldSelectedCount = 0; + SCTAB nOldTab = nTab; + SCTAB nLastTab = pDoc->GetTableCount() - 1; + SCTAB nStartTab, nEndTab; + if ( bAllTables ) + { + nStartTab = 0; + nEndTab = nLastTab; + pOldSelectedTables = new sal_Bool [ nEndTab + 1 ]; + for ( SCTAB j = 0; j <= nEndTab; j++ ) + { + pOldSelectedTables[j] = rMark.GetTableSelect( j ); + if ( pOldSelectedTables[j] ) + ++nOldSelectedCount; + } + } + else + { //! at least one is always selected + nStartTab = nEndTab = rMark.GetFirstSelected(); + for ( SCTAB j = nStartTab + 1; j <= nLastTab; j++ ) + { + if ( rMark.GetTableSelect( j ) ) + nEndTab = j; + } + } + + if ( nCommand == SVX_SEARCHCMD_REPLACE + || nCommand == SVX_SEARCHCMD_REPLACE_ALL ) + { + for ( SCTAB j = nStartTab; j <= nEndTab; j++ ) + { + if ( (bAllTables || rMark.GetTableSelect( j )) && + pDoc->IsTabProtected( j ) ) + { + if ( pOldSelectedTables ) + delete [] pOldSelectedTables; + ErrorMessage(STR_PROTECTIONERR); + return; + } + } + } + + if ( nCommand == SVX_SEARCHCMD_FIND + || nCommand == SVX_SEARCHCMD_FIND_ALL) + bAddUndo = false; + + //! account for bAttrib during Undo !!! + + ScDocument* pUndoDoc = NULL; + ScMarkData* pUndoMark = NULL; + String aUndoStr; + if (bAddUndo) + { + pUndoMark = new ScMarkData( rMark ); // Mark is being modified + if ( nCommand == SVX_SEARCHCMD_REPLACE_ALL ) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab ); + } + } + + if ( bAllTables ) + { //! select all, after pUndoMark has been created + for ( SCTAB j = nStartTab; j <= nEndTab; j++ ) + { + rMark.SelectTable( j, sal_True ); + } + } + + DoneBlockMode(true); // don't delete mark + InitOwnBlockMode(); + + // If search starts at the beginning don't ask again whether it shall start at the beginning + sal_Bool bFirst = true; + if ( nCol == 0 && nRow == 0 && nTab == nStartTab && !pSearchItem->GetBackward() ) + bFirst = false; + + sal_Bool bFound = false; + while (sal_True) + { + GetFrameWin()->EnterWait(); + if (pDoc->SearchAndReplace( *pSearchItem, nCol, nRow, nTab, rMark, aUndoStr, pUndoDoc ) ) + { + bFound = sal_True; + bFirst = sal_True; + if (bAddUndo) + { + GetViewData()->GetDocShell()->GetUndoManager()->AddUndoAction( + new ScUndoReplace( GetViewData()->GetDocShell(), *pUndoMark, + nCol, nRow, nTab, + aUndoStr, pUndoDoc, pSearchItem ) ); + pUndoDoc = NULL; + } + + break; // break 'while (TRUE)' + } + else if ( bFirst && (nCommand == SVX_SEARCHCMD_FIND || + nCommand == SVX_SEARCHCMD_REPLACE) ) + { + bFirst = false; + sal_uInt16 nRetVal; + GetFrameWin()->LeaveWait(); + if ( bIsApi ) + nRetVal = RET_NO; + else + { + // search dialog as parent (if available) + Window* pParent = GetParentOrChild(SID_SEARCH_DLG); + sal_uInt16 nStrId; + if ( pSearchItem->GetBackward() ) + { + if ( nStartTab == nEndTab ) + nStrId = STR_MSSG_SEARCHANDREPLACE_1; + else + nStrId = STR_MSSG_SEARCHANDREPLACE_4; + } + else + { + if ( nStartTab == nEndTab ) + nStrId = STR_MSSG_SEARCHANDREPLACE_2; + else + nStrId = STR_MSSG_SEARCHANDREPLACE_5; + } + MessBox aBox( pParent, WinBits(WB_YES_NO | WB_DEF_YES), + ScGlobal::GetRscString( STR_MSSG_SEARCHANDREPLACE_3 ), + ScGlobal::GetRscString( nStrId ) ); + nRetVal = aBox.Execute(); + } + + if ( nRetVal == RET_YES ) + { + ScDocument::GetSearchAndReplaceStart( *pSearchItem, nCol, nRow ); + if (pSearchItem->GetBackward()) + nTab = nEndTab; + else + nTab = nStartTab; + } + else + { + break; // break 'while (TRUE)' + } + } + else // nothing found + { + if ( nCommand == SVX_SEARCHCMD_FIND_ALL || nCommand == SVX_SEARCHCMD_REPLACE_ALL ) + { + pDocSh->PostPaintGridAll(); // Mark + } + + GetFrameWin()->LeaveWait(); + if (!bIsApi) + { + // search dialog as parent if available + Window* pParent = GetParentOrChild(SID_SEARCH_DLG); + // "nothing found" + InfoBox aBox( pParent, ScGlobal::GetRscString( STR_MSSG_SEARCHANDREPLACE_0 ) ); + aBox.Execute(); + } + + break; // break 'while (TRUE)' + } + } // of while sal_True + + if ( pOldSelectedTables ) + { // restore originally selected table + for ( SCTAB j = nStartTab; j <= nEndTab; j++ ) + { + rMark.SelectTable( j, pOldSelectedTables[j] ); + } + if ( bFound ) + { // if a table is selected as a "match" it remains (selected) + rMark.SelectTable( nTab, true ); + // It's a swap if only one table was selected before + //! otherwise now one table more might be selected + if ( nOldSelectedCount == 1 && nTab != nOldTab ) + rMark.SelectTable( nOldTab, false ); + } + delete [] pOldSelectedTables; + } + + MarkDataChanged(); + + if ( bFound ) + { + if ( nTab != GetViewData()->GetTabNo() ) + SetTabNo( nTab ); + + // if nothing is marked, DoneBlockMode, then marking can start + // directly from this place via Shift-Cursor + if (!rMark.IsMarked() && !rMark.IsMultiMarked()) + DoneBlockMode(sal_True); + + AlignToCursor( nCol, nRow, SC_FOLLOW_JUMP ); + SetCursor( nCol, nRow, sal_True ); + + if ( nCommand == SVX_SEARCHCMD_REPLACE + || nCommand == SVX_SEARCHCMD_REPLACE_ALL ) + { + if ( nCommand == SVX_SEARCHCMD_REPLACE ) + pDocSh->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID ); + else + pDocSh->PostPaintGridAll(); + pDocSh->SetDocumentModified(); + } + else if ( nCommand == SVX_SEARCHCMD_FIND_ALL ) + pDocSh->PostPaintGridAll(); // mark + GetFrameWin()->LeaveWait(); + } + + delete pUndoDoc; // remove if not used + delete pUndoMark; // can always be removed +} + + +//---------------------------------------------------------------------------- +// Zielwertsuche + +void ScViewFunc::Solve( const ScSolveParam& rParam ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + + SCCOL nDestCol = rParam.aRefVariableCell.Col(); + SCROW nDestRow = rParam.aRefVariableCell.Row(); + SCTAB nDestTab = rParam.aRefVariableCell.Tab(); + + ScEditableTester aTester( pDoc, nDestTab, nDestCol,nDestRow, nDestCol,nDestRow ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + return; + } + + if ( pDoc ) + { + String aTargetValStr; + if ( rParam.pStrTargetVal != NULL ) + aTargetValStr = *(rParam.pStrTargetVal); + + String aMsgStr; + String aResStr; + double nSolveResult; + + GetFrameWin()->EnterWait(); + + sal_Bool bExact = + pDoc->Solver( + rParam.aRefFormulaCell.Col(), + rParam.aRefFormulaCell.Row(), + rParam.aRefFormulaCell.Tab(), + nDestCol, nDestRow, nDestTab, + aTargetValStr, + nSolveResult ); + + GetFrameWin()->LeaveWait(); + + SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); + sal_uLong nFormat = 0; + const ScPatternAttr* pPattern = pDoc->GetPattern( nDestCol, nDestRow, nDestTab ); + if ( pPattern ) + nFormat = pPattern->GetNumberFormat( pFormatter ); + Color* p; + pFormatter->GetOutputString( nSolveResult, nFormat, aResStr, &p ); + + if ( bExact ) + { + aMsgStr = ScGlobal::GetRscString( STR_MSSG_SOLVE_0 ); + aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_1 ); + aMsgStr += String( aResStr ); + aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_2 ); + } + else + { + aMsgStr = ScGlobal::GetRscString( STR_MSSG_SOLVE_3 ); + aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_4 ); + aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_5 ); + aMsgStr += String( aResStr ); + aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_6 ); + } + + MessBox aBox( GetViewData()->GetDialogParent(), + WinBits(WB_YES_NO | WB_DEF_NO), + ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ), aMsgStr ); + sal_uInt16 nRetVal = aBox.Execute(); + + if ( RET_YES == nRetVal ) + EnterValue( nDestCol, nDestRow, nDestTab, nSolveResult ); + + GetViewData()->GetViewShell()->UpdateInputHandler( sal_True ); + } +} + + +//---------------------------------------------------------------------------- +// multi operation + +void ScViewFunc::TabOp( const ScTabOpParam& rParam, sal_Bool bRecord ) +{ + ScRange aRange; + if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE) + { + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + pDocSh->GetDocFunc().TabOp( aRange, &rMark, rParam, bRecord, false ); + } + else + ErrorMessage(STR_NOMULTISELECT); +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::MakeScenario( const String& rName, const String& rComment, + const Color& rColor, sal_uInt16 nFlags ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTab = GetViewData()->GetTabNo(); + + SCTAB nNewTab = pDocSh->MakeScenario( nTab, rName, rComment, rColor, nFlags, rMark ); + if (nFlags & SC_SCENARIO_COPYALL) + SetTabNo( nNewTab, true ); // SC_SCENARIO_COPYALL -> visible + else + { + SfxBindings& rBindings = GetViewData()->GetBindings(); + rBindings.Invalidate( SID_STATUS_DOCPOS ); // Statusbar + rBindings.Invalidate( SID_TABLES_COUNT ); + rBindings.Invalidate( SID_SELECT_SCENARIO ); + rBindings.Invalidate( FID_TABLE_SHOW ); + } +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::ExtendScenario() +{ + ScEditableTester aTester( this ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + return; + } + + // Undo: apply attributes + + ScDocument* pDoc = GetViewData()->GetDocument(); + ScPatternAttr aPattern( pDoc->GetPool() ); + aPattern.GetItemSet().Put( ScMergeFlagAttr( SC_MF_SCENARIO ) ); + aPattern.GetItemSet().Put( ScProtectionAttr( sal_True ) ); + ApplySelectionPattern(aPattern); +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::UseScenario( const String& rName ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + SCTAB nTab = GetViewData()->GetTabNo(); + + DoneBlockMode(); + InitOwnBlockMode(); + pDocSh->UseScenario( nTab, rName ); +} + + +//---------------------------------------------------------------------------- +// Insert table + +sal_Bool ScViewFunc::InsertTable( const String& rName, SCTAB nTab, sal_Bool bRecord ) +{ + // Order Tabl/Name is inverted for DocFunc + sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc(). + InsertTable( nTab, rName, bRecord, false ); + if (bSuccess) + SetTabNo( nTab, sal_True ); + + return bSuccess; +} + +//---------------------------------------------------------------------------- +// Insert tables + +sal_Bool ScViewFunc::InsertTables(SvStrings *pNames, SCTAB nTab, + SCTAB nCount, sal_Bool bRecord ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = false; + + SvStrings *pNameList= NULL; + + WaitObject aWait( GetFrameWin() ); + + if (bRecord) + { + pNameList= new SvStrings; + pDoc->BeginDrawUndo(); // InsertTab creates a SdrUndoNewPage + } + + sal_Bool bFlag=false; + + String aValTabName; + String *pStr; + + for(SCTAB i=0;i<nCount;i++) + { + if(pNames!=NULL) + { + pStr=pNames->GetObject(static_cast<sal_uInt16>(i)); + } + else + { + aValTabName.Erase(); + pDoc->CreateValidTabName( aValTabName); + pStr=&aValTabName; + } + + if(pDoc->InsertTab( nTab+i,*pStr)) + { + bFlag=sal_True; + pDocSh->Broadcast( ScTablesHint( SC_TAB_INSERTED, nTab+i ) ); + } + else + { + break; + } + + if(pNameList!=NULL) + pNameList->Insert(new String(*pStr),pNameList->Count()); + + } + + if (bFlag) + { + if (bRecord) + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoInsertTables( pDocSh, nTab, false, pNameList)); + + // Update views + + SetTabNo( nTab, sal_True ); + pDocSh->PostPaintExtras(); + pDocSh->SetDocumentModified(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + return sal_True; + } + else + { + return false; + } +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::AppendTable( const String& rName, sal_Bool bRecord ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = false; + + WaitObject aWait( GetFrameWin() ); + + if (bRecord) + pDoc->BeginDrawUndo(); // InsertTab creates a SdrUndoNewPage + + if (pDoc->InsertTab( SC_TAB_APPEND, rName )) + { + SCTAB nTab = pDoc->GetTableCount()-1; + if (bRecord) + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoInsertTab( pDocSh, nTab, sal_True, rName)); + GetViewData()->InsertTab( nTab ); + SetTabNo( nTab, sal_True ); + pDocSh->PostPaintExtras(); + pDocSh->SetDocumentModified(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + return sal_True; + } + else + { + return false; + } +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::DeleteTable( SCTAB nTab, sal_Bool bRecord ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + + sal_Bool bSuccess = pDocSh->GetDocFunc().DeleteTable( nTab, bRecord, false ); + if (bSuccess) + { + SCTAB nNewTab = nTab; + if ( nNewTab >= pDoc->GetTableCount() ) + --nNewTab; + SetTabNo( nNewTab, sal_True ); + } + return bSuccess; +} + +sal_Bool ScViewFunc::DeleteTables(const vector<SCTAB> &TheTabs, sal_Bool bRecord ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + sal_Bool bVbaEnabled = pDoc ? pDoc->IsInVBAMode() : false; + SCTAB nNewTab = TheTabs[0]; + WaitObject aWait( GetFrameWin() ); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = false; + if ( bVbaEnabled ) + bRecord = false; + + while ( nNewTab > 0 && !pDoc->IsVisible( nNewTab ) ) + --nNewTab; + + sal_Bool bWasLinked = false; + ScDocument* pUndoDoc = NULL; + ScRefUndoData* pUndoData = NULL; + if (bRecord) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + SCTAB nCount = pDoc->GetTableCount(); + + String aOldName; + for(unsigned int i=0; i<TheTabs.size(); ++i) + { + SCTAB nTab = TheTabs[i]; + if (i==0) + pUndoDoc->InitUndo( pDoc, nTab,nTab, true,true ); // incl. column/fow flags + else + pUndoDoc->AddUndoTab( nTab,nTab, true,true ); // incl. column/fow flags + + pDoc->CopyToDocument(0,0,nTab, MAXCOL,MAXROW,nTab, IDF_ALL,false, pUndoDoc ); + pDoc->GetName( nTab, aOldName ); + pUndoDoc->RenameTab( nTab, aOldName, false ); + if (pDoc->IsLinked(nTab)) + { + bWasLinked = sal_True; + pUndoDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), pDoc->GetLinkDoc(nTab), + pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab), + pDoc->GetLinkTab(nTab), + pDoc->GetLinkRefreshDelay(nTab) ); + } + if ( pDoc->IsScenario(nTab) ) + { + pUndoDoc->SetScenario( nTab, sal_True ); + String aComment; + Color aColor; + sal_uInt16 nScenFlags; + pDoc->GetScenarioData( nTab, aComment, aColor, nScenFlags ); + pUndoDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags ); + sal_Bool bActive = pDoc->IsActiveScenario( nTab ); + pUndoDoc->SetActiveScenario( nTab, bActive ); + } + pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) ); + pUndoDoc->SetTabBgColor( nTab, pDoc->GetTabBgColor(nTab) ); + pUndoDoc->SetSheetEvents( nTab, pDoc->GetSheetEvents( nTab ) ); + + if ( pDoc->IsTabProtected( nTab ) ) + pUndoDoc->SetTabProtection(nTab, pDoc->GetTabProtection(nTab)); + + // Drawing-Layer is responsible for its Undo !!! + // pUndoDoc->TransferDrawPage(pDoc, nTab,nTab); + } + + pUndoDoc->AddUndoTab( 0, nCount-1 ); // all Tabs for references + + pDoc->BeginDrawUndo(); // DeleteTab creates a SdrUndoDelPage + + pUndoData = new ScRefUndoData( pDoc ); + } + + sal_Bool bDelDone = false; + + for(int i=TheTabs.size()-1; i>=0; --i) + { + String sCodeName; + sal_Bool bHasCodeName = pDoc->GetCodeName( TheTabs[i], sCodeName ); + if (pDoc->DeleteTab( TheTabs[i], pUndoDoc )) + { + bDelDone = sal_True; + if( bVbaEnabled ) + { + if( bHasCodeName ) + { + VBA_DeleteModule( *pDocSh, sCodeName ); + } + } + pDocSh->Broadcast( ScTablesHint( SC_TAB_DELETED, TheTabs[i] ) ); + } + } + if (bRecord) + { + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoDeleteTab( GetViewData()->GetDocShell(), TheTabs, + pUndoDoc, pUndoData )); + } + + + if (bDelDone) + { + if ( nNewTab >= pDoc->GetTableCount() ) + nNewTab = pDoc->GetTableCount() - 1; + + SetTabNo( nNewTab, sal_True ); + + if (bWasLinked) + { + pDocSh->UpdateLinks(); // update Link-Manager + GetViewData()->GetBindings().Invalidate(SID_LINKS); + } + + pDocSh->PostPaintExtras(); + pDocSh->SetDocumentModified(); + + + SfxApplication* pSfxApp = SFX_APP(); // Navigator + pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) ); + pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); + } + else + { + delete pUndoDoc; + delete pUndoData; + } + return bDelDone; +} + + +//---------------------------------------------------------------------------- + +sal_Bool ScViewFunc::RenameTable( const String& rName, SCTAB nTab ) +{ + // order Table/Name is inverted for DocFunc + sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc(). + RenameTable( nTab, rName, true, false ); + if (bSuccess) + { + // the table name might be part of a formula + GetViewData()->GetViewShell()->UpdateInputHandler(); + } + return bSuccess; +} + + +//---------------------------------------------------------------------------- + +bool ScViewFunc::SetTabBgColor( const Color& rColor, SCTAB nTab ) +{ + bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().SetTabBgColor( nTab, rColor, sal_True, false ); + if (bSuccess) + { + GetViewData()->GetViewShell()->UpdateInputHandler(); + } + return bSuccess; +} + +bool ScViewFunc::SetTabBgColor( ScUndoTabColorInfo::List& rUndoSetTabBgColorInfoList ) +{ + bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().SetTabBgColor( rUndoSetTabBgColorInfoList, sal_True, false ); + if (bSuccess) + { + GetViewData()->GetViewShell()->UpdateInputHandler(); + } + return bSuccess; +} + +//---------------------------------------------------------------------------- + +void ScViewFunc::InsertAreaLink( const String& rFile, + const String& rFilter, const String& rOptions, + const String& rSource, sal_uLong nRefresh ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + SCCOL nPosX = GetViewData()->GetCurX(); + SCROW nPosY = GetViewData()->GetCurY(); + SCTAB nTab = GetViewData()->GetTabNo(); + ScAddress aPos( nPosX, nPosY, nTab ); + + pDocSh->GetDocFunc().InsertAreaLink( rFile, rFilter, rOptions, rSource, aPos, nRefresh, false, false ); +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::InsertTableLink( const String& rFile, + const String& rFilter, const String& rOptions, + const String& rTabName ) +{ + String aFilterName = rFilter; + String aOpt = rOptions; + ScDocumentLoader aLoader( rFile, aFilterName, aOpt ); + if (!aLoader.IsError()) + { + ScDocShell* pSrcSh = aLoader.GetDocShell(); + ScDocument* pSrcDoc = pSrcSh->GetDocument(); + SCTAB nTab = MAXTAB+1; + if (!rTabName.Len()) // no name given -> first table + nTab = 0; + else + { + String aTemp; + SCTAB nCount = pSrcDoc->GetTableCount(); + for (SCTAB i=0; i<nCount; i++) + { + pSrcDoc->GetName( i, aTemp ); + if ( aTemp == rTabName ) + nTab = i; + } + } + + if ( nTab <= MAXTAB ) + ImportTables( pSrcSh, 1, &nTab, sal_True, + GetViewData()->GetTabNo() ); + } +} + + +//---------------------------------------------------------------------------- +// Copy/link tables from another document + +void ScViewFunc::ImportTables( ScDocShell* pSrcShell, + SCTAB nCount, const SCTAB* pSrcTabs, sal_Bool bLink,SCTAB nTab ) +{ + ScDocument* pSrcDoc = pSrcShell->GetDocument(); + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + sal_Bool bUndo(pDoc->IsUndoEnabled()); + + sal_Bool bError = false; + sal_Bool bRefs = false; + sal_Bool bName = false; + + if (pSrcDoc->GetDrawLayer()) + pDocSh->MakeDrawLayer(); + + if (bUndo) + pDoc->BeginDrawUndo(); // drawing layer must do its own undo actions + + SCTAB nInsCount = 0; + SCTAB i; + for( i=0; i<nCount; i++ ) + { // insert sheets first and update all references + String aName; + pSrcDoc->GetName( pSrcTabs[i], aName ); + pDoc->CreateValidTabName( aName ); + if ( !pDoc->InsertTab( nTab+i, aName ) ) + { + bError = sal_True; // total error + break; // for + } + ++nInsCount; + } + for (i=0; i<nCount && !bError; i++) + { + SCTAB nSrcTab = pSrcTabs[i]; + SCTAB nDestTab1=nTab+i; + sal_uLong nErrVal = pDocSh->TransferTab( *pSrcShell, nSrcTab, nDestTab1, + false, false ); // no insert + + switch (nErrVal) + { + case 0: // internal error or full of errors + bError = true; + break; + case 2: + bRefs = sal_True; + break; + case 3: + bName = sal_True; + break; + case 4: + bRefs = bName = sal_True; + break; + } + + } + + if (bLink) + { + sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager(); + + SfxMedium* pMed = pSrcShell->GetMedium(); + String aFileName = pMed->GetName(); + String aFilterName; + if (pMed->GetFilter()) + aFilterName = pMed->GetFilter()->GetFilterName(); + String aOptions = ScDocumentLoader::GetOptions(*pMed); + + sal_Bool bWasThere = pDoc->HasLink( aFileName, aFilterName, aOptions ); + + sal_uLong nRefresh = 0; + String aTabStr; + for (i=0; i<nInsCount; i++) + { + pSrcDoc->GetName( pSrcTabs[i], aTabStr ); + pDoc->SetLink( nTab+i, SC_LINK_NORMAL, + aFileName, aFilterName, aOptions, aTabStr, nRefresh ); + } + + if (!bWasThere) // Insert link only once per source document + { + ScTableLink* pLink = new ScTableLink( pDocSh, aFileName, aFilterName, aOptions, nRefresh ); + pLink->SetInCreate( sal_True ); + pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aFileName, &aFilterName ); + pLink->Update(); + pLink->SetInCreate( false ); + + SfxBindings& rBindings = GetViewData()->GetBindings(); + rBindings.Invalidate( SID_LINKS ); + } + } + + + if (bUndo) + { + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoImportTab( pDocSh, nTab, nCount, bLink ) ); + } + + for (i=0; i<nInsCount; i++) + GetViewData()->InsertTab(nTab); + SetTabNo(nTab,sal_True); + pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, + PAINT_GRID | PAINT_TOP | PAINT_LEFT | PAINT_EXTRAS ); + + SfxApplication* pSfxApp = SFX_APP(); + pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) ); + + pDocSh->PostPaintExtras(); + pDocSh->PostPaintGridAll(); + pDocSh->SetDocumentModified(); + + if (bRefs) + ErrorMessage(STR_ABSREFLOST); + if (bName) + ErrorMessage(STR_NAMECONFLICT); +} + + +//---------------------------------------------------------------------------- +// Move/Copy table to another document + +void ScViewFunc::MoveTable( sal_uInt16 nDestDocNo, SCTAB nDestTab, sal_Bool bCopy, const String* pNewTabName ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + ScDocShell* pDocShell = GetViewData()->GetDocShell(); + ScDocument* pDestDoc = NULL; + ScDocShell* pDestShell = NULL; + ScTabViewShell* pDestViewSh = NULL; + sal_Bool bUndo (pDoc->IsUndoEnabled()); + bool bRename = pNewTabName && pNewTabName->Len(); + + sal_Bool bNewDoc = ( nDestDocNo == SC_DOC_NEW ); + if ( bNewDoc ) + { + nDestTab = 0; // firstly insert + + // execute without SFX_CALLMODE_RECORD, because already contained in move command + + String aUrl = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("private:factory/")); + aUrl.AppendAscii(RTL_CONSTASCII_STRINGPARAM( STRING_SCAPP )); // "scalc" + SfxStringItem aItem( SID_FILE_NAME, aUrl ); + SfxStringItem aTarget( SID_TARGETNAME, String::CreateFromAscii("_blank") ); + + const SfxPoolItem* pRetItem = GetViewData()->GetDispatcher().Execute( + SID_OPENDOC, SFX_CALLMODE_API|SFX_CALLMODE_SYNCHRON, &aItem, &aTarget, 0L ); + if ( pRetItem ) + { + if ( pRetItem->ISA( SfxObjectItem ) ) + pDestShell = PTR_CAST( ScDocShell, ((const SfxObjectItem*)pRetItem)->GetShell() ); + else if ( pRetItem->ISA( SfxViewFrameItem ) ) + { + SfxViewFrame* pFrm = ((const SfxViewFrameItem*)pRetItem)->GetFrame(); + if (pFrm) + pDestShell = PTR_CAST( ScDocShell, pFrm->GetObjectShell() ); + } + if (pDestShell) + pDestViewSh = pDestShell->GetBestViewShell(); + } + } + else + pDestShell = ScDocShell::GetShellByNum( nDestDocNo ); + + if (!pDestShell) + { + OSL_FAIL("Dest-Doc nicht gefunden !!!"); + return; + } + + ScMarkData& rMark = GetViewData()->GetMarkData(); + if (bRename && rMark.GetSelectCount() != 1) + { + // Custom sheet name is provided, but more than one sheet is selected. + // We don't support this scenario at the moment. + return; + } + + pDestDoc = pDestShell->GetDocument(); + + SCTAB nTab = GetViewData()->GetTabNo(); + + if (pDestDoc != pDoc) + { + if (bNewDoc) + { + while (pDestDoc->GetTableCount() > 1) + pDestDoc->DeleteTab(0); + pDestDoc->RenameTab( 0, + String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("______42_____")), + false ); + } + + SCTAB nTabCount = pDoc->GetTableCount(); + SCTAB nTabSelCount = rMark.GetSelectCount(); + + vector<SCTAB> TheTabs; + + for(SCTAB i=0; i<nTabCount; ++i) + { + if(rMark.GetTableSelect(i)) + { + String aTabName; + pDoc->GetName( i, aTabName); + TheTabs.push_back(i); + for(SCTAB j=i+1;j<nTabCount;j++) + { + if((!pDoc->IsVisible(j))&&(pDoc->IsScenario(j))) + { + pDoc->GetName( j, aTabName); + TheTabs.push_back(j); + i=j; + } + else break; + } + } + } + + GetFrameWin()->EnterWait(); + + if (pDoc->GetDrawLayer()) + pDestShell->MakeDrawLayer(); + + if (!bNewDoc && bUndo) + pDestDoc->BeginDrawUndo(); // drawing layer must do its own undo actions + + sal_uLong nErrVal =1; + if(nDestTab==SC_TAB_APPEND) + nDestTab=pDestDoc->GetTableCount(); + SCTAB nDestTab1=nDestTab; + for( sal_uInt16 j=0; j<TheTabs.size(); ++j, ++nDestTab1 ) + { // insert sheets first and update all references + String aName; + if (bRename) + aName = *pNewTabName; + else + pDoc->GetName( TheTabs[j], aName ); + + pDestDoc->CreateValidTabName( aName ); + if ( !pDestDoc->InsertTab( nDestTab1, aName ) ) + { + nErrVal = 0; // total error + break; // for + } + } + if ( nErrVal > 0 ) + { + nDestTab1 = nDestTab; + for(sal_uInt16 i=0; i<TheTabs.size();++i) + { + nErrVal = pDestShell->TransferTab( *pDocShell, TheTabs[i], static_cast<SCTAB>(nDestTab1), false, false ); + nDestTab1++; + } + } + String sName; + if (!bNewDoc && bUndo) + { + pDestDoc->GetName(nDestTab, sName); + pDestShell->GetUndoManager()->AddUndoAction( + new ScUndoImportTab( pDestShell, nDestTab, + static_cast<SCTAB>(TheTabs.size()), false)); + + } + else + { + pDestShell->GetUndoManager()->Clear(); + } + + GetFrameWin()->LeaveWait(); + switch (nErrVal) + { + case 0: // internal error or full of errors + { + ErrorMessage(STR_TABINSERT_ERROR); + return; + } + //break; + case 2: + ErrorMessage(STR_ABSREFLOST); + break; + case 3: + ErrorMessage(STR_NAMECONFLICT); + break; + case 4: + { + ErrorMessage(STR_ABSREFLOST); + ErrorMessage(STR_NAMECONFLICT); + } + break; + default: + break; + } + + if (!bCopy) + { + if(nTabCount!=nTabSelCount) + DeleteTables(TheTabs); // incl. Paint & Undo + else + ErrorMessage(STR_TABREMOVE_ERROR); + } + + if (bNewDoc) + { + // ChartListenerCollection must be updated before DeleteTab + if ( pDestDoc->IsChartListenerCollectionNeedsUpdate() ) + pDestDoc->UpdateChartListenerCollection(); + + pDestDoc->DeleteTab(static_cast<SCTAB>(TheTabs.size())); // old first table + if (pDestViewSh) + pDestViewSh->TabChanged(); // Pages auf dem Drawing-Layer + pDestShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, + PAINT_GRID | PAINT_TOP | PAINT_LEFT | + PAINT_EXTRAS | PAINT_SIZE ); + // PAINT_SIZE for outline + } + else + { + pDestShell->Broadcast( ScTablesHint( SC_TAB_INSERTED, nDestTab ) ); + pDestShell->PostPaintExtras(); + pDestShell->PostPaintGridAll(); + } + + TheTabs.clear(); + + pDestShell->SetDocumentModified(); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + } + else + { + // Move or copy within the same document. + SCTAB nTabCount = pDoc->GetTableCount(); + + auto_ptr< vector<SCTAB> > pSrcTabs(new vector<SCTAB>); + auto_ptr< vector<SCTAB> > pDestTabs(new vector<SCTAB>); + auto_ptr< vector<OUString> > pTabNames(new vector<OUString>); + auto_ptr< vector<OUString> > pDestNames(NULL); + pSrcTabs->reserve(nTabCount); + pDestTabs->reserve(nTabCount); + pTabNames->reserve(nTabCount); + String aDestName; + + for(SCTAB i=0;i<nTabCount;i++) + { + if(rMark.GetTableSelect(i)) + { + String aTabName; + pDoc->GetName( i, aTabName); + pTabNames->push_back(aTabName); + + for(SCTAB j=i+1;j<nTabCount;j++) + { + if((!pDoc->IsVisible(j))&&(pDoc->IsScenario(j))) + { + pDoc->GetName( j, aTabName); + pTabNames->push_back(aTabName); + i=j; + } + else break; + } + } + } + + if (bCopy && bUndo) + pDoc->BeginDrawUndo(); // drawing layer must do its own undo actions + + pDoc->GetName( nDestTab, aDestName); + SCTAB nDestTab1=nDestTab; + SCTAB nMovTab=0; + for (size_t j = 0, n = pTabNames->size(); j < n; ++j) + { + nTabCount = pDoc->GetTableCount(); + const OUString& rStr = (*pTabNames)[j]; + if(!pDoc->GetTable(rStr,nMovTab)) + { + nMovTab=nTabCount; + } + if(!pDoc->GetTable(aDestName,nDestTab1)) + { + nDestTab1=nTabCount; + } + pDocShell->MoveTable( nMovTab, nDestTab1, bCopy, false ); // Undo is here + + if(bCopy && pDoc->IsScenario(nMovTab)) + { + String aComment; + Color aColor; + sal_uInt16 nFlags; + + pDoc->GetScenarioData(nMovTab, aComment,aColor, nFlags); + pDoc->SetScenario(nDestTab1,sal_True); + pDoc->SetScenarioData(nDestTab1,aComment,aColor,nFlags); + sal_Bool bActive = pDoc->IsActiveScenario(nMovTab ); + pDoc->SetActiveScenario( nDestTab1, bActive ); + sal_Bool bVisible=pDoc->IsVisible(nMovTab); + pDoc->SetVisible(nDestTab1,bVisible ); + } + + pSrcTabs->push_back(nMovTab); + + if(!bCopy) + { + if(!pDoc->GetTable(rStr,nDestTab1)) + { + nDestTab1=nTabCount; + } + } + + pDestTabs->push_back(nDestTab1); + } + + // Rename must be done after all sheets have been moved. + if (bRename) + { + pDestNames.reset(new vector<OUString>); + size_t n = pDestTabs->size(); + pDestNames->reserve(n); + for (size_t j = 0; j < n; ++j) + { + SCTAB nRenameTab = (*pDestTabs)[j]; + String aTabName = *pNewTabName; + pDoc->CreateValidTabName( aTabName ); + pDestNames->push_back(aTabName); + pDoc->RenameTab(nRenameTab, aTabName); + } + } + else + // No need to keep this around when we are not renaming. + pTabNames.reset(); + + nTab = GetViewData()->GetTabNo(); + + if (bUndo) + { + if (bCopy) + { + pDocShell->GetUndoManager()->AddUndoAction( + new ScUndoCopyTab( + pDocShell, pSrcTabs.release(), pDestTabs.release(), pDestNames.release())); + } + else + { + pDocShell->GetUndoManager()->AddUndoAction( + new ScUndoMoveTab( + pDocShell, pSrcTabs.release(), pDestTabs.release(), pTabNames.release(), pDestNames.release())); + } + } + + SCTAB nNewTab = nDestTab; + if (nNewTab == SC_TAB_APPEND) + nNewTab = pDoc->GetTableCount()-1; + else if (!bCopy && nTab<nDestTab) + nNewTab--; + + SetTabNo( nNewTab, sal_True ); + + //#i29848# adjust references to data on the copied sheet + if( bCopy ) + ScChartHelper::AdjustRangesOfChartsOnDestinationPage( pDoc, pDestDoc, nTab, nNewTab ); + } +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::ShowTable( const String& rName ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + sal_Bool bUndo(pDoc->IsUndoEnabled()); + sal_Bool bFound = false; + SCTAB nPos = 0; + String aTabName; + SCTAB nCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nCount; i++) + { + pDoc->GetName( i, aTabName ); + if ( aTabName == rName ) + { + nPos = i; + bFound = sal_True; + } + } + + if (bFound) + { + pDoc->SetVisible( nPos, sal_True ); + if (bUndo) + { + pDocSh->GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( pDocSh, nPos, sal_True ) ); + } + SetTabNo( nPos, sal_True ); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + pDocSh->PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS); + pDocSh->SetDocumentModified(); + } + else + Sound::Beep(); +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::HideTable( SCTAB nTab ) +{ + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + sal_Bool bUndo(pDoc->IsUndoEnabled()); + SCTAB nVisible = 0; + SCTAB nCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nCount; i++) + { + if (pDoc->IsVisible(i)) + ++nVisible; + } + + if (nVisible > 1) + { + pDoc->SetVisible( nTab, false ); + if (bUndo) + { + pDocSh->GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( pDocSh, nTab, false ) ); + } + + // Update views + pDocSh->Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) ); + + SetTabNo( nTab, sal_True ); + SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); + pDocSh->PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS); + pDocSh->SetDocumentModified(); + } + else + Sound::Beep(); +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::InsertSpecialChar( const String& rStr, const Font& rFont ) +{ + ScEditableTester aTester( this ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + return; + } + + const sal_Unicode* pChar = rStr.GetBuffer(); + ScTabViewShell* pViewShell = GetViewData()->GetViewShell(); + SvxFontItem aFontItem( rFont.GetFamily(), + rFont.GetName(), + rFont.GetStyleName(), + rFont.GetPitch(), + rFont.GetCharSet(), + ATTR_FONT ); + + // if string contains WEAK characters, set all fonts + sal_uInt8 nScript; + ScDocument* pDoc = GetViewData()->GetDocument(); + if ( pDoc->HasStringWeakCharacters( rStr ) ) + nScript = SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN | SCRIPTTYPE_COMPLEX; + else + nScript = pDoc->GetStringScriptType( rStr ); + + SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONT, pViewShell->GetPool() ); + aSetItem.PutItemForScriptType( nScript, aFontItem ); + ApplyUserItemSet( aSetItem.GetItemSet() ); + + while ( *pChar ) + pViewShell->TabKeyInput( KeyEvent( *(pChar++), KeyCode() ) ); +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::UpdateLineAttrs( SvxBorderLine& rLine, + const SvxBorderLine* pDestLine, + const SvxBorderLine* pSrcLine, + sal_Bool bColor ) +{ + if ( pSrcLine && pDestLine ) + { + if ( bColor ) + { + rLine.SetColor ( pSrcLine->GetColor() ); + rLine.SetStyle ( pDestLine->GetStyle() ); + rLine.SetWidth ( pDestLine->GetWidth() ); + } + else + { + rLine.SetColor ( pDestLine->GetColor() ); + rLine.SetStyle ( pSrcLine->GetStyle() ); + rLine.SetWidth ( pSrcLine->GetWidth() ); + } + } +} + + +#define SET_LINE_ATTRIBUTES(LINE,BOXLINE) \ + pBoxLine = aBoxItem.Get##LINE(); \ + if ( pBoxLine ) \ + { \ + if ( pLine ) \ + { \ + UpdateLineAttrs( aLine, pBoxLine, pLine, bColorOnly ); \ + aBoxItem.SetLine( &aLine, BOXLINE ); \ + } \ + else \ + aBoxItem.SetLine( NULL, BOXLINE ); \ + } + + +//---------------------------------------------------------------------------- + +void ScViewFunc::SetSelectionFrameLines( const SvxBorderLine* pLine, + sal_Bool bColorOnly ) +{ + // Not editable only due to a matrix? Attribute is ok anyhow. + sal_Bool bOnlyNotBecauseOfMatrix; + if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix ) + { + ErrorMessage(STR_PROTECTIONERR); + return; + } + + ScDocument* pDoc = GetViewData()->GetDocument(); + ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered + ScViewUtil::UnmarkFiltered( aFuncMark, pDoc ); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + const ScPatternAttr* pSelAttrs = GetSelectionPattern(); + const SfxItemSet& rSelItemSet = pSelAttrs->GetItemSet(); + + const SfxPoolItem* pBorderAttr = NULL; + SfxItemState eItemState = rSelItemSet.GetItemState( ATTR_BORDER, sal_True, &pBorderAttr ); + + const SfxPoolItem* pTLBRItem = 0; + SfxItemState eTLBRState = rSelItemSet.GetItemState( ATTR_BORDER_TLBR, sal_True, &pTLBRItem ); + + const SfxPoolItem* pBLTRItem = 0; + SfxItemState eBLTRState = rSelItemSet.GetItemState( ATTR_BORDER_BLTR, sal_True, &pBLTRItem ); + + // any of the lines visible? + if( (eItemState != SFX_ITEM_DEFAULT) || (eTLBRState != SFX_ITEM_DEFAULT) || (eBLTRState != SFX_ITEM_DEFAULT) ) + { + // none of the lines don't care? + if( (eItemState != SFX_ITEM_DONTCARE) && (eTLBRState != SFX_ITEM_DONTCARE) && (eBLTRState != SFX_ITEM_DONTCARE) ) + { + SfxItemSet* pOldSet = new SfxItemSet( + *(pDoc->GetPool()), + ATTR_PATTERN_START, + ATTR_PATTERN_END ); + SfxItemSet* pNewSet = new SfxItemSet( + *(pDoc->GetPool()), + ATTR_PATTERN_START, + ATTR_PATTERN_END ); + + //------------------------------------------------------------ + const SvxBorderLine* pBoxLine = NULL; + SvxBorderLine aLine; + + // here pBoxLine is used + + if( pBorderAttr ) + { + SvxBoxItem aBoxItem( *(const SvxBoxItem*)pBorderAttr ); + SvxBoxInfoItem aBoxInfoItem( ATTR_BORDER_INNER ); + + SET_LINE_ATTRIBUTES(Top,BOX_LINE_TOP) + SET_LINE_ATTRIBUTES(Bottom,BOX_LINE_BOTTOM) + SET_LINE_ATTRIBUTES(Left,BOX_LINE_LEFT) + SET_LINE_ATTRIBUTES(Right,BOX_LINE_RIGHT) + + aBoxInfoItem.SetLine( aBoxItem.GetTop(), BOXINFO_LINE_HORI ); + aBoxInfoItem.SetLine( aBoxItem.GetLeft(), BOXINFO_LINE_VERT ); + aBoxInfoItem.ResetFlags(); // set Lines to Valid + + pOldSet->Put( *pBorderAttr ); + pNewSet->Put( aBoxItem ); + pNewSet->Put( aBoxInfoItem ); + } + + if( pTLBRItem && ((const SvxLineItem*)pTLBRItem)->GetLine() ) + { + SvxLineItem aTLBRItem( *(const SvxLineItem*)pTLBRItem ); + UpdateLineAttrs( aLine, aTLBRItem.GetLine(), pLine, bColorOnly ); + aTLBRItem.SetLine( &aLine ); + pOldSet->Put( *pTLBRItem ); + pNewSet->Put( aTLBRItem ); + } + + if( pBLTRItem && ((const SvxLineItem*)pBLTRItem)->GetLine() ) + { + SvxLineItem aBLTRItem( *(const SvxLineItem*)pBLTRItem ); + UpdateLineAttrs( aLine, aBLTRItem.GetLine(), pLine, bColorOnly ); + aBLTRItem.SetLine( &aLine ); + pOldSet->Put( *pBLTRItem ); + pNewSet->Put( aBLTRItem ); + } + + ApplyAttributes( pNewSet, pOldSet ); + + delete pOldSet; + delete pNewSet; + } + else // if ( eItemState == SFX_ITEM_DONTCARE ) + { + aFuncMark.MarkToMulti(); + pDoc->ApplySelectionLineStyle( aFuncMark, pLine, bColorOnly ); + } + + ScRange aMarkRange; + aFuncMark.GetMultiMarkArea( aMarkRange ); + SCCOL nStartCol = aMarkRange.aStart.Col(); + SCROW nStartRow = aMarkRange.aStart.Row(); + SCTAB nStartTab = aMarkRange.aStart.Tab(); + SCCOL nEndCol = aMarkRange.aEnd.Col(); + SCROW nEndRow = aMarkRange.aEnd.Row(); + SCTAB nEndTab = aMarkRange.aEnd.Tab(); + pDocSh->PostPaint( nStartCol, nStartRow, nStartTab, + nEndCol, nEndRow, nEndTab, + PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE ); + + pDocSh->UpdateOle( GetViewData() ); + pDocSh->SetDocumentModified(); + } +} + +#undef SET_LINE_ATTRIBUTES + + +//---------------------------------------------------------------------------- + +void ScViewFunc::SetConditionalFormat( const ScConditionalFormat& rNew ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + sal_uLong nIndex = pDoc->AddCondFormat(rNew); // for it there is no Undo + SfxUInt32Item aItem( ATTR_CONDITIONAL, nIndex ); + + ApplyAttr( aItem ); // with Paint and Undo... +} + + +//---------------------------------------------------------------------------- + +void ScViewFunc::SetValidation( const ScValidationData& rNew ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + sal_uLong nIndex = pDoc->AddValidationEntry(rNew); // for it there is no Undo + SfxUInt32Item aItem( ATTR_VALIDDATA, nIndex ); + + ApplyAttr( aItem ); // with Paint and Undo... +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |