<commit_before>/*************************************************************************
 *
 *  $RCSfile: swrect.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: kz $ $Date: 2005-01-20 14:04:31 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#pragma hdrstop

#ifndef PRODUCT
#ifndef _STREAM_HXX //autogen
#include <tools/stream.hxx>
#endif
#endif
#include <stdlib.h>
#include <math.h>
#include "swrect.hxx"

/*************************************************************************
|*
|*  SwRect::SwRect()
|*
|*  Ersterstellung      MA 02. Feb. 93
|*  Letzte Aenderung    MA 05. Sep. 93
|*
|*************************************************************************/

SwRect::SwRect( const Rectangle &rRect ) :
    nX( rRect.Left() ),
    nY( rRect.Top() )
{
    nWidth  = rRect.Right() == RECT_EMPTY ? 0 :
                            rRect.Right()  - rRect.Left() +1;
    nHeight = rRect.Bottom() == RECT_EMPTY ? 0 :
                            rRect.Bottom() - rRect.Top() + 1;
}

/*************************************************************************
|*
|*  SwRect::Center()
|*
|*  Ersterstellung      MA 27. Jan. 93
|*  Letzte Aenderung    MA 27. Jan. 93
|*
|*************************************************************************/
Point SwRect::Center() const
{
    return Point( Left() + Width()  / 2,
                  Top()  + Height() / 2 );

/*  Wer ruft schon ein Center auf ein "falsches" Rechteck?
    const long nRight = Right();
    const long nBottom= Bottom();
    return Point( min( Left(), nRight ) + long(abs( (nRight - Left())/2) ),
                  min( Top(),  nBottom) + long(abs( (nBottom - Top())/2)));
*/
}

/*************************************************************************
|*
|*  SwRect::Union()
|*
|*  Ersterstellung      MA 27. Jan. 93
|*  Letzte Aenderung    MA 27. Jan. 93
|*
|*************************************************************************/

SwRect& SwRect::Union( const SwRect& rRect )
{
    if ( Top() > rRect.Top() )
        Top( rRect.Top() );
    if ( Left() > rRect.Left() )
        Left( rRect.Left() );
    register long n = rRect.Right();
    if ( Right() < n )
        Right( n );
    n = rRect.Bottom();
    if ( Bottom() < n )
        Bottom( n );
    return *this;
}
/*************************************************************************
|*
|*  SwRect::Intersection(), _Intersection()
|*
|*  Ersterstellung      MA 27. Jan. 93
|*  Letzte Aenderung    MA 05. Sep. 93
|*
|*************************************************************************/

SwRect& SwRect::Intersection( const SwRect& rRect )
{
    //Hat das Teil ueberhaupt Gemeinsamkeiten mit mir?
    if ( IsOver( rRect ) )
    {
        //Bestimmung der kleineren  rechten sowie unteren und
        //           der groesseren linken  sowie oberen Kante.
        if ( Left() < rRect.Left() )
            Left( rRect.Left() );
        if ( Top() < rRect.Top() )
            Top( rRect.Top() );
        register long n = rRect.Right();
        if ( Right() > n )
            Right( n );
        n = rRect.Bottom();
        if ( Bottom() > n )
            Bottom( n );
    }
    else
        //Def.: Bei einer leeren Intersection wird nur die SSize genullt.
        nHeight = nWidth = 0;

    return *this;
}

SwRect& SwRect::_Intersection( const SwRect& rRect )
{
    //Bestimmung der kleineren  rechten sowie unteren und
    //           der groesseren linken  sowie oberen Kante.
    if ( Left() < rRect.Left() )
        Left( rRect.Left() );
    if ( Top() < rRect.Top() )
        Top( rRect.Top() );
    register long n = rRect.Right();
    if ( Right() > n )
        Right( n );
    n = rRect.Bottom();
    if ( Bottom() > n )
        Bottom( n );

    return *this;
}
/*************************************************************************
|*
|*  SwRect::IsInside()
|*
|*  Ersterstellung      MA 27. Jan. 93
|*  Letzte Aenderung    MA 27. Jan. 93
|*
|*************************************************************************/

BOOL SwRect::IsInside( const SwRect& rRect ) const
{
    const long nRight  = Right();
    const long nBottom = Bottom();
    const long nrRight = rRect.Right();
    const long nrBottom= rRect.Bottom();
    return (Left() <= rRect.Left()) && (rRect.Left()<= nRight)  &&
           (Left() <= nrRight)      && (nrRight     <= nRight)  &&
           (Top()  <= rRect.Top())  && (rRect.Top() <= nBottom) &&
           (Top()  <= nrBottom)     && (nrBottom    <= nBottom);
}

BOOL SwRect::IsInside( const Point& rPoint ) const
{
    return    (Left()  <= rPoint.X())
           && (Top()   <= rPoint.Y())
           && (Right() >= rPoint.X())
           && (Bottom()>= rPoint.Y());
}
/* -----------------------------11.04.00 15:46--------------------------------
    mouse moving of table borders
 ---------------------------------------------------------------------------*/
BOOL SwRect::IsNear( const Point& rPoint, long nTolerance ) const
{
    return    IsInside(rPoint) ||
        (((Left() - nTolerance)  <= rPoint.X())
           && ((Top()  - nTolerance)  <= rPoint.Y())
           && ((Right() + nTolerance) >= rPoint.X())
           && ((Bottom()  + nTolerance)>= rPoint.Y()));
}

/*************************************************************************
|*
|*  SwRect::IsOver()
|*
|*  Ersterstellung      MA 25. Feb. 94
|*  Letzte Aenderung    MA 27. Jun. 96
|*
|*************************************************************************/

BOOL SwRect::IsOver( const SwRect& rRect ) const
{
    return    (Top()   <= rRect.Bottom())
           && (Left()  <= rRect.Right())
           && (Right() >= rRect.Left())
           && (Bottom()>= rRect.Top()) ? TRUE : FALSE;
}

/*************************************************************************
|*
|*  SwRect::Justify()
|*
|*  Ersterstellung      MA 10. Oct. 94
|*  Letzte Aenderung    MA 23. Oct. 96
|*
|*************************************************************************/

void SwRect::Justify()
{
    if ( nHeight < 0 )
    {
        nY = nY + nHeight + 1;
        nHeight = -nHeight;
    }
    if ( nWidth < 0 )
    {
        nX = nX + nWidth + 1;
        nWidth = -nWidth;
    }
}

/*************************************************************************
|*
|*  SwRect::GetDistance()
|*
|*  Ersterstellung      MB 24. Mov. 04
|*
|*************************************************************************/

float SwRect::GetDistance( const Point &rPOINT, Point rClosest ) const {

    // 2d intervall or rectangle area
    const long fXMin = Left();
    const long fXMax = Right();
    const long fYMin = Top();
    const long fYMax = Bottom();

    float fSqrDistance = 0.0f;
    rClosest = rPOINT;

    // A point is in the box whenever xmin <= x <= xmax and
    // ymin <= y <= ymax and zmin <= z <= zmax.
    if(!(IsInside(rPOINT))) {

        if(rPOINT.X() < fXMin) {
            long fDelta = rPOINT.X() - fXMin;
            fSqrDistance += fDelta*fDelta;
            rClosest.X() = fXMin;
        }
        else if(rPOINT.X() > fXMax) {
            long fDelta = rPOINT.X() - fXMax;
            fSqrDistance += fDelta*fDelta;
            rClosest.X() = fXMax;
        }
        else {
            rClosest.X() = rPOINT.X();
        }

        if(rPOINT.Y() < fYMin ) {
            long fDelta = rPOINT.Y() - fYMin;
            fSqrDistance += fDelta*fDelta;
            rClosest.Y() = fYMin;
        }
        else if(rPOINT.Y() > fYMax) {
            long fDelta = rPOINT.Y() - fYMax;
            fSqrDistance += fDelta*fDelta;
            rClosest.Y() = fYMax;
        }
        else {
            rClosest.Y() = rPOINT.Y();
        }
    }

    return sqrt(fSqrDistance);
}

#ifdef VERTICAL_LAYOUT

// Similiar to the inline methods, but we need the function pointers

void SwRect::_Width( const long nNew ) { nWidth = nNew; }
void SwRect::_Height( const long nNew ) { nHeight = nNew; }
void SwRect::_Left( const long nLeft ){ nWidth += nX - nLeft; nX = nLeft; }
void SwRect::_Right( const long nRight ){ nWidth = nRight - nX; }
void SwRect::_Top( const long nTop ){ nHeight += nY - nTop; nY = nTop; }
void SwRect::_Bottom( const long nBottom ){ nHeight = nBottom - nY; }

long SwRect::_Width() const{ return nWidth; }
long SwRect::_Height() const{ return nHeight; }
long SwRect::_Left() const{ return nX; }
long SwRect::_Right() const{ return nX + nWidth; }
long SwRect::_Top() const{ return nY; }
long SwRect::_Bottom() const{ return nY + nHeight; }

void SwRect::AddWidth( const long nAdd ) { nWidth += nAdd; }
void SwRect::AddHeight( const long nAdd ) { nHeight += nAdd; }
void SwRect::SubLeft( const long nSub ){ nWidth += nSub; nX -= nSub; }
void SwRect::AddRight( const long nAdd ){ nWidth += nAdd; }
void SwRect::SubTop( const long nSub ){ nHeight += nSub; nY -= nSub; }
void SwRect::AddBottom( const long nAdd ){ nHeight += nAdd; }
void SwRect::SetPosX( const long nNew ){ nX = nNew; }
void SwRect::SetPosY( const long nNew ){ nY = nNew; }
const Point SwRect::_Pos()  const { return Pos(); }
const Size  SwRect::_Size() const { return SSize(); }
const Point SwRect::SwappedPos()  const { return Point( nY, nX ); }
const Size  SwRect::SwappedSize() const { return Size( nHeight, nWidth ); }
const Point SwRect::TopLeft() const { return Pos(); }
const Point SwRect::TopRight() const { return Point( nX + nWidth, nY ); }
const Point SwRect::BottomLeft() const { return Point( nX, nY + nHeight ); }
const Point SwRect::BottomRight() const
    { return Point( nX + nWidth, nY + nHeight ); }
long SwRect::GetLeftDistance( long nLimit ) const { return nX - nLimit; }
long SwRect::GetBottomDistance( long nLim ) const { return nLim - nY - nHeight;}
long SwRect::GetTopDistance( long nLimit ) const { return nY - nLimit; }
long SwRect::GetRightDistance( long nLim ) const { return nLim - nX - nWidth; }
BOOL SwRect::OverStepLeft( long nLimit ) const
    { return nLimit > nX && nX + nWidth > nLimit; }
BOOL SwRect::OverStepBottom( long nLimit ) const
    { return nLimit > nY && nY + nHeight > nLimit; }
BOOL SwRect::OverStepTop( long nLimit ) const
    { return nLimit > nY && nY + nHeight > nLimit; }
BOOL SwRect::OverStepRight( long nLimit ) const
    { return nLimit > nX && nX + nWidth > nLimit; }
void SwRect::SetLeftAndWidth( long nLeft, long nNew )
    { nX = nLeft; nWidth = nNew; }
void SwRect::SetTopAndHeight( long nTop, long nNew )
    { nY = nTop; nHeight = nNew; }
void SwRect::SetRightAndWidth( long nRight, long nNew )
    { nX = nRight - nNew; nWidth = nNew; }
void SwRect::SetBottomAndHeight( long nBottom, long nNew )
    { nY = nBottom - nNew; nHeight = nNew; }
void SwRect::SetUpperLeftCorner(  const Point& rNew )
    { nX = rNew.nA; nY = rNew.nB; }
void SwRect::SetUpperRightCorner(  const Point& rNew )
    { nX = rNew.nA - nWidth; nY = rNew.nB; }
void SwRect::SetLowerLeftCorner(  const Point& rNew )
    { nX = rNew.nA; nY = rNew.nB - nHeight; }
void SwRect::SetLowerRightCorner(  const Point& rNew )
    { nX = rNew.nA - nWidth; nY = rNew.nB - nHeight; }
#endif

#ifndef PRODUCT
/*************************************************************************
 *                  operator<<( ostream&, SwRect&)
 *************************************************************************/

SvStream &operator<<( SvStream &rStream, const SwRect &rRect )
{
    rStream << '[' << rRect.Top()   << '/' << rRect.Left()
            << ',' << rRect.Width() << 'x' << rRect.Height() << "] ";
    return rStream;
}
#endif

<commit_msg>INTEGRATION: CWS ooo19126 (1.12.378); FILE MERGED 2005/09/05 13:38:42 rt 1.12.378.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: swrect.cxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 03:01:24 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#pragma hdrstop

#ifndef PRODUCT
#ifndef _STREAM_HXX //autogen
#include <tools/stream.hxx>
#endif
#endif
#include <stdlib.h>
#include <math.h>
#include "swrect.hxx"

/*************************************************************************
|*
|*  SwRect::SwRect()
|*
|*  Ersterstellung      MA 02. Feb. 93
|*  Letzte Aenderung    MA 05. Sep. 93
|*
|*************************************************************************/

SwRect::SwRect( const Rectangle &rRect ) :
    nX( rRect.Left() ),
    nY( rRect.Top() )
{
    nWidth  = rRect.Right() == RECT_EMPTY ? 0 :
                            rRect.Right()  - rRect.Left() +1;
    nHeight = rRect.Bottom() == RECT_EMPTY ? 0 :
                            rRect.Bottom() - rRect.Top() + 1;
}

/*************************************************************************
|*
|*  SwRect::Center()
|*
|*  Ersterstellung      MA 27. Jan. 93
|*  Letzte Aenderung    MA 27. Jan. 93
|*
|*************************************************************************/
Point SwRect::Center() const
{
    return Point( Left() + Width()  / 2,
                  Top()  + Height() / 2 );

/*  Wer ruft schon ein Center auf ein "falsches" Rechteck?
    const long nRight = Right();
    const long nBottom= Bottom();
    return Point( min( Left(), nRight ) + long(abs( (nRight - Left())/2) ),
                  min( Top(),  nBottom) + long(abs( (nBottom - Top())/2)));
*/
}

/*************************************************************************
|*
|*  SwRect::Union()
|*
|*  Ersterstellung      MA 27. Jan. 93
|*  Letzte Aenderung    MA 27. Jan. 93
|*
|*************************************************************************/

SwRect& SwRect::Union( const SwRect& rRect )
{
    if ( Top() > rRect.Top() )
        Top( rRect.Top() );
    if ( Left() > rRect.Left() )
        Left( rRect.Left() );
    register long n = rRect.Right();
    if ( Right() < n )
        Right( n );
    n = rRect.Bottom();
    if ( Bottom() < n )
        Bottom( n );
    return *this;
}
/*************************************************************************
|*
|*  SwRect::Intersection(), _Intersection()
|*
|*  Ersterstellung      MA 27. Jan. 93
|*  Letzte Aenderung    MA 05. Sep. 93
|*
|*************************************************************************/

SwRect& SwRect::Intersection( const SwRect& rRect )
{
    //Hat das Teil ueberhaupt Gemeinsamkeiten mit mir?
    if ( IsOver( rRect ) )
    {
        //Bestimmung der kleineren  rechten sowie unteren und
        //           der groesseren linken  sowie oberen Kante.
        if ( Left() < rRect.Left() )
            Left( rRect.Left() );
        if ( Top() < rRect.Top() )
            Top( rRect.Top() );
        register long n = rRect.Right();
        if ( Right() > n )
            Right( n );
        n = rRect.Bottom();
        if ( Bottom() > n )
            Bottom( n );
    }
    else
        //Def.: Bei einer leeren Intersection wird nur die SSize genullt.
        nHeight = nWidth = 0;

    return *this;
}

SwRect& SwRect::_Intersection( const SwRect& rRect )
{
    //Bestimmung der kleineren  rechten sowie unteren und
    //           der groesseren linken  sowie oberen Kante.
    if ( Left() < rRect.Left() )
        Left( rRect.Left() );
    if ( Top() < rRect.Top() )
        Top( rRect.Top() );
    register long n = rRect.Right();
    if ( Right() > n )
        Right( n );
    n = rRect.Bottom();
    if ( Bottom() > n )
        Bottom( n );

    return *this;
}
/*************************************************************************
|*
|*  SwRect::IsInside()
|*
|*  Ersterstellung      MA 27. Jan. 93
|*  Letzte Aenderung    MA 27. Jan. 93
|*
|*************************************************************************/

BOOL SwRect::IsInside( const SwRect& rRect ) const
{
    const long nRight  = Right();
    const long nBottom = Bottom();
    const long nrRight = rRect.Right();
    const long nrBottom= rRect.Bottom();
    return (Left() <= rRect.Left()) && (rRect.Left()<= nRight)  &&
           (Left() <= nrRight)      && (nrRight     <= nRight)  &&
           (Top()  <= rRect.Top())  && (rRect.Top() <= nBottom) &&
           (Top()  <= nrBottom)     && (nrBottom    <= nBottom);
}

BOOL SwRect::IsInside( const Point& rPoint ) const
{
    return    (Left()  <= rPoint.X())
           && (Top()   <= rPoint.Y())
           && (Right() >= rPoint.X())
           && (Bottom()>= rPoint.Y());
}
/* -----------------------------11.04.00 15:46--------------------------------
    mouse moving of table borders
 ---------------------------------------------------------------------------*/
BOOL SwRect::IsNear( const Point& rPoint, long nTolerance ) const
{
    return    IsInside(rPoint) ||
        (((Left() - nTolerance)  <= rPoint.X())
           && ((Top()  - nTolerance)  <= rPoint.Y())
           && ((Right() + nTolerance) >= rPoint.X())
           && ((Bottom()  + nTolerance)>= rPoint.Y()));
}

/*************************************************************************
|*
|*  SwRect::IsOver()
|*
|*  Ersterstellung      MA 25. Feb. 94
|*  Letzte Aenderung    MA 27. Jun. 96
|*
|*************************************************************************/

BOOL SwRect::IsOver( const SwRect& rRect ) const
{
    return    (Top()   <= rRect.Bottom())
           && (Left()  <= rRect.Right())
           && (Right() >= rRect.Left())
           && (Bottom()>= rRect.Top()) ? TRUE : FALSE;
}

/*************************************************************************
|*
|*  SwRect::Justify()
|*
|*  Ersterstellung      MA 10. Oct. 94
|*  Letzte Aenderung    MA 23. Oct. 96
|*
|*************************************************************************/

void SwRect::Justify()
{
    if ( nHeight < 0 )
    {
        nY = nY + nHeight + 1;
        nHeight = -nHeight;
    }
    if ( nWidth < 0 )
    {
        nX = nX + nWidth + 1;
        nWidth = -nWidth;
    }
}

/*************************************************************************
|*
|*  SwRect::GetDistance()
|*
|*  Ersterstellung      MB 24. Mov. 04
|*
|*************************************************************************/

float SwRect::GetDistance( const Point &rPOINT, Point rClosest ) const {

    // 2d intervall or rectangle area
    const long fXMin = Left();
    const long fXMax = Right();
    const long fYMin = Top();
    const long fYMax = Bottom();

    float fSqrDistance = 0.0f;
    rClosest = rPOINT;

    // A point is in the box whenever xmin <= x <= xmax and
    // ymin <= y <= ymax and zmin <= z <= zmax.
    if(!(IsInside(rPOINT))) {

        if(rPOINT.X() < fXMin) {
            long fDelta = rPOINT.X() - fXMin;
            fSqrDistance += fDelta*fDelta;
            rClosest.X() = fXMin;
        }
        else if(rPOINT.X() > fXMax) {
            long fDelta = rPOINT.X() - fXMax;
            fSqrDistance += fDelta*fDelta;
            rClosest.X() = fXMax;
        }
        else {
            rClosest.X() = rPOINT.X();
        }

        if(rPOINT.Y() < fYMin ) {
            long fDelta = rPOINT.Y() - fYMin;
            fSqrDistance += fDelta*fDelta;
            rClosest.Y() = fYMin;
        }
        else if(rPOINT.Y() > fYMax) {
            long fDelta = rPOINT.Y() - fYMax;
            fSqrDistance += fDelta*fDelta;
            rClosest.Y() = fYMax;
        }
        else {
            rClosest.Y() = rPOINT.Y();
        }
    }

    return sqrt(fSqrDistance);
}

#ifdef VERTICAL_LAYOUT

// Similiar to the inline methods, but we need the function pointers

void SwRect::_Width( const long nNew ) { nWidth = nNew; }
void SwRect::_Height( const long nNew ) { nHeight = nNew; }
void SwRect::_Left( const long nLeft ){ nWidth += nX - nLeft; nX = nLeft; }
void SwRect::_Right( const long nRight ){ nWidth = nRight - nX; }
void SwRect::_Top( const long nTop ){ nHeight += nY - nTop; nY = nTop; }
void SwRect::_Bottom( const long nBottom ){ nHeight = nBottom - nY; }

long SwRect::_Width() const{ return nWidth; }
long SwRect::_Height() const{ return nHeight; }
long SwRect::_Left() const{ return nX; }
long SwRect::_Right() const{ return nX + nWidth; }
long SwRect::_Top() const{ return nY; }
long SwRect::_Bottom() const{ return nY + nHeight; }

void SwRect::AddWidth( const long nAdd ) { nWidth += nAdd; }
void SwRect::AddHeight( const long nAdd ) { nHeight += nAdd; }
void SwRect::SubLeft( const long nSub ){ nWidth += nSub; nX -= nSub; }
void SwRect::AddRight( const long nAdd ){ nWidth += nAdd; }
void SwRect::SubTop( const long nSub ){ nHeight += nSub; nY -= nSub; }
void SwRect::AddBottom( const long nAdd ){ nHeight += nAdd; }
void SwRect::SetPosX( const long nNew ){ nX = nNew; }
void SwRect::SetPosY( const long nNew ){ nY = nNew; }
const Point SwRect::_Pos()  const { return Pos(); }
const Size  SwRect::_Size() const { return SSize(); }
const Point SwRect::SwappedPos()  const { return Point( nY, nX ); }
const Size  SwRect::SwappedSize() const { return Size( nHeight, nWidth ); }
const Point SwRect::TopLeft() const { return Pos(); }
const Point SwRect::TopRight() const { return Point( nX + nWidth, nY ); }
const Point SwRect::BottomLeft() const { return Point( nX, nY + nHeight ); }
const Point SwRect::BottomRight() const
    { return Point( nX + nWidth, nY + nHeight ); }
long SwRect::GetLeftDistance( long nLimit ) const { return nX - nLimit; }
long SwRect::GetBottomDistance( long nLim ) const { return nLim - nY - nHeight;}
long SwRect::GetTopDistance( long nLimit ) const { return nY - nLimit; }
long SwRect::GetRightDistance( long nLim ) const { return nLim - nX - nWidth; }
BOOL SwRect::OverStepLeft( long nLimit ) const
    { return nLimit > nX && nX + nWidth > nLimit; }
BOOL SwRect::OverStepBottom( long nLimit ) const
    { return nLimit > nY && nY + nHeight > nLimit; }
BOOL SwRect::OverStepTop( long nLimit ) const
    { return nLimit > nY && nY + nHeight > nLimit; }
BOOL SwRect::OverStepRight( long nLimit ) const
    { return nLimit > nX && nX + nWidth > nLimit; }
void SwRect::SetLeftAndWidth( long nLeft, long nNew )
    { nX = nLeft; nWidth = nNew; }
void SwRect::SetTopAndHeight( long nTop, long nNew )
    { nY = nTop; nHeight = nNew; }
void SwRect::SetRightAndWidth( long nRight, long nNew )
    { nX = nRight - nNew; nWidth = nNew; }
void SwRect::SetBottomAndHeight( long nBottom, long nNew )
    { nY = nBottom - nNew; nHeight = nNew; }
void SwRect::SetUpperLeftCorner(  const Point& rNew )
    { nX = rNew.nA; nY = rNew.nB; }
void SwRect::SetUpperRightCorner(  const Point& rNew )
    { nX = rNew.nA - nWidth; nY = rNew.nB; }
void SwRect::SetLowerLeftCorner(  const Point& rNew )
    { nX = rNew.nA; nY = rNew.nB - nHeight; }
void SwRect::SetLowerRightCorner(  const Point& rNew )
    { nX = rNew.nA - nWidth; nY = rNew.nB - nHeight; }
#endif

#ifndef PRODUCT
/*************************************************************************
 *                  operator<<( ostream&, SwRect&)
 *************************************************************************/

SvStream &operator<<( SvStream &rStream, const SwRect &rRect )
{
    rStream << '[' << rRect.Top()   << '/' << rRect.Left()
            << ',' << rRect.Width() << 'x' << rRect.Height() << "] ";
    return rStream;
}
#endif

<|endoftext|>


<commit_before><commit_msg>Vulkan: fix bad depth clears.<commit_after><|endoftext|>


<commit_before><commit_msg>gui: viewer clang format names<commit_after><|endoftext|>


<commit_before>//
// ulib - a collection of useful classes
// Copyright (C) 2004,2005,2006,2007,2008,2018,2020 Michael Fink
//
/// \file VersionInfoResource.cpp version info resource class
//
#include "stdafx.h"
#include <ulib/win32/VersionInfoResource.hpp>
#include <WinBase.h> // for VOS_* constants
#include <winver.h> // for VOS_* constants, when not in winbase.h

#ifndef VOS_WINDOWSCE
#  define VOS_WINDOWSCE 0x00050000L
#endif

#ifndef _WIN32_WCE
#  pragma comment(lib, "version.lib")
#endif

using Win32::FixedFileInfo;
using Win32::VersionInfoResource;
using Win32::LANGANDCODEPAGE;

//
// FixedFileInfo
//

CString FixedFileInfo::GetFileVersion() const
{
   CString text;
   text.Format(_T("%u.%u.%u.%u"),
      HIWORD(dwFileVersionMS), LOWORD(dwFileVersionMS),
      HIWORD(dwFileVersionLS), LOWORD(dwFileVersionLS));
   return text;
}

CString FixedFileInfo::GetProductVersion() const
{
   CString text;
   text.Format(_T("%u.%u.%u.%u"),
      HIWORD(dwProductVersionMS), LOWORD(dwProductVersionMS),
      HIWORD(dwProductVersionLS), LOWORD(dwProductVersionLS));
   return text;
}

CString FixedFileInfo::GetFileOS() const
{
   CString text;

   switch (dwFileOS & 0xFFFF0000)
   {
   case VOS_DOS: // The file was designed for MS-DOS.
      text = _T("VOS_DOS"); break;
   case VOS_OS216: // The file was designed for 16-bit OS/2.
      text = _T("VOS_OS216"); break;
   case VOS_OS232: // The file was designed for 32-bit OS/2.
      text = _T("VOS_OS232"); break;
   case VOS_NT: // The file was designed for Windows NT and Windows 2000.
      text = _T("VOS_NT"); break;
   case VOS_WINDOWSCE:
      text = _T("VOS_WINDOWSCE"); break;
   case VOS_UNKNOWN:
      text = _T("VOS_UNKNOWN"); break;
   default:
      text = _T("unknown"); break;
   }

   switch (dwFileOS & 0x0000FFFF)
   {
   case VOS__WINDOWS16: // The file was designed for 16-bit Windows.
      text += _T(" | VOS__WINDOWS16"); break;
   case VOS__PM16: // The file was designed for 16-bit Presentation Manager.
      text += _T(" | VOS__PM16"); break;
   case VOS__PM32: // The file was designed for 32-bit Presentation Manager.
      text += _T(" | VOS__PM32"); break;
   case VOS__WINDOWS32: // The file was designed for the Win32 API.
      text += _T(" | VOS__WINDOWS32"); break;
   }

   return text;
}

CString FixedFileInfo::GetFileType() const
{
   CString text;
   switch (dwFileType)
   {
   case VFT_UNKNOWN:
      text = _T("VFT_UNKNOWN"); break;
   case VFT_APP:
      text = _T("VFT_APP"); break;
   case VFT_DLL:
      text = _T("VFT_DLL"); break;
   case VFT_DRV:
      text = _T("VFT_DRV"); break;
   case VFT_FONT:
      text = _T("VFT_FONT"); break;
   case VFT_VXD:
      text = _T("VFT_VXD"); break;
   case VFT_STATIC_LIB:
      text = _T("VFT_STATIC_LIB"); break;
   default:
      text = _T("unknown"); break;
   }
   return text;
}

//
// VersionInfoResource
//

VersionInfoResource::VersionInfoResource(LPCTSTR filename)
{
   // find out length
   DWORD dummy = 0;
   DWORD dwLen = ::GetFileVersionInfoSize(filename, &dummy);

   if (dwLen > 0)
   {
      m_versionInfoData.resize(dwLen);

      // get version info
      ::GetFileVersionInfo(filename, 0, dwLen, &m_versionInfoData[0]);
   }
}

LPVOID VersionInfoResource::QueryValue(LPCTSTR subBlock, UINT* puiSize)
{
   ATLASSERT(IsAvail());

   LPVOID data = NULL;
   UINT uiSize = 0;

   BOOL ret = VerQueryValue(&m_versionInfoData[0],
      subBlock,
      &data,
      puiSize != NULL ? puiSize : &uiSize);

   return ret == FALSE ? NULL : data;
}

void VersionInfoResource::GetLangAndCodepages(std::vector<LANGANDCODEPAGE>& langAndCodepageList)
{
   ATLASSERT(IsAvail());

   UINT size = 0;
   LPCVOID data = QueryValue(_T("\\VarFileInfo\\Translation"), &size);

   ATLASSERT((size % sizeof(LANGANDCODEPAGE)) == 0);

   const LANGANDCODEPAGE* langAndCodepage = reinterpret_cast<const LANGANDCODEPAGE*>(data);

   for (unsigned int i = 0; i < size / sizeof(LANGANDCODEPAGE); i++)
      langAndCodepageList.push_back(langAndCodepage[i]);
}

CString VersionInfoResource::GetStringValue(const LANGANDCODEPAGE& langAndCodepage, LPCTSTR valueName)
{
   CString buffer;
   buffer.Format(
      _T("\\StringFileInfo\\%04x%04x\\%s"),
      langAndCodepage.wLanguage, langAndCodepage.wCodePage,
      valueName);

   UINT size = 0;
   LPCWSTR text = reinterpret_cast<LPCWSTR>(QueryValue(buffer, &size));

   ATLASSERT(size == 0 || text[size - 1] == 0);

   return (text == NULL || *text == 0) ? CString(_T("???")) : CString(text);
}
<commit_msg>added default case for switch statement<commit_after>//
// ulib - a collection of useful classes
// Copyright (C) 2004,2005,2006,2007,2008,2018,2020 Michael Fink
//
/// \file VersionInfoResource.cpp version info resource class
//
#include "stdafx.h"
#include <ulib/win32/VersionInfoResource.hpp>
#include <WinBase.h> // for VOS_* constants
#include <winver.h> // for VOS_* constants, when not in winbase.h

#ifndef VOS_WINDOWSCE
#  define VOS_WINDOWSCE 0x00050000L
#endif

#ifndef _WIN32_WCE
#  pragma comment(lib, "version.lib")
#endif

using Win32::FixedFileInfo;
using Win32::VersionInfoResource;
using Win32::LANGANDCODEPAGE;

//
// FixedFileInfo
//

CString FixedFileInfo::GetFileVersion() const
{
   CString text;
   text.Format(_T("%u.%u.%u.%u"),
      HIWORD(dwFileVersionMS), LOWORD(dwFileVersionMS),
      HIWORD(dwFileVersionLS), LOWORD(dwFileVersionLS));
   return text;
}

CString FixedFileInfo::GetProductVersion() const
{
   CString text;
   text.Format(_T("%u.%u.%u.%u"),
      HIWORD(dwProductVersionMS), LOWORD(dwProductVersionMS),
      HIWORD(dwProductVersionLS), LOWORD(dwProductVersionLS));
   return text;
}

CString FixedFileInfo::GetFileOS() const
{
   CString text;

   switch (dwFileOS & 0xFFFF0000)
   {
   case VOS_DOS: // The file was designed for MS-DOS.
      text = _T("VOS_DOS"); break;
   case VOS_OS216: // The file was designed for 16-bit OS/2.
      text = _T("VOS_OS216"); break;
   case VOS_OS232: // The file was designed for 32-bit OS/2.
      text = _T("VOS_OS232"); break;
   case VOS_NT: // The file was designed for Windows NT and Windows 2000.
      text = _T("VOS_NT"); break;
   case VOS_WINDOWSCE:
      text = _T("VOS_WINDOWSCE"); break;
   case VOS_UNKNOWN:
      text = _T("VOS_UNKNOWN"); break;
   default:
      text = _T("unknown"); break;
   }

   switch (dwFileOS & 0x0000FFFF)
   {
   case VOS__WINDOWS16: // The file was designed for 16-bit Windows.
      text += _T(" | VOS__WINDOWS16"); break;
   case VOS__PM16: // The file was designed for 16-bit Presentation Manager.
      text += _T(" | VOS__PM16"); break;
   case VOS__PM32: // The file was designed for 32-bit Presentation Manager.
      text += _T(" | VOS__PM32"); break;
   case VOS__WINDOWS32: // The file was designed for the Win32 API.
      text += _T(" | VOS__WINDOWS32"); break;
   default:
      text.AppendFormat(_T(" | 0x%04x"), dwFileOS & 0x0000FFFF); break;
   }

   return text;
}

CString FixedFileInfo::GetFileType() const
{
   CString text;
   switch (dwFileType)
   {
   case VFT_UNKNOWN:
      text = _T("VFT_UNKNOWN"); break;
   case VFT_APP:
      text = _T("VFT_APP"); break;
   case VFT_DLL:
      text = _T("VFT_DLL"); break;
   case VFT_DRV:
      text = _T("VFT_DRV"); break;
   case VFT_FONT:
      text = _T("VFT_FONT"); break;
   case VFT_VXD:
      text = _T("VFT_VXD"); break;
   case VFT_STATIC_LIB:
      text = _T("VFT_STATIC_LIB"); break;
   default:
      text = _T("unknown"); break;
   }
   return text;
}

//
// VersionInfoResource
//

VersionInfoResource::VersionInfoResource(LPCTSTR filename)
{
   // find out length
   DWORD dummy = 0;
   DWORD dwLen = ::GetFileVersionInfoSize(filename, &dummy);

   if (dwLen > 0)
   {
      m_versionInfoData.resize(dwLen);

      // get version info
      ::GetFileVersionInfo(filename, 0, dwLen, &m_versionInfoData[0]);
   }
}

LPVOID VersionInfoResource::QueryValue(LPCTSTR subBlock, UINT* puiSize)
{
   ATLASSERT(IsAvail());

   LPVOID data = NULL;
   UINT uiSize = 0;

   BOOL ret = VerQueryValue(&m_versionInfoData[0],
      subBlock,
      &data,
      puiSize != NULL ? puiSize : &uiSize);

   return ret == FALSE ? NULL : data;
}

void VersionInfoResource::GetLangAndCodepages(std::vector<LANGANDCODEPAGE>& langAndCodepageList)
{
   ATLASSERT(IsAvail());

   UINT size = 0;
   LPCVOID data = QueryValue(_T("\\VarFileInfo\\Translation"), &size);

   ATLASSERT((size % sizeof(LANGANDCODEPAGE)) == 0);

   const LANGANDCODEPAGE* langAndCodepage = reinterpret_cast<const LANGANDCODEPAGE*>(data);

   for (unsigned int i = 0; i < size / sizeof(LANGANDCODEPAGE); i++)
      langAndCodepageList.push_back(langAndCodepage[i]);
}

CString VersionInfoResource::GetStringValue(const LANGANDCODEPAGE& langAndCodepage, LPCTSTR valueName)
{
   CString buffer;
   buffer.Format(
      _T("\\StringFileInfo\\%04x%04x\\%s"),
      langAndCodepage.wLanguage, langAndCodepage.wCodePage,
      valueName);

   UINT size = 0;
   LPCWSTR text = reinterpret_cast<LPCWSTR>(QueryValue(buffer, &size));

   ATLASSERT(size == 0 || text[size - 1] == 0);

   return (text == NULL || *text == 0) ? CString(_T("???")) : CString(text);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: ndnum.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: obo $ $Date: 2004-08-12 12:20:01 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#pragma hdrstop

#ifndef _NODE_HXX
#include <node.hxx>
#endif
#ifndef _DOC_HXX
#include <doc.hxx>
#endif
#ifndef _PAM_HXX
#include <pam.hxx>
#endif
#ifndef _NDTXT_HXX
#include <ndtxt.hxx>
#endif
#ifndef _NUMRULE_HXX
#include <numrule.hxx>
#endif
#ifndef _FLDBAS_HXX
#include <fldbas.hxx>           // UpdateFlds der KapitelNummerierung
#endif

_SV_IMPL_SORTAR_ALG( SwOutlineNodes, SwNodePtr )
BOOL SwOutlineNodes::Seek_Entry( const SwNodePtr rSrch, USHORT* pFndPos ) const
{
    ULONG nIdx = rSrch->GetIndex();

    register USHORT nO = Count(), nM, nU = 0;
    if( nO > 0 )
    {
//JP 17.03.98: aufgrund des Bug 48592 - wo unter anderem nach Undo/Redo
//              Nodes aus dem falschen NodesArray im OutlineArray standen,
//              jetzt mal einen Check eingebaut.
#ifndef PRODUCT
        {
            for( register USHORT n = 1; n < nO; ++n )
                if( &(*this)[ n-1 ]->GetNodes() !=
                    &(*this)[ n ]->GetNodes() )
                {
                    ASSERT( !this, "Node im falschen Outline-Array" );
                }
        }
#endif

        nO--;
        while( nU <= nO )
        {
            nM = nU + ( nO - nU ) / 2;
            if( (*this)[ nM ] == rSrch )
            {
                if( pFndPos )
                    *pFndPos = nM;
                return TRUE;
            }
            else if( (*this)[ nM ]->GetIndex() < nIdx )
                nU = nM + 1;
            else if( nM == 0 )
            {
                if( pFndPos )
                    *pFndPos = nU;
                return FALSE;
            }
            else
                nO = nM - 1;
        }
    }
    if( pFndPos )
        *pFndPos = nU;
    return FALSE;
}

void SwNodes::UpdateOutlineNode( const SwNode& rNd, BYTE nOldLevel,
                                 BYTE nNewLevel )
{
    const SwNodePtr pSrch = (SwNodePtr)&rNd;
    USHORT nSttPos;
    BOOL bSeekIdx = pOutlineNds->Seek_Entry( pSrch, &nSttPos );

    if( NO_NUMBERING == nOldLevel )         // neuen Level einfuegen
    {
        // nicht vorhanden, also einfuegen
        ASSERT( !bSeekIdx, "Der Node ist schon als OutlineNode vorhanden" );

        //JP 12.03.99: 63293 - Nodes vom RedlineBereich NIE aufnehmen
        ULONG nNd = rNd.GetIndex();
        if( nNd < GetEndOfRedlines().GetIndex() &&
            nNd > GetEndOfRedlines().FindStartNode()->GetIndex() )
            return ;

        // jetzt noch alle nachfolgende Outline-Nodes updaten
        pOutlineNds->Insert( pSrch );
        if( ! IsShowNum( nNewLevel ))
            return;     // keine Nummerierung dann kein Update
    }
    else if( NO_NUMBERING == nNewLevel )    // Level entfernen
    {
        if( !bSeekIdx )
            return;

        // jetzt noch alle nachfolgende Outline-Nodes updaten
        pOutlineNds->Remove( nSttPos );
        if( ! IsShowNum(nOldLevel) )
            return;     // keine Nummerierung dann kein Update
    }
    else if( !bSeekIdx )        // Update und Index nicht gefunden ??
        return ;

    {
        SwTxtNode & rTxtNd = (SwTxtNode &) rNd;
        SwPaM aPam(rTxtNd); // #115901#

        if (nNewLevel != NO_NUMBERING) // #115901#
        {
            const SwNodeNum * pNum = rTxtNd.GetOutlineNum();

            SwNodeNum aNum(0);

            if (0 != pNum)
                aNum = *pNum;

            aNum.SetLevel(rTxtNd.GetTxtColl()->GetOutlineLevel());
            rTxtNd.UpdateNum(aNum);

            GetDoc()->SetNumRule(aPam, *GetDoc()->GetOutlineNumRule());
        }
        else
        {
            GetDoc()->DelNumRules(aPam);
        }
    }

    // die Gliederungs-Felder Updaten
    GetDoc()->GetSysFldType( RES_CHAPTERFLD )->UpdateFlds();
}

void SwNodes::UpdtOutlineIdx( const SwNode& rNd )
{
    if( !pOutlineNds->Count() )     // keine OutlineNodes vorhanden ?
        return;

    const SwNodePtr pSrch = (SwNodePtr)&rNd;
    USHORT nPos;
    pOutlineNds->Seek_Entry( pSrch, &nPos );
    if( nPos == pOutlineNds->Count() )      // keine zum Updaten vorhanden ?
        return;

    if( nPos )
        --nPos;

    if( !GetDoc()->IsInDtor() && IsDocNodes() )
        UpdateOutlineNode( *(*pOutlineNds)[ nPos ], 0, 0 );
}

void SwNodes::UpdateOutlineNodes()
{
    if( pOutlineNds->Count() )      // OutlineNodes vorhanden ?
        UpdateOutlineNode( *(*pOutlineNds)[ 0 ], 0, 0 );
}
<commit_msg>INTEGRATION: CWS oasisbf2 (1.10.90); FILE MERGED 2004/11/04 15:30:26 dvo 1.10.90.1: #i31024# prevent headings with outline num-rules from being written as lists          (plus dependent changes for NO_NUM removal)<commit_after>/*************************************************************************
 *
 *  $RCSfile: ndnum.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: rt $ $Date: 2004-11-26 13:25:03 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#pragma hdrstop

#ifndef _NODE_HXX
#include <node.hxx>
#endif
#ifndef _DOC_HXX
#include <doc.hxx>
#endif
#ifndef _PAM_HXX
#include <pam.hxx>
#endif
#ifndef _NDTXT_HXX
#include <ndtxt.hxx>
#endif
#ifndef _NUMRULE_HXX
#include <numrule.hxx>
#endif
#ifndef _FLDBAS_HXX
#include <fldbas.hxx>           // UpdateFlds der KapitelNummerierung
#endif

_SV_IMPL_SORTAR_ALG( SwOutlineNodes, SwNodePtr )
BOOL SwOutlineNodes::Seek_Entry( const SwNodePtr rSrch, USHORT* pFndPos ) const
{
    ULONG nIdx = rSrch->GetIndex();

    register USHORT nO = Count(), nM, nU = 0;
    if( nO > 0 )
    {
//JP 17.03.98: aufgrund des Bug 48592 - wo unter anderem nach Undo/Redo
//              Nodes aus dem falschen NodesArray im OutlineArray standen,
//              jetzt mal einen Check eingebaut.
#ifndef PRODUCT
        {
            for( register USHORT n = 1; n < nO; ++n )
                if( &(*this)[ n-1 ]->GetNodes() !=
                    &(*this)[ n ]->GetNodes() )
                {
                    ASSERT( !this, "Node im falschen Outline-Array" );
                }
        }
#endif

        nO--;
        while( nU <= nO )
        {
            nM = nU + ( nO - nU ) / 2;
            if( (*this)[ nM ] == rSrch )
            {
                if( pFndPos )
                    *pFndPos = nM;
                return TRUE;
            }
            else if( (*this)[ nM ]->GetIndex() < nIdx )
                nU = nM + 1;
            else if( nM == 0 )
            {
                if( pFndPos )
                    *pFndPos = nU;
                return FALSE;
            }
            else
                nO = nM - 1;
        }
    }
    if( pFndPos )
        *pFndPos = nU;
    return FALSE;
}

void SwNodes::UpdateOutlineNode( const SwNode& rNd, BYTE nOldLevel,
                                 BYTE nNewLevel )
{
    const SwNodePtr pSrch = (SwNodePtr)&rNd;
    USHORT nSttPos;
    BOOL bSeekIdx = pOutlineNds->Seek_Entry( pSrch, &nSttPos );

    if( NO_NUMBERING == nOldLevel )         // neuen Level einfuegen
    {
        // nicht vorhanden, also einfuegen
        ASSERT( !bSeekIdx, "Der Node ist schon als OutlineNode vorhanden" );

        //JP 12.03.99: 63293 - Nodes vom RedlineBereich NIE aufnehmen
        ULONG nNd = rNd.GetIndex();
        if( nNd < GetEndOfRedlines().GetIndex() &&
            nNd > GetEndOfRedlines().FindStartNode()->GetIndex() )
            return ;

        // jetzt noch alle nachfolgende Outline-Nodes updaten
        pOutlineNds->Insert( pSrch );
        if( ! IsShowNum( nNewLevel ))
            return;     // keine Nummerierung dann kein Update
    }
    else if( NO_NUMBERING == nNewLevel )    // Level entfernen
    {
        if( !bSeekIdx )
            return;

        // jetzt noch alle nachfolgende Outline-Nodes updaten
        pOutlineNds->Remove( nSttPos );
        if( ! IsShowNum(nOldLevel) )
            return;     // keine Nummerierung dann kein Update
    }
    else if( !bSeekIdx )        // Update und Index nicht gefunden ??
        return ;

    {
        SwTxtNode & rTxtNd = (SwTxtNode &) rNd;
        SwPaM aPam(rTxtNd); // #115901#

        if (nNewLevel != NO_NUMBERING) // #115901#
        {
            const SwNodeNum * pNum = rTxtNd.GetOutlineNum();

            SwNodeNum aNum(0);

            if (0 != pNum)
                aNum = *pNum;

            aNum.SetNoNum(FALSE);
            aNum.SetLevel(rTxtNd.GetTxtColl()->GetOutlineLevel());
            rTxtNd.UpdateNum(aNum);

            //GetDoc()->SetNumRule(aPam, *GetDoc()->GetOutlineNumRule());
        }
        else
        {
            GetDoc()->DelNumRules(aPam);
        }
    }

    // die Gliederungs-Felder Updaten
    GetDoc()->GetSysFldType( RES_CHAPTERFLD )->UpdateFlds();
}

void SwNodes::UpdtOutlineIdx( const SwNode& rNd )
{
    if( !pOutlineNds->Count() )     // keine OutlineNodes vorhanden ?
        return;

    const SwNodePtr pSrch = (SwNodePtr)&rNd;
    USHORT nPos;
    pOutlineNds->Seek_Entry( pSrch, &nPos );
    if( nPos == pOutlineNds->Count() )      // keine zum Updaten vorhanden ?
        return;

    if( nPos )
        --nPos;

    if( !GetDoc()->IsInDtor() && IsDocNodes() )
        UpdateOutlineNode( *(*pOutlineNds)[ nPos ], 0, 0 );
}

void SwNodes::UpdateOutlineNodes()
{
    if( pOutlineNds->Count() )      // OutlineNodes vorhanden ?
        UpdateOutlineNode( *(*pOutlineNds)[ 0 ], 0, 0 );
}
<|endoftext|>


<commit_before>/*
 * This file is part of btag.
 *
 * © 2010-2011 Fernando Tarlá Cardoso Lemos
 *
 * Refer to the LICENSE file for licensing information.
 *
 */

#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>
#include <taglib/fileref.h>
#include <taglib/tag.h>
#include <cassert>
#include <cstdlib>
#include <exception>

#include "InteractiveTagger.h"
#include "validators.h"
#include "wide_string_cast.h"

namespace fs = boost::filesystem;

InteractiveTagger::InteractiveTagger()
    : m_input_filter(NULL), m_output_filter(NULL), m_dry_run(false)
{
    // Load the extensions supported by TagLib
    TagLib::StringList extensions = TagLib::FileRef::defaultFileExtensions();
    for (TagLib::StringList::ConstIterator it = extensions.begin(); it != extensions.end(); ++it)
        m_supported_extensions.push_back(L'.' + it->toWString());
}

void InteractiveTagger::set_file_rename_format(const std::string &format)
{
    m_file_rename_format = boost::lexical_cast<std::wstring>(format);
}

void InteractiveTagger::set_dir_rename_format(const std::string &format)
{
    m_dir_rename_format = boost::lexical_cast<std::wstring>(format);
}

void InteractiveTagger::tag(int num_paths, const char **paths)
{
    assert(m_terminal);

    // Build a list with the normalized paths
    std::list<fs::path> path_list;
    for (int i = 0; i < num_paths; ++i) {
        char *real_path = realpath(paths[i], NULL);
        if (!real_path) {
            std::string errstr("\"");
            errstr += paths[i];
            errstr += "\" is not a valid path";
            m_terminal->display_warning_message(errstr);
            continue;
        }
        path_list.push_back(fs::path(boost::lexical_cast<std::wstring>(std::string(real_path))));
        free(real_path);
    }

    // Sort it and tag the paths
    path_list.sort();
    BOOST_FOREACH(const fs::path &path, path_list) {
        // Check if the path exists
        if (!fs::exists(path)) {
            m_terminal->display_warning_message(L"Path \"" + path.string<std::wstring>()
                    + L"\" not found, skipping...");
            continue;
        }

        try {
            // If it's a regular file, just tag it
            if (fs::is_regular_file(path)) {
                if (!is_supported_extension(path)) {
                    m_terminal->display_warning_message(L"Path \"" + path.string<std::wstring>()
                            + L"\" has no supported extension, skipping...");
                    continue;
                }
                tag_file(path);
            }

            // If it's a directory, tag its contents
            else if (fs::is_directory(path)) {
                tag_directory(path);
            }

            // It's none of the above, do something about it
            else {
                m_terminal->display_warning_message(L"Path \"" + path.string<std::wstring>()
                        + L"\" is not a regular file or directory, skipping...");
            }
        }
        catch (std::exception &e) {
            m_terminal->display_warning_message(e.what());
        }
    }

    // Save the unsaved files
    if (!m_unsaved_files.empty()
            && (m_dry_run || m_terminal->ask_yes_no_question(L"=== OK to save the changes to the files?"))) {
        if (m_dry_run)
            m_terminal->display_info_message("=== Not saving changes (dry run mode)");
        BOOST_FOREACH(TagLib::FileRef &f, m_unsaved_files) {
            std::string message(m_dry_run ? "Not saving" : "Saving");
            message += " \"" + std::string(f.file()->name()) + '\"';
            m_terminal->display_info_message(message);
            if (!m_dry_run && !f.save())
                m_terminal->display_warning_message("Unable to save " + std::string(f.file()->name()) + "\"");
        }
    }

    // Perform the pending renames
    if (!m_pending_renames.empty()
            && (m_dry_run || m_terminal->ask_yes_no_question(L"=== OK to rename the files?"))) {
        if (m_dry_run)
            m_terminal->display_info_message("=== Not renaming files (dry run mode)");
        std::list<std::pair<fs::path, fs::path> >::const_iterator it;
        for (it = m_pending_renames.begin(); it != m_pending_renames.end(); ++it) {
            const fs::path &from((*it).first);
            const fs::path &to((*it).second);
            m_terminal->display_info_message(from.string());
            m_terminal->display_info_message(L"-> " + to.string<std::wstring>());
            if (!m_dry_run) {
                try { fs::rename(from, to); }
                catch (std::exception &e) { m_terminal->display_warning_message(e.what()); }
            }
        }
    }

    m_terminal->display_info_message("=== All done!");
}

bool InteractiveTagger::is_supported_extension(const fs::path &path)
{
    std::wstring extension(path.extension().string<std::wstring>());
    boost::to_lower(extension);

    BOOST_FOREACH(const std::wstring &supported_extension, m_supported_extensions) {
        if (extension == supported_extension)
            return true;
    }

    return false;
}

std::wstring InteractiveTagger::replace_tokens(const std::wstring &str,
        const std::map<std::wstring, std::wstring> &replacements)
{
    std::wstring res;
    res.reserve(str.size() * 3);

    bool parsing_token = false;
    std::wstring current_token;
    BOOST_FOREACH(char c, str) {
        if (c == '%') {
            if (parsing_token) {
                std::map<std::wstring, std::wstring>::const_iterator it = replacements.find(current_token);
                res += it == replacements.end() ? current_token : it->second;
                current_token.erase();
            }
            parsing_token = true;
        }
        else if (parsing_token) {
            if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
                current_token += c;
            }
            else {
                std::map<std::wstring, std::wstring>::const_iterator it = replacements.find(current_token);
                res += it == replacements.end() ? current_token : it->second;
                res += c;
                parsing_token = false;
                current_token.erase();
            }
        }
        else {
            res += c;
        }
    }
    if (parsing_token) {
        std::map<std::wstring, std::wstring>::const_iterator it = replacements.find(current_token);
        res += it == replacements.end() ? current_token : it->second;
    }

    return res;
}

void InteractiveTagger::tag_file(const fs::path &path, ConfirmationHandler &artist_confirmation,
       ConfirmationHandler &album_confirmation, int *year, int track)
{
    m_terminal->display_info_message(L"=== Tagging \"" + path.filename().string<std::wstring>() + L"\"");

    // Get a reference to the file
    TagLib::FileRef f(path.c_str());

    // Ask for the artist
    artist_confirmation.reset();
    if (!f.tag()->artist().isNull())
        artist_confirmation.set_local_default(m_input_filter->filter(f.tag()->artist().toWString()));
    artist_confirmation.ask(L"Artist:");
    while (!artist_confirmation.complies())
        artist_confirmation.ask(L"Artist (confirmation):");
    f.tag()->setArtist(artist_confirmation.answer());

    // Ask for the album
    album_confirmation.reset();
    if (!f.tag()->album().isNull())
        album_confirmation.set_local_default(m_input_filter->filter(f.tag()->album().toWString()));
    album_confirmation.ask(L"Album:");
    while (!album_confirmation.complies())
        album_confirmation.ask(L"Album (confirmation):");
    f.tag()->setAlbum(album_confirmation.answer());

    // Ask for the year
    boost::optional<int> default_year;
    if (year && *year != -1)
        default_year = *year;
    else if (f.tag()->year())
        default_year = f.tag()->year();
    YearValidator year_validator;
    int new_year = m_terminal->ask_number_question(L"Year:", default_year, &year_validator);
    f.tag()->setYear(new_year);
    if (year) *year = new_year;

    // Ask for the track
    if (track == -1)
        track = f.tag()->track();
    TrackValidator track_validator;
    int new_track = m_terminal->ask_number_question(L"Track:",
            track > 0 ? track : boost::optional<int>(), &track_validator);
    f.tag()->setTrack(new_track);

    // Ask for the song title
    boost::optional<std::wstring> default_title;
    if (!f.tag()->title().isNull())
        default_title = m_input_filter->filter(f.tag()->title().toWString());
    std::wstring new_title = m_terminal->ask_string_question(L"Title:", default_title);
    if (m_output_filter) {
        std::wstring filtered_title = m_output_filter->filter(new_title);
        if (m_input_filter->requires_confirmation_as_output_filter() && filtered_title != new_title)
            filtered_title = m_terminal->ask_string_question(L"Title (confirmation):", filtered_title);
        new_title = filtered_title;
    }
    f.tag()->setTitle(new_title);

    // Reset the comment and genre fields
    f.tag()->setComment(TagLib::String::null);
    f.tag()->setGenre(TagLib::String::null);

    // Add it to the list of unsaved files
    m_unsaved_files.push_back(f);

    // Add it to the list of pending renames based on the supplied format
    if (m_file_rename_format) {
        std::map<std::wstring, std::wstring> tokens;
        tokens[L"artist"] = m_renaming_filter->filter(artist_confirmation.answer());
        tokens[L"album"] = m_renaming_filter->filter(album_confirmation.answer());
        tokens[L"year"] = boost::lexical_cast<std::wstring>(new_year);
        std::wstring track_str(boost::lexical_cast<std::wstring>(new_track));
        if (track_str.size() == 1) track_str = L"0" + track_str;
        tokens[L"track"] = track_str;
        tokens[L"title"] = m_renaming_filter->filter(new_title);
        fs::path new_path = path.parent_path();
        new_path /= replace_tokens(*m_file_rename_format, tokens)
            + boost::to_lower_copy(path.extension().string<std::wstring>());
        if (new_path != path)
            m_pending_renames.push_back(std::pair<fs::path, fs::path>(path, new_path));
    }
}

void InteractiveTagger::tag_file(const boost::filesystem::path &path)
{
    // Tag a file without recording the global default
    ConfirmationHandler amnesiac(*m_terminal, m_input_filter, m_output_filter);
    tag_file(path, amnesiac, amnesiac, NULL, -1);
}

void InteractiveTagger::tag_directory(const fs::path &path)
{
    m_terminal->display_info_message(L"=== Entering \"" + path.string<std::wstring>() + L"\"");

    // Create lists of files and subdirectories
    std::list<fs::path> file_list, dir_list;
    fs::directory_iterator end_it;
    for (fs::directory_iterator it(path); it != end_it; ++it) {
        // Normalize the path (needed here so that we follow symlinks)
        char *real_path = realpath(it->path().c_str(), NULL);
        if (!real_path) {
            m_terminal->display_warning_message(L"\"" + it->path().filename().string<std::wstring>()
                    + L"\" is not a valid path, skipping...");
            continue;
        }
        fs::path boost_path(boost::lexical_cast<std::wstring>(real_path));
        free(real_path);

        // Add to the right list
        if (fs::is_regular_file(boost_path)) {
            if (is_supported_extension(boost_path)) {
                file_list.push_back(boost_path);
            }
            else {
                m_terminal->display_warning_message(L"\"" + it->path().filename().string<std::wstring>()
                        + L"\" has no supported extension, skipping...");
            }
        }
        else if (fs::is_directory(boost_path)) {
            dir_list.push_back(boost_path);
        }
        else {
            m_terminal->display_warning_message(L"\"" + boost_path.filename().string<std::wstring>()
                    + L"\" is not a regular file or directory, skipping...");
        }
    }

    // Sort those lists
    file_list.sort();
    dir_list.sort();

    // Tag all individual files
    ConfirmationHandler artist(*m_terminal, m_input_filter, m_output_filter);
    ConfirmationHandler album(*m_terminal, m_input_filter, m_output_filter);
    int year = -1;
    if (!file_list.empty()) {
        int track = 1;
        BOOST_FOREACH(const fs::path &p, file_list)
            tag_file(p, artist, album, &year, track++);
    }

    // We'll ask confirmation to descend into the subdirectories only if there are files
    BOOST_FOREACH(const fs::path &p, dir_list) {
        if (file_list.empty() || m_terminal->ask_yes_no_question(L"Descend into subdirectory \""
                    + boost::lexical_cast<std::wstring>(p.filename()) + L"\"?", false))
            tag_directory(p);
    }

    // Add it to the list of pending renames based on the supplied format
    if (!artist.answer().empty() && m_dir_rename_format) {
        std::map<std::wstring, std::wstring> tokens;
        tokens[L"artist"] = m_renaming_filter->filter(artist.answer());
        tokens[L"album"] = m_renaming_filter->filter(album.answer());
        tokens[L"year"] = boost::lexical_cast<std::wstring>(year);
        fs::path new_path = path.parent_path();
        new_path /= replace_tokens(*m_dir_rename_format, tokens);
        if (new_path != path)
            m_pending_renames.push_back(std::pair<fs::path, fs::path>(path, new_path));
    }
}
<commit_msg>Use the confirmation handler for the title too.<commit_after>/*
 * This file is part of btag.
 *
 * © 2010-2011 Fernando Tarlá Cardoso Lemos
 *
 * Refer to the LICENSE file for licensing information.
 *
 */

#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>
#include <taglib/fileref.h>
#include <taglib/tag.h>
#include <cassert>
#include <cstdlib>
#include <exception>

#include "InteractiveTagger.h"
#include "validators.h"
#include "wide_string_cast.h"

namespace fs = boost::filesystem;

InteractiveTagger::InteractiveTagger()
    : m_input_filter(NULL), m_output_filter(NULL), m_dry_run(false)
{
    // Load the extensions supported by TagLib
    TagLib::StringList extensions = TagLib::FileRef::defaultFileExtensions();
    for (TagLib::StringList::ConstIterator it = extensions.begin(); it != extensions.end(); ++it)
        m_supported_extensions.push_back(L'.' + it->toWString());
}

void InteractiveTagger::set_file_rename_format(const std::string &format)
{
    m_file_rename_format = boost::lexical_cast<std::wstring>(format);
}

void InteractiveTagger::set_dir_rename_format(const std::string &format)
{
    m_dir_rename_format = boost::lexical_cast<std::wstring>(format);
}

void InteractiveTagger::tag(int num_paths, const char **paths)
{
    assert(m_terminal);

    // Build a list with the normalized paths
    std::list<fs::path> path_list;
    for (int i = 0; i < num_paths; ++i) {
        char *real_path = realpath(paths[i], NULL);
        if (!real_path) {
            std::string errstr("\"");
            errstr += paths[i];
            errstr += "\" is not a valid path";
            m_terminal->display_warning_message(errstr);
            continue;
        }
        path_list.push_back(fs::path(boost::lexical_cast<std::wstring>(std::string(real_path))));
        free(real_path);
    }

    // Sort it and tag the paths
    path_list.sort();
    BOOST_FOREACH(const fs::path &path, path_list) {
        // Check if the path exists
        if (!fs::exists(path)) {
            m_terminal->display_warning_message(L"Path \"" + path.string<std::wstring>()
                    + L"\" not found, skipping...");
            continue;
        }

        try {
            // If it's a regular file, just tag it
            if (fs::is_regular_file(path)) {
                if (!is_supported_extension(path)) {
                    m_terminal->display_warning_message(L"Path \"" + path.string<std::wstring>()
                            + L"\" has no supported extension, skipping...");
                    continue;
                }
                tag_file(path);
            }

            // If it's a directory, tag its contents
            else if (fs::is_directory(path)) {
                tag_directory(path);
            }

            // It's none of the above, do something about it
            else {
                m_terminal->display_warning_message(L"Path \"" + path.string<std::wstring>()
                        + L"\" is not a regular file or directory, skipping...");
            }
        }
        catch (std::exception &e) {
            m_terminal->display_warning_message(e.what());
        }
    }

    // Save the unsaved files
    if (!m_unsaved_files.empty()
            && (m_dry_run || m_terminal->ask_yes_no_question(L"=== OK to save the changes to the files?"))) {
        if (m_dry_run)
            m_terminal->display_info_message("=== Not saving changes (dry run mode)");
        BOOST_FOREACH(TagLib::FileRef &f, m_unsaved_files) {
            std::string message(m_dry_run ? "Not saving" : "Saving");
            message += " \"" + std::string(f.file()->name()) + '\"';
            m_terminal->display_info_message(message);
            if (!m_dry_run && !f.save())
                m_terminal->display_warning_message("Unable to save " + std::string(f.file()->name()) + "\"");
        }
    }

    // Perform the pending renames
    if (!m_pending_renames.empty()
            && (m_dry_run || m_terminal->ask_yes_no_question(L"=== OK to rename the files?"))) {
        if (m_dry_run)
            m_terminal->display_info_message("=== Not renaming files (dry run mode)");
        std::list<std::pair<fs::path, fs::path> >::const_iterator it;
        for (it = m_pending_renames.begin(); it != m_pending_renames.end(); ++it) {
            const fs::path &from((*it).first);
            const fs::path &to((*it).second);
            m_terminal->display_info_message(from.string());
            m_terminal->display_info_message(L"-> " + to.string<std::wstring>());
            if (!m_dry_run) {
                try { fs::rename(from, to); }
                catch (std::exception &e) { m_terminal->display_warning_message(e.what()); }
            }
        }
    }

    m_terminal->display_info_message("=== All done!");
}

bool InteractiveTagger::is_supported_extension(const fs::path &path)
{
    std::wstring extension(path.extension().string<std::wstring>());
    boost::to_lower(extension);

    BOOST_FOREACH(const std::wstring &supported_extension, m_supported_extensions) {
        if (extension == supported_extension)
            return true;
    }

    return false;
}

std::wstring InteractiveTagger::replace_tokens(const std::wstring &str,
        const std::map<std::wstring, std::wstring> &replacements)
{
    std::wstring res;
    res.reserve(str.size() * 3);

    bool parsing_token = false;
    std::wstring current_token;
    BOOST_FOREACH(char c, str) {
        if (c == '%') {
            if (parsing_token) {
                std::map<std::wstring, std::wstring>::const_iterator it = replacements.find(current_token);
                res += it == replacements.end() ? current_token : it->second;
                current_token.erase();
            }
            parsing_token = true;
        }
        else if (parsing_token) {
            if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
                current_token += c;
            }
            else {
                std::map<std::wstring, std::wstring>::const_iterator it = replacements.find(current_token);
                res += it == replacements.end() ? current_token : it->second;
                res += c;
                parsing_token = false;
                current_token.erase();
            }
        }
        else {
            res += c;
        }
    }
    if (parsing_token) {
        std::map<std::wstring, std::wstring>::const_iterator it = replacements.find(current_token);
        res += it == replacements.end() ? current_token : it->second;
    }

    return res;
}

void InteractiveTagger::tag_file(const fs::path &path, ConfirmationHandler &artist_confirmation,
       ConfirmationHandler &album_confirmation, int *year, int track)
{
    m_terminal->display_info_message(L"=== Tagging \"" + path.filename().string<std::wstring>() + L"\"");

    // Get a reference to the file
    TagLib::FileRef f(path.c_str());

    // Ask for the artist
    artist_confirmation.reset();
    if (!f.tag()->artist().isNull())
        artist_confirmation.set_local_default(m_input_filter->filter(f.tag()->artist().toWString()));
    artist_confirmation.ask(L"Artist:");
    while (!artist_confirmation.complies())
        artist_confirmation.ask(L"Artist (confirmation):");
    f.tag()->setArtist(artist_confirmation.answer());

    // Ask for the album
    album_confirmation.reset();
    if (!f.tag()->album().isNull())
        album_confirmation.set_local_default(m_input_filter->filter(f.tag()->album().toWString()));
    album_confirmation.ask(L"Album:");
    while (!album_confirmation.complies())
        album_confirmation.ask(L"Album (confirmation):");
    f.tag()->setAlbum(album_confirmation.answer());

    // Ask for the year
    boost::optional<int> default_year;
    if (year && *year != -1)
        default_year = *year;
    else if (f.tag()->year())
        default_year = f.tag()->year();
    YearValidator year_validator;
    int new_year = m_terminal->ask_number_question(L"Year:", default_year, &year_validator);
    f.tag()->setYear(new_year);
    if (year) *year = new_year;

    // Ask for the track
    if (track == -1)
        track = f.tag()->track();
    TrackValidator track_validator;
    int new_track = m_terminal->ask_number_question(L"Track:",
            track > 0 ? track : boost::optional<int>(), &track_validator);
    f.tag()->setTrack(new_track);

    // Ask for the song title
    ConfirmationHandler title_confirmation(*m_terminal, m_input_filter, m_output_filter);
    title_confirmation.reset();
    if (!f.tag()->title().isNull())
        title_confirmation.set_local_default(m_input_filter->filter(f.tag()->title().toWString()));
    title_confirmation.ask(L"Title:");
    while (!title_confirmation.complies())
        title_confirmation.ask(L"Title (confirmation):");
    f.tag()->setTitle(title_confirmation.answer());

    // Reset the comment and genre fields
    f.tag()->setComment(TagLib::String::null);
    f.tag()->setGenre(TagLib::String::null);

    // Add it to the list of unsaved files
    m_unsaved_files.push_back(f);

    // Add it to the list of pending renames based on the supplied format
    if (m_file_rename_format) {
        std::map<std::wstring, std::wstring> tokens;
        tokens[L"artist"] = m_renaming_filter->filter(artist_confirmation.answer());
        tokens[L"album"] = m_renaming_filter->filter(album_confirmation.answer());
        tokens[L"year"] = boost::lexical_cast<std::wstring>(new_year);
        std::wstring track_str(boost::lexical_cast<std::wstring>(new_track));
        if (track_str.size() == 1) track_str = L"0" + track_str;
        tokens[L"track"] = track_str;
        tokens[L"title"] = m_renaming_filter->filter(title_confirmation.answer());
        fs::path new_path = path.parent_path();
        new_path /= replace_tokens(*m_file_rename_format, tokens)
            + boost::to_lower_copy(path.extension().string<std::wstring>());
        if (new_path != path)
            m_pending_renames.push_back(std::pair<fs::path, fs::path>(path, new_path));
    }
}

void InteractiveTagger::tag_file(const boost::filesystem::path &path)
{
    // Tag a file without recording the global default
    ConfirmationHandler amnesiac(*m_terminal, m_input_filter, m_output_filter);
    tag_file(path, amnesiac, amnesiac, NULL, -1);
}

void InteractiveTagger::tag_directory(const fs::path &path)
{
    m_terminal->display_info_message(L"=== Entering \"" + path.string<std::wstring>() + L"\"");

    // Create lists of files and subdirectories
    std::list<fs::path> file_list, dir_list;
    fs::directory_iterator end_it;
    for (fs::directory_iterator it(path); it != end_it; ++it) {
        // Normalize the path (needed here so that we follow symlinks)
        char *real_path = realpath(it->path().c_str(), NULL);
        if (!real_path) {
            m_terminal->display_warning_message(L"\"" + it->path().filename().string<std::wstring>()
                    + L"\" is not a valid path, skipping...");
            continue;
        }
        fs::path boost_path(boost::lexical_cast<std::wstring>(real_path));
        free(real_path);

        // Add to the right list
        if (fs::is_regular_file(boost_path)) {
            if (is_supported_extension(boost_path)) {
                file_list.push_back(boost_path);
            }
            else {
                m_terminal->display_warning_message(L"\"" + it->path().filename().string<std::wstring>()
                        + L"\" has no supported extension, skipping...");
            }
        }
        else if (fs::is_directory(boost_path)) {
            dir_list.push_back(boost_path);
        }
        else {
            m_terminal->display_warning_message(L"\"" + boost_path.filename().string<std::wstring>()
                    + L"\" is not a regular file or directory, skipping...");
        }
    }

    // Sort those lists
    file_list.sort();
    dir_list.sort();

    // Tag all individual files
    ConfirmationHandler artist(*m_terminal, m_input_filter, m_output_filter);
    ConfirmationHandler album(*m_terminal, m_input_filter, m_output_filter);
    int year = -1;
    if (!file_list.empty()) {
        int track = 1;
        BOOST_FOREACH(const fs::path &p, file_list)
            tag_file(p, artist, album, &year, track++);
    }

    // We'll ask confirmation to descend into the subdirectories only if there are files
    BOOST_FOREACH(const fs::path &p, dir_list) {
        if (file_list.empty() || m_terminal->ask_yes_no_question(L"Descend into subdirectory \""
                    + boost::lexical_cast<std::wstring>(p.filename()) + L"\"?", false))
            tag_directory(p);
    }

    // Add it to the list of pending renames based on the supplied format
    if (!artist.answer().empty() && m_dir_rename_format) {
        std::map<std::wstring, std::wstring> tokens;
        tokens[L"artist"] = m_renaming_filter->filter(artist.answer());
        tokens[L"album"] = m_renaming_filter->filter(album.answer());
        tokens[L"year"] = boost::lexical_cast<std::wstring>(year);
        fs::path new_path = path.parent_path();
        new_path /= replace_tokens(*m_dir_rename_format, tokens);
        if (new_path != path)
            m_pending_renames.push_back(std::pair<fs::path, fs::path>(path, new_path));
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "tensorfieldvalue.h"
#include <vespa/document/base/exceptions.h>
#include <vespa/document/datatype/tensor_data_type.h>
#include <vespa/vespalib/util/xmlstream.h>
#include <vespa/eval/eval/engine_or_factory.h>
#include <vespa/eval/eval/tensor_spec.h>
#include <vespa/eval/eval/value.h>
#include <vespa/eval/eval/engine_or_factory.h>
#include <ostream>
#include <cassert>

using vespalib::eval::EngineOrFactory;
using vespalib::eval::TensorSpec;
using vespalib::eval::ValueType;
using namespace vespalib::xml;

namespace document {

namespace {

TensorDataType emptyTensorDataType;

vespalib::string makeWrongTensorTypeMsg(const ValueType &fieldTensorType, const ValueType &tensorType)
{
    return vespalib::make_string("Field tensor type is '%s' but other tensor type is '%s'",
                                 fieldTensorType.to_spec().c_str(),
                                 tensorType.to_spec().c_str());
}

}

TensorFieldValue::TensorFieldValue()
    : TensorFieldValue(emptyTensorDataType)
{
}

TensorFieldValue::TensorFieldValue(const TensorDataType &dataType)
    : FieldValue(),
      _dataType(dataType),
      _tensor(),
      _altered(true)
{
}

TensorFieldValue::TensorFieldValue(const TensorFieldValue &rhs)
    : FieldValue(),
      _dataType(rhs._dataType),
      _tensor(),
      _altered(true)
{
    if (rhs._tensor) {
        _tensor = EngineOrFactory::get().copy(*rhs._tensor);
    }
}

TensorFieldValue::TensorFieldValue(TensorFieldValue &&rhs)
    : FieldValue(),
      _dataType(rhs._dataType),
      _tensor(),
      _altered(true)
{
    _tensor = std::move(rhs._tensor);
}

TensorFieldValue::~TensorFieldValue()
{
}

TensorFieldValue &
TensorFieldValue::operator=(const TensorFieldValue &rhs)
{
    if (this != &rhs) {
        if (&_dataType == &rhs._dataType || !rhs._tensor ||
            _dataType.isAssignableType(rhs._tensor->type())) {
            if (rhs._tensor) {
                _tensor = EngineOrFactory::get().copy(*rhs._tensor);
            } else {
                _tensor.reset();
            }
            _altered = true;
        } else {
            throw WrongTensorTypeException(makeWrongTensorTypeMsg(_dataType.getTensorType(), rhs._tensor->type()), VESPA_STRLOC);
        }
    }
    return *this;
}

TensorFieldValue &
TensorFieldValue::operator=(std::unique_ptr<vespalib::eval::Value> rhs)
{
    if (!rhs || _dataType.isAssignableType(rhs->type())) {
        _tensor = std::move(rhs);
        _altered = true;
    } else {
        throw WrongTensorTypeException(makeWrongTensorTypeMsg(_dataType.getTensorType(), rhs->type()), VESPA_STRLOC);
    }
    return *this;
}

void
TensorFieldValue::make_empty_if_not_existing()
{
    if (!_tensor) {
        TensorSpec empty_spec(_dataType.getTensorType().to_spec());
        _tensor = EngineOrFactory::get().from_spec(empty_spec);
    }
}

void
TensorFieldValue::accept(FieldValueVisitor &visitor)
{
    visitor.visit(*this);
}

void
TensorFieldValue::accept(ConstFieldValueVisitor &visitor) const
{
    visitor.visit(*this);
}

const DataType *
TensorFieldValue::getDataType() const
{
    return &_dataType;
}

bool
TensorFieldValue::hasChanged() const
{
    return _altered;
}

TensorFieldValue*
TensorFieldValue::clone() const
{
    return new TensorFieldValue(*this);
}

void
TensorFieldValue::print(std::ostream& out, bool verbose,
                        const std::string& indent) const
{
    (void) verbose;
    (void) indent;
    out << "{TensorFieldValue: ";
    if (_tensor) {
        out << EngineOrFactory::get().to_spec(*_tensor).to_string();
    } else {
        out << "null";
    }
    out << "}";
}

void
TensorFieldValue::printXml(XmlOutputStream& out) const
{
    out << "{TensorFieldValue::printXml not yet implemented}";
}

FieldValue &
TensorFieldValue::assign(const FieldValue &value)
{
    const TensorFieldValue *rhs =
        Identifiable::cast<const TensorFieldValue *>(&value);
    if (rhs != nullptr) {
        *this = *rhs;
    } else {
        return FieldValue::assign(value);
    }
    return *this;
}

void
TensorFieldValue::assignDeserialized(std::unique_ptr<vespalib::eval::Value> rhs)
{
    if (!rhs || _dataType.isAssignableType(rhs->type())) {
        _tensor = std::move(rhs);
        _altered = false; // Serialized form already exists
    } else {
        throw WrongTensorTypeException(makeWrongTensorTypeMsg(_dataType.getTensorType(), rhs->type()), VESPA_STRLOC);
    }
}

int
TensorFieldValue::compare(const FieldValue &other) const
{
    if (this == &other) {
        return 0;	// same identity
    }
    int diff = FieldValue::compare(other);
    if (diff != 0) {
        return diff;    // field type mismatch
    }
    const TensorFieldValue & rhs(static_cast<const TensorFieldValue &>(other));
    if (!_tensor) {
        return (rhs._tensor ? -1 : 0);
    }
    if (!rhs._tensor) {
        return 1;
    }
    // equal pointers always means identical
    if (_tensor.get() == rhs._tensor.get()) {
        return 0;
    }
    // compare just the type first:
    auto lhs_type = _tensor->type().to_spec();
    auto rhs_type = rhs._tensor->type().to_spec();
    int type_cmp = lhs_type.compare(rhs_type);
    if (type_cmp != 0) {
        return type_cmp;
    }
    // Compare the actual tensors by converting to TensorSpec strings.
    // TODO: this can be very slow, check if it might be used for anything
    // performance-critical.
    auto engine = EngineOrFactory::get();
    auto lhs_spec = engine.to_spec(*_tensor).to_string();
    auto rhs_spec = engine.to_spec(*rhs._tensor).to_string();
    return lhs_spec.compare(rhs_spec);
}

IMPLEMENT_IDENTIFIABLE(TensorFieldValue, FieldValue);

} // document
<commit_msg>use spec_from_value<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "tensorfieldvalue.h"
#include <vespa/document/base/exceptions.h>
#include <vespa/document/datatype/tensor_data_type.h>
#include <vespa/vespalib/util/xmlstream.h>
#include <vespa/eval/eval/engine_or_factory.h>
#include <vespa/eval/eval/tensor_spec.h>
#include <vespa/eval/eval/value_codec.h>
#include <vespa/eval/eval/value.h>
#include <ostream>
#include <cassert>

using vespalib::eval::EngineOrFactory;
using vespalib::eval::TensorSpec;
using vespalib::eval::ValueType;
using namespace vespalib::xml;

namespace document {

namespace {

TensorDataType emptyTensorDataType;

vespalib::string makeWrongTensorTypeMsg(const ValueType &fieldTensorType, const ValueType &tensorType)
{
    return vespalib::make_string("Field tensor type is '%s' but other tensor type is '%s'",
                                 fieldTensorType.to_spec().c_str(),
                                 tensorType.to_spec().c_str());
}

}

TensorFieldValue::TensorFieldValue()
    : TensorFieldValue(emptyTensorDataType)
{
}

TensorFieldValue::TensorFieldValue(const TensorDataType &dataType)
    : FieldValue(),
      _dataType(dataType),
      _tensor(),
      _altered(true)
{
}

TensorFieldValue::TensorFieldValue(const TensorFieldValue &rhs)
    : FieldValue(),
      _dataType(rhs._dataType),
      _tensor(),
      _altered(true)
{
    if (rhs._tensor) {
        _tensor = EngineOrFactory::get().copy(*rhs._tensor);
    }
}

TensorFieldValue::TensorFieldValue(TensorFieldValue &&rhs)
    : FieldValue(),
      _dataType(rhs._dataType),
      _tensor(),
      _altered(true)
{
    _tensor = std::move(rhs._tensor);
}

TensorFieldValue::~TensorFieldValue()
{
}

TensorFieldValue &
TensorFieldValue::operator=(const TensorFieldValue &rhs)
{
    if (this != &rhs) {
        if (&_dataType == &rhs._dataType || !rhs._tensor ||
            _dataType.isAssignableType(rhs._tensor->type())) {
            if (rhs._tensor) {
                _tensor = EngineOrFactory::get().copy(*rhs._tensor);
            } else {
                _tensor.reset();
            }
            _altered = true;
        } else {
            throw WrongTensorTypeException(makeWrongTensorTypeMsg(_dataType.getTensorType(), rhs._tensor->type()), VESPA_STRLOC);
        }
    }
    return *this;
}

TensorFieldValue &
TensorFieldValue::operator=(std::unique_ptr<vespalib::eval::Value> rhs)
{
    if (!rhs || _dataType.isAssignableType(rhs->type())) {
        _tensor = std::move(rhs);
        _altered = true;
    } else {
        throw WrongTensorTypeException(makeWrongTensorTypeMsg(_dataType.getTensorType(), rhs->type()), VESPA_STRLOC);
    }
    return *this;
}

void
TensorFieldValue::make_empty_if_not_existing()
{
    if (!_tensor) {
        TensorSpec empty_spec(_dataType.getTensorType().to_spec());
        _tensor = EngineOrFactory::get().from_spec(empty_spec);
    }
}

void
TensorFieldValue::accept(FieldValueVisitor &visitor)
{
    visitor.visit(*this);
}

void
TensorFieldValue::accept(ConstFieldValueVisitor &visitor) const
{
    visitor.visit(*this);
}

const DataType *
TensorFieldValue::getDataType() const
{
    return &_dataType;
}

bool
TensorFieldValue::hasChanged() const
{
    return _altered;
}

TensorFieldValue*
TensorFieldValue::clone() const
{
    return new TensorFieldValue(*this);
}

void
TensorFieldValue::print(std::ostream& out, bool verbose,
                        const std::string& indent) const
{
    (void) verbose;
    (void) indent;
    out << "{TensorFieldValue: ";
    if (_tensor) {
        out << spec_from_value(*_tensor).to_string();
    } else {
        out << "null";
    }
    out << "}";
}

void
TensorFieldValue::printXml(XmlOutputStream& out) const
{
    out << "{TensorFieldValue::printXml not yet implemented}";
}

FieldValue &
TensorFieldValue::assign(const FieldValue &value)
{
    const TensorFieldValue *rhs =
        Identifiable::cast<const TensorFieldValue *>(&value);
    if (rhs != nullptr) {
        *this = *rhs;
    } else {
        return FieldValue::assign(value);
    }
    return *this;
}

void
TensorFieldValue::assignDeserialized(std::unique_ptr<vespalib::eval::Value> rhs)
{
    if (!rhs || _dataType.isAssignableType(rhs->type())) {
        _tensor = std::move(rhs);
        _altered = false; // Serialized form already exists
    } else {
        throw WrongTensorTypeException(makeWrongTensorTypeMsg(_dataType.getTensorType(), rhs->type()), VESPA_STRLOC);
    }
}

int
TensorFieldValue::compare(const FieldValue &other) const
{
    if (this == &other) {
        return 0;	// same identity
    }
    int diff = FieldValue::compare(other);
    if (diff != 0) {
        return diff;    // field type mismatch
    }
    const TensorFieldValue & rhs(static_cast<const TensorFieldValue &>(other));
    if (!_tensor) {
        return (rhs._tensor ? -1 : 0);
    }
    if (!rhs._tensor) {
        return 1;
    }
    // equal pointers always means identical
    if (_tensor.get() == rhs._tensor.get()) {
        return 0;
    }
    // compare just the type first:
    auto lhs_type = _tensor->type().to_spec();
    auto rhs_type = rhs._tensor->type().to_spec();
    int type_cmp = lhs_type.compare(rhs_type);
    if (type_cmp != 0) {
        return type_cmp;
    }
    // Compare the actual tensors by converting to TensorSpec strings.
    // TODO: this can be very slow, check if it might be used for anything
    // performance-critical.
    auto lhs_spec = spec_from_value(*_tensor).to_string();
    auto rhs_spec = spec_from_value(*rhs._tensor).to_string();
    return lhs_spec.compare(rhs_spec);
}

IMPLEMENT_IDENTIFIABLE(TensorFieldValue, FieldValue);

} // document
<|endoftext|>