blob: da5d8d6c8a50aa15840a7ad17880280d8462b86d [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include <hintids.hxx>
#ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
#include <com/sun/star/i18n/ScriptType.hdl>
#endif
#include <tools/string.hxx>
#include <editeng/langitem.hxx>
#include <txatritr.hxx>
#include <fchrfmt.hxx>
#include <charfmt.hxx>
#include <breakit.hxx>
#include <ndtxt.hxx>
#include <txatbase.hxx>
using namespace ::com::sun::star::i18n;
SwScriptIterator::SwScriptIterator( const String& rStr, xub_StrLen nStt, sal_Bool bFrwrd )
: rText( rStr ),
nChgPos( rStr.Len() ),
nCurScript( ScriptType::WEAK ),
bForward( bFrwrd )
{
if( pBreakIt->GetBreakIter().is() )
{
if ( ! bFrwrd && nStt )
--nStt;
xub_StrLen nPos = nStt;
nCurScript = pBreakIt->GetBreakIter()->getScriptType( rText, nPos );
if( ScriptType::WEAK == nCurScript )
{
if( nPos )
{
nPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfScript(
rText, nPos, nCurScript );
if( nPos && nPos < rText.Len() )
{
nStt = --nPos;
nCurScript = pBreakIt->GetBreakIter()->getScriptType( rText,nPos);
}
}
}
nChgPos = bForward ?
(xub_StrLen)pBreakIt->GetBreakIter()->endOfScript( rText, nStt, nCurScript ) :
(xub_StrLen)pBreakIt->GetBreakIter()->beginOfScript( rText, nStt, nCurScript );
}
}
sal_Bool SwScriptIterator::Next()
{
sal_Bool bRet = sal_False;
if( pBreakIt->GetBreakIter().is() )
{
if ( bForward && nChgPos < rText.Len() )
{
nCurScript = pBreakIt->GetBreakIter()->getScriptType( rText, nChgPos );
nChgPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript(
rText, nChgPos, nCurScript );
bRet = sal_True;
}
else if ( ! bForward && nChgPos )
{
--nChgPos;
nCurScript = pBreakIt->GetBreakIter()->getScriptType( rText, nChgPos );
nChgPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfScript(
rText, nChgPos, nCurScript );
bRet = sal_True;
}
}
else
nChgPos = rText.Len();
return bRet;
}
// --------------------------------------------------------------------
SwTxtAttrIterator::SwTxtAttrIterator( const SwTxtNode& rTNd, sal_uInt16 nWhchId,
xub_StrLen nStt,
sal_Bool bUseGetWhichOfScript )
: aSIter( rTNd.GetTxt(), nStt ), rTxtNd( rTNd ),
pParaItem( 0 ), nChgPos( nStt ), nAttrPos( 0 ), nWhichId( nWhchId ),
bIsUseGetWhichOfScript( bUseGetWhichOfScript )
{
SearchNextChg();
}
sal_Bool SwTxtAttrIterator::Next()
{
sal_Bool bRet = sal_False;
if( nChgPos < aSIter.GetText().Len() )
{
bRet = sal_True;
if( aStack.Count() )
{
do {
const SwTxtAttr* pHt = (SwTxtAttr*)aStack[ 0 ];
const sal_uInt16 nEndPos = *pHt->End();
if( nChgPos >= nEndPos )
aStack.Remove( 0 );
else
break;
} while( aStack.Count() );
}
if( aStack.Count() )
{
sal_uInt16 nSavePos = nAttrPos;
SearchNextChg();
if( aStack.Count() )
{
const SwTxtAttr* pHt = (SwTxtAttr*)aStack[ 0 ];
const sal_uInt16 nEndPos = *pHt->End();
if( nChgPos >= nEndPos )
{
nChgPos = nEndPos;
nAttrPos = nSavePos;
if( RES_TXTATR_CHARFMT == pHt->Which() )
{
sal_uInt16 nWId = bIsUseGetWhichOfScript ?
GetWhichOfScript( nWhichId,
aSIter.GetCurrScript() ) : nWhichId;
pCurItem = &pHt->GetCharFmt().GetCharFmt()->GetFmtAttr(nWId);
}
else
pCurItem = &pHt->GetAttr();
aStack.Remove( 0 );
}
}
}
else
SearchNextChg();
}
return bRet;
}
void SwTxtAttrIterator::AddToStack( const SwTxtAttr& rAttr )
{
void* pAdd = (void*)&rAttr;
sal_uInt16 nIns = 0, nEndPos = *rAttr.End();
for( ; nIns < aStack.Count(); ++nIns )
if( *((SwTxtAttr*)aStack[ nIns ] )->GetEnd() > nEndPos )
break;
aStack.Insert( pAdd, nIns );
}
void SwTxtAttrIterator::SearchNextChg()
{
sal_uInt16 nWh = 0;
if( nChgPos == aSIter.GetScriptChgPos() )
{
aSIter.Next();
pParaItem = 0;
nAttrPos = 0; // must be restart at the beginning, because
// some attributes can start before or inside
// the current scripttype!
aStack.Remove( 0, aStack.Count() );
}
if( !pParaItem )
{
nWh = bIsUseGetWhichOfScript ?
GetWhichOfScript( nWhichId,
aSIter.GetCurrScript() ) : nWhichId;
pParaItem = &rTxtNd.GetSwAttrSet().Get( nWh );
}
xub_StrLen nStt = nChgPos;
nChgPos = aSIter.GetScriptChgPos();
pCurItem = pParaItem;
const SwpHints* pHts = rTxtNd.GetpSwpHints();
if( pHts )
{
if( !nWh )
{
nWh = bIsUseGetWhichOfScript ?
GetWhichOfScript( nWhichId,
aSIter.GetCurrScript() ) : nWhichId;
}
const SfxPoolItem* pItem = 0;
for( ; nAttrPos < pHts->Count(); ++nAttrPos )
{
const SwTxtAttr* pHt = (*pHts)[ nAttrPos ];
const sal_uInt16* pEnd = pHt->End();
const sal_uInt16 nHtStt = *pHt->GetStart();
if( nHtStt < nStt && ( !pEnd || *pEnd <= nStt ))
continue;
if( nHtStt >= nChgPos )
break;
pItem = CharFmt::GetItem( *pHt, nWh );
if ( pItem )
{
if( nHtStt > nStt )
{
if( nChgPos > nHtStt )
nChgPos = nHtStt;
break;
}
AddToStack( *pHt );
pCurItem = pItem;
if( *pEnd < nChgPos )
nChgPos = *pEnd;
}
}
}
}