{\rtf0\ansi{\fonttbl\f1\fswiss Helvetica;\f0\fmodern Courier;\f2\fnil Times-Roman;}
\paperw11760
\paperh7800
\margl120
\margr120
{\colortbl;\red0\green0\blue0;}
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b\i0\ulnone\fs24\fc0\cf0 #import "Object_AllocNDebug.h"\
#import <appkit/appkit.h>\
#import <stdlib.h>\
\
#ifndef REPLY_REQUEST0\
#	define REPLY_REQUEST0 "reply_request0"\
#	define REPLY_REQUEST1 "reply_request1"\
#	define REPLY_REQUEST2 "reply_request2"\
#endif\
\
@implementation Object(AllocNDebug)\
\

\b0\i\fc1\cf1 /* The class debug flag 
\fc0\cf0 Any debug message with a level below the appDebugLevel\
	is processed, while a message with a level above or euqal to appDebugLevel is\
	ignored.  The default value does not allow debug messages. */
\b\i0 \
static int appDebugLevel = NO_DEBUG;\

\b0\i\fc1\cf1 /* The class debug FILE* */
\b\i0\fc0\cf0 \
static FILE *errFile;\

\b0\i\fc1\cf1 /* A flag indicating if +initialize has been invoked */
\b\i0\fc0\cf0 \
static BOOL classInited = NO;\

\b0\i\fc1\cf1 /* The class NXStringTable of error messages */
\b\i0\fc0\cf0 \
static NXStringTable *errStringTable;\
\

\b0\i\fs28\fc1\cf1 /*\\ ---------------------- Initialization Methods ---------------------- \\*/
\b\i0\fs24\fc0\cf0 \
+ initialize\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker843 \markername initialize;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self;\
	
\i0\ul Description:
\i\ulnone  Initializes the appDebugLevel & errFile class variables;\
*/
\f1\b\i0\fc0\cf0 \

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc0\cf0 	if ( self == [Object class] && classInited == NO )\
	\{	
\b0\i /* Initialize the Object(AllocNDebug) class variables */
\b\i0 \
		errFile = stderr;\
		classInited = YES;\

\f0\b0\fs20 [self debug: MAX_DEBUG method: _cmd, "Object(AllocNDebug)[%s] +initialize", [self name]];
\f1\b\fs24 \
	\}\
\
	return self;\
\} 
\b0\i // End initialize
\b\i0 \
\
- setErrorTable: table\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker1270 \markername setErrorTable:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul\fc1\cf1 ReturnValue:
\i\ulnone\fc0\cf0  self;\
	
\i0\ul\fc1\cf1 Description:
\i\ulnone\fc0\cf0  Set our errStringTable class variable to that\
		given by table;\
	
\i0\ul\fc1\cf1 Args:
\i\ulnone\fc0\cf0  \
		table: the NXStringTable object to be used in our 
\b error: key:
\b0  method;\
*/\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b\i0\fc0\cf0 	errStringTable = table;\
\
	return self;\
\} 
\b0 // End setErrorTable:
\b \
\
- setErrorFile:(FILE *) file\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker1573 \markername setErrorFile:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul\fc1\cf1 ReturnValue:
\i\ulnone\fc0\cf0  self;\
	
\i0\ul\fc1\cf1 Description:
\i\ulnone\fc0\cf0  Set our errFile class variable to that\
		given by file;\
	
\i0\ul\fc1\cf1 Args:
\i\ulnone\fc0\cf0  \
		table: the FILE stream to be used in our 
\b error: key:
\b0 \
			and 
\b debug:
\b0  methods;\
*/\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b\i0\fc0\cf0 	if( file == NULL )\
	\{\
		[self alertOk: "NULL file passed to setErrorFile:, using stderr" quit: YES];\
		file = stderr;\
	\}\
	errFile = file;\
\
	return self;\
\} 
\b0\i // End setErrorFile:
\b\i0 \
\
- setAppDebugLevel:(int) level\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker1987 \markername setErrorFile:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul\fc1\cf1 ReturnValue:
\i\ulnone\fc0\cf0  self;\
	
\i0\ul\fc1\cf1 Description:
\i\ulnone\fc0\cf0  Set our appDebugLevel class variable to that\
		given by level;\
	
\i0\ul\fc1\cf1 Args:
\i\ulnone\fc0\cf0  \
		level: the new cutoff level for debugging messages;\
*/\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b\i0\fc0\cf0 \{\
	appDebugLevel = level;\
\
	return self;\
\} 
\b0\i // End setAppDebugLevel:
\b\i0 \
\
- (int) appDebugLevel\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker2266 \markername setErrorFile:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul\fc1\cf1 ReturnValue:
\i\ulnone\fc0\cf0  appDebugLevel;\
*/
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b\i0\fc0\cf0 \
\{\
	return appDebugLevel;\
\} 
\b0\i // End appDebugLevel
\b\i0 \
\

\b0\i\fs28 /*\\ ---------------------- Allocation Methods ---------------------- \\*/
\b\i0\fs24 \
- (void *) malloc:(int) sizeInBytes\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\fc1\cf1 /*
{{\NeXTHelpMarker2484 \markername malloc:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i0\ulnone\fs24\fc1\cf1  --- 
\i\ul MethodDescription
\i0\ulnone \
	
\ul ReturnValue:
\ulnone  
\i A pointer to the newly allocated memory;
\i0 \
	
\ul Description:
\ulnone  
\i This is a cover for the 
\f1\b\fc0\cf0 NXZoneMalloc
\f0\b0\fc1\cf1 () system call\
		which uses [self zone] as the zone.\
		It adds error checking to obviate the need for malloc() return\
		value checking at the allocation point;
\i0 \
	
\ul Args:
\ulnone \
		
\i sizeInBytes: The amount of memory to allocate;
\i0 \
*/
\f1\b\fc0\cf0 \
void *tmpPtr;\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc0\cf0 \
	tmpPtr = NXZoneMalloc([self zone], sizeInBytes);\
	if( tmpPtr == NULL )\
		[self systemErr: "Failed to malloc storage, size = %d" method: _cmd, sizeInBytes];\
\
	return tmpPtr;\
\} 
\b0\i // End malloc:
\b\i0 \
\
- (void *) realloc:(int) sizeInBytes oldPtr:(void *) ptr\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker3100 \markername realloc:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  A pointer to the newly allocated memory;\
	
\i0\ul Description:
\i\ulnone  This is a cover for the 
\f1\b\fc0\cf0 NXZoneRealloc
\f0\b0\fc1\cf1 () system call\
		which uses [self zone] as the zone.\
		It adds error checking to obviate the need for realloc() return\
		value checking at the allocation point;\
	
\i0\ul Args:
\i\ulnone \
		sizeInBytes: The amount of memory to allocate;\
		ptr: The pointer being reallocated;\
*/\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b\i0\fc0\cf0 void *tmpPtr;\
\
	tmpPtr = NXZoneRealloc([self zone], ptr, sizeInBytes);\
	if( tmpPtr == NULL )\
		[self systemErr: "Failed to realloc storage" method: _cmd];\
\
	return tmpPtr;\
\} 
\b0\i // End realloc: oldPtr:
\b\i0 \
\
- (char *) stringAlloc:(const char *) source copyTo:(char **) destination\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker3765 \markername stringAlloc:copyTo:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  A pointer to the duplicated string;\
	
\i0\ul Description:
\i\ulnone  This method duplicates the 
\i0 source
\i  string using\
		our 
\b malloc:
\b0  method and the system 
\b strcpy()
\b0  function.  It\
		also frees 
\i0 *destination
\i  if it is non NULL.;\
	
\i0\ul Args:
\i\ulnone \
		source: The string to be duplicated;\
		destination: A pointer to the char * which will point to the\
			duplicate string;\
*/\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b\i0\fc0\cf0 int sizeInBytes;\
char *dupPtr;\
\
	sizeInBytes = strlen(source) + 1;\
	dupPtr = (char *) [self malloc: sizeInBytes];\
	if( dupPtr != NULL )\
	\{\
		strcpy(dupPtr, source);\
		if( *destination != NULL )\
			free(*destination);\
		*destination = dupPtr;\
	\}\
\
	return dupPtr;\
\} 
\b0\i // End stringAlloc: copyTo:
\b\i0 \
\
- (char *) buildMsg:(char *) format, ...\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker4476 \markername buildMsg:...;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  A pointer the constructed message string;\
	
\i0\ul Description:
\i\ulnone  This method is a cover for the buildMsg:argList:\
		method.  It allows one to pass an arbitrary argument list\
		which is converted to a va_list and passed to buildMsg:argList:.\
		The resulting memory should be freed with 
\b free:
\b0 , but 
\b free
\b0 ()\
		may be used.;\
	
\i0\ul Args:
\i\ulnone \
		format: A printf style of format string given to 
\b NXVPrintf
\b0 ();\
		...: An argument list corresponding to format;\
	*/\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b\i0\fc1\cf1 va_list otherArgs;\
char *msg;\
\
	va_start(otherArgs, format);\
	msg = [self buildMsg: format argList: otherArgs];\
	va_end(otherArgs);\
\
	return msg;\
\} 
\b0\i // End buildMsg:, ...
\b\i0 \

\fc0\cf0 \
- (char *) buildMsg:(char *) format argList:(va_list) argList\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker5185 \markername buildMsg:argList:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  A pointer the constructed message string;\
	
\i0\ul Description:
\i\ulnone  This method builds a message string using the\
		the given 
\i0 format
\i  string and a variable number of arguments using\
		memory streams and 
\b malloc:
\b0 .  This is useful for constructing messages\
		that will be given to 
\b NXRunAlertPanel
\b0 () since there is no version\
		of that function which accepts a va_list.  The resulting memory\
		should be freed with 
\b free:
\b0 , but 
\b free
\b0 () may be used.;\
	
\i0\ul Args:
\i\ulnone \
		format: A printf style of format string given to 
\b NXVPrintf
\b0 ();\
*/\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b\i0\fc0\cf0 int msgSize, maxLength;\
char *msg, *streamBuffer;\
NXStream *tmpStream;\
\

\fc1\cf1 	if( format == 0 )\
	\{	
\b0\i // Inform user of invalid format
\b\i0 \
		[self alertOk: "unexpected (nil) pointer passed as format" quit: YES];\
		return 0;\
	\}\

\fc0\cf0 	
\b0\i /* Open an NXStream and use it to construct the message */
\b\i0 \
	tmpStream = 
\f2\fs28 NXOpenMemory
\f1\fs24 (NULL, 0, 
\fc1\cf1 NX_WRITEONLY
\fc0\cf0 );\
	if( tmpStream == NULL )\
	\{\
		NXRunAlertPanel("Internal Error" , "%s: failed to create memory stream",\
			"Quit", NULL, NULL, sel_getName(_cmd));\
		[NXApp terminate: self];\
	\}\
	
\b0\i /* Build the msg string */
\b\i0 \
	NXVPrintf(tmpStream, format, argList);\

\fc1\cf1 	NXGetMemoryBuffer(tmpStream, &
\fc0\cf0 streamBuffer
\fc1\cf1 , &
\fc0\cf0 msgSize
\fc1\cf1 , &maxLength);\

\fc0\cf0 \
	
\b0\i /* Allocate memory for the stream buffer and copy it over to it.  We do this\
		because the calling routine would either have to use NXCloseMemory\
		or vm_deallocate to free stream buffer since free() cannot be used. */
\b\i0 \
	msg = (char *) [self malloc: msgSize+1];\
	bcopy(streamBuffer, msg, msgSize);\
	msg[msgSize] = '\\0';\
	
\f2\fs28 NXCloseMemory
\f1\fs24\fc1\cf1 (tmpStream, NX_FREEBUFFER);\

\fc0\cf0 \
	return msg;\
\} 
\b0\i // End buildMsg: argList:
\b\i0 \
\
- (void) free:(void *) ptr\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker6801 \markername free:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  None;\
	
\i0\ul Description:
\i\ulnone  This method frees memory previously allocated by\
		our 
\b malloc:
\b0 , 
\b realloc:
\b0 , and 
\b stringAlloc:copyTo:
\b0  methods. It\
		uses the 
\b NXZoneFree
\b0 () routine, using [self zone] as the zone.;\
	
\i0\ul Args:
\i\ulnone \
		ptr: The pointer to the memory to be freed;\
*/\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b\i0\fc0\cf0 	NXZoneFree([self zone], ptr);\
\} 
\b0\i // End free:
\b\i0 \
\

\b0\i\fs28 /*\\ ---------------------------------- Error Message Methods ---------------------------------- \\*/
\b\i0\fs24 \

\b0\i /* The C library error handling global variable */
\b\i0 \
extern int errno;\
\
/* Ask the user the yes, no question in the "question" arg with\
	a cancel option if "cancel" is YES */\
- (int) askYesNo:(const char *) question cancel:(BOOL) cancel\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker7476 \markername askYesNo:cancel:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  The value returned by our 
\b alert:msg:btn1:btn2:btn3:,
\b0 ;\
	
\i0\ul Description:
\i\ulnone  This method invokes our 
\b alert:msg:btn1:btn2:btn3:,
\b0 \
		setting the default btn to "Yes", the alternate btn to "No",\
		and if 
\i0 cancel
\i  is YES, the other btn to "Cancel".  If 
\i0 cancel
\i \
		is NO, no other btn is used. The title of the panel is Alert\
		and the msg displayed is set to the 
\i0 question
\i  arg.;\
	
\i0\ul Args:
\i\ulnone \
		question: The string to be displayed in the panel;\
		cancel: A flag indicating if a cancel btn should be used;\
*/\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b\i0\fc0\cf0 int userAction;\
char *cancelBtn = NULL;\
\
	if( cancel == YES )\
		cancelBtn = "Cancel";\
	userAction = [self alert: NULL msg: question btn1: "Yes" btn2: "No" btn3: cancelBtn];\
\
	return userAction;\
\} 
\b0\i // End askYesNo: cancel:
\b\i0 \
\
- (int) alertOk:(const char *) msg quit:(BOOL) quit\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker8275 \markername alertOk:quit:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  The value returned by our 
\b alert:msg:btn1:btn2:btn3:,
\b0 ;\
	
\i0\ul Description:
\i\ulnone  This method invokes our 
\b alert:msg:btn1:btn2:btn3:,
\b0 \
		setting the default btn to "Ok", and the alternate btn to "Quit"\
		if 
\i0 quit
\i  is YES. If 
\i0 quit
\i  is NO, no other btn is used.\
		The title of the panel is Alert and the msg displayed is set\
		to the 
\i0 msg
\i  arg.;\
	
\i0\ul Args:
\i\ulnone \
		question: The string to be displayed in the panel;\
		cancel: A flag indicating if a cancel btn should be used;\
*/\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b\i0\fc0\cf0 int userAction;\
char *quitBtn;\
\
	quitBtn = ( quit == YES ? "Quit" : NULL );\
	userAction = [self alert: NULL msg: "%s" btn1: "Ok" btn2: quitBtn btn3: NULL, msg];\
	if( userAction == NX_ALERTALTERNATE )\
		[NXApp terminate: self];\
\
	return userAction;\
\} 
\b0\i // End alertOk: quit:
\b\i0 \
\
- (int) alert: (const char *) title msg:(const char *) format btn1:(const char *) theDefault\
	btn2:(const char *) alternate btn3:(const char *) other, ...\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker9191 \markername alert:msg:...;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  One of NX_ALERTDEFAULT, NX_ALERTALTERNATE\
		NX_ALERTOTHER as described in 
\b NXRunAlertPanel
\b0 ();\
	
\i0\ul Description:
\i\ulnone  This method invokes 
\b NXRunAlertPanel
\b0 ()\
		with a one-to-one correspondence between our args and function\
		arguments.  The total size of the panel message must be less\
		than 256 bytes, including the optional arguments.  If there are\
		no optional arguments, the message can have any size.;\
	
\i0\ul Args:
\i\ulnone \
		title: The string to be displayed as the panel title;\
		format: The string to be displayed in the panel body;\
		theDefault: The title of the default button;\
		alternate: The title of the alternate button;\
		other: The title of the other button;\
		...: Any additional args as specified in format;\
*/
\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b\i0\fc0\cf0 \
va_list otherArgs;\
int userSelection;\
char *msg;\
\
	
\b0\i /* Since there is not a version of NXRunAlertPanel that accepts a va_list,\
		we write out the msg using the format arg and vsprintf */
\b\i0 \
	va_start(otherArgs, other);\
	msg = [self buildMsg:(char *) format argList: otherArgs];\
	userSelection = NXRunAlertPanel(title, msg, theDefault, alternate, other);\
	[self free: msg];\
	va_end(otherArgs);\
\
	return userSelection;\
\} 
\b0\i // End alert: msg: btn1: btn2: btn3:, ...
\b\i0 \
\
- systemErr: (char *) userMsg method:(SEL) method, ...\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker10450 \markername systemErr:method:...;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self;\
	
\i0\ul Description:
\i\ulnone  Report system call errors using the given 
\i0 userMsg
\i \
		string and the system error as returned by strerror(errno) if\
		errno is nonzero.  The name of the class and invoking method\
		are preappended to the given message. The title of the panel\
		is "System Error", and it contains a single button titled "Ok".;\
	
\i0\ul Args:
\i\ulnone \
		userMsg: A printf style of format string;\
		method: The method which invoked this method;\
		...: The argument list associcated with the userMsg format;\
*/\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b\i0\fc0\cf0 va_list  otherArgs;\
char *format, *errorString = NULL, *msg;\
const char *methodName, *className;\
\
	
\b0\i /* Set class and method names */
\b\i0 \
	className = [[self class] name];\
	methodName =  sel_getName(method);\
	
\b0\i /* Get system error message */
\b\i0 \
	if( errno != 0 )\
		errorString = strerror(errno);\
	if( errorString == NULL )\
		errorString = "No system error message";\
	
\b0\i /* Build the format string */\

\b\i0\fc1\cf1 	format = [self buildMsg: "%s[%s]: %s\\n%s", className, methodName,\
		userMsg, errorString];
\fc0\cf0 \

\f0\b0\fs20 [self debug: MAX_DEBUG method: _cmd, "format = %s", format];
\f1\b\fs24 \
\
	
\b0\i /* Display the error panel */\

\b\i0\fc1\cf1 	va_start(otherArgs, method);\
	msg = [self buildMsg: format argList: otherArgs];
\fc0\cf0 \
	NXRunAlertPanel("System Error", msg, NULL, NULL, NULL);\
	[self free: format];\
	[self free: msg];\
	va_end(otherArgs);\
\
	
\b0\i /* Return and let user handle the error condition */
\b\i0 \
	return self;\
\} 
\b0\i // End systemErr: method:, ...
\b\i0 \
\
/* Report the error associated with the keyString and depending on\
	the continue depending on the severity */\
- error:(int) severity method:(SEL) method key:(const char *) keyString, ...\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker12043 \markername ;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self;\
	
\i0\ul Description:
\i\ulnone  Report system call errors using the given 
\i0 userMsg
\i \
		string and the system error as returned by strerror(errno) if\
		errno is nonzero.  The name of the class and invoking method\
		are also displayed. The title of the panel is "System Error", and\
		it contains a single button titled "Ok". ;\
	
\i0\ul Args:
\i\ulnone \
		severity: A printf style of format string and message;\
		method: The method which invoked this method;\
		keyString: The string to be used to lookup the error message\
			from the errStringTable.  If keyString fails to return a value\
			from errStringTable, it is assumed that keyString is the error\
			message.\
			The message that results is prefixed with the class and method\
			name which invoked this routine.;\
		...: A list of arguments that correspond to the error message\
			string returned from the error table using keyString;\
*/\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b\i0\fc0\cf0 va_list otherArgs;\
const char *errMessage, *replyRequest, *className, *methodName;\
char *format, *msg, *btn1 = "Ok", *btn2 = "Quit";\
int userSelection;\
\
	errMessage = [errStringTable valueForStringKey: keyString];\
	if( errMessage == NULL )\
		errMessage = keyString;\
\
	switch( severity )\
	\{	
\b0\i /* Set the message indicating if the user can try to continue and request that\
			the error message be sent to us */
\b\i0 \
		case INTERNAL_SORRY:\
			replyRequest = [errStringTable valueForStringKey: REPLY_REQUEST2];\
			break;\
		case INTERNAL_ALERT:\
			replyRequest = [errStringTable valueForStringKey: REPLY_REQUEST1];\
			break;\
		case INTERNAL_ERROR:\
		default:\
			replyRequest = [errStringTable valueForStringKey: REPLY_REQUEST0];\
			btn1 = "Quit"; btn2 = NULL;\
			break;\
	\}\
\
	
\b0\i /* Build the error message format & message */
\b\i0 \
	className = [[self class] name];\
	methodName =  sel_getName(method);\
	format = [self buildMsg: "%s[%s]: %s\\n", className, methodName,\
		errMessage, replyRequest];\
	va_start(otherArgs, keyString);\
	msg = [self buildMsg: format argList: otherArgs];\
\
	
\b0\i /* Display error panel */
\b\i0 \
	userSelection = NXRunAlertPanel("Internal Error", msg, btn1, btn2,NULL);\
	if( severity >= INTERNAL_ERROR || userSelection == NX_ALERTALTERNATE )\
		[NXApp terminate: self];\
	[self free: format];\
	[self free: msg];\
	va_end(otherArgs);\
\
	return self;\
\} 
\b0\i // End error: method: key:, ...
\b\i0 \
\
- debug: (int) debugLevel method:(SEL) method, ...\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker14362 \markername debug:method:...;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self if the message is logged, nil if it is not;\
	
\i0\ul Description:
\i\ulnone \
		Report debugging information or internal program errors.  Debugging\
		info is logged to errFile and internal errors bring a termination panel;\
	
\i0\ul Args:
\i\ulnone \
		debugLevel: The level of the message;\
		method: The method which invoked this method;\
		... : A list of arguments the first of which must be a\
			printf style format string to display the remaining args.\
			The format message can be NULL if one so desires.\
			The message that results is prefixed with the class and method\
			name which invoked this routine.;\
*/\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b\i0\fc0\cf0 va_list  otherArgs;\
char *msgFormat, *format;\
const char *methodName, *className;\
\
	/* Only those calls with levels less than the current debugging level\
		are logged */\
	if( debugLevel >= appDebugLevel )\
		return nil;\
\
	
\b0\i /* Build the error message format & message */
\b\i0 \
	className = [[self class] name];\
	methodName =  sel_getName(method);\
	va_start(otherArgs, method);\
	format = va_arg(otherArgs, char *);\
	if( format == NULL )\
		format = "NULL message";\
	msgFormat = [self buildMsg: "%s[%s]: %s\\n", className, methodName, format];\
\
	/* Log the message to the errFile */\
	vfprintf(errFile, msgFormat, otherArgs);\
	fflush(errFile);\
	[self free: msgFormat];\
	va_end(otherArgs);\
\
	return self;\
\} 
\b0\i // End debug: method:, ...
\b\i0 \
\
@end\
/* RCS Information:\
	$Author: me $;\
	$Date: 93/02/23 02:01:12 $;\
	$Source: /usr1/me/NeXTSrc/MyClasses/RCS/Object_AllocNDebug.m,v $;\
	$Revision: 1.1 $;\
*/\

}
