Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <com/sun/star/uno/Sequence.h>
21 : #include <unotools/linguprops.hxx>
22 : #include <unotools/lingucfg.hxx>
23 : #include <hintids.hxx>
24 : #include <sfx2/printer.hxx>
25 : #include <editeng/hyznitem.hxx>
26 : #include <editeng/escpitem.hxx>
27 : #include <editeng/hngpnctitem.hxx>
28 : #include <editeng/scriptspaceitem.hxx>
29 : #include <editeng/brshitem.hxx>
30 : #include <editeng/splwrap.hxx>
31 : #include <editeng/pgrditem.hxx>
32 : #include <editeng/tstpitem.hxx>
33 : #include <xmloff/odffields.hxx>
34 :
35 : #include <SwSmartTagMgr.hxx>
36 : #include <linguistic/lngprops.hxx>
37 : #include <editeng/unolingu.hxx>
38 : #include <breakit.hxx>
39 : #include <editeng/forbiddenruleitem.hxx>
40 : #include <txatbase.hxx>
41 : #include <fmtinfmt.hxx>
42 : #include <fmtfld.hxx>
43 : #include <fldbas.hxx>
44 : #include <PostItMgr.hxx>
45 : #include <swmodule.hxx>
46 : #include <vcl/svapp.hxx>
47 : #include <vcl/wrkwin.hxx>
48 : #include <viewsh.hxx> // ViewShell
49 : #include <viewopt.hxx> // SwViewOptions
50 : #include <frmtool.hxx> // DrawGraphic
51 : #include <IDocumentSettingAccess.hxx>
52 : #include <IDocumentDeviceAccess.hxx>
53 : #include <paratr.hxx> // SwFmtDrop
54 : #include <rootfrm.hxx> // SwRootFrm
55 : #include <inftxt.hxx> // SwTxtInfo
56 : #include <blink.hxx> // SwBlink
57 : #include <noteurl.hxx> // SwNoteURL
58 : #include <porftn.hxx> // SwFtnPortion
59 : #include <porrst.hxx> // SwHangingPortion
60 : #include <itratr.hxx>
61 : #include <accessibilityoptions.hxx>
62 : #include <wrong.hxx>
63 : #include <doc.hxx>
64 : #include <pam.hxx>
65 : #include <SwGrammarMarkUp.hxx>
66 : #include <cstdio>
67 : // #i12836# enhanced pdf export
68 : #include <EnhancedPDFExportHelper.hxx>
69 :
70 : #include <unomid.h>
71 :
72 : #if OSL_DEBUG_LEVEL > 1
73 : #include <stdio.h>
74 : #endif
75 :
76 : using namespace ::com::sun::star;
77 : using namespace ::com::sun::star::linguistic2;
78 : using namespace ::com::sun::star::uno;
79 : using namespace ::com::sun::star::beans;
80 :
81 :
82 : #define CHAR_UNDERSCORE ((sal_Unicode)0x005F)
83 : #define CHAR_LEFT_ARROW ((sal_Unicode)0x25C0)
84 : #define CHAR_RIGHT_ARROW ((sal_Unicode)0x25B6)
85 : #define CHAR_TAB ((sal_Unicode)0x2192)
86 : #define CHAR_TAB_RTL ((sal_Unicode)0x2190)
87 : #define CHAR_LINEBREAK ((sal_Unicode)0x21B5)
88 : #define CHAR_LINEBREAK_RTL ((sal_Unicode)0x21B3)
89 :
90 : #define DRAW_SPECIAL_OPTIONS_CENTER 1
91 : #define DRAW_SPECIAL_OPTIONS_ROTATE 2
92 :
93 : // variable moved to class <numfunc:GetDefBulletConfig>
94 : //extern const sal_Char sBulletFntName[];
95 : namespace numfunc
96 : {
97 : extern const String& GetDefBulletFontname();
98 : extern bool IsDefBulletFontUserDefined();
99 : }
100 :
101 : #ifdef DBG_UTIL
102 : sal_Bool SwTxtSizeInfo::IsOptDbg() const { return GetOpt().IsTest4(); }
103 : #endif
104 :
105 4152 : SwLineInfo::SwLineInfo()
106 : : pRuler( 0 ),
107 : pSpace( 0 ),
108 : nVertAlign( 0 ),
109 : nDefTabStop( 0 ),
110 : bListTabStopIncluded( false ),
111 4152 : nListTabStopPosition( 0 )
112 : {
113 4152 : }
114 :
115 4152 : SwLineInfo::~SwLineInfo()
116 : {
117 4152 : delete pRuler;
118 4152 : }
119 4152 : void SwLineInfo::CtorInitLineInfo( const SwAttrSet& rAttrSet,
120 : const SwTxtNode& rTxtNode )
121 : {
122 4152 : delete pRuler;
123 4152 : pRuler = new SvxTabStopItem( rAttrSet.GetTabStops() );
124 4152 : if ( rTxtNode.GetListTabStopPosition( nListTabStopPosition ) )
125 : {
126 167 : bListTabStopIncluded = true;
127 :
128 : // insert the list tab stop into SvxTabItem instance <pRuler>
129 : const SvxTabStop aListTabStop( nListTabStopPosition,
130 167 : SVX_TAB_ADJUST_LEFT );
131 167 : pRuler->Insert( aListTabStop );
132 :
133 : // remove default tab stops, which are before the inserted list tab stop
134 419 : for ( sal_uInt16 i = 0; i < pRuler->Count(); i++ )
135 : {
136 252 : if ( (*pRuler)[i].GetTabPos() < nListTabStopPosition &&
137 0 : (*pRuler)[i].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT )
138 : {
139 0 : pRuler->Remove(i);
140 0 : continue;
141 : }
142 : }
143 : }
144 :
145 4152 : if ( !rTxtNode.getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT) )
146 : {
147 : // remove default tab stop at position 0
148 8639 : for ( sal_uInt16 i = 0; i < pRuler->Count(); i++ )
149 : {
150 4951 : if ( (*pRuler)[i].GetTabPos() == 0 &&
151 161 : (*pRuler)[i].GetAdjustment() == SVX_TAB_ADJUST_DEFAULT )
152 : {
153 0 : pRuler->Remove(i);
154 0 : break;
155 : }
156 : }
157 : }
158 :
159 4152 : pSpace = &rAttrSet.GetLineSpacing();
160 4152 : nVertAlign = rAttrSet.GetParaVertAlign().GetValue();
161 4152 : nDefTabStop = MSHRT_MAX;
162 4152 : }
163 :
164 4152 : void SwTxtInfo::CtorInitTxtInfo( SwTxtFrm *pFrm )
165 : {
166 4152 : pPara = pFrm->GetPara();
167 4152 : nTxtStart = pFrm->GetOfst();
168 4152 : if( !pPara )
169 : {
170 : OSL_ENSURE( pPara, "+SwTxtInfo::CTOR: missing paragraph information" );
171 0 : pFrm->Format();
172 0 : pPara = pFrm->GetPara();
173 : }
174 4152 : }
175 :
176 2985 : SwTxtInfo::SwTxtInfo( const SwTxtInfo &rInf )
177 2985 : : pPara( ((SwTxtInfo&)rInf).GetParaPortion() ),
178 2985 : nTxtStart( rInf.GetTxtStart() )
179 2985 : { }
180 :
181 :
182 : #if OSL_DEBUG_LEVEL > 0
183 :
184 : void ChkOutDev( const SwTxtSizeInfo &rInf )
185 : {
186 : if ( !rInf.GetVsh() )
187 : return;
188 :
189 : const OutputDevice* pOut = rInf.GetOut();
190 : const OutputDevice* pRef = rInf.GetRefDev();
191 : OSL_ENSURE( pOut && pRef, "ChkOutDev: invalid output devices" );
192 : }
193 : #endif
194 :
195 :
196 6416 : inline xub_StrLen GetMinLen( const SwTxtSizeInfo &rInf )
197 : {
198 6416 : const xub_StrLen nInfLen = rInf.GetIdx() + rInf.GetLen();
199 6416 : return Min( rInf.GetTxt().Len(), nInfLen );
200 : }
201 :
202 :
203 721 : SwTxtSizeInfo::SwTxtSizeInfo( const SwTxtSizeInfo &rNew )
204 : : SwTxtInfo( rNew ),
205 721 : pKanaComp(((SwTxtSizeInfo&)rNew).GetpKanaComp()),
206 721 : pVsh(((SwTxtSizeInfo&)rNew).GetVsh()),
207 721 : pOut(((SwTxtSizeInfo&)rNew).GetOut()),
208 721 : pRef(((SwTxtSizeInfo&)rNew).GetRefDev()),
209 721 : pFnt(((SwTxtSizeInfo&)rNew).GetFont()),
210 721 : pUnderFnt(((SwTxtSizeInfo&)rNew).GetUnderFnt()),
211 : pFrm(rNew.pFrm),
212 721 : pOpt(&rNew.GetOpt()),
213 721 : pTxt(&rNew.GetTxt()),
214 721 : nIdx(rNew.GetIdx()),
215 721 : nLen(rNew.GetLen()),
216 721 : nKanaIdx( rNew.GetKanaIdx() ),
217 721 : bOnWin( rNew.OnWin() ),
218 721 : bNotEOL( rNew.NotEOL() ),
219 721 : bURLNotify( rNew.URLNotify() ),
220 721 : bStopUnderFlow( rNew.StopUnderFlow() ),
221 721 : bFtnInside( rNew.IsFtnInside() ),
222 721 : bOtherThanFtnInside( rNew.IsOtherThanFtnInside() ),
223 721 : bMulti( rNew.IsMulti() ),
224 721 : bFirstMulti( rNew.IsFirstMulti() ),
225 721 : bRuby( rNew.IsRuby() ),
226 721 : bHanging( rNew.IsHanging() ),
227 721 : bScriptSpace( rNew.HasScriptSpace() ),
228 721 : bForbiddenChars( rNew.HasForbiddenChars() ),
229 721 : bSnapToGrid( rNew.SnapToGrid() ),
230 18025 : nDirection( rNew.GetDirection() )
231 : {
232 : #if OSL_DEBUG_LEVEL > 0
233 : ChkOutDev( *this );
234 : #endif
235 721 : }
236 :
237 4152 : void SwTxtSizeInfo::CtorInitTxtSizeInfo( SwTxtFrm *pFrame, SwFont *pNewFnt,
238 : const xub_StrLen nNewIdx, const xub_StrLen nNewLen )
239 : {
240 4152 : pKanaComp = NULL;
241 4152 : nKanaIdx = 0;
242 4152 : pFrm = pFrame;
243 4152 : CtorInitTxtInfo( pFrm );
244 4152 : const SwTxtNode *pNd = pFrm->GetTxtNode();
245 4152 : pVsh = pFrm->getRootFrm()->GetCurrShell();
246 :
247 : // Get the output and reference device
248 4152 : if ( pVsh )
249 : {
250 4152 : pOut = pVsh->GetOut();
251 4152 : pRef = &pVsh->GetRefDev();
252 4152 : bOnWin = pVsh->GetWin() || OUTDEV_WINDOW == pOut->GetOutDevType();
253 : }
254 : else
255 : {
256 : // Access via StarONE. We do not need a Shell or an active one.
257 0 : if ( pNd->getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE) )
258 : {
259 : // We can only pick the AppWin here? (there's nothing better to pick?)
260 0 : pOut = GetpApp()->GetDefaultDevice();
261 : }
262 : else
263 0 : pOut = pNd->getIDocumentDeviceAccess()->getPrinter( false );
264 :
265 0 : pRef = pOut;
266 : }
267 :
268 : #if OSL_DEBUG_LEVEL > 0
269 : ChkOutDev( *this );
270 : #endif
271 :
272 : // Set default layout mode ( LTR or RTL ).
273 4152 : if ( pFrm->IsRightToLeft() )
274 : {
275 0 : pOut->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL );
276 0 : pRef->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL );
277 0 : nDirection = DIR_RIGHT2LEFT;
278 : }
279 : else
280 : {
281 4152 : pOut->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG );
282 4152 : pRef->SetLayoutMode( TEXT_LAYOUT_BIDI_STRONG );
283 4152 : nDirection = DIR_LEFT2RIGHT;
284 : }
285 :
286 : //
287 : // The Options
288 : //
289 : pOpt = pVsh ?
290 4152 : pVsh->GetViewOptions() :
291 8304 : SW_MOD()->GetViewOption( pNd->getIDocumentSettingAccess()->get(IDocumentSettingAccess::HTML_MODE) ); // Options from Module, due to StarONE
292 :
293 : // bURLNotify is set if MakeGraphic prepares it
294 : // TODO: Unwind
295 4152 : bURLNotify = pNoteURL && !bOnWin;
296 :
297 4152 : SetSnapToGrid( pNd->GetSwAttrSet().GetParaGrid().GetValue() &&
298 4152 : pFrm->IsInDocBody() );
299 :
300 4152 : pFnt = pNewFnt;
301 4152 : pUnderFnt = 0;
302 4152 : pTxt = &pNd->GetTxt();
303 :
304 4152 : nIdx = nNewIdx;
305 4152 : nLen = nNewLen;
306 4152 : bNotEOL = false;
307 4152 : bStopUnderFlow = bFtnInside = bOtherThanFtnInside = false;
308 : bMulti = bFirstMulti = bRuby = bHanging = bScriptSpace =
309 4152 : bForbiddenChars = false;
310 :
311 4152 : SetLen( GetMinLen( *this ) );
312 4152 : }
313 :
314 2264 : SwTxtSizeInfo::SwTxtSizeInfo( const SwTxtSizeInfo &rNew, const XubString &rTxt,
315 : const xub_StrLen nIndex, const xub_StrLen nLength )
316 : : SwTxtInfo( rNew ),
317 2264 : pKanaComp(((SwTxtSizeInfo&)rNew).GetpKanaComp()),
318 2264 : pVsh(((SwTxtSizeInfo&)rNew).GetVsh()),
319 2264 : pOut(((SwTxtSizeInfo&)rNew).GetOut()),
320 2264 : pRef(((SwTxtSizeInfo&)rNew).GetRefDev()),
321 2264 : pFnt(((SwTxtSizeInfo&)rNew).GetFont()),
322 2264 : pUnderFnt(((SwTxtSizeInfo&)rNew).GetUnderFnt()),
323 : pFrm( rNew.pFrm ),
324 2264 : pOpt(&rNew.GetOpt()),
325 : pTxt(&rTxt),
326 : nIdx(nIndex),
327 : nLen(nLength),
328 2264 : nKanaIdx( rNew.GetKanaIdx() ),
329 2264 : bOnWin( rNew.OnWin() ),
330 2264 : bNotEOL( rNew.NotEOL() ),
331 2264 : bURLNotify( rNew.URLNotify() ),
332 2264 : bStopUnderFlow( rNew.StopUnderFlow() ),
333 2264 : bFtnInside( rNew.IsFtnInside() ),
334 2264 : bOtherThanFtnInside( rNew.IsOtherThanFtnInside() ),
335 2264 : bMulti( rNew.IsMulti() ),
336 2264 : bFirstMulti( rNew.IsFirstMulti() ),
337 2264 : bRuby( rNew.IsRuby() ),
338 2264 : bHanging( rNew.IsHanging() ),
339 2264 : bScriptSpace( rNew.HasScriptSpace() ),
340 2264 : bForbiddenChars( rNew.HasForbiddenChars() ),
341 2264 : bSnapToGrid( rNew.SnapToGrid() ),
342 49808 : nDirection( rNew.GetDirection() )
343 : {
344 : #if OSL_DEBUG_LEVEL > 0
345 : ChkOutDev( *this );
346 : #endif
347 2264 : SetLen( GetMinLen( *this ) );
348 2264 : }
349 :
350 307 : void SwTxtSizeInfo::SelectFont()
351 : {
352 : // The path needs to go via ChgPhysFnt or the FontMetricCache gets confused.
353 : // In this case pLastMet has it's old value.
354 : // Wrong: GetOut()->SetFont( GetFont()->GetFnt() );
355 307 : GetFont()->Invalidate();
356 307 : GetFont()->ChgPhysFnt( pVsh, *GetOut() );
357 307 : }
358 :
359 0 : void SwTxtSizeInfo::NoteAnimation() const
360 : {
361 0 : if( OnWin() )
362 0 : SwRootFrm::FlushVout();
363 :
364 : OSL_ENSURE( pOut == pVsh->GetOut(),
365 : "SwTxtSizeInfo::NoteAnimation() changed pOut" );
366 0 : }
367 :
368 3 : SwPosSize SwTxtSizeInfo::GetTxtSize( OutputDevice* pOutDev,
369 : const SwScriptInfo* pSI,
370 : const XubString& rTxt,
371 : const xub_StrLen nIndex,
372 : const xub_StrLen nLength,
373 : const sal_uInt16 nComp ) const
374 : {
375 3 : SwDrawTextInfo aDrawInf( pVsh, *pOutDev, pSI, rTxt, nIndex, nLength );
376 3 : aDrawInf.SetFrm( pFrm );
377 3 : aDrawInf.SetFont( pFnt );
378 3 : aDrawInf.SetSnapToGrid( SnapToGrid() );
379 3 : aDrawInf.SetKanaComp( nComp );
380 3 : SwPosSize aSize = pFnt->_GetTxtSize( aDrawInf );
381 3 : return aSize;
382 : }
383 :
384 6 : SwPosSize SwTxtSizeInfo::GetTxtSize() const
385 : {
386 : const SwScriptInfo& rSI =
387 6 : ( (SwParaPortion*)GetParaPortion() )->GetScriptInfo();
388 :
389 : // in some cases, compression is not allowed or suppressed for
390 : // performance reasons
391 6 : sal_uInt16 nComp =( SW_CJK == GetFont()->GetActual() &&
392 0 : rSI.CountCompChg() &&
393 0 : ! IsMulti() ) ?
394 : GetKanaComp() :
395 6 : 0 ;
396 :
397 6 : SwDrawTextInfo aDrawInf( pVsh, *pOut, &rSI, *pTxt, nIdx, nLen );
398 6 : aDrawInf.SetFrm( pFrm );
399 6 : aDrawInf.SetFont( pFnt );
400 6 : aDrawInf.SetSnapToGrid( SnapToGrid() );
401 6 : aDrawInf.SetKanaComp( nComp );
402 6 : return pFnt->_GetTxtSize( aDrawInf );
403 : }
404 :
405 673 : void SwTxtSizeInfo::GetTxtSize( const SwScriptInfo* pSI, const xub_StrLen nIndex,
406 : const xub_StrLen nLength, const sal_uInt16 nComp,
407 : sal_uInt16& nMinSize, sal_uInt16& nMaxSizeDiff ) const
408 : {
409 673 : SwDrawTextInfo aDrawInf( pVsh, *pOut, pSI, *pTxt, nIndex, nLength );
410 673 : aDrawInf.SetFrm( pFrm );
411 673 : aDrawInf.SetFont( pFnt );
412 673 : aDrawInf.SetSnapToGrid( SnapToGrid() );
413 673 : aDrawInf.SetKanaComp( nComp );
414 673 : SwPosSize aSize = pFnt->_GetTxtSize( aDrawInf );
415 673 : nMaxSizeDiff = (sal_uInt16)aDrawInf.GetKanaDiff();
416 673 : nMinSize = aSize.Width();
417 673 : }
418 :
419 101 : xub_StrLen SwTxtSizeInfo::GetTxtBreak( const long nLineWidth,
420 : const xub_StrLen nMaxLen,
421 : const sal_uInt16 nComp ) const
422 : {
423 : const SwScriptInfo& rScriptInfo =
424 101 : ( (SwParaPortion*)GetParaPortion() )->GetScriptInfo();
425 :
426 : OSL_ENSURE( pRef == pOut, "GetTxtBreak is supposed to use the RefDev" );
427 : SwDrawTextInfo aDrawInf( pVsh, *pOut, &rScriptInfo,
428 101 : *pTxt, GetIdx(), nMaxLen );
429 101 : aDrawInf.SetFrm( pFrm );
430 101 : aDrawInf.SetFont( pFnt );
431 101 : aDrawInf.SetSnapToGrid( SnapToGrid() );
432 101 : aDrawInf.SetKanaComp( nComp );
433 101 : aDrawInf.SetHyphPos( 0 );
434 :
435 101 : return pFnt->GetTxtBreak( aDrawInf, nLineWidth );
436 : }
437 :
438 0 : xub_StrLen SwTxtSizeInfo::GetTxtBreak( const long nLineWidth,
439 : const xub_StrLen nMaxLen,
440 : const sal_uInt16 nComp,
441 : xub_StrLen& rExtraCharPos ) const
442 : {
443 : const SwScriptInfo& rScriptInfo =
444 0 : ( (SwParaPortion*)GetParaPortion() )->GetScriptInfo();
445 :
446 : OSL_ENSURE( pRef == pOut, "GetTxtBreak is supposed to use the RefDev" );
447 : SwDrawTextInfo aDrawInf( pVsh, *pOut, &rScriptInfo,
448 0 : *pTxt, GetIdx(), nMaxLen );
449 0 : aDrawInf.SetFrm( pFrm );
450 0 : aDrawInf.SetFont( pFnt );
451 0 : aDrawInf.SetSnapToGrid( SnapToGrid() );
452 0 : aDrawInf.SetKanaComp( nComp );
453 0 : aDrawInf.SetHyphPos( &rExtraCharPos );
454 :
455 0 : return pFnt->GetTxtBreak( aDrawInf, nLineWidth );
456 : }
457 :
458 1169 : void SwTxtPaintInfo::CtorInitTxtPaintInfo( SwTxtFrm *pFrame, const SwRect &rPaint )
459 : {
460 1169 : CtorInitTxtSizeInfo( pFrame );
461 1169 : aTxtFly.CtorInitTxtFly( pFrame ),
462 1169 : aPaintRect = rPaint;
463 1169 : nSpaceIdx = 0;
464 1169 : pSpaceAdd = NULL;
465 1169 : pWrongList = NULL;
466 1169 : pGrammarCheckList = NULL;
467 1169 : pSmartTags = NULL; // SMARTTAGS
468 :
469 : #if OSL_DEBUG_LEVEL > 1
470 : pBrushItem = ((SvxBrushItem*)-1);
471 : #else
472 1169 : pBrushItem = 0;
473 : #endif
474 1169 : }
475 :
476 0 : SwTxtPaintInfo::SwTxtPaintInfo( const SwTxtPaintInfo &rInf, const XubString &rTxt )
477 : : SwTxtSizeInfo( rInf, rTxt ),
478 0 : pWrongList( rInf.GetpWrongList() ),
479 0 : pGrammarCheckList( rInf.GetGrammarCheckList() ),
480 0 : pSmartTags( rInf.GetSmartTags() ), // SMARTTAGS
481 0 : pSpaceAdd( rInf.GetpSpaceAdd() ),
482 0 : pBrushItem( rInf.GetBrushItem() ),
483 0 : aTxtFly( *rInf.GetTxtFly() ),
484 0 : aPos( rInf.GetPos() ),
485 0 : aPaintRect( rInf.GetPaintRect() ),
486 0 : nSpaceIdx( rInf.GetSpaceIdx() )
487 0 : { }
488 :
489 721 : SwTxtPaintInfo::SwTxtPaintInfo( const SwTxtPaintInfo &rInf )
490 : : SwTxtSizeInfo( rInf ),
491 721 : pWrongList( rInf.GetpWrongList() ),
492 721 : pGrammarCheckList( rInf.GetGrammarCheckList() ),
493 721 : pSmartTags( rInf.GetSmartTags() ), // SMARTTAGS
494 721 : pSpaceAdd( rInf.GetpSpaceAdd() ),
495 721 : pBrushItem( rInf.GetBrushItem() ),
496 721 : aTxtFly( *rInf.GetTxtFly() ),
497 721 : aPos( rInf.GetPos() ),
498 721 : aPaintRect( rInf.GetPaintRect() ),
499 6489 : nSpaceIdx( rInf.GetSpaceIdx() )
500 721 : { }
501 :
502 : extern Color aGlobalRetoucheColor;
503 :
504 : /*************************************************************************
505 : * lcl_IsDarkBackground
506 : *
507 : * Returns if the current background color is dark.
508 : *************************************************************************/
509 :
510 22 : static sal_Bool lcl_IsDarkBackground( const SwTxtPaintInfo& rInf )
511 : {
512 22 : const Color* pCol = rInf.GetFont()->GetBackColor();
513 22 : if( ! pCol || COL_TRANSPARENT == pCol->GetColor() )
514 : {
515 : const SvxBrushItem* pItem;
516 22 : SwRect aOrigBackRect;
517 :
518 : // Consider, that [GetBackgroundBrush(...)] can set <pCol>
519 : // See implementation in /core/layout/paintfrm.cxx
520 : // There is a background color, if there is a background brush and
521 : // its color is *not* "no fill"/"auto fill".
522 22 : if( rInf.GetTxtFrm()->GetBackgroundBrush( pItem, pCol, aOrigBackRect, sal_False ) )
523 : {
524 0 : if ( !pCol )
525 0 : pCol = &pItem->GetColor();
526 :
527 : // Determined color <pCol> can be <COL_TRANSPARENT>. Thus, check it.
528 0 : if ( pCol->GetColor() == COL_TRANSPARENT)
529 0 : pCol = NULL;
530 : }
531 : else
532 22 : pCol = NULL;
533 : }
534 :
535 :
536 22 : if( !pCol )
537 22 : pCol = &aGlobalRetoucheColor;
538 :
539 22 : return pCol->IsDark();
540 : }
541 :
542 : /*************************************************************************
543 : * SwTxtPaintInfo::_DrawText()
544 : *************************************************************************/
545 :
546 449 : void SwTxtPaintInfo::_DrawText( const XubString &rText, const SwLinePortion &rPor,
547 : const xub_StrLen nStart, const xub_StrLen nLength,
548 : const sal_Bool bKern, const sal_Bool bWrong,
549 : const sal_Bool bSmartTag,
550 : const sal_Bool bGrammarCheck ) // SMARTTAGS
551 : {
552 449 : if( !nLength )
553 : return;
554 :
555 449 : if( GetFont()->IsBlink() && OnWin() && rPor.Width() )
556 : {
557 : // check if accessibility options allow blinking portions:
558 0 : const ViewShell* pSh = GetTxtFrm()->getRootFrm()->GetCurrShell();
559 0 : if ( pSh && ! pSh->GetAccessibilityOptions()->IsStopAnimatedText() &&
560 0 : ! pSh->IsPreView() )
561 : {
562 0 : if( !pBlink )
563 0 : pBlink = new SwBlink();
564 :
565 0 : Point aPoint( aPos );
566 :
567 0 : if ( GetTxtFrm()->IsRightToLeft() )
568 0 : GetTxtFrm()->SwitchLTRtoRTL( aPoint );
569 :
570 0 : if ( TEXT_LAYOUT_BIDI_STRONG != GetOut()->GetLayoutMode() )
571 0 : aPoint.X() -= rPor.Width();
572 :
573 0 : if ( GetTxtFrm()->IsVertical() )
574 0 : GetTxtFrm()->SwitchHorizontalToVertical( aPoint );
575 :
576 0 : pBlink->Insert( aPoint, &rPor, GetTxtFrm(), pFnt->GetOrientation() );
577 :
578 0 : if( !pBlink->IsVisible() )
579 : return;
580 : }
581 : else
582 : {
583 0 : delete pBlink;
584 0 : pBlink = NULL;
585 : }
586 : }
587 :
588 : // The SwScriptInfo is useless if we are inside a field portion
589 449 : SwScriptInfo* pSI = 0;
590 449 : if ( ! rPor.InFldGrp() )
591 405 : pSI = &GetParaPortion()->GetScriptInfo();
592 :
593 : // in some cases, kana compression is not allowed or suppressed for
594 : // performance reasons
595 449 : sal_uInt16 nComp = 0;
596 449 : if ( ! IsMulti() )
597 449 : nComp = GetKanaComp();
598 :
599 449 : sal_Bool bCfgIsAutoGrammar = sal_False;
600 449 : SvtLinguConfig().GetProperty( UPN_IS_GRAMMAR_AUTO ) >>= bCfgIsAutoGrammar;
601 449 : const sal_Bool bBullet = OnWin() && GetOpt().IsBlank() && IsNoSymbol();
602 449 : const sal_Bool bTmpWrong = bWrong && OnWin() && GetOpt().IsOnlineSpell();
603 449 : const sal_Bool bTmpGrammarCheck = bGrammarCheck && OnWin() && bCfgIsAutoGrammar && GetOpt().IsOnlineSpell();
604 449 : const sal_Bool bTmpSmart = bSmartTag && OnWin() && !GetOpt().IsPagePreview() && SwSmartTagMgr::Get().IsSmartTagsEnabled(); // SMARTTAGS
605 :
606 : OSL_ENSURE( GetParaPortion(), "No paragraph!");
607 : SwDrawTextInfo aDrawInf( pFrm->getRootFrm()->GetCurrShell(), *pOut, pSI, rText, nStart, nLength,
608 449 : rPor.Width(), bBullet );
609 :
610 449 : aDrawInf.SetLeft( GetPaintRect().Left() );
611 449 : aDrawInf.SetRight( GetPaintRect().Right() );
612 449 : aDrawInf.SetUnderFnt( pUnderFnt );
613 :
614 890 : const long nSpaceAdd = ( rPor.IsBlankPortion() || rPor.IsDropPortion() ||
615 890 : rPor.InNumberGrp() ) ? 0 : GetSpaceAdd();
616 449 : if ( nSpaceAdd )
617 : {
618 : xub_StrLen nCharCnt;
619 : // #i41860# Thai justified alignment needs some
620 : // additional information:
621 4 : aDrawInf.SetNumberOfBlanks( rPor.InTxtGrp() ?
622 4 : static_cast<const SwTxtPortion&>(rPor).GetSpaceCnt( *this, nCharCnt ) :
623 8 : 0 );
624 : }
625 :
626 449 : aDrawInf.SetSpace( nSpaceAdd );
627 449 : aDrawInf.SetKanaComp( nComp );
628 :
629 : // the font is used to identify the current script via nActual
630 449 : aDrawInf.SetFont( pFnt );
631 : // the frame is used to identify the orientation
632 449 : aDrawInf.SetFrm( GetTxtFrm() );
633 : // we have to know if the paragraph should snap to grid
634 449 : aDrawInf.SetSnapToGrid( SnapToGrid() );
635 : // for underlining we must know when not to add extra space behind
636 : // a character in justified mode
637 449 : aDrawInf.SetSpaceStop( ! rPor.GetPortion() ||
638 135 : rPor.GetPortion()->InFixMargGrp() ||
639 584 : rPor.GetPortion()->IsHolePortion() );
640 :
641 449 : if( GetTxtFly()->IsOn() )
642 : {
643 : // aPos needs to be the TopLeft, because we cannot calculate the
644 : // ClipRects otherwise
645 0 : const Point aPoint( aPos.X(), aPos.Y() - rPor.GetAscent() );
646 0 : const Size aSize( rPor.Width(), rPor.Height() );
647 0 : aDrawInf.SetPos( aPoint );
648 0 : aDrawInf.SetSize( aSize );
649 0 : aDrawInf.SetAscent( rPor.GetAscent() );
650 0 : aDrawInf.SetKern( bKern ? rPor.Width() : 0 );
651 0 : aDrawInf.SetWrong( bTmpWrong ? pWrongList : NULL );
652 0 : aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? pGrammarCheckList : NULL );
653 0 : aDrawInf.SetSmartTags( bTmpSmart ? pSmartTags : NULL ); // SMARTTAGS
654 0 : GetTxtFly()->DrawTextOpaque( aDrawInf );
655 : }
656 : else
657 : {
658 449 : aDrawInf.SetPos( aPos );
659 449 : if( bKern )
660 0 : pFnt->_DrawStretchText( aDrawInf );
661 : else
662 : {
663 449 : aDrawInf.SetWrong( bTmpWrong ? pWrongList : NULL );
664 449 : aDrawInf.SetGrammarCheck( bTmpGrammarCheck ? pGrammarCheckList : NULL );
665 449 : aDrawInf.SetSmartTags( bTmpSmart ? pSmartTags : NULL ); // SMARTTAGS
666 449 : pFnt->_DrawText( aDrawInf );
667 : }
668 : }
669 : }
670 :
671 527 : void SwTxtPaintInfo::CalcRect( const SwLinePortion& rPor,
672 : SwRect* pRect, SwRect* pIntersect ) const
673 : {
674 527 : Size aSize( rPor.Width(), rPor.Height() );
675 527 : if( rPor.IsHangingPortion() )
676 0 : aSize.Width() = ((SwHangingPortion&)rPor).GetInnerWidth();
677 527 : if( rPor.InSpaceGrp() && GetSpaceAdd() )
678 : {
679 4 : SwTwips nAdd = rPor.CalcSpacing( GetSpaceAdd(), *this );
680 4 : if( rPor.InFldGrp() && GetSpaceAdd() < 0 && nAdd )
681 0 : nAdd += GetSpaceAdd() / SPACING_PRECISION_FACTOR;
682 4 : aSize.Width() += nAdd;
683 : }
684 :
685 527 : Point aPoint;
686 :
687 527 : if( IsRotated() )
688 : {
689 0 : long nTmp = aSize.Width();
690 0 : aSize.Width() = aSize.Height();
691 0 : aSize.Height() = nTmp;
692 0 : if ( 1 == GetDirection() )
693 : {
694 0 : aPoint.A() = X() - rPor.GetAscent();
695 0 : aPoint.B() = Y() - aSize.Height();
696 : }
697 : else
698 : {
699 0 : aPoint.A() = X() - rPor.Height() + rPor.GetAscent();
700 0 : aPoint.B() = Y();
701 : }
702 : }
703 : else
704 : {
705 527 : aPoint.A() = X();
706 : //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
707 527 : if ( GetTxtFrm()->IsVertLR() )
708 0 : aPoint.B() = Y() - rPor.Height() + rPor.GetAscent();
709 : else
710 527 : aPoint.B() = Y() - rPor.GetAscent();
711 : }
712 :
713 : // Adjust x coordinate if we are inside a bidi portion
714 527 : const sal_Bool bFrmDir = GetTxtFrm()->IsRightToLeft();
715 527 : bool bCounterDir = ( ! bFrmDir && DIR_RIGHT2LEFT == GetDirection() ) ||
716 1054 : ( bFrmDir && DIR_LEFT2RIGHT == GetDirection() );
717 :
718 527 : if ( bCounterDir )
719 2 : aPoint.A() -= aSize.Width();
720 :
721 527 : SwRect aRect( aPoint, aSize );
722 :
723 527 : if ( GetTxtFrm()->IsRightToLeft() )
724 0 : GetTxtFrm()->SwitchLTRtoRTL( aRect );
725 :
726 527 : if ( GetTxtFrm()->IsVertical() )
727 0 : GetTxtFrm()->SwitchHorizontalToVertical( aRect );
728 :
729 527 : if ( pRect )
730 497 : *pRect = aRect;
731 :
732 527 : if( aRect.HasArea() && pIntersect )
733 : {
734 30 : ::SwAlignRect( aRect, (ViewShell*)GetVsh() );
735 :
736 30 : if ( GetOut()->IsClipRegion() )
737 : {
738 2 : SwRect aClip( GetOut()->GetClipRegion().GetBoundRect() );
739 2 : aRect.Intersection( aClip );
740 : }
741 :
742 30 : *pIntersect = aRect;
743 : }
744 527 : }
745 :
746 : /*************************************************************************
747 : * lcl_DrawSpecial
748 : *
749 : * Draws a special portion, e.g., line break portion, tab portion.
750 : * rPor - The portion
751 : * rRect - The rectangle surrounding the character
752 : * pCol - Specify a color for the character
753 : * bCenter - Draw the character centered, otherwise left aligned
754 : * bRotate - Rotate the character if character rotation is set
755 : *************************************************************************/
756 :
757 0 : static void lcl_DrawSpecial( const SwTxtPaintInfo& rInf, const SwLinePortion& rPor,
758 : SwRect& rRect, const Color* pCol, sal_Unicode cChar,
759 : sal_uInt8 nOptions )
760 : {
761 0 : bool bCenter = 0 != ( nOptions & DRAW_SPECIAL_OPTIONS_CENTER );
762 0 : bool bRotate = 0 != ( nOptions & DRAW_SPECIAL_OPTIONS_ROTATE );
763 :
764 : // rRect is given in absolute coordinates
765 0 : if ( rInf.GetTxtFrm()->IsRightToLeft() )
766 0 : rInf.GetTxtFrm()->SwitchRTLtoLTR( rRect );
767 0 : if ( rInf.GetTxtFrm()->IsVertical() )
768 0 : rInf.GetTxtFrm()->SwitchVerticalToHorizontal( rRect );
769 :
770 0 : const SwFont* pOldFnt = rInf.GetFont();
771 :
772 : // Font is generated only once:
773 : static SwFont* pFnt = 0;
774 0 : if ( ! pFnt )
775 : {
776 0 : pFnt = new SwFont( *pOldFnt );
777 0 : pFnt->SetFamily( FAMILY_DONTKNOW, pFnt->GetActual() );
778 0 : pFnt->SetName( numfunc::GetDefBulletFontname(), pFnt->GetActual() );
779 0 : pFnt->SetStyleName( aEmptyStr, pFnt->GetActual() );
780 0 : pFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, pFnt->GetActual() );
781 : }
782 :
783 : // Some of the current values are set at the font:
784 0 : if ( ! bRotate )
785 0 : pFnt->SetVertical( 0, rInf.GetTxtFrm()->IsVertical() );
786 : else
787 0 : pFnt->SetVertical( pOldFnt->GetOrientation() );
788 :
789 0 : if ( pCol )
790 0 : pFnt->SetColor( *pCol );
791 : else
792 0 : pFnt->SetColor( pOldFnt->GetColor() );
793 :
794 0 : Size aFontSize( 0, SPECIAL_FONT_HEIGHT );
795 0 : pFnt->SetSize( aFontSize, pFnt->GetActual() );
796 :
797 0 : ((SwTxtPaintInfo&)rInf).SetFont( pFnt );
798 :
799 : // The maximum width depends on the current orientation
800 0 : const sal_uInt16 nDir = pFnt->GetOrientation( rInf.GetTxtFrm()->IsVertical() );
801 0 : SwTwips nMaxWidth = 0;
802 0 : switch ( nDir )
803 : {
804 : case 0 :
805 0 : nMaxWidth = rRect.Width();
806 0 : break;
807 : case 900 :
808 : case 2700 :
809 0 : nMaxWidth = rRect.Height();
810 0 : break;
811 : default:
812 : OSL_FAIL( "Unknown direction set at font" );
813 0 : break;
814 : }
815 :
816 : // check if char fits into rectangle
817 0 : const OUString aTmp( cChar );
818 0 : aFontSize = rInf.GetTxtSize( aTmp ).SvLSize();
819 0 : while ( aFontSize.Width() > nMaxWidth )
820 : {
821 0 : SwTwips nFactor = ( 100 * aFontSize.Width() ) / nMaxWidth;
822 0 : const SwTwips nOldWidth = aFontSize.Width();
823 :
824 : // new height for font
825 0 : const sal_uInt8 nAct = pFnt->GetActual();
826 0 : aFontSize.Height() = ( 100 * pFnt->GetSize( nAct ).Height() ) / nFactor;
827 0 : aFontSize.Width() = ( 100 * pFnt->GetSize( nAct).Width() ) / nFactor;
828 :
829 0 : if ( !aFontSize.Width() && !aFontSize.Height() )
830 0 : break;
831 :
832 0 : pFnt->SetSize( aFontSize, nAct );
833 :
834 0 : aFontSize = rInf.GetTxtSize( aTmp ).SvLSize();
835 :
836 0 : if ( aFontSize.Width() >= nOldWidth )
837 0 : break;
838 : }
839 :
840 0 : const Point aOldPos( rInf.GetPos() );
841 :
842 : // adjust values so that tab is vertically and horizontally centered
843 0 : SwTwips nX = rRect.Left();
844 0 : SwTwips nY = rRect.Top();
845 0 : switch ( nDir )
846 : {
847 : case 0 :
848 0 : if ( bCenter )
849 0 : nX += ( rRect.Width() - aFontSize.Width() ) / 2;
850 0 : nY += ( rRect.Height() - aFontSize.Height() ) / 2 + rInf.GetAscent();
851 0 : break;
852 : case 900 :
853 0 : if ( bCenter )
854 0 : nX += ( rRect.Width() - aFontSize.Height() ) / 2 + rInf.GetAscent();
855 0 : nY += ( rRect.Height() + aFontSize.Width() ) / 2;
856 0 : break;
857 : case 2700 :
858 0 : if ( bCenter )
859 0 : nX += ( rRect.Width() + aFontSize.Height() ) / 2 - rInf.GetAscent();
860 0 : nY += ( rRect.Height() - aFontSize.Width() ) / 2;
861 0 : break;
862 : }
863 :
864 0 : Point aTmpPos( nX, nY );
865 0 : ((SwTxtPaintInfo&)rInf).SetPos( aTmpPos );
866 0 : sal_uInt16 nOldWidth = rPor.Width();
867 0 : ((SwLinePortion&)rPor).Width( (sal_uInt16)aFontSize.Width() );
868 0 : rInf.DrawText( aTmp, rPor );
869 0 : ((SwLinePortion&)rPor).Width( nOldWidth );
870 0 : ((SwTxtPaintInfo&)rInf).SetFont( (SwFont*)pOldFnt );
871 0 : ((SwTxtPaintInfo&)rInf).SetPos( aOldPos );
872 0 : }
873 :
874 28 : void SwTxtPaintInfo::DrawRect( const SwRect &rRect, sal_Bool bNoGraphic,
875 : sal_Bool bRetouche ) const
876 : {
877 28 : if ( OnWin() || !bRetouche )
878 : {
879 28 : if( aTxtFly.IsOn() )
880 : ((SwTxtPaintInfo*)this)->GetTxtFly()->
881 0 : DrawFlyRect( pOut, rRect, *this, bNoGraphic );
882 28 : else if ( bNoGraphic )
883 28 : pOut->DrawRect( rRect.SVRect() );
884 : else
885 : {
886 : OSL_ENSURE( ((SvxBrushItem*)-1) != pBrushItem, "DrawRect: Uninitialized BrushItem!" );
887 0 : ::DrawGraphic( pBrushItem, pOut, aItemRect, rRect );
888 : }
889 : }
890 28 : }
891 :
892 0 : void SwTxtPaintInfo::DrawTab( const SwLinePortion &rPor ) const
893 : {
894 0 : if( OnWin() )
895 : {
896 0 : SwRect aRect;
897 0 : CalcRect( rPor, &aRect );
898 :
899 0 : if ( ! aRect.HasArea() )
900 0 : return;
901 :
902 0 : const sal_Unicode cChar = GetTxtFrm()->IsRightToLeft() ?
903 0 : CHAR_TAB_RTL : CHAR_TAB;
904 : const sal_uInt8 nOptions = DRAW_SPECIAL_OPTIONS_CENTER |
905 0 : DRAW_SPECIAL_OPTIONS_ROTATE;
906 0 : lcl_DrawSpecial( *this, rPor, aRect, 0, cChar, nOptions );
907 : }
908 : }
909 :
910 0 : void SwTxtPaintInfo::DrawLineBreak( const SwLinePortion &rPor ) const
911 : {
912 0 : if( OnWin() )
913 : {
914 0 : KSHORT nOldWidth = rPor.Width();
915 0 : ((SwLinePortion&)rPor).Width( LINE_BREAK_WIDTH );
916 :
917 0 : SwRect aRect;
918 0 : CalcRect( rPor, &aRect );
919 :
920 0 : if( aRect.HasArea() )
921 : {
922 0 : const sal_Unicode cChar = GetTxtFrm()->IsRightToLeft() ?
923 0 : CHAR_LINEBREAK_RTL : CHAR_LINEBREAK;
924 0 : const sal_uInt8 nOptions = 0;
925 0 : lcl_DrawSpecial( *this, rPor, aRect, 0, cChar, nOptions );
926 : }
927 :
928 0 : ((SwLinePortion&)rPor).Width( nOldWidth );
929 : }
930 0 : }
931 :
932 0 : void SwTxtPaintInfo::DrawRedArrow( const SwLinePortion &rPor ) const
933 : {
934 0 : Size aSize( SPECIAL_FONT_HEIGHT, SPECIAL_FONT_HEIGHT );
935 0 : SwRect aRect( ((SwArrowPortion&)rPor).GetPos(), aSize );
936 : sal_Unicode cChar;
937 0 : if( ((SwArrowPortion&)rPor).IsLeft() )
938 : {
939 0 : aRect.Pos().Y() += 20 - GetAscent();
940 0 : aRect.Pos().X() += 20;
941 0 : if( aSize.Height() > rPor.Height() )
942 0 : aRect.Height( rPor.Height() );
943 0 : cChar = CHAR_LEFT_ARROW;
944 : }
945 : else
946 : {
947 0 : if( aSize.Height() > rPor.Height() )
948 0 : aRect.Height( rPor.Height() );
949 0 : aRect.Pos().Y() -= aRect.Height() + 20;
950 0 : aRect.Pos().X() -= aRect.Width() + 20;
951 0 : cChar = CHAR_RIGHT_ARROW;
952 : }
953 :
954 0 : if ( GetTxtFrm()->IsVertical() )
955 0 : GetTxtFrm()->SwitchHorizontalToVertical( aRect );
956 :
957 0 : Color aCol( COL_LIGHTRED );
958 :
959 0 : if( aRect.HasArea() )
960 : {
961 0 : const sal_uInt8 nOptions = 0;
962 0 : lcl_DrawSpecial( *this, rPor, aRect, &aCol, cChar, nOptions );
963 : }
964 0 : }
965 :
966 3 : void SwTxtPaintInfo::DrawPostIts( const SwLinePortion&, sal_Bool bScript ) const
967 : {
968 3 : if( OnWin() && pOpt->IsPostIts() )
969 : {
970 3 : Size aSize;
971 3 : Point aTmp;
972 :
973 3 : const sal_uInt16 nPostItsWidth = pOpt->GetPostItsWidth( GetOut() );
974 3 : const sal_uInt16 nFontHeight = pFnt->GetHeight( pVsh, *GetOut() );
975 3 : const sal_uInt16 nFontAscent = pFnt->GetAscent( pVsh, *GetOut() );
976 :
977 3 : switch ( pFnt->GetOrientation( GetTxtFrm()->IsVertical() ) )
978 : {
979 : case 0 :
980 3 : aSize.Width() = nPostItsWidth;
981 3 : aSize.Height() = nFontHeight;
982 3 : aTmp.X() = aPos.X();
983 3 : aTmp.Y() = aPos.Y() - nFontAscent;
984 3 : break;
985 : case 900 :
986 0 : aSize.Height() = nPostItsWidth;
987 0 : aSize.Width() = nFontHeight;
988 0 : aTmp.X() = aPos.X() - nFontAscent;
989 0 : aTmp.Y() = aPos.Y();
990 0 : break;
991 : case 2700 :
992 0 : aSize.Height() = nPostItsWidth;
993 0 : aSize.Width() = nFontHeight;
994 0 : aTmp.X() = aPos.X() - nFontHeight +
995 0 : nFontAscent;
996 0 : aTmp.Y() = aPos.Y();
997 0 : break;
998 : }
999 :
1000 3 : SwRect aTmpRect( aTmp, aSize );
1001 :
1002 3 : if ( GetTxtFrm()->IsRightToLeft() )
1003 0 : GetTxtFrm()->SwitchLTRtoRTL( aTmpRect );
1004 :
1005 3 : if ( GetTxtFrm()->IsVertical() )
1006 0 : GetTxtFrm()->SwitchHorizontalToVertical( aTmpRect );
1007 :
1008 3 : const Rectangle aRect( aTmpRect.SVRect() );
1009 3 : pOpt->PaintPostIts( (OutputDevice*)GetOut(), aRect, bScript );
1010 : }
1011 3 : }
1012 :
1013 0 : void SwTxtPaintInfo::DrawCheckBox( const SwFieldFormPortion &rPor, bool checked) const
1014 : {
1015 0 : SwRect aIntersect;
1016 0 : CalcRect( rPor, &aIntersect, 0 );
1017 0 : if ( aIntersect.HasArea() )
1018 : {
1019 0 : if (OnWin() && SwViewOption::IsFieldShadings() &&
1020 0 : !GetOpt().IsPagePreview())
1021 : {
1022 0 : OutputDevice* pOut_ = (OutputDevice*)GetOut();
1023 0 : pOut_->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
1024 0 : pOut_->SetFillColor( SwViewOption::GetFieldShadingsColor() );
1025 0 : pOut_->SetLineColor();
1026 0 : pOut_->DrawRect( aIntersect.SVRect() );
1027 0 : pOut_->Pop();
1028 : }
1029 0 : const int delta=10;
1030 0 : Rectangle r(aIntersect.Left()+delta, aIntersect.Top()+delta, aIntersect.Right()-delta, aIntersect.Bottom()-delta);
1031 0 : pOut->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
1032 0 : pOut->SetLineColor( Color(0, 0, 0));
1033 0 : pOut->SetFillColor();
1034 0 : pOut->DrawRect( r );
1035 0 : if (checked) {
1036 0 : pOut->DrawLine(r.TopLeft(), r.BottomRight());
1037 0 : pOut->DrawLine(r.TopRight(), r.BottomLeft());
1038 : }
1039 0 : pOut->Pop();
1040 : }
1041 0 : }
1042 :
1043 24 : void SwTxtPaintInfo::DrawBackground( const SwLinePortion &rPor ) const
1044 : {
1045 : OSL_ENSURE( OnWin(), "SwTxtPaintInfo::DrawBackground: printer pollution ?" );
1046 :
1047 24 : SwRect aIntersect;
1048 24 : CalcRect( rPor, 0, &aIntersect );
1049 :
1050 24 : if ( aIntersect.HasArea() )
1051 : {
1052 22 : OutputDevice* pTmpOut = (OutputDevice*)GetOut();
1053 22 : pTmpOut->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
1054 :
1055 : // For dark background we do not want to have a filled rectangle
1056 22 : if ( GetVsh() && GetVsh()->GetWin() && lcl_IsDarkBackground( *this ) )
1057 : {
1058 0 : pTmpOut->SetLineColor( SwViewOption::GetFontColor().GetColor() );
1059 : }
1060 : else
1061 : {
1062 22 : pTmpOut->SetFillColor( SwViewOption::GetFieldShadingsColor() );
1063 22 : pTmpOut->SetLineColor();
1064 : }
1065 :
1066 22 : DrawRect( aIntersect, sal_True );
1067 22 : pTmpOut->Pop();
1068 : }
1069 24 : }
1070 :
1071 497 : void SwTxtPaintInfo::_DrawBackBrush( const SwLinePortion &rPor ) const
1072 : {
1073 : {
1074 497 : SwRect aIntersect;
1075 497 : CalcRect( rPor, &aIntersect, 0 );
1076 497 : if(aIntersect.HasArea())
1077 : {
1078 497 : SwTxtNode *pNd = pFrm->GetTxtNode();
1079 497 : const ::sw::mark::IFieldmark* pFieldmark = NULL;
1080 497 : if(pNd)
1081 : {
1082 497 : const SwDoc *doc=pNd->GetDoc();
1083 497 : if(doc)
1084 : {
1085 497 : SwIndex aIndex(pNd, GetIdx());
1086 497 : SwPosition aPosition(*pNd, aIndex);
1087 497 : pFieldmark=doc->getIDocumentMarkAccess()->getFieldmarkFor(aPosition);
1088 : }
1089 : }
1090 497 : bool bIsStartMark=(1==GetLen() && CH_TXT_ATR_FIELDSTART==GetTxt().GetChar(GetIdx()));
1091 : if(pFieldmark) {
1092 : OSL_TRACE("Found Fieldmark");
1093 : #if OSL_DEBUG_LEVEL > 1
1094 : OUString str = pFieldmark->ToString( );
1095 : fprintf( stderr, "%s\n", rtl::OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr( ) );
1096 : #endif
1097 : }
1098 : if(bIsStartMark) OSL_TRACE("Found StartMark");
1099 503 : if (OnWin() && (pFieldmark!=NULL || bIsStartMark) &&
1100 3 : SwViewOption::IsFieldShadings() &&
1101 3 : !GetOpt().IsPagePreview())
1102 : {
1103 3 : OutputDevice* pOutDev = (OutputDevice*)GetOut();
1104 3 : pOutDev->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
1105 3 : bool bFilled = false;
1106 : // If this is a comment range, need to look up the color of the comment author.
1107 3 : if (pFieldmark->GetFieldname() == ODF_COMMENTRANGE)
1108 : {
1109 : // Search for the position of the postit field
1110 3 : const sal_Unicode fld[] = { CH_TXTATR_INWORD, 0 };
1111 3 : xub_StrLen nEndIdx = GetTxt().SearchChar(fld, GetIdx());
1112 3 : if (nEndIdx != STRING_NOTFOUND)
1113 : {
1114 3 : SwTxtAttr* pTxtAttr = pNd->GetTxtAttrForCharAt(nEndIdx, RES_TXTATR_FIELD);
1115 3 : const SwFmtFld& rPostItField = pTxtAttr->GetFld();
1116 : // Look up the author name
1117 3 : const OUString& rAuthor = rPostItField.GetFld()->GetPar1();
1118 3 : sal_uInt16 nIndex = pNd->GetDoc()->InsertRedlineAuthor(rAuthor);
1119 3 : pOutDev->SetFillColor( SwPostItMgr::GetColorLight(nIndex) );
1120 3 : pOutDev->SetLineColor( SwPostItMgr::GetColorAnchor(nIndex) );
1121 3 : bFilled = true;
1122 : }
1123 : }
1124 3 : if (!bFilled)
1125 : {
1126 0 : pOutDev->SetFillColor( SwViewOption::GetFieldShadingsColor() );
1127 0 : pOutDev->SetLineColor( );
1128 : }
1129 3 : pOutDev->DrawRect( aIntersect.SVRect() );
1130 3 : pOutDev->Pop();
1131 : }
1132 : }
1133 : }
1134 994 : if( !pFnt->GetBackColor() ) return;
1135 :
1136 : OSL_ENSURE( pFnt->GetBackColor(), "DrawBackBrush: Lost Color" );
1137 :
1138 6 : SwRect aIntersect;
1139 6 : CalcRect( rPor, 0, &aIntersect );
1140 :
1141 6 : if ( aIntersect.HasArea() )
1142 : {
1143 6 : OutputDevice* pTmpOut = (OutputDevice*)GetOut();
1144 :
1145 : // #i16816# tagged pdf support
1146 6 : SwTaggedPDFHelper aTaggedPDFHelper( 0, 0, 0, *pTmpOut );
1147 :
1148 6 : pTmpOut->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
1149 :
1150 6 : pTmpOut->SetFillColor( *pFnt->GetBackColor() );
1151 6 : pTmpOut->SetLineColor();
1152 :
1153 6 : DrawRect( aIntersect, sal_True, sal_False );
1154 :
1155 6 : pTmpOut->Pop();
1156 : }
1157 : }
1158 :
1159 56 : void SwTxtPaintInfo::DrawViewOpt( const SwLinePortion &rPor,
1160 : const MSHORT nWhich ) const
1161 : {
1162 56 : if( OnWin() && !IsMulti() )
1163 : {
1164 56 : bool bDraw = false;
1165 56 : switch( nWhich )
1166 : {
1167 : case POR_FTN:
1168 : case POR_QUOVADIS:
1169 : case POR_NUMBER:
1170 : case POR_FLD:
1171 : case POR_URL:
1172 : case POR_HIDDEN:
1173 : case POR_TOX:
1174 : case POR_REF:
1175 : case POR_META:
1176 : case POR_CONTROLCHAR:
1177 164 : if ( !GetOpt().IsPagePreview() &&
1178 44 : !GetOpt().IsReadonly() &&
1179 44 : SwViewOption::IsFieldShadings() &&
1180 : (POR_NUMBER != nWhich ||
1181 32 : pFrm->GetTxtNode()->HasMarkedLabel())) // #i27615#
1182 12 : bDraw = true;
1183 44 : break;
1184 0 : case POR_TAB: if ( GetOpt().IsTab() ) bDraw = true; break;
1185 4 : case POR_SOFTHYPH: if ( GetOpt().IsSoftHyph() )bDraw = true; break;
1186 8 : case POR_BLANK: if ( GetOpt().IsHardBlank())bDraw = true; break;
1187 : default:
1188 : {
1189 : OSL_ENSURE( !this, "SwTxtPaintInfo::DrawViewOpt: don't know how to draw this" );
1190 0 : break;
1191 : }
1192 : }
1193 56 : if ( bDraw )
1194 24 : DrawBackground( rPor );
1195 : }
1196 56 : }
1197 :
1198 0 : void SwTxtPaintInfo::_NotifyURL( const SwLinePortion &rPor ) const
1199 : {
1200 : OSL_ENSURE( pNoteURL, "NotifyURL: pNoteURL gone with the wind!" );
1201 :
1202 0 : SwRect aIntersect;
1203 0 : CalcRect( rPor, 0, &aIntersect );
1204 :
1205 0 : if( aIntersect.HasArea() )
1206 : {
1207 0 : SwTxtNode *pNd = (SwTxtNode*)GetTxtFrm()->GetTxtNode();
1208 : SwTxtAttr *const pAttr =
1209 0 : pNd->GetTxtAttrAt(GetIdx(), RES_TXTATR_INETFMT);
1210 0 : if( pAttr )
1211 : {
1212 0 : const SwFmtINetFmt& rFmt = pAttr->GetINetFmt();
1213 0 : pNoteURL->InsertURLNote( rFmt.GetValue(), rFmt.GetTargetFrame(),
1214 0 : aIntersect );
1215 : }
1216 : }
1217 0 : }
1218 :
1219 2 : static void lcl_InitHyphValues( PropertyValues &rVals,
1220 : sal_Int16 nMinLeading, sal_Int16 nMinTrailing )
1221 : {
1222 2 : sal_Int32 nLen = rVals.getLength();
1223 :
1224 2 : if (0 == nLen) // yet to be initialized?
1225 : {
1226 2 : rVals.realloc( 2 );
1227 2 : PropertyValue *pVal = rVals.getArray();
1228 :
1229 2 : pVal[0].Name = UPN_HYPH_MIN_LEADING;
1230 2 : pVal[0].Handle = UPH_HYPH_MIN_LEADING;
1231 2 : pVal[0].Value <<= nMinLeading;
1232 :
1233 2 : pVal[1].Name = UPN_HYPH_MIN_TRAILING;
1234 2 : pVal[1].Handle = UPH_HYPH_MIN_TRAILING;
1235 2 : pVal[1].Value <<= nMinTrailing;
1236 : }
1237 0 : else if (2 == nLen) // already initialized once?
1238 : {
1239 0 : PropertyValue *pVal = rVals.getArray();
1240 0 : pVal[0].Value <<= nMinLeading;
1241 0 : pVal[1].Value <<= nMinTrailing;
1242 : }
1243 : else {
1244 : OSL_FAIL( "unexpected size of sequence" );
1245 : }
1246 2 : }
1247 :
1248 0 : const PropertyValues & SwTxtFormatInfo::GetHyphValues() const
1249 : {
1250 : OSL_ENSURE( 2 == aHyphVals.getLength(),
1251 : "hyphenation values not yet initialized" );
1252 0 : return aHyphVals;
1253 : }
1254 :
1255 692 : sal_Bool SwTxtFormatInfo::InitHyph( const sal_Bool bAutoHyphen )
1256 : {
1257 692 : const SwAttrSet& rAttrSet = GetTxtFrm()->GetTxtNode()->GetSwAttrSet();
1258 692 : SetHanging( rAttrSet.GetHangingPunctuation().GetValue() );
1259 692 : SetScriptSpace( rAttrSet.GetScriptSpace().GetValue() );
1260 692 : SetForbiddenChars( rAttrSet.GetForbiddenRule().GetValue() );
1261 692 : const SvxHyphenZoneItem &rAttr = rAttrSet.GetHyphenZone();
1262 692 : MaxHyph() = rAttr.GetMaxHyphens();
1263 692 : sal_Bool bAuto = bAutoHyphen || rAttr.IsHyphen();
1264 692 : if( bAuto || bInterHyph )
1265 : {
1266 2 : nHyphStart = nHyphWrdStart = STRING_LEN;
1267 2 : nHyphWrdLen = 0;
1268 :
1269 2 : const sal_Int16 nMinimalLeading = Max(rAttr.GetMinLead(), sal_uInt8(2));
1270 2 : const sal_Int16 nMinimalTrailing = rAttr.GetMinTrail();
1271 2 : lcl_InitHyphValues( aHyphVals, nMinimalLeading, nMinimalTrailing);
1272 : }
1273 692 : return bAuto;
1274 : }
1275 :
1276 692 : void SwTxtFormatInfo::CtorInitTxtFormatInfo( SwTxtFrm *pNewFrm, const sal_Bool bNewInterHyph,
1277 : const sal_Bool bNewQuick, const sal_Bool bTst )
1278 : {
1279 692 : CtorInitTxtPaintInfo( pNewFrm, SwRect() );
1280 :
1281 692 : bQuick = bNewQuick;
1282 692 : bInterHyph = bNewInterHyph;
1283 :
1284 : //! needs to be done in this order
1285 692 : nMinLeading = 2;
1286 692 : nMinTrailing = 2;
1287 692 : nMinWordLength = 0;
1288 692 : bAutoHyph = InitHyph();
1289 :
1290 692 : bIgnoreFly = sal_False;
1291 692 : bFakeLineStart = sal_False;
1292 692 : bShift = sal_False;
1293 692 : bDropInit = sal_False;
1294 692 : bTestFormat = bTst;
1295 692 : nLeft = 0;
1296 692 : nRight = 0;
1297 692 : nFirst = 0;
1298 692 : nRealWidth = 0;
1299 692 : nForcedLeftMargin = 0;
1300 692 : pRest = 0;
1301 692 : nLineHeight = 0;
1302 692 : nLineNettoHeight = 0;
1303 692 : SetLineStart(0);
1304 692 : Init();
1305 692 : }
1306 :
1307 : /*************************************************************************
1308 : * SwTxtFormatInfo::IsHyphenate()
1309 : * If the Hyphenator returns ERROR or the language is set to NOLANGUAGE
1310 : * we do not hyphenate.
1311 : * Else, we always hyphenate if we do interactive hyphenation.
1312 : * If we do not do interactive hyphenation, we only hyphenate if ParaFmt is
1313 : * set to automatic hyphenation.
1314 : *************************************************************************/
1315 101 : sal_Bool SwTxtFormatInfo::IsHyphenate() const
1316 : {
1317 101 : if( !bInterHyph && !bAutoHyph )
1318 101 : return sal_False;
1319 :
1320 0 : LanguageType eTmp = GetFont()->GetLanguage();
1321 0 : if( LANGUAGE_DONTKNOW == eTmp || LANGUAGE_NONE == eTmp )
1322 0 : return sal_False;
1323 :
1324 0 : uno::Reference< XHyphenator > xHyph = ::GetHyphenator();
1325 0 : if (bInterHyph && xHyph.is())
1326 0 : SvxSpellWrapper::CheckHyphLang( xHyph, eTmp );
1327 :
1328 0 : if( !xHyph.is() || !xHyph->hasLocale( pBreakIt->GetLocale(eTmp) ) )
1329 0 : return sal_False;
1330 0 : return sal_True;
1331 : }
1332 :
1333 : /*************************************************************************
1334 : * SwTxtFormatInfo::GetDropFmt()
1335 : * Dropcaps called by the SwTxtFormatter::CTOR
1336 : *************************************************************************/
1337 :
1338 692 : const SwFmtDrop *SwTxtFormatInfo::GetDropFmt() const
1339 : {
1340 692 : const SwFmtDrop *pDrop = &GetTxtFrm()->GetTxtNode()->GetSwAttrSet().GetDrop();
1341 692 : if( 1 >= pDrop->GetLines() ||
1342 0 : ( !pDrop->GetChars() && !pDrop->GetWholeWord() ) )
1343 692 : pDrop = 0;
1344 692 : return pDrop;
1345 : }
1346 :
1347 1447 : void SwTxtFormatInfo::Init()
1348 : {
1349 : // Not initialized: pRest, nLeft, nRight, nFirst, nRealWidth
1350 1447 : X(0);
1351 : bArrowDone = bFull = bFtnDone = bErgoDone = bNumDone = bNoEndHyph =
1352 1447 : bNoMidHyph = bStop = bNewLine = bUnderFlow = bTabOverflow = sal_False;
1353 :
1354 : // generally we do not allow number portions in follows, except...
1355 1447 : if ( GetTxtFrm()->IsFollow() )
1356 : {
1357 0 : const SwTxtFrm* pMaster = GetTxtFrm()->FindMaster();
1358 : OSL_ENSURE(pMaster, "pTxtFrm without Master");
1359 0 : const SwLinePortion* pTmpPara = pMaster ? pMaster->GetPara() : NULL;
1360 :
1361 : // there is a master for this follow and the master does not have
1362 : // any contents (especially it does not have a number portion)
1363 : bNumDone = ! pTmpPara ||
1364 0 : ! ((SwParaPortion*)pTmpPara)->GetFirstPortion()->IsFlyPortion();
1365 : }
1366 :
1367 1447 : pRoot = 0;
1368 1447 : pLast = 0;
1369 1447 : pFly = 0;
1370 1447 : pLastFld = 0;
1371 1447 : pLastTab = 0;
1372 1447 : pUnderFlow = 0;
1373 1447 : cTabDecimal = 0;
1374 1447 : nWidth = nRealWidth;
1375 1447 : nForcedLeftMargin = 0;
1376 1447 : nSoftHyphPos = 0;
1377 1447 : nUnderScorePos = STRING_LEN;
1378 1447 : cHookChar = 0;
1379 1447 : SetIdx(0);
1380 1447 : SetLen( GetTxt().Len() );
1381 1447 : SetPaintOfst(0);
1382 1447 : }
1383 :
1384 : /*--------------------------------------------------
1385 : * There are a few differences between a copy constructor
1386 : * and the following constructor for multi-line formatting.
1387 : * The root is the first line inside the multi-portion,
1388 : * the line start is the actual position in the text,
1389 : * the line width is the rest width from the surrounding line
1390 : * and the bMulti and bFirstMulti-flag has to be set correctly.
1391 : * --------------------------------------------------*/
1392 :
1393 1 : SwTxtFormatInfo::SwTxtFormatInfo( const SwTxtFormatInfo& rInf,
1394 : SwLineLayout& rLay, SwTwips nActWidth ) : SwTxtPaintInfo( rInf ),
1395 1 : bTabOverflow( sal_False )
1396 : {
1397 1 : pRoot = &rLay;
1398 1 : pLast = &rLay;
1399 1 : pFly = NULL;
1400 1 : pLastFld = NULL;
1401 1 : pUnderFlow = NULL;
1402 1 : pRest = NULL;
1403 1 : pLastTab = NULL;
1404 :
1405 1 : nSoftHyphPos = 0;
1406 1 : nUnderScorePos = STRING_LEN;
1407 1 : nHyphStart = 0;
1408 1 : nHyphWrdStart = 0;
1409 1 : nHyphWrdLen = 0;
1410 1 : nLineStart = rInf.GetIdx();
1411 1 : nLeft = rInf.nLeft;
1412 1 : nRight = rInf.nRight;
1413 1 : nFirst = rInf.nLeft;
1414 1 : nRealWidth = KSHORT(nActWidth);
1415 1 : nWidth = nRealWidth;
1416 1 : nLineHeight = 0;
1417 1 : nLineNettoHeight = 0;
1418 1 : nForcedLeftMargin = 0;
1419 :
1420 1 : nMinLeading = 0;
1421 1 : nMinTrailing = 0;
1422 1 : nMinWordLength = 0;
1423 1 : bFull = sal_False;
1424 1 : bFtnDone = sal_True;
1425 1 : bErgoDone = sal_True;
1426 1 : bNumDone = sal_True;
1427 1 : bArrowDone = sal_True;
1428 1 : bStop = sal_False;
1429 1 : bNewLine = sal_True;
1430 1 : bShift = sal_False;
1431 1 : bUnderFlow = sal_False;
1432 1 : bInterHyph = sal_False;
1433 1 : bAutoHyph = sal_False;
1434 1 : bDropInit = sal_False;
1435 1 : bQuick = rInf.bQuick;
1436 1 : bNoEndHyph = sal_False;
1437 1 : bNoMidHyph = sal_False;
1438 1 : bIgnoreFly = sal_False;
1439 1 : bFakeLineStart = sal_False;
1440 :
1441 1 : cTabDecimal = 0;
1442 1 : cHookChar = 0;
1443 1 : nMaxHyph = 0;
1444 1 : bTestFormat = rInf.bTestFormat;
1445 1 : SetMulti( sal_True );
1446 1 : SetFirstMulti( rInf.IsFirstMulti() );
1447 1 : }
1448 5 : sal_Bool SwTxtFormatInfo::_CheckFtnPortion( SwLineLayout* pCurr )
1449 : {
1450 5 : KSHORT nHeight = pCurr->GetRealHeight();
1451 5 : SwLinePortion *pPor = pCurr->GetPortion();
1452 5 : sal_Bool bRet = sal_False;
1453 22 : while( pPor )
1454 : {
1455 12 : if( pPor->IsFtnPortion() && nHeight > ((SwFtnPortion*)pPor)->Orig() )
1456 : {
1457 0 : bRet = sal_True;
1458 0 : SetLineHeight( nHeight );
1459 0 : SetLineNettoHeight( pCurr->Height() );
1460 0 : break;
1461 : }
1462 12 : pPor = pPor->GetPortion();
1463 : }
1464 5 : return bRet;
1465 : }
1466 :
1467 682 : xub_StrLen SwTxtFormatInfo::ScanPortionEnd( const xub_StrLen nStart,
1468 : const xub_StrLen nEnd )
1469 : {
1470 682 : cHookChar = 0;
1471 682 : xub_StrLen i = nStart;
1472 :
1473 : //
1474 : // Used for decimal tab handling:
1475 : //
1476 682 : const sal_Unicode cTabDec = GetLastTab() ? (sal_Unicode)GetTabDecimal() : 0;
1477 682 : const sal_Unicode cThousandSep = ',' == cTabDec ? '.' : ',';
1478 : // #i45951# German (Switzerland) uses ' as thousand separator
1479 682 : const sal_Unicode cThousandSep2 = ',' == cTabDec ? '.' : '\'';
1480 :
1481 682 : bool bNumFound = false;
1482 682 : const bool bTabCompat = GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT);
1483 :
1484 12016 : for( ; i < nEnd; ++i )
1485 : {
1486 11401 : const sal_Unicode cPos = GetChar( i );
1487 11401 : switch( cPos )
1488 : {
1489 : case CH_TXTATR_BREAKWORD:
1490 : case CH_TXTATR_INWORD:
1491 0 : if( !HasHint( i ))
1492 0 : break;
1493 : // no break;
1494 :
1495 : case CHAR_SOFTHYPHEN:
1496 : case CHAR_HARDHYPHEN:
1497 : case CHAR_HARDBLANK:
1498 : case CH_TAB:
1499 : case CH_BREAK:
1500 : case CHAR_ZWSP :
1501 : case CHAR_ZWNBSP :
1502 67 : cHookChar = cPos;
1503 67 : return i;
1504 :
1505 : case CHAR_UNDERSCORE:
1506 1872 : if ( STRING_LEN == nUnderScorePos )
1507 6 : nUnderScorePos = i;
1508 1872 : break;
1509 :
1510 : default:
1511 9462 : if ( cTabDec )
1512 : {
1513 0 : if( cTabDec == cPos )
1514 : {
1515 : OSL_ENSURE( cPos, "Unexpected end of string" );
1516 0 : if( cPos ) // robust
1517 : {
1518 0 : cHookChar = cPos;
1519 0 : return i;
1520 : }
1521 : }
1522 :
1523 : //
1524 : // Compatibility: First non-digit character behind a
1525 : // a digit character becomes the hook character
1526 : //
1527 0 : if ( bTabCompat )
1528 : {
1529 0 : if ( ( 0x2F < cPos && cPos < 0x3A ) ||
1530 : ( bNumFound && ( cPos == cThousandSep || cPos == cThousandSep2 ) ) )
1531 : {
1532 0 : bNumFound = true;
1533 : }
1534 : else
1535 : {
1536 0 : if ( bNumFound )
1537 : {
1538 0 : cHookChar = cPos;
1539 0 : SetTabDecimal( cPos );
1540 0 : return i;
1541 : }
1542 : }
1543 : }
1544 : }
1545 : }
1546 : }
1547 :
1548 : // Check if character *behind* the portion has
1549 : // to become the hook:
1550 615 : if ( i == nEnd && i < GetTxt().Len() && bNumFound )
1551 : {
1552 0 : const sal_Unicode cPos = GetChar( i );
1553 0 : if ( cPos != cTabDec && cPos != cThousandSep && cPos !=cThousandSep2 && ( 0x2F >= cPos || cPos >= 0x3A ) )
1554 : {
1555 0 : cHookChar = GetChar( i );
1556 0 : SetTabDecimal( cHookChar );
1557 : }
1558 : }
1559 :
1560 615 : return i;
1561 : }
1562 :
1563 755 : sal_Bool SwTxtFormatInfo::LastKernPortion()
1564 : {
1565 755 : if( GetLast() )
1566 : {
1567 755 : if( GetLast()->IsKernPortion() )
1568 1 : return sal_True;
1569 763 : if( GetLast()->Width() || ( GetLast()->GetLen() &&
1570 9 : !GetLast()->IsHolePortion() ) )
1571 677 : return sal_False;
1572 : }
1573 77 : SwLinePortion* pPor = GetRoot();
1574 77 : SwLinePortion *pKern = NULL;
1575 251 : while( pPor )
1576 : {
1577 97 : if( pPor->IsKernPortion() )
1578 0 : pKern = pPor;
1579 97 : else if( pPor->Width() || ( pPor->GetLen() && !pPor->IsHolePortion() ) )
1580 20 : pKern = NULL;
1581 97 : pPor = pPor->GetPortion();
1582 : }
1583 77 : if( pKern )
1584 : {
1585 0 : SetLast( pKern );
1586 0 : return sal_True;
1587 : }
1588 77 : return sal_False;
1589 : }
1590 :
1591 64 : SwTxtSlot::SwTxtSlot( const SwTxtSizeInfo *pNew, const SwLinePortion *pPor,
1592 : bool bTxtLen, bool bExgLists, const sal_Char *pCh )
1593 : : pOldTxt( 0 ),
1594 : pOldSmartTagList( 0 ),
1595 : pOldGrammarCheckList( 0 ),
1596 64 : pTempList( 0 )
1597 : {
1598 64 : if( pCh )
1599 : {
1600 0 : aTxt = XubString( pCh, RTL_TEXTENCODING_MS_1252 );
1601 0 : bOn = sal_True;
1602 : }
1603 : else
1604 64 : bOn = pPor->GetExpTxt( *pNew, aTxt );
1605 :
1606 : // Teh text is replaced ...
1607 64 : if( bOn )
1608 : {
1609 64 : pInf = (SwTxtSizeInfo*)pNew;
1610 64 : nIdx = pInf->GetIdx();
1611 64 : nLen = pInf->GetLen();
1612 64 : pOldTxt = &(pInf->GetTxt());
1613 64 : pInf->SetTxt( aTxt );
1614 64 : pInf->SetIdx( 0 );
1615 64 : pInf->SetLen( bTxtLen ? pInf->GetTxt().Len() : pPor->GetLen() );
1616 :
1617 : // ST2
1618 64 : if ( bExgLists )
1619 : {
1620 56 : pOldSmartTagList = static_cast<SwTxtPaintInfo*>(pInf)->GetSmartTags();
1621 56 : if ( pOldSmartTagList )
1622 : {
1623 0 : const sal_uInt16 nPos = pOldSmartTagList->GetWrongPos(nIdx);
1624 0 : const xub_StrLen nListPos = pOldSmartTagList->Pos(nPos);
1625 0 : if( nListPos == nIdx )
1626 0 : ((SwTxtPaintInfo*)pInf)->SetSmartTags( pOldSmartTagList->SubList( nPos ) );
1627 0 : else if( !pTempList && nPos < pOldSmartTagList->Count() && nListPos < nIdx && aTxt.Len() )
1628 : {
1629 0 : pTempList = new SwWrongList( WRONGLIST_SMARTTAG );
1630 0 : pTempList->Insert( OUString(), 0, 0, aTxt.Len(), 0 );
1631 0 : ((SwTxtPaintInfo*)pInf)->SetSmartTags( pTempList );
1632 : }
1633 : else
1634 0 : ((SwTxtPaintInfo*)pInf)->SetSmartTags( 0);
1635 : }
1636 56 : pOldGrammarCheckList = static_cast<SwTxtPaintInfo*>(pInf)->GetGrammarCheckList();
1637 56 : if ( pOldGrammarCheckList )
1638 : {
1639 0 : const sal_uInt16 nPos = pOldGrammarCheckList->GetWrongPos(nIdx);
1640 0 : const xub_StrLen nListPos = pOldGrammarCheckList->Pos(nPos);
1641 0 : if( nListPos == nIdx )
1642 0 : ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pOldGrammarCheckList->SubList( nPos ) );
1643 0 : else if( !pTempList && nPos < pOldGrammarCheckList->Count() && nListPos < nIdx && aTxt.Len() )
1644 : {
1645 0 : pTempList = new SwWrongList( WRONGLIST_GRAMMAR );
1646 0 : pTempList->Insert( OUString(), 0, 0, aTxt.Len(), 0 );
1647 0 : ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pTempList );
1648 : }
1649 : else
1650 0 : ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( 0);
1651 : }
1652 : }
1653 : }
1654 64 : }
1655 :
1656 128 : SwTxtSlot::~SwTxtSlot()
1657 : {
1658 64 : if( bOn )
1659 : {
1660 64 : pInf->SetTxt( *pOldTxt );
1661 64 : pInf->SetIdx( nIdx );
1662 64 : pInf->SetLen( nLen );
1663 :
1664 : // ST2
1665 : // Restore old smart tag list
1666 64 : if ( pOldSmartTagList )
1667 0 : ((SwTxtPaintInfo*)pInf)->SetSmartTags( pOldSmartTagList );
1668 64 : if ( pOldGrammarCheckList )
1669 0 : ((SwTxtPaintInfo*)pInf)->SetGrammarCheckList( pOldGrammarCheckList );
1670 64 : delete pTempList;
1671 : }
1672 64 : }
1673 :
1674 326 : SwFontSave::SwFontSave( const SwTxtSizeInfo &rInf, SwFont *pNew,
1675 : SwAttrIter* pItr )
1676 326 : : pFnt( pNew ? ((SwTxtSizeInfo&)rInf).GetFont() : 0 )
1677 : {
1678 326 : if( pFnt )
1679 : {
1680 306 : pInf = &((SwTxtSizeInfo&)rInf);
1681 : // In these cases we temporarily switch to the new font:
1682 : // 1. the fonts have a different magic number
1683 : // 2. they have different script types
1684 : // 3. their background colors differ (this is not covered by 1.)
1685 1306 : if( pFnt->DifferentMagic( pNew, pFnt->GetActual() ) ||
1686 200 : pNew->GetActual() != pFnt->GetActual() ||
1687 400 : ( ! pNew->GetBackColor() && pFnt->GetBackColor() ) ||
1688 200 : ( pNew->GetBackColor() && ! pFnt->GetBackColor() ) ||
1689 200 : ( pNew->GetBackColor() && pFnt->GetBackColor() &&
1690 0 : ( *pNew->GetBackColor() != *pFnt->GetBackColor() ) ) )
1691 : {
1692 106 : pNew->SetTransparent( sal_True );
1693 106 : pNew->SetAlign( ALIGN_BASELINE );
1694 106 : pInf->SetFont( pNew );
1695 : }
1696 : else
1697 200 : pFnt = 0;
1698 306 : pNew->Invalidate();
1699 306 : pNew->ChgPhysFnt( pInf->GetVsh(), *pInf->GetOut() );
1700 306 : if( pItr && pItr->GetFnt() == pFnt )
1701 : {
1702 0 : pIter = pItr;
1703 0 : pIter->SetFnt( pNew );
1704 : }
1705 : else
1706 306 : pIter = NULL;
1707 : }
1708 326 : }
1709 :
1710 326 : SwFontSave::~SwFontSave()
1711 : {
1712 326 : if( pFnt )
1713 : {
1714 : // Reset SwFont
1715 106 : pFnt->Invalidate();
1716 106 : pInf->SetFont( pFnt );
1717 106 : if( pIter )
1718 : {
1719 0 : pIter->SetFnt( pFnt );
1720 0 : pIter->nPos = STRING_LEN;
1721 : }
1722 : }
1723 326 : }
1724 :
1725 0 : SwDefFontSave::SwDefFontSave( const SwTxtSizeInfo &rInf )
1726 0 : : pFnt( ((SwTxtSizeInfo&)rInf).GetFont() )
1727 : {
1728 0 : const bool bTmpAlter = pFnt->GetFixKerning() ||
1729 0 : ( RTL_TEXTENCODING_SYMBOL == pFnt->GetCharSet(pFnt->GetActual()) )
1730 : ;
1731 :
1732 : const bool bFamily = bTmpAlter &&
1733 0 : pFnt->GetName( pFnt->GetActual() ) != numfunc::GetDefBulletFontname();
1734 0 : const bool bRotation = pFnt->GetOrientation() &&
1735 0 : ! rInf.GetTxtFrm()->IsVertical();
1736 :
1737 0 : if( bFamily || bRotation )
1738 : {
1739 0 : pNewFnt = new SwFont( *pFnt );
1740 :
1741 0 : if ( bFamily )
1742 : {
1743 0 : pNewFnt->SetFamily( FAMILY_DONTKNOW, pFnt->GetActual() );
1744 0 : pNewFnt->SetName( numfunc::GetDefBulletFontname(), pFnt->GetActual() );
1745 0 : pNewFnt->SetStyleName( aEmptyStr, pFnt->GetActual() );
1746 0 : pNewFnt->SetCharSet( RTL_TEXTENCODING_SYMBOL, pFnt->GetActual() );
1747 0 : pNewFnt->SetFixKerning( 0 );
1748 : }
1749 :
1750 0 : if ( bRotation )
1751 0 : pNewFnt->SetVertical( 0, rInf.GetTxtFrm()->IsVertical() );
1752 :
1753 0 : pInf = &((SwTxtSizeInfo&)rInf);
1754 0 : pNewFnt->Invalidate();
1755 0 : pInf->SetFont( pNewFnt );
1756 : }
1757 : else
1758 : {
1759 0 : pFnt = 0;
1760 0 : pNewFnt = 0;
1761 : }
1762 0 : }
1763 :
1764 0 : SwDefFontSave::~SwDefFontSave()
1765 : {
1766 0 : if( pFnt )
1767 : {
1768 0 : delete pNewFnt;
1769 : // Reset SwFont
1770 0 : pFnt->Invalidate();
1771 0 : pInf->SetFont( pFnt );
1772 : }
1773 0 : }
1774 :
1775 0 : sal_Bool SwTxtFormatInfo::ChgHyph( const sal_Bool bNew )
1776 : {
1777 0 : const sal_Bool bOld = bAutoHyph;
1778 0 : if( bAutoHyph != bNew )
1779 : {
1780 0 : bAutoHyph = bNew;
1781 0 : InitHyph( bNew );
1782 : // Set language in the Hyphenator
1783 0 : if( pFnt )
1784 0 : pFnt->ChgPhysFnt( pVsh, *pOut );
1785 : }
1786 0 : return bOld;
1787 : }
1788 :
1789 :
1790 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|