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