Hola foreros.
Este hilo me ha venido de maravillas, pues tenía necesidad de una función similar a Directory modificada. El inconveneinte es que mi xHarbour no trae ni la mitad de estas funciones, aunque algunas parecidas. Así que para a prender a manipular esta faceta de (x)Harbour que desconocía por completo, lo primero que he hecho ha sido traducir la función Directory aquí expuesta, para adptarla a mi xHarbour.Tras muchos sudores este es el resultado:
- Code: Select all Expand view
HB_FUNC( XDIRECTORY ) // xDirectory( LPSTR cDir, LPSTR cAttr )
{
LPSTR pszDirSpec = hb_parc( 1 ) ;
LPSTR pszAttributes = hb_parc( 2 ) ;
PHB_ITEM pDir = hb_itemArrayNew( 0 ) ;
PHB_FFIND ffind ;
USHORT ulMask ;
ulMask = HB_FA_ARCHIVE |
HB_FA_READONLY |
HB_FA_DEVICE |
HB_FA_TEMPORARY |
HB_FA_SPARSE |
HB_FA_REPARSE |
HB_FA_COMPRESSED |
HB_FA_OFFLINE |
HB_FA_NOTINDEXED |
HB_FA_ENCRYPTED |
HB_FA_VOLCOMP ;
if ( pszAttributes && *pszAttributes ) ulMask |= hb_fsAttrEncode( pszAttributes ) ;
if ( pszDirSpec && *pszDirSpec )
{
if ( ( ffind = hb_fsFindFirst( pszDirSpec, ulMask ) ) != NULL )
{
PHB_ITEM pSubarray = hb_itemNew( NULL ) ;
do {
char buffer[ 32 ];
hb_arrayNew( pSubarray, ( ULONG ) 5 ) ;
hb_itemArrayPut( pSubarray, 1, hb_itemPutC( NULL, ( const char * ) ffind->szName ) ) ;
hb_itemArrayPut( pSubarray, 2, hb_itemPutNInt( NULL, ( HB_LONG ) ffind->size ) ) ;
hb_itemArrayPut( pSubarray, 3, hb_itemPutDL( NULL, ( LONG ) ffind->lDate ) ) ;
hb_itemArrayPut( pSubarray, 4, hb_itemPutC( NULL, ( const char * ) ffind->szTime ) ) ;
hb_itemArrayPut( pSubarray, 5, hb_itemPutC( NULL, ( const char * ) hb_fsAttrDecode( ffind->attr, buffer ) ) ) ;
hb_arrayAddForward( pDir, pSubarray );
}
while( hb_fsFindNext( ffind ) ) ;
hb_itemRelease( pSubarray ) ;
}
hb_fsFindClose( ffind ) ;
}
hb_itemReturnRelease( pDir ) ;
}
Y funciona perfectamente (aunque estoy seguro que se puede perfeccionar), así que con este punto de partida podré hacer lo que necesito.
El Único inconveniente es que no he podido/sabido traducir el trozo:
- Code: Select all Expand view
if( ulMask != HB_FA_LABEL )
{
/* CA-Cl*pper compatible behavior - add all file mask when
* last character is directory or drive separator
*/
HB_SIZE nLen = strlen( pszDirSpec ) - 1;
#ifdef HB_OS_HAS_DRIVE_LETTER
if( pszDirSpec[ nLen ] == HB_OS_PATH_DELIM_CHR ||
pszDirSpec[ nLen ] == HB_OS_DRIVE_DELIM_CHR )
#else
if( pszDirSpec[ nLen ] == HB_OS_PATH_DELIM_CHR )
#endif
pszDirSpec = pszFree = hb_xstrcpy( NULL, pszDirSpec, HB_OS_ALLFILE_MASK, NULL ) ;
}
pues en las cabeceras (includes) de mi xHarbour no existen las constantes HB_OS_PATH_DELIM_CHR, HB_OS_DRIVE_DELIM_CHR ni HB_OS_ALLFILE_MASK. Y aunque me imagino algo, con mis limitaciones en C++ no he sido capaz de implementarlo, aunque en realidad pasando atributos y nombres de directorios normales no lo he echado en falta.
Para seguir probando, he implementando una función que me dice si un directorio tiene subdirectorios o no, que seguramente será más rápida que empleando el tradicional Directory():
- Code: Select all Expand view
#define HB_FA_TODOS 65535
HB_FUNC( HASITSUBDIRS ) // HasItSubDirs( LPSTR cSubdir )
{
LPSTR cPath = hb_parc( 1 ) ;
char cDir[MAX_PATH] ;
PHB_FFIND ffind ;
BOOL lDirs = FALSE ;
if ( cPath && *cPath )
{
cDir[0] = 0 ;
strcat( cDir, cPath ) ;
strcat( cDir, "\\*.*" ) ;
if ( ( ffind = hb_fsFindFirst( cDir, HB_FA_TODOS ) ) != NULL )
{
hb_fsFindNext( ffind ) ;
while( hb_fsFindNext( ffind ) && !lDirs ) lDirs = ( ( ffind->attr & 16 ) == 16 ) ;
}
hb_fsFindClose( ffind ) ;
}
hb_retl( lDirs ) ;
}
Otra posible modificación sería hacer que xDirectory devuelva más datos. Como por ejemplo el el nombre de Windows de cada directorio, o la longitud del nombre, etc.
Muy interesante...
Un saludo.