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 :
21 : #include <comphelper/string.hxx>
22 : #include <svx/svdotext.hxx>
23 : #include <svx/svdpagv.hxx>
24 : #include <svx/svdview.hxx>
25 : #include <svx/svdpage.hxx>
26 : #include <svx/svdetc.hxx>
27 : #include <svx/svdoutl.hxx>
28 : #include <svx/svdmodel.hxx>
29 : #include "svx/svdglob.hxx"
30 : #include "svx/svdstr.hrc"
31 : #include <editeng/writingmodeitem.hxx>
32 : #include <svx/sdtfchim.hxx>
33 : #include <svtools/colorcfg.hxx>
34 : #include <editeng/editdata.hxx>
35 : #include <editeng/eeitem.hxx>
36 : #include <editeng/editstat.hxx>
37 : #include <editeng/outlobj.hxx>
38 : #include <editeng/editobj.hxx>
39 : #include <editeng/outliner.hxx>
40 : #include <editeng/fhgtitem.hxx>
41 : #include <svl/itempool.hxx>
42 : #include <editeng/adjustitem.hxx>
43 : #include <editeng/flditem.hxx>
44 : #include <svx/xftouit.hxx>
45 : #include <tools/helpers.hxx>
46 : #include <svx/xflgrit.hxx>
47 : #include <svx/svdpool.hxx>
48 : #include <svx/xflclit.hxx>
49 : #include <svl/style.hxx>
50 : #include <editeng/editeng.hxx>
51 : #include <svl/itemiter.hxx>
52 : #include <svx/sdr/properties/textproperties.hxx>
53 : #include <vcl/metaact.hxx>
54 : #include <svx/sdr/contact/viewcontactoftextobj.hxx>
55 : #include <basegfx/tuple/b2dtuple.hxx>
56 : #include <basegfx/matrix/b2dhommatrix.hxx>
57 : #include <basegfx/polygon/b2dpolygon.hxx>
58 : #include <drawinglayer/geometry/viewinformation2d.hxx>
59 : #include <vcl/virdev.hxx>
60 : #include <basegfx/matrix/b2dhommatrixtools.hxx>
61 : #include "svdconv.hxx"
62 :
63 : using namespace com::sun::star;
64 :
65 :
66 : // BaseProperties section
67 :
68 0 : sdr::properties::BaseProperties* SdrTextObj::CreateObjectSpecificProperties()
69 : {
70 0 : return new sdr::properties::TextProperties(*this);
71 : }
72 :
73 :
74 : // DrawContact section
75 :
76 0 : sdr::contact::ViewContact* SdrTextObj::CreateObjectSpecificViewContact()
77 : {
78 0 : return new sdr::contact::ViewContactOfTextObj(*this);
79 : }
80 :
81 :
82 :
83 0 : TYPEINIT1(SdrTextObj,SdrAttrObj);
84 :
85 0 : SdrTextObj::SdrTextObj()
86 : : SdrAttrObj(),
87 : mpText(NULL),
88 : pEdtOutl(NULL),
89 : pFormTextBoundRect(NULL),
90 0 : eTextKind(OBJ_TEXT)
91 : {
92 0 : bTextSizeDirty=false;
93 0 : bTextFrame=false;
94 0 : bPortionInfoChecked=false;
95 0 : bNoShear=false;
96 0 : bNoRotate=false;
97 0 : bNoMirror=false;
98 0 : bDisableAutoWidthOnDragging=false;
99 :
100 0 : mbInEditMode = false;
101 0 : mbTextHidden = false;
102 0 : mbTextAnimationAllowed = true;
103 0 : maTextEditOffset = Point(0, 0);
104 :
105 : // #i25616#
106 0 : mbSupportTextIndentingOnLineWidthChange = true;
107 0 : mbInDownScale = false;
108 0 : }
109 :
110 0 : SdrTextObj::SdrTextObj(const Rectangle& rNewRect)
111 : : SdrAttrObj(),
112 : aRect(rNewRect),
113 : mpText(NULL),
114 : pEdtOutl(NULL),
115 : pFormTextBoundRect(NULL),
116 0 : eTextKind(OBJ_TEXT)
117 : {
118 0 : bTextSizeDirty=false;
119 0 : bTextFrame=false;
120 0 : bPortionInfoChecked=false;
121 0 : bNoShear=false;
122 0 : bNoRotate=false;
123 0 : bNoMirror=false;
124 0 : bDisableAutoWidthOnDragging=false;
125 0 : ImpJustifyRect(aRect);
126 :
127 0 : mbInEditMode = false;
128 0 : mbTextHidden = false;
129 0 : mbTextAnimationAllowed = true;
130 0 : mbInDownScale = false;
131 0 : maTextEditOffset = Point(0, 0);
132 :
133 : // #i25616#
134 0 : mbSupportTextIndentingOnLineWidthChange = true;
135 0 : }
136 :
137 0 : SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind)
138 : : SdrAttrObj(),
139 : mpText(NULL),
140 : pEdtOutl(NULL),
141 : pFormTextBoundRect(NULL),
142 0 : eTextKind(eNewTextKind)
143 : {
144 0 : bTextSizeDirty=false;
145 0 : bTextFrame=true;
146 0 : bPortionInfoChecked=false;
147 0 : bNoShear=true;
148 0 : bNoRotate=false;
149 0 : bNoMirror=true;
150 0 : bDisableAutoWidthOnDragging=false;
151 :
152 0 : mbInEditMode = false;
153 0 : mbTextHidden = false;
154 0 : mbTextAnimationAllowed = true;
155 0 : mbInDownScale = false;
156 0 : maTextEditOffset = Point(0, 0);
157 :
158 : // #i25616#
159 0 : mbSupportTextIndentingOnLineWidthChange = true;
160 0 : }
161 :
162 0 : SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind, const Rectangle& rNewRect)
163 : : SdrAttrObj(),
164 : aRect(rNewRect),
165 : mpText(NULL),
166 : pEdtOutl(NULL),
167 : pFormTextBoundRect(NULL),
168 0 : eTextKind(eNewTextKind)
169 : {
170 0 : bTextSizeDirty=false;
171 0 : bTextFrame=true;
172 0 : bPortionInfoChecked=false;
173 0 : bNoShear=true;
174 0 : bNoRotate=false;
175 0 : bNoMirror=true;
176 0 : bDisableAutoWidthOnDragging=false;
177 0 : ImpJustifyRect(aRect);
178 :
179 0 : mbInEditMode = false;
180 0 : mbTextHidden = false;
181 0 : mbTextAnimationAllowed = true;
182 0 : mbInDownScale = false;
183 0 : maTextEditOffset = Point(0, 0);
184 :
185 : // #i25616#
186 0 : mbSupportTextIndentingOnLineWidthChange = true;
187 0 : }
188 :
189 0 : SdrTextObj::~SdrTextObj()
190 : {
191 0 : if( pModel )
192 : {
193 0 : SdrOutliner& rOutl = pModel->GetHitTestOutliner();
194 0 : if( rOutl.GetTextObj() == this )
195 0 : rOutl.SetTextObj( NULL );
196 : }
197 :
198 0 : delete mpText;
199 :
200 0 : delete pFormTextBoundRect;
201 :
202 0 : ImpLinkAbmeldung();
203 0 : }
204 :
205 0 : void SdrTextObj::FitFrameToTextSize()
206 : {
207 : DBG_ASSERT(pModel!=NULL,"SdrTextObj::FitFrameToTextSize(): pModel=NULL!");
208 0 : ImpJustifyRect(aRect);
209 :
210 0 : SdrText* pText = getActiveText();
211 0 : if( pText!=NULL && pText->GetOutlinerParaObject() && pModel!=NULL)
212 : {
213 0 : SdrOutliner& rOutliner=ImpGetDrawOutliner();
214 0 : rOutliner.SetPaperSize(Size(aRect.Right()-aRect.Left(),aRect.Bottom()-aRect.Top()));
215 0 : rOutliner.SetUpdateMode(true);
216 0 : rOutliner.SetText(*pText->GetOutlinerParaObject());
217 0 : Size aNewSize(rOutliner.CalcTextSize());
218 0 : rOutliner.Clear();
219 0 : aNewSize.Width()++; // because of possible rounding errors
220 0 : aNewSize.Width()+=GetTextLeftDistance()+GetTextRightDistance();
221 0 : aNewSize.Height()+=GetTextUpperDistance()+GetTextLowerDistance();
222 0 : Rectangle aNewRect(aRect);
223 0 : aNewRect.SetSize(aNewSize);
224 0 : ImpJustifyRect(aNewRect);
225 0 : if (aNewRect!=aRect) {
226 0 : SetLogicRect(aNewRect);
227 : }
228 : }
229 0 : }
230 :
231 0 : void SdrTextObj::NbcSetText(const OUString& rStr)
232 : {
233 0 : SdrOutliner& rOutliner=ImpGetDrawOutliner();
234 0 : rOutliner.SetStyleSheet( 0, GetStyleSheet());
235 0 : rOutliner.SetUpdateMode(true);
236 0 : rOutliner.SetText(rStr,rOutliner.GetParagraph( 0 ));
237 0 : OutlinerParaObject* pNewText=rOutliner.CreateParaObject();
238 0 : Size aSiz(rOutliner.CalcTextSize());
239 0 : rOutliner.Clear();
240 0 : NbcSetOutlinerParaObject(pNewText);
241 0 : aTextSize=aSiz;
242 0 : bTextSizeDirty=false;
243 0 : }
244 :
245 0 : void SdrTextObj::SetText(const OUString& rStr)
246 : {
247 0 : Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
248 0 : NbcSetText(rStr);
249 0 : SetChanged();
250 0 : BroadcastObjectChange();
251 0 : SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
252 0 : }
253 :
254 0 : void SdrTextObj::NbcSetText(SvStream& rInput, const OUString& rBaseURL, sal_uInt16 eFormat)
255 : {
256 0 : SdrOutliner& rOutliner=ImpGetDrawOutliner();
257 0 : rOutliner.SetStyleSheet( 0, GetStyleSheet());
258 0 : rOutliner.Read(rInput,rBaseURL,eFormat);
259 0 : OutlinerParaObject* pNewText=rOutliner.CreateParaObject();
260 0 : rOutliner.SetUpdateMode(true);
261 0 : Size aSiz(rOutliner.CalcTextSize());
262 0 : rOutliner.Clear();
263 0 : NbcSetOutlinerParaObject(pNewText);
264 0 : aTextSize=aSiz;
265 0 : bTextSizeDirty=false;
266 0 : }
267 :
268 0 : void SdrTextObj::SetText(SvStream& rInput, const OUString& rBaseURL, sal_uInt16 eFormat)
269 : {
270 0 : Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
271 0 : NbcSetText(rInput,rBaseURL,eFormat);
272 0 : SetChanged();
273 0 : BroadcastObjectChange();
274 0 : SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
275 0 : }
276 :
277 0 : const Size& SdrTextObj::GetTextSize() const
278 : {
279 0 : if (bTextSizeDirty)
280 : {
281 0 : Size aSiz;
282 0 : SdrText* pText = getActiveText();
283 0 : if( pText && pText->GetOutlinerParaObject ())
284 : {
285 0 : SdrOutliner& rOutliner=ImpGetDrawOutliner();
286 0 : rOutliner.SetText(*pText->GetOutlinerParaObject());
287 0 : rOutliner.SetUpdateMode(true);
288 0 : aSiz=rOutliner.CalcTextSize();
289 0 : rOutliner.Clear();
290 : }
291 : // casting to nonconst twice
292 0 : ((SdrTextObj*)this)->aTextSize=aSiz;
293 0 : ((SdrTextObj*)this)->bTextSizeDirty=false;
294 : }
295 0 : return aTextSize;
296 : }
297 :
298 0 : bool SdrTextObj::IsAutoGrowHeight() const
299 : {
300 0 : if(!bTextFrame)
301 0 : return false; // AutoGrow only together with TextFrames
302 :
303 0 : const SfxItemSet& rSet = GetObjectItemSet();
304 0 : bool bRet = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue();
305 :
306 0 : if(bRet)
307 : {
308 0 : SdrTextAniKind eAniKind = ((SdrTextAniKindItem&)(rSet.Get(SDRATTR_TEXT_ANIKIND))).GetValue();
309 :
310 0 : if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE)
311 : {
312 0 : SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue();
313 :
314 0 : if(eDirection == SDRTEXTANI_UP || eDirection == SDRTEXTANI_DOWN)
315 : {
316 0 : bRet = false;
317 : }
318 : }
319 : }
320 0 : return bRet;
321 : }
322 :
323 0 : bool SdrTextObj::IsAutoGrowWidth() const
324 : {
325 0 : if(!bTextFrame)
326 0 : return false; // AutoGrow only together with TextFrames
327 :
328 0 : const SfxItemSet& rSet = GetObjectItemSet();
329 0 : bool bRet = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWWIDTH))).GetValue();
330 :
331 0 : bool bInEditMOde = IsInEditMode();
332 :
333 0 : if(!bInEditMOde && bRet)
334 : {
335 0 : SdrTextAniKind eAniKind = ((SdrTextAniKindItem&)(rSet.Get(SDRATTR_TEXT_ANIKIND))).GetValue();
336 :
337 0 : if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE)
338 : {
339 0 : SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue();
340 :
341 0 : if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT)
342 : {
343 0 : bRet = false;
344 : }
345 : }
346 : }
347 0 : return bRet;
348 : }
349 :
350 0 : SdrTextHorzAdjust SdrTextObj::GetTextHorizontalAdjust() const
351 : {
352 0 : return GetTextHorizontalAdjust(GetObjectItemSet());
353 : }
354 :
355 0 : SdrTextHorzAdjust SdrTextObj::GetTextHorizontalAdjust(const SfxItemSet& rSet) const
356 : {
357 0 : if(IsContourTextFrame())
358 0 : return SDRTEXTHORZADJUST_BLOCK;
359 :
360 0 : SdrTextHorzAdjust eRet = ((SdrTextHorzAdjustItem&)(rSet.Get(SDRATTR_TEXT_HORZADJUST))).GetValue();
361 :
362 0 : bool bInEditMode = IsInEditMode();
363 :
364 0 : if(!bInEditMode && eRet == SDRTEXTHORZADJUST_BLOCK)
365 : {
366 0 : SdrTextAniKind eAniKind = ((SdrTextAniKindItem&)(rSet.Get(SDRATTR_TEXT_ANIKIND))).GetValue();
367 :
368 0 : if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE)
369 : {
370 0 : SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue();
371 :
372 0 : if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT)
373 : {
374 0 : eRet = SDRTEXTHORZADJUST_LEFT;
375 : }
376 : }
377 : }
378 :
379 0 : return eRet;
380 : } // defaults: BLOCK (justify) for text frame, CENTER for captions of drawing objects
381 :
382 0 : SdrTextVertAdjust SdrTextObj::GetTextVerticalAdjust() const
383 : {
384 0 : return GetTextVerticalAdjust(GetObjectItemSet());
385 : }
386 :
387 0 : SdrTextVertAdjust SdrTextObj::GetTextVerticalAdjust(const SfxItemSet& rSet) const
388 : {
389 0 : if(IsContourTextFrame())
390 0 : return SDRTEXTVERTADJUST_TOP;
391 :
392 : // Take care for vertical text animation here
393 0 : SdrTextVertAdjust eRet = ((SdrTextVertAdjustItem&)(rSet.Get(SDRATTR_TEXT_VERTADJUST))).GetValue();
394 0 : bool bInEditMode = IsInEditMode();
395 :
396 : // Take care for vertical text animation here
397 0 : if(!bInEditMode && eRet == SDRTEXTVERTADJUST_BLOCK)
398 : {
399 0 : SdrTextAniKind eAniKind = ((SdrTextAniKindItem&)(rSet.Get(SDRATTR_TEXT_ANIKIND))).GetValue();
400 :
401 0 : if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE)
402 : {
403 0 : SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue();
404 :
405 0 : if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT)
406 : {
407 0 : eRet = SDRTEXTVERTADJUST_TOP;
408 : }
409 : }
410 : }
411 :
412 0 : return eRet;
413 : } // defaults: TOP for text frame, CENTER for captions of drawing objects
414 :
415 0 : void SdrTextObj::ImpJustifyRect(Rectangle& rRect) const
416 : {
417 0 : if (!rRect.IsEmpty()) {
418 0 : rRect.Justify();
419 0 : if (rRect.Left()==rRect.Right()) rRect.Right()++;
420 0 : if (rRect.Top()==rRect.Bottom()) rRect.Bottom()++;
421 : }
422 0 : }
423 :
424 0 : void SdrTextObj::ImpCheckShear()
425 : {
426 0 : if (bNoShear && aGeo.nShearWink!=0) {
427 0 : aGeo.nShearWink=0;
428 0 : aGeo.nTan=0;
429 : }
430 0 : }
431 :
432 0 : void SdrTextObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
433 : {
434 0 : bool bNoTextFrame=!IsTextFrame();
435 0 : rInfo.bResizeFreeAllowed=bNoTextFrame || aGeo.nDrehWink%9000==0;
436 0 : rInfo.bResizePropAllowed=true;
437 0 : rInfo.bRotateFreeAllowed=true;
438 0 : rInfo.bRotate90Allowed =true;
439 0 : rInfo.bMirrorFreeAllowed=bNoTextFrame;
440 0 : rInfo.bMirror45Allowed =bNoTextFrame;
441 0 : rInfo.bMirror90Allowed =bNoTextFrame;
442 :
443 : // allow transparency
444 0 : rInfo.bTransparenceAllowed = true;
445 :
446 : // gradient depends on fillstyle
447 0 : XFillStyle eFillStyle = ((XFillStyleItem&)(GetObjectItem(XATTR_FILLSTYLE))).GetValue();
448 0 : rInfo.bGradientAllowed = (eFillStyle == XFILL_GRADIENT);
449 0 : rInfo.bShearAllowed =bNoTextFrame;
450 0 : rInfo.bEdgeRadiusAllowed=true;
451 0 : bool bCanConv=ImpCanConvTextToCurve();
452 0 : rInfo.bCanConvToPath =bCanConv;
453 0 : rInfo.bCanConvToPoly =bCanConv;
454 0 : rInfo.bCanConvToPathLineToArea=bCanConv;
455 0 : rInfo.bCanConvToPolyLineToArea=bCanConv;
456 0 : rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
457 0 : }
458 :
459 0 : sal_uInt16 SdrTextObj::GetObjIdentifier() const
460 : {
461 0 : return sal_uInt16(eTextKind);
462 : }
463 :
464 0 : bool SdrTextObj::HasTextImpl( SdrOutliner* pOutliner )
465 : {
466 0 : bool bRet=false;
467 0 : if(pOutliner)
468 : {
469 0 : Paragraph* p1stPara=pOutliner->GetParagraph( 0 );
470 0 : sal_Int32 nParaAnz=pOutliner->GetParagraphCount();
471 0 : if(p1stPara==NULL)
472 0 : nParaAnz=0;
473 :
474 0 : if(nParaAnz==1)
475 : {
476 : // if it is only one paragraph, check if that paragraph is empty
477 0 : if( pOutliner->GetText(p1stPara).isEmpty() )
478 0 : nParaAnz = 0;
479 : }
480 :
481 0 : bRet= nParaAnz!=0;
482 : }
483 0 : return bRet;
484 : }
485 :
486 0 : bool SdrTextObj::HasEditText() const
487 : {
488 0 : return HasTextImpl( pEdtOutl );
489 : }
490 :
491 0 : void SdrTextObj::SetPage(SdrPage* pNewPage)
492 : {
493 0 : bool bRemove=pNewPage==NULL && pPage!=NULL;
494 0 : bool bInsert=pNewPage!=NULL && pPage==NULL;
495 0 : bool bLinked=IsLinkedText();
496 :
497 0 : if (bLinked && bRemove) {
498 0 : ImpLinkAbmeldung();
499 : }
500 :
501 0 : SdrAttrObj::SetPage(pNewPage);
502 :
503 0 : if (bLinked && bInsert) {
504 0 : ImpLinkAnmeldung();
505 : }
506 0 : }
507 :
508 0 : void SdrTextObj::SetModel(SdrModel* pNewModel)
509 : {
510 0 : SdrModel* pOldModel=pModel;
511 0 : bool bLinked=IsLinkedText();
512 0 : bool bChg=pNewModel!=pModel;
513 :
514 0 : if (bLinked && bChg)
515 : {
516 0 : ImpLinkAbmeldung();
517 : }
518 :
519 0 : SdrAttrObj::SetModel(pNewModel);
520 :
521 0 : if( bChg )
522 : {
523 0 : if( pNewModel != 0 && pOldModel != 0 )
524 0 : SetTextSizeDirty();
525 :
526 0 : sal_Int32 nCount = getTextCount();
527 0 : for( sal_Int32 nText = 0; nText < nCount; nText++ )
528 : {
529 0 : SdrText* pText = getText( nText );
530 0 : if( pText )
531 0 : pText->SetModel( pNewModel );
532 : }
533 : }
534 :
535 0 : if (bLinked && bChg)
536 : {
537 0 : ImpLinkAnmeldung();
538 : }
539 0 : }
540 :
541 0 : bool SdrTextObj::NbcSetEckenradius(long nRad)
542 : {
543 0 : SetObjectItem(SdrEckenradiusItem(nRad));
544 0 : return true;
545 : }
546 :
547 0 : bool SdrTextObj::NbcSetAutoGrowHeight(bool bAuto)
548 : {
549 0 : if(bTextFrame)
550 : {
551 0 : SetObjectItem(SdrTextAutoGrowHeightItem(bAuto));
552 0 : return true;
553 : }
554 0 : return false;
555 : }
556 :
557 0 : bool SdrTextObj::NbcSetMaxTextFrameHeight(long nHgt)
558 : {
559 0 : if(bTextFrame)
560 : {
561 0 : SetObjectItem(SdrTextMaxFrameHeightItem(nHgt));
562 0 : return true;
563 : }
564 0 : return false;
565 : }
566 :
567 : // #115391# This implementation is based on the object size (aRect) and the
568 : // states of IsAutoGrowWidth/Height to correctly set TextMinFrameWidth/Height
569 0 : void SdrTextObj::AdaptTextMinSize()
570 : {
571 0 : if(bTextFrame && (!pModel || !pModel->IsPasteResize()))
572 : {
573 0 : const bool bW(IsAutoGrowWidth());
574 0 : const bool bH(IsAutoGrowHeight());
575 :
576 0 : if(bW || bH)
577 : {
578 : SfxItemSet aSet(
579 0 : *GetObjectItemSet().GetPool(),
580 : SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT,
581 : SDRATTR_TEXT_MINFRAMEWIDTH, SDRATTR_TEXT_AUTOGROWWIDTH, // contains SDRATTR_TEXT_MAXFRAMEWIDTH
582 0 : 0, 0);
583 :
584 0 : if(bW)
585 : {
586 0 : const long nDist(GetTextLeftDistance() + GetTextRightDistance());
587 0 : const long nW(std::max(long(0), (long)(aRect.GetWidth() - 1 - nDist)));
588 :
589 0 : aSet.Put(SdrTextMinFrameWidthItem(nW));
590 :
591 0 : if(!IsVerticalWriting() && bDisableAutoWidthOnDragging)
592 : {
593 0 : bDisableAutoWidthOnDragging = true;
594 0 : aSet.Put(SdrTextAutoGrowWidthItem(false));
595 : }
596 : }
597 :
598 0 : if(bH)
599 : {
600 0 : const long nDist(GetTextUpperDistance() + GetTextLowerDistance());
601 0 : const long nH(std::max(long(0), (long)(aRect.GetHeight() - 1 - nDist)));
602 :
603 0 : aSet.Put(SdrTextMinFrameHeightItem(nH));
604 :
605 0 : if(IsVerticalWriting() && bDisableAutoWidthOnDragging)
606 : {
607 0 : bDisableAutoWidthOnDragging = false;
608 0 : aSet.Put(SdrTextAutoGrowHeightItem(false));
609 : }
610 : }
611 :
612 0 : SetObjectItemSet(aSet);
613 0 : NbcAdjustTextFrameWidthAndHeight();
614 : }
615 : }
616 0 : }
617 :
618 0 : bool SdrTextObj::NbcSetAutoGrowWidth(bool bAuto)
619 : {
620 0 : if(bTextFrame)
621 : {
622 0 : SetObjectItem(SdrTextAutoGrowWidthItem(bAuto));
623 0 : return true;
624 : }
625 0 : return false;
626 : }
627 :
628 0 : bool SdrTextObj::NbcSetMaxTextFrameWidth(long nWdt)
629 : {
630 0 : if(bTextFrame)
631 : {
632 0 : SetObjectItem(SdrTextMaxFrameWidthItem(nWdt));
633 0 : return true;
634 : }
635 0 : return false;
636 : }
637 :
638 0 : bool SdrTextObj::NbcSetFitToSize(SdrFitToSizeType eFit)
639 : {
640 0 : if(bTextFrame)
641 : {
642 0 : SetObjectItem(SdrTextFitToSizeTypeItem(eFit));
643 0 : return true;
644 : }
645 0 : return false;
646 : }
647 :
648 0 : void SdrTextObj::ImpSetContourPolygon( SdrOutliner& rOutliner, Rectangle& rAnchorRect, bool bLineWidth ) const
649 : {
650 0 : basegfx::B2DPolyPolygon aXorPolyPolygon(TakeXorPoly());
651 0 : basegfx::B2DPolyPolygon* pContourPolyPolygon = 0L;
652 : basegfx::B2DHomMatrix aMatrix(basegfx::tools::createTranslateB2DHomMatrix(
653 0 : -rAnchorRect.Left(), -rAnchorRect.Top()));
654 :
655 0 : if(aGeo.nDrehWink)
656 : {
657 : // Unrotate!
658 0 : aMatrix.rotate(-aGeo.nDrehWink * nPi180);
659 : }
660 :
661 0 : aXorPolyPolygon.transform(aMatrix);
662 :
663 0 : if( bLineWidth )
664 : {
665 : // Take line width into account.
666 : // When doing the hit test, avoid this. (Performance!)
667 0 : pContourPolyPolygon = new basegfx::B2DPolyPolygon();
668 :
669 : // test if shadow needs to be avoided for TakeContour()
670 0 : const SfxItemSet& rSet = GetObjectItemSet();
671 0 : bool bShadowOn = ((SdrShadowItem&)(rSet.Get(SDRATTR_SHADOW))).GetValue();
672 :
673 : // #i33696#
674 : // Remember TextObject currently set at the DrawOutliner, it WILL be
675 : // replaced during calculating the outline since it uses an own paint
676 : // and that one uses the DrawOutliner, too.
677 0 : const SdrTextObj* pLastTextObject = rOutliner.GetTextObj();
678 :
679 0 : if(bShadowOn)
680 : {
681 : // force shadow off
682 0 : SdrObject* pCopy = Clone();
683 0 : pCopy->SetMergedItem(SdrShadowItem(false));
684 0 : *pContourPolyPolygon = pCopy->TakeContour();
685 0 : SdrObject::Free( pCopy );
686 : }
687 : else
688 : {
689 0 : *pContourPolyPolygon = TakeContour();
690 : }
691 :
692 : // #i33696#
693 : // restore remembered text object
694 0 : if(pLastTextObject != rOutliner.GetTextObj())
695 : {
696 0 : rOutliner.SetTextObj(pLastTextObject);
697 : }
698 :
699 0 : pContourPolyPolygon->transform(aMatrix);
700 : }
701 :
702 0 : rOutliner.SetPolygon(aXorPolyPolygon, pContourPolyPolygon);
703 0 : delete pContourPolyPolygon;
704 0 : }
705 :
706 0 : void SdrTextObj::TakeUnrotatedSnapRect(Rectangle& rRect) const
707 : {
708 0 : rRect=aRect;
709 0 : }
710 :
711 0 : void SdrTextObj::TakeTextAnchorRect(Rectangle& rAnchorRect) const
712 : {
713 0 : long nLeftDist=GetTextLeftDistance();
714 0 : long nRightDist=GetTextRightDistance();
715 0 : long nUpperDist=GetTextUpperDistance();
716 0 : long nLowerDist=GetTextLowerDistance();
717 0 : Rectangle aAnkRect(aRect); // the rectangle in which we anchor
718 0 : bool bFrame=IsTextFrame();
719 0 : if (!bFrame) {
720 0 : TakeUnrotatedSnapRect(aAnkRect);
721 : }
722 0 : Point aRotateRef(aAnkRect.TopLeft());
723 0 : aAnkRect.Left()+=nLeftDist;
724 0 : aAnkRect.Top()+=nUpperDist;
725 0 : aAnkRect.Right()-=nRightDist;
726 0 : aAnkRect.Bottom()-=nLowerDist;
727 :
728 : // Since sizes may be bigger than the object bounds it is necessary to
729 : // justify the rect now.
730 0 : ImpJustifyRect(aAnkRect);
731 :
732 0 : if (bFrame) {
733 : // TODO: Optimize this.
734 0 : if (aAnkRect.GetWidth()<2) aAnkRect.Right()=aAnkRect.Left()+1; // minimum size h and v: 2 px
735 0 : if (aAnkRect.GetHeight()<2) aAnkRect.Bottom()=aAnkRect.Top()+1;
736 : }
737 0 : if (aGeo.nDrehWink!=0) {
738 0 : Point aTmpPt(aAnkRect.TopLeft());
739 0 : RotatePoint(aTmpPt,aRotateRef,aGeo.nSin,aGeo.nCos);
740 0 : aTmpPt-=aAnkRect.TopLeft();
741 0 : aAnkRect.Move(aTmpPt.X(),aTmpPt.Y());
742 : }
743 0 : rAnchorRect=aAnkRect;
744 0 : }
745 :
746 0 : void SdrTextObj::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, bool bNoEditText,
747 : Rectangle* pAnchorRect, bool bLineWidth ) const
748 : {
749 0 : Rectangle aAnkRect; // the rectangle in which we anchor
750 0 : TakeTextAnchorRect(aAnkRect);
751 0 : SdrTextVertAdjust eVAdj=GetTextVerticalAdjust();
752 0 : SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust();
753 0 : SdrTextAniKind eAniKind=GetTextAniKind();
754 0 : SdrTextAniDirection eAniDirection=GetTextAniDirection();
755 :
756 0 : bool bFitToSize(IsFitToSize());
757 0 : bool bContourFrame=IsContourTextFrame();
758 :
759 0 : bool bFrame=IsTextFrame();
760 0 : sal_uIntPtr nStat0=rOutliner.GetControlWord();
761 0 : Size aNullSize;
762 0 : if (!bContourFrame)
763 : {
764 0 : rOutliner.SetControlWord(nStat0|EE_CNTRL_AUTOPAGESIZE);
765 0 : rOutliner.SetMinAutoPaperSize(aNullSize);
766 0 : rOutliner.SetMaxAutoPaperSize(Size(1000000,1000000));
767 : }
768 :
769 0 : if (!bFitToSize && !bContourFrame)
770 : {
771 0 : long nAnkWdt=aAnkRect.GetWidth();
772 0 : long nAnkHgt=aAnkRect.GetHeight();
773 0 : if (bFrame)
774 : {
775 0 : long nWdt=nAnkWdt;
776 0 : long nHgt=nAnkHgt;
777 :
778 0 : bool bInEditMode = IsInEditMode();
779 :
780 0 : if (!bInEditMode && (eAniKind==SDRTEXTANI_SCROLL || eAniKind==SDRTEXTANI_ALTERNATE || eAniKind==SDRTEXTANI_SLIDE))
781 : {
782 : // unlimited paper size for ticker text
783 0 : if (eAniDirection==SDRTEXTANI_LEFT || eAniDirection==SDRTEXTANI_RIGHT) nWdt=1000000;
784 0 : if (eAniDirection==SDRTEXTANI_UP || eAniDirection==SDRTEXTANI_DOWN) nHgt=1000000;
785 : }
786 :
787 : // #i119885# Do not limit/force height to geometrical frame (vice versa for vertical writing)
788 0 : if(IsVerticalWriting())
789 : {
790 0 : nWdt = 1000000;
791 : }
792 : else
793 : {
794 0 : nHgt = 1000000;
795 : }
796 :
797 0 : rOutliner.SetMaxAutoPaperSize(Size(nWdt,nHgt));
798 : }
799 :
800 : // New try with _BLOCK for hor and ver after completely
801 : // supporting full width for vertical text.
802 0 : if(SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting())
803 : {
804 0 : rOutliner.SetMinAutoPaperSize(Size(nAnkWdt, 0));
805 : }
806 :
807 0 : if(SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting())
808 : {
809 0 : rOutliner.SetMinAutoPaperSize(Size(0, nAnkHgt));
810 : }
811 : }
812 :
813 0 : rOutliner.SetPaperSize(aNullSize);
814 0 : if (bContourFrame)
815 0 : ImpSetContourPolygon( rOutliner, aAnkRect, bLineWidth );
816 :
817 : // put text into the outliner, if available from the edit outliner
818 0 : SdrText* pText = getActiveText();
819 0 : OutlinerParaObject* pOutlinerParaObject = pText ? pText->GetOutlinerParaObject() : 0;
820 0 : OutlinerParaObject* pPara = (pEdtOutl && !bNoEditText) ? pEdtOutl->CreateParaObject() : pOutlinerParaObject;
821 :
822 0 : if (pPara)
823 : {
824 0 : bool bHitTest = false;
825 0 : if( pModel )
826 0 : bHitTest = &pModel->GetHitTestOutliner() == &rOutliner;
827 :
828 0 : const SdrTextObj* pTestObj = rOutliner.GetTextObj();
829 0 : if( !pTestObj || !bHitTest || pTestObj != this ||
830 0 : pTestObj->GetOutlinerParaObject() != pOutlinerParaObject )
831 : {
832 0 : if( bHitTest ) // #i33696# take back fix #i27510#
833 : {
834 0 : rOutliner.SetTextObj( this );
835 0 : rOutliner.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue());
836 : }
837 :
838 0 : rOutliner.SetUpdateMode(true);
839 0 : rOutliner.SetText(*pPara);
840 : }
841 : }
842 : else
843 : {
844 0 : rOutliner.SetTextObj( NULL );
845 : }
846 :
847 0 : if (pEdtOutl && !bNoEditText && pPara)
848 0 : delete pPara;
849 :
850 0 : rOutliner.SetUpdateMode(true);
851 0 : rOutliner.SetControlWord(nStat0);
852 :
853 0 : if( pText )
854 0 : pText->CheckPortionInfo(rOutliner);
855 :
856 0 : Point aTextPos(aAnkRect.TopLeft());
857 0 : Size aTextSiz(rOutliner.GetPaperSize()); // GetPaperSize() adds a little tolerance, right?
858 :
859 : // For draw objects containing text correct hor/ver alignment if text is bigger
860 : // than the object itself. Without that correction, the text would always be
861 : // formatted to the left edge (or top edge when vertical) of the draw object.
862 0 : if(!IsTextFrame())
863 : {
864 0 : if(aAnkRect.GetWidth() < aTextSiz.Width() && !IsVerticalWriting())
865 : {
866 : // Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK,
867 : // else the alignment is wanted.
868 0 : if(SDRTEXTHORZADJUST_BLOCK == eHAdj)
869 : {
870 0 : eHAdj = SDRTEXTHORZADJUST_CENTER;
871 : }
872 : }
873 :
874 0 : if(aAnkRect.GetHeight() < aTextSiz.Height() && IsVerticalWriting())
875 : {
876 : // Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK,
877 : // else the alignment is wanted.
878 0 : if(SDRTEXTVERTADJUST_BLOCK == eVAdj)
879 : {
880 0 : eVAdj = SDRTEXTVERTADJUST_CENTER;
881 : }
882 : }
883 : }
884 :
885 0 : if (eHAdj==SDRTEXTHORZADJUST_CENTER || eHAdj==SDRTEXTHORZADJUST_RIGHT)
886 : {
887 0 : long nFreeWdt=aAnkRect.GetWidth()-aTextSiz.Width();
888 0 : if (eHAdj==SDRTEXTHORZADJUST_CENTER)
889 0 : aTextPos.X()+=nFreeWdt/2;
890 0 : if (eHAdj==SDRTEXTHORZADJUST_RIGHT)
891 0 : aTextPos.X()+=nFreeWdt;
892 : }
893 0 : if (eVAdj==SDRTEXTVERTADJUST_CENTER || eVAdj==SDRTEXTVERTADJUST_BOTTOM)
894 : {
895 0 : long nFreeHgt=aAnkRect.GetHeight()-aTextSiz.Height();
896 0 : if (eVAdj==SDRTEXTVERTADJUST_CENTER)
897 0 : aTextPos.Y()+=nFreeHgt/2;
898 0 : if (eVAdj==SDRTEXTVERTADJUST_BOTTOM)
899 0 : aTextPos.Y()+=nFreeHgt;
900 : }
901 0 : if (aGeo.nDrehWink!=0)
902 0 : RotatePoint(aTextPos,aAnkRect.TopLeft(),aGeo.nSin,aGeo.nCos);
903 :
904 0 : if (pAnchorRect)
905 0 : *pAnchorRect=aAnkRect;
906 :
907 : // rTextRect might not be correct in some cases at ContourFrame
908 0 : rTextRect=Rectangle(aTextPos,aTextSiz);
909 0 : if (bContourFrame)
910 0 : rTextRect=aAnkRect;
911 0 : }
912 :
913 0 : OutlinerParaObject* SdrTextObj::GetEditOutlinerParaObject() const
914 : {
915 0 : OutlinerParaObject* pPara=NULL;
916 0 : if( HasTextImpl( pEdtOutl ) )
917 : {
918 0 : sal_Int32 nParaAnz = pEdtOutl->GetParagraphCount();
919 0 : pPara = pEdtOutl->CreateParaObject(0, nParaAnz);
920 : }
921 0 : return pPara;
922 : }
923 :
924 0 : void SdrTextObj::ImpSetCharStretching(SdrOutliner& rOutliner, const Size& rTextSize, const Size& rShapeSize, Fraction& rFitXKorreg) const
925 : {
926 0 : OutputDevice* pOut = rOutliner.GetRefDevice();
927 0 : bool bNoStretching(false);
928 :
929 0 : if(pOut && pOut->GetOutDevType() == OUTDEV_PRINTER)
930 : {
931 : // check whether CharStretching is possible at all
932 0 : GDIMetaFile* pMtf = pOut->GetConnectMetaFile();
933 0 : OUString aTestString(static_cast<sal_Unicode>('J'));
934 :
935 0 : if(pMtf && (!pMtf->IsRecord() || pMtf->IsPause()))
936 0 : pMtf = NULL;
937 :
938 0 : if(pMtf)
939 0 : pMtf->Pause(true);
940 :
941 0 : Font aFontMerk(pOut->GetFont());
942 0 : Font aTmpFont( OutputDevice::GetDefaultFont( DEFAULTFONT_SERIF, LANGUAGE_SYSTEM, DEFAULTFONT_FLAGS_ONLYONE ) );
943 :
944 0 : aTmpFont.SetSize(Size(0,100));
945 0 : pOut->SetFont(aTmpFont);
946 0 : Size aSize1(pOut->GetTextWidth(aTestString), pOut->GetTextHeight());
947 0 : aTmpFont.SetSize(Size(800,100));
948 0 : pOut->SetFont(aTmpFont);
949 0 : Size aSize2(pOut->GetTextWidth(aTestString), pOut->GetTextHeight());
950 0 : pOut->SetFont(aFontMerk);
951 :
952 0 : if(pMtf)
953 0 : pMtf->Pause(false);
954 :
955 0 : bNoStretching = (aSize1 == aSize2);
956 :
957 : #ifdef WNT
958 : // Windows zooms the font proportionally when using Size(100,500),
959 : // we don't like that.
960 : if(aSize2.Height() >= aSize1.Height() * 2)
961 : {
962 : bNoStretching = true;
963 : }
964 : #endif
965 : }
966 0 : unsigned nLoopCount=0;
967 0 : bool bNoMoreLoop = false;
968 0 : long nXDiff0=0x7FFFFFFF;
969 0 : long nWantWdt=rShapeSize.Width();
970 0 : long nIsWdt=rTextSize.Width();
971 0 : if (nIsWdt==0) nIsWdt=1;
972 :
973 0 : long nWantHgt=rShapeSize.Height();
974 0 : long nIsHgt=rTextSize.Height();
975 0 : if (nIsHgt==0) nIsHgt=1;
976 :
977 0 : long nXTolPl=nWantWdt/100; // tolerance: +1%
978 0 : long nXTolMi=nWantWdt/25; // tolerance: -4%
979 0 : long nXKorr =nWantWdt/20; // correction scale: 5%
980 :
981 0 : long nX=(nWantWdt*100) /nIsWdt; // calculate X stretching
982 0 : long nY=(nWantHgt*100) /nIsHgt; // calculate Y stretching
983 0 : bool bChkX = true;
984 0 : if (bNoStretching) { // might only be be possible proportionally
985 0 : if (nX>nY) { nX=nY; bChkX=false; }
986 0 : else { nY=nX; }
987 : }
988 :
989 0 : while (nLoopCount<5 && !bNoMoreLoop) {
990 0 : if (nX<0) nX=-nX;
991 0 : if (nX<1) { nX=1; bNoMoreLoop = true; }
992 0 : if (nX>65535) { nX=65535; bNoMoreLoop = true; }
993 :
994 0 : if (nY<0) nY=-nY;
995 0 : if (nY<1) { nY=1; bNoMoreLoop = true; }
996 0 : if (nY>65535) { nY=65535; bNoMoreLoop = true; }
997 :
998 : // exception, there is no text yet (horizontal case)
999 0 : if(nIsWdt <= 1)
1000 : {
1001 0 : nX = nY;
1002 0 : bNoMoreLoop = true;
1003 : }
1004 :
1005 : // exception, there is no text yet (vertical case)
1006 0 : if(nIsHgt <= 1)
1007 : {
1008 0 : nY = nX;
1009 0 : bNoMoreLoop = true;
1010 : }
1011 :
1012 0 : rOutliner.SetGlobalCharStretching((sal_uInt16)nX,(sal_uInt16)nY);
1013 0 : nLoopCount++;
1014 0 : Size aSiz(rOutliner.CalcTextSize());
1015 0 : long nXDiff=aSiz.Width()-nWantWdt;
1016 0 : rFitXKorreg=Fraction(nWantWdt,aSiz.Width());
1017 0 : if (((nXDiff>=nXTolMi || !bChkX) && nXDiff<=nXTolPl) || nXDiff==nXDiff0) {
1018 0 : bNoMoreLoop = true;
1019 : } else {
1020 : // correct stretching factors
1021 0 : long nMul=nWantWdt;
1022 0 : long nDiv=aSiz.Width();
1023 0 : if (std::abs(nXDiff)<=2*nXKorr) {
1024 0 : if (nMul>nDiv) nDiv+=(nMul-nDiv)/2; // but only add half of what we calculated,
1025 0 : else nMul+=(nDiv-nMul)/2; // because the EditEngine calculates wrongly later on
1026 : }
1027 0 : nX=nX*nMul/nDiv;
1028 0 : if (bNoStretching) nY=nX;
1029 : }
1030 0 : nXDiff0=nXDiff;
1031 : }
1032 0 : }
1033 :
1034 0 : OUString SdrTextObj::TakeObjNameSingul() const
1035 : {
1036 0 : OUString aStr;
1037 :
1038 0 : switch(eTextKind)
1039 : {
1040 : case OBJ_OUTLINETEXT:
1041 : {
1042 0 : aStr = ImpGetResStr(STR_ObjNameSingulOUTLINETEXT);
1043 0 : break;
1044 : }
1045 :
1046 : case OBJ_TITLETEXT :
1047 : {
1048 0 : aStr = ImpGetResStr(STR_ObjNameSingulTITLETEXT);
1049 0 : break;
1050 : }
1051 :
1052 : default:
1053 : {
1054 0 : if(IsLinkedText())
1055 0 : aStr = ImpGetResStr(STR_ObjNameSingulTEXTLNK);
1056 : else
1057 0 : aStr = ImpGetResStr(STR_ObjNameSingulTEXT);
1058 0 : break;
1059 : }
1060 : }
1061 :
1062 0 : OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
1063 0 : if(pOutlinerParaObject && eTextKind != OBJ_OUTLINETEXT)
1064 : {
1065 : // shouldn't currently cause any problems at OUTLINETEXT
1066 0 : OUString aStr2(comphelper::string::stripStart(pOutlinerParaObject->GetTextObject().GetText(0), ' '));
1067 :
1068 : // avoid non expanded text portions in object name
1069 : // (second condition is new)
1070 0 : if(!aStr2.isEmpty() && aStr2.indexOf(sal_Unicode(255)) == -1)
1071 : {
1072 : // space between ResStr and content text
1073 0 : aStr += " ";
1074 :
1075 0 : aStr += "\'";
1076 :
1077 0 : if(aStr2.getLength() > 10)
1078 : {
1079 0 : aStr2 = aStr2.copy(0, 8);
1080 0 : aStr2 += "...";
1081 : }
1082 :
1083 0 : aStr += aStr2;
1084 0 : aStr += "\'";
1085 0 : }
1086 : }
1087 :
1088 0 : OUStringBuffer sName(aStr);
1089 :
1090 0 : OUString aName(GetName());
1091 0 : if (!aName.isEmpty())
1092 : {
1093 0 : sName.append(' ');
1094 0 : sName.append('\'');
1095 0 : sName.append(aName);
1096 0 : sName.append('\'');
1097 : }
1098 :
1099 0 : return sName.makeStringAndClear();
1100 : }
1101 :
1102 0 : OUString SdrTextObj::TakeObjNamePlural() const
1103 : {
1104 0 : OUString sName;
1105 0 : switch (eTextKind) {
1106 0 : case OBJ_OUTLINETEXT: sName=ImpGetResStr(STR_ObjNamePluralOUTLINETEXT); break;
1107 0 : case OBJ_TITLETEXT : sName=ImpGetResStr(STR_ObjNamePluralTITLETEXT); break;
1108 : default: {
1109 0 : if (IsLinkedText()) {
1110 0 : sName=ImpGetResStr(STR_ObjNamePluralTEXTLNK);
1111 : } else {
1112 0 : sName=ImpGetResStr(STR_ObjNamePluralTEXT);
1113 : }
1114 0 : } break;
1115 : } // switch
1116 0 : return sName;
1117 : }
1118 :
1119 0 : SdrTextObj* SdrTextObj::Clone() const
1120 : {
1121 0 : return CloneHelper< SdrTextObj >();
1122 : }
1123 :
1124 0 : SdrTextObj& SdrTextObj::operator=(const SdrTextObj& rObj)
1125 : {
1126 0 : if( this == &rObj )
1127 0 : return *this;
1128 : // call parent
1129 0 : SdrObject::operator=(rObj);
1130 :
1131 0 : aRect =rObj.aRect;
1132 0 : aGeo =rObj.aGeo;
1133 0 : eTextKind =rObj.eTextKind;
1134 0 : bTextFrame=rObj.bTextFrame;
1135 0 : aTextSize=rObj.aTextSize;
1136 0 : bTextSizeDirty=rObj.bTextSizeDirty;
1137 :
1138 : // Not all of the necessary parameters were copied yet.
1139 0 : bNoShear = rObj.bNoShear;
1140 0 : bNoRotate = rObj.bNoRotate;
1141 0 : bNoMirror = rObj.bNoMirror;
1142 0 : bDisableAutoWidthOnDragging = rObj.bDisableAutoWidthOnDragging;
1143 :
1144 0 : OutlinerParaObject* pNewOutlinerParaObject = 0;
1145 :
1146 0 : SdrText* pText = getActiveText();
1147 :
1148 0 : if( pText && rObj.HasText() )
1149 : {
1150 0 : const Outliner* pEO=rObj.pEdtOutl;
1151 0 : if (pEO!=NULL)
1152 : {
1153 0 : pNewOutlinerParaObject = pEO->CreateParaObject();
1154 : }
1155 : else
1156 : {
1157 0 : pNewOutlinerParaObject = new OutlinerParaObject(*rObj.getActiveText()->GetOutlinerParaObject());
1158 : }
1159 : }
1160 :
1161 0 : mpText->SetOutlinerParaObject( pNewOutlinerParaObject );
1162 0 : ImpSetTextStyleSheetListeners();
1163 0 : return *this;
1164 : }
1165 :
1166 0 : basegfx::B2DPolyPolygon SdrTextObj::TakeXorPoly() const
1167 : {
1168 0 : Polygon aPol(aRect);
1169 0 : if (aGeo.nShearWink!=0) ShearPoly(aPol,aRect.TopLeft(),aGeo.nTan);
1170 0 : if (aGeo.nDrehWink!=0) RotatePoly(aPol,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
1171 :
1172 0 : basegfx::B2DPolyPolygon aRetval;
1173 0 : aRetval.append(aPol.getB2DPolygon());
1174 0 : return aRetval;
1175 : }
1176 :
1177 0 : basegfx::B2DPolyPolygon SdrTextObj::TakeContour() const
1178 : {
1179 0 : basegfx::B2DPolyPolygon aRetval(SdrAttrObj::TakeContour());
1180 :
1181 : // and now add the BoundRect of the text, if necessary
1182 0 : if ( pModel && GetOutlinerParaObject() && !IsFontwork() && !IsContourTextFrame() )
1183 : {
1184 : // using Clone()-Paint() strategy inside TakeContour() leaves a destroyed
1185 : // SdrObject as pointer in DrawOutliner. Set *this again in fetching the outliner
1186 : // in every case
1187 0 : SdrOutliner& rOutliner=ImpGetDrawOutliner();
1188 :
1189 0 : Rectangle aAnchor2;
1190 0 : Rectangle aR;
1191 0 : TakeTextRect(rOutliner,aR,false,&aAnchor2);
1192 0 : rOutliner.Clear();
1193 0 : bool bFitToSize(IsFitToSize());
1194 0 : if (bFitToSize) aR=aAnchor2;
1195 0 : Polygon aPol(aR);
1196 0 : if (aGeo.nDrehWink!=0) RotatePoly(aPol,aR.TopLeft(),aGeo.nSin,aGeo.nCos);
1197 :
1198 0 : aRetval.append(aPol.getB2DPolygon());
1199 : }
1200 :
1201 0 : return aRetval;
1202 : }
1203 :
1204 0 : void SdrTextObj::RecalcSnapRect()
1205 : {
1206 0 : if (aGeo.nDrehWink!=0 || aGeo.nShearWink!=0) {
1207 0 : Polygon aPol(aRect);
1208 0 : if (aGeo.nShearWink!=0) ShearPoly(aPol,aRect.TopLeft(),aGeo.nTan);
1209 0 : if (aGeo.nDrehWink!=0) RotatePoly(aPol,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
1210 0 : maSnapRect=aPol.GetBoundRect();
1211 : } else {
1212 0 : maSnapRect=aRect;
1213 : }
1214 0 : }
1215 :
1216 0 : sal_uInt32 SdrTextObj::GetSnapPointCount() const
1217 : {
1218 0 : return 4L;
1219 : }
1220 :
1221 0 : Point SdrTextObj::GetSnapPoint(sal_uInt32 i) const
1222 : {
1223 0 : Point aP;
1224 0 : switch (i) {
1225 0 : case 0: aP=aRect.TopLeft(); break;
1226 0 : case 1: aP=aRect.TopRight(); break;
1227 0 : case 2: aP=aRect.BottomLeft(); break;
1228 0 : case 3: aP=aRect.BottomRight(); break;
1229 0 : default: aP=aRect.Center(); break;
1230 : }
1231 0 : if (aGeo.nShearWink!=0) ShearPoint(aP,aRect.TopLeft(),aGeo.nTan);
1232 0 : if (aGeo.nDrehWink!=0) RotatePoint(aP,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
1233 0 : return aP;
1234 : }
1235 :
1236 0 : void SdrTextObj::ImpCheckMasterCachable()
1237 : {
1238 0 : bNotMasterCachable=false;
1239 :
1240 0 : OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
1241 :
1242 0 : if(!bNotVisibleAsMaster && pOutlinerParaObject && pOutlinerParaObject->IsEditDoc() )
1243 : {
1244 0 : const EditTextObject& rText= pOutlinerParaObject->GetTextObject();
1245 0 : bNotMasterCachable=rText.HasField(SvxPageField::StaticClassId());
1246 0 : if( !bNotMasterCachable )
1247 : {
1248 0 : bNotMasterCachable=rText.HasField(SvxHeaderField::StaticClassId());
1249 0 : if( !bNotMasterCachable )
1250 : {
1251 0 : bNotMasterCachable=rText.HasField(SvxFooterField::StaticClassId());
1252 0 : if( !bNotMasterCachable )
1253 : {
1254 0 : bNotMasterCachable=rText.HasField(SvxDateTimeField::StaticClassId());
1255 : }
1256 : }
1257 : }
1258 : }
1259 0 : }
1260 :
1261 : // Extracted from ImpGetDrawOutliner()
1262 0 : void SdrTextObj::ImpInitDrawOutliner( SdrOutliner& rOutl ) const
1263 : {
1264 0 : rOutl.SetUpdateMode(false);
1265 0 : sal_uInt16 nOutlinerMode = OUTLINERMODE_OUTLINEOBJECT;
1266 0 : if ( !IsOutlText() )
1267 0 : nOutlinerMode = OUTLINERMODE_TEXTOBJECT;
1268 0 : rOutl.Init( nOutlinerMode );
1269 :
1270 0 : rOutl.SetGlobalCharStretching(100,100);
1271 0 : sal_uIntPtr nStat=rOutl.GetControlWord();
1272 0 : nStat&=~(EE_CNTRL_STRETCHING|EE_CNTRL_AUTOPAGESIZE);
1273 0 : rOutl.SetControlWord(nStat);
1274 0 : Size aNullSize;
1275 0 : Size aMaxSize(100000,100000);
1276 0 : rOutl.SetMinAutoPaperSize(aNullSize);
1277 0 : rOutl.SetMaxAutoPaperSize(aMaxSize);
1278 0 : rOutl.SetPaperSize(aMaxSize);
1279 0 : rOutl.ClearPolygon();
1280 0 : }
1281 :
1282 0 : SdrOutliner& SdrTextObj::ImpGetDrawOutliner() const
1283 : {
1284 0 : SdrOutliner& rOutl=pModel->GetDrawOutliner(this);
1285 :
1286 : // Code extracted to ImpInitDrawOutliner()
1287 0 : ImpInitDrawOutliner( rOutl );
1288 :
1289 0 : return rOutl;
1290 : }
1291 :
1292 : // Extracted from Paint()
1293 0 : void SdrTextObj::ImpSetupDrawOutlinerForPaint( bool bContourFrame,
1294 : SdrOutliner& rOutliner,
1295 : Rectangle& rTextRect,
1296 : Rectangle& rAnchorRect,
1297 : Rectangle& rPaintRect,
1298 : Fraction& rFitXKorreg ) const
1299 : {
1300 0 : if (!bContourFrame)
1301 : {
1302 : // FitToSize can't be used together with ContourFrame for now
1303 0 : if (IsFitToSize() || IsAutoFit())
1304 : {
1305 0 : sal_uIntPtr nStat=rOutliner.GetControlWord();
1306 0 : nStat|=EE_CNTRL_STRETCHING|EE_CNTRL_AUTOPAGESIZE;
1307 0 : rOutliner.SetControlWord(nStat);
1308 : }
1309 : }
1310 0 : rOutliner.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue());
1311 0 : TakeTextRect(rOutliner, rTextRect, false, &rAnchorRect);
1312 0 : rPaintRect = rTextRect;
1313 :
1314 0 : if (!bContourFrame)
1315 : {
1316 : // FitToSize can't be used together with ContourFrame for now
1317 0 : if (IsFitToSize())
1318 : {
1319 0 : ImpSetCharStretching(rOutliner,rTextRect.GetSize(),rAnchorRect.GetSize(),rFitXKorreg);
1320 0 : rPaintRect=rAnchorRect;
1321 : }
1322 0 : else if (IsAutoFit())
1323 : {
1324 0 : ImpAutoFitText(rOutliner);
1325 : }
1326 : }
1327 0 : }
1328 :
1329 0 : void SdrTextObj::ImpAutoFitText( SdrOutliner& rOutliner ) const
1330 : {
1331 0 : const Size aShapeSize=GetSnapRect().GetSize();
1332 : ImpAutoFitText( rOutliner,
1333 0 : Size(aShapeSize.Width()-GetTextLeftDistance()-GetTextRightDistance(),
1334 0 : aShapeSize.Height()-GetTextUpperDistance()-GetTextLowerDistance()),
1335 0 : IsVerticalWriting() );
1336 0 : }
1337 :
1338 0 : void SdrTextObj::ImpAutoFitText( SdrOutliner& rOutliner, const Size& rTextSize, bool bIsVerticalWriting )
1339 : {
1340 : // EditEngine formatting is unstable enough for
1341 : // line-breaking text that we need some more samples
1342 :
1343 : // loop early-exits if we detect an already attained value
1344 0 : sal_uInt16 nMinStretchX=0, nMinStretchY=0;
1345 0 : sal_uInt16 aOldStretchXVals[]={0,0,0,0,0,0,0,0,0,0};
1346 0 : const size_t aStretchArySize=SAL_N_ELEMENTS(aOldStretchXVals);
1347 0 : for(unsigned int i=0; i<aStretchArySize; ++i)
1348 : {
1349 0 : const Size aCurrTextSize = rOutliner.CalcTextSizeNTP();
1350 0 : double fFactor(1.0);
1351 0 : if( bIsVerticalWriting )
1352 0 : fFactor = double(rTextSize.Width())/aCurrTextSize.Width();
1353 : else
1354 0 : fFactor = double(rTextSize.Height())/aCurrTextSize.Height();
1355 : // fFactor scales in both x and y directions
1356 : // - this is fine for bulleted words
1357 : // - but it scales too much for a long paragraph
1358 : // - taking sqrt scales long paragraphs the best
1359 : // - bulleted words will have to go through more iterations
1360 0 : fFactor = std::sqrt(fFactor);
1361 :
1362 : sal_uInt16 nCurrStretchX, nCurrStretchY;
1363 0 : rOutliner.GetGlobalCharStretching(nCurrStretchX, nCurrStretchY);
1364 :
1365 0 : if (fFactor >= 1.0 )
1366 : {
1367 : // resulting text area fits into available shape rect -
1368 : // err on the larger stretching, to optimally fill area
1369 0 : nMinStretchX = std::max(nMinStretchX,nCurrStretchX);
1370 0 : nMinStretchY = std::max(nMinStretchY,nCurrStretchY);
1371 : }
1372 :
1373 0 : aOldStretchXVals[i] = nCurrStretchX;
1374 0 : if( std::find(aOldStretchXVals, aOldStretchXVals+i, nCurrStretchX) != aOldStretchXVals+i )
1375 0 : break; // same value already attained once; algo is looping, exit
1376 :
1377 0 : if (fFactor < 1.0 || (fFactor >= 1.0 && nCurrStretchX != 100))
1378 : {
1379 0 : nCurrStretchX = sal::static_int_cast<sal_uInt16>(nCurrStretchX*fFactor);
1380 0 : nCurrStretchY = sal::static_int_cast<sal_uInt16>(nCurrStretchY*fFactor);
1381 0 : rOutliner.SetGlobalCharStretching(std::min(sal_uInt16(100),nCurrStretchX),
1382 0 : std::min(sal_uInt16(100),nCurrStretchY));
1383 : OSL_TRACE("SdrTextObj::onEditOutlinerStatusEvent(): zoom is %d", nCurrStretchX);
1384 : }
1385 : }
1386 :
1387 : OSL_TRACE("---- SdrTextObj::onEditOutlinerStatusEvent(): final zoom is %d ----", nMinStretchX);
1388 0 : rOutliner.SetGlobalCharStretching(std::min(sal_uInt16(100),nMinStretchX),
1389 0 : std::min(sal_uInt16(100),nMinStretchY));
1390 0 : }
1391 :
1392 0 : void SdrTextObj::SetupOutlinerFormatting( SdrOutliner& rOutl, Rectangle& rPaintRect ) const
1393 : {
1394 0 : ImpInitDrawOutliner( rOutl );
1395 0 : UpdateOutlinerFormatting( rOutl, rPaintRect );
1396 0 : }
1397 :
1398 0 : void SdrTextObj::UpdateOutlinerFormatting( SdrOutliner& rOutl, Rectangle& rPaintRect ) const
1399 : {
1400 0 : Rectangle aTextRect;
1401 0 : Rectangle aAnchorRect;
1402 0 : Fraction aFitXKorreg(1,1);
1403 :
1404 0 : bool bContourFrame=IsContourTextFrame();
1405 :
1406 0 : if( GetModel() )
1407 : {
1408 : MapMode aMapMode(GetModel()->GetScaleUnit(), Point(0,0),
1409 0 : GetModel()->GetScaleFraction(),
1410 0 : GetModel()->GetScaleFraction());
1411 0 : rOutl.SetRefMapMode(aMapMode);
1412 : }
1413 :
1414 0 : ImpSetupDrawOutlinerForPaint( bContourFrame, rOutl, aTextRect, aAnchorRect, rPaintRect, aFitXKorreg );
1415 0 : }
1416 :
1417 :
1418 :
1419 0 : OutlinerParaObject* SdrTextObj::GetOutlinerParaObject() const
1420 : {
1421 0 : SdrText* pText = getActiveText();
1422 0 : if( pText )
1423 0 : return pText->GetOutlinerParaObject();
1424 : else
1425 0 : return 0;
1426 : }
1427 :
1428 0 : void SdrTextObj::NbcSetOutlinerParaObject(OutlinerParaObject* pTextObject)
1429 : {
1430 0 : NbcSetOutlinerParaObjectForText( pTextObject, getActiveText() );
1431 0 : }
1432 :
1433 0 : void SdrTextObj::NbcSetOutlinerParaObjectForText( OutlinerParaObject* pTextObject, SdrText* pText )
1434 : {
1435 0 : if( pText )
1436 0 : pText->SetOutlinerParaObject( pTextObject );
1437 :
1438 0 : if (pText && pText->GetOutlinerParaObject())
1439 : {
1440 0 : SvxWritingModeItem aWritingMode(pText->GetOutlinerParaObject()->IsVertical()
1441 : ? com::sun::star::text::WritingMode_TB_RL
1442 : : com::sun::star::text::WritingMode_LR_TB,
1443 0 : SDRATTR_TEXTDIRECTION);
1444 0 : GetProperties().SetObjectItemDirect(aWritingMode);
1445 : }
1446 :
1447 0 : SetTextSizeDirty();
1448 0 : if (IsTextFrame() && (IsAutoGrowHeight() || IsAutoGrowWidth()))
1449 : { // adapt text frame!
1450 0 : NbcAdjustTextFrameWidthAndHeight();
1451 : }
1452 0 : if (!IsTextFrame())
1453 : {
1454 : // the SnapRect keeps its size
1455 0 : SetRectsDirty(true);
1456 : }
1457 :
1458 : // always invalidate BoundRect on change
1459 0 : SetBoundRectDirty();
1460 0 : ActionChanged();
1461 :
1462 0 : ImpSetTextStyleSheetListeners();
1463 0 : ImpCheckMasterCachable();
1464 0 : }
1465 :
1466 0 : void SdrTextObj::NbcReformatText()
1467 : {
1468 0 : SdrText* pText = getActiveText();
1469 0 : if( pText && pText->GetOutlinerParaObject() )
1470 : {
1471 0 : pText->ReformatText();
1472 0 : if (bTextFrame)
1473 : {
1474 0 : NbcAdjustTextFrameWidthAndHeight();
1475 : }
1476 : else
1477 : {
1478 : // the SnapRect keeps its size
1479 0 : SetBoundRectDirty();
1480 0 : SetRectsDirty(true);
1481 : }
1482 0 : SetTextSizeDirty();
1483 0 : ActionChanged();
1484 : // i22396
1485 : // Necessary here since we have no compare operator at the outliner
1486 : // para object which may detect changes regarding the combination
1487 : // of outliner para data and configuration (e.g., change of
1488 : // formatting of text numerals)
1489 0 : GetViewContact().flushViewObjectContacts(false);
1490 : }
1491 0 : }
1492 :
1493 0 : void SdrTextObj::ReformatText()
1494 : {
1495 0 : if(GetOutlinerParaObject())
1496 : {
1497 0 : Rectangle aBoundRect0;
1498 0 : if (pUserCall!=NULL)
1499 0 : aBoundRect0=GetLastBoundRect();
1500 :
1501 0 : NbcReformatText();
1502 0 : SetChanged();
1503 0 : BroadcastObjectChange();
1504 0 : SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
1505 : }
1506 0 : }
1507 :
1508 0 : SdrObjGeoData* SdrTextObj::NewGeoData() const
1509 : {
1510 0 : return new SdrTextObjGeoData;
1511 : }
1512 :
1513 0 : void SdrTextObj::SaveGeoData(SdrObjGeoData& rGeo) const
1514 : {
1515 0 : SdrAttrObj::SaveGeoData(rGeo);
1516 0 : SdrTextObjGeoData& rTGeo=(SdrTextObjGeoData&)rGeo;
1517 0 : rTGeo.aRect =aRect;
1518 0 : rTGeo.aGeo =aGeo;
1519 0 : }
1520 :
1521 0 : void SdrTextObj::RestGeoData(const SdrObjGeoData& rGeo)
1522 : { // RectsDirty is called by SdrObject
1523 0 : SdrAttrObj::RestGeoData(rGeo);
1524 0 : SdrTextObjGeoData& rTGeo=(SdrTextObjGeoData&)rGeo;
1525 0 : NbcSetLogicRect(rTGeo.aRect);
1526 0 : aGeo =rTGeo.aGeo;
1527 0 : SetTextSizeDirty();
1528 0 : }
1529 :
1530 0 : SdrFitToSizeType SdrTextObj::GetFitToSize() const
1531 : {
1532 0 : SdrFitToSizeType eType = SDRTEXTFIT_NONE;
1533 :
1534 0 : if(!IsAutoGrowWidth())
1535 0 : eType = ((SdrTextFitToSizeTypeItem&)(GetObjectItem(SDRATTR_TEXT_FITTOSIZE))).GetValue();
1536 :
1537 0 : return eType;
1538 : }
1539 :
1540 0 : void SdrTextObj::ForceOutlinerParaObject()
1541 : {
1542 0 : SdrText* pText = getActiveText();
1543 0 : if( pText && (pText->GetOutlinerParaObject() == 0) )
1544 : {
1545 0 : sal_uInt16 nOutlMode = OUTLINERMODE_TEXTOBJECT;
1546 0 : if( IsTextFrame() && eTextKind == OBJ_OUTLINETEXT )
1547 0 : nOutlMode = OUTLINERMODE_OUTLINEOBJECT;
1548 :
1549 0 : pText->ForceOutlinerParaObject( nOutlMode );
1550 : }
1551 0 : }
1552 :
1553 0 : bool SdrTextObj::IsVerticalWriting() const
1554 : {
1555 0 : if(pEdtOutl)
1556 : {
1557 0 : return pEdtOutl->IsVertical();
1558 : }
1559 :
1560 0 : OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
1561 0 : if(pOutlinerParaObject)
1562 : {
1563 0 : return pOutlinerParaObject->IsVertical();
1564 : }
1565 :
1566 0 : return false;
1567 : }
1568 :
1569 0 : void SdrTextObj::SetVerticalWriting(bool bVertical)
1570 : {
1571 0 : OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
1572 0 : if( !pOutlinerParaObject && bVertical )
1573 : {
1574 : // we only need to force a outliner para object if the default of
1575 : // horizontal text is changed
1576 0 : ForceOutlinerParaObject();
1577 0 : pOutlinerParaObject = GetOutlinerParaObject();
1578 : }
1579 :
1580 0 : if( pOutlinerParaObject && (pOutlinerParaObject->IsVertical() != (bool)bVertical) )
1581 : {
1582 : // get item settings
1583 0 : const SfxItemSet& rSet = GetObjectItemSet();
1584 0 : bool bAutoGrowWidth = ((SdrTextAutoGrowWidthItem&)rSet.Get(SDRATTR_TEXT_AUTOGROWWIDTH)).GetValue();
1585 0 : bool bAutoGrowHeight = ((SdrTextAutoGrowHeightItem&)rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT)).GetValue();
1586 :
1587 : // Also exchange hor/ver adjust items
1588 0 : SdrTextHorzAdjust eHorz = ((SdrTextHorzAdjustItem&)(rSet.Get(SDRATTR_TEXT_HORZADJUST))).GetValue();
1589 0 : SdrTextVertAdjust eVert = ((SdrTextVertAdjustItem&)(rSet.Get(SDRATTR_TEXT_VERTADJUST))).GetValue();
1590 :
1591 : // rescue object size
1592 0 : Rectangle aObjectRect = GetSnapRect();
1593 :
1594 : // prepare ItemSet to set exchanged width and height items
1595 0 : SfxItemSet aNewSet(*rSet.GetPool(),
1596 : SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT,
1597 : // Expanded item ranges to also support hor and ver adjust.
1598 : SDRATTR_TEXT_VERTADJUST, SDRATTR_TEXT_VERTADJUST,
1599 : SDRATTR_TEXT_AUTOGROWWIDTH, SDRATTR_TEXT_HORZADJUST,
1600 0 : 0, 0);
1601 :
1602 0 : aNewSet.Put(rSet);
1603 0 : aNewSet.Put(SdrTextAutoGrowWidthItem(bAutoGrowHeight));
1604 0 : aNewSet.Put(SdrTextAutoGrowHeightItem(bAutoGrowWidth));
1605 :
1606 : // Exchange horz and vert adjusts
1607 0 : switch(eVert)
1608 : {
1609 0 : case SDRTEXTVERTADJUST_TOP: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); break;
1610 0 : case SDRTEXTVERTADJUST_CENTER: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER)); break;
1611 0 : case SDRTEXTVERTADJUST_BOTTOM: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT)); break;
1612 0 : case SDRTEXTVERTADJUST_BLOCK: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_BLOCK)); break;
1613 : }
1614 0 : switch(eHorz)
1615 : {
1616 0 : case SDRTEXTHORZADJUST_LEFT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM)); break;
1617 0 : case SDRTEXTHORZADJUST_CENTER: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER)); break;
1618 0 : case SDRTEXTHORZADJUST_RIGHT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP)); break;
1619 0 : case SDRTEXTHORZADJUST_BLOCK: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK)); break;
1620 : }
1621 :
1622 0 : SetObjectItemSet(aNewSet);
1623 :
1624 0 : pOutlinerParaObject = GetOutlinerParaObject();
1625 0 : if( pOutlinerParaObject )
1626 : {
1627 : // set ParaObject orientation accordingly
1628 0 : pOutlinerParaObject->SetVertical(bVertical);
1629 : }
1630 :
1631 : // restore object size
1632 0 : SetSnapRect(aObjectRect);
1633 : }
1634 0 : }
1635 :
1636 :
1637 :
1638 : // transformation interface for StarOfficeAPI. This implements support for
1639 : // homogeneous 3x3 matrices containing the transformation of the SdrObject. At the
1640 : // moment it contains a shearX, rotation and translation, but for setting all linear
1641 : // transforms like Scale, ShearX, ShearY, Rotate and Translate are supported.
1642 :
1643 :
1644 : // gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon
1645 : // with the base geometry and returns TRUE. Otherwise it returns FALSE.
1646 0 : bool SdrTextObj::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const
1647 : {
1648 : // get turn and shear
1649 0 : double fRotate = (aGeo.nDrehWink / 100.0) * F_PI180;
1650 0 : double fShearX = (aGeo.nShearWink / 100.0) * F_PI180;
1651 :
1652 : // get aRect, this is the unrotated snaprect
1653 0 : Rectangle aRectangle(aRect);
1654 :
1655 : // fill other values
1656 0 : basegfx::B2DTuple aScale(aRectangle.GetWidth(), aRectangle.GetHeight());
1657 0 : basegfx::B2DTuple aTranslate(aRectangle.Left(), aRectangle.Top());
1658 :
1659 : // position maybe relative to anchorpos, convert
1660 0 : if( pModel && pModel->IsWriter() )
1661 : {
1662 0 : if(GetAnchorPos().X() || GetAnchorPos().Y())
1663 : {
1664 0 : aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
1665 : }
1666 : }
1667 :
1668 : // force MapUnit to 100th mm
1669 0 : const SfxMapUnit eMapUnit(GetObjectMapUnit());
1670 0 : if(eMapUnit != SFX_MAPUNIT_100TH_MM)
1671 : {
1672 0 : switch(eMapUnit)
1673 : {
1674 : case SFX_MAPUNIT_TWIP :
1675 : {
1676 : // postion
1677 0 : aTranslate.setX(ImplTwipsToMM(aTranslate.getX()));
1678 0 : aTranslate.setY(ImplTwipsToMM(aTranslate.getY()));
1679 :
1680 : // size
1681 0 : aScale.setX(ImplTwipsToMM(aScale.getX()));
1682 0 : aScale.setY(ImplTwipsToMM(aScale.getY()));
1683 :
1684 0 : break;
1685 : }
1686 : default:
1687 : {
1688 : OSL_FAIL("TRGetBaseGeometry: Missing unit translation to 100th mm!");
1689 : }
1690 : }
1691 : }
1692 :
1693 : // build matrix
1694 0 : rMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
1695 : aScale,
1696 0 : basegfx::fTools::equalZero(fShearX) ? 0.0 : tan(fShearX),
1697 0 : basegfx::fTools::equalZero(fRotate) ? 0.0 : -fRotate,
1698 0 : aTranslate);
1699 :
1700 0 : return false;
1701 : }
1702 :
1703 : // sets the base geometry of the object using infos contained in the homogeneous 3x3 matrix.
1704 : // If it's an SdrPathObj it will use the provided geometry information. The Polygon has
1705 : // to use (0,0) as upper left and will be scaled to the given size in the matrix.
1706 0 : void SdrTextObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/)
1707 : {
1708 : // break up matrix
1709 0 : basegfx::B2DTuple aScale;
1710 0 : basegfx::B2DTuple aTranslate;
1711 0 : double fRotate(0.0);
1712 0 : double fShearX(0.0);
1713 0 : rMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
1714 :
1715 : // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
1716 : // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
1717 0 : if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
1718 : {
1719 0 : aScale.setX(fabs(aScale.getX()));
1720 0 : aScale.setY(fabs(aScale.getY()));
1721 0 : fRotate = fmod(fRotate + F_PI, F_2PI);
1722 : }
1723 :
1724 : // reset object shear and rotations
1725 0 : aGeo.nDrehWink = 0;
1726 0 : aGeo.RecalcSinCos();
1727 0 : aGeo.nShearWink = 0;
1728 0 : aGeo.RecalcTan();
1729 :
1730 : // force metric to pool metric
1731 0 : const SfxMapUnit eMapUnit(GetObjectMapUnit());
1732 0 : if(eMapUnit != SFX_MAPUNIT_100TH_MM)
1733 : {
1734 0 : switch(eMapUnit)
1735 : {
1736 : case SFX_MAPUNIT_TWIP :
1737 : {
1738 : // position
1739 0 : aTranslate.setX(ImplMMToTwips(aTranslate.getX()));
1740 0 : aTranslate.setY(ImplMMToTwips(aTranslate.getY()));
1741 :
1742 : // size
1743 0 : aScale.setX(ImplMMToTwips(aScale.getX()));
1744 0 : aScale.setY(ImplMMToTwips(aScale.getY()));
1745 :
1746 0 : break;
1747 : }
1748 : default:
1749 : {
1750 : OSL_FAIL("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
1751 : }
1752 : }
1753 : }
1754 :
1755 : // if anchor is used, make position relative to it
1756 0 : if( pModel && pModel->IsWriter() )
1757 : {
1758 0 : if(GetAnchorPos().X() || GetAnchorPos().Y())
1759 : {
1760 0 : aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
1761 : }
1762 : }
1763 :
1764 : // build and set BaseRect (use scale)
1765 0 : Point aPoint = Point();
1766 0 : Size aSize(FRound(aScale.getX()), FRound(aScale.getY()));
1767 0 : Rectangle aBaseRect(aPoint, aSize);
1768 0 : SetSnapRect(aBaseRect);
1769 :
1770 : // shear?
1771 0 : if(!basegfx::fTools::equalZero(fShearX))
1772 : {
1773 0 : GeoStat aGeoStat;
1774 0 : aGeoStat.nShearWink = FRound((atan(fShearX) / F_PI180) * 100.0);
1775 0 : aGeoStat.RecalcTan();
1776 0 : Shear(Point(), aGeoStat.nShearWink, aGeoStat.nTan, false);
1777 : }
1778 :
1779 : // rotation?
1780 0 : if(!basegfx::fTools::equalZero(fRotate))
1781 : {
1782 0 : GeoStat aGeoStat;
1783 :
1784 : // #i78696#
1785 : // fRotate is matematically correct, but aGeoStat.nDrehWink is
1786 : // mirrored -> mirror value here
1787 0 : aGeoStat.nDrehWink = NormAngle360(FRound(-fRotate / F_PI18000));
1788 0 : aGeoStat.RecalcSinCos();
1789 0 : Rotate(Point(), aGeoStat.nDrehWink, aGeoStat.nSin, aGeoStat.nCos);
1790 : }
1791 :
1792 : // translate?
1793 0 : if(!aTranslate.equalZero())
1794 : {
1795 0 : Move(Size(FRound(aTranslate.getX()), FRound(aTranslate.getY())));
1796 0 : }
1797 0 : }
1798 :
1799 0 : bool SdrTextObj::IsRealyEdited() const
1800 : {
1801 0 : return pEdtOutl && pEdtOutl->IsModified();
1802 : }
1803 :
1804 :
1805 : // moved inlines here form hxx
1806 :
1807 0 : long SdrTextObj::GetEckenradius() const
1808 : {
1809 0 : return ((SdrEckenradiusItem&)(GetObjectItemSet().Get(SDRATTR_ECKENRADIUS))).GetValue();
1810 : }
1811 :
1812 0 : long SdrTextObj::GetMinTextFrameHeight() const
1813 : {
1814 0 : return ((SdrTextMinFrameHeightItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_MINFRAMEHEIGHT))).GetValue();
1815 : }
1816 :
1817 0 : long SdrTextObj::GetMaxTextFrameHeight() const
1818 : {
1819 0 : return ((SdrTextMaxFrameHeightItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_MAXFRAMEHEIGHT))).GetValue();
1820 : }
1821 :
1822 0 : long SdrTextObj::GetMinTextFrameWidth() const
1823 : {
1824 0 : return ((SdrTextMinFrameWidthItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_MINFRAMEWIDTH))).GetValue();
1825 : }
1826 :
1827 0 : long SdrTextObj::GetMaxTextFrameWidth() const
1828 : {
1829 0 : return ((SdrTextMaxFrameWidthItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_MAXFRAMEWIDTH))).GetValue();
1830 : }
1831 :
1832 0 : bool SdrTextObj::IsFontwork() const
1833 : {
1834 : return (bTextFrame) ? false // Default is FALSE
1835 0 : : ((XFormTextStyleItem&)(GetObjectItemSet().Get(XATTR_FORMTXTSTYLE))).GetValue()!=XFT_NONE;
1836 : }
1837 :
1838 0 : bool SdrTextObj::IsHideContour() const
1839 : {
1840 : return (bTextFrame) ? false // Default is: no, don't HideContour; HideContour not together with TextFrames
1841 0 : : ((XFormTextHideFormItem&)(GetObjectItemSet().Get(XATTR_FORMTXTHIDEFORM))).GetValue();
1842 : }
1843 :
1844 0 : bool SdrTextObj::IsContourTextFrame() const
1845 : {
1846 : return (bTextFrame) ? false // ContourFrame not together with normal TextFrames
1847 0 : : ((SdrTextContourFrameItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_CONTOURFRAME))).GetValue();
1848 : }
1849 :
1850 0 : long SdrTextObj::GetTextLeftDistance() const
1851 : {
1852 0 : return ((SdrTextLeftDistItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_LEFTDIST))).GetValue();
1853 : }
1854 :
1855 0 : long SdrTextObj::GetTextRightDistance() const
1856 : {
1857 0 : return ((SdrTextRightDistItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_RIGHTDIST))).GetValue();
1858 : }
1859 :
1860 0 : long SdrTextObj::GetTextUpperDistance() const
1861 : {
1862 0 : return ((SdrTextUpperDistItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_UPPERDIST))).GetValue();
1863 : }
1864 :
1865 0 : long SdrTextObj::GetTextLowerDistance() const
1866 : {
1867 0 : return ((SdrTextLowerDistItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_LOWERDIST))).GetValue();
1868 : }
1869 :
1870 0 : SdrTextAniKind SdrTextObj::GetTextAniKind() const
1871 : {
1872 0 : return ((SdrTextAniKindItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_ANIKIND))).GetValue();
1873 : }
1874 :
1875 0 : SdrTextAniDirection SdrTextObj::GetTextAniDirection() const
1876 : {
1877 0 : return ((SdrTextAniDirectionItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue();
1878 : }
1879 :
1880 : // Get necessary data for text scroll animation. ATM base it on a Text-Metafile and a
1881 : // painting rectangle. Rotation is excluded from the returned values.
1882 0 : GDIMetaFile* SdrTextObj::GetTextScrollMetaFileAndRectangle(
1883 : Rectangle& rScrollRectangle, Rectangle& rPaintRectangle)
1884 : {
1885 0 : GDIMetaFile* pRetval = 0L;
1886 0 : SdrOutliner& rOutliner = ImpGetDrawOutliner();
1887 0 : Rectangle aTextRect;
1888 0 : Rectangle aAnchorRect;
1889 0 : Rectangle aPaintRect;
1890 0 : Fraction aFitXKorreg(1,1);
1891 0 : bool bContourFrame(IsContourTextFrame());
1892 :
1893 : // get outliner set up. To avoid getting a somehow rotated MetaFile,
1894 : // temporarily disable object rotation.
1895 0 : sal_Int32 nAngle(aGeo.nDrehWink);
1896 0 : aGeo.nDrehWink = 0L;
1897 0 : ImpSetupDrawOutlinerForPaint( bContourFrame, rOutliner, aTextRect, aAnchorRect, aPaintRect, aFitXKorreg );
1898 0 : aGeo.nDrehWink = nAngle;
1899 :
1900 0 : Rectangle aScrollFrameRect(aPaintRect);
1901 0 : const SfxItemSet& rSet = GetObjectItemSet();
1902 0 : SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue();
1903 :
1904 0 : if(SDRTEXTANI_LEFT == eDirection || SDRTEXTANI_RIGHT == eDirection)
1905 : {
1906 0 : aScrollFrameRect.Left() = aAnchorRect.Left();
1907 0 : aScrollFrameRect.Right() = aAnchorRect.Right();
1908 : }
1909 :
1910 0 : if(SDRTEXTANI_UP == eDirection || SDRTEXTANI_DOWN == eDirection)
1911 : {
1912 0 : aScrollFrameRect.Top() = aAnchorRect.Top();
1913 0 : aScrollFrameRect.Bottom() = aAnchorRect.Bottom();
1914 : }
1915 :
1916 : // create the MetaFile
1917 0 : pRetval = new GDIMetaFile;
1918 0 : VirtualDevice aBlackHole;
1919 0 : aBlackHole.EnableOutput(false);
1920 0 : pRetval->Record(&aBlackHole);
1921 0 : Point aPaintPos = aPaintRect.TopLeft();
1922 :
1923 0 : rOutliner.Draw(&aBlackHole, aPaintPos);
1924 :
1925 0 : pRetval->Stop();
1926 0 : pRetval->WindStart();
1927 :
1928 : // return PaintRectanglePixel and pRetval;
1929 0 : rScrollRectangle = aScrollFrameRect;
1930 0 : rPaintRectangle = aPaintRect;
1931 :
1932 0 : return pRetval;
1933 : }
1934 :
1935 : // Access to TextAnimationAllowed flag
1936 0 : bool SdrTextObj::IsAutoFit() const
1937 : {
1938 0 : return GetFitToSize()==SDRTEXTFIT_AUTOFIT;
1939 : }
1940 :
1941 0 : bool SdrTextObj::IsFitToSize() const
1942 : {
1943 0 : const SdrFitToSizeType eFit=GetFitToSize();
1944 0 : return (eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES);
1945 : }
1946 :
1947 0 : void SdrTextObj::SetTextAnimationAllowed(bool bNew)
1948 : {
1949 0 : if(mbTextAnimationAllowed != bNew)
1950 : {
1951 0 : mbTextAnimationAllowed = bNew;
1952 0 : ActionChanged();
1953 : }
1954 0 : }
1955 :
1956 : /** called from the SdrObjEditView during text edit when the status of the edit outliner changes */
1957 0 : void SdrTextObj::onEditOutlinerStatusEvent( EditStatus* pEditStatus )
1958 : {
1959 0 : const sal_uInt32 nStat = pEditStatus->GetStatusWord();
1960 0 : const bool bGrowX=(nStat & EE_STAT_TEXTWIDTHCHANGED) !=0;
1961 0 : const bool bGrowY=(nStat & EE_STAT_TEXTHEIGHTCHANGED) !=0;
1962 0 : if(bTextFrame && (bGrowX || bGrowY))
1963 : {
1964 0 : if ((bGrowX && IsAutoGrowWidth()) || (bGrowY && IsAutoGrowHeight()))
1965 : {
1966 0 : AdjustTextFrameWidthAndHeight();
1967 : }
1968 0 : else if (IsAutoFit() && !mbInDownScale)
1969 : {
1970 : OSL_ASSERT(pEdtOutl);
1971 0 : mbInDownScale = true;
1972 :
1973 : // sucks that we cannot disable paints via
1974 : // pEdtOutl->SetUpdateMode(FALSE) - but EditEngine skips
1975 : // formatting as well, then.
1976 0 : ImpAutoFitText(*pEdtOutl);
1977 0 : mbInDownScale = false;
1978 : }
1979 : }
1980 0 : }
1981 :
1982 : /** returns the currently active text. */
1983 0 : SdrText* SdrTextObj::getActiveText() const
1984 : {
1985 0 : if( !mpText )
1986 0 : return getText( 0 );
1987 : else
1988 0 : return mpText;
1989 : }
1990 :
1991 : /** returns the nth available text. */
1992 0 : SdrText* SdrTextObj::getText( sal_Int32 nIndex ) const
1993 : {
1994 0 : if( nIndex == 0 )
1995 : {
1996 0 : if( mpText == 0 )
1997 0 : const_cast< SdrTextObj* >(this)->mpText = new SdrText( *(const_cast< SdrTextObj* >(this)) );
1998 0 : return mpText;
1999 : }
2000 : else
2001 : {
2002 0 : return 0;
2003 : }
2004 : }
2005 :
2006 : /** returns the number of texts available for this object. */
2007 0 : sal_Int32 SdrTextObj::getTextCount() const
2008 : {
2009 0 : return 1;
2010 : }
2011 :
2012 : /** changes the current active text */
2013 0 : void SdrTextObj::setActiveText( sal_Int32 /*nIndex*/ )
2014 : {
2015 0 : }
2016 :
2017 : /** returns the index of the text that contains the given point or -1 */
2018 0 : sal_Int32 SdrTextObj::CheckTextHit(const Point& /*rPnt*/) const
2019 : {
2020 0 : return 0;
2021 : }
2022 :
2023 0 : void SdrTextObj::SetObjectItemNoBroadcast(const SfxPoolItem& rItem)
2024 : {
2025 0 : static_cast< sdr::properties::TextProperties& >(GetProperties()).SetObjectItemNoBroadcast(rItem);
2026 0 : }
2027 :
2028 :
2029 :
2030 : // The concept of the text object:
2031 : // ~~~~~~~~~~~~~~~~~~~~~~~~
2032 : // Attributes/Variations:
2033 : // - bool text frame / graphics object with caption
2034 : // - bool FontWork (if it is not a text frame and not a ContourTextFrame)
2035 : // - bool ContourTextFrame (if it is not a text frame and not Fontwork)
2036 : // - long rotation angle (if it is not FontWork)
2037 : // - long text frame margins (if it is not FontWork)
2038 : // - bool FitToSize (if it is not FontWork)
2039 : // - bool AutoGrowingWidth/Height (if it is not FitToSize and not FontWork)
2040 : // - long Min/MaxFrameWidth/Height (if AutoGrowingWidth/Height)
2041 : // - enum horizontal text anchoring left,center,right,justify/block,Stretch(ni)
2042 : // - enum vertical text anchoring top, middle, bottom, block, stretch(ni)
2043 : // - enum ticker text (if it is not FontWork)
2044 :
2045 : // Every derived object is either a text frame (bTextFrame=true)
2046 : // or a drawing object with a caption (bTextFrame=false).
2047 :
2048 : // Default anchoring for text frames:
2049 : // SDRTEXTHORZADJUST_BLOCK, SDRTEXTVERTADJUST_TOP
2050 : // = static Pool defaults
2051 : // Default anchoring for drawing objects with a caption:
2052 : // SDRTEXTHORZADJUST_CENTER, SDRTEXTVERTADJUST_CENTER
2053 : // via "hard" attribution of SdrAttrObj
2054 :
2055 : // Every object derived from SdrTextObj must return an "UnrotatedSnapRect"
2056 : // (->TakeUnrotatedSnapRect()) (the reference point for the rotation is the top
2057 : // left of the rectangle (aGeo.nDrehWink)) which is the basis for anchoring
2058 : // text. We then subtract the text frame margins from this rectangle, as a re-
2059 : // sult we get the anchoring area (->TakeTextAnchorRect()). Within this area, we
2060 : // calculate the anchoring point and the painting area, depending on the hori-
2061 : // zontal and vertical adjustment of the text (SdrTextVertAdjust,
2062 : // SdrTextHorzAdjust).
2063 : // In the case of drawing objects with a caption the painting area might well
2064 : // be larger than the anchoring area, for text frames on the other hand, it is
2065 : // always of the same or a smaller size (except when there are negative text
2066 : // frame margins).
2067 :
2068 : // FitToSize takes priority over text anchoring and AutoGrowHeight/Width. When
2069 : // FitToSize is turned on, the painting area is always equal to the anchoring
2070 : // area. Additionally, FitToSize doesn't allow automatic line breaks.
2071 :
2072 : // ContourTextFrame:
2073 : // - long rotation angle
2074 : // - long text frame margins (maybe later)
2075 : // - bool FitToSize (maybe later)
2076 : // - bool AutoGrowingWidth/Height (maybe much later)
2077 : // - long Min/MaxFrameWidth/Height (maybe much later)
2078 : // - enum horizontal text anchoring (maybe later, for now: left, centered)
2079 : // - enum vertical text anchoring (maybe later, for now: top)
2080 : // - enum ticker text (maybe later, maybe even with correct clipping)
2081 :
2082 : // When making changes, check these:
2083 : // - Paint
2084 : // - HitTest
2085 : // - ConvertToPoly
2086 : // - Edit
2087 : // - Printing, Saving, Painting in neighboring View while editing
2088 : // - ModelChanged (e. g. through a neighboring View or rulers) while editing
2089 : // - FillColorChanged while editin
2090 : // - and many more...
2091 :
2092 :
2093 :
2094 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|