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: edattr.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>
37 #ifndef _SVX_TSTPITEM_HXX //autogen
38 #include <svx/tstpitem.hxx>
40 #include <svx/lrspitem.hxx>
41 #include <svx/scripttypeitem.hxx>
42 #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
43 #include <com/sun/star/i18n/ScriptType.hdl>
45 #include <txatbase.hxx>
49 #include <edimp.hxx> // fuer MACROS
51 #include <swundo.hxx> // fuer UNDO-Ids
55 #include <rootfrm.hxx>
57 #include <breakit.hxx>
60 #include <crsskip.hxx>
61 #include <txtfrm.hxx> // SwTxtFrm
62 #include <scriptinfo.hxx>
63 #include <svtools/ctloptions.hxx>
64 #include <charfmt.hxx> // #i27615#
65 #include <numrule.hxx>
68 /*************************************
69 * harte Formatierung (Attribute)
70 *************************************/
72 // wenn Selektion groesser Max Nodes oder mehr als Max Selektionen
74 const USHORT
& getMaxLookup()
76 static const USHORT nMaxLookup
= 1000;
80 // --> OD 2008-01-16 #newlistlevelattrs#
81 BOOL
SwEditShell::GetCurAttr( SfxItemSet
& rSet
,
82 const bool bMergeIndentValuesOfNumRule
) const
85 if( GetCrsrCnt() > getMaxLookup() )
87 rSet
.InvalidateAllItems();
91 SfxItemSet
aSet( *rSet
.GetPool(), rSet
.GetRanges() );
92 SfxItemSet
*pSet
= &rSet
;
94 FOREACHPAM_START(this)
96 // #i27615# if the cursor is in front of the numbering label
97 // the attributes to get are those from the numbering format.
98 if (PCURCRSR
->IsInFrontOfLabel())
101 PCURCRSR
->GetPoint()->nNode
.GetNode().GetTxtNode();
105 SwNumRule
* pNumRule
= pTxtNd
->GetNumRule();
109 const String
& aCharFmtName
=
110 pNumRule
->Get(static_cast<USHORT
>(pTxtNd
->GetActualListLevel())).GetCharFmtName();
111 SwCharFmt
* pCharFmt
=
112 GetDoc()->FindCharFmtByName(aCharFmtName
);
115 rSet
.Put(pCharFmt
->GetAttrSet());
122 ULONG nSttNd
= PCURCRSR
->GetMark()->nNode
.GetIndex(),
123 nEndNd
= PCURCRSR
->GetPoint()->nNode
.GetIndex();
124 xub_StrLen nSttCnt
= PCURCRSR
->GetMark()->nContent
.GetIndex(),
125 nEndCnt
= PCURCRSR
->GetPoint()->nContent
.GetIndex();
127 if( nSttNd
> nEndNd
|| ( nSttNd
== nEndNd
&& nSttCnt
> nEndCnt
))
129 ULONG nTmp
= nSttNd
; nSttNd
= nEndNd
; nEndNd
= nTmp
;
130 nTmp
= nSttCnt
; nSttCnt
= nEndCnt
; nEndCnt
= (xub_StrLen
)nTmp
;
133 if( nEndNd
- nSttNd
>= getMaxLookup() )
136 rSet
.InvalidateAllItems();
140 // beim 1.Node traegt der Node die Werte in den GetSet ein (Initial)
141 // alle weiteren Nodes werden zum GetSet zu gemergt
142 for( ULONG n
= nSttNd
; n
<= nEndNd
; ++n
)
144 SwNode
* pNd
= GetDoc()->GetNodes()[ n
];
145 switch( pNd
->GetNodeType() )
149 xub_StrLen nStt
= n
== nSttNd
? nSttCnt
: 0,
150 nEnd
= n
== nEndNd
? nEndCnt
151 : ((SwTxtNode
*)pNd
)->GetTxt().Len();
152 // --> OD 2008-01-16 #newlistlevelattrs#
153 ((SwTxtNode
*)pNd
)->GetAttr( *pSet
, nStt
, nEnd
,
155 bMergeIndentValuesOfNumRule
);
161 ((SwCntntNode
*)pNd
)->GetAttr( *pSet
);
171 rSet
.MergeValues( aSet
);
184 SwTxtFmtColl
* SwEditShell::GetCurTxtFmtColl() const
186 SwTxtFmtColl
*pFmt
= 0;
188 if ( GetCrsrCnt() > getMaxLookup() )
191 FOREACHPAM_START(this)
193 ULONG nSttNd
= PCURCRSR
->GetMark()->nNode
.GetIndex(),
194 nEndNd
= PCURCRSR
->GetPoint()->nNode
.GetIndex();
195 xub_StrLen nSttCnt
= PCURCRSR
->GetMark()->nContent
.GetIndex(),
196 nEndCnt
= PCURCRSR
->GetPoint()->nContent
.GetIndex();
198 if( nSttNd
> nEndNd
|| ( nSttNd
== nEndNd
&& nSttCnt
> nEndCnt
))
200 ULONG nTmp
= nSttNd
; nSttNd
= nEndNd
; nEndNd
= nTmp
;
201 nTmp
= nSttCnt
; nSttCnt
= nEndCnt
; nEndCnt
= (xub_StrLen
)nTmp
;
204 if( nEndNd
- nSttNd
>= getMaxLookup() )
210 for( ULONG n
= nSttNd
; n
<= nEndNd
; ++n
)
212 SwNode
* pNd
= GetDoc()->GetNodes()[ n
];
213 if( pNd
->IsTxtNode() )
216 pFmt
= ((SwTxtNode
*)pNd
)->GetTxtColl();
217 else if( pFmt
== ((SwTxtNode
*)pNd
)->GetTxtColl() ) // ???
228 BOOL
SwEditShell::GetCurFtn( SwFmtFtn
* pFillFtn
)
230 // der Cursor muss auf dem akt. Fussnoten-Anker stehen:
231 SwPaM
* pCrsr
= GetCrsr();
232 SwTxtNode
* pTxtNd
= pCrsr
->GetNode()->GetTxtNode();
236 SwTxtAttr
*pFtn
= pTxtNd
->GetTxtAttr( pCrsr
->GetPoint()->nContent
,
238 if( pFtn
&& pFillFtn
)
240 // Daten vom Attribut uebertragen
241 const SwFmtFtn
&rFtn
= ((SwTxtFtn
*)pFtn
)->GetFtn();
242 pFillFtn
->SetNumber( rFtn
);
243 pFillFtn
->SetEndNote( rFtn
.IsEndNote() );
249 bool SwEditShell::SetCurFtn( const SwFmtFtn
& rFillFtn
)
254 SwPaM
* pCrsr
= GetCrsr(), *pFirst
= pCrsr
;
256 bChgd
|= pDoc
->SetCurFtn( *pCrsr
, rFillFtn
.GetNumStr(),
257 rFillFtn
.GetNumber(),
258 rFillFtn
.IsEndNote() );
260 } while( pFirst
!= ( pCrsr
= (SwPaM
*)pCrsr
->GetNext() ));
268 /*USHORT SwEditShell::GetFtnCnt( BOOL bEndNotes = FALSE ) const
270 const SwFtnIdxs &rIdxs = pDoc->GetFtnIdxs();
272 for ( USHORT i = 0; i < rIdxs.Count(); ++i )
274 const SwFmtFtn &rFtn = rIdxs[i]->GetFtn();
275 if ( bEndNotes == rFtn.IsEndNote() )
282 bool SwEditShell::HasFtns( bool bEndNotes
) const
284 const SwFtnIdxs
&rIdxs
= pDoc
->GetFtnIdxs();
285 for ( USHORT i
= 0; i
< rIdxs
.Count(); ++i
)
287 const SwFmtFtn
&rFtn
= rIdxs
[i
]->GetFtn();
288 if ( bEndNotes
== rFtn
.IsEndNote() )
295 // gebe Liste aller Fussnoten und deren Anfangstexte
296 USHORT
SwEditShell::GetSeqFtnList( SwSeqFldList
& rList
, bool bEndNotes
)
299 rList
.Remove( 0, rList
.Count() );
301 USHORT n
, nFtnCnt
= pDoc
->GetFtnIdxs().Count();
303 for( n
= 0; n
< nFtnCnt
; ++n
)
305 pTxtFtn
= pDoc
->GetFtnIdxs()[ n
];
306 const SwFmtFtn
& rFtn
= pTxtFtn
->GetFtn();
307 if ( rFtn
.IsEndNote() != bEndNotes
)
310 SwNodeIndex
* pIdx
= pTxtFtn
->GetStartNode();
313 SwNodeIndex
aIdx( *pIdx
, 1 );
314 SwTxtNode
* pTxtNd
= aIdx
.GetNode().GetTxtNode();
316 pTxtNd
= (SwTxtNode
*)pDoc
->GetNodes().GoNext( &aIdx
);
320 String
sTxt( rFtn
.GetViewNumStr( *pDoc
));
323 sTxt
+= pTxtNd
->GetExpandTxt( 0, USHRT_MAX
);
325 _SeqFldLstElem
* pNew
= new _SeqFldLstElem( sTxt
,
326 pTxtFtn
->GetSeqRefNo() );
327 while( rList
.InsertSort( pNew
) )
328 pNew
->sDlgEntry
+= ' ';
333 return rList
.Count();
337 // linken Rand ueber Objectleiste einstellen (aenhlich dem Stufen von
339 BOOL
SwEditShell::IsMoveLeftMargin( BOOL bRight
, BOOL bModulus
) const
343 const SvxTabStopItem
& rTabItem
= (SvxTabStopItem
&)GetDoc()->
344 GetDefault( RES_PARATR_TABSTOP
);
345 USHORT nDefDist
= static_cast<USHORT
>(rTabItem
.Count() ? rTabItem
[0].GetTabPos() : 1134);
349 FOREACHPAM_START(this)
351 ULONG nSttNd
= PCURCRSR
->GetMark()->nNode
.GetIndex(),
352 nEndNd
= PCURCRSR
->GetPoint()->nNode
.GetIndex();
354 if( nSttNd
> nEndNd
)
356 ULONG nTmp
= nSttNd
; nSttNd
= nEndNd
; nEndNd
= nTmp
;
360 for( ULONG n
= nSttNd
; bRet
&& n
<= nEndNd
; ++n
)
361 if( 0 != ( pCNd
= GetDoc()->GetNodes()[ n
]->GetTxtNode() ))
363 const SvxLRSpaceItem
& rLS
= (SvxLRSpaceItem
&)
364 pCNd
->GetAttr( RES_LR_SPACE
);
367 long nNext
= rLS
.GetTxtLeft() + nDefDist
;
369 nNext
= ( nNext
/ nDefDist
) * nDefDist
;
370 SwFrm
* pFrm
= pCNd
->GetFrm();
373 const USHORT nFrmWidth
= static_cast<USHORT
>( pFrm
->IsVertical() ?
374 pFrm
->Frm().Height() :
375 pFrm
->Frm().Width() );
376 bRet
= nFrmWidth
> ( nNext
+ MM50
);
390 void SwEditShell::MoveLeftMargin( BOOL bRight
, BOOL bModulus
)
393 StartUndo( UNDO_START
);
395 SwPaM
* pCrsr
= GetCrsr();
396 if( pCrsr
->GetNext() != pCrsr
) // Mehrfachselektion ?
398 SwPamRanges
aRangeArr( *pCrsr
);
399 SwPaM
aPam( *pCrsr
->GetPoint() );
400 for( USHORT n
= 0; n
< aRangeArr
.Count(); ++n
)
401 GetDoc()->MoveLeftMargin( aRangeArr
.SetPam( n
, aPam
),
405 GetDoc()->MoveLeftMargin( *pCrsr
, bRight
, bModulus
);
412 inline USHORT
lcl_SetScriptFlags( USHORT nType
)
417 case ::com::sun::star::i18n::ScriptType::LATIN
: nRet
= SCRIPTTYPE_LATIN
; break;
418 case ::com::sun::star::i18n::ScriptType::ASIAN
: nRet
= SCRIPTTYPE_ASIAN
; break;
419 case ::com::sun::star::i18n::ScriptType::COMPLEX
: nRet
= SCRIPTTYPE_COMPLEX
; break;
425 BOOL
lcl_IsNoEndTxtAttrAtPos( const SwTxtNode
& rTNd
, xub_StrLen nPos
,
426 USHORT
&rScrpt
, BOOL bInSelection
, BOOL bNum
)
429 const String
& rTxt
= rTNd
.GetTxt();
432 // consider numbering
437 // --> OD 2008-03-19 #refactorlists#
438 if ( rTNd
.IsInList() )
440 ASSERT( rTNd
.GetNumRule(),
441 "<lcl_IsNoEndTxtAttrAtPos(..)> - no list style found at text node. Serious defect -> please inform OD." );
442 const SwNumRule
* pNumRule
= rTNd
.GetNumRule();
443 const SwNumFmt
&rNumFmt
= pNumRule
->Get( static_cast<USHORT
>(rTNd
.GetActualListLevel()) );
444 if( SVX_NUM_BITMAP
!= rNumFmt
.GetNumberingType() )
446 if ( SVX_NUM_CHAR_SPECIAL
== rNumFmt
.GetNumberingType() )
447 sExp
= rNumFmt
.GetBulletChar();
449 sExp
= rTNd
.GetNumString();
455 if ( CH_TXTATR_BREAKWORD
== rTxt
.GetChar( nPos
) )
457 const SwTxtAttr
* const pAttr
= rTNd
.GetTxtAttrForCharAt( nPos
);
460 bRet
= TRUE
; // all other than fields can be
461 // defined as weak-script ?
462 if ( RES_TXTATR_FIELD
== pAttr
->Which() )
464 const SwField
* const pFld
= pAttr
->GetFld().GetFld();
467 sExp
+= pFld
->Expand();
473 xub_StrLen nEnd
= sExp
.Len();
480 for( n
= 0; n
< nEnd
; n
= (xub_StrLen
)
481 pBreakIt
->GetBreakIter()->endOfScript( sExp
, n
, nScript
))
483 nScript
= pBreakIt
->GetBreakIter()->getScriptType( sExp
, n
);
484 rScrpt
|= lcl_SetScriptFlags( nScript
);
488 rScrpt
|= lcl_SetScriptFlags( pBreakIt
->GetBreakIter()->
489 getScriptType( sExp
, nEnd
-1 ));
496 // returns the scripttpye of the selection
497 USHORT
SwEditShell::GetScriptType() const
500 //if( pBreakIt->GetBreakIter().is() )
502 FOREACHPAM_START(this)
504 const SwPosition
*pStt
= PCURCRSR
->Start(),
505 *pEnd
= pStt
== PCURCRSR
->GetMark()
506 ? PCURCRSR
->GetPoint()
507 : PCURCRSR
->GetMark();
508 if( pStt
== pEnd
|| *pStt
== *pEnd
)
510 const SwTxtNode
* pTNd
= pStt
->nNode
.GetNode().GetTxtNode();
513 // try to get SwScriptInfo
514 const SwScriptInfo
* pScriptInfo
= SwScriptInfo::GetScriptInfo( *pTNd
);
516 xub_StrLen nPos
= pStt
->nContent
.GetIndex();
517 //Task 90448: we need the scripttype of the previous
518 // position, if no selection exist!
521 SwIndex
aIdx( pStt
->nContent
);
522 if( pTNd
->GoPrevious( &aIdx
, CRSR_SKIP_CHARS
) )
523 nPos
= aIdx
.GetIndex();
528 if ( pTNd
->GetTxt().Len() )
530 nScript
= pScriptInfo
?
531 pScriptInfo
->ScriptType( nPos
) :
532 pBreakIt
->GetBreakIter()->getScriptType( pTNd
->GetTxt(), nPos
);
535 nScript
= GetI18NScriptTypeOfLanguage( (USHORT
)GetAppLanguage() );
537 if( !lcl_IsNoEndTxtAttrAtPos( *pTNd
, nPos
, nRet
, FALSE
, FALSE
))
538 nRet
|= lcl_SetScriptFlags( nScript
);
541 else if ( pBreakIt
->GetBreakIter().is() )
543 ULONG nEndIdx
= pEnd
->nNode
.GetIndex();
544 SwNodeIndex
aIdx( pStt
->nNode
);
545 for( ; aIdx
.GetIndex() <= nEndIdx
; aIdx
++ )
546 if( aIdx
.GetNode().IsTxtNode() )
548 const SwTxtNode
* pTNd
= aIdx
.GetNode().GetTxtNode();
549 const String
& rTxt
= pTNd
->GetTxt();
551 // try to get SwScriptInfo
552 const SwScriptInfo
* pScriptInfo
= SwScriptInfo::GetScriptInfo( *pTNd
);
554 xub_StrLen nChg
= aIdx
== pStt
->nNode
555 ? pStt
->nContent
.GetIndex()
557 nEndPos
= aIdx
== nEndIdx
558 ? pEnd
->nContent
.GetIndex()
561 ASSERT( nEndPos
<= rTxt
.Len(), "Index outside the range - endless loop!" );
562 if( nEndPos
> rTxt
.Len() )
563 nEndPos
= rTxt
.Len();
566 while( nChg
< nEndPos
)
568 nScript
= pScriptInfo
?
569 pScriptInfo
->ScriptType( nChg
) :
570 pBreakIt
->GetBreakIter()->getScriptType(
573 if( !lcl_IsNoEndTxtAttrAtPos( *pTNd
, nChg
, nRet
, TRUE
,
574 0 == nChg
&& rTxt
.Len() == nEndPos
) )
575 nRet
|= lcl_SetScriptFlags( nScript
);
577 if( (SCRIPTTYPE_LATIN
| SCRIPTTYPE_ASIAN
|
578 SCRIPTTYPE_COMPLEX
) == nRet
)
581 xub_StrLen nFldPos
= nChg
+1;
584 pScriptInfo
->NextScriptChg( nChg
) :
585 (xub_StrLen
)pBreakIt
->GetBreakIter()->endOfScript(
586 rTxt
, nChg
, nScript
);
588 nFldPos
= rTxt
.Search(
589 CH_TXTATR_BREAKWORD
, nFldPos
);
593 if( (SCRIPTTYPE_LATIN
| SCRIPTTYPE_ASIAN
|
594 SCRIPTTYPE_COMPLEX
) == nRet
)
598 if( (SCRIPTTYPE_LATIN
| SCRIPTTYPE_ASIAN
|
599 SCRIPTTYPE_COMPLEX
) == nRet
)
605 nRet
= SvtLanguageOptions::GetScriptTypeOfLanguage( LANGUAGE_SYSTEM
);
610 USHORT
SwEditShell::GetCurLang() const
612 const SwPaM
* pCrsr
= GetCrsr();
613 const SwPosition
& rPos
= *pCrsr
->GetPoint();
614 const SwTxtNode
* pTNd
= rPos
.nNode
.GetNode().GetTxtNode();
618 //JP 24.9.2001: if exist no selection, then get the language before
619 // the current character!
620 xub_StrLen nPos
= rPos
.nContent
.GetIndex();
621 if( nPos
&& !pCrsr
->HasMark() )
623 nLang
= pTNd
->GetLang( nPos
);
626 nLang
= LANGUAGE_DONTKNOW
;
630 USHORT
SwEditShell::GetScalingOfSelectedText() const
632 const SwPaM
* pCrsr
= GetCrsr();
633 const SwPosition
* pStt
= pCrsr
->Start();
634 const SwTxtNode
* pTNd
= pStt
->nNode
.GetNode().GetTxtNode();
635 ASSERT( pTNd
, "no textnode available" );
640 xub_StrLen nStt
= pStt
->nContent
.GetIndex(), nEnd
;
641 const SwPosition
* pEnd
= pStt
== pCrsr
->GetPoint()
644 if( pStt
->nNode
== pEnd
->nNode
)
645 nEnd
= pEnd
->nContent
.GetIndex();
647 nEnd
= pTNd
->GetTxt().Len();
648 nScaleWidth
= pTNd
->GetScalingOfSelectedText( nStt
, nEnd
);
651 nScaleWidth
= 100; // default are no scaling -> 100%