/************************************************************************* * * $RCSfile: tox.cxx,v $ * * $Revision: 1.2 $ * * last change: $Author: os $ $Date: 2001-06-06 10:41:24 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses * * - GNU Lesser General Public License Version 2.1 * - Sun Industry Standards Source License Version 1.1 * * Sun Microsystems Inc., October, 2000 * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2000 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library 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 for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * * Sun Industry Standards Source License Version 1.1 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.1 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://www.openoffice.org/license.html. * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2000 by Sun Microsystems, Inc. * * All Rights Reserved. * * Contributor(s): _______________________________________ * * ************************************************************************/ #ifdef PRECOMPILED #include "core_pch.hxx" #endif #pragma hdrstop #ifndef _TOOLS_RESID_HXX #include #endif #ifndef _HINTIDS_HXX #include #endif #ifndef _SWTYPES_HXX #include #endif #ifndef _ERRHDL_HXX #include #endif #ifndef _TXTATR_HXX #include #endif #ifndef _NDTXT_HXX #include #endif #ifndef _TXTTXMRK_HXX //autogen #include #endif #ifndef _TOX_HXX #include #endif #ifndef _POOLFMT_HRC #include #endif #ifndef _DOC_HXX #include #endif #ifndef _DOCARY_HXX #include #endif #ifndef _PARATR_HXX #include #endif #ifndef _SVX_TSPTITEM_HXX #include #endif const sal_Char* SwForm::aFormEntry = ""; const sal_Char* SwForm::aFormTab = ""; const sal_Char* SwForm::aFormPageNums = "<#>"; const sal_Char* SwForm::aFormLinkStt = ""; const sal_Char* SwForm::aFormLinkEnd = ""; const sal_Char* SwForm::aFormEntryNum = ""; const sal_Char* SwForm::aFormEntryTxt = ""; const sal_Char* SwForm::aFormChapterMark= ""; const sal_Char* SwForm::aFormText = ""; const sal_Char* SwForm::aFormAuth = ""; BYTE SwForm::nFormTabLen = 3; BYTE SwForm::nFormEntryLen = 3; BYTE SwForm::nFormPageNumsLen = 3; BYTE SwForm::nFormLinkSttLen = 4; BYTE SwForm::nFormLinkEndLen = 4; BYTE SwForm::nFormEntryNumLen = 4; BYTE SwForm::nFormEntryTxtLen = 4; BYTE SwForm::nFormChapterMarkLen = 3; BYTE SwForm::nFormTextLen = 3; BYTE SwForm::nFormAuthLen = 5; SV_IMPL_PTRARR(SwTOXMarks, SwTOXMark*) TYPEINIT2( SwTOXMark, SfxPoolItem, SwClient ); // fuers rtti /* -----------------23.09.99 14:09------------------- includes plain text at a given position into the appropriate token --------------------------------------------------*/ USHORT lcl_ConvertTextIntoPattern( String& rPattern, xub_StrLen nStart, xub_StrLen nEnd ) { String sTmp; sTmp.AssignAscii( RTL_CONSTASCII_STRINGPARAM( " 0) { sRet.AppendAscii( RTL_CONSTASCII_STRINGPARAM( ", " )); lcl_ConvertTextIntoPattern(sRet, sRet.Len() - 2, sRet.Len()); } sRet += sAuth; sTmp = String::CreateFromInt32( nVals[ i ] ); if(sTmp.Len() < 2) sTmp.Insert('0', 0); sRet.Insert(sTmp, sRet.Len() - 2); } return sRet; } /*-------------------------------------------------------------------- Beschreibung: Verzeichnis-Markierungen D/Ctor --------------------------------------------------------------------*/ // Konstruktor fuers Default vom Attribut-Pool SwTOXMark::SwTOXMark() : SfxPoolItem( RES_TXTATR_TOXMARK ), SwClient( 0 ), pTxtAttr( 0 ), bAutoGenerated(FALSE), bMainEntry(FALSE) { } SwTOXMark::SwTOXMark( const SwTOXType* pTyp ) : SfxPoolItem( RES_TXTATR_TOXMARK ), SwClient( (SwModify*)pTyp ), pTxtAttr( 0 ), nLevel( 0 ), bAutoGenerated(FALSE), bMainEntry(FALSE) { } SwTOXMark::SwTOXMark( const SwTOXMark& rCopy ) : SfxPoolItem( RES_TXTATR_TOXMARK ), SwClient((SwModify*)rCopy.GetRegisteredIn()), pTxtAttr( 0 ), nLevel( rCopy.nLevel ), aPrimaryKey( rCopy.aPrimaryKey ), aSecondaryKey( rCopy.aSecondaryKey ), bAutoGenerated( rCopy.bAutoGenerated), bMainEntry(rCopy.bMainEntry) { // AlternativString kopieren aAltText = rCopy.aAltText; } SwTOXMark::~SwTOXMark() { } int SwTOXMark::operator==( const SfxPoolItem& rAttr ) const { ASSERT( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" ); return GetRegisteredIn() == ((SwTOXMark&)rAttr).GetRegisteredIn(); } SfxPoolItem* SwTOXMark::Clone( SfxItemPool* ) const { return new SwTOXMark( *this ); } String SwTOXMark::GetText() const { String aStr; if( aAltText.Len() ) aStr = aAltText; else if( pTxtAttr && pTxtAttr->GetpTxtNd() ) { xub_StrLen* pEndIdx = pTxtAttr->GetEnd(); ASSERT( pEndIdx, "TOXMark ohne Mark!!"); if( pEndIdx ) { const xub_StrLen nStt = *pTxtAttr->GetStart(); aStr = pTxtAttr->GetpTxtNd()->GetExpandTxt( nStt, *pEndIdx-nStt ); } } return aStr; } /*-------------------------------------------------------------------- Beschreibung: Typen von Verzeichnissen verwalten --------------------------------------------------------------------*/ SwTOXType::SwTOXType( TOXTypes eTyp, const String& rName ) : SwModify(0), aName(rName), eType(eTyp) { } SwTOXType::SwTOXType(const SwTOXType& rCopy) : SwModify( (SwModify*)rCopy.GetRegisteredIn() ), aName(rCopy.aName), eType(rCopy.eType) { } /*-------------------------------------------------------------------- Beschreibung: Formen bearbeiten --------------------------------------------------------------------*/ SwForm::SwForm( USHORT nTyp ) : nType( nTyp ), nFormMaxLevel( SwForm::GetFormMaxLevel( nTyp )), // nFirstTabPos( lNumIndent ), bCommaSeparated(FALSE) { //bHasFirstTabPos = bGenerateTabPos = FALSE; bIsRelTabPos = TRUE; // Inhaltsverzeichnis hat entsprechend Anzahl Headlines + Ueberschrift // Benutzer hat 10 Ebenen + Ueberschrift // Stichwort hat 3 Ebenen + Ueberschrift + Trenner // indexes of tables, objects illustrations and authorities consist of a heading and one level USHORT nPoolId; switch( nType ) { case TOX_INDEX: nPoolId = STR_POOLCOLL_TOX_IDXH; break; case TOX_USER: nPoolId = STR_POOLCOLL_TOX_USERH; break; case TOX_CONTENT: nPoolId = STR_POOLCOLL_TOX_CNTNTH; break; case TOX_ILLUSTRATIONS: nPoolId = STR_POOLCOLL_TOX_ILLUSH; break; case TOX_OBJECTS : nPoolId = STR_POOLCOLL_TOX_OBJECTH; break; case TOX_TABLES : nPoolId = STR_POOLCOLL_TOX_TABLESH; break; case TOX_AUTHORITIES : nPoolId = STR_POOLCOLL_TOX_AUTHORITIESH; break; default: ASSERT( !this, "ungueltiger TOXTyp"); return ; } String sStr; { ByteString sBStr; if( TOX_CONTENT == nType ) ( sBStr = SwForm::aFormEntryNum ) += SwForm::aFormEntryTxt; else sBStr = SwForm::aFormEntry; if( TOX_AUTHORITIES != nType) { sBStr += SwForm::aFormTab; ByteString sTmp( RTL_CONSTASCII_STRINGPARAM( " ,65535,0," )); if(TOX_CONTENT == nType) { //the most right tab stop is "most_right_aligned" sTmp += ByteString::CreateFromInt32( SVX_TAB_ADJUST_END ); //and has a dot as FillChar sTmp.Append( RTL_CONSTASCII_STRINGPARAM( ",." )); sBStr.Insert(sTmp, sBStr.Len() - 1); } else { sTmp += ByteString::CreateFromInt32( SVX_TAB_ADJUST_LEFT ); //and has a space as FillChar sTmp.Append( RTL_CONSTASCII_STRINGPARAM( ", " )); } sBStr.Insert( sTmp, sBStr.Len() - 1); sBStr += SwForm::aFormPageNums; } sStr.AppendAscii( sBStr.GetBuffer(), sBStr.Len() ); } SetTemplate( 0, SW_RESSTR( nPoolId++ )); if(TOX_INDEX == nType) { for( USHORT i = 1; i < 5; ++i ) { if(1 == i) { String sTmp; sTmp.AssignAscii( SwForm::aFormEntry ); sTmp.Insert(' ', SwForm::nFormEntryLen - 1); SetPattern( i, sTmp ); SetTemplate( i, SW_RESSTR( STR_POOLCOLL_TOX_IDXBREAK )); } else { SetPattern( i, sStr ); SetTemplate( i, SW_RESSTR( STR_POOLCOLL_TOX_IDX1 + i - 2 )); } } } else for( USHORT i = 1; i < GetFormMax(); ++i, ++nPoolId ) // Nr 0 ist der Titel { if(TOX_AUTHORITIES == nType) SetPattern(i, lcl_GetAuthPattern(i)); else SetPattern( i, sStr ); if( TOX_CONTENT == nType && 6 == i ) nPoolId = STR_POOLCOLL_TOX_CNTNT6; else if( TOX_USER == nType && 6 == i ) nPoolId = STR_POOLCOLL_TOX_USER6; else if( TOX_AUTHORITIES == nType ) nPoolId = STR_POOLCOLL_TOX_AUTHORITIES1; SetTemplate( i, SW_RESSTR( nPoolId ) ); } } SwForm::SwForm(const SwForm& rForm) : nType( rForm.nType ) { *this = rForm; } SwForm& SwForm::operator=(const SwForm& rForm) { nType = rForm.nType; nFormMaxLevel = rForm.nFormMaxLevel; // nFirstTabPos = rForm.nFirstTabPos; // bHasFirstTabPos = rForm.bHasFirstTabPos; bGenerateTabPos = rForm.bGenerateTabPos; bIsRelTabPos = rForm.bIsRelTabPos; bCommaSeparated = rForm.bCommaSeparated; for(USHORT i=0; i < nFormMaxLevel; ++i) { aPattern[i] = rForm.aPattern[i]; aTemplate[i] = rForm.aTemplate[i]; } return *this; } USHORT SwForm::GetFormMaxLevel( USHORT nType ) { USHORT nRet = 0; switch( nType ) { case TOX_INDEX: nRet = 5; break; case TOX_USER: nRet = MAXLEVEL+1; break; case TOX_CONTENT: nRet = MAXLEVEL+1; break; case TOX_ILLUSTRATIONS: case TOX_OBJECTS : case TOX_TABLES : nRet = 2; break; case TOX_AUTHORITIES : nRet = AUTH_TYPE_END + 1; break; } return nRet; } /* -----------------15.06.99 13:39------------------- compatibilty methods: Version 5.0 and 5.1 need a value for the first tab stop --------------------------------------------------*/ USHORT lcl_GetPatternCount( const String& rPattern, const sal_Char* pToken ) { USHORT nRet = 0; String aSearch; aSearch.AssignAscii( pToken ); aSearch.Erase( aSearch.Len() - 1, 1 ); xub_StrLen nFound = rPattern.Search( aSearch ); while( STRING_NOTFOUND != nFound ) if( STRING_NOTFOUND != ( nFound = rPattern.Search( '>', nFound ) )) { ++nRet; nFound = rPattern.Search( aSearch, nFound ); } return nRet; } String lcl_GetPattern( const String& rPattern, const sal_Char* pToken ) { String sRet; String aSearch; aSearch.AssignAscii( pToken ); aSearch.Erase( aSearch.Len() - 1, 1 ); xub_StrLen nEnd, nFound = rPattern.Search( aSearch ); if( STRING_NOTFOUND != nFound && STRING_NOTFOUND != ( nEnd = rPattern.Search( '>', nFound )) ) sRet = rPattern.Copy( nFound, nEnd - nFound + 1 ); return sRet; } USHORT SwForm::GetFirstTabPos() const //{ return nFirstTabPos; } { DBG_WARNING("compatibility") String sFirstLevelPattern = aPattern[ 1 ]; USHORT nRet = 0; if( 2 <= ::lcl_GetPatternCount( sFirstLevelPattern, SwForm::aFormTab )) { //sTab is in the Form "" where value is the tab position an may be empty String sTab = lcl_GetPattern( sFirstLevelPattern, SwForm::aFormTab ); if( 3 <= sTab.GetTokenCount(',') ) { sTab = sTab.GetToken( 2, ','); sTab.Erase( sTab.Len() - 1, 1 ); nRet = sTab.ToInt32(); } } return nRet; } void SwForm::SetFirstTabPos( USHORT n ) //{ nFirstTabPos = n; } { // the tab stop token looks like: //for loading only: all levels get a first tab stop at the given position String sVal( String::CreateFromInt32( n )); String sTmp; sTmp.AssignAscii( SwForm::aFormTab ); sTmp.Insert(sVal, 2); for(USHORT i = 0; i < MAXLEVEL; i++) { //if two tabstops then exchange String& rPattern = aPattern[ i + 1]; if( 2 <= lcl_GetPatternCount( rPattern, SwForm::aFormTab )) { //change existing tab xub_StrLen nStart = rPattern.SearchAscii( "', nStart ); String sTmp( rPattern.Copy( nStart, nEnd - nStart + 1 )); rPattern.Erase( nStart, nEnd - nStart + 1 ); // if TabAlign is set String sTabAlign; if(sTmp.GetTokenCount(',') >= 4) { sTabAlign = sTmp.GetToken(3, ','); sTabAlign.Erase(sTabAlign.Len() - 1, 1); } String sTabFillChar; if(sTmp.GetTokenCount(',') >= 5) { sTabFillChar = sTmp.GetToken(4, ','); sTabFillChar.Erase(sTabAlign.Len() - 1, 1); } sTmp.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "'); String sTmp; sTmp.AssignAscii( SwForm::aFormTab ); sTmp.InsertAscii( " ,,", nFormTabLen - 1); sTmp.Insert( sVal, nFormTabLen + 2 ); rPattern.Insert( sTmp, nIndex + 1 ); } } } /* -----------------------------28.02.00 09:48-------------------------------- if the templates contain settings of the tab positions (<5.1) then they must be imported into the pattern ---------------------------------------------------------------------------*/ BOOL lcl_FindTabToken( const String& rPattern, xub_StrLen nSearchFrom, xub_StrLen& rFoundStart, xub_StrLen& rFoundEnd) { // search for // special handling of BOOL bRet = FALSE; String sToFind; sToFind.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "', nFoundPos +1); bRet = TRUE; break; } nFoundPos = rPattern.Search( sToFind, nSearchFrom ); } return bRet; } //----------------------------------------------------------------------------- void SwForm::AdjustTabStops(SwDoc& rDoc) { for(USHORT nLevel = 1; nLevel < GetFormMax(); nLevel++) { const String& sTemplateName = GetTemplate(nLevel); SwTxtFmtColl* pColl = rDoc.FindTxtFmtCollByName( sTemplateName ); if( !pColl ) { USHORT nId = rDoc.GetPoolId( sTemplateName, GET_POOLID_TXTCOLL ); if( USHRT_MAX != nId ) pColl = rDoc.GetTxtCollFromPool( nId ); } if( pColl ) { const SvxTabStopItem& rTabStops = pColl->GetTabStops( FALSE ); USHORT nTabCount = rTabStops.Count(); String sCurrentPattern = GetPattern(nLevel); xub_StrLen nLastTabFoundEndPos = 0; BOOL bChanged = FALSE; for(USHORT nTab = 0; nTab < nTabCount; nTab++) { bChanged = TRUE; const SvxTabStop& rTab = rTabStops[nTab]; xub_StrLen nStart, nEnd; if( ::lcl_FindTabToken( sCurrentPattern, nLastTabFoundEndPos, nStart, nEnd )) { sCurrentPattern.Erase( nStart, nEnd - nStart + 1 ); // should look like: T ,,12345,2,_ long nPosition = rTab.GetTabPos(); USHORT eAlign = rTab.GetAdjustment(); sal_Unicode cFillChar = rTab.GetFill(); //create new token String sNewToken; sNewToken.AssignAscii( RTL_CONSTASCII_STRINGPARAM("') == rSource.GetTokenCount('<'), "count of '<' and '>' not identical") // simple task - convert tokens // -> // -> // -> // <#> -> <# > // -> // -> // -> for( xub_StrLen nFound = 0; STRING_NOTFOUND != ( nFound = sRet.Search( '>', nFound )); ) { sRet.Insert( ' ', nFound ); nFound += 2; // skip over the blank and '>' } //more complicated: convert text between >TEXT< to xub_StrLen nOpenStart = 0; xub_StrLen nCloseStart = 0; xub_StrLen nClosePos = sRet.Search('>', nCloseStart); xub_StrLen nOpenPos = sRet.Search('<', nOpenStart); if(nOpenPos != STRING_NOTFOUND && nOpenPos > 0) { USHORT nOffset = lcl_ConvertTextIntoPattern( sRet, 0, nOpenPos); nCloseStart += nOffset; nClosePos += nOffset; nOpenStart = nClosePos; } else nOpenStart = nClosePos; nOpenPos = sRet.Search('<', ++nOpenStart); while(nOpenPos != STRING_NOTFOUND) { if(nClosePos < nOpenPos - 1) { USHORT nOffset = lcl_ConvertTextIntoPattern(sRet, nClosePos + 1, nOpenPos); nOpenStart += nOffset; nCloseStart = nOpenStart; } else { nCloseStart = nClosePos; nOpenStart = nOpenPos; } nClosePos = sRet.Search('>', ++nCloseStart); nOpenPos = sRet.Search('<', ++nOpenStart); } //is there any text at the end? if(nClosePos != STRING_NOTFOUND && nClosePos < sRet.Len() - 1) lcl_ConvertTextIntoPattern(sRet, nClosePos + 1, sRet.Len()); if(eType != TOX_INDEX) { // set most left tab stop to right alignment and FillChar == '.' String sTabSearch; sTabSearch.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GetTOXTypes().GetPos( pType )) { // type not in pDoc, so create it now const SwTOXTypes& rTypes = pDoc->GetTOXTypes(); BOOL bFound = FALSE; for( USHORT n = rTypes.Count(); n; ) { const SwTOXType* pCmp = rTypes[ --n ]; if( pCmp->GetType() == pType->GetType() && pCmp->GetTypeName() == pType->GetTypeName() ) { pType = (SwTOXType*)pCmp; bFound = TRUE; break; } } if( !bFound ) pType = (SwTOXType*)pDoc->InsertTOXType( *pType ); } pType->Add( this ); nCreateType = rSource.nCreateType; aTitle = rSource.aTitle; aForm = rSource.aForm; bProtected = rSource.bProtected; bFromChapter = rSource.bFromChapter; bFromObjectNames = rSource.bFromObjectNames; sMainEntryCharStyle = rSource.sMainEntryCharStyle; sSequenceName = rSource.sSequenceName; eCaptionDisplay = rSource.eCaptionDisplay; nOLEOptions = rSource.nOLEOptions; eLanguage = rSource.eLanguage; sSortAlgorithm = rSource.sSortAlgorithm; for( USHORT i = 0; i < MAXLEVEL; ++i ) aStyleNames[i] = rSource.aStyleNames[i]; // its the same data type! aData.nOptions = rSource.aData.nOptions; if( !pDoc || pDoc->IsCopyIsMove() ) aName = rSource.GetTOXName(); else aName = pDoc->GetUniqueTOXBaseName( *pType, &rSource.GetTOXName() ); return *this; } /* -----------------30.06.99 14:46------------------- Check if any style names are set in the array --------------------------------------------------*/ BOOL SwTOXBase::HasAnyStyleNames() const { for(USHORT i = 0; i < MAXLEVEL; i++) if(aStyleNames[i].Len()) return TRUE; return FALSE; } /*-------------------------------------------------------------------- Beschreibung: Verzeichnisspezifische Funktionen --------------------------------------------------------------------*/ SwTOXBase::~SwTOXBase() { // if( GetTOXType()->GetType() == TOX_USER ) // delete aData.pTemplateName; } /* -----------------16.07.99 16:02------------------- --------------------------------------------------*/ SwFormTokenEnumerator::SwFormTokenEnumerator( const String& rPattern ) : sPattern( rPattern ), nCurPatternPos( 0 ), nCurPatternLen( 0 ) { #ifdef DBG_UTIL DBG_ASSERT( !sPattern.Len() || (sPattern.GetChar(0) == '<' && sPattern.GetChar(sPattern.Len() - 1) == '>'), "Pattern incorrect!" ) // strip all characters included in TOX_STYLE_DELIMITER String sTmp( sPattern ); xub_StrLen nFoundStt = sTmp.Search(TOX_STYLE_DELIMITER); while(nFoundStt != STRING_NOTFOUND) { xub_StrLen nFoundEnd = sTmp.Search(TOX_STYLE_DELIMITER, nFoundStt + 1); DBG_ASSERT(STRING_NOTFOUND != nFoundEnd, "Pattern incorrect") sTmp.Erase(nFoundStt, nFoundEnd - nFoundStt + 1); nFoundStt = sTmp.Search(TOX_STYLE_DELIMITER); } DBG_ASSERT( sTmp.GetTokenCount('<') == sTmp.GetTokenCount('>'), "Pattern incorrect!") #endif } /* -----------------29.06.99 11:55------------------- --------------------------------------------------*/ SwFormToken SwFormTokenEnumerator::GetNextToken() { xub_StrLen nTokenLen, nEnd; nCurPatternPos += nCurPatternLen; FormTokenType eTokenType = _SearchNextToken( nCurPatternPos, nEnd, &nTokenLen ); nCurPatternLen = nEnd - nCurPatternPos; return BuildToken( eTokenType, nTokenLen ); } SwFormToken SwFormTokenEnumerator::GetCurToken() const { xub_StrLen nTokenLen, nEnd; FormTokenType eTokenType = _SearchNextToken( nCurPatternPos, nEnd, &nTokenLen ); return BuildToken( eTokenType, nTokenLen ); } SwFormToken SwFormTokenEnumerator::BuildToken( FormTokenType eTokenType, xub_StrLen nTokenLen ) const { String sToken( sPattern.Copy( nCurPatternPos, nCurPatternLen )); // at this point sPattern contains the // character style name, the PoolId, tab stop position, tab stop alignment, chapter info format // the form is: CharStyleName, PoolId[, TabStopPosition|ChapterInfoFormat[, TabStopAlignment[, TabFillChar]]] // in text tokens the form differs from the others: CharStyleName, PoolId[,\0xffinserted text\0xff] SwFormToken eRet( eTokenType ); String sAuthFieldEnum = sToken.Copy( 2, 2 ); sToken = sToken.Copy( nTokenLen, sToken.Len() - nTokenLen - 1); eRet.sCharStyleName = sToken.GetToken( 0, ','); String sTmp( sToken.GetToken( 1, ',' )); if( sTmp.Len() ) eRet.nPoolId = sTmp.ToInt32(); switch( eTokenType ) { case TOKEN_TEXT: { xub_StrLen nStartText = sToken.Search( TOX_STYLE_DELIMITER ); if( STRING_NOTFOUND != nStartText ) { xub_StrLen nEndText = sToken.Search( TOX_STYLE_DELIMITER, nStartText + 1); if( STRING_NOTFOUND != nEndText ) { eRet.sText = sToken.Copy( nStartText + 1, nEndText - nStartText - 1); } } } break; case TOKEN_TAB_STOP: if( (sTmp = sToken.GetToken( 2, ',' ) ).Len() ) eRet.nTabStopPosition = sTmp.ToInt32(); if( (sTmp = sToken.GetToken( 3, ',' ) ).Len() ) eRet.eTabAlign = sTmp.ToInt32(); if( (sTmp = sToken.GetToken( 4, ',' ) ).Len() ) eRet.cTabFillChar = sTmp.GetChar(0); break; case TOKEN_CHAPTER_INFO: if( (sTmp = sToken.GetToken( 2, ',' ) ).Len() ) eRet.nChapterFormat = sTmp.ToInt32(); //SwChapterFormat; break; case TOKEN_AUTHORITY: eRet.nAuthorityField = sAuthFieldEnum.ToInt32(); break; } return eRet; } FormTokenType SwFormTokenEnumerator::_SearchNextToken( xub_StrLen nStt, xub_StrLen& rEnd, xub_StrLen* pTokenLen ) const { //it's not so easy - it doesn't work if the text part contains a '>' //USHORT nTokenEnd = sPattern.Search('>'); rEnd = sPattern.Search( '>', nStt ); if( STRING_NOTFOUND == rEnd ) { rEnd = sPattern.Len(); return TOKEN_END; } xub_StrLen nTextSeparatorFirst = sPattern.Search( TOX_STYLE_DELIMITER, nStt ); if( STRING_NOTFOUND != nTextSeparatorFirst ) { xub_StrLen nTextSeparatorSecond = sPattern.Search( TOX_STYLE_DELIMITER, nTextSeparatorFirst + 1 ); if( STRING_NOTFOUND != nTextSeparatorSecond && rEnd > nTextSeparatorFirst ) rEnd = sPattern.Search( '>', nTextSeparatorSecond ); } ++rEnd; String sToken( sPattern.Copy( nStt, rEnd - nStt ) ); static struct { const sal_Char* pNm; USHORT nLen; USHORT nOffset; FormTokenType eToken; } __READONLY_DATA aTokenArr[] = { SwForm::aFormTab, SwForm::nFormEntryLen, 1, TOKEN_TAB_STOP, SwForm::aFormPageNums, SwForm::nFormPageNumsLen, 1, TOKEN_PAGE_NUMS, SwForm::aFormLinkStt, SwForm::nFormLinkSttLen, 1, TOKEN_LINK_START, SwForm::aFormLinkEnd, SwForm::nFormLinkEndLen, 1, TOKEN_LINK_END, SwForm::aFormEntryNum, SwForm::nFormEntryNumLen, 1, TOKEN_ENTRY_NO, SwForm::aFormEntryTxt, SwForm::nFormEntryTxtLen, 1, TOKEN_ENTRY_TEXT, SwForm::aFormChapterMark,SwForm::nFormChapterMarkLen,1,TOKEN_CHAPTER_INFO, SwForm::aFormText, SwForm::nFormTextLen, 1, TOKEN_TEXT, SwForm::aFormEntry, SwForm::nFormEntryLen, 1, TOKEN_ENTRY, SwForm::aFormAuth, SwForm::nFormAuthLen, 3, TOKEN_AUTHORITY, 0, 0, 0, TOKEN_END }; FormTokenType eTokenType = TOKEN_TEXT; xub_StrLen nTokenLen = 0; const sal_Char* pNm; for( int i = 0; 0 != ( pNm = aTokenArr[ i ].pNm ); ++i ) if( COMPARE_EQUAL == sToken.CompareToAscii( pNm, aTokenArr[ i ].nLen - aTokenArr[ i ].nOffset )) { eTokenType = aTokenArr[ i ].eToken; nTokenLen = aTokenArr[ i ].nLen; break; } ASSERT( pNm, "wrong token" ); if( pTokenLen ) *pTokenLen = nTokenLen; return eTokenType; } FormTokenType SwFormTokenEnumerator::GetCurTokenType() { xub_StrLen nEnd; return _SearchNextToken( nCurPatternPos, nEnd ); } FormTokenType SwFormTokenEnumerator::GetNextTokenType() { xub_StrLen nEnd; nCurPatternPos += nCurPatternLen; FormTokenType eTokenType; if( nCurPatternPos < sPattern.Len() ) { eTokenType = _SearchNextToken( nCurPatternPos, nEnd ); nCurPatternLen = nEnd - nCurPatternPos; } else { eTokenType = TOKEN_END; nCurPatternLen = 0; } return eTokenType; } FormTokenType SwFormTokenEnumerator::GetPrevTokenType() { FormTokenType eTokenType = TOKEN_END; if( nCurPatternPos ) { xub_StrLen nStt = 0, nEnd; do { eTokenType = _SearchNextToken( nStt, nEnd ); if( nEnd == nCurPatternPos ) { nCurPatternPos = nStt; nCurPatternLen = nEnd - nStt; break; } nStt = nEnd; if( nStt >= sPattern.Len() ) { eTokenType = TOKEN_END; break; } } while( TRUE ); } return eTokenType; } void SwFormTokenEnumerator::RemoveCurToken() { if( nCurPatternLen ) { sPattern.Erase( nCurPatternPos, nCurPatternLen ); nCurPatternLen = 0; GetNextTokenType(); } } void SwFormTokenEnumerator::InsertToken( const SwFormToken& rToken ) { String sIns( rToken.GetString() ); if( sIns.Len() ) { sPattern.Insert( sIns, nCurPatternPos ); nCurPatternLen = sIns.Len(); GetNextTokenType(); } } String SwFormToken::GetString() const { String sRet; BOOL bAppend = TRUE; switch( eTokenType ) { case TOKEN_ENTRY_NO: sRet.AssignAscii( SwForm::aFormEntryNum ); break; case TOKEN_ENTRY_TEXT: sRet.AssignAscii( SwForm::aFormEntryTxt ); break; case TOKEN_ENTRY: sRet.AssignAscii( SwForm::aFormEntry ); break; case TOKEN_TAB_STOP: sRet.AssignAscii( SwForm::aFormTab ); break; case TOKEN_TEXT: sRet.AssignAscii( SwForm::aFormText ); break; case TOKEN_PAGE_NUMS: sRet.AssignAscii( SwForm::aFormPageNums ); break; case TOKEN_CHAPTER_INFO: sRet.AssignAscii( SwForm::aFormChapterMark ); break; case TOKEN_LINK_START: sRet.AssignAscii( SwForm::aFormLinkStt ); break; case TOKEN_LINK_END: sRet.AssignAscii( SwForm::aFormLinkEnd ); break; case TOKEN_AUTHORITY: { sRet.AssignAscii( SwForm::aFormAuth ); String sTmp( String::CreateFromInt32( nAuthorityField )); if( sTmp.Len() < 2 ) sTmp.Insert('0', 0); sRet.Insert( sTmp, 2 ); } break; } sRet.Erase( sRet.Len() - 1 ); sRet += ' '; sRet += sCharStyleName; sRet += ','; sRet += String::CreateFromInt32( nPoolId ); sRet += ','; // TabStopPosition and TabAlign or ChapterInfoFormat if(TOKEN_TAB_STOP == eTokenType) { sRet += String::CreateFromInt32( nTabStopPosition ); sRet += ','; sRet += String::CreateFromInt32( eTabAlign ); sRet += ','; sRet += cTabFillChar; } else if(TOKEN_CHAPTER_INFO == eTokenType) { sRet += String::CreateFromInt32( nChapterFormat ); } else if(TOKEN_TEXT == eTokenType) { //append Text if Len() > 0 only! if( sText.Len() ) { sRet += TOX_STYLE_DELIMITER; String sTmp( sText ); sTmp.EraseAllChars( TOX_STYLE_DELIMITER ); sRet += sTmp; sRet += TOX_STYLE_DELIMITER; } else bAppend = FALSE; } if(bAppend) { sRet += '>'; } else { // don't append empty text tokens sRet.Erase(); } return sRet; }