/*
    SUPPL - a supplemental library for common useage
    Copyright (C) 1995,1996  Steffen Kaiser

    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 library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    See: COPYING.LB
*/
/* $Id: DFN.H 1.4 1998/07/20 08:42:46 ska Exp $
   $Locker:  $	$Name:  $	$State: Exp $

	Declarations for the DOS filename functions.

*/

#ifndef __DFN_H
#define __DFN_H

#include <portable.h>

#define DFN_FILENAME_BUFFER_LENGTH 512
	/*!ska Yes, I know that DOS has a more limited length but remember
		this is only twice as much as a Win95 filename can have. */


/* To support UNC paths, all functions are macro'ed from
	dfn*()   --->     dfnu*()
*/
#ifdef SUPPORT_UNC_PATH
#define dfnmerge dfnumerge
#define dfnsplit dfnusplit
#define dfnexpand dfnuexpand
#define dfnsqueeze dfnusqueeze
#define dfnmatch udfnmatch
#endif


int toFUpper(int ch);
/* Upcase character according the filename upcase table of the DOS NLS API.
	The upcase table is retreive only once during the program's run!
*/

void rereadUpcaseTable(void);
/* Mark the previously retreived upcase table as invalid, in order to cause
	that the toUpper() and toFUpper() functions re-retreive the table's
	addresses.
*/

int memcmpFI(const byte *buf1, const byte *buf2, unsigned len);
/* Compare both memory area case-insensitvely.

	To make the compare case-insensitve the toFUpper() function is used.

	If (buf1==NULL) || (buf2==NULL), the behaviour is undefined.
	If len == 0, memcmpFI() returns 0.

	Return:	
		 <0: buf1 is less then buf2
		==0: buf1 is equal to buf2
		 >0: buf1 is greater than buf2
*/

#ifdef _MICROC_
int _fmemcmpFI(unsigned const dseg, unsigned dofs
 , unsigned const sseg, unsigned sofs, unsigned length);
#else
int _fmemcmpFI(const byte far * dest, const byte * src, unsigned length);
#endif
/* Compare both far memory area case-insensitvely.

	To make the compare case-insensitve the toFUpper() function is used.

	If (buf1==NULL) || (buf2==NULL), the behaviour is undefined.
	If len == 0, _fmemcmpFI() returns 0.

	Return:	
		 <0: buf1 is less then buf2
		==0: buf1 is equal to buf2
		 >0: buf1 is greater than buf2
*/


char *dfnexpand(const char fname[], char path[]);
/* Expands a filename to it a fully-qualified DOS-style path relative to path.
	The expanded filename is stored into a malloc'ed buffer.
	fname[] is preprocessed by dfnsqueeze().

	If path == NULL, the current working directory is used.

   Return:
   	NULL: malloc failed or fname == NULL
	else: pointer to the malloc'ed buffer
*/

char *dfnmerge(char fname[], const char dr[], const char path[]
 , const char name[], const char ext[]);
/* Merge a file name.

	dr, path, name, ext:
		Pointers of the path components.
		If one of these is NULL (thus, it is not present), it is not merged.
		If (*path=='\0'), this means the root path!

	fname := <dr>:<path>\<name>.<ext>
		':' is added, if <dr> is present;
		'\' is added, if <path>,& <name> or <ext> are present;
		'.' is added, if <ext> is present.

	fname:	Pointer to the memory to receive the result.
			If NULL: the necessary memory is malloc'ed.

   Return:
   	NULL if malloc failed.
   	otherwise: pointer to the beginning of the malloc()'ed result.
*/

int dfnsplit(char fname[], char **dr, char **path, char **name, char **ext);
/* Split a file name.

	fname is the file name to split.

	dr, path, name, ext:	Pointers, which will receive the results.
							If one pointer is NULL, the particular filename
								portion is not saved.
							If one pointer receives NULL, the particular
								portion was not found in fname.
							dr does not has the ':'.
							The trailing '\\' is stripped from path.
								==> ญญ (**path=='\0') -> Root path!!
									(This is not a bug but a feature ;-)
							ext does not contain the leading '.'; ext itself
								contains no dot at all.
							Multiple backslashes are reduced to a single one.
							name may start with any number of dots.

	The returned pointers in dr, path, name,& ext are malloc()'ed;
	thus, they must be free()'ed by the programmer!

   Return:
   	0: Transformation failed, e.g. malloc() returned NULL
	1: dfnsplit() OK
*/

char *dfnsqueeze(const char fname[]);
/* Preprocess a filename:
		- Flip '/' -> '\\'
		- Squeeze '\\\\' -> '\\'
		- Squeeze '\\.\0' -> '\\'
		- Squeeze '\\.\\' -> '\\'
		- Upcase all characters (using DOS NLS API)

	The preprocessed filename is copied into a malloc'ed buffer.

   Return:
   	NULL: malloc failed or fname == NULL
	else: pointer to the malloc'ed buffer
*/

char *dfnpath(int drive);
/* Retreive the fully-qualified path of: "<drive>:."
	The path is malloc()'ed and has _no_ trailing backslash, except the
	path is the root directory.

	drive may be:
		'A'-'Z', 'a'-'z', or 1..32 (note: 1 == 'A'; supports up to 32 drives)
		0 == current drive

	Return:
		NULL: malloc() failed, non-existing drive, or drive invalid
		else: pointer to the path
*/

char *dfntruename(const char fn[]);
/* Return the truename of the file named fn.

	The truename of a file is a fully-qualified filename according
	the _physical_ access path. That means that the truename can be
	used to exactly determine, if two file specifications match the
	same physical file, e.g.:
			SUBST Z: C:\FREEDOS
		&& C:\FREEDOS\SUBST.EXE exists
		&& the current working directory is C:\FREEDOS ==>
			dfntruename("a:/subst.exe") --> "C:\\FREDOS\\SUBST.EXE"
			dfntruename("subst.exe") --> "C:\\FREEDOS\\SUBST.EXE"
	The filename fn[] need not exist.

	Return:
		NULL: malloc() failed, or DOS API call failed
		else: pointer to the malloc()'ed string

	But beware! The truename must not be used as a function to fully-qualify
	a filename. There are at least two cases when that fails:
		<<see source code "DFNTRUEN.C" for more details>>
*/

char *dfnsearch(char fname[], char *path, char *ext);
/* Search for the file fname[] within the search path *path. If no extension
	is supplied, all extensions in *ext are tried. *ext may contain wildcards.

	If path==NULL, the environment variable "PATH" is retreived.
	If *path==0, no search path is available (thus, scanning in current
	working directory only).
	If ext==NULL, the extensions ".COM.EXE.BAT" are used.
	If *ext==0, the extension is not altered.
	if *ext=='.', this dot is ignored at all.

	If path contains an entry ".", the current working directory is not
	tried first.
	If the program is running in an Windows environment, the default Windows
	pathes are not prepended automatically.

	If fname[] already contains a drive or path specification, path is ignored.
	If fname[] already contains an extension, ext is ignored.

	The returned filename is not necessarily fully-qualified, nor it is
	pre-processed by dfnsqueeze(). All what is asured is that the returned
	filename can be found relative to the current working directory. The
	function does neither try to open the file nor to asure that this file
	is executable in any way. But Hidden or System files are not included
	into the search.

	Return:
		NULL: fname[] == NULL, *fname == 0, no file found, malloc() failed
		else: pointer to fully-qualified filename, it's malloc()'ed
*/

int dfnmatch(char *fnam, char *pattern);
/*	Check if the filename matches the DOS-style pattern.

	Components, like '.' and '..', and the drive are matched literally.
	Further details see dfnmatch.c.
*/

int isUNCpath(const char fname[]);
/* Return, if fname[] is an UNC path. It is preceeded by two backslashes.
*/

char *UNCpath(const char fname[]);
/* Return a pointer to the first character of fname[], that is not a part
	of the UNC drive specification. That is either '\\', the root direc
	specificator, or '\0', if no path is following the UNC drive at all.

	Return:
		NULL: fname[] has no UNC drive spec
		else: pointer to a) '\\' the root direc mark; or b) '\0' if no path
*/

#endif
