diff options
Diffstat (limited to 'sw/source/filter/rtf/rtfnum.cxx')
-rw-r--r-- | sw/source/filter/rtf/rtfnum.cxx | 1460 |
1 files changed, 1460 insertions, 0 deletions
diff --git a/sw/source/filter/rtf/rtfnum.cxx b/sw/source/filter/rtf/rtfnum.cxx new file mode 100644 index 000000000000..507f35375ed6 --- /dev/null +++ b/sw/source/filter/rtf/rtfnum.cxx @@ -0,0 +1,1460 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sw.hxx" +#include <hintids.hxx> +#include <tools/stream.hxx> +#include <svtools/rtftoken.h> +#include <svtools/rtfkeywd.hxx> +#include <svl/intitem.hxx> +#include <svtools/rtfout.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/cmapitem.hxx> +#include <editeng/crsditem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/wrlmitem.hxx> +#include <shellio.hxx> +#include <fltini.hxx> +#include <swtypes.hxx> +#include <swparrtf.hxx> +#include <wrtrtf.hxx> +#include <ndtxt.hxx> +#include <doc.hxx> +#include <docary.hxx> +#include <pam.hxx> +#include <charfmt.hxx> +#include <charatr.hxx> +#include <paratr.hxx> +#ifndef _CMDID_H +#include <cmdid.h> +#endif +#include <numrule.hxx> + +#define RTF_NUMRULE_NAME "RTF_Num" + +SV_IMPL_VARARR( SwListArr, SwListEntry ) + + +void lcl_ExpandNumFmts( SwNumRule& rRule ) +{ + // dann noch das NumFormat in alle Ebenen setzen + for( BYTE n = 1; n < MAXLEVEL; ++n ) + if( !rRule.GetNumFmt( n ) ) + { + SwNumFmt aNumFmt( rRule.Get( 0 )); + aNumFmt.SetAbsLSpace( aNumFmt.GetAbsLSpace() * ( n + 1 ) ); + rRule.Set( n, aNumFmt ); + } +} + +SfxItemSet& GetNumChrFmt( SwDoc& rDoc, SwNumRule& rRule, BYTE nNumLvl ) +{ + SwCharFmt* pChrFmt = rRule.Get( nNumLvl ).GetCharFmt(); + if( !pChrFmt ) + { + String sNm( rRule.GetName() ); + ( sNm += ' ' ) += String::CreateFromInt32( nNumLvl + 1 ); + pChrFmt = rDoc.MakeCharFmt( sNm, rDoc.GetDfltCharFmt() ); + if( !rRule.GetNumFmt( nNumLvl )) + rRule.Set( nNumLvl, rRule.Get( nNumLvl ) ); + ((SwNumFmt*)rRule.GetNumFmt( nNumLvl ))->SetCharFmt( pChrFmt ); + } + return (SfxItemSet&)pChrFmt->GetAttrSet(); +} + +void SwRTFParser::ReadListLevel( SwNumRule& rRule, BYTE nNumLvl ) +{ + int nToken; + int nNumOpenBrakets = 1; // die erste wurde schon vorher erkannt !! + int nLvlTxtLevel = 0, nLvlNumberLevel = 0; + String sLvlText, sLvlNumber; + SwNumFmt* pCurNumFmt; + String aStringFollow = aEmptyStr; + + if( MAXLEVEL >= nNumLvl ) + { + pCurNumFmt = (SwNumFmt*)rRule.GetNumFmt( nNumLvl ); + pCurNumFmt->SetAbsLSpace( 0 ); + pCurNumFmt->SetFirstLineOffset( 0 ); + } + else + pCurNumFmt = 0; + + while( nNumOpenBrakets && IsParserWorking() ) + { + switch( ( nToken = GetNextToken() )) + { + case '}': + if( nNumOpenBrakets ) + { + if( nLvlTxtLevel == nNumOpenBrakets ) + { + if( DelCharAtEnd( sLvlText, ';' ).Len() && + sLvlText.Len() && sLvlText.Len() == + (USHORT)(sLvlText.GetChar( 0 )) + 1 ) + sLvlText.Erase( 0, 1 ); + nLvlTxtLevel = 0; + } + if( nLvlNumberLevel == nNumOpenBrakets ) + { + DelCharAtEnd( sLvlNumber, ';' ); + nLvlNumberLevel = 0; + } + } + --nNumOpenBrakets; + break; + + case '{': + { + if( RTF_IGNOREFLAG != GetNextToken() ) + nToken = SkipToken( -1 ); + // Unknown und alle bekannten nicht ausgewerteten Gruppen + // sofort ueberspringen + else if( RTF_UNKNOWNCONTROL != ( nToken = GetNextToken() )) +// RTF_PANOSE != nToken && RTF_FALT != nToken && +// RTF_FALT != nToken && RTF_FNAME != nToken && +// RTF_FONTEMB != nToken && RTF_FONTFILE != nToken ) + nToken = SkipToken( -2 ); + else + { + // gleich herausfiltern + ReadUnknownData(); + nToken = GetNextToken(); + if( '}' != nToken ) + eState = SVPAR_ERROR; + break; + } + ++nNumOpenBrakets; + } + break; + + case RTF_LEVELNFC: + { + sal_Int16 eType = SVX_NUM_ARABIC; + switch( nTokenValue ) + { + case 1: eType = SVX_NUM_ROMAN_UPPER; break; + case 2: eType = SVX_NUM_ROMAN_LOWER; break; + case 3: eType = SVX_NUM_CHARS_UPPER_LETTER_N; break; + case 4: eType = SVX_NUM_CHARS_LOWER_LETTER_N; break; + case 255: + case 23: eType = SVX_NUM_CHAR_SPECIAL; break; + } + if( pCurNumFmt ) + pCurNumFmt->SetNumberingType(eType); + } + break; + + case RTF_LEVELJC: + { + SvxAdjust eAdj = SVX_ADJUST_LEFT; + switch( nTokenValue ) + { + case 1: eAdj = SVX_ADJUST_CENTER; break; + case 2: eAdj = SVX_ADJUST_RIGHT; break; + } + if( pCurNumFmt ) + pCurNumFmt->SetNumAdjust( eAdj ); + } + break; + + case RTF_LEVELSTARTAT: + if( pCurNumFmt && -1 != nTokenValue ) + pCurNumFmt->SetStart( USHORT( nTokenValue )); + break; + + case RTF_LEVELTEXT: + nLvlTxtLevel = nNumOpenBrakets; + break; + + case RTF_LEVELNUMBERS: + nLvlNumberLevel = nNumOpenBrakets; + break; + + + case RTF_TEXTTOKEN: + if( nLvlTxtLevel == nNumOpenBrakets ) + sLvlText += aToken; + else if( nLvlNumberLevel == nNumOpenBrakets ) + sLvlNumber += aToken; + break; + + case RTF_LEVELFOLLOW: + /* removed; waiting for swnum02 to be integrated! + switch (nTokenValue) + { + case 0: + aStringFollow=String('\t'); + break; + case 1: + aStringFollow=String(' '); + break; + } + */ + break; + + case RTF_LEVELOLD: + case RTF_LEVELPREV: + case RTF_LEVELPREVSPACE: + case RTF_LEVELINDENT: + case RTF_LEVELSPACE: + case RTF_LEVELLEGAL: + case RTF_LEVELNORESTART: + break; + + default: + if( pCurNumFmt && ( + RTF_CHRFMT == (nToken & ~(0xff | RTF_SWGDEFS) ) || + RTF_PARFMT == (nToken & ~(0xff | RTF_SWGDEFS) ) )) + { + SfxItemSet aSet( pDoc->GetAttrPool(), aTxtNodeSetRange ); + // put the current CharFmtAttr into the set + SfxItemSet& rCFmtSet = GetNumChrFmt( *pDoc, rRule, nNumLvl ); + aSet.Put( rCFmtSet ); + // and put the current "LRSpace" into the set + { + SvxLRSpaceItem aLR( RES_LR_SPACE ); + aLR.SetTxtLeft( pCurNumFmt->GetAbsLSpace() ); + aLR.SetTxtFirstLineOfst(pCurNumFmt->GetFirstLineOffset()); + aSet.Put( aLR ); + } + + ReadAttr( nToken, &aSet ); + + //#i24880# Word appears to ignore char background for numbering + aSet.ClearItem(RES_CHRATR_BACKGROUND); + + // put all CharFmt Items into the charfmt + rCFmtSet.Put( aSet ); + + // test for LRSpace Item. If exist then set all relevant + // values on the numrule format + const SfxPoolItem* pItem; + if( SFX_ITEM_SET == aSet.GetItemState( RES_LR_SPACE, + FALSE, &pItem )) + { + const SvxLRSpaceItem& rLR = *(SvxLRSpaceItem*)pItem; + pCurNumFmt->SetAbsLSpace( static_cast< short >(rLR.GetTxtLeft()) ); + pCurNumFmt->SetFirstLineOffset( rLR.GetTxtFirstLineOfst()); + } + + // dann aus der Vorlage den Font holen + if( SVX_NUM_CHAR_SPECIAL == pCurNumFmt->GetNumberingType() ) + pCurNumFmt->SetBulletFont( FindFontOfItem( + pCurNumFmt->GetCharFmt()->GetFont() ) ); + } + break; + } + } + + if( IsParserWorking() && pCurNumFmt ) + { + // dann erzeuge mal die Pre/Postfix-Strings + if( sLvlText.Len() && + SVX_NUM_CHAR_SPECIAL == pCurNumFmt->GetNumberingType() ) + { + pCurNumFmt->SetBulletChar( sLvlText.GetChar( 0 ) ); + // dann aus der Vorlage den Font holen + if( pCurNumFmt->GetCharFmt() ) + pCurNumFmt->SetBulletFont( FindFontOfItem( + pCurNumFmt->GetCharFmt()->GetFont() ) ); + } + else if( sLvlNumber.Len() && sLvlText.Len() ) + { + // in sLvlText steht der Text, in sLvlNumber die Position + // der Ebenen in sLvlText + pCurNumFmt->SetPrefix( + sLvlText.Copy( 0, USHORT( sLvlNumber.GetChar( 0 ))-1 )); + pCurNumFmt->SetSuffix( sLvlText.Copy( + USHORT( sLvlNumber.GetChar( sLvlNumber.Len()-1 )) )); + // wieviele Levels stehen im String? + pCurNumFmt->SetIncludeUpperLevels( (BYTE)sLvlNumber.Len() ); + } + else + { + pCurNumFmt->SetNumberingType(SVX_NUM_NUMBER_NONE); + pCurNumFmt->SetSuffix( sLvlText ); + } + + String newSuffix=pCurNumFmt->GetSuffix(); + newSuffix+=aStringFollow; + pCurNumFmt->SetSuffix(newSuffix); + /* removed; waiting for swnum02 to be integrated! + if (aStringFollow.GetChar(0)=='\t' && !pCurNumFmt->IsItemize()) + { + pCurNumFmt->SetAbsLSpace(0); + pCurNumFmt->SetFirstLineOffset(0); + } + */ + } + + SkipToken( -1 ); +} + +void SwRTFParser::ReadListTable() +{ + int nToken; + int nNumOpenBrakets = 1; // die erste wurde schon vorher erkannt !! + bNewNumList = TRUE; + + BYTE nNumLvl = 0; + SwNumRule* pCurRule = 0; + SwListEntry aEntry; + + while( nNumOpenBrakets && IsParserWorking() ) + { + switch( ( nToken = GetNextToken() )) + { + case '}': if( --nNumOpenBrakets && IsParserWorking() ) + { + // Style konnte vollstaendig gelesen werden, + // also ist das noch ein stabiler Status + SaveState( RTF_LISTTABLE ); + if( 1 == nNumOpenBrakets ) + { + if( aEntry.nListId ) + aListArr.Insert( aEntry, aListArr.Count() ); + aEntry.Clear(); + } + } + break; + + case '{': + { + if( RTF_IGNOREFLAG != GetNextToken() ) + nToken = SkipToken( -1 ); + // Unknown und alle bekannten nicht ausgewerteten Gruppen + // sofort ueberspringen + else if( RTF_UNKNOWNCONTROL != ( nToken = GetNextToken() )) +// RTF_PANOSE != nToken && RTF_FALT != nToken && +// RTF_FALT != nToken && RTF_FNAME != nToken && +// RTF_FONTEMB != nToken && RTF_FONTFILE != nToken ) + nToken = SkipToken( -2 ); + else + { + // gleich herausfiltern + ReadUnknownData(); + nToken = GetNextToken(); + if( '}' != nToken ) + eState = SVPAR_ERROR; + break; + } + ++nNumOpenBrakets; + } + break; + + case RTF_LIST: + { + if( pCurRule && pCurRule->IsContinusNum() ) + lcl_ExpandNumFmts( *pCurRule ); + + String sTmp( String::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( RTF_NUMRULE_NAME " 1" ))); + aEntry.nListDocPos = pDoc->MakeNumRule( sTmp ); + pCurRule = pDoc->GetNumRuleTbl()[ aEntry.nListDocPos ]; + // --> OD 2008-07-08 #i91400# + pCurRule->SetName( pDoc->GetUniqueNumRuleName( &sTmp, FALSE ), + *pDoc ); + // <-- + pCurRule->SetAutoRule( FALSE ); + nNumLvl = (BYTE)-1; + } + break; + + case RTF_LISTID: aEntry.nListId = nTokenValue; break; + case RTF_LISTTEMPLATEID: aEntry.nListTemplateId = nTokenValue; break; + + case RTF_LISTRESTARTHDN: + break; + case RTF_LISTNAME: + if (nNextCh=='}') break; // #118989# empty listnames + if( RTF_TEXTTOKEN == GetNextToken() ) + { + String sTmp( DelCharAtEnd( aToken, ';' )); + if( sTmp.Len() && !pDoc->FindNumRulePtr( sTmp )) + { + // --> OD 2008-07-08 #i91400# + pCurRule->SetName( sTmp, *pDoc ); + // <-- + } + } + SkipGroup(); + break; + + case RTF_LISTSIMPLE: + pCurRule->SetContinusNum( TRUE ); + break; + + case RTF_LISTLEVEL: + { + if( ++nNumLvl < MAXLEVEL ) + pCurRule->Set( nNumLvl, pCurRule->Get( nNumLvl )); + ReadListLevel( *pCurRule, nNumLvl ); + } + break; + } + } + + if( pCurRule && pCurRule->IsContinusNum() ) + lcl_ExpandNumFmts( *pCurRule ); + + SkipToken( -1 ); // die schliesende Klammer wird "oben" ausgewertet +} + +BOOL lcl_IsEqual( SwNumRule* pOrigRule, SwNumRule* pRule ) +{ + BOOL bRet = 0; + if( pOrigRule && pRule ) + { + bRet = pOrigRule->GetRuleType() == pRule->GetRuleType() && + pOrigRule->IsContinusNum() == pRule->IsContinusNum() && + pOrigRule->IsAbsSpaces() == pRule->IsAbsSpaces(); + if( bRet ) + for( BYTE n = 0; bRet && n < MAXLEVEL; ++n ) + { + const SwNumFmt* pOFmt = pOrigRule->GetNumFmt( n ), + * pFmt = pRule->GetNumFmt( n ); + if( pFmt && pOFmt ) + { + SwCharFmt* pOCFmt = pOFmt->GetCharFmt(), + * pCFmt = pFmt->GetCharFmt(); + if( pOCFmt && pCFmt ) + { + bRet = 0 != (pCFmt->GetAttrSet() == pOCFmt->GetAttrSet()); + } + else + bRet = !pCFmt && !pOCFmt; + if( bRet ) + { + ((SwNumFmt*)pOFmt)->SetCharFmt( 0 ); + ((SwNumFmt*)pFmt)->SetCharFmt( 0 ); + bRet = *pOFmt == *pFmt; + ((SwNumFmt*)pOFmt)->SetCharFmt( pOCFmt ); + ((SwNumFmt*)pFmt)->SetCharFmt( pCFmt ); + } + } + else + bRet = !pFmt && !pOFmt; + } + } + return bRet; +} + +void SwRTFParser::ReadListOverrideTable() +{ + int nToken; + int nNumOpenBrakets = 1; // die erste wurde schon vorher erkannt !! + SwListEntry aEntry; + SwNumRule* pRule = 0, *pOrigRule = 0; + BYTE nNumLvl = 0; + BOOL bOverrideFormat = FALSE, bOverrideStart = FALSE; + + while( nNumOpenBrakets && IsParserWorking() ) + { + switch( ( nToken = GetNextToken() )) + { + case '}': + if( --nNumOpenBrakets && IsParserWorking() ) + { + // Style konnte vollstaendig gelesen werden, + // also ist das noch ein stabiler Status + SaveState( RTF_LISTOVERRIDETABLE ); + + if( 1 == nNumOpenBrakets ) + { + bOverrideFormat = FALSE, bOverrideStart = FALSE; + if( pRule ) + { + if( lcl_IsEqual( pOrigRule, pRule )) + { + // no changes on the rule -> use the original rule + aEntry.nListDocPos = pDoc->FindNumRule( + pOrigRule->GetName() ); + // delete the temp Rule + RemoveUnusedNumRule( pRule ); + } + else if( pRule->IsContinusNum() ) + lcl_ExpandNumFmts( *pRule ); + } + + if( aEntry.nListId && aEntry.nListNo ) + { + int nMatch=-1; + for( USHORT n = aListArr.Count(); n; ) + { + if( aListArr[ --n ].nListId == aEntry.nListId) + { + nMatch=n; + break; + } + } + if(nMatch>=0) + { + USHORT nMatch2 = static_cast< USHORT >(nMatch); + if (!aListArr[nMatch2].nListNo ) + { + aListArr[nMatch2].nListNo = aEntry.nListNo; + } + else + { + aEntry.nListDocPos=aListArr[nMatch2].nListDocPos; + aEntry.nListTemplateId=aListArr[nMatch2].nListTemplateId; + aListArr.Insert(aEntry, aListArr.Count()); + } + if(pOrigRule) + aListArr[nMatch2].nListDocPos = aEntry.nListDocPos; + } + } + aEntry.Clear(); + pOrigRule = 0; + pRule = 0; + } + } + break; + + case '{': + { + if( RTF_IGNOREFLAG != GetNextToken() ) + nToken = SkipToken( -1 ); + // Unknown und alle bekannten nicht ausgewerteten Gruppen + // sofort ueberspringen + else if( RTF_UNKNOWNCONTROL != ( nToken = GetNextToken() )) + nToken = SkipToken( -2 ); + else + { + // gleich herausfiltern + ReadUnknownData(); + nToken = GetNextToken(); + if( '}' != nToken ) + eState = SVPAR_ERROR; + break; + } + ++nNumOpenBrakets; + } + break; + + case RTF_LISTOVERRIDE: aEntry.Clear(); break; + case RTF_LISTID: aEntry.nListId = nTokenValue; break; + case RTF_LS: aEntry.nListNo = nTokenValue; break; + case RTF_LISTOVERRIDECOUNT: + if( nTokenValue ) + { + pRule = 0; + // dann erzeugen wir mal schnell eine Kopie von der NumRule, + // denn diese wird jetzt mal kurz veraendert. + if( aEntry.nListId ) + for( USHORT n = 0; n < aListArr.Count(); ++n ) + if( aListArr[ n ].nListId == aEntry.nListId ) + { + pRule = pDoc->GetNumRuleTbl()[ + aListArr[ n ].nListDocPos ]; + pOrigRule = pRule; + + String sTmp( String::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( RTF_NUMRULE_NAME " 1" ))); + aEntry.nListDocPos = pDoc->MakeNumRule( sTmp, pRule ); + pRule = pDoc->GetNumRuleTbl()[ aEntry.nListDocPos ]; + // --> OD 2008-07-08 #i91400# + pRule->SetName( pDoc->GetUniqueNumRuleName( &sTmp, FALSE ), + *pDoc ); + // <-- + pRule->SetAutoRule( FALSE ); + nNumLvl = (BYTE)-1; + aListArr.Insert( aEntry, aListArr.Count() ); + break; + } + + } + break; + + case RTF_LISTLEVEL: + if( pRule && bOverrideFormat ) + { + if( ++nNumLvl < MAXLEVEL ) + pRule->Set( nNumLvl, pRule->Get( nNumLvl )); + ReadListLevel( *pRule, nNumLvl ); + } + break; + + case RTF_LEVELSTARTAT: + if( pRule && bOverrideStart ) + { + } + break; + + case RTF_LISTOVERRIDESTART: + bOverrideStart = TRUE; + break; + + case RTF_LISTOVERRIDEFORMAT: + bOverrideFormat = TRUE; + break; + + case RTF_LFOLEVEL: + // was fehlt noch? + break; + } + } + + // search the outline numrule and set it into the doc + if( GetStyleTbl().Count() ) + { + if( !bStyleTabValid ) + MakeStyleTab(); + + const SfxPoolItem* pItem( 0 ); + const SwTxtFmtColl* pColl( 0 ); + USHORT nRulePos( USHRT_MAX ); + const SwNumRule *pNumRule = 0; + SvxRTFStyleType* pStyle = GetStyleTbl().First(); + do { + // --> OD 2007-12-17 #151213# + // suppress deletion of outline list style. + // refactoring of code: no assignments in if-condition +// if( MAXLEVEL > pStyle->nOutlineNo && +// 0 != ( pColl = aTxtCollTbl.Get( (USHORT)GetStyleTbl(). +// GetCurKey() )) && +// SFX_ITEM_SET == pColl->GetItemState( RES_PARATR_NUMRULE, +// FALSE, &pItem ) && +// USHRT_MAX != (nRulePos = pDoc->FindNumRule( +// ((SwNumRuleItem*)pItem)->GetValue() )) && +// (pNumRule = pDoc->GetNumRuleTbl()[ nRulePos ])->IsAutoRule() ) + if ( MAXLEVEL > pStyle->nOutlineNo ) + { + pColl = aTxtCollTbl.Get( (USHORT)GetStyleTbl().GetCurKey() ); + if ( pColl ) + { + const SfxItemState eItemState = + pColl->GetItemState( RES_PARATR_NUMRULE, FALSE, &pItem ); + if ( eItemState == SFX_ITEM_SET ) + { + nRulePos = pDoc->FindNumRule( ((SwNumRuleItem*)pItem)->GetValue() ); + if ( nRulePos != USHRT_MAX ) + { + pNumRule = pDoc->GetNumRuleTbl()[ nRulePos ]; + if ( pNumRule->IsAutoRule() && + pNumRule != pDoc->GetOutlineNumRule() ) + { + pDoc->SetOutlineNumRule( *pNumRule ); + pDoc->DelNumRule( pNumRule->GetName() ); + // now pNumRule pointer is invalid !!! + + // now decrement all position in the listtable, which will + // behind the doc-rule position + for( USHORT n = aListArr.Count(); n; ) + { + SwListEntry& rEntry = aListArr[ --n ]; + if( rEntry.nListDocPos == nRulePos ) + aListArr.Remove( n ); + else if( rEntry.nListDocPos > nRulePos ) + --rEntry.nListDocPos; + } + break; + } + } + } + } + } + // <-- + + pStyle->aAttrSet.ClearItem( FN_PARAM_NUM_LEVEL ); + + } while( 0 != (pStyle = GetStyleTbl().Next()) ); + } + + SkipToken( -1 ); // die schliesende Klammer wird "oben" ausgewertet +} + +SwNumRule* SwRTFParser::GetNumRuleOfListNo( long nListNo, BOOL bRemoveFromList ) +{ + SwNumRule* pRet = 0; + SwListEntry* pEntry; + for( USHORT n = aListArr.Count(); n; ) + if( ( pEntry = &aListArr[ --n ])->nListNo == nListNo ) + { + if( bRemoveFromList ) + aListArr.Remove( n ); + else + { + pEntry->bRuleUsed = TRUE; + pRet = pDoc->GetNumRuleTbl()[ pEntry->nListDocPos ]; + } + break; + } + return pRet; +} + +void SwRTFParser::RemoveUnusedNumRule( SwNumRule* pRule ) +{ + if( pRule ) + { + for ( BYTE nLvl = 0; nLvl < MAXLEVEL; ++nLvl ) + { + SwNumFmt& rNFmt = (SwNumFmt&)pRule->Get( nLvl ); + SwCharFmt* pCFmt = rNFmt.GetCharFmt(); + if( pCFmt ) + { + pCFmt->Remove( &rNFmt ); + if( !pCFmt->GetDepends() ) + pDoc->DelCharFmt( pCFmt ); + } + } + pDoc->DelNumRule( pRule->GetName() ); + } +#ifdef DBG_UTIL + else + { + ASSERT( pRule, "NumRulePointer 0 kann nicht geloescht werden" ); + } +#endif +} + +void SwRTFParser::RemoveUnusedNumRules() +{ + SwListEntry* pEntry; + SvPtrarr aDelArr; + USHORT n; + for( n = aListArr.Count(); n; ) + { + if( !( pEntry = &aListArr[ --n ])->bRuleUsed ) + { + // really *NOT* used by anyone else? + BOOL unused=TRUE; + for(USHORT j = 0; j < aListArr.Count(); ++j) + { + if (aListArr[n].nListNo==aListArr[j].nListNo) + unused&=!aListArr[j].bRuleUsed; + } + if (unused) + { + void * p = pDoc->GetNumRuleTbl()[pEntry->nListDocPos]; + // dont delete named char formats + if( USHRT_MAX == aDelArr.GetPos( p ) && + ((SwNumRule*)p)->GetName().EqualsAscii( RTF_NUMRULE_NAME, 0, + sizeof( RTF_NUMRULE_NAME )) ) + aDelArr.Insert( p, aDelArr.Count() ); + } + } + } + + for( n = aDelArr.Count(); n; ) + { + SwNumRule* pDel = (SwNumRule*)aDelArr[ --n ]; + RemoveUnusedNumRule( pDel ); + } +} + +const Font* SwRTFParser::FindFontOfItem( const SvxFontItem& rItem ) const +{ + SvxRTFFontTbl& rFntTbl = ((SwRTFParser*)this)->GetFontTbl(); + const Font* pFnt = rFntTbl.First(); + while( pFnt ) + { + if( pFnt->GetFamily() == rItem.GetFamily() && + pFnt->GetName() == rItem.GetFamilyName() && + pFnt->GetStyleName() == rItem.GetStyleName() && + pFnt->GetPitch() == rItem.GetPitch() && + pFnt->GetCharSet() == rItem.GetCharSet() ) + return pFnt; + + pFnt = rFntTbl.Next(); + } + return 0; +} + + +SwNumRule *SwRTFParser::ReadNumSecLevel( int nToken ) +{ + // lese die \pnseclvl - Gruppe + // nTokenValue gibt schon den richtigen Level vor 1 - 9! + BYTE nLevel = 0; + long nListNo = 0; + BOOL bContinus = TRUE; + + if( RTF_PNSECLVL == nToken ) + { + // suche die Rule - steht unter Nummer 3 + nListNo = 3; + bContinus = FALSE; + nLevel = MAXLEVEL <= (unsigned long) nTokenValue ? MAXLEVEL - 1 + : (!nTokenValue ? 0 : BYTE( nTokenValue - 1 )); + } + else + { + switch( nToken = GetNextToken() ) + { + case RTF_PNLVL: nListNo = 3; + bContinus = FALSE; + nLevel = MAXLEVEL <= (unsigned long) nTokenValue + ? MAXLEVEL - 1 + : (!nTokenValue ? 0 : BYTE( nTokenValue-1 )); + break; + + case RTF_PNLVLBODY: + nListNo = 2; + break; + case RTF_PNLVLBLT: + nListNo = 1; + break; + case RTF_PNLVLCONT: + SkipGroup(); + return 0; + default: + SkipGroup(); + return 0; + } + } + + // suche die Rule - steht unter Nummer 3 + USHORT nNewFlag = static_cast< USHORT >(1 << nListNo); + SwNumRule* pCurRule = GetNumRuleOfListNo( nListNo, + 0 != ( nNewNumSectDef & nNewFlag ) ); + if( !pCurRule ) + { + // dann muessen wir die mal anlegen + nNewNumSectDef &= ~nNewFlag; + String sTmp( String::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( RTF_NUMRULE_NAME " 1" ))); + SwListEntry aEntry( nListNo, 0, pDoc->MakeNumRule( sTmp )); + aEntry.nListNo = nListNo; + aListArr.Insert( aEntry, aListArr.Count() ); + pCurRule = pDoc->GetNumRuleTbl()[ aEntry.nListDocPos ]; + // --> OD 2008-07-08 #i91400# + pCurRule->SetName( pDoc->GetUniqueNumRuleName( &sTmp, FALSE ), *pDoc ); + // <-- + pCurRule->SetAutoRule( FALSE ); + pCurRule->SetContinusNum( bContinus ); + } + + if( !pCurRule->GetNumFmt( nLevel )) + pCurRule->Set( nLevel, pCurRule->Get( nLevel )); + SwNumFmt* pCurNumFmt = (SwNumFmt*)pCurRule->GetNumFmt( nLevel ); + if( RTF_PNLVLBLT == nToken ) + pCurNumFmt->SetNumberingType(SVX_NUM_CHAR_SPECIAL); + pCurNumFmt->SetSuffix( aEmptyStr ); + pCurNumFmt->SetPrefix( aEmptyStr ); + pCurNumFmt->SetNumberingType(SVX_NUM_NUMBER_NONE); + + if( bStyleTabValid && RTF_PNSECLVL != nToken ) + { + // dann den akt. Lvl und Rule am Absatz setzen. + // Dieses muss aber in den vorherigen "Kontext", sprich in den vor + // der Klammer offenen Attrset. Darum das SetNewGroup davor und dahinter + SetNewGroup( FALSE ); + GetAttrSet().Put( SfxUInt16Item( FN_PARAM_NUM_LEVEL, nLevel )); + GetAttrSet().Put( SwNumRuleItem( pCurRule->GetName() )); + SetNewGroup( TRUE ); + } + + FontUnderline eUnderline; + int nNumOpenBrakets = 1; // die erste wurde schon vorher erkannt !! + while( nNumOpenBrakets && IsParserWorking() ) + { + switch( ( nToken = GetNextToken() )) + { + case '}': + if( --nNumOpenBrakets && IsParserWorking() ) + { + // Style konnte vollstaendig gelesen werden, + // also ist das noch ein stabiler Status + SaveState( RTF_PNSECLVL ); + } + break; + + case '{': + { + if( RTF_IGNOREFLAG != GetNextToken() ) + nToken = SkipToken( -1 ); + // Unknown und alle bekannten nicht ausgewerteten Gruppen + // sofort ueberspringen + else if( RTF_UNKNOWNCONTROL != ( nToken = GetNextToken() )) + nToken = SkipToken( -2 ); + else + { + // gleich herausfiltern + ReadUnknownData(); + nToken = GetNextToken(); + if( '}' != nToken ) + eState = SVPAR_ERROR; + break; + } + ++nNumOpenBrakets; + } + break; + + case RTF_PNCARD: + case RTF_PNORD: + case RTF_PNORDT: + case RTF_PNDEC: pCurNumFmt->SetNumberingType(SVX_NUM_ARABIC); break; + case RTF_PNUCLTR: pCurNumFmt->SetNumberingType(SVX_NUM_CHARS_UPPER_LETTER_N); break; + case RTF_PNUCRM: pCurNumFmt->SetNumberingType(SVX_NUM_ROMAN_UPPER); break; + case RTF_PNLCLTR: pCurNumFmt->SetNumberingType(SVX_NUM_CHARS_LOWER_LETTER_N); break; + case RTF_PNLCRM: pCurNumFmt->SetNumberingType(SVX_NUM_ROMAN_LOWER); break; + + case RTF_PNF: + { + const Font& rSVFont = GetFont( USHORT(nTokenValue) ); + GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put( + SvxFontItem( rSVFont.GetFamily(), + rSVFont.GetName(), rSVFont.GetStyleName(), + rSVFont.GetPitch(), rSVFont.GetCharSet(), + RES_CHRATR_FONT )); + if( SVX_NUM_CHAR_SPECIAL == pCurNumFmt->GetNumberingType() ) + pCurNumFmt->SetBulletFont( &rSVFont ); + } + break; + case RTF_PNFS: + { + if( -1 == nTokenValue ) + nTokenValue = 240; + else + nTokenValue *= 10; + GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put( + SvxFontHeightItem( (const USHORT)nTokenValue, 100, RES_CHRATR_FONTSIZE )); + } + break; + + case RTF_PNB: + { + GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put( SvxWeightItem( + nTokenValue ? WEIGHT_BOLD : WEIGHT_NORMAL, RES_CHRATR_WEIGHT )); + } + break; + + case RTF_PNI: + { + GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put( SvxPostureItem( + nTokenValue ? ITALIC_NORMAL : ITALIC_NONE, RES_CHRATR_POSTURE )); + } + break; + + case RTF_PNCAPS: + case RTF_PNSCAPS: + { + GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put( SvxCaseMapItem( + nTokenValue ? SVX_CASEMAP_KAPITAELCHEN + : SVX_CASEMAP_NOT_MAPPED, RES_CHRATR_CASEMAP )); + } + break; + case RTF_PNSTRIKE: + { + GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put( SvxCrossedOutItem( + nTokenValue ? STRIKEOUT_SINGLE : STRIKEOUT_NONE, RES_CHRATR_CROSSEDOUT )); + } + break; + + case RTF_PNCF: + { + GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put( SvxColorItem( + GetColor( USHORT(nTokenValue) ), RES_CHRATR_COLOR )); + } + break; + + + case RTF_PNUL: + eUnderline = nTokenValue ? UNDERLINE_SINGLE : UNDERLINE_NONE; + goto NUMATTR_SETUNDERLINE; + case RTF_PNULD: + eUnderline = UNDERLINE_DOTTED; + goto NUMATTR_SETUNDERLINE; + case RTF_PNULDB: + eUnderline = UNDERLINE_DOUBLE; + goto NUMATTR_SETUNDERLINE; + case RTF_PNULNONE: + eUnderline = UNDERLINE_NONE; + goto NUMATTR_SETUNDERLINE; + case RTF_PNULW: + { + GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put( + SvxWordLineModeItem( TRUE, RES_CHRATR_WORDLINEMODE )); + } + eUnderline = UNDERLINE_SINGLE; + goto NUMATTR_SETUNDERLINE; + +NUMATTR_SETUNDERLINE: + { + GetNumChrFmt( *pDoc, *pCurRule, nLevel ).Put( + SvxUnderlineItem( eUnderline, RES_CHRATR_UNDERLINE )); + } + break; + + case RTF_PNINDENT: + if( 0 > short( nTokenValue ) ) + nTokenValue = - (short)nTokenValue; + pCurNumFmt->SetFirstLineOffset( - short( nTokenValue )); + pCurNumFmt->SetAbsLSpace( (nLevel + 1 ) * USHORT( nTokenValue )); + break; + case RTF_PNSP: + pCurNumFmt->SetCharTextDistance( USHORT( nTokenValue )); + break; + + case RTF_PNPREV: + if( nLevel ) + { + BYTE nPrev = 2, nLast = nLevel; + while( nLast && 1 < pCurRule->Get( --nLast ).GetIncludeUpperLevels() ) + ++nPrev; + pCurNumFmt->SetIncludeUpperLevels( nPrev ); + } + break; + + case RTF_PNQC: pCurNumFmt->SetNumAdjust( SVX_ADJUST_CENTER ); break; + case RTF_PNQL: pCurNumFmt->SetNumAdjust( SVX_ADJUST_LEFT ); break; + case RTF_PNQR: pCurNumFmt->SetNumAdjust( SVX_ADJUST_RIGHT ); break; + + case RTF_PNSTART: + pCurNumFmt->SetStart( USHORT( nTokenValue )); + break; + + case RTF_PNNUMONCE: + case RTF_PNACROSS: + case RTF_PNHANG: + case RTF_PNRESTART: break; + + case RTF_PNTXTA: + { + String sTmp; + GetTextToEndGroup( sTmp ); + if( SVX_NUM_CHAR_SPECIAL == pCurNumFmt->GetNumberingType() ) + { + pCurNumFmt->SetBulletChar( sTmp.GetChar( 0 ) ); + if( pCurNumFmt->GetCharFmt() ) + pCurNumFmt->SetBulletFont( FindFontOfItem( + pCurNumFmt->GetCharFmt()->GetFont() ) ); + sTmp.Erase(); + } + pCurNumFmt->SetSuffix( sTmp ); + } + break; + + case RTF_PNTXTB: + { + String sTmp; + pCurNumFmt->SetPrefix( GetTextToEndGroup( sTmp ) ); + } + break; + } + } + + // falls vollstaendige Numerierung an ist und das Zeichen davor ein + // Punkt ist, dann will RTF den Punkt als Trenner zwischen den Ebenen + // haben - das haben wir aber schon als default + if( 1 < pCurNumFmt->GetIncludeUpperLevels() && + 1 == pCurNumFmt->GetPrefix().Len() && + '.' == pCurNumFmt->GetPrefix().GetChar( 0 ) && + SVX_NUM_CHAR_SPECIAL != pCurNumFmt->GetNumberingType() ) + pCurNumFmt->SetPrefix( aEmptyStr ); + + // falls das ein nicht numerierter Absatz mit ein Prefix-Text mit + // einem Zeichen ist, dann setze den als Bulletzeichen + if( pCurNumFmt->GetCharFmt() && SVX_NUM_NUMBER_NONE == pCurNumFmt->GetNumberingType() && + 3 == nListNo && 1 == pCurNumFmt->GetPrefix().Len() ) + { + SwCharFmt* pChFmt = pCurNumFmt->GetCharFmt(); + pCurNumFmt->SetNumberingType(SVX_NUM_CHAR_SPECIAL); + pCurNumFmt->SetBulletFont( FindFontOfItem( pChFmt->GetFont() ) ); + + pCurNumFmt->SetBulletChar( pCurNumFmt->GetPrefix().GetChar( 0 ) ); + pCurNumFmt->SetPrefix( aEmptyStr ); + + // den Font oder sogar das gesamte CharFormat loeschen? + if( SFX_ITEM_SET == pChFmt->GetItemState( RES_CHRATR_FONT, FALSE )) + { + if( 1 == pChFmt->GetAttrSet().Count() ) + { + pCurNumFmt->SetCharFmt( 0 ); + pDoc->DelCharFmt( pChFmt ); + } + else + pChFmt->ResetFmtAttr( RES_CHRATR_FONT ); + } + } + + SkipToken( -1 ); // die schliesende Klammer wird "oben" ausgewertet + return pCurRule; +} + + +/* */ + +// dann noch die Ausgabe-Funktionen (nur fuer WinWord 97) + +BOOL lcl_IsExportNumRule( const SwNumRule& rRule, BYTE* pEnd = 0 ) +{ + BYTE nEnd = MAXLEVEL; + while( nEnd-- && !rRule.GetNumFmt( nEnd )) + ; + ++nEnd; + + const SwNumFmt* pNFmt; + BYTE nLvl; + + for( nLvl = 0; nLvl < nEnd; ++nLvl ) + if( SVX_NUM_NUMBER_NONE != ( pNFmt = &rRule.Get( nLvl )) + ->GetNumberingType() || pNFmt->GetPrefix().Len() || + (pNFmt->GetSuffix().Len() && pNFmt->GetSuffix() != aDotStr )) + break; + + if( pEnd ) + *pEnd = nEnd; + return nLvl != nEnd; +} + +void SwRTFWriter::OutRTFListTab() +{ + ByteString sOverrideList; + USHORT nId = 1, nTmplId = 1, n; + + // prepare the NodeNum to generate the NumString + SwNumberTree::tNumberVector aNumVector; + for( n = 0; n < MAXLEVEL; ++n ) + aNumVector.push_back(n); + BYTE aNumLvlPos[ MAXLEVEL ]; + + if( !pNumRuleTbl ) + BuildNumRuleTbl(); + + for( n = 0; n < pNumRuleTbl->Count(); ++n ) + { + const SwNumRule* pRule = (*pNumRuleTbl)[ n ]; + + // mit der ersten Rule wird auch die ListTable geschrieben + if( !sOverrideList.Len() ) + OutComment( *this, OOO_STRING_SVTOOLS_RTF_LISTTABLE ); + + Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LIST << OOO_STRING_SVTOOLS_RTF_LISTTEMPLATEID; + OutULong( nTmplId ); + ByteString sTmp; + + if( pRule->IsContinusNum() ) + Strm() << OOO_STRING_SVTOOLS_RTF_LISTSIMPLE; + + BYTE nLvl, nEnd; + lcl_IsExportNumRule( *pRule, &nEnd ); + + for( nLvl = 0; nLvl < nEnd; ++nLvl ) + { + const SwNumFmt& rFmt = pRule->Get( nLvl ); + Strm() << sNewLine; + if( nLvl > 8 ) // RTF-kennt nur 9 Ebenen + OutComment( *this, OOO_STRING_SVTOOLS_RTF_SOUTLVL ); + + Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LISTLEVEL << OOO_STRING_SVTOOLS_RTF_LEVELNFC; + + USHORT nVal = 0; + switch( rFmt.GetNumberingType() ) + { + case SVX_NUM_ROMAN_UPPER: nVal = 1; break; + case SVX_NUM_ROMAN_LOWER: nVal = 2; break; + case SVX_NUM_CHARS_UPPER_LETTER: + case SVX_NUM_CHARS_UPPER_LETTER_N: nVal = 3; break; + case SVX_NUM_CHARS_LOWER_LETTER: + case SVX_NUM_CHARS_LOWER_LETTER_N: nVal = 4; break; + + case SVX_NUM_BITMAP: + case SVX_NUM_CHAR_SPECIAL: nVal = 23; break; + } + OutLong( nVal ) << OOO_STRING_SVTOOLS_RTF_LEVELJC; + + switch( rFmt.GetNumAdjust() ) + { + case SVX_ADJUST_CENTER: nVal = 1; break; + case SVX_ADJUST_RIGHT: nVal = 2; break; + default: nVal = 0; break; + } + OutLong( nVal ) << OOO_STRING_SVTOOLS_RTF_LEVELSTARTAT; + OutLong( rFmt.GetStart() ) + << OOO_STRING_SVTOOLS_RTF_LEVELFOLLOW << "0{" << OOO_STRING_SVTOOLS_RTF_LEVELTEXT << ' '; + + BOOL bWriteBulletFont = FALSE; + memset( aNumLvlPos, 0, MAXLEVEL ); + if( SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType() || + SVX_NUM_BITMAP == rFmt.GetNumberingType() ) + { + Strm() << "\\'01"; + ByteString sNo( ByteString::CreateFromInt32( rFmt.GetBulletChar())); + Strm() << "\\u" << sNo.GetBuffer() << " ?"; + bWriteBulletFont = TRUE; + } + else if( SVX_NUM_NUMBER_NONE == rFmt.GetNumberingType() ) + { + String sOut( rFmt.GetPrefix() ); sOut += rFmt.GetSuffix(); + if( sOut.Len() ) + { + Strm() << "\\'"; + OutHex( sOut.Len() ); + RTFOutFuncs::Out_String( Strm(), sOut, + eDefaultEncoding, bWriteHelpFmt ); + } + } + else + { + memset( aNumLvlPos, 0, MAXLEVEL ); + BYTE* pLvlPos = aNumLvlPos; + // --> OD 2005-11-18 #128056# + // correction of refactoring done by cws swnumtree: + // - the numbering string has to be restrict to the level + // currently working on. + String sNumStr( pRule->MakeNumString( aNumVector, FALSE, TRUE, nLvl )); + // <-- + + // now search the nums in the string + for( BYTE i = 0; i <= nLvl; ++i ) + { + String sSrch( String::CreateFromInt32( i )); + xub_StrLen nFnd = sNumStr.Search( sSrch ); + if( STRING_NOTFOUND != nFnd ) + { + *pLvlPos = (BYTE)(nFnd + rFmt.GetPrefix().Len() + 1 ); + ++pLvlPos; + sNumStr.SetChar( nFnd, (sal_Unicode)i ); + } + } + + Strm() << "\\'"; + OutHex( sNumStr.Len() + rFmt.GetPrefix().Len() + + rFmt.GetSuffix().Len() ); + + if( rFmt.GetPrefix().Len() ) + RTFOutFuncs::Out_String( Strm(), rFmt.GetPrefix(), + eDefaultEncoding, bWriteHelpFmt ); + + + for( xub_StrLen x = 0; x < sNumStr.Len(); ++x ) + if( sNumStr.GetChar( x ) < 0x20 || + sNumStr.GetChar( x ) > 0xFF ) + { + Strm() << "\\'"; OutHex( sNumStr.GetChar( x ) ); + } + else + Strm() << (sal_Char)sNumStr.GetChar( x ); + + if( rFmt.GetSuffix().Len() ) + RTFOutFuncs::Out_String( Strm(), rFmt.GetSuffix(), + eDefaultEncoding, bWriteHelpFmt ); + } + + // write the levelnumbers + Strm() << ";}{" << OOO_STRING_SVTOOLS_RTF_LEVELNUMBERS; + for( BYTE i = 0; i <= nLvl && aNumLvlPos[ i ]; ++i ) + { + Strm() << "\\'"; OutHex( aNumLvlPos[ i ] ); + } + Strm() << ";}"; + + if( rFmt.GetCharFmt() ) + Out_SfxItemSet( aRTFAttrFnTab, *this, + rFmt.GetCharFmt()->GetAttrSet(), TRUE ); + + if( bWriteBulletFont ) + { + Strm() << OOO_STRING_SVTOOLS_RTF_F; + const Font* pFont = rFmt.GetBulletFont(); + if( !pFont ) + // --> OD 2006-06-27 #b6440955# + pFont = &numfunc::GetDefBulletFont(); + // <-- + OutULong( GetId( *pFont )); + } + + Strm() << OOO_STRING_SVTOOLS_RTF_FI; + OutLong( rFmt.GetFirstLineOffset() ) << OOO_STRING_SVTOOLS_RTF_LI; + OutLong( rFmt.GetAbsLSpace() ); + + Strm() << '}'; + + if( nLvl > 8 ) // RTF-kennt nur 9 Ebenen + Strm() << '}'; + } + + if( !pRule->IsAutoRule() ) + { + Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LISTNAME << ' '; + RTFOutFuncs::Out_String( Strm(), pRule->GetName(), eDefaultEncoding, + bWriteHelpFmt ) << ";}" ; + } + Strm() << OOO_STRING_SVTOOLS_RTF_LISTID; + OutULong( nId ) << '}' << sNewLine; + + sTmp = '{'; + ((((((( sTmp += OOO_STRING_SVTOOLS_RTF_LISTOVERRIDE ) += + OOO_STRING_SVTOOLS_RTF_LISTID ) += ByteString::CreateFromInt32( nId )) += + OOO_STRING_SVTOOLS_RTF_LISTOVERRIDECOUNT ) += '0' ) += + OOO_STRING_SVTOOLS_RTF_LS ) += ByteString::CreateFromInt32( n )) += '}'; + sOverrideList += sTmp; + + ++nId, ++nTmplId; + } + + if( sOverrideList.Len() ) + Strm() << "}{" << OOO_STRING_SVTOOLS_RTF_LISTOVERRIDETABLE + << sOverrideList.GetBuffer() << '}' << sNewLine; +} + +USHORT SwRTFWriter::GetId( const SwNumRuleItem& rItem ) const +{ + USHORT n, nId = USHRT_MAX; + if( !pNumRuleTbl ) + { + SwRTFWriter* pThis = (SwRTFWriter*)this; + pThis->BuildNumRuleTbl(); + } + const String& rNm = rItem.GetValue(); + for( n = pNumRuleTbl->Count(); n; ) + if( (*pNumRuleTbl)[ --n ]->GetName() == rNm ) + { + nId = n; + break; + } + + return nId; +} + +USHORT SwRTFWriter::GetNumRuleId( const SwNumRule& rRule ) +{ + if( !pNumRuleTbl ) + BuildNumRuleTbl(); + SwNumRulePtr pR = (SwNumRulePtr)&rRule; + return pNumRuleTbl->GetPos( pR ); +} + +void SwRTFWriter::BuildNumRuleTbl() +{ + const SwNumRuleTbl& rListTbl = pDoc->GetNumRuleTbl(); + if( !pNumRuleTbl ) + pNumRuleTbl = new SwNumRuleTbl( (BYTE)rListTbl.Count() ); + for( USHORT n = rListTbl.Count()+1; n; ) + { + SwNumRule* pRule; + --n; + if( n == rListTbl.Count() ) + pRule = (SwNumRule*)pDoc->GetOutlineNumRule(); + else + { + pRule = rListTbl[ n ]; + if( !pDoc->IsUsed( *pRule )) + continue; + } + + if( lcl_IsExportNumRule( *pRule )) + pNumRuleTbl->Insert( pRule, pNumRuleTbl->Count() ); + } +} + +BOOL SwRTFWriter::OutListNum( const SwTxtNode& rNd ) +{ + BOOL bRet = FALSE; + const SwNumRule* pRule = rNd.GetNumRule(); + + // --> OD 2008-03-18 #refactorlists# +// if( pRule && MAXLEVEL > rNd.GetActualListLevel() ) + if( pRule && rNd.IsInList() ) + // <-- + { + // --> OD 2008-03-18 #refactorlists# + ASSERT( rNd.GetActualListLevel() >= 0 && rNd.GetActualListLevel() < MAXLEVEL, + "<SwRTFWriter::OutListNum(..)> - text node does not have valid list level. Serious defect -> please inform OD" ); + // <-- + + bOutFmtAttr = FALSE; + bOutListNumTxt = TRUE; + bRet = TRUE; + + const bool bExportNumRule = USHRT_MAX != GetNumRuleId( *pRule ); + const BYTE nLvl = static_cast< BYTE >(rNd.GetActualListLevel()); + const SwNumFmt* pFmt = pRule->GetNumFmt( nLvl ); + if( !pFmt ) + pFmt = &pRule->Get( nLvl ); + + const SfxItemSet& rNdSet = rNd.GetSwAttrSet(); + + SfxItemSet aSet( *rNdSet.GetPool(), rNdSet.GetRanges() ); + aSet.SetParent( &rNdSet ); + SvxLRSpaceItem aLR( (SvxLRSpaceItem&)rNdSet.Get( RES_LR_SPACE ) ); + aLR.SetTxtLeft( aLR.GetTxtLeft() + pFmt->GetAbsLSpace() ); + + aLR.SetTxtFirstLineOfst( pFmt->GetFirstLineOffset() ); + if ( bExportNumRule ) + Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LISTTEXT << OOO_STRING_SVTOOLS_RTF_PARD << OOO_STRING_SVTOOLS_RTF_PLAIN << ' '; + + aSet.Put( aLR ); + Out_SfxItemSet( aRTFAttrFnTab, *this, aSet, TRUE ); + + if( pFmt->GetCharFmt() ) + Out_SfxItemSet( aRTFAttrFnTab, *this, + pFmt->GetCharFmt()->GetAttrSet(), TRUE ); + + { + String sTxt; + if( SVX_NUM_CHAR_SPECIAL == pFmt->GetNumberingType() || SVX_NUM_BITMAP == pFmt->GetNumberingType() ) + sTxt = pFmt->GetBulletChar(); + else + sTxt = rNd.GetNumString(); + + if( bOutFmtAttr ) + { + Strm() << ' '; + bOutFmtAttr = FALSE; + } + + if (sTxt.Len()) + { + RTFOutFuncs::Out_String(Strm(), sTxt, eDefaultEncoding, + bWriteHelpFmt); + } + + if( bExportNumRule ) + { + if( OUTLINE_RULE != pRule->GetRuleType() ) + { + Strm() << OOO_STRING_SVTOOLS_RTF_TAB << '}' << OOO_STRING_SVTOOLS_RTF_ILVL; + if( nLvl > 8 ) // RTF-kennt nur 9 Ebenen + { + OutULong( 8 ); + OutComment( *this, OOO_STRING_SVTOOLS_RTF_SOUTLVL ); + OutULong( nLvl ) << '}'; + } + else + OutULong( nLvl ); + Strm() << ' '; + } + else + Strm() << OOO_STRING_SVTOOLS_RTF_TAB << '}'; + } + else if( sTxt.Len() ) + Strm() << OOO_STRING_SVTOOLS_RTF_TAB; + } + bOutListNumTxt = FALSE; + } + return bRet; +} |