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