LibreOffice Module sw (master) 1
index.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <contentindex.hxx>
21
22#include <assert.h>
23#include <sal/log.hxx>
24
25#include <crossrefbookmark.hxx>
26
27SwContentIndex::SwContentIndex(const SwContentNode * pContentNode, sal_Int32 const nIdx)
28 : m_nIndex( nIdx )
29 , m_pContentNode( const_cast<SwContentNode*>(pContentNode) )
30 , m_pNext( nullptr )
31 , m_pPrev( nullptr )
32 , m_pMark( nullptr )
33{
35}
36
38 : m_pContentNode( rIdx.m_pContentNode )
39 , m_pNext( nullptr )
40 , m_pPrev( nullptr )
41 , m_pMark( nullptr )
42{
43 ChgValue( rIdx, rIdx.m_nIndex + nDiff );
44}
45
47 : m_nIndex( rIdx.m_nIndex )
48 , m_pContentNode( rIdx.m_pContentNode )
49 , m_pNext( nullptr )
50 , m_pPrev( nullptr )
51 , m_pMark( nullptr )
52{
53 ChgValue( rIdx, rIdx.m_nIndex );
54}
55
56void SwContentIndex::Init(sal_Int32 const nIdx)
57{
58 if (!m_pContentNode)
59 {
60 m_nIndex = 0; // always 0 if no IndexReg
61 }
62 else if (!m_pContentNode->m_pFirst) // first Index?
63 {
64 assert(!m_pContentNode->m_pLast);
65 m_pContentNode->m_pFirst = m_pContentNode->m_pLast = this;
66 m_nIndex = nIdx;
67 }
68 else if (nIdx > ((m_pContentNode->m_pLast->m_nIndex
69 - m_pContentNode->m_pFirst->m_nIndex) / 2))
70 {
71 ChgValue( *m_pContentNode->m_pLast, nIdx );
72 }
73 else
74 {
75 ChgValue( *m_pContentNode->m_pFirst, nIdx );
76 }
77}
78
79SwContentIndex& SwContentIndex::ChgValue( const SwContentIndex& rIdx, sal_Int32 nNewValue )
80{
81 assert(m_pContentNode == rIdx.m_pContentNode);
82 if (!m_pContentNode)
83 {
84 m_nIndex = 0;
85 return *this; // no IndexReg => no list to sort into; m_nIndex is 0
86 }
87 SwContentIndex* pFnd = const_cast<SwContentIndex*>(&rIdx);
88 if (rIdx.m_nIndex > nNewValue) // move forwards
89 {
90 for (;;)
91 {
92 SwContentIndex* pPrv = pFnd->m_pPrev;
93 if (!pPrv || pPrv->m_nIndex <= nNewValue)
94 break;
95 pFnd = pPrv;
96 }
97
98 if( pFnd != this )
99 {
100 // remove from list at old position
101 Remove();
102
103 m_pNext = pFnd;
104 m_pPrev = pFnd->m_pPrev;
105 if (m_pPrev)
106 m_pPrev->m_pNext = this;
107 else
108 m_pContentNode->m_pFirst = this;
109 pFnd->m_pPrev = this;
110 }
111 }
112 else if (rIdx.m_nIndex < nNewValue)
113 {
114 for (;;)
115 {
116 SwContentIndex* pNxt = pFnd->m_pNext;
117 if (!pNxt || pNxt->m_nIndex >= nNewValue)
118 break;
119 pFnd = pNxt;
120 }
121
122 if( pFnd != this )
123 {
124 // remove from list at old position
125 Remove();
126
127 m_pPrev = pFnd;
128 m_pNext = pFnd->m_pNext;
129 if (m_pNext)
130 m_pNext->m_pPrev = this;
131 else
132 m_pContentNode->m_pLast = this;
133 pFnd->m_pNext = this;
134 }
135 }
136 else if( pFnd != this )
137 {
138 // remove from list at old position
139 Remove();
140
141 m_pPrev = pFnd; // == &rIdx here
142 m_pNext = rIdx.m_pNext;
143 m_pPrev->m_pNext = this;
144
145 if (!m_pNext) // last in the list
146 m_pContentNode->m_pLast = this;
147 else
148 m_pNext->m_pPrev = this;
149 }
150
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;
155
156 m_nIndex = nNewValue;
157
158 return *this;
159}
160
162{
163 if (!m_pContentNode)
164 {
165 assert(!m_pPrev && !m_pNext);
166 return;
167 }
168
169 if (m_pPrev)
170 {
172 }
173 else if (m_pContentNode->m_pFirst == this)
174 {
175 m_pContentNode->m_pFirst = m_pNext;
176 }
177
178 if (m_pNext)
179 {
181 }
182 else if (m_pContentNode->m_pLast == this)
183 {
184 m_pContentNode->m_pLast = m_pPrev;
185 }
186}
187
189{
190 bool bEqual;
191 if (rIdx.m_pContentNode != m_pContentNode) // unregister!
192 {
193 Remove();
195 m_pNext = m_pPrev = nullptr;
196 bEqual = false;
197 }
198 else
199 bEqual = rIdx.m_nIndex == m_nIndex;
200
201 if( !bEqual )
202 ChgValue( rIdx, rIdx.m_nIndex );
203 return *this;
204}
205
207{
208 if (pArr != m_pContentNode) // unregister!
209 {
210 Remove();
211 m_pContentNode = const_cast<SwContentNode*>(pArr);
212 m_pNext = m_pPrev = nullptr;
213 Init(nIdx);
214 }
215 else if (m_nIndex != nIdx)
216 {
217 ChgValue( *this, nIdx );
218 }
219 return *this;
220}
221
223{
224 m_pMark = pMark;
225}
226
227SwContentIndexReg::SwContentIndexReg()
228 : m_pFirst( nullptr ), m_pLast( nullptr )
229{
230}
231
232SwContentIndexReg::~SwContentIndexReg()
233{
234 assert(!m_pFirst && !m_pLast && "There are still indices registered");
235}
236
237void SwContentIndexReg::Update(
238 SwContentIndex const & rIdx,
239 const sal_Int32 nDiff,
240 UpdateMode const eMode)
241{
242 SwContentIndex* pStt = const_cast<SwContentIndex*>(&rIdx);
243 const sal_Int32 nNewVal = rIdx.m_nIndex;
244 if (eMode & UpdateMode::Negative)
245 {
246 const sal_Int32 nLast = rIdx.m_nIndex + nDiff;
247 pStt = rIdx.m_pNext;
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)
252 {
253 pStt->m_nIndex = nNewVal;
254 pStt = pStt->m_pNext;
255 }
256 while( pStt )
257 {
258 pStt->m_nIndex = pStt->m_nIndex - nDiff;
259 pStt = pStt->m_pNext;
260 }
261 }
262 else
263 {
264 while (pStt && pStt->m_nIndex == nNewVal)
265 {
266 pStt->m_nIndex = pStt->m_nIndex + nDiff;
267 pStt = pStt->m_pPrev;
268 }
269 pStt = rIdx.m_pNext;
270 while( pStt )
271 {
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))
275 {
276 pStt->m_nIndex = pStt->m_nIndex + nDiff;
277 }
278 pStt = pStt->m_pNext;
279 }
280 }
281}
282
283void SwContentIndexReg::MoveTo( SwContentNode& rArr )
284{
285 if (!(this != &rArr && m_pFirst))
286 return;
287
288 SwContentIndex * pIdx = const_cast<SwContentIndex*>(m_pFirst);
289 SwContentIndex * pNext;
290 while( pIdx )
291 {
292 pNext = pIdx->m_pNext;
293 pIdx->Assign( &rArr, pIdx->GetIndex() );
294 pIdx = pNext;
295 }
296 m_pFirst = nullptr;
297 m_pLast = nullptr;
298}
299
300#ifdef DBG_UTIL
301
302// SwContentIndex
303
305{
306 SAL_WARN_IF( !(m_nIndex < SAL_MAX_INT32), "sw.core",
307 "SwContentIndex::operator++() wraps around" );
308
309 ChgValue( *this, m_nIndex+1 );
310 return m_nIndex;
311}
312
314{
315 SAL_WARN_IF( !(m_nIndex > 0), "sw.core",
316 "SwContentIndex::operator--(int) wraps around" );
317
318 const sal_Int32 nOldIndex = m_nIndex;
319 ChgValue( *this, m_nIndex-1 );
320 return nOldIndex;
321}
322
324{
325 SAL_WARN_IF( !( m_nIndex > 0), "sw.core",
326 "SwContentIndex::operator--() wraps around" );
327 return ChgValue( *this, m_nIndex-1 ).m_nIndex;
328}
329
330sal_Int32 SwContentIndex::operator+=( sal_Int32 const nVal )
331{
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;
335}
336
337sal_Int32 SwContentIndex::operator-=( sal_Int32 const nVal )
338{
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;
342}
343
344bool SwContentIndex::operator< ( const SwContentIndex & rIndex ) const
345{
346 // Attempt to compare indices into different arrays
347 assert(m_pContentNode == rIndex.m_pContentNode);
348 return m_nIndex < rIndex.m_nIndex;
349}
350
351bool SwContentIndex::operator<=( const SwContentIndex & rIndex ) const
352{
353 // Attempt to compare indices into different arrays
354 assert(m_pContentNode == rIndex.m_pContentNode);
355 return m_nIndex <= rIndex.m_nIndex;
356}
357
358bool SwContentIndex::operator> ( const SwContentIndex & rIndex ) const
359{
360 // Attempt to compare indices into different arrays
361 assert(m_pContentNode == rIndex.m_pContentNode);
362 return m_nIndex > rIndex.m_nIndex;
363}
364
365bool SwContentIndex::operator>=( const SwContentIndex & rIndex ) const
366{
367 // Attempt to compare indices into different arrays
368 assert(m_pContentNode == rIndex.m_pContentNode);
369 return m_nIndex >= rIndex.m_nIndex;
370}
371
373{
374 if (m_nIndex != nVal)
375 ChgValue( *this, nVal );
376
377 return *this;
378}
379
380#endif
381
382std::ostream& operator <<(std::ostream& s, const SwContentIndex& index)
383{
384 return s << "SwContentIndex offset (" << index.GetIndex() << ")";
385}
386
387std::ostream& operator <<(std::ostream& s, const SwNodeOffset& index)
388{
389 return s << sal_Int32(index);
390}
391
392/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Marks a character position inside a document model content node (SwContentNode)
sal_Int32 operator+=(sal_Int32 const)
Definition: index.cxx:330
bool operator>(const SwContentIndex &) const
Definition: index.cxx:358
const sw::mark::IMark * m_pMark
Pointer to a mark that owns this position to allow fast lookup of marks of an SwContentIndexReg.
sal_Int32 operator--()
Definition: index.cxx:323
void Init(sal_Int32 const nIdx)
Definition: index.cxx:56
SwContentNode * m_pContentNode
void SetMark(const sw::mark::IMark *pMark)
Definition: index.cxx:222
sal_Int32 m_nIndex
SwContentIndex(const SwContentNode *pContentNode, sal_Int32 const nIdx=0)
Definition: index.cxx:27
SwContentIndex & operator=(sal_Int32 const)
Definition: index.cxx:372
bool operator<=(const SwContentIndex &) const
Definition: index.cxx:351
SwContentIndex & ChgValue(const SwContentIndex &rIdx, sal_Int32 nNewValue)
Definition: index.cxx:79
sal_Int32 operator++()
Definition: index.cxx:304
SwContentIndex * m_pPrev
bool operator>=(const SwContentIndex &) const
Definition: index.cxx:365
bool operator<(const SwContentIndex &) const
Definition: index.cxx:344
void Remove()
Definition: index.cxx:161
SwContentIndex * m_pNext
sal_Int32 GetIndex() const
SwContentIndex & Assign(const SwContentNode *, sal_Int32)
Definition: index.cxx:206
sal_Int32 operator-=(sal_Int32 const)
Definition: index.cxx:337
std::ostream & operator<<(std::ostream &s, const SwContentIndex &index)
Definition: index.cxx:382
#define SAL_WARN_IF(condition, area, stream)
index
#define SAL_MAX_INT32