/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * 
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: svxruler.cxx,v $
 * $Revision: 1.39.76.1 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"

// INCLUDE ---------------------------------------------------------------

#include <string.h>
#include <limits.h>
#include <tools/shl.hxx>
#include <vcl/image.hxx>
#include <svtools/eitem.hxx>
#include <svtools/rectitem.hxx>
#include <sfx2/dispatch.hxx>

#include <svtools/smplhint.hxx>





#include <svx/dialogs.hrc>
#include <svx/dialmgr.hxx>
#include <svx/ruler.hxx>
#include "rlrcitem.hxx"
#include "rulritem.hxx"
#include <svx/tstpitem.hxx>
#include <svx/lrspitem.hxx>
#include "protitem.hxx"
#ifndef _APP_HXX
#include <vcl/svapp.hxx>
#endif
#ifndef RULER_TAB_RTL
#define RULER_TAB_RTL           ((USHORT)0x0010)
#endif

// STATIC DATA -----------------------------------------------------------

#define CTRL_ITEM_COUNT 14
#define GAP 10
#define OBJECT_BORDER_COUNT 4
#define TAB_GAP 1
#define INDENT_GAP 2
#define INDENT_FIRST_LINE   4
#define INDENT_LEFT_MARGIN  5
#define INDENT_RIGHT_MARGIN 6
#define INDENT_LEFT_BORDER  2
#define INDENT_RIGHT_BORDER 3
#define INDENT_COUNT        5 //without the first two old values

#define PIXEL_H_ADJUST( l1, l2 ) PixelHAdjust(l1,l2)

#ifdef DEBUGLIN

inline long ToMM(Window *pWin, long lVal)
{
	return pWin->PixelToLogic(Size(lVal, 0), MapMode(MAP_MM)).Width();
}

void Debug_Impl(Window *pWin, SvxColumnItem& rColItem)
{
	String aTmp("Aktuell: ");
	aTmp += rColItem.GetActColumn();
	aTmp += " ColLeft: ";
	aTmp +=  String(ToMM(pWin, rColItem.GetLeft()));
	aTmp += "   ColRight: ";
	aTmp +=  String(ToMM(pWin, rColItem.GetRight()));
	for(USHORT i = 0; i < rColItem.Count(); ++i) {
		aTmp += " Start: ";
		aTmp += String(ToMM(pWin, rColItem[i].nStart));
		aTmp += " End: ";
		aTmp += String(ToMM(pWin, rColItem[i].nEnd));
	}

	InfoBox(0, aTmp).Execute();
}

void Debug_Impl(Window *pWin, const SvxLongLRSpaceItem& rLRSpace)
{
	String aTmp("Left: ");
	aTmp += pWin->PixelToLogic(Size(rLRSpace.GetLeft(), 0), MapMode(MAP_MM)).Width();
	aTmp += "   Right: ";
	aTmp +=pWin->PixelToLogic(Size(rLRSpace.GetRight(), 0), MapMode(MAP_MM)).Width();
	InfoBox(0, aTmp).Execute();
}

void Debug_Impl(Window *pWin, const SvxLongULSpaceItem& rULSpace)
{
	String aTmp("Upper: ");
	aTmp += pWin->PixelToLogic(Size(rULSpace.GetUpper(), 0), MapMode(MAP_MM)).Width();
	aTmp += "   Lower: ";
	aTmp += pWin->PixelToLogic(Size(rULSpace.GetLower(), 0), MapMode(MAP_MM)).Width();

	InfoBox(0, aTmp).Execute();
}

void DebugTabStops_Impl(const SvxTabStopItem& rTabs)
{
	String aTmp("Tabs: ");

	// Def Tabs loeschen
	for(USHORT i = 0; i < rTabs.Count(); ++i)
	{
		aTmp += String(rTabs[i].GetTabPos() / 56);
		aTmp += " : ";
	}
	InfoBox(0, aTmp).Execute();
}

void DebugParaMargin_Impl(const SvxLRSpaceItem& rLRSpace)
{
	String aTmp("ParaLeft: ");
	aTmp += rLRSpace.GetTxtLeft() / 56;
	aTmp += "   ParaRight: ";
	aTmp += rLRSpace.GetRight() / 56;
	aTmp += "   FLI: ";
	aTmp += rLRSpace.GetTxtFirstLineOfst() / 56;
	InfoBox(0, aTmp).Execute();
}

#endif // DEBUGLIN
#ifdef DEBUG_RULER
#include <vcl/svapp.hxx>
#include <vcl/lstbox.hxx>
class RulerDebugWindow : public Window
{
    ListBox aBox;
public:
        RulerDebugWindow(Window* pParent) :
            Window(pParent, WB_BORDER|WB_SIZEMOVE|WB_DIALOGCONTROL|WB_CLIPCHILDREN|WB_SYSTEMWINDOW),
            aBox(this, WB_BORDER)
            {
                Size aOutput(200, 400);
                SetOutputSizePixel(aOutput);
                aBox.SetSizePixel(aOutput);
                aBox.Show();
                Show();
                Size aParentSize(pParent->GetOutputSizePixel());
                Size aOwnSize(GetSizePixel());
                aParentSize.Width() -= aOwnSize.Width();
                aParentSize.Height() -= aOwnSize.Height();
                SetPosPixel(Point(aParentSize.Width(), aParentSize.Height()));
            }
        ~RulerDebugWindow();

        ListBox& GetLBox() {return aBox;}
        static void     AddDebugText(const sal_Char* pDescription, const String& rText );
};
static RulerDebugWindow* pDebugWindow = 0;

RulerDebugWindow::~RulerDebugWindow()
{
    pDebugWindow = 0;
}
void     RulerDebugWindow::AddDebugText(const sal_Char* pDescription, const String& rText )
{
    if(!pDebugWindow)
    {
        Window* pParent = Application::GetFocusWindow();
        while(pParent->GetParent())
            pParent = pParent->GetParent();
        pDebugWindow = new RulerDebugWindow(pParent);
    }
    String sContent(String::CreateFromAscii(pDescription));
    sContent += rText;
    USHORT nPos = pDebugWindow->GetLBox().InsertEntry(sContent);
    pDebugWindow->GetLBox().SelectEntryPos(nPos);
    pDebugWindow->GrabFocus();
}

#define ADD_DEBUG_TEXT(cDescription, sValue) \
    RulerDebugWindow::AddDebugText(cDescription, sValue);

#define REMOVE_DEBUG_WINDOW \
    delete pDebugWindow;    \
    pDebugWindow = 0;

#else
#define ADD_DEBUG_TEXT(cDescription, sValue)
#define REMOVE_DEBUG_WINDOW
#endif

struct SvxRuler_Impl  {
	USHORT *pPercBuf;
	USHORT *pBlockBuf;
	USHORT nPercSize;
	long   nTotalDist;
	long   lOldWinPos;
	long   lMaxLeftLogic;
	long   lMaxRightLogic;
	long   lLastLMargin;
	long   lLastRMargin;
    SvxProtectItem aProtectItem;
    SfxBoolItem* pTextRTLItem;
	USHORT nControlerItems;
	USHORT nIdx;
	USHORT nColLeftPix, nColRightPix; // Pixelwerte fuer linken / rechten Rand
									  // bei Spalten; gepuffert, um Umrechenfehler
									  // zu vermeiden.
									  // Muesste vielleicht fuer weitere Werte
									  // aufgebohrt werden
    BOOL bIsTableRows : 1;      // pColumnItem contains table rows instead of columns
    //#i24363# tab stops relative to indent
    BOOL bIsTabsRelativeToIndent : 1; // Tab stops relative to paragraph indent?
    SvxRuler_Impl() :
    pPercBuf(0), pBlockBuf(0),
    nPercSize(0), nTotalDist(0),
    lOldWinPos(0),
    lMaxLeftLogic(0), lMaxRightLogic(0),
    lLastLMargin(0), lLastRMargin(0),
    aProtectItem(SID_RULER_PROTECT),
    pTextRTLItem(0), nControlerItems(0),
    nIdx(0),
    nColLeftPix(0), nColRightPix(0),

    bIsTableRows(FALSE),
    bIsTabsRelativeToIndent(TRUE)
	{
	}
	~SvxRuler_Impl()
	{
		nPercSize = 0; nTotalDist = 0;
		delete[] pPercBuf; delete[] pBlockBuf; pPercBuf = 0;
        delete pTextRTLItem;
	}
	void SetPercSize(USHORT nSize);

};



void SvxRuler_Impl::SetPercSize(USHORT nSize)
{
	if(nSize > nPercSize)
	{
		delete[] pPercBuf;
		delete[] pBlockBuf;
		pPercBuf = new USHORT[nPercSize = nSize];
		pBlockBuf = new USHORT[nPercSize = nSize];
	}
	size_t nSize2 = sizeof(USHORT) * nPercSize;
	memset(pPercBuf, 0, nSize2);
	memset(pBlockBuf, 0, nSize2);
}


// Konstruktor des Lineals

// SID_ATTR_ULSPACE, SID_ATTR_LRSPACE
// erwartet als Parameter SvxULSpaceItem f"ur Seitenr"ander
// (entweder links/rechts oder oben/unten)
// Lineal: SetMargin1, SetMargin2

// SID_RULER_PAGE_POS
// erwartet als Parameter Anfangswert der Seite sowie Seitenbreite
// Lineal: SetPagePos

// SID_ATTR_TABSTOP
// erwartet: SvxTabStopItem
// Lineal: SetTabs

// SID_ATTR_PARA_LRSPACE
// linker, rechter Absatzrand bei H-Lineal
// Lineal: SetIndents

// SID_RULER_BORDERS
// Tabellenraender, Spalten
// erwartet: so etwas wie SwTabCols
// Lineal: SetBorders


SvxRuler::SvxRuler
(
 Window* pParent,                               // StarView Parent
 Window* pWin,                                  // Ausgabefenster; wird fuer Umrechnung logische
				// Einheiten <-> Pixel verwendet
 USHORT  flags,                                 // Anzeige Flags, siehe ruler.hxx
 SfxBindings &rBindings,                // zugeordnete Bindings
 WinBits nWinStyle                              // StarView WinBits
)
: Ruler(pParent, nWinStyle),
  pCtrlItem(new SvxRulerItem *[CTRL_ITEM_COUNT]),
  pLRSpaceItem(0),
  pMinMaxItem(0),
  pULSpaceItem(0),
  pTabStopItem(0),
  pParaItem(0),
  pParaBorderItem(0),
  pPagePosItem(0),
  pColumnItem(0),
  pObjectItem(0),
  pEditWin(pWin),
  pRuler_Imp(new SvxRuler_Impl),
  bAppSetNullOffset(FALSE),  //Wird der 0-Offset des Lineals
                             //durch die appl. gesetzt?
  lLogicNullOffset(0),
  lAppNullOffset(LONG_MAX),
  lMinFrame(5),
  lInitialDragPos(0),
  nFlags(flags),
  nDragType(NONE),
  nDefTabType(RULER_TAB_LEFT),
  nTabCount(0),
  nTabBufSize(0),
  lDefTabDist(50),
  lTabPos(-1),
  pTabs(0),
  pIndents(0),
  pBorders(new RulerBorder[1]), //wg 1 Spaltiger Tabellen
  nBorderCount(0),
  pObjectBorders(0),
  pBindings(&rBindings),
  nDragOffset(0),
  nMaxLeft(0),
  nMaxRight(0),
  bValid(FALSE),
  bListening(FALSE),
  bActive(TRUE)

/*
   [Beschreibung]

   ctor;
   Datenpuffer initialisieren; ControllerItems werden erzeugt

*/
{
	memset(pCtrlItem, 0, sizeof(SvxRulerItem *) * CTRL_ITEM_COUNT);

	rBindings.EnterRegistrations();

	// Unterstuetzte Items anlegen
	USHORT i = 0;
	// Seitenraender

	pCtrlItem[i++] = new SvxRulerItem(SID_RULER_LR_MIN_MAX, *this, rBindings);
	if((nWinStyle & WB_VSCROLL) == WB_VSCROLL)
	{
		bHorz = FALSE;
		pCtrlItem[i++] = new SvxRulerItem(SID_ATTR_LONG_ULSPACE, *this, rBindings);
    }
	else
	{
		bHorz = TRUE;
		pCtrlItem[i++] = new SvxRulerItem(SID_ATTR_LONG_LRSPACE, *this, rBindings);
	}

	// Seitenposition
	pCtrlItem[i++] = new SvxRulerItem(SID_RULER_PAGE_POS, *this, rBindings);

	if((nFlags & SVXRULER_SUPPORT_TABS) == SVXRULER_SUPPORT_TABS)
	{
        USHORT nTabStopId = bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL;
        pCtrlItem[i++] = new SvxRulerItem(nTabStopId, *this, rBindings);
		SetExtraType(RULER_EXTRA_TAB, nDefTabType);
	}


    if(0 != (nFlags & (SVXRULER_SUPPORT_PARAGRAPH_MARGINS |SVXRULER_SUPPORT_PARAGRAPH_MARGINS_VERTICAL)))
	{
		if(bHorz)
			pCtrlItem[i++] = new SvxRulerItem(SID_ATTR_PARA_LRSPACE, *this, rBindings);
		else
			pCtrlItem[i++] = new SvxRulerItem(SID_ATTR_PARA_LRSPACE_VERTICAL, *this, rBindings);
        pIndents = new RulerIndent[5+INDENT_GAP];
		memset(pIndents, 0, sizeof(RulerIndent)*(3+INDENT_GAP));
		pIndents[0].nStyle = RULER_STYLE_DONTKNOW;
		pIndents[1].nStyle = RULER_STYLE_DONTKNOW;
        pIndents[INDENT_FIRST_LINE].nStyle = RULER_INDENT_TOP;
        pIndents[INDENT_LEFT_MARGIN].nStyle = RULER_INDENT_BOTTOM;
        pIndents[INDENT_RIGHT_MARGIN].nStyle = RULER_INDENT_BOTTOM;
        pIndents[INDENT_LEFT_BORDER].nStyle = RULER_INDENT_BORDER;
        pIndents[INDENT_RIGHT_BORDER].nStyle = RULER_INDENT_BORDER;
        for(USHORT nIn = 0; nIn < 7; nIn++)
            pIndents[nIn].nPos = 0;
    }

	if((nFlags & SVXRULER_SUPPORT_BORDERS) ==  SVXRULER_SUPPORT_BORDERS)
    {
        pCtrlItem[i++] = new SvxRulerItem(bHorz ? SID_RULER_BORDERS : SID_RULER_BORDERS_VERTICAL, *this, rBindings);
        pCtrlItem[i++] = new SvxRulerItem(bHorz ? SID_RULER_ROWS : SID_RULER_ROWS_VERTICAL, *this, rBindings);
    }

    pCtrlItem[i++] = new SvxRulerItem(SID_RULER_TEXT_RIGHT_TO_LEFT, *this, rBindings);

	if((nFlags & SVXRULER_SUPPORT_OBJECT) == SVXRULER_SUPPORT_OBJECT)
	{
		pCtrlItem[i++] = new SvxRulerItem(SID_RULER_OBJECT, *this, rBindings );
		pObjectBorders = new RulerBorder[OBJECT_BORDER_COUNT];
		size_t nSize = sizeof( RulerBorder ) * OBJECT_BORDER_COUNT;
		memset(pObjectBorders, 0, nSize);
        for(USHORT nBorder = 0; nBorder < OBJECT_BORDER_COUNT; ++nBorder)
		{
            pObjectBorders[nBorder].nPos   = 0;
            pObjectBorders[nBorder].nWidth = 0;
            pObjectBorders[nBorder].nStyle = RULER_BORDER_MOVEABLE;
		}
	}

	pCtrlItem[i++] = new SvxRulerItem( SID_RULER_PROTECT, *this, rBindings );
    pCtrlItem[i++] = new SvxRulerItem(SID_RULER_BORDER_DISTANCE, *this, rBindings);
    pRuler_Imp->nControlerItems=i;

	if((nFlags & SVXRULER_SUPPORT_SET_NULLOFFSET) ==
	   SVXRULER_SUPPORT_SET_NULLOFFSET)
		SetExtraType(RULER_EXTRA_NULLOFFSET, 0);

	rBindings.LeaveRegistrations();
}


__EXPORT SvxRuler::~SvxRuler()
/*
   [Beschreibung]

   Destruktor Lineal
   Freigabe interner Puffer


*/
{
    REMOVE_DEBUG_WINDOW
    if(bListening)
		EndListening(*pBindings);

	pBindings->EnterRegistrations();

	for(USHORT i = 0; i < CTRL_ITEM_COUNT  && pCtrlItem[i]; ++i)
		delete pCtrlItem[i];
	delete[] pCtrlItem;

	delete pLRSpaceItem;
	delete pMinMaxItem;
	delete pULSpaceItem;
	delete pTabStopItem;
	delete pParaItem;
    delete pParaBorderItem;
    delete pPagePosItem;
	delete pColumnItem;
	delete pObjectItem;
	delete[] pIndents;
	delete[] pBorders;
	delete[] pObjectBorders;
	delete[] pTabs;
	delete pRuler_Imp;

	pBindings->LeaveRegistrations();
}

/*

   [Beschreibung]

   Interne Umrechenroutinen

*/

long SvxRuler::ConvertHPosPixel(long nVal) const
{
	return pEditWin->LogicToPixel(Size(nVal, 0)).Width();
}

long SvxRuler::ConvertVPosPixel(long nVal) const
{
	return pEditWin->LogicToPixel(Size(0, nVal)).Height();
}

long SvxRuler::ConvertHSizePixel(long nVal) const
{
	return pEditWin->LogicToPixel(Size(nVal, 0)).Width();
}

long SvxRuler::ConvertVSizePixel(long nVal) const
{
	return pEditWin->LogicToPixel(Size(0, nVal)).Height();
}

long SvxRuler::ConvertPosPixel(long nVal) const
{
	return bHorz ? ConvertHPosPixel(nVal): ConvertVPosPixel(nVal);
}

long SvxRuler::ConvertSizePixel(long nVal) const
{
	return bHorz? ConvertHSizePixel(nVal): ConvertVSizePixel(nVal);
}


inline long SvxRuler::ConvertHPosLogic(long nVal) const
{
	return pEditWin->PixelToLogic(Size(nVal, 0)).Width();
}

inline long SvxRuler::ConvertVPosLogic(long nVal) const
{
	return pEditWin->PixelToLogic(Size(0, nVal)).Height();
}

inline long SvxRuler::ConvertHSizeLogic(long nVal) const
{
	return pEditWin->PixelToLogic(Size(nVal, 0)).Width();
}

inline long SvxRuler::ConvertVSizeLogic(long nVal) const
{
	return pEditWin->PixelToLogic(Size(0, nVal)).Height();
}

inline long SvxRuler::ConvertPosLogic(long nVal) const
{
	return bHorz? ConvertHPosLogic(nVal): ConvertVPosLogic(nVal);
}

inline long SvxRuler::ConvertSizeLogic(long nVal) const
{
	return bHorz? ConvertHSizeLogic(nVal): ConvertVSizeLogic(nVal);
}

long SvxRuler::PixelHAdjust(long nVal, long nValOld) const
{
		if(ConvertHSizePixel(nVal)!=ConvertHSizePixel(nValOld))
				return  nVal;
		else
				return  nValOld;
}

long SvxRuler::PixelVAdjust(long nVal, long nValOld) const
{
		if(ConvertVSizePixel(nVal)!=ConvertVSizePixel(nValOld))
				return  nVal;
		else
				return  nValOld;
}

long SvxRuler::PixelAdjust(long nVal, long nValOld) const
{
		if(ConvertSizePixel(nVal)!=ConvertSizePixel(nValOld))
				return  nVal;
		else
				return  nValOld;
}


inline USHORT SvxRuler::GetObjectBordersOff(USHORT nIdx) const
{
	return bHorz? nIdx: nIdx + 2;
}



void SvxRuler::UpdateFrame()

/*
   [Beschreibung]

   Linken, oberen Rand aktualisieren
   Items werden in die Darstellung des Lineals uebersetzt.

*/

{
	const USHORT nMarginStyle =
		( pRuler_Imp->aProtectItem.IsSizeProtected() ||
		  pRuler_Imp->aProtectItem.IsPosProtected() ) ?
		0 : RULER_MARGIN_SIZEABLE;

	if(pLRSpaceItem && pPagePosItem)
	{
		// wenn keine Initialisierung durch App Defaultverhalten
		const long nOld = lLogicNullOffset;
		lLogicNullOffset = pColumnItem?
			pColumnItem->GetLeft(): pLRSpaceItem->GetLeft();
		if(bAppSetNullOffset)
			lAppNullOffset += lLogicNullOffset - nOld;
		if(!bAppSetNullOffset || lAppNullOffset == LONG_MAX)
		{
			Ruler::SetNullOffset(ConvertHPosPixel(lLogicNullOffset));
			SetMargin1( 0, nMarginStyle );
			lAppNullOffset = 0;
		}
		else
			SetMargin1( ConvertHPosPixel( lAppNullOffset ), nMarginStyle );
		long lRight = 0;
			// bei Tabelle rechten Rand der Tabelle auswerten
		if(pColumnItem && pColumnItem->IsTable())
			lRight = pColumnItem->GetRight();
		else
			lRight = pLRSpaceItem->GetRight();

		ULONG aWidth=
			ConvertHPosPixel(pPagePosItem->GetWidth() - lRight -
									lLogicNullOffset + lAppNullOffset);
		SetMargin2( aWidth, nMarginStyle );
	}
	else
		if(pULSpaceItem && pPagePosItem)
		{
			// Nullpunkt aus oberem Rand des umgebenden Rahmens
			const long nOld = lLogicNullOffset;
			lLogicNullOffset = pColumnItem?
				pColumnItem->GetLeft(): pULSpaceItem->GetUpper();
			if(bAppSetNullOffset)
				lAppNullOffset += lLogicNullOffset - nOld;
			if(!bAppSetNullOffset || lAppNullOffset == LONG_MAX) {
				Ruler::SetNullOffset(ConvertVPosPixel(lLogicNullOffset));
				lAppNullOffset = 0;
				SetMargin1( 0, nMarginStyle );
			}
			else
				SetMargin1( ConvertVPosPixel( lAppNullOffset ),nMarginStyle );

			long lLower = pColumnItem ?
				pColumnItem->GetRight() : pULSpaceItem->GetLower();

			SetMargin2(ConvertVPosPixel(pPagePosItem->GetHeight() - lLower -
										lLogicNullOffset + lAppNullOffset),
										nMarginStyle );
		}
	else
	{
		// schaltet die Anzeige aus
		SetMargin1();
		SetMargin2();
	}
	if(pColumnItem)
	{
		pRuler_Imp->nColLeftPix = (USHORT) ConvertSizePixel(pColumnItem->GetLeft());
		pRuler_Imp->nColRightPix = (USHORT) ConvertSizePixel(pColumnItem->GetRight());
	}

}

void SvxRuler::MouseMove( const MouseEvent& rMEvt )
{
	if( bActive )
	{
		pBindings->Update( SID_RULER_LR_MIN_MAX );
		pBindings->Update( SID_ATTR_LONG_ULSPACE );
		pBindings->Update( SID_ATTR_LONG_LRSPACE );
		pBindings->Update( SID_RULER_PAGE_POS );
        pBindings->Update( bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL);
        pBindings->Update( bHorz ? SID_ATTR_PARA_LRSPACE : SID_ATTR_PARA_LRSPACE_VERTICAL);
        pBindings->Update( bHorz ? SID_RULER_BORDERS : SID_RULER_BORDERS_VERTICAL);
        pBindings->Update( bHorz ? SID_RULER_ROWS : SID_RULER_ROWS_VERTICAL);
        pBindings->Update( SID_RULER_OBJECT );
		pBindings->Update( SID_RULER_PROTECT );
	}
	Ruler::MouseMove( rMEvt );
}
void SvxRuler::StartListening_Impl()
{
    if(!bListening)
	{
		bValid = FALSE;
		StartListening(*pBindings);
		bListening = TRUE;
	}
}

void SvxRuler::UpdateFrame
(
 const SvxLongLRSpaceItem *pItem    // neuer Wert LRSpace
)

/*
   [Beschreibung]

   Neuen Wert fuer LRSpace merken; alten gfs. loeschen

*/

{
  if(bActive)
  {
	delete pLRSpaceItem; pLRSpaceItem = 0;
	if(pItem)
		pLRSpaceItem = new SvxLongLRSpaceItem(*pItem);
    StartListening_Impl();
  }
}


void SvxRuler::UpdateFrameMinMax
(
 const SfxRectangleItem *pItem  // Werte fuer MinMax
)

/*
   [Beschreibung]

   Neuen Wert fuer MinMax setzen; alten gfs. loeschen

*/

{
	if(bActive)
	{
		delete pMinMaxItem; pMinMaxItem = 0;
		if(pItem)
			pMinMaxItem = new SfxRectangleItem(*pItem);
	}
}


void SvxRuler::UpdateFrame
(
 const SvxLongULSpaceItem *pItem    // neuer Wert
)

/*
   [Beschreibung]

   Rechten / unteren Rand aktualisieren

*/


{
  if(bActive && !bHorz)
  {
	delete pULSpaceItem; pULSpaceItem = 0;
	if(pItem)
		pULSpaceItem = new SvxLongULSpaceItem(*pItem);
    StartListening_Impl();
  }
}

void SvxRuler::Update( const SvxProtectItem* pItem )
{
	if( pItem ) pRuler_Imp->aProtectItem = *pItem;
}
/* -----------------------------22.08.2002 13:10------------------------------

 ---------------------------------------------------------------------------*/
void SvxRuler::UpdateTextRTL(const SfxBoolItem* pItem)
{
  if(bActive && bHorz)
  {
    delete pRuler_Imp->pTextRTLItem; pRuler_Imp->pTextRTLItem = 0;
	if(pItem)
        pRuler_Imp->pTextRTLItem = new SfxBoolItem(*pItem);
    SetTextRTL(pRuler_Imp->pTextRTLItem && pRuler_Imp->pTextRTLItem->GetValue());
    StartListening_Impl();
  }
}

void SvxRuler::Update
(
 const SvxColumnItem *pItem,             // neuer Wert
 USHORT nSID //Slot Id to identify NULL items
)

/*
   [Beschreibung]

   Neuen Wert fuer Spaltendarstellung setzen

*/

{
	if(bActive)
	{
        if(pItem)
		{
            delete pColumnItem; pColumnItem = 0;
            pRuler_Imp->bIsTableRows = (pItem->Which() == SID_RULER_ROWS || pItem->Which() == SID_RULER_ROWS_VERTICAL);
            pColumnItem = new SvxColumnItem(*pItem);
            if(!bHorz && !pRuler_Imp->bIsTableRows)
                pColumnItem->SetWhich(SID_RULER_BORDERS_VERTICAL);
		}
        else if(pColumnItem && pColumnItem->Which() == nSID)
        //there are two groups of column items table/frame columns and table rows
        //both can occur in vertical or horizontal mode
        //the horizontal ruler handles the SID_RULER_BORDERS and SID_RULER_ROWS_VERTICAL
        //and the vertical handles SID_RULER_BORDERS_VERTICAL and SID_RULER_ROWS
        //if pColumnItem is already set with one of the ids then a NULL pItem argument
        //must not delete it
        {
            delete pColumnItem; pColumnItem = 0;
            pRuler_Imp->bIsTableRows = FALSE;
        }
        StartListening_Impl();
    }
}


void SvxRuler::UpdateColumns()
/*
   [Beschreibung]

   Anzeige der Spaltendarstellung aktualisieren

*/
{
	if(pColumnItem && pColumnItem->Count() > 1)
	{
		if( nBorderCount < pColumnItem->Count())
		{
			delete[] pBorders;
			nBorderCount = pColumnItem->Count();
			pBorders = new RulerBorder[nBorderCount];
		}
        USHORT _nFlags = RULER_BORDER_VARIABLE;
		BOOL bProtectColumns =
			pRuler_Imp->aProtectItem.IsSizeProtected() ||
			pRuler_Imp->aProtectItem.IsPosProtected();
		if( !bProtectColumns )
            _nFlags |= RULER_BORDER_MOVEABLE;
		if( pColumnItem->IsTable() )
            _nFlags |= RULER_BORDER_TABLE;
		else
			if ( !bProtectColumns )
                _nFlags |= RULER_BORDER_SIZEABLE;

		USHORT nBorders = pColumnItem->Count();
		if(!pRuler_Imp->bIsTableRows)
			--nBorders;
		for(USHORT i = 0; i < nBorders; ++i)
		{
            pBorders[i].nStyle = _nFlags;
			if(!(*pColumnItem)[i].bVisible)
				pBorders[i].nStyle |= RULER_STYLE_INVISIBLE;
			pBorders[i].nPos =
				ConvertPosPixel((*pColumnItem)[i].nEnd + lAppNullOffset);
			if(pColumnItem->Count() == i + 1)
			{
				//with table rows the end of the table is contained in the
				//column item but it has no width!
				pBorders[i].nWidth = 0;
			}
			else
			{
				pBorders[i].nWidth =
					ConvertSizePixel((*pColumnItem)[i+1].nStart -
								 (*pColumnItem)[i].nEnd);
			}
            pBorders[i].nMinPos =
                ConvertPosPixel((*pColumnItem)[i].nEndMin + lAppNullOffset);
            pBorders[i].nMaxPos =
                ConvertPosPixel((*pColumnItem)[i].nEndMax + lAppNullOffset);
        }
		SetBorders(pColumnItem->Count()-1, pBorders);
	}
	else
	{
		SetBorders();
	}
}


void SvxRuler::UpdateObject()

/*
   [Beschreibung]

   Anzeige der Objektdarstellung aktualisieren

*/

{
	if(pObjectItem)
	{
		DBG_ASSERT(pObjectBorders, "kein Buffer");
		// !! zum Seitenrand
		long nMargin = pLRSpaceItem? pLRSpaceItem->GetLeft(): 0;
		pObjectBorders[0].nPos =
			ConvertPosPixel(pObjectItem->GetStartX() -
							nMargin + lAppNullOffset);
		pObjectBorders[1].nPos =
			ConvertPosPixel(pObjectItem->GetEndX() - nMargin + lAppNullOffset);
		nMargin = pULSpaceItem? pULSpaceItem->GetUpper(): 0;
		pObjectBorders[2].nPos =
			ConvertPosPixel(pObjectItem->GetStartY() -
							nMargin + lAppNullOffset);
		pObjectBorders[3].nPos =
			ConvertPosPixel(pObjectItem->GetEndY() - nMargin + lAppNullOffset);

		const USHORT nOff = GetObjectBordersOff(0);
		SetBorders(2, pObjectBorders + nOff);
	}
	else
	{
		SetBorders();
	}
}


void SvxRuler::UpdatePara()

/*
   [Beschreibung]

   Anzeige der Absatzeinzuege aktualisieren:
   Linken Rand, Erstzeileneinzug, rechten Rand Absatz aktualisieren
   pIndents[0] = Buffer fuer alten Einzug
   pIndents[1] = Buffer fuer alten Einzug
   pIndents[INDENT_FIRST_LINE] = Erstzeileneinzug
   pIndents[3] = linker Rand
   pIndents[4] = rechter Rand
   pIndents[5] = left border distance
   pIndents[6] = right border distance

*/

{
	// Abhaengigkeit zu PagePosItem
	if(pParaItem && pPagePosItem && !pObjectItem)
	{
        BOOL bRTLText = pRuler_Imp->pTextRTLItem && pRuler_Imp->pTextRTLItem->GetValue();
        // Erstzeileneinzug, ist negativ zum linken Absatzrand
        long nLeftFrameMargin = GetLeftFrameMargin();
        long nRightFrameMargin = GetRightFrameMargin();
        if(bRTLText)
            pIndents[INDENT_FIRST_LINE].nPos =
                ConvertHPosPixel(
                nRightFrameMargin -
                pParaItem->GetTxtLeft() -
				pParaItem->GetTxtFirstLineOfst() + lAppNullOffset );
        else
            pIndents[INDENT_FIRST_LINE].nPos =
                ConvertHPosPixel(
                    nLeftFrameMargin +
                    pParaItem->GetTxtLeft() +
                    pParaItem->GetTxtFirstLineOfst() +
                    lAppNullOffset);
		if( pParaItem->IsAutoFirst() )
            pIndents[INDENT_FIRST_LINE].nStyle |= RULER_STYLE_INVISIBLE;
		else
            pIndents[INDENT_FIRST_LINE].nStyle &= ~RULER_STYLE_INVISIBLE;

        if(bRTLText)
        {
            // left margin
            pIndents[INDENT_LEFT_MARGIN].nPos =
                ConvertHPosPixel(
                    nRightFrameMargin -
                    pParaItem->GetTxtLeft() + lAppNullOffset);
            // right margin
            pIndents[INDENT_RIGHT_MARGIN].nPos =
                ConvertHPosPixel(
                    nLeftFrameMargin +
                    pParaItem->GetRight() + lAppNullOffset);
        }
        else
        {
            // linker Rand
            pIndents[INDENT_LEFT_MARGIN].nPos =
                ConvertHPosPixel(
                    nLeftFrameMargin +
                    pParaItem->GetTxtLeft() + lAppNullOffset);
            // rechter Rand, immer negativ zum rechten Rand des umgebenden Frames
            pIndents[INDENT_RIGHT_MARGIN].nPos =
                ConvertHPosPixel(
                    nRightFrameMargin -
                    pParaItem->GetRight() + lAppNullOffset);
        }
        if(pParaBorderItem)
        {
            pIndents[INDENT_LEFT_BORDER].nPos =
            ConvertHPosPixel( nLeftFrameMargin + lAppNullOffset);
            pIndents[INDENT_RIGHT_BORDER].nPos =
                ConvertHPosPixel(nRightFrameMargin - lAppNullOffset);
            pIndents[INDENT_LEFT_BORDER].nStyle = pIndents[INDENT_RIGHT_BORDER].nStyle &= ~RULER_STYLE_INVISIBLE;
        }
        else
            pIndents[INDENT_LEFT_BORDER].nStyle = pIndents[INDENT_RIGHT_BORDER].nStyle |= RULER_STYLE_INVISIBLE;

        SetIndents(INDENT_COUNT, pIndents+INDENT_GAP);
	}
	else
	{
		if(pIndents)
		{
            pIndents[INDENT_FIRST_LINE].nPos =
            pIndents[INDENT_LEFT_MARGIN].nPos =
            pIndents[INDENT_RIGHT_MARGIN].nPos = 0;
		}
		SetIndents();        // ausschalten
	}
}


void SvxRuler::UpdatePara
(
 const SvxLRSpaceItem *pItem    // neuer Wert Absatzeinzuege
)

/*
   [Beschreibung]

   Neuen Wert Absatzeinzuege merken
*/

{
	if(bActive)
	{
		delete pParaItem; pParaItem = 0;
		if(pItem)
			pParaItem = new SvxLRSpaceItem(*pItem);
        StartListening_Impl();
    }
}
void SvxRuler::UpdateParaBorder(const SvxLRSpaceItem * pItem )
/*
   [Description]
   Border distance
*/

{
	if(bActive)
	{
        delete pParaBorderItem; pParaBorderItem = 0;
		if(pItem)
            pParaBorderItem = new SvxLRSpaceItem(*pItem);
        StartListening_Impl();
    }
}


void SvxRuler::UpdatePage()

/*
   [Beschreibung]

   Anzeige von Postion und Breite der Seite aktualisieren

*/

{
	if(pPagePosItem)
	{
		// alle Objekte werden automatisch angepasst
		if(bHorz)
			SetPagePos(
				pEditWin->LogicToPixel(pPagePosItem->GetPos()).X(),
				pEditWin->LogicToPixel(Size(pPagePosItem->GetWidth(),0)).
				Width());
		else
			SetPagePos(
				pEditWin->LogicToPixel(pPagePosItem->GetPos()).Y(),
				pEditWin->LogicToPixel(Size(0, pPagePosItem->GetHeight())).
				Height());
		if(bAppSetNullOffset)
			SetNullOffset(ConvertSizePixel(-lAppNullOffset + lLogicNullOffset));
	}
	else
		SetPagePos();

	long lPos = 0;
    Point aOwnPos = GetPosPixel();
    Point aEdtWinPos = pEditWin->GetPosPixel();
    if( Application::GetSettings().GetLayoutRTL() && bHorz )
    {
        //#i73321# in RTL the window and the ruler is not mirrored but the 
        // influence of the vertical ruler is inverted
        Size aOwnSize = GetSizePixel();
        Size aEdtWinSize = pEditWin->GetSizePixel();
        lPos = aOwnSize.Width() - aEdtWinSize.Width();
        lPos -= (aEdtWinPos - aOwnPos).X();
    }
    else
    {
        Point aPos(aEdtWinPos - aOwnPos);
	    lPos= bHorz ? aPos.X() : aPos.Y();
    }

// Leider bekommen wir den Offset des Editfensters zum Lineal nie
// per Statusmeldung. Also setzen wir ihn selbst, wenn noetig.

	if(lPos!=pRuler_Imp->lOldWinPos)
	{
		pRuler_Imp->lOldWinPos=lPos;
		SetWinPos(lPos);
	}
}


void SvxRuler::Update
(
 const SvxPagePosSizeItem *pItem // neuer Wert Seitenattribute
)

/*
   [Beschreibung]

   Neuen Wert Seitenattribute merken

*/

{
	if(bActive)
	{
		delete pPagePosItem; pPagePosItem = 0;
		if(pItem)
			pPagePosItem = new SvxPagePosSizeItem(*pItem);
        StartListening_Impl();
    }
}


//

void SvxRuler::SetDefTabDist
(
 long l                                                 // Neuer Abstand fuer DefaultTabs in App-Metrik
)

/*
   [Beschreibung]

   Neuer Abstand fuer DefaultTabs wird gesetzt

*/

{

	lDefTabDist = l;
	UpdateTabs();
}


long SvxRuler::GetDefTabDist() const

/*
   [Beschreibung]

   Wert fuer DefaultTabs erfragen (wird in App.-Methik geliefert)

*/

{
	return lDefTabDist;
}


USHORT ToSvTab_Impl(SvxTabAdjust eAdj)

/*
   [Beschreibung]

   Interne Konvertierungsroutinen zwischen SV-Tab.-Enum und Svx

*/

{
	switch(eAdj) {
	case SVX_TAB_ADJUST_LEFT:    return RULER_TAB_LEFT;
	case SVX_TAB_ADJUST_RIGHT:   return RULER_TAB_RIGHT;
	case SVX_TAB_ADJUST_DECIMAL: return RULER_TAB_DECIMAL;
	case SVX_TAB_ADJUST_CENTER:  return RULER_TAB_CENTER;
	case SVX_TAB_ADJUST_DEFAULT: return RULER_TAB_DEFAULT;
    default: ;//prevent warning
	}
	return 0;
}


SvxTabAdjust ToAttrTab_Impl(USHORT eAdj)
{
	switch(eAdj) {
	case RULER_TAB_LEFT:    return SVX_TAB_ADJUST_LEFT    ;
	case RULER_TAB_RIGHT:   return SVX_TAB_ADJUST_RIGHT   ;
	case RULER_TAB_DECIMAL: return SVX_TAB_ADJUST_DECIMAL ;
	case RULER_TAB_CENTER:  return SVX_TAB_ADJUST_CENTER  ;
	case RULER_TAB_DEFAULT: return SVX_TAB_ADJUST_DEFAULT ;
	}
	return SVX_TAB_ADJUST_LEFT;
}


void SvxRuler::UpdateTabs()

/*
   [Beschreibung]

   Anzeige der Tabulatoren

*/

{
	if(IsDrag())
		return;
	if(pPagePosItem && pParaItem && pTabStopItem && !pObjectItem)
	{
		// Puffer fuer DefaultTabStop
		// Abstand letzter Tab <-> Rechter Absatzrand / DefaultTabDist
		BOOL bRTL = pRuler_Imp->pTextRTLItem && pRuler_Imp->pTextRTLItem->GetValue();
        long nLeftFrameMargin = GetLeftFrameMargin();
        long nRightFrameMargin = GetRightFrameMargin();

    //#i24363# tab stops relative to indent
        const long nParaItemTxtLeft = pRuler_Imp->bIsTabsRelativeToIndent ?
                                      pParaItem->GetTxtLeft() :
                                      0;

        const long lParaIndent = nLeftFrameMargin + nParaItemTxtLeft;

		const long lLastTab =
			 pTabStopItem->Count()?
			  ConvertHPosPixel((*pTabStopItem)[pTabStopItem->Count()-1].GetTabPos()): 0;
		const long lPosPixel =
			ConvertHPosPixel(lParaIndent) + lLastTab;
		const long lRightIndent =
			ConvertHPosPixel(nRightFrameMargin - pParaItem->GetRight());
		long nDefTabDist = ConvertHPosPixel(lDefTabDist);
		if( !nDefTabDist )
			nDefTabDist = 1;
		const USHORT nDefTabBuf = lPosPixel > lRightIndent ||
			lLastTab > lRightIndent
				? 0
				: (USHORT)( (lRightIndent - lPosPixel) / nDefTabDist );

		if(pTabStopItem->Count() + TAB_GAP + nDefTabBuf > nTabBufSize)
		{
			delete[] pTabs;
			// 10 (GAP) auf Vorrat
			nTabBufSize = pTabStopItem->Count() + TAB_GAP + nDefTabBuf + GAP;
			pTabs = new RulerTab[nTabBufSize];
		}

		nTabCount = 0;
		USHORT j;
        //#i24363# tab stops relative to indent
        const long lRightPixMargin = ConvertSizePixel(nRightFrameMargin - nParaItemTxtLeft );
		const long lParaIndentPix = ConvertSizePixel(lParaIndent);
		for(j = 0; j < pTabStopItem->Count(); ++j)
		{
			const SvxTabStop *pTab = &(*pTabStopItem)[j];
			pTabs[nTabCount+TAB_GAP].nPos =
				ConvertHPosPixel(
					lParaIndent + pTab->GetTabPos() + lAppNullOffset);
			if(bRTL)
			{
				pTabs[nTabCount+TAB_GAP].nPos = lParaIndentPix + lRightPixMargin - pTabs[nTabCount+TAB_GAP].nPos;
			}
			pTabs[nTabCount+TAB_GAP].nStyle = ToSvTab_Impl(pTab->GetAdjustment());
			++nTabCount;
		}
		if(!pTabStopItem->Count())
			pTabs[0].nPos = bRTL ? lRightPixMargin : lParaIndentPix;

		// Rest mit Default-Tabs fuellen
		if(bRTL)
		{
			for(j = 0; j < nDefTabBuf; ++j)
			{
				pTabs[nTabCount + TAB_GAP].nPos =
					pTabs[nTabCount].nPos - nDefTabDist;

				if(j == 0 )
					pTabs[nTabCount + TAB_GAP].nPos -=
						((pTabs[nTabCount + TAB_GAP].nPos - lRightPixMargin)
						 % nDefTabDist );
				if(pTabs[nTabCount+TAB_GAP].nPos <= lParaIndentPix)
					break;
				pTabs[nTabCount + TAB_GAP].nStyle = RULER_TAB_DEFAULT;
				++nTabCount;
			}
		}
		else
		{
			for(j = 0; j < nDefTabBuf; ++j)
			{
				pTabs[nTabCount + TAB_GAP].nPos =
					pTabs[nTabCount].nPos + nDefTabDist;

				if(j == 0 )
					pTabs[nTabCount + TAB_GAP].nPos -=
						((pTabs[nTabCount + TAB_GAP].nPos - lParaIndentPix)
						 % nDefTabDist );
				if(pTabs[nTabCount+TAB_GAP].nPos >= lRightIndent)
					break;
				pTabs[nTabCount + TAB_GAP].nStyle = RULER_TAB_DEFAULT;
				++nTabCount;
			}
		}
		SetTabs(nTabCount, pTabs+TAB_GAP);
		DBG_ASSERT(nTabCount + TAB_GAP <= nTabBufSize, "BufferSize zu klein");
	}
	else
	{
		SetTabs();
	}
}


void SvxRuler::Update
(
 const SvxTabStopItem *pItem    // Neuer Wert fuer Tabulatoren
)

/*
   [Beschreibung]

   Neuen Wert fuer Tabulatoren merken; alten gfs. loeschen

*/

{
	if(bActive)
	{
		delete pTabStopItem; pTabStopItem = 0;
		if(pItem)
		{
			pTabStopItem = new SvxTabStopItem(*pItem);
			if(!bHorz)
				pTabStopItem->SetWhich(SID_ATTR_TABSTOP_VERTICAL);
		}
        StartListening_Impl();
    }
}


void SvxRuler::Update
(
 const SvxObjectItem *pItem             // Neuer Wert fuer Objekte
)

/*
   [Beschreibung]

   Neuen Wert fuer Objekte merken

*/

{
	if(bActive)
	{
		delete pObjectItem; pObjectItem = 0;
		if(pItem)
			pObjectItem = new SvxObjectItem(*pItem);
        StartListening_Impl();
	}
}


void SvxRuler::SetNullOffsetLogic
(
 long lVal                                              // Setzen des logischen NullOffsets
)
{
	lAppNullOffset = lLogicNullOffset - lVal;
	bAppSetNullOffset = TRUE;
	Ruler::SetNullOffset(ConvertSizePixel(lVal));
	Update();
}


void SvxRuler::Update()

/*
   [Beschreibung]

   Aktualisierung der Anzeige anstossen

*/

{
	if(IsDrag())
		return;
	UpdatePage();
	UpdateFrame();
	if((nFlags & SVXRULER_SUPPORT_OBJECT) == SVXRULER_SUPPORT_OBJECT)
		UpdateObject();
	else
		UpdateColumns();

    if(0 != (nFlags & (SVXRULER_SUPPORT_PARAGRAPH_MARGINS |SVXRULER_SUPPORT_PARAGRAPH_MARGINS_VERTICAL)))
	  UpdatePara();
    if(0 != (nFlags & SVXRULER_SUPPORT_TABS))
      UpdateTabs();
}


inline long SvxRuler::GetPageWidth() const
{
	return bHorz ? pPagePosItem->GetWidth() : pPagePosItem->GetHeight();

}


inline long SvxRuler::GetFrameLeft() const

/*
   [Beschreibung]

   Erfragen des linken Randes in Pixeln

*/


{
	return  bAppSetNullOffset?
			GetMargin1() + ConvertSizePixel(lLogicNullOffset):
			Ruler::GetNullOffset();
}

inline void SvxRuler::SetFrameLeft(long l)

/*
   [Beschreibung]

   Setzen des linken Randes in Pixeln

*/

{
	BOOL bProtectColumns =
		pRuler_Imp->aProtectItem.IsSizeProtected() ||
		pRuler_Imp->aProtectItem.IsPosProtected();
	if(bAppSetNullOffset)
		SetMargin1(l - ConvertSizePixel(lLogicNullOffset),
				   bProtectColumns ? 0 : RULER_MARGIN_SIZEABLE);
	else
		Ruler::SetNullOffset(l);
}


long SvxRuler::GetFirstLineIndent() const

/*
   [Beschreibung]

   Erstzeileneinzug in Pixels erfragen
*/

{
    return pParaItem? pIndents[INDENT_FIRST_LINE].nPos: GetMargin1();
}


long SvxRuler::GetLeftIndent() const

/*
   [Beschreibung]

   Linken Absatzrand in Pixels erfragen
*/

{
    return pParaItem? pIndents[INDENT_LEFT_MARGIN].nPos: GetMargin1();
}



long SvxRuler::GetRightIndent() const

/*
   [Beschreibung]

   Rechten Absatzrand in Pixels erfragen
*/

{
    return pParaItem? pIndents[INDENT_RIGHT_MARGIN].nPos: GetMargin2();
}


long SvxRuler::GetLogicRightIndent() const

/*
   [Beschreibung]

   Rechten Absatzrand in Logic erfragen
*/

{
	return pParaItem ? GetRightFrameMargin()-pParaItem->GetRight() : GetRightFrameMargin();
}

// linker Rand in App-Werten; ist entweder der Seitenrand (=0)
// oder der linke Rand der Spalte, die im Spaltenattribut als
// altuelle Spalte eingestellt ist.

long SvxRuler::GetLeftFrameMargin() const
{
    // #126721# for some unknown reason the current column is set to 0xffff
    DBG_ASSERT(!pColumnItem || pColumnItem->GetActColumn() < pColumnItem->Count(),
                    "issue #126721# - invalid current column!");
    long nLeft =
        pColumnItem && pColumnItem->Count() && pColumnItem->GetActColumn() < pColumnItem->Count() ?
        (*pColumnItem)[pColumnItem->GetActColumn()].nStart : 0;
    if(pParaBorderItem && (!pColumnItem || pColumnItem->IsTable()))
        nLeft += pParaBorderItem->GetLeft();
    return nLeft;
}

inline long SvxRuler::GetLeftMin() const
{
	DBG_ASSERT(pMinMaxItem, "kein MinMax-Wert gesetzt");
	return pMinMaxItem?
		bHorz? 	pMinMaxItem->GetValue().Left(): pMinMaxItem->GetValue().Top()
				: 0;
}

inline long SvxRuler::GetRightMax() const
{
	DBG_ASSERT(pMinMaxItem, "kein MinMax-Wert gesetzt");
	return pMinMaxItem?
		bHorz? pMinMaxItem->GetValue().Right(): pMinMaxItem->GetValue().Bottom()
			: 0;
}


long SvxRuler::GetRightFrameMargin() const

/*
   [Beschreibung]

   Rechten umgebenden Rand erfragen (in logischen Einheiten)

*/

{
	if(pColumnItem)
	{
		if(!IsActLastColumn( TRUE ))
		{
			long nRet = (*pColumnItem)[GetActRightColumn( TRUE )].nEnd;
			if(pColumnItem->IsTable() && pParaBorderItem)
				nRet -= pParaBorderItem->GetRight();
			return nRet;
		}
	}

	long l = lLogicNullOffset;

	// gfs. rechten Tabelleneinzug abziehen
	if(pColumnItem && pColumnItem->IsTable())
		l += pColumnItem->GetRight();
    else if(bHorz && pLRSpaceItem)
		l += pLRSpaceItem->GetRight();
    else if(!bHorz && pULSpaceItem)
        l += pULSpaceItem->GetLower();

    if(pParaBorderItem &&
        (!pColumnItem || pColumnItem->IsTable()||IsActLastColumn( TRUE )))
        l += pParaBorderItem->GetRight();

    if(bHorz)
        l = pPagePosItem->GetWidth() - l;
	else
        l = pPagePosItem->GetHeight() - l;
    return l;
}

#define NEG_FLAG ( (nFlags & SVXRULER_SUPPORT_NEGATIVE_MARGINS) == \
				   SVXRULER_SUPPORT_NEGATIVE_MARGINS )
#define TAB_FLAG ( pColumnItem && pColumnItem->IsTable() )

long SvxRuler::GetCorrectedDragPos( BOOL bLeft, BOOL bRight )

/*
   [Beschreibung]

   Korrigiert die Position innerhalb der errechneten Grenzwerte.
   Die Grenzwerte sind in Pixel relativ zum Seitenrand.

*/

{
	const long lNullPix = Ruler::GetNullOffset();
	long lDragPos = GetDragPos() + lNullPix;
ADD_DEBUG_TEXT("lDragPos: ", String::CreateFromInt32(lDragPos))
 	BOOL bHoriRows = bHorz && pRuler_Imp->bIsTableRows;
	if((bLeft || (bHoriRows)) && lDragPos < nMaxLeft)
		lDragPos = nMaxLeft;
	else if((bRight||bHoriRows) && lDragPos > nMaxRight)
		lDragPos = nMaxRight;
	return lDragPos - lNullPix;
}



void ModifyTabs_Impl
(
 USHORT nCount,                                 // Anzahl Tabs
 RulerTab *pTabs,                               // Tab-Puffer
 long lDiff                                     // zu addierende Differenz
 )

/*
   [Beschreibung]

   Hilfsroutine; alle Tabs um einen festen Wert verschieben

*/
{
	if( pTabs )
		for(USHORT i = 0; i < nCount; ++i)	pTabs[i].nPos += lDiff;
}



void SvxRuler::DragMargin1()

/*
   [Beschreibung]

   Draggen des linken Frame-Randes

*/
{
	const long lDragPos = GetCorrectedDragPos( !TAB_FLAG || !NEG_FLAG, TRUE );
	DrawLine_Impl(lTabPos, ( TAB_FLAG && NEG_FLAG ) ? 3 : 7, bHorz);
    if(pColumnItem&&
	   (//nDragType & DRAG_OBJECT_SIZE_LINEAR ||
		nDragType & DRAG_OBJECT_SIZE_PROPORTIONAL))
		DragBorders();
    AdjustMargin1(lDragPos);
}
void SvxRuler::AdjustMargin1(long lDiff)
{
    const long nOld = bAppSetNullOffset? GetMargin1(): GetNullOffset();
    const long lDragPos = lDiff;
    BOOL bProtectColumns =
		pRuler_Imp->aProtectItem.IsSizeProtected() ||
		pRuler_Imp->aProtectItem.IsPosProtected();

	const USHORT nMarginStyle =
		bProtectColumns ? 0 : RULER_MARGIN_SIZEABLE;

	if(!bAppSetNullOffset)
	{
        long _lDiff = lDragPos;
        SetNullOffset(nOld + _lDiff);
		if(!pColumnItem||!(nDragType & DRAG_OBJECT_SIZE_LINEAR))
		{
            SetMargin2( GetMargin2() - _lDiff, nMarginStyle );

			if(!pColumnItem && !pObjectItem && pParaItem)
			{
				// Rechten Einzug an alter Position
                pIndents[INDENT_RIGHT_MARGIN].nPos -= _lDiff;
                SetIndents(INDENT_COUNT, pIndents+INDENT_GAP);
			}
			if(pObjectItem)
			{
                pObjectBorders[GetObjectBordersOff(0)].nPos -= _lDiff;
                pObjectBorders[GetObjectBordersOff(1)].nPos -= _lDiff;
				SetBorders(2, pObjectBorders + GetObjectBordersOff(0));
			}
			if(pColumnItem)
			{
				for(USHORT i = 0; i < pColumnItem->Count()-1; ++i)
                    pBorders[i].nPos -= _lDiff;
				SetBorders(pColumnItem->Count()-1, pBorders);
				if(pColumnItem->IsFirstAct())
				{
					// Rechten Einzug an alter Position
					if(pParaItem)
					{
                        pIndents[INDENT_RIGHT_MARGIN].nPos -= _lDiff;
                        SetIndents(INDENT_COUNT, pIndents+INDENT_GAP);
					}
				}
				else
				{
					if(pParaItem)
					{
                        pIndents[INDENT_FIRST_LINE].nPos -= _lDiff;
                        pIndents[INDENT_LEFT_MARGIN].nPos -= _lDiff;
                        pIndents[INDENT_RIGHT_MARGIN].nPos -= _lDiff;
                        SetIndents(INDENT_COUNT, pIndents+INDENT_GAP);
					}
				}
				if(pTabStopItem&& (nDragType & DRAG_OBJECT_SIZE_PROPORTIONAL)
				   &&!IsActFirstColumn())
				{
                    ModifyTabs_Impl(nTabCount+TAB_GAP, pTabs, -_lDiff);
					SetTabs(nTabCount, pTabs+TAB_GAP);
				}
			}
		}
	}
	else
	{
        long _lDiff = lDragPos - nOld;
        SetMargin1(nOld + _lDiff, nMarginStyle );

		if(!pColumnItem||!(nDragType & (DRAG_OBJECT_SIZE_LINEAR |
										DRAG_OBJECT_SIZE_PROPORTIONAL)))
		{
			if(!pColumnItem && !pObjectItem && pParaItem)
			{
				// Linke Einzuege an alter Position
                pIndents[INDENT_FIRST_LINE].nPos += _lDiff;
                pIndents[INDENT_LEFT_MARGIN].nPos += _lDiff;
                SetIndents(INDENT_COUNT, pIndents+INDENT_GAP);
			}

			if(pColumnItem)
			{
				for(USHORT i = 0; i < pColumnItem->Count()-1; ++i)
                    pBorders[i].nPos += _lDiff;
				SetBorders(pColumnItem->Count()-1, pBorders);
				if(pColumnItem->IsFirstAct())
				{
					// Linke Einzuege an alter Position
					if(pParaItem)
					{
                        pIndents[INDENT_FIRST_LINE].nPos += _lDiff;
                        pIndents[INDENT_LEFT_MARGIN].nPos += _lDiff;
                        SetIndents(INDENT_COUNT, pIndents+INDENT_GAP);
					}
				}
				else
				{
					if(pParaItem)
					{
                        pIndents[INDENT_FIRST_LINE].nPos += _lDiff;
                        pIndents[INDENT_LEFT_MARGIN].nPos += _lDiff;
                        pIndents[INDENT_RIGHT_MARGIN].nPos += _lDiff;
                        SetIndents(INDENT_COUNT, pIndents+INDENT_GAP);
					}
				}
			}
			if(pTabStopItem)
			{
                ModifyTabs_Impl(nTabCount+TAB_GAP, pTabs, _lDiff);
				SetTabs(nTabCount, pTabs+TAB_GAP);
			}
		}
	}
}


void SvxRuler::DragMargin2()
/*
   [Beschreibung]

   Draggen des rechten Frame-Randes

*/
{
	const long lDragPos = GetCorrectedDragPos( TRUE, !TAB_FLAG || !NEG_FLAG);
	DrawLine_Impl(lTabPos, ( TAB_FLAG && NEG_FLAG ) ? 5 : 7, bHorz);
	long lDiff = lDragPos - GetMargin2();

	if(pRuler_Imp->bIsTableRows && !bHorz && pColumnItem&&
	   (//nDragType & DRAG_OBJECT_SIZE_LINEAR ||
		nDragType & DRAG_OBJECT_SIZE_PROPORTIONAL))
		DragBorders();

	BOOL bProtectColumns =
		pRuler_Imp->aProtectItem.IsSizeProtected() ||
		pRuler_Imp->aProtectItem.IsPosProtected();
	const USHORT nMarginStyle =
		bProtectColumns ? 0 : RULER_MARGIN_SIZEABLE;
	SetMargin2( lDragPos, nMarginStyle );

	// Rechten Einzug an alter Position
	if((!pColumnItem || IsActLastColumn()) && pParaItem)
	{
        pIndents[INDENT_FIRST_LINE].nPos += lDiff;
        SetIndents(INDENT_COUNT, pIndents+INDENT_GAP);
	}
}


void SvxRuler::DragIndents()
/*
   [Beschreibung]

   Draggen der Absatzeinzuege

*/
{
	const long lDragPos = NEG_FLAG ? GetDragPos() : GetCorrectedDragPos();
	const USHORT nIdx = GetDragAryPos()+INDENT_GAP;
	const long lDiff = pIndents[nIdx].nPos - lDragPos;

	if((nIdx == INDENT_FIRST_LINE ||
            nIdx == INDENT_LEFT_MARGIN )  &&
		(nDragType & DRAG_OBJECT_LEFT_INDENT_ONLY) !=
        DRAG_OBJECT_LEFT_INDENT_ONLY)
        pIndents[INDENT_FIRST_LINE].nPos -= lDiff;

	pIndents[nIdx].nPos = lDragPos;

    SetIndents(INDENT_COUNT, pIndents + INDENT_GAP);
	DrawLine_Impl(lTabPos, 1, bHorz);
}


void SvxRuler::DrawLine_Impl(long &_lTabPos, int nNew, BOOL Hori)
/*
   [Beschreibung]

   Ausgaberoutine fuer Hilfslinie beim Vereschieben von Tabs, Tabellen-
   und anderen Spalten

*/
{
	if(Hori)
	{
		const long nHeight = pEditWin->GetOutputSize().Height();
		Point aZero=pEditWin->GetMapMode().GetOrigin();
        if(_lTabPos!=-1)
			pEditWin->InvertTracking(
                Rectangle( Point(_lTabPos, -aZero.Y()),
                           Point(_lTabPos, -aZero.Y()+nHeight)),
				SHOWTRACK_SPLIT | SHOWTRACK_CLIP );
		if( nNew & 1 )
		{

            _lTabPos = ConvertHSizeLogic(
                GetCorrectedDragPos( ( nNew&4 ) != 0, ( nNew&2 ) != 0 ) +
                GetNullOffset() );
			if(pPagePosItem)
                _lTabPos += pPagePosItem->GetPos().X();
			pEditWin->InvertTracking(
                Rectangle(Point(_lTabPos, -aZero.Y()),
                          Point(_lTabPos, -aZero.Y()+nHeight)),
				SHOWTRACK_CLIP | SHOWTRACK_SPLIT );
		}
	}
	else
	{
		const long nWidth = pEditWin->GetOutputSize().Width();
		Point aZero=pEditWin->GetMapMode().GetOrigin();
        if(_lTabPos != -1)
		{
			pEditWin->InvertTracking(
                Rectangle( Point(-aZero.X(), _lTabPos),
                           Point(-aZero.X()+nWidth, _lTabPos)),
				SHOWTRACK_SPLIT | SHOWTRACK_CLIP );
		}

		if(nNew & 1)
		{
            _lTabPos = ConvertVSizeLogic(GetCorrectedDragPos()+GetNullOffset());
			if(pPagePosItem)
                _lTabPos += pPagePosItem->GetPos().Y();
			pEditWin->InvertTracking(
                Rectangle( Point(-aZero.X(), _lTabPos),
                           Point(-aZero.X()+nWidth, _lTabPos)),
				SHOWTRACK_CLIP | SHOWTRACK_SPLIT );
		}
	}
}




void SvxRuler::DragTabs()

/*
   [Beschreibung]

   Draggen von Tabs

*/
{

	long lDragPos = GetCorrectedDragPos(TRUE, FALSE);

	USHORT nIdx = GetDragAryPos()+TAB_GAP;
	DrawLine_Impl(lTabPos, 7, bHorz);

	long nDiff = lDragPos - pTabs[nIdx].nPos;

	if(nDragType & DRAG_OBJECT_SIZE_LINEAR)
	{

		for(USHORT i = nIdx; i < nTabCount; ++i)
		{
			pTabs[i].nPos += nDiff;
			// auf Maximum begrenzen
			if(pTabs[i].nPos > GetMargin2())
				pTabs[nIdx].nStyle |= RULER_STYLE_INVISIBLE;
			else
				pTabs[nIdx].nStyle &= ~RULER_STYLE_INVISIBLE;
		}
	}
	else if(nDragType & DRAG_OBJECT_SIZE_PROPORTIONAL)
	{
		pRuler_Imp->nTotalDist -= nDiff;
		pTabs[nIdx].nPos = lDragPos;
		for(USHORT i = nIdx+1; i < nTabCount; ++i)
		{
			if(pTabs[i].nStyle & RULER_TAB_DEFAULT)
				// bei den DefaultTabs kann abgebrochen werden
				break;
			long nDelta = pRuler_Imp->nTotalDist * pRuler_Imp->pPercBuf[i];
			nDelta /= 1000;
			pTabs[i].nPos = pTabs[nIdx].nPos + nDelta;
			if(pTabs[i].nPos+GetNullOffset() > nMaxRight)
				pTabs[i].nStyle |= RULER_STYLE_INVISIBLE;
			else
				pTabs[i].nStyle &= ~RULER_STYLE_INVISIBLE;
		}
	}
	else
		pTabs[nIdx].nPos = lDragPos;

	if(IsDragDelete())
		pTabs[nIdx].nStyle |= RULER_STYLE_INVISIBLE;
	else
		pTabs[nIdx].nStyle &= ~RULER_STYLE_INVISIBLE;
	SetTabs(nTabCount, pTabs+TAB_GAP);
}



void SvxRuler::SetActive(BOOL bOn)
{
	if(bOn)
	{
		Activate();
/*		pBindings->Invalidate( SID_RULER_LR_MIN_MAX, TRUE, TRUE );
		pBindings->Update( SID_RULER_LR_MIN_MAX );
		pBindings->Invalidate( SID_ATTR_LONG_ULSPACE, TRUE, TRUE );
		pBindings->Update( SID_ATTR_LONG_ULSPACE );
		pBindings->Invalidate( SID_ATTR_LONG_LRSPACE, TRUE, TRUE );
		pBindings->Update( SID_ATTR_LONG_LRSPACE );
		pBindings->Invalidate( SID_RULER_PAGE_POS, TRUE, TRUE );
		pBindings->Update( SID_RULER_PAGE_POS );
		pBindings->Invalidate( SID_ATTR_TABSTOP, TRUE, TRUE );
		pBindings->Update( SID_ATTR_TABSTOP );
		pBindings->Invalidate( SID_ATTR_PARA_LRSPACE, TRUE, TRUE );
		pBindings->Update( SID_ATTR_PARA_LRSPACE );
		pBindings->Invalidate( SID_RULER_BORDERS, TRUE, TRUE );
		pBindings->Update( SID_RULER_BORDERS );
		pBindings->Invalidate( SID_RULER_OBJECT, TRUE, TRUE );
		pBindings->Update( SID_RULER_OBJECT );
		pBindings->Invalidate( SID_RULER_PROTECT, TRUE, TRUE );
		pBindings->Update( SID_RULER_PROTECT );*/
	}
	else
		Deactivate();
	if(bActive!=bOn)
	{
		pBindings->EnterRegistrations();
		if(bOn)
			for(USHORT i=0;i<pRuler_Imp->nControlerItems;i++)
				pCtrlItem[i]->ReBind();
		else
			for(USHORT j=0;j<pRuler_Imp->nControlerItems;j++)
				pCtrlItem[j]->UnBind();
		pBindings->LeaveRegistrations();
	}
	bActive = bOn;
}




void SvxRuler::UpdateParaContents_Impl
(
 long l,                                                // Differenz
 UpdateType eType                               // Art (alle, links oder rechts)
)

/*
   [Beschreibung]

   Hilfsroutine; Mitfuehren von Tabulatoren und Absatzraendern

*/
{
	switch(eType) {
	case MOVE_RIGHT:
        pIndents[INDENT_RIGHT_MARGIN].nPos += l;
		break;
	case MOVE_ALL:
        pIndents[INDENT_RIGHT_MARGIN].nPos += l;
		// no break
	case MOVE_LEFT:
		{
            pIndents[INDENT_FIRST_LINE].nPos += l;
            pIndents[INDENT_LEFT_MARGIN].nPos += l;
			if ( pTabs )
			{
				for(USHORT i = 0; i < nTabCount+TAB_GAP;++i)
					pTabs[i].nPos += l;
				SetTabs(nTabCount, pTabs+TAB_GAP);
			}
			break;
		}
	}
    SetIndents(INDENT_COUNT, pIndents+INDENT_GAP);
}



void SvxRuler::DragBorders()

/*
   [Beschreibung]

   Draggen von Borders (Tabellen- und anderen Spalten)

*/
{
	BOOL bLeftIndentsCorrected = FALSE, bRightIndentsCorrected = FALSE;
	int nIdx;

	if(GetDragType()==RULER_TYPE_BORDER)
	{
		DrawLine_Impl(lTabPos, 7, bHorz);
		nIdx = GetDragAryPos();
	}
	else
		nIdx=0;

	USHORT nDragSize = GetDragSize();
	long lDiff = 0;

	// the drag position has to be corrected to be able to prevent borders from passing each other
	long lPos = GetCorrectedDragPos();


	switch(nDragSize)
	{
	  case RULER_DRAGSIZE_MOVE:
		{
ADD_DEBUG_TEXT("lLastLMargin: ", String::CreateFromInt32(pRuler_Imp->lLastLMargin))
            lDiff = GetDragType()==RULER_TYPE_BORDER ?
				lPos-nDragOffset - pBorders[nIdx].nPos
				: GetDragType() == RULER_TYPE_MARGIN1 ? lPos - pRuler_Imp->lLastLMargin : lPos - pRuler_Imp->lLastRMargin;

//			pBorders[nIdx].nPos += lDiff;
//			lDiff = pBorders[nIdx].nPos - nOld;
			if(nDragType & DRAG_OBJECT_SIZE_LINEAR)
			{
				long nRight = GetMargin2()-lMinFrame; // rechter Begrenzer
				for(int i = nBorderCount-2; i >= nIdx; --i)
				{
					long l = pBorders[i].nPos;
					pBorders[i].nPos += lDiff;
					pBorders[i].nPos = Min(pBorders[i].nPos, nRight - pBorders[i].nWidth);
					nRight = pBorders[i].nPos - lMinFrame;
					// RR der Spalte aktualisieren
					if(i == GetActRightColumn())
					{
						UpdateParaContents_Impl(pBorders[i].nPos - l, MOVE_RIGHT);
						bRightIndentsCorrected = TRUE;
					}
					// LAR, EZE der Spalte aktualisieren
					else if(i == GetActLeftColumn())
					{
						UpdateParaContents_Impl(pBorders[i].nPos - l, MOVE_LEFT);
						bLeftIndentsCorrected = TRUE;
					}
				}
			}
			else if(nDragType & DRAG_OBJECT_SIZE_PROPORTIONAL)
			{
				int nLimit;
				long lLeft;
				int nStartLimit = nBorderCount-2;
				switch(GetDragType())
				{
                default: ;//prevent warning
					DBG_ERROR("svx::SvxRuler::DragBorders(), unknown drag type!" );
				case RULER_TYPE_BORDER:
					if(pRuler_Imp->bIsTableRows)
					{
						pBorders[nIdx].nPos += lDiff;
						if(bHorz)
						{
							lLeft = pBorders[nIdx].nPos;
							pRuler_Imp->nTotalDist -= lDiff;
							nLimit=nIdx+1;
						}
						else
						{
							lLeft = 0;
							nStartLimit = nIdx - 1;
							pRuler_Imp->nTotalDist += lDiff;
							nLimit = 0;
						}
					}
					else
					{
						nLimit=nIdx+1;
						pBorders[nIdx].nPos += lDiff;
						lLeft = pBorders[nIdx].nPos;
						pRuler_Imp->nTotalDist-=lDiff;
					}
				break;
				case RULER_TYPE_MARGIN1:
					nLimit=0;
					lLeft=pRuler_Imp->lLastLMargin+lDiff;
					pRuler_Imp->nTotalDist-=lDiff;
				break;
				case RULER_TYPE_MARGIN2:
					nLimit = 0;
					lLeft= 0;//pRuler_Imp->lLastRMargin + lDiff;
					nStartLimit = nBorderCount - 2;
					pRuler_Imp->nTotalDist += lDiff;
				break;
				}

				for(int i  = nStartLimit; i >= nLimit; --i)
				{

					long l = pBorders[i].nPos;
					pBorders[i].nPos=lLeft+
						(pRuler_Imp->nTotalDist*pRuler_Imp->pPercBuf[i])/1000+
							pRuler_Imp->pBlockBuf[i];

					// RR der Spalte aktualisieren
					if(!pRuler_Imp->bIsTableRows)
					{
						if(i == GetActRightColumn())
						{
							UpdateParaContents_Impl(pBorders[i].nPos - l, MOVE_RIGHT);
							bRightIndentsCorrected = TRUE;
						}
						// LAR, EZE der Spalte aktualisieren
						else if(i == GetActLeftColumn())
						{
							UpdateParaContents_Impl(pBorders[i].nPos - l, MOVE_LEFT);
							bLeftIndentsCorrected = TRUE;
						}
					}
				}
				if(pRuler_Imp->bIsTableRows)
				{
					//in vertical tables the left borders have to be moved
					if(bHorz)
					{
						for(int i  = 0; i < nIdx; ++i)
							pBorders[i].nPos += lDiff;
                        AdjustMargin1(lDiff);
					}
					else
					{
						//otherwise the right borders are moved
						for(int i  = pColumnItem->Count() - 1; i > nIdx; --i)
							pBorders[i].nPos += lDiff;
						SetMargin2( GetMargin2() + lDiff, 0 );
					}
				}
			}
            else if(pRuler_Imp->bIsTableRows)
            {
                //moving rows: if a row is resized all following rows
                //have to be moved by the same amount.
                //This includes the left border when the table is not limited
                //to a lower frame border.
                int nLimit;
                long lLeft;
                if(GetDragType()==RULER_TYPE_BORDER)
                {
                    nLimit=nIdx+1;
                    lLeft=(pBorders[nIdx].nPos+=lDiff);
                }
                else
                {
                    nLimit=0;
                    lLeft=pRuler_Imp->lLastLMargin+lDiff;
                }
				//in vertical tables the left borders have to be moved
				if(bHorz)
				{
					for(int i  = 0; i < nIdx; ++i)
					{
						pBorders[i].nPos += lDiff;
					}
                    AdjustMargin1(lDiff);
				}
				else
				{
					//otherwise the right borders are moved
					for(int i  = nBorderCount-2; i >= nLimit; --i)
					{
						pBorders[i].nPos += lDiff;
					}
					SetMargin2( GetMargin2() + lDiff, 0 );
				}
            }
			else
				pBorders[nIdx].nPos+=lDiff;
			break;
		}
	  case RULER_DRAGSIZE_1:
		{
			lDiff = lPos - pBorders[nIdx].nPos;
			pBorders[nIdx].nWidth += pBorders[nIdx].nPos - lPos;
			pBorders[nIdx].nPos = lPos;
			break;
		}
	  case RULER_DRAGSIZE_2:
		{
			const long nOld = pBorders[nIdx].nWidth;
			pBorders[nIdx].nWidth = lPos - pBorders[nIdx].nPos;
			lDiff = pBorders[nIdx].nWidth - nOld;
			break;
		}
	}
	if(!bRightIndentsCorrected &&
	   GetActRightColumn() == nIdx &&
	   nDragSize != RULER_DRAGSIZE_2 && pIndents &&
	   !pRuler_Imp->bIsTableRows)
	{
		UpdateParaContents_Impl(lDiff, MOVE_RIGHT);
	}
	else if(!bLeftIndentsCorrected &&
			GetActLeftColumn()==nIdx &&
			nDragSize != RULER_DRAGSIZE_1 && pIndents)
	{
		UpdateParaContents_Impl(lDiff, MOVE_LEFT);
	}
	SetBorders(pColumnItem->Count()-1, pBorders);
}


void SvxRuler::DragObjectBorder()

/*
   [Beschreibung]

   Draggen von Objektraendern

*/
{
	if(RULER_DRAGSIZE_MOVE == GetDragSize())
	{
		const long lPos = GetCorrectedDragPos();
		const USHORT nIdx = GetDragAryPos();
		pObjectBorders[GetObjectBordersOff(nIdx)].nPos = lPos;
		SetBorders(2, pObjectBorders + GetObjectBordersOff(0));
		DrawLine_Impl(lTabPos, 7, bHorz);

	}
}


void SvxRuler::ApplyMargins()
/*
   [Beschreibung]

   Anwenden von Randeinstellungen; durch Draggen veraendert.

*/
{
	const SfxPoolItem *pItem = 0;
	USHORT nId = SID_ATTR_LONG_LRSPACE;
	if(bHorz)
	{
		const long lOldNull = lLogicNullOffset;
		if(pRuler_Imp->lMaxLeftLogic!=-1&&nMaxLeft==GetMargin1()+Ruler::GetNullOffset())
			pLRSpaceItem->SetLeft(lLogicNullOffset=pRuler_Imp->lMaxLeftLogic);
		else
			pLRSpaceItem->SetLeft(PixelHAdjust(
				lLogicNullOffset =	ConvertHPosLogic(GetFrameLeft()) -
				lAppNullOffset,	pLRSpaceItem->GetLeft()));

		if(bAppSetNullOffset)
			lAppNullOffset += lLogicNullOffset - lOldNull;

		if(pRuler_Imp->lMaxRightLogic!=-1
		   &&nMaxRight==GetMargin2()+Ruler::GetNullOffset())
			pLRSpaceItem->SetRight(GetPageWidth()-pRuler_Imp->lMaxRightLogic);
		else
			pLRSpaceItem->SetRight(
				PixelHAdjust(
					Max((long)0,pPagePosItem->GetWidth() -
						pLRSpaceItem->GetLeft() -
						(ConvertHPosLogic(GetMargin2()) -
						 lAppNullOffset)),pLRSpaceItem->GetRight()));
		pItem = pLRSpaceItem;
#ifdef DEBUGLIN
		Debug_Impl(pEditWin,*pLRSpaceItem);
#endif // DEBUGLIN
	}
	else {
		const long lOldNull = lLogicNullOffset;
		pULSpaceItem->SetUpper(
			PixelVAdjust(
				lLogicNullOffset =
				ConvertVPosLogic(GetFrameLeft()) -
				lAppNullOffset,pULSpaceItem->GetUpper()));
		if(bAppSetNullOffset)
			lAppNullOffset += lLogicNullOffset - lOldNull;
		pULSpaceItem->SetLower(
			PixelVAdjust(
				Max((long)0, pPagePosItem->GetHeight() -
					pULSpaceItem->GetUpper() -
					(ConvertVPosLogic(GetMargin2()) -
					 lAppNullOffset)),pULSpaceItem->GetLower()));
		pItem = pULSpaceItem;
		nId = SID_ATTR_LONG_ULSPACE;
#ifdef DEBUGLIN
		Debug_Impl(pEditWin,*pULSpaceItem);
#endif // DEBUGLIN
	}
	pBindings->GetDispatcher()->Execute( nId, SFX_CALLMODE_RECORD, pItem, 0L );
	if(pTabStopItem)
		UpdateTabs();
}


void SvxRuler::ApplyIndents()
/*
   [Beschreibung]

   Anwenden von Absatzeinstellungen; durch Draggen veraendert.

*/
{
	long nNewTxtLeft;
	if(pColumnItem&&!IsActFirstColumn( TRUE ))
	{
		long nLeftCol=GetActLeftColumn( TRUE );
		nNewTxtLeft =
			PixelHAdjust(
				ConvertHPosLogic(
                    pIndents[INDENT_LEFT_MARGIN].nPos-
					(pBorders[nLeftCol].nPos +
					 pBorders[nLeftCol].nWidth))-
				lAppNullOffset,pParaItem->GetTxtLeft());
	}
	else
		nNewTxtLeft =
			PixelHAdjust(
                ConvertHPosLogic(pIndents[INDENT_LEFT_MARGIN].nPos),
				pParaItem->GetTxtLeft());

    BOOL bRTL = pRuler_Imp->pTextRTLItem && pRuler_Imp->pTextRTLItem->GetValue();

	long nNewFirstLineOffset;
	if(bRTL)
	{
		long nRightFrameMargin = GetRightFrameMargin();
		nNewFirstLineOffset = 	PixelHAdjust(nRightFrameMargin -
				ConvertHPosLogic(pIndents[INDENT_FIRST_LINE].nPos ) -
				lAppNullOffset,
				pParaItem->GetTxtFirstLineOfst());
	}
	else
		nNewFirstLineOffset=
			PixelHAdjust(
				ConvertHPosLogic(pIndents[INDENT_FIRST_LINE].nPos -
                             pIndents[INDENT_LEFT_MARGIN].nPos) -
				lAppNullOffset,
				pParaItem->GetTxtFirstLineOfst());

	// #62986# : Ist der neue TxtLeft kleiner als der alte FirstLineIndent,
    // dann geht die Differenz verloren und der Absatz wird insgesamt
	// zu weit eingerueckt, deswegen erst den FirstLineOffset setzen, dann den TxtLeft
	if(bRTL)
	{
        long nLeftFrameMargin = GetLeftFrameMargin();
        long nRightFrameMargin = GetRightFrameMargin();
		nNewTxtLeft = nRightFrameMargin - nNewTxtLeft - nLeftFrameMargin;
		nNewFirstLineOffset -= nNewTxtLeft;
		if(pParaBorderItem)
		{
			nNewTxtLeft += pParaBorderItem->GetLeft() + pParaBorderItem->GetRight();
			nNewFirstLineOffset -= pParaBorderItem->GetRight();
		}
	}
	pParaItem->SetTxtFirstLineOfst(
        sal::static_int_cast< short >(nNewFirstLineOffset));
	pParaItem->SetTxtLeft(nNewTxtLeft);

	if(pColumnItem && ((!bRTL && !IsActLastColumn( TRUE ))|| (bRTL && !IsActFirstColumn())))
	{
		if(bRTL)
		{
			long nActBorder = pBorders[GetActLeftColumn( TRUE )].nPos;
			long nRightMargin = pIndents[INDENT_RIGHT_MARGIN].nPos;
			long nConvert = ConvertHPosLogic( nRightMargin - nActBorder );
			pParaItem->SetRight( PixelHAdjust( nConvert - lAppNullOffset, pParaItem->GetRight() ) );
		}
		else
		{
			pParaItem->SetRight(
				PixelHAdjust(
					ConvertHPosLogic(
						pBorders[GetActRightColumn( TRUE )].nPos -
						pIndents[INDENT_RIGHT_MARGIN].nPos) -
					lAppNullOffset,
					pParaItem->GetRight()));
		}

	}
	else
	{
		if(bRTL)
		{
			pParaItem->SetRight( PixelHAdjust(
				ConvertHPosLogic(GetMargin1() +
                             pIndents[INDENT_RIGHT_MARGIN].nPos) - GetLeftFrameMargin() +
							 (pParaBorderItem ? pParaBorderItem->GetLeft() : 0) -
				lAppNullOffset,	pParaItem->GetRight()));
		}
		else
		{
			pParaItem->SetRight( PixelHAdjust(
				ConvertHPosLogic(GetMargin2() -
                             pIndents[INDENT_RIGHT_MARGIN].nPos) -
				lAppNullOffset,	pParaItem->GetRight()));
		}
	}
    USHORT nParaId  = bHorz ? SID_ATTR_PARA_LRSPACE : SID_ATTR_PARA_LRSPACE_VERTICAL;
    pBindings->GetDispatcher()->Execute( nParaId, SFX_CALLMODE_RECORD, pParaItem, 0L );
	UpdateTabs();
}


void SvxRuler::ApplyTabs()
/*
   [Beschreibung]

   Anwenden von Tabulatoreinstellungen; durch Draggen veraendert.

*/
{
	BOOL bRTL = pRuler_Imp->pTextRTLItem && pRuler_Imp->pTextRTLItem->GetValue();
	const USHORT nCoreIdx = GetDragAryPos();
	if(IsDragDelete())
	{
		pTabStopItem->Remove(nCoreIdx);
	}
	else if(DRAG_OBJECT_SIZE_LINEAR & nDragType ||
			DRAG_OBJECT_SIZE_PROPORTIONAL & nDragType)
	{
		SvxTabStopItem *pItem = new SvxTabStopItem(pTabStopItem->Which());
        //remove default tab stops
        for ( USHORT i = 0; i < pItem->Count(); )
        {
            if ( SVX_TAB_ADJUST_DEFAULT == (*pItem)[i].GetAdjustment() )
            {
                pItem->Remove(i);
                continue;
            }
            ++i;
        }

        USHORT j;
		for(j = 0; j < nCoreIdx; ++j)
		{
			pItem->Insert((*pTabStopItem)[j]);
		}
		for(; j < pTabStopItem->Count(); ++j)
		{
			SvxTabStop aTabStop = (*pTabStopItem)[j];
			aTabStop.GetTabPos() = PixelHAdjust(
				ConvertHPosLogic(pTabs[j+TAB_GAP].nPos -
								 GetLeftIndent()) -
				lAppNullOffset,
				aTabStop.GetTabPos());
			pItem->Insert(aTabStop);
		}
		delete pTabStopItem;
		pTabStopItem = pItem;
	}
	else if( pTabStopItem->Count() == 0 )
		return;
	else
	{
		SvxTabStop aTabStop = (*pTabStopItem)[nCoreIdx];
		if(pRuler_Imp->lMaxRightLogic!=-1&&
		   pTabs[nCoreIdx+TAB_GAP].nPos+Ruler::GetNullOffset()==nMaxRight)
			aTabStop.GetTabPos() = pRuler_Imp->lMaxRightLogic-lLogicNullOffset;
		else
		{
			if(bRTL)
            {
                //#i24363# tab stops relative to indent
                const long nTmpLeftIndent = pRuler_Imp->bIsTabsRelativeToIndent ?
                                            GetLeftIndent() :
                                            ConvertHPosPixel( GetRightFrameMargin() + lAppNullOffset );

				aTabStop.GetTabPos() = PixelHAdjust(
                    ConvertHPosLogic( nTmpLeftIndent - pTabs[nCoreIdx+TAB_GAP].nPos) - lAppNullOffset,
																						aTabStop.GetTabPos());
            }
			else
            {
                //#i24363# tab stops relative to indent
                const long nTmpLeftIndent = pRuler_Imp->bIsTabsRelativeToIndent ?
                                            GetLeftIndent() :
                                            0;

                aTabStop.GetTabPos() = PixelHAdjust(
                    ConvertHPosLogic( pTabs[nCoreIdx+TAB_GAP].nPos - nTmpLeftIndent ) - lAppNullOffset,
                                                                                         aTabStop.GetTabPos() );
            }
		}
		pTabStopItem->Remove(nCoreIdx);
		pTabStopItem->Insert(aTabStop);
	}
    USHORT nTabStopId = bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL;
    pBindings->GetDispatcher()->Execute( nTabStopId, SFX_CALLMODE_RECORD, pTabStopItem, 0L );
	UpdateTabs();
}


void SvxRuler::ApplyBorders()
/*
   [Beschreibung]

   Anwenden von (Tabellen-)Spalteneinstellungen; durch Draggen veraendert.

*/
{
	if(pColumnItem->IsTable())
	{
		long l = GetFrameLeft();
		if(l != pRuler_Imp->nColLeftPix)
			pColumnItem->SetLeft( PixelHAdjust(
				ConvertHPosLogic(l) - lAppNullOffset, pColumnItem->GetLeft()));
		l = GetMargin2();
		if(l != pRuler_Imp->nColRightPix)
		{
            long nWidthOrHeight = bHorz ? pPagePosItem->GetWidth() : pPagePosItem->GetHeight();
			pColumnItem->SetRight( PixelHAdjust( nWidthOrHeight -
					pColumnItem->GetLeft() - ConvertHPosLogic(l) -
					lAppNullOffset, pColumnItem->GetRight() ) );
		}
	}
	for(USHORT i = 0; i < pColumnItem->Count()-1; ++i)
	{
		long& nEnd = (*pColumnItem)[i].nEnd;
		nEnd = PIXEL_H_ADJUST(
			ConvertPosLogic(pBorders[i].nPos),
			(*pColumnItem)[i].nEnd);
		long& nStart = (*pColumnItem)[i+1].nStart;
		nStart = PIXEL_H_ADJUST(
			ConvertSizeLogic(pBorders[i].nPos +
							 pBorders[i].nWidth) -
			lAppNullOffset,
			(*pColumnItem)[i+1].nStart);
		// Es kann sein, dass aufgrund der PIXEL_H_ADJUST rejustierung auf
		// alte Werte die Breite < 0 wird. Das rerejustieren wir.
		if( nEnd > nStart )
			nStart = nEnd;
	}
#ifdef DEBUGLIN
		Debug_Impl(pEditWin,*pColumnItem);
#endif // DEBUGLIN
	SfxBoolItem aFlag(SID_RULER_ACT_LINE_ONLY,
					  nDragType & DRAG_OBJECT_ACTLINE_ONLY? TRUE: FALSE);
    USHORT nColId = pRuler_Imp->bIsTableRows ? (bHorz ? SID_RULER_ROWS : SID_RULER_ROWS_VERTICAL) :
                            (bHorz ? SID_RULER_BORDERS : SID_RULER_BORDERS_VERTICAL);
    pBindings->GetDispatcher()->Execute( nColId, SFX_CALLMODE_RECORD, pColumnItem, &aFlag, 0L );
}

void SvxRuler::ApplyObject()
/*
   [Beschreibung]

   Anwenden von Objekteinstellungen; durch Draggen veraendert.

*/
{
		// zum Seitenrand
	long nMargin = pLRSpaceItem? pLRSpaceItem->GetLeft(): 0;
	pObjectItem->SetStartX(
						   PixelAdjust(
							  ConvertPosLogic(pObjectBorders[0].nPos)
							  + nMargin - lAppNullOffset,pObjectItem->GetStartX()));
	pObjectItem->SetEndX(
						 PixelAdjust(
							 ConvertPosLogic(pObjectBorders[1].nPos)
						 + nMargin -  lAppNullOffset,pObjectItem->GetEndX()));
	nMargin = pULSpaceItem? pULSpaceItem->GetUpper(): 0;
	pObjectItem->SetStartY(
						 PixelAdjust(
							 ConvertPosLogic(pObjectBorders[2].nPos)
						   + nMargin - lAppNullOffset,pObjectItem->GetStartY()));
	pObjectItem->SetEndY(
					 PixelAdjust(
						 ConvertPosLogic(pObjectBorders[3].nPos)
						 + nMargin - lAppNullOffset,pObjectItem->GetEndY()));
	pBindings->GetDispatcher()->Execute( SID_RULER_OBJECT, SFX_CALLMODE_RECORD, pObjectItem, 0L );
}

void SvxRuler::PrepareProportional_Impl(RulerType eType)
/*
   [Beschreibung]

   Vorbereitung proportionales Draggen; es wird der proportionale
   Anteil bezogen auf die Gesamtbreite in Promille berechnet.

*/
{
	pRuler_Imp->nTotalDist = GetMargin2();
	switch((int)eType)
	{
      case RULER_TYPE_MARGIN2:
      case RULER_TYPE_MARGIN1:
	  case RULER_TYPE_BORDER:
		{
			DBG_ASSERT(pColumnItem, "kein ColumnItem");

			pRuler_Imp->SetPercSize(pColumnItem->Count());

			long lPos;
			long lWidth=0;
			USHORT nStart;
			USHORT nIdx=GetDragAryPos();
			lWidth=0;
			long lActWidth=0;
			long lActBorderSum;
			long lOrigLPos;

			if(eType != RULER_TYPE_BORDER)
			{
				lOrigLPos = GetMargin1();
				nStart = 0;
				lActBorderSum = 0;
			}
			else
			{
				if(pRuler_Imp->bIsTableRows &&!bHorz)
				{
					lOrigLPos = GetMargin1();
					nStart = 0;
				}
				else
				{
					lOrigLPos = pBorders[nIdx].nPos + pBorders[nIdx].nWidth;
					nStart = 1;
				}
				lActBorderSum = pBorders[nIdx].nWidth;
			}

            //in horizontal mode the percentage value has to be
            //calculated on a "current change" position base
            //because the height of the table changes while dragging
            if(pRuler_Imp->bIsTableRows && RULER_TYPE_BORDER == eType)
            {
                USHORT nStartBorder;
                USHORT nEndBorder;
                if(bHorz)
                {
                    nStartBorder = nIdx + 1;
                    nEndBorder = pColumnItem->Count() - 1;
                }
                else
                {
                    nStartBorder = 0;
                    nEndBorder = nIdx;
                }

				lWidth = pBorders[nIdx].nPos;
				if(bHorz)
					lWidth = GetMargin2() - lWidth;
                pRuler_Imp->nTotalDist = lWidth;
                lPos = lOrigLPos = pBorders[nIdx].nPos;

                for(USHORT i = nStartBorder; i < nEndBorder; ++i)
                {
                    if(bHorz)
					{
						lActWidth += pBorders[i].nPos - lPos;
						lPos = pBorders[i].nPos + pBorders[i].nWidth;
					}
					else
						lActWidth = pBorders[i].nPos;
                    pRuler_Imp->pPercBuf[i] = (USHORT)((lActWidth * 1000)
                                                    / pRuler_Imp->nTotalDist);
                    pRuler_Imp->pBlockBuf[i] = (USHORT)lActBorderSum;
                    lActBorderSum += pBorders[i].nWidth;
                }
            }
            else
            {
                lPos = lOrigLPos;
                for(USHORT ii = nStart; ii < pColumnItem->Count() - 1; ++ii)
                {
                    lWidth += pBorders[ii].nPos - lPos;
                    lPos = pBorders[ii].nPos + pBorders[ii].nWidth;
                }

                lWidth += GetMargin2() - lPos;
                pRuler_Imp->nTotalDist = lWidth;
                lPos = lOrigLPos;

                for(USHORT i = nStart; i < pColumnItem->Count() - 1; ++i)
                {
                    lActWidth += pBorders[i].nPos - lPos;
                    lPos = pBorders[i].nPos + pBorders[i].nWidth;
                    pRuler_Imp->pPercBuf[i] = (USHORT)((lActWidth * 1000)
                                                    / pRuler_Imp->nTotalDist);
                    pRuler_Imp->pBlockBuf[i] = (USHORT)lActBorderSum;
                    lActBorderSum += pBorders[i].nWidth;
                }
            }
        }
        break;
        case RULER_TYPE_TAB:
		{
			const USHORT nIdx = GetDragAryPos()+TAB_GAP;
			pRuler_Imp->nTotalDist -= pTabs[nIdx].nPos;
			pRuler_Imp->SetPercSize(nTabCount);
			for(USHORT n=0;n<=nIdx;pRuler_Imp->pPercBuf[n++]=0) ;
			for(USHORT i = nIdx+1; i < nTabCount; ++i)
			{
				const long nDelta = pTabs[i].nPos - pTabs[nIdx].nPos;
				pRuler_Imp->pPercBuf[i] = (USHORT)((nDelta * 1000) / pRuler_Imp->nTotalDist);
			}
			break;
		}
	}
}


void SvxRuler::EvalModifier()

/*
   [Beschreibung]

   Modifier Draggen auswerten

   Shift: Linear verschieben
   Control: Proportional verschieben
   Shift+Control: Tabelle: nur aktuelle Zeile
   alt: Bemassungspfeile (n.i.) //!!

*/

{
    USHORT nModifier = GetDragModifier();
    if(pRuler_Imp->bIsTableRows)
    {
        //rows can only be moved in one way, additionally current column is possible
        if(nModifier == KEY_SHIFT)
            nModifier = 0;
    }
    switch(nModifier)
    {
	 case KEY_SHIFT:
		nDragType = DRAG_OBJECT_SIZE_LINEAR;
		break;
	 case KEY_MOD1:  {
		 const RulerType eType = GetDragType();
		 nDragType = DRAG_OBJECT_SIZE_PROPORTIONAL;
		 if(RULER_TYPE_BORDER == eType || RULER_TYPE_TAB == eType||
			RULER_TYPE_MARGIN1&&pColumnItem)
			 PrepareProportional_Impl(eType);
		 break;
	 }
	 case KEY_MOD1 | KEY_SHIFT:
		if(GetDragType()!=RULER_TYPE_MARGIN1&&
		   GetDragType()!=RULER_TYPE_MARGIN2)
			nDragType = DRAG_OBJECT_ACTLINE_ONLY;
		break;
		// alt: Bemassungspfeile
	}
}


void __EXPORT SvxRuler::Click()

/*
   [Beschreibung]

   Ueberladener Handler SV; setzt Tab per Dispatcheraufruf

*/

{
	Ruler::Click();
	if( bActive )
	{
		pBindings->Update( SID_RULER_LR_MIN_MAX );
		pBindings->Update( SID_ATTR_LONG_ULSPACE );
		pBindings->Update( SID_ATTR_LONG_LRSPACE );
		pBindings->Update( SID_RULER_PAGE_POS );
        pBindings->Update( bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL);
        pBindings->Update( bHorz ? SID_ATTR_PARA_LRSPACE : SID_ATTR_PARA_LRSPACE_VERTICAL);
        pBindings->Update( bHorz ? SID_RULER_BORDERS : SID_RULER_BORDERS_VERTICAL);
        pBindings->Update( bHorz ? SID_RULER_ROWS : SID_RULER_ROWS_VERTICAL);
        pBindings->Update( SID_RULER_OBJECT );
		pBindings->Update( SID_RULER_PROTECT );
		pBindings->Update( SID_ATTR_PARA_LRSPACE_VERTICAL );
	}
	BOOL bRTL = pRuler_Imp->pTextRTLItem && pRuler_Imp->pTextRTLItem->GetValue();
	if(pTabStopItem &&
	   (nFlags & SVXRULER_SUPPORT_TABS) == SVXRULER_SUPPORT_TABS)
	{
		BOOL bContentProtected = pRuler_Imp->aProtectItem.IsCntntProtected();
		if( bContentProtected ) return;
		const long lPos = GetClickPos();
		if((bRTL && lPos < Min(GetFirstLineIndent(), GetLeftIndent()) && lPos > GetRightIndent()) ||
			(!bRTL && lPos > Min(GetFirstLineIndent(), GetLeftIndent()) && lPos < GetRightIndent()))
		{
			//convert position in left-to-right text
			long nTabPos;
    //#i24363# tab stops relative to indent
            if(bRTL)
                nTabPos = ( pRuler_Imp->bIsTabsRelativeToIndent ?
                            GetLeftIndent() :
                            ConvertHPosPixel( GetRightFrameMargin() + lAppNullOffset ) ) -
                          lPos;
            else
                nTabPos = lPos -
                          ( pRuler_Imp->bIsTabsRelativeToIndent ?
                            GetLeftIndent() :
                            0 );

			SvxTabStop aTabStop(ConvertHPosLogic(nTabPos),
								ToAttrTab_Impl(nDefTabType));
			pTabStopItem->Insert(aTabStop);
			UpdateTabs();
		}
	}
}


BOOL SvxRuler::CalcLimits
(
 long &nMax1,                                   // zu setzenden Minimalwert
 long &nMax2,                                   // zu setzenden Maximalwert
 BOOL
) const
/*
   [Beschreibung]

   Defaultimplementierung der virtuellen Funktion; kann die Applikation
   ueberladen, um eine eigene Grenzwertbehandlung zu implementieren.
   Die Werte sind auf die Seite bezogen.
*/
{
	nMax1 = LONG_MIN;
	nMax2 = LONG_MAX;
	return FALSE;
}


void SvxRuler::CalcMinMax()

/*
   [Beschreibung]

   Berechnet die Grenzwerte fuers Draggen; diese sind in Pixeln
   relativ zum Seitenrand

*/

{
	BOOL bRTL = pRuler_Imp->pTextRTLItem && pRuler_Imp->pTextRTLItem->GetValue();
	const long lNullPix = ConvertPosPixel(lLogicNullOffset);
	pRuler_Imp->lMaxLeftLogic=pRuler_Imp->lMaxRightLogic=-1;
	switch(GetDragType())
	{
	  case RULER_TYPE_MARGIN1:
		{        // linker Rand umgebender Frame
			// DragPos - NOf zwischen links - rechts
			pRuler_Imp->lMaxLeftLogic = GetLeftMin();
			nMaxLeft=ConvertSizePixel(pRuler_Imp->lMaxLeftLogic);

			if(!pColumnItem || pColumnItem->Count() == 1 )
			{
				if(bRTL)
				{
					nMaxRight = lNullPix - GetRightIndent() +
						Max(GetFirstLineIndent(), GetLeftIndent()) -
						lMinFrame;
				}
				else
				{
					nMaxRight = lNullPix + GetRightIndent() -
						Max(GetFirstLineIndent(), GetLeftIndent()) -
						lMinFrame;
				}
			}
			else if(pRuler_Imp->bIsTableRows)
			{
				//top border is not moveable when table rows are displayed
				// protection of content means the margin is not moveable - it's just a page break inside of a cell
				if(bHorz && !pRuler_Imp->aProtectItem.IsCntntProtected())
				{
					nMaxLeft = pBorders[0].nMinPos + lNullPix;
					if(nDragType & DRAG_OBJECT_SIZE_PROPORTIONAL)
						nMaxRight = GetRightIndent() + lNullPix -
								(pColumnItem->Count() - 1 ) * lMinFrame;
					else
						nMaxRight = pBorders[0].nPos - lMinFrame + lNullPix;
				}
				else
					nMaxLeft = nMaxRight = lNullPix;
			}
			else
			{
				if(nDragType & DRAG_OBJECT_SIZE_PROPORTIONAL)
				   //nDragType & DRAG_OBJECT_SIZE_LINEAR)
				{
					nMaxRight=lNullPix+CalcPropMaxRight();
				}
				else if(nDragType & DRAG_OBJECT_SIZE_LINEAR)
				{
					nMaxRight = ConvertPosPixel(
						GetPageWidth() - (
							(pColumnItem->IsTable() && pLRSpaceItem)
							? pLRSpaceItem->GetRight() : 0))
							- GetMargin2() + GetMargin1();
				}
				else
				{
					nMaxRight = lNullPix - lMinFrame;
					if(pColumnItem->IsFirstAct())
					{
						if(bRTL)
						{
							nMaxRight += Min(
								pBorders[0].nPos,
								Max(GetFirstLineIndent(), GetLeftIndent()) - GetRightIndent());
						}
						else
						{
							nMaxRight += Min(
								pBorders[0].nPos, GetRightIndent() -
								Max(GetFirstLineIndent(), GetLeftIndent()));
						}
					}
					else if( pColumnItem->Count() > 1 )
						nMaxRight += pBorders[0].nPos;
					else
						nMaxRight +=GetRightIndent() -
							Max(GetFirstLineIndent(), GetLeftIndent());
					// den linken Tabellen-Rand nicht ueber den Seitenrand ziehen
					if(pLRSpaceItem&&pColumnItem->IsTable())
					{
						long nTmp=ConvertSizePixel(pLRSpaceItem->GetLeft());
						if(nTmp>nMaxLeft)
							nMaxLeft=nTmp;
					}
				}
			}
			break;
		}
	  case RULER_TYPE_MARGIN2:
	 {        // rechter Rand umgebender Frame
		pRuler_Imp->lMaxRightLogic =
			pMinMaxItem ?
				GetPageWidth() - GetRightMax() : GetPageWidth();
		nMaxRight = ConvertSizePixel(pRuler_Imp->lMaxRightLogic);


		if(!pColumnItem)
		{
			if(bRTL)
			{
				nMaxLeft =  GetMargin2() + GetRightIndent() -
					Max(GetFirstLineIndent(),GetLeftIndent())  - GetMargin1()+
						lMinFrame + lNullPix;
			}
			else
			{
				nMaxLeft =  GetMargin2() - GetRightIndent() +
					Max(GetFirstLineIndent(),GetLeftIndent())  - GetMargin1()+
						lMinFrame + lNullPix;
			}
		}
		else if(pRuler_Imp->bIsTableRows)
		{
			// get the bottom move range from the last border position - only available for rows!
			// protection of content means the margin is not moveable - it's just a page break inside of a cell
			if(bHorz || pRuler_Imp->aProtectItem.IsCntntProtected())
			{
				nMaxLeft = nMaxRight = pBorders[pColumnItem->Count() - 1].nMaxPos + lNullPix;
			}
			else
			{
                if(nDragType & DRAG_OBJECT_SIZE_PROPORTIONAL)
                {
                    nMaxLeft = (pColumnItem->Count()) * lMinFrame + lNullPix;
                }
                else
                {
                    if(pColumnItem->Count() > 1)
                        nMaxLeft = pBorders[pColumnItem->Count() - 2].nPos + lMinFrame + lNullPix;
                    else
                        nMaxLeft = lMinFrame + lNullPix;
                }
                if(pColumnItem->Count() > 1)
                    nMaxRight = pBorders[pColumnItem->Count() - 2].nMaxPos + lNullPix;
                else
                    nMaxRight -= GetRightIndent() - lNullPix;
			}
		}
		else
		{
			nMaxLeft = lMinFrame + lNullPix;
			if(IsActLastColumn() || pColumnItem->Count() < 2 ) //Falls letzte Spalte aktiv
			{
				if(bRTL)
				{
					nMaxLeft = lMinFrame + lNullPix + GetMargin2() +
						GetRightIndent() - Max(GetFirstLineIndent(),
											   GetLeftIndent());
				}
				else
				{
					nMaxLeft = lMinFrame + lNullPix + GetMargin2() -
						GetRightIndent() + Max(GetFirstLineIndent(),
											   GetLeftIndent());
				}
			}
			if( pColumnItem->Count() >= 2 )
			{
				long nNewMaxLeft =
					lMinFrame + lNullPix +
					pBorders[pColumnItem->Count()-2].nPos +
					pBorders[pColumnItem->Count()-2].nWidth;
				nMaxLeft=Max(nMaxLeft,nNewMaxLeft);
			}

		}
		break;
	}
	case RULER_TYPE_BORDER:
	{                // Tabelle, Spalten (Modifier)
		const USHORT nIdx = GetDragAryPos();
		switch(GetDragSize())
		{
		  case RULER_DRAGSIZE_1 :
			{
				nMaxRight = pBorders[nIdx].nPos +
					pBorders[nIdx].nWidth + lNullPix;

				if(0 == nIdx)
					nMaxLeft = lNullPix;
				else
					nMaxLeft = pBorders[nIdx-1].nPos +
						pBorders[nIdx-1].nWidth + lNullPix;
				if(nIdx == pColumnItem->GetActColumn())
				{
					if(bRTL)
					{
						nMaxLeft += pBorders[nIdx].nPos +
							GetRightIndent() - Max(GetFirstLineIndent(),
												   GetLeftIndent());
					}
					else
					{
						nMaxLeft += pBorders[nIdx].nPos -
							GetRightIndent() + Max(GetFirstLineIndent(),
												   GetLeftIndent());
					}
					if(0 != nIdx)
						nMaxLeft -= pBorders[nIdx-1].nPos +
							pBorders[nIdx-1].nWidth;
				}
				nMaxLeft += lMinFrame;
				nMaxLeft += nDragOffset;
				break;
			}
		  case RULER_DRAGSIZE_MOVE:
			{
				if(pColumnItem)
				{
					//nIdx contains the position of the currently moved item
					//next visible separator on the left
					USHORT nLeftCol=GetActLeftColumn(FALSE, nIdx);
					//next visible separator on the right
					USHORT nRightCol=GetActRightColumn(FALSE, nIdx);
					//next separator on the left - regardless if visible or not
					USHORT nActLeftCol=GetActLeftColumn();
					//next separator on the right - regardless if visible or not
					USHORT nActRightCol=GetActRightColumn();
                    if(pColumnItem->IsTable())
					{
						if(nDragType & DRAG_OBJECT_ACTLINE_ONLY)
						{
							//the current row/column should be modified only
							//then the next/previous visible border position
							//marks the min/max positions
							nMaxLeft = nLeftCol == USHRT_MAX ?
								0 :
								pBorders[nLeftCol].nPos;
							//rows can always be increased without a limit
							if(pRuler_Imp->bIsTableRows)
								nMaxRight = pBorders[nIdx].nMaxPos;
							else
								nMaxRight = nRightCol == USHRT_MAX ?
									GetMargin2():
									pBorders[nRightCol].nPos;
							nMaxLeft += lNullPix;
							nMaxRight += lNullPix;
						}
						else
						{
							if(DRAG_OBJECT_SIZE_PROPORTIONAL & nDragType && !bHorz && pRuler_Imp->bIsTableRows)
								nMaxLeft = (nIdx + 1) * lMinFrame + lNullPix;
							else
								nMaxLeft = pBorders[nIdx].nMinPos + lNullPix;
							if(DRAG_OBJECT_SIZE_PROPORTIONAL & nDragType||
							(DRAG_OBJECT_SIZE_LINEAR & nDragType) )
							{
								if(pRuler_Imp->bIsTableRows)
								{
									if(bHorz)
										nMaxRight = GetRightIndent() + lNullPix -
												(pColumnItem->Count() - nIdx - 1) * lMinFrame;
									else
										nMaxRight = pBorders[nIdx].nMaxPos + lNullPix;
								}
								else
									nMaxRight=lNullPix+CalcPropMaxRight(nIdx);
							}
							else
								nMaxRight = pBorders[nIdx].nMaxPos + lNullPix;
						}
						nMaxLeft += lMinFrame;
						nMaxRight -= lMinFrame;

					}
					else
					{
                        if(nLeftCol==USHRT_MAX)
                            nMaxLeft=lNullPix;
                        else
                            nMaxLeft = pBorders[nLeftCol].nPos +
                                pBorders[nLeftCol].nWidth + lNullPix;

                        if(nActRightCol == nIdx)
                        {
                            if(bRTL)
                            {
                                nMaxLeft += pBorders[nIdx].nPos +
                                    GetRightIndent() - Max(GetFirstLineIndent(),
                                                           GetLeftIndent());
                                if(nActLeftCol!=USHRT_MAX)
                                    nMaxLeft -= pBorders[nActLeftCol].nPos +
                                        pBorders[nActLeftCol].nWidth;
                            }
                            else
                            {
                                nMaxLeft += pBorders[nIdx].nPos -
                                    GetRightIndent() + Max(GetFirstLineIndent(),
                                                           GetLeftIndent());
                                if(nActLeftCol!=USHRT_MAX)
                                    nMaxLeft -= pBorders[nActLeftCol].nPos +
                                        pBorders[nActLeftCol].nWidth;
                            }
                        }
                        nMaxLeft += lMinFrame;
                        nMaxLeft += nDragOffset;

                        // nMaxRight
                        // linear / proprotional verschieben
                        if(DRAG_OBJECT_SIZE_PROPORTIONAL & nDragType||
                           (DRAG_OBJECT_SIZE_LINEAR & nDragType) )
                        {
                            nMaxRight=lNullPix+CalcPropMaxRight(nIdx);
                        }
                        else if(DRAG_OBJECT_SIZE_LINEAR & nDragType)
                        {
                            nMaxRight=lNullPix+GetMargin2()-GetMargin1()+
                                (nBorderCount-nIdx-1)*lMinFrame;
                        }
                        else
                        {
                            if(nRightCol==USHRT_MAX)
                            { // letzte Spalte
                                nMaxRight = GetMargin2() + lNullPix;
                                if(IsActLastColumn())
                                {
                                    if(bRTL)
                                    {
                                        nMaxRight -=
                                            GetMargin2() + GetRightIndent() -
                                                Max(GetFirstLineIndent(),
                                                    GetLeftIndent());
                                    }
                                    else
                                    {
                                        nMaxRight -=
                                            GetMargin2() - GetRightIndent() +
                                                Max(GetFirstLineIndent(),
                                                    GetLeftIndent());
                                    }
                                    nMaxRight += pBorders[nIdx].nPos +
                                        pBorders[nIdx].nWidth;
                                }
                            }
                            else
                            {
                                nMaxRight = lNullPix + pBorders[nRightCol].nPos;
                                USHORT nNotHiddenRightCol =
                                    GetActRightColumn(TRUE, nIdx);

                                if( nActLeftCol == nIdx )
                                {
                                    long nBorder = nNotHiddenRightCol ==
                                        USHRT_MAX ?
                                        GetMargin2() :
                                        pBorders[nNotHiddenRightCol].nPos;
                                    if(bRTL)
                                    {
                                        nMaxRight -= nBorder + GetRightIndent() -
                                            Max(GetFirstLineIndent(),
                                                GetLeftIndent());
                                    }
                                    else
                                    {
                                        nMaxRight -= nBorder - GetRightIndent() +
                                            Max(GetFirstLineIndent(),
                                                GetLeftIndent());
                                    }
                                    nMaxRight += pBorders[nIdx].nPos +
                                        pBorders[nIdx].nWidth;
                                }
                            }
                            nMaxRight -= lMinFrame;
                            nMaxRight -= pBorders[nIdx].nWidth;
                        }
                    }
				}
				// ObjectItem
				else
				{
					if(pObjectItem->HasLimits())
					{
						if(CalcLimits(nMaxLeft, nMaxRight, nIdx & 1? FALSE: TRUE))
						{
							nMaxLeft = ConvertPosPixel(nMaxLeft);
							nMaxRight = ConvertPosPixel(nMaxRight);
						}
					}
					else
					{
						nMaxLeft = LONG_MIN;
						nMaxRight = LONG_MAX;
					}
				}
				break;
			}
		  case RULER_DRAGSIZE_2:
			{
				nMaxLeft = lNullPix + pBorders[nIdx].nPos;
				if(nIdx == pColumnItem->Count()-2) { // letzte Spalte
					nMaxRight = GetMargin2() + lNullPix;
					if(pColumnItem->IsLastAct()) {
						nMaxRight -=
							GetMargin2() - GetRightIndent() +
								Max(GetFirstLineIndent(),
									GetLeftIndent());
						nMaxRight += pBorders[nIdx].nPos +
							pBorders[nIdx].nWidth;
					}
				}
				else {
					nMaxRight = lNullPix + pBorders[nIdx+1].nPos;
					if(pColumnItem->GetActColumn()-1 == nIdx) {
						nMaxRight -= pBorders[nIdx+1].nPos  - GetRightIndent() +
							Max(GetFirstLineIndent(),
								GetLeftIndent());
						nMaxRight += pBorders[nIdx].nPos +
							pBorders[nIdx].nWidth;
					}
			}
				nMaxRight -= lMinFrame;
				nMaxRight -= pBorders[nIdx].nWidth;
				break;
			}
		}
		nMaxRight += nDragOffset;
		break;
	}
	  case RULER_TYPE_INDENT:
		{
		const USHORT nIdx = GetDragAryPos();
		switch(nIdx) {
		case INDENT_FIRST_LINE - INDENT_GAP:
		case INDENT_LEFT_MARGIN - INDENT_GAP:
            {
                if(bRTL)
                {
                    nMaxLeft = lNullPix + GetRightIndent();

                    if(pColumnItem && !pColumnItem->IsFirstAct())
                        nMaxLeft += pBorders[pColumnItem->GetActColumn()-1].nPos +
                            pBorders[pColumnItem->GetActColumn()-1].nWidth;
                    nMaxRight = lNullPix + GetMargin2();

                    // zusammem draggen
                    if((INDENT_FIRST_LINE - INDENT_GAP) != nIdx &&
                       (nDragType & DRAG_OBJECT_LEFT_INDENT_ONLY) !=
                       DRAG_OBJECT_LEFT_INDENT_ONLY)
                    {
                        if(GetLeftIndent() > GetFirstLineIndent())
                            nMaxLeft += GetLeftIndent() - GetFirstLineIndent();
                        else
                            nMaxRight -= GetFirstLineIndent() - GetLeftIndent();
                    }
                }
                else
                {
                    nMaxLeft = lNullPix;

                    if(pColumnItem && !pColumnItem->IsFirstAct())
                        nMaxLeft += pBorders[pColumnItem->GetActColumn()-1].nPos +
                            pBorders[pColumnItem->GetActColumn()-1].nWidth;
                    nMaxRight = lNullPix + GetRightIndent() - lMinFrame;

                    // zusammem draggen
                    if((INDENT_FIRST_LINE - INDENT_GAP) != nIdx &&
                       (nDragType & DRAG_OBJECT_LEFT_INDENT_ONLY) !=
                       DRAG_OBJECT_LEFT_INDENT_ONLY)
                    {
                        if(GetLeftIndent() > GetFirstLineIndent())
                            nMaxLeft += GetLeftIndent() - GetFirstLineIndent();
                        else
                            nMaxRight -= GetFirstLineIndent() - GetLeftIndent();
                    }
                }
            }
          break;
          case INDENT_RIGHT_MARGIN - INDENT_GAP:
            {
                if(bRTL)
                {
                    nMaxLeft = lNullPix;
                    nMaxRight = lNullPix + Min(GetFirstLineIndent(), GetLeftIndent()) - lMinFrame;
                    if(pColumnItem)
                    {
                        USHORT nRightCol=GetActRightColumn( TRUE );
                        if(!IsActLastColumn( TRUE ))
                            nMaxRight += pBorders[nRightCol].nPos;
                        else
                            nMaxRight += GetMargin2();
                    }
                    else
                        nMaxLeft += GetMargin1();
                    nMaxLeft += lMinFrame;
                }
                else
                {
                    nMaxLeft = lNullPix +
                        Max(GetFirstLineIndent(), GetLeftIndent());
                    nMaxRight = lNullPix;
                    if(pColumnItem)
                    {
                        USHORT nRightCol=GetActRightColumn( TRUE );
                        if(!IsActLastColumn( TRUE ))
                            nMaxRight += pBorders[nRightCol].nPos;
                        else
                            nMaxRight += GetMargin2();
                    }
                    else
                        nMaxRight += GetMargin2();
                    nMaxLeft += lMinFrame;
                }
            }
            break;
		}
		break;
	}
	case RULER_TYPE_TAB:                // Tabs (Modifier)
		/*
		   links = NOf + Max(LAR, EZ)
		   rechts = NOf + RAR
		   */
		nMaxLeft = bRTL ? lNullPix + GetRightIndent()
							: lNullPix + Min(GetFirstLineIndent(), GetLeftIndent());
		pRuler_Imp->lMaxRightLogic=GetLogicRightIndent()+lLogicNullOffset;
		nMaxRight = ConvertSizePixel(pRuler_Imp->lMaxRightLogic);
		break;
    default: ; //prevent warning
	}
#ifdef DEBUGLIN
	{
		String aStr("MinLeft: ");
		Size aSize(nMaxLeft + lNullPix, 0);
		Size aSize2(nMaxRight + lNullPix, 0);
		aSize = pEditWin->PixelToLogic(aSize, MapMode(MAP_MM));
		aSize2 = pEditWin->PixelToLogic(aSize2, MapMode(MAP_MM));
		aStr += String(aSize.Width());
		aStr += " MaxRight: ";
		aStr += String(aSize2.Width());
		InfoBox(0, aStr).Execute();
	}
#endif
}


long __EXPORT SvxRuler::StartDrag()

/*
   [Beschreibung]

   Beginn eines Drag-Vorgangs (SV-Handler); wertet Modifier aus
   und berechnet Grenzwerte

   [Querverweise]

   <SvxRuler::EvalModifier()>
   <SvxRuler::CalcMinMax()>
   <SvxRuler::EndDrag()>

*/

{
	BOOL bContentProtected = pRuler_Imp->aProtectItem.IsCntntProtected();
	if(!bValid)
		return FALSE;

	pRuler_Imp->lLastLMargin=GetMargin1();
	pRuler_Imp->lLastRMargin=GetMargin2();
	long bOk = 1;
	if(GetStartDragHdl().IsSet())
		bOk = Ruler::StartDrag();
	if(bOk) {
		lInitialDragPos = GetDragPos();
		switch(GetDragType()) {
		case RULER_TYPE_MARGIN1:        // linker Rand umgebender Frame
		case RULER_TYPE_MARGIN2:        // rechter Rand umgebender Frame
			if((bHorz && pLRSpaceItem) || (!bHorz && pULSpaceItem))
			{
				if(pColumnItem)
					EvalModifier();
				else
					nDragType = DRAG_OBJECT;
			}
			else
				bOk = FALSE;
			break;
		case RULER_TYPE_BORDER:                // Tabelle, Spalten (Modifier)
			if(pColumnItem)
			{
				nDragOffset = pColumnItem->IsTable()? 0 :
				GetDragPos() - pBorders[GetDragAryPos()].nPos;
				EvalModifier();

			}
			else
				nDragOffset = 0;
			break;
		case RULER_TYPE_INDENT: {                // Absatzeinzuege (Modifier)
			if( bContentProtected )
				return FALSE;
			USHORT nIndent = INDENT_LEFT_MARGIN;
            if((nIndent) == GetDragAryPos() + INDENT_GAP) {        // Linker Absatzeinzug
                pIndents[0] = pIndents[INDENT_FIRST_LINE];
				pIndents[0].nStyle |= RULER_STYLE_DONTKNOW;
				EvalModifier();
			}
			else
				nDragType = DRAG_OBJECT;
            pIndents[1] = pIndents[GetDragAryPos()+INDENT_GAP];
			pIndents[1].nStyle |= RULER_STYLE_DONTKNOW;
			break;
		}
		case RULER_TYPE_TAB:                // Tabs (Modifier)
			if( bContentProtected ) return FALSE;
			EvalModifier();
			pTabs[0] = pTabs[GetDragAryPos()+1];
			pTabs[0].nStyle |= RULER_STYLE_DONTKNOW;
			break;
		default:
			nDragType = NONE;
		}
	}
	else
		nDragType = NONE;
	if(bOk)
		CalcMinMax();
	return bOk;
}


void  __EXPORT SvxRuler::Drag()
/*
   [Beschreibung]

   SV-Draghandler

*/
{
	if(IsDragCanceled())
	{
		Ruler::Drag();
		return;
	}
	switch(GetDragType()) {
	case RULER_TYPE_MARGIN1:        // linker Rand umgebender Frame
		DragMargin1();
		pRuler_Imp->lLastLMargin=GetMargin1();
		break;
	case RULER_TYPE_MARGIN2:        // rechter Rand umgebender Frame
		DragMargin2();
        pRuler_Imp->lLastRMargin = GetMargin2();
        break;
	case RULER_TYPE_INDENT:         // Absatzeinzuege
		DragIndents();
		break;
	case RULER_TYPE_BORDER:         // Tabelle, Spalten
		if(pColumnItem)
			DragBorders();
		else if(pObjectItem)
			DragObjectBorder();
		break;
	case RULER_TYPE_TAB:            // Tabs
		DragTabs();
		break;
    default: ;//prevent warning
	}
	Ruler::Drag();
}


void __EXPORT SvxRuler::EndDrag()
/*
   [Beschreibung]

   SV-Handler; wird beim Beenden des Draggens gerufen.
   Stoesst die Aktualisierung der Daten der Applikation an, indem
   durch Aufruf der jeweiligen Apply...()- Methoden die Daten an die
   Applikation geschickt werden.

*/
{
	const BOOL bUndo = IsDragCanceled();
	const long lPos = GetDragPos();
	DrawLine_Impl(lTabPos, 6, bHorz);
	lTabPos=-1;
	if(!bUndo)
		switch(GetDragType())
		{
		  case RULER_TYPE_MARGIN1:   // linker, oberer Rand umgebender Frame
		  case RULER_TYPE_MARGIN2:   // rechter, unterer Rand umgebender Frame
			{
				if(!pColumnItem || !pColumnItem->IsTable())
					ApplyMargins();

				if(pColumnItem &&
				   (pColumnItem->IsTable() ||
					(nDragType & DRAG_OBJECT_SIZE_PROPORTIONAL)))
					ApplyBorders();

			}
			break;
		  case RULER_TYPE_BORDER:                // Tabelle, Spalten
			if(lInitialDragPos != lPos ||
				(pRuler_Imp->bIsTableRows && bHorz)) //special case - the null offset is changed here
			{
				if(pColumnItem)
				{
					ApplyBorders();
					if(bHorz)
						UpdateTabs();
				}
				else if(pObjectItem)
					ApplyObject();
			}
			break;
		  case RULER_TYPE_INDENT:                // Absatzeinzuege
			if(lInitialDragPos != lPos)
				ApplyIndents();
            SetIndents(INDENT_COUNT, pIndents+INDENT_GAP);
			break;
		  case RULER_TYPE_TAB:                // Tabs
			{
				ApplyTabs();
				pTabs[GetDragAryPos()].nStyle &= ~RULER_STYLE_INVISIBLE;
				SetTabs(nTabCount, pTabs+TAB_GAP);
			}
			break;
            default: ; //prevent warning
        }
	nDragType = NONE;
	Ruler::EndDrag();
	if(bUndo)
		for(USHORT i=0;i<pRuler_Imp->nControlerItems;i++)
		{
			pCtrlItem[i]->ClearCache();
			pCtrlItem[i]->GetBindings().Invalidate(pCtrlItem[i]->GetId());
			//		pCtrlItem[i]->UnBind();
//			pCtrlItem[i]->ReBind();
		}
}


void __EXPORT SvxRuler::ExtraDown()

/*
   [Beschreibung]

   Ueberladene SV-Methode; setzt den neuen Typ fuer den Defaulttabulator.
*/

{
	// Tabulator Typ umschalten
	if(pTabStopItem &&
		(nFlags & SVXRULER_SUPPORT_TABS) ==        SVXRULER_SUPPORT_TABS) {
		++nDefTabType;
		if(RULER_TAB_DEFAULT == nDefTabType)
			nDefTabType = RULER_TAB_LEFT;
		SetExtraType(RULER_EXTRA_TAB, nDefTabType);
	}
	Ruler::ExtraDown();
}


void __EXPORT SvxRuler::Notify(SfxBroadcaster&, const SfxHint& rHint)
/*

   [Beschreibung]

   Benachrichtigung durch die Bindings, dass die Statusaktualisierung
   beendet ist.
   Das Lineal aktualisiert seine Darstellung und meldet sich bei den
   Bindings wieder ab.

*/

{
	// Aktualisierung anstossen
	if(bActive &&
		rHint.Type() == TYPE(SfxSimpleHint) &&
	 ((SfxSimpleHint&) rHint ).GetId() == SFX_HINT_UPDATEDONE ) {
		Update();
		EndListening(*pBindings);
		bValid = TRUE;
		bListening = FALSE;
	}
}


IMPL_LINK_INLINE_START( SvxRuler, MenuSelect, Menu *, pMenu )

/*
   [Beschreibung]

   Handler des Kontextmenues fuer das Umschalten der Masseinheit

*/

{
	SetUnit(FieldUnit(pMenu->GetCurItemId()));
	return 0;
}
IMPL_LINK_INLINE_END( SvxRuler, MenuSelect, Menu *, pMenu )


IMPL_LINK( SvxRuler, TabMenuSelect, Menu *, pMenu )

/*
   [Beschreibung]

   Handler des Tabulatormenues fuer das Setzen des Typs

*/

{
    if(pTabStopItem && pTabStopItem->Count() > pRuler_Imp->nIdx)
    {
        SvxTabStop aTabStop = (*pTabStopItem)[pRuler_Imp->nIdx];
        aTabStop.GetAdjustment() = ToAttrTab_Impl(pMenu->GetCurItemId()-1);
        pTabStopItem->Remove(pRuler_Imp->nIdx);
        pTabStopItem->Insert(aTabStop);
        USHORT nTabStopId = bHorz ? SID_ATTR_TABSTOP : SID_ATTR_TABSTOP_VERTICAL;
        pBindings->GetDispatcher()->Execute( nTabStopId, SFX_CALLMODE_RECORD, pTabStopItem, 0L );
        UpdateTabs();
        pRuler_Imp->nIdx = 0;
    }
	return 0;
}


void SvxRuler::Command( const CommandEvent& rCEvt )

/*
   [Beschreibung]

   Mauskontextmenue fuer das Umschalten der Masseinheit

*/

{
	if ( COMMAND_CONTEXTMENU == rCEvt.GetCommand() )
	{
		CancelDrag();
        BOOL bRTL = pRuler_Imp->pTextRTLItem && pRuler_Imp->pTextRTLItem->GetValue();
		if ( pTabs &&
			 RULER_TYPE_TAB ==
			 GetType( rCEvt.GetMousePosPixel(), &pRuler_Imp->nIdx ) &&
			 pTabs[pRuler_Imp->nIdx+TAB_GAP].nStyle < RULER_TAB_DEFAULT )
		{
			PopupMenu aMenu;
			aMenu.SetSelectHdl(LINK(this, SvxRuler, TabMenuSelect));
			VirtualDevice aDev;
			const Size aSz(RULER_TAB_WIDTH+2, RULER_TAB_HEIGHT+2);
			aDev.SetOutputSize(aSz);
			aDev.SetBackground(Wallpaper(Color(COL_WHITE)));
			const Point aPt(aSz.Width() / 2, aSz.Height() / 2);

			for ( USHORT i = RULER_TAB_LEFT; i < RULER_TAB_DEFAULT; ++i )
			{
                USHORT nStyle = bRTL ? i|RULER_TAB_RTL : i;
				nStyle |= (USHORT)(bHorz ? WB_HORZ : WB_VERT);
				DrawTab(&aDev, aPt, nStyle);
				aMenu.InsertItem(i+1,
								 String(ResId(RID_SVXSTR_RULER_START+i, DIALOG_MGR())),
								 Image(aDev.GetBitmap(Point(), aSz), Color(COL_WHITE)));
				aMenu.CheckItem(i+1, i == pTabs[pRuler_Imp->nIdx+TAB_GAP].nStyle);
				aDev.SetOutputSize(aSz); // device loeschen
			}
			aMenu.Execute( this, rCEvt.GetMousePosPixel() );
		}
		else
		{
			PopupMenu aMenu(ResId(RID_SVXMN_RULER, DIALOG_MGR()));
			aMenu.SetSelectHdl(LINK(this, SvxRuler, MenuSelect));
			FieldUnit eUnit = GetUnit();
			const USHORT nCount = aMenu.GetItemCount();

            BOOL bReduceMetric = 0 != (nFlags &SVXRULER_SUPPORT_REDUCED_METRIC);
            for ( USHORT i = nCount; i; --i )
			{
                const USHORT nId = aMenu.GetItemId(i - 1);
				aMenu.CheckItem(nId, nId == (USHORT)eUnit);
                if(bReduceMetric &&
                        (nId == FUNIT_M ||
                         nId == FUNIT_KM ||
                         nId == FUNIT_FOOT ||
                         nId == FUNIT_MILE ))
                    aMenu.RemoveItem(i - 1);
			}
			aMenu.Execute( this, rCEvt.GetMousePosPixel() );
		}
	}
	else
		Ruler::Command( rCEvt );
}


USHORT SvxRuler::GetActRightColumn(
	BOOL bForceDontConsiderHidden, USHORT nAct ) const
{
	if( nAct == USHRT_MAX )
		nAct = pColumnItem->GetActColumn();
	else nAct++; //Damit man die ActDrag uebergeben kann

	BOOL bConsiderHidden = !bForceDontConsiderHidden &&
		!( nDragType & DRAG_OBJECT_ACTLINE_ONLY );

	while( nAct < pColumnItem->Count() - 1 )
	{
		if( (*pColumnItem)[nAct].bVisible || bConsiderHidden )
			return nAct;
		else
			nAct++;
	}
	return USHRT_MAX;
}



USHORT SvxRuler::GetActLeftColumn(
	BOOL bForceDontConsiderHidden, USHORT nAct ) const
{
	if(nAct==USHRT_MAX)
		nAct=pColumnItem->GetActColumn();

	USHORT nLOffs=1;

	BOOL bConsiderHidden = !bForceDontConsiderHidden &&
		!( nDragType & DRAG_OBJECT_ACTLINE_ONLY );

	while(nAct>=nLOffs)
	{
		if( (*pColumnItem)[ nAct - nLOffs ].bVisible || bConsiderHidden )
			return nAct-nLOffs;
		else
			nLOffs++;
	}
	return USHRT_MAX;
}


BOOL SvxRuler::IsActLastColumn(
	BOOL bForceDontConsiderHidden, USHORT nAct) const
{
	return GetActRightColumn(bForceDontConsiderHidden, nAct)==USHRT_MAX;
}

BOOL SvxRuler::IsActFirstColumn(
	BOOL bForceDontConsiderHidden, USHORT nAct) const
{
	return GetActLeftColumn(bForceDontConsiderHidden, nAct)==USHRT_MAX;
}

long SvxRuler::CalcPropMaxRight(USHORT nCol) const
{

	if(!(nDragType & DRAG_OBJECT_SIZE_LINEAR))
	{

		// ausgehend vom rechten Rand die Mindestbreiten
		// aller betroffenen Spalten abziehen
        long _nMaxRight = GetMargin2()-GetMargin1();

		long lFences=0;
		long lMinSpace=USHRT_MAX;
		long lOldPos;
		long lColumns=0;
		USHORT nStart;
		if(!pColumnItem->IsTable())
		{
			if(nCol==USHRT_MAX)
			{
				lOldPos=GetMargin1();
				nStart=0;
			}
			else
			{
				lOldPos=pBorders[nCol].nPos+pBorders[nCol].nWidth;
				nStart=nCol+1;
				lFences=pBorders[nCol].nWidth;
			}

			for(USHORT i = nStart; i < nBorderCount-1; ++i)
			{
				long lWidth=pBorders[i].nPos-lOldPos;
				lColumns+=lWidth;
				if(lWidth<lMinSpace)
					lMinSpace=lWidth;
				lOldPos=pBorders[i].nPos+pBorders[i].nWidth;
				lFences+=pBorders[i].nWidth;
			}
			long lWidth=GetMargin2()-lOldPos;
			lColumns+=lWidth;
			if(lWidth<lMinSpace)
				lMinSpace=lWidth;
		}
		else
		{
			USHORT nActCol;
			if(nCol==USHRT_MAX) //CalcMinMax fuer LeftMargin
			{
				lOldPos=GetMargin1();
			}
			else
			{
				lOldPos=pBorders[nCol].nPos;
			}
			lColumns=GetMargin2()-lOldPos;
			nActCol=nCol;
			lFences=0;
			while(nActCol<nBorderCount||nActCol==USHRT_MAX)
			{
				USHORT nRight;
				if(nActCol==USHRT_MAX)
				{
					nRight=0;
					while(!(*pColumnItem)[nRight].bVisible)
						nRight++;
				}
				else
					nRight=GetActRightColumn(FALSE, nActCol);
				long lWidth;
				if(nRight!=USHRT_MAX)
				{
					lWidth=pBorders[nRight].nPos-lOldPos;
					lOldPos=pBorders[nRight].nPos;
				}
				else
					lWidth=GetMargin2()-lOldPos;
				nActCol=nRight;
				if(lWidth<lMinSpace)
					lMinSpace=lWidth;
				if(nActCol==USHRT_MAX)
					break;
			}
		}

        _nMaxRight-=(long)(lFences+lMinFrame/(float)lMinSpace*lColumns);
        return _nMaxRight;
	}
	else
	{
		if(pColumnItem->IsTable())
		{
			USHORT nVisCols=0;
			for(USHORT i=GetActRightColumn(FALSE, nCol);i<nBorderCount;)
			{
				if((*pColumnItem)[i].bVisible)
					nVisCols++;
				i=GetActRightColumn(FALSE, i);
			}
			return GetMargin2()-GetMargin1()-(nVisCols+1)*lMinFrame;
		}
		else
		{
			long lWidth=0;
			for(USHORT i=nCol;i<nBorderCount-1;i++)
			{
				lWidth+=lMinFrame+pBorders[i].nWidth;
			}
			return GetMargin2()-GetMargin1()-lWidth;
		}
	}
}
/*-- 29.11.2007 08:24:23---------------------------------------------------
    //#i24363# tab stops relative to indent
  -----------------------------------------------------------------------*/
void SvxRuler::SetTabsRelativeToIndent( BOOL bRel )
{
    pRuler_Imp->bIsTabsRelativeToIndent = bRel;
}

