/* -*- Mode: C++ -*-
   KDChart - a multi-platform charting engine
   */

/****************************************************************************
 ** Copyright (C) 2001-2003 Klar�vdalens Datakonsult AB.  All rights reserved.
 **
 ** This file is part of the KDChart library.
 **
 ** This file may be distributed and/or modified under the terms of the
 ** GNU General Public License version 2 as published by the Free Software
 ** Foundation and appearing in the file LICENSE.GPL included in the
 ** packaging of this file.
 **
 ** Licensees holding valid commercial KDChart licenses may use this file in
 ** accordance with the KDChart Commercial License Agreement provided with
 ** the Software.
 **
 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 **
 ** See http://www.klaralvdalens-datakonsult.se/?page=products for
 **   information about KDChart Commercial License Agreements.
 **
 ** Contact info@klaralvdalens-datakonsult.se if any conditions of this
 ** licensing are not clear to you.
 **
 **********************************************************************/
#include <tqpainter.h>
#include <tqlabel.h>

#include <KDDrawText.h>
#include "KDChartAxesPainter.h"
#include "KDChartAxisParams.h"
#include "KDChartParams.h"

#include <stdlib.h>


/**
  Little helper function returning the number of seconds
  between UTC start date 1970/01/01 00:00 and a given date \c dt.
  The return value is negative for \c dt < 1970/01/01.
  */
int secondsSinceUTCStart( const TQDateTime& dt )
{
    TQDateTime dtStart( TQDate( 1970, 1, 1 ) );
    return dtStart.secsTo( dt );
}


/**
  \class KDChartAxesPainter KDChartAxesPainter.h

  \brief A common base class for classes that implement chart
  painters for chart types ith axes.
  */

/**
  Constructor. Sets up internal data structures as necessary.

  \param params the KDChartParams structure that defines the chart
  */
    KDChartAxesPainter::KDChartAxesPainter( KDChartParams* params ) :
KDChartPainter( params )
{
    // Intentionally left blank.
    // We cannot setup the geometry yet
    // since we do not know the size of the painter.
}

/**
  Destructor.
  */
KDChartAxesPainter::~KDChartAxesPainter()
{
    // intentionally left blank
}


#if COMPAT_TQT_VERSION < 0x030000
TQDateTime dateTimeFromString( const TQString& s ) // only ISODate is allowed
{
    int year(  s.mid(  0, 4 ).toInt() );
    int month( s.mid(  5, 2 ).toInt() );
    int day(   s.mid(  8, 2 ).toInt() );
    TQString t( s.mid( 11 ) );
    int hour(   t.mid( 0, 2 ).toInt() );
    int minute( t.mid( 3, 2 ).toInt() );
    int second( t.mid( 6, 2 ).toInt() );
    int msec(   t.mid( 9, 3 ).toInt() );
    if ( year && month && day )
        return TQDateTime( TQDate( year, month, day ),
                TQTime( hour, minute, second, msec ) );
    else
        return TQDateTime();
}
TQString dateTimeToString( const TQDateTime& dt )  // ISODate is returned
{
    TQString date;
    TQString month(
            TQString::number( dt.date().month() ).rightJustify( 2, '0' ) );
    TQString day(
            TQString::number( dt.date().day() ).rightJustify( 2, '0' ) );
    date = TQString::number( dt.date().year() ) + "-" + month + "-" + day;
    TQString time;
    time.sprintf( "%.2d:%.2d:%.2d",
            dt.time().hour(), dt.time().minute(), dt.time().second() );
    return date + "T" + time;
}
#endif


/**
  ReCalculate the labels based upon given nDelta and nDeltaPix.

  This is necessary to build isometric axes.
  */
void reCalculateLabelTexts(
        TQPainter* painter,
        const KDChartTableDataBase& data,
        const KDChartParams& params,
        uint axisNumber,
        double averageValueP1000,
        double delimLen,
        internal__KDChart__CalcValues& cv )
{
    KDChartAxesPainter::calculateLabelTexts(
            painter,
            data,
            params,
            axisNumber,
            averageValueP1000,
            delimLen,
            // start of reference parameters
            cv.basicPos,
            cv.orig,
            cv.dest,
            cv.pXDeltaFactor,
            cv.pYDeltaFactor,
            cv.pXDelimDeltaFaktor,
            cv.pYDelimDeltaFaktor,
            cv.nSubDelimFactor,
            cv.pDelimDelta,
            cv.nTxtHeight,
            cv.pTextsX,
            cv.pTextsY,
            cv.pTextsW,
            cv.pTextsH,
            cv.textAlign,
            cv.bLogarithmic,
            cv.isDateTime,
            cv.autoDtLabels,
            cv.dtLow,
            cv.dtHigh,
            cv.dtDeltaScale,
            true,
            cv.nDelta,
            cv.nDeltaPix );
            const KDChartAxisParams & para = params.axisParams( axisNumber );
            cv.bSteadyCalc = para.axisSteadyValueCalc();
            cv.bDecreasing = para.axisValuesDecreasing();
            cv.nLow        = para.trueAxisLow();
            cv.nHigh       = para.trueAxisHigh();
}


bool KDChartAxesPainter::calculateAllAxesLabelTextsAndCalcValues(
        TQPainter* painter,
        KDChartTableDataBase* data,
        double areaWidthP1000,
        double areaHeightP1000,
        double& delimLen)
{
    uint iAxis;
    double averageValueP1000 = TQMIN(areaWidthP1000, areaHeightP1000);//( areaWidthP1000 + areaHeightP1000 ) / 2.0;
    //tqDebug("KChart::KDChartAxesPainter::calculateAllAxesLabelTextsAndCalcValues()  averageValueP1000: %f", averageValueP1000);
    // length of little delimiter-marks indicating axis scaling
    delimLen = 20.0 * averageValueP1000; // per mille of area

    // Determine axes calculation values and labels before drawing the axes.

    // step #1: calculate all values independendly from the other axes' values
    for( iAxis = 0;  iAxis < KDCHART_MAX_AXES;  ++iAxis )
    {
        internal__KDChart__CalcValues& cv = calcVal[iAxis];
        cv.processThisAxis = (    params()->axisParams( iAxis ).axisVisible()
                               && KDChartAxisParams::AxisTypeUnknown
                                  != params()->axisParams( iAxis ).axisType() );
        if( cv.processThisAxis ){
            cv.nSubDelimFactor = 0.0;
            cv.pDelimDelta     = 0.0;
            cv.nTxtHeight      = 0.0;
            cv.pTextsX         = 0.0;
            cv.pTextsY         = 0.0;
            cv.pTextsW         = 0.0;
            cv.pTextsH         = 0.0;
            cv.textAlign       = TQt::AlignHCenter | TQt::AlignVCenter;
            cv.isDateTime      = false;
            cv.autoDtLabels    = false;
            calculateLabelTexts( painter,
                                 *data,
                                 *params(),
                                 iAxis,
                                 averageValueP1000,
                                 delimLen,
                                 // start of reference parameters
                                 cv.basicPos,
                                 cv.orig,
                                 cv.dest,
                                 cv.pXDeltaFactor,
                                 cv.pYDeltaFactor,
                                 cv.pXDelimDeltaFaktor,
                                 cv.pYDelimDeltaFaktor,
                                 cv.nSubDelimFactor,
                                 cv.pDelimDelta,
                                 cv.nTxtHeight,
                                 cv.pTextsX,
                                 cv.pTextsY,
                                 cv.pTextsW,
                                 cv.pTextsH,
                                 cv.textAlign,
                                 cv.bLogarithmic,
                                 cv.isDateTime,
                                 cv.autoDtLabels,
                                 cv.dtLow,
                                 cv.dtHigh,
                                 cv.dtDeltaScale );
            const KDChartAxisParams & para = params()->axisParams( iAxis );
            cv.bSteadyCalc = para.axisSteadyValueCalc();
            cv.bDecreasing = para.axisValuesDecreasing();
            cv.nLow        = para.trueAxisLow();
            cv.nHigh       = para.trueAxisHigh();
            cv.nDelta      = para.trueAxisDelta();
            cv.nDeltaPix   = para.trueAxisDeltaPixels();
            cv.pLastX      = cv.dest.x();
            cv.pLastY      = cv.dest.y();
        }
    }

    // step #2: if isometric axes are desired adjust/re-calculate some values
    for ( iAxis = 0; iAxis < KDCHART_MAX_AXES; ++iAxis ){
        internal__KDChart__CalcValues& cv = calcVal[iAxis];
        if(    cv.processThisAxis
                && cv.bSteadyCalc ){
            const KDChartAxisParams & para = params()->axisParams( iAxis );
            const uint isoRef = para.isometricReferenceAxis();
            if(    KDCHART_NO_AXIS != isoRef
                    && iAxis != isoRef
                    && (    KDCHART_MAX_AXES  > isoRef
                         || KDCHART_ALL_AXES == isoRef ) ){
                if( KDCHART_ALL_AXES == isoRef ){
                    uint iAxis2;
                    // first find the axis values to be taken as reference
                    double nDelta          = cv.nDelta;
                    double nDeltaPix       = cv.nDeltaPix;
                    double nSubDelimFactor = cv.nSubDelimFactor;
                    for ( iAxis2 = 0;
                          iAxis2 < KDCHART_MAX_AXES;
                          ++iAxis2 ){
                        internal__KDChart__CalcValues& cv2 = calcVal[iAxis2];
                        if(    cv2.processThisAxis
                            && cv2.bSteadyCalc
                            && (0.0 != cv2.nDelta)
                            && (fabs(cv2.nDeltaPix / cv2.nDelta) < fabs(nDeltaPix / nDelta)) ){
                            if( (nDelta >= 0.0) == (cv2.nDelta >= 0.0) )
                                nDelta = cv2.nDelta;
                            else
                                nDelta = cv2.nDelta * -1.0;
                            if( (nDeltaPix >= 0.0) == (cv2.nDeltaPix >= 0.0) )
                                nDeltaPix = cv2.nDeltaPix;
                            else
                                nDeltaPix = cv2.nDeltaPix * -1.0;
                            if( (nSubDelimFactor >= 0.0) == (cv2.nSubDelimFactor >= 0.0) )
                                nSubDelimFactor = cv2.nSubDelimFactor;
                            else
                                nSubDelimFactor = cv2.nSubDelimFactor * -1.0;
                        }
                    }
                    // now adjust all axes (if necessary)
                    for ( iAxis2 = 0;
                          iAxis2 < KDCHART_MAX_AXES;
                          ++iAxis2 ){
                        internal__KDChart__CalcValues& cv2 = calcVal[iAxis2];
                        if(    cv2.processThisAxis
                            && cv2.bSteadyCalc
                            && (    fabs(cv2.nDelta)    != fabs(nDelta)
                                 || fabs(cv2.nDeltaPix) != fabs(nDeltaPix) ) ){
                            //tqDebug("\nrecalculating scale for axis %x", iAxis2);
                            //tqDebug("cv2.nDelta %f   cv2.nDeltaPix %f       nDelta %f   nDeltaPix %f\n",
                            //        cv2.nDelta,cv2.nDeltaPix,nDelta,nDeltaPix);
                            if( (cv2.nDelta >= 0.0) == (nDelta >= 0.0) )
                                cv2.nDelta = nDelta;
                            else
                                cv2.nDelta = nDelta * -1.0;
                            if( (cv2.nDeltaPix >= 0.0) == (nDeltaPix >= 0.0) )
                                cv2.nDeltaPix = nDeltaPix;
                            else
                                cv2.nDeltaPix = nDeltaPix * -1.0;
                            reCalculateLabelTexts( painter,
                                                   *data,
                                                   *params(),
                                                   iAxis2,
                                                   averageValueP1000,
                                                   delimLen,
                                                   cv2 );
                            if( (cv2.nSubDelimFactor >= 0.0) == (nSubDelimFactor >= 0.0) )
                                cv2.nSubDelimFactor = nSubDelimFactor;
                            else
                                cv2.nSubDelimFactor = nSubDelimFactor * -1.0;
                        }
                    }
                }else{
                    internal__KDChart__CalcValues& cv2 = calcVal[isoRef];
                    // adjust this axis or the other axis (if necessary)
                    if(    cv2.processThisAxis
                            && cv2.bSteadyCalc
                            && (    cv2.nDelta    != cv.nDelta
                                || cv2.nDeltaPix != cv.nDeltaPix ) ){
                        if(    cv2.nDelta > cv.nDelta
                                || (     cv2.nDelta   == cv.nDelta
                                    && cv2.nDeltaPix < cv.nDeltaPix ) ){
                            // adjust this axis
                            //tqDebug("recalculating scale for this axis %x", iAxis);
                            cv.nDelta    = cv2.nDelta;
                            cv.nDeltaPix = cv2.nDeltaPix;
                            reCalculateLabelTexts(
                                    painter,
                                    *data,
                                    *params(),
                                    iAxis,
                                    averageValueP1000,
                                    delimLen,
                                    cv );
                            cv.nSubDelimFactor = cv2.nSubDelimFactor;
                        }else{
                            // adjust the other axis
                            //tqDebug("\nrecalculating scale for other axis %x", isoRef);
                            //tqDebug("cv2.nDelta %f   cv2.nDeltaPix %f       cv.nDelta %f   cv.nDeltaPix %f",
                            //        cv2.nDelta,cv2.nDeltaPix,cv.nDelta,cv.nDeltaPix);
                            cv2.nDelta    = cv.nDelta;
                            cv2.nDeltaPix = cv.nDeltaPix;
                            reCalculateLabelTexts(
                                    painter,
                                    *data,
                                    *params(),
                                    isoRef,
                                    averageValueP1000,
                                    delimLen,
                                    cv2 );
                            cv2.nSubDelimFactor = cv.nSubDelimFactor;
                        }
                    }
                }
            }
        }
    }
    return true;
}


/**
  Paints the actual axes areas.

  \param painter the TQPainter onto which the chart should be painted
  \param data the data that will be displayed as a chart
  */
void KDChartAxesPainter::paintAxes( TQPainter* painter,
        KDChartTableDataBase* data )
{
    if ( !painter || !data || 0 == params() )
        return ;

    const bool bMultiRowBarChart = KDChartParams::Bar == params()->chartType() &&
                                   KDChartParams::BarMultiRows == params()->barChartSubType();

    double areaWidthP1000 = _logicalWidth / 1000.0;
    double areaHeightP1000 = _logicalHeight / 1000.0;
    double averageValueP1000 = TQMIN(areaWidthP1000, areaHeightP1000);//( areaWidthP1000 + areaHeightP1000 ) / 2.0;
    // length of little delimiter-marks indicating axis scaling
    double delimLen;

//tqDebug("-------------------------------------------------------------------------------------");

    calculateAllAxesLabelTextsAndCalcValues( painter, data, areaWidthP1000, areaHeightP1000, delimLen );


    // Now the labels are known, so let us paint the axes...
    painter->save();
    painter->setPen( TQt::NoPen );

    bool screenOutput = params()->optimizeOutputForScreen();
    uint iAxis;

    for ( iAxis = 0; iAxis < KDCHART_MAX_AXES; ++iAxis ){
        internal__KDChart__CalcValues& cv = calcVal[iAxis];
        if( cv.processThisAxis ){

            const KDChartAxisParams & para = params()->axisParams( iAxis );

            internal__KDChart__CalcValues& cv = calcVal[iAxis];

            const TQColor labelsColor( para.axisLabelsColor() );

            // Debugging axis areas:
            //painter->fillRect(para.axisTrueAreaRect(), TQt::yellow);

            uint lineWidth = 0 <= para.axisLineWidth()
                ? para.axisLineWidth()
                : -1 * static_cast < int > ( para.axisLineWidth()
                        * averageValueP1000 );
            ( ( KDChartAxisParams& ) para ).setAxisTrueLineWidth( lineWidth );

            uint gridLineWidth
                = ( KDCHART_AXIS_GRID_AUTO_LINEWIDTH
                        == para.axisGridLineWidth() )
                ? lineWidth
                : (   ( 0 <= para.axisGridLineWidth() )
                        ? para.axisGridLineWidth()
                        : -1 * static_cast < int > ( para.axisGridLineWidth()
                            * averageValueP1000 ) );

            uint gridSubLineWidth
                = ( KDCHART_AXIS_GRID_AUTO_LINEWIDTH
                        == para.axisGridSubLineWidth() )
                ? lineWidth
                : (   ( 0 <= para.axisGridSubLineWidth() )
                        ? para.axisGridSubLineWidth()
                        : -1 * static_cast < int > ( para.axisGridSubLineWidth()
                            * averageValueP1000 ) );

            // Magic to find out axis scaling factors and labels text height
            // =============================================================
            //                                             - khz, 02/24/2001
            //
            // 1st Calculate the axis label texts height regarding to
            //     user-defined per-axis settings.
            //
            // 2nd This height is given to calculateLabelTexts() to
            //     calculate the delimiter and sub-delimiter distances as
            //     well as the axis scaling factors.
            //     If neccessary and possible the short replacement strings
            //     are taken that might have been specified by the user.
            //     - see KDChartAxisParams::setAxisLabelStringLists() -
            //
            // 3rd Before displaying the texts we make sure they fit into
            //     their space, if needed we will do the following
            //     in order to avoid clipping of text parts:
            //
            //     (a) ABSCISSA axes only: rotate the texts in 5 steps
            //                             until they are drawn vertically
            //
            //     (b) further reduce the texts' font height down to 6pt
            //         .
            //
            // If the texts *still* don't fit into their space, we are lost
            // and they will be clipped. Such is live.
            //
            // Why all this?
            //
            // Because I do not believe in axis areas growing and shrinking
            // regarding to long or short label texts: start such behaviour
            // and become mad.
            //
            // Better plan: ask the user to specify a way how to abbreviate
            //              label texts (e.g. by writing "200" instead
            //              of that wide and unreadable  "200,000.00")
            //
            //
            //   F E A T U R E   P L A N N E D   F O R   F U T U R E . . .
            //
            //

            // Note: The labels-touch-edges flag may have been set to true
            //       inside the calculateLabelTexts() function.
            bool bTouchEdges = para.axisLabelsTouchEdges();

            // NOTE: The steady-value-calc flag may have been set to true
            //       inside the calculateLabelTexts() function
            //       by a special setAxisLabelTextParams() call,
            //       therefor we do not store its value before calling that function.
            if( cv.bLogarithmic )
                cv.nSubDelimFactor = 0.1;

            const double nUsableAxisHeight = cv.pTextsH;
            const double nUsableAxisWidth  = cv.pTextsW;

            const bool isHorizontalAxis
                = (KDChartAxisParams::AxisPosBottom == cv.basicPos) ||
                (KDChartAxisParams::AxisPosTop    == cv.basicPos);

            TQStringList* labelTexts = ( TQStringList* ) para.axisLabelTexts();
            uint nLabels = ( 0 != labelTexts )
                ? labelTexts->count()
                : 0;
            // start point of 1st delimiter on the axis-line == grid-start
            TQPoint p1( cv.orig );
            // end point of 1st delimiter near the label text
            TQPoint p2( cv.orig );
            // end point of small sub-delimiter
            TQPoint p2a( cv.orig );
            // start point of 1st grid-line (beginnig at the axis)
            TQPoint pGA( cv.orig );
            // end point of 1st grid-line at the other side of the chart
            TQPoint pGZ( cv.orig );
            // start point of zero-line, this is often identical with p1
            // but will be different in case of shifted zero-line
            double axisZeroLineStartX = p1.x();
            double axisZeroLineStartY = p1.y();

            p2.setX(  p2.x()  + static_cast < int > ( cv.pXDelimDeltaFaktor * delimLen ) );
            p2.setY(  p2.y()  + static_cast < int > ( cv.pYDelimDeltaFaktor * delimLen ) );
            p2a.setX( p2a.x() + static_cast < int > ( cv.pXDelimDeltaFaktor * delimLen * 2.0 / 3.0 ) );
            p2a.setY( p2a.y() + static_cast < int > ( cv.pYDelimDeltaFaktor * delimLen * 2.0 / 3.0 ) );
            pGZ.setX( pGZ.x() - static_cast < int > ( cv.pXDelimDeltaFaktor * (_dataRect.width()  - 1) ) );
            pGZ.setY( pGZ.y() - static_cast < int > ( cv.pYDelimDeltaFaktor * (_dataRect.height() - 1) ) );

            if ( nLabels ) {
                // Sometimes the first or last labels partially reach out of
                // their axis area: we allow this
                const bool oldClippingFlag = painter->hasClipping();
                painter->setClipping( false );

                if( para.hasAxisFirstLabelText() )
                    labelTexts->first() = para.axisFirstLabelText();
                if( para.hasAxisLastLabelText() )
                    labelTexts->last() = para.axisLastLabelText();

                const double pXDelta = cv.pXDeltaFactor * cv.pDelimDelta;
                const double pYDelta = cv.pYDeltaFactor * cv.pDelimDelta;

                // draw label texts and delimiters and grid
                painter->setPen( TQPen( para.axisLineColor(),
                                 lineWidth ) );

                const TQString formatDT = cv.isDateTime
                    ? para.axisLabelsDateTimeFormat()
                    : TQString();

                // calculate font size
                const double minTextHeight = para.axisLabelsFontMinSize();
                //tqDebug("KChart::KDChartAxesPainter::paintAxes()  cv.nTxtHeight: %f   minTextHeight: %f", cv.nTxtHeight, minTextHeight);
                if ( minTextHeight > cv.nTxtHeight )
                    cv.nTxtHeight = minTextHeight;
                TQFont actFont( para.axisLabelsFont() );
                if ( para.axisLabelsFontUseRelSize() ) {
                    actFont.setPixelSize( static_cast < int > ( cv.nTxtHeight ) );
                }
                painter->setFont( actFont );
                TQFontMetrics fm( painter->fontMetrics() );

                int nLeaveOut = 0;
                int nRotation = 0;

                // Draw simple string labels
                // or calculate and draw nice Date/Time ruler?
                TQString commonDtHeader;
                if( cv.autoDtLabels ){
                    cv.textAlign = TQt::AlignCenter;
                    //tqDebug(dtLow.toString("\nd.MM.yyyy  -  h:mm:ss" ));
                    //tqDebug(dtHigh.toString( "d.MM.yyyy  -  h:mm:ss" ));
                    const TQDate& dLow  = cv.dtLow.date();
                    const TQTime& tLow  = cv.dtLow.time();
                    const TQDate& dHigh = cv.dtHigh.date();
                    const TQTime& tHigh = cv.dtHigh.time();
                    bool sameYear   = dLow.year() == dHigh.year();
                    bool sameMonth  = sameYear   && (dLow.month()  == dHigh.month() );
                    bool sameDay    = sameMonth  && (dLow.day()    == dHigh.day()   );
                    bool sameHour   = sameDay    && (tLow.hour()   == tHigh.hour()  );
                    bool sameMinute = sameHour   && (tLow.minute() == tHigh.minute());
                    bool sameSecond = sameMinute && (tLow.second() == tHigh.second());
                    if( sameDay ){
                        commonDtHeader = TQString::number( dLow.day() )
                            + ". "
#if COMPAT_TQT_VERSION >= 0x030000
                            + TQDate::longMonthName( dLow.month() )
#else
                            + dLow.monthName( dLow.month() )
#endif
                            + ' '
                            + TQString::number( dLow.year() );
                        if( sameHour ){
                            commonDtHeader += "  /  "
                                + TQString::number( tLow.hour() )
                                + ':';
                            if( sameMinute ){
                                if( 10 > tLow.minute() )
                                    commonDtHeader += '0';
                                commonDtHeader += TQString::number( tLow.minute() )
                                    + ':';
                                if( sameSecond ){
                                    if( 10 > tLow.second() )
                                        commonDtHeader += '0';
                                    commonDtHeader += TQString::number( tLow.second() );
                                    //
                                    // " Huston, we have a problem! "
                                    //
                                    // Currently we don't support milli secs
                                    // since they will not fit into a double
                                    // when looking at years...
                                    //
                                    // This will be improved in release 2.0.
                                    //                     (khz, 2002/07/12)
                                }
                                else
                                    commonDtHeader += "00";
                            }
                            else
                                commonDtHeader += "00";
                        }
                    }else if( sameMonth )
#if COMPAT_TQT_VERSION >= 0x030000
                        commonDtHeader = TQDate::longMonthName( dLow.month() )
#else
                            commonDtHeader = dLow.monthName( dLow.month() )
#endif
                            + ' '
                            + TQString::number( dLow.year() );
                    else if( sameYear )
                        commonDtHeader = TQString::number( dLow.year() );
                    //if( !commonDtHeader.isEmpty() )
                    //    tqDebug(commonDtHeader);
                }else{
                    // make sure all label texts fit into their space
                    // by rotating and/or shrinking the texts
                    // or by leaving out some of the labels
                    TQRegion unitedRegions;

                    const bool tryLeavingOut =
                        ( para.axisValueLeaveOut() == KDCHART_AXIS_LABELS_AUTO_LEAVEOUT )
                        || ( 0 < para.axisValueLeaveOut() );
                    if( tryLeavingOut ) {
                        if( para.axisValueLeaveOut()
                                == KDCHART_AXIS_LABELS_AUTO_LEAVEOUT )
                            nLeaveOut = 0;
                        else
                            nLeaveOut = para.axisValueLeaveOut();

                    }
                    else
                        nLeaveOut = 0;
                    int stepWidthLeaveOut = nLeaveOut+1;
                    int iStepsLeaveOut = 0;

                    const bool tryShrinking = !para.axisLabelsDontShrinkFont();
                    const double nInitialTxtHeight = cv.nTxtHeight;

                    const bool tryRotating = isHorizontalAxis
                        && !para.axisLabelsDontAutoRotate();
                    const int nInitialRotation = (    (360 >  para.axisLabelsRotation())
                            && (270 <= para.axisLabelsRotation()) )
                        ? para.axisLabelsRotation()
                        : 0;
                    nRotation = nInitialRotation;

                    bool textsDontFitIntoArea;
                    bool textsOverlapping;
                    bool textsMatching;
                    do {
                        textsDontFitIntoArea = false;
                        textsOverlapping = false;
                        textsMatching = true;
                        // test if all texts match without mutually overlapping
                        unitedRegions = TQRegion();
                        int align = nRotation
                            ? (TQt::AlignRight | TQt::AlignVCenter) // adjusting for rotation
                            : cv.textAlign;
                        TQPoint anchor(200,200);
                        int iLeaveOut = 0;
                        double iLabel=0.0;
                        for ( TQStringList::Iterator it = labelTexts->begin();
                                it != labelTexts->end();
                                ++it ) {
                            iLabel += 1.0;
                            if( iLeaveOut < nLeaveOut ) {
                                ++iLeaveOut;
                            } else {
                                iLeaveOut = 0;
                                anchor.setX( p2.x() + static_cast < int > ( pXDelta * (iLabel - 0.5) ) );
                                anchor.setY( p2.y() + static_cast < int > ( pYDelta * (iLabel - 0.5) ) );

                                // allow for shearing and/or scaling of the painter
                                anchor = painter->worldMatrix().map( anchor );

                                TQString text;
                                if( cv.isDateTime ){
#if COMPAT_TQT_VERSION >= 0x030000
                                    TQDateTime dt( TQDateTime::fromString( *it,
                                                Qt::ISODate ) );
                                    text = dt.toString( formatDT );
#else
                                    TQDateTime dt( dateTimeFromString( *it ) );
                                    text = dt.toString();
#endif
                                }else{
                                    text = *it;
                                }
                                KDDrawTextRegionAndTrueRect infosKDD =
                                    KDDrawText::measureRotatedText( painter,
                                            nRotation,
                                            anchor,
                                            text,
                                            0,
                                            align,
                                            &fm,
                                            false,
                                            false,
                                            15 );
                                if( infosKDD.region.boundingRect().left()
                                        < params()->globalLeadingLeft()+1 ){
                                    textsMatching = false;
                                    textsDontFitIntoArea = true;
                                    //tqDebug("too wide");
                                }
                                //tqDebug("nRotation: %i",nRotation);
                                TQRegion sectReg;
                                if( nRotation ){
                                    //tqDebug("test 1");
                                    sectReg = infosKDD.region.intersect( unitedRegions );
                                }else{
                                    //tqDebug("test 2");
                                    TQRect rect( infosKDD.region.boundingRect() );
                                    rect.addCoords(-2,-2,2,2);
                                    TQRegion biggerRegion( rect );
                                    sectReg = biggerRegion.intersect( unitedRegions );
                                }
                                if ( sectReg.isEmpty() )
                                    unitedRegions = unitedRegions.unite( infosKDD.region );
                                else {
                                    textsMatching = false;
                                    textsOverlapping = true;
                                    //tqDebug("label regions are intersecting");
                                    break;
                                }
                            }
                        }
/*
                        if(!iAxis){

                          tqDebug("nTxtHeight: "+TQString::number(cv.nTxtHeight)+"   nRotation: "+TQString::number(nRotation)+
                          "   matching: "+TQString(textsMatching ? "TRUE":"FALSE"));
                          tqDebug("nUsableAxisHeight: %f,  unitedRegions.boundingRect().height(): %i ",
                              nUsableAxisHeight, unitedRegions.boundingRect().height());
                          }
*/
                        if( isHorizontalAxis ) {
                            if( nUsableAxisHeight < unitedRegions.boundingRect().height() ){
                                //textsMatching = false;
                                textsDontFitIntoArea = true;
                            }
                        } else {
                            if( nUsableAxisWidth < unitedRegions.boundingRect().width() ){
                                //tqDebug("textsMatching: %s",textsMatching ? "TRUE" : "FALSE");
                                textsMatching = false;
                                textsDontFitIntoArea = true;
                                //tqDebug("too wide");
                            }
                            //else tqDebug("not too wide");
                        }
                        /*
                        if(textsMatching && !iAxis){
                          tqDebug("--------------------------");
                          tqDebug("nTxtHeight: "+TQString::number(cv.nTxtHeight)+"   nRotation: "+TQString::number(nRotation));
                          tqDebug("matching");
                          }
                        */
                        if( !textsMatching ) {
                            bool rotatingDoesNotHelp = false;
                            // step 1: In case of labels being too wide
                            //         to fit into the available space
                            //         we try to rotate the texts in 5 steps.
                            //         This is done for Abscissa axes only.
                            if ( tryRotating ) {
                                //tqDebug("try rotating");
                                // The following is designed for horizontal axes
                                // since we currently don't support label rotating
                                // on vertical axes.             (khz, 2002/08/15)
                                if( textsDontFitIntoArea  ){
                                    if( nRotation != nInitialRotation ){
                                      //textsDontFitIntoArea = false;
                                      nRotation = nInitialRotation;
                                    }
                                    rotatingDoesNotHelp = true;
                                    //tqDebug("rotating does not help (a)");
                                }
                                else{
                                    if( nRotation ) {
                                        if( 270 < nRotation ) {
                                            nRotation -= 5;
                                            if( 270 > nRotation )
                                                nRotation = 270; // drawing vertically now
                                        } else {
                                            if( nInitialRotation )
                                                nRotation = nInitialRotation;
                                            else
                                                nRotation = 0; // reset rotation to ZERO
                                            rotatingDoesNotHelp = true;
                                            //tqDebug("rotating does not help (b)");
                                        }
                                    } else {
                                        if( nInitialRotation )
                                            nRotation = nInitialRotation;
                                        else
                                            nRotation = 350; // (re-)start rotating with -10
                                    }
                                }
                            }
                            if ( !tryRotating || rotatingDoesNotHelp ) {

                                // step 2: In case of labels being too wide and
                                //         rotating them did not help or is forbidden
                                //         we try to reduce the font size.
                                if ( tryShrinking && (minTextHeight < cv.nTxtHeight) ) {
                                    //tqDebug("try shrinking");
                                    cv.nTxtHeight -= 1.0;
                                    if ( minTextHeight > cv.nTxtHeight )
                                        cv.nTxtHeight = minTextHeight;
                                } else {

                                    // step 3: In case reducing the font size is not possible
                                    //         any further (or is not allowed at all) we try
                                    //         to leave out some of the labels.
                                    if(    tryLeavingOut
                                        && textsOverlapping
                                        && (nLeaveOut+1 < static_cast < int > ( nLabels ) ) ) {
                                        //tqDebug("try leaving out");
                                        ++iStepsLeaveOut;
                                        //if(!iAxis)tqDebug("iStepsLeaveOut: %i", iStepsLeaveOut);
                                        nLeaveOut =
                                            iStepsLeaveOut*stepWidthLeaveOut - 1;
                                        if( tryShrinking )
                                            cv.nTxtHeight = nInitialTxtHeight;
                                    }
                                    else
                                        break;
                                }
                                if( tryShrinking ) {
                                    actFont.setPixelSize( static_cast < int > ( cv.nTxtHeight ) );
                                    //tqDebug("axis:     cv.nTxtHeight: %f", iAxis, cv.nTxtHeight);
                                    painter->setFont( actFont );
                                    fm = painter->fontMetrics();
                                }
                            }
                        }
//tqDebug("nLeaveOut: %i",nLeaveOut);
                    } while( !textsMatching );

                    if( nRotation ){
                        // The following is designed for horizontal axes
                        // since we currently don't support label rotating
                        // on vertical axes.             (khz, 2002/08/15)
                        //int oldVert = textAlign & (TQt::AlignTop | TQt::AlignBottom);
                        //int steepness = abs(270-nRotation);
                        //bool steep = (30 > steepness);
                        cv.textAlign = TQt::AlignRight | TQt::AlignVCenter;  // adjusting for rotation
                        //cv.textAlign = TQt::AlignRight | TQt::AlignVCenter;
                        /*  ( steep ? TQt::AlignVCenter : oldVert);*/
                        //int dx = pXDelta / 2 - steep ? (nTxtHeight / 4) : 0;
                        double dx = (pXDelta / 2) - (cv.nTxtHeight / 4);
                        double dy = /*steep ? 0 : */(cv.nTxtHeight / 2.0);
                        cv.pTextsX += dx;
                        cv.pTextsY += dy;
                    }
                    /*
                       TQBrush oldBrush = painter->brush();
                       TQRegion oldReg = painter->clipRegion();//TQPainter::CoordPainter);
                       painter->setBrush(TQt::Dense4Pattern);
                       painter->setClipRegion(unitedRegions);//,TQPainter::CoordPainter);
                       painter->drawRect(0,0,2000,1500);
                       painter->setClipRegion(oldReg);//,TQPainter::CoordPainter);
                       painter->setBrush(oldBrush);
                       */
                    /*if(!iAxis){
                      tqDebug("==========================");
                      tqDebug("nTxtHeight: "+TQString::number(nTxtHeight)+"   nRotation: "+TQString::number(nRotation));
                      tqDebug(textsMatching ? "matching":"not matching");
                      }*/
                }

                painter->setFont( actFont );
                fm = TQFontMetrics( painter->fontMetrics() );

                // set colour of grid pen
                TQPen gridPen, leaveOutGridPen;
                if( para.axisShowGrid() && !bMultiRowBarChart )
                    gridPen.setColor( para.axisGridColor() );

                const int pXDeltaDiv2 = static_cast < int > ( pXDelta / 2.0 );
                const int pYDeltaDiv2 = static_cast < int > ( pYDelta / 2.0 );

                bool bDrawAdditionalSubGridLine = false;
                double pGXMicroAdjust = 0.0;
                double pGYMicroAdjust = 0.0;
                if ( !bTouchEdges ) {
                    // adjust the data values pos
                    p1.setX( p1.x() + pXDeltaDiv2 );
                    p1.setY( p1.y() + pYDeltaDiv2 );
                    p2.setX( p2.x() + pXDeltaDiv2 );
                    p2.setY( p2.y() + pYDeltaDiv2 );
                    // adjust the short delimiter lines pos
                    p2a.setX( p2a.x() + pXDeltaDiv2 );
                    p2a.setY( p2a.y() + pYDeltaDiv2 );
                    // adjust grid lines pos
                    bDrawAdditionalSubGridLine =
                        isHorizontalAxis && !
                        params()->axisParams(
                                KDChartAxisParams::AxisPosRight ).axisVisible() &&
                        !bMultiRowBarChart;
                    pGA.setX( pGA.x() + pXDeltaDiv2 );
                    pGA.setY( pGA.y() + pYDeltaDiv2 );
                    pGZ.setX( pGZ.x() + pXDeltaDiv2 );
                    pGZ.setY( pGZ.y() + pYDeltaDiv2 );
                    // fine-tune grid line pos for grid of vertical axis
                    if( KDChartAxisParams::AxisTypeNORTH == para.axisType() ) {
                        pGXMicroAdjust = cv.pXDeltaFactor * lineWidth / 2.0;
                        pGYMicroAdjust = cv.pYDeltaFactor * lineWidth / 2.0;
                    }
                }
                double x1, y1, x2, y2, xGA, yGA, xGZ, yGZ,
                p1X, p1Y, p2X, p2Y, pGAX, pGAY, pGZX, pGZY, xT, yT;

                double pXSubDelimDelta = pXDelta * cv.nSubDelimFactor;
                double pYSubDelimDelta = pYDelta * cv.nSubDelimFactor;

                if (    !cv.autoDtLabels
                        && 0.0 != cv.nSubDelimFactor
                        && para.axisShowSubDelimiters()
                        && para.axisLabelsVisible()
                        && !nLeaveOut ) {
                    TQPen pen( para.axisLineColor(), static_cast < int > ( 0.5 * lineWidth ) );
                    uint penWidth = pen.width();
                    bool bOk = true;

                    if( cv.bLogarithmic )
                        cv.nSubDelimFactor = 0.1;

                    while ( fabs( ( pXDelta + pYDelta ) * cv.nSubDelimFactor / 6.0 )
                            <= 1.0 + penWidth
                            && bOk ) {
                        if ( 0 < penWidth ) {
                            --penWidth;
                            pen.setWidth( penWidth );
                        }else{
                            if( cv.bLogarithmic ){
                                break; // there is nothing we can do: we allways
                                // want 10 sub-delims per logarithmic step
                            }else{
                                if ( 0.5 != cv.nSubDelimFactor ) {
                                    // emercency: reduce number of sub-scaling
                                    cv.nSubDelimFactor = 0.5;

                                    pXSubDelimDelta = pXDelta * cv.nSubDelimFactor;
                                    pYSubDelimDelta = pYDelta * cv.nSubDelimFactor;
                                } else
                                    bOk = false;
                            }
                        }
                    }
                    if ( bOk ) {
                        x1 = p1.x();
                        y1 = p1.y();
                        x2 = p2a.x();
                        y2 = p2a.y();
                        xGA = pGA.x();
                        yGA = pGA.y();
                        xGZ = pGZ.x();
                        yGZ = pGZ.y();
                        p1X = x1;
                        p1Y = y1;
                        p2X = x2;
                        p2Y = y2;
                        pGAX = xGA;
                        pGAY = yGA;
                        pGZX = xGZ;
                        pGZY = yGZ;

                        // set up grid pen for drawing the sub-grid lines
                        const TQPen oldGridPen( gridPen );
                        if ( para.axisShowGrid() ) {
                            gridPen.setColor( para.axisGridSubColor() );
                            gridPen.setWidth( gridSubLineWidth );
                            gridPen.setStyle( para.axisGridSubStyle() );
                        }
                        const TQPen oldPen( painter->pen() );
                        painter->setPen( pen );
                        double nSubDelim = ( labelTexts->count() - 1 )
                            / cv.nSubDelimFactor;

                        //tqDebug("subDelim: %f",
                        modf( nSubDelim, &nSubDelim );

                        int logarithCnt = 1;
                        double xLogarithOffs = 0;
                        double yLogarithOffs = 0;
                        double dDummy;
                        double mainDelim = 0.0;
                        bool paint = true;

                        for ( double iDelim = 1.0;
                                iDelim <= nSubDelim + 1.0;
                                iDelim += 1.0, logarithCnt++ ) {
                          // test if it is a sub or a main delimiter
                            if ( mainDelim > 0.0 )
                              paint = true;
                            else
                              paint = false;

                            if ( cv.bLogarithmic )
                            {
                                if ( logarithCnt == 11 )
                                {
                                    xLogarithOffs +=
                                        pXDelta * log10( 10*cv.nSubDelimFactor*10 );
                                    yLogarithOffs +=
                                        pYDelta * log10( 10*cv.nSubDelimFactor*10 );
                                    logarithCnt=1;
                                }

                                pXSubDelimDelta =
                                    pXDelta * log10( 10*cv.nSubDelimFactor*logarithCnt );
                                pYSubDelimDelta =
                                    pYDelta * log10( 10*cv.nSubDelimFactor*logarithCnt );
                            }

                            if ( para.axisShowGrid() && !bMultiRowBarChart) {
                                // draw the sub grid line
                                if( 0.0 != modf((iDelim-1.0) * cv.nSubDelimFactor, &dDummy) )

                                    saveDrawLine( *painter,
                                                  TQPoint( static_cast<int>( pGAX - pGXMicroAdjust ),
                                                          static_cast<int>( pGAY - pGYMicroAdjust ) ),
                                                  TQPoint( static_cast<int>( pGZX - pGXMicroAdjust ),
                                                          static_cast<int>( pGZY - pGYMicroAdjust ) ),
                                                  gridPen );

                                if( cv.bLogarithmic ){
                                    pGAX = xGA + pXSubDelimDelta + xLogarithOffs;
                                    pGAY = yGA + pYSubDelimDelta + yLogarithOffs;
                                    pGZX = xGZ + pXSubDelimDelta + xLogarithOffs;
                                    pGZY = yGZ + pYSubDelimDelta + yLogarithOffs;
                                }else{
                                    pGAX = xGA + iDelim * pXSubDelimDelta;
                                    pGAY = yGA + iDelim * pYSubDelimDelta;
                                    pGZX = xGZ + iDelim * pXSubDelimDelta;
                                    pGZY = yGZ + iDelim * pYSubDelimDelta;
                                    /*
                                    if( !modf(iDelim * cv.nSubDelimFactor, &dDummy) ){
                                       pGAX = xGA + (iDelim * cv.nSubDelimFactor) * pXDelta;
                                       pGAY = yGA + (iDelim * cv.nSubDelimFactor) * pYDelta;
                                       pGZX = xGZ + (iDelim * cv.nSubDelimFactor) * pXDelta;
                                       pGZY = yGZ + (iDelim * cv.nSubDelimFactor) * pYDelta;
                                    }
                                    */
                                }
                            }


                            // draw the short delimiter line
                            // PENDING: Michel - make sure not to draw the sub-delimiters over the main ones.
                            // by testing if it is a sub delimiter or a main one
                            if ( paint )
                            painter->drawLine( TQPoint( static_cast<int>( p1X ), static_cast<int>( p1Y ) ),
                                               TQPoint( static_cast<int>( p2X ), static_cast<int>( p2Y ) ) );

                            mainDelim += 1.0;


                            if( cv.bLogarithmic ){
                                p1X = x1 + pXSubDelimDelta + xLogarithOffs;
                                p1Y = y1 + pYSubDelimDelta + yLogarithOffs;
                                p2X = x2 + pXSubDelimDelta + xLogarithOffs;
                                p2Y = y2 + pYSubDelimDelta + yLogarithOffs;
                            }else{
                                p1X = x1 + iDelim * pXSubDelimDelta;
                                p1Y = y1 + iDelim * pYSubDelimDelta;
                                p2X = x2 + iDelim * pXSubDelimDelta;
                                p2Y = y2 + iDelim * pYSubDelimDelta;
                            }

                            if ( mainDelim >= nSubDelim/(labelTexts->count() -1) )
                              mainDelim = 0.0;


                        } // for
                        // draw additional sub grid line
                        if( bDrawAdditionalSubGridLine
                                && para.axisShowGrid() ) {

                            saveDrawLine( *painter,
                                          TQPoint( static_cast<int>( pGAX - pGXMicroAdjust ),
                                                  static_cast<int>( pGAY - pGYMicroAdjust ) ),
                                          TQPoint( static_cast<int>( pGZX - pGXMicroAdjust ),
                                                  static_cast<int>( pGZY - pGYMicroAdjust ) ),
                                                  gridPen );

                        }
                        painter->setPen( oldPen );
                        gridPen = oldGridPen;
                    }
                }
                x1 = p1.x();
                y1 = p1.y();
                x2 = p2.x();
                y2 = p2.y();
                xGA = pGA.x();
                yGA = pGA.y();
                xGZ = pGZ.x();
                yGZ = pGZ.y();
                p1X = x1;
                p1Y = y1;
                p2X = x2;
                p2Y = y2;
                pGAX = xGA;
                pGAY = yGA;
                pGZX = xGZ;
                pGZY = yGZ;
                xT = cv.pTextsX;
                yT = cv.pTextsY;
                // set up grid pen for drawing the normal grid lines
                if ( para.axisShowGrid() ) {
                    gridPen.setWidth( gridLineWidth );
                    gridPen.setStyle( para.axisGridStyle() );
                    // if axis not visible draw the 1st grid line too
                    if( !para.axisLineVisible() )
		      saveDrawLine( *painter, cv.orig, cv.dest, gridPen );
                }
                if( nLeaveOut ) {
                    leaveOutGridPen = gridPen;
                    leaveOutGridPen.setWidth( gridLineWidth / 2 );
                    leaveOutGridPen.setStyle( Qt::DotLine );
                }
                //  =========================================================
                //  ||  The labels and delimiters and grid printing loops  ||
                //  =========================================================
                //
                double iLabel = 0.0;
                if( cv.autoDtLabels )
                {
                    /*
                       tqDebug("\ndtLow: %i %i %i    %i:%i:%i",
                       dtLow.date().year(),
                       dtLow.date().month(),
                       dtLow.date().day(),
                       dtLow.time().hour(),
                       dtLow.time().minute(),
                       dtLow.time().second());
                       tqDebug("dtHigh: %i %i %i    %i:%i:%i",
                       dtHigh.date().year(),
                       dtHigh.date().month(),
                       dtHigh.date().day(),
                       dtHigh.time().hour(),
                       dtHigh.time().minute(),
                       dtHigh.time().second());
                       */
                    int pXD = static_cast <int> (cv.pXDelimDeltaFaktor * 1.25 * (cv.nTxtHeight+4));
                    int pYD = static_cast <int> (cv.pYDelimDeltaFaktor * 1.25 * (cv.nTxtHeight+4));
                    int orgXD = pXD;
                    int orgYD = pYD;
                    cv.pTextsW = fabs( (0.0 == pXDelta) ? pXD : pXDelta );
                    cv.pTextsH = fabs( (0.0 == pYDelta) ? pYD : pYDelta );

                    double pSecX     = x1;
                    double pSecY     = y1;
                    bool   secPaint= false;
                    double pMinX     = x1;
                    double pMinY     = y1;
                    bool   minPaint= false;
                    double pHourX    = x1;
                    double pHourY    = y1;
                    bool   hourPaint= false;
                    double pDayX     = x1;
                    double pDayY     = y1;
                    bool   dayPaint= false;
                    /* khz: currently not used
                       double pWeekX    = x1;
                       double pWeekY    = y1;
                       bool   weekPaint= false;
                       */
                    double pMonthX   = x1;
                    double pMonthY   = y1;
                    bool   monthPaint= false;
                    /*double pQuarterX = x1;
                      double pQuarterY = y1;
                      bool   minPaint= false;
                      */
                    double pYearX    = x1;
                    double pYearY    = y1;
                    bool   yearPaint= false;

                    double pXYDelta = fabs( pXDelta ) + fabs( pYDelta );

                    if( 0.0 == para.trueAxisDeltaPixels() )
                        ( ( KDChartAxisParams& ) para ).setTrueAxisDeltaPixels( TQMIN(_logicalWidth, _logicalHeight) / 150 );

                    bool dtGoDown = cv.dtLow > cv.dtHigh;
                    int  mult = dtGoDown ? -1 : 1;
                    const TQDateTime& startDt = dtGoDown ? cv.dtHigh : cv.dtLow;

                    ( ( KDChartAxisParams& ) para ).setAxisDtLowPos( x1, y1 );
                    // adjust stored dt-low and scale settings
                    ( ( KDChartAxisParams& ) para ).setTrueAxisDtLow( startDt );
                    ( ( KDChartAxisParams& ) para ).setTrueAxisDtScale( cv.dtDeltaScale );

                    int gridDX = pGZ.x() - pGA.x();
                    int gridDY = pGZ.y() - pGA.y();
                    if ( para.axisShowGrid() ) {
                        gridPen.setColor( para.axisGridColor() );
                        gridPen.setWidth( gridLineWidth );
                        gridPen.setStyle( para.axisGridStyle() );
                    }
                    TQPen subGridPen(    gridPen.color(), 1, para.axisGridStyle() );
                    TQPen subSubGridPen( gridPen.color(), 1, para.axisGridSubStyle() );
                    TQPen pen = subGridPen;

                    TQDateTime dt(    startDt );
                    TQDateTime newDt( startDt );
                    for( uint i=1; i <= nLabels; ++i ){
                        switch( cv.dtDeltaScale ) {
                            case KDChartAxisParams::ValueScaleSecond:
                                dtAddSecs( dt, 1 * mult, newDt );
                                break;
                            case KDChartAxisParams::ValueScaleMinute:
                                dtAddSecs( dt, 60 * mult, newDt );
                                break;
                            case KDChartAxisParams::ValueScaleHour:
                                dtAddSecs( dt, 3600 * mult, newDt );
                                break;
                            case KDChartAxisParams::ValueScaleDay:
                                dtAddDays( dt, 1 * mult, newDt );
                                break;
                            case KDChartAxisParams::ValueScaleWeek:
                                dtAddDays( dt, 7 * mult, newDt );
                                break;
                            case KDChartAxisParams::ValueScaleMonth:
                                dtAddMonths( dt,1 * mult, newDt );
                                break;
                            case KDChartAxisParams::ValueScaleQuarter:
                                dtAddMonths( dt,3 * mult, newDt );
                                break;
                            case KDChartAxisParams::ValueScaleYear:
                                dtAddYears( dt, 1 * mult, newDt );
                                break;
                            default:
                                dtAddDays( dt, 1 * mult, newDt );
                                break;
                        }
                        const TQDateTime& testDt
                            = dtGoDown
                            ? (   ( newDt < cv.dtLow )
                                    ? cv.dtLow
                                    : newDt )
                            : (   ( newDt > cv.dtHigh )
                                    ? cv.dtHigh
                                    : newDt );
                        /*
                           tqDebug("    dt: %i %i %i    %i:%i:%i",
                           newDt.date().year(),newDt.date().month(),newDt.date().day(),
                           newDt.time().hour(),newDt.time().minute(),newDt.time().second());
                           tqDebug("testDt: %i %i %i    %i:%i:%i",
                           testDt.date().year(),testDt.date().month(),testDt.date().day(),
                           testDt.time().hour(),testDt.time().minute(),testDt.time().second());
                           */
                        bool endLoop = (i == nLabels) || (&testDt != &newDt);

                        secPaint = ( KDChartAxisParams::ValueScaleSecond >= cv.dtDeltaScale ) &&
                            ( testDt.time().second() != dt.time().second() ||
                              ( endLoop && ((pSecX != x1) || (pSecY != y1))));
                        minPaint = ( KDChartAxisParams::ValueScaleMinute >= cv.dtDeltaScale ) &&
                            ( testDt.time().minute() != dt.time().minute() ||
                              ( endLoop && ((pMinX != x1) || (pMinY != y1))));
                        hourPaint = ( KDChartAxisParams::ValueScaleHour >= cv.dtDeltaScale ) &&
                            ( testDt.time().hour() != dt.time().hour() ||
                              ( endLoop && ((pHourX != x1) || (pHourY != y1))));
                        dayPaint = ( KDChartAxisParams::ValueScaleDay >= cv.dtDeltaScale ) &&
                            ( testDt.date().day() != dt.date().day() ||
                              ( endLoop && ((pDayX != x1) || (pDayY != y1))));
                        /* khz: currently not used
                           weekPaint = ( KDChartAxisParams::ValueScaleWeek >= cv.dtDeltaScale ) &&
                           ( testDt.date().week() != dt.date().week() ||
                           ( endLoop && ((pWeekX != x1) || (pWeekY != y1))));
                           */
                        monthPaint = ( KDChartAxisParams::ValueScaleMonth >= cv.dtDeltaScale ) &&
                            ( testDt.date().month() != dt.date().month() ||
                              ( endLoop && ((pMonthX != x1) || (pMonthY != y1))));
                        yearPaint = ( KDChartAxisParams::ValueScaleYear >= cv.dtDeltaScale ) &&
                            ( testDt.date().year() != dt.date().year() ||
                              ( endLoop && ((pYearX != x1) || (pYearY != y1))));

                        p1X = x1 + iLabel * pXDelta;
                        p1Y = y1 + iLabel * pYDelta;
                        p2X = p1X + pXDelta;
                        p2Y = p1Y + pYDelta;
                        pXD = orgXD;
                        pYD = orgYD;

                        if( endLoop ){
                            ( ( KDChartAxisParams& ) para ).setAxisDtHighPos( p1X, p1Y );
                            // adjust stored dt-high settings
                            ( ( KDChartAxisParams& ) para ).setTrueAxisDtHigh( dt );
                        }
                        pen = subGridPen;
                        /*
                        // old code: just draw the seconds without any tests
                        // (not wise to do that when supporting sec1000
                        //  and the like some day...)
                        if( newDt.time().second() != dt.time().second() ){
                        painter->drawLine( TQPoint( p1X, p1Y ), TQPoint( p1X+pXD, p1Y+pYD ) );
                        painter->drawLine( TQPoint( p1X+pXD, p1Y+pYD ),
                        TQPoint( p1X+pXD + pXDelta, p1Y+pYD + pYDelta ) );
                        painter->drawText( p1X+pXD-orgXD, p1Y+pYD-orgYD,
                        pTextsW, pTextsH,
                        textAlign | TQt::DontClip,
                        TQString::number( dt.time().second() ) );
                        pXD += orgXD;
                        pYD += orgYD;
                        }
                        */
                        if( secPaint ){
                            painter->drawLine( TQPoint( static_cast<int>( pSecX+pXD ),
                                                       static_cast<int>( pSecY+pYD ) ),
                                               TQPoint( static_cast<int>( p2X + pXD ),
                                                       static_cast<int>( p2Y + pYD ) ) );
                            if( (pXDelta/2.0 < p2X - pSecX) || (pYDelta/2.0 < p2Y - pSecY) ){
                                TQPen oldPen( painter->pen() );
                                painter->setPen( TQPen( labelsColor ) );
                                painter->drawText( static_cast<int>( pSecX+pXD-orgXD ),
                                                   static_cast<int>( pSecY+pYD-orgYD ),
                                                   static_cast<int>( fabs((0.0 == pXDelta) ? cv.pTextsW : (p2X - pSecX))),
                                                   static_cast<int>( fabs((0.0 == pYDelta) ? cv.pTextsH : (p2Y - pSecY))),
                                        cv.textAlign | TQt::DontClip,
                                        TQString::number( dt.time().second() ) );
                                painter->setPen( oldPen );
                                if ( para.axisShowGrid() ){

                                    saveDrawLine( *painter,
                                                  TQPoint( static_cast<int>( pSecX ),
                                                          static_cast<int>( pSecY ) ),
                                                  TQPoint( static_cast<int>( pSecX + gridDX ),
                                                          static_cast<int>( pSecY + gridDY ) ),
                                            pen );
                                    pen = gridPen;
                                }
                                if( !minPaint || pMinX != pSecX || pMinY != pSecY ){
                                    painter->drawLine( TQPoint( static_cast<int>( pSecX ),
                                                               static_cast<int>( pSecY ) ),
                                                       TQPoint( static_cast<int>( pSecX+pXD ),
                                                               static_cast<int>( pSecY+pYD ) ) );
                                }
                            }
                            if( endLoop && !minPaint )
                                painter->drawLine( TQPoint( static_cast<int>( p2X ),
                                                           static_cast<int>( p2Y ) ),
                                                   TQPoint( static_cast<int>( p2X+pXD ),
                                                           static_cast<int>( p2Y+pYD ) ) );
                            pSecX = p1X + pXDelta;
                            pSecY = p1Y + pYDelta;
                            pXD += orgXD;
                            pYD += orgYD;
                        }
                        if( minPaint ){
                            painter->drawLine( TQPoint( static_cast<int>( pMinX+pXD ),
                                                       static_cast<int>( pMinY+pYD ) ),
                                               TQPoint( static_cast<int>( p2X + pXD ),
                                                       static_cast<int>( p2Y + pYD ) ) );
                            if( (pXDelta/2.0 < p2X - pMinX) || (pYDelta/2.0 < p2Y - pMinY) ){
                                TQPen oldPen( painter->pen() );
                                painter->setPen( TQPen( labelsColor ) );
                                painter->drawText( static_cast<int>( pMinX+pXD-orgXD ),
                                                   static_cast<int>( pMinY+pYD-orgYD ),
                                                   static_cast<int>( fabs((0.0 == pXDelta) ? cv.pTextsW : (p2X - pMinX)) ),
                                                   static_cast<int>( fabs((0.0 == pYDelta) ? cv.pTextsH : (p2Y - pMinY)) ),
                                                   cv.textAlign | TQt::DontClip,
                                                   TQString::number( dt.time().minute() ) );
                                painter->setPen( oldPen );
                                if ( para.axisShowGrid() ){
                                    if( !secPaint && 10 < pXYDelta  ){
                                        saveDrawLine( *painter,
                                                      TQPoint( static_cast<int>( pMinX+pXDelta/2 ),
                                                              static_cast<int>( pMinY+pYDelta/2 ) ),
                                                      TQPoint( static_cast<int>( pMinX+pXDelta/2 + gridDX ),
                                                              static_cast<int>( pMinY+pYDelta/2 + gridDY ) ),
                                                      subSubGridPen );
                                    }
                                    saveDrawLine( *painter,
                                                  TQPoint( static_cast<int>( pMinX ),
                                                          static_cast<int>( pMinY ) ),
                                                  TQPoint( static_cast<int>( pMinX + gridDX ),
                                                          static_cast<int>( pMinY + gridDY ) ),
                                                  pen );
                                    pen = gridPen;
                                }
                                if( !hourPaint || pHourX != pMinX || pHourY != pMinY ){
                                    painter->drawLine( TQPoint( static_cast<int>( pMinX ),
                                                               static_cast<int>( pMinY ) ),
                                                       TQPoint( static_cast<int>( pMinX+pXD ),
                                                               static_cast<int>( pMinY+pYD ) ) );
                                }
                            }
                            if( endLoop && !hourPaint )
                                painter->drawLine( TQPoint( static_cast<int>( p2X ),
                                                           static_cast<int>( p2Y ) ),
                                                   TQPoint( static_cast<int>( p2X+pXD ),
                                                           static_cast<int>( p2Y+pYD ) ) );
                            pMinX = p1X + pXDelta;
                            pMinY = p1Y + pYDelta;
                            pXD += orgXD;
                            pYD += orgYD;
                        }
                        if( hourPaint ){
                            painter->drawLine( TQPoint( static_cast<int>( pHourX+pXD ),
                                                       static_cast<int>( pHourY+pYD ) ),
                                               TQPoint( static_cast<int>( p2X + pXD ),
                                                       static_cast<int>( p2Y + pYD ) ) );
                            /*
                               tqDebug("line");
                               tqDebug("pXDelta / 2.0 : %f", pXDelta/2.0);
                               tqDebug("p2X - pHourX  : %f", p2X - pHourX);
                               */
                            if( (pXDelta/2.0 < p2X - pHourX) || (pYDelta/2.0 < p2Y - pHourY) ){
                                /*
                                   tqDebug("pHourX              %f", pHourX          );
                                   tqDebug("      +pXD          %i",        pXD      );
                                   tqDebug("          -orgXD    %i",            orgXD);
                                   tqDebug("pHourY              %f", pHourY          );
                                   tqDebug("      +pYD          %i",        pYD      );
                                   tqDebug("          -orgYD    %i",            orgYD);
                                   */
                                TQPen oldPen( painter->pen() );
                                painter->setPen( TQPen( labelsColor ) );
                                painter->drawText( static_cast<int>( pHourX+pXD-orgXD ),
                                                   static_cast<int>( pHourY+pYD-orgYD ),
                                                   static_cast<int>( fabs((0.0 == pXDelta) ? cv.pTextsW : (p2X - pHourX))),
                                                   static_cast<int>( fabs((0.0 == pYDelta) ? cv.pTextsH : (p2Y - pHourY))),
                                                   cv.textAlign | TQt::DontClip,
                                                   TQString::number( dt.time().hour() ) );
                                painter->setPen( oldPen );
                                if ( para.axisShowGrid() ){
                                    if( !minPaint && 10 < pXYDelta  ){
                                        saveDrawLine( *painter,
                                                      TQPoint( static_cast<int>( pHourX+pXDelta/2 ),
                                                              static_cast<int>( pHourY+pYDelta/2 ) ),
                                                      TQPoint( static_cast<int>( pHourX+pXDelta/2 + gridDX ),
                                                              static_cast<int>( pHourY+pYDelta/2 + gridDY ) ),
                                                      subSubGridPen );
                                    }
                                    saveDrawLine( *painter,
                                                  TQPoint( static_cast<int>( pHourX ),
                                                          static_cast<int>( pHourY ) ),
                                                  TQPoint( static_cast<int>( pHourX + gridDX ),
                                                          static_cast<int>( pHourY + gridDY ) ),
                                                  pen );
                                    pen = gridPen;
                                }
                                if( !dayPaint || pDayX != pHourX || pDayY != pHourY ){
                                    painter->drawLine( TQPoint( static_cast<int>( pHourX ),
                                                               static_cast<int>( pHourY ) ),
                                                       TQPoint( static_cast<int>( pHourX+pXD ),
                                                               static_cast<int>( pHourY+pYD ) ) );
                                }
                            }
                            if( endLoop && !dayPaint )
                                painter->drawLine( TQPoint( static_cast<int>( p2X ),
                                                           static_cast<int>( p2Y ) ),
                                                   TQPoint( static_cast<int>( p2X+pXD ),
                                                           static_cast<int>( p2Y+pYD ) ) );
                            pHourX = p1X + pXDelta;
                            pHourY = p1Y + pYDelta;
                            pXD += orgXD;
                            pYD += orgYD;
                        }
                        if( dayPaint ){
                            painter->drawLine( TQPoint( static_cast<int>( pDayX+pXD ),
                                                       static_cast<int>( pDayY+pYD ) ),
                                               TQPoint( static_cast<int>( p2X + pXD ),
                                                       static_cast<int>( p2Y + pYD ) ) );
                            if( (pXDelta/2.0 < p2X - pDayX) || (pYDelta/2.0 < p2Y - pDayY) ){
                                TQPen oldPen( painter->pen() );
                                painter->setPen( TQPen( labelsColor ) );
                                painter->drawText( static_cast<int>( pDayX+pXD-orgXD ),
                                                   static_cast<int>( pDayY+pYD-orgYD ),
                                                   static_cast<int>( fabs((0.0 == pXDelta) ? cv.pTextsW : (p2X - pDayX)) ),
                                                   static_cast<int>( fabs((0.0 == pYDelta) ? cv.pTextsH : (p2Y - pDayY)) ),
                                        cv.textAlign | TQt::DontClip,
                                        TQString::number( dt.date().day() ) );
                                painter->setPen( oldPen );
                                /* khz: currently not used
                                   if( !weekPaint || pWeekX != pDayX || pWeekY != pDayY )
                                   */
                                if ( para.axisShowGrid() ){
                                    if( !hourPaint && 10 < pXYDelta  ){
                                        saveDrawLine( *painter,
                                                      TQPoint( static_cast<int>( pDayX+pXDelta/2 ),
                                                              static_cast<int>( pDayY+pYDelta/2 ) ),
                                                      TQPoint( static_cast<int>( pDayX+pXDelta/2 + gridDX ),
                                                              static_cast<int>( pDayY+pYDelta/2 + gridDY ) ),
                                                subSubGridPen );
                                    }
                                    saveDrawLine( *painter,
                                                  TQPoint( static_cast<int>( pDayX ),
                                                          static_cast<int>( pDayY ) ),
                                                  TQPoint( static_cast<int>( pDayX + gridDX ),
                                                          static_cast<int>( pDayY + gridDY ) ),
                                            pen );
                                    pen = gridPen;
                                }
                                if( !monthPaint || pMonthX != pDayX || pMonthY != pDayY ){
                                    painter->drawLine( TQPoint( static_cast<int>( pDayX ),
                                                               static_cast<int>( pDayY ) ),
                                                       TQPoint( static_cast<int>( pDayX+pXD ),
                                                               static_cast<int>( pDayY+pYD ) ) );
                                }
                            }
                            /* khz: currently not used
                               if( endLoop && !weekPaint )
                               */
                            if( endLoop && !monthPaint )
                                painter->drawLine( TQPoint( static_cast<int>( p2X ),
                                                           static_cast<int>( p2Y ) ),
                                                   TQPoint( static_cast<int>( p2X+pXD ),
                                                           static_cast<int>( p2Y+pYD ) ) );
                            pDayX = p1X + pXDelta;
                            pDayY = p1Y + pYDelta;
                            pXD += orgXD;
                            pYD += orgYD;
                        }
                        /* khz: currently unused
                           if( weekPaint ){
                           painter->drawLine( TQPoint( pWeekX+pXD, pWeekY+pYD ),
                            TQPoint( p2X + pXD, p2Y + pYD ) );
                           if( (pXDelta/2.0 < p2X - pWeekX) || (pYDelta/2.0 < p2Y - pWeekY) ){
                           TQPen oldPen( painter->pen() );
                           painter->setPen( TQPen( labelsColor ) );
                           painter->drawText( pWeekX+pXD-orgXD, pWeekY+pYD-orgYD,
                           painter->setPen( oldPen );
                           fabs((0.0 == pXDelta) ? pTextsW : (p2X - pWeekX)),
                           fabs((0.0 == pYDelta) ? pTextsH : (p2Y - pWeekY)),
                           textAlign | TQt::DontClip,
                           TQString::number( dt.date().week() ) );
                           if ( para.axisShowGrid() ){
                           if( !dayPaint && 40 < pXYDelta  ){
                        // draw 7 lines:
                        //saveDrawLine( *painter,
                        //            TQPoint( pWeekX+pXDelta/2,
                        //                    pWeekY+pYDelta/2 ),
                        //            TQPoint( pWeekX+pXDelta/2 + gridDX,
                        //                    pWeekY+pYDelta/2 + gridDY ),
                        //            subSubGridPen );
                        }
                        saveDrawLine( *painter,
                        TQPoint( pWeekX,
                        pWeekY ),
                        TQPoint( pWeekX + gridDX,
                        pWeekY + gridDY ),
                        pen );
                        pen = gridPen;
                        }
                        if( !monthPaint || pMonthX != pDayX || pMonthY != pDayY ){
                        painter->drawLine( TQPoint( pWeekX, pWeekY ), TQPoint( pWeekX+pXD, pWeekY+pYD ) );
                        }
                        }
                        if( endLoop && !monthPaint )
                        painter->drawLine( TQPoint( p2X, p2Y ), TQPoint( p2X+pXD, p2Y+pYD ) );
                        pWeekX = p1X + pXDelta;
                        pWeekY = p1Y + pYDelta;
                        pXD += orgXD;
                        pYD += orgYD;
                        }
                        */
                        if( monthPaint ){
                            painter->drawLine( TQPoint( static_cast<int>( pMonthX+pXD ),
                                                       static_cast<int>( pMonthY+pYD ) ),
                                               TQPoint( static_cast<int>( p2X + pXD ),
                                                       static_cast<int>( p2Y + pYD ) ) );
                            if( (pXDelta/2.0 < p2X - pMonthX) || (pYDelta/2.0 < p2Y - pMonthY) ){
                                TQPen oldPen( painter->pen() );
                                painter->setPen( TQPen( labelsColor ) );
                                painter->drawText( static_cast<int>( pMonthX+pXD-orgXD ),
                                                   static_cast<int>( pMonthY+pYD-orgYD ),
                                                   static_cast<int>( fabs((0.0 == pXDelta) ? cv.pTextsW : (p2X - pMonthX)) ),
                                                   static_cast<int>( fabs((0.0 == pYDelta) ? cv.pTextsH : (p2Y - pMonthY)) ),
                                        cv.textAlign | TQt::DontClip,
                                        TQString::number( dt.date().month() ) );
                                painter->setPen( oldPen );
                                if ( para.axisShowGrid() ){
                                    /* khz: currently unused
                                       if( !weekPaint &&
                                       && 10 < pXYDelta  ){
                                       saveDrawLine( *painter,
                                       TQPoint( pMonthX+pXDelta/2,
                                       pMonthY+pYDelta/2 ),
                                       TQPoint( pMonthX+pXDelta/2 + gridDX,
                                       pMonthY+pYDelta/2 + gridDY ),
                                       subSubGridPen );
                                       }
                                       */
                                    saveDrawLine( *painter,
                                                  TQPoint( static_cast<int>( pMonthX ),
                                                          static_cast<int>( pMonthY ) ),
                                                  TQPoint( static_cast<int>( pMonthX + gridDX ),
                                                          static_cast<int>( pMonthY + gridDY ) ),
                                            pen );
                                    pen = gridPen;
                                }
                                if( !yearPaint || pYearX != pMonthX || pYearY != pMonthY ){
                                    painter->drawLine( TQPoint( static_cast<int>( pMonthX ),
                                                               static_cast<int>( pMonthY ) ),
                                                       TQPoint( static_cast<int>( pMonthX+pXD ),
                                                               static_cast<int>( pMonthY+pYD ) ) );
                                }
                            }
                            if( endLoop && !yearPaint )
                                painter->drawLine( TQPoint( static_cast<int>( p2X ),
                                                           static_cast<int>( p2Y ) ),
                                                   TQPoint( static_cast<int>( p2X+pXD ),
                                                           static_cast<int>( p2Y+pYD ) ) );
                            pMonthX = p1X + pXDelta;
                            pMonthY = p1Y + pYDelta;
                            pXD += orgXD;
                            pYD += orgYD;
                        }
                        if( yearPaint ){
                            painter->drawLine( TQPoint( static_cast<int>( pYearX+pXD ),
                                                       static_cast<int>( pYearY+pYD  ) ),
                                               TQPoint( static_cast<int>( p2X + pXD ),
                                                       static_cast<int>( p2Y + pYD ) ) );
                            if( (pXDelta/2.0 < p2X - pYearX) || (pYDelta/2.0 < p2Y - pYearY) ){
                                TQPen oldPen( painter->pen() );
                                painter->setPen( TQPen( labelsColor ) );
                                painter->drawText( static_cast<int>( pYearX+pXD-orgXD ),
                                                   static_cast<int>( pYearY+pYD-orgYD ),
                                                   static_cast<int>( fabs((0.0 == pXDelta) ? cv.pTextsW : (p2X - pYearX)) ),
                                                   static_cast<int>( fabs((0.0 == pYDelta) ? cv.pTextsH : (p2Y - pYearY)) ),
                                        cv.textAlign | TQt::DontClip,
                                        TQString::number( dt.date().year() ) );
                                painter->setPen( oldPen );
                                if ( para.axisShowGrid() ){
                                    if( !monthPaint && 10 < pXYDelta  ){
                                        saveDrawLine( *painter,
                                                      TQPoint( static_cast<int>( pYearX+pXDelta/2 ),
                                                              static_cast<int>( pYearY+pYDelta/2 ) ),
                                                      TQPoint( static_cast<int>( pYearX+pXDelta/2 + gridDX ),
                                                              static_cast<int>( pYearY+pYDelta/2 + gridDY ) ),
                                                subSubGridPen );
                                    }
                                    saveDrawLine( *painter,
                                                  TQPoint( static_cast<int>( pYearX ),
                                                          static_cast<int>( pYearY ) ),
                                                  TQPoint( static_cast<int>( pYearX + gridDX ),
                                                          static_cast<int>( pYearY + gridDY ) ),
                                            pen );
                                    pen = gridPen;
                                }
                                painter->drawLine( TQPoint( static_cast<int>( pYearX ),
                                                           static_cast<int>( pYearY ) ),
                                                   TQPoint( static_cast<int>( pYearX+pXD ),
                                                           static_cast<int>( pYearY+pYD ) ) );
                            }
                            if( endLoop )
                                painter->drawLine( TQPoint( static_cast<int>( p2X ),
                                                           static_cast<int>( p2Y ) ),
                                                   TQPoint( static_cast<int>( p2X+pXD ),
                                                           static_cast<int>( p2Y+pYD ) ) );
                            pYearX = p1X + pXDelta;
                            pYearY = p1Y + pYDelta;
                            pXD += orgXD;
                            pYD += orgYD;
                        }
                        if( &testDt != &newDt )
                            break;
                        dt = newDt;
                        iLabel += 1.0;
                    }
                    if( !commonDtHeader.isEmpty() ){
                        TQPen oldPen( painter->pen() );
                        painter->setPen( TQPen( labelsColor ) );
                        painter->drawText( static_cast<int>( x1 + pXD ), static_cast<int>( y1 + pYD ),
                                           commonDtHeader );
                        painter->setPen( oldPen );
                    }
                }else{
                    int iLeaveOut = nLeaveOut;
                    TQString label;
                    for ( TQStringList::Iterator labelIter = labelTexts->begin();
                          labelIter != labelTexts->end();
                          ++labelIter ) {
                        TQDateTime dt;
                        if( cv.isDateTime ){
#if COMPAT_TQT_VERSION >= 0x030000
                            dt = TQDateTime::fromString( *labelIter,
                                    Qt::ISODate );
                            label = dt.toString( formatDT );
#else
                            dt = dateTimeFromString( *labelIter );
                            label = dt.toString();
#endif
                        }else{
                            label = *labelIter;
                        }

                        if( iLeaveOut < nLeaveOut )
                            ++iLeaveOut;
                        else
                            iLeaveOut = 0;
                        //Pending Michel: test if the user implicitely wants to get rid
                        //of the non fractional values delimiters and grid lines.
                        // axisDigitsBehindComma == 0 and the user implicitely
                        // setAxisShowFractionalValuesDelimiters() to false
                        bool showDelim =  para.axisShowFractionalValuesDelimiters();
                        if ( para.axisShowGrid() && !bMultiRowBarChart ) {
			  if ( !label.isNull() || showDelim ){
                            if( !iLeaveOut )
                                // draw the main grid line

                                saveDrawLine( *painter,
                                              TQPoint( static_cast<int>( pGAX - pGXMicroAdjust ),
                                                      static_cast<int>( pGAY - pGYMicroAdjust ) ),
                                              TQPoint( static_cast<int>( pGZX - pGXMicroAdjust ),
                                                      static_cast<int>( pGZY - pGYMicroAdjust ) ),
                                              gridPen );

                            else if( para.axisShowSubDelimiters()  )
                                // draw a thin sub grid line instead of main line
                                saveDrawLine( *painter,
                                              TQPoint( static_cast<int>( pGAX - pGXMicroAdjust ),
                                                      static_cast<int>( pGAY - pGYMicroAdjust ) ),
                                              TQPoint( static_cast<int>( pGZX - pGXMicroAdjust ),
                                                      static_cast<int>( pGZY - pGYMicroAdjust ) ),
                                              leaveOutGridPen );
			  }
                        }
                        if ( para.axisLabelsVisible() ) {
                            if( !iLeaveOut ) {
                              /*PENDING Michel: those points should not be redrawn if sub-delimiters are drawn
			       *drawing the submarkers
			       * make it visible or not
			       *In the case we have a null label - axisDigitsBehindComma is implicitely set to 0 -
			       *also paint or dont paint the delimiter corresponding to this label - default is paint.
			       */
			      if ( !label.isNull() || showDelim )
                                painter->drawLine( TQPoint( static_cast<int>( p1X ),
                                                           static_cast<int>( p1Y ) ),
                                                   TQPoint( static_cast<int>( p2X ),
                                                           static_cast<int>( p2Y ) ) );

			      cv.pLastX = p1X;
			      cv.pLastY = p1Y;
			      TQPen oldPen( painter->pen() );
			      painter->setPen( TQPen( labelsColor ) );
			      if(    para.axisLabelsDontShrinkFont()
				     && isHorizontalAxis
				     && (TQt::AlignHCenter == (cv.textAlign & TQt::AlignHCenter)) ) {
				double w = fm.width( label ) + 4.0;
				double x0 = cv.pTextsX + cv.pTextsW / 2.0;

				painter->drawText( static_cast<int>( x0 - w / 2.0 ),
						   static_cast<int>( cv.pTextsY ),
						   static_cast<int>( w ),
						   static_cast<int>( cv.pTextsH ),
						   cv.textAlign, label );
			      } else {
				if( nRotation ){
				  KDDrawText::drawRotatedText(
						painter,
						nRotation,
						painter->worldMatrix().map(
                                                TQPoint( static_cast<int>( cv.pTextsX ),
                                                        static_cast<int>( cv.pTextsY ) ) ),
                                                label,
                                                0,
                                                cv.textAlign,
                                                false,
                                                &fm,
                                                screenOutput,screenOutput,0,
                                                screenOutput );
                                    } else {
				      // Pending Michel draw the axis labels
                                        painter->drawText( static_cast<int>( cv.pTextsX ),
                                                           static_cast<int>( cv.pTextsY ),
                                                           static_cast<int>( cv.pTextsW ),
                                                           static_cast<int>( cv.pTextsH ),
                                                           cv.textAlign | TQt::DontClip,
                                                           label );

                                        // debugging text rect
                                        /*
                                        painter->drawRect(static_cast <int>(cv.pTextsX),
							  static_cast <int>(cv.pTextsY),
							  static_cast <int> (nUsableAxisWidth),
							  static_cast <int> (nUsableAxisHeight));
					*/
                                    }
                                }
                                painter->setPen( oldPen );
                            }
                        }


                        if( cv.isDateTime ){
                            if( labelTexts->begin() == labelIter ){
                                ((KDChartAxisParams&)para).setAxisDtLowPos(
                                                                           pGAX - pGXMicroAdjust,
                                                                           pGAY - pGYMicroAdjust );
                                // adjust stored dt-low settings
                                ( ( KDChartAxisParams& ) para ).setTrueAxisDtLow( dt );
                            }else{
                                ((KDChartAxisParams&)para).setAxisDtHighPos(
                                                                            pGAX - pGXMicroAdjust,
                                                                            pGAY - pGYMicroAdjust );
                                // adjust stored dt-high settings
                                ( ( KDChartAxisParams& ) para ).setTrueAxisDtHigh( dt );
                            }
                        }

                        iLabel += 1.0;
                        p1X = x1 + iLabel * pXDelta;
                        p1Y = y1 + iLabel * pYDelta;
                        p2X = x2 + iLabel * pXDelta;
                        p2Y = y2 + iLabel * pYDelta;
                        cv.pTextsX = xT + iLabel * pXDelta;
                        cv.pTextsY = yT + iLabel * pYDelta;

                        pGAX = xGA + iLabel * pXDelta;
                        pGAY = yGA + iLabel * pYDelta;
                        pGZX = xGZ + iLabel * pXDelta;
                        pGZY = yGZ + iLabel * pYDelta;
                        /*
                        pGAX = xGA + iLabel * pXSubDelimDelta / cv.nSubDelimFactor;
                        pGAY = yGA + iLabel * pYSubDelimDelta / cv.nSubDelimFactor;
                        pGZX = xGZ + iLabel * pXSubDelimDelta / cv.nSubDelimFactor;
                        pGZY = yGZ + iLabel * pYSubDelimDelta / cv.nSubDelimFactor;
                        */
                    }
                }


                // adjust zero-line start, if not starting at origin
                if ( cv.bSteadyCalc &&
                     ( para.axisValuesDecreasing() ||
                       (0.0 != para.trueAxisLow())      ) ) {
                    //double x = p1.x();
                    double x = 0.0;
                     /* we have to find the *real* X axis position,
                     this is NOT always the p1.x() as it is the
                     case for left2 or right2 axes. [cmw, 12/01/2005] */
                     if (cv.basicPos==KDChartAxisParams::AxisPosRight)
                         x = static_cast<double>(_dataRect.right());
                     else
                         x = static_cast<double>(_dataRect.left());
                    double y = p1.y();
                    double mult = para.trueAxisLow() / para.trueAxisDelta();
                    x -= mult * pXDelta;
                    y -= mult * pYDelta;
                    axisZeroLineStartX = x;
                    axisZeroLineStartY = y;
                    //tqDebug( "axisZeroLineStartX %f,  axisZeroLineStartY %f",
                    //        axisZeroLineStartX, axisZeroLineStartY );
                }

                painter->setClipping( oldClippingFlag );
            } // if( nLabels )

            // draw zero-line (Ok, this might be overwritten by axes
            //  cause those are drawn after all labels and grid and
            //  zero-line(s) has been painted, see code below, starting
            // with "// draw all the axes".
            if ( cv.bSteadyCalc && !cv.isDateTime ) {
                ( ( KDChartAxisParams& ) para ).setAxisZeroLineStart( axisZeroLineStartX, axisZeroLineStartY );
                double axisZeroLineStart;
                int minCoord, maxCoord;
                double xFactor, yFactor;
                switch( cv.basicPos ){
                    case KDChartAxisParams::AxisPosLeft:
                        xFactor =  1.0;
                        yFactor =  0.0;
                        axisZeroLineStart = axisZeroLineStartY;
                        minCoord = TQMIN( cv.orig.y(), cv.dest.y() );
                        maxCoord = TQMAX( cv.orig.y(), cv.dest.y() );

                        break;
                    case KDChartAxisParams::AxisPosRight:
                        xFactor = -1.0;
                        yFactor =  0.0;
                        axisZeroLineStart = axisZeroLineStartY;
                        minCoord = TQMIN( cv.orig.y(), cv.dest.y() );
                        maxCoord = TQMAX( cv.orig.y(), cv.dest.y() );
                        break;
                    case KDChartAxisParams::AxisPosTop:
                        xFactor =  0.0;
                        yFactor =  1.0;
                        axisZeroLineStart = axisZeroLineStartX;
                        minCoord = TQMIN( cv.orig.x(), cv.dest.x() );
                        maxCoord = TQMAX( cv.orig.x(), cv.dest.x() );
                        break;
                    case KDChartAxisParams::AxisPosBottom:
                        xFactor =  0.0;
                        yFactor = -1.0;
                        axisZeroLineStart = axisZeroLineStartX;
                        minCoord = TQMIN( cv.orig.x(), cv.dest.x() );
                        maxCoord = TQMAX( cv.orig.x(), cv.dest.x() );
                        break;
                    default:
                        xFactor =  0.0;
                        yFactor =  0.0;
                        axisZeroLineStart = 0.0;
                        minCoord = 0;
                        maxCoord = 0;
                }
                if( axisZeroLineStart >= minCoord &&
                        axisZeroLineStart <= maxCoord ){
                    TQPoint pZ0( static_cast<int>( para.axisZeroLineStartX() ),
                                static_cast<int>( para.axisZeroLineStartY() ) );
                    TQPoint pZ(  static_cast<int>( para.axisZeroLineStartX()
                                + xFactor * _dataRect.width() ),
                                static_cast<int>( para.axisZeroLineStartY()
                                + yFactor * _dataRect.height() ) );
                    //tqDebug("------");
                    saveDrawLine( *painter,
                            pZ0,
                            pZ,
                            TQPen( para.axisZeroLineColor(),
                                lineWidth ) );
                }
            }

        }

    }

    // Drawing all the axes lines:
/*
    // 1. test if the standard axes are share one or several corner points
    //    if yes, we first draw a polyline using a "TQt::MiterJoin" PenJoinStyle
    //    to make sure the corners are filled
    internal__KDChart__CalcValues& cv1 = calcVal[ KDChartAxisParams::AxisPosLeft   ];
    internal__KDChart__CalcValues& cv2 = calcVal[ KDChartAxisParams::AxisPosBottom ];
    const KDChartAxisParams& pa1 = params()->axisParams( KDChartAxisParams::AxisPosLeft );
    const KDChartAxisParams& pa2 = params()->axisParams( KDChartAxisParams::AxisPosBottom );
tqDebug("\n\nx1: %i   y1: %i   w1: %i\nx2: %i   y2: %i   w2: %i",
cv1.orig.x(), cv1.orig.y(), pa1.axisTrueLineWidth(),
cv2.orig.x(), cv2.orig.y(), pa2.axisTrueLineWidth() );
    if( cv1.orig == cv2.orig ){
        const TQColor c1( pa1.axisLineColor() );
        const TQColor c2( pa2.axisLineColor() );
        const TQPoint pA( cv1.dest );
        const TQPoint pB( cv1.orig );
        const TQPoint pC( cv2.dest );
        TQPen pen( TQColor( (c1.red()   + c2.red())  /2,
                          (c1.green() + c2.green())/2,
                          (c1.blue()  + c2.blue()) /2 ),
                  TQMIN(pa1.axisTrueLineWidth(), pa2.axisTrueLineWidth()) );
        pen.setJoinStyle( TQt::MiterJoin );
        painter->setPen( pen );
        TQPointArray a;
        a.putPoints( 0, 3, pA.x(),pA.y(), pB.x(),pB.y(), pC.x(),pC.y() );
        painter->drawPolyline( a );
tqDebug("done\n" );
    }
*/
    // 2. draw the axes using their normal color
    for( iAxis = 0; iAxis < KDCHART_MAX_AXES; ++iAxis ){
        internal__KDChart__CalcValues& cv = calcVal[iAxis];
        const KDChartAxisParams & para = params()->axisParams( iAxis );
        if( cv.processThisAxis && para.axisLineVisible() ){
            painter->setPen( TQPen( para.axisLineColor(),
                             para.axisTrueLineWidth() ) );
            int x =         cv.dest.x();
            if( 2.0 >= TQABS(cv.pLastX - x) )
                x = static_cast < int > ( cv.pLastX );
            int y =         cv.dest.y();
            if( 2.0 >= TQABS(cv.pLastY - y) )
                y = static_cast < int > ( cv.pLastY );
            painter->drawLine( cv.orig, TQPoint(x,y) );
        }
    }

    painter->restore();
}


double fastPow10( int x )
{
    double res = 1.0;
    if( 0 <= x ){
        for( int i = 1; i <= x; ++i )
            res *= 10.0;
    }else{
        for( int i = -1; i >= x; --i )
            res /= 10.0;
    }
    return res;
}
double fastPow10( double x )
{
    return pow(10.0, x);
}


/**
  Calculates the actual label texts for one axis.

  \note When calling this function the actual area size for this
  axis must be set, this means you may only call it when
  \c KDChartPainter::setupGeometry() has been called before.

  \param painter the TQPainter onto which the chart should be painted
  \param data the data that will be displayed as a chart
  \param params the KDChartParams that were specified globally
  \param axisNumber the number of this axis (used in some params structures)
  \param averageValueP1000 (average height+width of the prtbl. area) / 1000
  \param basicPos the basic axis position returned by
  KDChartAxisParams::basicAxisPos()
  \param orig the axis start point
  \param delimLen the length of one delimiter mark
  \param (all others) the reference parameters to be returned
  by this function
  */
/**** static ****/
void KDChartAxesPainter::calculateLabelTexts(
        TQPainter* painter,
        const KDChartTableDataBase& data,
        const KDChartParams& params,
        uint axisNumber,
        double averageValueP1000,
        double delimLen,
        // start of return parameters
        KDChartAxisParams::AxisPos& basicPos,
        TQPoint& orig,
        TQPoint& dest,
        double& pXDeltaFactor,
        double& pYDeltaFactor,
        double& pXDelimDeltaFaktor,
        double& pYDelimDeltaFaktor,
        double& nSubDelimFactor,
        double& pDelimDelta,
        double& nTxtHeight,
        double& pTextsX,
        double& pTextsY,
        double& pTextsW,
        double& pTextsH,
        int& textAlign,
        bool& isLogarithmic,
        bool& isDateTime,
        bool& autoDtLabels,
        TQDateTime& dtLow,
        TQDateTime& dtHigh,
        KDChartAxisParams::ValueScale& dtDeltaScale,
        bool adjustTheValues,
        double trueDelta,
        double trueDeltaPix )
{
//tqDebug("\nentering KDChartAxesPainter::calculateLabelTexts() :   nTxtHeight: "+TQString::number(nTxtHeight));
    const KDChartAxisParams & para = params.axisParams( axisNumber );

    // store whether the labels are to be drawn in reverted order
    const bool bDecreasing = para.axisValuesDecreasing();

    basicPos = KDChartAxisParams::basicAxisPos( axisNumber );

    pXDeltaFactor = 0.0;
    pYDeltaFactor = 0.0;
    pXDelimDeltaFaktor = 0.0;
    pYDelimDeltaFaktor = 0.0;
    int axisLength;
    switch ( basicPos ) {
        case KDChartAxisParams::AxisPosBottom: {
            axisLength = para.axisTrueAreaRect().width();
            orig = bDecreasing
                 ? para.axisTrueAreaRect().topRight()
                 : para.axisTrueAreaRect().topLeft();
            dest = bDecreasing
                 ? para.axisTrueAreaRect().topLeft()
                 : para.axisTrueAreaRect().topRight();
            pYDelimDeltaFaktor = 1.0;
            pXDeltaFactor      = bDecreasing ? -1.0 : 1.0;
            //tqDebug("\nsetting pXDeltaFactor for axis %x", axisNumber);
            //tqDebug(bDecreasing ? "bDecreasing =  TRUE" : "bDecreasing = FALSE");
            //tqDebug("pXDeltaFactor = %f\n",pXDeltaFactor);
        }
        break;
        case KDChartAxisParams::AxisPosLeft: {
            axisLength = para.axisTrueAreaRect().height();
            orig = bDecreasing
                 ? para.axisTrueAreaRect().topRight()
                 : para.axisTrueAreaRect().bottomRight();
            dest = bDecreasing
                 ? para.axisTrueAreaRect().bottomRight()
                 : para.axisTrueAreaRect().topRight();
            pXDelimDeltaFaktor = -1.0;
            pYDeltaFactor      = bDecreasing ? 1.0 : -1.0;
        }
        break;
        case KDChartAxisParams::AxisPosTop: {
            axisLength = para.axisTrueAreaRect().width();
            orig = bDecreasing
                 ? para.axisTrueAreaRect().bottomRight()
                 : para.axisTrueAreaRect().bottomLeft();
            dest = bDecreasing
                 ? para.axisTrueAreaRect().bottomLeft()
                 : para.axisTrueAreaRect().bottomRight();
            pYDelimDeltaFaktor = -1.0;
            pXDeltaFactor      =  bDecreasing ? -1.0 : 1.0;
        }
        break;
        case KDChartAxisParams::AxisPosRight: {
            axisLength = para.axisTrueAreaRect().height();
            orig = bDecreasing
                 ? para.axisTrueAreaRect().topLeft()
                 : para.axisTrueAreaRect().bottomLeft();
            dest = bDecreasing
                 ? para.axisTrueAreaRect().bottomLeft()
                 : para.axisTrueAreaRect().topLeft();
            pXDelimDeltaFaktor = 1.0;
            pYDeltaFactor      = bDecreasing ? 1.0 : -1.0;
        }
        break;
        default: {
            axisLength = 0;
            tqDebug( "IMPLEMENTATION ERROR: KDChartAxesPainter::paintAxes() unhandled enum value." );
        }
        break;
    }

    // which dataset(s) is/are represented by this axis?
    uint dataset, dataset2, chart;
    if ( !params.axisDatasets( axisNumber, dataset, dataset2, chart ) ) {
        dataset = KDCHART_ALL_DATASETS;
        dataset2 = KDCHART_ALL_DATASETS;
        chart = 0;
        //tqDebug("\nautomatic set values:   chart: %u,\ndataset: %u,  dataset2: %u",
        //chart, dataset, dataset2);
    }
    // which dataset(s) with mode DataEntry (or mode ExtraLinesAnchor, resp.)
    // is/are represented by this axis?
    uint dataDataset, dataDataset2;
    if( params.findDatasets( KDChartParams::DataEntry,
                             KDChartParams::ExtraLinesAnchor,
                             dataDataset,
                             dataDataset2,
                             chart ) ) {
        // adjust dataDataset in case MORE THAN ONE AXIS
        //                    is representing THIS CHART
        if(    (    KDCHART_ALL_DATASETS != dataset
                 && KDCHART_NO_DATASET   != dataset )
            || (    KDCHART_ALL_DATASETS != dataDataset
                 && KDCHART_NO_DATASET   != dataDataset ) ){
            int ds = (KDCHART_ALL_DATASETS != dataset)
                   ? dataset
                   : 0;
            int dds = (KDCHART_ALL_DATASETS != dataDataset)
                    ? dataDataset
                    : 0;
            dataDataset  = TQMAX( ds, dds );
        }
        if(    (    KDCHART_ALL_DATASETS != dataset2
                 && KDCHART_NO_DATASET   != dataset2 )
            || (    KDCHART_ALL_DATASETS != dataDataset2
                 && KDCHART_NO_DATASET   != dataDataset2 ) ){
            int ds2 = (KDCHART_ALL_DATASETS != dataset2)
                    ? dataset2
                    : KDCHART_MAX_AXES-1;
            int dds2 = (KDCHART_ALL_DATASETS != dataDataset2)
                     ? dataDataset2
                     : KDCHART_MAX_AXES-1;
            dataDataset2  = TQMIN( ds2, dds2 );
        }
    }
    else {
        // Should not happen
        tqDebug( "IMPLEMENTATION ERROR: findDatasets( DataEntry, ExtraLinesAnchor ) should *always* return true. (b)" );
        dataDataset = KDCHART_ALL_DATASETS;
    }
    //tqDebug("\naxisNumber: %x\nchart: %x\ndataset: %x,  dataset2: %x,\ndataDataset: %x,  dataDataset2: %x",
    //axisNumber, chart, dataset, dataset2, dataDataset, dataDataset2);

    if ( para.axisLabelsFontUseRelSize() ){
        nTxtHeight = para.axisLabelsFontRelSize()
            * averageValueP1000;
//tqDebug("using rel. size in KDChartAxesPainter::calculateLabelTexts() :   nTxtHeight: "+TQString::number(nTxtHeight));
    }else {
        TQFontInfo info( para.axisLabelsFont() );
        nTxtHeight = info.pointSize();
//tqDebug("using FIXED size in KDChartAxesPainter::calculateLabelTexts() :   nTxtHeight: "+TQString::number(nTxtHeight));
    }

    const KDChartEnums::NumberNotation notation = para.axisLabelsNotation();
    const int     behindComma    = para.axisDigitsBehindComma();
    const int     divPow10       = para.axisLabelsDivPow10();
    const TQString decimalPoint   = para.axisLabelsDecimalPoint();
    const TQString thousandsPoint = para.axisLabelsThousandsPoint();
    const TQString prefix         = para.axisLabelsPrefix();
    const TQString postfix        = para.axisLabelsPostfix();
    const int     totalLen       = para.axisLabelsTotalLen();
    const TQChar   padFill        = para.axisLabelsPadFill();
    const bool    blockAlign     = para.axisLabelsBlockAlign();

    TQStringList labelTexts;
    int colNum = para.labelTextsDataRow();
    bool bDone = true;
    switch ( para.axisLabelTextsFormDataRow() ) {
        case KDChartAxisParams::LabelsFromDataRowYes: {
            // Take whatever is in the specified column (even if not a string)
            int trueBehindComma = -1;
            TQVariant value;
            for ( uint iDataset = 0; iDataset < data.usedRows(); iDataset++ ) {
                if( data.cellCoord( iDataset, colNum, value, 1 ) ){
                    if( TQVariant::String == value.type() )
                        labelTexts.append( value.toString() );
                    else {
                        labelTexts.append( applyLabelsFormat( value.toDouble(),
                                                              divPow10,
                                                              behindComma,
                                                              para.axisValueDelta(),
                                                              trueBehindComma,
                                                              notation,
                                                              decimalPoint,
                                                              thousandsPoint,
                                                              prefix,
                                                              postfix,
                                                              totalLen,
                                                              padFill,
                                                              blockAlign ) );

		    }
                }
            }
            break;
        }
        case KDChartAxisParams::LabelsFromDataRowGuess: {
            TQVariant value;
            for ( uint iDataset = 0; iDataset < data.usedRows(); iDataset++ ) {
                if( data.cellCoord( iDataset, colNum, value, 1 ) ){
                    if( TQVariant::String == value.type() ){
                        const TQString sVal( value.toString() );
                        if( !sVal.isEmpty() && !sVal.isNull() )
                            labelTexts.append( sVal );
                    }
                }else{
                    labelTexts.clear();
                    bDone = false;
                    break;
                }
            }
            break;
        }
        case KDChartAxisParams::LabelsFromDataRowNo: {
            bDone = false;
            break;
        }
        default:
            // Should not happen
            tqDebug( "KDChart: Unknown label texts source" );
    }

    // if necessary adjust text params *including* the steady value calc setting
    const bool dataCellsHaveSeveralCoordinates =
        (KDCHART_ALL_DATASETS == dataDataset)
        ? data.cellsHaveSeveralCoordinates()
        : data.cellsHaveSeveralCoordinates( dataDataset, dataDataset2 );
    if( dataCellsHaveSeveralCoordinates && !para.axisSteadyValueCalc() )
        ((KDChartParams&)params).setAxisLabelTextParams(
            axisNumber,
            true,
            KDCHART_AXIS_LABELS_AUTO_LIMIT,
            KDCHART_AXIS_LABELS_AUTO_LIMIT,
            KDCHART_AXIS_LABELS_AUTO_DELTA,
            para.axisLabelsDigitsBehindComma() );// NOTE: This sets MANY other params to default values too!


    const KDChartParams::ChartType params_chartType
        = ( 0 == chart )
        ? params.chartType()
        : params.additionalChartType();


    // store whether we are calculating Ordinate-like axis values
    const bool bSteadyCalc = para.axisSteadyValueCalc();

    // store whether logarithmic calculation is wanted
    isLogarithmic = bSteadyCalc &&
            (KDChartParams::Line == params_chartType) &&
            (KDChartAxisParams::AxisCalcLogarithmic == para.axisCalcMode());

    //tqDebug(bSteadyCalc ? "bSteadyCalc":"NOT bSteadyCalc");
    //tqDebug(isLogarithmic? "isLogarithmic":"NOT isLogarithmic");

    // store whether this is a vertical axis or a horizontal axis
    const bool bVertAxis = (KDChartAxisParams::AxisPosLeft  == basicPos) ||
                           (KDChartAxisParams::AxisPosRight == basicPos);

    // store the coordinate number to be used for this axis
    const int coordinate = bVertAxis ? 1 : 2;

    // store whether our coordinates are double or TQDateTime values
    const TQVariant::Type valueType =
        (KDCHART_ALL_DATASETS == dataDataset)
        ? data.cellsValueType(                            coordinate )
        : data.cellsValueType( dataDataset, dataDataset2, coordinate );
    isDateTime = valueType == TQVariant::DateTime;
    bool bIsDouble = valueType == TQVariant::Double;

    autoDtLabels = isDateTime && ( KDCHART_AXIS_LABELS_AUTO_DATETIME_FORMAT
            == para.axisLabelsDateTimeFormat() );

    if( autoDtLabels || bSteadyCalc )
        ( ( KDChartAxisParams& ) para ).setAxisLabelsTouchEdges( true );

    bool bStatistical = KDChartParams::HiLo       == params_chartType
                     || KDChartParams::BoxWhisker == params_chartType;

    if ( !bVertAxis && KDChartParams::BoxWhisker == params_chartType
                    && ! para.axisLabelStringCount() ) {
        uint ds1 = (KDCHART_ALL_DATASETS == dataDataset)
            ? 0
            : dataDataset;
        uint ds2 = (KDCHART_ALL_DATASETS == dataDataset)
            ? data.usedRows() - 1
            : dataDataset2;
        for (uint i = ds1; i <= ds2; ++i)
            labelTexts.append(
                    TQObject::tr( "Series " ) + TQString::number( i + 1 ) );
        bDone = true;
    }

    double nLow   =  1.0 + bSteadyCalc;// ? 0.0 : data.colsScrolledBy();
    double nHigh  = 10.0;
    double nDelta =  1.0;
    if ( !bDone ) {
        bDone = true;

        // look if exact label specification was made via limits and delta
        if (       ! isLogarithmic
                && ! para.axisLabelStringCount()
                && ! ( KDCHART_AXIS_LABELS_AUTO_LIMIT == para.axisValueStart() )
                && ! ( KDCHART_AXIS_LABELS_AUTO_LIMIT == para.axisValueEnd() )
                && ! ( para.axisValueStart() == para.axisValueEnd() )
                && ! ( KDCHART_AXIS_LABELS_AUTO_DELTA == para.axisValueDelta() )
                && ! ( 0.0 == para.axisValueDelta() ) ) {
            nLow   = para.axisValueStart().toDouble();
            nHigh  = para.axisValueEnd().toDouble();
            nDelta = para.axisValueDelta();
            int behindComma = para.axisDigitsBehindComma();
            int trueBehindComma = -1;
            bool upwards = (nLow < nHigh);
            if( upwards != (0.0 < nDelta) )
                nDelta *= -1.0;
            double nVal = nLow;
            bDone = false;
            bool bShowVeryLastLabel = false;
            //tqDebug("\n nLow: %f,  nHigh: %f,  nDelta: %f", nLow, nHigh, nDelta );
            while( bShowVeryLastLabel || (upwards ? (nVal <= nHigh) : (nVal >= nHigh)) ){
                //tqDebug("nVal    : %f", nVal );
                labelTexts.append( applyLabelsFormat( nVal,
                                                      divPow10,
                                                      behindComma,
                                                      nDelta,
                                                      trueBehindComma,
                                                      notation,
                                                      decimalPoint,
                                                      thousandsPoint,
                                                      prefix,
                                                      postfix,
                                                      totalLen,
                                                      padFill,
                                                      blockAlign ) );
                nVal += nDelta;
                //tqDebug("nVal-neu: %f", nVal );
                if( ! (upwards ? (nVal <= nHigh) : (nVal >= nHigh)) ){
                    // work around a rounding error: show the last label, even if not nVal == nHigh is not matching exactly
                    if( bShowVeryLastLabel )
                        bShowVeryLastLabel = false;
                    else{
                        TQString sHigh(  applyLabelsFormat( nHigh,
                                                           divPow10,
                                                           behindComma,
                                                           nDelta,
                                                           trueBehindComma,
                                                           notation,
                                                           decimalPoint,
                                                           thousandsPoint,
                                                           prefix,
                                                           postfix,
                                                           totalLen,
                                                           padFill,
                                                           blockAlign ) );
                        TQString sValue( applyLabelsFormat( nVal,
                                                           divPow10,
                                                           behindComma,
                                                           nDelta,
                                                           trueBehindComma,
                                                           notation,
                                                           decimalPoint,
                                                           thousandsPoint,
                                                           prefix,
                                                           postfix,
                                                           totalLen,
                                                           padFill,
                                                           blockAlign ) );
                        bShowVeryLastLabel = (sValue == sHigh);
                        //tqDebug("test:                 sHigh: "+sHigh+"   sValue: "+sValue );
                    }
                }
                bDone = true;
            }
            ( ( KDChartAxisParams& ) para ).setTrueAxisLowHighDelta( nLow, nHigh, nDelta );
            //tqDebug("\n[Z-0] nLow: %f,  nHigh: %f,  nDelta: %f", nLow, nHigh, nDelta );
        }         // look if a string list was specified
        else if ( para.axisLabelStringCount() ) {
            int nLabels = bSteadyCalc
                ? para.axisLabelStringCount()
                : bStatistical ? data.usedRows() : data.usedCols();
            calculateBasicTextFactors( nTxtHeight, para, averageValueP1000,
                    basicPos, orig, delimLen, nLabels,
                    // start of return parameters
                    pDelimDelta,
                    pTextsX, pTextsY, pTextsW, pTextsH,
                    textAlign );
            bool useShortLabels = false;
            TQStringList tmpList( para.axisLabelStringList() );

            // find start- and/or end-entry
            int iStart = 0;
            int iEnd = para.axisLabelStringCount() - 1;
            if(    ! ( KDCHART_AXIS_LABELS_AUTO_LIMIT == para.axisValueStart() )
                || ! ( KDCHART_AXIS_LABELS_AUTO_LIMIT == para.axisValueEnd() ) ) {
                const bool testStart = !( TQVariant::String == para.axisValueStart().type() );
                const bool testEnd   = !( TQVariant::String == para.axisValueEnd().type() );
                TQString sStart = testStart
                    ? para.axisValueStart().toString().upper()
                    : TQString();
                TQString sEnd = testEnd
                    ? para.axisValueEnd().toString().upper()
                    : TQString();

                uint i = 0;
                for ( TQStringList::Iterator it = tmpList.begin();
                        it != tmpList.end(); ++it, ++i ) {
                    if ( 0 == iStart &&
                         0 == TQString::compare( sStart, ( *it ).upper() ) ) {
                        iStart = i;
                    }
                    if ( 0 == TQString::compare( sEnd, ( *it ).upper() ) ) {
                        iEnd = i;
                    }
                }
            }

            // check text widths to ensure all the entries will fit
            // into the available space
            if (    para.axisLabelStringCount()
                 && para.axisShortLabelsStringCount()
                 && para.axisLabelStringList() != para.axisShortLabelsStringList() ) {
                TQFont font( para.axisLabelsFont() );
                if ( para.axisLabelsFontUseRelSize() )
                    font.setPixelSize( static_cast < int > ( nTxtHeight ) );
                painter->setFont( font );
                TQFontMetrics fm( painter->fontMetrics() );

                TQStringList::Iterator it = tmpList.begin();
                for ( int i = 0; i < nLabels; ++i ) {
                    if ( it != tmpList.end() ) {
                        if ( fm.width( *it ) > pTextsW ) {
                            useShortLabels = true;
                            break;
                        }
                        ++it;
                    }
                }
            }
            if ( useShortLabels )
                tmpList = para.axisShortLabelsStringList();
            else
                tmpList = para.axisLabelStringList();

            // prepare transfering the strings into the labelTexts list
            double ddelta
                = ( KDCHART_AXIS_LABELS_AUTO_DELTA == para.axisValueDelta() )
                ? 1.0
                : para.axisValueDelta();
            modf( ddelta, &ddelta );
            bool positive = ( 0.0 <= ddelta );
            int delta = static_cast < int > ( fabs( ddelta ) );
            // find 1st significant entry
            TQStringList::Iterator it = positive
                ? tmpList.begin()
                : tmpList.fromLast();
            if ( positive )
                for ( int i = 0; i < (int)tmpList.count(); ++i ) {
                    if ( i >= iStart )
                        break;
                    ++it;
                }
            else
                for ( int i = tmpList.count() - 1; i >= 0; --i ) {
                    if ( i <= iEnd )
                        break;
                    --it;
                }
            // transfer the strings
            int meter = delta;
            int i2 = positive ? iStart : iEnd;
            for ( int iLabel = 0; iLabel < nLabels; ) {
                if ( positive ) {
                    if ( it == tmpList.end() ) {
                        it = tmpList.begin();
                        i2 = 0;
                    }
                } else {
                    if ( it == tmpList.begin() ) {
                        it = tmpList.end();
                        i2 = tmpList.count();
                    }
                }
                if ( ( positive && i2 >= iStart )
                        || ( !positive && i2 <= iEnd ) ) {
                    if ( meter >= delta ) {
                        labelTexts << *it;
                        ++iLabel;
                        meter = 1;
                    } else {
                        meter += 1;
                    }
                }
                if ( positive ) {
                    if ( i2 == iEnd ) {
                        it = tmpList.begin();
                        i2 = 0;
                    } else {
                        ++it;
                        ++i2;
                    }
                } else {
                    if ( i2 == iStart ) {
                        it = tmpList.end();
                        i2 = tmpList.count();
                    } else {
                        --it;
                        --i2;
                    }
                }
            }
        } else {
            // find out if the associated dataset contains only strings
            // if yes, we will take these as label texts
            uint dset = ( dataset == KDCHART_ALL_DATASETS ) ? 0 : dataset;
            //tqDebug("\ndset: %u", dset);
            bDone = false;
            TQVariant value;
            for ( uint col = 0; col < data.usedCols(); ++col ) {
                if( data.cellCoord( dset, col, value, coordinate ) ){
                    if( TQVariant::String == value.type() ){
                        const TQString sVal = value.toString();
                        if( !sVal.isEmpty() && !sVal.isNull() ){
                            labelTexts.append( sVal );
                            bDone = true;
                        }
                    }else{
                        labelTexts.clear();
                        bDone = false;
                        break;
                    }
                }
            }
        }
    }


    if ( bDone ) {
        // Some strings were found, now let us see which of them are
        // actually to be taken right now.
        //
        //
        //   F E A T U R E   P L A N N E D   F O R   F U T U R E . . .
        //
        //

    }
    else {
        // No strings were found, so let us either calculate the texts
        // based upon the numerical values of the associated dataset(s)
        // or just compose some default texts...
        if ( data.usedCols() && bSteadyCalc ) {
            // double values for numerical coordinates
            double nLow = 0.01;
            double nHigh = 0.0;
            double orgLow = 0.0;
            double orgHigh = 0.0;
            double nDelta = 0.0;
            double nDist = 0.0;

            //  VERTICAL axes support three modes:
            enum { Normal, Stacked, Percent } mode;

            if( bVertAxis ){
                switch ( params_chartType ) {
                    case KDChartParams::Bar:
                        if ( KDChartParams::BarStacked
                                == params.barChartSubType() )
                            mode = Stacked;
                        else if ( KDChartParams::BarPercent
                                == params.barChartSubType() )
                            mode = Percent;
                        else
                            mode = Normal;
                        break;
                    case KDChartParams::Line:
                        if ( KDChartParams::LineStacked
                                == params.lineChartSubType() )
                            mode = Stacked;
                        else if ( KDChartParams::LinePercent
                                == params.lineChartSubType() )
                            mode = Percent;
                        else
                            mode = Normal;
                        break;
                    case KDChartParams::Area:
                        if ( KDChartParams::AreaStacked
                                == params.areaChartSubType() )
                            mode = Stacked;
                        else if ( KDChartParams::AreaPercent
                                == params.areaChartSubType() )
                            mode = Percent;
                        else
                            mode = Normal;
                        break;
                    case KDChartParams::HiLo:
                    case KDChartParams::BoxWhisker:
                        mode = Normal;
                        break;
                    case KDChartParams::Polar:
                        if ( KDChartParams::PolarStacked
                                == params.polarChartSubType() )
                            mode = Stacked;
                        else if ( KDChartParams::PolarPercent
                                == params.polarChartSubType() )
                            mode = Percent;
                        else
                            mode = Normal;
                        break;
                    default: {
                                 // Should not happen
                                 tqDebug( "IMPLEMENTATION ERROR: Unknown params_chartType in calculateLabelTexts()" );
                                 mode = Normal;
                             }
                }
            }else
                mode = Normal; // this axis is not a vertical axis

            uint nLabels = 200;

            // find highest and lowest value of associated dataset(s)
            bool bOrdFactorsOk = false;

            if( adjustTheValues ){
                nDelta = fabs( trueDelta );
                pDelimDelta = trueDeltaPix;
                nLow = TQMIN( para.trueAxisLow(), para.trueAxisHigh() );
                //tqDebug("\nsearching: para.trueAxisLow() %f    para.trueAxisHigh() %f",para.trueAxisLow(),para.trueAxisHigh());
                double orgLow( nLow );
                modf( nLow / nDelta, &nLow );
                nLow *= nDelta;
                if ( nLow > orgLow )
                    nLow -= nDelta;
                if ( 0.0 < nLow && 0.0 >= orgLow )
                    nLow = 0.0;
                nHigh = nLow;
                double dx = fabs( pXDeltaFactor * pDelimDelta );
                double dy = fabs( pYDeltaFactor * pDelimDelta );
                double x = 0.0;
                double y = 0.0;
                nLabels = 1;
                if( axisLength ){
                    do{
                        ++nLabels;
                        nHigh += nDelta;
                        x += dx;
                        y += dy;
                    }while( x < axisLength && y < axisLength );
                    nHigh -= nDelta;
                    --nLabels;
                }
                nDist = nHigh - nLow;
                bOrdFactorsOk = true;

            }

            if( !bOrdFactorsOk ){
                const bool bAutoCalcStart =
                       ( Percent != mode )
                    && ( KDCHART_AXIS_LABELS_AUTO_LIMIT == para.axisValueStart() );
                const bool bAutoCalcEnd =
                       ( Percent != mode )
                    && ( KDCHART_AXIS_LABELS_AUTO_LIMIT == para.axisValueEnd() );

                if( !bIsDouble && !isDateTime ){
                    // no data at all: let us use our default 0..10 range
                    nLow   = 0.0;
                    nHigh  = 10.0;
                    nDist  = 10.0;
                    nDelta = 1.0;
                    nSubDelimFactor = 0.5;
                    bIsDouble     = true;
                    bOrdFactorsOk = true;
                }else if( mode == Percent ){
                    // precentage mode: we use a 0..100 range
                    nLow   =   0.0;
                    nHigh  = 100.0;
                    nDist  = 100.0;
                    nDelta =  10.0;
                    nSubDelimFactor = 0.25;
                    bOrdFactorsOk = true;
                }else{
                    //tqDebug("\ngo:      nLow:  %f  nHigh: %f", nLow, nHigh );
                    // get the raw start value
                    const bool bStackedMode = (mode == Stacked);
                    if( bAutoCalcStart ){
                        if ( dataDataset == KDCHART_ALL_DATASETS ) {
                            if( bIsDouble ){
                                nLow = bStackedMode
                                     ? TQMIN( data.minColSum(), 0.0 )
                                     : data.minValue( coordinate,
                                                      isLogarithmic );
                                //tqDebug("\n1:      nLow:  %f", nLow );

                            }else{
                                dtLow = data.minDtValue( coordinate );
                            }
                        } else {
                            if( bIsDouble ){
                                nLow = bStackedMode
                                     ? TQMIN( data.minColSum( dataDataset, dataDataset2 ),
                                             0.0 )
                                     : data.minInRows( dataDataset,dataDataset2,
                                                       coordinate,
                                                       isLogarithmic );
                            }else{
                                dtLow = data.minDtInRows( dataDataset,dataDataset2,
                                                          coordinate );
                            }
                        }
                    }else{
                        if( bIsDouble ){
                            if( TQVariant::Double == para.axisValueStart().type() )
                                nLow  = para.axisValueStart().toDouble();
                        }else{
                            if( TQVariant::DateTime == para.axisValueStart().type() )
                                dtLow = para.axisValueStart().toDateTime();
                        }
                    }

                    // get the raw end value
                    if( bAutoCalcEnd ){
                        if ( dataDataset == KDCHART_ALL_DATASETS ) {
                            if( bIsDouble ){
                                nHigh = bStackedMode
                                      ? TQMAX( data.maxColSum(), 0.0 )
                                      : data.maxValue( coordinate );
                            }else{
                                dtHigh = data.maxDtValue( coordinate );
                            }
                        } else {
                            if( bIsDouble )
                                nHigh = bStackedMode
                                      ? TQMAX( data.maxColSum( dataDataset, dataDataset2 ),
                                              0.0 )
                                      : data.maxInRows( dataDataset,dataDataset2,
                                                        coordinate );
                            else
                                dtHigh = data.maxDtInRows( dataDataset,dataDataset2,
                                                          coordinate );
                        }
                        //tqDebug("\nbAutoCalcEnd:\n  nLow:  %f\n  nHigh: %f", nLow, nHigh );
                    }else{
                        if( bIsDouble ){
                            if( TQVariant::Double == para.axisValueEnd().type() )
                                nHigh = para.axisValueEnd().toDouble();
                        }else{
                            if( TQVariant::DateTime == para.axisValueEnd().type() )
                                dtHigh = para.axisValueEnd().toDateTime();
                        }
                    }
                }


                //tqDebug("\nnew:      nLow:  %f  nHigh: %f", nLow, nHigh );

                if( bIsDouble ) {
                    if(    DBL_MAX == nLow
                        || (    ( 0.0 == nHigh || 0 == nHigh )
                             && ( 0.0 == nLow  || 0 == nLow  ) ) ) {
                        // tqDebug("NO values or all values have ZERO value, showing 0.0 - 10.0 span");
                        nLow   = 0.0;
                        nHigh  = 10.0;
                        nDist  = 10.0;
                        nDelta = 1.0;
                        nSubDelimFactor = 0.5;
                        bOrdFactorsOk = true;
                        //tqDebug("nLow: %f,  nHigh: %f", nLow, nHigh);
                    }else if( nLow == nHigh ){
                        // if both values are equal, but NOT Zero
                        // -> move the appropriate one to Zero
                        if( nLow < 0.0 )
                            nHigh = 0.0;
                        else
                            nLow = 0.0;
                        //tqDebug("nLow: %f,  nHigh: %f", nLow, nHigh);
                    }else if( nHigh < nLow ){
                        // make sure nLow is <= nHigh
                        double nTmp = nLow;
                        nLow = nHigh;
                        nHigh = nTmp;
                    }
                } else if( isDateTime ){
                    bool toggleDts = dtLow > dtHigh;
                    if( toggleDts ) {
                        TQDateTime dt( dtLow );
                        dtLow = dtHigh;
                        dtHigh = dt;
                    }
                    double secDist = dtLow.secsTo( dtHigh );
                    secDist += (dtHigh.time().msec() - dtLow.time().msec()) / 1000.0;
                    const double aDist = fabs( secDist );
                    const double secMin   = 60.0;
                    const double secHour  = 60.0 * secMin;
                    const double secDay   = 24.0 * secHour;
                    //
                    // we temporarily disable week alignment until bug
                    // is fixed (1st week of year must not start in the
                    // preceeding year but rather be shown incompletely)
                    //
                    //                                 (khz, 2003/10/10)
                    //
                    //const int secWeek  =  7 * secDay;
                    const double secMonth = 30 * secDay;   // approx.
                    const double secYear  = 12 * secMonth; // approx.
                    if(      2.0*secMin > aDist )
                        dtDeltaScale = KDChartAxisParams::ValueScaleSecond;
                    else if( 2.0*secHour > aDist )
                        dtDeltaScale = KDChartAxisParams::ValueScaleMinute;
                    else if( 2.0*secDay > aDist )
                        dtDeltaScale = KDChartAxisParams::ValueScaleHour;
                    // khz: else if( 2*secWeek > aDist )
                    // khz:    dtDeltaScale = KDChartAxisParams::ValueScaleDay;
                    else if( 2.0*secMonth > aDist )
                        dtDeltaScale = KDChartAxisParams::ValueScaleDay;
                    // khz: dtDeltaScale = KDChartAxisParams::ValueScaleWeek;

                    else if( 2.0*secYear > aDist )
                        dtDeltaScale = KDChartAxisParams::ValueScaleMonth;
                    else if( 10.0*secYear > aDist )
                        dtDeltaScale = KDChartAxisParams::ValueScaleQuarter;
                    else
                        dtDeltaScale = KDChartAxisParams::ValueScaleYear;


                    //const int yearLow   = dtLow.date().year();
                    const int monthLow  = dtLow.date().month();
                    // khz: currently unused: const int dowLow    = dtLow.date().dayOfWeek();
                    const int dayLow    = dtLow.date().day();
                    const int hourLow   = dtLow.time().hour();
                    const int minuteLow = dtLow.time().minute();
                    const int secondLow = dtLow.time().second();

                    //const int yearHigh   = dtHigh.date().year();
                    const int monthHigh  = dtHigh.date().month();
                    // khz: currently unused: const int dowHigh    = dtHigh.date().dayOfWeek();
                    const int hourHigh   = dtHigh.time().hour();
                    const int minuteHigh = dtHigh.time().minute();
                    const int secondHigh = dtHigh.time().second();
                    int yearLowD   = 0;
                    int monthLowD  = 0;
                    int dayLowD    = 0;
                    int hourLowD   = 0;
                    int minuteLowD = 0;
                    int secondLowD = 0;
                    int yearHighD   = 0;
                    int monthHighD  = 0;
                    int dayHighD    = 0;
                    int hourHighD   = 0;
                    int minuteHighD = 0;
                    int secondHighD = 0;
                    bool gotoEndOfMonth = false;
                    switch( dtDeltaScale ) {
                        case KDChartAxisParams::ValueScaleSecond:
                            //tqDebug("\nKDChartAxisParams::ValueScaleSecond");
                            if( 5.0 < aDist ){
                                secondLowD = secondLow % 5;
                                if( secondHigh % 5 )
                                    secondHighD = 5 - secondHigh % 5;
                            }
                            break;
                        case KDChartAxisParams::ValueScaleMinute:
                            //tqDebug("\nKDChartAxisParams::ValueScaleMinute");
                            secondLowD = secondLow;
                            secondHighD = 59-secondHigh;
                            break;
                        case KDChartAxisParams::ValueScaleHour:
                            //tqDebug("\nKDChartAxisParams::ValueScaleHour");
                            minuteLowD = minuteLow;
                            secondLowD = secondLow;
                            minuteHighD = 59-minuteHigh;
                            secondHighD = 59-secondHigh;
                            break;
                        case KDChartAxisParams::ValueScaleDay:
                            //tqDebug("\nKDChartAxisParams::ValueScaleDay");
                            hourLowD   = hourLow;
                            minuteLowD = minuteLow;
                            secondLowD = secondLow;
                            hourHighD   = 23-hourHigh;
                            minuteHighD = 59-minuteHigh;
                            secondHighD = 59-secondHigh;
                            break;
                        case KDChartAxisParams::ValueScaleWeek:
                            //tqDebug("\nKDChartAxisParams::ValueScaleWeek");
                            // khz: week scaling is disabled at the moment
                            /*
                            dayLowD = dowLow - 1;
                            hourLowD   = hourLow;
                            minuteLowD = minuteLow;
                            secondLowD = secondLow;
                            if( 7 > dowHigh )
                            dayHighD = 7 - dowHigh + 1;
                            */
                            break;
                        case KDChartAxisParams::ValueScaleMonth:
                            //tqDebug("\nKDChartAxisParams::ValueScaleMonth");
                            if( 1 < dayLow )
                                dayLowD = dayLow - 1;
                            hourLowD   = hourLow;
                            minuteLowD = minuteLow;
                            secondLowD = secondLow;
                            gotoEndOfMonth = true;
                            break;
                        case KDChartAxisParams::ValueScaleQuarter:
                            //tqDebug("\nKDChartAxisParams::ValueScaleQuarter");
                            monthLowD = ( monthLow - 1 ) % 3;
                            dayLowD    = dayLow;
                            hourLowD   = hourLow;
                            minuteLowD = minuteLow;
                            secondLowD = secondLow;
                            if( ( monthHigh - 1 ) % 3 )
                                monthHighD = 3 - ( monthHigh - 1 ) % 3;
                            gotoEndOfMonth = true;
                            break;
                        case KDChartAxisParams::ValueScaleYear:
                            //tqDebug("\nKDChartAxisParams::ValueScaleYear");
                            monthLowD  = monthLow;
                            dayLowD    = dayLow;
                            hourLowD   = hourLow;
                            minuteLowD = minuteLow;
                            secondLowD = secondLow;
                            if( 12 > monthHigh )
                                monthHighD = 12 - monthHigh;
                            gotoEndOfMonth = true;
                            break;
                        default:
                            /* NOOP */
                            break;
                    }
                    dtLow  = dtLow.addSecs(   -1 * (secondLowD + 60*minuteLowD + 3600*hourLowD) );
                    dtLow  = dtLow.addDays(   -1 * dayLowD   );
                    dtAddMonths( dtLow, -1 * monthLowD, dtLow );
                    dtAddYears(  dtLow, -1 * yearLowD,  dtLow );
                    dtHigh = dtHigh.addSecs(   secondHighD + 60*minuteHighD + 3600* hourHighD );
                    dtHigh = dtHigh.addDays(   dayHighD   );
                    dtAddMonths( dtHigh, monthHighD, dtHigh );
                    dtAddYears(  dtHigh, yearHighD,  dtHigh );
                    if( gotoEndOfMonth ){
                        dtHigh.setDate( TQDate( dtHigh.date().year(),
                                    dtHigh.date().month(),
                                    dtHigh.date().daysInMonth() ) );
                        dtHigh.setTime( TQTime( 23, 59, 59 ) );
                    }
                    if( toggleDts ) {
                        TQDateTime dt( dtLow );
                        dtLow = dtHigh;
                        dtHigh = dt;
                    }
                    // secDist = dtLow.secsTo( dtHigh );

                    // NOTE: nSubDelimFactor is not set here since it
                    //        cannot be used for TQDateTime values.
                    nSubDelimFactor = 0.0;
                    bOrdFactorsOk = true;
                }


                if( !bOrdFactorsOk ) {
                    // adjust one or both of our limit values
                    // according to max-empty-inner-span settings
                    nDist = nHigh - nLow;
                    if( !isLogarithmic ){
                        // replace nLow (or nHigh, resp.) by zero if NOT ALL OF
                        // our values are located outside of the 'max. empty
                        //  inner space' (i.e. percentage of the y-axis range
                        // that may to contain NO data entries)
                        int maxEmpty = para.axisMaxEmptyInnerSpan();
                        if( bAutoCalcStart ) {
                            //tqDebug("\nbAutoCalcStart:\n  nLow:  %f\n  nHigh: %f", nLow, nHigh );
                            if( 0.0 < nLow ) {
                                if(    maxEmpty == KDCHART_AXIS_IGNORE_EMPTY_INNER_SPAN
                                    || maxEmpty > ( nLow / nHigh * 100.0 ) )
                                    nLow = 0.0;
                                else if( nDist / 100.0 < nLow )
                                    nLow -= nDist / 100.0; // shift lowest value
                            }
                            else if( nDist / 100.0 < fabs( nLow ) )
                                nLow -= nDist / 100.0; // shift lowest value
                            nDist = nHigh - nLow;
                            //tqDebug("* nLow:  %f\n  nHigh: %f", nLow, nHigh );
                        }
                        if( bAutoCalcEnd ) {
                            //tqDebug("\nbAutoCalcEnd:\n  nLow:  %f\n  nHigh: %f", nLow, nHigh );
                            if( 0.0 > nHigh ) {
                                if(    maxEmpty == KDCHART_AXIS_IGNORE_EMPTY_INNER_SPAN
                                        || maxEmpty > ( nHigh / nLow * 100.0 ) )
                                    nHigh = 0.0;
                                else if( nDist / 100.0 > nHigh )
                                    nHigh += nDist / 100.0; // shift highest value
                            }
                            else if( nDist / 100.0 < fabs( nHigh ) )
                                 nHigh += nDist / 100.0; // shift highest value
                            nDist = nHigh - nLow;
                            //tqDebug("* nLow:  %f\n  nHigh: %f\n\n", nLow, nHigh );
                        }
                    }
                }


                if( isLogarithmic ){
                    if( bIsDouble ) {
                        //tqDebug("\n[L--] nLow: %f,  nHigh: %f,  nDelta: %f", nLow, nHigh, nDelta );
                        if( 0.0 == TQABS( nLow ) )
                            nLow = -5;
                        else{
                            // find the Low / High values for the log. axis
                            nLow = log10( TQABS( nLow ) );
                            //if( 0.0 >= nLow ){
                                //nLow = fastPow10( -nLow );
                            //}
                        }
                        nHigh = log10( TQABS( nHigh ) );

                        //tqDebug("[L-0] nLow: %f,  nHigh: %f", nLow, nHigh );
                        double intPart=0.0; // initialization necessary for Borland C++
                        double fractPart = modf( nLow, &intPart );
                        //tqDebug("  intPart: %f\nfractPart: %f", intPart, fractPart );
                        if( 0.0 > nLow && 0.0 != fractPart )
                            nLow = intPart - 1.0;
                        else
                            nLow = intPart;
                        fractPart = modf( nHigh, &intPart );
                        if( 0.0 != fractPart )
                          nHigh = intPart + 1.0;

                        nDist = nHigh - nLow;
                        nDelta = 1.0;
                        nSubDelimFactor = 0.1;
                        //tqDebug("\n[L-1] nLow: %f,  nHigh: %f,  nDelta: %f", nLow, nHigh, nDelta );
                        bOrdFactorsOk = true;
                    }
                }


                if ( !bOrdFactorsOk ) {
                    // adjust one or both of our limit values
                    // according to first two digits of (nHigh - nLow) delta
                    double nDivisor;
                    double nRound;
                    nDist = nHigh - nLow;
                    //tqDebug("* nLow:  %f\n  nHigh: %f  nDist: %f\n\n", nLow, nHigh, nDist );
                    // find out factors and adjust nLow and nHigh
                    orgLow  = nLow;
                    orgHigh = nHigh;
                    calculateOrdinateFactors( para, isLogarithmic,
                                              nDist, nDivisor, nRound,
                                              nDelta, nSubDelimFactor,
                                              nLow, nHigh );
                    nLabels = params.roundVal( nDist / nDelta );

                    //tqDebug("\n0.  nOrgHigh: %f\n    nOrgLow:  %f",
                    //       orgHigh, orgLow);
                    //tqDebug("\n    nDist:    %f\n    nHigh:    %f\n    nLow:     %f",
                    //       nDist, nHigh, nLow);
                    //tqDebug("    nDelta: %f", nDelta);
                    //tqDebug("    nRound: %f", nRound);
                    //tqDebug("    nLabels: %u", nLabels);

                    if( para.axisSteadyValueCalc() ) {
                        ++nLabels;
                        //tqDebug("*   nLabels: %u", nLabels );
                    }
                }


                // calculate the amount of nLabels to be written we could take
                // based on the space we have for writing the label texts
                if( ! (    KDCHART_AXIS_LABELS_AUTO_DELTA
                        == para.axisValueDelta() ) ){
                    nDist = nHigh - nLow;
                    nDelta = para.axisValueDelta();
                    nLabels = params.roundVal( nDist / nDelta );

                    //tqDebug("\nI nLow: %f\n  nHigh: %f\n  nDelta: %f\n  nLabels: %u",
                    //       nLow, nHigh, nDelta, nLabels );

                    if( para.axisSteadyValueCalc() ) {
                        ++nLabels;

                        //tqDebug("* nLabels: %u", nLabels );

                    }
                }

                // make sure labels fit into available height, if vertical axis
                if( bVertAxis ) {
                    //Pending Michel
                    //find out the width
                    const KDChartAxisParams & xpara = params.axisParams( KDChartAxisParams::AxisPosBottom );
                    double areaWidth = xpara.axisTrueAreaRect().width();
                    //make sure to avoid inf
                    double areaHeight = para.axisTrueAreaRect().height()>0?para.axisTrueAreaRect().height():1.0;
                    double widthHeight = areaWidth / areaHeight;
                    //tqDebug( "widthHeight %f, nDelta %f", widthHeight, nDelta);
                    //tqDebug( "maxValue %f", data.maxValue());
                    //tqDebug( "maxColSum %f", data.maxColSum());
                    //tqDebug( "axisValueEnd() %f", para.axisValueEnd().toDouble());
                    double nDivisor;
                    double nRound;
                    orgLow = nLow;
                    orgHigh = nHigh;

                    //check if there are axis limitation - if not (auto calculation):
                    //adjust the axis for 3dbars in order to display the whole top of the bar
                    //in relation to the with and the height of the area.
                    // add conditions for multirows here
                    if ( KDCHART_AXIS_LABELS_AUTO_LIMIT == para.axisValueEnd().toDouble()) {
                        if (params.threeDBars() ) {
                            if (  KDChartParams::BarPercent != params.barChartSubType()) {
                                if ( widthHeight > 1.5 )
                                    orgHigh += nDelta * widthHeight;
                                else
                                    orgHigh += widthHeight * 0.5;
                            }
                        }
                    }  else {
                        orgHigh = nHigh = para.axisValueEnd().toDouble();
                    }
                    //tqDebug("\ncalc ordinate 0.  nDist: %f\n  nLow: %f\n  nHigh: %f\n  nDelta: %f\n  nLabels: %u", nDist, nLow, nHigh, nDelta, nLabels );
                    bool bTryNext = false;
                    uint minLabels = para.axisSteadyValueCalc() ? 3 : 2;
                    // the following must be processed at least twice - to avoid rounding errors
                    int pass = 0;
                    do{
                        nDist = nHigh - nLow;
                        nLow = orgLow;
                        nHigh = orgHigh;
                        /*
                        tqDebug("\n=============================================================================\ncalc ordinate 1.  nDist: %f\n  nLow: %f\n  nHigh: %f\n  nDelta: %f\n  nLabels: %u",
                        nDist, nLow, nHigh, nDelta, nLabels );
                        */
                        calculateOrdinateFactors( para, isLogarithmic,
                                nDist, nDivisor, nRound,
                                nDelta,
                                nSubDelimFactor, nLow, nHigh,
                                bTryNext );
                        nLabels = params.roundVal( nDist / nDelta );

                        //tqDebug("\ncalc ordinate 2.  nDist: %f\n+ nLow: %f\n  nHigh: %f\n  nDelta: %f\n  nLabels: %u",
                        //nDist, nLow, nHigh, nDelta, nLabels );
                        //TQString sDelta;sDelta.setNum( nDelta, 'f', 24 );
                        //TQString sLow;    sLow.setNum( nLow,   'f', 24 );
                        //tqDebug("nLow: %f,  sLow: %s,  sDelta: %s", nLow, sLow.latin1(), sDelta.latin1());

                        // special case: End values was set by the user, but no Detla values was set.
                        if( !bAutoCalcEnd && orgHigh > nLow + nLabels * nDelta ) {
                            ++nLabels;
                            //tqDebug("\nnLabels: %u\n", nLabels );
                        }
                        if( para.axisSteadyValueCalc() ) {
                            ++nLabels;
                            //tqDebug("\nnLabels: %u\n", nLabels );
                        }
                        //tqDebug("calc ordinate n.  nDist = nHigh - nLow: %f = %f - %f",nDist, nHigh, nLow);
                        //tqDebug("    nRound: %f\n", nRound);
                        bTryNext = true;
                        ++pass;
                    }while (    ( pass < 2 )
                             || (    ( minLabels < nLabels )
                                  && ( areaHeight < ( nTxtHeight * 1.5 ) * nLabels ) ) );
                }
            }

            // finally we can build the texts
            if( bIsDouble ) {
                int trueBehindComma = -1;
                double nVal = nLow;
                for ( uint i = 0; i < nLabels; ++i ) {
		  if( isLogarithmic ) {
                        labelTexts.append( applyLabelsFormat(
                            fastPow10( static_cast < int > ( nVal ) ),
                            divPow10,
                            behindComma,
                            1.0 == nDelta ? KDCHART_AXIS_LABELS_AUTO_DELTA : nDelta,
                            trueBehindComma,
                            notation,
                            decimalPoint,
                            thousandsPoint,
                            prefix,
                            postfix,
                            totalLen,
                            padFill,
                            blockAlign ) );
                  }  else {
                        labelTexts.append( applyLabelsFormat( nVal,
                                                              divPow10,
                                                              behindComma,
                                                              nDelta,
                                                              trueBehindComma,
                                                              notation,
                                                              decimalPoint,
                                                              thousandsPoint,
                                                              prefix,
                                                              postfix,
                                                              totalLen,
                                                              padFill,
                                                              blockAlign ) );
		  }
                    nVal += nDelta;
                }

                // save our true Low and High value
                //tqDebug(para.axisSteadyValueCalc()?"\ntrue " : "\nfalse");
                //tqDebug("nVal: %f,  nDelta: %f", nVal, nDelta );
                if ( para.axisSteadyValueCalc() ) {
                    nHigh = nVal - nDelta;
                }
                ( ( KDChartAxisParams& ) para ).setTrueAxisLowHighDelta( nLow, nHigh, nDelta );
                //tqDebug("[Z] nLow: %f,  nHigh: %f,  nDelta: %f", nLow, nHigh, nDelta );

            } else {
                bool goDown = dtLow > dtHigh;
                int mult = goDown ? -1 : 1;
                TQDateTime dt( dtLow );
                nLabels = 0;
                /*
                   tqDebug("dtLow:  ");
                   tqDebug(dtLow.toString(  Qt::ISODate ));
                   tqDebug("dtHigh: ");
                   tqDebug(dtHigh.toString( Qt::ISODate ));
                   */
                bool bDone=false;
                while( !bDone ) {
                    /*
                       tqDebug("dtLow: %i %i %i    %i:%i:%i",
                       dtLow.date().year(),
                       dtLow.date().month(),
                       dtLow.date().day(),
                       dtLow.time().hour(),
                       dtLow.time().minute(),
                       dtLow.time().second());
                       tqDebug("dtHigh: %i %i %i    %i:%i:%i",
                       dtHigh.date().year(),
                       dtHigh.date().month(),
                       dtHigh.date().day(),
                       dtHigh.time().hour(),
                       dtHigh.time().minute(),
                       dtHigh.time().second());
                       tqDebug("dt: %i %i %i    %i:%i:%i",
                       dt.date().year(),
                       dt.date().month(),
                       dt.date().day(),
                       dt.time().hour(),
                       dt.time().minute(),
                       dt.time().second());
                       */
                    ++nLabels;
                    if( autoDtLabels )
                        labelTexts.append( "x" );
                    else
#if COMPAT_TQT_VERSION >= 0x030000
                        labelTexts.append( dt.toString( Qt::ISODate ) );
#else
                    labelTexts.append( dateTimeToString( dt ) );
#endif
                    bDone = (goDown ? (dt < dtLow ) : (dt > dtHigh));
                    /*if( bDone ){
                      dtHigh = dt;
                      }else*/{
                          switch( dtDeltaScale ) {
                              case KDChartAxisParams::ValueScaleSecond:
                                  dtAddSecs( dt, 1 * mult, dt );
                                  break;
                              case KDChartAxisParams::ValueScaleMinute:
                                  dtAddSecs( dt, 60 * mult, dt );
                                  break;
                              case KDChartAxisParams::ValueScaleHour:
                                  dtAddSecs( dt, 3600 * mult, dt );
                                  break;
                              case KDChartAxisParams::ValueScaleDay:
                                  dtAddDays( dt, 1 * mult, dt );
                                  break;
                              case KDChartAxisParams::ValueScaleWeek:
                                  dtAddDays( dt, 7 * mult, dt );
                                  break;
                              case KDChartAxisParams::ValueScaleMonth:
                                  dtAddMonths( dt,1 * mult, dt );
                                  break;
                              case KDChartAxisParams::ValueScaleQuarter:
                                  dtAddMonths( dt,3 * mult, dt );
                                  break;
                              case KDChartAxisParams::ValueScaleYear:
                                  dtAddYears( dt, 1 * mult, dt );
                                  break;
                              default:
                                  dtAddDays( dt, 1 * mult, dt );
                                  break;
                          }
                      }
                }
                //if( autoDtLabels )
                //    labelTexts.append( "x" );
                ( ( KDChartAxisParams& ) para ).setTrueAxisDtLowHighDeltaScale(
                                                                               dtLow, dtHigh,
                                                                               dtDeltaScale );
                // note: pDelimDelta will be calculated below,
                //       look for "COMMOM CALC OF NLABELS, DELIM DELTA..."
            }
            bDone = true;
        }

        // let's generate some strings
        if ( !bDone ) {
            // default scenario for abscissa axes
            uint count = bStatistical
                ? (data.usedRows() ? data.usedRows() : 1)
                : (data.usedCols() ? data.usedCols() : 1);
            //double start( 1.0 );
            double start( 1.0 + (bSteadyCalc ? 0.0 : static_cast < double >(data.colsScrolledBy())) );
//tqDebug("colsScrolledBy: %i", data.colsScrolledBy());
//if(bVertAxis)
//tqDebug("vert nVal starting: %f",start);
//else
//tqDebug("horz nVal starting: %f",start);
//if(bSteadyCalc)
//tqDebug("bSteadyCalc");
//else
//tqDebug("not bSteadyCalc");
            double delta( 1.0 );
            double finis( start + delta * ( count - 1 ) );
            const bool startIsDouble = TQVariant::Double == para.axisValueStart().type();
            const bool endIsDouble   = TQVariant::Double == para.axisValueEnd().type();

            bool deltaIsAuto = true;
            if ( !( KDCHART_AXIS_LABELS_AUTO_DELTA == para.axisValueDelta() ) ) {
                delta = para.axisValueDelta();
                deltaIsAuto = false;
            }
            if ( KDCHART_AXIS_LABELS_AUTO_LIMIT == para.axisValueStart() ) {
                if ( ( KDCHART_AXIS_LABELS_AUTO_LIMIT == para.axisValueEnd() ) ) {
                    finis = start + delta * ( count - 1 );
                } else {
                    if( endIsDouble ){
                        finis = para.axisValueEnd().toDouble();
                        start = finis - delta * ( count - 1 );
//tqDebug("1 changing:   start: %f",start);
                    } else {
                        //
                        //
                        //   F E A T U R E   P L A N N E D   F O R   F U T U R E . . .
                        //
                        //
                    }
                }
            }else{
                if ( startIsDouble ) {
                    start = para.axisValueStart().toDouble() + (bSteadyCalc ? 0.0 : static_cast < double >(data.colsScrolledBy()));
//tqDebug("2 changing:   start: %f",start);
                } else {
                    //
                    //
                    //   F E A T U R E   P L A N N E D   F O R   F U T U R E . . .
                    //
                    //
                }
                if ( !( KDCHART_AXIS_LABELS_AUTO_LIMIT == para.axisValueEnd() ) ) {
                    if (endIsDouble ) {
                        finis = para.axisValueEnd().toDouble();
                        if ( deltaIsAuto ) {
                            delta = ( finis - start ) / count;
                        } else {
                            count = static_cast < uint > (
                                    ( finis - start ) / delta );
                        }
                    } else {
                        // auto-rows like
                        // sunday, monday, tuesday, ...
                        //
                        //
                        //   F E A T U R E   P L A N N E D   F O R   F U T U R E . . .
                        //
                        //
                    }
                }
                else {
                    finis = start + delta * ( count - 1 );
                }
            }
            TQString prefix( TQObject::tr( "Item " ) );
            TQString postfix;


            if ( startIsDouble && endIsDouble ) {
                int precis =
                    KDCHART_AXIS_LABELS_AUTO_DIGITS == para.axisDigitsBehindComma()
                    ? 0
                    : para.axisDigitsBehindComma();
                double s = start;
                double f = finis;
//tqDebug("label loop:   s: %f   f: %f",s,f);
                bool up = ( 0.0 < delta );
                // check the text widths of one large(?) entry
                // and hope all the entries will
                // fit into the available space
                double value = up ? s : f;
                uint nLabels = 0;
                while ( up ? ( value <= f ) : ( value >= s ) ) {
                    ++nLabels;
                    value += delta * up ? 1.0 : -1.0;
                }
                calculateBasicTextFactors( nTxtHeight, para,
                        averageValueP1000,
                        basicPos, orig, delimLen, nLabels,
                        // start of return parameters
                        pDelimDelta,
                        pTextsX, pTextsY, pTextsW, pTextsH,
                        textAlign );
                TQFont font( para.axisLabelsFont() );
                if ( para.axisLabelsFontUseRelSize() )
                    font.setPixelSize( static_cast < int > ( nTxtHeight ) );
                painter->setFont( font );
                TQFontMetrics fm( painter->fontMetrics() );

                if ( fm.width( prefix +
                            TQString::number( -fabs( ( s + f ) / 2.0 + delta ),
                                'f', precis ) )
                        > pTextsW ) {
                    prefix = "";
                    postfix = "";
                }
                // now transfer the strings into labelTexts
                value = up ? s : f;
                while ( up ? ( value <= f ) : ( value >= s ) ) {
                    labelTexts.append(
                            prefix + TQString::number( value, 'f', precis )
                            + postfix );
                    value += delta * up ? 1.0 : -1.0;
                }
            } else {
                // pending(KHZ): make sure this branch will ever be reached
                // check the text widths largest entry
                // to make sure it will fit into the available space
                calculateBasicTextFactors( nTxtHeight, para,
                        averageValueP1000,
                        basicPos, orig, delimLen,
                        count,
                        // start of return parameters
                        pDelimDelta,
                        pTextsX, pTextsY, pTextsW, pTextsH,
                        textAlign );
                TQFont font( para.axisLabelsFont() );
                if ( para.axisLabelsFontUseRelSize() )
                    font.setPixelSize( static_cast < int > ( nTxtHeight ) );
                painter->setFont( font );
                TQFontMetrics fm( painter->fontMetrics() );

                if ( fm.width( prefix + TQString::number( count - 1 ) )
                        > pTextsW ) {
                    prefix = "";
                    postfix = "";
                }
                // now transfer the strings into labelTexts
                for ( uint i = 1; i <= count; ++i )
                    labelTexts.append(
                            prefix + TQString::number( i ) + postfix );
            }
        }
    }

    /*
        finishing: COMMOM CALC OF NLABELS, DELIM DELTA...
    */
    uint nLabels = labelTexts.count()
        ? labelTexts.count()
        : 0;
    ( ( KDChartAxisParams& ) para ).setAxisLabelTexts( &labelTexts );

    if( !adjustTheValues ){

        calculateBasicTextFactors( nTxtHeight, para, averageValueP1000,
                basicPos, orig, delimLen, nLabels,
                // start of return parameters
                pDelimDelta,
                pTextsX, pTextsY, pTextsW, pTextsH,
                textAlign );
    }

    ( ( KDChartAxisParams& ) para ).setTrueAxisDeltaPixels( pDelimDelta );

    //tqDebug("\nsetting:   para.trueAxisLow() %f    para.trueAxisHigh() %f",para.trueAxisLow(),para.trueAxisHigh());
    //tqDebug("\npDelimDelta: %f", pDelimDelta );

    /*
       tqDebug( "Found label texts:" );
       for ( TQStringList::Iterator it = labelTexts.begin();
       it != labelTexts.end(); ++it )
       tqDebug( ">>>  %s", (*it).latin1() );
       tqDebug( "\n" );
       */
//tqDebug("\nleaving KDChartAxesPainter::calculateLabelTexts() :   nTxtHeight: "+TQString::number(nTxtHeight));
}


/**
  Calculates some label text factors needed
  by function \c calculateLabelTexts()

  \note When calling this function the actual area size for this
  axis must be set, this means you may only call it when
  \c KDChartPainter::setupGeometry() has been called before.

  \param nTxtHeight the text height to be used for calculating
  the return values
  \param para the KDChartAxisParams that were specified for this axis
  \param averageValueP1000 (average height+width of the prtbl. area) / 1000
  \param basicPos the basic axis position returned by
  KDChartAxisParams::basicAxisPos()
  \param orig the axis start point
  \param delimLen the length of one delimiter mark
  \param nLabels the number of labels to be shown at this axis
  \param (all others) the reference parameters to be returned
  by this function
  */
/**** static ****/
void KDChartAxesPainter::calculateBasicTextFactors( double nTxtHeight,
        const KDChartAxisParams& para,
        double /*averageValueP1000*/,
        KDChartAxisParams::AxisPos basicPos,
        const TQPoint& orig,
        double delimLen,
        uint nLabels,
        // start of return params
        double& pDelimDelta,
        double& pTextsX,
        double& pTextsY,
        double& pTextsW,
        double& pTextsH,
        int& textAlign )
{
    switch ( basicPos ) {
        case KDChartAxisParams::AxisPosBottom: {
            bool bTouchEdges = para.axisLabelsTouchEdges();
            double wid = para.axisTrueAreaRect().width();
            double divi = bTouchEdges
                ? ( 1 < nLabels ? nLabels - 1 : 1 )
                : ( nLabels ? nLabels : 10 );
            pDelimDelta = wid / divi;

            pTextsW = pDelimDelta - 4.0;
            pTextsX = orig.x() + 2.0
                - ( bTouchEdges
                        ? pDelimDelta / 2.0
                        : 0.0 );
            pTextsH = para.axisTrueAreaRect().height() - delimLen * 1.33;
            pTextsY = orig.y()
                + delimLen * 1.33;
            textAlign = TQt::AlignHCenter | TQt::AlignTop;
            /*
              tqDebug("pTextsW %f    wid %f    nLabels %u", pTextsW, wid, nLabels );
            */
        }
        break;
        case KDChartAxisParams::AxisPosLeft: {
            double hig = para.axisTrueAreaRect().height();
            pDelimDelta = hig / ( 1 < nLabels ? nLabels - 1 : 1 );

            pTextsX = para.axisTrueAreaRect().bottomLeft().x()
                + 2.0;
            pTextsY = orig.y() - nTxtHeight / 2;
            pTextsW = para.axisTrueAreaRect().width()
                - delimLen * 1.33 - 2.0;
            pTextsH = nTxtHeight;
            textAlign = TQt::AlignRight | TQt::AlignVCenter;
        }
        break;
        case KDChartAxisParams::AxisPosTop: {
            bool bTouchEdges = para.axisLabelsTouchEdges();
            double wid = para.axisTrueAreaRect().width();
            double divi = bTouchEdges
                ? ( 1 < nLabels ? nLabels - 1 : 1 )
                : ( nLabels ? nLabels : 10 );
            pDelimDelta = wid / divi;

            pTextsW = pDelimDelta - 4.0;
            pDelimDelta = wid / divi;

            pTextsX = orig.x() + 2.0
                - ( bTouchEdges
                        ? pDelimDelta / 2.0
                        : 0.0 );
            pTextsH = para.axisTrueAreaRect().height() - delimLen * 1.33;
            pTextsY = para.axisTrueAreaRect().topLeft().y();
            textAlign = TQt::AlignHCenter | TQt::AlignBottom;
        }
        break;
        case KDChartAxisParams::AxisPosRight: {
            double hig = para.axisTrueAreaRect().height();
            pDelimDelta = hig / ( 1 < nLabels ? nLabels - 1 : 1 );

            pTextsX = para.axisTrueAreaRect().bottomLeft().x()
                + delimLen * 1.33;
            pTextsY = orig.y() - nTxtHeight / 2;
            pTextsW = para.axisTrueAreaRect().width()
                - delimLen * 1.33 - 2.0;
            pTextsH = nTxtHeight;
            textAlign = TQt::AlignLeft | TQt::AlignVCenter;
        }
        break;
        default: {
            tqDebug( "IMPLEMENTATION ERROR: KDChartAxesPainter::calculateBasicTextFactors() unhandled enum value." );
            // NOOP since the 'basicPos' does not support more that these four values.
        }
        break;
    }
}


/**
  Takes double \c nVal and returns a TQString showing the amount of digits
  behind the comma that was specified by \c behindComma (or calculated
  automatically by removing trailing zeroes, resp.).
  To make sure the resulting string looks fine together with other strings
  of the same label row please specify \c nDelta indicating the step width
  from one label text to the other.
  To prevent the function from having to re-calculate the number of
  digits to keep behind the comma, provide it with a temporary helper
  variable "trueBehindComma" that has to be initialized with a value
  smaller than zero.

  \note This function is reserved for internal use.
  */
TQString KDChartAxesPainter::truncateBehindComma( const double nVal,
        const int    behindComma,
        const double nDelta,
        int& trueBehindComma )
{
    const int  nTrustedPrecision = 6; // when using 15 we got 1.850000 rounded to 1.849999999999999

    const bool bUseAutoDigits = KDCHART_AXIS_LABELS_AUTO_DIGITS == behindComma;
    const bool bAutoDelta     = KDCHART_AXIS_LABELS_AUTO_DELTA == nDelta;
    TQString sVal;
    sVal.setNum( nVal, 'f', bUseAutoDigits ? nTrustedPrecision
                                           : TQMIN(behindComma, nTrustedPrecision) );
    //tqDebug("nVal: %f    sVal: "+sVal, nVal );
    //tqDebug( TQString("                     %1").arg(sVal));
    if ( bUseAutoDigits ) {
        int comma = sVal.find( '.' );
        if ( -1 < comma ) {
            if ( bAutoDelta ) {
                int i = sVal.length();
                while ( 1 < i
                        && '0' == sVal[ i - 1 ] )
                    --i;
                sVal.truncate( i );
                if ( '.' == sVal[ i - 1 ] )
                    sVal.truncate( i - 1 );
            } else {
                if ( 0 > trueBehindComma ) {
                    TQString sDelta = TQString::number( nDelta, 'f', nTrustedPrecision );
                    int i = sDelta.length();
                    while ( 1 < i
                            && '0' == sDelta[ i - 1 ] )
                        --i;
                    sDelta.truncate( i );
                    if ( '.' == sDelta[ i - 1 ] )
                        trueBehindComma = 0;
                    else {
                        int deltaComma = sDelta.find( '.' );
                        if ( -1 < deltaComma )
                            trueBehindComma = sDelta.length() - deltaComma - 1;
                        else
                            trueBehindComma = 0;
                    }
                }
                // now we cut off the too-many digits behind the comma
                int nPos = comma + ( trueBehindComma ? trueBehindComma + 1 : 0 );
                sVal.truncate( nPos );
            }
        }
    }
    //tqDebug( TQString("                       -  %1").arg(trueBehindComma));
    return sVal;
}

#if 0

#if defined ( TQ_WS_WIN)
#define trunc(x) ((int)(x))
#endif

#else

// Ugly hack because Solaris (among others?) doesn't have trunc(),
// since the libs are not C99.  I could do a complex #if expression,
// but instead I will just define trunc() here.

double trunc(double x)
{
    return x >= 0.0 ? floor(x) : -floor(-x);
}

#endif


TQString KDChartAxesPainter::applyLabelsFormat( const double nVal_,
                        int   divPow10,
                        int   behindComma,
                        double nDelta_,
                        int&  trueBehindComma,
                        KDChartEnums::NumberNotation notation,
                        const TQString& decimalPoint,
                        const TQString& thousandsPoint,
                        const TQString& prefix,
                        const TQString& postfix,
                        int            totalLen,
                        const TQChar&   padFill,
                        bool           blockAlign )
{
    double nVal = nVal_ / fastPow10( divPow10 );
    double nDelta = nDelta_;

    double valLog10 = 0.0;
    if( notation == KDChartEnums::NumberNotationScientific ||
        notation == KDChartEnums::NumberNotationScientificBig ){
        valLog10 = (nVal != 0.0) ? trunc( log10(TQABS(nVal)) ) : 0.0;
        //tqDebug("nVal old: %f   valLog10: %f",nVal,valLog10);
        nVal   /= fastPow10( valLog10 );
        nDelta /= fastPow10( valLog10 );
        //tqDebug("nVal new: %f",nVal);
    }
    TQString sVal = truncateBehindComma( nVal,
                                        behindComma,
                                        nDelta,
                                        trueBehindComma );
    //tqDebug("sVal    : "+sVal+"   behindComma: %i",behindComma);

    int posComma = sVal.find( '.' );
    if( 0 <= posComma ){
        sVal.replace( posComma, 1, decimalPoint);
    }else{
        posComma = sVal.length();
    }
    if( notation == KDChartEnums::NumberNotationScientific ||
        notation == KDChartEnums::NumberNotationScientificBig ){
        if( notation == KDChartEnums::NumberNotationScientific )
            sVal.append( "e" );
        else
            sVal.append( "E" );
        sVal.append( TQString::number( valLog10, 'f', 0 ) );
    } else {
        if( thousandsPoint.length() ){
            const int minLen = (0 < sVal.length() && '-' == sVal[0])
                            ? 4
                            : 3;
            int n = posComma; // number of digits at the left side of the comma
            while( minLen < n ){
                n -= 3;
                sVal.insert(n, thousandsPoint);
            }
        }
    }
    sVal.append( postfix );
    int nFill = totalLen - (sVal.length() + prefix.length());
    if( 0 > nFill )
        nFill = 0;
    if( !blockAlign )
        sVal.prepend( prefix );
    for(int i=0; i < nFill; ++i)
        sVal.prepend( padFill );
    if( blockAlign )
        sVal.prepend( prefix );
    if ( totalLen > 0 )
        sVal.truncate( totalLen );
    /*Pending Michel: Force non fractional values
     *In case it is a fractional value
     *and the user has set axisLabelsDigitsBehindComma() == 0
     *return an empty string
     */
    if ( behindComma == 0 && TQString::number(nVal).find('.') > 0 )
      sVal = TQString();//sVal = "";
    return sVal;
}

/**
  Calculates the factors to be used for calculating ordinate labels texts.

  \note This function is reserved for internal use.
  */
void KDChartAxesPainter::calculateOrdinateFactors(
        const KDChartAxisParams& para,
        bool isLogarithmic,
        double& nDist,
        double& nDivisor,
        double& nRound,
        double& nDelta,
        double& nSubDelimFactor,
        double& nLow,
        double& nHigh,
        bool findNextRound )
{
    if ( findNextRound ) {
        if ( 1.0 > nRound )
            nRound = 1.0;
        else
            if ( 2.0 > nRound )
                nRound = 2.0;
            else
                if ( 2.5 > nRound )
                    nRound = 2.5;
                else
                    if ( 5.0 > nRound )
                        nRound = 5.0;
                    else {
                        nDivisor *= 10.0;
                        nRound = 1.0;
                    }
    } else {
        nDivisor = 1.0;
        TQString sDistDigis2;
        sDistDigis2.setNum( nDist, 'f', 24);
        if ( 1.0 > nDist ) {
            sDistDigis2.remove( 0, 2 );
            nDivisor = 0.01;
            while ( 0 < sDistDigis2.length()
                    && '0' == sDistDigis2[ 0 ] ) {
                nDivisor *= 0.1;
                sDistDigis2.remove( 0, 1 );
            }
        } else {
            if ( 10.0 > nDist ) {
                nDivisor = 0.1;
                // remove comma, if present
                sDistDigis2.remove( 1, 1 );
            } else
                if ( 100.0 > nDist )
                    nDivisor = 1.0;
                else {
                    int comma = sDistDigis2.find( '.' );
                    if ( -1 < comma )
                        sDistDigis2.truncate( comma );
                    nDivisor = fastPow10( (int)sDistDigis2.length() - 2 );
                }
        }
        sDistDigis2.truncate( 2 );
        bool bOk;
        double nDistDigis2( sDistDigis2.toDouble( &bOk ) );
        if ( !bOk )
            nDistDigis2 = 10.0;
        if ( 75.0 <= nDistDigis2 )
            nRound = 5.0;
        else
            if ( 40.0 <= nDistDigis2 )
                nRound = 2.5;
            else
                if ( 20.0 <= nDistDigis2 )
                    nRound = 2.0;
                else
                    nRound = 1.0;
    }

    nDelta = nRound * nDivisor;

    // make sure its a whole number > 0 if its a log axis. Just round up.
    if( isLogarithmic )
        nDelta = static_cast < int > ( nDelta ) < nDelta
               ? static_cast < int > ( nDelta ) + 1
               : static_cast < int > ( nDelta );

    bool bInvertedAxis = ( 0.0 > nDist );
    if( bInvertedAxis )
        nDelta *= -1.0;

    /*
       tqDebug("  n D i s t       :  %f", nDist   );
       tqDebug("  n D i v i s o r :  %f", nDivisor);
       tqDebug("  n R o u n d     :  %f", nRound  );
       tqDebug("  n D e l t a     :  %f", nDelta  );
       tqDebug("  nHigh           :  %f", nHigh   );
       tqDebug("  nLow            :  %f", nLow    );
       */
    if(    KDCHART_AXIS_LABELS_AUTO_LIMIT == para.axisValueStart()
        || !para.axisValueStartIsExact() ) {
        double orgLow( nLow );
        modf( nLow / nDelta, &nLow );
        nLow *= nDelta;
        if( bInvertedAxis ){
            if ( nLow < orgLow )
                nLow += nDelta;
            if ( 0.0 > nLow && 0.0 <= orgLow )
                nLow = 0.0;
        }else{
            if ( nLow > orgLow )
                nLow -= nDelta;
            if ( 0.0 < nLow && 0.0 >= orgLow )
                nLow = 0.0;
        }
    }
    if ( KDCHART_AXIS_LABELS_AUTO_LIMIT == para.axisValueEnd() ) {
        double orgHigh( nHigh );
        modf( nHigh / nDelta, &nHigh );
        nHigh *= nDelta;
        if( bInvertedAxis ){
            if ( nHigh > orgHigh )
                nHigh -= nDelta;
            if ( 0.0 < nHigh && 0.0 >= orgHigh )
                nHigh = 0.0;
        }else{
            if ( nHigh < orgHigh )
                nHigh += nDelta;
            if ( 0.0 > nHigh && 0.0 <= orgHigh )
                nHigh = 0.0;
        }
    }

    //tqDebug("  n H i g h       :  %f", nHigh   );
    //tqDebug("  n L o w         :  %f\n\n", nLow    );

    if ( 1.0 == nRound )
        nSubDelimFactor = 0.5;
    else
        if ( 2.0 == nRound )
            nSubDelimFactor = 0.25;
        else
            if ( 2.5 == nRound )
                nSubDelimFactor = 0.2;
            else
                if ( 5.0 == nRound )
                    nSubDelimFactor = 0.2;
                else {
                    // Should not happen
                    tqDebug( "IMPLEMENTATION ERROR: Unknown nRound in calculateOrdinateFactors()" );
                    nSubDelimFactor = 1.0;
                }

    nDist = nHigh - nLow;
}

/**** static ****/
void KDChartAxesPainter::saveDrawLine( TQPainter& painter,
        TQPoint pA,
        TQPoint pZ,
        TQPen pen )
{
    const TQPen oldPen( painter.pen() );
    bool bNice =    ( pen.color() == oldPen.color() )
        && ( pen.width() == oldPen.width() )
        && ( pen.style() == oldPen.style() );
    if ( !bNice )
        painter.setPen( pen );
    painter.drawLine( pA, pZ );
    if ( !bNice )
        painter.setPen( oldPen );
}

/**** static ****/
void KDChartAxesPainter::dtAddSecs( const TQDateTime& org, const int secs, TQDateTime& dest )
{
    //tqDebug("entering KDChartAxesPainter::dtAddSecs() ..");
    int s = org.time().second();
    int m = org.time().minute();
    int h = org.time().hour();
    int days = 0;
    if( -1 < secs ){
        int mins = (s + secs) / 60;
        if( 0 == mins )
            s += secs;
        else{
            s = (s + secs) % 60;
            int hours = (m + mins) / 60;
            if( 0 == hours )
                m += mins;
            else{
                m = (m + mins) % 60;
                days = (h + hours) / 24;
                if( 0 == days )
                    h += hours;
                else{
                    h = (h + hours) % 24;
                }
            }
        }
    }
    dest.setTime( TQTime(h,m,s) );
    dest.setDate( org.date() );
    if( days )
        dtAddDays( dest, days, dest );
    //tqDebug(".. KDChartAxesPainter::dtAddSecs() done.");
}

/**** static ****/
void KDChartAxesPainter::dtAddDays( const TQDateTime& org, const int days, TQDateTime& dest )
{
    //tqDebug("entering KDChartAxesPainter::dtAddDays() ..");
    int d = org.date().day();
    int m = org.date().month();
    int y = org.date().year();
    int dd = (-1 < days) ? 1 : -1;
    int di = 0;
    while( di != days ){
        d += dd;
        // underrunning day?
        if( 1 > d ){
            if( 1 < m ){
                --m;
                d = TQDate( y,m,1 ).daysInMonth();
            }
            else{
                --y;
                m = 12;
                d = 31;
            }
            // overrunning day?
        }else if( TQDate( y,m,1 ).daysInMonth() < d ){
            if( 12 > m )
                ++m;
            else{
                ++y;
                m = 1;
            }
            d = 1;
        }
        di += dd;
    }
    dest = TQDateTime( TQDate( y,m,d ), org.time() );
    //tqDebug(".. KDChartAxesPainter::dtAddDays() done.");
}

/**** static ****/
void KDChartAxesPainter::dtAddMonths( const TQDateTime& org, const int months, TQDateTime& dest )
{
    //tqDebug("entering KDChartAxesPainter::dtAddMonths() ..");
    int d = org.date().day();
    int m = org.date().month();
    int y = org.date().year();
    int md = (-1 < months) ? 1 : -1;
    int mi = 0;
    while( mi != months ){
        m += md;
        if( 1 > m ){
            --y;
            m = 12;
        }else if( 12 < m ){
            ++y;
            m = 1;
        }
        mi += md;
    }
    // TQMIN takes care for intercalary day
    dest = TQDateTime( TQDate( y,m,TQMIN( d, TQDate( y,m,1 ).daysInMonth() ) ),
            org.time() );
    //tqDebug(".. KDChartAxesPainter::dtAddMonths() done.");
}

/**** static ****/
void KDChartAxesPainter::dtAddYears( const TQDateTime& org, const int years, TQDateTime& dest )
{
    //tqDebug("entering KDChartAxesPainter::dtAddYears() ..");
    int d = org.date().day();
    int m = org.date().month();
    int y = org.date().year() + years;
    dest.setTime( org.time() );
    // TQMIN takes care for intercalary day
    dest = TQDateTime( TQDate( y,m,TQMIN( d, TQDate( y,m,d ).daysInMonth() ) ),
            org.time() );
    //tqDebug(".. KDChartAxesPainter::dtAddYears() done.");
}



void KDChartAxesPainter::calculateAbscissaInfos( const KDChartParams& params,
                                                 const KDChartTableDataBase& data,
                                                 uint datasetStart,
                                                 uint datasetEnd,
                                                 double logWidth,
                                                 const TQRect& dataRect,
                                                 abscissaInfos& infos )
{
    if( params.axisParams( KDChartAxisParams::AxisPosBottom ).axisVisible()
        && ( KDChartAxisParams::AxisTypeUnknown
             != params.axisParams( KDChartAxisParams::AxisPosBottom ).axisType() ) )
        infos.abscissaPara = &params.axisParams( KDChartAxisParams::AxisPosBottom );
    else
        if( params.axisParams( KDChartAxisParams::AxisPosBottom2 ).axisVisible()
            && ( KDChartAxisParams::AxisTypeUnknown
                 != params.axisParams( KDChartAxisParams::AxisPosBottom2 ).axisType() ) )
            infos.abscissaPara = &params.axisParams( KDChartAxisParams::AxisPosBottom2 );
        else
            if( params.axisParams( KDChartAxisParams::AxisPosTop ).axisVisible()
                && ( KDChartAxisParams::AxisTypeUnknown
                     != params.axisParams( KDChartAxisParams::AxisPosTop ).axisType() ) )
                infos.abscissaPara = &params.axisParams( KDChartAxisParams::AxisPosTop );
            else
                if( params.axisParams( KDChartAxisParams::AxisPosTop2 ).axisVisible()
                    && ( KDChartAxisParams::AxisTypeUnknown
                         != params.axisParams( KDChartAxisParams::AxisPosTop2 ).axisType() ) )
                    infos.abscissaPara = &params.axisParams( KDChartAxisParams::AxisPosTop2 );
                else
                    // default is bottom axis:
                    infos.abscissaPara = &params.axisParams( KDChartAxisParams::AxisPosBottom );

    if( infos.abscissaPara->axisLabelsTouchEdges() )
        infos.bCenterThePoints = false;

    infos.bAbscissaDecreasing = infos.abscissaPara->axisValuesDecreasing();
    infos.bAbscissaIsLogarithmic
        = KDChartAxisParams::AxisCalcLogarithmic == infos.abscissaPara->axisCalcMode();


    // Number of values: If -1, use all values, otherwise use the
    // specified number of values.
    infos.numValues = 0;
    if ( params.numValues() > -1 )
        infos.numValues = params.numValues();
    else
        infos.numValues = data.usedCols();

    TQVariant::Type type2Ref = TQVariant::Invalid;
    infos.bCellsHaveSeveralCoordinates =
        data.cellsHaveSeveralCoordinates( datasetStart, datasetEnd,
                                          &type2Ref );

    infos.numLabels = (infos.abscissaPara &&
                       infos.abscissaPara->axisLabelTexts())
                      ? infos.abscissaPara->axisLabelTexts()->count()
                      : infos.numValues;
    if( 0 >= infos.numLabels )
        infos.numLabels = 1;

    infos.bAbscissaHasTrueAxisValues =
        infos.abscissaPara && (0.0 != infos.abscissaPara->trueAxisDelta());
    infos.abscissaStart = infos.bAbscissaHasTrueAxisValues
                          ? infos.abscissaPara->trueAxisLow()
                          : 0.0;
    infos.abscissaEnd   = infos.bAbscissaHasTrueAxisValues
                          ? infos.abscissaPara->trueAxisHigh()
                          : 1.0 * (infos.numLabels - 1);
    infos.abscissaSpan  = fabs( infos.abscissaEnd - infos.abscissaStart );
    infos.abscissaDelta = infos.bAbscissaHasTrueAxisValues
                          ? infos.abscissaPara->trueAxisDelta()
                          : (   ( 0.0 != infos.abscissaSpan  )
                                ? ( infos.abscissaSpan / infos.numLabels )
                                : infos.abscissaSpan );

    //tqDebug( bAbscissaDecreasing ? "bAbscissaDecreasing =  TRUE" : "bAbscissaDecreasing = FALSE");
    //tqDebug( abscissaHasTrueAxisValues ? "abscissaHasTrueAxisValues =  TRUE" : "abscissaHasTrueAxisValues = FALSE");
    //tqDebug( "abscissaDelta = %f", abscissaDelta);

    infos.bAbscissaHasTrueAxisDtValues =
        (TQVariant::DateTime == type2Ref) &&
        infos.abscissaPara &&
        infos.abscissaPara->trueAxisDtLow().isValid();
    if( infos.bAbscissaHasTrueAxisDtValues ){
        infos.numLabels = 200;
        infos.bCenterThePoints = false;
    }

    infos.dtLowPos = infos.bAbscissaHasTrueAxisDtValues
                     ? infos.abscissaPara->axisDtLowPosX() - dataRect.x()
                     : 0.0;
    infos.dtHighPos = infos.bAbscissaHasTrueAxisDtValues
                      ? infos.abscissaPara->axisDtHighPosX() - dataRect.x()
                      : logWidth;
    infos.abscissaDtStart = infos.bAbscissaHasTrueAxisDtValues
                            ? infos.abscissaPara->trueAxisDtLow()
                            : TQDateTime();
    infos.abscissaDtEnd = infos.bAbscissaHasTrueAxisDtValues
                          ? infos.abscissaPara->trueAxisDtHigh()
                          : TQDateTime();

    //Pending Michel case when same hh:mm:ss but different msecs
    infos.bScaleLessThanDay = ( infos.bAbscissaHasTrueAxisDtValues
                                ? infos.abscissaPara->trueAxisDtDeltaScale()
                                : KDChartAxisParams::ValueScaleDay )
                              < KDChartAxisParams::ValueScaleDay;
    if ( infos.abscissaDtStart.time() == infos.abscissaDtEnd.time() &&  infos.bScaleLessThanDay )
        infos.dtHighPos = logWidth;

    // adjust the milli seconds:
    infos.abscissaDtStart.setTime(
        TQTime( infos.abscissaDtStart.time().hour(),
               infos.abscissaDtStart.time().minute(),
               infos.abscissaDtStart.time().second(),
               0 ) );
    infos.abscissaDtEnd.setTime(
        TQTime( infos.abscissaDtEnd.time().hour(),
               infos.abscissaDtEnd.time().minute(),
               infos.abscissaDtEnd.time().second(),
               999 ) );
    //tqDebug( infos.abscissaPara->trueAxisDtLow().toString("yyyy-MM-dd-hh:mm:ss.zzz"));
    //tqDebug( infos.abscissaPara->trueAxisDtHigh().toString("yyyy-MM-dd-hh:mm:ss.zzz"));
    //tqDebug(infos.abscissaDtStart.toString("yyyy-MM-dd-hh:mm:ss.zzz"));
    //tqDebug(infos.abscissaDtEnd.toString("yyyy-MM-dd-hh:mm:ss.zzz"));
/*
  infos.bScaleLessThanDay = ( infos.bAbscissaHasTrueAxisDtValues
  ? infos.abscissaPara->trueAxisDtDeltaScale()
  : KDChartAxisParams::ValueScaleDay )
  < KDChartAxisParams::ValueScaleDay;
*/
    if( infos.bAbscissaHasTrueAxisDtValues ){
        if( infos.bScaleLessThanDay  ){
            infos.abscissaDtSpan = infos.abscissaDtStart.secsTo( infos.abscissaDtEnd );

            /*  NOTE: We do *not* add the milli seconds because they aren't covered
                by the span indicated by infos.dtHighPos - infos.dtLowPos.
                if( infos.abscissaDtStart.time().msec() || infos.abscissaDtEnd.time().msec() )
                infos.abscissaDtSpan =
                ( infos.abscissaDtEnd.time().msec() -
                infos.abscissaDtStart.time().msec() ) / 1000.0;
            */
        }
        else{
            infos.abscissaDtSpan = infos.abscissaDtStart.daysTo( infos.abscissaDtEnd );
            if( infos.abscissaDtStart.time().msec() || infos.abscissaDtEnd.time().msec() )
                infos.abscissaDtSpan +=
                    ( infos.abscissaDtEnd.time().msec() -
                      infos.abscissaDtStart.time().msec() ) / (86400.0 * 1000.0);
            if( infos.abscissaDtEnd.time().second() )
                infos.abscissaDtSpan += infos.abscissaDtEnd.time().second() / 86400.0;
            if( infos.abscissaDtEnd.time().minute() )
                infos.abscissaDtSpan += infos.abscissaDtEnd.time().minute() / 1440.0;
            if( infos.abscissaDtEnd.time().hour() )
                infos.abscissaDtSpan += infos.abscissaDtEnd.time().hour()   / 24.0;
        }
    }else
        infos.abscissaDtSpan = 10.0;
    if( 0 == infos.abscissaDtSpan || 0.0 == infos.abscissaDtSpan )
        infos.abscissaDtSpan = 1.0;

    infos.abscissaDtPixelsPerScaleUnit = (infos.dtHighPos - infos.dtLowPos)/ infos.abscissaDtSpan;

    if( infos.bAbscissaHasTrueAxisDtValues )
        infos.abscissaDelta = 20.0;

    infos.pointDist
        = ( infos.abscissaPara && (0.0 != infos.abscissaPara->trueAxisDeltaPixels()) )
        ? infos.abscissaPara->trueAxisDeltaPixels()
        : ( logWidth /
            (
                (1 > ((double)(infos.numLabels) - (infos.bCenterThePoints ? 0.0 : 1.0)))
                ? ((double)(infos.numLabels) - (infos.bCenterThePoints ? 0.0 : 1.0))
                : 1 ) );

    infos.abscissaPixelsPerUnit = ( 0.0 != infos.abscissaDelta  )
                                  ? ( infos.pointDist / infos.abscissaDelta )
                                  : infos.pointDist;

    //const double infos.abscissaZeroPos2 = -1.0 * infos.abscissaPixelsPerUnit * infos.abscissaStart;
    infos.abscissaZeroPos = infos.abscissaPara->axisZeroLineStartX() - dataRect.x();
    //tqDebug("abscissaZeroPos %f    abscissaZeroPos2 %f",abscissaZeroPos,abscissaZeroPos2);

    /*
      tqDebug(abscissaPara ?
      "\nabscissaPara: OK" :
      "\nabscissaPara: leer");
      tqDebug(abscissaHasTrueAxisValues ?
      "abscissaHasTrueAxisValues: TRUE" :
      "abscissaHasTrueAxisValues: FALSE");
      tqDebug("abscissaStart: %f", abscissaStart);
      tqDebug("abscissaEnd  : %f",   abscissaEnd);
      tqDebug("abscissaPara->trueAxisDelta(): %f", abscissaPara->trueAxisDelta());
      tqDebug("numValues  : %u,      numLabels  : %u",   numValues, numLabels);
    */
}



bool KDChartAxesPainter::calculateAbscissaAxisValue( const TQVariant& value,
                                                     abscissaInfos& ai,
                                                     int colNumber,
                                                     double& xValue )
{
    if( ai.bCellsHaveSeveralCoordinates ) {
        if( TQVariant::Double == value.type() ) {
            double dVal = value.toDouble();
            if( ai.bAbscissaIsLogarithmic ){
                if( 0.0 < dVal )
                    xValue = ai.abscissaPixelsPerUnit * log10( dVal );
                else
                    xValue = -10250.0;
            }else{
                xValue = ai.abscissaPixelsPerUnit * dVal;
            }
            xValue *= ai.bAbscissaDecreasing ? -1.0 : 1.0;
            xValue += ai.abscissaZeroPos;
        }
        else if( ai.bAbscissaHasTrueAxisDtValues &&
                 TQVariant::DateTime == value.type() ) {
            const TQDateTime dtVal = value.toDateTime();
            double dT = ( ai.bScaleLessThanDay )
                      ? ai.abscissaDtStart.secsTo( dtVal )
                      : ai.abscissaDtStart.daysTo( dtVal );
            /*
            tqDebug("abscissaDtStart:  %i %i %i   %i:%i:%i.%i",
            ai.abscissaDtStart.date().year(),
            ai.abscissaDtStart.date().month(),
            ai.abscissaDtStart.date().day(),
            ai.abscissaDtStart.time().hour(),
            ai.abscissaDtStart.time().minute(),
            ai.abscissaDtStart.time().second(),
            ai.abscissaDtStart.time().msec());
            */
            //tqDebug("days to = %f",dT);

            /*
            tqDebug("                        dtVal: %i %i %i   %i:%i:%i.%i",
            dtVal.date().year(),
            dtVal.date().month(),
            dtVal.date().day(),
            dtVal.time().hour(),
            dtVal.time().minute(),
            dtVal.time().second(),
            dtVal.time().msec());
            */
            xValue = ai.abscissaDtPixelsPerScaleUnit * dT;
            if( dtVal.time().msec() )
                xValue += (ai.abscissaDtPixelsPerScaleUnit * dtVal.time().msec())
                    / (   ai.bScaleLessThanDay
                        ? 1000.0
                        : (1000.0 * 86400.0) );
            //tqDebug("xValue: %f",xValue);
            if( !ai.bScaleLessThanDay ){
                if( dtVal.time().second() )
                    xValue += (ai.abscissaDtPixelsPerScaleUnit * dtVal.time().second())
                        / 86400.0;
                if( dtVal.time().minute() )
                    xValue += (ai.abscissaDtPixelsPerScaleUnit * dtVal.time().minute())
                        / 1440.0;
                if( dtVal.time().hour() )
                    xValue += (ai.abscissaDtPixelsPerScaleUnit * dtVal.time().hour())
                        / 24.0;
            }
            xValue *= ai.bAbscissaDecreasing ? -1.0 : 1.0;
            xValue += ai.dtLowPos;
            // tqDebug("xValue = dtLowPos + abscissaDtPixelsPerScaleUnit * dT\n%f = %f + %f * %f",
            // xValue, dtLowPos, abscissaDtPixelsPerScaleUnit, dT);
        }
        else
            return false;
    } else
        xValue = ai.pointDist * ( double ) colNumber;
    return true;
}



/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/***                                                                   ***/
/***  Framework for data drawing using cartesian axes (Bar, Line, ...) ***/
/***                                                                   ***/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/

/**
  Paints the actual data area and registers the region for the data
  points if \a regions is not 0.

  \param painter the TQPainter onto which the chart should be painted
  \param data the data that will be displayed as a chart
  \param paint2nd specifies whether the main chart or the additional chart is to be drawn now
  \param regions a pointer to a list of regions that will be filled
  with regions representing the data segments, if not null
  */
void KDChartAxesPainter::paintData( TQPainter* painter,
        KDChartTableDataBase* data,
        bool paint2nd,
        KDChartDataRegionList* regions )
{
    bool bNormalMode = isNormalMode();

    uint chart = paint2nd ? 1 : 0;

    // find out the ordinate axis (or axes, resp.) belonging to this chart
    // (up to 4 ordinates might be in use: 2 left ones and 2 right ones)
    uint axesCount;
    KDChartParams::AxesArray ordinateAxes;
    ordinateAxes.resize( KDCHART_CNT_ORDINATES );
    if( !params()->chartAxes( chart, axesCount, ordinateAxes ) ) {
        // no axis - no fun!
        return;
        // We cannot draw data without an axis having calculated high/low
        // values and position of the zero line before.

        // PENDING(khz) Allow drawing without having a visible axis!
    }

    //const KDChartParams::ChartType params_chartType
    //  = paint2nd ? params()->additionalChartType() : params()->chartType();

    double logWidth = _dataRect.width();
    double areaWidthP1000 = logWidth / 1000.0;

    int nClipShiftUp = clipShiftUp(bNormalMode, areaWidthP1000);
    TQRect ourClipRect( _dataRect );
    if ( 0 < ourClipRect.top() ) {
        ourClipRect.setTop( ourClipRect.top() - nClipShiftUp );
        ourClipRect.setHeight( ourClipRect.height() + nClipShiftUp - 1 );
    } else
        ourClipRect.setHeight( ourClipRect.height() + nClipShiftUp / 2 - 1 );

    // protect axes ?
    //ourClipRect.setBottom( ourClipRect.bottom() - 1 );
    //ourClipRect.setLeft( ourClipRect.left() + 1 );
    //ourClipRect.setRight( ourClipRect.right() - 1 );

    const TQWMatrix & world = painter->worldMatrix();
    ourClipRect =
#if COMPAT_TQT_VERSION >= 0x030000
    world.mapRect( ourClipRect );
#else
    world.map( ourClipRect );
#endif
    painter->setClipRect( ourClipRect );
    painter->translate( _dataRect.x(), _dataRect.y() );

    painter->setPen( params()->outlineDataColor() );

    // find out which datasets are to be represented by this chart
    uint chartDatasetStart, chartDatasetEnd;
    findChartDatasets( data, paint2nd, chart, chartDatasetStart, chartDatasetEnd );

    // Note: 'aI' is *not* the axis number!
    for( uint aI = 0; aI < axesCount; ++aI ) {
        // 'axis' is the REAL axis number!
        uint axis = ordinateAxes.at( aI );

        const KDChartAxisParams* axisPara = &params()->axisParams( axis );

        uint datasetStart, datasetEnd;
        uint axisDatasetStart, axisDatasetEnd;
        uint dummy;
        if( params()->axisDatasets( axis,
                                    axisDatasetStart,
                                    axisDatasetEnd, dummy )
            && ( KDCHART_ALL_DATASETS != axisDatasetStart ) ) {

            if( KDCHART_NO_DATASET == axisDatasetStart ){
                //==========
                continue; //  NO DATASETS  -->  STOP PROCESSING THIS AXIS
                //==========
            }

            if(    axisDatasetStart >= chartDatasetStart
                && axisDatasetStart <= chartDatasetEnd )
                datasetStart = TQMAX( axisDatasetStart, chartDatasetStart );
            else if(    axisDatasetStart <= chartDatasetStart
                     && axisDatasetEnd   >= chartDatasetStart )
                datasetStart = chartDatasetStart;
            else
                datasetStart = 20;
            if(    axisDatasetEnd >= chartDatasetStart
                && axisDatasetEnd <= chartDatasetEnd )
                datasetEnd = TQMIN( axisDatasetEnd, chartDatasetEnd );
            else if(    axisDatasetEnd   >= chartDatasetEnd
                     && axisDatasetStart <= chartDatasetEnd )
                datasetEnd = chartDatasetEnd;
            else
                datasetEnd = 0;
        } else {
            datasetStart = chartDatasetStart;
            datasetEnd   = chartDatasetEnd;
        }

        //tqDebug("\n=========================================================="
        //       "\naxis   %u   axisDatasetStart %u   axisDatasetEnd %u   /   chartDatasetStart %u   chartDatasetEnd %u",
        //axis, axisDatasetStart, axisDatasetEnd, chartDatasetStart, chartDatasetEnd );

        double logHeight   = axisPara->axisTrueAreaRect().height();
        double axisYOffset = axisPara->axisTrueAreaRect().y() - _dataRect.y();

        //tqDebug("\n==========================================================\naxis   %u   logHeight %f   axisDatasetStart %u   chartDatasetStart %u   axisDatasetEnd %u   chartDatasetEnd %u",
        //axis, logHeight, axisDatasetStart, chartDatasetStart, axisDatasetEnd, chartDatasetEnd );
        //if( KDCHART_ALL_DATASETS == axisDatasetStart )
        //    tqDebug("  ALL DATASETS");
        //if( KDCHART_NO_DATASET == axisDatasetStart )
        //    tqDebug("  N O   DATESETS");

        double maxColumnValue = axisPara->trueAxisHigh();
        double minColumnValue = axisPara->trueAxisLow();
        double columnValueDistance = maxColumnValue - minColumnValue;


        // call the chart type specific data painter:
        specificPaintData( painter,
                           ourClipRect,
                           data,
                           regions,
                           axisPara,
                           bNormalMode,
                           chart,
                           logWidth,
                           areaWidthP1000,
                           logHeight,
                           axisYOffset,
                           minColumnValue,
                           maxColumnValue,
                           columnValueDistance,
                           chartDatasetStart,
                           chartDatasetEnd,
                           datasetStart,
                           datasetEnd );
    }
    painter->translate( - _dataRect.x(), - _dataRect.y() );
}
