LibreOffice Module sc (master) 1
userlist.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <memory>
22
23#include <global.hxx>
24#include <userlist.hxx>
27#include <com/sun/star/i18n/Calendar2.hpp>
28
29#include <algorithm>
30#include <utility>
31
32namespace {
33
34class FindByName
35{
36 const OUString& mrName;
37 bool mbUpper;
38public:
39 FindByName(const OUString& rName, bool bUpper) : mrName(rName), mbUpper(bUpper) {}
40 bool operator() (const ScUserListData::SubStr& r) const
41 {
42 return mbUpper ? r.maUpper == mrName : r.maReal == mrName;
43 }
44};
45
46}
47
48ScUserListData::SubStr::SubStr(OUString aReal, OUString aUpper) :
49 maReal(std::move(aReal)), maUpper(std::move(aUpper)) {}
50
52{
54 maSubStrings.clear();
55 const sal_Unicode* p = aStr.getStr();
56 const sal_Unicode* p0 = p;
57 sal_Int32 nLen = 0;
58 bool bFirst = true;
59 for (sal_Int32 i = 0, n = aStr.getLength(); i < n; ++i, ++p, ++nLen)
60 {
61 if (bFirst)
62 {
63 // very first character, or the first character after a separator.
64 p0 = p;
65 nLen = 0;
66 bFirst = false;
67 }
68 if (*p == cSep)
69 {
70 if (nLen)
71 {
72 OUString aSub(p0, nLen);
73 OUString aUpStr = ScGlobal::getCharClass().uppercase(aSub);
74 maSubStrings.emplace_back(aSub, aUpStr);
75 }
76 bFirst = true;
77 }
78 }
79
80 if (nLen)
81 {
82 OUString aSub(p0, nLen);
83 OUString aUpStr = ScGlobal::getCharClass().uppercase(aSub);
84 maSubStrings.emplace_back(aSub, aUpStr);
85 }
86}
87
89 aStr(std::move(_aStr))
90{
91 InitTokens();
92}
93
95 aStr(rData.aStr)
96{
97 InitTokens();
98}
99
101{
102}
103
104void ScUserListData::SetString( const OUString& rStr )
105{
106 aStr = rStr;
107 InitTokens();
108}
109
111{
112 return maSubStrings.size();
113}
114
115bool ScUserListData::GetSubIndex(const OUString& rSubStr, sal_uInt16& rIndex, bool& bMatchCase) const
116{
117 // First, case sensitive search.
118 SubStringsType::const_iterator itr = ::std::find_if(
119 maSubStrings.begin(), maSubStrings.end(), FindByName(rSubStr, false));
120 if (itr != maSubStrings.end())
121 {
122 rIndex = ::std::distance(maSubStrings.begin(), itr);
123 bMatchCase = true;
124 return true;
125 }
126
127 // When that fails, do a case insensitive search.
128 OUString aUpStr = ScGlobal::getCharClass().uppercase(rSubStr);
129 itr = ::std::find_if(
130 maSubStrings.begin(), maSubStrings.end(), FindByName(aUpStr, true));
131 if (itr != maSubStrings.end())
132 {
133 rIndex = ::std::distance(maSubStrings.begin(), itr);
134 bMatchCase = false;
135 return true;
136 }
137 bMatchCase = false;
138 return false;
139}
140
141OUString ScUserListData::GetSubStr(sal_uInt16 nIndex) const
142{
143 if (nIndex < maSubStrings.size())
144 return maSubStrings[nIndex].maReal;
145 else
146 return OUString();
147}
148
149sal_Int32 ScUserListData::Compare(const OUString& rSubStr1, const OUString& rSubStr2) const
150{
151 sal_uInt16 nIndex1, nIndex2;
152 bool bMatchCase;
153 bool bFound1 = GetSubIndex(rSubStr1, nIndex1, bMatchCase);
154 bool bFound2 = GetSubIndex(rSubStr2, nIndex2, bMatchCase);
155 if (bFound1)
156 {
157 if (bFound2)
158 {
159 if (nIndex1 < nIndex2)
160 return -1;
161 else if (nIndex1 > nIndex2)
162 return 1;
163 else
164 return 0;
165 }
166 else
167 return -1;
168 }
169 else if (bFound2)
170 return 1;
171 else
172 return ScGlobal::GetCaseTransliteration().compareString( rSubStr1, rSubStr2 );
173}
174
175sal_Int32 ScUserListData::ICompare(const OUString& rSubStr1, const OUString& rSubStr2) const
176{
177 sal_uInt16 nIndex1, nIndex2;
178 bool bMatchCase;
179 bool bFound1 = GetSubIndex(rSubStr1, nIndex1, bMatchCase);
180 bool bFound2 = GetSubIndex(rSubStr2, nIndex2, bMatchCase);
181 if (bFound1)
182 {
183 if (bFound2)
184 {
185 if (nIndex1 < nIndex2)
186 return -1;
187 else if (nIndex1 > nIndex2)
188 return 1;
189 else
190 return 0;
191 }
192 else
193 return -1;
194 }
195 else if (bFound2)
196 return 1;
197 else
198 return ScGlobal::GetTransliteration().compareString( rSubStr1, rSubStr2 );
199}
200
202{
203 using namespace ::com::sun::star;
204
206 uno::Sequence< i18n::CalendarItem2 > xCal;
207
208 const uno::Sequence< i18n::Calendar2 > xCalendars(
209 ScGlobal::getLocaleData().getAllCalendars() );
210
211 for ( const auto& rCalendar : xCalendars )
212 {
213 xCal = rCalendar.Days;
214 if ( xCal.hasElements() )
215 {
216 OUStringBuffer aDayShortBuf(32), aDayLongBuf(64);
217 sal_Int32 i;
218 sal_Int32 nLen = xCal.getLength();
219 sal_Int16 nStart = sal::static_int_cast<sal_Int16>(nLen);
220 while (nStart > 0)
221 {
222 if (xCal[--nStart].ID == rCalendar.StartOfWeek)
223 break;
224 }
225 sal_Int16 nLast = sal::static_int_cast<sal_Int16>( (nStart + nLen - 1) % nLen );
226 for (i = nStart; i != nLast; i = (i+1) % nLen)
227 {
228 aDayShortBuf.append(xCal[i].AbbrevName);
229 aDayShortBuf.append(cDelimiter);
230 aDayLongBuf.append(xCal[i].FullName);
231 aDayLongBuf.append(cDelimiter);
232 }
233 aDayShortBuf.append(xCal[i].AbbrevName);
234 aDayLongBuf.append(xCal[i].FullName);
235
236 OUString aDayShort = aDayShortBuf.makeStringAndClear();
237 OUString aDayLong = aDayLongBuf.makeStringAndClear();
238
239 if ( !HasEntry( aDayShort ) )
240 maData.push_back( std::make_unique<ScUserListData>( aDayShort ));
241 if ( !HasEntry( aDayLong ) )
242 maData.push_back( std::make_unique<ScUserListData>( aDayLong ));
243 }
244
245 xCal = rCalendar.Months;
246 if ( xCal.hasElements() )
247 {
248 OUStringBuffer aMonthShortBuf(128), aMonthLongBuf(128);
249 sal_Int32 i;
250 sal_Int32 nLen = xCal.getLength() - 1;
251 for (i = 0; i < nLen; i++)
252 {
253 aMonthShortBuf.append(xCal[i].AbbrevName);
254 aMonthShortBuf.append(cDelimiter);
255 aMonthLongBuf.append(xCal[i].FullName);
256 aMonthLongBuf.append(cDelimiter);
257 }
258 aMonthShortBuf.append(xCal[i].AbbrevName);
259 aMonthLongBuf.append(xCal[i].FullName);
260
261 OUString aMonthShort = aMonthShortBuf.makeStringAndClear();
262 OUString aMonthLong = aMonthLongBuf.makeStringAndClear();
263
264 if ( !HasEntry( aMonthShort ) )
265 maData.push_back( std::make_unique<ScUserListData>( aMonthShort ));
266 if ( !HasEntry( aMonthLong ) )
267 maData.push_back( std::make_unique<ScUserListData>( aMonthLong ));
268 }
269 }
270}
271
273{
274 for (const std::unique_ptr<ScUserListData>& rData : rOther.maData)
275 maData.push_back(std::make_unique<ScUserListData>(*rData));
276}
277
278const ScUserListData* ScUserList::GetData(const OUString& rSubStr) const
279{
280 const ScUserListData* pFirstCaseInsensitive = nullptr;
281 sal_uInt16 nIndex;
282 bool bMatchCase = false;
283
284 for (const auto& rxItem : maData)
285 {
286 if (rxItem->GetSubIndex(rSubStr, nIndex, bMatchCase))
287 {
288 if (bMatchCase)
289 return rxItem.get();
290 if (!pFirstCaseInsensitive)
291 pFirstCaseInsensitive = rxItem.get();
292 }
293 }
294
295 return pFirstCaseInsensitive;
296}
297
298const ScUserListData& ScUserList::operator[](size_t nIndex) const
299{
300 return *maData[nIndex];
301}
302
304{
305 return *maData[nIndex];
306}
307
309{
310 maData.clear();
311 for (const std::unique_ptr<ScUserListData>& rData : rOther.maData)
312 maData.push_back(std::make_unique<ScUserListData>(*rData));
313 return *this;
314}
315
316bool ScUserList::operator==( const ScUserList& r ) const
317{
318 return std::equal(maData.begin(), maData.end(), r.maData.begin(), r.maData.end(),
319 [](const std::unique_ptr<ScUserListData>& lhs, const std::unique_ptr<ScUserListData>& rhs) {
320 return (lhs->GetString() == rhs->GetString()) && (lhs->GetSubCount() == rhs->GetSubCount());
321 });
322}
323
324bool ScUserList::operator!=( const ScUserList& r ) const
325{
326 return !operator==( r );
327}
328
329bool ScUserList::HasEntry( std::u16string_view rStr ) const
330{
331 return ::std::any_of(maData.begin(), maData.end(),
332 [&] (std::unique_ptr<ScUserListData> const& pData)
333 { return pData->GetString() == rStr; } );
334}
335
337{
338 return maData.begin();
339}
340
342{
343 maData.clear();
344}
345
346size_t ScUserList::size() const
347{
348 return maData.size();
349}
350
352{
353 maData.push_back(std::unique_ptr<ScUserListData>(p));
354}
355
357{
358 maData.erase(itr);
359}
360
361/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString uppercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
static constexpr sal_Unicode cListDelimiter
Definition: global.hxx:560
::utl::TransliterationWrapper & GetCaseTransliteration()
Definition: global.cxx:1036
static SC_DLLPUBLIC ::utl::TransliterationWrapper & GetTransliteration()
Definition: global.cxx:1024
static SC_DLLPUBLIC const LocaleDataWrapper & getLocaleData()
Definition: global.cxx:1053
static SC_DLLPUBLIC const CharClass & getCharClass()
Definition: global.cxx:1062
Stores individual user-defined sort list.
Definition: userlist.hxx:33
SubStringsType maSubStrings
Definition: userlist.hxx:44
OUString GetSubStr(sal_uInt16 nIndex) const
Definition: userlist.cxx:141
sal_Int32 Compare(const OUString &rSubStr1, const OUString &rSubStr2) const
Definition: userlist.cxx:149
OUString aStr
Definition: userlist.hxx:45
sal_Int32 ICompare(const OUString &rSubStr1, const OUString &rSubStr2) const
Definition: userlist.cxx:175
size_t GetSubCount() const
Definition: userlist.cxx:110
SAL_DLLPRIVATE void InitTokens()
Definition: userlist.cxx:51
void SetString(const OUString &rStr)
Definition: userlist.cxx:104
bool GetSubIndex(const OUString &rSubStr, sal_uInt16 &rIndex, bool &bMatchCase) const
Definition: userlist.cxx:115
ScUserListData(OUString aStr)
Definition: userlist.cxx:88
Collection of user-defined sort lists.
Definition: userlist.hxx:67
void erase(const iterator &itr)
Definition: userlist.cxx:356
void clear()
Definition: userlist.cxx:341
DataType maData
Definition: userlist.hxx:69
void push_back(ScUserListData *p)
Definition: userlist.cxx:351
bool operator!=(const ScUserList &r) const
Definition: userlist.cxx:324
bool HasEntry(std::u16string_view rStr) const
If the list in rStr is already inserted.
Definition: userlist.cxx:329
iterator begin()
Definition: userlist.cxx:336
size_t size() const
Definition: userlist.cxx:346
const ScUserListData & operator[](size_t nIndex) const
Definition: userlist.cxx:298
DataType::iterator iterator
Definition: userlist.hxx:72
bool operator==(const ScUserList &r) const
Definition: userlist.cxx:316
ScUserList & operator=(const ScUserList &r)
Definition: userlist.cxx:308
const ScUserListData * GetData(const OUString &rSubStr) const
Definition: userlist.cxx:278
sal_Int32 compareString(const OUString &rStr1, const OUString &rStr2) const
sal_Int32 nIndex
void * p
sal_Int64 n
aStr
std::unique_ptr< sal_Int32[]> pData
int i
SubStr(OUString aReal, OUString aUpper)
Definition: userlist.cxx:48
const sal_Unicode cDelimiter
Definition: tpusrlst.cxx:45
sal_uInt16 sal_Unicode