Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 192, column 9
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ruler.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SVT_DLLIMPLEMENTATION -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/svtools/source/inc -I /home/maarten/src/libreoffice/core/svtools/inc -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/svtools/source/control/ruler.cxx

/home/maarten/src/libreoffice/core/svtools/source/control/ruler.cxx

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 <tools/debug.hxx>
21#include <tools/poly.hxx>
22#include <vcl/event.hxx>
23#include <vcl/settings.hxx>
24#include <vcl/vcllayout.hxx>
25#include <vcl/virdev.hxx>
26#include <vcl/ptrstyle.hxx>
27#include <sal/log.hxx>
28
29#include <svtools/ruler.hxx>
30#include <svtools/svtresid.hxx>
31#include <svtools/strings.hrc>
32#include <svtools/colorcfg.hxx>
33#include "accessibleruler.hxx"
34
35#include <memory>
36#include <vector>
37
38using namespace std;
39using namespace ::com::sun::star;
40using namespace ::com::sun::star::uno;
41using namespace ::com::sun::star::lang;
42using namespace ::com::sun::star::accessibility;
43
44#define RULER_OFF3 3
45#define RULER_RESIZE_OFF4 4
46#define RULER_MIN_SIZE3 3
47
48#define RULER_VAR_SIZE8 8
49
50#define RULER_UPDATE_LINES0x01 0x01
51
52#define RULER_CLIP150 150
53
54#define RULER_UNIT_MM0 0
55#define RULER_UNIT_CM1 1
56#define RULER_UNIT_M2 2
57#define RULER_UNIT_KM3 3
58#define RULER_UNIT_INCH4 4
59#define RULER_UNIT_FOOT5 5
60#define RULER_UNIT_MILE6 6
61#define RULER_UNIT_POINT7 7
62#define RULER_UNIT_PICA8 8
63#define RULER_UNIT_CHAR9 9
64#define RULER_UNIT_LINE10 10
65#define RULER_UNIT_COUNT11 11
66
67namespace
68{
69/**
70 * Pre-calculates glyph items for rText on rRenderContext. Subsequent calls
71 * avoid the calculation and just return a pointer to rTextGlyphs.
72 */
73SalLayoutGlyphs* lcl_GetRulerTextGlyphs(const vcl::RenderContext& rRenderContext, const OUString& rText,
74 SalLayoutGlyphs& rTextGlyphs)
75{
76 if (rTextGlyphs.IsValid())
77 // Use pre-calculated result.
78 return &rTextGlyphs;
79
80 // Calculate glyph items.
81
82 std::unique_ptr<SalLayout> pLayout = rRenderContext.ImplLayout(
83 rText, 0, rText.getLength(), Point(0, 0), 0, nullptr, SalLayoutFlags::GlyphItemsOnly);
84 if (!pLayout)
85 return nullptr;
86
87 const SalLayoutGlyphs* pGlyphs = pLayout->GetGlyphs();
88 if (!pGlyphs)
89 return nullptr;
90
91 // Remember the calculation result.
92 rTextGlyphs = *pGlyphs;
93
94 return &rTextGlyphs;
95}
96}
97
98class ImplRulerData
99{
100 friend class Ruler;
101
102private:
103 vector<RulerLine> pLines;
104 vector<RulerBorder> pBorders;
105 vector<RulerIndent> pIndents;
106 vector<RulerTab> pTabs;
107
108 long nNullVirOff;
109 long nRulVirOff;
110 long nRulWidth;
111 long nPageOff;
112 long nPageWidth;
113 long nNullOff;
114 long nMargin1;
115 long nMargin2;
116 // In this context, "frame margin" means paragraph margins (indents)
117 long nLeftFrameMargin;
118 long nRightFrameMargin;
119 RulerMarginStyle nMargin1Style;
120 RulerMarginStyle nMargin2Style;
121 bool bAutoPageWidth;
122 bool bTextRTL;
123
124public:
125 ImplRulerData();
126};
127
128ImplRulerData::ImplRulerData() :
129 nNullVirOff (0),
130 nRulVirOff (0),
131 nRulWidth (0),
132 nPageOff (0),
133 nPageWidth (0),
134 nNullOff (0),
135 nMargin1 (0),
136 nMargin2 (0),
137 nLeftFrameMargin (0),
138 nRightFrameMargin (0),
139 nMargin1Style (RulerMarginStyle::NONE),
140 nMargin2Style (RulerMarginStyle::NONE),
141 bAutoPageWidth (true), // Page width == EditWin width
142 bTextRTL (false)
143{
144}
145
146const RulerUnitData aImplRulerUnitTab[RULER_UNIT_COUNT11] =
147{
148{ MapUnit::Map100thMM, 100, 25.0, 25.0, 50.0, 100.0, " mm" }, // MM
149{ MapUnit::Map100thMM, 1000, 100.0, 500.0, 1000.0, 1000.0, " cm" }, // CM
150{ MapUnit::MapMM, 1000, 10.0, 250.0, 500.0, 1000.0, " m" }, // M
151{ MapUnit::MapCM, 100000, 12500.0, 25000.0, 50000.0, 100000.0, " km" }, // KM
152{ MapUnit::Map1000thInch, 1000, 62.5, 125.0, 500.0, 1000.0, "\"" }, // INCH
153{ MapUnit::Map100thInch, 1200, 120.0, 120.0, 600.0, 1200.0, "'" }, // FOOT
154{ MapUnit::Map10thInch, 633600, 63360.0, 63360.0, 316800.0, 633600.0, " miles" }, // MILE
155{ MapUnit::MapPoint, 1, 12.0, 12.0, 12.0, 36.0, " pt" }, // POINT
156{ MapUnit::Map100thMM, 423, 423.0, 423.0, 423.0, 846.0, " pc" }, // PICA
157{ MapUnit::Map100thMM, 371, 371.0, 371.0, 371.0, 743.0, " ch" }, // CHAR
158{ MapUnit::Map100thMM, 551, 551.0, 551.0, 551.0, 1102.0, " li" } // LINE
159};
160
161static RulerTabData ruler_tab =
162{
163 0, // DPIScaleFactor to be set
164 7, // ruler_tab_width
165 6, // ruler_tab_height
166 2, // ruler_tab_height2
167 2, // ruler_tab_width2
168 8, // ruler_tab_cwidth
169 4, // ruler_tab_cwidth2
170 4, // ruler_tab_cwidth3
171 2, // ruler_tab_cwidth4
172 4, // ruler_tab_dheight
173 1, // ruler_tab_dheight2
174 5, // ruler_tab_dwidth
175 3, // ruler_tab_dwidth2
176 3, // ruler_tab_dwidth3
177 1, // ruler_tab_dwidth4
178 5 // ruler_tab_textoff
179};
180
181void Ruler::ImplInit( WinBits nWinBits )
182{
183 // Set default WinBits
184 if ( !(nWinBits & WB_VERT) )
185 {
186 nWinBits |= WB_HORZ;
187
188 // RTL: no UI mirroring for horizontal rulers, because
189 // the document is also not mirrored
190 EnableRTL( false );
191 }
192
193 // Initialize variables
194 mnWinStyle = nWinBits; // Window-Style
195 mnBorderOff = 0; // Border-Offset
196 mnWinOff = 0; // EditWinOffset
197 mnWinWidth = 0; // EditWinWidth
198 mnWidth = 0; // Window width
199 mnHeight = 0; // Window height
200 mnVirOff = 0; // Offset of VirtualDevice from top-left corner
201 mnVirWidth = 0; // width or height from VirtualDevice
202 mnVirHeight = 0; // height of width from VirtualDevice
203 mnDragPos = 0; // Drag-Position (Null point)
204 mnDragAryPos = 0; // Drag-Array-Index
205 mnDragSize = RulerDragSize::Move; // Did size change at dragging
206 mnDragModifier = 0; // Modifier key at dragging
207 mnExtraStyle = 0; // Style of Extra field
208 mnCharWidth = 371;
209 mnLineHeight = 551;
210 mbCalc = true; // Should recalculate page width
211 mbFormat = true; // Should redraw
212 mbDrag = false; // Currently at dragging
213 mbDragDelete = false; // Has mouse left the dragging area
214 mbDragCanceled = false; // Dragging cancelled?
215 mbAutoWinWidth = true; // EditWinWidth == RulerWidth
216 mbActive = true; // Is ruler active
217 mnUpdateFlags = 0; // What needs to be updated
218 mpData = mpSaveData.get(); // Pointer to normal data
219 meExtraType = RulerExtra::DontKnow; // What is in extra field
220 meDragType = RulerType::DontKnow; // Which element is dragged
221
222 // Initialize Units
223 mnUnitIndex = RULER_UNIT_CM1;
224 meUnit = FieldUnit::CM;
225 maZoom = Fraction( 1, 1 );
226
227 // Recalculate border widths
228 if ( nWinBits & WB_BORDER )
229 mnBorderWidth = 1;
230 else
231 mnBorderWidth = 0;
232
233 // Settings
234 ImplInitSettings( true, true, true );
235
236 // Setup the default size
237 tools::Rectangle aRect;
238 GetTextBoundRect( aRect, "0123456789" );
239 long nDefHeight = aRect.GetHeight() + RULER_OFF3 * 2 + ruler_tab.textoff * 2 + mnBorderWidth;
240
241 Size aDefSize;
242 if ( nWinBits & WB_HORZ )
243 aDefSize.setHeight( nDefHeight );
244 else
245 aDefSize.setWidth( nDefHeight );
246 SetOutputSizePixel( aDefSize );
247 SetType(WindowType::RULER);
248}
249
250Ruler::Ruler( vcl::Window* pParent, WinBits nWinStyle ) :
251 Window( pParent, nWinStyle & WB_3DLOOK ),
252 maVirDev( VclPtr<VirtualDevice>::Create(*this) ),
253 maMapMode( MapUnit::Map100thMM ),
254 mpSaveData(new ImplRulerData),
255 mpData(nullptr),
256 mpDragData(new ImplRulerData)
257{
258 // Check to see if the ruler constructor has
259 // already been called before otherwise
260 // we end up with over-scaled elements
261 if (ruler_tab.DPIScaleFactor == 0)
262 {
263 ruler_tab.DPIScaleFactor = GetDPIScaleFactor();
264 ruler_tab.width *= ruler_tab.DPIScaleFactor;
265 ruler_tab.height *= ruler_tab.DPIScaleFactor;
266 ruler_tab.height2 *= ruler_tab.DPIScaleFactor;
267 ruler_tab.width2 *= ruler_tab.DPIScaleFactor;
268 ruler_tab.cwidth *= ruler_tab.DPIScaleFactor;
269 ruler_tab.cwidth2 *= ruler_tab.DPIScaleFactor;
270 ruler_tab.cwidth3 *= ruler_tab.DPIScaleFactor;
271 ruler_tab.cwidth4 *= ruler_tab.DPIScaleFactor;
272 ruler_tab.dheight *= ruler_tab.DPIScaleFactor;
273 ruler_tab.dheight2 *= ruler_tab.DPIScaleFactor;
274 ruler_tab.dwidth *= ruler_tab.DPIScaleFactor;
275 ruler_tab.dwidth2 *= ruler_tab.DPIScaleFactor;
276 ruler_tab.dwidth3 *= ruler_tab.DPIScaleFactor;
277 ruler_tab.dwidth4 *= ruler_tab.DPIScaleFactor;
278 ruler_tab.textoff *= ruler_tab.DPIScaleFactor;
279 }
280
281
282 ImplInit( nWinStyle );
283}
284
285Ruler::~Ruler()
286{
287 disposeOnce();
288}
1
Calling '~ScopedVclPtr'
289
290void Ruler::dispose()
291{
292 mpSaveData.reset();
293 mpDragData.reset();
294 mxAccContext.clear();
295 Window::dispose();
296}
297
298void Ruler::ImplVDrawLine(vcl::RenderContext& rRenderContext, long nX1, long nY1, long nX2, long nY2)
299{
300 if ( nX1 < -RULER_CLIP150 )
301 {
302 nX1 = -RULER_CLIP150;
303 if ( nX2 < -RULER_CLIP150 )
304 return;
305 }
306 long nClip = mnVirWidth + RULER_CLIP150;
307 if ( nX2 > nClip )
308 {
309 nX2 = nClip;
310 if ( nX1 > nClip )
311 return;
312 }
313
314 if ( mnWinStyle & WB_HORZ )
315 rRenderContext.DrawLine( Point( nX1, nY1 ), Point( nX2, nY2 ) );
316 else
317 rRenderContext.DrawLine( Point( nY1, nX1 ), Point( nY2, nX2 ) );
318}
319
320void Ruler::ImplVDrawRect(vcl::RenderContext& rRenderContext, long nX1, long nY1, long nX2, long nY2)
321{
322 if ( nX1 < -RULER_CLIP150 )
323 {
324 nX1 = -RULER_CLIP150;
325 if ( nX2 < -RULER_CLIP150 )
326 return;
327 }
328 long nClip = mnVirWidth + RULER_CLIP150;
329 if ( nX2 > nClip )
330 {
331 nX2 = nClip;
332 if ( nX1 > nClip )
333 return;
334 }
335
336 if ( mnWinStyle & WB_HORZ )
337 rRenderContext.DrawRect(tools::Rectangle(nX1, nY1, nX2, nY2));
338 else
339 rRenderContext.DrawRect(tools::Rectangle(nY1, nX1, nY2, nX2));
340}
341
342void Ruler::ImplVDrawText(vcl::RenderContext& rRenderContext, long nX, long nY, const OUString& rText, long nMin, long nMax)
343{
344 tools::Rectangle aRect;
345 SalLayoutGlyphs* pTextLayout
346 = lcl_GetRulerTextGlyphs(rRenderContext, rText, maTextGlyphs[rText]);
347 rRenderContext.GetTextBoundRect(aRect, rText, 0, 0, -1, 0, nullptr, pTextLayout);
348
349 long nShiftX = ( aRect.GetWidth() / 2 ) + aRect.Left();
350 long nShiftY = ( aRect.GetHeight() / 2 ) + aRect.Top();
351
352 if ( (nX > -RULER_CLIP150) && (nX < mnVirWidth + RULER_CLIP150) && ( nX < nMax - nShiftX ) && ( nX > nMin + nShiftX ) )
353 {
354 if ( mnWinStyle & WB_HORZ )
355 rRenderContext.DrawText(Point(nX - nShiftX, nY - nShiftY), rText, 0, -1, nullptr,
356 nullptr, pTextLayout);
357 else
358 rRenderContext.DrawText(Point(nY - nShiftX, nX - nShiftY), rText, 0, -1, nullptr,
359 nullptr, pTextLayout);
360 }
361}
362
363void Ruler::ImplInvertLines(vcl::RenderContext& rRenderContext)
364{
365 // Position lines
366 if (mpData->pLines.empty() || !mbActive || mbDrag || mbFormat || (mnUpdateFlags & RULER_UPDATE_LINES0x01) )
367 return;
368
369 long nNullWinOff = mpData->nNullVirOff + mnVirOff;
370 long nRulX1 = mpData->nRulVirOff + mnVirOff;
371 long nRulX2 = nRulX1 + mpData->nRulWidth;
372 long nY = (RULER_OFF3 * 2) + mnVirHeight - 1;
373
374 // Calculate rectangle
375 tools::Rectangle aRect;
376 if (mnWinStyle & WB_HORZ)
377 aRect.SetBottom( nY );
378 else
379 aRect.SetRight( nY );
380
381 // Draw lines
382 for (const RulerLine & rLine : mpData->pLines)
383 {
384 const long n = rLine.nPos + nNullWinOff;
385 if ((n >= nRulX1) && (n < nRulX2))
386 {
387 if (mnWinStyle & WB_HORZ )
388 {
389 aRect.SetLeft( n );
390 aRect.SetRight( n );
391 }
392 else
393 {
394 aRect.SetTop( n );
395 aRect.SetBottom( n );
396 }
397 tools::Rectangle aTempRect = aRect;
398
399 if (mnWinStyle & WB_HORZ)
400 aTempRect.SetBottom( RULER_OFF3 - 1 );
401 else
402 aTempRect.SetRight( RULER_OFF3 - 1 );
403
404 rRenderContext.Erase(aTempRect);
405
406 if (mnWinStyle & WB_HORZ)
407 {
408 aTempRect.SetBottom( aRect.Bottom() );
409 aTempRect.SetTop( aTempRect.Bottom() - RULER_OFF3 + 1 );
410 }
411 else
412 {
413 aTempRect.SetRight( aRect.Right() );
414 aTempRect.SetLeft( aTempRect.Right() - RULER_OFF3 + 1 );
415 }
416 rRenderContext.Erase(aTempRect);
417 Invert(aRect);
418 }
419 }
420 mnUpdateFlags = 0;
421}
422
423void Ruler::ImplDrawTicks(vcl::RenderContext& rRenderContext, long nMin, long nMax, long nStart, long nTop, long nBottom)
424{
425 double nCenter = nTop + ((nBottom - nTop) / 2);
426
427 long nTickLength3 = (nBottom - nTop) * 0.5;
428 long nTickLength2 = nTickLength3 * 0.66;
429 long nTickLength1 = nTickLength2 * 0.66;
430
431 long nScale = ruler_tab.DPIScaleFactor;
432 long DPIOffset = nScale - 1;
433
434 double nTick4 = aImplRulerUnitTab[mnUnitIndex].nTick4;
435 double nTick2 = 0;
436 double nTickCount = aImplRulerUnitTab[mnUnitIndex].nTick1 / nScale;
437 double nTickUnit = 0;
438 long nTickWidth;
439 bool bNoTicks = false;
440
441 Size aPixSize = rRenderContext.LogicToPixel(Size(nTick4, nTick4), maMapMode);
442
443 if (mnUnitIndex == RULER_UNIT_CHAR9)
444 {
445 if (mnCharWidth == 0)
446 mnCharWidth = 371;
447 nTick4 = mnCharWidth * 2;
448 nTick2 = mnCharWidth;
449 nTickCount = mnCharWidth;
450 nTickUnit = mnCharWidth;
451 }
452 else if (mnUnitIndex == RULER_UNIT_LINE10)
453 {
454 if (mnLineHeight == 0)
455 mnLineHeight = 551;
456 nTick4 = mnLineHeight * 2;
457 nTick2 = mnLineHeight;
458 nTickUnit = mnLineHeight;
459 nTickCount = mnLineHeight;
460 }
461
462 if (mnWinStyle & WB_HORZ)
463 {
464 nTickWidth = aPixSize.Width();
465 }
466 else
467 {
468 vcl::Font aFont = rRenderContext.GetFont();
469 if (mnWinStyle & WB_RIGHT_ALIGNED)
470 aFont.SetOrientation(2700);
471 else
472 aFont.SetOrientation(900);
473 rRenderContext.SetFont(aFont);
474 nTickWidth = aPixSize.Height();
475 }
476
477 long nMaxWidth = rRenderContext.PixelToLogic(Size(mpData->nPageWidth, 0), maMapMode).Width();
478 if (nMaxWidth < 0)
479 nMaxWidth = -nMaxWidth;
480
481 if ((mnUnitIndex == RULER_UNIT_CHAR9) || (mnUnitIndex == RULER_UNIT_LINE10))
482 nMaxWidth /= nTickUnit;
483 else
484 nMaxWidth /= aImplRulerUnitTab[mnUnitIndex].nTickUnit;
485
486 OUString aNumString = OUString::number(nMaxWidth);
487 long nTxtWidth = rRenderContext.GetTextWidth( aNumString );
488 const long nTextOff = 4;
489
490 // Determine the number divider for ruler drawn numbers - means which numbers
491 // should be shown on the ruler and which should be skipped because the ruler
492 // is not big enough to draw them
493 if (nTickWidth < nTxtWidth + nTextOff)
494 {
495 // Calculate the scale of the ruler
496 long nMulti = 1;
497 long nOrgTick4 = nTick4;
498
499 while (nTickWidth < nTxtWidth + nTextOff)
500 {
501 long nOldMulti = nMulti;
502 if (nTickWidth == 0)
503 nMulti *= 10;
504 else if (nMulti < 10)
505 nMulti++;
506 else if (nMulti < 100)
507 nMulti += 10;
508 else if (nMulti < 1000)
509 nMulti += 100;
510 else
511 nMulti += 1000;
512
513 // Overflow - in this case don't draw ticks and exit
514 if (nMulti < nOldMulti)
515 {
516 bNoTicks = true;
517 break;
518 }
519
520 nTick4 = nOrgTick4 * nMulti;
521 aPixSize = rRenderContext.LogicToPixel(Size(nTick4, nTick4), maMapMode);
522 if (mnWinStyle & WB_HORZ)
523 nTickWidth = aPixSize.Width();
524 else
525 nTickWidth = aPixSize.Height();
526 }
527 nTickCount = nTick4;
528 }
529 else
530 {
531 rRenderContext.SetLineColor(rRenderContext.GetSettings().GetStyleSettings().GetShadowColor());
532 }
533
534 if (bNoTicks)
535 return;
536
537 long n = 0;
538 double nTick = 0.0;
539 double nTick3 = 0;
540
541 if ((mnUnitIndex != RULER_UNIT_CHAR9) && (mnUnitIndex != RULER_UNIT_LINE10))
542 {
543 nTick2 = aImplRulerUnitTab[mnUnitIndex].nTick2;
544 nTick3 = aImplRulerUnitTab[mnUnitIndex].nTick3;
545 }
546
547 Size nTickGapSize;
548
549 nTickGapSize = rRenderContext.LogicToPixel(Size(nTickCount, nTickCount), maMapMode);
550 long nTickGap1 = mnWinStyle & WB_HORZ ? nTickGapSize.Width() : nTickGapSize.Height();
551 nTickGapSize = rRenderContext.LogicToPixel(Size(nTick2, nTick2), maMapMode);
552 long nTickGap2 = mnWinStyle & WB_HORZ ? nTickGapSize.Width() : nTickGapSize.Height();
553 nTickGapSize = rRenderContext.LogicToPixel(Size(nTick3, nTick3), maMapMode);
554 long nTickGap3 = mnWinStyle & WB_HORZ ? nTickGapSize.Width() : nTickGapSize.Height();
555
556 while (((nStart - n) >= nMin) || ((nStart + n) <= nMax))
557 {
558 // Null point
559 if (nTick == 0.0)
560 {
561 if (nStart > nMin)
562 {
563 // 0 is only painted when Margin1 is not equal to zero
564 if ((mpData->nMargin1Style & RulerMarginStyle::Invisible) || (mpData->nMargin1 != 0))
565 {
566 aNumString = "0";
567 ImplVDrawText(rRenderContext, nStart, nCenter, aNumString);
568 }
569 }
570 }
571 else
572 {
573 aPixSize = rRenderContext.LogicToPixel(Size(nTick, nTick), maMapMode);
574
575 if (mnWinStyle & WB_HORZ)
576 n = aPixSize.Width();
577 else
578 n = aPixSize.Height();
579
580 // Tick4 - Output (Text)
581 double aStep = nTick / nTick4;
582 double aRest = std::abs(aStep - std::floor(aStep));
583 double nAcceptanceDelta = 0.0001;
584
585 if (aRest < nAcceptanceDelta)
586 {
587 if ((mnUnitIndex == RULER_UNIT_CHAR9) || (mnUnitIndex == RULER_UNIT_LINE10))
588 aNumString = OUString::number(nTick / nTickUnit);
589 else
590 aNumString = OUString::number(nTick / aImplRulerUnitTab[mnUnitIndex].nTickUnit);
591
592 long nHorizontalLocation = nStart + n;
593 ImplVDrawText(rRenderContext, nHorizontalLocation, nCenter, aNumString, nMin, nMax);
594
595 if (nMin < nHorizontalLocation && nHorizontalLocation < nMax)
596 {
597 ImplVDrawRect(rRenderContext, nHorizontalLocation, nBottom - 1 * nScale, nHorizontalLocation + DPIOffset, nBottom);
598 ImplVDrawRect(rRenderContext, nHorizontalLocation, nTop, nHorizontalLocation + DPIOffset, nTop + 1 * nScale);
599 }
600
601 nHorizontalLocation = nStart - n;
602 ImplVDrawText(rRenderContext, nHorizontalLocation, nCenter, aNumString, nMin, nMax);
603
604 if (nMin < nHorizontalLocation && nHorizontalLocation < nMax)
605 {
606 ImplVDrawRect(rRenderContext, nHorizontalLocation, nBottom,
607 nHorizontalLocation + DPIOffset, nBottom - 1 * nScale);
608 ImplVDrawRect(rRenderContext, nHorizontalLocation, nTop,
609 nHorizontalLocation + DPIOffset, nTop + 1 * nScale);
610 }
611 }
612 // Tick/Tick2 - Output (Strokes)
613 else
614 {
615 long nTickLength = nTickLength1;
616
617 aStep = (nTick / nTick2);
618 aRest = std::abs(aStep - std::floor(aStep));
619 if (aRest < nAcceptanceDelta)
620 nTickLength = nTickLength2;
621
622 aStep = (nTick / nTick3);
623 aRest = std::abs(aStep - std::floor(aStep));
624 if (aRest < nAcceptanceDelta )
625 nTickLength = nTickLength3;
626
627 if ((nTickLength == nTickLength1 && nTickGap1 > 6) ||
628 (nTickLength == nTickLength2 && nTickGap2 > 6) ||
629 (nTickLength == nTickLength3 && nTickGap3 > 6))
630 {
631 long nT1 = nCenter - (nTickLength / 2.0);
632 long nT2 = nT1 + nTickLength - 1;
633 long nT;
634
635 nT = nStart + n;
636
637 if (nT < nMax)
638 ImplVDrawRect(rRenderContext, nT, nT1, nT + DPIOffset, nT2);
639 nT = nStart - n;
640 if (nT > nMin)
641 ImplVDrawRect(rRenderContext, nT, nT1, nT + DPIOffset, nT2);
642 }
643 }
644 }
645 nTick += nTickCount;
646 }
647}
648
649void Ruler::ImplDrawBorders(vcl::RenderContext& rRenderContext, long nMin, long nMax, long nVirTop, long nVirBottom)
650{
651 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
652 long n;
653 long n1;
654 long n2;
655 long nTemp1;
656 long nTemp2;
657
658 for (std::vector<RulerBorder>::size_type i = 0; i < mpData->pBorders.size(); i++)
659 {
660 if (mpData->pBorders[i].nStyle & RulerBorderStyle::Invisible)
661 continue;
662
663 n1 = mpData->pBorders[i].nPos + mpData->nNullVirOff;
664 n2 = n1 + mpData->pBorders[i].nWidth;
665
666 if (((n1 >= nMin) && (n1 <= nMax)) || ((n2 >= nMin) && (n2 <= nMax)))
667 {
668 if ((n2 - n1) > 3)
669 {
670 rRenderContext.SetLineColor();
671 rRenderContext.SetFillColor(rStyleSettings.GetFaceColor());
672 ImplVDrawRect(rRenderContext, n1, nVirTop, n2, nVirBottom);
673
674 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
675 ImplVDrawLine(rRenderContext, n1 + 1, nVirTop, n1 + 1, nVirBottom);
676 ImplVDrawLine(rRenderContext, n1, nVirTop, n2, nVirTop);
677
678 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
679 ImplVDrawLine(rRenderContext, n1, nVirTop, n1, nVirBottom);
680 ImplVDrawLine(rRenderContext, n1, nVirBottom, n2, nVirBottom);
681 ImplVDrawLine(rRenderContext, n2 - 1, nVirTop, n2 - 1, nVirBottom);
682
683 rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
684 ImplVDrawLine(rRenderContext, n2, nVirTop, n2, nVirBottom);
685
686 if (mpData->pBorders[i].nStyle & RulerBorderStyle::Variable)
687 {
688 if (n2 - n1 > RULER_VAR_SIZE8 + 4)
689 {
690 nTemp1 = n1 + (((n2 - n1 + 1) - RULER_VAR_SIZE8) / 2);
691 nTemp2 = nVirTop + (((nVirBottom - nVirTop + 1) - RULER_VAR_SIZE8) / 2);
692 long nTemp3 = nTemp1 + RULER_VAR_SIZE8 - 1;
693 long nTemp4 = nTemp2 + RULER_VAR_SIZE8 - 1;
694 long nTempY = nTemp2;
695
696 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
697 while (nTempY <= nTemp4)
698 {
699 ImplVDrawLine(rRenderContext, nTemp1, nTempY, nTemp3, nTempY);
700 nTempY += 2;
701 }
702
703 nTempY = nTemp2 + 1;
704 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
705 while (nTempY <= nTemp4)
706 {
707 ImplVDrawLine(rRenderContext, nTemp1, nTempY, nTemp3, nTempY);
708 nTempY += 2;
709 }
710 }
711 }
712
713 if (mpData->pBorders[i].nStyle & RulerBorderStyle::Sizeable)
714 {
715 if (n2 - n1 > RULER_VAR_SIZE8 + 10)
716 {
717 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
718 ImplVDrawLine(rRenderContext, n1 + 4, nVirTop + 3, n1 + 4, nVirBottom - 3);
719 ImplVDrawLine(rRenderContext, n2 - 5, nVirTop + 3, n2 - 5, nVirBottom - 3);
720 rRenderContext.SetLineColor(rStyleSettings.GetLightColor());
721 ImplVDrawLine(rRenderContext, n1 + 5, nVirTop + 3, n1 + 5, nVirBottom - 3);
722 ImplVDrawLine(rRenderContext, n2 - 4, nVirTop + 3, n2 - 4, nVirBottom - 3);
723 }
724 }
725 }
726 else
727 {
728 n = n1 + ((n2 - n1) / 2);
729 rRenderContext.SetLineColor(rStyleSettings.GetShadowColor());
730
731 ImplVDrawLine(rRenderContext, n - 1, nVirTop, n - 1, nVirBottom);
732 ImplVDrawLine(rRenderContext, n + 1, nVirTop, n + 1, nVirBottom);
733 rRenderContext.SetLineColor();
734 rRenderContext.SetFillColor(rStyleSettings.GetWindowColor());
735 ImplVDrawRect(rRenderContext, n, nVirTop, n, nVirBottom);
736 }
737 }
738 }
739}
740
741void Ruler::ImplDrawIndent(vcl::RenderContext& rRenderContext, const tools::Polygon& rPoly, bool bIsHit)
742{
743 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
744
745 rRenderContext.SetLineColor(rStyleSettings.GetDarkShadowColor());
746 rRenderContext.SetFillColor(bIsHit ? rStyleSettings.GetDarkShadowColor() : rStyleSettings.GetWorkspaceColor());
747 tools::Polygon aPolygon(rPoly);
748 aPolygon.Optimize(PolyOptimizeFlags::CLOSE);
749 rRenderContext.DrawPolygon(aPolygon);
750}
751
752void Ruler::ImplDrawIndents(vcl::RenderContext& rRenderContext, long nMin, long nMax, long nVirTop, long nVirBottom)
753{
754 long n;
755 long nIndentHeight = (mnVirHeight / 2) - 1;
756 long nIndentWidth2 = nIndentHeight-3;
757
758 tools::Polygon aPoly(5);
759
760 for (std::vector<RulerIndent>::size_type j = 0; j < mpData->pIndents.size(); j++)
761 {
762 if (mpData->pIndents[j].bInvisible)
763 continue;
764
765 RulerIndentStyle nIndentStyle = mpData->pIndents[j].nStyle;
766
767 n = mpData->pIndents[j].nPos+mpData->nNullVirOff;
768
769 if ((n >= nMin) && (n <= nMax))
770 {
771 if (nIndentStyle == RulerIndentStyle::Bottom)
772 {
773 aPoly.SetPoint(Point(n + 0, nVirBottom - nIndentHeight), 0);
774 aPoly.SetPoint(Point(n - nIndentWidth2, nVirBottom - 3), 1);
775 aPoly.SetPoint(Point(n - nIndentWidth2, nVirBottom), 2);
776 aPoly.SetPoint(Point(n + nIndentWidth2, nVirBottom), 3);
777 aPoly.SetPoint(Point(n + nIndentWidth2, nVirBottom - 3), 4);
778 }
779 else
780 {
781 aPoly.SetPoint(Point(n + 0, nVirTop + nIndentHeight), 0);
782 aPoly.SetPoint(Point(n - nIndentWidth2, nVirTop + 3), 1);
783 aPoly.SetPoint(Point(n - nIndentWidth2, nVirTop), 2);
784 aPoly.SetPoint(Point(n + nIndentWidth2, nVirTop), 3);
785 aPoly.SetPoint(Point(n + nIndentWidth2, nVirTop + 3), 4);
786 }
787
788 if (0 == (mnWinStyle & WB_HORZ))
789 {
790 Point aTmp;
791 for (sal_uInt16 i = 0; i < 5; i++)
792 {
793 aTmp = aPoly[i];
794 Point aSet(nVirBottom - aTmp.Y(), aTmp.X());
795 aPoly[i] = aSet;
796 }
797 }
798 bool bIsHit = false;
799 if (mxCurrentHitTest != nullptr && mxCurrentHitTest->eType == RulerType::Indent)
800 {
801 bIsHit = mxCurrentHitTest->nAryPos == j;
802 }
803 else if(mbDrag && meDragType == RulerType::Indent)
804 {
805 bIsHit = mnDragAryPos == j;
806 }
807 ImplDrawIndent(rRenderContext, aPoly, bIsHit);
808 }
809 }
810}
811
812static void ImplCenterTabPos(Point& rPos, sal_uInt16 nTabStyle)
813{
814 bool bRTL = 0 != (nTabStyle & RULER_TAB_RTL);
815 nTabStyle &= RULER_TAB_STYLE;
816 rPos.AdjustY(ruler_tab.height/2 );
817
818 if ( (!bRTL && nTabStyle == RULER_TAB_LEFT) ||
819 ( bRTL && nTabStyle == RULER_TAB_RIGHT) )
820 {
821 rPos.AdjustX( -(ruler_tab.width / 2) );
822 }
823 else if ( (!bRTL && nTabStyle == RULER_TAB_RIGHT) ||
824 ( bRTL && nTabStyle == RULER_TAB_LEFT) )
825 {
826 rPos.AdjustX(ruler_tab.width / 2 );
827 }
828}
829
830static void lcl_RotateRect_Impl(tools::Rectangle& rRect, const long nReference, bool bRightAligned)
831{
832 if (rRect.IsEmpty())
833 return;
834
835 tools::Rectangle aTmp(rRect);
836 rRect.SetTop( aTmp.Left() );
837 rRect.SetBottom( aTmp.Right() );
838 rRect.SetLeft( aTmp.Top() );
839 rRect.SetRight( aTmp.Bottom() );
840
841 if (bRightAligned)
842 {
843 long nRef = 2 * nReference;
844 rRect.SetLeft( nRef - rRect.Left() );
845 rRect.SetRight( nRef - rRect.Right() );
846 }
847}
848
849static void ImplDrawRulerTab(vcl::RenderContext& rRenderContext, const Point& rPos,
850 sal_uInt16 nStyle, WinBits nWinBits)
851{
852 if (nStyle & RULER_STYLE_INVISIBLE)
853 return;
854
855 sal_uInt16 nTabStyle = nStyle & RULER_TAB_STYLE;
856 bool bRTL = 0 != (nStyle & RULER_TAB_RTL);
857
858 // Scale by the screen DPI scaling factor
859 // However when doing this some of the rectangles
860 // drawn become asymmetric due to the +1 offsets
861 sal_uInt16 DPIOffset = rRenderContext.GetDPIScaleFactor() - 1;
862
863 tools::Rectangle aRect1;
864 tools::Rectangle aRect2;
865 tools::Rectangle aRect3;
866
867 aRect3.SetEmpty();
868
869 if (nTabStyle == RULER_TAB_DEFAULT)
870 {
871 aRect1.SetLeft( rPos.X() - ruler_tab.dwidth2 + 1 );
872 aRect1.SetTop( rPos.Y() - ruler_tab.dheight2 + 1 );
873 aRect1.SetRight( rPos.X() - ruler_tab.dwidth2 + ruler_tab.dwidth + DPIOffset );
874 aRect1.SetBottom( rPos.Y() );
875
876 aRect2.SetLeft( rPos.X() - ruler_tab.dwidth2 + ruler_tab.dwidth3 );
877 aRect2.SetTop( rPos.Y() - ruler_tab.dheight + 1 );
878 aRect2.SetRight( rPos.X() - ruler_tab.dwidth2 + ruler_tab.dwidth3 + ruler_tab.dwidth4 - 1 );
879 aRect2.SetBottom( rPos.Y() );
880
881 }
882 else if ((!bRTL && nTabStyle == RULER_TAB_LEFT) || (bRTL && nTabStyle == RULER_TAB_RIGHT))
883 {
884 aRect1.SetLeft( rPos.X() );
885 aRect1.SetTop( rPos.Y() - ruler_tab.height2 + 1 );
886 aRect1.SetRight( rPos.X() + ruler_tab.width - 1 );
887 aRect1.SetBottom( rPos.Y() );
888
889 aRect2.SetLeft( rPos.X() );
890 aRect2.SetTop( rPos.Y() - ruler_tab.height + 1 );
891 aRect2.SetRight( rPos.X() + ruler_tab.width2 - 1 );
892 aRect2.SetBottom( rPos.Y() );
893 }
894 else if ((!bRTL && nTabStyle == RULER_TAB_RIGHT) || (bRTL && nTabStyle == RULER_TAB_LEFT))
895 {
896 aRect1.SetLeft( rPos.X() - ruler_tab.width + 1 );
897 aRect1.SetTop( rPos.Y() - ruler_tab.height2 + 1 );
898 aRect1.SetRight( rPos.X() );
899 aRect1.SetBottom( rPos.Y() );
900
901 aRect2.SetLeft( rPos.X() - ruler_tab.width2 + 1 );
902 aRect2.SetTop( rPos.Y() - ruler_tab.height + 1 );
903 aRect2.SetRight( rPos.X() );
904 aRect2.SetBottom( rPos.Y() );
905 }
906 else
907 {
908 aRect1.SetLeft( rPos.X() - ruler_tab.cwidth2 + 1 );
909 aRect1.SetTop( rPos.Y() - ruler_tab.height2 + 1 );
910 aRect1.SetRight( rPos.X() - ruler_tab.cwidth2 + ruler_tab.cwidth + DPIOffset );
911 aRect1.SetBottom( rPos.Y() );
912
913 aRect2.SetLeft( rPos.X() - ruler_tab.cwidth2 + ruler_tab.cwidth3 );
914 aRect2.SetTop( rPos.Y() - ruler_tab.height + 1 );
915 aRect2.SetRight( rPos.X() - ruler_tab.cwidth2 + ruler_tab.cwidth3 + ruler_tab.cwidth4 - 1 );
916 aRect2.SetBottom( rPos.Y() );
917
918 if (nTabStyle == RULER_TAB_DECIMAL)
919 {
920 aRect3.SetLeft( rPos.X() - ruler_tab.cwidth2 + ruler_tab.cwidth - 1 );
921 aRect3.SetTop( rPos.Y() - ruler_tab.height + 1 + 1 - DPIOffset );
922 aRect3.SetRight( rPos.X() - ruler_tab.cwidth2 + ruler_tab.cwidth + DPIOffset );
923 aRect3.SetBottom( rPos.Y() - ruler_tab.height + 1 + 2 );
924 }
925 }
926 if (0 == (nWinBits & WB_HORZ))
927 {
928 bool bRightAligned = 0 != (nWinBits & WB_RIGHT_ALIGNED);
929 lcl_RotateRect_Impl(aRect1, rPos.Y(), bRightAligned);
930 lcl_RotateRect_Impl(aRect2, rPos.Y(), bRightAligned);
931 lcl_RotateRect_Impl(aRect3, rPos.Y(), bRightAligned);
932 }
933 rRenderContext.DrawRect(aRect1);
934 rRenderContext.DrawRect(aRect2);
935
936 if (!aRect3.IsEmpty())
937 rRenderContext.DrawRect(aRect3);
938}
939
940void Ruler::ImplDrawTab(vcl::RenderContext& rRenderContext, const Point& rPos, sal_uInt16 nStyle)
941{
942 if (nStyle & RULER_STYLE_INVISIBLE)
943 return;
944
945 rRenderContext.SetLineColor();
946
947 if (nStyle & RULER_STYLE_DONTKNOW)
948 rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetFaceColor());
949 else
950 rRenderContext.SetFillColor(rRenderContext.GetSettings().GetStyleSettings().GetDarkShadowColor());
951
952 if (mpData->bTextRTL)
953 nStyle |= RULER_TAB_RTL;
954
955 ImplDrawRulerTab(rRenderContext, rPos, nStyle, GetStyle());
956}
957
958void Ruler::ImplDrawTabs(vcl::RenderContext& rRenderContext, long nMin, long nMax, long nVirTop, long nVirBottom)
959{
960 for (const RulerTab & rTab : mpData->pTabs)
961 {
962 if (rTab.nStyle & RULER_STYLE_INVISIBLE)
963 continue;
964
965 long aPosition;
966 aPosition = rTab.nPos;
967 aPosition += +mpData->nNullVirOff;
968 long nTopBottom = (GetStyle() & WB_RIGHT_ALIGNED) ? nVirTop : nVirBottom;
969 if (nMin <= aPosition && aPosition <= nMax)
970 ImplDrawTab(rRenderContext, Point( aPosition, nTopBottom ), rTab.nStyle);
971 }
972}
973
974static int adjustSize(int nOrig)
975{
976 if (nOrig <= 0)
977 return 0;
978
979 // make sure we return an odd number, that looks better in the ruler
980 return ( (3*nOrig) / 8) * 2 + 1;
981}
982
983void Ruler::ApplySettings(vcl::RenderContext& rRenderContext)
984{
985 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
986
987 vcl::Font aFont = rStyleSettings.GetToolFont();
988 // make the font a bit smaller than default
989 Size aSize(adjustSize(aFont.GetFontSize().Width()), adjustSize(aFont.GetFontSize().Height()));
990 aFont.SetFontSize(aSize);
991
992 ApplyControlFont(rRenderContext, aFont);
993
994 ApplyControlForeground(*this, rStyleSettings.GetDarkShadowColor());
995 SetTextFillColor();
996
997 Color aColor;
998 svtools::ColorConfig aColorConfig;
999 aColor = aColorConfig.GetColorValue(svtools::APPBACKGROUND).nColor;
1000 ApplyControlBackground(rRenderContext, aColor);
1001}
1002
1003void Ruler::ImplInitSettings(bool bFont, bool bForeground, bool bBackground)
1004{
1005 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1006
1007 if (bFont)
1008 {
1009 vcl::Font aFont = rStyleSettings.GetToolFont();
1010 // make the font a bit smaller than default
1011 Size aSize(adjustSize(aFont.GetFontSize().Width()), adjustSize(aFont.GetFontSize().Height()));
1012 aFont.SetFontSize(aSize);
1013
1014 ApplyControlFont(*this, aFont);
1015 }
1016
1017 if (bForeground || bFont)
1018 {
1019 ApplyControlForeground(*this, rStyleSettings.GetDarkShadowColor());
1020 SetTextFillColor();
1021 }
1022
1023 if (bBackground)
1024 {
1025 Color aColor;
1026 svtools::ColorConfig aColorConfig;
1027 aColor = aColorConfig.GetColorValue(svtools::APPBACKGROUND).nColor;
1028 ApplyControlBackground(*this, aColor);
1029 }
1030
1031 maVirDev->SetSettings( GetSettings() );
1032 maVirDev->SetBackground( GetBackground() );
1033 vcl::Font aFont = GetFont();
1034
1035 if (mnWinStyle & WB_VERT)
1036 aFont.SetOrientation(900);
1037
1038 maVirDev->SetFont(aFont);
1039 maVirDev->SetTextColor(GetTextColor());
1040 maVirDev->SetTextFillColor(GetTextFillColor());
1041}
1042
1043void Ruler::ImplCalc()
1044{
1045 // calculate offset
1046 mpData->nRulVirOff = mnWinOff + mpData->nPageOff;
1047 if ( mpData->nRulVirOff > mnVirOff )
1048 mpData->nRulVirOff -= mnVirOff;
1049 else
1050 mpData->nRulVirOff = 0;
1051 long nRulWinOff = mpData->nRulVirOff+mnVirOff;
1052
1053 // calculate non-visual part of the page
1054 long nNotVisPageWidth;
1055 if ( mpData->nPageOff < 0 )
1056 {
1057 nNotVisPageWidth = -(mpData->nPageOff);
1058 if ( nRulWinOff < mnWinOff )
1059 nNotVisPageWidth -= mnWinOff-nRulWinOff;
1060 }
1061 else
1062 nNotVisPageWidth = 0;
1063
1064 // calculate width
1065 if ( mnWinStyle & WB_HORZ )
1066 {
1067 if ( mbAutoWinWidth )
1068 mnWinWidth = mnWidth - mnVirOff;
1069 if ( mpData->bAutoPageWidth )
1070 mpData->nPageWidth = mnWinWidth;
1071 mpData->nRulWidth = std::min( mnWinWidth, mpData->nPageWidth-nNotVisPageWidth );
1072 if ( nRulWinOff+mpData->nRulWidth > mnWidth )
1073 mpData->nRulWidth = mnWidth-nRulWinOff;
1074 }
1075 else
1076 {
1077 if ( mbAutoWinWidth )
1078 mnWinWidth = mnHeight - mnVirOff;
1079 if ( mpData->bAutoPageWidth )
1080 mpData->nPageWidth = mnWinWidth;
1081 mpData->nRulWidth = std::min( mnWinWidth, mpData->nPageWidth-nNotVisPageWidth );
1082 if ( nRulWinOff+mpData->nRulWidth > mnHeight )
1083 mpData->nRulWidth = mnHeight-nRulWinOff;
1084 }
1085
1086 mbCalc = false;
1087}
1088
1089void Ruler::ImplFormat(vcl::RenderContext const & rRenderContext)
1090{
1091 // if already formatted, don't do it again
1092 if (!mbFormat)
1093 return;
1094
1095 // don't do anything if the window still has no size
1096 if (!mnVirWidth)
1097 return;
1098
1099 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1100 long nP1; // pixel position of Page1
1101 long nP2; // pixel position of Page2
1102 long nM1; // pixel position of Margin1
1103 long nM2; // pixel position of Margin2
1104 long nVirTop; // top/left corner
1105 long nVirBottom; // bottom/right corner
1106 long nVirLeft; // left/top corner
1107 long nVirRight; // right/bottom corner
1108 long nNullVirOff; // for faster calculation
1109
1110 // calculate values
1111 if (mbCalc)
1112 ImplCalc();
1113
1114 mpData->nNullVirOff = mnWinOff + mpData->nPageOff + mpData->nNullOff - mnVirOff;
1115
1116 nNullVirOff = mpData->nNullVirOff;
1117 nVirLeft = mpData->nRulVirOff;
1118 nVirRight = nVirLeft + mpData->nRulWidth - 1;
1119 nVirTop = 0;
1120 nVirBottom = mnVirHeight - 1;
1121
1122 if (!IsReallyVisible())
1123 return;
1124
1125 Size aVirDevSize;
1126
1127 // initialize VirtualDevice
1128 if (mnWinStyle & WB_HORZ)
1129 {
1130 aVirDevSize.setWidth( mnVirWidth );
1131 aVirDevSize.setHeight( mnVirHeight );
1132 }
1133 else
1134 {
1135 aVirDevSize.setHeight( mnVirWidth );
1136 aVirDevSize.setWidth( mnVirHeight );
1137 }
1138 if (aVirDevSize != maVirDev->GetOutputSizePixel())
1139 maVirDev->SetOutputSizePixel(aVirDevSize);
1140 else
1141 maVirDev->Erase();
1142
1143 // calculate margins
1144 if (!(mpData->nMargin1Style & RulerMarginStyle::Invisible))
1145 {
1146 nM1 = mpData->nMargin1 + nNullVirOff;
1147 if (mpData->bAutoPageWidth)
1148 {
1149 nP1 = nVirLeft;
1150 if (nM1 < nVirLeft)
1151 nP1--;
1152 }
1153 else
1154 nP1 = nNullVirOff - mpData->nNullOff;
1155 }
1156 else
1157 {
1158 nM1 = nVirLeft-1;
1159 nP1 = nM1;
1160 }
1161 if (!(mpData->nMargin2Style & RulerMarginStyle::Invisible))
1162 {
1163 nM2 = mpData->nMargin2 + nNullVirOff;
1164 if (mpData->bAutoPageWidth)
1165 {
1166 nP2 = nVirRight;
1167 if (nM2 > nVirRight)
1168 nP2++;
1169 }
1170 else
1171 nP2 = nNullVirOff - mpData->nNullOff + mpData->nPageWidth;
1172 if (nM2 > nP2)
1173 nM2 = nP2;
1174 }
1175 else
1176 {
1177 nM2 = nVirRight+1;
1178 nP2 = nM2;
1179 }
1180
1181 // top/bottom border
1182 maVirDev->SetLineColor(rStyleSettings.GetShadowColor());
1183 ImplVDrawLine(*maVirDev, nVirLeft, nVirTop + 1, nM1, nVirTop + 1); //top left line
1184 ImplVDrawLine(*maVirDev, nM2, nVirTop + 1, nP2 - 1, nVirTop + 1); //top right line
1185
1186 nVirTop++;
1187 nVirBottom--;
1188
1189 // draw margin1, margin2 and in-between
1190 maVirDev->SetLineColor();
1191 maVirDev->SetFillColor(rStyleSettings.GetDialogColor());
1192 if (nM1 > nVirLeft)
1193 ImplVDrawRect(*maVirDev, nP1, nVirTop + 1, nM1, nVirBottom); //left gray rectangle
1194 if (nM2 < nP2)
1195 ImplVDrawRect(*maVirDev, nM2, nVirTop + 1, nP2, nVirBottom); //right gray rectangle
1196 if (nM2 - nM1 > 0)
1197 {
1198 maVirDev->SetFillColor(rStyleSettings.GetWindowColor());
1199 ImplVDrawRect(*maVirDev, nM1 + 1, nVirTop, nM2 - 1, nVirBottom); //center rectangle
1200 }
1201 maVirDev->SetLineColor(rStyleSettings.GetShadowColor());
1202 if (nM1 > nVirLeft)
1203 {
1204 ImplVDrawLine(*maVirDev, nM1, nVirTop + 1, nM1, nVirBottom); //right line of the left rectangle
1205 ImplVDrawLine(*maVirDev, nP1, nVirBottom, nM1, nVirBottom); //bottom line of the left rectangle
1206 if (nP1 >= nVirLeft)
1207 {
1208 ImplVDrawLine(*maVirDev, nP1, nVirTop + 1, nP1, nVirBottom); //left line of the left rectangle
1209 ImplVDrawLine(*maVirDev, nP1, nVirBottom, nP1 + 1, nVirBottom); //?
1210 }
1211 }
1212 if (nM2 < nP2)
1213 {
1214 ImplVDrawLine(*maVirDev, nM2, nVirBottom, nP2 - 1, nVirBottom); //bottom line of the right rectangle
1215 ImplVDrawLine(*maVirDev, nM2, nVirTop + 1, nM2, nVirBottom); //left line of the right rectangle
1216 if (nP2 <= nVirRight + 1)
1217 ImplVDrawLine(*maVirDev, nP2 - 1, nVirTop + 1, nP2 - 1, nVirBottom); //right line of the right rectangle
1218 }
1219
1220 long nMin = nVirLeft;
1221 long nMax = nP2;
1222 long nStart = 0;
1223
1224 if (mpData->bTextRTL)
1225 nStart = mpData->nRightFrameMargin + nNullVirOff;
1226 else
1227 nStart = mpData->nLeftFrameMargin + nNullVirOff;
1228
1229 if (nP1 > nVirLeft)
1230 nMin++;
1231
1232 if (nP2 < nVirRight)
1233 nMax--;
1234
1235 // Draw captions
1236 ImplDrawTicks(*maVirDev, nMin, nMax, nStart, nVirTop, nVirBottom);
1237
1238 // Draw borders
1239 if (!mpData->pBorders.empty())
1240 ImplDrawBorders(*maVirDev, nVirLeft, nP2, nVirTop, nVirBottom);
1241
1242 // Draw indents
1243 if (!mpData->pIndents.empty())
1244 ImplDrawIndents(*maVirDev, nVirLeft, nP2, nVirTop - 1, nVirBottom + 1);
1245
1246 // Tabs
1247 if (!mpData->pTabs.empty())
1248 ImplDrawTabs(*maVirDev, nVirLeft, nP2, nVirTop-1, nVirBottom + 1);
1249
1250 mbFormat = false;
1251}
1252
1253void Ruler::ImplInitExtraField( bool bUpdate )
1254{
1255 Size aWinSize = GetOutputSizePixel();
1256
1257 // extra field evaluate
1258 if ( mnWinStyle & WB_EXTRAFIELD )
1259 {
1260 maExtraRect.SetLeft( RULER_OFF3 );
1261 maExtraRect.SetTop( RULER_OFF3 );
1262 maExtraRect.SetRight( RULER_OFF3 + mnVirHeight - 1 );
1263 maExtraRect.SetBottom( RULER_OFF3 + mnVirHeight - 1 );
1264 if(mpData->bTextRTL)
1265 {
1266 if(mnWinStyle & WB_HORZ)
1267 maExtraRect.Move(aWinSize.Width() - maExtraRect.GetWidth() - maExtraRect.Left(), 0);
1268 else
1269 maExtraRect.Move(0, aWinSize.Height() - maExtraRect.GetHeight() - maExtraRect.Top());
1270 mnVirOff = 0;
1271 }
1272 else
1273 mnVirOff = maExtraRect.Right()+1;
1274
1275 }
1276 else
1277 {
1278 maExtraRect.SetEmpty();
1279 mnVirOff = 0;
1280 }
1281
1282 // mnVirWidth depends on mnVirOff
1283 if ( (mnVirWidth > RULER_MIN_SIZE3) ||
1284 ((aWinSize.Width() > RULER_MIN_SIZE3) && (aWinSize.Height() > RULER_MIN_SIZE3)) )
1285 {
1286 if ( mnWinStyle & WB_HORZ )
1287 mnVirWidth = aWinSize.Width()-mnVirOff;
1288 else
1289 mnVirWidth = aWinSize.Height()-mnVirOff;
1290
1291 if ( mnVirWidth < RULER_MIN_SIZE3 )
1292 mnVirWidth = 0;
1293 }
1294
1295 if ( bUpdate )
1296 {
1297 mbCalc = true;
1298 mbFormat = true;
1299 Invalidate();
1300 }
1301}
1302
1303void Ruler::ImplDraw(vcl::RenderContext& rRenderContext)
1304{
1305 if (mbFormat)
1306 {
1307 ImplFormat(rRenderContext);
1308 }
1309
1310 if (!IsReallyVisible())
1311 return;
1312
1313 // output the ruler to the virtual device
1314 Point aOffPos;
1315 Size aVirDevSize = maVirDev->GetOutputSizePixel();
1316
1317 if (mnWinStyle & WB_HORZ)
1318 {
1319 aOffPos.setX( mnVirOff );
1320 if (mpData->bTextRTL)
1321 aVirDevSize.AdjustWidth( -(maExtraRect.GetWidth()) );
1322
1323 aOffPos.setY( RULER_OFF3 );
1324 }
1325 else
1326 {
1327 aOffPos.setX( RULER_OFF3 );
1328 aOffPos.setY( mnVirOff );
1329 }
1330 rRenderContext.DrawOutDev(aOffPos, aVirDevSize, Point(), aVirDevSize, *maVirDev);
1331
1332 // redraw positionlines
1333 ImplInvertLines(rRenderContext);
1334}
1335
1336void Ruler::ImplDrawExtra(vcl::RenderContext& rRenderContext)
1337{
1338 const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
1339 tools::Rectangle aRect = maExtraRect;
1340 bool bEraseRect = false;
1341
1342 aRect.AdjustLeft(2 );
1343 aRect.AdjustTop(2 );
1344 aRect.AdjustRight( -2 );
1345 aRect.AdjustBottom( -2 );
1346
1347 if (mnExtraStyle & RULER_STYLE_HIGHLIGHT)
1348 {
1349 rRenderContext.SetFillColor(rStyleSettings.GetCheckedColor());
1350 bEraseRect = true;
1351 }
1352
1353 if (bEraseRect)
1354 {
1355 rRenderContext.SetLineColor();
1356 rRenderContext.DrawRect(aRect);
1357 }
1358
1359 // output content
1360 if (meExtraType == RulerExtra::NullOffset)
1361 {
1362 rRenderContext.SetLineColor(rStyleSettings.GetButtonTextColor());
1363 rRenderContext.DrawLine(Point(aRect.Left() + 1, aRect.Top() + 4),
1364 Point(aRect.Right() - 1, aRect.Top() + 4));
1365 rRenderContext.DrawLine(Point(aRect.Left() + 4, aRect.Top() + 1),
1366 Point(aRect.Left() + 4, aRect.Bottom() - 1));
1367 }
1368 else if (meExtraType == RulerExtra::Tab)
1369 {
1370 sal_uInt16 nTabStyle = mnExtraStyle & RULER_TAB_STYLE;
1371 if (mpData->bTextRTL)
1372 nTabStyle |= RULER_TAB_RTL;
1373 Point aCenter = aRect.Center();
1374 Point aDraw(aCenter);
1375 ImplCenterTabPos(aDraw, nTabStyle);
1376 WinBits nWinBits = GetStyle();
1377 if (0 == (nWinBits & WB_HORZ))
1378 {
1379 if ((nWinBits & WB_RIGHT_ALIGNED) != 0)
1380 aDraw.setY( 2 * aCenter.Y() - aDraw.Y() );
1381
1382 if (mpData->bTextRTL)
1383 {
1384 long nTemp = aDraw.X();
1385 aDraw.setX( aDraw.Y() );
1386 aDraw.setY( nTemp );
1387 }
1388 }
1389 ImplDrawTab(rRenderContext, aDraw, nTabStyle);
1390 }
1391}
1392
1393void Ruler::ImplUpdate( bool bMustCalc )
1394{
1395 // clear lines in this place so they aren't considered at recalculation
1396 if (!mbFormat)
1397 Invalidate(InvalidateFlags::NoErase);
1398
1399 // set flags
1400 if (bMustCalc)
1401 mbCalc = true;
1402 mbFormat = true;
1403
1404 // abort if we are dragging as drag-handler will update the ruler after drag is finished
1405 if (mbDrag)
1406 return;
1407
1408 // otherwise trigger update
1409 if (IsReallyVisible() && IsUpdateMode())
1410 {
1411 Invalidate(InvalidateFlags::NoErase);
1412 }
1413}
1414
1415bool Ruler::ImplHitTest( const Point& rPos, RulerSelection* pHitTest,
1416 bool bRequireStyle, RulerIndentStyle nRequiredStyle ) const
1417{
1418 sal_Int32 i;
1419 sal_uInt16 nStyle;
1420 long nHitBottom;
1421 long nX;
1422 long nY;
1423 long n1;
1424
1425 if ( !mbActive )
1426 return false;
1427
1428 // determine positions
1429 bool bIsHori = 0 != (mnWinStyle & WB_HORZ);
1430 if ( bIsHori )
1431 {
1432 nX = rPos.X();
1433 nY = rPos.Y();
1434 }
1435 else
1436 {
1437 nX = rPos.Y();
1438 nY = rPos.X();
1439 }
1440 nHitBottom = mnVirHeight + (RULER_OFF3 * 2);
1441
1442 // #i32608#
1443 pHitTest->nAryPos = 0;
1444 pHitTest->mnDragSize = RulerDragSize::Move;
1445 pHitTest->bSize = false;
1446 pHitTest->bSizeBar = false;
1447
1448 // so that leftover tabs and indents are taken into account
1449 long nXExtraOff;
1450 if ( !mpData->pTabs.empty() || !mpData->pIndents.empty() )
1451 nXExtraOff = (mnVirHeight / 2) - 4;
1452 else
1453 nXExtraOff = 0;
1454
1455 // test if outside
1456 nX -= mnVirOff;
1457 if ( (nX < mpData->nRulVirOff - nXExtraOff) ||
1458 (nX > mpData->nRulVirOff + mpData->nRulWidth + nXExtraOff) ||
1459 (nY < 0) ||
1460 (nY > nHitBottom) )
1461 {
1462 pHitTest->nPos = 0;
1463 pHitTest->eType = RulerType::Outside;
1464 return false;
1465 }
1466
1467 nX -= mpData->nNullVirOff;
1468 pHitTest->nPos = nX;
1469 pHitTest->eType = RulerType::DontKnow;
1470
1471 // first test the tabs
1472 tools::Rectangle aRect;
1473 if ( !mpData->pTabs.empty() )
1474 {
1475 aRect.SetBottom( nHitBottom );
1476 aRect.SetTop( aRect.Bottom() - ruler_tab.height - RULER_OFF3 );
1477
1478 for ( i = mpData->pTabs.size() - 1; i >= 0; i-- )
1479 {
1480 nStyle = mpData->pTabs[i].nStyle;
1481 if ( !(nStyle & RULER_STYLE_INVISIBLE) )
1482 {
1483 nStyle &= RULER_TAB_STYLE;
1484
1485 // default tabs are only shown (no action)
1486 if ( nStyle != RULER_TAB_DEFAULT )
1487 {
1488 n1 = mpData->pTabs[i].nPos;
1489
1490 if ( nStyle == RULER_TAB_LEFT )
1491 {
1492 aRect.SetLeft( n1 );
1493 aRect.SetRight( n1 + ruler_tab.width - 1 );
1494 }
1495 else if ( nStyle == RULER_TAB_RIGHT )
1496 {
1497 aRect.SetRight( n1 );
1498 aRect.SetLeft( n1 - ruler_tab.width - 1 );
1499 }
1500 else
1501 {
1502 aRect.SetLeft( n1 - ruler_tab.cwidth2 + 1 );
1503 aRect.SetRight( n1 - ruler_tab.cwidth2 + ruler_tab.cwidth );
1504 }
1505
1506 if ( aRect.IsInside( Point( nX, nY ) ) )
1507 {
1508 pHitTest->eType = RulerType::Tab;
1509 pHitTest->nAryPos = i;
1510 return true;
1511 }
1512 }
1513 }
1514 }
1515 }
1516
1517 // Indents
1518 if ( !mpData->pIndents.empty() )
1519 {
1520 long nIndentHeight = (mnVirHeight / 2) - 1;
1521 long nIndentWidth2 = nIndentHeight - 3;
1522
1523 for ( i = mpData->pIndents.size(); i; i-- )
1524 {
1525 RulerIndentStyle nIndentStyle = mpData->pIndents[i-1].nStyle;
1526 if ( (! bRequireStyle || nIndentStyle == nRequiredStyle) &&
1527 !mpData->pIndents[i-1].bInvisible )
1528 {
1529 n1 = mpData->pIndents[i-1].nPos;
1530
1531 if ( (nIndentStyle == RulerIndentStyle::Bottom) != !bIsHori )
1532 {
1533 aRect.SetLeft( n1-nIndentWidth2 );
1534 aRect.SetRight( n1+nIndentWidth2 );
1535 aRect.SetTop( nHitBottom-nIndentHeight-RULER_OFF3+1 );
1536 aRect.SetBottom( nHitBottom );
1537 }
1538 else
1539 {
1540 aRect.SetLeft( n1-nIndentWidth2 );
1541 aRect.SetRight( n1+nIndentWidth2 );
1542 aRect.SetTop( 0 );
1543 aRect.SetBottom( nIndentHeight+RULER_OFF3-1 );
1544 }
1545
1546 if ( aRect.IsInside( Point( nX, nY ) ) )
1547 {
1548 pHitTest->eType = RulerType::Indent;
1549 pHitTest->nAryPos = i-1;
1550 return true;
1551 }
1552 }
1553 }
1554 }
1555
1556 // test the borders
1557 int nBorderTolerance = 1;
1558 if(pHitTest->bExpandTest)
1559 {
1560 nBorderTolerance++;
1561 }
1562
1563 for ( i = mpData->pBorders.size(); i; i-- )
1564 {
1565 n1 = mpData->pBorders[i-1].nPos;
1566 long n2 = n1 + mpData->pBorders[i-1].nWidth;
1567
1568 // borders have at least 3 pixel padding
1569 if ( !mpData->pBorders[i-1].nWidth )
1570 {
1571 n1 -= nBorderTolerance;
1572 n2 += nBorderTolerance;
1573
1574 }
1575
1576 if ( (nX >= n1) && (nX <= n2) )
1577 {
1578 RulerBorderStyle nBorderStyle = mpData->pBorders[i-1].nStyle;
1579 if ( !(nBorderStyle & RulerBorderStyle::Invisible) )
1580 {
1581 pHitTest->eType = RulerType::Border;
1582 pHitTest->nAryPos = i-1;
1583
1584 if ( !(nBorderStyle & RulerBorderStyle::Sizeable) )
1585 {
1586 if ( nBorderStyle & RulerBorderStyle::Moveable )
1587 {
1588 pHitTest->bSizeBar = true;
1589 pHitTest->mnDragSize = RulerDragSize::Move;
1590 }
1591 }
1592 else
1593 {
1594 long nMOff = RULER_MOUSE_BORDERWIDTH;
1595 while ( nMOff*2 >= (n2-n1-RULER_MOUSE_BORDERMOVE) )
1596 {
1597 if ( nMOff < 2 )
1598 {
1599 nMOff = 0;
1600 break;
1601 }
1602 else
1603 nMOff--;
1604 }
1605
1606 if ( nX <= n1+nMOff )
1607 {
1608 pHitTest->bSize = true;
1609 pHitTest->mnDragSize = RulerDragSize::N1;
1610 }
1611 else if ( nX >= n2-nMOff )
1612 {
1613 pHitTest->bSize = true;
1614 pHitTest->mnDragSize = RulerDragSize::N2;
1615 }
1616 else
1617 {
1618 if ( nBorderStyle & RulerBorderStyle::Moveable )
1619 {
1620 pHitTest->bSizeBar = true;
1621 pHitTest->mnDragSize = RulerDragSize::Move;
1622 }
1623 }
1624 }
1625
1626 return true;
1627 }
1628 }
1629 }
1630
1631 // Margins
1632 int nMarginTolerance = pHitTest->bExpandTest ? nBorderTolerance : RULER_MOUSE_MARGINWIDTH;
1633
1634 if ( (mpData->nMargin1Style & (RulerMarginStyle::Sizeable | RulerMarginStyle::Invisible)) == RulerMarginStyle::Sizeable )
1635 {
1636 n1 = mpData->nMargin1;
1637 if ( (nX >= n1 - nMarginTolerance) && (nX <= n1 + nMarginTolerance) )
1638 {
1639 pHitTest->eType = RulerType::Margin1;
1640 pHitTest->bSize = true;
1641 return true;
1642 }
1643 }
1644 if ( (mpData->nMargin2Style & (RulerMarginStyle::Sizeable | RulerMarginStyle::Invisible)) == RulerMarginStyle::Sizeable )
1645 {
1646 n1 = mpData->nMargin2;
1647 if ( (nX >= n1 - nMarginTolerance) && (nX <= n1 + nMarginTolerance) )
1648 {
1649 pHitTest->eType = RulerType::Margin2;
1650 pHitTest->bSize = true;
1651 return true;
1652 }
1653 }
1654
1655 // test tabs again
1656 if ( !mpData->pTabs.empty() )
1657 {
1658 aRect.SetTop( RULER_OFF3 );
1659 aRect.SetBottom( nHitBottom );
1660
1661 for ( i = mpData->pTabs.size() - 1; i >= 0; i-- )
1662 {
1663 nStyle = mpData->pTabs[i].nStyle;
1664 if ( !(nStyle & RULER_STYLE_INVISIBLE) )
1665 {
1666 nStyle &= RULER_TAB_STYLE;
1667
1668 // default tabs are only shown (no action)
1669 if ( nStyle != RULER_TAB_DEFAULT )
1670 {
1671 n1 = mpData->pTabs[i].nPos;
1672
1673 if ( nStyle == RULER_TAB_LEFT )
1674 {
1675 aRect.SetLeft( n1 );
1676 aRect.SetRight( n1 + ruler_tab.width - 1 );
1677 }
1678 else if ( nStyle == RULER_TAB_RIGHT )
1679 {
1680 aRect.SetRight( n1 );
1681 aRect.SetLeft( n1 - ruler_tab.width - 1 );
1682 }
1683 else
1684 {
1685 aRect.SetLeft( n1 - ruler_tab.cwidth2 + 1 );
1686 aRect.SetRight( n1 - ruler_tab.cwidth2 + ruler_tab.cwidth );
1687 }
1688
1689 aRect.AdjustLeft( -1 );
1690 aRect.AdjustRight( 1 );
1691
1692 if ( aRect.IsInside( Point( nX, nY ) ) )
1693 {
1694 pHitTest->eType = RulerType::Tab;
1695 pHitTest->nAryPos = i;
1696 return true;
1697 }
1698 }
1699 }
1700 }
1701 }
1702
1703 return false;
1704}
1705
1706bool Ruler::ImplDocHitTest( const Point& rPos, RulerType eDragType,
1707 RulerSelection* pHitTest ) const
1708{
1709 Point aPos = rPos;
1710 bool bRequiredStyle = false;
1711 RulerIndentStyle nRequiredStyle = RulerIndentStyle::Top;
1712
1713 if (eDragType == RulerType::Indent)
1714 {
1715 bRequiredStyle = true;
1716 nRequiredStyle = RulerIndentStyle::Bottom;
1717 }
1718
1719 if ( mnWinStyle & WB_HORZ )
1720 aPos.AdjustX(mnWinOff );
1721 else
1722 aPos.AdjustY(mnWinOff );
1723
1724 if ( (eDragType == RulerType::Indent) || (eDragType == RulerType::DontKnow) )
1725 {
1726 if ( mnWinStyle & WB_HORZ )
1727 aPos.setY( RULER_OFF3 + 1 );
1728 else
1729 aPos.setX( RULER_OFF3 + 1 );
1730
1731 if ( ImplHitTest( aPos, pHitTest, bRequiredStyle, nRequiredStyle ) )
1732 {
1733 if ( (pHitTest->eType == eDragType) || (eDragType == RulerType::DontKnow) )
1734 return true;
1735 }
1736 }
1737
1738 if ( (eDragType == RulerType::Indent) ||
1739 (eDragType == RulerType::Tab) ||
1740 (eDragType == RulerType::DontKnow) )
1741 {
1742 if ( mnWinStyle & WB_HORZ )
1743 aPos.setY( mnHeight - RULER_OFF3 - 1 );
1744 else
1745 aPos.setX( mnWidth - RULER_OFF3 - 1 );
1746
1747 if ( ImplHitTest( aPos, pHitTest, bRequiredStyle, nRequiredStyle ) )
1748 {
1749 if ( (pHitTest->eType == eDragType) || (eDragType == RulerType::DontKnow) )
1750 return true;
1751 }
1752 }
1753
1754 if ( (eDragType == RulerType::Margin1) || (eDragType == RulerType::Margin2) ||
1755 (eDragType == RulerType::Border) || (eDragType == RulerType::DontKnow) )
1756 {
1757 if ( mnWinStyle & WB_HORZ )
1758 aPos.setY( RULER_OFF3 + (mnVirHeight / 2) );
1759 else
1760 aPos.setX( RULER_OFF3 + (mnVirHeight / 2) );
1761
1762 if ( ImplHitTest( aPos, pHitTest ) )
1763 {
1764 if ( (pHitTest->eType == eDragType) || (eDragType == RulerType::DontKnow) )
1765 return true;
1766 }
1767 }
1768
1769 pHitTest->eType = RulerType::DontKnow;
1770
1771 return false;
1772}
1773
1774bool Ruler::ImplStartDrag( RulerSelection const * pHitTest, sal_uInt16 nModifier )
1775{
1776 // don't trigger drag if a border that was clicked can not be changed
1777 if ( (pHitTest->eType == RulerType::Border) &&
1778 !pHitTest->bSize && !pHitTest->bSizeBar )
1779 return false;
1780
1781 // Set drag data
1782 meDragType = pHitTest->eType;
1783 mnDragPos = pHitTest->nPos;
1784 mnDragAryPos = pHitTest->nAryPos;
1785 mnDragSize = pHitTest->mnDragSize;
1786 mnDragModifier = nModifier;
1787 *mpDragData = *mpSaveData;
1788 mpData = mpDragData.get();
1789
1790 // call handler
1791 if (StartDrag())
1792 {
1793 // if the handler allows dragging, initialize dragging
1794 mbDrag = true;
1795 mnStartDragPos = mnDragPos;
1796 StartTracking();
1797 Invalidate(InvalidateFlags::NoErase);
1798 return true;
1799 }
1800 else
1801 {
1802 // otherwise reset the data
1803 meDragType = RulerType::DontKnow;
1804 mnDragPos = 0;
1805 mnDragAryPos = 0;
1806 mnDragSize = RulerDragSize::Move;
1807 mnDragModifier = 0;
1808 mpData = mpSaveData.get();
1809 }
1810
1811 return false;
1812}
1813
1814void Ruler::ImplDrag( const Point& rPos )
1815{
1816 long nX;
1817 long nY;
1818 long nOutHeight;
1819
1820 if ( mnWinStyle & WB_HORZ )
1821 {
1822 nX = rPos.X();
1823 nY = rPos.Y();
1824 nOutHeight = mnHeight;
1825 }
1826 else
1827 {
1828 nX = rPos.Y();
1829 nY = rPos.X();
1830 nOutHeight = mnWidth;
1831 }
1832
1833 // calculate and fit X
1834 nX -= mnVirOff;
1835 if ( nX < mpData->nRulVirOff )
1836 {
1837 nX = mpData->nRulVirOff;
1838 }
1839 else if ( nX > mpData->nRulVirOff+mpData->nRulWidth )
1840 {
1841 nX = mpData->nRulVirOff+mpData->nRulWidth;
1842 }
1843 nX -= mpData->nNullVirOff;
1844
1845 // if upper or left from ruler, then consider old values
1846 mbDragDelete = false;
1847 if ( nY < 0 )
1848 {
1849 if ( !mbDragCanceled )
1850 {
1851 // reset the data
1852 mbDragCanceled = true;
1853 ImplRulerData aTempData = *mpDragData;
1854 *mpDragData = *mpSaveData;
1855 mbCalc = true;
1856 mbFormat = true;
1857
1858 // call handler
1859 mnDragPos = mnStartDragPos;
1860 Drag();
1861
1862 // and redraw
1863 Invalidate(InvalidateFlags::NoErase);
1864
1865 // reset the data as before cancel
1866 *mpDragData = aTempData;
1867 }
1868 }
1869 else
1870 {
1871 mbDragCanceled = false;
1872
1873 // +2, so the tabs are not cleared too quickly
1874 if ( nY > nOutHeight + 2 )
1875 mbDragDelete = true;
1876
1877 mnDragPos = nX;
1878
1879 // call handler
1880 Drag();
1881
1882 // redraw
1883 if (mbFormat)
1884 Invalidate(InvalidateFlags::NoErase);
1885 }
1886}
1887
1888void Ruler::ImplEndDrag()
1889{
1890 // get values
1891 if ( mbDragCanceled )
1892 *mpDragData = *mpSaveData;
1893 else
1894 *mpSaveData = *mpDragData;
1895
1896 mpData = mpSaveData.get();
1897 mbDrag = false;
1898
1899 // call handler
1900 EndDrag();
1901
1902 // reset drag values
1903 meDragType = RulerType::DontKnow;
1904 mnDragPos = 0;
1905 mnDragAryPos = 0;
1906 mnDragSize = RulerDragSize::Move;
1907 mbDragCanceled = false;
1908 mbDragDelete = false;
1909 mnDragModifier = 0;
1910 mnStartDragPos = 0;
1911
1912 // redraw
1913 Invalidate(InvalidateFlags::NoErase);
1914}
1915
1916void Ruler::MouseButtonDown( const MouseEvent& rMEvt )
1917{
1918 if ( !rMEvt.IsLeft() || IsTracking() )
1919 return;
1920
1921 Point aMousePos = rMEvt.GetPosPixel();
1922 sal_uInt16 nMouseClicks = rMEvt.GetClicks();
1923 sal_uInt16 nMouseModifier = rMEvt.GetModifier();
1924
1925 // update ruler
1926 if ( mbFormat )
1927 {
1928 Invalidate(InvalidateFlags::NoErase);
1929 }
1930
1931 if ( maExtraRect.IsInside( aMousePos ) )
1932 {
1933 ExtraDown();
1934 }
1935 else
1936 {
1937 std::unique_ptr<RulerSelection> pHitTest(new RulerSelection);
1938 bool bHitTestResult = ImplHitTest(aMousePos, pHitTest.get());
1939
1940 if ( nMouseClicks == 1 )
1941 {
1942 if ( bHitTestResult )
1943 {
1944 ImplStartDrag( pHitTest.get(), nMouseModifier );
1945 }
1946 else
1947 {
1948 // calculate position inside of ruler area
1949 if ( pHitTest->eType == RulerType::DontKnow )
1950 {
1951 mnDragPos = pHitTest->nPos;
1952 Click();
1953 mnDragPos = 0;
1954
1955 // call HitTest again as a click, for example, could set a new tab
1956 if ( ImplHitTest(aMousePos, pHitTest.get()) )
1957 ImplStartDrag(pHitTest.get(), nMouseModifier);
1958 }
1959 }
1960 }
1961 else
1962 {
1963 if (bHitTestResult)
1964 {
1965 mnDragPos = pHitTest->nPos;
1966 mnDragAryPos = pHitTest->nAryPos;
1967 }
1968 meDragType = pHitTest->eType;
1969
1970 DoubleClick();
1971
1972 meDragType = RulerType::DontKnow;
1973 mnDragPos = 0;
1974 mnDragAryPos = 0;
1975 }
1976 }
1977}
1978
1979void Ruler::MouseMove( const MouseEvent& rMEvt )
1980{
1981 PointerStyle ePtrStyle = PointerStyle::Arrow;
1982
1983 mxPreviousHitTest.swap(mxCurrentHitTest);
1984
1985 mxCurrentHitTest.reset(new RulerSelection);
1986
1987 maHoverSelection.eType = RulerType::DontKnow;
1988
1989 if (ImplHitTest( rMEvt.GetPosPixel(), mxCurrentHitTest.get() ))
1990 {
1991 maHoverSelection = *mxCurrentHitTest;
1992
1993 if (mxCurrentHitTest->bSize)
1994 {
1995 if (mnWinStyle & WB_HORZ)
1996 {
1997 if (mxCurrentHitTest->mnDragSize == RulerDragSize::N1)
1998 ePtrStyle = PointerStyle::TabSelectW;
1999 else if (mxCurrentHitTest->mnDragSize == RulerDragSize::N2)
2000 ePtrStyle = PointerStyle::TabSelectE;
2001 else
2002 ePtrStyle = PointerStyle::ESize;
2003 }
2004 else
2005 {
2006 if (mxCurrentHitTest->mnDragSize == RulerDragSize::N1)
2007 ePtrStyle = PointerStyle::WindowNSize;
2008 else if (mxCurrentHitTest->mnDragSize == RulerDragSize::N2)
2009 ePtrStyle = PointerStyle::WindowSSize;
2010 else
2011 ePtrStyle = PointerStyle::SSize;
2012 }
2013 }
2014 else if (mxCurrentHitTest->bSizeBar)
2015 {
2016 if (mnWinStyle & WB_HORZ)
2017 ePtrStyle = PointerStyle::HSizeBar;
2018 else
2019 ePtrStyle = PointerStyle::VSizeBar;
2020 }
2021 }
2022
2023 if (mxPreviousHitTest != nullptr && mxPreviousHitTest->eType != mxCurrentHitTest->eType)
2024 {
2025 mbFormat = true;
2026 }
2027
2028 SetPointer( ePtrStyle );
2029
2030 if (mbFormat)
2031 {
2032 Invalidate(InvalidateFlags::NoErase);
2033 }
2034}
2035
2036void Ruler::Tracking( const TrackingEvent& rTEvt )
2037{
2038 if ( rTEvt.IsTrackingEnded() )
2039 {
2040 // reset the old state at cancel
2041 if ( rTEvt.IsTrackingCanceled() )
2042 {
2043 mbDragCanceled = true;
2044 mbFormat = true;
2045 }
2046
2047 ImplEndDrag();
2048 }
2049 else
2050 ImplDrag( rTEvt.GetMouseEvent().GetPosPixel() );
2051}
2052
2053void Ruler::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
2054{
2055 ImplDraw(rRenderContext);
2056
2057 // consider extra field
2058 if (mnWinStyle & WB_EXTRAFIELD)
2059 ImplDrawExtra(rRenderContext);
2060}
2061
2062void Ruler::Resize()
2063{
2064 Size aWinSize = GetOutputSizePixel();
2065
2066 long nNewHeight;
2067 if ( mnWinStyle & WB_HORZ )
2068 {
2069 if ( aWinSize.Height() != mnHeight )
2070 nNewHeight = aWinSize.Height();
2071 else
2072 nNewHeight = 0;
2073 }
2074 else
2075 {
2076 if ( aWinSize.Width() != mnWidth )
2077 nNewHeight = aWinSize.Width();
2078 else
2079 nNewHeight = 0;
2080 }
2081
2082 mbFormat = true;
2083
2084 // clear lines
2085 bool bVisible = IsReallyVisible();
2086 if ( bVisible && !mpData->pLines.empty() )
2087 {
2088 mnUpdateFlags |= RULER_UPDATE_LINES0x01;
2089 Invalidate(InvalidateFlags::NoErase);
2090 }
2091
2092 // recalculate some values if the height/width changes
2093 // extra field should always be updated
2094 ImplInitExtraField( mpData->bTextRTL );
2095 if ( nNewHeight )
2096 {
2097 mbCalc = true;
2098 mnVirHeight = nNewHeight - mnBorderWidth - ( RULER_OFF3 * 2 );
2099 }
2100 else
2101 {
2102 if ( mpData->bAutoPageWidth )
2103 ImplUpdate( true );
2104 else if ( mbAutoWinWidth )
2105 mbCalc = true;
2106 }
2107
2108 // clear part of the border
2109 if ( bVisible )
2110 {
2111 if ( nNewHeight )
2112 Invalidate(InvalidateFlags::NoErase);
2113 else if ( mpData->bAutoPageWidth )
2114 {
2115 // only at AutoPageWidth do we need to redraw
2116 tools::Rectangle aRect;
2117
2118 if ( mnWinStyle & WB_HORZ )
2119 {
2120 if ( mnWidth < aWinSize.Width() )
2121 aRect.SetLeft( mnWidth - RULER_RESIZE_OFF4 );
2122 else
2123 aRect.SetLeft( aWinSize.Width() - RULER_RESIZE_OFF4 );
2124 aRect.SetRight( aRect.Left() + RULER_RESIZE_OFF4 );
2125 aRect.SetTop( RULER_OFF3 );
2126 aRect.SetBottom( RULER_OFF3 + mnVirHeight );
2127 }
2128 else
2129 {
2130 if ( mnHeight < aWinSize.Height() )
2131 aRect.SetTop( mnHeight-RULER_RESIZE_OFF4 );
2132 else
2133 aRect.SetTop( aWinSize.Height()-RULER_RESIZE_OFF4 );
2134 aRect.SetBottom( aRect.Top() + RULER_RESIZE_OFF4 );
2135 aRect.SetLeft( RULER_OFF3 );
2136 aRect.SetRight( RULER_OFF3 + mnVirHeight );
2137 }
2138
2139 Invalidate(aRect, InvalidateFlags::NoErase);
2140 }
2141 }
2142
2143 mnWidth = aWinSize.Width();
2144 mnHeight = aWinSize.Height();
2145}
2146
2147void Ruler::StateChanged( StateChangedType nType )
2148{
2149 Window::StateChanged( nType );
2150
2151 if ( nType == StateChangedType::InitShow )
2152 Invalidate();
2153 else if ( nType == StateChangedType::UpdateMode )
2154 {
2155 if ( IsReallyVisible() && IsUpdateMode() )
2156 Invalidate();
2157 }
2158 else if ( (nType == StateChangedType::Zoom) ||
2159 (nType == StateChangedType::ControlFont) )
2160 {
2161 ImplInitSettings( true, false, false );
2162 Invalidate();
2163 }
2164 else if ( nType == StateChangedType::ControlForeground )
2165 {
2166 ImplInitSettings( false, true, false );
2167 Invalidate();
2168 }
2169 else if ( nType == StateChangedType::ControlBackground )
2170 {
2171 ImplInitSettings( false, false, true );
2172 Invalidate();
2173 }
2174}
2175
2176void Ruler::DataChanged( const DataChangedEvent& rDCEvt )
2177{
2178 Window::DataChanged( rDCEvt );
2179
2180 if ( (rDCEvt.GetType() == DataChangedEventType::FONTS) ||
2181 (rDCEvt.GetType() == DataChangedEventType::DISPLAY) ||
2182 (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
2183 ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
2184 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE)) )
2185 {
2186 mbFormat = true;
2187 ImplInitSettings( true, true, true );
2188 Invalidate();
2189 }
2190}
2191
2192bool Ruler::StartDrag()
2193{
2194 return false;
2195}
2196
2197void Ruler::Drag()
2198{
2199}
2200
2201void Ruler::EndDrag()
2202{
2203}
2204
2205void Ruler::Click()
2206{
2207}
2208
2209void Ruler::DoubleClick()
2210{
2211 maDoubleClickHdl.Call( this );
2212}
2213
2214void Ruler::ExtraDown()
2215{
2216}
2217
2218void Ruler::Activate()
2219{
2220 mbActive = true;
2221
2222 // update positionlines - draw is delayed
2223 mnUpdateFlags |= RULER_UPDATE_LINES0x01;
2224 Invalidate(InvalidateFlags::NoErase);
2225}
2226
2227void Ruler::Deactivate()
2228{
2229 // clear positionlines
2230 Invalidate(InvalidateFlags::NoErase);
2231
2232 mbActive = false;
2233}
2234
2235bool Ruler::StartDocDrag( const MouseEvent& rMEvt, RulerType eDragType )
2236{
2237 if ( !mbDrag )
2238 {
2239 Point aMousePos = rMEvt.GetPosPixel();
2240 sal_uInt16 nMouseClicks = rMEvt.GetClicks();
2241 sal_uInt16 nMouseModifier = rMEvt.GetModifier();
2242 RulerSelection aHitTest;
2243
2244 if(eDragType != RulerType::DontKnow)
2245 aHitTest.bExpandTest = true;
2246
2247 // update ruler
2248 if ( mbFormat )
2249 {
2250 if (!IsReallyVisible())
2251 {
2252 // set mpData for ImplDocHitTest()
2253 ImplFormat(*this);
2254 }
2255
2256 Invalidate(InvalidateFlags::NoErase);
2257 }
2258
2259 if ( nMouseClicks == 1 )
2260 {
2261 if ( ImplDocHitTest( aMousePos, eDragType, &aHitTest ) )
2262 {
2263 PointerStyle aPtr = PointerStyle::Arrow;
2264
2265 if ( aHitTest.bSize )
2266 {
2267 if ( mnWinStyle & WB_HORZ )
2268 aPtr = PointerStyle::ESize;
2269 else
2270 aPtr = PointerStyle::SSize;
2271 }
2272 else if ( aHitTest.bSizeBar )
2273 {
2274 if ( mnWinStyle & WB_HORZ )
2275 aPtr = PointerStyle::HSizeBar;
2276 else
2277 aPtr = PointerStyle::VSizeBar;
2278 }
2279 SetPointer( aPtr );
2280 return ImplStartDrag( &aHitTest, nMouseModifier );
2281 }
2282 }
2283 else if ( nMouseClicks == 2 )
2284 {
2285 if ( ImplDocHitTest( aMousePos, eDragType, &aHitTest ) )
2286 {
2287 mnDragPos = aHitTest.nPos;
2288 mnDragAryPos = aHitTest.nAryPos;
2289 }
2290
2291 DoubleClick();
2292
2293 mnDragPos = 0;
2294 mnDragAryPos = 0;
2295
2296 return true;
2297 }
2298 }
2299
2300 return false;
2301}
2302
2303void Ruler::CancelDrag()
2304{
2305 if ( mbDrag )
2306 {
2307 ImplDrag( Point( -1, -1 ) );
2308 ImplEndDrag();
2309 }
2310}
2311
2312RulerType Ruler::GetType( const Point& rPos, sal_uInt16* pAryPos )
2313{
2314 RulerSelection aHitTest;
2315
2316 // update ruler
2317 if ( IsReallyVisible() && mbFormat )
2318 {
2319 Invalidate(InvalidateFlags::NoErase);
2320 }
2321
2322 (void)ImplHitTest(rPos, &aHitTest);
2323
2324 // return values
2325 if ( pAryPos )
2326 *pAryPos = aHitTest.nAryPos;
2327 return aHitTest.eType;
2328}
2329
2330void Ruler::SetWinPos( long nNewOff, long nNewWidth )
2331{
2332 // should widths be automatically calculated
2333 if ( !nNewWidth )
2334 mbAutoWinWidth = true;
2335 else
2336 mbAutoWinWidth = false;
2337
2338 mnWinOff = nNewOff;
2339 mnWinWidth = nNewWidth;
2340 ImplUpdate( true );
2341}
2342
2343void Ruler::SetPagePos( long nNewOff, long nNewWidth )
2344{
2345 // should we do anything?
2346 if ( (mpData->nPageOff == nNewOff) && (mpData->nPageWidth == nNewWidth) )
2347 return;
2348
2349 // should widths be automatically calculated
2350 if ( !nNewWidth )
2351 mpData->bAutoPageWidth = true;
2352 else
2353 mpData->bAutoPageWidth = false;
2354
2355 mpData->nPageOff = nNewOff;
2356 mpData->nPageWidth = nNewWidth;
2357 ImplUpdate( true );
2358}
2359
2360void Ruler::SetBorderPos( long nOff )
2361{
2362 if ( mnWinStyle & WB_BORDER )
2363 {
2364 if ( mnBorderOff != nOff )
2365 {
2366 mnBorderOff = nOff;
2367
2368 if ( IsReallyVisible() && IsUpdateMode() )
2369 Invalidate(InvalidateFlags::NoErase);
2370 }
2371 }
2372}
2373
2374void Ruler::SetUnit( FieldUnit eNewUnit )
2375{
2376 if ( meUnit == eNewUnit )
2377 return;
2378
2379 meUnit = eNewUnit;
2380 switch ( meUnit )
2381 {
2382 case FieldUnit::MM:
2383 mnUnitIndex = RULER_UNIT_MM0;
2384 break;
2385 case FieldUnit::CM:
2386 mnUnitIndex = RULER_UNIT_CM1;
2387 break;
2388 case FieldUnit::M:
2389 mnUnitIndex = RULER_UNIT_M2;
2390 break;
2391 case FieldUnit::KM:
2392 mnUnitIndex = RULER_UNIT_KM3;
2393 break;
2394 case FieldUnit::INCH:
2395 mnUnitIndex = RULER_UNIT_INCH4;
2396 break;
2397 case FieldUnit::FOOT:
2398 mnUnitIndex = RULER_UNIT_FOOT5;
2399 break;
2400 case FieldUnit::MILE:
2401 mnUnitIndex = RULER_UNIT_MILE6;
2402 break;
2403 case FieldUnit::POINT:
2404 mnUnitIndex = RULER_UNIT_POINT7;
2405 break;
2406 case FieldUnit::PICA:
2407 mnUnitIndex = RULER_UNIT_PICA8;
2408 break;
2409 case FieldUnit::CHAR:
2410 mnUnitIndex = RULER_UNIT_CHAR9;
2411 break;
2412 case FieldUnit::LINE:
2413 mnUnitIndex = RULER_UNIT_LINE10;
2414 break;
2415 default:
2416 SAL_WARN( "svtools.control", "Ruler::SetUnit() - Wrong Unit" )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN
, "svtools.control")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break
; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult
( ::sal::detail::StreamStart() << "Ruler::SetUnit() - Wrong Unit"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svtools.control"
), ("/home/maarten/src/libreoffice/core/svtools/source/control/ruler.cxx"
":" "2416" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Ruler::SetUnit() - Wrong Unit"), 0)
; } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Ruler::SetUnit() - Wrong Unit"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svtools.control"), ("/home/maarten/src/libreoffice/core/svtools/source/control/ruler.cxx"
":" "2416" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "Ruler::SetUnit() - Wrong Unit") == 1) { ::sal_detail_log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svtools.control"), ("/home/maarten/src/libreoffice/core/svtools/source/control/ruler.cxx"
":" "2416" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "Ruler::SetUnit() - Wrong Unit"), 0)
; } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "Ruler::SetUnit() - Wrong Unit"; ::sal::detail::log
( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svtools.control"), ("/home/maarten/src/libreoffice/core/svtools/source/control/ruler.cxx"
":" "2416" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
2417 break;
2418 }
2419
2420 maMapMode.SetMapUnit( aImplRulerUnitTab[mnUnitIndex].eMapUnit );
2421 ImplUpdate();
2422}
2423
2424void Ruler::SetZoom( const Fraction& rNewZoom )
2425{
2426 DBG_ASSERT( rNewZoom.GetNumerator(), "Ruler::SetZoom() with scale 0 is not allowed" )do { if (true && (!(rNewZoom.GetNumerator()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svtools/source/control/ruler.cxx"
":" "2426" ": "), "%s", "Ruler::SetZoom() with scale 0 is not allowed"
); } } while (false)
;
2427
2428 if ( maZoom != rNewZoom )
2429 {
2430 maZoom = rNewZoom;
2431 maMapMode.SetScaleX( maZoom );
2432 maMapMode.SetScaleY( maZoom );
2433 ImplUpdate();
2434 }
2435}
2436
2437void Ruler::SetExtraType( RulerExtra eNewExtraType, sal_uInt16 nStyle )
2438{
2439 if ( mnWinStyle & WB_EXTRAFIELD )
2440 {
2441 meExtraType = eNewExtraType;
2442 mnExtraStyle = nStyle;
2443 if (IsReallyVisible() && IsUpdateMode())
2444 Invalidate();
2445 }
2446}
2447
2448void Ruler::SetNullOffset( long nPos )
2449{
2450 if ( mpData->nNullOff != nPos )
2451 {
2452 mpData->nNullVirOff += nPos - mpData->nNullOff;
2453 mpData->nNullOff = nPos;
2454 ImplUpdate();
2455 }
2456}
2457
2458void Ruler::SetLeftFrameMargin( long nPos )
2459{
2460 if ( mpData->nLeftFrameMargin != nPos )
2461 {
2462 mpData->nLeftFrameMargin = nPos;
2463 ImplUpdate();
2464 }
2465}
2466
2467void Ruler::SetRightFrameMargin( long nPos )
2468{
2469 if ( mpData->nRightFrameMargin != nPos )
2470 {
2471 mpData->nRightFrameMargin = nPos;
2472 ImplUpdate();
2473 }
2474}
2475
2476void Ruler::SetMargin1( long nPos, RulerMarginStyle nMarginStyle )
2477{
2478 if ( (mpData->nMargin1 != nPos) || (mpData->nMargin1Style != nMarginStyle) )
2479 {
2480 mpData->nMargin1 = nPos;
2481 mpData->nMargin1Style = nMarginStyle;
2482 ImplUpdate();
2483 }
2484}
2485
2486void Ruler::SetMargin2( long nPos, RulerMarginStyle nMarginStyle )
2487{
2488 DBG_ASSERT( (nPos >= mpData->nMargin1) ||do { if (true && (!((nPos >= mpData->nMargin1) ||
(mpData->nMargin1Style & RulerMarginStyle::Invisible)
|| (mpData->nMargin2Style & RulerMarginStyle::Invisible
)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/svtools/source/control/ruler.cxx"
":" "2491" ": "), "%s", "Ruler::SetMargin2() - Margin2 < Margin1"
); } } while (false)
2489 (mpData->nMargin1Style & RulerMarginStyle::Invisible) ||do { if (true && (!((nPos >= mpData->nMargin1) ||
(mpData->nMargin1Style & RulerMarginStyle::Invisible)
|| (mpData->nMargin2Style & RulerMarginStyle::Invisible
)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/svtools/source/control/ruler.cxx"
":" "2491" ": "), "%s", "Ruler::SetMargin2() - Margin2 < Margin1"
); } } while (false)
2490 (mpData->nMargin2Style & RulerMarginStyle::Invisible),do { if (true && (!((nPos >= mpData->nMargin1) ||
(mpData->nMargin1Style & RulerMarginStyle::Invisible)
|| (mpData->nMargin2Style & RulerMarginStyle::Invisible
)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/svtools/source/control/ruler.cxx"
":" "2491" ": "), "%s", "Ruler::SetMargin2() - Margin2 < Margin1"
); } } while (false)
2491 "Ruler::SetMargin2() - Margin2 < Margin1" )do { if (true && (!((nPos >= mpData->nMargin1) ||
(mpData->nMargin1Style & RulerMarginStyle::Invisible)
|| (mpData->nMargin2Style & RulerMarginStyle::Invisible
)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/svtools/source/control/ruler.cxx"
":" "2491" ": "), "%s", "Ruler::SetMargin2() - Margin2 < Margin1"
); } } while (false)
;
2492
2493 if ( (mpData->nMargin2 != nPos) || (mpData->nMargin2Style != nMarginStyle) )
2494 {
2495 mpData->nMargin2 = nPos;
2496 mpData->nMargin2Style = nMarginStyle;
2497 ImplUpdate();
2498 }
2499}
2500
2501void Ruler::SetLines( sal_uInt32 aLineArraySize, const RulerLine* pLineArray )
2502{
2503 // To determine if what has changed
2504 if ( mpData->pLines.size() == aLineArraySize )
2505 {
2506 sal_uInt32 i = aLineArraySize;
2507 vector<RulerLine>::const_iterator aItr1 = mpData->pLines.begin();
2508 const RulerLine* pAry2 = pLineArray;
2509 while ( i )
2510 {
2511 if ( aItr1->nPos != pAry2->nPos )
2512 break;
2513 ++aItr1;
2514 ++pAry2;
2515 i--;
2516 }
2517 if ( !i )
2518 return;
2519 }
2520
2521 // New values and new share issue
2522 bool bMustUpdate;
2523 bMustUpdate = IsReallyVisible() && IsUpdateMode();
2524
2525 // Delete old lines
2526 if ( bMustUpdate )
2527 Invalidate(InvalidateFlags::NoErase);
2528
2529 // New data set
2530 if ( !aLineArraySize || !pLineArray )
2531 {
2532 if ( mpData->pLines.empty() )
2533 return;
2534 mpData->pLines.clear();
2535 }
2536 else
2537 {
2538 if ( mpData->pLines.size() != aLineArraySize )
2539 {
2540 mpData->pLines.resize(aLineArraySize);
2541 }
2542
2543 std::copy( pLineArray,
2544 pLineArray + aLineArraySize,
2545 mpData->pLines.begin() );
2546
2547 if ( bMustUpdate )
2548 Invalidate(InvalidateFlags::NoErase);
2549 }
2550}
2551
2552void Ruler::SetBorders( sal_uInt32 aBorderArraySize, const RulerBorder* pBorderArray )
2553{
2554 if ( !aBorderArraySize || !pBorderArray )
2555 {
2556 if ( mpData->pBorders.empty() )
2557 return;
2558 mpData->pBorders.clear();
2559 }
2560 else
2561 {
2562 if ( mpData->pBorders.size() != aBorderArraySize )
2563 {
2564 mpData->pBorders.resize(aBorderArraySize);
2565 }
2566 else
2567 {
2568 sal_uInt32 i = aBorderArraySize;
2569 const RulerBorder* pAry1 = mpData->pBorders.data();
2570 const RulerBorder* pAry2 = pBorderArray;
2571 while ( i )
2572 {
2573 if ( (pAry1->nPos != pAry2->nPos) ||
2574 (pAry1->nWidth != pAry2->nWidth) ||
2575 (pAry1->nStyle != pAry2->nStyle) )
2576 break;
2577 pAry1++;
2578 pAry2++;
2579 i--;
2580 }
2581 if ( !i )
2582 return;
2583 }
2584 std::copy( pBorderArray,
2585 pBorderArray + aBorderArraySize,
2586 mpData->pBorders.begin() );
2587 }
2588
2589 ImplUpdate();
2590}
2591
2592void Ruler::SetIndents( sal_uInt32 aIndentArraySize, const RulerIndent* pIndentArray )
2593{
2594
2595 if ( !aIndentArraySize || !pIndentArray )
2596 {
2597 if ( mpData->pIndents.empty() )
2598 return;
2599 mpData->pIndents.clear();
2600 }
2601 else
2602 {
2603 if ( mpData->pIndents.size() != aIndentArraySize )
2604 {
2605 mpData->pIndents.resize(aIndentArraySize);
2606 }
2607 else
2608 {
2609 sal_uInt32 i = aIndentArraySize;
2610 const RulerIndent* pAry1 = mpData->pIndents.data();
2611 const RulerIndent* pAry2 = pIndentArray;
2612 while ( i )
2613 {
2614 if ( (pAry1->nPos != pAry2->nPos) ||
2615 (pAry1->nStyle != pAry2->nStyle) )
2616 break;
2617 pAry1++;
2618 pAry2++;
2619 i--;
2620 }
2621 if ( !i )
2622 return;
2623 }
2624
2625 std::copy( pIndentArray,
2626 pIndentArray + aIndentArraySize,
2627 mpData->pIndents.begin() );
2628 }
2629
2630 ImplUpdate();
2631}
2632
2633void Ruler::SetTabs( sal_uInt32 aTabArraySize, const RulerTab* pTabArray )
2634{
2635 if ( aTabArraySize == 0 || pTabArray == nullptr )
2636 {
2637 if ( mpData->pTabs.empty() )
2638 return;
2639 mpData->pTabs.clear();
2640 }
2641 else
2642 {
2643 if ( mpData->pTabs.size() != aTabArraySize )
2644 {
2645 mpData->pTabs.resize(aTabArraySize);
2646 }
2647 else
2648 {
2649 sal_uInt32 i = aTabArraySize;
2650 vector<RulerTab>::iterator aTabIterator = mpData->pTabs.begin();
2651 const RulerTab* pInputArray = pTabArray;
2652 while ( i )
2653 {
2654 RulerTab& aCurrent = *aTabIterator;
2655 if ( aCurrent.nPos != pInputArray->nPos ||
2656 aCurrent.nStyle != pInputArray->nStyle )
2657 {
2658 break;
2659 }
2660 ++aTabIterator;
2661 pInputArray++;
2662 i--;
2663 }
2664 if ( !i )
2665 return;
2666 }
2667 std::copy(pTabArray, pTabArray + aTabArraySize, mpData->pTabs.begin());
2668 }
2669
2670 ImplUpdate();
2671}
2672
2673const std::vector<RulerTab>& Ruler::GetTabs() const
2674{
2675 return mpData->pTabs;
2676}
2677
2678void Ruler::SetStyle( WinBits nStyle )
2679{
2680 if ( mnWinStyle != nStyle )
2681 {
2682 mnWinStyle = nStyle;
2683 ImplInitExtraField( true );
2684 }
2685}
2686
2687void Ruler::DrawTab(vcl::RenderContext& rRenderContext, const Color &rFillColor, const Point& rPos, sal_uInt16 nStyle)
2688{
2689 Point aPos(rPos);
2690 sal_uInt16 nTabStyle = nStyle & (RULER_TAB_STYLE | RULER_TAB_RTL);
2691
2692 rRenderContext.Push(PushFlags::LINECOLOR | PushFlags::FILLCOLOR);
2693 rRenderContext.SetLineColor();
2694 rRenderContext.SetFillColor(rFillColor);
2695 ImplCenterTabPos(aPos, nTabStyle);
2696 ImplDrawRulerTab(rRenderContext, aPos, nTabStyle, nStyle);
2697 rRenderContext.Pop();
2698}
2699
2700void Ruler::SetTextRTL(bool bRTL)
2701{
2702 if(mpData->bTextRTL != bRTL)
2703 {
2704 mpData->bTextRTL = bRTL;
2705 if ( IsReallyVisible() && IsUpdateMode() )
2706 ImplInitExtraField( true );
2707 }
2708
2709}
2710
2711long Ruler::GetPageOffset() const
2712{
2713 return mpData->nPageOff;
2714}
2715
2716long Ruler::GetNullOffset() const
2717{
2718 return mpData->nNullOff;
2719}
2720
2721long Ruler::GetMargin1() const
2722{
2723 return mpData->nMargin1;
2724}
2725
2726long Ruler::GetMargin2() const
2727{
2728 return mpData->nMargin2;
2729}
2730
2731
2732bool Ruler::GetTextRTL() const
2733{
2734 return mpData->bTextRTL;
2735}
2736
2737const RulerUnitData& Ruler::GetCurrentRulerUnit() const
2738{
2739 return aImplRulerUnitTab[mnUnitIndex];
2740}
2741
2742void Ruler::DrawTicks()
2743{
2744 mbFormat = true;
2745 Invalidate(InvalidateFlags::NoErase);
2746}
2747
2748uno::Reference< XAccessible > Ruler::CreateAccessible()
2749{
2750 vcl::Window* pParent = GetAccessibleParentWindow();
2751 OSL_ENSURE( pParent, "-SvxRuler::CreateAccessible(): No Parent!" )do { if (true && (!(pParent))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svtools/source/control/ruler.cxx"
":" "2751" ": "), "%s", "-SvxRuler::CreateAccessible(): No Parent!"
); } } while (false)
;
2752 uno::Reference< XAccessible > xAccParent = pParent->GetAccessible();
2753 if( xAccParent.is() )
2754 {
2755 // MT: Fixed compiler issue because the address from a temporary object was used.
2756 // BUT: Should it really be a Pointer, instead of const&???
2757 OUString aStr;
2758 if ( mnWinStyle & WB_HORZ )
2759 {
2760 aStr = SvtResId(STR_SVT_ACC_RULER_HORZ_NAMEreinterpret_cast<char const *>("STR_SVT_ACC_RULER_HORZ_NAME"
"\004" u8"Horizontal Ruler")
);
2761 }
2762 else
2763 {
2764 aStr = SvtResId(STR_SVT_ACC_RULER_VERT_NAMEreinterpret_cast<char const *>("STR_SVT_ACC_RULER_VERT_NAME"
"\004" u8"Vertical Ruler")
);
2765 }
2766 mxAccContext = new SvtRulerAccessible( xAccParent, *this, aStr );
2767 SetAccessible(mxAccContext.get());
2768 return mxAccContext.get();
2769 }
2770 else
2771 return uno::Reference< XAccessible >();
2772}
2773
2774/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx

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#ifndef INCLUDED_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
3
Calling copy constructor for 'Reference<VirtualDevice>'
6
Returning from copy constructor for 'Reference<VirtualDevice>'
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
7
Calling 'Reference::clear'
14
Returning; memory was released
205 if (aTmp.get()) {
15
Calling 'Reference::get'
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
2
Calling 'VclPtr::disposeAndClear'
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

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#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
4
Assuming field 'm_pBody' is non-null
5
Taking true branch
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody)
113 m_pBody->release();
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody
7.1
Field 'm_pBody' is non-null
7.1
Field 'm_pBody' is non-null
7.1
Field 'm_pBody' is non-null
7.1
Field 'm_pBody' is non-null
)
8
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
9
Calling 'VclReferenceBase::release'
13
Returning; memory was released
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
16
Use of memory after it is freed
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

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#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
10
Assuming the condition is true
11
Taking true branch
40 delete this;
12
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif