1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_editeng.hxx"
26
27 #include <vcl/wrkwin.hxx>
28 #include <vcl/dialog.hxx>
29 #include <vcl/msgbox.hxx>
30 #include <vcl/svapp.hxx>
31
32 #include <editeng/tstpitem.hxx>
33 #include <editeng/colritem.hxx>
34 #include <editeng/fontitem.hxx>
35 #include <editeng/crsditem.hxx>
36 #include <editeng/fhgtitem.hxx>
37 #include <editeng/postitem.hxx>
38 #include <editeng/kernitem.hxx>
39 #include <editeng/wrlmitem.hxx>
40 #include <editeng/wghtitem.hxx>
41 #include <editeng/udlnitem.hxx>
42 #include <editeng/cntritem.hxx>
43 #include <editeng/escpitem.hxx>
44 #include <editeng/shdditem.hxx>
45 #include <editeng/akrnitem.hxx>
46 #include <editeng/cscoitem.hxx>
47 #include <editeng/langitem.hxx>
48 #include <editeng/emphitem.hxx>
49 #include <editeng/charscaleitem.hxx>
50 #include <editeng/charreliefitem.hxx>
51 #include <editeng/xmlcnitm.hxx>
52 #include <editeng/editids.hrc>
53
54 #include <editdoc.hxx>
55 #include <editdbg.hxx>
56 #include <editeng/eerdll.hxx>
57 #include <eerdll2.hxx>
58 #include <tools/stream.hxx>
59 #include <tools/debug.hxx>
60 #include <tools/shl.hxx>
61 #include <vcl/svapp.hxx>
62 #include <com/sun/star/i18n/ScriptType.hpp>
63 #include <stdlib.h> // qsort
64
65 using namespace ::com::sun::star;
66
67
68 // ------------------------------------------------------------
69
GetScriptItemId(sal_uInt16 nItemId,short nScriptType)70 sal_uInt16 GetScriptItemId( sal_uInt16 nItemId, short nScriptType )
71 {
72 sal_uInt16 nId = nItemId;
73
74 if ( ( nScriptType == i18n::ScriptType::ASIAN ) ||
75 ( nScriptType == i18n::ScriptType::COMPLEX ) )
76 {
77 switch ( nItemId )
78 {
79 case EE_CHAR_LANGUAGE:
80 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_LANGUAGE_CJK : EE_CHAR_LANGUAGE_CTL;
81 break;
82 case EE_CHAR_FONTINFO:
83 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_FONTINFO_CJK : EE_CHAR_FONTINFO_CTL;
84 break;
85 case EE_CHAR_FONTHEIGHT:
86 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_FONTHEIGHT_CJK : EE_CHAR_FONTHEIGHT_CTL;
87 break;
88 case EE_CHAR_WEIGHT:
89 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_WEIGHT_CJK : EE_CHAR_WEIGHT_CTL;
90 break;
91 case EE_CHAR_ITALIC:
92 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_ITALIC_CJK : EE_CHAR_ITALIC_CTL;
93 break;
94 }
95 }
96
97 return nId;
98 }
99
IsScriptItemValid(sal_uInt16 nItemId,short nScriptType)100 sal_Bool IsScriptItemValid( sal_uInt16 nItemId, short nScriptType )
101 {
102 sal_Bool bValid = sal_True;
103
104 switch ( nItemId )
105 {
106 case EE_CHAR_LANGUAGE:
107 bValid = nScriptType == i18n::ScriptType::LATIN;
108 break;
109 case EE_CHAR_LANGUAGE_CJK:
110 bValid = nScriptType == i18n::ScriptType::ASIAN;
111 break;
112 case EE_CHAR_LANGUAGE_CTL:
113 bValid = nScriptType == i18n::ScriptType::COMPLEX;
114 break;
115 case EE_CHAR_FONTINFO:
116 bValid = nScriptType == i18n::ScriptType::LATIN;
117 break;
118 case EE_CHAR_FONTINFO_CJK:
119 bValid = nScriptType == i18n::ScriptType::ASIAN;
120 break;
121 case EE_CHAR_FONTINFO_CTL:
122 bValid = nScriptType == i18n::ScriptType::COMPLEX;
123 break;
124 case EE_CHAR_FONTHEIGHT:
125 bValid = nScriptType == i18n::ScriptType::LATIN;
126 break;
127 case EE_CHAR_FONTHEIGHT_CJK:
128 bValid = nScriptType == i18n::ScriptType::ASIAN;
129 break;
130 case EE_CHAR_FONTHEIGHT_CTL:
131 bValid = nScriptType == i18n::ScriptType::COMPLEX;
132 break;
133 case EE_CHAR_WEIGHT:
134 bValid = nScriptType == i18n::ScriptType::LATIN;
135 break;
136 case EE_CHAR_WEIGHT_CJK:
137 bValid = nScriptType == i18n::ScriptType::ASIAN;
138 break;
139 case EE_CHAR_WEIGHT_CTL:
140 bValid = nScriptType == i18n::ScriptType::COMPLEX;
141 break;
142 case EE_CHAR_ITALIC:
143 bValid = nScriptType == i18n::ScriptType::LATIN;
144 break;
145 case EE_CHAR_ITALIC_CJK:
146 bValid = nScriptType == i18n::ScriptType::ASIAN;
147 break;
148 case EE_CHAR_ITALIC_CTL:
149 bValid = nScriptType == i18n::ScriptType::COMPLEX;
150 break;
151 }
152
153 return bValid;
154 }
155
156
157 // ------------------------------------------------------------
158
159 // Sollte spaeter zentral nach TOOLS/STRING (Aktuell: 303)
160 // fuer Grep: WS_TARGET
161
162 DBG_NAME( EE_TextPortion );
163 DBG_NAME( EE_EditLine );
164 DBG_NAME( EE_ContentNode );
165 DBG_NAME( EE_CharAttribList );
166
167 SfxItemInfo aItemInfos[EDITITEMCOUNT] = {
168 { SID_ATTR_FRAMEDIRECTION, SFX_ITEM_POOLABLE }, // EE_PARA_WRITINGDIR
169 { 0, SFX_ITEM_POOLABLE }, // EE_PARA_XMLATTRIBS
170 { SID_ATTR_PARA_HANGPUNCTUATION, SFX_ITEM_POOLABLE }, // EE_PARA_HANGINGPUNCTUATION
171 { SID_ATTR_PARA_FORBIDDEN_RULES, SFX_ITEM_POOLABLE },
172 { SID_ATTR_PARA_SCRIPTSPACE, SFX_ITEM_POOLABLE }, // EE_PARA_ASIANCJKSPACING
173 { SID_ATTR_NUMBERING_RULE, SFX_ITEM_POOLABLE }, // EE_PARA_NUMBULL
174 { 0, SFX_ITEM_POOLABLE }, // EE_PARA_HYPHENATE
175 { 0, SFX_ITEM_POOLABLE }, // EE_PARA_BULLETSTATE
176 { 0, SFX_ITEM_POOLABLE }, // EE_PARA_OUTLLRSPACE
177 { SID_ATTR_PARA_OUTLLEVEL, SFX_ITEM_POOLABLE },
178 { SID_ATTR_PARA_BULLET, SFX_ITEM_POOLABLE },
179 { SID_ATTR_LRSPACE, SFX_ITEM_POOLABLE },
180 { SID_ATTR_ULSPACE, SFX_ITEM_POOLABLE },
181 { SID_ATTR_PARA_LINESPACE, SFX_ITEM_POOLABLE },
182 { SID_ATTR_PARA_ADJUST, SFX_ITEM_POOLABLE },
183 { SID_ATTR_TABSTOP, SFX_ITEM_POOLABLE },
184 { SID_ATTR_CHAR_COLOR, SFX_ITEM_POOLABLE },
185 { SID_ATTR_CHAR_FONT, SFX_ITEM_POOLABLE },
186 { SID_ATTR_CHAR_FONTHEIGHT, SFX_ITEM_POOLABLE },
187 { SID_ATTR_CHAR_SCALEWIDTH, SFX_ITEM_POOLABLE },
188 { SID_ATTR_CHAR_WEIGHT, SFX_ITEM_POOLABLE },
189 { SID_ATTR_CHAR_UNDERLINE, SFX_ITEM_POOLABLE },
190 { SID_ATTR_CHAR_STRIKEOUT, SFX_ITEM_POOLABLE },
191 { SID_ATTR_CHAR_POSTURE, SFX_ITEM_POOLABLE },
192 { SID_ATTR_CHAR_CONTOUR, SFX_ITEM_POOLABLE },
193 { SID_ATTR_CHAR_SHADOWED, SFX_ITEM_POOLABLE },
194 { SID_ATTR_CHAR_ESCAPEMENT, SFX_ITEM_POOLABLE },
195 { SID_ATTR_CHAR_AUTOKERN, SFX_ITEM_POOLABLE },
196 { SID_ATTR_CHAR_KERNING, SFX_ITEM_POOLABLE },
197 { SID_ATTR_CHAR_WORDLINEMODE, SFX_ITEM_POOLABLE },
198 { SID_ATTR_CHAR_LANGUAGE, SFX_ITEM_POOLABLE },
199 { SID_ATTR_CHAR_CJK_LANGUAGE, SFX_ITEM_POOLABLE },
200 { SID_ATTR_CHAR_CTL_LANGUAGE, SFX_ITEM_POOLABLE },
201 { SID_ATTR_CHAR_CJK_FONT, SFX_ITEM_POOLABLE },
202 { SID_ATTR_CHAR_CTL_FONT, SFX_ITEM_POOLABLE },
203 { SID_ATTR_CHAR_CJK_FONTHEIGHT, SFX_ITEM_POOLABLE },
204 { SID_ATTR_CHAR_CTL_FONTHEIGHT, SFX_ITEM_POOLABLE },
205 { SID_ATTR_CHAR_CJK_WEIGHT, SFX_ITEM_POOLABLE },
206 { SID_ATTR_CHAR_CTL_WEIGHT, SFX_ITEM_POOLABLE },
207 { SID_ATTR_CHAR_CJK_POSTURE, SFX_ITEM_POOLABLE },
208 { SID_ATTR_CHAR_CTL_POSTURE, SFX_ITEM_POOLABLE },
209 { SID_ATTR_CHAR_EMPHASISMARK, SFX_ITEM_POOLABLE },
210 { SID_ATTR_CHAR_RELIEF, SFX_ITEM_POOLABLE },
211 { 0, SFX_ITEM_POOLABLE }, // EE_CHAR_RUBI_DUMMY
212 { 0, SFX_ITEM_POOLABLE }, // EE_CHAR_XMLATTRIBS
213 { SID_ATTR_CHAR_OVERLINE, SFX_ITEM_POOLABLE },
214 { 0, SFX_ITEM_POOLABLE }, // EE_FEATURE_TAB
215 { 0, SFX_ITEM_POOLABLE }, // EE_FEATURE_LINEBR
216 { SID_ATTR_CHAR_CHARSETCOLOR, SFX_ITEM_POOLABLE }, // EE_FEATURE_NOTCONV
217 { SID_FIELD, SFX_ITEM_POOLABLE }
218 };
219
220 sal_uInt16 aV1Map[] = {
221 3999, 4001, 4002, 4003, 4004, 4005, 4006,
222 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4017, 4018, 4019 // MI: 4019?
223 };
224
225 sal_uInt16 aV2Map[] = {
226 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009,
227 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4018, 4019, 4020
228 };
229
230 sal_uInt16 aV3Map[] = {
231 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007,
232 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019,
233 4020, 4021
234 };
235
236 sal_uInt16 aV4Map[] = {
237 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003,
238 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013,
239 4014, 4015, 4016, 4017, 4018,
240 /* CJK Items inserted here: EE_CHAR_LANGUAGE - EE_CHAR_XMLATTRIBS */
241 4034, 4035, 4036, 4037
242 };
243
244 sal_uInt16 aV5Map[] = {
245 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003,
246 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013,
247 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023,
248 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033,
249 /* EE_CHAR_OVERLINE inserted here */
250 4035, 4036, 4037, 4038
251 };
252
CompareStart(const void * pFirst,const void * pSecond)253 int SAL_CALL CompareStart( const void* pFirst, const void* pSecond )
254 {
255 if ( (*((EditCharAttrib**)pFirst))->GetStart() < (*((EditCharAttrib**)pSecond))->GetStart() )
256 return (-1);
257 else if ( (*((EditCharAttrib**)pFirst))->GetStart() > (*((EditCharAttrib**)pSecond))->GetStart() )
258 return (1);
259 return 0;
260 }
261
MakeCharAttrib(SfxItemPool & rPool,const SfxPoolItem & rAttr,sal_uInt16 nS,sal_uInt16 nE)262 EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, sal_uInt16 nS, sal_uInt16 nE )
263 {
264 // das neue Attribut im Pool anlegen
265 const SfxPoolItem& rNew = rPool.Put( rAttr );
266
267 EditCharAttrib* pNew = 0;
268 switch( rNew.Which() )
269 {
270 case EE_CHAR_LANGUAGE:
271 case EE_CHAR_LANGUAGE_CJK:
272 case EE_CHAR_LANGUAGE_CTL:
273 {
274 pNew = new EditCharAttribLanguage( (const SvxLanguageItem&)rNew, nS, nE );
275 }
276 break;
277 case EE_CHAR_COLOR:
278 {
279 pNew = new EditCharAttribColor( (const SvxColorItem&)rNew, nS, nE );
280 }
281 break;
282 case EE_CHAR_FONTINFO:
283 case EE_CHAR_FONTINFO_CJK:
284 case EE_CHAR_FONTINFO_CTL:
285 {
286 pNew = new EditCharAttribFont( (const SvxFontItem&)rNew, nS, nE );
287 }
288 break;
289 case EE_CHAR_FONTHEIGHT:
290 case EE_CHAR_FONTHEIGHT_CJK:
291 case EE_CHAR_FONTHEIGHT_CTL:
292 {
293 pNew = new EditCharAttribFontHeight( (const SvxFontHeightItem&)rNew, nS, nE );
294 }
295 break;
296 case EE_CHAR_FONTWIDTH:
297 {
298 pNew = new EditCharAttribFontWidth( (const SvxCharScaleWidthItem&)rNew, nS, nE );
299 }
300 break;
301 case EE_CHAR_WEIGHT:
302 case EE_CHAR_WEIGHT_CJK:
303 case EE_CHAR_WEIGHT_CTL:
304 {
305 pNew = new EditCharAttribWeight( (const SvxWeightItem&)rNew, nS, nE );
306 }
307 break;
308 case EE_CHAR_UNDERLINE:
309 {
310 pNew = new EditCharAttribUnderline( (const SvxUnderlineItem&)rNew, nS, nE );
311 }
312 break;
313 case EE_CHAR_OVERLINE:
314 {
315 pNew = new EditCharAttribOverline( (const SvxOverlineItem&)rNew, nS, nE );
316 }
317 break;
318 case EE_CHAR_EMPHASISMARK:
319 {
320 pNew = new EditCharAttribEmphasisMark( (const SvxEmphasisMarkItem&)rNew, nS, nE );
321 }
322 break;
323 case EE_CHAR_RELIEF:
324 {
325 pNew = new EditCharAttribRelief( (const SvxCharReliefItem&)rNew, nS, nE );
326 }
327 break;
328 case EE_CHAR_STRIKEOUT:
329 {
330 pNew = new EditCharAttribStrikeout( (const SvxCrossedOutItem&)rNew, nS, nE );
331 }
332 break;
333 case EE_CHAR_ITALIC:
334 case EE_CHAR_ITALIC_CJK:
335 case EE_CHAR_ITALIC_CTL:
336 {
337 pNew = new EditCharAttribItalic( (const SvxPostureItem&)rNew, nS, nE );
338 }
339 break;
340 case EE_CHAR_OUTLINE:
341 {
342 pNew = new EditCharAttribOutline( (const SvxContourItem&)rNew, nS, nE );
343 }
344 break;
345 case EE_CHAR_SHADOW:
346 {
347 pNew = new EditCharAttribShadow( (const SvxShadowedItem&)rNew, nS, nE );
348 }
349 break;
350 case EE_CHAR_ESCAPEMENT:
351 {
352 pNew = new EditCharAttribEscapement( (const SvxEscapementItem&)rNew, nS, nE );
353 }
354 break;
355 case EE_CHAR_PAIRKERNING:
356 {
357 pNew = new EditCharAttribPairKerning( (const SvxAutoKernItem&)rNew, nS, nE );
358 }
359 break;
360 case EE_CHAR_KERNING:
361 {
362 pNew = new EditCharAttribKerning( (const SvxKerningItem&)rNew, nS, nE );
363 }
364 break;
365 case EE_CHAR_WLM:
366 {
367 pNew = new EditCharAttribWordLineMode( (const SvxWordLineModeItem&)rNew, nS, nE );
368 }
369 break;
370 case EE_CHAR_XMLATTRIBS:
371 {
372 pNew = new EditCharAttrib( rNew, nS, nE ); // Attrib is only for holding XML information...
373 }
374 break;
375 case EE_FEATURE_TAB:
376 {
377 pNew = new EditCharAttribTab( (const SfxVoidItem&)rNew, nS );
378 }
379 break;
380 case EE_FEATURE_LINEBR:
381 {
382 pNew = new EditCharAttribLineBreak( (const SfxVoidItem&)rNew, nS );
383 }
384 break;
385 case EE_FEATURE_FIELD:
386 {
387 pNew = new EditCharAttribField( (const SvxFieldItem&)rNew, nS );
388 }
389 break;
390 default:
391 {
392 DBG_ERROR( "Ungueltiges Attribut!" );
393 }
394 }
395 return pNew;
396 }
397
398 // -------------------------------------------------------------------------
399 // class EditLine
400 // -------------------------------------------------------------------------
401
EditLine()402 EditLine::EditLine()
403 {
404 DBG_CTOR( EE_EditLine, 0 );
405
406 nStart = nEnd = 0;
407 nStartPortion = 0; // damit in ungueltiger Zeile ohne Portions von einer gueltigen Zeile mit der Portion Nr0 unterscieden werden kann.
408 nEndPortion = 0;
409 nHeight = 0;
410 nStartPosX = 0;
411 nTxtHeight = 0;
412 nTxtWidth = 0;
413 nCrsrHeight = 0;
414 nMaxAscent = 0;
415 bHangingPunctuation = sal_False;
416 bInvalid = sal_True;
417 }
418
EditLine(const EditLine & r)419 EditLine::EditLine( const EditLine& r )
420 {
421 DBG_CTOR( EE_EditLine, 0 );
422
423 nEnd = r.nEnd;
424 nStart = r.nStart;
425 nStartPortion = r.nStartPortion;
426 nEndPortion = r.nEndPortion;
427 bHangingPunctuation = r.bHangingPunctuation;
428
429 nHeight = 0;
430 nStartPosX = 0;
431 nTxtHeight = 0;
432 nTxtWidth = 0;
433 nCrsrHeight = 0;
434 nMaxAscent = 0;
435 bInvalid = sal_True;
436 }
437
~EditLine()438 EditLine::~EditLine()
439 {
440 DBG_DTOR( EE_EditLine, 0 );
441 }
442
Clone() const443 EditLine* EditLine::Clone() const
444 {
445 EditLine* pL = new EditLine;
446 if ( aPositions.Count() )
447 {
448 pL->aPositions.Insert (aPositions.GetData(), aPositions.Count(), 0);
449 }
450 pL->nStartPosX = nStartPosX;
451 pL->nStart = nStart;
452 pL->nEnd = nEnd;
453 pL->nStartPortion = nStartPortion;
454 pL->nEndPortion = nEndPortion;
455 pL->nHeight = nHeight;
456 pL->nTxtWidth = nTxtWidth;
457 pL->nTxtHeight = nTxtHeight;
458 pL->nCrsrHeight = nCrsrHeight;
459 pL->nMaxAscent = nMaxAscent;
460
461 return pL;
462 }
463
operator ==(const EditLine & r1,const EditLine & r2)464 sal_Bool operator == ( const EditLine& r1, const EditLine& r2 )
465 {
466 if ( r1.nStart != r2.nStart )
467 return sal_False;
468
469 if ( r1.nEnd != r2.nEnd )
470 return sal_False;
471
472 if ( r1.nStartPortion != r2.nStartPortion )
473 return sal_False;
474
475 if ( r1.nEndPortion != r2.nEndPortion )
476 return sal_False;
477
478 return sal_True;
479 }
480
operator =(const EditLine & r)481 EditLine& EditLine::operator = ( const EditLine& r )
482 {
483 nEnd = r.nEnd;
484 nStart = r.nStart;
485 nEndPortion = r.nEndPortion;
486 nStartPortion = r.nStartPortion;
487 return *this;
488 }
489
490
operator !=(const EditLine & r1,const EditLine & r2)491 sal_Bool operator != ( const EditLine& r1, const EditLine& r2 )
492 {
493 return !( r1 == r2 );
494 }
495
CalcTextSize(ParaPortion & rParaPortion)496 Size EditLine::CalcTextSize( ParaPortion& rParaPortion )
497 {
498 Size aSz;
499 Size aTmpSz;
500 TextPortion* pPortion;
501
502 sal_uInt16 nIndex = GetStart();
503
504 DBG_ASSERT( rParaPortion.GetTextPortions().Count(), "GetTextSize vor CreatePortions !" );
505
506 for ( sal_uInt16 n = nStartPortion; n <= nEndPortion; n++ )
507 {
508 pPortion = rParaPortion.GetTextPortions().GetObject(n);
509 switch ( pPortion->GetKind() )
510 {
511 case PORTIONKIND_TEXT:
512 case PORTIONKIND_FIELD:
513 case PORTIONKIND_HYPHENATOR:
514 {
515 aTmpSz = pPortion->GetSize();
516 aSz.Width() += aTmpSz.Width();
517 if ( aSz.Height() < aTmpSz.Height() )
518 aSz.Height() = aTmpSz.Height();
519 }
520 break;
521 case PORTIONKIND_TAB:
522 // case PORTIONKIND_EXTRASPACE:
523 {
524 aSz.Width() += pPortion->GetSize().Width();
525 }
526 break;
527 }
528 nIndex = nIndex + pPortion->GetLen();
529 }
530
531 SetHeight( (sal_uInt16)aSz.Height() );
532 return aSz;
533 }
534
535 // -------------------------------------------------------------------------
536 // class EditLineList
537 // -------------------------------------------------------------------------
EditLineList()538 EditLineList::EditLineList()
539 {
540 }
541
~EditLineList()542 EditLineList::~EditLineList()
543 {
544 Reset();
545 }
546
Reset()547 void EditLineList::Reset()
548 {
549 for ( sal_uInt16 nLine = 0; nLine < Count(); nLine++ )
550 delete GetObject(nLine);
551 Remove( 0, Count() );
552 }
553
DeleteFromLine(sal_uInt16 nDelFrom)554 void EditLineList::DeleteFromLine( sal_uInt16 nDelFrom )
555 {
556 DBG_ASSERT( nDelFrom <= (Count() - 1), "DeleteFromLine: Out of range" );
557 for ( sal_uInt16 nL = nDelFrom; nL < Count(); nL++ )
558 delete GetObject(nL);
559 Remove( nDelFrom, Count()-nDelFrom );
560 }
561
FindLine(sal_uInt16 nChar,sal_Bool bInclEnd)562 sal_uInt16 EditLineList::FindLine( sal_uInt16 nChar, sal_Bool bInclEnd )
563 {
564 for ( sal_uInt16 nLine = 0; nLine < Count(); nLine++ )
565 {
566 EditLine* pLine = GetObject( nLine );
567 if ( ( bInclEnd && ( pLine->GetEnd() >= nChar ) ) ||
568 ( pLine->GetEnd() > nChar ) )
569 {
570 return nLine;
571 }
572 }
573
574 DBG_ASSERT( !bInclEnd, "Zeile nicht gefunden: FindLine" );
575 return ( Count() - 1 );
576 }
577
578 // -------------------------------------------------------------------------
579 // class EditSelection
580 // -------------------------------------------------------------------------
DbgIsBuggy(EditDoc & rDoc)581 sal_Bool EditPaM::DbgIsBuggy( EditDoc& rDoc )
582 {
583 if ( !pNode )
584 return sal_True;
585 if ( rDoc.GetPos( pNode ) >= rDoc.Count() )
586 return sal_True;
587 if ( nIndex > pNode->Len() )
588 return sal_True;
589
590 return sal_False;
591 }
592
DbgIsBuggy(EditDoc & rDoc)593 sal_Bool EditSelection::DbgIsBuggy( EditDoc& rDoc )
594 {
595 if ( aStartPaM.DbgIsBuggy( rDoc ) )
596 return sal_True;
597 if ( aEndPaM.DbgIsBuggy( rDoc ) )
598 return sal_True;
599
600 return sal_False;
601 }
602
EditSelection()603 EditSelection::EditSelection()
604 {
605 }
606
EditSelection(const EditPaM & rStartAndAnd)607 EditSelection::EditSelection( const EditPaM& rStartAndAnd )
608 {
609 // koennte noch optimiert werden!
610 // nicht erst Def-CTOR vom PaM rufen!
611 aStartPaM = rStartAndAnd;
612 aEndPaM = rStartAndAnd;
613 }
614
EditSelection(const EditPaM & rStart,const EditPaM & rEnd)615 EditSelection::EditSelection( const EditPaM& rStart, const EditPaM& rEnd )
616 {
617 // koennte noch optimiert werden!
618 aStartPaM = rStart;
619 aEndPaM = rEnd;
620 }
621
operator =(const EditPaM & rPaM)622 EditSelection& EditSelection::operator = ( const EditPaM& rPaM )
623 {
624 aStartPaM = rPaM;
625 aEndPaM = rPaM;
626 return *this;
627 }
628
IsInvalid() const629 sal_Bool EditSelection::IsInvalid() const
630 {
631 EditPaM aEmptyPaM;
632
633 if ( aStartPaM == aEmptyPaM )
634 return sal_True;
635
636 if ( aEndPaM == aEmptyPaM )
637 return sal_True;
638
639 return sal_False;
640 }
641
Adjust(const ContentList & rNodes)642 sal_Bool EditSelection::Adjust( const ContentList& rNodes )
643 {
644 DBG_ASSERT( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index im Wald in Adjust(1)" );
645 DBG_ASSERT( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index im Wald in Adjust(2)" );
646
647 ContentNode* pStartNode = aStartPaM.GetNode();
648 ContentNode* pEndNode = aEndPaM.GetNode();
649
650 sal_uInt32 nStartNode = rNodes.GetPos( pStartNode );
651 sal_uInt32 nEndNode = rNodes.GetPos( pEndNode );
652
653 DBG_ASSERT( nStartNode != USHRT_MAX, "Node im Wald in Adjust(1)" );
654 DBG_ASSERT( nEndNode != USHRT_MAX, "Node im Wald in Adjust(2)" );
655
656 sal_Bool bSwap = sal_False;
657 if ( nStartNode > nEndNode )
658 bSwap = sal_True;
659 else if ( ( nStartNode == nEndNode ) && ( aStartPaM.GetIndex() > aEndPaM.GetIndex() ) )
660 bSwap = sal_True;
661
662 if ( bSwap )
663 {
664 EditPaM aTmpPaM( aStartPaM );
665 aStartPaM = aEndPaM;
666 aEndPaM = aTmpPaM;
667 }
668
669 return bSwap;
670 }
671
672
673 // -------------------------------------------------------------------------
674 // class EditPaM
675 // -------------------------------------------------------------------------
operator ==(const EditPaM & r1,const EditPaM & r2)676 sal_Bool operator == ( const EditPaM& r1, const EditPaM& r2 )
677 {
678 if ( r1.GetNode() != r2.GetNode() )
679 return sal_False;
680
681 if ( r1.GetIndex() != r2.GetIndex() )
682 return sal_False;
683
684 return sal_True;
685 }
686
operator =(const EditPaM & rPaM)687 EditPaM& EditPaM::operator = ( const EditPaM& rPaM )
688 {
689 nIndex = rPaM.nIndex;
690 pNode = rPaM.pNode;
691 return *this;
692 }
693
operator !=(const EditPaM & r1,const EditPaM & r2)694 sal_Bool operator != ( const EditPaM& r1, const EditPaM& r2 )
695 {
696 return !( r1 == r2 );
697 }
698
699
700 // -------------------------------------------------------------------------
701 // class ContentNode
702 // -------------------------------------------------------------------------
ContentNode(SfxItemPool & rPool)703 ContentNode::ContentNode( SfxItemPool& rPool ) : aContentAttribs( rPool )
704 {
705 DBG_CTOR( EE_ContentNode, 0 );
706 pWrongList = NULL;
707 }
708
ContentNode(const XubString & rStr,const ContentAttribs & rContentAttribs)709 ContentNode::ContentNode( const XubString& rStr, const ContentAttribs& rContentAttribs ) :
710 XubString( rStr ), aContentAttribs( rContentAttribs )
711 {
712 DBG_CTOR( EE_ContentNode, 0 );
713 pWrongList = NULL;
714 }
715
~ContentNode()716 ContentNode::~ContentNode()
717 {
718 DBG_DTOR( EE_ContentNode, 0 );
719 #ifndef SVX_LIGHT
720 delete pWrongList;
721 #endif
722 }
723
ExpandAttribs(sal_uInt16 nIndex,sal_uInt16 nNew,SfxItemPool & rItemPool)724 void ContentNode::ExpandAttribs( sal_uInt16 nIndex, sal_uInt16 nNew, SfxItemPool& rItemPool )
725 {
726 if ( !nNew )
727 return;
728
729 // Da Features anders behandelt werden als normale Zeichenattribute,
730 // kann sich hier auch die Sortierung der Start-Liste aendern!
731 // In jedem if..., in dem weiter (n) Moeglichkeiten aufgrund von
732 // bFeature oder Spezialfall existieren,
733 // muessen (n-1) Moeglichkeiten mit bResort versehen werden.
734 // Die wahrscheinlichste Moeglichkeit erhaelt kein bResort,
735 // so dass nicht neu sortiert wird, wenn sich alle Attribute
736 // gleich verhalten.
737 sal_Bool bResort = sal_False;
738 sal_Bool bExpandedEmptyAtIndexNull = sal_False;
739
740 sal_uInt16 nAttr = 0;
741 EditCharAttrib* pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr );
742 while ( pAttrib )
743 {
744 if ( pAttrib->GetEnd() >= nIndex )
745 {
746 // Alle Attribute hinter der Einfuegeposition verschieben...
747 if ( pAttrib->GetStart() > nIndex )
748 {
749 pAttrib->MoveForward( nNew );
750 }
751 // 0: Leeres Attribut expandieren, wenn an Einfuegestelle
752 else if ( pAttrib->IsEmpty() )
753 {
754 // Index nicht pruefen, leeres durfte nur dort liegen.
755 // Wenn spaeter doch Ueberpruefung:
756 // Spezialfall: Start == 0; AbsLen == 1, nNew = 1 => Expand, weil durch Absatzumbruch!
757 // Start <= nIndex, End >= nIndex => Start=End=nIndex!
758 // if ( pAttrib->GetStart() == nIndex )
759 pAttrib->Expand( nNew );
760 if ( pAttrib->GetStart() == 0 )
761 bExpandedEmptyAtIndexNull = sal_True;
762 }
763 // 1: Attribut startet davor, geht bis Index...
764 else if ( pAttrib->GetEnd() == nIndex ) // Start muss davor liegen
765 {
766 // Nur expandieren, wenn kein Feature,
767 // und wenn nicht in ExcludeListe!
768 // Sonst geht z.B. ein UL bis zum neuen ULDB, beide expandieren
769 // if ( !pAttrib->IsFeature() && !rExclList.FindAttrib( pAttrib->Which() ) )
770 if ( !pAttrib->IsFeature() && !aCharAttribList.FindEmptyAttrib( pAttrib->Which(), nIndex ) )
771 {
772 if ( !pAttrib->IsEdge() )
773 pAttrib->Expand( nNew );
774 }
775 else
776 bResort = sal_True;
777 }
778 // 2: Attribut startet davor, geht hinter Index...
779 else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) )
780 {
781 DBG_ASSERT( !pAttrib->IsFeature(), "Grosses Feature?!" );
782 pAttrib->Expand( nNew );
783 }
784 // 3: Attribut startet auf Index...
785 else if ( pAttrib->GetStart() == nIndex )
786 {
787 if ( pAttrib->IsFeature() )
788 {
789 pAttrib->MoveForward( nNew );
790 bResort = sal_True;
791 }
792 else
793 {
794 sal_Bool bExpand = sal_False;
795 if ( nIndex == 0 )
796 {
797 bExpand = sal_True;
798 if( bExpandedEmptyAtIndexNull )
799 {
800 // Check if this kind of attribut was empty and expanded here...
801 sal_uInt16 nW = pAttrib->GetItem()->Which();
802 for ( sal_uInt16 nA = 0; nA < nAttr; nA++ )
803 {
804 EditCharAttrib* pA = aCharAttribList.GetAttribs()[nA];
805 if ( ( pA->GetStart() == 0 ) && ( pA->GetItem()->Which() == nW ) )
806 {
807 bExpand = sal_False;
808 break;
809 }
810 }
811
812 }
813 }
814 if ( bExpand )
815 {
816 pAttrib->Expand( nNew );
817 bResort = sal_True;
818 }
819 else
820 {
821 pAttrib->MoveForward( nNew );
822 }
823 }
824 }
825 }
826
827 if ( pAttrib->IsEdge() )
828 pAttrib->SetEdge( sal_False );
829
830 DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" );
831
832 DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribut verdreht!" );
833 DBG_ASSERT( ( pAttrib->GetEnd() <= Len() ), "Expand: Attrib groesser als Absatz!" );
834 if ( pAttrib->IsEmpty() )
835 {
836 DBG_ERROR( "Leeres Attribut nach ExpandAttribs?" );
837 bResort = sal_True;
838 aCharAttribList.GetAttribs().Remove( nAttr );
839 rItemPool.Remove( *pAttrib->GetItem() );
840 delete pAttrib;
841 nAttr--;
842 }
843 nAttr++;
844 pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr );
845 }
846
847 if ( bResort )
848 aCharAttribList.ResortAttribs();
849
850 #ifndef SVX_LIGHT
851 if ( pWrongList )
852 {
853 sal_Bool bSep = ( GetChar( nIndex ) == ' ' ) || IsFeature( nIndex );
854 pWrongList->TextInserted( nIndex, nNew, bSep );
855 }
856 #endif // !SVX_LIGHT
857
858 #ifdef EDITDEBUG
859 DBG_ASSERT( CheckOrderedList( aCharAttribList.GetAttribs(), sal_True ), "Expand: Start-Liste verdreht" );
860 #endif
861 }
862
CollapsAttribs(sal_uInt16 nIndex,sal_uInt16 nDeleted,SfxItemPool & rItemPool)863 void ContentNode::CollapsAttribs( sal_uInt16 nIndex, sal_uInt16 nDeleted, SfxItemPool& rItemPool )
864 {
865 if ( !nDeleted )
866 return;
867
868 // Da Features anders behandelt werden als normale Zeichenattribute,
869 // kann sich hier auch die Sortierung der Start-Liste aendern!
870 sal_Bool bResort = sal_False;
871 sal_Bool bDelAttr = sal_False;
872 sal_uInt16 nEndChanges = nIndex+nDeleted;
873
874 sal_uInt16 nAttr = 0;
875 EditCharAttrib* pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr );
876 while ( pAttrib )
877 {
878 bDelAttr = sal_False;
879 if ( pAttrib->GetEnd() >= nIndex )
880 {
881 // Alles Attribute hinter der Einfuegeposition verschieben...
882 if ( pAttrib->GetStart() >= nEndChanges )
883 {
884 pAttrib->MoveBackward( nDeleted );
885 }
886 // 1. Innenliegende Attribute loeschen...
887 else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() <= nEndChanges ) )
888 {
889 // Spezialfall: Attrubt deckt genau den Bereich ab
890 // => als leeres Attribut behalten.
891 if ( !pAttrib->IsFeature() && ( pAttrib->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) )
892 pAttrib->GetEnd() = nIndex; // leer
893 else
894 bDelAttr = sal_True;
895 }
896 // 2. Attribut beginnt davor, endet drinnen oder dahinter...
897 else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) )
898 {
899 DBG_ASSERT( !pAttrib->IsFeature(), "Collapsing Feature!" );
900 if ( pAttrib->GetEnd() <= nEndChanges ) // endet drinnen
901 pAttrib->GetEnd() = nIndex;
902 else
903 pAttrib->Collaps( nDeleted ); // endet dahinter
904 }
905 // 3. Attribut beginnt drinnen, endet dahinter...
906 else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() > nEndChanges ) )
907 {
908 // Features duerfen nicht expandieren!
909 if ( pAttrib->IsFeature() )
910 {
911 pAttrib->MoveBackward( nDeleted );
912 bResort = sal_True;
913 }
914 else
915 {
916 pAttrib->GetStart() = nEndChanges;
917 pAttrib->MoveBackward( nDeleted );
918 }
919 }
920 }
921 DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" );
922
923 DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collaps: Attribut verdreht!" );
924 DBG_ASSERT( ( pAttrib->GetEnd() <= Len()) || bDelAttr, "Collaps: Attrib groesser als Absatz!" );
925 if ( bDelAttr /* || pAttrib->IsEmpty() */ )
926 {
927 bResort = sal_True;
928 aCharAttribList.GetAttribs().Remove( nAttr );
929 rItemPool.Remove( *pAttrib->GetItem() );
930 delete pAttrib;
931 nAttr--;
932 }
933 else if ( pAttrib->IsEmpty() )
934 aCharAttribList.HasEmptyAttribs() = sal_True;
935
936 nAttr++;
937 pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr );
938 }
939
940 if ( bResort )
941 aCharAttribList.ResortAttribs();
942
943 #ifndef SVX_LIGHT
944 if ( pWrongList )
945 pWrongList->TextDeleted( nIndex, nDeleted );
946 #endif // !SVX_LIGHT
947
948 #ifdef EDITDEBUG
949 DBG_ASSERT( CheckOrderedList( aCharAttribList.GetAttribs(), sal_True ), "Collaps: Start-Liste verdreht" );
950 #endif
951 }
952
CopyAndCutAttribs(ContentNode * pPrevNode,SfxItemPool & rPool,sal_Bool bKeepEndingAttribs)953 void ContentNode::CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, sal_Bool bKeepEndingAttribs )
954 {
955 DBG_ASSERT( pPrevNode, "kopieren von Attributen auf einen NULL-Pointer ?" );
956
957 xub_StrLen nCut = pPrevNode->Len();
958
959 sal_uInt16 nAttr = 0;
960 EditCharAttrib* pAttrib = GetAttrib( pPrevNode->GetCharAttribs().GetAttribs(), nAttr );
961 while ( pAttrib )
962 {
963 if ( pAttrib->GetEnd() < nCut )
964 {
965 // bleiben unveraendert....
966 ;
967 }
968 else if ( pAttrib->GetEnd() == nCut )
969 {
970 // muessen als leeres Attribut kopiert werden.
971 if ( bKeepEndingAttribs && !pAttrib->IsFeature() && !aCharAttribList.FindAttrib( pAttrib->GetItem()->Which(), 0 ) )
972 {
973 EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, 0 );
974 DBG_ASSERT( pNewAttrib, "MakeCharAttrib fehlgeschlagen!" );
975 aCharAttribList.InsertAttrib( pNewAttrib );
976 }
977 }
978 else if ( pAttrib->IsInside( nCut ) || ( !nCut && !pAttrib->GetStart() && !pAttrib->IsFeature() ) )
979 {
980 // Wenn ganz vorne gecuttet wird, muss das Attribut erhalten bleiben!
981 // muessen kopiert und geaendert werden
982 EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, pAttrib->GetEnd()-nCut );
983 DBG_ASSERT( pNewAttrib, "MakeCharAttrib fehlgeschlagen!" );
984 aCharAttribList.InsertAttrib( pNewAttrib );
985 // stutzen:
986 pAttrib->GetEnd() = nCut;
987 }
988 else
989 {
990 // alle dahinter verschieben in den neuen Node (this)
991 // pPrevNode->GetCharAttribs().RemoveAttrib( pAttrib );
992 pPrevNode->GetCharAttribs().GetAttribs().Remove( nAttr );
993 aCharAttribList.InsertAttrib( pAttrib );
994 DBG_ASSERT( pAttrib->GetStart() >= nCut, "Start < nCut!" );
995 DBG_ASSERT( pAttrib->GetEnd() >= nCut, "End < nCut!" );
996 pAttrib->GetStart() = pAttrib->GetStart() - nCut;
997 pAttrib->GetEnd() = pAttrib->GetEnd() - nCut;
998 nAttr--;
999 }
1000 nAttr++;
1001 pAttrib = GetAttrib( pPrevNode->GetCharAttribs().GetAttribs(), nAttr );
1002 }
1003 }
1004
AppendAttribs(ContentNode * pNextNode)1005 void ContentNode::AppendAttribs( ContentNode* pNextNode )
1006 {
1007 DBG_ASSERT( pNextNode, "kopieren von Attributen von einen NULL-Pointer ?" );
1008
1009 sal_uInt16 nNewStart = Len();
1010
1011 #ifdef EDITDEBUG
1012 DBG_ASSERT( aCharAttribList.DbgCheckAttribs(), "Attribute VOR AppendAttribs kaputt" );
1013 #endif
1014
1015 sal_uInt16 nAttr = 0;
1016 EditCharAttrib* pAttrib = GetAttrib( pNextNode->GetCharAttribs().GetAttribs(), nAttr );
1017 while ( pAttrib )
1018 {
1019 // alle Attribute verschieben in den aktuellen Node (this)
1020 sal_Bool bMelted = sal_False;
1021 if ( ( pAttrib->GetStart() == 0 ) && ( !pAttrib->IsFeature() ) )
1022 {
1023 // Evtl koennen Attribute zusammengefasst werden:
1024 sal_uInt16 nTmpAttr = 0;
1025 EditCharAttrib* pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr );
1026 while ( !bMelted && pTmpAttrib )
1027 {
1028 if ( pTmpAttrib->GetEnd() == nNewStart )
1029 {
1030 if ( ( pTmpAttrib->Which() == pAttrib->Which() ) &&
1031 ( *(pTmpAttrib->GetItem()) == *(pAttrib->GetItem() ) ) )
1032 {
1033 pTmpAttrib->GetEnd() =
1034 pTmpAttrib->GetEnd() + pAttrib->GetLen();
1035 pNextNode->GetCharAttribs().GetAttribs().Remove( nAttr );
1036 // Vom Pool abmelden ?!
1037 delete pAttrib;
1038 bMelted = sal_True;
1039 }
1040 }
1041 ++nTmpAttr;
1042 pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr );
1043 }
1044 }
1045
1046 if ( !bMelted )
1047 {
1048 pAttrib->GetStart() = pAttrib->GetStart() + nNewStart;
1049 pAttrib->GetEnd() = pAttrib->GetEnd() + nNewStart;
1050 aCharAttribList.InsertAttrib( pAttrib );
1051 ++nAttr;
1052 }
1053 pAttrib = GetAttrib( pNextNode->GetCharAttribs().GetAttribs(), nAttr );
1054 }
1055 // Fuer die Attribute, die nur ruebergewandert sind:
1056 pNextNode->GetCharAttribs().Clear();
1057
1058 #ifdef EDITDEBUG
1059 DBG_ASSERT( aCharAttribList.DbgCheckAttribs(), "Attribute NACH AppendAttribs kaputt" );
1060 #endif
1061 }
1062
CreateDefFont()1063 void ContentNode::CreateDefFont()
1064 {
1065 // Erst alle Informationen aus dem Style verwenden...
1066 SfxStyleSheet* pS = aContentAttribs.GetStyleSheet();
1067 if ( pS )
1068 CreateFont( GetCharAttribs().GetDefFont(), pS->GetItemSet() );
1069
1070 // ... dann die harte Absatzformatierung rueberbuegeln...
1071 CreateFont( GetCharAttribs().GetDefFont(),
1072 GetContentAttribs().GetItems(), pS == NULL );
1073 }
1074
SetStyleSheet(SfxStyleSheet * pS,const SvxFont & rFontFromStyle)1075 void ContentNode::SetStyleSheet( SfxStyleSheet* pS, const SvxFont& rFontFromStyle )
1076 {
1077 aContentAttribs.SetStyleSheet( pS );
1078
1079 // Erst alle Informationen aus dem Style verwenden...
1080 GetCharAttribs().GetDefFont() = rFontFromStyle;
1081 // ... dann die harte Absatzformatierung rueberbuegeln...
1082 CreateFont( GetCharAttribs().GetDefFont(),
1083 GetContentAttribs().GetItems(), pS == NULL );
1084 }
1085
SetStyleSheet(SfxStyleSheet * pS,sal_Bool bRecalcFont)1086 void ContentNode::SetStyleSheet( SfxStyleSheet* pS, sal_Bool bRecalcFont )
1087 {
1088 aContentAttribs.SetStyleSheet( pS );
1089 if ( bRecalcFont )
1090 CreateDefFont();
1091 }
1092
DestroyWrongList()1093 void ContentNode::DestroyWrongList()
1094 {
1095 #ifndef SVX_LIGHT
1096 delete pWrongList;
1097 #endif
1098 pWrongList = NULL;
1099 }
1100
CreateWrongList()1101 void ContentNode::CreateWrongList()
1102 {
1103 DBG_ASSERT( !pWrongList, "WrongList existiert schon!" );
1104 #ifndef SVX_LIGHT
1105 pWrongList = new WrongList;
1106 #endif
1107 }
1108
SetWrongList(WrongList * p)1109 void ContentNode::SetWrongList( WrongList* p )
1110 {
1111 DBG_ASSERT( !pWrongList, "WrongList existiert schon!" );
1112 pWrongList = p;
1113 }
1114
1115 // -------------------------------------------------------------------------
1116 // class ContentAttribs
1117 // -------------------------------------------------------------------------
ContentAttribs(SfxItemPool & rPool)1118 ContentAttribs::ContentAttribs( SfxItemPool& rPool ) :
1119 aAttribSet( rPool, EE_PARA_START, EE_CHAR_END )
1120 {
1121 pStyle = 0;
1122 }
1123
ContentAttribs(const ContentAttribs & rRef)1124 ContentAttribs::ContentAttribs( const ContentAttribs& rRef ) :
1125 aAttribSet( rRef.aAttribSet )
1126 {
1127 pStyle = rRef.pStyle;
1128 }
1129
~ContentAttribs()1130 ContentAttribs::~ContentAttribs()
1131 {
1132 }
1133
FindTabStop(long nCurPos,sal_uInt16 nDefTab)1134 SvxTabStop ContentAttribs::FindTabStop( long nCurPos, sal_uInt16 nDefTab )
1135 {
1136 const SvxTabStopItem& rTabs = (const SvxTabStopItem&) GetItem( EE_PARA_TABS );
1137 for ( sal_uInt16 i = 0; i < rTabs.Count(); i++ )
1138 {
1139 const SvxTabStop& rTab = rTabs[i];
1140 if ( rTab.GetTabPos() > nCurPos )
1141 return rTab;
1142 }
1143
1144 // DefTab ermitteln...
1145 SvxTabStop aTabStop;
1146 long x = nCurPos / nDefTab + 1;
1147 aTabStop.GetTabPos() = nDefTab * x;
1148 return aTabStop;
1149 }
1150
SetStyleSheet(SfxStyleSheet * pS)1151 void ContentAttribs::SetStyleSheet( SfxStyleSheet* pS )
1152 {
1153 sal_Bool bStyleChanged = ( pStyle != pS );
1154 pStyle = pS;
1155 // #104799# Only when other style sheet, not when current style sheet modified
1156 if ( pStyle && bStyleChanged )
1157 {
1158 // Gezielt die Attribute aus der Absatzformatierung entfernen, die im Style
1159 // spezifiziert sind, damit die Attribute des Styles wirken koennen.
1160 const SfxItemSet& rStyleAttribs = pStyle->GetItemSet();
1161 for ( sal_uInt16 nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ )
1162 {
1163 // #99635# Don't change bullet on/off
1164 if ( ( nWhich != EE_PARA_BULLETSTATE ) && ( rStyleAttribs.GetItemState( nWhich ) == SFX_ITEM_ON ) )
1165 aAttribSet.ClearItem( nWhich );
1166 }
1167 }
1168 }
1169
GetItem(sal_uInt16 nWhich)1170 const SfxPoolItem& ContentAttribs::GetItem( sal_uInt16 nWhich )
1171 {
1172 // Harte Absatzattribute haben Vorrang!
1173 SfxItemSet* pTakeFrom = &aAttribSet;
1174 if ( pStyle && ( aAttribSet.GetItemState( nWhich, sal_False ) != SFX_ITEM_ON ) )
1175 pTakeFrom = &pStyle->GetItemSet();
1176
1177 return pTakeFrom->Get( nWhich );
1178 }
1179
HasItem(sal_uInt16 nWhich)1180 sal_Bool ContentAttribs::HasItem( sal_uInt16 nWhich )
1181 {
1182 sal_Bool bHasItem = sal_False;
1183 if ( aAttribSet.GetItemState( nWhich, sal_False ) == SFX_ITEM_ON )
1184 bHasItem = sal_True;
1185 else if ( pStyle && pStyle->GetItemSet().GetItemState( nWhich ) == SFX_ITEM_ON )
1186 bHasItem = sal_True;
1187
1188 return bHasItem;
1189 }
1190
1191
1192
1193 // ----------------------------------------------------------------------
1194 // class ItemList
1195 // ----------------------------------------------------------------------
FindAttrib(sal_uInt16 nWhich)1196 const SfxPoolItem* ItemList::FindAttrib( sal_uInt16 nWhich )
1197 {
1198 const SfxPoolItem* pItem = First();
1199 while ( pItem && ( pItem->Which() != nWhich ) )
1200 pItem = Next();
1201
1202 return pItem;
1203 }
1204
1205 // -------------------------------------------------------------------------
1206 // class EditDoc
1207 // -------------------------------------------------------------------------
EditDoc(SfxItemPool * pPool)1208 EditDoc::EditDoc( SfxItemPool* pPool )
1209 {
1210 if ( pPool )
1211 {
1212 pItemPool = pPool;
1213 bOwnerOfPool = sal_False;
1214 }
1215 else
1216 {
1217 pItemPool = new EditEngineItemPool( sal_False );
1218 bOwnerOfPool = sal_True;
1219 }
1220
1221 nDefTab = DEFTAB;
1222 bIsVertical = sal_False;
1223 bIsFixedCellHeight = sal_False;
1224
1225 // Don't create a empty node, Clear() will be called in EditEngine-CTOR
1226
1227 SetModified( sal_False );
1228 };
1229
~EditDoc()1230 EditDoc::~EditDoc()
1231 {
1232 ImplDestroyContents();
1233 if ( bOwnerOfPool )
1234 SfxItemPool::Free(pItemPool);
1235 }
1236
ImplDestroyContents()1237 void EditDoc::ImplDestroyContents()
1238 {
1239 for ( sal_uInt32 nNode = Count(); nNode; )
1240 RemoveItemsFromPool( GetObject( --nNode ) );
1241 DeleteAndDestroy( 0, Count() );
1242 }
1243
RemoveItemsFromPool(ContentNode * pNode)1244 void EditDoc::RemoveItemsFromPool( ContentNode* pNode )
1245 {
1246 for ( sal_uInt16 nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ )
1247 {
1248 EditCharAttrib* pAttr = pNode->GetCharAttribs().GetAttribs()[nAttr];
1249 GetItemPool().Remove( *pAttr->GetItem() );
1250 }
1251 }
1252
CreateFont(SvxFont & rFont,const SfxItemSet & rSet,bool bSearchInParent,short nScriptType)1253 void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, short nScriptType )
1254 {
1255 Font aPrevFont( rFont );
1256 rFont.SetAlign( ALIGN_BASELINE );
1257 rFont.SetTransparent( sal_True );
1258
1259 sal_uInt16 nWhich_FontInfo = GetScriptItemId( EE_CHAR_FONTINFO, nScriptType );
1260 sal_uInt16 nWhich_Language = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType );
1261 sal_uInt16 nWhich_FontHeight = GetScriptItemId( EE_CHAR_FONTHEIGHT, nScriptType );
1262 sal_uInt16 nWhich_Weight = GetScriptItemId( EE_CHAR_WEIGHT, nScriptType );
1263 sal_uInt16 nWhich_Italic = GetScriptItemId( EE_CHAR_ITALIC, nScriptType );
1264
1265 if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontInfo ) == SFX_ITEM_ON ) )
1266 {
1267 const SvxFontItem& rFontItem = (const SvxFontItem&)rSet.Get( nWhich_FontInfo );
1268 rFont.SetName( rFontItem.GetFamilyName() );
1269 rFont.SetFamily( rFontItem.GetFamily() );
1270 rFont.SetPitch( rFontItem.GetPitch() );
1271 rFont.SetCharSet( rFontItem.GetCharSet() );
1272 }
1273 if ( bSearchInParent || ( rSet.GetItemState( nWhich_Language ) == SFX_ITEM_ON ) )
1274 rFont.SetLanguage( ((const SvxLanguageItem&)rSet.Get( nWhich_Language )).GetLanguage() );
1275 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_COLOR ) == SFX_ITEM_ON ) )
1276 rFont.SetColor( ((const SvxColorItem&)rSet.Get( EE_CHAR_COLOR )).GetValue() );
1277 if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontHeight ) == SFX_ITEM_ON ) )
1278 rFont.SetSize( Size( rFont.GetSize().Width(), ((const SvxFontHeightItem&)rSet.Get( nWhich_FontHeight ) ).GetHeight() ) );
1279 if ( bSearchInParent || ( rSet.GetItemState( nWhich_Weight ) == SFX_ITEM_ON ) )
1280 rFont.SetWeight( ((const SvxWeightItem&)rSet.Get( nWhich_Weight )).GetWeight() );
1281 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_UNDERLINE ) == SFX_ITEM_ON ) )
1282 rFont.SetUnderline( ((const SvxUnderlineItem&)rSet.Get( EE_CHAR_UNDERLINE )).GetLineStyle() );
1283 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OVERLINE ) == SFX_ITEM_ON ) )
1284 rFont.SetOverline( ((const SvxOverlineItem&)rSet.Get( EE_CHAR_OVERLINE )).GetLineStyle() );
1285 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_STRIKEOUT ) == SFX_ITEM_ON ) )
1286 rFont.SetStrikeout( ((const SvxCrossedOutItem&)rSet.Get( EE_CHAR_STRIKEOUT )).GetStrikeout() );
1287 if ( bSearchInParent || ( rSet.GetItemState( nWhich_Italic ) == SFX_ITEM_ON ) )
1288 rFont.SetItalic( ((const SvxPostureItem&)rSet.Get( nWhich_Italic )).GetPosture() );
1289 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OUTLINE ) == SFX_ITEM_ON ) )
1290 rFont.SetOutline( ((const SvxContourItem&)rSet.Get( EE_CHAR_OUTLINE )).GetValue() );
1291 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_SHADOW ) == SFX_ITEM_ON ) )
1292 rFont.SetShadow( ((const SvxShadowedItem&)rSet.Get( EE_CHAR_SHADOW )).GetValue() );
1293 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_ESCAPEMENT ) == SFX_ITEM_ON ) )
1294 {
1295 const SvxEscapementItem& rEsc = (const SvxEscapementItem&) rSet.Get( EE_CHAR_ESCAPEMENT );
1296
1297 sal_uInt16 nProp = rEsc.GetProp();
1298 rFont.SetPropr( (sal_uInt8)nProp );
1299
1300 short nEsc = rEsc.GetEsc();
1301 if ( nEsc == DFLT_ESC_AUTO_SUPER )
1302 nEsc = 100 - nProp;
1303 else if ( nEsc == DFLT_ESC_AUTO_SUB )
1304 nEsc = sal::static_int_cast< short >( -( 100 - nProp ) );
1305 rFont.SetEscapement( nEsc );
1306 }
1307 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_PAIRKERNING ) == SFX_ITEM_ON ) )
1308 rFont.SetKerning( ((const SvxAutoKernItem&)rSet.Get( EE_CHAR_PAIRKERNING )).GetValue() );
1309 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_KERNING ) == SFX_ITEM_ON ) )
1310 rFont.SetFixKerning( ((const SvxKerningItem&)rSet.Get( EE_CHAR_KERNING )).GetValue() );
1311 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_WLM ) == SFX_ITEM_ON ) )
1312 rFont.SetWordLineMode( ((const SvxWordLineModeItem&)rSet.Get( EE_CHAR_WLM )).GetValue() );
1313 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_EMPHASISMARK ) == SFX_ITEM_ON ) )
1314 rFont.SetEmphasisMark( ((const SvxEmphasisMarkItem&)rSet.Get( EE_CHAR_EMPHASISMARK )).GetValue() );
1315 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_RELIEF ) == SFX_ITEM_ON ) )
1316 rFont.SetRelief( (FontRelief)((const SvxCharReliefItem&)rSet.Get( EE_CHAR_RELIEF )).GetValue() );
1317
1318 // Ob ich jetzt den ganzen Font vergleiche, oder vor jeder Aenderung
1319 // pruefe, ob der Wert sich aendert, bleibt sich relativ gleich.
1320 // So ggf ein MakeUniqFont im Font mehr, dafuer bei Aenderung schnellerer
1321 // Abbruch der Abfrage, oder ich musste noch jedesmal ein bChanged pflegen.
1322 if ( rFont == aPrevFont )
1323 rFont = aPrevFont; // => Gleicher ImpPointer fuer IsSameInstance
1324 }
1325
CreateDefFont(sal_Bool bUseStyles)1326 void EditDoc::CreateDefFont( sal_Bool bUseStyles )
1327 {
1328 SfxItemSet aTmpSet( GetItemPool(), EE_PARA_START, EE_CHAR_END );
1329 CreateFont( aDefFont, aTmpSet );
1330 aDefFont.SetVertical( IsVertical() );
1331 aDefFont.SetOrientation( IsVertical() ? 2700 : 0 );
1332
1333 for ( sal_uInt32 nNode = 0; nNode < Count(); nNode++ )
1334 {
1335 ContentNode* pNode = GetObject( nNode );
1336 pNode->GetCharAttribs().GetDefFont() = aDefFont;
1337 if ( bUseStyles )
1338 pNode->CreateDefFont();
1339 }
1340 }
1341
1342 static const sal_Unicode aCR[] = { 0x0d, 0x00 };
1343 static const sal_Unicode aLF[] = { 0x0a, 0x00 };
1344 static const sal_Unicode aCRLF[] = { 0x0d, 0x0a, 0x00 };
1345
GetSepStr(LineEnd eEnd)1346 XubString EditDoc::GetSepStr( LineEnd eEnd )
1347 {
1348 XubString aSep;
1349 if ( eEnd == LINEEND_CR )
1350 aSep = aCR;
1351 else if ( eEnd == LINEEND_LF )
1352 aSep = aLF;
1353 else
1354 aSep = aCRLF;
1355 return aSep;
1356 }
1357
GetText(LineEnd eEnd) const1358 XubString EditDoc::GetText( LineEnd eEnd ) const
1359 {
1360 sal_uLong nLen = GetTextLen();
1361 sal_uInt32 nNodes = Count();
1362
1363 String aSep = EditDoc::GetSepStr( eEnd );
1364 sal_uInt16 nSepSize = aSep.Len();
1365
1366 if ( nSepSize )
1367 nLen += nNodes * nSepSize;
1368 if ( nLen > 0xFFFb / sizeof(xub_Unicode) )
1369 {
1370 DBG_ERROR( "Text zu gross fuer String" );
1371 return XubString();
1372 }
1373 xub_Unicode* pStr = new xub_Unicode[nLen+1];
1374 xub_Unicode* pCur = pStr;
1375 sal_uInt32 nLastNode = nNodes-1;
1376 for ( sal_uInt32 nNode = 0; nNode < nNodes; nNode++ )
1377 {
1378 XubString aTmp( GetParaAsString( GetObject(nNode) ) );
1379 memcpy( pCur, aTmp.GetBuffer(), aTmp.Len()*sizeof(sal_Unicode) );
1380 pCur += aTmp.Len();
1381 if ( nSepSize && ( nNode != nLastNode ) )
1382 {
1383 memcpy( pCur, aSep.GetBuffer(), nSepSize*sizeof(sal_Unicode ) );
1384 pCur += nSepSize;
1385 }
1386 }
1387 *pCur = '\0';
1388 XubString aASCIIText( pStr );
1389 delete[] pStr;
1390 return aASCIIText;
1391 }
1392
GetParaAsString(sal_uInt32 nNode) const1393 XubString EditDoc::GetParaAsString( sal_uInt32 nNode ) const
1394 {
1395 return GetParaAsString( SaveGetObject( nNode ) );
1396 }
1397
GetParaAsString(ContentNode * pNode,sal_uInt16 nStartPos,sal_uInt16 nEndPos,sal_Bool bResolveFields) const1398 XubString EditDoc::GetParaAsString( ContentNode* pNode, sal_uInt16 nStartPos, sal_uInt16 nEndPos, sal_Bool bResolveFields ) const
1399 {
1400 if ( nEndPos > pNode->Len() )
1401 nEndPos = pNode->Len();
1402
1403 DBG_ASSERT( nStartPos <= nEndPos, "Start und Ende vertauscht?" );
1404
1405 sal_uInt16 nIndex = nStartPos;
1406 XubString aStr;
1407 EditCharAttrib* pNextFeature = pNode->GetCharAttribs().FindFeature( nIndex );
1408 while ( nIndex < nEndPos )
1409 {
1410 sal_uInt16 nEnd = nEndPos;
1411 if ( pNextFeature && ( pNextFeature->GetStart() < nEnd ) )
1412 nEnd = pNextFeature->GetStart();
1413 else
1414 pNextFeature = 0; // Feature interessiert unten nicht
1415
1416 DBG_ASSERT( nEnd >= nIndex, "Ende vorm Index?" );
1417 //!! beware of sub string length of -1 which is also defined as STRING_LEN and
1418 //!! thus would result in adding the whole sub string up to the end of the node !!
1419 if (nEnd > nIndex)
1420 aStr += XubString( *pNode, nIndex, nEnd - nIndex );
1421
1422 if ( pNextFeature )
1423 {
1424 switch ( pNextFeature->GetItem()->Which() )
1425 {
1426 case EE_FEATURE_TAB: aStr += '\t';
1427 break;
1428 case EE_FEATURE_LINEBR: aStr += '\x0A';
1429 break;
1430 case EE_FEATURE_FIELD: if ( bResolveFields )
1431 aStr += ((EditCharAttribField*)pNextFeature)->GetFieldValue();
1432 break;
1433 default: DBG_ERROR( "Was fuer ein Feature ?" );
1434 }
1435 pNextFeature = pNode->GetCharAttribs().FindFeature( ++nEnd );
1436 }
1437 nIndex = nEnd;
1438 }
1439 return aStr;
1440 }
1441
GetTextLen() const1442 sal_uLong EditDoc::GetTextLen() const
1443 {
1444 sal_uLong nLen = 0;
1445 for ( sal_uInt32 nNode = 0; nNode < Count(); nNode++ )
1446 {
1447 ContentNode* pNode = GetObject( nNode );
1448 nLen += pNode->Len();
1449 // Felder k�nnen laenger sein als der Platzhalter im Node.
1450 const CharAttribArray& rAttrs = pNode->GetCharAttribs().GetAttribs();
1451 for ( sal_uInt16 nAttr = rAttrs.Count(); nAttr; )
1452 {
1453 EditCharAttrib* pAttr = rAttrs[--nAttr];
1454 if ( pAttr->Which() == EE_FEATURE_FIELD )
1455 {
1456 sal_uInt16 nFieldLen = ((EditCharAttribField*)pAttr)->GetFieldValue().Len();
1457 if ( !nFieldLen )
1458 nLen--;
1459 else
1460 nLen += nFieldLen-1;
1461 }
1462 }
1463 }
1464 return nLen;
1465 }
1466
Clear()1467 EditPaM EditDoc::Clear()
1468 {
1469 ImplDestroyContents();
1470
1471 ContentNode* pNode = new ContentNode( GetItemPool() );
1472 Insert( pNode, 0 );
1473
1474 CreateDefFont( sal_False );
1475
1476 SetModified( sal_False );
1477
1478 EditPaM aPaM( pNode, 0 );
1479 return aPaM;
1480 }
1481
SetModified(sal_Bool b)1482 void EditDoc::SetModified( sal_Bool b )
1483 {
1484 bModified = b;
1485 if ( bModified )
1486 {
1487 aModifyHdl.Call( NULL );
1488 }
1489 }
1490
RemoveText()1491 EditPaM EditDoc::RemoveText()
1492 {
1493 // Das alte ItemSetmerken, damit z.B. im Chart Font behalten bleibt
1494 ContentNode* pPrevFirstNode = GetObject(0);
1495 SfxStyleSheet* pPrevStyle = pPrevFirstNode->GetStyleSheet();
1496 SfxItemSet aPrevSet( pPrevFirstNode->GetContentAttribs().GetItems() );
1497 Font aPrevFont( pPrevFirstNode->GetCharAttribs().GetDefFont() );
1498
1499 ImplDestroyContents();
1500
1501 ContentNode* pNode = new ContentNode( GetItemPool() );
1502 Insert( pNode, 0 );
1503
1504 pNode->SetStyleSheet( pPrevStyle, sal_False );
1505 pNode->GetContentAttribs().GetItems().Set( aPrevSet );
1506 pNode->GetCharAttribs().GetDefFont() = aPrevFont;
1507
1508 SetModified( sal_True );
1509
1510 EditPaM aPaM( pNode, 0 );
1511 return aPaM;
1512 }
1513
InsertText(const EditPaM & rPaM,xub_Unicode c)1514 void EditDoc::InsertText( const EditPaM& rPaM, xub_Unicode c )
1515 {
1516 DBG_ASSERT( c != 0x0A, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
1517 DBG_ASSERT( c != 0x0D, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
1518 DBG_ASSERT( c != '\t', "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
1519
1520 rPaM.GetNode()->Insert( c, rPaM.GetIndex() );
1521 rPaM.GetNode()->ExpandAttribs( rPaM.GetIndex(), 1, GetItemPool() );
1522
1523 SetModified( sal_True );
1524 }
1525
InsertText(EditPaM aPaM,const XubString & rStr)1526 EditPaM EditDoc::InsertText( EditPaM aPaM, const XubString& rStr )
1527 {
1528 DBG_ASSERT( rStr.Search( 0x0A ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
1529 DBG_ASSERT( rStr.Search( 0x0D ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
1530 DBG_ASSERT( rStr.Search( '\t' ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
1531 DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertText1" );
1532
1533 aPaM.GetNode()->Insert( rStr, aPaM.GetIndex() );
1534 aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.Len(), GetItemPool() );
1535 aPaM.GetIndex() = aPaM.GetIndex() + rStr.Len();
1536
1537 SetModified( sal_True );
1538
1539 return aPaM;
1540 }
1541
InsertParaBreak(EditPaM aPaM,sal_Bool bKeepEndingAttribs)1542 EditPaM EditDoc::InsertParaBreak( EditPaM aPaM, sal_Bool bKeepEndingAttribs )
1543 {
1544 DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertParaBreak" );
1545 ContentNode* pCurNode = aPaM.GetNode();
1546 sal_uInt32 nPos = GetPos( pCurNode );
1547 XubString aStr = aPaM.GetNode()->Copy( aPaM.GetIndex() );
1548 aPaM.GetNode()->Erase( aPaM.GetIndex() );
1549
1550 // the paragraph attributes...
1551 ContentAttribs aContentAttribs( aPaM.GetNode()->GetContentAttribs() );
1552
1553 // for a new paragraph we like to have the bullet/numbering visible by default
1554 aContentAttribs.GetItems().Put( SfxBoolItem( EE_PARA_BULLETSTATE, sal_True), EE_PARA_BULLETSTATE );
1555
1556 // ContenNode-CTOR kopiert auch die Absatzattribute
1557 ContentNode* pNode = new ContentNode( aStr, aContentAttribs );
1558
1559 // Den Default-Font kopieren
1560 pNode->GetCharAttribs().GetDefFont() = aPaM.GetNode()->GetCharAttribs().GetDefFont();
1561 SfxStyleSheet* pStyle = aPaM.GetNode()->GetStyleSheet();
1562 if ( pStyle )
1563 {
1564 XubString aFollow( pStyle->GetFollow() );
1565 if ( aFollow.Len() && ( aFollow != pStyle->GetName() ) )
1566 {
1567 SfxStyleSheetBase* pNext = pStyle->GetPool().Find( aFollow, pStyle->GetFamily() );
1568 pNode->SetStyleSheet( (SfxStyleSheet*)pNext );
1569 }
1570 }
1571
1572 // Zeichenattribute muessen ggf. kopiert bzw gestutzt werden:
1573 pNode->CopyAndCutAttribs( aPaM.GetNode(), GetItemPool(), bKeepEndingAttribs );
1574
1575 Insert( pNode, nPos+1 );
1576
1577 SetModified( sal_True );
1578
1579 aPaM.SetNode( pNode );
1580 aPaM.SetIndex( 0 );
1581 return aPaM;
1582 }
1583
InsertFeature(EditPaM aPaM,const SfxPoolItem & rItem)1584 EditPaM EditDoc::InsertFeature( EditPaM aPaM, const SfxPoolItem& rItem )
1585 {
1586 DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertFeature" );
1587
1588 aPaM.GetNode()->Insert( CH_FEATURE, aPaM.GetIndex() );
1589 aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1, GetItemPool() );
1590
1591 // Fuer das Feature ein Feature-Attribut anlegen...
1592 EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rItem, aPaM.GetIndex(), aPaM.GetIndex()+1 );
1593 DBG_ASSERT( pAttrib, "Warum kann ich kein Feature anlegen ?" );
1594 aPaM.GetNode()->GetCharAttribs().InsertAttrib( pAttrib );
1595
1596 SetModified( sal_True );
1597
1598 aPaM.GetIndex()++;
1599 return aPaM;
1600 }
1601
ConnectParagraphs(ContentNode * pLeft,ContentNode * pRight)1602 EditPaM EditDoc::ConnectParagraphs( ContentNode* pLeft, ContentNode* pRight )
1603 {
1604 const EditPaM aPaM( pLeft, pLeft->Len() );
1605
1606 // Erst die Attribute, da sonst nLen nicht stimmt!
1607 pLeft->AppendAttribs( pRight );
1608 // Dann den Text...
1609 *pLeft += *pRight;
1610
1611 // der rechte verschwindet.
1612 RemoveItemsFromPool( pRight );
1613 sal_uInt32 nRight = GetPos( pRight );
1614 Remove( nRight );
1615 delete pRight;
1616
1617 SetModified( sal_True );
1618
1619 return aPaM;
1620 }
1621
RemoveChars(EditPaM aPaM,sal_uInt16 nChars)1622 EditPaM EditDoc::RemoveChars( EditPaM aPaM, sal_uInt16 nChars )
1623 {
1624 // Evtl. Features entfernen!
1625 aPaM.GetNode()->Erase( aPaM.GetIndex(), nChars );
1626 aPaM.GetNode()->CollapsAttribs( aPaM.GetIndex(), nChars, GetItemPool() );
1627
1628 SetModified( sal_True );
1629
1630 return aPaM;
1631 }
1632
InsertAttribInSelection(ContentNode * pNode,sal_uInt16 nStart,sal_uInt16 nEnd,const SfxPoolItem & rPoolItem)1633 void EditDoc::InsertAttribInSelection( ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd, const SfxPoolItem& rPoolItem )
1634 {
1635 DBG_ASSERT( pNode, "Wohin mit dem Attribut?" );
1636 DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribut zu gross!" );
1637
1638 // fuer Optimierung:
1639 // dieses endet am Anfang der Selektion => kann erweitert werden
1640 EditCharAttrib* pEndingAttrib = 0;
1641 // dieses startet am Ende der Selektion => kann erweitert werden
1642 EditCharAttrib* pStartingAttrib = 0;
1643
1644 DBG_ASSERT( nStart <= nEnd, "Kleiner Rechenfehler in InsertAttribInSelection" );
1645
1646 RemoveAttribs( pNode, nStart, nEnd, pStartingAttrib, pEndingAttrib, rPoolItem.Which() );
1647
1648 if ( pStartingAttrib && pEndingAttrib &&
1649 ( *(pStartingAttrib->GetItem()) == rPoolItem ) &&
1650 ( *(pEndingAttrib->GetItem()) == rPoolItem ) )
1651 {
1652 // wird ein groesses Attribut.
1653 pEndingAttrib->GetEnd() = pStartingAttrib->GetEnd();
1654 GetItemPool().Remove( *(pStartingAttrib->GetItem()) );
1655 pNode->GetCharAttribs().GetAttribs().Remove( pNode->GetCharAttribs().GetAttribs().GetPos( pStartingAttrib ) );
1656 delete pStartingAttrib;
1657 }
1658 else if ( pStartingAttrib && ( *(pStartingAttrib->GetItem()) == rPoolItem ) )
1659 pStartingAttrib->GetStart() = nStart;
1660 else if ( pEndingAttrib && ( *(pEndingAttrib->GetItem()) == rPoolItem ) )
1661 pEndingAttrib->GetEnd() = nEnd;
1662 else
1663 InsertAttrib( rPoolItem, pNode, nStart, nEnd );
1664
1665 if ( pStartingAttrib )
1666 pNode->GetCharAttribs().ResortAttribs();
1667
1668 SetModified( sal_True );
1669 }
1670
RemoveAttribs(ContentNode * pNode,sal_uInt16 nStart,sal_uInt16 nEnd,sal_uInt16 nWhich)1671 sal_Bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd, sal_uInt16 nWhich )
1672 {
1673 EditCharAttrib* pStarting;
1674 EditCharAttrib* pEnding;
1675 return RemoveAttribs( pNode, nStart, nEnd, pStarting, pEnding, nWhich );
1676 }
1677
RemoveAttribs(ContentNode * pNode,sal_uInt16 nStart,sal_uInt16 nEnd,EditCharAttrib * & rpStarting,EditCharAttrib * & rpEnding,sal_uInt16 nWhich)1678 sal_Bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd, EditCharAttrib*& rpStarting, EditCharAttrib*& rpEnding, sal_uInt16 nWhich )
1679 {
1680 DBG_ASSERT( pNode, "Wohin mit dem Attribut?" );
1681 DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribut zu gross!" );
1682
1683 // dieses endet am Anfang der Selektion => kann erweitert werden
1684 rpEnding = 0;
1685 // dieses startet am Ende der Selektion => kann erweitert werden
1686 rpStarting = 0;
1687
1688 sal_Bool bChanged = sal_False;
1689
1690 DBG_ASSERT( nStart <= nEnd, "Kleiner Rechenfehler in InsertAttribInSelection" );
1691
1692 // ueber die Attribute iterieren...
1693 sal_uInt16 nAttr = 0;
1694 EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
1695 while ( pAttr )
1696 {
1697 sal_Bool bRemoveAttrib = sal_False;
1698 // MT 11.9.97:
1699 // Ich denke dass in dieser Methode generell keine Features geloescht
1700 // werden sollen.
1701 // => Dann koennen die Feature-Abfragen weiter unten entfallen
1702 sal_uInt16 nAttrWhich = pAttr->Which();
1703 if ( ( nAttrWhich < EE_FEATURE_START ) && ( !nWhich || ( nAttrWhich == nWhich ) ) )
1704 {
1705 // Attribut beginnt in Selection
1706 if ( ( pAttr->GetStart() >= nStart ) && ( pAttr->GetStart() <= nEnd ) )
1707 {
1708 bChanged = sal_True;
1709 if ( pAttr->GetEnd() > nEnd )
1710 {
1711 pAttr->GetStart() = nEnd; // dann faengt es dahinter an
1712 rpStarting = pAttr;
1713 if ( nWhich )
1714 break; // es kann kein weiteres Attrib hier liegen
1715 }
1716 else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) )
1717 {
1718 // Feature nur loeschen, wenn genau an der Stelle
1719 bRemoveAttrib = sal_True;
1720 }
1721 }
1722
1723 // Attribut endet in Selection
1724 else if ( ( pAttr->GetEnd() >= nStart ) && ( pAttr->GetEnd() <= nEnd ) )
1725 {
1726 bChanged = sal_True;
1727 if ( ( pAttr->GetStart() < nStart ) && !pAttr->IsFeature() )
1728 {
1729 pAttr->GetEnd() = nStart; // dann hoert es hier auf
1730 rpEnding = pAttr;
1731 }
1732 else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) )
1733 {
1734 // Feature nur loeschen, wenn genau an der Stelle
1735 bRemoveAttrib = sal_True;
1736 }
1737 }
1738 // Attribut ueberlappt die Selektion
1739 else if ( ( pAttr->GetStart() <= nStart ) && ( pAttr->GetEnd() >= nEnd ) )
1740 {
1741 bChanged = sal_True;
1742 if ( pAttr->GetStart() == nStart )
1743 {
1744 pAttr->GetStart() = nEnd;
1745 rpStarting = pAttr;
1746 if ( nWhich )
1747 break; // es kann weitere Attribute geben!
1748 }
1749 else if ( pAttr->GetEnd() == nEnd )
1750 {
1751 pAttr->GetEnd() = nStart;
1752 rpEnding = pAttr;
1753 if ( nWhich )
1754 break; // es kann weitere Attribute geben!
1755 }
1756 else // Attribut muss gesplittet werden...
1757 {
1758 sal_uInt16 nOldEnd = pAttr->GetEnd();
1759 pAttr->GetEnd() = nStart;
1760 rpEnding = pAttr;
1761 InsertAttrib( *pAttr->GetItem(), pNode, nEnd, nOldEnd );
1762 if ( nWhich )
1763 break; // es kann weitere Attribute geben!
1764 }
1765 }
1766 }
1767 if ( bRemoveAttrib )
1768 {
1769 DBG_ASSERT( ( pAttr != rpStarting ) && ( pAttr != rpEnding ), "Loeschen und behalten des gleichen Attributs ?" );
1770 DBG_ASSERT( !pAttr->IsFeature(), "RemoveAttribs: Remove a feature?!" );
1771 pNode->GetCharAttribs().GetAttribs().Remove(nAttr);
1772 GetItemPool().Remove( *pAttr->GetItem() );
1773 delete pAttr;
1774 nAttr--;
1775 }
1776 nAttr++;
1777 pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
1778 }
1779
1780 if ( bChanged )
1781 {
1782 // char attributes need to be sorted by start again
1783 pNode->GetCharAttribs().ResortAttribs();
1784
1785 SetModified( sal_True );
1786 }
1787
1788 return bChanged;
1789 }
1790
InsertAttrib(const SfxPoolItem & rPoolItem,ContentNode * pNode,sal_uInt16 nStart,sal_uInt16 nEnd)1791 void EditDoc::InsertAttrib( const SfxPoolItem& rPoolItem, ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd )
1792 {
1793 // Diese Methode prueft nicht mehr, ob ein entspr. Attribut
1794 // schon an der Stelle existiert!
1795
1796 EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rPoolItem, nStart, nEnd );
1797 DBG_ASSERT( pAttrib, "MakeCharAttrib fehlgeschlagen!" );
1798 pNode->GetCharAttribs().InsertAttrib( pAttrib );
1799
1800 SetModified( sal_True );
1801 }
1802
InsertAttrib(ContentNode * pNode,sal_uInt16 nStart,sal_uInt16 nEnd,const SfxPoolItem & rPoolItem)1803 void EditDoc::InsertAttrib( ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd, const SfxPoolItem& rPoolItem )
1804 {
1805 if ( nStart != nEnd )
1806 {
1807 InsertAttribInSelection( pNode, nStart, nEnd, rPoolItem );
1808 }
1809 else
1810 {
1811 // Pruefen, ob schon ein neues Attribut mit der WhichId an der Stelle:
1812 EditCharAttrib* pAttr = pNode->GetCharAttribs().FindEmptyAttrib( rPoolItem.Which(), nStart );
1813 if ( pAttr )
1814 {
1815 // Attribut entfernen....
1816 pNode->GetCharAttribs().GetAttribs().Remove(
1817 pNode->GetCharAttribs().GetAttribs().GetPos( pAttr ) );
1818 delete pAttr; // #i120865#, need free it explicitly
1819 }
1820
1821 // pruefen, ob ein 'gleiches' Attribut an der Stelle liegt.
1822 pAttr = pNode->GetCharAttribs().FindAttrib( rPoolItem.Which(), nStart );
1823 if ( pAttr )
1824 {
1825 if ( pAttr->IsInside( nStart ) ) // splitten
1826 {
1827 // ???????????????????????????????
1828 // eigentlich noch pruefen, ob wirklich splittet, oder return !
1829 // ???????????????????????????????
1830 sal_uInt16 nOldEnd = pAttr->GetEnd();
1831 pAttr->GetEnd() = nStart;
1832 pAttr = MakeCharAttrib( GetItemPool(), *(pAttr->GetItem()), nStart, nOldEnd );
1833 pNode->GetCharAttribs().InsertAttrib( pAttr );
1834 }
1835 else if ( pAttr->GetEnd() == nStart )
1836 {
1837 DBG_ASSERT( !pAttr->IsEmpty(), "Doch noch ein leeres Attribut?" );
1838 // pruefen, ob genau das gleiche Attribut
1839 if ( *(pAttr->GetItem()) == rPoolItem )
1840 return;
1841 }
1842 }
1843 InsertAttrib( rPoolItem, pNode, nStart, nStart );
1844 }
1845
1846 SetModified( sal_True );
1847 }
1848
FindAttribs(ContentNode * pNode,sal_uInt16 nStartPos,sal_uInt16 nEndPos,SfxItemSet & rCurSet)1849 void EditDoc::FindAttribs( ContentNode* pNode, sal_uInt16 nStartPos, sal_uInt16 nEndPos, SfxItemSet& rCurSet )
1850 {
1851 DBG_ASSERT( pNode, "Wo soll ich suchen ?" );
1852 DBG_ASSERT( nStartPos <= nEndPos, "Ungueltiger Bereich!" );
1853
1854 sal_uInt16 nAttr = 0;
1855 EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
1856 // keine Selection...
1857 if ( nStartPos == nEndPos )
1858 {
1859 while ( pAttr && ( pAttr->GetStart() <= nEndPos) )
1860 {
1861 const SfxPoolItem* pItem = 0;
1862 // Attribut liegt dadrueber...
1863 if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() > nStartPos ) )
1864 pItem = pAttr->GetItem();
1865 // Attribut endet hier, ist nicht leer
1866 else if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() == nStartPos ) )
1867 {
1868 if ( !pNode->GetCharAttribs().FindEmptyAttrib( pAttr->GetItem()->Which(), nStartPos ) )
1869 pItem = pAttr->GetItem();
1870 }
1871 // Attribut endet hier, ist leer
1872 else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() == nStartPos ) )
1873 {
1874 pItem = pAttr->GetItem();
1875 }
1876 // Attribut beginnt hier
1877 else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() > nStartPos ) )
1878 {
1879 if ( nStartPos == 0 ) // Sonderfall
1880 pItem = pAttr->GetItem();
1881 }
1882
1883 if ( pItem )
1884 {
1885 sal_uInt16 nWhich = pItem->Which();
1886 if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
1887 {
1888 rCurSet.Put( *pItem );
1889 }
1890 else if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_ON )
1891 {
1892 const SfxPoolItem& rItem = rCurSet.Get( nWhich );
1893 if ( rItem != *pItem )
1894 {
1895 rCurSet.InvalidateItem( nWhich );
1896 }
1897 }
1898 }
1899 nAttr++;
1900 pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
1901 }
1902 }
1903 else // Selektion
1904 {
1905 while ( pAttr && ( pAttr->GetStart() < nEndPos) )
1906 {
1907 const SfxPoolItem* pItem = 0;
1908 // Attribut liegt dadrueber...
1909 if ( ( pAttr->GetStart() <= nStartPos ) && ( pAttr->GetEnd() >= nEndPos ) )
1910 pItem = pAttr->GetItem();
1911 // Attribut startet mitten drin...
1912 else if ( pAttr->GetStart() >= nStartPos )
1913 {
1914 // !!! pItem = pAttr->GetItem();
1915 // einfach nur pItem reicht nicht, da ich z.B. bei Shadow
1916 // niemals ein ungleiches Item finden wuerde, da ein solche
1917 // seine Anwesenheit durch Abwesenheit repraesentiert!
1918 // if ( ... )
1919 // Es muesste geprueft werden, on genau das gleiche Attribut
1920 // an der Bruchstelle aufsetzt, was recht aufwendig ist.
1921 // Da ich beim Einfuegen von Attributen aber etwas optimiere
1922 // tritt der Fall nicht so schnell auf...
1923 // Also aus Geschwindigkeitsgruenden:
1924 rCurSet.InvalidateItem( pAttr->GetItem()->Which() );
1925
1926 }
1927 // Attribut endet mitten drin...
1928 else if ( pAttr->GetEnd() > nStartPos )
1929 {
1930 // pItem = pAttr->GetItem();
1931 // s.o.
1932 /*-----------------31.05.95 16:01-------------------
1933 Ist falsch, wenn das gleiche Attribut sofort wieder
1934 eingestellt wird!
1935 => Sollte am besten nicht vorkommen, also gleich beim
1936 Setzen von Attributen richtig machen!
1937 --------------------------------------------------*/
1938 rCurSet.InvalidateItem( pAttr->GetItem()->Which() );
1939 }
1940
1941 if ( pItem )
1942 {
1943 sal_uInt16 nWhich = pItem->Which();
1944 if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
1945 {
1946 rCurSet.Put( *pItem );
1947 }
1948 else if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_ON )
1949 {
1950 const SfxPoolItem& rItem = rCurSet.Get( nWhich );
1951 if ( rItem != *pItem )
1952 {
1953 rCurSet.InvalidateItem( nWhich );
1954 }
1955 }
1956 }
1957 nAttr++;
1958 pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
1959 }
1960 }
1961 }
1962
1963
1964 // -------------------------------------------------------------------------
1965 // class EditCharAttribList
1966 // -------------------------------------------------------------------------
1967
CharAttribList()1968 CharAttribList::CharAttribList()
1969 {
1970 DBG_CTOR( EE_CharAttribList, 0 );
1971 bHasEmptyAttribs = sal_False;
1972 }
1973
~CharAttribList()1974 CharAttribList::~CharAttribList()
1975 {
1976 DBG_DTOR( EE_CharAttribList, 0 );
1977
1978 sal_uInt16 nAttr = 0;
1979 EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr );
1980 while ( pAttr )
1981 {
1982 delete pAttr;
1983 ++nAttr;
1984 pAttr = GetAttrib( aAttribs, nAttr );
1985 }
1986 Clear();
1987 }
1988
InsertAttrib(EditCharAttrib * pAttrib)1989 void CharAttribList::InsertAttrib( EditCharAttrib* pAttrib )
1990 {
1991 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1992 // optimieren: binaere Suche ? !
1993 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1994
1995 // MT: 26.11.98
1996 // Vielleicht aber auch einfach nur rueckwaerts iterieren:
1997 // Der haeufigste und kritischste Fall: Attribute kommen bereits
1998 // sortiert an (InsertBinTextObject!)
1999 // Hier waere auch binaere Suche nicht optimal.
2000 // => Wuerde einiges bringen!
2001
2002 const sal_uInt16 nCount = Count();
2003 const sal_uInt16 nStart = pAttrib->GetStart(); // vielleicht besser fuer Comp.Opt.
2004
2005 if ( pAttrib->IsEmpty() )
2006 bHasEmptyAttribs = sal_True;
2007
2008 sal_Bool bInserted = sal_False;
2009 for ( sal_uInt16 x = 0; x < nCount; x++ )
2010 {
2011 EditCharAttribPtr pCurAttrib = aAttribs[x];
2012 if ( pCurAttrib->GetStart() > nStart )
2013 {
2014 aAttribs.Insert( pAttrib, x );
2015 bInserted = sal_True;
2016 break;
2017 }
2018 }
2019 if ( !bInserted )
2020 aAttribs.Insert( pAttrib, nCount );
2021 }
2022
ResortAttribs()2023 void CharAttribList::ResortAttribs()
2024 {
2025 if ( Count() )
2026 {
2027 #if defined __SUNPRO_CC
2028 #pragma disable_warn
2029 #endif
2030 qsort( (void*)aAttribs.GetData(), aAttribs.Count(), sizeof( EditCharAttrib* ), CompareStart );
2031 #if defined __SUNPRO_CC
2032 #pragma enable_warn
2033 #endif
2034 }
2035 }
2036
OptimizeRanges(SfxItemPool & rItemPool)2037 void CharAttribList::OptimizeRanges( SfxItemPool& rItemPool )
2038 {
2039 for ( sal_uInt16 n = 0; n < aAttribs.Count(); n++ )
2040 {
2041 EditCharAttrib* pAttr = aAttribs.GetObject( n );
2042 for ( sal_uInt16 nNext = n+1; nNext < aAttribs.Count(); nNext++ )
2043 {
2044 EditCharAttrib* p = aAttribs.GetObject( nNext );
2045 if ( !pAttr->IsFeature() && ( p->GetStart() == pAttr->GetEnd() ) && ( p->Which() == pAttr->Which() ) )
2046 {
2047 if ( *p->GetItem() == *pAttr->GetItem() )
2048 {
2049 pAttr->GetEnd() = p->GetEnd();
2050 aAttribs.Remove( nNext );
2051 rItemPool.Remove( *p->GetItem() );
2052 delete p;
2053 }
2054 break; // only 1 attr with same which can start here.
2055 }
2056 else if ( p->GetStart() > pAttr->GetEnd() )
2057 {
2058 break;
2059 }
2060 }
2061 }
2062 }
2063
FindAttrib(sal_uInt16 nWhich,sal_uInt16 nPos)2064 EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_uInt16 nPos )
2065 {
2066 // Rueckwaerts, falls eins dort endet, das naechste startet.
2067 // => Das startende gilt...
2068 sal_uInt16 nAttr = aAttribs.Count()-1;
2069 EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr );
2070 while ( pAttr )
2071 {
2072 if ( ( pAttr->Which() == nWhich ) && pAttr->IsIn(nPos) )
2073 return pAttr;
2074 pAttr = GetAttrib( aAttribs, --nAttr );
2075 }
2076 return 0;
2077 }
2078
FindNextAttrib(sal_uInt16 nWhich,sal_uInt16 nFromPos) const2079 EditCharAttrib* CharAttribList::FindNextAttrib( sal_uInt16 nWhich, sal_uInt16 nFromPos ) const
2080 {
2081 DBG_ASSERT( nWhich, "FindNextAttrib: Which?" );
2082 const sal_uInt16 nAttribs = aAttribs.Count();
2083 for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ )
2084 {
2085 EditCharAttrib* pAttr = aAttribs[ nAttr ];
2086 if ( ( pAttr->GetStart() >= nFromPos ) && ( pAttr->Which() == nWhich ) )
2087 return pAttr;
2088 }
2089 return 0;
2090 }
2091
HasAttrib(sal_uInt16 nWhich) const2092 sal_Bool CharAttribList::HasAttrib( sal_uInt16 nWhich ) const
2093 {
2094 for ( sal_uInt16 nAttr = aAttribs.Count(); nAttr; )
2095 {
2096 const EditCharAttrib* pAttr = aAttribs[--nAttr];
2097 if ( pAttr->Which() == nWhich )
2098 return sal_True;
2099 }
2100 return sal_False;
2101 }
2102
HasAttrib(sal_uInt16 nStartPos,sal_uInt16 nEndPos) const2103 sal_Bool CharAttribList::HasAttrib( sal_uInt16 nStartPos, sal_uInt16 nEndPos ) const
2104 {
2105 sal_Bool bAttr = sal_False;
2106 for ( sal_uInt16 nAttr = aAttribs.Count(); nAttr && !bAttr; )
2107 {
2108 const EditCharAttrib* pAttr = aAttribs[--nAttr];
2109 if ( ( pAttr->GetStart() < nEndPos ) && ( pAttr->GetEnd() > nStartPos ) )
2110 return bAttr = sal_True;
2111 }
2112 return bAttr;
2113 }
2114
2115
HasBoundingAttrib(sal_uInt16 nBound)2116 sal_Bool CharAttribList::HasBoundingAttrib( sal_uInt16 nBound )
2117 {
2118 // Rueckwaerts, falls eins dort endet, das naechste startet.
2119 // => Das startende gilt...
2120 sal_uInt16 nAttr = aAttribs.Count()-1;
2121 EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr );
2122 while ( pAttr && ( pAttr->GetEnd() >= nBound ) )
2123 {
2124 if ( ( pAttr->GetStart() == nBound ) || ( pAttr->GetEnd() == nBound ) )
2125 return sal_True;
2126 pAttr = GetAttrib( aAttribs, --nAttr );
2127 }
2128 return sal_False;
2129 }
2130
FindEmptyAttrib(sal_uInt16 nWhich,sal_uInt16 nPos)2131 EditCharAttrib* CharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_uInt16 nPos )
2132 {
2133 if ( !bHasEmptyAttribs )
2134 return 0;
2135 sal_uInt16 nAttr = 0;
2136 EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr );
2137 while ( pAttr && ( pAttr->GetStart() <= nPos ) )
2138 {
2139 if ( ( pAttr->GetStart() == nPos ) && ( pAttr->GetEnd() == nPos ) && ( pAttr->Which() == nWhich ) )
2140 return pAttr;
2141 nAttr++;
2142 pAttr = GetAttrib( aAttribs, nAttr );
2143 }
2144 return 0;
2145 }
2146
FindFeature(sal_uInt16 nPos) const2147 EditCharAttrib* CharAttribList::FindFeature( sal_uInt16 nPos ) const
2148 {
2149
2150 sal_uInt16 nAttr = 0;
2151 EditCharAttrib* pNextAttrib = GetAttrib( aAttribs, nAttr );
2152
2153 // erstmal zur gewuenschten Position...
2154 while ( pNextAttrib && ( pNextAttrib->GetStart() < nPos ) )
2155 {
2156 nAttr++;
2157 pNextAttrib = GetAttrib( aAttribs, nAttr );
2158 }
2159
2160 // jetzt das Feature suchen...
2161 while ( pNextAttrib && !pNextAttrib->IsFeature() )
2162 {
2163 nAttr++;
2164 pNextAttrib = GetAttrib( aAttribs, nAttr );
2165 }
2166
2167 return pNextAttrib;
2168 }
2169
2170
DeleteEmptyAttribs(SfxItemPool & rItemPool)2171 void CharAttribList::DeleteEmptyAttribs( SfxItemPool& rItemPool )
2172 {
2173 for ( sal_uInt16 nAttr = 0; nAttr < aAttribs.Count(); nAttr++ )
2174 {
2175 EditCharAttrib* pAttr = aAttribs[nAttr];
2176 if ( pAttr->IsEmpty() )
2177 {
2178 rItemPool.Remove( *pAttr->GetItem() );
2179 aAttribs.Remove( nAttr );
2180 delete pAttr;
2181 nAttr--;
2182 }
2183 }
2184 bHasEmptyAttribs = sal_False;
2185 }
2186
DbgCheckAttribs()2187 sal_Bool CharAttribList::DbgCheckAttribs()
2188 {
2189 #ifdef DBG_UTIL
2190 sal_Bool bOK = sal_True;
2191 for ( sal_uInt16 nAttr = 0; nAttr < aAttribs.Count(); nAttr++ )
2192 {
2193 EditCharAttrib* pAttr = aAttribs[nAttr];
2194 if ( pAttr->GetStart() > pAttr->GetEnd() )
2195 {
2196 bOK = sal_False;
2197 DBG_ERROR( "Attr verdreht" );
2198 }
2199 else if ( pAttr->IsFeature() && ( pAttr->GetLen() != 1 ) )
2200 {
2201 bOK = sal_False;
2202 DBG_ERROR( "Feature, Len != 1" );
2203 }
2204 }
2205 return bOK;
2206 #else
2207 return sal_True;
2208 #endif
2209 }
2210
2211
2212
SvxFontTable()2213 SvxFontTable::SvxFontTable()
2214 {
2215 }
2216
~SvxFontTable()2217 SvxFontTable::~SvxFontTable()
2218 {
2219 SvxFontItem* pItem = First();
2220 while( pItem )
2221 {
2222 delete pItem;
2223 pItem = Next();
2224 }
2225 }
2226
GetId(const SvxFontItem & rFontItem)2227 sal_uLong SvxFontTable::GetId( const SvxFontItem& rFontItem )
2228 {
2229 SvxFontItem* pItem = First();
2230 while ( pItem )
2231 {
2232 if ( *pItem == rFontItem )
2233 return GetCurKey();
2234 pItem = Next();
2235 }
2236 DBG_WARNING( "Font nicht gefunden: GetId()" );
2237 return 0;
2238 }
2239
SvxColorList()2240 SvxColorList::SvxColorList()
2241 {
2242 }
2243
~SvxColorList()2244 SvxColorList::~SvxColorList()
2245 {
2246 SvxColorItem* pItem = First();
2247 while( pItem )
2248 {
2249 delete pItem;
2250 pItem = Next();
2251 }
2252 }
2253
GetId(const SvxColorItem & rColorItem)2254 sal_uLong SvxColorList::GetId( const SvxColorItem& rColorItem )
2255 {
2256 SvxColorItem* pItem = First();
2257 while ( pItem )
2258 {
2259 if ( *pItem == rColorItem )
2260 return GetCurPos();
2261 pItem = Next();
2262 }
2263 DBG_WARNING( "Color nicht gefunden: GetId()" );
2264 return 0;
2265 }
2266
EditEngineItemPool(sal_Bool bPersistenRefCounts)2267 EditEngineItemPool::EditEngineItemPool( sal_Bool bPersistenRefCounts )
2268 : SfxItemPool( String( "EditEngineItemPool", RTL_TEXTENCODING_ASCII_US ), EE_ITEMS_START, EE_ITEMS_END,
2269 aItemInfos, 0, bPersistenRefCounts )
2270 {
2271 SetVersionMap( 1, 3999, 4015, aV1Map );
2272 SetVersionMap( 2, 3999, 4019, aV2Map );
2273 SetVersionMap( 3, 3997, 4020, aV3Map );
2274 SetVersionMap( 4, 3994, 4022, aV4Map );
2275 SetVersionMap( 5, 3994, 4037, aV5Map );
2276
2277 DBG_ASSERT( EE_DLL(), "EditDLL?!" );
2278 SfxPoolItem** ppDefItems = EE_DLL()->GetGlobalData()->GetDefItems();
2279 SetDefaults( ppDefItems );
2280 }
2281
~EditEngineItemPool()2282 EditEngineItemPool::~EditEngineItemPool()
2283 {
2284 }
2285
Store(SvStream & rStream) const2286 SvStream& EditEngineItemPool::Store( SvStream& rStream ) const
2287 {
2288 // Bei einem 3.1-Export muess ein Hack eingebaut werden, da BUG im
2289 // SfxItemSet::Load, aber nicht nachtraeglich in 3.1 fixbar.
2290
2291 // Der eingestellte Range muss nach Store erhalten bleiben, weil dann
2292 // erst die ItemSets gespeichert werden...
2293
2294 long nVersion = rStream.GetVersion();
2295 sal_Bool b31Format = ( nVersion && ( nVersion <= SOFFICE_FILEFORMAT_31 ) )
2296 ? sal_True : sal_False;
2297
2298 EditEngineItemPool* pThis = (EditEngineItemPool*)this;
2299 if ( b31Format )
2300 pThis->SetStoringRange( 3997, 4022 );
2301 else
2302 pThis->SetStoringRange( EE_ITEMS_START, EE_ITEMS_END );
2303
2304 return SfxItemPool::Store( rStream );
2305 }
2306