/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_tools.hxx" #define _DIR_CXX #include #include #include #include #include #ifndef _COMPED_HXX #include "comdep.hxx" #endif #include DBG_NAME( Dir ) DECLARE_LIST( DirEntryList, DirEntry* ) DECLARE_LIST( FSysSortList, FSysSort* ) DECLARE_LIST( FileStatList, FileStat* ) #define APPEND (sal_uInt16) 65535 /************************************************************************* |* |* Dir::InsertPointReached() |* |* Beschreibung stellt fest, ob eingefuegt werden musz |* Ersterstellung MA 05.11.91 |* Letzte Aenderung MI 05.02.92 |* *************************************************************************/ sal_Bool Dir::ImpInsertPointReached( const DirEntry& rNewEntry, const FileStat& rNewStat, sal_uIntPtr nCurPos, sal_uIntPtr nSortIndex ) const { #define VALUE( nKindFlags ) \ ( ( FSYS_KIND_FILE | FSYS_KIND_DIR | FSYS_KIND_DEV | \ FSYS_KIND_CHAR | FSYS_KIND_BLOCK ) & nKindFlags ) // einfache Dinge erfordern einfache Loesungen if ( !pLst->Count() ) return sal_True; FSysSort nSort = *( pSortLst->GetObject( nSortIndex ) ); FileStat *pOldStat = NULL; DirEntry *pCurLstObj = pLst->GetObject( nCurPos ); if ( pStatLst ) pOldStat = pStatLst->GetObject( nCurPos ); switch( nSort ) { case FSYS_SORT_NAME: case (FSYS_SORT_NAME | FSYS_SORT_ASCENDING): if ( pCurLstObj->aName > rNewEntry.aName ) return sal_True; if ( !(pCurLstObj->aName == rNewEntry.aName) ) return sal_False; break; case (FSYS_SORT_NAME | FSYS_SORT_DESCENDING): if ( pCurLstObj->aName < rNewEntry.aName ) return sal_True; if ( !(pCurLstObj->aName == rNewEntry.aName) ) return sal_False; break; case FSYS_SORT_EXT: case (FSYS_SORT_EXT | FSYS_SORT_ASCENDING): { if ( pCurLstObj->GetExtension() > rNewEntry.GetExtension() ) return sal_True; if ( !(pCurLstObj->GetExtension() == rNewEntry.GetExtension()) ) return sal_False; break; } case (FSYS_SORT_EXT | FSYS_SORT_DESCENDING): { if ( pCurLstObj->GetExtension() < rNewEntry.GetExtension() ) return sal_True; if ( !(pCurLstObj->GetExtension() == rNewEntry.GetExtension()) ) return sal_False; break; } case FSYS_SORT_KIND: case (FSYS_SORT_KIND | FSYS_SORT_ASCENDING ): if ( VALUE(pOldStat->nKindFlags) > VALUE(rNewStat.nKindFlags) ) return sal_True; if ( !(VALUE(pOldStat->nKindFlags) == VALUE(rNewStat.nKindFlags)) ) return sal_False; break; case (FSYS_SORT_KIND | FSYS_SORT_DESCENDING): if ( VALUE(pOldStat->nKindFlags) < VALUE(rNewStat.nKindFlags) ) return sal_True; if ( !(VALUE(pOldStat->nKindFlags) == VALUE(rNewStat.nKindFlags)) ) return sal_False; break; case FSYS_SORT_SIZE: case (FSYS_SORT_SIZE | FSYS_SORT_ASCENDING): if ( pOldStat->nSize > rNewStat.nSize ) return sal_True; if ( !(pOldStat->nSize == rNewStat.nSize) ) return sal_False; break; case (FSYS_SORT_SIZE | FSYS_SORT_DESCENDING): if ( pOldStat->nSize < rNewStat.nSize ) return sal_True; if ( !(pOldStat->nSize == rNewStat.nSize) ) return sal_False; break; case FSYS_SORT_MODIFYED: case (FSYS_SORT_MODIFYED | FSYS_SORT_ASCENDING): if ( (pOldStat->aDateModified >= rNewStat.aDateModified) && (pOldStat->aTimeModified > rNewStat.aTimeModified) ) return sal_True; if ( !((pOldStat->aDateModified == rNewStat.aDateModified) && (pOldStat->aTimeModified == rNewStat.aTimeModified)) ) return sal_False; break; case (FSYS_SORT_MODIFYED | FSYS_SORT_DESCENDING): if ( (pOldStat->aDateModified <= rNewStat.aDateModified) && (pOldStat->aTimeModified < rNewStat.aTimeModified) ) return sal_True; if ( !((pOldStat->aDateModified == rNewStat.aDateModified) && (pOldStat->aTimeModified == rNewStat.aTimeModified)) ) return sal_False; break; case FSYS_SORT_CREATED: case (FSYS_SORT_CREATED | FSYS_SORT_ASCENDING): if ( (pOldStat->aDateCreated >= rNewStat.aDateCreated) && (pOldStat->aTimeCreated > rNewStat.aTimeCreated) ) return sal_True; if ( !((pOldStat->aDateCreated == rNewStat.aDateCreated) && (pOldStat->aTimeCreated == rNewStat.aTimeCreated)) ) return sal_False; break; case (FSYS_SORT_CREATED | FSYS_SORT_DESCENDING): if ( (pOldStat->aDateCreated <= rNewStat.aDateCreated) && (pOldStat->aTimeCreated < rNewStat.aTimeCreated) ) return sal_True; if ( !((pOldStat->aDateCreated == rNewStat.aDateCreated) && (pOldStat->aTimeCreated == rNewStat.aTimeCreated)) ) return sal_False; break; case FSYS_SORT_ACCESSED: case (FSYS_SORT_ACCESSED | FSYS_SORT_ASCENDING): if ( (pOldStat->aDateAccessed >= rNewStat.aDateAccessed) && (pOldStat->aTimeAccessed > rNewStat.aTimeAccessed) ) return sal_True; if ( !((pOldStat->aDateAccessed == rNewStat.aDateAccessed) && (pOldStat->aTimeAccessed == rNewStat.aTimeAccessed)) ) return sal_False; break; case (FSYS_SORT_ACCESSED | FSYS_SORT_DESCENDING): if ( (pOldStat->aDateAccessed <= rNewStat.aDateAccessed) && (pOldStat->aTimeAccessed < rNewStat.aTimeAccessed) ) return sal_True; if ( !((pOldStat->aDateAccessed == rNewStat.aDateAccessed) && (pOldStat->aTimeAccessed == rNewStat.aTimeAccessed)) ) return sal_False; break; default: /* Kann nicht sein */; } if ( nSortIndex == ( pSortLst->Count() - 1 ) ) return sal_True; else //Rekursion return ImpInsertPointReached( rNewEntry, rNewStat, nCurPos, nSortIndex + 1 ); #undef VALUE } /************************************************************************* |* |* Dir::ImpSortedInsert() |* |* Beschreibung fuegt sortiert ein |* Ersterstellung MA 05.11.91 |* Letzte Aenderung MA 03.12.91 |* *************************************************************************/ void Dir::ImpSortedInsert( const DirEntry *pNewEntry, const FileStat *pNewStat ) { //Sonderfall, keine Sortierung gewuenscht. if ( !pSortLst ) { pLst->Insert( (DirEntry*)pNewEntry, APPEND ); return; } pLst->First(); do { if ( ImpInsertPointReached( *pNewEntry, *pNewStat, pLst->GetCurPos(), (sal_uIntPtr)0 ) ) { if ( pStatLst ) pStatLst->Insert( (FileStat*)pNewStat, pLst->GetCurPos() ); pLst->Insert( (DirEntry*)pNewEntry ); return; } } while( pLst->Next() ); if ( pStatLst ) pStatLst->Insert( (FileStat*)pNewStat, APPEND ); pLst->Insert( (DirEntry*)pNewEntry, APPEND ); } /************************************************************************* |* |* Dir::Construct() |* |* Beschreibung gemeinsame Implementation der Ctoren |* Ersterstellung MI 02.06.93 |* Letzte Aenderung MI 02.06.93 |* *************************************************************************/ void Dir::Construct( DirEntryKind nKindFlags ) { pLst = NULL; pSortLst = NULL; pStatLst = NULL; eAttrMask = nKindFlags; ByteString aTempName( GetName(), osl_getThreadTextEncoding() ); if ( aTempName.Search( "*" ) != STRING_NOTFOUND || aTempName.Search( "?" ) != STRING_NOTFOUND ) #if defined( WNT ) && !defined( WTC ) { ByteString aTStr(CutName(), osl_getThreadTextEncoding()); char* pBuffer = new char[aTStr.Len()+1]; strcpy( pBuffer, aTStr.GetBuffer() ); CharLowerBuff( pBuffer, aTStr.Len() ); aNameMask = WildCard( String(pBuffer, osl_getThreadTextEncoding()), ';' ); delete [] pBuffer; } #else aNameMask = WildCard( CutName(), ';' ); #endif else aNameMask = String("*", osl_getThreadTextEncoding()); } /************************************************************************* |* |* Dir::Update() |* |* Beschreibung FSYS.SDW |* Ersterstellung MI 16.05.91 |* Letzte Aenderung MI 19.09.96 |* *************************************************************************/ sal_Bool Dir::Update() { Reset(); return Scan( USHRT_MAX ) > 0; } /************************************************************************* |* |* Dir::Reset() |* |* Beschreibung |* Ersterstellung MI 22.10.96 |* Letzte Aenderung MI 22.10.96 |* *************************************************************************/ void Dir::Reset() { // ggf. alten Reader l"oschen if ( pReader && pReader->bInUse ) DELETEZ(pReader); // alle DirEntries aus der Liste entfernen und deren Speicher freigeben if ( pLst ) { DirEntry* pEntry = pLst->First(); while (pEntry) { DirEntry* pNext = pLst->Next(); delete pEntry; pEntry = pNext; } pLst->Clear(); } else pLst = new DirEntryList(); // Alte File-Stat's Loeschen if ( pStatLst ) { //Erstmal die alten Loeschen FileStat* pEntry = pStatLst->First(); while (pEntry) { FileStat* pNext = pStatLst->Next(); delete pEntry; pEntry = pNext; } pStatLst->Clear(); delete pStatLst; } // Verlangen die Sortierkriterien FileStat's? if ( pSortLst ) { pSortLst->First(); do { if ( *( pSortLst->GetCurObject() ) & ( FSYS_SORT_KIND | FSYS_SORT_SIZE | FSYS_SORT_CREATED | FSYS_SORT_MODIFYED | FSYS_SORT_ACCESSED ) ) pStatLst = new FileStatList(); } while ( !pStatLst && pSortLst->Next() ); } #ifndef BOOTSTRAP // ggf. einen neuen Reader aufsetzen if ( !pReader ) pReader = new DirReader_Impl( *this ); #endif // gibt es das zu oeffnende Verzeichnis ueberhaupt? #if !defined(UNX) && !defined(OS2) //explanation: see DirReader_Impl::Read() in unx.cxx if( !pReader->pDosDir ) { nError = FSYS_ERR_NOTADIRECTORY; DELETEZ( pReader ); return; } #endif } /************************************************************************* |* |* Dir::Scan() |* |* Beschreibung FSYS.SDW |* Ersterstellung MI 18.09.96 |* Letzte Aenderung MI 19.09.96 |* *************************************************************************/ sal_uInt16 Dir::Scan( sal_uInt16 nCount ) { sal_uInt16 nRead = 0; // Anzahl in dieser Runde gelesener Eintr"age FSysFailOnErrorImpl(); // noch nicht fertig gewesen if ( pReader ) { // frischer Reader? if ( !pLst->Count() ) { // dann ggf. Laufwerke scannen pReader->bInUse = sal_True; nRead = pReader->Init(); } // weiterlesen... while ( nRead <= nCount && !pReader->bReady ) nRead = nRead + pReader->Read(); // fertig? if ( pReader && pReader->bReady ) DELETEZ( pReader ); } // Anzahl der gelesenen zur"uckgeben return nRead; } /************************************************************************* |* |* Dir::Dir() |* |* Beschreibung FSYS.SDW |* Ersterstellung MI 16.05.91 |* Letzte Aenderung MI 04.03.92 |* *************************************************************************/ Dir::Dir( const DirEntry& rDirEntry, DirEntryKind nKindFlags, FSysSort nSort, ... ): DirEntry( rDirEntry ), pReader( 0 ) { DBG_CTOR( Dir, NULL ); Construct( nKindFlags ); std::va_list pArgs; va_start( pArgs, nSort ); ImpSetSort( pArgs, nSort ); Reset(); } /************************************************************************* |* |* Dir::Dir() |* |* Beschreibung FSYS.SDW |* Ersterstellung MI 02.06.93 |* Letzte Aenderung MI 02.06.93 |* *************************************************************************/ Dir::Dir( const DirEntry& rDirEntry, DirEntryKind nKindFlags ): DirEntry( rDirEntry ), pReader( 0 ) { DBG_CTOR( Dir, NULL ); Construct( nKindFlags ); Reset(); } /************************************************************************* |* |* Dir::Dir() |* |* Beschreibung FSYS.SDW |* Ersterstellung MI 16.05.91 |* Letzte Aenderung MA 04.11.91 |* *************************************************************************/ Dir::Dir(): pReader( 0 ) { DBG_CTOR( Dir, NULL ); pLst = NULL; pSortLst = NULL; pStatLst = NULL; eAttrMask = FSYS_KIND_ALL; aNameMask = String("*", osl_getThreadTextEncoding()); } /************************************************************************* |* |* Dir::~Dir() |* |* Beschreibung FSYS.SDW |* Ersterstellung MI 16.05.91 |* Letzte Aenderung MA 04.11.91 |* *************************************************************************/ Dir::~Dir() { DBG_DTOR( Dir, NULL ); // alle DirEntries aus der Liste entfernen und deren Speicher freigeben if ( pLst ) { DirEntry* pEntry = pLst->First(); while (pEntry) { DirEntry* pNext = pLst->Next(); delete pEntry; pEntry = pNext; } pLst->Clear(); delete pLst; } // alle Sorts aus der Liste entfernen und deren Speicher freigeben if ( pSortLst ) { FSysSort* pEntry = pSortLst->First(); while (pEntry) { FSysSort* pNext = pSortLst->Next(); delete pEntry; pEntry = pNext; } pSortLst->Clear(); delete pSortLst; } // alle FileStat's aus der Liste entfernen und deren Speicher freigeben if ( pStatLst ) { FileStat* pEntry = pStatLst->First(); while (pEntry) { FileStat* pNext = pStatLst->Next(); delete pEntry; pEntry = pNext; } pStatLst->Clear(); delete pStatLst; } // ggf. laufenden Reader freigeben delete pReader; } /************************************************************************* |* |* Dir::ImpSetSort() |* |* Beschreibung FSYS.SDW |* Ersterstellung MA 04.11.91 |* Letzte Aenderung MI 05.02.92 |* *************************************************************************/ FSysError Dir::ImpSetSort( std::va_list pArgs, int nFirstSort ) { sal_Bool bLast; FSysSort *pSort; FSysSortList *pNewSortLst = new FSysSortList; *( pSort = new FSysSort ) = nFirstSort; do { // letztes Kriterium? bLast = FSYS_SORT_END == (*pSort & FSYS_SORT_END); *pSort &= ~FSYS_SORT_END; FSysSort nSort = *pSort & ~(sal_uInt16)FSYS_SORT_ASCENDING & ~(sal_uInt16)FSYS_SORT_DESCENDING; // g"utliges Sortierkriterium? if ( ( nSort == FSYS_SORT_NAME ) || ( nSort == FSYS_SORT_SIZE ) || ( nSort == FSYS_SORT_EXT ) || ( nSort == FSYS_SORT_CREATED ) || ( nSort == FSYS_SORT_MODIFYED ) || ( nSort == FSYS_SORT_ACCESSED ) || ( nSort == FSYS_SORT_KIND ) ) { pNewSortLst->Insert( pSort, APPEND ); *(pSort = new FSysSort) = va_arg( pArgs, FSysSort ); } else { // ungueltiger Sort oder FSYS_SORT_NONE FSysSort* pEntry = pNewSortLst->First(); while (pEntry) { FSysSort* pNext = pNewSortLst->Next(); delete pEntry; pEntry = pNext; } pNewSortLst->Clear(); delete pNewSortLst; if ( *pSort == FSYS_SORT_NONE ) { delete pSort; if ( pSortLst ) delete pSortLst; return FSYS_ERR_OK; } else { delete pSort; return FSYS_ERR_NOTSUPPORTED; } } } while ( !bLast ); va_end( pArgs ); delete pSort; // JP:6.3.00 - delete the initial pointer //Enfernen der alten Sort-Elemente if ( pSortLst ) { FSysSort* pEntry = pSortLst->First(); while (pEntry) { FSysSort* pNext = pSortLst->Next(); delete pEntry; pEntry = pNext; } pSortLst->Clear(); delete pSortLst; } pSortLst = pNewSortLst; //Jetzt noch neu Sortieren... //Wenn keine FileStats da sind, aber nun welche gebraucht werden, //ist der Aufruf von Update() die einfachste Moeglichkeit if ( !pStatLst && pSortLst ) { pSortLst->First(); do { if ( *(pSortLst->GetCurObject()) & ( FSYS_SORT_CREATED | FSYS_SORT_MODIFYED | FSYS_SORT_SIZE | FSYS_SORT_ACCESSED | FSYS_SORT_KIND ) ) { Update(); return FSYS_ERR_OK; } } while ( !pStatLst && pSortLst->Next() ); } if ( pLst ) { //Keine DirEntry's, kein Sort. DirEntryList *pOldLst = pLst; //alte Liste merken pLst = new DirEntryList(); //neue Liste (zu Sortieren) FileStatList *pOldStatLst = NULL; //alte StatListe merken if ( pStatLst ) { pOldStatLst = pStatLst; pStatLst = new FileStatList(); //neue StatListe (zu Sortieren) } pOldLst->First(); do { //Sortiertes Einfuegen der Elemente aus den gemerkten Listen //in die 'richtigen' Listen if ( pOldStatLst ) ImpSortedInsert( pOldLst->GetCurObject(), pOldStatLst->GetObject( pOldLst->GetCurPos() ) ); else ImpSortedInsert( pOldLst->GetCurObject(), NULL ); } while( pOldLst->Next() ); delete pOldLst; if ( pOldStatLst ) delete pOldStatLst; } return FSYS_ERR_OK; } /************************************************************************* |* |* Dir::SetSort() |* |* Beschreibung FSYS.SDW |* Ersterstellung MA 04.11.91 |* Letzte Aenderung MI 05.02.92 |* *************************************************************************/ FSysError Dir::SetSort( FSysSort nSort, ... ) { std::va_list pArgs; va_start( pArgs, nSort ); return ImpSetSort( pArgs, nSort ); } /************************************************************************* |* |* Dir::operator[]() |* |* Beschreibung FSYS.SDW |* Ersterstellung MI 16.05.91 |* Letzte Aenderung MI 16.05.91 |* *************************************************************************/ DirEntry& Dir::operator[] ( sal_uInt16 nIndex ) const { DBG_ASSERT( nIndex < Count(), "Dir::operator[] : nIndex > Count()" ); DirEntry *pEntry = pLst->GetObject( nIndex ); return *pEntry; } /************************************************************************* |* |* Dir::operator+= () |* |* Beschreibung FSYS.SDW |* Ersterstellung MI 16.05.91 |* Letzte Aenderung MI 16.05.91 |* *************************************************************************/ Dir& Dir::operator+=( const Dir& rDir ) { // ggf. erst den Rest lesen if ( pReader ) Scan( USHRT_MAX ); DBG_ASSERT( !rDir.pReader, "Dir::+= with incomplete Dir" ); // ggf. initiale Liste erzeugen if ( !pLst ) pLst = new DirEntryList(); //Verlangen die Sortierkriterien FileStat's? sal_Bool bStat = sal_False; if ( pSortLst ) { pSortLst->First(); do { if ( *(pSortLst->GetCurObject()) & ( FSYS_SORT_CREATED | FSYS_SORT_MODIFYED | FSYS_SORT_SIZE | FSYS_SORT_ACCESSED | FSYS_SORT_KIND ) ) bStat = sal_True; } while ( !bStat && pSortLst->Next() ); } FileStat * stat = NULL; for ( sal_uInt16 nNr = 0; nNr < rDir.Count(); nNr++ ) { if ( bStat ) { if ( rDir.pStatLst ) stat = new FileStat( *rDir.pStatLst->GetObject(nNr) ); else stat = new FileStat( rDir[nNr] ); } ImpSortedInsert( new DirEntry( rDir[nNr] ), stat ); } return *this; } /************************************************************************* |* |* Dir::Count() |* |* Beschreibung FSYS.SDW |* Ersterstellung MI 16.05.91 |* Letzte Aenderung MI 18.09.96 |* *************************************************************************/ sal_uInt16 Dir::Count( sal_Bool bUpdated ) const { // ggf. erst den Rest lesen if ( bUpdated && pReader ) ((Dir*)this)->Scan( USHRT_MAX ); return pLst == NULL ? 0 : (sal_uInt16) pLst->Count(); }