// macCOPY.c 10/3/90 G.Garchar

#include	"Resources.h"
#include	"memory.h"
#include	"Files.h"
#include	"Types.h"

#include "dosintosh.h" 
	
void macCOPY(char line1[], char line2[], int (*callback[])());

main(char *input, int (*callback[])(), short prefrefnum) {
	unsigned char sPath[256], dPath[256];
	int i;
	
	i = (*callback[ParsePathCallBack])(input,sPath);
	input += i;
	i = (*callback[ParsePathCallBack])(input,dPath);
	macCOPY(sPath,dPath,callback);
	}

#include	"Common.c"		// done after the main() proc!!!


void WildStamp(char pat[], char name[]) {
	/* takes a name and pattern and returns a new name */
	short x, y = 0; // POSITIONS IN PAT AND NAME CHARACTER ARRAYS
	short nLen;
	nLen = strlen(name);
	for (x = 0; pat[x] != '\0'; x++) {
		if (pat[x] == '?') { // SKIP THIS CHARACTER
			if (x < nLen) // PATTERN POSITION WITHIN NAME?
				y += 1;
			}
		else { // STAMP THIS CHARACTER
			if (pat[x] == '*') { // STAMP REMAINING CHARACTERS?
				if (nLen < strlen(name)) name[y] = '\0';
				return;
				}
			name[y] = pat[x];
			y += 1;
			}
		}
	name[y] = '\0'; // NAME SAME LENGTH AS PATTERN
	}
						
		
															
void MakeName(char name[], char spec[]) {
	char dotStr[2] = {'.','\0'};
	char nameExt[256];
	char specExt[256];		
	
	SplitDot(name, nameExt);
	SplitDot(spec, specExt);		
	WildStamp(spec, name);
	WildStamp(specExt, nameExt);
	if (strcmp(nameExt, dotStr) == 0) *nameExt = '\0';
	strcat(name, nameExt);
	strcat(spec, specExt);
	}
			
long GetFileNum(index, volNo, dirID, name, info) 
	short index;
	short volNo;
	long dirID;
	char name[];
	struct {
		OSType fdType;
		OSType fdCreator;
		unsigned long mdDate;
		} *info;
	{
	char pString[256];		
	HFileInfo pBlock;
	
	pBlock.ioNamePtr = pString; // RESERVE STRING MEMORY
	pBlock.ioVRefNum = volNo;
	pBlock.ioFDirIndex = index;
	pBlock.ioDirID = dirID;			
	strcpy(pBlock.ioNamePtr, name);
	c2pstr(pBlock.ioNamePtr);
	if (PBHGetFInfo((HParmBlkPtr)&pBlock, false) == noErr) {
		p2cstr(pBlock.ioNamePtr);
		strcpy(name, pBlock.ioNamePtr);			
		info->fdType = pBlock.ioFlFndrInfo.fdType;
		info->fdCreator = pBlock.ioFlFndrInfo.fdCreator;
		info->mdDate = pBlock.ioFlMdDat;
		return pBlock.ioDirID;
		}
	else
		return 0L;
	}
	
long OpenDest(short dVolNo, long dDirID, char dName[]) {
	/* opens, or creates empty destination file, returns refnum */
	char pString[256];
	HFileInfo pBlock;
	
	pBlock.ioNamePtr = pString; // RESERVE STRING MEMORY
	pBlock.ioVRefNum = dVolNo;
	pBlock.ioDirID = dDirID;
	strcpy(pBlock.ioNamePtr, dName);
	c2pstr(pBlock.ioNamePtr);		
	if (PBHOpen((HParmBlkPtr)&pBlock, false)) { // OPEN DESTINATION
		if (PBHCreate((HParmBlkPtr)&pBlock, false) == noErr)
			PBHOpen((HParmBlkPtr)&pBlock, false);
		else  // FILE CREATION ERROR
			return 0L;
		}
	return pBlock.ioFRefNum;
	}
		
												
OSErr DupFile(short sVolNo, long sDirID, char sName[], short dRefNum) {
	/* opens and reads source file, writes destination, closes source */
	char buffer[512];
	char pString[256];
	HFileInfo pBlock;
	HIOParam pBlock2;
	OSErr eofFlag;
	short sRefNum;
	
	pBlock.ioNamePtr = pString; // RESERVE STRING MEMORY
	pBlock.ioVRefNum = sVolNo;
	pBlock.ioDirID = sDirID;
	strcpy(pBlock.ioNamePtr, sName);
	c2pstr(pBlock.ioNamePtr);
	if (PBHOpen((HParmBlkPtr)&pBlock, false))  // OPEN SOURCE
		return pBlock.ioResult;
	pBlock.ioFDirIndex = 0; // USE NAME & DIRID
	if (PBHGetFInfo((HParmBlkPtr)&pBlock, false))
		return pBlock.ioResult;
	sRefNum = pBlock.ioFRefNum;
	pBlock2.ioBuffer = buffer;
	pBlock2.ioReqCount = sizeof(buffer);
	SetFPos(sRefNum, fsFromStart, 0L);
	do { // TRANSFER DATA
		pBlock2.ioRefNum = sRefNum;
		pBlock2.ioPosMode = fsAtMark;
		PBRead((ParmBlkPtr)&pBlock2, false);  // READ SOURCE
		eofFlag = pBlock2.ioResult;
		pBlock2.ioRefNum = dRefNum;
		pBlock2.ioReqCount = pBlock2.ioActCount;
		pBlock2.ioPosMode = fsFromLEOF;
		pBlock2.ioPosOffset = 0;
		if (PBWrite((ParmBlkPtr)&pBlock2, false)) // WRITE DESTINATION
			return pBlock2.ioResult;
		} while (eofFlag == noErr);
	pBlock2.ioRefNum = sRefNum;
	PBClose((ParmBlkPtr)&pBlock2, false);
	return pBlock2.ioResult;
	}
																	
OSErr SetInfo(volNo, dirID, name, info) 
	short volNo;
	long dirID;
	char name[];
	struct {
		OSType fdType;
		OSType fdCreator;
		unsigned long mdDate;
		} info;
	{
	char pString[256];
	HFileInfo pBlock;
	
	pBlock.ioNamePtr = pString; // RESERVE STRING MEMORY
	pBlock.ioVRefNum = volNo;
	pBlock.ioDirID = dirID;
	strcpy(pBlock.ioNamePtr, name);
	c2pstr(pBlock.ioNamePtr);
	pBlock.ioFDirIndex = 0; // USE NAME & DIRID
	if (PBHGetFInfo((HParmBlkPtr)&pBlock, false))
		return pBlock.ioResult;
	pBlock.ioFlFndrInfo.fdType = info.fdType;
	pBlock.ioFlFndrInfo.fdCreator = info.fdCreator;
	pBlock.ioFlMdDat = info.mdDate;
	pBlock.ioDirID = dirID; //(needed?)
	if (PBHSetFInfo((HParmBlkPtr)&pBlock, false))
		return pBlock.ioResult;
	}
														
		
									
short CopySpec(sVolNo, sDirID, sSpec, dVolNo, dDirID, dSpec, callback)
	short sVolNo;
	long sDirID;
	char sSpec[];
	short dVolNo;
	long dDirID;
	char dSpec[];
	int (*callback[])();
	{
	Boolean dSeparate = true; // FOR AT LEAST FIRST SOURCE FILE
	char dName[256], sName[256];
	char sNameOld[256]; // NEW FILE MIGHT MAKE INDEX+1 REREAD
	HIOParam pBlock2;
	long dRefNum = 0;
	long sFileNum;
	short dFileCount = 0; // TO BE RETURNED
	short index = 0;
	struct {
		OSType fdType;
		OSType fdCreator;
		unsigned long mdDate;
		} info;
	
	do { // FIND FIRST SOURCE FILE
		index += 1;
		sFileNum = GetFileNum(index, sVolNo, sDirID, sName, &info);
		if (!sFileNum) { // FILE NOT FOUND?
			print(string(fnfstr), sSpec);
			return dFileCount;
			}
		} while (SpecMatch(sSpec, sName) == false);
	for (;;) { // DUPLICATE AND FIND NEXT SOURCE
		strcpy(dName, sName);
		MakeName(dName, dSpec);
		if (sDirID == dDirID)
			if (strcmp(sName, dName) == 0) {
				print(string(NoSelfCopyStr));
				return dFileCount;
				}
		/* OPEN DESTINATION */
		dRefNum = OpenDest(dVolNo, dDirID, dName);
		if (!dRefNum) {
			print(string(FCrtErrStr));
			return dFileCount;
			}
		if (dSeparate) { // RESET MARK?
			dFileCount += 1;
			pBlock2.ioRefNum = dRefNum;
			pBlock2.ioMisc = 0; // CLEAR DESTINATION
			PBSetEOF((ParmBlkPtr)&pBlock2, false);
			dSeparate = strchr(dSpec, '*') || strchr(dSpec, '?');
			}
		print(string(nameStr2), sName);
		DupFile (sVolNo, sDirID, sName, dRefNum); // DUPLICATE SOURCE FILE			
		pBlock2.ioRefNum = dRefNum;
		PBClose((ParmBlkPtr)&pBlock2, false); // CLOSE DESTINATION
		SetInfo(dVolNo, dDirID, dName, info);
		strcpy(sNameOld, sName); // SAVE TO COMPARE
		do { // GET NEXT MATCHING SOURCE FILE
			do { // GET NEXT NEW SOURCE FILE
				index += 1;
				sFileNum = GetFileNum(index, sVolNo, sDirID, sName, &info);
				if (sFileNum == 0) return dFileCount;
				} while (strcmp(sNameOld, sName) == 0);
			} while (SpecMatch(sSpec, sName) == false);
		if (!dSeparate) GetDateTime(&info.mdDate);
		}
	}
	
								
void macCOPY(char line1[], char line2[], int (*callback[])()) {
	char path[256];
	char dSpec[256], sSpec[256];
	long dDirID, sDirID;
	short dVolNo, sVolNo;
	short fileCount;
	short result;
	
	if (*line1 == '\0') { // EMPTY COMMAND LINE?
		print(string(invParamStr)); // INVALID NUMBER OF PARAMETERS!
		return;
		}
	/* FIGURE SOURCE */
		result = GetSpec(line1, path, sSpec, &sDirID, &sVolNo);
		if (result == 1) print(string(invSVolStr));
		else if (result == 2) print(string(invSDirStr));
		else { /* FIGURE DESTINATION */
			result = GetSpec(line2, path, dSpec, &dDirID, &dVolNo);
			if (result == 1) print(string(invDVolStr));
			else if (result == 2) print(string(invDDirStr));
			else { // DO COPY
				fileCount = 
					CopySpec(sVolNo, sDirID, sSpec, dVolNo, dDirID, dSpec, callback);
				print(string(footerCopStr), fileCount);
				}
			}
	}