1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 #include <clipcontext.hxx>
12 #include <document.hxx>
13 #include <mtvelements.hxx>
15 #include <scitems.hxx>
16 #include <tokenarray.hxx>
17 #include <editutil.hxx>
18 #include <clipparam.hxx>
20 #include <svl/intitem.hxx>
21 #include <svl/numformat.hxx>
22 #include <formula/errorcodes.hxx>
23 #include <refdata.hxx>
24 #include <listenercontext.hxx>
28 ClipContextBase::ClipContextBase(ScDocument
& rDoc
) :
29 mpSet(new ColumnBlockPositionSet(rDoc
)) {}
31 ClipContextBase::~ClipContextBase() {}
33 ColumnBlockPosition
* ClipContextBase::getBlockPosition(SCTAB nTab
, SCCOL nCol
)
35 return mpSet
->getBlockPosition(nTab
, nCol
);
38 CopyFromClipContext::CopyFromClipContext(ScDocument
& rDoc
,
39 ScDocument
* pRefUndoDoc
, ScDocument
* pClipDoc
, InsertDeleteFlags nInsertFlag
,
40 bool bAsLink
, bool bSkipEmptyCells
) :
41 ClipContextBase(rDoc
),
42 mnDestCol1(-1), mnDestCol2(-1),
43 mnDestRow1(-1), mnDestRow2(-1),
44 mnTabStart(-1), mnTabEnd(-1),
46 mpRefUndoDoc(pRefUndoDoc
), mpClipDoc(pClipDoc
),
47 mnInsertFlag(nInsertFlag
), mnDeleteFlag(InsertDeleteFlags::NONE
),
48 mpCondFormatList(nullptr),
49 mbAsLink(bAsLink
), mbSkipEmptyCells(bSkipEmptyCells
),
50 mbTableProtected(false)
54 CopyFromClipContext::~CopyFromClipContext()
58 void CopyFromClipContext::setTabRange(SCTAB nStart
, SCTAB nEnd
)
64 SCTAB
CopyFromClipContext::getTabStart() const
69 SCTAB
CopyFromClipContext::getTabEnd() const
74 void CopyFromClipContext::setDestRange( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
82 CopyFromClipContext::Range
CopyFromClipContext::getDestRange() const
85 aRet
.mnCol1
= mnDestCol1
;
86 aRet
.mnCol2
= mnDestCol2
;
87 aRet
.mnRow1
= mnDestRow1
;
88 aRet
.mnRow2
= mnDestRow2
;
92 ScDocument
* CopyFromClipContext::getUndoDoc()
97 ScDocument
* CopyFromClipContext::getClipDoc()
102 InsertDeleteFlags
CopyFromClipContext::getInsertFlag() const
107 void CopyFromClipContext::setDeleteFlag( InsertDeleteFlags nFlag
)
109 mnDeleteFlag
= nFlag
;
112 InsertDeleteFlags
CopyFromClipContext::getDeleteFlag() const
117 void CopyFromClipContext::setListeningFormulaSpans(
118 SCTAB nTab
, SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
120 for (SCCOL nCol
= nCol1
; nCol
<= nCol2
; ++nCol
)
121 maListeningFormulaSpans
.set(mrDestDoc
, nTab
, nCol
, nRow1
, nRow2
, true);
126 class StartListeningAction
: public sc::ColumnSpanSet::Action
128 ScDocument
& mrDestDoc
;
129 sc::StartListeningContext
& mrStartCxt
;
130 sc::EndListeningContext
& mrEndCxt
;
133 StartListeningAction( ScDocument
& rDestDoc
, sc::StartListeningContext
& rStartCxt
, sc::EndListeningContext
& rEndCxt
) :
134 mrDestDoc(rDestDoc
), mrStartCxt(rStartCxt
), mrEndCxt(rEndCxt
)
138 virtual void execute( const ScAddress
& rPos
, SCROW nLength
, bool bVal
) override
143 SCROW nRow1
= rPos
.Row();
144 SCROW nRow2
= nRow1
+ nLength
- 1;
146 mrDestDoc
.StartListeningFromClip(
147 mrStartCxt
, mrEndCxt
, rPos
.Tab(), rPos
.Col(), nRow1
, rPos
.Col(), nRow2
);
153 void CopyFromClipContext::startListeningFormulas()
155 auto pSet
= std::make_shared
<sc::ColumnBlockPositionSet
>(mrDestDoc
);
156 sc::StartListeningContext
aStartCxt(mrDestDoc
, pSet
);
157 sc::EndListeningContext
aEndCxt(mrDestDoc
, pSet
, nullptr);
159 StartListeningAction
aAction(mrDestDoc
, aStartCxt
, aEndCxt
);
160 maListeningFormulaSpans
.executeAction(mrDestDoc
, aAction
);
163 void CopyFromClipContext::setSingleCellColumnSize( size_t nSize
)
165 maSingleCells
.resize(nSize
);
166 maSingleCellAttrs
.resize(nSize
);
167 maSinglePatterns
.resize(nSize
, nullptr);
168 maSingleNotes
.resize(nSize
, nullptr);
169 maSingleSparkline
.resize(nSize
);
172 ScCellValue
& CopyFromClipContext::getSingleCell( size_t nColOffset
)
174 assert(nColOffset
< maSingleCells
.size());
175 return maSingleCells
[nColOffset
];
178 sc::CellTextAttr
& CopyFromClipContext::getSingleCellAttr( size_t nColOffset
)
180 assert(nColOffset
< maSingleCellAttrs
.size());
181 return maSingleCellAttrs
[nColOffset
];
184 void CopyFromClipContext::setSingleCell( const ScAddress
& rSrcPos
, const ScColumn
& rSrcCol
)
186 SCCOL nColOffset
= rSrcPos
.Col() - mpClipDoc
->GetClipParam().getWholeRange().aStart
.Col();
187 ScCellValue
& rSrcCell
= getSingleCell(nColOffset
);
189 const sc::CellTextAttr
* pAttr
= rSrcCol
.GetCellTextAttr(rSrcPos
.Row());
193 sc::CellTextAttr
& rAttr
= getSingleCellAttr(nColOffset
);
199 ScSingleRefData aRef
;
200 aRef
.InitAddress(rSrcPos
);
201 aRef
.SetFlag3D(true);
203 ScTokenArray
aArr(*mpClipDoc
);
204 aArr
.AddSingleReference(aRef
);
205 rSrcCell
.set(new ScFormulaCell(*mpClipDoc
, rSrcPos
, aArr
));
209 rSrcCell
.assign(*mpClipDoc
, rSrcPos
);
211 // Check the paste flag to see whether we want to paste this cell. If the
212 // flag says we don't want to paste this cell, we'll return with true.
213 InsertDeleteFlags nFlags
= getInsertFlag();
214 bool bNumeric
= (nFlags
& InsertDeleteFlags::VALUE
) != InsertDeleteFlags::NONE
;
215 bool bDateTime
= (nFlags
& InsertDeleteFlags::DATETIME
) != InsertDeleteFlags::NONE
;
216 bool bString
= (nFlags
& InsertDeleteFlags::STRING
) != InsertDeleteFlags::NONE
;
217 bool bBoolean
= (nFlags
& InsertDeleteFlags::SPECIAL_BOOLEAN
) != InsertDeleteFlags::NONE
;
218 bool bFormula
= (nFlags
& InsertDeleteFlags::FORMULA
) != InsertDeleteFlags::NONE
;
220 switch (rSrcCell
.getType())
224 bool bPaste
= isDateCell(rSrcCol
, rSrcPos
.Row()) ? bDateTime
: bNumeric
;
230 case CELLTYPE_STRING
:
238 case CELLTYPE_FORMULA
:
242 // Check if this formula cell is a boolean cell, and if so, go ahead and paste it.
243 const ScTokenArray
* pCode
= rSrcCell
.getFormula()->GetCode();
244 if (pCode
&& pCode
->GetLen() == 1)
246 const formula::FormulaToken
* p
= pCode
->FirstToken();
247 if (p
->GetOpCode() == ocTrue
|| p
->GetOpCode() == ocFalse
)
248 // This is a boolean formula. Good.
257 FormulaError nErr
= rSrcCell
.getFormula()->GetErrCode();
258 if (nErr
!= FormulaError::NONE
)
260 // error codes are cloned with values
262 // Error code is treated as numeric value. Don't paste it.
266 // Turn this into a formula cell with just the error code.
267 ScFormulaCell
* pErrCell
= new ScFormulaCell(*mpClipDoc
, rSrcPos
);
268 pErrCell
->SetErrCode(nErr
);
269 rSrcCell
.set(pErrCell
);
272 else if (rSrcCell
.getFormula()->IsEmptyDisplayedAsString())
274 // Empty stays empty and doesn't become 0.
277 else if (rSrcCell
.getFormula()->IsValue())
279 bool bPaste
= isDateCell(rSrcCol
, rSrcPos
.Row()) ? bDateTime
: bNumeric
;
287 // Turn this into a numeric cell.
288 rSrcCell
.set(rSrcCell
.getFormula()->GetValue());
292 svl::SharedString aStr
= rSrcCell
.getFormula()->GetString();
295 // do not clone empty string
300 // Turn this into a string or edit cell.
301 if (rSrcCell
.getFormula()->IsMultilineResult())
303 std::unique_ptr
<EditTextObject
> pObj(mrDestDoc
.CreateSharedStringTextObject(
304 rSrcCell
.getFormula()->GetString()));
308 rSrcCell
.set(rSrcCell
.getFormula()->GetString());
311 // We don't want to paste this.
317 // There is nothing to paste.
322 const ScPatternAttr
* CopyFromClipContext::getSingleCellPattern( size_t nColOffset
) const
324 assert(nColOffset
< maSinglePatterns
.size());
325 return maSinglePatterns
[nColOffset
];
328 void CopyFromClipContext::setSingleCellPattern( size_t nColOffset
, const ScPatternAttr
* pAttr
)
330 assert(nColOffset
< maSinglePatterns
.size());
331 maSinglePatterns
[nColOffset
] = pAttr
;
334 const ScPostIt
* CopyFromClipContext::getSingleCellNote( size_t nColOffset
) const
336 assert(nColOffset
< maSingleNotes
.size());
337 return maSingleNotes
[nColOffset
];
340 void CopyFromClipContext::setSingleCellNote( size_t nColOffset
, const ScPostIt
* pNote
)
342 assert(nColOffset
< maSingleNotes
.size());
343 maSingleNotes
[nColOffset
] = pNote
;
346 std::shared_ptr
<sc::Sparkline
> const& CopyFromClipContext::getSingleSparkline(size_t nColOffset
) const
348 assert(nColOffset
< maSingleSparkline
.size());
349 return maSingleSparkline
[nColOffset
];
352 void CopyFromClipContext::setSingleSparkline(size_t nColOffset
, std::shared_ptr
<sc::Sparkline
> const& pSparkline
)
354 assert(nColOffset
< maSingleSparkline
.size());
355 maSingleSparkline
[nColOffset
] = pSparkline
;
358 void CopyFromClipContext::setCondFormatList( ScConditionalFormatList
* pCondFormatList
)
360 mpCondFormatList
= pCondFormatList
;
363 ScConditionalFormatList
* CopyFromClipContext::getCondFormatList()
365 return mpCondFormatList
;
368 void CopyFromClipContext::setTableProtected( bool b
)
370 mbTableProtected
= b
;
373 bool CopyFromClipContext::isTableProtected() const
375 return mbTableProtected
;
378 bool CopyFromClipContext::isAsLink() const
383 bool CopyFromClipContext::isSkipEmptyCells() const
385 return mbSkipEmptyCells
;
388 bool CopyFromClipContext::isCloneNotes() const
390 return bool(mnInsertFlag
& (InsertDeleteFlags::NOTE
| InsertDeleteFlags::ADDNOTES
));
393 bool CopyFromClipContext::isCloneSparklines() const
395 return bool(mnInsertFlag
& InsertDeleteFlags::SPARKLINES
);
398 bool CopyFromClipContext::isDateCell( const ScColumn
& rCol
, SCROW nRow
) const
400 sal_uInt32 nNumIndex
= rCol
.GetAttr(nRow
, ATTR_VALUE_FORMAT
).GetValue();
401 SvNumFormatType nType
= mpClipDoc
->GetFormatTable()->GetType(nNumIndex
);
402 return (nType
== SvNumFormatType::DATE
) || (nType
== SvNumFormatType::TIME
) || (nType
== SvNumFormatType::DATETIME
);
405 CopyToClipContext::CopyToClipContext(
406 ScDocument
& rDoc
, bool bKeepScenarioFlags
, bool bCopyChartRanges
) :
407 ClipContextBase(rDoc
), mbKeepScenarioFlags(bKeepScenarioFlags
), mbCopyChartRanges(bCopyChartRanges
) {}
409 CopyToClipContext::~CopyToClipContext() {}
411 bool CopyToClipContext::isKeepScenarioFlags() const
413 return mbKeepScenarioFlags
;
416 CopyToDocContext::CopyToDocContext(ScDocument
& rDoc
) :
417 ClipContextBase(rDoc
), mbStartListening(true) {}
419 CopyToDocContext::~CopyToDocContext() {}
421 void CopyToDocContext::setStartListening( bool b
)
423 mbStartListening
= b
;
426 bool CopyToDocContext::isStartListening() const
428 return mbStartListening
;
431 MixDocContext::MixDocContext(ScDocument
& rDoc
) : ClipContextBase(rDoc
) {}
432 MixDocContext::~MixDocContext() {}
436 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */