merge the formfield patch from ooo-build
[ooovba.git] / sw / source / core / text / redlnitr.cxx
blob3a9a7a1072f98297fc0fb26b83e0beac7c3e5288
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: redlnitr.cxx,v $
10 * $Revision: 1.42 $
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>
40 #endif
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>
56 #endif
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();
77 // attribute array
78 pHints = rTxtNode.GetpSwpHints();
80 // Build a font matching the default paragraph style:
81 SwFontAccess aFontAccess( &rTxtNode.GetAnyFmtColl(), pShell );
82 delete pFnt;
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;
88 if ( pFrm )
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
102 // them to the font
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 ) );
117 xub_StrLen nChg = 0;
118 USHORT nCnt = 0;
122 nChg = pScriptInfo->GetScriptChg( nCnt );
123 USHORT nScript = pScriptInfo->GetScriptType( nCnt++ );
124 BYTE nTmp = 4;
125 switch ( nScript ) {
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;
130 default:
131 if( !aMagicNo[SW_LATIN ] ) nTmp = SW_LATIN;
133 if( nTmp < 4 )
135 pFnt->ChkMagic( pShell, nTmp );
136 pFnt->GetMagic( aMagicNo[ nTmp ], aFntIdx[ nTmp ], nTmp );
138 } while( nChg < rTxtNode.GetTxt().Len() );
140 else
142 pFnt->ChkMagic( pShell, SW_LATIN );
143 pFnt->GetMagic( aMagicNo[ SW_LATIN ], aFntIdx[ SW_LATIN ], SW_LATIN );
146 nStartIndex = nEndIndex = nPos = nChgCnt = 0;
147 nPropFont = 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;
160 if( pExtInp )
162 pArr = &pExtInp->GetAttrs();
163 nInputStt = pExtInp->Start()->nContent.GetIndex();
164 Seek( 0 );
167 pRedln = new SwRedlineItr( rTxtNode, *pFnt, aAttrHandler, nRedlPos,
168 bShow, pArr, nInputStt );
170 if( pRedln->IsOn() )
171 ++nChgCnt;
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 )
200 if( pArr )
201 pExt = new SwExtend( *pArr, nExtStart );
202 else
203 pExt = NULL;
204 Seek( rFnt, 0, STRING_LEN );
207 SwRedlineItr::~SwRedlineItr()
209 Clear( NULL );
210 delete pSet;
211 delete pExt;
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 )
219 short nRet = 0;
220 if( ExtOn() )
221 return 0; // Abkuerzung: wenn wir innerhalb eines ExtendTextInputs sind
222 // kann es keine anderen Attributwechsel (auch nicht durch Redlining) geben
223 if( bShow )
225 if( bOn )
227 if( nNew >= nEnd )
229 --nRet;
230 _Clear( &rFnt ); // Wir gehen hinter den aktuellen Bereich
231 ++nAct; // und pruefen gleich den naechsten
233 else if( nNew < nStart )
235 --nRet;
236 _Clear( &rFnt ); // Wir gehen vor den aktuellen Bereich
237 if( nAct > nFirst )
238 nAct = nFirst; // Die Pruefung muss von vorne beginnen
239 else
240 return nRet + EnterExtend( rFnt, nNew ); // Es gibt keinen vor uns.
242 else
243 return nRet + EnterExtend( rFnt, nNew ); // Wir sind im gleichen Bereich geblieben.
245 if( MSHRT_MAX == nAct || nOld > nNew )
246 nAct = nFirst;
248 nStart = STRING_LEN;
249 nEnd = STRING_LEN;
251 for( ; nAct < rDoc.GetRedlineTbl().Count() ; ++nAct )
253 rDoc.GetRedlineTbl()[ nAct ]->CalcStartEnd( nNdIdx, nStart, nEnd );
255 if( nNew < nEnd )
257 if( nNew >= nStart ) // der einzig moegliche Kandidat
259 bOn = sal_True;
260 const SwRedline *pRed = rDoc.GetRedlineTbl()[ nAct ];
262 if (pSet)
263 pSet->ClearItem();
264 else
266 SwAttrPool& rPool =
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();
277 while( nWhich )
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();
295 ++nRet;
297 break;
299 nStart = STRING_LEN;
300 nEnd = STRING_LEN;
303 return nRet + EnterExtend( rFnt, nNew );
306 void SwRedlineItr::FillHints( MSHORT nAuthor, RedlineType_t eType )
308 switch ( eType )
310 case nsRedlineType_t::REDLINE_INSERT:
311 SW_MOD()->GetInsertAuthorAttr(nAuthor, *pSet);
312 break;
313 case nsRedlineType_t::REDLINE_DELETE:
314 SW_MOD()->GetDeletedAuthorAttr(nAuthor, *pSet);
315 break;
316 case nsRedlineType_t::REDLINE_FORMAT:
317 case nsRedlineType_t::REDLINE_FMTCOLL:
318 SW_MOD()->GetFormatAuthorAttr(nAuthor, *pSet);
319 break;
320 default:
321 break;
325 void SwRedlineItr::ChangeTxtAttr( SwFont* pFnt, SwTxtAttr &rHt, sal_Bool bChg )
327 ASSERT( IsOn(), "SwRedlineItr::ChangeTxtAttr: Off?" );
329 if( !bShow && !pExt )
330 return;
332 if( bChg )
334 if ( pExt && pExt->IsOn() )
335 rAttrHandler.PushAndChg( rHt, *pExt->GetFont() );
336 else
337 rAttrHandler.PushAndChg( rHt, *pFnt );
339 else
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?" );
349 bOn = sal_False;
350 while( aHints.Count() )
352 SwTxtAttr *pPos = aHints[ 0 ];
353 aHints.Remove(0);
354 if( pFnt )
355 rAttrHandler.PopAndChg( *pPos, *pFnt );
356 else
357 rAttrHandler.Pop( *pPos );
358 SwTxtAttr::Destroy(pPos, const_cast<SwDoc&>(rDoc).GetAttrPool() );
360 if( pFnt )
361 pFnt->SetNoCol( sal_False );
364 xub_StrLen SwRedlineItr::_GetNextRedln( xub_StrLen nNext )
366 nNext = NextExtend( nNext );
367 if( !bShow || MSHRT_MAX == nFirst )
368 return nNext;
369 if( MSHRT_MAX == nAct )
371 nAct = nFirst;
372 rDoc.GetRedlineTbl()[ nAct ]->CalcStartEnd( nNdIdx, nStart, nEnd );
374 if( bOn || !nStart )
376 if( nEnd < nNext )
377 nNext = nEnd;
379 else if( nStart < nNext )
380 nNext = nStart;
381 return 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 )
394 return sal_True;
396 return sal_False;
399 sal_Bool SwRedlineItr::CheckLine( xub_StrLen nChkStart, xub_StrLen nChkEnd )
401 if( nFirst == MSHRT_MAX )
402 return sal_False;
403 if( nChkEnd == nChkStart ) // Leerzeilen gucken ein Zeichen weiter.
404 ++nChkEnd;
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 )
414 break;
415 if( nChkStart <= nEnd && ( nChkEnd > nStart || STRING_LEN == nEnd ) )
417 bRet = sal_True;
418 break;
422 nStart = nOldStart;
423 nEnd = nOldEnd;
424 nAct = nOldAct;
425 return bRet;
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" );
456 nPos = nNew;
457 if( Inside() )
459 pFnt = new SwFont( rFnt );
460 ActualizeFont( rFnt, rArr[ nPos - nStart ] );
461 return 1;
463 return 0;
466 sal_Bool SwExtend::_Leave( SwFont& rFnt, xub_StrLen nNew )
468 ASSERT( Inside(), "SwExtend: Leave without Enter" );
469 MSHORT nOldAttr = rArr[ nPos - nStart ];
470 nPos = nNew;
471 if( Inside() )
472 { // Wir sind innerhalb des ExtendText-Bereichs geblieben
473 MSHORT nAttr = rArr[ nPos - nStart ];
474 if( nOldAttr != nAttr ) // Gibt es einen (inneren) Attributwechsel?
476 rFnt = *pFnt;
477 ActualizeFont( rFnt, nAttr );
480 else
482 rFnt = *pFnt;
483 delete pFnt;
484 pFnt = NULL;
485 return sal_True;
487 return sal_False;
490 xub_StrLen SwExtend::Next( xub_StrLen nNext )
492 if( nPos < nStart )
494 if( nNext > nStart )
495 nNext = nStart;
497 else if( nPos < nEnd )
499 MSHORT nIdx = nPos - nStart;
500 MSHORT nAttr = rArr[ nIdx ];
501 while( ++nIdx < rArr.Count() && nAttr == rArr[ nIdx ] )
502 ; //nothing
503 nIdx = nIdx + nStart;
504 if( nNext > nIdx )
505 nNext = nIdx;
507 return nNext;