1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <hintids.hxx>
21 #include <editeng/charscaleitem.hxx>
23 #include <sfx2/printer.hxx>
24 #include <svx/svdobj.hxx>
25 #include <vcl/window.hxx>
26 #include <vcl/svapp.hxx>
27 #include <fmtanchr.hxx>
28 #include <fmtfsize.hxx>
29 #include <fmtornt.hxx>
30 #include <fmtflcnt.hxx>
31 #include <fmtcntnt.hxx>
37 #include <viewsh.hxx> // ViewShell
38 #include <rootfrm.hxx>
41 #include <dcontact.hxx>
42 #include <fldbas.hxx> // SwField
43 #include <pam.hxx> // SwPosition (lcl_MinMaxNode)
45 #include <htmltbl.hxx>
46 #include <swtable.hxx>
47 #include <redlnitr.hxx>
48 #include <fmtsrnd.hxx>
50 #include <breakit.hxx>
51 #include <com/sun/star/i18n/WordType.hpp>
52 #include <com/sun/star/i18n/ScriptType.hpp>
53 #include <editeng/lrspitem.hxx>
54 #include <switerator.hxx>
55 #include <boost/foreach.hpp>
57 using namespace ::com::sun::star::i18n
;
58 using namespace ::com::sun::star
;
60 /*************************************************************************
62 *************************************************************************/
64 void SwAttrIter::Chg( SwTxtAttr
*pHt
)
66 OSL_ENSURE( pHt
&& pFnt
, "No attribute of font available for change");
67 if( pRedln
&& pRedln
->IsOn() )
68 pRedln
->ChangeTxtAttr( pFnt
, *pHt
, sal_True
);
70 aAttrHandler
.PushAndChg( *pHt
, *pFnt
);
74 /*************************************************************************
76 *************************************************************************/
78 void SwAttrIter::Rst( SwTxtAttr
*pHt
)
80 OSL_ENSURE( pHt
&& pFnt
, "No attribute of font available for reset");
81 // get top from stack after removing pHt
82 if( pRedln
&& pRedln
->IsOn() )
83 pRedln
->ChangeTxtAttr( pFnt
, *pHt
, sal_False
);
85 aAttrHandler
.PopAndChg( *pHt
, *pFnt
);
89 /*************************************************************************
90 * virtual SwAttrIter::~SwAttrIter()
91 *************************************************************************/
93 SwAttrIter::~SwAttrIter()
99 /*************************************************************************
100 * SwAttrIter::GetAttr()
102 * Liefert fuer eine Position das Attribut, wenn das Attribut genau auf
103 * der Position nPos liegt und kein EndIndex besitzt.
104 * GetAttr() wird fuer Attribute benoetigt, die die Formatierung beeinflussen
105 * sollen, ohne dabei den Inhalt des Strings zu veraendern. Solche "entarteten"
106 * Attribute sind z.B. Felder (die expandierten Text bereit halten) und
107 * zeilengebundene Frames. Um Mehrdeutigkeiten zwischen verschiedenen
108 * solcher Attribute zu vermeiden, werden beim Anlegen eines Attributs
109 * an der Startposition ein Sonderzeichen in den String einfuegt.
110 * Der Formatierer stoesst auf das Sonderzeichen und holt sich per
111 * GetAttr() das entartete Attribut.
112 *************************************************************************/
114 SwTxtAttr
*SwAttrIter::GetAttr( const xub_StrLen nPosition
) const
116 return (m_pTxtNode
) ? m_pTxtNode
->GetTxtAttrForCharAt(nPosition
) : 0;
119 /*************************************************************************
120 * SwAttrIter::SeekAndChg()
121 *************************************************************************/
123 sal_Bool
SwAttrIter::SeekAndChgAttrIter( const xub_StrLen nNewPos
, OutputDevice
* pOut
)
125 sal_Bool bChg
= nStartIndex
&& nNewPos
== nPos
? pFnt
->IsFntChg() : Seek( nNewPos
);
126 if ( pLastOut
!= pOut
)
129 pFnt
->SetFntChg( sal_True
);
134 // wenn der Aenderungszaehler auf Null ist, kennen wir die MagicNo
135 // des gewuenschten Fonts ...
136 if ( !nChgCnt
&& !nPropFont
)
137 pFnt
->SetMagic( aMagicNo
[ pFnt
->GetActual() ],
138 aFntIdx
[ pFnt
->GetActual() ], pFnt
->GetActual() );
139 pFnt
->ChgPhysFnt( pShell
, *pOut
);
144 sal_Bool
SwAttrIter::IsSymbol( const xub_StrLen nNewPos
)
147 if ( !nChgCnt
&& !nPropFont
)
148 pFnt
->SetMagic( aMagicNo
[ pFnt
->GetActual() ],
149 aFntIdx
[ pFnt
->GetActual() ], pFnt
->GetActual() );
150 return pFnt
->IsSymbol( pShell
);
153 /*************************************************************************
154 * SwAttrIter::SeekStartAndChg()
155 *************************************************************************/
157 sal_Bool
SwAttrIter::SeekStartAndChgAttrIter( OutputDevice
* pOut
, const sal_Bool bParaFont
)
159 if ( pRedln
&& pRedln
->ExtOn() )
160 pRedln
->LeaveExtend( *pFnt
, 0 );
162 // reset font to its original state
163 aAttrHandler
.Reset();
164 aAttrHandler
.ResetFont( *pFnt
);
166 nStartIndex
= nEndIndex
= nPos
= nChgCnt
= 0;
168 pFnt
->SetProportion( nPropFont
);
171 pRedln
->Clear( pFnt
);
173 nChgCnt
= nChgCnt
+ pRedln
->Seek( *pFnt
, 0, STRING_LEN
);
178 if ( pHints
&& !bParaFont
)
181 // Solange wir noch nicht am Ende des StartArrays angekommen sind &&
182 // das TextAttribut an Position 0 beginnt ...
183 while ( ( nStartIndex
< pHints
->GetStartCount() ) &&
184 !(*(pTxtAttr
=pHints
->GetStart(nStartIndex
))->GetStart()) )
186 // oeffne die TextAttribute
192 sal_Bool bChg
= pFnt
->IsFntChg();
193 if ( pLastOut
!= pOut
)
196 pFnt
->SetFntChg( sal_True
);
201 // wenn der Aenderungszaehler auf Null ist, kennen wir die MagicNo
202 // des gewuenschten Fonts ...
203 if ( !nChgCnt
&& !nPropFont
)
204 pFnt
->SetMagic( aMagicNo
[ pFnt
->GetActual() ],
205 aFntIdx
[ pFnt
->GetActual() ], pFnt
->GetActual() );
206 pFnt
->ChgPhysFnt( pShell
, *pOut
);
211 /*************************************************************************
212 * SwAttrIter::SeekFwd()
213 *************************************************************************/
215 // AMA: Neuer AttrIter Nov 94
217 void SwAttrIter::SeekFwd( const xub_StrLen nNewPos
)
221 if ( nStartIndex
) // wenn ueberhaupt schon Attribute geoeffnet wurden...
223 // Schliesse Attr, die z. Z. geoeffnet sind, vor nNewPos+1 aber enden.
225 // Solange wir noch nicht am Ende des EndArrays angekommen sind &&
226 // das TextAttribut vor oder an der neuen Position endet ...
227 while ( ( nEndIndex
< pHints
->GetEndCount() ) &&
228 (*(pTxtAttr
=pHints
->GetEnd(nEndIndex
))->GetAnyEnd()<=nNewPos
))
230 // schliesse die TextAttribute, deren StartPos vor
231 // oder an der alten nPos lag, die z.Z. geoeffnet sind.
232 if (*pTxtAttr
->GetStart() <= nPos
) Rst( pTxtAttr
);
236 else // ueberlies die nicht geoeffneten Enden
238 while ( ( nEndIndex
< pHints
->GetEndCount() ) &&
239 (*(pTxtAttr
=pHints
->GetEnd(nEndIndex
))->GetAnyEnd()<=nNewPos
))
244 // Solange wir noch nicht am Ende des StartArrays angekommen sind &&
245 // das TextAttribut vor oder an der neuen Position beginnt ...
246 while ( ( nStartIndex
< pHints
->GetStartCount() ) &&
247 (*(pTxtAttr
=pHints
->GetStart(nStartIndex
))->GetStart()<=nNewPos
))
249 // oeffne die TextAttribute, deren Ende hinter der neuen Position liegt
250 if ( *pTxtAttr
->GetAnyEnd() > nNewPos
) Chg( pTxtAttr
);
256 /*************************************************************************
258 *************************************************************************/
260 sal_Bool
SwAttrIter::Seek( const xub_StrLen nNewPos
)
262 if ( pRedln
&& pRedln
->ExtOn() )
263 pRedln
->LeaveExtend( *pFnt
, nNewPos
);
267 if( !nNewPos
|| nNewPos
< nPos
)
270 pRedln
->Clear( NULL
);
272 // reset font to its original state
273 aAttrHandler
.Reset();
274 aAttrHandler
.ResetFont( *pFnt
);
277 pFnt
->SetProportion( nPropFont
);
278 nStartIndex
= nEndIndex
= nPos
= 0;
282 // resetting the font here makes it necessary to apply any
283 // changes for extended input directly to the font
284 if ( pRedln
&& pRedln
->ExtOn() )
286 pRedln
->UpdateExtFont( *pFnt
);
293 pFnt
->SetActual( SwScriptInfo::WhichFont( nNewPos
, 0, pScriptInfo
) );
296 nChgCnt
= nChgCnt
+ pRedln
->Seek( *pFnt
, nNewPos
, nPos
);
300 pFnt
->SetProportion( nPropFont
);
302 return pFnt
->IsFntChg();
305 /*************************************************************************
306 * SwAttrIter::GetNextAttr()
307 *************************************************************************/
309 xub_StrLen
SwAttrIter::GetNextAttr( ) const
311 xub_StrLen nNext
= STRING_LEN
;
314 if (pHints
->GetStartCount() > nStartIndex
) // Gibt es noch Starts?
315 nNext
= (*pHints
->GetStart(nStartIndex
)->GetStart());
316 if (pHints
->GetEndCount() > nEndIndex
) // Gibt es noch Enden?
318 xub_StrLen nNextEnd
= (*pHints
->GetEnd(nEndIndex
)->GetAnyEnd());
319 if ( nNextEnd
<nNext
) nNext
= nNextEnd
; // Wer ist naeher?
322 if (m_pTxtNode
!=NULL
) {
323 //TODO maybe use hints like FieldHints for this instead of looking at the text...
324 int l
=(nNext
<m_pTxtNode
->Len()?nNext
:m_pTxtNode
->Len());
326 const sal_Unicode
*txt
=m_pTxtNode
->GetTxt().GetBuffer();
327 while(p
<l
&& txt
[p
]!=CH_TXT_ATR_FIELDSTART
&& txt
[p
]!=CH_TXT_ATR_FIELDEND
&& txt
[p
]!=CH_TXT_ATR_FORMELEMENT
) p
++;
328 if ((p
<l
&& p
>nPos
) || nNext
<=p
)
334 return pRedln
->GetNextRedln( nNext
);
349 xub_StrLen nNoLineBreak
;
350 SwMinMaxArgs( OutputDevice
* pOutI
, ViewShell
* pShI
, sal_uLong
& rMinI
, sal_uLong
&rMaxI
, sal_uLong
&rAbsI
)
351 : pOut( pOutI
), pSh( pShI
), rMin( rMinI
), rMax( rMaxI
), rAbsMin( rAbsI
)
352 { nRowWidth
= nWordWidth
= nWordAdd
= 0; nNoLineBreak
= STRING_LEN
; }
353 void Minimum( long nNew
) const { if( (long)rMin
< nNew
) rMin
= nNew
; }
354 void NewWord() { nWordAdd
= nWordWidth
= 0; }
357 static sal_Bool
lcl_MinMaxString( SwMinMaxArgs
& rArg
, SwFont
* pFnt
, const XubString
&rTxt
,
358 xub_StrLen nIdx
, xub_StrLen nEnd
)
360 sal_Bool bRet
= sal_False
;
363 xub_StrLen nStop
= nIdx
;
365 LanguageType eLang
= pFnt
->GetLanguage();
366 if( pBreakIt
->GetBreakIter().is() )
368 bClear
= CH_BLANK
== rTxt
.GetChar( nStop
);
369 Boundary
aBndry( pBreakIt
->GetBreakIter()->getWordBoundary( rTxt
, nIdx
,
370 pBreakIt
->GetLocale( eLang
),
371 WordType::DICTIONARY_WORD
, sal_True
) );
372 nStop
= (xub_StrLen
)aBndry
.endPos
;
373 if( nIdx
<= aBndry
.startPos
&& nIdx
&& nIdx
-1 != rArg
.nNoLineBreak
)
382 while( nStop
< nEnd
&& CH_BLANK
!= rTxt
.GetChar( nStop
) )
384 bClear
= nStop
== nIdx
;
388 while( nStop
< nEnd
&& CH_BLANK
== rTxt
.GetChar( nStop
) )
393 SwDrawTextInfo
aDrawInf( rArg
.pSh
, *rArg
.pOut
, 0, rTxt
, nIdx
, nStop
- nIdx
);
394 long nAktWidth
= pFnt
->_GetTxtSize( aDrawInf
).Width();
395 rArg
.nRowWidth
+= nAktWidth
;
400 rArg
.nWordWidth
+= nAktWidth
;
401 if( (long)rArg
.rAbsMin
< rArg
.nWordWidth
)
402 rArg
.rAbsMin
= rArg
.nWordWidth
;
403 rArg
.Minimum( rArg
.nWordWidth
+ rArg
.nWordAdd
);
411 sal_Bool
SwTxtNode::IsSymbol( const xub_StrLen nBegin
) const//swmodtest 080307
413 SwScriptInfo aScriptInfo
;
414 SwAttrIter
aIter( *(SwTxtNode
*)this, aScriptInfo
);
415 aIter
.Seek( nBegin
);
416 return aIter
.GetFnt()->IsSymbol(
417 const_cast<ViewShell
*>(getIDocumentLayoutAccess()->GetCurrentViewShell()) );//swmod 080311
420 class SwMinMaxNodeArgs
423 sal_uLong nMaxWidth
; // Summe aller Rahmenbreite
424 long nMinWidth
; // Breitester Rahmen
425 long nLeftRest
; // noch nicht von Rahmen ueberdeckter Platz im l. Rand
426 long nRightRest
; // noch nicht von Rahmen ueberdeckter Platz im r. Rand
427 long nLeftDiff
; // Min/Max-Differenz des Rahmens im linken Rand
428 long nRightDiff
; // Min/Max-Differenz des Rahmens im rechten Rand
429 sal_uLong nIndx
; // Indexnummer des Nodes
430 void Minimum( long nNew
) { if( nNew
> nMinWidth
) nMinWidth
= nNew
; }
433 static void lcl_MinMaxNode( SwFrmFmt
* pNd
, SwMinMaxNodeArgs
* pIn
)
435 const SwFmtAnchor
& rFmtA
= pNd
->GetAnchor();
437 bool bCalculate
= false;
438 if ((FLY_AT_PARA
== rFmtA
.GetAnchorId()) ||
439 (FLY_AT_CHAR
== rFmtA
.GetAnchorId()))
446 const SwPosition
*pPos
= rFmtA
.GetCntntAnchor();
447 OSL_ENSURE(pPos
&& pIn
, "Unexpected NULL arguments");
448 if (!pPos
|| !pIn
|| pIn
->nIndx
!= pPos
->nNode
.GetIndex())
455 SwHTMLTableLayout
*pLayout
= 0;
456 MSHORT nWhich
= pNd
->Which();
457 if( RES_DRAWFRMFMT
!= nWhich
)
459 // Enthaelt der Rahmen zu Beginn oder am Ende eine Tabelle?
460 const SwNodes
& rNodes
= pNd
->GetDoc()->GetNodes();
461 const SwFmtCntnt
& rFlyCntnt
= pNd
->GetCntnt();
462 sal_uLong nStt
= rFlyCntnt
.GetCntntIdx()->GetIndex();
463 SwTableNode
* pTblNd
= rNodes
[nStt
+1]->GetTableNode();
466 SwNode
*pNd2
= rNodes
[nStt
];
467 pNd2
= rNodes
[pNd2
->EndOfSectionIndex()-1];
468 if( pNd2
->IsEndNode() )
469 pTblNd
= pNd2
->StartOfSectionNode()->GetTableNode();
473 pLayout
= pTblNd
->GetTable().GetHTMLTableLayout();
476 const SwFmtHoriOrient
& rOrient
= pNd
->GetHoriOrient();
477 sal_Int16 eHoriOri
= rOrient
.GetHoriOrient();
482 nMin
= pLayout
->GetMin();
483 nMax
= pLayout
->GetMax();
488 if( RES_DRAWFRMFMT
== nWhich
)
490 const SdrObject
* pSObj
= pNd
->FindSdrObject();
492 nMin
= pSObj
->GetCurrentBoundRect().GetWidth();
499 const SwFmtFrmSize
&rSz
= pNd
->GetFrmSize();
500 nMin
= rSz
.GetWidth();
506 const SvxLRSpaceItem
&rLR
= pNd
->GetLRSpace();
507 nMin
+= rLR
.GetLeft();
508 nMin
+= rLR
.GetRight();
509 nMax
+= rLR
.GetLeft();
510 nMax
+= rLR
.GetRight();
512 if( SURROUND_THROUGHT
== pNd
->GetSurround().GetSurround() )
514 pIn
->Minimum( nMin
);
518 // Rahmen, die recht bzw. links ausgerichtet sind, gehen nur
519 // teilweise in die Max-Berechnung ein, da der Rand schon berueck-
520 // sichtigt wird. Nur wenn die Rahmen in den Textkoerper ragen,
521 // wird dieser Teil hinzuaddiert.
524 case text::HoriOrientation::RIGHT
:
528 pIn
->nRightRest
-= pIn
->nRightDiff
;
529 pIn
->nRightDiff
= nDiff
;
531 if( text::RelOrientation::FRAME
!= rOrient
.GetRelationOrient() )
533 if( pIn
->nRightRest
> 0 )
536 pIn
->nRightRest
-= nMin
;
539 case text::HoriOrientation::LEFT
:
543 pIn
->nLeftRest
-= pIn
->nLeftDiff
;
544 pIn
->nLeftDiff
= nDiff
;
546 if( text::RelOrientation::FRAME
!= rOrient
.GetRelationOrient() &&
549 pIn
->nLeftRest
-= nMin
;
554 pIn
->nMaxWidth
+= nMax
;
555 pIn
->Minimum( nMin
);
561 #define FLYINCNT_MIN_WIDTH 284
563 // changing this method very likely requires changing of
564 // "GetScalingOfSelectedText"
565 void SwTxtNode::GetMinMaxSize( sal_uLong nIndex
, sal_uLong
& rMin
, sal_uLong
&rMax
,
566 sal_uLong
& rAbsMin
, OutputDevice
* pOut
) const
569 GetDoc()->GetEditShell( &pSh
);
573 pOut
= pSh
->GetWin();
575 pOut
= GetpApp()->GetDefaultDevice();
578 MapMode
aOldMap( pOut
->GetMapMode() );
579 pOut
->SetMapMode( MapMode( MAP_TWIP
) );
585 const SvxLRSpaceItem
&rSpace
= GetSwAttrSet().GetLRSpace();
586 long nLROffset
= rSpace
.GetTxtLeft() + GetLeftMarginWithNum( sal_True
);
588 // Bei Numerierung ist ein neg. Erstzeileneinzug vermutlich
589 // bereits gefuellt...
590 if( !GetFirstLineOfsWithNum( nFLOffs
) || nFLOffs
> nLROffset
)
593 SwMinMaxNodeArgs aNodeArgs
;
594 aNodeArgs
.nMinWidth
= 0;
595 aNodeArgs
.nMaxWidth
= 0;
596 aNodeArgs
.nLeftRest
= nLROffset
;
597 aNodeArgs
.nRightRest
= rSpace
.GetRight();
598 aNodeArgs
.nLeftDiff
= 0;
599 aNodeArgs
.nRightDiff
= 0;
602 SwFrmFmts
* pTmp
= (SwFrmFmts
*)GetDoc()->GetSpzFrmFmts();
605 aNodeArgs
.nIndx
= nIndex
;
606 BOOST_FOREACH( SwFrmFmt
*pFmt
, *pTmp
)
607 lcl_MinMaxNode( pFmt
, &aNodeArgs
);
610 if( aNodeArgs
.nLeftRest
< 0 )
611 aNodeArgs
.Minimum( nLROffset
- aNodeArgs
.nLeftRest
);
612 aNodeArgs
.nLeftRest
-= aNodeArgs
.nLeftDiff
;
613 if( aNodeArgs
.nLeftRest
< 0 )
614 aNodeArgs
.nMaxWidth
-= aNodeArgs
.nLeftRest
;
616 if( aNodeArgs
.nRightRest
< 0 )
617 aNodeArgs
.Minimum( rSpace
.GetRight() - aNodeArgs
.nRightRest
);
618 aNodeArgs
.nRightRest
-= aNodeArgs
.nRightDiff
;
619 if( aNodeArgs
.nRightRest
< 0 )
620 aNodeArgs
.nMaxWidth
-= aNodeArgs
.nRightRest
;
622 SwScriptInfo aScriptInfo
;
623 SwAttrIter
aIter( *(SwTxtNode
*)this, aScriptInfo
);
625 aIter
.SeekAndChgAttrIter( nIdx
, pOut
);
626 xub_StrLen nLen
= m_Text
.Len();
629 SwMinMaxArgs
aArg( pOut
, pSh
, rMin
, rMax
, rAbsMin
);
632 xub_StrLen nNextChg
= aIter
.GetNextAttr();
633 xub_StrLen nStop
= aScriptInfo
.NextScriptChg( nIdx
);
634 if( nNextChg
> nStop
)
636 SwTxtAttr
*pHint
= NULL
;
637 sal_Unicode cChar
= CH_BLANK
;
639 while( nStop
< nLen
&& nStop
< nNextChg
&&
640 CH_TAB
!= ( cChar
= m_Text
.GetChar( nStop
) ) &&
641 CH_BREAK
!= cChar
&& CHAR_HARDBLANK
!= cChar
&&
642 CHAR_HARDHYPHEN
!= cChar
&& CHAR_SOFTHYPHEN
!= cChar
&&
645 if( ( CH_TXTATR_BREAKWORD
!= cChar
&& CH_TXTATR_INWORD
!= cChar
)
646 || ( 0 == ( pHint
= aIter
.GetAttr( nStop
) ) ) )
649 if ( lcl_MinMaxString( aArg
, aIter
.GetFnt(), m_Text
, nIdx
, nStop
) )
654 aIter
.SeekAndChgAttrIter( nIdx
, pOut
);
659 if( (long)rMax
< aArg
.nRowWidth
)
660 rMax
= aArg
.nRowWidth
;
663 aIter
.SeekAndChgAttrIter( ++nIdx
, pOut
);
669 aIter
.SeekAndChgAttrIter( ++nIdx
, pOut
);
672 case CHAR_SOFTHYPHEN
:
676 case CHAR_HARDHYPHEN
:
678 OUString
sTmp( cChar
);
679 SwDrawTextInfo
aDrawInf( const_cast<ViewShell
*>(getIDocumentLayoutAccess()->GetCurrentViewShell()),
680 *pOut
, 0, sTmp
, 0, 1, 0, sal_False
);//swmod 080311
681 nAktWidth
= aIter
.GetFnt()->_GetTxtSize( aDrawInf
).Width();
682 aArg
.nWordWidth
+= nAktWidth
;
683 aArg
.nRowWidth
+= nAktWidth
;
684 if( (long)rAbsMin
< aArg
.nWordWidth
)
685 rAbsMin
= aArg
.nWordWidth
;
686 aArg
.Minimum( aArg
.nWordWidth
+ aArg
.nWordAdd
);
687 aArg
.nNoLineBreak
= nIdx
++;
690 case CH_TXTATR_BREAKWORD
:
691 case CH_TXTATR_INWORD
:
695 long nOldWidth
= aArg
.nWordWidth
;
696 long nOldAdd
= aArg
.nWordAdd
;
699 switch( pHint
->Which() )
701 case RES_TXTATR_FLYCNT
:
703 SwFrmFmt
*pFrmFmt
= pHint
->GetFlyCnt().GetFrmFmt();
704 const SvxLRSpaceItem
&rLR
= pFrmFmt
->GetLRSpace();
705 if( RES_DRAWFRMFMT
== pFrmFmt
->Which() )
707 const SdrObject
* pSObj
= pFrmFmt
->FindSdrObject();
709 nAktWidth
= pSObj
->GetCurrentBoundRect().GetWidth();
715 const SwFmtFrmSize
& rTmpSize
= pFrmFmt
->GetFrmSize();
716 if( RES_FLYFRMFMT
== pFrmFmt
->Which()
717 && rTmpSize
.GetWidthPercent() )
719 /*-----------------------------------------------------------------------------
720 * Hier ein HACK fuer folgende Situation: In dem Absatz befindet sich
721 * ein Textrahmen mit relativer Groesse. Dann nehmen wir mal als minimale
722 * Breite 0,5 cm und als maximale KSHRT_MAX.
723 * Sauberer und vielleicht spaeter notwendig waere es, ueber den Inhalt
724 * des Textrahmens zu iterieren und GetMinMaxSize rekursiv zu rufen.
725 * --------------------------------------------------------------------------*/
726 nAktWidth
= FLYINCNT_MIN_WIDTH
; // 0,5 cm
727 if( (long)rMax
< KSHRT_MAX
)
731 nAktWidth
= pFrmFmt
->GetFrmSize().GetWidth();
733 nAktWidth
+= rLR
.GetLeft();
734 nAktWidth
+= rLR
.GetRight();
735 aArg
.nWordAdd
= nOldWidth
+ nOldAdd
;
736 aArg
.nWordWidth
= nAktWidth
;
737 aArg
.nRowWidth
+= nAktWidth
;
738 if( (long)rAbsMin
< aArg
.nWordWidth
)
739 rAbsMin
= aArg
.nWordWidth
;
740 aArg
.Minimum( aArg
.nWordWidth
+ aArg
.nWordAdd
);
743 case RES_TXTATR_FTN
:
745 const XubString aTxt
= pHint
->GetFtn().GetNumStr();
746 if( lcl_MinMaxString( aArg
, aIter
.GetFnt(), aTxt
, 0,
751 case RES_TXTATR_FIELD
:
753 SwField
*pFld
= (SwField
*)pHint
->GetFld().GetFld();
754 const String aTxt
= pFld
->ExpandField(true);
755 if( lcl_MinMaxString( aArg
, aIter
.GetFnt(), aTxt
, 0,
760 default: aArg
.nWordWidth
= nOldWidth
;
761 aArg
.nWordAdd
= nOldAdd
;
764 aIter
.SeekAndChgAttrIter( ++nIdx
, pOut
);
769 if( (long)rMax
< aArg
.nRowWidth
)
770 rMax
= aArg
.nRowWidth
;
772 nLROffset
+= rSpace
.GetRight();
774 rAbsMin
+= nLROffset
;
778 if( (long)rMin
< aNodeArgs
.nMinWidth
)
779 rMin
= aNodeArgs
.nMinWidth
;
780 if( (long)rAbsMin
< aNodeArgs
.nMinWidth
)
781 rAbsMin
= aNodeArgs
.nMinWidth
;
782 rMax
+= aNodeArgs
.nMaxWidth
;
785 if( rMax
< rMin
) // z.B. Rahmen mit Durchlauf gehen zunaechst nur
786 rMax
= rMin
; // in das Minimum ein
787 pOut
->SetMapMode( aOldMap
);
790 /*************************************************************************
791 * SwTxtNode::GetScalingOfSelectedText()
793 * Calculates the width of the text part specified by nStt and nEnd,
794 * the height of the line containing nStt is devided by this width,
795 * indicating the scaling factor, if the text part is rotated.
796 * Having CH_BREAKs in the text part, this method returns the scaling
797 * factor for the longest of the text parts separated by the CH_BREAKs.
799 * changing this method very likely requires changing of "GetMinMaxSize"
800 *************************************************************************/
802 sal_uInt16
SwTxtNode::GetScalingOfSelectedText( xub_StrLen nStt
, xub_StrLen nEnd
)
805 ViewShell
* pSh
= NULL
;
806 OutputDevice
* pOut
= NULL
;
807 GetDoc()->GetEditShell( &pSh
);
810 pOut
= &pSh
->GetRefDev();
813 //Zugriff ueber StarONE, es muss keine Shell existieren oder aktiv sein.
814 if ( getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE
) )
815 pOut
= GetpApp()->GetDefaultDevice();
817 pOut
= getIDocumentDeviceAccess()->getReferenceDevice( true );
820 OSL_ENSURE( pOut
, "GetScalingOfSelectedText without outdev" );
822 MapMode
aOldMap( pOut
->GetMapMode() );
823 pOut
->SetMapMode( MapMode( MAP_TWIP
) );
827 if ( !pBreakIt
->GetBreakIter().is() )
830 SwScriptInfo aScriptInfo
;
831 SwAttrIter
aIter( *(SwTxtNode
*)this, aScriptInfo
);
832 aIter
.SeekAndChgAttrIter( nStt
, pOut
);
835 pBreakIt
->GetBreakIter()->getWordBoundary( GetTxt(), nStt
,
836 pBreakIt
->GetLocale( aIter
.GetFnt()->GetLanguage() ),
837 WordType::DICTIONARY_WORD
, sal_True
);
839 if ( nStt
== aBound
.startPos
)
841 // cursor is at left or right border of word
842 pOut
->SetMapMode( aOldMap
);
846 nStt
= (xub_StrLen
)aBound
.startPos
;
847 nEnd
= (xub_StrLen
)aBound
.endPos
;
851 pOut
->SetMapMode( aOldMap
);
856 SwScriptInfo aScriptInfo
;
857 SwAttrIter
aIter( *(SwTxtNode
*)this, aScriptInfo
);
859 // We do not want scaling attributes to be considered during this
860 // calculation. For this, we push a temporary scaling attribute with
861 // scaling value 100 and priority flag on top of the scaling stack
862 SwAttrHandler
& rAH
= aIter
.GetAttrHandler();
863 SvxCharScaleWidthItem
aItem(100, RES_CHRATR_SCALEW
);
864 SwTxtAttrEnd
aAttr( aItem
, nStt
, nEnd
);
865 aAttr
.SetPriorityAttr( sal_True
);
866 rAH
.PushAndChg( aAttr
, *(aIter
.GetFnt()) );
868 xub_StrLen nIdx
= nStt
;
870 sal_uLong nWidth
= 0;
871 sal_uLong nProWidth
= 0;
875 aIter
.SeekAndChgAttrIter( nIdx
, pOut
);
877 // scan for end of portion
878 xub_StrLen nNextChg
= aIter
.GetNextAttr();
879 xub_StrLen nStop
= aScriptInfo
.NextScriptChg( nIdx
);
880 if( nNextChg
> nStop
)
884 sal_Unicode cChar
= CH_BLANK
;
885 SwTxtAttr
* pHint
= NULL
;
887 // stop at special characters in [ nIdx, nNextChg ]
888 while( nStop
< nEnd
&& nStop
< nNextChg
)
890 cChar
= m_Text
.GetChar( nStop
);
894 CHAR_HARDBLANK
== cChar
||
895 CHAR_HARDHYPHEN
== cChar
||
896 CHAR_SOFTHYPHEN
== cChar
||
898 (CH_TXTATR_BREAKWORD
== cChar
|| CH_TXTATR_INWORD
== cChar
) &&
899 (0 == (pHint
= aIter
.GetAttr(nStop
)))
909 // calculate text widths up to cChar
912 SwDrawTextInfo
aDrawInf( pSh
, *pOut
, 0, GetTxt(), nIdx
, nStop
- nIdx
);
913 nProWidth
+= aIter
.GetFnt()->_GetTxtSize( aDrawInf
).Width();
917 aIter
.SeekAndChgAttrIter( nIdx
, pOut
);
919 if ( cChar
== CH_BREAK
)
921 nWidth
= Max( nWidth
, nProWidth
);
925 else if ( cChar
== CH_TAB
)
927 // tab receives width of one space
928 OUString
sTmp( CH_BLANK
);
929 SwDrawTextInfo
aDrawInf( pSh
, *pOut
, 0, sTmp
, 0, 1 );
930 nProWidth
+= aIter
.GetFnt()->_GetTxtSize( aDrawInf
).Width();
933 else if ( cChar
== CHAR_SOFTHYPHEN
)
935 else if ( cChar
== CHAR_HARDBLANK
|| cChar
== CHAR_HARDHYPHEN
)
937 OUString
sTmp( cChar
);
938 SwDrawTextInfo
aDrawInf( pSh
, *pOut
, 0, sTmp
, 0, 1 );
939 nProWidth
+= aIter
.GetFnt()->_GetTxtSize( aDrawInf
).Width();
942 else if ( pHint
&& ( cChar
== CH_TXTATR_BREAKWORD
|| CH_TXTATR_INWORD
) )
944 switch( pHint
->Which() )
946 case RES_TXTATR_FTN
:
948 const XubString aTxt
= pHint
->GetFtn().GetNumStr();
949 SwDrawTextInfo
aDrawInf( pSh
, *pOut
, 0, aTxt
, 0, aTxt
.Len() );
951 nProWidth
+= aIter
.GetFnt()->_GetTxtSize( aDrawInf
).Width();
954 case RES_TXTATR_FIELD
:
956 SwField
*pFld
= (SwField
*)pHint
->GetFld().GetFld();
957 String
const aTxt
= pFld
->ExpandField(true);
958 SwDrawTextInfo
aDrawInf( pSh
, *pOut
, 0, aTxt
, 0, aTxt
.Len() );
960 nProWidth
+= aIter
.GetFnt()->_GetTxtSize( aDrawInf
).Width();
965 // any suggestions for a default action?
972 nWidth
= Max( nWidth
, nProWidth
);
974 // search for a text frame this node belongs to
975 SwIterator
<SwTxtFrm
,SwTxtNode
> aFrmIter( *this );
977 for( SwTxtFrm
* pTmpFrm
= aFrmIter
.First(); pTmpFrm
; pTmpFrm
= aFrmIter
.Next() )
979 if ( pTmpFrm
->GetOfst() <= nStt
&&
980 ( !pTmpFrm
->GetFollow() ||
981 pTmpFrm
->GetFollow()->GetOfst() > nStt
) )
988 // search for the line containing nStt
989 if ( pFrm
&& pFrm
->HasPara() )
991 SwTxtInfo
aInf( pFrm
);
992 SwTxtIter
aLine( pFrm
, &aInf
);
993 aLine
.CharToLine( nStt
);
994 pOut
->SetMapMode( aOldMap
);
995 return (sal_uInt16
)( nWidth
?
996 ( ( 100 * aLine
.GetCurr()->Height() ) / nWidth
) : 0 );
998 // no frame or no paragraph, we take the height of the character
999 // at nStt as line height
1001 aIter
.SeekAndChgAttrIter( nStt
, pOut
);
1002 pOut
->SetMapMode( aOldMap
);
1004 SwDrawTextInfo
aDrawInf( pSh
, *pOut
, 0, GetTxt(), nStt
, 1 );
1006 ( nWidth
? ((100 * aIter
.GetFnt()->_GetTxtSize( aDrawInf
).Height()) / nWidth
) : 0 );
1009 sal_uInt16
SwTxtNode::GetWidthOfLeadingTabs() const
1011 sal_uInt16 nRet
= 0;
1013 xub_StrLen nIdx
= 0;
1016 while ( nIdx
< GetTxt().Len() &&
1017 ( '\t' == ( cCh
= GetTxt().GetChar( nIdx
) ) ||
1023 SwPosition
aPos( *this );
1024 aPos
.nContent
+= nIdx
;
1026 // Find the non-follow text frame:
1027 SwIterator
<SwTxtFrm
,SwTxtNode
> aIter( *this );
1028 for( SwTxtFrm
* pFrm
= aIter
.First(); pFrm
; pFrm
= aIter
.Next() )
1030 // Only consider master frames:
1031 if ( !pFrm
->IsFollow() )
1035 pFrm
->GetCharRect( aRect
, aPos
);
1037 ( pFrm
->IsRightToLeft() ?
1038 (pFrm
->*fnRect
->fnGetPrtRight
)() - (aRect
.*fnRect
->fnGetRight
)() :
1039 (aRect
.*fnRect
->fnGetLeft
)() - (pFrm
->*fnRect
->fnGetPrtLeft
)() );
1048 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */