/******************************************************************************
 * program:     wp2latex                                                      *
 * function:    convert WordPerfect files into LaTeX                          *
 * modul:       wp2lfuti.cc                                                   *
 * description: Some File Utilities for WP2Latex converter                    *
 ******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <common.h>

#ifndef __UNIX__
 #include <io.h>
#endif

#include "typedfs.h"
#include "stringa.h"

#include "wp2latex.h"
#include "struct.h"


#ifdef __UNIX__
 #define DIR_DELIMITER '/'
#else
 #define DIR_DELIMITER '\\'
#endif


#ifndef min
 #define min(value1,value2) ((value1 < value2) ? value1 : value2)
#endif

/*----------------------------------------------------*/
/*-------------Basic file I/O operations--------------*/
/*----------------------------------------------------*/


/** Opens a file for writting and optionally checks its existency.
 * @param[in]	name	File name.
 * @param[in]	type	Type of the file.
 * @param[in]   Err     File stream for error message, use NULL when no output is needed. */
FILE *OpenWrChk(const char *name, const char *type, FILE *Err)
{
FILE *fp;

  if(Err==NULL) Err=stderr;
  if(Noclobber)
    {
      if((fp = fopen(name, "r")) != NULL)
      {
        fclose(fp);
        fprintf(Err, _("\nError: File '%s' protected against overwritting."), name);
        return NULL;
      }
    }

  if((fp=fopen(name, type)) == NULL )
    {
    if(Err!=NULL)
        fprintf(Err, _("\nError: File '%s' can not be created."), name);
    return NULL;
    }
return fp;
}



/** Return a size of a file. filelength() is not available in UNIX. */
long filesize(FILE *f)
{
#ifdef __UNIX__
  long pos,len;
  if((pos=ftell(f))<0) return(0);
  fseek(f,0,SEEK_END);
  len=ftell(f);
  fseek(f,pos,SEEK_SET);
  return(len);
#else
  return(filelength(fileno(f)));
#endif
}


/** This procedure copies "Src" file to "Dest"
 * @param[in]	 Dest	destination file name.
 * @param[in]	 Src	source file name.
 * @return	0 on success; <0 on failure. */
int CopyFile(const char *Dest, const char *Src)
{
FILE *in, *out;
char Buff[32];
size_t sz;

 out = fopen(Dest,"rb");
 if(out!=NULL)
	{
	fclose(out);
	return(-1);	//file already exist
	}

 if((in=fopen(Src,"rb"))==NULL)
	return(-2);
 if((out=fopen(Dest,"wb"))==NULL)
    {
    fclose(in);
    return(-3);
    }

 while((sz=fread(Buff,1,sizeof(Buff),in)) > 0)
    {
    fwrite(Buff,1,sz,out);
    }

 fclose(in);
 fclose(out);

return(0);
}


/** This procedure copies 'size' bytes from "Src" file to "Dest".
 * @return	0-OK; <0 Error;
 *              -1 Output file already exists; -2 Invalid input file;
 *		-3 Cannot create output file */
int CopyFile(const char *Dest, FILE *in, long size)
{
FILE *out;
char Buff[32];
size_t sz;

 out = fopen(Dest,"rb");
 if(out!=NULL)
   {
   fclose(out);
   return(-1);		//file already exist
   }

 if(in==NULL) return(-2);

 if(Dest==NULL || (out=fopen(Dest,"wb"))==NULL)
   {
   return(-3);
   }

 while(size > 0)
    {
    if(feof(in)) break;
    sz = fread(Buff, 1, min(sizeof(Buff),size), in);
    if(sz==0 || sz>sizeof(Buff)) break;
    fwrite(Buff,1,sz,out);
    size -= sz;
    }

 fclose(out);

return(size);
}


/** This procedure copies 'size' bytes from "Src" file to "Dest".
 * @return	0-OK; <0 Error;
 *              -1 Invalid output file; -2 Invalid input file; */
int CopyFile(FILE *out, FILE *in, long size)
{
char Buff[32];
size_t sz;

 if(out==NULL) return(-1);
 if(in==NULL) return(-2);

 while(size > 0)
    {
    if(feof(in)) break;
    sz = fread(Buff, 1, min(sizeof(Buff),size), in);
    if(sz==0 || sz>sizeof(Buff)) break;
    fwrite(Buff,1,sz,out);
    size -= sz;
    }

 fclose(out);

return(size);
}


DWORD ch_fgetc(FILE *F)
{
DWORD d;
  d=fgetc(F);
  if(d==EOF) d=0xFFFFFFFF;
  return(d);
}


DWORD w_fgetc(FILE *F)
{
WORD w;
  if(RdWORD_LoEnd(&w,F)<2) return(0xFFFFFFFF);
  return(w);
}


DWORD W_fgetc(FILE *F)
{
WORD w;
  if(RdWORD_HiEnd(&w,F)<2) return(0xFFFFFFFF);
  return(w);
}



/*---------------------------------------------------------*/
/*--------------File related string operations-------------*/
/*---------------------------------------------------------*/

/**This function reads one line from the text file and store it to the string.*/
string & fGets2(FILE *f, string & pstr, long MaxStrSize)
{
  char c;

  pstr="";
  while (!feof(f))
     {
     c = getc(f);
     if (c == '\n') break;
     if (c == '\r') continue;
     if ((unsigned char)c == 0xFF)
	if(feof(f)) break;	//Fix the situation, when 0xFF is read before eof

     pstr += c;
     if(MaxStrSize>0)
        if(--MaxStrSize==0) break;
     }

 return(pstr);
}



/*---------------------------------------------------------*/
/*----------Filename handling string operations------------*/
/*---------------------------------------------------------*/

/**This function returns a positive value >=0 if the given path is absolute*/
int AbsolutePath(const char *TestedPath)
{
 if(TestedPath==NULL) return(-1);
 if(*TestedPath==0) return(-2);

#if defined(__MSDOS__) || defined(__WIN32__) || defined(_WIN32) || defined(_WIN64) || defined(__OS2__)
 if(*TestedPath>' ')	//path is at least 2 byte long
   if(TestedPath[1]==':') return(1);
#endif
#ifdef __UNIX__
 if(*TestedPath=='~') return(1);
#endif

 if(*TestedPath=='\\' || *TestedPath=='/') return(1);

return 0;
}


/** This function extracts filename from a full path */
string CutFileName(const char *FullFilename)
{
char ch;
int i,j;

 if(FullFilename==NULL) return string("Unknown");
 while(*FullFilename==' ') FullFilename++;  //Erase spaces at the beginning of the filename
 i=strlen(FullFilename);
 j=-i;
 if(i==0) return string("Unknown");

 while(i>=0)	//search form end of a string
   {
   ch=FullFilename[i];
   if(ch=='.' && j<0)
	j=i;		//extension found

   if(ch=='/' || ch=='\\' || ch==':')
   	{
	i++;
	break;
	}
   i--;
   }

 if(i<0) i=0;
 if(j<0) j=-j;		//No extension found

return copy(FullFilename,i,j-i);
}


/// This function gets path end position from path and file name.
int GetPathEnd(const char *FullName)
{
unsigned LastPos;
const char *NameStep;

 if(FullName==NULL) return(0);

 LastPos = 0;
 NameStep = FullName;
 while(*NameStep!=0)
   {
   switch(*NameStep)
     {
     case ':':		/* Patch for MsDOS like c:\ or x: */	
	       if(NameStep-FullName == 1)
	          LastPos = NameStep-FullName;
	       break;
     case '/':
     case '\\':LastPos = NameStep-FullName;
               break;
     }
   NameStep++;
   }

return(LastPos);
}


const char *GetExtension(const char *FullName)
{
const char *NameStep;
int LastPos;

if(FullName==NULL) return(NULL);

LastPos=strlen(FullName);
NameStep=FullName+LastPos+1;
while(NameStep>FullName)
	{
	NameStep--;

	if(*NameStep=='/' || *NameStep=='\\' || *NameStep==':')
		break;
	if(*NameStep=='.')
		return(NameStep);
	}

return(FullName+LastPos);
}


/** Obtain filename with extension without leading path. */
const char *GetFullFileName(const char *PathName)
{
const char *NameStep;

 if(PathName==NULL) return(NULL);

 NameStep = PathName+strlen(PathName);
 while(NameStep>PathName)
	{
	if(*NameStep=='/' || *NameStep=='\\' || *NameStep==':')
		return(NameStep+1);
	NameStep--;
	}

return(PathName);
}


temp_string MergePaths(const string & Path, const string & RelPath, bool EnsureTrail)
{
temp_string tmp;
char c;
 if(RelPath=="") return(Path);
 c=RelPath[0];
 if(c=='/' || c=='\\') return(RelPath);

 if(RelPath[0]=='.')
    {
    c=RelPath[1];
    if(c==0) return(Path);
    if(c=='/' || c=='\\')
         {
	 tmp = Path;
         c=Path[StrLen(Path)-1];
         if(c=='/' || c=='\\')
                {
		tmp += RelPath()+2;
		tmp += DIR_DELIMITER;
                return(tmp);
                }
	 tmp += DIR_DELIMITER;
         tmp+=RelPath()+2;
         return tmp;
         }
    }

	// Ensure that resulting path ends with '/' or '\\' based on OS
  tmp = Path+RelPath;
  if(EnsureTrail && length(tmp)>0)
  {
    c = tmp[length(tmp)-1];
    if(c!='/' && c!='\\') tmp += DIR_DELIMITER;
  }
return tmp;
}
