23 #include <osl/diagnose.h>
27 #include <tokenarray.hxx>
38 #include <document.hxx>
50 #include <com/sun/star/sheet/ComplexReference.hpp>
51 #include <com/sun/star/sheet/ExternalReference.hpp>
52 #include <com/sun/star/sheet/FormulaToken.hpp>
53 #include <com/sun/star/sheet/ReferenceFlags.hpp>
54 #include <com/sun/star/sheet/NameToken.hpp>
64 void lcl_SingleRefToCalc(
ScSingleRefData& rRef,
const sheet::SingleReference& rAPI )
68 rRef.
SetColRel( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
69 rRef.
SetRowRel( ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE ) != 0 );
70 rRef.
SetTabRel( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_RELATIVE ) != 0 );
71 rRef.
SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED ) != 0 );
72 rRef.
SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED ) != 0 );
73 rRef.
SetTabDeleted( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_DELETED ) != 0 );
74 rRef.
SetFlag3D( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D ) != 0 );
75 rRef.
SetRelName( ( rAPI.Flags & sheet::ReferenceFlags::RELATIVE_NAME ) != 0 );
78 rRef.
SetRelCol(static_cast<SCCOL>(rAPI.RelativeColumn));
80 rRef.
SetAbsCol(static_cast<SCCOL>(rAPI.Column));
83 rRef.
SetRelRow(static_cast<SCROW>(rAPI.RelativeRow));
85 rRef.
SetAbsRow(static_cast<SCROW>(rAPI.Row));
88 rRef.
SetRelTab(static_cast<SCTAB>(rAPI.RelativeSheet));
90 rRef.
SetAbsTab(static_cast<SCTAB>(rAPI.Sheet));
93 void lcl_ExternalRefToCalc(
ScSingleRefData& rRef,
const sheet::SingleReference& rAPI )
97 rRef.
SetColRel( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
98 rRef.
SetRowRel( ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE ) != 0 );
99 rRef.
SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED ) != 0 );
100 rRef.
SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED ) != 0 );
102 rRef.
SetFlag3D( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D ) != 0 );
106 rRef.
SetRelCol(static_cast<SCCOL>(rAPI.RelativeColumn));
108 rRef.
SetAbsCol(static_cast<SCCOL>(rAPI.Column));
111 rRef.
SetRelRow(static_cast<SCROW>(rAPI.RelativeRow));
113 rRef.
SetAbsRow(static_cast<SCROW>(rAPI.Row));
119 struct TokenPointerRange
124 TokenPointerRange() : mpStart(nullptr), mpStop(nullptr) {}
126 mpStart(p), mpStop( p + static_cast<size_t>(n)) {}
130 TokenPointerRange maPointerRange[2];
134 bool bSkipRelName =
true ) :
135 mbSkipRelName(bSkipRelName)
137 maPointerRange[0] = TokenPointerRange( pCode, nLen);
138 maPointerRange[1] = TokenPointerRange( pRPN, nRPN);
141 bool skipToken(
size_t i,
const FormulaToken*
const * pp )
151 if ((*pp)->GetRef() > 1)
158 switch ((*pp)->GetType())
161 return (*pp)->GetSingleRef()->IsRelName();
178 if (skipToken( i, pp))
240 whitespace.nCount = 1;
241 whitespace.cChar = 0x20;
246 sbyte.eInForceArray = ParamClass::Unknown;
255 sharedstring.mpData = pData;
256 sharedstring.mpDataIgnoreCase = pDataIgnoreCase;
293 name.nSheet = nSheet;
294 name.nIndex = nIndex;
302 extref.nFileId = nFileId;
304 extref.aRef.Ref2 = rRef;
305 maExternalName = rTabName;
313 extref.nFileId = nFileId;
315 maExternalName = rTabName;
323 extname.nFileId = nFileId;
324 maExternalName = rName;
331 maExternalName = rStr;
339 return aRef.Ref1.Valid(rDoc);
341 return aRef.Valid(rDoc);
353 #define IF_NOT_OPCODE_ERROR(o,c) SAL_WARN_IF((eOp!=o), "sc.core", #c "::ctor: OpCode " << static_cast<int>(eOp) << " lost, converted to " #o "; maybe inherit from FormulaToken instead!")
422 SAL_WARN(
"sc.core",
"unknown ScRawToken::CreateToken() type " <<
int(GetType()));
426 #undef IF_NOT_OPCODE_ERROR
436 && _rToken1.FormulaToken::operator ==(_rToken2));
444 aTemp1.Ref2 = aTemp1.Ref1;
459 ScRange aRange1 = aTemp1.toAbs(rLimits, aPos), aRange2 = aTemp2.
toAbs(rLimits, aPos);
463 return aRange1 == aRange2 && aTemp1.Ref1.FlagValue() == aTemp2.
Ref1.
FlagValue() && aTemp1.Ref2.FlagValue() == aTemp2.
Ref2.
FlagValue();
468 #if DEBUG_FORMULA_COMPILER
473 cout <<
"-- ScSingleRefToken" <<
endl;
477 cout <<
"-- ScDoubleRefToken" << endl;
481 cout <<
"-- FormulaToken" << endl;
482 cout <<
" opcode: " <<
int(rToken.
GetOpCode()) <<
" " <<
484 cout <<
" type: " <<
static_cast<int>(rToken.
GetType()) << endl;
488 cout <<
" value: " << rToken.
GetDouble() << endl;
504 const ScAddress & rPos,
bool bReuseDoubleRef )
549 aRef.
Extend(rLimits, rRef2, rPos);
561 xRes = (bReuseDoubleRef && rTok1.
GetRef() == 1 ? &rTok1 : rTok1.
Clone());
566 xRes = (bReuseDoubleRef && rTok2.
GetRef() == 1 ? &rTok2 : rTok2.
Clone());
575 if (pRefList->empty())
586 for (
size_t i=0; i<2; ++i)
591 rRef.
Extend(rLimits, *pt[i]->GetSingleRef(), rPos);
594 rRef.
Extend(rLimits, *pt[i]->GetDoubleRef(), rPos);
601 for (
const auto& rRefData : *p)
603 rRef.
Extend(rLimits, rRefData, rPos);
611 rRef.
Extend(rLimits, *pt[i]->GetSingleRef(), rPos);
617 rRef.
Extend(rLimits, *pt[i]->GetDoubleRef(), rPos);
660 if (!FormulaToken::operator==( r ) || &aRefList != r.
GetRefList())
755 if (!FormulaToken::operator==(r))
821 if (!FormulaToken::operator==(r))
854 if ( !FormulaToken::operator==(r) )
872 mxAreaRefRPN( r.mxAreaRefRPN ? r.mxAreaRefRPN->
Clone() : nullptr),
894 SAL_WARN(
"sc.core",
"ScTableRefToken::GetSheet - maybe adapt caller to know about TableRef?");
921 if ( !FormulaToken::operator==(r) )
946 , mpJumpMatrix(
std::move(p))
1005 xMatrix == static_cast<const ScMatrixCellResultToken &>(r).xMatrix;
1066 OSL_ENSURE( r.
GetType() !=
svMatrix,
"ScMatrixFormulaCellToken::operator=: assigning ScMatrixToken to ScMatrixFormulaCellToken is not proper, use ScMatrixCellResultToken instead");
1100 OSL_FAIL(
"ScMatrixFormulaCellToken::SetUpperLeftDouble: not modifying unhandled token type");
1112 double f,
const svl::SharedString & rStr,
const OUString & rFormula,
bool bEmptyDisplayedAsString ) :
1116 mbEmptyDisplayedAsString( bEmptyDisplayedAsString)
1119 assert( !bEmptyDisplayedAsString || (f == 0.0 && rStr.
getString().isEmpty()));
1139 bool bError = FormulaTokenArray::AddFormulaToken(rToken, rSPool, pExtRef);
1143 const OpCode eOpCode =
static_cast<OpCode>(rToken.OpCode);
1145 const uno::TypeClass eClass = rToken.Data.getValueTypeClass();
1148 case uno::TypeClass_STRUCT:
1150 uno::Type aType = rToken.Data.getValueType();
1154 sheet::SingleReference aApiRef;
1155 rToken.Data >>= aApiRef;
1156 lcl_SingleRefToCalc( aSingleRef, aApiRef );
1167 sheet::ComplexReference aApiRef;
1168 rToken.Data >>= aApiRef;
1169 lcl_SingleRefToCalc( aComplRef.
Ref1, aApiRef.Reference1 );
1170 lcl_SingleRefToCalc( aComplRef.
Ref2, aApiRef.Reference2 );
1179 sheet::NameToken aTokenData;
1180 rToken.Data >>= aTokenData;
1183 SAL_WARN_IF( aTokenData.Sheet < -1 || std::numeric_limits<sal_Int16>::max() < aTokenData.Sheet,
1185 "ScTokenArray::AddFormulaToken - NameToken.Sheet out of limits: " << aTokenData.Sheet);
1186 sal_Int16 nSheet =
static_cast<sal_Int16
>(aTokenData.Sheet);
1198 sheet::ExternalReference aApiExtRef;
1199 if( (eOpCode ==
ocPush) && (rToken.Data >>= aApiExtRef) && (0 <= aApiExtRef.Index) && (aApiExtRef.Index <=
SAL_MAX_UINT16) )
1201 sal_uInt16 nFileId =
static_cast< sal_uInt16
>( aApiExtRef.Index );
1202 sheet::SingleReference aApiSRef;
1203 sheet::ComplexReference aApiCRef;
1205 if( aApiExtRef.Reference >>= aApiSRef )
1208 size_t nCacheId =
static_cast< size_t >( aApiSRef.Sheet );
1210 if( !aTabName.isEmpty() )
1214 lcl_ExternalRefToCalc( aSingleRef, aApiSRef );
1220 else if( aApiExtRef.Reference >>= aApiCRef )
1223 size_t nCacheId =
static_cast< size_t >( aApiCRef.Reference1.Sheet );
1225 if( !aTabName.isEmpty() )
1229 lcl_ExternalRefToCalc( aComplRef.
Ref1, aApiCRef.Reference1 );
1230 lcl_ExternalRefToCalc( aComplRef.
Ref2, aApiCRef.Reference2 );
1233 aComplRef.
Ref1.
Tab() +
static_cast<SCTAB>(aApiCRef.Reference2.Sheet - aApiCRef.Reference1.Sheet));
1239 else if( aApiExtRef.Reference >>= aName )
1241 if( !aName.isEmpty() )
1256 case uno::TypeClass_SEQUENCE:
1261 uno::Sequence< uno::Sequence< uno::Any >>>::
get()))
1282 #if HAVE_CPP_CONSTINIT_SORTED_VECTOR
1318 static const bool bThreadingProhibited = std::getenv(
"SC_NO_THREADED_CALCULATION");
1320 if (bThreadingProhibited)
1328 if (aThreadedCalcDenyList.find(eOp) != aThreadedCalcDenyList.end())
1331 <<
"(" <<
int(eOp) <<
") disables threaded calculation of formula group");
1346 <<
" disables threaded calculation of formula group");
1370 <<
"(" <<
int(eOp) <<
") disables vectorisation for formula group");
1555 <<
"(" <<
int(eOp) <<
") disables vectorisation for formula group");
1609 <<
"(" <<
int(eOp) <<
") disables vectorisation for formula group");
1645 <<
"(" <<
int(eOp) <<
") disables vectorisation for formula group");
1721 nVal += (size_t(rRef.
IsRowRel()) << 1);
1722 nVal += (size_t(rRef.
IsTabRel()) << 2);
1731 static const OUStringHash aHasher;
1737 sal_uInt16
n = std::min<sal_uInt16>(
nLen, 20);
1738 for (sal_uInt16 i = 0; i < n; ++i)
1752 nHash +=
static_cast<size_t>(nVal);
1759 nHash += std::hash<double>()(fVal);
1766 nHash += aHasher(aStr);
1778 size_t nVal1 = HashSingleRef(rRef.
Ref1);
1779 size_t nVal2 = HashSingleRef(rRef.
Ref2);
1786 nHash +=
static_cast<size_t>(eOp);
1791 nHash +=
static_cast<size_t>(eOp);
1793 nHash = (nHash << 4) - nHash;
1826 for (; p != pEnd; ++p)
1828 switch ((*p)->GetType())
1867 mxSheetLimits(&rDoc.GetSheetLimits()),
1874 mxSheetLimits(&rLimits),
1902 Move(std::move(rArr));
1914 for (sal_uInt16 i=0; i<
nLen; i++)
1916 if ( ppToken1[i] != ppToken2[i] &&
1917 !(*ppToken1[i] == *ppToken2[i]) )
1927 FormulaTokenArray::Clear();
1949 pp = p->pCode.get();
1951 for( sal_uInt16 i = 0; i <
nLen; i++, pp++ )
1953 *pp = (*pp)->
Clone();
1961 for( sal_uInt16 i = 0; i <
nRPN; i++, pp++ )
1967 sal_uInt16 nIdx = 0xFFFF;
1968 for( sal_uInt16 j = 0; j <
nLen; j++, p2++ )
1975 if( nIdx == 0xFFFF )
1978 *pp = p->pCode[ nIdx ];
2007 pp = aNew.
pCode.get();
2009 for( sal_uInt16 i = 0; i <
nLen; i++, pp++ )
2011 *pp = (*pp)->
Clone();
2019 for( sal_uInt16 i = 0; i <
nRPN; i++, pp++ )
2025 sal_uInt16 nIdx = 0xFFFF;
2026 for( sal_uInt16 j = 0; j <
nLen; j++, p2++ )
2033 if( nIdx == 0xFFFF )
2036 *pp = aNew.
pCode[ nIdx ];
2056 bool bResult = (bPrevWasSep == bNewVal);
2057 bPrevWasSep = bNewVal;
2063 int nCol = -1, nRow = 0;
2064 int i, nPrevRowSep = -1, nStart = 0;
2065 bool bPrevWasSep =
false;
2067 bool bNumeric =
false;
2071 for ( i =
nLen ; i-- > nStart ; )
2136 if( nPrevRowSep < 0 ||
2137 ((nPrevRowSep - i) % 2) == 1)
2144 nCol = (nPrevRowSep - i) / 2;
2146 else if( (nPrevRowSep - i)/2 != nCol)
2178 if( nCol <= 0 || nRow <= 0 )
2183 for ( i = nStart, nCol = 0, nRow = 0 ; i <
nLen ; i++ )
2232 nLen = sal_uInt16( nStart );
2240 sal_uInt16 nIdx =
nLen;
2325 sal_uInt16 nTokens = 1;
2329 if( !rFormulaNmsp.isEmpty() )
2333 Assign( nTokens, aTokens );
2346 nExtend = rPos.
Row();
2352 nExtend = rPos.
Col();
2353 nCol =
static_cast<SCCOL>(nExtend) + 1;
2356 if ( rPos.
Row() <= 0 )
2358 nExtend = rPos.
Row();
2362 if ( rPos.
Col() <= 0 )
2364 nExtend = rPos.
Col();
2365 nCol =
static_cast<SCCOL>(nExtend) - 1;
2368 OSL_FAIL(
"unknown Direction" );
2377 if ( nParamCount &&
nRPN > nParamCount )
2381 for ( ; nParam <
nRPN-1; nParam++ )
2393 if (aAbs.
Row() == nRow && aAbs.
Row() > nExtend)
2395 nExtend = aAbs.
Row();
2400 if (aAbs.
Col() == nCol &&
static_cast<SCCOLROW>(aAbs.
Col()) > nExtend)
2402 nExtend = aAbs.
Col();
2407 if (aAbs.
Row() == nRow && aAbs.
Row() < nExtend)
2409 nExtend = aAbs.
Row();
2414 if (aAbs.
Col() == nCol &&
static_cast<SCCOLROW>(aAbs.
Col()) < nExtend)
2416 nExtend = aAbs.
Col();
2475 void GetExternalTableData(
const ScDocument* pOldDoc,
const ScDocument* pNewDoc,
const SCTAB nTab, OUString& rTabName, sal_uInt16& rFileId)
2477 const OUString& aFileName = pOldDoc->
GetFileURL();
2480 if (rTabName.isEmpty())
2481 pOldDoc->
GetName(nTab, rTabName);
2520 if (bCheckCopyArea && IsInCopyRange(aRange, &rOldDoc))
2546 for ( sal_uInt16 j=0; j<
nLen; ++j )
2548 switch (
pCode[j]->GetType() )
2552 if (SkipReference(
pCode[j], rPos, rOldDoc, bRangeName,
true))
2563 GetExternalTableData(&rOldDoc, &rNewDoc, rRef1.
Tab(), aTabName, nFileId);
2572 if (SkipReference(
pCode[j], rPos, rOldDoc, bRangeName,
true))
2581 GetExternalTableData(&rOldDoc, &rNewDoc, rRef.
Tab(), aTabName, nFileId);
2597 bool bCheckCopyRange)
2600 for (
size_t j=0; j<2; ++j)
2604 for (; pp != pEnd; ++pp)
2614 if (!SkipReference(p, rOldPos, rOldDoc,
false, bCheckCopyRange))
2621 AdjustSingleRefData( rRef1, rOldPos, rNewPos );
2622 AdjustSingleRefData( rRef2, rOldPos, rNewPos );
2627 if (!SkipReference(p, rOldPos, rOldDoc,
false, bCheckCopyRange))
2632 AdjustSingleRefData( rRef, rOldPos, rNewPos );
2647 for (
size_t j=0; j<2; ++j)
2651 for (; pp != pEnd; ++pp)
2695 for (
size_t j=0; j<2; ++j)
2697 FormulaToken*
const * pp = aPtrs.maPointerRange[j].mpStart;
2698 FormulaToken*
const *
const pEnd = aPtrs.maPointerRange[j].mpStop;
2699 for (; pp != pEnd; ++pp)
2715 if (nTab1 <= nTab && nTab <= nTab2)
2724 if (rRef.
Tab() + nPosTab == nTab)
2729 if (rRef.
Tab() == nTab)
2782 return aSelectedRange;
2835 restoreDeletedRef(rRef.
Ref1, rCxt);
2836 restoreDeletedRef(rRef.
Ref2, rCxt);
3131 ScRange aSelectedRange = getSelectedRange(rCxt);
3141 assert(!
"can't move");
3146 for (
size_t j=0; j<2; ++j)
3150 for (; pp != pEnd; ++pp)
3166 setRefDeleted(rRef, rCxt);
3177 restoreDeletedRef(rRef, rCxt);
3204 setRefDeleted(rRef, rCxt);
3210 const ShrinkResult eSR = shrinkRange(rCxt, aAbs, aSelectedRange, rRef);
3219 else if (eSR == STICKY)
3244 if (aSelectedRange.
Contains(aCheckRange))
3247 restoreDeletedRef(rRef, rCxt);
3255 if (expandRange(rCxt, aAbs, aSelectedRange, rRef))
3264 if (expandRangeByEdge(rCxt, aAbs, aSelectedRange, rRef))
3328 if ((*pp)->GetType() ==
svIndex)
3330 switch ((*pp)->GetOpCode())
3334 SCTAB nOldTab = (*pp)->GetSheet();
3347 if (isDBDataModified(rCxt.
mrDoc, **pp))
3375 assert(!
"can't move");
3379 for (
size_t j=0; j<2; ++j)
3383 for (; pp != pEnd; ++pp)
3476 if ((*pp)->GetType() ==
svIndex)
3478 switch ((*pp)->GetOpCode())
3482 SCTAB nOldTab = (*pp)->GetSheet();
3489 if (isDBDataModified(rCxt.
mrDoc, **pp))
3506 for (
size_t j=0; j<2; ++j)
3510 for (; pp != pEnd; ++pp)
3523 if (aAbs.
Tab() == nTab && nRow1 <= aAbs.
Row() && aAbs.
Row() <= nRow2)
3527 if (it != rColMap.
end())
3530 SCCOL nNewCol = it->second;
3554 if (it != rColMap.
end())
3557 SCCOL nNewCol = it->second;
3575 for (
size_t j=0; j<2; ++j)
3579 for (; pp != pEnd; ++pp)
3592 if (aAbs.
Tab() == nTab && nCol1 <= aAbs.
Col() && aAbs.
Col() <= nCol2)
3596 if (it != rRowMap.
end())
3599 SCROW nNewRow = it->second;
3623 if (it != rRowMap.
end())
3626 SCROW nNewRow = it->second;
3643 bool adjustSingleRefInName(
3658 bool bChanged =
false;
3706 bool adjustDoubleRefInName(
3709 bool bRefChanged =
false;
3719 ScRange aSelectedRange = getSelectedRange(rCxt);
3736 ScRange aSelectedRange = getSelectedRange(rCxt);
3760 aCxt.mnRowDelta = 0;
3762 aCxt.mnColDelta = 0;
3763 if (!aCxt.mnColDelta && !aCxt.mnRowDelta && !aCxt.mnTabDelta)
3768 if (adjustSingleRefInName(rRef.
Ref2, aCxt, rPos, &rRef))
3771 if (adjustSingleRefInName(rRef.
Ref1, aCxt, rPos,
nullptr))
3777 if (adjustSingleRefInName(rRef.
Ref2, rCxt, rPos, &rRef))
3780 if (adjustSingleRefInName(rRef.
Ref1, rCxt, rPos,
nullptr))
3802 for (
size_t j=0; j<2; ++j)
3806 for (; pp != pEnd; ++pp)
3838 if (nDelStartRow <= aAbs.
Row() && aAbs.
Row() <= nDelEndRow)
3867 if (nDelStartCol <= aAbs.
Col() && aAbs.
Col() <= nDelEndCol)
3876 if (adjustSingleRefInName(rRef, rCxt, rPos,
nullptr))
3892 if (adjustDoubleRefInName(rRef, rCxt, rPos))
4011 if (adjustDoubleRefInName(rRef, rCxt, rPos))
4016 if (adjustDoubleRefInName(rRef, rCxt, rPos))
4068 assert(!
"can't move");
4077 for (
size_t j=0; j<2; ++j)
4081 for (; pp != pEnd; ++pp)
4152 if (nDelPos <= aAbs.
Tab() && aAbs.
Tab() < nDelPos + nSheets)
4158 if (nDelPos < aAbs.
Tab())
4165 else if (rOldPos.
Tab() != rNewPos.
Tab())
4178 if (nInsPos <= aAbs.
Tab())
4185 else if (rOldPos.
Tab() != rNewPos.
Tab())
4201 bool bMoreThanOneTab = aStartPos.
Tab() != aEndPos.
Tab();
4202 bool bModified =
false;
4203 if (bMoreThanOneTab && aStartPos.
Tab() == nDelPos && nDelPos + nSheets <= aEndPos.
Tab())
4213 bModified = adjustSingleRefOnDeletedTab(rLimits, rRef1, nDelPos, nSheets, rOldPos, rNewPos);
4216 if (bMoreThanOneTab && aEndPos.
Tab() == nDelPos && aStartPos.
Tab() <= nDelPos - nSheets)
4226 bModified |= adjustSingleRefOnDeletedTab(rLimits, rRef2, nDelPos, nSheets, rOldPos, rNewPos);
4241 for (
size_t j=0; j<2; ++j)
4245 for (; pp != pEnd; ++pp)
4272 if ((*pp)->GetType() ==
svIndex)
4274 switch ((*pp)->GetOpCode())
4278 SCTAB nOldTab = (*pp)->GetSheet();
4285 (*pp)->SetSheet( nOldTab - rCxt.
mnSheets);
4294 if (isDBDataModified(rCxt.
mrDoc, **pp))
4314 for (
size_t j=0; j<2; ++j)
4318 for (; pp != pEnd; ++pp)
4348 if ((*pp)->GetType() ==
svIndex)
4350 switch ((*pp)->GetOpCode())
4354 SCTAB nOldTab = (*pp)->GetSheet();
4360 (*pp)->SetSheet( nOldTab + rCxt.
mnSheets);
4366 if (isDBDataModified(rCxt.
mrDoc, **pp))
4383 if (nNewTab == rPos.
Tab())