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