diff options
Diffstat (limited to 'sc/source/core/tool/userlist.cxx')
-rw-r--r-- | sc/source/core/tool/userlist.cxx | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/sc/source/core/tool/userlist.cxx b/sc/source/core/tool/userlist.cxx new file mode 100644 index 000000000..10a4de328 --- /dev/null +++ b/sc/source/core/tool/userlist.cxx @@ -0,0 +1,360 @@ +/* -*- 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 <memory> +#include <unotools/charclass.hxx> + +#include <global.hxx> +#include <userlist.hxx> +#include <unotools/localedatawrapper.hxx> +#include <unotools/transliterationwrapper.hxx> +#include <com/sun/star/i18n/Calendar2.hpp> + +#include <algorithm> + +namespace { + +class FindByName +{ + const OUString& mrName; + bool mbUpper; +public: + FindByName(const OUString& rName, bool bUpper) : mrName(rName), mbUpper(bUpper) {} + bool operator() (const ScUserListData::SubStr& r) const + { + return mbUpper ? r.maUpper == mrName : r.maReal == mrName; + } +}; + +} + +ScUserListData::SubStr::SubStr(const OUString& rReal, const OUString& rUpper) : + maReal(rReal), maUpper(rUpper) {} + +void ScUserListData::InitTokens() +{ + sal_Unicode cSep = ScGlobal::cListDelimiter; + maSubStrings.clear(); + const sal_Unicode* p = aStr.getStr(); + const sal_Unicode* p0 = p; + sal_Int32 nLen = 0; + bool bFirst = true; + for (sal_Int32 i = 0, n = aStr.getLength(); i < n; ++i, ++p, ++nLen) + { + if (bFirst) + { + // very first character, or the first character after a separator. + p0 = p; + nLen = 0; + bFirst = false; + } + if (*p == cSep) + { + if (nLen) + { + OUString aSub(p0, nLen); + OUString aUpStr = ScGlobal::getCharClass().uppercase(aSub); + maSubStrings.emplace_back(aSub, aUpStr); + } + bFirst = true; + } + } + + if (nLen) + { + OUString aSub(p0, nLen); + OUString aUpStr = ScGlobal::getCharClass().uppercase(aSub); + maSubStrings.emplace_back(aSub, aUpStr); + } +} + +ScUserListData::ScUserListData(const OUString& rStr) : + aStr(rStr) +{ + InitTokens(); +} + +ScUserListData::ScUserListData(const ScUserListData& rData) : + aStr(rData.aStr) +{ + InitTokens(); +} + +ScUserListData::~ScUserListData() +{ +} + +void ScUserListData::SetString( const OUString& rStr ) +{ + aStr = rStr; + InitTokens(); +} + +size_t ScUserListData::GetSubCount() const +{ + return maSubStrings.size(); +} + +bool ScUserListData::GetSubIndex(const OUString& rSubStr, sal_uInt16& rIndex, bool& bMatchCase) const +{ + // First, case sensitive search. + SubStringsType::const_iterator itr = ::std::find_if( + maSubStrings.begin(), maSubStrings.end(), FindByName(rSubStr, false)); + if (itr != maSubStrings.end()) + { + rIndex = ::std::distance(maSubStrings.begin(), itr); + bMatchCase = true; + return true; + } + + // When that fails, do a case insensitive search. + OUString aUpStr = ScGlobal::getCharClass().uppercase(rSubStr); + itr = ::std::find_if( + maSubStrings.begin(), maSubStrings.end(), FindByName(aUpStr, true)); + if (itr != maSubStrings.end()) + { + rIndex = ::std::distance(maSubStrings.begin(), itr); + bMatchCase = false; + return true; + } + bMatchCase = false; + return false; +} + +OUString ScUserListData::GetSubStr(sal_uInt16 nIndex) const +{ + if (nIndex < maSubStrings.size()) + return maSubStrings[nIndex].maReal; + else + return OUString(); +} + +sal_Int32 ScUserListData::Compare(const OUString& rSubStr1, const OUString& rSubStr2) const +{ + sal_uInt16 nIndex1, nIndex2; + bool bMatchCase; + bool bFound1 = GetSubIndex(rSubStr1, nIndex1, bMatchCase); + bool bFound2 = GetSubIndex(rSubStr2, nIndex2, bMatchCase); + if (bFound1) + { + if (bFound2) + { + if (nIndex1 < nIndex2) + return -1; + else if (nIndex1 > nIndex2) + return 1; + else + return 0; + } + else + return -1; + } + else if (bFound2) + return 1; + else + return ScGlobal::GetCaseTransliteration().compareString( rSubStr1, rSubStr2 ); +} + +sal_Int32 ScUserListData::ICompare(const OUString& rSubStr1, const OUString& rSubStr2) const +{ + sal_uInt16 nIndex1, nIndex2; + bool bMatchCase; + bool bFound1 = GetSubIndex(rSubStr1, nIndex1, bMatchCase); + bool bFound2 = GetSubIndex(rSubStr2, nIndex2, bMatchCase); + if (bFound1) + { + if (bFound2) + { + if (nIndex1 < nIndex2) + return -1; + else if (nIndex1 > nIndex2) + return 1; + else + return 0; + } + else + return -1; + } + else if (bFound2) + return 1; + else + return ScGlobal::GetTransliteration().compareString( rSubStr1, rSubStr2 ); +} + +ScUserList::ScUserList() +{ + using namespace ::com::sun::star; + + sal_Unicode cDelimiter = ScGlobal::cListDelimiter; + uno::Sequence< i18n::CalendarItem2 > xCal; + + const uno::Sequence< i18n::Calendar2 > xCalendars( + ScGlobal::getLocaleData().getAllCalendars() ); + + for ( const auto& rCalendar : xCalendars ) + { + xCal = rCalendar.Days; + if ( xCal.hasElements() ) + { + OUStringBuffer aDayShortBuf(32), aDayLongBuf(64); + sal_Int32 i; + sal_Int32 nLen = xCal.getLength(); + sal_Int16 nStart = sal::static_int_cast<sal_Int16>(nLen); + while (nStart > 0) + { + if (xCal[--nStart].ID == rCalendar.StartOfWeek) + break; + } + sal_Int16 nLast = sal::static_int_cast<sal_Int16>( (nStart + nLen - 1) % nLen ); + for (i = nStart; i != nLast; i = (i+1) % nLen) + { + aDayShortBuf.append(xCal[i].AbbrevName); + aDayShortBuf.append(cDelimiter); + aDayLongBuf.append(xCal[i].FullName); + aDayLongBuf.append(cDelimiter); + } + aDayShortBuf.append(xCal[i].AbbrevName); + aDayLongBuf.append(xCal[i].FullName); + + OUString aDayShort = aDayShortBuf.makeStringAndClear(); + OUString aDayLong = aDayLongBuf.makeStringAndClear(); + + if ( !HasEntry( aDayShort ) ) + maData.push_back( std::make_unique<ScUserListData>( aDayShort )); + if ( !HasEntry( aDayLong ) ) + maData.push_back( std::make_unique<ScUserListData>( aDayLong )); + } + + xCal = rCalendar.Months; + if ( xCal.hasElements() ) + { + OUStringBuffer aMonthShortBuf(128), aMonthLongBuf(128); + sal_Int32 i; + sal_Int32 nLen = xCal.getLength() - 1; + for (i = 0; i < nLen; i++) + { + aMonthShortBuf.append(xCal[i].AbbrevName); + aMonthShortBuf.append(cDelimiter); + aMonthLongBuf.append(xCal[i].FullName); + aMonthLongBuf.append(cDelimiter); + } + aMonthShortBuf.append(xCal[i].AbbrevName); + aMonthLongBuf.append(xCal[i].FullName); + + OUString aMonthShort = aMonthShortBuf.makeStringAndClear(); + OUString aMonthLong = aMonthLongBuf.makeStringAndClear(); + + if ( !HasEntry( aMonthShort ) ) + maData.push_back( std::make_unique<ScUserListData>( aMonthShort )); + if ( !HasEntry( aMonthLong ) ) + maData.push_back( std::make_unique<ScUserListData>( aMonthLong )); + } + } +} + +ScUserList::ScUserList(const ScUserList& rOther) +{ + for (const std::unique_ptr<ScUserListData>& rData : rOther.maData) + maData.push_back(std::make_unique<ScUserListData>(*rData)); +} + +const ScUserListData* ScUserList::GetData(const OUString& rSubStr) const +{ + const ScUserListData* pFirstCaseInsensitive = nullptr; + sal_uInt16 nIndex; + bool bMatchCase = false; + + for (const auto& rxItem : maData) + { + if (rxItem->GetSubIndex(rSubStr, nIndex, bMatchCase)) + { + if (bMatchCase) + return rxItem.get(); + if (!pFirstCaseInsensitive) + pFirstCaseInsensitive = rxItem.get(); + } + } + + return pFirstCaseInsensitive; +} + +const ScUserListData& ScUserList::operator[](size_t nIndex) const +{ + return *maData[nIndex]; +} + +ScUserListData& ScUserList::operator[](size_t nIndex) +{ + return *maData[nIndex]; +} + +ScUserList& ScUserList::operator=( const ScUserList& rOther ) +{ + maData.clear(); + for (const std::unique_ptr<ScUserListData>& rData : rOther.maData) + maData.push_back(std::make_unique<ScUserListData>(*rData)); + return *this; +} + +bool ScUserList::operator==( const ScUserList& r ) const +{ + return std::equal(maData.begin(), maData.end(), r.maData.begin(), r.maData.end(), + [](const std::unique_ptr<ScUserListData>& lhs, const std::unique_ptr<ScUserListData>& rhs) { + return (lhs->GetString() == rhs->GetString()) && (lhs->GetSubCount() == rhs->GetSubCount()); + }); +} + +bool ScUserList::operator!=( const ScUserList& r ) const +{ + return !operator==( r ); +} + +bool ScUserList::HasEntry( std::u16string_view rStr ) const +{ + return ::std::any_of(maData.begin(), maData.end(), + [&] (std::unique_ptr<ScUserListData> const& pData) + { return pData->GetString() == rStr; } ); +} + +ScUserList::iterator ScUserList::begin() +{ + return maData.begin(); +} + +void ScUserList::clear() +{ + maData.clear(); +} + +size_t ScUserList::size() const +{ + return maData.size(); +} + +void ScUserList::push_back(ScUserListData* p) +{ + maData.push_back(std::unique_ptr<ScUserListData>(p)); +} + +void ScUserList::erase(const iterator& itr) +{ + maData.erase(itr); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |