[Libreoffice-commits] core.git: 7 commits - sw/inc sw/source
Michael Stahl
mstahl at redhat.com
Fri Feb 15 13:46:58 PST 2013
sw/inc/ndtxt.hxx | 12 +++++
sw/source/core/doc/doc.cxx | 19 ++++----
sw/source/core/doc/docedt.cxx | 19 +++++++-
sw/source/core/doc/doclay.cxx | 17 ++++++-
sw/source/core/docnode/node.cxx | 36 ++++++++++------
sw/source/core/txtnode/ndtxt.cxx | 63 ++++++++++++++++++++--------
sw/source/core/txtnode/thints.cxx | 25 ++++++++++-
sw/source/core/txtnode/txtedt.cxx | 17 ++++++-
sw/source/core/undo/undel.cxx | 10 ++--
sw/source/core/undo/unins.cxx | 25 ++++-------
sw/source/core/undo/unovwr.cxx | 14 ++++--
sw/source/filter/xml/xmltbli.cxx | 83 ++++++++++++++++++++++++++++----------
sw/source/filter/xml/xmltbli.hxx | 2
13 files changed, 245 insertions(+), 97 deletions(-)
New commits:
commit 1b5839f49c07beb6fbde6c7370a5636d22f9ab77
Author: Michael Stahl <mstahl at redhat.com>
Date: Fri Feb 15 22:36:55 2013 +0100
fdo#60842: sw ODF import: support value-type="string" on cells:
According to ODF 1.2 part 1 19.385 office:value-type, the attributes of
table:table-cell, namely office:value-type="string" and
office:string-value="foo", should override the element content of the
cell.
Change-Id: Ic580307effb046d127c4d64a4f963f0e91b3a2d1
diff --git a/sw/source/filter/xml/xmltbli.cxx b/sw/source/filter/xml/xmltbli.cxx
index 378a307..d35254d 100644
--- a/sw/source/filter/xml/xmltbli.cxx
+++ b/sw/source/filter/xml/xmltbli.cxx
@@ -95,6 +95,7 @@ enum SwXMLTableCellAttrTokens
XML_TOK_TABLE_BOOLEAN_VALUE,
XML_TOK_TABLE_PROTECTED,
XML_TOK_TABLE_STRING_VALUE,
+ XML_TOK_TABLE_VALUE_TYPE,
XML_TOK_TABLE_CELL_ATTR_END=XML_TOK_UNKNOWN
};
@@ -136,6 +137,7 @@ static SvXMLTokenMapEntry aTableCellAttrTokenMap[] =
{ XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TOK_TABLE_PROTECTED },
{ XML_NAMESPACE_TABLE, XML_PROTECT, XML_TOK_TABLE_PROTECTED }, // for backwards compatibility with SRC629 (and before)
{ XML_NAMESPACE_OFFICE, XML_STRING_VALUE, XML_TOK_TABLE_STRING_VALUE },
+ { XML_NAMESPACE_OFFICE, XML_VALUE_TYPE, XML_TOK_TABLE_VALUE_TYPE },
XML_TOKEN_MAP_END
};
@@ -162,6 +164,7 @@ class SwXMLTableCell_Impl
OUString aStyleName;
OUString mXmlId;
+ OUString m_StringValue;
OUString sFormula; // cell formula; valid if length > 0
double dValue; // formula value
@@ -175,7 +178,7 @@ class SwXMLTableCell_Impl
sal_Bool bProtected : 1;
sal_Bool bHasValue; // determines whether dValue attribute is valid
sal_Bool mbCovered;
- sal_Bool mbTextValue;
+ bool m_bHasStringValue;
public:
@@ -185,18 +188,19 @@ public:
nColSpan( nCSpan ),
bProtected( sal_False ),
mbCovered( sal_False )
+ , m_bHasStringValue(false)
{}
inline void Set( const OUString& rStyleName,
sal_uInt32 nRSpan, sal_uInt32 nCSpan,
const SwStartNode *pStNd, SwXMLTableContext *pTable,
- sal_Bool bProtect = sal_False,
- const OUString* pFormula = NULL,
- sal_Bool bHasValue = sal_False,
- sal_Bool mbCovered = sal_False,
- double dVal = 0.0,
- sal_Bool mbTextValue = sal_False,
- OUString const& i_rXmlId = OUString());
+ sal_Bool bProtect,
+ const OUString* pFormula,
+ sal_Bool bHasValue,
+ sal_Bool bCovered,
+ double dVal,
+ OUString const*const pStringValue,
+ OUString const& i_rXmlId);
bool IsUsed() const { return pStartNode!=0 ||
xSubTable.Is() || bProtected;}
@@ -210,7 +214,10 @@ public:
sal_Bool HasValue() const { return bHasValue; }
sal_Bool IsProtected() const { return bProtected; }
sal_Bool IsCovered() const { return mbCovered; }
- sal_Bool HasTextValue() const { return mbTextValue; }
+ bool HasStringValue() const { return m_bHasStringValue; }
+ OUString const* GetStringValue() const {
+ return (m_bHasStringValue) ? &m_StringValue : 0;
+ }
const OUString& GetXmlId() const { return mXmlId; }
const SwStartNode *GetStartNode() const { return pStartNode; }
@@ -230,7 +237,7 @@ inline void SwXMLTableCell_Impl::Set( const OUString& rStyleName,
sal_Bool bHasVal,
sal_Bool bCov,
double dVal,
- sal_Bool bTextVal,
+ OUString const*const pStringValue,
OUString const& i_rXmlId )
{
aStyleName = rStyleName;
@@ -241,7 +248,11 @@ inline void SwXMLTableCell_Impl::Set( const OUString& rStyleName,
dValue = dVal;
bHasValue = bHasVal;
mbCovered = bCov;
- mbTextValue = bTextVal;
+ if (pStringValue)
+ {
+ m_StringValue = *pStringValue;
+ }
+ m_bHasStringValue = (pStringValue != 0);
bProtected = bProtect;
if (!mbCovered) // ensure uniqueness
@@ -396,12 +407,14 @@ class SwXMLTableCellContext_Impl : public SvXMLImportContext
OUString sFormula;
OUString sSaveParaDefault;
OUString mXmlId;
+ OUString m_StringValue;
SvXMLImportContextRef xMyTable;
double fValue;
sal_Bool bHasValue;
- sal_Bool bHasTextValue;
+ bool m_bHasStringValue;
+ bool m_bValueTypeIsString;
sal_Bool bProtect;
sal_uInt32 nRowSpan;
@@ -445,7 +458,8 @@ SwXMLTableCellContext_Impl::SwXMLTableCellContext_Impl(
xMyTable( pTable ),
fValue( 0.0 ),
bHasValue( sal_False ),
- bHasTextValue( sal_False ),
+ m_bHasStringValue(false),
+ m_bValueTypeIsString(false),
bProtect( sal_False ),
nRowSpan( 1UL ),
nColSpan( 1UL ),
@@ -550,7 +564,19 @@ SwXMLTableCellContext_Impl::SwXMLTableCellContext_Impl(
break;
case XML_TOK_TABLE_STRING_VALUE:
{
- bHasTextValue = sal_True;
+ m_StringValue = rValue;
+ m_bHasStringValue = true;
+ }
+ break;
+ case XML_TOK_TABLE_VALUE_TYPE:
+ {
+ if ("string" == rValue)
+ {
+ m_bValueTypeIsString = true;
+ }
+ // ignore other types - it would be correct to require
+ // matching value-type and $type-value attributes,
+ // but we've been reading those without checking forever.
}
break;
}
@@ -566,7 +592,8 @@ inline void SwXMLTableCellContext_Impl::_InsertContent()
GetTable()->InsertCell( aStyleName, nRowSpan, nColSpan,
GetTable()->InsertTableSection(),
mXmlId,
- NULL, bProtect, &sFormula, bHasValue, fValue, bHasTextValue );
+ NULL, bProtect, &sFormula, bHasValue, fValue,
+ (m_bHasStringValue && m_bValueTypeIsString) ? &m_StringValue : 0);
}
inline void SwXMLTableCellContext_Impl::InsertContent()
@@ -643,9 +670,13 @@ SvXMLImportContext *SwXMLTableCellContext_Impl::CreateChildContext(
{
if( GetTable()->IsValid() )
InsertContentIfNotThere();
- pContext = GetImport().GetTextImport()->CreateTextChildContext(
+ // fdo#60842: "office:string-value" overrides text content -> no import
+ if (!(m_bValueTypeIsString && m_bHasStringValue))
+ {
+ pContext = GetImport().GetTextImport()->CreateTextChildContext(
GetImport(), nPrefix, rLocalName, xAttrList,
XML_TEXT_TYPE_CELL );
+ }
}
if( !pContext )
@@ -1579,7 +1610,7 @@ void SwXMLTableContext::InsertCell( const OUString& rStyleName,
const OUString* pFormula,
sal_Bool bHasValue,
double fValue,
- sal_Bool bTextValue )
+ OUString const*const pStringValue )
{
OSL_ENSURE( nCurCol < GetColumnCount(),
"SwXMLTableContext::InsertCell: row is full" );
@@ -1673,7 +1704,7 @@ void SwXMLTableContext::InsertCell( const OUString& rStyleName,
GetCell( nRowsReq-j, nColsReq-i )
->Set( sStyleName, j, i, pStartNode,
pTable, bProtect, pFormula, bHasValue, bCovered, fValue,
- bTextValue, i_rXmlId );
+ pStringValue, i_rXmlId );
}
}
@@ -1742,7 +1773,7 @@ void SwXMLTableContext::InsertRepRows( sal_uInt32 nCount )
0, pSrcCell->IsProtected(),
&pSrcCell->GetFormula(),
pSrcCell->HasValue(), pSrcCell->GetValue(),
- pSrcCell->HasTextValue() );
+ pSrcCell->GetStringValue() );
}
}
FinishRow();
@@ -2076,6 +2107,18 @@ SwTableBox *SwXMLTableContext::MakeTableBox(
if( pCell->GetStartNode() )
{
+ if (pCell->HasStringValue())
+ {
+ SwNodeIndex const aNodeIndex(*(pCell->GetStartNode()), 1);
+ SwTxtNode *const pTxtNode(aNodeIndex.GetNode().GetTxtNode());
+ SAL_WARN_IF(!pTxtNode, "sw", "Should have a text node in cell?");
+ if (pTxtNode)
+ {
+ SAL_WARN_IF(pTxtNode->GetTxt().Len(), "sw", "why text here?");
+ pTxtNode->InsertText(*pCell->GetStringValue(),
+ SwIndex(pTxtNode, 0));
+ }
+ }
// try to rescue broken documents with a certain pattern
// if: 1) the cell has a default number format (number 0)
@@ -2139,7 +2182,7 @@ SwTableBox *SwXMLTableContext::MakeTableBox(
SwTblBoxFormula aFormulaItem( rFormula );
pBoxFmt2->SetFmtAttr( aFormulaItem );
}
- else if( !pCell->HasValue() && pCell->HasTextValue() )
+ else if (!pCell->HasValue() && pCell->HasStringValue())
{
// Check for another inconsistency:
// No value but a non-textual format, i.e. a number format
diff --git a/sw/source/filter/xml/xmltbli.hxx b/sw/source/filter/xml/xmltbli.hxx
index 06329c5..f6d9da9 100644
--- a/sw/source/filter/xml/xmltbli.hxx
+++ b/sw/source/filter/xml/xmltbli.hxx
@@ -177,7 +177,7 @@ public:
const ::rtl::OUString *pFormula=0,
sal_Bool bHasValue = sal_False,
double fValue = 0.0,
- sal_Bool bTextValue = sal_False );
+ ::rtl::OUString const*const pStringValue = 0);
void InsertRow( const ::rtl::OUString& rStyleName,
const ::rtl::OUString& rDfltCellStyleName,
bool bInHead,
commit 0e49d87d92a3f1aeeeda547f1a7e710dcd4fee95
Author: Michael Stahl <mstahl at redhat.com>
Date: Fri Feb 15 16:27:34 2013 +0100
fdo#60732: check max size in SwTxtNode::ReplaceTextOnly
Change-Id: I1ca2075ab99fe1b09df700f55645b44f38cf5bcc
diff --git a/sw/source/core/txtnode/txtedt.cxx b/sw/source/core/txtnode/txtedt.cxx
index 3c8503b..40327cb 100644
--- a/sw/source/core/txtnode/txtedt.cxx
+++ b/sw/source/core/txtnode/txtedt.cxx
@@ -1799,9 +1799,19 @@ void SwTxtNode::TransliterateText(
{
// now apply the changes from end to start to leave the offsets of the
// yet unchanged text parts remain the same.
+ size_t nSum(m_Text.Len());
for (size_t i = 0; i < aChanges.size(); ++i)
- {
- swTransliterationChgData &rData = aChanges[ aChanges.size() - 1 - i ];
+ { // check this here since AddChanges cannot be moved below
+ // call to ReplaceTextOnly
+ swTransliterationChgData & rData =
+ aChanges[ aChanges.size() - 1 - i ];
+ nSum = nSum + rData.sChanged.Len() - rData.nLen;
+ if (nSum > TXTNODE_MAX)
+ {
+ SAL_WARN("sw.core", "SwTxtNode::ReplaceTextOnly: "
+ "node text with insertion > TXTNODE_MAX.");
+ return;
+ }
if (pUndo)
pUndo->AddChanges( *this, rData.nStart, rData.nLen, rData.aOffsets );
ReplaceTextOnly( rData.nStart, rData.nLen, rData.sChanged, rData.aOffsets );
@@ -1814,6 +1824,9 @@ void SwTxtNode::ReplaceTextOnly( xub_StrLen nPos, xub_StrLen nLen,
const XubString& rText,
const Sequence<sal_Int32>& rOffsets )
{
+ assert(static_cast<size_t>(m_Text.Len()) +
+ static_cast<size_t>(rText.Len()) - nLen <= TXTNODE_MAX);
+
m_Text.Replace( nPos, nLen, rText );
xub_StrLen nTLen = rText.Len();
commit b6d45f26ea5bcc848737921b59a16253eb1d8587
Author: Michael Stahl <mstahl at redhat.com>
Date: Fri Feb 15 15:28:24 2013 +0100
fdo#60732: check max size in SwTxtNode::ReplaceText
Also adjust SwUndoReplace to not assume that everything was inserted and
use the stored indexes instead in Undo.
Change-Id: I52f3aaf063c2b1bd52381bdc19e29a41a12c3847
diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index 0c48f64..fb46717 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -333,6 +333,8 @@ public:
const SwIndex & rStart, const xub_StrLen nLen);
/// replace nDelLen characters at rStart with rText
+ /// in case the replacement does not fit, it is partially inserted up to
+ /// TXTNODE_MAX
void ReplaceText( const SwIndex& rStart, const xub_StrLen nDelLen,
const XubString& rText );
void ReplaceTextOnly( xub_StrLen nPos, xub_StrLen nLen, const XubString& rText,
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 63a2c01..4bc16af 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -3322,11 +3322,23 @@ XubString SwTxtNode::GetRedlineTxt( xub_StrLen nIdx, xub_StrLen nLen,
*************************************************************************/
void SwTxtNode::ReplaceText( const SwIndex& rStart, const xub_StrLen nDelLen,
- const XubString& rText )
+ const XubString& rStr)
{
OSL_ENSURE( rStart.GetIndex() < m_Text.Len() &&
rStart.GetIndex() + nDelLen <= m_Text.Len(),
"SwTxtNode::ReplaceText: index out of bounds" );
+
+ ssize_t const nOverflow(static_cast<ssize_t>(m_Text.Len())
+ + static_cast<ssize_t>(rStr.Len()) - nDelLen - TXTNODE_MAX);
+ SAL_WARN_IF(nOverflow > 0, "sw.core",
+ "SwTxtNode::ReplaceText: node text with insertion > TXTNODE_MAX.");
+ OUString const sInserted(
+ (nOverflow > 0) ? rStr.Copy(0, rStr.Len() - nOverflow) : rStr);
+ if (sInserted.isEmpty())
+ {
+ return;
+ }
+
const xub_StrLen nStartPos = rStart.GetIndex();
xub_StrLen nEndPos = nStartPos + nDelLen;
xub_StrLen nLen = nDelLen;
@@ -3353,17 +3365,17 @@ void SwTxtNode::ReplaceText( const SwIndex& rStart, const xub_StrLen nDelLen,
bool bOldExpFlg = IsIgnoreDontExpand();
SetIgnoreDontExpand( true );
- if( nLen && rText.Len() )
+ if (nLen && sInserted.getLength())
{
// dann das 1. Zeichen ersetzen den Rest loschen und einfuegen
// Dadurch wird die Attributierung des 1. Zeichen expandiert!
- m_Text.SetChar( nStartPos, rText.GetChar( 0 ) );
+ m_Text.SetChar( nStartPos, sInserted[0] );
++((SwIndex&)rStart);
m_Text.Erase( rStart.GetIndex(), nLen - 1 );
Update( rStart, nLen - 1, true );
- XubString aTmpTxt( rText ); aTmpTxt.Erase( 0, 1 );
+ XubString aTmpTxt(sInserted); aTmpTxt.Erase( 0, 1 );
m_Text.Insert( aTmpTxt, rStart.GetIndex() );
Update( rStart, aTmpTxt.Len(), false );
}
@@ -3372,15 +3384,15 @@ void SwTxtNode::ReplaceText( const SwIndex& rStart, const xub_StrLen nDelLen,
m_Text.Erase( nStartPos, nLen );
Update( rStart, nLen, true );
- m_Text.Insert( rText, nStartPos );
- Update( rStart, rText.Len(), false );
+ m_Text.Insert( sInserted, nStartPos );
+ Update( rStart, sInserted.getLength(), false );
}
SetIgnoreDontExpand( bOldExpFlg );
SwDelTxt aDelHint( nStartPos, nDelLen );
NotifyClients( 0, &aDelHint );
- SwInsTxt aHint( nStartPos, rText.Len() );
+ SwInsTxt aHint( nStartPos, sInserted.getLength() );
NotifyClients( 0, &aHint );
}
diff --git a/sw/source/core/undo/unins.cxx b/sw/source/core/undo/unins.cxx
index 4a0e67f..ac49017 100644
--- a/sw/source/core/undo/unins.cxx
+++ b/sw/source/core/undo/unins.cxx
@@ -672,11 +672,7 @@ void SwUndoReplace::Impl::UndoImpl(::sw::UndoRedoContext & rContext)
}
SwIndex aIdx( pNd, m_nSttCnt );
- if( m_nSttNd == m_nEndNd )
- {
- pNd->EraseText( aIdx, sal_uInt16( m_sIns.getLength() ) );
- }
- else
+ // don't look at m_sIns for deletion, maybe it was not completely inserted
{
rPam.GetPoint()->nNode = *pNd;
rPam.GetPoint()->nContent.Assign( pNd, m_nSttCnt );
@@ -783,13 +779,9 @@ void SwUndoReplace::Impl::RedoImpl(::sw::UndoRedoContext & rContext)
void SwUndoReplace::Impl::SetEnd(SwPaM const& rPam)
{
- if( rPam.GetPoint()->nNode != rPam.GetMark()->nNode )
- {
- // multiple paragraphs were inserted
- const SwPosition* pEnd = rPam.End();
- m_nEndNd = m_nOffset + pEnd->nNode.GetIndex();
- m_nEndCnt = pEnd->nContent.GetIndex();
- }
+ const SwPosition* pEnd = rPam.End();
+ m_nEndNd = m_nOffset + pEnd->nNode.GetIndex();
+ m_nEndCnt = pEnd->nContent.GetIndex();
}
commit d47218d79a2440e71efb66b2224063801ba6623b
Author: Michael Stahl <mstahl at redhat.com>
Date: Fri Feb 15 13:29:04 2013 +0100
fdo#60732: make callers of SwTxtNode::InsertText more robust:
Return the actually inserted string from InsertText(), so callers can
check if the insertion was actually successful.
Especially InsertHint() will likely cause problems if it cannot insert
its CH_TXTATR; also Undo objects should not Undo more than was actually
inserted.
Change-Id: I87c9ea8b226ae4a2a6c20c112da76db07051a1bf
diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index 4b78cd9..0c48f64 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -244,7 +244,10 @@ public:
virtual sal_uInt16 ResetAllAttr();
/// insert text content
- void InsertText( const XubString & rStr, const SwIndex & rIdx,
+ /// @param rStr text to insert; in case it does not fit into the limit of
+ /// TXTNODE_MAX, the longest prefix that fits is inserted
+ /// @return the prefix of rStr that was actually inserted
+ OUString InsertText( const XubString & rStr, const SwIndex & rIdx,
const enum IDocumentContentOperations::InsertFlags nMode
= IDocumentContentOperations::INS_DEFAULT );
diff --git a/sw/source/core/doc/doc.cxx b/sw/source/core/doc/doc.cxx
index b9bc7d2..c5879f4 100644
--- a/sw/source/core/doc/doc.cxx
+++ b/sw/source/core/doc/doc.cxx
@@ -945,12 +945,11 @@ bool SwDoc::InsertString( const SwPaM &rRg, const String &rStr,
if (!bDoesUndo || !GetIDocumentUndoRedo().DoesGroupUndo())
{
- pNode->InsertText( rStr, rPos.nContent, nInsertMode );
-
+ OUString const ins(pNode->InsertText(rStr, rPos.nContent, nInsertMode));
if (bDoesUndo)
{
- SwUndoInsert * const pUndo( new SwUndoInsert(
- rPos.nNode, rPos.nContent.GetIndex(), rStr.Len(), nInsertMode));
+ SwUndoInsert * const pUndo( new SwUndoInsert(rPos.nNode,
+ rPos.nContent.GetIndex(), ins.getLength(), nInsertMode));
GetIDocumentUndoRedo().AppendUndo(pUndo);
}
}
@@ -980,16 +979,16 @@ bool SwDoc::InsertString( const SwPaM &rRg, const String &rStr,
GetIDocumentUndoRedo().AppendUndo( pUndo );
}
- pNode->InsertText( rStr, rPos.nContent, nInsertMode );
+ OUString const ins(pNode->InsertText(rStr, rPos.nContent, nInsertMode));
- for( xub_StrLen i = 0; i < rStr.Len(); ++i )
+ for (sal_Int32 i = 0; i < ins.getLength(); ++i)
{
nInsPos++;
- // if CanGrouping() returns sal_True, everything has already been done
- if( !pUndo->CanGrouping( rStr.GetChar( i ) ))
+ // if CanGrouping() returns true, everything has already been done
+ if (!pUndo->CanGrouping(ins[i]))
{
- pUndo = new SwUndoInsert( rPos.nNode, nInsPos, 1, nInsertMode,
- !rCC.isLetterNumeric( rStr, i ) );
+ pUndo = new SwUndoInsert(rPos.nNode, nInsPos, 1, nInsertMode,
+ !rCC.isLetterNumeric(ins, i));
GetIDocumentUndoRedo().AppendUndo( pUndo );
}
}
diff --git a/sw/source/core/doc/docedt.cxx b/sw/source/core/doc/docedt.cxx
index 8859efb..539ebf4 100644
--- a/sw/source/core/doc/docedt.cxx
+++ b/sw/source/core/doc/docedt.cxx
@@ -716,8 +716,11 @@ bool SwDoc::Overwrite( const SwPaM &rRg, const String &rStr )
}
SwTxtNode *pNode = rPt.nNode.GetNode().GetTxtNode();
- if(!pNode)
+ if (!pNode || ( static_cast<size_t>(rStr.Len()) // worst case: no erase
+ + static_cast<size_t>(pNode->GetTxt().Len()) > TXTNODE_MAX))
+ {
return sal_False;
+ }
if (GetIDocumentUndoRedo().DoesUndo())
{
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 0fa7087..63a2c01 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -1703,23 +1703,27 @@ void SwTxtNode::CopyText( SwTxtNode *const pDest,
}
-void SwTxtNode::InsertText( const XubString & rStr, const SwIndex & rIdx,
+OUString SwTxtNode::InsertText( const XubString & rStr, const SwIndex & rIdx,
const IDocumentContentOperations::InsertFlags nMode )
{
OSL_ENSURE( rIdx <= m_Text.Len(), "SwTxtNode::InsertText: invalid index." );
- OSL_ENSURE( (sal_uLong)m_Text.Len() + (sal_uLong)rStr.Len() <= STRING_LEN,
- "SwTxtNode::InsertText: node text with insertion > STRING_LEN." );
xub_StrLen aPos = rIdx.GetIndex();
xub_StrLen nLen = m_Text.Len() - aPos;
ssize_t const nOverflow(static_cast<ssize_t>(m_Text.Len())
+ static_cast<ssize_t>(rStr.Len()) - TXTNODE_MAX);
- m_Text.Insert((nOverflow > 0) ? rStr.Copy(0, rStr.Len() - nOverflow) : rStr,
- aPos);
+ SAL_WARN_IF(nOverflow > 0, "sw.core",
+ "SwTxtNode::InsertText: node text with insertion > TXTNODE_MAX.");
+ OUString const sInserted(
+ (nOverflow > 0) ? rStr.Copy(0, rStr.Len() - nOverflow) : rStr);
+ if (sInserted.isEmpty())
+ {
+ return sInserted;
+ }
+ m_Text.Insert(sInserted, aPos);
assert(m_Text.Len() <= TXTNODE_MAX);
nLen = m_Text.Len() - aPos - nLen;
-
- if ( !nLen ) return;
+ assert(nLen != 0);
bool bOldExpFlg = IsIgnoreDontExpand();
if (nMode & IDocumentContentOperations::INS_FORCEHINTEXPAND)
@@ -1804,6 +1808,7 @@ void SwTxtNode::InsertText( const XubString & rStr, const SwIndex & rIdx,
SetCalcHiddenCharFlags();
CHECK_SWPHINTS(this);
+ return sInserted;
}
/*************************************************************************
@@ -3007,9 +3012,12 @@ sal_Bool SwTxtNode::GetExpandTxt( SwTxtNode& rDestNd, const SwIndex* pDestIdx,
if( aExpand.Len() )
{
++aDestIdx; // dahinter einfuegen;
- rDestNd.InsertText( aExpand, aDestIdx );
+ OUString const ins(
+ rDestNd.InsertText( aExpand, aDestIdx));
+ SAL_INFO_IF(ins.getLength() != aExpand.Len(),
+ "sw.core", "GetExpandTxt lossage");
aDestIdx = nInsPos + nAttrStartIdx;
- nInsPos = nInsPos + aExpand.Len();
+ nInsPos = nInsPos + ins.getLength();
}
rDestNd.EraseText( aDestIdx, 1 );
--nInsPos;
@@ -3038,10 +3046,13 @@ sal_Bool SwTxtNode::GetExpandTxt( SwTxtNode& rDestNd, const SwIndex* pDestIdx,
rDestNd.InsertItem(aItem,
aDestIdx.GetIndex(),
aDestIdx.GetIndex() );
- rDestNd.InsertText( sExpand, aDestIdx,
- IDocumentContentOperations::INS_EMPTYEXPAND);
+ OUString const ins( rDestNd.InsertText(sExpand,
+ aDestIdx,
+ IDocumentContentOperations::INS_EMPTYEXPAND));
+ SAL_INFO_IF(ins.getLength() != sExpand.Len(),
+ "sw.core", "GetExpandTxt lossage");
aDestIdx = nInsPos + nAttrStartIdx;
- nInsPos = nInsPos + sExpand.Len();
+ nInsPos = nInsPos + ins.getLength();
}
}
rDestNd.EraseText( aDestIdx, 1 );
diff --git a/sw/source/core/txtnode/thints.cxx b/sw/source/core/txtnode/thints.cxx
index 6f66720..e133f45 100644
--- a/sw/source/core/txtnode/thints.cxx
+++ b/sw/source/core/txtnode/thints.cxx
@@ -1254,7 +1254,15 @@ bool SwTxtNode::InsertHint( SwTxtAttr * const pAttr, const SetAttrMode nMode )
SwIndex aIdx( this, *pAttr->GetStart() );
const rtl::OUString c(GetCharOfTxtAttr(*pAttr));
- InsertText( c, aIdx, nInsertFlags );
+ OUString const ins( InsertText(c, aIdx, nInsertFlags) );
+ if (ins.isEmpty())
+ {
+ // do not record deletion of Format!
+ ::sw::UndoGuard const ug(
+ pFmt->GetDoc()->GetIDocumentUndoRedo());
+ DestroyAttr(pAttr);
+ return false; // text node full :(
+ }
nInsMode |= nsSetAttrMode::SETATTR_NOTXTATRCHR;
if (pAnchor &&
@@ -1371,7 +1379,12 @@ bool SwTxtNode::InsertHint( SwTxtAttr * const pAttr, const SetAttrMode nMode )
// Dokument nicht eingetrage wird.
SwIndex aNdIdx( this, *pAttr->GetStart() );
const rtl::OUString c(GetCharOfTxtAttr(*pAttr));
- InsertText( c, aNdIdx, nInsertFlags );
+ OUString const ins( InsertText(c, aNdIdx, nInsertFlags) );
+ if (ins.isEmpty())
+ {
+ DestroyAttr(pAttr);
+ return false; // text node full :(
+ }
nInsMode |= nsSetAttrMode::SETATTR_NOTXTATRCHR;
}
@@ -1430,7 +1443,13 @@ bool SwTxtNode::InsertHint( SwTxtAttr * const pAttr, const SetAttrMode nMode )
if( !(nsSetAttrMode::SETATTR_NOTXTATRCHR & nInsMode) )
{
SwIndex aIdx( this, *pAttr->GetStart() );
- InsertText( rtl::OUString(GetCharOfTxtAttr(*pAttr)), aIdx, nInsertFlags );
+ OUString const ins( InsertText(OUString(GetCharOfTxtAttr(*pAttr)),
+ aIdx, nInsertFlags) );
+ if (ins.isEmpty())
+ {
+ DestroyAttr(pAttr);
+ return false; // text node full :(
+ }
// adjust end of hint to account for inserted CH_TXTATR
xub_StrLen * const pEnd(pAttr->GetEnd());
diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx
index fc62fcd..f824b8e 100644
--- a/sw/source/core/undo/undel.cxx
+++ b/sw/source/core/undo/undel.cxx
@@ -789,8 +789,9 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
}
if( pTxtNd )
{
- pTxtNd->InsertText( *pEndStr, aPos.nContent,
- IDocumentContentOperations::INS_NOHINTEXPAND );
+ OUString const ins( pTxtNd->InsertText(*pEndStr, aPos.nContent,
+ IDocumentContentOperations::INS_NOHINTEXPAND) );
+ assert(ins.getLength() == pEndStr->Len()); // must succeed
// METADATA: restore
pTxtNd->RestoreMetadata(m_pMetadataUndoEnd);
}
@@ -882,8 +883,9 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
// SectionNode mode and selection from top to bottom:
// -> in StartNode is still the rest of the Join => delete
aPos.nContent.Assign( pTxtNd, nSttCntnt );
- pTxtNd->InsertText( *pSttStr, aPos.nContent,
- IDocumentContentOperations::INS_NOHINTEXPAND );
+ OUString const ins( pTxtNd->InsertText(*pSttStr, aPos.nContent,
+ IDocumentContentOperations::INS_NOHINTEXPAND) );
+ assert(ins.getLength() == pSttStr->Len()); // must succeed
// METADATA: restore
pTxtNd->RestoreMetadata(m_pMetadataUndoStart);
}
diff --git a/sw/source/core/undo/unins.cxx b/sw/source/core/undo/unins.cxx
index 473a915..4a0e67f 100644
--- a/sw/source/core/undo/unins.cxx
+++ b/sw/source/core/undo/unins.cxx
@@ -340,8 +340,10 @@ void SwUndoInsert::RedoImpl(::sw::UndoRedoContext & rContext)
{
SwTxtNode *const pTxtNode = pCNd->GetTxtNode();
OSL_ENSURE( pTxtNode, "where is my textnode ?" );
- pTxtNode->InsertText( *pTxt, pPam->GetMark()->nContent,
- m_nInsertFlags );
+ OUString const ins(
+ pTxtNode->InsertText( *pTxt, pPam->GetMark()->nContent,
+ m_nInsertFlags) );
+ assert(ins.getLength() == pTxt->Len()); // must succeed
DELETEZ( pTxt );
}
else
@@ -704,7 +706,8 @@ void SwUndoReplace::Impl::UndoImpl(::sw::UndoRedoContext & rContext)
if (!m_sOld.isEmpty())
{
- pNd->InsertText( m_sOld, aIdx );
+ OUString const ins( pNd->InsertText( m_sOld, aIdx ) );
+ assert(ins.getLength() == m_sOld.getLength()); // must succeed
}
if( pHistory )
diff --git a/sw/source/core/undo/unovwr.cxx b/sw/source/core/undo/unovwr.cxx
index b242426..3cc6c4d 100644
--- a/sw/source/core/undo/unovwr.cxx
+++ b/sw/source/core/undo/unovwr.cxx
@@ -154,8 +154,9 @@ sal_Bool SwUndoOverwrite::CanGrouping( SwDoc* pDoc, SwPosition& rPos,
bool bOldExpFlg = pDelTxtNd->IsIgnoreDontExpand();
pDelTxtNd->SetIgnoreDontExpand( true );
- pDelTxtNd->InsertText( rtl::OUString(cIns), rPos.nContent,
- IDocumentContentOperations::INS_EMPTYEXPAND );
+ OUString const ins( pDelTxtNd->InsertText(OUString(cIns), rPos.nContent,
+ IDocumentContentOperations::INS_EMPTYEXPAND) );
+ assert(ins.getLength() == 1); // check in SwDoc::Overwrite => cannot fail
aInsStr.Insert( cIns );
if( !bInsChar )
@@ -210,7 +211,8 @@ void SwUndoOverwrite::UndoImpl(::sw::UndoRedoContext & rContext)
{
// do it individually, to keep the attributes!
*pTmpStr = aDelStr.GetChar( n );
- pTxtNd->InsertText( aTmpStr, rIdx /*???, SETATTR_NOTXTATRCHR*/ );
+ OUString const ins( pTxtNd->InsertText(aTmpStr, rIdx) );
+ assert(ins.getLength() == 1); // cannot fail
rIdx -= 2;
pTxtNd->EraseText( rIdx, 1 );
rIdx += 2;
@@ -279,8 +281,10 @@ void SwUndoOverwrite::RedoImpl(::sw::UndoRedoContext & rContext)
for( xub_StrLen n = 0; n < aInsStr.Len(); n++ )
{
// do it individually, to keep the attributes!
- pTxtNd->InsertText( rtl::OUString(aInsStr.GetChar(n)), rIdx,
- IDocumentContentOperations::INS_EMPTYEXPAND );
+ OUString const ins(
+ pTxtNd->InsertText( rtl::OUString(aInsStr.GetChar(n)), rIdx,
+ IDocumentContentOperations::INS_EMPTYEXPAND) );
+ assert(ins.getLength() == 1); // cannot fail
if( n < aDelStr.Len() )
{
rIdx -= 2;
commit 447bb5b5006051672ec526b75bec7db02d2db82e
Author: Michael Stahl <mstahl at redhat.com>
Date: Thu Feb 14 23:34:16 2013 +0100
SwDoc::Overwrite: probably a bad idea to overwrite fieldmarks
Change-Id: Iba94df67c21514cf4f5361bab28629c6d5d9d3e8
diff --git a/sw/source/core/doc/docedt.cxx b/sw/source/core/doc/docedt.cxx
index 4ec41ac..8859efb 100644
--- a/sw/source/core/doc/docedt.cxx
+++ b/sw/source/core/doc/docedt.cxx
@@ -131,8 +131,18 @@ typedef boost::ptr_vector< _SaveRedline > _SaveRedlines;
static bool lcl_MayOverwrite( const SwTxtNode *pNode, const xub_StrLen nPos )
{
sal_Unicode cChr = pNode->GetTxt().GetChar( nPos );
- return !( ( CH_TXTATR_BREAKWORD == cChr || CH_TXTATR_INWORD == cChr ) &&
- (0 != pNode->GetTxtAttrForCharAt( nPos ) ) );
+ switch (cChr)
+ {
+ case CH_TXTATR_BREAKWORD:
+ case CH_TXTATR_INWORD:
+ return !pNode->GetTxtAttrForCharAt(nPos);// how could there be none?
+ case CH_TXT_ATR_FIELDSTART:
+ case CH_TXT_ATR_FIELDEND:
+ case CH_TXT_ATR_FORMELEMENT:
+ return false;
+ default:
+ return true;
+ }
}
static void lcl_SkipAttr( const SwTxtNode *pNode, SwIndex &rIdx, xub_StrLen &rStart )
commit 5a80c24b145c8efe0dd384ef88e7d31173522fb8
Author: Michael Stahl <mstahl at redhat.com>
Date: Thu Feb 14 23:02:35 2013 +0100
sw: do not crash when it's not possible to insert fly
Change-Id: Idfcf54013107ba6b7ce3de0d0bddbef306698f33
diff --git a/sw/source/core/doc/doclay.cxx b/sw/source/core/doc/doclay.cxx
index f73cc72..b97a263 100644
--- a/sw/source/core/doc/doclay.cxx
+++ b/sw/source/core/doc/doclay.cxx
@@ -654,7 +654,11 @@ SwFlyFrmFmt* SwDoc::_MakeFlySection( const SwPosition& rAnchPos,
if (pTxtNode != NULL)
{
SwFmtFlyCnt aFmt( pFmt );
- pTxtNode->InsertItem( aFmt, nStt, nStt );
+ bool const bSuccess( pTxtNode->InsertItem(aFmt, nStt, nStt) );
+ if (!bSuccess) // may fail if there's no space left or header/ftr
+ { // pFmt is dead now
+ return 0;
+ }
}
}
@@ -740,7 +744,9 @@ SwFlyFrmFmt* SwDoc::MakeFlySection( RndStdIds eAnchorType,
if (bCalledFromShell && !lcl_IsItemSet(*pNewTxtNd, RES_PARATR_ADJUST) &&
SFX_ITEM_SET == pAnchorNode->GetSwAttrSet().
GetItemState(RES_PARATR_ADJUST, sal_True, &pItem))
+ {
static_cast<SwCntntNode *>(pNewTxtNd)->SetAttr(*pItem);
+ }
pFmt = _MakeFlySection( *pAnchorPos, *pNewTxtNd,
eAnchorType, pFlySet, pFrmFmt );
@@ -941,8 +947,13 @@ SwDrawFrmFmt* SwDoc::Insert( const SwPaM &rRg,
{
xub_StrLen nStt = rRg.GetPoint()->nContent.GetIndex();
SwFmtFlyCnt aFmt( pFmt );
- rRg.GetPoint()->nNode.GetNode().GetTxtNode()->InsertItem(
- aFmt, nStt, nStt );
+ bool const bSuccess( // may fail if there's no space left
+ rRg.GetPoint()->nNode.GetNode().GetTxtNode()->InsertItem(
+ aFmt, nStt, nStt));
+ if (!bSuccess)
+ { // pFmt is dead now
+ return 0;
+ }
}
SwDrawContact* pContact = new SwDrawContact( pFmt, &rDrawObj );
commit 549c0f785d4b6d4bc1b39b22827d77d66f48430a
Author: Michael Stahl <mstahl at redhat.com>
Date: Thu Feb 14 19:27:28 2013 +0100
fdo#60732: SwTxtNode: limit to less than STRING_LEN chars
It's not a good idea to have STRING_LEN characters in a SwTxtNode
because then there is no valid SwPosition at the end of the paragraph.
Also it turns out that LO 3.6 and 4.0 do rather stupid things with a
full SwTxtNode. So enforce a limit, at first in the usual places that
are used during file import, SwTxtNode::InsertText() and
SwCntntNode::CanJoinPrev()/CanJoinNext().
Change-Id: Icb0f44acd20aa81635d42b84d4ae0f9b693a661c
diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index 5a47fb2..4b78cd9 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -70,6 +70,11 @@ namespace com { namespace sun { namespace star {
typedef std::set< xub_StrLen > SwSoftPageBreakList;
+// do not fill the String up to the max - need to be able to have a
+// SwPosition "behind" the last character, i.e., at index TXTNODE_MAX + 1
+// (also STRING_LEN is often used for "not found")
+const xub_StrLen TXTNODE_MAX = STRING_LEN - 2;
+
/// SwTxtNode is a paragraph in the document model.
class SW_DLLPUBLIC SwTxtNode: public SwCntntNode, public ::sfx2::Metadatable
{
diff --git a/sw/source/core/docnode/node.cxx b/sw/source/core/docnode/node.cxx
index a972611..61a720f 100644
--- a/sw/source/core/docnode/node.cxx
+++ b/sw/source/core/docnode/node.cxx
@@ -1624,12 +1624,26 @@ const SfxPoolItem* SwCntntNode::GetNoCondAttr( sal_uInt16 nWhich,
return pFnd;
}
+static bool lcl_CheckMaxLength(SwNode const& rPrev, SwNode const& rNext)
+{
+ if (rPrev.GetNodeType() != rNext.GetNodeType())
+ {
+ return false;
+ }
+ if (!rPrev.IsTxtNode())
+ {
+ return true;
+ }
+ size_t const nSum( static_cast<const SwTxtNode&>(rPrev).GetTxt().Len()
+ + static_cast<const SwTxtNode&>(rNext).GetTxt().Len());
+ return (nSum <= TXTNODE_MAX);
+}
+
// Can we join two Nodes?
// We can return the 2nd position in pIdx.
int SwCntntNode::CanJoinNext( SwNodeIndex* pIdx ) const
{
const SwNodes& rNds = GetNodes();
- sal_uInt8 nNdType = GetNodeType();
SwNodeIndex aIdx( *this, 1 );
const SwNode* pNd = this;
@@ -1638,16 +1652,11 @@ int SwCntntNode::CanJoinNext( SwNodeIndex* pIdx ) const
( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )))
++aIdx;
- if( pNd->GetNodeType() != nNdType || rNds.Count()-1 == aIdx.GetIndex() )
+ if (rNds.Count()-1 == aIdx.GetIndex())
return sal_False;
- if( IsTxtNode() )
- { // Do not merge strings if the result exceeds the allowed string length
- const SwTxtNode* pTxtNd = static_cast<const SwTxtNode*>(this);
- sal_uInt64 nSum = pTxtNd->GetTxt().Len();
- pTxtNd = static_cast<const SwTxtNode*>(pNd);
- nSum += pTxtNd->GetTxt().Len();
- if( nSum > STRING_LEN )
- return sal_False;
+ if (!lcl_CheckMaxLength(*this, *pNd))
+ {
+ return false;
}
if( pIdx )
*pIdx = aIdx;
@@ -1658,7 +1667,6 @@ int SwCntntNode::CanJoinNext( SwNodeIndex* pIdx ) const
// We can return the 2nd position in pIdx.
int SwCntntNode::CanJoinPrev( SwNodeIndex* pIdx ) const
{
- sal_uInt8 nNdType = GetNodeType();
SwNodeIndex aIdx( *this, -1 );
const SwNode* pNd = this;
@@ -1667,8 +1675,12 @@ int SwCntntNode::CanJoinPrev( SwNodeIndex* pIdx ) const
( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode() )))
aIdx--;
- if( pNd->GetNodeType() != nNdType || 0 == aIdx.GetIndex() )
+ if (0 == aIdx.GetIndex())
return sal_False;
+ if (!lcl_CheckMaxLength(*pNd, *this))
+ {
+ return false;
+ }
if( pIdx )
*pIdx = aIdx;
return sal_True;
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index aff2753..0fa7087 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -1712,7 +1712,11 @@ void SwTxtNode::InsertText( const XubString & rStr, const SwIndex & rIdx,
xub_StrLen aPos = rIdx.GetIndex();
xub_StrLen nLen = m_Text.Len() - aPos;
- m_Text.Insert( rStr, aPos );
+ ssize_t const nOverflow(static_cast<ssize_t>(m_Text.Len())
+ + static_cast<ssize_t>(rStr.Len()) - TXTNODE_MAX);
+ m_Text.Insert((nOverflow > 0) ? rStr.Copy(0, rStr.Len() - nOverflow) : rStr,
+ aPos);
+ assert(m_Text.Len() <= TXTNODE_MAX);
nLen = m_Text.Len() - aPos - nLen;
if ( !nLen ) return;
More information about the Libreoffice-commits
mailing list