1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svl.hxx"
26
27 #include <svl/slstitm.hxx>
28 #include <svl/poolitem.hxx>
29 #include <com/sun/star/uno/Any.hxx>
30 #include <com/sun/star/uno/Sequence.hxx>
31 #include <tools/stream.hxx>
32
33 // STATIC DATA -----------------------------------------------------------
34
35 DBG_NAME(SfxStringListItem)
36
37 // -----------------------------------------------------------------------
38
39 TYPEINIT1_AUTOFACTORY(SfxStringListItem, SfxPoolItem);
40
41 class SfxImpStringList
42 {
43 public:
44 sal_uInt16 nRefCount;
45 List aList;
46
SfxImpStringList()47 SfxImpStringList() { nRefCount = 1; }
48 ~SfxImpStringList();
49 void Sort( sal_Bool bAscending, List* );
50 };
51
52 //------------------------------------------------------------------------
53
~SfxImpStringList()54 SfxImpStringList::~SfxImpStringList()
55 {
56 DBG_ASSERT(nRefCount!=0xffff,"ImpList already deleted");
57 String* pStr = (String*)aList.First();
58 while( pStr )
59 {
60 delete pStr;
61 pStr = (String*)aList.Next();
62 }
63 nRefCount = 0xffff;
64 }
65
66 //------------------------------------------------------------------------
67
Sort(sal_Bool bAscending,List * pParallelList)68 void SfxImpStringList::Sort( sal_Bool bAscending, List* pParallelList )
69 {
70 DBG_ASSERT(!pParallelList || pParallelList->Count() >= aList.Count(),"Sort:ParallelList too small");
71 sal_uLong nCount = aList.Count();
72 if( nCount > 1 )
73 {
74 nCount -= 2;
75 // Bubble Dir Einen
76 sal_Bool bSwapped = sal_True;
77 while( bSwapped )
78 {
79 bSwapped = sal_False;
80 for( sal_uLong nCur = 0; nCur <= nCount; nCur++ )
81 {
82 String* pStr1 = (String*)aList.GetObject( nCur );
83 String* pStr2 = (String*)aList.GetObject( nCur+1 );
84 // COMPARE_GREATER => pStr2 ist groesser als pStr1
85 StringCompare eCompare = pStr1->CompareIgnoreCaseToAscii( *pStr2 ); //@@@
86 sal_Bool bSwap = sal_False;
87 if( bAscending )
88 {
89 if( eCompare == COMPARE_LESS )
90 bSwap = sal_True;
91 }
92 else if( eCompare == COMPARE_GREATER )
93 bSwap = sal_True;
94
95 if( bSwap )
96 {
97 bSwapped = sal_True;
98 aList.Replace( pStr1, nCur + 1 );
99 aList.Replace( pStr2, nCur );
100 if( pParallelList )
101 {
102 void* p1 = pParallelList->GetObject( nCur );
103 void* p2 = pParallelList->GetObject( nCur + 1 );
104 pParallelList->Replace( p1, nCur + 1 );
105 pParallelList->Replace( p2, nCur );
106 }
107 }
108 }
109 }
110 }
111 }
112
113 // class SfxStringListItem -----------------------------------------------
114
SfxStringListItem()115 SfxStringListItem::SfxStringListItem() :
116 pImp(NULL)
117 {
118 }
119
120 //------------------------------------------------------------------------
121
SfxStringListItem(sal_uInt16 which,const List * pList)122 SfxStringListItem::SfxStringListItem( sal_uInt16 which, const List* pList ) :
123 SfxPoolItem( which ),
124 pImp(NULL)
125 {
126 // PB: das Putten einer leeren Liste funktionierte nicht,
127 // deshalb habe ich hier die Abfrage nach dem Count auskommentiert
128 if( pList /*!!! && pList->Count() */ )
129 {
130 pImp = new SfxImpStringList;
131
132 long i, nCount = pList->Count();
133 String *pStr1, *pStr2;
134 for( i=0; i < nCount; i++ )
135 {
136 pStr1 = (String*)pList->GetObject(i);
137 pStr2 = new String( *pStr1 );
138 pImp->aList.Insert( pStr2, LIST_APPEND );
139 }
140 }
141 }
142
143 //------------------------------------------------------------------------
144
SfxStringListItem(sal_uInt16 which,SvStream & rStream)145 SfxStringListItem::SfxStringListItem( sal_uInt16 which, SvStream& rStream ) :
146 SfxPoolItem( which ),
147 pImp(NULL)
148 {
149 long nEntryCount;
150 rStream >> nEntryCount;
151
152 if( nEntryCount )
153 pImp = new SfxImpStringList;
154
155 long i;
156 String* pStr;
157 for( i=0; i < nEntryCount; i++ )
158 {
159 pStr = new String;
160 readByteString(rStream, *pStr);
161 pImp->aList.Insert( pStr, LIST_APPEND );
162 }
163 }
164
165 //------------------------------------------------------------------------
166
SfxStringListItem(const SfxStringListItem & rItem)167 SfxStringListItem::SfxStringListItem( const SfxStringListItem& rItem ) :
168 SfxPoolItem( rItem ),
169 pImp(NULL)
170 {
171 pImp = rItem.pImp;
172
173 if( pImp )
174 {
175 DBG_ASSERT(pImp->nRefCount!=0xffff,"ImpList not valid");
176 pImp->nRefCount++;
177 }
178 }
179
180 //------------------------------------------------------------------------
181
~SfxStringListItem()182 SfxStringListItem::~SfxStringListItem()
183 {
184 if( pImp )
185 {
186 DBG_ASSERT(pImp->nRefCount!=0xffff,"ImpList not valid");
187 if( pImp->nRefCount > 1 )
188 pImp->nRefCount--;
189 else
190 delete pImp;
191 }
192 }
193
194 //------------------------------------------------------------------------
195
GetList()196 List* SfxStringListItem::GetList()
197 {
198 if( !pImp )
199 pImp = new SfxImpStringList;
200 DBG_ASSERT(pImp->nRefCount!=0xffff,"ImpList not valid");
201 return &(pImp->aList);
202 }
203
204 //------------------------------------------------------------------------
205
operator ==(const SfxPoolItem & rItem) const206 int SfxStringListItem::operator==( const SfxPoolItem& rItem ) const
207 {
208 DBG_ASSERT( SfxPoolItem::operator==( rItem ), "unequal type" );
209
210 SfxStringListItem* pItem = (SfxStringListItem*)&rItem;
211
212 if( pImp == pItem->pImp )
213 return sal_True;
214 else
215 return sal_False;
216 }
217
218 //------------------------------------------------------------------------
219
GetPresentation(SfxItemPresentation,SfxMapUnit,SfxMapUnit,XubString & rText,const IntlWrapper *) const220 SfxItemPresentation SfxStringListItem::GetPresentation
221 (
222 SfxItemPresentation /*ePresentation*/,
223 SfxMapUnit /*eCoreMetric*/,
224 SfxMapUnit /*ePresentationMetric*/,
225 XubString& rText,
226 const IntlWrapper *
227 ) const
228 {
229 rText.AssignAscii(RTL_CONSTASCII_STRINGPARAM("(List)"));
230 return SFX_ITEM_PRESENTATION_NONE;
231 }
232
233 //------------------------------------------------------------------------
234
Clone(SfxItemPool *) const235 SfxPoolItem* SfxStringListItem::Clone( SfxItemPool *) const
236 {
237 return new SfxStringListItem( *this );
238 /*
239 if( pImp )
240 return new SfxStringListItem( Which(), &(pImp->aList) );
241 else
242 return new SfxStringListItem( Which(), NULL );
243 */
244
245 }
246
247 //------------------------------------------------------------------------
248
Create(SvStream & rStream,sal_uInt16) const249 SfxPoolItem* SfxStringListItem::Create( SvStream & rStream, sal_uInt16 ) const
250 {
251 return new SfxStringListItem( Which(), rStream );
252 }
253
254 //------------------------------------------------------------------------
255
Store(SvStream & rStream,sal_uInt16) const256 SvStream& SfxStringListItem::Store( SvStream & rStream, sal_uInt16 ) const
257 {
258 if( !pImp )
259 {
260 rStream << 0L;
261 return rStream;
262 }
263
264 DBG_ASSERT(pImp->nRefCount!=0xffff,"ImpList not valid");
265
266 long nCount = pImp->aList.Count();
267 rStream << nCount;
268
269 long i;
270 String* pStr;
271 for( i=0; i < nCount; i++ )
272 {
273 pStr = (String*)(pImp->aList.GetObject( i ));
274 writeByteString(rStream, *pStr);
275 }
276
277 return rStream;
278 }
279
280 //------------------------------------------------------------------------
281
SetString(const XubString & rStr)282 void SfxStringListItem::SetString( const XubString& rStr )
283 {
284 DBG_ASSERT(GetRefCount()==0,"SetString:RefCount!=0");
285
286 if ( pImp && (pImp->nRefCount == 1) )
287 delete pImp;
288 else
289 if( pImp )
290 pImp->nRefCount--;
291 pImp = new SfxImpStringList;
292
293 xub_StrLen nStart = 0;
294 xub_StrLen nDelimPos;
295 XubString aStr(rStr);
296 aStr.ConvertLineEnd(LINEEND_CR);
297 do
298 {
299 nDelimPos = aStr.Search( _CR, nStart );
300 xub_StrLen nLen;
301 if ( nDelimPos == STRING_NOTFOUND )
302 nLen = 0xffff;
303 else
304 nLen = nDelimPos - nStart;
305
306 XubString* pStr = new XubString(aStr.Copy(nStart, nLen));
307 // String gehoert der Liste
308 pImp->aList.Insert( pStr, LIST_APPEND );
309
310 nStart += nLen + 1 ; // delimiter ueberspringen
311 } while( nDelimPos != STRING_NOTFOUND );
312
313 // Kein Leerstring am Ende
314 if( pImp->aList.Last() &&
315 !((XubString*)pImp->aList.Last())->Len() )
316 delete (XubString*)pImp->aList.Remove( pImp->aList.Count()-1 );
317 }
318
319 //------------------------------------------------------------------------
320
GetString()321 XubString SfxStringListItem::GetString()
322 {
323 XubString aStr;
324 if ( pImp )
325 {
326 DBG_ASSERT(pImp->nRefCount!=0xffff,"ImpList not valid");
327 XubString* pStr = (XubString*)(pImp->aList.First());
328 while( pStr )
329 {
330 aStr += *pStr;
331 pStr = (XubString*)(pImp->aList.Next());
332 if ( pStr )
333 aStr += '\r';
334 }
335 }
336 aStr.ConvertLineEnd();
337 return aStr;
338 }
339
340 //------------------------------------------------------------------------
341
342 #ifndef TF_POOLABLE
343
IsPoolable() const344 int SfxStringListItem::IsPoolable() const
345 {
346 return sal_False;
347 }
348
349 #endif
350
351 //------------------------------------------------------------------------
352
Sort(sal_Bool bAscending,List * pParallelList)353 void SfxStringListItem::Sort( sal_Bool bAscending, List* pParallelList )
354 {
355 DBG_ASSERT(GetRefCount()==0,"Sort:RefCount!=0");
356 if( pImp )
357 pImp->Sort( bAscending, pParallelList );
358 }
359
360 //----------------------------------------------------------------------------
SetStringList(const com::sun::star::uno::Sequence<rtl::OUString> & rList)361 void SfxStringListItem::SetStringList( const com::sun::star::uno::Sequence< rtl::OUString >& rList )
362 {
363 DBG_ASSERT(GetRefCount()==0,"SetString:RefCount!=0");
364
365 if ( pImp && (pImp->nRefCount == 1) )
366 delete pImp;
367 else
368 if( pImp )
369 pImp->nRefCount--;
370 pImp = new SfxImpStringList;
371
372 for ( sal_Int32 n = 0; n < rList.getLength(); n++ )
373 {
374 XubString* pStr = new XubString( rList[n] );
375 // String gehoert der Liste
376 pImp->aList.Insert( pStr, LIST_APPEND );
377 }
378 }
379
380 //----------------------------------------------------------------------------
GetStringList(com::sun::star::uno::Sequence<rtl::OUString> & rList) const381 void SfxStringListItem::GetStringList( com::sun::star::uno::Sequence< rtl::OUString >& rList ) const
382 {
383 long nCount = pImp->aList.Count();
384
385 rList.realloc( nCount );
386 for( long i=0; i < nCount; i++ )
387 rList[i] = *(String*)(pImp->aList.GetObject( i ));
388 }
389
390 //----------------------------------------------------------------------------
391 // virtual
PutValue(const com::sun::star::uno::Any & rVal,sal_uInt8)392 sal_Bool SfxStringListItem::PutValue( const com::sun::star::uno::Any& rVal,sal_uInt8 )
393 {
394 com::sun::star::uno::Sequence< rtl::OUString > aValue;
395 if ( rVal >>= aValue )
396 {
397 SetStringList( aValue );
398 return sal_True;
399 }
400
401 DBG_ERROR( "SfxStringListItem::PutValue - Wrong type!" );
402 return sal_False;
403 }
404
405 //----------------------------------------------------------------------------
406 // virtual
QueryValue(com::sun::star::uno::Any & rVal,sal_uInt8) const407 sal_Bool SfxStringListItem::QueryValue( com::sun::star::uno::Any& rVal,sal_uInt8 ) const
408 {
409 // GetString() is not const!!!
410 SfxStringListItem* pThis = const_cast< SfxStringListItem * >( this );
411
412 com::sun::star::uno::Sequence< rtl::OUString > aStringList;
413 pThis->GetStringList( aStringList );
414 rVal = ::com::sun::star::uno::makeAny( aStringList );
415 return sal_True;
416 }
417
418
419