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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <contentindex.hxx>
23 #include <sal/log.hxx>
25 #include <crossrefbookmark.hxx>
27 SwContentIndex::SwContentIndex(const SwContentNode
* pContentNode
, sal_Int32
const nIdx
)
29 , m_pContentNode( const_cast<SwContentNode
*>(pContentNode
) )
37 SwContentIndex::SwContentIndex( const SwContentIndex
& rIdx
, short nDiff
)
38 : m_pContentNode( rIdx
.m_pContentNode
)
43 ChgValue( rIdx
, rIdx
.m_nIndex
+ nDiff
);
46 SwContentIndex::SwContentIndex( const SwContentIndex
& rIdx
)
47 : m_nIndex( rIdx
.m_nIndex
)
48 , m_pContentNode( rIdx
.m_pContentNode
)
53 ChgValue( rIdx
, rIdx
.m_nIndex
);
56 void SwContentIndex::Init(sal_Int32
const nIdx
)
60 m_nIndex
= 0; // always 0 if no IndexReg
62 else if (!m_pContentNode
->m_pFirst
) // first Index?
64 assert(!m_pContentNode
->m_pLast
);
65 m_pContentNode
->m_pFirst
= m_pContentNode
->m_pLast
= this;
68 else if (nIdx
> ((m_pContentNode
->m_pLast
->m_nIndex
69 - m_pContentNode
->m_pFirst
->m_nIndex
) / 2))
71 ChgValue( *m_pContentNode
->m_pLast
, nIdx
);
75 ChgValue( *m_pContentNode
->m_pFirst
, nIdx
);
79 SwContentIndex
& SwContentIndex::ChgValue( const SwContentIndex
& rIdx
, sal_Int32 nNewValue
)
81 assert(m_pContentNode
== rIdx
.m_pContentNode
);
85 return *this; // no IndexReg => no list to sort into; m_nIndex is 0
87 SwContentIndex
* pFnd
= const_cast<SwContentIndex
*>(&rIdx
);
88 if (rIdx
.m_nIndex
> nNewValue
) // move forwards
92 SwContentIndex
* pPrv
= pFnd
->m_pPrev
;
93 if (!pPrv
|| pPrv
->m_nIndex
<= nNewValue
)
100 // remove from list at old position
104 m_pPrev
= pFnd
->m_pPrev
;
106 m_pPrev
->m_pNext
= this;
108 m_pContentNode
->m_pFirst
= this;
109 pFnd
->m_pPrev
= this;
112 else if (rIdx
.m_nIndex
< nNewValue
)
116 SwContentIndex
* pNxt
= pFnd
->m_pNext
;
117 if (!pNxt
|| pNxt
->m_nIndex
>= nNewValue
)
124 // remove from list at old position
128 m_pNext
= pFnd
->m_pNext
;
130 m_pNext
->m_pPrev
= this;
132 m_pContentNode
->m_pLast
= this;
133 pFnd
->m_pNext
= this;
136 else if( pFnd
!= this )
138 // remove from list at old position
141 m_pPrev
= pFnd
; // == &rIdx here
142 m_pNext
= rIdx
.m_pNext
;
143 m_pPrev
->m_pNext
= this;
145 if (!m_pNext
) // last in the list
146 m_pContentNode
->m_pLast
= this;
148 m_pNext
->m_pPrev
= this;
151 if (m_pContentNode
->m_pFirst
== m_pNext
)
152 m_pContentNode
->m_pFirst
= this;
153 if (m_pContentNode
->m_pLast
== m_pPrev
)
154 m_pContentNode
->m_pLast
= this;
156 m_nIndex
= nNewValue
;
161 void SwContentIndex::Remove()
165 assert(!m_pPrev
&& !m_pNext
);
171 m_pPrev
->m_pNext
= m_pNext
;
173 else if (m_pContentNode
->m_pFirst
== this)
175 m_pContentNode
->m_pFirst
= m_pNext
;
180 m_pNext
->m_pPrev
= m_pPrev
;
182 else if (m_pContentNode
->m_pLast
== this)
184 m_pContentNode
->m_pLast
= m_pPrev
;
188 SwContentIndex
& SwContentIndex::operator=( const SwContentIndex
& rIdx
)
191 if (rIdx
.m_pContentNode
!= m_pContentNode
) // unregister!
194 m_pContentNode
= rIdx
.m_pContentNode
;
195 m_pNext
= m_pPrev
= nullptr;
199 bEqual
= rIdx
.m_nIndex
== m_nIndex
;
202 ChgValue( rIdx
, rIdx
.m_nIndex
);
206 SwContentIndex
& SwContentIndex::Assign( const SwContentNode
* pArr
, sal_Int32 nIdx
)
208 if (pArr
!= m_pContentNode
) // unregister!
211 m_pContentNode
= const_cast<SwContentNode
*>(pArr
);
212 m_pNext
= m_pPrev
= nullptr;
215 else if (m_nIndex
!= nIdx
)
217 ChgValue( *this, nIdx
);
222 void SwContentIndex::SetMark(const sw::mark::IMark
* pMark
)
227 SwContentIndexReg::SwContentIndexReg()
228 : m_pFirst( nullptr ), m_pLast( nullptr )
232 SwContentIndexReg::~SwContentIndexReg()
234 assert(!m_pFirst
&& !m_pLast
&& "There are still indices registered");
237 void SwContentIndexReg::Update(
238 SwContentIndex
const & rIdx
,
239 const sal_Int32 nDiff
,
240 UpdateMode
const eMode
)
242 SwContentIndex
* pStt
= const_cast<SwContentIndex
*>(&rIdx
);
243 const sal_Int32 nNewVal
= rIdx
.m_nIndex
;
244 if (eMode
& UpdateMode::Negative
)
246 const sal_Int32 nLast
= rIdx
.m_nIndex
+ nDiff
;
248 // skip over the ones that already have the right value
249 while (pStt
&& pStt
->m_nIndex
== nNewVal
)
250 pStt
= pStt
->m_pNext
;
251 while (pStt
&& pStt
->m_nIndex
<= nLast
)
253 pStt
->m_nIndex
= nNewVal
;
254 pStt
= pStt
->m_pNext
;
258 pStt
->m_nIndex
= pStt
->m_nIndex
- nDiff
;
259 pStt
= pStt
->m_pNext
;
264 while (pStt
&& pStt
->m_nIndex
== nNewVal
)
266 pStt
->m_nIndex
= pStt
->m_nIndex
+ nDiff
;
267 pStt
= pStt
->m_pPrev
;
272 // HACK: avoid updating position of cross-ref bookmarks
273 if (!pStt
->m_pMark
|| nullptr == dynamic_cast<
274 ::sw::mark::CrossRefBookmark
const*>(pStt
->m_pMark
))
276 pStt
->m_nIndex
= pStt
->m_nIndex
+ nDiff
;
278 pStt
= pStt
->m_pNext
;
283 void SwContentIndexReg::MoveTo( SwContentNode
& rArr
)
285 if (!(this != &rArr
&& m_pFirst
))
288 SwContentIndex
* pIdx
= const_cast<SwContentIndex
*>(m_pFirst
);
289 SwContentIndex
* pNext
;
292 pNext
= pIdx
->m_pNext
;
293 pIdx
->Assign( &rArr
, pIdx
->GetIndex() );
304 sal_Int32
SwContentIndex::operator++()
306 SAL_WARN_IF( !(m_nIndex
< SAL_MAX_INT32
), "sw.core",
307 "SwContentIndex::operator++() wraps around" );
309 ChgValue( *this, m_nIndex
+1 );
313 sal_Int32
SwContentIndex::operator--(int)
315 SAL_WARN_IF( !(m_nIndex
> 0), "sw.core",
316 "SwContentIndex::operator--(int) wraps around" );
318 const sal_Int32 nOldIndex
= m_nIndex
;
319 ChgValue( *this, m_nIndex
-1 );
323 sal_Int32
SwContentIndex::operator--()
325 SAL_WARN_IF( !( m_nIndex
> 0), "sw.core",
326 "SwContentIndex::operator--() wraps around" );
327 return ChgValue( *this, m_nIndex
-1 ).m_nIndex
;
330 sal_Int32
SwContentIndex::operator+=( sal_Int32
const nVal
)
332 SAL_WARN_IF( !(nVal
> 0 ? m_nIndex
<= SAL_MAX_INT32
- nVal
: m_nIndex
>= nVal
), "sw.core",
333 "SwContentIndex SwContentIndex::operator+=(sal_Int32) wraps around" );
334 return ChgValue( *this, m_nIndex
+ nVal
).m_nIndex
;
337 sal_Int32
SwContentIndex::operator-=( sal_Int32
const nVal
)
339 SAL_WARN_IF( !(m_nIndex
>= nVal
), "sw.core",
340 "SwContentIndex::operator-=(sal_Int32) wraps around" );
341 return ChgValue( *this, m_nIndex
- nVal
).m_nIndex
;
344 bool SwContentIndex::operator< ( const SwContentIndex
& rIndex
) const
346 // Attempt to compare indices into different arrays
347 assert(m_pContentNode
== rIndex
.m_pContentNode
);
348 return m_nIndex
< rIndex
.m_nIndex
;
351 bool SwContentIndex::operator<=( const SwContentIndex
& rIndex
) const
353 // Attempt to compare indices into different arrays
354 assert(m_pContentNode
== rIndex
.m_pContentNode
);
355 return m_nIndex
<= rIndex
.m_nIndex
;
358 bool SwContentIndex::operator> ( const SwContentIndex
& rIndex
) const
360 // Attempt to compare indices into different arrays
361 assert(m_pContentNode
== rIndex
.m_pContentNode
);
362 return m_nIndex
> rIndex
.m_nIndex
;
365 bool SwContentIndex::operator>=( const SwContentIndex
& rIndex
) const
367 // Attempt to compare indices into different arrays
368 assert(m_pContentNode
== rIndex
.m_pContentNode
);
369 return m_nIndex
>= rIndex
.m_nIndex
;
372 SwContentIndex
& SwContentIndex::operator= ( sal_Int32
const nVal
)
374 if (m_nIndex
!= nVal
)
375 ChgValue( *this, nVal
);
382 std::ostream
& operator <<(std::ostream
& s
, const SwContentIndex
& index
)
384 return s
<< "SwContentIndex offset (" << index
.GetIndex() << ")";
387 std::ostream
& operator <<(std::ostream
& s
, const SwNodeOffset
& index
)
389 return s
<< sal_Int32(index
);
392 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */