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 47 SfxImpStringList() { nRefCount = 1; } 48 ~SfxImpStringList(); 49 void Sort( sal_Bool bAscending, List* ); 50 }; 51 52 //------------------------------------------------------------------------ 53 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 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 115 SfxStringListItem::SfxStringListItem() : 116 pImp(NULL) 117 { 118 } 119 120 //------------------------------------------------------------------------ 121 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 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 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 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 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 206 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 220 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 235 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 249 SfxPoolItem* SfxStringListItem::Create( SvStream & rStream, sal_uInt16 ) const 250 { 251 return new SfxStringListItem( Which(), rStream ); 252 } 253 254 //------------------------------------------------------------------------ 255 256 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 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 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 344 int SfxStringListItem::IsPoolable() const 345 { 346 return sal_False; 347 } 348 349 #endif 350 351 //------------------------------------------------------------------------ 352 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 //---------------------------------------------------------------------------- 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 //---------------------------------------------------------------------------- 381 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 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 407 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