/*
 * $Id$
 */

/*
 * Harbour Project source code:
 * Harbour common FileSys API (accessed from standalone utilities and the RTL)
 *
 * Copyright 1999 Victor Szakats <info@szelvesz.hu>
 * www - http://www.harbour-project.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version, with one exception:
 *
 * The exception is that if you link the Harbour Runtime Library (HRL)
 * and/or the Harbour Virtual Machine (HVM) with other files to produce
 * an executable, this does not by itself cause the resulting executable
 * to be covered by the GNU General Public License. Your use of that
 * executable is in no way restricted on account of linking the HRL
 * and/or HVM code into it.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA (or visit
 * their web site at http://www.gnu.org/).
 *
 */

#include "hbapi.h"
#include "hbapifs.h"

/* Split given filename into path, name and extension, plus determine drive */
PHB_FNAME hb_fsFNameSplit( char * pszFileName )
{
   PHB_FNAME pFileName;
   char * pszPos;
   char * pszAt;

   HB_TRACE(HB_TR_DEBUG, ("hb_fsFNameSplit(%s)", pszFileName));

   HB_TRACE(HB_TR_INFO, ("hb_fsFNameSplit: Filename: |%s|\n", pszFileName));

   /* Grab memory, set defaults */

   pFileName = ( PHB_FNAME ) hb_xgrab( sizeof( HB_FNAME ) );

   pszPos = pFileName->szBuffer;

   /* Find the end of the path part, and find out where the
      name+ext starts */

   pszAt = NULL;
   if( pszFileName[ 0 ] != '\0' )
   {
      int iPos = strlen( pszFileName );

      while( --iPos >= 0 )
      {
         if( strchr( OS_PATH_DELIMITER_LIST, pszFileName[ iPos ] ) )
         {
            pszAt = pszFileName + iPos;
            break;
         }
      }
   }

   if( pszAt )
   {
      pFileName->szPath = pszPos;
      strncpy( pszPos, pszFileName, pszAt - pszFileName + 1 );
      pszPos += pszAt - pszFileName + 1;
      *pszPos++ = '\0';
      pszFileName = pszAt + 1;
   }
   else
      pFileName->szPath = NULL;

   /* From this point pszFileName will point to the name+ext part of the path */

   /* Split the filename part to name and extension */

   pszAt = strrchr( pszFileName, '.' );
   if( pszAt && pszAt != pszFileName )
   {
      pFileName->szName = pszPos;
      strncpy( pszPos, pszFileName, pszAt - pszFileName );
      pszPos += pszAt - pszFileName;
      *pszPos++ = '\0';

      pFileName->szExtension = pszPos;
      strcpy( pszPos, pszAt );
      pszPos += strlen( pszAt ) + 1;
   }
   else
   {
      if( pszFileName[ 0 ] != '\0' )
      {
         pFileName->szName = pszPos;
         strcpy( pszPos, pszFileName );
         pszPos += strlen( pszFileName ) + 1;
      }
      else
         pFileName->szName = NULL;

      pFileName->szExtension = NULL;
   }

   /* Duplicate the drive letter from the path for easy access on
      platforms where applicable. Note that the drive info is always
      present also in the path itself. */

   if( pFileName->szPath && ( pszAt = strchr( pFileName->szPath, ':' ) ) != NULL )
   {
      pFileName->szDrive = pszPos;
      strncpy( pszPos, pFileName->szPath, pszAt - pFileName->szPath + 1 );
      pszPos += pszAt - pFileName->szPath + 1;
      *pszPos = '\0';
   }
   else
      pFileName->szDrive = NULL;

   HB_TRACE(HB_TR_INFO, ("hb_fsFNameSplit:   szPath: |%s|\n", pFileName->szPath));
   HB_TRACE(HB_TR_INFO, ("hb_fsFNameSplit:   szName: |%s|\n", pFileName->szName));
   HB_TRACE(HB_TR_INFO, ("hb_fsFNameSplit:    szExt: |%s|\n", pFileName->szExtension));
   HB_TRACE(HB_TR_INFO, ("hb_fsFNameSplit:  szDrive: |%s|\n", pFileName->szDrive));

   return pFileName;
}

/* NOTE: szFileName buffer must be at least _POSIX_PATH_MAX long */

/* This function joins path, name and extension into a string with a filename */
char * hb_fsFNameMerge( char * pszFileName, PHB_FNAME pFileName )
{
   char * pszName;

   HB_TRACE(HB_TR_DEBUG, ("hb_fsFNameMerge(%p, %p)", pszFileName, pFileName));

   /* Set the result to an empty string */
   pszFileName[ 0 ] = '\0';

   /* Strip preceding path separators from the filename */
   pszName = pFileName->szName;
   if( pszName && pszName[ 0 ] != '\0' && strchr( OS_PATH_DELIMITER_LIST, pszName[ 0 ] ) )
      pszName++;

   /* Add path if specified */
   if( pFileName->szPath )
      strcat( pszFileName, pFileName->szPath );

   /* If we have a path, append a path separator to the path if there
      was none. */
   if( pszFileName[ 0 ] != '\0' && ( pszName || pFileName->szExtension ) )
   {
      int iLen = strlen( pszFileName ) - 1;

      if( strchr( OS_PATH_DELIMITER_LIST, pszFileName[ iLen ] ) == NULL )
      {
         char szPathSep[ 2 ];

         szPathSep[ 0 ] = OS_PATH_DELIMITER;
         szPathSep[ 1 ] = '\0';

         strcat( pszFileName, szPathSep );
      }
   }

   /* Add filename (without extension) if specified */
   if( pszName )
      strcat( pszFileName, pszName );

   /* Add extension if specified */
   if( pFileName->szExtension )
   {
      /* Add a dot if the extension doesn't have it */
      if( pFileName->szExtension[ 0 ] != '\0' && 
          pFileName->szExtension[ 0 ] != '.' )
         strcat( pszFileName, "." );

      strcat( pszFileName, pFileName->szExtension );
   }

   HB_TRACE(HB_TR_INFO, ("hb_fsFNameMerge:   szPath: |%s|\n", pFileName->szPath));
   HB_TRACE(HB_TR_INFO, ("hb_fsFNameMerge:   szName: |%s|\n", pFileName->szName));
   HB_TRACE(HB_TR_INFO, ("hb_fsFNameMerge:    szExt: |%s|\n", pFileName->szExtension));
   HB_TRACE(HB_TR_INFO, ("hb_fsFNameMerge:  szDrive: |%s|\n", pFileName->szDrive));
   HB_TRACE(HB_TR_INFO, ("hb_fsFNameMerge: Filename: |%s|\n", pszFileName));

   return pszFileName;
}

