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