xref: /trunk/main/sw/source/filter/rtf/rtfnum.cxx (revision 91568915)
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_sw.hxx"
26 #include <hintids.hxx>
27 #include <tools/stream.hxx>
28 #include <svtools/rtftoken.h>
29 #include <svtools/rtfkeywd.hxx>
30 #include <svl/intitem.hxx>
31 #include <svtools/rtfout.hxx>
32 #include <editeng/lrspitem.hxx>
33 #include <editeng/fontitem.hxx>
34 #include <editeng/fhgtitem.hxx>
35 #include <editeng/wghtitem.hxx>
36 #include <editeng/postitem.hxx>
37 #include <editeng/cmapitem.hxx>
38 #include <editeng/crsditem.hxx>
39 #include <editeng/colritem.hxx>
40 #include <editeng/udlnitem.hxx>
41 #include <editeng/wrlmitem.hxx>
42 #include <shellio.hxx>
43 #include <fltini.hxx>
44 #include <swtypes.hxx>
45 #include <swparrtf.hxx>
46 #include <ndtxt.hxx>
47 #include <doc.hxx>
48 #include <docary.hxx>
49 #include <pam.hxx>
50 #include <charfmt.hxx>
51 #include <charatr.hxx>
52 #include <paratr.hxx>
53 #ifndef _CMDID_H
54 #include <cmdid.h>
55 #endif
56 #include <numrule.hxx>
57 
58 #define RTF_NUMRULE_NAME "RTF_Num"
59 
lcl_GetStyleForNFC(sal_Int16 nNFC)60 static sal_Int16 lcl_GetStyleForNFC( sal_Int16 nNFC)
61 {
62     static const sal_Int16 aMap[] =
63     {
64     style::NumberingType::ARABIC,                   // 0 - Arabic (1, 2, 3)
65     style::NumberingType::ROMAN_UPPER,              // 1 - Uppercase Roman numeral (I, II, III)
66     style::NumberingType::ROMAN_LOWER,              // 2 - Lowercase Roman numeral (i, ii, iii)
67     style::NumberingType::CHARS_UPPER_LETTER_N,     // 3 - Uppercase letter (A, B, C)
68     style::NumberingType::CHARS_LOWER_LETTER_N,     // 4 - Lowercase letter (a, b, c)
69     style::NumberingType::ARABIC,                   // 5 - Ordinal number (1st, 2nd, 3rd)
70     style::NumberingType::ARABIC,                   // 6 - Cardinal text number (One, Two Three)
71     style::NumberingType::ARABIC,                   // 7 - Ordinal text number (First, Second, Third)
72     style::NumberingType::NUMBER_NONE,              // 8 - Not defined
73     style::NumberingType::NUMBER_NONE,              // 9 - Not defined
74     style::NumberingType::NUMBER_LOWER_ZH,          // 10 - Kanji numbering without the digit character (*dbnum1).
75     style::NumberingType::NUMBER_LOWER_ZH,          // 11 - Kanji numbering with the digit character (*dbnum2).
76     style::NumberingType::AIU_HALFWIDTH_JA,         // 12 - phonetic Katakana characters in "aiueo" order (*aiueo).
77     style::NumberingType::IROHA_HALFWIDTH_JA,       // 13 - phonetic katakana characters in "iroha" order (*iroha).
78     style::NumberingType::FULLWIDTH_ARABIC,         // 14 - Double Byte character
79     style::NumberingType::ARABIC,                   // 15 - Single Byte character
80     style::NumberingType::NUMBER_TRADITIONAL_JA,    // 16 - Kanji numbering 3 (*dbnum3).
81     style::NumberingType::ARABIC,                   // 17 - Kanji numbering 4 (*dbnum4).
82     style::NumberingType::ARABIC,                   // 18 - Circle numbering (*circlenum). - decimalEnclosedCircleChinese
83     style::NumberingType::FULLWIDTH_ARABIC,         // 19 - Double-byte Arabic numbering
84     style::NumberingType::AIU_FULLWIDTH_JA,         // 20 - phonetic double-byte Katakana characters (*aiueo*dbchar).
85     style::NumberingType::IROHA_FULLWIDTH_JA,       // 21 - phonetic double-byte katakana characters (*iroha*dbchar).
86     style::NumberingType::ARABIC,                   // 22 - Arabic with leading zero (01, 02, 03, ..., 10, 11)
87     style::NumberingType::CHAR_SPECIAL,             // 23 - Bullet (no number at all)
88     style::NumberingType::HANGUL_SYLLABLE_KO,       // 24 - Korean numbering 2 (*ganada).
89     style::NumberingType::HANGUL_JAMO_KO,           // 25 - Korean numbering 1 (*chosung).
90     style::NumberingType::ARABIC,                   // 26 - Chinese numbering 1 (*gb1). - decimalEnclosedFullstop
91     style::NumberingType::ARABIC,                   // 27 - Chinese numbering 2 (*gb2). - decimalEnclosedParen
92     style::NumberingType::ARABIC,                   // 28 - Chinese numbering 3 (*gb3). - decimalEnclosedCircleChinese
93     style::NumberingType::ARABIC,                   // 29 - Chinese numbering 4 (*gb4). - ideographEnclosedCircle
94     style::NumberingType::TIAN_GAN_ZH,              // 30 - Chinese Zodiac numbering 1 (* zodiac1)
95     style::NumberingType::DI_ZI_ZH,                 // 31 - Chinese Zodiac numbering 2 (* zodiac2)
96     style::NumberingType::ARABIC,                   // 32 - Chinese Zodiac numbering 3 (* zodiac3)
97     style::NumberingType::NUMBER_LOWER_ZH,          // 33 - Taiwanese double-byte numbering 1
98     style::NumberingType::NUMBER_UPPER_ZH_TW,       // 34 - Taiwanese double-byte numbering 2
99     style::NumberingType::NUMBER_LOWER_ZH,          // 35 - Taiwanese double-byte numbering 3
100     style::NumberingType::ARABIC,                   // 36 - Taiwanese double-byte numbering 4
101     style::NumberingType::NUMBER_LOWER_ZH,          // 37 - Chinese double-byte numbering 1
102     style::NumberingType::NUMBER_UPPER_ZH,          // 38 - Chinese double-byte numbering 2
103     style::NumberingType::NUMBER_LOWER_ZH,          // 39 - Chinese double-byte numbering 3
104     style::NumberingType::ARABIC,                   // 40 - Chinese double-byte numbering 4
105     style::NumberingType::NUMBER_HANGUL_KO,         // 41 - Korean double-byte numbering 1
106     style::NumberingType::NUMBER_HANGUL_KO,         // 42 - Korean double-byte numbering 2
107     style::NumberingType::NUMBER_HANGUL_KO,         // 43 - Korean double-byte numbering 3
108     style::NumberingType::NUMBER_LOWER_ZH,          // 44 - Korean double-byte numbering 4
109     style::NumberingType::CHARS_HEBREW,             // 45 - Hebrew non-standard decimal
110     style::NumberingType::CHARS_ARABIC,             // 46 - Arabic Alif Ba Tah
111     style::NumberingType::CHARS_HEBREW,             // 47 - Hebrew Biblical standard
112     style::NumberingType::ARABIC                    // 48 - Arabic Abjad style
113 
114     };
115     const int nLen = sizeof(aMap)/sizeof(aMap[0]);
116     sal_Int16 nRet = style::NumberingType::NUMBER_NONE;
117     if (nNFC>=0 && nNFC<nLen)
118         nRet = aMap[nNFC];
119     else if (nNFC==255)
120         nRet = style::NumberingType::CHAR_SPECIAL;
121     return nRet;
122 }
123 
lcl_ExpandNumFmts(SwNumRule & rRule)124 void lcl_ExpandNumFmts( SwNumRule& rRule )
125 {
126 	// dann noch das NumFormat in alle Ebenen setzen
127 	for( sal_uInt8 n = 1; n < MAXLEVEL; ++n )
128 		if( !rRule.GetNumFmt( n ) )
129 		{
130 			SwNumFmt aNumFmt( rRule.Get( 0 ));
131 			aNumFmt.SetAbsLSpace( aNumFmt.GetAbsLSpace() * ( n + 1 ) );
132 			rRule.Set( n, aNumFmt );
133 		}
134 }
135 
GetNumChrFmt(SwDoc & rDoc,SwNumRule & rRule,sal_uInt8 nNumLvl)136 SfxItemSet& GetNumChrFmt( SwDoc& rDoc, SwNumRule& rRule, sal_uInt8 nNumLvl )
137 {
138 	SwCharFmt* pChrFmt = rRule.Get( nNumLvl ).GetCharFmt();
139 	if( !pChrFmt )
140 	{
141 		String sNm( rRule.GetName() );
142 		( sNm += ' ' ) += String::CreateFromInt32( nNumLvl + 1 );
143 		pChrFmt = rDoc.MakeCharFmt( sNm, rDoc.GetDfltCharFmt() );
144 		if( !rRule.GetNumFmt( nNumLvl ))
145 			rRule.Set( nNumLvl, rRule.Get( nNumLvl ) );
146 		((SwNumFmt*)rRule.GetNumFmt( nNumLvl ))->SetCharFmt( pChrFmt );
147 	}
148 	return (SfxItemSet&)pChrFmt->GetAttrSet();
149 }
150 
ReadListLevel(SwNumRule & rRule,sal_uInt8 nNumLvl)151 void SwRTFParser::ReadListLevel( SwNumRule& rRule, sal_uInt8 nNumLvl )
152 {
153 	int nToken;
154 	int nNumOpenBrakets = 1;		// die erste wurde schon vorher erkannt !!
155 	int nLvlTxtLevel = 0, nLvlNumberLevel = 0;
156 	String sLvlText, sLvlNumber;
157 	SwNumFmt* pCurNumFmt;
158 	String aStringFollow = aEmptyStr;
159 
160 	if( MAXLEVEL >= nNumLvl )
161 	{
162 		pCurNumFmt = (SwNumFmt*)rRule.GetNumFmt( nNumLvl );
163 		pCurNumFmt->SetAbsLSpace( 0 );
164 		pCurNumFmt->SetFirstLineOffset( 0 );
165 	}
166 	else
167 		pCurNumFmt = 0;
168 
169 	while( nNumOpenBrakets && IsParserWorking() )
170 	{
171 		switch( ( nToken = GetNextToken() ))
172 		{
173 		case '}':
174 			if( nNumOpenBrakets )
175 			{
176 				if( nLvlTxtLevel == nNumOpenBrakets )
177 				{
178 					if( DelCharAtEnd( sLvlText, ';' ).Len() &&
179 						sLvlText.Len() && sLvlText.Len() ==
180 						(sal_uInt16)(sLvlText.GetChar( 0 )) + 1 )
181 						sLvlText.Erase( 0, 1 );
182 					nLvlTxtLevel = 0;
183 				}
184 				if( nLvlNumberLevel == nNumOpenBrakets )
185 				{
186 					DelCharAtEnd( sLvlNumber, ';' );
187 					nLvlNumberLevel = 0;
188 				}
189 			}
190 			--nNumOpenBrakets;
191 			break;
192 
193 		case '{':
194 			{
195 				if( RTF_IGNOREFLAG != GetNextToken() )
196 					nToken = SkipToken( -1 );
197 				// Unknown und alle bekannten nicht ausgewerteten Gruppen
198 				// sofort ueberspringen
199 				else if( RTF_UNKNOWNCONTROL != ( nToken = GetNextToken() ))
200 //						RTF_PANOSE != nToken && RTF_FALT != nToken &&
201 //						RTF_FALT != nToken && RTF_FNAME != nToken &&
202 //						RTF_FONTEMB != nToken && RTF_FONTFILE != nToken )
203 					nToken = SkipToken( -2 );
204 				else
205 				{
206 					// gleich herausfiltern
207 					ReadUnknownData();
208 					nToken = GetNextToken();
209 					if( '}' != nToken )
210 						eState = SVPAR_ERROR;
211 					break;
212 				}
213 				++nNumOpenBrakets;
214 			}
215 			break;
216 
217 		case RTF_LEVELNFC:
218 			{
219 				sal_Int16 eType = lcl_GetStyleForNFC( nTokenValue ) ;
220 
221 				if( pCurNumFmt )
222 					pCurNumFmt->SetNumberingType(eType);
223 			}
224 			break;
225 
226 		case RTF_LEVELJC:
227 			{
228 				SvxAdjust eAdj = SVX_ADJUST_LEFT;
229 				switch( nTokenValue )
230 				{
231 				case 1:		eAdj = SVX_ADJUST_CENTER;	break;
232 				case 2:		eAdj = SVX_ADJUST_RIGHT;	break;
233 				}
234 				if( pCurNumFmt )
235 					pCurNumFmt->SetNumAdjust( eAdj );
236 			}
237 			break;
238 
239 		case RTF_LEVELSTARTAT:
240 			if( pCurNumFmt && -1 != nTokenValue )
241 				pCurNumFmt->SetStart( sal_uInt16( nTokenValue ));
242 			break;
243 
244 		case RTF_LEVELTEXT:
245 			nLvlTxtLevel = nNumOpenBrakets;
246 			break;
247 
248 		case RTF_LEVELNUMBERS:
249 			nLvlNumberLevel = nNumOpenBrakets;
250 			break;
251 
252 
253 		case RTF_TEXTTOKEN:
254 			if( nLvlTxtLevel == nNumOpenBrakets )
255 				sLvlText += aToken;
256 			else if( nLvlNumberLevel == nNumOpenBrakets )
257 				sLvlNumber += aToken;
258 			break;
259 
260 		case RTF_LEVELFOLLOW:
261 		  /* removed; waiting for swnum02 to be integrated!
262 			switch (nTokenValue)
263 			{
264 			case 0:
265 				aStringFollow=String('\t');
266 				break;
267 			case 1:
268 				aStringFollow=String(' ');
269 				break;
270 			}
271 			*/
272 			break;
273 
274 		case RTF_LEVELOLD:
275 		case RTF_LEVELPREV:
276 		case RTF_LEVELPREVSPACE:
277 		case RTF_LEVELINDENT:
278 		case RTF_LEVELSPACE:
279 		case RTF_LEVELLEGAL:
280 		case RTF_LEVELNORESTART:
281 			break;
282 
283 		default:
284 			if( pCurNumFmt && (
285 				RTF_CHRFMT == (nToken & ~(0xff | RTF_SWGDEFS) ) ||
286 				RTF_PARFMT == (nToken & ~(0xff | RTF_SWGDEFS) ) ))
287 			{
288 				SfxItemSet aSet( pDoc->GetAttrPool(), aTxtNodeSetRange );
289 				// put the current CharFmtAttr into the set
290 				SfxItemSet& rCFmtSet = GetNumChrFmt( *pDoc, rRule, nNumLvl );
291 				aSet.Put( rCFmtSet );
292 				// and put the current "LRSpace" into the set
293 				{
294                     SvxLRSpaceItem aLR( RES_LR_SPACE );
295 					aLR.SetTxtLeft( pCurNumFmt->GetAbsLSpace() );
296 					aLR.SetTxtFirstLineOfst(pCurNumFmt->GetFirstLineOffset());
297 					aSet.Put( aLR );
298 				}
299 
300 				ReadAttr( nToken, &aSet );
301 
302                 //#i24880# Word appears to ignore char background for numbering
303                 aSet.ClearItem(RES_CHRATR_BACKGROUND);
304 
305 				// put all CharFmt Items into the charfmt
306 				rCFmtSet.Put( aSet );
307 
308 				// test for LRSpace Item. If exist then set all relevant
309 				// values on the numrule format
310 				const SfxPoolItem* pItem;
311 				if( SFX_ITEM_SET == aSet.GetItemState( RES_LR_SPACE,
312 						sal_False, &pItem ))
313 				{
314 					const SvxLRSpaceItem& rLR = *(SvxLRSpaceItem*)pItem;
315                     pCurNumFmt->SetAbsLSpace( static_cast< short >(rLR.GetTxtLeft()) );
316 					pCurNumFmt->SetFirstLineOffset( rLR.GetTxtFirstLineOfst());
317 				}
318 
319 				// dann aus der Vorlage den Font holen
320 				if( SVX_NUM_CHAR_SPECIAL == pCurNumFmt->GetNumberingType() )
321 					pCurNumFmt->SetBulletFont( FindFontOfItem(
322 								pCurNumFmt->GetCharFmt()->GetFont() ) );
323 			}
324 			break;
325 		}
326 	}
327 
328 	if( IsParserWorking() && pCurNumFmt )
329 	{
330 		// dann erzeuge mal die Pre/Postfix-Strings
331 		if( sLvlText.Len() &&
332 			SVX_NUM_CHAR_SPECIAL == pCurNumFmt->GetNumberingType() )
333 		{
334 			pCurNumFmt->SetBulletChar( sLvlText.GetChar( 0 ) );
335 			// dann aus der Vorlage den Font holen
336 			if( pCurNumFmt->GetCharFmt() )
337 				pCurNumFmt->SetBulletFont( FindFontOfItem(
338 						pCurNumFmt->GetCharFmt()->GetFont() ) );
339 		}
340 		else if( sLvlNumber.Len() && sLvlText.Len() )
341 		{
342 			// in sLvlText steht der Text, in sLvlNumber die Position
343 			// der Ebenen in sLvlText
344 			pCurNumFmt->SetPrefix(
345 				sLvlText.Copy( 0, sal_uInt16( sLvlNumber.GetChar( 0 ))-1 ));
346 			pCurNumFmt->SetSuffix( sLvlText.Copy(
347 					sal_uInt16( sLvlNumber.GetChar( sLvlNumber.Len()-1 )) ));
348 			// wieviele Levels stehen im String?
349 			pCurNumFmt->SetIncludeUpperLevels( (sal_uInt8)sLvlNumber.Len() );
350 		}
351 		else
352 		{
353 			pCurNumFmt->SetNumberingType(SVX_NUM_NUMBER_NONE);
354 			pCurNumFmt->SetSuffix( sLvlText );
355 		}
356 
357 		String newSuffix=pCurNumFmt->GetSuffix();
358 		newSuffix+=aStringFollow;
359 		pCurNumFmt->SetSuffix(newSuffix);
360 		/* removed; waiting for swnum02 to be integrated!
361 		if (aStringFollow.GetChar(0)=='\t' && !pCurNumFmt->IsItemize())
362 		{
363 			pCurNumFmt->SetAbsLSpace(0);
364 			pCurNumFmt->SetFirstLineOffset(0);
365 		}
366 		*/
367 	}
368 
369 	SkipToken( -1 );
370 }
371 
ReadListTable()372 void SwRTFParser::ReadListTable()
373 {
374 	int nToken;
375 	int nNumOpenBrakets = 1;		// die erste wurde schon vorher erkannt !!
376 	bNewNumList = sal_True;
377 
378 	sal_uInt8 nNumLvl = 0;
379 	SwNumRule* pCurRule = 0;
380 	SwListEntry aEntry;
381 
382 	while( nNumOpenBrakets && IsParserWorking() )
383 	{
384 		switch( ( nToken = GetNextToken() ))
385 		{
386 		case '}':		if( --nNumOpenBrakets && IsParserWorking() )
387 						{
388 							// Style konnte vollstaendig gelesen werden,
389 							// also ist das noch ein stabiler Status
390 							SaveState( RTF_LISTTABLE );
391 							if( 1 == nNumOpenBrakets )
392 							{
393 								if( aEntry.nListId )
394 									aListArr.push_back( aEntry );
395 								aEntry.Clear();
396 							}
397 						}
398 						break;
399 
400 		case '{':
401 			{
402 				if( RTF_IGNOREFLAG != GetNextToken() )
403 					nToken = SkipToken( -1 );
404 				// Unknown und alle bekannten nicht ausgewerteten Gruppen
405 				// sofort ueberspringen
406 				else if( RTF_UNKNOWNCONTROL != ( nToken = GetNextToken() ))
407 //						RTF_PANOSE != nToken && RTF_FALT != nToken &&
408 //						RTF_FALT != nToken && RTF_FNAME != nToken &&
409 //						RTF_FONTEMB != nToken && RTF_FONTFILE != nToken )
410 					nToken = SkipToken( -2 );
411 				else
412 				{
413 					// gleich herausfiltern
414 					ReadUnknownData();
415 					nToken = GetNextToken();
416 					if( '}' != nToken )
417 						eState = SVPAR_ERROR;
418 					break;
419 				}
420 				++nNumOpenBrakets;
421 			}
422 			break;
423 
424 		case RTF_LIST:
425 			{
426 				if( pCurRule && pCurRule->IsContinusNum() )
427 					lcl_ExpandNumFmts( *pCurRule );
428 
429 				String sTmp( String::CreateFromAscii(
430 					RTL_CONSTASCII_STRINGPARAM( RTF_NUMRULE_NAME " 1" )));
431 				aEntry.nListDocPos = pDoc->MakeNumRule( sTmp );
432 				pCurRule = pDoc->GetNumRuleTbl()[ aEntry.nListDocPos ];
433                 // --> OD 2008-07-08 #i91400#
434                 pCurRule->SetName( pDoc->GetUniqueNumRuleName( &sTmp, sal_False ),
435                                    *pDoc );
436                 // <--
437 				pCurRule->SetAutoRule( sal_False );
438 				nNumLvl = (sal_uInt8)-1;
439 			}
440 			break;
441 
442 		case RTF_LISTID:			aEntry.nListId = nTokenValue;		break;
443 		case RTF_LISTTEMPLATEID:	aEntry.nListTemplateId = nTokenValue; break;
444 
445 		case RTF_LISTRESTARTHDN:
446 			break;
447 		case RTF_LISTNAME:
448 			if (nNextCh=='}') break;  // #118989# empty listnames
449 			if( RTF_TEXTTOKEN == GetNextToken() )
450 			{
451 				String sTmp( DelCharAtEnd( aToken, ';' ));
452 				if( sTmp.Len() && !pDoc->FindNumRulePtr( sTmp ))
453                 {
454                     // --> OD 2008-07-08 #i91400#
455                     pCurRule->SetName( sTmp, *pDoc );
456                     // <--
457                 }
458 			}
459 			SkipGroup();
460 			break;
461 
462 		case RTF_LISTSIMPLE:
463 			pCurRule->SetContinusNum( sal_True );
464 			break;
465 
466 		case RTF_LISTLEVEL:
467 			{
468 				if( ++nNumLvl < MAXLEVEL )
469 					pCurRule->Set( nNumLvl, pCurRule->Get( nNumLvl ));
470 				ReadListLevel( *pCurRule, nNumLvl );
471 			}
472 			break;
473 		}
474 	}
475 
476 	if( pCurRule && pCurRule->IsContinusNum() )
477 		lcl_ExpandNumFmts( *pCurRule );
478 
479 	SkipToken( -1 );		// die schliesende Klammer wird "oben" ausgewertet
480 }
481 
lcl_IsEqual(SwNumRule * pOrigRule,SwNumRule * pRule)482 sal_Bool lcl_IsEqual( SwNumRule* pOrigRule, SwNumRule* pRule )
483 {
484 	sal_Bool bRet = 0;
485 	if( pOrigRule && pRule )
486 	{
487 		bRet =  pOrigRule->GetRuleType() == pRule->GetRuleType() &&
488 				pOrigRule->IsContinusNum() == pRule->IsContinusNum() &&
489 				pOrigRule->IsAbsSpaces() == pRule->IsAbsSpaces();
490 		if( bRet )
491 			for( sal_uInt8 n = 0; bRet && n < MAXLEVEL; ++n )
492 			{
493 				const SwNumFmt* pOFmt = pOrigRule->GetNumFmt( n ),
494 							  *	pFmt = pRule->GetNumFmt( n );
495 				if( pFmt && pOFmt )
496 				{
497 					SwCharFmt* pOCFmt = pOFmt->GetCharFmt(),
498 							 * pCFmt = pFmt->GetCharFmt();
499 					if( pOCFmt && pCFmt )
500 					{
501                         bRet = 0 != (pCFmt->GetAttrSet() == pOCFmt->GetAttrSet());
502 					}
503 					else
504 						bRet = !pCFmt && !pOCFmt;
505 					if( bRet )
506 					{
507 						((SwNumFmt*)pOFmt)->SetCharFmt( 0 );
508 						((SwNumFmt*)pFmt)->SetCharFmt( 0 );
509 						bRet = *pOFmt == *pFmt;
510 						((SwNumFmt*)pOFmt)->SetCharFmt( pOCFmt );
511 						((SwNumFmt*)pFmt)->SetCharFmt( pCFmt );
512 					}
513 				}
514 				else
515 					bRet = !pFmt && !pOFmt;
516 			}
517 	}
518 	return bRet;
519 }
520 
ReadListOverrideTable()521 void SwRTFParser::ReadListOverrideTable()
522 {
523 	int nToken;
524 	int nNumOpenBrakets = 1;		// die erste wurde schon vorher erkannt !!
525 	SwListEntry aEntry;
526 	SwNumRule* pRule = 0, *pOrigRule = 0;
527 	sal_uInt8 nNumLvl = 0;
528 	sal_Bool bOverrideFormat = sal_False, bOverrideStart = sal_False;
529 
530 	while( nNumOpenBrakets && IsParserWorking() )
531 	{
532 		switch( ( nToken = GetNextToken() ))
533 		{
534 		case '}':
535 			if( --nNumOpenBrakets && IsParserWorking() )
536 			{
537 				// Style konnte vollstaendig gelesen werden,
538 				// also ist das noch ein stabiler Status
539 				SaveState( RTF_LISTOVERRIDETABLE );
540 
541 				if( 1 == nNumOpenBrakets )
542 				{
543 					bOverrideFormat = sal_False, bOverrideStart = sal_False;
544 					if( pRule )
545 					{
546 						if( lcl_IsEqual( pOrigRule, pRule ))
547 						{
548 							// no changes on the rule -> use the original rule
549 							aEntry.nListDocPos = pDoc->FindNumRule(
550 													pOrigRule->GetName() );
551 							// delete the temp Rule
552 							RemoveUnusedNumRule( pRule );
553 						}
554 						else if( pRule->IsContinusNum() )
555 							lcl_ExpandNumFmts( *pRule );
556 					}
557 
558 					if( aEntry.nListId && aEntry.nListNo )
559 					{
560 						int nMatch=-1;
561 						for( size_t n = aListArr.size(); n; )
562 						{
563 							if( aListArr[ --n ].nListId == aEntry.nListId)
564 							{
565 								nMatch=n;
566 								break;
567 							}
568 						}
569 						if(nMatch>=0)
570 						{
571                             sal_uInt16 nMatch2 = static_cast< sal_uInt16 >(nMatch);
572                             if (!aListArr[nMatch2].nListNo )
573 							{
574                                 aListArr[nMatch2].nListNo = aEntry.nListNo;
575 							}
576 							else
577 							{
578                                 aEntry.nListDocPos=aListArr[nMatch2].nListDocPos;
579                                 aEntry.nListTemplateId=aListArr[nMatch2].nListTemplateId;
580 								aListArr.push_back( aEntry );
581 							}
582 							if(pOrigRule)
583                                 aListArr[nMatch2].nListDocPos = aEntry.nListDocPos;
584 						}
585 					}
586 					aEntry.Clear();
587 					pOrigRule = 0;
588 					pRule = 0;
589 				}
590 			}
591 			break;
592 
593 		case '{':
594 			{
595 				if( RTF_IGNOREFLAG != GetNextToken() )
596 					nToken = SkipToken( -1 );
597 				// Unknown und alle bekannten nicht ausgewerteten Gruppen
598 				// sofort ueberspringen
599 				else if( RTF_UNKNOWNCONTROL != ( nToken = GetNextToken() ))
600 					nToken = SkipToken( -2 );
601 				else
602 				{
603 					// gleich herausfiltern
604 					ReadUnknownData();
605 					nToken = GetNextToken();
606 					if( '}' != nToken )
607 						eState = SVPAR_ERROR;
608 					break;
609 				}
610 				++nNumOpenBrakets;
611 			}
612 			break;
613 
614 		case RTF_LISTOVERRIDE:		aEntry.Clear();					break;
615 		case RTF_LISTID:			aEntry.nListId = nTokenValue;	break;
616 		case RTF_LS:				aEntry.nListNo = nTokenValue;	break;
617 		case RTF_LISTOVERRIDECOUNT:
618 			if( nTokenValue )
619 			{
620 				pRule = 0;
621 				// dann erzeugen wir mal schnell eine Kopie von der NumRule,
622 				// denn diese wird jetzt mal kurz veraendert.
623 				if( aEntry.nListId )
624 					for( size_t n = 0; n < aListArr.size(); ++n )
625 						if( aListArr[ n ].nListId == aEntry.nListId )
626 						{
627 							pRule = pDoc->GetNumRuleTbl()[
628 												aListArr[ n ].nListDocPos ];
629 							pOrigRule = pRule;
630 
631 							String sTmp( String::CreateFromAscii(
632 								RTL_CONSTASCII_STRINGPARAM( RTF_NUMRULE_NAME " 1" )));
633 							aEntry.nListDocPos = pDoc->MakeNumRule( sTmp, pRule );
634 							pRule = pDoc->GetNumRuleTbl()[ aEntry.nListDocPos ];
635                             // --> OD 2008-07-08 #i91400#
636                             pRule->SetName( pDoc->GetUniqueNumRuleName( &sTmp, sal_False ),
637                                             *pDoc );
638                             // <--
639 							pRule->SetAutoRule( sal_False );
640 							nNumLvl = (sal_uInt8)-1;
641 							aListArr.push_back( aEntry );
642 							break;
643 						}
644 
645 			}
646 			break;
647 
648 		case RTF_LISTLEVEL:
649 			if( pRule && bOverrideFormat )
650 			{
651 				if( ++nNumLvl < MAXLEVEL )
652 					pRule->Set( nNumLvl, pRule->Get( nNumLvl ));
653 				ReadListLevel( *pRule, nNumLvl );
654 			}
655 			break;
656 
657 		case RTF_LEVELSTARTAT:
658 			if( pRule && bOverrideStart )
659 			{
660 			}
661 			break;
662 
663 		case RTF_LISTOVERRIDESTART:
664 			bOverrideStart = sal_True;
665 			break;
666 
667 		case RTF_LISTOVERRIDEFORMAT:
668 			bOverrideFormat = sal_True;
669 			break;
670 
671 		case RTF_LFOLEVEL:
672 			// was fehlt noch?
673 			break;
674 		}
675 	}
676 
677 	// search the outline numrule and set it into the doc
678 	if( GetStyleTbl().Count() )
679 	{
680 		if( !bStyleTabValid )
681 			MakeStyleTab();
682 
683         const SfxPoolItem* pItem( 0 );
684         const SwTxtFmtColl* pColl( 0 );
685         sal_uInt16 nRulePos( USHRT_MAX );
686 		const SwNumRule *pNumRule = 0;
687         SvxRTFStyleType* pStyle = GetStyleTbl().First();
688 		do {
689             // --> OD 2007-12-17 #151213#
690             // suppress deletion of outline list style.
691             // refactoring of code: no assignments in if-condition
692 //            if( MAXLEVEL > pStyle->nOutlineNo &&
693 //                0 != ( pColl = aTxtCollTbl.Get( (sal_uInt16)GetStyleTbl().
694 //                                                        GetCurKey() )) &&
695 //                SFX_ITEM_SET == pColl->GetItemState( RES_PARATR_NUMRULE,
696 //                                                    sal_False, &pItem ) &&
697 //                USHRT_MAX != (nRulePos = pDoc->FindNumRule(
698 //                                ((SwNumRuleItem*)pItem)->GetValue() )) &&
699 //                (pNumRule = pDoc->GetNumRuleTbl()[ nRulePos ])->IsAutoRule() )
700             if ( MAXLEVEL > pStyle->nOutlineNo )
701             {
702                 pColl = aTxtCollTbl.Get( (sal_uInt16)GetStyleTbl().GetCurKey() );
703                 if ( pColl )
704                 {
705                     const SfxItemState eItemState =
706                         pColl->GetItemState( RES_PARATR_NUMRULE, sal_False, &pItem );
707                     if ( eItemState == SFX_ITEM_SET )
708                     {
709                         nRulePos = pDoc->FindNumRule( ((SwNumRuleItem*)pItem)->GetValue() );
710                         if ( nRulePos != USHRT_MAX )
711                         {
712                             pNumRule = pDoc->GetNumRuleTbl()[ nRulePos ];
713                             if ( pNumRule->IsAutoRule() &&
714                                  pNumRule != pDoc->GetOutlineNumRule() )
715                             {
716                                 pDoc->SetOutlineNumRule( *pNumRule );
717                                 pDoc->DelNumRule( pNumRule->GetName() );
718                                 // now pNumRule pointer is invalid !!!
719 
720                                 // now decrement all position in the listtable, which will
721                                 // behind the doc-rule position
722                                 for( size_t n = aListArr.size(); n; )
723                                 {
724                                     SwListEntry& rEntry = aListArr[ --n ];
725                                     if( rEntry.nListDocPos == nRulePos )
726                                         aListArr.erase( aListArr.begin()+n );
727                                     else if( rEntry.nListDocPos > nRulePos )
728                                         --rEntry.nListDocPos;
729                                 }
730                                 break;
731                             }
732                         }
733                     }
734                 }
735             }
736             // <--
737 
738 			pStyle->aAttrSet.ClearItem( FN_PARAM_NUM_LEVEL );
739 
740 		} while( 0 != (pStyle = GetStyleTbl().Next()) );
741 	}
742 
743 	SkipToken( -1 );		// die schliesende Klammer wird "oben" ausgewertet
744 }
745 
GetNumRuleOfListNo(long nListNo,sal_Bool bRemoveFromList)746 SwNumRule* SwRTFParser::GetNumRuleOfListNo( long nListNo, sal_Bool bRemoveFromList )
747 {
748 	SwNumRule* pRet = 0;
749 	SwListEntry* pEntry;
750 	for( size_t n = aListArr.size(); n; )
751 		if( ( pEntry = &aListArr[ --n ])->nListNo == nListNo )
752 		{
753 			if( bRemoveFromList )
754 				aListArr.erase( aListArr.begin()+n );
755 			else
756 			{
757 				pEntry->bRuleUsed = sal_True;
758 				pRet = pDoc->GetNumRuleTbl()[ pEntry->nListDocPos ];
759 			}
760 			break;
761 		}
762 	return pRet;
763 }
764 
RemoveUnusedNumRule(SwNumRule * pRule)765 void SwRTFParser::RemoveUnusedNumRule( SwNumRule* pRule )
766 {
767 	if( pRule )
768 	{
769 		for ( sal_uInt8 nLvl = 0; nLvl < MAXLEVEL; ++nLvl )
770 		{
771 			SwNumFmt& rNFmt = (SwNumFmt&)pRule->Get( nLvl );
772 			SwCharFmt* pCFmt = rNFmt.GetCharFmt();
773 			if( pCFmt )
774 			{
775                 rNFmt.ForgetCharFmt();
776 				if( !pCFmt->GetDepends() )
777 					pDoc->DelCharFmt( pCFmt );
778 			}
779 		}
780 		pDoc->DelNumRule( pRule->GetName() );
781 	}
782 #ifdef DBG_UTIL
783 	else
784 	{
785 		ASSERT( pRule, "NumRulePointer 0 kann nicht geloescht werden" );
786 	}
787 #endif
788 }
789 
RemoveUnusedNumRules()790 void SwRTFParser::RemoveUnusedNumRules()
791 {
792 	SwListEntry* pEntry;
793 	SvPtrarr aDelArr;
794 	size_t n;
795 	for( n = aListArr.size(); n; )
796 	{
797 		if( !( pEntry = &aListArr[ --n ])->bRuleUsed )
798 		{
799 			// really *NOT* used by anyone else?
800 			sal_Bool unused=sal_True;
801             for(size_t j = 0;  j < aListArr.size();  ++j)
802 			{
803 				if (aListArr[n].nListNo==aListArr[j].nListNo)
804 					unused&=!aListArr[j].bRuleUsed;
805 			}
806 			if (unused)
807 			{
808 				void * p = pDoc->GetNumRuleTbl()[pEntry->nListDocPos];
809 				// dont delete named char formats
810 				if( USHRT_MAX == aDelArr.GetPos( p ) &&
811 					((SwNumRule*)p)->GetName().EqualsAscii( RTF_NUMRULE_NAME, 0,
812 									sizeof( RTF_NUMRULE_NAME )) )
813 					aDelArr.Insert( p, aDelArr.Count() );
814 			}
815 		}
816 	}
817 
818 	for( n = aDelArr.Count(); n; )
819 	{
820 		SwNumRule* pDel = (SwNumRule*)aDelArr[ --n ];
821 		RemoveUnusedNumRule( pDel );
822 	}
823 }
824 
FindFontOfItem(const SvxFontItem & rItem) const825 const Font* SwRTFParser::FindFontOfItem( const SvxFontItem& rItem ) const
826 {
827 	SvxRTFFontTbl& rFntTbl = ((SwRTFParser*)this)->GetFontTbl();
828 	const Font* pFnt = rFntTbl.First();
829 	while( pFnt )
830 	{
831 		if( pFnt->GetFamily() == rItem.GetFamily() &&
832 			pFnt->GetName() == rItem.GetFamilyName() &&
833 			pFnt->GetStyleName() == rItem.GetStyleName() &&
834 			pFnt->GetPitch() == rItem.GetPitch() &&
835 			pFnt->GetCharSet() == rItem.GetCharSet() )
836 			return pFnt;
837 
838 		pFnt = rFntTbl.Next();
839 	}
840 	return 0;
841 }
842 
843 
ReadNumSecLevel(int nToken)844 SwNumRule *SwRTFParser::ReadNumSecLevel( int nToken )
845 {
846 	// lese die \pnseclvl - Gruppe
847 	// nTokenValue gibt schon den richtigen Level vor 1 - 9!
848 	sal_uInt8 nLevel = 0;
849 	long nListNo = 0;
850 	sal_Bool bContinus = sal_True;
851 
852 	if( RTF_PNSECLVL == nToken )
853 	{
854 		// suche die Rule - steht unter Nummer 3
855 		nListNo = 3;
856 		bContinus = sal_False;
857 		nLevel = MAXLEVEL <= (unsigned long) nTokenValue ? MAXLEVEL - 1
858 			: (!nTokenValue ? 0 : sal_uInt8( nTokenValue - 1 ));
859 	}
860 	else
861 	{
862 		switch( nToken = GetNextToken() )
863 		{
864 		case RTF_PNLVL:			nListNo = 3;
865 								bContinus = sal_False;
866 								nLevel = MAXLEVEL <= (unsigned long) nTokenValue
867 													? MAXLEVEL - 1
868                                     : (!nTokenValue ? 0 : sal_uInt8( nTokenValue-1 ));
869 								break;
870 
871 		case RTF_PNLVLBODY:
872             nListNo = 2;
873             break;
874 		case RTF_PNLVLBLT:
875             nListNo = 1;
876             break;
877 		case RTF_PNLVLCONT:
878     		SkipGroup();
879 			return 0;
880 		default:
881 			SkipGroup();
882 			return 0;
883 		}
884 	}
885 
886 	// suche die Rule - steht unter Nummer 3
887     sal_uInt16 nNewFlag = static_cast< sal_uInt16 >(1 << nListNo);
888 	SwNumRule* pCurRule = GetNumRuleOfListNo( nListNo,
889 										0 != ( nNewNumSectDef & nNewFlag ) );
890 	if( !pCurRule )
891 	{
892 		// dann muessen wir die mal anlegen
893 		nNewNumSectDef &= ~nNewFlag;
894 		String sTmp( String::CreateFromAscii(
895 						RTL_CONSTASCII_STRINGPARAM( RTF_NUMRULE_NAME " 1" )));
896 		SwListEntry aEntry( nListNo, 0, pDoc->MakeNumRule( sTmp ));
897 		aEntry.nListNo = nListNo;
898 		aListArr.push_back( aEntry );
899 		pCurRule = pDoc->GetNumRuleTbl()[ aEntry.nListDocPos ];
900         // --> OD 2008-07-08 #i91400#
901         pCurRule->SetName( pDoc->GetUniqueNumRuleName( &sTmp, sal_False ), *pDoc );
902         // <--
903 		pCurRule->SetAutoRule( sal_False );
904 		pCurRule->SetContinusNum( bContinus );
905 	}
906 
907 	if( !pCurRule->GetNumFmt( nLevel ))
908 		pCurRule->Set( nLevel, pCurRule->Get( nLevel ));
909 	SwNumFmt* pCurNumFmt = (SwNumFmt*)pCurRule->GetNumFmt( nLevel );
910 	if( RTF_PNLVLBLT == nToken )
911 		pCurNumFmt->SetNumberingType(SVX_NUM_CHAR_SPECIAL);
912 	pCurNumFmt->SetSuffix( aEmptyStr );
913 	pCurNumFmt->SetPrefix( aEmptyStr );
914 	pCurNumFmt->SetNumberingType(SVX_NUM_NUMBER_NONE);
915 
916 	if( bStyleTabValid && RTF_PNSECLVL != nToken )
917 	{
918 		// dann den akt. Lvl und Rule am Absatz setzen.
919 		// Dieses muss aber in den vorherigen "Kontext", sprich in den vor
920 		// der Klammer offenen Attrset. Darum das SetNewGroup davor und dahinter
921 		SetNewGroup( sal_False );
922 		GetAttrSet().Put( SfxUInt16Item( FN_PARAM_NUM_LEVEL, nLevel ));
923 		GetAttrSet().Put( SwNumRuleItem( pCurRule->GetName() ));
924 		SetNewGroup( sal_True );
925 	}
926 
927 	FontUnderline eUnderline;
928 	int nNumOpenBrakets = 1;		// die erste wurde schon vorher erkannt !!
929 	while( nNumOpenBrakets && IsParserWorking() )
930 	{
931 		switch( ( nToken = GetNextToken() ))
932 		{
933 		case '}':
934 			if( --nNumOpenBrakets && IsParserWorking() )
935 			{
936 				// Style konnte vollstaendig gelesen werden,
937 				// also ist das noch ein stabiler Status
938 				SaveState( RTF_PNSECLVL );
939 			}
940 			break;
941 
942 		case '{':
943 			{
944 				if( RTF_IGNOREFLAG != GetNextToken() )
945 					nToken = SkipToken( -1 );
946 				// Unknown und alle bekannten nicht ausgewerteten Gruppen
947 				// sofort ueberspringen
948 				else if( RTF_UNKNOWNCONTROL != ( nToken = GetNextToken() ))
949 					nToken = SkipToken( -2 );
950 				else
951 				{
952 					// gleich herausfiltern
953 					ReadUnknownData();
954 					nToken = GetNextToken();
955 					if( '}' != nToken )
956 						eState = SVPAR_ERROR;
957 					break;
958 				}
959 				++nNumOpenBrakets;
960 			}
961 			break;
962 
963 		case RTF_PNCARD:
964 		case RTF_PNORD:
965 		case RTF_PNORDT:
966 		case RTF_PNDEC: 	pCurNumFmt->SetNumberingType(SVX_NUM_ARABIC);				break;
967 		case RTF_PNUCLTR:	pCurNumFmt->SetNumberingType(SVX_NUM_CHARS_UPPER_LETTER_N);	break;
968 		case RTF_PNUCRM:    pCurNumFmt->SetNumberingType(SVX_NUM_ROMAN_UPPER);			break;
969 		case RTF_PNLCLTR:   pCurNumFmt->SetNumberingType(SVX_NUM_CHARS_LOWER_LETTER_N);	break;
970 		case RTF_PNLCRM:    pCurNumFmt->SetNumberingType(SVX_NUM_ROMAN_LOWER);			break;
971 
972 		case RTF_PNF:
973 			{
974 				const Font& rSVFont = GetFont( sal_uInt16(nTokenValue) );
975 				GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put(
976 							SvxFontItem( rSVFont.GetFamily(),
977 								rSVFont.GetName(), rSVFont.GetStyleName(),
978                                 rSVFont.GetPitch(), rSVFont.GetCharSet(),
979                                             RES_CHRATR_FONT ));
980 				if( SVX_NUM_CHAR_SPECIAL == pCurNumFmt->GetNumberingType() )
981 					pCurNumFmt->SetBulletFont( &rSVFont );
982 			}
983 			break;
984 		case RTF_PNFS:
985 			{
986 				if( -1 == nTokenValue )
987 					nTokenValue = 240;
988 				else
989 					nTokenValue *= 10;
990 				GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put(
991                             SvxFontHeightItem( (const sal_uInt16)nTokenValue, 100, RES_CHRATR_FONTSIZE ));
992 			}
993 			break;
994 
995 		case RTF_PNB:
996 			{
997 				GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put( SvxWeightItem(
998                                 nTokenValue ? WEIGHT_BOLD : WEIGHT_NORMAL, RES_CHRATR_WEIGHT ));
999 			}
1000 			break;
1001 
1002 		case RTF_PNI:
1003 			{
1004 				GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put( SvxPostureItem(
1005                             nTokenValue ? ITALIC_NORMAL : ITALIC_NONE, RES_CHRATR_POSTURE ));
1006 			}
1007 			break;
1008 
1009 		case RTF_PNCAPS:
1010 		case RTF_PNSCAPS:
1011 			{
1012 				GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put( SvxCaseMapItem(
1013 								nTokenValue ? SVX_CASEMAP_KAPITAELCHEN
1014                                             : SVX_CASEMAP_NOT_MAPPED, RES_CHRATR_CASEMAP ));
1015 			}
1016 			break;
1017 		case RTF_PNSTRIKE:
1018 			{
1019 				GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put( SvxCrossedOutItem(
1020                         nTokenValue ? STRIKEOUT_SINGLE : STRIKEOUT_NONE, RES_CHRATR_CROSSEDOUT ));
1021 			}
1022 			break;
1023 
1024 		case RTF_PNCF:
1025 			{
1026 				GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put( SvxColorItem(
1027                             GetColor( sal_uInt16(nTokenValue) ), RES_CHRATR_COLOR ));
1028 			}
1029 			break;
1030 
1031 
1032 		case RTF_PNUL:
1033 			eUnderline = nTokenValue ? UNDERLINE_SINGLE : UNDERLINE_NONE;
1034 			goto NUMATTR_SETUNDERLINE;
1035 		case RTF_PNULD:
1036 			eUnderline = UNDERLINE_DOTTED;
1037 			goto NUMATTR_SETUNDERLINE;
1038 		case RTF_PNULDB:
1039 			eUnderline = UNDERLINE_DOUBLE;
1040 			goto NUMATTR_SETUNDERLINE;
1041 		case RTF_PNULNONE:
1042 			eUnderline = UNDERLINE_NONE;
1043 			goto NUMATTR_SETUNDERLINE;
1044 		case RTF_PNULW:
1045 			{
1046 				GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put(
1047                                     SvxWordLineModeItem( sal_True, RES_CHRATR_WORDLINEMODE ));
1048 			}
1049 			eUnderline = UNDERLINE_SINGLE;
1050 			goto NUMATTR_SETUNDERLINE;
1051 
1052 NUMATTR_SETUNDERLINE:
1053 			{
1054 				GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put(
1055                         SvxUnderlineItem( eUnderline, RES_CHRATR_UNDERLINE ));
1056 			}
1057 			break;
1058 
1059 		case RTF_PNINDENT:
1060 			if( 0 > short( nTokenValue ) )
1061 				nTokenValue = - (short)nTokenValue;
1062 			pCurNumFmt->SetFirstLineOffset( - short( nTokenValue ));
1063 			pCurNumFmt->SetAbsLSpace( (nLevel + 1 ) * sal_uInt16( nTokenValue ));
1064 			break;
1065 		case RTF_PNSP:
1066 			pCurNumFmt->SetCharTextDistance( sal_uInt16( nTokenValue ));
1067 			break;
1068 
1069 		case RTF_PNPREV:
1070 			if( nLevel )
1071 			{
1072 				sal_uInt8 nPrev = 2, nLast = nLevel;
1073 				while( nLast && 1 < pCurRule->Get( --nLast ).GetIncludeUpperLevels() )
1074 					++nPrev;
1075 				pCurNumFmt->SetIncludeUpperLevels( nPrev );
1076 			}
1077 			break;
1078 
1079 		case RTF_PNQC:	pCurNumFmt->SetNumAdjust( SVX_ADJUST_CENTER ); 	break;
1080 		case RTF_PNQL:	pCurNumFmt->SetNumAdjust( SVX_ADJUST_LEFT ); 		break;
1081 		case RTF_PNQR:	pCurNumFmt->SetNumAdjust( SVX_ADJUST_RIGHT );		break;
1082 
1083 		case RTF_PNSTART:
1084 			pCurNumFmt->SetStart( sal_uInt16( nTokenValue ));
1085 			break;
1086 
1087 		case RTF_PNNUMONCE:
1088 		case RTF_PNACROSS:
1089 		case RTF_PNHANG:
1090 		case RTF_PNRESTART:		break;
1091 
1092 		case RTF_PNTXTA:
1093 			{
1094 				String sTmp;
1095 				GetTextToEndGroup( sTmp );
1096 				if( SVX_NUM_CHAR_SPECIAL == pCurNumFmt->GetNumberingType() )
1097 				{
1098 					pCurNumFmt->SetBulletChar( sTmp.GetChar( 0 ) );
1099 					if( pCurNumFmt->GetCharFmt() )
1100 						pCurNumFmt->SetBulletFont( FindFontOfItem(
1101 									pCurNumFmt->GetCharFmt()->GetFont() ) );
1102 					sTmp.Erase();
1103 				}
1104 				pCurNumFmt->SetSuffix( sTmp );
1105 			}
1106 			break;
1107 
1108 		case RTF_PNTXTB:
1109 			{
1110 				String sTmp;
1111 				pCurNumFmt->SetPrefix( GetTextToEndGroup( sTmp ) );
1112 			}
1113 			break;
1114 		}
1115 	}
1116 
1117 	// falls vollstaendige Numerierung an ist und das Zeichen davor ein
1118 	// Punkt ist, dann will RTF den Punkt als Trenner zwischen den Ebenen
1119 	// haben - das haben wir aber schon als default
1120 	if( 1 < pCurNumFmt->GetIncludeUpperLevels() &&
1121 		1 == pCurNumFmt->GetPrefix().Len() &&
1122 		'.' == pCurNumFmt->GetPrefix().GetChar( 0 ) &&
1123 		SVX_NUM_CHAR_SPECIAL != pCurNumFmt->GetNumberingType() )
1124 		pCurNumFmt->SetPrefix( aEmptyStr );
1125 
1126 	// falls das ein nicht numerierter Absatz mit ein Prefix-Text mit
1127 	// einem Zeichen ist, dann setze den als Bulletzeichen
1128 	if( pCurNumFmt->GetCharFmt() && SVX_NUM_NUMBER_NONE == pCurNumFmt->GetNumberingType() &&
1129 		3 == nListNo && 1 == pCurNumFmt->GetPrefix().Len() )
1130 	{
1131 		SwCharFmt* pChFmt = pCurNumFmt->GetCharFmt();
1132 		pCurNumFmt->SetNumberingType(SVX_NUM_CHAR_SPECIAL);
1133 		pCurNumFmt->SetBulletFont( FindFontOfItem( pChFmt->GetFont() ) );
1134 
1135 		pCurNumFmt->SetBulletChar( pCurNumFmt->GetPrefix().GetChar( 0 ) );
1136 		pCurNumFmt->SetPrefix( aEmptyStr );
1137 
1138 		// den Font oder sogar das gesamte CharFormat loeschen?
1139 		if( SFX_ITEM_SET == pChFmt->GetItemState( RES_CHRATR_FONT, sal_False ))
1140 		{
1141 			if( 1 == pChFmt->GetAttrSet().Count() )
1142 			{
1143 				pCurNumFmt->SetCharFmt( 0 );
1144 				pDoc->DelCharFmt( pChFmt );
1145 			}
1146 			else
1147                 pChFmt->ResetFmtAttr( RES_CHRATR_FONT );
1148 		}
1149 	}
1150 
1151 	SkipToken( -1 );		// die schliesende Klammer wird "oben" ausgewertet
1152     return pCurRule;
1153 }
1154 
1155 
1156 /*  */
1157 
1158 // dann noch die Ausgabe-Funktionen (nur fuer WinWord 97)
1159 
lcl_IsExportNumRule(const SwNumRule & rRule,sal_uInt8 * pEnd=0)1160 sal_Bool lcl_IsExportNumRule( const SwNumRule& rRule, sal_uInt8* pEnd = 0 )
1161 {
1162 	sal_uInt8 nEnd = MAXLEVEL;
1163 	while( nEnd-- && !rRule.GetNumFmt( nEnd ))
1164 		;
1165 	++nEnd;
1166 
1167 	const SwNumFmt* pNFmt;
1168 	sal_uInt8 nLvl;
1169 
1170 	for( nLvl = 0; nLvl < nEnd; ++nLvl )
1171 		if( SVX_NUM_NUMBER_NONE != ( pNFmt = &rRule.Get( nLvl ))
1172 			->GetNumberingType() || pNFmt->GetPrefix().Len() ||
1173 			(pNFmt->GetSuffix().Len() && pNFmt->GetSuffix() != aDotStr ))
1174 			break;
1175 
1176 	if( pEnd )
1177 		*pEnd = nEnd;
1178 	return nLvl != nEnd;
1179 }
1180