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: redlnitr.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 <svtools/whiter.hxx>
37 #include <tools/shl.hxx>
38 #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
39 #include <com/sun/star/i18n/ScriptType.hdl>
41 #include <swmodule.hxx>
42 #include <redline.hxx> // SwRedline
43 #include <txtatr.hxx> // SwTxt ...
44 #include <docary.hxx> // SwRedlineTbl
45 #include <itratr.hxx> // SwAttrIter
46 #include <ndtxt.hxx> // SwTxtNode
47 #include <doc.hxx> // SwDoc
48 #include <rootfrm.hxx>
49 #include <breakit.hxx>
50 #include <vcl/keycodes.hxx>
51 #include <vcl/cmdevt.hxx>
52 #include <vcl/settings.hxx>
53 #include <txtfrm.hxx> // SwTxtFrm
54 #ifndef _APP_HXX //autogen
55 #include <vcl/svapp.hxx>
57 #include <redlnitr.hxx>
58 #include <extinput.hxx>
59 #include <sfx2/printer.hxx>
60 #include <vcl/window.hxx>
62 using namespace ::com::sun::star
;
64 /*************************************************************************
65 * SwAttrIter::CtorInitAttrIter()
66 *************************************************************************/
67 void SwAttrIter::CtorInitAttrIter( SwTxtNode
& rTxtNode
, SwScriptInfo
& rScrInf
, SwTxtFrm
* pFrm
)
69 // Beim HTML-Import kann es vorkommen, dass kein Layout existiert.
70 SwRootFrm
* pRootFrm
= rTxtNode
.getIDocumentLayoutAccess()->GetRootFrm();
71 pShell
= pRootFrm
? pRootFrm
->GetShell() : 0;
73 pScriptInfo
= &rScrInf
;
75 // attributes set at the whole paragraph
76 pAttrSet
= rTxtNode
.GetpSwAttrSet();
78 pHints
= rTxtNode
.GetpSwpHints();
80 // Build a font matching the default paragraph style:
81 SwFontAccess
aFontAccess( &rTxtNode
.GetAnyFmtColl(), pShell
);
83 pFnt
= new SwFont( *aFontAccess
.Get()->GetFont() );
85 // set font to vertical if frame layout is vertical
86 sal_Bool bVertLayout
= sal_False
;
87 sal_Bool bRTL
= sal_False
;
90 if ( pFrm
->IsVertical() )
92 bVertLayout
= sal_True
;
93 pFnt
->SetVertical( pFnt
->GetOrientation(), sal_True
);
95 bRTL
= pFrm
->IsRightToLeft();
98 // Initialize the default attribute of the attribute handler
99 // based on the attribute array cached together with the font.
100 // If any further attributes for the paragraph are given in pAttrSet
101 // consider them during construction of the default array, and apply
103 aAttrHandler
.Init( aFontAccess
.Get()->GetDefault(), pAttrSet
,
104 *rTxtNode
.getIDocumentSettingAccess(), pShell
, *pFnt
, bVertLayout
);
106 aMagicNo
[SW_LATIN
] = aMagicNo
[SW_CJK
] = aMagicNo
[SW_CTL
] = NULL
;
108 // determine script changes if not already done for current paragraph
109 ASSERT( pScriptInfo
, "No script info available");
110 if ( pScriptInfo
->GetInvalidity() != STRING_LEN
)
111 pScriptInfo
->InitScriptInfo( rTxtNode
, bRTL
);
113 if ( pBreakIt
->GetBreakIter().is() )
115 pFnt
->SetActual( SwScriptInfo::WhichFont( 0, 0, pScriptInfo
) );
122 nChg
= pScriptInfo
->GetScriptChg( nCnt
);
123 USHORT nScript
= pScriptInfo
->GetScriptType( nCnt
++ );
126 case i18n::ScriptType::ASIAN
:
127 if( !aMagicNo
[SW_CJK
] ) nTmp
= SW_CJK
; break;
128 case i18n::ScriptType::COMPLEX
:
129 if( !aMagicNo
[SW_CTL
] ) nTmp
= SW_CTL
; break;
131 if( !aMagicNo
[SW_LATIN
] ) nTmp
= SW_LATIN
;
135 pFnt
->ChkMagic( pShell
, nTmp
);
136 pFnt
->GetMagic( aMagicNo
[ nTmp
], aFntIdx
[ nTmp
], nTmp
);
138 } while( nChg
< rTxtNode
.GetTxt().Len() );
142 pFnt
->ChkMagic( pShell
, SW_LATIN
);
143 pFnt
->GetMagic( aMagicNo
[ SW_LATIN
], aFntIdx
[ SW_LATIN
], SW_LATIN
);
146 nStartIndex
= nEndIndex
= nPos
= nChgCnt
= 0;
148 SwDoc
* pDoc
= rTxtNode
.GetDoc();
149 const IDocumentRedlineAccess
* pIDRA
= rTxtNode
.getIDocumentRedlineAccess();
151 const SwExtTextInput
* pExtInp
= pDoc
->GetExtTextInput( rTxtNode
);
152 const bool bShow
= IDocumentRedlineAccess::IsShowChanges( pIDRA
->GetRedlineMode() );
153 if( pExtInp
|| bShow
)
155 MSHORT nRedlPos
= pIDRA
->GetRedlinePos( rTxtNode
, USHRT_MAX
);
156 if( pExtInp
|| MSHRT_MAX
!= nRedlPos
)
158 const SvUShorts
* pArr
= 0;
159 xub_StrLen nInputStt
= 0;
162 pArr
= &pExtInp
->GetAttrs();
163 nInputStt
= pExtInp
->Start()->nContent
.GetIndex();
167 pRedln
= new SwRedlineItr( rTxtNode
, *pFnt
, aAttrHandler
, nRedlPos
,
168 bShow
, pArr
, nInputStt
);
176 /*************************************************************************
177 * SwRedlineItr - Der Redline-Iterator
179 * Folgende Informationen/Zustaende gibt es im RedlineIterator:
181 * nFirst ist der erste Index der RedlineTbl, der mit dem Absatz ueberlappt.
183 * nAct ist der zur Zeit aktive ( wenn bOn gesetzt ist ) oder der naechste
184 * in Frage kommende Index.
185 * nStart und nEnd geben die Grenzen des Objekts innerhalb des Absatzes an.
187 * Wenn bOn gesetzt ist, ist der Font entsprechend manipuliert worden.
189 * Wenn nAct auf MSHRT_MAX gesetzt wurde ( durch Reset() ), so ist zur Zeit
190 * kein Redline aktiv, nStart und nEnd sind invalid.
191 *************************************************************************/
193 SwRedlineItr::SwRedlineItr( const SwTxtNode
& rTxtNd
, SwFont
& rFnt
,
194 SwAttrHandler
& rAH
, MSHORT nRed
, sal_Bool bShw
, const SvUShorts
*pArr
,
195 xub_StrLen nExtStart
)
196 : rDoc( *rTxtNd
.GetDoc() ), rNd( rTxtNd
), rAttrHandler( rAH
), pSet( 0 ),
197 nNdIdx( rTxtNd
.GetIndex() ), nFirst( nRed
),
198 nAct( MSHRT_MAX
), bOn( sal_False
), bShow( bShw
)
201 pExt
= new SwExtend( *pArr
, nExtStart
);
204 Seek( rFnt
, 0, STRING_LEN
);
207 SwRedlineItr::~SwRedlineItr()
214 // Der Return-Wert von SwRedlineItr::Seek gibt an, ob der aktuelle Font
215 // veraendert wurde durch Verlassen (-1) oder Betreten eines Bereichs (+1)
217 short SwRedlineItr::_Seek( SwFont
& rFnt
, xub_StrLen nNew
, xub_StrLen nOld
)
221 return 0; // Abkuerzung: wenn wir innerhalb eines ExtendTextInputs sind
222 // kann es keine anderen Attributwechsel (auch nicht durch Redlining) geben
230 _Clear( &rFnt
); // Wir gehen hinter den aktuellen Bereich
231 ++nAct
; // und pruefen gleich den naechsten
233 else if( nNew
< nStart
)
236 _Clear( &rFnt
); // Wir gehen vor den aktuellen Bereich
238 nAct
= nFirst
; // Die Pruefung muss von vorne beginnen
240 return nRet
+ EnterExtend( rFnt
, nNew
); // Es gibt keinen vor uns.
243 return nRet
+ EnterExtend( rFnt
, nNew
); // Wir sind im gleichen Bereich geblieben.
245 if( MSHRT_MAX
== nAct
|| nOld
> nNew
)
251 for( ; nAct
< rDoc
.GetRedlineTbl().Count() ; ++nAct
)
253 rDoc
.GetRedlineTbl()[ nAct
]->CalcStartEnd( nNdIdx
, nStart
, nEnd
);
257 if( nNew
>= nStart
) // der einzig moegliche Kandidat
260 const SwRedline
*pRed
= rDoc
.GetRedlineTbl()[ nAct
];
267 const_cast<SwDoc
&>(rDoc
).GetAttrPool();
268 pSet
= new SfxItemSet(rPool
, RES_CHRATR_BEGIN
, RES_CHRATR_END
-1);
271 if( 1 < pRed
->GetStackCount() )
272 FillHints( pRed
->GetAuthor( 1 ), pRed
->GetType( 1 ) );
273 FillHints( pRed
->GetAuthor(), pRed
->GetType() );
275 SfxWhichIter
aIter( *pSet
);
276 MSHORT nWhich
= aIter
.FirstWhich();
279 const SfxPoolItem
* pItem
;
280 if( ( nWhich
< RES_CHRATR_END
) &&
281 ( SFX_ITEM_SET
== pSet
->GetItemState( nWhich
, sal_True
, &pItem
) ) )
283 SwTxtAttr
* pAttr
= MakeRedlineTxtAttr(
284 const_cast<SwDoc
&>(rDoc
),
285 *const_cast<SfxPoolItem
*>(pItem
) );
286 pAttr
->SetPriorityAttr( sal_True
);
287 aHints
.C40_INSERT( SwTxtAttr
, pAttr
, aHints
.Count());
288 rAttrHandler
.PushAndChg( *pAttr
, rFnt
);
289 if( RES_CHRATR_COLOR
== nWhich
)
290 rFnt
.SetNoCol( sal_True
);
292 nWhich
= aIter
.NextWhich();
303 return nRet
+ EnterExtend( rFnt
, nNew
);
306 void SwRedlineItr::FillHints( MSHORT nAuthor
, RedlineType_t eType
)
310 case nsRedlineType_t::REDLINE_INSERT
:
311 SW_MOD()->GetInsertAuthorAttr(nAuthor
, *pSet
);
313 case nsRedlineType_t::REDLINE_DELETE
:
314 SW_MOD()->GetDeletedAuthorAttr(nAuthor
, *pSet
);
316 case nsRedlineType_t::REDLINE_FORMAT
:
317 case nsRedlineType_t::REDLINE_FMTCOLL
:
318 SW_MOD()->GetFormatAuthorAttr(nAuthor
, *pSet
);
325 void SwRedlineItr::ChangeTxtAttr( SwFont
* pFnt
, SwTxtAttr
&rHt
, sal_Bool bChg
)
327 ASSERT( IsOn(), "SwRedlineItr::ChangeTxtAttr: Off?" );
329 if( !bShow
&& !pExt
)
334 if ( pExt
&& pExt
->IsOn() )
335 rAttrHandler
.PushAndChg( rHt
, *pExt
->GetFont() );
337 rAttrHandler
.PushAndChg( rHt
, *pFnt
);
341 ASSERT( ! pExt
|| ! pExt
->IsOn(), "Pop of attribute during opened extension" )
342 rAttrHandler
.PopAndChg( rHt
, *pFnt
);
346 void SwRedlineItr::_Clear( SwFont
* pFnt
)
348 ASSERT( bOn
, "SwRedlineItr::Clear: Off?" );
350 while( aHints
.Count() )
352 SwTxtAttr
*pPos
= aHints
[ 0 ];
355 rAttrHandler
.PopAndChg( *pPos
, *pFnt
);
357 rAttrHandler
.Pop( *pPos
);
358 SwTxtAttr::Destroy(pPos
, const_cast<SwDoc
&>(rDoc
).GetAttrPool() );
361 pFnt
->SetNoCol( sal_False
);
364 xub_StrLen
SwRedlineItr::_GetNextRedln( xub_StrLen nNext
)
366 nNext
= NextExtend( nNext
);
367 if( !bShow
|| MSHRT_MAX
== nFirst
)
369 if( MSHRT_MAX
== nAct
)
372 rDoc
.GetRedlineTbl()[ nAct
]->CalcStartEnd( nNdIdx
, nStart
, nEnd
);
379 else if( nStart
< nNext
)
384 sal_Bool
SwRedlineItr::_ChkSpecialUnderline() const
386 // Wenn die Unterstreichung oder das Escapement vom Redling kommt,
387 // wenden wir immer das SpecialUnderlining, d.h. die Unterstreichung
388 // unter der Grundlinie an.
389 for( MSHORT i
= 0; i
< aHints
.Count(); ++i
)
391 MSHORT nWhich
= aHints
[i
]->Which();
392 if( RES_CHRATR_UNDERLINE
== nWhich
||
393 RES_CHRATR_ESCAPEMENT
== nWhich
)
399 sal_Bool
SwRedlineItr::CheckLine( xub_StrLen nChkStart
, xub_StrLen nChkEnd
)
401 if( nFirst
== MSHRT_MAX
)
403 if( nChkEnd
== nChkStart
) // Leerzeilen gucken ein Zeichen weiter.
405 xub_StrLen nOldStart
= nStart
;
406 xub_StrLen nOldEnd
= nEnd
;
407 xub_StrLen nOldAct
= nAct
;
408 sal_Bool bRet
= sal_False
;
410 for( nAct
= nFirst
; nAct
< rDoc
.GetRedlineTbl().Count() ; ++nAct
)
412 rDoc
.GetRedlineTbl()[ nAct
]->CalcStartEnd( nNdIdx
, nStart
, nEnd
);
413 if( nChkEnd
< nStart
)
415 if( nChkStart
<= nEnd
&& ( nChkEnd
> nStart
|| STRING_LEN
== nEnd
) )
428 void SwExtend::ActualizeFont( SwFont
&rFnt
, MSHORT nAttr
)
430 if ( nAttr
& EXTTEXTINPUT_ATTR_UNDERLINE
)
431 rFnt
.SetUnderline( UNDERLINE_SINGLE
);
432 else if ( nAttr
& EXTTEXTINPUT_ATTR_BOLDUNDERLINE
)
433 rFnt
.SetUnderline( UNDERLINE_BOLD
);
434 else if ( nAttr
& EXTTEXTINPUT_ATTR_DOTTEDUNDERLINE
)
435 rFnt
.SetUnderline( UNDERLINE_DOTTED
);
436 else if ( nAttr
& EXTTEXTINPUT_ATTR_DASHDOTUNDERLINE
)
437 rFnt
.SetUnderline( UNDERLINE_DOTTED
);
439 if ( nAttr
& EXTTEXTINPUT_ATTR_REDTEXT
)
440 rFnt
.SetColor( Color( COL_RED
) );
442 if ( nAttr
& EXTTEXTINPUT_ATTR_HIGHLIGHT
)
444 const StyleSettings
& rStyleSettings
= GetpApp()->GetSettings().GetStyleSettings();
445 rFnt
.SetColor( rStyleSettings
.GetHighlightTextColor() );
446 rFnt
.SetBackColor( new Color( rStyleSettings
.GetHighlightColor() ) );
448 if ( nAttr
& EXTTEXTINPUT_ATTR_GRAYWAVELINE
)
449 rFnt
.SetGreyWave( sal_True
);
452 short SwExtend::Enter( SwFont
& rFnt
, xub_StrLen nNew
)
454 ASSERT( !Inside(), "SwExtend: Enter without Leave" );
455 ASSERT( !pFnt
, "SwExtend: Enter with Font" );
459 pFnt
= new SwFont( rFnt
);
460 ActualizeFont( rFnt
, rArr
[ nPos
- nStart
] );
466 sal_Bool
SwExtend::_Leave( SwFont
& rFnt
, xub_StrLen nNew
)
468 ASSERT( Inside(), "SwExtend: Leave without Enter" );
469 MSHORT nOldAttr
= rArr
[ nPos
- nStart
];
472 { // Wir sind innerhalb des ExtendText-Bereichs geblieben
473 MSHORT nAttr
= rArr
[ nPos
- nStart
];
474 if( nOldAttr
!= nAttr
) // Gibt es einen (inneren) Attributwechsel?
477 ActualizeFont( rFnt
, nAttr
);
490 xub_StrLen
SwExtend::Next( xub_StrLen nNext
)
497 else if( nPos
< nEnd
)
499 MSHORT nIdx
= nPos
- nStart
;
500 MSHORT nAttr
= rArr
[ nIdx
];
501 while( ++nIdx
< rArr
.Count() && nAttr
== rArr
[ nIdx
] )
503 nIdx
= nIdx
+ nStart
;