/*static char *SCCSID = "@(#)crackpth.c	6.2 92/01/31";*/
#define ASWAP1 ASWAP1
#define INCL_DOSERRORS
#include <os2def.h>
#include <bse.h>
#include <fsh.h>	/* for dbcs.h */
#include <cdib.h>

#include "api.h"
#include "const.h"
#include "chain.h"
#include "misc.h"
#include "buf.h"
#include "dir.h"
#include "storage.h"
#include "volume.h"
#include "frame.h"
#include "tables.h"
#include "lw.h"
#include "fsdata.h"
#include "heap.h"
#include "dbcs.h"
#include "codepage.h"
#include "pr_wrsub.h"
#include "pr_heap.h"
#include "pr_misc.h"

#ifdef DEBUG
#include "pr_debug.h"
#endif

/*
 ***	CrackPath - convert path name to pinball form
 *
 *	This routine copies a pathname from an OS/2 buffer to a pinball
 *	buffer and converts the name to pinball's internal form in the
 *	process.  The internal form of the path buffer is:
 *		DW	hVPB		; volume for path
 *		DW	pathlen		; offset of the namlen byte -----+
 *		DB	len1		; length of first path element	 |
 *		DB	"path1"						 |
 *		.							 |
 *		.							 |
 *		DB	lenn		; length of last path element	 |
 *		DB	"pathn"						 |
 *		DB	namlen		; length of name component <-----+
 *		DB	"name"
 *
 *	"pathlen" is the total length of all path elements including
 *	the pathlen value.  In other words, it's the offset of the
 *	"namlen" byte in the result structure.  All lengths include the
 *	length byte itself, so a file/directory name of "A" is coded as
 *		DB	2,"A"
 *
 *	All "\" characters are removed.  If the pathname has no directories
 *	in it (i.e., the root directory) then PATHLEN = 2.
 *
 *	BUGBUG - deal with DBCS issues.
 *
 *	ENTRY	hVPB = handle to volume
 *		pbString = ptr to OS/2 path name (null terminated string)
 *		pcp = ptr to cracked path buffer
 *	EXIT	pcp = ptr to cracked path
 *		returns
 *		    NO_ERROR
 *		    ERROR_FILENAME_EXCED_RANGE
 *		    ERROR_NOT_ENOUGH_MEMORY
 *
 *	HISTORY
 *	    19-Sep-89 by JR (John Rogers, JohnRo@Microsoft)
 *		- Avoid warnings from Microsoft C 5.2 (on slash-slash comments).
 */

USHORT
CrackPath (
    HVOL hVPB,			/* volume path is relative to */
    PBYTE pbString,		/* path name as an ASCIIZ string */
    PCRACKEDPATH far *ppcp,	/* buffer to crack name into */
    PFRAME pfrm)
{
	USHORT cusPath;		/* count of total bytes in path */
	int cbName;		/* count of bytes in name + length byte */
	PBYTE pbName;		/* ptr to length byte of name */
	PCRACKEDPATH pcp;
	PBYTE pbTemp;		/* ptr to next component */

	PCPENTRY pCPEnt;	/* ptr to cur code page entry */
	UINT iCP;		/* index to current code page (in global
				 * table) - put into cracked path */

	iCP = 0;

	/* Code Page ID 0 means use the first one (0) */
	if (*pcurCodePage != 0) {
	    while ((paCodePageEnt [iCP].CodePageID) != *pcurCodePage) {
#ifdef DEBUG

		if (iCP >= cCodePage) {
		    dprintf (__FILE__": Couldn't find current code page\n");
		    Int3 ();
		}

		if ((paCodePageEnt [iCP].bFlags & CPF_REQUIRED) == 0) {
		    dprintf ("%s: Current code page not in required set\n",
			     __FILE__);
		    Int3 ();
		}
#endif
		iCP++;
	    }
#ifdef DEBUG
	    if ((paCodePageEnt [iCP].CountryCode != 0) &&
		(paCodePageEnt [iCP].CountryCode != usCountry)) {
		dprintf (__FILE__": Code page matches, but country code doesn't\n");
		Int3 ();
	    }
#endif
	}

	pCPEnt = &paCodePageEnt [iCP];

	if ((pcp = *ppcp = GHS (CPATHBUFSIZE,pfrm)) == NULL)
		return (ERROR_NOT_ENOUGH_MEMORY);

	pbString += 3;			/* skip over "x:\" */
	pbName = &pcp->sp.c;		/* point to name length byte */
	cusPath = sizeof (pcp->cbPath);	 /* sizeof (path length) */

	/*
	 * For each dir name and file name (separated by '\'),
	 * calculate the length and store name preceeded by length
	 * in cracked path.
	 * Also, add the length of each name to the path length.
	 */
	do {
		pbTemp = pbString;
		if (FSH_FINDCHAR (1, "\\", &pbTemp) == NO_ERROR) {
		    /* *pbTemp points to '\\' */
		    cbName = (pbTemp - pbString);
		} else {
		    /* no more "\\" in path */
		    cbName = fstrlen (pbTemp);
		}

		/* upcase the name (if any) */
		if (cbName) {
		    NameUpCase (pbString, cbName, pCPEnt, pbName + 1);
		    pbString += cbName;
		}

		if (++cbName > PB_CCHMAXPATHCOMP)
		    return ERROR_FILENAME_EXCED_RANGE;

		*pbName = (BYTE)cbName; /* store name length */
		pbName += cbName;	/* point to next name */
		cusPath += cbName;	/* add to path length */
	} while (*pbString++ != 0);

	/* the max path size takes into account a null terminator
	 * (we do not store the null character in our cracked path)
	 */
	if (cusPath >= CPATHBUFSIZE)
	    return ERROR_FILENAME_EXCED_RANGE;

	pcp->cbPath = cusPath - cbName; /* offset of file name */
	pcp->hVPB = hVPB;		/* copy into buffer for FindDir */
	pfrm->pbLastName = pbTemp;	/* pointer to last mixed-case name -
					 * used by LDECreate */
	pfrm->iCP = (BYTE) iCP;		/* index for current code page (in
					 * global code page array) - used
					 * by LDECreate */

	return NO_ERROR;
}
