1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tdir.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_tools.hxx"
39 #include <tools/debug.hxx>
40 #include <tools/list.hxx>
45 #include <tools/fsys.hxx>
50 DECLARE_LIST( DirEntryList
, DirEntry
* )
51 DECLARE_LIST( FSysSortList
, FSysSort
* )
52 DECLARE_LIST( FileStatList
, FileStat
* )
54 #define APPEND (USHORT) 65535
56 /*************************************************************************
58 |* Dir::InsertPointReached()
60 |* Beschreibung stellt fest, ob eingefuegt werden musz
61 |* Ersterstellung MA 05.11.91
62 |* Letzte Aenderung MI 05.02.92
64 *************************************************************************/
66 BOOL
Dir::ImpInsertPointReached( const DirEntry
& rNewEntry
,
67 const FileStat
& rNewStat
,
68 ULONG nCurPos
, ULONG nSortIndex
) const
70 #define VALUE( nKindFlags ) \
71 ( ( FSYS_KIND_FILE | FSYS_KIND_DIR | FSYS_KIND_DEV | \
72 FSYS_KIND_CHAR | FSYS_KIND_BLOCK ) & nKindFlags )
74 // einfache Dinge erfordern einfache Loesungen
78 FSysSort nSort
= *( pSortLst
->GetObject( nSortIndex
) );
79 FileStat
*pOldStat
= NULL
;
80 DirEntry
*pCurLstObj
= pLst
->GetObject( nCurPos
);
82 pOldStat
= pStatLst
->GetObject( nCurPos
);
87 case (FSYS_SORT_NAME
| FSYS_SORT_ASCENDING
):
88 if ( pCurLstObj
->aName
> rNewEntry
.aName
)
90 if ( !(pCurLstObj
->aName
== rNewEntry
.aName
) )
93 case (FSYS_SORT_NAME
| FSYS_SORT_DESCENDING
):
94 if ( pCurLstObj
->aName
< rNewEntry
.aName
)
96 if ( !(pCurLstObj
->aName
== rNewEntry
.aName
) )
101 case (FSYS_SORT_EXT
| FSYS_SORT_ASCENDING
):
103 if ( pCurLstObj
->GetExtension() > rNewEntry
.GetExtension() )
105 if ( !(pCurLstObj
->GetExtension() == rNewEntry
.GetExtension()) )
109 case (FSYS_SORT_EXT
| FSYS_SORT_DESCENDING
):
111 if ( pCurLstObj
->GetExtension() < rNewEntry
.GetExtension() )
113 if ( !(pCurLstObj
->GetExtension() == rNewEntry
.GetExtension()) )
119 case (FSYS_SORT_KIND
| FSYS_SORT_ASCENDING
):
120 if ( VALUE(pOldStat
->nKindFlags
) > VALUE(rNewStat
.nKindFlags
) )
122 if ( !(VALUE(pOldStat
->nKindFlags
) == VALUE(rNewStat
.nKindFlags
)) )
125 case (FSYS_SORT_KIND
| FSYS_SORT_DESCENDING
):
126 if ( VALUE(pOldStat
->nKindFlags
) < VALUE(rNewStat
.nKindFlags
) )
128 if ( !(VALUE(pOldStat
->nKindFlags
) == VALUE(rNewStat
.nKindFlags
)) )
133 case (FSYS_SORT_SIZE
| FSYS_SORT_ASCENDING
):
134 if ( pOldStat
->nSize
> rNewStat
.nSize
)
136 if ( !(pOldStat
->nSize
== rNewStat
.nSize
) )
139 case (FSYS_SORT_SIZE
| FSYS_SORT_DESCENDING
):
140 if ( pOldStat
->nSize
< rNewStat
.nSize
)
142 if ( !(pOldStat
->nSize
== rNewStat
.nSize
) )
146 case FSYS_SORT_MODIFYED
:
147 case (FSYS_SORT_MODIFYED
| FSYS_SORT_ASCENDING
):
148 if ( (pOldStat
->aDateModified
>= rNewStat
.aDateModified
) &&
149 (pOldStat
->aTimeModified
> rNewStat
.aTimeModified
) )
151 if ( !((pOldStat
->aDateModified
== rNewStat
.aDateModified
) &&
152 (pOldStat
->aTimeModified
== rNewStat
.aTimeModified
)) )
155 case (FSYS_SORT_MODIFYED
| FSYS_SORT_DESCENDING
):
156 if ( (pOldStat
->aDateModified
<= rNewStat
.aDateModified
) &&
157 (pOldStat
->aTimeModified
< rNewStat
.aTimeModified
) )
159 if ( !((pOldStat
->aDateModified
== rNewStat
.aDateModified
) &&
160 (pOldStat
->aTimeModified
== rNewStat
.aTimeModified
)) )
164 case FSYS_SORT_CREATED
:
165 case (FSYS_SORT_CREATED
| FSYS_SORT_ASCENDING
):
166 if ( (pOldStat
->aDateCreated
>= rNewStat
.aDateCreated
) &&
167 (pOldStat
->aTimeCreated
> rNewStat
.aTimeCreated
) )
169 if ( !((pOldStat
->aDateCreated
== rNewStat
.aDateCreated
) &&
170 (pOldStat
->aTimeCreated
== rNewStat
.aTimeCreated
)) )
173 case (FSYS_SORT_CREATED
| FSYS_SORT_DESCENDING
):
174 if ( (pOldStat
->aDateCreated
<= rNewStat
.aDateCreated
) &&
175 (pOldStat
->aTimeCreated
< rNewStat
.aTimeCreated
) )
177 if ( !((pOldStat
->aDateCreated
== rNewStat
.aDateCreated
) &&
178 (pOldStat
->aTimeCreated
== rNewStat
.aTimeCreated
)) )
182 case FSYS_SORT_ACCESSED
:
183 case (FSYS_SORT_ACCESSED
| FSYS_SORT_ASCENDING
):
184 if ( (pOldStat
->aDateAccessed
>= rNewStat
.aDateAccessed
) &&
185 (pOldStat
->aTimeAccessed
> rNewStat
.aTimeAccessed
) )
187 if ( !((pOldStat
->aDateAccessed
== rNewStat
.aDateAccessed
) &&
188 (pOldStat
->aTimeAccessed
== rNewStat
.aTimeAccessed
)) )
191 case (FSYS_SORT_ACCESSED
| FSYS_SORT_DESCENDING
):
192 if ( (pOldStat
->aDateAccessed
<= rNewStat
.aDateAccessed
) &&
193 (pOldStat
->aTimeAccessed
< rNewStat
.aTimeAccessed
) )
195 if ( !((pOldStat
->aDateAccessed
== rNewStat
.aDateAccessed
) &&
196 (pOldStat
->aTimeAccessed
== rNewStat
.aTimeAccessed
)) )
199 default: /* Kann nicht sein */;
202 if ( nSortIndex
== ( pSortLst
->Count() - 1 ) )
206 return ImpInsertPointReached( rNewEntry
, rNewStat
,
207 nCurPos
, nSortIndex
+ 1 );
211 /*************************************************************************
213 |* Dir::ImpSortedInsert()
215 |* Beschreibung fuegt sortiert ein
216 |* Ersterstellung MA 05.11.91
217 |* Letzte Aenderung MA 03.12.91
219 *************************************************************************/
221 void Dir::ImpSortedInsert( const DirEntry
*pNewEntry
, const FileStat
*pNewStat
)
223 //Sonderfall, keine Sortierung gewuenscht.
225 pLst
->Insert( (DirEntry
*)pNewEntry
, APPEND
);
231 if ( ImpInsertPointReached( *pNewEntry
, *pNewStat
, pLst
->GetCurPos(),
235 pStatLst
->Insert( (FileStat
*)pNewStat
, pLst
->GetCurPos() );
236 pLst
->Insert( (DirEntry
*)pNewEntry
);
239 } while( pLst
->Next() );
242 pStatLst
->Insert( (FileStat
*)pNewStat
, APPEND
);
243 pLst
->Insert( (DirEntry
*)pNewEntry
, APPEND
);
246 /*************************************************************************
250 |* Beschreibung gemeinsame Implementation der Ctoren
251 |* Ersterstellung MI 02.06.93
252 |* Letzte Aenderung MI 02.06.93
254 *************************************************************************/
256 void Dir::Construct( DirEntryKind nKindFlags
)
261 eAttrMask
= nKindFlags
;
262 ByteString
aTempName( GetName(), osl_getThreadTextEncoding() );
263 if ( aTempName
.Search( "*" ) != STRING_NOTFOUND
||
264 aTempName
.Search( "?" ) != STRING_NOTFOUND
)
265 #if defined( WNT ) && !defined( WTC )
267 ByteString
aTStr(CutName(), osl_getThreadTextEncoding());
268 char* pBuffer
= new char[aTStr
.Len()+1];
269 strcpy( pBuffer
, aTStr
.GetBuffer() );
270 CharLowerBuff( pBuffer
, aTStr
.Len() );
271 aNameMask
= WildCard( String(pBuffer
, osl_getThreadTextEncoding()), ';' );
275 aNameMask
= WildCard( CutName(), ';' );
278 aNameMask
= String("*", osl_getThreadTextEncoding());
281 /*************************************************************************
285 |* Beschreibung FSYS.SDW
286 |* Ersterstellung MI 16.05.91
287 |* Letzte Aenderung MI 19.09.96
289 *************************************************************************/
294 return Scan( USHRT_MAX
) > 0;
297 /*************************************************************************
302 |* Ersterstellung MI 22.10.96
303 |* Letzte Aenderung MI 22.10.96
305 *************************************************************************/
309 // ggf. alten Reader l"oschen
310 if ( pReader
&& pReader
->bInUse
)
313 // alle DirEntries aus der Liste entfernen und deren Speicher freigeben
316 DirEntry
* pEntry
= pLst
->First();
319 DirEntry
* pNext
= pLst
->Next();
326 pLst
= new DirEntryList();
328 // Alte File-Stat's Loeschen
331 //Erstmal die alten Loeschen
332 FileStat
* pEntry
= pStatLst
->First();
335 FileStat
* pNext
= pStatLst
->Next();
343 // Verlangen die Sortierkriterien FileStat's?
349 if ( *( pSortLst
->GetCurObject() ) &
350 ( FSYS_SORT_KIND
| FSYS_SORT_SIZE
|
351 FSYS_SORT_CREATED
| FSYS_SORT_MODIFYED
| FSYS_SORT_ACCESSED
) )
352 pStatLst
= new FileStatList();
353 } while ( !pStatLst
&& pSortLst
->Next() );
357 // ggf. einen neuen Reader aufsetzen
359 pReader
= new DirReader_Impl( *this );
362 // gibt es das zu oeffnende Verzeichnis ueberhaupt?
363 #if !defined(UNX) && !defined(OS2) //explanation: see DirReader_Impl::Read() in unx.cxx
364 if( !pReader
->pDosDir
)
366 nError
= FSYS_ERR_NOTADIRECTORY
;
373 /*************************************************************************
377 |* Beschreibung FSYS.SDW
378 |* Ersterstellung MI 18.09.96
379 |* Letzte Aenderung MI 19.09.96
381 *************************************************************************/
383 USHORT
Dir::Scan( USHORT nCount
)
386 USHORT nRead
= 0; // Anzahl in dieser Runde gelesener Eintr"age
387 FSysFailOnErrorImpl();
389 // noch nicht fertig gewesen
393 if ( !pLst
->Count() )
395 // dann ggf. Laufwerke scannen
396 pReader
->bInUse
= TRUE
;
397 nRead
= pReader
->Init();
401 while ( nRead
<= nCount
&& !pReader
->bReady
)
402 nRead
= nRead
+ pReader
->Read();
405 if ( pReader
&& pReader
->bReady
)
409 // Anzahl der gelesenen zur"uckgeben
413 /*************************************************************************
417 |* Beschreibung FSYS.SDW
418 |* Ersterstellung MI 16.05.91
419 |* Letzte Aenderung MI 04.03.92
421 *************************************************************************/
423 Dir::Dir( const DirEntry
& rDirEntry
, DirEntryKind nKindFlags
, FSysSort nSort
, ... ):
424 DirEntry( rDirEntry
),
427 DBG_CTOR( Dir
, NULL
);
429 Construct( nKindFlags
);
432 va_start( pArgs
, nSort
);
433 ImpSetSort( pArgs
, nSort
);
438 /*************************************************************************
442 |* Beschreibung FSYS.SDW
443 |* Ersterstellung MI 02.06.93
444 |* Letzte Aenderung MI 02.06.93
446 *************************************************************************/
448 Dir::Dir( const DirEntry
& rDirEntry
, DirEntryKind nKindFlags
):
449 DirEntry( rDirEntry
),
452 DBG_CTOR( Dir
, NULL
);
454 Construct( nKindFlags
);
458 /*************************************************************************
462 |* Beschreibung FSYS.SDW
463 |* Ersterstellung MI 16.05.91
464 |* Letzte Aenderung MA 04.11.91
466 *************************************************************************/
471 DBG_CTOR( Dir
, NULL
);
476 eAttrMask
= FSYS_KIND_ALL
;
477 aNameMask
= String("*", osl_getThreadTextEncoding());
480 /*************************************************************************
484 |* Beschreibung FSYS.SDW
485 |* Ersterstellung MI 16.05.91
486 |* Letzte Aenderung MA 04.11.91
488 *************************************************************************/
492 DBG_DTOR( Dir
, NULL
);
494 // alle DirEntries aus der Liste entfernen und deren Speicher freigeben
497 DirEntry
* pEntry
= pLst
->First();
500 DirEntry
* pNext
= pLst
->Next();
509 // alle Sorts aus der Liste entfernen und deren Speicher freigeben
512 FSysSort
* pEntry
= pSortLst
->First();
515 FSysSort
* pNext
= pSortLst
->Next();
524 // alle FileStat's aus der Liste entfernen und deren Speicher freigeben
527 FileStat
* pEntry
= pStatLst
->First();
530 FileStat
* pNext
= pStatLst
->Next();
538 // ggf. laufenden Reader freigeben
542 /*************************************************************************
546 |* Beschreibung FSYS.SDW
547 |* Ersterstellung MA 04.11.91
548 |* Letzte Aenderung MI 05.02.92
550 *************************************************************************/
552 FSysError
Dir::ImpSetSort( std::va_list pArgs
, int nFirstSort
)
556 FSysSortList
*pNewSortLst
= new FSysSortList
;
558 *( pSort
= new FSysSort
) = nFirstSort
;
561 // letztes Kriterium?
562 bLast
= FSYS_SORT_END
== (*pSort
& FSYS_SORT_END
);
563 *pSort
&= ~FSYS_SORT_END
;
565 FSysSort nSort
= *pSort
& ~(USHORT
)FSYS_SORT_ASCENDING
566 & ~(USHORT
)FSYS_SORT_DESCENDING
;
568 // g"utliges Sortierkriterium?
569 if ( ( nSort
== FSYS_SORT_NAME
) ||
570 ( nSort
== FSYS_SORT_SIZE
) ||
571 ( nSort
== FSYS_SORT_EXT
) ||
572 ( nSort
== FSYS_SORT_CREATED
) ||
573 ( nSort
== FSYS_SORT_MODIFYED
) ||
574 ( nSort
== FSYS_SORT_ACCESSED
) ||
575 ( nSort
== FSYS_SORT_KIND
) )
577 pNewSortLst
->Insert( pSort
, APPEND
);
578 *(pSort
= new FSysSort
) = va_arg( pArgs
, FSysSort
);
581 { // ungueltiger Sort oder FSYS_SORT_NONE
582 FSysSort
* pEntry
= pNewSortLst
->First();
585 FSysSort
* pNext
= pNewSortLst
->Next();
589 pNewSortLst
->Clear();
591 if ( *pSort
== FSYS_SORT_NONE
)
601 return FSYS_ERR_NOTSUPPORTED
;
607 delete pSort
; // JP:6.3.00 - delete the initial pointer
609 //Enfernen der alten Sort-Elemente
612 FSysSort
* pEntry
= pSortLst
->First();
615 FSysSort
* pNext
= pSortLst
->Next();
622 pSortLst
= pNewSortLst
;
624 //Jetzt noch neu Sortieren...
626 //Wenn keine FileStats da sind, aber nun welche gebraucht werden,
627 //ist der Aufruf von Update() die einfachste Moeglichkeit
628 if ( !pStatLst
&& pSortLst
)
633 if ( *(pSortLst
->GetCurObject()) &
634 ( FSYS_SORT_CREATED
| FSYS_SORT_MODIFYED
| FSYS_SORT_SIZE
|
635 FSYS_SORT_ACCESSED
| FSYS_SORT_KIND
) )
640 } while ( !pStatLst
&& pSortLst
->Next() );
643 if ( pLst
) { //Keine DirEntry's, kein Sort.
644 DirEntryList
*pOldLst
= pLst
; //alte Liste merken
645 pLst
= new DirEntryList(); //neue Liste (zu Sortieren)
647 FileStatList
*pOldStatLst
= NULL
; //alte StatListe merken
649 pOldStatLst
= pStatLst
;
650 pStatLst
= new FileStatList(); //neue StatListe (zu Sortieren)
655 //Sortiertes Einfuegen der Elemente aus den gemerkten Listen
656 //in die 'richtigen' Listen
658 ImpSortedInsert( pOldLst
->GetCurObject(),
659 pOldStatLst
->GetObject( pOldLst
->GetCurPos() ) );
661 ImpSortedInsert( pOldLst
->GetCurObject(), NULL
);
662 } while( pOldLst
->Next() );
671 /*************************************************************************
675 |* Beschreibung FSYS.SDW
676 |* Ersterstellung MA 04.11.91
677 |* Letzte Aenderung MI 05.02.92
679 *************************************************************************/
681 FSysError
Dir::SetSort( FSysSort nSort
, ... )
684 va_start( pArgs
, nSort
);
685 return ImpSetSort( pArgs
, nSort
);
688 /*************************************************************************
692 |* Beschreibung FSYS.SDW
693 |* Ersterstellung MI 16.05.91
694 |* Letzte Aenderung MI 16.05.91
696 *************************************************************************/
698 DirEntry
& Dir::operator[] ( USHORT nIndex
) const
700 DBG_ASSERT( nIndex
< Count(), "Dir::operator[] : nIndex > Count()" );
702 DirEntry
*pEntry
= pLst
->GetObject( nIndex
);
706 /*************************************************************************
708 |* Dir::operator+= ()
710 |* Beschreibung FSYS.SDW
711 |* Ersterstellung MI 16.05.91
712 |* Letzte Aenderung MI 16.05.91
714 *************************************************************************/
716 Dir
& Dir::operator+=( const Dir
& rDir
)
718 // ggf. erst den Rest lesen
721 DBG_ASSERT( !rDir
.pReader
, "Dir::+= with incomplete Dir" );
723 // ggf. initiale Liste erzeugen
725 pLst
= new DirEntryList();
727 //Verlangen die Sortierkriterien FileStat's?
732 if ( *(pSortLst
->GetCurObject()) &
733 ( FSYS_SORT_CREATED
| FSYS_SORT_MODIFYED
| FSYS_SORT_SIZE
|
734 FSYS_SORT_ACCESSED
| FSYS_SORT_KIND
) )
736 } while ( !bStat
&& pSortLst
->Next() );
738 FileStat
* stat
= NULL
;
739 for ( USHORT nNr
= 0; nNr
< rDir
.Count(); nNr
++ )
744 stat
= new FileStat( *rDir
.pStatLst
->GetObject(nNr
) );
746 stat
= new FileStat( rDir
[nNr
] );
748 ImpSortedInsert( new DirEntry( rDir
[nNr
] ), stat
);
753 /*************************************************************************
757 |* Beschreibung FSYS.SDW
758 |* Ersterstellung MI 16.05.91
759 |* Letzte Aenderung MI 18.09.96
761 *************************************************************************/
764 USHORT
Dir::Count( BOOL bUpdated
) const
766 // ggf. erst den Rest lesen
767 if ( bUpdated
&& pReader
)
768 ((Dir
*)this)->Scan( USHRT_MAX
);
770 return pLst
== NULL
? 0 : (USHORT
) pLst
->Count();