Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "txatbase.hxx"
31 : : #include "ndhints.hxx"
32 : : #include <txtatr.hxx>
33 : :
34 : : #ifdef DBG_UTIL
35 : : #include <pam.hxx>
36 : : #endif
37 : :
38 : :
39 : : inline void DumpHints(const SwpHtStart &, const SwpHtEnd &) { }
40 : :
41 : : /*************************************************************************
42 : : * IsLessStart()
43 : : *************************************************************************/
44 : :
45 : : // Sortierreihenfolge: Start, Ende (umgekehrt!), Which-Wert (umgekehrt!),
46 : : // als letztes die Adresse selbst
47 : :
48 : 765918 : static sal_Bool lcl_IsLessStart( const SwTxtAttr &rHt1, const SwTxtAttr &rHt2 )
49 : : {
50 [ + + ]: 765918 : if ( *rHt1.GetStart() == *rHt2.GetStart() )
51 : : {
52 : 40942 : const xub_StrLen nHt1 = *rHt1.GetAnyEnd();
53 : 40942 : const xub_StrLen nHt2 = *rHt2.GetAnyEnd();
54 [ + + ]: 40942 : if ( nHt1 == nHt2 )
55 : : {
56 : 40096 : const sal_uInt16 nWhich1 = rHt1.Which();
57 : 40096 : const sal_uInt16 nWhich2 = rHt2.Which();
58 [ + + ]: 40096 : if ( nWhich1 == nWhich2 )
59 : : {
60 [ - + ]: 38531 : if ( RES_TXTATR_CHARFMT == nWhich1 )
61 : : {
62 : 0 : const sal_uInt16 nS1 = static_cast<const SwTxtCharFmt&>(rHt1).GetSortNumber();
63 : 0 : const sal_uInt16 nS2 = static_cast<const SwTxtCharFmt&>(rHt2).GetSortNumber();
64 : : OSL_ENSURE( nS1 != nS2, "AUTOSTYLES: lcl_IsLessStart trouble" );
65 [ # # ]: 0 : if ( nS1 != nS2 ) // robust
66 : 0 : return nS1 < nS2;
67 : : }
68 : :
69 : 38531 : return (long)&rHt1 < (long)&rHt2;
70 : : }
71 : : // order is important! for requirements see hintids.hxx
72 : 1565 : return ( nWhich1 > nWhich2 );
73 : : }
74 : 846 : return ( nHt1 > nHt2 );
75 : : }
76 : 765918 : return ( *rHt1.GetStart() < *rHt2.GetStart() );
77 : : }
78 : :
79 : : /*************************************************************************
80 : : * inline IsLessEnd()
81 : : *************************************************************************/
82 : :
83 : : // Zuerst nach Ende danach nach Ptr
84 : 786719 : static sal_Bool lcl_IsLessEnd( const SwTxtAttr &rHt1, const SwTxtAttr &rHt2 )
85 : : {
86 : 786719 : const xub_StrLen nHt1 = *rHt1.GetAnyEnd();
87 : 786719 : const xub_StrLen nHt2 = *rHt2.GetAnyEnd();
88 [ + + ]: 786719 : if ( nHt1 == nHt2 )
89 : : {
90 [ + + ]: 52807 : if ( *rHt1.GetStart() == *rHt2.GetStart() )
91 : : {
92 : 49250 : const sal_uInt16 nWhich1 = rHt1.Which();
93 : 49250 : const sal_uInt16 nWhich2 = rHt2.Which();
94 [ + + ]: 49250 : if ( nWhich1 == nWhich2 )
95 : : {
96 [ + + ]: 47120 : if ( RES_TXTATR_CHARFMT == nWhich1 )
97 : : {
98 : 48 : const sal_uInt16 nS1 = static_cast<const SwTxtCharFmt&>(rHt1).GetSortNumber();
99 : 48 : const sal_uInt16 nS2 = static_cast<const SwTxtCharFmt&>(rHt2).GetSortNumber();
100 : : OSL_ENSURE( nS1 != nS2, "AUTOSTYLES: lcl_IsLessEnd trouble" );
101 [ - + ]: 48 : if ( nS1 != nS2 ) // robust
102 : 0 : return nS1 > nS2;
103 : : }
104 : :
105 : 47120 : return (long)&rHt1 > (long)&rHt2;
106 : : }
107 : : // order is important! for requirements see hintids.hxx
108 : 2130 : return ( nWhich1 < nWhich2 );
109 : : }
110 : : else
111 : 3557 : return ( *rHt1.GetStart() > *rHt2.GetStart() );
112 : : }
113 : 786719 : return ( nHt1 < nHt2 );
114 : : }
115 : :
116 : 86186 : bool CompareSwpHtStart::operator()(SwTxtAttr* const lhs, SwTxtAttr* const rhs) const
117 : : {
118 : 86186 : return lcl_IsLessStart( *lhs, *rhs );
119 : : }
120 : :
121 : 96049 : bool CompareSwpHtEnd::operator()(SwTxtAttr* const lhs, SwTxtAttr* const rhs) const
122 : : {
123 : 96049 : return lcl_IsLessEnd( *lhs, *rhs );
124 : : }
125 : :
126 : : /*************************************************************************
127 : : * class SwpHintsArr
128 : : *************************************************************************/
129 : :
130 : 31748 : void SwpHintsArray::Insert( const SwTxtAttr *pHt )
131 : : {
132 : 31748 : Resort();
133 : : assert(m_HintStarts.find(const_cast<SwTxtAttr*>(pHt))
134 : : == m_HintStarts.end()); // "Insert: hint already in HtStart"
135 : : assert(m_HintEnds.find(const_cast<SwTxtAttr*>(pHt))
136 : : == m_HintEnds.end()); // "Insert: hint already in HtEnd"
137 [ + - ]: 31748 : m_HintStarts.insert( const_cast<SwTxtAttr*>(pHt) );
138 [ + - ]: 31748 : m_HintEnds .insert( const_cast<SwTxtAttr*>(pHt) );
139 : 31748 : }
140 : :
141 : 23081 : void SwpHintsArray::DeleteAtPos( const sal_uInt16 nPos )
142 : : {
143 : : // optimization: nPos is the position in the Starts array
144 [ + - ]: 23081 : SwTxtAttr *pHt = m_HintStarts[ nPos ];
145 [ + - ][ + - ]: 23081 : m_HintStarts.erase( m_HintStarts.begin() + nPos );
146 : :
147 [ + - ]: 23081 : Resort();
148 : :
149 [ + - ]: 23081 : bool const done = m_HintEnds.erase(pHt);
150 : : assert(done);
151 : : (void) done; // unused in NDEBUG
152 : 23081 : }
153 : :
154 : 1245 : sal_uInt16 SwpHintsArray::GetPos( const SwTxtAttr *pHt ) const
155 : : {
156 : : // DO NOT use find() here!
157 : : // if called from SwTxtNode::InsertItem, pHt has already been deleted,
158 : : // so it cannot be dereferenced
159 [ + + ]: 1758 : for (size_t i = 0; i < m_HintStarts.size(); ++i)
160 : : {
161 [ + + ]: 1753 : if (m_HintStarts[i] == pHt)
162 : : {
163 : 1240 : return i;
164 : : }
165 : : }
166 : 1245 : return USHRT_MAX;
167 : : }
168 : :
169 : : #ifdef DBG_UTIL
170 : :
171 : : /*************************************************************************
172 : : * SwpHintsArray::Check()
173 : : *************************************************************************/
174 : :
175 : :
176 : : #define CHECK_ERR(cond, text) \
177 : : if(!(cond)) \
178 : : { \
179 : : OSL_ENSURE(!this, text); \
180 : : DumpHints(m_HintStarts, m_HintEnds); \
181 : : return !(const_cast<SwpHintsArray*>(this))->Resort(); \
182 : : }
183 : :
184 : : bool SwpHintsArray::Check() const
185 : : {
186 : : // 1) gleiche Anzahl in beiden Arrays
187 : : CHECK_ERR( m_HintStarts.size() == m_HintEnds.size(),
188 : : "HintsCheck: wrong sizes" );
189 : : xub_StrLen nLastStart = 0;
190 : : xub_StrLen nLastEnd = 0;
191 : :
192 : : const SwTxtAttr *pLastStart = 0;
193 : : const SwTxtAttr *pLastEnd = 0;
194 : :
195 : : for( sal_uInt16 i = 0; i < Count(); ++i )
196 : : {
197 : : // --- Start-Kontrolle ---
198 : :
199 : : // 2a) gueltiger Pointer? vgl. DELETEFF
200 : : const SwTxtAttr *pHt = m_HintStarts[i];
201 : : CHECK_ERR( 0xFF != *(unsigned char*)pHt, "HintsCheck: start ptr was deleted" );
202 : :
203 : : // 3a) Stimmt die Start-Sortierung?
204 : : xub_StrLen nIdx = *pHt->GetStart();
205 : : CHECK_ERR( nIdx >= nLastStart, "HintsCheck: starts are unsorted" );
206 : :
207 : : // 4a) IsLessStart-Konsistenz
208 : : if( pLastStart )
209 : : CHECK_ERR( lcl_IsLessStart( *pLastStart, *pHt ), "HintsCheck: IsLastStart" );
210 : :
211 : : nLastStart = nIdx;
212 : : pLastStart = pHt;
213 : :
214 : : // --- End-Kontrolle ---
215 : :
216 : : // 2b) gueltiger Pointer? vgl. DELETEFF
217 : : const SwTxtAttr *pHtEnd = m_HintEnds[i];
218 : : CHECK_ERR( 0xFF != *(unsigned char*)pHtEnd, "HintsCheck: end ptr was deleted" );
219 : :
220 : : // 3b) Stimmt die End-Sortierung?
221 : : nIdx = *pHtEnd->GetAnyEnd();
222 : : CHECK_ERR( nIdx >= nLastEnd, "HintsCheck: ends are unsorted" );
223 : : nLastEnd = nIdx;
224 : :
225 : : // 4b) IsLessEnd-Konsistenz
226 : : if( pLastEnd )
227 : : CHECK_ERR( lcl_IsLessEnd( *pLastEnd, *pHtEnd ), "HintsCheck: IsLastEnd" );
228 : :
229 : : nLastEnd = nIdx;
230 : : pLastEnd = pHtEnd;
231 : :
232 : : // --- Ueberkreuzungen ---
233 : :
234 : : // 5) gleiche Pointer in beiden Arrays
235 : : if (m_HintStarts.find(const_cast<SwTxtAttr*>(pHt)) == m_HintStarts.end())
236 : : nIdx = STRING_LEN;
237 : :
238 : : CHECK_ERR( STRING_LEN != nIdx, "HintsCheck: no GetStartOf" );
239 : :
240 : : // 6) gleiche Pointer in beiden Arrays
241 : : if (m_HintEnds.find(const_cast<SwTxtAttr*>(pHt)) == m_HintEnds.end())
242 : : nIdx = STRING_LEN;
243 : :
244 : : CHECK_ERR( STRING_LEN != nIdx, "HintsCheck: no GetEndOf" );
245 : :
246 : : // 7a) character attributes in array?
247 : : sal_uInt16 nWhich = pHt->Which();
248 : : CHECK_ERR( !isCHRATR(nWhich),
249 : : "HintsCheck: Character attribute in start array" );
250 : :
251 : : // 7b) character attributes in array?
252 : : nWhich = pHtEnd->Which();
253 : : CHECK_ERR( !isCHRATR(nWhich),
254 : : "HintsCheck: Character attribute in end array" );
255 : :
256 : : // 8) style portion check
257 : : const SwTxtAttr* pHtThis = m_HintStarts[i];
258 : : const SwTxtAttr* pHtLast = i > 0 ? m_HintStarts[i-1] : 0;
259 : : CHECK_ERR( 0 == i ||
260 : : ( RES_TXTATR_CHARFMT != pHtLast->Which() && RES_TXTATR_AUTOFMT != pHtLast->Which() ) ||
261 : : ( RES_TXTATR_CHARFMT != pHtThis->Which() && RES_TXTATR_AUTOFMT != pHtThis->Which() ) ||
262 : : ( *pHtThis->GetStart() >= *pHtLast->GetEnd() ) ||
263 : : ( ( ( (*pHtThis->GetStart() == *pHtLast->GetStart())
264 : : && (*pHtThis->GetEnd() == *pHtLast->GetEnd())
265 : : ) // same range
266 : : || (*pHtThis->GetStart() == *pHtThis->GetEnd())
267 : : )
268 : : && ( (pHtThis->Which() != RES_TXTATR_AUTOFMT)
269 : : || (pHtLast->Which() != RES_TXTATR_AUTOFMT)
270 : : ) // never two AUTOFMT on same range
271 : : ),
272 : : "HintsCheck: Portion inconsistency. "
273 : : "This can be temporarily ok during undo operations" );
274 : :
275 : : // 9) nesting portion check
276 : : if (pHtThis->IsNesting())
277 : : {
278 : : for ( sal_uInt16 j = 0; j < Count(); ++j )
279 : : {
280 : : SwTxtAttr const * const pOther( m_HintStarts[j] );
281 : : if ( pOther->IsNesting() && (i != j) )
282 : : {
283 : : SwComparePosition cmp = ComparePosition(
284 : : *pHtThis->GetStart(), *pHtThis->GetEnd(),
285 : : *pOther->GetStart(), *pOther->GetEnd());
286 : : CHECK_ERR( (POS_OVERLAP_BEFORE != cmp) &&
287 : : (POS_OVERLAP_BEHIND != cmp),
288 : : "HintsCheck: overlapping nesting hints!!!" );
289 : : }
290 : : }
291 : : }
292 : :
293 : : // 10) dummy char check (unfortunately cannot check SwTxtNode::m_Text)
294 : : if (pHtThis->HasDummyChar())
295 : : {
296 : : for ( sal_uInt16 j = 0; j < i; ++j )
297 : : {
298 : : SwTxtAttr const * const pOther( m_HintStarts[j] );
299 : : if (pOther->HasDummyChar())
300 : : {
301 : : CHECK_ERR( (*pOther->GetStart() != *pHtThis->GetStart()),
302 : : "HintsCheck: multiple hints claim same CH_TXTATR!");
303 : : }
304 : : }
305 : : }
306 : : }
307 : : return true;
308 : : }
309 : :
310 : : #endif /* DBG_UTIL */
311 : :
312 : : /*************************************************************************
313 : : * SwpHintsArray::Resort()
314 : : *************************************************************************/
315 : :
316 : : // Resort() wird vor jedem Insert und Delete gerufen.
317 : : // Wenn Textmasse geloescht wird, so werden die Indizes in
318 : : // ndtxt.cxx angepasst. Leider erfolgt noch keine Neusortierung
319 : : // auf gleichen Positionen.
320 : :
321 : 81295 : bool SwpHintsArray::Resort()
322 : : {
323 : 81295 : bool bResort = false;
324 : 81295 : const SwTxtAttr *pLast = 0;
325 : : sal_uInt16 i;
326 : :
327 [ + + ]: 814179 : for ( i = 0; i < m_HintStarts.size(); ++i )
328 : : {
329 [ + - ]: 732884 : SwTxtAttr *pHt = m_HintStarts[i];
330 [ + + ][ + - ]: 732884 : if( pLast && !lcl_IsLessStart( *pLast, *pHt ) )
[ + + ][ + + ]
331 : : {
332 [ + - ][ + - ]: 8 : m_HintStarts.erase( m_HintStarts.begin() + i );
333 [ + - ]: 8 : m_HintStarts.insert( pHt );
334 [ + - ]: 8 : pHt = m_HintStarts[i];
335 [ - + ]: 8 : if ( pHt != pLast )
336 : 0 : --i;
337 : 8 : bResort = true;
338 : : }
339 : 732884 : pLast = pHt;
340 : : }
341 : :
342 : 81295 : pLast = 0;
343 [ + + ]: 837260 : for ( i = 0; i < m_HintEnds.size(); ++i )
344 : : {
345 [ + - ]: 755965 : SwTxtAttr *pHt = m_HintEnds[i];
346 [ + + ][ + - ]: 755965 : if( pLast && !lcl_IsLessEnd( *pLast, *pHt ) )
[ + + ][ + + ]
347 : : {
348 [ + - ][ + - ]: 8 : m_HintEnds.erase( m_HintEnds.begin() + i );
349 [ + - ]: 8 : m_HintEnds.insert( pHt );
350 [ + - ]: 8 : pHt = m_HintEnds[i]; // normalerweise == pLast
351 : : // Wenn die Unordnung etwas groesser ist (24200),
352 : : // muessen wir Position i erneut vergleichen.
353 [ - + ]: 8 : if ( pLast != pHt )
354 : 0 : --i;
355 : 8 : bResort = true;
356 : : }
357 : 755965 : pLast = pHt;
358 : : }
359 : 81295 : return bResort;
360 : : }
361 : :
362 : :
363 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|