//	IC_Errors.c

#include "Carbon68kGlue.h"
#include "stdio.h"
#include "Utils.h"
#include "offscreen_manager.h"
#include "ADFS_LogFile.h"
#include "IC_Errors.h"

ErrorString		g_errorStrings[IC_Err_NUMTYPES] = {
	"No error", 
	"System Error", 
	"Break from loop", 
	"Couldn't load the dialog.", 
	"Couldn't load a dialog item.", 
	"Wrong number of dialog items.", 
	"Illegal conversion.", 
	"Unsupported Image Type.", 
	"Not a DOS 3.3 disk.", 
	"Not a ProDOS disk.", 
	"Not a Pascal disk.", 
	"Not a CP/M disk.", 
	"Out of memory.", 
	"Unsupported file system.", 
	"Can't read ProDOS block.", 
	"Not really a folder.", 
	"Can't locate file: Ò%sÓ", 
	"Can't seek file: Ò%sÓ", 
	"You are about to crash.",
	"Directory full.",
	"Disk full.",
	"Can't read nibblized disk images.", 
	"Trying to read past end of disk.", 
	"Trying to read past end of file.", 
	"Illegal ProDOS file storage type.", 
	"Can't quite handle forked files (yet)", 
	"Can't handle files with storage type 'Pascal Area'", 
	"Prepare: Origin Not Zero!", 
	"Prepare: Already Prepared!", 
	"ProDOS: Extended directory, but couldn't fine empty entry?", 
	"File too large", 
	"Entry not found", 
	"Can't delete file, file already deleted!", 
	"Can't delete file, directory already empty.",
	"Must read/write only on sector boundaries.",
	"Can't write more than one block at a time.",
	"Couldn't load prefs file. Try setting the owner to you in the finder.",
	"Illegal track/sector access.", 
	"File locked.", 
	"Disk locked.", 
	"File or Disk locked.", 
	"File already exists.",
	"Invisible File.", 
	"Not a block device.",  
	"Not a sector device.", 
	"Can't read Pascal Block"
	//	when adding strings, don't for get the comma above the last one
};

//	SBI:Utils.h
int			check_key_down(long key_mask);
void		HandleEvent(EventRecord *theEvent);

static	pascal Boolean		MyModalDialogFilterProc(
    DialogRef		theDialog, 
    EventRecord		*theEvent, 
    DialogItemIndex	*itemHit)
{
	Boolean		handledB = FALSE;

	switch (theEvent->what) {
	
		case osEvt:
		case updateEvt: {
			if (GetDialogWindow(theDialog) != (WindowRef)theEvent->message) {
				HandleEvent(theEvent);
			} else {
				DrawDialog(theDialog);
			}
			break;
		}
	}

	if (!handledB) {
		handledB = StdFilterProc(theDialog, theEvent, itemHit);
	}

	return handledB;
}

#define			kMaxQueuedErrors	10
#define			kMaxBigStrSize		256

typedef char	BigErrStr[kMaxBigStrSize];
BigErrStr		g_QueuedErrors[kMaxQueuedErrors];
short			g_numQueuedErrors	= 0;
short			g_quietErrors		= 0;

void		QuietErrors(Boolean quietB)
{
	if (quietB) {
		g_quietErrors++;
	} else {
		g_quietErrors--;
	}
}

Boolean		ReportPendingErrors(void)
{
	g_quietErrors = FALSE;

	if (g_numQueuedErrors) {
		short		curError;
		
		for (curError = 0; curError < g_numQueuedErrors; curError++) {
			AlertID(g_QueuedErrors[curError], -1);
		}
		
		g_numQueuedErrors = 0;
	}
	
	return TRUE;
}

void		AlertID(char *errStrZ, long errNum)
{
	char			errNumString[255] = "";
    
   	if (errNum == -1) {
	    strcpy(errNumString, errStrZ);
	} else {
	    sprintf(errNumString, "%s  Error: %ld", errStrZ, errNum);
	}
	
	if (g_quietErrors) {
		if (g_numQueuedErrors < kMaxQueuedErrors) {
			ushort		strLenS = strlen(errNumString);
			char		*strZ;
			
			if (strLenS >= kMaxBigStrSize) {
				strLenS = kMaxBigStrSize - 1;
			}
			
			strZ = g_QueuedErrors[g_numQueuedErrors++];

			memcpy(strZ, errNumString, strLenS);
			strZ[strLenS] = 0;
		}
	} else {
		short			itemHit;
		PortAndDevice	savePD;
	    ModalFilterUPP	modalFilterProc = NewModalFilterUPP(MyModalDialogFilterProc);
		DialogRef		gAlertWindow = NULL;

		g_quietErrors++;

		ADFS_Log(errNumString);
		ADFS_Log("\n");
		
		CopyCStringToPascal(errNumString, (uchar *)errNumString);
		ParamText((StringPtr)&errNumString, (StringPtr)"\p", (StringPtr)"\p", (StringPtr)"\p");

		GetPortAndDevice(&savePD);

		gAlertWindow = GetNewDialog(200, NULL, (WindowRef)-1);
		SetDialogDefaultItem(gAlertWindow, 1);
		SetPort(GetDialogPort(gAlertWindow));

		SetStandardCursor(arrowCursor);

		do {
			ModalDialog(modalFilterProc, &itemHit);
		} while (itemHit != 1);

		DisposeModalFilterUPP(modalFilterProc);
		DisposeDialog(gAlertWindow);
		gAlertWindow = NULL;

		SetPortAndDevice(&savePD);

		if (errNum == IC_Err_YOU_WILL_CRASH) {
			DebugStr((uchar *)errNumString);
			ExitToShell();
		}
		
		if (check_key_down(option_key)) {
			DebugStr("\pExiting because of programmer break.");
		}
		
		g_quietErrors--;
	}
}

Boolean		ReportErrorStr(OSErr err, char *errStr)
{
	AlertID(errStr, err);
	return TRUE;
}

void		ReportOSErr(OSErr err)
{
	char		*errStr = g_errorStrings[1];
	
	switch (err) {
	}

	ReportErrorStr(err, errStr);
}

Boolean		ReportError(OSErr err)
{
	char		*errStr = g_errorStrings[1];
	
	if (err >= 1 && err < IC_Err_NUMTYPES) {
		errStr = g_errorStrings[err];
	}

	return ReportErrorStr(err, errStr);
}

long	AssertFailed(
	const char *assertion, 
	const char *file_name, 
	long line_number)
{
	char	str1[256];
	
	sprintf(str1, "Assert Fail: Ò%sÓ.  Line %d of file %s.", 
		assertion, (int)line_number, file_name);
	
	ReportErrorStr(-1, str1);

	return 0;
}

void		ReportFreeSpace(unsigned long neededMem)
{
	char 	alertStr[256];
	char 	kStr[32];
	Size		size;
	
	PurgeMem((long)neededMem);
	size = CompactMem((long)neededMem);

	sprintf((char *)kStr, "%d", (int)(((float)(neededMem - size) / 1024.0) + 1));
	sprintf(alertStr, 
		"Out of memory!  Use 'Get Info' in the finder to add at least "
		"%s K to the application.", kStr);
	
	AlertID(alertStr, -1);
}

