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