xref: /aoo42x/main/svtools/source/control/ruler.cxx (revision 2bfcd321)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26 
27 #include <string.h>
28 #include <tools/debug.hxx>
29 #include <vcl/svapp.hxx>
30 #include <tools/poly.hxx>
31 #include <vcl/i18nhelp.hxx>
32 
33 #define _SV_RULER_CXX
34 #include <svtools/ruler.hxx>
35 //IAccessibility2 Implementation 2009-----
36 #include <svtools/svtdata.hxx>
37 #include <svtools/svtools.hrc>
38 using namespace	::rtl;
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::uno;
41 using namespace ::com::sun::star::lang;
42 using namespace ::com::sun::star::accessibility;
43 //-----IAccessibility2 Implementation 2009
44 // =======================================================================
45 
46 #define RULER_OFF           3
47 #define RULER_TEXTOFF       2
48 #define RULER_RESIZE_OFF    4
49 #define RULER_LINE_WIDTH    7
50 #define RULER_MIN_SIZE      3
51 
52 #define RULER_TICK1_WIDTH   1
53 #define RULER_TICK2_WIDTH   3
54 #define RULER_TICK3_WIDTH   5
55 
56 #define RULER_VAR_SIZE      8
57 
58 #define RULER_TAB_HEIGHT2   2
59 #define RULER_TAB_WIDTH2    2
60 #define RULER_TAB_CWIDTH    8
61 #define RULER_TAB_CWIDTH2   4
62 #define RULER_TAB_CWIDTH3   4
63 #define RULER_TAB_CWIDTH4   2
64 #define RULER_TAB_DHEIGHT   4
65 #define RULER_TAB_DHEIGHT2  1
66 #define RULER_TAB_DWIDTH    5
67 #define RULER_TAB_DWIDTH2   3
68 #define RULER_TAB_DWIDTH3   3
69 #define RULER_TAB_DWIDTH4   1
70 
71 #define RULER_UPDATE_LINES  0x01
72 #define RULER_UPDATE_DRAW   0x02
73 
74 #define RULER_CLIP          150
75 
76 // =======================================================================
77 
78 #define RULER_UNIT_MM       0
79 #define RULER_UNIT_CM       1
80 #define RULER_UNIT_M        2
81 #define RULER_UNIT_KM       3
82 #define RULER_UNIT_INCH     4
83 #define RULER_UNIT_FOOT     5
84 #define RULER_UNIT_MILE     6
85 #define RULER_UNIT_POINT    7
86 #define RULER_UNIT_PICA     8
87 #define RULER_UNIT_COUNT    9
88 
89 // -----------------
90 // - ImplRulerData -
91 // -----------------
92 class ImplRulerData
93 {
94     friend              class Ruler;
95 
96 private:
97     RulerLine*          pLines;
98     RulerArrow*         pArrows;
99     RulerBorder*        pBorders;
100     RulerIndent*        pIndents;
101     RulerTab*           pTabs;
102     long                nNullVirOff;
103     long                nRulVirOff;
104     long                nRulWidth;
105     long                nPageOff;
106     long                nPageWidth;
107     long                nNullOff;
108     long                nMargin1;
109     long                nMargin2;
110     sal_uInt16              nLines;
111     sal_uInt16              nArrows;
112     sal_uInt16              nBorders;
113     sal_uInt16              nIndents;
114     sal_uInt16              nTabs;
115     sal_uInt16              nMargin1Style;
116     sal_uInt16              nMargin2Style;
117     sal_Bool                bAutoPageWidth;
118     sal_Bool                bTextRTL;
119 
120 #ifdef _SV_RULER_CXX
121 public:
122                         ImplRulerData();
123                         ~ImplRulerData();
124     ImplRulerData&      operator=( const ImplRulerData& rData );
125 #endif
126 };
127 
128 
129 struct ImplRulerUnitData
130 {
131     MapUnit         eMapUnit;           // MAP_UNIT zum Umrechnen
132     long            nTickUnit;          // Teiler fuer Einheit
133     long            nTick1;             // Schrittweite
134     long            nTick2;             // Tick fuer halbe Werte
135     long            nTick3;             // Tick fuer Zahlenausgabe
136     long            n100THMM;           // Teiler fuer Einheit
137     sal_uInt16          nUnitDigits;        // Anzahl Nachkommastellen
138     sal_Char        aUnitStr[8];        // Einheiten-String
139 };
140 
141 static ImplRulerUnitData aImplRulerUnitTab[RULER_UNIT_COUNT] =
142 {
143 { MAP_100TH_MM,        100,    25,     50,    100,     100, 3, " mm"    }, // MM
144 { MAP_100TH_MM,       1000,   250,    500,   1000,    1000, 3, " cm"    }, // CM
145 { MAP_MM,             1000,   250,    500,   1000,   10000, 4, " m"     }, // M
146 { MAP_CM,           100000, 25000,  50000, 100000,  100000, 6, " km"    }, // KM
147 { MAP_100TH_INCH,      100,    10,     50,    100,    2540, 3, "\""     }, // INCH
148 { MAP_100TH_INCH,     1200,   120,    600,   1200,   30480, 3, "'"      }, // FOOT
149 { MAP_10TH_INCH,    633600, 63360, 316800, 633600, 1609344, 4, " miles" }, // MILE
150 { MAP_POINT,             1,    12,     12,     36,     353, 2, " pt"    }, // POINT
151 { MAP_100TH_MM,        423,   423,    423,    846,     423, 3, " pi"    }  // PICA
152 };
153 
154 // =======================================================================
155 
156 struct ImplRulerHitTest
157 {
158     long        nPos;
159     RulerType   eType;
160     sal_uInt16      nAryPos;
161     sal_uInt16      mnDragSize;
162     sal_Bool        bSize;
163     sal_Bool        bSizeBar;
164     sal_Bool        bExpandTest;
165     ImplRulerHitTest() :
166         bExpandTest( sal_False ) {}
167 };
168 
169 // =======================================================================
170 
171 ImplRulerData::ImplRulerData()
172 {
173     memset( this, 0, sizeof( ImplRulerData ) );
174 
175     // PageBreite == EditWinBreite
176     bAutoPageWidth   = sal_True;
177 }
178 
179 // -----------------------------------------------------------------------
180 
181 ImplRulerData::~ImplRulerData()
182 {
183     delete[] pLines;
184     delete[] pArrows;
185     delete[] pBorders;
186     delete[] pIndents;
187     delete[] pTabs;
188 }
189 
190 // -----------------------------------------------------------------------
191 
192 ImplRulerData& ImplRulerData::operator=( const ImplRulerData& rData )
193 {
194     delete[] pLines;
195     delete[] pArrows;
196     delete[] pBorders;
197     delete[] pIndents;
198     delete[] pTabs;
199 
200     memcpy( this, &rData, sizeof( ImplRulerData ) );
201 
202     if ( rData.pLines )
203     {
204         pLines = new RulerLine[nLines];
205         memcpy( pLines, rData.pLines, nLines*sizeof( RulerLine ) );
206     }
207 
208     if ( rData.pArrows )
209     {
210         pArrows = new RulerArrow[nArrows];
211         memcpy( pArrows, rData.pArrows, nArrows*sizeof( RulerArrow ) );
212     }
213 
214     if ( rData.pBorders )
215     {
216         pBorders = new RulerBorder[nBorders];
217         memcpy( pBorders, rData.pBorders, nBorders*sizeof( RulerBorder ) );
218     }
219 
220     if ( rData.pIndents )
221     {
222         pIndents = new RulerIndent[nIndents];
223         memcpy( pIndents, rData.pIndents, nIndents*sizeof( RulerIndent ) );
224     }
225 
226     if ( rData.pTabs )
227     {
228         pTabs = new RulerTab[nTabs];
229         memcpy( pTabs, rData.pTabs, nTabs*sizeof( RulerTab ) );
230     }
231 
232     return *this;
233 }
234 
235 // =======================================================================
236 
237 void Ruler::ImplInit( WinBits nWinBits )
238 {
239     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
240 
241     // Default WinBits setzen
242     if ( !(nWinBits & WB_VERT) )
243     {
244         nWinBits |= WB_HORZ;
245 
246         // --- RTL --- no UI mirroring for horizontal rulers, because
247         // the document is also not mirrored
248         EnableRTL( sal_False );
249     }
250 
251     // Variablen initialisieren
252     mnWinStyle      = nWinBits;             // Window-Style
253     mnBorderOff     = 0;                    // Border-Offset
254     mnWinOff        = 0;                    // EditWinOffset
255     mnWinWidth      = 0;                    // EditWinWidth
256     mnWidth         = 0;                    // Fensterbreite
257     mnHeight        = 0;                    // Fensterhoehe
258     mnVirOff        = 0;                    // Offset des VirtualDeice vom linke/oberen Rand
259     mnVirWidth      = 0;                    // Breite bzw. Hoehe vom VirtualDevice
260     mnVirHeight     = 0;                    // Hoehe bzw. Breite vom VirtualDevice
261     mnDragPos       = 0;                    // Drag-Position (NullPunkt)
262     mnUpdateEvtId   = 0;                    // Noch kein Update-Event verschickt
263     mnDragAryPos    = 0;                    // Drag-Array-Index
264     mnDragSize      = 0;                    // Wird beim Draggen die Groesse geaendert
265     mnDragScroll    = 0;                    // Soll beim Draggen gescrollt werden
266     mnDragModifier  = 0;                    // Modifier-Tasten beim Draggen
267     mnExtraStyle    = 0;                    // Style des Extra-Feldes
268     mnExtraClicks   = 0;                    // Click-Anzahl fuer Extra-Feld
269     mnExtraModifier = 0;                    // Modifier-Tasten beim Click im Extrafeld
270     mbCalc          = sal_True;                 // Muessen Pagebreiten neu berechnet werden
271     mbFormat        = sal_True;                 // Muss neu ausgegeben werden
272     mbDrag          = sal_False;                // Sind wir im Drag-Modus
273     mbDragDelete    = sal_False;                // Wird Maus beim Draggen unten rausgezogen
274     mbDragCanceled  = sal_False;                // Wurde Dragging abgebrochen
275     mbAutoWinWidth  = sal_True;                 // EditWinBreite == RulerBreite
276     mbActive        = sal_True;                 // Ist Lineal aktiv
277     mnUpdateFlags   = 0;                    // Was soll im Update-Handler upgedatet werden
278     mpData          = mpSaveData;           // Wir zeigen auf die normalen Daten
279     meExtraType     = RULER_EXTRA_DONTKNOW; // Was im ExtraFeld dargestellt wird
280     meDragType      = RULER_TYPE_DONTKNOW;  // Gibt an, was gedragt wird
281 
282     // Units initialisieren
283     mnUnitIndex     = RULER_UNIT_CM;
284     meUnit          = FUNIT_CM;
285     maZoom          = Fraction( 1, 1 );
286     meSourceUnit    = MAP_100TH_MM;
287 
288     // Border-Breiten berechnen
289     if ( nWinBits & WB_BORDER )
290     {
291         if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
292             mnBorderWidth = 2;
293         else
294             mnBorderWidth = 1;
295     }
296     else
297         mnBorderWidth = 0;
298 
299     // Einstellungen setzen
300     ImplInitSettings( sal_True, sal_True, sal_True );
301 
302     // Default-Groesse setzen
303     long nDefHeight = GetTextHeight() + RULER_OFF*2 + RULER_TEXTOFF*2 + mnBorderWidth;
304     Size aDefSize;
305     if ( nWinBits & WB_HORZ )
306         aDefSize.Height() = nDefHeight;
307     else
308         aDefSize.Width() = nDefHeight;
309     SetOutputSizePixel( aDefSize );
310 	//IAccessibility2 Implementation 2009-----
311 	SetType(WINDOW_RULER);
312 	pAccContext = NULL;
313 	//-----IAccessibility2 Implementation 2009
314 }
315 
316 // -----------------------------------------------------------------------
317 
318 Ruler::Ruler( Window* pParent, WinBits nWinStyle ) :
319     Window( pParent, nWinStyle & WB_3DLOOK ),
320     maVirDev( *this ),
321     maMapMode( MAP_100TH_MM ),
322     mpSaveData(new ImplRulerData),
323     mpData(0),
324     mpDragData(new ImplRulerData)
325 {
326     ImplInit( nWinStyle );
327 }
328 
329 // -----------------------------------------------------------------------
330 
331 Ruler::~Ruler()
332 {
333     if ( mnUpdateEvtId )
334         Application::RemoveUserEvent( mnUpdateEvtId );
335     delete mpSaveData;
336     delete mpDragData;
337 	//IAccessibility2 Implementation 2009-----
338 	if( pAccContext )
339 		pAccContext->release();
340 	//-----IAccessibility2 Implementation 2009
341 }
342 
343 // -----------------------------------------------------------------------
344 
345 void Ruler::ImplVDrawLine( long nX1, long nY1, long nX2, long nY2 )
346 {
347     if ( nX1 < -RULER_CLIP )
348     {
349         nX1 = -RULER_CLIP;
350         if ( nX2 < -RULER_CLIP )
351             return;
352     }
353     long nClip = mnVirWidth+RULER_CLIP;
354     if ( nX2 > nClip )
355     {
356         nX2 = nClip;
357         if ( nX1 > nClip )
358             return;
359     }
360 
361     if ( mnWinStyle & WB_HORZ )
362         maVirDev.DrawLine( Point( nX1, nY1 ), Point( nX2, nY2 ) );
363     else
364         maVirDev.DrawLine( Point( nY1, nX1 ), Point( nY2, nX2 ) );
365 }
366 
367 // -----------------------------------------------------------------------
368 
369 void Ruler::ImplVDrawRect( long nX1, long nY1, long nX2, long nY2 )
370 {
371     if ( nX1 < -RULER_CLIP )
372     {
373         nX1 = -RULER_CLIP;
374         if ( nX2 < -RULER_CLIP )
375             return;
376     }
377     long nClip = mnVirWidth+RULER_CLIP;
378     if ( nX2 > nClip )
379     {
380         nX2 = nClip;
381         if ( nX1 > nClip )
382             return;
383     }
384 
385     if ( mnWinStyle & WB_HORZ )
386         maVirDev.DrawRect( Rectangle( nX1, nY1, nX2, nY2 ) );
387     else
388         maVirDev.DrawRect( Rectangle( nY1, nX1, nY2, nX2 ) );
389 }
390 
391 // -----------------------------------------------------------------------
392 
393 void Ruler::ImplVDrawText( long nX, long nY, const String& rText )
394 {
395     if ( (nX > -RULER_CLIP) && (nX < mnVirWidth+RULER_CLIP) )
396     {
397         if ( mnWinStyle & WB_HORZ )
398             maVirDev.DrawText( Point( nX, nY ), rText );
399         else
400             maVirDev.DrawText( Point( nY, nX ), rText );
401     }
402 }
403 
404 // -----------------------------------------------------------------------
405 
406 void Ruler::ImplInvertLines( sal_Bool bErase )
407 {
408     // Positionslinien
409     if ( mpData->nLines && mbActive && !mbDrag && !mbFormat &&
410          !(mnUpdateFlags & RULER_UPDATE_LINES) )
411     {
412         long n;
413         long nNullWinOff = mpData->nNullVirOff+mnVirOff;
414         long nRulX1 = mpData->nRulVirOff+mnVirOff;
415         long nRulX2 = nRulX1+mpData->nRulWidth;
416         long nY = (RULER_OFF*2)+mnVirHeight-1;
417 
418         // Rectangle berechnen
419         Rectangle aRect;
420         if ( mnWinStyle & WB_HORZ )
421             aRect.Bottom() = nY;
422         else
423             aRect.Right() = nY;
424 
425         // Linien ausgeben
426         for ( sal_uInt16 i = 0; i < mpData->nLines; i++ )
427         {
428             n = mpData->pLines[i].nPos+nNullWinOff;
429             if ( (n >= nRulX1) && (n < nRulX2) )
430             {
431                 if ( mnWinStyle & WB_HORZ )
432                 {
433                     aRect.Left()   = n;
434                     aRect.Right()  = n;
435                 }
436                 else
437                 {
438                     aRect.Top()    = n;
439                     aRect.Bottom() = n;
440                 }
441                 if ( bErase )
442                 {
443                     Rectangle aTempRect = aRect;
444                     if ( mnWinStyle & WB_HORZ )
445                         aTempRect.Bottom() = RULER_OFF-1;
446                     else
447                         aTempRect.Right() = RULER_OFF-1;
448                     Erase( aTempRect );
449                     if ( mnWinStyle & WB_HORZ )
450                     {
451                         aTempRect.Bottom() = aRect.Bottom();
452                         aTempRect.Top()    = aTempRect.Bottom()-RULER_OFF+1;
453                     }
454                     else
455                     {
456                         aTempRect.Right()  = aRect.Right();
457                         aTempRect.Left()   = aTempRect.Right()-RULER_OFF+1;
458                     }
459                     Erase( aTempRect );
460                 }
461                 Invert( aRect );
462             }
463         }
464     }
465 }
466 
467 // -----------------------------------------------------------------------
468 
469 void Ruler::ImplDrawTicks( long nMin, long nMax, long nStart, long nCenter )
470 {
471     long    n = 0;
472     long    nTick = 0;
473     long    nTick3 = aImplRulerUnitTab[mnUnitIndex].nTick3;
474     long    nTickCount = aImplRulerUnitTab[mnUnitIndex].nTick1;
475     Size    aPixSize = maVirDev.LogicToPixel( Size( nTick3, nTick3 ), maMapMode );
476     long    nTickWidth;
477     long    nX;
478     long    nY;
479     sal_Bool    bNoTicks = sal_False;
480 
481     // Groessenvorberechnung
482     // Sizes calculation
483     sal_Bool bVertRight = sal_False;
484     if ( mnWinStyle & WB_HORZ )
485         nTickWidth = aPixSize.Width();
486     else
487     {
488         Font aFont = GetFont();
489         if ( mnWinStyle & WB_RIGHT_ALIGNED )
490         {
491             aFont.SetOrientation( 2700 );
492             bVertRight = sal_True;
493         }
494         else
495             aFont.SetOrientation( 900 );
496         maVirDev.SetFont( aFont );
497         nTickWidth = aPixSize.Height();
498     }
499     long nMaxWidth = maVirDev.PixelToLogic( Size( mpData->nPageWidth, 0 ), maMapMode ).Width();
500     if ( nMaxWidth < 0 )
501         nMaxWidth = -nMaxWidth;
502     nMaxWidth /= aImplRulerUnitTab[mnUnitIndex].nTickUnit;
503     UniString aNumStr( UniString::CreateFromInt32( nMaxWidth ) );
504     long nTxtWidth = GetTextWidth( aNumStr );
505 
506     const long nTextOff   = 4;
507     if ( nTickWidth < nTxtWidth+nTextOff )
508     {
509         // Calculate the scale of the ruler
510         long nMulti     = 1;
511         long nOrgTick3  = nTick3;
512         while ( nTickWidth < nTxtWidth+nTextOff )
513         {
514             long nOldMulti = nMulti;
515             if ( !nTickWidth ) //If nTickWidth equals 0
516                 nMulti *= 10;
517             else if ( nMulti < 10 )
518                 nMulti++;
519             else if ( nMulti < 100 )
520                 nMulti += 10;
521             else if ( nMulti < 1000 )
522                 nMulti += 100;
523             else
524                 nMulti += 1000;
525             // Ueberlauf, dann geben wir nichts aus, da wir bei so einem
526             // unsinnigen Massstab sowieso nichts vernuenftiges anzeigen
527             // koennen
528             if ( nMulti < nOldMulti )
529             {
530                 bNoTicks = sal_True;
531                 break;
532             }
533 
534             nTick3 = nOrgTick3 * nMulti;
535             aPixSize = maVirDev.LogicToPixel( Size( nTick3, nTick3 ), maMapMode );
536             if ( mnWinStyle & WB_HORZ )
537                 nTickWidth = aPixSize.Width();
538             else
539                 nTickWidth = aPixSize.Height();
540         }
541         nTickCount = nTick3;
542     }
543     else
544         maVirDev.SetLineColor( GetSettings().GetStyleSettings().GetWindowTextColor() );
545 
546     if ( !bNoTicks )
547     {
548         long nTxtWidth2;
549         long nTxtHeight2 = GetTextHeight()/2;
550         while ( ((nStart-n) >= nMin) || ((nStart+n) <= nMax) )
551         {
552             // Null-Punkt
553             if ( !nTick )
554             {
555                 if ( nStart > nMin )
556                 {
557                     // 0 is only painted when Margin1 is not equal to zero
558                     if ( (mpData->nMargin1Style & RULER_STYLE_INVISIBLE) || (mpData->nMargin1 != 0) )
559                     {
560                         aNumStr = (sal_Unicode)'0';
561                         nTxtWidth2 = maVirDev.GetTextWidth( aNumStr )/2;
562                         if ( (mnWinStyle & WB_HORZ)^mpData->bTextRTL )
563                             nX = nStart-nTxtWidth2;
564                         else
565                             nX = nStart+nTxtWidth2;
566                         long n_Y = bVertRight ? nCenter+nTxtHeight2 : nCenter-nTxtHeight2;
567 						ImplVDrawText( nX, n_Y, aNumStr );
568                     }
569                 }
570             }
571             else
572             {
573                 aPixSize = maVirDev.LogicToPixel( Size( nTick, nTick ), maMapMode );
574 
575                 if ( mnWinStyle & WB_HORZ )
576                     n = aPixSize.Width();
577                 else
578                     n = aPixSize.Height();
579 
580                 // Tick3 - Output (Text)
581                 if ( !(nTick % nTick3) )
582                 {
583                     aNumStr = UniString::CreateFromInt32( nTick / aImplRulerUnitTab[mnUnitIndex].nTickUnit );
584                     nTxtWidth2 = GetTextWidth( aNumStr )/2;
585 
586                     nX = nStart+n;
587                     //different orientation needs a different starting position
588                     nY = bVertRight ? nCenter+nTxtHeight2 : nCenter-nTxtHeight2;
589 
590                     // Check if we can display full number
591                     if ( nX < (nMax-nTxtWidth2) )
592                     {
593                         if ( mnWinStyle & WB_HORZ )
594                             nX -= nTxtWidth2;
595                         else
596                             nX += nTxtWidth2;
597                         ImplVDrawText( nX, nY, aNumStr );
598                     }
599                     nX = nStart-n;
600                     if ( nX > (nMin+nTxtWidth2) )
601                     {
602                         if ( mnWinStyle & WB_HORZ )
603                             nX -= nTxtWidth2;
604                         else
605                             nX += nTxtWidth2;
606                         ImplVDrawText( nX, nY, aNumStr );
607                     }
608                 }
609                 // Tick/Tick2 - Output (Strokes)
610                 else
611                 {
612                     if ( !(nTick % aImplRulerUnitTab[mnUnitIndex].nTick2) )
613                         nTickWidth = RULER_TICK2_WIDTH;
614                     else
615                         nTickWidth = RULER_TICK1_WIDTH;
616                     long nT1 = nCenter-(nTickWidth/2);
617                     long nT2 = nT1+nTickWidth-1;
618                     long nT;
619 
620                     nT = nStart+n;
621                     if ( nT < nMax )
622                         ImplVDrawLine( nT, nT1, nT, nT2 );
623                     nT = nStart-n;
624                     if ( nT > nMin )
625                         ImplVDrawLine( nT, nT1, nT, nT2 );
626                 }
627             }
628             // #i49017# with some zoom factors the value nTick can overflow
629             if( ((sal_uLong)nTick + (sal_uLong)nTickCount) > (sal_uLong)LONG_MAX)
630                 break;
631             nTick += nTickCount;
632         }
633     }
634 }
635 
636 // -----------------------------------------------------------------------
637 
638 void Ruler::ImplDrawArrows( long nCenter )
639 {
640     sal_uInt16          i;
641     long            n1;
642     long            n2;
643     long            n3;
644     long            n4;
645     long            nLogWidth;
646     String          aStr;
647     String          aStr2;
648     sal_Bool            bDrawUnit;
649     long            nTxtWidth;
650     long            nTxtHeight2 = GetTextHeight()/2;
651 
652     const vcl::I18nHelper& rI18nHelper = GetSettings().GetLocaleI18nHelper();
653 
654     maVirDev.SetLineColor( GetSettings().GetStyleSettings().GetWindowTextColor() );
655     for ( i = 0; i < mpData->nArrows; i++ )
656     {
657         n1 = mpData->pArrows[i].nPos+mpData->nNullVirOff+1;
658         n2 = n1+mpData->pArrows[i].nWidth-2;
659 
660         // Einheit umrechnen
661         nLogWidth = mpData->pArrows[i].nLogWidth;
662         if ( meSourceUnit == MAP_TWIP )
663         {
664             if ( nLogWidth >= 100000 )
665                 nLogWidth = (nLogWidth*254)/144;
666             else
667                 nLogWidth = (nLogWidth*2540)/1440;
668         }
669         if ( nLogWidth >= 1000000 )
670             nLogWidth = (nLogWidth / aImplRulerUnitTab[mnUnitIndex].n100THMM) * 1000;
671         else
672             nLogWidth = (nLogWidth*1000) / aImplRulerUnitTab[mnUnitIndex].n100THMM;
673 		aStr = rI18nHelper.GetNum( nLogWidth, aImplRulerUnitTab[mnUnitIndex].nUnitDigits, sal_True, sal_False );
674 
675         // Einheit an den String haengen
676         aStr2 = aStr;
677         aStr2.AppendAscii( aImplRulerUnitTab[mnUnitIndex].aUnitStr );
678 
679         // Textbreite ermitteln
680         bDrawUnit = sal_True;
681         nTxtWidth = GetTextWidth( aStr2 );
682         if ( nTxtWidth < mpData->pArrows[i].nWidth-10 )
683             aStr = aStr2;
684         else
685         {
686             nTxtWidth = GetTextWidth( aStr );
687             if ( nTxtWidth > mpData->pArrows[i].nWidth-10 )
688                 bDrawUnit = sal_False;
689         }
690 
691         // Ist genuegen Platz fuer Einheiten-String vorhanden
692         if ( bDrawUnit )
693         {
694             n3 = n1 + ((n2-n1)/2) - 1;
695             if ( mnWinStyle & WB_HORZ )
696                 n3 -= nTxtWidth/2;
697             else
698                 n3 += nTxtWidth/2;
699             if ( mnWinStyle & WB_HORZ )
700             {
701                 n4 = n3 + nTxtWidth + 2;
702                 ImplVDrawLine( n1, nCenter, n3, nCenter );
703                 ImplVDrawLine( n4, nCenter, n2, nCenter );
704             }
705             else
706             {
707                 n4 = n3 - nTxtWidth - 2;
708                 ImplVDrawLine( n1, nCenter, n4, nCenter );
709                 ImplVDrawLine( n3, nCenter, n2, nCenter );
710             }
711             ImplVDrawText( n3, nCenter-nTxtHeight2, aStr );
712         }
713         else
714             ImplVDrawLine( n1, nCenter, n2, nCenter );
715         ImplVDrawLine( n1+1, nCenter-1, n1+1, nCenter+1 );
716         ImplVDrawLine( n1+2, nCenter-2, n1+2, nCenter+2 );
717         ImplVDrawLine( n2-1, nCenter-1, n2-1, nCenter+1 );
718         ImplVDrawLine( n2-2, nCenter-2, n2-2, nCenter+2 );
719     }
720 }
721 
722 // -----------------------------------------------------------------------
723 
724 void Ruler::ImplDrawBorders( long nMin, long nMax, long nVirTop, long nVirBottom )
725 {
726     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
727     long    n;
728     long    n1;
729     long    n2;
730     long    nTemp1;
731     long    nTemp2;
732     sal_uInt16  i;
733 
734     for ( i = 0; i < mpData->nBorders; i++ )
735     {
736         if ( mpData->pBorders[i].nStyle & RULER_STYLE_INVISIBLE )
737             continue;
738 
739         n1 = mpData->pBorders[i].nPos+mpData->nNullVirOff;
740         n2 = n1+mpData->pBorders[i].nWidth;
741 
742         if ( ((n1 >= nMin) && (n1 <= nMax)) || ((n2 >= nMin) && (n2 <= nMax)) )
743         {
744             if ( (n2-n1) > 3 )
745             {
746                 maVirDev.SetLineColor();
747                 if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
748                     maVirDev.SetFillColor( rStyleSettings.GetFaceColor() );
749                 else
750                     maVirDev.SetFillColor( rStyleSettings.GetWindowColor() );
751                 ImplVDrawRect( n1, nVirTop, n2, nVirBottom );
752                 if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
753                 {
754                     maVirDev.SetLineColor( rStyleSettings.GetLightColor() );
755                     ImplVDrawLine( n1+1, nVirTop, n1+1, nVirBottom );
756                     ImplVDrawLine( n1, nVirTop, n2, nVirTop );
757                     maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
758                     ImplVDrawLine( n1, nVirTop, n1, nVirBottom );
759                     ImplVDrawLine( n1, nVirBottom, n2, nVirBottom );
760                     ImplVDrawLine( n2-1, nVirTop, n2-1, nVirBottom );
761                     maVirDev.SetLineColor( rStyleSettings.GetWindowTextColor() );
762                     ImplVDrawLine( n2, nVirTop, n2, nVirBottom );
763                 }
764                 else
765                 {
766                     maVirDev.SetLineColor( rStyleSettings.GetWindowTextColor() );
767                     ImplVDrawLine( n1, nVirTop, n1, nVirBottom );
768                     ImplVDrawLine( n2, nVirTop, n2, nVirBottom );
769                 }
770 
771                 if ( mpData->pBorders[i].nStyle & RULER_BORDER_VARIABLE )
772                 {
773                     if ( n2-n1 > RULER_VAR_SIZE+4 )
774                     {
775                         nTemp1 = n1 + (((n2-n1+1)-RULER_VAR_SIZE) / 2);
776                         nTemp2 = nVirTop + (((nVirBottom-nVirTop+1)-RULER_VAR_SIZE) / 2);
777                         long nTemp3 = nTemp1+RULER_VAR_SIZE-1;
778                         long nTemp4 = nTemp2+RULER_VAR_SIZE-1;
779                         long nTempY = nTemp2;
780                         if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
781                             maVirDev.SetLineColor( rStyleSettings.GetLightColor() );
782                         else
783                             maVirDev.SetLineColor( rStyleSettings.GetWindowTextColor() );
784                         while ( nTempY <= nTemp4 )
785                         {
786                             ImplVDrawLine( nTemp1, nTempY, nTemp3, nTempY );
787                             nTempY += 2;
788                         }
789                         if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
790                         {
791                             nTempY = nTemp2+1;
792                             maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
793                             while ( nTempY <= nTemp4 )
794                             {
795                                 ImplVDrawLine( nTemp1, nTempY, nTemp3, nTempY );
796                                 nTempY += 2;
797                             }
798                         }
799                     }
800                 }
801 
802                 if ( mpData->pBorders[i].nStyle & RULER_BORDER_SIZEABLE )
803                 {
804                     if ( n2-n1 > RULER_VAR_SIZE+10 )
805                     {
806                         if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
807                         {
808                             maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
809                             ImplVDrawLine( n1+4, nVirTop+3, n1+4, nVirBottom-3 );
810                             ImplVDrawLine( n2-5, nVirTop+3, n2-5, nVirBottom-3 );
811                             maVirDev.SetLineColor( rStyleSettings.GetLightColor() );
812                             ImplVDrawLine( n1+5, nVirTop+3, n1+5, nVirBottom-3 );
813                             ImplVDrawLine( n2-4, nVirTop+3, n2-4, nVirBottom-3 );
814                         }
815                         else
816                         {
817                             maVirDev.SetLineColor( rStyleSettings.GetWindowTextColor() );
818                             ImplVDrawLine( n1+4, nVirTop+3, n1+4, nVirBottom-3 );
819                             ImplVDrawLine( n2-4, nVirTop+3, n2-4, nVirBottom-3 );
820                         }
821                     }
822                 }
823             }
824             else
825             {
826                 n = n1+((n2-n1)/2);
827                 if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
828                     maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
829                 else
830                     maVirDev.SetLineColor( rStyleSettings.GetWindowTextColor() );
831                 if ( mpData->pBorders[i].nStyle & RULER_BORDER_SNAP )
832                     ImplVDrawLine( n, nVirTop, n, nVirBottom );
833                 else if ( mpData->pBorders[i].nStyle & RULER_BORDER_MARGIN )
834                     ImplVDrawLine( n, nVirTop, n, nVirBottom );
835                 else
836                 {
837                     ImplVDrawLine( n-1, nVirTop, n-1, nVirBottom );
838                     ImplVDrawLine( n+1, nVirTop, n+1, nVirBottom );
839                     maVirDev.SetLineColor();
840                     maVirDev.SetFillColor( rStyleSettings.GetWindowColor() );
841                     ImplVDrawRect( n, nVirTop, n, nVirBottom );
842                 }
843             }
844         }
845     }
846 }
847 
848 // -----------------------------------------------------------------------
849 
850 void Ruler::ImplDrawIndent( const Polygon& rPoly, sal_uInt16 nStyle )
851 {
852     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
853     Point   aPos1;
854     Point   aPos2;
855     sal_uInt16  nIndentStyle = nStyle & RULER_INDENT_STYLE;
856 
857     if ( nStyle & RULER_STYLE_INVISIBLE )
858         return;
859 
860     if ( nStyle & RULER_STYLE_DONTKNOW )
861     {
862         maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
863         maVirDev.SetFillColor( rStyleSettings.GetFaceColor() );
864     }
865     else
866     {
867         maVirDev.SetLineColor( rStyleSettings.GetDarkShadowColor() );
868         maVirDev.SetFillColor( rStyleSettings.GetFaceColor() );
869     }
870 
871     maVirDev.DrawPolygon( rPoly );
872 
873     if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) && !(nStyle & RULER_STYLE_DONTKNOW) )
874     {
875         if ( nIndentStyle == RULER_INDENT_BOTTOM )
876         {
877             maVirDev.SetLineColor( rStyleSettings.GetLightColor() );
878             aPos1 = rPoly.GetPoint( 2 );
879             aPos1.X()++;
880             aPos2 = rPoly.GetPoint( 1 );
881             aPos2.X()++;
882             maVirDev.DrawLine( aPos2, aPos1 );
883             aPos2.X()--;
884             aPos2.Y()++;
885             aPos1 = rPoly.GetPoint( 0 );
886             aPos1.Y()++;
887             maVirDev.DrawLine( aPos2, aPos1 );
888             maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
889             aPos2 = rPoly.GetPoint( 4 );
890             aPos2.Y()++;
891             maVirDev.DrawLine( aPos1, aPos2 );
892             aPos2.X()--;
893             aPos1 = rPoly.GetPoint( 3 );
894             aPos1.X()--;
895             maVirDev.DrawLine( aPos2, aPos1 );
896             aPos1.Y()--;
897             aPos2 = rPoly.GetPoint( 2 );
898             aPos2.X()++;
899             aPos2.Y()--;
900             maVirDev.DrawLine( aPos2, aPos1 );
901         }
902         else
903         {
904             maVirDev.SetLineColor( rStyleSettings.GetLightColor() );
905             aPos1 = rPoly.GetPoint( 2 );
906             aPos1.X()++;
907             aPos1.Y()++;
908             aPos2 = rPoly.GetPoint( 3 );
909             aPos2.Y()++;
910             maVirDev.DrawLine( aPos1, aPos2 );
911             aPos2 = rPoly.GetPoint( 1 );
912             aPos2.X()++;
913             maVirDev.DrawLine( aPos1, aPos2 );
914             aPos2.X()--;
915             aPos2.Y()--;
916             aPos1 = rPoly.GetPoint( 0 );
917             aPos1.Y()--;
918             maVirDev.DrawLine( aPos2, aPos1 );
919             maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
920             aPos2 = rPoly.GetPoint( 4 );
921             aPos2.Y()--;
922             maVirDev.DrawLine( aPos1, aPos2 );
923             aPos2.X()--;
924             aPos1 = rPoly.GetPoint( 3 );
925             aPos1.X()--;
926             maVirDev.DrawLine( aPos2, aPos1 );
927         }
928 
929         maVirDev.SetLineColor( rStyleSettings.GetDarkShadowColor() );
930         maVirDev.SetFillColor();
931         maVirDev.DrawPolygon( rPoly );
932     }
933 }
934 
935 // -----------------------------------------------------------------------
936 
937 void Ruler::ImplDrawIndents( long nMin, long nMax, long nVirTop, long nVirBottom )
938 {
939     sal_uInt16  j;
940     long    n;
941     long    nIndentHeight = (mnVirHeight/2) - 1;
942     long    nIndentWidth2 = nIndentHeight-3;
943     Polygon aPoly( 5 );
944 
945     for ( j = 0; j < mpData->nIndents; j++ )
946     {
947         if ( mpData->pIndents[j].nStyle & RULER_STYLE_INVISIBLE )
948             continue;
949 
950         sal_uInt16  nStyle = mpData->pIndents[j].nStyle;
951         sal_uInt16  nIndentStyle = nStyle & RULER_INDENT_STYLE;
952 
953         n = mpData->pIndents[j].nPos+mpData->nNullVirOff;
954 
955         if ( (n >= nMin) && (n <= nMax) )
956         {
957             if(nIndentStyle == RULER_INDENT_BORDER)
958             {
959 				const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
960 				maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
961                 ImplVDrawLine( n, nVirTop, n, nVirBottom );
962             }
963             else if ( nIndentStyle == RULER_INDENT_BOTTOM )
964             {
965                 aPoly.SetPoint( Point( n+0, nVirBottom-nIndentHeight ), 0 );
966                 aPoly.SetPoint( Point( n-nIndentWidth2, nVirBottom-3 ), 1 );
967                 aPoly.SetPoint( Point( n-nIndentWidth2, nVirBottom ), 2 );
968                 aPoly.SetPoint( Point( n+nIndentWidth2, nVirBottom ), 3 );
969                 aPoly.SetPoint( Point( n+nIndentWidth2, nVirBottom-3 ), 4 );
970             }
971             else
972             {
973                 aPoly.SetPoint( Point( n+0, nVirTop+nIndentHeight ), 0 );
974                 aPoly.SetPoint( Point( n-nIndentWidth2, nVirTop+3 ), 1 );
975                 aPoly.SetPoint( Point( n-nIndentWidth2, nVirTop ), 2 );
976                 aPoly.SetPoint( Point( n+nIndentWidth2, nVirTop ), 3 );
977                 aPoly.SetPoint( Point( n+nIndentWidth2, nVirTop+3 ), 4 );
978             }
979 
980             if(0 == (mnWinStyle & WB_HORZ))
981             {
982                 Point aTmp;
983                 for(sal_uInt16 i = 0; i < 5; i++)
984                 {
985                     aTmp = aPoly[i];
986                     Point aSet(nVirBottom - aTmp.Y(), aTmp.X());
987                     aPoly[i] = aSet;
988                 }
989             }
990             if(RULER_INDENT_BORDER != nIndentStyle)
991 				ImplDrawIndent( aPoly, nStyle );
992         }
993     }
994 }
995 
996 // -----------------------------------------------------------------------
997 
998 static void ImplCenterTabPos( Point& rPos, sal_uInt16 nTabStyle )
999 {
1000     sal_Bool bRTL  = 0 != (nTabStyle & RULER_TAB_RTL);
1001     nTabStyle &= RULER_TAB_STYLE;
1002     rPos.Y() += RULER_TAB_HEIGHT/2;
1003     if ( (!bRTL && nTabStyle == RULER_TAB_LEFT) ||( bRTL && nTabStyle == RULER_TAB_RIGHT))
1004         rPos.X() -= RULER_TAB_WIDTH/2;
1005     else if ( (!bRTL && nTabStyle == RULER_TAB_RIGHT) ||( bRTL && nTabStyle == RULER_TAB_LEFT))
1006         rPos.X() += RULER_TAB_WIDTH/2;
1007 }
1008 
1009 // -----------------------------------------------------------------------
1010 void lcl_RotateRect_Impl(Rectangle& rRect, const long nReference, sal_Bool bRightAligned)
1011 {
1012     if(!rRect.IsEmpty())
1013     {
1014         Rectangle aTmp(rRect);
1015         rRect.Top() = aTmp.Left();
1016         rRect.Bottom() = aTmp.Right();
1017         rRect.Left() = aTmp.Top();
1018         rRect.Right() = aTmp.Bottom();
1019         if(bRightAligned)
1020         {
1021             long nRef = 2 * nReference;
1022 			rRect.Left() = nRef - rRect.Left();
1023             rRect.Right() = nRef - rRect.Right();
1024         }
1025     }
1026 }
1027 // -----------------------------------------------------------------------
1028 
1029 static void ImplDrawRulerTab( OutputDevice* pDevice,
1030                              const Point& rPos, sal_uInt16 nStyle, WinBits nWinBits )
1031 {
1032     if ( nStyle & RULER_STYLE_INVISIBLE )
1033         return;
1034 
1035     sal_uInt16 nTabStyle = nStyle & RULER_TAB_STYLE;
1036     sal_Bool bRTL = 0 != (nStyle & RULER_TAB_RTL);
1037     Rectangle aRect1, aRect2, aRect3;
1038     aRect3.SetEmpty();
1039     if ( nTabStyle == RULER_TAB_DEFAULT )
1040     {
1041         aRect1.Left() =     rPos.X() - RULER_TAB_DWIDTH2 + 1                ;
1042         aRect1.Top() =      rPos.Y() - RULER_TAB_DHEIGHT2 + 1               ;
1043         aRect1.Right() =    rPos.X() - RULER_TAB_DWIDTH2 + RULER_TAB_DWIDTH ;
1044         aRect1.Bottom() =   rPos.Y();
1045         aRect2.Left() =     rPos.X() - RULER_TAB_DWIDTH2 + RULER_TAB_DWIDTH3;
1046         aRect2.Top() =      rPos.Y() - RULER_TAB_DHEIGHT + 1;
1047         aRect2.Right() =    rPos.X() - RULER_TAB_DWIDTH2 + RULER_TAB_DWIDTH3 + RULER_TAB_DWIDTH4 - 1;
1048         aRect2.Bottom() =   rPos.Y();
1049 
1050     }
1051     else if ( (!bRTL && nTabStyle == RULER_TAB_LEFT) ||( bRTL && nTabStyle == RULER_TAB_RIGHT))
1052     {
1053         aRect1.Left() =     rPos.X();
1054         aRect1.Top() =      rPos.Y() - RULER_TAB_HEIGHT2 + 1;
1055         aRect1.Right() =    rPos.X() + RULER_TAB_WIDTH - 1;
1056         aRect1.Bottom() =   rPos.Y();
1057         aRect2.Left() =     rPos.X();
1058         aRect2.Top() =      rPos.Y() - RULER_TAB_HEIGHT + 1;
1059         aRect2.Right() =    rPos.X() + RULER_TAB_WIDTH2 - 1;
1060         aRect2.Bottom() =   rPos.Y();
1061     }
1062     else if ( (!bRTL && nTabStyle == RULER_TAB_RIGHT) ||( bRTL && nTabStyle == RULER_TAB_LEFT))
1063     {
1064         aRect1.Left() =     rPos.X() - RULER_TAB_WIDTH + 1;
1065         aRect1.Top() =      rPos.Y() - RULER_TAB_HEIGHT2 + 1;
1066         aRect1.Right() =    rPos.X();
1067         aRect1.Bottom() =   rPos.Y();
1068         aRect2.Left() =     rPos.X() - RULER_TAB_WIDTH2 + 1;
1069         aRect2.Top() =      rPos.Y() - RULER_TAB_HEIGHT + 1;
1070         aRect2.Right() =    rPos.X();
1071         aRect2.Bottom() =   rPos.Y();
1072     }
1073     else
1074     {
1075         aRect1.Left() =     rPos.X() - RULER_TAB_CWIDTH2 + 1;
1076         aRect1.Top() =      rPos.Y() - RULER_TAB_HEIGHT2 + 1;
1077         aRect1.Right() =    rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH;
1078         aRect1.Bottom() =   rPos.Y();
1079         aRect2.Left() =     rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH3;
1080         aRect2.Top() =      rPos.Y() - RULER_TAB_HEIGHT + 1;
1081         aRect2.Right() =    rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH3 + RULER_TAB_CWIDTH4 - 1;
1082         aRect2.Bottom() =   rPos.Y();
1083 
1084         if ( nTabStyle == RULER_TAB_DECIMAL )
1085         {
1086             aRect3.Left() = rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH - 1;
1087             aRect3.Top()  = rPos.Y() - RULER_TAB_HEIGHT + 1 + 1;
1088             aRect3.Right() = rPos.X() - RULER_TAB_CWIDTH2 + RULER_TAB_CWIDTH;
1089             aRect3.Bottom()= rPos.Y() - RULER_TAB_HEIGHT + 1 + 2 ;
1090         }
1091     }
1092     if( 0 == (nWinBits&WB_HORZ) )
1093     {
1094         sal_Bool bRightAligned = 0 != (nWinBits&WB_RIGHT_ALIGNED);
1095         lcl_RotateRect_Impl(aRect1, rPos.Y(), bRightAligned);
1096         lcl_RotateRect_Impl(aRect2, rPos.Y(), bRightAligned);
1097         lcl_RotateRect_Impl(aRect3, rPos.Y(), bRightAligned);
1098     }
1099     pDevice->DrawRect( aRect1 );
1100     pDevice->DrawRect( aRect2 );
1101     if(!aRect2.IsEmpty())
1102         pDevice->DrawRect( aRect3 );
1103 
1104 }
1105 
1106 // -----------------------------------------------------------------------
1107 
1108 void Ruler::ImplDrawTab( OutputDevice* pDevice, const Point& rPos, sal_uInt16 nStyle )
1109 {
1110     if ( nStyle & RULER_STYLE_INVISIBLE )
1111         return;
1112 
1113     pDevice->SetLineColor();
1114     if ( nStyle & RULER_STYLE_DONTKNOW )
1115         pDevice->SetFillColor( GetSettings().GetStyleSettings().GetFaceColor() );
1116     else
1117         pDevice->SetFillColor( GetSettings().GetStyleSettings().GetWindowTextColor() );
1118 
1119     if(mpData->bTextRTL)
1120         nStyle |= RULER_TAB_RTL;
1121     ImplDrawRulerTab( pDevice, rPos, nStyle, GetStyle());
1122 }
1123 
1124 // -----------------------------------------------------------------------
1125 
1126 void Ruler::ImplDrawTabs( long nMin, long nMax, long nVirTop, long nVirBottom )
1127 {
1128     for ( sal_uInt16 i = 0; i < mpData->nTabs; i++ )
1129     {
1130         if ( mpData->pTabs[i].nStyle & RULER_STYLE_INVISIBLE )
1131             continue;
1132 
1133         long n;
1134             n = mpData->pTabs[i].nPos;
1135 		n += +mpData->nNullVirOff;
1136         long nTopBottom = GetStyle() & WB_RIGHT_ALIGNED ? nVirTop : nVirBottom;
1137         if ( (n >= nMin) && (n <= nMax) )
1138             ImplDrawTab( &maVirDev, Point( n, nTopBottom ), mpData->pTabs[i].nStyle );
1139     }
1140 }
1141 
1142 // -----------------------------------------------------------------------
1143 
1144 void Ruler::ImplInitSettings( sal_Bool bFont,
1145                               sal_Bool bForeground, sal_Bool bBackground )
1146 {
1147     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1148 
1149     if ( bFont )
1150     {
1151         Font aFont;
1152         aFont = rStyleSettings.GetToolFont();
1153         if ( IsControlFont() )
1154             aFont.Merge( GetControlFont() );
1155         SetZoomedPointFont( aFont );
1156     }
1157 
1158     if ( bForeground || bFont )
1159     {
1160         Color aColor;
1161         if ( IsControlForeground() )
1162             aColor = GetControlForeground();
1163         else
1164             aColor = rStyleSettings.GetWindowTextColor();
1165         SetTextColor( aColor );
1166         SetTextFillColor();
1167     }
1168 
1169     if ( bBackground )
1170     {
1171         Color aColor;
1172         if ( IsControlBackground() )
1173             aColor = GetControlBackground();
1174         else
1175             aColor = rStyleSettings.GetFaceColor();
1176         SetBackground( aColor );
1177     }
1178 
1179     maVirDev.SetSettings( GetSettings() );
1180     maVirDev.SetBackground( GetBackground() );
1181     Font aFont = GetFont();
1182     if ( mnWinStyle & WB_VERT )
1183         aFont.SetOrientation( 900 );
1184     maVirDev.SetFont( aFont );
1185     maVirDev.SetTextColor( GetTextColor() );
1186     maVirDev.SetTextFillColor( GetTextFillColor() );
1187 }
1188 
1189 // -----------------------------------------------------------------------
1190 
1191 void Ruler::ImplCalc()
1192 {
1193     // Offset berechnen
1194     mpData->nRulVirOff = mnWinOff + mpData->nPageOff;
1195     if ( mpData->nRulVirOff > mnVirOff )
1196         mpData->nRulVirOff -= mnVirOff;
1197     else
1198         mpData->nRulVirOff = 0;
1199     long nRulWinOff = mpData->nRulVirOff+mnVirOff;
1200 
1201     // Nicht sichtbaren Bereich der Page berechnen
1202     long nNotVisPageWidth;
1203     if ( mpData->nPageOff < 0 )
1204     {
1205         nNotVisPageWidth = -(mpData->nPageOff);
1206         if ( nRulWinOff < mnWinOff )
1207             nNotVisPageWidth -= mnWinOff-nRulWinOff;
1208     }
1209     else
1210         nNotVisPageWidth = 0;
1211 
1212     // Breite berechnen
1213     if ( mnWinStyle & WB_HORZ )
1214     {
1215         if ( mbAutoWinWidth )
1216             mnWinWidth = mnWidth - mnVirOff;
1217         if ( mpData->bAutoPageWidth )
1218             mpData->nPageWidth = mnWinWidth;
1219         mpData->nRulWidth = Min( mnWinWidth, mpData->nPageWidth-nNotVisPageWidth );
1220         if ( nRulWinOff+mpData->nRulWidth > mnWidth )
1221             mpData->nRulWidth = mnWidth-nRulWinOff;
1222     }
1223     else
1224     {
1225         if ( mbAutoWinWidth )
1226             mnWinWidth = mnHeight - mnVirOff;
1227         if ( mpData->bAutoPageWidth )
1228             mpData->nPageWidth = mnWinWidth;
1229         mpData->nRulWidth = Min( mnWinWidth, mpData->nPageWidth-nNotVisPageWidth );
1230         if ( nRulWinOff+mpData->nRulWidth > mnHeight )
1231             mpData->nRulWidth = mnHeight-nRulWinOff;
1232     }
1233 
1234     mbCalc = sal_False;
1235 }
1236 
1237 // -----------------------------------------------------------------------
1238 
1239 void Ruler::ImplFormat()
1240 {
1241     // Wenn schon formatiert ist, brauchen wir es nicht nochmal
1242     if ( !mbFormat )
1243         return;
1244 
1245     // Wenn Fenster noch keine Groesse hat, brauchen wir noch nichts machen
1246     if ( !mnVirWidth )
1247         return;
1248 
1249     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1250     long    nP1;            // Pixel-Position von Page1
1251     long    nP2;            // Pixel-Position von Page2
1252     long    nM1;            // Pixel-Position von Margin1
1253     long    nM2;            // Pixel-Position von Margin2
1254     long    nVirTop;        // Obere/Linke-Kante bei Ausgabe
1255     long    nVirBottom;     // Untere/Rechte-Kante bei Ausgabe
1256     long    nVirLeft;       // Linke/Obere-Kante bei Ausgabe
1257     long    nVirRight;      // Rechte/Untere-Kante bei Ausgabe
1258     long    nNullVirOff;    // Fuer schnellere Berechnung
1259 
1260     // Werte berechnen
1261     if ( mbCalc )
1262         ImplCalc();
1263     mpData->nNullVirOff = mnWinOff+mpData->nPageOff+mpData->nNullOff-mnVirOff;
1264     nNullVirOff = mpData->nNullVirOff;
1265     nVirLeft    = mpData->nRulVirOff;
1266     nVirRight   = nVirLeft+mpData->nRulWidth-1;
1267     nVirTop     = 0;
1268     nVirBottom  = mnVirHeight-1;
1269 
1270     if ( !IsReallyVisible() )
1271         return;
1272 
1273     Size    aVirDevSize;
1274     sal_Bool    b3DLook = !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO);
1275 
1276     // VirtualDevice initialize
1277     if ( mnWinStyle & WB_HORZ )
1278     {
1279         aVirDevSize.Width() = mnVirWidth;
1280         aVirDevSize.Height() = mnVirHeight;
1281     }
1282     else
1283     {
1284         aVirDevSize.Height() = mnVirWidth;
1285         aVirDevSize.Width() = mnVirHeight;
1286     }
1287     if ( aVirDevSize != maVirDev.GetOutputSizePixel() )
1288         maVirDev.SetOutputSizePixel( aVirDevSize, sal_True );
1289     else
1290         maVirDev.Erase();
1291 
1292     // Raender berechnen
1293     if ( !(mpData->nMargin1Style & RULER_STYLE_INVISIBLE) )
1294     {
1295         nM1 = mpData->nMargin1+nNullVirOff;
1296         if ( mpData->bAutoPageWidth )
1297         {
1298             nP1 = nVirLeft;
1299             if ( nM1 < nVirLeft )
1300                 nP1--;
1301         }
1302         else
1303             nP1 = nNullVirOff-mpData->nNullOff;
1304     }
1305     else
1306     {
1307         nM1 = nVirLeft-1;
1308         nP1 = nM1;
1309     }
1310     if ( !(mpData->nMargin2Style & RULER_STYLE_INVISIBLE) )
1311     {
1312         nM2 = mpData->nMargin2+nNullVirOff;
1313         if ( mpData->bAutoPageWidth )
1314         {
1315             nP2 = nVirRight;
1316             if ( nM2 > nVirRight )
1317                 nP2++;
1318         }
1319         else
1320             nP2 = nNullVirOff-mpData->nNullOff+mpData->nPageWidth;
1321         if ( nM2 > nP2 )
1322             nM2 = nP2;
1323     }
1324     else
1325     {
1326         nM2 = nVirRight+1;
1327         nP2 = nM2;
1328     }
1329 
1330     // Obere/untere Kante ausgeben
1331     if ( b3DLook )
1332         maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
1333     else
1334         maVirDev.SetLineColor( rStyleSettings.GetWindowTextColor() );
1335     ImplVDrawLine( nVirLeft, nVirTop, nM1 - 1, nVirTop ); //top left line
1336     ImplVDrawLine( nM2 +1, nVirTop, nP2 -1, nVirTop );      //top right line
1337 
1338     // Jetzt wird zwischen dem Schatten ausgegeben
1339     nVirTop++;
1340     nVirBottom--;
1341 
1342     // Margin1, Margin2 und Zwischenraum ausgeben
1343     maVirDev.SetLineColor();
1344     if ( b3DLook )
1345         maVirDev.SetFillColor( rStyleSettings.GetFaceColor() );
1346     else
1347         maVirDev.SetFillColor( rStyleSettings.GetWindowColor() );
1348     if ( nM1 > nVirLeft )
1349         ImplVDrawRect( nP1, nVirTop, nM1-1, nVirBottom ); //left gray rectangle
1350     if ( nM2 < nP2 )
1351         ImplVDrawRect( nM2+1, nVirTop, nP2, nVirBottom ); //right gray rectangle
1352     if ( nM2-nM1 > 0 )
1353     {
1354         maVirDev.SetFillColor( rStyleSettings.GetWindowColor() );
1355         ImplVDrawRect( nM1, nVirTop, nM2-1, nVirBottom ); //center rectangle
1356     }
1357     if ( b3DLook )
1358     {
1359         maVirDev.SetLineColor( rStyleSettings.GetShadowColor() );
1360         if ( nM1 > nVirLeft )
1361         {
1362             ImplVDrawLine( nM1-1, nVirTop, nM1-1, nVirBottom );//right line of the left rectangle
1363             ImplVDrawLine( nP1, nVirBottom, nM1-1, nVirBottom );//bottom line of the left rectangle
1364             if ( nP1 >= nVirLeft )
1365             {
1366                 ImplVDrawLine( nP1, nVirTop, nP1, nVirBottom );//left line of the left rectangle
1367                 ImplVDrawLine( nP1, nVirBottom, nP1+1, nVirBottom );//?
1368             }
1369         }
1370         if ( nM2 < nP2 )
1371         {
1372             ImplVDrawLine( nM2+1, nVirBottom, nP2-1, nVirBottom );//bottom line of the right rectangle
1373             ImplVDrawLine( nM2+1, nVirTop, nM2+1, nVirBottom );//left line of the right rectangle
1374             if ( nP2 <= nVirRight+1 )
1375                 ImplVDrawLine( nP2-1, nVirTop, nP2-1, nVirBottom );//right line of the right rectangle
1376         }
1377     }
1378     else
1379     {
1380         maVirDev.SetLineColor( rStyleSettings.GetWindowTextColor() );
1381         if ( nP1 >= nVirLeft )
1382             ImplVDrawLine( nP1, nVirTop, nP1, nVirBottom+1 );
1383         if ( nM1 > nP1 )
1384             ImplVDrawLine( nM1, nVirTop, nM1, nVirBottom );
1385         if ( nM2 < nP2 )
1386             ImplVDrawLine( nM2, nVirTop, nM2, nVirBottom );
1387         if ( nP2 <= nVirRight+1 )
1388             ImplVDrawLine( nP2, nVirTop, nP2, nVirBottom+1 );
1389     }
1390 
1391     // Lineal-Beschriftung (nur wenn keine Bemassungspfeile)
1392     if ( !mpData->pArrows )
1393     {
1394         long    nMin = nVirLeft;
1395         long    nMax = nP2;
1396         long    nStart = mpData->bTextRTL ? mpData->nMargin2 + nNullVirOff : nNullVirOff;
1397         long    nCenter = nVirTop+((nVirBottom-nVirTop)/2);
1398 
1399         // Nicht Schatten uebermalen
1400         if ( nP1 > nVirLeft )
1401             nMin++;
1402         if ( nP2 < nVirRight )
1403             nMax--;
1404 
1405         // Draw captions
1406         ImplDrawTicks( nMin, nMax, nStart, nCenter );
1407     }
1408 
1409     // Draw borders
1410     if ( mpData->pBorders )
1411         ImplDrawBorders( nVirLeft, nP2, nVirTop, nVirBottom );
1412 
1413     // Draw indents
1414     if ( mpData->pIndents )
1415         ImplDrawIndents( nVirLeft, nP2, nVirTop-1, nVirBottom+1 );
1416 
1417     // Tabs
1418     if ( mpData->pTabs )
1419     {
1420         ImplDrawTabs( nVirLeft, nP2, nVirTop-1, nVirBottom+1 );
1421     }
1422 
1423     // Bemassungspfeile
1424     if ( mpData->pArrows )
1425         ImplDrawArrows( nVirTop+((nVirBottom-nVirTop)/2) );
1426 
1427     // Wir haben formatiert
1428     mbFormat = sal_False;
1429 }
1430 
1431 // -----------------------------------------------------------------------
1432 
1433 void Ruler::ImplInitExtraField( sal_Bool bUpdate )
1434 {
1435     // Extra-Field beruecksichtigen
1436     if ( mnWinStyle & WB_EXTRAFIELD )
1437     {
1438         maExtraRect.Left()   = RULER_OFF;
1439         maExtraRect.Top()    = RULER_OFF;
1440         maExtraRect.Right()  = RULER_OFF+mnVirHeight-1;
1441         maExtraRect.Bottom() = RULER_OFF+mnVirHeight-1;
1442         if(mpData->bTextRTL)
1443         {
1444             Size aWinSize = GetOutputSizePixel();
1445             if(mnWinStyle & WB_HORZ)
1446 				maExtraRect.Move(aWinSize.Width() - maExtraRect.GetWidth() - maExtraRect.Left(), 0);
1447 			else
1448 				maExtraRect.Move(0, aWinSize.Height() - maExtraRect.GetHeight() - maExtraRect.Top());
1449 			mnVirOff = 0;
1450         }
1451 		else
1452 	        mnVirOff = maExtraRect.Right()+1;
1453 
1454     }
1455     else
1456     {
1457         maExtraRect.SetEmpty();
1458         mnVirOff = 0;
1459     }
1460 
1461     if ( bUpdate )
1462     {
1463         mbCalc      = sal_True;
1464         mbFormat    = sal_True;
1465         Invalidate();
1466     }
1467 }
1468 
1469 // -----------------------------------------------------------------------
1470 
1471 void Ruler::ImplDraw()
1472 {
1473     if ( mbFormat )
1474         ImplFormat();
1475 
1476     if ( IsReallyVisible() )
1477     {
1478         // Lineal ueber das VirtualDevice ausgeben
1479         Point   aOffPos;
1480         Size    aVirDevSize = maVirDev.GetOutputSizePixel();
1481 //        Size    aVirDevSize2 = maVirDev.GetOutputSizePixel();
1482         if ( mnWinStyle & WB_HORZ )
1483         {
1484 			aOffPos.X() = mnVirOff;
1485 			if(mpData->bTextRTL)
1486 				aVirDevSize.Width() -= maExtraRect.GetWidth();
1487 
1488 //	else
1489 //		aVirDevSize.Width() -= mnVirOff;
1490             aOffPos.Y() = RULER_OFF;
1491         }
1492         else
1493         {
1494             aOffPos.X() = RULER_OFF;
1495 			aOffPos.Y() = mnVirOff;
1496 //	else
1497 //		aVirDevSize.Height() -= mnVirOff;
1498         }
1499         DrawOutDev( aOffPos, aVirDevSize, Point(), aVirDevSize, maVirDev );
1500 
1501         // Positionslinien neu malen
1502         ImplInvertLines( sal_True );
1503     }
1504 }
1505 
1506 // -----------------------------------------------------------------------
1507 
1508 void Ruler::ImplDrawExtra( sal_Bool bPaint )
1509 {
1510     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
1511     Rectangle   aRect = maExtraRect;
1512     sal_Bool        bEraseRect = sal_False;
1513 
1514     if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
1515     {
1516         aRect.Left()    += 2;
1517         aRect.Top()     += 2;
1518         aRect.Right()   -= 2;
1519         aRect.Bottom()  -= 2;
1520     }
1521     else
1522     {
1523         aRect.Left()    += 1;
1524         aRect.Top()     += 1;
1525         aRect.Right()   -= 1;
1526         aRect.Bottom()  -= 1;
1527     }
1528 
1529     if ( !bPaint && !(mnExtraStyle & RULER_STYLE_HIGHLIGHT) )
1530     {
1531         if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
1532             SetFillColor( rStyleSettings.GetFaceColor() );
1533         else
1534             SetFillColor( rStyleSettings.GetWindowColor() );
1535         bEraseRect = sal_True;
1536     }
1537     else
1538     {
1539         if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) && (mnExtraStyle & RULER_STYLE_HIGHLIGHT) )
1540         {
1541             SetFillColor( rStyleSettings.GetCheckedColor() );
1542             bEraseRect = sal_True;
1543         }
1544     }
1545 
1546     if ( bEraseRect )
1547     {
1548         SetLineColor();
1549         DrawRect( aRect );
1550     }
1551 
1552     // Inhalt ausgeben
1553     if ( meExtraType == RULER_EXTRA_NULLOFFSET )
1554     {
1555         if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
1556             SetLineColor( rStyleSettings.GetButtonTextColor() );
1557         else
1558             SetLineColor( rStyleSettings.GetWindowTextColor() );
1559         DrawLine( Point( aRect.Left()+1, aRect.Top()+4 ),
1560                   Point( aRect.Right()-1, aRect.Top()+4 ) );
1561         DrawLine( Point( aRect.Left()+4, aRect.Top()+1 ),
1562                   Point( aRect.Left()+4, aRect.Bottom()-1 ) );
1563     }
1564     else if ( meExtraType == RULER_EXTRA_TAB )
1565     {
1566         sal_uInt16 nTabStyle = mnExtraStyle & RULER_TAB_STYLE;
1567         if(mpData->bTextRTL)
1568             nTabStyle |= RULER_TAB_RTL;
1569         Point aCenter = aRect.Center();
1570 		Point aDraw(aCenter);
1571         ImplCenterTabPos( aDraw, nTabStyle );
1572         WinBits nWinBits = GetStyle();
1573         if(0 == (nWinBits&WB_HORZ) )
1574 		{
1575 			if(0 != (nWinBits&WB_RIGHT_ALIGNED))
1576 				aDraw.Y() = 2 * aCenter.Y() - aDraw.Y();
1577 			if(mpData->bTextRTL)
1578 			{
1579 				long nTemp = aDraw.X();
1580 				aDraw.X() = aDraw.Y();
1581 				aDraw.Y() = nTemp;
1582 			}
1583 		}
1584         ImplDrawTab( this, aDraw, nTabStyle );
1585     }
1586 
1587     if ( (rStyleSettings.GetOptions() & STYLE_OPTION_MONO) && (mnExtraStyle & RULER_STYLE_HIGHLIGHT) )
1588         Invert( aRect );
1589 }
1590 
1591 // -----------------------------------------------------------------------
1592 
1593 void Ruler::ImplUpdate( sal_Bool bMustCalc )
1594 {
1595     // Hier schon Linien loeschen, damit Sie vor dem Neuberechnen schon
1596     // geloscht sind, da danach die alten Positionen nicht mehr bestimmt
1597     // werden koennen
1598     if ( !mbFormat )
1599         ImplInvertLines();
1600 
1601     // Flags setzen
1602     if ( bMustCalc )
1603         mbCalc = sal_True;
1604     mbFormat = sal_True;
1605 
1606     // Wenn wir am Draggen sind, wird nach dem Drag-Handler automatisch
1607     // das Lineal neu upgedatet
1608     if ( mbDrag )
1609         return;
1610 
1611     // Gegebenenfalls Update ausloesen
1612     if ( IsReallyVisible() && IsUpdateMode() )
1613     {
1614         mnUpdateFlags |= RULER_UPDATE_DRAW;
1615         if ( !mnUpdateEvtId )
1616             mnUpdateEvtId = Application::PostUserEvent( LINK( this, Ruler, ImplUpdateHdl ), NULL );
1617     }
1618 }
1619 
1620 // -----------------------------------------------------------------------
1621 
1622 sal_Bool Ruler::ImplHitTest( const Point& rPos, ImplRulerHitTest* pHitTest,
1623                          sal_Bool bRequireStyle, sal_uInt16 nRequiredStyle ) const
1624 {
1625     sal_uInt16      i;
1626     sal_uInt16      nStyle;
1627     long        nHitBottom;
1628     long        nX;
1629     long        nY;
1630     long        n1;
1631     long        n2;
1632 
1633     if ( !mbActive )
1634         return sal_False;
1635 
1636     // Position ermitteln
1637 	sal_Bool bIsHori = 0 != (mnWinStyle & WB_HORZ);
1638     if ( bIsHori )
1639     {
1640         nX = rPos.X();
1641         nY = rPos.Y();
1642     }
1643     else
1644     {
1645         nX = rPos.Y();
1646         nY = rPos.X();
1647     }
1648     nHitBottom = mnVirHeight+(RULER_OFF*2);
1649 
1650     // --> FME 2004-08-05 #i32608#
1651     pHitTest->nAryPos = 0;
1652     pHitTest->mnDragSize = 0;
1653     pHitTest->bSize = sal_False;
1654     pHitTest->bSizeBar = sal_False;
1655     // <--
1656 
1657     // Damit ueberstehende Tabs und Einzuege mit beruecksichtigt werden
1658     long nXExtraOff;
1659     if ( mpData->pTabs || mpData->pIndents )
1660         nXExtraOff = (mnVirHeight/2) - 4;
1661     else
1662         nXExtraOff = 0;
1663 
1664     // Test auf ausserhalb
1665     nX -= mnVirOff;
1666     long nXTemp = nX;
1667     if ( (nX < mpData->nRulVirOff-nXExtraOff) || (nX > mpData->nRulVirOff+mpData->nRulWidth+nXExtraOff) ||
1668          (nY < 0) || (nY > nHitBottom) )
1669     {
1670         pHitTest->nPos = 0;
1671         pHitTest->eType = RULER_TYPE_OUTSIDE;
1672         return sal_False;
1673     }
1674 
1675     nX -= mpData->nNullVirOff;
1676     pHitTest->nPos  = nX;
1677     pHitTest->eType = RULER_TYPE_DONTKNOW;
1678 
1679     // Zuerst die Tabs testen
1680     Rectangle aRect;
1681     if ( mpData->pTabs )
1682     {
1683         aRect.Bottom()  = nHitBottom;
1684         aRect.Top()     = aRect.Bottom()-RULER_TAB_HEIGHT-RULER_OFF;
1685 
1686         for ( i = mpData->nTabs; i; i-- )
1687         {
1688             nStyle = mpData->pTabs[i-1].nStyle;
1689             if ( !(nStyle & RULER_STYLE_INVISIBLE) )
1690             {
1691                 nStyle &= RULER_TAB_STYLE;
1692 
1693                 // Default-Tabs werden nur angezeigt
1694                 if ( nStyle != RULER_TAB_DEFAULT )
1695                 {
1696                     n1 = mpData->pTabs[i-1].nPos;
1697 
1698                     if ( nStyle == RULER_TAB_LEFT )
1699                     {
1700                         aRect.Left()    = n1;
1701                         aRect.Right()   = n1+RULER_TAB_WIDTH-1;
1702                     }
1703                     else if ( nStyle == RULER_TAB_RIGHT )
1704                     {
1705                         aRect.Right()   = n1;
1706                         aRect.Left()    = n1-RULER_TAB_WIDTH-1;
1707                     }
1708                     else
1709                     {
1710                         aRect.Left()    = n1-RULER_TAB_CWIDTH2+1;
1711                         aRect.Right()   = n1-RULER_TAB_CWIDTH2+RULER_TAB_CWIDTH;
1712                     }
1713 
1714 					if ( aRect.IsInside( Point( nX, nY ) ) )
1715                     {
1716                         pHitTest->eType     = RULER_TYPE_TAB;
1717                         pHitTest->nAryPos   = i-1;
1718                         return sal_True;
1719                     }
1720                 }
1721             }
1722         }
1723     }
1724 
1725     // Dann die Einzuege
1726     if ( mpData->pIndents )
1727     {
1728         long nIndentHeight = (mnVirHeight/2) - 1;
1729         long nIndentWidth2 = nIndentHeight-3;
1730 
1731         for ( i = mpData->nIndents; i; i-- )
1732         {
1733             nStyle = mpData->pIndents[i-1].nStyle;
1734             if ( (! bRequireStyle || nStyle == nRequiredStyle) &&
1735                  !(nStyle & RULER_STYLE_INVISIBLE) )
1736             {
1737                 nStyle &= RULER_INDENT_STYLE;
1738                 n1 = mpData->pIndents[i-1].nPos;
1739 
1740                 if ( (nStyle == RULER_INDENT_BOTTOM) ^ (!bIsHori) )
1741                 {
1742                     aRect.Left()    = n1-nIndentWidth2;
1743                     aRect.Right()   = n1+nIndentWidth2;
1744                     aRect.Top()     = nHitBottom-nIndentHeight-RULER_OFF+1;
1745                     aRect.Bottom()  = nHitBottom;
1746                 }
1747                 else
1748                 {
1749                     aRect.Left()    = n1-nIndentWidth2;
1750                     aRect.Right()   = n1+nIndentWidth2;
1751                     aRect.Top()     = 0;
1752                     aRect.Bottom()  = nIndentHeight+RULER_OFF-1;
1753                 }
1754 
1755                 if ( aRect.IsInside( Point( nX, nY ) ) )
1756                 {
1757                     pHitTest->eType     = RULER_TYPE_INDENT;
1758                     pHitTest->nAryPos   = i-1;
1759                     return sal_True;
1760                 }
1761             }
1762         }
1763     }
1764 
1765     // Jetzt zaehlt nichts mehr, was links oder rechts uebersteht
1766     if ( (nXTemp < mpData->nRulVirOff) || (nXTemp > mpData->nRulVirOff+mpData->nRulWidth) )
1767     {
1768         pHitTest->nPos = 0;
1769         pHitTest->eType = RULER_TYPE_OUTSIDE;
1770         return sal_False;
1771     }
1772 
1773     // Danach die Spalten testen
1774     int nBorderTolerance = 1;
1775     if(pHitTest->bExpandTest)
1776     {
1777         nBorderTolerance++;
1778     }
1779 
1780     for ( i = mpData->nBorders; i; i-- )
1781     {
1782         n1 = mpData->pBorders[i-1].nPos;
1783         n2 = n1 + mpData->pBorders[i-1].nWidth;
1784 
1785         // Spalten werden mit mindestens 3 Pixel breite gezeichnet
1786         if ( !mpData->pBorders[i-1].nWidth )
1787         {
1788              n1 -= nBorderTolerance;
1789              n2 += nBorderTolerance;
1790 
1791         }
1792 
1793         if ( (nX >= n1) && (nX <= n2) )
1794         {
1795             nStyle = mpData->pBorders[i-1].nStyle;
1796             if ( !(nStyle & RULER_STYLE_INVISIBLE) )
1797             {
1798                 pHitTest->eType     = RULER_TYPE_BORDER;
1799                 pHitTest->nAryPos   = i-1;
1800 
1801                 if ( !(nStyle & RULER_BORDER_SIZEABLE) )
1802                 {
1803                     if ( nStyle & RULER_BORDER_MOVEABLE )
1804                     {
1805                         pHitTest->bSizeBar = sal_True;
1806                         pHitTest->mnDragSize = RULER_DRAGSIZE_MOVE;
1807                     }
1808                 }
1809                 else
1810                 {
1811                     long nMOff = RULER_MOUSE_BORDERWIDTH;
1812                     while ( nMOff*2 >= (n2-n1-RULER_MOUSE_BORDERMOVE) )
1813                     {
1814                         if ( nMOff < 2 )
1815                         {
1816                             nMOff = 0;
1817                             break;
1818                         }
1819                         else
1820                             nMOff--;
1821                     }
1822 
1823                     if ( nX <= n1+nMOff )
1824                     {
1825                         pHitTest->bSize = sal_True;
1826                         pHitTest->mnDragSize = RULER_DRAGSIZE_1;
1827                     }
1828                     else if ( nX >= n2-nMOff )
1829                     {
1830                         pHitTest->bSize = sal_True;
1831                         pHitTest->mnDragSize = RULER_DRAGSIZE_2;
1832                     }
1833                     else
1834                     {
1835                         if ( nStyle & RULER_BORDER_MOVEABLE )
1836                         {
1837                             pHitTest->bSizeBar = sal_True;
1838                             pHitTest->mnDragSize = RULER_DRAGSIZE_MOVE;
1839                         }
1840                     }
1841                 }
1842 
1843                 return sal_True;
1844             }
1845         }
1846     }
1847 
1848     // Und zum Schluss die Raender
1849     int nMarginTolerance = pHitTest->bExpandTest ? nBorderTolerance : RULER_MOUSE_MARGINWIDTH;
1850 
1851     if ( (mpData->nMargin1Style & (RULER_MARGIN_SIZEABLE | RULER_STYLE_INVISIBLE)) == RULER_MARGIN_SIZEABLE )
1852     {
1853         n1 = mpData->nMargin1;
1854         if ( (nX >= n1 - nMarginTolerance) && (nX <= n1 + nMarginTolerance) )
1855         {
1856             pHitTest->eType = RULER_TYPE_MARGIN1;
1857             pHitTest->bSize = sal_True;
1858             return sal_True;
1859         }
1860     }
1861     if ( (mpData->nMargin2Style & (RULER_MARGIN_SIZEABLE | RULER_STYLE_INVISIBLE)) == RULER_MARGIN_SIZEABLE )
1862     {
1863         n1 = mpData->nMargin2;
1864         if ( (nX >= n1 - nMarginTolerance) && (nX <= n1 + nMarginTolerance) )
1865         {
1866             pHitTest->eType = RULER_TYPE_MARGIN2;
1867             pHitTest->bSize = sal_True;
1868             return sal_True;
1869         }
1870     }
1871 
1872     // Jetzt nocheinmal die Tabs testen, nur mit etwas mehr spielraum
1873     if ( mpData->pTabs )
1874     {
1875         aRect.Top()     = RULER_OFF;
1876         aRect.Bottom()  = nHitBottom;
1877 
1878         for ( i = mpData->nTabs; i; i-- )
1879         {
1880             nStyle = mpData->pTabs[i-1].nStyle;
1881             if ( !(nStyle & RULER_STYLE_INVISIBLE) )
1882             {
1883                 nStyle &= RULER_TAB_STYLE;
1884 
1885                 // Default-Tabs werden nur angezeigt
1886                 if ( nStyle != RULER_TAB_DEFAULT )
1887                 {
1888                     n1 = mpData->pTabs[i-1].nPos;
1889 
1890                     if ( nStyle == RULER_TAB_LEFT )
1891                     {
1892                         aRect.Left()    = n1;
1893                         aRect.Right()   = n1+RULER_TAB_WIDTH-1;
1894                     }
1895                     else if ( nStyle == RULER_TAB_RIGHT )
1896                     {
1897                         aRect.Right()   = n1;
1898                         aRect.Left()    = n1-RULER_TAB_WIDTH-1;
1899                     }
1900                     else
1901                     {
1902                         aRect.Left()    = n1-RULER_TAB_CWIDTH2+1;
1903                         aRect.Right()   = n1-RULER_TAB_CWIDTH2+RULER_TAB_CWIDTH;
1904                     }
1905 
1906                     aRect.Left()--;
1907                     aRect.Right()++;
1908 
1909                     if ( aRect.IsInside( Point( nX, nY ) ) )
1910                     {
1911                         pHitTest->eType     = RULER_TYPE_TAB;
1912                         pHitTest->nAryPos   = i-1;
1913                         return sal_True;
1914                     }
1915                 }
1916             }
1917         }
1918     }
1919 
1920     return sal_False;
1921 }
1922 
1923 // -----------------------------------------------------------------------
1924 
1925 sal_Bool Ruler::ImplDocHitTest( const Point& rPos, RulerType eDragType,
1926                             ImplRulerHitTest* pHitTest ) const
1927 {
1928     Point aPos = rPos;
1929     sal_Bool bRequiredStyle = sal_False;
1930     sal_uInt16 nRequiredStyle = 0;
1931 
1932     if (eDragType == RULER_TYPE_INDENT)
1933     {
1934         bRequiredStyle = sal_True;
1935         nRequiredStyle = RULER_INDENT_BOTTOM;
1936     }
1937 
1938     if ( mnWinStyle & WB_HORZ )
1939         aPos.X() += mnWinOff;
1940     else
1941         aPos.Y() += mnWinOff;
1942 
1943     if ( (eDragType == RULER_TYPE_INDENT) || (eDragType == RULER_TYPE_DONTKNOW) )
1944     {
1945         if ( mnWinStyle & WB_HORZ )
1946             aPos.Y() = RULER_OFF+1;
1947         else
1948             aPos.X() = RULER_OFF+1;
1949 
1950         // HitTest durchfuehren
1951         if ( ImplHitTest( aPos, pHitTest, bRequiredStyle, nRequiredStyle ) )
1952         {
1953             if ( (pHitTest->eType == eDragType) || (eDragType == RULER_TYPE_DONTKNOW) )
1954                 return sal_True;
1955         }
1956     }
1957 
1958     if ( (eDragType == RULER_TYPE_INDENT) || (eDragType == RULER_TYPE_TAB) ||
1959          (eDragType == RULER_TYPE_DONTKNOW) )
1960     {
1961         if ( mnWinStyle & WB_HORZ )
1962             aPos.Y() = mnHeight-RULER_OFF-1;
1963         else
1964             aPos.X() = mnWidth-RULER_OFF-1;
1965 
1966         // HitTest durchfuehren
1967         if ( ImplHitTest( aPos, pHitTest, bRequiredStyle, nRequiredStyle ) )
1968         {
1969             if ( (pHitTest->eType == eDragType) || (eDragType == RULER_TYPE_DONTKNOW) )
1970                 return sal_True;
1971         }
1972     }
1973 
1974     if ( (eDragType == RULER_TYPE_MARGIN1) || (eDragType == RULER_TYPE_MARGIN2) ||
1975          (eDragType == RULER_TYPE_BORDER) || (eDragType == RULER_TYPE_DONTKNOW) )
1976     {
1977         if ( mnWinStyle & WB_HORZ )
1978             aPos.Y() = RULER_OFF + (mnVirHeight/2);
1979         else
1980             aPos.X() = RULER_OFF + (mnVirHeight/2);
1981 
1982         // HitTest durchfuehren
1983         if ( ImplHitTest( aPos, pHitTest ) )
1984         {
1985             if ( (pHitTest->eType == eDragType) || (eDragType == RULER_TYPE_DONTKNOW) )
1986                 return sal_True;
1987         }
1988     }
1989 
1990     // Auf DontKnow setzen
1991     pHitTest->eType = RULER_TYPE_DONTKNOW;
1992 
1993     return sal_False;
1994 }
1995 
1996 // -----------------------------------------------------------------------
1997 
1998 sal_Bool Ruler::ImplStartDrag( ImplRulerHitTest* pHitTest, sal_uInt16 nModifier )
1999 {
2000     // Wenn eine Spalte angeklick wurde, die weder verschiebar noch
2001     // in der Groesse aenderbar ist, brauchen wir auch kein Drag ausloesen
2002     if ( (pHitTest->eType == RULER_TYPE_BORDER) &&
2003          !pHitTest->bSize && !pHitTest->bSizeBar )
2004         return sal_False;
2005 
2006     // Dragdaten setzen
2007     meDragType      = pHitTest->eType;
2008     mnDragPos       = pHitTest->nPos;
2009     mnDragAryPos    = pHitTest->nAryPos;
2010     mnDragSize      = pHitTest->mnDragSize;
2011     mnDragModifier  = nModifier;
2012     *mpDragData     = *mpSaveData;
2013     mpData          = mpDragData;
2014 
2015     // Handler rufen
2016     if ( StartDrag() )
2017     {
2018         // Wenn der Handler das Draggen erlaubt, dann das Draggen
2019         // initialisieren
2020         ImplInvertLines();
2021         mbDrag = sal_True;
2022         mnStartDragPos = mnDragPos;
2023         StartTracking();
2024         return sal_True;
2025     }
2026     else
2027     {
2028         // Ansonsten muessen wir die Daten zuruecksetzen
2029         meDragType      = RULER_TYPE_DONTKNOW;
2030         mnDragPos       = 0;
2031         mnDragAryPos    = 0;
2032         mnDragSize      = 0;
2033         mnDragModifier  = 0;
2034         mpData          = mpSaveData;
2035     }
2036 
2037     return sal_False;
2038 }
2039 
2040 // -----------------------------------------------------------------------
2041 
2042 void Ruler::ImplDrag( const Point& rPos )
2043 {
2044     long  nX;
2045     long  nY;
2046     long  nOutHeight;
2047 
2048     if ( mnWinStyle & WB_HORZ )
2049     {
2050         nX          = rPos.X();
2051         nY          = rPos.Y();
2052         nOutHeight  = mnHeight;
2053     }
2054     else
2055     {
2056         nX          = rPos.Y();
2057         nY          = rPos.X();
2058         nOutHeight  = mnWidth;
2059     }
2060 
2061     // X berechnen und einpassen
2062     nX -= mnVirOff;
2063     if ( nX < mpData->nRulVirOff )
2064     {
2065         nX = mpData->nRulVirOff;
2066         mnDragScroll = RULER_SCROLL_1;
2067     }
2068     else if ( nX > mpData->nRulVirOff+mpData->nRulWidth )
2069     {
2070         nX = mpData->nRulVirOff+mpData->nRulWidth;
2071         mnDragScroll = RULER_SCROLL_2;
2072     }
2073     nX -= mpData->nNullVirOff;
2074 
2075     // Wenn oberhalb oder links vom Lineal, dann alte Werte
2076     mbDragDelete = sal_False;
2077     if ( nY < 0 )
2078     {
2079         if ( !mbDragCanceled )
2080         {
2081             // Daten wiederherstellen
2082             mbDragCanceled = sal_True;
2083             ImplRulerData aTempData;
2084             aTempData = *mpDragData;
2085             *mpDragData = *mpSaveData;
2086             mbCalc = sal_True;
2087             mbFormat = sal_True;
2088 
2089             // Handler rufen
2090             mnDragPos = mnStartDragPos;
2091             Drag();
2092 
2093             // Und neu ausgeben (zeitverzoegert)
2094 /*
2095             mnUpdateFlags |= RULER_UPDATE_DRAW;
2096             if ( mnUpdateEvtId )
2097                 Application::RemoveUserEvent( mnUpdateEvtId );
2098             mnUpdateEvtId = Application::PostUserEvent( LINK( this, Ruler, ImplUpdateHdl ), NULL );
2099 */
2100             ImplDraw();
2101 
2102             // Daten wieder wie vor dem Cancel herstellen
2103             *mpDragData = aTempData;
2104         }
2105     }
2106     else
2107     {
2108         mbDragCanceled = sal_False;
2109 
2110         // +2, damit nicht so schnell die Tabs geloescht werden
2111         if ( nY > nOutHeight+2 )
2112             mbDragDelete = sal_True;
2113 
2114         mnDragPos = nX;
2115 
2116         // Handler rufen
2117         Drag();
2118 
2119         // Und neu ausgeben
2120         if ( mbFormat )
2121             ImplDraw();
2122     }
2123 
2124     mnDragScroll = 0;
2125 }
2126 
2127 // -----------------------------------------------------------------------
2128 
2129 void Ruler::ImplEndDrag()
2130 {
2131     // Werte uebernehmen
2132     if ( mbDragCanceled )
2133         *mpDragData = *mpSaveData;
2134     else
2135         *mpSaveData = *mpDragData;
2136     mpData = mpSaveData;
2137     mbDrag = sal_False;
2138 
2139     // Handler rufen
2140     EndDrag();
2141 
2142     // Drag-Werte zuruecksetzen
2143     meDragType      = RULER_TYPE_DONTKNOW;
2144     mnDragPos       = 0;
2145     mnDragAryPos    = 0;
2146     mnDragSize      = 0;
2147     mbDragCanceled  = sal_False;
2148     mbDragDelete    = sal_False;
2149     mnDragModifier  = 0;
2150     mnDragScroll    = 0;
2151     mnStartDragPos  = 0;
2152 
2153     // Und neu ausgeben
2154     ImplDraw();
2155 }
2156 
2157 // -----------------------------------------------------------------------
2158 
2159 IMPL_LINK( Ruler, ImplUpdateHdl, void*, EMPTYARG )
2160 {
2161     mnUpdateEvtId = 0;
2162 
2163     // Feststellen, was upgedatet werden muss
2164     if ( mnUpdateFlags & RULER_UPDATE_DRAW )
2165     {
2166         mnUpdateFlags = 0;
2167         ImplDraw();
2168     }
2169     else if ( mnUpdateFlags & RULER_UPDATE_LINES )
2170     {
2171         mnUpdateFlags = 0;
2172         ImplInvertLines();
2173     }
2174 
2175     return 0;
2176 }
2177 
2178 // -----------------------------------------------------------------------
2179 
2180 void Ruler::MouseButtonDown( const MouseEvent& rMEvt )
2181 {
2182     if ( rMEvt.IsLeft() && !IsTracking() )
2183     {
2184         Point   aMousePos = rMEvt.GetPosPixel();
2185         sal_uInt16  nMouseClicks = rMEvt.GetClicks();
2186         sal_uInt16  nMouseModifier = rMEvt.GetModifier();
2187 
2188         // Gegebenenfalls Lineal updaten (damit mit den richtigen Daten
2189         // gearbeitet wird und die Anzeige auch zur Bearbeitung passt)
2190         if ( mbFormat )
2191         {
2192             ImplDraw();
2193             mnUpdateFlags &= ~RULER_UPDATE_DRAW;
2194         }
2195 
2196         if ( maExtraRect.IsInside( aMousePos ) )
2197         {
2198             mnExtraClicks = nMouseClicks;
2199             mnExtraModifier = nMouseModifier;
2200             ExtraDown();
2201             mnExtraClicks = 0;
2202             mnExtraModifier = 0;
2203         }
2204         else
2205         {
2206             ImplRulerHitTest aHitTest;
2207 
2208             if ( nMouseClicks == 1 )
2209             {
2210                 if ( ImplHitTest( aMousePos, &aHitTest ) )
2211                     ImplStartDrag( &aHitTest, nMouseModifier );
2212                 else
2213                 {
2214                     // Position innerhalb des Lineal-Bereiches
2215                     if ( aHitTest.eType == RULER_TYPE_DONTKNOW )
2216                     {
2217                         mnDragPos = aHitTest.nPos;
2218                         Click();
2219                         mnDragPos = 0;
2220 
2221                         // Nocheinmal HitTest durchfuehren, da durch den Click
2222                         // zum Beispiel ein neuer Tab gesetzt werden konnte
2223                         if ( ImplHitTest( aMousePos, &aHitTest ) )
2224                             ImplStartDrag( &aHitTest, nMouseModifier );
2225                     }
2226                 }
2227             }
2228             else
2229             {
2230                 if ( ImplHitTest( aMousePos, &aHitTest ) )
2231                 {
2232                     mnDragPos    = aHitTest.nPos;
2233                     mnDragAryPos = aHitTest.nAryPos;
2234                 }
2235                 meDragType = aHitTest.eType;
2236 
2237                 DoubleClick();
2238 
2239                 meDragType      = RULER_TYPE_DONTKNOW;
2240                 mnDragPos       = 0;
2241                 mnDragAryPos    = 0;
2242             }
2243         }
2244     }
2245 }
2246 
2247 // -----------------------------------------------------------------------
2248 
2249 void Ruler::MouseMove( const MouseEvent& rMEvt )
2250 {
2251     PointerStyle ePtrStyle = POINTER_ARROW;
2252 
2253     // Gegebenenfalls Lineal updaten (damit mit den richtigen Daten
2254     // gearbeitet wird und die Anzeige auch zur Bearbeitung passt)
2255     if ( mbFormat )
2256     {
2257         ImplDraw();
2258         mnUpdateFlags &= ~RULER_UPDATE_DRAW;
2259     }
2260 
2261     ImplRulerHitTest aHitTest;
2262     if ( ImplHitTest( rMEvt.GetPosPixel(), &aHitTest ) )
2263     {
2264         if ( aHitTest.bSize )
2265         {
2266             if ( mnWinStyle & WB_HORZ )
2267                 ePtrStyle = POINTER_ESIZE;
2268             else
2269                 ePtrStyle = POINTER_SSIZE;
2270         }
2271         else if ( aHitTest.bSizeBar )
2272         {
2273             if ( mnWinStyle & WB_HORZ )
2274                 ePtrStyle = POINTER_HSIZEBAR;
2275             else
2276                 ePtrStyle = POINTER_VSIZEBAR;
2277         }
2278     }
2279 
2280     SetPointer( Pointer( ePtrStyle ) );
2281 }
2282 
2283 // -----------------------------------------------------------------------
2284 
2285 void Ruler::Tracking( const TrackingEvent& rTEvt )
2286 {
2287     if ( rTEvt.IsTrackingEnded() )
2288     {
2289         // Bei Abbruch, den alten Status wieder herstellen
2290         if ( rTEvt.IsTrackingCanceled() )
2291         {
2292             mbDragCanceled = sal_True;
2293             mbFormat       = sal_True;
2294         }
2295 
2296         ImplEndDrag();
2297     }
2298     else
2299         ImplDrag( rTEvt.GetMouseEvent().GetPosPixel() );
2300 }
2301 
2302 // -----------------------------------------------------------------------
2303 
2304 void Ruler::Paint( const Rectangle& )
2305 {
2306     ImplDraw();
2307 
2308     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
2309 
2310     // Extra-Field beruecksichtigen
2311     if ( mnWinStyle & WB_EXTRAFIELD )
2312     {
2313         if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
2314         {
2315             SetLineColor( rStyleSettings.GetShadowColor() );
2316             DrawLine( Point( maExtraRect.Left(), maExtraRect.Top() ),
2317                       Point( maExtraRect.Right()-1, maExtraRect.Top() ) );
2318             DrawLine( Point( maExtraRect.Left(), maExtraRect.Top() ),
2319                       Point( maExtraRect.Left(), maExtraRect.Bottom()-1 ) );
2320             DrawLine( Point( maExtraRect.Left(), maExtraRect.Bottom()-1 ),
2321                       Point( maExtraRect.Right()-1, maExtraRect.Bottom()-1 ) );
2322             DrawLine( Point( maExtraRect.Right()-1, maExtraRect.Top() ),
2323                       Point( maExtraRect.Right()-1, maExtraRect.Bottom()-1 ) );
2324             SetLineColor( rStyleSettings.GetLightColor() );
2325             DrawLine( Point( maExtraRect.Left()+1, maExtraRect.Top()+1 ),
2326                       Point( maExtraRect.Right()-2, maExtraRect.Top()+1 ) );
2327             DrawLine( Point( maExtraRect.Left()+1, maExtraRect.Top()+1 ),
2328                       Point( maExtraRect.Left()+1, maExtraRect.Bottom()-2 ) );
2329             DrawLine( Point( maExtraRect.Left(), maExtraRect.Bottom() ),
2330                       Point( maExtraRect.Right(), maExtraRect.Bottom() ) );
2331             DrawLine( Point( maExtraRect.Right(), maExtraRect.Top() ),
2332                       Point( maExtraRect.Right(), maExtraRect.Bottom() ) );
2333         }
2334         else
2335         {
2336             SetLineColor( rStyleSettings.GetWindowTextColor() );
2337             SetFillColor( rStyleSettings.GetWindowColor() );
2338             DrawRect( maExtraRect );
2339         }
2340 
2341         // Imhalt vom Extrafeld ausgeben
2342         ImplDrawExtra( sal_True );
2343     }
2344 
2345     if ( mnWinStyle & WB_BORDER )
2346     {
2347         if ( mnWinStyle & WB_HORZ )
2348         {
2349             if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
2350             {
2351                 SetLineColor( rStyleSettings.GetShadowColor() );
2352                 DrawLine( Point( mnBorderOff, mnHeight-2 ),
2353                           Point( mnWidth, mnHeight-2 ) );
2354                 if ( mnBorderOff )
2355                 {
2356                     DrawLine( Point( mnBorderOff-1, mnHeight-2 ),
2357                               Point( mnBorderOff-1, mnHeight-1 ) );
2358                 }
2359             }
2360             SetLineColor( rStyleSettings.GetWindowTextColor() );
2361             DrawLine( Point( mnBorderOff, mnHeight-1 ),
2362                       Point( mnWidth, mnHeight-1 ) );
2363         }
2364         else
2365         {
2366             if ( !(rStyleSettings.GetOptions() & STYLE_OPTION_MONO) )
2367             {
2368                 SetLineColor( rStyleSettings.GetShadowColor() );
2369                 DrawLine( Point( mnWidth-2, mnBorderOff ),
2370                           Point( mnWidth-2, mnHeight ) );
2371                 if ( mnBorderOff )
2372                 {
2373                     DrawLine( Point( mnWidth-2, mnBorderOff-1 ),
2374                               Point( mnWidth-1, mnBorderOff-1 ) );
2375                 }
2376             }
2377             SetLineColor( rStyleSettings.GetWindowTextColor() );
2378             DrawLine( Point( mnWidth-1, mnBorderOff ),
2379                       Point( mnWidth-1, mnHeight ) );
2380         }
2381     }
2382 }
2383 
2384 // -----------------------------------------------------------------------
2385 
2386 void Ruler::Resize()
2387 {
2388     Size aWinSize = GetOutputSizePixel();
2389 
2390     long nNewHeight;
2391     if ( mnWinStyle & WB_HORZ )
2392     {
2393         if ( aWinSize.Height() != mnHeight )
2394             nNewHeight = aWinSize.Height();
2395         else
2396             nNewHeight = 0;
2397     }
2398     else
2399     {
2400         if ( aWinSize.Width() != mnWidth )
2401             nNewHeight = aWinSize.Width();
2402         else
2403             nNewHeight = 0;
2404     }
2405 
2406     // Hier schon Linien loeschen
2407     sal_Bool bVisible = IsReallyVisible();
2408     if ( bVisible && mpData->nLines )
2409     {
2410         ImplInvertLines();
2411         mnUpdateFlags |= RULER_UPDATE_LINES;
2412         if ( !mnUpdateEvtId )
2413             mnUpdateEvtId = Application::PostUserEvent( LINK( this, Ruler, ImplUpdateHdl ), NULL );
2414     }
2415     mbFormat = sal_True;
2416 
2417     // Wenn sich die Hoehe bzw. Breite aendert, dann muessen besimmte Werte
2418     // neu berechnet werden
2419     //extra field should always be updated
2420     ImplInitExtraField( mpData->bTextRTL );
2421     if ( nNewHeight )
2422     {
2423         mbCalc = sal_True;
2424         mnVirHeight = nNewHeight - mnBorderWidth - (RULER_OFF*2);
2425     }
2426     else
2427     {
2428         if ( mpData->bAutoPageWidth )
2429             ImplUpdate( sal_True );
2430         else if ( mbAutoWinWidth )
2431             mbCalc = sal_True;
2432     }
2433 
2434     // Wenn Ruler eine Groesse hat, dann Groesse vom VirtualDevice setzen
2435     if ( (mnVirWidth > RULER_MIN_SIZE) ||
2436          ((aWinSize.Width() > RULER_MIN_SIZE) && (aWinSize.Height() > RULER_MIN_SIZE)) )
2437     {
2438         if ( mnWinStyle & WB_HORZ )
2439             mnVirWidth = aWinSize.Width()-mnVirOff;
2440         else
2441             mnVirWidth = aWinSize.Height()-mnVirOff;
2442         if ( mnVirWidth < RULER_MIN_SIZE )
2443             mnVirWidth = 0;
2444     }
2445 
2446     // Gegebenenfalls ein Teil vom Rand loeschen, da 3D-Effekt/Trennlinie am
2447     // Fensterrand
2448     if ( bVisible )
2449     {
2450         if ( nNewHeight )
2451             Invalidate();
2452         else if ( mpData->bAutoPageWidth )
2453         {
2454             // Nur bei AutoPageWidth haben wir rechts einen 3D-Effekt,
2455             // der sich der Fensterbreite anpasst und deshalb neu gezeichnet
2456             // werden muss
2457             Rectangle aRect;
2458 
2459             if ( mnWinStyle & WB_HORZ )
2460             {
2461                 if ( mnWidth < aWinSize.Width() )
2462                     aRect.Left() = mnWidth-RULER_RESIZE_OFF;
2463                 else
2464                     aRect.Left() = aWinSize.Width()-RULER_RESIZE_OFF;
2465                 aRect.Right()   = aRect.Left()+RULER_RESIZE_OFF;
2466                 aRect.Top()     = RULER_OFF;
2467                 aRect.Bottom()  = RULER_OFF+mnVirHeight;
2468             }
2469             else
2470             {
2471                 if ( mnHeight < aWinSize.Height() )
2472                     aRect.Top() = mnHeight-RULER_RESIZE_OFF;
2473                 else
2474                     aRect.Top() = aWinSize.Height()-RULER_RESIZE_OFF;
2475                 aRect.Bottom() = aRect.Top()+RULER_RESIZE_OFF;
2476                 aRect.Left()    = RULER_OFF;
2477                 aRect.Right()   = RULER_OFF+mnVirHeight;
2478             }
2479 
2480             Invalidate( aRect );
2481         }
2482     }
2483 
2484     // Neue Groesse merken
2485     mnWidth  = aWinSize.Width();
2486     mnHeight = aWinSize.Height();
2487 }
2488 
2489 // -----------------------------------------------------------------------
2490 
2491 void Ruler::StateChanged( StateChangedType nType )
2492 {
2493     Window::StateChanged( nType );
2494 
2495     if ( nType == STATE_CHANGE_INITSHOW )
2496         ImplFormat();
2497     else if ( nType == STATE_CHANGE_UPDATEMODE )
2498     {
2499         if ( IsReallyVisible() && IsUpdateMode() )
2500             ImplDraw();
2501     }
2502     else if ( (nType == STATE_CHANGE_ZOOM) ||
2503               (nType == STATE_CHANGE_CONTROLFONT) )
2504     {
2505         ImplInitSettings( sal_True, sal_False, sal_False );
2506         Invalidate();
2507     }
2508     else if ( nType == STATE_CHANGE_CONTROLFOREGROUND )
2509     {
2510         ImplInitSettings( sal_False, sal_True, sal_False );
2511         Invalidate();
2512     }
2513     else if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
2514     {
2515         ImplInitSettings( sal_False, sal_False, sal_True );
2516         Invalidate();
2517     }
2518 }
2519 
2520 // -----------------------------------------------------------------------
2521 
2522 void Ruler::DataChanged( const DataChangedEvent& rDCEvt )
2523 {
2524     Window::DataChanged( rDCEvt );
2525 
2526     if ( (rDCEvt.GetType() == DATACHANGED_FONTS) ||
2527          (rDCEvt.GetType() == DATACHANGED_DISPLAY) ||
2528          (rDCEvt.GetType() == DATACHANGED_FONTSUBSTITUTION) ||
2529          ((rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
2530           (rDCEvt.GetFlags() & SETTINGS_STYLE)) )
2531     {
2532         mbFormat = sal_True;
2533         ImplInitSettings( sal_True, sal_True, sal_True );
2534         Invalidate();
2535     }
2536 }
2537 
2538 // -----------------------------------------------------------------------
2539 
2540 long Ruler::StartDrag()
2541 {
2542     if ( maStartDragHdl.IsSet() )
2543         return maStartDragHdl.Call( this );
2544     else
2545         return sal_False;
2546 }
2547 
2548 // -----------------------------------------------------------------------
2549 
2550 void Ruler::Drag()
2551 {
2552     maDragHdl.Call( this );
2553 }
2554 
2555 // -----------------------------------------------------------------------
2556 
2557 void Ruler::EndDrag()
2558 {
2559     maEndDragHdl.Call( this );
2560 }
2561 
2562 // -----------------------------------------------------------------------
2563 
2564 void Ruler::Click()
2565 {
2566     maClickHdl.Call( this );
2567 }
2568 
2569 // -----------------------------------------------------------------------
2570 
2571 void Ruler::DoubleClick()
2572 {
2573     maDoubleClickHdl.Call( this );
2574 }
2575 
2576 // -----------------------------------------------------------------------
2577 
2578 void Ruler::ExtraDown()
2579 {
2580     maExtraDownHdl.Call( this );
2581 }
2582 
2583 // -----------------------------------------------------------------------
2584 
2585 void Ruler::Activate()
2586 {
2587     mbActive = sal_True;
2588 
2589     // Positionslinien wieder anzeigen (erst hinter mbActive=sal_True rufen, da
2590     // von ImplInvertLines() ausgewertet wird). Das Zeichnen der Linien
2591     // wird verzoegert, damit im vermutlich noch nicht gepainteten Zustand
2592     // Linien gezeichnet werden.
2593     mnUpdateFlags |= RULER_UPDATE_LINES;
2594     if ( !mnUpdateEvtId )
2595         mnUpdateEvtId = Application::PostUserEvent( LINK( this, Ruler, ImplUpdateHdl ), NULL );
2596 }
2597 
2598 // -----------------------------------------------------------------------
2599 
2600 void Ruler::Deactivate()
2601 {
2602     // Positionslinien loeschen (schon vor mbActive=sal_False rufen, da
2603     // von ImplInvertLines() ausgewertet wird)
2604     ImplInvertLines();
2605 
2606     mbActive = sal_False;
2607 }
2608 
2609 // -----------------------------------------------------------------------
2610 
2611 sal_Bool Ruler::StartDocDrag( const MouseEvent& rMEvt, RulerType eDragType )
2612 {
2613     if ( !mbDrag )
2614     {
2615         Point               aMousePos = rMEvt.GetPosPixel();
2616         sal_uInt16              nMouseClicks = rMEvt.GetClicks();
2617         sal_uInt16              nMouseModifier = rMEvt.GetModifier();
2618         ImplRulerHitTest    aHitTest;
2619         if(eDragType != RULER_TYPE_DONTKNOW)
2620             aHitTest.bExpandTest = sal_True;
2621 
2622         // Gegebenenfalls Lineal updaten (damit mit den richtigen Daten
2623         // gearbeitet wird und die Anzeige auch zur Bearbeitung passt)
2624         if ( mbFormat )
2625         {
2626             ImplDraw();
2627             mnUpdateFlags &= ~RULER_UPDATE_DRAW;
2628         }
2629 
2630         if ( nMouseClicks == 1 )
2631         {
2632             if ( ImplDocHitTest( aMousePos, eDragType, &aHitTest ) )
2633             {
2634                 Pointer aPtr;
2635 
2636                 if ( aHitTest.bSize )
2637                 {
2638                     if ( mnWinStyle & WB_HORZ )
2639                         aPtr = Pointer( POINTER_ESIZE );
2640                     else
2641                         aPtr = Pointer( POINTER_SSIZE );
2642                 }
2643                 else if ( aHitTest.bSizeBar )
2644                 {
2645                     if ( mnWinStyle & WB_HORZ )
2646                         aPtr = Pointer( POINTER_HSIZEBAR );
2647                     else
2648                         aPtr = Pointer( POINTER_VSIZEBAR );
2649                 }
2650                 SetPointer( aPtr );
2651                 return ImplStartDrag( &aHitTest, nMouseModifier );
2652             }
2653         }
2654         else if ( nMouseClicks == 2 )
2655         {
2656             if ( ImplDocHitTest( aMousePos, eDragType, &aHitTest ) )
2657             {
2658                 mnDragPos    = aHitTest.nPos;
2659                 mnDragAryPos = aHitTest.nAryPos;
2660             }
2661             eDragType = aHitTest.eType;
2662 
2663             DoubleClick();
2664 
2665             eDragType       = RULER_TYPE_DONTKNOW;
2666             mnDragPos       = 0;
2667             mnDragAryPos    = 0;
2668 
2669             return sal_True;
2670         }
2671     }
2672 
2673     return sal_False;
2674 }
2675 
2676 // -----------------------------------------------------------------------
2677 
2678 RulerType Ruler::GetDocType( const Point& rPos, RulerType eDragType,
2679                              sal_uInt16* pAryPos ) const
2680 {
2681     ImplRulerHitTest aHitTest;
2682 
2683     // Gegebenenfalls Lineal updaten (damit mit den richtigen Daten
2684     // gearbeitet wird und die Anzeige auch zur Bearbeitung passt)
2685     if ( IsReallyVisible() && mbFormat )
2686     {
2687         ((Ruler*)this)->ImplDraw();
2688         ((Ruler*)this)->mnUpdateFlags &= ~RULER_UPDATE_DRAW;
2689     }
2690 
2691     // HitTest durchfuehren
2692     ImplDocHitTest( rPos, eDragType, &aHitTest );
2693 
2694     // Werte zurueckgeben
2695     if ( pAryPos )
2696         *pAryPos = aHitTest.nAryPos;
2697     return aHitTest.eType;
2698 }
2699 
2700 // -----------------------------------------------------------------------
2701 
2702 void Ruler::CancelDrag()
2703 {
2704     if ( mbDrag )
2705     {
2706         ImplDrag( Point( -1, -1 ) );
2707         ImplEndDrag();
2708     }
2709 }
2710 
2711 // -----------------------------------------------------------------------
2712 
2713 RulerType Ruler::GetType( const Point& rPos, sal_uInt16* pAryPos ) const
2714 {
2715     ImplRulerHitTest aHitTest;
2716 
2717     // Gegebenenfalls Lineal updaten (damit mit den richtigen Daten
2718     // gearbeitet wird und die Anzeige auch zur Bearbeitung passt)
2719     if ( IsReallyVisible() && mbFormat )
2720     {
2721         ((Ruler*)this)->ImplDraw();
2722         ((Ruler*)this)->mnUpdateFlags &= ~RULER_UPDATE_DRAW;
2723     }
2724 
2725     // HitTest durchfuehren
2726     ImplHitTest( rPos, &aHitTest );
2727 
2728     // Werte zurueckgeben
2729     if ( pAryPos )
2730         *pAryPos = aHitTest.nAryPos;
2731     return aHitTest.eType;
2732 }
2733 
2734 // -----------------------------------------------------------------------
2735 
2736 void Ruler::SetWinPos( long nNewOff, long nNewWidth )
2737 {
2738     // Gegebenenfalls werden die Breiten automatisch berechnet
2739     if ( !nNewWidth )
2740         mbAutoWinWidth = sal_True;
2741     else
2742         mbAutoWinWidth = sal_False;
2743 
2744     // Werte setzen (werden in ImplFormat gegebenenfalls mitberechnet)
2745     mnWinOff = nNewOff;
2746     mnWinWidth = nNewWidth;
2747     ImplUpdate( sal_True );
2748 }
2749 
2750 // -----------------------------------------------------------------------
2751 
2752 void Ruler::SetPagePos( long nNewOff, long nNewWidth )
2753 {
2754     // Muessen wir ueberhaupt was machen
2755     if ( (mpData->nPageOff == nNewOff) && (mpData->nPageWidth == nNewWidth) )
2756         return;
2757 
2758     // Gegebenenfalls werden die Breiten automatisch berechnet
2759     if ( !nNewWidth )
2760         mpData->bAutoPageWidth = sal_True;
2761     else
2762         mpData->bAutoPageWidth = sal_False;
2763 
2764     // Werte setzen (werden in ImplFormat gegebenenfalls mitberechnet)
2765     mpData->nPageOff     = nNewOff;
2766     mpData->nPageWidth   = nNewWidth;
2767     ImplUpdate( sal_True );
2768 }
2769 
2770 // -----------------------------------------------------------------------
2771 
2772 void Ruler::SetBorderPos( long nOff )
2773 {
2774     if ( mnWinStyle & WB_BORDER )
2775     {
2776         if ( mnBorderOff != nOff )
2777         {
2778             mnBorderOff = nOff;
2779 
2780             if ( IsReallyVisible() && IsUpdateMode() )
2781                 Invalidate();
2782         }
2783     }
2784 }
2785 
2786 // -----------------------------------------------------------------------
2787 
2788 void Ruler::SetUnit( FieldUnit eNewUnit )
2789 {
2790     if ( meUnit != eNewUnit )
2791     {
2792         meUnit = eNewUnit;
2793         switch ( meUnit )
2794         {
2795             case FUNIT_MM:
2796                 mnUnitIndex = RULER_UNIT_MM;
2797                 break;
2798             case FUNIT_CM:
2799                 mnUnitIndex = RULER_UNIT_CM;
2800                 break;
2801             case FUNIT_M:
2802                 mnUnitIndex = RULER_UNIT_M;
2803                 break;
2804             case FUNIT_KM:
2805                 mnUnitIndex = RULER_UNIT_KM;
2806                 break;
2807             case FUNIT_INCH:
2808                 mnUnitIndex = RULER_UNIT_INCH;
2809                 break;
2810             case FUNIT_FOOT:
2811                 mnUnitIndex = RULER_UNIT_FOOT;
2812                 break;
2813             case FUNIT_MILE:
2814                 mnUnitIndex = RULER_UNIT_MILE;
2815                 break;
2816             case FUNIT_POINT:
2817                 mnUnitIndex = RULER_UNIT_POINT;
2818                 break;
2819             case FUNIT_PICA:
2820                 mnUnitIndex = RULER_UNIT_PICA;
2821                 break;
2822             default:
2823 #ifdef DBG_UTIL
2824                 DBG_ERRORFILE( "Ruler::SetUnit() - Wrong Unit" );
2825 #endif
2826                 break;
2827         }
2828 
2829         maMapMode.SetMapUnit( aImplRulerUnitTab[mnUnitIndex].eMapUnit );
2830         ImplUpdate();
2831     }
2832 }
2833 
2834 // -----------------------------------------------------------------------
2835 
2836 void Ruler::SetZoom( const Fraction& rNewZoom )
2837 {
2838     DBG_ASSERT( rNewZoom.GetNumerator(), "Ruler::SetZoom() with scale 0 is not allowed" );
2839 
2840     if ( maZoom != rNewZoom )
2841     {
2842         maZoom = rNewZoom;
2843         maMapMode.SetScaleX( maZoom );
2844         maMapMode.SetScaleY( maZoom );
2845         ImplUpdate();
2846     }
2847 }
2848 
2849 // -----------------------------------------------------------------------
2850 
2851 void Ruler::SetExtraType( RulerExtra eNewExtraType, sal_uInt16 nStyle )
2852 {
2853     if ( mnWinStyle & WB_EXTRAFIELD )
2854     {
2855         meExtraType  = eNewExtraType;
2856         mnExtraStyle = nStyle;
2857         if ( IsReallyVisible() && IsUpdateMode() )
2858             ImplDrawExtra( sal_False );
2859     }
2860 }
2861 
2862 // -----------------------------------------------------------------------
2863 
2864 void Ruler::SetNullOffset( long nPos )
2865 {
2866     if ( mpData->nNullOff != nPos )
2867     {
2868         mpData->nNullOff = nPos;
2869         ImplUpdate();
2870     }
2871 }
2872 
2873 // -----------------------------------------------------------------------
2874 
2875 void Ruler::SetMargin1( long nPos, sal_uInt16 nMarginStyle )
2876 {
2877     if ( (mpData->nMargin1 != nPos) || (mpData->nMargin1Style != nMarginStyle) )
2878     {
2879         mpData->nMargin1      = nPos;
2880         mpData->nMargin1Style = nMarginStyle;
2881         ImplUpdate();
2882     }
2883 }
2884 
2885 // -----------------------------------------------------------------------
2886 
2887 void Ruler::SetMargin2( long nPos, sal_uInt16 nMarginStyle )
2888 {
2889     DBG_ASSERT( (nPos >= mpData->nMargin1) ||
2890                 (mpData->nMargin1Style & RULER_STYLE_INVISIBLE) ||
2891                 (mpData->nMargin2Style & RULER_STYLE_INVISIBLE),
2892                 "Ruler::SetMargin2() - Margin2 < Margin1" );
2893 
2894     if ( (mpData->nMargin2 != nPos) || (mpData->nMargin2Style != nMarginStyle) )
2895     {
2896         mpData->nMargin2      = nPos;
2897         mpData->nMargin2Style = nMarginStyle;
2898         ImplUpdate();
2899     }
2900 }
2901 
2902 // -----------------------------------------------------------------------
2903 
2904 void Ruler::SetLines( sal_uInt16 n, const RulerLine* pLineAry )
2905 {
2906     // To determine if what has changed
2907     if ( mpData->nLines == n )
2908     {
2909         sal_uInt16           i = n;
2910         const RulerLine* pAry1 = mpData->pLines;
2911         const RulerLine* pAry2 = pLineAry;
2912         while ( i )
2913         {
2914             if ( (pAry1->nPos   != pAry2->nPos)   ||
2915                  (pAry1->nStyle != pAry2->nStyle) )
2916                 break;
2917             pAry1++;
2918             pAry2++;
2919             i--;
2920         }
2921         if ( !i )
2922             return;
2923     }
2924 
2925     // New values and new share issue
2926     sal_Bool bMustUpdate;
2927     if ( IsReallyVisible() && IsUpdateMode() )
2928         bMustUpdate = sal_True;
2929     else
2930         bMustUpdate = sal_False;
2931 
2932     // Delete old lines
2933     if ( bMustUpdate )
2934         ImplInvertLines();
2935 
2936     // New data set
2937     if ( !n || !pLineAry )
2938     {
2939         if ( !mpData->pLines )
2940             return;
2941         delete[] mpData->pLines;
2942         mpData->nLines = 0;
2943         mpData->pLines = NULL;
2944     }
2945     else
2946     {
2947         if ( mpData->nLines != n )
2948         {
2949             delete[] mpData->pLines;
2950             mpData->nLines = n;
2951             mpData->pLines = new RulerLine[n];
2952         }
2953 
2954         memcpy( mpData->pLines, pLineAry, n*sizeof( RulerLine ) );
2955 
2956         // Linien neu ausgeben
2957         if ( bMustUpdate )
2958             ImplInvertLines();
2959     }
2960 }
2961 
2962 // -----------------------------------------------------------------------
2963 
2964 void Ruler::SetArrows( sal_uInt16 n, const RulerArrow* pArrowAry )
2965 {
2966     if ( !n || !pArrowAry )
2967     {
2968         if ( !mpData->pArrows )
2969             return;
2970         delete[] mpData->pArrows;
2971         mpData->nArrows = 0;
2972         mpData->pArrows = NULL;
2973     }
2974     else
2975     {
2976         if ( mpData->nArrows != n )
2977         {
2978             delete[] mpData->pArrows;
2979             mpData->nArrows = n;
2980             mpData->pArrows = new RulerArrow[n];
2981         }
2982         else
2983         {
2984             sal_uInt16            i = n;
2985             const RulerArrow* pAry1 = mpData->pArrows;
2986             const RulerArrow* pAry2 = pArrowAry;
2987             while ( i )
2988             {
2989                 if ( (pAry1->nPos      != pAry2->nPos)      ||
2990                      (pAry1->nWidth    != pAry2->nWidth)    ||
2991                      (pAry1->nLogWidth != pAry2->nLogWidth) ||
2992                      (pAry1->nStyle    != pAry2->nStyle) )
2993                     break;
2994                 pAry1++;
2995                 pAry2++;
2996                 i--;
2997             }
2998             if ( !i )
2999                 return;
3000         }
3001 
3002         memcpy( mpData->pArrows, pArrowAry, n*sizeof( RulerArrow ) );
3003     }
3004 
3005     ImplUpdate();
3006 }
3007 
3008 // -----------------------------------------------------------------------
3009 
3010 void Ruler::SetBorders( sal_uInt16 n, const RulerBorder* pBrdAry )
3011 {
3012     if ( !n || !pBrdAry )
3013     {
3014         if ( !mpData->pBorders )
3015             return;
3016         delete[] mpData->pBorders;
3017         mpData->nBorders = 0;
3018         mpData->pBorders = NULL;
3019     }
3020     else
3021     {
3022         if ( mpData->nBorders != n )
3023         {
3024             delete[] mpData->pBorders;
3025             mpData->nBorders = n;
3026             mpData->pBorders = new RulerBorder[n];
3027         }
3028         else
3029         {
3030             sal_uInt16             i = n;
3031             const RulerBorder* pAry1 = mpData->pBorders;
3032             const RulerBorder* pAry2 = pBrdAry;
3033             while ( i )
3034             {
3035                 if ( (pAry1->nPos   != pAry2->nPos)   ||
3036                      (pAry1->nWidth != pAry2->nWidth) ||
3037                      (pAry1->nStyle != pAry2->nStyle) )
3038                     break;
3039                 pAry1++;
3040                 pAry2++;
3041                 i--;
3042             }
3043             if ( !i )
3044                 return;
3045         }
3046 
3047         memcpy( mpData->pBorders, pBrdAry, n*sizeof( RulerBorder ) );
3048     }
3049 
3050     ImplUpdate();
3051 }
3052 
3053 // -----------------------------------------------------------------------
3054 
3055 void Ruler::SetIndents( sal_uInt16 n, const RulerIndent* pIndentAry )
3056 {
3057 
3058     if ( !n || !pIndentAry )
3059     {
3060         if ( !mpData->pIndents )
3061             return;
3062         delete[] mpData->pIndents;
3063         mpData->nIndents = 0;
3064         mpData->pIndents = NULL;
3065     }
3066     else
3067     {
3068         if ( mpData->nIndents != n )
3069         {
3070             delete[] mpData->pIndents;
3071             mpData->nIndents = n;
3072             mpData->pIndents = new RulerIndent[n];
3073         }
3074         else
3075         {
3076             sal_uInt16             i = n;
3077             const RulerIndent* pAry1 = mpData->pIndents;
3078             const RulerIndent* pAry2 = pIndentAry;
3079             while ( i )
3080             {
3081                 if ( (pAry1->nPos   != pAry2->nPos) ||
3082                      (pAry1->nStyle != pAry2->nStyle) )
3083                     break;
3084                 pAry1++;
3085                 pAry2++;
3086                 i--;
3087             }
3088             if ( !i )
3089                 return;
3090         }
3091 
3092         memcpy( mpData->pIndents, pIndentAry, n*sizeof( RulerIndent ) );
3093     }
3094 
3095     ImplUpdate();
3096 }
3097 
3098 // -----------------------------------------------------------------------
3099 
3100 void Ruler::SetTabs( sal_uInt16 n, const RulerTab* pTabAry )
3101 {
3102     if ( !n || !pTabAry )
3103     {
3104         if ( !mpData->pTabs )
3105             return;
3106         delete[] mpData->pTabs;
3107         mpData->nTabs = 0;
3108         mpData->pTabs = NULL;
3109     }
3110     else
3111     {
3112         if ( mpData->nTabs != n )
3113         {
3114             delete[] mpData->pTabs;
3115             mpData->nTabs = n;
3116             mpData->pTabs = new RulerTab[n];
3117         }
3118         else
3119         {
3120             sal_uInt16          i = n;
3121             const RulerTab* pAry1 = mpData->pTabs;
3122             const RulerTab* pAry2 = pTabAry;
3123             while ( i )
3124             {
3125                 if ( (pAry1->nPos   != pAry2->nPos) ||
3126                      (pAry1->nStyle != pAry2->nStyle) )
3127                     break;
3128                 pAry1++;
3129                 pAry2++;
3130                 i--;
3131             }
3132             if ( !i )
3133                 return;
3134         }
3135 
3136         memcpy( mpData->pTabs, pTabAry, n*sizeof( RulerTab ) );
3137     }
3138 
3139     ImplUpdate();
3140 }
3141 
3142 // -----------------------------------------------------------------------
3143 
3144 void Ruler::SetStyle( WinBits nStyle )
3145 {
3146     if ( mnWinStyle != nStyle )
3147     {
3148         mnWinStyle = nStyle;
3149         ImplInitExtraField( sal_True );
3150     }
3151 }
3152 
3153 // -----------------------------------------------------------------------
3154 
3155 void Ruler::DrawTab( OutputDevice* pDevice, const Point& rPos, sal_uInt16 nStyle )
3156 {
3157     /*const StyleSettings&    rStyleSettings =*/ pDevice->GetSettings().GetStyleSettings();
3158     Point                   aPos( rPos );
3159     sal_uInt16                  nTabStyle = nStyle & (RULER_TAB_STYLE | RULER_TAB_RTL);
3160 
3161     pDevice->Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
3162     pDevice->SetLineColor();
3163     pDevice->SetFillColor( pDevice->GetSettings().GetStyleSettings().GetWindowTextColor() );
3164     ImplCenterTabPos( aPos, nTabStyle );
3165     ImplDrawRulerTab( pDevice, aPos, nTabStyle, nStyle  );
3166     pDevice->Pop();
3167 }
3168 /* -----------------16.10.2002 15:17-----------------
3169  *
3170  * --------------------------------------------------*/
3171 void Ruler::SetTextRTL(sal_Bool bRTL)
3172 {
3173     if(mpData->bTextRTL != bRTL)
3174     {
3175         mpData->bTextRTL = bRTL;
3176         if ( IsReallyVisible() && IsUpdateMode() )
3177             ImplInitExtraField( sal_True );
3178     }
3179 
3180 }
3181 long Ruler::GetPageOffset() const { return mpData->nPageOff; }
3182 long                Ruler::GetPageWidth() const { return mpData->nPageWidth; }
3183 long                Ruler::GetNullOffset() const { return mpData->nNullOff; }
3184 long                Ruler::GetMargin1() const { return mpData->nMargin1; }
3185 sal_uInt16              Ruler::GetMargin1Style() const { return mpData->nMargin1Style; }
3186 long                Ruler::GetMargin2() const { return mpData->nMargin2; }
3187 sal_uInt16              Ruler::GetMargin2Style() const { return mpData->nMargin2Style; }
3188 sal_uInt16              Ruler::GetLineCount() const { return mpData->nLines; }
3189 const RulerLine*    Ruler::GetLines() const { return mpData->pLines; }
3190 sal_uInt16              Ruler::GetArrowCount() const { return mpData->nArrows; }
3191 const RulerArrow*   Ruler::GetArrows() const { return mpData->pArrows; }
3192 sal_uInt16              Ruler::GetBorderCount() const { return mpData->nBorders; }
3193 const RulerBorder*  Ruler::GetBorders() const { return mpData->pBorders; }
3194 sal_uInt16              Ruler::GetIndentCount() const { return mpData->nIndents; }
3195 const RulerIndent*  Ruler::GetIndents() const { return mpData->pIndents; }
3196 
3197 //IAccessibility2 Implementation 2009-----
3198 uno::Reference< XAccessible > Ruler::CreateAccessible()
3199 {
3200 	Window*						pParent = GetAccessibleParentWindow();
3201 	DBG_ASSERT( pParent, "-SvxRuler::CreateAccessible(): No Parent!" );
3202 	uno::Reference< XAccessible >	xAccParent  = pParent->GetAccessible();
3203 	if( xAccParent.is() )
3204 	{
3205 		// MT: Fixed compiler issue because the address from a temporary object was used.
3206 		// BUT: Shoudl it really be a Pointer, instead of const&???
3207 		OUString aStr;
3208 		if ( mnWinStyle & WB_HORZ )
3209 		{
3210 			aStr = OUString(XubString(SvtResId(STR_SVT_ACC_RULER_HORZ_NAME)));
3211 		}
3212 		else
3213 		{
3214 			aStr = OUString(XubString(SvtResId(STR_SVT_ACC_RULER_VERT_NAME)));
3215 		}
3216 		pAccContext = new SvtRulerAccessible( xAccParent, *this, aStr );
3217 		pAccContext->acquire();
3218 		this->SetAccessible(pAccContext);
3219 		return pAccContext;
3220 	}
3221 	else
3222 		return uno::Reference< XAccessible >();
3223 }
3224 //-----IAccessibility2 Implementation 2009
3225