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