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  {
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 {
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  for (;;)
91  {
92  SwIndex* 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_pIndexReg->m_pFirst = this;
109  pFnd->m_pPrev = this;
110  }
111  }
112  else if (rIdx.m_nIndex < nNewValue)
113  {
114  for (;;)
115  {
116  SwIndex* 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_pIndexReg->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_pIndexReg->m_pLast = this;
147  else
148  m_pNext->m_pPrev = this;
149  }
150 
151  if (m_pIndexReg->m_pFirst == m_pNext)
152  m_pIndexReg->m_pFirst = this;
153  if (m_pIndexReg->m_pLast == m_pPrev)
154  m_pIndexReg->m_pLast = this;
155 
156  m_nIndex = nNewValue;
157 
158  return *this;
159 }
160 
162 {
163  if (!m_pIndexReg)
164  {
165  assert(!m_pPrev && !m_pNext);
166  return;
167  }
168 
169  if (m_pPrev)
170  {
172  }
173  else if (m_pIndexReg->m_pFirst == this)
174  {
176  }
177 
178  if (m_pNext)
179  {
181  }
182  else if (m_pIndexReg->m_pLast == this)
183  {
185  }
186 }
187 
189 {
190  bool bEqual;
191  if (rIdx.m_pIndexReg != m_pIndexReg) // unregister!
192  {
193  Remove();
194  m_pIndexReg = rIdx.m_pIndexReg;
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 
206 SwIndex& SwIndex::Assign( SwIndexReg* pArr, sal_Int32 nIdx )
207 {
208  if (pArr != m_pIndexReg) // unregister!
209  {
210  Remove();
211  m_pIndexReg = 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 
228  : m_pFirst( nullptr ), m_pLast( nullptr )
229 {
230 }
231 
233 {
234  assert(!m_pFirst && !m_pLast && "There are still indices registered");
235 }
236 
238  SwIndex const & rIdx,
239  const sal_Int32 nDiff,
240  const bool bNeg,
241  const bool /* argument is only used in derived class*/ )
242 {
243  SwIndex* pStt = const_cast<SwIndex*>(&rIdx);
244  const sal_Int32 nNewVal = rIdx.m_nIndex;
245  if( bNeg )
246  {
247  const sal_Int32 nLast = rIdx.GetIndex() + nDiff;
248  while (pStt && pStt->m_nIndex == nNewVal)
249  {
250  pStt->m_nIndex = nNewVal;
251  pStt = pStt->m_pPrev;
252  }
253  pStt = rIdx.m_pNext;
254  while (pStt && pStt->m_nIndex >= nNewVal
255  && pStt->m_nIndex <= nLast)
256  {
257  pStt->m_nIndex = nNewVal;
258  pStt = pStt->m_pNext;
259  }
260  while( pStt )
261  {
262  pStt->m_nIndex = pStt->m_nIndex - nDiff;
263  pStt = pStt->m_pNext;
264  }
265  }
266  else
267  {
268  while (pStt && pStt->m_nIndex == nNewVal)
269  {
270  pStt->m_nIndex = pStt->m_nIndex + nDiff;
271  pStt = pStt->m_pPrev;
272  }
273  pStt = rIdx.m_pNext;
274  while( pStt )
275  {
276  // HACK: avoid updating position of cross-ref bookmarks
277  if (!pStt->m_pMark || nullptr == dynamic_cast<
278  ::sw::mark::CrossRefBookmark const*>(pStt->m_pMark))
279  {
280  pStt->m_nIndex = pStt->m_nIndex + nDiff;
281  }
282  pStt = pStt->m_pNext;
283  }
284  }
285 }
286 
288 {
289  if (!(this != &rArr && m_pFirst))
290  return;
291 
292  SwIndex * pIdx = const_cast<SwIndex*>(m_pFirst);
293  SwIndex * pNext;
294  while( pIdx )
295  {
296  pNext = pIdx->m_pNext;
297  pIdx->Assign( &rArr, pIdx->GetIndex() );
298  pIdx = pNext;
299  }
300  m_pFirst = nullptr;
301  m_pLast = nullptr;
302 }
303 
304 #ifdef DBG_UTIL
305 
306 // SwIndex
307 
309 {
310  SAL_WARN_IF( !(m_nIndex < SAL_MAX_INT32), "sw.core",
311  "SwIndex::operator++() wraps around" );
312 
313  ChgValue( *this, m_nIndex+1 );
314  return m_nIndex;
315 }
316 
317 sal_Int32 SwIndex::operator--(int)
318 {
319  SAL_WARN_IF( !(m_nIndex > 0), "sw.core",
320  "SwIndex::operator--(int) wraps around" );
321 
322  const sal_Int32 nOldIndex = m_nIndex;
323  ChgValue( *this, m_nIndex-1 );
324  return nOldIndex;
325 }
326 
328 {
329  SAL_WARN_IF( !( m_nIndex > 0), "sw.core",
330  "SwIndex::operator--() wraps around" );
331  return ChgValue( *this, m_nIndex-1 ).m_nIndex;
332 }
333 
334 sal_Int32 SwIndex::operator+=( sal_Int32 const nVal )
335 {
336  SAL_WARN_IF( !(m_nIndex <= SAL_MAX_INT32 - nVal), "sw.core",
337  "SwIndex SwIndex::operator+=(sal_Int32) wraps around" );
338  return ChgValue( *this, m_nIndex + nVal ).m_nIndex;
339 }
340 
341 sal_Int32 SwIndex::operator-=( sal_Int32 const nVal )
342 {
343  SAL_WARN_IF( !(m_nIndex >= nVal), "sw.core",
344  "SwIndex::operator-=(sal_Int32) wraps around" );
345  return ChgValue( *this, m_nIndex - nVal ).m_nIndex;
346 }
347 
348 bool SwIndex::operator< ( const SwIndex & rIndex ) const
349 {
350  // Attempt to compare indices into different arrays
351  assert(m_pIndexReg == rIndex.m_pIndexReg);
352  return m_nIndex < rIndex.m_nIndex;
353 }
354 
355 bool SwIndex::operator<=( const SwIndex & rIndex ) const
356 {
357  // Attempt to compare indices into different arrays
358  assert(m_pIndexReg == rIndex.m_pIndexReg);
359  return m_nIndex <= rIndex.m_nIndex;
360 }
361 
362 bool SwIndex::operator> ( const SwIndex & rIndex ) const
363 {
364  // Attempt to compare indices into different arrays
365  assert(m_pIndexReg == rIndex.m_pIndexReg);
366  return m_nIndex > rIndex.m_nIndex;
367 }
368 
369 bool SwIndex::operator>=( const SwIndex & rIndex ) const
370 {
371  // Attempt to compare indices into different arrays
372  assert(m_pIndexReg == rIndex.m_pIndexReg);
373  return m_nIndex >= rIndex.m_nIndex;
374 }
375 
376 SwIndex& SwIndex::operator= ( sal_Int32 const nVal )
377 {
378  if (m_nIndex != nVal)
379  ChgValue( *this, nVal );
380 
381  return *this;
382 }
383 
384 #endif
385 
386 std::ostream& operator <<(std::ostream& s, const SwIndex& index)
387 {
388  return s << "SwIndex offset (" << index.GetIndex() << ")";
389 }
390 
391 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::ostream & operator<<(std::ostream &s, const SwIndex &index)
Definition: index.cxx:386
void Remove()
Definition: index.cxx:161
sal_Int32 operator--()
Definition: index.cxx:327
SwIndex(SwIndexReg *const pReg, sal_Int32 const nIdx=0)
Definition: index.cxx:27
SwIndex * m_pPrev
Definition: index.hxx:42
bool operator<=(const SwIndex &) const
Definition: index.cxx:355
SwIndex * m_pNext
Definition: index.hxx:41
SwIndexReg()
Definition: index.cxx:227
SwIndex & ChgValue(const SwIndex &rIdx, sal_Int32 nNewValue)
Definition: index.cxx:79
sal_Int32 m_nIndex
Definition: index.hxx:38
sal_Int32 operator++()
Definition: index.cxx:308
SwIndexReg * m_pIndexReg
Definition: index.hxx:39
void MoveTo(SwIndexReg &rArr)
Definition: index.cxx:287
const SwIndex * m_pLast
Definition: index.hxx:112
bool operator<(const SwIndex &) const
Definition: index.cxx:348
void Init(sal_Int32 const nIdx)
Definition: index.cxx:56
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
virtual void Update(SwIndex const &rPos, const sal_Int32 nChangeLen, const bool bNegative=false, const bool bDelete=false)
Definition: index.cxx:237
sal_Int32 operator-=(sal_Int32 const )
Definition: index.cxx:341
#define SAL_MAX_INT32
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
Marks a character position inside a document model node.
Definition: index.hxx:33
void SetMark(const sw::mark::IMark *pMark)
Definition: index.cxx:222
#define SAL_WARN_IF(condition, area, stream)
virtual ~SwIndexReg()
Definition: index.cxx:232
sal_Int32 GetIndex() const
Definition: index.hxx:91
SwIndex & operator=(sal_Int32 const )
Definition: index.cxx:376
bool operator>(const SwIndex &) const
Definition: index.cxx:362
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:45
const SwIndex * m_pFirst
Definition: index.hxx:111
bool operator>=(const SwIndex &) const
Definition: index.cxx:369
sal_Int32 operator+=(sal_Int32 const )
Definition: index.cxx:334