office-gobmx/sw/source/uibase/utlui/numfmtlb.cxx
Caolán McNamara 59cb37a210 cid#1606900 silence bogus Overflowed integer argument
Change-Id: I227775c53ed041539ea8c6ab80827c7a6cc1db02
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171735
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Tested-by: Jenkins
2024-08-11 21:30:45 +02:00

467 lines
14 KiB
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 <i18nlangtag/lang.h>
#include <svl/numformat.hxx>
#include <svl/zformat.hxx>
#include <svl/eitem.hxx>
#include <svx/svxids.hrc>
#include <svx/numinf.hxx>
#include <svx/flagsdef.hxx>
#include <svl/itemset.hxx>
#include <osl/diagnose.h>
#include <docsh.hxx>
#include <swtypes.hxx>
#include <swmodule.hxx>
#include <view.hxx>
#include <wrtsh.hxx>
#include <numfmtlb.hxx>
#include <strings.hrc>
#include <swabstdlg.hxx>
#include <memory>
/**
* Description:
* nFormatType: Display the formats of this Type
* nDefaultFormat: Select this format and possibly insert it
*/
namespace
{
bool lcl_isSystemFormat(sal_uInt32 nDefaultFormat, SvNumberFormatter* pFormatter, LanguageType eCurLanguage)
{
const sal_uInt32 nSysNumFormat = pFormatter->GetFormatIndex(NF_NUMBER_SYSTEM, eCurLanguage);
if (nDefaultFormat == nSysNumFormat)
return true;
const sal_uInt32 nSysShortDateFormat = pFormatter->GetFormatIndex(NF_DATE_SYSTEM_SHORT, eCurLanguage);
if (nDefaultFormat == nSysShortDateFormat)
return true;
const sal_uInt32 nSysLongDateFormat = pFormatter->GetFormatIndex(NF_DATE_SYSTEM_LONG, eCurLanguage);
if (nDefaultFormat == nSysLongDateFormat)
return true;
if ( eCurLanguage != GetAppLanguage() )
return false;
if (nDefaultFormat == pFormatter->GetFormatForLanguageIfBuiltIn(nSysNumFormat, LANGUAGE_SYSTEM))
return true;
if (nDefaultFormat == pFormatter->GetFormatForLanguageIfBuiltIn(nSysShortDateFormat, LANGUAGE_SYSTEM))
return true;
if (nDefaultFormat == pFormatter->GetFormatForLanguageIfBuiltIn(nSysLongDateFormat, LANGUAGE_SYSTEM))
return true;
return false;
}
}
double SwNumFormatBase::GetDefValue(const SvNumFormatType nFormatType)
{
SvxNumValCategory nDefValue = SvxNumValCategory::Standard;
switch (nFormatType)
{
case SvNumFormatType::DATE:
case SvNumFormatType::DATE|SvNumFormatType::TIME:
nDefValue = SvxNumValCategory::Date;
break;
case SvNumFormatType::TIME:
nDefValue = SvxNumValCategory::Time;
break;
case SvNumFormatType::TEXT:
case SvNumFormatType::UNDEFINED:
nDefValue = SvxNumValCategory::Standard;
break;
case SvNumFormatType::CURRENCY:
nDefValue = SvxNumValCategory::Currency;
break;
case SvNumFormatType::PERCENT:
nDefValue = SvxNumValCategory::Percent;
break;
case SvNumFormatType::LOGICAL:
nDefValue = SvxNumValCategory::Boolean;
break;
default:
nDefValue = SvxNumValCategory::Standard;
break;
}
return fSvxNumValConst[nDefValue];
}
SwNumFormatBase::SwNumFormatBase()
: m_nStdEntry(0)
, m_nDefFormat(0)
, m_nCurrFormatType(SvNumFormatType::ALL)
, m_bOneArea(false)
, mbCurrFormatTypeNeedsInit(true)
, m_bShowLanguageControl(false)
, m_bUseAutomaticLanguage(true)
{
}
NumFormatListBox::NumFormatListBox(std::unique_ptr<weld::ComboBox> xControl)
: mxControl(std::move(xControl))
{
Init();
}
SwNumFormatTreeView::SwNumFormatTreeView(std::unique_ptr<weld::TreeView> xControl)
: mxControl(std::move(xControl))
{
Init();
}
void SwNumFormatBase::Init()
{
if (SwView *pView = GetActiveView())
m_eCurLanguage = pView->GetWrtShell().GetCurLang();
else
m_eCurLanguage = SvtSysLocale().GetLanguageTag().getLanguageType();
SetFormatType(SvNumFormatType::NUMBER);
SetDefFormat(m_nDefFormat);
}
void NumFormatListBox::Init()
{
SwNumFormatBase::Init();
mxControl->connect_changed(LINK(this, NumFormatListBox, SelectHdl));
}
void SwNumFormatTreeView::Init()
{
SwNumFormatBase::Init();
mxControl->connect_changed(LINK(this, SwNumFormatTreeView, SelectHdl));
}
void SwNumFormatBase::SetFormatType(const SvNumFormatType nFormatType)
{
if (!mbCurrFormatTypeNeedsInit &&
(m_nCurrFormatType & nFormatType)) // there are mixed formats, like for example DateTime
return;
SwView *pView = GetActiveView();
if(!pView)
return;
SwWrtShell &rSh = pView->GetWrtShell();
SvNumberFormatter* pFormatter = rSh.GetNumberFormatter();
clear(); // Remove all entries from the Listbox
NfIndexTableOffset eOffsetStart = NF_NUMBER_START;
NfIndexTableOffset eOffsetEnd = NF_NUMBER_START;
switch( nFormatType )
{
case SvNumFormatType::NUMBER:
eOffsetStart=NF_NUMBER_START;
eOffsetEnd=NF_NUMBER_END;
break;
case SvNumFormatType::PERCENT:
eOffsetStart=NF_PERCENT_START;
eOffsetEnd=NF_PERCENT_END;
break;
case SvNumFormatType::CURRENCY:
eOffsetStart=NF_CURRENCY_START;
eOffsetEnd=NF_CURRENCY_END;
break;
case SvNumFormatType::DATETIME:
eOffsetStart=NF_DATE_START;
eOffsetEnd=NF_TIME_END;
break;
case SvNumFormatType::DATE:
eOffsetStart=NF_DATE_START;
eOffsetEnd=NF_DATE_END;
break;
case SvNumFormatType::TIME:
eOffsetStart=NF_TIME_START;
eOffsetEnd=NF_TIME_END;
break;
case SvNumFormatType::SCIENTIFIC:
eOffsetStart=NF_SCIENTIFIC_START;
eOffsetEnd=NF_SCIENTIFIC_END;
break;
case SvNumFormatType::FRACTION:
eOffsetStart=NF_FRACTION_START;
eOffsetEnd=NF_FRACTION_END;
break;
case SvNumFormatType::LOGICAL:
eOffsetStart=NF_BOOLEAN;
eOffsetEnd=NF_BOOLEAN;
break;
case SvNumFormatType::TEXT:
eOffsetStart=NF_TEXT;
eOffsetEnd=NF_TEXT;
break;
case SvNumFormatType::ALL:
eOffsetStart=NF_NUMERIC_START;
eOffsetEnd = NfIndexTableOffset( NF_INDEX_TABLE_ENTRIES - 1 );
break;
default:
OSL_FAIL("what a format?");
break;
}
const SvNumberformat* pFormat;
sal_Int32 i = 0;
const Color* pCol;
double fVal = SwNumFormatBase::GetDefValue(nFormatType);
OUString sValue;
const sal_uInt32 nSysNumFormat = pFormatter->GetFormatIndex(
NF_NUMBER_SYSTEM, m_eCurLanguage );
const sal_uInt32 nSysShortDateFormat = pFormatter->GetFormatIndex(
NF_DATE_SYSTEM_SHORT, m_eCurLanguage );
const sal_uInt32 nSysLongDateFormat = pFormatter->GetFormatIndex(
NF_DATE_SYSTEM_LONG, m_eCurLanguage );
for (int nIndex = eOffsetStart; nIndex <= eOffsetEnd; ++nIndex)
{
const sal_uInt32 nFormat = pFormatter->GetFormatIndex(
static_cast<NfIndexTableOffset>(nIndex), m_eCurLanguage );
pFormat = pFormatter->GetEntry( nFormat );
if( nFormat == pFormatter->GetFormatIndex( NF_NUMBER_STANDARD,
m_eCurLanguage )
|| pFormat->GetOutputString( fVal, sValue, &pCol, pFormatter->GetNatNum(), pFormatter->GetROLanguageData() )
|| nFormatType == SvNumFormatType::UNDEFINED )
{
sValue = pFormat->GetFormatstring();
}
else if( nFormatType == SvNumFormatType::TEXT )
{
pFormatter->GetOutputString( u"\"ABC\""_ustr, nFormat, sValue, &pCol);
}
if (nFormat != nSysNumFormat &&
nFormat != nSysShortDateFormat &&
nFormat != nSysLongDateFormat)
{
append(OUString::number(nFormat), sValue);
if( nFormat == pFormatter->GetStandardFormat(
nFormatType, m_eCurLanguage ) )
m_nStdEntry = i;
++i;
}
}
append_text(SwResId(STR_DEFINE_NUMBERFORMAT));
set_active(m_nStdEntry);
m_nCurrFormatType = nFormatType;
mbCurrFormatTypeNeedsInit = false;
}
void SwNumFormatBase::SetDefFormat(const sal_uInt32 nDefaultFormat)
{
if (nDefaultFormat == NUMBERFORMAT_ENTRY_NOT_FOUND)
{
m_nDefFormat = nDefaultFormat;
return;
}
SwView *pView = GetActiveView();
if(!pView)
return;
SwWrtShell &rSh = pView->GetWrtShell();
SvNumberFormatter* pFormatter = rSh.GetNumberFormatter();
SvNumFormatType nType = pFormatter->GetType(nDefaultFormat);
SetFormatType(nType);
sal_uInt32 nFormat = pFormatter->GetFormatForLanguageIfBuiltIn(nDefaultFormat, m_eCurLanguage);
for (sal_Int32 i = 0, nCount = get_count(); i < nCount; ++i)
{
if (nFormat == get_id(i).toUInt32())
{
set_active(i);
m_nStdEntry = i;
m_nDefFormat = GetFormat();
return;
}
}
// No entry found:
OUString sValue;
const Color* pCol = nullptr;
if (nType == SvNumFormatType::TEXT)
{
pFormatter->GetOutputString(u"\"ABC\""_ustr, nDefaultFormat, sValue, &pCol);
}
else
{
pFormatter->GetOutputString(SwNumFormatBase::GetDefValue(nType), nDefaultFormat, sValue, &pCol);
}
sal_Int32 nPos = 0;
while (get_id(nPos).toUInt32() == NUMBERFORMAT_ENTRY_NOT_FOUND)
nPos++;
if ( lcl_isSystemFormat(nDefaultFormat, pFormatter, m_eCurLanguage) )
{
sValue += SwResId(RID_STR_SYSTEM);
}
insert_text(nPos, sValue); // Insert as first numeric entry
set_id(nPos, OUString::number(nDefaultFormat));
set_active(nPos);
m_nDefFormat = GetFormat();
}
sal_uInt32 NumFormatListBox::GetFormat() const
{
return mxControl->get_active_id().toUInt32();
}
sal_uInt32 SwNumFormatTreeView::GetFormat() const
{
return mxControl->get_selected_id().toUInt32();
}
void SwNumFormatBase::CallSelectHdl()
{
const sal_Int32 nPos = get_active();
OUString sDefine(SwResId( STR_DEFINE_NUMBERFORMAT ));
SwView *pView = GetActiveView();
if (!pView || nPos != get_count() - 1 || get_text(nPos) != sDefine)
return;
SwWrtShell &rSh = pView->GetWrtShell();
SvNumberFormatter* pFormatter = rSh.GetNumberFormatter();
SfxItemSetFixed<
SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_INFO,
SID_ATTR_NUMBERFORMAT_ONE_AREA, SID_ATTR_NUMBERFORMAT_ONE_AREA,
SID_ATTR_NUMBERFORMAT_NOLANGUAGE,
SID_ATTR_NUMBERFORMAT_NOLANGUAGE,
SID_ATTR_NUMBERFORMAT_ADD_AUTO,
SID_ATTR_NUMBERFORMAT_ADD_AUTO> aCoreSet( rSh.GetAttrPool() );
double fValue = SwNumFormatBase::GetDefValue(m_nCurrFormatType);
sal_uInt32 nFormat = pFormatter->GetStandardFormat( m_nCurrFormatType, m_eCurLanguage);
aCoreSet.Put( SfxUInt32Item( SID_ATTR_NUMBERFORMAT_VALUE, nFormat ));
aCoreSet.Put( SvxNumberInfoItem( pFormatter, fValue,
SID_ATTR_NUMBERFORMAT_INFO ) );
if( (SvNumFormatType::DATE | SvNumFormatType::TIME) & m_nCurrFormatType )
aCoreSet.Put(SfxBoolItem(SID_ATTR_NUMBERFORMAT_ONE_AREA, m_bOneArea));
aCoreSet.Put(SfxBoolItem(SID_ATTR_NUMBERFORMAT_NOLANGUAGE, !m_bShowLanguageControl));
aCoreSet.Put(SfxBoolItem(SID_ATTR_NUMBERFORMAT_ADD_AUTO, m_bUseAutomaticLanguage));
// force deselect to break mouse lock on selected entry
set_active(-1);
SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateNumFormatDialog(&get_widget(), aCoreSet));
if (RET_OK == pDlg->Execute())
{
const SvxNumberInfoItem* pFormatInfoItem = pView->GetDocShell()->
GetItem( SID_ATTR_NUMBERFORMAT_INFO );
if( pFormatInfoItem )
{
for ( sal_uInt32 key : pFormatInfoItem->GetDelFormats() )
pFormatter->DeleteEntry( key );
}
const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
if( const SfxUInt32Item* pFormatValueItem = pOutSet->GetItemIfSet(
SID_ATTR_NUMBERFORMAT_VALUE, false ))
{
sal_uInt32 nNumberFormat = pFormatValueItem->GetValue();
// oj #105473# change order of calls
const SvNumberformat* pFormat = pFormatter->GetEntry(nNumberFormat);
if( pFormat )
m_eCurLanguage = pFormat->GetLanguage();
// SetDefFormat uses eCurLanguage to look for if this format already in the list
SetDefFormat(nNumberFormat);
}
const SfxBoolItem* pAddAutoItem;
if( m_bShowLanguageControl && (pAddAutoItem = pOutSet->GetItemIfSet(
SID_ATTR_NUMBERFORMAT_ADD_AUTO, false)))
{
m_bUseAutomaticLanguage = pAddAutoItem->GetValue();
}
}
else
SetDefFormat(nFormat);
}
IMPL_LINK_NOARG(NumFormatListBox, SelectHdl, weld::ComboBox&, void)
{
CallSelectHdl();
}
IMPL_LINK_NOARG(SwNumFormatTreeView, SelectHdl, weld::TreeView&, void)
{
CallSelectHdl();
}
void SwNumFormatBase::clear()
{
mbCurrFormatTypeNeedsInit = true;
m_nCurrFormatType = SvNumFormatType::ALL;
}
void NumFormatListBox::clear()
{
mxControl->clear();
SwNumFormatBase::clear();
}
void SwNumFormatTreeView::clear()
{
mxControl->clear();
SwNumFormatBase::clear();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */