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