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