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>
21 #include <unotools/charclass.hxx>
22 
23 #include <global.hxx>
24 #include <userlist.hxx>
28 
29 #include <algorithm>
30 
31 namespace {
32 
33 class FindByName
34 {
35  const OUString& mrName;
36  bool mbUpper;
37 public:
38  FindByName(const OUString& rName, bool bUpper) : mrName(rName), mbUpper(bUpper) {}
39  bool operator() (const ScUserListData::SubStr& r) const
40  {
41  return mbUpper ? r.maUpper == mrName : r.maReal == mrName;
42  }
43 };
44 
45 }
46 
47 ScUserListData::SubStr::SubStr(const OUString& rReal, const OUString& rUpper) :
48  maReal(rReal), maUpper(rUpper) {}
49 
51 {
53  maSubStrings.clear();
54  const sal_Unicode* p = aStr.getStr();
55  const sal_Unicode* p0 = p;
56  sal_Int32 nLen = 0;
57  bool bFirst = true;
58  for (sal_Int32 i = 0, n = aStr.getLength(); i < n; ++i, ++p, ++nLen)
59  {
60  if (bFirst)
61  {
62  // very first character, or the first character after a separator.
63  p0 = p;
64  nLen = 0;
65  bFirst = false;
66  }
67  if (*p == cSep)
68  {
69  if (nLen)
70  {
71  OUString aSub(p0, nLen);
72  OUString aUpStr = ScGlobal::getCharClassPtr()->uppercase(aSub);
73  maSubStrings.emplace_back(aSub, aUpStr);
74  }
75  bFirst = true;
76  }
77  }
78 
79  if (nLen)
80  {
81  OUString aSub(p0, nLen);
82  OUString aUpStr = ScGlobal::getCharClassPtr()->uppercase(aSub);
83  maSubStrings.emplace_back(aSub, aUpStr);
84  }
85 }
86 
87 ScUserListData::ScUserListData(const OUString& rStr) :
88  aStr(rStr)
89 {
90  InitTokens();
91 }
92 
94  aStr(rData.aStr)
95 {
96  InitTokens();
97 }
98 
100 {
101 }
102 
103 void ScUserListData::SetString( const OUString& rStr )
104 {
105  aStr = rStr;
106  InitTokens();
107 }
108 
110 {
111  return maSubStrings.size();
112 }
113 
114 bool ScUserListData::GetSubIndex(const OUString& rSubStr, sal_uInt16& rIndex, bool& bMatchCase) const
115 {
116  // First, case sensitive search.
117  SubStringsType::const_iterator itr = ::std::find_if(
118  maSubStrings.begin(), maSubStrings.end(), FindByName(rSubStr, false));
119  if (itr != maSubStrings.end())
120  {
121  rIndex = ::std::distance(maSubStrings.begin(), itr);
122  bMatchCase = true;
123  return true;
124  }
125 
126  // When that fails, do a case insensitive search.
127  OUString aUpStr = ScGlobal::getCharClassPtr()->uppercase(rSubStr);
128  itr = ::std::find_if(
129  maSubStrings.begin(), maSubStrings.end(), FindByName(aUpStr, true));
130  if (itr != maSubStrings.end())
131  {
132  rIndex = ::std::distance(maSubStrings.begin(), itr);
133  bMatchCase = false;
134  return true;
135  }
136  bMatchCase = false;
137  return false;
138 }
139 
140 OUString ScUserListData::GetSubStr(sal_uInt16 nIndex) const
141 {
142  if (nIndex < maSubStrings.size())
143  return maSubStrings[nIndex].maReal;
144  else
145  return OUString();
146 }
147 
148 sal_Int32 ScUserListData::Compare(const OUString& rSubStr1, const OUString& rSubStr2) const
149 {
150  sal_uInt16 nIndex1, nIndex2;
151  bool bMatchCase;
152  bool bFound1 = GetSubIndex(rSubStr1, nIndex1, bMatchCase);
153  bool bFound2 = GetSubIndex(rSubStr2, nIndex2, bMatchCase);
154  if (bFound1)
155  {
156  if (bFound2)
157  {
158  if (nIndex1 < nIndex2)
159  return -1;
160  else if (nIndex1 > nIndex2)
161  return 1;
162  else
163  return 0;
164  }
165  else
166  return -1;
167  }
168  else if (bFound2)
169  return 1;
170  else
171  return ScGlobal::GetCaseTransliteration()->compareString( rSubStr1, rSubStr2 );
172 }
173 
174 sal_Int32 ScUserListData::ICompare(const OUString& rSubStr1, const OUString& rSubStr2) const
175 {
176  sal_uInt16 nIndex1, nIndex2;
177  bool bMatchCase;
178  bool bFound1 = GetSubIndex(rSubStr1, nIndex1, bMatchCase);
179  bool bFound2 = GetSubIndex(rSubStr2, nIndex2, bMatchCase);
180  if (bFound1)
181  {
182  if (bFound2)
183  {
184  if (nIndex1 < nIndex2)
185  return -1;
186  else if (nIndex1 > nIndex2)
187  return 1;
188  else
189  return 0;
190  }
191  else
192  return -1;
193  }
194  else if (bFound2)
195  return 1;
196  else
197  return ScGlobal::GetpTransliteration()->compareString( rSubStr1, rSubStr2 );
198 }
199 
201 {
202  using namespace ::com::sun::star;
203 
205  uno::Sequence< i18n::CalendarItem2 > xCal;
206 
207  const uno::Sequence< i18n::Calendar2 > xCalendars(
208  ScGlobal::getLocaleDataPtr()->getAllCalendars() );
209 
210  for ( const auto& rCalendar : xCalendars )
211  {
212  xCal = rCalendar.Days;
213  if ( xCal.hasElements() )
214  {
215  OUStringBuffer aDayShortBuf(32), aDayLongBuf(64);
216  sal_Int32 i;
217  sal_Int32 nLen = xCal.getLength();
218  sal_Int16 nStart = sal::static_int_cast<sal_Int16>(nLen);
219  while (nStart > 0)
220  {
221  if (xCal[--nStart].ID == rCalendar.StartOfWeek)
222  break;
223  }
224  sal_Int16 nLast = sal::static_int_cast<sal_Int16>( (nStart + nLen - 1) % nLen );
225  for (i = nStart; i != nLast; i = (i+1) % nLen)
226  {
227  aDayShortBuf.append(xCal[i].AbbrevName);
228  aDayShortBuf.append(cDelimiter);
229  aDayLongBuf.append(xCal[i].FullName);
230  aDayLongBuf.append(cDelimiter);
231  }
232  aDayShortBuf.append(xCal[i].AbbrevName);
233  aDayLongBuf.append(xCal[i].FullName);
234 
235  OUString aDayShort = aDayShortBuf.makeStringAndClear();
236  OUString aDayLong = aDayLongBuf.makeStringAndClear();
237 
238  if ( !HasEntry( aDayShort ) )
239  maData.push_back( std::make_unique<ScUserListData>( aDayShort ));
240  if ( !HasEntry( aDayLong ) )
241  maData.push_back( std::make_unique<ScUserListData>( aDayLong ));
242  }
243 
244  xCal = rCalendar.Months;
245  if ( xCal.hasElements() )
246  {
247  OUStringBuffer aMonthShortBuf(128), aMonthLongBuf(128);
248  sal_Int32 i;
249  sal_Int32 nLen = xCal.getLength() - 1;
250  for (i = 0; i < nLen; i++)
251  {
252  aMonthShortBuf.append(xCal[i].AbbrevName);
253  aMonthShortBuf.append(cDelimiter);
254  aMonthLongBuf.append(xCal[i].FullName);
255  aMonthLongBuf.append(cDelimiter);
256  }
257  aMonthShortBuf.append(xCal[i].AbbrevName);
258  aMonthLongBuf.append(xCal[i].FullName);
259 
260  OUString aMonthShort = aMonthShortBuf.makeStringAndClear();
261  OUString aMonthLong = aMonthLongBuf.makeStringAndClear();
262 
263  if ( !HasEntry( aMonthShort ) )
264  maData.push_back( std::make_unique<ScUserListData>( aMonthShort ));
265  if ( !HasEntry( aMonthLong ) )
266  maData.push_back( std::make_unique<ScUserListData>( aMonthLong ));
267  }
268  }
269 }
270 
272 {
273  for (const std::unique_ptr<ScUserListData>& rData : rOther.maData)
274  maData.push_back(std::make_unique<ScUserListData>(*rData));
275 }
276 
277 const ScUserListData* ScUserList::GetData(const OUString& rSubStr) const
278 {
279  const ScUserListData* pFirstCaseInsensitive = nullptr;
280  sal_uInt16 nIndex;
281  bool bMatchCase = false;
282 
283  for (const auto& rxItem : maData)
284  {
285  if (rxItem->GetSubIndex(rSubStr, nIndex, bMatchCase))
286  {
287  if (bMatchCase)
288  return rxItem.get();
289  if (!pFirstCaseInsensitive)
290  pFirstCaseInsensitive = rxItem.get();
291  }
292  }
293 
294  return pFirstCaseInsensitive;
295 }
296 
297 const ScUserListData& ScUserList::operator[](size_t nIndex) const
298 {
299  return *maData[nIndex];
300 }
301 
303 {
304  return *maData[nIndex];
305 }
306 
308 {
309  maData.clear();
310  for (const std::unique_ptr<ScUserListData>& rData : rOther.maData)
311  maData.push_back(std::make_unique<ScUserListData>(*rData));
312  return *this;
313 }
314 
315 bool ScUserList::operator==( const ScUserList& r ) const
316 {
317  return std::equal(maData.begin(), maData.end(), r.maData.begin(), r.maData.end(),
318  [](const std::unique_ptr<ScUserListData>& lhs, const std::unique_ptr<ScUserListData>& rhs) {
319  return (lhs->GetString() == rhs->GetString()) && (lhs->GetSubCount() == rhs->GetSubCount());
320  });
321 }
322 
323 bool ScUserList::operator!=( const ScUserList& r ) const
324 {
325  return !operator==( r );
326 }
327 
328 bool ScUserList::HasEntry( const OUString& rStr ) const
329 {
330  return ::std::any_of(maData.begin(), maData.end(),
331  [&] (std::unique_ptr<ScUserListData> const& pData)
332  { return pData->GetString() == rStr; } );
333 }
334 
336 {
337  return maData.begin();
338 }
339 
341 {
342  maData.clear();
343 }
344 
345 size_t ScUserList::size() const
346 {
347  return maData.size();
348 }
349 
351 {
352  maData.push_back(std::unique_ptr<ScUserListData>(p));
353 }
354 
355 void ScUserList::erase(const iterator& itr)
356 {
357  maData.erase(itr);
358 }
359 
360 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Collection of user-defined sort lists.
Definition: userlist.hxx:66
sal_Int32 Compare(const OUString &rSubStr1, const OUString &rSubStr2) const
Definition: userlist.cxx:148
sal_Int32 nIndex
sal_Int32 compareString(const OUString &rStr1, const OUString &rStr2) const
#define ID
static SC_DLLPUBLIC::utl::TransliterationWrapper * GetpTransliteration()
Definition: global.cxx:976
std::unique_ptr< ContentProperties > pData
SubStr(const OUString &rReal, const OUString &rUpper)
Definition: userlist.cxx:47
::utl::TransliterationWrapper * GetCaseTransliteration()
Definition: global.cxx:988
sal_Int64 n
const ContentProperties & rData
DataType maData
Definition: userlist.hxx:69
size_t size() const
Definition: userlist.cxx:345
const sal_Unicode cDelimiter
Definition: tpusrlst.cxx:44
sal_Int32 ICompare(const OUString &rSubStr1, const OUString &rSubStr2) const
Definition: userlist.cxx:174
OUString aStr
Definition: userlist.hxx:45
bool GetSubIndex(const OUString &rSubStr, sal_uInt16 &rIndex, bool &bMatchCase) const
Definition: userlist.cxx:114
bool HasEntry(const OUString &rStr) const
If the list in rStr is already inserted.
Definition: userlist.cxx:328
sal_uInt16 sal_Unicode
void push_back(ScUserListData *p)
Definition: userlist.cxx:350
Stores individual user-defined sort list.
Definition: userlist.hxx:33
void erase(const iterator &itr)
Definition: userlist.cxx:355
static constexpr sal_Unicode cListDelimiter
Definition: global.hxx:549
size_t GetSubCount() const
Definition: userlist.cxx:109
bool operator==(const ScUserList &r) const
Definition: userlist.cxx:315
int i
OUString uppercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
DataType::iterator iterator
Definition: userlist.hxx:71
static SC_DLLPUBLIC const LocaleDataWrapper * getLocaleDataPtr()
Definition: global.cxx:1001
ScUserList & operator=(const ScUserList &r)
Definition: userlist.cxx:307
SubStringsType maSubStrings
Definition: userlist.hxx:44
const ScUserListData & operator[](size_t nIndex) const
Definition: userlist.cxx:297
bool operator!=(const ScUserList &r) const
Definition: userlist.cxx:323
void clear()
Definition: userlist.cxx:340
static SC_DLLPUBLIC const CharClass * getCharClassPtr()
Definition: global.cxx:1010
iterator begin()
Definition: userlist.cxx:335
void * p
ScUserListData(const OUString &rStr)
Definition: userlist.cxx:87
SAL_DLLPRIVATE void InitTokens()
Definition: userlist.cxx:50
aStr
void SetString(const OUString &rStr)
Definition: userlist.cxx:103
OUString GetSubStr(sal_uInt16 nIndex) const
Definition: userlist.cxx:140
const ScUserListData * GetData(const OUString &rSubStr) const
Definition: userlist.cxx:277