/* -*- 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 #include #include #include #include #include #include #include "areasdlg.hxx" #include "scresid.hxx" #include "rangenam.hxx" #include "reffact.hxx" #include "tabvwsh.hxx" #include "docsh.hxx" #include "globstr.hrc" #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 }; #define HDL(hdl) LINK( this, ScPrintAreasDlg, hdl ) #define ERRORBOX(nId) ScopedVclPtrInstance(this, ScGlobal::GetRscString(nId))->Execute() // global functions (->at the end of the file): static bool lcl_CheckRepeatString( const OUString& rStr, ScDocument* pDoc, bool bIsRow, ScRange* pRange ); static void lcl_GetRepeatRangeString( const ScRange* pRange, ScDocument* pDoc, 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 // class ScPrintAreasDlg ScPrintAreasDlg::ScPrintAreasDlg( SfxBindings* pB, SfxChildWindow* pCW, vcl::Window* pParent ) : ScAnyRefDlg(pB, pCW, pParent, "PrintAreasDialog", "modules/scalc/ui/printareasdialog.ui") , bDlgLostFocus(false) , pDoc(nullptr) , pViewData(nullptr) , nCurTab(0) { get(pLbPrintArea,"lbprintarea"); get(pEdPrintArea,"edprintarea"); pEdPrintArea->SetReferences(this, get("printframe")->get_label_widget()); pRefInputEdit = pEdPrintArea; get(pRbPrintArea,"rbprintarea"); pRbPrintArea->SetReferences(this, pEdPrintArea); get(pLbRepeatRow,"lbrepeatrow"); get(pEdRepeatRow,"edrepeatrow"); pEdRepeatRow->SetReferences(this, get("rowframe")->get_label_widget()); get(pRbRepeatRow,"rbrepeatrow"); pRbRepeatRow->SetReferences(this, pEdRepeatRow); get(pLbRepeatCol,"lbrepeatcol"); get(pEdRepeatCol,"edrepeatcol"); pEdRepeatCol->SetReferences(this, get("colframe")->get_label_widget()); get(pRbRepeatCol,"rbrepeatcol"); pRbRepeatCol->SetReferences(this, pEdRepeatCol); get(pBtnOk,"ok"); get(pBtnCancel,"cancel"); ScTabViewShell* pScViewSh = dynamic_cast( SfxViewShell::Current() ); ScDocShell* pScDocSh = dynamic_cast( SfxObjectShell::Current() ); OSL_ENSURE( pScDocSh, "Current DocumentShell not found :-(" ); pDoc = &pScDocSh->GetDocument(); if ( pScViewSh ) { pViewData = &pScViewSh->GetViewData(); nCurTab = pViewData->GetTabNo(); } Impl_Reset(); //@BugID 54702 Enable/Disable only in base class //SFX_APPWINDOW->Enable(); } ScPrintAreasDlg::~ScPrintAreasDlg() { disposeOnce(); } void ScPrintAreasDlg::dispose() { // clean extra data of ListBox entries ListBox* aLb[3] = { pLbPrintArea, pLbRepeatRow, pLbRepeatCol }; for (ListBox* pBox : aLb) { const sal_Int32 nCount = pBox->GetEntryCount(); for ( sal_Int32 j=0; j(pBox->GetEntryData(j)); } pLbPrintArea.clear(); pEdPrintArea.clear(); pRbPrintArea.clear(); pLbRepeatRow.clear(); pEdRepeatRow.clear(); pRbRepeatRow.clear(); pLbRepeatCol.clear(); pEdRepeatCol.clear(); pRbRepeatCol.clear(); pBtnOk.clear(); pBtnCancel.clear(); pRefInputEdit.clear(); ScAnyRefDlg::dispose(); } bool ScPrintAreasDlg::Close() { return 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* /* pDoc */ ) { if ( pRefInputEdit ) { if ( rRef.aStart != rRef.aEnd ) RefInputStart( pRefInputEdit ); OUString aStr; const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention(); if ( pEdPrintArea == pRefInputEdit ) { aStr = rRef.Format(ScRefFlags::RANGE_ABS, pDoc, eConv); OUString aVal = pEdPrintArea->GetText(); Selection aSel = pEdPrintArea->GetSelection(); aSel.Justify(); aVal = aVal.replaceAt( aSel.Min(), aSel.Len(), aStr ); Selection aNewSel( aSel.Min(), aSel.Min()+aStr.getLength() ); pEdPrintArea->SetRefString( aVal ); pEdPrintArea->SetSelection( aNewSel ); } else { bool bRow = ( pEdRepeatRow == pRefInputEdit ); lcl_GetRepeatRangeString(&rRef, pDoc, bRow, aStr); pRefInputEdit->SetRefString( aStr ); } Impl_ModifyHdl( *pRefInputEdit ); } } void ScPrintAreasDlg::AddRefEntry() { if ( pRefInputEdit == pEdPrintArea ) { const sal_Unicode sep = ScCompiler::GetNativeSymbolChar(ocSep); OUString aVal = pEdPrintArea->GetText() + OUStringLiteral1(sep); pEdPrintArea->SetText(aVal); sal_Int32 nLen = aVal.getLength(); pEdPrintArea->SetSelection( Selection( nLen, nLen ) ); Impl_ModifyHdl( *pEdPrintArea ); } } void ScPrintAreasDlg::Deactivate() { bDlgLostFocus = true; } void ScPrintAreasDlg::SetActive() { if ( bDlgLostFocus ) { bDlgLostFocus = false; if ( pRefInputEdit ) { pRefInputEdit->GrabFocus(); Impl_ModifyHdl( *pRefInputEdit ); } } else GrabFocus(); RefInputDone(); } void ScPrintAreasDlg::Impl_Reset() { OUString aStrRange; const ScRange* pRepeatColRange = pDoc->GetRepeatColRange( nCurTab ); const ScRange* pRepeatRowRange = pDoc->GetRepeatRowRange( nCurTab ); pEdPrintArea->SetModifyHdl ( HDL(Impl_ModifyHdl) ); pEdRepeatRow->SetModifyHdl ( HDL(Impl_ModifyHdl) ); pEdRepeatCol->SetModifyHdl ( HDL(Impl_ModifyHdl) ); pEdPrintArea->SetGetFocusHdl( HDL(Impl_GetFocusHdl) ); pEdRepeatRow->SetGetFocusHdl( HDL(Impl_GetFocusHdl) ); pEdRepeatCol->SetGetFocusHdl( HDL(Impl_GetFocusHdl) ); pLbPrintArea->SetGetFocusHdl( HDL(Impl_GetFocusHdl) ); pLbRepeatRow->SetGetFocusHdl( HDL(Impl_GetFocusHdl) ); pLbRepeatCol->SetGetFocusHdl( HDL(Impl_GetFocusHdl) ); pLbPrintArea->SetSelectHdl ( HDL(Impl_SelectHdl) ); pLbRepeatRow->SetSelectHdl ( HDL(Impl_SelectHdl) ); pLbRepeatCol->SetSelectHdl ( HDL(Impl_SelectHdl) ); pBtnOk-> SetClickHdl ( HDL(Impl_BtnHdl) ); pBtnCancel-> SetClickHdl ( HDL(Impl_BtnHdl) ); Impl_FillLists(); // printing area aStrRange.clear(); OUString aOne; const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention(); const sal_Unicode sep = ScCompiler::GetNativeSymbolChar(ocSep); sal_uInt16 nRangeCount = pDoc->GetPrintRangeCount( nCurTab ); for (sal_uInt16 i=0; iGetPrintRange( nCurTab, i ); if (pPrintRange) { if ( !aStrRange.isEmpty() ) aStrRange += OUStringLiteral1(sep); aOne = pPrintRange->Format(ScRefFlags::RANGE_ABS, pDoc, eConv); aStrRange += aOne; } } pEdPrintArea->SetText( aStrRange ); // repeat row lcl_GetRepeatRangeString(pRepeatRowRange, pDoc, true, aStrRange); pEdRepeatRow->SetText( aStrRange ); // repeat column lcl_GetRepeatRangeString(pRepeatColRange, pDoc, false, aStrRange); pEdRepeatCol->SetText( aStrRange ); Impl_ModifyHdl( *pEdPrintArea ); Impl_ModifyHdl( *pEdRepeatRow ); Impl_ModifyHdl( *pEdRepeatCol ); if( pDoc->IsPrintEntireSheet( nCurTab ) ) pLbPrintArea->SelectEntryPos( SC_AREASDLG_PR_ENTIRE ); pEdPrintArea->SaveValue(); // save for FillItemSet(): pEdRepeatRow->SaveValue(); pEdRepeatCol->SaveValue(); } bool ScPrintAreasDlg::Impl_GetItem( Edit* pEd, SfxStringItem& rItem ) { OUString aRangeStr = pEd->GetText(); bool bDataChanged = pEd->IsValueChangedFromSaved(); if ( !aRangeStr.isEmpty() && pEdPrintArea != pEd ) { ScRange aRange; const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention(); lcl_CheckRepeatString(aRangeStr, pDoc, pEdRepeatRow == pEd, &aRange); aRangeStr = aRange.Format(ScRefFlags::RANGE_ABS, pDoc, eConv); } rItem.SetValue( aRangeStr ); return bDataChanged; } bool ScPrintAreasDlg::Impl_CheckRefStrings() { bool bOk = false; OUString aStrPrintArea = pEdPrintArea->GetText(); OUString aStrRepeatRow = pEdRepeatRow->GetText(); OUString aStrRepeatCol = pEdRepeatCol->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 = pDoc->GetAddressConvention(); const sal_Unicode sep = ScCompiler::GetNativeSymbolChar(ocSep); ScAddress aAddr; ScRange aRange; sal_Int32 nSepCount = comphelper::string::getTokenCount(aStrPrintArea, sep); for ( sal_Int32 i = 0; i < nSepCount && bPrintAreaOk; ++i ) { OUString aOne = aStrPrintArea.getToken(i, sep); ScRefFlags nResult = aRange.Parse( aOne, pDoc, eConv ); if ((nResult & nValidRange) != nValidRange) { ScRefFlags nAddrResult = aAddr.Parse( aOne, pDoc, eConv ); if ((nAddrResult & nValidAddr) != nValidAddr) bPrintAreaOk = false; } } } bool bRepeatRowOk = aStrRepeatRow.isEmpty(); if ( !bRepeatRowOk ) bRepeatRowOk = lcl_CheckRepeatString(aStrRepeatRow, pDoc, true, nullptr); bool bRepeatColOk = aStrRepeatCol.isEmpty(); if ( !bRepeatColOk ) bRepeatColOk = lcl_CheckRepeatString(aStrRepeatCol, pDoc, false, nullptr); // error messages bOk = (bPrintAreaOk && bRepeatRowOk && bRepeatColOk); if ( !bOk ) { Edit* pEd = nullptr; if ( !bPrintAreaOk ) pEd = pEdPrintArea; else if ( !bRepeatRowOk ) pEd = pEdRepeatRow; else if ( !bRepeatColOk ) pEd = pEdRepeatCol; ERRORBOX( 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; if ( pViewData ) bSimple = (pViewData->GetSimpleArea( aRange ) == SC_MARK_SIMPLE); formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention(); if ( bSimple ) aStrRange = aRange.Format(ScRefFlags::RANGE_ABS, pDoc, eConv); else { ScRangeListRef aList( new ScRangeList ); pViewData->GetMarkData().FillRangeListWithMarks( aList.get(), false ); aList->Format(aStrRange, ScRefFlags::RANGE_ABS, pDoc, eConv); } pLbPrintArea->SetEntryData( SC_AREASDLG_PR_SELECT, new OUString( aStrRange ) ); // Get ranges and remember in ListBoxen ScRangeName* pRangeNames = pDoc->GetRangeName(); if (!pRangeNames || pRangeNames->empty()) // No range names to process. return; ScRangeName::const_iterator itr = pRangeNames->begin(), itrEnd = pRangeNames->end(); for (; itr != itrEnd; ++itr) { if (!itr->second->HasType(ScRangeData::Type::AbsArea ) && !itr->second->HasType(ScRangeData::Type::RefArea) && !itr->second->HasType(ScRangeData::Type::AbsPos )) continue; OUString aName = itr->second->GetName(); OUString aSymbol; itr->second->GetSymbol(aSymbol); if (aRange.ParseAny(aSymbol, pDoc, eConv) & ScRefFlags::VALID) { if (itr->second->HasType(ScRangeData::Type::PrintArea)) { aSymbol = aRange.Format(ScRefFlags::RANGE_ABS, pDoc, eConv); pLbPrintArea->SetEntryData( pLbPrintArea->InsertEntry(aName), new OUString(aSymbol) ); } if (itr->second->HasType(ScRangeData::Type::RowHeader)) { lcl_GetRepeatRangeString(&aRange, pDoc, true, aSymbol); pLbRepeatRow->SetEntryData( pLbRepeatRow->InsertEntry(aName), new OUString(aSymbol) ); } if (itr->second->HasType(ScRangeData::Type::ColHeader)) { lcl_GetRepeatRangeString(&aRange, pDoc, false, aSymbol); pLbRepeatCol->SetEntryData( pLbRepeatCol->InsertEntry(aName), new OUString(aSymbol)); } } } } // Handler: IMPL_LINK( ScPrintAreasDlg, Impl_BtnHdl, Button*, pBtn, void ) { if ( pBtnOk == pBtn ) { if ( Impl_CheckRefStrings() ) { OUString aStr; SfxStringItem aPrintArea( SID_CHANGE_PRINTAREA, aStr ); SfxStringItem aRepeatRow( FN_PARAM_2, aStr ); SfxStringItem aRepeatCol( FN_PARAM_3, aStr ); // Printing area changed? // first try the list box, if "Entire sheet" is selected bool bEntireSheet = (pLbPrintArea->GetSelectEntryPos() == SC_AREASDLG_PR_ENTIRE); SfxBoolItem aEntireSheet( FN_PARAM_4, bEntireSheet ); bool bDataChanged = bEntireSheet != pDoc->IsPrintEntireSheet( nCurTab ); if( !bEntireSheet ) { // if new list box selection is not "Entire sheet", get the edit field contents bDataChanged |= Impl_GetItem( pEdPrintArea, aPrintArea ); } // Repeat row changed? bDataChanged |= Impl_GetItem( pEdRepeatRow, aRepeatRow ); // Repeat column changed? bDataChanged |= Impl_GetItem( pEdRepeatCol, aRepeatCol ); if ( bDataChanged ) { SetDispatcherLock( false ); SwitchToDocument(); GetBindings().GetDispatcher()->ExecuteList(SID_CHANGE_PRINTAREA, SfxCallMode::SLOT | SfxCallMode::RECORD, { &aPrintArea, &aRepeatRow, &aRepeatCol, &aEntireSheet }); } Close(); } } else if ( pBtnCancel == pBtn ) Close(); } IMPL_LINK( ScPrintAreasDlg, Impl_GetFocusHdl, Control&, rCtrl, void ) { if ( &rCtrl ==static_cast(pEdPrintArea) || &rCtrl ==static_cast(pEdRepeatRow) || &rCtrl ==static_cast(pEdRepeatCol)) { pRefInputEdit = static_cast(&rCtrl); } else if ( &rCtrl ==static_cast(pLbPrintArea)) { pRefInputEdit = pEdPrintArea; } else if ( &rCtrl ==static_cast(pLbRepeatRow)) { pRefInputEdit = pEdRepeatRow; } else if ( &rCtrl ==static_cast(pLbRepeatCol)) { pRefInputEdit = pEdRepeatCol; } } IMPL_LINK( ScPrintAreasDlg, Impl_SelectHdl, ListBox&, rLb, void ) { ListBox* pLb = &rLb; const sal_Int32 nSelPos = pLb->GetSelectEntryPos(); Edit* pEd = nullptr; // list box positions of specific entries, default to "repeat row/column" list boxes sal_Int32 nAllSheetPos = SC_AREASDLG_RR_NONE; sal_Int32 nUserDefPos = SC_AREASDLG_RR_USER; sal_Int32 nFirstCustomPos = SC_AREASDLG_RR_OFFSET; // find edit field for list box, and list box positions if( pLb == pLbPrintArea ) { pEd = pEdPrintArea; nAllSheetPos = SC_AREASDLG_PR_ENTIRE; nUserDefPos = SC_AREASDLG_PR_USER; nFirstCustomPos = SC_AREASDLG_PR_SELECT; // "Selection" and following } else if( pLb == pLbRepeatCol ) pEd = pEdRepeatCol; else if( pLb == pLbRepeatRow ) pEd = pEdRepeatRow; else return; // fill edit field according to list box selection if( (nSelPos == 0) || (nSelPos == nAllSheetPos) ) pEd->SetText( EMPTY_OUSTRING ); else if( nSelPos == nUserDefPos && !pLb->IsTravelSelect() && pEd->GetText().isEmpty()) pLb->SelectEntryPos( 0 ); else if( nSelPos >= nFirstCustomPos ) pEd->SetText( *static_cast< OUString* >( pLb->GetEntryData( nSelPos ) ) ); } IMPL_LINK( ScPrintAreasDlg, Impl_ModifyHdl, Edit&, rEd, void ) { ListBox* 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 == pEdPrintArea ) { pLb = pLbPrintArea; nUserDefPos = SC_AREASDLG_PR_USER; nFirstCustomPos = SC_AREASDLG_PR_SELECT; // "Selection" and following } else if( &rEd == pEdRepeatCol ) pLb = pLbRepeatCol; else if( &rEd == pEdRepeatRow ) pLb = pLbRepeatRow; else return; // set list box selection according to edit field const sal_Int32 nEntryCount = pLb->GetEntryCount(); OUString aStrEd( rEd.GetText() ); OUString aEdUpper = aStrEd.toAsciiUpperCase(); if ( (nEntryCount > nFirstCustomPos) && !aStrEd.isEmpty() ) { bool bFound = false; sal_Int32 i; for ( i=nFirstCustomPos; i(pLb->GetEntryData( i )); bFound = ( (*pSymbol) ==aStrEd || (*pSymbol) == aEdUpper ); } pLb->SelectEntryPos( bFound ? i-1 : nUserDefPos ); } else pLb->SelectEntryPos( !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 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 <= MAXROWCOUNT ); if ( bStrOk ) nNum = static_cast(n - 1); } } else { SCCOL nCol = 0; bStrOk = ::AlphaToCol( nCol, aStr); nNum = nCol; } } if ( bStrOk ) rVal = nNum; return bStrOk; } static bool lcl_CheckOne_XL_A1( const OUString& rStr, bool bIsRow, SCCOLROW& rVal ) { // XL A1 style is identical to OOO one for print range formats. return lcl_CheckOne_OOO(rStr, bIsRow, rVal); } static bool lcl_CheckOne_XL_R1C1( const OUString& rStr, bool bIsRow, SCCOLROW& rVal ) { sal_Int32 nLen = rStr.getLength(); 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 (rStr[0] != preUpper && rStr[0] != preLower) return false; OUString aNumStr = rStr.copy(1); if (!CharClass::isAsciiNumeric(aNumStr)) return false; sal_Int32 nNum = aNumStr.toInt32(); if (nNum <= 0) return false; if ((bIsRow && nNum > MAXROWCOUNT) || (!bIsRow && nNum > MAXCOLCOUNT)) return false; rVal = static_cast(nNum-1); return true; } static bool lcl_CheckRepeatOne( const OUString& rStr, formula::FormulaGrammar::AddressConvention eConv, bool bIsRow, SCCOLROW& rVal ) { switch (eConv) { case formula::FormulaGrammar::CONV_OOO: return lcl_CheckOne_OOO(rStr, bIsRow, rVal); case formula::FormulaGrammar::CONV_XL_A1: return lcl_CheckOne_XL_A1(rStr, bIsRow, rVal); case formula::FormulaGrammar::CONV_XL_R1C1: return lcl_CheckOne_XL_R1C1(rStr, bIsRow, rVal); default: { // added to avoid warnings } } return false; } static bool lcl_CheckRepeatString( const OUString& rStr, ScDocument* pDoc, bool bIsRow, ScRange* pRange ) { // Row: [valid row] rsep [valid row] // Col: [valid col] rsep [valid col] const formula::FormulaGrammar::AddressConvention eConv = pDoc->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 = rStr.getLength(); bool bEndPos = false; for( sal_Int32 i = 0; i < nLen; ++i ) { const sal_Unicode c = rStr[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(aBuf, eConv, bIsRow, nVal); if (!bRes) return false; if (pRange) { if (bIsRow) { pRange->aStart.SetRow(static_cast(nVal)); pRange->aEnd.SetRow(static_cast(nVal)); } else { pRange->aStart.SetCol(static_cast(nVal)); pRange->aEnd.SetCol(static_cast(nVal)); } } aBuf.clear(); bEndPos = true; } else aBuf += OUStringLiteral1(c); } if (!aBuf.isEmpty()) { bool bRes = lcl_CheckRepeatOne(aBuf, eConv, bIsRow, nVal); if (!bRes) return false; if (pRange) { if (bIsRow) { if (!bEndPos) pRange->aStart.SetRow(static_cast(nVal)); pRange->aEnd.SetRow(static_cast(nVal)); } else { if (!bEndPos) pRange->aStart.SetCol(static_cast(nVal)); pRange->aEnd.SetCol(static_cast(nVal)); } } } return true; } static void lcl_GetRepeatRangeString( const ScRange* pRange, ScDocument* pDoc, bool bIsRow, OUString& rStr ) { rStr.clear(); if (!pRange) return; const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention(); const ScAddress& rStart = pRange->aStart; const ScAddress& rEnd = pRange->aEnd; const ScRefFlags nFmt = bIsRow ? (ScRefFlags::ROW_VALID | ScRefFlags::ROW_ABS) : (ScRefFlags::COL_VALID | ScRefFlags::COL_ABS); rStr += rStart.Format(nFmt, pDoc, eConv); if ((bIsRow && rStart.Row() != rEnd.Row()) || (!bIsRow && rStart.Col() != rEnd.Col())) { rStr += ScCompiler::GetNativeSymbol(ocRange); rStr += rEnd.Format(nFmt, pDoc, eConv); } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */