Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  areasdlg.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
 */


#include <rangelst.hxx>

#include <o3tl/string_view.hxx>
#include <sfx2/dispatch.hxx>
#include <svl/stritem.hxx>
#include <vcl/svapp.hxx>
#include <vcl/weld.hxx>
#include <unotools/charclass.hxx>

#include <areasdlg.hxx>
#include <rangenam.hxx>
#include <reffact.hxx>
#include <tabvwsh.hxx>
#include <docsh.hxx>
#include <globstr.hrc>
#include <scresid.hxx>
#include <compiler.hxx>
#include <markdata.hxx>

// List box positions for print range (PR)
enum {
    SC_AREASDLG_PR_ENTIRE  = 1,
    SC_AREASDLG_PR_USER    = 2,
    SC_AREASDLG_PR_SELECT  = 3
};

// List box positions for repeat ranges (RR)
enum {
    SC_AREASDLG_RR_NONE    = 0,
    SC_AREASDLG_RR_USER    = 1,
    SC_AREASDLG_RR_OFFSET  = 2
};

namespace
{
    void ERRORBOX(weld::Window* pParent, TranslateId rId)
    {
        std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent,
                                                  VclMessageType::Warning, VclButtonsType::Ok,
                                                  ScResId(rId)));
        xBox->run();
    }
}

// global functions (->at the end of the file):

static bool lcl_CheckRepeatString( std::u16string_view aStr, const ScDocument& rDocbool bIsRow, ScRange* pRange );
static void lcl_GetRepeatRangeString( const std::optional<ScRange>& oRange, const ScDocument& rDoc, bool bIsRow, OUString& rStr );

#if 0
// this method is useful when debugging address flags.
static void printAddressFlags(ScRefFlags nFlag)
{
    if ((nFlag & ScRefFlags::COL_ABS      ) == ScRefFlags::COL_ABS      ) printf("ScRefFlags::COL_ABS \n");
    if ((nFlag & ScRefFlags::ROW_ABS      ) == ScRefFlags::ROW_ABS      ) printf("ScRefFlags::ROW_ABS \n");
    if ((nFlag & ScRefFlags::TAB_ABS      ) == ScRefFlags::TAB_ABS      ) printf("ScRefFlags::TAB_ABS \n");
    if ((nFlag & ScRefFlags::TAB_3D       ) == ScRefFlags::TAB_3D       ) printf("ScRefFlags::TAB_3D \n");
    if ((nFlag & ScRefFlags::COL2_ABS     ) == ScRefFlags::COL2_ABS     ) printf("ScRefFlags::COL2_ABS \n");
    if ((nFlag & ScRefFlags::ROW2_ABS     ) == ScRefFlags::ROW2_ABS     ) printf("ScRefFlags::ROW2_ABS \n");
    if ((nFlag & ScRefFlags::TAB2_ABS     ) == ScRefFlags::TAB2_ABS     ) printf("ScRefFlags::TAB2_ABS \n");
    if ((nFlag & ScRefFlags::TAB2_3D      ) == ScRefFlags::TAB2_3D      ) printf("ScRefFlags::TAB2_3D \n");
    if ((nFlag & ScRefFlags::ROW_VALID    ) == ScRefFlags::ROW_VALID    ) printf("ScRefFlags::ROW_VALID \n");
    if ((nFlag & ScRefFlags::COL_VALID    ) == ScRefFlags::COL_VALID    ) printf("ScRefFlags::COL_VALID \n");
    if ((nFlag & ScRefFlags::TAB_VALID    ) == ScRefFlags::TAB_VALID    ) printf("ScRefFlags::TAB_VALID \n");
    if ((nFlag & ScRefFlags::FORCE_DOC    ) == ScRefFlags::FORCE_DOC    ) printf("ScRefFlags::FORCE_DOC \n");
    if ((nFlag & ScRefFlags::ROW2_VALID   ) == ScRefFlags::ROW2_VALID   ) printf("ScRefFlags::ROW2_VALID \n");
    if ((nFlag & ScRefFlags::COL2_VALID   ) == ScRefFlags::COL2_VALID   ) printf("ScRefFlags::COL2_VALID \n");
    if ((nFlag & ScRefFlags::TAB2_VALID   ) == ScRefFlags::TAB2_VALID   ) printf("ScRefFlags::TAB2_VALID \n");
    if ((nFlag & ScRefFlags::VALID        ) == ScRefFlags::VALID        ) printf("ScRefFlags::VALID \n");
    if ((nFlag & ScRefFlags::ADDR_ABS     ) == ScRefFlags::ADDR_ABS     ) printf("ScRefFlags::ADDR_ABS \n");
    if ((nFlag & ScRefFlags::RANGE_ABS    ) == ScRefFlags::RANGE_ABS    ) printf("ScRefFlags::RANGE_ABS \n");
    if ((nFlag & ScRefFlags::ADDR_ABS_3D  ) == ScRefFlags::ADDR_ABS_3D  ) printf("ScRefFlags::ADDR_ABS_3D \n");
    if ((nFlag & ScRefFlags::RANGE_ABS_3D ) == ScRefFlags::RANGE_ABS_3D ) printf("ScRefFlags::RANGE_ABS_3D \n");
}
#endif


ScPrintAreasDlg::ScPrintAreasDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent, ScViewData& rData)
    : ScAnyRefDlgController(pB, pCW, pParent, u"modules/scalc/ui/printareasdialog.ui"_ustr, u"PrintAreasDialog"_ustr)
    , bDlgLostFocus(false)
    , rViewData(rData)
    , rDoc(rViewData.GetDocument())
    , nCurTab(rViewData.GetTabNo())
    , m_xLbPrintArea(m_xBuilder->weld_combo_box(u"lbprintarea"_ustr))
    , m_xEdPrintArea(new formula::RefEdit(m_xBuilder->weld_entry(u"edprintarea"_ustr)))
    , m_xRbPrintArea(new formula::RefButton(m_xBuilder->weld_button(u"rbprintarea"_ustr)))
    , m_xLbRepeatRow(m_xBuilder->weld_combo_box(u"lbrepeatrow"_ustr))
    , m_xEdRepeatRow(new formula::RefEdit(m_xBuilder->weld_entry(u"edrepeatrow"_ustr)))
    , m_xRbRepeatRow(new formula::RefButton(m_xBuilder->weld_button(u"rbrepeatrow"_ustr)))
    , m_xLbRepeatCol(m_xBuilder->weld_combo_box(u"lbrepeatcol"_ustr))
    , m_xEdRepeatCol(new formula::RefEdit(m_xBuilder->weld_entry(u"edrepeatcol"_ustr)))
    , m_xRbRepeatCol(new formula::RefButton(m_xBuilder->weld_button(u"rbrepeatcol"_ustr)))
    , m_xBtnOk(m_xBuilder->weld_button(u"ok"_ustr))
    , m_xBtnCancel(m_xBuilder->weld_button(u"cancel"_ustr))
    , m_xPrintFrame(m_xBuilder->weld_frame(u"printframe"_ustr))
    , m_xRowFrame(m_xBuilder->weld_frame(u"rowframe"_ustr))
    , m_xColFrame(m_xBuilder->weld_frame(u"colframe"_ustr))
    , m_xPrintFrameFT(m_xPrintFrame->weld_label_widget())
    , m_xRowFrameFT(m_xRowFrame->weld_label_widget())
    , m_xColFrameFT(m_xColFrame->weld_label_widget())
{
    m_xEdPrintArea->SetReferences(this, m_xPrintFrameFT.get());
    m_pRefInputEdit = m_xEdPrintArea.get();
    m_xRbPrintArea->SetReferences(this, m_xEdPrintArea.get());

    m_xEdRepeatRow->SetReferences(this, m_xRowFrameFT.get());
    m_xRbRepeatRow->SetReferences(this, m_xEdRepeatRow.get());

    m_xEdRepeatCol->SetReferences(this, m_xColFrameFT.get());
    m_xRbRepeatCol->SetReferences(this, m_xEdRepeatCol.get());

    Impl_Reset();

    //@BugID 54702 Enable/Disable only in base class
    //SFX_APPWINDOW->Enable();
}

ScPrintAreasDlg::~ScPrintAreasDlg()
{
}

void ScPrintAreasDlg::Close()
{
    DoClose( ScPrintAreasDlgWrapper::GetChildWindowId() );
}

bool ScPrintAreasDlg::IsTableLocked() const
{
    //  Printing areas are per table, therefore it makes no sense,
    //  to switch the table during input

    return true;
}

void ScPrintAreasDlg::SetReference( const ScRange& rRef, ScDocument& /* rDoc */ )
{
    if ( !m_pRefInputEdit )
        return;

    if ( rRef.aStart != rRef.aEnd )
        RefInputStart( m_pRefInputEdit );

    OUString  aStr;
    const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();

    if (m_xEdPrintArea.get() == m_pRefInputEdit)
    {
        aStr = rRef.Format(rDoc, ScRefFlags::RANGE_ABS, eConv);
        OUString aVal = m_xEdPrintArea->GetText();
        Selection aSel = m_xEdPrintArea->GetSelection();
        aSel.Normalize();
        aVal = aVal.replaceAt( aSel.Min(), aSel.Len(), aStr );
        Selection aNewSel( aSel.Min(), aSel.Min()+aStr.getLength() );
        m_xEdPrintArea->SetRefString( aVal );
        m_xEdPrintArea->SetSelection( aNewSel );
    }
    else
    {
        bool bRow = ( m_xEdRepeatRow.get() == m_pRefInputEdit );
        lcl_GetRepeatRangeString(rRef, rDoc, bRow, aStr);
        m_pRefInputEdit->SetRefString( aStr );
    }
    Impl_ModifyHdl( *m_pRefInputEdit );
}

void ScPrintAreasDlg::AddRefEntry()
{
    if (m_pRefInputEdit == m_xEdPrintArea.get())
    {
        const sal_Unicode sep = ScCompiler::GetNativeSymbolChar(ocSep);
        OUString aVal = m_xEdPrintArea->GetText() + OUStringChar(sep);
        m_xEdPrintArea->SetText(aVal);

        sal_Int32 nLen = aVal.getLength();
        m_xEdPrintArea->SetSelection( Selection( nLen, nLen ) );

        Impl_ModifyHdl( *m_xEdPrintArea );
    }
}

void ScPrintAreasDlg::Deactivate()
{
    bDlgLostFocus = true;
}

void ScPrintAreasDlg::SetActive()
{
    if ( bDlgLostFocus )
    {
        bDlgLostFocus = false;

        if ( m_pRefInputEdit )
        {
            m_pRefInputEdit->GrabFocus();
            Impl_ModifyHdl( *m_pRefInputEdit );
        }
    }
    else
        m_xDialog->grab_focus();

    RefInputDone();
}

void ScPrintAreasDlg::Impl_Reset()
{
    OUString        aStrRange;
    std::optional<ScRange> oRepeatColRange = rDoc.GetRepeatColRange( nCurTab );
    std::optional<ScRange> oRepeatRowRange = rDoc.GetRepeatRowRange( nCurTab );

    m_xEdPrintArea->SetModifyHdl   (LINK( this, ScPrintAreasDlg, Impl_ModifyHdl));
    m_xEdRepeatRow->SetModifyHdl   (LINK( this, ScPrintAreasDlg, Impl_ModifyHdl));
    m_xEdRepeatCol->SetModifyHdl   (LINK( this, ScPrintAreasDlg, Impl_ModifyHdl));
    m_xEdPrintArea->SetGetFocusHdl(LINK( this, ScPrintAreasDlg, Impl_GetEditFocusHdl));
    m_xEdRepeatRow->SetGetFocusHdl(LINK( this, ScPrintAreasDlg, Impl_GetEditFocusHdl));
    m_xEdRepeatCol->SetGetFocusHdl(LINK( this, ScPrintAreasDlg, Impl_GetEditFocusHdl));
    m_xLbPrintArea->connect_focus_in(LINK( this, ScPrintAreasDlg, Impl_GetFocusHdl));
    m_xLbRepeatRow->connect_focus_in(LINK( this, ScPrintAreasDlg, Impl_GetFocusHdl));
    m_xLbRepeatCol->connect_focus_in(LINK( this, ScPrintAreasDlg, Impl_GetFocusHdl));
    m_xLbPrintArea->connect_changed(LINK( this, ScPrintAreasDlg, Impl_SelectHdl));
    m_xLbRepeatRow->connect_changed(LINK( this, ScPrintAreasDlg, Impl_SelectHdl));
    m_xLbRepeatCol->connect_changed(LINK( this, ScPrintAreasDlg, Impl_SelectHdl));
    m_xBtnOk->connect_clicked(LINK( this, ScPrintAreasDlg, Impl_BtnHdl));
    m_xBtnCancel->connect_clicked(LINK( this, ScPrintAreasDlg, Impl_BtnHdl));

    Impl_FillLists();

    // printing area

    aStrRange.clear();
    const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
    const sal_Unicode sep = ScCompiler::GetNativeSymbolChar(ocSep);
    sal_uInt16 nRangeCount = rDoc.GetPrintRangeCount( nCurTab );
    for (sal_uInt16 i=0; i<nRangeCount; i++)
    {
        const ScRange* pPrintRange = rDoc.GetPrintRange( nCurTab, i );
        if (pPrintRange)
        {
            if ( !aStrRange.isEmpty() )
                aStrRange += OUStringChar(sep);
            aStrRange += pPrintRange->Format(rDoc, ScRefFlags::RANGE_ABS, eConv);
        }
    }
    m_xEdPrintArea->SetText( aStrRange );

    // repeat row

    lcl_GetRepeatRangeString(oRepeatRowRange, rDoc, true, aStrRange);
    m_xEdRepeatRow->SetText( aStrRange );

    // repeat column

    lcl_GetRepeatRangeString(oRepeatColRange, rDoc, false, aStrRange);
    m_xEdRepeatCol->SetText( aStrRange );

    Impl_ModifyHdl( *m_xEdPrintArea );
    Impl_ModifyHdl( *m_xEdRepeatRow );
    Impl_ModifyHdl( *m_xEdRepeatCol );
    if( rDoc.IsPrintEntireSheet( nCurTab ) )
        m_xLbPrintArea->set_active(SC_AREASDLG_PR_ENTIRE);

    m_xEdPrintArea->SaveValue();   // save for FillItemSet():
    m_xEdRepeatRow->SaveValue();
    m_xEdRepeatCol->SaveValue();
}

bool ScPrintAreasDlg::Impl_GetItem( const formula::RefEdit* pEd, SfxStringItem& rItem )
{
    OUString  aRangeStr = pEd->GetText();
    bool bDataChanged = pEd->IsValueChangedFromSaved();

    if ( !aRangeStr.isEmpty() && m_xEdPrintArea.get() != pEd )
    {
        ScRange aRange;
        const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
        lcl_CheckRepeatString(aRangeStr, rDoc, m_xEdRepeatRow.get() == pEd, &aRange);
        aRangeStr = aRange.Format(rDoc, ScRefFlags::RANGE_ABS, eConv);
    }

    rItem.SetValue( aRangeStr );

    return bDataChanged;
}

bool ScPrintAreasDlg::Impl_CheckRefStrings()
{
    bool        bOk = false;
    OUString      aStrPrintArea   = m_xEdPrintArea->GetText();
    OUString      aStrRepeatRow   = m_xEdRepeatRow->GetText();
    OUString      aStrRepeatCol   = m_xEdRepeatCol->GetText();

    bool bPrintAreaOk = true;
    if ( !aStrPrintArea.isEmpty() )
    {
        const ScRefFlags nValidAddr  = ScRefFlags::VALID | ScRefFlags::ROW_VALID | ScRefFlags::COL_VALID;
        const ScRefFlags nValidRange = nValidAddr | ScRefFlags::ROW2_VALID | ScRefFlags::COL2_VALID;
        const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
        const sal_Unicode sep  = ScCompiler::GetNativeSymbolChar(ocSep);

        ScAddress aAddr;
        ScRange aRange;
        for ( sal_Int32 nIdx = 0; nIdx >= 0; )
        {
            const OUString aOne = aStrPrintArea.getToken(0, sep, nIdx);
            ScRefFlags nResult = aRange.Parse( aOne, rDoc, eConv );
            if ((nResult & nValidRange) != nValidRange)
            {
                ScRefFlags nAddrResult = aAddr.Parse( aOne, rDoc, eConv );
                if ((nAddrResult & nValidAddr) != nValidAddr)
                {
                    bPrintAreaOk = false;
                    break;
                }
            }
        }
    }

    bool bRepeatRowOk = aStrRepeatRow.isEmpty();
    if ( !bRepeatRowOk )
        bRepeatRowOk = lcl_CheckRepeatString(aStrRepeatRow, rDoc, true, nullptr);

    bool bRepeatColOk = aStrRepeatCol.isEmpty();
    if ( !bRepeatColOk )
        bRepeatColOk = lcl_CheckRepeatString(aStrRepeatCol, rDoc, false, nullptr);

    // error messages

    bOk = (bPrintAreaOk && bRepeatRowOk && bRepeatColOk);

    if ( !bOk )
    {
        formula::RefEdit* pEd = nullptr;

        if ( !bPrintAreaOk ) pEd = m_xEdPrintArea.get();
        else if ( !bRepeatRowOk ) pEd = m_xEdRepeatRow.get();
        else if ( !bRepeatColOk ) pEd = m_xEdRepeatCol.get();

        ERRORBOX(m_xDialog.get(), STR_INVALID_TABREF);

        OSL_ASSERT(pEd);

        if (pEd)
            pEd->GrabFocus();
    }

    return bOk;
}

void ScPrintAreasDlg::Impl_FillLists()
{

    // Get selection and remember String in PrintArea-ListBox

    ScRange  aRange;
    OUString aStrRange;
    bool bSimple = true;

    bSimple = (rViewData.GetSimpleArea( aRange ) == SC_MARK_SIMPLE);

    formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();

    if ( bSimple )
        aStrRange = aRange.Format(rDoc, ScRefFlags::RANGE_ABS, eConv);
    else
    {
        ScRangeListRef aList( new ScRangeList );
        rViewData.GetMarkData().FillRangeListWithMarks( aList.get(), false );
        aList->Format(aStrRange, ScRefFlags::RANGE_ABS, rDoc, eConv);
    }

    m_xLbPrintArea->set_id(SC_AREASDLG_PR_SELECT, aStrRange);

    // Get ranges and remember in ListBoxen

    ScRangeName* pRangeNames = rDoc.GetRangeName();

    if (!pRangeNames || pRangeNames->empty())
        // No range names to process.
        return;

    for (const auto& rEntry : *pRangeNames)
    {
        if (!rEntry.second->HasType(ScRangeData::Type::AbsArea   )
            && !rEntry.second->HasType(ScRangeData::Type::RefArea)
            && !rEntry.second->HasType(ScRangeData::Type::AbsPos ))
            continue;

        OUString aName = rEntry.second->GetName();
        OUString aSymbol = rEntry.second->GetSymbol();
        if (aRange.ParseAny(aSymbol, rDoc, eConv) & ScRefFlags::VALID)
        {
            if (rEntry.second->HasType(ScRangeData::Type::PrintArea))
            {
                aSymbol = aRange.Format(rDoc, ScRefFlags::RANGE_ABS, eConv);
                m_xLbPrintArea->append(aSymbol, aName);
            }

            if (rEntry.second->HasType(ScRangeData::Type::RowHeader))
            {
                lcl_GetRepeatRangeString(aRange, rDoc, true, aSymbol);
                m_xLbRepeatRow->append(aSymbol, aName);
            }

            if (rEntry.second->HasType(ScRangeData::Type::ColHeader))
            {
                lcl_GetRepeatRangeString(aRange, rDoc, false, aSymbol);
                m_xLbRepeatCol->append(aSymbol, aName);
            }
        }
    }
}

// Handler:

IMPL_LINK(ScPrintAreasDlg, Impl_BtnHdl, weld::Button&, rBtn, void)
{
    if (m_xBtnOk.get() == &rBtn)
    {
        if ( Impl_CheckRefStrings() )
        {
            SfxStringItem   aPrintArea( SID_CHANGE_PRINTAREA, u""_ustr );
            SfxStringItem   aRepeatRow( FN_PARAM_2, u""_ustr );
            SfxStringItem   aRepeatCol( FN_PARAM_3, u""_ustr );

            // Printing area changed?

            // first try the list box, if "Entire sheet" is selected
            bool bEntireSheet = (m_xLbPrintArea->get_active() == SC_AREASDLG_PR_ENTIRE);
            SfxBoolItem aEntireSheet( FN_PARAM_4, bEntireSheet );

            bool bDataChanged = bEntireSheet != rDoc.IsPrintEntireSheet( nCurTab );
            if( !bEntireSheet )
            {
                // if new list box selection is not "Entire sheet", get the edit field contents
                bDataChanged |= Impl_GetItem( m_xEdPrintArea.get(), aPrintArea );
            }

            // Repeat row changed?

            bDataChanged |= Impl_GetItem( m_xEdRepeatRow.get(), aRepeatRow );

            // Repeat column changed?

            bDataChanged |= Impl_GetItem( m_xEdRepeatCol.get(), aRepeatCol );

            if ( bDataChanged )
            {
                SetDispatcherLock( false );
                SwitchToDocument();
                GetBindings().GetDispatcher()->ExecuteList(SID_CHANGE_PRINTAREA,
                      SfxCallMode::SLOT | SfxCallMode::RECORD,
                      { &aPrintArea, &aRepeatRow, &aRepeatCol, &aEntireSheet });
            }

            response(RET_OK);
        }
    }
    else if (m_xBtnCancel.get() == &rBtn)
        response(RET_CANCEL);
}

IMPL_LINK(ScPrintAreasDlg, Impl_GetEditFocusHdl, formula::RefEdit&, rCtrl, void)
{
    m_pRefInputEdit = &rCtrl;
}

IMPL_LINK(ScPrintAreasDlg, Impl_GetFocusHdl, weld::Widget&, rCtrl, void)
{
    if (&rCtrl == m_xLbPrintArea.get())
        m_pRefInputEdit = m_xEdPrintArea.get();
    else if (&rCtrl == m_xLbRepeatRow.get())
        m_pRefInputEdit = m_xEdRepeatRow.get();
    else if (&rCtrl == m_xLbRepeatCol.get())
        m_pRefInputEdit = m_xEdRepeatCol.get();
}

IMPL_LINK( ScPrintAreasDlg, Impl_SelectHdl, weld::ComboBox&, rLb, void )
{
    const sal_Int32 nSelPos = rLb.get_active();
    formula::RefEdit* pEd = nullptr;

    // list box positions of specific entries, default to "repeat row/column" list boxes
    sal_Int32 nAllSheetPos = SC_AREASDLG_RR_NONE;
    sal_Int32 nFirstCustomPos = SC_AREASDLG_RR_OFFSET;

    // find edit field for list box, and list box positions
    if (&rLb == m_xLbPrintArea.get())
    {
        pEd = m_xEdPrintArea.get();
        nAllSheetPos = SC_AREASDLG_PR_ENTIRE;
        nFirstCustomPos = SC_AREASDLG_PR_SELECT;    // "Selection" and following
    }
    else if (&rLb == m_xLbRepeatCol.get())
        pEd = m_xEdRepeatCol.get();
    else if (&rLb == m_xLbRepeatRow.get())
        pEd = m_xEdRepeatRow.get();
    else
        return;

    // fill edit field according to list box selection
    if( (nSelPos == 0) || (nSelPos == nAllSheetPos) )
        pEd->SetText( OUString() );
    else if( nSelPos >= nFirstCustomPos )
        pEd->SetText(rLb.get_id(nSelPos));
}

IMPL_LINK( ScPrintAreasDlg, Impl_ModifyHdl, formula::RefEdit&, rEd, void )
{
    weld::ComboBox* pLb = nullptr;

    // list box positions of specific entries, default to "repeat row/column" list boxes
    sal_Int32 nUserDefPos = SC_AREASDLG_RR_USER;
    sal_Int32 nFirstCustomPos = SC_AREASDLG_RR_OFFSET;

    if( &rEd == m_xEdPrintArea.get() )
    {
        pLb = m_xLbPrintArea.get();
        nUserDefPos = SC_AREASDLG_PR_USER;
        nFirstCustomPos = SC_AREASDLG_PR_SELECT;    // "Selection" and following
    }
    else if( &rEd == m_xEdRepeatCol.get() )
        pLb = m_xLbRepeatCol.get();
    else if( &rEd == m_xEdRepeatRow.get() )
        pLb = m_xLbRepeatRow.get();
    else
        return;

    // set list box selection according to edit field
    const sal_Int32 nEntryCount = pLb->get_count();
    OUString aStrEd( rEd.GetText() );
    OUString aEdUpper = aStrEd.toAsciiUpperCase();

    if ( (nEntryCount > nFirstCustomPos) && !aStrEd.isEmpty() )
    {
        bool    bFound  = false;
        sal_Int32 i;

        for ( i=nFirstCustomPos; i<nEntryCount && !bFound; i++ )
        {
            const OUString aSymbol = pLb->get_id(i);
            bFound = (aSymbol == aStrEd || aSymbol == aEdUpper);
        }

        pLb->set_active( bFound ? i-1 : nUserDefPos );
    }
    else
        pLb->set_active( !aStrEd.isEmpty() ? nUserDefPos : 0 );
}

// global functions:

// TODO: It might make sense to move these functions to address.?xx. -kohei

static bool lcl_CheckOne_OOO( const ScDocument& rDoc, const OUString& rStr, bool bIsRow, SCCOLROW& rVal )
{
    // Allowed syntax for rStr:
    // Row: [$]1-MAXTAB
    // Col: [$]A-IV

    OUString    aStr    = rStr;
    sal_Int32   nLen    = aStr.getLength();
    SCCOLROW    nNum    = 0;
    bool    bStrOk  = ( nLen > 0 ) && ( bIsRow ? ( nLen < 6 ) : ( nLen < 4 ) );

    if ( bStrOk )
    {
        if ( '$' == aStr[0] )
            aStr = aStr.copy( 1 );

        if ( bIsRow )
        {
            bStrOk = CharClass::isAsciiNumeric(aStr);

            if ( bStrOk )
            {
                sal_Int32 n = aStr.toInt32();

                bStrOk = (n > 0) && ( n <= rDoc.GetSheetLimits().GetMaxRowCount() );
                if ( bStrOk )
                    nNum = static_cast<SCCOLROW>(n - 1);
            }
        }
        else
        {
            SCCOL nCol = 0;
            bStrOk = ::AlphaToCol(rDoc, nCol, aStr);
            nNum = nCol;
        }
    }

    if ( bStrOk )
        rVal = nNum;

    return bStrOk;
}

static bool lcl_CheckOne_XL_A1( const ScDocument& rDoc, const OUString& rStr, bool bIsRow, SCCOLROW& rVal )
{
    // XL A1 style is identical to OOO one for print range formats.
    return lcl_CheckOne_OOO(rDoc, rStr, bIsRow, rVal);
}

static bool lcl_CheckOne_XL_R1C1( const ScDocument& rDoc, std::u16string_view aStr, bool bIsRow, SCCOLROW& rVal )
{
    sal_Int32 nLen = aStr.size();
    if (nLen <= 1)
        // There must be at least two characters.
        return false;

    const sal_Unicode preUpper = bIsRow ? 'R' : 'C';
    const sal_Unicode preLower = bIsRow ? 'r' : 'c';
    if (aStr[0] != preUpper && aStr[0] != preLower)
        return false;

    std::u16string_view aNumStr = aStr.substr(1);
    if (!CharClass::isAsciiNumeric(aNumStr))
        return false;

    sal_Int32 nNum = o3tl::toInt32(aNumStr);

    if (nNum <= 0)
        return false;

    if ((bIsRow && nNum > rDoc.GetSheetLimits().GetMaxRowCount()) ||
        (!bIsRow && nNum > rDoc.GetSheetLimits().GetMaxColCount()))
        return false;

    rVal = static_cast<SCCOLROW>(nNum-1);
    return true;
}

static bool lcl_CheckRepeatOne( const ScDocument& rDoc, const OUString& rStr, formula::FormulaGrammar::AddressConvention eConv, bool bIsRow, SCCOLROW& rVal )
{
    switch (eConv)
    {
        case formula::FormulaGrammar::CONV_OOO:
            return lcl_CheckOne_OOO(rDoc, rStr, bIsRow, rVal);
        case formula::FormulaGrammar::CONV_XL_A1:
            return lcl_CheckOne_XL_A1(rDoc, rStr, bIsRow, rVal);
        case formula::FormulaGrammar::CONV_XL_R1C1:
            return lcl_CheckOne_XL_R1C1(rDoc, rStr, bIsRow, rVal);
        default:
        {
            // added to avoid warnings
        }
    }
    return false;
}

static bool lcl_CheckRepeatString( std::u16string_view aStr, const ScDocument& rDocbool bIsRow, ScRange* pRange )
{
    // Row: [valid row] rsep [valid row]
    // Col: [valid col] rsep [valid col]

    const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
    const sal_Unicode rsep = ScCompiler::GetNativeSymbolChar(ocRange);

    if (pRange)
    {
        // initialize the range value.
        pRange->aStart.SetCol(0);
        pRange->aStart.SetRow(0);
        pRange->aEnd.SetCol(0);
        pRange->aEnd.SetRow(0);
    }

    OUString aBuf;
    SCCOLROW nVal = 0;
    sal_Int32 nLen = aStr.size();
    bool bEndPos = false;
    for( sal_Int32 i = 0; i < nLen; ++i )
    {
        const sal_Unicode c = aStr[i];
        if (c == rsep)
        {
            if (bEndPos)
                // We aren't supposed to have more than one range separator.
                return false;

            // range separator
            if (aBuf.isEmpty())
                return false;

            bool bRes = lcl_CheckRepeatOne(rDoc, aBuf, eConv, bIsRow, nVal);
            if (!bRes)
                return false;

            if (pRange)
            {
                if (bIsRow)
                {
                    pRange->aStart.SetRow(static_cast<SCROW>(nVal));
                    pRange->aEnd.SetRow(static_cast<SCROW>(nVal));
                }
                else
                {
                    pRange->aStart.SetCol(static_cast<SCCOL>(nVal));
                    pRange->aEnd.SetCol(static_cast<SCCOL>(nVal));
                }
            }

            aBuf.clear();
            bEndPos = true;
        }
        else
            aBuf += OUStringChar(c);
    }

    if (!aBuf.isEmpty())
    {
        bool bRes = lcl_CheckRepeatOne(rDoc, aBuf, eConv, bIsRow, nVal);
        if (!bRes)
            return false;

        if (pRange)
        {
            if (bIsRow)
            {
                if (!bEndPos)
                    pRange->aStart.SetRow(static_cast<SCROW>(nVal));
                pRange->aEnd.SetRow(static_cast<SCROW>(nVal));
            }
            else
            {
                if (!bEndPos)
                    pRange->aStart.SetCol(static_cast<SCCOL>(nVal));
                pRange->aEnd.SetCol(static_cast<SCCOL>(nVal));
            }
        }
    }

    return true;
}

static void lcl_GetRepeatRangeString( const std::optional<ScRange>& oRange, const ScDocument& rDoc, bool bIsRow, OUString& rStr )
{
    rStr.clear();
    if (!oRange)
        return;

    const formula::FormulaGrammar::AddressConvention eConv = rDoc.GetAddressConvention();
    const ScAddress& rStart = oRange->aStart;
    const ScAddress& rEnd   = oRange->aEnd;

    const ScRefFlags nFmt = bIsRow
                            ? (ScRefFlags::ROW_VALID | ScRefFlags::ROW_ABS)
                            : (ScRefFlags::COL_VALID | ScRefFlags::COL_ABS);
    rStr += rStart.Format(nFmt, &rDoc, eConv);
    if ((bIsRow && rStart.Row() != rEnd.Row()) || (!bIsRow && rStart.Col() != rEnd.Col()))
    {
        rStr += ScCompiler::GetNativeSymbol(ocRange);
        rStr += rEnd.Format(nFmt, &rDoc, eConv);
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=65 H=96 G=81

¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge