summaryrefslogtreecommitdiffstats
path: root/editeng
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2017-04-26 18:07:42 +0200
committerEike Rathke <erack@redhat.com>2017-04-26 18:08:07 +0200
commitd57ba3fb9076b46b4aa10468bad1f96a6bee87d8 (patch)
treec79fdff7c111313168c1bcdc9c1f7dede726f41f /editeng
parentHack-around an unclear Windows problem in the test. (diff)
downloadcore-d57ba3fb9076b46b4aa10468bad1f96a6bee87d8.tar.gz
core-d57ba3fb9076b46b4aa10468bad1f96a6bee87d8.zip
check all ParaPortionList::SafeGetObject() return values for nullptr
Change-Id: I46fdd613c9ad3762f045f984caff2a8dbef9bf16
Diffstat (limited to 'editeng')
-rw-r--r--editeng/source/editeng/impedit.cxx39
-rw-r--r--editeng/source/editeng/impedit2.cxx227
-rw-r--r--editeng/source/editeng/impedit3.cxx16
-rw-r--r--editeng/source/editeng/impedit5.cxx2
4 files changed, 165 insertions, 119 deletions
diff --git a/editeng/source/editeng/impedit.cxx b/editeng/source/editeng/impedit.cxx
index 43cb55259fb9..5f29334efd9a 100644
--- a/editeng/source/editeng/impedit.cxx
+++ b/editeng/source/editeng/impedit.cxx
@@ -253,7 +253,12 @@ void ImpEditView::DrawSelection( EditSelection aTmpSel, vcl::Region* pRegion, Ou
for ( sal_Int32 nPara = nStartPara; nPara <= nEndPara; nPara++ )
{
ParaPortion* pTmpPortion = pEditEngine->GetParaPortions().SafeGetObject( nPara );
- DBG_ASSERT( pTmpPortion, "Portion in Selection not found!" );
+ if (!pTmpPortion)
+ {
+ SAL_WARN( "editeng", "Portion in Selection not found!" );
+ continue;
+ }
+
DBG_ASSERT( !pTmpPortion->IsInvalid(), "Portion in Selection not formatted!" );
if ( !pTmpPortion->IsVisible() || pTmpPortion->IsInvalid() )
@@ -2087,21 +2092,24 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD
{
sal_Int32 nPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() );
ParaPortion* pPPortion = pEditEngine->GetParaPortions().SafeGetObject( nPara );
- long nDestParaStartY = pEditEngine->GetParaPortions().GetYOffset( pPPortion );
- long nRel = aDocPos.Y() - nDestParaStartY;
- if ( nRel < ( pPPortion->GetHeight() / 2 ) )
+ if (pPPortion)
{
- pDragAndDropInfo->nOutlinerDropDest = nPara;
- }
- else
- {
- pDragAndDropInfo->nOutlinerDropDest = nPara+1;
- }
+ long nDestParaStartY = pEditEngine->GetParaPortions().GetYOffset( pPPortion );
+ long nRel = aDocPos.Y() - nDestParaStartY;
+ if ( nRel < ( pPPortion->GetHeight() / 2 ) )
+ {
+ pDragAndDropInfo->nOutlinerDropDest = nPara;
+ }
+ else
+ {
+ pDragAndDropInfo->nOutlinerDropDest = nPara+1;
+ }
- if( ( pDragAndDropInfo->nOutlinerDropDest >= pDragAndDropInfo->aBeginDragSel.nStartPara ) &&
- ( pDragAndDropInfo->nOutlinerDropDest <= (pDragAndDropInfo->aBeginDragSel.nEndPara+1) ) )
- {
- bAccept = false;
+ if( ( pDragAndDropInfo->nOutlinerDropDest >= pDragAndDropInfo->aBeginDragSel.nStartPara ) &&
+ ( pDragAndDropInfo->nOutlinerDropDest <= (pDragAndDropInfo->aBeginDragSel.nEndPara+1) ) )
+ {
+ bAccept = false;
+ }
}
}
else if ( HasSelection() )
@@ -2125,7 +2133,8 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD
if ( pDragAndDropInfo->nOutlinerDropDest < pEditEngine->GetEditDoc().Count() )
{
ParaPortion* pPPortion = pEditEngine->GetParaPortions().SafeGetObject( pDragAndDropInfo->nOutlinerDropDest );
- nDDYPos = pEditEngine->GetParaPortions().GetYOffset( pPPortion );
+ if (pPPortion)
+ nDDYPos = pEditEngine->GetParaPortions().GetYOffset( pPPortion );
}
else
{
diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx
index 71295dfe7022..0d53cbf3e3a8 100644
--- a/editeng/source/editeng/impedit2.cxx
+++ b/editeng/source/editeng/impedit2.cxx
@@ -491,13 +491,16 @@ void ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView )
FormatDoc();
ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( GetEditDoc().GetPos( aPaM.GetNode() ) );
- sal_Int32 nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), true );
- const EditLine& rLine = pParaPortion->GetLines()[nLine];
- if ( nInputEnd > rLine.GetEnd() )
- nInputEnd = rLine.GetEnd();
- tools::Rectangle aR2 = PaMtoEditCursor( EditPaM( aPaM.GetNode(), nInputEnd ), GetCursorFlags::EndOfLine );
- tools::Rectangle aRect = pView->GetImpEditView()->GetWindowPos( aR1 );
- pView->GetWindow()->SetCursorRect( &aRect, aR2.Left()-aR1.Right() );
+ if (pParaPortion)
+ {
+ sal_Int32 nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), true );
+ const EditLine& rLine = pParaPortion->GetLines()[nLine];
+ if ( nInputEnd > rLine.GetEnd() )
+ nInputEnd = rLine.GetEnd();
+ tools::Rectangle aR2 = PaMtoEditCursor( EditPaM( aPaM.GetNode(), nInputEnd ), GetCursorFlags::EndOfLine );
+ tools::Rectangle aRect = pView->GetImpEditView()->GetWindowPos( aR1 );
+ pView->GetWindow()->SetCursorRect( &aRect, aR2.Left()-aR1.Right() );
+ }
}
else
{
@@ -549,18 +552,21 @@ void ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView )
FormatDoc();
ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( GetEditDoc().GetPos( aPaM.GetNode() ) );
- sal_Int32 nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), true );
- const EditLine& rLine = pParaPortion->GetLines()[nLine];
- std::unique_ptr<tools::Rectangle[]> aRects(new tools::Rectangle[ mpIMEInfos->nLen ]);
- for (sal_Int32 i = 0; i < mpIMEInfos->nLen; ++i)
+ if (pParaPortion)
{
- sal_Int32 nInputPos = mpIMEInfos->aPos.GetIndex() + i;
- if ( nInputPos > rLine.GetEnd() )
- nInputPos = rLine.GetEnd();
- tools::Rectangle aR2 = GetEditCursor( pParaPortion, nInputPos );
- aRects[ i ] = pView->GetImpEditView()->GetWindowPos( aR2 );
+ sal_Int32 nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), true );
+ const EditLine& rLine = pParaPortion->GetLines()[nLine];
+ std::unique_ptr<tools::Rectangle[]> aRects(new tools::Rectangle[ mpIMEInfos->nLen ]);
+ for (sal_Int32 i = 0; i < mpIMEInfos->nLen; ++i)
+ {
+ sal_Int32 nInputPos = mpIMEInfos->aPos.GetIndex() + i;
+ if ( nInputPos > rLine.GetEnd() )
+ nInputPos = rLine.GetEnd();
+ tools::Rectangle aR2 = GetEditCursor( pParaPortion, nInputPos );
+ aRects[ i ] = pView->GetImpEditView()->GetWindowPos( aR2 );
+ }
+ pView->GetWindow()->SetCompositionCharRect( aRects.get(), mpIMEInfos->nLen );
}
- pView->GetWindow()->SetCompositionCharRect( aRects.get(), mpIMEInfos->nLen );
}
}
@@ -926,6 +932,8 @@ EditPaM ImpEditEngine::CursorVisualStartEnd( EditView* pEditView, const EditPaM&
sal_Int32 nPara = GetEditDoc().GetPos( aPaM.GetNode() );
ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
+ if (!pParaPortion)
+ return aPaM;
sal_Int32 nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), false );
const EditLine& rLine = pParaPortion->GetLines()[nLine];
@@ -981,6 +989,8 @@ EditPaM ImpEditEngine::CursorVisualLeftRight( EditView* pEditView, const EditPaM
sal_Int32 nPara = GetEditDoc().GetPos( aPaM.GetNode() );
ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
+ if (!pParaPortion)
+ return aPaM;
sal_Int32 nLine = pParaPortion->GetLines().FindLine( aPaM.GetIndex(), false );
const EditLine& rLine = pParaPortion->GetLines()[nLine];
@@ -1361,6 +1371,8 @@ EditPaM ImpEditEngine::CursorEndOfDoc()
ContentNode* pLastNode = aEditDoc.GetObject( aEditDoc.Count()-1 );
ParaPortion* pLastPortion = GetParaPortions().SafeGetObject( aEditDoc.Count()-1 );
OSL_ENSURE( pLastNode && pLastPortion, "CursorEndOfDoc: Node or Portion not found" );
+ if (!(pLastNode && pLastPortion))
+ return EditPaM();
if ( !pLastPortion->IsVisible() )
{
@@ -1598,6 +1610,9 @@ static bool lcl_HasStrongLTR ( const OUString& rTxt, sal_Int32 nStart, sal_Int3
void ImpEditEngine::InitScriptTypes( sal_Int32 nPara )
{
ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
+ if (!pParaPortion)
+ return;
+
ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
rTypes.clear();
@@ -1792,6 +1807,9 @@ SvtScriptType ImpEditEngine::GetItemScriptType( const EditSelection& rSel ) cons
for ( sal_Int32 nPara = nStartPara; nPara <= nEndPara; nPara++ )
{
const ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
+ if (!pParaPortion)
+ continue;
+
if ( pParaPortion->aScriptInfos.empty() )
const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara );
@@ -1836,17 +1854,20 @@ bool ImpEditEngine::IsScriptChange( const EditPaM& rPaM ) const
{
sal_Int32 nPara = GetEditDoc().GetPos( rPaM.GetNode() );
const ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
- if ( pParaPortion->aScriptInfos.empty() )
- const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara );
-
- const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
- const sal_Int32 nPos = rPaM.GetIndex();
- for (const ScriptTypePosInfo & rType : rTypes)
+ if (pParaPortion)
{
- if ( rType.nStartPos == nPos )
- {
- bScriptChange = true;
- break;
+ if ( pParaPortion->aScriptInfos.empty() )
+ const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara );
+
+ const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
+ const sal_Int32 nPos = rPaM.GetIndex();
+ for (const ScriptTypePosInfo & rType : rTypes)
+ {
+ if ( rType.nStartPos == nPos )
+ {
+ bScriptChange = true;
+ break;
+ }
}
}
}
@@ -1858,14 +1879,17 @@ bool ImpEditEngine::HasScriptType( sal_Int32 nPara, sal_uInt16 nType ) const
bool bTypeFound = false;
const ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
- if ( pParaPortion->aScriptInfos.empty() )
- const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara );
-
- const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
- for ( size_t n = rTypes.size(); n && !bTypeFound; )
+ if (pParaPortion)
{
- if ( rTypes[--n].nScriptType == nType )
+ if ( pParaPortion->aScriptInfos.empty() )
+ const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara );
+
+ const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos;
+ for ( size_t n = rTypes.size(); n && !bTypeFound; )
+ {
+ if ( rTypes[--n].nScriptType == nType )
bTypeFound = true;
+ }
}
return bTypeFound;
}
@@ -1873,6 +1897,9 @@ bool ImpEditEngine::HasScriptType( sal_Int32 nPara, sal_uInt16 nType ) const
void ImpEditEngine::InitWritingDirections( sal_Int32 nPara )
{
ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
+ if (!pParaPortion)
+ return;
+
WritingDirectionInfos& rInfos = pParaPortion->aWritingDirectionInfos;
rInfos.clear();
@@ -1961,19 +1988,21 @@ bool ImpEditEngine::IsRightToLeft( sal_Int32 nPara ) const
bool ImpEditEngine::HasDifferentRTLLevels( const ContentNode* pNode )
{
- sal_Int32 nPara = GetEditDoc().GetPos( pNode );
- ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
-
bool bHasDifferentRTLLevels = false;
- sal_uInt16 nRTLLevel = IsRightToLeft( nPara ) ? 1 : 0;
- for ( sal_Int32 n = 0; n < pParaPortion->GetTextPortions().Count(); n++ )
+ sal_Int32 nPara = GetEditDoc().GetPos( pNode );
+ ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
+ if (pParaPortion)
{
- const TextPortion& rTextPortion = pParaPortion->GetTextPortions()[n];
- if ( rTextPortion.GetRightToLeftLevel() != nRTLLevel )
+ sal_uInt16 nRTLLevel = IsRightToLeft( nPara ) ? 1 : 0;
+ for ( sal_Int32 n = 0; n < pParaPortion->GetTextPortions().Count(); n++ )
{
- bHasDifferentRTLLevels = true;
- break;
+ const TextPortion& rTextPortion = pParaPortion->GetTextPortions()[n];
+ if ( rTextPortion.GetRightToLeftLevel() != nRTLLevel )
+ {
+ bHasDifferentRTLLevels = true;
+ break;
+ }
}
}
return bHasDifferentRTLLevels;
@@ -1988,20 +2017,23 @@ sal_uInt8 ImpEditEngine::GetRightToLeft( sal_Int32 nPara, sal_Int32 nPos, sal_In
if ( pNode && pNode->Len() )
{
ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara );
- if ( pParaPortion->aWritingDirectionInfos.empty() )
- InitWritingDirections( nPara );
-
- WritingDirectionInfos& rDirInfos = pParaPortion->aWritingDirectionInfos;
- for (const WritingDirectionInfo & rDirInfo : rDirInfos)
+ if (pParaPortion)
{
- if ( ( rDirInfo.nStartPos <= nPos ) && ( rDirInfo.nEndPos >= nPos ) )
+ if ( pParaPortion->aWritingDirectionInfos.empty() )
+ InitWritingDirections( nPara );
+
+ WritingDirectionInfos& rDirInfos = pParaPortion->aWritingDirectionInfos;
+ for (const WritingDirectionInfo & rDirInfo : rDirInfos)
{
- nRightToLeft = rDirInfo.nType;
- if ( pStart )
- *pStart = rDirInfo.nStartPos;
- if ( pEnd )
- *pEnd = rDirInfo.nEndPos;
- break;
+ if ( ( rDirInfo.nStartPos <= nPos ) && ( rDirInfo.nEndPos >= nPos ) )
+ {
+ nRightToLeft = rDirInfo.nType;
+ if ( pStart )
+ *pStart = rDirInfo.nStartPos;
+ if ( pEnd )
+ *pEnd = rDirInfo.nEndPos;
+ break;
+ }
}
}
}
@@ -4074,54 +4106,57 @@ void ImpEditEngine::CalcHeight( ParaPortion* pPortion )
if ( nPortion && !aStatus.ULSpaceSummation() )
{
ParaPortion* pPrev = GetParaPortions().SafeGetObject( nPortion-1 );
- const SvxULSpaceItem& rPrevULItem = static_cast<const SvxULSpaceItem&>(pPrev->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE ));
- const SvxLineSpacingItem& rPrevLSItem = static_cast<const SvxLineSpacingItem&>(pPrev->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ));
+ if (pPrev)
+ {
+ const SvxULSpaceItem& rPrevULItem = static_cast<const SvxULSpaceItem&>(pPrev->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE ));
+ const SvxLineSpacingItem& rPrevLSItem = static_cast<const SvxLineSpacingItem&>(pPrev->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ));
- // In relation between WinWord6/Writer3:
- // With a proportional line spacing the paragraph spacing is
- // also manipulated.
- // Only Writer3: Do not add up, but minimum distance.
+ // In relation between WinWord6/Writer3:
+ // With a proportional line spacing the paragraph spacing is
+ // also manipulated.
+ // Only Writer3: Do not add up, but minimum distance.
- // check if distance by LineSpacing > Upper:
- sal_uInt16 nExtraSpace = GetYValue( lcl_CalcExtraSpace( pPortion, rLSItem ) );
- if ( nExtraSpace > pPortion->nFirstLineOffset )
- {
- // Paragraph becomes 'bigger':
- pPortion->nHeight += ( nExtraSpace - pPortion->nFirstLineOffset );
- pPortion->nFirstLineOffset = nExtraSpace;
- }
+ // check if distance by LineSpacing > Upper:
+ sal_uInt16 nExtraSpace = GetYValue( lcl_CalcExtraSpace( pPortion, rLSItem ) );
+ if ( nExtraSpace > pPortion->nFirstLineOffset )
+ {
+ // Paragraph becomes 'bigger':
+ pPortion->nHeight += ( nExtraSpace - pPortion->nFirstLineOffset );
+ pPortion->nFirstLineOffset = nExtraSpace;
+ }
- // Determine nFirstLineOffset now f(pNode) => now f(pNode, pPrev):
- sal_uInt16 nPrevLower = GetYValue( rPrevULItem.GetLower() );
+ // Determine nFirstLineOffset now f(pNode) => now f(pNode, pPrev):
+ sal_uInt16 nPrevLower = GetYValue( rPrevULItem.GetLower() );
- // This PrevLower is still in the height of PrevPortion ...
- if ( nPrevLower > pPortion->nFirstLineOffset )
- {
- // Paragraph is 'small':
- pPortion->nHeight -= pPortion->nFirstLineOffset;
- pPortion->nFirstLineOffset = 0;
- }
- else if ( nPrevLower )
- {
- // Paragraph becomes 'somewhat smaller':
- pPortion->nHeight -= nPrevLower;
- pPortion->nFirstLineOffset =
- pPortion->nFirstLineOffset - nPrevLower;
- }
- // I find it not so good, but Writer3 feature:
- // Check if distance by LineSpacing > Lower: this value is not
- // stuck in the height of PrevPortion.
- if ( !pPrev->IsInvalid() )
- {
- nExtraSpace = GetYValue( lcl_CalcExtraSpace( pPrev, rPrevLSItem ) );
- if ( nExtraSpace > nPrevLower )
+ // This PrevLower is still in the height of PrevPortion ...
+ if ( nPrevLower > pPortion->nFirstLineOffset )
+ {
+ // Paragraph is 'small':
+ pPortion->nHeight -= pPortion->nFirstLineOffset;
+ pPortion->nFirstLineOffset = 0;
+ }
+ else if ( nPrevLower )
{
- sal_uInt16 nMoreLower = nExtraSpace - nPrevLower;
- // Paragraph becomes 'bigger', 'grows' downwards:
- if ( nMoreLower > pPortion->nFirstLineOffset )
+ // Paragraph becomes 'somewhat smaller':
+ pPortion->nHeight -= nPrevLower;
+ pPortion->nFirstLineOffset =
+ pPortion->nFirstLineOffset - nPrevLower;
+ }
+ // I find it not so good, but Writer3 feature:
+ // Check if distance by LineSpacing > Lower: this value is not
+ // stuck in the height of PrevPortion.
+ if ( !pPrev->IsInvalid() )
+ {
+ nExtraSpace = GetYValue( lcl_CalcExtraSpace( pPrev, rPrevLSItem ) );
+ if ( nExtraSpace > nPrevLower )
{
- pPortion->nHeight += ( nMoreLower - pPortion->nFirstLineOffset );
- pPortion->nFirstLineOffset = nMoreLower;
+ sal_uInt16 nMoreLower = nExtraSpace - nPrevLower;
+ // Paragraph becomes 'bigger', 'grows' downwards:
+ if ( nMoreLower > pPortion->nFirstLineOffset )
+ {
+ pPortion->nHeight += ( nMoreLower - pPortion->nFirstLineOffset );
+ pPortion->nFirstLineOffset = nMoreLower;
+ }
}
}
}
diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx
index 462229e2f25e..b9808e3c4a5f 100644
--- a/editeng/source/editeng/impedit3.cxx
+++ b/editeng/source/editeng/impedit3.cxx
@@ -3981,14 +3981,16 @@ EditSelection ImpEditEngine::MoveParagraphs( Range aOldPositions, sal_Int32 nNew
ParaPortion* pUpperPortion = GetParaPortions().SafeGetObject( nFirstPortion );
ParaPortion* pLowerPortion = GetParaPortions().SafeGetObject( nLastPortion );
+ if (pUpperPortion && pLowerPortion)
+ {
+ aInvalidRect = tools::Rectangle(); // make empty
+ aInvalidRect.Left() = 0;
+ aInvalidRect.Right() = aPaperSize.Width();
+ aInvalidRect.Top() = GetParaPortions().GetYOffset( pUpperPortion );
+ aInvalidRect.Bottom() = GetParaPortions().GetYOffset( pLowerPortion ) + pLowerPortion->GetHeight();
- aInvalidRect = tools::Rectangle(); // make empty
- aInvalidRect.Left() = 0;
- aInvalidRect.Right() = aPaperSize.Width();
- aInvalidRect.Top() = GetParaPortions().GetYOffset( pUpperPortion );
- aInvalidRect.Bottom() = GetParaPortions().GetYOffset( pLowerPortion ) + pLowerPortion->GetHeight();
-
- UpdateViews( pCurView );
+ UpdateViews( pCurView );
+ }
}
else
{
diff --git a/editeng/source/editeng/impedit5.cxx b/editeng/source/editeng/impedit5.cxx
index 62fec10b9244..2dbebccfe6c5 100644
--- a/editeng/source/editeng/impedit5.cxx
+++ b/editeng/source/editeng/impedit5.cxx
@@ -657,7 +657,7 @@ void ImpEditEngine::RemoveCharAttribs( sal_Int32 nPara, sal_uInt16 nWhich, bool
DBG_ASSERT( pNode, "Node not found: RemoveCharAttribs" );
DBG_ASSERT( pPortion, "Portion not found: RemoveCharAttribs" );
- if ( !pNode )
+ if ( !pNode || !pPortion )
return;
size_t nAttr = 0;