1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: itratr.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <svx/charscaleitem.hxx>
38 #include <sfx2/printer.hxx>
39 #include <svx/lrspitem.hxx>
40 #include <vcl/window.hxx>
41 #include <vcl/svapp.hxx>
42 #include <fmtanchr.hxx>
43 #include <fmtfsize.hxx>
44 #include <fmtornt.hxx>
45 #include <fmtflcnt.hxx>
46 #include <fmtcntnt.hxx>
52 #include <viewsh.hxx> // ViewShell
53 #include <rootfrm.hxx>
56 #include <dcontact.hxx>
57 #include <fldbas.hxx> // SwField
58 #include <pam.hxx> // SwPosition (lcl_MinMaxNode)
60 #include <htmltbl.hxx>
61 #include <swtable.hxx>
62 #include <redlnitr.hxx>
63 #include <fmtsrnd.hxx>
65 #include <breakit.hxx>
66 #include <com/sun/star/i18n/WordType.hpp>
67 #include <com/sun/star/i18n/ScriptType.hdl>
69 using namespace ::com::sun::star::i18n
;
70 using namespace ::com::sun::star
;
72 /*************************************************************************
74 *************************************************************************/
76 void SwAttrIter::Chg( SwTxtAttr
*pHt
)
78 ASSERT( pHt
&& pFnt
, "No attribute of font available for change");
79 if( pRedln
&& pRedln
->IsOn() )
80 pRedln
->ChangeTxtAttr( pFnt
, *pHt
, sal_True
);
82 aAttrHandler
.PushAndChg( *pHt
, *pFnt
);
86 /*************************************************************************
88 *************************************************************************/
90 void SwAttrIter::Rst( SwTxtAttr
*pHt
)
92 ASSERT( pHt
&& pFnt
, "No attribute of font available for reset");
93 // get top from stack after removing pHt
94 if( pRedln
&& pRedln
->IsOn() )
95 pRedln
->ChangeTxtAttr( pFnt
, *pHt
, sal_False
);
97 aAttrHandler
.PopAndChg( *pHt
, *pFnt
);
101 /*************************************************************************
102 * virtual SwAttrIter::~SwAttrIter()
103 *************************************************************************/
105 SwAttrIter::~SwAttrIter()
111 /*************************************************************************
112 * SwAttrIter::GetAttr()
114 * Liefert fuer eine Position das Attribut, wenn das Attribut genau auf
115 * der Position nPos liegt und kein EndIndex besitzt.
116 * GetAttr() wird fuer Attribute benoetigt, die die Formatierung beeinflussen
117 * sollen, ohne dabei den Inhalt des Strings zu veraendern. Solche "entarteten"
118 * Attribute sind z.B. Felder (die expandierten Text bereit halten) und
119 * zeilengebundene Frames. Um Mehrdeutigkeiten zwischen verschiedenen
120 * solcher Attribute zu vermeiden, werden beim Anlegen eines Attributs
121 * an der Startposition ein Sonderzeichen in den String einfuegt.
122 * Der Formatierer stoesst auf das Sonderzeichen und holt sich per
123 * GetAttr() das entartete Attribut.
124 *************************************************************************/
126 SwTxtAttr
*SwAttrIter::GetAttr( const xub_StrLen nPosition
) const
128 return (m_pTxtNode
) ? m_pTxtNode
->GetTxtAttrForCharAt(nPosition
) : 0;
131 /*************************************************************************
132 * SwAttrIter::SeekAndChg()
133 *************************************************************************/
135 sal_Bool
SwAttrIter::SeekAndChgAttrIter( const xub_StrLen nNewPos
, OutputDevice
* pOut
)
137 sal_Bool bChg
= nStartIndex
&& nNewPos
== nPos
? pFnt
->IsFntChg() : Seek( nNewPos
);
138 if ( pLastOut
!= pOut
)
141 pFnt
->SetFntChg( sal_True
);
146 // wenn der Aenderungszaehler auf Null ist, kennen wir die MagicNo
147 // des gewuenschten Fonts ...
148 if ( !nChgCnt
&& !nPropFont
)
149 pFnt
->SetMagic( aMagicNo
[ pFnt
->GetActual() ],
150 aFntIdx
[ pFnt
->GetActual() ], pFnt
->GetActual() );
151 pFnt
->ChgPhysFnt( pShell
, *pOut
);
156 sal_Bool
SwAttrIter::IsSymbol( const xub_StrLen nNewPos
)
159 if ( !nChgCnt
&& !nPropFont
)
160 pFnt
->SetMagic( aMagicNo
[ pFnt
->GetActual() ],
161 aFntIdx
[ pFnt
->GetActual() ], pFnt
->GetActual() );
162 return pFnt
->IsSymbol( pShell
);
165 /*************************************************************************
166 * SwAttrIter::SeekStartAndChg()
167 *************************************************************************/
169 sal_Bool
SwAttrIter::SeekStartAndChgAttrIter( OutputDevice
* pOut
, const sal_Bool bParaFont
)
171 if ( pRedln
&& pRedln
->ExtOn() )
172 pRedln
->LeaveExtend( *pFnt
, 0 );
174 // reset font to its original state
175 aAttrHandler
.Reset();
176 aAttrHandler
.ResetFont( *pFnt
);
178 nStartIndex
= nEndIndex
= nPos
= nChgCnt
= 0;
180 pFnt
->SetProportion( nPropFont
);
183 pRedln
->Clear( pFnt
);
185 nChgCnt
= nChgCnt
+ pRedln
->Seek( *pFnt
, 0, STRING_LEN
);
190 if ( pHints
&& !bParaFont
)
193 // Solange wir noch nicht am Ende des StartArrays angekommen sind &&
194 // das TextAttribut an Position 0 beginnt ...
195 while ( ( nStartIndex
< pHints
->GetStartCount() ) &&
196 !(*(pTxtAttr
=pHints
->GetStart(nStartIndex
))->GetStart()) )
198 // oeffne die TextAttribute
204 sal_Bool bChg
= pFnt
->IsFntChg();
205 if ( pLastOut
!= pOut
)
208 pFnt
->SetFntChg( sal_True
);
213 // wenn der Aenderungszaehler auf Null ist, kennen wir die MagicNo
214 // des gewuenschten Fonts ...
215 if ( !nChgCnt
&& !nPropFont
)
216 pFnt
->SetMagic( aMagicNo
[ pFnt
->GetActual() ],
217 aFntIdx
[ pFnt
->GetActual() ], pFnt
->GetActual() );
218 pFnt
->ChgPhysFnt( pShell
, *pOut
);
223 /*************************************************************************
224 * SwAttrIter::SeekFwd()
225 *************************************************************************/
227 // AMA: Neuer AttrIter Nov 94
229 void SwAttrIter::SeekFwd( const xub_StrLen nNewPos
)
233 if ( nStartIndex
) // wenn ueberhaupt schon Attribute geoeffnet wurden...
235 // Schliesse Attr, die z. Z. geoeffnet sind, vor nNewPos+1 aber enden.
237 // Solange wir noch nicht am Ende des EndArrays angekommen sind &&
238 // das TextAttribut vor oder an der neuen Position endet ...
239 while ( ( nEndIndex
< pHints
->GetEndCount() ) &&
240 (*(pTxtAttr
=pHints
->GetEnd(nEndIndex
))->GetAnyEnd()<=nNewPos
))
242 // schliesse die TextAttribute, deren StartPos vor
243 // oder an der alten nPos lag, die z.Z. geoeffnet sind.
244 if (*pTxtAttr
->GetStart() <= nPos
) Rst( pTxtAttr
);
248 else // ueberlies die nicht geoeffneten Enden
250 while ( ( nEndIndex
< pHints
->GetEndCount() ) &&
251 (*(pTxtAttr
=pHints
->GetEnd(nEndIndex
))->GetAnyEnd()<=nNewPos
))
256 // Solange wir noch nicht am Ende des StartArrays angekommen sind &&
257 // das TextAttribut vor oder an der neuen Position beginnt ...
258 while ( ( nStartIndex
< pHints
->GetStartCount() ) &&
259 (*(pTxtAttr
=pHints
->GetStart(nStartIndex
))->GetStart()<=nNewPos
))
261 // oeffne die TextAttribute, deren Ende hinter der neuen Position liegt
262 if ( *pTxtAttr
->GetAnyEnd() > nNewPos
) Chg( pTxtAttr
);
268 /*************************************************************************
270 *************************************************************************/
272 sal_Bool
SwAttrIter::Seek( const xub_StrLen nNewPos
)
274 if ( pRedln
&& pRedln
->ExtOn() )
275 pRedln
->LeaveExtend( *pFnt
, nNewPos
);
279 if( !nNewPos
|| nNewPos
< nPos
)
282 pRedln
->Clear( NULL
);
284 // reset font to its original state
285 aAttrHandler
.Reset();
286 aAttrHandler
.ResetFont( *pFnt
);
289 pFnt
->SetProportion( nPropFont
);
290 nStartIndex
= nEndIndex
= nPos
= 0;
294 // resetting the font here makes it necessary to apply any
295 // changes for extended input directly to the font
296 if ( pRedln
&& pRedln
->ExtOn() )
298 pRedln
->UpdateExtFont( *pFnt
);
305 pFnt
->SetActual( SwScriptInfo::WhichFont( nNewPos
, 0, pScriptInfo
) );
308 nChgCnt
= nChgCnt
+ pRedln
->Seek( *pFnt
, nNewPos
, nPos
);
312 pFnt
->SetProportion( nPropFont
);
314 return pFnt
->IsFntChg();
317 /*************************************************************************
318 * SwAttrIter::GetNextAttr()
319 *************************************************************************/
321 xub_StrLen
SwAttrIter::GetNextAttr( ) const
323 xub_StrLen nNext
= STRING_LEN
;
326 if (pHints
->GetStartCount() > nStartIndex
) // Gibt es noch Starts?
327 nNext
= (*pHints
->GetStart(nStartIndex
)->GetStart());
328 if (pHints
->GetEndCount() > nEndIndex
) // Gibt es noch Enden?
330 xub_StrLen nNextEnd
= (*pHints
->GetEnd(nEndIndex
)->GetAnyEnd());
331 if ( nNextEnd
<nNext
) nNext
= nNextEnd
; // Wer ist naeher?
334 if (m_pTxtNode
!=NULL
) {
335 //TODO maybe use hints like FieldHints for this instead of looking at the text...
336 int l
=(nNext
<m_pTxtNode
->Len()?nNext
:m_pTxtNode
->Len());
338 const sal_Unicode
*txt
=m_pTxtNode
->GetTxt().GetBuffer();
339 while(p
<l
&& txt
[p
]!=CH_TXT_ATR_FIELDSTART
&& txt
[p
]!=CH_TXT_ATR_FIELDEND
&& txt
[p
]!=CH_TXT_ATR_FORMELEMENT
) p
++;
340 if ((p
<l
&& p
>nPos
) || nNext
<=p
)
346 return pRedln
->GetNextRedln( nNext
);
350 #if OSL_DEBUG_LEVEL > 1
351 /*************************************************************************
353 *************************************************************************/
355 void SwAttrIter::Dump( SvStream
&/*rOS*/ ) const
357 // Noch nicht an den neuen Attributiterator angepasst ...
373 xub_StrLen nNoLineBreak
;
374 SwMinMaxArgs( OutputDevice
* pOutI
, ViewShell
* pShI
, ULONG
& rMinI
, ULONG
&rMaxI
, ULONG
&rAbsI
)
375 : pOut( pOutI
), pSh( pShI
), rMin( rMinI
), rMax( rMaxI
), rAbsMin( rAbsI
)
376 { nRowWidth
= nWordWidth
= nWordAdd
= 0; nNoLineBreak
= STRING_LEN
; }
377 void Minimum( long nNew
) { if( (long)rMin
< nNew
) rMin
= nNew
; }
378 void NewWord() { nWordAdd
= nWordWidth
= 0; }
381 sal_Bool
lcl_MinMaxString( SwMinMaxArgs
& rArg
, SwFont
* pFnt
, const XubString
&rTxt
,
382 xub_StrLen nIdx
, xub_StrLen nEnd
)
384 sal_Bool bRet
= sal_False
;
387 xub_StrLen nStop
= nIdx
;
389 LanguageType eLang
= pFnt
->GetLanguage();
390 if( pBreakIt
->GetBreakIter().is() )
392 bClear
= CH_BLANK
== rTxt
.GetChar( nStop
);
393 Boundary
aBndry( pBreakIt
->GetBreakIter()->getWordBoundary( rTxt
, nIdx
,
394 pBreakIt
->GetLocale( eLang
),
395 WordType::DICTIONARY_WORD
, TRUE
) );
396 nStop
= (xub_StrLen
)aBndry
.endPos
;
397 if( nIdx
<= aBndry
.startPos
&& nIdx
&& nIdx
-1 != rArg
.nNoLineBreak
)
406 while( nStop
< nEnd
&& CH_BLANK
!= rTxt
.GetChar( nStop
) )
408 bClear
= nStop
== nIdx
;
412 while( nStop
< nEnd
&& CH_BLANK
== rTxt
.GetChar( nStop
) )
417 SwDrawTextInfo
aDrawInf( rArg
.pSh
, *rArg
.pOut
, 0, rTxt
, nIdx
, nStop
- nIdx
);
418 long nAktWidth
= pFnt
->_GetTxtSize( aDrawInf
).Width();
419 rArg
.nRowWidth
+= nAktWidth
;
424 rArg
.nWordWidth
+= nAktWidth
;
425 if( (long)rArg
.rAbsMin
< rArg
.nWordWidth
)
426 rArg
.rAbsMin
= rArg
.nWordWidth
;
427 rArg
.Minimum( rArg
.nWordWidth
+ rArg
.nWordAdd
);
435 sal_Bool
SwTxtNode::IsSymbol( const xub_StrLen nBegin
) const
437 SwScriptInfo aScriptInfo
;
438 SwAttrIter
aIter( *(SwTxtNode
*)this, aScriptInfo
);
439 aIter
.Seek( nBegin
);
440 const SwRootFrm
* pTmpRootFrm
= getIDocumentLayoutAccess()->GetRootFrm();
441 return aIter
.GetFnt()->IsSymbol( pTmpRootFrm
?
442 pTmpRootFrm
->GetCurrShell() :
446 class SwMinMaxNodeArgs
449 ULONG nMaxWidth
; // Summe aller Rahmenbreite
450 long nMinWidth
; // Breitester Rahmen
451 long nLeftRest
; // noch nicht von Rahmen ueberdeckter Platz im l. Rand
452 long nRightRest
; // noch nicht von Rahmen ueberdeckter Platz im r. Rand
453 long nLeftDiff
; // Min/Max-Differenz des Rahmens im linken Rand
454 long nRightDiff
; // Min/Max-Differenz des Rahmens im rechten Rand
455 ULONG nIndx
; // Indexnummer des Nodes
456 void Minimum( long nNew
) { if( nNew
> nMinWidth
) nMinWidth
= nNew
; }
459 sal_Bool
lcl_MinMaxNode( const SwFrmFmtPtr
& rpNd
, void* pArgs
)
461 const SwFmtAnchor
& rFmtA
= ((SwFrmFmt
*)rpNd
)->GetAnchor();
463 bool bCalculate
= false;
465 (FLY_AT_CNTNT
== rFmtA
.GetAnchorId()) ||
466 (FLY_AUTO_CNTNT
== rFmtA
.GetAnchorId())
474 const SwMinMaxNodeArgs
*pIn
= (const SwMinMaxNodeArgs
*)pArgs
;
475 const SwPosition
*pPos
= rFmtA
.GetCntntAnchor();
476 ASSERT(pPos
&& pIn
, "Unexpected NULL arguments");
477 if (!pPos
|| !pIn
|| pIn
->nIndx
!= pPos
->nNode
.GetIndex())
484 SwHTMLTableLayout
*pLayout
= 0;
485 MSHORT nWhich
= ((SwFrmFmt
*)rpNd
)->Which();
486 if( RES_DRAWFRMFMT
!= nWhich
)
488 // Enthaelt der Rahmen zu Beginn oder am Ende eine Tabelle?
489 const SwNodes
& rNodes
= static_cast<SwFrmFmt
*>(rpNd
)->GetDoc()->GetNodes();
490 const SwFmtCntnt
& rFlyCntnt
= ((SwFrmFmt
*)rpNd
)->GetCntnt();
491 ULONG nStt
= rFlyCntnt
.GetCntntIdx()->GetIndex();
492 SwTableNode
* pTblNd
= rNodes
[nStt
+1]->GetTableNode();
495 SwNode
*pNd
= rNodes
[nStt
];
496 pNd
= rNodes
[pNd
->EndOfSectionIndex()-1];
497 if( pNd
->IsEndNode() )
498 pTblNd
= pNd
->StartOfSectionNode()->GetTableNode();
502 pLayout
= pTblNd
->GetTable().GetHTMLTableLayout();
505 const SwFmtHoriOrient
& rOrient
= ((SwFrmFmt
*)rpNd
)->GetHoriOrient();
506 sal_Int16 eHoriOri
= rOrient
.GetHoriOrient();
511 nMin
= pLayout
->GetMin();
512 nMax
= pLayout
->GetMax();
517 if( RES_DRAWFRMFMT
== nWhich
)
519 const SdrObject
* pSObj
= rpNd
->FindSdrObject();
521 nMin
= pSObj
->GetCurrentBoundRect().GetWidth();
528 const SwFmtFrmSize
&rSz
= ( (SwFrmFmt
*)rpNd
)->GetFrmSize();
529 nMin
= rSz
.GetWidth();
535 const SvxLRSpaceItem
&rLR
= ( (SwFrmFmt
*)rpNd
)->GetLRSpace();
536 nMin
+= rLR
.GetLeft();
537 nMin
+= rLR
.GetRight();
538 nMax
+= rLR
.GetLeft();
539 nMax
+= rLR
.GetRight();
541 if( SURROUND_THROUGHT
== ((SwFrmFmt
*)rpNd
)->GetSurround().GetSurround() )
543 ( (SwMinMaxNodeArgs
*)pArgs
)->Minimum( nMin
);
547 // Rahmen, die recht bzw. links ausgerichtet sind, gehen nur
548 // teilweise in die Max-Berechnung ein, da der Rand schon berueck-
549 // sichtigt wird. Nur wenn die Rahmen in den Textkoerper ragen,
550 // wird dieser Teil hinzuaddiert.
553 case text::HoriOrientation::RIGHT
:
557 ((SwMinMaxNodeArgs
*)pArgs
)->nRightRest
-=
558 ((SwMinMaxNodeArgs
*)pArgs
)->nRightDiff
;
559 ((SwMinMaxNodeArgs
*)pArgs
)->nRightDiff
= nDiff
;
561 if( text::RelOrientation::FRAME
!= rOrient
.GetRelationOrient() )
563 if( ((SwMinMaxNodeArgs
*)pArgs
)->nRightRest
> 0 )
564 ((SwMinMaxNodeArgs
*)pArgs
)->nRightRest
= 0;
566 ((SwMinMaxNodeArgs
*)pArgs
)->nRightRest
-= nMin
;
569 case text::HoriOrientation::LEFT
:
573 ((SwMinMaxNodeArgs
*)pArgs
)->nLeftRest
-=
574 ((SwMinMaxNodeArgs
*)pArgs
)->nLeftDiff
;
575 ((SwMinMaxNodeArgs
*)pArgs
)->nLeftDiff
= nDiff
;
577 if( text::RelOrientation::FRAME
!= rOrient
.GetRelationOrient() &&
578 ((SwMinMaxNodeArgs
*)pArgs
)->nLeftRest
< 0 )
579 ((SwMinMaxNodeArgs
*)pArgs
)->nLeftRest
= 0;
580 ((SwMinMaxNodeArgs
*)pArgs
)->nLeftRest
-= nMin
;
585 ( (SwMinMaxNodeArgs
*)pArgs
)->nMaxWidth
+= nMax
;
586 ( (SwMinMaxNodeArgs
*)pArgs
)->Minimum( nMin
);
593 #define FLYINCNT_MIN_WIDTH 284
595 // changing this method very likely requires changing of
596 // "GetScalingOfSelectedText"
597 void SwTxtNode::GetMinMaxSize( ULONG nIndex
, ULONG
& rMin
, ULONG
&rMax
,
598 ULONG
& rAbsMin
, OutputDevice
* pOut
) const
601 GetDoc()->GetEditShell( &pSh
);
605 pOut
= pSh
->GetWin();
607 pOut
= GetpApp()->GetDefaultDevice();
610 MapMode
aOldMap( pOut
->GetMapMode() );
611 pOut
->SetMapMode( MapMode( MAP_TWIP
) );
617 const SvxLRSpaceItem
&rSpace
= GetSwAttrSet().GetLRSpace();
618 long nLROffset
= rSpace
.GetTxtLeft() + GetLeftMarginWithNum( sal_True
);
620 // Bei Numerierung ist ein neg. Erstzeileneinzug vermutlich
621 // bereits gefuellt...
622 if( !GetFirstLineOfsWithNum( nFLOffs
) || nFLOffs
> nLROffset
)
625 SwMinMaxNodeArgs aNodeArgs
;
626 aNodeArgs
.nMinWidth
= 0;
627 aNodeArgs
.nMaxWidth
= 0;
628 aNodeArgs
.nLeftRest
= nLROffset
;
629 aNodeArgs
.nRightRest
= rSpace
.GetRight();
630 aNodeArgs
.nLeftDiff
= 0;
631 aNodeArgs
.nRightDiff
= 0;
634 SwSpzFrmFmts
* pTmp
= (SwSpzFrmFmts
*)GetDoc()->GetSpzFrmFmts();
637 aNodeArgs
.nIndx
= nIndex
;
638 pTmp
->ForEach( &lcl_MinMaxNode
, &aNodeArgs
);
641 if( aNodeArgs
.nLeftRest
< 0 )
642 aNodeArgs
.Minimum( nLROffset
- aNodeArgs
.nLeftRest
);
643 aNodeArgs
.nLeftRest
-= aNodeArgs
.nLeftDiff
;
644 if( aNodeArgs
.nLeftRest
< 0 )
645 aNodeArgs
.nMaxWidth
-= aNodeArgs
.nLeftRest
;
647 if( aNodeArgs
.nRightRest
< 0 )
648 aNodeArgs
.Minimum( rSpace
.GetRight() - aNodeArgs
.nRightRest
);
649 aNodeArgs
.nRightRest
-= aNodeArgs
.nRightDiff
;
650 if( aNodeArgs
.nRightRest
< 0 )
651 aNodeArgs
.nMaxWidth
-= aNodeArgs
.nRightRest
;
653 SwScriptInfo aScriptInfo
;
654 SwAttrIter
aIter( *(SwTxtNode
*)this, aScriptInfo
);
656 aIter
.SeekAndChgAttrIter( nIdx
, pOut
);
657 xub_StrLen nLen
= m_Text
.Len();
660 SwMinMaxArgs
aArg( pOut
, pSh
, rMin
, rMax
, rAbsMin
);
663 xub_StrLen nNextChg
= aIter
.GetNextAttr();
664 xub_StrLen nStop
= aScriptInfo
.NextScriptChg( nIdx
);
665 if( nNextChg
> nStop
)
667 SwTxtAttr
*pHint
= NULL
;
668 xub_Unicode cChar
= CH_BLANK
;
670 while( nStop
< nLen
&& nStop
< nNextChg
&&
671 CH_TAB
!= ( cChar
= m_Text
.GetChar( nStop
) ) &&
672 CH_BREAK
!= cChar
&& CHAR_HARDBLANK
!= cChar
&&
673 CHAR_HARDHYPHEN
!= cChar
&& CHAR_SOFTHYPHEN
!= cChar
&&
676 if( ( CH_TXTATR_BREAKWORD
!= cChar
&& CH_TXTATR_INWORD
!= cChar
)
677 || ( 0 == ( pHint
= aIter
.GetAttr( nStop
) ) ) )
680 if ( lcl_MinMaxString( aArg
, aIter
.GetFnt(), m_Text
, nIdx
, nStop
) )
685 aIter
.SeekAndChgAttrIter( nIdx
, pOut
);
690 if( (long)rMax
< aArg
.nRowWidth
)
691 rMax
= aArg
.nRowWidth
;
694 aIter
.SeekAndChgAttrIter( ++nIdx
, pOut
);
700 aIter
.SeekAndChgAttrIter( ++nIdx
, pOut
);
703 case CHAR_SOFTHYPHEN
:
707 case CHAR_HARDHYPHEN
:
709 XubString
sTmp( cChar
);
710 const SwRootFrm
* pTmpRootFrm
= getIDocumentLayoutAccess()->GetRootFrm();
711 SwDrawTextInfo
aDrawInf( pTmpRootFrm
?
712 pTmpRootFrm
->GetCurrShell() :
713 0, *pOut
, 0, sTmp
, 0, 1, 0, sal_False
);
714 nAktWidth
= aIter
.GetFnt()->_GetTxtSize( aDrawInf
).Width();
715 aArg
.nWordWidth
+= nAktWidth
;
716 aArg
.nRowWidth
+= nAktWidth
;
717 if( (long)rAbsMin
< aArg
.nWordWidth
)
718 rAbsMin
= aArg
.nWordWidth
;
719 aArg
.Minimum( aArg
.nWordWidth
+ aArg
.nWordAdd
);
720 aArg
.nNoLineBreak
= nIdx
++;
723 case CH_TXTATR_BREAKWORD
:
724 case CH_TXTATR_INWORD
:
728 long nOldWidth
= aArg
.nWordWidth
;
729 long nOldAdd
= aArg
.nWordAdd
;
732 switch( pHint
->Which() )
734 case RES_TXTATR_FLYCNT
:
736 SwFrmFmt
*pFrmFmt
= pHint
->GetFlyCnt().GetFrmFmt();
737 const SvxLRSpaceItem
&rLR
= pFrmFmt
->GetLRSpace();
738 if( RES_DRAWFRMFMT
== pFrmFmt
->Which() )
740 const SdrObject
* pSObj
= pFrmFmt
->FindSdrObject();
742 nAktWidth
= pSObj
->GetCurrentBoundRect().GetWidth();
748 const SwFmtFrmSize
& rTmpSize
= pFrmFmt
->GetFrmSize();
749 if( RES_FLYFRMFMT
== pFrmFmt
->Which()
750 && rTmpSize
.GetWidthPercent() )
752 /*-----------------24.01.97 14:09----------------------------------------------
753 * Hier ein HACK fuer folgende Situation: In dem Absatz befindet sich
754 * ein Textrahmen mit relativer Groesse. Dann nehmen wir mal als minimale
755 * Breite 0,5 cm und als maximale KSHRT_MAX.
756 * Sauberer und vielleicht spaeter notwendig waere es, ueber den Inhalt
757 * des Textrahmens zu iterieren und GetMinMaxSize rekursiv zu rufen.
758 * --------------------------------------------------------------------------*/
759 nAktWidth
= FLYINCNT_MIN_WIDTH
; // 0,5 cm
760 if( (long)rMax
< KSHRT_MAX
)
764 nAktWidth
= pFrmFmt
->GetFrmSize().GetWidth();
766 nAktWidth
+= rLR
.GetLeft();
767 nAktWidth
+= rLR
.GetRight();
768 aArg
.nWordAdd
= nOldWidth
+ nOldAdd
;
769 aArg
.nWordWidth
= nAktWidth
;
770 aArg
.nRowWidth
+= nAktWidth
;
771 if( (long)rAbsMin
< aArg
.nWordWidth
)
772 rAbsMin
= aArg
.nWordWidth
;
773 aArg
.Minimum( aArg
.nWordWidth
+ aArg
.nWordAdd
);
776 case RES_TXTATR_FTN
:
778 const XubString aTxt
= pHint
->GetFtn().GetNumStr();
779 if( lcl_MinMaxString( aArg
, aIter
.GetFnt(), aTxt
, 0,
784 case RES_TXTATR_FIELD
:
786 SwField
*pFld
= (SwField
*)pHint
->GetFld().GetFld();
787 const String aTxt
= pFld
->GetCntnt( FALSE
);
788 if( lcl_MinMaxString( aArg
, aIter
.GetFnt(), aTxt
, 0,
793 default: aArg
.nWordWidth
= nOldWidth
;
794 aArg
.nWordAdd
= nOldAdd
;
797 aIter
.SeekAndChgAttrIter( ++nIdx
, pOut
);
802 if( (long)rMax
< aArg
.nRowWidth
)
803 rMax
= aArg
.nRowWidth
;
805 nLROffset
+= rSpace
.GetRight();
807 rAbsMin
+= nLROffset
;
811 if( (long)rMin
< aNodeArgs
.nMinWidth
)
812 rMin
= aNodeArgs
.nMinWidth
;
813 if( (long)rAbsMin
< aNodeArgs
.nMinWidth
)
814 rAbsMin
= aNodeArgs
.nMinWidth
;
815 rMax
+= aNodeArgs
.nMaxWidth
;
818 if( rMax
< rMin
) // z.B. Rahmen mit Durchlauf gehen zunaechst nur
819 rMax
= rMin
; // in das Minimum ein
820 pOut
->SetMapMode( aOldMap
);
823 /*************************************************************************
824 * SwTxtNode::GetScalingOfSelectedText()
826 * Calculates the width of the text part specified by nStt and nEnd,
827 * the height of the line containing nStt is devided by this width,
828 * indicating the scaling factor, if the text part is rotated.
829 * Having CH_BREAKs in the text part, this method returns the scaling
830 * factor for the longest of the text parts separated by the CH_BREAKs.
832 * changing this method very likely requires changing of "GetMinMaxSize"
833 *************************************************************************/
835 USHORT
SwTxtNode::GetScalingOfSelectedText( xub_StrLen nStt
, xub_StrLen nEnd
)
838 ViewShell
* pSh
= NULL
;
839 OutputDevice
* pOut
= NULL
;
840 GetDoc()->GetEditShell( &pSh
);
843 pOut
= &pSh
->GetRefDev();
846 //Zugriff ueber StarONE, es muss keine Shell existieren oder aktiv sein.
847 if ( getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE
) )
848 pOut
= GetpApp()->GetDefaultDevice();
850 pOut
= getIDocumentDeviceAccess()->getReferenceDevice( true );
853 ASSERT( pOut
, "GetScalingOfSelectedText without outdev" )
855 MapMode
aOldMap( pOut
->GetMapMode() );
856 pOut
->SetMapMode( MapMode( MAP_TWIP
) );
860 if ( !pBreakIt
->GetBreakIter().is() )
863 SwScriptInfo aScriptInfo
;
864 SwAttrIter
aIter( *(SwTxtNode
*)this, aScriptInfo
);
865 aIter
.SeekAndChgAttrIter( nStt
, pOut
);
868 pBreakIt
->GetBreakIter()->getWordBoundary( GetTxt(), nStt
,
869 pBreakIt
->GetLocale( aIter
.GetFnt()->GetLanguage() ),
870 WordType::DICTIONARY_WORD
, sal_True
);
872 if ( nStt
== aBound
.startPos
)
874 // cursor is at left or right border of word
875 pOut
->SetMapMode( aOldMap
);
879 nStt
= (xub_StrLen
)aBound
.startPos
;
880 nEnd
= (xub_StrLen
)aBound
.endPos
;
884 pOut
->SetMapMode( aOldMap
);
889 SwScriptInfo aScriptInfo
;
890 SwAttrIter
aIter( *(SwTxtNode
*)this, aScriptInfo
);
892 // We do not want scaling attributes to be considered during this
893 // calculation. For this, we push a temporary scaling attribute with
894 // scaling value 100 and priority flag on top of the scaling stack
895 SwAttrHandler
& rAH
= aIter
.GetAttrHandler();
896 SvxCharScaleWidthItem
aItem(100, RES_CHRATR_SCALEW
);
897 SwTxtAttrEnd
aAttr( aItem
, nStt
, nEnd
);
898 aAttr
.SetPriorityAttr( sal_True
);
899 rAH
.PushAndChg( aAttr
, *(aIter
.GetFnt()) );
901 xub_StrLen nIdx
= nStt
;
908 aIter
.SeekAndChgAttrIter( nIdx
, pOut
);
910 // scan for end of portion
911 xub_StrLen nNextChg
= aIter
.GetNextAttr();
912 xub_StrLen nStop
= aScriptInfo
.NextScriptChg( nIdx
);
913 if( nNextChg
> nStop
)
917 xub_Unicode cChar
= CH_BLANK
;
918 SwTxtAttr
* pHint
= NULL
;
920 // stop at special characters in [ nIdx, nNextChg ]
921 while( nStop
< nEnd
&& nStop
< nNextChg
)
923 cChar
= m_Text
.GetChar( nStop
);
924 if( CH_TAB
== cChar
|| CH_BREAK
== cChar
||
925 CHAR_HARDBLANK
== cChar
|| CHAR_HARDHYPHEN
== cChar
||
926 CHAR_SOFTHYPHEN
== cChar
||
927 ( CH_TXTATR_BREAKWORD
== cChar
|| CH_TXTATR_INWORD
== cChar
) &&
928 ( 0 == ( pHint
= aIter
.GetAttr( nStop
) ) ) )
934 // calculate text widths up to cChar
937 SwDrawTextInfo
aDrawInf( pSh
, *pOut
, 0, GetTxt(), nIdx
, nStop
- nIdx
);
938 nProWidth
+= aIter
.GetFnt()->_GetTxtSize( aDrawInf
).Width();
942 aIter
.SeekAndChgAttrIter( nIdx
, pOut
);
944 if ( cChar
== CH_BREAK
)
946 nWidth
= Max( nWidth
, nProWidth
);
950 else if ( cChar
== CH_TAB
)
952 // tab receives width of one space
953 XubString
sTmp( CH_BLANK
);
954 SwDrawTextInfo
aDrawInf( pSh
, *pOut
, 0, sTmp
, 0, 1 );
955 nProWidth
+= aIter
.GetFnt()->_GetTxtSize( aDrawInf
).Width();
958 else if ( cChar
== CHAR_SOFTHYPHEN
)
960 else if ( cChar
== CHAR_HARDBLANK
|| cChar
== CHAR_HARDHYPHEN
)
962 XubString
sTmp( cChar
);
963 SwDrawTextInfo
aDrawInf( pSh
, *pOut
, 0, sTmp
, 0, 1 );
964 nProWidth
+= aIter
.GetFnt()->_GetTxtSize( aDrawInf
).Width();
967 else if ( pHint
&& ( cChar
== CH_TXTATR_BREAKWORD
|| CH_TXTATR_INWORD
) )
969 switch( pHint
->Which() )
971 case RES_TXTATR_FTN
:
973 const XubString aTxt
= pHint
->GetFtn().GetNumStr();
974 SwDrawTextInfo
aDrawInf( pSh
, *pOut
, 0, aTxt
, 0, aTxt
.Len() );
976 nProWidth
+= aIter
.GetFnt()->_GetTxtSize( aDrawInf
).Width();
979 case RES_TXTATR_FIELD
:
981 SwField
*pFld
= (SwField
*)pHint
->GetFld().GetFld();
982 const String aTxt
= pFld
->GetCntnt( FALSE
);
983 SwDrawTextInfo
aDrawInf( pSh
, *pOut
, 0, aTxt
, 0, aTxt
.Len() );
985 nProWidth
+= aIter
.GetFnt()->_GetTxtSize( aDrawInf
).Width();
990 // any suggestions for a default action?
997 nWidth
= Max( nWidth
, nProWidth
);
999 // search for a text frame this node belongs to
1000 SwClientIter
aClientIter( *(SwTxtNode
*)this );
1001 SwClient
* pLastFrm
= aClientIter
.GoStart();
1006 if ( pLastFrm
->ISA( SwTxtFrm
) )
1008 SwTxtFrm
* pTmpFrm
= ( SwTxtFrm
* )pLastFrm
;
1009 if ( pTmpFrm
->GetOfst() <= nStt
&&
1010 ( !pTmpFrm
->GetFollow() ||
1011 pTmpFrm
->GetFollow()->GetOfst() > nStt
) )
1017 pLastFrm
= ++aClientIter
;
1020 // search for the line containing nStt
1021 if ( pFrm
&& pFrm
->HasPara() )
1023 SwTxtInfo
aInf( pFrm
);
1024 SwTxtIter
aLine( pFrm
, &aInf
);
1025 aLine
.CharToLine( nStt
);
1026 pOut
->SetMapMode( aOldMap
);
1027 return (USHORT
)( nWidth
?
1028 ( ( 100 * aLine
.GetCurr()->Height() ) / nWidth
) : 0 );
1030 // no frame or no paragraph, we take the height of the character
1031 // at nStt as line height
1033 aIter
.SeekAndChgAttrIter( nStt
, pOut
);
1034 pOut
->SetMapMode( aOldMap
);
1036 SwDrawTextInfo
aDrawInf( pSh
, *pOut
, 0, GetTxt(), nStt
, 1 );
1038 ( nWidth
? ((100 * aIter
.GetFnt()->_GetTxtSize( aDrawInf
).Height()) / nWidth
) : 0 );
1041 USHORT
SwTxtNode::GetWidthOfLeadingTabs() const
1045 xub_StrLen nIdx
= 0;
1048 while ( nIdx
< GetTxt().Len() &&
1049 ( '\t' == ( cCh
= GetTxt().GetChar( nIdx
) ) ||
1055 SwPosition
aPos( *this );
1056 aPos
.nContent
+= nIdx
;
1058 // Find the non-follow text frame:
1059 SwClientIter
aClientIter( (SwTxtNode
&)*this );
1060 SwClient
* pLastFrm
= aClientIter
.GoStart();
1064 // Only consider master frames:
1065 if ( pLastFrm
->ISA(SwTxtFrm
) &&
1066 !static_cast<SwTxtFrm
*>(pLastFrm
)->IsFollow() )
1068 const SwTxtFrm
* pFrm
= static_cast<SwTxtFrm
*>(pLastFrm
);
1071 pFrm
->GetCharRect( aRect
, aPos
);
1073 ( pFrm
->IsRightToLeft() ?
1074 (pFrm
->*fnRect
->fnGetPrtRight
)() - (aRect
.*fnRect
->fnGetRight
)() :
1075 (aRect
.*fnRect
->fnGetLeft
)() - (pFrm
->*fnRect
->fnGetPrtLeft
)() );
1078 pLastFrm
= ++aClientIter
;