Milán Major

netscape-revival

1 branch
Code

nspr/src/md_Mac/LoggingConsole.c

/************************************************************************/
/*	Project...:	Standard ANSI-C Library									*/
/*	Name......:	console.c												*/
/*	Purpose...:	Stubs for console.c										*/
/*  Copyright.: ©Copyright 1994 by metrowerks inc. All rights reserved. */
/************************************************************************/

#ifndef __CONSOLE__
#include <console.h>
#endif


#include <Errors.h>
#include <Files.h>
#include <Script.h>
#include <TextUtils.h>
#include <Types.h>

#include "MacErrorHandling.h"


/*
 *	The following four functions provide the UI for the console package.
 *	Users wishing to replace SIOUX with their own console package need
 *	only provide the four functions below in a library.
 */


extern long	gInTimerCallback;

// We keep a copy of the file pointer around in a static.
short 	gLogFileRefNum = 0;
FSSpec	gLogFileFSSpec;

#define kLocalLogBufferSize (1024 * 16)
unsigned char gLocalLogBuffer[kLocalLogBufferSize];
unsigned char *gLocalLogBufferMark = gLocalLogBuffer;

/*
 *	extern short InstallConsole(short fd);
 *
 *	Installs the Console package, this function will be called right
 *	before any read or write to one of the standard streams.
 *
 *	short fd:		The stream which we are reading/writing to/from.
 *	returns short:	0 no error occurred, anything else error.
 */

short InstallConsole(short fd)
{
#ifdef DEBUG
	OSErr		err;
	char		*fNameFromEnv;
	StringPtr	fName;
	
	if (gLogFileRefNum != 0)
		return 0;					// ItÕs already been opened.
		
	// Create the FSSpec weÕll use.
	// 1st get the name of the file
	fNameFromEnv = PR_GetEnv("CONSOLE_LOG_NAME");
	
	if (fNameFromEnv == NULL)
		fNameFromEnv = "Console Log\0";
	
	fName = (StringPtr)strdup(fNameFromEnv);
	require ((fName != NULL), exitFail);
	
	// convert to Pascal style name
	fName = c2pstr((char *)fName);
	
	// Create the File Spec
	err = FSMakeFSSpec(0, 0, fName, &gLogFileFSSpec);
	require (((err == noErr) || (err == fnfErr)), exitFailRelease);		// OK if itÕs not there.
		
	// Try to create the file
	err = FSpCreate(&gLogFileFSSpec, 'CWIE', 'TEXT', smSystemScript);
	require (((err == noErr) || (err == dupFNErr)), exitFailRelease);	// OK if it already exists
	
	// Now open it.
	err = FSpOpenDF(&gLogFileFSSpec, fsRdWrPerm, &gLogFileRefNum);
	require ((err == noErr), exitFailRelease);
		
	// Truncate the file
	err = SetEOF(gLogFileRefNum, 0);
	require ((err == noErr), exitFailRelease);
	
	return 0;
	
	
exitFailRelease:
	free (fName);

exitFail:
	return -1;
#else
	#pragma unused(fd)
	return -1;
#endif
}

/*
 *	extern void RemoveConsole(void);
 *
 *	Removes the console package.  It is called after all other streams
 *	are closed and exit functions (installed by either atexit or _atexit)
 *	have been called.  Since there is no way to recover from an error,
 *	this function doesn't need to return any.
 */

void RemoveConsole(void)
{
	OSErr	err;
	
	err = FSClose(gLogFileRefNum);
}

/*
 *	extern long WriteCharsToConsole(char *buffer, long n);
 *
 *	Writes a stream of output to the Console window.  This function is
 *	called by write.
 *
 *	char *buffer:	Pointer to the buffer to be written.
 *	long n:			The length of the buffer to be written.
 *	returns short:	Actual number of characters written to the stream,
 *					-1 if an error occurred.
 */

long WriteCharsToConsole(char *buffer, long n)
{
	int 	i;
	long	spaceInBuffer;
	long	bytesWritten = n;
	long	amtToMove = 0;
	OSErr	err = noErr;

	// Convert LF (0x0A) to CR (0x0D)
	for (i = 0; i < n; i++) {
		if (buffer[i] == '\n')
			buffer[i] = '\r';
	}
	
	if ((gInTimerCallback) || (gLogFileRefNum == 0)) {
		DebugStr("\pYikes, in timer callback");
		
		// Do we have room in the buffer?
		spaceInBuffer = (unsigned long)&gLocalLogBuffer + kLocalLogBufferSize - (unsigned long)gLocalLogBufferMark;
		
		amtToMove = (n > spaceInBuffer) ? spaceInBuffer : n; 
		
		BlockMoveData(buffer, gLocalLogBufferMark, amtToMove);

		gLocalLogBufferMark += amtToMove;
		
		return amtToMove;
	}
	else {
		// Is there anything in the buffer that needs to be written?
		if (gLocalLogBufferMark != gLocalLogBuffer) {
			amtToMove = (unsigned long)gLocalLogBufferMark - (unsigned long)&gLocalLogBuffer;
			err = FSWrite(gLogFileRefNum, &bytesWritten, gLocalLogBuffer);
		}
		if (err == noErr)
			err = FSWrite(gLogFileRefNum, &bytesWritten, buffer);
#if 0
		if (err == noErr)
			err = FlushVol(NULL, gLogFileFSSpec.vRefNum);
#endif	
		return ((err == noErr) ? bytesWritten : -1);
	}
}

/*
 *	extern long ReadCharsFromConsole(char *buffer, long n);
 *
 *	Reads from the Console into a buffer.  This function is called by
 *	read.
 *
 *	char *buffer:	Pointer to the buffer which will recieve the input.
 *	long n:			The maximum amount of characters to be read (size of
 *					buffer).
 *	returns short:	Actual number of characters read from the stream,
 *					-1 if an error occurred.
 */

long ReadCharsFromConsole(char *buffer, long n)
{
#pragma unused (buffer, n)

	return 0;
}

/*
 *	extern char *__ttyname(long fildes);
 *
 *	Return the name of the current terminal (only valid terminals are
 *	the standard stream (ie stdin, stdout, stderr).
 *
 *	long fildes:	The stream to query.
 *
 *	returns char*:	A pointer to static global data which contains a C string
 *					or NULL if the stream is not valid.
 */

extern char *__ttyname(long fildes)
{
#pragma unused (fildes)
	/* all streams have the same name */
	static char *__devicename = "null device";

	if (fildes >= 0 && fildes <= 2)
		return (__devicename);

	return (0L);
}