Line data Source code
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 <comphelper/string.hxx>
21 : #include <vcl/wrkwin.hxx>
22 : #include <vcl/dialog.hxx>
23 : #include <vcl/msgbox.hxx>
24 : #include <vcl/svapp.hxx>
25 :
26 : #include <editeng/tstpitem.hxx>
27 : #include <editeng/colritem.hxx>
28 : #include <editeng/fontitem.hxx>
29 : #include <editeng/crossedoutitem.hxx>
30 : #include <editeng/fhgtitem.hxx>
31 : #include <editeng/flditem.hxx>
32 : #include <editeng/postitem.hxx>
33 : #include <editeng/kernitem.hxx>
34 : #include <editeng/wrlmitem.hxx>
35 : #include <editeng/wghtitem.hxx>
36 : #include <editeng/udlnitem.hxx>
37 : #include <editeng/cmapitem.hxx>
38 : #include <editeng/contouritem.hxx>
39 : #include <editeng/escapementitem.hxx>
40 : #include <editeng/shdditem.hxx>
41 : #include <editeng/autokernitem.hxx>
42 : #include <editeng/charsetcoloritem.hxx>
43 : #include <editeng/langitem.hxx>
44 : #include <editeng/emphasismarkitem.hxx>
45 : #include <editeng/charscaleitem.hxx>
46 : #include <editeng/charreliefitem.hxx>
47 : #include <editeng/xmlcnitm.hxx>
48 : #include <editeng/editids.hrc>
49 : #include "editeng/editdata.hxx"
50 : #include "editeng/lrspitem.hxx"
51 : #include "editeng/ulspitem.hxx"
52 : #include "editeng/lspcitem.hxx"
53 :
54 : #include <editdoc.hxx>
55 : #include <editdbg.hxx>
56 : #include <editeng/eerdll.hxx>
57 : #include <eerdll2.hxx>
58 : #include <impedit.hxx>
59 :
60 : #include <rtl/ustrbuf.hxx>
61 :
62 : #include <svl/grabbagitem.hxx>
63 : #include <tools/stream.hxx>
64 : #include <tools/debug.hxx>
65 : #include <com/sun/star/i18n/ScriptType.hpp>
66 :
67 : #include <cassert>
68 : #include <limits>
69 :
70 : #include <boost/bind.hpp>
71 :
72 : using namespace ::com::sun::star;
73 :
74 :
75 :
76 :
77 5349494 : sal_uInt16 GetScriptItemId( sal_uInt16 nItemId, SvtScriptType nScriptType )
78 : {
79 5349494 : sal_uInt16 nId = nItemId;
80 :
81 5349494 : if ( ( nScriptType == SvtScriptType::ASIAN ) ||
82 : ( nScriptType == SvtScriptType::COMPLEX ) )
83 : {
84 0 : switch ( nItemId )
85 : {
86 : case EE_CHAR_LANGUAGE:
87 0 : nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_LANGUAGE_CJK : EE_CHAR_LANGUAGE_CTL;
88 0 : break;
89 : case EE_CHAR_FONTINFO:
90 0 : nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_FONTINFO_CJK : EE_CHAR_FONTINFO_CTL;
91 0 : break;
92 : case EE_CHAR_FONTHEIGHT:
93 0 : nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_FONTHEIGHT_CJK : EE_CHAR_FONTHEIGHT_CTL;
94 0 : break;
95 : case EE_CHAR_WEIGHT:
96 0 : nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_WEIGHT_CJK : EE_CHAR_WEIGHT_CTL;
97 0 : break;
98 : case EE_CHAR_ITALIC:
99 0 : nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_ITALIC_CJK : EE_CHAR_ITALIC_CTL;
100 0 : break;
101 : }
102 : }
103 :
104 5349494 : return nId;
105 : }
106 :
107 519004 : bool IsScriptItemValid( sal_uInt16 nItemId, short nScriptType )
108 : {
109 519004 : bool bValid = true;
110 :
111 519004 : switch ( nItemId )
112 : {
113 : case EE_CHAR_LANGUAGE:
114 11758 : bValid = nScriptType == i18n::ScriptType::LATIN;
115 11758 : break;
116 : case EE_CHAR_LANGUAGE_CJK:
117 10141 : bValid = nScriptType == i18n::ScriptType::ASIAN;
118 10141 : break;
119 : case EE_CHAR_LANGUAGE_CTL:
120 10600 : bValid = nScriptType == i18n::ScriptType::COMPLEX;
121 10600 : break;
122 : case EE_CHAR_FONTINFO:
123 25908 : bValid = nScriptType == i18n::ScriptType::LATIN;
124 25908 : break;
125 : case EE_CHAR_FONTINFO_CJK:
126 18414 : bValid = nScriptType == i18n::ScriptType::ASIAN;
127 18414 : break;
128 : case EE_CHAR_FONTINFO_CTL:
129 17481 : bValid = nScriptType == i18n::ScriptType::COMPLEX;
130 17481 : break;
131 : case EE_CHAR_FONTHEIGHT:
132 36930 : bValid = nScriptType == i18n::ScriptType::LATIN;
133 36930 : break;
134 : case EE_CHAR_FONTHEIGHT_CJK:
135 25129 : bValid = nScriptType == i18n::ScriptType::ASIAN;
136 25129 : break;
137 : case EE_CHAR_FONTHEIGHT_CTL:
138 26588 : bValid = nScriptType == i18n::ScriptType::COMPLEX;
139 26588 : break;
140 : case EE_CHAR_WEIGHT:
141 22022 : bValid = nScriptType == i18n::ScriptType::LATIN;
142 22022 : break;
143 : case EE_CHAR_WEIGHT_CJK:
144 18288 : bValid = nScriptType == i18n::ScriptType::ASIAN;
145 18288 : break;
146 : case EE_CHAR_WEIGHT_CTL:
147 18836 : bValid = nScriptType == i18n::ScriptType::COMPLEX;
148 18836 : break;
149 : case EE_CHAR_ITALIC:
150 17875 : bValid = nScriptType == i18n::ScriptType::LATIN;
151 17875 : break;
152 : case EE_CHAR_ITALIC_CJK:
153 14198 : bValid = nScriptType == i18n::ScriptType::ASIAN;
154 14198 : break;
155 : case EE_CHAR_ITALIC_CTL:
156 13822 : bValid = nScriptType == i18n::ScriptType::COMPLEX;
157 13822 : break;
158 : }
159 :
160 519004 : return bValid;
161 : }
162 :
163 : const SfxItemInfo aItemInfos[EDITITEMCOUNT] = {
164 : { SID_ATTR_FRAMEDIRECTION, SfxItemPoolFlags::POOLABLE }, // EE_PARA_WRITINGDIR
165 : { 0, SfxItemPoolFlags::POOLABLE }, // EE_PARA_XMLATTRIBS
166 : { SID_ATTR_PARA_HANGPUNCTUATION, SfxItemPoolFlags::POOLABLE }, // EE_PARA_HANGINGPUNCTUATION
167 : { SID_ATTR_PARA_FORBIDDEN_RULES, SfxItemPoolFlags::POOLABLE },
168 : { SID_ATTR_PARA_SCRIPTSPACE, SfxItemPoolFlags::POOLABLE }, // EE_PARA_ASIANCJKSPACING
169 : { SID_ATTR_NUMBERING_RULE, SfxItemPoolFlags::POOLABLE }, // EE_PARA_NUMBULL
170 : { 0, SfxItemPoolFlags::POOLABLE }, // EE_PARA_HYPHENATE
171 : { 0, SfxItemPoolFlags::POOLABLE }, // EE_PARA_BULLETSTATE
172 : { 0, SfxItemPoolFlags::POOLABLE }, // EE_PARA_OUTLLRSPACE
173 : { SID_ATTR_PARA_OUTLLEVEL, SfxItemPoolFlags::POOLABLE }, // EE_PARA_OUTLLEVEL
174 : { SID_ATTR_PARA_BULLET, SfxItemPoolFlags::POOLABLE }, // EE_PARA_BULLET
175 : { SID_ATTR_LRSPACE, SfxItemPoolFlags::POOLABLE }, // EE_PARA_LRSPACE
176 : { SID_ATTR_ULSPACE, SfxItemPoolFlags::POOLABLE }, // EE_PARA_ULSPACE
177 : { SID_ATTR_PARA_LINESPACE, SfxItemPoolFlags::POOLABLE }, // EE_PARA_SBL
178 : { SID_ATTR_PARA_ADJUST, SfxItemPoolFlags::POOLABLE }, // EE_PARA_JUST
179 : { SID_ATTR_TABSTOP, SfxItemPoolFlags::POOLABLE }, // EE_PARA_TABS
180 : { SID_ATTR_ALIGN_HOR_JUSTIFY_METHOD, SfxItemPoolFlags::POOLABLE }, // EE_PARA_JUST_METHOD
181 : { SID_ATTR_ALIGN_VER_JUSTIFY, SfxItemPoolFlags::POOLABLE }, // EE_PARA_VER_JUST
182 : { SID_ATTR_CHAR_COLOR, SfxItemPoolFlags::POOLABLE },
183 : { SID_ATTR_CHAR_FONT, SfxItemPoolFlags::POOLABLE },
184 : { SID_ATTR_CHAR_FONTHEIGHT, SfxItemPoolFlags::POOLABLE },
185 : { SID_ATTR_CHAR_SCALEWIDTH, SfxItemPoolFlags::POOLABLE },
186 : { SID_ATTR_CHAR_WEIGHT, SfxItemPoolFlags::POOLABLE },
187 : { SID_ATTR_CHAR_UNDERLINE, SfxItemPoolFlags::POOLABLE },
188 : { SID_ATTR_CHAR_STRIKEOUT, SfxItemPoolFlags::POOLABLE },
189 : { SID_ATTR_CHAR_POSTURE, SfxItemPoolFlags::POOLABLE },
190 : { SID_ATTR_CHAR_CONTOUR, SfxItemPoolFlags::POOLABLE },
191 : { SID_ATTR_CHAR_SHADOWED, SfxItemPoolFlags::POOLABLE },
192 : { SID_ATTR_CHAR_ESCAPEMENT, SfxItemPoolFlags::POOLABLE },
193 : { SID_ATTR_CHAR_AUTOKERN, SfxItemPoolFlags::POOLABLE },
194 : { SID_ATTR_CHAR_KERNING, SfxItemPoolFlags::POOLABLE },
195 : { SID_ATTR_CHAR_WORDLINEMODE, SfxItemPoolFlags::POOLABLE },
196 : { SID_ATTR_CHAR_LANGUAGE, SfxItemPoolFlags::POOLABLE },
197 : { SID_ATTR_CHAR_CJK_LANGUAGE, SfxItemPoolFlags::POOLABLE },
198 : { SID_ATTR_CHAR_CTL_LANGUAGE, SfxItemPoolFlags::POOLABLE },
199 : { SID_ATTR_CHAR_CJK_FONT, SfxItemPoolFlags::POOLABLE },
200 : { SID_ATTR_CHAR_CTL_FONT, SfxItemPoolFlags::POOLABLE },
201 : { SID_ATTR_CHAR_CJK_FONTHEIGHT, SfxItemPoolFlags::POOLABLE },
202 : { SID_ATTR_CHAR_CTL_FONTHEIGHT, SfxItemPoolFlags::POOLABLE },
203 : { SID_ATTR_CHAR_CJK_WEIGHT, SfxItemPoolFlags::POOLABLE },
204 : { SID_ATTR_CHAR_CTL_WEIGHT, SfxItemPoolFlags::POOLABLE },
205 : { SID_ATTR_CHAR_CJK_POSTURE, SfxItemPoolFlags::POOLABLE },
206 : { SID_ATTR_CHAR_CTL_POSTURE, SfxItemPoolFlags::POOLABLE },
207 : { SID_ATTR_CHAR_EMPHASISMARK, SfxItemPoolFlags::POOLABLE },
208 : { SID_ATTR_CHAR_RELIEF, SfxItemPoolFlags::POOLABLE },
209 : { 0, SfxItemPoolFlags::POOLABLE }, // EE_CHAR_RUBI_DUMMY
210 : { 0, SfxItemPoolFlags::POOLABLE }, // EE_CHAR_XMLATTRIBS
211 : { SID_ATTR_CHAR_OVERLINE, SfxItemPoolFlags::POOLABLE },
212 : { SID_ATTR_CHAR_CASEMAP, SfxItemPoolFlags::POOLABLE }, // EE_CHAR_CASEMAP
213 : { SID_ATTR_CHAR_GRABBAG, SfxItemPoolFlags::POOLABLE }, // EE_CHAR_GRABBAG
214 : { SID_ATTR_CHAR_BACK_COLOR, SfxItemPoolFlags::POOLABLE }, // EE_CHAR_BKGCOLOR
215 : { 0, SfxItemPoolFlags::POOLABLE }, // EE_FEATURE_TAB
216 : { 0, SfxItemPoolFlags::POOLABLE }, // EE_FEATURE_LINEBR
217 : { SID_ATTR_CHAR_CHARSETCOLOR, SfxItemPoolFlags::POOLABLE }, // EE_FEATURE_NOTCONV
218 : { SID_FIELD, SfxItemPoolFlags::POOLABLE }
219 : };
220 :
221 : const sal_uInt16 aV1Map[] = {
222 : 3999, 4001, 4002, 4003, 4004, 4005, 4006,
223 : 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4017, 4018, 4019 // MI: 4019?
224 : };
225 :
226 : const sal_uInt16 aV2Map[] = {
227 : 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009,
228 : 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4018, 4019, 4020
229 : };
230 :
231 : const sal_uInt16 aV3Map[] = {
232 : 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007,
233 : 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019,
234 : 4020, 4021
235 : };
236 :
237 : const sal_uInt16 aV4Map[] = {
238 : 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003,
239 : 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013,
240 : 4014, 4015, 4016, 4017, 4018,
241 : /* CJK Items inserted here: EE_CHAR_LANGUAGE - EE_CHAR_XMLATTRIBS */
242 : 4034, 4035, 4036, 4037
243 : };
244 :
245 : const sal_uInt16 aV5Map[] = {
246 : 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003,
247 : 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013,
248 : 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023,
249 : 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033,
250 : /* EE_CHAR_OVERLINE inserted here */
251 : 4035, 4036, 4037, 4038
252 : };
253 :
254 : const sal_uInt16 aV6Map[] = {
255 : 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003,
256 : 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013,
257 : 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023,
258 : 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033,
259 : 4035, 4036, 4037, 4038,
260 : /* EE_CHAR_GRABBAG inserted here */
261 : 4039
262 : };
263 :
264 258408 : EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, sal_Int32 nS, sal_Int32 nE )
265 : {
266 : // Create a new attribute in the pool
267 258408 : const SfxPoolItem& rNew = rPool.Put( rAttr );
268 :
269 258408 : EditCharAttrib* pNew = 0;
270 258408 : switch( rNew.Which() )
271 : {
272 : case EE_CHAR_LANGUAGE:
273 : case EE_CHAR_LANGUAGE_CJK:
274 : case EE_CHAR_LANGUAGE_CTL:
275 : {
276 24384 : pNew = new EditCharAttribLanguage( static_cast<const SvxLanguageItem&>(rNew), nS, nE );
277 : }
278 24384 : break;
279 : case EE_CHAR_COLOR:
280 : {
281 19289 : pNew = new EditCharAttribColor( static_cast<const SvxColorItem&>(rNew), nS, nE );
282 : }
283 19289 : break;
284 : case EE_CHAR_FONTINFO:
285 : case EE_CHAR_FONTINFO_CJK:
286 : case EE_CHAR_FONTINFO_CTL:
287 : {
288 35254 : pNew = new EditCharAttribFont( static_cast<const SvxFontItem&>(rNew), nS, nE );
289 : }
290 35254 : break;
291 : case EE_CHAR_FONTHEIGHT:
292 : case EE_CHAR_FONTHEIGHT_CJK:
293 : case EE_CHAR_FONTHEIGHT_CTL:
294 : {
295 50122 : pNew = new EditCharAttribFontHeight( static_cast<const SvxFontHeightItem&>(rNew), nS, nE );
296 : }
297 50122 : break;
298 : case EE_CHAR_FONTWIDTH:
299 : {
300 2150 : pNew = new EditCharAttribFontWidth( static_cast<const SvxCharScaleWidthItem&>(rNew), nS, nE );
301 : }
302 2150 : break;
303 : case EE_CHAR_WEIGHT:
304 : case EE_CHAR_WEIGHT_CJK:
305 : case EE_CHAR_WEIGHT_CTL:
306 : {
307 32242 : pNew = new EditCharAttribWeight( static_cast<const SvxWeightItem&>(rNew), nS, nE );
308 : }
309 32242 : break;
310 : case EE_CHAR_UNDERLINE:
311 : {
312 7950 : pNew = new EditCharAttribUnderline( static_cast<const SvxUnderlineItem&>(rNew), nS, nE );
313 : }
314 7950 : break;
315 : case EE_CHAR_OVERLINE:
316 : {
317 1636 : pNew = new EditCharAttribOverline( static_cast<const SvxOverlineItem&>(rNew), nS, nE );
318 : }
319 1636 : break;
320 : case EE_CHAR_EMPHASISMARK:
321 : {
322 2478 : pNew = new EditCharAttribEmphasisMark( static_cast<const SvxEmphasisMarkItem&>(rNew), nS, nE );
323 : }
324 2478 : break;
325 : case EE_CHAR_RELIEF:
326 : {
327 2155 : pNew = new EditCharAttribRelief( static_cast<const SvxCharReliefItem&>(rNew), nS, nE );
328 : }
329 2155 : break;
330 : case EE_CHAR_STRIKEOUT:
331 : {
332 6774 : pNew = new EditCharAttribStrikeout( static_cast<const SvxCrossedOutItem&>(rNew), nS, nE );
333 : }
334 6774 : break;
335 : case EE_CHAR_ITALIC:
336 : case EE_CHAR_ITALIC_CJK:
337 : case EE_CHAR_ITALIC_CTL:
338 : {
339 18649 : pNew = new EditCharAttribItalic( static_cast<const SvxPostureItem&>(rNew), nS, nE );
340 : }
341 18649 : break;
342 : case EE_CHAR_OUTLINE:
343 : {
344 2927 : pNew = new EditCharAttribOutline( static_cast<const SvxContourItem&>(rNew), nS, nE );
345 : }
346 2927 : break;
347 : case EE_CHAR_SHADOW:
348 : {
349 2972 : pNew = new EditCharAttribShadow( static_cast<const SvxShadowedItem&>(rNew), nS, nE );
350 : }
351 2972 : break;
352 : case EE_CHAR_ESCAPEMENT:
353 : {
354 6879 : pNew = new EditCharAttribEscapement( static_cast<const SvxEscapementItem&>(rNew), nS, nE );
355 : }
356 6879 : break;
357 : case EE_CHAR_PAIRKERNING:
358 : {
359 2076 : pNew = new EditCharAttribPairKerning( static_cast<const SvxAutoKernItem&>(rNew), nS, nE );
360 : }
361 2076 : break;
362 : case EE_CHAR_KERNING:
363 : {
364 6018 : pNew = new EditCharAttribKerning( static_cast<const SvxKerningItem&>(rNew), nS, nE );
365 : }
366 6018 : break;
367 : case EE_CHAR_WLM:
368 : {
369 1983 : pNew = new EditCharAttribWordLineMode( static_cast<const SvxWordLineModeItem&>(rNew), nS, nE );
370 : }
371 1983 : break;
372 : case EE_CHAR_XMLATTRIBS:
373 : {
374 1605 : pNew = new EditCharAttrib( rNew, nS, nE ); // Attribute is only for holding XML information...
375 : }
376 1605 : break;
377 : case EE_CHAR_CASEMAP:
378 : {
379 5633 : pNew = new EditCharAttribCaseMap( static_cast<const SvxCaseMapItem&>(rNew), nS, nE );
380 : }
381 5633 : break;
382 : case EE_CHAR_GRABBAG:
383 : {
384 1545 : pNew = new EditCharAttribGrabBag( static_cast<const SfxGrabBagItem&>(rNew), nS, nE );
385 : }
386 1545 : break;
387 : case EE_FEATURE_TAB:
388 : {
389 104 : pNew = new EditCharAttribTab( static_cast<const SfxVoidItem&>(rNew), nS );
390 : }
391 104 : break;
392 : case EE_FEATURE_LINEBR:
393 : {
394 115 : pNew = new EditCharAttribLineBreak( static_cast<const SfxVoidItem&>(rNew), nS );
395 : }
396 115 : break;
397 : case EE_FEATURE_FIELD:
398 : {
399 21518 : pNew = new EditCharAttribField( static_cast<const SvxFieldItem&>(rNew), nS );
400 : }
401 21518 : break;
402 : case EE_CHAR_BKGCOLOR:
403 : {
404 1950 : pNew = new EditCharAttribBackgroundColor( static_cast<const SvxBackgroundColorItem&>(rNew), nS, nE );
405 : }
406 1950 : break;
407 : default:
408 : {
409 : OSL_FAIL( "Invalid Attribute!" );
410 : }
411 : }
412 258408 : return pNew;
413 : }
414 :
415 506251 : TextPortionList::TextPortionList()
416 : {
417 506251 : }
418 :
419 1007816 : TextPortionList::~TextPortionList()
420 : {
421 503908 : Reset();
422 503908 : }
423 :
424 563624 : void TextPortionList::Reset()
425 : {
426 563624 : maPortions.clear();
427 563624 : }
428 :
429 144049 : void TextPortionList::DeleteFromPortion(sal_Int32 nDelFrom)
430 : {
431 : DBG_ASSERT( ( nDelFrom < (sal_Int32)maPortions.size() ) || ( (nDelFrom == 0) && maPortions.empty() ), "DeleteFromPortion: Out of range" );
432 144049 : PortionsType::iterator it = maPortions.begin();
433 144049 : std::advance(it, nDelFrom);
434 144049 : maPortions.erase(it, maPortions.end());
435 144049 : }
436 :
437 1526854 : sal_Int32 TextPortionList::Count() const
438 : {
439 1526854 : return (sal_Int32)maPortions.size();
440 : }
441 :
442 60102 : const TextPortion* TextPortionList::operator[](sal_Int32 nPos) const
443 : {
444 60102 : return &maPortions[nPos];
445 : }
446 :
447 1677123 : TextPortion* TextPortionList::operator[](sal_Int32 nPos)
448 : {
449 1677123 : return &maPortions[nPos];
450 : }
451 :
452 394515 : void TextPortionList::Append(TextPortion* p)
453 : {
454 394515 : maPortions.push_back(p);
455 394515 : }
456 :
457 80227 : void TextPortionList::Insert(sal_Int32 nPos, TextPortion* p)
458 : {
459 80227 : maPortions.insert(maPortions.begin()+nPos, p);
460 80227 : }
461 :
462 0 : void TextPortionList::Remove(sal_Int32 nPos)
463 : {
464 0 : maPortions.erase(maPortions.begin()+nPos);
465 0 : }
466 :
467 : namespace {
468 :
469 : class FindTextPortionByAddress : std::unary_function<TextPortion, bool>
470 : {
471 : const TextPortion* mp;
472 : public:
473 0 : FindTextPortionByAddress(const TextPortion* p) : mp(p) {}
474 0 : bool operator() (const TextPortion& v) const
475 : {
476 0 : return &v == mp;
477 : }
478 : };
479 :
480 : }
481 :
482 0 : sal_Int32 TextPortionList::GetPos(const TextPortion* p) const
483 : {
484 : PortionsType::const_iterator it =
485 0 : std::find_if(maPortions.begin(), maPortions.end(), FindTextPortionByAddress(p));
486 :
487 0 : if (it == maPortions.end())
488 0 : return std::numeric_limits<sal_Int32>::max(); // not found.
489 :
490 0 : return std::distance(maPortions.begin(), it);
491 : }
492 :
493 2692 : sal_Int32 TextPortionList::FindPortion(
494 : sal_Int32 nCharPos, sal_Int32& nPortionStart, bool bPreferStartingPortion) const
495 : {
496 : // When nCharPos at portion limit, the left portion is found
497 2692 : sal_Int32 nTmpPos = 0;
498 2692 : sal_Int32 n = maPortions.size();
499 3873 : for (sal_Int32 i = 0; i < n; ++i)
500 : {
501 3873 : const TextPortion& rPortion = maPortions[i];
502 3873 : nTmpPos = nTmpPos + rPortion.GetLen();
503 3873 : if ( nTmpPos >= nCharPos )
504 : {
505 : // take this one if we don't prefer the starting portion, or if it's the last one
506 2692 : if ( ( nTmpPos != nCharPos ) || !bPreferStartingPortion || ( i == n-1 ) )
507 : {
508 2692 : nPortionStart = nTmpPos - rPortion.GetLen();
509 2692 : return i;
510 : }
511 : }
512 : }
513 : OSL_FAIL( "FindPortion: Not found!" );
514 0 : return n - 1;
515 : }
516 :
517 0 : sal_Int32 TextPortionList::GetStartPos(sal_Int32 nPortion)
518 : {
519 0 : sal_Int32 nPos = 0;
520 0 : for (sal_Int32 i = 0; i < nPortion; ++i)
521 : {
522 0 : const TextPortion& rPortion = maPortions[i];
523 0 : nPos = nPos + rPortion.GetLen();
524 : }
525 0 : return nPos;
526 : }
527 :
528 0 : ExtraPortionInfo::ExtraPortionInfo()
529 : : nOrgWidth(0)
530 : , nWidthFullCompression(0)
531 : , nPortionOffsetX(0)
532 : , nMaxCompression100thPercent(0)
533 : , nAsianCompressionTypes(0)
534 : , bFirstCharIsRightPunktuation(false)
535 : , bCompressed(false)
536 : , pOrgDXArray(NULL)
537 0 : , lineBreaksList()
538 : {
539 0 : }
540 :
541 0 : ExtraPortionInfo::~ExtraPortionInfo()
542 : {
543 0 : delete[] pOrgDXArray;
544 0 : }
545 :
546 0 : void ExtraPortionInfo::SaveOrgDXArray( const long* pDXArray, sal_Int32 nLen )
547 : {
548 0 : delete[] pOrgDXArray;
549 0 : if (pDXArray)
550 : {
551 0 : pOrgDXArray = new long[nLen];
552 0 : memcpy( pOrgDXArray, pDXArray, nLen * sizeof(long) );
553 : }
554 : else
555 0 : pOrgDXArray = NULL;
556 0 : }
557 :
558 506251 : ParaPortion::ParaPortion( ContentNode* pN )
559 : {
560 :
561 506251 : pNode = pN;
562 506251 : bInvalid = true;
563 506251 : bVisible = true;
564 506251 : bSimple = false;
565 506251 : bForceRepaint = false;
566 506251 : nInvalidPosStart = 0;
567 506251 : nInvalidDiff = 0;
568 506251 : nHeight = 0;
569 506251 : nFirstLineOffset = 0;
570 506251 : nBulletX = 0;
571 506251 : }
572 :
573 503908 : ParaPortion::~ParaPortion()
574 : {
575 503908 : }
576 :
577 281851 : void ParaPortion::MarkInvalid( sal_Int32 nStart, sal_Int32 nDiff )
578 : {
579 281851 : if ( !bInvalid )
580 : {
581 : // nInvalidPosEnd = nStart; // ??? => CreateLines
582 23841 : nInvalidPosStart = ( nDiff >= 0 ) ? nStart : ( nStart + nDiff );
583 23841 : nInvalidDiff = nDiff;
584 : }
585 : else
586 : {
587 : // Simple tap in succession
588 259989 : if ( ( nDiff > 0 ) && ( nInvalidDiff > 0 ) &&
589 1979 : ( ( nInvalidPosStart+nInvalidDiff ) == nStart ) )
590 : {
591 1978 : nInvalidDiff = nInvalidDiff + nDiff;
592 : }
593 : // Simple delete in succession
594 256032 : else if ( ( nDiff < 0 ) && ( nInvalidDiff < 0 ) && ( nInvalidPosStart == nStart ) )
595 : {
596 0 : nInvalidPosStart = nInvalidPosStart + nDiff;
597 0 : nInvalidDiff = nInvalidDiff + nDiff;
598 : }
599 : else
600 : {
601 : // nInvalidPosEnd = pNode->Len();
602 : DBG_ASSERT( ( nDiff >= 0 ) || ( (nStart+nDiff) >= 0 ), "MarkInvalid: Diff out of Range" );
603 256032 : nInvalidPosStart = std::min( nInvalidPosStart, ( nDiff < 0 ? nStart+nDiff : nDiff ) );
604 256032 : nInvalidDiff = 0;
605 256032 : bSimple = false;
606 : }
607 : }
608 281851 : bInvalid = true;
609 281851 : aScriptInfos.clear();
610 281851 : aWritingDirectionInfos.clear();
611 281851 : }
612 :
613 989939 : void ParaPortion::MarkSelectionInvalid( sal_Int32 nStart, sal_Int32 /* nEnd */ )
614 : {
615 989939 : if ( !bInvalid )
616 : {
617 88202 : nInvalidPosStart = nStart;
618 : // nInvalidPosEnd = nEnd;
619 : }
620 : else
621 : {
622 901737 : nInvalidPosStart = std::min( nInvalidPosStart, nStart );
623 : // nInvalidPosEnd = pNode->Len();
624 : }
625 989939 : nInvalidDiff = 0;
626 989939 : bInvalid = true;
627 989939 : bSimple = false;
628 989939 : aScriptInfos.clear();
629 989939 : aWritingDirectionInfos.clear();
630 989939 : }
631 :
632 8 : sal_Int32 ParaPortion::GetLineNumber( sal_Int32 nIndex ) const
633 : {
634 : DBG_ASSERTWARNING( aLineList.Count(), "Empty ParaPortion in GetLine!" );
635 : DBG_ASSERT( bVisible, "Why GetLine() on an invisible paragraph?" );
636 :
637 8 : for ( sal_Int32 nLine = 0; nLine < aLineList.Count(); nLine++ )
638 : {
639 8 : if ( aLineList[nLine]->IsIn( nIndex ) )
640 8 : return (sal_Int32)nLine;
641 : }
642 :
643 : // Then it should be at the end of the last line!
644 : DBG_ASSERT( nIndex == aLineList[ aLineList.Count() - 1 ]->GetEnd(), "Index dead wrong!" );
645 0 : return (aLineList.Count()-1);
646 : }
647 :
648 0 : void ParaPortion::SetVisible( bool bMakeVisible )
649 : {
650 0 : bVisible = bMakeVisible;
651 0 : }
652 :
653 2 : void ParaPortion::CorrectValuesBehindLastFormattedLine( sal_Int32 nLastFormattedLine )
654 : {
655 2 : sal_Int32 nLines = aLineList.Count();
656 : DBG_ASSERT( nLines, "CorrectPortionNumbersFromLine: Empty Portion?" );
657 2 : if ( nLastFormattedLine < ( nLines - 1 ) )
658 : {
659 0 : const EditLine* pLastFormatted = aLineList[ nLastFormattedLine ];
660 0 : const EditLine* pUnformatted = aLineList[ nLastFormattedLine+1 ];
661 0 : sal_Int32 nPortionDiff = pUnformatted->GetStartPortion() - pLastFormatted->GetEndPortion();
662 0 : sal_Int32 nTextDiff = pUnformatted->GetStart() - pLastFormatted->GetEnd();
663 0 : nTextDiff++; // LastFormatted->GetEnd() was included => 1 deducted too much!
664 :
665 : // The first unformatted must begin exactly one Portion behind the last
666 : // of the formatted:
667 : // If the modified line was split into one portion, can
668 : // nLastEnd > nNextStart!
669 0 : int nPDiff = -( nPortionDiff-1 );
670 0 : int nTDiff = -( nTextDiff-1 );
671 0 : if ( nPDiff || nTDiff )
672 : {
673 0 : for ( sal_Int32 nL = nLastFormattedLine+1; nL < nLines; nL++ )
674 : {
675 0 : EditLine* pLine = aLineList[ nL ];
676 :
677 0 : pLine->GetStartPortion() = pLine->GetStartPortion() + nPDiff;
678 0 : pLine->GetEndPortion() = pLine->GetEndPortion() + nPDiff;
679 :
680 0 : pLine->GetStart() = pLine->GetStart() + nTDiff;
681 0 : pLine->GetEnd() = pLine->GetEnd() + nTDiff;
682 :
683 0 : pLine->SetValid();
684 : }
685 : }
686 : }
687 : DBG_ASSERT( aLineList[ aLineList.Count()-1 ]->GetEnd() == pNode->Len(), "CorrectLines: The end is not right!" );
688 2 : }
689 :
690 : // Shared reverse lookup acceleration pieces ...
691 :
692 : namespace {
693 :
694 : template<typename _Array, typename _Val>
695 6013548 : sal_Int32 FastGetPos(const _Array& rArray, const _Val* p, sal_Int32& rLastPos)
696 : {
697 6013548 : sal_Int32 nArrayLen = rArray.size();
698 :
699 : // Through certain filter code-paths we do a lot of appends, which in
700 : // turn call GetPos - creating some N^2 nightmares. If we have a
701 : // non-trivially large list, do a few checks from the end first.
702 6013548 : if (rLastPos > 16 && nArrayLen > 16)
703 : {
704 : sal_Int32 nEnd;
705 14711 : if (rLastPos > nArrayLen - 2)
706 6875 : nEnd = nArrayLen;
707 : else
708 7836 : nEnd = rLastPos + 2;
709 :
710 46697 : for (sal_Int32 nIdx = rLastPos - 2; nIdx < nEnd; ++nIdx)
711 : {
712 46624 : if (&rArray.at(nIdx) == p)
713 : {
714 14638 : rLastPos = nIdx;
715 14638 : return nIdx;
716 : }
717 : }
718 : }
719 : // The world's lamest linear search from svarray ...
720 6739014 : for (sal_Int32 nIdx = 0; nIdx < nArrayLen; ++nIdx)
721 6739011 : if (&rArray.at(nIdx) == p)
722 5998907 : return rLastPos = nIdx;
723 :
724 : // XXX "not found" condition for sal_Int32 indexes
725 3 : return EE_PARA_NOT_FOUND;
726 : }
727 :
728 : }
729 :
730 42102 : ParaPortionList::ParaPortionList() : nLastCache( 0 )
731 : {
732 42102 : }
733 :
734 39771 : ParaPortionList::~ParaPortionList()
735 : {
736 39771 : }
737 :
738 1031803 : sal_Int32 ParaPortionList::GetPos(const ParaPortion* p) const
739 : {
740 1031803 : return FastGetPos(maPortions, p, nLastCache);
741 : }
742 :
743 2812394 : ParaPortion* ParaPortionList::operator [](sal_Int32 nPos)
744 : {
745 2812394 : return 0 <= nPos && nPos < (sal_Int32)maPortions.size() ? &maPortions[nPos] : NULL;
746 : }
747 :
748 0 : const ParaPortion* ParaPortionList::operator [](sal_Int32 nPos) const
749 : {
750 0 : return 0 <= nPos && nPos < (sal_Int32)maPortions.size() ? &maPortions[nPos] : NULL;
751 : }
752 :
753 0 : ParaPortion* ParaPortionList::Release(sal_Int32 nPos)
754 : {
755 0 : if (nPos < 0 || (sal_Int32)maPortions.size() <= nPos)
756 : {
757 : SAL_WARN( "editeng", "ParaPortionList::Release - out of bounds pos " << nPos);
758 0 : return NULL;
759 : }
760 0 : return maPortions.release(maPortions.begin()+nPos).release();
761 : }
762 :
763 2445 : void ParaPortionList::Remove(sal_Int32 nPos)
764 : {
765 2445 : if (nPos < 0 || (sal_Int32)maPortions.size() <= nPos)
766 : {
767 : SAL_WARN( "editeng", "ParaPortionList::Remove - out of bounds pos " << nPos);
768 2445 : return;
769 : }
770 2445 : maPortions.erase(maPortions.begin()+nPos);
771 : }
772 :
773 506251 : void ParaPortionList::Insert(sal_Int32 nPos, ParaPortion* p)
774 : {
775 506251 : if (nPos < 0 || (sal_Int32)maPortions.size() < nPos)
776 : {
777 : SAL_WARN( "editeng", "ParaPortionList::Insert - out of bounds pos " << nPos);
778 506251 : return;
779 : }
780 506251 : maPortions.insert(maPortions.begin()+nPos, p);
781 : }
782 :
783 0 : void ParaPortionList::Append(ParaPortion* p)
784 : {
785 0 : maPortions.push_back(p);
786 0 : }
787 :
788 2574856 : sal_Int32 ParaPortionList::Count() const
789 : {
790 2574856 : size_t nSize = maPortions.size();
791 2574856 : if (nSize > SAL_MAX_INT32)
792 : {
793 : SAL_WARN( "editeng", "ParaPortionList::Count - overflow " << nSize);
794 0 : return SAL_MAX_INT32;
795 : }
796 2574856 : return nSize;
797 : }
798 :
799 487397 : void ParaPortionList::Reset()
800 : {
801 487397 : maPortions.clear();
802 487397 : }
803 :
804 190 : long ParaPortionList::GetYOffset(const ParaPortion* pPPortion) const
805 : {
806 190 : long nHeight = 0;
807 190 : for (sal_Int32 i = 0, n = maPortions.size(); i < n; ++i)
808 : {
809 190 : const ParaPortion* pTmpPortion = &maPortions[i];
810 190 : if ( pTmpPortion == pPPortion )
811 190 : return nHeight;
812 0 : nHeight += pTmpPortion->GetHeight();
813 : }
814 : OSL_FAIL( "GetYOffset: Portion not found" );
815 0 : return nHeight;
816 : }
817 :
818 3 : sal_Int32 ParaPortionList::FindParagraph(long nYOffset) const
819 : {
820 3 : long nY = 0;
821 3 : for (size_t i = 0, n = maPortions.size(); i < n; ++i)
822 : {
823 3 : nY += maPortions[i].GetHeight(); // should also be correct even in bVisible!
824 3 : if ( nY > nYOffset )
825 3 : return i <= SAL_MAX_INT32 ? static_cast<sal_Int32>(i) : SAL_MAX_INT32;
826 : }
827 0 : return EE_PARA_NOT_FOUND;
828 : }
829 :
830 1263472 : const ParaPortion* ParaPortionList::SafeGetObject(sal_Int32 nPos) const
831 : {
832 1263472 : return 0 <= nPos && nPos < (sal_Int32)maPortions.size() ? &maPortions[nPos] : NULL;
833 : }
834 :
835 1586452 : ParaPortion* ParaPortionList::SafeGetObject(sal_Int32 nPos)
836 : {
837 1586452 : return 0 <= nPos && nPos < (sal_Int32)maPortions.size() ? &maPortions[nPos] : NULL;
838 : }
839 :
840 : #if OSL_DEBUG_LEVEL > 0
841 : void
842 : ParaPortionList::DbgCheck(ParaPortionList const& rParas, EditDoc const& rDoc)
843 : {
844 : assert(rParas.Count() == rDoc.Count());
845 : for (sal_Int32 i = 0; i < rParas.Count(); ++i)
846 : {
847 : assert(rParas.SafeGetObject(i) != nullptr);
848 : assert(rParas.SafeGetObject(i)->GetNode() != nullptr);
849 : assert(rParas.SafeGetObject(i)->GetNode() == rDoc.GetObject(i));
850 : }
851 : }
852 : #endif
853 :
854 6316 : ContentAttribsInfo::ContentAttribsInfo( const SfxItemSet& rParaAttribs ) :
855 6316 : aPrevParaAttribs( rParaAttribs)
856 : {
857 6316 : }
858 :
859 6299 : void ContentAttribsInfo::RemoveAllCharAttribsFromPool(SfxItemPool& rPool) const
860 : {
861 6299 : CharAttribsType::const_iterator it = aPrevCharAttribs.begin(), itEnd = aPrevCharAttribs.end();
862 47235 : for (; it != itEnd; ++it)
863 40936 : rPool.Remove(*it->GetItem());
864 6299 : }
865 :
866 41049 : void ContentAttribsInfo::AppendCharAttrib(EditCharAttrib* pNew)
867 : {
868 41049 : aPrevCharAttribs.push_back(pNew);
869 41049 : }
870 :
871 4 : void ConvertItem( SfxPoolItem& rPoolItem, MapUnit eSourceUnit, MapUnit eDestUnit )
872 : {
873 : DBG_ASSERT( eSourceUnit != eDestUnit, "ConvertItem - Why?!" );
874 :
875 4 : switch ( rPoolItem.Which() )
876 : {
877 : case EE_PARA_LRSPACE:
878 : {
879 : DBG_ASSERT( rPoolItem.IsA( TYPE( SvxLRSpaceItem ) ), "ConvertItem: invalid Item!" );
880 0 : SvxLRSpaceItem& rItem = static_cast<SvxLRSpaceItem&>(rPoolItem);
881 0 : rItem.SetTextFirstLineOfst( sal::static_int_cast< short >( OutputDevice::LogicToLogic( rItem.GetTextFirstLineOfst(), eSourceUnit, eDestUnit ) ) );
882 0 : rItem.SetTextLeft( OutputDevice::LogicToLogic( rItem.GetTextLeft(), eSourceUnit, eDestUnit ) );
883 0 : rItem.SetRight( OutputDevice::LogicToLogic( rItem.GetRight(), eSourceUnit, eDestUnit ) );
884 : }
885 0 : break;
886 : case EE_PARA_ULSPACE:
887 : {
888 : DBG_ASSERT( rPoolItem.IsA( TYPE( SvxULSpaceItem ) ), "ConvertItem: Invalid Item!" );
889 0 : SvxULSpaceItem& rItem = static_cast<SvxULSpaceItem&>(rPoolItem);
890 0 : rItem.SetUpper( sal::static_int_cast< sal_uInt16 >( OutputDevice::LogicToLogic( rItem.GetUpper(), eSourceUnit, eDestUnit ) ) );
891 0 : rItem.SetLower( sal::static_int_cast< sal_uInt16 >( OutputDevice::LogicToLogic( rItem.GetLower(), eSourceUnit, eDestUnit ) ) );
892 : }
893 0 : break;
894 : case EE_PARA_SBL:
895 : {
896 : DBG_ASSERT( rPoolItem.IsA( TYPE( SvxLineSpacingItem ) ), "ConvertItem: Invalid Item!" );
897 0 : SvxLineSpacingItem& rItem = static_cast<SvxLineSpacingItem&>(rPoolItem);
898 : // SetLineHeight changes also eLineSpace!
899 0 : if ( rItem.GetLineSpaceRule() == SVX_LINE_SPACE_MIN )
900 0 : rItem.SetLineHeight( sal::static_int_cast< sal_uInt16 >( OutputDevice::LogicToLogic( rItem.GetLineHeight(), eSourceUnit, eDestUnit ) ) );
901 : }
902 0 : break;
903 : case EE_PARA_TABS:
904 : {
905 : DBG_ASSERT( rPoolItem.IsA( TYPE( SvxTabStopItem ) ), "ConvertItem: Invalid Item!" );
906 0 : SvxTabStopItem& rItem = static_cast<SvxTabStopItem&>(rPoolItem);
907 0 : SvxTabStopItem aNewItem( EE_PARA_TABS );
908 0 : for ( sal_uInt16 i = 0; i < rItem.Count(); i++ )
909 : {
910 0 : const SvxTabStop& rTab = rItem[i];
911 0 : SvxTabStop aNewStop( OutputDevice::LogicToLogic( rTab.GetTabPos(), eSourceUnit, eDestUnit ), rTab.GetAdjustment(), rTab.GetDecimal(), rTab.GetFill() );
912 0 : aNewItem.Insert( aNewStop );
913 : }
914 0 : rItem = aNewItem;
915 : }
916 0 : break;
917 : case EE_CHAR_FONTHEIGHT:
918 : case EE_CHAR_FONTHEIGHT_CJK:
919 : case EE_CHAR_FONTHEIGHT_CTL:
920 : {
921 : DBG_ASSERT( rPoolItem.IsA( TYPE( SvxFontHeightItem ) ), "ConvertItem: Invalid Item!" );
922 0 : SvxFontHeightItem& rItem = static_cast<SvxFontHeightItem&>(rPoolItem);
923 0 : rItem.SetHeight( OutputDevice::LogicToLogic( rItem.GetHeight(), eSourceUnit, eDestUnit ) );
924 : }
925 0 : break;
926 : }
927 4 : }
928 :
929 4 : void ConvertAndPutItems( SfxItemSet& rDest, const SfxItemSet& rSource, const MapUnit* pSourceUnit, const MapUnit* pDestUnit )
930 : {
931 4 : const SfxItemPool* pSourcePool = rSource.GetPool();
932 4 : const SfxItemPool* pDestPool = rDest.GetPool();
933 :
934 208 : for ( sal_uInt16 nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ )
935 : {
936 : // If possible go through SlotID ...
937 :
938 204 : sal_uInt16 nSourceWhich = nWhich;
939 204 : sal_uInt16 nSlot = pDestPool->GetTrueSlotId( nWhich );
940 204 : if ( nSlot )
941 : {
942 180 : sal_uInt16 nW = pSourcePool->GetTrueWhich( nSlot );
943 180 : if ( nW )
944 180 : nSourceWhich = nW;
945 : }
946 :
947 204 : if ( rSource.GetItemState( nSourceWhich, false ) == SfxItemState::SET )
948 : {
949 0 : MapUnit eSourceUnit = pSourceUnit ? *pSourceUnit : (MapUnit)pSourcePool->GetMetric( nSourceWhich );
950 0 : MapUnit eDestUnit = pDestUnit ? *pDestUnit : (MapUnit)pDestPool->GetMetric( nWhich );
951 0 : if ( eSourceUnit != eDestUnit )
952 : {
953 0 : SfxPoolItem* pItem = rSource.Get( nSourceWhich ).Clone();
954 : // pItem->SetWhich( nWhich );
955 0 : ConvertItem( *pItem, eSourceUnit, eDestUnit );
956 0 : rDest.Put( *pItem, nWhich );
957 0 : delete pItem;
958 : }
959 : else
960 : {
961 0 : rDest.Put( rSource.Get( nSourceWhich ), nWhich );
962 : }
963 : }
964 : }
965 4 : }
966 :
967 462685 : EditLine::EditLine() :
968 : bHangingPunctuation(false),
969 462685 : bInvalid(true)
970 : {
971 :
972 462685 : nStart = nEnd = 0;
973 462685 : nStartPortion = 0; // to be able to tell the difference between a line
974 : // without Ptorions form one with the Portion number 0
975 462685 : nEndPortion = 0;
976 462685 : nHeight = 0;
977 462685 : nStartPosX = 0;
978 462685 : nTxtHeight = 0;
979 462685 : nTxtWidth = 0;
980 462685 : nCrsrHeight = 0;
981 462685 : nMaxAscent = 0;
982 462685 : }
983 :
984 144052 : EditLine::EditLine( const EditLine& r ) :
985 : bHangingPunctuation(r.bHangingPunctuation),
986 144052 : bInvalid(true)
987 : {
988 :
989 144052 : nEnd = r.nEnd;
990 144052 : nStart = r.nStart;
991 144052 : nStartPortion = r.nStartPortion;
992 144052 : nEndPortion = r.nEndPortion;
993 :
994 144052 : nHeight = 0;
995 144052 : nStartPosX = 0;
996 144052 : nTxtHeight = 0;
997 144052 : nTxtWidth = 0;
998 144052 : nCrsrHeight = 0;
999 144052 : nMaxAscent = 0;
1000 144052 : }
1001 :
1002 604443 : EditLine::~EditLine()
1003 : {
1004 604443 : }
1005 :
1006 :
1007 :
1008 0 : EditLine* EditLine::Clone() const
1009 : {
1010 0 : EditLine* pL = new EditLine;
1011 0 : pL->aPositions = aPositions;
1012 0 : pL->nStartPosX = nStartPosX;
1013 0 : pL->nStart = nStart;
1014 0 : pL->nEnd = nEnd;
1015 0 : pL->nStartPortion = nStartPortion;
1016 0 : pL->nEndPortion = nEndPortion;
1017 0 : pL->nHeight = nHeight;
1018 0 : pL->nTxtWidth = nTxtWidth;
1019 0 : pL->nTxtHeight = nTxtHeight;
1020 0 : pL->nCrsrHeight = nCrsrHeight;
1021 0 : pL->nMaxAscent = nMaxAscent;
1022 :
1023 0 : return pL;
1024 : }
1025 :
1026 0 : bool operator == ( const EditLine& r1, const EditLine& r2 )
1027 : {
1028 0 : if ( r1.nStart != r2.nStart )
1029 0 : return false;
1030 :
1031 0 : if ( r1.nEnd != r2.nEnd )
1032 0 : return false;
1033 :
1034 0 : if ( r1.nStartPortion != r2.nStartPortion )
1035 0 : return false;
1036 :
1037 0 : if ( r1.nEndPortion != r2.nEndPortion )
1038 0 : return false;
1039 :
1040 0 : return true;
1041 : }
1042 :
1043 80658 : EditLine& EditLine::operator = ( const EditLine& r )
1044 : {
1045 80658 : nEnd = r.nEnd;
1046 80658 : nStart = r.nStart;
1047 80658 : nEndPortion = r.nEndPortion;
1048 80658 : nStartPortion = r.nStartPortion;
1049 80658 : return *this;
1050 : }
1051 :
1052 :
1053 0 : bool operator != ( const EditLine& r1, const EditLine& r2 )
1054 : {
1055 0 : return !( r1 == r2 );
1056 : }
1057 :
1058 490589 : void EditLine::SetHeight( sal_uInt16 nH, sal_uInt16 nTxtH, sal_uInt16 nCrsrH )
1059 : {
1060 490589 : nHeight = nH;
1061 490589 : nTxtHeight = ( nTxtH ? nTxtH : nH );
1062 490589 : nCrsrHeight = ( nCrsrH ? nCrsrH : nTxtHeight );
1063 490589 : }
1064 :
1065 468127 : void EditLine::SetStartPosX( long start )
1066 : {
1067 468127 : if (start > 0)
1068 32421 : nStartPosX = start;
1069 : else
1070 435706 : nStartPosX = 0;
1071 468127 : }
1072 :
1073 224710 : Size EditLine::CalcTextSize( ParaPortion& rParaPortion )
1074 : {
1075 224710 : Size aSz;
1076 224710 : Size aTmpSz;
1077 : TextPortion* pPortion;
1078 :
1079 : DBG_ASSERT( rParaPortion.GetTextPortions().Count(), "GetTextSize before CreatePortions !" );
1080 :
1081 456048 : for ( sal_Int32 n = nStartPortion; n <= nEndPortion; n++ )
1082 : {
1083 231338 : pPortion = rParaPortion.GetTextPortions()[n];
1084 231338 : switch ( pPortion->GetKind() )
1085 : {
1086 : case PortionKind::TEXT:
1087 : case PortionKind::FIELD:
1088 : case PortionKind::HYPHENATOR:
1089 : {
1090 231206 : aTmpSz = pPortion->GetSize();
1091 231206 : aSz.Width() += aTmpSz.Width();
1092 231206 : if ( aSz.Height() < aTmpSz.Height() )
1093 224720 : aSz.Height() = aTmpSz.Height();
1094 : }
1095 231206 : break;
1096 : case PortionKind::TAB:
1097 : {
1098 12 : aSz.Width() += pPortion->GetSize().Width();
1099 : }
1100 12 : break;
1101 120 : case PortionKind::LINEBREAK: break;
1102 : }
1103 : }
1104 :
1105 224710 : SetHeight( (sal_uInt16)aSz.Height() );
1106 224710 : return aSz;
1107 : }
1108 :
1109 506251 : EditLineList::EditLineList()
1110 : {
1111 506251 : }
1112 :
1113 1007816 : EditLineList::~EditLineList()
1114 : {
1115 503908 : Reset();
1116 503908 : }
1117 :
1118 563624 : void EditLineList::Reset()
1119 : {
1120 563624 : maLines.clear();
1121 563624 : }
1122 :
1123 2 : void EditLineList::DeleteFromLine(sal_Int32 nDelFrom)
1124 : {
1125 : DBG_ASSERT( nDelFrom <= ((sal_Int32)maLines.size() - 1), "DeleteFromLine: Out of range" );
1126 2 : LinesType::iterator it = maLines.begin();
1127 2 : std::advance(it, nDelFrom);
1128 2 : maLines.erase(it, maLines.end());
1129 2 : }
1130 :
1131 120 : sal_Int32 EditLineList::FindLine(sal_Int32 nChar, bool bInclEnd)
1132 : {
1133 120 : sal_Int32 n = maLines.size();
1134 159 : for (sal_Int32 i = 0; i < n; ++i)
1135 : {
1136 142 : const EditLine& rLine = maLines[i];
1137 224 : if ( (bInclEnd && (rLine.GetEnd() >= nChar)) ||
1138 82 : (rLine.GetEnd() > nChar) )
1139 : {
1140 103 : return i;
1141 : }
1142 : }
1143 :
1144 : DBG_ASSERT( !bInclEnd, "Line not found: FindLine" );
1145 17 : return n - 1;
1146 : }
1147 :
1148 3700973 : sal_Int32 EditLineList::Count() const
1149 : {
1150 3700973 : return maLines.size();
1151 : }
1152 :
1153 27621 : const EditLine* EditLineList::operator[](sal_Int32 nPos) const
1154 : {
1155 27621 : return &maLines[nPos];
1156 : }
1157 :
1158 1696930 : EditLine* EditLineList::operator[](sal_Int32 nPos)
1159 : {
1160 1696930 : return &maLines[nPos];
1161 : }
1162 :
1163 382159 : void EditLineList::Append(EditLine* p)
1164 : {
1165 382159 : maLines.push_back(p);
1166 382159 : }
1167 :
1168 80526 : void EditLineList::Insert(sal_Int32 nPos, EditLine* p)
1169 : {
1170 80526 : maLines.insert(maLines.begin()+nPos, p);
1171 80526 : }
1172 :
1173 2904065 : EditPaM::EditPaM() : pNode(NULL), nIndex(0) {}
1174 2195209 : EditPaM::EditPaM(const EditPaM& r) : pNode(r.pNode), nIndex(r.nIndex) {}
1175 2674056 : EditPaM::EditPaM(ContentNode* p, sal_Int32 n) : pNode(p), nIndex(n) {}
1176 :
1177 :
1178 :
1179 144808 : void EditPaM::SetNode(ContentNode* p)
1180 : {
1181 144808 : pNode = p;
1182 144808 : }
1183 :
1184 0 : bool EditPaM::DbgIsBuggy( EditDoc& rDoc )
1185 : {
1186 0 : return !pNode ||
1187 0 : rDoc.GetPos( pNode ) >= rDoc.Count() ||
1188 0 : nIndex > pNode->Len();
1189 : }
1190 :
1191 0 : bool EditSelection::DbgIsBuggy( EditDoc& rDoc )
1192 : {
1193 0 : return aStartPaM.DbgIsBuggy( rDoc ) || aEndPaM.DbgIsBuggy( rDoc );
1194 : }
1195 :
1196 266902 : EditSelection::EditSelection()
1197 : {
1198 266902 : }
1199 :
1200 227458 : EditSelection::EditSelection( const EditPaM& rStartAndAnd )
1201 : {
1202 : // could still be optimized!
1203 : // do no first call the Def-constructor from PaM!
1204 227458 : aStartPaM = rStartAndAnd;
1205 227458 : aEndPaM = rStartAndAnd;
1206 227458 : }
1207 :
1208 915942 : EditSelection::EditSelection( const EditPaM& rStart, const EditPaM& rEnd )
1209 : {
1210 : // could still be optimized!
1211 915942 : aStartPaM = rStart;
1212 915942 : aEndPaM = rEnd;
1213 915942 : }
1214 :
1215 3586 : EditSelection& EditSelection::operator = ( const EditPaM& rPaM )
1216 : {
1217 3586 : aStartPaM = rPaM;
1218 3586 : aEndPaM = rPaM;
1219 3586 : return *this;
1220 : }
1221 :
1222 500711 : void EditSelection::Adjust( const EditDoc& rNodes )
1223 : {
1224 : DBG_ASSERT( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index out of range in Adjust(1)" );
1225 : DBG_ASSERT( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index out of range in Adjust(2)" );
1226 :
1227 500711 : const ContentNode* pStartNode = aStartPaM.GetNode();
1228 500711 : const ContentNode* pEndNode = aEndPaM.GetNode();
1229 :
1230 500711 : sal_Int32 nStartNode = rNodes.GetPos( pStartNode );
1231 500711 : sal_Int32 nEndNode = rNodes.GetPos( pEndNode );
1232 :
1233 : DBG_ASSERT( nStartNode != SAL_MAX_INT32, "Node out of range in Adjust(1)" );
1234 : DBG_ASSERT( nEndNode != SAL_MAX_INT32, "Node out of range in Adjust(2)" );
1235 :
1236 500711 : const bool bSwap = ( nStartNode > nEndNode ) ||
1237 487463 : ( ( nStartNode == nEndNode ) &&
1238 988174 : ( aStartPaM.GetIndex() > aEndPaM.GetIndex() ) );
1239 :
1240 500711 : if ( bSwap )
1241 : {
1242 0 : EditPaM aTmpPaM( aStartPaM );
1243 0 : aStartPaM = aEndPaM;
1244 0 : aEndPaM = aTmpPaM;
1245 : }
1246 500711 : }
1247 :
1248 310086 : bool operator == ( const EditPaM& r1, const EditPaM& r2 )
1249 : {
1250 616549 : return ( r1.GetNode() == r2.GetNode() ) &&
1251 616549 : ( r1.GetIndex() == r2.GetIndex() );
1252 : }
1253 :
1254 3396268 : EditPaM& EditPaM::operator = ( const EditPaM& rPaM )
1255 : {
1256 3396268 : nIndex = rPaM.nIndex;
1257 3396268 : pNode = rPaM.pNode;
1258 3396268 : return *this;
1259 : }
1260 :
1261 310074 : bool operator != ( const EditPaM& r1, const EditPaM& r2 )
1262 : {
1263 310074 : return !( r1 == r2 );
1264 : }
1265 :
1266 499814 : ContentNode::ContentNode( SfxItemPool& rPool ) : aContentAttribs( rPool )
1267 : {
1268 499814 : }
1269 :
1270 6437 : ContentNode::ContentNode( const OUString& rStr, const ContentAttribs& rContentAttribs ) :
1271 6437 : maString(rStr), aContentAttribs(rContentAttribs)
1272 : {
1273 6437 : }
1274 :
1275 503908 : ContentNode::~ContentNode()
1276 : {
1277 503908 : }
1278 :
1279 274475 : void ContentNode::ExpandAttribs( sal_Int32 nIndex, sal_Int32 nNew, SfxItemPool& rItemPool )
1280 : {
1281 274475 : if ( !nNew )
1282 289631 : return;
1283 :
1284 : #if OSL_DEBUG_LEVEL > 0
1285 : CharAttribList::DbgCheckAttribs(aCharAttribList);
1286 : #endif
1287 :
1288 : // Since features are treated differently than normal character attributes,
1289 : // can also the order of the start list be change!
1290 : // In every if ..., in the next (n) opportunities due to bFeature or
1291 : // an existing special case, must (n-1) opportunities be provided with
1292 : // bResort. The most likely possibility receives no bResort, so that is
1293 : // not sorted anew when all attributes are the same.
1294 259319 : bool bResort = false;
1295 259319 : bool bExpandedEmptyAtIndexNull = false;
1296 :
1297 259319 : sal_Int32 nAttr = 0;
1298 259319 : CharAttribList::AttribsType& rAttribs = aCharAttribList.GetAttribs();
1299 259319 : EditCharAttrib* pAttrib = GetAttrib(rAttribs, nAttr);
1300 546628 : while ( pAttrib )
1301 : {
1302 27990 : if ( pAttrib->GetEnd() >= nIndex )
1303 : {
1304 : // Move all attributes behind the insertion point...
1305 26909 : if ( pAttrib->GetStart() > nIndex )
1306 : {
1307 1839 : pAttrib->MoveForward( nNew );
1308 : }
1309 : // 0: Expand empty attribute, if at insertion point
1310 25070 : else if ( pAttrib->IsEmpty() )
1311 : {
1312 : // Do not check Index, a empty one could only be there
1313 : // When later checking it anyhow:
1314 : // Special caase: Start == 0; AbsLen == 1, nNew = 1
1315 : // => Expand, because of paragraph break!
1316 : // Start <= nIndex, End >= nIndex => Start=End=nIndex!
1317 : // if ( pAttrib->GetStart() == nIndex )
1318 16924 : pAttrib->Expand( nNew );
1319 16924 : bResort = true;
1320 16924 : if ( pAttrib->GetStart() == 0 )
1321 16857 : bExpandedEmptyAtIndexNull = true;
1322 : }
1323 : // 1: Attribute starts before, goes to index ...
1324 8146 : else if ( pAttrib->GetEnd() == nIndex ) // Start must be before
1325 : {
1326 : // Only expand when there is no feature
1327 : // and if not in exclude list!
1328 : // Otherwise, a UL will go on until a new ULDB, expaning both
1329 : // if ( !pAttrib->IsFeature() && !rExclList.FindAttrib( pAttrib->Which() ) )
1330 8116 : if ( !pAttrib->IsFeature() && !aCharAttribList.FindEmptyAttrib( pAttrib->Which(), nIndex ) )
1331 : {
1332 7320 : if ( !pAttrib->IsEdge() )
1333 7320 : pAttrib->Expand( nNew );
1334 : }
1335 : else
1336 796 : bResort = true;
1337 : }
1338 : // 2: Attribute starts before, goes past the Index...
1339 30 : else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) )
1340 : {
1341 : DBG_ASSERT( !pAttrib->IsFeature(), "Large Feature?!" );
1342 0 : pAttrib->Expand( nNew );
1343 : }
1344 : // 3: Attribute starts on index...
1345 30 : else if ( pAttrib->GetStart() == nIndex )
1346 : {
1347 30 : if ( pAttrib->IsFeature() )
1348 : {
1349 3 : pAttrib->MoveForward( nNew );
1350 3 : bResort = true;
1351 : }
1352 : else
1353 : {
1354 27 : bool bExpand = false;
1355 27 : if ( nIndex == 0 )
1356 : {
1357 27 : bExpand = true;
1358 27 : if( bExpandedEmptyAtIndexNull )
1359 : {
1360 : // Check if this kind of attribute was empty and expanded here...
1361 0 : sal_uInt16 nW = pAttrib->GetItem()->Which();
1362 0 : for ( sal_Int32 nA = 0; nA < nAttr; nA++ )
1363 : {
1364 0 : const EditCharAttrib& r = aCharAttribList.GetAttribs()[nA];
1365 0 : if ( ( r.GetStart() == 0 ) && ( r.GetItem()->Which() == nW ) )
1366 : {
1367 0 : bExpand = false;
1368 0 : break;
1369 : }
1370 : }
1371 :
1372 : }
1373 : }
1374 27 : if ( bExpand )
1375 : {
1376 27 : pAttrib->Expand( nNew );
1377 27 : bResort = true;
1378 : }
1379 : else
1380 : {
1381 0 : pAttrib->MoveForward( nNew );
1382 : }
1383 : }
1384 : }
1385 : }
1386 :
1387 27990 : if ( pAttrib->IsEdge() )
1388 0 : pAttrib->SetEdge(false);
1389 :
1390 : DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" );
1391 :
1392 : DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribute distorted!" );
1393 : DBG_ASSERT( ( pAttrib->GetEnd() <= Len() ), "Expand: Attribute larger than paragraph!" );
1394 27990 : if ( pAttrib->IsEmpty() )
1395 : {
1396 : OSL_FAIL( "Empty Attribute after ExpandAttribs?" );
1397 0 : bResort = true;
1398 0 : rItemPool.Remove( *pAttrib->GetItem() );
1399 0 : rAttribs.erase(rAttribs.begin()+nAttr);
1400 0 : --nAttr;
1401 : }
1402 27990 : ++nAttr;
1403 27990 : pAttrib = GetAttrib(rAttribs, nAttr);
1404 : }
1405 :
1406 259319 : if ( bResort )
1407 1831 : aCharAttribList.ResortAttribs();
1408 :
1409 259319 : if (mpWrongList)
1410 : {
1411 58973 : bool bSep = ( maString[ nIndex ] == ' ' ) || IsFeature( nIndex );
1412 58973 : mpWrongList->TextInserted( nIndex, nNew, bSep );
1413 : }
1414 :
1415 : #if OSL_DEBUG_LEVEL > 0
1416 : CharAttribList::DbgCheckAttribs(aCharAttribList);
1417 : #endif
1418 : }
1419 :
1420 5823 : void ContentNode::CollapsAttribs( sal_Int32 nIndex, sal_Int32 nDeleted, SfxItemPool& rItemPool )
1421 : {
1422 5823 : if ( !nDeleted )
1423 10662 : return;
1424 :
1425 : #if OSL_DEBUG_LEVEL > 0
1426 : CharAttribList::DbgCheckAttribs(aCharAttribList);
1427 : #endif
1428 :
1429 : // Since features are treated differently than normal character attributes,
1430 : // can also the order of the start list be change!
1431 984 : bool bResort = false;
1432 984 : sal_Int32 nEndChanges = nIndex+nDeleted;
1433 :
1434 984 : sal_Int32 nAttr = 0;
1435 984 : CharAttribList::AttribsType& rAttribs = aCharAttribList.GetAttribs();
1436 984 : EditCharAttrib* pAttrib = GetAttrib(rAttribs, nAttr);
1437 3284 : while ( pAttrib )
1438 : {
1439 1316 : bool bDelAttr = false;
1440 1316 : if ( pAttrib->GetEnd() >= nIndex )
1441 : {
1442 : // Move all Attribute behind the insert point...
1443 1316 : if ( pAttrib->GetStart() >= nEndChanges )
1444 : {
1445 191 : pAttrib->MoveBackward( nDeleted );
1446 : }
1447 : // 1. Delete Internal attributes...
1448 1125 : else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() <= nEndChanges ) )
1449 : {
1450 : // Special case: Attribute covers the area exactly
1451 : // => keep as empty Attribute.
1452 797 : if ( !pAttrib->IsFeature() && ( pAttrib->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) )
1453 : {
1454 84 : pAttrib->GetEnd() = nIndex; // empty
1455 84 : bResort = true;
1456 : }
1457 : else
1458 713 : bDelAttr = true;
1459 : }
1460 : // 2. Attribute starts earlier, ends inside or behind it ...
1461 328 : else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) )
1462 : {
1463 : DBG_ASSERT( !pAttrib->IsFeature(), "Collapsing Feature!" );
1464 295 : if ( pAttrib->GetEnd() <= nEndChanges ) // ends inside
1465 9 : pAttrib->GetEnd() = nIndex;
1466 : else
1467 286 : pAttrib->Collaps( nDeleted ); // ends behind
1468 : }
1469 : // 3. Attribute starts inside, ending behind ...
1470 33 : else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() > nEndChanges ) )
1471 : {
1472 : // Features not allowed to expand!
1473 15 : if ( pAttrib->IsFeature() )
1474 : {
1475 0 : pAttrib->MoveBackward( nDeleted );
1476 0 : bResort = true;
1477 : }
1478 : else
1479 : {
1480 15 : pAttrib->GetStart() = nEndChanges;
1481 15 : pAttrib->MoveBackward( nDeleted );
1482 : }
1483 : }
1484 : }
1485 : DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" );
1486 :
1487 : DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collaps: Attribut distorted!" );
1488 : DBG_ASSERT( ( pAttrib->GetEnd() <= Len()) || bDelAttr, "Collaps: Attribute larger than paragraph!" );
1489 1316 : if ( bDelAttr )
1490 : {
1491 713 : bResort = true;
1492 713 : rItemPool.Remove( *pAttrib->GetItem() );
1493 713 : rAttribs.erase(rAttribs.begin()+nAttr);
1494 713 : nAttr--;
1495 : }
1496 603 : else if ( pAttrib->IsEmpty() )
1497 84 : aCharAttribList.SetHasEmptyAttribs(true);
1498 :
1499 1316 : nAttr++;
1500 1316 : pAttrib = GetAttrib(rAttribs, nAttr);
1501 : }
1502 :
1503 984 : if ( bResort )
1504 630 : aCharAttribList.ResortAttribs();
1505 :
1506 984 : if (mpWrongList)
1507 84 : mpWrongList->TextDeleted(nIndex, nDeleted);
1508 :
1509 : #if OSL_DEBUG_LEVEL > 0
1510 : CharAttribList::DbgCheckAttribs(aCharAttribList);
1511 : #endif
1512 : }
1513 :
1514 6437 : void ContentNode::CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, bool bKeepEndingAttribs )
1515 : {
1516 : DBG_ASSERT( pPrevNode, "Copy of attributes to a null pointer?" );
1517 :
1518 : #if OSL_DEBUG_LEVEL > 0
1519 : CharAttribList::DbgCheckAttribs(aCharAttribList);
1520 : CharAttribList::DbgCheckAttribs(pPrevNode->aCharAttribList);
1521 : #endif
1522 :
1523 6437 : sal_Int32 nCut = pPrevNode->Len();
1524 :
1525 6437 : sal_Int32 nAttr = 0;
1526 6437 : CharAttribList::AttribsType& rPrevAttribs = pPrevNode->GetCharAttribs().GetAttribs();
1527 6437 : EditCharAttrib* pAttrib = GetAttrib(rPrevAttribs, nAttr);
1528 25405 : while ( pAttrib )
1529 : {
1530 12531 : if ( pAttrib->GetEnd() < nCut )
1531 : {
1532 : // remain unchanged ....
1533 : ;
1534 : }
1535 11327 : else if ( pAttrib->GetEnd() == nCut )
1536 : {
1537 : // must be copied as an empty attributes.
1538 11326 : if ( bKeepEndingAttribs && !pAttrib->IsFeature() && !aCharAttribList.FindAttrib( pAttrib->GetItem()->Which(), 0 ) )
1539 : {
1540 10157 : EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, 0 );
1541 : DBG_ASSERT( pNewAttrib, "MakeCharAttrib failed!" );
1542 10157 : aCharAttribList.InsertAttrib( pNewAttrib );
1543 : }
1544 : }
1545 1 : else if ( pAttrib->IsInside( nCut ) || ( !nCut && !pAttrib->GetStart() && !pAttrib->IsFeature() ) )
1546 : {
1547 : // If cut is done right at the front then the attribute must be
1548 : // kept! Has to be copied and changed.
1549 0 : EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, pAttrib->GetEnd()-nCut );
1550 : DBG_ASSERT( pNewAttrib, "MakeCharAttrib failed!" );
1551 0 : aCharAttribList.InsertAttrib( pNewAttrib );
1552 0 : pAttrib->GetEnd() = nCut;
1553 : }
1554 : else
1555 : {
1556 : // Move all attributes in the current node (this)
1557 1 : CharAttribList::AttribsType::iterator it = rPrevAttribs.begin() + nAttr;
1558 1 : aCharAttribList.InsertAttrib(rPrevAttribs.release(it).release());
1559 1 : pAttrib->MoveBackward( nCut );
1560 1 : nAttr--;
1561 : }
1562 12531 : nAttr++;
1563 12531 : pAttrib = GetAttrib(rPrevAttribs, nAttr);
1564 : }
1565 :
1566 : #if OSL_DEBUG_LEVEL > 0
1567 : CharAttribList::DbgCheckAttribs(aCharAttribList);
1568 : CharAttribList::DbgCheckAttribs(pPrevNode->aCharAttribList);
1569 : #endif
1570 6437 : }
1571 :
1572 2429 : void ContentNode::AppendAttribs( ContentNode* pNextNode )
1573 : {
1574 : DBG_ASSERT( pNextNode, "Copy of attributes to a null pointer?" );
1575 :
1576 2429 : sal_Int32 nNewStart = maString.getLength();
1577 :
1578 : #if OSL_DEBUG_LEVEL > 0
1579 : CharAttribList::DbgCheckAttribs(aCharAttribList);
1580 : CharAttribList::DbgCheckAttribs(pNextNode->aCharAttribList);
1581 : #endif
1582 :
1583 2429 : sal_Int32 nAttr = 0;
1584 2429 : CharAttribList::AttribsType& rNextAttribs = pNextNode->GetCharAttribs().GetAttribs();
1585 2429 : EditCharAttrib* pAttrib = GetAttrib(rNextAttribs, nAttr);
1586 5178 : while ( pAttrib )
1587 : {
1588 : // Move all attributes in the current node (this)
1589 320 : bool bMelted = false;
1590 320 : if ( ( pAttrib->GetStart() == 0 ) && ( !pAttrib->IsFeature() ) )
1591 : {
1592 : // Attributes can possibly be summarized as:
1593 320 : sal_Int32 nTmpAttr = 0;
1594 320 : EditCharAttrib* pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr );
1595 1110 : while ( !bMelted && pTmpAttrib )
1596 : {
1597 470 : if ( pTmpAttrib->GetEnd() == nNewStart )
1598 : {
1599 470 : if (pTmpAttrib->Which() == pAttrib->Which())
1600 : {
1601 : // prevent adding 2 0-length attributes at same position
1602 630 : if ((*(pTmpAttrib->GetItem()) == *(pAttrib->GetItem()))
1603 315 : || (0 == pAttrib->GetLen()))
1604 : {
1605 315 : pTmpAttrib->GetEnd() =
1606 315 : pTmpAttrib->GetEnd() + pAttrib->GetLen();
1607 315 : rNextAttribs.erase(rNextAttribs.begin()+nAttr);
1608 : // Unsubscribe from the pool?!
1609 315 : bMelted = true;
1610 : }
1611 0 : else if (0 == pTmpAttrib->GetLen())
1612 : {
1613 0 : aCharAttribList.Remove(nTmpAttr);
1614 0 : --nTmpAttr; // to cancel later increment...
1615 : }
1616 : }
1617 : }
1618 470 : ++nTmpAttr;
1619 470 : pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr );
1620 : }
1621 : }
1622 :
1623 320 : if ( !bMelted )
1624 : {
1625 5 : pAttrib->GetStart() = pAttrib->GetStart() + nNewStart;
1626 5 : pAttrib->GetEnd() = pAttrib->GetEnd() + nNewStart;
1627 5 : CharAttribList::AttribsType::iterator it = rNextAttribs.begin() + nAttr;
1628 5 : aCharAttribList.InsertAttrib(rNextAttribs.release(it).release());
1629 : }
1630 320 : pAttrib = GetAttrib(rNextAttribs, nAttr);
1631 : }
1632 : // For the Attributes that just moved over:
1633 2429 : rNextAttribs.clear();
1634 :
1635 : #if OSL_DEBUG_LEVEL > 0
1636 : CharAttribList::DbgCheckAttribs(aCharAttribList);
1637 : CharAttribList::DbgCheckAttribs(pNextNode->aCharAttribList);
1638 : #endif
1639 2429 : }
1640 :
1641 623220 : void ContentNode::CreateDefFont()
1642 : {
1643 : // First use the information from the style ...
1644 623220 : SfxStyleSheet* pS = aContentAttribs.GetStyleSheet();
1645 623220 : if ( pS )
1646 139741 : CreateFont( GetCharAttribs().GetDefFont(), pS->GetItemSet() );
1647 :
1648 : // ... then iron out the hard paragraph formatting...
1649 623220 : CreateFont( GetCharAttribs().GetDefFont(),
1650 1246440 : GetContentAttribs().GetItems(), pS == NULL );
1651 623220 : }
1652 :
1653 0 : void ContentNode::SetStyleSheet( SfxStyleSheet* pS, const SvxFont& rFontFromStyle )
1654 : {
1655 0 : aContentAttribs.SetStyleSheet( pS );
1656 :
1657 :
1658 : // First use the information from the style ...
1659 0 : GetCharAttribs().GetDefFont() = rFontFromStyle;
1660 : // ... then iron out the hard paragraph formatting...
1661 0 : CreateFont( GetCharAttribs().GetDefFont(),
1662 0 : GetContentAttribs().GetItems(), pS == NULL );
1663 0 : }
1664 :
1665 294501 : void ContentNode::SetStyleSheet( SfxStyleSheet* pS, bool bRecalcFont )
1666 : {
1667 294501 : aContentAttribs.SetStyleSheet( pS );
1668 294501 : if ( bRecalcFont )
1669 67065 : CreateDefFont();
1670 294501 : }
1671 :
1672 58828 : bool ContentNode::IsFeature( sal_Int32 nPos ) const
1673 : {
1674 58828 : return maString[nPos] == CH_FEATURE;
1675 : }
1676 :
1677 9167717 : sal_Int32 ContentNode::Len() const
1678 : {
1679 9167717 : return maString.getLength();
1680 : }
1681 :
1682 1644 : sal_uLong ContentNode::GetExpandedLen() const
1683 : {
1684 1644 : sal_uLong nLen = maString.getLength();
1685 :
1686 : // Fields can be longer than the placeholder in the Node
1687 1644 : const CharAttribList::AttribsType& rAttrs = GetCharAttribs().GetAttribs();
1688 19669 : for (sal_Int32 nAttr = rAttrs.size(); nAttr; )
1689 : {
1690 16381 : const EditCharAttrib& rAttr = rAttrs[--nAttr];
1691 16381 : if (rAttr.Which() == EE_FEATURE_FIELD)
1692 : {
1693 27 : nLen += static_cast<const EditCharAttribField&>(rAttr).GetFieldValue().getLength();
1694 27 : --nLen; // Standalone, to avoid corner cases when previous getLength() returns 0
1695 : }
1696 : }
1697 :
1698 1644 : return nLen;
1699 : }
1700 :
1701 36299 : OUString ContentNode::GetExpandedText(sal_Int32 nStartPos, sal_Int32 nEndPos, bool bResolveFields) const
1702 : {
1703 36299 : if ( nEndPos < 0 || nEndPos > Len() )
1704 31048 : nEndPos = Len();
1705 :
1706 : DBG_ASSERT( nStartPos <= nEndPos, "Start and End reversed?" );
1707 :
1708 36299 : sal_Int32 nIndex = nStartPos;
1709 36299 : OUString aStr;
1710 36299 : const EditCharAttrib* pNextFeature = GetCharAttribs().FindFeature( nIndex );
1711 80868 : while ( nIndex < nEndPos )
1712 : {
1713 8270 : sal_Int32 nEnd = nEndPos;
1714 8270 : if ( pNextFeature && ( pNextFeature->GetStart() < nEnd ) )
1715 1339 : nEnd = pNextFeature->GetStart();
1716 : else
1717 6931 : pNextFeature = 0; // Feature does not interest the below
1718 :
1719 : DBG_ASSERT( nEnd >= nIndex, "End in front of the index?" );
1720 : //!! beware of sub string length of -1
1721 8270 : if (nEnd > nIndex)
1722 7117 : aStr += GetString().copy(nIndex, nEnd - nIndex);
1723 :
1724 8270 : if ( pNextFeature )
1725 : {
1726 1339 : switch ( pNextFeature->GetItem()->Which() )
1727 : {
1728 0 : case EE_FEATURE_TAB: aStr += "\t";
1729 0 : break;
1730 28 : case EE_FEATURE_LINEBR: aStr += "\x0A";
1731 28 : break;
1732 : case EE_FEATURE_FIELD:
1733 1311 : if ( bResolveFields )
1734 1311 : aStr += static_cast<const EditCharAttribField*>(pNextFeature)->GetFieldValue();
1735 1311 : break;
1736 : default: OSL_FAIL( "What feature?" );
1737 : }
1738 1339 : pNextFeature = GetCharAttribs().FindFeature( ++nEnd );
1739 : }
1740 8270 : nIndex = nEnd;
1741 : }
1742 36299 : return aStr;
1743 : }
1744 :
1745 166 : void ContentNode::UnExpandPosition( sal_Int32 &rPos, bool bBiasStart )
1746 : {
1747 166 : sal_Int32 nOffset = 0;
1748 :
1749 166 : const CharAttribList::AttribsType& rAttrs = GetCharAttribs().GetAttribs();
1750 242 : for (size_t nAttr = 0; nAttr < rAttrs.size(); ++nAttr )
1751 : {
1752 158 : const EditCharAttrib& rAttr = rAttrs[nAttr];
1753 : assert (!(nAttr < rAttrs.size() - 1) ||
1754 : rAttrs[nAttr].GetStart() <= rAttrs[nAttr + 1].GetStart());
1755 :
1756 158 : nOffset = rAttr.GetStart();
1757 :
1758 158 : if (nOffset >= rPos) // happens after the position
1759 59 : return;
1760 :
1761 99 : sal_Int32 nChunk = 0;
1762 99 : if (rAttr.Which() == EE_FEATURE_FIELD)
1763 : {
1764 93 : nChunk += static_cast<const EditCharAttribField&>(rAttr).GetFieldValue().getLength();
1765 93 : nChunk--; // Character representing the field in the string
1766 :
1767 93 : if (nOffset + nChunk >= rPos) // we're inside the field
1768 : {
1769 23 : if (bBiasStart)
1770 11 : rPos = rAttr.GetStart();
1771 : else
1772 12 : rPos = rAttr.GetEnd();
1773 23 : return;
1774 : }
1775 : // Adjust for the position
1776 70 : rPos -= nChunk;
1777 : }
1778 : }
1779 : assert (rPos <= Len());
1780 : }
1781 :
1782 : /*
1783 : * Fields are represented by a single character in the underlying string
1784 : * and/or selection, however, they can be expanded to the full value of
1785 : * the field. When we're dealing with selection / offsets however we need
1786 : * to deal in character positions inside the real (unexpanded) string.
1787 : * This method maps us back to character offsets.
1788 : */
1789 83 : void ContentNode::UnExpandPositions( sal_Int32 &rStartPos, sal_Int32 &rEndPos )
1790 : {
1791 83 : UnExpandPosition( rStartPos, true );
1792 83 : UnExpandPosition( rEndPos, false );
1793 83 : }
1794 :
1795 0 : void ContentNode::SetChar(sal_Int32 nPos, sal_Unicode c)
1796 : {
1797 0 : maString = maString.replaceAt(nPos, 1, OUString(c));
1798 0 : }
1799 :
1800 274475 : void ContentNode::Insert(const OUString& rStr, sal_Int32 nPos)
1801 : {
1802 274475 : maString = maString.replaceAt(nPos, 0, rStr);
1803 274475 : }
1804 :
1805 2429 : void ContentNode::Append(const OUString& rStr)
1806 : {
1807 2429 : maString += rStr;
1808 2429 : }
1809 :
1810 6437 : void ContentNode::Erase(sal_Int32 nPos)
1811 : {
1812 6437 : maString = maString.copy(0, nPos);
1813 6437 : }
1814 :
1815 5823 : void ContentNode::Erase(sal_Int32 nPos, sal_Int32 nCount)
1816 : {
1817 5823 : maString = maString.replaceAt(nPos, nCount, "");
1818 5823 : }
1819 :
1820 6437 : OUString ContentNode::Copy(sal_Int32 nPos) const
1821 : {
1822 6437 : return maString.copy(nPos);
1823 : }
1824 :
1825 139478 : OUString ContentNode::Copy(sal_Int32 nPos, sal_Int32 nCount) const
1826 : {
1827 139478 : return maString.copy(nPos, nCount);
1828 : }
1829 :
1830 204347 : sal_Unicode ContentNode::GetChar(sal_Int32 nPos) const
1831 : {
1832 204347 : return maString[nPos];
1833 : }
1834 :
1835 985 : void ContentNode::EnsureWrongList()
1836 : {
1837 985 : if (!mpWrongList)
1838 0 : CreateWrongList();
1839 985 : }
1840 :
1841 191700 : WrongList* ContentNode::GetWrongList()
1842 : {
1843 191700 : return mpWrongList.get();
1844 : }
1845 :
1846 5 : const WrongList* ContentNode::GetWrongList() const
1847 : {
1848 5 : return mpWrongList.get();
1849 : }
1850 :
1851 48864 : void ContentNode::SetWrongList( WrongList* p )
1852 : {
1853 48864 : mpWrongList.reset(p);
1854 48864 : }
1855 :
1856 116675 : void ContentNode::CreateWrongList()
1857 : {
1858 : SAL_WARN_IF( mpWrongList && !mpWrongList->empty(), "editeng", "WrongList already exist!");
1859 116675 : if (!mpWrongList || !mpWrongList->empty())
1860 116529 : mpWrongList.reset(new WrongList);
1861 116675 : }
1862 :
1863 229 : void ContentNode::DestroyWrongList()
1864 : {
1865 229 : mpWrongList.reset();
1866 229 : }
1867 :
1868 499814 : ContentAttribs::ContentAttribs( SfxItemPool& rPool )
1869 : : pStyle(0)
1870 499814 : , aAttribSet( rPool, EE_PARA_START, EE_CHAR_END )
1871 : {
1872 499814 : }
1873 :
1874 12874 : ContentAttribs::ContentAttribs( const ContentAttribs& rRef )
1875 : : pStyle(rRef.pStyle)
1876 12874 : , aAttribSet( rRef.aAttribSet )
1877 : {
1878 12874 : }
1879 :
1880 510345 : ContentAttribs::~ContentAttribs()
1881 : {
1882 510345 : }
1883 :
1884 12 : SvxTabStop ContentAttribs::FindTabStop( sal_Int32 nCurPos, sal_uInt16 nDefTab )
1885 : {
1886 12 : const SvxTabStopItem& rTabs = static_cast<const SvxTabStopItem&>( GetItem( EE_PARA_TABS ) );
1887 21 : for ( sal_uInt16 i = 0; i < rTabs.Count(); i++ )
1888 : {
1889 14 : const SvxTabStop& rTab = rTabs[i];
1890 14 : if ( rTab.GetTabPos() > nCurPos )
1891 5 : return rTab;
1892 : }
1893 :
1894 : // Determine DefTab ...
1895 7 : SvxTabStop aTabStop;
1896 7 : const sal_Int32 x = nCurPos / nDefTab + 1;
1897 7 : aTabStop.GetTabPos() = nDefTab * x;
1898 7 : return aTabStop;
1899 : }
1900 :
1901 294501 : void ContentAttribs::SetStyleSheet( SfxStyleSheet* pS )
1902 : {
1903 294501 : bool bStyleChanged = ( pStyle != pS );
1904 294501 : pStyle = pS;
1905 : // Only when other style sheet, not when current style sheet modified
1906 294501 : if ( pStyle && bStyleChanged )
1907 : {
1908 : // Selectively remove the attributes from the paragraph formatting
1909 : // which are specified in the style, so that the attributes of the
1910 : // style can have an affect.
1911 67065 : const SfxItemSet& rStyleAttribs = pStyle->GetItemSet();
1912 3487380 : for ( sal_uInt16 nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ )
1913 : {
1914 : // Don't change bullet on/off
1915 3420315 : if ( ( nWhich != EE_PARA_BULLETSTATE ) && ( rStyleAttribs.GetItemState( nWhich ) == SfxItemState::SET ) )
1916 1597794 : aAttribSet.ClearItem( nWhich );
1917 : }
1918 : }
1919 294501 : }
1920 :
1921 6683636 : const SfxPoolItem& ContentAttribs::GetItem( sal_uInt16 nWhich ) const
1922 : {
1923 : // Hard paragraph attributes take precedence!
1924 6683636 : const SfxItemSet* pTakeFrom = &aAttribSet;
1925 6683636 : if ( pStyle && ( aAttribSet.GetItemState( nWhich, false ) != SfxItemState::SET ) )
1926 1005880 : pTakeFrom = &pStyle->GetItemSet();
1927 :
1928 6683636 : return pTakeFrom->Get( nWhich );
1929 : }
1930 :
1931 14405 : bool ContentAttribs::HasItem( sal_uInt16 nWhich ) const
1932 : {
1933 14405 : bool bHasItem = false;
1934 14405 : if ( aAttribSet.GetItemState( nWhich, false ) == SfxItemState::SET )
1935 0 : bHasItem = true;
1936 14405 : else if ( pStyle && pStyle->GetItemSet().GetItemState( nWhich ) == SfxItemState::SET )
1937 0 : bHasItem = true;
1938 :
1939 14405 : return bHasItem;
1940 : }
1941 :
1942 :
1943 0 : ItemList::ItemList() : CurrentItem( 0 )
1944 : {
1945 0 : }
1946 :
1947 0 : const SfxPoolItem* ItemList::First()
1948 : {
1949 0 : CurrentItem = 0;
1950 0 : return aItemPool.empty() ? NULL : aItemPool[ 0 ];
1951 : }
1952 :
1953 0 : const SfxPoolItem* ItemList::Next()
1954 : {
1955 0 : if ( CurrentItem + 1 < (sal_Int32)aItemPool.size() )
1956 : {
1957 0 : ++CurrentItem;
1958 0 : return aItemPool[ CurrentItem ];
1959 : }
1960 0 : return NULL;
1961 : }
1962 :
1963 0 : void ItemList::Insert( const SfxPoolItem* pItem )
1964 : {
1965 0 : aItemPool.push_back( pItem );
1966 0 : CurrentItem = aItemPool.size() - 1;
1967 0 : }
1968 :
1969 :
1970 42102 : EditDoc::EditDoc( SfxItemPool* pPool ) :
1971 : nLastCache(0),
1972 22 : pItemPool(pPool ? pPool : new EditEngineItemPool(false)),
1973 : nDefTab(DEFTAB),
1974 : bIsVertical(false),
1975 : bIsFixedCellHeight(false),
1976 42102 : bOwnerOfPool(pPool == nullptr),
1977 84226 : bModified(false)
1978 : {
1979 : // Don't create a empty node, Clear() will be called in EditEngine-CTOR
1980 42102 : };
1981 :
1982 79542 : EditDoc::~EditDoc()
1983 : {
1984 39771 : ImplDestroyContents();
1985 39771 : if ( bOwnerOfPool )
1986 21 : SfxItemPool::Free(pItemPool);
1987 39771 : }
1988 :
1989 : namespace {
1990 :
1991 : class RemoveEachItemFromPool : std::unary_function<ContentNode, void>
1992 : {
1993 : EditDoc& mrDoc;
1994 : public:
1995 527168 : RemoveEachItemFromPool(EditDoc& rDoc) : mrDoc(rDoc) {}
1996 501463 : void operator() (const ContentNode& rNode)
1997 : {
1998 501463 : mrDoc.RemoveItemsFromPool(rNode);
1999 501463 : }
2000 : };
2001 :
2002 : struct ClearSpellErrorsHandler : std::unary_function<ContentNode, void>
2003 : {
2004 0 : void operator() (ContentNode& rNode)
2005 : {
2006 0 : rNode.DestroyWrongList();
2007 0 : }
2008 : };
2009 :
2010 : }
2011 :
2012 527168 : void EditDoc::ImplDestroyContents()
2013 : {
2014 527168 : std::for_each(maContents.begin(), maContents.end(), RemoveEachItemFromPool(*this));
2015 527168 : maContents.clear();
2016 527168 : }
2017 :
2018 503892 : void EditDoc::RemoveItemsFromPool(const ContentNode& rNode)
2019 : {
2020 702226 : for (sal_Int32 nAttr = 0; nAttr < rNode.GetCharAttribs().Count(); ++nAttr)
2021 : {
2022 198334 : const EditCharAttrib& rAttr = rNode.GetCharAttribs().GetAttribs()[nAttr];
2023 198334 : GetItemPool().Remove(*rAttr.GetItem());
2024 : }
2025 503892 : }
2026 :
2027 1026502 : void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, SvtScriptType nScriptType )
2028 : {
2029 1026502 : vcl::Font aPrevFont( rFont );
2030 1026502 : rFont.SetAlign( ALIGN_BASELINE );
2031 1026502 : rFont.SetTransparent( true );
2032 :
2033 1026502 : sal_uInt16 nWhich_FontInfo = GetScriptItemId( EE_CHAR_FONTINFO, nScriptType );
2034 1026502 : sal_uInt16 nWhich_Language = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType );
2035 1026502 : sal_uInt16 nWhich_FontHeight = GetScriptItemId( EE_CHAR_FONTHEIGHT, nScriptType );
2036 1026502 : sal_uInt16 nWhich_Weight = GetScriptItemId( EE_CHAR_WEIGHT, nScriptType );
2037 1026502 : sal_uInt16 nWhich_Italic = GetScriptItemId( EE_CHAR_ITALIC, nScriptType );
2038 :
2039 1026502 : if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontInfo ) == SfxItemState::SET ) )
2040 : {
2041 887076 : const SvxFontItem& rFontItem = static_cast<const SvxFontItem&>(rSet.Get( nWhich_FontInfo ));
2042 887076 : rFont.SetName( rFontItem.GetFamilyName() );
2043 887076 : rFont.SetFamily( rFontItem.GetFamily() );
2044 887076 : rFont.SetPitch( rFontItem.GetPitch() );
2045 887076 : rFont.SetCharSet( rFontItem.GetCharSet() );
2046 : }
2047 1026502 : if ( bSearchInParent || ( rSet.GetItemState( nWhich_Language ) == SfxItemState::SET ) )
2048 886972 : rFont.SetLanguage( static_cast<const SvxLanguageItem&>(rSet.Get( nWhich_Language )).GetLanguage() );
2049 1026502 : if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_COLOR ) == SfxItemState::SET ) )
2050 886979 : rFont.SetColor( static_cast<const SvxColorItem&>(rSet.Get( EE_CHAR_COLOR )).GetValue() );
2051 1026502 : if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_BKGCOLOR ) == SfxItemState::SET ) )
2052 887017 : rFont.SetFillColor( static_cast<const SvxBackgroundColorItem&>(rSet.Get( EE_CHAR_BKGCOLOR )).GetValue() );
2053 1026502 : if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontHeight ) == SfxItemState::SET ) )
2054 898140 : rFont.SetSize( Size( rFont.GetSize().Width(), static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich_FontHeight ) ).GetHeight() ) );
2055 1026502 : if ( bSearchInParent || ( rSet.GetItemState( nWhich_Weight ) == SfxItemState::SET ) )
2056 887010 : rFont.SetWeight( static_cast<const SvxWeightItem&>(rSet.Get( nWhich_Weight )).GetWeight() );
2057 1026502 : if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_UNDERLINE ) == SfxItemState::SET ) )
2058 887077 : rFont.SetUnderline( static_cast<const SvxUnderlineItem&>(rSet.Get( EE_CHAR_UNDERLINE )).GetLineStyle() );
2059 1026502 : if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OVERLINE ) == SfxItemState::SET ) )
2060 887080 : rFont.SetOverline( static_cast<const SvxOverlineItem&>(rSet.Get( EE_CHAR_OVERLINE )).GetLineStyle() );
2061 1026502 : if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_STRIKEOUT ) == SfxItemState::SET ) )
2062 887090 : rFont.SetStrikeout( static_cast<const SvxCrossedOutItem&>(rSet.Get( EE_CHAR_STRIKEOUT )).GetStrikeout() );
2063 1026502 : if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_CASEMAP ) == SfxItemState::SET ) )
2064 886999 : rFont.SetCaseMap( static_cast<const SvxCaseMapItem&>(rSet.Get( EE_CHAR_CASEMAP )).GetCaseMap() );
2065 1026502 : if ( bSearchInParent || ( rSet.GetItemState( nWhich_Italic ) == SfxItemState::SET ) )
2066 887023 : rFont.SetItalic( static_cast<const SvxPostureItem&>(rSet.Get( nWhich_Italic )).GetPosture() );
2067 1026502 : if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OUTLINE ) == SfxItemState::SET ) )
2068 887087 : rFont.SetOutline( static_cast<const SvxContourItem&>(rSet.Get( EE_CHAR_OUTLINE )).GetValue() );
2069 1026502 : if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_SHADOW ) == SfxItemState::SET ) )
2070 886990 : rFont.SetShadow( static_cast<const SvxShadowedItem&>(rSet.Get( EE_CHAR_SHADOW )).GetValue() );
2071 1026502 : if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_ESCAPEMENT ) == SfxItemState::SET ) )
2072 : {
2073 887005 : const SvxEscapementItem& rEsc = static_cast<const SvxEscapementItem&>( rSet.Get( EE_CHAR_ESCAPEMENT ) );
2074 :
2075 887005 : sal_uInt16 nProp = rEsc.GetProp();
2076 887005 : rFont.SetPropr( (sal_uInt8)nProp );
2077 :
2078 887005 : short nEsc = rEsc.GetEsc();
2079 887005 : if ( nEsc == DFLT_ESC_AUTO_SUPER )
2080 0 : nEsc = 100 - nProp;
2081 887005 : else if ( nEsc == DFLT_ESC_AUTO_SUB )
2082 0 : nEsc = sal::static_int_cast< short >( -( 100 - nProp ) );
2083 887005 : rFont.SetEscapement( nEsc );
2084 : }
2085 1026502 : if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_PAIRKERNING ) == SfxItemState::SET ) )
2086 886953 : rFont.SetKerning( static_cast<const SvxAutoKernItem&>(rSet.Get( EE_CHAR_PAIRKERNING )).GetValue() ? FontKerning::FontSpecific : FontKerning::NONE );
2087 1026502 : if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_KERNING ) == SfxItemState::SET ) )
2088 886959 : rFont.SetFixKerning( static_cast<const SvxKerningItem&>(rSet.Get( EE_CHAR_KERNING )).GetValue() );
2089 1026502 : if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_WLM ) == SfxItemState::SET ) )
2090 886977 : rFont.SetWordLineMode( static_cast<const SvxWordLineModeItem&>(rSet.Get( EE_CHAR_WLM )).GetValue() );
2091 1026502 : if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_EMPHASISMARK ) == SfxItemState::SET ) )
2092 886993 : rFont.SetEmphasisMark( static_cast<const SvxEmphasisMarkItem&>(rSet.Get( EE_CHAR_EMPHASISMARK )).GetValue() );
2093 1026502 : if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_RELIEF ) == SfxItemState::SET ) )
2094 886761 : rFont.SetRelief( (FontRelief)static_cast<const SvxCharReliefItem&>(rSet.Get( EE_CHAR_RELIEF )).GetValue() );
2095 :
2096 : // If comparing the entire font, or if checking before each alteration
2097 : // whether the value changes, remains relatively the same thing.
2098 : // So possible one MakeUniqFont more in the font, but as a result a quicker
2099 : // abortion of the query, or one must each time check bChanged.
2100 1026502 : if ( rFont == aPrevFont )
2101 753360 : rFont = aPrevFont; // => The same ImpPointer for IsSameInstance
2102 1026502 : }
2103 :
2104 259965 : void EditDoc::CreateDefFont( bool bUseStyles )
2105 : {
2106 259965 : SfxItemSet aTmpSet( GetItemPool(), EE_PARA_START, EE_CHAR_END );
2107 259965 : CreateFont( aDefFont, aTmpSet );
2108 259965 : aDefFont.SetVertical( IsVertical() );
2109 259965 : aDefFont.SetOrientation( IsVertical() ? 2700 : 0 );
2110 :
2111 519930 : for ( sal_Int32 nNode = 0; nNode < Count(); nNode++ )
2112 : {
2113 259965 : ContentNode* pNode = GetObject( nNode );
2114 259965 : pNode->GetCharAttribs().GetDefFont() = aDefFont;
2115 259965 : if ( bUseStyles )
2116 4 : pNode->CreateDefFont();
2117 259965 : }
2118 259965 : }
2119 :
2120 4981745 : sal_Int32 EditDoc::GetPos(const ContentNode* p) const
2121 : {
2122 4981745 : return FastGetPos(maContents, p, nLastCache);
2123 : }
2124 :
2125 3744572 : const ContentNode* EditDoc::GetObject(sal_Int32 nPos) const
2126 : {
2127 3744572 : return 0 <= nPos && nPos < (sal_Int32)maContents.size() ? &maContents[nPos] : NULL;
2128 : }
2129 :
2130 4857606 : ContentNode* EditDoc::GetObject(sal_Int32 nPos)
2131 : {
2132 4857606 : return 0 <= nPos && nPos < (sal_Int32)maContents.size() ? &maContents[nPos] : NULL;
2133 : }
2134 :
2135 0 : const ContentNode* EditDoc::operator[](sal_Int32 nPos) const
2136 : {
2137 0 : return GetObject(nPos);
2138 : }
2139 :
2140 798887 : ContentNode* EditDoc::operator[](sal_Int32 nPos)
2141 : {
2142 798887 : return GetObject(nPos);
2143 : }
2144 :
2145 506251 : void EditDoc::Insert(sal_Int32 nPos, ContentNode* p)
2146 : {
2147 506251 : if (nPos < 0 || nPos == SAL_MAX_INT32)
2148 : {
2149 : SAL_WARN( "editeng", "EditDoc::Insert - overflow pos " << nPos);
2150 506251 : return;
2151 : }
2152 506251 : maContents.insert(maContents.begin()+nPos, p);
2153 : }
2154 :
2155 2429 : void EditDoc::Remove(sal_Int32 nPos)
2156 : {
2157 2429 : if (nPos < 0 || nPos >= (sal_Int32)maContents.size())
2158 : {
2159 : SAL_WARN( "editeng", "EditDoc::Remove - out of bounds pos " << nPos);
2160 2429 : return;
2161 : }
2162 2429 : maContents.erase(maContents.begin() + nPos);
2163 : }
2164 :
2165 16 : void EditDoc::Release(sal_Int32 nPos)
2166 : {
2167 16 : if (nPos < 0 || nPos >= (sal_Int32)maContents.size())
2168 : {
2169 : SAL_WARN( "editeng", "EditDoc::Release - out of bounds pos " << nPos);
2170 16 : return;
2171 : }
2172 16 : maContents.release(maContents.begin() + nPos).release();
2173 : }
2174 :
2175 1298907 : sal_Int32 EditDoc::Count() const
2176 : {
2177 1298907 : size_t nSize = maContents.size();
2178 1298907 : if (nSize > SAL_MAX_INT32)
2179 : {
2180 : SAL_WARN( "editeng", "EditDoc::Count - overflow " << nSize);
2181 0 : return SAL_MAX_INT32;
2182 : }
2183 1298907 : return nSize;
2184 : }
2185 :
2186 6139 : OUString EditDoc::GetSepStr( LineEnd eEnd )
2187 : {
2188 6139 : if ( eEnd == LINEEND_CR )
2189 0 : return OUString("\015"); // 0x0d
2190 6139 : if ( eEnd == LINEEND_LF )
2191 6139 : return OUString("\012"); // 0x0a
2192 0 : return OUString("\015\012"); // 0x0d, 0x0a
2193 : }
2194 :
2195 1303 : OUString EditDoc::GetText( LineEnd eEnd ) const
2196 : {
2197 1303 : const sal_Int32 nNodes = Count();
2198 1303 : if (nNodes == 0)
2199 0 : return OUString();
2200 :
2201 1303 : const OUString aSep = EditDoc::GetSepStr( eEnd );
2202 1303 : const sal_Int32 nSepSize = aSep.getLength();
2203 1303 : const sal_uInt32 nLen = GetTextLen() + (nNodes - 1)*nSepSize;
2204 :
2205 2606 : OUStringBuffer aBuffer(nLen + 16); // leave some slack
2206 :
2207 2858 : for ( sal_Int32 nNode = 0; nNode < nNodes; nNode++ )
2208 : {
2209 1555 : if ( nSepSize && nNode>0 )
2210 : {
2211 252 : aBuffer.append(aSep);
2212 : }
2213 1555 : aBuffer.append(GetParaAsString( GetObject(nNode) ));
2214 : }
2215 :
2216 2606 : return aBuffer.makeStringAndClear();
2217 : }
2218 :
2219 29447 : OUString EditDoc::GetParaAsString( sal_Int32 nNode ) const
2220 : {
2221 29447 : return GetParaAsString( GetObject( nNode ) );
2222 : }
2223 :
2224 36253 : OUString EditDoc::GetParaAsString(
2225 : const ContentNode* pNode, sal_Int32 nStartPos, sal_Int32 nEndPos,
2226 : bool bResolveFields)
2227 : {
2228 36253 : return pNode->GetExpandedText(nStartPos, nEndPos, bResolveFields);
2229 : }
2230 :
2231 902310 : EditPaM EditDoc::GetStartPaM() const
2232 : {
2233 902310 : ContentNode* p = const_cast<ContentNode*>(GetObject(0));
2234 902310 : return EditPaM(p, 0);
2235 : }
2236 :
2237 16042 : EditPaM EditDoc::GetEndPaM() const
2238 : {
2239 16042 : ContentNode* pLastNode = const_cast<ContentNode*>(GetObject(Count()-1));
2240 16042 : return EditPaM( pLastNode, pLastNode->Len() );
2241 : }
2242 :
2243 1346 : sal_uLong EditDoc::GetTextLen() const
2244 : {
2245 1346 : sal_uLong nLen = 0;
2246 2944 : for ( sal_Int32 nNode = 0; nNode < Count(); nNode++ )
2247 : {
2248 1598 : const ContentNode* pNode = GetObject( nNode );
2249 1598 : nLen += pNode->GetExpandedLen();
2250 : }
2251 1346 : return nLen;
2252 : }
2253 :
2254 259961 : EditPaM EditDoc::Clear()
2255 : {
2256 259961 : ImplDestroyContents();
2257 :
2258 259961 : ContentNode* pNode = new ContentNode( GetItemPool() );
2259 259961 : Insert(0, pNode);
2260 :
2261 259961 : CreateDefFont(false);
2262 :
2263 259961 : SetModified(false);
2264 :
2265 259961 : return EditPaM( pNode, 0 );
2266 : }
2267 :
2268 0 : void EditDoc::ClearSpellErrors()
2269 : {
2270 0 : std::for_each(maContents.begin(), maContents.end(), ClearSpellErrorsHandler());
2271 0 : }
2272 :
2273 1586557 : void EditDoc::SetModified( bool b )
2274 : {
2275 1586557 : bModified = b;
2276 1586557 : if ( bModified )
2277 : {
2278 1326424 : aModifyHdl.Call( NULL );
2279 : }
2280 1586557 : }
2281 :
2282 227436 : EditPaM EditDoc::RemoveText()
2283 : {
2284 : // Keep the old ItemSet, to keep the chart Font.
2285 227436 : ContentNode* pPrevFirstNode = GetObject(0);
2286 227436 : SfxStyleSheet* pPrevStyle = pPrevFirstNode->GetStyleSheet();
2287 227436 : SfxItemSet aPrevSet( pPrevFirstNode->GetContentAttribs().GetItems() );
2288 454872 : vcl::Font aPrevFont( pPrevFirstNode->GetCharAttribs().GetDefFont() );
2289 :
2290 227436 : ImplDestroyContents();
2291 :
2292 227436 : ContentNode* pNode = new ContentNode( GetItemPool() );
2293 227436 : Insert(0, pNode);
2294 :
2295 227436 : pNode->SetStyleSheet(pPrevStyle, false);
2296 227436 : pNode->GetContentAttribs().GetItems().Set( aPrevSet );
2297 227436 : pNode->GetCharAttribs().GetDefFont() = aPrevFont;
2298 :
2299 227436 : SetModified(true);
2300 :
2301 454872 : return EditPaM( pNode, 0 );
2302 : }
2303 :
2304 265040 : EditPaM EditDoc::InsertText( EditPaM aPaM, const OUString& rStr )
2305 : {
2306 : DBG_ASSERT( rStr.indexOf( 0x0A ) == -1, "EditDoc::InsertText: Newlines prohibited in paragraph!" );
2307 : DBG_ASSERT( rStr.indexOf( 0x0D ) == -1, "EditDoc::InsertText: Newlines prohibited in paragraph!" );
2308 : DBG_ASSERT( rStr.indexOf( '\t' ) == -1, "EditDoc::InsertText: Newlines prohibited in paragraph!" );
2309 : DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertText1" );
2310 :
2311 265040 : aPaM.GetNode()->Insert( rStr, aPaM.GetIndex() );
2312 265040 : aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.getLength(), GetItemPool() );
2313 265040 : aPaM.SetIndex( aPaM.GetIndex() + rStr.getLength() );
2314 :
2315 265040 : SetModified( true );
2316 :
2317 265040 : return aPaM;
2318 : }
2319 :
2320 6437 : EditPaM EditDoc::InsertParaBreak( EditPaM aPaM, bool bKeepEndingAttribs )
2321 : {
2322 : DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertParaBreak" );
2323 6437 : ContentNode* pCurNode = aPaM.GetNode();
2324 6437 : sal_Int32 nPos = GetPos( pCurNode );
2325 6437 : OUString aStr = aPaM.GetNode()->Copy( aPaM.GetIndex() );
2326 6437 : aPaM.GetNode()->Erase( aPaM.GetIndex() );
2327 :
2328 : // the paragraph attributes...
2329 12874 : ContentAttribs aContentAttribs( aPaM.GetNode()->GetContentAttribs() );
2330 :
2331 : // for a new paragraph we like to have the bullet/numbering visible by default
2332 6437 : aContentAttribs.GetItems().Put( SfxBoolItem( EE_PARA_BULLETSTATE, true), EE_PARA_BULLETSTATE );
2333 :
2334 : // ContenNode constructor copies also the paragraph attributes
2335 6437 : ContentNode* pNode = new ContentNode( aStr, aContentAttribs );
2336 :
2337 : // Copy the Default Font
2338 6437 : pNode->GetCharAttribs().GetDefFont() = aPaM.GetNode()->GetCharAttribs().GetDefFont();
2339 6437 : SfxStyleSheet* pStyle = aPaM.GetNode()->GetStyleSheet();
2340 6437 : if ( pStyle )
2341 : {
2342 4157 : OUString aFollow( pStyle->GetFollow() );
2343 4157 : if ( !aFollow.isEmpty() && ( aFollow != pStyle->GetName() ) )
2344 : {
2345 0 : SfxStyleSheetBase* pNext = pStyle->GetPool().Find( aFollow, pStyle->GetFamily() );
2346 0 : pNode->SetStyleSheet( static_cast<SfxStyleSheet*>(pNext) );
2347 4157 : }
2348 : }
2349 :
2350 : // Character attributes may need to be copied or trimmed:
2351 6437 : pNode->CopyAndCutAttribs( aPaM.GetNode(), GetItemPool(), bKeepEndingAttribs );
2352 :
2353 6437 : Insert(nPos+1, pNode);
2354 :
2355 6437 : SetModified(true);
2356 :
2357 6437 : aPaM.SetNode( pNode );
2358 6437 : aPaM.SetIndex( 0 );
2359 12874 : return aPaM;
2360 : }
2361 :
2362 9435 : EditPaM EditDoc::InsertFeature( EditPaM aPaM, const SfxPoolItem& rItem )
2363 : {
2364 : DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertFeature" );
2365 :
2366 9435 : aPaM.GetNode()->Insert( OUString(CH_FEATURE), aPaM.GetIndex() );
2367 9435 : aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1, GetItemPool() );
2368 :
2369 : // Create a feature-attribute for the feature...
2370 9435 : EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rItem, aPaM.GetIndex(), aPaM.GetIndex()+1 );
2371 : DBG_ASSERT( pAttrib, "Why can not the feature be created?" );
2372 9435 : aPaM.GetNode()->GetCharAttribs().InsertAttrib( pAttrib );
2373 :
2374 9435 : SetModified( true );
2375 :
2376 9435 : aPaM.SetIndex( aPaM.GetIndex() + 1 );
2377 9435 : return aPaM;
2378 : }
2379 :
2380 2429 : EditPaM EditDoc::ConnectParagraphs( ContentNode* pLeft, ContentNode* pRight )
2381 : {
2382 2429 : const EditPaM aPaM( pLeft, pLeft->Len() );
2383 :
2384 : // First the attributes, otherwise nLen will not be correct!
2385 2429 : pLeft->AppendAttribs( pRight );
2386 : // then the Text...
2387 2429 : pLeft->Append(pRight->GetString());
2388 :
2389 : // the one to the right disappears.
2390 2429 : RemoveItemsFromPool(*pRight);
2391 2429 : sal_Int32 nRight = GetPos( pRight );
2392 2429 : Remove( nRight );
2393 :
2394 2429 : SetModified(true);
2395 :
2396 2429 : return aPaM;
2397 : }
2398 :
2399 5823 : EditPaM EditDoc::RemoveChars( EditPaM aPaM, sal_Int32 nChars )
2400 : {
2401 : // Maybe remove Features!
2402 5823 : aPaM.GetNode()->Erase( aPaM.GetIndex(), nChars );
2403 5823 : aPaM.GetNode()->CollapsAttribs( aPaM.GetIndex(), nChars, GetItemPool() );
2404 :
2405 5823 : SetModified( true );
2406 :
2407 5823 : return aPaM;
2408 : }
2409 :
2410 43076 : void EditDoc::InsertAttribInSelection( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd, const SfxPoolItem& rPoolItem )
2411 : {
2412 : DBG_ASSERT( pNode, "What to do with the attribute?" );
2413 : DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribute to large!" );
2414 :
2415 : // for Optimization:
2416 : // This ends at the beginning of the selection => can be expanded
2417 43076 : EditCharAttrib* pEndingAttrib = 0;
2418 : // This starts at the end of the selection => can be expanded
2419 43076 : EditCharAttrib* pStartingAttrib = 0;
2420 :
2421 : DBG_ASSERT( nStart <= nEnd, "Small miscalculations in InsertAttribInSelection" );
2422 :
2423 43076 : RemoveAttribs( pNode, nStart, nEnd, pStartingAttrib, pEndingAttrib, rPoolItem.Which() );
2424 :
2425 43141 : if ( pStartingAttrib && pEndingAttrib &&
2426 43078 : ( *(pStartingAttrib->GetItem()) == rPoolItem ) &&
2427 0 : ( *(pEndingAttrib->GetItem()) == rPoolItem ) )
2428 : {
2429 : // Will become a large Attribute.
2430 0 : pEndingAttrib->GetEnd() = pStartingAttrib->GetEnd();
2431 0 : GetItemPool().Remove( *(pStartingAttrib->GetItem()) );
2432 0 : pNode->GetCharAttribs().Remove(pStartingAttrib);
2433 : }
2434 43076 : else if ( pStartingAttrib && ( *(pStartingAttrib->GetItem()) == rPoolItem ) )
2435 60 : pStartingAttrib->GetStart() = nStart;
2436 43016 : else if ( pEndingAttrib && ( *(pEndingAttrib->GetItem()) == rPoolItem ) )
2437 9463 : pEndingAttrib->GetEnd() = nEnd;
2438 : else
2439 33553 : InsertAttrib( rPoolItem, pNode, nStart, nEnd );
2440 :
2441 43076 : if ( pStartingAttrib )
2442 63 : pNode->GetCharAttribs().ResortAttribs();
2443 :
2444 43076 : SetModified(true);
2445 43076 : }
2446 :
2447 969 : bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd, sal_uInt16 nWhich )
2448 : {
2449 : EditCharAttrib* pStarting;
2450 : EditCharAttrib* pEnding;
2451 969 : return RemoveAttribs( pNode, nStart, nEnd, pStarting, pEnding, nWhich );
2452 : }
2453 :
2454 44045 : bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd, EditCharAttrib*& rpStarting, EditCharAttrib*& rpEnding, sal_uInt16 nWhich )
2455 : {
2456 :
2457 : DBG_ASSERT( pNode, "What to do with the attribute?" );
2458 : DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribute to large!" );
2459 :
2460 : // This ends at the beginning of the selection => can be expanded
2461 44045 : rpEnding = 0;
2462 : // This starts at the end of the selection => can be expanded
2463 44045 : rpStarting = 0;
2464 :
2465 44045 : bool bChanged = false;
2466 :
2467 : DBG_ASSERT( nStart <= nEnd, "Small miscalculations in InsertAttribInSelection" );
2468 :
2469 : #if OSL_DEBUG_LEVEL > 0
2470 : CharAttribList::DbgCheckAttribs(pNode->GetCharAttribs());
2471 : #endif
2472 :
2473 : // iterate over the attributes ...
2474 44045 : sal_Int32 nAttr = 0;
2475 44045 : CharAttribList::AttribsType& rAttribs = pNode->GetCharAttribs().GetAttribs();
2476 44045 : EditCharAttrib* pAttr = GetAttrib(rAttribs, nAttr);
2477 445168 : while ( pAttr )
2478 : {
2479 357190 : bool bRemoveAttrib = false;
2480 357190 : sal_uInt16 nAttrWhich = pAttr->Which();
2481 357190 : if ( ( nAttrWhich < EE_FEATURE_START ) && ( !nWhich || ( nAttrWhich == nWhich ) ) )
2482 : {
2483 : // Attribute starts in Selection
2484 15983 : if ( ( pAttr->GetStart() >= nStart ) && ( pAttr->GetStart() <= nEnd ) )
2485 : {
2486 2940 : bChanged = true;
2487 2940 : if ( pAttr->GetEnd() > nEnd )
2488 : {
2489 63 : pAttr->GetStart() = nEnd; // then it starts after this
2490 63 : rpStarting = pAttr;
2491 63 : if ( nWhich )
2492 63 : break; // There can be no further attributes here
2493 : }
2494 2877 : else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) )
2495 : {
2496 : // Delete feature only if on the exact spot
2497 2877 : bRemoveAttrib = true;
2498 : }
2499 : }
2500 :
2501 : // Attribute ends in Selection
2502 13043 : else if ( ( pAttr->GetEnd() >= nStart ) && ( pAttr->GetEnd() <= nEnd ) )
2503 : {
2504 11029 : bChanged = true;
2505 11029 : if ( ( pAttr->GetStart() < nStart ) && !pAttr->IsFeature() )
2506 : {
2507 11029 : pAttr->GetEnd() = nStart; // then it ends here
2508 11029 : rpEnding = pAttr;
2509 : }
2510 0 : else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) )
2511 : {
2512 : // Delete feature only if on the exact spot
2513 0 : bRemoveAttrib = true;
2514 : }
2515 : }
2516 : // Attribute overlaps the selection
2517 2014 : else if ( ( pAttr->GetStart() <= nStart ) && ( pAttr->GetEnd() >= nEnd ) )
2518 : {
2519 49 : bChanged = true;
2520 49 : if ( pAttr->GetStart() == nStart )
2521 : {
2522 0 : pAttr->GetStart() = nEnd;
2523 0 : rpStarting = pAttr;
2524 0 : if ( nWhich )
2525 0 : break; // There can be further attributes!
2526 : }
2527 49 : else if ( pAttr->GetEnd() == nEnd )
2528 : {
2529 0 : pAttr->GetEnd() = nStart;
2530 0 : rpEnding = pAttr;
2531 0 : if ( nWhich )
2532 0 : break; // There can be further attributes!
2533 : }
2534 : else // Attribute must be split ...
2535 : {
2536 49 : sal_Int32 nOldEnd = pAttr->GetEnd();
2537 49 : pAttr->GetEnd() = nStart;
2538 49 : rpEnding = pAttr;
2539 49 : InsertAttrib( *pAttr->GetItem(), pNode, nEnd, nOldEnd );
2540 49 : if ( nWhich )
2541 49 : break; // There can be further attributes!
2542 : }
2543 : }
2544 : }
2545 357078 : if ( bRemoveAttrib )
2546 : {
2547 : DBG_ASSERT( ( pAttr != rpStarting ) && ( pAttr != rpEnding ), "Delete and retain the same attribute?" );
2548 : DBG_ASSERT( !pAttr->IsFeature(), "RemoveAttribs: Remove a feature?!" );
2549 2877 : GetItemPool().Remove( *pAttr->GetItem() );
2550 2877 : rAttribs.erase(rAttribs.begin()+nAttr);
2551 2877 : nAttr--;
2552 : }
2553 357078 : nAttr++;
2554 357078 : pAttr = GetAttrib(rAttribs, nAttr);
2555 : }
2556 :
2557 44045 : if ( bChanged )
2558 : {
2559 : // char attributes need to be sorted by start again
2560 13722 : pNode->GetCharAttribs().ResortAttribs();
2561 13722 : SetModified(true);
2562 : }
2563 :
2564 : #if OSL_DEBUG_LEVEL > 0
2565 : CharAttribList::DbgCheckAttribs(pNode->GetCharAttribs());
2566 : #endif
2567 :
2568 44045 : return bChanged;
2569 : }
2570 :
2571 59898 : void EditDoc::InsertAttrib( const SfxPoolItem& rPoolItem, ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd )
2572 : {
2573 : // This method no longer checks whether a corresponding attribute already
2574 : // exists at this place!
2575 59898 : EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rPoolItem, nStart, nEnd );
2576 : DBG_ASSERT( pAttrib, "MakeCharAttrib failed!" );
2577 59898 : pNode->GetCharAttribs().InsertAttrib( pAttrib );
2578 :
2579 59898 : SetModified( true );
2580 59898 : }
2581 :
2582 76623 : void EditDoc::InsertAttrib( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd, const SfxPoolItem& rPoolItem )
2583 : {
2584 76623 : if ( nStart != nEnd )
2585 : {
2586 43076 : InsertAttribInSelection( pNode, nStart, nEnd, rPoolItem );
2587 : }
2588 : else
2589 : {
2590 : // Check whether already a new attribute with WhichId exists at this place:
2591 33547 : CharAttribList& rAttrList = pNode->GetCharAttribs();
2592 33547 : EditCharAttrib* pAttr = rAttrList.FindEmptyAttrib( rPoolItem.Which(), nStart );
2593 33547 : if ( pAttr )
2594 : {
2595 : // Remove attribute....
2596 8197 : rAttrList.Release(pAttr);
2597 : }
2598 :
2599 : // check whether 'the same' attribute exist at this place.
2600 33547 : pAttr = rAttrList.FindAttrib( rPoolItem.Which(), nStart );
2601 33547 : if ( pAttr )
2602 : {
2603 7327 : if ( pAttr->IsInside( nStart ) ) // split
2604 : {
2605 : // check again if really splitting, or return !
2606 0 : sal_Int32 nOldEnd = pAttr->GetEnd();
2607 0 : pAttr->GetEnd() = nStart;
2608 0 : EditCharAttrib* pNew = MakeCharAttrib( GetItemPool(), *(pAttr->GetItem()), nStart, nOldEnd );
2609 0 : rAttrList.InsertAttrib(pNew);
2610 : }
2611 7327 : else if ( pAttr->GetEnd() == nStart )
2612 : {
2613 : DBG_ASSERT( !pAttr->IsEmpty(), "Still an empty attribute?" );
2614 : // Check if exactly the same attribute
2615 7327 : if ( *(pAttr->GetItem()) == rPoolItem )
2616 83874 : return;
2617 : }
2618 : }
2619 26296 : InsertAttrib( rPoolItem, pNode, nStart, nStart );
2620 : }
2621 :
2622 69372 : SetModified( true );
2623 : }
2624 :
2625 5054 : void EditDoc::FindAttribs( ContentNode* pNode, sal_Int32 nStartPos, sal_Int32 nEndPos, SfxItemSet& rCurSet )
2626 : {
2627 : DBG_ASSERT( pNode, "Where to search?" );
2628 : DBG_ASSERT( nStartPos <= nEndPos, "Invalid region!" );
2629 :
2630 5054 : sal_uInt16 nAttr = 0;
2631 5054 : EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
2632 : // No Selection...
2633 5054 : if ( nStartPos == nEndPos )
2634 : {
2635 18865 : while ( pAttr && ( pAttr->GetStart() <= nEndPos) )
2636 : {
2637 10745 : const SfxPoolItem* pItem = 0;
2638 : // Attribute is about...
2639 10745 : if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() > nStartPos ) )
2640 0 : pItem = pAttr->GetItem();
2641 : // Attribute ending here is not empty
2642 10745 : else if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() == nStartPos ) )
2643 : {
2644 0 : if ( !pNode->GetCharAttribs().FindEmptyAttrib( pAttr->GetItem()->Which(), nStartPos ) )
2645 0 : pItem = pAttr->GetItem();
2646 : }
2647 : // Attribute ending here is empty
2648 10745 : else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() == nStartPos ) )
2649 : {
2650 5080 : pItem = pAttr->GetItem();
2651 : }
2652 : // Attribute starts here
2653 5665 : else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() > nStartPos ) )
2654 : {
2655 5665 : if ( nStartPos == 0 ) // special case
2656 5665 : pItem = pAttr->GetItem();
2657 : }
2658 :
2659 10745 : if ( pItem )
2660 : {
2661 10745 : sal_uInt16 nWhich = pItem->Which();
2662 10745 : if ( rCurSet.GetItemState( nWhich ) == SfxItemState::DEFAULT )
2663 : {
2664 6703 : rCurSet.Put( *pItem );
2665 : }
2666 4042 : else if ( rCurSet.GetItemState( nWhich ) == SfxItemState::SET )
2667 : {
2668 4042 : const SfxPoolItem& rItem = rCurSet.Get( nWhich );
2669 4042 : if ( rItem != *pItem )
2670 : {
2671 0 : rCurSet.InvalidateItem( nWhich );
2672 : }
2673 : }
2674 : }
2675 10745 : nAttr++;
2676 10745 : pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
2677 : }
2678 : }
2679 : else // Selection
2680 : {
2681 18945 : while ( pAttr && ( pAttr->GetStart() < nEndPos) )
2682 : {
2683 16957 : const SfxPoolItem* pItem = 0;
2684 : // Attribut is about...
2685 16957 : if ( ( pAttr->GetStart() <= nStartPos ) && ( pAttr->GetEnd() >= nEndPos ) )
2686 16952 : pItem = pAttr->GetItem();
2687 : // Attribute starts right in the middle ...
2688 5 : else if ( pAttr->GetStart() >= nStartPos )
2689 : {
2690 : // !!! pItem = pAttr->GetItem();
2691 : // PItem is simply not enough, since one for example in case
2692 : // of Shadow, would never find an unequal item, since such a
2693 : // item represents its presence by absence!
2694 : // If (...)
2695 : // It needs to be examined on exactly the same attribute at the
2696 : // breaki point, which is quite expensive.
2697 : // Since optimazation is done when inserting the attributes
2698 : // this case does not appear so fast ...
2699 : // So based on the need for speed:
2700 1 : rCurSet.InvalidateItem( pAttr->GetItem()->Which() );
2701 :
2702 : }
2703 : // Attribute ends in the middle of it ...
2704 4 : else if ( pAttr->GetEnd() > nStartPos )
2705 : {
2706 0 : rCurSet.InvalidateItem( pAttr->GetItem()->Which() );
2707 : }
2708 :
2709 16957 : if ( pItem )
2710 : {
2711 16952 : sal_uInt16 nWhich = pItem->Which();
2712 16952 : if ( rCurSet.GetItemState( nWhich ) == SfxItemState::DEFAULT )
2713 : {
2714 8868 : rCurSet.Put( *pItem );
2715 : }
2716 8084 : else if ( rCurSet.GetItemState( nWhich ) == SfxItemState::SET )
2717 : {
2718 8084 : const SfxPoolItem& rItem = rCurSet.Get( nWhich );
2719 8084 : if ( rItem != *pItem )
2720 : {
2721 0 : rCurSet.InvalidateItem( nWhich );
2722 : }
2723 : }
2724 : }
2725 16957 : nAttr++;
2726 16957 : pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
2727 : }
2728 : }
2729 5054 : }
2730 :
2731 : namespace {
2732 :
2733 : struct LessByStart : std::binary_function<EditCharAttrib, EditCharAttrib, bool>
2734 : {
2735 448595 : bool operator() (const EditCharAttrib& left, const EditCharAttrib& right) const
2736 : {
2737 448595 : return left.GetStart() < right.GetStart();
2738 : }
2739 : };
2740 :
2741 : }
2742 :
2743 506251 : CharAttribList::CharAttribList()
2744 : : aAttribs()
2745 : , aDefFont()
2746 506251 : , bHasEmptyAttribs(false)
2747 : {
2748 506251 : }
2749 :
2750 503908 : CharAttribList::~CharAttribList()
2751 : {
2752 503908 : }
2753 :
2754 217365 : void CharAttribList::InsertAttrib( EditCharAttrib* pAttrib )
2755 : {
2756 : // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2757 : // optimize: binary search? !
2758 : // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2759 :
2760 : // Maybe just simply iterate backwards:
2761 : // The most common and critical case: Attributes are already sorted
2762 : // (InsertBinTextObject!) binary search would not be optimal here.
2763 : // => Would bring something!
2764 :
2765 217365 : const sal_Int32 nStart = pAttrib->GetStart(); // may be better for Comp.Opt.
2766 :
2767 : #if OSL_DEBUG_LEVEL > 0
2768 : CharAttribList::DbgCheckAttribs(*this);
2769 : #endif
2770 :
2771 217365 : if ( pAttrib->IsEmpty() )
2772 49081 : bHasEmptyAttribs = true;
2773 :
2774 217365 : bool bInsert(true);
2775 1837722 : for (sal_Int32 i = 0, n = aAttribs.size(); i < n; ++i)
2776 : {
2777 1623918 : const EditCharAttrib& rCurAttrib = aAttribs[i];
2778 1623918 : if (rCurAttrib.GetStart() > nStart)
2779 : {
2780 3561 : aAttribs.insert(aAttribs.begin()+i, pAttrib);
2781 3561 : bInsert = false;
2782 3561 : break;
2783 : }
2784 : }
2785 :
2786 217365 : if (bInsert) aAttribs.push_back(pAttrib);
2787 :
2788 : #if OSL_DEBUG_LEVEL > 0
2789 : CharAttribList::DbgCheckAttribs(*this);
2790 : #endif
2791 217365 : }
2792 :
2793 16246 : void CharAttribList::ResortAttribs()
2794 : {
2795 16246 : aAttribs.sort(LessByStart());
2796 :
2797 : #if OSL_DEBUG_LEVEL > 0
2798 : CharAttribList::DbgCheckAttribs(*this);
2799 : #endif
2800 16246 : }
2801 :
2802 26701 : void CharAttribList::OptimizeRanges( SfxItemPool& rItemPool )
2803 : {
2804 : #if OSL_DEBUG_LEVEL > 0
2805 : CharAttribList::DbgCheckAttribs(*this);
2806 : #endif
2807 190328 : for (sal_Int32 i = 0; i < (sal_Int32)aAttribs.size(); ++i)
2808 : {
2809 163627 : EditCharAttrib& rAttr = aAttribs[i];
2810 1621785 : for (sal_Int32 nNext = i+1; nNext < (sal_Int32)aAttribs.size(); ++nNext)
2811 : {
2812 1461393 : EditCharAttrib& rNext = aAttribs[nNext];
2813 1461393 : if (!rAttr.IsFeature() && rNext.GetStart() == rAttr.GetEnd() && rNext.Which() == rAttr.Which())
2814 : {
2815 668 : if (*rNext.GetItem() == *rAttr.GetItem())
2816 : {
2817 49 : rAttr.GetEnd() = rNext.GetEnd();
2818 49 : rItemPool.Remove(*rNext.GetItem());
2819 49 : aAttribs.erase(aAttribs.begin()+nNext);
2820 : }
2821 668 : break; // only 1 attr with same which can start here.
2822 : }
2823 1460725 : else if (rNext.GetStart() > rAttr.GetEnd())
2824 : {
2825 2567 : break;
2826 : }
2827 : }
2828 : }
2829 : #if OSL_DEBUG_LEVEL > 0
2830 : CharAttribList::DbgCheckAttribs(*this);
2831 : #endif
2832 26701 : }
2833 :
2834 987293 : sal_Int32 CharAttribList::Count() const
2835 : {
2836 987293 : return aAttribs.size();
2837 : }
2838 :
2839 216984 : const EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) const
2840 : {
2841 : // Backwards, if one ends where the next starts.
2842 : // => The starting one is the valid one ...
2843 216984 : AttribsType::const_reverse_iterator it = aAttribs.rbegin(), itEnd = aAttribs.rend();
2844 395229 : for (; it != itEnd; ++it)
2845 : {
2846 183759 : const EditCharAttrib& rAttr = *it;
2847 183759 : if (rAttr.Which() == nWhich && rAttr.IsIn(nPos))
2848 5514 : return &rAttr;
2849 : }
2850 211470 : return NULL;
2851 : }
2852 :
2853 59902 : EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos )
2854 : {
2855 : // Backwards, if one ends where the next starts.
2856 : // => The starting one is the valid one ...
2857 59902 : AttribsType::reverse_iterator it = aAttribs.rbegin(), itEnd = aAttribs.rend();
2858 492861 : for (; it != itEnd; ++it)
2859 : {
2860 440872 : EditCharAttrib& rAttr = *it;
2861 440872 : if (rAttr.Which() == nWhich && rAttr.IsIn(nPos))
2862 7913 : return &rAttr;
2863 : }
2864 51989 : return NULL;
2865 : }
2866 :
2867 283291 : const EditCharAttrib* CharAttribList::FindNextAttrib( sal_uInt16 nWhich, sal_Int32 nFromPos ) const
2868 : {
2869 : DBG_ASSERT( nWhich, "FindNextAttrib: Which?" );
2870 283291 : AttribsType::const_iterator it = aAttribs.begin(), itEnd = aAttribs.end();
2871 505898 : for (; it != itEnd; ++it)
2872 : {
2873 247141 : const EditCharAttrib& rAttr = *it;
2874 247141 : if (rAttr.GetStart() >= nFromPos && rAttr.Which() == nWhich)
2875 24534 : return &rAttr;
2876 : }
2877 258757 : return NULL;
2878 : }
2879 :
2880 0 : bool CharAttribList::HasAttrib( sal_Int32 nStartPos, sal_Int32 nEndPos ) const
2881 : {
2882 0 : AttribsType::const_reverse_iterator it = aAttribs.rbegin(), itEnd = aAttribs.rend();
2883 0 : for (; it != itEnd; ++it)
2884 : {
2885 0 : const EditCharAttrib& rAttr = *it;
2886 0 : if (rAttr.GetStart() < nEndPos && rAttr.GetEnd() > nStartPos)
2887 0 : return true;
2888 : }
2889 0 : return false;
2890 : }
2891 :
2892 :
2893 :
2894 : namespace {
2895 :
2896 : class FindByAddress : std::unary_function<EditCharAttrib, bool>
2897 : {
2898 : const EditCharAttrib* mpAttr;
2899 : public:
2900 8197 : FindByAddress(const EditCharAttrib* p) : mpAttr(p) {}
2901 16262 : bool operator() (const EditCharAttrib& r) const
2902 : {
2903 16262 : return &r == mpAttr;
2904 : }
2905 : };
2906 :
2907 : }
2908 :
2909 0 : void CharAttribList::Remove(const EditCharAttrib* p)
2910 : {
2911 0 : AttribsType::iterator it = std::find_if(aAttribs.begin(), aAttribs.end(), FindByAddress(p));
2912 0 : if (it != aAttribs.end())
2913 0 : aAttribs.erase(it);
2914 0 : }
2915 :
2916 2056 : void CharAttribList::Remove(sal_Int32 nPos)
2917 : {
2918 2056 : if (nPos >= (sal_Int32)aAttribs.size())
2919 2056 : return;
2920 :
2921 2056 : aAttribs.erase(aAttribs.begin()+nPos);
2922 : }
2923 :
2924 8197 : void CharAttribList::Release(const EditCharAttrib* p)
2925 : {
2926 8197 : AttribsType::iterator it = std::find_if(aAttribs.begin(), aAttribs.end(), FindByAddress(p));
2927 8197 : if (it != aAttribs.end())
2928 8197 : aAttribs.release(it).release();
2929 8197 : }
2930 :
2931 84 : void CharAttribList::SetHasEmptyAttribs(bool b)
2932 : {
2933 84 : bHasEmptyAttribs = b;
2934 84 : }
2935 :
2936 0 : bool CharAttribList::HasBoundingAttrib( sal_Int32 nBound ) const
2937 : {
2938 : // Backwards, if one ends where the next starts.
2939 : // => The starting one is the valid one ...
2940 0 : AttribsType::const_reverse_iterator it = aAttribs.rbegin(), itEnd = aAttribs.rend();
2941 0 : for (; it != itEnd; ++it)
2942 : {
2943 0 : const EditCharAttrib& rAttr = *it;
2944 0 : if (rAttr.GetEnd() < nBound)
2945 0 : return false;
2946 :
2947 0 : if (rAttr.GetStart() == nBound || rAttr.GetEnd() == nBound)
2948 0 : return true;
2949 : }
2950 0 : return false;
2951 : }
2952 :
2953 0 : const EditCharAttrib* CharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) const
2954 : {
2955 0 : if ( !bHasEmptyAttribs )
2956 0 : return NULL;
2957 :
2958 0 : AttribsType::const_iterator it = aAttribs.begin(), itEnd = aAttribs.end();
2959 0 : for (; it != itEnd; ++it)
2960 : {
2961 0 : const EditCharAttrib& rAttr = *it;
2962 0 : if (rAttr.GetStart() == nPos && rAttr.GetEnd() == nPos && rAttr.Which() == nWhich)
2963 0 : return &rAttr;
2964 : }
2965 0 : return NULL;
2966 : }
2967 :
2968 40909 : EditCharAttrib* CharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_Int32 nPos )
2969 : {
2970 40909 : if ( !bHasEmptyAttribs )
2971 1774 : return NULL;
2972 :
2973 39135 : AttribsType::iterator it = aAttribs.begin(), itEnd = aAttribs.end();
2974 431787 : for (; it != itEnd; ++it)
2975 : {
2976 400891 : EditCharAttrib& rAttr = *it;
2977 400891 : if (rAttr.GetStart() == nPos && rAttr.GetEnd() == nPos && rAttr.Which() == nWhich)
2978 8239 : return &rAttr;
2979 : }
2980 30896 : return NULL;
2981 : }
2982 :
2983 : namespace {
2984 :
2985 : class FindByStartPos : std::unary_function<EditCharAttrib, bool>
2986 : {
2987 : sal_Int32 mnPos;
2988 : public:
2989 274601 : FindByStartPos(sal_Int32 nPos) : mnPos(nPos) {}
2990 135606 : bool operator() (const EditCharAttrib& r) const
2991 : {
2992 135606 : return r.GetStart() >= mnPos;
2993 : }
2994 : };
2995 :
2996 : }
2997 :
2998 274601 : const EditCharAttrib* CharAttribList::FindFeature( sal_Int32 nPos ) const
2999 : {
3000 : // First, find the first attribute that starts at or after specified position.
3001 : AttribsType::const_iterator it =
3002 274601 : std::find_if(aAttribs.begin(), aAttribs.end(), FindByStartPos(nPos));
3003 :
3004 274601 : if (it == aAttribs.end())
3005 : // All attributes are before the specified position.
3006 248147 : return NULL;
3007 :
3008 : // And find the first attribute with feature.
3009 26454 : it = std::find_if(it, aAttribs.end(), boost::bind(&EditCharAttrib::IsFeature, _1) == true);
3010 26454 : return it == aAttribs.end() ? NULL : &(*it);
3011 : }
3012 :
3013 : namespace {
3014 :
3015 : class RemoveEmptyAttrItem : std::unary_function<EditCharAttrib, void>
3016 : {
3017 : SfxItemPool& mrItemPool;
3018 : public:
3019 633 : RemoveEmptyAttrItem(SfxItemPool& rPool) : mrItemPool(rPool) {}
3020 8913 : void operator() (const EditCharAttrib& r)
3021 : {
3022 8913 : if (r.IsEmpty())
3023 16 : mrItemPool.Remove(*r.GetItem());
3024 8913 : }
3025 : };
3026 :
3027 : }
3028 :
3029 633 : void CharAttribList::DeleteEmptyAttribs( SfxItemPool& rItemPool )
3030 : {
3031 633 : std::for_each(aAttribs.begin(), aAttribs.end(), RemoveEmptyAttrItem(rItemPool));
3032 633 : aAttribs.erase_if(boost::bind(&EditCharAttrib::IsEmpty, _1) == true);
3033 633 : bHasEmptyAttribs = false;
3034 633 : }
3035 :
3036 : #if OSL_DEBUG_LEVEL > 0
3037 : void CharAttribList::DbgCheckAttribs(CharAttribList const& rAttribs)
3038 : {
3039 : AttribsType::const_iterator it = rAttribs.aAttribs.begin();
3040 : AttribsType::const_iterator itEnd = rAttribs.aAttribs.end();
3041 : std::set<std::pair<sal_Int32, sal_uInt16>> zero_set;
3042 : for (; it != itEnd; ++it)
3043 : {
3044 : const EditCharAttrib& rAttr = *it;
3045 : assert(rAttr.GetStart() <= rAttr.GetEnd());
3046 : assert(!rAttr.IsFeature() || rAttr.GetLen() == 1);
3047 : if (0 == rAttr.GetLen())
3048 : {
3049 : // not sure if 0-length attributes allowed at all in non-empty para?
3050 : assert(zero_set.insert(std::make_pair(rAttr.GetStart(), rAttr.Which())).second && "duplicate 0-length attribute detected");
3051 : }
3052 : }
3053 : CheckOrderedList(rAttribs.GetAttribs(), true);
3054 : // CheckOrderedList(rAttribs.GetAttribs(), false); // this does not work - need 2nd array to sort by ends?
3055 : }
3056 : #endif
3057 :
3058 :
3059 56134 : EditEngineItemPool::EditEngineItemPool( bool bPersistenRefCounts )
3060 : : SfxItemPool( "EditEngineItemPool", EE_ITEMS_START, EE_ITEMS_END,
3061 56134 : aItemInfos, 0, bPersistenRefCounts )
3062 : {
3063 56134 : SetVersionMap( 1, 3999, 4015, aV1Map );
3064 56134 : SetVersionMap( 2, 3999, 4019, aV2Map );
3065 56134 : SetVersionMap( 3, 3997, 4020, aV3Map );
3066 56134 : SetVersionMap( 4, 3994, 4022, aV4Map );
3067 56134 : SetVersionMap( 5, 3994, 4037, aV5Map );
3068 56134 : SetVersionMap( 6, 3994, 4038, aV6Map );
3069 :
3070 56134 : SfxPoolItem** ppDefItems = EE_DLL().GetGlobalData()->GetDefItems();
3071 56134 : SetDefaults( ppDefItems );
3072 56134 : }
3073 :
3074 95100 : EditEngineItemPool::~EditEngineItemPool()
3075 : {
3076 95100 : }
3077 :
3078 6366 : SvStream& EditEngineItemPool::Store( SvStream& rStream ) const
3079 : {
3080 : // for a 3.1 export a hack has to be installed, as in there is a BUG in
3081 : // SfxItemSet::Load, but not subsequently after 3.1.
3082 :
3083 : // The selected range must be kept after Store, because itemsets are not
3084 : // stored until then...
3085 :
3086 6366 : long nVersion = rStream.GetVersion();
3087 6366 : bool b31Format = nVersion && ( nVersion <= SOFFICE_FILEFORMAT_31 );
3088 :
3089 6366 : EditEngineItemPool* pThis = const_cast<EditEngineItemPool*>(this);
3090 6366 : if ( b31Format )
3091 0 : pThis->SetStoringRange( 3997, 4022 );
3092 : else
3093 6366 : pThis->SetStoringRange( EE_ITEMS_START, EE_ITEMS_END );
3094 :
3095 6366 : return SfxItemPool::Store( rStream );
3096 444 : }
3097 :
3098 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|