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