<commit_before>/*************************************************************************
 *
 *  $RCSfile: dpgroupdlg.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-03-29 12:55:05 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#ifdef SC_DLLIMPLEMENTATION
#undef SC_DLLIMPLEMENTATION
#endif

#ifdef PCH
#include "ui_pch.hxx"
#endif

#ifndef SC_DPGROUPDLG_HXX
#include "dpgroupdlg.hxx"
#endif
#ifndef SC_DPGROUPDLG_HRC
#include "dpgroupdlg.hrc"
#endif

#ifndef _TOOLS_RESARY_HXX
#include <tools/resary.hxx>
#endif
#ifndef SC_SCRESID_HXX
#include "scresid.hxx"
#endif
#ifndef SC_SC_HRC
#include "sc.hrc"
#endif

#ifndef _COM_SUN_STAR_SHEET_DATAPILOTFIELDGROUPBY_HPP_
#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
#endif

// ============================================================================

namespace {

/** Date part flags in order of the list box entries. */
static const sal_Int32 spnDateParts[] =
{
    com::sun::star::sheet::DataPilotFieldGroupBy::SECONDS,
    com::sun::star::sheet::DataPilotFieldGroupBy::MINUTES,
    com::sun::star::sheet::DataPilotFieldGroupBy::HOURS,
    com::sun::star::sheet::DataPilotFieldGroupBy::DAYS,
    com::sun::star::sheet::DataPilotFieldGroupBy::MONTHS,
    com::sun::star::sheet::DataPilotFieldGroupBy::QUARTERS,
    com::sun::star::sheet::DataPilotFieldGroupBy::YEARS
};

} // namespace

// ============================================================================

ScDPGroupEditHelper::ScDPGroupEditHelper( RadioButton& rRbAuto, RadioButton& rRbMan, Edit& rEdValue ) :
    mrRbAuto( rRbAuto ),
    mrRbMan( rRbMan ),
    mrEdValue( rEdValue )
{
    mrRbAuto.SetClickHdl( LINK( this, ScDPGroupEditHelper, ClickHdl ) );
    mrRbMan.SetClickHdl( LINK( this, ScDPGroupEditHelper, ClickHdl ) );
}

bool ScDPGroupEditHelper::IsAuto() const
{
    return mrRbAuto.IsChecked();
}

double ScDPGroupEditHelper::GetValue() const
{
    double fValue;
    if( !ImplGetValue( fValue ) )
        fValue = 0.0;
    return fValue;
}

void ScDPGroupEditHelper::SetValue( bool bAuto, double fValue )
{
    if( bAuto )
    {
        mrRbAuto.Check();
        ClickHdl( &mrRbAuto );
    }
    else
    {
        mrRbMan.Check();
        ClickHdl( &mrRbMan );
    }
    ImplSetValue( fValue );
}

IMPL_LINK( ScDPGroupEditHelper, ClickHdl, RadioButton*, pButton )
{
    if( pButton == &mrRbAuto )
    {
        // disable edit field on clicking "automatic" radio button
        mrEdValue.Disable();
    }
    else if( pButton == &mrRbMan )
    {
        // enable and set focus to edit field on clicking "manual" radio button
        mrEdValue.Enable();
        mrEdValue.GrabFocus();
    }
    return 0;
}

// ----------------------------------------------------------------------------

ScDPNumGroupEditHelper::ScDPNumGroupEditHelper(
        RadioButton& rRbAuto, RadioButton& rRbMan, ScDoubleField& rEdValue ) :
    ScDPGroupEditHelper( rRbAuto, rRbMan, rEdValue ),
    mrEdValue( rEdValue )
{
}

bool ScDPNumGroupEditHelper::ImplGetValue( double& rfValue ) const
{
    return mrEdValue.GetValue( rfValue );
}

void ScDPNumGroupEditHelper::ImplSetValue( double fValue )
{
    mrEdValue.SetValue( fValue );
}

// ----------------------------------------------------------------------------

ScDPDateGroupEditHelper::ScDPDateGroupEditHelper(
        RadioButton& rRbAuto, RadioButton& rRbMan, DateField& rEdValue, const Date& rNullDate ) :
    ScDPGroupEditHelper( rRbAuto, rRbMan, rEdValue ),
    mrEdValue( rEdValue ),
    maNullDate( rNullDate )
{
}

bool ScDPDateGroupEditHelper::ImplGetValue( double& rfValue ) const
{
    rfValue = mrEdValue.GetDate() - maNullDate;
    return true;
}

void ScDPDateGroupEditHelper::ImplSetValue( double fValue )
{
    Date aDate( maNullDate );
    aDate += static_cast< sal_Int32 >( fValue );
    mrEdValue.SetDate( aDate );
}

// ============================================================================
// ============================================================================

ScDPNumGroupDlg::ScDPNumGroupDlg( Window* pParent, const ScDPNumGroupInfo& rInfo ) :
    ModalDialog     ( pParent, ScResId( RID_SCDLG_DPNUMGROUP ) ),
    maFlStart       ( this, ScResId( FL_START ) ),
    maRbAutoStart   ( this, ScResId( RB_AUTOSTART ) ),
    maRbManStart    ( this, ScResId( RB_MANSTART ) ),
    maEdStart       ( this, ScResId( ED_START ) ),
    maFlEnd         ( this, ScResId( FL_END ) ),
    maRbAutoEnd     ( this, ScResId( RB_AUTOEND ) ),
    maRbManEnd      ( this, ScResId( RB_MANEND ) ),
    maEdEnd         ( this, ScResId( ED_END ) ),
    maFlBy          ( this, ScResId( FL_BY ) ),
    maEdBy          ( this, ScResId( ED_BY ) ),
    maBtnOk         ( this, ScResId( BTN_OK ) ),
    maBtnCancel     ( this, ScResId( BTN_CANCEL ) ),
    maBtnHelp       ( this, ScResId( BTN_HELP ) ),
    maStartHelper   ( maRbAutoStart, maRbManStart, maEdStart ),
    maEndHelper     ( maRbAutoEnd, maRbManEnd, maEdEnd )
{
    FreeResource();

    maStartHelper.SetValue( rInfo.AutoStart, rInfo.Start );
    maEndHelper.SetValue( rInfo.AutoEnd, rInfo.End );
    maEdBy.SetValue( (rInfo.Step <= 0.0) ? 1.0 : rInfo.Step );

    /*  Set the initial focus, currently it is somewhere after calling all the radio
        button click handlers. Now the first enabled editable control is focused. */
    if( maEdStart.IsEnabled() )
        maEdStart.GrabFocus();
    else if( maEdEnd.IsEnabled() )
        maEdEnd.GrabFocus();
    else
        maEdBy.GrabFocus();
}

ScDPNumGroupInfo ScDPNumGroupDlg::GetGroupInfo() const
{
    ScDPNumGroupInfo aInfo;
    aInfo.Enable = sal_True;
    aInfo.DateValues = sal_False;
    aInfo.AutoStart = maStartHelper.IsAuto();
    aInfo.AutoEnd = maEndHelper.IsAuto();

    // get values and silently auto-correct them, if they are not valid
    // TODO: error messages in OK event?
    aInfo.Start = maStartHelper.GetValue();
    aInfo.End = maEndHelper.GetValue();
    if( !maEdBy.GetValue( aInfo.Step ) || (aInfo.Step <= 0.0) )
        aInfo.Step = 1.0;
    if( aInfo.End <= aInfo.Start )
        aInfo.End = aInfo.Start + aInfo.Step;

    return aInfo;
}

// ============================================================================

ScDPDateGroupDlg::ScDPDateGroupDlg( Window* pParent,
        const ScDPNumGroupInfo& rInfo, sal_Int32 nDatePart, const Date& rNullDate ) :
    ModalDialog     ( pParent, ScResId( RID_SCDLG_DPDATEGROUP ) ),
    maFlStart       ( this, ScResId( FL_START ) ),
    maRbAutoStart   ( this, ScResId( RB_AUTOSTART ) ),
    maRbManStart    ( this, ScResId( RB_MANSTART ) ),
    maEdStart       ( this, ScResId( ED_START ) ),
    maFlEnd         ( this, ScResId( FL_END ) ),
    maRbAutoEnd     ( this, ScResId( RB_AUTOEND ) ),
    maRbManEnd      ( this, ScResId( RB_MANEND ) ),
    maEdEnd         ( this, ScResId( ED_END ) ),
    maFlBy          ( this, ScResId( FL_BY ) ),
    maRbNumDays     ( this, ScResId( RB_NUMDAYS ) ),
    maRbUnits       ( this, ScResId( RB_UNITS ) ),
    maEdNumDays     ( this, ScResId( ED_NUMDAYS ) ),
    maLbUnits       ( this, ScResId( LB_UNITS ) ),
    maBtnOk         ( this, ScResId( BTN_OK ) ),
    maBtnCancel     ( this, ScResId( BTN_CANCEL ) ),
    maBtnHelp       ( this, ScResId( BTN_HELP ) ),
    maStartHelper   ( maRbAutoStart, maRbManStart, maEdStart, rNullDate ),
    maEndHelper     ( maRbAutoEnd, maRbManEnd, maEdEnd, rNullDate )
{
    maLbUnits.SetHelpId( HID_SC_DPDATEGROUP_LB );
    ResStringArray aArr( ScResId( STR_UNITS ) );
    for( USHORT nIdx = 0, nCount = aArr.Count(); nIdx < nCount; ++nIdx )
        maLbUnits.InsertEntry( aArr.GetString( nIdx ) );

    FreeResource();

    maEdStart.SetShowDateCentury( TRUE );
    maEdEnd.SetShowDateCentury( TRUE );

    maStartHelper.SetValue( rInfo.AutoStart, rInfo.Start );
    maEndHelper.SetValue( rInfo.AutoEnd, rInfo.End );

    if( nDatePart == 0 )
        nDatePart = com::sun::star::sheet::DataPilotFieldGroupBy::MONTHS;
    for( ULONG nIdx = 0, nCount = maLbUnits.GetEntryCount(); nIdx < nCount; ++nIdx )
        maLbUnits.CheckEntryPos( static_cast< USHORT >( nIdx ), (nDatePart & spnDateParts[ nIdx ]) != 0 );

    if( rInfo.DateValues )
    {
        maRbNumDays.Check();
        ClickHdl( &maRbNumDays );

        double fNumDays = rInfo.Step;
        if( fNumDays < 1.0 )
            fNumDays = 1.0;
        else if( fNumDays > 32767.0 )
            fNumDays = 32767.0;
        maEdNumDays.SetValue( static_cast< long >( fNumDays ) );
    }
    else
    {
        maRbUnits.Check();
        ClickHdl( &maRbUnits );
    }

    /*  Set the initial focus, currently it is somewhere after calling all the radio
        button click handlers. Now the first enabled editable control is focused. */
    if( maEdStart.IsEnabled() )
        maEdStart.GrabFocus();
    else if( maEdEnd.IsEnabled() )
        maEdEnd.GrabFocus();
    else if( maEdNumDays.IsEnabled() )
        maEdNumDays.GrabFocus();
    else if( maLbUnits.IsEnabled() )
        maLbUnits.GrabFocus();

    maRbNumDays.SetClickHdl( LINK( this, ScDPDateGroupDlg, ClickHdl ) );
    maRbUnits.SetClickHdl( LINK( this, ScDPDateGroupDlg, ClickHdl ) );
    maLbUnits.SetCheckButtonHdl( LINK( this, ScDPDateGroupDlg, CheckHdl ) );
}

ScDPNumGroupInfo ScDPDateGroupDlg::GetGroupInfo() const
{
    ScDPNumGroupInfo aInfo;
    aInfo.Enable = sal_True;
    aInfo.DateValues = maRbNumDays.IsChecked();
    aInfo.AutoStart = maStartHelper.IsAuto();
    aInfo.AutoEnd = maEndHelper.IsAuto();

    // get values and silently auto-correct them, if they are not valid
    // TODO: error messages in OK event?
    aInfo.Start = maStartHelper.GetValue();
    aInfo.End = maEndHelper.GetValue();
    long nNumDays = maEdNumDays.GetValue();
    aInfo.Step = aInfo.DateValues ? nNumDays : 0L;
    if( aInfo.End <= aInfo.Start )
        aInfo.End = aInfo.Start + nNumDays;

    return aInfo;
}

sal_Int32 ScDPDateGroupDlg::GetDatePart() const
{
    // return DAYS for special "number of days" mode
    if( maRbNumDays.IsChecked() )
        return com::sun::star::sheet::DataPilotFieldGroupBy::DAYS;

    // return listbox contents for "units" mode
    sal_Int32 nDatePart = 0;
    for( ULONG nIdx = 0, nCount = maLbUnits.GetEntryCount(); nIdx < nCount; ++nIdx )
        if( maLbUnits.IsChecked( static_cast< USHORT >( nIdx ) ) )
            nDatePart |= spnDateParts[ nIdx ];
    return nDatePart;
}

IMPL_LINK( ScDPDateGroupDlg, ClickHdl, RadioButton*, pButton )
{
    if( pButton == &maRbNumDays )
    {
        maLbUnits.Disable();
        // enable and set focus to edit field on clicking "num of days" radio button
        maEdNumDays.Enable();
        maEdNumDays.GrabFocus();
        maBtnOk.Enable();
    }
    else if( pButton == &maRbUnits )
    {
        maEdNumDays.Disable();
        // enable and set focus to listbox on clicking "units" radio button
        maLbUnits.Enable();
        maLbUnits.GrabFocus();
        // disable OK button if no date part selected
        CheckHdl( &maLbUnits );
    }
    return 0;
}

IMPL_LINK( ScDPDateGroupDlg, CheckHdl, SvxCheckListBox*, pListBox )
{
    // enable/disable OK button on modifying check list box
    if( pListBox == &maLbUnits )
        maBtnOk.Enable( maLbUnits.GetCheckedEntryCount() > 0 );
    return 0;
}

// ============================================================================

<commit_msg>INTEGRATION: CWS ooo19126 (1.4.116); FILE MERGED 2005/09/05 15:04:15 rt 1.4.116.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dpgroupdlg.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 20:34:36 $
 *
 *  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
 *
 ************************************************************************/

#ifdef SC_DLLIMPLEMENTATION
#undef SC_DLLIMPLEMENTATION
#endif

#ifdef PCH
#include "ui_pch.hxx"
#endif

#ifndef SC_DPGROUPDLG_HXX
#include "dpgroupdlg.hxx"
#endif
#ifndef SC_DPGROUPDLG_HRC
#include "dpgroupdlg.hrc"
#endif

#ifndef _TOOLS_RESARY_HXX
#include <tools/resary.hxx>
#endif
#ifndef SC_SCRESID_HXX
#include "scresid.hxx"
#endif
#ifndef SC_SC_HRC
#include "sc.hrc"
#endif

#ifndef _COM_SUN_STAR_SHEET_DATAPILOTFIELDGROUPBY_HPP_
#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
#endif

// ============================================================================

namespace {

/** Date part flags in order of the list box entries. */
static const sal_Int32 spnDateParts[] =
{
    com::sun::star::sheet::DataPilotFieldGroupBy::SECONDS,
    com::sun::star::sheet::DataPilotFieldGroupBy::MINUTES,
    com::sun::star::sheet::DataPilotFieldGroupBy::HOURS,
    com::sun::star::sheet::DataPilotFieldGroupBy::DAYS,
    com::sun::star::sheet::DataPilotFieldGroupBy::MONTHS,
    com::sun::star::sheet::DataPilotFieldGroupBy::QUARTERS,
    com::sun::star::sheet::DataPilotFieldGroupBy::YEARS
};

} // namespace

// ============================================================================

ScDPGroupEditHelper::ScDPGroupEditHelper( RadioButton& rRbAuto, RadioButton& rRbMan, Edit& rEdValue ) :
    mrRbAuto( rRbAuto ),
    mrRbMan( rRbMan ),
    mrEdValue( rEdValue )
{
    mrRbAuto.SetClickHdl( LINK( this, ScDPGroupEditHelper, ClickHdl ) );
    mrRbMan.SetClickHdl( LINK( this, ScDPGroupEditHelper, ClickHdl ) );
}

bool ScDPGroupEditHelper::IsAuto() const
{
    return mrRbAuto.IsChecked();
}

double ScDPGroupEditHelper::GetValue() const
{
    double fValue;
    if( !ImplGetValue( fValue ) )
        fValue = 0.0;
    return fValue;
}

void ScDPGroupEditHelper::SetValue( bool bAuto, double fValue )
{
    if( bAuto )
    {
        mrRbAuto.Check();
        ClickHdl( &mrRbAuto );
    }
    else
    {
        mrRbMan.Check();
        ClickHdl( &mrRbMan );
    }
    ImplSetValue( fValue );
}

IMPL_LINK( ScDPGroupEditHelper, ClickHdl, RadioButton*, pButton )
{
    if( pButton == &mrRbAuto )
    {
        // disable edit field on clicking "automatic" radio button
        mrEdValue.Disable();
    }
    else if( pButton == &mrRbMan )
    {
        // enable and set focus to edit field on clicking "manual" radio button
        mrEdValue.Enable();
        mrEdValue.GrabFocus();
    }
    return 0;
}

// ----------------------------------------------------------------------------

ScDPNumGroupEditHelper::ScDPNumGroupEditHelper(
        RadioButton& rRbAuto, RadioButton& rRbMan, ScDoubleField& rEdValue ) :
    ScDPGroupEditHelper( rRbAuto, rRbMan, rEdValue ),
    mrEdValue( rEdValue )
{
}

bool ScDPNumGroupEditHelper::ImplGetValue( double& rfValue ) const
{
    return mrEdValue.GetValue( rfValue );
}

void ScDPNumGroupEditHelper::ImplSetValue( double fValue )
{
    mrEdValue.SetValue( fValue );
}

// ----------------------------------------------------------------------------

ScDPDateGroupEditHelper::ScDPDateGroupEditHelper(
        RadioButton& rRbAuto, RadioButton& rRbMan, DateField& rEdValue, const Date& rNullDate ) :
    ScDPGroupEditHelper( rRbAuto, rRbMan, rEdValue ),
    mrEdValue( rEdValue ),
    maNullDate( rNullDate )
{
}

bool ScDPDateGroupEditHelper::ImplGetValue( double& rfValue ) const
{
    rfValue = mrEdValue.GetDate() - maNullDate;
    return true;
}

void ScDPDateGroupEditHelper::ImplSetValue( double fValue )
{
    Date aDate( maNullDate );
    aDate += static_cast< sal_Int32 >( fValue );
    mrEdValue.SetDate( aDate );
}

// ============================================================================
// ============================================================================

ScDPNumGroupDlg::ScDPNumGroupDlg( Window* pParent, const ScDPNumGroupInfo& rInfo ) :
    ModalDialog     ( pParent, ScResId( RID_SCDLG_DPNUMGROUP ) ),
    maFlStart       ( this, ScResId( FL_START ) ),
    maRbAutoStart   ( this, ScResId( RB_AUTOSTART ) ),
    maRbManStart    ( this, ScResId( RB_MANSTART ) ),
    maEdStart       ( this, ScResId( ED_START ) ),
    maFlEnd         ( this, ScResId( FL_END ) ),
    maRbAutoEnd     ( this, ScResId( RB_AUTOEND ) ),
    maRbManEnd      ( this, ScResId( RB_MANEND ) ),
    maEdEnd         ( this, ScResId( ED_END ) ),
    maFlBy          ( this, ScResId( FL_BY ) ),
    maEdBy          ( this, ScResId( ED_BY ) ),
    maBtnOk         ( this, ScResId( BTN_OK ) ),
    maBtnCancel     ( this, ScResId( BTN_CANCEL ) ),
    maBtnHelp       ( this, ScResId( BTN_HELP ) ),
    maStartHelper   ( maRbAutoStart, maRbManStart, maEdStart ),
    maEndHelper     ( maRbAutoEnd, maRbManEnd, maEdEnd )
{
    FreeResource();

    maStartHelper.SetValue( rInfo.AutoStart, rInfo.Start );
    maEndHelper.SetValue( rInfo.AutoEnd, rInfo.End );
    maEdBy.SetValue( (rInfo.Step <= 0.0) ? 1.0 : rInfo.Step );

    /*  Set the initial focus, currently it is somewhere after calling all the radio
        button click handlers. Now the first enabled editable control is focused. */
    if( maEdStart.IsEnabled() )
        maEdStart.GrabFocus();
    else if( maEdEnd.IsEnabled() )
        maEdEnd.GrabFocus();
    else
        maEdBy.GrabFocus();
}

ScDPNumGroupInfo ScDPNumGroupDlg::GetGroupInfo() const
{
    ScDPNumGroupInfo aInfo;
    aInfo.Enable = sal_True;
    aInfo.DateValues = sal_False;
    aInfo.AutoStart = maStartHelper.IsAuto();
    aInfo.AutoEnd = maEndHelper.IsAuto();

    // get values and silently auto-correct them, if they are not valid
    // TODO: error messages in OK event?
    aInfo.Start = maStartHelper.GetValue();
    aInfo.End = maEndHelper.GetValue();
    if( !maEdBy.GetValue( aInfo.Step ) || (aInfo.Step <= 0.0) )
        aInfo.Step = 1.0;
    if( aInfo.End <= aInfo.Start )
        aInfo.End = aInfo.Start + aInfo.Step;

    return aInfo;
}

// ============================================================================

ScDPDateGroupDlg::ScDPDateGroupDlg( Window* pParent,
        const ScDPNumGroupInfo& rInfo, sal_Int32 nDatePart, const Date& rNullDate ) :
    ModalDialog     ( pParent, ScResId( RID_SCDLG_DPDATEGROUP ) ),
    maFlStart       ( this, ScResId( FL_START ) ),
    maRbAutoStart   ( this, ScResId( RB_AUTOSTART ) ),
    maRbManStart    ( this, ScResId( RB_MANSTART ) ),
    maEdStart       ( this, ScResId( ED_START ) ),
    maFlEnd         ( this, ScResId( FL_END ) ),
    maRbAutoEnd     ( this, ScResId( RB_AUTOEND ) ),
    maRbManEnd      ( this, ScResId( RB_MANEND ) ),
    maEdEnd         ( this, ScResId( ED_END ) ),
    maFlBy          ( this, ScResId( FL_BY ) ),
    maRbNumDays     ( this, ScResId( RB_NUMDAYS ) ),
    maRbUnits       ( this, ScResId( RB_UNITS ) ),
    maEdNumDays     ( this, ScResId( ED_NUMDAYS ) ),
    maLbUnits       ( this, ScResId( LB_UNITS ) ),
    maBtnOk         ( this, ScResId( BTN_OK ) ),
    maBtnCancel     ( this, ScResId( BTN_CANCEL ) ),
    maBtnHelp       ( this, ScResId( BTN_HELP ) ),
    maStartHelper   ( maRbAutoStart, maRbManStart, maEdStart, rNullDate ),
    maEndHelper     ( maRbAutoEnd, maRbManEnd, maEdEnd, rNullDate )
{
    maLbUnits.SetHelpId( HID_SC_DPDATEGROUP_LB );
    ResStringArray aArr( ScResId( STR_UNITS ) );
    for( USHORT nIdx = 0, nCount = aArr.Count(); nIdx < nCount; ++nIdx )
        maLbUnits.InsertEntry( aArr.GetString( nIdx ) );

    FreeResource();

    maEdStart.SetShowDateCentury( TRUE );
    maEdEnd.SetShowDateCentury( TRUE );

    maStartHelper.SetValue( rInfo.AutoStart, rInfo.Start );
    maEndHelper.SetValue( rInfo.AutoEnd, rInfo.End );

    if( nDatePart == 0 )
        nDatePart = com::sun::star::sheet::DataPilotFieldGroupBy::MONTHS;
    for( ULONG nIdx = 0, nCount = maLbUnits.GetEntryCount(); nIdx < nCount; ++nIdx )
        maLbUnits.CheckEntryPos( static_cast< USHORT >( nIdx ), (nDatePart & spnDateParts[ nIdx ]) != 0 );

    if( rInfo.DateValues )
    {
        maRbNumDays.Check();
        ClickHdl( &maRbNumDays );

        double fNumDays = rInfo.Step;
        if( fNumDays < 1.0 )
            fNumDays = 1.0;
        else if( fNumDays > 32767.0 )
            fNumDays = 32767.0;
        maEdNumDays.SetValue( static_cast< long >( fNumDays ) );
    }
    else
    {
        maRbUnits.Check();
        ClickHdl( &maRbUnits );
    }

    /*  Set the initial focus, currently it is somewhere after calling all the radio
        button click handlers. Now the first enabled editable control is focused. */
    if( maEdStart.IsEnabled() )
        maEdStart.GrabFocus();
    else if( maEdEnd.IsEnabled() )
        maEdEnd.GrabFocus();
    else if( maEdNumDays.IsEnabled() )
        maEdNumDays.GrabFocus();
    else if( maLbUnits.IsEnabled() )
        maLbUnits.GrabFocus();

    maRbNumDays.SetClickHdl( LINK( this, ScDPDateGroupDlg, ClickHdl ) );
    maRbUnits.SetClickHdl( LINK( this, ScDPDateGroupDlg, ClickHdl ) );
    maLbUnits.SetCheckButtonHdl( LINK( this, ScDPDateGroupDlg, CheckHdl ) );
}

ScDPNumGroupInfo ScDPDateGroupDlg::GetGroupInfo() const
{
    ScDPNumGroupInfo aInfo;
    aInfo.Enable = sal_True;
    aInfo.DateValues = maRbNumDays.IsChecked();
    aInfo.AutoStart = maStartHelper.IsAuto();
    aInfo.AutoEnd = maEndHelper.IsAuto();

    // get values and silently auto-correct them, if they are not valid
    // TODO: error messages in OK event?
    aInfo.Start = maStartHelper.GetValue();
    aInfo.End = maEndHelper.GetValue();
    long nNumDays = maEdNumDays.GetValue();
    aInfo.Step = aInfo.DateValues ? nNumDays : 0L;
    if( aInfo.End <= aInfo.Start )
        aInfo.End = aInfo.Start + nNumDays;

    return aInfo;
}

sal_Int32 ScDPDateGroupDlg::GetDatePart() const
{
    // return DAYS for special "number of days" mode
    if( maRbNumDays.IsChecked() )
        return com::sun::star::sheet::DataPilotFieldGroupBy::DAYS;

    // return listbox contents for "units" mode
    sal_Int32 nDatePart = 0;
    for( ULONG nIdx = 0, nCount = maLbUnits.GetEntryCount(); nIdx < nCount; ++nIdx )
        if( maLbUnits.IsChecked( static_cast< USHORT >( nIdx ) ) )
            nDatePart |= spnDateParts[ nIdx ];
    return nDatePart;
}

IMPL_LINK( ScDPDateGroupDlg, ClickHdl, RadioButton*, pButton )
{
    if( pButton == &maRbNumDays )
    {
        maLbUnits.Disable();
        // enable and set focus to edit field on clicking "num of days" radio button
        maEdNumDays.Enable();
        maEdNumDays.GrabFocus();
        maBtnOk.Enable();
    }
    else if( pButton == &maRbUnits )
    {
        maEdNumDays.Disable();
        // enable and set focus to listbox on clicking "units" radio button
        maLbUnits.Enable();
        maLbUnits.GrabFocus();
        // disable OK button if no date part selected
        CheckHdl( &maLbUnits );
    }
    return 0;
}

IMPL_LINK( ScDPDateGroupDlg, CheckHdl, SvxCheckListBox*, pListBox )
{
    // enable/disable OK button on modifying check list box
    if( pListBox == &maLbUnits )
        maBtnOk.Enable( maLbUnits.GetCheckedEntryCount() > 0 );
    return 0;
}

// ============================================================================

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: pntlock.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2007-02-27 13:09:30 $
 *
 *  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
 *
 ************************************************************************/

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

#include "pntlock.hxx"

//------------------------------------------------------------------------

ScPaintLockData::ScPaintLockData(USHORT nNewMode) :
    nMode( nNewMode ),
    nLevel( 0 ),
    nDocLevel( 0 ),
    nParts( 0 ),
    bModified( FALSE )
{
}

ScPaintLockData::~ScPaintLockData()
{
}

void ScPaintLockData::AddRange( const ScRange& rRange, USHORT nP )
{
    if (!xRangeList.Is())
        xRangeList = new ScRangeList;

    xRangeList->Join( rRange );
    nParts |= nP;
}

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

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

#include "pntlock.hxx"

//------------------------------------------------------------------------

ScPaintLockData::ScPaintLockData(USHORT nNewMode) :
    nMode( nNewMode ),
    nLevel( 0 ),
    nDocLevel( 0 ),
    nParts( 0 ),
    bModified( FALSE )
{
}

ScPaintLockData::~ScPaintLockData()
{
}

void ScPaintLockData::AddRange( const ScRange& rRange, USHORT nP )
{
    if (!xRangeList.Is())
        xRangeList = new ScRangeList;

    xRangeList->Join( rRange );
    nParts |= nP;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: drawsh2.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: sab $ $Date: 2002-11-11 13:59:36 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "ui_pch.hxx"
#endif

#pragma hdrstop

//------------------------------------------------------------------

#include "scitems.hxx"
#include <svx/eeitem.hxx>
#include <svx/sizeitem.hxx>
#include <svx/svdpagv.hxx>
#include <svx/xdef.hxx>
#include <sfx2/app.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/viewfrm.hxx>
#include <svtools/ptitem.hxx>
#include <svtools/whiter.hxx>
#include <svx/svdobj.hxx>
#include <svx/svdouno.hxx>

#include "drawsh.hxx"
#include "drawview.hxx"
#include "viewdata.hxx"
#include "sc.hrc"
#include "tabvwsh.hxx"

#ifndef _IPOBJ_HXX
#include <so3/ipobj.hxx>
#endif
#ifndef _SVDOOLE2_HXX
#include <svx/svdoole2.hxx>
#endif

USHORT ScGetFontWorkId();       // in drtxtob

//------------------------------------------------------------------

ScDrawShell::ScDrawShell( ScViewData* pData ) :
    SfxShell(pData->GetViewShell()),
    pViewData( pData )
{
    SetPool( &pViewData->GetScDrawView()->GetModel()->GetItemPool() );
    SetUndoManager( pViewData->GetSfxDocShell()->GetUndoManager() );
    SetHelpId( HID_SCSHELL_DRAWSH );
    SetName(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Drawing")));
}

ScDrawShell::~ScDrawShell()
{
}

void ScDrawShell::GetState( SfxItemSet& rSet )          // Zustaende / Toggles
{
    ScDrawView* pView    = pViewData->GetScDrawView();
    SdrDragMode eMode    = pView->GetDragMode();

    rSet.Put( SfxBoolItem( SID_OBJECT_ROTATE, eMode == SDRDRAG_ROTATE ) );
    rSet.Put( SfxBoolItem( SID_OBJECT_MIRROR, eMode == SDRDRAG_MIRROR ) );
    rSet.Put( SfxBoolItem( SID_BEZIER_EDIT, !pView->IsFrameDragSingles() ) );

    USHORT nFWId = ScGetFontWorkId();
    SfxViewFrame* pViewFrm = pViewData->GetViewShell()->GetViewFrame();
    rSet.Put(SfxBoolItem(SID_FONTWORK, pViewFrm->HasChildWindow(nFWId)));

    switch( pView->GetAnchor() )
    {
        case SCA_PAGE:
        rSet.Put( SfxBoolItem( SID_ANCHOR_PAGE, TRUE ) );
        rSet.Put( SfxBoolItem( SID_ANCHOR_CELL, FALSE ) );
        break;

        case SCA_CELL:
        rSet.Put( SfxBoolItem( SID_ANCHOR_PAGE, FALSE ) );
        rSet.Put( SfxBoolItem( SID_ANCHOR_CELL, TRUE ) );
        break;

        default:
        rSet.Put( SfxBoolItem( SID_ANCHOR_PAGE, FALSE ) );
        rSet.Put( SfxBoolItem( SID_ANCHOR_CELL, FALSE ) );
        break;
    }
}

void ScDrawShell::GetDrawFuncState( SfxItemSet& rSet )      // Funktionen disablen
{
    ScDrawView* pView = pViewData->GetScDrawView();
    const SdrMarkList& rMarkList = pView->GetMarkList();
    ULONG nMarkCount = rMarkList.GetMarkCount();

    if ( nMarkCount <= 1 || !pView->IsGroupPossible() )
        rSet.DisableItem( SID_GROUP );
    if ( nMarkCount == 0 || !pView->IsUnGroupPossible() )
        rSet.DisableItem( SID_UNGROUP );
    if ( nMarkCount != 1 || !pView->IsGroupEnterPossible() )
        rSet.DisableItem( SID_ENTER_GROUP );
    if ( !pView->IsGroupEntered() )
        rSet.DisableItem( SID_LEAVE_GROUP );

    if (!pView->IsMirrorAllowed(TRUE,TRUE))
    {
        rSet.DisableItem( SID_MIRROR_HORIZONTAL );
        rSet.DisableItem( SID_MIRROR_VERTICAL );
    }

    if ( nMarkCount <= 1 )                      // nichts oder nur ein Objekt selektiert
    {
            //  Ausrichtung
        rSet.DisableItem( SID_OBJECT_ALIGN_LEFT );      // keine Ausrichtung an der Seite
        rSet.DisableItem( SID_OBJECT_ALIGN_CENTER );
        rSet.DisableItem( SID_OBJECT_ALIGN_RIGHT );
        rSet.DisableItem( SID_OBJECT_ALIGN_UP );
        rSet.DisableItem( SID_OBJECT_ALIGN_MIDDLE );
        rSet.DisableItem( SID_OBJECT_ALIGN_DOWN );
    }

    if ( !nMarkCount || pView->HasMarkedControl() )
    {
        //  Layer von Controls darf nicht veraendert werden
        rSet.DisableItem( SID_OBJECT_HEAVEN );
        rSet.DisableItem( SID_OBJECT_HELL );
    }
    else
    {
        if(AreAllObjectsOnLayer(SC_LAYER_FRONT,rMarkList))
        {
            rSet.DisableItem( SID_OBJECT_HEAVEN );
        }
        else if(AreAllObjectsOnLayer(SC_LAYER_BACK,rMarkList))
        {
            rSet.DisableItem( SID_OBJECT_HELL );
        }
    }

    BOOL bCanRename = FALSE;
    if ( nMarkCount == 1 )
    {
        UINT16 nObjType = rMarkList.GetMark( 0 )->GetObj()->GetObjIdentifier();
        if ( nObjType == OBJ_OLE2 || nObjType == OBJ_GRAF || nObjType == OBJ_GRUP )
            bCanRename = TRUE;

        // #91929#; don't show original size entry if not possible
        if ( nObjType == OBJ_OLE2 )
        {
            SdrOle2Obj* pOleObj = static_cast<SdrOle2Obj*>(rMarkList.GetMark( 0 )->GetObj());
            if (pOleObj->GetObjRef().Is() && ((pOleObj->GetObjRef()->GetMiscStatus() & SVOBJ_MISCSTATUS_SERVERRESIZE) == SVOBJ_MISCSTATUS_SERVERRESIZE))
                rSet.DisableItem(SID_ORIGINALSIZE);
        }
    }
    if ( !bCanRename )
        rSet.DisableItem( SID_RENAME_OBJECT );

    if ( !nMarkCount )                          // nichts selektiert
    {
            //  Anordnung
        rSet.DisableItem( SID_FRAME_UP );
        rSet.DisableItem( SID_FRAME_DOWN );
        rSet.DisableItem( SID_FRAME_TO_TOP );
        rSet.DisableItem( SID_FRAME_TO_BOTTOM );
            //  Clipboard / loeschen
        rSet.DisableItem( SID_DELETE );
        rSet.DisableItem( SID_DELETE_CONTENTS );
        rSet.DisableItem( SID_CUT );
        rSet.DisableItem( SID_COPY );
            //  sonstiges
        rSet.DisableItem( SID_ANCHOR_TOGGLE );
        rSet.DisableItem( SID_ORIGINALSIZE );
        rSet.DisableItem( SID_ATTR_TRANSFORM );
    }

    if ( rSet.GetItemState( SID_ENABLE_HYPHENATION ) != SFX_ITEM_UNKNOWN )
    {
        SfxItemSet aAttrs( pView->GetModel()->GetItemPool() );
        pView->GetAttributes( aAttrs );
        if( aAttrs.GetItemState( EE_PARA_HYPHENATE ) >= SFX_ITEM_AVAILABLE )
        {
            BOOL bValue = ( (const SfxBoolItem&) aAttrs.Get( EE_PARA_HYPHENATE ) ).GetValue();
            rSet.Put( SfxBoolItem( SID_ENABLE_HYPHENATION, bValue ) );
        }
    }
}

//
//          Attribute fuer Drawing-Objekte
//

void ScDrawShell::GetDrawAttrState( SfxItemSet& rSet )
{
    Point       aMousePos   = pViewData->GetMousePosPixel();
    Window*     pWindow     = pViewData->GetActiveWin();
    ScDrawView* pDrView     = pViewData->GetScDrawView();
    Point       aPos        = pWindow->PixelToLogic(aMousePos);
    BOOL        bHasMarked  = pDrView->HasMarkedObj();

    if( bHasMarked )
    {
        rSet.Put( pDrView->GetAttrFromMarked(FALSE) );

        // Wenn die View selektierte Objekte besitzt, muessen entspr. Items
        // von SFX_ITEM_DEFAULT (_ON) auf SFX_ITEM_DISABLED geaendert werden

        SfxWhichIter aIter( rSet, XATTR_LINE_FIRST, XATTR_FILL_LAST );
        USHORT nWhich = aIter.FirstWhich();
        while( nWhich )
        {
            if( SFX_ITEM_DEFAULT == rSet.GetItemState( nWhich ) )
                rSet.DisableItem( nWhich );

            nWhich = aIter.NextWhich();
        }
    }
    else
        rSet.Put( pDrView->GetDefaultAttr() );

    // Position- und Groesse-Items
    if ( pDrView->IsAction() )
    {
        Rectangle aRect;
        pDrView->TakeActionRect( aRect );

        if ( aRect.IsEmpty() )
            rSet.Put( SfxPointItem(SID_ATTR_POSITION, aPos) );
        else
        {
            pDrView->GetPageViewPvNum(0)->LogicToPagePos(aRect);
            rSet.Put( SfxPointItem( SID_ATTR_POSITION, aRect.TopLeft() ) );
            rSet.Put( SvxSizeItem( SID_ATTR_SIZE,
                    Size( aRect.Right() - aRect.Left(),
                          aRect.Bottom() - aRect.Top() ) ) );
        }
    }
    else
    {
        rSet.Put( SfxPointItem(SID_ATTR_POSITION, aPos) );

        if ( bHasMarked )
        {
            Rectangle aRect = pDrView->GetAllMarkedRect();
            pDrView->GetPageViewPvNum(0)->LogicToPagePos(aRect);
            rSet.Put( SvxSizeItem( SID_ATTR_SIZE,
                                   Size( aRect.Right() - aRect.Left(),
                                         aRect.Bottom() - aRect.Top()) ) );
        }
        else
            rSet.Put( SvxSizeItem( SID_ATTR_SIZE, Size( 0, 0 ) ) );
    }

}

void ScDrawShell::GetAttrFuncState(SfxItemSet &rSet)
{
    //  Dialoge fuer Draw-Attribute disablen, wenn noetig

    ScDrawView* pDrView = pViewData->GetScDrawView();
    SfxItemSet aViewSet = pDrView->GetAttrFromMarked(FALSE);

    if ( aViewSet.GetItemState( XATTR_LINESTYLE ) == SFX_ITEM_DEFAULT )
    {
        rSet.DisableItem( SID_ATTRIBUTES_LINE );
        rSet.DisableItem( SID_ATTR_LINEEND_STYLE );     // Tbx-Controller
    }

    if ( aViewSet.GetItemState( XATTR_FILLSTYLE ) == SFX_ITEM_DEFAULT )
        rSet.DisableItem( SID_ATTRIBUTES_AREA );
}

BOOL ScDrawShell::AreAllObjectsOnLayer(USHORT nLayerNo,const SdrMarkList& rMark)
{
    BOOL bResult=TRUE;
    ULONG nCount = rMark.GetMarkCount();
    for (ULONG i=0; i<nCount; i++)
    {
        SdrObject* pObj = rMark.GetMark(i)->GetObj();
        if ( !pObj->ISA(SdrUnoObj) )
        {
            if(nLayerNo!=pObj->GetLayer())
            {
                bResult=FALSE;
                break;
            }
        }
    }
    return bResult;
}

<commit_msg>INTEGRATION: CWS calc06 (1.7.92); FILE MERGED 2003/03/18 19:12:06 nn 1.7.92.1: #108137# keyboard-compatible state for position/size in status bar<commit_after>/*************************************************************************
 *
 *  $RCSfile: drawsh2.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2003-04-08 16:31:33 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "ui_pch.hxx"
#endif

#pragma hdrstop

//------------------------------------------------------------------

#include "scitems.hxx"
#include <svx/eeitem.hxx>
#include <svx/sizeitem.hxx>
#include <svx/svdpagv.hxx>
#include <svx/xdef.hxx>
#include <sfx2/app.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/viewfrm.hxx>
#include <svtools/ptitem.hxx>
#include <svtools/whiter.hxx>
#include <svx/svdobj.hxx>
#include <svx/svdouno.hxx>

#include "drawsh.hxx"
#include "drawview.hxx"
#include "viewdata.hxx"
#include "sc.hrc"
#include "tabvwsh.hxx"

#ifndef _IPOBJ_HXX
#include <so3/ipobj.hxx>
#endif
#ifndef _SVDOOLE2_HXX
#include <svx/svdoole2.hxx>
#endif

USHORT ScGetFontWorkId();       // in drtxtob

//------------------------------------------------------------------

ScDrawShell::ScDrawShell( ScViewData* pData ) :
    SfxShell(pData->GetViewShell()),
    pViewData( pData )
{
    SetPool( &pViewData->GetScDrawView()->GetModel()->GetItemPool() );
    SetUndoManager( pViewData->GetSfxDocShell()->GetUndoManager() );
    SetHelpId( HID_SCSHELL_DRAWSH );
    SetName(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Drawing")));
}

ScDrawShell::~ScDrawShell()
{
}

void ScDrawShell::GetState( SfxItemSet& rSet )          // Zustaende / Toggles
{
    ScDrawView* pView    = pViewData->GetScDrawView();
    SdrDragMode eMode    = pView->GetDragMode();

    rSet.Put( SfxBoolItem( SID_OBJECT_ROTATE, eMode == SDRDRAG_ROTATE ) );
    rSet.Put( SfxBoolItem( SID_OBJECT_MIRROR, eMode == SDRDRAG_MIRROR ) );
    rSet.Put( SfxBoolItem( SID_BEZIER_EDIT, !pView->IsFrameDragSingles() ) );

    USHORT nFWId = ScGetFontWorkId();
    SfxViewFrame* pViewFrm = pViewData->GetViewShell()->GetViewFrame();
    rSet.Put(SfxBoolItem(SID_FONTWORK, pViewFrm->HasChildWindow(nFWId)));

    switch( pView->GetAnchor() )
    {
        case SCA_PAGE:
        rSet.Put( SfxBoolItem( SID_ANCHOR_PAGE, TRUE ) );
        rSet.Put( SfxBoolItem( SID_ANCHOR_CELL, FALSE ) );
        break;

        case SCA_CELL:
        rSet.Put( SfxBoolItem( SID_ANCHOR_PAGE, FALSE ) );
        rSet.Put( SfxBoolItem( SID_ANCHOR_CELL, TRUE ) );
        break;

        default:
        rSet.Put( SfxBoolItem( SID_ANCHOR_PAGE, FALSE ) );
        rSet.Put( SfxBoolItem( SID_ANCHOR_CELL, FALSE ) );
        break;
    }
}

void ScDrawShell::GetDrawFuncState( SfxItemSet& rSet )      // Funktionen disablen
{
    ScDrawView* pView = pViewData->GetScDrawView();
    const SdrMarkList& rMarkList = pView->GetMarkList();
    ULONG nMarkCount = rMarkList.GetMarkCount();

    if ( nMarkCount <= 1 || !pView->IsGroupPossible() )
        rSet.DisableItem( SID_GROUP );
    if ( nMarkCount == 0 || !pView->IsUnGroupPossible() )
        rSet.DisableItem( SID_UNGROUP );
    if ( nMarkCount != 1 || !pView->IsGroupEnterPossible() )
        rSet.DisableItem( SID_ENTER_GROUP );
    if ( !pView->IsGroupEntered() )
        rSet.DisableItem( SID_LEAVE_GROUP );

    if (!pView->IsMirrorAllowed(TRUE,TRUE))
    {
        rSet.DisableItem( SID_MIRROR_HORIZONTAL );
        rSet.DisableItem( SID_MIRROR_VERTICAL );
    }

    if ( nMarkCount <= 1 )                      // nichts oder nur ein Objekt selektiert
    {
            //  Ausrichtung
        rSet.DisableItem( SID_OBJECT_ALIGN_LEFT );      // keine Ausrichtung an der Seite
        rSet.DisableItem( SID_OBJECT_ALIGN_CENTER );
        rSet.DisableItem( SID_OBJECT_ALIGN_RIGHT );
        rSet.DisableItem( SID_OBJECT_ALIGN_UP );
        rSet.DisableItem( SID_OBJECT_ALIGN_MIDDLE );
        rSet.DisableItem( SID_OBJECT_ALIGN_DOWN );
    }

    if ( !nMarkCount || pView->HasMarkedControl() )
    {
        //  Layer von Controls darf nicht veraendert werden
        rSet.DisableItem( SID_OBJECT_HEAVEN );
        rSet.DisableItem( SID_OBJECT_HELL );
    }
    else
    {
        if(AreAllObjectsOnLayer(SC_LAYER_FRONT,rMarkList))
        {
            rSet.DisableItem( SID_OBJECT_HEAVEN );
        }
        else if(AreAllObjectsOnLayer(SC_LAYER_BACK,rMarkList))
        {
            rSet.DisableItem( SID_OBJECT_HELL );
        }
    }

    BOOL bCanRename = FALSE;
    if ( nMarkCount == 1 )
    {
        UINT16 nObjType = rMarkList.GetMark( 0 )->GetObj()->GetObjIdentifier();
        if ( nObjType == OBJ_OLE2 || nObjType == OBJ_GRAF || nObjType == OBJ_GRUP )
            bCanRename = TRUE;

        // #91929#; don't show original size entry if not possible
        if ( nObjType == OBJ_OLE2 )
        {
            SdrOle2Obj* pOleObj = static_cast<SdrOle2Obj*>(rMarkList.GetMark( 0 )->GetObj());
            if (pOleObj->GetObjRef().Is() && ((pOleObj->GetObjRef()->GetMiscStatus() & SVOBJ_MISCSTATUS_SERVERRESIZE) == SVOBJ_MISCSTATUS_SERVERRESIZE))
                rSet.DisableItem(SID_ORIGINALSIZE);
        }
    }
    if ( !bCanRename )
        rSet.DisableItem( SID_RENAME_OBJECT );

    if ( !nMarkCount )                          // nichts selektiert
    {
            //  Anordnung
        rSet.DisableItem( SID_FRAME_UP );
        rSet.DisableItem( SID_FRAME_DOWN );
        rSet.DisableItem( SID_FRAME_TO_TOP );
        rSet.DisableItem( SID_FRAME_TO_BOTTOM );
            //  Clipboard / loeschen
        rSet.DisableItem( SID_DELETE );
        rSet.DisableItem( SID_DELETE_CONTENTS );
        rSet.DisableItem( SID_CUT );
        rSet.DisableItem( SID_COPY );
            //  sonstiges
        rSet.DisableItem( SID_ANCHOR_TOGGLE );
        rSet.DisableItem( SID_ORIGINALSIZE );
        rSet.DisableItem( SID_ATTR_TRANSFORM );
    }

    if ( rSet.GetItemState( SID_ENABLE_HYPHENATION ) != SFX_ITEM_UNKNOWN )
    {
        SfxItemSet aAttrs( pView->GetModel()->GetItemPool() );
        pView->GetAttributes( aAttrs );
        if( aAttrs.GetItemState( EE_PARA_HYPHENATE ) >= SFX_ITEM_AVAILABLE )
        {
            BOOL bValue = ( (const SfxBoolItem&) aAttrs.Get( EE_PARA_HYPHENATE ) ).GetValue();
            rSet.Put( SfxBoolItem( SID_ENABLE_HYPHENATION, bValue ) );
        }
    }
}

//
//          Attribute fuer Drawing-Objekte
//

void ScDrawShell::GetDrawAttrState( SfxItemSet& rSet )
{
    Point       aMousePos   = pViewData->GetMousePosPixel();
    Window*     pWindow     = pViewData->GetActiveWin();
    ScDrawView* pDrView     = pViewData->GetScDrawView();
    Point       aPos        = pWindow->PixelToLogic(aMousePos);
    BOOL        bHasMarked  = pDrView->HasMarkedObj();

    if( bHasMarked )
    {
        rSet.Put( pDrView->GetAttrFromMarked(FALSE) );

        // Wenn die View selektierte Objekte besitzt, muessen entspr. Items
        // von SFX_ITEM_DEFAULT (_ON) auf SFX_ITEM_DISABLED geaendert werden

        SfxWhichIter aIter( rSet, XATTR_LINE_FIRST, XATTR_FILL_LAST );
        USHORT nWhich = aIter.FirstWhich();
        while( nWhich )
        {
            if( SFX_ITEM_DEFAULT == rSet.GetItemState( nWhich ) )
                rSet.DisableItem( nWhich );

            nWhich = aIter.NextWhich();
        }
    }
    else
        rSet.Put( pDrView->GetDefaultAttr() );

    //  Items for position and size (see ScGridWindow::UpdateStatusPosSize, #108137#)

    //  SvxPosSizeStatusBarControl needs a SvxSizeItem also in SID_TABLE_CELL (in conflict
    //  with the sdi definition), because an invalid item state or unknown item type would
    //  enable date/time display, and a SfxStringItem would show the text!

    BOOL bActionItem = FALSE;
    if ( pDrView->IsAction() )              // action rectangle
    {
        Rectangle aRect;
        pDrView->TakeActionRect( aRect );
        if ( !aRect.IsEmpty() )
        {
            pDrView->GetPageViewPvNum(0)->LogicToPagePos(aRect);
            rSet.Put( SfxPointItem( SID_ATTR_POSITION, aRect.TopLeft() ) );
            Size aSize( aRect.Right() - aRect.Left(), aRect.Bottom() - aRect.Top() );
            rSet.Put( SvxSizeItem( SID_ATTR_SIZE, aSize ) );
            rSet.Put( SvxSizeItem( SID_TABLE_CELL, aSize ) );
            bActionItem = TRUE;
        }
    }
    if ( !bActionItem )
    {
        if ( pDrView->HasMarkedObj() )      // selected objects
        {
            Rectangle aRect = pDrView->GetAllMarkedRect();
            pDrView->GetPageViewPvNum(0)->LogicToPagePos(aRect);
            rSet.Put( SfxPointItem( SID_ATTR_POSITION, aRect.TopLeft() ) );
            Size aSize( aRect.Right() - aRect.Left(), aRect.Bottom() - aRect.Top() );
            rSet.Put( SvxSizeItem( SID_ATTR_SIZE, aSize ) );
            rSet.Put( SvxSizeItem( SID_TABLE_CELL, aSize ) );
        }
        else                                // mouse position
        {
            // aPos is initialized above
            pDrView->GetPageViewPvNum(0)->LogicToPagePos(aPos);
            rSet.Put( SfxPointItem( SID_ATTR_POSITION, aPos ) );
            rSet.Put( SvxSizeItem( SID_ATTR_SIZE, Size( 0, 0 ) ) );
            rSet.Put( SvxSizeItem( SID_TABLE_CELL, Size( 0, 0 ) ) );
        }
    }
}

void ScDrawShell::GetAttrFuncState(SfxItemSet &rSet)
{
    //  Dialoge fuer Draw-Attribute disablen, wenn noetig

    ScDrawView* pDrView = pViewData->GetScDrawView();
    SfxItemSet aViewSet = pDrView->GetAttrFromMarked(FALSE);

    if ( aViewSet.GetItemState( XATTR_LINESTYLE ) == SFX_ITEM_DEFAULT )
    {
        rSet.DisableItem( SID_ATTRIBUTES_LINE );
        rSet.DisableItem( SID_ATTR_LINEEND_STYLE );     // Tbx-Controller
    }

    if ( aViewSet.GetItemState( XATTR_FILLSTYLE ) == SFX_ITEM_DEFAULT )
        rSet.DisableItem( SID_ATTRIBUTES_AREA );
}

BOOL ScDrawShell::AreAllObjectsOnLayer(USHORT nLayerNo,const SdrMarkList& rMark)
{
    BOOL bResult=TRUE;
    ULONG nCount = rMark.GetMarkCount();
    for (ULONG i=0; i<nCount; i++)
    {
        SdrObject* pObj = rMark.GetMark(i)->GetObj();
        if ( !pObj->ISA(SdrUnoObj) )
        {
            if(nLayerNo!=pObj->GetLayer())
            {
                bResult=FALSE;
                break;
            }
        }
    }
    return bResult;
}

<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <boost/range/adaptors.hpp>

#include "GlobalContext.hpp"
#include "FunctionContext.hpp"
#include "Type.hpp"
#include "Variable.hpp"

#include "ltac/prologue.hpp"
#include "ltac/Utils.hpp"
#include "ltac/Printer.hpp"

using namespace eddic;

namespace {

std::set<ltac::Register> parameter_registers(std::shared_ptr<eddic::Function> function, Platform platform, std::shared_ptr<Configuration> configuration){
    std::set<ltac::Register> overriden_registers;

    auto descriptor = getPlatformDescriptor(platform);

    if(function->standard || configuration->option_defined("fparameter-allocation")){
        unsigned int maxInt = descriptor->numberOfIntParamRegisters();

        for(auto& parameter : function->parameters){
            auto type = function->getParameterType(parameter.name);
            unsigned int position = function->getParameterPositionByType(parameter.name);

            if(mtac::is_single_int_register(type) && position <= maxInt){
                overriden_registers.insert(ltac::Register(descriptor->int_param_register(position)));
            }
        }
    }

    return overriden_registers;
}

std::set<ltac::FloatRegister> float_parameter_registers(std::shared_ptr<eddic::Function> function, Platform platform, std::shared_ptr<Configuration> configuration){
    std::set<ltac::FloatRegister> overriden_float_registers;

    auto descriptor = getPlatformDescriptor(platform);

    if(function->standard || configuration->option_defined("fparameter-allocation")){
        unsigned int maxFloat = descriptor->numberOfFloatParamRegisters();

        for(auto& parameter : function->parameters){
            auto type = function->getParameterType(parameter.name);
            unsigned int position = function->getParameterPositionByType(parameter.name);

            if(mtac::is_single_float_register(type) && position <= maxFloat){
                overriden_float_registers.insert(ltac::FloatRegister(descriptor->float_param_register(position)));
            }
        }
    }

    return overriden_float_registers;
}

bool callee_save(std::shared_ptr<eddic::Function> definition, ltac::Register reg, Platform platform, std::shared_ptr<Configuration> configuration){
    auto return_type = definition->returnType;
    auto descriptor = getPlatformDescriptor(platform);

    //Do not save the return registers
    if((return_type == INT || return_type == BOOL || return_type == CHAR) && reg.reg == descriptor->int_return_register1()){
        return false;
    } else if(return_type == STRING && (reg.reg == descriptor->int_return_register1() || reg.reg == descriptor->int_return_register2())){
        return false;
    } else if(return_type->is_pointer() && reg.reg == descriptor->int_return_register1()){
        return false;
    }

    auto parameters = parameter_registers(definition, platform, configuration);

    //Do not save the parameters registers, they are saved by the caller if necessary
    if(parameters.count(reg)){
        return false;
    }

    return true;
}

bool callee_save(std::shared_ptr<eddic::Function> definition, ltac::FloatRegister reg, Platform platform, std::shared_ptr<Configuration> configuration){
    auto return_type = definition->returnType;
    auto descriptor = getPlatformDescriptor(platform);

    //Do not save the return register
    if(return_type == FLOAT && reg.reg == descriptor->float_return_register()){
        return false;
    }

    auto parameters = float_parameter_registers(definition, platform, configuration);

    //Do not save the parameters registers, they are saved by the caller if necessary
    if(parameters.count(reg)){
        return false;
    }

    return true;
}

void callee_save_registers(mtac::function_p function, mtac::basic_block_p bb, Platform platform, std::shared_ptr<Configuration> configuration){
    //Save registers for all other functions than main
    if(!function->is_main()){
        for(auto& reg : function->use_registers()){
            if(callee_save(function->definition, reg, platform, configuration)){
                ltac::add_instruction(bb, ltac::Operator::PUSH, reg);
            }
        }

        for(auto& float_reg : function->use_float_registers()){
            if(callee_save(function->definition, float_reg, platform, configuration)){
                ltac::add_instruction(bb, ltac::Operator::SUB, ltac::SP, static_cast<int>(FLOAT->size(platform)));
                ltac::add_instruction(bb, ltac::Operator::FMOV, ltac::Address(ltac::SP, 0), float_reg);
            }
        }
    }
}

void callee_restore_registers(mtac::function_p function, mtac::basic_block_p bb, Platform platform, std::shared_ptr<Configuration> configuration){
    //Save registers for all other functions than main
    if(!function->is_main()){
        for(auto& float_reg : boost::adaptors::reverse(function->use_float_registers())){
            if(callee_save(function->definition, float_reg, platform, configuration)){
                ltac::add_instruction(bb, ltac::Operator::FMOV, float_reg, ltac::Address(ltac::SP, 0));
                ltac::add_instruction(bb, ltac::Operator::ADD, ltac::SP, static_cast<int>(FLOAT->size(platform)));
            }
        }

        for(auto& reg : boost::adaptors::reverse(function->use_registers())){
            if(callee_save(function->definition, reg, platform, configuration)){
                ltac::add_instruction(bb, ltac::Operator::POP, reg);
            }
        }
    }
}

template<typename It>
void callee_restore_registers(mtac::function_p function, It& it, Platform platform, std::shared_ptr<Configuration> configuration){
    //Save registers for all other functions than main
    if(!function->is_main()){
        for(auto& reg : function->use_registers()){
            if(callee_save(function->definition, reg, platform, configuration)){
                it.insert(std::make_shared<ltac::Instruction>(ltac::Operator::POP, reg));
            }
        }

        for(auto& float_reg : function->use_float_registers()){
            if(callee_save(function->definition, float_reg, platform, configuration)){
                it.insert(std::make_shared<ltac::Instruction>(ltac::Operator::ADD, ltac::SP, static_cast<int>(FLOAT->size(platform))));
                it.insert(std::make_shared<ltac::Instruction>(ltac::Operator::FMOV, float_reg, ltac::Address(ltac::SP, 0)));
            }
        }
    }
}

template<typename T>
bool contains(const std::set<T>& set, const T& value){
    return set.find(value) != set.end();
}

template<typename T>
bool contains(const std::unordered_set<T>& set, const T& value){
    return set.find(value) != set.end();
}

bool caller_save(mtac::function_p source, std::shared_ptr<eddic::Function> target_definition, ltac::Register reg, Platform platform, std::shared_ptr<Configuration> configuration){
    auto source_parameters = parameter_registers(source->definition, platform, configuration);
    auto target_parameters = parameter_registers(target_definition, platform, configuration);
    auto variable_registers = source->variable_registers();

    //Only saved is used to hold a variable (not bound) or as a parameter in the source function
    if(contains(target_parameters, reg) && (contains(variable_registers, reg) || contains(source_parameters, reg))){
        return true;
    }

    return false;
}

bool caller_save(mtac::function_p source, std::shared_ptr<eddic::Function> target_definition, ltac::FloatRegister reg, Platform platform, std::shared_ptr<Configuration> configuration){
    auto source_parameters = float_parameter_registers(source->definition, platform, configuration);
    auto target_parameters = float_parameter_registers(target_definition, platform, configuration);
    auto variable_registers = source->variable_float_registers();

    //Only saved is used to hold a variable (not bound) or as a parameter in the source function
    if(contains(target_parameters, reg) && (contains(variable_registers, reg) || contains(source_parameters, reg))){
        return true;
    }

    return false;
}

template<typename It>
void caller_save_registers(mtac::function_p function, std::shared_ptr<eddic::Function> target_function, mtac::basic_block_p bb, It it, Platform platform, std::shared_ptr<Configuration> configuration){
    auto pre_it = it.it;

    auto call = boost::get<std::shared_ptr<ltac::Jump>>(*it);

    while(true){
        while(pre_it != bb->l_statements.begin()){
            --pre_it;

            auto statement = *pre_it;

            if(auto* ptr = boost::get<std::shared_ptr<ltac::Instruction>>(&statement)){
                if((*ptr)->op == ltac::Operator::PRE_PARAM){
                    (*ptr)->op = ltac::Operator::NOP;

                    for(auto& float_reg : boost::adaptors::reverse(function->use_float_registers())){
                        if(caller_save(function, target_function, float_reg, platform, configuration)){
                            pre_it = bb->l_statements.insert(pre_it, std::make_shared<ltac::Instruction>(ltac::Operator::FMOV, ltac::Address(ltac::SP, 0), float_reg));
                            pre_it = bb->l_statements.insert(pre_it, std::make_shared<ltac::Instruction>(ltac::Operator::SUB, ltac::SP, static_cast<int>(FLOAT->size(platform))));
                        }
                    }

                    for(auto& reg : boost::adaptors::reverse(function->use_registers())){
                        if(caller_save(function, target_function, reg, platform, configuration)){
                            pre_it = bb->l_statements.insert(pre_it, std::make_shared<ltac::Instruction>(ltac::Operator::PUSH, reg));
                        }
                    }

                    return;
                }
            }
        }

        bb = bb->prev;
        pre_it = bb->l_statements.end();
    }
}

template<typename It, typename Type>
void find(It& it, const Type& value){
    while(true){
        if(auto* ptr = boost::get<Type>(&*it)){
            if(*ptr == value){
                return;
            }
        }

        ++it;
    }
}

template<typename It>
void caller_cleanup(mtac::function_p function, std::shared_ptr<eddic::Function> target_function, mtac::basic_block_p bb, It it, Platform platform, std::shared_ptr<Configuration> configuration){
    auto call = boost::get<std::shared_ptr<ltac::Jump>>(*it);

    caller_save_registers(function, target_function, bb, it, platform, configuration);

    //The iterator has been invalidated by the save, find the call again
    it.restart();
    find(it, call);

    if(it.has_next()){
        ++it;

        bool rewind = true;

        if(auto* ptr = boost::get<std::shared_ptr<ltac::Instruction>>(&*it)){
            if((*ptr)->op == ltac::Operator::ADD){
                if(auto* reg_ptr = boost::get<ltac::Register>(&*(*ptr)->arg1)){
                    if(*reg_ptr == ltac::SP){
                       rewind = false;
                    }
                }
            }
        }

        if(rewind){
            --it;
        }
    }

    for(auto& float_reg : boost::adaptors::reverse(function->use_float_registers())){
        if(caller_save(function, target_function, float_reg, platform, configuration)){
            it.insert_after(std::make_shared<ltac::Instruction>(ltac::Operator::FMOV, float_reg, ltac::Address(ltac::SP, 0)));
            it.insert_after(std::make_shared<ltac::Instruction>(ltac::Operator::ADD, ltac::SP, static_cast<int>(FLOAT->size(platform))));
        }
    }

    for(auto& reg : boost::adaptors::reverse(function->use_registers())){
        if(caller_save(function, target_function, reg, platform, configuration)){
            it.insert_after(std::make_shared<ltac::Instruction>(ltac::Operator::POP, reg));
        }
    }
}

} //End of anonymous

void ltac::generate_prologue_epilogue(mtac::program_p ltac_program, std::shared_ptr<Configuration> configuration){
    bool omit_fp = configuration->option_defined("fomit-frame-pointer");
    auto platform = ltac_program->context->target_platform();

    for(auto& function : ltac_program->functions){
        auto size = function->context->size();

        //1. Generate prologue

        auto bb = function->entry_bb();

        //Enter stack frame
        if(!omit_fp){
            ltac::add_instruction(bb, ltac::Operator::ENTER);
        }

        //Allocate stack space for locals
        ltac::add_instruction(bb, ltac::Operator::SUB, ltac::SP, size);

        auto iter = function->context->begin();
        auto end = function->context->end();

        //Clear stack variables
        for(; iter != end; iter++){
            auto var = iter->second;

            //Only stack variables needs to be cleared
            if(var->position().isStack()){
                auto type = var->type();
                int position = var->position().offset();

                auto int_size = INT->size(platform);

                if(type->is_array() && type->has_elements()){
                    ltac::add_instruction(bb, ltac::Operator::MOV, ltac::Address(ltac::BP, position), static_cast<int>(type->elements()));
                    ltac::add_instruction(bb, ltac::Operator::MEMSET, ltac::Address(ltac::BP, position + int_size),
                            static_cast<int>((type->data_type()->size(platform) / int_size * type->elements())));
                } else if(type->is_custom_type()){
                    ltac::add_instruction(bb, ltac::Operator::MEMSET, ltac::Address(ltac::BP, position), static_cast<int>(type->size(platform) / int_size));
                }
            }
        }

        callee_save_registers(function, bb, platform, configuration);

        //2. Generate epilogue

        bb = function->exit_bb();

        callee_restore_registers(function, bb, platform, configuration);

        ltac::add_instruction(bb, ltac::Operator::ADD, ltac::SP, size);

        //Leave stack frame
        if(!omit_fp){
            ltac::add_instruction(bb, ltac::Operator::LEAVE);
        }

        ltac::add_instruction(bb, ltac::Operator::RET);

        //3. Generate epilogue for each unresolved RET

        for(auto& bb : function){
            auto it = iterate(bb->l_statements);

            while(it.has_next()){
                auto statement = *it;

                if(auto* ptr = boost::get<std::shared_ptr<ltac::Instruction>>(&statement)){
                    if((*ptr)->op == ltac::Operator::PRE_RET){
                        (*ptr)->op = ltac::Operator::RET;

                        //Leave stack frame
                        if(!omit_fp){
                            it.insert(std::make_shared<ltac::Instruction>(ltac::Operator::LEAVE));
                        }

                        it.insert(std::make_shared<ltac::Instruction>(ltac::Operator::ADD, ltac::SP, size));

                        callee_restore_registers(function, it, platform, configuration);
                    }
                }

                ++it;
            }
        }

        //4. Generate caller save/restore code

        for(auto& bb : function){
            auto it = iterate(bb->l_statements);

            while(it.has_next()){
                auto statement = *it;

                if(auto* ptr = boost::get<std::shared_ptr<ltac::Jump>>(&statement)){
                    if((*ptr)->type == ltac::JumpType::CALL){
                        caller_cleanup(function, (*ptr)->target_function, bb, it, platform, configuration);

                        //The iterator is invalidated by the cleanup, necessary to find the call again
                        it.restart();
                        find(it, *ptr);
                    }
                }

                ++it;
            }
        }
    }
}
<commit_msg>Init the size of arrays inside structures<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011-2012.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <boost/range/adaptors.hpp>

#include "GlobalContext.hpp"
#include "FunctionContext.hpp"
#include "Type.hpp"
#include "Variable.hpp"

#include "ltac/prologue.hpp"
#include "ltac/Utils.hpp"
#include "ltac/Printer.hpp"

using namespace eddic;

namespace {

std::set<ltac::Register> parameter_registers(std::shared_ptr<eddic::Function> function, Platform platform, std::shared_ptr<Configuration> configuration){
    std::set<ltac::Register> overriden_registers;

    auto descriptor = getPlatformDescriptor(platform);

    if(function->standard || configuration->option_defined("fparameter-allocation")){
        unsigned int maxInt = descriptor->numberOfIntParamRegisters();

        for(auto& parameter : function->parameters){
            auto type = function->getParameterType(parameter.name);
            unsigned int position = function->getParameterPositionByType(parameter.name);

            if(mtac::is_single_int_register(type) && position <= maxInt){
                overriden_registers.insert(ltac::Register(descriptor->int_param_register(position)));
            }
        }
    }

    return overriden_registers;
}

std::set<ltac::FloatRegister> float_parameter_registers(std::shared_ptr<eddic::Function> function, Platform platform, std::shared_ptr<Configuration> configuration){
    std::set<ltac::FloatRegister> overriden_float_registers;

    auto descriptor = getPlatformDescriptor(platform);

    if(function->standard || configuration->option_defined("fparameter-allocation")){
        unsigned int maxFloat = descriptor->numberOfFloatParamRegisters();

        for(auto& parameter : function->parameters){
            auto type = function->getParameterType(parameter.name);
            unsigned int position = function->getParameterPositionByType(parameter.name);

            if(mtac::is_single_float_register(type) && position <= maxFloat){
                overriden_float_registers.insert(ltac::FloatRegister(descriptor->float_param_register(position)));
            }
        }
    }

    return overriden_float_registers;
}

bool callee_save(std::shared_ptr<eddic::Function> definition, ltac::Register reg, Platform platform, std::shared_ptr<Configuration> configuration){
    auto return_type = definition->returnType;
    auto descriptor = getPlatformDescriptor(platform);

    //Do not save the return registers
    if((return_type == INT || return_type == BOOL || return_type == CHAR) && reg.reg == descriptor->int_return_register1()){
        return false;
    } else if(return_type == STRING && (reg.reg == descriptor->int_return_register1() || reg.reg == descriptor->int_return_register2())){
        return false;
    } else if(return_type->is_pointer() && reg.reg == descriptor->int_return_register1()){
        return false;
    }

    auto parameters = parameter_registers(definition, platform, configuration);

    //Do not save the parameters registers, they are saved by the caller if necessary
    if(parameters.count(reg)){
        return false;
    }

    return true;
}

bool callee_save(std::shared_ptr<eddic::Function> definition, ltac::FloatRegister reg, Platform platform, std::shared_ptr<Configuration> configuration){
    auto return_type = definition->returnType;
    auto descriptor = getPlatformDescriptor(platform);

    //Do not save the return register
    if(return_type == FLOAT && reg.reg == descriptor->float_return_register()){
        return false;
    }

    auto parameters = float_parameter_registers(definition, platform, configuration);

    //Do not save the parameters registers, they are saved by the caller if necessary
    if(parameters.count(reg)){
        return false;
    }

    return true;
}

void callee_save_registers(mtac::function_p function, mtac::basic_block_p bb, Platform platform, std::shared_ptr<Configuration> configuration){
    //Save registers for all other functions than main
    if(!function->is_main()){
        for(auto& reg : function->use_registers()){
            if(callee_save(function->definition, reg, platform, configuration)){
                ltac::add_instruction(bb, ltac::Operator::PUSH, reg);
            }
        }

        for(auto& float_reg : function->use_float_registers()){
            if(callee_save(function->definition, float_reg, platform, configuration)){
                ltac::add_instruction(bb, ltac::Operator::SUB, ltac::SP, static_cast<int>(FLOAT->size(platform)));
                ltac::add_instruction(bb, ltac::Operator::FMOV, ltac::Address(ltac::SP, 0), float_reg);
            }
        }
    }
}

void callee_restore_registers(mtac::function_p function, mtac::basic_block_p bb, Platform platform, std::shared_ptr<Configuration> configuration){
    //Save registers for all other functions than main
    if(!function->is_main()){
        for(auto& float_reg : boost::adaptors::reverse(function->use_float_registers())){
            if(callee_save(function->definition, float_reg, platform, configuration)){
                ltac::add_instruction(bb, ltac::Operator::FMOV, float_reg, ltac::Address(ltac::SP, 0));
                ltac::add_instruction(bb, ltac::Operator::ADD, ltac::SP, static_cast<int>(FLOAT->size(platform)));
            }
        }

        for(auto& reg : boost::adaptors::reverse(function->use_registers())){
            if(callee_save(function->definition, reg, platform, configuration)){
                ltac::add_instruction(bb, ltac::Operator::POP, reg);
            }
        }
    }
}

template<typename It>
void callee_restore_registers(mtac::function_p function, It& it, Platform platform, std::shared_ptr<Configuration> configuration){
    //Save registers for all other functions than main
    if(!function->is_main()){
        for(auto& reg : function->use_registers()){
            if(callee_save(function->definition, reg, platform, configuration)){
                it.insert(std::make_shared<ltac::Instruction>(ltac::Operator::POP, reg));
            }
        }

        for(auto& float_reg : function->use_float_registers()){
            if(callee_save(function->definition, float_reg, platform, configuration)){
                it.insert(std::make_shared<ltac::Instruction>(ltac::Operator::ADD, ltac::SP, static_cast<int>(FLOAT->size(platform))));
                it.insert(std::make_shared<ltac::Instruction>(ltac::Operator::FMOV, float_reg, ltac::Address(ltac::SP, 0)));
            }
        }
    }
}

template<typename T>
bool contains(const std::set<T>& set, const T& value){
    return set.find(value) != set.end();
}

template<typename T>
bool contains(const std::unordered_set<T>& set, const T& value){
    return set.find(value) != set.end();
}

bool caller_save(mtac::function_p source, std::shared_ptr<eddic::Function> target_definition, ltac::Register reg, Platform platform, std::shared_ptr<Configuration> configuration){
    auto source_parameters = parameter_registers(source->definition, platform, configuration);
    auto target_parameters = parameter_registers(target_definition, platform, configuration);
    auto variable_registers = source->variable_registers();

    //Only saved is used to hold a variable (not bound) or as a parameter in the source function
    if(contains(target_parameters, reg) && (contains(variable_registers, reg) || contains(source_parameters, reg))){
        return true;
    }

    return false;
}

bool caller_save(mtac::function_p source, std::shared_ptr<eddic::Function> target_definition, ltac::FloatRegister reg, Platform platform, std::shared_ptr<Configuration> configuration){
    auto source_parameters = float_parameter_registers(source->definition, platform, configuration);
    auto target_parameters = float_parameter_registers(target_definition, platform, configuration);
    auto variable_registers = source->variable_float_registers();

    //Only saved is used to hold a variable (not bound) or as a parameter in the source function
    if(contains(target_parameters, reg) && (contains(variable_registers, reg) || contains(source_parameters, reg))){
        return true;
    }

    return false;
}

template<typename It>
void caller_save_registers(mtac::function_p function, std::shared_ptr<eddic::Function> target_function, mtac::basic_block_p bb, It it, Platform platform, std::shared_ptr<Configuration> configuration){
    auto pre_it = it.it;

    auto call = boost::get<std::shared_ptr<ltac::Jump>>(*it);

    while(true){
        while(pre_it != bb->l_statements.begin()){
            --pre_it;

            auto statement = *pre_it;

            if(auto* ptr = boost::get<std::shared_ptr<ltac::Instruction>>(&statement)){
                if((*ptr)->op == ltac::Operator::PRE_PARAM){
                    (*ptr)->op = ltac::Operator::NOP;

                    for(auto& float_reg : boost::adaptors::reverse(function->use_float_registers())){
                        if(caller_save(function, target_function, float_reg, platform, configuration)){
                            pre_it = bb->l_statements.insert(pre_it, std::make_shared<ltac::Instruction>(ltac::Operator::FMOV, ltac::Address(ltac::SP, 0), float_reg));
                            pre_it = bb->l_statements.insert(pre_it, std::make_shared<ltac::Instruction>(ltac::Operator::SUB, ltac::SP, static_cast<int>(FLOAT->size(platform))));
                        }
                    }

                    for(auto& reg : boost::adaptors::reverse(function->use_registers())){
                        if(caller_save(function, target_function, reg, platform, configuration)){
                            pre_it = bb->l_statements.insert(pre_it, std::make_shared<ltac::Instruction>(ltac::Operator::PUSH, reg));
                        }
                    }

                    return;
                }
            }
        }

        bb = bb->prev;
        pre_it = bb->l_statements.end();
    }
}

template<typename It, typename Type>
void find(It& it, const Type& value){
    while(true){
        if(auto* ptr = boost::get<Type>(&*it)){
            if(*ptr == value){
                return;
            }
        }

        ++it;
    }
}

template<typename It>
void caller_cleanup(mtac::function_p function, std::shared_ptr<eddic::Function> target_function, mtac::basic_block_p bb, It it, Platform platform, std::shared_ptr<Configuration> configuration){
    auto call = boost::get<std::shared_ptr<ltac::Jump>>(*it);

    caller_save_registers(function, target_function, bb, it, platform, configuration);

    //The iterator has been invalidated by the save, find the call again
    it.restart();
    find(it, call);

    if(it.has_next()){
        ++it;

        bool rewind = true;

        if(auto* ptr = boost::get<std::shared_ptr<ltac::Instruction>>(&*it)){
            if((*ptr)->op == ltac::Operator::ADD){
                if(auto* reg_ptr = boost::get<ltac::Register>(&*(*ptr)->arg1)){
                    if(*reg_ptr == ltac::SP){
                       rewind = false;
                    }
                }
            }
        }

        if(rewind){
            --it;
        }
    }

    for(auto& float_reg : boost::adaptors::reverse(function->use_float_registers())){
        if(caller_save(function, target_function, float_reg, platform, configuration)){
            it.insert_after(std::make_shared<ltac::Instruction>(ltac::Operator::FMOV, float_reg, ltac::Address(ltac::SP, 0)));
            it.insert_after(std::make_shared<ltac::Instruction>(ltac::Operator::ADD, ltac::SP, static_cast<int>(FLOAT->size(platform))));
        }
    }

    for(auto& reg : boost::adaptors::reverse(function->use_registers())){
        if(caller_save(function, target_function, reg, platform, configuration)){
            it.insert_after(std::make_shared<ltac::Instruction>(ltac::Operator::POP, reg));
        }
    }
}

} //End of anonymous

void ltac::generate_prologue_epilogue(mtac::program_p ltac_program, std::shared_ptr<Configuration> configuration){
    bool omit_fp = configuration->option_defined("fomit-frame-pointer");
    auto platform = ltac_program->context->target_platform();

    for(auto& function : ltac_program->functions){
        auto size = function->context->size();

        //1. Generate prologue

        auto bb = function->entry_bb();

        //Enter stack frame
        if(!omit_fp){
            ltac::add_instruction(bb, ltac::Operator::ENTER);
        }

        //Allocate stack space for locals
        ltac::add_instruction(bb, ltac::Operator::SUB, ltac::SP, size);

        auto iter = function->context->begin();
        auto end = function->context->end();

        //Clear stack variables
        for(; iter != end; iter++){
            auto var = iter->second;

            //Only stack variables needs to be cleared
            if(var->position().isStack()){
                auto type = var->type();
                int position = var->position().offset();

                auto int_size = INT->size(platform);

                if(type->is_array() && type->has_elements()){
                    ltac::add_instruction(bb, ltac::Operator::MOV, ltac::Address(ltac::BP, position), static_cast<int>(type->elements()));
                    ltac::add_instruction(bb, ltac::Operator::MEMSET, ltac::Address(ltac::BP, position + int_size),
                            static_cast<int>((type->data_type()->size(platform) / int_size * type->elements())));
                } else if(type->is_custom_type()){
                    ltac::add_instruction(bb, ltac::Operator::MEMSET, ltac::Address(ltac::BP, position), static_cast<int>(type->size(platform) / int_size));

                    //Set the lengths of the arrays
                    auto struct_type = function->context->global()->get_struct(type->mangle());
                    for(auto& member : struct_type->members){
                        if(member->type->is_array()){
                            ltac::add_instruction(bb, ltac::Operator::MOV,
                                    ltac::Address(ltac::BP, position + function->context->global()->member_offset(struct_type, member->name)),
                                    static_cast<int>(member->type->elements()));
                        }
                    }
                }
            }
        }

        callee_save_registers(function, bb, platform, configuration);

        //2. Generate epilogue

        bb = function->exit_bb();

        callee_restore_registers(function, bb, platform, configuration);

        ltac::add_instruction(bb, ltac::Operator::ADD, ltac::SP, size);

        //Leave stack frame
        if(!omit_fp){
            ltac::add_instruction(bb, ltac::Operator::LEAVE);
        }

        ltac::add_instruction(bb, ltac::Operator::RET);

        //3. Generate epilogue for each unresolved RET

        for(auto& bb : function){
            auto it = iterate(bb->l_statements);

            while(it.has_next()){
                auto statement = *it;

                if(auto* ptr = boost::get<std::shared_ptr<ltac::Instruction>>(&statement)){
                    if((*ptr)->op == ltac::Operator::PRE_RET){
                        (*ptr)->op = ltac::Operator::RET;

                        //Leave stack frame
                        if(!omit_fp){
                            it.insert(std::make_shared<ltac::Instruction>(ltac::Operator::LEAVE));
                        }

                        it.insert(std::make_shared<ltac::Instruction>(ltac::Operator::ADD, ltac::SP, size));

                        callee_restore_registers(function, it, platform, configuration);
                    }
                }

                ++it;
            }
        }

        //4. Generate caller save/restore code

        for(auto& bb : function){
            auto it = iterate(bb->l_statements);

            while(it.has_next()){
                auto statement = *it;

                if(auto* ptr = boost::get<std::shared_ptr<ltac::Jump>>(&statement)){
                    if((*ptr)->type == ltac::JumpType::CALL){
                        caller_cleanup(function, (*ptr)->target_function, bb, it, platform, configuration);

                        //The iterator is invalidated by the cleanup, necessary to find the call again
                        it.restart();
                        find(it, *ptr);
                    }
                }

                ++it;
            }
        }
    }
}
<|endoftext|>