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