Update ooo320-m1
[ooovba.git] / svx / source / editeng / editdoc.cxx
blob7160a4197a870278085b1dd05d971fc8a37155f9
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: editdoc.cxx,v $
10 * $Revision: 1.48.148.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include <eeng_pch.hxx>
36 #include <svx/tstpitem.hxx>
37 #include <svx/colritem.hxx>
38 #include <fontitem.hxx>
39 #include <svx/crsditem.hxx>
40 #include <svx/fhgtitem.hxx>
41 #include <svx/postitem.hxx>
42 #include <svx/kernitem.hxx>
43 #include <svx/wrlmitem.hxx>
44 #include <svx/wghtitem.hxx>
45 #include <svx/udlnitem.hxx>
46 #include <svx/cntritem.hxx>
47 #include <svx/escpitem.hxx>
48 #include <svx/shdditem.hxx>
49 #include <svx/akrnitem.hxx>
50 #include <svx/cscoitem.hxx>
51 #include <svx/langitem.hxx>
52 #include <svx/emphitem.hxx>
53 #include <svx/charscaleitem.hxx>
54 #include <svx/charreliefitem.hxx>
55 #include <xmlcnitm.hxx>
57 #include <editdoc.hxx>
58 #include <editdbg.hxx>
59 #include <eerdll.hxx>
60 #include <eerdll2.hxx>
61 #include <tools/stream.hxx>
63 #include <tools/debug.hxx>
64 #include <tools/shl.hxx>
65 #include <vcl/svapp.hxx>
67 #ifndef _COM_SUN_STAR_TEXT_SCRIPTTYPE_HPP_
68 #include <com/sun/star/i18n/ScriptType.hpp>
69 #endif
71 #include <stdlib.h> // qsort
73 using namespace ::com::sun::star;
76 // ------------------------------------------------------------
78 USHORT GetScriptItemId( USHORT nItemId, short nScriptType )
80 USHORT nId = nItemId;
82 if ( ( nScriptType == i18n::ScriptType::ASIAN ) ||
83 ( nScriptType == i18n::ScriptType::COMPLEX ) )
85 switch ( nItemId )
87 case EE_CHAR_LANGUAGE:
88 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_LANGUAGE_CJK : EE_CHAR_LANGUAGE_CTL;
89 break;
90 case EE_CHAR_FONTINFO:
91 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_FONTINFO_CJK : EE_CHAR_FONTINFO_CTL;
92 break;
93 case EE_CHAR_FONTHEIGHT:
94 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_FONTHEIGHT_CJK : EE_CHAR_FONTHEIGHT_CTL;
95 break;
96 case EE_CHAR_WEIGHT:
97 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_WEIGHT_CJK : EE_CHAR_WEIGHT_CTL;
98 break;
99 case EE_CHAR_ITALIC:
100 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_ITALIC_CJK : EE_CHAR_ITALIC_CTL;
101 break;
105 return nId;
108 BOOL IsScriptItemValid( USHORT nItemId, short nScriptType )
110 BOOL bValid = TRUE;
112 switch ( nItemId )
114 case EE_CHAR_LANGUAGE:
115 bValid = nScriptType == i18n::ScriptType::LATIN;
116 break;
117 case EE_CHAR_LANGUAGE_CJK:
118 bValid = nScriptType == i18n::ScriptType::ASIAN;
119 break;
120 case EE_CHAR_LANGUAGE_CTL:
121 bValid = nScriptType == i18n::ScriptType::COMPLEX;
122 break;
123 case EE_CHAR_FONTINFO:
124 bValid = nScriptType == i18n::ScriptType::LATIN;
125 break;
126 case EE_CHAR_FONTINFO_CJK:
127 bValid = nScriptType == i18n::ScriptType::ASIAN;
128 break;
129 case EE_CHAR_FONTINFO_CTL:
130 bValid = nScriptType == i18n::ScriptType::COMPLEX;
131 break;
132 case EE_CHAR_FONTHEIGHT:
133 bValid = nScriptType == i18n::ScriptType::LATIN;
134 break;
135 case EE_CHAR_FONTHEIGHT_CJK:
136 bValid = nScriptType == i18n::ScriptType::ASIAN;
137 break;
138 case EE_CHAR_FONTHEIGHT_CTL:
139 bValid = nScriptType == i18n::ScriptType::COMPLEX;
140 break;
141 case EE_CHAR_WEIGHT:
142 bValid = nScriptType == i18n::ScriptType::LATIN;
143 break;
144 case EE_CHAR_WEIGHT_CJK:
145 bValid = nScriptType == i18n::ScriptType::ASIAN;
146 break;
147 case EE_CHAR_WEIGHT_CTL:
148 bValid = nScriptType == i18n::ScriptType::COMPLEX;
149 break;
150 case EE_CHAR_ITALIC:
151 bValid = nScriptType == i18n::ScriptType::LATIN;
152 break;
153 case EE_CHAR_ITALIC_CJK:
154 bValid = nScriptType == i18n::ScriptType::ASIAN;
155 break;
156 case EE_CHAR_ITALIC_CTL:
157 bValid = nScriptType == i18n::ScriptType::COMPLEX;
158 break;
161 return bValid;
165 // ------------------------------------------------------------
167 // Sollte spaeter zentral nach TOOLS/STRING (Aktuell: 303)
168 // fuer Grep: WS_TARGET
170 DBG_NAME( EE_TextPortion );
171 DBG_NAME( EE_EditLine );
172 DBG_NAME( EE_ContentNode );
173 DBG_NAME( EE_CharAttribList );
175 SfxItemInfo aItemInfos[EDITITEMCOUNT] = {
176 { SID_ATTR_FRAMEDIRECTION, SFX_ITEM_POOLABLE }, // EE_PARA_WRITINGDIR
177 { 0, SFX_ITEM_POOLABLE }, // EE_PARA_XMLATTRIBS
178 { SID_ATTR_PARA_HANGPUNCTUATION, SFX_ITEM_POOLABLE }, // EE_PARA_HANGINGPUNCTUATION
179 { SID_ATTR_PARA_FORBIDDEN_RULES, SFX_ITEM_POOLABLE },
180 { SID_ATTR_PARA_SCRIPTSPACE, SFX_ITEM_POOLABLE }, // EE_PARA_ASIANCJKSPACING
181 { SID_ATTR_NUMBERING_RULE, SFX_ITEM_POOLABLE }, // EE_PARA_NUMBULL
182 { 0, SFX_ITEM_POOLABLE }, // EE_PARA_HYPHENATE
183 { 0, SFX_ITEM_POOLABLE }, // EE_PARA_BULLETSTATE
184 { 0, SFX_ITEM_POOLABLE }, // EE_PARA_OUTLLRSPACE
185 { SID_ATTR_PARA_OUTLLEVEL, SFX_ITEM_POOLABLE },
186 { SID_ATTR_PARA_BULLET, SFX_ITEM_POOLABLE },
187 { SID_ATTR_LRSPACE, SFX_ITEM_POOLABLE },
188 { SID_ATTR_ULSPACE, SFX_ITEM_POOLABLE },
189 { SID_ATTR_PARA_LINESPACE, SFX_ITEM_POOLABLE },
190 { SID_ATTR_PARA_ADJUST, SFX_ITEM_POOLABLE },
191 { SID_ATTR_TABSTOP, SFX_ITEM_POOLABLE },
192 { SID_ATTR_CHAR_COLOR, SFX_ITEM_POOLABLE },
193 { SID_ATTR_CHAR_FONT, SFX_ITEM_POOLABLE },
194 { SID_ATTR_CHAR_FONTHEIGHT, SFX_ITEM_POOLABLE },
195 { SID_ATTR_CHAR_SCALEWIDTH, SFX_ITEM_POOLABLE },
196 { SID_ATTR_CHAR_WEIGHT, SFX_ITEM_POOLABLE },
197 { SID_ATTR_CHAR_UNDERLINE, SFX_ITEM_POOLABLE },
198 { SID_ATTR_CHAR_STRIKEOUT, SFX_ITEM_POOLABLE },
199 { SID_ATTR_CHAR_POSTURE, SFX_ITEM_POOLABLE },
200 { SID_ATTR_CHAR_CONTOUR, SFX_ITEM_POOLABLE },
201 { SID_ATTR_CHAR_SHADOWED, SFX_ITEM_POOLABLE },
202 { SID_ATTR_CHAR_ESCAPEMENT, SFX_ITEM_POOLABLE },
203 { SID_ATTR_CHAR_AUTOKERN, SFX_ITEM_POOLABLE },
204 { SID_ATTR_CHAR_KERNING, SFX_ITEM_POOLABLE },
205 { SID_ATTR_CHAR_WORDLINEMODE, SFX_ITEM_POOLABLE },
206 { SID_ATTR_CHAR_LANGUAGE, SFX_ITEM_POOLABLE },
207 { SID_ATTR_CHAR_CJK_LANGUAGE, SFX_ITEM_POOLABLE },
208 { SID_ATTR_CHAR_CTL_LANGUAGE, SFX_ITEM_POOLABLE },
209 { SID_ATTR_CHAR_CJK_FONT, SFX_ITEM_POOLABLE },
210 { SID_ATTR_CHAR_CTL_FONT, SFX_ITEM_POOLABLE },
211 { SID_ATTR_CHAR_CJK_FONTHEIGHT, SFX_ITEM_POOLABLE },
212 { SID_ATTR_CHAR_CTL_FONTHEIGHT, SFX_ITEM_POOLABLE },
213 { SID_ATTR_CHAR_CJK_WEIGHT, SFX_ITEM_POOLABLE },
214 { SID_ATTR_CHAR_CTL_WEIGHT, SFX_ITEM_POOLABLE },
215 { SID_ATTR_CHAR_CJK_POSTURE, SFX_ITEM_POOLABLE },
216 { SID_ATTR_CHAR_CTL_POSTURE, SFX_ITEM_POOLABLE },
217 { SID_ATTR_CHAR_EMPHASISMARK, SFX_ITEM_POOLABLE },
218 { SID_ATTR_CHAR_RELIEF, SFX_ITEM_POOLABLE },
219 { 0, SFX_ITEM_POOLABLE }, // EE_CHAR_RUBI_DUMMY
220 { 0, SFX_ITEM_POOLABLE }, // EE_CHAR_XMLATTRIBS
221 { SID_ATTR_CHAR_OVERLINE, SFX_ITEM_POOLABLE },
222 { 0, SFX_ITEM_POOLABLE }, // EE_FEATURE_TAB
223 { 0, SFX_ITEM_POOLABLE }, // EE_FEATURE_LINEBR
224 { SID_ATTR_CHAR_CHARSETCOLOR, SFX_ITEM_POOLABLE }, // EE_FEATURE_NOTCONV
225 { SID_FIELD, SFX_ITEM_POOLABLE }
228 USHORT aV1Map[] = {
229 3999, 4001, 4002, 4003, 4004, 4005, 4006,
230 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4017, 4018, 4019 // MI: 4019?
233 USHORT aV2Map[] = {
234 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009,
235 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4018, 4019, 4020
238 USHORT aV3Map[] = {
239 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007,
240 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019,
241 4020, 4021
244 USHORT aV4Map[] = {
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,
248 /* CJK Items inserted here: EE_CHAR_LANGUAGE - EE_CHAR_XMLATTRIBS */
249 4034, 4035, 4036, 4037
252 USHORT aV5Map[] = {
253 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003,
254 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013,
255 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023,
256 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033,
257 /* EE_CHAR_OVERLINE inserted here */
258 4035, 4036, 4037, 4038
261 SV_IMPL_PTRARR( DummyContentList, ContentNode* );
262 SV_IMPL_VARARR( ScriptTypePosInfos, ScriptTypePosInfo );
263 SV_IMPL_VARARR( WritingDirectionInfos, WritingDirectionInfo );
264 // SV_IMPL_VARARR( ExtraCharInfos, ExtraCharInfo );
267 int SAL_CALL CompareStart( const void* pFirst, const void* pSecond )
269 if ( (*((EditCharAttrib**)pFirst))->GetStart() < (*((EditCharAttrib**)pSecond))->GetStart() )
270 return (-1);
271 else if ( (*((EditCharAttrib**)pFirst))->GetStart() > (*((EditCharAttrib**)pSecond))->GetStart() )
272 return (1);
273 return 0;
276 EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, USHORT nS, USHORT nE )
278 // das neue Attribut im Pool anlegen
279 const SfxPoolItem& rNew = rPool.Put( rAttr );
281 EditCharAttrib* pNew = 0;
282 switch( rNew.Which() )
284 case EE_CHAR_LANGUAGE:
285 case EE_CHAR_LANGUAGE_CJK:
286 case EE_CHAR_LANGUAGE_CTL:
288 pNew = new EditCharAttribLanguage( (const SvxLanguageItem&)rNew, nS, nE );
290 break;
291 case EE_CHAR_COLOR:
293 pNew = new EditCharAttribColor( (const SvxColorItem&)rNew, nS, nE );
295 break;
296 case EE_CHAR_FONTINFO:
297 case EE_CHAR_FONTINFO_CJK:
298 case EE_CHAR_FONTINFO_CTL:
300 pNew = new EditCharAttribFont( (const SvxFontItem&)rNew, nS, nE );
302 break;
303 case EE_CHAR_FONTHEIGHT:
304 case EE_CHAR_FONTHEIGHT_CJK:
305 case EE_CHAR_FONTHEIGHT_CTL:
307 pNew = new EditCharAttribFontHeight( (const SvxFontHeightItem&)rNew, nS, nE );
309 break;
310 case EE_CHAR_FONTWIDTH:
312 pNew = new EditCharAttribFontWidth( (const SvxCharScaleWidthItem&)rNew, nS, nE );
314 break;
315 case EE_CHAR_WEIGHT:
316 case EE_CHAR_WEIGHT_CJK:
317 case EE_CHAR_WEIGHT_CTL:
319 pNew = new EditCharAttribWeight( (const SvxWeightItem&)rNew, nS, nE );
321 break;
322 case EE_CHAR_UNDERLINE:
324 pNew = new EditCharAttribUnderline( (const SvxUnderlineItem&)rNew, nS, nE );
326 break;
327 case EE_CHAR_OVERLINE:
329 pNew = new EditCharAttribOverline( (const SvxOverlineItem&)rNew, nS, nE );
331 break;
332 case EE_CHAR_EMPHASISMARK:
334 pNew = new EditCharAttribEmphasisMark( (const SvxEmphasisMarkItem&)rNew, nS, nE );
336 break;
337 case EE_CHAR_RELIEF:
339 pNew = new EditCharAttribRelief( (const SvxCharReliefItem&)rNew, nS, nE );
341 break;
342 case EE_CHAR_STRIKEOUT:
344 pNew = new EditCharAttribStrikeout( (const SvxCrossedOutItem&)rNew, nS, nE );
346 break;
347 case EE_CHAR_ITALIC:
348 case EE_CHAR_ITALIC_CJK:
349 case EE_CHAR_ITALIC_CTL:
351 pNew = new EditCharAttribItalic( (const SvxPostureItem&)rNew, nS, nE );
353 break;
354 case EE_CHAR_OUTLINE:
356 pNew = new EditCharAttribOutline( (const SvxContourItem&)rNew, nS, nE );
358 break;
359 case EE_CHAR_SHADOW:
361 pNew = new EditCharAttribShadow( (const SvxShadowedItem&)rNew, nS, nE );
363 break;
364 case EE_CHAR_ESCAPEMENT:
366 pNew = new EditCharAttribEscapement( (const SvxEscapementItem&)rNew, nS, nE );
368 break;
369 case EE_CHAR_PAIRKERNING:
371 pNew = new EditCharAttribPairKerning( (const SvxAutoKernItem&)rNew, nS, nE );
373 break;
374 case EE_CHAR_KERNING:
376 pNew = new EditCharAttribKerning( (const SvxKerningItem&)rNew, nS, nE );
378 break;
379 case EE_CHAR_WLM:
381 pNew = new EditCharAttribWordLineMode( (const SvxWordLineModeItem&)rNew, nS, nE );
383 break;
384 case EE_CHAR_XMLATTRIBS:
386 pNew = new EditCharAttrib( rNew, nS, nE ); // Attrib is only for holding XML information...
388 break;
389 case EE_FEATURE_TAB:
391 pNew = new EditCharAttribTab( (const SfxVoidItem&)rNew, nS );
393 break;
394 case EE_FEATURE_LINEBR:
396 pNew = new EditCharAttribLineBreak( (const SfxVoidItem&)rNew, nS );
398 break;
399 case EE_FEATURE_FIELD:
401 pNew = new EditCharAttribField( (const SvxFieldItem&)rNew, nS );
403 break;
404 default:
406 DBG_ERROR( "Ungueltiges Attribut!" );
409 return pNew;
412 // -------------------------------------------------------------------------
413 // class EditLine
414 // -------------------------------------------------------------------------
416 EditLine::EditLine()
418 DBG_CTOR( EE_EditLine, 0 );
420 nStart = nEnd = 0;
421 nStartPortion = 0; // damit in ungueltiger Zeile ohne Portions von einer gueltigen Zeile mit der Portion Nr0 unterscieden werden kann.
422 nEndPortion = 0;
423 nHeight = 0;
424 nStartPosX = 0;
425 nTxtHeight = 0;
426 nTxtWidth = 0;
427 nCrsrHeight = 0;
428 nMaxAscent = 0;
429 bHangingPunctuation = FALSE;
430 bInvalid = TRUE;
433 EditLine::EditLine( const EditLine& r )
435 DBG_CTOR( EE_EditLine, 0 );
437 nEnd = r.nEnd;
438 nStart = r.nStart;
439 nStartPortion = r.nStartPortion;
440 nEndPortion = r.nEndPortion;
441 bHangingPunctuation = r.bHangingPunctuation;
443 nHeight = 0;
444 nStartPosX = 0;
445 nTxtHeight = 0;
446 nTxtWidth = 0;
447 nCrsrHeight = 0;
448 nMaxAscent = 0;
449 bInvalid = TRUE;
452 EditLine::~EditLine()
454 DBG_DTOR( EE_EditLine, 0 );
457 EditLine* EditLine::Clone() const
459 EditLine* pL = new EditLine;
460 if ( aPositions.Count() )
462 pL->aPositions.Insert (aPositions.GetData(), aPositions.Count(), 0);
464 pL->nStartPosX = nStartPosX;
465 pL->nStart = nStart;
466 pL->nEnd = nEnd;
467 pL->nStartPortion = nStartPortion;
468 pL->nEndPortion = nEndPortion;
469 pL->nHeight = nHeight;
470 pL->nTxtWidth = nTxtWidth;
471 pL->nTxtHeight = nTxtHeight;
472 pL->nCrsrHeight = nCrsrHeight;
473 pL->nMaxAscent = nMaxAscent;
475 return pL;
478 BOOL operator == ( const EditLine& r1, const EditLine& r2 )
480 if ( r1.nStart != r2.nStart )
481 return FALSE;
483 if ( r1.nEnd != r2.nEnd )
484 return FALSE;
486 if ( r1.nStartPortion != r2.nStartPortion )
487 return FALSE;
489 if ( r1.nEndPortion != r2.nEndPortion )
490 return FALSE;
492 return TRUE;
495 EditLine& EditLine::operator = ( const EditLine& r )
497 nEnd = r.nEnd;
498 nStart = r.nStart;
499 nEndPortion = r.nEndPortion;
500 nStartPortion = r.nStartPortion;
501 return *this;
505 BOOL operator != ( const EditLine& r1, const EditLine& r2 )
507 return !( r1 == r2 );
510 Size EditLine::CalcTextSize( ParaPortion& rParaPortion )
512 Size aSz;
513 Size aTmpSz;
514 TextPortion* pPortion;
516 USHORT nIndex = GetStart();
518 DBG_ASSERT( rParaPortion.GetTextPortions().Count(), "GetTextSize vor CreatePortions !" );
520 for ( USHORT n = nStartPortion; n <= nEndPortion; n++ )
522 pPortion = rParaPortion.GetTextPortions().GetObject(n);
523 switch ( pPortion->GetKind() )
525 case PORTIONKIND_TEXT:
526 case PORTIONKIND_FIELD:
527 case PORTIONKIND_HYPHENATOR:
529 aTmpSz = pPortion->GetSize();
530 aSz.Width() += aTmpSz.Width();
531 if ( aSz.Height() < aTmpSz.Height() )
532 aSz.Height() = aTmpSz.Height();
534 break;
535 case PORTIONKIND_TAB:
536 // case PORTIONKIND_EXTRASPACE:
538 aSz.Width() += pPortion->GetSize().Width();
540 break;
542 nIndex = nIndex + pPortion->GetLen();
545 SetHeight( (USHORT)aSz.Height() );
546 return aSz;
549 \f// -------------------------------------------------------------------------
550 // class EditLineList
551 // -------------------------------------------------------------------------
552 EditLineList::EditLineList()
556 EditLineList::~EditLineList()
558 Reset();
561 void EditLineList::Reset()
563 for ( USHORT nLine = 0; nLine < Count(); nLine++ )
564 delete GetObject(nLine);
565 Remove( 0, Count() );
568 void EditLineList::DeleteFromLine( USHORT nDelFrom )
570 DBG_ASSERT( nDelFrom <= (Count() - 1), "DeleteFromLine: Out of range" );
571 for ( USHORT nL = nDelFrom; nL < Count(); nL++ )
572 delete GetObject(nL);
573 Remove( nDelFrom, Count()-nDelFrom );
576 USHORT EditLineList::FindLine( USHORT nChar, BOOL bInclEnd )
578 for ( USHORT nLine = 0; nLine < Count(); nLine++ )
580 EditLine* pLine = GetObject( nLine );
581 if ( ( bInclEnd && ( pLine->GetEnd() >= nChar ) ) ||
582 ( pLine->GetEnd() > nChar ) )
584 return nLine;
588 DBG_ASSERT( !bInclEnd, "Zeile nicht gefunden: FindLine" );
589 return ( Count() - 1 );
592 \f// -------------------------------------------------------------------------
593 // class EditSelection
594 // -------------------------------------------------------------------------
595 BOOL EditPaM::DbgIsBuggy( EditDoc& rDoc )
597 if ( !pNode )
598 return TRUE;
599 if ( rDoc.GetPos( pNode ) >= rDoc.Count() )
600 return TRUE;
601 if ( nIndex > pNode->Len() )
602 return TRUE;
604 return FALSE;
607 BOOL EditSelection::DbgIsBuggy( EditDoc& rDoc )
609 if ( aStartPaM.DbgIsBuggy( rDoc ) )
610 return TRUE;
611 if ( aEndPaM.DbgIsBuggy( rDoc ) )
612 return TRUE;
614 return FALSE;
617 EditSelection::EditSelection()
621 EditSelection::EditSelection( const EditPaM& rStartAndAnd )
623 // koennte noch optimiert werden!
624 // nicht erst Def-CTOR vom PaM rufen!
625 aStartPaM = rStartAndAnd;
626 aEndPaM = rStartAndAnd;
629 EditSelection::EditSelection( const EditPaM& rStart, const EditPaM& rEnd )
631 // koennte noch optimiert werden!
632 aStartPaM = rStart;
633 aEndPaM = rEnd;
636 EditSelection& EditSelection::operator = ( const EditPaM& rPaM )
638 aStartPaM = rPaM;
639 aEndPaM = rPaM;
640 return *this;
643 BOOL EditSelection::IsInvalid() const
645 EditPaM aEmptyPaM;
647 if ( aStartPaM == aEmptyPaM )
648 return TRUE;
650 if ( aEndPaM == aEmptyPaM )
651 return TRUE;
653 return FALSE;
656 BOOL EditSelection::Adjust( const ContentList& rNodes )
658 DBG_ASSERT( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index im Wald in Adjust(1)" );
659 DBG_ASSERT( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index im Wald in Adjust(2)" );
661 ContentNode* pStartNode = aStartPaM.GetNode();
662 ContentNode* pEndNode = aEndPaM.GetNode();
664 USHORT nStartNode = rNodes.GetPos( pStartNode );
665 USHORT nEndNode = rNodes.GetPos( pEndNode );
667 DBG_ASSERT( nStartNode != USHRT_MAX, "Node im Wald in Adjust(1)" );
668 DBG_ASSERT( nEndNode != USHRT_MAX, "Node im Wald in Adjust(2)" );
670 BOOL bSwap = FALSE;
671 if ( nStartNode > nEndNode )
672 bSwap = TRUE;
673 else if ( ( nStartNode == nEndNode ) && ( aStartPaM.GetIndex() > aEndPaM.GetIndex() ) )
674 bSwap = TRUE;
676 if ( bSwap )
678 EditPaM aTmpPaM( aStartPaM );
679 aStartPaM = aEndPaM;
680 aEndPaM = aTmpPaM;
683 return bSwap;
687 \f// -------------------------------------------------------------------------
688 // class EditPaM
689 // -------------------------------------------------------------------------
690 BOOL operator == ( const EditPaM& r1, const EditPaM& r2 )
692 if ( r1.GetNode() != r2.GetNode() )
693 return FALSE;
695 if ( r1.GetIndex() != r2.GetIndex() )
696 return FALSE;
698 return TRUE;
701 EditPaM& EditPaM::operator = ( const EditPaM& rPaM )
703 nIndex = rPaM.nIndex;
704 pNode = rPaM.pNode;
705 return *this;
708 BOOL operator != ( const EditPaM& r1, const EditPaM& r2 )
710 return !( r1 == r2 );
714 \f// -------------------------------------------------------------------------
715 // class ContentNode
716 // -------------------------------------------------------------------------
717 ContentNode::ContentNode( SfxItemPool& rPool ) : aContentAttribs( rPool )
719 DBG_CTOR( EE_ContentNode, 0 );
720 pWrongList = NULL;
723 ContentNode::ContentNode( const XubString& rStr, const ContentAttribs& rContentAttribs ) :
724 XubString( rStr ), aContentAttribs( rContentAttribs )
726 DBG_CTOR( EE_ContentNode, 0 );
727 pWrongList = NULL;
730 ContentNode::~ContentNode()
732 DBG_DTOR( EE_ContentNode, 0 );
733 #ifndef SVX_LIGHT
734 delete pWrongList;
735 #endif
738 void ContentNode::ExpandAttribs( USHORT nIndex, USHORT nNew, SfxItemPool& rItemPool )
740 if ( !nNew )
741 return;
743 // Da Features anders behandelt werden als normale Zeichenattribute,
744 // kann sich hier auch die Sortierung der Start-Liste aendern!
745 // In jedem if..., in dem weiter (n) Moeglichkeiten aufgrund von
746 // bFeature oder Spezialfall existieren,
747 // muessen (n-1) Moeglichkeiten mit bResort versehen werden.
748 // Die wahrscheinlichste Moeglichkeit erhaelt kein bResort,
749 // so dass nicht neu sortiert wird, wenn sich alle Attribute
750 // gleich verhalten.
751 BOOL bResort = FALSE;
752 BOOL bExpandedEmptyAtIndexNull = FALSE;
754 USHORT nAttr = 0;
755 EditCharAttrib* pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr );
756 while ( pAttrib )
758 if ( pAttrib->GetEnd() >= nIndex )
760 // Alle Attribute hinter der Einfuegeposition verschieben...
761 if ( pAttrib->GetStart() > nIndex )
763 pAttrib->MoveForward( nNew );
765 // 0: Leeres Attribut expandieren, wenn an Einfuegestelle
766 else if ( pAttrib->IsEmpty() )
768 // Index nicht pruefen, leeres durfte nur dort liegen.
769 // Wenn spaeter doch Ueberpruefung:
770 // Spezialfall: Start == 0; AbsLen == 1, nNew = 1 => Expand, weil durch Absatzumbruch!
771 // Start <= nIndex, End >= nIndex => Start=End=nIndex!
772 // if ( pAttrib->GetStart() == nIndex )
773 pAttrib->Expand( nNew );
774 if ( pAttrib->GetStart() == 0 )
775 bExpandedEmptyAtIndexNull = TRUE;
777 // 1: Attribut startet davor, geht bis Index...
778 else if ( pAttrib->GetEnd() == nIndex ) // Start muss davor liegen
780 // Nur expandieren, wenn kein Feature,
781 // und wenn nicht in ExcludeListe!
782 // Sonst geht z.B. ein UL bis zum neuen ULDB, beide expandieren
783 // if ( !pAttrib->IsFeature() && !rExclList.FindAttrib( pAttrib->Which() ) )
784 if ( !pAttrib->IsFeature() && !aCharAttribList.FindEmptyAttrib( pAttrib->Which(), nIndex ) )
786 if ( !pAttrib->IsEdge() )
787 pAttrib->Expand( nNew );
789 else
790 bResort = TRUE;
792 // 2: Attribut startet davor, geht hinter Index...
793 else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) )
795 DBG_ASSERT( !pAttrib->IsFeature(), "Grosses Feature?!" );
796 pAttrib->Expand( nNew );
798 // 3: Attribut startet auf Index...
799 else if ( pAttrib->GetStart() == nIndex )
801 if ( pAttrib->IsFeature() )
803 pAttrib->MoveForward( nNew );
804 bResort = TRUE;
806 else
808 BOOL bExpand = FALSE;
809 if ( nIndex == 0 )
811 bExpand = TRUE;
812 if( bExpandedEmptyAtIndexNull )
814 // Check if this kind of attribut was empty and expanded here...
815 USHORT nW = pAttrib->GetItem()->Which();
816 for ( USHORT nA = 0; nA < nAttr; nA++ )
818 EditCharAttrib* pA = aCharAttribList.GetAttribs()[nA];
819 if ( ( pA->GetStart() == 0 ) && ( pA->GetItem()->Which() == nW ) )
821 bExpand = FALSE;
822 break;
828 if ( bExpand )
830 pAttrib->Expand( nNew );
831 bResort = TRUE;
833 else
835 pAttrib->MoveForward( nNew );
841 if ( pAttrib->IsEdge() )
842 pAttrib->SetEdge( FALSE );
844 DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" );
846 DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribut verdreht!" );
847 DBG_ASSERT( ( pAttrib->GetEnd() <= Len() ), "Expand: Attrib groesser als Absatz!" );
848 if ( pAttrib->IsEmpty() )
850 DBG_ERROR( "Leeres Attribut nach ExpandAttribs?" );
851 bResort = TRUE;
852 aCharAttribList.GetAttribs().Remove( nAttr );
853 rItemPool.Remove( *pAttrib->GetItem() );
854 delete pAttrib;
855 nAttr--;
857 nAttr++;
858 pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr );
861 if ( bResort )
862 aCharAttribList.ResortAttribs();
864 #ifndef SVX_LIGHT
865 if ( pWrongList )
867 BOOL bSep = ( GetChar( nIndex ) == ' ' ) || IsFeature( nIndex );
868 pWrongList->TextInserted( nIndex, nNew, bSep );
870 #endif // !SVX_LIGHT
872 #ifdef EDITDEBUG
873 DBG_ASSERT( CheckOrderedList( aCharAttribList.GetAttribs(), TRUE ), "Expand: Start-Liste verdreht" );
874 #endif
877 void ContentNode::CollapsAttribs( USHORT nIndex, USHORT nDeleted, SfxItemPool& rItemPool )
879 if ( !nDeleted )
880 return;
882 // Da Features anders behandelt werden als normale Zeichenattribute,
883 // kann sich hier auch die Sortierung der Start-Liste aendern!
884 BOOL bResort = FALSE;
885 BOOL bDelAttr = FALSE;
886 USHORT nEndChanges = nIndex+nDeleted;
888 USHORT nAttr = 0;
889 EditCharAttrib* pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr );
890 while ( pAttrib )
892 bDelAttr = FALSE;
893 if ( pAttrib->GetEnd() >= nIndex )
895 // Alles Attribute hinter der Einfuegeposition verschieben...
896 if ( pAttrib->GetStart() >= nEndChanges )
898 pAttrib->MoveBackward( nDeleted );
900 // 1. Innenliegende Attribute loeschen...
901 else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() <= nEndChanges ) )
903 // Spezialfall: Attrubt deckt genau den Bereich ab
904 // => als leeres Attribut behalten.
905 if ( !pAttrib->IsFeature() && ( pAttrib->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) )
906 pAttrib->GetEnd() = nIndex; // leer
907 else
908 bDelAttr = TRUE;
910 // 2. Attribut beginnt davor, endet drinnen oder dahinter...
911 else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) )
913 DBG_ASSERT( !pAttrib->IsFeature(), "Collapsing Feature!" );
914 if ( pAttrib->GetEnd() <= nEndChanges ) // endet drinnen
915 pAttrib->GetEnd() = nIndex;
916 else
917 pAttrib->Collaps( nDeleted ); // endet dahinter
919 // 3. Attribut beginnt drinnen, endet dahinter...
920 else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() > nEndChanges ) )
922 // Features duerfen nicht expandieren!
923 if ( pAttrib->IsFeature() )
925 pAttrib->MoveBackward( nDeleted );
926 bResort = TRUE;
928 else
930 pAttrib->GetStart() = nEndChanges;
931 pAttrib->MoveBackward( nDeleted );
935 DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" );
937 DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collaps: Attribut verdreht!" );
938 DBG_ASSERT( ( pAttrib->GetEnd() <= Len()) || bDelAttr, "Collaps: Attrib groesser als Absatz!" );
939 if ( bDelAttr /* || pAttrib->IsEmpty() */ )
941 bResort = TRUE;
942 aCharAttribList.GetAttribs().Remove( nAttr );
943 rItemPool.Remove( *pAttrib->GetItem() );
944 delete pAttrib;
945 nAttr--;
947 else if ( pAttrib->IsEmpty() )
948 aCharAttribList.HasEmptyAttribs() = TRUE;
950 nAttr++;
951 pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr );
954 if ( bResort )
955 aCharAttribList.ResortAttribs();
957 #ifndef SVX_LIGHT
958 if ( pWrongList )
959 pWrongList->TextDeleted( nIndex, nDeleted );
960 #endif // !SVX_LIGHT
962 #ifdef EDITDEBUG
963 DBG_ASSERT( CheckOrderedList( aCharAttribList.GetAttribs(), TRUE ), "Collaps: Start-Liste verdreht" );
964 #endif
967 void ContentNode::CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, BOOL bKeepEndingAttribs )
969 DBG_ASSERT( pPrevNode, "kopieren von Attributen auf einen NULL-Pointer ?" );
971 xub_StrLen nCut = pPrevNode->Len();
973 USHORT nAttr = 0;
974 EditCharAttrib* pAttrib = GetAttrib( pPrevNode->GetCharAttribs().GetAttribs(), nAttr );
975 while ( pAttrib )
977 if ( pAttrib->GetEnd() < nCut )
979 // bleiben unveraendert....
982 else if ( pAttrib->GetEnd() == nCut )
984 // muessen als leeres Attribut kopiert werden.
985 if ( bKeepEndingAttribs && !pAttrib->IsFeature() && !aCharAttribList.FindAttrib( pAttrib->GetItem()->Which(), 0 ) )
987 EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, 0 );
988 DBG_ASSERT( pNewAttrib, "MakeCharAttrib fehlgeschlagen!" );
989 aCharAttribList.InsertAttrib( pNewAttrib );
992 else if ( pAttrib->IsInside( nCut ) || ( !nCut && !pAttrib->GetStart() && !pAttrib->IsFeature() ) )
994 // Wenn ganz vorne gecuttet wird, muss das Attribut erhalten bleiben!
995 // muessen kopiert und geaendert werden
996 EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, pAttrib->GetEnd()-nCut );
997 DBG_ASSERT( pNewAttrib, "MakeCharAttrib fehlgeschlagen!" );
998 aCharAttribList.InsertAttrib( pNewAttrib );
999 // stutzen:
1000 pAttrib->GetEnd() = nCut;
1002 else
1004 // alle dahinter verschieben in den neuen Node (this)
1005 // pPrevNode->GetCharAttribs().RemoveAttrib( pAttrib );
1006 pPrevNode->GetCharAttribs().GetAttribs().Remove( nAttr );
1007 aCharAttribList.InsertAttrib( pAttrib );
1008 DBG_ASSERT( pAttrib->GetStart() >= nCut, "Start < nCut!" );
1009 DBG_ASSERT( pAttrib->GetEnd() >= nCut, "End < nCut!" );
1010 pAttrib->GetStart() = pAttrib->GetStart() - nCut;
1011 pAttrib->GetEnd() = pAttrib->GetEnd() - nCut;
1012 nAttr--;
1014 nAttr++;
1015 pAttrib = GetAttrib( pPrevNode->GetCharAttribs().GetAttribs(), nAttr );
1019 void ContentNode::AppendAttribs( ContentNode* pNextNode )
1021 DBG_ASSERT( pNextNode, "kopieren von Attributen von einen NULL-Pointer ?" );
1023 USHORT nNewStart = Len();
1025 #ifdef EDITDEBUG
1026 DBG_ASSERT( aCharAttribList.DbgCheckAttribs(), "Attribute VOR AppendAttribs kaputt" );
1027 #endif
1029 USHORT nAttr = 0;
1030 EditCharAttrib* pAttrib = GetAttrib( pNextNode->GetCharAttribs().GetAttribs(), nAttr );
1031 while ( pAttrib )
1033 // alle Attribute verschieben in den aktuellen Node (this)
1034 BOOL bMelted = FALSE;
1035 if ( ( pAttrib->GetStart() == 0 ) && ( !pAttrib->IsFeature() ) )
1037 // Evtl koennen Attribute zusammengefasst werden:
1038 USHORT nTmpAttr = 0;
1039 EditCharAttrib* pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr );
1040 while ( !bMelted && pTmpAttrib )
1042 if ( pTmpAttrib->GetEnd() == nNewStart )
1044 if ( ( pTmpAttrib->Which() == pAttrib->Which() ) &&
1045 ( *(pTmpAttrib->GetItem()) == *(pAttrib->GetItem() ) ) )
1047 pTmpAttrib->GetEnd() =
1048 pTmpAttrib->GetEnd() + pAttrib->GetLen();
1049 pNextNode->GetCharAttribs().GetAttribs().Remove( nAttr );
1050 // Vom Pool abmelden ?!
1051 delete pAttrib;
1052 bMelted = TRUE;
1055 ++nTmpAttr;
1056 pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr );
1060 if ( !bMelted )
1062 pAttrib->GetStart() = pAttrib->GetStart() + nNewStart;
1063 pAttrib->GetEnd() = pAttrib->GetEnd() + nNewStart;
1064 aCharAttribList.InsertAttrib( pAttrib );
1065 ++nAttr;
1067 pAttrib = GetAttrib( pNextNode->GetCharAttribs().GetAttribs(), nAttr );
1069 // Fuer die Attribute, die nur ruebergewandert sind:
1070 pNextNode->GetCharAttribs().Clear();
1072 #ifdef EDITDEBUG
1073 DBG_ASSERT( aCharAttribList.DbgCheckAttribs(), "Attribute NACH AppendAttribs kaputt" );
1074 #endif
1077 void ContentNode::CreateDefFont()
1079 // Erst alle Informationen aus dem Style verwenden...
1080 SfxStyleSheet* pS = aContentAttribs.GetStyleSheet();
1081 if ( pS )
1082 CreateFont( GetCharAttribs().GetDefFont(), pS->GetItemSet() );
1084 // ... dann die harte Absatzformatierung rueberbuegeln...
1085 CreateFont( GetCharAttribs().GetDefFont(),
1086 GetContentAttribs().GetItems(), pS == NULL );
1089 void ContentNode::SetStyleSheet( SfxStyleSheet* pS, const SvxFont& rFontFromStyle )
1091 aContentAttribs.SetStyleSheet( pS );
1093 // Erst alle Informationen aus dem Style verwenden...
1094 GetCharAttribs().GetDefFont() = rFontFromStyle;
1095 // ... dann die harte Absatzformatierung rueberbuegeln...
1096 CreateFont( GetCharAttribs().GetDefFont(),
1097 GetContentAttribs().GetItems(), pS == NULL );
1100 void ContentNode::SetStyleSheet( SfxStyleSheet* pS, BOOL bRecalcFont )
1102 aContentAttribs.SetStyleSheet( pS );
1103 if ( bRecalcFont )
1104 CreateDefFont();
1107 void ContentNode::DestroyWrongList()
1109 #ifndef SVX_LIGHT
1110 delete pWrongList;
1111 #endif
1112 pWrongList = NULL;
1115 void ContentNode::CreateWrongList()
1117 DBG_ASSERT( !pWrongList, "WrongList existiert schon!" );
1118 #ifndef SVX_LIGHT
1119 pWrongList = new WrongList;
1120 #endif
1123 void ContentNode::SetWrongList( WrongList* p )
1125 DBG_ASSERT( !pWrongList, "WrongList existiert schon!" );
1126 pWrongList = p;
1129 \f// -------------------------------------------------------------------------
1130 // class ContentAttribs
1131 // -------------------------------------------------------------------------
1132 ContentAttribs::ContentAttribs( SfxItemPool& rPool ) :
1133 aAttribSet( rPool, EE_PARA_START, EE_CHAR_END )
1135 pStyle = 0;
1138 ContentAttribs::ContentAttribs( const ContentAttribs& rRef ) :
1139 aAttribSet( rRef.aAttribSet )
1141 pStyle = rRef.pStyle;
1144 ContentAttribs::~ContentAttribs()
1148 SvxTabStop ContentAttribs::FindTabStop( long nCurPos, USHORT nDefTab )
1150 const SvxTabStopItem& rTabs = (const SvxTabStopItem&) GetItem( EE_PARA_TABS );
1151 for ( USHORT i = 0; i < rTabs.Count(); i++ )
1153 const SvxTabStop& rTab = rTabs[i];
1154 if ( rTab.GetTabPos() > nCurPos )
1155 return rTab;
1158 // DefTab ermitteln...
1159 SvxTabStop aTabStop;
1160 long x = nCurPos / nDefTab + 1;
1161 aTabStop.GetTabPos() = nDefTab * x;
1162 return aTabStop;
1165 void ContentAttribs::SetStyleSheet( SfxStyleSheet* pS )
1167 BOOL bStyleChanged = ( pStyle != pS );
1168 pStyle = pS;
1169 // #104799# Only when other style sheet, not when current style sheet modified
1170 if ( pStyle && bStyleChanged )
1172 // Gezielt die Attribute aus der Absatzformatierung entfernen, die im Style
1173 // spezifiziert sind, damit die Attribute des Styles wirken koennen.
1174 const SfxItemSet& rStyleAttribs = pStyle->GetItemSet();
1175 for ( USHORT nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ )
1177 // #99635# Don't change bullet on/off
1178 if ( ( nWhich != EE_PARA_BULLETSTATE ) && ( rStyleAttribs.GetItemState( nWhich ) == SFX_ITEM_ON ) )
1179 aAttribSet.ClearItem( nWhich );
1184 const SfxPoolItem& ContentAttribs::GetItem( USHORT nWhich )
1186 // Harte Absatzattribute haben Vorrang!
1187 SfxItemSet* pTakeFrom = &aAttribSet;
1188 if ( pStyle && ( aAttribSet.GetItemState( nWhich, FALSE ) != SFX_ITEM_ON ) )
1189 pTakeFrom = &pStyle->GetItemSet();
1191 return pTakeFrom->Get( nWhich );
1194 BOOL ContentAttribs::HasItem( USHORT nWhich )
1196 BOOL bHasItem = FALSE;
1197 if ( aAttribSet.GetItemState( nWhich, FALSE ) == SFX_ITEM_ON )
1198 bHasItem = TRUE;
1199 else if ( pStyle && pStyle->GetItemSet().GetItemState( nWhich ) == SFX_ITEM_ON )
1200 bHasItem = TRUE;
1202 return bHasItem;
1207 \f// ----------------------------------------------------------------------
1208 // class ItemList
1209 // ----------------------------------------------------------------------
1210 const SfxPoolItem* ItemList::FindAttrib( USHORT nWhich )
1212 const SfxPoolItem* pItem = First();
1213 while ( pItem && ( pItem->Which() != nWhich ) )
1214 pItem = Next();
1216 return pItem;
1219 \f// -------------------------------------------------------------------------
1220 // class EditDoc
1221 // -------------------------------------------------------------------------
1222 EditDoc::EditDoc( SfxItemPool* pPool )
1224 if ( pPool )
1226 pItemPool = pPool;
1227 bOwnerOfPool = FALSE;
1229 else
1231 pItemPool = new EditEngineItemPool( FALSE );
1232 bOwnerOfPool = TRUE;
1235 nDefTab = DEFTAB;
1236 bIsVertical = FALSE;
1237 bIsFixedCellHeight = FALSE;
1239 // Don't create a empty node, Clear() will be called in EditEngine-CTOR
1241 SetModified( FALSE );
1244 EditDoc::~EditDoc()
1246 ImplDestroyContents();
1247 if ( bOwnerOfPool )
1248 SfxItemPool::Free(pItemPool);
1251 void EditDoc::ImplDestroyContents()
1253 for ( USHORT nNode = Count(); nNode; )
1254 RemoveItemsFromPool( GetObject( --nNode ) );
1255 DeleteAndDestroy( 0, Count() );
1258 void EditDoc::RemoveItemsFromPool( ContentNode* pNode )
1260 for ( USHORT nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ )
1262 EditCharAttrib* pAttr = pNode->GetCharAttribs().GetAttribs()[nAttr];
1263 GetItemPool().Remove( *pAttr->GetItem() );
1267 void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, short nScriptType )
1269 Font aPrevFont( rFont );
1270 rFont.SetAlign( ALIGN_BASELINE );
1271 rFont.SetTransparent( TRUE );
1273 USHORT nWhich_FontInfo = GetScriptItemId( EE_CHAR_FONTINFO, nScriptType );
1274 USHORT nWhich_Language = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType );
1275 USHORT nWhich_FontHeight = GetScriptItemId( EE_CHAR_FONTHEIGHT, nScriptType );
1276 USHORT nWhich_Weight = GetScriptItemId( EE_CHAR_WEIGHT, nScriptType );
1277 USHORT nWhich_Italic = GetScriptItemId( EE_CHAR_ITALIC, nScriptType );
1279 if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontInfo ) == SFX_ITEM_ON ) )
1281 const SvxFontItem& rFontItem = (const SvxFontItem&)rSet.Get( nWhich_FontInfo );
1282 rFont.SetName( rFontItem.GetFamilyName() );
1283 rFont.SetFamily( rFontItem.GetFamily() );
1284 rFont.SetPitch( rFontItem.GetPitch() );
1285 rFont.SetCharSet( rFontItem.GetCharSet() );
1287 if ( bSearchInParent || ( rSet.GetItemState( nWhich_Language ) == SFX_ITEM_ON ) )
1288 rFont.SetLanguage( ((const SvxLanguageItem&)rSet.Get( nWhich_Language )).GetLanguage() );
1289 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_COLOR ) == SFX_ITEM_ON ) )
1290 rFont.SetColor( ((const SvxColorItem&)rSet.Get( EE_CHAR_COLOR )).GetValue() );
1291 if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontHeight ) == SFX_ITEM_ON ) )
1292 rFont.SetSize( Size( rFont.GetSize().Width(), ((const SvxFontHeightItem&)rSet.Get( nWhich_FontHeight ) ).GetHeight() ) );
1293 if ( bSearchInParent || ( rSet.GetItemState( nWhich_Weight ) == SFX_ITEM_ON ) )
1294 rFont.SetWeight( ((const SvxWeightItem&)rSet.Get( nWhich_Weight )).GetWeight() );
1295 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_UNDERLINE ) == SFX_ITEM_ON ) )
1296 rFont.SetUnderline( ((const SvxUnderlineItem&)rSet.Get( EE_CHAR_UNDERLINE )).GetLineStyle() );
1297 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OVERLINE ) == SFX_ITEM_ON ) )
1298 rFont.SetOverline( ((const SvxOverlineItem&)rSet.Get( EE_CHAR_OVERLINE )).GetLineStyle() );
1299 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_STRIKEOUT ) == SFX_ITEM_ON ) )
1300 rFont.SetStrikeout( ((const SvxCrossedOutItem&)rSet.Get( EE_CHAR_STRIKEOUT )).GetStrikeout() );
1301 if ( bSearchInParent || ( rSet.GetItemState( nWhich_Italic ) == SFX_ITEM_ON ) )
1302 rFont.SetItalic( ((const SvxPostureItem&)rSet.Get( nWhich_Italic )).GetPosture() );
1303 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OUTLINE ) == SFX_ITEM_ON ) )
1304 rFont.SetOutline( ((const SvxContourItem&)rSet.Get( EE_CHAR_OUTLINE )).GetValue() );
1305 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_SHADOW ) == SFX_ITEM_ON ) )
1306 rFont.SetShadow( ((const SvxShadowedItem&)rSet.Get( EE_CHAR_SHADOW )).GetValue() );
1307 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_ESCAPEMENT ) == SFX_ITEM_ON ) )
1309 const SvxEscapementItem& rEsc = (const SvxEscapementItem&) rSet.Get( EE_CHAR_ESCAPEMENT );
1311 USHORT nProp = rEsc.GetProp();
1312 rFont.SetPropr( (BYTE)nProp );
1314 short nEsc = rEsc.GetEsc();
1315 if ( nEsc == DFLT_ESC_AUTO_SUPER )
1316 nEsc = 100 - nProp;
1317 else if ( nEsc == DFLT_ESC_AUTO_SUB )
1318 nEsc = sal::static_int_cast< short >( -( 100 - nProp ) );
1319 rFont.SetEscapement( nEsc );
1321 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_PAIRKERNING ) == SFX_ITEM_ON ) )
1322 rFont.SetKerning( ((const SvxAutoKernItem&)rSet.Get( EE_CHAR_PAIRKERNING )).GetValue() );
1323 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_KERNING ) == SFX_ITEM_ON ) )
1324 rFont.SetFixKerning( ((const SvxKerningItem&)rSet.Get( EE_CHAR_KERNING )).GetValue() );
1325 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_WLM ) == SFX_ITEM_ON ) )
1326 rFont.SetWordLineMode( ((const SvxWordLineModeItem&)rSet.Get( EE_CHAR_WLM )).GetValue() );
1327 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_EMPHASISMARK ) == SFX_ITEM_ON ) )
1328 rFont.SetEmphasisMark( ((const SvxEmphasisMarkItem&)rSet.Get( EE_CHAR_EMPHASISMARK )).GetValue() );
1329 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_RELIEF ) == SFX_ITEM_ON ) )
1330 rFont.SetRelief( (FontRelief)((const SvxCharReliefItem&)rSet.Get( EE_CHAR_RELIEF )).GetValue() );
1332 // Ob ich jetzt den ganzen Font vergleiche, oder vor jeder Aenderung
1333 // pruefe, ob der Wert sich aendert, bleibt sich relativ gleich.
1334 // So ggf ein MakeUniqFont im Font mehr, dafuer bei Aenderung schnellerer
1335 // Abbruch der Abfrage, oder ich musste noch jedesmal ein bChanged pflegen.
1336 if ( rFont == aPrevFont )
1337 rFont = aPrevFont; // => Gleicher ImpPointer fuer IsSameInstance
1340 void EditDoc::CreateDefFont( BOOL bUseStyles )
1342 SfxItemSet aTmpSet( GetItemPool(), EE_PARA_START, EE_CHAR_END );
1343 CreateFont( aDefFont, aTmpSet );
1344 aDefFont.SetVertical( IsVertical() );
1345 aDefFont.SetOrientation( IsVertical() ? 2700 : 0 );
1347 for ( USHORT nNode = 0; nNode < Count(); nNode++ )
1349 ContentNode* pNode = GetObject( nNode );
1350 pNode->GetCharAttribs().GetDefFont() = aDefFont;
1351 if ( bUseStyles )
1352 pNode->CreateDefFont();
1356 static const sal_Unicode aCR[] = { 0x0d, 0x00 };
1357 static const sal_Unicode aLF[] = { 0x0a, 0x00 };
1358 static const sal_Unicode aCRLF[] = { 0x0d, 0x0a, 0x00 };
1360 XubString EditDoc::GetSepStr( LineEnd eEnd )
1362 XubString aSep;
1363 if ( eEnd == LINEEND_CR )
1364 aSep = aCR;
1365 else if ( eEnd == LINEEND_LF )
1366 aSep = aLF;
1367 else
1368 aSep = aCRLF;
1369 return aSep;
1372 XubString EditDoc::GetText( LineEnd eEnd ) const
1374 ULONG nLen = GetTextLen();
1375 USHORT nNodes = Count();
1377 String aSep = EditDoc::GetSepStr( eEnd );
1378 USHORT nSepSize = aSep.Len();
1380 if ( nSepSize )
1381 nLen += nNodes * nSepSize;
1382 if ( nLen > 0xFFFb / sizeof(xub_Unicode) )
1384 DBG_ERROR( "Text zu gross fuer String" );
1385 return XubString();
1387 xub_Unicode* pStr = new xub_Unicode[nLen+1];
1388 xub_Unicode* pCur = pStr;
1389 USHORT nLastNode = nNodes-1;
1390 for ( USHORT nNode = 0; nNode < nNodes; nNode++ )
1392 XubString aTmp( GetParaAsString( GetObject(nNode) ) );
1393 memcpy( pCur, aTmp.GetBuffer(), aTmp.Len()*sizeof(sal_Unicode) );
1394 pCur += aTmp.Len();
1395 if ( nSepSize && ( nNode != nLastNode ) )
1397 memcpy( pCur, aSep.GetBuffer(), nSepSize*sizeof(sal_Unicode ) );
1398 pCur += nSepSize;
1401 *pCur = '\0';
1402 XubString aASCIIText( pStr );
1403 delete[] pStr;
1404 return aASCIIText;
1407 XubString EditDoc::GetParaAsString( USHORT nNode ) const
1409 return GetParaAsString( SaveGetObject( nNode ) );
1412 XubString EditDoc::GetParaAsString( ContentNode* pNode, USHORT nStartPos, USHORT nEndPos, BOOL bResolveFields ) const
1414 if ( nEndPos > pNode->Len() )
1415 nEndPos = pNode->Len();
1417 DBG_ASSERT( nStartPos <= nEndPos, "Start und Ende vertauscht?" );
1419 USHORT nIndex = nStartPos;
1420 XubString aStr;
1421 EditCharAttrib* pNextFeature = pNode->GetCharAttribs().FindFeature( nIndex );
1422 while ( nIndex < nEndPos )
1424 USHORT nEnd = nEndPos;
1425 if ( pNextFeature && ( pNextFeature->GetStart() < nEnd ) )
1426 nEnd = pNextFeature->GetStart();
1427 else
1428 pNextFeature = 0; // Feature interessiert unten nicht
1431 DBG_ASSERT( nEnd >= nIndex, "Ende vorm Index?" );
1432 aStr += XubString( *pNode, nIndex, nEnd-nIndex );
1434 if ( pNextFeature )
1436 switch ( pNextFeature->GetItem()->Which() )
1438 case EE_FEATURE_TAB: aStr += '\t';
1439 break;
1440 case EE_FEATURE_LINEBR: aStr += '\x0A';
1441 break;
1442 case EE_FEATURE_FIELD: if ( bResolveFields )
1443 aStr += ((EditCharAttribField*)pNextFeature)->GetFieldValue();
1444 break;
1445 default: DBG_ERROR( "Was fuer ein Feature ?" );
1447 pNextFeature = pNode->GetCharAttribs().FindFeature( ++nEnd );
1449 nIndex = nEnd;
1451 return aStr;
1454 ULONG EditDoc::GetTextLen() const
1456 ULONG nLen = 0;
1457 for ( USHORT nNode = 0; nNode < Count(); nNode++ )
1459 ContentNode* pNode = GetObject( nNode );
1460 nLen += pNode->Len();
1461 // Felder k”nnen laenger sein als der Platzhalter im Node.
1462 const CharAttribArray& rAttrs = pNode->GetCharAttribs().GetAttribs();
1463 for ( USHORT nAttr = rAttrs.Count(); nAttr; )
1465 EditCharAttrib* pAttr = rAttrs[--nAttr];
1466 if ( pAttr->Which() == EE_FEATURE_FIELD )
1468 USHORT nFieldLen = ((EditCharAttribField*)pAttr)->GetFieldValue().Len();
1469 if ( !nFieldLen )
1470 nLen--;
1471 else
1472 nLen += nFieldLen-1;
1476 return nLen;
1479 EditPaM EditDoc::Clear()
1481 ImplDestroyContents();
1483 ContentNode* pNode = new ContentNode( GetItemPool() );
1484 Insert( pNode, 0 );
1486 CreateDefFont( FALSE );
1488 SetModified( FALSE );
1490 EditPaM aPaM( pNode, 0 );
1491 return aPaM;
1494 void EditDoc::SetModified( BOOL b )
1496 bModified = b;
1497 if ( bModified )
1499 aModifyHdl.Call( NULL );
1503 EditPaM EditDoc::RemoveText()
1505 // Das alte ItemSetmerken, damit z.B. im Chart Font behalten bleibt
1506 ContentNode* pPrevFirstNode = GetObject(0);
1507 SfxStyleSheet* pPrevStyle = pPrevFirstNode->GetStyleSheet();
1508 SfxItemSet aPrevSet( pPrevFirstNode->GetContentAttribs().GetItems() );
1509 Font aPrevFont( pPrevFirstNode->GetCharAttribs().GetDefFont() );
1511 ImplDestroyContents();
1513 ContentNode* pNode = new ContentNode( GetItemPool() );
1514 Insert( pNode, 0 );
1516 pNode->SetStyleSheet( pPrevStyle, FALSE );
1517 pNode->GetContentAttribs().GetItems().Set( aPrevSet );
1518 pNode->GetCharAttribs().GetDefFont() = aPrevFont;
1520 SetModified( TRUE );
1522 EditPaM aPaM( pNode, 0 );
1523 return aPaM;
1526 void EditDoc::InsertText( const EditPaM& rPaM, xub_Unicode c )
1528 DBG_ASSERT( c != 0x0A, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
1529 DBG_ASSERT( c != 0x0D, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
1530 DBG_ASSERT( c != '\t', "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
1532 rPaM.GetNode()->Insert( c, rPaM.GetIndex() );
1533 rPaM.GetNode()->ExpandAttribs( rPaM.GetIndex(), 1, GetItemPool() );
1535 SetModified( TRUE );
1538 EditPaM EditDoc::InsertText( EditPaM aPaM, const XubString& rStr )
1540 DBG_ASSERT( rStr.Search( 0x0A ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
1541 DBG_ASSERT( rStr.Search( 0x0D ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
1542 DBG_ASSERT( rStr.Search( '\t' ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" );
1543 DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertText1" );
1545 aPaM.GetNode()->Insert( rStr, aPaM.GetIndex() );
1546 aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.Len(), GetItemPool() );
1547 aPaM.GetIndex() = aPaM.GetIndex() + rStr.Len();
1549 SetModified( TRUE );
1551 return aPaM;
1554 EditPaM EditDoc::InsertParaBreak( EditPaM aPaM, BOOL bKeepEndingAttribs )
1556 DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertParaBreak" );
1557 ContentNode* pCurNode = aPaM.GetNode();
1558 USHORT nPos = GetPos( pCurNode );
1559 XubString aStr = aPaM.GetNode()->Copy( aPaM.GetIndex() );
1560 aPaM.GetNode()->Erase( aPaM.GetIndex() );
1562 // the paragraph attributes...
1563 ContentAttribs aContentAttribs( aPaM.GetNode()->GetContentAttribs() );
1565 // for a new paragraph we like to have the bullet/numbering visible by default
1566 aContentAttribs.GetItems().Put( SfxBoolItem( EE_PARA_BULLETSTATE, TRUE), EE_PARA_BULLETSTATE );
1568 // ContenNode-CTOR kopiert auch die Absatzattribute
1569 ContentNode* pNode = new ContentNode( aStr, aContentAttribs );
1571 // Den Default-Font kopieren
1572 pNode->GetCharAttribs().GetDefFont() = aPaM.GetNode()->GetCharAttribs().GetDefFont();
1573 SfxStyleSheet* pStyle = aPaM.GetNode()->GetStyleSheet();
1574 if ( pStyle )
1576 XubString aFollow( pStyle->GetFollow() );
1577 if ( aFollow.Len() && ( aFollow != pStyle->GetName() ) )
1579 SfxStyleSheetBase* pNext = pStyle->GetPool().Find( aFollow, pStyle->GetFamily() );
1580 pNode->SetStyleSheet( (SfxStyleSheet*)pNext );
1584 // Zeichenattribute muessen ggf. kopiert bzw gestutzt werden:
1585 pNode->CopyAndCutAttribs( aPaM.GetNode(), GetItemPool(), bKeepEndingAttribs );
1587 Insert( pNode, nPos+1 );
1589 SetModified( TRUE );
1591 aPaM.SetNode( pNode );
1592 aPaM.SetIndex( 0 );
1593 return aPaM;
1596 EditPaM EditDoc::InsertFeature( EditPaM aPaM, const SfxPoolItem& rItem )
1598 DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertFeature" );
1600 aPaM.GetNode()->Insert( CH_FEATURE, aPaM.GetIndex() );
1601 aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1, GetItemPool() );
1603 // Fuer das Feature ein Feature-Attribut anlegen...
1604 EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rItem, aPaM.GetIndex(), aPaM.GetIndex()+1 );
1605 DBG_ASSERT( pAttrib, "Warum kann ich kein Feature anlegen ?" );
1606 aPaM.GetNode()->GetCharAttribs().InsertAttrib( pAttrib );
1608 SetModified( TRUE );
1610 aPaM.GetIndex()++;
1611 return aPaM;
1614 EditPaM EditDoc::ConnectParagraphs( ContentNode* pLeft, ContentNode* pRight )
1616 const EditPaM aPaM( pLeft, pLeft->Len() );
1618 // Erst die Attribute, da sonst nLen nicht stimmt!
1619 pLeft->AppendAttribs( pRight );
1620 // Dann den Text...
1621 *pLeft += *pRight;
1623 // der rechte verschwindet.
1624 RemoveItemsFromPool( pRight );
1625 USHORT nRight = GetPos( pRight );
1626 Remove( nRight );
1627 delete pRight;
1629 SetModified( TRUE );
1631 return aPaM;
1634 EditPaM EditDoc::RemoveChars( EditPaM aPaM, USHORT nChars )
1636 // Evtl. Features entfernen!
1637 aPaM.GetNode()->Erase( aPaM.GetIndex(), nChars );
1638 aPaM.GetNode()->CollapsAttribs( aPaM.GetIndex(), nChars, GetItemPool() );
1640 SetModified( TRUE );
1642 return aPaM;
1645 void EditDoc::InsertAttribInSelection( ContentNode* pNode, USHORT nStart, USHORT nEnd, const SfxPoolItem& rPoolItem )
1647 DBG_ASSERT( pNode, "Wohin mit dem Attribut?" );
1648 DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribut zu gross!" );
1650 // fuer Optimierung:
1651 // dieses endet am Anfang der Selektion => kann erweitert werden
1652 EditCharAttrib* pEndingAttrib = 0;
1653 // dieses startet am Ende der Selektion => kann erweitert werden
1654 EditCharAttrib* pStartingAttrib = 0;
1656 DBG_ASSERT( nStart <= nEnd, "Kleiner Rechenfehler in InsertAttribInSelection" );
1658 RemoveAttribs( pNode, nStart, nEnd, pStartingAttrib, pEndingAttrib, rPoolItem.Which() );
1660 if ( pStartingAttrib && pEndingAttrib &&
1661 ( *(pStartingAttrib->GetItem()) == rPoolItem ) &&
1662 ( *(pEndingAttrib->GetItem()) == rPoolItem ) )
1664 // wird ein groesses Attribut.
1665 pEndingAttrib->GetEnd() = pStartingAttrib->GetEnd();
1666 GetItemPool().Remove( *(pStartingAttrib->GetItem()) );
1667 pNode->GetCharAttribs().GetAttribs().Remove( pNode->GetCharAttribs().GetAttribs().GetPos( pStartingAttrib ) );
1668 delete pStartingAttrib;
1670 else if ( pStartingAttrib && ( *(pStartingAttrib->GetItem()) == rPoolItem ) )
1671 pStartingAttrib->GetStart() = nStart;
1672 else if ( pEndingAttrib && ( *(pEndingAttrib->GetItem()) == rPoolItem ) )
1673 pEndingAttrib->GetEnd() = nEnd;
1674 else
1675 InsertAttrib( rPoolItem, pNode, nStart, nEnd );
1677 if ( pStartingAttrib )
1678 pNode->GetCharAttribs().ResortAttribs();
1680 SetModified( TRUE );
1683 BOOL EditDoc::RemoveAttribs( ContentNode* pNode, USHORT nStart, USHORT nEnd, USHORT nWhich )
1685 EditCharAttrib* pStarting;
1686 EditCharAttrib* pEnding;
1687 return RemoveAttribs( pNode, nStart, nEnd, pStarting, pEnding, nWhich );
1690 BOOL EditDoc::RemoveAttribs( ContentNode* pNode, USHORT nStart, USHORT nEnd, EditCharAttrib*& rpStarting, EditCharAttrib*& rpEnding, USHORT nWhich )
1692 DBG_ASSERT( pNode, "Wohin mit dem Attribut?" );
1693 DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribut zu gross!" );
1695 // dieses endet am Anfang der Selektion => kann erweitert werden
1696 rpEnding = 0;
1697 // dieses startet am Ende der Selektion => kann erweitert werden
1698 rpStarting = 0;
1700 BOOL bChanged = FALSE;
1702 DBG_ASSERT( nStart <= nEnd, "Kleiner Rechenfehler in InsertAttribInSelection" );
1704 // ueber die Attribute iterieren...
1705 USHORT nAttr = 0;
1706 EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
1707 while ( pAttr )
1709 BOOL bRemoveAttrib = FALSE;
1710 // MT 11.9.97:
1711 // Ich denke dass in dieser Methode generell keine Features geloescht
1712 // werden sollen.
1713 // => Dann koennen die Feature-Abfragen weiter unten entfallen
1714 USHORT nAttrWhich = pAttr->Which();
1715 if ( ( nAttrWhich < EE_FEATURE_START ) && ( !nWhich || ( nAttrWhich == nWhich ) ) )
1717 // Attribut beginnt in Selection
1718 if ( ( pAttr->GetStart() >= nStart ) && ( pAttr->GetStart() <= nEnd ) )
1720 bChanged = TRUE;
1721 if ( pAttr->GetEnd() > nEnd )
1723 pAttr->GetStart() = nEnd; // dann faengt es dahinter an
1724 rpStarting = pAttr;
1725 if ( nWhich )
1726 break; // es kann kein weiteres Attrib hier liegen
1728 else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) )
1730 // Feature nur loeschen, wenn genau an der Stelle
1731 bRemoveAttrib = TRUE;
1735 // Attribut endet in Selection
1736 else if ( ( pAttr->GetEnd() >= nStart ) && ( pAttr->GetEnd() <= nEnd ) )
1738 bChanged = TRUE;
1739 if ( ( pAttr->GetStart() < nStart ) && !pAttr->IsFeature() )
1741 pAttr->GetEnd() = nStart; // dann hoert es hier auf
1742 rpEnding = pAttr;
1744 else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) )
1746 // Feature nur loeschen, wenn genau an der Stelle
1747 bRemoveAttrib = TRUE;
1750 // Attribut ueberlappt die Selektion
1751 else if ( ( pAttr->GetStart() <= nStart ) && ( pAttr->GetEnd() >= nEnd ) )
1753 bChanged = TRUE;
1754 if ( pAttr->GetStart() == nStart )
1756 pAttr->GetStart() = nEnd;
1757 rpStarting = pAttr;
1758 if ( nWhich )
1759 break; // es kann weitere Attribute geben!
1761 else if ( pAttr->GetEnd() == nEnd )
1763 pAttr->GetEnd() = nStart;
1764 rpEnding = pAttr;
1765 if ( nWhich )
1766 break; // es kann weitere Attribute geben!
1768 else // Attribut muss gesplittet werden...
1770 USHORT nOldEnd = pAttr->GetEnd();
1771 pAttr->GetEnd() = nStart;
1772 rpEnding = pAttr;
1773 InsertAttrib( *pAttr->GetItem(), pNode, nEnd, nOldEnd );
1774 if ( nWhich )
1775 break; // es kann weitere Attribute geben!
1779 if ( bRemoveAttrib )
1781 DBG_ASSERT( ( pAttr != rpStarting ) && ( pAttr != rpEnding ), "Loeschen und behalten des gleichen Attributs ?" );
1782 DBG_ASSERT( !pAttr->IsFeature(), "RemoveAttribs: Remove a feature?!" );
1783 pNode->GetCharAttribs().GetAttribs().Remove(nAttr);
1784 GetItemPool().Remove( *pAttr->GetItem() );
1785 delete pAttr;
1786 nAttr--;
1788 nAttr++;
1789 pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
1792 if ( bChanged )
1793 SetModified( TRUE );
1795 return bChanged;
1798 void EditDoc::InsertAttrib( const SfxPoolItem& rPoolItem, ContentNode* pNode, USHORT nStart, USHORT nEnd )
1800 // Diese Methode prueft nicht mehr, ob ein entspr. Attribut
1801 // schon an der Stelle existiert!
1803 EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rPoolItem, nStart, nEnd );
1804 DBG_ASSERT( pAttrib, "MakeCharAttrib fehlgeschlagen!" );
1805 pNode->GetCharAttribs().InsertAttrib( pAttrib );
1807 SetModified( TRUE );
1810 void EditDoc::InsertAttrib( ContentNode* pNode, USHORT nStart, USHORT nEnd, const SfxPoolItem& rPoolItem )
1812 if ( nStart != nEnd )
1814 InsertAttribInSelection( pNode, nStart, nEnd, rPoolItem );
1816 else
1818 // Pruefen, ob schon ein neues Attribut mit der WhichId an der Stelle:
1819 EditCharAttrib* pAttr = pNode->GetCharAttribs().FindEmptyAttrib( rPoolItem.Which(), nStart );
1820 if ( pAttr )
1822 // Attribut entfernen....
1823 pNode->GetCharAttribs().GetAttribs().Remove(
1824 pNode->GetCharAttribs().GetAttribs().GetPos( pAttr ) );
1827 // pruefen, ob ein 'gleiches' Attribut an der Stelle liegt.
1828 pAttr = pNode->GetCharAttribs().FindAttrib( rPoolItem.Which(), nStart );
1829 if ( pAttr )
1831 if ( pAttr->IsInside( nStart ) ) // splitten
1833 // ???????????????????????????????
1834 // eigentlich noch pruefen, ob wirklich splittet, oder return !
1835 // ???????????????????????????????
1836 USHORT nOldEnd = pAttr->GetEnd();
1837 pAttr->GetEnd() = nStart;
1838 pAttr = MakeCharAttrib( GetItemPool(), *(pAttr->GetItem()), nStart, nOldEnd );
1839 pNode->GetCharAttribs().InsertAttrib( pAttr );
1841 else if ( pAttr->GetEnd() == nStart )
1843 DBG_ASSERT( !pAttr->IsEmpty(), "Doch noch ein leeres Attribut?" );
1844 // pruefen, ob genau das gleiche Attribut
1845 if ( *(pAttr->GetItem()) == rPoolItem )
1846 return;
1849 InsertAttrib( rPoolItem, pNode, nStart, nStart );
1852 SetModified( TRUE );
1855 void EditDoc::FindAttribs( ContentNode* pNode, USHORT nStartPos, USHORT nEndPos, SfxItemSet& rCurSet )
1857 DBG_ASSERT( pNode, "Wo soll ich suchen ?" );
1858 DBG_ASSERT( nStartPos <= nEndPos, "Ungueltiger Bereich!" );
1860 USHORT nAttr = 0;
1861 EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
1862 // keine Selection...
1863 if ( nStartPos == nEndPos )
1865 while ( pAttr && ( pAttr->GetStart() <= nEndPos) )
1867 const SfxPoolItem* pItem = 0;
1868 // Attribut liegt dadrueber...
1869 if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() > nStartPos ) )
1870 pItem = pAttr->GetItem();
1871 // Attribut endet hier, ist nicht leer
1872 else if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() == nStartPos ) )
1874 if ( !pNode->GetCharAttribs().FindEmptyAttrib( pAttr->GetItem()->Which(), nStartPos ) )
1875 pItem = pAttr->GetItem();
1877 // Attribut endet hier, ist leer
1878 else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() == nStartPos ) )
1880 pItem = pAttr->GetItem();
1882 // Attribut beginnt hier
1883 else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() > nStartPos ) )
1885 if ( nStartPos == 0 ) // Sonderfall
1886 pItem = pAttr->GetItem();
1889 if ( pItem )
1891 USHORT nWhich = pItem->Which();
1892 if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
1894 rCurSet.Put( *pItem );
1896 else if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_ON )
1898 const SfxPoolItem& rItem = rCurSet.Get( nWhich );
1899 if ( rItem != *pItem )
1901 rCurSet.InvalidateItem( nWhich );
1905 nAttr++;
1906 pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
1909 else // Selektion
1911 while ( pAttr && ( pAttr->GetStart() < nEndPos) )
1913 const SfxPoolItem* pItem = 0;
1914 // Attribut liegt dadrueber...
1915 if ( ( pAttr->GetStart() <= nStartPos ) && ( pAttr->GetEnd() >= nEndPos ) )
1916 pItem = pAttr->GetItem();
1917 // Attribut startet mitten drin...
1918 else if ( pAttr->GetStart() >= nStartPos )
1920 // !!! pItem = pAttr->GetItem();
1921 // einfach nur pItem reicht nicht, da ich z.B. bei Shadow
1922 // niemals ein ungleiches Item finden wuerde, da ein solche
1923 // seine Anwesenheit durch Abwesenheit repraesentiert!
1924 // if ( ... )
1925 // Es muesste geprueft werden, on genau das gleiche Attribut
1926 // an der Bruchstelle aufsetzt, was recht aufwendig ist.
1927 // Da ich beim Einfuegen von Attributen aber etwas optimiere
1928 // tritt der Fall nicht so schnell auf...
1929 // Also aus Geschwindigkeitsgruenden:
1930 rCurSet.InvalidateItem( pAttr->GetItem()->Which() );
1933 // Attribut endet mitten drin...
1934 else if ( pAttr->GetEnd() > nStartPos )
1936 // pItem = pAttr->GetItem();
1937 // s.o.
1938 /*-----------------31.05.95 16:01-------------------
1939 Ist falsch, wenn das gleiche Attribut sofort wieder
1940 eingestellt wird!
1941 => Sollte am besten nicht vorkommen, also gleich beim
1942 Setzen von Attributen richtig machen!
1943 --------------------------------------------------*/
1944 rCurSet.InvalidateItem( pAttr->GetItem()->Which() );
1947 if ( pItem )
1949 USHORT nWhich = pItem->Which();
1950 if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
1952 rCurSet.Put( *pItem );
1954 else if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_ON )
1956 const SfxPoolItem& rItem = rCurSet.Get( nWhich );
1957 if ( rItem != *pItem )
1959 rCurSet.InvalidateItem( nWhich );
1963 nAttr++;
1964 pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
1970 \f// -------------------------------------------------------------------------
1971 // class EditCharAttribList
1972 // -------------------------------------------------------------------------
1974 CharAttribList::CharAttribList()
1976 DBG_CTOR( EE_CharAttribList, 0 );
1977 bHasEmptyAttribs = FALSE;
1980 CharAttribList::~CharAttribList()
1982 DBG_DTOR( EE_CharAttribList, 0 );
1984 USHORT nAttr = 0;
1985 EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr );
1986 while ( pAttr )
1988 delete pAttr;
1989 ++nAttr;
1990 pAttr = GetAttrib( aAttribs, nAttr );
1992 Clear();
1995 void CharAttribList::InsertAttrib( EditCharAttrib* pAttrib )
1997 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1998 // optimieren: binaere Suche ? !
1999 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2001 // MT: 26.11.98
2002 // Vielleicht aber auch einfach nur rueckwaerts iterieren:
2003 // Der haeufigste und kritischste Fall: Attribute kommen bereits
2004 // sortiert an (InsertBinTextObject!)
2005 // Hier waere auch binaere Suche nicht optimal.
2006 // => Wuerde einiges bringen!
2008 const USHORT nCount = Count();
2009 const USHORT nStart = pAttrib->GetStart(); // vielleicht besser fuer Comp.Opt.
2011 if ( pAttrib->IsEmpty() )
2012 bHasEmptyAttribs = TRUE;
2014 BOOL bInserted = FALSE;
2015 for ( USHORT x = 0; x < nCount; x++ )
2017 EditCharAttribPtr pCurAttrib = aAttribs[x];
2018 if ( pCurAttrib->GetStart() > nStart )
2020 aAttribs.Insert( pAttrib, x );
2021 bInserted = TRUE;
2022 break;
2025 if ( !bInserted )
2026 aAttribs.Insert( pAttrib, nCount );
2029 void CharAttribList::ResortAttribs()
2031 if ( Count() )
2033 #if defined __SUNPRO_CC
2034 #pragma disable_warn
2035 #endif
2036 qsort( (void*)aAttribs.GetData(), aAttribs.Count(), sizeof( EditCharAttrib* ), CompareStart );
2037 #if defined __SUNPRO_CC
2038 #pragma enable_warn
2039 #endif
2043 void CharAttribList::OptimizeRanges( SfxItemPool& rItemPool )
2045 for ( USHORT n = 0; n < aAttribs.Count(); n++ )
2047 EditCharAttrib* pAttr = aAttribs.GetObject( n );
2048 for ( USHORT nNext = n+1; nNext < aAttribs.Count(); nNext++ )
2050 EditCharAttrib* p = aAttribs.GetObject( nNext );
2051 if ( !pAttr->IsFeature() && ( p->GetStart() == pAttr->GetEnd() ) && ( p->Which() == pAttr->Which() ) )
2053 if ( *p->GetItem() == *pAttr->GetItem() )
2055 pAttr->GetEnd() = p->GetEnd();
2056 aAttribs.Remove( nNext );
2057 rItemPool.Remove( *p->GetItem() );
2058 delete p;
2060 break; // only 1 attr with same which can start here.
2062 else if ( p->GetStart() > pAttr->GetEnd() )
2064 break;
2070 EditCharAttrib* CharAttribList::FindAttrib( USHORT nWhich, USHORT nPos )
2072 // Rueckwaerts, falls eins dort endet, das naechste startet.
2073 // => Das startende gilt...
2074 USHORT nAttr = aAttribs.Count()-1;
2075 EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr );
2076 while ( pAttr )
2078 if ( ( pAttr->Which() == nWhich ) && pAttr->IsIn(nPos) )
2079 return pAttr;
2080 pAttr = GetAttrib( aAttribs, --nAttr );
2082 return 0;
2085 EditCharAttrib* CharAttribList::FindNextAttrib( USHORT nWhich, USHORT nFromPos ) const
2087 DBG_ASSERT( nWhich, "FindNextAttrib: Which?" );
2088 const USHORT nAttribs = aAttribs.Count();
2089 for ( USHORT nAttr = 0; nAttr < nAttribs; nAttr++ )
2091 EditCharAttrib* pAttr = aAttribs[ nAttr ];
2092 if ( ( pAttr->GetStart() >= nFromPos ) && ( pAttr->Which() == nWhich ) )
2093 return pAttr;
2095 return 0;
2098 BOOL CharAttribList::HasAttrib( USHORT nWhich ) const
2100 for ( USHORT nAttr = aAttribs.Count(); nAttr; )
2102 const EditCharAttrib* pAttr = aAttribs[--nAttr];
2103 if ( pAttr->Which() == nWhich )
2104 return TRUE;
2106 return FALSE;
2109 BOOL CharAttribList::HasAttrib( USHORT nStartPos, USHORT nEndPos ) const
2111 BOOL bAttr = FALSE;
2112 for ( USHORT nAttr = aAttribs.Count(); nAttr && !bAttr; )
2114 const EditCharAttrib* pAttr = aAttribs[--nAttr];
2115 if ( ( pAttr->GetStart() < nEndPos ) && ( pAttr->GetEnd() > nStartPos ) )
2116 return bAttr = TRUE;
2118 return bAttr;
2122 BOOL CharAttribList::HasBoundingAttrib( USHORT nBound )
2124 // Rueckwaerts, falls eins dort endet, das naechste startet.
2125 // => Das startende gilt...
2126 USHORT nAttr = aAttribs.Count()-1;
2127 EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr );
2128 while ( pAttr && ( pAttr->GetEnd() >= nBound ) )
2130 if ( ( pAttr->GetStart() == nBound ) || ( pAttr->GetEnd() == nBound ) )
2131 return TRUE;
2132 pAttr = GetAttrib( aAttribs, --nAttr );
2134 return FALSE;
2137 EditCharAttrib* CharAttribList::FindEmptyAttrib( USHORT nWhich, USHORT nPos )
2139 if ( !bHasEmptyAttribs )
2140 return 0;
2141 USHORT nAttr = 0;
2142 EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr );
2143 while ( pAttr && ( pAttr->GetStart() <= nPos ) )
2145 if ( ( pAttr->GetStart() == nPos ) && ( pAttr->GetEnd() == nPos ) && ( pAttr->Which() == nWhich ) )
2146 return pAttr;
2147 nAttr++;
2148 pAttr = GetAttrib( aAttribs, nAttr );
2150 return 0;
2153 EditCharAttrib* CharAttribList::FindFeature( USHORT nPos ) const
2156 USHORT nAttr = 0;
2157 EditCharAttrib* pNextAttrib = GetAttrib( aAttribs, nAttr );
2159 // erstmal zur gewuenschten Position...
2160 while ( pNextAttrib && ( pNextAttrib->GetStart() < nPos ) )
2162 nAttr++;
2163 pNextAttrib = GetAttrib( aAttribs, nAttr );
2166 // jetzt das Feature suchen...
2167 while ( pNextAttrib && !pNextAttrib->IsFeature() )
2169 nAttr++;
2170 pNextAttrib = GetAttrib( aAttribs, nAttr );
2173 return pNextAttrib;
2177 void CharAttribList::DeleteEmptyAttribs( SfxItemPool& rItemPool )
2179 for ( USHORT nAttr = 0; nAttr < aAttribs.Count(); nAttr++ )
2181 EditCharAttrib* pAttr = aAttribs[nAttr];
2182 if ( pAttr->IsEmpty() )
2184 rItemPool.Remove( *pAttr->GetItem() );
2185 aAttribs.Remove( nAttr );
2186 delete pAttr;
2187 nAttr--;
2190 bHasEmptyAttribs = FALSE;
2193 BOOL CharAttribList::DbgCheckAttribs()
2195 #ifdef DBG_UTIL
2196 BOOL bOK = TRUE;
2197 for ( USHORT nAttr = 0; nAttr < aAttribs.Count(); nAttr++ )
2199 EditCharAttrib* pAttr = aAttribs[nAttr];
2200 if ( pAttr->GetStart() > pAttr->GetEnd() )
2202 bOK = FALSE;
2203 DBG_ERROR( "Attr verdreht" );
2205 else if ( pAttr->IsFeature() && ( pAttr->GetLen() != 1 ) )
2207 bOK = FALSE;
2208 DBG_ERROR( "Feature, Len != 1" );
2211 return bOK;
2212 #else
2213 return TRUE;
2214 #endif
2219 SvxFontTable::SvxFontTable()
2223 SvxFontTable::~SvxFontTable()
2225 SvxFontItem* pItem = First();
2226 while( pItem )
2228 delete pItem;
2229 pItem = Next();
2233 ULONG SvxFontTable::GetId( const SvxFontItem& rFontItem )
2235 SvxFontItem* pItem = First();
2236 while ( pItem )
2238 if ( *pItem == rFontItem )
2239 return GetCurKey();
2240 pItem = Next();
2242 DBG_WARNING( "Font nicht gefunden: GetId()" );
2243 return 0;
2246 SvxColorList::SvxColorList()
2250 SvxColorList::~SvxColorList()
2252 SvxColorItem* pItem = First();
2253 while( pItem )
2255 delete pItem;
2256 pItem = Next();
2260 ULONG SvxColorList::GetId( const SvxColorItem& rColorItem )
2262 SvxColorItem* pItem = First();
2263 while ( pItem )
2265 if ( *pItem == rColorItem )
2266 return GetCurPos();
2267 pItem = Next();
2269 DBG_WARNING( "Color nicht gefunden: GetId()" );
2270 return 0;
2273 EditEngineItemPool::EditEngineItemPool( BOOL bPersistenRefCounts )
2274 : SfxItemPool( String( "EditEngineItemPool", RTL_TEXTENCODING_ASCII_US ), EE_ITEMS_START, EE_ITEMS_END,
2275 aItemInfos, 0, bPersistenRefCounts )
2277 SetVersionMap( 1, 3999, 4015, aV1Map );
2278 SetVersionMap( 2, 3999, 4019, aV2Map );
2279 SetVersionMap( 3, 3997, 4020, aV3Map );
2280 SetVersionMap( 4, 3994, 4022, aV4Map );
2281 SetVersionMap( 5, 3994, 4037, aV5Map );
2283 DBG_ASSERT( EE_DLL(), "EditDLL?!" );
2284 SfxPoolItem** ppDefItems = EE_DLL()->GetGlobalData()->GetDefItems();
2285 SetDefaults( ppDefItems );
2288 EditEngineItemPool::~EditEngineItemPool()
2292 SvStream& EditEngineItemPool::Store( SvStream& rStream ) const
2294 // Bei einem 3.1-Export muess ein Hack eingebaut werden, da BUG im
2295 // SfxItemSet::Load, aber nicht nachtraeglich in 3.1 fixbar.
2297 // Der eingestellte Range muss nach Store erhalten bleiben, weil dann
2298 // erst die ItemSets gespeichert werden...
2300 long nVersion = rStream.GetVersion();
2301 BOOL b31Format = ( nVersion && ( nVersion <= SOFFICE_FILEFORMAT_31 ) )
2302 ? TRUE : FALSE;
2304 EditEngineItemPool* pThis = (EditEngineItemPool*)this;
2305 if ( b31Format )
2306 pThis->SetStoringRange( 3997, 4022 );
2307 else
2308 pThis->SetStoringRange( EE_ITEMS_START, EE_ITEMS_END );
2310 return SfxItemPool::Store( rStream );