blob: 290799a8ab22b00ee7babc5d2e23f374a84e98f6 [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 <pam.hxx> // GetSpaces
#include <txtcfg.hxx>
#include <frminf.hxx> // SwTxtFrminfo
#include <itrtxt.hxx> // SwTxtMargin
/*************************************************************************
* SwTxtMargin::GetTxtStart()
*************************************************************************/
xub_StrLen SwTxtMargin::GetTxtStart() const
{
const XubString &rTxt = GetInfo().GetTxt();
const xub_StrLen nTmpPos = nStart;
const xub_StrLen nEnd = nTmpPos + pCurr->GetLen();
xub_StrLen i;
for( i = nTmpPos; i < nEnd; ++i )
{
const xub_Unicode aChar = rTxt.GetChar( i );
if( CH_TAB != aChar && ' ' != aChar )
return i;
}
return i;
}
/*************************************************************************
* SwTxtMargin::GetTxtEnd()
*************************************************************************/
xub_StrLen SwTxtMargin::GetTxtEnd() const
{
const XubString &rTxt = GetInfo().GetTxt();
const xub_StrLen nTmpPos = nStart;
const xub_StrLen nEnd = nTmpPos + pCurr->GetLen();
long i;
for( i = nEnd - 1; i >= nTmpPos; --i )
{
xub_Unicode aChar = rTxt.GetChar( static_cast<xub_StrLen>(i) );
if( CH_TAB != aChar && CH_BREAK != aChar && ' ' != aChar )
return static_cast<xub_StrLen>(i + 1);
}
return static_cast<xub_StrLen>(i + 1);
}
/*************************************************************************
* SwTxtFrmInfo::IsOneLine()
*************************************************************************/
// Passt der Absatz in eine Zeile?
sal_Bool SwTxtFrmInfo::IsOneLine() const
{
const SwLineLayout *pLay = pFrm->GetPara();
if( !pLay )
return sal_False;
else
{
// 6575: bei Follows natuerlich sal_False
if( pFrm->GetFollow() )
return sal_False;
pLay = pLay->GetNext();
while( pLay )
{
if( pLay->GetLen() )
return sal_False;
pLay = pLay->GetNext();
}
return sal_True;
}
}
/*************************************************************************
* SwTxtFrmInfo::IsFilled()
*************************************************************************/
// Ist die Zeile zu X% gefuellt?
sal_Bool SwTxtFrmInfo::IsFilled( const sal_uInt8 nPercent ) const
{
const SwLineLayout *pLay = pFrm->GetPara();
if( !pLay )
return sal_False;
else
{
long nWidth = pFrm->Prt().Width();
nWidth *= nPercent;
nWidth /= 100;
return KSHORT(nWidth) <= pLay->Width();
}
}
/*************************************************************************
* SwTxtFrmInfo::GetLineStart()
*************************************************************************/
// Wo beginnt der Text (ohne whitespaces)? ( Dokument global )
SwTwips SwTxtFrmInfo::GetLineStart( const SwTxtCursor &rLine ) const
{
xub_StrLen nTxtStart = rLine.GetTxtStart();
SwTwips nStart;
if( rLine.GetStart() == nTxtStart )
nStart = rLine.GetLineStart();
else
{
SwRect aRect;
if( ((SwTxtCursor&)rLine).GetCharRect( &aRect, nTxtStart ) )
nStart = aRect.Left();
else
nStart = rLine.GetLineStart();
}
return nStart;
}
/*************************************************************************
* SwTxtFrmInfo::GetLineStart()
*************************************************************************/
// Wo beginnt der Text (ohne whitespaces)? (rel. im Frame)
SwTwips SwTxtFrmInfo::GetLineStart() const
{
SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm );
SwTxtCursor aLine( (SwTxtFrm*)pFrm, &aInf );
return GetLineStart( aLine ) - pFrm->Frm().Left() - pFrm->Prt().Left();
}
// errechne die Position des Zeichens und gebe die Mittelposition zurueck
SwTwips SwTxtFrmInfo::GetCharPos( xub_StrLen nChar, sal_Bool bCenter ) const
{
SWRECTFN( pFrm )
SwFrmSwapper aSwapper( pFrm, sal_True );
SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm );
SwTxtCursor aLine( (SwTxtFrm*)pFrm, &aInf );
SwTwips nStt, nNext;
SwRect aRect;
if( ((SwTxtCursor&)aLine).GetCharRect( &aRect, nChar ) )
{
if ( bVert )
pFrm->SwitchHorizontalToVertical( aRect );
nStt = (aRect.*fnRect->fnGetLeft)();
}
else
nStt = aLine.GetLineStart();
if( !bCenter )
return nStt - (pFrm->Frm().*fnRect->fnGetLeft)();
if( ((SwTxtCursor&)aLine).GetCharRect( &aRect, nChar+1 ) )
{
if ( bVert )
pFrm->SwitchHorizontalToVertical( aRect );
nNext = (aRect.*fnRect->fnGetLeft)();
}
else
nNext = aLine.GetLineStart();
return (( nNext + nStt ) / 2 ) - (pFrm->Frm().*fnRect->fnGetLeft)();
}
/*************************************************************************
* SwTxtFrmInfo::GetSpaces()
*************************************************************************/
SwPaM *AddPam( SwPaM *pPam, const SwTxtFrm* pTxtFrm,
const xub_StrLen nPos, const xub_StrLen nLen )
{
if( nLen )
{
// Es koennte auch der erste sein.
if( pPam->HasMark() )
{
// liegt die neue Position genau hinter der aktuellen, dann
// erweiter den Pam einfach
if( nPos == pPam->GetPoint()->nContent.GetIndex() )
{
pPam->GetPoint()->nContent += nLen;
return pPam;
}
pPam = new SwPaM( *pPam );
}
SwIndex &rContent = pPam->GetPoint()->nContent;
rContent.Assign( (SwTxtNode*)pTxtFrm->GetTxtNode(), nPos );
pPam->SetMark();
rContent += nLen;
}
return pPam;
}
// Sammelt die whitespaces am Zeilenbeginn und -ende im Pam
void SwTxtFrmInfo::GetSpaces( SwPaM &rPam, sal_Bool bWithLineBreak ) const
{
SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm );
SwTxtMargin aLine( (SwTxtFrm*)pFrm, &aInf );
SwPaM *pPam = &rPam;
sal_Bool bFirstLine = sal_True;
do {
if( aLine.GetCurr()->GetLen() )
{
xub_StrLen nPos = aLine.GetTxtStart();
// Bug 49649: von der ersten Line die Blanks/Tabs NICHT
// mit selektieren
if( !bFirstLine && nPos > aLine.GetStart() )
pPam = AddPam( pPam, pFrm, aLine.GetStart(),
nPos - aLine.GetStart() );
// Bug 49649: von der letzten Line die Blanks/Tabs NICHT
// mit selektieren
if( aLine.GetNext() )
{
nPos = aLine.GetTxtEnd();
if( nPos < aLine.GetEnd() )
{
MSHORT nOff = !bWithLineBreak && CH_BREAK ==
aLine.GetInfo().GetChar( aLine.GetEnd() - 1 )
? 1 : 0;
pPam = AddPam( pPam, pFrm, nPos, aLine.GetEnd() - nPos - nOff );
}
}
}
bFirstLine = sal_False;
}
while( aLine.Next() );
}
/*************************************************************************
* SwTxtFrmInfo::IsBullet()
*************************************************************************/
// Ist an der Textposition ein Bullet/Symbol etc?
// Fonts: CharSet, SYMBOL und DONTKNOW
sal_Bool SwTxtFrmInfo::IsBullet( xub_StrLen nTxtStart ) const
{
SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm );
SwTxtMargin aLine( (SwTxtFrm*)pFrm, &aInf );
aInf.SetIdx( nTxtStart );
return aLine.IsSymbol( nTxtStart );
}
/*************************************************************************
* SwTxtFrmInfo::GetFirstIndent()
*************************************************************************/
// Ermittelt Erstzeileneinzug
// Voraussetzung fuer pos. oder neg. EZE ist, dass alle
// Zeilen ausser der ersten Zeile den selben linken Rand haben.
// Wir wollen nicht so knauserig sein und arbeiten mit einer Toleranz
// von TOLERANCE Twips.
#define TOLERANCE 20
SwTwips SwTxtFrmInfo::GetFirstIndent() const
{
SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm );
SwTxtCursor aLine( (SwTxtFrm*)pFrm, &aInf );
const SwTwips nFirst = GetLineStart( aLine );
if( !aLine.Next() )
return 0;
SwTwips nLeft = GetLineStart( aLine );
while( aLine.Next() )
{
if( aLine.GetCurr()->GetLen() )
{
const SwTwips nCurrLeft = GetLineStart( aLine );
if( nLeft + TOLERANCE < nCurrLeft ||
nLeft - TOLERANCE > nCurrLeft )
return 0;
}
}
// Vorerst wird nur +1, -1 und 0 returnt.
if( nLeft == nFirst )
return 0;
else
if( nLeft > nFirst )
return -1;
else
return +1;
}
/*************************************************************************
* SwTxtFrmInfo::GetBigIndent()
*************************************************************************/
KSHORT SwTxtFrmInfo::GetBigIndent( xub_StrLen& rFndPos,
const SwTxtFrm *pNextFrm ) const
{
SwTxtSizeInfo aInf( (SwTxtFrm*)pFrm );
SwTxtCursor aLine( (SwTxtFrm*)pFrm, &aInf );
SwTwips nNextIndent = 0;
if( pNextFrm )
{
// ich bin einzeilig
SwTxtSizeInfo aNxtInf( (SwTxtFrm*)pNextFrm );
SwTxtCursor aNxtLine( (SwTxtFrm*)pNextFrm, &aNxtInf );
nNextIndent = GetLineStart( aNxtLine );
}
else
{
// ich bin mehrzeilig
if( aLine.Next() )
{
nNextIndent = GetLineStart( aLine );
aLine.Prev();
}
}
if( nNextIndent <= GetLineStart( aLine ) )
return 0;
const Point aPoint( nNextIndent, aLine.Y() );
rFndPos = aLine.GetCrsrOfst( 0, aPoint, sal_False );
if( 1 >= rFndPos )
return 0;
// steht vor einem "nicht Space"
const XubString& rTxt = aInf.GetTxt();
xub_Unicode aChar = rTxt.GetChar( rFndPos );
if( CH_TAB == aChar || CH_BREAK == aChar || ' ' == aChar ||
(( CH_TXTATR_BREAKWORD == aChar || CH_TXTATR_INWORD == aChar ) &&
aInf.HasHint( rFndPos ) ) )
return 0;
// und hinter einem "Space"
aChar = rTxt.GetChar( rFndPos - 1 );
if( CH_TAB != aChar && CH_BREAK != aChar &&
( ( CH_TXTATR_BREAKWORD != aChar && CH_TXTATR_INWORD != aChar ) ||
!aInf.HasHint( rFndPos - 1 ) ) &&
// mehr als 2 Blanks !!
( ' ' != aChar || ' ' != rTxt.GetChar( rFndPos - 2 ) ) )
return 0;
SwRect aRect;
return aLine.GetCharRect( &aRect, rFndPos )
? KSHORT( aRect.Left() - pFrm->Frm().Left() - pFrm->Prt().Left())
: 0;
}