/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// There MUST be exactly one reference per range token and nothing // else, and it MUST be a valid reference, not some #REF!
sal_uInt16 nLen = pArray->GetLen(); if (!nLen) continue; // Should a missing range really be allowed? if (nLen != 1)
{
bFailure = true; break;
}
const FormulaToken* p = pArray->FirstToken(); if (!p)
{
bFailure = true; break;
}
switch (p->GetType())
{ case svSingleRef:
{ const ScSingleRefData& rRef = *p->GetSingleRef(); if (!rRef.Valid(rDoc))
bFailure = true; elseif (bOnly3DRef && !rRef.IsFlag3D())
bFailure = true;
} break; case svDoubleRef:
{ const ScComplexRefData& rRef = *p->GetDoubleRef(); if (!rRef.Valid(rDoc))
bFailure = true; elseif (bOnly3DRef && !rRef.Ref1.IsFlag3D())
bFailure = true;
} break; case svExternalSingleRef:
{ if (!p->GetSingleRef()->ValidExternal(rDoc))
bFailure = true;
} break; case svExternalDoubleRef:
{ if (!p->GetDoubleRef()->ValidExternal(rDoc))
bFailure = true;
} break; case svString: if (p->GetString().isEmpty())
bFailure = true; break; case svIndex:
{ if (p->GetOpCode() == ocName)
{
ScRangeData* pNameRange = rDoc.FindRangeNameBySheetAndIndex(p->GetSheet(), p->GetIndex()); if (!pNameRange->HasReferences())
bFailure = true;
}
} break; default:
bFailure = true; break;
} if (!bFailure)
rRefTokens.emplace_back(p->Clone());
// Display sheet name on 2nd reference only when the 1st and 2nd refs are on // different sheets.
aData.Ref2.SetFlag3D(rRange.aStart.Tab() != rRange.aEnd.Tab());
if (bExternal && nFileId != p->GetIndex()) // different external file continue;
if (aRange.Intersects(aRange2)) returntrue;
} returnfalse;
}
namespace {
class JoinRefTokenRanges
{ public: /** * Insert a new reference token into the existing list of reference tokens, * but in that process, try to join as many adjacent ranges as possible. * * @param rTokens existing list of reference tokens * @param rToken new token
*/ voidoperator() (const ScDocument* pDoc, vector<ScTokenRef>& rTokens, const ScTokenRef& pToken, const ScAddress& rPos)
{
join(pDoc, rTokens, pToken, rPos);
}
private:
/** * Check two 1-dimensional ranges to see if they overlap each other. * * @param nMin1 min value of range 1 * @param nMax1 max value of range 1 * @param nMin2 min value of range 2 * @param nMax2 max value of range 2 * @param rNewMin min value of new range in case they overlap * @param rNewMax max value of new range in case they overlap
*/ template<typename T> staticbool overlaps(T nMin1, T nMax1, T nMin2, T nMax2, T& rNewMin, T& rNewMax)
{ bool bDisjoint1 = (nMin1 > nMax2) && (nMin1 - nMax2 > 1); bool bDisjoint2 = (nMin2 > nMax1) && (nMin2 - nMax1 > 1); if (bDisjoint1 || bDisjoint2) // These two ranges cannot be joined. Move on. returnfalse;
T nMin = std::min(nMin1, nMin2);
T nMax = std::max(nMax1, nMax2);
rNewMin = nMin;
rNewMax = nMax;
returntrue;
}
void join(const ScDocument* pDoc, vector<ScTokenRef>& rTokens, const ScTokenRef& pToken, const ScAddress& rPos)
{ // Normalize the token to a double reference.
ScComplexRefData aData; if (!ScRefTokenHelper::getDoubleRefDataFromToken(aData, pToken)) return;
// Get the information of the new token. bool bExternal = ScRefTokenHelper::isExternalRef(pToken);
sal_uInt16 nFileId = bExternal ? pToken->GetIndex() : 0;
svl::SharedString aTabName = bExternal ? pToken->GetString() : svl::SharedString::getEmptyString();
bool bJoined = false; for (ScTokenRef& pOldToken : rTokens)
{ if (!ScRefTokenHelper::isRef(pOldToken)) // A non-ref token should not have been added here in the first // place! continue;
if (bExternal != ScRefTokenHelper::isExternalRef(pOldToken)) // External and internal refs don't mix. continue;
if (bExternal)
{ if (nFileId != pOldToken->GetIndex()) // Different external files. continue;
if (aTabName != pOldToken->GetString()) // Different table names. continue;
}
ScComplexRefData aOldData; if (!ScRefTokenHelper::getDoubleRefDataFromToken(aOldData, pOldToken)) continue;
if (bJoinRanges)
{
aNew.aStart.SetRow(nNewMin);
aNew.aEnd.SetRow(nNewMax);
aNewData.SetRange(pDoc->GetSheetLimits(), aNew, rPos);
}
}
if (bJoinRanges)
{ if (bExternal)
pOldToken.reset(new ScExternalDoubleRefToken(nFileId, aTabName, aNewData)); else
pOldToken.reset(new ScDoubleRefToken(pDoc->GetSheetLimits(), aNewData));
bJoined = true; break;
}
}
if (bJoined)
{ if (rTokens.size() == 1) // There is only one left. No need to do more joining. return;
// Pop the last token from the list, and keep joining recursively.
ScTokenRef p = rTokens.back();
rTokens.pop_back();
join(pDoc, rTokens, p, rPos);
} else
rTokens.push_back(pToken);
}
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.