//  This may look like C code, but it is really -*- C++ -*-

//  ------------------------------------------------------------------
//  The Goldware Library
//  Copyright (C) 1990-1999 Odinn Sorensen
//  Copyright (C) 1999-2000 Alexander S. Aganichev
//  ------------------------------------------------------------------
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library 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
//  Library General Public License for more details.
//
//  You should have received a copy of the GNU Library General Public
//  License along with this program; if not, write to the Free
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
//  MA 02111-1307, USA
//  ------------------------------------------------------------------
//  $Id: gfilutl2.cpp,v 1.8 2002/11/04 18:59:49 asa Exp $
//  ------------------------------------------------------------------
//  File utility functions
//  ------------------------------------------------------------------

#include <gfilutil.h>
#ifndef __HAVE_DRIVES__
#include <pwd.h>
#endif
#ifdef __WIN32__
#include <windows.h>
#endif


//  ------------------------------------------------------------------

std::string& AddBackslash(std::string& p) {

  for(size_t posn = 0; (posn=p.find(GOLD_WRONG_SLASH_CHR, posn)) != p.npos; posn++)
    p[posn] = GOLD_SLASH_CHR;
  if(p[p.length()-1] != GOLD_SLASH_CHR)
    p += GOLD_SLASH_STR;

  return p;
}


//  ------------------------------------------------------------------
//  Add path to filename, if no path is set

void MakePathname(std::string& pathname, const std::string& path, const std::string& name) {

  Path pn;
  MakePathname(pn, path.c_str(), name.c_str());
  pathname = pn;
}


//  ------------------------------------------------------------------

void PathCopy(std::string& dst, const char* src) {

  dst = src;
  strschg_environ(dst);
  AddBackslash(dst);
}


//  ------------------------------------------------------------------

int strschg_environ(std::string& s) {

  std::string fnd;
  int replaced = 0;
  size_t posn, posn1;

  while(((posn=s.find('%')) != s.npos) and ((posn1=s.find('%', posn+1)) != s.npos)) {
    fnd = s.substr(posn+1, posn1-1); 
    const char* rep = getenv(fnd.c_str());
    rep = rep ? rep : "";
    s.replace(posn, posn1-posn+1, rep);
    replaced++;
  }

#ifndef __HAVE_DRIVES__
  if(not s.empty() and (s[0] == '~')) {
    std::string name;
    char* lname;
    const char *p = s.c_str()+1;
    if((s.length() != 1) and not isslash(*p)) {
      while(*p and not isslash(*p))
        name += *p++;
    }
    else {
      if ((lname = getlogin()) == NULL)
        lname = getenv("LOGNAME");
      name = lname;
    }
    struct passwd *pe = getpwnam(name.c_str());
    if(pe != NULL) {
      std::string dirname = pe->pw_dir;
      dirname += "/";
      if(isslash(*p))
        ++p;
      dirname += p;
      s = dirname.c_str();
      replaced++;
    }
  }
#endif

  return replaced;
}


//  ------------------------------------------------------------------

bool maketruepath(std::string &dirname) {

  bool ok = true;
  std::string ndirname;
  char cwd[GMAXPATH];
  getcwd(cwd, GMAXPATH);
#ifdef __HAVE_DRIVES__
#ifdef __WIN32__
  char expanded[GMAXPATH];
  char *k;
  if(GetFullPathName(dirname.c_str(), GMAXPATH, expanded, &k) == 0) {
    dirname = cwd;
    ok = false;
  }
  else {
    if(access(expanded, R_OK) == 0)
      dirname = expanded;
    else {
      dirname = cwd;
      ok = false;
    }
  }
#elif defined __OS2__
  char expanded[GMAXPATH];
  if(_fullpath(expanded, dirname.c_str(), GMAXPATH) == 0) {
    if(access(expanded, R_OK) == 0)
      dirname = expanded;
    else {
      dirname = cwd;
      ok = false;
    }
  }
  else {
    dirname = cwd;
    ok = false;
  }
#elif defined __DJGPP__
  char expanded[GMAXPATH];
  _fixpath(dirname.c_str(), expanded);
  if(access(expanded, R_OK) == 0)
    dirname = expanded;
  else {
    dirname = cwd;
    ok = false;
  }  
#else
  long inspos = -1;
  if((dirname.length() == 2) and (dirname[1] == ':'))
    inspos = 2;
  else if((dirname.length() < 2) or (dirname[1] != ':') or isslash(dirname[0]))
    inspos = 0;
  else if(not isslash(dirname[2]))
    inspos = 2;
  if(inspos != -1) {
    char chdrive[] = " :";
    chdrive[0] = (inspos == 2) ? dirname[0] : cwd[0];
    if(not chdir(chdrive)) {
      char dwd[GMAXPATH];
      getcwd(dwd, GMAXPATH);
      if(isslash(dirname[0]))
        ndirname = chdrive;
      else {
        ndirname = dwd;
        ndirname += "/";
      }
      ndirname += dirname.c_str() + inspos;
      dirname = ndirname;
    } else {
      dirname = cwd;
      ok = false;
    }
    chdir(cwd);
  }
#endif
#else
  if(not dirname.empty() and (dirname[0] == '~')) {
    char* lname;
    const char *p = dirname.c_str()+1;
    if((dirname.length() != 1) and not isslash(*p)) {
      while(*p and not isslash(*p))
        ndirname += *p++; // get user name
    } else {
      if ((lname = getlogin()) == NULL)
        lname = getenv("LOGNAME");
      ndirname = lname; // get current user name
    }
    struct passwd *pe = getpwnam(ndirname.c_str()); // get home
    if(pe != NULL) {
      ndirname = pe->pw_dir;
      ndirname += "/";
      if(isslash(*p))
        ++p;
      ndirname += p;
      dirname = ndirname;
    } else {
      dirname = cwd;
      ok = false;
    }
  } else if(not dirname.empty() and not isslash(dirname[0])) {
    ndirname = cwd;
    ndirname += "/";
    ndirname += dirname;
    dirname = ndirname;
  }
#endif
  size_t posn;
  for(posn = 0; (posn=dirname.find(GOLD_WRONG_SLASH_CHR, posn)) != dirname.npos; posn++)
    dirname[posn] = GOLD_SLASH_CHR;
  size_t skipfrom, skipto;
#ifdef __HAVE_DRIVES__ /* Prevent from destroying UNC names */
  if(dirname.length() > 1) {
    while((skipfrom=dirname.find("\\\\", 1)) != dirname.npos)
      dirname.erase(skipfrom, 1);
  }
#endif
  size_t len = dirname.length();
#ifdef __HAVE_DRIVES__
  while((len > 3) and isslash(dirname[--len]))
#else
  while((len > 1) and isslash(dirname[--len]))
#endif
    dirname.erase(len, 1);
  if(access(dirname.c_str(), R_OK)) {
    dirname = cwd;
    ok = false;
  }
#ifdef __HAVE_DRIVES__
  if((dirname.length() > 2) and (dirname[0] == '\\') and (dirname[1] == '\\'))
    posn = 2;
  else
#endif
    posn = 0;
  for(; (posn=dirname.find('\\', posn)) != dirname.npos; posn++)
    dirname[posn] = '/';
  while((skipto=dirname.find("/../")) != dirname.npos) {
    skipfrom = (skipto == 0) ? 0 : dirname.rfind('/', skipto-1);
    skipto += 2;
    dirname.erase(skipfrom, skipto-skipfrom+1);
  }
  while((skipfrom=dirname.find("/./")) != dirname.npos)
    dirname.erase(skipfrom, 2);
  len = dirname.length();
  if(len > 2 and not strcmp(&(dirname.c_str()[len-2]), "/."))
    dirname.erase(len-2, 2);
  len = dirname.length();
#ifdef __HAVE_DRIVES__
  if((len > 3) and isslash(dirname[--len]))
#else
  if((len > 1) and isslash(dirname[--len]))
#endif
    dirname.erase(len, 1);
  return ok;
}


//  ------------------------------------------------------------------
